1- import { IconBranch } from '@douyinfe/semi-icons' ;
2- import { Button , Popover , Spin , Switch } from '@douyinfe/semi-ui' ;
3- import { css , cx } from '@emotion/css' ;
1+ import { Spin } from '@douyinfe/semi-ui' ;
42import { useRequest } from 'ahooks' ;
5- import { flatten } from 'lodash-es' ;
6- import { Fragment , useEffect } from 'react' ;
7- import RuleContentSwitcher from '@/share/components/rule-content-switcher' ;
8- import RuleDetail from '@/share/components/rule-detail' ;
3+ import { flatten , groupBy } from 'lodash-es' ;
4+ import { useEffect } from 'react' ;
95import { EVENTs , VIRTUAL_KEY } from '@/share/core/constant' ;
106import notify from '@/share/core/notify' ;
11- import type { Rule } from '@/share/core/types' ;
7+ import type { RuleWithVirtualKey } from '@/share/core/types' ;
128import { getVirtualKey } from '@/share/core/utils' ;
139import Api from '@/share/pages/api' ;
14- import { textEllipsis } from '@/share/pages/styles' ;
15- import QuickEdit from './quick-edit' ;
10+ import GroupItem from './common/group-item' ;
1611
1712const AllRules = ( ) => {
1813 const {
19- data = [ ] ,
14+ data = { } ,
2015 loading,
2116 mutate,
2217 } = useRequest (
23- async ( ) => {
24- const res = await Api . getAllRules ( ) ;
25- return flatten ( Object . values ( res ) )
26- . sort ( ( a , b ) => a . group . localeCompare ( b . group ) )
27- . map ( x => ( { ...x , [ VIRTUAL_KEY ] : getVirtualKey ( x ) } ) ) ;
28- } ,
18+ async ( ) =>
19+ groupBy (
20+ flatten ( Object . values ( await Api . getAllRules ( ) ) ) . map ( x => ( {
21+ ...x ,
22+ [ VIRTUAL_KEY ] : getVirtualKey ( x ) ,
23+ } ) ) ,
24+ 'group' ,
25+ ) ,
2926 {
3027 manual : false ,
3128 } ,
3229 ) ;
3330
3431 useEffect ( ( ) => {
3532 const handleRuleUpdate = ( request : any ) => {
36- const rule : Rule = request . target ;
37- const key = getVirtualKey ( rule ) ;
33+ const key = getVirtualKey ( request . target ) ;
34+ const rule : RuleWithVirtualKey = {
35+ ...request . target ,
36+ [ VIRTUAL_KEY ] : key ,
37+ } ;
3838 mutate ( currentData => {
3939 if ( ! currentData ) {
4040 return ;
4141 }
42- const index = currentData . findIndex ( x => x [ VIRTUAL_KEY ] === key ) ;
43- if ( index === - 1 ) {
44- return currentData ;
42+ const oldGroup = Object . entries ( currentData ) . find ( ( [ _ , value ] ) =>
43+ value . some ( x => x [ VIRTUAL_KEY ] === key ) ,
44+ ) ;
45+ const newData = { ...currentData } ;
46+ if ( ! oldGroup ) {
47+ // new
48+ newData [ rule . group ] = [ ...( currentData [ rule . group ] || [ ] ) , rule ] ;
49+ return newData ;
50+ }
51+ if ( oldGroup [ 0 ] !== rule . group ) {
52+ // group changed
53+ newData [ oldGroup [ 0 ] ] = oldGroup [ 1 ] . filter (
54+ x => x [ VIRTUAL_KEY ] !== key ,
55+ ) ;
56+ newData [ rule . group ] = [ ...( currentData [ rule . group ] || [ ] ) , rule ] ;
57+ return newData ;
58+ } else {
59+ // group not change
60+ const index = oldGroup [ 1 ] . findIndex ( x => x [ VIRTUAL_KEY ] === key ) ;
61+ newData [ oldGroup [ 0 ] ] = [ ...oldGroup [ 1 ] ] ;
62+ newData [ oldGroup [ 0 ] ] [ index ] = rule ;
63+ return newData ;
4564 }
46- const result = [ ...currentData ] ;
47- result . splice ( index , 1 , {
48- ...rule ,
49- [ VIRTUAL_KEY ] : key ,
50- } ) ;
51- return result ;
5265 } ) ;
5366 } ;
5467
@@ -59,65 +72,12 @@ const AllRules = () => {
5972 } ;
6073 } , [ ] ) ;
6174
62- if ( data . length === 0 && ! loading ) {
63- return null ;
64- }
65-
66- const renderedGroup = new Set < string > ( ) ;
67-
6875 return (
6976 < Spin spinning = { loading } >
70- < div className = "item-block" >
71- { data . map ( item => {
72- const itemDOM = (
73- < div className = "item" key = { item [ VIRTUAL_KEY ] } >
74- < Switch
75- size = "small"
76- checked = { item . enable }
77- onChange = { checked =>
78- Api . saveRule ( {
79- ...item ,
80- enable : checked ,
81- } )
82- }
83- />
84- < Popover
85- showArrow
86- position = "top"
87- content = { < RuleDetail rule = { item } size = "small" /> }
88- style = { { maxWidth : '300px' } }
89- >
90- < div className = { cx ( textEllipsis , 'name' ) } > { item . name } </ div >
91- </ Popover >
92- < div className = "actions" >
93- < QuickEdit rule = { item } />
94- < RuleContentSwitcher
95- rule = { item }
96- type = { item . ruleType }
97- size = "small"
98- add = { false }
99- >
100- < Button
101- theme = "borderless"
102- type = "tertiary"
103- size = "small"
104- icon = { < IconBranch /> }
105- />
106- </ RuleContentSwitcher >
107- </ div >
108- </ div >
109- ) ;
110-
111- if ( renderedGroup . has ( item . group ) ) {
112- return itemDOM ;
113- }
114- return (
115- < Fragment key = { item . group } >
116- < div className = "title" > { item . group } </ div >
117- { itemDOM }
118- </ Fragment >
119- ) ;
120- } ) }
77+ < div className = "main-list" >
78+ { Object . entries ( data ) . map ( ( [ group , rules ] ) => (
79+ < GroupItem key = { group } group = { group } rules = { rules } hasToggle />
80+ ) ) }
12181 </ div >
12282 </ Spin >
12383 ) ;
0 commit comments