Skip to content

Commit

Permalink
Merge branch 'master' into jfdoming/translation-sync
Browse files Browse the repository at this point in the history
  • Loading branch information
jfdoming authored Jan 9, 2025
2 parents b15a223 + 6111f94 commit dcf7e67
Show file tree
Hide file tree
Showing 16 changed files with 145 additions and 77 deletions.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
80 changes: 42 additions & 38 deletions packages/desktop-client/src/components/accounts/Account.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
// @ts-strict-ignore
import React, {
PureComponent,
type MutableRefObject,
Expand Down Expand Up @@ -332,8 +331,8 @@ class AccountInternal extends PureComponent<
AccountInternalState
> {
paged: PagedQuery<TransactionEntity> | null;
rootQuery: Query;
currentQuery: Query;
rootQuery!: Query;
currentQuery!: Query;
table: TableRef;
unlisten?: () => void;
dispatchSelected?: (action: Actions) => void;
Expand Down Expand Up @@ -383,7 +382,7 @@ class AccountInternal extends PureComponent<
// first message referencing a non-deleted row so that we can
// highlight the row
//
let focusId: null | string;
let focusId: null | string = null;
if (
messages.every(msg => msg.dataset === 'transactions') &&
!messages.find(msg => msg.column === 'tombstone')
Expand Down Expand Up @@ -536,7 +535,7 @@ class AccountInternal extends PureComponent<
this.setState(
{
transactions: data,
transactionCount: this.paged?.totalCount,
transactionCount: this.paged?.totalCount ?? 0,
transactionsFiltered: isFiltered,
loading: false,
workingHard: false,
Expand Down Expand Up @@ -678,14 +677,17 @@ class AccountInternal extends PureComponent<
const account = this.props.accounts.find(
account => account.id === accountId,
);
return (
account &&
this.state.search === '' &&
this.state.filterConditions.length === 0 &&
(this.state.sort === null ||
(this.state.sort.field === 'date' &&
this.state.sort.ascDesc === 'desc'))
);

if (!account) return false;
if (this.state.search !== '') return false;
if (this.state.filterConditions.length > 0) return false;
if (this.state.sort === null) {
return true;
} else {
return (
this.state.sort.field === 'date' && this.state.sort.ascDesc === 'desc'
);
}
};

async calculateBalances() {
Expand Down Expand Up @@ -713,7 +715,7 @@ class AccountInternal extends PureComponent<
onSaveName = (name: string) => {
const accountNameError = validateAccountName(
name,
this.props.accountId,
this.props.accountId ?? '',
this.props.accounts,
);
if (accountNameError) {
Expand All @@ -722,7 +724,7 @@ class AccountInternal extends PureComponent<
const account = this.props.accounts.find(
account => account.id === this.props.accountId,
);
this.props.updateAccount({ ...account, name });
this.props.updateAccount({ ...account, name } as AccountEntity);
this.setState({ editingName: false, nameError: '' });
}
};
Expand Down Expand Up @@ -920,9 +922,9 @@ class AccountInternal extends PureComponent<
await this.refetchTransactions();
};

onReconcile = async (balance: number) => {
onReconcile = async (amount: number | null) => {
this.setState(({ showCleared }) => ({
reconcileAmount: balance,
reconcileAmount: amount,
showCleared: true,
prevShowCleared: showCleared,
}));
Expand Down Expand Up @@ -1301,14 +1303,16 @@ class AccountInternal extends PureComponent<

onConditionsOpChange = (value: 'and' | 'or') => {
this.setState({ filterConditionsOp: value });
this.setState({ filterId: { ...this.state.filterId, status: 'changed' } });
this.setState({
filterId: { ...this.state.filterId, status: 'changed' } as SavedFilter,
});
this.applyFilters([...this.state.filterConditions]);
if (this.state.search !== '') {
this.onSearch(this.state.search);
}
};

onReloadSavedFilter = (savedFilter: SavedFilter, item: string) => {
onReloadSavedFilter = (savedFilter: SavedFilter, item?: string) => {
if (item === 'reload') {
const [savedFilter] = this.props.savedFilters.filter(
f => f.id === this.state.filterId?.id,
Expand All @@ -1320,7 +1324,7 @@ class AccountInternal extends PureComponent<
this.setState({
filterConditionsOp: savedFilter.conditionsOp ?? 'and',
});
this.applyFilters([...savedFilter.conditions]);
this.applyFilters([...(savedFilter.conditions ?? [])]);
}
}
this.setState({ filterId: { ...this.state.filterId, ...savedFilter } });
Expand Down Expand Up @@ -1348,7 +1352,7 @@ class AccountInternal extends PureComponent<
filterId: {
...this.state.filterId,
status: this.state.filterId && 'changed',
},
} as SavedFilter,
});
if (this.state.search !== '') {
this.onSearch(this.state.search);
Expand All @@ -1365,7 +1369,7 @@ class AccountInternal extends PureComponent<
filterId: {
...this.state.filterId,
status: this.state.filterId && 'changed',
},
} as SavedFilter,
});
}
if (this.state.search !== '') {
Expand Down Expand Up @@ -1402,7 +1406,7 @@ class AccountInternal extends PureComponent<
filterId: {
...this.state.filterId,
status: this.state.filterId && 'changed',
},
} as SavedFilter,
});
this.applyFilters([...filterConditions, condition]);
}
Expand Down Expand Up @@ -1660,11 +1664,11 @@ class AccountInternal extends PureComponent<

