TenantAtlas/app/Livewire/SettingsCatalogSettingsTable.php
2025-12-14 20:23:18 +01:00

126 lines
4.9 KiB
PHP

<?php
namespace App\Livewire;
use Filament\Actions\Action;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Table;
use Filament\Tables\TableComponent;
use Illuminate\Contracts\View\View;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Str;
class SettingsCatalogSettingsTable extends TableComponent
{
/**
* @var array<int, array<string, mixed>>
*/
public array $settingsRows = [];
public string $context = 'policy';
/**
* @param array<int, array<string, mixed>> $settingsRows
*/
public function mount(array $settingsRows = [], string $context = 'policy'): void
{
$this->settingsRows = $settingsRows;
$this->context = $context;
}
public function table(Table $table): Table
{
return $table
->queryStringIdentifier('settingsCatalog'.Str::studly($this->context))
->records(function (?string $search, int|string $page, int|string $recordsPerPage, ?string $sortColumn, ?string $sortDirection): LengthAwarePaginator {
$records = collect($this->settingsRows);
if (filled($search)) {
$needle = Str::lower($search);
$records = $records->filter(function (array $row) use ($needle): bool {
$haystack = implode(' ', [
(string) ($row['definition'] ?? ''),
(string) ($row['type'] ?? ''),
(string) ($row['value'] ?? ''),
(string) ($row['path'] ?? ''),
]);
return Str::contains(Str::lower($haystack), $needle);
});
}
if (filled($sortColumn)) {
$direction = Str::lower((string) ($sortDirection ?? 'asc')) === 'desc' ? 'desc' : 'asc';
$records = $records->sortBy(
fn (array $row) => (string) ($row[$sortColumn] ?? ''),
SORT_NATURAL | SORT_FLAG_CASE,
$direction === 'desc'
);
}
$perPage = is_numeric($recordsPerPage) ? max(1, (int) $recordsPerPage) : 25;
$currentPage = is_numeric($page) ? max(1, (int) $page) : 1;
$total = $records->count();
$items = $records->forPage($currentPage, $perPage)->values();
return new LengthAwarePaginator(
$items,
$total,
$perPage,
$currentPage
);
})
->paginated([25, 50, 100])
->defaultPaginationPageOption(25)
->searchable()
->searchPlaceholder('Search definition/value…')
->striped()
->deferLoading(! app()->runningUnitTests())
->columns([
TextColumn::make('definition')
->label('Definition')
->limit(60)
->tooltip(fn (?string $state): ?string => filled($state) ? $state : null)
->searchable()
->extraAttributes(['class' => 'font-mono text-xs']),
TextColumn::make('type')
->label('Type')
->limit(50)
->tooltip(fn (?string $state): ?string => filled($state) ? $state : null)
->toggleable()
->extraAttributes(['class' => 'font-mono text-xs']),
TextColumn::make('value')
->label('Value')
->badge(fn (?string $state): bool => $state === '(group)')
->color(fn (?string $state): string => $state === '(group)' ? 'gray' : 'primary')
->limit(60)
->tooltip(fn (?string $state): ?string => filled($state) ? $state : null)
->searchable(),
TextColumn::make('path')
->label('Path')
->limit(80)
->tooltip(fn (?string $state): ?string => filled($state) ? $state : null)
->toggleable(isToggledHiddenByDefault: true)
->extraAttributes(['class' => 'font-mono text-xs']),
])
->actions([
Action::make('details')
->label('Details')
->icon('heroicon-m-eye')
->slideOver()
->modalSubmitAction(false)
->modalCancelActionLabel('Close')
->modalHeading(fn (array $record): string => (string) ($record['definition'] ?? 'Setting details'))
->modalContent(fn (array $record): View => view('filament.modals.settings-catalog-setting-details', ['record' => $record])),
]);
}
public function render(): View
{
return view('livewire.settings-catalog-settings-table');
}
}