diff --git a/src/main/java/de/deadlocker8/budgetmaster/transactions/TransactionController.java b/src/main/java/de/deadlocker8/budgetmaster/transactions/TransactionController.java index acb0b578b6fc57b6f18930c32184059c498682fa..6d96e1090ce4a9c7a56d82c8e277691ea549a760 100644 --- a/src/main/java/de/deadlocker8/budgetmaster/transactions/TransactionController.java +++ b/src/main/java/de/deadlocker8/budgetmaster/transactions/TransactionController.java @@ -27,6 +27,7 @@ import org.springframework.validation.BindingResult; import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpServletRequest; +import java.text.MessageFormat; import java.util.List; import java.util.Optional; @@ -214,7 +215,7 @@ public class TransactionController extends BaseController public String editTransaction(Model model, @CookieValue("currentDate") String cookieDate, @PathVariable("ID") Integer ID) { Optional<Transaction> transactionOptional = transactionService.getRepository().findById(ID); - if(!transactionOptional.isPresent()) + if(transactionOptional.isEmpty()) { throw new ResourceNotFoundException(); } @@ -257,4 +258,66 @@ public class TransactionController extends BaseController model.addAttribute("highlightID", ID); return "transactions/transactions"; } + + @GetMapping("/transactions/{ID}/changeTypeModal") + public String changeTypeModal(Model model, @PathVariable("ID") Integer ID) + { + final Optional<Transaction> transactionOptional = transactionService.getRepository().findById(ID); + if(transactionOptional.isEmpty()) + { + throw new ResourceNotFoundException(); + } + + model.addAttribute("transaction", transactionOptional.get()); + return "transactions/changeTypeModal"; + } + + @GetMapping("/transactions/{ID}/changeType") + public String changeTypeModal(Model model, @PathVariable("ID") Integer ID, + @CookieValue("currentDate") String cookieDate, + @RequestParam(value = "newType") int newType) + { + final Optional<Transaction> transactionOptional = transactionService.getRepository().findById(ID); + if(transactionOptional.isEmpty()) + { + throw new ResourceNotFoundException(); + } + + final Optional<TransactionType> transactionTypeOptional = TransactionType.getByID(newType); + if(transactionTypeOptional.isEmpty()) + { + throw new IllegalArgumentException(); + } + + Transaction transaction = transactionOptional.get(); + // select first transaction in order to provide correct start date for repeating transactions + if(transaction.getRepeatingOption() != null) + { + transaction = transaction.getRepeatingOption().getReferringTransactions().get(0); + } + + final TransactionType newTransactionType = transactionTypeOptional.get(); + LOGGER.debug(MessageFormat.format("Changing transaction type to {0} for transaction with ID {1}", newTransactionType, transaction.getID())); + + + String redirectUrl = ""; + switch(newTransactionType) + { + case NORMAL: + transaction.setTransferAccount(null); + redirectUrl = "transactions/newTransactionNormal"; + break; + case REPEATING: + redirectUrl = "transactions/newTransactionRepeating"; + break; + case TRANSFER: + redirectUrl = "transactions/newTransactionTransfer"; + break; + } + + DateTime date = dateService.getDateTimeFromCookie(cookieDate); + transactionService.prepareModelNewOrEdit(model, true, date, transaction, accountService.getAllAccountsAsc()); + + return redirectUrl; + } } \ No newline at end of file diff --git a/src/main/java/de/deadlocker8/budgetmaster/transactions/TransactionType.java b/src/main/java/de/deadlocker8/budgetmaster/transactions/TransactionType.java new file mode 100644 index 0000000000000000000000000000000000000000..2847e8543cb66b8d993bb2051f289e4800ee6b66 --- /dev/null +++ b/src/main/java/de/deadlocker8/budgetmaster/transactions/TransactionType.java @@ -0,0 +1,45 @@ +package de.deadlocker8.budgetmaster.transactions; + +import java.util.Optional; + +public enum TransactionType +{ + NORMAL(1), + REPEATING(2), + TRANSFER(3); + + private int typeID; + + TransactionType(int typeID) + { + this.typeID = typeID; + } + + public int getTypeID() + { + return typeID; + } + + public static Optional<TransactionType> getByID(int typeID) + { + switch(typeID) + { + case 1: + return Optional.of(NORMAL); + case 2: + return Optional.of(REPEATING); + case 3: + return Optional.of(TRANSFER); + default: + return Optional.empty(); + } + } + + @Override + public String toString() + { + return "TransactionType{" + + "typeID=" + typeID + + '}'; + } +} diff --git a/src/main/resources/languages/_de.properties b/src/main/resources/languages/_de.properties index ad554dae3774865945f78b2089e970b0034e6db0..859ce427de57179157f86df93cddc7c34de11e66 100644 --- a/src/main/resources/languages/_de.properties +++ b/src/main/resources/languages/_de.properties @@ -68,6 +68,8 @@ placeholder.advice=Füge {0} hinzu save.as.template=Vorlage erzeugen save.as.template.errorsInForm=Vorlage konnte nicht erstellt werden, da Fehler im Formular existieren! transaction.change.type=Buchungstyp ändern +transaction.change.type.warning=Hinweis: Nicht gespeicherte Änderungen gehen verloren! +transaction.change.type.new=Neuer Buchungstyp # WEEK DAYS monday=Montag diff --git a/src/main/resources/languages/_en.properties b/src/main/resources/languages/_en.properties index d0fcf399d62fc20c840a47e003cf3169c2369dfc..707179352119d1082eb51495203a15e3434183e8 100644 --- a/src/main/resources/languages/_en.properties +++ b/src/main/resources/languages/_en.properties @@ -68,6 +68,8 @@ placeholder.advice=Get started by adding {0} save.as.template=Create template save.as.template.errorsInForm=Template could not be created because errors exist in the form! transaction.change.type=Change type +transaction.change.type.warning=Note: Unsaved changes will be lost! +transaction.change.type.new=New type # WEEK DAYS monday=Monday diff --git a/src/main/resources/static/js/templates.js b/src/main/resources/static/js/templates.js index 2935786e9301184873a4c6d795a649abdb771061..eae1407d3bffa4f02496c35f954d06b4c15ab7f8 100644 --- a/src/main/resources/static/js/templates.js +++ b/src/main/resources/static/js/templates.js @@ -5,24 +5,6 @@ $(document).ready(function() $('#modalConfirmDelete').modal('open'); } - if($('#buttonSaveAsTemplate').length) - { - M.FloatingActionButton.init(document.querySelectorAll('#transaction-actions-button'), {}); - - $('.transaction-action').click(function() - { - let actionType = $(this).attr('data-action-type'); - if(actionType === 'saveAsTemplate') - { - openSaveAsTemplateModal(this); - } - else if(actionType === 'changeType') - { - changeTransactionType(this); - } - }); - } - M.Collapsible.init(document.querySelector('.collapsible.expandable'), { accordion: false }); @@ -70,84 +52,6 @@ function handleIncludeAccountCheckbox(checkboxID, selectID) }); } -function createAndOpenModal(data) -{ - let modalID = '#modalCreateFromTransaction'; - - $('#saveAsTemplateModalContainer').html(data); - $(modalID).modal(); - $(modalID).modal('open'); - let templateNameInput = document.getElementById('template-name'); - templateNameInput.focus(); - $(templateNameInput).on('keypress', function(e) - { - let code = e.keyCode || e.which; - if(code === 13) - { - saveAsTemplate(); - } - }); - - $('#buttonCreateTemplate').click(function() - { - saveAsTemplate(); - }); -} - -function saveAsTemplate() -{ - // validate template name - let templateName = document.getElementById('template-name').value; - let isValid = validateTemplateName(templateName); - if(!isValid) - { - return - } - - let form = document.getElementsByName('NewTransaction')[0]; - form.appendChild(createAdditionalHiddenInput('templateName', templateName)); - form.appendChild(createAdditionalHiddenInput('includeCategory', document.getElementById('include-category').checked)); - form.appendChild(createAdditionalHiddenInput('includeAccount', document.getElementById('include-account').checked)); - - // replace form target url - form.action = $('#buttonCreateTemplate').attr('data-url'); - form.submit(); -} - -function validateTemplateName(templateName) -{ - if(templateName.length === 0) - { - addTooltip('template-name', templateNameEmptyValidationMessage); - return false; - } - else - { - removeTooltip('template-name'); - } - - if(existingTemplateNames.includes(templateName)) - { - addTooltip('template-name', templateNameDuplicateValidationMessage); - return false; - } - else - { - removeTooltip('template-name'); - } - - return true; -} - -function createAdditionalHiddenInput(name, value) -{ - let newInput = document.createElement('input'); - newInput.setAttribute('type', 'hidden'); - newInput.setAttribute('name', name); - newInput.setAttribute('value', value); - return newInput; -} - function searchTemplates(searchText) { searchText = searchText.trim(); @@ -192,29 +96,3 @@ function searchTemplates(searchText) collapsible.classList.remove('hidden'); } } - -function openSaveAsTemplateModal(item) -{ - // check if transaction form is valid - let isValidForm = validateForm(true); - if(!isValidForm) - { - $('#modalCreateFromTransaction').modal('close'); - M.toast({html: createTemplateWithErrorInForm}); - return; - } - - $.ajax({ - type: 'GET', - url: $(item).attr('data-url'), - data: {}, - success: function(data) - { - createAndOpenModal(data) - } - }); -} - -function changeTransactionType(item) -{ -} \ No newline at end of file diff --git a/src/main/resources/static/js/transactionActions.js b/src/main/resources/static/js/transactionActions.js new file mode 100644 index 0000000000000000000000000000000000000000..31218d7ede95e669adb354d50eff26dd37fea531 --- /dev/null +++ b/src/main/resources/static/js/transactionActions.js @@ -0,0 +1,150 @@ +$(document).ready(function() +{ + M.FloatingActionButton.init(document.querySelectorAll('#transaction-actions-button'), {}); + + $('.transaction-action').click(function() + { + let actionType = $(this).attr('data-action-type'); + if(actionType === 'saveAsTemplate') + { + openSaveAsTemplateModal(this); + } + else if(actionType === 'changeType') + { + openChangeTransactionTypeModal(this); + } + }); +}); + +function openSaveAsTemplateModal(item) +{ + // check if transaction form is valid + let isValidForm = validateForm(true); + if(!isValidForm) + { + $('#modalCreateFromTransaction').modal('close'); + M.toast({html: createTemplateWithErrorInForm}); + return; + } + + $.ajax({ + type: 'GET', + url: $(item).attr('data-url'), + data: {}, + success: function(data) + { + createAndOpenModal(data) + } + }); +} + +function createAndOpenModal(data) +{ + let modalID = '#modalCreateFromTransaction'; + + $('#saveAsTemplateModalContainer').html(data); + $(modalID).modal(); + $(modalID).modal('open'); + let templateNameInput = document.getElementById('template-name'); + templateNameInput.focus(); + $(templateNameInput).on('keypress', function(e) + { + let code = e.keyCode || e.which; + if(code === 13) + { + saveAsTemplate(); + } + }); + + $('#buttonCreateTemplate').click(function() + { + saveAsTemplate(); + }); +} + +function saveAsTemplate() +{ + // validate template name + let templateName = document.getElementById('template-name').value; + let isValid = validateTemplateName(templateName); + if(!isValid) + { + return + } + + let form = document.getElementsByName('NewTransaction')[0]; + form.appendChild(createAdditionalHiddenInput('templateName', templateName)); + form.appendChild(createAdditionalHiddenInput('includeCategory', document.getElementById('include-category').checked)); + form.appendChild(createAdditionalHiddenInput('includeAccount', document.getElementById('include-account').checked)); + + // replace form target url + form.action = $('#buttonCreateTemplate').attr('data-url'); + form.submit(); +} + +function validateTemplateName(templateName) +{ + if(templateName.length === 0) + { + addTooltip('template-name', templateNameEmptyValidationMessage); + return false; + } + else + { + removeTooltip('template-name'); + } + + if(existingTemplateNames.includes(templateName)) + { + addTooltip('template-name', templateNameDuplicateValidationMessage); + return false; + } + else + { + removeTooltip('template-name'); + } + + return true; +} + +function createAdditionalHiddenInput(name, value) +{ + let newInput = document.createElement('input'); + newInput.setAttribute('type', 'hidden'); + newInput.setAttribute('name', name); + newInput.setAttribute('value', value); + return newInput; +} + +function openChangeTransactionTypeModal(item) +{ + console.log($(item).attr('data-url')); + $.ajax({ + type: 'GET', + url: $(item).attr('data-url'), + data: {}, + success: function(data) + { + createAndOpenModalSelectNewType(data) + } + }); +} + +function createAndOpenModalSelectNewType(data) +{ + let modalID = '#modalChangeTransactionType'; + + $('#changeTransactionTypeModalContainer').html(data); + $(modalID).modal(); + $(modalID).modal('open'); + $('#newTypeSelect').formSelect(); + + $('#buttonChangeTransactionType').click(function() + { + let newType = document.getElementById('newTypeSelect').value; + document.getElementById('inputNewType').setAttribute('value', newType); + + let form = document.getElementById('formChangeTransactionType'); + form.submit(); + }); +} \ No newline at end of file diff --git a/src/main/resources/templates/transactions/changeTypeModal.ftl b/src/main/resources/templates/transactions/changeTypeModal.ftl new file mode 100644 index 0000000000000000000000000000000000000000..7afe21baeff0bcb6d68eee16c20e1928d297f77a --- /dev/null +++ b/src/main/resources/templates/transactions/changeTypeModal.ftl @@ -0,0 +1,38 @@ +<#global locale = static["de.thecodelabs.utils.util.Localization"]> +<#import "/spring.ftl" as s> + +<div id="modalChangeTransactionType" class="modal background-color"> + <div class="modal-content"> + <h4>${locale.getString("transaction.change.type")}</h4> + + <div class="row"> + <div class="sol s12"> + ${locale.getString("transaction.change.type.warning")} + </div> + </div> + <div class="row"> + <div class="input-field col s12"> + <select id="newTypeSelect"> + <#if transaction.isRepeating() || transaction.isTransfer()> + <option value="1">${locale.getString("title.transaction.new.normal")}</option> + </#if> + <#if !transaction.isRepeating()> + <option value="2">${locale.getString("title.transaction.new.repeating")}</option> + </#if> + <#if !transaction.isTransfer()> + <option value="3">${locale.getString("title.transaction.new.transfer")}</option> + </#if> + </select> + <label for="newTypeSelect">${locale.getString("transaction.change.type.new")}</label> + </div> + </div> + </div> + <div class="modal-footer background-color"> + <a class="modal-action modal-close waves-effect waves-light red btn-flat white-text">${locale.getString("cancel")}</a> + <a id="buttonChangeTransactionType" class="modal-action waves-effect waves-light green btn-flat white-text">${locale.getString("ok")}</a> + </div> + + <form id="formChangeTransactionType" class="hidden" action="<@s.url '/transactions/${transaction.getID()?c}/changeType'/>"> + <input type="hidden" name="newType" id="inputNewType"> + </form> +</div> \ 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 5ceadf98789b4382695466fad3d331b5fdc21578..1d4226d61baf2ea99cc4dd2faa9494c8fd8de70b 100644 --- a/src/main/resources/templates/transactions/newTransactionMacros.ftl +++ b/src/main/resources/templates/transactions/newTransactionMacros.ftl @@ -377,13 +377,13 @@ <#macro buttonTransactionActions> <div class="fixed-action-btn" id="transaction-actions-button"> - <a id="buttonSaveAsTemplate" class="btn-floating btn-large waves-effect waves-light budgetmaster-blue"> + <a class="btn-floating btn-large waves-effect waves-light budgetmaster-blue"> <i class="material-icons left">settings</i>${locale.getString("save")} </a> <ul> <li> - <a class="btn-floating btn transaction-action mobile-fab-tip no-wrap" data-action-type="changeType" data-url="<@s.url '/transactions/changeType'/>">${locale.getString("transaction.change.type")}</a> - <a class="btn-floating btn transaction-action budgetmaster-baby-blue" data-action-type="changeType" data-url="<@s.url '/transactions/changeType'/>"><i class="material-icons">shuffle</i></a> + <a class="btn-floating btn transaction-action mobile-fab-tip no-wrap" data-action-type="changeType" data-url="<@s.url '/transactions/${transaction.getID()?c}/changeTypeModal'/>">${locale.getString("transaction.change.type")}</a> + <a class="btn-floating btn transaction-action budgetmaster-baby-blue" data-action-type="changeType" data-url="<@s.url '/transactions/${transaction.getID()?c}/changeTypeModal'/>"><i class="material-icons">shuffle</i></a> </li> <li> <a class="btn-floating btn transaction-action mobile-fab-tip no-wrap" data-action-type="saveAsTemplate" data-url="<@s.url '/templates/fromTransactionModal'/>">${locale.getString("save.as.template")}</a> diff --git a/src/main/resources/templates/transactions/newTransactionNormal.ftl b/src/main/resources/templates/transactions/newTransactionNormal.ftl index 2c9e4542ebe5dd20f41ec31c8c45146c5d6cae8c..1664b697d8ef02f89a9528295febb2b987747230 100644 --- a/src/main/resources/templates/transactions/newTransactionNormal.ftl +++ b/src/main/resources/templates/transactions/newTransactionNormal.ftl @@ -65,6 +65,8 @@ </form> <div id="saveAsTemplateModalContainer"></div> + + <div id="changeTransactionTypeModalContainer"></div> </div> </div> </main> @@ -85,6 +87,7 @@ <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/transactionActions.js'/>"></script> <script src="<@s.url '/js/categorySelect.js'/>"></script> <script src="<@s.url '/js/templates.js'/>"></script> </body> diff --git a/src/main/resources/templates/transactions/newTransactionRepeating.ftl b/src/main/resources/templates/transactions/newTransactionRepeating.ftl index b5219f4108b13e75135674b867764c0dfcfc1d60..06fb6526d2e9fa8c93b70bb869e2cac99deeab07 100644 --- a/src/main/resources/templates/transactions/newTransactionRepeating.ftl +++ b/src/main/resources/templates/transactions/newTransactionRepeating.ftl @@ -62,6 +62,8 @@ <#-- buttons --> <@newTransactionMacros.buttons '/transactions'/> </form> + + <div id="changeTransactionTypeModalContainer"></div> </div> </div> </main> @@ -76,6 +78,7 @@ <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/transactionActions.js'/>"></script> <script src="<@s.url '/js/categorySelect.js'/>"></script> </body> </html> diff --git a/src/main/resources/templates/transactions/newTransactionTransfer.ftl b/src/main/resources/templates/transactions/newTransactionTransfer.ftl index f579be86ba539784680ddc4f783ce12606349e5d..5ac2c8bc178819b9917c18acf376b3d935b2e70b 100644 --- a/src/main/resources/templates/transactions/newTransactionTransfer.ftl +++ b/src/main/resources/templates/transactions/newTransactionTransfer.ftl @@ -70,6 +70,8 @@ </form> <div id="saveAsTemplateModalContainer"></div> + + <div id="changeTransactionTypeModalContainer"></div> </div> </div> </main> @@ -90,6 +92,7 @@ <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/transactionActions.js'/>"></script> <script src="<@s.url '/js/categorySelect.js'/>"></script> <script src="<@s.url '/js/templates.js'/>"></script> </body>