label('Acknowledge all matching') ->icon('heroicon-o-check') ->color('gray') ->requiresConfirmation() ->visible(fn (): bool => $this->getStatusFilterValue() === Finding::STATUS_NEW) ->modalDescription(function (): string { $count = $this->getAllMatchingCount(); return "You are about to acknowledge {$count} finding".($count === 1 ? '' : 's').' matching the current filters.'; }) ->form(function (): array { $count = $this->getAllMatchingCount(); if ($count <= 100) { return []; } return [ TextInput::make('confirmation') ->label('Type ACKNOWLEDGE to confirm') ->required() ->in(['ACKNOWLEDGE']) ->validationMessages([ 'in' => 'Please type ACKNOWLEDGE to confirm.', ]), ]; }) ->action(function (array $data): void { $query = $this->buildAllMatchingQuery(); $count = (clone $query)->count(); if ($count === 0) { Notification::make() ->title('No matching findings') ->body('There are no new findings matching the current filters.') ->warning() ->send(); return; } $updated = $query->update([ 'status' => Finding::STATUS_ACKNOWLEDGED, 'acknowledged_at' => now(), 'acknowledged_by_user_id' => auth()->id(), ]); $this->deselectAllTableRecords(); $this->resetPage(); Notification::make() ->title('Bulk acknowledge completed') ->body("Acknowledged {$updated} finding".($updated === 1 ? '' : 's').'.') ->success() ->send(); }) ) ->preserveVisibility() ->requireCapability(Capabilities::TENANT_FINDINGS_ACKNOWLEDGE) ->tooltip(UiTooltips::INSUFFICIENT_PERMISSION) ->apply(), ]; } protected function buildAllMatchingQuery(): Builder { $query = Finding::query(); $tenantId = \Filament\Facades\Filament::getTenant()?->getKey(); if (! is_numeric($tenantId)) { return $query->whereRaw('1 = 0'); } $query->where('tenant_id', (int) $tenantId); $query->where('status', Finding::STATUS_NEW); $findingType = $this->getFindingTypeFilterValue(); if (is_string($findingType) && $findingType !== '') { $query->where('finding_type', $findingType); } $scopeKeyState = $this->getTableFilterState('scope_key') ?? []; $scopeKey = Arr::get($scopeKeyState, 'scope_key'); if (is_string($scopeKey) && $scopeKey !== '') { $query->where('scope_key', $scopeKey); } $runIdsState = $this->getTableFilterState('run_ids') ?? []; $baselineRunId = Arr::get($runIdsState, 'baseline_run_id'); if (is_numeric($baselineRunId)) { $query->where('baseline_run_id', (int) $baselineRunId); } $currentRunId = Arr::get($runIdsState, 'current_run_id'); if (is_numeric($currentRunId)) { $query->where('current_run_id', (int) $currentRunId); } return $query; } protected function getAllMatchingCount(): int { return (int) $this->buildAllMatchingQuery()->count(); } protected function getStatusFilterValue(): string { $state = $this->getTableFilterState('status') ?? []; $value = Arr::get($state, 'value'); return is_string($value) && $value !== '' ? $value : Finding::STATUS_NEW; } protected function getFindingTypeFilterValue(): string { $state = $this->getTableFilterState('finding_type') ?? []; $value = Arr::get($state, 'value'); return is_string($value) && $value !== '' ? $value : Finding::FINDING_TYPE_DRIFT; } }