From 1c8c530a32f830dd3d7c579fcc9aa70e9400d4bc Mon Sep 17 00:00:00 2001
From: Robert Goldmann <deadlocker@gmx.de>
Date: Mon, 31 Jan 2022 22:29:24 +0100
Subject: [PATCH] #546 - template overview: allow templates to be moved to
 groups

---
 .../TemplateGroupController.java              | 55 ++++++++++++++++++-
 .../resources/languages/base_de.properties    |  6 +-
 .../resources/languages/base_en.properties    |  4 ++
 src/main/resources/static/js/templates.js     | 45 ++++++++++++++-
 .../templates/templates/templateFunctions.ftl | 10 +++-
 5 files changed, 113 insertions(+), 7 deletions(-)

diff --git a/src/main/java/de/deadlocker8/budgetmaster/templategroup/TemplateGroupController.java b/src/main/java/de/deadlocker8/budgetmaster/templategroup/TemplateGroupController.java
index 0f72f9a4f..214681042 100644
--- a/src/main/java/de/deadlocker8/budgetmaster/templategroup/TemplateGroupController.java
+++ b/src/main/java/de/deadlocker8/budgetmaster/templategroup/TemplateGroupController.java
@@ -1,6 +1,9 @@
 package de.deadlocker8.budgetmaster.templategroup;
 
+import com.google.gson.JsonObject;
 import de.deadlocker8.budgetmaster.controller.BaseController;
+import de.deadlocker8.budgetmaster.templates.Template;
+import de.deadlocker8.budgetmaster.templates.TemplateService;
 import de.deadlocker8.budgetmaster.utils.Mappings;
 import de.deadlocker8.budgetmaster.utils.ResourceNotFoundException;
 import de.deadlocker8.budgetmaster.utils.WebRequestUtils;
@@ -22,11 +25,13 @@ import java.util.Optional;
 public class TemplateGroupController extends BaseController
 {
 	private final TemplateGroupService templateGroupService;
+	private final TemplateService templateService;
 
 	@Autowired
-	public TemplateGroupController(TemplateGroupService templateGroupService)
+	public TemplateGroupController(TemplateGroupService templateGroupService, TemplateService templateService)
 	{
 		this.templateGroupService = templateGroupService;
+		this.templateService = templateService;
 	}
 
 	@GetMapping
@@ -106,4 +111,52 @@ public class TemplateGroupController extends BaseController
 		model.addAttribute("templateGroup", templateGroup);
 		return "templateGroups/newTemplateGroup";
 	}
+
+	@PostMapping(value = "/moveTemplateToGroup")
+	@ResponseBody
+	public String moveTemplateToGroup(@RequestParam("templateID") String templateID,
+									  @RequestParam("groupID") String groupID)
+	{
+		int templateIDParsed;
+		int groupIDParsed;
+		try
+		{
+			templateIDParsed = Integer.parseInt(templateID);
+			groupIDParsed = Integer.parseInt(groupID);
+		}
+		catch(NumberFormatException e)
+		{
+			return createJsonResponse(false, Localization.getString("template.move.to.group.error.parse"));
+		}
+
+		Optional<Template> templateOptional = templateService.findById(templateIDParsed);
+		if(templateOptional.isEmpty())
+		{
+			return createJsonResponse(false, Localization.getString("template.move.to.group.error.invalidTemplate"));
+		}
+
+		Optional<TemplateGroup> templateGroupOptional = templateGroupService.findById(groupIDParsed);
+		if(templateGroupOptional.isEmpty())
+		{
+			return createJsonResponse(false, Localization.getString("template.move.to.group.error.invalidGroup"));
+
+		}
+
+		final Template template = templateOptional.get();
+		final TemplateGroup templateGroup = templateGroupOptional.get();
+
+		LOGGER.debug("Moving template with ID {} to group {}", templateID, groupID);
+		template.setTemplateGroup(templateGroup);
+		templateService.getRepository().save(template);
+
+		return createJsonResponse(true, Localization.getString("template.move.to.group.success"));
+	}
+
+	private String createJsonResponse(boolean isSuccess, String localizedMessage)
+	{
+		final JsonObject data = new JsonObject();
+		data.addProperty("success", isSuccess);
+		data.addProperty("localizedMessage", localizedMessage);
+		return data.toString();
+	}
 }
\ No newline at end of file
diff --git a/src/main/resources/languages/base_de.properties b/src/main/resources/languages/base_de.properties
index a3a555192..9a256e8e1 100644
--- a/src/main/resources/languages/base_de.properties
+++ b/src/main/resources/languages/base_de.properties
@@ -176,7 +176,11 @@ upload.image.headline=Bild hochladen
 available.images=Verfügbare Bilder
 icons.images=Eigene Bilder
 icons.builtin=Mitgelieferte Icons
