From e62e8ca24eb932d4e7004327650eb0d0c0f24b23 Mon Sep 17 00:00:00 2001 From: Neil <55785687+carkom@users.noreply.github.com> Date: Sat, 16 Dec 2023 21:38:45 +0000 Subject: [PATCH] Custom Reports Enable Legend (#2078) * enable Legend * notes * adding type * overhaul * calculateLegend --- .../src/components/reports/ReportSidebar.js | 2 +- .../src/components/reports/ReportTopbar.js | 7 ++- .../src/components/reports/entities.d.ts | 10 +++- .../components/reports/graphs/BarGraph.tsx | 38 ++------------- .../components/reports/graphs/DonutGraph.tsx | 42 ++--------------- .../reports/graphs/StackedBarGraph.tsx | 46 +++++-------------- .../reports/reports/CustomReport.js | 7 +-- .../reports/spreadsheets/calculateLegend.ts | 31 +++++++++++++ .../spreadsheets/default-spreadsheet.tsx | 17 ++++++- upcoming-release-notes/2078.md | 6 +++ 10 files changed, 86 insertions(+), 120 deletions(-) create mode 100644 packages/desktop-client/src/components/reports/spreadsheets/calculateLegend.ts create mode 100644 upcoming-release-notes/2078.md diff --git a/packages/desktop-client/src/components/reports/ReportSidebar.js b/packages/desktop-client/src/components/reports/ReportSidebar.js index 347f3184f..d3bad3e9a 100644 --- a/packages/desktop-client/src/components/reports/ReportSidebar.js +++ b/packages/desktop-client/src/components/reports/ReportSidebar.js @@ -99,7 +99,7 @@ export function ReportSidebar({ } if (['AreaGraph', 'DonutGraph'].includes(graphType)) { setGraphType('TableGraph'); - //setViewLegend(false); + setViewLegend(false); } if (['Month', 'Year'].includes(groupBy)) { setGroupBy('Category'); diff --git a/packages/desktop-client/src/components/reports/ReportTopbar.js b/packages/desktop-client/src/components/reports/ReportTopbar.js index c623a5203..353f9ddcb 100644 --- a/packages/desktop-client/src/components/reports/ReportTopbar.js +++ b/packages/desktop-client/src/components/reports/ReportTopbar.js @@ -45,7 +45,7 @@ export function ReportTopbar({ title="Data Table" onSelect={() => { setGraphType('TableGraph'); - //setViewLegend(false); + setViewLegend(false); setTypeDisabled([]); }} style={{ marginRight: 15 }} @@ -78,7 +78,7 @@ export function ReportTopbar({ onSelect={() => { setGraphType('AreaGraph'); setGroupBy('Month'); - //setViewLegend(false); + setViewLegend(false); setTypeDisabled([]); }} style={{ marginRight: 15 }} @@ -116,8 +116,7 @@ export function ReportTopbar({ style={{ marginRight: 15 }} title="Show Legend" disabled={ - true //descoping for future PR - //graphType === 'TableGraph' || graphType === 'AreaGraph' ? true : false + graphType === 'TableGraph' || graphType === 'AreaGraph' ? true : false } > <ListBullet width={15} height={15} /> diff --git a/packages/desktop-client/src/components/reports/entities.d.ts b/packages/desktop-client/src/components/reports/entities.d.ts index cbd01affb..d58698837 100644 --- a/packages/desktop-client/src/components/reports/entities.d.ts +++ b/packages/desktop-client/src/components/reports/entities.d.ts @@ -2,6 +2,7 @@ export type DataEntity = { data: Array<ItemEntity>; monthData: Array<MonthData>; groupedData: Array<GroupedEntity>; + legend: LegendEntity[]; startDate: string; endDate: string; totalDebts: number; @@ -9,7 +10,12 @@ export type DataEntity = { totalTotals: number; }; -type ItemEntity = { +type LegendEntity = { + name: string; + color: string; +}; + +export type ItemEntity = { id: string; name: string; monthData: MonthData[]; @@ -18,7 +24,7 @@ type ItemEntity = { totalTotals: number; }; -type MonthData = { +export type MonthData = { date: string; totalAssets: number; totalDebts: number; diff --git a/packages/desktop-client/src/components/reports/graphs/BarGraph.tsx b/packages/desktop-client/src/components/reports/graphs/BarGraph.tsx index ca7c4d042..9a44dfd90 100644 --- a/packages/desktop-client/src/components/reports/graphs/BarGraph.tsx +++ b/packages/desktop-client/src/components/reports/graphs/BarGraph.tsx @@ -5,7 +5,6 @@ import { BarChart, Bar, CartesianGrid, - //Legend, Cell, ReferenceLine, XAxis, @@ -21,7 +20,6 @@ import { theme } from '../../../style'; import { type CSSProperties } from '../../../style'; import AlignedText from '../../common/AlignedText'; import PrivacyFilter from '../../PrivacyFilter'; -import { getColorScale } from '../chart-theme'; import Container from '../Container'; import { type DataEntity } from '../entities'; import getCustomTick from '../getCustomTick'; @@ -107,26 +105,6 @@ const CustomTooltip = ({ ); } }; -/* Descoped for future PR -type CustomLegendProps = { - active?: boolean; - payload?: PayloadItem[]; - label?: string; -}; - -const CustomLegend = ({ active, payload, label }: CustomLegendProps) => { - const agg = payload[0].payload.children.map(leg => { - return { - name: leg.props.name, - color: leg.props.fill, - }; - }); - - OnChangeLegend(agg); - - return <div />; -}; -*/ type BarGraphProps = { style?: CSSProperties; @@ -145,7 +123,6 @@ function BarGraph({ }: BarGraphProps) { const privacyMode = usePrivacyMode(); - const colorScale = getColorScale('qualitative'); const yAxis = ['Month', 'Year'].includes(groupBy) ? 'date' : 'name'; const splitData = ['Month', 'Year'].includes(groupBy) ? 'monthData' : 'data'; @@ -180,9 +157,6 @@ function BarGraph({ data={data[splitData]} margin={{ top: 0, right: 0, left: 0, bottom: 0 }} > - { - //!compact && <Legend content={<CustomLegend />} /> - } <Tooltip content={ <CustomTooltip @@ -215,17 +189,11 @@ function BarGraph({ <ReferenceLine y={0} stroke={theme.pageTextLight} /> )} <Bar dataKey={val => getVal(val)} stackId="a"> - {data[splitData].map((entry, index) => ( + {data.legend.map((entry, index) => ( <Cell key={`cell-${index}`} - fill={ - yAxis === 'date' - ? balanceTypeOp === 'totalDebts' - ? theme.reportsRed - : theme.reportsBlue - : colorScale[index % colorScale.length] - } - name={entry[yAxis]} + fill={entry.color} + name={entry.name} /> ))} </Bar> diff --git a/packages/desktop-client/src/components/reports/graphs/DonutGraph.tsx b/packages/desktop-client/src/components/reports/graphs/DonutGraph.tsx index 87b42a9d5..f377a48e9 100644 --- a/packages/desktop-client/src/components/reports/graphs/DonutGraph.tsx +++ b/packages/desktop-client/src/components/reports/graphs/DonutGraph.tsx @@ -1,14 +1,7 @@ import React from 'react'; import { css } from 'glamor'; -import { - PieChart, - Pie, - Cell, - //Legend, - Tooltip, - ResponsiveContainer, -} from 'recharts'; +import { PieChart, Pie, Cell, Tooltip, ResponsiveContainer } from 'recharts'; import { amountToCurrency } from 'loot-core/src/shared/util'; @@ -16,7 +9,6 @@ import { theme } from '../../../style'; import { type CSSProperties } from '../../../style'; import Text from '../../common/Text'; import PrivacyFilter from '../../PrivacyFilter'; -import { getColorScale } from '../chart-theme'; import Container from '../Container'; import { type DataEntity } from '../entities'; import numberFormatterTooltip from '../numberFormatter'; @@ -72,27 +64,6 @@ const CustomTooltip = ({ active, payload, label }: CustomTooltipProps) => { } }; -/* Descoped for future PR -type CustomLegendProps = { - active?: boolean; - payload?: PayloadItem[]; - label?: string; -}; - -const CustomLegend = ({ active, payload, label }: CustomLegendProps) => { - const agg = payload.map(leg => { - return { - name: leg.value, - color: leg.color, - }; - }); - - OnChangeLegend(agg); - - return <div />; -}; -*/ - type DonutGraphProps = { style?: CSSProperties; data: DataEntity; @@ -108,7 +79,6 @@ function DonutGraph({ balanceTypeOp, compact, }: DonutGraphProps) { - const colorScale = getColorScale('qualitative'); const yAxis = ['Month', 'Year'].includes(groupBy) ? 'date' : 'name'; const splitData = ['Month', 'Year'].includes(groupBy) ? 'monthData' : 'data'; @@ -133,9 +103,6 @@ function DonutGraph({ <div> {!compact && <div style={{ marginTop: '15px' }} />} <PieChart width={width} height={height}> - { - //<Legend content={<CustomLegend />} /> - } <Tooltip content={<CustomTooltip />} formatter={numberFormatterTooltip} @@ -149,11 +116,8 @@ function DonutGraph({ innerRadius={Math.min(width, height) * 0.2} fill="#8884d8" > - {data[splitData].map((entry, index) => ( - <Cell - key={`cell-${index}`} - fill={colorScale[index % colorScale.length]} - /> + {data.legend.map((entry, index) => ( + <Cell key={`cell-${index}`} fill={entry.color} /> ))} </Pie> </PieChart> diff --git a/packages/desktop-client/src/components/reports/graphs/StackedBarGraph.tsx b/packages/desktop-client/src/components/reports/graphs/StackedBarGraph.tsx index bb080e448..4eb60cfdb 100644 --- a/packages/desktop-client/src/components/reports/graphs/StackedBarGraph.tsx +++ b/packages/desktop-client/src/components/reports/graphs/StackedBarGraph.tsx @@ -5,7 +5,6 @@ import { BarChart, Bar, CartesianGrid, - //Legend, XAxis, YAxis, Tooltip, @@ -19,7 +18,6 @@ import { theme } from '../../../style'; import { type CSSProperties } from '../../../style'; import AlignedText from '../../common/AlignedText'; import PrivacyFilter from '../../PrivacyFilter'; -import { getColorScale } from '../chart-theme'; import Container from '../Container'; import { type DataEntity } from '../entities'; import getCustomTick from '../getCustomTick'; @@ -93,27 +91,6 @@ const CustomTooltip = ({ active, payload, label }: CustomTooltipProps) => { } }; -/* Descoped for future PR -type CustomLegendProps = { - active?: boolean; - payload?: PayloadItem[]; - label?: string; -}; - -const CustomLegend = ({ active, payload, label }: CustomLegendProps) => { - const agg = payload.map(leg => { - return { - name: leg.value, - color: leg.color, - }; - }); - - OnChangeLegend(agg.slice(0).reverse()); - - return <div />; -}; -*/ - type StackedBarGraphProps = { style?: CSSProperties; data: DataEntity; @@ -122,7 +99,6 @@ type StackedBarGraphProps = { function StackedBarGraph({ style, data, compact }: StackedBarGraphProps) { const privacyMode = usePrivacyMode(); - const colorScale = getColorScale('qualitative'); return ( <Container @@ -142,9 +118,6 @@ function StackedBarGraph({ style, data, compact }: StackedBarGraphProps) { data={data.monthData} margin={{ top: 0, right: 0, left: 0, bottom: 0 }} > - { - //<Legend content={<CustomLegend />} /> - } <Tooltip content={<CustomTooltip />} formatter={numberFormatterTooltip} @@ -163,14 +136,17 @@ function StackedBarGraph({ style, data, compact }: StackedBarGraphProps) { tickLine={{ stroke: theme.pageText }} /> )} - {data.data.reverse().map((c, index) => ( - <Bar - key={c.name} - dataKey={c.name} - stackId="a" - fill={colorScale[index % colorScale.length]} - /> - ))} + {data.legend + .slice(0) + .reverse() + .map(entry => ( + <Bar + key={entry.name} + dataKey={entry.name} + stackId="a" + fill={entry.color} + /> + ))} </BarChart> </div> </ResponsiveContainer> diff --git a/packages/desktop-client/src/components/reports/reports/CustomReport.js b/packages/desktop-client/src/components/reports/reports/CustomReport.js index 01103a485..edd208d9a 100644 --- a/packages/desktop-client/src/components/reports/reports/CustomReport.js +++ b/packages/desktop-client/src/components/reports/reports/CustomReport.js @@ -64,8 +64,6 @@ export default function CustomReport() { const [viewLegend, setViewLegend] = useState(false); const [viewSummary, setViewSummary] = useState(false); const [viewLabels, setViewLabels] = useState(false); - //const [legend, setLegend] = useState([]); - const legend = []; const dateRangeLine = ReportOptions.dateRange.length - 3; const months = monthUtils.rangeInclusive(startDate, endDate); @@ -103,6 +101,7 @@ export default function CustomReport() { } run(); }, []); + const balanceTypeOp = ReportOptions.balanceTypeMap.get(balanceType); const payees = useCachedPayees(); const accounts = useCachedAccounts(); @@ -149,6 +148,7 @@ export default function CustomReport() { payees, accounts, setDataCheck, + graphType, }); }, [ startDate, @@ -164,6 +164,7 @@ export default function CustomReport() { showEmpty, showOffBudgetHidden, showUncategorized, + graphType, ]); const graphData = useReport('default', getGraphData); const groupedData = useReport('grouped', getGroupData); @@ -348,7 +349,7 @@ export default function CustomReport() { /> )} {viewLegend && ( - <ReportLegend legend={legend} groupBy={groupBy} /> + <ReportLegend legend={data.legend} groupBy={groupBy} /> )} </View> )} diff --git a/packages/desktop-client/src/components/reports/spreadsheets/calculateLegend.ts b/packages/desktop-client/src/components/reports/spreadsheets/calculateLegend.ts new file mode 100644 index 000000000..7ff756f4f --- /dev/null +++ b/packages/desktop-client/src/components/reports/spreadsheets/calculateLegend.ts @@ -0,0 +1,31 @@ +import { theme } from '../../../style'; +import { getColorScale } from '../chart-theme'; +import { type ItemEntity, type MonthData } from '../entities'; + +function calculateLegend( + monthData: MonthData[], + calcDataFiltered: ItemEntity[], + groupBy: string, + graphType: string, + balanceTypeOp: string, +) { + const colorScale = getColorScale('qualitative'); + const chooseData = ['Month', 'Year'].includes(groupBy) + ? monthData + : calcDataFiltered; + return chooseData.map((c, index) => { + return { + name: ['Month', 'Year'].includes(groupBy) ? c.date : c.name, + color: + graphType === 'DonutGraph' + ? colorScale[index % colorScale.length] + : ['Month', 'Year'].includes(groupBy) + ? balanceTypeOp === 'totalDebts' + ? theme.reportsRed + : theme.reportsBlue + : colorScale[index % colorScale.length], + }; + }); +} + +export default calculateLegend; diff --git a/packages/desktop-client/src/components/reports/spreadsheets/default-spreadsheet.tsx b/packages/desktop-client/src/components/reports/spreadsheets/default-spreadsheet.tsx index 23fcf52c9..e26e17360 100644 --- a/packages/desktop-client/src/components/reports/spreadsheets/default-spreadsheet.tsx +++ b/packages/desktop-client/src/components/reports/spreadsheets/default-spreadsheet.tsx @@ -14,6 +14,7 @@ import { import { categoryLists, groupBySelections } from '../ReportOptions'; +import calculateLegend from './calculateLegend'; import filterHiddenItems from './filterHiddenItems'; import makeQuery from './makeQuery'; import recalculate from './recalculate'; @@ -33,6 +34,7 @@ export type createSpreadsheetProps = { payees?: PayeeEntity[]; accounts?: AccountEntity[]; setDataCheck?: (value: boolean) => void; + graphType: string; }; export default function createSpreadsheet({ @@ -50,6 +52,7 @@ export default function createSpreadsheet({ payees, accounts, setDataCheck, + graphType, }: createSpreadsheetProps) { const [categoryList, categoryGroup] = categoryLists( showOffBudgetHidden, @@ -167,10 +170,22 @@ export default function createSpreadsheet({ const calc = recalculate({ item, months, assets, debts, groupByLabel }); return { ...calc }; }); + const calcDataFiltered = calcData.filter(i => + !showEmpty ? i[balanceTypeOp] !== 0 : true, + ); + + const legend = calculateLegend( + monthData, + calcDataFiltered, + groupBy, + graphType, + balanceTypeOp, + ); setData({ - data: calcData.filter(i => (!showEmpty ? i[balanceTypeOp] !== 0 : true)), + data: calcDataFiltered, monthData, + legend, startDate, endDate, totalDebts: integerToAmount(totalDebts), diff --git a/upcoming-release-notes/2078.md b/upcoming-release-notes/2078.md new file mode 100644 index 000000000..56a60e0b5 --- /dev/null +++ b/upcoming-release-notes/2078.md @@ -0,0 +1,6 @@ +--- +category: Enhancements +authors: [carkom] +--- + +Enable Legend for custom reports. -- GitLab