diff --git a/resources/views/errors/503.blade.php b/resources/views/errors/503.blade.php index 80fcda2..bf4d881 100644 --- a/resources/views/errors/503.blade.php +++ b/resources/views/errors/503.blade.php @@ -13,33 +13,8 @@ mid-deploy or freshly installed, which is exactly when the Vite manifest may not exist. Pulling it in through @vite would throw an exception instead of rendering the reassurance the visitor came for. --}} - - -
-
-
{{ __('updating.badge') }}
-

{{ __('updating.title') }}

-

{{ __('updating.body') }}

-

{{ __('updating.auto') }}

-
+ + @include('partials.updating-panel') diff --git a/resources/views/layouts/admin.blade.php b/resources/views/layouts/admin.blade.php index f6dc560..f647cb6 100644 --- a/resources/views/layouts/admin.blade.php +++ b/resources/views/layouts/admin.blade.php @@ -119,47 +119,23 @@ x-transition:enter="transition ease-out duration-200" x-transition:enter-start="opacity-0" x-transition:enter-end="opacity-100" - class="fixed inset-0 z-[100] flex items-center justify-center bg-bg px-4" + class="fixed inset-0 z-[100] overflow-auto" role="alert" aria-live="assertive" > -
-
- -
- -

{{ __('admin_settings.update_overlay_title') }}

-

{{ __('admin_settings.update_offline_hint') }}

- - {{-- Queued: the agent has not picked the request up yet, so there - is no step yet either. - - This used to count down to the agent's next tick. It was wrong - twice over. Wrong in fact: the countdown target was recomputed - on every poll, and where the reported interval was shorter than - the timer actually installed it landed in the past every time - and reset to a full minute — so it ran backwards four seconds - and jumped, forever. And wrong in kind: with the agent woken - the moment the request lands there is nothing left to wait for. - A sentence, not a clock. --}} -

- {{ $updateState['instant'] ? __('admin_settings.update_starting') : __('admin_settings.update_starting_queued') }} -

- - {{-- Running: the step, how long it has been going, and the tail - of the log — a run that IS stuck is then visibly stuck AT a - step, not just a spinner nobody can read anything from. --}} -
-

-

-

-            
-
+ {{-- The SAME panel the 503 page renders. It used to be a light card in + the app's own tokens, which meant an operator saw one design while + the application was still up and a completely different one the + moment the containers went down — two faces for one event, swapping + mid-update. The operator detail rides along inside it rather than + beside it. --}} + @include('partials.updating-panel', [ + 'body' => __('admin_settings.update_offline_hint'), + 'detail' => true, + 'starting' => $updateState['instant'] + ? __('admin_settings.update_starting') + : __('admin_settings.update_starting_queued'), + ]) @livewire('wire-elements-modal') diff --git a/resources/views/partials/updating-panel.blade.php b/resources/views/partials/updating-panel.blade.php new file mode 100644 index 0000000..6dcf8df --- /dev/null +++ b/resources/views/partials/updating-panel.blade.php @@ -0,0 +1,71 @@ +{{-- + "We are updating" — one panel, used in both places it can appear. + + It showed up twice with two different faces: the console's own overlay in the + app's light tokens while the application was still up, and then this, the + 503 page, once the containers went down. Two designs for one event, one + replacing the other mid-update. Reported as "the first screen must not be + there", and rightly. + + The styles are inline and self-contained rather than Tailwind classes, + because the other place this renders is the 503 page — shown while the + application is mid-deploy or freshly installed, exactly when the Vite + manifest may not exist. A stylesheet reference there would throw instead of + rendering the reassurance the visitor came for. + + Prefixed class names: this is injected into the console's own document, + which has a stylesheet of its own, and `.badge` is not a name to claim + globally. +--}} + + +
+
+
+
{{ __('updating.badge') }}
+

{{ __('updating.title') }}

+

{{ $body ?? __('updating.body') }}

+ + {{-- Only in the console. A customer looking at the 503 has no use for a + deployment step, and an operator watching a run that is stuck has + no use for anything else: "läuft gerade" alone is what sends + somebody to the shell. The markup is Alpine-driven and inert + wherever Alpine is not — which is why it is behind a flag rather + than always present. --}} + @if ($detail ?? false) +
+

{{ $starting ?? '' }}

+

+

+

+            
+ @endif +

{{ __('updating.auto') }}

+
+
diff --git a/tests/Feature/Admin/UpdateButtonTest.php b/tests/Feature/Admin/UpdateButtonTest.php index f63a433..30de3f0 100644 --- a/tests/Feature/Admin/UpdateButtonTest.php +++ b/tests/Feature/Admin/UpdateButtonTest.php @@ -761,3 +761,32 @@ it('does not answer the watcher for somebody who is not an operator', function ( ->get(route('admin.update.state')) ->assertForbidden(); }); + +it('shows one design while updating, not two swapping mid-run', function () { + // Reported as "the first screen must not be there". It was the console's + // own overlay in the app's light tokens; then the containers went down and + // the 503 page took over with a completely different face. Two designs for + // one event, replacing each other mid-update. + // + // Both render the same partial now, so there is nothing left that can + // disagree. + $console = Illuminate\Support\Facades\File::get(resource_path('views/layouts/admin.blade.php')); + $maintenance = Illuminate\Support\Facades\File::get(resource_path('views/errors/503.blade.php')); + + expect($console)->toContain("partials.updating-panel") + ->and($maintenance)->toContain("partials.updating-panel") + // And nothing left behind that would render a second look. + ->and($console)->not->toContain('update_overlay_title') + ->and($maintenance)->not->toContain('