TenantAtlas/resources/views/filament/infolists/entries/normalized-diff.blade.php
2025-12-29 03:04:45 +01:00

170 lines
8.6 KiB
PHP

@php
$diff = $getState() ?? ['summary' => [], 'added' => [], 'removed' => [], 'changed' => []];
$summary = $diff['summary'] ?? [];
$groupByBlock = static function (array $items): array {
$groups = [];
foreach ($items as $path => $value) {
if (! is_string($path) || $path === '') {
continue;
}
$parts = explode(' > ', $path, 2);
if (count($parts) === 2) {
[$group, $label] = $parts;
} else {
$group = 'Other';
$label = $path;
}
$groups[$group][$label] = $value;
}
ksort($groups);
return $groups;
};
$stringify = static function (mixed $value): string {
if ($value === null) {
return '—';
}
if (is_bool($value)) {
return $value ? 'Enabled' : 'Disabled';
}
if (is_scalar($value)) {
return (string) $value;
}
return json_encode($value, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE) ?: '';
};
$isExpandable = static function (mixed $value): bool {
if (is_array($value)) {
return true;
}
return is_string($value) && strlen($value) > 160;
};
@endphp
<div class="space-y-4">
<x-filament::section
heading="Normalized diff"
:description="$summary['message'] ?? sprintf('%d added, %d removed, %d changed', $summary['added'] ?? 0, $summary['removed'] ?? 0, $summary['changed'] ?? 0)"
>
<div class="flex flex-wrap gap-2">
<x-filament::badge color="success">
{{ (int) ($summary['added'] ?? 0) }} added
</x-filament::badge>
<x-filament::badge color="danger">
{{ (int) ($summary['removed'] ?? 0) }} removed
</x-filament::badge>
<x-filament::badge color="warning">
{{ (int) ($summary['changed'] ?? 0) }} changed
</x-filament::badge>
</div>
</x-filament::section>
@foreach (['changed' => ['label' => 'Changed', 'collapsed' => false], 'added' => ['label' => 'Added', 'collapsed' => true], 'removed' => ['label' => 'Removed', 'collapsed' => true]] as $key => $meta)
@php
$items = $diff[$key] ?? [];
$groups = $groupByBlock(is_array($items) ? $items : []);
@endphp
@if ($groups !== [])
<x-filament::section
:heading="$meta['label']"
collapsible
:collapsed="$meta['collapsed']"
>
<div class="space-y-6">
@foreach ($groups as $group => $groupItems)
<div>
<div class="flex items-center justify-between">
<div class="text-sm font-medium text-gray-900 dark:text-white">
{{ $group }}
</div>
<x-filament::badge size="sm" color="gray">
{{ count($groupItems) }}
</x-filament::badge>
</div>
<div class="mt-2 divide-y divide-gray-200 rounded-lg border border-gray-200 dark:divide-white/10 dark:border-white/10">
@foreach ($groupItems as $name => $value)
<div class="px-4 py-3">
@if ($key === 'changed' && is_array($value) && array_key_exists('from', $value) && array_key_exists('to', $value))
@php
$from = $value['from'];
$to = $value['to'];
$fromText = $stringify($from);
$toText = $stringify($to);
@endphp
<div class="grid grid-cols-1 gap-2 sm:grid-cols-3">
<div class="text-sm font-medium text-gray-900 dark:text-white">
{{ (string) $name }}
</div>
<div class="text-sm text-gray-600 dark:text-gray-300">
<span class="text-xs font-semibold uppercase tracking-wide text-gray-500 dark:text-gray-400">From</span>
@if ($isExpandable($from))
<details class="mt-1">
<summary class="cursor-pointer text-sm text-gray-700 dark:text-gray-200">
View
</summary>
<pre class="mt-2 overflow-x-auto text-xs text-gray-800 dark:text-gray-200">{{ $fromText }}</pre>
</details>
@else
<div class="mt-1">{{ $fromText }}</div>
@endif
</div>
<div class="text-sm text-gray-600 dark:text-gray-300">
<span class="text-xs font-semibold uppercase tracking-wide text-gray-500 dark:text-gray-400">To</span>
@if ($isExpandable($to))
<details class="mt-1">
<summary class="cursor-pointer text-sm text-gray-700 dark:text-gray-200">
View
</summary>
<pre class="mt-2 overflow-x-auto text-xs text-gray-800 dark:text-gray-200">{{ $toText }}</pre>
</details>
@else
<div class="mt-1">{{ $toText }}</div>
@endif
</div>
</div>
@else
@php
$text = $stringify($value);
@endphp
<div class="flex flex-col gap-2 sm:flex-row sm:items-start sm:justify-between">
<div class="text-sm font-medium text-gray-900 dark:text-white">
{{ (string) $name }}
</div>
<div class="text-sm text-gray-700 dark:text-gray-200 sm:max-w-[70%]">
@if ($isExpandable($value))
<details>
<summary class="cursor-pointer text-sm text-gray-700 dark:text-gray-200">
View
</summary>
<pre class="mt-2 overflow-x-auto text-xs text-gray-800 dark:text-gray-200">{{ $text }}</pre>
</details>
@else
<div class="break-words">{{ $text }}</div>
@endif
</div>
</div>
@endif
</div>
@endforeach
</div>
</div>
@endforeach
</div>
</x-filament::section>
@endif
@endforeach
</div>