diff --git a/public/assets/js/app.js b/public/assets/js/app.js index 38593d6c9786f9d0b0e4bc9cbfbfaf79176f3479..66c543c165f0b19e8a02172fc0ee827ab20d6edc 100644 --- a/public/assets/js/app.js +++ b/public/assets/js/app.js @@ -348,7 +348,7 @@ function initializeAjaxLinks() { if ($(this).data('json')) { data = JSON.stringify($(this).data('json')); } else { - data = $('#dynamicJson').val(); + data = $('#'+$(this).data('json-dynamic')).val(); } $.ajax({ diff --git a/src/Controller/ApiEntryController.php b/src/Controller/ApiEntryController.php index 45274e29934a19f3f01df6d4bc7b37d637075739..2e1f604f0218824ac26a171e489148ad3f6f7784 100644 --- a/src/Controller/ApiEntryController.php +++ b/src/Controller/ApiEntryController.php @@ -491,6 +491,8 @@ class ApiEntryController extends AppBaseController } /** + * Supprime une entrée d'un lexique, on détermine l'entrée à supprimer à partir de la graphie passée en paramètre + * * @Route("/delete", name="api_entry_delete", methods={"DELETE"}) * * @OA\Response( diff --git a/src/Controller/ApiLabelController.php b/src/Controller/ApiLabelController.php index c1d9dfb982a69fdb589b9f106716417261110459..a065ce31ae585752dd8343d4c26983a52b9c7a53 100644 --- a/src/Controller/ApiLabelController.php +++ b/src/Controller/ApiLabelController.php @@ -153,8 +153,8 @@ class ApiLabelController extends AppBaseController * @OA\RequestBody( * required=true, * @OA\JsonContent( - * required={"entries_ids"}, - * @OA\Property(property="entries_ids", type="array", + * required={"headwords_ids"}, + * @OA\Property(property="headwords_ids", type="array", * example={1, 2}, * @OA\Items( * type="integer" @@ -174,23 +174,23 @@ class ApiLabelController extends AppBaseController if (!$data) { return $this->createJsonResponse(401, ['error' => sprintf("Json non valide")]); } - if ($missingFields = $this->getMissingFields($data, ['entries_ids'])) { + if ($missingFields = $this->getMissingFields($data, ['headwords_ids'])) { return $this->createJsonResponse(401, ['error' => sprintf("Veuillez fournir une valeur pour: %s", implode(', ', $missingFields))]); } - // Pour chaque id d'entrée, on cherche l'entrée et on appose le label au headword correspondant - // On émet un avertissement pour chaque entrée non trouvée + // Pour chaque id de mot-vedette, on cherche le mot-vedette et on lui appose le label + // On émet un avertissement pour chaque headword non trouvé $count = 0; - foreach ($data['entries_ids'] as $entryId) { - $entry = $this->doctrine->getRepository(Entry::class)->find($entryId); - if ($entry) { - $entry->getHeadword()->addLabel($label); + foreach ($data['headwords_ids'] as $headwordId) { + $headword = $this->doctrine->getRepository(Headword::class)->find($headwordId); + if ($headword) { + $headword->addLabel($label); $count++; } else { - $this->warning[] = sprintf("Pas d'entrée trouvée pour l'id %s", $entryId); + $this->warning[] = sprintf("Pas de mot-vedette trouvé pour l'id %s", $headwordId); } } - $this->success[] = sprintf("Label %s ajouté à %s entrées", $label, $count); + $this->success[] = sprintf("Label %s ajouté à %s mots-vedettes", $label, $count); $this->doctrine->getManager()->flush(); diff --git a/src/Controller/EntryController.php b/src/Controller/EntryController.php index a78241fb0e9bb3940a386c20b18b8cef02646359..bba3a24cd70b3a70e6e508d974f6618fb82b73a9 100644 --- a/src/Controller/EntryController.php +++ b/src/Controller/EntryController.php @@ -81,7 +81,7 @@ class EntryController extends AppBaseController // $labels = $labelManager->getVisibleLabels($entry, $this->getUser(), $category); return $this->render('entry/_chooseLabel.html.twig', array( - 'entries_ids' => [$entry->getId()], + 'headwords_ids' => [$entry->getHeadword()->getId()], 'lexicon' => $entry->getLexicon(), 'entry' => $entry, 'category' => $category, diff --git a/templates/entry/_chooseLabel.html.twig b/templates/entry/_chooseLabel.html.twig index bba824866eecf7ac9b5d566c215ea957f7eff74a..786b20fad5c9cb182cf21ed1fa479a51ad487c59 100644 --- a/templates/entry/_chooseLabel.html.twig +++ b/templates/entry/_chooseLabel.html.twig @@ -35,25 +35,38 @@ {% set master = '' %} <div id="chooseLabelList"> {% for label in label_manager.visibleLabels(lexicon, app.user, category) %} -{# {% if label.master != master %}#} -{# <h5 class="mt-3">{{ label.master|trans|capitalize }}</h5>#} -{# {% endif %}#} - {# <a href="{{ path('app_entry_add_label', {id: entry.id, labelId: label.id}) }}">#} - {% if label not in entry.headword.labels %} + {% if entry|default(null) %} + + {% if label not in entry.headword.labels %} + <div class="mt-2"> + {# <a href="{{ path('app_entry_add_label', {id: entry.id, labelId: label.id}) }}">#} + <a class="ajax-link" href="#" data-method="POST" data-url="{{ path('label_add', {id: label.id}) }}" + data-json="{{ {headwords_ids: headwords_ids}|json_encode }}"> + {% include "label/_labelBadge.html.twig" %} + <i class="fa fa-lg fa-plus-circle text-success" style="margin-left: -8px"></i> + </a> + </div> + {% endif %} + + {% else %} {# actions sur uen sélection d'entrées : on affiche tous les labels et pour chacun un bouton "ajouter" et un bouton 'supprimer' #} + <div class="mt-2"> - <a class="ajax-link" href="#" data-method="POST" data-url="{{ path('label_add', {id: label.id}) }}" - {% if entries_ids|default(null) %}data-json="{{ {entries_ids: entries_ids}|json_encode }}"{% endif %} > - {% include "label/_labelBadge.html.twig" %} + {% include "label/_labelBadge.html.twig" %} + <a class="ajax-link" href="#" data-method="POST" data-url="{{ path('label_add', {id: label.id}) }}" data-json-dynamic="headwordsIds"> <i class="fa fa-lg fa-plus-circle text-success" style="margin-left: -8px"></i> </a> + <a class="ajax-link" href="#" data-method="DELETE" data-url="{{ path('label_remove', {id: label.id}) }}" data-json-dynamic="headwordsIds"> + <i class="fa fa-lg fa-times-circle text-danger" style="margin-left: -3px;"></i> + </a> </div> + {% endif %} - {% set master = label.master %} + {% endfor %} </div> - <input id="dynamicJson" type="hidden" value=""/> + <input id="headwordsIds" type="hidden" value=""/> <script> @@ -63,7 +76,7 @@ var selectedValues = $('[name="form[selected_entries][]"]:checked').map(function (i, element) { return $(element).val(); }).get(); - $('#dynamicJson').val(JSON.stringify({entries_ids: selectedValues})); + $('#headwordsIds').val(JSON.stringify({headwords_ids: selectedValues})); // searchbox pour filtrer les labels diff --git a/templates/lexicon/_selectionActions.html.twig b/templates/lexicon/_selectionActions.html.twig index 502e88105a7e59df5c30c3b96f613a41c13334a8..bb1b53747627c16937f7ab7c24030974253b44da 100644 --- a/templates/lexicon/_selectionActions.html.twig +++ b/templates/lexicon/_selectionActions.html.twig @@ -1,10 +1,25 @@ -<div class="row"> +<div id="selectionActions" class="row"> <div class="col-md-12"> <i>{{ "Avec la sélection"|trans }}:</i> {# ADD label Remosve LAbel, delete entries, export entries, connu, pas connu #} - <a 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_GENERAL")}) }}">{{ "Général"|trans }}</a> + <a title="{{ "Gestion des labels"|trans }}" + 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_GENERAL")}) }}"> + <i class="fa fa-tag"></i> {{ "Général"|trans }} + </a> + <a title="{{ "Gestion des labels"|trans }}" + 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_INSTITUTIONAL")}) }}"> + <i class="fa fa-tag"></i> {{ "Institutionnel"|trans }} + </a> + <a title="{{ "Gestion des labels"|trans }}" + 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> {# <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 2eff1eb98807cb5f32845d8fe0b28ac4916ad43d..c7d5d7ebf2299d60b7ecfd012b8d7b6ba0ab6871 100644 --- a/templates/lexicon/show.html.twig +++ b/templates/lexicon/show.html.twig @@ -64,11 +64,11 @@ <tr class="{{ known ? 'headword-known' }}"> <td>{{entry.addingOrder }}</td> <td class="d-flex justify-content-between"> - <span> + <label> <input class="me-2" type="checkbox" name="form[selected_entries][]" - value="{{ entry.id }}" id="form_selected_entries_{{ entry.id }}"/> + value="{{ entry.headword.id }}" id="form_selected_entries_{{ entry.id }}"/> {{ entry }} - </span> + </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 %} @@ -114,6 +114,8 @@ </div> </div> + <input id="entriesIds" type="hidden" value=""/> + {% endblock %} {% block javascripts %} @@ -122,6 +124,11 @@ <script type="text/javascript"> $(function() { + toggleSelectionActions(); + $('[name="form[selected_entries][]"]').on('change', function () { + toggleSelectionActions(); + }) + $('#toggle-known').on('click', function () { if ($(this).hasClass('collapsed')) { $('.headword-known').show('slow'); @@ -129,23 +136,42 @@ } else { $('.headword-known').hide('slow').find('input').prop("checked", false); $(this).addClass('collapsed'); + toggleSelectionActions(); } }) $('#selectNone').on('click', function() { $('input:checkbox').prop('checked', false); $('#selectModal').modal('hide'); + toggleSelectionActions(); }); $('#selectAll').on('click', function() { $('input:checkbox:visible').prop('checked', true); $('#selectModal').modal('hide'); + toggleSelectionActions(); }); $('#selectN').on('click', function(){ var nb = $(this).parent().find('input').val(); $('input:checkbox:visible').slice(0, nb).prop('checked', true); $('#selectModal').modal('hide'); + toggleSelectionActions(); }); }); + + function toggleSelectionActions() { + var $selected = $('[name="form[selected_entries][]"]:checked'); + if ($selected.length) { + $('#selectionActions').show(); + } else { + $('#selectionActions').hide(); + } + + // 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 = $selected.map(function (i, element) { + return $(element).val(); + }).get(); + $('#entriesIds').val(JSON.stringify({entries_ids: selectedValues})); + } </script> {% endblock %}