mirror of
https://github.com/actualbudget/actual.git
synced 2026-03-11 20:44:32 -05:00
[refactor] Migrate Discover schedules to tsx (#1946)
This commit is contained in:
@@ -3,7 +3,9 @@ import React, { useState } from 'react';
|
||||
import q, { runQuery } from 'loot-core/src/client/query-helpers';
|
||||
import { send } from 'loot-core/src/platform/client/fetch';
|
||||
import { getRecurringDescription } from 'loot-core/src/shared/schedules';
|
||||
import type { DiscoverScheduleEntity } from 'loot-core/src/types/models';
|
||||
|
||||
import type { BoundActions } from '../../hooks/useActions';
|
||||
import useSelected, {
|
||||
useSelectedDispatch,
|
||||
useSelectedItems,
|
||||
@@ -11,6 +13,7 @@ import useSelected, {
|
||||
} from '../../hooks/useSelected';
|
||||
import useSendPlatformRequest from '../../hooks/useSendPlatformRequest';
|
||||
import { theme } from '../../style';
|
||||
import type { CommonModalProps } from '../../types/modals';
|
||||
import { ButtonWithLoading } from '../common/Button';
|
||||
import Modal from '../common/Modal';
|
||||
import Paragraph from '../common/Paragraph';
|
||||
@@ -21,16 +24,22 @@ import DisplayId from '../util/DisplayId';
|
||||
|
||||
import { ScheduleAmountCell } from './SchedulesTable';
|
||||
|
||||
let ROW_HEIGHT = 43;
|
||||
const ROW_HEIGHT = 43;
|
||||
|
||||
function DiscoverSchedulesTable({ schedules, loading }) {
|
||||
let selectedItems = useSelectedItems();
|
||||
let dispatchSelected = useSelectedDispatch();
|
||||
function DiscoverSchedulesTable({
|
||||
schedules,
|
||||
loading,
|
||||
}: {
|
||||
schedules: DiscoverScheduleEntity[];
|
||||
loading: boolean;
|
||||
}) {
|
||||
const selectedItems = useSelectedItems();
|
||||
const dispatchSelected = useSelectedDispatch();
|
||||
|
||||
function renderItem({ item }) {
|
||||
let selected = selectedItems.has(item.id);
|
||||
let amountOp = item._conditions.find(c => c.field === 'amount').op;
|
||||
let recurDescription = getRecurringDescription(item.date);
|
||||
function renderItem({ item }: { item: DiscoverScheduleEntity }) {
|
||||
const selected = selectedItems.has(item.id);
|
||||
const amountOp = item._conditions.find(c => c.field === 'amount').op;
|
||||
const recurDescription = getRecurringDescription(item.date);
|
||||
|
||||
return (
|
||||
<Row
|
||||
@@ -110,33 +119,45 @@ function DiscoverSchedulesTable({ schedules, loading }) {
|
||||
);
|
||||
}
|
||||
|
||||
export default function DiscoverSchedules({ modalProps, actions }) {
|
||||
let { data: schedules, isLoading } =
|
||||
useSendPlatformRequest('schedule/discover');
|
||||
if (!schedules) schedules = [];
|
||||
export default function DiscoverSchedules({
|
||||
modalProps,
|
||||
actions,
|
||||
}: {
|
||||
modalProps: CommonModalProps;
|
||||
actions: BoundActions;
|
||||
}) {
|
||||
const { data, isLoading } = useSendPlatformRequest('schedule/discover');
|
||||
|
||||
let [creating, setCreating] = useState(false);
|
||||
const schedules = data || [];
|
||||
|
||||
let selectedInst = useSelected('discover-schedules', schedules, []);
|
||||
const [creating, setCreating] = useState(false);
|
||||
|
||||
const selectedInst = useSelected<DiscoverScheduleEntity>(
|
||||
'discover-schedules',
|
||||
schedules,
|
||||
[],
|
||||
);
|
||||
|
||||
async function onCreate() {
|
||||
let selected = schedules.filter(s => selectedInst.items.has(s.id));
|
||||
const selected = schedules.filter(s => selectedInst.items.has(s.id));
|
||||
setCreating(true);
|
||||
|
||||
for (let schedule of selected) {
|
||||
let scheduleId = await send('schedule/create', {
|
||||
const scheduleId = await send('schedule/create', {
|
||||
conditions: schedule._conditions,
|
||||
schedule: {},
|
||||
});
|
||||
|
||||
// Now query for matching transactions and link them automatically
|
||||
let { filters } = await send('make-filters-from-conditions', {
|
||||
const { filters } = await send('make-filters-from-conditions', {
|
||||
conditions: schedule._conditions,
|
||||
});
|
||||
|
||||
if (filters.length > 0) {
|
||||
let { data: transactions } = await runQuery(
|
||||
const { data: transactions } = await runQuery(
|
||||
q('transactions').filter({ $and: filters }).select('id'),
|
||||
);
|
||||
|
||||
await send('transactions-batch-update', {
|
||||
updated: transactions.map(t => ({
|
||||
id: t.id,
|
||||
@@ -60,7 +60,7 @@ function fireBlur(onBlur, e) {
|
||||
}
|
||||
|
||||
type FieldProps = ComponentProps<typeof View> & {
|
||||
width: number | 'flex';
|
||||
width: CSSProperties['width'];
|
||||
name?: string;
|
||||
truncate?: boolean;
|
||||
contentStyle?: CSSProperties;
|
||||
|
||||
@@ -7,6 +7,7 @@ import React, {
|
||||
useRef,
|
||||
type Dispatch,
|
||||
type ReactElement,
|
||||
type MouseEvent,
|
||||
} from 'react';
|
||||
import { useSelector } from 'react-redux';
|
||||
|
||||
@@ -53,7 +54,7 @@ export default function useSelected<T extends Item>(
|
||||
name: string,
|
||||
items: T[],
|
||||
initialSelectedIds: string[],
|
||||
selectAllFilter?: (T) => boolean,
|
||||
selectAllFilter?: (item: T) => boolean,
|
||||
) {
|
||||
const [state, dispatch] = useReducer(
|
||||
(state: State, action: Actions) => {
|
||||
@@ -312,7 +313,7 @@ type SelectedProviderWithItemsProps<T extends Item> = {
|
||||
initialSelectedIds: string[];
|
||||
fetchAllIds: () => Promise<string[]>;
|
||||
registerDispatch?: (dispatch: Dispatch<Actions>) => void;
|
||||
selectAllFilter?: (T) => boolean;
|
||||
selectAllFilter?: (item: T) => boolean;
|
||||
children: ReactElement;
|
||||
};
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ export default function useSendPlatformRequest<K extends keyof Handlers>(
|
||||
args?: Parameters<Handlers[K]>[0],
|
||||
options?: { catchErrors?: boolean },
|
||||
) {
|
||||
const [data, setData] = useState<unknown>(null);
|
||||
const [data, setData] = useState<Awaited<ReturnType<Handlers[K]>>>(null);
|
||||
const [isLoading, setIsLoading] = useState<boolean | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
@@ -31,7 +31,6 @@ function reconcileFiles(
|
||||
localFiles: Budget[],
|
||||
remoteFiles: RemoteFile[] | null,
|
||||
): File[] {
|
||||
console.log({ localFiles, remoteFiles });
|
||||
const reconciled = new Set();
|
||||
|
||||
const files = localFiles.map((localFile): File & { deleted: boolean } => {
|
||||
|
||||
@@ -12,6 +12,8 @@ import * as db from '../db';
|
||||
import { fromDateRepr } from '../models';
|
||||
import { Schedule as RSchedule } from '../util/rschedule';
|
||||
|
||||
import { SchedulesHandlers } from './types/handlers';
|
||||
|
||||
function takeDates(config) {
|
||||
let schedule = new RSchedule({ rrules: recurConfigToRSchedule(config) });
|
||||
return schedule
|
||||
@@ -392,7 +394,8 @@ export async function findSchedules() {
|
||||
},
|
||||
);
|
||||
|
||||
let finalized = [];
|
||||
const finalized: Awaited<ReturnType<SchedulesHandlers['schedule/discover']>> =
|
||||
[];
|
||||
for (let schedule of schedules) {
|
||||
finalized.push(await findStartDate(schedule));
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { DiscoverScheduleEntity } from '../../../types/models';
|
||||
|
||||
export interface SchedulesHandlers {
|
||||
'schedule/create': (arg: {
|
||||
schedule: {
|
||||
@@ -22,7 +24,7 @@ export interface SchedulesHandlers {
|
||||
|
||||
'schedule/force-run-service': () => Promise<unknown>;
|
||||
|
||||
'schedule/discover': () => Promise<unknown>;
|
||||
'schedule/discover': () => Promise<DiscoverScheduleEntity[]>;
|
||||
|
||||
'schedule/get-upcoming-dates': (arg: {
|
||||
config;
|
||||
|
||||
@@ -31,3 +31,25 @@ export interface ScheduleEntity {
|
||||
_conditions: unknown;
|
||||
_actions: unknown;
|
||||
}
|
||||
|
||||
export type DiscoverScheduleEntity = {
|
||||
id: ScheduleEntity['id'];
|
||||
account: AccountEntity['id'];
|
||||
payee: PayeeEntity['id'];
|
||||
date: ScheduleEntity['_date'];
|
||||
amount: ScheduleEntity['_amount'];
|
||||
_conditions: Array<
|
||||
| { op: 'is'; field: 'account'; value: AccountEntity['id'] }
|
||||
| { op: 'is'; field: 'payee'; value: PayeeEntity['id'] }
|
||||
| {
|
||||
op: 'is' | 'isapprox';
|
||||
field: 'date';
|
||||
value: ScheduleEntity['_date'];
|
||||
}
|
||||
| {
|
||||
op: 'is' | 'isapprox';
|
||||
field: 'amount';
|
||||
value: ScheduleEntity['_amount'];
|
||||
}
|
||||
>;
|
||||
};
|
||||
|
||||
6
upcoming-release-notes/1946.md
Normal file
6
upcoming-release-notes/1946.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
category: Maintenance
|
||||
authors: [muhsinkamil]
|
||||
---
|
||||
|
||||
Refactor DiscoverSchedules component to tsx and enrich types for schedules discover endpoint.
|
||||
Reference in New Issue
Block a user