Skip to content

Commit

Permalink
Merge branch 'master' into zach/lock-transactions
Browse files Browse the repository at this point in the history
  • Loading branch information
zachwhelchel authored Oct 24, 2023
2 parents 2d91704 + 0af2987 commit 3f0c453
Show file tree
Hide file tree
Showing 440 changed files with 1,549 additions and 548 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.
10 changes: 10 additions & 0 deletions packages/desktop-client/e2e/page-models/reports-page.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,16 @@ export class ReportsPage {
return this.pageContent.getByRole('link', { name: /^Net/ }).waitFor();
}

async goToNetWorthPage() {
await this.pageContent.getByRole('link', { name: /^Net/ }).click();
return new ReportsPage(this.page);
}

async goToCashFlowPage() {
await this.pageContent.getByRole('link', { name: /^Cash/ }).click();
return new ReportsPage(this.page);
}

async getAvailableReportList() {
return this.pageContent
.getByRole('link')
Expand Down
10 changes: 10 additions & 0 deletions packages/desktop-client/e2e/reports.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,14 @@ test.describe('Reports', () => {
expect(reports).toEqual(['Net Worth', 'Cash Flow']);
await expect(page).toHaveScreenshot(screenshotConfig(page));
});

test('loads net worth graph and checks visuals', async () => {
await reportsPage.goToNetWorthPage();
await expect(page).toHaveScreenshot(screenshotConfig(page));
});

test('loads cash flow graph and checks visuals', async () => {
await reportsPage.goToCashFlowPage();
await expect(page).toHaveScreenshot(screenshotConfig(page));
});
});
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.
2 changes: 1 addition & 1 deletion packages/desktop-client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@
"watch": "cross-env BROWSER=none yarn start",
"build": "cross-env INLINE_RUNTIME_CHUNK=false craco build",
"build:browser": "cross-env ./bin/build-browser",
"generate:icons": "rm src/icons/*/*.js; cd src/icons && svgr --expand-props start --ext js -d . .",
"generate:icons": "rm src/icons/*/*.tsx; cd src/icons && svgr --typescript --expand-props start -d . .",
"test": "craco test",
"e2e": "npx playwright test --browser=chromium",
"vrt": "cross-env VRT=true npx playwright test --browser=chromium"
Expand Down
55 changes: 6 additions & 49 deletions packages/desktop-client/src/components/FinancesApp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import {
Route,
Routes,
Navigate,
NavLink,
useNavigate,
BrowserRouter,
useLocation,
Expand All @@ -21,12 +20,8 @@ import checkForUpdateNotification from 'loot-core/src/client/update-notification
import * as undo from 'loot-core/src/platform/client/undo';

import { useActions } from '../hooks/useActions';
import Add from '../icons/v1/Add';
import Cog from '../icons/v1/Cog';
import PiggyBank from '../icons/v1/PiggyBank';
import Wallet from '../icons/v1/Wallet';
import { useResponsive } from '../ResponsiveProvider';
import { theme, styles } from '../style';
import { theme } from '../style';
import { ExposeNavigate } from '../util/router-tools';
import { getIsOutdated, getLatestVersion } from '../util/versions';

Expand All @@ -35,11 +30,13 @@ import { BudgetMonthCountProvider } from './budget/BudgetMonthCountContext';
import View from './common/View';
import GlobalKeys from './GlobalKeys';
import { ManageRulesPage } from './ManageRulesPage';
import MobileNavTabs from './mobile/MobileNavTabs';
import Modals from './Modals';
import Notifications from './Notifications';
import { ManagePayeesPage } from './payees/ManagePayeesPage';
import Reports from './reports';
import { NarrowAlternate, WideComponent } from './responsive';
import ScrollProvider from './ScrollProvider';
import Settings from './settings';
import FloatableSidebar, { SidebarProvider } from './sidebar';
import Titlebar, { TitlebarProvider } from './Titlebar';
Expand Down Expand Up @@ -73,48 +70,6 @@ function WideNotSupported({ children, redirectTo = '/budget' }) {
return isNarrowWidth ? children : null;
}

function NavTab({ icon: TabIcon, name, path }) {
return (
<NavLink
to={path}
style={({ isActive }) => ({
alignItems: 'center',
color: isActive ? theme.mobileNavItemSelected : theme.mobileNavItem,
display: 'flex',
flexDirection: 'column',
textDecoration: 'none',
})}
>
<TabIcon width={22} height={22} style={{ marginBottom: '5px' }} />
{name}
</NavLink>
);
}

function MobileNavTabs() {
const { isNarrowWidth } = useResponsive();
return (
<div
style={{
backgroundColor: theme.mobileNavBackground,
borderTop: `1px solid ${theme.menuBorder}`,
bottom: 0,
...styles.shadow,
display: isNarrowWidth ? 'flex' : 'none',
height: '80px',
justifyContent: 'space-around',
paddingTop: 10,
width: '100%',
}}
>
<NavTab name="Budget" path="/budget" icon={Wallet} />
<NavTab name="Accounts" path="/accounts" icon={PiggyBank} />
<NavTab name="Transaction" path="/transactions/new" icon={Add} />
<NavTab name="Settings" path="/settings" icon={Cog} />
</div>
);
}

function RouterBehaviors({ getAccounts }) {
let navigate = useNavigate();
useEffect(() => {
Expand Down Expand Up @@ -305,7 +260,9 @@ export default function FinancesAppWithContext() {
<BudgetMonthCountProvider>
<PayeesProvider>
<AccountsProvider>
<DndProvider backend={Backend}>{app}</DndProvider>
<DndProvider backend={Backend}>
<ScrollProvider>{app}</ScrollProvider>
</DndProvider>
</AccountsProvider>
</PayeesProvider>
</BudgetMonthCountProvider>
Expand Down
3 changes: 2 additions & 1 deletion packages/desktop-client/src/components/GlobalKeys.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { useEffect } from 'react';
import { useNavigate } from 'react-router-dom';

import * as Platform from 'loot-core/src/client/platform';

import useNavigate from '../hooks/useNavigate';

export default function GlobalKeys() {
let navigate = useNavigate();
useEffect(() => {
Expand Down
2 changes: 1 addition & 1 deletion packages/desktop-client/src/components/LoggedInUser.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ export default function LoggedInUser({
return (
<Text
style={{
color: theme.altpageTextSubdued,
color: theme.pageTextLight,
fontStyle: 'italic',
...styles.delayedFadeIn,
...style,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
import React, { useState, useEffect, useCallback, useMemo } from 'react';
import React, {
useState,
useEffect,
useCallback,
useMemo,
type SetStateAction,
type Dispatch,
} from 'react';
import { useDispatch, useSelector } from 'react-redux';

import { pushModal } from 'loot-core/src/client/actions/modals';
Expand All @@ -7,6 +14,7 @@ import { send } from 'loot-core/src/platform/client/fetch';
import * as undo from 'loot-core/src/platform/client/undo';
import { mapField, friendlyOp } from 'loot-core/src/shared/rules';
import { describeSchedule } from 'loot-core/src/shared/schedules';
import { type RuleEntity } from 'loot-core/src/types/models';

import useCategories from '../hooks/useCategories';
import useSelected, { SelectedProvider } from '../hooks/useSelected';
Expand Down Expand Up @@ -76,7 +84,17 @@ function ruleToString(rule, data) {
);
}

function ManageRulesContent({ isModal, payeeId, setLoading }) {
type ManageRulesContentProps = {
isModal: boolean;
payeeId: string | null;
setLoading?: Dispatch<SetStateAction<boolean>>;
};

function ManageRulesContent({
isModal,
payeeId,
setLoading,
}: ManageRulesContentProps) {
let [allRules, setAllRules] = useState(null);
let [rules, setRules] = useState(null);
let [filter, setFilter] = useState('');
Expand Down Expand Up @@ -191,7 +209,7 @@ function ManageRulesContent({ isModal, payeeId, setLoading }) {
}, []);

function onCreateRule() {
let rule = {
let rule: RuleEntity = {
stage: null,
conditionsOp: 'and',
conditions: [
Expand Down Expand Up @@ -314,11 +332,17 @@ function ManageRulesContent({ isModal, payeeId, setLoading }) {
);
}

type ManageRulesProps = {
isModal: boolean;
payeeId: string | null;
setLoading?: Dispatch<SetStateAction<boolean>>;
};

export default function ManageRules({
isModal,
payeeId,
setLoading = () => {},
}) {
}: ManageRulesProps) {
return (
<SchedulesQuery.Provider>
<ManageRulesContent
Expand Down
8 changes: 4 additions & 4 deletions packages/desktop-client/src/components/Notifications.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ function Notification({
color: positive
? theme.noticeText
: error
? theme.alt3ErrorText
? theme.errorTextDark
: theme.alt4WarningText,
}}
>
Expand All @@ -129,7 +129,7 @@ function Notification({
positive
? theme.noticeBorder
: error
? theme.altErrorAccent
? theme.errorBorder
: theme.altWarningAccent
}`,
...styles.shadowLarge,
Expand Down Expand Up @@ -175,7 +175,7 @@ function Notification({
positive
? theme.noticeBorder
: error
? theme.altErrorAccent
? theme.errorBorder
: theme.altWarningAccent
}`,
color: 'currentColor',
Expand All @@ -185,7 +185,7 @@ function Notification({
backgroundColor: positive
? theme.noticeBackground
: error
? theme.altErrorBackground
? theme.errorBackground
: theme.altWarningBackground,
},
}}
Expand Down
54 changes: 54 additions & 0 deletions packages/desktop-client/src/components/ScrollProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import React, {
type ReactNode,
createContext,
useState,
useContext,
useEffect,
} from 'react';

import debounce from 'debounce';

type IScrollContext = {
scrollY: number | undefined;
isBottomReached: boolean;
};

const ScrollContext = createContext<IScrollContext | undefined>(undefined);

type ScrollProviderProps = {
children?: ReactNode;
};

export default function ScrollProvider({ children }: ScrollProviderProps) {
const [scrollY, setScrollY] = useState(undefined);
const [isBottomReached, setIsBottomReached] = useState(false);

useEffect(() => {
const listenToScroll = debounce(e => {
setScrollY(e.target?.scrollTop || 0);
setIsBottomReached(
e.target?.scrollHeight - e.target?.scrollTop <= e.target?.clientHeight,
);
}, 20);

window.addEventListener('scroll', listenToScroll, {
capture: true,
passive: true,
});
return () =>
window.removeEventListener('scroll', listenToScroll, {
capture: true,
});
}, []);

return (
<ScrollContext.Provider
value={{ scrollY, isBottomReached }}
children={children}
/>
);
}

export function useScroll(): IScrollContext {
return useContext(ScrollContext);
}
7 changes: 4 additions & 3 deletions packages/desktop-client/src/components/Titlebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@ import React, {
type ReactNode,
} from 'react';
import { useSelector } from 'react-redux';
import { Routes, Route, useLocation, useNavigate } from 'react-router-dom';
import { Routes, Route, useLocation } from 'react-router-dom';

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';

import { useActions } from '../hooks/useActions';
import useFeatureFlag from '../hooks/useFeatureFlag';
import useNavigate from '../hooks/useNavigate';
import ArrowLeft from '../icons/v1/ArrowLeft';
import AlertTriangle from '../icons/v2/AlertTriangle';
import SvgEye from '../icons/v2/Eye';
Expand Down Expand Up @@ -152,15 +153,15 @@ export function SyncButton({ style, isMobile = false }: SyncButtonProps) {

const mobileColor =
syncState === 'error'
? theme.alt4ErrorText
? theme.errorText
: syncState === 'disabled' ||
syncState === 'offline' ||
syncState === 'local'
? theme.sidebarItemText
: style.color;
const desktopColor =
syncState === 'error'
? theme.alt2ErrorText
? theme.errorTextDark
: syncState === 'disabled' ||
syncState === 'offline' ||
syncState === 'local'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export default function UpdateNotification() {
bottom: 0,
right: 0,
margin: '15px 17px',
backgroundColor: theme.altPageTextPositive,
backgroundColor: theme.pageTextPositive,
color: theme.tableBackground,
padding: '7px 10px',
borderRadius: 4,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { useEffect, useMemo, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { useParams, useNavigate } from 'react-router-dom';
import { useParams } from 'react-router-dom';

import debounce from 'debounce';
import memoizeOne from 'memoize-one';
Expand All @@ -20,6 +20,7 @@ import {
} from 'loot-core/src/shared/transactions';

import useCategories from '../../hooks/useCategories';
import useNavigate from '../../hooks/useNavigate';
import { useSetThemeColor } from '../../hooks/useSetThemeColor';
import { theme } from '../../style';

Expand Down
Loading

0 comments on commit 3f0c453

Please sign in to comment.