You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by ma...@apache.org on 2024/02/14 21:44:52 UTC
(camel-karavan) 06/06: Incoming navigation for #1109
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 b23fe7eacc9772969bcf25a8ca72265138559130
Author: Marat Gubaidullin <ma...@talismancloud.io>
AuthorDate: Wed Feb 14 16:44:15 2024 -0500
Incoming navigation for #1109
---
karavan-space/src/App.tsx | 2 +-
karavan-space/src/designer/DesignerStore.ts | 17 ++++-
karavan-space/src/designer/KaravanDesigner.tsx | 10 +--
.../src/designer/route/DslConnections.tsx | 74 ++++++++++++++++++----
.../src/designer/utils/InfrastructureAPI.ts | 4 +-
karavan-space/src/space/SpacePage.tsx | 7 +-
karavan-space/src/topology/TopologyApi.tsx | 2 +-
karavan-space/src/topology/TopologyStore.ts | 9 ---
karavan-space/src/topology/TopologyTab.tsx | 5 +-
9 files changed, 94 insertions(+), 36 deletions(-)
diff --git a/karavan-space/src/App.tsx b/karavan-space/src/App.tsx
index 77d1289e..2adec90f 100644
--- a/karavan-space/src/App.tsx
+++ b/karavan-space/src/App.tsx
@@ -33,7 +33,7 @@ import {KnowledgebasePage} from "./knowledgebase/KnowledgebasePage";
import {EventBus} from "./designer/utils/EventBus";
import {Notification} from "./designer/utils/Notification";
import {TopologyTab} from "./topology/TopologyTab";
-import {IntegrationFile} from "./topology/TopologyStore";
+import {IntegrationFile} from "karavan-core/lib/model/IntegrationDefinition";
class MenuItem {
pageId: string = '';
diff --git a/karavan-space/src/designer/DesignerStore.ts b/karavan-space/src/designer/DesignerStore.ts
index ef95b8d4..7a6aab41 100644
--- a/karavan-space/src/designer/DesignerStore.ts
+++ b/karavan-space/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-space/src/designer/KaravanDesigner.tsx b/karavan-space/src/designer/KaravanDesigner.tsx
index 05831a38..9fbe3864 100644
--- a/karavan-space/src/designer/KaravanDesigner.tsx
+++ b/karavan-space/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";
@@ -48,7 +48,7 @@ interface Props {
onSaveCustomCode: (name: string, code: string) => void
onGetCustomCode: (name: string, javaType: string) => Promise<string | undefined>
onSavePropertyPlaceholder: (key: string, value: string) => void
- onInternalConsumerClick: (uri: string, name: string) => void
+ onInternalConsumerClick: (uri?: string, name?: string, routeId?: string) => void
filename: string
yaml: string
dark: boolean
@@ -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-space/src/designer/route/DslConnections.tsx b/karavan-space/src/designer/route/DslConnections.tsx
index ebb89933..99339f7c 100644
--- a/karavan-space/src/designer/route/DslConnections.tsx
+++ b/karavan-space/src/designer/route/DslConnections.tsx
@@ -24,28 +24,45 @@ 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 {DeleteElementIcon} from "../utils/ElementIcons";
-import {Button} 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";
const overlapGap: number = 40;
export function DslConnections() {
- const [integration] = useIntegrationStore((state) => [state.integration], 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] =
useConnectionsStore((s) => [s.steps, s.addStep, s.deleteStep, s.clearSteps], shallow)
const [svgKey, setSvgKey] = useState<string>('svgKey');
+ const [tons, setTons] = useState<Map<string, string[]>>(new Map<string, string[]>());
useEffect(() => {
+ const integrations = getIntegrations(files);
+ setTons(prevState => {
+ const data = new Map<string, string[]>();
+ TopologyUtils.findTopologyOutgoingNodes(integrations).forEach(t => {
+ const key = (t.step as any)?.uri + ':' + (t.step as any)?.parameters.name;
+ if (data.has(key)) {
+ const list = data.get(key) || [];
+ list.push(t.routeId);
+ data.set(key, list);
+ } else {
+ data.set(key, [t.routeId]);
+ }
+ });
+ return data;
+ });
const sub1 = EventBus.onPosition()?.subscribe((evt: DslPosition) => setPosition(evt));
return () => {
sub1?.unsubscribe();
};
- });
+ }, [files]);
useEffect(() => {
const toDelete1: string[] = Array.from(steps.keys()).filter(k => CamelDefinitionApiExt.findElementInIntegration(integration, k) === undefined);
@@ -63,11 +80,17 @@ 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 => !(pos.step.dslName === 'FromDefinition' && TopologyUtils.hasInternalUri(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) => {
const y1 = pos1.headerRect.y + pos1.headerRect.height / 2;
@@ -104,9 +127,22 @@ 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 getIncomingIcons(data: [string, number]) {
const pos = steps.get(data[0]);
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 localDirects = getToDirectSteps(name);
const fromY = pos.headerRect.y + pos.headerRect.height / 2 - top;
const r = pos.headerRect.height / 2;
const incomingX = 20;
@@ -116,6 +152,16 @@ export function DslConnections() {
<div key={pos.step.uuid + "-icon"}
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"}>
+ <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)}>
+ {routeId}
+ </Button>
+ </Tooltip>
+ )}
</div>
)
}
@@ -204,13 +250,15 @@ export function DslConnections() {
<div key={pos.step.uuid + "-icon"}
style={{display: "block", position: "absolute", top: imageY, left: imageX}}>
{CamelUi.getConnectionIcon(pos.step)}
- {directOrSeda &&
- <Button style={{position: 'absolute', right: 27, top: -12, whiteSpace: 'nowrap', zIndex: 300, padding: 0}}
- variant={'link'}
- aria-label="Goto"
- onClick={_ => InfrastructureAPI.onInternalConsumerClick(uri, name)}>
- {name}
- </Button>
+ {name !== undefined &&
+ <Tooltip content={`Go to ${uri}:${name}`} position={"left"}>
+ <Button style={{position: 'absolute', right: 27, top: -12, whiteSpace: 'nowrap', zIndex: 300, padding: 0}}
+ variant={'link'}
+ aria-label="Goto"
+ onClick={_ => InfrastructureAPI.onInternalConsumerClick(uri, name, undefined)}>
+ {name}
+ </Button>
+ </Tooltip>
}
</div>
)
diff --git a/karavan-space/src/designer/utils/InfrastructureAPI.ts b/karavan-space/src/designer/utils/InfrastructureAPI.ts
index 77ef1bd3..c386d6fc 100644
--- a/karavan-space/src/designer/utils/InfrastructureAPI.ts
+++ b/karavan-space/src/designer/utils/InfrastructureAPI.ts
@@ -21,7 +21,7 @@ export class InfrastructureAPI {
static onSaveCustomCode: (name: string, code: string) => void;
static onSave: (filename: string, yaml: string, propertyOnly: boolean) => void;
static onSavePropertyPlaceholder: (key: string, value: string) => void;
- static onInternalConsumerClick: (uri: string, name: string) => void;
+ static onInternalConsumerClick: (uri?: string, name?: string, routeId?: string) => void;
static setOnGetCustomCode(onGetCustomCode: (name: string, javaType: string) => Promise<string | undefined>){
this.onGetCustomCode = onGetCustomCode
@@ -39,7 +39,7 @@ export class InfrastructureAPI {
this.onSavePropertyPlaceholder = onSavePropertyPlaceholder
}
- static setOnInternalConsumerClick(onInternalConsumerClick:(uri: string, name: string) => void){
+ static setOnInternalConsumerClick(onInternalConsumerClick:(uri?: string, name?: string, routeId?: string) => void){
this.onInternalConsumerClick = onInternalConsumerClick
}
diff --git a/karavan-space/src/space/SpacePage.tsx b/karavan-space/src/space/SpacePage.tsx
index 24c62b66..548e5025 100644
--- a/karavan-space/src/space/SpacePage.tsx
+++ b/karavan-space/src/space/SpacePage.tsx
@@ -28,7 +28,7 @@ import DownloadImageIcon from "@patternfly/react-icons/dist/esm/icons/image-icon
import GithubImageIcon from "@patternfly/react-icons/dist/esm/icons/github-icon";
import UploadIcon from "@patternfly/react-icons/dist/esm/icons/upload-icon";
import {KaravanDesigner} from "../designer/KaravanDesigner";
-import Editor from "@monaco-editor/react";
+import {IntegrationFile} from "karavan-core/lib/model/IntegrationDefinition";
import {UploadModal} from "./UploadModal";
import {EventBus} from "../designer/utils/EventBus";
@@ -111,9 +111,10 @@ export class SpacePage extends React.Component<Props, State> {
propertyPlaceholders={[]}
beans={[]}
onSavePropertyPlaceholder={(key, value) => {}}
- onInternalConsumerClick={(uri, name) => {
- console.log("onInternalConsumerClick", uri, name)
+ onInternalConsumerClick={(uri?: string, name?: string, routeId?: string) => {
+ console.log("onInternalConsumerClick", uri, name, routeId)
}}
+ files={[new IntegrationFile("example.camel.yaml", yaml)]}
/>
)
}
diff --git a/karavan-space/src/topology/TopologyApi.tsx b/karavan-space/src/topology/TopologyApi.tsx
index c60c197b..a640d508 100644
--- a/karavan-space/src/topology/TopologyApi.tsx
+++ b/karavan-space/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-space/src/topology/TopologyStore.ts b/karavan-space/src/topology/TopologyStore.ts
index 4e9ee643..517e2794 100644
--- a/karavan-space/src/topology/TopologyStore.ts
+++ b/karavan-space/src/topology/TopologyStore.ts
@@ -18,15 +18,6 @@
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 {
selectedIds: string []
diff --git a/karavan-space/src/topology/TopologyTab.tsx b/karavan-space/src/topology/TopologyTab.tsx
index 1f2d165e..694eeb64 100644
--- a/karavan-space/src/topology/TopologyTab.tsx
+++ b/karavan-space/src/topology/TopologyTab.tsx
@@ -31,10 +31,11 @@ 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[],
@@ -137,7 +138,7 @@ export function TopologyTab(props: Props) {
});
}, [ranker, controller, setRanker]);
- return (
+ return (
<TopologyView
className="topology-panel"
contextToolbar={!props.hideToolbar