Compare commits

...

17 Commits

Author SHA1 Message Date
6848aab1e1 Added a lock icon to the "private" URLs 2025-08-31 14:54:45 +02:00
903fb525c0 Made the blocks on the dashboard clickable 2025-08-31 14:24:36 +02:00
6103a34ae1 Switched from browser refresh to update webpage with API fetch
Added an ID field to the API. Added a fetch script that updates the webpage every second.
2025-08-31 14:06:55 +02:00
f2a006b397 Updated frontend and changed a little backend
Added svg icons to the applications. Frontend will display the icon by name of [id].[icon_filetype] which defaults to svg. Able to set to other filetypes. Changed the frontend to center the application
2025-08-31 13:31:15 +02:00
7cb07691bb Added icon filetype so icons can be saved as [id].[icon_filetype] 2025-08-31 13:06:07 +02:00
3e8ecf7565 Added labels to each service 2025-08-31 13:00:23 +02:00
4876f16760 Run on all addresses 2025-08-31 12:36:53 +02:00
67cad7f8a9 Set port to 80 and disable the reloader 2025-08-31 12:34:38 +02:00
9323605b48 Renamed DockerFile to Dockerfile 2025-08-31 12:24:52 +02:00
0431ccbec4 Rename DockerFile to Dockerfile 2025-08-31 12:24:28 +02:00
363196c0db Added requirements.txt, removed an unused package 2025-08-31 12:21:34 +02:00
aadcc81d02 Merge branch 'main' of https://github.com/StefBuwalda/dashboard_test 2025-08-31 12:18:09 +02:00
e0349ab058 Set up docker auto build, copied from another project 2025-08-31 12:18:08 +02:00
Stef
f841afa105 Create main.yml 2025-08-31 12:14:56 +02:00
071c15f40d Dynamically build the page. Automatically update by refreshing page 2025-08-31 12:12:49 +02:00
fd0cb02615 Two colors of borders 2025-08-31 11:59:08 +02:00
3b3c49d8df Added a first version of the dashboard 2025-08-31 11:49:11 +02:00
20 changed files with 227 additions and 16 deletions

46
.github/workflows/main.yml vendored Normal file
View File

@@ -0,0 +1,46 @@
name: Build and Push to GHCR
on:
push:
branches:
- main
permissions:
packages: write
contents: read
jobs:
build:
runs-on: ubuntu-latest
steps:
# Checkout code
- name: Checkout code
uses: actions/checkout@v4.2.2
# Log in to GHCR
- name: Log in to GitHub Container Registry
uses: docker/login-action@v3.5.0
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
# Set up Docker Buildx (needed for ARM64 cross-build)
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3.11.1
# Build and push Docker image with caching
- name: Build and push ARM64 image
uses: docker/build-push-action@v6.18.0
with:
context: .
push: true
platforms: linux/arm64
tags: |
ghcr.io/stefbuwalda/dashboard_test:arm64
ghcr.io/stefbuwalda/dashboard_test:latest
cache-from: type=registry,ref=ghcr.io/stefbuwalda/dashboard_test:cache
cache-to: type=registry,ref=ghcr.io/stefbuwalda/dashboard_test:cache,mode=max
build-args: |
PIP_NO_CACHE_DIR=1

17
Dockerfile Normal file
View File

@@ -0,0 +1,17 @@
FROM python:3.12-slim
# Everything will be done in /app (Not in the main OS Image)
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
RUN chmod +x ./entrypoint.sh
ENV FLASK_APP=app.py
ENTRYPOINT ["./entrypoint.sh"]
CMD []

View File

@@ -1,5 +1,5 @@
# import requests as r
from flask import jsonify, Flask
from flask import jsonify, Flask, render_template
from poll_services import start_async_loop
from mem import services
import threading
@@ -10,6 +10,11 @@ app = Flask(__name__)
@app.route("/")
def homepage():
return render_template("home.html", services=services)
@app.route("/api/status")
def status():
return jsonify([s.to_dict() for s in services])
@@ -21,4 +26,4 @@ if __name__ == "__main__":
t.start()
# Run flask app
app.run(debug=True, use_reloader=False)
app.run(host="0.0.0.0", port=80, debug=True, use_reloader=False)

8
entrypoint.sh Normal file
View File

@@ -0,0 +1,8 @@
#!/bin/sh
set -ex
#echo "Running database migrations..."
#flask db upgrade
echo "Starting Flask app..."
python app.py

