diff --git a/public/assets/js/app.js b/public/assets/js/app.js index 66c543c165f0b19e8a02172fc0ee827ab20d6edc..fd5681fbfae0f61ec7daea9f5891cc4f7a385e15 100644 --- a/public/assets/js/app.js +++ b/public/assets/js/app.js @@ -34,29 +34,16 @@ $(function() { $('body').on('click', ".modal-show, .modal-form", function (event) { openModal(event); }); - $('body').on('click', ".modal-inject-selection", function (event) { - var $link = $(this); - var selectionName = $(this).data('selection-name'); - var selectedValues = $('[name="'+selectionName+'"]:checked').map(function (i, element) { - return $(element).val(); - }).get(); - var myArrayQry = selectedValues.map(function(el, idx) { - return 'myArray[' + idx + ']=' + el; - }).join('&'); - $link.data('url', $link.data('url') + '?' + myArrayQry); -console.log($link.data('url'), myArrayQry); - openModal(event); - }); function openModal(e) { var appModal = $('#bootstrap-modal'); var url = $(e.currentTarget).attr('data-url'); var $overlay = $('#overlay').show(); var isForm = $(e.currentTarget).hasClass('modal-form'); - var joinPreviousForm = $(e.currentTarget).hasClass('join-previous-form'); + var extraFormId = $(e.currentTarget).data('extra-form-id'); - if (joinPreviousForm) { - url = url + (url.indexOf('?') >= 0 ? '&' : '?') + $('.form-to-join').serialize(); + if ($(extraFormId)) { + url = url + (url.indexOf('?') >= 0 ? '&' : '?') + $(extraFormId).serialize(); }; e.preventDefault(); diff --git a/src/Controller/AppBaseController.php b/src/Controller/AppBaseController.php index edd938f6cd8eb30a3132f9f7619c4f91006a7188..3851f0ea575fdcb74a11cff25e12056eb6fb912f 100644 --- a/src/Controller/AppBaseController.php +++ b/src/Controller/AppBaseController.php @@ -5,6 +5,7 @@ namespace App\Controller; use App\Entity\Entry; use App\Entity\Graphy; use App\Entity\Headword; +use App\Entity\HeadwordUserInfo; use App\Entity\Label; use App\Entity\Lexicon; use App\Entity\User; @@ -174,7 +175,7 @@ class AppBaseController extends AbstractController return false; } foreach ($array as $item) { - if (! is_int($item)) return false; + if (! ctype_digit((string)$item)) return false; } return true; } @@ -402,4 +403,35 @@ class AppBaseController extends AbstractController $sortingOrder = $session->get($discriminator . 'sortingOrder'); } } + + + // passe de connu à inconnu ou vice-versa. crée l'entité HeadwordUserInfo si besoin + public function toggleKnownOrCreateHeadwordUserInfo(Headword $headword, User $user) + { + $headwordUserInfo = $headword->getHeadwordUserInfoByUser($user); + if ($headwordUserInfo) { + $headwordUserInfo->setKnown(!$headwordUserInfo->isKnown()); + } else { + $headwordUserInfo = new HeadwordUserInfo(); + $this->em->persist($headwordUserInfo); + $headwordUserInfo->setUser($user); + $headwordUserInfo->setHeadword($headword); + $headwordUserInfo->setKnown(true); + } + } + + // passe au statut $statut. crée l'entité HeadwordUserInfo si besoin + public function setKnownStatusOrCreateHeadwordUserInfo(Headword $headword, User $user, $status) + { + $headwordUserInfo = $headword->getHeadwordUserInfoByUser($user); + if ($headwordUserInfo) { + $headwordUserInfo->setKnown($status); + } else { + $headwordUserInfo = new HeadwordUserInfo(); + $this->em->persist($headwordUserInfo); + $headwordUserInfo->setUser($user); + $headwordUserInfo->setHeadword($headword); + $headwordUserInfo->setKnown($status); + } + } } diff --git a/src/Controller/HeadwordController.php b/src/Controller/HeadwordController.php index 388386d13b90047fff0ebbdb03a6e7d7483239cf..9f3d85a859392184eaa0cf5f07ff29c95f42a0bd 100644 --- a/src/Controller/HeadwordController.php +++ b/src/Controller/HeadwordController.php @@ -23,7 +23,7 @@ use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter; /** * @Route("/headword") */ -class HeadwordController extends AbstractController +class HeadwordController extends AppBaseController { // /** // * @Route("/", name="app_headword_index", methods={"GET"}) @@ -57,20 +57,11 @@ class HeadwordController extends AbstractController * @ParamConverter("user", options={"id" = "userId"}) * */ - public function toggleKnown(ManagerRegistry $doctrine, Request $request, Headword $headword, User $user): Response + public function toggleKnown(Request $request, Headword $headword, User $user): Response { - $headwordUserInfo = $headword->getHeadwordUserInfoByUser($user); - if ($headwordUserInfo) { - $headwordUserInfo->setKnown(!$headwordUserInfo->isKnown()); - } else { - $headwordUserInfo = new HeadwordUserInfo(); - $doctrine->getManager()->persist($headwordUserInfo); - $headwordUserInfo->setUser($user); - $headwordUserInfo->setHeadword($headword); - $headwordUserInfo->setKnown(true); - } + $this->toggleKnownOrCreateHeadwordUserInfo($headword, $user); - $doctrine->getManager()->flush(); + $this->em->flush(); return $this->redirectToRoute('app_lexicon_show', ['id' => $request->get('lexiconId')]); } diff --git a/src/Controller/LexiconController.php b/src/Controller/LexiconController.php index d26030e1da08e08f321f815984eef00ee212b885..7f7729456ea22b73a608f4e8b4f659eefa0b4c49 100644 --- a/src/Controller/LexiconController.php +++ b/src/Controller/LexiconController.php @@ -6,8 +6,10 @@ use App\Entity\Entry; use App\Entity\Label; use App\Entity\Lexicon; use App\Entity\Log; +use App\Form\CopyEntriesType; use App\Form\SearchStringType; use App\Manager\LabelManager; +use App\Repository\EntryRepository; use App\Repository\LexiconRepository; use Doctrine\Persistence\ManagerRegistry; use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted; @@ -85,4 +87,102 @@ class LexiconController extends AppBaseController )); } + /** + * @Route("/{id}/process-selected-entries", name="app_lexicon_process_selected_entries") + */ + public function processSelectedEntries(Request $request, EntryRepository $entryRepository, Lexicon $lexicon) + { + $formData = $request->get('form'); + $selectedIds = $formData['selected_entries'] ?? null; + + if ($selectedIds) { + + if ($request->request->has('delete_entries')) { + foreach ($selectedIds as $selectedId) { + $entry = $entryRepository->find($selectedId); + $entryRepository->remove($entry); + } + $this->em->flush(); + } + + if ($request->request->has('known_entries')) { + foreach ($selectedIds as $selectedId) { + $entry = $entryRepository->find($selectedId); + $headword = $entry->getHeadword(); + $this->setKnownStatusOrCreateHeadwordUserInfo($headword, $this->getUser(), true); + } + $this->em->flush(); + } + + if ($request->request->has('unknown_entries')) { + foreach ($selectedIds as $selectedId) { + $entry = $entryRepository->find($selectedId); + $headword = $entry->getHeadword(); + $this->setKnownStatusOrCreateHeadwordUserInfo($headword, $this->getUser(), false); + } + $this->em->flush(); + } + + } + + return $this->redirectToRoute('app_lexicon_show', array( + 'id' => $lexicon->getId(), + )); + } + + /** + * @Route("/{id}/copy-entries", name="app_lexicon_copy_entries") + */ + public function copySelection(LabelManager $labelManager, Request $request, Lexicon $lexicon, EntryRepository $entryRepository) + { + $formData = $request->get('form'); + $selectedIds = $formData['selected_entries'] ?? null; + + $form = $this->createForm(CopyEntriesType::class, null, [ + 'action' => $this->generateUrl('app_lexicon_copy_entries', [ + 'id' => $lexicon->getId(), + 'selectedIds' => $selectedIds, + ]), + 'originLexicon' => $lexicon, + ]); + $form->handleRequest($request); + + if ($form->isSubmitted() && $form->isValid()) { + $forwardRequest = Request::create( + $this->generateUrl('api_copy_entries'), 'POST', [], [], [], [], + json_encode([ + 'entries' => $request->get('selectedIds'), + 'merge' => $form->get('merge')->getData(), + 'target_lex' => [$form->get('lexicon')->getData()->getId()], + ]) + ); + + $response = $this->forward('App\Controller\ApiEntryController::copyEntries', array( + 'request' => $forwardRequest, +// '_route' => $request->attributes->get('_route'), +// '_route_params' => $request->attributes->get('_route_params'), + )); + + if ($response->getStatusCode() == 200) { + $this->addFlash('success', "Copie effectuée"); + } else { + $message = (array) json_decode($response->getContent()); + $this->addFlash('danger', reset($message) ?? 'Requête terminée'); + } + + return $this->render('closeModalAndReload.html.twig'); + } + + $this->addFlash('info', sprintf("<strong>Fusion :</strong> + <br><i>« Overwrite » :</i> On remplace l'entrée cible si elle existe + <br><i>« Ignore » :</i> On ne fait rien si l'entrée cible existe + <br><i>« Merge » :</i> On fusionne les 2 entrées + ")); + + return $this->render('genericModalForm.html.twig', [ + 'title' => "Copie des entrées vers un autre lexique", + 'form' => $form->createView(), + ]); + } + } diff --git a/src/Entity/Lexicon.php b/src/Entity/Lexicon.php index f6b055df7824bd0b1588051cf8e56eabe6765e96..7e12d0d8220ed61cd8110b41f994deb554f540a8 100644 --- a/src/Entity/Lexicon.php +++ b/src/Entity/Lexicon.php @@ -37,6 +37,12 @@ class Lexicon self::MERGE_OVERWRITE, self::MERGE_IGNORE, self::MERGE_MERGE ]; + const MERGE_MODES_FORMATTED = [ + "Ignore" => self::MERGE_IGNORE, + "Overwrite" => self::MERGE_OVERWRITE, + "Merge" => self::MERGE_MERGE + ]; + /** * @ORM\Id * @ORM\GeneratedValue diff --git a/src/Form/CopyEntriesType.php b/src/Form/CopyEntriesType.php new file mode 100644 index 0000000000000000000000000000000000000000..de6b475b6dd17a283c942e92cd51c80a381ace69 --- /dev/null +++ b/src/Form/CopyEntriesType.php @@ -0,0 +1,76 @@ +<?php + +namespace App\Form; + +use App\Entity\Group; +use App\Entity\Lexicon; +use App\Entity\User; +use App\Languages\LanguagesIso; +use App\Repository\LexiconRepository; +use Symfony\Bridge\Doctrine\Form\Type\EntityType; +use Symfony\Component\Form\AbstractType; +use Symfony\Component\Form\Extension\Core\Type\ChoiceType; +use Symfony\Component\Form\Extension\Core\Type\SubmitType; +use Symfony\Component\Form\Extension\Core\Type\TextType; +use Symfony\Component\Form\FormBuilderInterface; +use Symfony\Component\OptionsResolver\OptionsResolver; +use Symfony\Component\Security\Core\Security; +use Symfony\Component\Validator\Constraints\NotBlank; + +class CopyEntriesType extends AbstractType +{ + /** + * @var Security + */ + protected $security; + + public function __construct(Security $security) + { + $this->security = $security; + } + + public function buildForm(FormBuilderInterface $builder, array $options): void + { + $originLexicon = $options['originLexicon']; + $user = $this->security->getUser(); + $lexicons = array_diff($user->getMyLexicons(), [$originLexicon]); + + $builder + ->add('lexicon', EntityType::class, [ + 'class' => Lexicon::class, + 'constraints' => [ + new NotBlank([ + 'message' => 'Veuillez choisir un lexique de destination', + ]), + ], + 'label' => 'Lexique de destination', + 'choices' => $lexicons, + ]) + ->add('merge', ChoiceType::class, [ + 'constraints' => [ + new NotBlank([ + 'message' => 'Veuillez choisir un paramètre de fusion', + ]), + ], + 'label' => 'Fusion', + 'choices' => Lexicon::MERGE_MODES_FORMATTED, + ]) + ->add('submit', SubmitType::class, [ + 'label' => 'Enregistrer', + 'attr' => ['class' => 'btn-dark'] + ]) + ; + } + + public function configureOptions(OptionsResolver $resolver): void + { + $resolver->setDefaults([ + 'originLexicon' => null, + 'attr' => [ + 'data-ajax-form' => '', + 'data-ajax-form-target' => '#bootstrap-modal .modal-content', + 'novalidate' => 'novalidate', + ], + ]); + } +} diff --git a/templates/closeModalAndReload.html.twig b/templates/closeModalAndReload.html.twig new file mode 100644 index 0000000000000000000000000000000000000000..008ce6ad81d812c167045eef724cf5acb1e51bd7 --- /dev/null +++ b/templates/closeModalAndReload.html.twig @@ -0,0 +1,6 @@ +<script type="text/javascript"> + $(function () { + $('#bootstrap-modal').modal('hide'); + location.reload(); + }); +</script> \ No newline at end of file diff --git a/templates/entry/_chooseLabel.html.twig b/templates/entry/_chooseLabel.html.twig index 786b20fad5c9cb182cf21ed1fa479a51ad487c59..9aae5fc0619237b30dee44609176a4dfdee35792 100644 --- a/templates/entry/_chooseLabel.html.twig +++ b/templates/entry/_chooseLabel.html.twig @@ -74,7 +74,7 @@ // création du json qui sera récupéré par les liens ajax-link à partir des entrées sélectionnées, si pas de tag data-json sur le lien ajax-link var selectedValues = $('[name="form[selected_entries][]"]:checked').map(function (i, element) { - return $(element).val(); + return $(element).data('headword-id'); }).get(); $('#headwordsIds').val(JSON.stringify({headwords_ids: selectedValues})); diff --git a/templates/flashes.html.twig b/templates/flashes.html.twig new file mode 100644 index 0000000000000000000000000000000000000000..2fb995933d7ba926b55fea091ac476085ceca9eb --- /dev/null +++ b/templates/flashes.html.twig @@ -0,0 +1,15 @@ +<div class="row"> + <div class="col-md-12"> + {% if app.session.started %} + {% for type, flashes in app.session.flashbag.all %} + {% for message in flashes %} + <div class="alert alert-{{ type }} alert-dismissible fade show" role="alert"> + {{ message|trans|raw }} + <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button> + </div> + {% endfor %} + {% endfor %} + + {% endif %} + </div> +</div> \ No newline at end of file diff --git a/templates/genericModalForm.html.twig b/templates/genericModalForm.html.twig index 3e3c1c793f5270cd6b3feb7358b5b5c569b0bf75..afa15982140f49a37e4db78bd98358131cbd7c4a 100644 --- a/templates/genericModalForm.html.twig +++ b/templates/genericModalForm.html.twig @@ -2,7 +2,7 @@ {% block modal_title %} {% if title|default(false) %} - {{ title|raw }} + {{ title|raw|trans }} {% else %} {{ 'Modification'|trans }} {% endif %} @@ -11,6 +11,9 @@ {% block modal_body %} <div class="row"> <div class="col-md-12"> + + {% include "flashes.html.twig" %} + {{ form_start(form) }} {{ form_errors(form) }} {% for child in form %} @@ -22,7 +25,7 @@ <div class="col-sm-4"></div> <div class="col-sm-8"> {{ form_widget(form.submit) }} - <button type="button" class="btn btn-ap" data-dismiss="modal">{{ 'Annuler'|trans }}</button> + <button type="button" class="btn btn-light" data-bs-dismiss="modal">{{ 'Annuler'|trans }}</button> </div> </div> {{ form_end(form) }} diff --git a/templates/lexicon/_selectionActions.html.twig b/templates/lexicon/_selectionActions.html.twig index bb1b53747627c16937f7ab7c24030974253b44da..36d94c38968ff46f4539691bc7e7cdc2b8f6a5a6 100644 --- a/templates/lexicon/_selectionActions.html.twig +++ b/templates/lexicon/_selectionActions.html.twig @@ -16,10 +16,23 @@ href="#" class="modal-form btn btn-dark btn-sm" data-url="{{ path('app_lexicon_choose_label', {id: lexicon.id, category: constant("App\\Entity\\Label::LABEL_CATEGORY_MILESTONE")}) }}"> <i class="fa fa-tag"></i> {{ "Échéance"|trans }} </a> - <a title="{{ "Supprimer les entrées"|trans }}" - href="#" class="ajax-link btn btn-dark btn-sm" data-method="POST" data-url="{{ path('label_add', {id: label.id}) }}" data-json-dynamic="entriesIds"> - <i class="fa fa-trash"></i> +{# <a title="{{ "Supprimer les entrées"|trans }}"#} +{# href="#" class="ajax-link btn btn-dark btn-sm" data-method="POST" data-url="{{ path('label_add', {id: label.id}) }}" data-json-dynamic="entriesIds">#} +{# <i class="fa fa-trash"></i>#} +{# </a>#} + <button title="{{ "Marquer les entrées comme connues"|trans }}" type="submit" name="known_entries" class="btn btn-light btn-sm"> + <i class="fa fa-circle text-success"></i> + </button> + <button title="{{ "Marquer les entrées comme non connues"|trans }}" type="submit" name="unknown_entries" class="btn btn-light btn-sm"> + <i class="fa fa-circle text-warning"></i> + </button> + <a title="{{ "Exporter les entrées vers un autre lexique"|trans }}" href="#" class="modal-form btn btn-light btn-sm" + data-extra-form-id="#entriesSelection" data-url="{{ path('app_lexicon_copy_entries', {id: lexicon.id}) }}"> + <i class="fa fa-external-link"></i> </a> + <button title="{{ "Supprimer les entrées"|trans }}" type="submit" name="delete_entries" class="btn btn-light btn-sm"> + <i class="fa fa-trash"></i> + </button> {# <div class="dropdown">#} {# <button class="btn btn-secondary dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false">#} diff --git a/templates/lexicon/show.html.twig b/templates/lexicon/show.html.twig index c7d5d7ebf2299d60b7ecfd012b8d7b6ba0ab6871..42ff4a7131eacbe5cae73644581d3851d476c76c 100644 --- a/templates/lexicon/show.html.twig +++ b/templates/lexicon/show.html.twig @@ -31,82 +31,87 @@ <div class="row mt-4"> <div class="col-md-12"> - <table class="table table-bordered"> - <thead> - <tr> - <th colspan="2" class="text-center">{{ "Mot-vedette"|trans }}</th> - <th colspan="3" class="text-center">{{ "Labels"|trans }}</th> - <th></th> - {% if not lexicon.user %} + <form name="entries_selection" id="entriesSelection" action="{{ path('app_lexicon_process_selected_entries', {id: lexicon.id}) }}" method="post" novalidate="novalidate" autocomplete="off"> + + <table class="table table-bordered"> + <thead> + <tr> + <th colspan="2" class="text-center">{{ "Mot-vedette"|trans }}</th> + <th colspan="3" class="text-center">{{ "Labels"|trans }}</th> <th></th> - {% endif %} - </tr> - <tr> - <th>{{ macros.sorting_column_with_filter("Ajout"|trans, 'createdAt', _context, {id: lexicon.id}) }}</th> - <th class="d-flex justify-content-between"> - <i id="super-select" class="fa fa-square-o" data-bs-toggle="modal" data-bs-target="#selectModal"></i> - {{ macros.sorting_column_with_filter('<i class="fa fa-sort-alpha-asc"></i>', 'value', _context, {id: lexicon.id}) }} - <i id="toggle-known" class="fa fa-eye"></i> - </th> - <th>{{ "Général"|trans }}</th> - <th>{{ "Institutionnel"|trans }}</th> - <th>{{ "Échéance"|trans }}</th> - <th>Définitions</th> - {% if not lexicon.user %} - <th class="text-center"><i class="fa fa-user-circle"></i></th> - {% endif %} - </tr> - </thead> - <tbody> - {% for entry in entries %} - {# @var entry \App\Entity\Entry #} - {% set known = entry.headword.knownByUser(app.user) %} - <tr class="{{ known ? 'headword-known' }}"> - <td>{{entry.addingOrder }}</td> - <td class="d-flex justify-content-between"> - <label> - <input class="me-2" type="checkbox" name="form[selected_entries][]" - value="{{ entry.headword.id }}" id="form_selected_entries_{{ entry.id }}"/> - {{ entry }} - </label> - <a title="{{ known ? 'Mot-vedette connu. Cliquer pour modifier'|trans : 'Mot-vedette connu. Cliquer pour modifier'|trans }}" - href="{{ path('app_headword_toggle_known', {id: entry.headword.id, userId: app.user.id, lexiconId: lexicon.id}) }}"> - {% if known %}<i class="fa fa-circle text-success"></i>{% else %}<i class="fa fa-circle text-warning"></i>{% endif %} - </a> - </td> -{# <td>{% for label in entry.headword.morphologicalLabels %}<span class="badge bg-primary">{{ label }}</span> {% endfor %}</td>#} - <td class="col-md-2 modal-form" data-url="{{ path('app_entry_choose_label', {id: entry.id, category: constant("App\\Entity\\Label::LABEL_CATEGORY_GENERAL")}) }}"> - {% for label in entry.headword.generalLabels %}<span class="blink-target">{% include "label/_labelBadge.html.twig" %}</span>{% endfor %} - </td> - <td class="col-md-2 modal-form" data-url="{{ path('app_entry_choose_label', {id: entry.id, category: constant("App\\Entity\\Label::LABEL_CATEGORY_INSTITUTIONAL")}) }}"> - {% for label in entry.headword.institutionalLabels %}<span class="blink-target">{% include "label/_labelBadge.html.twig" %}</span>{% endfor %} - </td> - <td class="col-md-2 modal-form" data-url="{{ path('app_entry_choose_label', {id: entry.id, category: constant("App\\Entity\\Label::LABEL_CATEGORY_MILESTONE")}) }}"> - {% for label in entry.headword.milestoneLabels %}<span class="blink-target">{% include "label/_labelBadge.html.twig" %}</span>{% endfor %} - </td> - <td> - {% for pos, definition in entry.formattedDefinitions %} - <a class="text-decoration-none" data-bs-toggle="collapse" href="#def-{{ entry.id }}-{{ loop.index }}" role="button" aria-expanded="false" aria-controls="collapseExample"> - <span class="badge bg-definition text-black"><i class="bi-caret-right-fill"></i> {{ pos }}</span> + {% if not lexicon.user %} + <th></th> + {% endif %} + </tr> + <tr> + <th>{{ macros.sorting_column_with_filter("Ajout"|trans, 'createdAt', _context, {id: lexicon.id}) }}</th> + <th class="d-flex justify-content-between"> + <i id="super-select" class="fa fa-square-o" data-bs-toggle="modal" data-bs-target="#selectModal"></i> + {{ macros.sorting_column_with_filter('<i class="fa fa-sort-alpha-asc"></i>', 'value', _context, {id: lexicon.id}) }} + <i id="toggle-known" class="fa fa-eye"></i> + </th> + <th>{{ "Général"|trans }}</th> + <th>{{ "Institutionnel"|trans }}</th> + <th>{{ "Échéance"|trans }}</th> + <th>Définitions</th> + {% if not lexicon.user %} + <th class="text-center"><i class="fa fa-user-circle"></i></th> + {% endif %} + </tr> + </thead> + <tbody> + {% for entry in entries %} + {# @var entry \App\Entity\Entry #} + {% set known = entry.headword.knownByUser(app.user) %} + <tr class="{{ known ? 'headword-known' }}"> + <td>{{entry.addingOrder }}</td> + <td class="d-flex justify-content-between"> + <label> + {# "value" est utilisé par Symfo quand on soumet le form. "data-headword-id" est utilisé par la vue chooseLabel pour injecter du json dans le sliens ajax #} + <input class="me-2" type="checkbox" name="form[selected_entries][]" data-headword-id="{{ entry.headword.id }}" + value="{{ entry.id }}" id="form_selected_entries_{{ entry.id }}"/> + {{ entry }} + </label> + <a title="{{ known ? 'Mot-vedette connu. Cliquer pour modifier'|trans : 'Mot-vedette connu. Cliquer pour modifier'|trans }}" + href="{{ path('app_headword_toggle_known', {id: entry.headword.id, userId: app.user.id, lexiconId: lexicon.id}) }}"> + {% if known %}<i class="fa fa-circle text-success"></i>{% else %}<i class="fa fa-circle text-warning"></i>{% endif %} </a> - <div class="collapse" id="def-{{ entry.id }}-{{ loop.index }}"> - <div class="card card-body card-definition"> - {{ definition }} + </td> + {# <td>{% for label in entry.headword.morphologicalLabels %}<span class="badge bg-primary">{{ label }}</span> {% endfor %}</td>#} + <td class="col-md-2 modal-form" data-url="{{ path('app_entry_choose_label', {id: entry.id, category: constant("App\\Entity\\Label::LABEL_CATEGORY_GENERAL")}) }}"> + {% for label in entry.headword.generalLabels %}<span class="blink-target">{% include "label/_labelBadge.html.twig" %}</span>{% endfor %} + </td> + <td class="col-md-2 modal-form" data-url="{{ path('app_entry_choose_label', {id: entry.id, category: constant("App\\Entity\\Label::LABEL_CATEGORY_INSTITUTIONAL")}) }}"> + {% for label in entry.headword.institutionalLabels %}<span class="blink-target">{% include "label/_labelBadge.html.twig" %}</span>{% endfor %} + </td> + <td class="col-md-2 modal-form" data-url="{{ path('app_entry_choose_label', {id: entry.id, category: constant("App\\Entity\\Label::LABEL_CATEGORY_MILESTONE")}) }}"> + {% for label in entry.headword.milestoneLabels %}<span class="blink-target">{% include "label/_labelBadge.html.twig" %}</span>{% endfor %} + </td> + <td> + {% for pos, definition in entry.formattedDefinitions %} + <a class="text-decoration-none" data-bs-toggle="collapse" href="#def-{{ entry.id }}-{{ loop.index }}" role="button" aria-expanded="false" aria-controls="collapseExample"> + <span class="badge bg-definition text-black"><i class="bi-caret-right-fill"></i> {{ pos }}</span> + </a> + <div class="collapse" id="def-{{ entry.id }}-{{ loop.index }}"> + <div class="card card-body card-definition"> + {{ definition }} + </div> </div> - </div> - {% endfor %} - </td> - {% if not lexicon.user %} - <td class="text-center">{{ entry.createdBy|badge }}</td> - {% endif %} -{# <td>{{ entry.createdAt ? entry.createdAt|date('Y-m-d H:i:s') : '' }}</td>#} -{# <td>{{ entry.updatedAt ? entry.updatedAt|date('Y-m-d H:i:s') : '' }}</td>#} - </tr> - {% endfor %} - </tbody> - </table> - - {% include "lexicon/_selectionActions.html.twig" %} + {% endfor %} + </td> + {% if not lexicon.user %} + <td class="text-center">{{ entry.createdBy|badge }}</td> + {% endif %} + {# <td>{{ entry.createdAt ? entry.createdAt|date('Y-m-d H:i:s') : '' }}</td>#} + {# <td>{{ entry.updatedAt ? entry.updatedAt|date('Y-m-d H:i:s') : '' }}</td>#} + </tr> + {% endfor %} + </tbody> + </table> + + {% include "lexicon/_selectionActions.html.twig" %} + + </form> </div> </div> @@ -114,6 +119,7 @@ </div> </div> +{# Pas utilisé pour l'instant #} <input id="entriesIds" type="hidden" value=""/> {% endblock %} @@ -168,6 +174,7 @@ } // création du json qui sera récupéré par les liens ajax-link à partir des entrées sélectionnées, si pas de tag data-json sur le lien ajax-link + // PAS UTILISÉ POUR L'INSTANT var selectedValues = $selected.map(function (i, element) { return $(element).val(); }).get();