balibabu commited on
Commit
9cded99
·
1 Parent(s): efaa250

feat: Build the positions of the Switch handle #1739 (#2018)

Browse files

### What problem does this PR solve?

feat: Build the positions of the Switch handle #1739

### Type of change


- [x] New Feature (non-breaking change which adds functionality)

web/src/pages/flow/canvas/node/hooks.ts CHANGED
@@ -1,11 +1,10 @@
1
  import get from 'lodash/get';
2
- import intersectionWith from 'lodash/intersectionWith';
3
- import isEqual from 'lodash/isEqual';
4
  import pick from 'lodash/pick';
5
  import { useEffect, useMemo, useState } from 'react';
6
  import { useUpdateNodeInternals } from 'reactflow';
 
7
  import { IPosition, NodeData } from '../../interface';
8
- import { buildNewPositionMap } from '../../utils';
9
 
10
  export const useBuildCategorizeHandlePositions = ({
11
  data,
@@ -14,40 +13,41 @@ export const useBuildCategorizeHandlePositions = ({
14
  id: string;
15
  data: NodeData;
16
  }) => {
 
17
  const updateNodeInternals = useUpdateNodeInternals();
18
  const [positionMap, setPositionMap] = useState<Record<string, IPosition>>({});
19
- const categoryData = useMemo(
20
- () => get(data, 'form.category_description') ?? {},
21
- [data],
22
- );
 
 
 
 
 
23
 
24
  const positions = useMemo(() => {
25
  return Object.keys(categoryData)
26
- .map((x) => {
27
  const position = positionMap[x];
28
- return { text: x, ...position };
 
 
 
 
29
  })
30
  .filter((x) => typeof x?.right === 'number');
31
- }, [categoryData, positionMap]);
32
 
33
  useEffect(() => {
34
  // Cache used coordinates
35
  setPositionMap((state) => {
36
- // index in use
37
- const indexesInUse = Object.values(state).map((x) => x.idx);
38
  const categoryDataKeys = Object.keys(categoryData);
39
  const stateKeys = Object.keys(state);
40
- if (!isEqual(categoryDataKeys.sort(), stateKeys.sort())) {
41
- const intersectionKeys = intersectionWith(
42
- stateKeys,
43
  categoryDataKeys,
44
- (categoryDataKey, postionMapKey) => categoryDataKey === postionMapKey,
45
- );
46
- const newPositionMap = buildNewPositionMap(
47
- categoryDataKeys.filter(
48
- (x) => !intersectionKeys.some((y) => y === x),
49
- ),
50
- indexesInUse,
51
  );
52
 
53
  const nextPositionMap = {
@@ -68,10 +68,30 @@ export const useBuildCategorizeHandlePositions = ({
68
  return { positions };
69
  };
70
 
71
- export const useBuildSwitchHandlePositions = ({
72
- data,
73
- id,
74
- }: {
75
- id: string;
76
- data: NodeData;
77
- }) => {};
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import get from 'lodash/get';
 
 
2
  import pick from 'lodash/pick';
3
  import { useEffect, useMemo, useState } from 'react';
4
  import { useUpdateNodeInternals } from 'reactflow';
5
+ import { Operator } from '../../constant';
6
  import { IPosition, NodeData } from '../../interface';
7
+ import { buildNewPositionMap, isKeysEqual } from '../../utils';
8
 
9
  export const useBuildCategorizeHandlePositions = ({
10
  data,
 
13
  id: string;
14
  data: NodeData;
15
  }) => {
16
+ const operatorName = data.label as Operator;
17
  const updateNodeInternals = useUpdateNodeInternals();
18
  const [positionMap, setPositionMap] = useState<Record<string, IPosition>>({});
19
+
20
+ const categoryData = useMemo(() => {
21
+ if (operatorName === Operator.Categorize) {
22
+ return get(data, `form.category_description`, {});
23
+ } else if (operatorName === Operator.Switch) {
24
+ return get(data, 'form.conditions', []);
25
+ }
26
+ return {};
27
+ }, [data, operatorName]);
28
 
29
  const positions = useMemo(() => {
30
  return Object.keys(categoryData)
31
+ .map((x, idx) => {
32
  const position = positionMap[x];
33
+ let text = x;
34
+ if (operatorName === Operator.Switch) {
35
+ text = `Item ${idx + 1}`;
36
+ }
37
+ return { text, ...position };
38
  })
39
  .filter((x) => typeof x?.right === 'number');
40
+ }, [categoryData, positionMap, operatorName]);
41
 
42
  useEffect(() => {
43
  // Cache used coordinates
44
  setPositionMap((state) => {
 
 
45
  const categoryDataKeys = Object.keys(categoryData);
46
  const stateKeys = Object.keys(state);
47
+ if (!isKeysEqual(categoryDataKeys, stateKeys)) {
48
+ const { newPositionMap, intersectionKeys } = buildNewPositionMap(
 
49
  categoryDataKeys,
50
+ state,
 
 
 
 
 
 
51
  );
52
 
53
  const nextPositionMap = {
 
68
  return { positions };
69
  };
70
 
71
+ // export const useBuildSwitchHandlePositions = ({
72
+ // data,
73
+ // id,
74
+ // }: {
75
+ // id: string;
76
+ // data: NodeData;
77
+ // }) => {
78
+ // const [positionMap, setPositionMap] = useState<Record<string, IPosition>>({});
79
+ // const conditions = useMemo(() => get(data, 'form.conditions', []), [data]);
80
+ // const updateNodeInternals = useUpdateNodeInternals();
81
+
82
+ // const positions = useMemo(() => {
83
+ // return conditions
84
+ // .map((x, idx) => {
85
+ // const text = `Item ${idx}`;
86
+ // const position = positionMap[text];
87
+ // return { text: text, ...position };
88
+ // })
89
+ // .filter((x) => typeof x?.right === 'number');
90
+ // }, [conditions, positionMap]);
91
+
92
+ // useEffect(() => {
93
+ // updateNodeInternals(id);
94
+ // }, [id, updateNodeInternals, positionMap]);
95
+
96
+ // return { positions };
97
+ // };
web/src/pages/flow/constant.tsx CHANGED
@@ -87,7 +87,19 @@ export const operatorIconMap = {
87
  [Operator.Switch]: SwitchIcon,
88
  };
89
 
90
- export const operatorMap = {
 
 
 
 
 
 
 
 
 
 
 
 
91
  [Operator.Retrieval]: {
92
  backgroundColor: '#cad6e0',
93
  color: '#385974',
@@ -388,7 +400,7 @@ export const initialExeSqlValues = {
388
  top_n: 30,
389
  };
390
 
391
- export const initialSwitchValues = { conditions: [{}] };
392
 
393
  export const CategorizeAnchorPointPositions = [
394
  { top: 1, right: 34 },
 
87
  [Operator.Switch]: SwitchIcon,
88
  };
89
 
90
+ export const operatorMap: Record<
91
+ Operator,
92
+ {
93
+ backgroundColor?: string;
94
+ color?: string;
95
+ width?: number;
96
+ height?: number;
97
+ fontSize?: number;
98
+ iconFontSize?: number;
99
+ iconWidth?: number;
100
+ moreIconColor?: number;
101
+ }
102
+ > = {
103
  [Operator.Retrieval]: {
104
  backgroundColor: '#cad6e0',
105
  color: '#385974',
 
400
  top_n: 30,
401
  };
402
 
403
+ export const initialSwitchValues = { conditions: [] };
404
 
405
  export const CategorizeAnchorPointPositions = [
406
  { top: 1, right: 34 },
web/src/pages/flow/interface.ts CHANGED
@@ -64,11 +64,34 @@ export interface IRelevantForm extends IGenerateForm {
64
  no: string;
65
  }
66
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67
  export type NodeData = {
68
  label: string; // operator type
69
  name: string; // operator name
70
  color: string;
71
- form: IBeginForm | IRetrievalForm | IGenerateForm | ICategorizeForm;
 
 
 
 
 
72
  };
73
 
74
  export type IPosition = { top: number; right: number; idx: number };
 
64
  no: string;
65
  }
66
 
67
+ interface Condition {
68
+ items: Item[];
69
+ logical_operator: string;
70
+ to: string;
71
+ }
72
+
73
+ interface Item {
74
+ cpn_id: string;
75
+ operator: string;
76
+ value: string;
77
+ }
78
+
79
+ export interface ISwitchForm {
80
+ conditions: Condition[];
81
+ end_cpn_id: string;
82
+ no: string;
83
+ }
84
+
85
  export type NodeData = {
86
  label: string; // operator type
87
  name: string; // operator name
88
  color: string;
89
+ form:
90
+ | IBeginForm
91
+ | IRetrievalForm
92
+ | IGenerateForm
93
+ | ICategorizeForm
94
+ | ISwitchForm;
95
  };
96
 
97
  export type IPosition = { top: number; right: number; idx: number };
web/src/pages/flow/store.ts CHANGED
@@ -184,6 +184,14 @@ const useGraphStore = create<RFState>()(
184
  'to',
185
  ]);
186
  break;
 
 
 
 
 
 
 
 
187
  default:
188
  break;
189
  }
 
184
  'to',
185
  ]);
186
  break;
187
+ // case Operator.Switch:
188
+ // if (sourceHandle)
189
+ // updateNodeForm(source, target, [
190
+ // 'conditions',
191
+ // sourceHandle,
192
+ // 'to',
193
+ // ]);
194
+ // break;
195
  default:
196
  break;
197
  }
web/src/pages/flow/utils.ts CHANGED
@@ -1,7 +1,7 @@
1
  import { DSLComponents } from '@/interfaces/database/flow';
2
  import { removeUselessFieldsFromValues } from '@/utils/form';
3
  import { humanId } from 'human-id';
4
- import { curry, sample } from 'lodash';
5
  import pipe from 'lodash/fp/pipe';
6
  import isObject from 'lodash/isObject';
7
  import { Edge, Node, Position } from 'reactflow';
@@ -172,10 +172,24 @@ export const isEdgeEqual = (previous: Edge, current: Edge) =>
172
  previous.sourceHandle === current.sourceHandle;
173
 
174
  export const buildNewPositionMap = (
175
- categoryDataKeys: string[],
176
- indexesInUse: number[],
177
  ) => {
178
- return categoryDataKeys.reduce<Record<string, IPosition>>((pre, cur) => {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
179
  // take a coordinate
180
  const effectiveIdxes = CategorizeAnchorPointPositions.map(
181
  (x, idx) => idx,
@@ -188,4 +202,10 @@ export const buildNewPositionMap = (
188
 
189
  return pre;
190
  }, {});
 
 
 
 
 
 
191
  };
 
1
  import { DSLComponents } from '@/interfaces/database/flow';
2
  import { removeUselessFieldsFromValues } from '@/utils/form';
3
  import { humanId } from 'human-id';
4
+ import { curry, intersectionWith, isEqual, sample } from 'lodash';
5
  import pipe from 'lodash/fp/pipe';
6
  import isObject from 'lodash/isObject';
7
  import { Edge, Node, Position } from 'reactflow';
 
172
  previous.sourceHandle === current.sourceHandle;
173
 
174
  export const buildNewPositionMap = (
175
+ currentKeys: string[],
176
+ previousPositionMap: Record<string, IPosition>,
177
  ) => {
178
+ // index in use
179
+ const indexesInUse = Object.values(previousPositionMap).map((x) => x.idx);
180
+ const previousKeys = Object.keys(previousPositionMap);
181
+ const intersectionKeys = intersectionWith(
182
+ previousKeys,
183
+ currentKeys,
184
+ (categoryDataKey, positionMapKey) => categoryDataKey === positionMapKey,
185
+ );
186
+ // difference set
187
+ const currentDifferenceKeys = currentKeys.filter(
188
+ (x) => !intersectionKeys.some((y) => y === x),
189
+ );
190
+ const newPositionMap = currentDifferenceKeys.reduce<
191
+ Record<string, IPosition>
192
+ >((pre, cur) => {
193
  // take a coordinate
194
  const effectiveIdxes = CategorizeAnchorPointPositions.map(
195
  (x, idx) => idx,
 
202
 
203
  return pre;
204
  }, {});
205
+
206
+ return { intersectionKeys, newPositionMap };
207
+ };
208
+
209
+ export const isKeysEqual = (currentKeys: string[], previousKeys: string[]) => {
210
+ return isEqual(currentKeys.sort(), previousKeys.sort());
211
  };