You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by ma...@apache.org on 2023/08/22 23:50:33 UTC

[camel-karavan] 02/03: Selector for #836

This is an automated email from the ASF dual-hosted git repository.

marat pushed a commit to branch feature-836
in repository https://gitbox.apache.org/repos/asf/camel-karavan.git

commit 0f739725cb4c5314a51d560dd3fa82e75718a288
Author: Marat Gubaidullin <ma...@Marats-MacBook-Pro.local>
AuthorDate: Tue Aug 22 19:41:26 2023 -0400

    Selector for #836
---
 karavan-designer/public/example/demo.camel.yaml    | 120 +++++------
 karavan-designer/src/designer/KaravanStore.ts      | 105 ++++++----
 .../src/designer/route/DslConnections.tsx          |  14 +-
 karavan-designer/src/designer/route/DslElement.tsx |  14 +-
 .../src/designer/route/DslSelector.tsx             | 229 +++++++++++----------
 .../src/designer/route/RouteDesigner.tsx           |  72 +++----
 .../designer/route/useDrawerMutationsObserver.tsx  |   2 +-
 .../src/designer/route/useResizeObserver.tsx       |   2 +-
 .../src/designer/route/useRouteDesignerHook.tsx    |  14 +-
 9 files changed, 288 insertions(+), 284 deletions(-)

diff --git a/karavan-designer/public/example/demo.camel.yaml b/karavan-designer/public/example/demo.camel.yaml
index 878ed244..4aed6c49 100644
--- a/karavan-designer/public/example/demo.camel.yaml
+++ b/karavan-designer/public/example/demo.camel.yaml
@@ -1,44 +1,44 @@
-- route:
-    id: route-f435
-    from:
-      uri: kamelet:timer-source
-      id: from-e52c
-      steps:
-        - choice:
-            when:
-              - expression: {}
-                id: when-064f
-                steps:
-                  - multicast:
-                      id: multicast-38ce
-                      steps:
-                        - bean:
-                            id: bean-3b8e
-                        - log:
-                            message: ${body}
-                            id: log-546f
-                        - loop:
-                            expression: {}
-                            id: loop-4635
-                            steps:
-                              - convertBodyTo:
-                                  id: convertBodyTo-1cae
-            otherwise:
-              id: otherwise-0b09
-              steps:
-                - filter:
-                    expression: {}
-                    id: filter-a02b
-            id: choice-c53c
-        - doTry:
-            id: doTry-8fd5
-            doCatch:
-              - id: doCatch-1071
-              - id: doCatch-c38e
-            steps:
-              - routingSlip:
-                  expression: {}
-                  id: routingSlip-a85a
+#- route:
+#    id: route-f435
+#    from:
+#      uri: kamelet:timer-source
+#      id: from-e52c
+#      steps:
+#        - choice:
+#            when:
+#              - expression: {}
+#                id: when-064f
+#                steps:
+#                  - multicast:
+#                      id: multicast-38ce
+#                      steps:
+#                        - bean:
+#                            id: bean-3b8e
+#                        - log:
+#                            message: ${body}
+#                            id: log-546f
+#                        - loop:
+#                            expression: {}
+#                            id: loop-4635
+#                            steps:
+#                              - convertBodyTo:
+#                                  id: convertBodyTo-1cae
+#            otherwise:
+#              id: otherwise-0b09
+#              steps:
+#                - filter:
+#                    expression: {}
+#                    id: filter-a02b
+#            id: choice-c53c
+#        - doTry:
+#            id: doTry-8fd5
+#            doCatch:
+#              - id: doCatch-1071
+#              - id: doCatch-c38e
+#            steps:
+#              - routingSlip:
+#                  expression: {}
+#                  id: routingSlip-a85a
 - route:
     id: route-178a
     from:
@@ -50,22 +50,22 @@
             steps:
               - bean:
                   id: bean-a5ef
-              - aggregate:
-                  id: aggregate-f5d8
-              - aggregate:
-                  id: aggregate-b9e7
-              - aggregate:
-                  id: aggregate-5eb8
-              - aggregate:
-                  id: aggregate-c57e
-              - aggregate:
-                  id: aggregate-1cd4
-              - bean:
-                  id: bean-72a1
-              - choice:
-                  when:
-                    - expression: {}
-                      id: when-a56b
-                  otherwise:
-                    id: otherwise-9f31
-                  id: choice-1905
+#              - aggregate:
+#                  id: aggregate-f5d8
+#              - aggregate:
+#                  id: aggregate-b9e7
+#              - aggregate:
+#                  id: aggregate-5eb8
+#              - aggregate:
+#                  id: aggregate-c57e
+#              - aggregate:
+#                  id: aggregate-1cd4
+#              - bean:
+#                  id: bean-72a1
+#              - choice:
+#                  when:
+#                    - expression: {}
+#                      id: when-a56b
+#                  otherwise:
+#                    id: otherwise-9f31
+#                  id: choice-1905
diff --git a/karavan-designer/src/designer/KaravanStore.ts b/karavan-designer/src/designer/KaravanStore.ts
index 440c944b..4dc570ed 100644
--- a/karavan-designer/src/designer/KaravanStore.ts
+++ b/karavan-designer/src/designer/KaravanStore.ts
@@ -15,11 +15,9 @@
  * limitations under the License.
  */
 
