Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
A
actual-vt-capstone
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Container Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
danieljk
actual-vt-capstone
Commits
550ad931
Unverified
Commit
550ad931
authored
2 years ago
by
Jed Fox
Committed by
GitHub
2 years ago
Browse files
Options
Downloads
Patches
Plain Diff
Add support for filtering the rules list (#475)
parent
799f123e
No related branches found
Branches containing commit
No related tags found
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
packages/desktop-client/src/components/ManageRules.js
+189
-79
189 additions, 79 deletions
packages/desktop-client/src/components/ManageRules.js
with
189 additions
and
79 deletions
packages/desktop-client/src/components/ManageRules.js
+
189
−
79
View file @
550ad931
import
React
,
{
useState
,
useEffect
,
useRef
,
useCallback
}
from
'
react
'
;
import
React
,
{
useState
,
useEffect
,
useRef
,
useCallback
,
useMemo
}
from
'
react
'
;
import
{
useDispatch
,
useSelector
}
from
'
react-redux
'
;
import
{
format
as
formatDate
,
parseISO
}
from
'
date-fns
'
;
...
...
@@ -20,7 +26,8 @@ import {
Text
,
Button
,
Stack
,
ExternalLink
ExternalLink
,
Input
}
from
'
loot-design/src/components/common
'
;
import
{
SelectCell
,
...
...
@@ -222,6 +229,14 @@ export function ConditionExpression({
);
}
function
describeSchedule
(
schedule
,
payee
)
{
if
(
payee
)
{
return
`
${
payee
.
name
}
(
${
schedule
.
next_date
}
)`
;
}
else
{
return
`Next:
${
schedule
.
next_date
}
`
;
}
}
function
ScheduleValue
({
value
})
{
let
payees
=
useSelector
(
state
=>
state
.
queries
.
payees
);
let
byId
=
getPayeesById
(
payees
);
...
...
@@ -232,12 +247,7 @@ function ScheduleValue({ value }) {
value
=
{
value
}
field
=
"
rule
"
data
=
{
schedules
}
describe
=
{
s
=>
{
let
payeeId
=
s
.
_payee
;
return
byId
[
payeeId
]
?
`
${
byId
[
payeeId
].
name
}
(
${
s
.
next_date
}
)`
:
`Next:
${
s
.
next_date
}
`
;
}}
describe
=
{
schedule
=>
describeSchedule
(
schedule
,
byId
[
schedule
.
_payee
])}
/
>
);
}
...
...
@@ -495,15 +505,80 @@ function RulesList({
);
}
export
default
function
ManageRules
({
isModal
,
payeeId
,
setLoading
=
()
=>
{}
})
{
function
mapValue
(
field
,
value
,
{
payees
,
categories
,
accounts
})
{
if
(
!
value
)
return
''
;
if
(
field
===
'
payee
'
)
{
return
payees
.
find
(
p
=>
p
.
id
===
value
).
name
;
}
else
if
(
field
===
'
category
'
)
{
return
categories
.
find
(
c
=>
c
.
id
===
value
).
name
;
}
else
if
(
field
===
'
account
'
)
{
return
accounts
.
find
(
a
=>
a
.
id
===
value
).
name
;
}
else
{
return
value
;
}
}
function
ruleToString
(
rule
,
data
)
{
let
conditions
=
rule
.
conditions
.
flatMap
(
cond
=>
[
mapField
(
cond
.
field
),
friendlyOp
(
cond
.
op
),
cond
.
op
===
'
oneOf
'
?
cond
.
value
.
map
(
v
=>
mapValue
(
cond
.
field
,
v
,
data
)).
join
(
'
,
'
)
:
mapValue
(
cond
.
field
,
cond
.
value
,
data
)
]);
let
actions
=
rule
.
actions
.
flatMap
(
action
=>
{
if
(
action
.
op
===
'
set
'
)
{
return
[
friendlyOp
(
action
.
op
),
mapField
(
action
.
field
),
'
to
'
,
mapValue
(
action
.
field
,
action
.
value
,
data
)
];
}
else
if
(
action
.
op
===
'
link-schedule
'
)
{
let
schedule
=
data
.
schedules
.
find
(
s
=>
s
.
id
===
action
.
value
);
return
[
friendlyOp
(
action
.
op
),
describeSchedule
(
schedule
,
data
.
payees
.
find
(
p
=>
p
.
id
===
schedule
.
_payee
)
)
];
}
else
{
return
[];
}
});
return
(
(
rule
.
stage
||
''
)
+
'
'
+
conditions
.
join
(
'
'
)
+
'
'
+
actions
.
join
(
'
'
)
);
}
function
ManageRulesContent
({
isModal
,
payeeId
,
setLoading
})
{
let
[
allRules
,
setAllRules
]
=
useState
(
null
);
let
[
rules
,
setRules
]
=
useState
(
null
);
let
[
filter
,
setFilter
]
=
useState
(
''
);
let
dispatch
=
useDispatch
();
let
navigator
=
useTableNavigator
(
rules
,
[
'
select
'
,
'
edit
'
]);
let
{
data
:
schedules
}
=
SchedulesQuery
.
useQuery
();
let
filterData
=
useSelector
(
state
=>
({
payees
:
state
.
queries
.
payees
,
categories
:
state
.
queries
.
categories
.
list
,
accounts
:
state
.
queries
.
accounts
,
schedules
}));
let
filteredRules
=
useMemo
(
()
=>
filter
===
''
||
!
rules
?
rules
:
rules
.
filter
(
rule
=>
ruleToString
(
rule
,
filterData
)
.
toLowerCase
()
.
includes
(
filter
.
toLowerCase
())
),
[
rules
,
filter
,
filterData
]
);
let
selectedInst
=
useSelected
(
'
manage-rules
'
,
allRules
,
[]);
let
[
hoveredRule
,
setHoveredRule
]
=
useState
(
null
);
let
tableRef
=
useRef
(
null
);
...
...
@@ -635,78 +710,113 @@ export default function ManageRules({
return
null
;
}
let
actions
=
(
<
View
style
=
{{
flexDirection
:
'
row
'
,
alignItems
:
'
center
'
,
padding
:
isModal
?
'
13px 15px
'
:
'
0 0 15px
'
,
borderTop
:
'
1px solid
'
+
colors
.
border
}}
>
<
View
style
=
{{
color
:
colors
.
n4
,
flexDirection
:
'
row
'
,
alignItems
:
'
center
'
,
width
:
'
50%
'
}}
>
<
Text
>
Rules
are
always
run
in
the
order
that
you
see
them
.{
'
'
}
<
ExternalLink
asAnchor
=
{
true
}
href
=
"
https://actualbudget.github.io/docs/Budgeting/rules/
"
style
=
{{
color
:
colors
.
n4
}}
return
(
<
SelectedProvider
instance
=
{
selectedInst
}
>
<
View
style
=
{{
overflow
:
'
hidden
'
}}
>
<
View
style
=
{{
flexDirection
:
'
row
'
,
alignItems
:
'
center
'
,
padding
:
isModal
?
'
0 13px 15px
'
:
'
0 0 15px
'
,
flexShrink
:
0
}}
>
<
View
style
=
{{
color
:
colors
.
n4
,
flexDirection
:
'
row
'
,
alignItems
:
'
center
'
,
width
:
'
50%
'
}}
>
Learn
more
<
/ExternalLink
>
<
/Text
>
<
Text
>
Rules
are
always
run
in
the
order
that
you
see
them
.{
'
'
}
<
ExternalLink
asAnchor
=
{
true
}
href
=
"
https://actualbudget.github.io/docs/Budgeting/rules/
"
style
=
{{
color
:
colors
.
n4
}}
>
Learn
more
<
/ExternalLink
>
<
/Text
>
<
/View
>
<
View
style
=
{{
flex
:
1
}}
/
>
<
Input
placeholder
=
"
Filter rules...
"
value
=
{
filter
}
onChange
=
{
e
=>
{
setFilter
(
e
.
target
.
value
);
navigator
.
onEdit
(
null
);
}}
style
=
{{
width
:
350
,
borderColor
:
isModal
?
null
:
'
transparent
'
,
backgroundColor
:
isModal
?
null
:
colors
.
n11
,
'
:focus
'
:
isModal
?
null
:
{
backgroundColor
:
'
white
'
,
'
::placeholder
'
:
{
color
:
colors
.
n8
}
}
}}
/
>
<
/View
>
<
View
style
=
{{
flex
:
1
}}
>
<
RulesHeader
/>
<
SimpleTable
ref
=
{
tableRef
}
data
=
{
filteredRules
}
navigator
=
{
navigator
}
loadMore
=
{
loadMore
}
// Hide the last border of the item in the table
style
=
{{
marginBottom
:
-
1
}}
>
<
RulesList
rules
=
{
filteredRules
}
selectedItems
=
{
selectedInst
.
items
}
navigator
=
{
navigator
}
hoveredRule
=
{
hoveredRule
}
onHover
=
{
onHover
}
onEditRule
=
{
onEditRule
}
/
>
<
/SimpleTable
>
<
/View
>
<
View
style
=
{{
paddingBlock
:
15
,
paddingInline
:
isModal
?
13
:
0
,
borderTop
:
isModal
&&
'
1px solid
'
+
colors
.
border
,
flexShrink
:
0
}}
>
<
Stack
direction
=
"
row
"
align
=
"
center
"
justify
=
"
flex-end
"
spacing
=
{
2
}
>
{
selectedInst
.
items
.
size
>
0
&&
(
<
Button
onClick
=
{
onDeleteSelected
}
>
Delete
{
selectedInst
.
items
.
size
}
rules
<
/Button
>
)}
<
Button
primary
onClick
=
{
onCreateRule
}
>
Create
new
rule
<
/Button
>
<
/Stack
>
<
/View
>
<
/View
>
<
View
style
=
{{
flex
:
1
}}
/
>
<
Stack
direction
=
"
row
"
align
=
"
center
"
justify
=
"
flex-end
"
spacing
=
{
2
}
>
{
selectedInst
.
items
.
size
>
0
&&
(
<
Button
onClick
=
{
onDeleteSelected
}
>
Delete
{
selectedInst
.
items
.
size
}
rules
<
/Button
>
)}
<
Button
primary
onClick
=
{
onCreateRule
}
>
Create
new
rule
<
/Button
>
<
/Stack
>
<
/View
>
<
/SelectedProvider
>
);
}
export
default
function
ManageRules
({
isModal
,
payeeId
,
setLoading
=
()
=>
{}
})
{
return
(
<
SchedulesQuery
.
Provider
>
<
SelectedProvider
instance
=
{
selectedInst
}
>
<
View
style
=
{{
overflow
:
'
hidden
'
}}
>
{
!
isModal
&&
actions
}
<
View
style
=
{{
flex
:
1
}}
>
<
RulesHeader
/>
<
SimpleTable
ref
=
{
tableRef
}
data
=
{
rules
}
navigator
=
{
navigator
}
loadMore
=
{
loadMore
}
// Hide the last border of the item in the table
style
=
{{
marginBottom
:
-
1
}}
>
<
RulesList
rules
=
{
rules
}
selectedItems
=
{
selectedInst
.
items
}
navigator
=
{
navigator
}
hoveredRule
=
{
hoveredRule
}
onHover
=
{
onHover
}
onEditRule
=
{
onEditRule
}
/
>
<
/SimpleTable
>
<
/View
>
{
isModal
&&
actions
}
<
/View
>
<
/SelectedProvider
>
<
ManageRulesContent
isModal
=
{
isModal
}
payeeId
=
{
payeeId
}
setLoading
=
{
setLoading
}
/
>
<
/SchedulesQuery.Provider
>
);
}
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment