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 6049277081ef75432d48af4535c5bf631f6e7161 Author: Marat Gubaidullin <ma...@talismancloud.io> AuthorDate: Wed Feb 14 12:05:37 2024 -0500 Incoming navigation for #1109 --- karavan-core/src/core/api/TopologyUtils.ts | 2 +- .../src/core/model/IntegrationDefinition.ts | 10 +++++++ karavan-designer/src/App.tsx | 6 ++--- karavan-designer/src/DesignerPage.tsx | 2 ++ karavan-designer/src/designer/DesignerStore.ts | 17 +++++++++++- karavan-designer/src/designer/KaravanDesigner.tsx | 8 +++--- .../src/designer/route/DslConnections.tsx | 31 +++++++++++++--------- karavan-designer/src/topology/TopologyApi.tsx | 2 +- karavan-designer/src/topology/TopologyStore.ts | 23 ---------------- karavan-designer/src/topology/TopologyTab.tsx | 16 ++++++----- 10 files changed, 64 insertions(+), 53 deletions(-) diff --git a/karavan-core/src/core/api/TopologyUtils.ts b/karavan-core/src/core/api/TopologyUtils.ts index 949fe507..38932df2 100644 --- a/karavan-core/src/core/api/TopologyUtils.ts +++ b/karavan-core/src/core/api/TopologyUtils.ts @@ -57,7 +57,7 @@ export class TopologyUtils { const uri = (element as any).uri; const component = ComponentApi.findByName(uri); return component !== undefined && - (TopologyUtils.isComponentInternal(component.component.label)); + (TopologyUtils.isComponentInternal(component.component.label) || TopologyUtils.hasInternalUri(element)); } static getConnectorType = (element: CamelElement): 'component' | 'kamelet' => { diff --git a/karavan-core/src/core/model/IntegrationDefinition.ts b/karavan-core/src/core/model/IntegrationDefinition.ts index 18d01dc8..f5cd70cd 100644 --- a/karavan-core/src/core/model/IntegrationDefinition.ts +++ b/karavan-core/src/core/model/IntegrationDefinition.ts @@ -17,6 +17,16 @@ import { v4 as uuidv4 } from 'uuid'; import { RegistryBeanDefinition } from './CamelDefinition'; +export class IntegrationFile { + name: string = ''; + code: string = ''; + + constructor(name: string, code: string) { + this.name = name; + this.code = code; + } +} + export class DefinitionProperty { title: string = ''; description: string = ''; diff --git a/karavan-designer/src/App.tsx b/karavan-designer/src/App.tsx index 9217fa82..46894d94 100644 --- a/karavan-designer/src/App.tsx +++ b/karavan-designer/src/App.tsx @@ -42,8 +42,7 @@ import {Notification} from "./designer/utils/Notification"; import {EventBus} from "./designer/utils/EventBus"; import {TopologyTab} from "./topology/TopologyTab"; import {useEffect, useState} from "react"; -import {IntegrationFile, useTopologyStore} from "./topology/TopologyStore"; -import {shallow} from "zustand/shallow"; +import {IntegrationFile} from "karavan-core/lib/model/IntegrationDefinition"; class MenuItem { pageId: string = ''; @@ -59,7 +58,6 @@ class MenuItem { export function App() { - const [setFiles] = useTopologyStore((s) => [s.setFiles], shallow); const [pageId, setPageId] = useState<string>('designer'); const [name, setName] = useState<string>('example.yaml'); const [key, setKey] = useState<string>(''); @@ -95,7 +93,6 @@ export function App() { if (data[4]) { setYaml(data[4]); setName("demo.camel.yaml"); - setFiles([new IntegrationFile("demo.camel.yaml", yaml)]); } if (data[5]) { @@ -167,6 +164,7 @@ export function App() { case "topology": return ( <TopologyTab + files={[new IntegrationFile("demo.camel.yaml", yaml)]} onSetFile={fileName => {}} onClickAddRoute={() => {}} onClickAddREST={() => {}} diff --git a/karavan-designer/src/DesignerPage.tsx b/karavan-designer/src/DesignerPage.tsx index 4a30e899..d3586927 100644 --- a/karavan-designer/src/DesignerPage.tsx +++ b/karavan-designer/src/DesignerPage.tsx @@ -26,6 +26,7 @@ import DownloadIcon from "@patternfly/react-icons/dist/esm/icons/download-icon"; import DownloadImageIcon from "@patternfly/react-icons/dist/esm/icons/image-icon"; import {KaravanDesigner} from "./designer/KaravanDesigner"; import {EventBus} from "./designer/utils/EventBus"; +import {IntegrationFile} from "karavan-core/lib/model/IntegrationDefinition"; interface Props { name: string, @@ -80,6 +81,7 @@ export const DesignerPage = (props: Props) => { onInternalConsumerClick={(uri, name, direction: 'from' | 'to') => { console.log("onInternalConsumerClick", uri, name, direction) }} + files={[new IntegrationFile("demo.camel.yaml", yaml)]} /> ) } diff --git a/karavan-designer/src/designer/DesignerStore.ts b/karavan-designer/src/designer/DesignerStore.ts index ef95b8d4..7a6aab41 100644 --- a/karavan-designer/src/designer/DesignerStore.ts +++ b/karavan-designer/src/designer/DesignerStore.ts @@ -20,6 +20,7 @@ import {DslPosition, EventBus} from "./utils/EventBus"; import {createWithEqualityFn} from "zustand/traditional"; import {shallow} from "zustand/shallow"; import {RegistryBeanDefinition} from "karavan-core/lib/model/CamelDefinition"; +import {IntegrationFile} from "karavan-core/lib/model/IntegrationDefinition"; interface IntegrationState { integration: Integration; @@ -27,6 +28,9 @@ interface IntegrationState { setIntegration: (integration: Integration, propertyOnly: boolean) => void; propertyOnly: boolean; reset: () => void; + files: IntegrationFile [] + setFiles: (files: IntegrationFile []) => void + resetFiles: (files: IntegrationFile []) => void } export const useIntegrationStore = createWithEqualityFn<IntegrationState>((set) => ({ @@ -46,7 +50,18 @@ export const useIntegrationStore = createWithEqualityFn<IntegrationState>((set) }, reset: () => { set({integration: Integration.createNew("demo", "plain"), json: '{}', propertyOnly: false}); - } + }, + files: [], + setFiles: (files: IntegrationFile []) => { + set((state: IntegrationState) => { + return {files: files}; + }); + }, + resetFiles: (files: IntegrationFile []) => { + set((state: IntegrationState) => { + return {files: [...files]}; + }); + }, }), shallow) diff --git a/karavan-designer/src/designer/KaravanDesigner.tsx b/karavan-designer/src/designer/KaravanDesigner.tsx index 75e6c012..58dbbf6d 100644 --- a/karavan-designer/src/designer/KaravanDesigner.tsx +++ b/karavan-designer/src/designer/KaravanDesigner.tsx @@ -28,7 +28,7 @@ import { import './karavan.css'; import {RouteDesigner} from "./route/RouteDesigner"; import {CamelDefinitionYaml} from "karavan-core/lib/api/CamelDefinitionYaml"; -import {Integration} from "karavan-core/lib/model/IntegrationDefinition"; +import {Integration, IntegrationFile} from "karavan-core/lib/model/IntegrationDefinition"; import {CamelUtil} from "karavan-core/lib/api/CamelUtil"; import {CamelUi} from "./utils/CamelUi"; import {useDesignerStore, useIntegrationStore} from "./DesignerStore"; @@ -57,6 +57,7 @@ interface Props { tab?: "routes" | "rest" | "beans" propertyPlaceholders: string[] beans: RegistryBeanDefinition[] + files: IntegrationFile[] } export function KaravanDesigner(props: Props) { @@ -65,8 +66,8 @@ export function KaravanDesigner(props: Props) { const [setDark, hideLogDSL, setHideLogDSL, setSelectedStep, reset, badge, message, setPropertyPlaceholders, setBeans] = useDesignerStore((s) => [s.setDark, s.hideLogDSL, s.setHideLogDSL, s.setSelectedStep, s.reset, s.notificationBadge, s.notificationMessage, s.setPropertyPlaceholders, s.setBeans], shallow) - const [integration, setIntegration] = useIntegrationStore((s) => - [s.integration, s.setIntegration], shallow) + const [integration, setIntegration, resetFiles] = useIntegrationStore((s) => + [s.integration, s.setIntegration, s.resetFiles], shallow) useEffect(() => { const sub = EventBus.onIntegrationUpdate()?.subscribe((update: IntegrationUpdate) => @@ -92,6 +93,7 @@ export function KaravanDesigner(props: Props) { setDark(props.dark); setPropertyPlaceholders(props.propertyPlaceholders) setBeans(props.beans) + resetFiles(props.files) setHideLogDSL(props.hideLogDSL === true); return () => { sub?.unsubscribe(); diff --git a/karavan-designer/src/designer/route/DslConnections.tsx b/karavan-designer/src/designer/route/DslConnections.tsx index cab339f8..072aaac9 100644 --- a/karavan-designer/src/designer/route/DslConnections.tsx +++ b/karavan-designer/src/designer/route/DslConnections.tsx @@ -26,15 +26,14 @@ import {CamelElement} from "karavan-core/lib/model/IntegrationDefinition"; import {v4 as uuidv4} from "uuid"; import {Button, Tooltip} from "@patternfly/react-core"; import {InfrastructureAPI} from "../utils/InfrastructureAPI"; -import {useTopologyStore} from "../../topology/TopologyStore"; import {getIntegrations} from "../../topology/TopologyApi"; +import {ComponentApi} from "karavan-core/lib/api/ComponentApi"; const overlapGap: number = 40; export function DslConnections() { - const [integration] = useIntegrationStore((state) => [state.integration], shallow) - const [files] = useTopologyStore((s) => [s.files], shallow); + const [integration, files] = useIntegrationStore((s) => [s.integration, s.files], shallow) const [width, height, top, left, hideLogDSL] = useDesignerStore((s) => [s.width, s.height, s.top, s.left, s.hideLogDSL], shallow) const [steps, addStep, deleteStep, clearSteps] = @@ -81,10 +80,16 @@ 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)); + } + function getIncomings() { let outs: [string, number][] = Array.from(steps.values()) .filter(pos => ["FromDefinition"].includes(pos.step.dslName)) - .filter(pos => !TopologyUtils.isElementInternalComponent(pos.step)) + .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) => { @@ -122,12 +127,12 @@ 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 => (s.step as any)?.parameters?.name === name) - } + // 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 => (s.step as any)?.parameters?.name === name) + // } function getIncomingIcons(data: [string, number]) { const pos = steps.get(data[0]); @@ -137,7 +142,7 @@ export function DslConnections() { 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 localDirects = getToDirectSteps(name); + // const localDirects = getToDirectSteps(name); const fromY = pos.headerRect.y + pos.headerRect.height / 2 - top; const r = pos.headerRect.height / 2; const incomingX = 20; @@ -152,7 +157,7 @@ export function DslConnections() { <Button style={{position: 'absolute', left: 27, top: (index * 16) + (12), whiteSpace: 'nowrap', zIndex: 300, padding: 0}} variant={'link'} aria-label="Goto" - onClick={_ => InfrastructureAPI.onInternalConsumerClick(uri, name, 'from')}> + onClick={_ => InfrastructureAPI.onInternalConsumerClick(uri, name, 'to')}> {routeId} </Button> </Tooltip> @@ -250,7 +255,7 @@ export function DslConnections() { <Button style={{position: 'absolute', right: 27, top: -12, whiteSpace: 'nowrap', zIndex: 300, padding: 0}} variant={'link'} aria-label="Goto" - onClick={_ => InfrastructureAPI.onInternalConsumerClick(uri, name, 'to')}> + onClick={_ => InfrastructureAPI.onInternalConsumerClick(uri, name, 'from')}> {name} </Button> </Tooltip> diff --git a/karavan-designer/src/topology/TopologyApi.tsx b/karavan-designer/src/topology/TopologyApi.tsx index c60c197b..a640d508 100644 --- a/karavan-designer/src/topology/TopologyApi.tsx +++ b/karavan-designer/src/topology/TopologyApi.tsx @@ -39,7 +39,7 @@ import { TopologyRouteNode } from "karavan-core/lib/model/TopologyDefinition"; import CustomEdge from "./CustomEdge"; -import {IntegrationFile} from "./TopologyStore"; +import {IntegrationFile} from "karavan-core/lib/model/IntegrationDefinition"; import CustomGroup from "./CustomGroup"; const NODE_DIAMETER = 60; diff --git a/karavan-designer/src/topology/TopologyStore.ts b/karavan-designer/src/topology/TopologyStore.ts index c6322f39..517e2794 100644 --- a/karavan-designer/src/topology/TopologyStore.ts +++ b/karavan-designer/src/topology/TopologyStore.ts @@ -18,20 +18,8 @@ import {createWithEqualityFn} from "zustand/traditional"; import {shallow} from "zustand/shallow"; -export class IntegrationFile { - name: string = ''; - code: string = ''; - - constructor(name: string, code: string) { - this.name = name; - this.code = code; - } -} interface TopologyState { - files: IntegrationFile [] - setFiles: (files: IntegrationFile []) => void - resetFiles: (files: IntegrationFile []) => void selectedIds: string [] fileName?: string setSelectedIds: (selectedIds: string []) => void @@ -43,17 +31,6 @@ interface TopologyState { } export const useTopologyStore = createWithEqualityFn<TopologyState>((set) => ({ - files: [], - setFiles: (files: IntegrationFile []) => { - set((state: TopologyState) => { - return {files: files}; - }); - }, - resetFiles: (files: IntegrationFile []) => { - set((state: TopologyState) => { - return {files: [...files]}; - }); - }, selectedIds: [], setSelectedIds: (selectedIds: string[]) => { set((state: TopologyState) => { diff --git a/karavan-designer/src/topology/TopologyTab.tsx b/karavan-designer/src/topology/TopologyTab.tsx index bf16124a..694eeb64 100644 --- a/karavan-designer/src/topology/TopologyTab.tsx +++ b/karavan-designer/src/topology/TopologyTab.tsx @@ -31,12 +31,14 @@ import { } from '@patternfly/react-topology'; import {customComponentFactory, getModel} from "./TopologyApi"; import {shallow} from "zustand/shallow"; -import {IntegrationFile, useTopologyStore} from "./TopologyStore"; +import {useTopologyStore} from "./TopologyStore"; import {TopologyPropertiesPanel} from "./TopologyPropertiesPanel"; import {TopologyToolbar} from "./TopologyToolbar"; import {useDesignerStore} from "../designer/DesignerStore"; +import {IntegrationFile} from "karavan-core/lib/model/IntegrationDefinition"; interface Props { + files: IntegrationFile[], onSetFile: (fileName: string) => void hideToolbar: boolean onClickAddRoute: () => void @@ -46,8 +48,8 @@ interface Props { export function TopologyTab(props: Props) { - const [selectedIds, setSelectedIds, setFileName, ranker, setRanker, setNodeData, files] = useTopologyStore((s) => - [s.selectedIds, s.setSelectedIds, s.setFileName, s.ranker, s.setRanker, s.setNodeData, s.files], shallow); + const [selectedIds, setSelectedIds, setFileName, ranker, setRanker, setNodeData] = useTopologyStore((s) => + [s.selectedIds, s.setSelectedIds, s.setFileName, s.ranker, s.setRanker, s.setNodeData], shallow); const [setSelectedStep] = useDesignerStore((s) => [s.setSelectedStep], shallow) function setTopologySelected(model: Model, ids: string []) { @@ -69,7 +71,7 @@ export function TopologyTab(props: Props) { } const controller = React.useMemo(() => { - const model = getModel(files); + const model = getModel(props.files); const newController = new Visualization(); newController.registerLayoutFactory((_, graph) => new DagreLayout(graph, { @@ -96,9 +98,9 @@ export function TopologyTab(props: Props) { React.useEffect(() => { setSelectedIds([]) - const model = getModel(files); + const model = getModel(props.files); controller.fromModel(model, false); - }, [ranker, controller, setSelectedIds, files]); + }, [ranker, controller, setSelectedIds, props.files]); const controlButtons = React.useMemo(() => { // const customButtons = [ @@ -136,7 +138,7 @@ export function TopologyTab(props: Props) { }); }, [ranker, controller, setRanker]); - return ( + return ( <TopologyView className="topology-panel" contextToolbar={!props.hideToolbar