From a622b3c2567351f3306c521439a0fbd7e0d0454e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20P?= <nicolo.paraciani@cnr.it> Date: Sat, 9 Nov 2024 11:18:45 +0100 Subject: [PATCH] Implement vocab delete in Stimulus TODO: show modal warning before deleting --- assets/controllers/vocabs_controller.js | 59 +++++++++++++++---- templates/vocab_func_context/index.html.twig | 61 +++++++++++++++----- 2 files changed, 96 insertions(+), 24 deletions(-) diff --git a/assets/controllers/vocabs_controller.js b/assets/controllers/vocabs_controller.js index 310925e..6516e46 100644 --- a/assets/controllers/vocabs_controller.js +++ b/assets/controllers/vocabs_controller.js @@ -18,10 +18,10 @@ export default class extends Controller { * @todo Simpler way? */ edit(event) { - const id = event.currentTarget.getAttribute('data-vocabs-id-value'); + const id = event.currentTarget.getAttribute('data-id'); this.saveTargets.forEach((btn, index) => { - if (btn.getAttribute('data-vocabs-id-value') === id) { + if (btn.getAttribute('data-id') === id) { btn.classList.toggle('is-hidden'); this.inputTargets[index].disabled = false; this.cancelTargets[index].classList.toggle('is-hidden'); @@ -32,11 +32,11 @@ export default class extends Controller { } async save(event) { - const id = event.currentTarget.getAttribute('data-vocabs-id-value'); + const id = event.currentTarget.getAttribute('data-id'); let term = ''; for (let input of this.inputTargets) { - if (input.getAttribute('data-vocabs-id-value') === id) { + if (input.getAttribute('data-id') === id) { term = input.value; } } @@ -45,25 +45,62 @@ export default class extends Controller { data.append("_id", id); data.append("_new_term", term); - const res = await fetch(this.saveUrlValue, { + const url = event.currentTarget.getAttribute('data-url'); + + const res = await fetch(url, { method: "POST", body: data, }); - // TODO: show notification if (res.status === 200) { - console.log('Saved...'); + let notif = document.getElementById('ajax-saved'); + notif.classList.toggle('is-hidden'); }; - } - delete() { + this.cancelTargets.find(btn => btn.getAttribute('data-id') === id) + .classList.toggle('is-hidden'); + + this.editTargets.find(btn => btn.getAttribute('data-id') === id) + .classList.toggle('is-hidden'); + const input = this.inputTargets.find(input => input.getAttribute('data-id') === id) + input.disabled = true; + event.target.classList.toggle('is-hidden'); + + } + /** + * + * @todo Show modal before deleting! Show delete error (500)! + */ + async delete(event) { + const id = event.currentTarget.getAttribute('data-id'); + const url = event.currentTarget.getAttribute('data-url'); + + let data = new FormData; + data.append("_id", id); + + const res = await fetch(url, { + method: "POST", + body: data, + }); + + if (res.status === 200) { + let notif = document.getElementById('ajax-deleted'); + notif.classList.toggle('is-hidden'); + this.rowTargets.find(row => row.getAttribute('data-id') === id) + .classList.add('is-hidden'); + }; + + if (res.status === 500) { + let notif = document.getElementById('ajax-error'); + notif.classList.toggle('is-hidden'); + } } cancel(event) { - const id = event.currentTarget.getAttribute('data-vocabs-id-value'); + const id = event.currentTarget.getAttribute('data-id'); this.editTargets.forEach((btn, index) => { - if (btn.getAttribute('data-vocabs-id-value') === id) { + if (btn.getAttribute('data-id') === id) { btn.classList.toggle('is-hidden'); this.inputTargets[index].disabled = true; this.saveTargets[index].classList.toggle('is-hidden'); diff --git a/templates/vocab_func_context/index.html.twig b/templates/vocab_func_context/index.html.twig index 94338ff..0f1f691 100644 --- a/templates/vocab_func_context/index.html.twig +++ b/templates/vocab_func_context/index.html.twig @@ -3,7 +3,7 @@ {% block title %}Vocab - Functional context | ArCOA{% endblock %} {% block rightpanel %} -<div class="container" style="max-width: 50vw"> +<div class="container" style="max-width: 50vw" data-controller="vocabs"> <h1 class="is-size-1 mt-0 has-text-centered">Vocabulary</h1> <h2 class="is-size-3 mt-4 has-text-centered">Functional context</h2> @@ -30,8 +30,24 @@ <div class="notification is-success is-hidden mt-5" data-controller="notification" - data-notification-target=""="notif"> + data-notification-target="notif" + id="ajax-saved"> <button class="delete" data-action="click->notification#close"></button> + Term saved successfully + </div> + <div class="notification is-success is-hidden mt-5" + data-controller="notification" + data-notification-target="notif" + id="ajax-deleted"> + <button class="delete" data-action="click->notification#close"></button> + Term deleted successfully + </div> + <div class="notification is-danger is-light is-hidden mt-5" + data-controller="notification" + data-notification-target="notif" + id="ajax-error"> + <button class="delete" data-action="click->notification#close"></button> + The term could not be deleted because it's related to existing records </div> {% for message in app.flashes('notice') %} <div class="notification is-success mt-5" data-controller="notification" @@ -41,14 +57,14 @@ </div> {% endfor %} <h3 class="mt-6 mb-5 is-size-5"><strong>Terms in vocabulary</strong></h3> - <table class="table is-fullwidth" id="terms" data-controller="vocabs"> + <table class="table is-fullwidth" id="terms"> <tr><th>Term</th>{% if is_granted('ROLE_ADMIN') or is_granted('ROLE_REVISOR') %}<th>Actions</th>{% endif %}</tr> {% for term in terms %} <tr data-vocabs-target="row" - data-vocabs-id-value="{{ term.id }}"> + data-id="{{ term.id }}"> <td> <input class="input" type="text" value="{{ term.term }}" disabled - data-vocabs-id-value="{{ term.id }}" data-vocabs-target="input" /> + data-id="{{ term.id }}" data-vocabs-target="input" /> </td> {% if is_granted('ROLE_ADMIN') or is_granted('ROLE_REVISOR') %} <td> @@ -56,15 +72,15 @@ <button class="button is-primary is-hidden" data-vocabs-target="save" data-action="click->vocabs#save" - data-vocabs-saveUrl-value="{{ path('app_vocab_func_context_upd') }}" - data-vocabs-id-value="{{ term.id }}"> + data-url="{{ path('app_vocab_func_context_upd') }}" + data-id="{{ term.id }}"> Save <span class="icon ml-2"> <i class="fa fa-save"></i> </span> </button> <button class="button is-hidden" - data-vocabs-id-value="{{ term.id }}" + data-id="{{ term.id }}" data-vocabs-target="cancel" data-action="click->vocabs#cancel"> Cancel @@ -74,7 +90,7 @@ </button> <button class="button is-link" data-vocabs-target="edit" - data-vocabs-id-value="{{ term.id }}" + data-id="{{ term.id }}" data-action="click->vocabs#edit"> Edit <span class="icon ml-2"> @@ -82,9 +98,9 @@ </span> </button> <button class="button is-danger" - data-vocabs-id-value="{{ term.id }}" + data-id="{{ term.id }}" data-action="click->vocabs#delete" - data-vocabs-delUrl-value="{{ path('app_vocab_func_context_del') }}"> + data-url="{{ path('app_vocab_func_context_del') }}"> Delete <span class="icon ml-2"> <i class="fa fa-trash"></i> @@ -96,8 +112,27 @@ </tr> {% endfor %} </table> - + </div> + <div class="modal" data-vocabs-target="modal"> + <div class="modal-background"></div> + <div class="modal-card"> + <header class="modal-card-head"> + <span class="icon is-large has-text-warning"> + <i class="fa fa-warning fa-2x"></i> + </span> + <p class="modal-card-title has-text-danger pl-2"><strong>Delete term?</strong></p> + <button class="delete" aria-label="close"></button> + </header> + <section class="modal-card-body"> + <p class="is-size-5">This term will be permanently deleted. Proceed?</p> + </section> + <footer class="modal-card-foot"> + <div class="buttons is-right"> + <button class="button is-link" data-action="click->vocabs#delete">Confirm</button> + <button class="button is-light" id="cancel">Cancel</button> + </div> + </footer> + </div> </div> </div> -<script type="text/javascript" defer></script> {% endblock %} \ No newline at end of file