mirror of
https://github.com/StefBuwalda/dashboard_test.git
synced 2025-10-30 11:19:58 +00:00
First big step in moving towards DB storage instead of memory storage
This commit is contained in:
19
app.py
19
app.py
@@ -5,8 +5,8 @@ from mem import services, app, db
|
|||||||
import threading
|
import threading
|
||||||
from flask_migrate import upgrade, stamp
|
from flask_migrate import upgrade, stamp
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from models import service
|
from models import service, log
|
||||||
|
from typing import Any, Optional, cast
|
||||||
|
|
||||||
# Init and upgrade
|
# Init and upgrade
|
||||||
with app.app_context():
|
with app.app_context():
|
||||||
@@ -39,7 +39,20 @@ def homepage():
|
|||||||
|
|
||||||
@app.route("/api/status")
|
@app.route("/api/status")
|
||||||
def status():
|
def status():
|
||||||
return jsonify([s.to_dict() for s in services])
|
results: list[dict[str, Any]] = []
|
||||||
|
with app.app_context():
|
||||||
|
a = db.session.query(service).all()
|
||||||
|
for s in a:
|
||||||
|
b = cast(
|
||||||
|
Optional[log],
|
||||||
|
s.logs.order_by(
|
||||||
|
log.dateCreated.desc() # type: ignore
|
||||||
|
).first(),
|
||||||
|
)
|
||||||
|
if b:
|
||||||
|
results.append(s.to_dict() | b.to_dict())
|
||||||
|
|
||||||
|
return jsonify(results)
|
||||||
|
|
||||||
|
|
||||||
@app.route("/favicon.svg")
|
@app.route("/favicon.svg")
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
from typing import Any, Optional
|
from typing import Any
|
||||||
from flask import Flask
|
from flask import Flask
|
||||||
from flask_sqlalchemy import SQLAlchemy
|
from flask_sqlalchemy import SQLAlchemy
|
||||||
from flask_migrate import Migrate
|
from flask_migrate import Migrate
|
||||||
@@ -7,12 +7,8 @@ from flask_migrate import Migrate
|
|||||||
class service:
|
class service:
|
||||||
id: int
|
id: int
|
||||||
url: str
|
url: str
|
||||||
status: Optional[int]
|
|
||||||
online: bool
|
online: bool
|
||||||
public: bool
|
public: bool
|
||||||
error: Optional[str]
|
|
||||||
ping: Optional[int]
|
|
||||||
icon_filetype: str
|
|
||||||
ping_type: int
|
ping_type: int
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
@@ -21,7 +17,6 @@ class service:
|
|||||||
url: str = "",
|
url: str = "",
|
||||||
label: str = "",
|
label: str = "",
|
||||||
public: bool = True,
|
public: bool = True,
|
||||||
icon_filetype: str = "svg",
|
|
||||||
ping_type: int = 0,
|
ping_type: int = 0,
|
||||||
):
|
):
|
||||||
self.id = id
|
self.id = id
|
||||||
@@ -30,38 +25,15 @@ class service:
|
|||||||
self.label = label
|
self.label = label
|
||||||
self.ping_type = ping_type
|
self.ping_type = ping_type
|
||||||
|
|
||||||
self.online = False
|
|
||||||
self.status = None
|
|
||||||
self.error = None
|
|
||||||
self.ping = None
|
|
||||||
self.icon_filetype = icon_filetype
|
|
||||||
|
|
||||||
def to_dict(self) -> dict[str, Any]:
|
def to_dict(self) -> dict[str, Any]:
|
||||||
return {
|
return {
|
||||||
"url": self.url,
|
"url": self.url,
|
||||||
"status": self.status,
|
|
||||||
"public": self.public,
|
"public": self.public,
|
||||||
"online": self.online,
|
|
||||||
"error": self.error,
|
|
||||||
"ping": self.ping,
|
|
||||||
"label": self.label,
|
"label": self.label,
|
||||||
"icon_filetype": self.icon_filetype,
|
|
||||||
"id": self.id,
|
"id": self.id,
|
||||||
"ping_type": self.ping_type,
|
"ping_type": self.ping_type,
|
||||||
}
|
}
|
||||||
|
|
||||||
def set_status(self, status: Optional[int]):
|
|
||||||
self.status = status
|
|
||||||
|
|
||||||
def set_online(self, b: bool):
|
|
||||||
self.online = b
|
|
||||||
|
|
||||||
def set_error(self, s: Optional[str]):
|
|
||||||
self.error = s
|
|
||||||
|
|
||||||
def set_ping(self, n: Optional[int]):
|
|
||||||
self.ping = n
|
|
||||||
|
|
||||||
|
|
||||||
services: list[service] = [
|
services: list[service] = [
|
||||||
service(0, "https://git.ihatemen.uk/", "Gitea"),
|
service(0, "https://git.ihatemen.uk/", "Gitea"),
|
||||||
|
|||||||
@@ -75,18 +75,18 @@
|
|||||||
|
|
||||||
// Build all service divs as a single string
|
// Build all service divs as a single string
|
||||||
main_body.innerHTML = services.map(s => `
|
main_body.innerHTML = services.map(s => `
|
||||||
<a href="${s.url}" class="d-block text-body text-decoration-none m-2 border border-3 ${s.online ? 'border-success' : 'border-danger'}" style="width: 175px">
|
<a href="${s.url}" class="d-block text-body text-decoration-none m-2 border border-3 ${s.ping ? 'border-success' : 'border-danger'}" style="width: 175px">
|
||||||
<div class="bg-body-tertiary d-flex flex-column align-items-center">
|
<div class="bg-body-tertiary d-flex flex-column align-items-center">
|
||||||
<div class="bg-dark w-100">
|
<div class="bg-dark w-100">
|
||||||
<h4 class="text-center text-truncate m-0 p-1">${s.label}</h4>
|
<h4 class="text-center text-truncate m-0 p-1">${s.label}</h4>
|
||||||
</div>
|
</div>
|
||||||
<div class="position-relative ratio ratio-1x1">
|
<div class="position-relative ratio ratio-1x1">
|
||||||
<div class="d-flex justify-content-center align-items-center">
|
<div class="d-flex justify-content-center align-items-center">
|
||||||
<img src="static/icons/${s.id}.${s.icon_filetype}" class="img-fluid w-75">
|
<img src="static/icons/${s.service_id - 1}.svg" class="img-fluid w-75">
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
${s.public ? `` : `<img src='static/lock.svg' class='img-fluid position-absolute bottom-0 end-0 w-25'>`}
|
${s.public_access ? `` : `<img src='static/lock.svg' class='img-fluid position-absolute bottom-0 end-0 w-25'>`}
|
||||||
<div class="position-absolute bottom-0 text-body bg-dark bg-opacity-75 px-1 rounded">${s.online ? s.ping + "ms" : ""}</div>
|
<div class="position-absolute bottom-0 text-body bg-dark bg-opacity-75 px-1 rounded">${s.ping ? s.ping + "ms" : ""}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
12
models.py
12
models.py
@@ -21,6 +21,14 @@ class log(db.Model):
|
|||||||
|
|
||||||
self.dateCreated = datetime.now(timezone.utc)
|
self.dateCreated = datetime.now(timezone.utc)
|
||||||
|
|
||||||
|
def to_dict(self) -> dict[str, Any]:
|
||||||
|
return {
|
||||||
|
"log_id": self.id,
|
||||||
|
"service_id": self.service_id,
|
||||||
|
"ping": self.ping,
|
||||||
|
"dateCreated": self.dateCreated,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class service(db.Model):
|
class service(db.Model):
|
||||||
id: int = db.Column(db.Integer, primary_key=True) # TODO: Switch to UUID
|
id: int = db.Column(db.Integer, primary_key=True) # TODO: Switch to UUID
|
||||||
@@ -29,7 +37,7 @@ class service(db.Model):
|
|||||||
public_access: bool = db.Column(db.Boolean, nullable=False)
|
public_access: bool = db.Column(db.Boolean, nullable=False)
|
||||||
ping_method: int = db.Column(db.Integer, nullable=False)
|
ping_method: int = db.Column(db.Integer, nullable=False)
|
||||||
|
|
||||||
logs = db.relationship("log")
|
logs = db.relationship("log", lazy="dynamic")
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self, url: str, label: str, public_access: bool, ping_method: int
|
self, url: str, label: str, public_access: bool, ping_method: int
|
||||||
@@ -49,6 +57,6 @@ class service(db.Model):
|
|||||||
"url": self.url,
|
"url": self.url,
|
||||||
"public_access": self.public_access,
|
"public_access": self.public_access,
|
||||||
"label": self.label,
|
"label": self.label,
|
||||||
"id": self.id,
|
"service_id": self.id,
|
||||||
"ping_method": self.ping_method,
|
"ping_method": self.ping_method,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,25 +28,14 @@ async def check_service(client: aiohttp.ClientSession, s: service) -> log:
|
|||||||
case _:
|
case _:
|
||||||
raise Exception("UNKNOWN PING TYPE")
|
raise Exception("UNKNOWN PING TYPE")
|
||||||
after = time.perf_counter()
|
after = time.perf_counter()
|
||||||
s.set_error(None)
|
if r.status == 200:
|
||||||
s.set_online(r.status == 200)
|
return log(service_id=s.id + 1, ping=int((after - before) * 1000))
|
||||||
s.set_status(r.status)
|
|
||||||
if r.status != 200:
|
|
||||||
s.set_ping(None)
|
|
||||||
else:
|
else:
|
||||||
s.set_ping(int((after - before) * 1000))
|
return log(service_id=s.id + 1, ping=None)
|
||||||
except aiohttp.ConnectionTimeoutError:
|
except aiohttp.ConnectionTimeoutError:
|
||||||
s.set_error("Connection Timeout")
|
return log(service_id=s.id + 1, ping=None)
|
||||||
s.set_online(False)
|
except Exception:
|
||||||
s.set_status(None)
|
return log(service_id=s.id + 1, ping=None)
|
||||||
s.set_ping(None)
|
|
||||||
except Exception as e:
|
|
||||||
print(type(e))
|
|
||||||
s.set_error(str(e))
|
|
||||||
s.set_online(False)
|
|
||||||
s.set_status(None)
|
|
||||||
s.set_ping(None)
|
|
||||||
return log(service_id=s.id, ping=s.ping)
|
|
||||||
|
|
||||||
|
|
||||||
def start_async_loop():
|
def start_async_loop():
|
||||||
|
|||||||
Reference in New Issue
Block a user