diff --git a/packages/desktop-client/src/components/filters/CompactFiltersButton.tsx b/packages/desktop-client/src/components/filters/CompactFiltersButton.tsx
new file mode 100644
index 00000000000..28f73ef9a1b
--- /dev/null
+++ b/packages/desktop-client/src/components/filters/CompactFiltersButton.tsx
@@ -0,0 +1,18 @@
+import React from 'react';
+
+import { Filter } from '../../icons/v1';
+import Button from '../common/Button';
+
+type CompactFiltersButtonProps = {
+ onClick: (newValue) => void;
+};
+
+function CompactFiltersButton({ onClick }: CompactFiltersButtonProps) {
+ return (
+
+ );
+}
+
+export default CompactFiltersButton;
diff --git a/packages/desktop-client/src/components/filters/FiltersButton.tsx b/packages/desktop-client/src/components/filters/FiltersButton.tsx
new file mode 100644
index 00000000000..1b3ef60aafc
--- /dev/null
+++ b/packages/desktop-client/src/components/filters/FiltersButton.tsx
@@ -0,0 +1,21 @@
+import React from 'react';
+
+import { SettingsSliderAlternate } from '../../icons/v2';
+import Button from '../common/Button';
+
+type FiltersButtonProps = {
+ onClick: (newValue) => void;
+};
+
+function FiltersButton({ onClick }: FiltersButtonProps) {
+ return (
+
+ );
+}
+
+export default FiltersButton;
diff --git a/packages/desktop-client/src/components/filters/FiltersMenu.js b/packages/desktop-client/src/components/filters/FiltersMenu.js
index dd5411203d9..544c3cedda1 100644
--- a/packages/desktop-client/src/components/filters/FiltersMenu.js
+++ b/packages/desktop-client/src/components/filters/FiltersMenu.js
@@ -24,10 +24,9 @@ import {
import { titleFirst } from 'loot-core/src/shared/util';
import DeleteIcon from '../../icons/v0/Delete';
-import Filter from '../../icons/v1/Filter';
-import SettingsSliderAlternate from '../../icons/v2/SettingsSliderAlternate';
import { theme } from '../../style';
import Button from '../common/Button';
+import HoverTarget from '../common/HoverTarget';
import Menu from '../common/Menu';
import Select from '../common/Select';
import Stack from '../common/Stack';
@@ -37,6 +36,8 @@ import Value from '../rules/Value';
import { Tooltip } from '../tooltips';
import GenericInput from '../util/GenericInput';
+import CompactFiltersButton from './CompactFiltersButton';
+import FiltersButton from './FiltersButton';
import { CondOpMenu } from './SavedFilters';
let filterFields = [
@@ -336,28 +337,7 @@ function ConfigureField({
);
}
-function ButtonType({ type, dispatch }) {
- return (
-
- );
-}
-
-export function FilterButton({ onApply, type }) {
+export function FilterButton({ onApply, compact, hover }) {
let filters = useFilters();
let { dateFormat } = useSelector(state => {
@@ -440,7 +420,32 @@ export function FilterButton({ onApply, type }) {
return (
-
+
+ hover && (
+
+ Filters
+
+ )
+ }
+ >
+ {compact ? (
+ dispatch({ type: 'select-field' })}
+ />
+ ) : (
+ dispatch({ type: 'select-field' })} />
+ )}
+
{state.fieldsOpen && (
;
+ categories: Array;
selectedCategories: CategoryListProps['items'];
setSelectedCategories: (selectedCategories: CategoryEntity[]) => null;
};
export default function CategorySelector({
categoryGroups,
+ categories,
selectedCategories,
setSelectedCategories,
}: CategorySelectorProps) {
const [uncheckedHidden, setUncheckedHidden] = useState(false);
+ const selectedCategoryMap = useMemo(
+ () => selectedCategories.map(selected => selected.id),
+ [selectedCategories],
+ );
+ const allCategoriesSelected = categories.every(category =>
+ selectedCategoryMap.includes(category.id),
+ );
+
+ const allCategoriesUnselected = !categories.some(category =>
+ selectedCategoryMap.includes(category.id),
+ );
+
+ let selectAll: CategoryEntity[] = [];
+ categoryGroups.map(categoryGroup =>
+ categoryGroup.categories.map(category => selectAll.push(category)),
+ );
+
return (
- <>
-
-
+
+
+ {
+ setSelectedCategories(selectAll);
+ }}
+ style={{ marginRight: 5, padding: 8 }}
+ >
+
+
+ {
+ setSelectedCategories([]);
+ }}
+ style={{ padding: 8 }}
+ >
+
+
+
+
{categoryGroups &&
@@ -166,6 +215,6 @@ export default function CategorySelector({
);
})}
- >
+
);
}
diff --git a/packages/desktop-client/src/components/reports/GraphButton.tsx b/packages/desktop-client/src/components/reports/GraphButton.tsx
new file mode 100644
index 00000000000..d3857def566
--- /dev/null
+++ b/packages/desktop-client/src/components/reports/GraphButton.tsx
@@ -0,0 +1,59 @@
+import React, { type HTMLProps } from 'react';
+
+import { type CSSProperties, theme } from '../../style';
+import Button from '../common/Button';
+import HoverTarget from '../common/HoverTarget';
+import Text from '../common/Text';
+import { Tooltip } from '../tooltips';
+
+type GraphButtonProps = HTMLProps & {
+ selected?: boolean;
+ style?: CSSProperties;
+ onSelect?: (newValue) => void;
+ title?: string;
+ disabled?: boolean;
+};
+
+const GraphButton = ({
+ selected,
+ children,
+ onSelect,
+ title,
+ style,
+ disabled,
+}: GraphButtonProps) => {
+ return (
+ (
+
+ {title}
+
+ )}
+ >
+
+ {children}
+
+
+ );
+};
+
+export default GraphButton;
diff --git a/packages/desktop-client/src/components/reports/Header.js b/packages/desktop-client/src/components/reports/Header.js
index 1e8fc518501..e1b6408bd1b 100644
--- a/packages/desktop-client/src/components/reports/Header.js
+++ b/packages/desktop-client/src/components/reports/Header.js
@@ -26,6 +26,18 @@ export function validateEnd(allMonths, start, end) {
return boundedRange(earliest, start, end);
}
+export function validateRange(allMonths, start, end) {
+ const latest = monthUtils.currentMonth();
+ const earliest = allMonths[allMonths.length - 1].name;
+ if (end > latest) {
+ end = latest;
+ }
+ if (start < earliest) {
+ start = earliest;
+ }
+ return [start, end];
+}
+
function boundedRange(earliest, start, end) {
const latest = monthUtils.currentMonth();
if (end > latest) {
diff --git a/packages/desktop-client/src/components/reports/LoadingIndicator.tsx b/packages/desktop-client/src/components/reports/LoadingIndicator.tsx
new file mode 100644
index 00000000000..8e71593df3c
--- /dev/null
+++ b/packages/desktop-client/src/components/reports/LoadingIndicator.tsx
@@ -0,0 +1,33 @@
+import React from 'react';
+
+import AnimatedLoading from '../../icons/AnimatedLoading';
+import { theme, styles } from '../../style';
+import Block from '../common/Block';
+import View from '../common/View';
+
+type LoadingIndicatorProps = {
+ message?: string;
+};
+
+const LoadingIndicator = ({ message }: LoadingIndicatorProps) => {
+ return (
+
+ {message && (
+ {message}
+ )}
+
+
+ );
+};
+
+export default LoadingIndicator;
diff --git a/packages/desktop-client/src/components/reports/Overview.js b/packages/desktop-client/src/components/reports/Overview.js
index 05082df5a88..5c2784bd001 100644
--- a/packages/desktop-client/src/components/reports/Overview.js
+++ b/packages/desktop-client/src/components/reports/Overview.js
@@ -2,7 +2,6 @@ import React from 'react';
import { useSelector } from 'react-redux';
import useFeatureFlag from '../../hooks/useFeatureFlag';
-import AnimatedLoading from '../../icons/AnimatedLoading';
import { styles } from '../../style';
import View from '../common/View';
@@ -12,20 +11,6 @@ import CustomReportCard from './reports/CustomReportCard';
import NetWorthCard from './reports/NetWorthCard';
import SankeyCard from './reports/SankeyCard';
-export function LoadingIndicator() {
- return (
-
-
-
- );
-}
-
export default function Overview() {
let categorySpendingReportFeatureFlag = useFeatureFlag(
'categorySpendingReport',
diff --git a/packages/desktop-client/src/components/reports/ReportOptions.tsx b/packages/desktop-client/src/components/reports/ReportOptions.tsx
index a310a5f026d..73e2fff5b51 100644
--- a/packages/desktop-client/src/components/reports/ReportOptions.tsx
+++ b/packages/desktop-client/src/components/reports/ReportOptions.tsx
@@ -18,6 +18,8 @@ const dateRangeOptions = [
{ description: '3 months', name: 2 },
{ description: '6 months', name: 5 },
{ description: '1 year', name: 11 },
+ { description: 'Year to date', name: 'yearToDate' },
+ { description: 'Last year', name: 'lastYear' },
{ description: 'All time', name: 'allMonths' },
];
diff --git a/packages/desktop-client/src/components/reports/ReportSidebar.js b/packages/desktop-client/src/components/reports/ReportSidebar.js
index 8a43f59d648..5f22d0a13c7 100644
--- a/packages/desktop-client/src/components/reports/ReportSidebar.js
+++ b/packages/desktop-client/src/components/reports/ReportSidebar.js
@@ -15,6 +15,7 @@ import {
validateEnd,
getLatestRange,
getFullRange,
+ validateRange,
} from './Header';
import { ReportOptions } from './ReportOptions';
@@ -73,7 +74,39 @@ export function ReportSidebar({
selectedCategories,
setSelectedCategories,
}) {
- function onChangeMode(cond) {
+ const onSelectRange = cond => {
+ switch (cond) {
+ case 'All time':
+ onChangeDates(...getFullRange(allMonths));
+ break;
+ case 'Year to date':
+ onChangeDates(
+ ...validateRange(
+ allMonths,
+ monthUtils.getYearStart(monthUtils.currentMonth()),
+ monthUtils.currentMonth(),
+ ),
+ );
+ break;
+ case 'Last year':
+ onChangeDates(
+ ...validateRange(
+ allMonths,
+ monthUtils.getYearStart(
+ monthUtils.prevYear(monthUtils.currentMonth()),
+ ),
+ monthUtils.getYearEnd(
+ monthUtils.prevYear(monthUtils.currentDate()),
+ ),
+ ),
+ );
+ break;
+ default:
+ onChangeDates(...getLatestRange(ReportOptions.dateRangeMap.get(cond)));
+ }
+ };
+
+ const onChangeMode = cond => {
setMode(cond);
if (cond === 'time') {
if (graphType === 'TableGraph') {
@@ -101,9 +134,9 @@ export function ReportSidebar({
setTypeDisabled([]);
}
}
- }
+ };
- function onChangeSplit(cond) {
+ const onChangeSplit = cond => {
setGroupBy(cond);
if (mode === 'total') {
if (graphType !== 'TableGraph') {
@@ -113,15 +146,16 @@ export function ReportSidebar({
if (['Net'].includes(balanceType) && graphType !== 'TableGraph') {
setBalanceType('Expense');
}
- }
+ };
return (
@@ -301,7 +335,7 @@ export function ReportSidebar({
{
setDateRange(e);
- if (e === 'allMonths') {
- onChangeDates(...getFullRange(allMonths));
- } else {
- onChangeDates(
- ...getLatestRange(ReportOptions.dateRangeMap.get(e)),
- );
- }
+ onSelectRange(e);
}}
options={ReportOptions.dateRange.map(option => [
option.description,
@@ -387,7 +415,7 @@ export function ReportSidebar({
diff --git a/packages/desktop-client/src/components/reports/ReportTableHeader.tsx b/packages/desktop-client/src/components/reports/ReportTableHeader.tsx
index 932d7e4a341..48ce3585072 100644
--- a/packages/desktop-client/src/components/reports/ReportTableHeader.tsx
+++ b/packages/desktop-client/src/components/reports/ReportTableHeader.tsx
@@ -2,7 +2,7 @@ import React from 'react';
import * as d from 'date-fns';
-import { theme } from '../../style';
+import { styles, theme } from '../../style';
import { Row, Cell } from '../table';
export default function ReportTableHeader({
@@ -23,6 +23,7 @@ export default function ReportTableHeader({
12 && item[groupByItem]}
style={{
minWidth: 125,
+ ...styles.tnum,
}}
/>
{item.monthData && mode === 'time'
@@ -59,6 +60,7 @@ const TableRow = memo(
|
|
>
@@ -106,6 +110,7 @@ const TableRow = memo(
style={{
fontWeight: 600,
minWidth: 85,
+ ...styles.tnum,
}}
width="flex"
privacyFilter
@@ -119,6 +124,7 @@ const TableRow = memo(
style={{
fontWeight: 600,
minWidth: 85,
+ ...styles.tnum,
}}
width="flex"
privacyFilter
diff --git a/packages/desktop-client/src/components/reports/ReportTableTotals.tsx b/packages/desktop-client/src/components/reports/ReportTableTotals.tsx
index 5f37740a9c5..1286a7f87dd 100644
--- a/packages/desktop-client/src/components/reports/ReportTableTotals.tsx
+++ b/packages/desktop-client/src/components/reports/ReportTableTotals.tsx
@@ -6,7 +6,7 @@ import {
integerToCurrency,
} from 'loot-core/src/shared/util';
-import { theme } from '../../style';
+import { styles, theme } from '../../style';
import { Row, Cell } from '../table';
export default function ReportTableTotals({
@@ -29,6 +29,7 @@ export default function ReportTableTotals({
- {children}
-
- );
-}
-
export function ReportTopbar({
graphType,
setGraphType,
@@ -67,6 +48,7 @@ export function ReportTopbar({
//setViewLegend(false);
setTypeDisabled([]);
}}
+ style={{ marginRight: 15 }}
>
@@ -86,7 +68,7 @@ export function ReportTopbar({
setBalanceType('Expense');
}
}}
- style={{ marginLeft: 15 }}
+ style={{ marginRight: 15 }}
>
@@ -99,7 +81,7 @@ export function ReportTopbar({
//setViewLegend(false);
setTypeDisabled([]);
}}
- style={{ marginLeft: 15 }}
+ style={{ marginRight: 15 }}
disabled={mode === 'total' ? false : true}
>
@@ -112,7 +94,7 @@ export function ReportTopbar({
setTypeDisabled(['Net']);
setBalanceType('Expense');
}}
- style={{ marginLeft: 15 }}
+ style={{ marginRight: 15 }}
disabled={mode === 'total' ? false : true}
>
@@ -121,8 +103,8 @@ export function ReportTopbar({
style={{
width: 1,
height: 30,
- backgroundColor: theme.altPillBorder,
- marginLeft: 15,
+ backgroundColor: theme.pillBorderDark,
+ marginRight: 15,
flexShrink: 0,
}}
/>
@@ -131,7 +113,7 @@ export function ReportTopbar({
onSelect={() => {
setViewLegend(!viewLegend);
}}
- style={{ marginLeft: 15 }}
+ style={{ marginRight: 15 }}
title="Show Legend"
disabled={
true //descoping for future PR
@@ -145,7 +127,7 @@ export function ReportTopbar({
onSelect={() => {
setViewSummary(!viewSummary);
}}
- style={{ marginLeft: 15 }}
+ style={{ marginRight: 15 }}
title="Show Summary"
>
@@ -155,7 +137,7 @@ export function ReportTopbar({
onSelect={() => {
setViewLabels(!viewLabels);
}}
- style={{ marginLeft: 15 }}
+ style={{ marginRight: 15 }}
title="Show labels"
disabled={true}
>
@@ -165,13 +147,12 @@ export function ReportTopbar({
style={{
width: 1,
height: 30,
- backgroundColor: theme.altPillBorder,
+ backgroundColor: theme.pillBorderDark,
marginRight: 15,
- marginLeft: 15,
flexShrink: 0,
}}
/>
-
+
| |
diff --git a/packages/desktop-client/src/components/reports/getCustomTick.ts b/packages/desktop-client/src/components/reports/getCustomTick.ts
new file mode 100644
index 00000000000..07ab8f777b6
--- /dev/null
+++ b/packages/desktop-client/src/components/reports/getCustomTick.ts
@@ -0,0 +1,9 @@
+const getCustomTick = (value: string, isPrivacyModeEnabled: boolean) => {
+ if (isPrivacyModeEnabled) {
+ return '...';
+ } else {
+ return value;
+ }
+};
+
+export default getCustomTick;
diff --git a/packages/desktop-client/src/components/reports/graphs/AreaGraph.tsx b/packages/desktop-client/src/components/reports/graphs/AreaGraph.tsx
index 174e649f1c1..2370d57d0fe 100644
--- a/packages/desktop-client/src/components/reports/graphs/AreaGraph.tsx
+++ b/packages/desktop-client/src/components/reports/graphs/AreaGraph.tsx
@@ -11,6 +11,7 @@ import {
ResponsiveContainer,
} from 'recharts';
+import usePrivacyMode from 'loot-core/src/client/privacy';
import { amountToCurrency } from 'loot-core/src/shared/util';
import { theme } from '../../../style';
@@ -94,14 +95,14 @@ type AreaGraphProps = {
data;
balanceTypeOp;
compact: boolean;
- domain?: {
- totalTotals?: [number, number];
- };
};
function AreaGraph({ style, data, balanceTypeOp, compact }: AreaGraphProps) {
+ let privacyMode = usePrivacyMode();
+
const tickFormatter = tick => {
- return `${Math.round(tick).toLocaleString()}`; // Formats the tick values as strings with commas
+ if (!privacyMode) return `${Math.round(tick).toLocaleString()}`; // Formats the tick values as strings with commas
+ return '...';
};
const gradientOffset = () => {
diff --git a/packages/desktop-client/src/components/reports/graphs/BarGraph.tsx b/packages/desktop-client/src/components/reports/graphs/BarGraph.tsx
index 79f169864a5..6fdaf45a21e 100644
--- a/packages/desktop-client/src/components/reports/graphs/BarGraph.tsx
+++ b/packages/desktop-client/src/components/reports/graphs/BarGraph.tsx
@@ -14,6 +14,7 @@ import {
ResponsiveContainer,
} from 'recharts';
+import usePrivacyMode from 'loot-core/src/client/privacy';
import { amountToCurrency } from 'loot-core/src/shared/util';
import { theme } from '../../../style';
@@ -22,6 +23,7 @@ import AlignedText from '../../common/AlignedText';
import PrivacyFilter from '../../PrivacyFilter';
import { getColorScale } from '../chart-theme';
import Container from '../Container';
+import getCustomTick from '../getCustomTick';
import numberFormatterTooltip from '../numberFormatter';
type PayloadChild = {
@@ -32,7 +34,6 @@ type PayloadChild = {
};
type PayloadItem = {
- value: string;
payload: {
name: string;
totalAssets: number | string;
@@ -105,7 +106,6 @@ const CustomTooltip = ({
);
}
};
-
/* Descoped for future PR
type CustomLegendProps = {
active?: boolean;
@@ -148,6 +148,8 @@ function BarGraph({
compact,
domain,
}: BarGraphProps) {
+ let privacyMode = usePrivacyMode();
+
const colorScale = getColorScale('qualitative');
const yAxis = ['Month', 'Year'].includes(groupBy) ? 'date' : 'name';
const splitData = ['Month', 'Year'].includes(groupBy) ? 'monthData' : 'data';
@@ -211,6 +213,7 @@ function BarGraph({
)}
{!compact && (
getCustomTick(value, privacyMode)}
tick={{ fill: theme.pageText }}
tickLine={{ stroke: theme.pageText }}
/>
diff --git a/packages/desktop-client/src/components/reports/graphs/StackedBarGraph.tsx b/packages/desktop-client/src/components/reports/graphs/StackedBarGraph.tsx
index 228798f7081..f0925ab9a1d 100644
--- a/packages/desktop-client/src/components/reports/graphs/StackedBarGraph.tsx
+++ b/packages/desktop-client/src/components/reports/graphs/StackedBarGraph.tsx
@@ -12,6 +12,7 @@ import {
ResponsiveContainer,
} from 'recharts';
+import usePrivacyMode from 'loot-core/src/client/privacy';
import { amountToCurrency } from 'loot-core/src/shared/util';
import { theme } from '../../../style';
@@ -20,6 +21,7 @@ import AlignedText from '../../common/AlignedText';
import PrivacyFilter from '../../PrivacyFilter';
import { getColorScale } from '../chart-theme';
import Container from '../Container';
+import getCustomTick from '../getCustomTick';
import numberFormatterTooltip from '../numberFormatter';
type PayloadItem = {
@@ -116,28 +118,12 @@ type StackedBarGraphProps = {
data;
balanceTypeOp;
compact: boolean;
- domain?: {
- y?: [number, number];
- };
};
-function StackedBarGraph({
- style,
- data,
- balanceTypeOp,
- compact,
- domain,
-}: StackedBarGraphProps) {
+function StackedBarGraph({ style, data, compact }: StackedBarGraphProps) {
+ let privacyMode = usePrivacyMode();
const colorScale = getColorScale('qualitative');
- const getVal = (obj, key) => {
- if (balanceTypeOp === 'totalDebts') {
- return -1 * obj[key].amount;
- } else {
- return obj[key].amount;
- }
- };
-
return (
{!compact && (
getCustomTick(value, privacyMode)}
tick={{ fill: theme.pageText }}
tickLine={{ stroke: theme.pageText }}
/>
)}
- {data.groupBy
- .slice(0)
- .reverse()
- .map((c, index) => (
- getVal(val, c.name)}
- name={c.name}
- stackId="a"
- fill={colorScale[index % colorScale.length]}
- />
- ))}
+ {data.groupBy.reverse().map((c, index) => (
+
+ ))}
diff --git a/packages/desktop-client/src/components/reports/reports/CashFlowCard.js b/packages/desktop-client/src/components/reports/reports/CashFlowCard.js
index 1ccf6dfc650..bc752f4bbf4 100644
--- a/packages/desktop-client/src/components/reports/reports/CashFlowCard.js
+++ b/packages/desktop-client/src/components/reports/reports/CashFlowCard.js
@@ -13,7 +13,7 @@ import Change from '../Change';
import { chartTheme } from '../chart-theme';
import Container from '../Container';
import DateRange from '../DateRange';
-import { LoadingIndicator } from '../Overview';
+import LoadingIndicator from '../LoadingIndicator';
import ReportCard from '../ReportCard';
import { simpleCashFlow } from '../spreadsheets/cash-flow-spreadsheet';
import Tooltip from '../Tooltip';
@@ -56,7 +56,7 @@ function CashFlowCard() {
diff --git a/packages/desktop-client/src/components/reports/reports/CategorySpendingCard.js b/packages/desktop-client/src/components/reports/reports/CategorySpendingCard.js
index 1b4742c1820..2a705305d9f 100644
--- a/packages/desktop-client/src/components/reports/reports/CategorySpendingCard.js
+++ b/packages/desktop-client/src/components/reports/reports/CategorySpendingCard.js
@@ -8,7 +8,7 @@ import Block from '../../common/Block';
import View from '../../common/View';
import DateRange from '../DateRange';
import CategorySpendingGraph from '../graphs/CategorySpendingGraph';
-import { LoadingIndicator } from '../Overview';
+import LoadingIndicator from '../LoadingIndicator';
import ReportCard from '../ReportCard';
import categorySpendingSpreadsheet from '../spreadsheets/category-spending-spreadsheet';
import useReport from '../useReport';
diff --git a/packages/desktop-client/src/components/reports/reports/CustomReport.js b/packages/desktop-client/src/components/reports/reports/CustomReport.js
index 8aeb682c95d..a2b43f8184f 100644
--- a/packages/desktop-client/src/components/reports/reports/CustomReport.js
+++ b/packages/desktop-client/src/components/reports/reports/CustomReport.js
@@ -1,8 +1,9 @@
import React, { useState, useEffect, useMemo } from 'react';
-import { useSelector } from 'react-redux';
import * as d from 'date-fns';
+import { useCachedAccounts } from 'loot-core/src/client/data-hooks/accounts';
+import { useCachedPayees } from 'loot-core/src/client/data-hooks/payees';
import { send } from 'loot-core/src/platform/client/fetch';
import * as monthUtils from 'loot-core/src/shared/months';
import { amountToCurrency } from 'loot-core/src/shared/util';
@@ -18,6 +19,7 @@ import { AppliedFilters } from '../../filters/FiltersMenu';
import PrivacyFilter from '../../PrivacyFilter';
import { ChooseGraph } from '../ChooseGraph';
import Header from '../Header';
+import LoadingIndicator from '../LoadingIndicator';
import { ReportOptions } from '../ReportOptions';
import { ReportSidebar } from '../ReportSidebar';
import { ReportLegend, ReportSummary } from '../ReportSummary';
@@ -29,13 +31,6 @@ import { fromDateRepr } from '../util';
export default function CustomReport() {
const categories = useCategories();
- let { payees, accounts } = useSelector(state => {
- return {
- payees: state.queries.payees,
- accounts: state.queries.accounts,
- };
- });
-
const {
filters,
conditionsOp,
@@ -60,6 +55,7 @@ export default function CustomReport() {
const [hidden, setHidden] = useState(false);
const [uncat, setUncat] = useState(false);
const [dateRange, setDateRange] = useState('6 months');
+ const [dataCheck, setDataCheck] = useState(false);
const [graphType, setGraphType] = useState('BarGraph');
const [viewLegend, setViewLegend] = useState(false);
@@ -67,39 +63,8 @@ export default function CustomReport() {
const [viewLabels, setViewLabels] = useState(false);
//const [legend, setLegend] = useState([]);
let legend = [];
- const dateRangeLine = ReportOptions.dateRange.length - 1;
-
+ const dateRangeLine = ReportOptions.dateRange.length - 3;
const months = monthUtils.rangeInclusive(start, end);
- const getGraphData = useMemo(() => {
- return defaultSpreadsheet(
- start,
- end,
- groupBy,
- ReportOptions.balanceTypeMap.get(balanceType),
- categories,
- selectedCategories,
- payees,
- accounts,
- filters,
- conditionsOp,
- hidden,
- uncat,
- );
- }, [
- start,
- end,
- groupBy,
- balanceType,
- categories,
- selectedCategories,
- payees,
- accounts,
- filters,
- conditionsOp,
- hidden,
- uncat,
- ]);
- const data = useReport('default', getGraphData);
useEffect(() => {
if (selectedCategories === null && categories.list.length !== 0) {
@@ -136,6 +101,42 @@ export default function CustomReport() {
run();
}, []);
+ let payees = useCachedPayees();
+ let accounts = useCachedAccounts();
+
+ const getGraphData = useMemo(() => {
+ setDataCheck(false);
+ return defaultSpreadsheet(
+ start,
+ end,
+ groupBy,
+ ReportOptions.balanceTypeMap.get(balanceType),
+ categories,
+ selectedCategories,
+ payees,
+ accounts,
+ filters,
+ conditionsOp,
+ hidden,
+ uncat,
+ setDataCheck,
+ );
+ }, [
+ start,
+ end,
+ groupBy,
+ balanceType,
+ categories,
+ selectedCategories,
+ payees,
+ accounts,
+ filters,
+ conditionsOp,
+ hidden,
+ uncat,
+ ]);
+ const data = useReport('default', getGraphData);
+
let [scrollWidth, setScrollWidth] = useState(0);
if (!allMonths || !data) {
@@ -149,12 +150,7 @@ export default function CustomReport() {
return (
-
+
)}
-
+
+ {dataCheck ? (
+
+ ) : (
+
+ )}
{(viewLegend || viewSummary) && (
diff --git a/packages/desktop-client/src/components/reports/reports/SankeyCard.js b/packages/desktop-client/src/components/reports/reports/SankeyCard.js
index 1732311dbfa..f79ec227260 100644
--- a/packages/desktop-client/src/components/reports/reports/SankeyCard.js
+++ b/packages/desktop-client/src/components/reports/reports/SankeyCard.js
@@ -8,7 +8,7 @@ import Block from '../../common/Block';
import View from '../../common/View';
import DateRange from '../DateRange';
import SankeyGraph from '../graphs/SankeyGraph';
-import { LoadingIndicator } from '../Overview';
+import LoadingIndicator from '../LoadingIndicator';
import ReportCard from '../ReportCard';
import sankeySpreadsheet from '../spreadsheets/sankey-spreadsheet';
import useReport from '../useReport';
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 5e20982ce58..b55a7b71bd8 100644
--- a/packages/desktop-client/src/components/reports/spreadsheets/default-spreadsheet.tsx
+++ b/packages/desktop-client/src/components/reports/spreadsheets/default-spreadsheet.tsx
@@ -5,13 +5,13 @@ import { send } from 'loot-core/src/platform/client/fetch';
import * as monthUtils from 'loot-core/src/shared/months';
import { integerToAmount, amountToInteger } from 'loot-core/src/shared/util';
-import { index } from '../util';
+import { index, indexStack } from '../util';
export default function createSpreadsheet(
start,
end,
groupBy,
- typeItem,
+ balanceTypeOp,
categories,
selectedCategories,
payees,
@@ -20,6 +20,7 @@ export default function createSpreadsheet(
conditionsOp,
hidden,
uncat,
+ setDataCheck,
) {
let uncatCat = {
name: 'Uncategorized',
@@ -282,8 +283,9 @@ export default function createSpreadsheet(
};
});
- const categoryGroupCalcData = catGroup.map(group => {
- if (hidden || group.hidden === 0) {
+ const categoryGroupCalcData = catGroup
+ .filter(f => hidden || f.hidden === 0)
+ .map(group => {
let groupedStarting = 0;
const mon = months.map(month => {
let groupedAssets = 0;
@@ -317,10 +319,7 @@ export default function createSpreadsheet(
hidden: group.hidden,
balances: index(mon, 'date'),
};
- } else {
- return null;
- }
- });
+ });
const groupByData = groupBy === 'Group' ? categoryGroupCalcData : calcData;
@@ -329,35 +328,37 @@ export default function createSpreadsheet(
return { ...calc };
});
- const categoryGroupData = catGroup.map(group => {
- const catData = group.categories.map(graph => {
- let catMatch = null;
- calcData.map(cat => {
- if (
- cat.id === null
- ? cat.uncat_id === graph.uncat_id
- : cat.id === graph.id
- ) {
- catMatch = cat;
+ const categoryGroupData = catGroup
+ .filter(f => hidden || f.hidden === 0)
+ .map(group => {
+ const catData = group.categories.map(graph => {
+ let catMatch = null;
+ calcData.map(cat => {
+ if (
+ cat.id === null
+ ? cat.uncat_id === graph.uncat_id
+ : cat.id === graph.id
+ ) {
+ catMatch = cat;
+ }
+ return null;
+ });
+ const calcCat = catMatch && recalculate(catMatch, start, end);
+ return { ...calcCat };
+ });
+ let groupMatch = null;
+ categoryGroupCalcData.map(split => {
+ if (split.id === group.id) {
+ groupMatch = split;
}
return null;
});
- const calcCat = catMatch && recalculate(catMatch, start, end);
- return { ...calcCat };
- });
- let groupMatch = null;
- categoryGroupCalcData.map(split => {
- if (split.id === group.id) {
- groupMatch = split;
- }
- return null;
+ const calcGroup = groupMatch && recalculate(groupMatch, start, end);
+ return {
+ ...calcGroup,
+ categories: catData,
+ };
});
- const calcGroup = groupMatch && recalculate(groupMatch, start, end);
- return {
- ...calcGroup,
- categories: catData,
- };
- });
let totalAssets = 0;
let totalDebts = 0;
@@ -393,26 +394,27 @@ export default function createSpreadsheet(
});
const stackedData = months.map(month => {
- let perMonthAmounts = 0;
const stacked = data.map(graph => {
let stackAmounts = 0;
if (graph.indexedMonthData[month]) {
- perMonthAmounts += graph.indexedMonthData[month][typeItem];
- stackAmounts += graph.indexedMonthData[month][typeItem];
+ stackAmounts += graph.indexedMonthData[month][balanceTypeOp];
}
return {
name: graph.name,
id: graph.id,
- amount: stackAmounts,
+ amount: Math.abs(stackAmounts),
};
});
- const indexedStack = index(stacked, 'name');
+ const indexedStack = indexStack(
+ stacked.filter(i => i[balanceTypeOp] !== 0),
+ 'name',
+ 'amount',
+ );
return {
// eslint-disable-next-line rulesdir/typography
date: d.format(d.parseISO(`${month}-01`), "MMM ''yy"),
...indexedStack,
- totalTotals: perMonthAmounts,
};
});
@@ -428,6 +430,7 @@ export default function createSpreadsheet(
totalAssets: integerToAmount(totalAssets),
totalTotals: integerToAmount(totalTotals),
});
+ setDataCheck?.(true);
};
}
diff --git a/packages/desktop-client/src/components/reports/util.js b/packages/desktop-client/src/components/reports/util.js
index 1cae0b43d3f..b3cb72c85ad 100644
--- a/packages/desktop-client/src/components/reports/util.js
+++ b/packages/desktop-client/src/components/reports/util.js
@@ -21,6 +21,14 @@ export function index(data, field, mapper) {
return result;
}
+export function indexStack(data, fieldName, field) {
+ const result = {};
+ data.forEach(item => {
+ result[item[fieldName]] = item[field];
+ });
+ return result;
+}
+
export function indexCashFlow(data, date, isTransfer) {
const results = {};
data.forEach(item => {
diff --git a/packages/desktop-client/src/icons/v2/CheckAll.tsx b/packages/desktop-client/src/icons/v2/CheckAll.tsx
new file mode 100644
index 00000000000..69d0dc07965
--- /dev/null
+++ b/packages/desktop-client/src/icons/v2/CheckAll.tsx
@@ -0,0 +1,19 @@
+import * as React from 'react';
+import type { SVGProps } from 'react';
+const SvgCheckAll = (props: SVGProps) => (
+
+);
+export default SvgCheckAll;
diff --git a/packages/desktop-client/src/icons/v2/UncheckAll.tsx b/packages/desktop-client/src/icons/v2/UncheckAll.tsx
new file mode 100644
index 00000000000..13698bbea4d
--- /dev/null
+++ b/packages/desktop-client/src/icons/v2/UncheckAll.tsx
@@ -0,0 +1,19 @@
+import * as React from 'react';
+import type { SVGProps } from 'react';
+const SvgUncheckAll = (props: SVGProps) => (
+
+);
+export default SvgUncheckAll;
diff --git a/packages/desktop-client/src/icons/v2/check-all.svg b/packages/desktop-client/src/icons/v2/check-all.svg
new file mode 100644
index 00000000000..25f62f457bf
--- /dev/null
+++ b/packages/desktop-client/src/icons/v2/check-all.svg
@@ -0,0 +1,6 @@
+
+
diff --git a/packages/desktop-client/src/icons/v2/index.ts b/packages/desktop-client/src/icons/v2/index.ts
index c1455d4cdcb..a27e73a12f2 100644
--- a/packages/desktop-client/src/icons/v2/index.ts
+++ b/packages/desktop-client/src/icons/v2/index.ts
@@ -8,6 +8,7 @@ export { default as ArrowsShrink3 } from './ArrowsShrink3';
export { default as ArrowsSynchronize } from './ArrowsSynchronize';
export { default as Calendar3 } from './Calendar3';
export { default as Calendar } from './Calendar';
+export { default as CheckAll } from './CheckAll';
export { default as CheckCircle1 } from './CheckCircle1';
export { default as CheckCircleHollow } from './CheckCircleHollow';
export { default as Check } from './Check';
@@ -37,6 +38,7 @@ export { default as SearchAlternate } from './SearchAlternate';
export { default as SettingsSliderAlternate } from './SettingsSliderAlternate';
export { default as Subtract } from './Subtract';
export { default as Sun } from './Sun';
+export { default as UncheckAll } from './UncheckAll';
export { default as UploadThickBottom } from './UploadThickBottom';
export { default as ValidationCheck } from './ValidationCheck';
export { default as ViewHide } from './ViewHide';
diff --git a/packages/desktop-client/src/icons/v2/uncheck-all.svg b/packages/desktop-client/src/icons/v2/uncheck-all.svg
new file mode 100644
index 00000000000..b11cab4cc73
--- /dev/null
+++ b/packages/desktop-client/src/icons/v2/uncheck-all.svg
@@ -0,0 +1,6 @@
+
+
\ No newline at end of file
diff --git a/packages/desktop-client/src/style/themes/dark.ts b/packages/desktop-client/src/style/themes/dark.ts
index c1808b69673..071f0a28d28 100644
--- a/packages/desktop-client/src/style/themes/dark.ts
+++ b/packages/desktop-client/src/style/themes/dark.ts
@@ -10,7 +10,7 @@ export const pageBackgroundLineBottom = colorPalette.navy150;
export const pageText = colorPalette.navy150;
export const pageTextLight = colorPalette.navy300;
export const pageTextSubdued = colorPalette.navy500;
-export const pageTextDark = colorPalette.navy800;
+export const pageTextDark = colorPalette.navy100;
export const pageTextPositive = colorPalette.purple200;
export const pageTextLink = colorPalette.purple400;
export const pageTextLinkLight = colorPalette.purple200;
diff --git a/packages/loot-core/src/shared/months.ts b/packages/loot-core/src/shared/months.ts
index c87d8694d65..d314391a825 100644
--- a/packages/loot-core/src/shared/months.ts
+++ b/packages/loot-core/src/shared/months.ts
@@ -118,6 +118,10 @@ export function nextMonth(month: DateLike): string {
return d.format(d.addMonths(_parse(month), 1), 'yyyy-MM');
}
+export function prevYear(month: DateLike): string {
+ return d.format(d.subMonths(_parse(month), 12), 'yyyy-MM');
+}
+
export function prevMonth(month: DateLike): string {
return d.format(d.subMonths(_parse(month), 1), 'yyyy-MM');
}
diff --git a/upcoming-release-notes/1930.md b/upcoming-release-notes/1930.md
new file mode 100644
index 00000000000..5ecd2fc4726
--- /dev/null
+++ b/upcoming-release-notes/1930.md
@@ -0,0 +1,6 @@
+---
+category: Bugfix
+authors: [carkom]
+---
+
+Bug fixes for custom reports.