-icons.numberOf=Icons
+icons.numberOf=Icons#
+template.move.to.group.success=Erfolgreich gespeichert
+template.move.to.group.error.parse=Fehler beim Speichern
+template.move.to.group.error.invalidTemplate=Ungültige Vorlage
+template.move.to.group.error.invalidGroup=Ungültige Gruppe
 
 notification.transaction.add.warning=Konto mit Sichtbarkeit "{0}" erlaubt keine neuen Buchungen!
 
diff --git a/src/main/resources/languages/base_en.properties b/src/main/resources/languages/base_en.properties
index d66cf5f81..ecc182a10 100644
--- a/src/main/resources/languages/base_en.properties
+++ b/src/main/resources/languages/base_en.properties
@@ -178,6 +178,10 @@ available.images=Available Images
 icons.images=Custom Images
 icons.builtin=Built-in Icons
 icons.numberOf=Icons
+template.move.to.group.success=Successfully saved
+template.move.to.group.error.parse=Fehler beim Speichern
+template.move.to.group.error.invalidTemplate=Invalid template
+template.move.to.group.error.invalidGroup=Invalid group
 
 notification.transaction.add.warning=Account with visibility "{0}" does not allow new transactions!
 
diff --git a/src/main/resources/static/js/templates.js b/src/main/resources/static/js/templates.js
index 585aded4e..5a6f7a6c9 100644
--- a/src/main/resources/static/js/templates.js
+++ b/src/main/resources/static/js/templates.js
@@ -12,9 +12,48 @@ $(document).ready(function()
             group: 'templates',
             onEnd: function (event) {
                 let draggedItem = event.item;
-                console.log(draggedItem);
-                console.log(event.to);
-                console.log(event.to.dataset.groupName);
+                let templateID = draggedItem.dataset.templateId;
+                let groupID = event.to.dataset.groupId;
+
+                let formID = 'form-move-template-to-group';
+                let form = document.getElementById(formID);
+                let inputTemplateID = form.querySelector('input[name="templateID"]');
+                let inputGroupID = form.querySelector('input[name="groupID"]');
+
+                inputTemplateID.value = templateID;
+                inputGroupID.value = groupID;
+
+                $.ajax({
+                    url: form.action,
+                    type: 'POST',
+                    processData: false,
+                    contentType: false,
+                    data: new FormData(form),
+                    success: function(response)
+                    {
+                        inputTemplateID.value = '';
+                        inputGroupID.value = '';
+
+                        let parsedData = JSON.parse(response);
+                        let isSuccess = parsedData['success']
+                        M.toast({
+                            html: parsedData['localizedMessage'],
+                            classes: isSuccess ? 'green' : 'red'
+                        });
+                    },
+                    error: function(response)
+                    {
+                        inputTemplateID.value = '';
+                        inputGroupID.value = '';
+
+                        let parsedData = JSON.parse(response);
+                        console.log(parsedData)
+                        M.toast({
+                            html: parsedData['localizedMessage'],
+                            classes: 'red'
+                        });
+                    }
+                });
             },
         });
     }
diff --git a/src/main/resources/templates/templates/templateFunctions.ftl b/src/main/resources/templates/templates/templateFunctions.ftl
index f83b7a11f..ec2a6d495 100644
--- a/src/main/resources/templates/templates/templateFunctions.ftl
+++ b/src/main/resources/templates/templates/templateFunctions.ftl
@@ -40,7 +40,7 @@
         <div class="row">
             <div class="col s12">
                 <#list templatesByGroup as templateGroup, templates>
-                    <ul class="collapsible expandable templateCollapsible" data-group-name="${getTemplateGroupName(templateGroup)}">
+                    <ul class="collapsible expandable templateCollapsible" data-group-id="${templateGroup.ID?c}">
                         <#if templatesByGroup?size != 1 && templates?size != 0>
                             <div class="template-group-headline">${getTemplateGroupName(templateGroup)}</div>
                         </#if>
@@ -53,10 +53,16 @@
             </div>
         </div>
     </div>
+
+     <form id="form-move-template-to-group" method="post" action="<@s.url '/templateGroups/moveTemplateToGroup'/>">
+        <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
+        <input type="hidden" name="templateID" value=""/>
+        <input type="hidden" name="groupID" value=""/>
+     </form>
 </#macro>
 
 <#macro templateItem template>
-    <li class="template-item z-depth-2">
+    <li class="template-item z-depth-2" data-template-id="${template.ID?c}">
         <div class="collapsible-header bold">
             <@templateHeader template/>
             <div class="collapsible-header-button">
-- 
GitLab