diff --git a/BudgetMasterServer/src/main/resources/static/js/transactionImport.js b/BudgetMasterServer/src/main/resources/static/js/transactionImport.js index cc29ec50a45955a9bab869cdd3c37c20e36623af..80fcbb31a9543895c1e3dfa1b40efe8658b48ce6 100644 --- a/BudgetMasterServer/src/main/resources/static/js/transactionImport.js +++ b/BudgetMasterServer/src/main/resources/static/js/transactionImport.js @@ -9,12 +9,12 @@ $(document).ready(function() $('#table-transaction-rows').DataTable({ paging: false, - order: [[1, 'desc']], + order: [[2, 'desc']], info: false, scrollX: true, scrollY: false, columnDefs: [ - { orderable: false, targets: 5} + { orderable: false, targets: 6} ], language: { search: '' , searchPlaceholder: localizedSearch}, }); @@ -56,34 +56,42 @@ function initCsvTransactionForms() for(let i = 0; i < forms.length; i++) { let form = forms[i]; - $(form).submit(function(event) + console.log(i) + console.log(form) + // form.removeEventListener('submit', submitTransactionInPlaceForm); + form.addEventListener('submit', submitTransactionInPlaceForm); + } +} + +function submitTransactionInPlaceForm(event) +{ + const form = event.target; + console.log('form ' + form) + const csvTransactionId = form.dataset.index; + console.log('go') + + $.ajax({ + type: 'POST', + url: $(this).attr('action'), + data: new FormData(form), + processData: false, + contentType: false, + success: function(response) + { + $('#transaction-import-row-' + csvTransactionId).replaceWith(response); + initCsvTransactions(); + }, + error: function(response) { - const csvTransactionId = form.dataset.index; - - $.ajax({ - type: 'POST', - url: $(this).attr('action'), - data: new FormData(form), - processData: false, - contentType: false, - success: function(response) - { - $('#transaction-import-row-' + csvTransactionId).replaceWith(response); - initCsvTransactions(); - }, - error: function(response) - { - M.toast({ - html: "Error saving transaction", - classes: 'red' - }); - console.error(response); - } + M.toast({ + html: "Error saving transaction", + classes: 'red' }); + console.error(response); + } + }); - event.preventDefault(); - }); - } + event.preventDefault(); } function initCsvTransactionButtons() @@ -92,23 +100,29 @@ function initCsvTransactionButtons() for(let i = 0; i < buttonsSkip.length; i++) { const button = buttonsSkip[i]; - button.addEventListener('click', function() - { - performCsvTransactionGetRequestWithoutReload(button, 'Error skipping transaction'); - }); + button.removeEventListener('click', skipRow); + button.addEventListener('click', skipRow); } const buttonsUndoSkip = document.getElementsByClassName('button-request-transaction-import-undo-skip'); for(let i = 0; i < buttonsUndoSkip.length; i++) { const button = buttonsUndoSkip[i]; - button.addEventListener('click', function() - { - performCsvTransactionGetRequestWithoutReload(button, 'Error undo skip transaction'); - }); + button.removeEventListener('click', undoSkipRow); + button.addEventListener('click', undoSkipRow); } } +function skipRow(event) +{ + performCsvTransactionGetRequestWithoutReload(event.currentTarget, 'Error skipping transaction'); +} + +function undoSkipRow(event) +{ + performCsvTransactionGetRequestWithoutReload(event.currentTarget, 'Error undo skip transaction'); +} + function performCsvTransactionGetRequestWithoutReload(button, errorMessage) { const url = button.dataset.url; diff --git a/BudgetMasterServer/src/main/resources/templates/helpers/customSelectMacros.ftl b/BudgetMasterServer/src/main/resources/templates/helpers/customSelectMacros.ftl index 78cce0aede1730e4b6540500a161df1776fe2f79..ad57d9ac37ced628baaa352300c5bd4e20b9e5f1 100644 --- a/BudgetMasterServer/src/main/resources/templates/helpers/customSelectMacros.ftl +++ b/BudgetMasterServer/src/main/resources/templates/helpers/customSelectMacros.ftl @@ -13,14 +13,14 @@ </div> </#macro> -<#macro customSelectEnd inputName selectedItem> - <input type="hidden" name="${inputName}" class="hidden-input-custom-select" <#if selectedItem??>value="${selectedItem.getID()?c}"</#if>/> +<#macro customSelectEnd inputName selectedItem form=""> + <input type="hidden" name="${inputName}" class="hidden-input-custom-select" <#if selectedItem??>value="${selectedItem.getID()?c}"</#if> <#if form?has_content>form="${form}"</#if>/> </div> </div> </div> </#macro> -<#macro customCategorySelect categories selectedCategory inputClasses labelText id showName=true rowClasses="" disabled=false> +<#macro customCategorySelect categories selectedCategory inputClasses labelText id showName=true rowClasses="" disabled=false form=""> <@customSelectStart "category-select-wrapper" categories inputClasses labelText id "label" disabled rowClasses> <div class="custom-select-trigger" tabindex="0"> <div class="custom-select-selected-item"> @@ -52,7 +52,7 @@ </#list> </div> </@customSelectStart> - <@customSelectEnd "category" selectedCategory/> + <@customSelectEnd "category" selectedCategory form/> </#macro> <#macro customAccountSelect selector inputName accounts selectedAccount inputClasses labelText id disabled=false> diff --git a/BudgetMasterServer/src/main/resources/templates/helpers/header.ftl b/BudgetMasterServer/src/main/resources/templates/helpers/header.ftl index 4b8ee3807b306c7f579babd95bd1abf787d96ec2..808412c4e078938582336689aba59c939bf2bc62 100644 --- a/BudgetMasterServer/src/main/resources/templates/helpers/header.ftl +++ b/BudgetMasterServer/src/main/resources/templates/helpers/header.ftl @@ -130,8 +130,8 @@ </a> </#macro> -<#macro buttonSubmit name icon localizationKey id="" color="background-blue" classes="" disabled=false formaction="" value="" onclick=""> - <button id="${id}" class="btn waves-effect waves-light ${color} ${classes}" type="submit" name="${name}" <#if disabled>disabled</#if> <#if formaction?has_content>formaction="<@s.url formaction/>"</#if> <#if value?has_content>value="${value}"</#if> <#if onclick?has_content>onclick="${onclick}"</#if>> +<#macro buttonSubmit name icon localizationKey id="" color="background-blue" classes="" disabled=false formaction="" value="" onclick="" form=""> + <button <#if id?has_content>id="${id}"</#if> class="btn waves-effect waves-light ${color} ${classes}" type="submit" name="${name}" <#if disabled>disabled</#if> <#if formaction?has_content>formaction="<@s.url formaction/>"</#if> <#if value?has_content>value="${value}"</#if> <#if onclick?has_content>onclick="${onclick}" </#if> <#if form?has_content>form="${form}" </#if>> <i class="material-icons left <#if !localizationKey?has_content>no-margin</#if>">${icon}</i><#if localizationKey?has_content>${locale.getString(localizationKey)}</#if> </button> </#macro> diff --git a/BudgetMasterServer/src/main/resources/templates/transactions/transactionImportMacros.ftl b/BudgetMasterServer/src/main/resources/templates/transactions/transactionImportMacros.ftl index cf03a21ed3319f7d6b49d40f128fafe890d98720..86fdd0c0d2d09d9704514b7218a9b409a8fc3b13 100644 --- a/BudgetMasterServer/src/main/resources/templates/transactions/transactionImportMacros.ftl +++ b/BudgetMasterServer/src/main/resources/templates/transactions/transactionImportMacros.ftl @@ -168,6 +168,7 @@ <table class="bordered centered" id="table-transaction-rows" style="width:100%"> <thead> <tr> + <td class="hidden"></td> <td class="bold">${locale.getString("transactions.import.status")}</td> <td class="bold">${locale.getString("transaction.new.label.date")}</td> <td class="bold">${locale.getString("transaction.new.label.category")}</td> @@ -189,21 +190,24 @@ <#macro renderCsvTransaction csvTransaction index> <tr class="transaction-import-row <#if csvTransaction.getStatus().name() == 'SKIPPED'>transaction-import-row-skipped</#if>" id="transaction-import-row-${index}"> - <form name="NewTransactionInPlace" method="POST" action="<@s.url '/transactionImport/' + index + '/newTransactionInPlace'/>" data-index="${index}"> - <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/> + <td class="hidden"> + <form name="NewTransactionInPlace" id="newTransactionInPlace_${index}" method="POST" action="<@s.url '/transactionImport/' + index + '/newTransactionInPlace'/>" data-index="${index}"> + <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/> + </form> + </td> <td data-order="${locale.getString(csvTransaction.getStatus().getLocalizationKey())}" data-search="${locale.getString(csvTransaction.getStatus().getLocalizationKey())}"><@statusBanner csvTransaction.getStatus()/></td> <td data-order="${csvTransaction.getDate()}" data-search="${csvTransaction.getDate()}">${csvTransaction.getDate()}</td> <td data-order="${csvTransaction.getCategory().getName()}" data-search="${csvTransaction.getCategory().getName()}"> - <@customSelectMacros.customCategorySelect categories csvTransaction.getCategory() "left-align no-margin-top no-margin-bottom" "" "csvTransaction-category-${index}" false "no-margin-bottom" csvTransaction.getStatus().name() == 'SKIPPED'/> + <@customSelectMacros.customCategorySelect categories csvTransaction.getCategory() "left-align no-margin-top no-margin-bottom" "" "csvTransaction-category-${index}" false "no-margin-bottom" csvTransaction.getStatus().name() == 'SKIPPED' 'newTransactionInPlace_${index}'/> </td> <td data-order="${csvTransaction.getName()}" data-search="${csvTransaction.getName()}"> <div class="input-field no-margin-top no-margin-bottom"> - <input class="no-margin-bottom autocomplete" type="text" name="name" autocomplete="off" required value="${csvTransaction.getName()}" <#if csvTransaction.getStatus().name() == 'SKIPPED'>disabled</#if>> + <input form="newTransactionInPlace_${index}" class="no-margin-bottom autocomplete" type="text" name="name" autocomplete="off" required value="${csvTransaction.getName()}" <#if csvTransaction.getStatus().name() == 'SKIPPED'>disabled</#if>> </div> </td> <td data-order="${csvTransaction.getDescription()}" data-search="${csvTransaction.getDescription()}"> <div class="input-field no-margin-top no-margin-bottom"> - <input class="no-margin-bottom" type="text" name="description" value="${csvTransaction.getDescription()}" <#if csvTransaction.getStatus().name() == 'SKIPPED'>disabled</#if>> + <input form="newTransactionInPlace_${index}" class="no-margin-bottom" type="text" name="description" value="${csvTransaction.getDescription()}" <#if csvTransaction.getStatus().name() == 'SKIPPED'>disabled</#if>> </div> </td> <td data-order="${currencyService.getCurrencyString(csvTransaction.getAmount())}" data-search="${currencyService.getCurrencyString(csvTransaction.getAmount())}">${currencyService.getCurrencyString(csvTransaction.getAmount())}</td> @@ -211,7 +215,7 @@ <#if csvTransaction.getStatus().name() == 'SKIPPED'> <@header.buttonFlat url='/transactionImport/' + index + '/undoSkip' isDataUrl=true icon='do_disturb_off' localizationKey='' classes="no-padding text-default button-request-transaction-import-undo-skip" datasetIndex=index/> <#else> - <@header.buttonSubmit name='action' icon='save' localizationKey='' classes='text-white'/> + <@header.buttonSubmit name='action' icon='save' localizationKey='' classes='text-white' form='newTransactionInPlace_${index}'/> <div class="fixed-action-btn edit-transaction-button"> <a class="btn-floating btn-flat waves-effect waves-light no-padding text-default edit-transaction-button-link"> <i class="material-icons text-default">edit</i> diff --git a/BudgetMasterServer/src/test/java/de/deadlocker8/budgetmaster/integration/selenium/CsvImportTest.java b/BudgetMasterServer/src/test/java/de/deadlocker8/budgetmaster/integration/selenium/CsvImportTest.java index 70ea4e3805482a30c3f1f1baa57ee5fd57081cc3..28fec653212aa84ee5d4fa3dc81de0e126b0cf65 100644 --- a/BudgetMasterServer/src/test/java/de/deadlocker8/budgetmaster/integration/selenium/CsvImportTest.java +++ b/BudgetMasterServer/src/test/java/de/deadlocker8/budgetmaster/integration/selenium/CsvImportTest.java @@ -642,23 +642,23 @@ class CsvImportTest extends SeleniumTestBase { final List<WebElement> columns = row.findElements(By.tagName("td")); - assertThat(columns.get(0).findElements(By.cssSelector(".banner.background-" + statusColor))) + assertThat(columns.get(1).findElements(By.cssSelector(".banner.background-" + statusColor))) .hasSize(1); - assertThat(columns.get(1).getText()) + assertThat(columns.get(2).getText()) .isEqualTo(date); - final WebElement categoryCircle = columns.get(2).findElement(By.className("category-circle")); + final WebElement categoryCircle = columns.get(3).findElement(By.className("category-circle")); categoryName = categoryName.substring(0, 1).toUpperCase(); assertThat(categoryCircle.findElement(By.tagName("span"))).hasFieldOrPropertyWithValue("text", categoryName); - assertThat(columns.get(3).findElement(By.name("name")).getAttribute("value")) + assertThat(columns.get(4).findElement(By.name("name")).getAttribute("value")) .isEqualTo(name); - assertThat(columns.get(4).findElement(By.name("description")).getAttribute("value")) + assertThat(columns.get(5).findElement(By.name("description")).getAttribute("value")) .isEqualTo(description); - assertThat(columns.get(5).getText()) + assertThat(columns.get(6).getText()) .isEqualTo(amount); } } \ No newline at end of file