diff --git a/packages/desktop-client/src/components/FinancesApp.js b/packages/desktop-client/src/components/FinancesApp.js index 02c0a4792e7cd0838e69325e9733f7f0beaada41..a64de70a4c6e9f8e1c0a0fbe556cadea38e89d95 100644 --- a/packages/desktop-client/src/components/FinancesApp.js +++ b/packages/desktop-client/src/components/FinancesApp.js @@ -207,7 +207,12 @@ class FinancesApp extends React.Component { let oldPush = this.history.push; this.history.push = (to, state) => { - return oldPush.call(this.history, to, makeLocationState(state)); + let newState = makeLocationState(to.state || state); + if (typeof to === 'object') { + return oldPush.call(this.history, { ...to, state: newState }); + } else { + return oldPush.call(this.history, to, newState); + } }; // I'm not sure if this is the best approach but we need this to diff --git a/packages/desktop-client/src/components/Titlebar.js b/packages/desktop-client/src/components/Titlebar.js index 47df41225641df99650a02187309959b3b190599..04d077ae85cc178e4f576fffc3ff1f53973bb495 100644 --- a/packages/desktop-client/src/components/Titlebar.js +++ b/packages/desktop-client/src/components/Titlebar.js @@ -186,7 +186,7 @@ function BudgetTitlebar({ globalPrefs, saveGlobalPrefs, localPrefs }) { /> {reportBudgetEnabled && ( <View style={{ marginLeft: -5 }}> - <Button + <ButtonWithLoading bare loading={loading} style={{ @@ -197,7 +197,7 @@ function BudgetTitlebar({ globalPrefs, saveGlobalPrefs, localPrefs }) { onClick={() => setShowTooltip(true)} > {budgetType === 'report' ? 'Report budget' : 'Rollover budget'} - </Button> + </ButtonWithLoading> {showTooltip && ( <Tooltip position="bottom-left" diff --git a/packages/desktop-client/src/components/accounts/Filters.js b/packages/desktop-client/src/components/accounts/Filters.js index 0899e512322a1520d0f6b757e55d2f03c1dfdbe8..0d70654b901e6d5392e476509aba13286df25efb 100644 --- a/packages/desktop-client/src/components/accounts/Filters.js +++ b/packages/desktop-client/src/components/accounts/Filters.js @@ -182,6 +182,7 @@ function ConfigureField({ field, op, value, dispatch, onApply }) { {type === 'boolean' ? [ <OpButton + key="true" op="true" selected={value === true} onClick={() => { @@ -190,6 +191,7 @@ function ConfigureField({ field, op, value, dispatch, onApply }) { }} />, <OpButton + key="false" op="false" selected={value === false} onClick={() => { @@ -200,6 +202,7 @@ function ConfigureField({ field, op, value, dispatch, onApply }) { ] : ops.map(currOp => ( <OpButton + key={currOp} op={currOp} selected={currOp === op} onClick={() => dispatch({ type: 'set-op', op: currOp })} @@ -445,6 +448,7 @@ export function AppliedFilters({ filters, editingFilter, onDelete }) { > {filters.map((filter, i) => ( <FilterExpression + key={i} customName={filter.customName} field={filter.field} op={filter.op} diff --git a/packages/desktop-client/src/components/modals/EditRule.js b/packages/desktop-client/src/components/modals/EditRule.js index 513046425dddce82be44fe9e3696303ceb2e5e60..932f099b846a53bf1f437b61da0896be1d73a74e 100644 --- a/packages/desktop-client/src/components/modals/EditRule.js +++ b/packages/desktop-client/src/components/modals/EditRule.js @@ -220,6 +220,18 @@ export function ConditionEditor({ ); } +function formatAmount(amount) { + if (!amount) { + return integerToCurrency(0); + } else if (typeof amount === 'number') { + return integerToCurrency(amount); + } else { + return `${integerToCurrency(amount.num1)} to ${integerToCurrency( + amount.num2 + )}`; + } +} + function ScheduleDescription({ id }) { let dateFormat = useSelector(state => { return state.prefs.local.dateFormat || 'MM/dd/yyyy'; @@ -254,7 +266,7 @@ function ScheduleDescription({ id }) { </Text> <Text style={{ margin: '0 5px' }}> — </Text> <Text style={{ flexShrink: 0 }}> - Amount: {integerToCurrency(schedule._amount || 0)} + Amount: {formatAmount(schedule._amount)} </Text> <Text style={{ margin: '0 5px' }}> — </Text> <Text style={{ flexShrink: 0 }}> @@ -504,9 +516,8 @@ export function ConditionsList({ } return ( - <View> + <View key={i}> <ConditionEditor - key={i} conditionFields={conditionFields} editorStyle={editorStyle} ops={ops} @@ -775,9 +786,8 @@ export default function EditRule({ ) : ( <Stack spacing={2}> {actions.map((action, i) => ( - <View> + <View key={i}> <ActionEditor - key={i} ops={['set', 'link-schedule']} action={action} editorStyle={editorStyle} diff --git a/packages/desktop-client/src/components/reports/graphs/NetWorthGraph.js b/packages/desktop-client/src/components/reports/graphs/NetWorthGraph.js index 93a8c1767472a7c4423be6f325a575f11a6c2fc2..7228f15f5f1aa535a7c6e1749650a0140ebfcd98 100644 --- a/packages/desktop-client/src/components/reports/graphs/NetWorthGraph.js +++ b/packages/desktop-client/src/components/reports/graphs/NetWorthGraph.js @@ -41,7 +41,7 @@ function Area({ start, end, data, style, scale, range }) { x={startX} y={zero + 1} width={endX - startX} - height={range.y[0] - zero - 1} + height={Math.max(range.y[0] - zero - 1, 0)} fill="#ffffff" /> </clipPath> diff --git a/packages/desktop-client/src/components/schedules/EditSchedule.js b/packages/desktop-client/src/components/schedules/EditSchedule.js index b68db6d6d927b3f7a89fece13e93b80b21af29bf..79cd946730c55d86162a6cba2d947cc31f99a299 100644 --- a/packages/desktop-client/src/components/schedules/EditSchedule.js +++ b/packages/desktop-client/src/components/schedules/EditSchedule.js @@ -532,7 +532,9 @@ export default function ScheduleDetails() { style={{ marginTop: 10, color: colors.n4 }} > {state.upcomingDates.map(date => ( - <View>{monthUtils.format(date, `${dateFormat} EEEE`)}</View> + <View key={date}> + {monthUtils.format(date, `${dateFormat} EEEE`)} + </View> ))} </Stack> </View> @@ -555,7 +557,7 @@ export default function ScheduleDetails() { dispatch({ type: 'set-repeats', repeats: e.target.checked }); }} /> - <label for="form_repeats" style={{ userSelect: 'none' }}> + <label htmlFor="form_repeats" style={{ userSelect: 'none' }}> Repeats </label> </View> @@ -586,7 +588,10 @@ export default function ScheduleDetails() { }); }} /> - <label for="form_posts_transaction" style={{ userSelect: 'none' }}> + <label + htmlFor="form_posts_transaction" + style={{ userSelect: 'none' }} + > Automatically add transaction </label> </View> diff --git a/packages/loot-core/src/client/data-hooks/payees.js b/packages/loot-core/src/client/data-hooks/payees.js index b8383aa912263ab4aea1d9026f73d69e5ed7fdfe..af440ea06c4c434cae70fe8418da5d61b92dea2d 100644 --- a/packages/loot-core/src/client/data-hooks/payees.js +++ b/packages/loot-core/src/client/data-hooks/payees.js @@ -4,7 +4,7 @@ import q, { liveQuery } from 'loot-core/src/client/query-helpers'; import { getPayeesById } from 'loot-core/src/client/reducers/queries'; export function usePayees() { - let [data, setData] = useState(null); + let [data, setData] = useState([]); useEffect(() => { let query = liveQuery(q('payees').select('*'), async payees => { diff --git a/packages/loot-core/src/shared/util.js b/packages/loot-core/src/shared/util.js index c9c577086becce628b5e246e921636c6a5f544a9..abd643979610610d34470e41eba1dcf747c7397f 100644 --- a/packages/loot-core/src/shared/util.js +++ b/packages/loot-core/src/shared/util.js @@ -312,7 +312,9 @@ const MIN_SAFE_NUMBER = -MAX_SAFE_NUMBER; export function safeNumber(value) { if (!Number.isInteger(value)) { - throw new Error('safeNumber: number is not an integer: ' + value); + throw new Error( + 'safeNumber: number is not an integer: ' + JSON.stringify(value) + ); } if (value > MAX_SAFE_NUMBER || value < MIN_SAFE_NUMBER) { throw new Error( diff --git a/packages/loot-design/src/components/DateSelect.js b/packages/loot-design/src/components/DateSelect.js index fdba62c31f2d79b0669d10ee4298f424c373cdb2..87df94a8069d5b89b008684fca0eab3e1da2ec73 100644 --- a/packages/loot-design/src/components/DateSelect.js +++ b/packages/loot-design/src/components/DateSelect.js @@ -166,11 +166,11 @@ export default function DateSelect({ return d.format(date, dateFormat); } } - return null; + return ''; }, [defaultValue, dateFormat]); let picker = useRef(null); - let [value, setValue] = useState(parsedDefaultValue || ''); + let [value, setValue] = useState(parsedDefaultValue); let [open, setOpen] = useState(embedded || isOpen || false); let inputRef = useRef(null); diff --git a/packages/loot-design/src/components/sidebar.js b/packages/loot-design/src/components/sidebar.js index 29544d7ca853f6b7afe313e9c38f08bc1c1f98e4..db88ad647a844ce64c614307071c84d2103a4507 100644 --- a/packages/loot-design/src/components/sidebar.js +++ b/packages/loot-design/src/components/sidebar.js @@ -230,7 +230,6 @@ function Account({ <DropHighlight pos={dropPos} /> <View innerRef={dragRef}> <AnchorLink - ref={dragRef} to={to} style={[ accountNameStyle,