Dashboard layout: Apps card header (R-909), launcher header wraps on a phone (R-907), overflow counted after the page filter (R-906)
- Apps card: title row (logo top-aligned, name, address cut with an ellipsis and full in title) over a wrapping .stack-tags row; the tags no longer share a space-between row with the name. - Phone (768px block): .page-header wraps; the share button drops to its own line, text whole. - GetBannerAlerts(page, lang): the layout's filter before the cap; baseData and /monitoring use it. - Tests: TestStackCardHeaderLayout, TestR907_PageHeaderWrapsOnAPhone, TestR906_* (all red against 05e12921). - No Hungarian string changed. The three stacks parity fixtures are re-captured in the next commit (this commit alone fails TestI18nParity on them; both are pushed together). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012qRErfCoiTkvDK9N5XHbzb
This commit is contained in:
@@ -24,12 +24,12 @@
|
||||
<div class="stack-title-row">
|
||||
<img class="stack-logo-lg" src="{{logoURL .Meta.Slug}}" alt="" data-fallback="{{if $im}}/static/infra-logo.svg{{else}}/static/app-placeholder.svg{{end}}"
|
||||
onerror="if(!this.dataset.step){this.dataset.step='1';this.src='{{logoPNGURL .Meta.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>
|
||||
<div class="stack-title-text">
|
||||
<h3>{{if $im}}{{$im.DisplayName}}{{else}}{{.Meta.DisplayName}}{{end}}</h3>
|
||||
{{$subdomain := index $.Subdomains .Name}}
|
||||
{{if and $subdomain (or .Deployed .Protected)}}
|
||||
<a class="subdomain-link" href="https://{{$subdomain}}.{{$.Domain}}" target="_blank">
|
||||
{{$subdomain}}.{{$.Domain}} ↗
|
||||
<a class="subdomain-link" href="https://{{$subdomain}}.{{$.Domain}}" target="_blank" title="{{$subdomain}}.{{$.Domain}}">
|
||||
<span class="subdomain-text">{{$subdomain}}.{{$.Domain}}</span> ↗
|
||||
</a>
|
||||
{{if and .Deployed (routeUnpublished .State)}}
|
||||
<span class="route-unpublished" title="{{T "stacks.a_proxy_traefik_csak_egeszseges"}}"><svg class="ico ico-sm"><use href="#i-triangle-alert"/></svg> {{T "stacks.url_nem_elerheto_utvonal_nincs"}}</span>
|
||||
@@ -37,6 +37,7 @@
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="stack-tags">
|
||||
<span class="tag tag-{{stateColor .State}}"><span class="dot"></span>{{stateLabel .State}}</span>
|
||||
{{if .Orphaned}}<span class="tag tag-warn">{{T "common.elavult"}}</span>{{end}}
|
||||
{{template "meta_badge" (lifecycleBadge .Meta)}}
|
||||
@@ -44,6 +45,7 @@
|
||||
{{$ms := index $.MissingStorage .Name}}{{if $ms}}<span class="tag tag-warn" title="{{T "stacks.az_alkalmazas_adattaroloja_nem_elerheto"}}"><svg class="ico ico-sm"><use href="#i-triangle-alert"/></svg>{{T "stacks.hianyzo_tarhely"}}</span>{{end}}
|
||||
{{$ns := index $.NetworkStubs .Name}}{{if $ns}}<span class="tag tag-warn" title="{{T "stacks.az_alkalmazas_kornyezeteben_a_halozati"}}"><svg class="ico ico-sm"><use href="#i-triangle-alert"/></svg>{{T "stacks.halozati_tarhely_hibas_az_alkalmazas"}}</span>{{end}}
|
||||
{{$nw := index $.NetworkWarnings .Name}}{{if $nw}}<span class="tag tag-warn" title="{{T "stacks.a_halozati_tarhely_nas_jelenleg"}}"><svg class="ico ico-sm"><use href="#i-triangle-alert"/></svg>{{T "stacks.halozati_tarhely_nem_elerheto"}}</span>{{end}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{if $im}}
|
||||
|
||||
@@ -447,24 +447,48 @@ h3 {
|
||||
.stack-detail-card.stack-state-run::before,
|
||||
.stack-detail-card.stack-state-progress::before { background: var(--blue); }
|
||||
.stack-detail-card.stack-state-warn::before { background: var(--warn); }
|
||||
/* Card header, the same on every card (2026-10-08): row 1 = logo + name (+ the address under it), row 2 =
|
||||
the tags, left-aligned and wrapping. The tags used to share one space-between row with the name and
|
||||
covered it once an installed app had two of them; the logo was centred on the name block, so a card
|
||||
with an address carried it lower. Pinned by TestStackCardHeaderLayout. */
|
||||
.stack-detail-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
flex-direction: column;
|
||||
gap: .6rem;
|
||||
margin-bottom: .75rem;
|
||||
}
|
||||
.stack-title-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
align-items: flex-start;
|
||||
gap: .75rem;
|
||||
min-width: 0;
|
||||
}
|
||||
.stack-title-text {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
.stack-title-text h3 { margin-bottom: .25rem; overflow-wrap: anywhere; }
|
||||
.stack-title-text .route-unpublished { white-space: normal; }
|
||||
.stack-tags {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: .4rem;
|
||||
}
|
||||
.subdomain-link {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
gap: .3rem;
|
||||
max-width: 100%;
|
||||
font-size: .8rem;
|
||||
color: var(--blue-bright);
|
||||
text-decoration: none;
|
||||
transition: color 0.2s ease;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.subdomain-text {
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.subdomain-link:hover { text-decoration: underline; }
|
||||
/* Tag — square 2px state chip with a 6px dot. Color only on deviation:
|
||||
@@ -2675,6 +2699,10 @@ a.stat-card:hover {
|
||||
.app-row { flex-wrap: wrap; }
|
||||
.app-row-actions { width: 100%; justify-content: flex-end; }
|
||||
.stack-grid { grid-template-columns: 1fr; }
|
||||
/* R-907: a page header (title, domain chip, buttons) wraps instead of running off the screen; on the
|
||||
launcher the share button drops to its own line. Pinned by TestR907_PageHeaderWrapsOnAPhone. */
|
||||
.page-header { flex-wrap: wrap; row-gap: .6rem; }
|
||||
.share-open-btn { margin-left: 0; white-space: nowrap; }
|
||||
.stats-grid { grid-template-columns: repeat(3, 1fr); }
|
||||
.deploy-info { flex-direction: column; }
|
||||
.system-info-items { flex-direction: column; gap: 1rem; }
|
||||
|
||||
Reference in New Issue
Block a user