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


The following commit(s) were added to refs/heads/main by this push:
     new a983bd1b Fix #1449
a983bd1b is described below

commit a983bd1b8a2c0ff64ed370d649a291e20ad16c78
Author: Marat Gubaidullin <ma...@talismancloud.io>
AuthorDate: Mon Oct 28 16:32:46 2024 -0400

    Fix #1449
---
 .../src/main/webui/src/designer/icons/EipIcons.tsx |   4 +-
 .../webui/src/designer/property/DslProperties.css  |  10 +-
 .../src/designer/property/PropertiesHeader.tsx     | 259 ++++++++++++---------
 .../src/designer/property/usePropertiesHook.tsx    |   1 +
 .../webui/src/designer/route/DslConnections.css    |   9 +
 .../webui/src/designer/route/DslConnections.tsx    |  34 +--
 .../src/designer/route/element/DslElement.css      |   4 +
 .../src/main/webui/src/designer/utils/CamelUi.tsx  |   4 +-
 karavan-core/src/core/api/CamelDisplayUtil.ts      |   4 +-
 karavan-core/src/core/api/CamelUtil.ts             |  23 +-
 karavan-designer/src/designer/icons/EipIcons.tsx   |   4 +-
 .../src/designer/property/DslProperties.css        |  10 +-
 .../src/designer/property/PropertiesHeader.tsx     | 259 ++++++++++++---------
 .../src/designer/property/usePropertiesHook.tsx    |   1 +
 .../src/designer/route/DslConnections.css          |   9 +
 .../src/designer/route/DslConnections.tsx          |  34 +--
 .../src/designer/route/element/DslElement.css      |   4 +
 karavan-designer/src/designer/utils/CamelUi.tsx    |   4 +-
 karavan-space/src/designer/icons/EipIcons.tsx      |   4 +-
 .../src/designer/property/DslProperties.css        |  10 +-
 .../src/designer/property/PropertiesHeader.tsx     | 259 ++++++++++++---------
 .../src/designer/property/usePropertiesHook.tsx    |   1 +
 .../src/designer/route/DslConnections.css          |   9 +
 .../src/designer/route/DslConnections.tsx          |  34 +--
 .../src/designer/route/element/DslElement.css      |   4 +
 karavan-space/src/designer/utils/CamelUi.tsx       |   4 +-
 26 files changed, 608 insertions(+), 394 deletions(-)

diff --git a/karavan-app/src/main/webui/src/designer/icons/EipIcons.tsx 
b/karavan-app/src/main/webui/src/designer/icons/EipIcons.tsx
index fc928d9f..4bdac684 100644
--- a/karavan-app/src/main/webui/src/designer/icons/EipIcons.tsx
+++ b/karavan-app/src/main/webui/src/designer/icons/EipIcons.tsx
@@ -50,14 +50,14 @@ export function AggregateIcon() {
     );
 }
 
