From 5277076648f7774d7c647bd21847669f06b9ca27 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 8 Sep 2026 01:44:32 +0000 Subject: [PATCH] fix(web): repair toast, card overflow, version and settings gaps MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Field report from the running appliance: cards overlapped, the test button gave no feedback, the version showed 0.0.0 and the footer was missing. - toast: the redesigned stylesheet had no .toast rule, so every notification rendered as unstyled text below the fold and no action ever appeared to do anything. Restore it as a fixed, elevated, tone-coloured toast above the bottom nav. - resource cards: a long scanner URI blew up the implicit grid track and pushed the card ~140px over its container into the neighbouring column. Pin the track to minmax(0,1fr) and add the missing min-width:0 guards on the flex/grid children that carry truncated text. - connection test: the card action is now "Verbindung prüfen" (so "Testen" is not on screen twice), it locks while running and leaves the result in the card instead of only in a toast. Same for scanners. Target form errors are shown inline as well. - version: in the image app/ is copied to /app, so the lookup landed on /VERSION and always failed. Copy VERSION into the image and resolve it next to the app, at the repo root, or from SCAN2TARGET_VERSION. - settings: add the auto-refresh switch, explain the sign-in card when no account form is shown, and name the Home Assistant endpoint and its method (a browser GET answers 405). - footer: version, source and documentation links plus live/polling state under every view. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01PnunQ6KenoLUPCZRxjvhDd --- Dockerfile | 1 + app/main.py | 23 +++++++--- app/web/src/App.svelte | 2 + app/web/src/app.css | 49 +++++++++++++++++++-- app/web/src/components/layout/Footer.svelte | 29 ++++++++++++ app/web/src/components/ui/Icon.svelte | 2 + app/web/src/lib/i18n.js | 6 +++ app/web/src/views/DevicesView.svelte | 17 +++++-- app/web/src/views/SettingsView.svelte | 11 +++-- app/web/src/views/TargetsView.svelte | 20 ++++++++- 10 files changed, 143 insertions(+), 17 deletions(-) create mode 100644 app/web/src/components/layout/Footer.svelte diff --git a/Dockerfile b/Dockerfile index 0ecb2e3..fd8c112 100644 --- a/Dockerfile +++ b/Dockerfile @@ -37,6 +37,7 @@ WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY app/ ./ +COPY VERSION ./VERSION COPY --from=frontend-builder /app/web/dist ./web/dist RUN mkdir -p /data/scans /data/db /data/auth /data/logs /var/log/scan2target /tmp/scan2target/scans \ diff --git a/app/main.py b/app/main.py index 0da970e..1273873 100644 --- a/app/main.py +++ b/app/main.py @@ -60,12 +60,23 @@ def no_cache_file(path: Path, media_type: str | None = None) -> FileResponse: def get_version() -> str: - version_file = Path(__file__).parent.parent / "VERSION" - try: - return version_file.read_text().strip() - except OSError as exc: - logger.warning("Could not read VERSION file (%s): %s", version_file, exc) - return "0.0.0" + """Read the version from VERSION, next to the app or at the repo root.""" + env_version = os.environ.get("SCAN2TARGET_VERSION", "").strip() + if env_version: + return env_version + + # In the container the app lives at /app, in a checkout at /app. + candidates = ( + Path(__file__).parent / "VERSION", + Path(__file__).parent.parent / "VERSION", + ) + for version_file in candidates: + try: + return version_file.read_text().strip() + except OSError: + continue + logger.warning("Could not read VERSION file (tried: %s)", ", ".join(str(c) for c in candidates)) + return "0.0.0" @asynccontextmanager diff --git a/app/web/src/App.svelte b/app/web/src/App.svelte index b849f89..410d3d3 100644 --- a/app/web/src/App.svelte +++ b/app/web/src/App.svelte @@ -6,6 +6,7 @@ import Sidebar from './components/layout/Sidebar.svelte'; import Topbar from './components/layout/Topbar.svelte'; import BottomNav from './components/layout/BottomNav.svelte'; + import Footer from './components/layout/Footer.svelte'; import Toast from './components/ui/Toast.svelte'; import LoginOverlay from './components/LoginOverlay.svelte'; import NewScanView from './views/NewScanView.svelte'; @@ -48,6 +49,7 @@ {:else if state.page === 'manage'} {:else}{/if} +