Implementing report profiles and disclosure policy as per spec 357. Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #428
175 lines
7.7 KiB
PHP
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();
|
|
}
|
|
}
|