TenantAtlas/resources/views/filament/infolists/entries/policy-settings-standard.blade.php

339 lines
16 KiB
PHP

@php
use Illuminate\Support\Str;
// Extract state from Filament ViewEntry
$state = $getState();
$status = $state['status'] ?? 'success';
$warnings = $state['warnings'] ?? [];
$settings = $state['settings'] ?? [];
$settingsTable = $state['settings_table'] ?? null;
$policyType = $state['policy_type'] ?? null;
$stringifyValue = function (mixed $value): string {
if (is_null($value)) {
return 'N/A';
}
if (is_bool($value)) {
return $value ? 'Enabled' : 'Disabled';
}
if (is_scalar($value)) {
return (string) $value;
}
if (is_array($value)) {
$encoded = json_encode($value, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
return is_string($encoded) ? $encoded : 'N/A';
}
if (is_object($value)) {
if (method_exists($value, '__toString')) {
return (string) $value;
}
$encoded = json_encode((array) $value, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
return is_string($encoded) ? $encoded : 'N/A';
}
return 'N/A';
};
$shouldRenderBadges = function (mixed $value): bool {
if (! is_array($value) || $value === []) {
return false;
}
if (! array_is_list($value)) {
return false;
}
foreach ($value as $item) {
if (! is_scalar($item) && ! is_null($item)) {
return false;
}
}
return true;
};
$asEnabledDisabledBadgeValue = function (mixed $value): ?bool {
if (is_bool($value)) {
return $value;
}
if (! is_string($value)) {
return null;
}
$normalized = strtolower(trim($value));
return match ($normalized) {
'enabled', 'true', 'yes', '1' => true,
'disabled', 'false', 'no', '0' => false,
default => null,
};
};
@endphp
<div class="space-y-4">
{{-- Warnings --}}
@if(!empty($warnings))
<x-filament::section>
<div class="space-y-2">
@foreach($warnings as $warning)
<div class="flex items-start gap-2 text-sm text-warning-600 dark:text-warning-400">
<svg class="w-5 h-5 flex-shrink-0 mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"/>
</svg>
<span>{{ $warning }}</span>
</div>
@endforeach
</div>
</x-filament::section>
@endif
{{-- Settings Table (for Settings Catalog legacy format) --}}
@if($settingsTable && !empty($settingsTable['rows']))
<x-filament::section
:heading="$settingsTable['title'] ?? 'Settings'"
:description="$settingsTable['description'] ?? null"
>
<x-slot name="headerEnd">
<span class="text-sm text-gray-500 dark:text-gray-400">
{{ count($settingsTable['rows']) }} {{ Str::plural('setting', count($settingsTable['rows'])) }}
</span>
</x-slot>
<div class="divide-y divide-gray-200 dark:divide-gray-700">
@foreach($settingsTable['rows'] as $row)
<div class="py-3 sm:grid sm:grid-cols-3 sm:gap-4">
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">
{{ $row['definition'] ?? $row['label'] ?? $row['path'] ?? 'Setting' }}
</dt>
<dd class="mt-1 sm:mt-0 sm:col-span-2">
<span class="text-sm text-gray-900 dark:text-white">
@php
$badgeValue = $asEnabledDisabledBadgeValue($row['value'] ?? null);
@endphp
@if(! is_null($badgeValue))
<x-filament::badge :color="$badgeValue ? 'success' : 'gray'" size="sm">
{{ $badgeValue ? 'Enabled' : 'Disabled' }}
</x-filament::badge>
@elseif(is_numeric($row['value']))
<span class="font-mono font-semibold">{{ $row['value'] }}</span>
@else
{{ $row['value'] ?? 'N/A' }}
@endif
</span>
</dd>
</div>
@endforeach
</div>
</x-filament::section>
@endif
{{-- Settings Blocks (for OMA Settings, Key/Value pairs, etc.) --}}
@foreach($settings as $block)
@php
$blockType = is_array($block) ? ($block['type'] ?? null) : null;
@endphp
@if($blockType === 'table')
<x-filament::section
:heading="$block['title'] ?? 'Settings'"
collapsible
>
<x-slot name="headerEnd">
<span class="text-sm text-gray-500 dark:text-gray-400">
{{ count($block['rows'] ?? []) }} {{ Str::plural('item', count($block['rows'] ?? [])) }}
</span>
</x-slot>
<div class="divide-y divide-gray-200 dark:divide-gray-700">
@foreach($block['rows'] ?? [] as $row)
<div class="py-3 sm:grid sm:grid-cols-3 sm:gap-4">
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400 break-words">
{{ $row['label'] ?? $row['path'] ?? 'Setting' }}
@if(!empty($row['description']))
<p class="text-xs text-gray-400 mt-0.5">{{ Str::limit($row['description'], 80) }}</p>
@endif
</dt>
<dd class="mt-1 sm:mt-0 sm:col-span-2">
@php
$badgeValue = $asEnabledDisabledBadgeValue($row['value'] ?? null);
@endphp
@if(! is_null($badgeValue))
<x-filament::badge :color="$badgeValue ? 'success' : 'gray'" size="sm">
{{ $badgeValue ? 'Enabled' : 'Disabled' }}
</x-filament::badge>
@elseif(is_numeric($row['value']))
<span class="font-mono text-sm font-semibold text-gray-900 dark:text-white">
{{ $row['value'] }}
</span>
@elseif($shouldRenderBadges($row['value'] ?? null))
<div class="flex flex-wrap gap-1.5">
@foreach(($row['value'] ?? []) as $item)
<x-filament::badge color="gray" size="sm">
{{ is_bool($item) ? ($item ? 'Enabled' : 'Disabled') : (string) $item }}
</x-filament::badge>
@endforeach
</div>
@else
<span class="text-sm text-gray-900 dark:text-white break-words">
{{ Str::limit($stringifyValue($row['value'] ?? null), 200) }}
</span>
@endif
</dd>
</div>
@endforeach
</div>
</x-filament::section>
@elseif($blockType === 'keyValue')
<x-filament::section
:heading="$block['title'] ?? 'Settings'"
collapsible
>
<x-slot name="headerEnd">
<span class="text-sm text-gray-500 dark:text-gray-400">
{{ count($block['entries'] ?? []) }} {{ Str::plural('entry', count($block['entries'] ?? [])) }}
</span>
</x-slot>
<div class="divide-y divide-gray-200 dark:divide-gray-700">
@foreach($block['entries'] ?? [] as $entry)
<div class="py-3 sm:grid sm:grid-cols-3 sm:gap-4">
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400">
{{ $entry['key'] }}
</dt>
<dd class="mt-1 sm:mt-0 sm:col-span-2">
@php
$rawValue = $entry['value'] ?? null;
$isScriptContent = in_array($entry['key'] ?? null, ['scriptContent', 'detectionScriptContent', 'remediationScriptContent'], true)
&& (bool) config('tenantpilot.display.show_script_content', false);
$badgeValue = $asEnabledDisabledBadgeValue($rawValue);
@endphp
@if($isScriptContent)
@php
$code = is_string($rawValue) ? $rawValue : $stringifyValue($rawValue);
$firstLine = strtok($code, "\n") ?: '';
$grammar = 'powershell';
if ($policyType === 'deviceShellScript') {
$shebang = trim($firstLine);
if (str_starts_with($shebang, '#!')) {
if (str_contains($shebang, 'zsh')) {
$grammar = 'zsh';
} elseif (str_contains($shebang, 'bash')) {
$grammar = 'bash';
} else {
$grammar = 'sh';
}
} else {
$grammar = 'sh';
}
} elseif ($policyType === 'deviceManagementScript' || $policyType === 'deviceHealthScript') {
$grammar = 'powershell';
}
$highlightedHtml = null;
if (class_exists(\Torchlight\Engine\Engine::class)) {
try {
$highlightedHtml = (new \Torchlight\Engine\Engine())->codeToHtml(
code: $code,
grammar: $grammar,
theme: [
'light' => 'github-light',
'dark' => 'github-dark',
],
withGutter: false,
withWrapper: true,
);
} catch (\Throwable $e) {
$highlightedHtml = null;
}
}
@endphp
<div x-data="{ open: false }" class="space-y-2">
<div class="flex items-center gap-2">
<x-filament::button
size="xs"
color="gray"
type="button"
x-on:click="open = !open"
>
<span x-show="!open" x-cloak>Show</span>
<span x-show="open" x-cloak>Hide</span>
</x-filament::button>
<span class="text-xs text-gray-500 dark:text-gray-400">
{{ number_format(Str::length($code)) }} chars
</span>
</div>
<div x-show="open" x-cloak>
@if (is_string($highlightedHtml) && $highlightedHtml !== '')
@once
@include('filament.partials.torchlight-dark-overrides')
@endonce
<div class="overflow-x-auto">{!! $highlightedHtml !!}</div>
@else
<pre class="text-xs font-mono text-gray-900 dark:text-white whitespace-pre-wrap break-words">{{ $code }}</pre>
@endif
</div>
</div>
@elseif($shouldRenderBadges($rawValue))
<div class="flex flex-wrap gap-1.5">
@foreach(($rawValue ?? []) as $item)
<x-filament::badge color="gray" size="sm">
{{ is_bool($item) ? ($item ? 'Enabled' : 'Disabled') : (string) $item }}
</x-filament::badge>
@endforeach
</div>
@elseif(! is_null($badgeValue))
<x-filament::badge :color="$badgeValue ? 'success' : 'gray'" size="sm">
{{ $badgeValue ? 'Enabled' : 'Disabled' }}
</x-filament::badge>
@else
<span class="text-sm text-gray-900 dark:text-white break-words">
{{ Str::limit($stringifyValue($rawValue), 200) }}
</span>
@endif
</dd>
</div>
@endforeach
</div>
</x-filament::section>
@endif
@endforeach
{{-- Empty state --}}
@if(empty($settings) && (!$settingsTable || empty($settingsTable['rows'])))
<div class="text-center py-12">
<svg class="mx-auto h-12 w-12 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/>
</svg>
<p class="mt-4 text-sm text-gray-500 dark:text-gray-400">
No settings data available
</p>
<p class="mt-1 text-xs text-gray-400 dark:text-gray-500">
This policy may not contain settings, or they are in an unsupported format
</p>
</div>
@endif
</div>