diff --git a/src/Controller/PartListsController.php b/src/Controller/PartListsController.php index 574d4221..6e85f7f2 100644 --- a/src/Controller/PartListsController.php +++ b/src/Controller/PartListsController.php @@ -74,6 +74,7 @@ class PartListsController extends AbstractController $redirect = $request->request->get('redirect_back'); $ids = $request->request->get('ids'); $action = $request->request->get('action'); + $target = $request->request->get('target'); if (!$this->isCsrfTokenValid('table_action', $request->request->get('_token'))) { $this->addFlash('error', 'csfr_invalid'); @@ -84,7 +85,7 @@ class PartListsController extends AbstractController $this->addFlash('error', 'part.table.actions.no_params_given'); } else { $parts = $actionHandler->idStringToArray($ids); - $actionHandler->handleAction($action, $parts, null); + $actionHandler->handleAction($action, $parts, $target ? (int) $target : null); //Save changes $this->entityManager->flush(); diff --git a/src/Controller/SelectAPIController.php b/src/Controller/SelectAPIController.php new file mode 100644 index 00000000..851850f7 --- /dev/null +++ b/src/Controller/SelectAPIController.php @@ -0,0 +1,120 @@ +. + */ + +namespace App\Controller; + + +use App\Entity\Base\AbstractStructuralDBElement; +use App\Entity\Parts\Category; +use App\Entity\Parts\Footprint; +use App\Entity\Parts\Manufacturer; +use App\Entity\Parts\MeasurementUnit; +use App\Services\Trees\NodesListBuilder; +use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\Event\ResponseEvent; +use Symfony\Component\Routing\Annotation\Route; +use Symfony\Contracts\Translation\TranslatorInterface; + +/** + * @Route("/select_api") + * @package App\Controller + */ +class SelectAPIController extends AbstractController +{ + private $nodesListBuilder; + private $translator; + + public function __construct(NodesListBuilder $nodesListBuilder, TranslatorInterface $translator) + { + $this->nodesListBuilder = $nodesListBuilder; + $this->translator = $translator; + } + + /** + * @Route("/category", name="select_category") + */ + public function category(): Response + { + return $this->getResponseForClass(Category::class); + } + + /** + * @Route("/footprint", name="select_footprint") + */ + public function footprint(): Response + { + return $this->getResponseForClass(Footprint::class, true); + } + + /** + * @Route("/manufacturer", name="select_manufacturer") + */ + public function manufacturer(): Response + { + return $this->getResponseForClass(Manufacturer::class, true); + } + + /** + * @Route("/measurement_unit", name="select_measurement_unit") + */ + public function measurement_unit(): Response + { + return $this->getResponseForClass(MeasurementUnit::class, true); + } + + protected function getResponseForClass(string $class, bool $include_empty = false): Response + { + $test_obj = new $class; + $this->denyAccessUnlessGranted('read', $test_obj); + + $nodes = $this->nodesListBuilder->typeToNodesList($class); + + $json = $this->buildJSONStructure($nodes); + + if ($include_empty) { + array_unshift($json, [ + 'text' => '', + 'value' => null, + 'data-subtext' => $this->translator->trans('part_list.action.select_null'), + ]); + } + + return $this->json($json); + } + + protected function buildJSONStructure(array $nodes_list): array + { + $entries = []; + + foreach ($nodes_list as $node) { + /** @var AbstractStructuralDBElement $node */ + $entry = [ + 'text' => str_repeat('   ', $node->getLevel()) . htmlspecialchars($node->getName()), + 'value' => $node->getID(), + 'data-subtext' => $node->getParent() ? $node->getParent()->getFullPath() : null, + ]; + + $entries[] = $entry; + } + + return $entries; + } +} \ No newline at end of file diff --git a/src/Services/Parts/PartsTableActionHandler.php b/src/Services/Parts/PartsTableActionHandler.php index e0921672..130a6427 100644 --- a/src/Services/Parts/PartsTableActionHandler.php +++ b/src/Services/Parts/PartsTableActionHandler.php @@ -21,6 +21,10 @@ namespace App\Services\Parts; +use App\Entity\Parts\Category; +use App\Entity\Parts\Footprint; +use App\Entity\Parts\Manufacturer; +use App\Entity\Parts\MeasurementUnit; use App\Entity\Parts\Part; use Doctrine\ORM\EntityManagerInterface; use Symfony\Component\Security\Core\Exception\AccessDeniedException; @@ -77,6 +81,22 @@ final class PartsTableActionHandler $this->denyAccessUnlessGranted('delete', $part); $this->entityManager->remove($part); break; + case 'change_category': + $this->denyAccessUnlessGranted('category.edit', $part); + $part->setCategory($this->entityManager->find(Category::class, $target_id)); + break; + case 'change_footprint': + $this->denyAccessUnlessGranted('footprint.edit', $part); + $part->setFootprint($target_id === null ? null : $this->entityManager->find(Footprint::class, $target_id)); + break; + case 'change_manufacturer': + $this->denyAccessUnlessGranted('manufacturer.edit', $part); + $part->setManufacturer($target_id === null ? null : $this->entityManager->find(Manufacturer::class, $target_id)); + break; + case 'change_unit': + $this->denyAccessUnlessGranted('unit.edit', $part); + $part->setPartUnit($target_id === null ? null : $this->entityManager->find(MeasurementUnit::class, $target_id)); + break; default: throw new \InvalidArgumentException('The given action is unknown! (' . $action . ')'); diff --git a/templates/Parts/lists/_parts_list.html.twig b/templates/Parts/lists/_parts_list.html.twig index 6dddd8d0..d62e5616 100644 --- a/templates/Parts/lists/_parts_list.html.twig +++ b/templates/Parts/lists/_parts_list.html.twig @@ -8,10 +8,19 @@

elements selected!

- + + + + + + + + @@ -29,3 +38,46 @@
+ \ No newline at end of file