-export function ToIcon() {
+export function ToIcon(classname: string = '') {
     return (
         <svg
             xmlns="http://www.w3.org/2000/svg";
             width={800}
             height={800}
             viewBox="0 0 32 32"
-            className="icon"
+            className={classname ? "icon " + classname : "icon"}
         >
             <path d="m12.103 11.923 2.58 2.59H2.513v2h12.17l-2.58 2.59 1.41 
1.41 5-5-5-5z"/>
             <path
diff --git a/karavan-app/src/main/webui/src/designer/property/DslProperties.css 
b/karavan-app/src/main/webui/src/designer/property/DslProperties.css
index 97b97a38..e2401cf3 100644
--- a/karavan-app/src/main/webui/src/designer/property/DslProperties.css
+++ b/karavan-app/src/main/webui/src/designer/property/DslProperties.css
@@ -24,14 +24,22 @@
     width: 100%;
     display: flex;
     flex-direction: row;
+    /*justify-content: space-between;*/
+    gap: 10px;
 }
 
 .karavan .properties .headers .top h1 {
-    width: 100%;
+    /*width: 100%;*/
     margin-top: auto;
     margin-bottom: auto;
+    text-wrap: nowrap;
+}
+
+.karavan .properties .headers .top .pf-v5-c-switch {
+    column-gap: 6px;
 }
 
+
 .karavan .properties .footer {
     height: 100%;
     display: contents;
diff --git 
a/karavan-app/src/main/webui/src/designer/property/PropertiesHeader.tsx 
b/karavan-app/src/main/webui/src/designer/property/PropertiesHeader.tsx
index b8aca6b4..00a3e1ee 100644
--- a/karavan-app/src/main/webui/src/designer/property/PropertiesHeader.tsx
+++ b/karavan-app/src/main/webui/src/designer/property/PropertiesHeader.tsx
@@ -25,13 +25,13 @@ import {
     MenuToggle,
     DropdownList,
     DropdownItem, Flex, Popover, FlexItem, Badge, ClipboardCopy,
-    Switch,
+    Switch, Radio, Tooltip,
 } from '@patternfly/react-core';
 import '../karavan.css';
 import './DslProperties.css';
 import "@patternfly/patternfly/patternfly.css";
 import {CamelUi} from "../utils/CamelUi";
-import {useDesignerStore, useSelectorStore} from "../DesignerStore";
+import {useDesignerStore} from "../DesignerStore";
 import {shallow} from "zustand/shallow";
 import {usePropertiesHook} from "./usePropertiesHook";
 import {CamelDisplayUtil} from "karavan-core/lib/api/CamelDisplayUtil";
@@ -56,7 +56,13 @@ export function PropertiesHeader(props: Props) {
     const [isHeadersExpanded, setIsHeadersExpanded] = useState<boolean>(false);
     const [isExchangePropertiesExpanded, setIsExchangePropertiesExpanded] = 
useState<boolean>(false);
     const [isMenuOpen, setMenuOpen] = useState<boolean>(false);
-    const [isStepTypeOpen, setIsStepTypeOpen] = React.useState(false);
+    const [stepIsPoll, setStepIsPoll] = React.useState(false);
+    const [stepDynamic, setStepDynamic] = React.useState(false);
+
+    useEffect(() => {
+        setStepDynamic(selectedStep?.dslName === 'ToDynamicDefinition')
+        setStepIsPoll(selectedStep?.dslName === 'PollDefinition')
+    }, [])
 
     useEffect(() => {
         setMenuOpen(false)
@@ -68,67 +74,70 @@ export function PropertiesHeader(props: Props) {
         const targetDslTitle = targetDsl?.replace("Definition", "");
         const showMenu = hasSteps || targetDsl !== undefined;
         return showMenu ?
-            <Dropdown
-                popperProps={{position: "end"}}
-                isOpen={isMenuOpen}
-                onSelect={() => {
-                }}
-                onOpenChange={(isOpen: boolean) => setMenuOpen(isOpen)}
-                toggle={(toggleRef: React.Ref<MenuToggleElement>) => (
-                    <MenuToggle
-                        className="header-menu-toggle"
-                        ref={toggleRef}
-                        aria-label="menu"
-                        variant="plain"
-                        onClick={() => setMenuOpen(!isMenuOpen)}
-                        isExpanded={isMenuOpen}
-                    >
-                        <EllipsisVIcon/>
-                    </MenuToggle>
-                )}
-            >
-                <DropdownList>
-                    {isFrom &&
-                        <DropdownItem key="changeFrom" onClick={(ev) => {
-                            ev.preventDefault()
-                            openSelectorToReplaceFrom((selectedStep as any).id)
-                            setMenuOpen(false);
-                        }}>
-                            Change From...
-                        </DropdownItem>}
-                    {hasSteps &&
-                        <DropdownItem key="saveStepsRoute" onClick={(ev) => {
-                            ev.preventDefault()
-                            if (selectedStep) {
-                                saveAsRoute(selectedStep, true);
-                                setMenuOpen(false);
-                            }
-                        }}>
-                            Save Steps to Route
-                        </DropdownItem>}
-                    {hasSteps && !isFrom &&
-                        <DropdownItem key="saveElementRoute" onClick={(ev) => {
-                            ev.preventDefault()
-                            if (selectedStep) {
-                                saveAsRoute(selectedStep, false);
+            <div style={{display: 'flex', flexDirection: 'row', 
justifyContent: 'end', width: '100%'}}>
+                <Dropdown
+                    popperProps={{position: "end"}}
+                    isOpen={isMenuOpen}
+                    onSelect={() => {
+                    }}
+                    onOpenChange={(isOpen: boolean) => setMenuOpen(isOpen)}
+                    toggle={(toggleRef: React.Ref<MenuToggleElement>) => (
+                        <MenuToggle
+                            className="header-menu-toggle"
+                            ref={toggleRef}
+                            aria-label="menu"
+                            variant="plain"
+                            onClick={() => setMenuOpen(!isMenuOpen)}
+                            isExpanded={isMenuOpen}
+                        >
+                            <EllipsisVIcon/>
+                        </MenuToggle>
+                    )}
+                >
+                    <DropdownList>
+                        {isFrom &&
+                            <DropdownItem key="changeFrom" onClick={(ev) => {
+                                ev.preventDefault()
+                                openSelectorToReplaceFrom((selectedStep as 
any).id)
                                 setMenuOpen(false);
-                            }
-                        }}>
-                            Save Element to Route
-                        </DropdownItem>}
-                    {targetDsl &&
-                        <DropdownItem key="convert"
-                                      onClick={(ev) => {
-                                          ev.preventDefault()
-                                          if (selectedStep) {
-                                              convertStep(selectedStep, 
targetDsl);
-                                              setMenuOpen(false);
-                                          }
-                                      }}>
-                            Convert to {targetDslTitle}
-                        </DropdownItem>}
-                </DropdownList>
-            </Dropdown> : <></>;
+                            }}>
+                                Change From...
+                            </DropdownItem>}
+                        {hasSteps &&
+                            <DropdownItem key="saveStepsRoute" onClick={(ev) 
=> {
+                                ev.preventDefault()
+                                if (selectedStep) {
+                                    saveAsRoute(selectedStep, true);
+                                    setMenuOpen(false);
+                                }
+                            }}>
+                                Save Steps to Route
+                            </DropdownItem>}
+                        {hasSteps && !isFrom &&
+                            <DropdownItem key="saveElementRoute" onClick={(ev) 
=> {
+                                ev.preventDefault()
+                                if (selectedStep) {
+                                    saveAsRoute(selectedStep, false);
+                                    setMenuOpen(false);
+                                }
+                            }}>
+                                Save Element to Route
+                            </DropdownItem>}
+                        {targetDsl &&
+                            <DropdownItem key="convert"
+                                          onClick={(ev) => {
+                                              ev.preventDefault()
+                                              if (selectedStep) {
+                                                  convertStep(selectedStep, 
targetDsl);
+                                                  setMenuOpen(false);
+                                              }
+                                          }}>
+                                Convert to {targetDslTitle}
+                            </DropdownItem>}
+                    </DropdownList>
+                </Dropdown>
+            </div>
+            : <></>;
     }
 
     function getExchangePropertiesSection(): React.JSX.Element {
@@ -138,35 +147,35 @@ export function PropertiesHeader(props: Props) {
                                isExpanded={isExchangePropertiesExpanded}>
                 <Flex className='component-headers' direction={{default: 
"column"}}>
                     {exchangeProperties.map((header, index, array) =>
-                            <Flex key={index}>
-                                <ClipboardCopy key={index} hoverTip="Copy" 
clickTip="Copied" variant="inline-compact"
-                                               isCode>
-                                    {header.name}
-                                </ClipboardCopy>
-                                <FlexItem align={{default: 'alignRight'}}>
-                                    <Popover
-                                        position={"left"}
-                                        headerContent={header.name}
-                                        bodyContent={header.description}
-                                        footerContent={
-                                            <Flex>
-                                                <Text 
component={TextVariants.p}>{header.javaType}</Text>
-                                                <FlexItem align={{default: 
'alignRight'}}>
-                                                    <Badge 
isRead>{header.label}</Badge>
-                                                </FlexItem>
-                                            </Flex>
-                                        }
-                                    >
-                                        <button type="button" aria-label="More 
info" onClick={e => {
-                                            e.preventDefault();
-                                            e.stopPropagation();
-                                        }} 
className="pf-v5-c-form__group-label-help">
-                                            <HelpIcon/>
-                                        </button>
-                                    </Popover>
-                                </FlexItem>
-                            </Flex>
-                        )}
+                        <Flex key={index}>
+                            <ClipboardCopy key={index} hoverTip="Copy" 
clickTip="Copied" variant="inline-compact"
+                                           isCode>
+                                {header.name}
+                            </ClipboardCopy>
+                            <FlexItem align={{default: 'alignRight'}}>
+                                <Popover
+                                    position={"left"}
+                                    headerContent={header.name}
+                                    bodyContent={header.description}
+                                    footerContent={
+                                        <Flex>
+                                            <Text 
component={TextVariants.p}>{header.javaType}</Text>
+                                            <FlexItem align={{default: 
'alignRight'}}>
+                                                <Badge 
isRead>{header.label}</Badge>
+                                            </FlexItem>
+                                        </Flex>
+                                    }
+                                >
+                                    <button type="button" aria-label="More 
info" onClick={e => {
+                                        e.preventDefault();
+                                        e.stopPropagation();
+                                    }} 
className="pf-v5-c-form__group-label-help">
+                                        <HelpIcon/>
+                                    </button>
+                                </Popover>
+                            </FlexItem>
+                        </Flex>
+                    )}
                 </Flex>
             </ExpandableSection>
         )
@@ -235,24 +244,58 @@ export function PropertiesHeader(props: Props) {
     const component = ComponentApi.findStepComponent(selectedStep);
     const groups = (isFrom || isPoll) ? ['consumer', 'common'] : ['producer', 
'common'];
     const isKamelet = CamelUi.isKamelet(selectedStep);
-    const isStepComponent = !isFrom && selectedStep !== undefined && 
!isKamelet && ['ToDefinition', 
'PollDefinition'].includes(selectedStep?.dslName);
+    const isStepComponent = !isFrom && selectedStep !== undefined && 
!isKamelet && ['ToDefinition', 'PollDefinition', 
'ToDynamicDefinition'].includes(selectedStep?.dslName);
+
+    function changeStepType(poll: boolean, dynamic: boolean) {
+        if (selectedStep) {
+            if  (poll) {
+                convertStep(selectedStep, 'PollDefinition');
+                setStepIsPoll(true);
+                setStepDynamic(false);
+            } else if (dynamic) {
+                convertStep(selectedStep, 'ToDynamicDefinition');
+                setStepIsPoll(false);
+                setStepDynamic(true);
+            } else {
+                convertStep(selectedStep, 'ToDefinition');
+                setStepIsPoll(false);
+                setStepDynamic(false);
+            }
+        }
+    }
 
     function getComponentStepTypeSwitch() {
-        return (component?.component.producerOnly
-            ? <></>
-            : <Switch
-                id="step-type-switch"
-                label="Poll"
-                isChecked={isStepTypeOpen}
-                onChange={(event, checked) => {
-                    if (selectedStep) {
-                        convertStep(selectedStep, checked ? 'PollDefinition' : 
'ToDefinition');
-                        setIsStepTypeOpen(checked);
-                    }
-                }}
-                ouiaId="step-type-switch"
-                isReversed
-            />
+        const pollSupported = !component?.component.producerOnly;
+        return (<div style={{display: 'flex', flexDirection: 'row', 
justifyContent: 'end', width: '100%', gap: '10px'}}>
+                <Tooltip content='Send messages to a dynamic endpoint 
evaluated on-demand' position='top-end'>
+                    <Switch
+                        id="step-type-dynamic"
+                        label="Dynamic"
+                        isChecked={stepDynamic}
+                        onChange={(event, checked) => {
+                            changeStepType(stepIsPoll, checked)
+                        }}
+                        ouiaId="step-type-switch"
+                        isDisabled={stepIsPoll}
+                        isReversed
+                    />
+                </Tooltip>
+                {pollSupported &&
+                    <Tooltip content='Simple Polling Consumer to obtain the 
additional data' position='top-end'>
+                        <Switch
+                            id="step-type-poll"
+                            label="Poll"
+                            isChecked={stepIsPoll}
+                            onChange={(event, checked) => {
+                                changeStepType(checked, stepDynamic)
+                            }}
+                            ouiaId="step-type-switch"
+                            isDisabled={stepDynamic}
+                            isReversed
+                        />
+                    </Tooltip>
+                }
+            </div>
         )
     }
 
diff --git 
a/karavan-app/src/main/webui/src/designer/property/usePropertiesHook.tsx 
b/karavan-app/src/main/webui/src/designer/property/usePropertiesHook.tsx
index 2d806c0d..5c8e38b4 100644
--- a/karavan-app/src/main/webui/src/designer/property/usePropertiesHook.tsx
+++ b/karavan-app/src/main/webui/src/designer/property/usePropertiesHook.tsx
@@ -177,6 +177,7 @@ export function usePropertiesHook(designerType: 'routes' | 
'rest' | 'beans' = 'r
     }
 
     const convertStep = (step: CamelElement, targetDslName: string) => {
+        console.log(targetDslName)
         try {
             // setSelectedStep(undefined);
             if (targetDslName === 'ChoiceDefinition' && step.dslName === 
'FilterDefinition') {
diff --git a/karavan-app/src/main/webui/src/designer/route/DslConnections.css 
b/karavan-app/src/main/webui/src/designer/route/DslConnections.css
index 03da5f2a..a75582ea 100644
--- a/karavan-app/src/main/webui/src/designer/route/DslConnections.css
+++ b/karavan-app/src/main/webui/src/designer/route/DslConnections.css
@@ -54,6 +54,15 @@
     fill: transparent;
 }
 
+.karavan .dsl-page .graph .connections .path-dynamic {
+    stroke-dasharray: 5;
+    -webkit-animation: dashdrawR 0.5s linear infinite;
+    animation: dashdrawR 0.5s linear infinite;
+    stroke: var(--pf-v5-global--Color--200);
+    stroke-width: 1;
+    fill: transparent;
+}
+
 .karavan .dsl-page .graph .connections .path-poll {
     stroke-dasharray: 5;
     -webkit-animation: dashdrawL 0.5s linear infinite;
diff --git a/karavan-app/src/main/webui/src/designer/route/DslConnections.tsx 
b/karavan-app/src/main/webui/src/designer/route/DslConnections.tsx
index 99fd0934..be404896 100644
--- a/karavan-app/src/main/webui/src/designer/route/DslConnections.tsx
+++ b/karavan-app/src/main/webui/src/designer/route/DslConnections.tsx
@@ -33,6 +33,7 @@ import {INTERNAL_COMPONENTS} from 
"karavan-core/lib/api/ComponentApi";
 const overlapGap: number = 40;
 const DIAMETER: number = 34;
 const RADIUS: number = DIAMETER / 2;
+type ConnectionType =  'internal' | 'remote' | 'nav' | 'poll' | 'dynamic';
 
 export function DslConnections() {
 
@@ -83,10 +84,12 @@ export function DslConnections() {
         }
     }
 
-    function getElementType(element: CamelElement): 'internal' | 'remote' | 
'nav' | 'poll' {
+    function getElementType(element: CamelElement): ConnectionType {
         const uri = (element as any).uri;
         if (element.dslName === 'PollDefinition') {
             return 'poll';
+        } else if (element.dslName === 'ToDynamicDefinition') {
+            return 'dynamic';
         } else if (INTERNAL_COMPONENTS.includes((uri))) {
             return 'nav';
         } else {
@@ -95,8 +98,8 @@ export function DslConnections() {
         }
     }
 
-    function getIncomings(): [string, number, 'internal' | 'remote' | 'nav' | 
'poll'][] {
-        let outs: [string, number, 'internal' | 'remote' | 'nav' | 'poll'][] = 
Array.from(steps.values())
+    function getIncomings(): [string, number, ConnectionType][] {
+        let outs: [string, number, ConnectionType][] = 
Array.from(steps.values())
             .filter(pos => ["FromDefinition"].includes(pos.step.dslName))
             .filter(pos => !(pos.step.dslName === 'FromDefinition' && 
(pos.step as any).uri === 'kamelet:source'))
             .sort((pos1: DslPosition, pos2: DslPosition) => {
@@ -111,7 +114,7 @@ export function DslConnections() {
         return outs;
     }
 
-    function getIncoming(data: [string, number, 'internal' | 'remote' | 'nav' 
| 'poll']) {
+    function getIncoming(data: [string, number, ConnectionType]) {
         const pos = steps.get(data[0]);
         if (pos) {
             const fromX = pos.headerRect.x + pos.headerRect.width / 2 - left;
@@ -144,7 +147,7 @@ export function DslConnections() {
     //         .filter(s =>  (s.step as any)?.parameters?.name === name)
     // }
 
-    function getIncomingIcons(data: [string, number, 'internal' | 'remote' | 
'nav' | 'poll']) {
+    function getIncomingIcons(data: [string, number, ConnectionType]) {
         const pos = steps.get(data[0]);
         if (pos) {
             const step = (pos.step as any);
@@ -186,7 +189,7 @@ export function DslConnections() {
         }
     }
 
-    function hasOverlap(data: [string, number, 'internal' | 'remote' | 'nav' | 
'poll'][]): boolean {
+    function hasOverlap(data: [string, number, ConnectionType][]): boolean {
         let result = false;
         data.forEach((d, i, arr) => {
             if (i > 0 && d[1] - arr[i - 1][1] < overlapGap) result = true;
@@ -194,8 +197,8 @@ export function DslConnections() {
         return result;
     }
 
-    function addGap(data: [string, number, 'internal' | 'remote' | 'nav' | 
'poll'][]): [string, number, 'internal' | 'remote' | 'nav' | 'poll'][] {
-        const result: [string, number, 'internal' | 'remote' | 'nav' | 
'poll'][] = [];
+    function addGap(data: [string, number, ConnectionType][]): [string, 
number, ConnectionType][] {
+        const result: [string, number, ConnectionType][] = [];
         data.forEach((d, i, arr) => {
             if (i > 0 && d[1] - arr[i - 1][1] < overlapGap) result.push([d[0], 
d[1] + overlapGap, d[2]])
             else result.push(d);
@@ -204,12 +207,12 @@ export function DslConnections() {
     }
 
 
-    function getOutgoings(): [string, number, 'internal' | 'remote' | 'nav' | 
'poll'][] {
+    function getOutgoings(): [string, number, ConnectionType][] {
         const outgoingDefinitions = TopologyUtils.getOutgoingDefinitions();
-        let outs: [string, number, 'internal' | 'remote' | 'nav' | 'poll'][] = 
Array.from(steps.values())
+        let outs: [string, number, ConnectionType][] = 
Array.from(steps.values())
             .filter(pos => outgoingDefinitions.includes(pos.step.dslName))
             .filter(pos => pos.step.dslName !== 'KameletDefinition' || 
(pos.step.dslName === 'KameletDefinition' && 
!CamelUi.isActionKamelet(pos.step)))
-            .filter(pos => ['ToDefinition', 
'PollDefinition'].includes(pos.step.dslName) && 
!CamelUi.isActionKamelet(pos.step))
+            .filter(pos => ['ToDefinition', 'PollDefinition', 
"ToDynamicDefinition"].includes(pos.step.dslName) && 
!CamelUi.isActionKamelet(pos.step))
             .filter(pos => !CamelUi.isKameletSink(pos.step))
             .sort((pos1: DslPosition, pos2: DslPosition) => {
                 const y1 = pos1.headerRect.y + pos1.headerRect.height / 2;
@@ -223,11 +226,12 @@ export function DslConnections() {
         return outs;
     }
 
-    function getOutgoing(data: [string, number, 'internal' | 'remote' | 'nav' 
| 'poll']) {
+    function getOutgoing(data: [string, number, ConnectionType]) {
         const pos = steps.get(data[0]);
         const isInternal = data[2] === 'internal';
         const isNav = data[2] === 'nav';
         const isPoll = data[2] === 'poll';
+        const isDynamic = data[2] === 'dynamic';
         if (pos) {
             const fromX = pos.headerRect.x + pos.headerRect.width / 2 - left;
             const fromY = pos.headerRect.y + pos.headerRect.height / 2 - top;
@@ -244,7 +248,9 @@ export function DslConnections() {
             const lineXi = lineX1 + 40;
             const lineYi = lineY2;
 
-            const className = isNav ? 'path-incoming-nav' : (isPoll ? 
'path-poll' : 'path-incoming')
+            const className = isNav
+                ? 'path-incoming-nav'
+                : (isPoll ? 'path-poll' : (isDynamic ? 'path-dynamic' 
:'path-incoming'))
 
             return (!isInternal
                     ? <g key={pos.step.uuid + "-outgoing"}>
@@ -258,7 +264,7 @@ export function DslConnections() {
         }
     }
 
-    function getOutgoingIcons(data: [string, number, 'internal' | 'remote' | 
'nav' | 'poll']) {
+    function getOutgoingIcons(data: [string, number, ConnectionType]) {
         const pos = steps.get(data[0]);
         if (pos) {
             const step = (pos.step as any);
diff --git 
a/karavan-app/src/main/webui/src/designer/route/element/DslElement.css 
b/karavan-app/src/main/webui/src/designer/route/element/DslElement.css
index 785f667b..1b431837 100644
--- a/karavan-app/src/main/webui/src/designer/route/element/DslElement.css
+++ b/karavan-app/src/main/webui/src/designer/route/element/DslElement.css
@@ -128,6 +128,10 @@
     border-radius: 33px;
 }
 
+.karavan .step-element .header-icon-circle .dynamic{
+    fill: var(--pf-v5-global--Color--400);
+}
+
 .karavan .step-element .header-icon-square {
     border-radius: 33px;
 }
diff --git a/karavan-app/src/main/webui/src/designer/utils/CamelUi.tsx 
b/karavan-app/src/main/webui/src/designer/utils/CamelUi.tsx
index 045b154d..646f5ed9 100644
--- a/karavan-app/src/main/webui/src/designer/utils/CamelUi.tsx
+++ b/karavan-app/src/main/webui/src/designer/utils/CamelUi.tsx
@@ -728,7 +728,9 @@ export class CamelUi {
             case 'AggregateDefinition':
                 return <AggregateIcon/>;
             case 'ToDefinition':
-                return <ToIcon/>;
+                return ToIcon();
+            case 'ToDynamicDefinition':
+                return ToIcon('dynamic');
             case 'PollDefinition':
                 return <PollIcon/>;
             case 'ChoiceDefinition' :
diff --git a/karavan-core/src/core/api/CamelDisplayUtil.ts 
b/karavan-core/src/core/api/CamelDisplayUtil.ts
index d2078144..e103435b 100644
--- a/karavan-core/src/core/api/CamelDisplayUtil.ts
+++ b/karavan-core/src/core/api/CamelDisplayUtil.ts
@@ -33,7 +33,7 @@ export class CamelDisplayUtil {
         } else if (element.dslName === 'RouteDefinition') {
             const routeId = (element as RouteDefinition).id
             return routeId ? routeId : CamelUtil.capitalizeName((element as 
any).stepName);
-        } else if ((element as any).uri && (['ToDefinition', 'FromDefinition', 
'PollDefinition'].includes(element.dslName))) {
+        } else if ((element as any).uri && (['ToDefinition', 'FromDefinition', 
'PollDefinition', 'ToDynamicDefinition'].includes(element.dslName))) {
             const uri = (element as any).uri
             return ComponentApi.getComponentTitleFromUri(uri) || '';
         } else {
@@ -46,7 +46,7 @@ export class CamelDisplayUtil {
         const kamelet: KameletModel | undefined = 
CamelUtil.getKamelet(element);
         if (kamelet) {
             return kamelet.spec.definition.description;
-        } else if ((element as any).uri && (['ToDefinition', 'FromDefinition', 
'PollDefinition'].includes(element.dslName))) {
+        } else if ((element as any).uri && (['ToDefinition', 'FromDefinition', 
'PollDefinition', 'ToDynamicDefinition'].includes(element.dslName))) {
             const uri = (element as any).uri
             return ComponentApi.getComponentDescriptionFromUri(uri) || '';
         } else {
diff --git a/karavan-core/src/core/api/CamelUtil.ts 
b/karavan-core/src/core/api/CamelUtil.ts
index 993bb306..5ee687a1 100644
--- a/karavan-core/src/core/api/CamelUtil.ts
+++ b/karavan-core/src/core/api/CamelUtil.ts
@@ -182,21 +182,16 @@ export class CamelUtil {
         const uri: string = (element as any).uri;
         const name = ComponentApi.getComponentNameFromUri(uri);
 
-        if (dslName === 'ToDynamicDefinition') {
-            const component = ComponentApi.findByName(dslName);
-            return component ? 
ComponentApi.getComponentProperties(component?.component.name, 'producer') : [];
+        if (name) {
+            const component = ComponentApi.findByName(name);
+            return component
+                ? ComponentApi.getComponentProperties(
+                    component?.component.name,
+                    element.dslName === 'FromDefinition' ? 'consumer' : 
'producer',
+                )
+                : [];
         } else {
-            if (name) {
-                const component = ComponentApi.findByName(name);
-                return component
-                    ? ComponentApi.getComponentProperties(
-                        component?.component.name,
-                        element.dslName === 'FromDefinition' ? 'consumer' : 
'producer',
-                    )
-                    : [];
-            } else {
-                return [];
-            }
+            return [];
         }
     };
 
diff --git a/karavan-designer/src/designer/icons/EipIcons.tsx 
b/karavan-designer/src/designer/icons/EipIcons.tsx
index fc928d9f..4bdac684 100644
--- a/karavan-designer/src/designer/icons/EipIcons.tsx
+++ b/karavan-designer/src/designer/icons/EipIcons.tsx
@@ -50,14 +50,14 @@ export function AggregateIcon() {
     );
 }
 
-export function ToIcon() {
+export function ToIcon(classname: string = '') {
     return (
         <svg
             xmlns="http://www.w3.org/2000/svg";
             width={800}
             height={800}
             viewBox="0 0 32 32"
-            className="icon"
+            className={classname ? "icon " + classname : "icon"}
         >
             <path d="m12.103 11.923 2.58 2.59H2.513v2h12.17l-2.58 2.59 1.41 
1.41 5-5-5-5z"/>
             <path
diff --git a/karavan-designer/src/designer/property/DslProperties.css 
b/karavan-designer/src/designer/property/DslProperties.css
index 97b97a38..e2401cf3 100644
--- a/karavan-designer/src/designer/property/DslProperties.css
+++ b/karavan-designer/src/designer/property/DslProperties.css
@@ -24,14 +24,22 @@
     width: 100%;
     display: flex;
     flex-direction: row;
+    /*justify-content: space-between;*/
+    gap: 10px;
 }
 
 .karavan .properties .headers .top h1 {
-    width: 100%;
+    /*width: 100%;*/
     margin-top: auto;
     margin-bottom: auto;
+    text-wrap: nowrap;
+}
+
+.karavan .properties .headers .top .pf-v5-c-switch {
+    column-gap: 6px;
 }
 
+
 .karavan .properties .footer {
     height: 100%;
     display: contents;
diff --git a/karavan-designer/src/designer/property/PropertiesHeader.tsx 
b/karavan-designer/src/designer/property/PropertiesHeader.tsx
index b8aca6b4..00a3e1ee 100644
--- a/karavan-designer/src/designer/property/PropertiesHeader.tsx
+++ b/karavan-designer/src/designer/property/PropertiesHeader.tsx
@@ -25,13 +25,13 @@ import {
     MenuToggle,
     DropdownList,
     DropdownItem, Flex, Popover, FlexItem, Badge, ClipboardCopy,
-    Switch,
+    Switch, Radio, Tooltip,
 } from '@patternfly/react-core';
 import '../karavan.css';
 import './DslProperties.css';
 import "@patternfly/patternfly/patternfly.css";
 import {CamelUi} from "../utils/CamelUi";
-import {useDesignerStore, useSelectorStore} from "../DesignerStore";
+import {useDesignerStore} from "../DesignerStore";
 import {shallow} from "zustand/shallow";
 import {usePropertiesHook} from "./usePropertiesHook";
 import {CamelDisplayUtil} from "karavan-core/lib/api/CamelDisplayUtil";
@@ -56,7 +56,13 @@ export function PropertiesHeader(props: Props) {
     const [isHeadersExpanded, setIsHeadersExpanded] = useState<boolean>(false);
     const [isExchangePropertiesExpanded, setIsExchangePropertiesExpanded] = 
useState<boolean>(false);
     const [isMenuOpen, setMenuOpen] = useState<boolean>(false);
-    const [isStepTypeOpen, setIsStepTypeOpen] = React.useState(false);
+    const [stepIsPoll, setStepIsPoll] = React.useState(false);
+    const [stepDynamic, setStepDynamic] = React.useState(false);
+
+    useEffect(() => {
+        setStepDynamic(selectedStep?.dslName === 'ToDynamicDefinition')
+        setStepIsPoll(selectedStep?.dslName === 'PollDefinition')
+    }, [])
 
     useEffect(() => {
         setMenuOpen(false)
@@ -68,67 +74,70 @@ export function PropertiesHeader(props: Props) {
         const targetDslTitle = targetDsl?.replace("Definition", "");
         const showMenu = hasSteps || targetDsl !== undefined;
         return showMenu ?
-            <Dropdown
-                popperProps={{position: "end"}}
-                isOpen={isMenuOpen}
-                onSelect={() => {
-                }}
-                onOpenChange={(isOpen: boolean) => setMenuOpen(isOpen)}
-                toggle={(toggleRef: React.Ref<MenuToggleElement>) => (
-                    <MenuToggle
-                        className="header-menu-toggle"
-                        ref={toggleRef}
-                        aria-label="menu"
-                        variant="plain"
-                        onClick={() => setMenuOpen(!isMenuOpen)}
-                        isExpanded={isMenuOpen}
-                    >
-                        <EllipsisVIcon/>
-                    </MenuToggle>
-                )}
-            >
-                <DropdownList>
-                    {isFrom &&
-                        <DropdownItem key="changeFrom" onClick={(ev) => {
-                            ev.preventDefault()
-                            openSelectorToReplaceFrom((selectedStep as any).id)
-                            setMenuOpen(false);
-                        }}>
-                            Change From...
-                        </DropdownItem>}
-                    {hasSteps &&
-                        <DropdownItem key="saveStepsRoute" onClick={(ev) => {
-                            ev.preventDefault()
-                            if (selectedStep) {
-                                saveAsRoute(selectedStep, true);
-                                setMenuOpen(false);
-                            }
-                        }}>
-                            Save Steps to Route
-                        </DropdownItem>}
-                    {hasSteps && !isFrom &&
-                        <DropdownItem key="saveElementRoute" onClick={(ev) => {
-                            ev.preventDefault()
-                            if (selectedStep) {
-                                saveAsRoute(selectedStep, false);
+            <div style={{display: 'flex', flexDirection: 'row', 
justifyContent: 'end', width: '100%'}}>
+                <Dropdown
+                    popperProps={{position: "end"}}
+                    isOpen={isMenuOpen}
+                    onSelect={() => {
+                    }}
+                    onOpenChange={(isOpen: boolean) => setMenuOpen(isOpen)}
+                    toggle={(toggleRef: React.Ref<MenuToggleElement>) => (
+                        <MenuToggle
+                            className="header-menu-toggle"
+                            ref={toggleRef}
+                            aria-label="menu"
+                            variant="plain"
+                            onClick={() => setMenuOpen(!isMenuOpen)}
+                            isExpanded={isMenuOpen}
+                        >
+                            <EllipsisVIcon/>
+                        </MenuToggle>
+                    )}
+                >
+                    <DropdownList>
+                        {isFrom &&
+                            <DropdownItem key="changeFrom" onClick={(ev) => {
+                                ev.preventDefault()
+                                openSelectorToReplaceFrom((selectedStep as 
any).id)
                                 setMenuOpen(false);
-                            }
-                        }}>
-                            Save Element to Route
-                        </DropdownItem>}
-                    {targetDsl &&
-                        <DropdownItem key="convert"
-                                      onClick={(ev) => {
-                                          ev.preventDefault()
-                                          if (selectedStep) {
-                                              convertStep(selectedStep, 
targetDsl);
-                                              setMenuOpen(false);
-                                          }
-                                      }}>
-                            Convert to {targetDslTitle}
-                        </DropdownItem>}
-                </DropdownList>
-            </Dropdown> : <></>;
+                            }}>
+                                Change From...
+                            </DropdownItem>}
+                        {hasSteps &&
+                            <DropdownItem key="saveStepsRoute" onClick={(ev) 
=> {
+                                ev.preventDefault()
+                                if (selectedStep) {
+                                    saveAsRoute(selectedStep, true);
+                                    setMenuOpen(false);
+                                }
+                            }}>
+                                Save Steps to Route
+                            </DropdownItem>}
+                        {hasSteps && !isFrom &&
+                            <DropdownItem key="saveElementRoute" onClick={(ev) 
=> {
+                                ev.preventDefault()
+                                if (selectedStep) {
+                                    saveAsRoute(selectedStep, false);
+                                    setMenuOpen(false);
+                                }
+                            }}>
+                                Save Element to Route
+                            </DropdownItem>}
+                        {targetDsl &&
+                            <DropdownItem key="convert"
+                                          onClick={(ev) => {
+                                              ev.preventDefault()
+                                              if (selectedStep) {
+                                                  convertStep(selectedStep, 
targetDsl);
+                                                  setMenuOpen(false);
+                                              }
+                                          }}>
+                                Convert to {targetDslTitle}
+                            </DropdownItem>}
+                    </DropdownList>
+                </Dropdown>
+            </div>
+            : <></>;
     }
 
     function getExchangePropertiesSection(): React.JSX.Element {
@@ -138,35 +147,35 @@ export function PropertiesHeader(props: Props) {
                                isExpanded={isExchangePropertiesExpanded}>
                 <Flex className='component-headers' direction={{default: 
"column"}}>
                     {exchangeProperties.map((header, index, array) =>
-                            <Flex key={index}>
-                                <ClipboardCopy key={index} hoverTip="Copy" 
clickTip="Copied" variant="inline-compact"
-                                               isCode>
-                                    {header.name}
-                                </ClipboardCopy>
-                                <FlexItem align={{default: 'alignRight'}}>
-                                    <Popover
-                                        position={"left"}
-                                        headerContent={header.name}
-                                        bodyContent={header.description}
-                                        footerContent={
-                                            <Flex>
-                                                <Text 
component={TextVariants.p}>{header.javaType}</Text>
-                                                <FlexItem align={{default: 
'alignRight'}}>
-                                                    <Badge 
isRead>{header.label}</Badge>
-                                                </FlexItem>
-                                            </Flex>
-                                        }
-                                    >
-                                        <button type="button" aria-label="More 
info" onClick={e => {
-                                            e.preventDefault();
-                                            e.stopPropagation();
-                                        }} 
className="pf-v5-c-form__group-label-help">
-                                            <HelpIcon/>
-                                        </button>
-                                    </Popover>
-                                </FlexItem>
-                            </Flex>
-                        )}
+                        <Flex key={index}>
+                            <ClipboardCopy key={index} hoverTip="Copy" 
clickTip="Copied" variant="inline-compact"
+                                           isCode>
+                                {header.name}
+                            </ClipboardCopy>
+                            <FlexItem align={{default: 'alignRight'}}>
+                                <Popover
+                                    position={"left"}
+                                    headerContent={header.name}
+                                    bodyContent={header.description}
+                                    footerContent={
+                                        <Flex>
+                                            <Text 
component={TextVariants.p}>{header.javaType}</Text>
+                                            <FlexItem align={{default: 
'alignRight'}}>
+                                                <Badge 
isRead>{header.label}</Badge>
+                                            </FlexItem>
+                                        </Flex>
+                                    }
+                                >
+                                    <button type="button" aria-label="More 
info" onClick={e => {
+                                        e.preventDefault();
+                                        e.stopPropagation();
+                                    }} 
className="pf-v5-c-form__group-label-help">
+                                        <HelpIcon/>
+                                    </button>
+                                </Popover>
+                            </FlexItem>
+                        </Flex>
+                    )}
                 </Flex>
             </ExpandableSection>
         )
@@ -235,24 +244,58 @@ export function PropertiesHeader(props: Props) {
     const component = ComponentApi.findStepComponent(selectedStep);
     const groups = (isFrom || isPoll) ? ['consumer', 'common'] : ['producer', 
'common'];
     const isKamelet = CamelUi.isKamelet(selectedStep);
-    const isStepComponent = !isFrom && selectedStep !== undefined && 
!isKamelet && ['ToDefinition', 
'PollDefinition'].includes(selectedStep?.dslName);
+    const isStepComponent = !isFrom && selectedStep !== undefined && 
!isKamelet && ['ToDefinition', 'PollDefinition', 
'ToDynamicDefinition'].includes(selectedStep?.dslName);
+
+    function changeStepType(poll: boolean, dynamic: boolean) {
+        if (selectedStep) {
+            if  (poll) {
+                convertStep(selectedStep, 'PollDefinition');
+                setStepIsPoll(true);
+                setStepDynamic(false);
+            } else if (dynamic) {
+                convertStep(selectedStep, 'ToDynamicDefinition');
+                setStepIsPoll(false);
+                setStepDynamic(true);
+            } else {
+                convertStep(selectedStep, 'ToDefinition');
+                setStepIsPoll(false);
+                setStepDynamic(false);
+            }
+        }
+    }
 
     function getComponentStepTypeSwitch() {
-        return (component?.component.producerOnly
-            ? <></>
-            : <Switch
-                id="step-type-switch"
-                label="Poll"
-                isChecked={isStepTypeOpen}
-                onChange={(event, checked) => {
-                    if (selectedStep) {
-                        convertStep(selectedStep, checked ? 'PollDefinition' : 
'ToDefinition');
-                        setIsStepTypeOpen(checked);
-                    }
-                }}
-                ouiaId="step-type-switch"
-                isReversed
-            />
+        const pollSupported = !component?.component.producerOnly;
+        return (<div style={{display: 'flex', flexDirection: 'row', 
justifyContent: 'end', width: '100%', gap: '10px'}}>
+                <Tooltip content='Send messages to a dynamic endpoint 
evaluated on-demand' position='top-end'>
+                    <Switch
+                        id="step-type-dynamic"
+                        label="Dynamic"
+                        isChecked={stepDynamic}
+                        onChange={(event, checked) => {
+                            changeStepType(stepIsPoll, checked)
+                        }}
+                        ouiaId="step-type-switch"
+                        isDisabled={stepIsPoll}
+                        isReversed
+                    />
+                </Tooltip>
+                {pollSupported &&
+                    <Tooltip content='Simple Polling Consumer to obtain the 
additional data' position='top-end'>
+                        <Switch
+                            id="step-type-poll"
+                            label="Poll"
+                            isChecked={stepIsPoll}
+                            onChange={(event, checked) => {
+                                changeStepType(checked, stepDynamic)
+                            }}
+                            ouiaId="step-type-switch"
+                            isDisabled={stepDynamic}
+                            isReversed
+                        />
+                    </Tooltip>
+                }
+            </div>
         )
     }
 
diff --git a/karavan-designer/src/designer/property/usePropertiesHook.tsx 
b/karavan-designer/src/designer/property/usePropertiesHook.tsx
index 2d806c0d..5c8e38b4 100644
--- a/karavan-designer/src/designer/property/usePropertiesHook.tsx
+++ b/karavan-designer/src/designer/property/usePropertiesHook.tsx
@@ -177,6 +177,7 @@ export function usePropertiesHook(designerType: 'routes' | 
'rest' | 'beans' = 'r
     }
 
     const convertStep = (step: CamelElement, targetDslName: string) => {
+        console.log(targetDslName)
         try {
             // setSelectedStep(undefined);
             if (targetDslName === 'ChoiceDefinition' && step.dslName === 
'FilterDefinition') {
diff --git a/karavan-designer/src/designer/route/DslConnections.css 
b/karavan-designer/src/designer/route/DslConnections.css
index 03da5f2a..a75582ea 100644
--- a/karavan-designer/src/designer/route/DslConnections.css
+++ b/karavan-designer/src/designer/route/DslConnections.css
@@ -54,6 +54,15 @@
     fill: transparent;
 }
 
+.karavan .dsl-page .graph .connections .path-dynamic {
+    stroke-dasharray: 5;
+    -webkit-animation: dashdrawR 0.5s linear infinite;
+    animation: dashdrawR 0.5s linear infinite;
+    stroke: var(--pf-v5-global--Color--200);
+    stroke-width: 1;
+    fill: transparent;
+}
+
 .karavan .dsl-page .graph .connections .path-poll {
     stroke-dasharray: 5;
     -webkit-animation: dashdrawL 0.5s linear infinite;
diff --git a/karavan-designer/src/designer/route/DslConnections.tsx 
b/karavan-designer/src/designer/route/DslConnections.tsx
index 99fd0934..be404896 100644
--- a/karavan-designer/src/designer/route/DslConnections.tsx
+++ b/karavan-designer/src/designer/route/DslConnections.tsx
@@ -33,6 +33,7 @@ import {INTERNAL_COMPONENTS} from 
"karavan-core/lib/api/ComponentApi";
 const overlapGap: number = 40;
 const DIAMETER: number = 34;
 const RADIUS: number = DIAMETER / 2;
+type ConnectionType =  'internal' | 'remote' | 'nav' | 'poll' | 'dynamic';
 
 export function DslConnections() {
 
@@ -83,10 +84,12 @@ export function DslConnections() {
         }
     }
 
-    function getElementType(element: CamelElement): 'internal' | 'remote' | 
'nav' | 'poll' {
+    function getElementType(element: CamelElement): ConnectionType {
         const uri = (element as any).uri;
         if (element.dslName === 'PollDefinition') {
             return 'poll';
+        } else if (element.dslName === 'ToDynamicDefinition') {
+            return 'dynamic';
         } else if (INTERNAL_COMPONENTS.includes((uri))) {
             return 'nav';
         } else {
@@ -95,8 +98,8 @@ export function DslConnections() {
         }
     }
 
-    function getIncomings(): [string, number, 'internal' | 'remote' | 'nav' | 
'poll'][] {
-        let outs: [string, number, 'internal' | 'remote' | 'nav' | 'poll'][] = 
Array.from(steps.values())
+    function getIncomings(): [string, number, ConnectionType][] {
+        let outs: [string, number, ConnectionType][] = 
Array.from(steps.values())
             .filter(pos => ["FromDefinition"].includes(pos.step.dslName))
             .filter(pos => !(pos.step.dslName === 'FromDefinition' && 
(pos.step as any).uri === 'kamelet:source'))
             .sort((pos1: DslPosition, pos2: DslPosition) => {
@@ -111,7 +114,7 @@ export function DslConnections() {
         return outs;
     }
 
-    function getIncoming(data: [string, number, 'internal' | 'remote' | 'nav' 
| 'poll']) {
+    function getIncoming(data: [string, number, ConnectionType]) {
         const pos = steps.get(data[0]);
         if (pos) {
             const fromX = pos.headerRect.x + pos.headerRect.width / 2 - left;
@@ -144,7 +147,7 @@ export function DslConnections() {
     //         .filter(s =>  (s.step as any)?.parameters?.name === name)
     // }
 
-    function getIncomingIcons(data: [string, number, 'internal' | 'remote' | 
'nav' | 'poll']) {
+    function getIncomingIcons(data: [string, number, ConnectionType]) {
         const pos = steps.get(data[0]);
         if (pos) {
             const step = (pos.step as any);
@@ -186,7 +189,7 @@ export function DslConnections() {
         }
     }
 
-    function hasOverlap(data: [string, number, 'internal' | 'remote' | 'nav' | 
'poll'][]): boolean {
+    function hasOverlap(data: [string, number, ConnectionType][]): boolean {
         let result = false;
         data.forEach((d, i, arr) => {
             if (i > 0 && d[1] - arr[i - 1][1] < overlapGap) result = true;
@@ -194,8 +197,8 @@ export function DslConnections() {
         return result;
     }
 
-    function addGap(data: [string, number, 'internal' | 'remote' | 'nav' | 
'poll'][]): [string, number, 'internal' | 'remote' | 'nav' | 'poll'][] {
-        const result: [string, number, 'internal' | 'remote' | 'nav' | 
'poll'][] = [];
+    function addGap(data: [string, number, ConnectionType][]): [string, 
number, ConnectionType][] {
+        const result: [string, number, ConnectionType][] = [];
         data.forEach((d, i, arr) => {
             if (i > 0 && d[1] - arr[i - 1][1] < overlapGap) result.push([d[0], 
d[1] + overlapGap, d[2]])
             else result.push(d);
@@ -204,12 +207,12 @@ export function DslConnections() {
     }
 
 
-    function getOutgoings(): [string, number, 'internal' | 'remote' | 'nav' | 
'poll'][] {
+    function getOutgoings(): [string, number, ConnectionType][] {
         const outgoingDefinitions = TopologyUtils.getOutgoingDefinitions();
-        let outs: [string, number, 'internal' | 'remote' | 'nav' | 'poll'][] = 
Array.from(steps.values())
+        let outs: [string, number, ConnectionType][] = 
Array.from(steps.values())
             .filter(pos => outgoingDefinitions.includes(pos.step.dslName))
             .filter(pos => pos.step.dslName !== 'KameletDefinition' || 
(pos.step.dslName === 'KameletDefinition' && 
!CamelUi.isActionKamelet(pos.step)))
-            .filter(pos => ['ToDefinition', 
'PollDefinition'].includes(pos.step.dslName) && 
!CamelUi.isActionKamelet(pos.step))
+            .filter(pos => ['ToDefinition', 'PollDefinition', 
"ToDynamicDefinition"].includes(pos.step.dslName) && 
!CamelUi.isActionKamelet(pos.step))
             .filter(pos => !CamelUi.isKameletSink(pos.step))
             .sort((pos1: DslPosition, pos2: DslPosition) => {
                 const y1 = pos1.headerRect.y + pos1.headerRect.height / 2;
@@ -223,11 +226,12 @@ export function DslConnections() {
         return outs;
     }
 
-    function getOutgoing(data: [string, number, 'internal' | 'remote' | 'nav' 
| 'poll']) {
+    function getOutgoing(data: [string, number, ConnectionType]) {
         const pos = steps.get(data[0]);
         const isInternal = data[2] === 'internal';
         const isNav = data[2] === 'nav';
         const isPoll = data[2] === 'poll';
+        const isDynamic = data[2] === 'dynamic';
         if (pos) {
             const fromX = pos.headerRect.x + pos.headerRect.width / 2 - left;
             const fromY = pos.headerRect.y + pos.headerRect.height / 2 - top;
@@ -244,7 +248,9 @@ export function DslConnections() {
             const lineXi = lineX1 + 40;
             const lineYi = lineY2;
 
-            const className = isNav ? 'path-incoming-nav' : (isPoll ? 
'path-poll' : 'path-incoming')
+            const className = isNav
+                ? 'path-incoming-nav'
+                : (isPoll ? 'path-poll' : (isDynamic ? 'path-dynamic' 
:'path-incoming'))
 
             return (!isInternal
                     ? <g key={pos.step.uuid + "-outgoing"}>
@@ -258,7 +264,7 @@ export function DslConnections() {
         }
     }
 
-    function getOutgoingIcons(data: [string, number, 'internal' | 'remote' | 
'nav' | 'poll']) {
+    function getOutgoingIcons(data: [string, number, ConnectionType]) {
         const pos = steps.get(data[0]);
         if (pos) {
             const step = (pos.step as any);
diff --git a/karavan-designer/src/designer/route/element/DslElement.css 
b/karavan-designer/src/designer/route/element/DslElement.css
index 785f667b..1b431837 100644
--- a/karavan-designer/src/designer/route/element/DslElement.css
+++ b/karavan-designer/src/designer/route/element/DslElement.css
@@ -128,6 +128,10 @@
     border-radius: 33px;
 }
 
+.karavan .step-element .header-icon-circle .dynamic{
+    fill: var(--pf-v5-global--Color--400);
+}
+
 .karavan .step-element .header-icon-square {
     border-radius: 33px;
 }
diff --git a/karavan-designer/src/designer/utils/CamelUi.tsx 
b/karavan-designer/src/designer/utils/CamelUi.tsx
index 045b154d..646f5ed9 100644
--- a/karavan-designer/src/designer/utils/CamelUi.tsx
+++ b/karavan-designer/src/designer/utils/CamelUi.tsx
@@ -728,7 +728,9 @@ export class CamelUi {
             case 'AggregateDefinition':
                 return <AggregateIcon/>;
             case 'ToDefinition':
-                return <ToIcon/>;
+                return ToIcon();
+            case 'ToDynamicDefinition':
+                return ToIcon('dynamic');
             case 'PollDefinition':
                 return <PollIcon/>;
             case 'ChoiceDefinition' :
diff --git a/karavan-space/src/designer/icons/EipIcons.tsx 
b/karavan-space/src/designer/icons/EipIcons.tsx
index fc928d9f..4bdac684 100644
--- a/karavan-space/src/designer/icons/EipIcons.tsx
+++ b/karavan-space/src/designer/icons/EipIcons.tsx
@@ -50,14 +50,14 @@ export function AggregateIcon() {
     );
 }
 
-export function ToIcon() {
+export function ToIcon(classname: string = '') {
     return (
         <svg
             xmlns="http://www.w3.org/2000/svg";
             width={800}
             height={800}
             viewBox="0 0 32 32"
-            className="icon"
+            className={classname ? "icon " + classname : "icon"}
         >
             <path d="m12.103 11.923 2.58 2.59H2.513v2h12.17l-2.58 2.59 1.41 
1.41 5-5-5-5z"/>
             <path
diff --git a/karavan-space/src/designer/property/DslProperties.css 
b/karavan-space/src/designer/property/DslProperties.css
index 97b97a38..e2401cf3 100644
--- a/karavan-space/src/designer/property/DslProperties.css
+++ b/karavan-space/src/designer/property/DslProperties.css
@@ -24,14 +24,22 @@
     width: 100%;
     display: flex;
     flex-direction: row;
+    /*justify-content: space-between;*/
+    gap: 10px;
 }
 
 .karavan .properties .headers .top h1 {
-    width: 100%;
+    /*width: 100%;*/
     margin-top: auto;
     margin-bottom: auto;
+    text-wrap: nowrap;
+}
+
+.karavan .properties .headers .top .pf-v5-c-switch {
+    column-gap: 6px;
 }
 
+
 .karavan .properties .footer {
     height: 100%;
     display: contents;
diff --git a/karavan-space/src/designer/property/PropertiesHeader.tsx 
b/karavan-space/src/designer/property/PropertiesHeader.tsx
index b8aca6b4..00a3e1ee 100644
--- a/karavan-space/src/designer/property/PropertiesHeader.tsx
+++ b/karavan-space/src/designer/property/PropertiesHeader.tsx
@@ -25,13 +25,13 @@ import {
     MenuToggle,
     DropdownList,
     DropdownItem, Flex, Popover, FlexItem, Badge, ClipboardCopy,
-    Switch,
+    Switch, Radio, Tooltip,
 } from '@patternfly/react-core';
 import '../karavan.css';
 import './DslProperties.css';
 import "@patternfly/patternfly/patternfly.css";
 import {CamelUi} from "../utils/CamelUi";
-import {useDesignerStore, useSelectorStore} from "../DesignerStore";
+import {useDesignerStore} from "../DesignerStore";
 import {shallow} from "zustand/shallow";
 import {usePropertiesHook} from "./usePropertiesHook";
 import {CamelDisplayUtil} from "karavan-core/lib/api/CamelDisplayUtil";
@@ -56,7 +56,13 @@ export function PropertiesHeader(props: Props) {
     const [isHeadersExpanded, setIsHeadersExpanded] = useState<boolean>(false);
     const [isExchangePropertiesExpanded, setIsExchangePropertiesExpanded] = 
useState<boolean>(false);
     const [isMenuOpen, setMenuOpen] = useState<boolean>(false);
-    const [isStepTypeOpen, setIsStepTypeOpen] = React.useState(false);
+    const [stepIsPoll, setStepIsPoll] = React.useState(false);
+    const [stepDynamic, setStepDynamic] = React.useState(false);
+
+    useEffect(() => {
+        setStepDynamic(selectedStep?.dslName === 'ToDynamicDefinition')
+        setStepIsPoll(selectedStep?.dslName === 'PollDefinition')
+    }, [])
 
     useEffect(() => {
         setMenuOpen(false)
@@ -68,67 +74,70 @@ export function PropertiesHeader(props: Props) {
         const targetDslTitle = targetDsl?.replace("Definition", "");
         const showMenu = hasSteps || targetDsl !== undefined;
         return showMenu ?
-            <Dropdown
-                popperProps={{position: "end"}}
-                isOpen={isMenuOpen}
-                onSelect={() => {
-                }}
-                onOpenChange={(isOpen: boolean) => setMenuOpen(isOpen)}
-                toggle={(toggleRef: React.Ref<MenuToggleElement>) => (
-                    <MenuToggle
-                        className="header-menu-toggle"
-                        ref={toggleRef}
-                        aria-label="menu"
-                        variant="plain"
-                        onClick={() => setMenuOpen(!isMenuOpen)}
-                        isExpanded={isMenuOpen}
-                    >
-                        <EllipsisVIcon/>
-                    </MenuToggle>
-                )}
-            >
-                <DropdownList>
-                    {isFrom &&
-                        <DropdownItem key="changeFrom" onClick={(ev) => {
-                            ev.preventDefault()
-                            openSelectorToReplaceFrom((selectedStep as any).id)
-                            setMenuOpen(false);
-                        }}>
-                            Change From...
-                        </DropdownItem>}
-                    {hasSteps &&
-                        <DropdownItem key="saveStepsRoute" onClick={(ev) => {
-                            ev.preventDefault()
-                            if (selectedStep) {
-                                saveAsRoute(selectedStep, true);
-                                setMenuOpen(false);
-                            }
-                        }}>
-                            Save Steps to Route
-                        </DropdownItem>}
-                    {hasSteps && !isFrom &&
-                        <DropdownItem key="saveElementRoute" onClick={(ev) => {
-                            ev.preventDefault()
-                            if (selectedStep) {
-                                saveAsRoute(selectedStep, false);
+            <div style={{display: 'flex', flexDirection: 'row', 
justifyContent: 'end', width: '100%'}}>
+                <Dropdown
+                    popperProps={{position: "end"}}
+                    isOpen={isMenuOpen}
+                    onSelect={() => {
+                    }}
+                    onOpenChange={(isOpen: boolean) => setMenuOpen(isOpen)}
+                    toggle={(toggleRef: React.Ref<MenuToggleElement>) => (
+                        <MenuToggle
+                            className="header-menu-toggle"
+                            ref={toggleRef}
+                            aria-label="menu"
+                            variant="plain"
+                            onClick={() => setMenuOpen(!isMenuOpen)}
+                            isExpanded={isMenuOpen}
+                        >
+                            <EllipsisVIcon/>
+                        </MenuToggle>
+                    )}
+                >
+                    <DropdownList>
+                        {isFrom &&
+                            <DropdownItem key="changeFrom" onClick={(ev) => {
+                                ev.preventDefault()
+                                openSelectorToReplaceFrom((selectedStep as 
any).id)
                                 setMenuOpen(false);
-                            }
-                        }}>
-                            Save Element to Route
-                        </DropdownItem>}
-                    {targetDsl &&
-                        <DropdownItem key="convert"
-                                      onClick={(ev) => {
-                                          ev.preventDefault()
-                                          if (selectedStep) {
-                                              convertStep(selectedStep, 
targetDsl);
-                                              setMenuOpen(false);
-                                          }
-                                      }}>
-                            Convert to {targetDslTitle}
-                        </DropdownItem>}
-                </DropdownList>
-            </Dropdown> : <></>;
+                            }}>
+                                Change From...
+                            </DropdownItem>}
+                        {hasSteps &&
+                            <DropdownItem key="saveStepsRoute" onClick={(ev) 
=> {
+                                ev.preventDefault()
+                                if (selectedStep) {
+                                    saveAsRoute(selectedStep, true);
+                                    setMenuOpen(false);
+                                }
+                            }}>
+                                Save Steps to Route
+                            </DropdownItem>}
+                        {hasSteps && !isFrom &&
+                            <DropdownItem key="saveElementRoute" onClick={(ev) 
=> {
+                                ev.preventDefault()
+                                if (selectedStep) {
+                                    saveAsRoute(selectedStep, false);
+                                    setMenuOpen(false);
+                                }
+                            }}>
+                                Save Element to Route
+                            </DropdownItem>}
+                        {targetDsl &&
+                            <DropdownItem key="convert"
+                                          onClick={(ev) => {
+                                              ev.preventDefault()
+                                              if (selectedStep) {
+                                                  convertStep(selectedStep, 
targetDsl);
+                                                  setMenuOpen(false);
+                                              }
+                                          }}>
+                                Convert to {targetDslTitle}
+                            </DropdownItem>}
+                    </DropdownList>
+                </Dropdown>
+            </div>
+            : <></>;
     }
 
     function getExchangePropertiesSection(): React.JSX.Element {
@@ -138,35 +147,35 @@ export function PropertiesHeader(props: Props) {
                                isExpanded={isExchangePropertiesExpanded}>
                 <Flex className='component-headers' direction={{default: 
"column"}}>
                     {exchangeProperties.map((header, index, array) =>
-                            <Flex key={index}>
-                                <ClipboardCopy key={index} hoverTip="Copy" 
clickTip="Copied" variant="inline-compact"
-                                               isCode>
-                                    {header.name}
-                                </ClipboardCopy>
-                                <FlexItem align={{default: 'alignRight'}}>
-                                    <Popover
-                                        position={"left"}
-                                        headerContent={header.name}
-                                        bodyContent={header.description}
-                                        footerContent={
-                                            <Flex>
-                                                <Text 
component={TextVariants.p}>{header.javaType}</Text>
-                                                <FlexItem align={{default: 
'alignRight'}}>
-                                                    <Badge 
isRead>{header.label}</Badge>
-                                                </FlexItem>
-                                            </Flex>
-                                        }
-                                    >
-                                        <button type="button" aria-label="More 
info" onClick={e => {
-                                            e.preventDefault();
-                                            e.stopPropagation();
-                                        }} 
className="pf-v5-c-form__group-label-help">
-                                            <HelpIcon/>
-                                        </button>
-                                    </Popover>
-                                </FlexItem>
-                            </Flex>
-                        )}
+                        <Flex key={index}>
+                            <ClipboardCopy key={index} hoverTip="Copy" 
clickTip="Copied" variant="inline-compact"
+                                           isCode>
+                                {header.name}
+                            </ClipboardCopy>
+                            <FlexItem align={{default: 'alignRight'}}>
+                                <Popover
+                                    position={"left"}
+                                    headerContent={header.name}
+                                    bodyContent={header.description}
+                                    footerContent={
+                                        <Flex>
+                                            <Text 
component={TextVariants.p}>{header.javaType}</Text>
+                                            <FlexItem align={{default: 
'alignRight'}}>
+                                                <Badge 
isRead>{header.label}</Badge>
+                                            </FlexItem>
+                                        </Flex>
+                                    }
+                                >
+                                    <button type="button" aria-label="More 
info" onClick={e => {
+                                        e.preventDefault();
+                                        e.stopPropagation();
+                                    }} 
className="pf-v5-c-form__group-label-help">
+                                        <HelpIcon/>
+                                    </button>
+                                </Popover>
+                            </FlexItem>
+                        </Flex>
+                    )}
                 </Flex>
             </ExpandableSection>
         )
@@ -235,24 +244,58 @@ export function PropertiesHeader(props: Props) {
     const component = ComponentApi.findStepComponent(selectedStep);
     const groups = (isFrom || isPoll) ? ['consumer', 'common'] : ['producer', 
'common'];
     const isKamelet = CamelUi.isKamelet(selectedStep);
-    const isStepComponent = !isFrom && selectedStep !== undefined && 
!isKamelet && ['ToDefinition', 
'PollDefinition'].includes(selectedStep?.dslName);
+    const isStepComponent = !isFrom && selectedStep !== undefined && 
!isKamelet && ['ToDefinition', 'PollDefinition', 
'ToDynamicDefinition'].includes(selectedStep?.dslName);
+
+    function changeStepType(poll: boolean, dynamic: boolean) {
+        if (selectedStep) {
+            if  (poll) {
+                convertStep(selectedStep, 'PollDefinition');
+                setStepIsPoll(true);
+                setStepDynamic(false);
+            } else if (dynamic) {
+                convertStep(selectedStep, 'ToDynamicDefinition');
+                setStepIsPoll(false);
+                setStepDynamic(true);
+            } else {
+                convertStep(selectedStep, 'ToDefinition');
+                setStepIsPoll(false);
+                setStepDynamic(false);
+            }
+        }
+    }
 
     function getComponentStepTypeSwitch() {
-        return (component?.component.producerOnly
-            ? <></>
-            : <Switch
-                id="step-type-switch"
-                label="Poll"
-                isChecked={isStepTypeOpen}
-                onChange={(event, checked) => {
-                    if (selectedStep) {
-                        convertStep(selectedStep, checked ? 'PollDefinition' : 
'ToDefinition');
-                        setIsStepTypeOpen(checked);
-                    }
-                }}
-                ouiaId="step-type-switch"
-                isReversed
-            />
+        const pollSupported = !component?.component.producerOnly;
+        return (<div style={{display: 'flex', flexDirection: 'row', 
justifyContent: 'end', width: '100%', gap: '10px'}}>
+                <Tooltip content='Send messages to a dynamic endpoint 
evaluated on-demand' position='top-end'>
+                    <Switch
+                        id="step-type-dynamic"
+                        label="Dynamic"
+                        isChecked={stepDynamic}
+                        onChange={(event, checked) => {
+                            changeStepType(stepIsPoll, checked)
+                        }}
+                        ouiaId="step-type-switch"
+                        isDisabled={stepIsPoll}
+                        isReversed
+                    />
+                </Tooltip>
+                {pollSupported &&
+                    <Tooltip content='Simple Polling Consumer to obtain the 
additional data' position='top-end'>
+                        <Switch
+                            id="step-type-poll"
+                            label="Poll"
+                            isChecked={stepIsPoll}
+                            onChange={(event, checked) => {
+                                changeStepType(checked, stepDynamic)
+                            }}
+                            ouiaId="step-type-switch"
+                            isDisabled={stepDynamic}
+                            isReversed
+                        />
+                    </Tooltip>
+                }
+            </div>
         )
     }
 
diff --git a/karavan-space/src/designer/property/usePropertiesHook.tsx 
b/karavan-space/src/designer/property/usePropertiesHook.tsx
index 2d806c0d..5c8e38b4 100644
--- a/karavan-space/src/designer/property/usePropertiesHook.tsx
+++ b/karavan-space/src/designer/property/usePropertiesHook.tsx
@@ -177,6 +177,7 @@ export function usePropertiesHook(designerType: 'routes' | 
'rest' | 'beans' = 'r
     }
 
     const convertStep = (step: CamelElement, targetDslName: string) => {
+        console.log(targetDslName)
         try {
             // setSelectedStep(undefined);
             if (targetDslName === 'ChoiceDefinition' && step.dslName === 
'FilterDefinition') {
diff --git a/karavan-space/src/designer/route/DslConnections.css 
b/karavan-space/src/designer/route/DslConnections.css
index 03da5f2a..a75582ea 100644
--- a/karavan-space/src/designer/route/DslConnections.css
+++ b/karavan-space/src/designer/route/DslConnections.css
@@ -54,6 +54,15 @@
     fill: transparent;
 }
 
+.karavan .dsl-page .graph .connections .path-dynamic {
+    stroke-dasharray: 5;
+    -webkit-animation: dashdrawR 0.5s linear infinite;
+    animation: dashdrawR 0.5s linear infinite;
+    stroke: var(--pf-v5-global--Color--200);
+    stroke-width: 1;
+    fill: transparent;
+}
+
 .karavan .dsl-page .graph .connections .path-poll {
     stroke-dasharray: 5;
     -webkit-animation: dashdrawL 0.5s linear infinite;
diff --git a/karavan-space/src/designer/route/DslConnections.tsx 
b/karavan-space/src/designer/route/DslConnections.tsx
index 99fd0934..be404896 100644
--- a/karavan-space/src/designer/route/DslConnections.tsx
+++ b/karavan-space/src/designer/route/DslConnections.tsx
@@ -33,6 +33,7 @@ import {INTERNAL_COMPONENTS} from 
"karavan-core/lib/api/ComponentApi";
 const overlapGap: number = 40;
 const DIAMETER: number = 34;
 const RADIUS: number = DIAMETER / 2;
+type ConnectionType =  'internal' | 'remote' | 'nav' | 'poll' | 'dynamic';
 
 export function DslConnections() {
 
@@ -83,10 +84,12 @@ export function DslConnections() {
         }
     }
 
-    function getElementType(element: CamelElement): 'internal' | 'remote' | 
'nav' | 'poll' {
+    function getElementType(element: CamelElement): ConnectionType {
         const uri = (element as any).uri;
         if (element.dslName === 'PollDefinition') {
             return 'poll';
+        } else if (element.dslName === 'ToDynamicDefinition') {
+            return 'dynamic';
         } else if (INTERNAL_COMPONENTS.includes((uri))) {
             return 'nav';
         } else {
@@ -95,8 +98,8 @@ export function DslConnections() {
         }
     }
 
-    function getIncomings(): [string, number, 'internal' | 'remote' | 'nav' | 
'poll'][] {
-        let outs: [string, number, 'internal' | 'remote' | 'nav' | 'poll'][] = 
Array.from(steps.values())
+    function getIncomings(): [string, number, ConnectionType][] {
+        let outs: [string, number, ConnectionType][] = 
Array.from(steps.values())
             .filter(pos => ["FromDefinition"].includes(pos.step.dslName))
             .filter(pos => !(pos.step.dslName === 'FromDefinition' && 
(pos.step as any).uri === 'kamelet:source'))
             .sort((pos1: DslPosition, pos2: DslPosition) => {
@@ -111,7 +114,7 @@ export function DslConnections() {
         return outs;
     }
 
-    function getIncoming(data: [string, number, 'internal' | 'remote' | 'nav' 
| 'poll']) {
+    function getIncoming(data: [string, number, ConnectionType]) {
         const pos = steps.get(data[0]);
         if (pos) {
             const fromX = pos.headerRect.x + pos.headerRect.width / 2 - left;
@@ -144,7 +147,7 @@ export function DslConnections() {
     //         .filter(s =>  (s.step as any)?.parameters?.name === name)
     // }
 
-    function getIncomingIcons(data: [string, number, 'internal' | 'remote' | 
'nav' | 'poll']) {
+    function getIncomingIcons(data: [string, number, ConnectionType]) {
         const pos = steps.get(data[0]);
         if (pos) {
             const step = (pos.step as any);
@@ -186,7 +189,7 @@ export function DslConnections() {
         }
     }
 
-    function hasOverlap(data: [string, number, 'internal' | 'remote' | 'nav' | 
'poll'][]): boolean {
+    function hasOverlap(data: [string, number, ConnectionType][]): boolean {
         let result = false;
         data.forEach((d, i, arr) => {
             if (i > 0 && d[1] - arr[i - 1][1] < overlapGap) result = true;
@@ -194,8 +197,8 @@ export function DslConnections() {
         return result;
     }
 
-    function addGap(data: [string, number, 'internal' | 'remote' | 'nav' | 
'poll'][]): [string, number, 'internal' | 'remote' | 'nav' | 'poll'][] {
-        const result: [string, number, 'internal' | 'remote' | 'nav' | 
'poll'][] = [];
+    function addGap(data: [string, number, ConnectionType][]): [string, 
number, ConnectionType][] {
+        const result: [string, number, ConnectionType][] = [];
         data.forEach((d, i, arr) => {
             if (i > 0 && d[1] - arr[i - 1][1] < overlapGap) result.push([d[0], 
d[1] + overlapGap, d[2]])
             else result.push(d);
@@ -204,12 +207,12 @@ export function DslConnections() {
     }
 
 
-    function getOutgoings(): [string, number, 'internal' | 'remote' | 'nav' | 
'poll'][] {
+    function getOutgoings(): [string, number, ConnectionType][] {
         const outgoingDefinitions = TopologyUtils.getOutgoingDefinitions();
-        let outs: [string, number, 'internal' | 'remote' | 'nav' | 'poll'][] = 
Array.from(steps.values())
+        let outs: [string, number, ConnectionType][] = 
Array.from(steps.values())
             .filter(pos => outgoingDefinitions.includes(pos.step.dslName))
             .filter(pos => pos.step.dslName !== 'KameletDefinition' || 
(pos.step.dslName === 'KameletDefinition' && 
!CamelUi.isActionKamelet(pos.step)))
-            .filter(pos => ['ToDefinition', 
'PollDefinition'].includes(pos.step.dslName) && 
!CamelUi.isActionKamelet(pos.step))
+            .filter(pos => ['ToDefinition', 'PollDefinition', 
"ToDynamicDefinition"].includes(pos.step.dslName) && 
!CamelUi.isActionKamelet(pos.step))
             .filter(pos => !CamelUi.isKameletSink(pos.step))
             .sort((pos1: DslPosition, pos2: DslPosition) => {
                 const y1 = pos1.headerRect.y + pos1.headerRect.height / 2;
@@ -223,11 +226,12 @@ export function DslConnections() {
         return outs;
     }
 
-    function getOutgoing(data: [string, number, 'internal' | 'remote' | 'nav' 
| 'poll']) {
+    function getOutgoing(data: [string, number, ConnectionType]) {
         const pos = steps.get(data[0]);
         const isInternal = data[2] === 'internal';
         const isNav = data[2] === 'nav';
         const isPoll = data[2] === 'poll';
+        const isDynamic = data[2] === 'dynamic';
         if (pos) {
             const fromX = pos.headerRect.x + pos.headerRect.width / 2 - left;
             const fromY = pos.headerRect.y + pos.headerRect.height / 2 - top;
@@ -244,7 +248,9 @@ export function DslConnections() {
             const lineXi = lineX1 + 40;
             const lineYi = lineY2;
 
-            const className = isNav ? 'path-incoming-nav' : (isPoll ? 
'path-poll' : 'path-incoming')
+            const className = isNav
+                ? 'path-incoming-nav'
+                : (isPoll ? 'path-poll' : (isDynamic ? 'path-dynamic' 
:'path-incoming'))
 
             return (!isInternal
                     ? <g key={pos.step.uuid + "-outgoing"}>
@@ -258,7 +264,7 @@ export function DslConnections() {
         }
     }
 
-    function getOutgoingIcons(data: [string, number, 'internal' | 'remote' | 
'nav' | 'poll']) {
+    function getOutgoingIcons(data: [string, number, ConnectionType]) {
         const pos = steps.get(data[0]);
         if (pos) {
             const step = (pos.step as any);
diff --git a/karavan-space/src/designer/route/element/DslElement.css 
b/karavan-space/src/designer/route/element/DslElement.css
index 785f667b..1b431837 100644
--- a/karavan-space/src/designer/route/element/DslElement.css
+++ b/karavan-space/src/designer/route/element/DslElement.css
@@ -128,6 +128,10 @@
     border-radius: 33px;
 }
 
+.karavan .step-element .header-icon-circle .dynamic{
+    fill: var(--pf-v5-global--Color--400);
+}
+
 .karavan .step-element .header-icon-square {
     border-radius: 33px;
 }
diff --git a/karavan-space/src/designer/utils/CamelUi.tsx 
b/karavan-space/src/designer/utils/CamelUi.tsx
index 045b154d..646f5ed9 100644
--- a/karavan-space/src/designer/utils/CamelUi.tsx
+++ b/karavan-space/src/designer/utils/CamelUi.tsx
@@ -728,7 +728,9 @@ export class CamelUi {
             case 'AggregateDefinition':
                 return <AggregateIcon/>;
             case 'ToDefinition':
-                return <ToIcon/>;
+                return ToIcon();
+            case 'ToDynamicDefinition':
+                return ToIcon('dynamic');
             case 'PollDefinition':
                 return <PollIcon/>;
             case 'ChoiceDefinition' :

Reply via email to