diff --git a/assets/controllers/elements/datatables/parts_controller.js b/assets/controllers/elements/datatables/parts_controller.js
index 33362648..1fe11a20 100644
--- a/assets/controllers/elements/datatables/parts_controller.js
+++ b/assets/controllers/elements/datatables/parts_controller.js
@@ -107,6 +107,13 @@ export default class extends DatatablesController {
//Hide the select element (the tomselect button is the sibling of the select element)
select_target.nextElementSibling.classList.add('d-none');
}
+
+ //If the selected option has a data-turbo attribute, set it to the form
+ if (selected_option.dataset.turbo) {
+ this.element.dataset.turbo = selected_option.dataset.turbo;
+ } else {
+ this.element.dataset.turbo = true;
+ }
}
confirmDeletionAtSubmit(event) {
diff --git a/src/Controller/PartImportExportController.php b/src/Controller/PartImportExportController.php
new file mode 100644
index 00000000..e3013cb8
--- /dev/null
+++ b/src/Controller/PartImportExportController.php
@@ -0,0 +1,63 @@
+.
+ */
+
+namespace App\Controller;
+
+use App\Services\ImportExportSystem\EntityExporter;
+use App\Services\Parts\PartsTableActionHandler;
+use Doctrine\ORM\EntityManagerInterface;
+use InvalidArgumentException;
+use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\Response;
+use Symfony\Component\Routing\Annotation\Route;
+
+class PartImportExportController extends AbstractController
+{
+ private EntityManagerInterface $entityManager;
+ private PartsTableActionHandler $partsTableActionHandler;
+
+ public function __construct(EntityManagerInterface $entityManager, PartsTableActionHandler $partsTableActionHandler)
+ {
+ $this->entityManager = $entityManager;
+ $this->partsTableActionHandler = $partsTableActionHandler;
+ }
+
+ /**
+ * @Route("/parts/export", name="parts_export", methods={"GET"})
+ * @return Response
+ */
+ public function exportParts(Request $request, EntityExporter $entityExporter): Response
+ {
+ $ids = $request->query->get('ids', '');
+ $parts = $this->partsTableActionHandler->idStringToArray($ids);
+
+ if (empty($parts)) {
+ throw new \RuntimeException('No parts found!');
+ }
+
+ //Ensure that we have access to the parts
+ foreach ($parts as $part) {
+ $this->denyAccessUnlessGranted('read', $part);
+ }
+
+ return $entityExporter->exportEntityFromRequest($parts, $request);
+ }
+}
\ No newline at end of file
diff --git a/src/Controller/SelectAPIController.php b/src/Controller/SelectAPIController.php
index 0f30b648..1b7784e4 100644
--- a/src/Controller/SelectAPIController.php
+++ b/src/Controller/SelectAPIController.php
@@ -95,6 +95,25 @@ class SelectAPIController extends AbstractController
return $this->getResponseForClass(Project::class, false);
}
+ /**
+ * @Route("/export_level", name="select_export_level")
+ */
+ public function exportLevel(): Response
+ {
+ $entries = [
+ 1 => $this->translator->trans('export.level.simple'),
+ 2 => $this->translator->trans('export.level.extended'),
+ 3 => $this->translator->trans('export.level.full'),
+ ];
+
+ return $this->json(array_map(function ($key, $value) {
+ return [
+ 'text' => $value,
+ 'value' => $key,
+ ];
+ }, array_keys($entries), $entries));
+ }
+
/**
* @Route("/label_profiles", name="select_label_profiles")
* @return Response
diff --git a/src/Services/ImportExportSystem/EntityExporter.php b/src/Services/ImportExportSystem/EntityExporter.php
index e4b4e552..2b84b115 100644
--- a/src/Services/ImportExportSystem/EntityExporter.php
+++ b/src/Services/ImportExportSystem/EntityExporter.php
@@ -52,7 +52,7 @@ class EntityExporter
$resolver->setDefault('format', 'csv');
$resolver->setAllowedValues('format', ['csv', 'json', 'xml', 'yaml']);
- $resolver->setDefault('csv_delimiter', ',');
+ $resolver->setDefault('csv_delimiter', ';');
$resolver->setAllowedTypes('csv_delimiter', 'string');
$resolver->setDefault('level', 'extended');
diff --git a/src/Services/Parts/PartsTableActionHandler.php b/src/Services/Parts/PartsTableActionHandler.php
index 8b695141..3061d2f3 100644
--- a/src/Services/Parts/PartsTableActionHandler.php
+++ b/src/Services/Parts/PartsTableActionHandler.php
@@ -102,6 +102,34 @@ final class PartsTableActionHandler
);
}
+ //When action starts with "export_" we have to redirect to the export controller
+ $matches = [];
+ if (preg_match('/^export_(json|yaml|xml|csv)$/', $action, $matches)) {
+ $ids = implode(',', array_map(static fn (Part $part) => $part->getID(), $selected_parts));
+ switch ($target_id) {
+ case 1:
+ default:
+ $level = 'simple';
+ break;
+ case 2:
+ $level = 'extended';
+ break;
+ case 3:
+ $level = 'full';
+ break;
+ }
+
+
+ return new RedirectResponse(
+ $this->urlGenerator->generate('parts_export', [
+ 'format' => $matches[1],
+ 'level' => $level,
+ 'ids' => $ids,
+ '_redirect' => $redirect_url
+ ])
+ );
+ }
+
//Iterate over the parts and apply the action to it:
foreach ($selected_parts as $part) {
diff --git a/templates/components/datatables.macro.html.twig b/templates/components/datatables.macro.html.twig
index e8a91c7f..fcc38453 100644
--- a/templates/components/datatables.macro.html.twig
+++ b/templates/components/datatables.macro.html.twig
@@ -63,6 +63,12 @@
+