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 828e234ffabc729377a1d469e97a7ac0dff28845 Author: Marat Gubaidullin <[email protected]> AuthorDate: Sun Sep 1 14:45:27 2024 -0400 Sync with designer --- karavan-vscode/webview/topology/CustomGroup.tsx | 6 +- karavan-vscode/webview/topology/CustomNode.tsx | 23 ++-- karavan-vscode/webview/topology/TopologyApi.tsx | 126 ++++++++++++--------- .../webview/topology/TopologyPropertiesPanel.tsx | 4 +- karavan-vscode/webview/topology/TopologyTab.tsx | 5 +- .../webview/topology/TopologyToolbar.tsx | 7 ++ karavan-vscode/webview/topology/topology.css | 4 + 7 files changed, 110 insertions(+), 65 deletions(-) diff --git a/karavan-vscode/webview/topology/CustomGroup.tsx b/karavan-vscode/webview/topology/CustomGroup.tsx index 9e366c7c..595250a8 100644 --- a/karavan-vscode/webview/topology/CustomGroup.tsx +++ b/karavan-vscode/webview/topology/CustomGroup.tsx @@ -18,13 +18,11 @@ import * as React from 'react'; import './topology.css'; -import { DefaultGroup, observer} from '@patternfly/react-topology'; - +import {DefaultGroup, observer} from '@patternfly/react-topology'; const CustomGroup: React.FC<any> = observer(({ element, ...rest }) => { - return ( - <DefaultGroup element={element} {...rest}> + <DefaultGroup element={element} className={"topology-group"} {...rest}> </DefaultGroup> ) }) diff --git a/karavan-vscode/webview/topology/CustomNode.tsx b/karavan-vscode/webview/topology/CustomNode.tsx index e0a022d0..fd8d12e6 100644 --- a/karavan-vscode/webview/topology/CustomNode.tsx +++ b/karavan-vscode/webview/topology/CustomNode.tsx @@ -22,6 +22,8 @@ import {DefaultNode, observer} from '@patternfly/react-topology'; import {getDesignerIcon} from "../designer/icons/KaravanIcons"; import {CamelUi} from "../designer/utils/CamelUi"; import './topology.css'; +import {RouteDefinition} from "core/model/CamelDefinition"; +import {AutoStartupIcon, ErrorHandlerIcon} from "../designer/icons/OtherIcons"; function getIcon(data: any) { if (['route', 'rest', 'routeConfiguration'].includes(data.icon)) { @@ -41,15 +43,22 @@ function getIcon(data: any) { } function getAttachments(data: any) { - if (data?.step?.dslName === 'RouteDefinition' && data?.step?.autoStartup !== false) { - const x = 0; - const y = 0; - const rx = x + 9; - const ry = y + 9; + if (data && data?.step?.dslName === 'RouteDefinition') { + const route: RouteDefinition = data?.step; + const autoStartup = route?.autoStartup !== false; + const errorHandler = route?.errorHandler !== undefined; return ( <g className="pf-topology__node__label__badge auto-start" transform="translate(-4, -4)"> - <rect className="badge" x={x} width="22" y={y} height="17" rx={rx} ry={ry}></rect> - <text className='text' x={rx + 2} y={ry} textAnchor="middle" dy="0.35em">A</text> + {errorHandler && + <g className="" transform="translate(13, -4)"> + {ErrorHandlerIcon()} + </g> + } + {autoStartup && + <g className="" transform="translate(-4, -4)"> + {AutoStartupIcon()} + </g> + } </g> ) } else <></> diff --git a/karavan-vscode/webview/topology/TopologyApi.tsx b/karavan-vscode/webview/topology/TopologyApi.tsx index a6385542..fda10d1f 100644 --- a/karavan-vscode/webview/topology/TopologyApi.tsx +++ b/karavan-vscode/webview/topology/TopologyApi.tsx @@ -33,15 +33,10 @@ import CustomNode from "./CustomNode"; import {Integration, IntegrationFile} from "core/model/IntegrationDefinition"; import {CamelDefinitionYaml} from "core/api/CamelDefinitionYaml"; import {TopologyUtils} from "core/api/TopologyUtils"; -import { - TopologyIncomingNode, - TopologyOutgoingNode, - TopologyRestNode, - TopologyRouteConfigurationNode, - TopologyRouteNode -} from "core/model/TopologyDefinition"; +import {TopologyIncomingNode, TopologyOutgoingNode, TopologyRestNode, TopologyRouteConfigurationNode, TopologyRouteNode} from "core/model/TopologyDefinition"; import CustomEdge from "./CustomEdge"; import CustomGroup from "./CustomGroup"; +import {INTERNAL_COMPONENTS} from "core/api/ComponentApi"; const NODE_DIAMETER = 60; @@ -174,16 +169,18 @@ export function getExternalEdges(tons: TopologyOutgoingNode[], tins: TopologyInc tons.filter(ton => ton.type === 'external').forEach((ton, index) => { const uniqueUri = ton.uniqueUri; if (uniqueUri) { - const target = TopologyUtils.getNodeIdByUniqueUri(tins, uniqueUri); - const node: EdgeModel = { - id: 'external-' + ton.id + '-' + index, - type: 'edge', - source: ton.id, - target: target, - edgeStyle: EdgeStyle.dotted, - animationSpeed: EdgeAnimationSpeed.slow - } - if (target) result.push(node); + TopologyUtils.getNodeIdByUniqueUri(tins, uniqueUri).forEach(target => { + const node: EdgeModel = { + id: 'external-' + ton.id + '-' + target, + type: 'edge', + source: ton.id, + target: target, + edgeStyle: EdgeStyle.dotted, + animationSpeed: EdgeAnimationSpeed.medium, + data : {groupName: uniqueUri} + } + result.push(node); + }); } }); return result; @@ -251,8 +248,10 @@ export function getInternalEdges(tons: TopologyOutgoingNode[], tins: TopologyInc if (target) result.push(node); } else { const uri: string = (ton.step as any).uri; - if (uri?.startsWith("direct") || uri?.startsWith("seda")) { - const name = (ton.step as any).parameters.name; + const component = uri?.split(":")?.[0]; + if (INTERNAL_COMPONENTS.includes(component)) { + const step = (ton.step as any); + const name = step.parameters.name || step.parameters.address; const target = TopologyUtils.getRouteIdByUriAndName(tins, uri, name); const node: EdgeModel = { id: 'internal-' + ton.id + '-' + index, @@ -280,33 +279,6 @@ export function getModel(files: IntegrationFile[], grouping?: boolean): Model { const trcons = TopologyUtils.findTopologyRouteConfigurationOutgoingNodes(integrations); const nodes: NodeModel[] = []; - const groups: NodeModel[] = []; - - const children1: string[] = []; - children1.push(...tins.filter(i => i.type === 'external').map(i => i.id)); - children1.push(...trestns.map(i => i.id)); - groups.push({ - id: 'consumer-group', - children: children1, - type: 'group', - group: true, - label: 'Consumer group', - style: { - padding: 25, - } - }) - - const children2 = [...tons.filter(i => i.type === 'external').map(i => i.id)]; - groups.push({ - id: 'producer-group', - children: children2, - type: 'group', - group: true, - label: 'Producer group', - style: { - padding: 25, - } - }) nodes.push(...getRestNodes(trestns)) nodes.push(...getIncomingNodes(tins)) @@ -315,17 +287,69 @@ export function getModel(files: IntegrationFile[], grouping?: boolean): Model { nodes.push(...getOutgoingNodes(tons)) nodes.push(...getOutgoingNodes(trcons)) - if (grouping === true) { - nodes.push(...groups) - } - const edges: EdgeModel[] = []; edges.push(...getIncomingEdges(tins)); edges.push(...getOutgoingEdges(tons)); edges.push(...getRestEdges(trestns, tins)); edges.push(...getInternalEdges(tons, tins)); edges.push(...getInternalEdges(trcons, tins)); - // edges.push(...getExternalEdges(tons,tins)); + + + // Groups + const groups: NodeModel[] = []; + if (grouping === true) { + const children1: string[] = []; + children1.push(...tins.filter(i => i.type === 'external').map(i => i.id)); + children1.push(...trestns.map(i => i.id)); + groups.push({ + id: 'consumer-group', + children: children1, + type: 'group', + group: true, + label: 'Consumer group', + style: { + padding: 20, + } + }) + + const children2 = [...tons.filter(i => i.type === 'external').map(i => i.id)]; + groups.push({ + id: 'producer-group', + children: children2, + type: 'group', + group: true, + label: 'Producer group', + style: { + padding: 20, + }, + }) + } else { + const externalEdges = getExternalEdges(tons,tins); + edges.push(...externalEdges); + // const uniqueGroups: Map<string, string[]> = new Map(); + // + // externalEdges.forEach(edge => { + // const groupName = edge.data.groupName; + // const children = uniqueGroups.get(groupName) || []; + // if (edge.source) children.push(edge.source) + // if (edge.target) children.push(edge.target) + // uniqueGroups.set(groupName, [...new Set(children)]); + // }); + // + // uniqueGroups.forEach((children, groupName) => { + // groups.push({ + // id: groupName + '-group', + // children: children, + // type: 'group', + // group: true, + // // label: edge.id + ' group', + // style: { + // padding: 20, + // } + // }) + // }) + } + nodes.push(...groups) return {nodes: nodes, edges: edges, graph: {id: 'g1', type: 'graph', layout: 'Dagre'}}; } diff --git a/karavan-vscode/webview/topology/TopologyPropertiesPanel.tsx b/karavan-vscode/webview/topology/TopologyPropertiesPanel.tsx index 0fd93b3d..60ae9a50 100644 --- a/karavan-vscode/webview/topology/TopologyPropertiesPanel.tsx +++ b/karavan-vscode/webview/topology/TopologyPropertiesPanel.tsx @@ -30,7 +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"; +import {INTERNAL_COMPONENTS} from "core/api/ComponentApi"; interface Props { onSetFile: (fileName: string) => void @@ -69,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 (NAV_COMPONENTS.includes(uri)) { + if (INTERNAL_COMPONENTS.includes(uri)) { return uri.concat(":").concat(name); } else { return uri; diff --git a/karavan-vscode/webview/topology/TopologyTab.tsx b/karavan-vscode/webview/topology/TopologyTab.tsx index 51f5d24e..a98703b4 100644 --- a/karavan-vscode/webview/topology/TopologyTab.tsx +++ b/karavan-vscode/webview/topology/TopologyTab.tsx @@ -45,6 +45,7 @@ interface Props { onClickAddREST: () => void onClickAddKamelet: () => void onClickAddBean: () => void + isDev?: boolean } export function TopologyTab(props: Props) { @@ -146,7 +147,9 @@ export function TopologyTab(props: Props) { ? <TopologyToolbar onClickAddRoute={props.onClickAddRoute} onClickAddBean={props.onClickAddBean} onClickAddKamelet={props.onClickAddKamelet} - onClickAddREST={props.onClickAddREST}/> + onClickAddREST={props.onClickAddREST} + isDev={props.isDev} + /> : undefined} sideBar={<TopologyPropertiesPanel onSetFile={props.onSetFile}/>} controlBar={ diff --git a/karavan-vscode/webview/topology/TopologyToolbar.tsx b/karavan-vscode/webview/topology/TopologyToolbar.tsx index 0b23c542..2ac6eda9 100644 --- a/karavan-vscode/webview/topology/TopologyToolbar.tsx +++ b/karavan-vscode/webview/topology/TopologyToolbar.tsx @@ -24,17 +24,20 @@ import PlusIcon from "@patternfly/react-icons/dist/esm/icons/plus-icon"; import {useTopologyStore} from "./TopologyStore"; import {shallow} from "zustand/shallow"; + interface Props { onClickAddRoute: () => void onClickAddREST: () => void onClickAddKamelet: () => void onClickAddBean: () => void + isDev?: boolean } export function TopologyToolbar (props: Props) { const [showGroups, setShowGroups] = useTopologyStore((s) => [s.showGroups, s.setShowGroups], shallow); + const isDev = props.isDev return ( <div className='topology-toolbar'> @@ -52,6 +55,7 @@ export function TopologyToolbar (props: Props) { <ToolbarItem align={{default:"alignRight"}}> <Tooltip content={"Add Integration Route"} position={"bottom"}> <Button className="dev-action-button" size="sm" + isDisabled={!isDev} variant={"primary"} icon={<PlusIcon/>} onClick={e => props.onClickAddRoute()} @@ -63,6 +67,7 @@ export function TopologyToolbar (props: Props) { <ToolbarItem align={{default:"alignRight"}}> <Tooltip content={"Add REST API"} position={"bottom"}> <Button className="dev-action-button" size="sm" + isDisabled={!isDev} variant={"secondary"} icon={<PlusIcon/>} onClick={e => props.onClickAddREST()} @@ -74,6 +79,7 @@ export function TopologyToolbar (props: Props) { <ToolbarItem align={{default:"alignRight"}}> <Tooltip content={"Add Kamelet"} position={"bottom"}> <Button className="dev-action-button" size="sm" + isDisabled={!isDev} variant={"secondary"} icon={<PlusIcon/>} onClick={e => props.onClickAddKamelet()} @@ -85,6 +91,7 @@ export function TopologyToolbar (props: Props) { <ToolbarItem align={{default:"alignRight"}}> <Tooltip content={"Add Bean"} position={"bottom"}> <Button className="dev-action-button" size="sm" + isDisabled={!isDev} variant={"secondary"} icon={<PlusIcon/>} onClick={e => props.onClickAddBean()} diff --git a/karavan-vscode/webview/topology/topology.css b/karavan-vscode/webview/topology/topology.css index 1828bd1e..6edc633d 100644 --- a/karavan-vscode/webview/topology/topology.css +++ b/karavan-vscode/webview/topology/topology.css @@ -115,4 +115,8 @@ .karavan .topology-panel .auto-start .text { fill: var(--pf-topology__node__label__text--Fill); +} + +.karavan .topology-group .pf-topology__group__label { + display: none; } \ No newline at end of file
