987e915bf2
New /launcher page: a grid of large tappable tiles, one per openable deployed app (subdomain presence is the single openability criterion, shared with the Megnyitás button via the extracted Server.subdomainMap helper). Colored tiles (deterministic slug color or .felhom.yml brand_color), white glyph/monogram fallback, target=_blank links for operational apps, greyed unclickable tiles for stopped ones. First sidebar item; / stays the Vezérlőpult. Universal app placeholder: new AppPlaceholderSVG served at /static/app-placeholder.svg, now the default FallbackIcon on app_list_row so a logo-less app shows a placeholder instead of visibility:hidden. Brand mark is never an app placeholder. New Metadata.BrandColor; new funcmap tileColor/initial. 10 new test functions + 4 red-proofs. No agent coupling; MinAgent unchanged.
33 lines
1.9 KiB
HTML
33 lines
1.9 KiB
HTML
{{/* app_list_row / app_list_row_end — THE canonical app-list row (v0.126.0).
|
|
One grammar on every list surface: icon + name (+ optional one-line secondary) left,
|
|
caller-provided action block right. A row without a secondary line stays compact.
|
|
|
|
Usage (the layout_start/layout_end idiom):
|
|
{{template "app_list_row" dict "Slug" .Slug "Name" .DisplayName}}
|
|
...caller action buttons / status...
|
|
{{template "app_list_row_end"}}
|
|
|
|
dict keys: Slug (icon lookup), Name, Secondary (optional one-liner),
|
|
RowClass (optional extra row class, e.g. stack-state-run), Href (optional data-href),
|
|
FallbackIcon (optional last-resort icon URL). DEFAULTS to /static/app-placeholder.svg (the
|
|
generic app-grid glyph) when a caller omits it — so a logo-less app shows a placeholder, not a
|
|
hidden dead-end. Infra rows pass /static/infra-logo.svg to override that with the server glyph.
|
|
|
|
Do NOT hand-roll app rows — scripts/app_row_dedup_gate.py asserts this markup exists
|
|
here ONCE (the backups_apps expander header is the single allowlisted aligned copy). */}}
|
|
{{define "app_list_row"}}
|
|
<div class="app-row{{with .RowClass}} {{.}}{{end}}"{{with .Href}} data-href="{{.}}"{{end}}>
|
|
<img class="app-row-icon" src="{{logoURL .Slug}}" alt="" data-fallback="{{if .FallbackIcon}}{{.FallbackIcon}}{{else}}/static/app-placeholder.svg{{end}}"
|
|
onerror="if(!this.dataset.step){this.dataset.step='1';this.src='{{logoPNGURL .Slug}}';}else if(this.dataset.fallback&&this.dataset.step==='1'){this.dataset.step='2';this.src=this.dataset.fallback;}else{this.onerror=null;this.style.visibility='hidden';}">
|
|
<div class="app-row-text">
|
|
<span class="app-row-name">{{.Name}}</span>
|
|
{{with .Secondary}}<span class="app-row-secondary">{{.}}</span>{{end}}
|
|
</div>
|
|
<div class="app-row-actions">
|
|
{{end}}
|
|
|
|
{{define "app_list_row_end"}}
|
|
</div>
|
|
</div>
|
|
{{end}}
|