diff --git a/packages/desktop-client/src/components/reports/ReportSidebar.js b/packages/desktop-client/src/components/reports/ReportSidebar.js index 347f3184f61fb043be08d62ac00c84e3185c3c17..d3bad3e9a1a57315c277135034cbf4b00eba78d6 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 c623a520327dcce25d20fa8b874a8694187c0027..353f9ddcb1ecc2c0a5b89c65b0a1fae5d798a788 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 cbd01affb5244cca3c6fc887406be4fdda90a0c4..d58698837380243eb08253b585ee0799b04bf574 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 ca7c4d0426511dab8c4907fecf33c042015ab3bf..9a44dfd907918f4b6e2576cceb8eda4b775e4e7d 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 87b42a9d5208faf344ddfbd5f6be48aeb821b000..f377a48e92b4b738dbd1fd40f5bb95af88d4b910 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 bb080e4485e973a3f0f0df7ea2a99a4e4c1901f9..4eb60cfdbd315413294a41363ea0d9aeec10fbae 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 01103a48532830554ff2fd6e572d963c9db913c9..edd208d9a30ffba18c7ec2e3297611e7bc5a3743 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 0000000000000000000000000000000000000000..7ff756f4fcb0841e62fb60f99e58d9f85892308f --- /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 23fcf52c9313a56d908a202925cbdf937eed8aa4..e26e173609042a17a21b8008d7ed7792b4294d5b 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 0000000000000000000000000000000000000000..56a60e0b50bc415871d634aedd616ca763e80cc9 --- /dev/null +++ b/upcoming-release-notes/2078.md @@ -0,0 +1,6 @@ +--- +category: Enhancements +authors: [carkom] +--- + +Enable Legend for custom reports.