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 c0ff8484fce7b6efce7da076dd75833e816702e8
Author: Marat Gubaidullin <marat.gubaidul...@gmail.com>
AuthorDate: Tue Jan 10 22:31:53 2023 -0500

    App UI improvements
---
 .../main/webui/src/designer/KaravanDesigner.tsx    |  5 --
 .../src/main/webui/src/designer/karavan.css        |  1 +
 .../main/webui/src/designer/route/DslElement.tsx   | 22 +++--
 .../webui/src/designer/route/RouteDesigner.tsx     | 52 ++++++++++--
 .../route/property/ComponentParameterField.tsx     |  1 +
 .../src/main/webui/src/designer/utils/CamelUi.tsx  | 15 +++-
 .../main/webui/src/designer/utils/KaravanIcons.tsx | 99 ++++++++++++++++++++++
 .../src/main/webui/src/projects/ProjectPage.tsx    |  6 +-
 8 files changed, 176 insertions(+), 25 deletions(-)

diff --git a/karavan-app/src/main/webui/src/designer/KaravanDesigner.tsx 
b/karavan-app/src/main/webui/src/designer/KaravanDesigner.tsx
index b4ac345..e7f975b 100644
--- a/karavan-app/src/main/webui/src/designer/KaravanDesigner.tsx
+++ b/karavan-app/src/main/webui/src/designer/KaravanDesigner.tsx
@@ -27,7 +27,6 @@ import {CamelUtil} from "karavan-core/lib/api/CamelUtil";
 import {CamelUi} from "./utils/CamelUi";
 import {BeansDesigner} from "./beans/BeansDesigner";
 import {RestDesigner} from "./rest/RestDesigner";
