From 7ed4b73e894452656324f308c3a651de1f8bf939 Mon Sep 17 00:00:00 2001 From: Robert Goldmann <deadlocker@gmx.de> Date: Thu, 8 Dec 2022 23:20:49 +0100 Subject: [PATCH] #683 - added click feature for default charts --- .../budgetmaster/charts/ChartController.java | 22 +++++++++---------- .../budgetmaster/charts/DefaultCharts.java | 16 +++++++------- ...hlyIncomesAndExpendituresPerCategoryBar.js | 21 ++++++++++++++++++ ...MonthlyIncomesAndExpendituresPerYearBar.js | 19 ++++++++++++++++ .../AverageTransactionAmountPerCategoryBar.js | 21 ++++++++++++++++++ .../IncomesAndExpendituresByCategoryPie.js | 13 +++++++++++ .../IncomesAndExpendituresPerMonthBar.js | 21 +++++++++++++++++- ...omesAndExpendituresPerMonthByCategories.js | 21 ++++++++++++++++++ .../IncomesAndExpendituresPerYearBar.js | 22 ++++++++++++++++++- ...comesAndExpendituresPerYearByCategories.js | 21 ++++++++++++++++++ 10 files changed, 176 insertions(+), 21 deletions(-) diff --git a/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/charts/ChartController.java b/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/charts/ChartController.java index 969528dd3..f13b83849 100644 --- a/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/charts/ChartController.java +++ b/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/charts/ChartController.java @@ -273,11 +273,20 @@ public class ChartController extends BaseController { String title; final String clickedCategory = chartSettings.getClickedCategory(); - if(clickedCategory == null) + if(chartSettings.getClickedAmountType() == null) + { + for(FilterObject filterCategory : chartSettings.getFilterConfiguration().getFilterCategories()) + { + filterCategory.setInclude(filterCategory.getName().equals(clickedCategory)); + } + + title = Localization.getString("chart.matching.transactions.title.category", clickedCategory); + } + else { if(chartSettings.getClickedAmountType() == ChartAmountType.INCOME) { - title = Localization.getString("titles.incomes"); + title = Localization.getString("title.incomes"); chartSettings.getFilterConfiguration().setIncludeIncome(true); chartSettings.getFilterConfiguration().setIncludeExpenditure(false); } @@ -288,15 +297,6 @@ public class ChartController extends BaseController chartSettings.getFilterConfiguration().setIncludeExpenditure(true); } } - else - { - for(FilterObject filterCategory : chartSettings.getFilterConfiguration().getFilterCategories()) - { - filterCategory.setInclude(filterCategory.getName().equals(clickedCategory)); - } - - title = Localization.getString("chart.matching.transactions.title.category", clickedCategory); - } final List<Transaction> transactions = transactionService.getTransactionsForAccount(helpers.getCurrentAccount(), chartSettings.getStartDate(), chartSettings.getEndDate(), chartSettings.getFilterConfiguration()); final List<Transaction> convertedTransactions = convertTransferAmounts(transactions); diff --git a/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/charts/DefaultCharts.java b/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/charts/DefaultCharts.java index 53f935e1c..b67257ca1 100644 --- a/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/charts/DefaultCharts.java +++ b/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/charts/DefaultCharts.java @@ -24,7 +24,7 @@ public class DefaultCharts private static final Chart CHART_INCOMES_AND_EXPENDITURES_PER_MONTH_BAR = new Chart("charts.default.incomesAndExpendituresPerMonthBar", getChartFromFile("charts/IncomesAndExpendituresPerMonthBar.js"), - ChartType.DEFAULT, 12, ChartDisplayType.BAR, ChartGroupType.MONTH, "incomesAndExpendituresPerMonthBar.png"); + ChartType.DEFAULT, 13, ChartDisplayType.BAR, ChartGroupType.MONTH, "incomesAndExpendituresPerMonthBar.png"); private static final Chart CHART_INCOMES_AND_EXPENDITURES_PER_MONTH_LINE = new Chart("charts.default.incomesAndExpendituresPerMonthLine", getChartFromFile("charts/IncomesAndExpendituresPerMonthLine.js"), @@ -36,11 +36,11 @@ public class DefaultCharts private static final Chart CHART_INCOMES_AND_EXPENDITURES_BY_CATEGORY_PIE = new Chart("charts.default.incomesAndExpendituresByCategoryPie", getChartFromFile("charts/IncomesAndExpendituresByCategoryPie.js"), - ChartType.DEFAULT, 9, ChartDisplayType.PIE, ChartGroupType.NONE, "incomesAndExpendituresByCategoryPie.png"); + ChartType.DEFAULT, 12, ChartDisplayType.PIE, ChartGroupType.NONE, "incomesAndExpendituresByCategoryPie.png"); private static final Chart CHART_INCOMES_AND_EXPENDITURES_PER_MONTH_BY_CATEGORIES = new Chart("charts.default.incomesAndExpendituresPerMonthByCategories", getChartFromFile("charts/IncomesAndExpendituresPerMonthByCategories.js"), - ChartType.DEFAULT, 24, ChartDisplayType.BAR, ChartGroupType.MONTH, "incomesAndExpendituresPerMonthByCategories.png"); + ChartType.DEFAULT, 25, ChartDisplayType.BAR, ChartGroupType.MONTH, "incomesAndExpendituresPerMonthByCategories.png"); private static final Chart CHART_REST_PER_MONTH = new Chart("charts.default.restPerMonth", getChartFromFile("charts/RestPerMonth.js"), @@ -48,23 +48,23 @@ public class DefaultCharts private static final Chart CHART_INCOMES_AND_EXPENDITURES_PER_YEAR_BAR = new Chart("charts.default.incomesAndExpendituresPerYearBar", getChartFromFile("charts/IncomesAndExpendituresPerYearBar.js"), - ChartType.DEFAULT, 7, ChartDisplayType.BAR, ChartGroupType.YEAR, "incomesAndExpendituresPerYearBar.png"); + ChartType.DEFAULT, 10, ChartDisplayType.BAR, ChartGroupType.YEAR, "incomesAndExpendituresPerYearBar.png"); private static final Chart CHART_INCOMES_AND_EXPENDITURES_PER_YEAR_BY_CATEGORIES = new Chart("charts.default.incomesAndExpendituresPerYearByCategories", getChartFromFile("charts/IncomesAndExpendituresPerYearByCategories.js"), - ChartType.DEFAULT, 4, ChartDisplayType.BAR, ChartGroupType.YEAR, "incomesAndExpendituresPerYearByCategories.png"); + ChartType.DEFAULT, 5, ChartDisplayType.BAR, ChartGroupType.YEAR, "incomesAndExpendituresPerYearByCategories.png"); private static final Chart CHART_AVERAGE_TRANSACTION_AMOUNT_PER_CATEGORY = new Chart("charts.default.averageTransactionAmountPerCategory", getChartFromFile("charts/AverageTransactionAmountPerCategoryBar.js"), - ChartType.DEFAULT, 10, ChartDisplayType.BAR, ChartGroupType.NONE, "averageTransactionAmountPerCategory.png"); + ChartType.DEFAULT, 11, ChartDisplayType.BAR, ChartGroupType.NONE, "averageTransactionAmountPerCategory.png"); private static final Chart CHART_AVERAGE_MONTHLY_INCOMES_AND_EXPENDITURES_PER_YEAR_BAR = new Chart("charts.default.averageMonthlyIncomesAndExpendituresPerYearBar", getChartFromFile("charts/AverageMonthlyIncomesAndExpendituresPerYearBar.js"), - ChartType.DEFAULT, 10, ChartDisplayType.BAR, ChartGroupType.YEAR, "averageMonthlyIncomesAndExpendituresPerYearBar.png"); + ChartType.DEFAULT, 12, ChartDisplayType.BAR, ChartGroupType.YEAR, "averageMonthlyIncomesAndExpendituresPerYearBar.png"); private static final Chart CHART_AVERAGE_MONTHLY_INCOMES_AND_EXPENDITURES_PER_CATEGORY_BAR = new Chart("charts.default.averageMonthlyIncomesAndExpendituresPerCategoryBar", getChartFromFile("charts/AverageMonthlyIncomesAndExpendituresPerCategoryBar.js"), - ChartType.DEFAULT, 2, ChartDisplayType.BAR, ChartGroupType.NONE, "averageMonthlyIncomesAndExpendituresPerCategoryBar.png"); + ChartType.DEFAULT, 8, ChartDisplayType.BAR, ChartGroupType.NONE, "averageMonthlyIncomesAndExpendituresPerCategoryBar.png"); private DefaultCharts() { diff --git a/BudgetMasterServer/src/main/resources/charts/AverageMonthlyIncomesAndExpendituresPerCategoryBar.js b/BudgetMasterServer/src/main/resources/charts/AverageMonthlyIncomesAndExpendituresPerCategoryBar.js index b09348d31..e4652d885 100644 --- a/BudgetMasterServer/src/main/resources/charts/AverageMonthlyIncomesAndExpendituresPerCategoryBar.js +++ b/BudgetMasterServer/src/main/resources/charts/AverageMonthlyIncomesAndExpendituresPerCategoryBar.js @@ -105,6 +105,27 @@ var plotlyConfig = { Plotly.newPlot("containerID", plotlyData, plotlyLayout, plotlyConfig); +REGEX_CATGEORY_NAME = new RegExp("(.*)\\s-?\\d+.\\d\\s€"); + +var plotContainer = document.getElementById('containerID'); +plotContainer.on('plotly_click', function(data){ + if(data.event.shiftKey !== true) + { + return; + } + + let index = data.points.length - 1; + let hoverText = data.points[index].hovertext; + let match = hoverText.match(REGEX_CATGEORY_NAME); + if(match === null) + { + console.error('could not extract category name from: "' + hoverText + '"'); + return; + } + + getAndShowMatchingTransactions(null, match[1]); +}); + function addDPlotlyData(plotlyData, averageValue, categoryName, color, showLegend) { // add border if category color is white diff --git a/BudgetMasterServer/src/main/resources/charts/AverageMonthlyIncomesAndExpendituresPerYearBar.js b/BudgetMasterServer/src/main/resources/charts/AverageMonthlyIncomesAndExpendituresPerYearBar.js index 47470435b..dd149b1dc 100644 --- a/BudgetMasterServer/src/main/resources/charts/AverageMonthlyIncomesAndExpendituresPerYearBar.js +++ b/BudgetMasterServer/src/main/resources/charts/AverageMonthlyIncomesAndExpendituresPerYearBar.js @@ -128,6 +128,25 @@ var plotlyConfig = { Plotly.newPlot("containerID", plotlyData, plotlyLayout, plotlyConfig); +var plotContainer = document.getElementById('containerID'); +plotContainer.on('plotly_click', function(data){ + if(data.event.shiftKey !== true) + { + return; + } + + let index = data.points.length - 1; + let amountTypeText = data.points[index].data.name; + + let amountType = 'EXPENDITURE'; + if(amountTypeText === localizedData['traceName1']) + { + amountType = 'INCOME'; + } + + getAndShowMatchingTransactions(amountType, null); +}); + function prepareHoverText(value) { return value.toFixed(1) + ' ' + localizedCurrency; diff --git a/BudgetMasterServer/src/main/resources/charts/AverageTransactionAmountPerCategoryBar.js b/BudgetMasterServer/src/main/resources/charts/AverageTransactionAmountPerCategoryBar.js index b604e7b75..ac1f4718f 100644 --- a/BudgetMasterServer/src/main/resources/charts/AverageTransactionAmountPerCategoryBar.js +++ b/BudgetMasterServer/src/main/resources/charts/AverageTransactionAmountPerCategoryBar.js @@ -97,6 +97,27 @@ var plotlyConfig = { Plotly.newPlot("containerID", plotlyData, plotlyLayout, plotlyConfig); +REGEX_CATGEORY_NAME = new RegExp("(.*)\\s-?\\d+.\\d\\s€"); + +var plotContainer = document.getElementById('containerID'); +plotContainer.on('plotly_click', function(data){ + if(data.event.shiftKey !== true) + { + return; + } + + let index = data.points.length - 1; + let hoverText = data.points[index].hovertext; + let match = hoverText.match(REGEX_CATGEORY_NAME); + if(match === null) + { + console.error('could not extract category name from: "' + hoverText + '"'); + return; + } + + getAndShowMatchingTransactions(null, match[1]); +}); + function calculateAverage(values) { var sum = 0; diff --git a/BudgetMasterServer/src/main/resources/charts/IncomesAndExpendituresByCategoryPie.js b/BudgetMasterServer/src/main/resources/charts/IncomesAndExpendituresByCategoryPie.js index 66d12bb48..f8193d0ff 100644 --- a/BudgetMasterServer/src/main/resources/charts/IncomesAndExpendituresByCategoryPie.js +++ b/BudgetMasterServer/src/main/resources/charts/IncomesAndExpendituresByCategoryPie.js @@ -159,6 +159,19 @@ var plotlyConfig = { Plotly.newPlot("containerID", plotlyData, plotlyLayout, plotlyConfig); + +var plotContainer = document.getElementById('containerID'); +plotContainer.on('plotly_click', function(data){ + if(data.event.shiftKey !== true) + { + return; + } + + let index = data.points.length - 1; + getAndShowMatchingTransactions(null, data.points[index].label); +}); + + function addSeries(sumHandler, column) { var plotlyData = []; diff --git a/BudgetMasterServer/src/main/resources/charts/IncomesAndExpendituresPerMonthBar.js b/BudgetMasterServer/src/main/resources/charts/IncomesAndExpendituresPerMonthBar.js index b0f0a346b..91515689c 100644 --- a/BudgetMasterServer/src/main/resources/charts/IncomesAndExpendituresPerMonthBar.js +++ b/BudgetMasterServer/src/main/resources/charts/IncomesAndExpendituresPerMonthBar.js @@ -102,4 +102,23 @@ var plotlyConfig = { }; // Don't touch this line -Plotly.newPlot("containerID", plotlyData, plotlyLayout, plotlyConfig); \ No newline at end of file +Plotly.newPlot("containerID", plotlyData, plotlyLayout, plotlyConfig); + +var plotContainer = document.getElementById('containerID'); +plotContainer.on('plotly_click', function(data){ + if(data.event.shiftKey !== true) + { + return; + } + + let index = data.points.length - 1; + let amountTypeText = data.points[index].data.name; + + let amountType = 'EXPENDITURE'; + if(amountTypeText === localizedData['traceName1']) + { + amountType = 'INCOME'; + } + + getAndShowMatchingTransactions(amountType, null); +}); \ No newline at end of file diff --git a/BudgetMasterServer/src/main/resources/charts/IncomesAndExpendituresPerMonthByCategories.js b/BudgetMasterServer/src/main/resources/charts/IncomesAndExpendituresPerMonthByCategories.js index 4bd71aea8..5d6acc00f 100644 --- a/BudgetMasterServer/src/main/resources/charts/IncomesAndExpendituresPerMonthByCategories.js +++ b/BudgetMasterServer/src/main/resources/charts/IncomesAndExpendituresPerMonthByCategories.js @@ -198,6 +198,27 @@ var plotlyConfig = { Plotly.newPlot("containerID", plotlyData, plotlyLayout, plotlyConfig); +REGEX_CATGEORY_NAME = new RegExp("(.*)\\s\\d+.\\d%"); + +var plotContainer = document.getElementById('containerID'); +plotContainer.on('plotly_click', function(data){ + if(data.event.shiftKey !== true) + { + return; + } + + let index = data.points.length - 1; + let hoverText = data.points[index].hovertext; + let match = hoverText.match(REGEX_CATGEORY_NAME); + if(match === null) + { + console.error('could not extract category name from: "' + hoverText + '"'); + return; + } + + getAndShowMatchingTransactions(null, match[1]); +}); + function prepareHoverText(categoryName, percentage, value) { value = value / 100; diff --git a/BudgetMasterServer/src/main/resources/charts/IncomesAndExpendituresPerYearBar.js b/BudgetMasterServer/src/main/resources/charts/IncomesAndExpendituresPerYearBar.js index d03e7f05f..674fb55fd 100644 --- a/BudgetMasterServer/src/main/resources/charts/IncomesAndExpendituresPerYearBar.js +++ b/BudgetMasterServer/src/main/resources/charts/IncomesAndExpendituresPerYearBar.js @@ -102,4 +102,24 @@ var plotlyConfig = { }; // Don't touch this line -Plotly.newPlot("containerID", plotlyData, plotlyLayout, plotlyConfig); \ No newline at end of file +Plotly.newPlot("containerID", plotlyData, plotlyLayout, plotlyConfig); + + +var plotContainer = document.getElementById('containerID'); +plotContainer.on('plotly_click', function(data){ + if(data.event.shiftKey !== true) + { + return; + } + + let index = data.points.length - 1; + let amountTypeText = data.points[index].data.name; + + let amountType = 'EXPENDITURE'; + if(amountTypeText === localizedData['traceName1']) + { + amountType = 'INCOME'; + } + + getAndShowMatchingTransactions(amountType, null); +}); \ No newline at end of file diff --git a/BudgetMasterServer/src/main/resources/charts/IncomesAndExpendituresPerYearByCategories.js b/BudgetMasterServer/src/main/resources/charts/IncomesAndExpendituresPerYearByCategories.js index dcb1e0b4c..ff3413d9a 100644 --- a/BudgetMasterServer/src/main/resources/charts/IncomesAndExpendituresPerYearByCategories.js +++ b/BudgetMasterServer/src/main/resources/charts/IncomesAndExpendituresPerYearByCategories.js @@ -198,6 +198,27 @@ var plotlyConfig = { Plotly.newPlot("containerID", plotlyData, plotlyLayout, plotlyConfig); +REGEX_CATGEORY_NAME = new RegExp("(.*)\\s\\d+.\\d%"); + +var plotContainer = document.getElementById('containerID'); +plotContainer.on('plotly_click', function(data){ + if(data.event.shiftKey !== true) + { + return; + } + + let index = data.points.length - 1; + let hoverText = data.points[index].hovertext; + let match = hoverText.match(REGEX_CATGEORY_NAME); + if(match === null) + { + console.error('could not extract category name from: "' + hoverText + '"'); + return; + } + + getAndShowMatchingTransactions(null, match[1]); +}); + function prepareHoverText(categoryName, percentage, value) { value = value / 100; -- GitLab