columns([ Tables\Columns\TextColumn::make('policy.display_name') ->label('Policy') ->sortable() ->searchable(), Tables\Columns\TextColumn::make('policy_type') ->label('Type') ->badge() ->formatStateUsing(fn (?string $state) => static::typeMeta($state)['label'] ?? $state), Tables\Columns\TextColumn::make('restore_mode') ->label('Restore') ->badge() ->state(fn (BackupItem $record) => static::typeMeta($record->policy_type)['restore'] ?? 'enabled') ->color(fn (?string $state) => $state === 'preview-only' ? 'warning' : 'success'), Tables\Columns\TextColumn::make('risk') ->label('Risk') ->badge() ->state(fn (BackupItem $record) => static::typeMeta($record->policy_type)['risk'] ?? 'n/a') ->color(fn (?string $state) => str_contains((string) $state, 'high') ? 'danger' : 'gray'), Tables\Columns\TextColumn::make('policy_identifier') ->label('Policy ID') ->copyable(), Tables\Columns\TextColumn::make('platform')->badge(), Tables\Columns\TextColumn::make('captured_at')->dateTime(), Tables\Columns\TextColumn::make('created_at')->since(), ]) ->filters([]) ->headerActions([ Actions\Action::make('addPolicies') ->label('Policies hinzufügen') ->icon('heroicon-o-plus') ->form([ Forms\Components\Select::make('policy_ids') ->label('Policies') ->multiple() ->required() ->searchable() ->options(function (RelationManager $livewire) { $backupSet = $livewire->getOwnerRecord(); $tenantId = $backupSet?->tenant_id ?? Tenant::current()->getKey(); $existing = $backupSet ? $backupSet->items()->pluck('policy_id')->filter()->all() : []; return Policy::query() ->where('tenant_id', $tenantId) ->when($existing, fn (Builder $query) => $query->whereNotIn('id', $existing)) ->orderBy('display_name') ->pluck('display_name', 'id'); }), ]) ->action(function (array $data, BackupService $service) { if (empty($data['policy_ids'])) { Notification::make() ->title('No policies selected') ->warning() ->send(); return; } $backupSet = $this->getOwnerRecord(); $tenant = $backupSet?->tenant ?? Tenant::current(); $service->addPoliciesToSet( tenant: $tenant, backupSet: $backupSet, policyIds: $data['policy_ids'], actorEmail: auth()->user()?->email, actorName: auth()->user()?->name, ); Notification::make() ->title('Policies added to backup') ->success() ->send(); }), ]) ->actions([ Actions\ViewAction::make() ->label('View policy') ->url(fn ($record) => $record->policy_id ? PolicyResource::getUrl('view', ['record' => $record->policy_id]) : null) ->hidden(fn ($record) => ! $record->policy_id) ->openUrlInNewTab(true), Actions\Action::make('remove') ->label('Remove') ->color('danger') ->icon('heroicon-o-x-mark') ->requiresConfirmation() ->action(function (BackupItem $record, AuditLogger $auditLogger) { $record->delete(); if ($record->backupSet) { $record->backupSet->update([ 'item_count' => $record->backupSet->items()->count(), ]); } if ($record->tenant) { $auditLogger->log( tenant: $record->tenant, action: 'backup.item_removed', resourceType: 'backup_set', resourceId: (string) $record->backup_set_id, status: 'success', context: ['metadata' => ['policy_id' => $record->policy_id]] ); } Notification::make() ->title('Policy removed from backup') ->success() ->send(); }), ]) ->bulkActions([]); } /** * @return array{label:?string,category:?string,restore:?string,risk:?string}|array */ private static function typeMeta(?string $type): array { if ($type === null) { return []; } return collect(config('tenantpilot.supported_policy_types', [])) ->firstWhere('type', $type) ?? []; } }