diff --git a/BudgetMasterServer/pom.xml b/BudgetMasterServer/pom.xml index f7e5fcec923a3fd7d9e4a90f0cc59f95c34e0cc6..2ee143d64033e48bb013835693085c80fda001fa 100644 --- a/BudgetMasterServer/pom.xml +++ b/BudgetMasterServer/pom.xml @@ -5,7 +5,7 @@ <parent> <artifactId>BudgetMaster</artifactId> <groupId>de.deadlocker8</groupId> - <version>2.15.0</version> + <version>2.15.1</version> </parent> <modelVersion>4.0.0</modelVersion> @@ -40,7 +40,7 @@ <vanilla-picker.version>2.12.1</vanilla-picker.version> <jacoco-maven-plugin.version>0.8.10</jacoco-maven-plugin.version> <opencsv.version>5.7.1</opencsv.version> - <datatables.version>1.13.4</datatables.version> + <datatables.version>1.13.5</datatables.version> <jakarta.xml.bind-api.version>4.0.0</jakarta.xml.bind-api.version> <junit-jupiter-engine.version>5.9.3</junit-jupiter-engine.version> diff --git a/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/authentication/WebSecurityConfig.java b/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/authentication/WebSecurityConfig.java index 8e189f7342cef18843d97aba4ec7f11ed2732c6a..c2fa6bfa60134e3895945149829f9572bf0ce01b 100644 --- a/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/authentication/WebSecurityConfig.java +++ b/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/authentication/WebSecurityConfig.java @@ -3,6 +3,7 @@ package de.deadlocker8.budgetmaster.authentication; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configurers.LogoutConfigurer; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.web.DefaultRedirectStrategy; import org.springframework.security.web.RedirectStrategy; @@ -20,34 +21,30 @@ public class WebSecurityConfig return new BCryptPasswordEncoder(); } - @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http - .csrf() - .and() - - .authorizeHttpRequests() - .requestMatchers("/css/**", "/js/**", "/images/**", "/webjars/**", "/favicon.ico", "/touch_icon.png").permitAll() - .requestMatchers("/login").permitAll() - .requestMatchers("/**").authenticated() - .and() - .formLogin() - .loginPage("/login") - .successHandler((req, res, auth) -> { - Object preLoginURL = req.getSession().getAttribute("preLoginURL"); - if(preLoginURL == null || preLoginUrlBlacklist.isBlacklisted(preLoginURL.toString())) - { - preLoginURL = "/"; - } - redirectStrategy.sendRedirect(req, res, preLoginURL.toString()); - }) - .permitAll() - .and() - - .logout() - .permitAll(); + .csrf(csrf -> csrf.configure(http)) + .authorizeHttpRequests(authorization -> authorization + .requestMatchers("/css/**", "/js/**", "/images/**", "/webjars/**", "/favicon.ico", "/touch_icon.png").permitAll() + .requestMatchers("/login").permitAll() + .requestMatchers("/**").authenticated()) + .formLogin(formLogin -> formLogin + .loginPage("/login") + .permitAll() + .successHandler((req, res, auth) -> { + Object preLoginURL = req.getSession().getAttribute("preLoginURL"); + if(preLoginURL == null || preLoginUrlBlacklist.isBlacklisted(preLoginURL.toString())) + { + preLoginURL = "/"; + } + redirectStrategy.sendRedirect(req, res, preLoginURL.toString()); + }) + .permitAll() + ) + .logout(LogoutConfigurer::permitAll + ); return http.build(); } diff --git a/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/controller/AboutController.java b/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/controller/AboutController.java index 2fe7f898120a63b612312b05490cbc809aab935c..59c3a3fc11f0f6343ef829f4488db99f5a3cef16 100644 --- a/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/controller/AboutController.java +++ b/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/controller/AboutController.java @@ -47,6 +47,7 @@ public class AboutController extends BaseController public String whatsNewModal(Model model) { final List<NewsEntry> newsEntries = new ArrayList<>(); + newsEntries.add(NewsEntry.createWithLocalizationKey("csvImportBugfixMultipleTimes")); newsEntries.add(NewsEntry.createWithLocalizationKey("dockerImageSize")); newsEntries.add(NewsEntry.createWithLocalizationKey("csvImportAvoidPageReload")); newsEntries.add(NewsEntry.createWithLocalizationKey("csvImportBugfixFloatingPointPrecision")); diff --git a/BudgetMasterServer/src/main/resources/config/templates/settings.properties b/BudgetMasterServer/src/main/resources/config/templates/settings.properties index 90e5c081d2fcb1fd65afe4d5b14ff38688a3a871..2f69a16dd529aba6e69bb6f4055108188ef0afd0 100644 --- a/BudgetMasterServer/src/main/resources/config/templates/settings.properties +++ b/BudgetMasterServer/src/main/resources/config/templates/settings.properties @@ -18,7 +18,7 @@ budgetmaster.database.password=budgetmaster server.ssl.keyStoreType=PKCS12 # set to true if you want to use SSL (highly recommended) -security.require-ssl=false +server.ssl.enabled=false # insert path to the keystore (relative to the location of BudgetMaster jar/exe or as absolute path) server.ssl.key-store=<path_to_keystore> server.ssl.key-store-password=<keystore_password> diff --git a/BudgetMasterServer/src/main/resources/languages/base_de.properties b/BudgetMasterServer/src/main/resources/languages/base_de.properties index c0721a1a84890bf59e982671300b35d8065a74de..909ca7e831714fc6b878304fd88d51e164776176 100644 --- a/BudgetMasterServer/src/main/resources/languages/base_de.properties +++ b/BudgetMasterServer/src/main/resources/languages/base_de.properties @@ -1,7 +1,7 @@ locale=de # DEFAULT -credits=Verwendete Schriftarten: Roboto<br>Verwendete Bibliotheken:<br>spring-boot-starter-parent 3.1.0<br>spring-boot-devtools 3.1.0<br>spring-boot-starter-web 3.1.0<br>spring-boot-starter-test 3.1.0<br>spring-boot-starter-security 3.1.0<br>spring-boot-starter-freemarker 3.1.0<br>spring-boot-starter-validation 3.1.0<br>spring-boot-starter-data-jpa 3.1.0<br>hibernate-jpamodelgen 6.1.7.Final<br>jakarta.xml.bind-api 4.0.0<br>maven-surefire-plugin 2.22.2<br>launch4j-maven-plugin 1.7.25<br>jquery 3.6.4<br>materialize 1.0.0<br>fontawesome 6.4.0<br>Google Material Icons<br>Vanilla-picker 2.12.1<br>SortableJS 1.15.0<br>jlibs 3.2.0<br>itextpdf 5.5.13.3<br>mousetrap 1.6.5<br>plotly 2.24.2<br>momentjs 2.29.4<br>codemirror 5.62.2<br>webjars-locator 0.46<br>libUtils 3.2.7<br>libStorage 3.2.3<br>natorder 1.1.3<br>jgit 6.6.0.202305301015-r<br>opencsv 5.7.1<br>datatables 1.13.4<br> +credits=Verwendete Schriftarten: Roboto<br>Verwendete Bibliotheken:<br>spring-boot-starter-parent 3.1.1<br>spring-boot-devtools 3.1.1<br>spring-boot-starter-web 3.1.1<br>spring-boot-starter-test 3.1.1<br>spring-boot-starter-security 3.1.1<br>spring-boot-starter-freemarker 3.1.1<br>spring-boot-starter-validation 3.1.1<br>spring-boot-starter-data-jpa 3.1.1<br>hibernate-jpamodelgen 6.1.7.Final<br>jakarta.xml.bind-api 4.0.0<br>maven-surefire-plugin 2.22.2<br>launch4j-maven-plugin 1.7.25<br>jquery 3.6.4<br>materialize 1.0.0<br>fontawesome 6.4.0<br>Google Material Icons<br>Vanilla-picker 2.12.1<br>SortableJS 1.15.0<br>jlibs 3.2.0<br>itextpdf 5.5.13.3<br>mousetrap 1.6.5<br>plotly 2.24.2<br>momentjs 2.29.4<br>codemirror 5.62.2<br>webjars-locator 0.46<br>libUtils 3.2.7<br>libStorage 3.2.3<br>natorder 1.1.3<br>jgit 6.6.0.202305301015-r<br>opencsv 5.7.1<br>datatables 1.13.5<br> folder=Deadlocker/BudgetMaster roadmap.url=https://roadmaps.thecodelabs.de/roadmap/1 github.url=https://github.com/deadlocker8/BudgetMaster diff --git a/BudgetMasterServer/src/main/resources/languages/base_en.properties b/BudgetMasterServer/src/main/resources/languages/base_en.properties index a27725004209fcee4c0de3d158c8414fd9940bee..3cdeaf46b97948f8a3c74598d89f6bfebff795b3 100644 --- a/BudgetMasterServer/src/main/resources/languages/base_en.properties +++ b/BudgetMasterServer/src/main/resources/languages/base_en.properties @@ -1,7 +1,7 @@ locale=en # DEFAULT -credits=Fonts used: Roboto<br>Libraries used:<br>spring-boot-starter-parent 3.1.0<br>spring-boot-devtools 3.1.0<br>spring-boot-starter-web 3.1.0<br>spring-boot-starter-test 3.1.0<br>spring-boot-starter-security 3.1.0<br>pring-boot-starter-freemarker 3.1.0<br>spring-boot-starter-validation 3.1.0<br>spring-boot-starter-data-jpa 3.1.0<br>hibernate-jpamodelgen 6.1.7.Final<br>jakarta.xml.bind-api 4.0.0<br>maven-surefire-plugin 2.22.2<br>launch4j-maven-plugin 1.7.25<br>jquery 3.6.4<br>materialize 1.0.0<br>fontawesome 6.4.0<br>Google Material Icons<br>Vanilla-picker 2.12.1<br>SortableJS 1.15.0<br>jlibs 3.2.0<br>itextpdf 5.5.13.3<br>mousetrap 1.6.5<br>plotly 2.24.2<br>momentjs 2.29.4<br>codemirror 5.62.2<br>webjars-locator 0.46<br>libUtils 3.2.7<br>libStorage 3.2.3<br>natorder 1.1.3<br>jgit 6.6.0.202305301015-r<br>opencsv 5.7.1<br>datatables 1.13.4<br> +credits=Fonts used: Roboto<br>Libraries used:<br>spring-boot-starter-parent 3.1.1<br>spring-boot-devtools 3.1.1<br>spring-boot-starter-web 3.1.1<br>spring-boot-starter-test 3.1.1<br>spring-boot-starter-security 3.1.1<br>pring-boot-starter-freemarker 3.1.1<br>spring-boot-starter-validation 3.1.1<br>spring-boot-starter-data-jpa 3.1.1<br>hibernate-jpamodelgen 6.1.7.Final<br>jakarta.xml.bind-api 4.0.0<br>maven-surefire-plugin 2.22.2<br>launch4j-maven-plugin 1.7.25<br>jquery 3.6.4<br>materialize 1.0.0<br>fontawesome 6.4.0<br>Google Material Icons<br>Vanilla-picker 2.12.1<br>SortableJS 1.15.0<br>jlibs 3.2.0<br>itextpdf 5.5.13.3<br>mousetrap 1.6.5<br>plotly 2.24.2<br>momentjs 2.29.4<br>codemirror 5.62.2<br>webjars-locator 0.46<br>libUtils 3.2.7<br>libStorage 3.2.3<br>natorder 1.1.3<br>jgit 6.6.0.202305301015-r<br>opencsv 5.7.1<br>datatables 1.13.5<br> folder=Deadlocker/BudgetMaster roadmap.url=https://roadmaps.thecodelabs.de/roadmap/2 github.url=https://github.com/deadlocker8/BudgetMaster diff --git a/BudgetMasterServer/src/main/resources/languages/news_de.properties b/BudgetMasterServer/src/main/resources/languages/news_de.properties index 8fedcd8663ca4c0724353576e2dfa510b56239e8..c13e4ffede024b99afabca8d9eb2ecd34c047bf6 100644 --- a/BudgetMasterServer/src/main/resources/languages/news_de.properties +++ b/BudgetMasterServer/src/main/resources/languages/news_de.properties @@ -2,6 +2,9 @@ news.further.information=Weitere Informationen news.all.releases=Alle veröffentlichten und geplanten Versionen: news.detailed=Ausführliches Changelog (nur auf Englisch): +news.csvImportBugfixMultipleTimes.headline=Bugfix: Buchungen werden nicht mehr doppelt gespeichert +news.csvImportBugfixMultipleTimes.description=Behebt einen Fehler, der dazu führte, dass Buchungen beim CSV-Import mehrfach gespeichert wurden. + news.dockerImageSize.headline=Größe des Docker-Images reduziert news.dockerImageSize.description=Deutliche Reduzierung der Größe des Docker-Images. diff --git a/BudgetMasterServer/src/main/resources/languages/news_en.properties b/BudgetMasterServer/src/main/resources/languages/news_en.properties index b19f2aceab26526029a158061d886baf369db27f..0a16f09e86dbac279c4aed56cbcf0ad07374461d 100644 --- a/BudgetMasterServer/src/main/resources/languages/news_en.properties +++ b/BudgetMasterServer/src/main/resources/languages/news_en.properties @@ -2,6 +2,9 @@ news.further.information=Further information news.all.releases=All published and planned releases: news.detailed=Detailed changelog (english only): +news.csvImportBugfixMultipleTimes.headline=Bugfix: Transactions are no longer saved multiple times +news.csvImportBugfixMultipleTimes.description=Fixed an error that caused transactions to be saved multiple times during CSV import. + news.dockerImageSize.headline=Improve docker image size news.dockerImageSize.description=Drastically reduce the size of the docker image. 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/transactionImport.ftl b/BudgetMasterServer/src/main/resources/templates/transactions/transactionImport.ftl index 34cda149620590fe0602a26fb7ebec5dc0cad012..21f8a5099ebe5aec00fa8e5ea08f9f1c143c14e2 100644 --- a/BudgetMasterServer/src/main/resources/templates/transactions/transactionImport.ftl +++ b/BudgetMasterServer/src/main/resources/templates/transactions/transactionImport.ftl @@ -8,7 +8,7 @@ <@header.style "transactionImport"/> <@header.style "collapsible"/> <#import "/spring.ftl" as s> - <link rel="stylesheet" href="<@s.url '/webjars/datatables/1.13.4/css/jquery.dataTables.min.css'/>"/> + <link rel="stylesheet" href="<@s.url '/webjars/datatables/1.13.5/css/jquery.dataTables.min.css'/>"/> </head> <@header.body> <#import "../helpers/navbar.ftl" as navbar> @@ -27,6 +27,10 @@ </div> </div> + <script> + transactionNameSuggestions = {}; + </script> + <@header.content> <div class="container"> <#if csvRows??> @@ -69,7 +73,7 @@ <!-- Scripts--> <#import "../helpers/scripts.ftl" as scripts> <@scripts.scripts/> - <script src="<@s.url '/webjars/datatables/1.13.4/js/jquery.dataTables.min.js'/>"></script> + <script src="<@s.url '/webjars/datatables/1.13.5/js/jquery.dataTables.min.js'/>"></script> <script src="<@s.url '/js/transactionImport.js'/>"></script> </@header.body> </html> diff --git a/BudgetMasterServer/src/main/resources/templates/transactions/transactionImportMacros.ftl b/BudgetMasterServer/src/main/resources/templates/transactions/transactionImportMacros.ftl index cf03a21ed3319f7d6b49d40f128fafe890d98720..b383e17c5aa2e0ffddff9a9f6f8ee07f1a937725 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> @@ -185,25 +186,30 @@ </tbody> </table> </div> + + <@newTransactionMacros.insertNameSuggestions/> </#macro> <#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 +217,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> @@ -236,8 +242,6 @@ </td> </form> </tr> - - <@newTransactionMacros.insertNameSuggestions/> </#macro> <#macro showColumnSettingsErrors> 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 diff --git a/Dockerfile b/Dockerfile index a22fa66035e98495d63bee7dac266a5f8cc4a126..e8ba619648cd8cd426b2a4c1c657acebaf461bb4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,7 +8,7 @@ ARG APP_DIR=/BudgetMaster RUN mkdir -p $APP_DIR RUN mkdir -p /root/.Deadlocker/BudgetMaster -COPY BudgetMasterServer/build/2.15.0/BudgetMasterServer-v2.15.0.jar /BudgetMaster/BudgetMaster.jar +COPY BudgetMasterServer/build/2.15.1/BudgetMasterServer-v2.15.1.jar /BudgetMaster/BudgetMaster.jar COPY BudgetMasterServer/src/main/resources/config/templates/settings-docker.properties /root/.Deadlocker/BudgetMaster/settings.properties RUN echo "server.port=9000" > ~/.Deadlocker/BudgetMaster/settings.properties diff --git a/README.md b/README.md index 5a372d77e32b0e0b9cb3ac77f0d6ff87687af1d1..a81661ababf31dfadf5b4780216824cfc56a2dd0 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Manage your monthly budget easily with BudgetMaster - __start:__ 17.12.16 -- __current release:__ v2.15.0 (43) from 21.06.23 +- __current release:__ v2.15.1 (44) from 18.07.23 ## Key Features - Keep your data private - Host your own BudgetMaster server or use it in standalone mode. All data remains on your machines. diff --git a/docker-compose.yaml b/docker-compose.yaml index b539481d234208e6efe40f799614fde0dbec9594..387c92e6107d8f9686089b2c6c47a95846ce00eb 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -6,9 +6,9 @@ services: volumes: - "./data/budgetmaster:/root/.Deadlocker/BudgetMaster" expose: - - "8080" + - "9000" ports: - - "8080:8080" + - "9000:9000" networks: - netPostgres environment: diff --git a/pom.xml b/pom.xml index 96f6b691b629f83435c2b062a73f94058bf83734..493b63bebb17311fd341dac28aca0c98166362f3 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ <groupId>de.deadlocker8</groupId> <artifactId>BudgetMaster</artifactId> <packaging>pom</packaging> - <version>2.15.0</version> + <version>2.15.1</version> <name>BudgetMaster</name> <modules> @@ -40,7 +40,7 @@ <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> - <version>3.1.0</version> + <version>3.1.1</version> <relativePath/> </parent> @@ -51,7 +51,7 @@ <app.versionDate>${maven.build.timestamp}</app.versionDate> <maven.build.timestamp.format>dd.MM.yy</maven.build.timestamp.format> - <app.versionCode>43</app.versionCode> + <app.versionCode>44</app.versionCode> <app.author>Robert Goldmann</app.author> <testcontainer.version>1.18.3</testcontainer.version>