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 44a689ff94a5497d0ab76535a0603e20398ca175 Author: Marat Gubaidullin <[email protected]> AuthorDate: Mon Jul 15 12:13:27 2024 -0400 Fix #1315 --- .../webui/src/designer/route/DslConnections.tsx | 27 ++++++------ .../designer/route/element/DslElementHeader.tsx | 8 ++-- .../main/webui/src/designer/selector/DslCard.tsx | 2 + .../src/main/webui/src/designer/utils/CamelUi.tsx | 7 ++- .../main/webui/src/designer/utils/DslMetaModel.ts | 1 + .../src/knowledgebase/components/ComponentCard.tsx | 11 +++-- .../webui/src/topology/TopologyPropertiesPanel.tsx | 3 +- karavan-designer/public/example/demo.camel.yaml | 51 +++++++++++++++------- karavan-designer/src/App.tsx | 2 +- .../src/designer/route/DslConnections.tsx | 27 ++++++------ .../designer/route/element/DslElementHeader.tsx | 8 ++-- karavan-designer/src/designer/selector/DslCard.tsx | 2 + karavan-designer/src/designer/utils/CamelUi.tsx | 7 ++- .../src/designer/utils/DslMetaModel.ts | 1 + .../src/designer/utils/Notification.tsx | 2 +- .../src/knowledgebase/components/ComponentCard.tsx | 11 +++-- .../src/topology/TopologyPropertiesPanel.tsx | 3 +- .../src/designer/route/DslConnections.tsx | 27 ++++++------ .../designer/route/element/DslElementHeader.tsx | 8 ++-- karavan-space/src/designer/selector/DslCard.tsx | 2 + karavan-space/src/designer/utils/CamelUi.tsx | 7 ++- karavan-space/src/designer/utils/DslMetaModel.ts | 1 + .../src/knowledgebase/components/ComponentCard.tsx | 11 +++-- .../src/topology/TopologyPropertiesPanel.tsx | 3 +- 24 files changed, 139 insertions(+), 93 deletions(-) diff --git a/karavan-app/src/main/webui/src/designer/route/DslConnections.tsx b/karavan-app/src/main/webui/src/designer/route/DslConnections.tsx index d1720b55..3f65b1f7 100644 --- a/karavan-app/src/main/webui/src/designer/route/DslConnections.tsx +++ b/karavan-app/src/main/webui/src/designer/route/DslConnections.tsx @@ -17,14 +17,14 @@ import React, {JSX, useEffect, useState} from 'react'; import '../karavan.css'; import {DslPosition, EventBus} from "../utils/EventBus"; -import {CamelUi} from "../utils/CamelUi"; +import {CamelUi, NAV_COMPONENTS} from "../utils/CamelUi"; import {useConnectionsStore, useDesignerStore, useIntegrationStore} from "../DesignerStore"; import {shallow} from "zustand/shallow"; import {CamelDefinitionApiExt} from "karavan-core/lib/api/CamelDefinitionApiExt"; import {TopologyUtils} from "karavan-core/lib/api/TopologyUtils"; import {CamelElement} from "karavan-core/lib/model/IntegrationDefinition"; import {v4 as uuidv4} from "uuid"; -import {Button, Tooltip} from "@patternfly/react-core"; +import {Badge, Button, Tooltip} from "@patternfly/react-core"; import {InfrastructureAPI} from "../utils/InfrastructureAPI"; import {getIntegrations} from "../../topology/TopologyApi"; import {ComponentApi} from "karavan-core/lib/api/ComponentApi"; @@ -85,14 +85,13 @@ export function DslConnections() { function isElementInternalComponent (element: CamelElement): boolean { const uri = (element as any).uri; const component = ComponentApi.findByName(uri); - return component !== undefined && (TopologyUtils.isComponentInternal(component.component.label)); + return component !== undefined && component.component.remote !== true; } function getIncomings() { let outs: [string, number][] = Array.from(steps.values()) .filter(pos => ["FromDefinition"].includes(pos.step.dslName)) .filter(pos => !isElementInternalComponent(pos.step)) - // .filter(pos => !(pos.step.dslName === 'FromDefinition' && TopologyUtils.hasInternalUri(pos.step))) .filter(pos => !(pos.step.dslName === 'FromDefinition' && (pos.step as any).uri === 'kamelet:source')) .sort((pos1: DslPosition, pos2: DslPosition) => { const y1 = pos1.headerRect.y + pos1.headerRect.height / 2; @@ -132,7 +131,7 @@ export function DslConnections() { // function getToDirectSteps(name: string) { // return Array.from(steps.values()) // .filter(s => s.step.dslName === 'ToDefinition') - // .filter(s => ['direct','seda'].includes((s.step as any)?.uri)) + // .filter(s => NAV_COMPONENTS.includes((s.step as any)?.uri)) // .filter(s => (s.step as any)?.parameters?.name === name) // } @@ -141,9 +140,9 @@ export function DslConnections() { if (pos) { const step = (pos.step as any); const uri = step?.uri; - const directOrSeda: boolean = step && uri && step?.dslName === 'FromDefinition' && ['direct','seda'].includes(uri); - const name: string = directOrSeda ? (step?.parameters?.name) : undefined; - const routes = directOrSeda ? tons.get(uri + ':' +name) || [] : []; + const internalCall: boolean = step && uri && step?.dslName === 'FromDefinition' && NAV_COMPONENTS.includes(uri); + const name: string = internalCall ? (step?.parameters?.name) : undefined; + const routes = internalCall ? tons.get(uri + ':' +name) || [] : []; // const localDirects = getToDirectSteps(name); const fromY = pos.headerRect.y + pos.headerRect.height / 2 - top; const r = pos.headerRect.height / 2; @@ -152,7 +151,8 @@ export function DslConnections() { const imageY = fromY - r + 6; return ( <div key={pos.step.uuid + "-icon"} - style={{display: "block", position: "absolute", top: imageY, left: imageX}}> + style={{display: "block", position: "absolute", top: imageY, left: imageX}} + > {CamelUi.getConnectionIcon(pos.step)} {routes.map((routeId, index) => <Tooltip key={`${routeId}:${index}`} content={`Go to route:${routeId}`} position={"right"}> @@ -193,7 +193,7 @@ export function DslConnections() { .filter(pos => outgoingDefinitions.includes(pos.step.dslName)) .filter(pos => pos.step.dslName !== 'KameletDefinition' || (pos.step.dslName === 'KameletDefinition' && !CamelUi.isActionKamelet(pos.step))) .filter(pos => pos.step.dslName === 'ToDefinition' && !CamelUi.isActionKamelet(pos.step)) - .filter(pos => pos.step.dslName !== 'SagaDefinition') + .filter(pos => !isElementInternalComponent(pos.step)) .filter(pos => !CamelUi.isKameletSink(pos.step)) .sort((pos1: DslPosition, pos2: DslPosition) => { const y1 = pos1.headerRect.y + pos1.headerRect.height / 2; @@ -241,8 +241,8 @@ export function DslConnections() { if (pos) { const step = (pos.step as any); const uri = step?.uri; - const directOrSeda = step && uri && step?.dslName === 'ToDefinition' && ['direct','seda'].includes(uri); - const name = directOrSeda ? (step?.parameters?.name) : ''; + const internalCall = step && uri && step?.dslName === 'ToDefinition' && NAV_COMPONENTS.includes(uri); + const name = internalCall ? (step?.parameters?.name) : ''; const r = pos.headerRect.height / 2; const outgoingX = width - 20; const outgoingY = data[1] + RADIUS; @@ -443,7 +443,8 @@ export function DslConnections() { function getSvg() { const stepsArray = Array.from(steps.values()); const arrows = stepsArray.map(pos => getArrow(pos)).flat(1); - const uniqueArrows = [...new Map(arrows.map(item => [(item as any).key, item])).values()] + const uniqueArrows = [...new Map(arrows.map(item => [(item as any).key, item])).values()]; + return ( <svg key={svgKey} style={{width: width, height: height, position: "absolute", left: 0, top: 0}} diff --git a/karavan-app/src/main/webui/src/designer/route/element/DslElementHeader.tsx b/karavan-app/src/main/webui/src/designer/route/element/DslElementHeader.tsx index c911dc2c..8b20a452 100644 --- a/karavan-app/src/main/webui/src/designer/route/element/DslElementHeader.tsx +++ b/karavan-app/src/main/webui/src/designer/route/element/DslElementHeader.tsx @@ -304,11 +304,9 @@ export function DslElementHeader(props: Props) { function getDeleteButton() { return ( - <Tooltip position={"right"} content={<div>{"Delete element"}</div>}> - <button type="button" aria-label="Delete" onClick={e => onDeleteElement(e)} className="delete-button"> - <DeleteElementIcon/> - </button> - </Tooltip> + <button type="button" aria-label="Delete" onClick={e => onDeleteElement(e)} className="delete-button"> + <DeleteElementIcon/> + </button> ) } diff --git a/karavan-app/src/main/webui/src/designer/selector/DslCard.tsx b/karavan-app/src/main/webui/src/designer/selector/DslCard.tsx index 510bce5c..3b965150 100644 --- a/karavan-app/src/main/webui/src/designer/selector/DslCard.tsx +++ b/karavan-app/src/main/webui/src/designer/selector/DslCard.tsx @@ -43,6 +43,7 @@ export function DslCard (props: Props) { const {dsl, index} = props; const labels = dsl.labels !== undefined ? dsl.labels.split(",").filter(label => label !== 'eip') : []; const isCustom = KameletApi.getCustomKameletNames().includes(dsl.name); + const isRemote = dsl.remote; return ( <Card key={dsl.dsl + index} isCompact isPlain isFlat isRounded className="dsl-card" onClick={event => selectDsl(event, dsl)}> @@ -67,6 +68,7 @@ export function DslCard (props: Props) { {labels.map((label, index) => <Badge key={label + "-" + index} isRead className="labels">{label}</Badge>)} </div> + {dsl.navigation === 'component' && <Badge isRead className="labels">{isRemote ? 'remote' : 'internal'}</Badge>} {isCustom && <Badge className="custom">custom</Badge>} </CardFooter> </Card> 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 8a1fbde7..2e500773 100644 --- a/karavan-app/src/main/webui/src/designer/utils/CamelUi.tsx +++ b/karavan-app/src/main/webui/src/designer/utils/CamelUi.tsx @@ -170,6 +170,8 @@ export class RouteToCreate { } } +export const NAV_COMPONENTS = ['direct', 'seda', 'vertx'] + const INTEGRATION_PATTERNS = 'Integration Patterns'; const stepConvertMap = new Map<string, string>([ @@ -290,6 +292,7 @@ export class CamelUi { version: c.component.version, supportLevel: c.component.supportLevel, supportType: c.component.supportType, + remote: c.component.remote, })); } @@ -692,11 +695,11 @@ export class CamelUi { const k: KameletModel | undefined = CamelUtil.getKamelet(element); if (["FromDefinition", "KameletDefinition"].includes(element.dslName) && k !== undefined) { return k ? this.getIconFromSource(k.icon()) : CamelUi.getIconForDslName(element.dslName); - } else if ("FromDefinition" === element.dslName && component !== undefined && TopologyUtils.isComponentInternal(component.component.label)) { + } else if ("FromDefinition" === element.dslName && component !== undefined && component.component.remote !== true) { return this.getIconForComponent(component?.component.title, component?.component.label); } else if (element.dslName === "ToDefinition" && (element as ToDefinition).uri?.startsWith("kamelet:")) { return k ? this.getIconFromSource(k.icon()) : CamelUi.getIconForDslName(element.dslName); - } else if (element.dslName === "ToDefinition" && component && TopologyUtils.isComponentInternal(component.component.label)) { + } else if (element.dslName === "ToDefinition" && component && component.component.remote !== true) { return this.getIconForComponent(component?.component.title, component?.component.label); } else if (element.dslName === "ToDefinition" && component && TopologyUtils.hasDirectUri(element)) { return this.getIconForComponent(component?.component.title, component?.component.label); diff --git a/karavan-app/src/main/webui/src/designer/utils/DslMetaModel.ts b/karavan-app/src/main/webui/src/designer/utils/DslMetaModel.ts index d267a56d..89edb33a 100644 --- a/karavan-app/src/main/webui/src/designer/utils/DslMetaModel.ts +++ b/karavan-app/src/main/webui/src/designer/utils/DslMetaModel.ts @@ -26,6 +26,7 @@ export class DslMetaModel { version: string = '' supportLevel: string = '' supportType: string = '' + remote: boolean = false properties: any; public constructor(init?: Partial<DslMetaModel>) { diff --git a/karavan-app/src/main/webui/src/knowledgebase/components/ComponentCard.tsx b/karavan-app/src/main/webui/src/knowledgebase/components/ComponentCard.tsx index 91ec2595..8794ef1e 100644 --- a/karavan-app/src/main/webui/src/knowledgebase/components/ComponentCard.tsx +++ b/karavan-app/src/main/webui/src/knowledgebase/components/ComponentCard.tsx @@ -16,7 +16,7 @@ */ import React, { useEffect, useState } from 'react'; import { - CardHeader, Card, CardTitle, CardBody, CardFooter, Badge, Checkbox + CardHeader, Card, CardTitle, CardBody, CardFooter, Badge, Checkbox, Flex } from '@patternfly/react-core'; import '../../designer/karavan.css'; import {CamelUi} from "../../designer/utils/CamelUi"; @@ -53,13 +53,16 @@ export function ComponentCard(props: Props) { setBlockedComponents([...ComponentApi.getBlockedComponentNames()]); } const isBlockedComponent = blockedComponents ? blockedComponents.findIndex(r => r === component.component.name) > -1 : false; + const isRemote = component.component.remote; return ( <Card isCompact key={component.component.name} className="kamelet-card" onClick={event => click(event)} > <CardHeader className="header-labels"> - {component.component.supportType === 'Supported' && <Badge isRead className="support-type labels">{component.component.supportType}</Badge>} - <Badge isRead className="support-level labels">{component.component.supportLevel}</Badge> + <Flex style={{width:'100%'}} gap={{default:'gapSm'}} justifyContent={{default: 'justifyContentSpaceBetween'}}> + <Badge isRead className="support-level labels">{component.component.supportLevel}</Badge> + <Badge isRead className="version labels">{component.component.version}</Badge> + </Flex> {showBlockCheckbox && <Checkbox id={component.component.name} className="block-checkbox labels" isChecked={!isBlockedComponent} onChange={(_, checked) => selectComponent(_, checked)}/>} </CardHeader> @@ -70,7 +73,7 @@ export function ComponentCard(props: Props) { <CardBody>{component.component.description}</CardBody> <CardFooter className="footer-labels"> <Badge isRead className="labels">{component.component.label}</Badge> - <Badge isRead className="version labels">{component.component.version}</Badge> + <Badge isRead className="labels">{isRemote ? 'remote' : 'internal'}</Badge> </CardFooter> </Card> ) diff --git a/karavan-app/src/main/webui/src/topology/TopologyPropertiesPanel.tsx b/karavan-app/src/main/webui/src/topology/TopologyPropertiesPanel.tsx index a32d6969..0fd93b3d 100644 --- a/karavan-app/src/main/webui/src/topology/TopologyPropertiesPanel.tsx +++ b/karavan-app/src/main/webui/src/topology/TopologyPropertiesPanel.tsx @@ -30,6 +30,7 @@ import { TooltipPosition } from "@patternfly/react-core"; import CloseIcon from "@patternfly/react-icons/dist/esm/icons/times-icon"; +import {NAV_COMPONENTS} from "../designer/utils/CamelUi"; interface Props { onSetFile: (fileName: string) => void @@ -68,7 +69,7 @@ export function TopologyPropertiesPanel(props: Props) { if (isRoute()) { const uri: string = nodeData?.step?.from.uri || ''; const name: string = nodeData?.step?.from.parameters?.name || ''; - if (['direct','seda'].includes(uri)) { + if (NAV_COMPONENTS.includes(uri)) { return uri.concat(":").concat(name); } else { return uri; diff --git a/karavan-designer/public/example/demo.camel.yaml b/karavan-designer/public/example/demo.camel.yaml index f4456979..efb2964d 100644 --- a/karavan-designer/public/example/demo.camel.yaml +++ b/karavan-designer/public/example/demo.camel.yaml @@ -8,28 +8,47 @@ message: Hello period: 1 steps: - - aggregate: - id: aggregate-46cb - completionSize: 1 - to: id: to-df39 uri: amqp - - aggregate: - id: aggregate-1193 - completionSize: 121212 - completionTimeout: "{{bean:beanName.method}}" - to: id: to-1600 uri: kamelet:kafka-sink -- rest: - id: rest-d262 - get: - - id: get-7de4 - to: direct:test + - to: + id: to-d9bc + uri: pdf + - to: + id: to-4588 + uri: controlbus + - to: + id: to-ac40 + uri: vertx + parameters: + address: DATA + - to: + id: to-3855 + uri: direct - route: - id: test + id: route-d18a + nodePrefixId: route-f11 from: - id: from-aeed + id: from-519d + uri: seda +- route: + id: route-06fe + nodePrefixId: route-0b9 + from: + id: from-f068 uri: direct - parameters: - name: test +#- rest: +# id: rest-d262 +# get: +# - id: get-7de4 +# to: direct:test +#- route: +# id: test +# from: +# id: from-aeed +# uri: direct +# parameters: +# name: test diff --git a/karavan-designer/src/App.tsx b/karavan-designer/src/App.tsx index b7344e30..bc6d9f7b 100644 --- a/karavan-designer/src/App.tsx +++ b/karavan-designer/src/App.tsx @@ -58,7 +58,7 @@ class MenuItem { export function App() { - const [pageId, setPageId] = useState<string>('topology'); + const [pageId, setPageId] = useState<string>('designer'); const [name, setName] = useState<string>('example.yaml'); const [key, setKey] = useState<string>(''); const [yaml, setYaml] = useState<string>(''); diff --git a/karavan-designer/src/designer/route/DslConnections.tsx b/karavan-designer/src/designer/route/DslConnections.tsx index d1720b55..3f65b1f7 100644 --- a/karavan-designer/src/designer/route/DslConnections.tsx +++ b/karavan-designer/src/designer/route/DslConnections.tsx @@ -17,14 +17,14 @@ import React, {JSX, useEffect, useState} from 'react'; import '../karavan.css'; import {DslPosition, EventBus} from "../utils/EventBus"; -import {CamelUi} from "../utils/CamelUi"; +import {CamelUi, NAV_COMPONENTS} from "../utils/CamelUi"; import {useConnectionsStore, useDesignerStore, useIntegrationStore} from "../DesignerStore"; import {shallow} from "zustand/shallow"; import {CamelDefinitionApiExt} from "karavan-core/lib/api/CamelDefinitionApiExt"; import {TopologyUtils} from "karavan-core/lib/api/TopologyUtils"; import {CamelElement} from "karavan-core/lib/model/IntegrationDefinition"; import {v4 as uuidv4} from "uuid"; -import {Button, Tooltip} from "@patternfly/react-core"; +import {Badge, Button, Tooltip} from "@patternfly/react-core"; import {InfrastructureAPI} from "../utils/InfrastructureAPI"; import {getIntegrations} from "../../topology/TopologyApi"; import {ComponentApi} from "karavan-core/lib/api/ComponentApi"; @@ -85,14 +85,13 @@ export function DslConnections() { function isElementInternalComponent (element: CamelElement): boolean { const uri = (element as any).uri; const component = ComponentApi.findByName(uri); - return component !== undefined && (TopologyUtils.isComponentInternal(component.component.label)); + return component !== undefined && component.component.remote !== true; } function getIncomings() { let outs: [string, number][] = Array.from(steps.values()) .filter(pos => ["FromDefinition"].includes(pos.step.dslName)) .filter(pos => !isElementInternalComponent(pos.step)) - // .filter(pos => !(pos.step.dslName === 'FromDefinition' && TopologyUtils.hasInternalUri(pos.step))) .filter(pos => !(pos.step.dslName === 'FromDefinition' && (pos.step as any).uri === 'kamelet:source')) .sort((pos1: DslPosition, pos2: DslPosition) => { const y1 = pos1.headerRect.y + pos1.headerRect.height / 2; @@ -132,7 +131,7 @@ export function DslConnections() { // function getToDirectSteps(name: string) { // return Array.from(steps.values()) // .filter(s => s.step.dslName === 'ToDefinition') - // .filter(s => ['direct','seda'].includes((s.step as any)?.uri)) + // .filter(s => NAV_COMPONENTS.includes((s.step as any)?.uri)) // .filter(s => (s.step as any)?.parameters?.name === name) // } @@ -141,9 +140,9 @@ export function DslConnections() { if (pos) { const step = (pos.step as any); const uri = step?.uri; - const directOrSeda: boolean = step && uri && step?.dslName === 'FromDefinition' && ['direct','seda'].includes(uri); - const name: string = directOrSeda ? (step?.parameters?.name) : undefined; - const routes = directOrSeda ? tons.get(uri + ':' +name) || [] : []; + const internalCall: boolean = step && uri && step?.dslName === 'FromDefinition' && NAV_COMPONENTS.includes(uri); + const name: string = internalCall ? (step?.parameters?.name) : undefined; + const routes = internalCall ? tons.get(uri + ':' +name) || [] : []; // const localDirects = getToDirectSteps(name); const fromY = pos.headerRect.y + pos.headerRect.height / 2 - top; const r = pos.headerRect.height / 2; @@ -152,7 +151,8 @@ export function DslConnections() { const imageY = fromY - r + 6; return ( <div key={pos.step.uuid + "-icon"} - style={{display: "block", position: "absolute", top: imageY, left: imageX}}> + style={{display: "block", position: "absolute", top: imageY, left: imageX}} + > {CamelUi.getConnectionIcon(pos.step)} {routes.map((routeId, index) => <Tooltip key={`${routeId}:${index}`} content={`Go to route:${routeId}`} position={"right"}> @@ -193,7 +193,7 @@ export function DslConnections() { .filter(pos => outgoingDefinitions.includes(pos.step.dslName)) .filter(pos => pos.step.dslName !== 'KameletDefinition' || (pos.step.dslName === 'KameletDefinition' && !CamelUi.isActionKamelet(pos.step))) .filter(pos => pos.step.dslName === 'ToDefinition' && !CamelUi.isActionKamelet(pos.step)) - .filter(pos => pos.step.dslName !== 'SagaDefinition') + .filter(pos => !isElementInternalComponent(pos.step)) .filter(pos => !CamelUi.isKameletSink(pos.step)) .sort((pos1: DslPosition, pos2: DslPosition) => { const y1 = pos1.headerRect.y + pos1.headerRect.height / 2; @@ -241,8 +241,8 @@ export function DslConnections() { if (pos) { const step = (pos.step as any); const uri = step?.uri; - const directOrSeda = step && uri && step?.dslName === 'ToDefinition' && ['direct','seda'].includes(uri); - const name = directOrSeda ? (step?.parameters?.name) : ''; + const internalCall = step && uri && step?.dslName === 'ToDefinition' && NAV_COMPONENTS.includes(uri); + const name = internalCall ? (step?.parameters?.name) : ''; const r = pos.headerRect.height / 2; const outgoingX = width - 20; const outgoingY = data[1] + RADIUS; @@ -443,7 +443,8 @@ export function DslConnections() { function getSvg() { const stepsArray = Array.from(steps.values()); const arrows = stepsArray.map(pos => getArrow(pos)).flat(1); - const uniqueArrows = [...new Map(arrows.map(item => [(item as any).key, item])).values()] + const uniqueArrows = [...new Map(arrows.map(item => [(item as any).key, item])).values()]; + return ( <svg key={svgKey} style={{width: width, height: height, position: "absolute", left: 0, top: 0}} diff --git a/karavan-designer/src/designer/route/element/DslElementHeader.tsx b/karavan-designer/src/designer/route/element/DslElementHeader.tsx index c911dc2c..8b20a452 100644 --- a/karavan-designer/src/designer/route/element/DslElementHeader.tsx +++ b/karavan-designer/src/designer/route/element/DslElementHeader.tsx @@ -304,11 +304,9 @@ export function DslElementHeader(props: Props) { function getDeleteButton() { return ( - <Tooltip position={"right"} content={<div>{"Delete element"}</div>}> - <button type="button" aria-label="Delete" onClick={e => onDeleteElement(e)} className="delete-button"> - <DeleteElementIcon/> - </button> - </Tooltip> + <button type="button" aria-label="Delete" onClick={e => onDeleteElement(e)} className="delete-button"> + <DeleteElementIcon/> + </button> ) } diff --git a/karavan-designer/src/designer/selector/DslCard.tsx b/karavan-designer/src/designer/selector/DslCard.tsx index 510bce5c..3b965150 100644 --- a/karavan-designer/src/designer/selector/DslCard.tsx +++ b/karavan-designer/src/designer/selector/DslCard.tsx @@ -43,6 +43,7 @@ export function DslCard (props: Props) { const {dsl, index} = props; const labels = dsl.labels !== undefined ? dsl.labels.split(",").filter(label => label !== 'eip') : []; const isCustom = KameletApi.getCustomKameletNames().includes(dsl.name); + const isRemote = dsl.remote; return ( <Card key={dsl.dsl + index} isCompact isPlain isFlat isRounded className="dsl-card" onClick={event => selectDsl(event, dsl)}> @@ -67,6 +68,7 @@ export function DslCard (props: Props) { {labels.map((label, index) => <Badge key={label + "-" + index} isRead className="labels">{label}</Badge>)} </div> + {dsl.navigation === 'component' && <Badge isRead className="labels">{isRemote ? 'remote' : 'internal'}</Badge>} {isCustom && <Badge className="custom">custom</Badge>} </CardFooter> </Card> diff --git a/karavan-designer/src/designer/utils/CamelUi.tsx b/karavan-designer/src/designer/utils/CamelUi.tsx index 8a1fbde7..2e500773 100644 --- a/karavan-designer/src/designer/utils/CamelUi.tsx +++ b/karavan-designer/src/designer/utils/CamelUi.tsx @@ -170,6 +170,8 @@ export class RouteToCreate { } } +export const NAV_COMPONENTS = ['direct', 'seda', 'vertx'] + const INTEGRATION_PATTERNS = 'Integration Patterns'; const stepConvertMap = new Map<string, string>([ @@ -290,6 +292,7 @@ export class CamelUi { version: c.component.version, supportLevel: c.component.supportLevel, supportType: c.component.supportType, + remote: c.component.remote, })); } @@ -692,11 +695,11 @@ export class CamelUi { const k: KameletModel | undefined = CamelUtil.getKamelet(element); if (["FromDefinition", "KameletDefinition"].includes(element.dslName) && k !== undefined) { return k ? this.getIconFromSource(k.icon()) : CamelUi.getIconForDslName(element.dslName); - } else if ("FromDefinition" === element.dslName && component !== undefined && TopologyUtils.isComponentInternal(component.component.label)) { + } else if ("FromDefinition" === element.dslName && component !== undefined && component.component.remote !== true) { return this.getIconForComponent(component?.component.title, component?.component.label); } else if (element.dslName === "ToDefinition" && (element as ToDefinition).uri?.startsWith("kamelet:")) { return k ? this.getIconFromSource(k.icon()) : CamelUi.getIconForDslName(element.dslName); - } else if (element.dslName === "ToDefinition" && component && TopologyUtils.isComponentInternal(component.component.label)) { + } else if (element.dslName === "ToDefinition" && component && component.component.remote !== true) { return this.getIconForComponent(component?.component.title, component?.component.label); } else if (element.dslName === "ToDefinition" && component && TopologyUtils.hasDirectUri(element)) { return this.getIconForComponent(component?.component.title, component?.component.label); diff --git a/karavan-designer/src/designer/utils/DslMetaModel.ts b/karavan-designer/src/designer/utils/DslMetaModel.ts index d267a56d..89edb33a 100644 --- a/karavan-designer/src/designer/utils/DslMetaModel.ts +++ b/karavan-designer/src/designer/utils/DslMetaModel.ts @@ -26,6 +26,7 @@ export class DslMetaModel { version: string = '' supportLevel: string = '' supportType: string = '' + remote: boolean = false properties: any; public constructor(init?: Partial<DslMetaModel>) { diff --git a/karavan-designer/src/designer/utils/Notification.tsx b/karavan-designer/src/designer/utils/Notification.tsx index 1f435c4b..ae8ebd54 100644 --- a/karavan-designer/src/designer/utils/Notification.tsx +++ b/karavan-designer/src/designer/utils/Notification.tsx @@ -45,7 +45,7 @@ export function Notification () { <AlertGroup isToast isLiveRegion> {alerts.map((e: ToastMessage) => ( <Alert key={e.id} className="main-alert" variant={e.variant} title={e.title} - timeout={['success', 'info', 'custom'].includes(e.variant) ? 1000 : 20000} + timeout={['success', 'info', 'custom'].includes(e.variant) ? 2300 : 20000} actionClose={<AlertActionCloseButton onClose={() => { setAlerts(prevState => { return [...prevState.filter(t => t.id !== e.id)]; diff --git a/karavan-designer/src/knowledgebase/components/ComponentCard.tsx b/karavan-designer/src/knowledgebase/components/ComponentCard.tsx index 91ec2595..8794ef1e 100644 --- a/karavan-designer/src/knowledgebase/components/ComponentCard.tsx +++ b/karavan-designer/src/knowledgebase/components/ComponentCard.tsx @@ -16,7 +16,7 @@ */ import React, { useEffect, useState } from 'react'; import { - CardHeader, Card, CardTitle, CardBody, CardFooter, Badge, Checkbox + CardHeader, Card, CardTitle, CardBody, CardFooter, Badge, Checkbox, Flex } from '@patternfly/react-core'; import '../../designer/karavan.css'; import {CamelUi} from "../../designer/utils/CamelUi"; @@ -53,13 +53,16 @@ export function ComponentCard(props: Props) { setBlockedComponents([...ComponentApi.getBlockedComponentNames()]); } const isBlockedComponent = blockedComponents ? blockedComponents.findIndex(r => r === component.component.name) > -1 : false; + const isRemote = component.component.remote; return ( <Card isCompact key={component.component.name} className="kamelet-card" onClick={event => click(event)} > <CardHeader className="header-labels"> - {component.component.supportType === 'Supported' && <Badge isRead className="support-type labels">{component.component.supportType}</Badge>} - <Badge isRead className="support-level labels">{component.component.supportLevel}</Badge> + <Flex style={{width:'100%'}} gap={{default:'gapSm'}} justifyContent={{default: 'justifyContentSpaceBetween'}}> + <Badge isRead className="support-level labels">{component.component.supportLevel}</Badge> + <Badge isRead className="version labels">{component.component.version}</Badge> + </Flex> {showBlockCheckbox && <Checkbox id={component.component.name} className="block-checkbox labels" isChecked={!isBlockedComponent} onChange={(_, checked) => selectComponent(_, checked)}/>} </CardHeader> @@ -70,7 +73,7 @@ export function ComponentCard(props: Props) { <CardBody>{component.component.description}</CardBody> <CardFooter className="footer-labels"> <Badge isRead className="labels">{component.component.label}</Badge> - <Badge isRead className="version labels">{component.component.version}</Badge> + <Badge isRead className="labels">{isRemote ? 'remote' : 'internal'}</Badge> </CardFooter> </Card> ) diff --git a/karavan-designer/src/topology/TopologyPropertiesPanel.tsx b/karavan-designer/src/topology/TopologyPropertiesPanel.tsx index a32d6969..0fd93b3d 100644 --- a/karavan-designer/src/topology/TopologyPropertiesPanel.tsx +++ b/karavan-designer/src/topology/TopologyPropertiesPanel.tsx @@ -30,6 +30,7 @@ import { TooltipPosition } from "@patternfly/react-core"; import CloseIcon from "@patternfly/react-icons/dist/esm/icons/times-icon"; +import {NAV_COMPONENTS} from "../designer/utils/CamelUi"; interface Props { onSetFile: (fileName: string) => void @@ -68,7 +69,7 @@ export function TopologyPropertiesPanel(props: Props) { if (isRoute()) { const uri: string = nodeData?.step?.from.uri || ''; const name: string = nodeData?.step?.from.parameters?.name || ''; - if (['direct','seda'].includes(uri)) { + if (NAV_COMPONENTS.includes(uri)) { return uri.concat(":").concat(name); } else { return uri; diff --git a/karavan-space/src/designer/route/DslConnections.tsx b/karavan-space/src/designer/route/DslConnections.tsx index d1720b55..3f65b1f7 100644 --- a/karavan-space/src/designer/route/DslConnections.tsx +++ b/karavan-space/src/designer/route/DslConnections.tsx @@ -17,14 +17,14 @@ import React, {JSX, useEffect, useState} from 'react'; import '../karavan.css'; import {DslPosition, EventBus} from "../utils/EventBus"; -import {CamelUi} from "../utils/CamelUi"; +import {CamelUi, NAV_COMPONENTS} from "../utils/CamelUi"; import {useConnectionsStore, useDesignerStore, useIntegrationStore} from "../DesignerStore"; import {shallow} from "zustand/shallow"; import {CamelDefinitionApiExt} from "karavan-core/lib/api/CamelDefinitionApiExt"; import {TopologyUtils} from "karavan-core/lib/api/TopologyUtils"; import {CamelElement} from "karavan-core/lib/model/IntegrationDefinition"; import {v4 as uuidv4} from "uuid"; -import {Button, Tooltip} from "@patternfly/react-core"; +import {Badge, Button, Tooltip} from "@patternfly/react-core"; import {InfrastructureAPI} from "../utils/InfrastructureAPI"; import {getIntegrations} from "../../topology/TopologyApi"; import {ComponentApi} from "karavan-core/lib/api/ComponentApi"; @@ -85,14 +85,13 @@ export function DslConnections() { function isElementInternalComponent (element: CamelElement): boolean { const uri = (element as any).uri; const component = ComponentApi.findByName(uri); - return component !== undefined && (TopologyUtils.isComponentInternal(component.component.label)); + return component !== undefined && component.component.remote !== true; } function getIncomings() { let outs: [string, number][] = Array.from(steps.values()) .filter(pos => ["FromDefinition"].includes(pos.step.dslName)) .filter(pos => !isElementInternalComponent(pos.step)) - // .filter(pos => !(pos.step.dslName === 'FromDefinition' && TopologyUtils.hasInternalUri(pos.step))) .filter(pos => !(pos.step.dslName === 'FromDefinition' && (pos.step as any).uri === 'kamelet:source')) .sort((pos1: DslPosition, pos2: DslPosition) => { const y1 = pos1.headerRect.y + pos1.headerRect.height / 2; @@ -132,7 +131,7 @@ export function DslConnections() { // function getToDirectSteps(name: string) { // return Array.from(steps.values()) // .filter(s => s.step.dslName === 'ToDefinition') - // .filter(s => ['direct','seda'].includes((s.step as any)?.uri)) + // .filter(s => NAV_COMPONENTS.includes((s.step as any)?.uri)) // .filter(s => (s.step as any)?.parameters?.name === name) // } @@ -141,9 +140,9 @@ export function DslConnections() { if (pos) { const step = (pos.step as any); const uri = step?.uri; - const directOrSeda: boolean = step && uri && step?.dslName === 'FromDefinition' && ['direct','seda'].includes(uri); - const name: string = directOrSeda ? (step?.parameters?.name) : undefined; - const routes = directOrSeda ? tons.get(uri + ':' +name) || [] : []; + const internalCall: boolean = step && uri && step?.dslName === 'FromDefinition' && NAV_COMPONENTS.includes(uri); + const name: string = internalCall ? (step?.parameters?.name) : undefined; + const routes = internalCall ? tons.get(uri + ':' +name) || [] : []; // const localDirects = getToDirectSteps(name); const fromY = pos.headerRect.y + pos.headerRect.height / 2 - top; const r = pos.headerRect.height / 2; @@ -152,7 +151,8 @@ export function DslConnections() { const imageY = fromY - r + 6; return ( <div key={pos.step.uuid + "-icon"} - style={{display: "block", position: "absolute", top: imageY, left: imageX}}> + style={{display: "block", position: "absolute", top: imageY, left: imageX}} + > {CamelUi.getConnectionIcon(pos.step)} {routes.map((routeId, index) => <Tooltip key={`${routeId}:${index}`} content={`Go to route:${routeId}`} position={"right"}> @@ -193,7 +193,7 @@ export function DslConnections() { .filter(pos => outgoingDefinitions.includes(pos.step.dslName)) .filter(pos => pos.step.dslName !== 'KameletDefinition' || (pos.step.dslName === 'KameletDefinition' && !CamelUi.isActionKamelet(pos.step))) .filter(pos => pos.step.dslName === 'ToDefinition' && !CamelUi.isActionKamelet(pos.step)) - .filter(pos => pos.step.dslName !== 'SagaDefinition') + .filter(pos => !isElementInternalComponent(pos.step)) .filter(pos => !CamelUi.isKameletSink(pos.step)) .sort((pos1: DslPosition, pos2: DslPosition) => { const y1 = pos1.headerRect.y + pos1.headerRect.height / 2; @@ -241,8 +241,8 @@ export function DslConnections() { if (pos) { const step = (pos.step as any); const uri = step?.uri; - const directOrSeda = step && uri && step?.dslName === 'ToDefinition' && ['direct','seda'].includes(uri); - const name = directOrSeda ? (step?.parameters?.name) : ''; + const internalCall = step && uri && step?.dslName === 'ToDefinition' && NAV_COMPONENTS.includes(uri); + const name = internalCall ? (step?.parameters?.name) : ''; const r = pos.headerRect.height / 2; const outgoingX = width - 20; const outgoingY = data[1] + RADIUS; @@ -443,7 +443,8 @@ export function DslConnections() { function getSvg() { const stepsArray = Array.from(steps.values()); const arrows = stepsArray.map(pos => getArrow(pos)).flat(1); - const uniqueArrows = [...new Map(arrows.map(item => [(item as any).key, item])).values()] + const uniqueArrows = [...new Map(arrows.map(item => [(item as any).key, item])).values()]; + return ( <svg key={svgKey} style={{width: width, height: height, position: "absolute", left: 0, top: 0}} diff --git a/karavan-space/src/designer/route/element/DslElementHeader.tsx b/karavan-space/src/designer/route/element/DslElementHeader.tsx index c911dc2c..8b20a452 100644 --- a/karavan-space/src/designer/route/element/DslElementHeader.tsx +++ b/karavan-space/src/designer/route/element/DslElementHeader.tsx @@ -304,11 +304,9 @@ export function DslElementHeader(props: Props) { function getDeleteButton() { return ( - <Tooltip position={"right"} content={<div>{"Delete element"}</div>}> - <button type="button" aria-label="Delete" onClick={e => onDeleteElement(e)} className="delete-button"> - <DeleteElementIcon/> - </button> - </Tooltip> + <button type="button" aria-label="Delete" onClick={e => onDeleteElement(e)} className="delete-button"> + <DeleteElementIcon/> + </button> ) } diff --git a/karavan-space/src/designer/selector/DslCard.tsx b/karavan-space/src/designer/selector/DslCard.tsx index 510bce5c..3b965150 100644 --- a/karavan-space/src/designer/selector/DslCard.tsx +++ b/karavan-space/src/designer/selector/DslCard.tsx @@ -43,6 +43,7 @@ export function DslCard (props: Props) { const {dsl, index} = props; const labels = dsl.labels !== undefined ? dsl.labels.split(",").filter(label => label !== 'eip') : []; const isCustom = KameletApi.getCustomKameletNames().includes(dsl.name); + const isRemote = dsl.remote; return ( <Card key={dsl.dsl + index} isCompact isPlain isFlat isRounded className="dsl-card" onClick={event => selectDsl(event, dsl)}> @@ -67,6 +68,7 @@ export function DslCard (props: Props) { {labels.map((label, index) => <Badge key={label + "-" + index} isRead className="labels">{label}</Badge>)} </div> + {dsl.navigation === 'component' && <Badge isRead className="labels">{isRemote ? 'remote' : 'internal'}</Badge>} {isCustom && <Badge className="custom">custom</Badge>} </CardFooter> </Card> diff --git a/karavan-space/src/designer/utils/CamelUi.tsx b/karavan-space/src/designer/utils/CamelUi.tsx index 8a1fbde7..2e500773 100644 --- a/karavan-space/src/designer/utils/CamelUi.tsx +++ b/karavan-space/src/designer/utils/CamelUi.tsx @@ -170,6 +170,8 @@ export class RouteToCreate { } } +export const NAV_COMPONENTS = ['direct', 'seda', 'vertx'] + const INTEGRATION_PATTERNS = 'Integration Patterns'; const stepConvertMap = new Map<string, string>([ @@ -290,6 +292,7 @@ export class CamelUi { version: c.component.version, supportLevel: c.component.supportLevel, supportType: c.component.supportType, + remote: c.component.remote, })); } @@ -692,11 +695,11 @@ export class CamelUi { const k: KameletModel | undefined = CamelUtil.getKamelet(element); if (["FromDefinition", "KameletDefinition"].includes(element.dslName) && k !== undefined) { return k ? this.getIconFromSource(k.icon()) : CamelUi.getIconForDslName(element.dslName); - } else if ("FromDefinition" === element.dslName && component !== undefined && TopologyUtils.isComponentInternal(component.component.label)) { + } else if ("FromDefinition" === element.dslName && component !== undefined && component.component.remote !== true) { return this.getIconForComponent(component?.component.title, component?.component.label); } else if (element.dslName === "ToDefinition" && (element as ToDefinition).uri?.startsWith("kamelet:")) { return k ? this.getIconFromSource(k.icon()) : CamelUi.getIconForDslName(element.dslName); - } else if (element.dslName === "ToDefinition" && component && TopologyUtils.isComponentInternal(component.component.label)) { + } else if (element.dslName === "ToDefinition" && component && component.component.remote !== true) { return this.getIconForComponent(component?.component.title, component?.component.label); } else if (element.dslName === "ToDefinition" && component && TopologyUtils.hasDirectUri(element)) { return this.getIconForComponent(component?.component.title, component?.component.label); diff --git a/karavan-space/src/designer/utils/DslMetaModel.ts b/karavan-space/src/designer/utils/DslMetaModel.ts index d267a56d..89edb33a 100644 --- a/karavan-space/src/designer/utils/DslMetaModel.ts +++ b/karavan-space/src/designer/utils/DslMetaModel.ts @@ -26,6 +26,7 @@ export class DslMetaModel { version: string = '' supportLevel: string = '' supportType: string = '' + remote: boolean = false properties: any; public constructor(init?: Partial<DslMetaModel>) { diff --git a/karavan-space/src/knowledgebase/components/ComponentCard.tsx b/karavan-space/src/knowledgebase/components/ComponentCard.tsx index 91ec2595..8794ef1e 100644 --- a/karavan-space/src/knowledgebase/components/ComponentCard.tsx +++ b/karavan-space/src/knowledgebase/components/ComponentCard.tsx @@ -16,7 +16,7 @@ */ import React, { useEffect, useState } from 'react'; import { - CardHeader, Card, CardTitle, CardBody, CardFooter, Badge, Checkbox + CardHeader, Card, CardTitle, CardBody, CardFooter, Badge, Checkbox, Flex } from '@patternfly/react-core'; import '../../designer/karavan.css'; import {CamelUi} from "../../designer/utils/CamelUi"; @@ -53,13 +53,16 @@ export function ComponentCard(props: Props) { setBlockedComponents([...ComponentApi.getBlockedComponentNames()]); } const isBlockedComponent = blockedComponents ? blockedComponents.findIndex(r => r === component.component.name) > -1 : false; + const isRemote = component.component.remote; return ( <Card isCompact key={component.component.name} className="kamelet-card" onClick={event => click(event)} > <CardHeader className="header-labels"> - {component.component.supportType === 'Supported' && <Badge isRead className="support-type labels">{component.component.supportType}</Badge>} - <Badge isRead className="support-level labels">{component.component.supportLevel}</Badge> + <Flex style={{width:'100%'}} gap={{default:'gapSm'}} justifyContent={{default: 'justifyContentSpaceBetween'}}> + <Badge isRead className="support-level labels">{component.component.supportLevel}</Badge> + <Badge isRead className="version labels">{component.component.version}</Badge> + </Flex> {showBlockCheckbox && <Checkbox id={component.component.name} className="block-checkbox labels" isChecked={!isBlockedComponent} onChange={(_, checked) => selectComponent(_, checked)}/>} </CardHeader> @@ -70,7 +73,7 @@ export function ComponentCard(props: Props) { <CardBody>{component.component.description}</CardBody> <CardFooter className="footer-labels"> <Badge isRead className="labels">{component.component.label}</Badge> - <Badge isRead className="version labels">{component.component.version}</Badge> + <Badge isRead className="labels">{isRemote ? 'remote' : 'internal'}</Badge> </CardFooter> </Card> ) diff --git a/karavan-space/src/topology/TopologyPropertiesPanel.tsx b/karavan-space/src/topology/TopologyPropertiesPanel.tsx index a32d6969..0fd93b3d 100644 --- a/karavan-space/src/topology/TopologyPropertiesPanel.tsx +++ b/karavan-space/src/topology/TopologyPropertiesPanel.tsx @@ -30,6 +30,7 @@ import { TooltipPosition } from "@patternfly/react-core"; import CloseIcon from "@patternfly/react-icons/dist/esm/icons/times-icon"; +import {NAV_COMPONENTS} from "../designer/utils/CamelUi"; interface Props { onSetFile: (fileName: string) => void @@ -68,7 +69,7 @@ export function TopologyPropertiesPanel(props: Props) { if (isRoute()) { const uri: string = nodeData?.step?.from.uri || ''; const name: string = nodeData?.step?.from.parameters?.name || ''; - if (['direct','seda'].includes(uri)) { + if (NAV_COMPONENTS.includes(uri)) { return uri.concat(":").concat(name); } else { return uri;
