controller v0.264.0: the household is told when an update is undone or held, in its language
gates / gates (push) Successful in 25s

app_update_undone / app_update_held events (09 decision 15), on by
default and seeded once on existing boxes; R-606 update sentences as
key+args rendered per reader; R-646 startup applied-meta backfill for
apps current with the catalog; R-620 a disabled notifier WARNs once per
event type. Needs hub v0.120.0.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
This commit is contained in:
2026-09-23 13:51:21 +02:00
parent c3a2aba0d2
commit bc278944a3
27 changed files with 1086 additions and 86 deletions
@@ -29,11 +29,11 @@
</div>
{{if .Stack.Updating}}
<div class="alert alert-info" style="margin-top:1rem" data-update-phase="{{.Stack.UpdatePhase}}">{{.Stack.UpdatePhaseLabel}}</div>
<div class="alert alert-info" style="margin-top:1rem" data-update-phase="{{.Stack.UpdatePhase}}">{{updatePhaseText .Stack}}</div>
{{else if .Stack.HoldReason}}
<div class="alert alert-error" style="margin-top:1rem" data-held="true">{{.Stack.HoldReason}} <a href="/backups/apps" class="btn btn-sm btn-outline">{{T "app_info.mentesek"}}</a></div>
<div class="alert alert-error" style="margin-top:1rem" data-held="true">{{holdText .Stack}} <a href="/backups/apps" class="btn btn-sm btn-outline">{{T "app_info.mentesek"}}</a></div>
{{else if .Stack.UpdateError}}
<div class="alert alert-warning" style="margin-top:1rem" data-update-error="true">{{.Stack.UpdateError}}</div>
<div class="alert alert-warning" style="margin-top:1rem" data-update-error="true">{{updateErrorText .Stack}}</div>
{{else if .UpdateUndoneLine}}
<div class="alert alert-info" style="margin-top:1rem" data-update-undone="true">{{.UpdateUndoneLine}}</div>
{{end}}
@@ -74,6 +74,14 @@
<input type="checkbox" name="event_app_start_failed" {{with .NotificationPrefs}}{{range .EnabledEvents}}{{if eq . "app_start_failed"}}checked{{end}}{{end}}{{end}}>
<span class="toggle-label">{{T "settings_notifications.alkalmazas_nem_fut"}}</span>
</label>
<label class="toggle">
<input type="checkbox" name="event_app_update_undone" {{with .NotificationPrefs}}{{range .EnabledEvents}}{{if eq . "app_update_undone"}}checked{{end}}{{end}}{{end}}>
<span class="toggle-label">{{T "settings_notifications.app_update_undone"}}</span>
</label>
<label class="toggle">
<input type="checkbox" name="event_app_update_held" {{with .NotificationPrefs}}{{range .EnabledEvents}}{{if eq . "app_update_held"}}checked{{end}}{{end}}{{end}}>
<span class="toggle-label">{{T "settings_notifications.app_update_held"}}</span>
</label>
</div>
</div>
<div class="form-group">
@@ -91,17 +91,17 @@
a green Frissítés beside a crash loop. An app being updated offers no lifecycle
button; a held app offers none that would start it, only the way back. */}}
{{if .Updating}}
<span class="tag tag-progress" data-update-phase="{{.UpdatePhase}}"><span class="dot"></span>{{.UpdatePhaseLabel}}</span>
<span class="tag tag-progress" data-update-phase="{{.UpdatePhase}}"><span class="dot"></span>{{updatePhaseText .}}</span>
{{else if .HoldReason}}
<div class="alert alert-error" data-held="true">{{.HoldReason}} <a href="/backups/apps" class="btn btn-sm btn-outline">{{T "stacks.mentesek"}}</a></div>
<div class="alert alert-error" data-held="true">{{holdText .}} <a href="/backups/apps" class="btn btn-sm btn-outline">{{T "stacks.mentesek"}}</a></div>
{{if not .Orphaned}}<button class="btn btn-danger" onclick="removeStack('{{.Name}}')">{{T "common.eltavolitas"}}</button>{{end}}
{{else if isOperational .State}}
{{if .UpdateError}}<div class="alert alert-warning" data-update-error="true">{{.UpdateError}}</div>{{end}}
{{if .UpdateError}}<div class="alert alert-warning" data-update-error="true">{{updateErrorText .}}</div>{{end}}
{{if not .Orphaned}}<button class="btn btn-success" onclick="stackAction(event, '{{.Name}}', 'update')">{{T "stacks.frissites"}}</button>{{end}}
<button class="btn btn-warning" onclick="stackAction(event, '{{.Name}}', 'restart')">{{T "common.ujrainditas"}}</button>
<button class="btn btn-danger" onclick="stackAction(event, '{{.Name}}', 'stop')">{{T "stacks.leallitas"}}</button>
{{else}}
{{if .UpdateError}}<div class="alert alert-warning" data-update-error="true">{{.UpdateError}}</div>{{end}}
{{if .UpdateError}}<div class="alert alert-warning" data-update-error="true">{{updateErrorText .}}</div>{{end}}
<button class="btn btn-success" onclick="stackAction(event, '{{.Name}}', 'start')">{{T "stacks.inditas"}}</button>
{{if not .Orphaned}}<button class="btn btn-danger" onclick="removeStack('{{.Name}}')">{{T "common.eltavolitas"}}</button>{{end}}
{{end}}