Some checks failed
PR Fast Feedback / fast-feedback (pull_request) Failing after 3m58s
Applied diagnostic surface contract rules to Audit Log inspect modal and Support Diagnostics action context, consolidating raw diagnostic data into safe modals according to Spec 374.
355 lines
18 KiB
PHP
355 lines
18 KiB
PHP
@php
|
|
use Illuminate\Support\Str;
|
|
|
|
/** @var array<string, mixed> $bundle */
|
|
$summary = is_array($bundle['summary'] ?? null) ? $bundle['summary'] : [];
|
|
$context = is_array($bundle['context'] ?? null) ? $bundle['context'] : [];
|
|
$sections = is_array($bundle['sections'] ?? null) ? $bundle['sections'] : [];
|
|
$redaction = is_array($bundle['redaction'] ?? null) ? $bundle['redaction'] : [];
|
|
$notes = is_array($bundle['notes'] ?? null) ? $bundle['notes'] : [];
|
|
$recommendedFirstCheck = is_array(data_get($summary, 'recommended_first_check'))
|
|
? data_get($summary, 'recommended_first_check')
|
|
: null;
|
|
$contextNotes = collect($notes)
|
|
->filter(static fn (mixed $note): bool => is_string($note) && trim($note) !== '')
|
|
->reject(static fn (string $note): bool => str_contains($note, 'redacted support view'))
|
|
->values()
|
|
->all();
|
|
|
|
$availabilityLabel = static function (?string $availability): string {
|
|
return match ($availability) {
|
|
'available' => 'Available',
|
|
'current' => 'Current',
|
|
'fresh' => 'Fresh',
|
|
'ready' => 'Ready',
|
|
'partial' => 'Partial',
|
|
'stale' => 'Stale',
|
|
'error' => 'Error',
|
|
'missing' => 'Not observed',
|
|
'unavailable' => 'Unavailable',
|
|
'redacted' => 'Redacted',
|
|
default => filled($availability) ? Str::headline(str_replace('_', ' ', (string) $availability)) : 'Unknown',
|
|
};
|
|
};
|
|
|
|
$availabilityColor = static function (?string $availability): string {
|
|
return match ($availability) {
|
|
'available', 'current', 'fresh', 'ready' => 'success',
|
|
'partial', 'stale' => 'warning',
|
|
'error', 'missing', 'unavailable' => 'danger',
|
|
default => 'gray',
|
|
};
|
|
};
|
|
|
|
$contextTypeLabel = static function (?string $type): string {
|
|
return match ($type) {
|
|
'operation_run' => 'Operation context',
|
|
'tenant' => 'Environment context',
|
|
default => filled($type) ? Str::headline(str_replace('_', ' ', (string) $type)) : 'Environment context',
|
|
};
|
|
};
|
|
|
|
$freshnessStateLabel = static function (?string $state): string {
|
|
return match ($state) {
|
|
'fresh' => 'Fresh',
|
|
'mixed' => 'Mixed freshness',
|
|
'missing_context' => 'Missing context',
|
|
default => filled($state) ? Str::headline(str_replace('_', ' ', (string) $state)) : 'Unknown freshness',
|
|
};
|
|
};
|
|
|
|
$redactionModeLabel = static function (?string $mode): string {
|
|
return match ($mode) {
|
|
'default_redacted', 'default-redacted' => 'Redacted support view',
|
|
default => filled($mode) ? Str::headline(str_replace('_', ' ', (string) $mode)) : 'Redacted support view',
|
|
};
|
|
};
|
|
|
|
$referenceTypeLabel = static function (?string $type): string {
|
|
return match ($type) {
|
|
'audit_log' => 'Audit event',
|
|
'environment_review' => 'Environment review',
|
|
'finding' => 'Finding',
|
|
'operation_run' => 'Operation',
|
|
'provider_connection' => 'Provider connection',
|
|
'review_pack' => 'Review pack',
|
|
'stored_report' => 'Stored report',
|
|
'tenant' => 'Environment',
|
|
default => filled($type) ? Str::headline(str_replace('_', ' ', (string) $type)) : 'Reference',
|
|
};
|
|
};
|
|
|
|
$referenceDescription = static function (array $reference) use ($availabilityLabel, $referenceTypeLabel): string {
|
|
$parts = [
|
|
$referenceTypeLabel(is_string($reference['type'] ?? null) ? (string) $reference['type'] : null),
|
|
$availabilityLabel(is_string($reference['availability'] ?? null) ? (string) $reference['availability'] : 'missing'),
|
|
];
|
|
|
|
if (is_string($reference['freshness_note'] ?? null) && trim((string) $reference['freshness_note']) !== '') {
|
|
$parts[] = (string) $reference['freshness_note'];
|
|
}
|
|
|
|
return implode(' - ', $parts);
|
|
};
|
|
|
|
$sectionObserved = static function (array $section, array $references): string {
|
|
if (is_string($section['freshness_note'] ?? null) && trim((string) $section['freshness_note']) !== '') {
|
|
return (string) $section['freshness_note'];
|
|
}
|
|
|
|
$availableCount = collect($references)
|
|
->filter(static fn (array $reference): bool => ($reference['availability'] ?? null) === 'available')
|
|
->count();
|
|
|
|
if ($availableCount > 0) {
|
|
return $availableCount === 1 ? '1 related reference observed.' : $availableCount.' related references observed.';
|
|
}
|
|
|
|
return 'No related record observed in this support context.';
|
|
};
|
|
@endphp
|
|
|
|
<div class="space-y-4">
|
|
<x-filament::section
|
|
:heading="data_get($summary, 'headline', data_get($bundle, 'headline', 'Support diagnostics'))"
|
|
:description="data_get($summary, 'dominant_issue', data_get($bundle, 'dominant_issue', 'No dominant issue available.'))"
|
|
>
|
|
<x-slot name="afterHeader">
|
|
<div class="flex flex-wrap gap-2">
|
|
<x-filament::badge color="gray" size="sm">
|
|
{{ $contextTypeLabel(data_get($context, 'type', data_get($bundle, 'context_type', 'tenant'))) }}
|
|
</x-filament::badge>
|
|
<x-filament::badge color="gray" size="sm">
|
|
{{ $freshnessStateLabel(data_get($summary, 'freshness_state', data_get($bundle, 'freshness_state', 'mixed'))) }}
|
|
</x-filament::badge>
|
|
<x-filament::badge color="warning" size="sm">
|
|
{{ $redactionModeLabel(data_get($redaction, 'mode', data_get($bundle, 'redaction_mode', 'default_redacted'))) }}
|
|
</x-filament::badge>
|
|
</div>
|
|
</x-slot>
|
|
|
|
<div class="space-y-4">
|
|
<p class="text-sm leading-6 text-gray-700 dark:text-gray-200">
|
|
Use this quick support context to start with the recommended first check before opening lower technical sections.
|
|
</p>
|
|
|
|
@if ($recommendedFirstCheck !== null)
|
|
@php
|
|
$firstCheckReference = is_array($recommendedFirstCheck['reference'] ?? null)
|
|
? $recommendedFirstCheck['reference']
|
|
: null;
|
|
$firstCheckReferenceLabel = $firstCheckReference['label'] ?? 'Reference unavailable';
|
|
$firstCheckReferenceUrl = is_string($firstCheckReference['url'] ?? null) && trim((string) $firstCheckReference['url']) !== ''
|
|
? (string) $firstCheckReference['url']
|
|
: null;
|
|
$firstCheckReferenceActionLabel = $firstCheckReference['action_label'] ?? ($firstCheckReferenceUrl ? 'Open' : 'Unavailable');
|
|
@endphp
|
|
|
|
<div class="space-y-3 border-t border-gray-200 pt-4 dark:border-white/10">
|
|
<div class="flex flex-wrap items-start justify-between gap-3">
|
|
<div class="space-y-1">
|
|
<h3 class="text-sm font-semibold text-gray-950 dark:text-white">
|
|
Recommended first check
|
|
</h3>
|
|
<p class="text-sm leading-6 text-gray-700 dark:text-gray-200">
|
|
{{ data_get($recommendedFirstCheck, 'body', 'Start with the highest-confidence support reference before inspecting lower sections.') }}
|
|
</p>
|
|
</div>
|
|
<x-filament::badge color="warning" size="sm">
|
|
{{ data_get($recommendedFirstCheck, 'label', 'Review source first') }}
|
|
</x-filament::badge>
|
|
</div>
|
|
|
|
@if ($firstCheckReference !== null)
|
|
<div class="flex flex-wrap items-center gap-2 text-sm">
|
|
<span class="font-medium text-gray-950 dark:text-white">
|
|
{{ $firstCheckReferenceLabel }}
|
|
</span>
|
|
|
|
@if ($firstCheckReferenceUrl)
|
|
<x-filament::link
|
|
:href="$firstCheckReferenceUrl"
|
|
rel="noopener noreferrer"
|
|
size="sm"
|
|
target="_blank"
|
|
>
|
|
{{ $firstCheckReferenceActionLabel }}
|
|
</x-filament::link>
|
|
@else
|
|
<x-filament::badge color="gray" size="sm">
|
|
{{ $firstCheckReferenceActionLabel }}
|
|
</x-filament::badge>
|
|
@endif
|
|
</div>
|
|
@endif
|
|
</div>
|
|
@endif
|
|
|
|
<dl class="grid grid-cols-1 gap-3 text-sm sm:grid-cols-2">
|
|
<div class="space-y-1">
|
|
<dt class="text-xs font-medium uppercase tracking-wide text-gray-500 dark:text-gray-400">Workspace</dt>
|
|
<dd class="text-gray-950 dark:text-white">{{ data_get($context, 'workspace_label', 'Workspace unavailable') }}</dd>
|
|
</div>
|
|
<div class="space-y-1">
|
|
<dt class="text-xs font-medium uppercase tracking-wide text-gray-500 dark:text-gray-400">Environment</dt>
|
|
<dd class="text-gray-950 dark:text-white">{{ data_get($context, 'tenant_label', 'Environment unavailable') }}</dd>
|
|
</div>
|
|
</dl>
|
|
</div>
|
|
</x-filament::section>
|
|
|
|
@if (is_array($bundle['contextual_help'] ?? null))
|
|
@include('filament.components.product-knowledge.contextual-help', ['help' => $bundle['contextual_help']])
|
|
@endif
|
|
|
|
@if ($notes !== [])
|
|
<div class="rounded-md border border-gray-200 bg-gray-50 px-4 py-3 dark:border-white/10 dark:bg-white/5">
|
|
<div class="flex flex-col gap-2 sm:flex-row sm:items-start sm:justify-between">
|
|
<div class="space-y-1">
|
|
<p class="text-xs font-medium uppercase tracking-wide text-gray-500 dark:text-gray-400">
|
|
Support scope
|
|
</p>
|
|
<p class="text-sm leading-6 text-gray-700 dark:text-gray-200">
|
|
Read-only, redacted support view. Restricted provider details are excluded.
|
|
</p>
|
|
</div>
|
|
|
|
@if ($contextNotes !== [])
|
|
<div class="flex flex-wrap gap-2 sm:justify-end">
|
|
@foreach ($contextNotes as $note)
|
|
<span class="inline-flex max-w-full rounded-md bg-white px-2 py-1 text-xs font-medium text-gray-600 ring-1 ring-gray-950/10 dark:bg-white/5 dark:text-gray-300 dark:ring-white/10">
|
|
{{ $note }}
|
|
</span>
|
|
@endforeach
|
|
</div>
|
|
@endif
|
|
</div>
|
|
</div>
|
|
@endif
|
|
|
|
<div class="space-y-3">
|
|
@foreach ($sections as $section)
|
|
@php
|
|
$references = is_array($section['references'] ?? null) ? $section['references'] : [];
|
|
$markers = is_array($section['redaction_markers'] ?? null) ? $section['redaction_markers'] : [];
|
|
$availability = is_string($section['availability'] ?? null) && trim((string) $section['availability']) !== ''
|
|
? (string) $section['availability']
|
|
: 'missing';
|
|
$sectionLabel = $section['label'] ?? $section['key'] ?? 'Section';
|
|
$sectionSummary = $section['summary'] ?? 'No summary available.';
|
|
$actionReference = collect($references)
|
|
->first(static fn (array $reference): bool => is_string($reference['url'] ?? null) && trim((string) $reference['url']) !== '');
|
|
$actionReference = is_array($actionReference)
|
|
? $actionReference
|
|
: (is_array($references[0] ?? null) ? $references[0] : null);
|
|
$sectionActionUrl = is_array($actionReference) && is_string($actionReference['url'] ?? null) && trim((string) $actionReference['url']) !== ''
|
|
? (string) $actionReference['url']
|
|
: null;
|
|
$sectionActionLabel = is_array($actionReference)
|
|
? (string) ($actionReference['action_label'] ?? ($sectionActionUrl ? 'Open' : 'No action available'))
|
|
: 'No action available';
|
|
$sectionObservedText = $sectionObserved($section, $references);
|
|
@endphp
|
|
|
|
<x-filament::section
|
|
:heading="$sectionLabel"
|
|
compact
|
|
>
|
|
<x-slot name="afterHeader">
|
|
<x-filament::badge :color="$availabilityColor($availability)" size="sm">
|
|
{{ $availabilityLabel($availability) }}
|
|
</x-filament::badge>
|
|
</x-slot>
|
|
|
|
<div class="space-y-3">
|
|
<dl class="grid grid-cols-1 gap-3 text-sm md:grid-cols-4">
|
|
<div class="space-y-1">
|
|
<dt class="text-xs font-medium uppercase tracking-wide text-gray-500 dark:text-gray-400">Status</dt>
|
|
<dd class="text-gray-950 dark:text-white">{{ $availabilityLabel($availability) }}</dd>
|
|
</div>
|
|
<div class="space-y-1 md:col-span-1">
|
|
<dt class="text-xs font-medium uppercase tracking-wide text-gray-500 dark:text-gray-400">Why relevant</dt>
|
|
<dd class="leading-6 text-gray-700 dark:text-gray-200">{{ $sectionSummary }}</dd>
|
|
</div>
|
|
<div class="space-y-1 md:col-span-1">
|
|
<dt class="text-xs font-medium uppercase tracking-wide text-gray-500 dark:text-gray-400">Observed</dt>
|
|
<dd class="leading-6 text-gray-700 dark:text-gray-200">{{ $sectionObservedText }}</dd>
|
|
</div>
|
|
<div class="space-y-1 md:col-span-1">
|
|
<dt class="text-xs font-medium uppercase tracking-wide text-gray-500 dark:text-gray-400">Action</dt>
|
|
<dd>
|
|
@if ($sectionActionUrl)
|
|
<x-filament::link
|
|
:href="$sectionActionUrl"
|
|
rel="noopener noreferrer"
|
|
size="sm"
|
|
target="_blank"
|
|
>
|
|
{{ $sectionActionLabel }}
|
|
</x-filament::link>
|
|
@else
|
|
<x-filament::badge color="gray" size="sm">
|
|
{{ $sectionActionLabel }}
|
|
</x-filament::badge>
|
|
@endif
|
|
</dd>
|
|
</div>
|
|
</dl>
|
|
|
|
@if ($references !== [])
|
|
<div class="divide-y divide-gray-200 border-t border-gray-200 dark:divide-white/10 dark:border-white/10">
|
|
@foreach ($references as $reference)
|
|
@php
|
|
$referenceLabel = $reference['label'] ?? 'Reference unavailable';
|
|
$referenceUrl = is_string($reference['url'] ?? null) && trim((string) $reference['url']) !== ''
|
|
? (string) $reference['url']
|
|
: null;
|
|
$referenceActionLabel = $reference['action_label'] ?? ($referenceUrl ? 'Open' : 'Unavailable');
|
|
@endphp
|
|
|
|
<div class="flex flex-wrap items-start justify-between gap-3 py-3">
|
|
<div class="space-y-1">
|
|
<p class="text-sm font-medium text-gray-950 dark:text-white">
|
|
{{ $referenceLabel }}
|
|
</p>
|
|
<p class="text-xs leading-5 text-gray-500 dark:text-gray-400">
|
|
{{ $referenceDescription($reference) }}
|
|
</p>
|
|
</div>
|
|
|
|
<div>
|
|
@if ($referenceUrl)
|
|
<x-filament::link
|
|
:href="$referenceUrl"
|
|
rel="noopener noreferrer"
|
|
size="sm"
|
|
target="_blank"
|
|
>
|
|
{{ $referenceActionLabel }}
|
|
</x-filament::link>
|
|
@else
|
|
<x-filament::badge color="gray" size="sm">
|
|
{{ $referenceActionLabel }}
|
|
</x-filament::badge>
|
|
@endif
|
|
</div>
|
|
</div>
|
|
@endforeach
|
|
</div>
|
|
@endif
|
|
|
|
@if ($markers !== [])
|
|
<div class="flex flex-wrap gap-2">
|
|
@foreach ($markers as $marker)
|
|
<x-filament::badge color="warning" size="sm">
|
|
{{ trim((string) (($marker['replacement_text'] ?? '[REDACTED]').' '.Str::of((string) ($marker['reason'] ?? 'redacted'))->replace('_', ' '))) }}
|
|
</x-filament::badge>
|
|
@endforeach
|
|
</div>
|
|
@endif
|
|
</div>
|
|
</x-filament::section>
|
|
@endforeach
|
|
</div>
|
|
</div>
|