f30a80841e
gates / gates (push) Successful in 50s
FileBrowser (and traefik, cloudflared, samba) has no app.yaml, so Deployed is false. Since v0.315.0 the app page read Deployed alone and showed FileBrowser "not installed", with Install and without its login. A protected infra stack is now installed by definition on the app page (Deployed || Protected, as every other surface already counted): settings/guide/log tabs, Restart only, no install page, no data tab. The Install press would have deployed the infra stack as an app: DeployStack and the deploy API now refuse a protected stack. In the operator state (the box does not know FileBrowser's password - both demo boxes) the login panel offers "Új jelszó beállítása": the file browser's own CLI with the server stopped (spiked on demo-hp: new 200, old 401, users/shares/settings unchanged), verified, stored encrypted, state generated. Every installed app's settings tab has the login panel with exactly one answer: the box's fields, the login the app wrote (InitialCreds), or a sentence chosen by the catalog's new app_info.login_kind (first_visit default, email, none; none behind the family gate says the family sign-in is the login). "Fájlok ↗" opens the library folder, else the first declared folder, else a media app's first present drive's media folder. The data tab lists each drive's media folders; a folder whose drive is not bound into FileBrowser is text, never a link. Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
84 lines
4.1 KiB
Go
84 lines
4.1 KiB
Go
package web
|
||
|
||
import "gitea.dooplex.hu/admin/felhom-controller/internal/i18n"
|
||
|
||
// Infra-stack display metadata (v0.126.0 Part B). The protected base stacks (infra.go:
|
||
// traefik, cloudflared, filebrowser) carry no catalog metadata, so they rendered as bare
|
||
// directory names on the dashboard and app cards. This map gives them curated Hungarian
|
||
// identity — DISPLAY ONLY, keyed by stack name; it never affects protection, deploy or
|
||
// backup logic.
|
||
//
|
||
// Linked marks the ONLY infra stack with a customer-facing UI (filebrowser →
|
||
// files.<domain>). cloudflared and traefik have no customer UI — rendering an open link
|
||
// for them is the guarded-wrong outcome (render test asserts absence).
|
||
|
||
// InfraMeta is one protected infra stack's customer-facing identity.
|
||
type InfraMeta struct {
|
||
DisplayName string
|
||
Description string
|
||
Linked bool // has a customer-facing URL (subdomain via protectedStackSubdomains)
|
||
}
|
||
|
||
var infraMetaMap = map[string]InfraMeta{
|
||
"cloudflared": {
|
||
DisplayName: "Cloudflare Tunnel",
|
||
Description: "Biztonságos internetkapcsolat — a szerver portnyitás nélkül érhető el kívülről.",
|
||
},
|
||
"traefik": {
|
||
DisplayName: "Traefik",
|
||
Description: "Forgalomirányító (reverse proxy) — a kéréseket a megfelelő alkalmazáshoz irányítja.",
|
||
},
|
||
"filebrowser": {
|
||
DisplayName: "FileBrowser",
|
||
Description: "Fájlkezelő — a tárhely fájljainak böngészése a böngészőből.",
|
||
Linked: true,
|
||
},
|
||
// R-7: the LAN sharing stack has no web UI of its own (it is reached from Windows Intéző /
|
||
// Mac Finder), so Linked stays false — it is configured on the „Megosztás" page.
|
||
"samba": {
|
||
DisplayName: "Hálózati megosztás",
|
||
Description: "Fájlmegosztás a helyi hálózaton — a mappák a Windows Intézőben és a Mac Finderben jelennek meg.",
|
||
},
|
||
}
|
||
|
||
// infraMetaFor returns the curated metadata for a protected infra stack, nil for
|
||
// everything else (templates branch on the nil).
|
||
func infraMetaFor(stackName string) *InfraMeta {
|
||
if m, ok := infraMetaMap[stackName]; ok {
|
||
return &m
|
||
}
|
||
return nil
|
||
}
|
||
|
||
// infraMetaIn is infraMetaFor in a language: names that are product names stay; descriptions — and samba's display
|
||
// name — come from the bundle. The template func `infraMeta` and the app page (v0.320.0) both read it here.
|
||
func infraMetaIn(b *i18n.Bundle, lang, stackName string) *InfraMeta {
|
||
m := infraMetaFor(stackName)
|
||
if m == nil {
|
||
return nil
|
||
}
|
||
out := *m
|
||
if b == nil {
|
||
return &out
|
||
}
|
||
if v, _, ok := b.Text(lang, "func.infra."+stackName+".description"); ok {
|
||
out.Description = v
|
||
}
|
||
if v, _, ok := b.Text(lang, "func.infra."+stackName+".display"); ok {
|
||
out.DisplayName = v
|
||
}
|
||
return &out
|
||
}
|
||
|
||
// InfraLogoSVG is the shared generic infra icon (Lucide-style "server", monochrome,
|
||
// --text-2 stroke) — the last-resort icon for infra stacks whose logo asset is not
|
||
// synced. Served at /static/infra-logo.svg; consumed via the app-row FallbackIcon slot.
|
||
const InfraLogoSVG = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="#94A6BF" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="2" width="20" height="8" rx="2"/><rect x="2" y="14" width="20" height="8" rx="2"/><line x1="6" y1="6" x2="6.01" y2="6"/><line x1="6" y1="18" x2="6.01" y2="18"/></svg>`
|
||
|
||
// AppPlaceholderSVG is the generic APP placeholder icon — a 2×2 rounded-square app-grid, matching
|
||
// InfraLogoSVG's monochrome --text-2 visual language but a distinct glyph (apps, not server racks).
|
||
// It is the default FallbackIcon on every app-list row for a regular app whose logo asset is missing,
|
||
// replacing the old visibility:hidden dead-end. NEVER the felhom brand mark: the brand is platform
|
||
// identity, never an app stand-in (design ruling, CONTEXT.md). Served at /static/app-placeholder.svg.
|
||
const AppPlaceholderSVG = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="#94A6BF" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="7" height="7" rx="1.5"/><rect x="14" y="3" width="7" height="7" rx="1.5"/><rect x="3" y="14" width="7" height="7" rx="1.5"/><rect x="14" y="14" width="7" height="7" rx="1.5"/></svg>`
|