From 6aa6eb81a176a8361c940e2184d649c2928130cd Mon Sep 17 00:00:00 2001 From: librelad Date: Wed, 19 Aug 2026 03:08:22 +0100 Subject: [PATCH] Fix WebUI service URLs and Traefik flag; add app icon to instance modal MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Found while installing two LAN-only Bookstack instances — both in the same no-domain path as the previous commit: - apps-services.json advertised every app at http://localhost:. The CFG_SERVER_IP override it reads is defined in no config file, so the lookup always fell through to the "localhost" default — a URL that only resolves for someone browsing on the server itself. Now falls back to $local_ip_v4, the same host APP_URL is stamped with. - traefikManaged was inferred from `access == public`, a stated placeholder. Public only means the port is published on the host; it says nothing about a router. It reported true for both new instances despite their compose having traefik.enable:false. Now read from the port's own traefik column, gated on the app's domain actually being set — resolved per-app here rather than from $domain_full, which this generator never populates. - The "New instance" modal led with bare text. It now shows the type's icon in the same .app-card-icon holder the grid cards use, so it's visually tied to the app the user clicked. Co-Authored-By: Claude Opus 5 --- .../components/apps/core/css/apps.css | 12 +++++ .../apps/core/js/instance-manager.js | 18 ++++++- .../data/generators/apps/webui_services.sh | 47 ++++++++++++++++--- 3 files changed, 70 insertions(+), 7 deletions(-) diff --git a/containers/libreportal/frontend/components/apps/core/css/apps.css b/containers/libreportal/frontend/components/apps/core/css/apps.css index 3bb1600..1b67208 100644 --- a/containers/libreportal/frontend/components/apps/core/css/apps.css +++ b/containers/libreportal/frontend/components/apps/core/css/apps.css @@ -634,9 +634,21 @@ } .lp-instance-head h3 { margin: 0; + /* Takes the slack so the close button stays pinned right once the icon is + added ahead of the title — space-between alone would centre the heading. */ + flex: 1; font-size: 18px; font-weight: 700; } +/* Reuses .app-card-icon (the grid card's holder) for identical framing, scaled + down to sit on a heading line rather than a card. */ +.lp-instance-icon { + width: 44px; + height: 44px; + min-width: 44px; + padding: 8px; + border-radius: 10px; +} .lp-instance-x { background: transparent; border: none; diff --git a/containers/libreportal/frontend/components/apps/core/js/instance-manager.js b/containers/libreportal/frontend/components/apps/core/js/instance-manager.js index e29ba2e..6410cc7 100644 --- a/containers/libreportal/frontend/components/apps/core/js/instance-manager.js +++ b/containers/libreportal/frontend/components/apps/core/js/instance-manager.js @@ -33,12 +33,24 @@ class InstanceManager { } } + // The type's entry in the apps list — source of both the heading and the icon. + _typeApp(typeSlug) { + return (window.apps || []).find(x => (x.command || '').split(' ').pop() === typeSlug); + } + // The type's display title, for the modal heading. _typeTitle(typeSlug) { - const a = (window.apps || []).find(x => (x.command || '').split(' ').pop() === typeSlug); + const a = this._typeApp(typeSlug); return a ? (a.name || typeSlug).split(' - ')[0].trim() : typeSlug; } + // The type's icon. Same source and same default the grid cards use, so the + // modal shows the exact artwork the user just clicked on. + _typeIcon(typeSlug) { + const a = this._typeApp(typeSlug); + return (a && a.icon) || '/core/icons/apps/default.svg'; + } + // user text -> [a-z0-9] id (mirrors the backend's instanceIdPart) _idPart(raw) { return String(raw || '').toLowerCase().replace(/[^a-z0-9]/g, ''); @@ -59,6 +71,7 @@ class InstanceManager { async openCreateModal(typeSlug) { if (document.getElementById('lp-instance-modal')) return; const title = this._typeTitle(typeSlug); + const icon = this._typeIcon(typeSlug); this.domains = await this._loadDomains(); // With no CFG_DOMAIN_n set, a subdomain has nothing to attach to — the backend @@ -76,6 +89,9 @@ class InstanceManager { overlay.innerHTML = `