diff --git a/src/Entity/ProjectSystem/Project.php b/src/Entity/ProjectSystem/Project.php index 54970b08..6b82454d 100644 --- a/src/Entity/ProjectSystem/Project.php +++ b/src/Entity/ProjectSystem/Project.php @@ -52,7 +52,7 @@ class Project extends AbstractStructuralDBElement protected $parent; /** - * @ORM\OneToMany(targetEntity="ProjectBOMEntry", mappedBy="project") + * @ORM\OneToMany(targetEntity="ProjectBOMEntry", mappedBy="project", cascade={"persist", "remove"}, orphanRemoval=true) */ protected $bom_entries; @@ -96,6 +96,23 @@ class Project extends AbstractStructuralDBElement $this->bom_entries = new ArrayCollection(); } + public function __clone() + { + //When cloning this project, we have to clone each bom entry too. + if ($this->id) { + $bom_entries = $this->bom_entries; + $this->bom_entries = new ArrayCollection(); + //Set master attachment is needed + foreach ($bom_entries as $bom_entry) { + $clone = clone $bom_entry; + $this->bom_entries->add($clone); + } + } + + //Parent has to be last call, as it resets the ID + parent::__clone(); + } + /** * Get the order quantity of this device. * @@ -154,20 +171,31 @@ class Project extends AbstractStructuralDBElement } /** - * @return mixed + * @return Collection|ProjectBOMEntry[] */ - public function getBomEntries() + public function getBomEntries(): Collection { return $this->bom_entries; } /** - * @param mixed $bom_entries - * @return Project + * @param ProjectBOMEntry $entry + * @return $this */ - public function setBomEntries($bom_entries) + public function addBomEntry(ProjectBOMEntry $entry): self { - $this->bom_entries = $bom_entries; + $entry->setProject($this); + $this->bom_entries->add($entry); + return $this; + } + + /** + * @param ProjectBOMEntry $entry + * @return $this + */ + public function removeBomEntry(ProjectBOMEntry $entry): self + { + $this->bom_entries->removeElement($entry); return $this; } diff --git a/src/Entity/ProjectSystem/ProjectBOMEntry.php b/src/Entity/ProjectSystem/ProjectBOMEntry.php index 77fe40f0..ad2e5af1 100644 --- a/src/Entity/ProjectSystem/ProjectBOMEntry.php +++ b/src/Entity/ProjectSystem/ProjectBOMEntry.php @@ -32,6 +32,7 @@ use Symfony\Component\Validator\Constraints as Assert; * The ProjectBOMEntry class represents a entry in a project's BOM. * * @ORM\Table("device_parts") + * @ORM\HasLifecycleCallbacks() * @ORM\Entity() */ class ProjectBOMEntry extends AbstractDBElement diff --git a/src/Form/AdminPages/ProjectAdminForm.php b/src/Form/AdminPages/ProjectAdminForm.php index f382ae6e..fdf53899 100644 --- a/src/Form/AdminPages/ProjectAdminForm.php +++ b/src/Form/AdminPages/ProjectAdminForm.php @@ -21,7 +21,9 @@ namespace App\Form\AdminPages; use App\Entity\Base\AbstractNamedDBElement; +use App\Form\ProjectSystem\ProjectBOMEntryType; use App\Form\Type\RichTextEditorType; +use Symfony\Component\Form\Extension\Core\Type\CollectionType; use Symfony\Component\Form\FormBuilderInterface; class ProjectAdminForm extends BaseEntityAdminForm @@ -38,5 +40,17 @@ class ProjectAdminForm extends BaseEntityAdminForm 'rows' => 2, ], ]); + + $builder->add('bom_entries', CollectionType::class, [ + 'entry_type' => ProjectBOMEntryType::class, + 'entry_options' => [ + 'label' => false, + ], + 'allow_add' => true, + 'allow_delete' => true, + 'by_reference' => false, + 'reindex_enable' => true, + 'label' => false, + ]); } } \ No newline at end of file diff --git a/src/Form/ProjectSystem/ProjectBOMEntryType.php b/src/Form/ProjectSystem/ProjectBOMEntryType.php new file mode 100644 index 00000000..a210fdfd --- /dev/null +++ b/src/Form/ProjectSystem/ProjectBOMEntryType.php @@ -0,0 +1,67 @@ +add('quantity', NumberType::class, [ + 'label' => 'project.bom.quantity', + ]) + + ->add('part', EntityType::class, [ + 'class' => Part::class, + 'choice_label' => 'name', + 'required' => false, + ]) + + ->add('name', TextType::class, [ + 'label' => 'project.bom.name', + 'required' => false, + 'empty_data' => '' + ]) + ->add('mountnames', TextType::class, [ + 'required' => false, + 'label' => 'project.bom.mountnames', + 'empty_data' => '', + 'attr' => [ + 'class' => 'tagsinput', + 'data-controller' => 'elements--tagsinput', + ] + ]) + ->add('comment', TextType::class, [ + 'required' => false, + 'label' => 'project.bom.comment', + 'empty_data' => '' + ]) + ; + + } + + public function configureOptions(OptionsResolver $resolver): void + { + $resolver->setDefaults([ + 'data_class' => ProjectBOMEntry::class, + ]); + } + + + public function getBlockPrefix() + { + return 'project_bom_entry'; + } +} \ No newline at end of file diff --git a/templates/AdminPages/DeviceAdmin.html.twig b/templates/AdminPages/DeviceAdmin.html.twig index b241f831..e40efea6 100644 --- a/templates/AdminPages/DeviceAdmin.html.twig +++ b/templates/AdminPages/DeviceAdmin.html.twig @@ -12,6 +12,32 @@ {% trans %}device.new{% endtrans %} {% endblock %} +{% block additional_pills %} + +{% endblock %} + {% block additional_controls %} {{ form_row(form.description) }} +{% endblock %} + +{% block additional_panes %} +
+ {% form_theme form.bom_entries with ['Form/collection_types_layout.html.twig'] %} + + {% import 'components/collection_type.macro.html.twig' as collection %} +
+ + + {% for attachment in form.bom_entries %} + {{ form_widget(attachment) }} + {% endfor %} + +
+ + +
+
{% endblock %} \ No newline at end of file diff --git a/templates/Form/collection_types_layout.html.twig b/templates/Form/collection_types_layout.html.twig new file mode 100644 index 00000000..def3d6e3 --- /dev/null +++ b/templates/Form/collection_types_layout.html.twig @@ -0,0 +1,15 @@ +{% block project_bom_entry_widget %} + {% import 'components/collection_type.macro.html.twig' as collection %} + + + {{ form_widget(form) }} + + + + {{ form_errors(form) }} + + +{% endblock %} \ No newline at end of file