TenantAtlas/resources/views/filament/pages/operations/tenantless-operation-run-viewer.blade.php
ahmido a107e7e41b feat: restore safety integrity and queue slide-over (#210)
## Summary
- add the Spec 181 restore-safety layer with scope fingerprinting, preview/check integrity states, execution safety snapshots, result attention, and operator-facing copy across the wizard, restore detail, and canonical operation detail
- add focused unit and feature coverage for restore-safety assessment, result attention, and restore-linked operation detail
- switch the finding exceptions queue `Inspect exception` action to a native Filament slide-over while preserving query-param-backed inline summary behavior

## Testing
- `vendor/bin/sail artisan test --compact tests/Feature/Monitoring/FindingExceptionsQueueTest.php tests/Feature/Filament/RestoreSafetyIntegrityWizardTest.php tests/Feature/Filament/RestoreResultAttentionSurfaceTest.php tests/Feature/Operations/RestoreLinkedOperationDetailTest.php tests/Unit/Support/RestoreSafety`

## Notes
- Spec 181 checklist is complete (`specs/181-restore-safety-integrity/checklists/requirements.md`)
- the branch still has unchecked follow-up tasks in `specs/181-restore-safety-integrity/tasks.md`: `T012`, `T018`, `T019`, `T023`, `T025`, `T029`, `T032`, `T033`, `T041`, `T042`, `T043`, `T044`
- Filament v5 / Livewire v4 compliance is preserved, no panel provider registration changes were made, no global-search behavior was added, destructive actions remain confirmation-gated, and no new Filament assets were introduced

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #210
2026-04-06 23:37:14 +00:00

83 lines
4.0 KiB
PHP

@php
$contextBanner = $this->canonicalContextBanner();
$blockedBanner = $this->blockedExecutionBanner();
$lifecycleBanner = $this->lifecycleBanner();
$restoreContinuationBanner = $this->restoreContinuationBanner();
$pollInterval = $this->pollInterval();
@endphp
<x-filament-panels::page>
<div
@if ($pollInterval !== null) wire:poll.{{ $pollInterval }} @endif
>
@if ($contextBanner !== null)
@php
$bannerClasses = match ($contextBanner['tone']) {
'amber' => 'border-amber-200 bg-amber-50 text-amber-900 dark:border-amber-500/30 dark:bg-amber-500/10 dark:text-amber-100',
'slate' => 'border-slate-200 bg-slate-50 text-slate-900 dark:border-slate-500/30 dark:bg-slate-500/10 dark:text-slate-100',
default => 'border-sky-200 bg-sky-50 text-sky-900 dark:border-sky-500/30 dark:bg-sky-500/10 dark:text-sky-100',
};
@endphp
<div class="mb-6 rounded-lg border px-4 py-3 text-sm {{ $bannerClasses }}">
<p class="font-semibold">{{ $contextBanner['title'] }}</p>
<p class="mt-1">{{ $contextBanner['body'] }}</p>
</div>
@endif
@if ($blockedBanner !== null)
@php
$blockedBannerClasses = 'border-amber-200 bg-amber-50 text-amber-900 dark:border-amber-500/30 dark:bg-amber-500/10 dark:text-amber-100';
@endphp
<div class="mb-6 rounded-lg border px-4 py-3 text-sm {{ $blockedBannerClasses }}">
<p class="font-semibold">{{ $blockedBanner['title'] }}</p>
<p class="mt-1">{{ $blockedBanner['body'] }}</p>
</div>
@endif
@if ($lifecycleBanner !== null)
@php
$lifecycleBannerClasses = match ($lifecycleBanner['tone']) {
'rose' => 'border-rose-200 bg-rose-50 text-rose-900 dark:border-rose-500/30 dark:bg-rose-500/10 dark:text-rose-100',
default => 'border-amber-200 bg-amber-50 text-amber-900 dark:border-amber-500/30 dark:bg-amber-500/10 dark:text-amber-100',
};
@endphp
<div class="mb-6 rounded-lg border px-4 py-3 text-sm {{ $lifecycleBannerClasses }}">
<p class="font-semibold">{{ $lifecycleBanner['title'] }}</p>
<p class="mt-1">{{ $lifecycleBanner['body'] }}</p>
</div>
@endif
@if ($restoreContinuationBanner !== null)
@php
$restoreContinuationClasses = match ($restoreContinuationBanner['tone']) {
'amber' => 'border-amber-200 bg-amber-50 text-amber-900 dark:border-amber-500/30 dark:bg-amber-500/10 dark:text-amber-100',
default => 'border-sky-200 bg-sky-50 text-sky-900 dark:border-sky-500/30 dark:bg-sky-500/10 dark:text-sky-100',
};
@endphp
<div class="mb-6 rounded-lg border px-4 py-3 text-sm {{ $restoreContinuationClasses }}">
<p class="font-semibold">{{ $restoreContinuationBanner['title'] }}</p>
<p class="mt-1">{{ $restoreContinuationBanner['body'] }}</p>
@if ($restoreContinuationBanner['url'] !== null && $restoreContinuationBanner['link_label'] !== null)
<p class="mt-3">
<a href="{{ $restoreContinuationBanner['url'] }}" class="font-semibold underline underline-offset-2">
{{ $restoreContinuationBanner['link_label'] }}
</a>
</p>
@endif
</div>
@endif
@if ($this->redactionIntegrityNote())
<div class="mb-6 rounded-lg border border-amber-200 bg-amber-50 px-4 py-3 text-sm text-amber-900 dark:border-amber-500/30 dark:bg-amber-500/10 dark:text-amber-100">
{{ $this->redactionIntegrityNote() }}
</div>
@endif
{{ $this->infolist }}
</div>
</x-filament-panels::page>