From 1d5f23397f7a938878a018e1c4a41ebea98acc4f Mon Sep 17 00:00:00 2001 From: MK13 Date: Mon, 1 Jul 2019 23:46:21 +0200 Subject: [PATCH] Add another chart + UI for charts --- .../chart/AbstractChartGenerator.java | 30 +++++++++ .../AccountGroupExpensesChartGenerator.java | 40 ------------ .../de/financer/chart/ChartGenerator.java | 7 ++ .../de/financer/chart/ChartParameter.java | 4 ++ .../java/de/financer/chart/ChartType.java | 18 ++++++ .../financer/chart/FinancerChartFactory.java | 38 +++++++++++ .../impl/AccountGroupExpensesGenerator.java | 36 +++++++++++ .../impl/AccountGroupExpensesParameter.java | 44 +++++++++++++ .../financer/controller/ChartController.java | 47 ++++++++++++-- .../financer/controller/ReportController.java | 64 +++++++++++++++++++ ...onfigAccountGroupExpenseForPeriodForm.java | 22 +++++++ .../de/financer/form/SelectChartForm.java | 13 ++++ .../de/financer/util/ControllerUtils.java | 23 +++++++ .../main/resources/i18n/message.properties | 20 +++++- .../resources/i18n/message_de_DE.properties | 19 +++++- .../src/main/resources/static/css/main.css | 11 +++- .../templates/account/accountOverview.html | 5 ++ ...onfigureAccountGroupExpensesForPeriod.html | 23 +++++++ .../templates/report/selectChart.html | 24 +++++++ 19 files changed, 438 insertions(+), 50 deletions(-) create mode 100644 financer-web-client/src/main/java/de/financer/chart/AbstractChartGenerator.java delete mode 100644 financer-web-client/src/main/java/de/financer/chart/AccountGroupExpensesChartGenerator.java create mode 100644 financer-web-client/src/main/java/de/financer/chart/ChartGenerator.java create mode 100644 financer-web-client/src/main/java/de/financer/chart/ChartParameter.java create mode 100644 financer-web-client/src/main/java/de/financer/chart/ChartType.java create mode 100644 financer-web-client/src/main/java/de/financer/chart/FinancerChartFactory.java create mode 100644 financer-web-client/src/main/java/de/financer/chart/impl/AccountGroupExpensesGenerator.java create mode 100644 financer-web-client/src/main/java/de/financer/chart/impl/AccountGroupExpensesParameter.java create mode 100644 financer-web-client/src/main/java/de/financer/controller/ReportController.java create mode 100644 financer-web-client/src/main/java/de/financer/form/ConfigAccountGroupExpenseForPeriodForm.java create mode 100644 financer-web-client/src/main/java/de/financer/form/SelectChartForm.java create mode 100644 financer-web-client/src/main/resources/templates/report/configureAccountGroupExpensesForPeriod.html create mode 100644 financer-web-client/src/main/resources/templates/report/selectChart.html diff --git a/financer-web-client/src/main/java/de/financer/chart/AbstractChartGenerator.java b/financer-web-client/src/main/java/de/financer/chart/AbstractChartGenerator.java new file mode 100644 index 0000000..251b606 --- /dev/null +++ b/financer-web-client/src/main/java/de/financer/chart/AbstractChartGenerator.java @@ -0,0 +1,30 @@ +package de.financer.chart; + +import de.financer.config.FinancerConfig; +import org.springframework.context.MessageSource; +import org.springframework.context.i18n.LocaleContextHolder; + +public abstract class AbstractChartGenerator

implements ChartGenerator

