mirror of
https://github.com/Part-DB/Part-DB-server.git
synced 2026-01-13 13:49:33 +00:00
Assemblies einführen
This commit is contained in:
parent
e1418dfdc1
commit
f0748a2123
107 changed files with 14096 additions and 98 deletions
80
src/Controller/AdminPages/AssemblyAdminController.php
Normal file
80
src/Controller/AdminPages/AssemblyAdminController.php
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
|
||||
*
|
||||
* Copyright (C) 2019 - 2022 Jan Böhmer (https://github.com/jbtronics)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published
|
||||
* by the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Controller\AdminPages;
|
||||
|
||||
use App\Entity\AssemblySystem\Assembly;
|
||||
use App\Entity\Attachments\AssemblyAttachment;
|
||||
use App\Entity\Parameters\AssemblyParameter;
|
||||
use App\Form\AdminPages\AssemblyAdminForm;
|
||||
use App\Services\ImportExportSystem\EntityExporter;
|
||||
use App\Services\ImportExportSystem\EntityImporter;
|
||||
use App\Services\Trees\StructuralElementRecursionHelper;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
|
||||
#[Route(path: '/assembly')]
|
||||
class AssemblyAdminController extends BaseAdminController
|
||||
{
|
||||
protected string $entity_class = Assembly::class;
|
||||
protected string $twig_template = 'admin/assembly_admin.html.twig';
|
||||
protected string $form_class = AssemblyAdminForm::class;
|
||||
protected string $route_base = 'assembly';
|
||||
protected string $attachment_class = AssemblyAttachment::class;
|
||||
protected ?string $parameter_class = AssemblyParameter::class;
|
||||
|
||||
#[Route(path: '/{id}', name: 'assembly_delete', methods: ['DELETE'])]
|
||||
public function delete(Request $request, Assembly $entity, StructuralElementRecursionHelper $recursionHelper): RedirectResponse
|
||||
{
|
||||
return $this->_delete($request, $entity, $recursionHelper);
|
||||
}
|
||||
|
||||
#[Route(path: '/{id}/edit/{timestamp}', name: 'assembly_edit', requirements: ['id' => '\d+'])]
|
||||
#[Route(path: '/{id}/edit', requirements: ['id' => '\d+'])]
|
||||
public function edit(Assembly $entity, Request $request, EntityManagerInterface $em, ?string $timestamp = null): Response
|
||||
{
|
||||
return $this->_edit($entity, $request, $em, $timestamp);
|
||||
}
|
||||
|
||||
#[Route(path: '/new', name: 'assembly_new')]
|
||||
#[Route(path: '/{id}/clone', name: 'assembly_clone')]
|
||||
#[Route(path: '/')]
|
||||
public function new(Request $request, EntityManagerInterface $em, EntityImporter $importer, ?Assembly $entity = null): Response
|
||||
{
|
||||
return $this->_new($request, $em, $importer, $entity);
|
||||
}
|
||||
|
||||
#[Route(path: '/export', name: 'assembly_export_all')]
|
||||
public function exportAll(EntityManagerInterface $em, EntityExporter $exporter, Request $request): Response
|
||||
{
|
||||
return $this->_exportAll($em, $exporter, $request);
|
||||
}
|
||||
|
||||
#[Route(path: '/{id}/export', name: 'assembly_export')]
|
||||
public function exportEntity(Assembly $entity, EntityExporter $exporter, Request $request): Response
|
||||
{
|
||||
return $this->_exportEntity($entity, $exporter, $request);
|
||||
}
|
||||
}
|
||||
302
src/Controller/AssemblyController.php
Normal file
302
src/Controller/AssemblyController.php
Normal file
|
|
@ -0,0 +1,302 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
|
||||
*
|
||||
* Copyright (C) 2019 - 2022 Jan Böhmer (https://github.com/jbtronics)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published
|
||||
* by the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
namespace App\Controller;
|
||||
|
||||
use App\DataTables\AssemblyBomEntriesDataTable;
|
||||
use App\Entity\AssemblySystem\Assembly;
|
||||
use App\Entity\AssemblySystem\AssemblyBOMEntry;
|
||||
use App\Entity\Parts\Part;
|
||||
use App\Form\AssemblySystem\AssemblyAddPartsType;
|
||||
use App\Form\AssemblySystem\AssemblyBuildType;
|
||||
use App\Helpers\Assemblies\AssemblyBuildRequest;
|
||||
use App\Repository\PartRepository;
|
||||
use App\Services\ImportExportSystem\BOMImporter;
|
||||
use App\Services\AssemblySystem\AssemblyBuildHelper;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use League\Csv\SyntaxError;
|
||||
use Omines\DataTablesBundle\DataTableFactory;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\FileType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Component\Validator\Validator\ValidatorInterface;
|
||||
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
use function Symfony\Component\Translation\t;
|
||||
|
||||
#[Route(path: '/assembly')]
|
||||
class AssemblyController extends AbstractController
|
||||
{
|
||||
private PartRepository $partRepository;
|
||||
|
||||
public function __construct(
|
||||
private readonly DataTableFactory $dataTableFactory,
|
||||
private readonly EntityManagerInterface $entityManager,
|
||||
private readonly TranslatorInterface $translator,
|
||||
) {
|
||||
$this->partRepository = $this->entityManager->getRepository(Part::class);
|
||||
}
|
||||
|
||||
#[Route(path: '/{id}/info', name: 'assembly_info', requirements: ['id' => '\d+'])]
|
||||
public function info(Assembly $assembly, Request $request, AssemblyBuildHelper $buildHelper): Response
|
||||
{
|
||||
$this->denyAccessUnlessGranted('read', $assembly);
|
||||
|
||||
$table = $this->dataTableFactory->createFromType(AssemblyBomEntriesDataTable::class, ['assembly' => $assembly])
|
||||
->handleRequest($request);
|
||||
|
||||
if ($table->isCallback()) {
|
||||
return $table->getResponse();
|
||||
}
|
||||
|
||||
return $this->render('assemblies/info/info.html.twig', [
|
||||
'buildHelper' => $buildHelper,
|
||||
'datatable' => $table,
|
||||
'assembly' => $assembly,
|
||||
]);
|
||||
}
|
||||
|
||||
#[Route(path: '/{id}/build', name: 'assembly_build', requirements: ['id' => '\d+'])]
|
||||
public function build(Assembly $assembly, Request $request, AssemblyBuildHelper $buildHelper, EntityManagerInterface $entityManager): Response
|
||||
{
|
||||
$this->denyAccessUnlessGranted('read', $assembly);
|
||||
|
||||
//If no number of builds is given (or it is invalid), just assume 1
|
||||
$number_of_builds = $request->query->getInt('n', 1);
|
||||
if ($number_of_builds < 1) {
|
||||
$number_of_builds = 1;
|
||||
}
|
||||
|
||||
$assemblyBuildRequest = new AssemblyBuildRequest($assembly, $number_of_builds);
|
||||
$form = $this->createForm(AssemblyBuildType::class, $assemblyBuildRequest);
|
||||
|
||||
$form->handleRequest($request);
|
||||
if ($form->isSubmitted()) {
|
||||
if ($form->isValid()) {
|
||||
//Ensure that the user can withdraw stock from all parts
|
||||
$this->denyAccessUnlessGranted('@parts_stock.withdraw');
|
||||
|
||||
//We have to do a flush already here, so that the newly created partLot gets an ID and can be logged to DB later.
|
||||
$entityManager->flush();
|
||||
$buildHelper->doBuild($assemblyBuildRequest);
|
||||
$entityManager->flush();
|
||||
$this->addFlash('success', 'assembly.build.flash.success');
|
||||
|
||||
return $this->redirect(
|
||||
$request->get('_redirect',
|
||||
$this->generateUrl('assembly_info', ['id' => $assembly->getID()]
|
||||
)));
|
||||
}
|
||||
|
||||
$this->addFlash('error', 'assembly.build.flash.invalid_input');
|
||||
}
|
||||
|
||||
return $this->render('assemblies/build/build.html.twig', [
|
||||
'buildHelper' => $buildHelper,
|
||||
'assembly' => $assembly,
|
||||
'build_request' => $assemblyBuildRequest,
|
||||
'number_of_builds' => $number_of_builds,
|
||||
'form' => $form,
|
||||
]);
|
||||
}
|
||||
|
||||
#[Route(path: '/{id}/import_bom', name: 'assembly_import_bom', requirements: ['id' => '\d+'])]
|
||||
public function importBOM(Request $request, EntityManagerInterface $entityManager, Assembly $assembly,
|
||||
BOMImporter $BOMImporter, ValidatorInterface $validator): Response
|
||||
{
|
||||
$this->denyAccessUnlessGranted('edit', $assembly);
|
||||
|
||||
$builder = $this->createFormBuilder();
|
||||
$builder->add('file', FileType::class, [
|
||||
'label' => 'import.file',
|
||||
'required' => true,
|
||||
'attr' => [
|
||||
'accept' => '.csv, .json'
|
||||
]
|
||||
]);
|
||||
$builder->add('type', ChoiceType::class, [
|
||||
'label' => 'assembly.bom_import.type',
|
||||
'required' => true,
|
||||
'choices' => [
|
||||
'assembly.bom_import.type.json' => 'json',
|
||||
'assembly.bom_import.type.kicad_pcbnew' => 'kicad_pcbnew',
|
||||
]
|
||||
]);
|
||||
$builder->add('clear_existing_bom', CheckboxType::class, [
|
||||
'label' => 'assembly.bom_import.clear_existing_bom',
|
||||
'required' => false,
|
||||
'data' => false,
|
||||
'help' => 'assembly.bom_import.clear_existing_bom.help',
|
||||
]);
|
||||
$builder->add('submit', SubmitType::class, [
|
||||
'label' => 'import.btn',
|
||||
]);
|
||||
|
||||
$form = $builder->getForm();
|
||||
|
||||
$form->handleRequest($request);
|
||||
if ($form->isSubmitted() && $form->isValid()) {
|
||||
|
||||
//Clear existing BOM entries if requested
|
||||
if ($form->get('clear_existing_bom')->getData()) {
|
||||
$assembly->getBomEntries()->clear();
|
||||
$entityManager->flush();
|
||||
}
|
||||
|
||||
try {
|
||||
$entries = $BOMImporter->importFileIntoAssembly($form->get('file')->getData(), $assembly, [
|
||||
'type' => $form->get('type')->getData(),
|
||||
]);
|
||||
|
||||
//Validate the assembly entries
|
||||
$errors = $validator->validateProperty($assembly, 'bom_entries');
|
||||
|
||||
//If no validation errors occured, save the changes and redirect to edit page
|
||||
if (count ($errors) === 0) {
|
||||
foreach ($entries as $entry) {
|
||||
if ($entry instanceof AssemblyBOMEntry && $entry->getPart() !== null) {
|
||||
$part = $entry->getPart();
|
||||
if ($part->getID() === null) {
|
||||
$this->partRepository->save($part);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->addFlash('success', t('assembly.bom_import.flash.success', ['%count%' => count($entries)]));
|
||||
$entityManager->flush();
|
||||
return $this->redirectToRoute('assembly_edit', ['id' => $assembly->getID()]);
|
||||
}
|
||||
|
||||
//When we get here, there were validation errors
|
||||
$this->addFlash('error', t('assembly.bom_import.flash.invalid_entries'));
|
||||
|
||||
} catch (\UnexpectedValueException|\RuntimeException|SyntaxError $e) {
|
||||
$this->addFlash('error', t('assembly.bom_import.flash.invalid_file', ['%message%' => $e->getMessage()]));
|
||||
}
|
||||
}
|
||||
|
||||
$jsonTemplate = [
|
||||
[
|
||||
"quantity" => 1.0,
|
||||
"name" => $this->translator->trans('assembly.bom_import.template.entry.name'),
|
||||
"part" => [
|
||||
"id" => null,
|
||||
"ipn" => $this->translator->trans('assembly.bom_import.template.entry.part.ipn'),
|
||||
"mpnr" => $this->translator->trans('assembly.bom_import.template.entry.part.mpnr'),
|
||||
"name" => $this->translator->trans('assembly.bom_import.template.entry.part.name'),
|
||||
"description" => null,
|
||||
"manufacturer" => [
|
||||
"id" => null,
|
||||
"name" => $this->translator->trans('assembly.bom_import.template.entry.part.manufacturer.name')
|
||||
],
|
||||
"category" => [
|
||||
"id" => null,
|
||||
"name" => $this->translator->trans('assembly.bom_import.template.entry.part.category.name')
|
||||
]
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
return $this->render('assemblies/import_bom.html.twig', [
|
||||
'assembly' => $assembly,
|
||||
'jsonTemplate' => $jsonTemplate,
|
||||
'form' => $form,
|
||||
'errors' => $errors ?? null,
|
||||
]);
|
||||
}
|
||||
|
||||
#[Route(path: '/add_parts', name: 'assembly_add_parts_no_id')]
|
||||
#[Route(path: '/{id}/add_parts', name: 'assembly_add_parts', requirements: ['id' => '\d+'])]
|
||||
public function addPart(Request $request, EntityManagerInterface $entityManager, ?Assembly $assembly): Response
|
||||
{
|
||||
if($assembly instanceof Assembly) {
|
||||
$this->denyAccessUnlessGranted('edit', $assembly);
|
||||
} else {
|
||||
$this->denyAccessUnlessGranted('@assemblies.edit');
|
||||
}
|
||||
|
||||
$form = $this->createForm(AssemblyAddPartsType::class, null, [
|
||||
'assembly' => $assembly,
|
||||
]);
|
||||
|
||||
//Preset the BOM entries with the selected parts, when the form was not submitted yet
|
||||
$preset_data = new ArrayCollection();
|
||||
foreach (explode(',', (string) $request->get('parts', '')) as $part_id) {
|
||||
//Skip empty part IDs. Postgres seems to be especially sensitive to empty strings, as it does not allow them in integer columns
|
||||
if ($part_id === '') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$part = $entityManager->getRepository(Part::class)->find($part_id);
|
||||
if (null !== $part) {
|
||||
//If there is already a BOM entry for this part, we use this one (we edit it then)
|
||||
$bom_entry = $entityManager->getRepository(AssemblyBOMEntry::class)->findOneBy([
|
||||
'assembly' => $assembly,
|
||||
'part' => $part
|
||||
]);
|
||||
if ($bom_entry !== null) {
|
||||
$preset_data->add($bom_entry);
|
||||
} else { //Otherwise create an empty one
|
||||
$entry = new AssemblyBOMEntry();
|
||||
$entry->setAssembly($assembly);
|
||||
$entry->setPart($part);
|
||||
$preset_data->add($entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
$form['bom_entries']->setData($preset_data);
|
||||
|
||||
$form->handleRequest($request);
|
||||
if ($form->isSubmitted() && $form->isValid()) {
|
||||
$target_assembly = $assembly ?? $form->get('assembly')->getData();
|
||||
|
||||
//Ensure that we really have acces to the selected assembly
|
||||
$this->denyAccessUnlessGranted('edit', $target_assembly);
|
||||
|
||||
$data = $form->getData();
|
||||
$bom_entries = $data['bom_entries'];
|
||||
foreach ($bom_entries as $bom_entry){
|
||||
$target_assembly->addBOMEntry($bom_entry);
|
||||
}
|
||||
|
||||
$entityManager->flush();
|
||||
|
||||
//If a redirect query parameter is set, redirect to this page
|
||||
if ($request->query->get('_redirect')) {
|
||||
return $this->redirect($request->query->get('_redirect'));
|
||||
}
|
||||
//Otherwise just show the assembly info page
|
||||
return $this->redirectToRoute('assembly_info', ['id' => $target_assembly->getID()]);
|
||||
}
|
||||
|
||||
return $this->render('assemblies/add_parts.html.twig', [
|
||||
'assembly' => $assembly,
|
||||
'form' => $form,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
@ -23,6 +23,7 @@ declare(strict_types=1);
|
|||
namespace App\Controller;
|
||||
|
||||
use App\DataTables\LogDataTable;
|
||||
use App\Entity\AssemblySystem\Assembly;
|
||||
use App\Entity\Attachments\AttachmentUpload;
|
||||
use App\Entity\Parts\Category;
|
||||
use App\Entity\Parts\Footprint;
|
||||
|
|
@ -45,6 +46,7 @@ use App\Services\LogSystem\TimeTravel;
|
|||
use App\Services\Parameters\ParameterExtractor;
|
||||
use App\Services\Parts\PartLotWithdrawAddHelper;
|
||||
use App\Services\Parts\PricedetailHelper;
|
||||
use App\Services\AssemblySystem\AssemblyBuildPartHelper;
|
||||
use App\Services\ProjectSystem\ProjectBuildPartHelper;
|
||||
use App\Settings\BehaviorSettings\PartInfoSettings;
|
||||
use DateTime;
|
||||
|
|
@ -204,15 +206,18 @@ final class PartController extends AbstractController
|
|||
|
||||
#[Route(path: '/new', name: 'part_new')]
|
||||
#[Route(path: '/{id}/clone', name: 'part_clone')]
|
||||
#[Route(path: '/new_build_part/{project_id}', name: 'part_new_build_part')]
|
||||
#[Route(path: '/new_build_part_project/{project_id}', name: 'part_new_build_part')]
|
||||
#[Route(path: '/new_build_part_assembly/{assembly_id}', name: 'part_new_build_part_assembly')]
|
||||
public function new(
|
||||
Request $request,
|
||||
EntityManagerInterface $em,
|
||||
TranslatorInterface $translator,
|
||||
AttachmentSubmitHandler $attachmentSubmitHandler,
|
||||
ProjectBuildPartHelper $projectBuildPartHelper,
|
||||
AssemblyBuildPartHelper $assemblyBuildPartHelper,
|
||||
#[MapEntity(mapping: ['id' => 'id'])] ?Part $part = null,
|
||||
#[MapEntity(mapping: ['project_id' => 'id'])] ?Project $project = null
|
||||
#[MapEntity(mapping: ['project_id' => 'id'])] ?Project $project = null,
|
||||
#[MapEntity(mapping: ['assembly_id' => 'id'])] ?Assembly $assembly = null
|
||||
): Response {
|
||||
|
||||
if ($part instanceof Part) {
|
||||
|
|
@ -226,6 +231,14 @@ final class PartController extends AbstractController
|
|||
return $this->redirectToRoute('part_edit', ['id' => $project->getBuildPart()->getID()]);
|
||||
}
|
||||
$new_part = $projectBuildPartHelper->getPartInitialization($project);
|
||||
} elseif ($assembly instanceof Assembly) {
|
||||
//Initialize a new part for a build part from the given assembly
|
||||
//Ensure that the assembly has not already a build part
|
||||
if ($project->getBuildPart() instanceof Part) {
|
||||
$this->addFlash('error', 'part.new_build_part.error.build_part_already_exists');
|
||||
return $this->redirectToRoute('part_edit', ['id' => $project->getBuildPart()->getID()]);
|
||||
}
|
||||
$new_part = $assemblyBuildPartHelper->getPartInitialization($assembly);
|
||||
} else { //Create an empty part from scratch
|
||||
$new_part = new Part();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace App\Controller;
|
||||
|
||||
use App\Entity\AssemblySystem\Assembly;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use App\Entity\ProjectSystem\Project;
|
||||
use App\Entity\Parts\Category;
|
||||
|
|
@ -129,4 +130,17 @@ class TreeController extends AbstractController
|
|||
|
||||
return new JsonResponse($tree);
|
||||
}
|
||||
|
||||
#[Route(path: '/assembly/{id}', name: 'tree_assembly')]
|
||||
#[Route(path: '/assemblies', name: 'tree_assembly_root')]
|
||||
public function assemblyTree(?Assembly $assembly = null): JsonResponse
|
||||
{
|
||||
if ($this->isGranted('@assemblies.read')) {
|
||||
$tree = $this->treeGenerator->getTreeView(Assembly::class, $assembly, 'assemblies');
|
||||
} else {
|
||||
return new JsonResponse("Access denied", Response::HTTP_FORBIDDEN);
|
||||
}
|
||||
|
||||
return new JsonResponse($tree);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,9 @@ declare(strict_types=1);
|
|||
|
||||
namespace App\Controller;
|
||||
|
||||
use App\Entity\AssemblySystem\Assembly;
|
||||
use App\Entity\Parameters\AbstractParameter;
|
||||
use App\Services\Attachments\AssemblyPreviewGenerator;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use App\Entity\Attachments\Attachment;
|
||||
use App\Entity\Parts\Category;
|
||||
|
|
@ -53,6 +55,8 @@ use Symfony\Component\Routing\Attribute\Route;
|
|||
use Symfony\Component\Serializer\Encoder\JsonEncoder;
|
||||
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
|
||||
use Symfony\Component\Serializer\Serializer;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
use InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* In this controller the endpoints for the typeaheads are collected.
|
||||
|
|
@ -60,8 +64,11 @@ use Symfony\Component\Serializer\Serializer;
|
|||
#[Route(path: '/typeahead')]
|
||||
class TypeaheadController extends AbstractController
|
||||
{
|
||||
public function __construct(protected AttachmentURLGenerator $urlGenerator, protected Packages $assets)
|
||||
{
|
||||
public function __construct(
|
||||
protected AttachmentURLGenerator $urlGenerator,
|
||||
protected Packages $assets,
|
||||
protected TranslatorInterface $translator
|
||||
) {
|
||||
}
|
||||
|
||||
#[Route(path: '/builtInResources/search', name: 'typeahead_builtInRessources')]
|
||||
|
|
@ -109,19 +116,22 @@ class TypeaheadController extends AbstractController
|
|||
'group' => GroupParameter::class,
|
||||
'measurement_unit' => MeasurementUnitParameter::class,
|
||||
'currency' => Currency::class,
|
||||
default => throw new \InvalidArgumentException('Invalid parameter type: '.$type),
|
||||
default => throw new InvalidArgumentException('Invalid parameter type: '.$type),
|
||||
};
|
||||
}
|
||||
|
||||
#[Route(path: '/parts/search/{query}', name: 'typeahead_parts')]
|
||||
public function parts(EntityManagerInterface $entityManager, PartPreviewGenerator $previewGenerator,
|
||||
AttachmentURLGenerator $attachmentURLGenerator, string $query = ""): JsonResponse
|
||||
{
|
||||
public function parts(
|
||||
EntityManagerInterface $entityManager,
|
||||
PartPreviewGenerator $previewGenerator,
|
||||
AttachmentURLGenerator $attachmentURLGenerator,
|
||||
string $query = ""
|
||||
): JsonResponse {
|
||||
$this->denyAccessUnlessGranted('@parts.read');
|
||||
|
||||
$repo = $entityManager->getRepository(Part::class);
|
||||
$partRepository = $entityManager->getRepository(Part::class);
|
||||
|
||||
$parts = $repo->autocompleteSearch($query, 100);
|
||||
$parts = $partRepository->autocompleteSearch($query, 100);
|
||||
|
||||
$data = [];
|
||||
foreach ($parts as $part) {
|
||||
|
|
@ -147,6 +157,44 @@ class TypeaheadController extends AbstractController
|
|||
return new JsonResponse($data);
|
||||
}
|
||||
|
||||
#[Route(path: '/assemblies/search/{query}', name: 'typeahead_assemblies')]
|
||||
public function assemblies(
|
||||
EntityManagerInterface $entityManager,
|
||||
AssemblyPreviewGenerator $assemblyPreviewGenerator,
|
||||
AttachmentURLGenerator $attachmentURLGenerator,
|
||||
string $query = ""
|
||||
): JsonResponse {
|
||||
$this->denyAccessUnlessGranted('@assemblies.read');
|
||||
|
||||
$result = [];
|
||||
|
||||
$assemblyRepository = $entityManager->getRepository(Assembly::class);
|
||||
|
||||
$assemblies = $assemblyRepository->autocompleteSearch($query, 100);
|
||||
|
||||
foreach ($assemblies as $assembly) {
|
||||
$preview_attachment = $assemblyPreviewGenerator->getTablePreviewAttachment($assembly);
|
||||
|
||||
if($preview_attachment instanceof Attachment) {
|
||||
$preview_url = $attachmentURLGenerator->getThumbnailURL($preview_attachment, 'thumbnail_sm');
|
||||
} else {
|
||||
$preview_url = '';
|
||||
}
|
||||
|
||||
/** @var Assembly $assembly */
|
||||
$result[] = [
|
||||
'id' => $assembly->getID(),
|
||||
'name' => $this->translator->trans('typeahead.parts.assembly.name', ['%name%' => $assembly->getName()]),
|
||||
'category' => '',
|
||||
'footprint' => '',
|
||||
'description' => mb_strimwidth($assembly->getDescription(), 0, 127, '...'),
|
||||
'image' => $preview_url,
|
||||
];
|
||||
}
|
||||
|
||||
return new JsonResponse($result);
|
||||
}
|
||||
|
||||
#[Route(path: '/parameters/{type}/search/{query}', name: 'typeahead_parameters', requirements: ['type' => '.+'])]
|
||||
public function parameters(string $type, EntityManagerInterface $entityManager, string $query = ""): JsonResponse
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue