Skip to content

Commit

Permalink
Merge branch 'master' into enhancement/context_menus/sidebar
Browse files Browse the repository at this point in the history
  • Loading branch information
UnderKoen committed Dec 17, 2024
2 parents ca98b6a + 94666a2 commit 472c7bc
Show file tree
Hide file tree
Showing 287 changed files with 3,772 additions and 535 deletions.
10 changes: 8 additions & 2 deletions .github/ISSUE_TEMPLATE/bug-report.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@ body:
options:
- label: 'I have searched and found no existing issue'
required: true
- label: 'I will be providing steps how to reproduce the bug (in most cases this will also mean uploading a demo budget file)'
required: true
validations:
required: true
- type: textarea
Expand All @@ -36,6 +34,14 @@ body:
value: 'A bug happened!'
validations:
required: true
- type: textarea
id: reproduction
attributes:
label: How can we reproduce the issue?
description: Please give step-by-step instructions on how to reproduce the issue. In most cases this might also require uploading a sample budget/import file.
value: 'How can we reproduce the issue?'
validations:
required: true
- type: markdown
id: env-info
attributes:
Expand Down
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.
6 changes: 3 additions & 3 deletions packages/desktop-client/e2e/accounts.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,17 +54,17 @@ test.describe('Accounts', () => {
await expect(page).toMatchThemeScreenshots();
});

