TenantAtlas/apps/platform/app/Filament/Resources/ReviewPackResource/Pages/ViewReviewPack.php
ahmido b7907bd69d feat: add report profile and disclosure policy to rendered review reports (#428)
Implementing report profiles and disclosure policy as per spec 357.

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #428
2026-06-06 09:41:19 +00:00

175 lines
7.7 KiB
PHP

<?php
namespace App\Filament\Resources\ReviewPackResource\Pages;
use App\Filament\Pages\Reviews\CustomerReviewWorkspace;
use App\Filament\Resources\ReviewPackResource;
use App\Models\EnvironmentReview;
use App\Models\ReviewPack;
use App\Services\ReviewPackService;
use App\Support\Auth\Capabilities;
use App\Support\Rbac\UiEnforcement;
use App\Support\ReviewPacks\ReportProfileRegistry;
use App\Support\ReviewPacks\ReviewPackOutputResolutionGuidance;
use App\Support\ReviewPackStatus;
use Filament\Actions;
use Filament\Forms\Components\Toggle;
use Filament\Resources\Pages\ViewRecord;
use Filament\Schemas\Components\Section;
class ViewReviewPack extends ViewRecord
{
protected static string $resource = ReviewPackResource::class;
protected function getHeaderActions(): array
{
if (ReviewPackResource::isCustomerWorkspaceFlow()) {
return [
$this->openRenderedReportAction([
'source_surface' => CustomerReviewWorkspace::SOURCE_SURFACE,
CustomerReviewWorkspace::DETAIL_CONTEXT_QUERY_KEY => 1,
'review_id' => $this->record->environment_review_id,
'tenant_filter_id' => request()->query('tenant_filter_id'),
'interpretation_version' => $this->record->environmentReview?->controlInterpretationVersion(),
], 'primary'),
Actions\Action::make('download')
->label(fn (): string => ReviewPackResource::downloadActionLabelFor($this->record))
->icon('heroicon-o-arrow-down-tray')
->color('gray')
->visible(fn (): bool => $this->record->status === ReviewPackStatus::Ready->value)
->url(fn (): string => app(ReviewPackService::class)->generateDownloadUrl($this->record, [
'source_surface' => CustomerReviewWorkspace::SOURCE_SURFACE,
]))
->openUrlInNewTab(),
];
}
$regenerateAction = UiEnforcement::forAction(
Actions\Action::make('regenerate')
->label('Regenerate')
->icon('heroicon-o-arrow-path')
->color('primary')
->disabled(fn (): bool => ReviewPackResource::reviewPackGenerationBlocked($this->record->tenant))
->requiresConfirmation()
->modalDescription('This will generate a new review pack with the same options. The current pack will remain available until it expires.')
->action(function (array $data): void {
/** @var ReviewPack $record */
$record = $this->record;
$options = array_merge($record->options ?? [], [
'include_pii' => (bool) ($data['include_pii'] ?? ($record->options['include_pii'] ?? true)),
'include_operations' => (bool) ($data['include_operations'] ?? ($record->options['include_operations'] ?? true)),
]);
ReviewPackResource::executeGeneration($options);
})
->form(function (): array {
/** @var ReviewPack $record */
$record = $this->record;
$currentOptions = $record->options ?? [];
return [
Section::make('Pack options')
->schema([
Toggle::make('include_pii')
->label('Include PII')
->helperText('Include personally identifiable information in the export.')
->default((bool) ($currentOptions['include_pii'] ?? true)),
Toggle::make('include_operations')
->label('Include operations')
->helperText('Include recent operation history in the export.')
->default((bool) ($currentOptions['include_operations'] ?? true)),
]),
];
})
)
->requireCapability(Capabilities::REVIEW_PACK_MANAGE)
->preserveDisabled()
->apply();
$regenerateAction->tooltip(fn (): ?string => ReviewPackResource::reviewPackGenerationActionTooltip($this->record->tenant));
return [
$this->openRenderedReportAction([
'source_surface' => 'review_pack',
'review_id' => $this->record->environment_review_id,
'tenant_filter_id' => request()->query('tenant_filter_id'),
'interpretation_version' => $this->record->environmentReview?->controlInterpretationVersion(),
]),
Actions\Action::make('download')
->label(fn (): string => ReviewPackResource::downloadActionLabelFor($this->record))
->icon('heroicon-o-arrow-down-tray')
->color('gray')
->visible(fn (): bool => $this->record->status === ReviewPackStatus::Ready->value)
->url(fn (): string => app(ReviewPackService::class)->generateDownloadUrl($this->record))
->openUrlInNewTab(),
$regenerateAction,
];
}
/**
* @param array<string, scalar|null> $parameters
*/
private function openRenderedReportAction(array $parameters = [], string $color = 'primary'): Actions\Action
{
return Actions\Action::make('open_rendered_report')
->label(fn (): string => \App\Filament\Resources\EnvironmentReviewResource::renderedReportActionLabelFor($this->record->environmentReview))
->icon('heroicon-o-document-text')
->color($color)
->visible(fn (): bool => $this->canOpenRenderedReport())
->url(fn (): string => app(ReviewPackService::class)->generateRenderedReportUrl(
$this->record,
$this->renderedReportParameters($parameters),
))
->openUrlInNewTab();
}
/**
* @param array<string, scalar|null> $parameters
* @return array<string, scalar|null>
*/
private function renderedReportParameters(array $parameters): array
{
$parameters = array_filter($parameters, static fn (mixed $value): bool => $value !== null && $value !== '');
$review = $this->record->environmentReview;
if (! $review instanceof EnvironmentReview) {
return $parameters;
}
if (! array_key_exists(ReportProfileRegistry::QUERY_PARAMETER, $parameters)) {
$guidance = ReviewPackOutputResolutionGuidance::fromReadiness(
ReviewPackOutputResolutionGuidance::readinessForReview($review),
);
$parameters[ReportProfileRegistry::QUERY_PARAMETER] = ReportProfileRegistry::defaultForRenderedReportState(
(string) ($guidance['state'] ?? ReviewPackOutputResolutionGuidance::STATE_UNKNOWN),
array_key_exists(CustomerReviewWorkspace::DETAIL_CONTEXT_QUERY_KEY, $parameters),
);
}
return $parameters;
}
private function canOpenRenderedReport(): bool
{
/** @var ReviewPack $record */
$record = $this->record;
if ($record->status !== ReviewPackStatus::Ready->value) {
return false;
}
if ($record->expires_at !== null && $record->expires_at->isPast()) {
return false;
}
if (! $record->environmentReview instanceof \App\Models\EnvironmentReview) {
return false;
}
return (int) ($record->environmentReview->current_export_review_pack_id ?? 0) === (int) $record->getKey();
}
}