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