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/12/07 02:37:07 UTC

(camel-karavan) 01/04: Preview fixes of new Designer

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

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

commit e1fcd92dbc5fd548eb5de9aea2b4cce120eb1c82
Author: Marat Gubaidullin <ma...@talismancloud.io>
AuthorDate: Wed Dec 6 11:01:02 2023 -0500

    Preview fixes of new Designer
---
 karavan-designer/public/example/demo.camel.yaml    |  19 ++
 .../src/designer/route/DslConnections.tsx          |   4 +-
 .../src/designer/route/element/DslElement.css      |  17 +-
 .../src/designer/route/element/DslElement.tsx      | 213 ++-------------
 .../{DslElement.tsx => DslElementHeader.tsx}       | 304 +++------------------
 karavan-designer/src/designer/utils/CamelUi.tsx    |   3 +-
 6 files changed, 96 insertions(+), 464 deletions(-)

diff --git a/karavan-designer/public/example/demo.camel.yaml b/karavan-designer/public/example/demo.camel.yaml
index 40e3c45b..ccd98241 100644
--- a/karavan-designer/public/example/demo.camel.yaml
+++ b/karavan-designer/public/example/demo.camel.yaml
@@ -32,6 +32,25 @@
                     message: ${body}
                     id: log-6831
             id: choice-c1db
+        - saga:
+            id: saga-8f2c
+            steps:
+              - to:
+                  uri: kamelet:azure-cosmosdb-sink
+                  id: to-1394
+- route:
+    nodePrefixId: route-d10
+    id: route-3ad9
+    from:
+      uri: kamelet:azure-storage-datalake-source
+      id: from-1516
+- route:
+    nodePrefixId: route-171
+    id: route-99f9
+    from:
+      uri: kamelet:azure-storage-blob-source
+      id: from-f8e9
+      steps:
         - multicast:
             id: multicast-6a53
             steps:
diff --git a/karavan-designer/src/designer/route/DslConnections.tsx b/karavan-designer/src/designer/route/DslConnections.tsx
index 5f9467b6..a4eef251 100644
--- a/karavan-designer/src/designer/route/DslConnections.tsx
+++ b/karavan-designer/src/designer/route/DslConnections.tsx
@@ -283,7 +283,7 @@ export function DslConnections() {
             if (parent) {
             const rect1 = parent.headerRect;
             const rect2 = pos.headerRect;
-            return getComplexArrow(pos.step.uuid, rect1, rect2);
+            return getComplexArrow(pos.step.uuid + ":" + pos.parent.uuid, rect1, rect2);
             }
         }
     }
@@ -294,7 +294,7 @@ export function DslConnections() {
         const nextStep = steps.get(uuid);
         const rect2 = nextStep?.rect;
         if (rect1 && rect2) {
-            return getComplexArrow(uuid, rect1, rect2);
+            return getComplexArrow(uuid + "-" + btn.nextstep.uuid, rect1, rect2);
         }
     }
 
diff --git a/karavan-designer/src/designer/route/element/DslElement.css b/karavan-designer/src/designer/route/element/DslElement.css
index 3039f422..7af5bd51 100644
--- a/karavan-designer/src/designer/route/element/DslElement.css
+++ b/karavan-designer/src/designer/route/element/DslElement.css
@@ -17,12 +17,19 @@
 
 .karavan .dsl-page .flows .step-element .header-route {
     display: block;
-    border: none;
     background: transparent;
-    padding: 0;
-    margin: 3px 24px 10px 24px;
-    /*min-width: 260px;*/
+    padding: 10px;
+    margin: 0;
     z-index: 101;
+    min-width: 260px;
+}
+
+.karavan .dsl-page .flows .step-element .header-bottom-line {
+    border-bottom: 1px dashed;
+}
+
+.karavan .dsl-page .flows .step-element .header-route:hover {
+    cursor: pointer;
 }
 
 .karavan .step-element .header-route .delete-button {
@@ -214,4 +221,4 @@
     width: 20px;
     height: 20px;
     background: white;
-}
\ No newline at end of file
+}
diff --git a/karavan-designer/src/designer/route/element/DslElement.tsx b/karavan-designer/src/designer/route/element/DslElement.tsx
index 6e8ce718..a1b63a98 100644
--- a/karavan-designer/src/designer/route/element/DslElement.tsx
+++ b/karavan-designer/src/designer/route/element/DslElement.tsx
@@ -14,20 +14,19 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-import React, {CSSProperties, useMemo, useState} from 'react';
-import {Text, Tooltip,} from '@patternfly/react-core';
+import React, {CSSProperties, useState} from 'react';
+import {Tooltip,} from '@patternfly/react-core';
 import '../../karavan.css';
 import './DslElement.css';
 import {CamelElement} from "karavan-core/lib/model/IntegrationDefinition";