{ + private FinancerConfig financerConfig; + private MessageSource messageSource; + + public String getMessage(String key) { + return this.getMessage(key, null); + } + + public String getMessage(String key, Object[] args) { + return this.messageSource.getMessage(key, args, LocaleContextHolder.getLocale()); + } + + public FinancerConfig getFinancerConfig() { + return financerConfig; + } + + public void setFinancerConfig(FinancerConfig financerConfig) { + this.financerConfig = financerConfig; + } + + public void setMessageSource(MessageSource messageSource) { + this.messageSource = messageSource; + } +} diff --git a/financer-web-client/src/main/java/de/financer/chart/AccountGroupExpensesChartGenerator.java b/financer-web-client/src/main/java/de/financer/chart/AccountGroupExpensesChartGenerator.java deleted file mode 100644 index 32999f2..0000000 --- a/financer-web-client/src/main/java/de/financer/chart/AccountGroupExpensesChartGenerator.java +++ /dev/null @@ -1,40 +0,0 @@ -package de.financer.chart; - -import de.financer.config.FinancerConfig; -import de.financer.dto.AccountGroupExpense; -import de.financer.template.GetAccountGroupExpensesTemplate; -import de.financer.util.ControllerUtils; -import org.apache.commons.collections4.IterableUtils; -import org.jfree.chart.ChartFactory; -import org.jfree.chart.JFreeChart; -import org.jfree.data.general.DefaultPieDataset; -import org.jfree.data.general.PieDataset; -import org.springframework.context.MessageSource; -import org.springframework.context.i18n.LocaleContextHolder; - -import java.time.LocalDate; - -public class AccountGroupExpensesChartGenerator { - public JFreeChart generateChart(FinancerConfig financerConfig, LocalDate periodStart, LocalDate periodEnd, MessageSource messageSource) { - final String start = ControllerUtils.formatDate(financerConfig, periodStart); - final String end = ControllerUtils.formatDate(financerConfig, periodEnd); - - final Iterable expenses = new GetAccountGroupExpensesTemplate() - .exchange(financerConfig, start, end).getBody(); - - final PieDataset dataSet = createDataSet(expenses); - - return ChartFactory.createPieChart(messageSource - .getMessage("financer.chart.account-group-expenses-current-period.title", null, LocaleContextHolder - .getLocale()), dataSet); - } - - private PieDataset createDataSet(Iterable data) { - final DefaultPieDataset dataSet = new DefaultPieDataset(); - - IterableUtils.toList(data).stream() - .forEach((ex) -> dataSet.setValue(ex.getAccountGroup().getName(), ex.getExpense())); - - return dataSet; - } -} diff --git a/financer-web-client/src/main/java/de/financer/chart/ChartGenerator.java b/financer-web-client/src/main/java/de/financer/chart/ChartGenerator.java new file mode 100644 index 0000000..9c86266 --- /dev/null +++ b/financer-web-client/src/main/java/de/financer/chart/ChartGenerator.java @@ -0,0 +1,7 @@ +package de.financer.chart; + +import org.jfree.chart.JFreeChart; + +public interface ChartGenerator

