diff --git a/src/Controller/BatchEdaController.php b/src/Controller/BatchEdaController.php new file mode 100644 index 00000000..65045a86 --- /dev/null +++ b/src/Controller/BatchEdaController.php @@ -0,0 +1,95 @@ +denyAccessUnlessGranted('@parts.edit'); + + $ids = $request->query->getString('ids', ''); + $redirectUrl = $request->query->getString('_redirect', ''); + + //Parse part IDs and load parts + $idArray = array_filter(array_map('intval', explode(',', $ids))); + $parts = $this->entityManager->getRepository(Part::class)->findBy(['id' => $idArray]); + + if ($parts === []) { + $this->addFlash('error', 'batch_eda.no_parts_selected'); + + return $redirectUrl !== '' ? $this->redirect($redirectUrl) : $this->redirectToRoute('parts_show_all'); + } + + $form = $this->createForm(BatchEdaType::class); + $form->handleRequest($request); + + if ($form->isSubmitted() && $form->isValid()) { + $updated = 0; + + foreach ($parts as $part) { + $this->denyAccessUnlessGranted('edit', $part); + $edaInfo = $part->getEdaInfo(); + + if ($form->get('apply_reference_prefix')->getData()) { + $edaInfo->setReferencePrefix($form->get('reference_prefix')->getData() ?: null); + $updated++; + } + if ($form->get('apply_value')->getData()) { + $edaInfo->setValue($form->get('value')->getData() ?: null); + $updated++; + } + if ($form->get('apply_kicad_symbol')->getData()) { + $edaInfo->setKicadSymbol($form->get('kicad_symbol')->getData() ?: null); + $updated++; + } + if ($form->get('apply_kicad_footprint')->getData()) { + $edaInfo->setKicadFootprint($form->get('kicad_footprint')->getData() ?: null); + $updated++; + } + if ($form->get('apply_visibility')->getData()) { + $edaInfo->setVisibility($form->get('visibility')->getData()); + $updated++; + } + if ($form->get('apply_exclude_from_bom')->getData()) { + $edaInfo->setExcludeFromBom($form->get('exclude_from_bom')->getData()); + $updated++; + } + if ($form->get('apply_exclude_from_board')->getData()) { + $edaInfo->setExcludeFromBoard($form->get('exclude_from_board')->getData()); + $updated++; + } + if ($form->get('apply_exclude_from_sim')->getData()) { + $edaInfo->setExcludeFromSim($form->get('exclude_from_sim')->getData()); + $updated++; + } + } + + $this->entityManager->flush(); + $this->addFlash('success', 'batch_eda.success'); + + return $redirectUrl !== '' ? $this->redirect($redirectUrl) : $this->redirectToRoute('parts_show_all'); + } + + return $this->render('parts/batch_eda_edit.html.twig', [ + 'form' => $form->createView(), + 'parts' => $parts, + 'redirect_url' => $redirectUrl, + ]); + } +} diff --git a/src/Form/Part/EDA/BatchEdaType.php b/src/Form/Part/EDA/BatchEdaType.php new file mode 100644 index 00000000..c5c839f2 --- /dev/null +++ b/src/Form/Part/EDA/BatchEdaType.php @@ -0,0 +1,112 @@ +add('reference_prefix', TextType::class, [ + 'label' => 'eda_info.reference_prefix', + 'required' => false, + 'attr' => ['placeholder' => t('eda_info.reference_prefix.placeholder')], + ]) + ->add('apply_reference_prefix', CheckboxType::class, [ + 'label' => 'batch_eda.apply', + 'required' => false, + 'mapped' => false, + ]) + ->add('value', TextType::class, [ + 'label' => 'eda_info.value', + 'required' => false, + 'attr' => ['placeholder' => t('eda_info.value.placeholder')], + ]) + ->add('apply_value', CheckboxType::class, [ + 'label' => 'batch_eda.apply', + 'required' => false, + 'mapped' => false, + ]) + ->add('kicad_symbol', KicadFieldAutocompleteType::class, [ + 'label' => 'eda_info.kicad_symbol', + 'type' => KicadFieldAutocompleteType::TYPE_SYMBOL, + 'required' => false, + 'attr' => ['placeholder' => t('eda_info.kicad_symbol.placeholder')], + ]) + ->add('apply_kicad_symbol', CheckboxType::class, [ + 'label' => 'batch_eda.apply', + 'required' => false, + 'mapped' => false, + ]) + ->add('kicad_footprint', KicadFieldAutocompleteType::class, [ + 'label' => 'eda_info.kicad_footprint', + 'type' => KicadFieldAutocompleteType::TYPE_FOOTPRINT, + 'required' => false, + 'attr' => ['placeholder' => t('eda_info.kicad_footprint.placeholder')], + ]) + ->add('apply_kicad_footprint', CheckboxType::class, [ + 'label' => 'batch_eda.apply', + 'required' => false, + 'mapped' => false, + ]) + ->add('visibility', TriStateCheckboxType::class, [ + 'label' => 'eda_info.visibility', + ]) + ->add('apply_visibility', CheckboxType::class, [ + 'label' => 'batch_eda.apply', + 'required' => false, + 'mapped' => false, + ]) + ->add('exclude_from_bom', TriStateCheckboxType::class, [ + 'label' => 'eda_info.exclude_from_bom', + ]) + ->add('apply_exclude_from_bom', CheckboxType::class, [ + 'label' => 'batch_eda.apply', + 'required' => false, + 'mapped' => false, + ]) + ->add('exclude_from_board', TriStateCheckboxType::class, [ + 'label' => 'eda_info.exclude_from_board', + ]) + ->add('apply_exclude_from_board', CheckboxType::class, [ + 'label' => 'batch_eda.apply', + 'required' => false, + 'mapped' => false, + ]) + ->add('exclude_from_sim', TriStateCheckboxType::class, [ + 'label' => 'eda_info.exclude_from_sim', + ]) + ->add('apply_exclude_from_sim', CheckboxType::class, [ + 'label' => 'batch_eda.apply', + 'required' => false, + 'mapped' => false, + ]) + ->add('submit', SubmitType::class, [ + 'label' => 'batch_eda.submit', + 'attr' => ['class' => 'btn btn-primary'], + ]); + } + + public function configureOptions(OptionsResolver $resolver): void + { + $resolver->setDefaults([ + 'data_class' => null, + ]); + } +} diff --git a/src/Services/Parts/PartsTableActionHandler.php b/src/Services/Parts/PartsTableActionHandler.php index 945cff7b..b0353e29 100644 --- a/src/Services/Parts/PartsTableActionHandler.php +++ b/src/Services/Parts/PartsTableActionHandler.php @@ -127,6 +127,15 @@ implode(',', array_map(static fn (PartLot $lot) => $lot->getID(), $part->getPart ); } + if ($action === 'batch_edit_eda') { + $ids = implode(',', array_map(static fn (Part $part) => $part->getID(), $selected_parts)); + return new RedirectResponse( + $this->urlGenerator->generate('batch_eda_edit', [ + '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 d7873498..90f8a3e1 100644 --- a/templates/components/datatables.macro.html.twig +++ b/templates/components/datatables.macro.html.twig @@ -62,6 +62,9 @@ + + + diff --git a/templates/parts/batch_eda_edit.html.twig b/templates/parts/batch_eda_edit.html.twig new file mode 100644 index 00000000..b1ca533c --- /dev/null +++ b/templates/parts/batch_eda_edit.html.twig @@ -0,0 +1,88 @@ +{% extends "main_card.html.twig" %} + +{% block title %}{% trans %}batch_eda.title{% endtrans %}{% endblock %} + +{% block card_title %} + {% trans %}batch_eda.title{% endtrans %} +{% endblock %} + +{% block card_content %} +
+

