Dashboard Studio 1.6.1: show version, load fresh files after updates
- Version shown under About in the dashboard settings, with a link to the repository; /api/version reports it - index.html is never cached and stamps the version on every asset URL, so browsers can't keep running old files after an update - Open screens check the version after reconnecting and every 5 minutes and reload into the new version (editing only shows a message); pending saves are flushed first Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -12,6 +12,7 @@ import asyncio
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
import aiohttp
|
||||
@@ -32,7 +33,20 @@ HA_WS_URL = "ws://supervisor/core/websocket"
|
||||
HA_API_URL = "http://supervisor/core/api"
|
||||
INGRESS_PROXY_IP = "172.30.32.2"
|
||||
|
||||
WEB_DIR = Path(__file__).resolve().parent.parent / "web"
|
||||
APP_DIR = Path(__file__).resolve().parent.parent
|
||||
WEB_DIR = APP_DIR / "web"
|
||||
|
||||
|
||||
def read_version():
|
||||
"""The app version from config.yaml (copied into the image next to server/ and web/)."""
|
||||
try:
|
||||
m = re.search(r'^version:\s*"?([^"\n]+)"?', (APP_DIR / "config.yaml").read_text(), re.M)
|
||||
return m.group(1).strip() if m else "dev"
|
||||
except OSError:
|
||||
return "dev"
|
||||
|
||||
|
||||
VERSION = read_version()
|
||||
DATA_DIR = Path("/data") if Path("/data").is_dir() else Path(__file__).resolve().parent.parent / "data"
|
||||
STORE_FILE = DATA_DIR / "dashboards.json"
|
||||
PORT = int(os.environ.get("PORT", "8099"))
|
||||
@@ -86,7 +100,15 @@ def save_store(data):
|
||||
|
||||
|
||||
async def index(request):
|
||||
return web.FileResponse(WEB_DIR / "index.html")
|
||||
# Stamp the version on every asset URL, so an update can never be served from a stale cache.
|
||||
html = (WEB_DIR / "index.html").read_text()
|
||||
html = re.sub(r'(static/[\w.-]+\.(?:js|css|png))"', rf'\1?v={VERSION}"', html)
|
||||
html = html.replace("__VERSION__", VERSION)
|
||||
return web.Response(text=html, content_type="text/html", headers={"Cache-Control": "no-store"})
|
||||
|
||||
|
||||
async def version(request):
|
||||
return web.json_response({"version": VERSION}, headers={"Cache-Control": "no-store"})
|
||||
|
||||
|
||||
async def get_dashboards(request):
|
||||
@@ -191,6 +213,7 @@ async def on_cleanup(app):
|
||||
def make_app():
|
||||
app = web.Application(middlewares=[ingress_only], client_max_size=8 * 1024 * 1024)
|
||||
app.router.add_get("/", index)
|
||||
app.router.add_get("/api/version", version)
|
||||
app.router.add_get("/api/dashboards", get_dashboards)
|
||||
app.router.add_put("/api/dashboards", put_dashboards)
|
||||
app.router.add_get("/api/camera/{entity_id}", camera)
|
||||
@@ -206,5 +229,5 @@ def make_app():
|
||||
if __name__ == "__main__":
|
||||
if IN_HOME_ASSISTANT and not SUPERVISOR_TOKEN:
|
||||
LOG.error("SUPERVISOR_TOKEN is missing; the app can't talk to Home Assistant")
|
||||
LOG.info("Dashboard Studio listening on port %s (data in %s)", PORT, DATA_DIR)
|
||||
LOG.info("Dashboard Studio %s listening on port %s (data in %s)", VERSION, PORT, DATA_DIR)
|
||||
web.run_app(make_app(), port=PORT, access_log=None)
|
||||
|
||||
Reference in New Issue
Block a user