-import {RouteConfigurationDesigner} from 
"./configuration/RouteConfigurationDesigner";
 import {getDesignerIcon} from "./utils/KaravanIcons";
 
 interface Props {
@@ -132,7 +131,6 @@ export class KaravanDesigner extends React.Component<Props, 
State> {
                     <Tab eventKey='routes' title={this.getTab("Routes", 
"Integration flows", "routes")}></Tab>
                     <Tab eventKey='rest' title={this.getTab("REST", "REST 
services", "rest")}></Tab>
                     <Tab eventKey='beans' title={this.getTab("Beans", "Beans 
Configuration", "beans")}></Tab>
-                    <Tab eventKey='routeConfiguration' 
title={this.getTab("Configuration", "Route Configuration", 
"routeConfiguration")}></Tab>
                 </Tabs>
                     {tab === 'routes' && <RouteDesigner 
integration={this.state.integration}
                                                         onSave={(integration, 
propertyOnly) => this.save(integration, propertyOnly)}
@@ -144,9 +142,6 @@ export class KaravanDesigner extends React.Component<Props, 
State> {
                     {tab === 'beans' && <BeansDesigner 
integration={this.state.integration}
                                                        onSave={(integration, 
propertyOnly) => this.save(integration, propertyOnly)}
                                                        
dark={this.props.dark}/>}
-                    {tab === 'routeConfiguration' && 
<RouteConfigurationDesigner integration={this.state.integration}
-                                                              
onSave={(integration, propertyOnly) => this.save(integration, propertyOnly)}
-                                                              
dark={this.props.dark}/>}
             </PageSection>
         )
     }
diff --git a/karavan-app/src/main/webui/src/designer/karavan.css 
b/karavan-app/src/main/webui/src/designer/karavan.css
index 2ae90aa..3598b1a 100644
--- a/karavan-app/src/main/webui/src/designer/karavan.css
+++ b/karavan-app/src/main/webui/src/designer/karavan.css
@@ -525,6 +525,7 @@
     margin-top: 16px;
     display: flex;
     justify-content: center;
+    gap: 6px;
 }
 
 /*connections*/
diff --git a/karavan-app/src/main/webui/src/designer/route/DslElement.tsx 
b/karavan-app/src/main/webui/src/designer/route/DslElement.tsx
index 31ee222..868f3e2 100644
--- a/karavan-app/src/main/webui/src/designer/route/DslElement.tsx
+++ b/karavan-app/src/main/webui/src/designer/route/DslElement.tsx
@@ -131,15 +131,19 @@ export class DslElement extends React.Component<Props, 
State> {
 
     hasBorder = (): boolean => {
         return (this.props.step?.hasSteps() && 
!['FromDefinition'].includes(this.props.step.dslName))
-            || ['RouteDefinition', 'TryDefinition', 'ChoiceDefinition', 
'SwitchDefinition'].includes(this.props.step.dslName);
+            || ['RouteConfigurationDefinition',
+                'RouteDefinition',
+                'TryDefinition',
+                'ChoiceDefinition',
+                'SwitchDefinition'].includes(this.props.step.dslName);
     }
 
     isNotDraggable = (): boolean => {
-        return ['FromDefinition', 'RouteDefinition', 'WhenDefinition', 
'OtherwiseDefinition'].includes(this.props.step.dslName);
+        return ['FromDefinition', 'RouteConfigurationDefinition', 
'RouteDefinition', 'WhenDefinition', 
'OtherwiseDefinition'].includes(this.props.step.dslName);
     }
 
     isWide = (): boolean => {
-        return ['RouteDefinition', 'ChoiceDefinition', 'SwitchDefinition', 
'MulticastDefinition', 'TryDefinition', 'CircuitBreakerDefinition']
+        return ['RouteConfigurationDefinition', 'RouteDefinition', 
'ChoiceDefinition', 'SwitchDefinition', 'MulticastDefinition', 'TryDefinition', 
'CircuitBreakerDefinition']
             .includes(this.props.step.dslName);
     }
 
@@ -153,7 +157,7 @@ export class DslElement extends React.Component<Props, 
State> {
     }
 
     isRoot = (): boolean => {
-        return this.props.step?.dslName?.startsWith("RouteDefinition");
+        return ['RouteConfigurationDefinition', 
'RouteDefinition'].includes(this.props.step?.dslName);
     }
 
     isInStepWithChildren = () => {
@@ -224,14 +228,18 @@ export class DslElement extends React.Component<Props, 
State> {
 
     getHeader = () => {
         const step: CamelElement = this.props.step;
+        const parent = this.props.parent;
+        const inRouteConfiguration = parent !== undefined && parent.dslName 
=== 'RouteConfigurationDefinition';
         const availableModels = 
CamelUi.getSelectorModelsForParent(step.dslName, false);
         const showAddButton = !['CatchDefinition', 
'RouteDefinition'].includes(step.dslName) && availableModels.length > 0;
-        const showInsertButton = !['FromDefinition', 'RouteDefinition', 
'CatchDefinition', 'FinallyDefinition', 'WhenDefinition', 
'OtherwiseDefinition'].includes(step.dslName);
-        const headerClass = step.dslName === 'RouteDefinition' ? 
"header-route" : "header"
+        const showInsertButton =
+            !['FromDefinition', 'RouteConfigurationDefinition', 
'RouteDefinition', 'CatchDefinition', 'FinallyDefinition', 'WhenDefinition', 
'OtherwiseDefinition'].includes(step.dslName)
+            && !inRouteConfiguration;
+        const headerClass = ['RouteConfigurationDefinition', 
'RouteDefinition'].includes(step.dslName) ? "header-route" : "header"
         const headerClasses = this.isSelected() ? headerClass + " selected" : 
headerClass;
         return (
             <div className={headerClasses} style={this.getHeaderStyle()}>
-                {this.props.step.dslName !== 'RouteDefinition' &&
+                {!['RouteConfigurationDefinition', 
'RouteDefinition'].includes(this.props.step.dslName) &&
                     <div ref={el => this.sendPosition(el, this.isSelected())}
                          className={"header-icon"}
                          style={this.isWide() ? {width: ""} : {}}>
diff --git a/karavan-app/src/main/webui/src/designer/route/RouteDesigner.tsx 
b/karavan-app/src/main/webui/src/designer/route/RouteDesigner.tsx
index 6c976a9..01c02f7 100644
--- a/karavan-app/src/main/webui/src/designer/route/RouteDesigner.tsx
+++ b/karavan-app/src/main/webui/src/designer/route/RouteDesigner.tsx
@@ -28,7 +28,7 @@ import {DslSelector} from "./DslSelector";
 import {DslMetaModel} from "../utils/DslMetaModel";
 import {DslProperties} from "./DslProperties";
 import {CamelUtil} from "karavan-core/lib/api/CamelUtil";
-import {FromDefinition, RouteDefinition} from 
"karavan-core/lib/model/CamelDefinition";
+import {FromDefinition, RouteConfigurationDefinition, RouteDefinition} from 
"karavan-core/lib/model/CamelDefinition";
 import {CamelElement, Integration} from 
"karavan-core/lib/model/IntegrationDefinition";
 import {CamelDefinitionApiExt} from 
"karavan-core/lib/api/CamelDefinitionApiExt";
 import {CamelDefinitionApi} from "karavan-core/lib/api/CamelDefinitionApi";
@@ -40,7 +40,6 @@ import {CamelUi, RouteToCreate} from "../utils/CamelUi";
 import {findDOMNode} from "react-dom";
 import {CamelDisplayUtil} from "karavan-core/lib/api/CamelDisplayUtil";
 import {toPng} from 'html-to-image';
-import {KaravanDesigner} from "../KaravanDesigner";
 
 interface Props {
     onSave?: (integration: Integration, propertyOnly: boolean) => void
@@ -149,6 +148,7 @@ export class RouteDesigner extends React.Component<Props, 
State> {
     showDeleteConfirmation = (id: string) => {
         let message: string;
         let ce: CamelElement;
+        let isRouteConfiguration: boolean = false;
         ce = 
CamelDefinitionApiExt.findElementInIntegration(this.state.integration, id)!;
         if (ce.dslName === 'FromDefinition') { // Get the RouteDefinition for 
this.  Use its uuid.
             let flows = this.state.integration.spec.flows!;
@@ -164,6 +164,9 @@ export class RouteDesigner extends React.Component<Props, 
State> {
             message = 'Deleting the first element will delete the entire 
route!';
         } else if (ce.dslName === 'RouteDefinition') {
             message = 'Delete route?';
+        } else if (ce.dslName === 'RouteConfigurationDefinition') {
+            message = 'Delete route configuration?';
+            isRouteConfiguration = true;
         } else {
             message = 'Delete element from route?';
         }
@@ -241,6 +244,19 @@ export class RouteDesigner extends React.Component<Props, 
State> {
         }
     }
 
+    createRouteConfiguration = () => {
+        const clone = CamelUtil.cloneIntegration(this.state.integration);
+        const routeConfiguration = new RouteConfigurationDefinition();
+        const i = 
CamelDefinitionApiExt.addRouteConfigurationToIntegration(clone, 
routeConfiguration);
+        this.setState({
+            integration: i,
+            propertyOnly: false,
+            key: Math.random().toString(),
+            selectedStep: routeConfiguration,
+            selectedUuid: routeConfiguration.uuid,
+        });
+    }
+
     addStep = (step: CamelElement, parentId: string, position?: number | 
undefined) => {
         const i = 
CamelDefinitionApiExt.addStepToIntegration(this.state.integration, step, 
parentId, position);
         const clone = CamelUtil.cloneIntegration(i);
@@ -356,21 +372,35 @@ export class RouteDesigner extends React.Component<Props, 
State> {
     }
 
     getGraph() {
-        const routes = CamelUi.getRoutes(this.state.integration);
+        const {selectedUuid, integration, key, width, height, top, left} = 
this.state;
+        const routes = CamelUi.getRoutes(integration);
+        const routeConfigurations = 
CamelUi.getRouteConfigurations(integration);
         return (
             <div ref={this.state.printerRef} className="graph">
-                <DslConnections height={this.state.height} 
width={this.state.width} top={this.state.top}
-                                left={this.state.left} 
integration={this.state.integration}/>
+                <DslConnections height={height} width={width} top={top} 
left={left} integration={integration}/>
                 <div className="flows" data-click="FLOWS" onClick={event => 
this.unselectElement(event)}
                      ref={el => this.onResizePage(el)}>
+                    {routeConfigurations?.map((routeConfiguration , index: 
number) => (
+                        <DslElement key={routeConfiguration.uuid + key}
+                                    integration={integration}
+                                    openSelector={this.openSelector}
+                                    deleteElement={this.showDeleteConfirmation}
+                                    selectElement={this.selectElement}
+                                    moveElement={this.moveElement}
+                                    selectedUuid={selectedUuid}
+                                    inSteps={false}
+                                    position={index}
+                                    step={routeConfiguration}
+                                    parent={undefined}/>
+                    ))}
                     {routes?.map((route: any, index: number) => (
-                        <DslElement key={route.uuid + this.state.key}
-                                    integration={this.state.integration}
+                        <DslElement key={route.uuid + key}
+                                    integration={integration}
                                     openSelector={this.openSelector}
                                     deleteElement={this.showDeleteConfirmation}
                                     selectElement={this.selectElement}
                                     moveElement={this.moveElement}
-                                    selectedUuid={this.state.selectedUuid}
+                                    selectedUuid={selectedUuid}
                                     inSteps={false}
                                     position={index}
                                     step={route}
@@ -379,10 +409,14 @@ export class RouteDesigner extends React.Component<Props, 
State> {
                     <div className="add-flow">
                         <Button
                             variant={routes.length === 0 ? "primary" : 
"secondary"}
-                            data-click="ADD_ROUTE"
                             icon={<PlusIcon/>}
                             onClick={e => this.openSelector(undefined, 
undefined)}>Create new route
                         </Button>
+                        <Button
+                            variant="secondary"
+                            icon={<PlusIcon/>}
+                            onClick={e => 
this.createRouteConfiguration()}>Create new configuration
+                        </Button>
                     </div>
                 </div>
             </div>)
diff --git 
a/karavan-app/src/main/webui/src/designer/route/property/ComponentParameterField.tsx
 
b/karavan-app/src/main/webui/src/designer/route/property/ComponentParameterField.tsx
index 67dd816..7c9ce9d 100644
--- 
a/karavan-app/src/main/webui/src/designer/route/property/ComponentParameterField.tsx
+++ 
b/karavan-app/src/main/webui/src/designer/route/property/ComponentParameterField.tsx
@@ -289,6 +289,7 @@ export class ComponentParameterField extends 
React.Component<Props, State> {
         const property: ComponentProperty = this.props.property;
         const value = this.props.value;
         const id = prefix + "-" + property.name;
+        console.log("property", property)
         return (
             <FormGroup
                 key={id}
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 f4e33c5..ab015ea 100644
--- a/karavan-app/src/main/webui/src/designer/utils/CamelUi.tsx
+++ b/karavan-app/src/main/webui/src/designer/utils/CamelUi.tsx
@@ -21,9 +21,16 @@ import {ComponentApi} from 
"karavan-core/lib/api/ComponentApi";
 import {CamelMetadataApi} from "karavan-core/lib/model/CamelMetadata";
 import {CamelUtil} from "karavan-core/lib/api/CamelUtil";
 import {CamelDefinitionApiExt} from 
"karavan-core/lib/api/CamelDefinitionApiExt";
-import {NamedBeanDefinition, RouteConfigurationDefinition, RouteDefinition, 
SagaDefinition, ToDefinition} from "karavan-core/lib/model/CamelDefinition";
+import {
+    InterceptSendToEndpointDefinition,
+    NamedBeanDefinition,
+    RouteConfigurationDefinition,
+    RouteDefinition,
+    SagaDefinition,
+    ToDefinition
+} from "karavan-core/lib/model/CamelDefinition";
 import {CamelElement, Integration} from 
"karavan-core/lib/model/IntegrationDefinition";
-import {AggregateIcon, ChoiceIcon, FilterIcon, SagaIcon, SortIcon, SplitIcon} 
from "./KaravanIcons";
+import {AggregateIcon, ChoiceIcon, FilterIcon, Intercept, InterceptFrom, 
InterceptSendToEndpoint, OnCompletion, SagaIcon, SortIcon, SplitIcon} from 
"./KaravanIcons";
 import React from "react";
 
 const StepElements: string[] = [
@@ -489,6 +496,10 @@ export class CamelUi {
             case 'SagaDefinition' :return <SagaIcon/>;
             case 'FilterDefinition' :return <FilterIcon/>;
             case 'SortDefinition' :return <SortIcon/>;
+            case 'OnCompletionDefinition' :return <OnCompletion/>;
+            case 'InterceptDefinition' :return <Intercept/>;
+            case 'InterceptFromDefinition' :return <InterceptFrom/>;
+            case 'InterceptSendToEndpointDefinition' :return 
<InterceptSendToEndpoint/>;
             default: return 
this.getIconFromSource(CamelUi.getIconSrcForName(dslName))
         }
     }
diff --git a/karavan-app/src/main/webui/src/designer/utils/KaravanIcons.tsx 
b/karavan-app/src/main/webui/src/designer/utils/KaravanIcons.tsx
index 33206f4..63bb26d 100644
--- a/karavan-app/src/main/webui/src/designer/utils/KaravanIcons.tsx
+++ b/karavan-app/src/main/webui/src/designer/utils/KaravanIcons.tsx
@@ -450,6 +450,105 @@ export function SortIcon() {
     );
 }
 
+export function OnCompletion() {
+    return (
+        <svg
+            className="icon" width="32px" height="32px"
+            xmlns="http://www.w3.org/2000/svg";
+            id="icon"
+            fill="#000"
+            viewBox="0 0 32 32"
+        >
+            <defs>
+                <style>{".cls-1 { fill: none; }"}</style>
+            </defs>
+            <path d="M22 26.59L19.41 24 18 25.41 22 29.41 30 21.41 28.59 20 22 
26.59z"></path>
+            <circle cx="16" cy="16" r="2"></circle>
+            <path d="M16 22a6 6 0 116-6 6.007 6.007 0 01-6 6zm0-10a4 4 0 104 4 
4.005 4.005 0 00-4-4z"></path>
+            <path d="M28 16a12 12 0 10-12 12v-2a10 10 0 1110-10z"></path>
+            <path
+                id="_Transparent_Rectangle_"
+                d="M0 0H32V32H0z"
+                className="cls-1"
+                data-name="&lt;Transparent Rectangle&gt;"
+            ></path>
+        </svg>
+    );
+}
+
+export function Intercept() {
+    return (
+        <svg
+            className="icon" width="32px" height="32px"
+            xmlns="http://www.w3.org/2000/svg";
+            id="icon"
+            fill="#000"
+            viewBox="0 0 32 32"
+        >
+            <defs>
+                <style>{".cls-1 {    fill: none; }"}</style>
+            </defs>
+            <path d="M15 4H17V28H15z"></path>
+            <path d="M10 7v18H4V7h6m0-2H4a2 2 0 00-2 2v18a2 2 0 002 2h6a2 2 0 
002-2V7a2 2 0 00-2-2zM28 7v18h-6V7h6m0-2h-6a2 2 0 00-2 2v18a2 2 0 002 2h6a2 2 0 
002-2V7a2 2 0 00-2-2z"></path>
+            <path
+                id="_Transparent_Rectangle_"
+                d="M0 0H32V32H0z"
+                className="cls-1"
+                data-name="&lt;Transparent Rectangle&gt;"
+            ></path>
+        </svg>
+    );
+}
+
+export function InterceptFrom() {
+    return (
+        <svg
+            className="icon" width="32px" height="32px"
+            xmlns="http://www.w3.org/2000/svg";
+            id="icon"
+            fill="#000"
+            viewBox="0 0 32 32"
+        >
+            <defs>
+                <style>{".cls-1 {    fill: none; }"}</style>
+            </defs>
+            <path d="M26 30H14a2 2 0 01-2-2v-3h2v3h12V4H14v3h-2V4a2 2 0 
012-2h12a2 2 0 012 2v24a2 2 0 01-2 2z"></path>
+            <path d="M14.59 20.59L18.17 17 4 17 4 15 18.17 15 14.59 11.41 16 
10 22 16 16 22 14.59 20.59z"></path>
+            <path
+                id="_Transparent_Rectangle_"
+                d="M0 0H32V32H0z"
+                className="cls-1"
+                data-name="&lt;Transparent Rectangle&gt;"
+            ></path>
+        </svg>
+    );
+}
+
+export function InterceptSendToEndpoint() {
+    return (
+        <svg
+            className="icon" width="32px" height="32px"
+            xmlns="http://www.w3.org/2000/svg";
+            id="icon"
+            fill="#000"
+            viewBox="0 0 32 32"
+        >
+            <defs>
+                <style>{".cls-1 {    fill: none; }"}</style>
+            </defs>
+            <path d="M6 30h12a2.002 2.002 0 002-2v-3h-2v3H6V4h12v3h2V4a2.002 
2.002 0 00-2-2H6a2.002 2.002 0 00-2 2v24a2.002 2.002 0 002 2z"></path>
+            <path d="M20.586 20.586L24.172 17 10 17 10 15 24.172 15 20.586 
11.414 22 10 28 16 22 22 20.586 20.586z"></path>
+            <path
+                id="_Transparent_Rectangle_"
+                d="M0 0H32V32H0z"
+                className="cls-1"
+                data-name="&lt;Transparent Rectangle&gt;"
+            ></path>
+        </svg>
+    );
+}
+
+
 export function SpringIcon() {
     return (
         <svg
diff --git a/karavan-app/src/main/webui/src/projects/ProjectPage.tsx 
b/karavan-app/src/main/webui/src/projects/ProjectPage.tsx
index ec13a67..1ebf251 100644
--- a/karavan-app/src/main/webui/src/projects/ProjectPage.tsx
+++ b/karavan-app/src/main/webui/src/projects/ProjectPage.tsx
@@ -212,9 +212,11 @@ export class ProjectPage extends React.Component<Props, 
State> {
                             this.setState({file: undefined})
                             this.onRefresh();
                         }}>
-                            {"Project: " + project?.projectId}
+                            <Flex direction={{default:"row"}}>
+                                <FlexItem>{"Project: " + 
project?.projectId}</FlexItem>
+                                
<FlexItem><Badge>{getProjectFileType(file)}</Badge></FlexItem>
+                            </Flex>
                         </BreadcrumbItem>
-                        <Badge>{getProjectFileType(file)}</Badge>
                     </Breadcrumb>
                     <TextContent className="title">
                         <Text component="h1">{isLog ? filename : 
file.name}</Text>

Reply via email to