Skip to content

Commit

Permalink
Convert SavedFilters to Typescript (#2320)
Browse files Browse the repository at this point in the history
* move saved filters

* MenuButton

* fixes

* update

* FiltersStack

* notes

* merge fixes

* review fixes

* error catch
  • Loading branch information
carkom authored Feb 13, 2024
1 parent 08cbdab commit 2a0f833
Show file tree
Hide file tree
Showing 9 changed files with 447 additions and 347 deletions.
2 changes: 1 addition & 1 deletion packages/desktop-client/src/components/accounts/Header.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import { Search } from '../common/Search';
import { Stack } from '../common/Stack';
import { View } from '../common/View';
import { FilterButton } from '../filters/FiltersMenu';
import { FiltersStack } from '../filters/SavedFilters';
import { FiltersStack } from '../filters/FiltersStack';
import { KeyHandlers } from '../KeyHandlers';
import { NotesButton } from '../NotesButton';
import { SelectedTransactionsButton } from '../transactions/SelectedTransactions';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import { type RuleConditionEntity } from 'loot-core/src/types/models';

import { View } from '../common/View';

import { CondOpMenu } from './CondOpMenu';
import { FilterExpression } from './FilterExpression';
import { CondOpMenu } from './SavedFilters';

type AppliedFiltersProps = {
filters: RuleConditionEntity[];
Expand All @@ -15,7 +15,7 @@ type AppliedFiltersProps = {
) => RuleConditionEntity;
onDelete: (filter: RuleConditionEntity) => void;
conditionsOp: string;
onCondOpChange: () => void;
onCondOpChange: (value: string, filters: RuleConditionEntity[]) => void;
};

export function AppliedFilters({
Expand Down
37 changes: 37 additions & 0 deletions packages/desktop-client/src/components/filters/CondOpMenu.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import React from 'react';

import { type RuleConditionEntity } from 'loot-core/types/models';

import { theme } from '../../style';
import { Text } from '../common/Text';
import { View } from '../common/View';
import { FieldSelect } from '../modals/EditRule';

export function CondOpMenu({
conditionsOp,
onCondOpChange,
filters,
}: {
conditionsOp: string;
onCondOpChange: (value: string, filters: RuleConditionEntity[]) => void;
filters: RuleConditionEntity[];
}) {
return filters.length > 1 ? (
<Text style={{ color: theme.pageText, marginTop: 11, marginRight: 5 }}>
<FieldSelect
style={{ display: 'inline-flex' }}
fields={[
['and', 'all'],
['or', 'any'],
]}
value={conditionsOp}
onChange={(name: string, value: string) =>
onCondOpChange(value, filters)
}
/>
of:
</Text>
) : (
<View />
);
}
54 changes: 54 additions & 0 deletions packages/desktop-client/src/components/filters/FilterMenu.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import React from 'react';

import { Menu } from '../common/Menu';
import { MenuTooltip } from '../common/MenuTooltip';

import { type SavedFilter } from './SavedFilterMenuButton';

export function FilterMenu({
onClose,
filterId,
onFilterMenuSelect,
}: {
onClose: () => void;
filterId: SavedFilter;
onFilterMenuSelect: (item: string) => void;
}) {
return (
<MenuTooltip width={200} onClose={onClose}>
<Menu
onMenuSelect={item => {
onFilterMenuSelect(item);
}}
items={
!filterId.id
? [
{ name: 'save-filter', text: 'Save new filter' },
{ name: 'clear-filter', text: 'Clear all conditions' },
]
: filterId.id !== null && filterId.status === 'saved'
? [
{ name: 'rename-filter', text: 'Rename' },
{ name: 'delete-filter', text: 'Delete' },
Menu.line,
{
name: 'save-filter',
text: 'Save new filter',
disabled: true,
},
{ name: 'clear-filter', text: 'Clear all conditions' },
]
: [
{ name: 'rename-filter', text: 'Rename' },
{ name: 'update-filter', text: 'Update condtions' },
{ name: 'reload-filter', text: 'Revert changes' },
{ name: 'delete-filter', text: 'Delete' },
Menu.line,
{ name: 'save-filter', text: 'Save new filter' },
{ name: 'clear-filter', text: 'Clear all conditions' },
]
}
/>
</MenuTooltip>
);
}
65 changes: 65 additions & 0 deletions packages/desktop-client/src/components/filters/FiltersStack.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import React from 'react';

import { type RuleConditionEntity } from 'loot-core/types/models/rule';

import { Stack } from '../common/Stack';
import { View } from '../common/View';

import { AppliedFilters } from './AppliedFilters';
import {
type SavedFilter,
SavedFilterMenuButton,
} from './SavedFilterMenuButton';

export function FiltersStack({
filters,
conditionsOp,
onUpdateFilter,
onDeleteFilter,
onClearFilters,
onReloadSavedFilter,
filterId,
filtersList,
onCondOpChange,
}: {
filters: RuleConditionEntity[];
conditionsOp: string;
onUpdateFilter: (
filter: RuleConditionEntity,
newFilter: RuleConditionEntity,
) => RuleConditionEntity;
onDeleteFilter: (filter: RuleConditionEntity) => void;
onClearFilters: () => void;
onReloadSavedFilter: (savedFilter: SavedFilter, value?: string) => void;
filterId: SavedFilter;
filtersList: RuleConditionEntity[];
onCondOpChange: () => void;
}) {
return (
<View>
<Stack
spacing={2}
direction="row"
justify="flex-start"
align="flex-start"
>
<AppliedFilters
filters={filters}
conditionsOp={conditionsOp}
onCondOpChange={onCondOpChange}
onUpdate={onUpdateFilter}
onDelete={onDeleteFilter}
/>
<View style={{ flex: 1 }} />
<SavedFilterMenuButton
filters={filters}
conditionsOp={conditionsOp}
filterId={filterId}
onClearFilters={onClearFilters}
onReloadSavedFilter={onReloadSavedFilter}
filtersList={filtersList}
/>
</Stack>
</View>
);
}
79 changes: 79 additions & 0 deletions packages/desktop-client/src/components/filters/NameFilter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import React, { useRef, useEffect } from 'react';

import { theme } from '../../style';
import { Button } from '../common/Button';
import { Input } from '../common/Input';
import { MenuTooltip } from '../common/MenuTooltip';
import { Stack } from '../common/Stack';
import { Text } from '../common/Text';
import { FormField, FormLabel } from '../forms';

export function NameFilter({
onClose,
menuItem,
name,
setName,
adding,
onAddUpdate,
err,
}: {
onClose: () => void;
menuItem: string;
name: string;
setName: (item: string) => void;
adding: boolean;
onAddUpdate: () => void;
err: string | null;
}) {
const inputRef = useRef<HTMLInputElement>(null);

useEffect(() => {
if (inputRef.current) {
inputRef.current.focus();
}
}, []);

return (
<MenuTooltip width={325} onClose={onClose}>
{menuItem !== 'update-filter' && (
<form>
<Stack
direction="row"
justify="flex-end"
align="center"
style={{ padding: 10 }}
>
<FormField style={{ flex: 1 }}>
<FormLabel
title="Filter Name"
htmlFor="name-field"
style={{ userSelect: 'none' }}
/>
<Input
id="name-field"
inputRef={inputRef}
defaultValue={name || ''}
onUpdate={setName}
/>
</FormField>
<Button
type="primary"
style={{ marginTop: 18 }}
onClick={e => {
e.preventDefault();
onAddUpdate();
}}
>
{adding ? 'Add' : 'Update'}
</Button>
</Stack>
</form>
)}
{err && (
<Stack direction="row" align="center" style={{ padding: 10 }}>
<Text style={{ color: theme.errorText }}>{err}</Text>
</Stack>
)}
</MenuTooltip>
);
}
Loading

0 comments on commit 2a0f833

Please sign in to comment.