SuperSeller3000/src/Infrastructure/Http/Controller/Admin/PipelineArchiveCrudController.php

116 lines
4.3 KiB
PHP
Raw Normal View History

<?php
declare(strict_types=1);
namespace App\Infrastructure\Http\Controller\Admin;
use App\Domain\Pipeline\AIPipelineJob;
use App\Domain\Pipeline\AIPipelineJobStatus;
use Doctrine\ORM\QueryBuilder;
use EasyCorp\Bundle\EasyAdminBundle\Collection\FieldCollection;
use EasyCorp\Bundle\EasyAdminBundle\Collection\FilterCollection;
use EasyCorp\Bundle\EasyAdminBundle\Config\Action;
use EasyCorp\Bundle\EasyAdminBundle\Config\Actions;
use EasyCorp\Bundle\EasyAdminBundle\Config\Crud;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
use EasyCorp\Bundle\EasyAdminBundle\Dto\EntityDto;
use EasyCorp\Bundle\EasyAdminBundle\Dto\SearchDto;
use EasyCorp\Bundle\EasyAdminBundle\Field\DateTimeField;
use EasyCorp\Bundle\EasyAdminBundle\Field\IdField;
use EasyCorp\Bundle\EasyAdminBundle\Field\IntegerField;
use EasyCorp\Bundle\EasyAdminBundle\Field\TextareaField;
use EasyCorp\Bundle\EasyAdminBundle\Field\TextField;
use EasyCorp\Bundle\EasyAdminBundle\Orm\EntityRepository;
use Symfony\Component\Translation\TranslatableMessage;
/** @extends AbstractCrudController<AIPipelineJob> */
final class PipelineArchiveCrudController extends AbstractCrudController
{
public static function getEntityFqcn(): string
{
return AIPipelineJob::class;
}
public function configureCrud(Crud $crud): Crud
{
return $crud
->setEntityLabelInSingular(new TranslatableMessage('crud.pipeline_job.singular', [], 'admin'))
->setEntityLabelInPlural(new TranslatableMessage('crud.pipeline_job.plural_archive', [], 'admin'))
->setDefaultSort(['completedAt' => 'DESC'])
->showEntityActionsInlined();
}
public function configureActions(Actions $actions): Actions
{
return $actions
->add(Crud::PAGE_INDEX, Action::DETAIL)
->disable(Action::NEW, Action::EDIT, Action::DELETE);
}
public function configureFields(string $pageName): iterable
{
yield IdField::new('id')->hideOnIndex();
yield TextField::new('inventoryNumber', 'Inventory #')
->hideOnForm()
->formatValue(static fn ($v, AIPipelineJob $job): string => (string) ($job->getInputData()['inventoryNumber'] ?? '—'));
yield TextField::new('statusLabel', 'Status')
->hideOnForm();
yield IntegerField::new('attemptCount', 'Attempts')->hideOnForm();
yield DateTimeField::new('createdAt', 'Started')->hideOnForm();
yield DateTimeField::new('completedAt', 'Completed')->hideOnForm();
yield TextField::new('articleId', 'Article')
->hideOnForm()
->formatValue(static fn ($v, AIPipelineJob $job): string => $job->getArticleId()?->toRfc4122() ?? '—');
yield TextareaField::new('aiResults', 'AI Results')
->onlyOnDetail()
->formatValue(static fn ($v, AIPipelineJob $job): string => self::formatStepResults($job));
}
public function createIndexQueryBuilder(
SearchDto $searchDto,
EntityDto $entityDto,
FieldCollection $fields,
FilterCollection $filters,
): QueryBuilder {
$qb = $this->container->get(EntityRepository::class)->createQueryBuilder($searchDto, $entityDto, $fields, $filters);
$qb->andWhere('entity.status = :completed')
->setParameter('completed', AIPipelineJobStatus::Completed);
return $qb;
}
private static function formatStepResults(AIPipelineJob $job): string
{
$output = $job->getOutputData();
if ([] === $output) {
return '(none)';
}
$lines = [];
$labels = [
'vision' => 'Vision',
'specs_research' => 'Specs Research',
'json_coding' => 'JSON Coding',
'validation' => 'Validation',
];
foreach ($labels as $key => $label) {
if (!isset($output[$key])) {
continue;
}
$data = $output[$key];
$lines[] = "=== {$label} ===";
foreach ($data as $k => $v) {
if (\is_array($v)) {
$lines[] = "{$k}: ".json_encode($v, \JSON_UNESCAPED_UNICODE | \JSON_PRETTY_PRINT);
} else {
$lines[] = "{$k}: {$v}";
}
}
$lines[] = '';
}
return implode("\n", $lines);
}
}