diff --git a/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/templates/TemplateController.java b/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/templates/TemplateController.java index c85eb843ce281dd1ce795254e839bc2378376099..bbd276b1583a9667ff28524621e56963e68d9a91 100644 --- a/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/templates/TemplateController.java +++ b/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/templates/TemplateController.java @@ -191,7 +191,7 @@ public class TemplateController extends BaseController transaction.setDate(csvTransaction.getDate()); transaction.setAmount(csvTransaction.getAmount()); transaction.setIsExpenditure(csvTransaction.getAmount() <= 0); - // TODO: set category from CsvTransaction + transaction.setCategory(csvTransaction.getCategory()); } } diff --git a/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/transactions/TransactionImportController.java b/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/transactions/TransactionImportController.java index 5f7d1b788d8c5222bc5ec0802fc0f8d6494792d2..9ac38b34903959a1f6b85359369e93e3fb38e2d2 100644 --- a/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/transactions/TransactionImportController.java +++ b/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/transactions/TransactionImportController.java @@ -1,6 +1,7 @@ package de.deadlocker8.budgetmaster.transactions; import de.deadlocker8.budgetmaster.accounts.AccountService; +import de.deadlocker8.budgetmaster.categories.Category; import de.deadlocker8.budgetmaster.categories.CategoryService; import de.deadlocker8.budgetmaster.categories.CategoryType; import de.deadlocker8.budgetmaster.controller.BaseController; @@ -34,6 +35,7 @@ public class TransactionImportController extends BaseController private static class ModelAttributes { public static final String ERROR = "error"; + public static final String CATEGORIES = "categories"; } private static class ReturnValues @@ -92,6 +94,8 @@ public class TransactionImportController extends BaseController model.addAttribute(ModelAttributes.ERROR, bindingResult); } + model.addAttribute(ModelAttributes.CATEGORIES, categoryService.getAllEntitiesAsc()); + return ReturnValues.TRANSACTION_IMPORT; } @@ -206,7 +210,8 @@ public class TransactionImportController extends BaseController throw new CsvTransactionParseException(Localization.getString("transactions.import.error.parse.amount", index + 1)); } - return new CsvTransaction(parsedDateOptional.get(), name, parsedAmountOptional.get(), description, CsvTransactionStatus.PENDING); + final Category categoryNone = categoryService.findByType(CategoryType.NONE); + return new CsvTransaction(parsedDateOptional.get(), name, parsedAmountOptional.get(), description, CsvTransactionStatus.PENDING, categoryNone); } @GetMapping("/cancel") @@ -288,6 +293,7 @@ public class TransactionImportController extends BaseController // update original CsvTransaction attributes with values from user (from newCsvTransaction) csvTransaction.setName(newCsvTransaction.getName()); csvTransaction.setDescription(newCsvTransaction.getDescription()); + csvTransaction.setCategory(newCsvTransaction.getCategory()); final Transaction newTransaction = createTransactionFromCsvTransaction(csvTransaction); transactionService.getRepository().save(newTransaction); @@ -304,8 +310,7 @@ public class TransactionImportController extends BaseController newTransaction.setAmount(csvTransaction.getAmount()); newTransaction.setIsExpenditure(csvTransaction.getAmount() <= 0); newTransaction.setAccount(helpers.getCurrentAccountOrDefault()); - // TODO: set category from CsvTransaction - newTransaction.setCategory(categoryService.findByType(CategoryType.NONE)); + newTransaction.setCategory(csvTransaction.getCategory()); return newTransaction; } diff --git a/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/transactions/csvimport/CsvTransaction.java b/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/transactions/csvimport/CsvTransaction.java index 70c46064ab2d66a078281de4d1d564522230d088..5bb23d6dc76b5e7506da1a1ddef3d94652ca5c46 100644 --- a/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/transactions/csvimport/CsvTransaction.java +++ b/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/transactions/csvimport/CsvTransaction.java @@ -1,5 +1,7 @@ package de.deadlocker8.budgetmaster.transactions.csvimport; +import de.deadlocker8.budgetmaster.categories.Category; + import java.time.LocalDate; import java.util.Objects; @@ -10,14 +12,16 @@ public final class CsvTransaction private final Integer amount; private String description; private CsvTransactionStatus status; + private Category category; - public CsvTransaction(LocalDate date, String name, Integer amount, String description, CsvTransactionStatus status) + public CsvTransaction(LocalDate date, String name, Integer amount, String description, CsvTransactionStatus status, Category category) { this.date = date; this.name = name; this.amount = amount; this.description = description; this.status = status; + this.category = category; } public LocalDate getDate() @@ -60,30 +64,41 @@ public final class CsvTransaction this.status = status; } + public Category getCategory() + { + return category; + } + + public void setCategory(Category category) + { + this.category = category; + } + @Override public boolean equals(Object o) { if(this == o) return true; if(o == null || getClass() != o.getClass()) return false; CsvTransaction that = (CsvTransaction) o; - return Objects.equals(date, that.date) && Objects.equals(name, that.name) && Objects.equals(amount, that.amount) && Objects.equals(description, that.description) && status == that.status; + return Objects.equals(date, that.date) && Objects.equals(name, that.name) && Objects.equals(amount, that.amount) && Objects.equals(description, that.description) && status == that.status && Objects.equals(category, that.category); } @Override public int hashCode() { - return Objects.hash(date, name, amount, description, status); + return Objects.hash(date, name, amount, description, status, category); } @Override public String toString() { return "CsvTransaction{" + - "date='" + date + '\'' + + "date=" + date + ", name='" + name + '\'' + ", amount=" + amount + ", description='" + description + '\'' + ", status=" + status + + ", category=" + category + '}'; } } diff --git a/BudgetMasterServer/src/main/resources/static/css/transactionImport.css b/BudgetMasterServer/src/main/resources/static/css/transactionImport.css index 1b674849e6a3e76f7386a6e23d3ddd9e7653a039..b25359846af85ec02bb8eefe7e4ee5defa77082f 100644 --- a/BudgetMasterServer/src/main/resources/static/css/transactionImport.css +++ b/BudgetMasterServer/src/main/resources/static/css/transactionImport.css @@ -34,6 +34,23 @@ border-radius: 0; } +/* override custom select styling*/ +.category-select-wrapper { + margin: 0; +} + +.category-select-margin-top { + margin-top: 1rem; +} + +.custom-select-trigger { + width: 50px; +} + +.custom-select-options { + width: 50vmin; +} + /* label focus color */ #table-transaction-rows_filter input[type=search]:focus + label { color: var(--color-blue) !important; diff --git a/BudgetMasterServer/src/main/resources/static/js/customSelect.js b/BudgetMasterServer/src/main/resources/static/js/customSelect.js index 83742cd3810e20be7cb5c3edfbee14549deff470..0d7a626616b2eeacc1fddc6d061378eba414b36a 100644 --- a/BudgetMasterServer/src/main/resources/static/js/customSelect.js +++ b/BudgetMasterServer/src/main/resources/static/js/customSelect.js @@ -8,9 +8,12 @@ function initCustomSelects() let allCustomSelects = []; let selectorCategorySelect = '.category-select-wrapper'; - if($(selectorCategorySelect).length) + let transactionCategorySelects = document.querySelectorAll(selectorCategorySelect); + + for(let i = 0; i < transactionCategorySelects.length; i++) { - let categorySelect = new CustomSelect(selectorCategorySelect); + let id = transactionCategorySelects[i].id; + let categorySelect = new CustomSelect('#' + id); categorySelect.init(); allCustomSelects.push(categorySelect); } @@ -248,7 +251,12 @@ class CustomSelect item.classList.add('selected'); let itemSelector = document.querySelector(this.selector + ' .custom-select-selected-item'); + let isOnlyIcon = itemSelector.querySelector('.custom-select-item-name') === null; itemSelector.innerHTML = item.innerHTML; + if(isOnlyIcon) + { + itemSelector.querySelector('.custom-select-item-name').remove(); + } let itemCircle = itemSelector.querySelector('.category-circle'); itemCircle.classList.add('no-margin-left'); @@ -258,7 +266,7 @@ class CustomSelect this.removeSelectionStyleClassFromAll(); this.close(this.selector); - this.selectedId = this.resetSelectedItemId(); + this.resetSelectedItemId(); if(this.confirmSelectionCallback && typeof (this.confirmSelectionCallback) == "function") { diff --git a/BudgetMasterServer/src/main/resources/templates/categories/deleteCategoryModal.ftl b/BudgetMasterServer/src/main/resources/templates/categories/deleteCategoryModal.ftl index 705490ea2577c4d3484890f9ca8ccadadb15ee55..44920c02ab7ef736f353bbf313936d0b96b37a26 100644 --- a/BudgetMasterServer/src/main/resources/templates/categories/deleteCategoryModal.ftl +++ b/BudgetMasterServer/src/main/resources/templates/categories/deleteCategoryModal.ftl @@ -12,7 +12,7 @@ <form name="DestinationCategory" id="formDestinationCategory" action="<@s.url '/categories/${categoryToDelete.ID?c}/delete'/>" method="post"> <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/> <#import "../helpers/validation.ftl" as validation> - <@customSelectMacros.customCategorySelect availableCategories preselectedCategory "col s12 m12 l8 offset-l2" locale.getString("info.title.category.delete.move")/> + <@customSelectMacros.customCategorySelect availableCategories preselectedCategory "col s12 m12 l8 offset-l2" locale.getString("info.title.category.delete.move") "transaction-category"/> </form> </div> diff --git a/BudgetMasterServer/src/main/resources/templates/helpers/customSelectMacros.ftl b/BudgetMasterServer/src/main/resources/templates/helpers/customSelectMacros.ftl index c76bd77653ab3da3626a541c135c22eee3244c05..9ad1ffa0d77db99d4e28494adda1d126a6f9d301 100644 --- a/BudgetMasterServer/src/main/resources/templates/helpers/customSelectMacros.ftl +++ b/BudgetMasterServer/src/main/resources/templates/helpers/customSelectMacros.ftl @@ -1,10 +1,12 @@ <#import "../categories/categoriesFunctions.ftl" as categoriesFunctions> -<#macro customSelectStart selector items inputClasses labelText id icon disabled=false> - <div class="row"> +<#macro customSelectStart selector items inputClasses labelText id icon disabled=false rowClasses=""> + <div class="row ${rowClasses}"> <div class="input-field ${inputClasses}"> <i class="material-icons prefix">${icon}</i> - <label class="input-label" for="${id}">${labelText}</label> + <#if labelText?has_content> + <label class="input-label" for="${id}">${labelText}</label> + </#if> <div class="custom-select-wrapper ${selector} <#if disabled>disabled</#if>" id="${id}"> <div class="custom-select"> <#nested> @@ -18,11 +20,11 @@ </div> </#macro> -<#macro customCategorySelect categories selectedCategory inputClasses labelText> - <@customSelectStart "category-select-wrapper" categories inputClasses labelText "transaction-category" "label"> +<#macro customCategorySelect categories selectedCategory inputClasses labelText id showName=true rowClasses=""> + <@customSelectStart "category-select-wrapper" categories inputClasses labelText id "label" false rowClasses> <div class="custom-select-trigger" tabindex="0"> <div class="custom-select-selected-item"> - <#if selectedCategory??><@customSelectOptionCategoryContent category=selectedCategory classes="no-margin-left" datasetValue=true/></#if> + <#if selectedCategory??><@customSelectOptionCategoryContent category=selectedCategory classes="no-margin-left" datasetValue=true showName=showName/></#if> </div> <div class="custom-select-arrow"></div> </div> @@ -140,9 +142,11 @@ </div> </#macro> -<#macro customSelectOptionCategoryContent category classes="" datasetValue=false> +<#macro customSelectOptionCategoryContent category classes="" datasetValue=false showName=true> <@categoriesFunctions.categoryCircle category=category classes="category-circle-small ${classes}" datasetValue=datasetValue/> - <span class="custom-select-item-name">${categoriesFunctions.getCategoryName(category)}</span> + <#if showName> + <span class="custom-select-item-name">${categoriesFunctions.getCategoryName(category)}</span> + </#if> </#macro> <#macro customSelectAccountOption account isSelected> diff --git a/BudgetMasterServer/src/main/resources/templates/templates/newTemplate.ftl b/BudgetMasterServer/src/main/resources/templates/templates/newTemplate.ftl index 6ad6015a444e5b7ab8e32a659656272543413a17..8a0696cc01b7934a76277efb72fcd31720591987 100644 --- a/BudgetMasterServer/src/main/resources/templates/templates/newTemplate.ftl +++ b/BudgetMasterServer/src/main/resources/templates/templates/newTemplate.ftl @@ -54,7 +54,7 @@ <@newTransactionMacros.transactionAmount template/> <#-- category --> - <@customSelectMacros.customCategorySelect categories template.getCategory() "col s12 m12 l8 offset-l2" locale.getString("transaction.new.label.category")/> + <@customSelectMacros.customCategorySelect categories template.getCategory() "col s12 m12 l8 offset-l2" locale.getString("transaction.new.label.category") "transaction-category"/> <#-- description --> <@newTransactionMacros.transactionDescription template/> diff --git a/BudgetMasterServer/src/main/resources/templates/transactions/newTransactionNormal.ftl b/BudgetMasterServer/src/main/resources/templates/transactions/newTransactionNormal.ftl index c529aaa42442ccf7b000bf1055981797d2c99919..35aa56b0d1de8ef20dd3de65d210d24b29d23f4e 100644 --- a/BudgetMasterServer/src/main/resources/templates/transactions/newTransactionNormal.ftl +++ b/BudgetMasterServer/src/main/resources/templates/transactions/newTransactionNormal.ftl @@ -53,7 +53,7 @@ <@newTransactionMacros.transactionAmount transaction/> <#-- category --> - <@customSelectMacros.customCategorySelect categories transaction.getCategory() "col s12 m12 l8 offset-l2" locale.getString("transaction.new.label.category")/> + <@customSelectMacros.customCategorySelect categories transaction.getCategory() "col s12 m12 l8 offset-l2" locale.getString("transaction.new.label.category") "transaction-category"/> <#-- date --> <@newTransactionMacros.transactionStartDate transaction currentDate/> diff --git a/BudgetMasterServer/src/main/resources/templates/transactions/newTransactionTransfer.ftl b/BudgetMasterServer/src/main/resources/templates/transactions/newTransactionTransfer.ftl index 3ef2b5821fb76eb230398c65eaff29b994bd346d..ce46b6140636430acdbf5ab4568c598146657512 100644 --- a/BudgetMasterServer/src/main/resources/templates/transactions/newTransactionTransfer.ftl +++ b/BudgetMasterServer/src/main/resources/templates/transactions/newTransactionTransfer.ftl @@ -51,7 +51,7 @@ <@newTransactionMacros.transactionAmount transaction/> <#-- category --> - <@customSelectMacros.customCategorySelect categories transaction.getCategory() "col s12 m12 l8 offset-l2" locale.getString("transaction.new.label.category")/> + <@customSelectMacros.customCategorySelect categories transaction.getCategory() "col s12 m12 l8 offset-l2" locale.getString("transaction.new.label.category") "transaction-category"/> <#-- date --> <@newTransactionMacros.transactionStartDate transaction currentDate/> diff --git a/BudgetMasterServer/src/main/resources/templates/transactions/transactionImport.ftl b/BudgetMasterServer/src/main/resources/templates/transactions/transactionImport.ftl index 6c7e61a0ec12170969b3be73050d715e698c87a3..c415c2b14f82814589622c53f1b9fd2873264816 100644 --- a/BudgetMasterServer/src/main/resources/templates/transactions/transactionImport.ftl +++ b/BudgetMasterServer/src/main/resources/templates/transactions/transactionImport.ftl @@ -15,6 +15,7 @@ <@navbar.navbar "importCSV" settings/> <#import "transactionsMacros.ftl" as transactionMacros> + <#import "../helpers/customSelectMacros.ftl" as customSelectMacros> <main> <div class="card main-card background-color"> @@ -223,6 +224,7 @@ <tr> <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> <td class="bold">${locale.getString("transaction.new.label.name")}</td> <td class="bold">${locale.getString("transaction.new.label.description")}</td> <td class="bold">${locale.getString("transaction.new.label.amount")}</td> @@ -245,6 +247,9 @@ <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/> <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"/> + </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" type="text" name="name" required value="${csvTransaction.getName()}">