diff --git a/packages/desktop-client/e2e/budget.test.js b/packages/desktop-client/e2e/budget.test.js index 630d6d87a76d4642eb7247a4bacdca85f9f1ecf8..3a2df2e45fc0f42b6e759a4c875c1f457addf824 100644 --- a/packages/desktop-client/e2e/budget.test.js +++ b/packages/desktop-client/e2e/budget.test.js @@ -59,12 +59,9 @@ test.describe('Budget', () => { }); test('clicking on spent amounts opens a transaction page', async () => { - const categoryName = await budgetPage.getCategoryNameForRow(1); const accountPage = await budgetPage.clickOnSpentAmountForRow(1); expect(page.url()).toContain('/accounts'); - expect(await accountPage.accountName.textContent()).toMatch( - new RegExp(String.raw`${categoryName} \(\w+ \d+\)`), - ); + expect(await accountPage.accountName.textContent()).toMatch('All Accounts'); await page.getByRole('button', { name: 'Back' }).click(); }); }); diff --git a/packages/desktop-client/e2e/transactions.test.js-snapshots/Transactions-filters-transactions-by-category-5-chromium-linux.png b/packages/desktop-client/e2e/transactions.test.js-snapshots/Transactions-filters-transactions-by-category-5-chromium-linux.png index 1fc3ac1bd3e680658fab4d427de78509842a2694..dbd82168c5141839df0a47373d20f324bec84905 100644 Binary files a/packages/desktop-client/e2e/transactions.test.js-snapshots/Transactions-filters-transactions-by-category-5-chromium-linux.png and b/packages/desktop-client/e2e/transactions.test.js-snapshots/Transactions-filters-transactions-by-category-5-chromium-linux.png differ diff --git a/packages/desktop-client/e2e/transactions.test.js-snapshots/Transactions-filters-transactions-by-category-6-chromium-linux.png b/packages/desktop-client/e2e/transactions.test.js-snapshots/Transactions-filters-transactions-by-category-6-chromium-linux.png index d446e5e6cc74cf4a4702b9a5077d2d672d234d4c..cb95bf73f398e4507701d3a98de1db50ed1f44b2 100644 Binary files a/packages/desktop-client/e2e/transactions.test.js-snapshots/Transactions-filters-transactions-by-category-6-chromium-linux.png and b/packages/desktop-client/e2e/transactions.test.js-snapshots/Transactions-filters-transactions-by-category-6-chromium-linux.png differ diff --git a/packages/desktop-client/e2e/transactions.test.js-snapshots/Transactions-filters-transactions-by-date-5-chromium-linux.png b/packages/desktop-client/e2e/transactions.test.js-snapshots/Transactions-filters-transactions-by-date-5-chromium-linux.png index e80a360011a7775097aa02fa470a88818dca0ee7..6e8b3283128b2abae22e180acf80dc1df6c7be32 100644 Binary files a/packages/desktop-client/e2e/transactions.test.js-snapshots/Transactions-filters-transactions-by-date-5-chromium-linux.png and b/packages/desktop-client/e2e/transactions.test.js-snapshots/Transactions-filters-transactions-by-date-5-chromium-linux.png differ diff --git a/packages/desktop-client/e2e/transactions.test.js-snapshots/Transactions-filters-transactions-by-date-6-chromium-linux.png b/packages/desktop-client/e2e/transactions.test.js-snapshots/Transactions-filters-transactions-by-date-6-chromium-linux.png index 1f283ae2f78bad8e19229de90df0447f51a29e1c..26cbaf7f242fe80cee672ca49e07ba4fd2d16629 100644 Binary files a/packages/desktop-client/e2e/transactions.test.js-snapshots/Transactions-filters-transactions-by-date-6-chromium-linux.png and b/packages/desktop-client/e2e/transactions.test.js-snapshots/Transactions-filters-transactions-by-date-6-chromium-linux.png differ diff --git a/packages/desktop-client/src/components/accounts/Account.jsx b/packages/desktop-client/src/components/accounts/Account.jsx index 62f2a7f6f11f08db927e6d1e79fd08fe160484a9..4afd78dfe15b94861b3e2526903b505530727d07 100644 --- a/packages/desktop-client/src/components/accounts/Account.jsx +++ b/packages/desktop-client/src/components/accounts/Account.jsx @@ -204,7 +204,7 @@ class AccountInternal extends PureComponent { this.state = { search: '', - filters: [], + filters: props.conditions || [], loading: true, workingHard: false, reconcileAmount: null, @@ -280,7 +280,7 @@ class AccountInternal extends PureComponent { // Important that any async work happens last so that the // listeners are set up synchronously await this.props.initiallyLoadPayees(); - await this.fetchTransactions(); + await this.fetchTransactions(this.state.filters); // If there is a pending undo, apply it immediately (this happens // when an undo changes the location to this page) @@ -337,10 +337,11 @@ class AccountInternal extends PureComponent { this.paged?.run(); }; - fetchTransactions = () => { + fetchTransactions = filters => { const query = this.makeRootQuery(); this.rootQuery = this.currentQuery = query; - this.updateQuery(query); + if (filters) this.applyFilters(filters); + else this.updateQuery(query); if (this.props.accountId) { this.props.markAccountRead(this.props.accountId); @@ -348,18 +349,8 @@ class AccountInternal extends PureComponent { }; makeRootQuery = () => { - const locationState = this.props.location.state; const accountId = this.props.accountId; - if (locationState && locationState.filter) { - return q('transactions') - .options({ splits: 'grouped' }) - .filter({ - 'account.offbudget': false, - ...locationState.filter, - }); - } - return queries.makeTransactionsQuery(accountId); }; @@ -1603,6 +1594,10 @@ export function Account() { const modalShowing = useSelector(state => state.modals.modalStack.length > 0); const accountsSyncing = useSelector(state => state.account.accountsSyncing); const lastUndoState = useSelector(state => state.app.lastUndoState); + const conditions = + location.state && location.state.conditions + ? location.state.conditions + : []; const state = { newTransactions, @@ -1619,6 +1614,7 @@ export function Account() { modalShowing, accountsSyncing, lastUndoState, + conditions, }; const dispatch = useDispatch(); @@ -1629,21 +1625,12 @@ export function Account() { ); const transform = useMemo(() => { - let filterByAccount = queries.getAccountFilter(params.id, '_account'); - let filterByPayee = queries.getAccountFilter( + const filterByAccount = queries.getAccountFilter(params.id, '_account'); + const filterByPayee = queries.getAccountFilter( params.id, '_payee.transfer_acct', ); - // Never show schedules on these pages - if ( - (location.state && location.state.filter) || - params.id === 'uncategorized' - ) { - filterByAccount = { id: null }; - filterByPayee = { id: null }; - } - return q => { q = q.filter({ $and: [{ '_account.closed': false }], @@ -1664,7 +1651,7 @@ export function Account() { {...actionCreators} modalShowing={state.modalShowing} accountId={params.id} - categoryId={location?.state?.filter?.category} + categoryId={location?.state?.categoryId} location={location} filtersList={filtersList} /> diff --git a/packages/desktop-client/src/components/accounts/Balance.jsx b/packages/desktop-client/src/components/accounts/Balance.jsx index 27305c1de947fcacb3148763e6155c93adb15e78..5c0ca0272356d8aaf201c81a9f1994718909bd7d 100644 --- a/packages/desktop-client/src/components/accounts/Balance.jsx +++ b/packages/desktop-client/src/components/accounts/Balance.jsx @@ -104,6 +104,20 @@ function SelectedBalance({ selectedItems, account }) { ); } +function FilteredBalance({ selectedItems }) { + const balance = selectedItems + .filter(item => !item._unmatched && !item.is_parent) + .reduce((sum, product) => sum + product.amount, 0); + + return ( + <DetailedBalance + name="Filtered balance:" + balance={balance} + isExactBalance={true} + /> + ); +} + function MoreBalances({ balanceQuery }) { const cleared = useSheetValue({ name: balanceQuery.name + '-cleared', @@ -127,6 +141,8 @@ export function Balances({ showExtraBalances, onToggleExtraBalances, account, + filteredItems, + transactions, }) { const selectedItems = useSelectedItems(); @@ -184,6 +200,9 @@ export function Balances({ {selectedItems.size > 0 && ( <SelectedBalance selectedItems={selectedItems} account={account} /> )} + {filteredItems.length > 0 && ( + <FilteredBalance selectedItems={transactions} /> + )} </View> ); } diff --git a/packages/desktop-client/src/components/accounts/Header.jsx b/packages/desktop-client/src/components/accounts/Header.jsx index 93cd451150303e1301424f294e9e94f6a0d10ee2..3d968d19a920a849c8d3a995fa8ccaeb651fb6ce 100644 --- a/packages/desktop-client/src/components/accounts/Header.jsx +++ b/packages/desktop-client/src/components/accounts/Header.jsx @@ -212,6 +212,8 @@ export function AccountHeader({ showExtraBalances={showExtraBalances} onToggleExtraBalances={onToggleExtraBalances} account={account} + filteredItems={filters} + transactions={transactions} /> <Stack diff --git a/packages/desktop-client/src/components/budget/BudgetTable.jsx b/packages/desktop-client/src/components/budget/BudgetTable.jsx index d9f4d4df8bb8a7b93fcf192471b274575d3c20f6..48c701732b349dc017ff5e1c12edb2533336866f 100644 --- a/packages/desktop-client/src/components/budget/BudgetTable.jsx +++ b/packages/desktop-client/src/components/budget/BudgetTable.jsx @@ -126,8 +126,8 @@ class BudgetTableInner extends Component { } }; - onShowActivity = (catName, catId, monthIndex) => { - this.props.onShowActivity(catName, catId, this.resolveMonth(monthIndex)); + onShowActivity = (catId, monthIndex) => { + this.props.onShowActivity(catId, this.resolveMonth(monthIndex)); }; onBudgetAction = (monthIndex, type, args) => { diff --git a/packages/desktop-client/src/components/budget/ExpenseCategory.tsx b/packages/desktop-client/src/components/budget/ExpenseCategory.tsx index 660f54646fd19decab6cd132ff920bffbc713d88..16a5fa61d2c20b237f7164d92f5e6875cd09ccfe 100644 --- a/packages/desktop-client/src/components/budget/ExpenseCategory.tsx +++ b/packages/desktop-client/src/components/budget/ExpenseCategory.tsx @@ -29,7 +29,7 @@ type ExpenseCategoryProps = { onDelete?: ComponentProps<typeof SidebarCategory>['onDelete']; onDragChange: OnDragChangeCallback<CategoryEntity>; onBudgetAction: (idx: number, action: string, arg: unknown) => void; - onShowActivity: (name: string, id: string, idx: number) => void; + onShowActivity: (id: string, idx: number) => void; onReorder: OnDropCallback; }; diff --git a/packages/desktop-client/src/components/budget/IncomeCategory.tsx b/packages/desktop-client/src/components/budget/IncomeCategory.tsx index 922c6f921b13fd178d60dedf8f3b139b0404b47a..f240d72b3d614b0baec5c4b6fa6827bf59a5e13e 100644 --- a/packages/desktop-client/src/components/budget/IncomeCategory.tsx +++ b/packages/desktop-client/src/components/budget/IncomeCategory.tsx @@ -27,7 +27,7 @@ type IncomeCategoryProps = { onDragChange: OnDragChangeCallback<CategoryEntity>; onBudgetAction: (idx: number, action: string, arg: unknown) => void; onReorder: OnDropCallback; - onShowActivity: (name: string, id: string, idx: number) => void; + onShowActivity: (id: string, idx: number) => void; }; export function IncomeCategory({ diff --git a/packages/desktop-client/src/components/budget/index.tsx b/packages/desktop-client/src/components/budget/index.tsx index 0fc28ec312138f0d5b2cff1ee88355ceb5639c39..ed36d976b254d49e80b1041d25a9a1317ed2b354 100644 --- a/packages/desktop-client/src/components/budget/index.tsx +++ b/packages/desktop-client/src/components/budget/index.tsx @@ -297,18 +297,22 @@ function BudgetInner(props: BudgetProps) { dispatch(applyBudgetAction(month, type, args)); }; - const onShowActivity = (categoryName, categoryId, month) => { + const onShowActivity = (categoryId, month) => { + const conditions = [ + { field: 'category', op: 'is', value: categoryId, type: 'id' }, + { + field: 'date', + op: 'is', + value: month, + options: { month: true }, + type: 'date', + }, + ]; navigate('/accounts', { state: { goBack: true, - filterName: `${categoryName} (${monthUtils.format( - month, - 'MMMM yyyy', - )})`, - filter: { - category: categoryId, - date: { $transform: '$month', $eq: month }, - }, + conditions, + categoryId, }, }); }; diff --git a/packages/desktop-client/src/components/budget/report/ReportComponents.tsx b/packages/desktop-client/src/components/budget/report/ReportComponents.tsx index 079fe0d575336d0053cf8d4ad81386971b3f8b0e..3181c8da7cb5554f7b7df4cb4f083ae6967d2729 100644 --- a/packages/desktop-client/src/components/budget/report/ReportComponents.tsx +++ b/packages/desktop-client/src/components/budget/report/ReportComponents.tsx @@ -147,7 +147,7 @@ type CategoryMonthProps = { editing: boolean; onEdit: (id: string | null, idx?: number) => void; onBudgetAction: (idx: number, action: string, arg: unknown) => void; - onShowActivity: (name: string, id: string, idx: number) => void; + onShowActivity: (id: string, idx: number) => void; }; export const CategoryMonth = memo(function CategoryMonth({ monthIndex, @@ -301,7 +301,7 @@ export const CategoryMonth = memo(function CategoryMonth({ <Field name="spent" width="flex" style={{ textAlign: 'right' }}> <span data-testid="category-month-spent" - onClick={() => onShowActivity(category.name, category.id, monthIndex)} + onClick={() => onShowActivity(category.id, monthIndex)} > <CellValue binding={reportBudget.catSumAmount(category.id)} diff --git a/packages/desktop-client/src/components/budget/rollover/RolloverComponents.tsx b/packages/desktop-client/src/components/budget/rollover/RolloverComponents.tsx index 20be6272fbdcb8b7b58c845e84fae528a8427611..2fa62d10692e8fc6458a8da8efc93850ec359a75 100644 --- a/packages/desktop-client/src/components/budget/rollover/RolloverComponents.tsx +++ b/packages/desktop-client/src/components/budget/rollover/RolloverComponents.tsx @@ -143,7 +143,7 @@ type ExpenseCategoryMonthProps = { editing: boolean; onEdit: (id: string | null, idx?: number) => void; onBudgetAction: (idx: number, action: string, arg?: unknown) => void; - onShowActivity: (name: string, id: string, idx: number) => void; + onShowActivity: (id: string, idx: number) => void; }; export const ExpenseCategoryMonth = memo(function ExpenseCategoryMonth({ monthIndex, @@ -297,7 +297,7 @@ export const ExpenseCategoryMonth = memo(function ExpenseCategoryMonth({ <Field name="spent" width="flex" style={{ textAlign: 'right' }}> <span data-testid="category-month-spent" - onClick={() => onShowActivity(category.name, category.id, monthIndex)} + onClick={() => onShowActivity(category.id, monthIndex)} > <CellValue binding={rolloverBudget.catSumAmount(category.id)} @@ -367,7 +367,7 @@ type IncomeCategoryMonthProps = { category: { id: string; name: string }; isLast: boolean; monthIndex: number; - onShowActivity: (name: string, id: string, idx: number) => void; + onShowActivity: (id: string, idx: number) => void; }; export function IncomeCategoryMonth({ category, @@ -386,9 +386,7 @@ export function IncomeCategoryMonth({ ...(isLast && { borderBottomWidth: 0 }), }} > - <span - onClick={() => onShowActivity(category.name, category.id, monthIndex)} - > + <span onClick={() => onShowActivity(category.id, monthIndex)}> <CellValue binding={rolloverBudget.catSumAmount(category.id)} type="financial" diff --git a/upcoming-release-notes/2408.md b/upcoming-release-notes/2408.md new file mode 100644 index 0000000000000000000000000000000000000000..36be61c142e22c51ec4ecb3abd784605c21d456d --- /dev/null +++ b/upcoming-release-notes/2408.md @@ -0,0 +1,6 @@ +--- +category: Enhancements +authors: [carkom] +--- + +Updating the way the "budget" page links to the "accounts" page when clicking on the "spent" column items to use the filters functionality