-import {create} from 'zustand'
 import {CamelElement, Integration} from "karavan-core/lib/model/IntegrationDefinition";
 import {createWithEqualityFn} from "zustand/traditional";
 import {shallow} from "zustand/shallow";
-import {useState} from "react";
 import {DslPosition} from "./utils/EventBus";
 
 interface IntegrationState {
@@ -35,11 +33,77 @@ export const useIntegrationStore = createWithEqualityFn<IntegrationState>((set)
 }), shallow)
 
 
+interface SelectorStateState {
+    showSelector: boolean;
+    setShowSelector: (showSelector: boolean) => void;
+    showSteps: boolean;
+    setShowSteps: (showSteps: boolean) => void;
+    parentDsl?: string;
+    setParentDsl: (parentDsl?: string) => void;
+    parentId: string;
+    setParentId: (parentId: string) => void;
+    selectorTabIndex?: string | number
+    setSelectorTabIndex: (selectorTabIndex?: string | number) => void;
+    selectedPosition?: number;
+    setSelectedPosition: (selectedPosition?: number) => void;
+    selectedLabels: string [];
+    addSelectedLabel: (label: string) => void;
+    deleteSelectedLabel: (label: string) => void;
+    clearSelectedLabels: () => void;
+    setSelectedLabels: (selectedLabels: string []) => void;
+}
+
+export const useSelectorStore = createWithEqualityFn<SelectorStateState>((set) => ({
+    showSelector: false,
+    deleteMessage: '',
+    parentId: '',
+    showSteps: true,
+    selectedLabels: [],
+    addSelectedLabel: (label: string) => {
+        set(state => ({
+            selectedLabels: [...state.selectedLabels, label]
+        }))
+    },
+    deleteSelectedLabel: (label: string) => {
+        set(state => ({
+            selectedLabels: [...state.selectedLabels.filter(x => x !== label)]
+        }))
+    },
+    clearSelectedLabels: () => {
+        set((state: SelectorStateState) => {
+            state.selectedLabels.length = 0;
+            return state;
+        })
+    },
+    setSelectedLabels: (selectedLabels: string []) => {
+        set({selectedLabels: selectedLabels})
+    },
+    setSelectorTabIndex: (selectorTabIndex?: string | number) => {
+        set({selectorTabIndex: selectorTabIndex})
+    },
+    setParentDsl: (parentDsl?: string) => {
+        set({parentDsl: parentDsl})
+    },
+    setShowSelector: (showSelector: boolean) => {
+        set({showSelector: showSelector})
+    },
+    setShowSteps: (showSteps: boolean) => {
+        set({showSteps: showSteps})
+    },
+    setParentId: (parentId: string) => {
+        set({parentId: parentId})
+    },
+    setSelectedPosition: (selectedPosition?: number) => {
+        set({selectedPosition: selectedPosition})
+    },
+}), shallow)
+
+
 interface ConnectionsState {
     steps: Map<string, DslPosition>;
     addStep: (uuid: string, position: DslPosition) => void;
     deleteStep: (uuid: string) => void;
-    clear: () => void;
+    clearSteps: () => void;
     setSteps: (steps: Map<string, DslPosition>) => void;
 }
 
@@ -60,7 +124,7 @@ export const useConnectionsStore = createWithEqualityFn<ConnectionsState>((set)
             return state;
         })
     },
