diff --git a/.github/workflows/electron-master.yml b/.github/workflows/electron-master.yml index 633a48cff89..a7511042871 100644 --- a/.github/workflows/electron-master.yml +++ b/.github/workflows/electron-master.yml @@ -48,13 +48,17 @@ jobs: sudo flatpak install org.electronjs.Electron2.BaseApp/x86_64/23.08 -y - name: Set up environment uses: ./.github/actions/setup - - name: Build Electron + - name: Build Electron for Mac + if: ${{ startsWith(matrix.os, 'macos') }} run: ./bin/package-electron env: - # CSC_KEY_PASSWORD: ${{ secrets.CSC_KEY_PASSWORD }} - # CSC_LINK: ${{ secrets.CSC_LINK }} + CSC_KEY_PASSWORD: ${{ secrets.CSC_KEY_PASSWORD }} + CSC_LINK: ${{ secrets.CSC_LINK }} APPLE_ID: ${{ secrets.APPLE_ID }} APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }} + - name: Build Electron + if: ${{ ! startsWith(matrix.os, 'macos') }} + run: ./bin/package-electron - name: Upload Build uses: actions/upload-artifact@v4 with: diff --git a/packages/desktop-client/src/components/accounts/Account.jsx b/packages/desktop-client/src/components/accounts/Account.jsx index 01bcc5abd85..b946bcbabae 100644 --- a/packages/desktop-client/src/components/accounts/Account.jsx +++ b/packages/desktop-client/src/components/accounts/Account.jsx @@ -1113,10 +1113,10 @@ class AccountInternal extends PureComponent { ); }; - onConditionsOpChange = (value, conditions) => { + onConditionsOpChange = value => { this.setState({ filterConditionsOp: value }); this.setState({ filterId: { ...this.state.filterId, status: 'changed' } }); - this.applyFilters([...conditions]); + this.applyFilters([...this.state.filterConditions]); if (this.state.search !== '') { this.onSearch(this.state.search); } diff --git a/packages/desktop-client/src/components/filters/FilterExpression.tsx b/packages/desktop-client/src/components/filters/FilterExpression.tsx index d649fd09c3f..34df7694a76 100644 --- a/packages/desktop-client/src/components/filters/FilterExpression.tsx +++ b/packages/desktop-client/src/components/filters/FilterExpression.tsx @@ -79,7 +79,8 @@ export function FilterExpression({ valueIsRaw={ op === 'contains' || op === 'matches' || - op === 'doesNotContain' + op === 'doesNotContain' || + op === 'hasTags' } /> diff --git a/packages/desktop-client/src/components/filters/FiltersMenu.jsx b/packages/desktop-client/src/components/filters/FiltersMenu.jsx index 61720dff6dd..8baacffe99e 100644 --- a/packages/desktop-client/src/components/filters/FiltersMenu.jsx +++ b/packages/desktop-client/src/components/filters/FiltersMenu.jsx @@ -201,7 +201,10 @@ function ConfigureField({ subfield={subfield} type={ type === 'id' && - (op === 'contains' || op === 'matches' || op === 'doesNotContain') + (op === 'contains' || + op === 'matches' || + op === 'doesNotContain' || + op === 'hasTags') ? 'string' : type } diff --git a/packages/desktop-client/src/components/filters/FiltersStack.tsx b/packages/desktop-client/src/components/filters/FiltersStack.tsx index 3af0c68b736..02576c5de1d 100644 --- a/packages/desktop-client/src/components/filters/FiltersStack.tsx +++ b/packages/desktop-client/src/components/filters/FiltersStack.tsx @@ -34,7 +34,7 @@ export function FiltersStack({ onReloadSavedFilter: (savedFilter: SavedFilter, value?: string) => void; filterId: SavedFilter; savedFilters: TransactionFilterEntity[]; - onConditionsOpChange: () => void; + onConditionsOpChange: (value: 'and' | 'or') => void; }) { return ( diff --git a/packages/desktop-client/src/components/filters/updateFilterReducer.ts b/packages/desktop-client/src/components/filters/updateFilterReducer.ts index 5cb3727367e..4f6286f8383 100644 --- a/packages/desktop-client/src/components/filters/updateFilterReducer.ts +++ b/packages/desktop-client/src/components/filters/updateFilterReducer.ts @@ -18,7 +18,8 @@ export function updateFilterReducer( action.op === 'matches' || action.op === 'is' || action.op === 'doesNotContain' || - action.op === 'isNot') + action.op === 'isNot' || + action.op === 'hasTags') ) { // Clear out the value if switching between contains or // is/oneof for the id or string type diff --git a/packages/desktop-client/src/components/modals/EditRule.jsx b/packages/desktop-client/src/components/modals/EditRule.jsx index b896846fcfe..c409c77f51a 100644 --- a/packages/desktop-client/src/components/modals/EditRule.jsx +++ b/packages/desktop-client/src/components/modals/EditRule.jsx @@ -94,7 +94,7 @@ export function FieldSelect({ fields, style, value, onChange }) { bare options={fields} value={value} - onChange={value => onChange('field', value)} + onChange={onChange} buttonStyle={{ color: theme.pageTextPositive }} /> @@ -116,7 +116,7 @@ export function OpSelect({ // TODO: Add matches op support for payees, accounts, categories. .filter(op => type === 'id' - ? !['contains', 'matches', 'doesNotContain'].includes(op) + ? !['contains', 'matches', 'doesNotContain', 'hasTags'].includes(op) : true, ) .map(op => [op, formatOp(op, type)]); @@ -260,7 +260,11 @@ function ConditionEditor({ return ( - + onChange('field', value)} + /> {valueEditor} @@ -373,7 +377,7 @@ function ActionEditor({ action, editorStyle, onChange, onDelete, onAdd }) { onChange('field', value)} /> @@ -838,7 +842,7 @@ export function EditRule({ defaultRule, onSave: originalOnSave }) { setStage(stage); } - function onChangeConditionsOp(name, value) { + function onChangeConditionsOp(value) { setConditionsOp(value); } diff --git a/packages/desktop-client/src/components/reports/reports/CustomReport.tsx b/packages/desktop-client/src/components/reports/reports/CustomReport.tsx index c0ed8630347..df09f6eed27 100644 --- a/packages/desktop-client/src/components/reports/reports/CustomReport.tsx +++ b/packages/desktop-client/src/components/reports/reports/CustomReport.tsx @@ -155,7 +155,7 @@ export function CustomReport() { !!conditions.find( ({ field, op }) => field === 'category' && - ['contains', 'doesNotContain', 'matches'].includes(op), + ['contains', 'doesNotContain', 'matches', 'hasTags'].includes(op), ) || conditions.filter(({ field }) => field === 'category').length >= 2; const setSelectedCategories = (newCategories: CategoryEntity[]) => { diff --git a/packages/desktop-client/src/components/sidebar/Accounts.tsx b/packages/desktop-client/src/components/sidebar/Accounts.tsx index 398a7aae949..93ea82d1f9b 100644 --- a/packages/desktop-client/src/components/sidebar/Accounts.tsx +++ b/packages/desktop-client/src/components/sidebar/Accounts.tsx @@ -1,5 +1,6 @@ // @ts-strict-ignore import React, { useState } from 'react'; +import { useTranslation } from 'react-i18next'; import { useSelector } from 'react-redux'; import * as queries from 'loot-core/src/client/queries'; @@ -31,6 +32,7 @@ export function Accounts({ onToggleClosedAccounts, onReorder, }: AccountsProps) { + const { t } = useTranslation(); const [isDragging, setIsDragging] = useState(false); const failedAccounts = useFailedAccounts(); const updatedAccounts = useUpdatedAccounts(); @@ -62,7 +64,7 @@ export function Accounts({ return ( 0 && ( 0 && ( 0 && ( @@ -157,7 +161,7 @@ export function Accounts({ }} onClick={onAddAccount} Icon={SvgAdd} - title="Add account" + title={t('Add account')} /> ); diff --git a/packages/desktop-client/src/components/sidebar/Sidebar.tsx b/packages/desktop-client/src/components/sidebar/Sidebar.tsx index 687410eeeff..7ea8c47f578 100644 --- a/packages/desktop-client/src/components/sidebar/Sidebar.tsx +++ b/packages/desktop-client/src/components/sidebar/Sidebar.tsx @@ -1,4 +1,5 @@ import React, { useRef, useState } from 'react'; +import { useTranslation } from 'react-i18next'; import { useDispatch } from 'react-redux'; import { Resizable } from 're-resizable'; @@ -38,6 +39,7 @@ import { Tools } from './Tools'; export function Sidebar() { const hasWindowButtons = !Platform.isBrowser && Platform.OS === 'mac'; + const { t } = useTranslation(); const dispatch = useDispatch(); const sidebar = useSidebar(); const accounts = useAccounts(); @@ -149,10 +151,10 @@ export function Sidebar() { - - + + - + @@ -177,6 +179,7 @@ export function Sidebar() { } function EditableBudgetName() { + const { t } = useTranslation(); const dispatch = useDispatch(); const navigate = useNavigate(); const [budgetName, setBudgetNamePref] = useMetadataPref('budgetName'); @@ -205,10 +208,10 @@ function EditableBudgetName() { } const items = [ - { name: 'rename', text: 'Rename budget' }, - { name: 'settings', text: 'Settings' }, - ...(Platform.isBrowser ? [{ name: 'help', text: 'Help' }] : []), - { name: 'close', text: 'Close file' }, + { name: 'rename', text: t('Rename budget') }, + { name: 'settings', text: t('Settings') }, + ...(Platform.isBrowser ? [{ name: 'help', text: t('Help') }] : []), + { name: 'close', text: t('Close file') }, ]; if (editing) { @@ -250,7 +253,7 @@ function EditableBudgetName() { onPress={() => setMenuOpen(true)} > - {budgetName || 'A budget has no name'} + {budgetName || t('A budget has no name')} diff --git a/packages/desktop-client/src/components/sidebar/ToggleButton.tsx b/packages/desktop-client/src/components/sidebar/ToggleButton.tsx index bf7c79f5dc8..e7fddb15913 100644 --- a/packages/desktop-client/src/components/sidebar/ToggleButton.tsx +++ b/packages/desktop-client/src/components/sidebar/ToggleButton.tsx @@ -1,4 +1,5 @@ import React, { type ComponentPropsWithoutRef } from 'react'; +import { useTranslation } from 'react-i18next'; import { SvgPin } from '../../icons/v1'; import { SvgArrowButtonLeft1 } from '../../icons/v2'; @@ -17,11 +18,12 @@ export function ToggleButton({ isFloating, onFloat, }: ToggleButtonProps) { + const { t } = useTranslation(); return (