diff --git a/src/main/java/de/deadlocker8/budgetmaster/templates/TemplateController.java b/src/main/java/de/deadlocker8/budgetmaster/templates/TemplateController.java index 16b449615dd68baa385551bcff5fb43a05657cad..2d47b2151f4c02a6ec8bcb1a3798f7264849fb3a 100644 --- a/src/main/java/de/deadlocker8/budgetmaster/templates/TemplateController.java +++ b/src/main/java/de/deadlocker8/budgetmaster/templates/TemplateController.java @@ -14,6 +14,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; +import org.springframework.validation.BindingResult; import org.springframework.web.bind.annotation.*; import org.springframework.web.server.ResponseStatusException; @@ -72,11 +73,11 @@ public class TemplateController extends BaseController } @PostMapping(value = "/templates/fromTransaction") - public String postNormal(@RequestParam(value = "templateName") String templateName, - @ModelAttribute("NewTransaction") Transaction transaction, - @RequestParam(value = "isPayment", required = false) boolean isPayment, - @RequestParam(value = "includeCategory") Boolean includeCategory, - @RequestParam(value = "includeAccount") Boolean includeAccount) + public String postFromTransaction(@RequestParam(value = "templateName") String templateName, + @ModelAttribute("NewTransaction") Transaction transaction, + @RequestParam(value = "isPayment", required = false) boolean isPayment, + @RequestParam(value = "includeCategory") Boolean includeCategory, + @RequestParam(value = "includeAccount") Boolean includeAccount) { transactionService.handleAmount(transaction, isPayment); transactionService.handleTags(transaction); @@ -141,4 +142,36 @@ public class TemplateController extends BaseController } return "transactions/newTransactionNormal"; } + + @GetMapping("/templates/newTemplate") + public String newTemplate(Model model) + { + final Template emptyTemplate = new Template(); + templateService.prepareTemplateForNewTransaction(emptyTemplate); + templateService.prepareModelNewOrEdit(model, false, emptyTemplate, true, accountService.getAllAccountsAsc()); + return "templates/newTemplate"; + } + + @PostMapping(value = "/templates/newTemplate") + public String post(Model model, + @ModelAttribute("NewTemplate") Template template, BindingResult bindingResult, + @RequestParam(value = "isPayment", required = false) boolean isPayment) + { + + TemplateValidator templateValidator = new TemplateValidator(); + templateValidator.validate(template, bindingResult); + + transactionService.handleAmount(template, isPayment); + transactionService.handleTags(template); + + if(bindingResult.hasErrors()) + { + model.addAttribute("error", bindingResult); + templateService.prepareModelNewOrEdit(model, template.getID() != null, template, isPayment, accountService.getAllAccountsAsc()); + return "templates/newTemplate"; + } + + templateService.getRepository().save(template); + return "redirect:/transactions"; + } } \ No newline at end of file diff --git a/src/main/java/de/deadlocker8/budgetmaster/templates/TemplateService.java b/src/main/java/de/deadlocker8/budgetmaster/templates/TemplateService.java index 07fefa6c985bccd3ded1fb91763716105a61b9be..45c6149030cca1bca229612fbd608ccc9d177e63 100644 --- a/src/main/java/de/deadlocker8/budgetmaster/templates/TemplateService.java +++ b/src/main/java/de/deadlocker8/budgetmaster/templates/TemplateService.java @@ -1,30 +1,46 @@ package de.deadlocker8.budgetmaster.templates; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; import de.deadlocker8.budgetmaster.accounts.Account; import de.deadlocker8.budgetmaster.accounts.AccountService; import de.deadlocker8.budgetmaster.categories.CategoryService; import de.deadlocker8.budgetmaster.categories.CategoryType; import de.deadlocker8.budgetmaster.services.Resetable; +import de.deadlocker8.budgetmaster.settings.SettingsService; import de.deadlocker8.budgetmaster.transactions.Transaction; +import de.deadlocker8.budgetmaster.transactions.TransactionBase; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import org.springframework.ui.Model; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; @Service public class TemplateService implements Resetable { + private static final Gson GSON = new GsonBuilder() + .setPrettyPrinting() + .create(); + private final Logger LOGGER = LoggerFactory.getLogger(this.getClass()); private final TemplateRepository templateRepository; private final AccountService accountService; private final CategoryService categoryService; + private final SettingsService settingsService; + @Autowired - public TemplateService(TemplateRepository templateRepository, AccountService accountService, CategoryService categoryService) + public TemplateService(TemplateRepository templateRepository, AccountService accountService, CategoryService categoryService, SettingsService settingsService) { this.templateRepository = templateRepository; this.accountService = accountService; this.categoryService = categoryService; + this.settingsService = settingsService; } public TemplateRepository getRepository() @@ -72,4 +88,15 @@ public class TemplateService implements Resetable template.setAccount(selectedAccount); } } + + public void prepareModelNewOrEdit(Model model, boolean isEdit, TransactionBase item, boolean isPayment, List<Account> accounts) + { + model.addAttribute("isEdit", isEdit); + model.addAttribute("categories", categoryService.getRepository().findAllByOrderByNameAsc()); + model.addAttribute("accounts", accounts); + model.addAttribute("template", item); + model.addAttribute("settings", settingsService.getSettings()); + model.addAttribute("isPayment", isPayment); + model.addAttribute("suggestionsJSON", GSON.toJson(new ArrayList<String>())); + } } diff --git a/src/main/java/de/deadlocker8/budgetmaster/templates/TemplateValidator.java b/src/main/java/de/deadlocker8/budgetmaster/templates/TemplateValidator.java new file mode 100644 index 0000000000000000000000000000000000000000..39e12581c6914006a1bdd6bab12c22053ea7d2e8 --- /dev/null +++ b/src/main/java/de/deadlocker8/budgetmaster/templates/TemplateValidator.java @@ -0,0 +1,21 @@ +package de.deadlocker8.budgetmaster.templates; + +import de.deadlocker8.budgetmaster.transactions.Transaction; +import de.deadlocker8.budgetmaster.utils.Strings; +import org.springframework.validation.Errors; +import org.springframework.validation.ValidationUtils; +import org.springframework.validation.Validator; + + +public class TemplateValidator implements Validator +{ + public boolean supports(Class clazz) + { + return Transaction.class.equals(clazz); + } + + public void validate(Object obj, Errors errors) + { + ValidationUtils.rejectIfEmptyOrWhitespace(errors, "templateName", Strings.WARNING_EMPTY_TRANSACTION_NAME); + } +} \ No newline at end of file diff --git a/src/main/resources/languages/_de.properties b/src/main/resources/languages/_de.properties index b40ac64252359f055cb3421ac66d10e3a5e59bf0..e7b0784d127700a2eb4d72b0dbbc08e5ec668e88 100644 --- a/src/main/resources/languages/_de.properties +++ b/src/main/resources/languages/_de.properties @@ -139,7 +139,7 @@ warning.settings.password.confirmation.empty=Bitte gib dein Passwort zur Bestät warning.settings.password.confirmation.wrong=Passwort und Passwort Wiederholung stimmen nicht überein. warning.empty.chart.name=Bitte gib einen Namen ein. warning.empty.chart.script=Bitte gib ein Script ein. -warning.empty.template.name=Es existiert bereits eine Vorlage mit diesem Namen. +warning.duplicate.template.name=Es existiert bereits eine Vorlage mit diesem Namen. # UI menu.home=Startseite @@ -230,6 +230,8 @@ repeating.end.afterXTimes.A=nach repeating.end.afterXTimes.B=Wiederholungen repeating.end.date=am +template.new.label.name=Vorlagenname + login.password=Passwort login.button=Login logout.success=Erfolgreich abgemeldet. diff --git a/src/main/resources/languages/_en.properties b/src/main/resources/languages/_en.properties index 261d7f1864a53ce41eb810913da40b97e11148e4..762a81a7c46a6ef1e5bf194341346ce950427594 100644 --- a/src/main/resources/languages/_en.properties +++ b/src/main/resources/languages/_en.properties @@ -139,7 +139,7 @@ warning.settings.password.confirmation.empty=Please enter your password again fo warning.settings.password.confirmation.wrong=Password and password confirmation do not match. warning.empty.chart.name=Please insert a name. warning.empty.chart.script=Please insert a script. -warning.empty.template.name=A template with this name is already existing. +warning.duplicate.template.name=A template with this name is already existing. # UI menu.home=Home @@ -230,6 +230,8 @@ repeating.end.afterXTimes.A=after repeating.end.afterXTimes.B=times repeating.end.date=on +template.new.label.name=Template name + login.password=Password login.button=Login logout.success=Successfully logged out. diff --git a/src/main/resources/templates/templates/newTemplate.ftl b/src/main/resources/templates/templates/newTemplate.ftl new file mode 100644 index 0000000000000000000000000000000000000000..5a5d5c525e03599058230d9747ee7dc6bd12ee2d --- /dev/null +++ b/src/main/resources/templates/templates/newTemplate.ftl @@ -0,0 +1,80 @@ +<html> + <head> + <#import "../helpers/header.ftl" as header> + <@header.header "BudgetMaster"/> + <@header.style "transactions"/> + <@header.style "datepicker"/> + <@header.style "categories"/> + <@header.style "collapsible"/> + <#import "/spring.ftl" as s> + </head> + <body class="budgetmaster-blue-light"> + <#import "../helpers/navbar.ftl" as navbar> + <@navbar.navbar "transactions" settings/> + + <#import "../transactions/newTransactionMacros.ftl" as newTransactionMacros> + <#import "templateFunctions.ftl" as templateFunctions> + + <main> + <div class="card main-card background-color"> + <div class="container"> + <div class="section center-align"> + <div class="headline"><#if isEdit>${locale.getString("title.template.edit")}<#else>${locale.getString("title.template.new")}</#if></div> + </div> + </div> + <div class="container"> + <#import "../helpers/validation.ftl" as validation> + <form name="NewTemplate" action="<@s.url '/templates/newTemplate'/>" method="post" onsubmit="return validateForm()"> + <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/> + <input type="hidden" name="ID" value="<#if template.getID()??>${template.getID()?c}</#if>"> + + <#-- isPayment switch --> + <@newTransactionMacros.isExpenditureSwitch template isPayment/> + + <#-- template name --> + <@templateFunctions.templateName template/> + + <#-- name --> + <@newTransactionMacros.transactionName template suggestionsJSON/> + + <#-- amount --> + <@newTransactionMacros.transactionAmount template/> + + <#-- category --> + <@newTransactionMacros.categorySelect categories template.getCategory() "col s12 m12 l8 offset-l2" locale.getString("transaction.new.label.category")/> + + <#-- description --> + <@newTransactionMacros.transactionDescription template/> + + <#-- tags --> + <@newTransactionMacros.transactionTags template/> + + <#-- account --> + <#if template.getAccount()??> + <@newTransactionMacros.account accounts template.getAccount() "transaction-account" "account" locale.getString("transaction.new.label.account")/> + <#else> + <@newTransactionMacros.account accounts helpers.getCurrentAccountOrDefault() "transaction-account" "account" locale.getString("transaction.new.label.account")/> + </#if> + + <br> + <#-- buttons --> + <@newTransactionMacros.buttons/> + </form> + </div> + </div> + </main> + + <!-- Pass localization to JS --> + <#import "../helpers/globalDatePicker.ftl" as datePicker> + <@datePicker.datePickerLocalization/> + + <!-- Scripts--> + <#import "../helpers/scripts.ftl" as scripts> + <@scripts.scripts/> + <script src="<@s.url '/js/libs/spectrum.js'/>"></script> + <script src="<@s.url '/js/helpers.js'/>"></script> + <script src="<@s.url '/js/transactions.js'/>"></script> + <script src="<@s.url '/js/categorySelect.js'/>"></script> + <script src="<@s.url '/js/templates.js'/>"></script> + </body> +</html> diff --git a/src/main/resources/templates/templates/templateFunctions.ftl b/src/main/resources/templates/templates/templateFunctions.ftl index e2cf1267f56de0e8ebd2f229f7e071b9b43eee02..2ad4251a5777b689ba2911159f932c5e210fb7e3 100644 --- a/src/main/resources/templates/templates/templateFunctions.ftl +++ b/src/main/resources/templates/templates/templateFunctions.ftl @@ -1,4 +1,5 @@ <#import "/spring.ftl" as s> +<#import "../helpers/validation.ftl" as validation> <#macro buttonNew> <a href="<@s.url '/templates/newTemplate'/>" class="waves-effect waves-light btn budgetmaster-blue"><i @@ -126,4 +127,13 @@ <td>${template.getTransferAccount().getName()}</td> </tr> </#if> +</#macro> + +<#macro templateName template> + <div class="row"> + <div class="input-field col s12 m12 l8 offset-l2"> + <input id="template-name" type="text" name="templateName" <@validation.validation "templateName"/> value="<#if template.getTemplateName()??>${template.getTemplateName()}</#if>"> + <label for="template-name">${locale.getString("template.new.label.name")}</label> + </div> + </div> </#macro> \ No newline at end of file diff --git a/src/main/resources/templates/transactions/newTransactionMacros.ftl b/src/main/resources/templates/transactions/newTransactionMacros.ftl index 143f854fb6b53476d28df3d797c57c154abe86fe..5702f7fd49e8e7bb9369daf0dd7bf8cef95d41b4 100644 --- a/src/main/resources/templates/transactions/newTransactionMacros.ftl +++ b/src/main/resources/templates/transactions/newTransactionMacros.ftl @@ -1,4 +1,5 @@ <#import "/spring.ftl" as s> +<#import "../helpers/validation.ftl" as validation> <#macro isExpenditureSwitch transaction isPayment> <#if isPayment> diff --git a/src/main/resources/templates/transactions/newTransactionNormal.ftl b/src/main/resources/templates/transactions/newTransactionNormal.ftl index 39e39fe6b457484567106faf05ee0af9db4c1c62..2890327da7fe9da85409e7428eeace6517da813a 100644 --- a/src/main/resources/templates/transactions/newTransactionNormal.ftl +++ b/src/main/resources/templates/transactions/newTransactionNormal.ftl @@ -74,7 +74,7 @@ <script> createTemplateWithErrorInForm = '${locale.getString("save.as.template.errorsInForm")}'; templateNameEmptyValidationMessage = "${locale.getString("warning.empty.transaction.name")}"; - templateNameDuplicateValidationMessage = "${locale.getString("warning.empty.template.name")}"; + templateNameDuplicateValidationMessage = "${locale.getString("warning.duplicate.template.name")}"; </script> <!-- Scripts--> diff --git a/src/main/resources/templates/transactions/newTransactionTransfer.ftl b/src/main/resources/templates/transactions/newTransactionTransfer.ftl index e8f3cd7c00fec60589e58add5c6bbdc0b28703c4..498f3cea2d0c7f13334e6944a89d0b914e75093c 100644 --- a/src/main/resources/templates/transactions/newTransactionTransfer.ftl +++ b/src/main/resources/templates/transactions/newTransactionTransfer.ftl @@ -79,7 +79,7 @@ <script> createTemplateWithErrorInForm = '${locale.getString("save.as.template.errorsInForm")}'; templateNameEmptyValidationMessage = "${locale.getString("warning.empty.transaction.name")}"; - templateNameDuplicateValidationMessage = "${locale.getString("warning.empty.template.name")}"; + templateNameDuplicateValidationMessage = "${locale.getString("warning.duplicate.template.name")}"; </script> <!-- Scripts-->