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:
2026-10-08 14:32:06 +02:00
parent 05e129267a
commit d5f2e47ea1
8 changed files with 330 additions and 9 deletions
+46 -1
View File
@@ -338,8 +338,40 @@ func (am *AlertManager) Refresh(report *monitor.HealthReport, cfg *config.Config
am.mu.Unlock()
}
// GetAlerts returns a copy of the current alerts, optionally excluding specific IDs.
// GetAlerts returns a copy of the current alerts, optionally excluding specific IDs. It keeps the
// Inline and page-bound alerts (the debug dump and the placement tests read them); a page's banner
// reads GetBannerAlerts instead.
func (am *AlertManager) GetAlerts(lang string, excludeIDs ...string) []Alert {
return am.collectAlerts(lang, nil, excludeIDs...)
}
// GetBannerAlerts returns only the alerts the layout banner shows on page — no Inline alert, no alert
// whose PageOnly leaves page out — and caps THAT list. R-906: the cap used to count every alert and
// the layout dropped the other pages' alerts afterwards, so a page could show „+ 5 további
// figyelmeztetés" with no warning above it (9202, nine inline disk warnings). Pinned by
// TestR906_OverflowCountsOnlyThisPagesBannerAlerts.
func (am *AlertManager) GetBannerAlerts(page, lang string) []Alert {
return am.collectAlerts(lang, func(a Alert) bool { return bannerShows(a, page) })
}
// bannerShows is the layout's own filter (layout.html: not Inline, and PageOnly empty or naming the
// page), in Go, so the cap and the template agree on what a page shows.
func bannerShows(a Alert, page string) bool {
if a.Inline {
return false
}
if len(a.PageOnly) == 0 {
return true
}
for _, p := range a.PageOnly {
if p == page {
return true
}
}
return false
}
func (am *AlertManager) collectAlerts(lang string, keep func(Alert) bool, excludeIDs ...string) []Alert {
am.mu.RLock()
defer am.mu.RUnlock()
@@ -377,6 +409,19 @@ func (am *AlertManager) GetAlerts(lang string, excludeIDs ...string) []Alert {
result = append(result, a)
}
if keep != nil {
kept := result[:0]
for _, a := range result {
if keep(a) {
kept = append(kept, a)
}
}
result = kept
if len(result) == 0 {
return nil
}
}
// Cap at 5 visible alerts
if len(result) > 5 {
overflow := len(result) - 5