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 869f26a528434b821679054134a1c55b6f833474
Author: Marat Gubaidullin <ma...@talismancloud.io>
AuthorDate: Thu Apr 11 11:10:45 2024 -0400

    Fix #1133
---
 .../webui/src/designer/property/DslProperties.tsx  | 144 +------------
 .../src/designer/property/PropertiesHeader.tsx     | 239 +++++++++++++++++++++
 .../webui/src/designer/utils/IntegrationHeader.tsx |  16 +-
 .../webui/src/expression/ExpressionModalEditor.css |   9 +-
 .../webui/src/expression/ExpressionModalEditor.tsx |  25 ++-
 karavan-core/src/core/model/CamelMetadata.ts       |   4 +
 karavan-designer/public/example/demo.camel.yaml    | 201 +----------------
 .../src/designer/property/DslProperties.tsx        | 144 +------------
 .../src/designer/property/PropertiesHeader.tsx     | 239 +++++++++++++++++++++
 .../src/designer/utils/IntegrationHeader.tsx       |  16 +-
 .../src/main/resources/CamelMetadata.header.ts     |   4 +
 .../src/designer/property/DslProperties.tsx        | 144 +------------
 .../src/designer/property/PropertiesHeader.tsx     | 239 +++++++++++++++++++++
 .../src/designer/utils/IntegrationHeader.tsx       |  16 +-
 .../src/expression/ExpressionModalEditor.css       |   9 +-
 .../src/expression/ExpressionModalEditor.tsx       |  25 ++-
 16 files changed, 791 insertions(+), 683 deletions(-)

