From dd5e9155c625077557e48c361c201229525a4a01 Mon Sep 17 00:00:00 2001 From: George Sumpster <gsumpster@gmail.com> Date: Sat, 28 Jan 2023 12:23:25 -0800 Subject: [PATCH] Add 'Duplicate Transaction' to bulk editor for #548 (#582) --- .../src/components/accounts/Account.js | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/packages/desktop-client/src/components/accounts/Account.js b/packages/desktop-client/src/components/accounts/Account.js index 4e463f71a..32c42f2ea 100644 --- a/packages/desktop-client/src/components/accounts/Account.js +++ b/packages/desktop-client/src/components/accounts/Account.js @@ -18,6 +18,7 @@ import { deleteTransaction, updateTransaction, realizeTempTransactions, + ungroupTransaction, ungroupTransactions } from 'loot-core/src/shared/transactions'; import { @@ -464,6 +465,7 @@ function SelectedTransactionsButton({ style, getTransaction, onShow, + onDuplicate, onDelete, onEdit, onUnlink, @@ -480,6 +482,12 @@ function SelectedTransactionsButton({ }; }, [selectedItems]); + let ambiguousDuplication = useMemo(() => { + let transactions = [...selectedItems].map(id => getTransaction(id)); + + return transactions.some(t => t.is_child); + }, [selectedItems]); + let linked = useMemo(() => { return ( !types.preview && @@ -513,6 +521,11 @@ function SelectedTransactionsButton({ ] : [ { name: 'show', text: 'Show', key: 'F' }, + { + name: 'duplicate', + text: 'Duplicate', + disabled: ambiguousDuplication + }, { name: 'delete', text: 'Delete', key: 'D' }, ...(linked ? [ @@ -545,6 +558,9 @@ function SelectedTransactionsButton({ case 'show': onShow([...selectedItems]); break; + case 'duplicate': + onDuplicate([...selectedItems]); + break; case 'delete': onDelete([...selectedItems]); break; @@ -620,6 +636,7 @@ const AccountHeader = React.memo( onMenuSelect, onReconcile, onBatchDelete, + onBatchDuplicate, onBatchEdit, onBatchUnlink, onApplyFilter, @@ -824,6 +841,7 @@ const AccountHeader = React.memo( <SelectedTransactionsButton getTransaction={id => transactions.find(t => t.id === id)} onShow={onShowTransactions} + onDuplicate={onBatchDuplicate} onDelete={onBatchDelete} onEdit={onBatchEdit} onUnlink={onBatchUnlink} @@ -1511,6 +1529,31 @@ class AccountInternal extends React.PureComponent { } }; + onBatchDuplicate = async ids => { + this.setState({ workingHard: true }); + + let { data } = await runQuery( + q('transactions') + .filter({ id: { $oneof: ids } }) + .select('*') + .options({ splits: 'grouped' }) + ); + + let changes = { + added: data + .reduce((newTransactions, trans) => { + return newTransactions.concat( + realizeTempTransactions(ungroupTransaction(trans)) + ); + }, []) + .map(({ sort_order, ...trans }) => ({ ...trans })) + }; + + await send('transactions-batch-update', changes); + + await this.refetchTransactions(); + }; + onBatchDelete = async ids => { this.setState({ workingHard: true }); @@ -1707,6 +1750,7 @@ class AccountInternal extends React.PureComponent { onSync={this.onSync} onImport={this.onImport} onBatchDelete={this.onBatchDelete} + onBatchDuplicate={this.onBatchDuplicate} onBatchEdit={this.onBatchEdit} onBatchUnlink={this.onBatchUnlink} onDeleteFilter={this.onDeleteFilter} -- GitLab