test.describe('Budgeted Accounts', () => {
test.describe('On Budget Accounts', () => {
// Reset filters
test.afterEach(async () => {
await accountPage.removeFilter(0);
});

test('creates a transfer from two existing transactions', async () => {
accountPage = await navigation.goToAccountPage('For budget');
accountPage = await navigation.goToAccountPage('On budget');
await accountPage.waitFor();

await expect(accountPage.accountName).toHaveText('Budgeted Accounts');
await expect(accountPage.accountName).toHaveText('On Budget Accounts');

await accountPage.filterByNote('Test Acc Transfer');

Expand Down
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.
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.
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.
4 changes: 2 additions & 2 deletions packages/desktop-client/e2e/budget.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,12 @@ test.describe('Budget', () => {
test('renders the summary information: available funds, overspent, budgeted and for next month', async () => {
const summary = budgetPage.budgetSummary.first();

await expect(summary.getByText('Available Funds')).toBeVisible({
await expect(summary.getByText('Available funds')).toBeVisible({
timeout: 10000,
});
await expect(summary.getByText(/^Overspent in /)).toBeVisible();
await expect(summary.getByText('Budgeted')).toBeVisible();
await expect(summary.getByText('For Next Month')).toBeVisible();
await expect(summary.getByText('For next month')).toBeVisible();
await expect(page).toMatchThemeScreenshots();
});

Expand Down
4 changes: 2 additions & 2 deletions packages/desktop-client/e2e/page-models/mobile-budget-page.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export class MobileBudgetPage {
name: 'Saved',
});
this.projectedSavingsButton = this.budgetTableHeader.getByRole('button', {
name: 'Projected Savings',
name: 'Projected savings',
});
this.overspentButton = this.budgetTableHeader.getByRole('button', {
name: 'Overspent',
Expand Down Expand Up @@ -294,7 +294,7 @@ export class MobileBudgetPage {
}

throw new Error(
'None of “Saved”, “Projected Savings”, or “Overspent” buttons could be located on the page',
'None of “Saved”, “Projected savings”, or “Overspent” buttons could be located on the page',
);
}

Expand Down
2 changes: 1 addition & 1 deletion packages/desktop-client/e2e/page-models/navigation.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ export class Navigation {
await this.page.getByLabel('Balance:').fill(String(data.balance));

if (data.offBudget) {
await this.page.getByLabel('Off-budget').click();
await this.page.getByLabel('Off budget').click();
}

await this.page
Expand Down
26 changes: 16 additions & 10 deletions packages/desktop-client/src/components/LoggedInUser.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
// @ts-strict-ignore
import React, { useState, useEffect, useRef, type CSSProperties } from 'react';
import { Trans, useTranslation } from 'react-i18next';
import { useSelector } from 'react-redux';
import { useDispatch, useSelector } from 'react-redux';

import { closeBudget, getUserData, signOut } from 'loot-core/client/actions';
import { type State } from 'loot-core/src/client/state-types';

import { useActions } from '../hooks/useActions';
import { useNavigate } from '../hooks/useNavigate';
import { theme, styles } from '../style';

Expand All @@ -27,22 +27,28 @@ export function LoggedInUser({
color,
}: LoggedInUserProps) {
const { t } = useTranslation();

const dispatch = useDispatch();
const navigate = useNavigate();
const userData = useSelector((state: State) => state.user.data);
const { getUserData, signOut, closeBudget } = useActions();
const [loading, setLoading] = useState(true);
const [menuOpen, setMenuOpen] = useState(false);
const serverUrl = useServerURL();
const triggerRef = useRef(null);

useEffect(() => {
getUserData().then(() => setLoading(false));
async function init() {
await dispatch(getUserData());
}

init().then(() => setLoading(false));
}, []);

const navigate = useNavigate();
async function onCloseBudget() {
await dispatch(closeBudget());
}

async function onChangePassword() {
await closeBudget();
await onCloseBudget();
navigate('/change-password');
}

Expand All @@ -54,14 +60,14 @@ export function LoggedInUser({
onChangePassword();
break;
case 'sign-in':
await closeBudget();
await onCloseBudget();
navigate('/login');
break;
case 'sign-out':
signOut();
dispatch(signOut());
break;
case 'config-server':
await closeBudget();
await onCloseBudget();
navigate('/config-server');
break;
default:
Expand Down
4 changes: 2 additions & 2 deletions packages/desktop-client/src/components/ManageRulesPage.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import React from 'react';

import { t } from 'i18next';
import { useTranslation } from 'react-i18next';

import { ManageRules } from './ManageRules';
import { Page } from './Page';

export function ManageRulesPage() {
const { t } = useTranslation();
return (
<Page header={t('Rules')}>
<ManageRules isModal={false} payeeId={null} />
Expand Down
11 changes: 11 additions & 0 deletions packages/desktop-client/src/components/Modals.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ import { KeyboardShortcutModal } from './modals/KeyboardShortcutModal';
import { LoadBackupModal } from './modals/LoadBackupModal';
import { ConfirmChangeDocumentDirModal } from './modals/manager/ConfirmChangeDocumentDir';
import { DeleteFileModal } from './modals/manager/DeleteFileModal';
import { DuplicateFileModal } from './modals/manager/DuplicateFileModal';
import { FilesSettingsModal } from './modals/manager/FilesSettingsModal';
import { ImportActualModal } from './modals/manager/ImportActualModal';
import { ImportModal } from './modals/manager/ImportModal';
Expand Down Expand Up @@ -586,6 +587,16 @@ export function Modals() {
return <BudgetListModal key={name} />;
case 'delete-budget':
return <DeleteFileModal key={name} file={options.file} />;
case 'duplicate-budget':
return (
<DuplicateFileModal
key={name}
file={options.file}
managePage={options?.managePage}
loadBudget={options?.loadBudget}
onComplete={options?.onComplete}
/>
);
case 'import':
return <ImportModal key={name} />;
case 'files-settings':
Expand Down
3 changes: 2 additions & 1 deletion packages/desktop-client/src/components/Notes.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
// @ts-strict-ignore
import React, { useEffect, useRef, type CSSProperties } from 'react';
import { useTranslation } from 'react-i18next';
import ReactMarkdown from 'react-markdown';

import { css } from '@emotion/css';
import { t } from 'i18next';
import remarkGfm from 'remark-gfm';

import { theme } from '../style';
Expand Down Expand Up @@ -99,6 +99,7 @@ export function Notes({
getStyle,
}: NotesProps) {
const { isNarrowWidth } = useResponsive();
const { t } = useTranslation();

const textAreaRef = useRef<HTMLTextAreaElement>();

Expand Down
4 changes: 2 additions & 2 deletions packages/desktop-client/src/components/NotesButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ import React, {
type ComponentProps,
type CSSProperties,
} from 'react';

import { t } from 'i18next';
import { useTranslation } from 'react-i18next';

import { send } from 'loot-core/src/platform/client/fetch';

Expand Down Expand Up @@ -36,6 +35,7 @@ export function NotesButton({
tooltipPosition = 'bottom start',
style,
}: NotesButtonProps) {
const { t } = useTranslation();
const triggerRef = useRef(null);
const [isOpen, setIsOpen] = useState<boolean>(false);
const note = useNotes(id) || '';
Expand Down
3 changes: 2 additions & 1 deletion packages/desktop-client/src/components/Notifications.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ import React, {
type SetStateAction,
type CSSProperties,
} from 'react';
import { useTranslation } from 'react-i18next';
import { useDispatch, useSelector } from 'react-redux';

import { css } from '@emotion/css';
import { t } from 'i18next';

import { removeNotification } from 'loot-core/client/actions';
import { type State } from 'loot-core/src/client/state-types';
Expand Down Expand Up @@ -91,6 +91,7 @@ function Notification({
notification: NotificationWithId;
onRemove: () => void;
}) {
const { t } = useTranslation();
const {
type,
title,
Expand Down
4 changes: 2 additions & 2 deletions packages/desktop-client/src/components/ThemeSelector.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import React, { useRef, useState, type CSSProperties } from 'react';

import { t } from 'i18next';
import { useTranslation } from 'react-i18next';

import type { Theme } from 'loot-core/src/types/prefs';

Expand All @@ -22,6 +21,7 @@ export function ThemeSelector({ style }: ThemeSelectorProps) {
const triggerRef = useRef(null);

const { isNarrowWidth } = useResponsive();
const { t } = useTranslation();

const themeIcons = {
light: SvgSun,
Expand Down
18 changes: 11 additions & 7 deletions packages/desktop-client/src/components/Titlebar.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import React, { useState, useEffect, type CSSProperties } from 'react';
import { useHotkeys } from 'react-hotkeys-hook';
import { useTranslation } from 'react-i18next';
import { useDispatch } from 'react-redux';
import { Routes, Route, useLocation } from 'react-router-dom';

import { css } from '@emotion/css';
import { t } from 'i18next';

import { sync } from 'loot-core/client/actions';
import * as Platform from 'loot-core/src/client/platform';
import * as queries from 'loot-core/src/client/queries';
import { listen } from 'loot-core/src/platform/client/fetch';
Expand All @@ -13,7 +15,6 @@ import {
isElectron,
} from 'loot-core/src/shared/environment';

import { useActions } from '../hooks/useActions';
import { useGlobalPref } from '../hooks/useGlobalPref';
import { useMetadataPref } from '../hooks/useMetadataPref';
import { useNavigate } from '../hooks/useNavigate';
Expand Down Expand Up @@ -107,9 +108,9 @@ type SyncButtonProps = {
isMobile?: boolean;
};
function SyncButton({ style, isMobile = false }: SyncButtonProps) {
const { t } = useTranslation();
const [cloudFileId] = useMetadataPref('cloudFileId');
const { sync } = useActions();

const dispatch = useDispatch();
const [syncing, setSyncing] = useState(false);
const [syncState, setSyncState] = useState<
null | 'offline' | 'local' | 'disabled' | 'error'
Expand Down Expand Up @@ -193,15 +194,17 @@ function SyncButton({ style, isMobile = false }: SyncButtonProps) {
marginRight: 5,
};

const onSync = () => dispatch(sync());

useHotkeys(
'ctrl+s, cmd+s, meta+s',
sync,
onSync,
{
enableOnFormTags: true,
preventDefault: true,
scopes: ['app'],
},
[sync],
[onSync],
);

return (
Expand All @@ -223,7 +226,7 @@ function SyncButton({ style, isMobile = false }: SyncButtonProps) {
'&[data-hovered]': hoveredStyle,
'&[data-pressed]': activeStyle,
})}
onPress={sync}
onPress={onSync}
>
{isMobile ? (
syncState === 'error' ? (
Expand Down Expand Up @@ -265,6 +268,7 @@ type TitlebarProps = {
};

export function Titlebar({ style }: TitlebarProps) {
const { t } = useTranslation();
const navigate = useNavigate();
const location = useLocation();
const sidebar = useSidebar();
Expand Down
21 changes: 13 additions & 8 deletions packages/desktop-client/src/components/UpdateNotification.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import React from 'react';
import { useTranslation } from 'react-i18next';
import { useSelector } from 'react-redux';
import { useSelector, useDispatch } from 'react-redux';

import { setAppState, updateApp } from 'loot-core/client/actions';
import { type State } from 'loot-core/src/client/state-types';

import { useActions } from '../hooks/useActions';
import { SvgClose } from '../icons/v1';
import { theme } from '../style';

Expand All @@ -20,7 +20,10 @@ export function UpdateNotification() {
(state: State) => state.app.showUpdateNotification,
);

const { updateApp, setAppState } = useActions();
const dispatch = useDispatch();
const onRestart = () => {
dispatch(updateApp());
};

if (updateInfo && showUpdateNotification) {
const notes = updateInfo.releaseNotes;
Expand Down Expand Up @@ -51,7 +54,7 @@ export function UpdateNotification() {
<Text>
<Link
variant="text"
onClick={updateApp}
onClick={onRestart}
style={{
color: theme.buttonPrimaryText,
textDecoration: 'underline',
Expand Down Expand Up @@ -81,10 +84,12 @@ export function UpdateNotification() {
style={{ display: 'inline', padding: '1px 7px 2px 7px' }}
onPress={() => {
// Set a flag to never show an update notification again for this session
setAppState({
updateInfo: null,
showUpdateNotification: false,
});
dispatch(
setAppState({
updateInfo: null,
showUpdateNotification: false,
}),
);
}}
>
<SvgClose
Expand Down
Loading

0 comments on commit 472c7bc

Please sign in to comment.