Custom Reports Enable Legend (#2078)

* enable Legend

* notes

* adding type

* overhaul

* calculateLegend
This commit is contained in:
Neil
2023-12-16 21:38:45 +00:00
committed by GitHub
parent 4497fbcb10
commit e62e8ca24e
10 changed files with 86 additions and 120 deletions

View File

@@ -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');

View File

@@ -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} />

View File

@@ -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;

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>
)}

View File

@@ -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;

View File

@@ -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),

View File

@@ -0,0 +1,6 @@
---
category: Enhancements
authors: [carkom]
---
Enable Legend for custom reports.