Commit 1710eef23fb0bb3a7440162a9b838c7723f678e3

Authored by xp.Huang
2 parents 1c479be8 08c5e0f2

Merge branch 'feat/rule-chain-designer' into 'main_dev'

feat: 实现选中部分节点创建规则链

See merge request yunteng/thingskit-front!915
@@ -13,6 +13,9 @@ import { EntryCategoryComponentEnum } from '../enum/category'; @@ -13,6 +13,9 @@ import { EntryCategoryComponentEnum } from '../enum/category';
13 13
14 const ignoreNodeKeys: string[] = [EntryCategoryComponentEnum.INPUT]; 14 const ignoreNodeKeys: string[] = [EntryCategoryComponentEnum.INPUT];
15 15
  16 +export const SOURCE_HANDLE = '__handle-right';
  17 +export const TARGET_HANDLE = '__handle-left';
  18 +
16 export function useBasicDataTransform() { 19 export function useBasicDataTransform() {
17 const nodeConfigMap = new Map<string, NodeData>(); 20 const nodeConfigMap = new Map<string, NodeData>();
18 21
@@ -21,7 +24,7 @@ export function useBasicDataTransform() { @@ -21,7 +24,7 @@ export function useBasicDataTransform() {
21 const category = allComponents[key as RuleNodeTypeEnum]; 24 const category = allComponents[key as RuleNodeTypeEnum];
22 for (const nodeConfig of category.components) { 25 for (const nodeConfig of category.components) {
23 const { clazz } = nodeConfig; 26 const { clazz } = nodeConfig;
24 - nodeConfigMap.set(clazz, { config: nodeConfig, category: category.category }); 27 + nodeConfigMap.set(clazz, { config: nodeConfig, categoryConfig: category.category });
25 } 28 }
26 } 29 }
27 } 30 }
@@ -49,8 +52,7 @@ export function useBasicDataTransform() { @@ -49,8 +52,7 @@ export function useBasicDataTransform() {
49 const { connections, nodes, firstNodeIndex } = unref(ruleChain); 52 const { connections, nodes, firstNodeIndex } = unref(ruleChain);
50 const indexMap = new Map<number, BasicNodeBindData>(); 53 const indexMap = new Map<number, BasicNodeBindData>();
51 const groupByConnections = new Map<string, string[]>(); 54 const groupByConnections = new Map<string, string[]>();
52 - const SOURCE_HANDLE = '__handle-right';  
53 - const TARGET_HANDLE = '__handle-left'; 55 +
54 const SEPARATOR = ','; 56 const SEPARATOR = ',';
55 const edges: Elements = []; 57 const edges: Elements = [];
56 const { getAddedgesParams } = useAddEdges(); 58 const { getAddedgesParams } = useAddEdges();
@@ -207,6 +209,8 @@ export function useBasicDataTransform() { @@ -207,6 +209,8 @@ export function useBasicDataTransform() {
207 function getNodes(nodesRef: Ref<GraphNode[]> | GraphNode[], removeId: boolean) { 209 function getNodes(nodesRef: Ref<GraphNode[]> | GraphNode[], removeId: boolean) {
208 const nodes: BasicNodeBindData[] = []; 210 const nodes: BasicNodeBindData[] = [];
209 211
  212 + let offsetX = 0;
  213 + let offsetY = 0;
210 for (const node of unref(nodesRef)) { 214 for (const node of unref(nodesRef)) {
211 const nodeData = node.data as NodeData; 215 const nodeData = node.data as NodeData;
212 216
@@ -214,16 +218,31 @@ export function useBasicDataTransform() { @@ -214,16 +218,31 @@ export function useBasicDataTransform() {
214 218
215 const data = nodeData.data; 219 const data = nodeData.data;
216 220
217 - nodes.push(  
218 - Object.assign(  
219 - mergeData(data, nodeData, node),  
220 - nodeData.created && !removeId  
221 - ? ({  
222 - id: { id: node.id, entityType: RuleChainEntityType.RULE_NODE },  
223 - } as BasicNodeBindData)  
224 - : {}  
225 - ) 221 + const resultNode = Object.assign(
  222 + mergeData(data, nodeData, node),
  223 + nodeData.created && !removeId
  224 + ? ({
  225 + id: { id: node.id, entityType: RuleChainEntityType.RULE_NODE },
  226 + } as BasicNodeBindData)
  227 + : {}
226 ); 228 );
  229 +
  230 + if (resultNode.additionalInfo.layoutX < offsetX) offsetX = resultNode.additionalInfo.layoutX;
  231 + if (resultNode.additionalInfo.layoutY < offsetY) offsetY = resultNode.additionalInfo.layoutY;
  232 +
  233 + nodes.push(resultNode);
  234 + }
  235 +
  236 + /**
  237 + * compatible thingsboard rule chain designer.
  238 + * thingsboard rule chain designer does not have negative coordinated.
  239 + */
  240 + if (offsetX < 0 || offsetY < 0) {
  241 + nodes.forEach((node) => {
  242 + const { layoutX = 0, layoutY = 0 } = node.additionalInfo || {};
  243 + node.additionalInfo!.layoutX = layoutX + Math.abs(offsetX);
  244 + node.additionalInfo!.layoutY = layoutY + Math.abs(offsetY);
  245 + });
227 } 246 }
228 247
229 return nodes; 248 return nodes;
@@ -266,9 +285,22 @@ export function useBasicDataTransform() { @@ -266,9 +285,22 @@ export function useBasicDataTransform() {
266 nodes: Ref<GraphNode[]> | GraphNode[] = [], 285 nodes: Ref<GraphNode[]> | GraphNode[] = [],
267 edges: Ref<GraphEdge[]> | GraphEdge[] = [] 286 edges: Ref<GraphEdge[]> | GraphEdge[] = []
268 ) { 287 ) {
  288 + let flag = true;
  289 +
  290 + if (unref(nodes).length <= 1) flag = false;
  291 +
269 const rootNode: GraphNode[] = []; 292 const rootNode: GraphNode[] = [];
270 293
271 - let flag = true; 294 + for (const edge of unref(edges)) {
  295 + if (!unref(nodes).find((node) => node.id === edge.source)) rootNode.push(edge.targetNode);
  296 + }
  297 +
  298 + for (const node of unref(nodes)) {
  299 + if (!unref(edges).some((edge) => edge.target === node.id)) rootNode.push(node);
  300 + }
  301 +
  302 + if (rootNode.length > 1) return { flag: false, firstNode: null };
  303 +
272 for (const node of unref(nodes)) { 304 for (const node of unref(nodes)) {
273 const list = unref(edges).filter( 305 const list = unref(edges).filter(
274 (edge) => edge.source === node.id || edge.target === node.id 306 (edge) => edge.source === node.id || edge.target === node.id
@@ -278,14 +310,6 @@ export function useBasicDataTransform() { @@ -278,14 +310,6 @@ export function useBasicDataTransform() {
278 flag = false; 310 flag = false;
279 break; 311 break;
280 } 312 }
281 -  
282 - if (!list.filter((edge) => edge.target === node.id).length) {  
283 - if (!rootNode.length) rootNode.push(node);  
284 - else {  
285 - flag = false;  
286 - break;  
287 - }  
288 - }  
289 } 313 }
290 314
291 return { flag, firstNode: rootNode[0] || null }; 315 return { flag, firstNode: rootNode[0] || null };
@@ -5,7 +5,7 @@ import { useAddNodes } from './useAddNodes'; @@ -5,7 +5,7 @@ import { useAddNodes } from './useAddNodes';
5 import { buildUUID } from '/@/utils/uuid'; 5 import { buildUUID } from '/@/utils/uuid';
6 import { Ref, toRaw, unref } from 'vue'; 6 import { Ref, toRaw, unref } from 'vue';
7 import { useSaveAndRedo } from './useSaveAndRedo'; 7 import { useSaveAndRedo } from './useSaveAndRedo';
8 -import { isUnDef } from '/@/utils/is'; 8 +import { isNullOrUnDef, isUnDef } from '/@/utils/is';
9 import { useAddEdges } from './useAddEdges'; 9 import { useAddEdges } from './useAddEdges';
10 import { EdgeData } from '../types/node'; 10 import { EdgeData } from '../types/node';
11 import { CreateNodeModal } from '../src/components/CreateNodeModal'; 11 import { CreateNodeModal } from '../src/components/CreateNodeModal';
@@ -13,9 +13,11 @@ import { CreateEdgeModal } from '../src/components/CreateEdgeModal'; @@ -13,9 +13,11 @@ import { CreateEdgeModal } from '../src/components/CreateEdgeModal';
13 import { UpdateNodeDrawer } from '../src/components/UpdateNodeDrawer'; 13 import { UpdateNodeDrawer } from '../src/components/UpdateNodeDrawer';
14 import { UpdateEdgeDrawer } from '../src/components/UpdateEdgeDrawer'; 14 import { UpdateEdgeDrawer } from '../src/components/UpdateEdgeDrawer';
15 import { CreateRuleChainModal } from '../src/components/CreateRuleChainModal'; 15 import { CreateRuleChainModal } from '../src/components/CreateRuleChainModal';
16 -import { useBasicDataTransform } from './useBasicDataTransform'; 16 +import { SOURCE_HANDLE, TARGET_HANDLE, useBasicDataTransform } from './useBasicDataTransform';
17 import { cloneDeep } from 'lodash-es'; 17 import { cloneDeep } from 'lodash-es';
18 import { useNewNode } from './useNewNode'; 18 import { useNewNode } from './useNewNode';
  19 +import { RuleChainDetail } from '../types/ruleNode';
  20 +import { saveRuleChainData, saveRuleChainDetail } from '/@/api/ruleDesigner';
19 21
20 interface HandleContextMenuActionParamsType { 22 interface HandleContextMenuActionParamsType {
21 menuType: RuleContextMenuEnum; 23 menuType: RuleContextMenuEnum;
@@ -47,11 +49,15 @@ export function transformToRuleChain( @@ -47,11 +49,15 @@ export function transformToRuleChain(
47 const outputEdges = unref(edgesRef).filter((edge) => !nodeMap.has(edge.target)); 49 const outputEdges = unref(edgesRef).filter((edge) => !nodeMap.has(edge.target));
48 const outputEdgesId = outputEdges.map((edge) => edge.id); 50 const outputEdgesId = outputEdges.map((edge) => edge.id);
49 51
  52 + const inputEdges = unref(edgesRef).filter((edge) => !nodeMap.has(edge.source));
  53 + const inputEdgesId = inputEdges.map((edge) => edge.id);
  54 +
50 const { getOutputNodeConfig } = useNewNode(); 55 const { getOutputNodeConfig } = useNewNode();
51 const outputNode = outputEdges.map((edge) => { 56 const outputNode = outputEdges.map((edge) => {
52 const id = buildUUID(); 57 const id = buildUUID();
53 const name = (edge.data as EdgeData).data?.type?.join(' / ') || ''; 58 const name = (edge.data as EdgeData).data?.type?.join(' / ') || '';
54 edge.target = id; 59 edge.target = id;
  60 + edge.targetHandle = `${id}${TARGET_HANDLE}`;
55 return getOutputNodeConfig(name, edge.targetNode.position, id); 61 return getOutputNodeConfig(name, edge.targetNode.position, id);
56 }); 62 });
57 63
@@ -61,9 +67,9 @@ export function transformToRuleChain( @@ -61,9 +67,9 @@ export function transformToRuleChain(
61 67
62 const { firstNode } = validateCanCreateRuleChain(nodesRef, edgesRef); 68 const { firstNode } = validateCanCreateRuleChain(nodesRef, edgesRef);
63 69
64 - const firstNodeIndex = nodesRef.findIndex((node) => node.id === firstNode.id); 70 + const firstNodeIndex = nodesRef.findIndex((node) => node.id === firstNode?.id);
65 71
66 - return { connections, nodes, firstNodeIndex, outputEdgesId }; 72 + return { connections, nodes, firstNodeIndex, outputEdgesId, inputEdgesId };
67 } 73 }
68 74
69 export const NODE_WIDTH = 176; 75 export const NODE_WIDTH = 176;
@@ -87,20 +93,13 @@ function getElementsCenter(nodes: Ref<GraphNode[]> | GraphNode[] = []) { @@ -87,20 +93,13 @@ function getElementsCenter(nodes: Ref<GraphNode[]> | GraphNode[] = []) {
87 continue; 93 continue;
88 } 94 }
89 95
90 - if (x < leftTopX!) {  
91 - leftTopX = x;  
92 - if (y < leftTopY!) {  
93 - leftTopY = y;  
94 - }  
95 - continue;  
96 - } 96 + if (x < leftTopX!) leftTopX = x;
97 97
98 - if (x + NODE_WIDTH > rightBottomX!) {  
99 - rightBottomX = x + NODE_WIDTH;  
100 - if (y + NODE_HEIGHT > rightBottomY!) {  
101 - rightBottomY = y + NODE_HEIGHT;  
102 - }  
103 - } 98 + if (y < leftTopY!) leftTopY = y;
  99 +
  100 + if (x + NODE_WIDTH > rightBottomX!) rightBottomX = x + NODE_WIDTH;
  101 +
  102 + if (y + NODE_HEIGHT > rightBottomY!) rightBottomY = y + NODE_HEIGHT;
104 } 103 }
105 104
106 return { 105 return {
@@ -109,6 +108,60 @@ function getElementsCenter(nodes: Ref<GraphNode[]> | GraphNode[] = []) { @@ -109,6 +108,60 @@ function getElementsCenter(nodes: Ref<GraphNode[]> | GraphNode[] = []) {
109 }; 108 };
110 } 109 }
111 110
  111 +function createRuleChainNode({
  112 + originX,
  113 + originY,
  114 + outputEdges,
  115 + inputEdges,
  116 + ruleChainDetail,
  117 +}: {
  118 + originX: number;
  119 + originY: number;
  120 + ruleChainDetail: RuleChainDetail;
  121 + outputEdges: Ref<(GraphEdge | undefined)[]> | (GraphEdge | undefined)[];
  122 + inputEdges: Ref<(GraphEdge | undefined)[]> | (GraphEdge | undefined)[];
  123 +}) {
  124 + const { getRuleChainNodeConfig } = useNewNode();
  125 + const { getAddedgesParams } = useAddEdges();
  126 + const nodeId = buildUUID();
  127 +
  128 + const ruleChainNode = getRuleChainNodeConfig({
  129 + name: ruleChainDetail.name,
  130 + position: { x: originX - NODE_WIDTH / 2, y: originY - NODE_HEIGHT / 2 },
  131 + ruleChainId: ruleChainDetail.id.id,
  132 + id: nodeId,
  133 + });
  134 +
  135 + const newInputEdges = unref(inputEdges).map((edge) =>
  136 + getAddedgesParams(
  137 + {
  138 + source: edge!.source,
  139 + target: nodeId,
  140 + sourceHandle: `${edge?.source}${SOURCE_HANDLE}`,
  141 + targetHandle: `${nodeId}${TARGET_HANDLE}`,
  142 + },
  143 + toRaw(unref(edge!.data as EdgeData).data)
  144 + )
  145 + );
  146 +
  147 + const newOutputEdges = unref(outputEdges).map((edge) =>
  148 + getAddedgesParams(
  149 + {
  150 + source: nodeId,
  151 + target: edge!.target,
  152 + sourceHandle: `${nodeId}${SOURCE_HANDLE}`,
  153 + targetHandle: `${edge?.target}${TARGET_HANDLE}`,
  154 + },
  155 + toRaw(unref(edge!.data as EdgeData).data)
  156 + )
  157 + );
  158 +
  159 + return {
  160 + nodes: [ruleChainNode],
  161 + edges: [...newInputEdges, ...newOutputEdges],
  162 + };
  163 +}
  164 +
112 export function useContextMenuAction() { 165 export function useContextMenuAction() {
113 const copy = (params: HandleContextMenuActionParamsType) => { 166 const copy = (params: HandleContextMenuActionParamsType) => {
114 const { node } = params; 167 const { node } = params;
@@ -248,35 +301,51 @@ export function useContextMenuAction() { @@ -248,35 +301,51 @@ export function useContextMenuAction() {
248 useSaveAndRedoActionType?.handleRedoChange(flowActionType!); 301 useSaveAndRedoActionType?.handleRedoChange(flowActionType!);
249 }; 302 };
250 303
251 - const createRuleChain = async (_params: HandleContextMenuActionParamsType) => {  
252 - // const { useSaveAndRedoActionType, modalActionType, flowActionType } = params;  
253 - // const { createRuleChainModalActionType } = modalActionType;  
254 - // const result = (await unref(createRuleChainModalActionType)?.openCreateRuleChainModal()) as {  
255 - // name: string;  
256 - // additionalInfo: { description: string };  
257 - // };  
258 - // const ruleChainDetail = await saveRuleChainDetail(  
259 - // Object.assign(result, { debugger: false, type: 'CORE' }) as Partial<RuleChainDetail>  
260 - // );  
261 - // const selectedNodes = unref(flowActionType?.getSelectedNodes);  
262 - // const selectedEdges = unref(flowActionType?.getSelectedEdges);  
263 - // const { firstNodeIndex, connections, nodes, outputEdgesId } = transformToRuleChain(  
264 - // selectedNodes,  
265 - // selectedEdges  
266 - // );  
267 - // await saveRuleChainData({  
268 - // firstNodeIndex,  
269 - // connections,  
270 - // nodes,  
271 - // ruleChainId: ruleChainDetail.id,  
272 - // });  
273 - // const outputEdges = outputEdgesId.map((id) => flowActionType?.findEdge(id));  
274 - // console.log(getElementsCenter(unref(selectedNodes)));  
275 - // const { originX, originY } = getElementsCenter(unref(selectedNodes));  
276 - // const {} = useNewNode();  
277 - // flowActionType?.removeNodes(selectedNodes || []);  
278 - // flowActionType?.removeEdges(selectedEdges || []);  
279 - // useSaveAndRedoActionType?.triggerChange(); 304 + const createRuleChain = async (params: HandleContextMenuActionParamsType) => {
  305 + const { useSaveAndRedoActionType, modalActionType, flowActionType } = params;
  306 + const { createRuleChainModalActionType } = modalActionType;
  307 + const result = (await unref(createRuleChainModalActionType)?.openCreateRuleChainModal()) as {
  308 + name: string;
  309 + additionalInfo: { description: string };
  310 + };
  311 +
  312 + const ruleChainDetail = await saveRuleChainDetail(
  313 + Object.assign(result, { debugger: false, type: 'CORE' }) as Partial<RuleChainDetail>
  314 + );
  315 +
  316 + const selectedNodes = unref(flowActionType?.getSelectedNodes);
  317 + const selectedEdges = unref(flowActionType?.getSelectedEdges);
  318 + const { firstNodeIndex, connections, nodes, outputEdgesId, inputEdgesId } =
  319 + transformToRuleChain(selectedNodes, selectedEdges);
  320 +
  321 + await saveRuleChainData({
  322 + firstNodeIndex,
  323 + connections: connections.filter(
  324 + (connection) => !isNullOrUnDef(connection.fromIndex) && !isNullOrUnDef(connection.toIndex)
  325 + ),
  326 + nodes,
  327 + ruleChainId: ruleChainDetail.id,
  328 + });
  329 +
  330 + const outputEdges = outputEdgesId.map((id) => flowActionType?.findEdge(id));
  331 + const inputEdges = inputEdgesId.map((id) => flowActionType?.findEdge(id));
  332 +
  333 + const { originX, originY } = getElementsCenter(unref(selectedNodes));
  334 +
  335 + flowActionType?.removeNodes(selectedNodes || []);
  336 + flowActionType?.removeEdges(selectedEdges || []);
  337 +
  338 + const { nodes: newNode, edges: newEdges } = createRuleChainNode({
  339 + originX,
  340 + originY,
  341 + outputEdges,
  342 + inputEdges,
  343 + ruleChainDetail,
  344 + });
  345 +
  346 + flowActionType?.addNodes(newNode);
  347 + flowActionType?.addEdges(newEdges);
  348 + useSaveAndRedoActionType?.triggerChange();
280 }; 349 };
281 350
282 const handleContextMenuAction = (params: HandleContextMenuActionParamsType) => { 351 const handleContextMenuAction = (params: HandleContextMenuActionParamsType) => {
@@ -40,13 +40,23 @@ export function useNewNode() { @@ -40,13 +40,23 @@ export function useNewNode() {
40 return newNode; 40 return newNode;
41 }; 41 };
42 42
43 - const getRuleChainNodeConfig = (name: string, position: XYPosition, id?: string) => { 43 + const getRuleChainNodeConfig = ({
  44 + name,
  45 + position,
  46 + ruleChainId,
  47 + id,
  48 + }: {
  49 + name: string;
  50 + position: XYPosition;
  51 + ruleChainId: string;
  52 + id?: string;
  53 + }) => {
44 const { getAddNodesParams } = useAddNodes(); 54 const { getAddNodesParams } = useAddNodes();
45 const newNode = getAddNodesParams( 55 const newNode = getAddNodesParams(
46 position, 56 position,
47 { 57 {
48 ...new RuleChainConfig(), 58 ...new RuleChainConfig(),
49 - data: { name }, 59 + data: { name, configuration: { ruleChainId } },
50 }, 60 },
51 { 61 {
52 id, 62 id,
@@ -65,6 +65,7 @@ export function useRuleFlow(options: UseRuleFlowOptionsType) { @@ -65,6 +65,7 @@ export function useRuleFlow(options: UseRuleFlowOptionsType) {
65 minZoom: 1, 65 minZoom: 1,
66 panOnScroll: true, 66 panOnScroll: true,
67 selectionMode: SelectionMode.Partial, 67 selectionMode: SelectionMode.Partial,
  68 +
68 nodeTypes: { 69 nodeTypes: {
69 [NodeTypeEnum.CUSTOM]: markRaw(BasicNode) as NodeComponent, 70 [NodeTypeEnum.CUSTOM]: markRaw(BasicNode) as NodeComponent,
70 }, 71 },
@@ -79,14 +80,16 @@ export function useRuleFlow(options: UseRuleFlowOptionsType) { @@ -79,14 +80,16 @@ export function useRuleFlow(options: UseRuleFlowOptionsType) {
79 y: 0, 80 y: 0,
80 }, 81 },
81 isValidConnection(connection, elements) { 82 isValidConnection(connection, elements) {
  83 + if (!elements.targetNode || !elements.sourceNode) return false;
  84 +
82 const validateList = [validateInputAndOutput]; 85 const validateList = [validateInputAndOutput];
83 const targetData = elements.targetNode.data as NodeData; 86 const targetData = elements.targetNode.data as NodeData;
84 87
85 if ( 88 if (
86 - targetData.category?.validateConnection &&  
87 - isFunction(targetData.category.validateConnection) 89 + targetData.categoryConfig?.validateConnection &&
  90 + isFunction(targetData.categoryConfig.validateConnection)
88 ) 91 )
89 - validateList.push(targetData.category?.validateConnection); 92 + validateList.push(targetData.categoryConfig?.validateConnection);
90 93
91 if (targetData.config?.validateConnection && isFunction(targetData.config.validateConnection)) 94 if (targetData.config?.validateConnection && isFunction(targetData.config.validateConnection))
92 validateList.push(targetData.config.validateConnection); 95 validateList.push(targetData.config.validateConnection);
@@ -47,7 +47,6 @@ @@ -47,7 +47,6 @@
47 47
48 const setValue: CreateModalDefineExposeType['setFieldsValue'] = (value) => { 48 const setValue: CreateModalDefineExposeType['setFieldsValue'] = (value) => {
49 resetFields(); 49 resetFields();
50 - console.log(value);  
51 setFieldsValue({ 50 setFieldsValue({
52 ...value, 51 ...value,
53 ...(value?.[RelatedDeviceAttributeFieldsEnum.DEVICE_RELATIONS_QUERY] || {}), 52 ...(value?.[RelatedDeviceAttributeFieldsEnum.DEVICE_RELATIONS_QUERY] || {}),
@@ -14,6 +14,7 @@ export const RuleChainConfig: NodeItemConfigType = { @@ -14,6 +14,7 @@ export const RuleChainConfig: NodeItemConfigType = {
14 clazz: 'org.thingsboard.rule.engine.flow.TbRuleChainInputNode', 14 clazz: 'org.thingsboard.rule.engine.flow.TbRuleChainInputNode',
15 categoryType: RuleNodeTypeEnum.FLOW, 15 categoryType: RuleNodeTypeEnum.FLOW,
16 name: 'rule chain', 16 name: 'rule chain',
  17 + // backgroundColor: '#d6c4f1',
17 configurationDescriptor: { 18 configurationDescriptor: {
18 nodeDefinition: { 19 nodeDefinition: {
19 details: 20 details:
@@ -14,7 +14,7 @@ @@ -14,7 +14,7 @@
14 const handleClick = () => { 14 const handleClick = () => {
15 const { data } = props.nodeProps?.data || ({} as NodeData); 15 const { data } = props.nodeProps?.data || ({} as NodeData);
16 const { configuration } = (data || {}) as { configuration: Record<'ruleChainId', string> }; 16 const { configuration } = (data || {}) as { configuration: Record<'ruleChainId', string> };
17 - if (configuration.ruleChainId) { 17 + if (configuration?.ruleChainId) {
18 ROUTER.push(`/rule/chain/${configuration.ruleChainId}`); 18 ROUTER.push(`/rule/chain/${configuration.ruleChainId}`);
19 } 19 }
20 }; 20 };
@@ -36,8 +36,8 @@ @@ -36,8 +36,8 @@
36 36
37 const getIcon = computed(() => { 37 const getIcon = computed(() => {
38 const { icon } = unref(getNodeDefinition); 38 const { icon } = unref(getNodeDefinition);
39 - const { category } = unref(getData);  
40 - const { icon: categoryIcon } = category || {}; 39 + const { categoryConfig } = unref(getData);
  40 + const { icon: categoryIcon } = categoryConfig || {};
41 return icon || categoryIcon || 'tabler:circuit-ground'; 41 return icon || categoryIcon || 'tabler:circuit-ground';
42 }); 42 });
43 43
@@ -47,8 +47,8 @@ @@ -47,8 +47,8 @@
47 }); 47 });
48 48
49 const getBackgroundColor = computed(() => { 49 const getBackgroundColor = computed(() => {
50 - const { config, category } = unref(getData);  
51 - const { backgroundColor: categoryBackgroundColor } = category || {}; 50 + const { config, categoryConfig } = unref(getData);
  51 + const { backgroundColor: categoryBackgroundColor } = categoryConfig || {};
52 const { backgroundColor } = config || {}; 52 const { backgroundColor } = config || {};
53 return backgroundColor || categoryBackgroundColor; 53 return backgroundColor || categoryBackgroundColor;
54 }); 54 });
@@ -60,8 +60,8 @@ @@ -60,8 +60,8 @@
60 <section class="text-dark-900 text-xs"> 60 <section class="text-dark-900 text-xs">
61 <p class="mb-0 font-bold"> {{ getData?.data?.name }} </p> 61 <p class="mb-0 font-bold"> {{ getData?.data?.name }} </p>
62 <p class="mb-0 mt-2 text-gray-500 italic"> 62 <p class="mb-0 mt-2 text-gray-500 italic">
63 - {{ getData.category?.title }}  
64 - {{ getData?.category?.title && getData.config?.name ? '-' : '' }} 63 + {{ getData.categoryConfig?.title }}
  64 + {{ getData?.categoryConfig?.title && getData.config?.name ? '-' : '' }}
65 {{ getData.config?.name }} 65 {{ getData.config?.name }}
66 </p> 66 </p>
67 <p class="mt-1 mb-0 text-gray-500">{{ getData.data?.description }}</p> 67 <p class="mt-1 mb-0 text-gray-500">{{ getData.data?.description }}</p>
@@ -48,7 +48,7 @@ @@ -48,7 +48,7 @@
48 v-for="config in getCurrentCategoryNode.components" 48 v-for="config in getCurrentCategoryNode.components"
49 :key="config.clazz" 49 :key="config.clazz"
50 :config="config" 50 :config="config"
51 - :category="getCurrentCategoryNode.category" 51 + :categoryConfig="getCurrentCategoryNode.category"
52 /> 52 />
53 </body> 53 </body>
54 </section> 54 </section>
@@ -5,7 +5,7 @@ @@ -5,7 +5,7 @@
5 import { CategoryConfigType, NodeItemConfigType } from '../../../types/node'; 5 import { CategoryConfigType, NodeItemConfigType } from '../../../types/node';
6 6
7 const props = defineProps<{ 7 const props = defineProps<{
8 - category?: CategoryConfigType; 8 + categoryConfig?: CategoryConfigType;
9 config?: NodeItemConfigType; 9 config?: NodeItemConfigType;
10 }>(); 10 }>();
11 11
@@ -20,7 +20,7 @@ @@ -20,7 +20,7 @@
20 20
21 const getIcon = computed(() => { 21 const getIcon = computed(() => {
22 const { icon } = unref(getNodeDefinition); 22 const { icon } = unref(getNodeDefinition);
23 - const { icon: categoryIcon } = props.category || {}; 23 + const { icon: categoryIcon } = props.categoryConfig || {};
24 return icon || categoryIcon || 'tabler:circuit-ground'; 24 return icon || categoryIcon || 'tabler:circuit-ground';
25 }); 25 });
26 26
@@ -30,9 +30,9 @@ @@ -30,9 +30,9 @@
30 }); 30 });
31 31
32 const getBackgroundColor = computed(() => { 32 const getBackgroundColor = computed(() => {
33 - const { config, category } = props; 33 + const { config, categoryConfig } = props;
34 const { backgroundColor } = config || {}; 34 const { backgroundColor } = config || {};
35 - const { backgroundColor: categoryBackgroundColor } = category || {}; 35 + const { backgroundColor: categoryBackgroundColor } = categoryConfig || {};
36 return backgroundColor || categoryBackgroundColor; 36 return backgroundColor || categoryBackgroundColor;
37 }); 37 });
38 38
@@ -87,8 +87,8 @@ @@ -87,8 +87,8 @@
87 {{ config?.name }} 87 {{ config?.name }}
88 </span> 88 </span>
89 </div> 89 </div>
90 - <div class="w-4 h-4 bg-dark-50 rounded-1 border absolute -left-2 border-light-50"></div>  
91 - <div class="w-4 h-4 bg-dark-50 rounded-1 border absolute -right-2 border-light-50"></div> 90 + <div class="w-4 h-4 bg-gray-300 rounded-md border absolute -left-3 border-gray-500"></div>
  91 + <div class="w-4 h-4 bg-gray-300 rounded-md border absolute -right-3 border-gray-500"></div>
92 </main> 92 </main>
93 </Tooltip> 93 </Tooltip>
94 </template> 94 </template>
@@ -64,8 +64,8 @@ @@ -64,8 +64,8 @@
64 64
65 const getNodeIcon = computed(() => { 65 const getNodeIcon = computed(() => {
66 const { nodeData } = props; 66 const { nodeData } = props;
67 - const { category, config } = nodeData;  
68 - const { icon: categoryIcon } = category || {}; 67 + const { categoryConfig, config } = nodeData;
  68 + const { icon: categoryIcon } = categoryConfig || {};
69 const { configurationDescriptor } = config || {}; 69 const { configurationDescriptor } = config || {};
70 const { nodeDefinition } = configurationDescriptor || {}; 70 const { nodeDefinition } = configurationDescriptor || {};
71 const { icon } = nodeDefinition || {}; 71 const { icon } = nodeDefinition || {};
@@ -74,8 +74,8 @@ @@ -74,8 +74,8 @@
74 }); 74 });
75 75
76 const getTitleBackgroundColor = computed(() => { 76 const getTitleBackgroundColor = computed(() => {
77 - const { category, config } = props.nodeData;  
78 - const { backgroundColor: categoryBackgroundColor } = category || {}; 77 + const { categoryConfig, config } = props.nodeData;
  78 + const { backgroundColor: categoryBackgroundColor } = categoryConfig || {};
79 const { backgroundColor } = config || {}; 79 const { backgroundColor } = config || {};
80 return categoryBackgroundColor || backgroundColor; 80 return categoryBackgroundColor || backgroundColor;
81 }); 81 });
@@ -90,7 +90,7 @@ @@ -90,7 +90,7 @@
90 <template #title> 90 <template #title>
91 <h2 class="font-bold text-2xl truncate">{{ nodeData?.data?.name }}</h2> 91 <h2 class="font-bold text-2xl truncate">{{ nodeData?.data?.name }}</h2>
92 <p class="mb-0 text-gray-700"> 92 <p class="mb-0 text-gray-700">
93 - <span> {{ nodeData?.category?.title }}</span> 93 + <span> {{ nodeData?.categoryConfig?.title }}</span>
94 <span class="mx-1">-</span> 94 <span class="mx-1">-</span>
95 <span>{{ nodeData?.config?.name }}</span> 95 <span>{{ nodeData?.config?.name }}</span>
96 </p> 96 </p>
1 .vue-flow__handle { 1 .vue-flow__handle {
2 width: 16px; 2 width: 16px;
3 height: 16px; 3 height: 16px;
  4 + border-radius: 6px;
  5 + background-color: #d1d5db;
  6 + border-color: #6b7280;
  7 +}
  8 +
  9 +.vue-flow__handle:hover{
  10 + background-color: #000;
4 } 11 }
5 12
6 .vue-flow__handle-right { 13 .vue-flow__handle-right {
7 - right: -8px; 14 + right: -12px;
8 } 15 }
9 16
10 .vue-flow__handle-left { 17 .vue-flow__handle-left {
11 - left: -8px; 18 + left: -12px;
12 } 19 }
13 20
14 .vue-flow__background.vue-flow__container { 21 .vue-flow__background.vue-flow__container {
@@ -134,7 +134,7 @@ export interface DragTransferData { @@ -134,7 +134,7 @@ export interface DragTransferData {
134 } 134 }
135 135
136 export interface NodeData<T = BasicNodeFormData> { 136 export interface NodeData<T = BasicNodeFormData> {
137 - category?: CategoryConfigType; 137 + categoryConfig?: CategoryConfigType;
138 config?: NodeItemConfigType; 138 config?: NodeItemConfigType;
139 data?: T; 139 data?: T;
140 created?: boolean; 140 created?: boolean;