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 0841c2d18d8ef60cbf1157b9ac937db54598a453 Author: Marat Gubaidullin <ma...@talismancloud.io> AuthorDate: Mon Jul 15 19:01:24 2024 -0400 #1315 --- karavan-designer/public/example/demo.camel.yaml | 20 ++-- karavan-designer/src/designer/karavan.css | 30 ++---- .../src/designer/route/DslConnections.tsx | 104 ++++++++++++--------- 3 files changed, 74 insertions(+), 80 deletions(-) diff --git a/karavan-designer/public/example/demo.camel.yaml b/karavan-designer/public/example/demo.camel.yaml index efb2964d..3ae9fd88 100644 --- a/karavan-designer/public/example/demo.camel.yaml +++ b/karavan-designer/public/example/demo.camel.yaml @@ -28,27 +28,21 @@ - to: id: to-3855 uri: direct + parameters: + name: hello-world-direct - route: id: route-d18a nodePrefixId: route-f11 from: id: from-519d - uri: seda + uri: vertx + parameters: + address: DATA - route: id: route-06fe nodePrefixId: route-0b9 from: id: from-f068 uri: direct -#- rest: -# id: rest-d262 -# get: -# - id: get-7de4 -# to: direct:test -#- route: -# id: test -# from: -# id: from-aeed -# uri: direct -# parameters: -# name: test + parameters: + name: hello-world-direct diff --git a/karavan-designer/src/designer/karavan.css b/karavan-designer/src/designer/karavan.css index 7053de7d..6e7954bb 100644 --- a/karavan-designer/src/designer/karavan.css +++ b/karavan-designer/src/designer/karavan.css @@ -428,6 +428,12 @@ fill: transparent; } +.karavan .dsl-page .graph .connections .path-incoming-nav { + stroke: var(--pf-v5-global--Color--200); + stroke-width: 1; + fill: transparent; +} + .karavan .dsl-page .graph .connections .path-direct { stroke-dasharray: 0; stroke: var(--pf-v5-global--Color--200); @@ -575,30 +581,6 @@ height: 100px; } -/*Exception*/ -/*Template*/ -/*Error*/ - -.karavan .templates-page, -.karavan .exception-page, -.karavan .error-page { - flex: 1; - overflow: auto; -} - -.karavan .templates-page-columns, -.karavan .exception-page-columns, -.karavan .error-page-columns { - height: 100%; - background: #fafafa; -} - -.karavan .templates-page-columns .pf-v5-c-empty-state, -.karavan .exception-page-columns .pf-v5-c-empty-state, -.karavan .error-page-columns .pf-v5-c-empty-state { - margin: auto; - height: 100%; -} /* Help */ .dont-show { diff --git a/karavan-designer/src/designer/route/DslConnections.tsx b/karavan-designer/src/designer/route/DslConnections.tsx index 3f65b1f7..2d08cb58 100644 --- a/karavan-designer/src/designer/route/DslConnections.tsx +++ b/karavan-designer/src/designer/route/DslConnections.tsx @@ -24,7 +24,7 @@ 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 {Badge, Button, Tooltip} from "@patternfly/react-core"; +import {Button, Tooltip} from "@patternfly/react-core"; import {InfrastructureAPI} from "../utils/InfrastructureAPI"; import {getIntegrations} from "../../topology/TopologyApi"; import {ComponentApi} from "karavan-core/lib/api/ComponentApi"; @@ -82,30 +82,33 @@ export function DslConnections() { } } - function isElementInternalComponent (element: CamelElement): boolean { + function getElementType(element: CamelElement): 'internal' | 'remote' | 'nav' { const uri = (element as any).uri; - const component = ComponentApi.findByName(uri); - return component !== undefined && component.component.remote !== true; + if (NAV_COMPONENTS.includes((uri))) { + return 'nav'; + } else { + const component = ComponentApi.findByName(uri); + return (component !== undefined && component.component.remote !== true) ? 'internal' : 'remote'; + } } - function getIncomings() { - let outs: [string, number][] = Array.from(steps.values()) + function getIncomings(): [string, number, 'internal' | 'remote' | 'nav'][] { + let outs: [string, number, 'internal' | 'remote' | 'nav'][] = Array.from(steps.values()) .filter(pos => ["FromDefinition"].includes(pos.step.dslName)) - .filter(pos => !isElementInternalComponent(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; const y2 = pos2.headerRect.y + pos2.headerRect.height / 2; return y1 > y2 ? 1 : -1 }) - .map(pos => [pos.step.uuid, pos.headerRect.y]); + .map(pos => [pos.step.uuid, pos.headerRect.y, getElementType(pos.step)]); while (hasOverlap(outs)) { outs = addGap(outs); } return outs; } - function getIncoming(data: [string, number]) { + function getIncoming(data: [string, number, 'internal' | 'remote' | 'nav']) { const pos = steps.get(data[0]); if (pos) { const fromX = pos.headerRect.x + pos.headerRect.width / 2 - left; @@ -117,13 +120,16 @@ export function DslConnections() { const lineY1 = fromY; const lineX2 = fromX - r * 2 + 7; const lineY2 = fromY; - - return ( - <g key={pos.step.uuid + "-incoming"}> - <circle cx={incomingX} cy={fromY} r={r} className="circle-incoming"/> - <path d={`M ${lineX1},${lineY1} C ${lineX1},${lineY2} ${lineX2},${lineY1} ${lineX2},${lineY2}`} - className="path-incoming" markerEnd="url(#arrowhead)"/> - </g> + const isInternal = data[2] === 'internal'; + const isNav = data[2] === 'nav'; + return (!isInternal + ? <g key={pos.step.uuid + "-incoming"}> + <circle cx={incomingX} cy={fromY} r={r} className="circle-incoming"/> + <path d={`M ${lineX1},${lineY1} C ${lineX1},${lineY2} ${lineX2},${lineY1} ${lineX2},${lineY2}`} + className={isNav ? 'path-incoming-nav' : 'path-incoming'} + markerEnd="url(#arrowhead)"/> + </g> + : <></> ) } } @@ -135,14 +141,14 @@ export function DslConnections() { // .filter(s => (s.step as any)?.parameters?.name === name) // } - function getIncomingIcons(data: [string, number]) { + function getIncomingIcons(data: [string, number, 'internal' | 'remote' | 'nav']) { const pos = steps.get(data[0]); if (pos) { const step = (pos.step as any); const uri = step?.uri; 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 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; @@ -156,7 +162,14 @@ export function DslConnections() { {CamelUi.getConnectionIcon(pos.step)} {routes.map((routeId, index) => <Tooltip key={`${routeId}:${index}`} content={`Go to route:${routeId}`} position={"right"}> - <Button style={{position: 'absolute', left: 27, top: (index * 16) + (12), whiteSpace: 'nowrap', zIndex: 300, padding: 0}} + <Button style={{ + position: 'absolute', + left: 27, + top: (index * 16) + (12), + whiteSpace: 'nowrap', + zIndex: 300, + padding: 0 + }} variant={'link'} aria-label="Goto" onClick={_ => InfrastructureAPI.onInternalConsumerClick(undefined, undefined, routeId)}> @@ -169,7 +182,7 @@ export function DslConnections() { } } - function hasOverlap(data: [string, number][]): boolean { + function hasOverlap(data: [string, number, 'internal' | 'remote' | 'nav'][]): boolean { let result = false; data.forEach((d, i, arr) => { if (i > 0 && d[1] - arr[i - 1][1] < overlapGap) result = true; @@ -177,37 +190,36 @@ export function DslConnections() { return result; } - function addGap(data: [string, number][]): [string, number][] { - const result: [string, number][] = []; + function addGap(data: [string, number, 'internal' | 'remote' | 'nav'][]): [string, number, 'internal' | 'remote' | 'nav'][] { + const result: [string, number, 'internal' | 'remote' | 'nav'][] = []; data.forEach((d, i, arr) => { - if (i > 0 && d[1] - arr[i - 1][1] < overlapGap) result.push([d[0], d[1] + overlapGap]) + if (i > 0 && d[1] - arr[i - 1][1] < overlapGap) result.push([d[0], d[1] + overlapGap, d[2]]) else result.push(d); }) return result; } - function getOutgoings(): [string, number][] { + function getOutgoings(): [string, number, 'internal' | 'remote' | 'nav'][] { const outgoingDefinitions = TopologyUtils.getOutgoingDefinitions(); - let outs: [string, number][] = Array.from(steps.values()) + let outs: [string, number, 'internal' | 'remote' | 'nav'][] = Array.from(steps.values()) .filter(pos => outgoingDefinitions.includes(pos.step.dslName)) .filter(pos => pos.step.dslName !== 'KameletDefinition' || (pos.step.dslName === 'KameletDefinition' && !CamelUi.isActionKamelet(pos.step))) .filter(pos => pos.step.dslName === 'ToDefinition' && !CamelUi.isActionKamelet(pos.step)) - .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; const y2 = pos2.headerRect.y + pos2.headerRect.height / 2; return y1 > y2 ? 1 : -1 }) - .map(pos => [pos.step.uuid, pos.headerRect.y - top]); + .map(pos => [pos.step.uuid, pos.headerRect.y - top, getElementType(pos.step)]); while (hasOverlap(outs)) { outs = addGap(outs); } return outs; } - function getOutgoing(data: [string, number]) { + function getOutgoing(data: [string, number, 'internal' | 'remote' | 'nav']) { const pos = steps.get(data[0]); if (pos) { const fromX = pos.headerRect.x + pos.headerRect.width / 2 - left; @@ -224,32 +236,36 @@ export function DslConnections() { const lineXi = lineX1 + 40; const lineYi = lineY2; - - return ( - <g key={pos.step.uuid + "-outgoing"}> + const isInternal = data[2] === 'internal'; + const isNav = data[2] === 'nav'; + return (!isInternal + ? <g key={pos.step.uuid + "-outgoing"}> <circle cx={outgoingX} cy={outgoingY} r={r} className="circle-outgoing"/> <path d={`M ${lineX1},${lineY1} C ${lineXi - 20}, ${lineY1} ${lineX1 - RADIUS},${lineYi} ${lineXi},${lineYi} L ${lineX2},${lineY2}`} - className="path-incoming" markerEnd="url(#arrowhead)"/> + className={isNav ? 'path-incoming-nav' : 'path-incoming'} markerEnd="url(#arrowhead)"/> </g> + : <></> ) } } - function getOutgoingIcons(data: [string, number]) { + function getOutgoingIcons(data: [string, number, 'internal' | 'remote' | 'nav']) { const pos = steps.get(data[0]); if (pos) { const step = (pos.step as any); const uri = step?.uri; - const internalCall = step && uri && step?.dslName === 'ToDefinition' && NAV_COMPONENTS.includes(uri); - const name = internalCall ? (step?.parameters?.name) : ''; + const isInternal = data[2] === 'internal'; + const isNav = data[2] === 'nav'; + const internalCall = step && uri && step?.dslName === 'ToDefinition' && isNav; + const name = internalCall ? (step?.parameters?.name ? step?.parameters.name : step?.parameters?.address) : ''; const r = pos.headerRect.height / 2; const outgoingX = width - 20; const outgoingY = data[1] + RADIUS; const imageX = outgoingX - r + 6; const imageY = outgoingY - r + 6; - return ( - <div key={pos.step.uuid + "-icon"} + return (!isInternal + ? <div key={pos.step.uuid + "-icon"} style={{display: "block", position: "absolute", top: imageY, left: imageX}}> {CamelUi.getConnectionIcon(pos.step)} {name !== undefined && @@ -263,6 +279,7 @@ export function DslConnections() { </Tooltip> } </div> + : <></> ) } } @@ -290,7 +307,7 @@ export function DslConnections() { return ['ChoiceDefinition', 'MulticastDefinition', 'LoadBalanceDefinition', 'TryDefinition', 'RouteConfigurationDefinition'].includes(pos.step.dslName); } - function addArrowToList(list: JSX.Element[], from?: DslPosition, to?: DslPosition, fromHeader?: boolean, toHeader?: boolean): JSX.Element[] { + function addArrowToList(list: JSX.Element[], from?: DslPosition, to?: DslPosition, fromHeader?: boolean, toHeader?: boolean): JSX.Element[] { const result: JSX.Element[] = [...list]; if (from && to) { const rect1 = fromHeader === true ? from.headerRect : from.rect; @@ -302,7 +319,7 @@ export function DslConnections() { } function getParentDsl(uuid?: string): string | undefined { - return uuid ? steps.get(uuid)?.parent?.dslName : undefined; + return uuid ? steps.get(uuid)?.parent?.dslName : undefined; } function getArrow(pos: DslPosition): JSX.Element[] { @@ -407,8 +424,8 @@ export function DslConnections() { const gapX = Math.abs(endX - startX); const gapY = Math.abs(endTempY - startY); - const radX = gapX > DIAMETER ? 20 : gapX/2; - const radY = gapY > DIAMETER ? 20 : gapY/2; + const radX = gapX > DIAMETER ? 20 : gapX / 2; + const radY = gapY > DIAMETER ? 20 : gapY / 2; const endY = rect2.y - top - radY - (toHeader ? 9 : 6); const iRadX = startX > endX ? -1 * radX : radX; @@ -443,14 +460,15 @@ 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}} viewBox={"0 0 " + (width) + " " + (height)}> <defs> - <marker id="arrowhead" markerWidth="9" markerHeight="6" refX="0" refY="3" orient="auto" className="arrow"> + <marker id="arrowhead" markerWidth="9" markerHeight="6" refX="0" refY="3" orient="auto" + className="arrow"> <polygon points="0 0, 9 3, 0 6"/> </marker> </defs>