diff --git a/karavan-app/src/main/webui/src/designer/property/DslProperties.tsx 
b/karavan-app/src/main/webui/src/designer/property/DslProperties.tsx
index 656d816c..7448351c 100644
--- a/karavan-app/src/main/webui/src/designer/property/DslProperties.tsx
+++ b/karavan-app/src/main/webui/src/designer/property/DslProperties.tsx
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-import React, {useEffect, useState} from 'react';
+import React, {useState} from 'react';
 import {
     Form,
     Text,
@@ -23,11 +23,6 @@ import {
     ExpandableSection,
     Button,
     Tooltip,
-    Dropdown,
-    MenuToggleElement,
-    MenuToggle,
-    DropdownList,
-    DropdownItem, Flex, Popover, FlexItem, Badge, ClipboardCopy,
 } from '@patternfly/react-core';
 import '../karavan.css';
 import './DslProperties.css';
@@ -43,9 +38,7 @@ import {useDesignerStore, useIntegrationStore} from 
"../DesignerStore";
 import {shallow} from "zustand/shallow";
 import {usePropertiesHook} from "./usePropertiesHook";
 import {CamelDisplayUtil} from "karavan-core/lib/api/CamelDisplayUtil";
-import EllipsisVIcon from 
'@patternfly/react-icons/dist/esm/icons/ellipsis-v-icon';
-import {ComponentApi} from "karavan-core/lib/api/ComponentApi";
-import HelpIcon from "@patternfly/react-icons/dist/js/icons/help-icon";
+import {PropertiesHeader} from "./PropertiesHeader";
 
 interface Props {
     designerType: 'routes' | 'rest' | 'beans'
@@ -56,8 +49,6 @@ export function DslProperties(props: Props) {
     const [integration] = useIntegrationStore((s) => [s.integration], shallow)
 
     const {
-        saveAsRoute,
-        convertStep,
         cloneElement,
         onDataFormatChange,
         onPropertyChange,
@@ -70,135 +61,6 @@ export function DslProperties(props: Props) {
         = useDesignerStore((s) => [s.selectedStep, s.dark], shallow)
 
     const [showAdvanced, setShowAdvanced] = useState<boolean>(false);
-    const [isDescriptionExpanded, setIsDescriptionExpanded] = 
useState<boolean>(false);
-    const [isMenuOpen, setMenuOpen] = useState<boolean>(false);
-
-    useEffect(() => {
-        setMenuOpen(false)
-    }, [selectedStep])
-
-    function getHeaderMenu(): JSX.Element {
-        const hasSteps = selectedStep?.hasSteps();
-        const targetDsl = CamelUi.getConvertTargetDsl(selectedStep?.dslName);
-        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>
-                    {hasSteps &&
-                        <DropdownItem key="saveRoute" onClick={(ev) => {
-                            ev.preventDefault()
-                            if (selectedStep) {
-                                saveAsRoute(selectedStep, true);
-                                setMenuOpen(false);
-                            }
-                        }}>
-                            Save Steps to Route
-                        </DropdownItem>}
-                    {hasSteps &&
-                        <DropdownItem key="saveRoute" 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> : <></>;
-    }
-
-    function getRouteHeader(): JSX.Element {
-        const title = selectedStep && CamelDisplayUtil.getTitle(selectedStep)
-        const description = selectedStep && 
CamelDisplayUtil.getDescription(selectedStep);
-        const descriptionLines: string [] = description ? 
description?.split("\n") : [""];
-        const headers = ComponentApi.getComponentHeadersList(selectedStep)
-        const groups = selectedStep?.dslName === 'FromDefinition' ? 
['consumer', 'common'] : ['producer', 'common']
-        return (
-            <div className="headers">
-                <div className="top">
-                    <Title headingLevel="h1" size="md">{title}</Title>
-                    {getHeaderMenu()}
-                </div>
-                <Text 
component={TextVariants.p}>{descriptionLines.at(0)}</Text>
-                {descriptionLines.length > 1 &&
-                    <ExpandableSection toggleText={isDescriptionExpanded ? 
'Show less' : 'Show more'}
-                                       onToggle={(_event, isExpanded) => 
setIsDescriptionExpanded(!isDescriptionExpanded)}
-                                       isExpanded={isDescriptionExpanded}>
-                        {descriptionLines.filter((value, index) => index > 0)
-                            .map((desc, index, array) => <Text key={index} 
component={TextVariants.p}>{desc}</Text>)}
-                    </ExpandableSection>}
-
-                {headers.length > 0 &&
-                    <ExpandableSection toggleText='Headers'
-                                       onToggle={(_event, isExpanded) => 
setIsDescriptionExpanded(!isDescriptionExpanded)}
-                                       isExpanded={isDescriptionExpanded}>
-                        <Flex className='component-headers' 
direction={{default:"column"}}>
-                            {headers.filter((header) => 
groups.includes(header.group))
-                                .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.group}</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>}
-            </div>
-        )
-    }
 
     function getClonableElementHeader(): JSX.Element {
         const title = selectedStep && CamelDisplayUtil.getTitle(selectedStep);
@@ -219,7 +81,7 @@ export function DslProperties(props: Props) {
     }
 
     function getComponentHeader(): JSX.Element {
-        if (props.designerType === 'routes') return getRouteHeader()
+        if (props.designerType === 'routes') return <PropertiesHeader 
designerType={props.designerType} />
         else return getClonableElementHeader();
     }
 
diff --git 
a/karavan-app/src/main/webui/src/designer/property/PropertiesHeader.tsx 
b/karavan-app/src/main/webui/src/designer/property/PropertiesHeader.tsx
new file mode 100644
index 00000000..9a38fa13
--- /dev/null
+++ b/karavan-app/src/main/webui/src/designer/property/PropertiesHeader.tsx
@@ -0,0 +1,239 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import React, {useEffect, useState} from 'react';
+import {
+    Text,
+    Title,
+    TextVariants,
+    ExpandableSection,
+    Dropdown,
+    MenuToggleElement,
+    MenuToggle,
+    DropdownList,
+    DropdownItem, Flex, Popover, FlexItem, Badge, ClipboardCopy,
+} from '@patternfly/react-core';
+import '../karavan.css';
+import './DslProperties.css';
+import "@patternfly/patternfly/patternfly.css";
+import {CamelUi} from "../utils/CamelUi";
+import {useDesignerStore} from "../DesignerStore";
+import {shallow} from "zustand/shallow";
+import {usePropertiesHook} from "./usePropertiesHook";
+import {CamelDisplayUtil} from "karavan-core/lib/api/CamelDisplayUtil";
+import EllipsisVIcon from 
'@patternfly/react-icons/dist/esm/icons/ellipsis-v-icon';
+import {ComponentApi} from "karavan-core/lib/api/ComponentApi";
+import HelpIcon from "@patternfly/react-icons/dist/js/icons/help-icon";
+import {CamelMetadataApi} from "karavan-core/lib/model/CamelMetadata";
+
+interface Props {
+    designerType: 'routes' | 'rest' | 'beans'
+}
+
+export function PropertiesHeader(props: Props) {
+
+    const {
+        saveAsRoute,
+        convertStep,
+    } =
+        usePropertiesHook(props.designerType);
+
+    const [selectedStep, dark]
+        = useDesignerStore((s) => [s.selectedStep, s.dark], shallow)
+
+    const [isDescriptionExpanded, setIsDescriptionExpanded] = 
useState<boolean>(false);
+    const [isHeadersExpanded, setIsHeadersExpanded] = useState<boolean>(false);
+    const [isExchangePropertiesExpanded, setIsExchangePropertiesExpanded] = 
useState<boolean>(false);
+    const [isMenuOpen, setMenuOpen] = useState<boolean>(false);
+
+    useEffect(() => {
+        setMenuOpen(false)
+    }, [selectedStep])
+
+    function getHeaderMenu(): React.JSX.Element {
+        const hasSteps = selectedStep?.hasSteps();
+        const targetDsl = CamelUi.getConvertTargetDsl(selectedStep?.dslName);
+        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>
+                    {hasSteps &&
+                        <DropdownItem key="saveRoute" onClick={(ev) => {
+                            ev.preventDefault()
+                            if (selectedStep) {
+                                saveAsRoute(selectedStep, true);
+                                setMenuOpen(false);
+                            }
+                        }}>
+                            Save Steps to Route
+                        </DropdownItem>}
+                    {hasSteps &&
+                        <DropdownItem key="saveRoute" 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> : <></>;
+    }
+
+    function getExchangePropertiesSection(): React.JSX.Element {
+        return (
+            <ExpandableSection toggleText='Exchange Properties'
+                               onToggle={(_event, isExpanded) => 
setIsExchangePropertiesExpanded(!isExchangePropertiesExpanded)}
+                               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>
+            </ExpandableSection>
+        )
+    }
+
+    function getComponentHeadersSection(): React.JSX.Element {
+        return (
+            <ExpandableSection toggleText='Headers'
+                               onToggle={(_event, isExpanded) => 
setIsHeadersExpanded(!isHeadersExpanded)}
+                               isExpanded={isHeadersExpanded}>
+                <Flex className='component-headers' direction={{default: 
"column"}}>
+                    {headers.filter((header) => groups.includes(header.group))
+                        .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.group}</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>
+        )
+    }
+
+    function getDescriptionSection(): React.JSX.Element {
+        return (
+            <ExpandableSection toggleText={isDescriptionExpanded ? 'Show less' 
: 'Show more'}
+                               onToggle={(_event, isExpanded) => 
setIsDescriptionExpanded(!isDescriptionExpanded)}
+                               isExpanded={isDescriptionExpanded}>
+                {descriptionLines.filter((value, index) => index > 0)
+                    .map((desc, index, array) => <Text key={index} 
component={TextVariants.p}>{desc}</Text>)}
+            </ExpandableSection>
+        )
+    }
+
+    const title = selectedStep && CamelDisplayUtil.getTitle(selectedStep)
+    const description = selectedStep && 
CamelDisplayUtil.getDescription(selectedStep);
+    const descriptionLines: string [] = description ? description?.split("\n") 
: [""];
+    const headers = ComponentApi.getComponentHeadersList(selectedStep)
+    const exchangeProperties = selectedStep ? 
CamelMetadataApi.getExchangeProperties(selectedStep.dslName) : [];
+    const groups = selectedStep?.dslName === 'FromDefinition' ? ['consumer', 
'common'] : ['producer', 'common']
+    return (
+        <div className="headers">
+            <div className="top">
+                <Title headingLevel="h1" size="md">{title}</Title>
+                {getHeaderMenu()}
+            </div>
+            <Text component={TextVariants.p}>{descriptionLines.at(0)}</Text>
+            {descriptionLines.length > 1 && getDescriptionSection()}
+            {headers.length > 0 && getComponentHeadersSection()}
+            {exchangeProperties.length > 0 && getExchangePropertiesSection()}
+        </div>
+    )
+}
diff --git 
a/karavan-app/src/main/webui/src/designer/utils/IntegrationHeader.tsx 
b/karavan-app/src/main/webui/src/designer/utils/IntegrationHeader.tsx
index 9b75fd5e..be1f998f 100644
--- a/karavan-app/src/main/webui/src/designer/utils/IntegrationHeader.tsx
+++ b/karavan-app/src/main/webui/src/designer/utils/IntegrationHeader.tsx
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 import React from 'react';
-import {FormGroup, TextInput, Title} from "@patternfly/react-core";
+import {FormGroup, TextInput} from "@patternfly/react-core";
 import {useIntegrationStore} from "../DesignerStore";
 import {shallow} from "zustand/shallow";
 
@@ -25,22 +25,8 @@ export function IntegrationHeader () {
 
     const isKamelet = integration.type === 'kamelet';
 
-    function getKameletType(): string {
-        // const labels = integration.metadata.labels;
-        // if (labels && labels.l)
-        // "camel.apache.org/kamelet.type"
-        return '';
-    }
-
     return (
         <div className="headers">
-            {/*<Title headingLevel="h1" size="md">Integration</Title>*/}
-            {/*<FormGroup label="Title" fieldId="title" isRequired>*/}
-            {/*    <TextInput className="text-field" type="text" id="title" 
name="title" isReadOnly*/}
-            {/*               value={*/}
-            {/*                   
CamelUi.titleFromName(this.props.integration.metadata.name)*/}
-            {/*               }/>*/}
-            {/*</FormGroup>*/}
             <FormGroup label="Kind" fieldId="kind" isRequired>
                 <TextInput className="text-field" type="text" id="kind" 
name="kind"
                            value={integration.kind} readOnlyVariant="default"/>
diff --git 
a/karavan-app/src/main/webui/src/expression/ExpressionModalEditor.css 
b/karavan-app/src/main/webui/src/expression/ExpressionModalEditor.css
index 732d3abd..c06a3a60 100644
--- a/karavan-app/src/main/webui/src/expression/ExpressionModalEditor.css
+++ b/karavan-app/src/main/webui/src/expression/ExpressionModalEditor.css
@@ -22,7 +22,6 @@
     height: 100%;
     display: flex;
     flex-direction: column;
-    gap: 16px;
     justify-content: space-between;
     align-items: stretch;
 }
@@ -36,11 +35,19 @@
 .panel-middle {
     /*height: 64px;*/
 }
+@keyframes smooth-appear {
+    to {
+        bottom: 20px;
+        opacity:1;
+    }
+}
 
 .panel-bottom {
     flex: 1;
     height: 100%;
     overflow-y: auto;
+    opacity:0;
+    animation: smooth-appear 1s ease forwards;
 }
 
 .context {
diff --git 
a/karavan-app/src/main/webui/src/expression/ExpressionModalEditor.tsx 
b/karavan-app/src/main/webui/src/expression/ExpressionModalEditor.tsx
index 038c4010..127cbda9 100644
--- a/karavan-app/src/main/webui/src/expression/ExpressionModalEditor.tsx
+++ b/karavan-app/src/main/webui/src/expression/ExpressionModalEditor.tsx
@@ -16,12 +16,14 @@
  */
 import React, {useEffect, useState} from 'react';
 import {
-    Button, Modal, Title, TitleSizes
+    Button, Modal, Switch, Title, TitleSizes
 } from '@patternfly/react-core';
 import Editor from "@monaco-editor/react";
 import {ExpressionBottomPanel} from "./ExpressionBottomPanel";
 import './ExpressionModalEditor.css'
-import {Context, ExpressionFunctions, ExpressionVariables} from 
"./ExpressionContextModel";
+import {ExpressionFunctions, ExpressionVariables} from 
"./ExpressionContextModel";
+import ArrowDown from "@patternfly/react-icons/dist/esm/icons/angle-down-icon";
+import ArrowUp from "@patternfly/react-icons/dist/esm/icons/angle-up-icon";
 
 interface Props {
     name: string,
@@ -37,9 +39,10 @@ interface Props {
 export function ExpressionModalEditor(props: Props) {
 
     const [customCode, setCustomCode] = useState<string | undefined>();
+    const [showVariables, setShowVariables] = useState<boolean>(true);
+    const [key, setKey] = useState<string>('');
 
     useEffect(() => {
-        console.log(title, dslLanguage)
         setCustomCode(props.customCode)
     },[]);
 
@@ -80,7 +83,8 @@ export function ExpressionModalEditor(props: Props) {
             <div className='container'>
                 <div className='panel-top'>
                     <Editor
-                        height="100%"
+                        key={key}
+                        height={"100%"}
                         width="100%"
                         defaultLanguage={'java'}
                         language={'java'}
@@ -98,9 +102,16 @@ export function ExpressionModalEditor(props: Props) {
                         onChange={(value, _) => setCustomCode(value)}
                     />
                 </div>
-                {show && <div className='panel-bottom'>
-                    {dslLanguage && <ExpressionBottomPanel 
dslLanguage={dslLanguage}/>}
-                </div>}
+                <Button style={{padding:"0"}} variant="link" 
icon={showVariables ? <ArrowDown/> : <ArrowUp/>} onClick={e => {
+                    setShowVariables(!showVariables);
+                    setKey(Math.random().toString());
+                    }}
+                />
+                {show && showVariables &&
+                    <div className='panel-bottom'>
+                        {dslLanguage && <ExpressionBottomPanel  
dslLanguage={dslLanguage}/>}
+                    </div>
+                }
             </div>
         </Modal>
     )
diff --git a/karavan-core/src/core/model/CamelMetadata.ts 
b/karavan-core/src/core/model/CamelMetadata.ts
index 64794b7d..8b477919 100644
--- a/karavan-core/src/core/model/CamelMetadata.ts
+++ b/karavan-core/src/core/model/CamelMetadata.ts
@@ -119,6 +119,10 @@ export class CamelMetadataApi {
     static hasLanguage = (name: string): boolean | undefined => {
         return Languages.filter(value => value[0] === name).length > 0;
     }
+
+    static getExchangeProperties = (className: string): ExchangePropertyMeta 
[] => {
+        return CamelModelMetadata.find(e => e.className === 
className)?.exchangeProperties || [];
+    }
 }
 
 export const DataFormats: [string, string, string][] = [
diff --git a/karavan-designer/public/example/demo.camel.yaml 
b/karavan-designer/public/example/demo.camel.yaml
index c02b8092..fc1cbb19 100644
--- a/karavan-designer/public/example/demo.camel.yaml
+++ b/karavan-designer/public/example/demo.camel.yaml
@@ -1,68 +1,3 @@
-#- route:
-#    id: route-a947
-#    nodePrefixId: route-a32
-#    from:
-#      id: from-c489
-#      description: Receive Data
-#      uri: kamelet:aws-ddb-streams-source
-#      steps:
-#        - setHeader:
-#            id: setBody-4434
-#            expression:
-#              simple:
-#                id: simple-abd8
-#                expression: dddddd
-#        - filter:
-#            id: filter-929b
-#            expression:
-#              simple:
-#                id: simple-d932
-#                expression: Hello
-#            steps:
-#              - bean:
-#                  id: bean-120b
-#                  ref: xxx
-#              - log:
-#                  id: log-d86e
-#                  message: ${body}!!!
-#              - to:
-#                  id: to-9f7d
-#                  description: Send notification
-#                  uri: kafka
-#        - to:
-#            id: to-53a3
-#            description: Send payments
-#            uri: amqp
-#- route:
-#    id: route-8609
-#    nodePrefixId: route-ae2
-#    from:
-#      id: from-6aee
-#      uri: timer
-#      steps:
-#        - to:
-#            id: to-2df4
-#            uri: direct
-#            parameters:
-#              name: second_direct
-#        - to:
-#            id: to-e017
-#            uri: direct
-#            parameters:
-#              name: second_direct
-#- route:
-#    id: first-firect
-#    from:
-#      id: from-f155
-#      uri: direct
-#      parameters:
-#        name: first-firect
-#      steps:
-#        - to:
-#            id: to-5c86
-#            uri: direct
-#            parameters:
-#              name: second_direct
 - route:
     id: second_direct
     from:
@@ -84,6 +19,8 @@
         - to:
             id: to-4711
             uri: metrics
+        - aggregate:
+            id: aggregate-2870
 - route:
     id: route-18e5
     nodePrefixId: route-656
@@ -126,137 +63,3 @@
             variableSend: hello
             variableReceive: world
             uri: amqp
-
-
-#      steps:
-#        - marshal:
-#            id: marshal-b68c
-#        - filter:
-#            expression:
-#              simple:
-#                id: simple-1465
-#            id: filter-b351
-#        - choice:
-#            when:
-#              - expression:
-#                  simple:
-#                    id: simple-99bf
-#                id: when-ab5e
-#                steps:
-#                  - to:
-#                      uri: arangodb
-#                      id: to-f70a
-#                  - removeProperties:
-#                      id: removeProperties-344a
-#              - expression:
-#                  simple:
-#                    id: simple-d199
-#                id: when-37cd
-#                steps:
-#                  - to:
-#                      uri: amqp
-#                      id: to-fbfe
-#                  - choice:
-#                      when:
-#                        - expression:
-#                            simple:
-#                              id: simple-e78b
-#                          id: when-b7d0
-#                      otherwise:
-#                        id: otherwise-40d0
-#                      id: choice-8f6b
-#            otherwise:
-#              id: otherwise-382c
-#              steps:
-#                - log:
-#                    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-171
-#    id: route-99f9
-#    from:
-#      uri: kamelet:azure-storage-blob-source
-#      id: from-f8e9
-#      steps:
-#        - multicast:
-#            id: multicast-6a53
-#            steps:
-#              - log:
-#                  message: ${body}
-#                  id: log-799d
-#              - log:
-#                  message: ${body}
-#                  id: log-fc8e
-#              - log:
-#                  message: ${body}
-#                  id: log-1e42
-#        - filter:
-#            expression:
-#              simple:
-#                id: simple-7ff9
-#            id: filter-8c99
-#            steps:
-#              - process:
-#                  id: process-e1c1
-#                  description: Call cutom java bean
-#              - delay:
-#                  expression:
-#                    simple:
-#                      id: simple-64a6
-#                  id: delay-b1ec
-#        - doTry:
-#            id: doTry-46cd
-#            doCatch:
-#              - id: doCatch-c6e7
-#                steps:
-#                  - log:
-#                      message: ${body}
-#                      id: log-77df
-#                  - choice:
-#                      when:
-#                        - expression:
-#                            simple:
-#                              id: simple-c7db
-#                          id: when-f058
-#                      otherwise:
-#                        id: otherwise-1e11
-#                      id: choice-8374
-#                  - wireTap:
-#                      id: wireTap-a25e
-#            doFinally:
-#              id: doFinally-0a65
-#              steps:
-#                - log:
-#                    message: ${body}
-#                    id: log-f4fa
-#                - log:
-#                    message: ${body}
-#                    id: log-cd30
-#            steps:
-#              - pollEnrich:
-#                  expression:
-#                    simple:
-#                      id: simple-6181
-#                  id: pollEnrich-a41b
-#              - filter:
-#                  expression:
-#                    simple:
-#                      id: simple-a69b
-#                  id: filter-07cf
-#                  steps:
-#                    - setBody:
-#                        expression:
-#                          simple:
-#                            id: simple-f0dc
-#                        id: setBody-3c0c
-#              - process:
-#                  id: process-6d06
-#        - circuitBreaker:
-#            id: circuitBreaker-4af8
\ No newline at end of file
diff --git a/karavan-designer/src/designer/property/DslProperties.tsx 
b/karavan-designer/src/designer/property/DslProperties.tsx
index 656d816c..7448351c 100644
--- a/karavan-designer/src/designer/property/DslProperties.tsx
+++ b/karavan-designer/src/designer/property/DslProperties.tsx
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-import React, {useEffect, useState} from 'react';
+import React, {useState} from 'react';
 import {
     Form,
     Text,
@@ -23,11 +23,6 @@ import {
     ExpandableSection,
     Button,
     Tooltip,
-    Dropdown,
-    MenuToggleElement,
-    MenuToggle,
-    DropdownList,
-    DropdownItem, Flex, Popover, FlexItem, Badge, ClipboardCopy,
 } from '@patternfly/react-core';
 import '../karavan.css';
 import './DslProperties.css';
@@ -43,9 +38,7 @@ import {useDesignerStore, useIntegrationStore} from 
"../DesignerStore";
 import {shallow} from "zustand/shallow";
 import {usePropertiesHook} from "./usePropertiesHook";
 import {CamelDisplayUtil} from "karavan-core/lib/api/CamelDisplayUtil";
-import EllipsisVIcon from 
'@patternfly/react-icons/dist/esm/icons/ellipsis-v-icon';
-import {ComponentApi} from "karavan-core/lib/api/ComponentApi";
-import HelpIcon from "@patternfly/react-icons/dist/js/icons/help-icon";
+import {PropertiesHeader} from "./PropertiesHeader";
 
 interface Props {
     designerType: 'routes' | 'rest' | 'beans'
@@ -56,8 +49,6 @@ export function DslProperties(props: Props) {
     const [integration] = useIntegrationStore((s) => [s.integration], shallow)
 
     const {
-        saveAsRoute,
-        convertStep,
         cloneElement,
         onDataFormatChange,
         onPropertyChange,
@@ -70,135 +61,6 @@ export function DslProperties(props: Props) {
         = useDesignerStore((s) => [s.selectedStep, s.dark], shallow)
 
     const [showAdvanced, setShowAdvanced] = useState<boolean>(false);
-    const [isDescriptionExpanded, setIsDescriptionExpanded] = 
useState<boolean>(false);
-    const [isMenuOpen, setMenuOpen] = useState<boolean>(false);
-
-    useEffect(() => {
-        setMenuOpen(false)
-    }, [selectedStep])
-
-    function getHeaderMenu(): JSX.Element {
-        const hasSteps = selectedStep?.hasSteps();
-        const targetDsl = CamelUi.getConvertTargetDsl(selectedStep?.dslName);
-        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>
-                    {hasSteps &&
-                        <DropdownItem key="saveRoute" onClick={(ev) => {
-                            ev.preventDefault()
-                            if (selectedStep) {
-                                saveAsRoute(selectedStep, true);
-                                setMenuOpen(false);
-                            }
-                        }}>
-                            Save Steps to Route
-                        </DropdownItem>}
-                    {hasSteps &&
-                        <DropdownItem key="saveRoute" 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> : <></>;
-    }
-
-    function getRouteHeader(): JSX.Element {
-        const title = selectedStep && CamelDisplayUtil.getTitle(selectedStep)
-        const description = selectedStep && 
CamelDisplayUtil.getDescription(selectedStep);
-        const descriptionLines: string [] = description ? 
description?.split("\n") : [""];
-        const headers = ComponentApi.getComponentHeadersList(selectedStep)
-        const groups = selectedStep?.dslName === 'FromDefinition' ? 
['consumer', 'common'] : ['producer', 'common']
-        return (
-            <div className="headers">
-                <div className="top">
-                    <Title headingLevel="h1" size="md">{title}</Title>
-                    {getHeaderMenu()}
-                </div>
-                <Text 
component={TextVariants.p}>{descriptionLines.at(0)}</Text>
-                {descriptionLines.length > 1 &&
-                    <ExpandableSection toggleText={isDescriptionExpanded ? 
'Show less' : 'Show more'}
-                                       onToggle={(_event, isExpanded) => 
setIsDescriptionExpanded(!isDescriptionExpanded)}
-                                       isExpanded={isDescriptionExpanded}>
-                        {descriptionLines.filter((value, index) => index > 0)
-                            .map((desc, index, array) => <Text key={index} 
component={TextVariants.p}>{desc}</Text>)}
-                    </ExpandableSection>}
-
-                {headers.length > 0 &&
-                    <ExpandableSection toggleText='Headers'
-                                       onToggle={(_event, isExpanded) => 
setIsDescriptionExpanded(!isDescriptionExpanded)}
-                                       isExpanded={isDescriptionExpanded}>
-                        <Flex className='component-headers' 
direction={{default:"column"}}>
-                            {headers.filter((header) => 
groups.includes(header.group))
-                                .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.group}</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>}
-            </div>
-        )
-    }
 
     function getClonableElementHeader(): JSX.Element {
         const title = selectedStep && CamelDisplayUtil.getTitle(selectedStep);
@@ -219,7 +81,7 @@ export function DslProperties(props: Props) {
     }
 
     function getComponentHeader(): JSX.Element {
-        if (props.designerType === 'routes') return getRouteHeader()
+        if (props.designerType === 'routes') return <PropertiesHeader 
designerType={props.designerType} />
         else return getClonableElementHeader();
     }
 
diff --git a/karavan-designer/src/designer/property/PropertiesHeader.tsx 
b/karavan-designer/src/designer/property/PropertiesHeader.tsx
new file mode 100644
index 00000000..9a38fa13
--- /dev/null
+++ b/karavan-designer/src/designer/property/PropertiesHeader.tsx
@@ -0,0 +1,239 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import React, {useEffect, useState} from 'react';
+import {
+    Text,
+    Title,
+    TextVariants,
+    ExpandableSection,
+    Dropdown,
+    MenuToggleElement,
+    MenuToggle,
+    DropdownList,
+    DropdownItem, Flex, Popover, FlexItem, Badge, ClipboardCopy,
+} from '@patternfly/react-core';
+import '../karavan.css';
+import './DslProperties.css';
+import "@patternfly/patternfly/patternfly.css";
+import {CamelUi} from "../utils/CamelUi";
+import {useDesignerStore} from "../DesignerStore";
+import {shallow} from "zustand/shallow";
+import {usePropertiesHook} from "./usePropertiesHook";
+import {CamelDisplayUtil} from "karavan-core/lib/api/CamelDisplayUtil";
+import EllipsisVIcon from 
'@patternfly/react-icons/dist/esm/icons/ellipsis-v-icon';
+import {ComponentApi} from "karavan-core/lib/api/ComponentApi";
+import HelpIcon from "@patternfly/react-icons/dist/js/icons/help-icon";
+import {CamelMetadataApi} from "karavan-core/lib/model/CamelMetadata";
+
+interface Props {
+    designerType: 'routes' | 'rest' | 'beans'
+}
+
+export function PropertiesHeader(props: Props) {
+
+    const {
+        saveAsRoute,
+        convertStep,
+    } =
+        usePropertiesHook(props.designerType);
+
+    const [selectedStep, dark]
+        = useDesignerStore((s) => [s.selectedStep, s.dark], shallow)
+
+    const [isDescriptionExpanded, setIsDescriptionExpanded] = 
useState<boolean>(false);
+    const [isHeadersExpanded, setIsHeadersExpanded] = useState<boolean>(false);
+    const [isExchangePropertiesExpanded, setIsExchangePropertiesExpanded] = 
useState<boolean>(false);
+    const [isMenuOpen, setMenuOpen] = useState<boolean>(false);
+
+    useEffect(() => {
+        setMenuOpen(false)
+    }, [selectedStep])
+
+    function getHeaderMenu(): React.JSX.Element {
+        const hasSteps = selectedStep?.hasSteps();
+        const targetDsl = CamelUi.getConvertTargetDsl(selectedStep?.dslName);
+        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>
+                    {hasSteps &&
+                        <DropdownItem key="saveRoute" onClick={(ev) => {
+                            ev.preventDefault()
+                            if (selectedStep) {
+                                saveAsRoute(selectedStep, true);
+                                setMenuOpen(false);
+                            }
+                        }}>
+                            Save Steps to Route
+                        </DropdownItem>}
+                    {hasSteps &&
+                        <DropdownItem key="saveRoute" 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> : <></>;
+    }
+
+    function getExchangePropertiesSection(): React.JSX.Element {
+        return (
+            <ExpandableSection toggleText='Exchange Properties'
+                               onToggle={(_event, isExpanded) => 
setIsExchangePropertiesExpanded(!isExchangePropertiesExpanded)}
+                               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>
+            </ExpandableSection>
+        )
+    }
+
+    function getComponentHeadersSection(): React.JSX.Element {
+        return (
+            <ExpandableSection toggleText='Headers'
+                               onToggle={(_event, isExpanded) => 
setIsHeadersExpanded(!isHeadersExpanded)}
+                               isExpanded={isHeadersExpanded}>
+                <Flex className='component-headers' direction={{default: 
"column"}}>
+                    {headers.filter((header) => groups.includes(header.group))
+                        .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.group}</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>
+        )
+    }
+
+    function getDescriptionSection(): React.JSX.Element {
+        return (
+            <ExpandableSection toggleText={isDescriptionExpanded ? 'Show less' 
: 'Show more'}
+                               onToggle={(_event, isExpanded) => 
setIsDescriptionExpanded(!isDescriptionExpanded)}
+                               isExpanded={isDescriptionExpanded}>
+                {descriptionLines.filter((value, index) => index > 0)
+                    .map((desc, index, array) => <Text key={index} 
component={TextVariants.p}>{desc}</Text>)}
+            </ExpandableSection>
+        )
+    }
+
+    const title = selectedStep && CamelDisplayUtil.getTitle(selectedStep)
+    const description = selectedStep && 
CamelDisplayUtil.getDescription(selectedStep);
+    const descriptionLines: string [] = description ? description?.split("\n") 
: [""];
+    const headers = ComponentApi.getComponentHeadersList(selectedStep)
+    const exchangeProperties = selectedStep ? 
CamelMetadataApi.getExchangeProperties(selectedStep.dslName) : [];
+    const groups = selectedStep?.dslName === 'FromDefinition' ? ['consumer', 
'common'] : ['producer', 'common']
+    return (
+        <div className="headers">
+            <div className="top">
+                <Title headingLevel="h1" size="md">{title}</Title>
+                {getHeaderMenu()}
+            </div>
+            <Text component={TextVariants.p}>{descriptionLines.at(0)}</Text>
+            {descriptionLines.length > 1 && getDescriptionSection()}
+            {headers.length > 0 && getComponentHeadersSection()}
+            {exchangeProperties.length > 0 && getExchangePropertiesSection()}
+        </div>
+    )
+}
diff --git a/karavan-designer/src/designer/utils/IntegrationHeader.tsx 
b/karavan-designer/src/designer/utils/IntegrationHeader.tsx
index 9b75fd5e..be1f998f 100644
--- a/karavan-designer/src/designer/utils/IntegrationHeader.tsx
+++ b/karavan-designer/src/designer/utils/IntegrationHeader.tsx
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 import React from 'react';
-import {FormGroup, TextInput, Title} from "@patternfly/react-core";
+import {FormGroup, TextInput} from "@patternfly/react-core";
 import {useIntegrationStore} from "../DesignerStore";
 import {shallow} from "zustand/shallow";
 
@@ -25,22 +25,8 @@ export function IntegrationHeader () {
 
     const isKamelet = integration.type === 'kamelet';
 
-    function getKameletType(): string {
-        // const labels = integration.metadata.labels;
-        // if (labels && labels.l)
-        // "camel.apache.org/kamelet.type"
-        return '';
-    }
-
     return (
         <div className="headers">
-            {/*<Title headingLevel="h1" size="md">Integration</Title>*/}
-            {/*<FormGroup label="Title" fieldId="title" isRequired>*/}
-            {/*    <TextInput className="text-field" type="text" id="title" 
name="title" isReadOnly*/}
-            {/*               value={*/}
-            {/*                   
CamelUi.titleFromName(this.props.integration.metadata.name)*/}
-            {/*               }/>*/}
-            {/*</FormGroup>*/}
             <FormGroup label="Kind" fieldId="kind" isRequired>
                 <TextInput className="text-field" type="text" id="kind" 
name="kind"
                            value={integration.kind} readOnlyVariant="default"/>
diff --git a/karavan-generator/src/main/resources/CamelMetadata.header.ts 
b/karavan-generator/src/main/resources/CamelMetadata.header.ts
index 89e7eaa2..266481d7 100644
--- a/karavan-generator/src/main/resources/CamelMetadata.header.ts
+++ b/karavan-generator/src/main/resources/CamelMetadata.header.ts
@@ -119,4 +119,8 @@ export class CamelMetadataApi {
     static hasLanguage = (name: string): boolean | undefined => {
         return Languages.filter(value => value[0] === name).length > 0;
     }
+
+    static getExchangeProperties = (className: string): ExchangePropertyMeta 
[] => {
+        return CamelModelMetadata.find(e => e.className === 
className)?.exchangeProperties || [];
+    }
 }
diff --git a/karavan-space/src/designer/property/DslProperties.tsx 
b/karavan-space/src/designer/property/DslProperties.tsx
index 656d816c..7448351c 100644
--- a/karavan-space/src/designer/property/DslProperties.tsx
+++ b/karavan-space/src/designer/property/DslProperties.tsx
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-import React, {useEffect, useState} from 'react';
+import React, {useState} from 'react';
 import {
     Form,
     Text,
@@ -23,11 +23,6 @@ import {
     ExpandableSection,
     Button,
     Tooltip,
-    Dropdown,
-    MenuToggleElement,
-    MenuToggle,
-    DropdownList,
-    DropdownItem, Flex, Popover, FlexItem, Badge, ClipboardCopy,
 } from '@patternfly/react-core';
 import '../karavan.css';
 import './DslProperties.css';
@@ -43,9 +38,7 @@ import {useDesignerStore, useIntegrationStore} from 
"../DesignerStore";
 import {shallow} from "zustand/shallow";
 import {usePropertiesHook} from "./usePropertiesHook";
 import {CamelDisplayUtil} from "karavan-core/lib/api/CamelDisplayUtil";
-import EllipsisVIcon from 
'@patternfly/react-icons/dist/esm/icons/ellipsis-v-icon';
-import {ComponentApi} from "karavan-core/lib/api/ComponentApi";
-import HelpIcon from "@patternfly/react-icons/dist/js/icons/help-icon";
+import {PropertiesHeader} from "./PropertiesHeader";
 
 interface Props {
     designerType: 'routes' | 'rest' | 'beans'
@@ -56,8 +49,6 @@ export function DslProperties(props: Props) {
     const [integration] = useIntegrationStore((s) => [s.integration], shallow)
 
     const {
-        saveAsRoute,
-        convertStep,
         cloneElement,
         onDataFormatChange,
         onPropertyChange,
@@ -70,135 +61,6 @@ export function DslProperties(props: Props) {
         = useDesignerStore((s) => [s.selectedStep, s.dark], shallow)
 
     const [showAdvanced, setShowAdvanced] = useState<boolean>(false);
-    const [isDescriptionExpanded, setIsDescriptionExpanded] = 
useState<boolean>(false);
-    const [isMenuOpen, setMenuOpen] = useState<boolean>(false);
-
-    useEffect(() => {
-        setMenuOpen(false)
-    }, [selectedStep])
-
-    function getHeaderMenu(): JSX.Element {
-        const hasSteps = selectedStep?.hasSteps();
-        const targetDsl = CamelUi.getConvertTargetDsl(selectedStep?.dslName);
-        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>
-                    {hasSteps &&
-                        <DropdownItem key="saveRoute" onClick={(ev) => {
-                            ev.preventDefault()
-                            if (selectedStep) {
-                                saveAsRoute(selectedStep, true);
-                                setMenuOpen(false);
-                            }
-                        }}>
-                            Save Steps to Route
-                        </DropdownItem>}
-                    {hasSteps &&
-                        <DropdownItem key="saveRoute" 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> : <></>;
-    }
-
-    function getRouteHeader(): JSX.Element {
-        const title = selectedStep && CamelDisplayUtil.getTitle(selectedStep)
-        const description = selectedStep && 
CamelDisplayUtil.getDescription(selectedStep);
-        const descriptionLines: string [] = description ? 
description?.split("\n") : [""];
-        const headers = ComponentApi.getComponentHeadersList(selectedStep)
-        const groups = selectedStep?.dslName === 'FromDefinition' ? 
['consumer', 'common'] : ['producer', 'common']
-        return (
-            <div className="headers">
-                <div className="top">
-                    <Title headingLevel="h1" size="md">{title}</Title>
-                    {getHeaderMenu()}
-                </div>
-                <Text 
component={TextVariants.p}>{descriptionLines.at(0)}</Text>
-                {descriptionLines.length > 1 &&
-                    <ExpandableSection toggleText={isDescriptionExpanded ? 
'Show less' : 'Show more'}
-                                       onToggle={(_event, isExpanded) => 
setIsDescriptionExpanded(!isDescriptionExpanded)}
-                                       isExpanded={isDescriptionExpanded}>
-                        {descriptionLines.filter((value, index) => index > 0)
-                            .map((desc, index, array) => <Text key={index} 
component={TextVariants.p}>{desc}</Text>)}
-                    </ExpandableSection>}
-
-                {headers.length > 0 &&
-                    <ExpandableSection toggleText='Headers'
-                                       onToggle={(_event, isExpanded) => 
setIsDescriptionExpanded(!isDescriptionExpanded)}
-                                       isExpanded={isDescriptionExpanded}>
-                        <Flex className='component-headers' 
direction={{default:"column"}}>
-                            {headers.filter((header) => 
groups.includes(header.group))
-                                .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.group}</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>}
-            </div>
-        )
-    }
 
     function getClonableElementHeader(): JSX.Element {
         const title = selectedStep && CamelDisplayUtil.getTitle(selectedStep);
@@ -219,7 +81,7 @@ export function DslProperties(props: Props) {
     }
 
     function getComponentHeader(): JSX.Element {
-        if (props.designerType === 'routes') return getRouteHeader()
+        if (props.designerType === 'routes') return <PropertiesHeader 
designerType={props.designerType} />
         else return getClonableElementHeader();
     }
 
diff --git a/karavan-space/src/designer/property/PropertiesHeader.tsx 
b/karavan-space/src/designer/property/PropertiesHeader.tsx
new file mode 100644
index 00000000..9a38fa13
--- /dev/null
+++ b/karavan-space/src/designer/property/PropertiesHeader.tsx
@@ -0,0 +1,239 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import React, {useEffect, useState} from 'react';
+import {
+    Text,
+    Title,
+    TextVariants,
+    ExpandableSection,
+    Dropdown,
+    MenuToggleElement,
+    MenuToggle,
+    DropdownList,
+    DropdownItem, Flex, Popover, FlexItem, Badge, ClipboardCopy,
+} from '@patternfly/react-core';
+import '../karavan.css';
+import './DslProperties.css';
+import "@patternfly/patternfly/patternfly.css";
+import {CamelUi} from "../utils/CamelUi";
+import {useDesignerStore} from "../DesignerStore";
+import {shallow} from "zustand/shallow";
+import {usePropertiesHook} from "./usePropertiesHook";
+import {CamelDisplayUtil} from "karavan-core/lib/api/CamelDisplayUtil";
+import EllipsisVIcon from 
'@patternfly/react-icons/dist/esm/icons/ellipsis-v-icon';
+import {ComponentApi} from "karavan-core/lib/api/ComponentApi";
+import HelpIcon from "@patternfly/react-icons/dist/js/icons/help-icon";
+import {CamelMetadataApi} from "karavan-core/lib/model/CamelMetadata";
+
+interface Props {
+    designerType: 'routes' | 'rest' | 'beans'
+}
+
+export function PropertiesHeader(props: Props) {
+
+    const {
+        saveAsRoute,
+        convertStep,
+    } =
+        usePropertiesHook(props.designerType);
+
+    const [selectedStep, dark]
+        = useDesignerStore((s) => [s.selectedStep, s.dark], shallow)
+
+    const [isDescriptionExpanded, setIsDescriptionExpanded] = 
useState<boolean>(false);
+    const [isHeadersExpanded, setIsHeadersExpanded] = useState<boolean>(false);
+    const [isExchangePropertiesExpanded, setIsExchangePropertiesExpanded] = 
useState<boolean>(false);
+    const [isMenuOpen, setMenuOpen] = useState<boolean>(false);
+
+    useEffect(() => {
+        setMenuOpen(false)
+    }, [selectedStep])
+
+    function getHeaderMenu(): React.JSX.Element {
+        const hasSteps = selectedStep?.hasSteps();
+        const targetDsl = CamelUi.getConvertTargetDsl(selectedStep?.dslName);
+        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>
+                    {hasSteps &&
+                        <DropdownItem key="saveRoute" onClick={(ev) => {
+                            ev.preventDefault()
+                            if (selectedStep) {
+                                saveAsRoute(selectedStep, true);
+                                setMenuOpen(false);
+                            }
+                        }}>
+                            Save Steps to Route
+                        </DropdownItem>}
+                    {hasSteps &&
+                        <DropdownItem key="saveRoute" 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> : <></>;
+    }
+
+    function getExchangePropertiesSection(): React.JSX.Element {
+        return (
+            <ExpandableSection toggleText='Exchange Properties'
+                               onToggle={(_event, isExpanded) => 
setIsExchangePropertiesExpanded(!isExchangePropertiesExpanded)}
+                               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>
+            </ExpandableSection>
+        )
+    }
+
+    function getComponentHeadersSection(): React.JSX.Element {
+        return (
+            <ExpandableSection toggleText='Headers'
+                               onToggle={(_event, isExpanded) => 
setIsHeadersExpanded(!isHeadersExpanded)}
+                               isExpanded={isHeadersExpanded}>
+                <Flex className='component-headers' direction={{default: 
"column"}}>
+                    {headers.filter((header) => groups.includes(header.group))
+                        .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.group}</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>
+        )
+    }
+
+    function getDescriptionSection(): React.JSX.Element {
+        return (
+            <ExpandableSection toggleText={isDescriptionExpanded ? 'Show less' 
: 'Show more'}
+                               onToggle={(_event, isExpanded) => 
setIsDescriptionExpanded(!isDescriptionExpanded)}
+                               isExpanded={isDescriptionExpanded}>
+                {descriptionLines.filter((value, index) => index > 0)
+                    .map((desc, index, array) => <Text key={index} 
component={TextVariants.p}>{desc}</Text>)}
+            </ExpandableSection>
+        )
+    }
+
+    const title = selectedStep && CamelDisplayUtil.getTitle(selectedStep)
+    const description = selectedStep && 
CamelDisplayUtil.getDescription(selectedStep);
+    const descriptionLines: string [] = description ? description?.split("\n") 
: [""];
+    const headers = ComponentApi.getComponentHeadersList(selectedStep)
+    const exchangeProperties = selectedStep ? 
CamelMetadataApi.getExchangeProperties(selectedStep.dslName) : [];
+    const groups = selectedStep?.dslName === 'FromDefinition' ? ['consumer', 
'common'] : ['producer', 'common']
+    return (
+        <div className="headers">
+            <div className="top">
+                <Title headingLevel="h1" size="md">{title}</Title>
+                {getHeaderMenu()}
+            </div>
+            <Text component={TextVariants.p}>{descriptionLines.at(0)}</Text>
+            {descriptionLines.length > 1 && getDescriptionSection()}
+            {headers.length > 0 && getComponentHeadersSection()}
+            {exchangeProperties.length > 0 && getExchangePropertiesSection()}
+        </div>
+    )
+}
diff --git a/karavan-space/src/designer/utils/IntegrationHeader.tsx 
b/karavan-space/src/designer/utils/IntegrationHeader.tsx
index 9b75fd5e..be1f998f 100644
--- a/karavan-space/src/designer/utils/IntegrationHeader.tsx
+++ b/karavan-space/src/designer/utils/IntegrationHeader.tsx
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 import React from 'react';
-import {FormGroup, TextInput, Title} from "@patternfly/react-core";
+import {FormGroup, TextInput} from "@patternfly/react-core";
 import {useIntegrationStore} from "../DesignerStore";
 import {shallow} from "zustand/shallow";
 
@@ -25,22 +25,8 @@ export function IntegrationHeader () {
 
     const isKamelet = integration.type === 'kamelet';
 
-    function getKameletType(): string {
-        // const labels = integration.metadata.labels;
-        // if (labels && labels.l)
-        // "camel.apache.org/kamelet.type"
-        return '';
-    }
-
     return (
         <div className="headers">
-            {/*<Title headingLevel="h1" size="md">Integration</Title>*/}
-            {/*<FormGroup label="Title" fieldId="title" isRequired>*/}
-            {/*    <TextInput className="text-field" type="text" id="title" 
name="title" isReadOnly*/}
-            {/*               value={*/}
-            {/*                   
CamelUi.titleFromName(this.props.integration.metadata.name)*/}
-            {/*               }/>*/}
-            {/*</FormGroup>*/}
             <FormGroup label="Kind" fieldId="kind" isRequired>
                 <TextInput className="text-field" type="text" id="kind" 
name="kind"
                            value={integration.kind} readOnlyVariant="default"/>
diff --git a/karavan-space/src/expression/ExpressionModalEditor.css 
b/karavan-space/src/expression/ExpressionModalEditor.css
index 732d3abd..c06a3a60 100644
--- a/karavan-space/src/expression/ExpressionModalEditor.css
+++ b/karavan-space/src/expression/ExpressionModalEditor.css
@@ -22,7 +22,6 @@
     height: 100%;
     display: flex;
     flex-direction: column;
-    gap: 16px;
     justify-content: space-between;
     align-items: stretch;
 }
@@ -36,11 +35,19 @@
 .panel-middle {
     /*height: 64px;*/
 }
+@keyframes smooth-appear {
+    to {
+        bottom: 20px;
+        opacity:1;
+    }
+}
 
 .panel-bottom {
     flex: 1;
     height: 100%;
     overflow-y: auto;
+    opacity:0;
+    animation: smooth-appear 1s ease forwards;
 }
 
 .context {
diff --git a/karavan-space/src/expression/ExpressionModalEditor.tsx 
b/karavan-space/src/expression/ExpressionModalEditor.tsx
index 038c4010..127cbda9 100644
--- a/karavan-space/src/expression/ExpressionModalEditor.tsx
+++ b/karavan-space/src/expression/ExpressionModalEditor.tsx
@@ -16,12 +16,14 @@
  */
 import React, {useEffect, useState} from 'react';
 import {
-    Button, Modal, Title, TitleSizes
+    Button, Modal, Switch, Title, TitleSizes
 } from '@patternfly/react-core';
 import Editor from "@monaco-editor/react";
 import {ExpressionBottomPanel} from "./ExpressionBottomPanel";
 import './ExpressionModalEditor.css'
-import {Context, ExpressionFunctions, ExpressionVariables} from 
"./ExpressionContextModel";
+import {ExpressionFunctions, ExpressionVariables} from 
"./ExpressionContextModel";
+import ArrowDown from "@patternfly/react-icons/dist/esm/icons/angle-down-icon";
+import ArrowUp from "@patternfly/react-icons/dist/esm/icons/angle-up-icon";
 
 interface Props {
     name: string,
@@ -37,9 +39,10 @@ interface Props {
 export function ExpressionModalEditor(props: Props) {
 
     const [customCode, setCustomCode] = useState<string | undefined>();
+    const [showVariables, setShowVariables] = useState<boolean>(true);
+    const [key, setKey] = useState<string>('');
 
     useEffect(() => {
-        console.log(title, dslLanguage)
         setCustomCode(props.customCode)
     },[]);
 
@@ -80,7 +83,8 @@ export function ExpressionModalEditor(props: Props) {
             <div className='container'>
                 <div className='panel-top'>
                     <Editor
-                        height="100%"
+                        key={key}
+                        height={"100%"}
                         width="100%"
                         defaultLanguage={'java'}
                         language={'java'}
@@ -98,9 +102,16 @@ export function ExpressionModalEditor(props: Props) {
                         onChange={(value, _) => setCustomCode(value)}
                     />
                 </div>
-                {show && <div className='panel-bottom'>
-                    {dslLanguage && <ExpressionBottomPanel 
dslLanguage={dslLanguage}/>}
-                </div>}
+                <Button style={{padding:"0"}} variant="link" 
icon={showVariables ? <ArrowDown/> : <ArrowUp/>} onClick={e => {
+                    setShowVariables(!showVariables);
+                    setKey(Math.random().toString());
+                    }}
+                />
+                {show && showVariables &&
+                    <div className='panel-bottom'>
+                        {dslLanguage && <ExpressionBottomPanel  
dslLanguage={dslLanguage}/>}
+                    </div>
+                }
             </div>
         </Modal>
     )

Reply via email to