{ + JFreeChart generateChart(P parameter); +} diff --git a/financer-web-client/src/main/java/de/financer/chart/ChartParameter.java b/financer-web-client/src/main/java/de/financer/chart/ChartParameter.java new file mode 100644 index 0000000..2eb9c29 --- /dev/null +++ b/financer-web-client/src/main/java/de/financer/chart/ChartParameter.java @@ -0,0 +1,4 @@ +package de.financer.chart; + +public interface ChartParameter { +} diff --git a/financer-web-client/src/main/java/de/financer/chart/ChartType.java b/financer-web-client/src/main/java/de/financer/chart/ChartType.java new file mode 100644 index 0000000..fc98c91 --- /dev/null +++ b/financer-web-client/src/main/java/de/financer/chart/ChartType.java @@ -0,0 +1,18 @@ +package de.financer.chart; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +public enum ChartType { + ACCOUNT_GROUP_EXPENSES_CURRENT_PERIOD, + ACCOUNT_GROUP_EXPENSES_FOR_PERIOD; + + public static List valueList() { + return Arrays.stream(ChartType.values()).map(ChartType::name).collect(Collectors.toList()); + } + + public static ChartType getByValue(String value) { + return Arrays.asList(values()).stream().filter((ct) -> ct.name().equals(value)).findFirst().get(); + } +} diff --git a/financer-web-client/src/main/java/de/financer/chart/FinancerChartFactory.java b/financer-web-client/src/main/java/de/financer/chart/FinancerChartFactory.java new file mode 100644 index 0000000..7c44c07 --- /dev/null +++ b/financer-web-client/src/main/java/de/financer/chart/FinancerChartFactory.java @@ -0,0 +1,38 @@ +package de.financer.chart; + +import de.financer.chart.impl.AccountGroupExpensesGenerator; +import de.financer.config.FinancerConfig; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.MessageSource; +import org.springframework.stereotype.Component; + +@Component +public class FinancerChartFactory { + @Autowired + private FinancerConfig financerConfig; + + @Autowired + private MessageSource messageSource; + + public

ChartGenerator

getGenerator(ChartType chartType) { + AbstractChartGenerator

generator; + + switch (chartType) { + case ACCOUNT_GROUP_EXPENSES_CURRENT_PERIOD: + // TODO WHY IS THIS CAST NECESSARY??? + generator = (AbstractChartGenerator

) new AccountGroupExpensesGenerator(); + break; + default: + generator = null; + } + + configureGenerator(generator); + + return generator; + } + + private void configureGenerator(AbstractChartGenerator generator) { + generator.setFinancerConfig(this.financerConfig); + generator.setMessageSource(this.messageSource); + } +} diff --git a/financer-web-client/src/main/java/de/financer/chart/impl/AccountGroupExpensesGenerator.java b/financer-web-client/src/main/java/de/financer/chart/impl/AccountGroupExpensesGenerator.java new file mode 100644 index 0000000..92db9d0 --- /dev/null +++ b/financer-web-client/src/main/java/de/financer/chart/impl/AccountGroupExpensesGenerator.java @@ -0,0 +1,36 @@ +package de.financer.chart.impl; + +import de.financer.chart.AbstractChartGenerator; +import de.financer.dto.AccountGroupExpense; +import de.financer.template.GetAccountGroupExpensesTemplate; +import de.financer.util.ControllerUtils; +import org.apache.commons.collections4.IterableUtils; +import org.jfree.chart.ChartFactory; +import org.jfree.chart.JFreeChart; +import org.jfree.data.general.DefaultPieDataset; +import org.jfree.data.general.PieDataset; + +public class AccountGroupExpensesGenerator extends AbstractChartGenerator { + @Override + public JFreeChart generateChart(AccountGroupExpensesParameter parameter) { + final String start = ControllerUtils.formatDate(this.getFinancerConfig(), parameter.getPeriodStart()); + final String end = ControllerUtils.formatDate(this.getFinancerConfig(), parameter.getPeriodEnd()); + + final Iterable expenses = new GetAccountGroupExpensesTemplate() + .exchange(this.getFinancerConfig(), start, end).getBody(); + + final PieDataset dataSet = createDataSet(expenses); + + return ChartFactory + .createPieChart(this.getMessage(parameter.getTitle(), parameter.getArgsForTitle()), dataSet); + } + + private PieDataset createDataSet(Iterable data) { + final DefaultPieDataset dataSet = new DefaultPieDataset(); + + IterableUtils.toList(data).stream() + .forEach((ex) -> dataSet.setValue(ex.getAccountGroup().getName(), ex.getExpense())); + + return dataSet; + } +} diff --git a/financer-web-client/src/main/java/de/financer/chart/impl/AccountGroupExpensesParameter.java b/financer-web-client/src/main/java/de/financer/chart/impl/AccountGroupExpensesParameter.java new file mode 100644 index 0000000..ab053e0 --- /dev/null +++ b/financer-web-client/src/main/java/de/financer/chart/impl/AccountGroupExpensesParameter.java @@ -0,0 +1,44 @@ +package de.financer.chart.impl; + +import de.financer.chart.ChartParameter; + +import java.time.LocalDate; + +public class AccountGroupExpensesParameter implements ChartParameter { + private LocalDate periodStart; + private LocalDate periodEnd; + private String title; + private Object[] argsForTitle; + + public LocalDate getPeriodStart() { + return periodStart; + } + + public void setPeriodStart(LocalDate periodStart) { + this.periodStart = periodStart; + } + + public LocalDate getPeriodEnd() { + return periodEnd; + } + + public void setPeriodEnd(LocalDate periodEnd) { + this.periodEnd = periodEnd; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public Object[] getArgsForTitle() { + return argsForTitle; + } + + public void setArgsForTitle(Object[] argsForTitle) { + this.argsForTitle = argsForTitle; + } +} diff --git a/financer-web-client/src/main/java/de/financer/controller/ChartController.java b/financer-web-client/src/main/java/de/financer/controller/ChartController.java index 4de1ed3..4bbd902 100644 --- a/financer-web-client/src/main/java/de/financer/controller/ChartController.java +++ b/financer-web-client/src/main/java/de/financer/controller/ChartController.java @@ -1,14 +1,20 @@ package de.financer.controller; -import de.financer.chart.AccountGroupExpensesChartGenerator; +import de.financer.chart.impl.AccountGroupExpensesParameter; +import de.financer.chart.ChartGenerator; +import de.financer.chart.ChartType; +import de.financer.chart.FinancerChartFactory; import de.financer.config.FinancerConfig; +import de.financer.form.ConfigAccountGroupExpenseForPeriodForm; +import de.financer.util.ControllerUtils; import de.financer.util.ExpensePeriod; import org.jfree.chart.ChartUtils; import org.jfree.chart.JFreeChart; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.MessageSource; +import org.springframework.context.i18n.LocaleContextHolder; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @@ -19,16 +25,47 @@ public class ChartController { private FinancerConfig financerConfig; @Autowired - private MessageSource messageSource; + private FinancerChartFactory financerChartFactory; @GetMapping("/getAccountGroupExpensesCurrentPeriod") public void getAccountGroupExpensesCurrentPeriod(HttpServletResponse response) { final ExpensePeriod period = ExpensePeriod .getCurrentExpensePeriod(this.financerConfig.getMonthPeriodStartDay()); + final AccountGroupExpensesParameter parameter = new AccountGroupExpensesParameter(); - JFreeChart chart = new AccountGroupExpensesChartGenerator() - .generateChart(this.financerConfig, period.getStart(), period.getEnd(), this.messageSource); + parameter.setPeriodStart(period.getStart()); + parameter.setPeriodEnd(period.getEnd()); + parameter.setTitle("financer.chart.account-group-expenses-current-period.title"); + final ChartGenerator generator = + this.financerChartFactory.getGenerator(ChartType.ACCOUNT_GROUP_EXPENSES_CURRENT_PERIOD); + + final JFreeChart chart = generator.generateChart(parameter); + + writeChart(response, chart); + } + + @PostMapping("/getAccountGroupExpensesForPeriod") + public void getAccountGroupExpensesForPeriod(HttpServletResponse response, ConfigAccountGroupExpenseForPeriodForm form) { + final AccountGroupExpensesParameter parameter = new AccountGroupExpensesParameter(); + + parameter.setPeriodStart(ControllerUtils.parseDate(this.financerConfig, form.getFromDate())); + parameter.setPeriodEnd(ControllerUtils.parseDate(this.financerConfig, form.getToDate())); + parameter.setTitle("financer.chart.account-group-expenses-for-period.title"); + parameter.setArgsForTitle(new Object[]{ControllerUtils.formatDate(this.financerConfig, form + .getFromDate(), LocaleContextHolder + .getLocale()), ControllerUtils.formatDate(this.financerConfig, form.getToDate(), LocaleContextHolder + .getLocale())}); + + final ChartGenerator generator = + this.financerChartFactory.getGenerator(ChartType.ACCOUNT_GROUP_EXPENSES_CURRENT_PERIOD); + + final JFreeChart chart = generator.generateChart(parameter); + + writeChart(response, chart); + } + + private void writeChart(HttpServletResponse response, JFreeChart chart) { response.setContentType("image/png"); try { diff --git a/financer-web-client/src/main/java/de/financer/controller/ReportController.java b/financer-web-client/src/main/java/de/financer/controller/ReportController.java new file mode 100644 index 0000000..94607c7 --- /dev/null +++ b/financer-web-client/src/main/java/de/financer/controller/ReportController.java @@ -0,0 +1,64 @@ +package de.financer.controller; + +import de.financer.chart.ChartType; +import de.financer.config.FinancerConfig; +import de.financer.form.ConfigAccountGroupExpenseForPeriodForm; +import de.financer.form.SelectChartForm; +import de.financer.util.ControllerUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; + +import java.util.NoSuchElementException; + +@Controller +public class ReportController { + @Autowired + private FinancerConfig financerConfig; + + @GetMapping("/selectChart") + public String selectChart(Model model) { + model.addAttribute("form", new SelectChartForm()); + model.addAttribute("availableCharts", ChartType.valueList()); + ControllerUtils.addVersionAttribute(model, this.financerConfig); + ControllerUtils.addCurrencySymbol(model, this.financerConfig); + + return "report/selectChart"; + } + + @PostMapping("/configureChart") + public String configureChart(SelectChartForm form, Model model) { + final ChartType selectedChartType; + + try { + selectedChartType = ChartType.getByValue(form.getChartType()); + } + catch (NoSuchElementException nsee) { + model.addAttribute("form", new SelectChartForm()); + model.addAttribute("errorMessage", "UNKNOWN_CHART_TYPE"); + model.addAttribute("availableCharts", ChartType.valueList()); + ControllerUtils.addVersionAttribute(model, this.financerConfig); + ControllerUtils.addCurrencySymbol(model, this.financerConfig); + + return "report/selectChart"; + } + + switch(selectedChartType) { + case ACCOUNT_GROUP_EXPENSES_CURRENT_PERIOD: + // Special case: this chart does not require parameters, so we can + // directly redirect to the actual chart instead of the config page + return "redirect:/getAccountGroupExpensesCurrentPeriod"; + case ACCOUNT_GROUP_EXPENSES_FOR_PERIOD: + model.addAttribute("form", new ConfigAccountGroupExpenseForPeriodForm()); + ControllerUtils.addVersionAttribute(model, this.financerConfig); + ControllerUtils.addCurrencySymbol(model, this.financerConfig); + + return "report/configureAccountGroupExpensesForPeriod"; + default: + // Cannot happen + throw new IllegalStateException("Unexpected value: " + selectedChartType); + } + } +} diff --git a/financer-web-client/src/main/java/de/financer/form/ConfigAccountGroupExpenseForPeriodForm.java b/financer-web-client/src/main/java/de/financer/form/ConfigAccountGroupExpenseForPeriodForm.java new file mode 100644 index 0000000..562cebe --- /dev/null +++ b/financer-web-client/src/main/java/de/financer/form/ConfigAccountGroupExpenseForPeriodForm.java @@ -0,0 +1,22 @@ +package de.financer.form; + +public class ConfigAccountGroupExpenseForPeriodForm { + private String fromDate; + private String toDate; + + public String getFromDate() { + return fromDate; + } + + public void setFromDate(String fromDate) { + this.fromDate = fromDate; + } + + public String getToDate() { + return toDate; + } + + public void setToDate(String toDate) { + this.toDate = toDate; + } +} diff --git a/financer-web-client/src/main/java/de/financer/form/SelectChartForm.java b/financer-web-client/src/main/java/de/financer/form/SelectChartForm.java new file mode 100644 index 0000000..f653b38 --- /dev/null +++ b/financer-web-client/src/main/java/de/financer/form/SelectChartForm.java @@ -0,0 +1,13 @@ +package de.financer.form; + +public class SelectChartForm { + private String chartType; + + public String getChartType() { + return chartType; + } + + public void setChartType(String chartType) { + this.chartType = chartType; + } +} diff --git a/financer-web-client/src/main/java/de/financer/util/ControllerUtils.java b/financer-web-client/src/main/java/de/financer/util/ControllerUtils.java index 6fbd38f..52ece98 100644 --- a/financer-web-client/src/main/java/de/financer/util/ControllerUtils.java +++ b/financer-web-client/src/main/java/de/financer/util/ControllerUtils.java @@ -11,10 +11,13 @@ import org.apache.commons.collections4.IterableUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.ui.Model; +import java.text.DateFormat; import java.time.LocalDate; import java.time.format.DateTimeFormatter; +import java.time.format.FormatStyle; import java.util.Comparator; import java.util.List; +import java.util.Locale; import java.util.stream.Collectors; public class ControllerUtils { @@ -55,6 +58,26 @@ public class ControllerUtils { return formatted.format(DateTimeFormatter.ofPattern(financerConfig.getDateFormat())); } + public static String formatDate(FinancerConfig financerConfig, String dateFromForm, Locale locale) { + if (StringUtils.isEmpty(dateFromForm)) { + return null; + } + + // The format is always "yyyy-MM-dd", see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/date + final LocalDate formatted = LocalDate.parse(dateFromForm, DateTimeFormatter.ofPattern("yyyy-MM-dd")); + + return formatted.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT).withLocale(locale)); + } + + public static LocalDate parseDate(FinancerConfig financerConfig, String dateFromForm) { + if (StringUtils.isEmpty(dateFromForm)) { + return null; + } + + // The format is always "yyyy-MM-dd", see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/date + return LocalDate.parse(dateFromForm, DateTimeFormatter.ofPattern("yyyy-MM-dd")); + } + public static List filterEmptyEntries(Iterable recurringTransactions) { return IterableUtils.toList(recurringTransactions).stream() .filter((rt) -> rt.getFromAccount() != null && rt.getToAccount() != null) diff --git a/financer-web-client/src/main/resources/i18n/message.properties b/financer-web-client/src/main/resources/i18n/message.properties index 8cc88e2..54d9a8a 100644 --- a/financer-web-client/src/main/resources/i18n/message.properties +++ b/financer-web-client/src/main/resources/i18n/message.properties @@ -7,6 +7,7 @@ financer.account-overview.available-actions.create-transaction=Create new transa financer.account-overview.available-actions.create-recurring-transaction=Create new recurring transaction financer.account-overview.available-actions.recurring-transaction-all=Show all recurring transactions financer.account-overview.available-actions.create-account-group=Create new account group +financer.account-overview.available-actions.select-chart=Generate a chart financer.account-overview.status=Status\: financer.account-overview.status.recurring-transaction-due-today=Recurring transactions due today\: financer.account-overview.status.recurring-transaction-active=Active recurring transactions\: @@ -18,7 +19,7 @@ financer.account-overview.table-header.group=Group financer.account-overview.table-header.balance=Current Balance financer.account-overview.table-header.type=Type financer.account-overview.table-header.status=Status -financer.account-overview.tooltip.status.current-expenses=Period from {0} to {1} +financer.account-overview.tooltip.status.current-expenses=Period from {0} to {1}. Clicking the amount will open a graphical overview about the expenses grouped by account group financer.account-overview.tooltip.status.current-assets=Assets available at short-notice financer.account-new.title=financer\: create new account @@ -103,6 +104,14 @@ financer.recurring-to-transaction-with-amount.title=financer\: create transactio financer.recurring-to-transaction-with-amount.label.amount=Amount\: financer.recurring-to-transaction-with-amount.submit=Create +financer.chart-select.title=Select a chart to generate +financer.chart-select.submit=Select + +financer.chart-config-account-group-expenses-for-period.title=Configure account group expenses for period chart +financer.chart-config-account-group-expenses-for-period.label.from-date=From date\: +financer.chart-config-account-group-expenses-for-period.label.to-date=To date\: +financer.chart-config-account-group-expenses-for-period.submit=Generate + financer.interval-type.DAILY=Daily financer.interval-type.WEEKLY=Weekly financer.interval-type.MONTHLY=Monthly @@ -133,10 +142,16 @@ financer.heading.recurring-transaction-list.dueToday=financer\: recurring transa financer.heading.recurring-transaction-list.active=financer\: active recurring transactions financer.heading.recurring-transaction-list.all=financer\: all recurring transaction financer.heading.recurring-to-transaction-with-amount=financer\: create transaction from recurring with amount +financer.heading.chart-select=financer\: select a chart to generate +financer.heading.chart-config-account-group-expenses-for-period=financer\: configure account group expenses for period chart financer.cancel-back-to-overview=Cancel and back to overview financer.chart.account-group-expenses-current-period.title=Expenses of the current period grouped by account group +financer.chart.account-group-expenses-for-period.title=Expenses for period from {0} to {1} grouped by account group + +financer.chart.name.ACCOUNT_GROUP_EXPENSES_CURRENT_PERIOD=Expenses of the current period grouped by account group +financer.chart.name.ACCOUNT_GROUP_EXPENSES_FOR_PERIOD=Expenses for a configurable period grouped by account group financer.error-message.UNKNOWN_ERROR=An unknown error occurred! financer.error-message.INVALID_ACCOUNT_TYPE=The selected account type is not valid! @@ -164,4 +179,5 @@ financer.error-message.TRANSACTION_NOT_FOUND=The transaction could not be found! financer.error-message.ACCOUNT_NOT_FOUND=The account could not be found! financer.error-message.DUPLICATE_ACCOUNT_KEY=An account with the given key already exists! financer.error-message.DUPLICATE_ACCOUNT_GROUP_NAME=An account group with the given key already exists! -financer.error-message.ACCOUNT_GROUP_NOT_FOUND=The account group could not be found! \ No newline at end of file +financer.error-message.ACCOUNT_GROUP_NOT_FOUND=The account group could not be found! +financer.error-message.UNKNOWN_CHART_TYPE=The selected chart type is not known! \ No newline at end of file diff --git a/financer-web-client/src/main/resources/i18n/message_de_DE.properties b/financer-web-client/src/main/resources/i18n/message_de_DE.properties index f2c1286..11eb9dc 100644 --- a/financer-web-client/src/main/resources/i18n/message_de_DE.properties +++ b/financer-web-client/src/main/resources/i18n/message_de_DE.properties @@ -7,6 +7,7 @@ financer.account-overview.available-actions.create-transaction=Neue Buchung erst financer.account-overview.available-actions.create-recurring-transaction=Neue wiederkehrende Buchung erstellen financer.account-overview.available-actions.recurring-transaction-all=Zeige alle wiederkehrende Buchungen financer.account-overview.available-actions.create-account-group=Neue Konto-Gruppe erstellen +financer.account-overview.available-actions.select-chart=Ein Diagramm erzeugen financer.account-overview.status=Status\: financer.account-overview.status.recurring-transaction-due-today=Wiederkehrende Buchungen heute f\u00E4llig\: financer.account-overview.status.recurring-transaction-active=Aktive wiederkehrende Buchungen\: @@ -18,7 +19,7 @@ financer.account-overview.table-header.group=Gruppe financer.account-overview.table-header.balance=Kontostand financer.account-overview.table-header.type=Typ financer.account-overview.table-header.status=Status -financer.account-overview.tooltip.status.current-expenses=Periode ab {0} bis {1} +financer.account-overview.tooltip.status.current-expenses=Periode ab {0} bis {1}. Durch Klicken des Betrags kann eine grafische \u00DCbersicht über die Ausgaben gruppiert nach Konto-Gruppe angezeigt werden financer.account-overview.tooltip.status.current-assets=Kurzfristig verf\u00FCgbares Verm\u00F6gen financer.account-new.title=financer\: Neues Konto erstellen @@ -103,6 +104,14 @@ financer.recurring-to-transaction-with-amount.title=financer\: Buchung mit Betra financer.recurring-to-transaction-with-amount.label.amount=Betrag\: financer.recurring-to-transaction-with-amount.submit=Erstellen +financer.chart-select.title=Ein Diagramm zum Erzeugen ausw\u00E4hlen +financer.chart-select.submit=Ausw\u00E4hlen + +financer.chart-config-account-group-expenses-for-period.title=Konfigurieren von Ausgaben f\u00FCr Periode gruppiert nach Konto-Gruppe Diagramm +financer.chart-config-account-group-expenses-for-period.label.from-date=Von Datum\: +financer.chart-config-account-group-expenses-for-period.label.to-date=Bis Datum\: +financer.chart-config-account-group-expenses-for-period.submit=Erzeugen + financer.interval-type.DAILY=T\u00E4glich financer.interval-type.WEEKLY=W\u00F6chentlich financer.interval-type.MONTHLY=Monatlich @@ -133,7 +142,13 @@ financer.heading.recurring-transaction-list.dueToday=financer\: wiederkehrende B financer.heading.recurring-transaction-list.active=financer\: aktive wiederkehrende Buchungen financer.heading.recurring-transaction-list.all=financer\: alle wiederkehrende Buchungen financer.heading.recurring-to-transaction-with-amount=financer\: Buchung mit Betrag aus wiederkehrender Buchung erstellen +financer.heading.chart-select=financer\: ein Diagramm zum Erzeugen ausw\u00E4hlen +financer.heading.chart-config-account-group-expenses-for-period=financer\: konfigurieren von Ausgaben f\u00FCr Periode gruppiert nach Konto-Gruppe Diagramm financer.cancel-back-to-overview=Abbrechen und zur \u00DCbersicht -financer.chart.account-group-expenses-current-period.title=Ausgaben in der aktuellen Periode gruppiert nach Konto-Gruppe \ No newline at end of file +financer.chart.account-group-expenses-current-period.title=Ausgaben in der aktuellen Periode gruppiert nach Konto-Gruppe +financer.chart.account-group-expenses-for-period.title=Ausgaben in der Periode vom {0} bis {1} gruppiert nach Konto-Gruppe + +financer.chart.name.ACCOUNT_GROUP_EXPENSES_CURRENT_PERIOD=Ausgaben in der aktuellen Periode gruppiert nach Konto-Gruppe +financer.chart.name.ACCOUNT_GROUP_EXPENSES_FOR_PERIOD=Ausgaben f\u00FCr eine konfigurierbare Periode gruppiert nach Konto-Gruppe \ No newline at end of file diff --git a/financer-web-client/src/main/resources/static/css/main.css b/financer-web-client/src/main/resources/static/css/main.css index 6644a3f..0251481 100644 --- a/financer-web-client/src/main/resources/static/css/main.css +++ b/financer-web-client/src/main/resources/static/css/main.css @@ -67,15 +67,24 @@ tr:hover { #new-transaction-form *, #new-recurring-transaction-form *, #recurring-to-transaction-with-amount-form *, -#new-account-group-form * { +#new-account-group-form *, +#chart-config-account-group-expenses-for-period-form * { display: block; margin-top: 1em; width: 20em; box-sizing: border-box; } +#chart-select-form div { + width: 20em; + margin-top: 1em; + display: block; +} + input[type=submit] { + margin-top: 1em; margin-bottom: 1em; + width: 20em; } #footer-container { diff --git a/financer-web-client/src/main/resources/templates/account/accountOverview.html b/financer-web-client/src/main/resources/templates/account/accountOverview.html index 4a7ee60..a2dbc17 100644 --- a/financer-web-client/src/main/resources/templates/account/accountOverview.html +++ b/financer-web-client/src/main/resources/templates/account/accountOverview.html @@ -28,6 +28,7 @@ +

@@ -48,6 +49,10 @@
+
+ +
diff --git a/financer-web-client/src/main/resources/templates/report/configureAccountGroupExpensesForPeriod.html b/financer-web-client/src/main/resources/templates/report/configureAccountGroupExpensesForPeriod.html new file mode 100644 index 0000000..1208d4d --- /dev/null +++ b/financer-web-client/src/main/resources/templates/report/configureAccountGroupExpensesForPeriod.html @@ -0,0 +1,23 @@ + + + + + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <link rel="stylesheet" th:href="@{/css/main.css}"> +</head> +<body> +<h1 th:text="#{financer.heading.chart-config-account-group-expenses-for-period}"/> +<span class="errorMessage" th:if="${errorMessage != null}" th:text="#{'financer.error-message.' + ${errorMessage}}"/> +<a th:href="@{/accountOverview}" th:text="#{financer.cancel-back-to-overview}"/> +<form id="chart-config-account-group-expenses-for-period-form" action="#" + th:action="@{/getAccountGroupExpensesForPeriod}" th:object="${form}" method="post"> + <label for="fromDate" th:text="#{financer.chart-config-account-group-expenses-for-period.label.from-date}"/> + <input type="date" id="fromDate" th:field="*{fromDate}"/> + <label for="toDate" th:text="#{financer.chart-config-account-group-expenses-for-period.label.to-date}"/> + <input type="date" id="toDate" th:field="*{toDate}"/> + <input type="submit" th:value="#{financer.chart-config-account-group-expenses-for-period.submit}"/> +</form> +<div th:replace="includes/footer :: footer"/> +</body> +</html> \ No newline at end of file diff --git a/financer-web-client/src/main/resources/templates/report/selectChart.html b/financer-web-client/src/main/resources/templates/report/selectChart.html new file mode 100644 index 0000000..d53a74f --- /dev/null +++ b/financer-web-client/src/main/resources/templates/report/selectChart.html @@ -0,0 +1,24 @@ +<!DOCTYPE HTML> +<html xmlns:th="http://www.thymeleaf.org"> +<head> + <title th:text="#{financer.chart-select.title}"/> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <link rel="stylesheet" th:href="@{/css/main.css}"> +</head> +<body> +<h1 th:text="#{financer.heading.chart-select}"/> +<span class="errorMessage" th:if="${errorMessage != null}" th:text="#{'financer.error-message.' + ${errorMessage}}"/> +<a th:href="@{/accountOverview}" th:text="#{financer.cancel-back-to-overview}"/> +<form id="chart-select-form" action="#" th:action="@{/configureChart}" th:object="${form}" method="post"> + <th:block th:each="chart, iterStat : ${availableCharts}"> + <div> + <input type="radio" th:value="${chart}" th:field="*{chartType}" th:id="'chart' + ${iterStat.count}"/> + <label th:for="'chart' + ${iterStat.count}" th:text="#{${'financer.chart.name.' + chart}}"/> + </div> + </th:block> + <input type="submit" th:value="#{financer.chart-select.submit}"/> +</form> +<div th:replace="includes/footer :: footer"/> +</body> +</html> \ No newline at end of file