$arguments * @param array $context */ public function mountAction(string $name, array $arguments = [], array $context = []): mixed { if (($context['table'] ?? false) === true && $name === 'view' && filled($context['recordKey'] ?? null)) { $this->resolveOwnerScopedOperationRun($context['recordKey']); } return parent::mountAction($name, $arguments, $context); } public static function actionSurfaceDeclaration(): ActionSurfaceDeclaration { return ActionSurfaceDeclaration::forRelationManager(ActionSurfaceProfile::RelationManager) ->exempt(ActionSurfaceSlot::ListHeader, 'Executions relation list has no header actions.') ->satisfy(ActionSurfaceSlot::InspectAffordance, ActionSurfaceInspectAffordance::ViewAction->value) ->exempt(ActionSurfaceSlot::ListRowMoreMenu, 'Single primary row action is exposed, so no row menu is needed.') ->exempt(ActionSurfaceSlot::ListBulkMoreGroup, 'Bulk actions are intentionally omitted for operation run safety.') ->exempt(ActionSurfaceSlot::ListEmptyState, 'No empty-state actions are exposed in this embedded relation manager.'); } public function table(Table $table): Table { return $table ->modifyQueryUsing(fn (Builder $query) => $query->where('tenant_id', Tenant::currentOrFail()->getKey())) ->defaultSort('created_at', 'desc') ->paginated(\App\Support\Filament\TablePaginationProfiles::relationManager()) ->columns([ Tables\Columns\TextColumn::make('created_at') ->label('Enqueued') ->dateTime() ->sortable(), Tables\Columns\TextColumn::make('type') ->label('Type') ->formatStateUsing(Closure::fromCallable([self::class, 'formatOperationType'])), Tables\Columns\TextColumn::make('status') ->badge() ->formatStateUsing(BadgeRenderer::label(BadgeDomain::OperationRunStatus)) ->color(BadgeRenderer::color(BadgeDomain::OperationRunStatus)) ->icon(BadgeRenderer::icon(BadgeDomain::OperationRunStatus)) ->iconColor(BadgeRenderer::iconColor(BadgeDomain::OperationRunStatus)), Tables\Columns\TextColumn::make('outcome') ->badge() ->formatStateUsing(BadgeRenderer::label(BadgeDomain::OperationRunOutcome)) ->color(BadgeRenderer::color(BadgeDomain::OperationRunOutcome)) ->icon(BadgeRenderer::icon(BadgeDomain::OperationRunOutcome)) ->iconColor(BadgeRenderer::iconColor(BadgeDomain::OperationRunOutcome)), Tables\Columns\TextColumn::make('counts') ->label('Counts') ->getStateUsing(function (OperationRun $record): string { $counts = is_array($record->summary_counts) ? $record->summary_counts : []; $total = (int) ($counts['total'] ?? 0); $succeeded = (int) ($counts['succeeded'] ?? 0); $failed = (int) ($counts['failed'] ?? 0); if ($total === 0 && $succeeded === 0 && $failed === 0) { return '—'; } return sprintf('%d/%d (%d failed)', $succeeded, $total, $failed); }), ]) ->filters([]) ->headerActions([]) ->actions([ Actions\Action::make('view') ->label('View') ->icon('heroicon-o-eye') ->url(function (OperationRun $record): string { $record = $this->resolveOwnerScopedOperationRun($record); $tenant = Tenant::currentOrFail(); return OperationRunLinks::view($record, $tenant); }) ->openUrlInNewTab(true), ]) ->bulkActions([]) ->emptyStateHeading('No schedule runs yet') ->emptyStateDescription('Operation history will appear here after this schedule has been enqueued.'); } private function resolveOwnerScopedOperationRun(mixed $record): OperationRun { $recordId = $record instanceof OperationRun ? (int) $record->getKey() : (is_numeric($record) ? (int) $record : 0); if ($recordId <= 0) { abort(404); } $resolvedRecord = $this->getOwnerRecord() ->operationRuns() ->where('tenant_id', Tenant::currentOrFail()->getKey()) ->whereKey($recordId) ->first(); if (! $resolvedRecord instanceof OperationRun) { abort(404); } return $resolvedRecord; } public static function formatOperationType(?string $state): string { return OperationCatalog::label($state); } }