diff --git a/.eslintrc.js b/.eslintrc.js index c411995fc87..d757f5187a8 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -38,6 +38,7 @@ module.exports = { extends: [ 'react-app', 'plugin:react/recommended', + 'plugin:prettier/recommended', 'plugin:@typescript-eslint/recommended', 'plugin:import/typescript', ], @@ -46,6 +47,7 @@ module.exports = { reportUnusedDisableDirectives: true, globals: { globalThis: false, + vi: true, }, rules: { 'prettier/prettier': 'warn', diff --git a/package.json b/package.json index db6163d7b54..62c6175f39c 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ "vrt": "yarn workspaces foreach --all --parallel --verbose run vrt", "rebuild-electron": "./node_modules/.bin/electron-rebuild -f -m ./packages/loot-core", "rebuild-node": "yarn workspace loot-core rebuild", - "lint": "eslint . --max-warnings 0", + "lint": "eslint . --max-warnings 0 --ext .js,.jsx,.ts,.tsx", "lint:verbose": "DEBUG=eslint:cli-engine eslint . --max-warnings 0", "typecheck": "yarn tsc && tsc-strict", "jq": "./node_modules/node-jq/bin/jq" @@ -44,15 +44,16 @@ "devDependencies": { "cross-env": "^7.0.3", "eslint": "^8.37.0", + "eslint-config-prettier": "^9.1.0", "eslint-config-react-app": "7.0.1", "eslint-import-resolver-typescript": "3.5.5", "eslint-plugin-import": "2.27.5", - "eslint-plugin-prettier": "4.2.1", + "eslint-plugin-prettier": "5.1.3", "eslint-plugin-react": "7.32.2", "eslint-plugin-rulesdir": "^0.2.2", "node-jq": "^4.0.1", "npm-run-all": "^4.1.3", - "prettier": "2.8.2", + "prettier": "3.2.4", "react-refresh": "^0.14.0", "source-map-support": "^0.5.21", "typescript": "^5.0.2", diff --git a/packages/crdt/src/crdt/timestamp.ts b/packages/crdt/src/crdt/timestamp.ts index 4eb8f399c21..ab54cf707dd 100644 --- a/packages/crdt/src/crdt/timestamp.ts +++ b/packages/crdt/src/crdt/timestamp.ts @@ -267,10 +267,10 @@ export class Timestamp { lNew === lOld && lNew === lMsg ? Math.max(cOld, cMsg) + 1 : lNew === lOld - ? cOld + 1 - : lNew === lMsg - ? cMsg + 1 - : 0; + ? cOld + 1 + : lNew === lMsg + ? cMsg + 1 + : 0; // check the result for drift and counter overflow if (lNew - phys > config.maxDrift) { diff --git a/packages/desktop-client/src/components/Notifications.tsx b/packages/desktop-client/src/components/Notifications.tsx index 122a1231870..d134ed26148 100644 --- a/packages/desktop-client/src/components/Notifications.tsx +++ b/packages/desktop-client/src/components/Notifications.tsx @@ -119,8 +119,8 @@ function Notification({ color: positive ? theme.noticeText : error - ? theme.errorTextDark - : theme.warningTextDark, + ? theme.errorTextDark + : theme.warningTextDark, }} > diff --git a/packages/desktop-client/src/components/Titlebar.tsx b/packages/desktop-client/src/components/Titlebar.tsx index e3487eddac9..57e16344bb8 100644 --- a/packages/desktop-client/src/components/Titlebar.tsx +++ b/packages/desktop-client/src/components/Titlebar.tsx @@ -177,18 +177,18 @@ function SyncButton({ style, isMobile = false }: SyncButtonProps) { syncState === 'error' ? theme.errorText : syncState === 'disabled' || - syncState === 'offline' || - syncState === 'local' - ? theme.mobileHeaderTextSubdued - : theme.mobileHeaderText; + syncState === 'offline' || + syncState === 'local' + ? theme.mobileHeaderTextSubdued + : theme.mobileHeaderText; const desktopColor = syncState === 'error' ? theme.errorTextDark : syncState === 'disabled' || - syncState === 'offline' || - syncState === 'local' - ? theme.tableTextLight - : 'inherit'; + syncState === 'offline' || + syncState === 'local' + ? theme.tableTextLight + : 'inherit'; const activeStyle = isMobile ? { @@ -263,8 +263,8 @@ function SyncButton({ style, isMobile = false }: SyncButtonProps) { {syncState === 'disabled' ? 'Disabled' : syncState === 'offline' - ? 'Offline' - : 'Sync'} + ? 'Offline' + : 'Sync'} diff --git a/packages/desktop-client/src/components/accounts/Balance.jsx b/packages/desktop-client/src/components/accounts/Balance.jsx index f2cb12c752f..d1df3c59a3b 100644 --- a/packages/desktop-client/src/components/accounts/Balance.jsx +++ b/packages/desktop-client/src/components/accounts/Balance.jsx @@ -159,8 +159,8 @@ export function Balances({ value < 0 ? theme.errorText : value > 0 - ? theme.noticeTextLight - : theme.pageTextSubdued, + ? theme.noticeTextLight + : theme.pageTextSubdued, })} privacyFilter={{ blurIntensity: 5, diff --git a/packages/desktop-client/src/components/autocomplete/AccountAutocomplete.tsx b/packages/desktop-client/src/components/autocomplete/AccountAutocomplete.tsx index 3b514ac2f01..f296e7b297f 100644 --- a/packages/desktop-client/src/components/autocomplete/AccountAutocomplete.tsx +++ b/packages/desktop-client/src/components/autocomplete/AccountAutocomplete.tsx @@ -41,8 +41,8 @@ function AccountList({ item.closed ? 'Closed Accounts' : item.offbudget - ? 'Off Budget' - : 'For Budget' + ? 'Off Budget' + : 'For Budget' }`; lastItem = item; diff --git a/packages/desktop-client/src/components/budget/BudgetCategories.jsx b/packages/desktop-client/src/components/budget/BudgetCategories.jsx index a223fea97e7..c80bfb2ab35 100644 --- a/packages/desktop-client/src/components/budget/BudgetCategories.jsx +++ b/packages/desktop-client/src/components/budget/BudgetCategories.jsx @@ -292,8 +292,8 @@ export const BudgetCategories = memo( item.value ? item.value.id : item.type === 'income-separator' - ? 'separator' - : idx + ? 'separator' + : idx } value={pos} > diff --git a/packages/desktop-client/src/components/budget/MobileBudgetTable.jsx b/packages/desktop-client/src/components/budget/MobileBudgetTable.jsx index fb5b9d5c24d..3c2251d77b3 100644 --- a/packages/desktop-client/src/components/budget/MobileBudgetTable.jsx +++ b/packages/desktop-client/src/components/budget/MobileBudgetTable.jsx @@ -117,8 +117,8 @@ function Saved({ projected, onClick }) { color: projected ? theme.warningText : isNegative - ? theme.errorTextDark - : theme.formInputText, + ? theme.errorTextDark + : theme.formInputText, }} /> diff --git a/packages/desktop-client/src/components/budget/report/budgetsummary/Saved.tsx b/packages/desktop-client/src/components/budget/report/budgetsummary/Saved.tsx index 3575bd63f07..b17906ec4d9 100644 --- a/packages/desktop-client/src/components/budget/report/budgetsummary/Saved.tsx +++ b/packages/desktop-client/src/components/budget/report/budgetsummary/Saved.tsx @@ -81,8 +81,8 @@ export function Saved({ projected, style }: SavedProps) { color: projected ? theme.warningText : isNegative - ? theme.errorTextDark - : theme.upcomingText, + ? theme.errorTextDark + : theme.upcomingText, }, ])}`} > diff --git a/packages/desktop-client/src/components/budget/util.ts b/packages/desktop-client/src/components/budget/util.ts index ed0f93bb953..cb7b926b734 100644 --- a/packages/desktop-client/src/components/budget/util.ts +++ b/packages/desktop-client/src/components/budget/util.ts @@ -73,8 +73,8 @@ export function makeAmountFullStyle(value: number) { value < 0 ? theme.errorText : value === 0 - ? theme.tableTextSubdued - : theme.noticeText, + ? theme.tableTextSubdued + : theme.noticeText, }; } diff --git a/packages/desktop-client/src/components/common/Stack.tsx b/packages/desktop-client/src/components/common/Stack.tsx index 6c9013380f0..a8e6f5c4638 100644 --- a/packages/desktop-client/src/components/common/Stack.tsx +++ b/packages/desktop-client/src/components/common/Stack.tsx @@ -14,20 +14,23 @@ import { Text } from './Text'; import { View } from './View'; function getChildren(key, children) { - return Children.toArray(children).reduce((list, child) => { - if (child) { - if ( - typeof child === 'object' && - 'type' in child && - child.type === Fragment - ) { - return list.concat(getChildren(child.key, child.props.children)); + return Children.toArray(children).reduce( + (list, child) => { + if (child) { + if ( + typeof child === 'object' && + 'type' in child && + child.type === Fragment + ) { + return list.concat(getChildren(child.key, child.props.children)); + } + list.push({ key: key + child['key'], child }); + return list; } - list.push({ key: key + child['key'], child }); return list; - } - return list; - }, [] as Array<{ key: string; child: ReactNode }>); + }, + [] as Array<{ key: string; child: ReactNode }>, + ); } type StackProps = ComponentProps & { diff --git a/packages/desktop-client/src/components/filters/FiltersMenu.jsx b/packages/desktop-client/src/components/filters/FiltersMenu.jsx index 99edbf4dd49..2d40d6375c1 100644 --- a/packages/desktop-client/src/components/filters/FiltersMenu.jsx +++ b/packages/desktop-client/src/components/filters/FiltersMenu.jsx @@ -196,12 +196,12 @@ function ConfigureField({ ['amount-outflow', 'Amount (outflow)'], ] : field === 'date' - ? [ - ['date', 'Date'], - ['month', 'Month'], - ['year', 'Year'], - ] - : null + ? [ + ['date', 'Date'], + ['month', 'Month'], + ['year', 'Year'], + ] + : null } value={subfield} onChange={sub => { diff --git a/packages/desktop-client/src/components/modals/GoCardlessExternalMsg.tsx b/packages/desktop-client/src/components/modals/GoCardlessExternalMsg.tsx index b89c7835a48..dbb74a9562b 100644 --- a/packages/desktop-client/src/components/modals/GoCardlessExternalMsg.tsx +++ b/packages/desktop-client/src/components/modals/GoCardlessExternalMsg.tsx @@ -288,10 +288,10 @@ export function GoCardlessExternalMsg({ {isConfigurationLoading ? 'Checking GoCardless configuration..' : waiting === 'browser' - ? 'Waiting on GoCardless...' - : waiting === 'accounts' - ? 'Loading accounts...' - : null} + ? 'Waiting on GoCardless...' + : waiting === 'accounts' + ? 'Loading accounts...' + : null} {waiting === 'browser' && ( diff --git a/packages/desktop-client/src/components/modals/ImportTransactions.jsx b/packages/desktop-client/src/components/modals/ImportTransactions.jsx index 731e0bb965e..db53af08937 100644 --- a/packages/desktop-client/src/components/modals/ImportTransactions.jsx +++ b/packages/desktop-client/src/components/modals/ImportTransactions.jsx @@ -11,7 +11,6 @@ import { } from 'loot-core/src/shared/util'; import { useActions } from '../../hooks/useActions'; -import { useFeatureFlag } from '../../hooks/useFeatureFlag'; import { theme, styles } from '../../style'; import { Button, ButtonWithLoading } from '../common/Button'; import { Input } from '../common/Input'; diff --git a/packages/desktop-client/src/components/modals/ImportTransactions.test.jsx b/packages/desktop-client/src/components/modals/ImportTransactions.test.js similarity index 100% rename from packages/desktop-client/src/components/modals/ImportTransactions.test.jsx rename to packages/desktop-client/src/components/modals/ImportTransactions.test.js diff --git a/packages/desktop-client/src/components/modals/MergeUnusedPayees.jsx b/packages/desktop-client/src/components/modals/MergeUnusedPayees.jsx index 1fde89e701b..5e36e4f9d99 100644 --- a/packages/desktop-client/src/components/modals/MergeUnusedPayees.jsx +++ b/packages/desktop-client/src/components/modals/MergeUnusedPayees.jsx @@ -14,11 +14,7 @@ import { View } from '../common/View'; const highlightStyle = { color: theme.pageTextPositive }; -export function MergeUnusedPayees({ - modalProps, - payeeIds, - targetPayeeId, -}) { +export function MergeUnusedPayees({ modalProps, payeeIds, targetPayeeId }) { const { payees: allPayees, modalStack } = useSelector(state => ({ payees: state.queries.payees, modalStack: state.modals.modalStack, diff --git a/packages/desktop-client/src/components/modals/PlaidExternalMsg.tsx b/packages/desktop-client/src/components/modals/PlaidExternalMsg.tsx index 72a2b3969f9..ec368be342f 100644 --- a/packages/desktop-client/src/components/modals/PlaidExternalMsg.tsx +++ b/packages/desktop-client/src/components/modals/PlaidExternalMsg.tsx @@ -92,8 +92,8 @@ export function PlaidExternalMsg({ {waiting === 'browser' ? 'Waiting on browser...' : waiting === 'accounts' - ? 'Loading accounts...' - : null} + ? 'Loading accounts...' + : null} ) : success ? ( diff --git a/packages/desktop-client/src/components/payees/PayeeTableRow.tsx b/packages/desktop-client/src/components/payees/PayeeTableRow.tsx index 64603fb52f7..a9c1182242d 100644 --- a/packages/desktop-client/src/components/payees/PayeeTableRow.tsx +++ b/packages/desktop-client/src/components/payees/PayeeTableRow.tsx @@ -104,10 +104,10 @@ export const PayeeTableRow = memo( backgroundColor: hovered ? theme.tableRowBackgroundHover : selected - ? theme.tableRowBackgroundHighlight - : backgroundFocus - ? theme.tableRowBackgroundHover - : theme.tableBackground, + ? theme.tableRowBackgroundHighlight + : backgroundFocus + ? theme.tableRowBackgroundHover + : theme.tableBackground, ...(selected && { backgroundColor: theme.tableRowBackgroundHighlight, zIndex: 100, diff --git a/packages/desktop-client/src/components/reports/ChooseGraph.tsx b/packages/desktop-client/src/components/reports/ChooseGraph.tsx index 244a4b05009..a4e0b5b21bf 100644 --- a/packages/desktop-client/src/components/reports/ChooseGraph.tsx +++ b/packages/desktop-client/src/components/reports/ChooseGraph.tsx @@ -53,8 +53,8 @@ export function ChooseGraph({ groupBy === 'Category' ? 'groupedData' : ['Month', 'Year'].includes(groupBy) - ? 'monthData' - : 'data'; + ? 'monthData' + : 'data'; const saveScrollWidth = value => { setScrollWidth(!value ? 0 : value); diff --git a/packages/desktop-client/src/components/reports/ReportSidebar.jsx b/packages/desktop-client/src/components/reports/ReportSidebar.jsx index 843ab3697de..49857c63d88 100644 --- a/packages/desktop-client/src/components/reports/ReportSidebar.jsx +++ b/packages/desktop-client/src/components/reports/ReportSidebar.jsx @@ -191,8 +191,8 @@ export function ReportSidebar({ mode === 'time' ? ['Month', 'Year'] : graphType === 'AreaGraph' - ? ['Category', 'Group', 'Payee', 'Account', 'Year'] - : ['Year'] + ? ['Category', 'Group', 'Payee', 'Account', 'Year'] + : ['Year'] } /> diff --git a/packages/desktop-client/src/components/reports/ReportSummary.tsx b/packages/desktop-client/src/components/reports/ReportSummary.tsx index a8dac85fbc4..eab6d9a0709 100644 --- a/packages/desktop-client/src/components/reports/ReportSummary.tsx +++ b/packages/desktop-client/src/components/reports/ReportSummary.tsx @@ -81,8 +81,8 @@ export function ReportSummary({ {balanceTypeOp === 'totalDebts' ? 'TOTAL SPENDING' : balanceTypeOp === 'totalAssets' - ? 'TOTAL DEPOSITS' - : 'NET ' + net} + ? 'TOTAL DEPOSITS' + : 'NET ' + net} onHover && onHover(rule.id)} diff --git a/packages/desktop-client/src/components/rules/Value.tsx b/packages/desktop-client/src/components/rules/Value.tsx index 77b453154d1..c641dc496e7 100644 --- a/packages/desktop-client/src/components/rules/Value.tsx +++ b/packages/desktop-client/src/components/rules/Value.tsx @@ -49,10 +49,10 @@ export function Value({ (field === 'payee' ? payees : field === 'category' - ? categories - : field === 'account' - ? accounts - : []); + ? categories + : field === 'account' + ? accounts + : []); const [expanded, setExpanded] = useState(false); diff --git a/packages/desktop-client/src/components/schedules/PostsOfflineNotification.jsx b/packages/desktop-client/src/components/schedules/PostsOfflineNotification.jsx index e4114113d06..6073a87babf 100644 --- a/packages/desktop-client/src/components/schedules/PostsOfflineNotification.jsx +++ b/packages/desktop-client/src/components/schedules/PostsOfflineNotification.jsx @@ -36,8 +36,8 @@ export function PostsOfflineNotification({ modalProps, actions }) { {idx === payees.length - 1 ? ' ' : idx === payees.length - 2 - ? ', and ' - : ', '} + ? ', and ' + : ', '} ))} diff --git a/packages/desktop-client/src/components/sidebar/Account.tsx b/packages/desktop-client/src/components/sidebar/Account.tsx index dc42b4e7a78..3cd28ba2e61 100644 --- a/packages/desktop-client/src/components/sidebar/Account.tsx +++ b/packages/desktop-client/src/components/sidebar/Account.tsx @@ -63,8 +63,8 @@ export function Account({ ? account.closed ? 'account-closed' : account.offbudget - ? 'account-offbudget' - : 'account-onbudget' + ? 'account-offbudget' + : 'account-onbudget' : 'title'; const { dragRef } = useDraggable({ diff --git a/packages/desktop-client/src/components/spreadsheet/CellValue.tsx b/packages/desktop-client/src/components/spreadsheet/CellValue.tsx index f528c21b2f2..0c453a9744a 100644 --- a/packages/desktop-client/src/components/spreadsheet/CellValue.tsx +++ b/packages/desktop-client/src/components/spreadsheet/CellValue.tsx @@ -43,8 +43,8 @@ export function CellValue({ privacyFilter != null ? privacyFilter : type === 'financial' - ? true - : undefined + ? true + : undefined } > ( backgroundColor: bare ? 'transparent' : disabled // always use disabled before primary since we can have a disabled primary button - ? theme.buttonNormalDisabledBackground - : primary - ? theme.buttonPrimaryBackground - : theme.buttonNormalBackground, + ? theme.buttonNormalDisabledBackground + : primary + ? theme.buttonPrimaryBackground + : theme.buttonNormalBackground, border: bare ? 'none' : '1px solid ' + (disabled ? theme.buttonNormalDisabledBorder : primary - ? theme.buttonPrimaryBorder - : theme.buttonNormalBorder), + ? theme.buttonPrimaryBorder + : theme.buttonNormalBorder), color: bare ? 'inherit' : disabled - ? theme.buttonNormalDisabledText - : primary - ? theme.buttonPrimaryText - : theme.buttonNormalText, + ? theme.buttonNormalDisabledText + : primary + ? theme.buttonPrimaryText + : theme.buttonNormalText, ':focus': bare ? null : { @@ -717,8 +717,8 @@ export function SheetCell({ privacyFilter != null ? privacyFilter : type === 'financial' - ? true - : undefined + ? true + : undefined } data-cellname={sheetValue} > @@ -1327,8 +1327,8 @@ export function useTableNavigator( ? 'up' : 'down' : e.shiftKey - ? 'left' - : 'right', + ? 'left' + : 'right', ); break; default: diff --git a/packages/desktop-client/src/components/transactions/MobileTransaction.jsx b/packages/desktop-client/src/components/transactions/MobileTransaction.jsx index e78adfaf995..4f05daa85af 100644 --- a/packages/desktop-client/src/components/transactions/MobileTransaction.jsx +++ b/packages/desktop-client/src/components/transactions/MobileTransaction.jsx @@ -473,8 +473,8 @@ const TransactionEditInner = memo(function TransactionEditInner({ return isOffBudget ? 'Off Budget' : isBudgetTransfer(trans) - ? 'Transfer' - : lookupName(categories, trans.category); + ? 'Transfer' + : lookupName(categories, trans.category); }; const onTotalAmountEdit = () => { @@ -1172,8 +1172,8 @@ const Transaction = memo(function Transaction({ const prettyCategory = transferAcct ? 'Transfer' : isParent - ? 'Split' - : categoryName; + ? 'Split' + : categoryName; const isPreview = isPreviewId(id); const isReconciled = transaction.reconciled; diff --git a/packages/desktop-client/src/components/transactions/TransactionList.jsx b/packages/desktop-client/src/components/transactions/TransactionList.jsx index 4625bd5672c..c25778a34e3 100644 --- a/packages/desktop-client/src/components/transactions/TransactionList.jsx +++ b/packages/desktop-client/src/components/transactions/TransactionList.jsx @@ -1,5 +1,4 @@ import React, { useRef, useCallback, useLayoutEffect } from 'react'; -import { useNavigate } from 'react-router-dom'; import { send } from 'loot-core/src/platform/client/fetch'; import { @@ -11,6 +10,7 @@ import { } from 'loot-core/src/shared/transactions'; import { getChangedValues, applyChanges } from 'loot-core/src/shared/util'; +import { useNavigate } from '../../hooks/useNavigate'; import { theme } from '../../style'; import { TransactionTable } from './TransactionsTable'; diff --git a/packages/desktop-client/src/components/transactions/TransactionsTable.jsx b/packages/desktop-client/src/components/transactions/TransactionsTable.jsx index bca1906fcea..2e3291b86a2 100644 --- a/packages/desktop-client/src/components/transactions/TransactionsTable.jsx +++ b/packages/desktop-client/src/components/transactions/TransactionsTable.jsx @@ -168,54 +168,57 @@ export function SplitsExpandedProvider({ children, initialMode = 'expand' }) { const cachedState = useSelector(state => state.app.lastSplitState); const reduxDispatch = useDispatch(); - const [state, dispatch] = useReducer((state, action) => { - switch (action.type) { - case 'toggle-split': { - const ids = new Set([...state.ids]); - const { id } = action; - if (ids.has(id)) { - ids.delete(id); - } else { - ids.add(id); + const [state, dispatch] = useReducer( + (state, action) => { + switch (action.type) { + case 'toggle-split': { + const ids = new Set([...state.ids]); + const { id } = action; + if (ids.has(id)) { + ids.delete(id); + } else { + ids.add(id); + } + return { ...state, ids }; } - return { ...state, ids }; - } - case 'open-split': { - const ids = new Set([...state.ids]); - const { id } = action; - if (state.mode === 'collapse') { - ids.delete(id); - } else { - ids.add(id); + case 'open-split': { + const ids = new Set([...state.ids]); + const { id } = action; + if (state.mode === 'collapse') { + ids.delete(id); + } else { + ids.add(id); + } + return { ...state, ids }; } - return { ...state, ids }; - } - case 'set-mode': { - return { - ...state, - mode: action.mode, - ids: new Set(), - transitionId: null, - }; - } - case 'switch-mode': - if (state.transitionId != null) { - // You can only transition once at a time - return state; + case 'set-mode': { + return { + ...state, + mode: action.mode, + ids: new Set(), + transitionId: null, + }; } + case 'switch-mode': + if (state.transitionId != null) { + // You can only transition once at a time + return state; + } - return { - ...state, - mode: state.mode === 'expand' ? 'collapse' : 'expand', - transitionId: action.id, - ids: new Set(), - }; - case 'finish-switch-mode': - return { ...state, transitionId: null }; - default: - throw new Error('Unknown action type: ' + action.type); - } - }, cachedState.current || { ids: new Set(), mode: initialMode }); + return { + ...state, + mode: state.mode === 'expand' ? 'collapse' : 'expand', + transitionId: action.id, + ids: new Set(), + }; + case 'finish-switch-mode': + return { ...state, transitionId: null }; + default: + throw new Error('Unknown action type: ' + action.type); + } + }, + cachedState.current || { ids: new Set(), mode: initialMode }, + ); useEffect(() => { if (state.transitionId != null) { @@ -419,14 +422,14 @@ function StatusCell({ status === 'cleared' ? theme.noticeTextLight : status === 'reconciled' - ? theme.noticeTextLight - : status === 'missed' - ? theme.errorText - : status === 'due' - ? theme.warningText - : selected - ? theme.pageTextLinkLight - : theme.pageTextSubdued; + ? theme.noticeTextLight + : status === 'missed' + ? theme.errorText + : status === 'due' + ? theme.warningText + : selected + ? theme.pageTextLinkLight + : theme.pageTextSubdued; function onSelect() { if (isClearedField) { @@ -869,8 +872,8 @@ const Transaction = memo(function Transaction(props) { backgroundColor: selected ? theme.tableRowBackgroundHighlight : backgroundFocus - ? theme.tableRowBackgroundHover - : theme.tableBackground, + ? theme.tableRowBackgroundHover + : theme.tableBackground, ':hover': !(backgroundFocus || selected) && { backgroundColor: theme.tableRowBackgroundHover, }, @@ -1090,18 +1093,18 @@ const Transaction = memo(function Transaction(props) { notes === 'missed' ? theme.errorText : notes === 'due' - ? theme.warningText - : selected - ? theme.formLabelText - : theme.upcomingText, + ? theme.warningText + : selected + ? theme.formLabelText + : theme.upcomingText, backgroundColor: notes === 'missed' ? theme.errorBackground : notes === 'due' - ? theme.warningBackground - : selected - ? theme.formLabelBackground - : theme.upcomingBackground, + ? theme.warningBackground + : selected + ? theme.formLabelBackground + : theme.upcomingBackground, margin: '0 5px', padding: '3px 7px', borderRadius: 4, @@ -1174,10 +1177,10 @@ const Transaction = memo(function Transaction(props) { isParent ? 'Split' : isOffBudget - ? 'Off Budget' - : isBudgetTransfer - ? 'Transfer' - : '' + ? 'Off Budget' + : isBudgetTransfer + ? 'Transfer' + : '' } valueStyle={valueStyle} style={{ @@ -1204,8 +1207,8 @@ const Transaction = memo(function Transaction(props) { 'name', ) : transaction.id - ? 'Categorize' - : '' + ? 'Categorize' + : '' } exposed={focusedField === 'category'} onExpose={name => onEdit(id, name)} @@ -1333,10 +1336,10 @@ const Transaction = memo(function Transaction(props) { isPreview ? notes : reconciled - ? 'reconciled' - : cleared - ? 'cleared' - : null + ? 'reconciled' + : cleared + ? 'cleared' + : null } isChild={isChild} onEdit={onEdit} @@ -1349,7 +1352,14 @@ const Transaction = memo(function Transaction(props) { ); }); -function TransactionError({ error, isDeposit, onAddSplit, onDistributeRemainder, style, canDistributeRemainder }) { +function TransactionError({ + error, + isDeposit, + onAddSplit, + onDistributeRemainder, + style, + canDistributeRemainder, +}) { switch (error.type) { case 'SplitTransactionError': if (error.version === 1) { @@ -1453,7 +1463,9 @@ function NewTransaction({ const error = transactions[0].error; const isDeposit = transactions[0].amount > 0; - const emptyChildTransactions = transactions.filter(t => t.parent_id === transactions[0].id && t.amount === 0) + const emptyChildTransactions = transactions.filter( + t => t.parent_id === transactions[0].id && t.amount === 0, + ); return ( onAddSplit(transactions[0].id)} - onDistributeRemainder={() => onDistributeRemainder(transactions[0].id)} + onDistributeRemainder={() => + onDistributeRemainder(transactions[0].id) + } canDistributeRemainder={emptyChildTransactions.length > 0} /> ) : ( @@ -1615,31 +1629,35 @@ function TransactionTableInner({ const hasSplitError = (!expanded || isLastChild(transactions, index)) && error && - error.type === 'SplitTransactionError' + error.type === 'SplitTransactionError'; const emptyChildTransactions = transactions.filter( - t => t.parent_id === (trans.is_parent ? trans.id : trans.parent_id) && t.amount === 0 - ) + t => + t.parent_id === (trans.is_parent ? trans.id : trans.parent_id) && + t.amount === 0, + ); return ( <> {hasSplitError && ( - - props.onAddSplit(trans.id)} - onDistributeRemainder={() => props.onDistributeRemainder(trans.id)} - canDistributeRemainder={emptyChildTransactions.length > 0} - /> - - )} + + props.onAddSplit(trans.id)} + onDistributeRemainder={() => + props.onDistributeRemainder(trans.id) + } + canDistributeRemainder={emptyChildTransactions.length > 0} + /> + + )} { const { transactions, tableNavigator, newTransactions } = latestState.current; - const targetTransactions = isTemporaryId(id) ? newTransactions : transactions + const targetTransactions = isTemporaryId(id) + ? newTransactions + : transactions; const transaction = targetTransactions.find(t => t.id === id); - const parentTransaction = transaction.is_parent ? transaction : targetTransactions.find( - t => t.id === transaction.parent_id - ) + const parentTransaction = transaction.is_parent + ? transaction + : targetTransactions.find(t => t.id === transaction.parent_id); const siblingTransactions = targetTransactions.filter( - t => t.parent_id === (transaction.is_parent ? transaction.id : transaction.parent_id) - ) + t => + t.parent_id === + (transaction.is_parent ? transaction.id : transaction.parent_id), + ); const emptyTransactions = siblingTransactions.filter(t => t.amount === 0); @@ -2136,11 +2158,11 @@ export const TransactionTable = forwardRef((props, ref) => { let remainingCents = remainingAmount - amountPerTransaction * emptyTransactions.length; - let amounts = new Array(emptyTransactions.length).fill( + const amounts = new Array(emptyTransactions.length).fill( amountPerTransaction, ); - for (let amountIndex in amounts) { + for (const amountIndex in amounts) { if (remainingCents === 0) break; amounts[amountIndex] += 1; @@ -2148,9 +2170,9 @@ export const TransactionTable = forwardRef((props, ref) => { } if (isTemporaryId(id)) { - newNavigator.onEdit(null) + newNavigator.onEdit(null); } else { - tableNavigator.onEdit(null) + tableNavigator.onEdit(null); } for (const transactionIndex in emptyTransactions) { @@ -2163,7 +2185,6 @@ export const TransactionTable = forwardRef((props, ref) => { [latestState], ); - function onCloseAddTransaction() { setNewTransactions( makeTemporaryTransactions( diff --git a/packages/desktop-client/src/components/transactions/TransactionsTable.test.jsx b/packages/desktop-client/src/components/transactions/TransactionsTable.test.jsx index bdb29b763c2..56bf5d3cf75 100644 --- a/packages/desktop-client/src/components/transactions/TransactionsTable.test.jsx +++ b/packages/desktop-client/src/components/transactions/TransactionsTable.test.jsx @@ -64,8 +64,8 @@ function generateTransactions(count, splitAtIndexes = [], showError = false) { i === 0 ? null : i === 1 - ? usualGroup.categories[1].id - : usualGroup.categories[0].id, + ? usualGroup.categories[1].id + : usualGroup.categories[0].id, amount: isSplit ? 50 : undefined, sort_order: i, }, @@ -817,7 +817,9 @@ describe('Transactions', () => { // Add another split transaction and make sure everything is // updated properly - await userEvent.click(toolbar.querySelector('[data-testid="add-split-button"]')); + await userEvent.click( + toolbar.querySelector('[data-testid="add-split-button"]'), + ); expect(getTransactions().length).toBe(7); expect(getTransactions()[2].amount).toBe(0); expectErrorToExist(getTransactions().slice(0, 3)); diff --git a/packages/desktop-client/src/setupTests.jsx b/packages/desktop-client/src/setupTests.js similarity index 70% rename from packages/desktop-client/src/setupTests.jsx rename to packages/desktop-client/src/setupTests.js index e04418579f3..0975add586c 100644 --- a/packages/desktop-client/src/setupTests.jsx +++ b/packages/desktop-client/src/setupTests.js @@ -7,16 +7,11 @@ installPolyfills(); global.IS_TESTING = true; global.Actual = {}; -vi.mock( - 'react-virtualized-auto-sizer', - () => ({ - default: (props) => { - return ( - props.children({height: 1000, width: 600}) - ); - } - }) -); +vi.mock('react-virtualized-auto-sizer', () => ({ + default: props => { + return props.children({ height: 1000, width: 600 }); + }, +})); global.Date.now = () => 123456789; diff --git a/packages/desktop-client/vite.config.mts b/packages/desktop-client/vite.config.mts index 051d515e251..97de911bb94 100644 --- a/packages/desktop-client/vite.config.mts +++ b/packages/desktop-client/vite.config.mts @@ -29,7 +29,7 @@ const addWatchers = (): Plugin => ({ const injectShims = (): Plugin[] => { const buildShims = path.resolve('./src/build-shims.js'); const commonInject = { - exclude: ['src/setupTests.jsx'], + exclude: ['src/setupTests.js'], global: [buildShims, 'global'], }; @@ -166,7 +166,7 @@ export default defineConfig(async ({ mode }) => { include: ['src/**/*.{test,spec}.?(c|m)[jt]s?(x)'], environment: 'jsdom', globals: true, - setupFiles: './src/setupTests.jsx', + setupFiles: './src/setupTests.js', }, }; }); diff --git a/packages/desktop-electron/security.js b/packages/desktop-electron/security.js index a3f43a22745..e961bf7e5fb 100644 --- a/packages/desktop-electron/security.js +++ b/packages/desktop-electron/security.js @@ -25,16 +25,14 @@ electron.app.on('web-contents-created', function (event, contents) { }); electron.app.on('ready', function () { - electron.session.defaultSession.setPermissionRequestHandler(function ( - webContents, - permission, - callback, - ) { - const url = webContents.getURL(); - if (url.startsWith('file://')) { - callback(true); - } else { - callback(false); - } - }); + electron.session.defaultSession.setPermissionRequestHandler( + function (webContents, permission, callback) { + const url = webContents.getURL(); + if (url.startsWith('file://')) { + callback(true); + } else { + callback(false); + } + }, + ); }); diff --git a/packages/loot-core/src/client/platform.electron.ts b/packages/loot-core/src/client/platform.electron.ts index 57ec58da8f7..aee5e87a997 100644 --- a/packages/loot-core/src/client/platform.electron.ts +++ b/packages/loot-core/src/client/platform.electron.ts @@ -9,9 +9,9 @@ export const isPlaywright = false; export const OS: 'windows' | 'mac' | 'linux' | 'unknown' = isWindows ? 'windows' : isMac - ? 'mac' - : isLinux - ? 'linux' - : 'unknown'; + ? 'mac' + : isLinux + ? 'linux' + : 'unknown'; export const env: 'web' | 'mobile' | 'unknown' = 'unknown'; export const isBrowser = false; diff --git a/packages/loot-core/src/client/platform.web.ts b/packages/loot-core/src/client/platform.web.ts index 25a86de84ca..7d81d477d56 100644 --- a/packages/loot-core/src/client/platform.web.ts +++ b/packages/loot-core/src/client/platform.web.ts @@ -9,7 +9,7 @@ export const isPlaywright = navigator.userAgent === 'playwright'; export const OS: 'windows' | 'mac' | 'linux' | 'unknown' = isWindows ? 'windows' : isMac - ? 'mac' - : 'linux'; + ? 'mac' + : 'linux'; export const env: 'web' | 'mobile' | 'unknown' = 'web'; export const isBrowser = true; diff --git a/packages/loot-core/src/client/query-helpers.test.ts b/packages/loot-core/src/client/query-helpers.test.ts index 55721e9683e..a5ab249d287 100644 --- a/packages/loot-core/src/client/query-helpers.test.ts +++ b/packages/loot-core/src/client/query-helpers.test.ts @@ -55,12 +55,12 @@ function runPagedQuery(query, data) { return op === '$gte' ? row.date >= filter.date[op] : op === '$lte' - ? row.date <= filter.date[op] - : op === '$lt' - ? row.date < filter.date[op] - : op === '$gt' - ? row.date > filter.date[op] - : false; + ? row.date <= filter.date[op] + : op === '$lt' + ? row.date < filter.date[op] + : op === '$gt' + ? row.date > filter.date[op] + : false; }) .map(row => select(row, query.selectExpressions)), query.limit, diff --git a/packages/loot-core/src/platform/server/connection/index.web.ts b/packages/loot-core/src/platform/server/connection/index.web.ts index 6e2a37287ea..212f64e96eb 100644 --- a/packages/loot-core/src/platform/server/connection/index.web.ts +++ b/packages/loot-core/src/platform/server/connection/index.web.ts @@ -9,8 +9,8 @@ function getGlobalObject() { typeof window !== 'undefined' ? window : typeof self !== 'undefined' - ? self - : null; + ? self + : null; if (!obj) { throw new Error('Cannot get global object'); } diff --git a/packages/loot-core/src/server/accounts/export-to-csv.ts b/packages/loot-core/src/server/accounts/export-to-csv.ts index 79a838fa1ad..6d9dd432b7e 100644 --- a/packages/loot-core/src/server/accounts/export-to-csv.ts +++ b/packages/loot-core/src/server/accounts/export-to-csv.ts @@ -98,8 +98,8 @@ export async function exportQueryToCSV(query) { trans.Reconciled === true ? 'Reconciled' : trans.Cleared === true - ? 'Cleared' - : 'Not cleared', + ? 'Cleared' + : 'Not cleared', }; }); diff --git a/packages/loot-core/src/server/accounts/parse-file.test.ts b/packages/loot-core/src/server/accounts/parse-file.test.ts index b848988432f..95bcf6fff05 100644 --- a/packages/loot-core/src/server/accounts/parse-file.test.ts +++ b/packages/loot-core/src/server/accounts/parse-file.test.ts @@ -36,9 +36,8 @@ async function importFileWithRealTime( ) { // Emscripten requires a real Date.now! global.restoreDateNow(); - const { errors, transactions: originalTransactions } = await parseFile( - filepath, - ); + const { errors, transactions: originalTransactions } = + await parseFile(filepath); global.restoreFakeDateNow(); let transactions = originalTransactions; diff --git a/packages/loot-core/src/server/accounts/rules.ts b/packages/loot-core/src/server/accounts/rules.ts index f532bc2c2a3..0a514f75855 100644 --- a/packages/loot-core/src/server/accounts/rules.ts +++ b/packages/loot-core/src/server/accounts/rules.ts @@ -88,8 +88,8 @@ const CONDITION_TYPES = { typeof value === 'string' ? parseDateString(value) : value.frequency != null - ? parseRecurDate(value) - : null; + ? parseRecurDate(value) + : null; assert( parsed, 'date-format', diff --git a/packages/loot-core/src/server/backups.ts b/packages/loot-core/src/server/backups.ts index a68d8f3d597..1fda2dee5bb 100644 --- a/packages/loot-core/src/server/backups.ts +++ b/packages/loot-core/src/server/backups.ts @@ -214,10 +214,13 @@ export function startBackupService(id: string) { } // Make a backup every 15 minutes - serviceInterval = setInterval(async () => { - console.log('Making backup'); - await makeBackup(id); - }, 1000 * 60 * 15); + serviceInterval = setInterval( + async () => { + console.log('Making backup'); + await makeBackup(id); + }, + 1000 * 60 * 15, + ); } export function stopBackupService() { diff --git a/packages/loot-core/src/server/budget/goals/goalsSchedule.ts b/packages/loot-core/src/server/budget/goals/goalsSchedule.ts index 2b825b0a46c..ac7d6520094 100644 --- a/packages/loot-core/src/server/budget/goals/goalsSchedule.ts +++ b/packages/loot-core/src/server/budget/goals/goalsSchedule.ts @@ -217,9 +217,8 @@ export async function goalsSchedule( const totalPayMonthOf = await getPayMonthOfTotal(t_payMonthOf); const totalSinking = await getSinkingTotal(t_sinking); - const totalSinkingBaseContribution = await getSinkingBaseContributionTotal( - t_sinking, - ); + const totalSinkingBaseContribution = + await getSinkingBaseContributionTotal(t_sinking); if (balance >= totalSinking + totalPayMonthOf) { to_budget += Math.round(totalPayMonthOf + totalSinkingBaseContribution); diff --git a/packages/loot-core/src/server/budget/goaltemplates.ts b/packages/loot-core/src/server/budget/goaltemplates.ts index 6813d00af8a..0d94aa7775a 100644 --- a/packages/loot-core/src/server/budget/goaltemplates.ts +++ b/packages/loot-core/src/server/budget/goaltemplates.ts @@ -259,9 +259,8 @@ async function processTemplate( t.type === 'schedule' || t.type === 'by', ); - const { lowPriority, errorNotice } = await checkScheduleTemplates( - template_lines, - ); + const { lowPriority, errorNotice } = + await checkScheduleTemplates(template_lines); priorityCheck = lowPriority; skipSchedule = priorityCheck !== priority ? true : false; isScheduleOrBy = true; diff --git a/packages/loot-core/src/server/importers/ynab4.ts b/packages/loot-core/src/server/importers/ynab4.ts index 010c9e981ec..f285b8047c3 100644 --- a/packages/loot-core/src/server/importers/ynab4.ts +++ b/packages/loot-core/src/server/importers/ynab4.ts @@ -377,9 +377,12 @@ function getFile(entries: AdmZip.IZipEntry[], path: string) { } function join(...paths: string[]): string { - return paths.slice(1).reduce((full, path) => { - return full + '/' + path.replace(/^\//, ''); - }, paths[0].replace(/\/$/, '')); + return paths.slice(1).reduce( + (full, path) => { + return full + '/' + path.replace(/^\//, ''); + }, + paths[0].replace(/\/$/, ''), + ); } export function parseFile(buffer: Buffer): YNAB4.YFull { diff --git a/upcoming-release-notes/2253.md b/upcoming-release-notes/2253.md new file mode 100644 index 00000000000..3306f0dce4d --- /dev/null +++ b/upcoming-release-notes/2253.md @@ -0,0 +1,6 @@ +--- +category: Maintenance +authors: [MatissJanis] +--- + +Upgrading prettier, fixing the issues and enabling it for jsx files too diff --git a/yarn.lock b/yarn.lock index 669359f25af..63b4df37413 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2700,6 +2700,13 @@ __metadata: languageName: node linkType: hard +"@pkgr/core@npm:^0.1.0": + version: 0.1.1 + resolution: "@pkgr/core@npm:0.1.1" + checksum: 6f25fd2e3008f259c77207ac9915b02f1628420403b2630c92a07ff963129238c9262afc9e84344c7a23b5cc1f3965e2cd17e3798219f5fd78a63d144d3cceba + languageName: node + linkType: hard + "@pkgr/utils@npm:^2.3.1": version: 2.4.1 resolution: "@pkgr/utils@npm:2.4.1" @@ -4914,15 +4921,16 @@ __metadata: dependencies: cross-env: "npm:^7.0.3" eslint: "npm:^8.37.0" + eslint-config-prettier: "npm:^9.1.0" eslint-config-react-app: "npm:7.0.1" eslint-import-resolver-typescript: "npm:3.5.5" eslint-plugin-import: "npm:2.27.5" - eslint-plugin-prettier: "npm:4.2.1" + eslint-plugin-prettier: "npm:5.1.3" eslint-plugin-react: "npm:7.32.2" eslint-plugin-rulesdir: "npm:^0.2.2" node-jq: "npm:^4.0.1" npm-run-all: "npm:^4.1.3" - prettier: "npm:2.8.2" + prettier: "npm:3.2.4" react-refresh: "npm:^0.14.0" source-map-support: "npm:^0.5.21" typescript: "npm:^5.0.2" @@ -7853,6 +7861,17 @@ __metadata: languageName: node linkType: hard +"eslint-config-prettier@npm:^9.1.0": + version: 9.1.0 + resolution: "eslint-config-prettier@npm:9.1.0" + peerDependencies: + eslint: ">=7.0.0" + bin: + eslint-config-prettier: bin/cli.js + checksum: 411e3b3b1c7aa04e3e0f20d561271b3b909014956c4dba51c878bf1a23dbb8c800a3be235c46c4732c70827276e540b6eed4636d9b09b444fd0a8e07f0fcd830 + languageName: node + linkType: hard + "eslint-config-react-app@npm:7.0.1": version: 7.0.1 resolution: "eslint-config-react-app@npm:7.0.1" @@ -8055,18 +8074,23 @@ __metadata: languageName: node linkType: hard -"eslint-plugin-prettier@npm:4.2.1": - version: 4.2.1 - resolution: "eslint-plugin-prettier@npm:4.2.1" +"eslint-plugin-prettier@npm:5.1.3": + version: 5.1.3 + resolution: "eslint-plugin-prettier@npm:5.1.3" dependencies: prettier-linter-helpers: "npm:^1.0.0" + synckit: "npm:^0.8.6" peerDependencies: - eslint: ">=7.28.0" - prettier: ">=2.0.0" + "@types/eslint": ">=8.0.0" + eslint: ">=8.0.0" + eslint-config-prettier: "*" + prettier: ">=3.0.0" peerDependenciesMeta: + "@types/eslint": + optional: true eslint-config-prettier: optional: true - checksum: d387f85dd1bfcb6bc6b794845fee6afb9ebb2375653de6bcde6e615892fb97f85121a7c012a4651b181fc09953bdf54c9bc70cab7ad297019d89ae87dd007e28 + checksum: 4f26a30444adc61ed692cdb5a9f7e8d9f5794f0917151051e66755ce032a08c3cc72c8b5d56101412e90f6d77035bd8194ea8731e9c16aacdd5ae345a8dae188 languageName: node linkType: hard @@ -13650,12 +13674,12 @@ __metadata: languageName: node linkType: hard -"prettier@npm:2.8.2": - version: 2.8.2 - resolution: "prettier@npm:2.8.2" +"prettier@npm:3.2.4": + version: 3.2.4 + resolution: "prettier@npm:3.2.4" bin: - prettier: bin-prettier.js - checksum: 2362d0902d7c5aa820e3b022ad5d7b0b0dca7beb847aa3f71d2fc53d0a8e412147278950482d3ac733c98718603b4bbd2ca64ad864d2af4fa2fb7d034e786ae7 + prettier: bin/prettier.cjs + checksum: e2b735d0552501b3a7ac8bd3ba3b6de2920bb35bd4cd02d08cb9057ebe3e96d83b9a7e4b903d987b7530a50223b12c74d107c154337236ae2c68156ba1e65cd2 languageName: node linkType: hard @@ -15657,6 +15681,16 @@ __metadata: languageName: node linkType: hard +"synckit@npm:^0.8.6": + version: 0.8.8 + resolution: "synckit@npm:0.8.8" + dependencies: + "@pkgr/core": "npm:^0.1.0" + tslib: "npm:^2.6.2" + checksum: 2864a5c3e689ad5b991bebbd8a583c5682c4fa08a4f39986b510b6b5d160c08fc3672444069f8f96ed6a9d12772879c674c1f61e728573eadfa90af40a765b74 + languageName: node + linkType: hard + "tabbable@npm:^5.3.3": version: 5.3.3 resolution: "tabbable@npm:5.3.3" @@ -16114,6 +16148,13 @@ __metadata: languageName: node linkType: hard +"tslib@npm:^2.6.2": + version: 2.6.2 + resolution: "tslib@npm:2.6.2" + checksum: bd26c22d36736513980091a1e356378e8b662ded04204453d353a7f34a4c21ed0afc59b5f90719d4ba756e581a162ecbf93118dc9c6be5acf70aa309188166ca + languageName: node + linkType: hard + "tsutils@npm:^3.21.0": version: 3.21.0 resolution: "tsutils@npm:3.21.0"