const showEmptyMessage = !loading && !accountId && accounts.length === 0;

const isNameEditable =
accountId &&
accountId !== 'onbudget' &&
accountId !== 'offbudget' &&
accountId !== 'uncategorized';
const isNameEditable = accountId
? accountId !== 'onbudget' &&
accountId !== 'offbudget' &&
accountId !== 'uncategorized'
: false;

const balanceQuery = this.getBalanceQuery(accountId);

Expand All @@ -1687,9 +1691,9 @@ class AccountInternal extends PureComponent<
<View style={styles.page}>
<AccountHeader
tableRef={this.table}
editingName={editingName}
isNameEditable={isNameEditable}
workingHard={workingHard}
editingName={editingName ?? false}
isNameEditable={isNameEditable ?? false}
workingHard={workingHard ?? false}
account={account}
filterId={filterId}
savedFilters={this.props.savedFilters}
Expand All @@ -1698,15 +1702,15 @@ class AccountInternal extends PureComponent<
failedAccounts={failedAccounts}
accounts={accounts}
transactions={transactions}
showBalances={showBalances}
showExtraBalances={showExtraBalances}
showCleared={showCleared}
showReconciled={showReconciled}
showEmptyMessage={showEmptyMessage}
showBalances={showBalances ?? false}
showExtraBalances={showExtraBalances ?? false}
showCleared={showCleared ?? false}
showReconciled={showReconciled ?? false}
showEmptyMessage={showEmptyMessage ?? false}
balanceQuery={balanceQuery}
canCalculateBalance={this.canCalculateBalance}
canCalculateBalance={this?.canCalculateBalance ?? undefined}
filteredAmount={filteredAmount}
isFiltered={transactionsFiltered}
isFiltered={transactionsFiltered ?? false}
isSorted={this.state.sort !== null}
reconcileAmount={reconcileAmount}
search={this.state.search}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ import { useHover } from 'usehooks-ts';

import { isPreviewId } from 'loot-core/shared/transactions';
import { useCachedSchedules } from 'loot-core/src/client/data-hooks/schedules';
import { q } from 'loot-core/src/shared/query';
import { q, type Query } from 'loot-core/src/shared/query';
import { getScheduledAmount } from 'loot-core/src/shared/schedules';
import { type AccountEntity } from 'loot-core/types/models';

import { useSelectedItems } from '../../hooks/useSelected';
import { SvgArrowButtonRight1 } from '../../icons/v2';
Expand All @@ -15,11 +16,22 @@ import { Button } from '../common/Button2';
import { Text } from '../common/Text';
import { View } from '../common/View';
import { PrivacyFilter } from '../PrivacyFilter';
import { type Binding } from '../spreadsheet';
import { CellValue, CellValueText } from '../spreadsheet/CellValue';
import { useFormat } from '../spreadsheet/useFormat';
import { useSheetValue } from '../spreadsheet/useSheetValue';