View File

@@ -2,21 +2,33 @@ from typing import Any, Optional
class service:
id = int
url: str
status: Optional[int]
online: bool
public: bool
error: Optional[str]
ping: Optional[int]
icon_filetype: str
def __init__(self, url: str = "", public: bool = True):
def __init__(
self,
id: int,
url: str = "",
label: str = "",
public: bool = True,
icon_filetype: str = "svg",
):
self.id = id
self.url = url
self.public = public
self.label = label
self.online = False
self.status = None
self.error = None
self.ping = None
self.icon_filetype = icon_filetype
def to_dict(self) -> dict[str, Any]:
return {
@@ -26,6 +38,9 @@ class service:
"online": self.online,
"error": self.error,
"ping": self.ping,
"label": self.label,
"icon_filetype": self.icon_filetype,
"id": self.id,
}
def set_status(self, status: Optional[int]):
@@ -42,14 +57,14 @@ class service:
services: list[service] = [
service("https://git.ihatemen.uk/"),
service("https://plex.ihatemen.uk/"),
service("https://truenas.local/", False),
service("https://cloud.ihatemen.uk/"),
service("https://request.ihatemen.uk/"),
service("https://id.ihatemen.uk/"),
service("http://tautulli.local", False),
service("https://transmission.local", False),
service("https://vault.ihatemen.uk"),
service("https://nginx.local", False),
service(0, "https://git.ihatemen.uk/", "Gitea"),
service(1, "https://plex.ihatemen.uk/", "Plex"),
service(2, "https://truenas.local/", "TrueNAS", False),
service(3, "https://cloud.ihatemen.uk/", "NextCloud"),
service(4, "https://request.ihatemen.uk/", "Overseerr"),
service(5, "https://id.ihatemen.uk/", "PocketID"),
service(6, "http://tautulli.local", "Tautulli", False),
service(7, "https://transmission.local", "Transmission", False),
service(8, "https://vault.ihatemen.uk", "Vault Warden"),
service(9, "https://nginx.local", "Nginx (NPM)", False),
]

View File

@@ -1,11 +1,8 @@
from mem import services, service
import httpx
import urllib3
import asyncio
import time
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
async def check_service(client: httpx.AsyncClient, s: service):
try:

16
requirements.txt Normal file
View File

@@ -0,0 +1,16 @@
anyio==4.10.0
blinker==1.9.0
certifi==2025.8.3
click==8.2.1
colorama==0.4.6
Flask==3.1.2
h11==0.16.0
httpcore==1.0.9
httpx==0.28.1
idna==3.10
itsdangerous==2.2.0
Jinja2==3.1.6
MarkupSafe==3.0.2
sniffio==1.3.1
typing_extensions==4.15.0
Werkzeug==3.1.3

