TenantAtlas/apps/platform/app/Filament/Resources/ReviewPackResource/Pages/ViewReviewPack.php
Ahmed Darrazi 54f81d4a50
Some checks failed
PR Fast Feedback / fast-feedback (pull_request) Failing after 2m1s
feat: review pack pdf and html renderer v1 (spec 356)
Implemented the first version of the PDF and HTML renderer for review packs. Added ReviewPackRenderedReportController and related blade views to render reports. Updated EnvironmentReviewResource, ReviewPackResource, ReviewPackService, and routing. Added new tests for the renderer and download actions, and updated UI documentation.
2026-06-05 22:38:10 +02:00

145 lines
6.5 KiB
PHP

<?php
namespace App\Filament\Resources\ReviewPackResource\Pages;
use App\Filament\Pages\Reviews\CustomerReviewWorkspace;
use App\Filament\Resources\ReviewPackResource;
use App\Models\ReviewPack;
use App\Services\ReviewPackService;
use App\Support\Auth\Capabilities;
use App\Support\Rbac\UiEnforcement;
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,
array_filter($parameters, static fn (mixed $value): bool => $value !== null && $value !== ''),
))
->openUrlInNewTab();
}
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();
}
}