diff --git a/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/accounts/AccountController.java b/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/accounts/AccountController.java index 54b0bd55bd7f8627971927b683b0fd010e9a4754..7e3035fae0524d27be5d8e72fe343b56bb2a896c 100644 --- a/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/accounts/AccountController.java +++ b/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/accounts/AccountController.java @@ -11,16 +11,16 @@ import de.deadlocker8.budgetmaster.utils.notification.Notification; import de.deadlocker8.budgetmaster.utils.notification.NotificationLinkBuilder; import de.deadlocker8.budgetmaster.utils.notification.NotificationType; import de.thecodelabs.utils.util.Localization; +import jakarta.servlet.http.HttpServletRequest; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.validation.BindingResult; import org.springframework.validation.FieldError; import org.springframework.web.bind.annotation.*; +import org.springframework.web.context.request.RequestAttributes; import org.springframework.web.context.request.WebRequest; -import jakarta.servlet.http.HttpServletRequest; - import java.text.MessageFormat; import java.time.LocalDate; import java.util.List; @@ -43,6 +43,7 @@ public class AccountController extends BaseController public static final String ERROR = "error"; public static final String NOTIFICATIONS = "notifications"; public static final String TODAY = "today"; + public static final String FILTER_CONFIGURATION = "accountsFilterConfiguration"; } private static class ReturnValues @@ -115,22 +116,24 @@ public class AccountController extends BaseController } @GetMapping - public String accounts(Model model) + public String accounts(Model model, HttpServletRequest request) { - model.addAttribute(ModelAttributes.ALL_ENTITIES, accountService.getAllEntitiesAsc()); + final AccountsFilterConfiguration accountsFilterConfiguration = getAccountsFilterConfiguration(request); + model.addAttribute(ModelAttributes.ALL_ENTITIES, accountService.getFilteredEntitiesAsc(accountsFilterConfiguration)); return ReturnValues.SHOW_ALL; } @GetMapping("/{ID}/requestDelete") - public String requestDeleteAccount(Model model, @PathVariable("ID") Integer ID) + public String requestDeleteAccount(Model model, @PathVariable("ID") Integer ID, HttpServletRequest request) { - model.addAttribute(ModelAttributes.ALL_ENTITIES, accountService.getAllEntitiesAsc()); + final AccountsFilterConfiguration accountsFilterConfiguration = getAccountsFilterConfiguration(request); + model.addAttribute(ModelAttributes.ALL_ENTITIES, accountService.getFilteredEntitiesAsc(accountsFilterConfiguration)); model.addAttribute(ModelAttributes.ENTITY_TO_DELETE, accountService.getRepository().getReferenceById(ID)); return ReturnValues.DELETE_ENTITY; } @GetMapping("/{ID}/delete") - public String deleteAccountAndReferringTransactions(WebRequest request, Model model, @PathVariable("ID") Integer ID) + public String deleteAccountAndReferringTransactions(HttpServletRequest servletRequest, WebRequest request, Model model, @PathVariable("ID") Integer ID) { // at least one account is required (to delete a sole account another one has to be created first) final Account accountToDelete = accountService.getRepository().getReferenceById(ID); @@ -141,7 +144,8 @@ public class AccountController extends BaseController return ReturnValues.REDIRECT_SHOW_ALL; } - model.addAttribute(ModelAttributes.ALL_ENTITIES, accountService.getAllEntitiesAsc()); + final AccountsFilterConfiguration accountsFilterConfiguration = getAccountsFilterConfiguration(servletRequest); + model.addAttribute(ModelAttributes.ALL_ENTITIES, accountService.getFilteredEntitiesAsc(accountsFilterConfiguration)); model.addAttribute(ModelAttributes.CURRENT_ACCOUNT, accountToDelete); model.addAttribute(ModelAttributes.ACCOUNT_NOT_DELETABLE, true); return ReturnValues.SHOW_ALL; @@ -272,4 +276,23 @@ public class AccountController extends BaseController settingsService.updateLastAccountEndDateReminderDate(); return "redirect:" + request.getHeader("Referer"); } + + @PostMapping(value = "/applyFilter") + public String applyFilter(WebRequest request, + @ModelAttribute("AccountsFilter") AccountsFilterConfiguration accountsFilterConfiguration) + { + request.setAttribute(ModelAttributes.FILTER_CONFIGURATION, accountsFilterConfiguration, RequestAttributes.SCOPE_SESSION); + return ReturnValues.REDIRECT_SHOW_ALL; + } + + private AccountsFilterConfiguration getAccountsFilterConfiguration(HttpServletRequest request) + { + Object sessionAccountsFilterConfiguration = request.getSession().getAttribute(ModelAttributes.FILTER_CONFIGURATION); + if(sessionAccountsFilterConfiguration == null) + { + request.getSession().setAttribute(ModelAttributes.FILTER_CONFIGURATION, AccountsFilterConfiguration.DEFAULT); + return AccountsFilterConfiguration.DEFAULT; + } + return (AccountsFilterConfiguration) sessionAccountsFilterConfiguration; + } } \ No newline at end of file diff --git a/BudgetMasterServer/src/main/resources/templates/accounts/accounts.ftl b/BudgetMasterServer/src/main/resources/templates/accounts/accounts.ftl index 10880927e8bea35ecc1b41d84021c6e8fb64782e..baf58c7e50bb064417d61abec637fa8d26615e0e 100644 --- a/BudgetMasterServer/src/main/resources/templates/accounts/accounts.ftl +++ b/BudgetMasterServer/src/main/resources/templates/accounts/accounts.ftl @@ -24,107 +24,110 @@ <div class="center-align"><@header.buttonLink url='/accounts/newAccount' icon='add' localizationKey='title.account.new' id='button-new-account'/></div> <br> <div class="container account-container"> - <table class="bordered"> - <thead class="hide-on-med-and-down"> - <tr> - <th></th> - <th> - <div>${locale.getString("account.new.label.state")}</div> - <div> - <label> - <input type="checkbox" /> - <span><i class="fas fa-edit placeholder-icon-right"></i>${locale.getString("account.state.full.access")}</span> - </label> - </div> - <div> - <label> - <input type="checkbox" /> - <span><i class="fas fa-lock placeholder-icon-right"></i>${locale.getString("account.state.read.only")}</span> - </label> - </div> - <div> - <label> - <input type="checkbox" /> - <span><i class="far fa-eye-slash placeholder-icon-right"></i>${locale.getString("account.state.hidden")}</span> - </label> - </div> - </th> - <th> - <div>${locale.getString("account.new.label.endDate")}</div> - <div> - <label> - <input type="checkbox" /> - <span><i class="fas fa-bell placeholder-icon-right"></i>${locale.getString("account.label.endDate.with")}</span> - </label> - </div> - <div> - <label> - <input type="checkbox" /> - <span><i class="fas fa-bell-slash placeholder-icon-right"></i>${locale.getString("account.label.endDate.without")}</span> - </label> - </div> - </th> - <th> - <div>${locale.getString("account.new.label.name")}</div> - <div class="input-field"> - <input type="text" id="accounts-filter-name"> - </div> - </th> - <th> - <div>${locale.getString("transaction.new.label.description")}</div> - <div class="input-field"> - <input type="text" id="accounts-filter-description"> - </div> - </th> - <th class="vertical-align-middle"> - <button class="btn waves-effect waves-light background-green" type="submit" id="accounts-filter-button"> - <i class="fas fa-filter left"></i>${locale.getString("filter.apply")} - </button> - </th> - </tr> - </thead> + <form name="AccountsFilter" action="<@s.url '/accounts/applyFilter'/>" method="post"> + <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" /> + <table class="bordered"> + <thead class="hide-on-med-and-down"> + <tr> + <th></th> + <th> + <div>${locale.getString("account.new.label.state")}</div> + <div> + <label> + <input type="checkbox" name="includeFullAccess" <#if accountsFilterConfiguration?? && accountsFilterConfiguration.includeFullAccess>checked</#if>/> + <span><i class="fas fa-edit placeholder-icon-right"></i>${locale.getString("account.state.full.access")}</span> + </label> + </div> + <div> + <label> + <input type="checkbox" name="includeReadOnly" <#if accountsFilterConfiguration?? && accountsFilterConfiguration.includeReadOnly>checked</#if>/> + <span><i class="fas fa-lock placeholder-icon-right"></i>${locale.getString("account.state.read.only")}</span> + </label> + </div> + <div> + <label> + <input type="checkbox" name="includeHidden" <#if accountsFilterConfiguration?? && accountsFilterConfiguration.includeHidden>checked</#if>/> + <span><i class="far fa-eye-slash placeholder-icon-right"></i>${locale.getString("account.state.hidden")}</span> + </label> + </div> + </th> + <th> + <div>${locale.getString("account.new.label.endDate")}</div> + <div> + <label> + <input type="checkbox" name="includeWithEndDate" <#if accountsFilterConfiguration?? && accountsFilterConfiguration.includeWithEndDate>checked</#if>/> + <span><i class="fas fa-bell placeholder-icon-right"></i>${locale.getString("account.label.endDate.with")}</span> + </label> + </div> + <div> + <label> + <input type="checkbox" name="includeWithoutEndDate" <#if accountsFilterConfiguration?? && accountsFilterConfiguration.includeWithoutEndDate>checked</#if>/> + <span><i class="fas fa-bell-slash placeholder-icon-right"></i>${locale.getString("account.label.endDate.without")}</span> + </label> + </div> + </th> + <th> + <div>${locale.getString("account.new.label.name")}</div> + <div class="input-field"> + <input type="text" name="name" value="<#if accountsFilterConfiguration??>${accountsFilterConfiguration.name}</#if>"/> + </div> + </th> + <th> + <div>${locale.getString("transaction.new.label.description")}</div> + <div class="input-field"> + <input type="text" name="description" value="<#if accountsFilterConfiguration??>${accountsFilterConfiguration.description}</#if>"/> + </div> + </th> + <th class="vertical-align-middle"> + <button class="btn waves-effect waves-light background-green" type="submit" id="accounts-filter-button"> + <i class="fas fa-filter left"></i>${locale.getString("filter.apply")} + </button> + </th> + </tr> + </thead> - <#list accounts as account> - <#if (account.getType().name() == "CUSTOM")> - <tr class="account-overview-row"> - <td><@customSelectMacros.accountIcon account account.getName() "text-blue"/></td> - <td> - <#if account.getAccountState().name() == "READ_ONLY"> - <div class="placeholder-icon placeholder-icon-right"></div> - <i class="fas fa-lock placeholder-icon-right"></i> - <#elseif account.getAccountState().name() == "HIDDEN"> - <div class="placeholder-icon placeholder-icon-right"></div> - <i class="far fa-eye-slash placeholder-icon-right"></i> - <#else> - <a href="<@s.url '/accounts/${account.getID()?c}/setAsDefault'/>" class="btn-flat no-padding text-default tooltipped" data-position="left" data-tooltip="${locale.getString("account.tooltip.default")}"><i class="material-icons left"><#if account.isDefault()>star<#else>star_border</#if></i></a> - <i class="fas fa-edit placeholder-icon-right"></i> - </#if> - </td> - <td> - <#if account.getEndDate()??> - <i class="fas fa-bell placeholder-icon-right"></i> ${dateService.getDateStringNormal(account.getEndDate())} - <#else> - <div class="placeholder-icon"></div> - </#if> - </td> - <td>${account.getName()}</td> - <td> - <div class="truncate account-description"> - ${account.getDescription()} - </div> - </td> - <td> - <a href="<@s.url '/accounts/${account.getID()?c}/edit'/>" class="btn-flat no-padding text-default"><i class="material-icons left">edit</i></a> - <@header.buttonFlat url='/accounts/' + account.ID?c + '/requestDelete' icon='delete' localizationKey='' classes="no-padding text-default button-request-delete-account" isDataUrl=true/> - </td> - </tr> - </#if> - </#list> - </table> - <#if accounts?size == 0> - <div class="headline center-align">${locale.getString("placeholder")}</div> - </#if> - </div> + <#list accounts as account> + <#if (account.getType().name() == "CUSTOM")> + <tr class="account-overview-row"> + <td><@customSelectMacros.accountIcon account account.getName() "text-blue"/></td> + <td> + <#if account.getAccountState().name() == "READ_ONLY"> + <div class="placeholder-icon placeholder-icon-right"></div> + <i class="fas fa-lock placeholder-icon-right"></i> + <#elseif account.getAccountState().name() == "HIDDEN"> + <div class="placeholder-icon placeholder-icon-right"></div> + <i class="far fa-eye-slash placeholder-icon-right"></i> + <#else> + <a href="<@s.url '/accounts/${account.getID()?c}/setAsDefault'/>" class="btn-flat no-padding text-default tooltipped" data-position="left" data-tooltip="${locale.getString("account.tooltip.default")}"><i class="material-icons left"><#if account.isDefault()>star<#else>star_border</#if></i></a> + <i class="fas fa-edit placeholder-icon-right"></i> + </#if> + </td> + <td> + <#if account.getEndDate()??> + <i class="fas fa-bell placeholder-icon-right"></i> ${dateService.getDateStringNormal(account.getEndDate())} + <#else> + <div class="placeholder-icon"></div> + </#if> + </td> + <td>${account.getName()}</td> + <td> + <div class="truncate account-description"> + ${account.getDescription()} + </div> + </td> + <td> + <a href="<@s.url '/accounts/${account.getID()?c}/edit'/>" class="btn-flat no-padding text-default"><i class="material-icons left">edit</i></a> + <@header.buttonFlat url='/accounts/' + account.ID?c + '/requestDelete' icon='delete' localizationKey='' classes="no-padding text-default button-request-delete-account" isDataUrl=true/> + </td> + </tr> + </#if> + </#list> + </table> + </form> + <#if accounts?size == 0> + <div class="headline center-align">${locale.getString("placeholder")}</div> + </#if> + </div> </@header.content> </div>