-    clear: () => {
+    clearSteps: () => {
         set((state: ConnectionsState) => {
             state.steps.clear();
             return state;
@@ -73,32 +137,20 @@ export const useConnectionsStore = createWithEqualityFn<ConnectionsState>((set)
 
 interface DesignerState {
     shiftKeyPressed: boolean;
-    showSelector: boolean;
-    setShowSelector: (showSelector: boolean) => void;
     showDeleteConfirmation: boolean;
     setShowDeleteConfirmation: (showDeleteConfirmation: boolean) => void;
     showMoveConfirmation: boolean;
     setShowMoveConfirmation: (showMoveConfirmation: boolean) => void;
     propertyOnly: boolean;
     setPropertyOnly: (propertyOnly: boolean) => void;
-    showSteps: boolean;
-    setShowSteps: (showSteps: boolean) => void;
     deleteMessage: string;
     setDeleteMessage: (deleteMessage: string) => void;
-    parentDsl?: string;
-    setParentDsl: (parentDsl?: string) => void;
-    selectedPosition?: number;
-    setSelectedPosition: (selectedPosition?: number) => void;
     selectedStep?: CamelElement;
     setSelectedStep: (selectedStep?: CamelElement) => void;
-    parentId: string;
-    setParentId: (parentId: string) => void;
     selectedUuids: string[];
     setSelectedUuids: (selectedUuids: string[]) => void;
     clipboardSteps: string[];
     setClipboardSteps: (clipboardSteps: string[]) => void;
-    selectorTabIndex?: string | number
-    setSelectorTabIndex: (selectorTabIndex?: string | number) => void;
     width: number,
     height: number,
     top: number,
@@ -108,30 +160,15 @@ interface DesignerState {
 
 export const useDesignerStore = createWithEqualityFn<DesignerState>((set) => ({
     shiftKeyPressed: false,
-    showSelector: false,
     showDeleteConfirmation: false,
     showMoveConfirmation: false,
     deleteMessage: '',
-    parentId: '',
-    showSteps: true,
     selectedUuids: [],
     clipboardSteps: [],
     propertyOnly: false,
-    setSelectorTabIndex: (selectorTabIndex?: string | number) => {
-        set({selectorTabIndex: selectorTabIndex})
-    },
     setSelectedStep: (selectedStep?: CamelElement) => {
         set({selectedStep: selectedStep})
     },
-    setSelectedPosition: (selectedPosition?: number) => {
-        set({selectedPosition: selectedPosition})
-    },
-    setParentDsl: (parentDsl?: string) => {
-        set({parentDsl: parentDsl})
-    },
-    setShowSelector: (showSelector: boolean) => {
-        set({showSelector: showSelector})
-    },
     setShowDeleteConfirmation: (showDeleteConfirmation: boolean) => {
         set({showDeleteConfirmation: showDeleteConfirmation})
     },
@@ -141,15 +178,9 @@ export const useDesignerStore = createWithEqualityFn<DesignerState>((set) => ({
     setPropertyOnly: (propertyOnly: boolean) => {
         set({propertyOnly: propertyOnly})
     },
-    setShowSteps: (showSteps: boolean) => {
-        set({showSteps: showSteps})
-    },
     setDeleteMessage: (deleteMessage: string) => {
         set({deleteMessage: deleteMessage})
     },
-    setParentId: (parentId: string) => {
-        set({parentId: parentId})
-    },
     setSelectedUuids: (selectedUuids: string[]) => {
         set({selectedUuids: selectedUuids})
     },
diff --git a/karavan-designer/src/designer/route/DslConnections.tsx b/karavan-designer/src/designer/route/DslConnections.tsx
index 18d37819..7a58e30f 100644
--- a/karavan-designer/src/designer/route/DslConnections.tsx
+++ b/karavan-designer/src/designer/route/DslConnections.tsx
@@ -28,19 +28,18 @@ const outgoingDefinitions: string[] = ['ToDefinition', 'KameletDefinition', 'ToD
 
 export const DslConnections = () => {
 
-    const [ width, height, top, left] = useDesignerStore((s) =>
+    const [width, height, top, left] = useDesignerStore((s) =>
         [s.width, s.height, s.top, s.left])
-    const [ steps, addStep, deleteStep, clear] = useConnectionsStore((s) => [s.steps, s.addStep, s.deleteStep, s.clear])
+    const [ steps, addStep, deleteStep, clearSteps] = useConnectionsStore((s) => [s.steps, s.addStep, s.deleteStep, s.clearSteps])
 
     useEffect(() => {
         const sub = EventBus.onPosition()?.subscribe((evt: DslPosition) => setPosition(evt));
         return () => {
             sub?.unsubscribe();
         };
-    }, [width, height, top, left]);
+    }, []);
 
     function setPosition(evt: DslPosition) {
-        console.log("setPosition", evt);
         if (evt.command === "add") {
             addStep(evt.step.uuid, evt);
         }
@@ -48,7 +47,7 @@ export const DslConnections = () => {
             deleteStep(evt.step.uuid);
         }
         else if (evt.command === "clean") {
-            clear();
+            clearSteps();
         }
     }
 
@@ -427,8 +426,8 @@ export const DslConnections = () => {
         const stepsArray = Array.from(steps.values());
         return (
             <svg
-                style={{width: width, height: height, position: "absolute", left: 0, top: 0}}
-                viewBox={"0 0 " + (width) + " " + (height)}>
+                style={{width: width, height: height + 80, position: "absolute", left: 0, top: 0}}
+                viewBox={"0 0 " + (width) + " " + (height + 80)}>
                 <defs>
                     <marker id="arrowhead" markerWidth="9" markerHeight="6" refX="0" refY="3" orient="auto" className="arrow">
                         <polygon points="0 0, 9 3, 0 6"/>
@@ -443,7 +442,6 @@ export const DslConnections = () => {
         )
     }
 
-    console.log("RENDER CONNECTION")
     return (
         <div id="connections" className="connections" style={{ width: width, height: height + 80}}>
             {getSvg()}
diff --git a/karavan-designer/src/designer/route/DslElement.tsx b/karavan-designer/src/designer/route/DslElement.tsx
index 2e42ed03..72380c03 100644
--- a/karavan-designer/src/designer/route/DslElement.tsx
+++ b/karavan-designer/src/designer/route/DslElement.tsx
@@ -49,11 +49,11 @@ export const DslElement = (props: Props) => {
 
     const [integration, setIntegration] = useIntegrationStore((s) => [s.integration, s.setIntegration], shallow)
 
-    const [showSelector, showDeleteConfirmation, propertyOnly, showSteps,deleteMessage,parentId, selectedUuids,clipboardSteps, parentDsl,selectedPosition,selectedStep,selectorTabIndex,showMoveConfirmation,
-        setShowSelector, setShowDeleteConfirmation,setPropertyOnly,setShowSteps,setDeleteMessage, setParentId, setParentDsl, setSelectedPosition, setSelectedUuids, setClipboardSteps,setPosition,setShowMoveConfirmation,
+    const [showDeleteConfirmation, propertyOnly,deleteMessage, selectedUuids,clipboardSteps,selectedStep,showMoveConfirmation,
+        setShowDeleteConfirmation,setPropertyOnly,setDeleteMessage, setSelectedUuids, setClipboardSteps,setPosition,setShowMoveConfirmation,
         width, height, top, left] = useDesignerStore((s) =>
-        [s.showSelector, s.showDeleteConfirmation, s.propertyOnly, s.showSteps,s.deleteMessage,s.parentId, s.selectedUuids,s.clipboardSteps, s.parentDsl, s.selectedPosition, s.selectedStep,s.selectorTabIndex, s.showMoveConfirmation,
-            s.setShowSelector, s.setShowDeleteConfirmation,s.setPropertyOnly,s.setShowSteps,s.setDeleteMessage, s.setParentId, s.setParentDsl, s.setSelectedPosition, s.setSelectedUuids, s.setClipboardSteps, s.setPosition, s.setShowMoveConfirmation,
+        [s.showDeleteConfirmation, s.propertyOnly,s.deleteMessage, s.selectedUuids,s.clipboardSteps, s.selectedStep, s.showMoveConfirmation,
+            s.setShowDeleteConfirmation,s.setPropertyOnly,s.setDeleteMessage, s.setSelectedUuids, s.setClipboardSteps, s.setPosition, s.setShowMoveConfirmation,
             s.width, s.height, s.top, s.left], shallow)
     const [isDragging, setIsDragging] = useState<boolean>(false);
 
@@ -74,11 +74,6 @@ export const DslElement = (props: Props) => {
         }
     }
 
-    function closeDslSelector () {
-        // setState({showSelector: false})
-        setShowSelector(false);
-    }
-
     function onDeleteElement (evt: React.MouseEvent) {
         evt.stopPropagation();
         onShowDeleteConfirmation(props.step.uuid);
@@ -432,7 +427,6 @@ export const DslElement = (props: Props) => {
         <div key={"root" + element.uuid}
              className={className}
              ref={el => sendPosition(el, isSelected())}
-             // ref={el => sendPosition(el, isSelected())}
              style={{
                  borderStyle: hasBorder() ? "dotted" : "none",
                  borderColor: isSelected() ? "var(--step-border-color-selected)" : "var(--step-border-color)",
diff --git a/karavan-designer/src/designer/route/DslSelector.tsx b/karavan-designer/src/designer/route/DslSelector.tsx
index 47eb3b39..d18b9a87 100644
--- a/karavan-designer/src/designer/route/DslSelector.tsx
+++ b/karavan-designer/src/designer/route/DslSelector.tsx
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-import React from 'react';
+import React, {useEffect, useState} from 'react';
 import {
     Badge,
     Card, CardBody, CardFooter, CardHeader, Flex, FlexItem, Form, FormGroup, Gallery, Modal, PageSection,
@@ -24,66 +24,71 @@ import {
 import '../karavan.css';
 import {CamelUi} from "../utils/CamelUi";
 import {DslMetaModel} from "../utils/DslMetaModel";
+import {useDesignerStore, useSelectorStore} from "../KaravanStore";
+import {shallow} from "zustand/shallow";
+import {useRouteDesignerHook} from "./useRouteDesignerHook";
 
 interface Props {
-    onDslSelect: (dsl: DslMetaModel, parentId: string, position?: number | undefined) => void,
-    onClose?: () => void,
-    parentId: string,
-    parentDsl?: string,
-    showSteps: boolean,
     dark: boolean,
-    isOpen: boolean,
-    position?: number
     tabIndex?: string | number
 }
 
-interface State {
-    tabIndex: string | number
-    filter: string;
-    selectedLabels: string []
-}
+export const DslSelector = (props: Props) => {
 
-export class DslSelector extends React.Component<Props, State> {
+    const [showSelector, showSteps, parentId, parentDsl, selectorTabIndex, setShowSelector, setSelectorTabIndex,
+        selectedPosition, selectedLabels, setSelectedLabels, addSelectedLabel, deleteSelectedLabelbels] =
+        useSelectorStore((s) =>
+            [s.showSelector, s.showSteps, s.parentId, s.parentDsl, s.selectorTabIndex, s.setShowSelector, s.setSelectorTabIndex,
+                s.selectedPosition, s.selectedLabels, s.setSelectedLabels, s.addSelectedLabel, s.deleteSelectedLabel], shallow)
 
-    public state: State = {
-        tabIndex: this.props.tabIndex ? this.props.tabIndex : (this.props.parentDsl ? 'eip' : 'kamelet'),
-        filter: '',
-        selectedLabels: []
-    }
+    //
+    // const [showSelector, showDeleteConfirmation, showSteps, deleteMessage, parentId, parentDsl, selectedPosition, selectorTabIndex,
+    //     setShowSelector, setShowDeleteConfirmation, setPosition, setSelectorTabIndex, width, height, top, left] = useDesignerStore((s) =>
+    //     [s.showSelector, s.showDeleteConfirmation, s.showSteps, s.deleteMessage, s.parentId, s.parentDsl, s.selectedPosition, s.selectorTabIndex,
+    //         s.setShowSelector, s.setShowDeleteConfirmation, s.setPosition, s.setSelectorTabIndex, s.width, s.height, s.top, s.left], shallow)
 
-    selectTab = (evt: React.MouseEvent<HTMLElement, MouseEvent>, eventKey: string | number) => {
-        this.setState({tabIndex: eventKey});
-    }
+    const {deleteElement, selectElement, moveElement, onShowDeleteConfirmation, onDslSelect, openSelector, createRouteConfiguration} = useRouteDesignerHook();
 
-    componentDidUpdate = (prevProps: Readonly<Props>, prevState: Readonly<State>, snapshot?: any) => {
-        if (prevProps.parentDsl !== this.props.parentDsl) {
-            this.setState({tabIndex: CamelUi.getSelectorModelTypes(this.props.parentDsl, this.props.showSteps)[0][0]});
-        }
+
+    const [filter, setFilter] = useState<string>('');
+
+    useEffect(() => {
+    }, [selectedLabels]);
+
+
+    function selectTab(evt: React.MouseEvent<HTMLElement, MouseEvent>, eventKey: string | number) {
+        setSelectorTabIndex(eventKey);
     }
 
-    selectDsl = (evt: React.MouseEvent, dsl: any) => {
+    // function componentDidUpdate(prevProps: Readonly<Props>, prevState: Readonly<State>, snapshot?: any) {
+    //     if (prevProps.parentDsl !== props.parentDsl) {
+    //         this.setState({tabIndex: CamelUi.getSelectorModelTypes(props.parentDsl, props.showSteps)[0][0]});
+    //     }
+    // }
+
+    function selectDsl(evt: React.MouseEvent, dsl: any) {
         evt.stopPropagation();
-        this.setState({filter: ""});
-        this.props.onDslSelect.call(this, dsl, this.props.parentId, this.props.position);
+        setFilter('');
+        onDslSelect(dsl, parentId, selectedPosition);
     }
 
-    searchInput = () => {
+    function searchInput() {
         return (
             <Form isHorizontal className="search" autoComplete="off">
                 <FormGroup fieldId="search">
-                    <TextInput className="text-field" type="text" id="search" name="search" 
-                            value={this.state.filter}
-                            onChange={(_, value) => this.setState({filter: value})}/>
+                    <TextInput className="text-field" type="text" id="search" name="search"
+                               value={filter}
+                               onChange={(_, value) => setFilter(value)}/>
                 </FormGroup>
             </Form>
         )
     }
 
-    getCard(dsl: DslMetaModel, index: number) {
+    function getCard(dsl: DslMetaModel, index: number) {
         const labels = dsl.labels !== undefined ? dsl.labels.split(",").filter(label => label !== 'eip') : [];
         return (
             <Card key={dsl.dsl + index} isCompact className="dsl-card"
-                  onClick={event => this.selectDsl(event, dsl)}>
+                  onClick={event => selectDsl(event, dsl)}>
                 <CardHeader className="header-labels">
                     <Badge isRead className="support-level labels">{dsl.supportLevel}</Badge>
                     {['kamelet', 'component'].includes(dsl.navigation.toLowerCase()) &&
@@ -99,7 +104,8 @@ export class DslSelector extends React.Component<Props, State> {
                 </CardBody>
                 <CardFooter className="footer-labels">
                     <div style={{display: "flex", flexDirection: "row", justifyContent: "start"}}>
-                        {labels.map(label => <Badge key={label} isRead className="labels">{label}</Badge>)}
+                        {labels.map((label, index) => <Badge key={label + "-" + index} isRead
+                                                             className="labels">{label}</Badge>)}
                     </div>
 
                 </CardFooter>
@@ -107,90 +113,85 @@ export class DslSelector extends React.Component<Props, State> {
         )
     }
 
-    close = () => {
-        this.setState({filter: ""});
-        this.props.onClose?.call(this);
+    function close() {
+        setFilter('');
+        setShowSelector(false);
     }
 
-    selectLabel = (eipLabel: string) => {
-        if (!this.state.selectedLabels.includes(eipLabel)) {
-            this.setState((state) => {
-                state.selectedLabels.push(eipLabel);
-                return state
-            })
+    function selectLabel(eipLabel: string) {
+        if (!selectedLabels.includes(eipLabel)) {
+            addSelectedLabel(eipLabel);
         } else {
-            this.setState((state) => {
-                const index = state.selectedLabels.findIndex((label) => label === eipLabel);
-                state.selectedLabels.splice(index, 1);
-                return state;
-            })
+            deleteSelectedLabelbels(eipLabel);
         }
     }
 
-    render() {
-        const isEip = this.state.tabIndex === 'eip';
-        const {parentDsl, isOpen} = this.props;
-        const title = parentDsl === undefined ? "Select source" : "Select step";
-        const navigation: string = this.state.tabIndex ? this.state.tabIndex.toString() : "";
-        const elements = CamelUi.getSelectorModelsForParentFiltered(parentDsl, navigation, this.props.showSteps);
-        const eipLabels = [...new Set(elements.map(e => e.labels).join(",").split(",").filter(e => e !== 'eip'))];
-        const filteredElement = elements
-            .filter((dsl: DslMetaModel) => CamelUi.checkFilter(dsl, this.state.filter))
-            .filter((dsl: DslMetaModel) => {
-                if (!isEip || this.state.selectedLabels.length === 0) {
-                    return true;
-                } else {
-                    return dsl.labels.split(",").some(r => this.state.selectedLabels.includes(r));
-                }
-            });
 
-        return (
-            <Modal
-                aria-label={title}
-                width={'90%'}
-                className='dsl-modal'
-                isOpen={this.props.isOpen}
-                onClose={() => this.close()}
-                header={
-                    <Flex direction={{default: "column"}}>
-                        <FlexItem>
-                            <h3>{title}</h3>
-                            {this.searchInput()}
-                        </FlexItem>
-                        <FlexItem>
-                            <Tabs style={{overflow: 'hidden'}} activeKey={this.state.tabIndex}
-                                  onSelect={this.selectTab}>
-                                {parentDsl !== undefined &&
-                                    <Tab eventKey={"eip"} key={"tab-eip"}
-                                         title={<TabTitleText>Integration Patterns</TabTitleText>}>
-                                    </Tab>
-                                }
-                                <Tab eventKey={'kamelet'} key={"tab-kamelet"}
-                                     title={<TabTitleText>Kamelets</TabTitleText>}>
-                                </Tab>
-                                <Tab eventKey={'component'} key={'tab-component'}
-                                     title={<TabTitleText>Components</TabTitleText>}>
+    const isEip = selectorTabIndex === 'eip';
+    const title = parentDsl === undefined ? "Select source" : "Select step";
+    const navigation: string = selectorTabIndex ? selectorTabIndex.toString() : '';
+    const elements = CamelUi.getSelectorModelsForParentFiltered(parentDsl, navigation, showSteps);
+    const eipLabels = [...new Set(elements.map(e => e.labels).join(",").split(",").filter(e => e !== 'eip'))];
+    console.log("-----");
+    console.log(selectedLabels);
+    console.log(eipLabels);
+    console.log("-----");
+    const filteredElement = elements
+        .filter((dsl: DslMetaModel) => CamelUi.checkFilter(dsl, filter))
+        .filter((dsl: DslMetaModel) => {
+            if (!isEip || selectedLabels.length === 0) {
+                return true;
+            } else {
+                return dsl.labels.split(",").some(r => selectedLabels.includes(r));
+            }
+        });
+
+    return (
+        <Modal
+            aria-label={title}
+            width={'90%'}
+            className='dsl-modal'
+            isOpen={showSelector}
+            onClose={() => close()}
+            header={
+                <Flex direction={{default: "column"}}>
+                    <FlexItem>
+                        <h3>{title}</h3>
+                        {searchInput()}
+                    </FlexItem>
+                    <FlexItem>
+                        <Tabs style={{overflow: 'hidden'}} activeKey={selectorTabIndex}
+                              onSelect={selectTab}>
+                            {parentDsl !== undefined &&
+                                <Tab eventKey={"eip"} key={"tab-eip"}
+                                     title={<TabTitleText>Integration Patterns</TabTitleText>}>
                                 </Tab>
-                            </Tabs>
-                        </FlexItem>
-                    </Flex>
-                }
-                actions={{}}>
-                <PageSection padding={{default:"noPadding"}} variant={this.props.dark ? "darker" : "light"}>
-                    {isEip && <ToggleGroup aria-label="Labels" isCompact>
-                        {eipLabels.map(eipLabel => <ToggleGroupItem
-                            key={eipLabel}
-                            text={eipLabel}
-                            buttonId={eipLabel}
-                            isSelected={this.state.selectedLabels.includes(eipLabel)}
-                            onChange={selected => this.selectLabel(eipLabel)}
-                        />)}
-                    </ToggleGroup>}
-                    <Gallery key={"gallery-" + navigation} hasGutter className="dsl-gallery">
-                        {isOpen && filteredElement.map((dsl: DslMetaModel, index: number) => this.getCard(dsl, index))}
-                    </Gallery>
-                </PageSection>
-            </Modal>
-        )
-    }
+                            }
+                            <Tab eventKey={'kamelet'} key={"tab-kamelet"}
+                                 title={<TabTitleText>Kamelets</TabTitleText>}>
+                            </Tab>
+                            <Tab eventKey={'component'} key={'tab-component'}
+                                 title={<TabTitleText>Components</TabTitleText>}>
+                            </Tab>
+                        </Tabs>
+                    </FlexItem>
+                </Flex>
+            }
+            actions={{}}>
+            <PageSection padding={{default: "noPadding"}} variant={props.dark ? "darker" : "light"}>
+                {isEip && <ToggleGroup aria-label="Labels" isCompact>
+                    {eipLabels.map(eipLabel => <ToggleGroupItem
+                        key={eipLabel}
+                        text={eipLabel}
+                        buttonId={eipLabel}
+                        isSelected={selectedLabels.includes(eipLabel)}
+                        onChange={selected => selectLabel(eipLabel)}
+                    />)}
+                </ToggleGroup>}
+                <Gallery key={"gallery-" + navigation} hasGutter className="dsl-gallery">
+                    {showSelector && filteredElement.map((dsl: DslMetaModel, index: number) => getCard(dsl, index))}
+                </Gallery>
+            </PageSection>
+        </Modal>
+    )
 }
\ No newline at end of file
diff --git a/karavan-designer/src/designer/route/RouteDesigner.tsx b/karavan-designer/src/designer/route/RouteDesigner.tsx
index 17bc9b28..f6bb737b 100644
--- a/karavan-designer/src/designer/route/RouteDesigner.tsx
+++ b/karavan-designer/src/designer/route/RouteDesigner.tsx
@@ -33,7 +33,7 @@ import {DslElement} from "./DslElement";
 import {CamelUi} from "../utils/CamelUi";
 import {CamelDisplayUtil} from "karavan-core/lib/api/CamelDisplayUtil";
 import {useRouteDesignerHook} from "./useRouteDesignerHook";
-import {useDesignerStore, useIntegrationStore} from "../KaravanStore";
+import {useConnectionsStore, useDesignerStore, useIntegrationStore, useSelectorStore} from "../KaravanStore";
 import {shallow} from "zustand/shallow";
 import {CamelUtil} from "karavan-core/lib/api/CamelUtil";
 import {RouteConfigurationDefinition} from "karavan-core/lib/model/CamelDefinition";
@@ -53,35 +53,32 @@ export const RouteDesigner = (props: Props) => {
     const printerRef = React.createRef();
     const contentRef: React.RefObject<HTMLDivElement> = useRef(null);
 
-    const {
-        deleteElement,
-        selectElement,
-        moveElement,
-        onShowDeleteConfirmation,
-        onDslSelect,
-        openSelector,
-        createRouteConfiguration
-    } = useRouteDesignerHook();
+    const {deleteElement, selectElement, moveElement, onShowDeleteConfirmation, onDslSelect, openSelector, createRouteConfiguration} = useRouteDesignerHook();
 
     const [integration] = useIntegrationStore((state) => [state.integration], shallow)
-    const [showSelector, showDeleteConfirmation, showSteps, deleteMessage, parentId, parentDsl, selectedPosition, selectorTabIndex,
-        setShowSelector, setShowDeleteConfirmation, setPosition, width, height, top, left] = useDesignerStore((s) =>
-        [s.showSelector, s.showDeleteConfirmation, s.showSteps, s.deleteMessage, s.parentId, s.parentDsl, s.selectedPosition, s.selectorTabIndex,
-            s.setShowSelector, s.setShowDeleteConfirmation, s.setPosition, s.width, s.height, s.top, s.left], shallow)
+    const [showDeleteConfirmation, deleteMessage , setShowDeleteConfirmation, setPosition, width, height, top, left] =
+        useDesignerStore((s) =>
+        [s.showDeleteConfirmation, s.deleteMessage, s.setShowDeleteConfirmation, s.setPosition, s.width, s.height, s.top, s.left], shallow)
 
-    // const [refState, setRefState] = useState<Element | null>(null);
+    const [showSelector, showSteps, parentId, parentDsl, selectorTabIndex, setShowSelector, setSelectorTabIndex] =
+        useSelectorStore((s) =>
+        [s.showSelector, s.showSteps, s.parentId, s.parentDsl, s.selectorTabIndex, s.setShowSelector, s.setSelectorTabIndex], shallow)
 
-    const onResize = useCallback((target: HTMLDivElement) => {
-        if (flowRef && flowRef.current) {
-            const el = flowRef.current.getBoundingClientRect();
-            if (width !== el.width || height !== el.height || top !== el.top || left !== el.left) {
-                setPosition(el.width, el.height, el.top, el.left)
-                console.log("elmRect", el)
-            }
+    const [clearSteps] = useConnectionsStore((s) => [s.clearSteps])
+
+    useEffect(() => {
+        if (flowRef.current === null) {
+            clearSteps();
+        } else {
+            changeGraphSize();
         }
-    }, []);
+    }, [showSelector]);
 
-    const onMutate = useCallback((target: HTMLDivElement, mutations: any) => {
+    const onChangeGraphSize = useCallback((target: HTMLDivElement)  => {
+        changeGraphSize();
+    }, [])
+
+    function changeGraphSize ()  {
         if (flowRef && flowRef.current) {
             const el = flowRef.current.getBoundingClientRect();
             if (width !== el.width || height !== el.height || top !== el.top || left !== el.left) {
@@ -89,15 +86,11 @@ export const RouteDesigner = (props: Props) => {
                 console.log("elmRect", el)
             }
         }
-    }, []);
+    }
 
-    const firstRef = useResizeObserver(onResize);
-    const secondRef = useMutationsObserver(onMutate);
+    const firstRef = useResizeObserver(onChangeGraphSize);
+    const secondRef = useMutationsObserver(onChangeGraphSize);
     const flowRef = useRef<HTMLDivElement | null>(null);
-    //
-    // useEffect(() => {
-    //     if (refState) console.log("useEffect RouteDesigner", refState);
-    // }, [refState]);
 
     // function componentDidMount() {
     //     logic.componentDidMount();
@@ -123,19 +116,6 @@ export const RouteDesigner = (props: Props) => {
     //     return logic.componentDidUpdate(prevState, snapshot);
     // }
 
-    function getSelectorModal() {
-        return (
-            <DslSelector
-                isOpen={showSelector}
-                onClose={() => setShowSelector(false)}
-                dark={props.dark}
-                parentId={parentId}
-                parentDsl={parentDsl}
-                showSteps={showSteps}
-                position={selectedPosition}
-                tabIndex={selectorTabIndex}
-                onDslSelect={(dsl, parentId1) => onDslSelect(dsl, parentId1)}/>)
-    }
 
     function getDeleteConfirmation() {
         let htmlContent: string = deleteMessage;
@@ -174,8 +154,6 @@ export const RouteDesigner = (props: Props) => {
         )
     }
 
-    console.log("RENDER ROUTE_DESIGNER");
-
     function getGraph() {
         const routes = CamelUi.getRoutes(integration);
         const routeConfigurations = CamelUi.getRouteConfigurations(integration);
@@ -234,7 +212,7 @@ export const RouteDesigner = (props: Props) => {
                     </DrawerContent>
                 </Drawer>
             </div>
-            {getSelectorModal()}
+            <DslSelector dark={props.dark}/>
             {getDeleteConfirmation()}
         </div>
     )
diff --git a/karavan-designer/src/designer/route/useDrawerMutationsObserver.tsx b/karavan-designer/src/designer/route/useDrawerMutationsObserver.tsx
index f24a9e58..b7b5fbb0 100644
--- a/karavan-designer/src/designer/route/useDrawerMutationsObserver.tsx
+++ b/karavan-designer/src/designer/route/useDrawerMutationsObserver.tsx
@@ -21,7 +21,7 @@ function useMutationsObserver<T extends HTMLElement>(callback: (target: T, mutat
     const ref = useRef<T>(null)
 
     useLayoutEffect(() => {
-
+        console.log("useMutationsObserver")
         const element = ref?.current;
         if (!element) {
             return;
diff --git a/karavan-designer/src/designer/route/useResizeObserver.tsx b/karavan-designer/src/designer/route/useResizeObserver.tsx
index 27915bea..8b7ea995 100644
--- a/karavan-designer/src/designer/route/useResizeObserver.tsx
+++ b/karavan-designer/src/designer/route/useResizeObserver.tsx
@@ -21,7 +21,7 @@ function useResizeObserver<T extends HTMLElement>(callback: (target: T, entry: R
     const ref = useRef<T>(null)
 
     useLayoutEffect(() => {
-
+        console.log("useResizeObserver")
         const element = ref?.current;
         if (!element) {
             return;
diff --git a/karavan-designer/src/designer/route/useRouteDesignerHook.tsx b/karavan-designer/src/designer/route/useRouteDesignerHook.tsx
index fd97b731..5d78199e 100644
--- a/karavan-designer/src/designer/route/useRouteDesignerHook.tsx
+++ b/karavan-designer/src/designer/route/useRouteDesignerHook.tsx
@@ -30,19 +30,21 @@ import {RouteDesigner} from "./RouteDesigner";
 import {findDOMNode} from "react-dom";
 import {Subscription} from "rxjs";
 import debounce from 'lodash.debounce';
-import {useDesignerStore, useIntegrationStore} from "../KaravanStore";
+import {useDesignerStore, useIntegrationStore, useSelectorStore} from "../KaravanStore";
 import {shallow} from "zustand/shallow";
 import {setTabIndex} from "@patternfly/react-core";
 
 export const useRouteDesignerHook = () => {
 
     const [integration, setIntegration] = useIntegrationStore((state) => [state.integration, state.setIntegration], shallow)
-    const [showSelector, showDeleteConfirmation, propertyOnly, showSteps,deleteMessage,parentId, selectedUuids,clipboardSteps, parentDsl,selectedPosition,selectedStep,selectorTabIndex,shiftKeyPressed,
-        setShowSelector, setShowDeleteConfirmation,setPropertyOnly,setShowSteps, setDeleteMessage, setSelectedStep, setParentId, setParentDsl, setSelectedPosition, setSelectedUuids, setClipboardSteps,setPosition,setSelectorTabIndex,
+    const [ showDeleteConfirmation, propertyOnly,deleteMessage, selectedUuids,clipboardSteps,selectedStep,shiftKeyPressed,
+        setShowDeleteConfirmation,setPropertyOnly, setDeleteMessage, setSelectedStep, setSelectedUuids, setClipboardSteps, setPosition,
         width, height, top, left] = useDesignerStore((s) =>
-        [s.showSelector, s.showDeleteConfirmation, s.propertyOnly, s.showSteps,s.deleteMessage,s.parentId, s.selectedUuids,s.clipboardSteps, s.parentDsl, s.selectedPosition, s.selectedStep,s.selectorTabIndex, s.shiftKeyPressed,
-            s.setShowSelector, s.setShowDeleteConfirmation,s.setPropertyOnly,s.setShowSteps,s.setDeleteMessage, s.setSelectedStep, s.setParentId, s.setParentDsl, s.setSelectedPosition, s.setSelectedUuids, s.setClipboardSteps, s.setPosition,s.setSelectorTabIndex,
+        [s.showDeleteConfirmation, s.propertyOnly,s.deleteMessage, s.selectedUuids,s.clipboardSteps, s.selectedStep, s.shiftKeyPressed,
+             s.setShowDeleteConfirmation,s.setPropertyOnly,s.setDeleteMessage, s.setSelectedStep, s.setSelectedUuids, s.setClipboardSteps, s.setPosition,
             s.width, s.height, s.top, s.left], shallow)
+    const [setParentId, setShowSelector, setSelectorTabIndex, setParentDsl, setShowSteps, setSelectedPosition] = useSelectorStore((s) =>
+        [s.setParentId, s.setShowSelector, s.setSelectorTabIndex, s.setParentDsl, s.setShowSteps, s.setSelectedPosition], shallow)
 
     // const commandSub = EventBus.onCommand()?.subscribe((command: Command) => onCommand(command));
     //
@@ -266,7 +268,7 @@ export const useRouteDesignerHook = () => {
         setParentDsl(parentDsl);
         setShowSteps(showSteps);
         setSelectedPosition(position);
-        setSelectorTabIndex(selectorTabIndex);
+        setSelectorTabIndex((parentId === undefined && parentDsl === undefined) ? 'kamelet' : 'eip');
     }
     //
     // function closeDslSelector = () => {