Mirror of https://github.com/roostorg/osprey
github.com/roostorg/osprey
1import { useState } from 'react';
2import { AutoComplete, Button, Drawer, Input, Space } from 'antd';
3import { OptionData, OptionGroupData } from 'rc-select/lib/interface/index';
4import { Core } from 'cytoscape';
5import shallow from 'zustand/shallow';
6
7import useApplicationConfigStore from '../../stores/ApplicationConfigStore';
8import useRulesVisualizerStore from '../../stores/RulesVisualizerStore';
9import { getGraphJson } from '../../actions/RulesVisualizerActions';
10import Text, { TextSizes } from '../../uikit/Text';
11import { DEFAULT_ANIMATE_DURATION } from './RulesVisualizer';
12import { LabelInfo } from '../../stores/ApplicationConfigStore';
13
14import styles from './RulesVisualizerHeader.module.css';
15
16const RulesVisualizerHeader = ({
17 cy,
18 setIsLoading,
19 showLabelUpstream,
20 showLabelDownstream,
21}: {
22 cy: Core | null;
23 setIsLoading: Function;
24 showLabelUpstream: boolean;
25 showLabelDownstream: boolean;
26}) => {
27 const [isDrawerVisible, setIsDrawerVisible] = useState(false);
28 const [labelInfoMapping, knownActionNames] = useApplicationConfigStore(
29 (state) => [state.labelInfoMapping, state.knownActionNames],
30 shallow
31 );
32 const [updateRuleVizGraph, nodes, selectedFeature, selectedFeatureType] = useRulesVisualizerStore(
33 (state) => [state.updateRuleVizGraph, state.nodes, state.selectedFeature, state.selectedFeatureType],
34 shallow
35 );
36
37 const selectedFeatureText = (
38 <Space>
39 <Text size={TextSizes.H5}>{selectedFeatureType}</Text>
40 <Text size={TextSizes.H7}>{selectedFeature}</Text>
41 </Space>
42 );
43
44 const handleFeatureSelect = async (value: string, e: OptionData | OptionGroupData) => {
45 setIsLoading(true);
46 updateRuleVizGraph({ nodes: null, edges: null });
47 const graphJson = await getGraphJson(e.type, [`${e.value}`], showLabelUpstream, showLabelDownstream);
48 updateRuleVizGraph(graphJson);
49 setIsLoading(false);
50 };
51
52 const handleNodeSelect = (value: string, e: OptionData | OptionGroupData) => {
53 if (cy) {
54 cy.animate({
55 easing: 'ease-out-cubic',
56 duration: DEFAULT_ANIMATE_DURATION,
57 fit: { eles: cy.elements(), padding: 0 },
58 complete: () => {
59 cy.animate({
60 easing: 'ease-in-cubic',
61 duration: DEFAULT_ANIMATE_DURATION,
62 fit: { eles: cy.getElementById(e.id), padding: 300 },
63 });
64 },
65 });
66 }
67 setIsDrawerVisible(false);
68 };
69
70 const drawer = (
71 <Drawer
72 title={selectedFeatureText}
73 placement="right"
74 closable={false}
75 onClose={() => setIsDrawerVisible(false)}
76 visible={isDrawerVisible}
77 width="600"
78 >
79 <div className={styles.drawerBody}>
80 <AutoComplete
81 className={styles.autocomplete}
82 options={nodes?.map((node) => ({ value: node.name, id: node.id }))}
83 onSelect={handleNodeSelect}
84 filterOption
85 >
86 <Input.Search size="large" placeholder="Search by node" enterButton allowClear />
87 </AutoComplete>
88 </div>
89 </Drawer>
90 );
91
92 return (
93 <div className={styles.header}>
94 <Text className={styles.leftHeaderContainer} size={TextSizes.H3}>
95 Rules Visualizer
96 </Text>
97 <div className={styles.rightHeaderContainer}>
98 <Space>
99 {selectedFeature && (
100 <Button size="large" onClick={() => setIsDrawerVisible(true)}>
101 {selectedFeatureText}
102 </Button>
103 )}
104 <AutoComplete
105 className={styles.autocomplete}
106 options={getSuggestions(knownActionNames, labelInfoMapping)}
107 onSelect={handleFeatureSelect}
108 filterOption
109 defaultOpen
110 autoFocus
111 >
112 <Input.Search size="large" placeholder="Search by action or label" enterButton allowClear />
113 </AutoComplete>
114 </Space>
115 </div>
116 {drawer}
117 </div>
118 );
119};
120
121function getSuggestions(actions: Set<String>, labels: Map<string, LabelInfo>) {
122 return [
123 {
124 label: 'Actions',
125 options: [...actions].map((action) => ({
126 value: action,
127 type: 'action',
128 })),
129 },
130 {
131 label: 'Labels',
132 options: [...labels.keys()].map((label) => ({
133 value: label,
134 type: 'label',
135 })) as OptionData[],
136 },
137 ] as OptionGroupData[];
138}
139
140export default RulesVisualizerHeader;