function DetailedBalance({ name, balance, isExactBalance = true }) {
type DetailedBalanceProps = {
name: string;
balance: number;
isExactBalance?: boolean;
};

function DetailedBalance({
name,
balance,
isExactBalance = true,
}: DetailedBalanceProps) {
const format = useFormat();
return (
<Text
Expand All @@ -42,32 +54,37 @@ function DetailedBalance({ name, balance, isExactBalance = true }) {
);
}

function SelectedBalance({ selectedItems, account }) {
type SelectedBalanceProps = {
selectedItems: Set<string>;
account?: AccountEntity;
};

function SelectedBalance({ selectedItems, account }: SelectedBalanceProps) {
const { t } = useTranslation();

const name = `selected-balance-${[...selectedItems].join('-')}`;

const rows = useSheetValue({
name,
const rows = useSheetValue<'balance', `selected-transactions-${string}`>({
name: name as `selected-transactions-${string}`,
query: q('transactions')
.filter({
id: { $oneof: [...selectedItems] },
parent_id: { $oneof: [...selectedItems] },
})
.select('id'),
});
const ids = new Set((rows || []).map(r => r.id));
const ids = new Set((rows || []).map((r: { id: string }) => r.id));

const finalIds = [...selectedItems].filter(id => !ids.has(id));
let balance = useSheetValue({
name: name + '-sum',
let balance = useSheetValue<'balance', `selected-balance-${string}`>({
name: (name + '-sum') as `selected-balance-${string}`,
query: q('transactions')
.filter({ id: { $oneof: finalIds } })
.options({ splits: 'all' })
.calculate({ $sum: '$amount' }),
});

let scheduleBalance = null;
let scheduleBalance = 0;

const { isLoading, schedules = [] } = useCachedSchedules();

Expand Down Expand Up @@ -95,14 +112,10 @@ function SelectedBalance({ selectedItems, account }) {
}
}

if (balance == null) {
if (scheduleBalance == null) {
return null;
} else {
balance = scheduleBalance;
}
} else if (scheduleBalance != null) {
balance += scheduleBalance;
if (!balance && !scheduleBalance) {
return null;
} else {
balance = (balance ?? 0) + scheduleBalance;
}

return (
Expand All @@ -114,46 +127,67 @@ function SelectedBalance({ selectedItems, account }) {
);
}

function FilteredBalance({ filteredAmount }) {
type FilteredBalanceProps = {
filteredAmount?: number | null;
};

function FilteredBalance({ filteredAmount }: FilteredBalanceProps) {
const { t } = useTranslation();

return (
<DetailedBalance
name={t('Filtered balance:')}
balance={filteredAmount || 0}
balance={filteredAmount ?? 0}
isExactBalance={true}
/>
);
}

function MoreBalances({ balanceQuery }) {
type MoreBalancesProps = {
balanceQuery: { name: `balance-query-${string}`; query: Query };
};

function MoreBalances({ balanceQuery }: MoreBalancesProps) {
const { t } = useTranslation();

const cleared = useSheetValue({
name: balanceQuery.name + '-cleared',
const cleared = useSheetValue<'balance', `balance-query-${string}-cleared`>({
name: (balanceQuery.name + '-cleared') as `balance-query-${string}-cleared`,
query: balanceQuery.query.filter({ cleared: true }),
});
const uncleared = useSheetValue({
name: balanceQuery.name + '-uncleared',
const uncleared = useSheetValue<
'balance',
`balance-query-${string}-uncleared`
>({
name: (balanceQuery.name +
'-uncleared') as `balance-query-${string}-uncleared`,
query: balanceQuery.query.filter({ cleared: false }),
});

return (
<View style={{ flexDirection: 'row' }}>
<DetailedBalance name={t('Cleared total:')} balance={cleared} />
<DetailedBalance name={t('Uncleared total:')} balance={uncleared} />
<DetailedBalance name={t('Cleared total:')} balance={cleared ?? 0} />
<DetailedBalance name={t('Uncleared total:')} balance={uncleared ?? 0} />
</View>
);
}

type BalancesProps = {
balanceQuery: { name: `balance-query-${string}`; query: Query };
showExtraBalances: boolean;
onToggleExtraBalances: () => void;
account?: AccountEntity;
isFiltered: boolean;
filteredAmount?: number | null;
};

export function Balances({
balanceQuery,
showExtraBalances,
onToggleExtraBalances,
account,
isFiltered,
filteredAmount,
}) {
}: BalancesProps) {
const selectedItems = useSelectedItems();
const buttonRef = useRef(null);
const isButtonHovered = useHover(buttonRef);
Expand All @@ -177,7 +211,15 @@ export function Balances({
paddingBottom: 1,
}}
>
<CellValue binding={{ ...balanceQuery, value: 0 }} type="financial">
<CellValue
binding={
{ ...balanceQuery, value: 0 } as Binding<
'balance',
`balance-query-${string}`
>
}
type="financial"
>
{props => (
<CellValueText
{...props}
Expand Down
Loading

0 comments on commit dcf7e67

Please sign in to comment.