diff --git a/config/services.yaml b/config/services.yaml
index 132c787d..c119d1ef 100644
--- a/config/services.yaml
+++ b/config/services.yaml
@@ -183,9 +183,12 @@ services:
App\DataTables\Helpers\ColumnSortHelper:
shared: false # Service has a state so not share it between different tables
+ App\DataTables\AssemblyDataTable:
+ arguments:
+ $visible_columns: '%partdb.table.assemblies.default_columns%'
App\DataTables\AssemblyBomEntriesDataTable:
- arguments:
- $visible_columns: '%partdb.table.assemblies.default_columns%'
+ arguments:
+ $visible_columns: '%partdb.table.assemblies_bom.default_columns%'
####################################################################################################################
# Label system
diff --git a/src/Form/Type/AssemblySelectType.php b/src/Form/Type/AssemblySelectType.php
new file mode 100644
index 00000000..10e858f2
--- /dev/null
+++ b/src/Form/Type/AssemblySelectType.php
@@ -0,0 +1,124 @@
+addEventListener(FormEvents::PRE_SET_DATA, function (PreSetDataEvent $event) {
+ $form = $event->getForm();
+ $config = $form->getConfig()->getOptions();
+ $data = $event->getData() ?? [];
+
+ $config['compound'] = false;
+ $config['choices'] = is_iterable($data) ? $data : [$data];
+ $config['error_bubbling'] = true;
+
+ $form->add('autocomplete', EntityType::class, $config);
+ });
+
+ //After form submit, we have to add the selected element as choice, otherwise the form will not accept this element
+ $builder->addEventListener(FormEvents::PRE_SUBMIT, function(FormEvent $event) {
+ $data = $event->getData();
+ $form = $event->getForm();
+ $options = $form->get('autocomplete')->getConfig()->getOptions();
+
+
+ if (!isset($data['autocomplete']) || '' === $data['autocomplete'] || empty($data['autocomplete'])) {
+ $options['choices'] = [];
+ } else {
+ //Extract the ID from the submitted data
+ $id = $data['autocomplete'];
+ //Find the element in the database
+ $element = $this->em->find($options['class'], $id);
+
+ //Add the element as choice
+ $options['choices'] = [$element];
+ $options['error_bubbling'] = true;
+ $form->add('autocomplete', EntityType::class, $options);
+ }
+ });
+
+ $builder->setDataMapper($this);
+ }
+
+ public function configureOptions(OptionsResolver $resolver): void
+ {
+ $resolver->setDefaults([
+ 'class' => Assembly::class,
+ 'choice_label' => 'name',
+ 'compound' => true,
+ 'error_bubbling' => false,
+ ]);
+
+ error_log($this->urlGenerator->generate('typeahead_assemblies', ['query' => '__QUERY__']));
+
+ $resolver->setDefaults([
+ 'attr' => [
+ 'data-controller' => 'elements--assembly-select',
+ 'data-autocomplete' => $this->urlGenerator->generate('typeahead_assemblies', ['query' => '__QUERY__']),
+ 'autocomplete' => 'off',
+ ],
+ ]);
+
+ $resolver->setDefaults([
+ //Prefill the selected choice with the needed data, so the user can see it without an additional Ajax request
+ 'choice_attr' => ChoiceList::attr($this, function (?Assembly $assembly) {
+ if($assembly instanceof Assembly) {
+ //Determine the picture to show:
+ $preview_attachment = $this->previewGenerator->getTablePreviewAttachment($assembly);
+ if ($preview_attachment instanceof Attachment) {
+ $preview_url = $this->attachmentURLGenerator->getThumbnailURL($preview_attachment,
+ 'thumbnail_sm');
+ } else {
+ $preview_url = '';
+ }
+ }
+
+ return $assembly instanceof Assembly ? [
+ 'data-description' => $assembly->getDescription() ? mb_strimwidth($assembly->getDescription(), 0, 127, '...') : '',
+ 'data-category' => '',
+ 'data-footprint' => '',
+ 'data-image' => $preview_url,
+ ] : [];
+ })
+ ]);
+ }
+
+ public function mapDataToForms($data, \Traversable $forms): void
+ {
+ $form = current(iterator_to_array($forms, false));
+ $form->setData($data);
+ }
+
+ public function mapFormsToData(\Traversable $forms, &$data): void
+ {
+ $form = current(iterator_to_array($forms, false));
+ $data = $form->getData();
+ }
+
+}
diff --git a/src/Repository/AssemblyRepository.php b/src/Repository/AssemblyRepository.php
new file mode 100644
index 00000000..031e6e82
--- /dev/null
+++ b/src/Repository/AssemblyRepository.php
@@ -0,0 +1,69 @@
+.
+ */
+
+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 .
+ */
+
+namespace App\Repository;
+
+use App\Entity\AssemblySystem\Assembly;
+
+/**
+ * @template TEntityClass of Assembly
+ * @extends DBElementRepository
+ */
+class AssemblyRepository extends StructuralDBElementRepository
+{
+ /**
+ * @return Assembly[]
+ */
+ public function autocompleteSearch(string $query, int $max_limits = 50): array
+ {
+ $qb = $this->createQueryBuilder('assembly');
+ $qb->select('assembly')
+ ->where('ILIKE(assembly.name, :query) = TRUE')
+ ->orWhere('ILIKE(assembly.description, :query) = TRUE');
+
+ $qb->setParameter('query', '%'.$query.'%');
+
+ $qb->setMaxResults($max_limits);
+ $qb->orderBy('NATSORT(assembly.name)', 'ASC');
+
+ return $qb->getQuery()->getResult();
+ }
+}
\ No newline at end of file
diff --git a/src/Services/Attachments/AssemblyPreviewGenerator.php b/src/Services/Attachments/AssemblyPreviewGenerator.php
new file mode 100644
index 00000000..9ecbbd07
--- /dev/null
+++ b/src/Services/Attachments/AssemblyPreviewGenerator.php
@@ -0,0 +1,93 @@
+.
+ */
+
+declare(strict_types=1);
+
+namespace App\Services\Attachments;
+
+use App\Entity\AssemblySystem\Assembly;
+use App\Entity\Attachments\Attachment;
+
+class AssemblyPreviewGenerator
+{
+ public function __construct(protected AttachmentManager $attachmentHelper)
+ {
+ }
+
+ /**
+ * Returns a list of attachments that can be used for previewing the assembly ordered by priority.
+ *
+ * @param Assembly $assembly the assembly for which the attachments should be determined
+ *
+ * @return (Attachment|null)[]
+ *
+ * @psalm-return list
+ */
+ public function getPreviewAttachments(Assembly $assembly): array
+ {
+ $list = [];
+
+ //Master attachment has top priority
+ $attachment = $assembly->getMasterPictureAttachment();
+ if ($this->isAttachmentValidPicture($attachment)) {
+ $list[] = $attachment;
+ }
+
+ //Then comes the other images of the assembly
+ foreach ($assembly->getAttachments() as $attachment) {
+ //Dont show the master attachment twice
+ if ($this->isAttachmentValidPicture($attachment) && $attachment !== $assembly->getMasterPictureAttachment()) {
+ $list[] = $attachment;
+ }
+ }
+
+ return $list;
+ }
+
+ /**
+ * Determines what attachment should be used for previewing a assembly (especially in assembly table).
+ * The returned attachment is guaranteed to be existing and be a picture.
+ *
+ * @param Assembly $assembly The assembly for which the attachment should be determined
+ */
+ public function getTablePreviewAttachment(Assembly $assembly): ?Attachment
+ {
+ $attachment = $assembly->getMasterPictureAttachment();
+ if ($this->isAttachmentValidPicture($attachment)) {
+ return $attachment;
+ }
+
+ return null;
+ }
+
+ /**
+ * Checks if a attachment is exising and a valid picture.
+ *
+ * @param Attachment|null $attachment the attachment that should be checked
+ *
+ * @return bool true if the attachment is valid
+ */
+ protected function isAttachmentValidPicture(?Attachment $attachment): bool
+ {
+ return $attachment instanceof Attachment
+ && $attachment->isPicture()
+ && $this->attachmentHelper->isFileExisting($attachment);
+ }
+}
diff --git a/templates/assemblies/info/info.html.twig b/templates/assemblies/info/info.html.twig
index 2ef6cf25..dbda5f7e 100644
--- a/templates/assemblies/info/info.html.twig
+++ b/templates/assemblies/info/info.html.twig
@@ -135,7 +135,7 @@
{% include "assemblies/info/_builds.html.twig" %}
- {% include "assemblies/info/_attachments_info.html.twig" with {"part": assembly} %}
+ {% include "assemblies/info/_attachments_info.html.twig" with {"assembly": assembly} %}
{% for name, parameters in assembly.groupedParameters %}
diff --git a/translations/messages.cs.xlf b/translations/messages.cs.xlf
index 16fb09a9..c437de98 100644
--- a/translations/messages.cs.xlf
+++ b/translations/messages.cs.xlf
@@ -9996,12 +9996,6 @@ Element 3
Interní číslo dílu (IPN)
-
-
- assembly.edit.ipn
- Interní číslo dílu (IPN)
-
- assembly.status.draft
@@ -13612,6 +13606,12 @@ Vezměte prosím na vědomí, že se nemůžete vydávat za uživatele se zakáz
Sestavy
+
+
+ assembly.referencedAssembly.labelp
+ Odkazované sestavy
+
+ assembly.edit
@@ -13780,6 +13780,12 @@ Vezměte prosím na vědomí, že se nemůžete vydávat za uživatele se zakáz
Sestavit
+
+
+ assembly.build.form.referencedAssembly
+ Sestava "%name%"
+
+ assembly.builds.no_stocked_builds
diff --git a/translations/messages.da.xlf b/translations/messages.da.xlf
index cade27c6..cee4f08c 100644
--- a/translations/messages.da.xlf
+++ b/translations/messages.da.xlf
@@ -10010,12 +10010,6 @@ Element 3
Internt Partnummer (IPN)
-
-
- assembly.edit.ipn
- Internt Partnummer (IPN)
-
- assembly.status.draft
diff --git a/translations/messages.el.xlf b/translations/messages.el.xlf
index 08fb7df8..7d345fbd 100644
--- a/translations/messages.el.xlf
+++ b/translations/messages.el.xlf
@@ -2620,6 +2620,12 @@
%value% (Μέρος)
+
+
+ part.table.name.value.for_assembly
+ %value% (Συναρμολόγηση)
+
+ part.table.name.value.for_project
@@ -2629,7 +2635,7 @@
assembly.edit.status
- Κατάσταση
+ Κατάσταση συναρμολόγησης
@@ -2692,6 +2698,12 @@
Συναρμολογήσεις
+
+
+ assembly.referencedAssembly.labelp
+ Αναφερόμενες συναρμολογήσεις
+
+ assembly.edit
@@ -2860,6 +2872,12 @@
Κατασκευή
+
+
+ assembly.build.form.referencedAssembly
+ Συναρμολόγηση "%name%"
+
+ assembly.builds.no_stocked_builds
@@ -2914,6 +2932,12 @@
έργο
+
+
+ assembly.bom.referencedAssembly
+ Συναρμολόγηση
+
+ assembly.bom.name
@@ -2950,10 +2974,10 @@
Εισαγωγή εξαρτημάτων συναρμολόγησης
-
+
- assembly.bom.partOrProject
- Εξάρτημα
+ assembly.bom.partOrAssembly
+ Μέρος ή συναρμολόγηση
diff --git a/translations/messages.en.xlf b/translations/messages.en.xlf
index 57114e16..e541313b 100644
--- a/translations/messages.en.xlf
+++ b/translations/messages.en.xlf
@@ -10089,12 +10089,6 @@ Element 1 -> Element 1.2
Internal Part Number (IPN)
-
-
- assembly.edit.ipn
- Internal Part Number (IPN)
-
- assembly.status.draft
diff --git a/translations/messages.es.xlf b/translations/messages.es.xlf
index 50047268..999fd71a 100644
--- a/translations/messages.es.xlf
+++ b/translations/messages.es.xlf
@@ -10020,12 +10020,6 @@ Elemento 3
Número de Componente Interno (IPN)
-
-
- assembly.edit.ipn
- Número de Componente Interno (IPN)
-
- assembly.status.draft
diff --git a/translations/messages.it.xlf b/translations/messages.it.xlf
index 89c69f83..951a1bd3 100644
--- a/translations/messages.it.xlf
+++ b/translations/messages.it.xlf
@@ -10022,12 +10022,6 @@ Element 3
Codice interno (IPN)
-
-
- assembly.edit.ipn
- Codice interno (IPN)
-
- assembly.status.draft
diff --git a/translations/messages.pl.xlf b/translations/messages.pl.xlf
index 21ad869b..d9d4eac2 100644
--- a/translations/messages.pl.xlf
+++ b/translations/messages.pl.xlf
@@ -10025,12 +10025,6 @@ Element 3
Internal Part Number (IPN)
-
-
- assembly.edit.ipn
- Internal Part Number (IPN)
-
- assembly.status.draft
diff --git a/translations/messages.ru.xlf b/translations/messages.ru.xlf
index 5c4757f7..7ede4235 100644
--- a/translations/messages.ru.xlf
+++ b/translations/messages.ru.xlf
@@ -10029,12 +10029,6 @@
Внутренний номер компонента (IPN)
-
-
- assembly.edit.ipn
- Внутренний номер компонента (IPN)
-
- assembly.status.draft
@@ -13116,18 +13110,6 @@
Проект
-
-
- part.info.add_part_to_assembly
- Добавить эту часть в сборку
-
-
-
-
- assembly.bom.project
- Проект
-
- assembly.bom.referencedAssembly
diff --git a/translations/messages.zh.xlf b/translations/messages.zh.xlf
index 08cae400..a3e44de6 100644
--- a/translations/messages.zh.xlf
+++ b/translations/messages.zh.xlf
@@ -10028,12 +10028,6 @@ Element 3
内部零件号 (IPN)
-
-
- assembly.edit.ipn
- 内部零件号 (IPN)
-
- assembly.status.draft
diff --git a/translations/validators.da.xlf b/translations/validators.da.xlf
index bf4125fe..f30dd211 100644
--- a/translations/validators.da.xlf
+++ b/translations/validators.da.xlf
@@ -251,12 +251,6 @@
Du skal vælge en komponent eller angive et navn til en ikke-komponent styklistepost!
-
-
- validator.project.bom_entry.only_part_or_assembly_allowed
- Det er kun tilladt at vælge én del eller en samling. Venligst tilpas dit valg!
-
- project.bom_entry.name_already_in_bom
diff --git a/translations/validators.de.xlf b/translations/validators.de.xlf
index fec52c8e..8e6d7f02 100644
--- a/translations/validators.de.xlf
+++ b/translations/validators.de.xlf
@@ -251,12 +251,6 @@
Sie müssen ein Bauteil bzw. eine Baugruppe auswählen, oder einen Namen für ein nicht-Bauteil BOM-Eintrag setzen!
-
-
- validator.project.bom_entry.only_part_or_assembly_allowed
- Es darf nur ein Bauteil oder eine Baugruppe ausgewählt werden. Bitte passen Sie Ihre Auswahl an!
-
- project.bom_entry.name_already_in_bom
diff --git a/translations/validators.en.xlf b/translations/validators.en.xlf
index 08d3f2df..8bc34a33 100644
--- a/translations/validators.en.xlf
+++ b/translations/validators.en.xlf
@@ -251,12 +251,6 @@
You have to select a part or assembly, or set a name for a non-component Bom entry!
-
-
- validator.project.bom_entry.only_part_or_assembly_allowed
- Only one part or assembly may be selected. Please modify your selection!
-
- project.bom_entry.name_already_in_bom
@@ -429,7 +423,6 @@
validator.assembly.bom_entry.name_or_part_neededYou must select a part or set a name for the entry!
- You must select a part or set a name for the entry!
diff --git a/translations/validators.hr.xlf b/translations/validators.hr.xlf
index c14b86f1..485cb0e2 100644
--- a/translations/validators.hr.xlf
+++ b/translations/validators.hr.xlf
@@ -251,12 +251,6 @@
Morate odabrati dio za unos u BOM ili postaviti naziv za unos koji nije dio.
-
-
- validator.project.bom_entry.only_part_or_assembly_allowed
- Dozvoljeno je odabrati samo jednu komponentu ili sklop. Molimo prilagodite svoj odabir!
-
- project.bom_entry.name_already_in_bom
diff --git a/translations/validators.it.xlf b/translations/validators.it.xlf
index 7f88537c..74d3969f 100644
--- a/translations/validators.it.xlf
+++ b/translations/validators.it.xlf
@@ -251,12 +251,6 @@
È necessario selezionare un componente o assegnare un nome ad una voce BOM che non indica un componente!
-
-
- validator.project.bom_entry.only_part_or_assembly_allowed
- È consentito selezionare solo una parte o un assieme. Si prega di modificare la selezione!
-
- project.bom_entry.name_already_in_bom
diff --git a/translations/validators.pl.xlf b/translations/validators.pl.xlf
index 060de0e1..9916178c 100644
--- a/translations/validators.pl.xlf
+++ b/translations/validators.pl.xlf
@@ -251,12 +251,6 @@
Należy wybrać część dla wpisu BOM części lub ustawić nazwę dla wpisu BOM niebędącego częścią.
-
-
- validator.project.bom_entry.only_part_or_assembly_allowed
- Można wybrać tylko jedną część lub zespół. Proszę dostosować swój wybór!
-
- project.bom_entry.name_already_in_bom
diff --git a/translations/validators.ru.xlf b/translations/validators.ru.xlf
index e4a3199f..b8029e47 100644
--- a/translations/validators.ru.xlf
+++ b/translations/validators.ru.xlf
@@ -251,12 +251,6 @@
Вам необходимо выбрать компонент или задать имя для BOM, не относящейся к компоненту!
-
-
- validator.project.bom_entry.only_part_or_assembly_allowed
- Можно выбрать только деталь или сборку. Пожалуйста, измените ваш выбор!
-
- project.bom_entry.name_already_in_bom
diff --git a/translations/validators.zh.xlf b/translations/validators.zh.xlf
index 1844351e..6e4fc056 100644
--- a/translations/validators.zh.xlf
+++ b/translations/validators.zh.xlf
@@ -251,12 +251,6 @@
您必须为 BOM 条目选择部件,或为非部件 BOM 条目设置名称。
-
-
- validator.project.bom_entry.only_part_or_assembly_allowed
- 只能选择一个零件或组件。请修改您的选择!
-
- project.bom_entry.name_already_in_bom