-import {CamelUi} from "../../utils/CamelUi";
 import {EventBus} from "../../utils/EventBus";
 import {ChildElement, CamelDefinitionApiExt} from "karavan-core/lib/api/CamelDefinitionApiExt";
-import {CamelUtil} from "karavan-core/lib/api/CamelUtil";
 import {CamelDisplayUtil} from "karavan-core/lib/api/CamelDisplayUtil";
 import {useDesignerStore, useIntegrationStore} from "../../DesignerStore";
 import {shallow} from "zustand/shallow";
 import {useRouteDesignerHook} from "../useRouteDesignerHook";
-import {AddElementIcon, DeleteElementIcon, InsertElementIcon} from "./DslElementIcons";
+import {AddElementIcon} from "./DslElementIcons";
+import {DslElementHeader} from "./DslElementHeader";
 
 interface Props {
     step: CamelElement,
@@ -70,11 +69,6 @@ export function DslElement(props: Props) {
         }
     }
 
-    function onDeleteElement(evt: React.MouseEvent) {
-        evt.stopPropagation();
-        onShowDeleteConfirmation(props.step.uuid);
-    }
-
     function onSelectElement(evt: React.MouseEvent) {
         evt.stopPropagation();
         selectElement(props.step);
@@ -106,11 +100,11 @@ export function DslElement(props: Props) {
 
     function hasBorder(): boolean {
         const step = props.step;
-        if (['FilterDefinition'].includes(step.dslName)) {
+        if (['FilterDefinition', 'RouteDefinition', 'RouteConfigurationDefinition'].includes(step.dslName)) {
             return true;
         }
-        if (['FromDefinition',
-            'RouteDefinition',
+        if ([
+            'FromDefinition',
             'TryDefinition',
             'CatchDefinition', 'FinallyDefinition',
             'ChoiceDefinition',
@@ -125,9 +119,8 @@ export function DslElement(props: Props) {
         return ['FromDefinition', 'RouteConfigurationDefinition', 'RouteDefinition', 'WhenDefinition', 'OtherwiseDefinition'].includes(props.step.dslName);
     }
 
-    function isWide(): boolean {
-        return ['RouteConfigurationDefinition', 'RouteDefinition', 'ChoiceDefinition', 'SwitchDefinition', 'MulticastDefinition', 'TryDefinition', 'CircuitBreakerDefinition']
-            .includes(props.step.dslName);
+    function isRoute(): boolean {
+        return ['RouteDefinition'].includes(props.step.dslName);
     }
 
     function isAddStepButtonLeft(): boolean {
@@ -139,9 +132,6 @@ export function DslElement(props: Props) {
         return ['MulticastDefinition'].includes(props.step.dslName);
     }
 
-    function isRoot(): boolean {
-        return ['RouteConfigurationDefinition', 'RouteDefinition'].includes(props.step?.dslName);
-    }
 
     function isInStepWithChildren() {
         const step: CamelElement = props.step;
@@ -149,49 +139,6 @@ export function DslElement(props: Props) {
         return children.filter((c: ChildElement) => c.name === 'steps' || c.multiple).length > 0 && props.inSteps;
     }
 
-    function getChildrenInfo(step: CamelElement): [boolean, number, boolean, number, number] {
-        const children = CamelDefinitionApiExt.getElementChildrenDefinition(step.dslName);
-        const hasStepsField = children.filter((c: ChildElement) => c.name === 'steps').length === 1;
-        const stepsChildrenCount = children
-            .filter(c => c.name === 'steps')
-            .map((child: ChildElement, index: number) => {
-                const children: CamelElement[] = CamelDefinitionApiExt.getElementChildren(step, child);
-                return children.length;
-            }).reduce((a, b) => a + b, 0);
-
-        const hasNonStepsFields = children.filter(c => c.name !== 'steps' && c.name !== 'expression' && c.name !== 'onWhen').length > 0;
-        const childrenCount = children
-            .map((child: ChildElement, index: number) => {
-                const children: CamelElement[] = CamelDefinitionApiExt.getElementChildren(step, child);
-                return children.length;
-            }).reduce((a, b) => a + b, 0);
-        const nonStepChildrenCount = childrenCount - stepsChildrenCount;
-        return [hasStepsField, stepsChildrenCount, hasNonStepsFields, nonStepChildrenCount, childrenCount]
-    }
-
-    function hasWideChildrenElement() {
-        const [hasStepsField, stepsChildrenCount, hasNonStepsFields, nonStepChildrenCount, childrenCount] = getChildrenInfo(props.step);
-        if (isHorizontal() && stepsChildrenCount > 1) return true;
-        else if (hasStepsField && stepsChildrenCount > 0 && hasNonStepsFields && nonStepChildrenCount > 0) return true;
-        else if (!hasStepsField && hasNonStepsFields && childrenCount > 1) return true;
-        else if (hasStepsField && stepsChildrenCount > 0 && hasNonStepsFields && childrenCount > 1) return true;
-        else return false;
-    }
-
-    function hasBorderOverSteps(step: CamelElement) {
-        const [hasStepsField, stepsChildrenCount, hasNonStepsFields, nonStepChildrenCount] = getChildrenInfo(step);
-        if (hasStepsField && stepsChildrenCount > 0 && hasNonStepsFields && nonStepChildrenCount > 0) return true;
-        else return false;
-    }
-
-    function getHeaderStyle() {
-        const style: CSSProperties = {
-            width: isWide() ? "100%" : "",
-            fontWeight: isElementSelected() ? "bold" : "normal",
-        };
-        return style;
-    }
-
     function sendButtonPosition(el: HTMLButtonElement | null) {
         const {nextStep, step, parent} = props;
         let needArrow = !hasBorder() && !['ChoiceDefinition', 'MulticastDefinition', 'TryDefinition'].includes(step.dslName);
@@ -233,97 +180,6 @@ export function DslElement(props: Props) {
         }
     }
 
-    function getAvailableModels() { // TODO: make static list-of-values instead
-        const step: CamelElement = props.step
-        return CamelUi.getSelectorModelsForParent(step.dslName, false);
-    }
-
-    const availableModels = useMemo(
-        () => getAvailableModels(),
-        [props.step.dslName]
-    );
-
-
-    function getHeader() {
-        const step: CamelElement = props.step;
-        const parent = props.parent;
-        const inRouteConfiguration = parent !== undefined && parent.dslName === 'RouteConfigurationDefinition';
-        const showAddButton = !['CatchDefinition', 'RouteDefinition'].includes(step.dslName) && availableModels.length > 0;
-        const showInsertButton =
-            !['FromDefinition', 'RouteConfigurationDefinition', 'RouteDefinition', 'CatchDefinition', 'FinallyDefinition', 'WhenDefinition', 'OtherwiseDefinition'].includes(step.dslName)
-            && !inRouteConfiguration;
-        const headerClass = ['RouteConfigurationDefinition', 'RouteDefinition'].includes(step.dslName) ? "header-route" : "header"
-        const headerClasses = isElementSelected() ? headerClass + " selected" : headerClass;
-        return (
-            <div className={"dsl-element " + headerClasses} style={getHeaderStyle()} ref={headerRef}>
-                {!['RouteConfigurationDefinition', 'RouteDefinition'].includes(props.step.dslName) &&
-                    <div
-                        ref={el => sendPosition(el)}
-                        className={"header-icon"}
-                        style={isWide() ? {width: ""} : {}}>
-                        {CamelUi.getIconForElement(step)}
-                    </div>
-                }
-                <div className={hasWideChildrenElement() ? "header-text" : ""}>
-                    {hasWideChildrenElement() && <div className="spacer"/>}
-                    {getHeaderTextWithTooltip(step)}
-                </div>
-                {showInsertButton && getInsertElementButton()}
-                {getDeleteButton()}
-                {showAddButton && getAddElementButton()}
-            </div>
-        )
-    }
-
-    function getHeaderText(step: CamelElement): string {
-        if (isKamelet() && step.dslName === 'ToDefinition' && (step as any).uri === 'kamelet:sink') {
-            return "Sink";
-        } else if (isKamelet() && step.dslName === 'FromDefinition' && (step as any).uri === 'kamelet:source') {
-            return "Source";
-        } else {
-            return (step as any).description ? (step as any).description : CamelUi.getElementTitle(props.step);
-        }
-    }
-
-    function getHeaderTextWithTooltip(step: CamelElement) {
-        const checkRequired = CamelUtil.checkRequired(step);
-        const title = getHeaderText(step);
-        let className = hasWideChildrenElement() ? "text text-right" : "text text-bottom";
-        if (!checkRequired[0]) className = className + " header-text-required";
-        if (checkRequired[0]) {
-            return <Text className={className}>{title}</Text>
-        } else return (
-            <Tooltip position={"right"} className="tooltip-required-field"
-                     content={checkRequired[1].map((text, i) => (<div key={i}>{text}</div>))}>
-                <Text className={className}>{title}</Text>
-            </Tooltip>
-        )
-    }
-
-    function getHeaderWithTooltip(tooltip: string | undefined) {
-        return (
-            <>
-                {getHeader()}
-                <Tooltip triggerRef={headerRef} position={"left"} content={<div>{tooltip}</div>}/>
-            </>
-
-        )
-    }
-
-    function getHeaderTooltip(): string | undefined {
-        if (CamelUi.isShowExpressionTooltip(props.step)) return CamelUi.getExpressionTooltip(props.step);
-        if (CamelUi.isShowUriTooltip(props.step)) return CamelUi.getUriTooltip(props.step);
-        return undefined;
-    }
-
-    function getElementHeader() {
-        const tooltip = getHeaderTooltip();
-        if (tooltip !== undefined && !isDragging) {
-            return getHeaderWithTooltip(tooltip);
-        }
-        return getHeader();
-    }
-
     function getChildrenStyle() {
         const style: CSSProperties = {
             display: "flex",
@@ -333,8 +189,6 @@ export function DslElement(props: Props) {
     }
 
     function getChildrenElementsStyle(child: ChildElement, notOnlySteps: boolean) {
-        const step = props.step;
-        const isBorder = child.name === 'steps' && hasBorderOverSteps(step);
         const style: CSSProperties = {
             // borderStyle: isBorder ? "dotted" : "none",
             borderColor: "var(--step-border-color)",
@@ -408,7 +262,7 @@ export function DslElement(props: Props) {
     }
 
     function getAddStepButton() {
-        const {step, nextStep} = props;
+        const {step} = props;
         const hideAddButton = step.dslName === 'StepDefinition' && !CamelDisplayUtil.isStepDefinitionExpanded(integration, step.uuid, selectedUuids.at(0));
         if (hideAddButton) return (<></>)
         else return (
@@ -429,44 +283,6 @@ export function DslElement(props: Props) {
         )
     }
 
-    function getAddElementButton() {
-        return (
-            <Tooltip position={"bottom"}
-                     content={<div>{"Add DSL element to " + CamelDisplayUtil.getTitle(props.step)}</div>}>
-                <button
-                    type="button"
-                    aria-label="Add"
-                    onClick={e => onOpenSelector(e, false)}
-                    className={"add-element-button"}>
-                    <AddElementIcon/>
-                </button>
-            </Tooltip>
-        )
-    }
-
-    function getInsertElementButton() {
-        return (
-            <Tooltip position={"left"} content={<div>{"Insert element before"}</div>}>
-                <button type="button"
-                        aria-label="Insert"
-                        onClick={e => onOpenSelector(e, true, true)}
-                        className={"insert-element-button"}>
-                    <InsertElementIcon/>
-                </button>
-            </Tooltip>
-        )
-    }
-
-    function getDeleteButton() {
-        return (
-            <Tooltip position={"right"} content={<div>{"Delete element"}</div>}>
-                <button type="button" aria-label="Delete" onClick={e => onDeleteElement(e)} className="delete-button">
-                    <DeleteElementIcon/>
-                </button>
-            </Tooltip>
-        )
-    }
-
     const element: CamelElement = props.step;
     const className = "step-element"
         + (isElementSelected() ? " step-element-selected" : "") + (!props.step.showChildren ? " hidden-step" : "")
@@ -516,7 +332,14 @@ export function DslElement(props: Props) {
              onDrop={event => dragElement(event, element)}
              draggable={!isNotDraggable()}
         >
-            {getElementHeader()}
+            <DslElementHeader headerRef={headerRef}
+                              step={props.step}
+                              parent={props.parent}
+                              nextStep={props.nextStep}
+                              prevStep={props.prevStep}
+                              inSteps={props.inSteps}
+                              isDragging={isDragging}
+                              position={props.position}/>
             {getChildElements()}
         </div>
     )
diff --git a/karavan-designer/src/designer/route/element/DslElement.tsx b/karavan-designer/src/designer/route/element/DslElementHeader.tsx
similarity index 50%
copy from karavan-designer/src/designer/route/element/DslElement.tsx
copy to karavan-designer/src/designer/route/element/DslElementHeader.tsx
index 6e8ce718..9ac4ab99 100644
--- a/karavan-designer/src/designer/route/element/DslElement.tsx
+++ b/karavan-designer/src/designer/route/element/DslElementHeader.tsx
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-import React, {CSSProperties, useMemo, useState} from 'react';
+import React, {CSSProperties, useMemo} from 'react';
 import {Text, Tooltip,} from '@patternfly/react-core';
 import '../../karavan.css';
 import './DslElement.css';
@@ -24,24 +24,29 @@ import {EventBus} from "../../utils/EventBus";
 import {ChildElement, CamelDefinitionApiExt} from "karavan-core/lib/api/CamelDefinitionApiExt";
 import {CamelUtil} from "karavan-core/lib/api/CamelUtil";
 import {CamelDisplayUtil} from "karavan-core/lib/api/CamelDisplayUtil";
-import {useDesignerStore, useIntegrationStore} from "../../DesignerStore";
+import {useDesignerStore} from "../../DesignerStore";
 import {shallow} from "zustand/shallow";
 import {useRouteDesignerHook} from "../useRouteDesignerHook";
 import {AddElementIcon, DeleteElementIcon, InsertElementIcon} from "./DslElementIcons";
+import {
+    InterceptDefinition,
+    InterceptFromDefinition,
+    InterceptSendToEndpointDefinition, OnCompletionDefinition, OnExceptionDefinition, RouteConfigurationDefinition
+} from "karavan-core/lib/model/CamelDefinition";
 
 interface Props {
+    headerRef: React.RefObject<HTMLDivElement>
     step: CamelElement,
     parent: CamelElement | undefined,
     nextStep: CamelElement | undefined,
     prevStep: CamelElement | undefined,
     inSteps: boolean
     position: number
+    isDragging: boolean
 }
 
-export function DslElement(props: Props) {
+export function DslElementHeader(props: Props) {
 
-    const headerRef = React.useRef<HTMLDivElement>(null);
-    const addButtonRef = React.useRef<HTMLDivElement>(null);
     const {
         selectElement,
         moveElement,
@@ -52,14 +57,9 @@ export function DslElement(props: Props) {
         isActionKamelet
     } = useRouteDesignerHook();
 
-    const [integration] = useIntegrationStore((s) => [s.integration, s.setIntegration], shallow)
-
     const [selectedUuids, selectedStep, showMoveConfirmation, setShowMoveConfirmation, hideLogDSL, setMoveElements] =
         useDesignerStore((s) =>
             [s.selectedUuids, s.selectedStep, s.showMoveConfirmation, s.setShowMoveConfirmation, s.hideLogDSL, s.setMoveElements], shallow)
-    const [isDragging, setIsDragging] = useState<boolean>(false);
-
-    const [isDraggedOver, setIsDraggedOver] = useState<boolean>(false);
 
     function onOpenSelector(evt: React.MouseEvent, showSteps: boolean = true, isInsert: boolean = false) {
         evt.stopPropagation();
@@ -75,27 +75,6 @@ export function DslElement(props: Props) {
         onShowDeleteConfirmation(props.step.uuid);
     }
 
-    function onSelectElement(evt: React.MouseEvent) {
-        evt.stopPropagation();
-        selectElement(props.step);
-    }
-
-    function dragElement(event: React.DragEvent<HTMLDivElement>, element: CamelElement) {
-        event.preventDefault();
-        event.stopPropagation();
-        setIsDraggedOver(false);
-        const sourceUuid = event.dataTransfer.getData("text/plain");
-        const targetUuid = element.uuid;
-        if (sourceUuid !== targetUuid) {
-            if (element.hasSteps()) {
-                setShowMoveConfirmation(true);
-                setMoveElements([sourceUuid, targetUuid])
-            } else {
-                moveElement(sourceUuid, targetUuid, false);
-            }
-        }
-    }
-
     function isElementSelected(): boolean {
         return selectedUuids.includes(props.step.uuid);
     }
@@ -104,51 +83,15 @@ export function DslElement(props: Props) {
         return props.step.dslName === 'LogDefinition' && hideLogDSL;
     }
 
-    function hasBorder(): boolean {
-        const step = props.step;
-        if (['FilterDefinition'].includes(step.dslName)) {
-            return true;
-        }
-        if (['FromDefinition',
-            'RouteDefinition',
-            'TryDefinition',
-            'CatchDefinition', 'FinallyDefinition',
-            'ChoiceDefinition',
-            'SwitchDefinition', 'WhenDefinition', 'OtherwiseDefinition'
-        ].includes(step.dslName)) {
-            return false;
-        }
-        return props.step?.hasSteps();
-    }
-
-    function isNotDraggable(): boolean {
-        return ['FromDefinition', 'RouteConfigurationDefinition', 'RouteDefinition', 'WhenDefinition', 'OtherwiseDefinition'].includes(props.step.dslName);
-    }
-
     function isWide(): boolean {
         return ['RouteConfigurationDefinition', 'RouteDefinition', 'ChoiceDefinition', 'SwitchDefinition', 'MulticastDefinition', 'TryDefinition', 'CircuitBreakerDefinition']
             .includes(props.step.dslName);
     }
 
-    function isAddStepButtonLeft(): boolean {
-        return ['MulticastDefinition']
-            .includes(props.step.dslName);
-    }
-
     function isHorizontal(): boolean {
         return ['MulticastDefinition'].includes(props.step.dslName);
     }
 
-    function isRoot(): boolean {
-        return ['RouteConfigurationDefinition', 'RouteDefinition'].includes(props.step?.dslName);
-    }
-
-    function isInStepWithChildren() {
-        const step: CamelElement = props.step;
-        const children = CamelDefinitionApiExt.getElementChildrenDefinition(step.dslName);
-        return children.filter((c: ChildElement) => c.name === 'steps' || c.multiple).length > 0 && props.inSteps;
-    }
-
     function getChildrenInfo(step: CamelElement): [boolean, number, boolean, number, number] {
         const children = CamelDefinitionApiExt.getElementChildrenDefinition(step.dslName);
         const hasStepsField = children.filter((c: ChildElement) => c.name === 'steps').length === 1;
@@ -178,12 +121,6 @@ export function DslElement(props: Props) {
         else return false;
     }
 
-    function hasBorderOverSteps(step: CamelElement) {
-        const [hasStepsField, stepsChildrenCount, hasNonStepsFields, nonStepChildrenCount] = getChildrenInfo(step);
-        if (hasStepsField && stepsChildrenCount > 0 && hasNonStepsFields && nonStepChildrenCount > 0) return true;
-        else return false;
-    }
-
     function getHeaderStyle() {
         const style: CSSProperties = {
             width: isWide() ? "100%" : "",
@@ -192,24 +129,6 @@ export function DslElement(props: Props) {
         return style;
     }
 
-    function sendButtonPosition(el: HTMLButtonElement | null) {
-        const {nextStep, step, parent} = props;
-        let needArrow = !hasBorder() && !['ChoiceDefinition', 'MulticastDefinition', 'TryDefinition'].includes(step.dslName);
-
-        if (parent
-            && ['TryDefinition'].includes(parent.dslName)
-            && !['CatchDefinition', 'FinallyDefinition'].includes(step.dslName)) {
-            needArrow = true;
-        }
-
-        if (el && nextStep && needArrow) {
-            const rect = headerRef.current?.getBoundingClientRect();
-
-            if (rect)
-                EventBus.sendButtonPosition("add", step.uuid, nextStep, rect);
-        }
-    }
-
     function sendPosition(el: HTMLDivElement | null) {
         const {step, prevStep, parent} = props;
         const isSelected = isElementSelected();
@@ -243,6 +162,30 @@ export function DslElement(props: Props) {
         [props.step.dslName]
     );
 
+    function hasElements(rc: RouteConfigurationDefinition): boolean {
+        return (rc.interceptFrom !== undefined && rc.interceptFrom.length > 0)
+    || (rc.intercept !== undefined && rc.intercept.length > 0)
+    || (rc.interceptSendToEndpoint !== undefined && rc.interceptSendToEndpoint.length > 0)
+    || (rc.onException !== undefined && rc.onException.length > 0)
+    || (rc.onCompletion !== undefined && rc.onCompletion.length > 0)
+    }
+
+    function getHeaderClasses(): string {
+        const classes: string[] = [];
+        const step: CamelElement = props.step;
+        if (step.dslName === 'RouteDefinition') {
+            classes.push(...'header-route', 'header-bottom-line')
+        } else if (step.dslName === 'RouteConfigurationDefinition') {
+            classes.push('header-route')
+            if (hasElements(step)) classes.push('header-bottom-line')
+        } else {
+            classes.push('header')
+        }
+        if (isElementSelected()) {
+            classes.push("selected")
+        }
+        return classes.join(" ");
+    }
 
     function getHeader() {
         const step: CamelElement = props.step;
@@ -252,10 +195,9 @@ export function DslElement(props: Props) {
         const showInsertButton =
             !['FromDefinition', 'RouteConfigurationDefinition', 'RouteDefinition', 'CatchDefinition', 'FinallyDefinition', 'WhenDefinition', 'OtherwiseDefinition'].includes(step.dslName)
             && !inRouteConfiguration;
-        const headerClass = ['RouteConfigurationDefinition', 'RouteDefinition'].includes(step.dslName) ? "header-route" : "header"
-        const headerClasses = isElementSelected() ? headerClass + " selected" : headerClass;
+        const headerClasses = getHeaderClasses();
         return (
-            <div className={"dsl-element " + headerClasses} style={getHeaderStyle()} ref={headerRef}>
+            <div className={"dsl-element " + headerClasses} style={getHeaderStyle()} ref={props.headerRef}>
                 {!['RouteConfigurationDefinition', 'RouteDefinition'].includes(props.step.dslName) &&
                     <div
                         ref={el => sendPosition(el)}
@@ -286,8 +228,8 @@ export function DslElement(props: Props) {
     }
 
     function getHeaderTextWithTooltip(step: CamelElement) {
-        const checkRequired = CamelUtil.checkRequired(step);
         const title = getHeaderText(step);
+        const checkRequired = CamelUtil.checkRequired(step);
         let className = hasWideChildrenElement() ? "text text-right" : "text text-bottom";
         if (!checkRequired[0]) className = className + " header-text-required";
         if (checkRequired[0]) {
@@ -304,7 +246,7 @@ export function DslElement(props: Props) {
         return (
             <>
                 {getHeader()}
-                <Tooltip triggerRef={headerRef} position={"left"} content={<div>{tooltip}</div>}/>
+                <Tooltip triggerRef={props.headerRef} position={"left"} content={<div>{tooltip}</div>}/>
             </>
 
         )
@@ -316,118 +258,6 @@ export function DslElement(props: Props) {
         return undefined;
     }
 
-    function getElementHeader() {
-        const tooltip = getHeaderTooltip();
-        if (tooltip !== undefined && !isDragging) {
-            return getHeaderWithTooltip(tooltip);
-        }
-        return getHeader();
-    }
-
-    function getChildrenStyle() {
-        const style: CSSProperties = {
-            display: "flex",
-            flexDirection: "row",
-        }
-        return style;
-    }
-
-    function getChildrenElementsStyle(child: ChildElement, notOnlySteps: boolean) {
-        const step = props.step;
-        const isBorder = child.name === 'steps' && hasBorderOverSteps(step);
-        const style: CSSProperties = {
-            // borderStyle: isBorder ? "dotted" : "none",
-            borderColor: "var(--step-border-color)",
-            borderWidth: "1px",
-            borderRadius: "16px",
-            display: isHorizontal() || child.name !== 'steps' ? "flex" : "block",
-            flexDirection: "row",
-        }
-        return style;
-    }
-
-    function getChildElements() {
-        const step: CamelElement = props.step;
-        let children: ChildElement[] = CamelDefinitionApiExt.getElementChildrenDefinition(step.dslName);
-        const notOnlySteps = children.filter(c => c.name === 'steps').length === 1
-            && children.filter(c => c.multiple && c.name !== 'steps').length > 0;
-
-        if (step.dslName !== 'RouteDefinition') {
-            children = children.filter(child => {
-                const cc = CamelDefinitionApiExt.getElementChildrenDefinition(child.className);
-                return child.name === 'steps' || cc.filter(c => c.multiple).length > 0;
-            })
-        }
-        if (step.dslName === 'CatchDefinition') { // exception
-            children = children.filter(value => value.name !== 'onWhen')
-        }
-        return (
-            <div key={step.uuid + "-children"} className="children" style={getChildrenStyle()}>
-                {children.map((child: ChildElement, index: number) => getChildDslElements(child, index, notOnlySteps))}
-            </div>
-        )
-    }
-
-    function getChildDslElements(child: ChildElement, index: number, notOnlySteps: boolean) {
-        const step = props.step;
-        const children: CamelElement[] = CamelDefinitionApiExt.getElementChildren(step, child);
-        if (children.length > 0) {
-            return (
-                <div className={child.name + " has-child"} style={getChildrenElementsStyle(child, notOnlySteps)}
-                     key={step.uuid + "-child-" + index}>
-                    {children.map((element, index) => {
-                            let prevStep = children.at(index - 1);
-                            let nextStep: CamelElement | undefined = undefined;
-                            if (['TryDefinition', 'ChoiceDefinition'].includes(step.dslName)) {
-                                nextStep = props.nextStep;
-                            } else {
-                                nextStep = children.at(index + 1);
-                            }
-                            return (<div key={step.uuid + child.className + index}>
-                                <DslElement
-                                    inSteps={child.name === 'steps'}
-                                    position={index}
-                                    step={element}
-                                    nextStep={nextStep}
-                                    prevStep={prevStep}
-                                    parent={step}/>
-                            </div>)
-                        }
-                    )}
-                    {child.name === 'steps' && getAddStepButton()}
-                </div>
-            )
-        } else if (child.name === 'steps') {
-            return (
-                <div className={child.name + " has-child"} style={getChildrenElementsStyle(child, notOnlySteps)}
-                     key={step.uuid + "-child-" + index}>
-                    {getAddStepButton()}
-                </div>
-            )
-        }
-    }
-
-    function getAddStepButton() {
-        const {step, nextStep} = props;
-        const hideAddButton = step.dslName === 'StepDefinition' && !CamelDisplayUtil.isStepDefinitionExpanded(integration, step.uuid, selectedUuids.at(0));
-        if (hideAddButton) return (<></>)
-        else return (
-            <div ref={addButtonRef}>
-                <Tooltip position={"bottom"}
-                         content={<div>{"Add step to " + CamelDisplayUtil.getTitle(step)}</div>}
-                >
-                    <button type="button"
-                            ref={el => sendButtonPosition(el)}
-                            aria-label="Add"
-                            onClick={e => onOpenSelector(e)}
-                            className={isAddStepButtonLeft() ? "add-button add-button-left" : "add-button add-button-bottom"}>
-                        <AddElementIcon/>
-                    </button>
-
-                </Tooltip>
-            </div>
-        )
-    }
 
     function getAddElementButton() {
         return (
@@ -467,57 +297,9 @@ export function DslElement(props: Props) {
         )
     }
 
-    const element: CamelElement = props.step;
-    const className = "step-element"
-        + (isElementSelected() ? " step-element-selected" : "") + (!props.step.showChildren ? " hidden-step" : "")
-        + ((element as any).disabled ? " disabled " : "");
-    return (
-        <div key={"root" + element.uuid}
-             className={className}
-             ref={el => sendPosition(el)}
-             style={{
-                 borderStyle: hasBorder() ? "dashed" : "none",
-                 borderColor: isElementSelected() ? "var(--step-border-color-selected)" : "var(--step-border-color)",
-                 marginTop: isInStepWithChildren() ? "16px" : "8px",
-                 zIndex: element.dslName === 'ToDefinition' ? 20 : 10,
-                 boxShadow: isDraggedOver ? "0px 0px 1px 2px var(--step-border-color-selected)" : "none",
-             }}
-             onMouseOver={event => event.stopPropagation()}
-             onClick={event => onSelectElement(event)}
-             onDragStart={event => {
-                 event.stopPropagation();
-                 event.dataTransfer.setData("text/plain", element.uuid);
-                 (event.target as any).style.opacity = .5;
-                 setIsDragging(true);
-             }}
-             onDragEnd={event => {
-                 (event.target as any).style.opacity = '';
-                 setIsDragging(false);
-             }}
-             onDragOver={event => {
-                 event.preventDefault();
-                 event.stopPropagation();
-                 if (element.dslName !== 'FromDefinition' && !isDragging) {
-                     setIsDraggedOver(true);
-                 }
-             }}
-             onDragEnter={event => {
-                 event.preventDefault();
-                 event.stopPropagation();
-                 if (element.dslName !== 'FromDefinition') {
-                     setIsDraggedOver(true);
-                 }
-             }}
-             onDragLeave={event => {
-                 event.preventDefault();
-                 event.stopPropagation();
-                 setIsDraggedOver(false);
-             }}
-             onDrop={event => dragElement(event, element)}
-             draggable={!isNotDraggable()}
-        >
-            {getElementHeader()}
-            {getChildElements()}
-        </div>
-    )
+    const tooltip = getHeaderTooltip();
+    if (tooltip !== undefined && !props.isDragging) {
+        return getHeaderWithTooltip(tooltip);
+    }
+    return getHeader();
 }
diff --git a/karavan-designer/src/designer/utils/CamelUi.tsx b/karavan-designer/src/designer/utils/CamelUi.tsx
index 61a7d27c..5caae0a7 100644
--- a/karavan-designer/src/designer/utils/CamelUi.tsx
+++ b/karavan-designer/src/designer/utils/CamelUi.tsx
@@ -337,7 +337,7 @@ export class CamelUi {
     static getElementTitle = (element: CamelElement): string => {
         if (element.dslName === 'RouteDefinition') {
             const routeId = (element as RouteDefinition).id
-            return routeId ? "Route: " + routeId : CamelUtil.capitalizeName((element as any).stepName);
+            return routeId ? routeId : CamelUtil.capitalizeName((element as any).stepName);
         } else if (['ToDefinition', 'ToDynamicDefinition', 'FromDefinition', 'KameletDefinition'].includes(element.dslName) && (element as any).uri) {
             const uri = (element as any).uri;
             const kameletTitle = uri && uri.startsWith("kamelet:") ? KameletApi.findKameletByUri(uri)?.title() : undefined;
@@ -787,4 +787,5 @@ export class CamelUi {
             .forEach((f: any) => result.push(f));
         return result;
     }
+
 }
\ No newline at end of file