12
static/icons/0.svg Normal file
View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg">
<style>
.st1{fill:#fff}
</style>
<g id="Icon">
<circle cx="512" cy="512" r="512" style="fill:#609926"/>
<path class="st1" d="M762.2 350.3c-100.9 5.3-160.7 8-212 8.5v114.1l-16-7.9-.1-106.1c-58.9 0-110.7-3.1-209.1-8.6-12.3-.1-29.5-2.4-47.9-2.5-47.1-.1-110.2 33.5-106.7 118C175.8 597.6 296 609.9 344 610.9c5.3 24.7 61.8 110.1 103.6 114.6H631c109.9-8.2 192.3-373.8 131.2-375.2zm-546 117.3c-4.7-36.6 11.8-74.8 73.2-73.2C296.1 462 307 501.5 329 561.9c-56.2-7.4-104-25.7-112.8-94.3zm415.6 83.5-51.3 105.6c-6.5 13.4-22.7 19-36.2 12.5l-105.6-51.3c-13.4-6.5-19-22.7-12.5-36.2l51.3-105.6c6.5-13.4 22.7-19 36.2-12.5l105.6 51.3c13.4 6.6 19 22.8 12.5 36.2z"/>
<path class="st1" d="M555 609.9c.1-.2.2-.3.2-.5 17.2-35.2 24.3-49.8 19.8-62.4-3.9-11.1-15.5-16.6-36.7-26.6-.8-.4-1.7-.8-2.5-1.2.2-2.3-.1-4.7-1-7-.8-2.3-2.1-4.3-3.7-6l13.6-27.8-11.9-5.8-13.7 28.4c-2 0-4.1.3-6.2 1-8.9 3.2-13.5 13-10.3 21.9.7 1.9 1.7 3.5 2.8 5l-23.6 48.4c-1.9 0-3.8.3-5.7 1-8.9 3.2-13.5 13-10.3 21.9 3.2 8.9 13 13.5 21.9 10.3 8.9-3.2 13.5-13 10.3-21.9-.9-2.5-2.3-4.6-4-6.3l23-47.2c2.5.2 5 0 7.5-.9 2.1-.8 3.9-1.9 5.5-3.3.9.4 1.9.9 2.7 1.3 17.4 8.2 27.9 13.2 30 19.1 2.6 7.5-5.1 23.4-19.3 52.3-.1.2-.2.5-.4.7-2.2-.1-4.4.2-6.5 1-8.9 3.2-13.5 13-10.3 21.9 3.2 8.9 13 13.5 21.9 10.3 8.9-3.2 13.5-13 10.3-21.9-.6-2-1.9-4-3.4-5.7z"/>
</g>

After

Width:  |  Height:  |  Size: 1.5 KiB

1
static/icons/1.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><rect width="512" height="512" rx="15%" fill="#282a2d"/><path d="M256 70H148l108 186-108 186h108l108-186z" fill="#e5a00d"/></svg>

After

Width:  |  Height:  |  Size: 191 B

5
static/icons/2.svg Normal file
View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg">
<circle cx="512" cy="512" r="512" style="fill:#0095d5"/>
<path d="M780 468.41v114.21L535.48 723.86v-114.2zM488.69 609.66v114.21L244 582.62V468.41l110.57 63.79a1.81 1.81 0 0 0 .4.24zM611 512l-98.91 57.15-99-57.15 99-57.15zm145.7-84.09-99 57.15-122.22-70.64V300.13zm-268-127.81v114.32L366.3 485l-99-57.06z" style="fill:#fff"/>
</svg>

After

Width:  |  Height:  |  Size: 550 B

9
static/icons/3.svg Normal file
View File

@@ -0,0 +1,9 @@
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Transformed by: SVG Repo Mixer Tools -->
<svg fill="#ffffff" width="800px" height="800px" viewBox="-3.2 -3.2 38.40 38.40" xmlns="http://www.w3.org/2000/svg" stroke="#ffffff">
<g id="SVGRepo_bgCarrier" stroke-width="0" transform="translate(0,0), scale(1)">
<rect x="-3.2" y="-3.2" width="38.40" height="38.40" rx="19.2" fill="#00678e" strokewidth="0"/>

After

Width:  |  Height:  |  Size: 1.4 KiB

5
static/icons/4.svg Normal file
View File

@@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="57.54 57.53 396.92 396.93">
<path d="M0 0 C0.77839233 0.70552002 0.77839233 0.70552002 1.57250977 1.42529297 C20.51724698 18.95857955 35.3183542 42.25039645 45.25 65.9375 C45.75917969 67.13761719 46.26835937 68.33773437 46.79296875 69.57421875 C53.13904333 85.15591751 57.42335993 102.21306817 59.25 118.9375 C59.35957031 119.79472656 59.46914063 120.65195313 59.58203125 121.53515625 C65.30647708 174.58168758 49.01780615 227.1014046 15.875 268.5 C12.4098987 272.65198864 8.83161111 276.6927508 5.1875 280.6875 C4.48197998 281.46589233 4.48197998 281.46589233 3.76220703 282.26000977 C-13.77107955 301.20474698 -37.06289645 316.0058542 -60.75 325.9375 C-61.95011719 326.44667969 -63.15023438 326.95585937 -64.38671875 327.48046875 C-79.96841751 333.82654333 -97.02556817 338.11085993 -113.75 339.9375 C-114.60722656 340.04707031 -115.46445312 340.15664063 -116.34765625 340.26953125 C-169.39418758 345.99397708 -221.9139046 329.70530615 -263.3125 296.5625 C-267.46448864 293.0973987 -271.5052508 289.51911111 -275.5 285.875 C-276.27839233 285.16947998 -276.27839233 285.16947998 -277.07250977 284.44970703 C-296.01724698 266.91642045 -310.8183542 243.62460355 -320.75 219.9375 C-321.25917969 218.73738281 -321.76835937 217.53726562 -322.29296875 216.30078125 C-328.63904333 200.71908249 -332.92335993 183.66193183 -334.75 166.9375 C-334.85957031 166.08027344 -334.96914063 165.22304688 -335.08203125 164.33984375 C-340.80647708 111.29331242 -324.51780615 58.7735954 -291.375 17.375 C-287.9098987 13.22301136 -284.33161111 9.1822492 -280.6875 5.1875 C-280.21715332 4.66857178 -279.74680664 4.14964355 -279.26220703 3.61499023 C-261.72892045 -15.32974698 -238.43710355 -30.1308542 -214.75 -40.0625 C-213.54988281 -40.57167969 -212.34976563 -41.08085938 -211.11328125 -41.60546875 C-195.53158249 -47.95154333 -178.47443183 -52.23585993 -161.75 -54.0625 C-160.89277344 -54.17207031 -160.03554687 -54.28164063 -159.15234375 -54.39453125 C-99.82500101 -60.79676248 -43.54726444 -39.72491441 0 0 Z " fill="#A289F9" transform="translate(393.75,113.0625)"/>
<path d="M0 0 C2.63622485 2.22708275 5.19150738 4.52921782 7.7409668 6.85546875 C8.46670898 7.49871094 9.19245117 8.14195312 9.94018555 8.8046875 C28.36748008 26.03588989 41.75155651 53.35960955 42.86425781 78.65869141 C43.70797362 112.3608808 36.58885956 142.14006064 13.7409668 167.85546875 C12.54020508 169.20705078 12.54020508 169.20705078 11.31518555 170.5859375 C-8.53153214 191.53705519 -37.09680019 204.15705607 -65.8137207 205.140625 C-77.94100422 205.37709014 -89.5422865 205.25443065 -101.2590332 201.85546875 C-103.0224707 201.37980469 -103.0224707 201.37980469 -104.8215332 200.89453125 C-121.40302939 195.94116057 -136.3527812 187.31831389 -149.2590332 175.85546875 C-150.14848633 175.0665625 -151.03793945 174.27765625 -151.9543457 173.46484375 C-167.40909083 158.83370573 -177.61511815 140.25052542 -183.2590332 119.85546875 C-183.5787207 118.70820313 -183.8984082 117.5609375 -184.2277832 116.37890625 C-188.26683057 98.91376625 -188.98196274 77.02425735 -183.2590332 59.85546875 C-182.5990332 58.86546875 -181.9390332 57.87546875 -181.2590332 56.85546875 C-180.93032227 57.46132812 -180.60161133 58.0671875 -180.26293945 58.69140625 C-172.21889547 72.86113142 -160.79177658 83.491992 -144.8840332 88.23046875 C-127.13242009 91.2910917 -110.45150547 88.72225434 -95.2590332 78.85546875 C-83.60677615 70.49132656 -75.75104634 56.9235307 -73.2590332 42.85546875 C-71.45757952 24.03946126 -74.73970981 8.78864654 -86.8762207 -6.1328125 C-90.96217608 -10.5413433 -95.77705169 -13.57401274 -100.90356445 -16.6640625 C-103.2590332 -18.14453125 -103.2590332 -18.14453125 -105.2590332 -20.14453125 C-103.57312478 -20.62926803 -101.88520775 -21.10702051 -100.1965332 -21.58203125 C-98.78694336 -21.98228516 -98.78694336 -21.98228516 -97.34887695 -22.390625 C-64.24168178 -30.4686132 -26.24452842 -21.45755623 0 0 Z " fill="#131928" transform="translate(344.259033203125,182.14453125)"/>
<path d="M0 0 C27.51668329 -1.54459553 56.68622642 12.36261605 76.97143555 30.24731445 C100.05828616 51.22761351 116.14269665 79.83089922 118.22119141 111.35473633 C119.4842267 149.41509562 109.54536352 181.25369492 83.42504883 209.56640625 C61.20694161 232.76768274 30.18258643 245.68447023 -1.72436523 246.47045898 C-37.47694444 246.75019142 -67.91707948 234.63666274 -93.52539062 209.50195312 C-112.03605933 190.64804024 -127.24579555 162.86302866 -128.09765625 135.91015625 C-128.08605469 134.97042969 -128.07445312 134.03070313 -128.0625 133.0625 C-128.05347656 132.10472656 -128.04445312 131.14695312 -128.03515625 130.16015625 C-128.01775391 129.09087891 -128.01775391 129.09087891 -128 128 C-127.67 128 -127.34 128 -127 128 C-126.79246094 129.23492187 -126.58492187 130.46984375 -126.37109375 131.7421875 C-122.03641631 156.12747696 -112.65378734 175.70645513 -96 194 C-95.43023437 194.65226563 -94.86046875 195.30453125 -94.2734375 195.9765625 C-77.53338041 214.09016274 -49.82674725 227.04001852 -25.19677734 228.12329102 C8.55585455 228.96826963 38.21751895 221.8135893 64 199 C64.82757813 198.27296875 65.65515625 197.5459375 66.5078125 196.796875 C87.15165343 177.37583998 99.32367565 148.51732778 100.28515625 120.4453125 C100.52162139 108.31802898 100.3989619 96.7167467 97 85 C96.68289063 83.824375 96.36578125 82.64875 96.0390625 81.4375 C91.07002873 64.80357134 82.4108957 49.99996858 71 37 C70.28457031 36.18402344 69.56914062 35.36804688 68.83203125 34.52734375 C50.47303107 14.99722536 25.98974766 5.20070823 0 1 C0 0.67 0 0.34 0 0 Z " fill="#6865CD" transform="translate(286,158)"/>
</svg>

After

Width:  |  Height:  |  Size: 5.5 KiB

1
static/icons/5.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" viewBox="0 0 512 512"><circle cx="256" cy="256" r="256"/><path d="M268.6 102.4c64.4 0 116.8 52.4 116.8 116.7 0 25.3-8 49.4-23 69.6-14.8 19.9-35 34.3-58.4 41.7l-6.5 2-15.5-76.2 4.3-2c14-6.7 23-21.1 23-36.6 0-22.4-18.2-40.6-40.6-40.6S228 195.2 228 217.6c0 15.5 9 29.8 23 36.6l4.2 2-25 153.4h-69.5V102.4z" style="fill:#fff"/></svg>

After

Width:  |  Height:  |  Size: 389 B

1
static/icons/6.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" viewBox="0 0 512 512"><circle cx="256" cy="256" r="256" style="fill:#292b2f"/><path d="M380.6 344.1c-14.8 0-27.5 8.6-33.5 21.1l-53.2-7.7c-.2-20.3-16.7-36.8-37.1-36.8-7.3 0-14 2.1-19.8 5.7l-75.6-85.6c4.4-6.1 6.9-13.5 6.9-21.6 0-20.5-16.6-37.1-37.1-37.1s-37.1 16.6-37.1 37.1 16.6 37.1 37.1 37.1c6.3 0 12.3-1.6 17.5-4.4l76.4 86.5c-3.4 5.6-5.4 12.2-5.4 19.3 0 20.5 16.6 37.1 37.1 37.1 14.7 0 27.4-8.5 33.4-20.9l53.3 7.7c.3 20.2 16.8 36.5 37.1 36.5 20.5 0 37.1-16.6 37.1-37.1.1-20.3-16.6-36.9-37.1-36.9" style="fill:#fff"/><path d="M380.6 93.7c-20.5 0-37.1 16.6-37.1 37.1 0 10.1 4 19.2 10.6 25.9L271.8 273c-4.6-2-9.6-3.1-15-3.1-20.5 0-37.1 16.6-37.1 37.1q0 5.55 1.5 10.5l-62.5 38.7c-6.8-7.4-16.6-12.1-27.4-12.1-20.5 0-37.1 16.6-37.1 37.1s16.6 37.1 37.1 37.1 37.1-16.6 37.1-37.1c0-3.5-.5-7-1.4-10.2l62.6-38.8c6.8 7.3 16.5 11.9 27.2 11.9 20.5 0 37.1-16.6 37.1-37.1 0-9-3.2-17.3-8.6-23.8l83-117.3c3.8 1.3 7.9 2.1 12.2 2.1 20.5 0 37.1-16.6 37.1-37.1s-16.5-37.2-37-37.2" style="fill:#e5a00d"/></svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

1
static/icons/7.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 7.8 KiB

1
static/icons/8.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" viewBox="0 0 512 512"><path d="M76.8 0h358.4C477.6 0 512 34.4 512 76.8v358.4c0 42.4-34.4 76.8-76.8 76.8H76.8C34.4 512 0 477.6 0 435.2V76.8C0 34.4 34.4 0 76.8 0" style="fill:#175ddc"/><path d="M372 297V131H256v294c47-28 115-74 116-128m49-198v198c0 106-152 181-165 181S91 403 91 297V99s0-17 17-17h296s17 0 17 17" style="fill:#fff"/></svg>

After

Width:  |  Height:  |  Size: 397 B

1
static/icons/9.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 8.9 KiB

5
static/lock.svg Normal file
View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M12 22C17.5228 22 22 17.5228 22 12C22 6.47715 17.5228 2 12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22Z" fill="#878e96"/>
<path d="M15.7491 10.73V10C15.7491 9.07 15.7491 6.25 11.9991 6.25C8.24915 6.25 8.24915 9.07 8.24915 10V10.73C7.02915 11 6.61914 11.79 6.61914 13.5V14.5C6.61914 16.7 7.29915 17.38 9.49915 17.38H14.4991C16.6991 17.38 17.3792 16.7 17.3792 14.5V13.5C17.3792 11.79 16.9691 11 15.7491 10.73ZM11.9991 15.1C11.3891 15.1 10.8992 14.61 10.8992 14C10.8992 13.39 11.3891 12.9 11.9991 12.9C12.6091 12.9 13.0991 13.39 13.0991 14C13.0991 14.61 12.6091 15.1 11.9991 15.1ZM14.2491 10.62H9.74915V10C9.74915 8.54 10.1091 7.75 11.9991 7.75C13.8891 7.75 14.2491 8.54 14.2491 10V10.62Z" fill="#292D32"/>
</svg>

After

Width:  |  Height:  |  Size: 950 B

6
static/no_access.svg Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg fill="#000000" width="800px" height="800px" viewBox="0 0 36 36" version="1.1" preserveAspectRatio="xMidYMid meet" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>no-access-solid</title>
<path d="M18,2A16,16,0,1,0,34,18,16,16,0,0,0,18,2ZM29.15,20H6.85A.85.85,0,0,1,6,19.15V16.85A.85.85,0,0,1,6.85,16H29.15a.85.85,0,0,1,.85.85v2.29A.85.85,0,0,1,29.15,20Z" class="clr-i-solid clr-i-solid-path-1"></path>
<rect x="0" y="0" width="36" height="36" fill-opacity="0"/>
</svg>

After

Width:  |  Height:  |  Size: 642 B

59
templates/home.html Normal file
View File

@@ -0,0 +1,59 @@
<!DOCTYPE html>
<html lang="en" data-bs-theme="dark">
<head>
<meta charset="UTF-8">
<title>Debug Divs</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-sRIl4kxILFvY47J16cr9ZwB07vP4J8+LH7qKQnuqkuIAvNWLzeN8tE5YBujZqJLB" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/js/bootstrap.bundle.min.js"
integrity="sha384-FKyoEForCGlyvwx9Hj09JcYn3nv7wiPVlz7YYwJrWVcXK/BmnVDxM+D2scQbITxI"
crossorigin="anonymous"></script>
</head>
<body id="main_body" class="m-2 bg-light-subtle d-flex flex-wrap justify-content-center">
</body>
<script>
const main_body = document.getElementById("main_body");
const url = '/api/status';
function fetchData() {
fetch(url, { cache: 'no-store' })
.then(response => response.json())
.then(data => {
console.log(data)
updateWebpage(data)
})
.catch(error => console.error("Error fetching data", error))
.finally(() => {
setTimeout(fetchData, 1000); // schedule next request after 1 second
});
}
function updateWebpage(services) {
main_body.innerHTML = ''; // Clear webpage
// Build all service divs as a single string
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: 200px">
<div class="bg-body-tertiary d-flex flex-column align-items-center">
<div class="bg-dark w-100">
<h4 class="text-center text-truncate m-0" style="font-size: 1.5rem;">${s.label}</h4>
</div>
<div class="position-relative ratio ratio-1x1">
<img src="static/icons/${s.id}.${s.icon_filetype}" class="img-fluid">
${s.public ? `` : `<div>
<img src='static/lock.svg' class='img-fluid position-absolute bottom-0 end-0 w-25'>
</div>` }
</div>
</div>
</a>
`).join(''); // join into a single string
}
fetchData(); // start the loop
</script>
</html>