From e1134b7b6205d5e376850fde26f56a95365b96b9 Mon Sep 17 00:00:00 2001 From: Robert Goldmann <deadlocker@gmx.de> Date: Sun, 14 Jul 2019 15:36:46 +0200 Subject: [PATCH] #435 - added filter button --- .../budgetmaster/charts/ChartController.java | 37 ++- .../budgetmaster/charts/ChartSettings.java | 84 +++++ .../filter/FilterHelpersService.java | 7 +- src/main/resources/languages/_de.properties | 2 +- src/main/resources/languages/_en.properties | 2 +- .../resources/templates/charts/charts.ftl | 36 ++- .../templates/filter/filterMacros.ftl | 303 ++++++++++-------- 7 files changed, 319 insertions(+), 152 deletions(-) create mode 100644 src/main/java/de/deadlocker8/budgetmaster/charts/ChartSettings.java diff --git a/src/main/java/de/deadlocker8/budgetmaster/charts/ChartController.java b/src/main/java/de/deadlocker8/budgetmaster/charts/ChartController.java index 5eca1afa7..6721cc10c 100644 --- a/src/main/java/de/deadlocker8/budgetmaster/charts/ChartController.java +++ b/src/main/java/de/deadlocker8/budgetmaster/charts/ChartController.java @@ -1,10 +1,11 @@ package de.deadlocker8.budgetmaster.charts; import de.deadlocker8.budgetmaster.controller.BaseController; +import de.deadlocker8.budgetmaster.filter.FilterConfiguration; +import de.deadlocker8.budgetmaster.filter.FilterHelpersService; import de.deadlocker8.budgetmaster.services.HelpersService; import de.deadlocker8.budgetmaster.settings.SettingsService; import de.deadlocker8.budgetmaster.utils.ResourceNotFoundException; -import org.joda.time.DateTime; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; @@ -14,29 +15,40 @@ import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; +import java.util.ArrayList; +import java.util.List; + @Controller public class ChartController extends BaseController { private final ChartService chartService; private final HelpersService helpers; private final SettingsService settingsService; + private final FilterHelpersService filterHelpersService; @Autowired - public ChartController(ChartService chartService, HelpersService helpers, SettingsService settingsService) + public ChartController(ChartService chartService, HelpersService helpers, SettingsService settingsService, FilterHelpersService filterHelpersService) { this.chartService = chartService; this.helpers = helpers; this.settingsService = settingsService; + this.filterHelpersService = filterHelpersService; } @RequestMapping("/charts") public String charts(Model model) { - model.addAttribute("charts", chartService.getRepository().findAllByOrderByNameAsc()); + List<Chart> charts = chartService.getRepository().findAllByOrderByNameAsc(); + + FilterConfiguration defaultFilterConfiguration = FilterConfiguration.DEFAULT; + defaultFilterConfiguration.setFilterCategories(filterHelpersService.getFilterCategories()); + defaultFilterConfiguration.setFilterTags(filterHelpersService.getFilterTags()); + + ChartSettings defaultChartSettings = ChartSettings.getDefault(charts.get(0).getID(), defaultFilterConfiguration); + + model.addAttribute("chartSettings", defaultChartSettings); + model.addAttribute("charts", charts); model.addAttribute("settings", settingsService.getSettings()); - DateTime now = DateTime.now(); - model.addAttribute("defaultStartDate", now.withDayOfMonth(1)); - model.addAttribute("defaultEndDate", now.dayOfMonth().withMaximumValue()); return "charts/charts"; } @@ -136,4 +148,17 @@ public class ChartController extends BaseController Chart chartToDelete = chartService.getRepository().getOne(ID); return chartToDelete != null && chartToDelete.getType() == ChartType.CUSTOM; } + + @RequestMapping(value = "/charts/showChart", method = RequestMethod.POST) + public String showChart(Model model, @ModelAttribute("NewChartSettings") ChartSettings chartSettings, BindingResult bindingResult) + { + chartSettings.setFilterConfiguration(filterHelpersService.updateCategoriesAndTags(chartSettings.getFilterConfiguration())); + + model.addAttribute("chartSettings", chartSettings); + model.addAttribute("charts", chartService.getRepository().findAllByOrderByNameAsc()); + model.addAttribute("settings", settingsService.getSettings()); + //TODO: load chart from database + + return "charts/charts"; + } } diff --git a/src/main/java/de/deadlocker8/budgetmaster/charts/ChartSettings.java b/src/main/java/de/deadlocker8/budgetmaster/charts/ChartSettings.java new file mode 100644 index 000000000..e5ef9a4ce --- /dev/null +++ b/src/main/java/de/deadlocker8/budgetmaster/charts/ChartSettings.java @@ -0,0 +1,84 @@ +package de.deadlocker8.budgetmaster.charts; + +import de.deadlocker8.budgetmaster.filter.FilterConfiguration; +import org.joda.time.DateTime; +import org.springframework.format.annotation.DateTimeFormat; + + +public class ChartSettings +{ + private int chartID; + @DateTimeFormat(pattern = "dd.MM.yyyy") + private DateTime startDate; + @DateTimeFormat(pattern = "dd.MM.yyyy") + private DateTime endDate; + private FilterConfiguration filterConfiguration; + + public static ChartSettings getDefault(int chartID, FilterConfiguration filterConfiguration) + { + return new ChartSettings(chartID, DateTime.now().withDayOfMonth(1), DateTime.now().dayOfMonth().withMaximumValue(), filterConfiguration); + } + + public ChartSettings() + { + } + + public ChartSettings(int chartID, DateTime startDate, DateTime endDate, FilterConfiguration filterConfiguration) + { + this.chartID = chartID; + this.startDate = startDate; + this.endDate = endDate; + this.filterConfiguration = filterConfiguration; + } + + public int getChartID() + { + return chartID; + } + + public void setChartID(int chartID) + { + this.chartID = chartID; + } + + public DateTime getStartDate() + { + return startDate; + } + + public void setStartDate(DateTime startDate) + { + this.startDate = startDate; + } + + public DateTime getEndDate() + { + return endDate; + } + + public void setEndDate(DateTime endDate) + { + this.endDate = endDate; + } + + public FilterConfiguration getFilterConfiguration() + { + return filterConfiguration; + } + + public void setFilterConfiguration(FilterConfiguration filterConfiguration) + { + this.filterConfiguration = filterConfiguration; + } + + @Override + public String toString() + { + return "ChartSettings{" + + "chartID=" + chartID + + ", startDate=" + startDate + + ", endDate=" + endDate + + ", filterConfiguration=" + filterConfiguration + + '}'; + } +} diff --git a/src/main/java/de/deadlocker8/budgetmaster/filter/FilterHelpersService.java b/src/main/java/de/deadlocker8/budgetmaster/filter/FilterHelpersService.java index 7f1069c78..7af3b6491 100644 --- a/src/main/java/de/deadlocker8/budgetmaster/filter/FilterHelpersService.java +++ b/src/main/java/de/deadlocker8/budgetmaster/filter/FilterHelpersService.java @@ -33,12 +33,13 @@ public class FilterHelpersService filterConfiguration.setFilterTags(getFilterTags()); return filterConfiguration; } + return updateCategoriesAndTags((FilterConfiguration) sessionFilterConfiguration); + } - // update categories and tags - FilterConfiguration filterConfiguration = (FilterConfiguration)sessionFilterConfiguration; + public FilterConfiguration updateCategoriesAndTags(FilterConfiguration filterConfiguration) + { filterConfiguration.setFilterCategories(updateObjects(filterConfiguration.getFilterCategories(), getFilterCategories())); filterConfiguration.setFilterTags(updateObjects(filterConfiguration.getFilterTags(), getFilterTags())); - return filterConfiguration; } diff --git a/src/main/resources/languages/_de.properties b/src/main/resources/languages/_de.properties index ce6394bd9..9a3fa0249 100644 --- a/src/main/resources/languages/_de.properties +++ b/src/main/resources/languages/_de.properties @@ -335,7 +335,7 @@ chart.new.label.script=Script chart.new.info.default=Diese mitgeliefert Diagrammvorlage kann nicht �berschrieben werden, aber du kannst dir den Code ansehen. chart.type=Typ chart.actions=Aktionen -chart.show=Anzeigen +chart.show=Diagramm anzeigen chart.steps.first=Schritt 1: W�hle ein Diagramm chart.steps.first.label=Diagramm diff --git a/src/main/resources/languages/_en.properties b/src/main/resources/languages/_en.properties index d13266622..814c6dee1 100644 --- a/src/main/resources/languages/_en.properties +++ b/src/main/resources/languages/_en.properties @@ -335,7 +335,7 @@ chart.new.label.script=Script chart.new.info.default=This default chart can\'t be overwritten but you can have a look on how it's implemented. chart.type=Type chart.actions=Actions -chart.show=Show +chart.show=Show chart chart.steps.first=Step 1: Choose a chart chart.steps.first.label=Chart diff --git a/src/main/resources/templates/charts/charts.ftl b/src/main/resources/templates/charts/charts.ftl index c1f0563dc..6af2e6fd7 100644 --- a/src/main/resources/templates/charts/charts.ftl +++ b/src/main/resources/templates/charts/charts.ftl @@ -3,6 +3,7 @@ <#import "../helpers/header.ftl" as header> <@header.header "BudgetMaster"/> <@header.style "datepicker"/> + <@header.style "filter"/> <#import "/spring.ftl" as s> </head> <body class="budgetmaster-blue-light"> @@ -10,6 +11,8 @@ <@navbar.navbar "charts" settings/> <#import "chartFunctions.ftl" as chartFunctions> + <#import "../transactions/transactionsMacros.ftl" as transactionsMacros> + <#import "../filter/filterMacros.ftl" as filterMacros> <main> <div class="card main-card background-color"> @@ -19,7 +22,7 @@ </div> </div> <div class="container"> - <form name="ChartSettings" action="<@s.url '/charts/showChart'/>" method="post"> + <form name="NewChartSettings" action="<@s.url '/charts/showChart'/>" method="post"> <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/> <!-- STEP 1 --> @@ -30,9 +33,14 @@ </div> <div class="row"> <div class="input-field col s12 m12 l8 offset-l2 no-margin-top"> - <select name="chart"> + <select name="chartID"> <#list charts as chart> <#assign chartName=chartFunctions.getChartName(chart)> + <#if chartSettings.getChartID() == chart.getID()> + <option selected value="${chart.getID()?c}">${chartName}</option> + <#continue> + </#if> + <option value="${chart.getID()?c}">${chartName}</option> </#list> </select> @@ -48,14 +56,14 @@ </div> <div class="row"> <div class="input-field col s6 m6 l4 offset-l2"> - <#assign startDate = dateService.getLongDateString(defaultStartDate)/> + <#assign startDate = dateService.getLongDateString(chartSettings.getStartDate())/> <input id="chart-datepicker" type="text" class="datepicker" name="startDate" value="${startDate}"> <label for="chart-datepicker">${locale.getString("chart.steps.second.label.start")}</label> </div> <div class="input-field col s6 m6 l4 "> - <#assign endDate = dateService.getLongDateString(defaultEndDate)/> + <#assign endDate = dateService.getLongDateString(chartSettings.getEndDate())/> <input id="chart-datepicker-end" type="text" class="datepicker" name="endDate" value="${endDate}"> <label for="chart-datepicker-end">${locale.getString("chart.steps.second.label.end")}</label> @@ -77,22 +85,21 @@ </div> </div> <div class="row"> - <div class="input-field col s12 m12 l8 offset-l2 no-margin-top"> - <input id="chart-name" type="text" name="name" value=""> - <label for="chart-name">${locale.getString("chart.new.label.name")}</label> + <div class="col s12 m12 l8 offset-l2 no-margin-top center-align"> + <@transactionsMacros.buttonFilter chartSettings.getFilterConfiguration().isActive()/> </div> </div> + <@filterMacros.filterModalCharts chartSettings.getFilterConfiguration()/> + <br> <#-- buttons --> - <div class="hide-on-med-and-up"> - <div class="row center-align"> - <div class="col s12"> - <button class="btn waves-effect waves-light budgetmaster-blue" type="submit" name="buttonSave"> - <i class="material-icons left">show_chart</i>${locale.getString("chart.show")} - </button> - </div> + <div class="row center-align"> + <div class="col s12"> + <button class="btn waves-effect waves-light budgetmaster-blue" type="submit" name="buttonSave"> + <i class="material-icons left">show_chart</i>${locale.getString("chart.show")} + </button> </div> </div> </form> @@ -108,5 +115,6 @@ <#import "../helpers/scripts.ftl" as scripts> <@scripts.scripts/> <script src="<@s.url '/js/charts.js'/>"></script> + <script src="<@s.url '/js/filter.js'/>"></script> </body> </html> \ No newline at end of file diff --git a/src/main/resources/templates/filter/filterMacros.ftl b/src/main/resources/templates/filter/filterMacros.ftl index 0afbff990..e5a966a7e 100644 --- a/src/main/resources/templates/filter/filterMacros.ftl +++ b/src/main/resources/templates/filter/filterMacros.ftl @@ -25,6 +25,31 @@ </div> </#macro> +<#macro buttonsCharts> + <div class="row hide-on-small-only valign-wrapper"> + <div class="col s6 right-align"> + <@buttonReset/> + </div> + + <div class="col s6 left-align"> + <@buttonClose/> + </div> + </div> + + <div class="hide-on-med-and-up valign-wrapper"> + <div class="row center-align"> + <div class="col s12"> + <@buttonReset/> + </div> + </div> + <div class="row center-align"> + <div class="col s12"> + <@buttonClose/> + </div> + </div> + </div> +</#macro> + <#macro buttonReset> <a href="<@s.url '/filter/reset'/>" class="waves-effect waves-light btn budgetmaster-blue"><i class="material-icons left">settings_backup_restore</i>${locale.getString("filter.reset")}</a> </#macro> @@ -35,6 +60,10 @@ </button> </#macro> +<#macro buttonClose> + <a class="modal-action modal-close waves-effect waves-light budgetmaster-blue btn-flat white-text"><i class="fas fa-filter left"></i>${locale.getString("filter.apply")}</a> +</#macro> + <#macro buttonsAllOrNone> <div class="row no-margin"> <div class="col s6 right-align"> @@ -52,133 +81,7 @@ <h4>${locale.getString("title.filter")}</h4> <form name="NewFilterConfiguration" action="<@s.url '/filter/apply'/>" method="post"> <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/> - - <div class="row"> - <div class="s12"> - <ul class="collapsible z-depth-2" id="filterSettings"> - <li id="section-type"> - <div class="collapsible-header"> - <i class="fas fa-piggy-bank"></i> - ${locale.getString("filter.type")} - <div class="collapsible-header-status"></div> - </div> - <div class="collapsible-body"> - <div class="row no-margin"> - <div class="col s12 m4 l4"> - <label> - <input type="checkbox" name="includeIncome" <#if filterConfiguration.isIncludeIncome()>checked="checked"</#if>> - <span class="text-color">${locale.getString('filter.type.income')}</span> - </label> - </div> - <div class="col s12 m4 l4"> - <label> - <input type="checkbox" name="includeExpenditure" <#if filterConfiguration.isIncludeExpenditure()>checked="checked"</#if>> - <span class="text-color">${locale.getString('filter.type.expenditure')}</span> - </label> - </div> - <div class="col s12 m4 l4"> - <label> - <input type="checkbox" name="includeTransfer" <#if filterConfiguration.isIncludeTransfer()>checked="checked"</#if>> - <span class="text-color">${locale.getString('filter.type.transfer')}</span> - </label> - </div> - </div> - </div> - </li> - - <li id="section-repeating"> - <div class="collapsible-header"> - <i class="material-icons">repeat</i> - ${locale.getString("filter.repeating")} - <div class="collapsible-header-status"></div> - </div> - <div class="collapsible-body"> - <div class="row no-margin"> - <div class="col s6 m6 l6"> - <label> - <input type="checkbox" name="includeNotRepeating" <#if filterConfiguration.isIncludeNotRepeating()>checked="checked"</#if>> - <span class="text-color">${locale.getString('filter.repeating.false')}</span> - </label> - </div> - <div class="col s6 m6 l6"> - <label> - <input type="checkbox" name="includeRepeating" <#if filterConfiguration.isIncludeRepeating()>checked="checked"</#if>> - <span class="text-color">${locale.getString('filter.repeating.true')}</span> - </label> - </div> - </div> - </div> - </li> - - <li id="section-categories"> - <div class="collapsible-header"> - <i class="material-icons">label</i> - ${locale.getString("filter.categories")} - <div class="collapsible-header-status"></div> - </div> - <div class="collapsible-body"> - <@buttonsAllOrNone/> - <div class="row no-margin"> - <div class="col s12"> - <#list filterConfiguration.getFilterCategories() as filterCategory> - <div> - <label> - <input type="checkbox" name="filterCategories['${filterCategory?index}'].include" <#if filterCategory.isInclude()>checked="checked"</#if>> - <span class="text-color">${filterCategory.getName()}</span> - </label> - <input type="hidden" name="filterCategories['${filterCategory?index}'].ID" value="${filterCategory.getID()}"/> - <input type="hidden" name="filterCategories['${filterCategory?index}'].name" value="${filterCategory.getName()}"/> - </div> - </#list> - </div> - </div> - </div> - </li> - - <li id="section-tags"> - <div class="collapsible-header"> - <i class="material-icons">local_offer</i> - ${locale.getString("filter.tags")} - <div class="collapsible-header-status"></div> - </div> - <div class="collapsible-body"> - <@buttonsAllOrNone/> - <div class="row no-margin"> - <div class="col s12"> - <#list filterConfiguration.getFilterTags() as filterTag> - <div> - <label> - <input type="checkbox" name="filterTags['${filterTag?index}'].include" <#if filterTag.isInclude()>checked="checked"</#if>> - <span class="text-color">${filterTag.getName()}</span> - </label> - <input type="hidden" name="filterTags['${filterTag?index}'].ID" value="${filterTag.getID()}"/> - <input type="hidden" name="filterTags['${filterTag?index}'].name" value="${filterTag.getName()}"/> - </div> - </#list> - </div> - </div> - </div> - </li> - - <li id="section-name"> - <div class="collapsible-header"> - <i class="material-icons">subject</i> - ${locale.getString("filter.name")} - <div class="collapsible-header-status"></div> - </div> - <div class="collapsible-body"> - <div class="row no-margin"> - <div class="input-field col s12"> - <input id="filter-name" type="text" name="name" value="<#if filterConfiguration.getName()??>${filterConfiguration.getName()}</#if>"> - <label for="filter-name">${locale.getString("filter.name.contains")}</label> - </div> - </div> - </div> - </li> - </ul> - </div> - </div> - + <@filterModalContent filterConfiguration/> <@buttons/> </form> </div> @@ -187,3 +90,149 @@ </div> </div> </#macro> + +<#macro filterModalCharts filterConfiguration> + <div id="modalFilter" class="modal background-color"> + <div class="modal-content"> + <h4>${locale.getString("title.filter")}</h4> + <@filterModalContent filterConfiguration "filterConfiguration"/> + <@buttonsCharts/> + </div> + <div class="modal-footer background-color"> + <a href="" class="modal-action modal-close waves-effect waves-light red btn-flat white-text">${locale.getString("cancel")}</a> + </div> + </div> +</#macro> + +<#macro filterModalContent filterConfiguration prefix=""> + <#if prefix?length gt 0> + <#assign prefixValue = prefix + "."/> + <#else> + <#assign prefixValue = ""/> + </#if> + <div class="row"> + <div class="s12"> + <ul class="collapsible z-depth-2" id="filterSettings"> + <li id="section-type"> + <div class="collapsible-header"> + <i class="fas fa-piggy-bank"></i> + ${locale.getString("filter.type")} + <div class="collapsible-header-status"></div> + </div> + <div class="collapsible-body"> + <div class="row no-margin"> + <div class="col s12 m4 l4"> + <label> + <input type="checkbox" name="${prefixValue}includeIncome" <#if filterConfiguration.isIncludeIncome()>checked="checked"</#if>> + <span class="text-color">${locale.getString('filter.type.income')}</span> + </label> + </div> + <div class="col s12 m4 l4"> + <label> + <input type="checkbox" name="${prefixValue}includeExpenditure" <#if filterConfiguration.isIncludeExpenditure()>checked="checked"</#if>> + <span class="text-color">${locale.getString('filter.type.expenditure')}</span> + </label> + </div> + <div class="col s12 m4 l4"> + <label> + <input type="checkbox" name="${prefixValue}includeTransfer" <#if filterConfiguration.isIncludeTransfer()>checked="checked"</#if>> + <span class="text-color">${locale.getString('filter.type.transfer')}</span> + </label> + </div> + </div> + </div> + </li> + + <li id="section-repeating"> + <div class="collapsible-header"> + <i class="material-icons">repeat</i> + ${locale.getString("filter.repeating")} + <div class="collapsible-header-status"></div> + </div> + <div class="collapsible-body"> + <div class="row no-margin"> + <div class="col s6 m6 l6"> + <label> + <input type="checkbox" name="${prefixValue}includeNotRepeating" <#if filterConfiguration.isIncludeNotRepeating()>checked="checked"</#if>> + <span class="text-color">${locale.getString('filter.repeating.false')}</span> + </label> + </div> + <div class="col s6 m6 l6"> + <label> + <input type="checkbox" name="${prefixValue}includeRepeating" <#if filterConfiguration.isIncludeRepeating()>checked="checked"</#if>> + <span class="text-color">${locale.getString('filter.repeating.true')}</span> + </label> + </div> + </div> + </div> + </li> + + <li id="section-categories"> + <div class="collapsible-header"> + <i class="material-icons">label</i> + ${locale.getString("filter.categories")} + <div class="collapsible-header-status"></div> + </div> + <div class="collapsible-body"> + <@buttonsAllOrNone/> + <div class="row no-margin"> + <div class="col s12"> + <#list filterConfiguration.getFilterCategories() as filterCategory> + <div> + <label> + <input type="checkbox" name="${prefixValue}filterCategories['${filterCategory?index}'].include" <#if filterCategory.isInclude()>checked="checked"</#if>> + <span class="text-color">${filterCategory.getName()}</span> + </label> + <input type="hidden" name="${prefixValue}filterCategories['${filterCategory?index}'].ID" value="${filterCategory.getID()}"/> + <input type="hidden" name="${prefixValue}filterCategories['${filterCategory?index}'].name" value="${filterCategory.getName()}"/> + </div> + </#list> + </div> + </div> + </div> + </li> + + <li id="section-tags"> + <div class="collapsible-header"> + <i class="material-icons">local_offer</i> + ${locale.getString("filter.tags")} + <div class="collapsible-header-status"></div> + </div> + <div class="collapsible-body"> + <@buttonsAllOrNone/> + <div class="row no-margin"> + <div class="col s12"> + <#list filterConfiguration.getFilterTags() as filterTag> + <div> + <label> + <input type="checkbox" name="${prefixValue}filterTags['${filterTag?index}'].include" <#if filterTag.isInclude()>checked="checked"</#if>> + <span class="text-color">${filterTag.getName()}</span> + </label> + <input type="hidden" name="${prefixValue}filterTags['${filterTag?index}'].ID" value="${filterTag.getID()}"/> + <input type="hidden" name="${prefixValue}filterTags['${filterTag?index}'].name" value="${filterTag.getName()}"/> + </div> + </#list> + </div> + </div> + </div> + </li> + + <li id="section-name"> + <div class="collapsible-header"> + <i class="material-icons">subject</i> + ${locale.getString("filter.name")} + <div class="collapsible-header-status"></div> + </div> + <div class="collapsible-body"> + <div class="row no-margin"> + <div class="input-field col s12"> + <input id="filter-name" type="text" name="${prefixValue}name" value="<#if filterConfiguration.getName()??>${filterConfiguration.getName()}</#if>"> + <label for="filter-name">${locale.getString("filter.name.contains")}</label> + </div> + </div> + </div> + </li> + </ul> + </div> + </div> +</#macro> -- GitLab