{% trans with {'%count%': parts|length} %}batch_eda.description{% endtrans %}

+
+ {% trans %}batch_eda.show_parts{% endtrans %} + +
+
+ + {{ form_start(form) }} + +

{% trans %}batch_eda.apply_hint{% endtrans %}

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
{% trans %}batch_eda.apply{% endtrans %}{% trans %}batch_eda.field{% endtrans %}{% trans %}batch_eda.value{% endtrans %}
{{ form_widget(form.apply_reference_prefix) }}{{ form_label(form.reference_prefix) }}{{ form_widget(form.reference_prefix, {'attr': {'class': 'form-control-sm'}}) }}{{ form_errors(form.reference_prefix) }}
{{ form_widget(form.apply_value) }}{{ form_label(form.value) }}{{ form_widget(form.value, {'attr': {'class': 'form-control-sm'}}) }}{{ form_errors(form.value) }}
{{ form_widget(form.apply_kicad_symbol) }}{{ form_label(form.kicad_symbol) }}{{ form_widget(form.kicad_symbol) }}{{ form_errors(form.kicad_symbol) }}
{{ form_widget(form.apply_kicad_footprint) }}{{ form_label(form.kicad_footprint) }}{{ form_widget(form.kicad_footprint) }}{{ form_errors(form.kicad_footprint) }}
{{ form_widget(form.apply_visibility) }}{{ form_label(form.visibility) }}{{ form_widget(form.visibility) }}
{{ form_widget(form.apply_exclude_from_bom) }}{{ form_label(form.exclude_from_bom) }}{{ form_widget(form.exclude_from_bom) }}
{{ form_widget(form.apply_exclude_from_board) }}{{ form_label(form.exclude_from_board) }}{{ form_widget(form.exclude_from_board) }}
{{ form_widget(form.apply_exclude_from_sim) }}{{ form_label(form.exclude_from_sim) }}{{ form_widget(form.exclude_from_sim) }}
+ +
+ {% if redirect_url %} + {% trans %}batch_eda.cancel{% endtrans %} + {% else %} + {% trans %}batch_eda.cancel{% endtrans %} + {% endif %} + {{ form_widget(form.submit) }} +
+ + {{ form_end(form) }} +{% endblock %} diff --git a/translations/messages.en.xlf b/translations/messages.en.xlf index 11c40831..ff3a2523 100644 --- a/translations/messages.en.xlf +++ b/translations/messages.en.xlf @@ -10917,6 +10917,84 @@ Please note, that you can not impersonate a disabled user. If you try you will g Bulk Info Provider Import + + + part_list.action.group.eda + EDA / KiCad + + + + + part_list.action.batch_edit_eda + Batch Edit EDA Fields + + + + + batch_eda.title + Batch Edit EDA Fields + + + + + batch_eda.description + Edit EDA/KiCad fields for %count% selected parts. Check the "Apply" box next to each field you want to change. + + + + + batch_eda.show_parts + Show selected parts + + + + + batch_eda.apply_hint + Only fields with the "Apply" checkbox checked will be changed. Unchecked fields are left unchanged. + + + + + batch_eda.apply + Apply + + + + + batch_eda.field + Field + + + + + batch_eda.value + Value + + + + + batch_eda.submit + Apply to Selected Parts + + + + + batch_eda.cancel + Cancel + + + + + batch_eda.success + EDA fields updated successfully. + + + + + batch_eda.no_parts_selected + No parts were selected for batch editing. + + info_providers.bulk_import.step1.spn_recommendation