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 2023/10/20 17:03:15 UTC
[camel-karavan] branch main updated: Topology in space
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
The following commit(s) were added to refs/heads/main by this push:
new 3a6ee123 Topology in space
3a6ee123 is described below
commit 3a6ee1239f39992701b091ea81c2b354ceaa6a42
Author: Marat Gubaidullin <ma...@talismancloud.io>
AuthorDate: Fri Oct 20 13:03:07 2023 -0400
Topology in space
---
karavan-space/src/App.tsx | 21 +++++++++++++--
.../src/designer/beans/BeanProperties.tsx | 6 ++---
karavan-space/src/designer/beans/BeansDesigner.tsx | 2 +-
.../src/designer/kamelet/KameletDesigner.tsx | 2 +-
.../src/designer/route/usePropertiesHook.tsx | 4 ++-
karavan-space/src/topology/CustomNode.tsx | 7 ++++-
karavan-space/src/topology/TopologyApi.tsx | 31 ++++++++++++++++++----
karavan-space/src/topology/TopologyTab.tsx | 1 -
8 files changed, 59 insertions(+), 15 deletions(-)
diff --git a/karavan-space/src/App.tsx b/karavan-space/src/App.tsx
index c5d11f87..728230e8 100644
--- a/karavan-space/src/App.tsx
+++ b/karavan-space/src/App.tsx
@@ -23,14 +23,17 @@ import {KameletApi} from "karavan-core/lib/api/KameletApi";
import {ComponentApi} from "karavan-core/lib/api/ComponentApi";
import {BlueprintIcon} from "@patternfly/react-icons";
import KnowledgebaseIcon from "@patternfly/react-icons/dist/js/icons/book-open-icon";
+import TopologyIcon from "@patternfly/react-icons/dist/js/icons/topology-icon";
import {KaravanIcon} from "./designer/utils/KaravanIcons";
import './designer/karavan.css';
import {SpacePage} from "./space/SpacePage";
import {GithubModal} from "./space/GithubModal";
import {TemplateApi} from "karavan-core/lib/api/TemplateApi";
import {KnowledgebasePage} from "./knowledgebase/KnowledgebasePage";
-import {EventBus, ToastMessage} from "./designer/utils/EventBus";
+import {EventBus} from "./designer/utils/EventBus";
import {Notification} from "./designer/utils/Notification";
+import {TopologyTab} from "./topology/TopologyTab";
+import {IntegrationFile} from "./topology/TopologyStore";
class MenuItem {
pageId: string = '';
@@ -60,7 +63,7 @@ class App extends React.Component<Props, State> {
public state: State = {
pageId: "designer",
- name: 'example.yaml',
+ name: 'example.camel.yaml',
key: '',
yaml: '',
githubModalIsOpen: false
@@ -118,6 +121,7 @@ class App extends React.Component<Props, State> {
const {pageId} = this.state;
const pages: MenuItem[] = [
new MenuItem("designer", "Designer", <BlueprintIcon/>),
+ new MenuItem("topology", "Topology", <TopologyIcon/>),
new MenuItem("knowledgebase", "Knowledgebase", <KnowledgebaseIcon/>),
]
return (<Flex className="nav-buttons" direction={{default: "column"}} style={{height: "100%"}}
@@ -144,6 +148,10 @@ class App extends React.Component<Props, State> {
</Flex>)
}
+ getIntegrationFiles(): IntegrationFile[]{
+ return [new IntegrationFile("example.camel.yaml", this.state.yaml)];
+ }
+
getDesigner() {
const {name, yaml, pageId} = this.state;
const dark = document.body.className.includes('vscode-dark');
@@ -161,6 +169,15 @@ class App extends React.Component<Props, State> {
return (
<KnowledgebasePage dark={dark}/>
)
+ case "topology":
+ return (
+ <TopologyTab
+ files={this.getIntegrationFiles()}
+ onSetFile={fileName => {}}
+ onClickCreateButton={() => {}}
+ hideToolbar={false}
+ />
+ )
}
}
diff --git a/karavan-space/src/designer/beans/BeanProperties.tsx b/karavan-space/src/designer/beans/BeanProperties.tsx
index fdb73d2a..455291c4 100644
--- a/karavan-space/src/designer/beans/BeanProperties.tsx
+++ b/karavan-space/src/designer/beans/BeanProperties.tsx
@@ -73,7 +73,7 @@ export function BeanProperties (props: Props) {
function onBeanPropertyUpdate () {
if (selectedStep) {
- const bean = CamelUtil.cloneBean(selectedStep);
+ const bean = CamelUtil.cloneBean(selectedStep as RegistryBeanDefinition);
const beanProperties: any = {};
properties.forEach((p: any) => beanProperties[p[0]] = p[1]);
bean.properties = beanProperties;
@@ -83,7 +83,7 @@ export function BeanProperties (props: Props) {
function beanFieldChanged (fieldId: string, value: string) {
if (selectedStep) {
- const bean = CamelUtil.cloneBean(selectedStep);
+ const bean = CamelUtil.cloneBean(selectedStep as RegistryBeanDefinition);
(bean as any)[fieldId] = value;
props.onChange(bean);
}
@@ -137,7 +137,7 @@ export function BeanProperties (props: Props) {
function cloneBean () {
if (selectedStep) {
- const bean = CamelUtil.cloneBean(selectedStep);
+ const bean = CamelUtil.cloneBean(selectedStep as RegistryBeanDefinition);
bean.uuid = uuidv4();
props.onClone(bean);
}
diff --git a/karavan-space/src/designer/beans/BeansDesigner.tsx b/karavan-space/src/designer/beans/BeansDesigner.tsx
index 64bac96f..8cd99f25 100644
--- a/karavan-space/src/designer/beans/BeansDesigner.tsx
+++ b/karavan-space/src/designer/beans/BeansDesigner.tsx
@@ -49,7 +49,7 @@ export function BeansDesigner() {
}
function deleteBean() {
- const i = CamelDefinitionApiExt.deleteBeanFromIntegration(integration, selectedStep);
+ const i = CamelDefinitionApiExt.deleteBeanFromIntegration(integration, selectedStep as RegistryBeanDefinition);
setIntegration(i, false);
setShowDeleteConfirmation(false);
setSelectedStep(undefined);
diff --git a/karavan-space/src/designer/kamelet/KameletDesigner.tsx b/karavan-space/src/designer/kamelet/KameletDesigner.tsx
index dd889b92..c235ef9b 100644
--- a/karavan-space/src/designer/kamelet/KameletDesigner.tsx
+++ b/karavan-space/src/designer/kamelet/KameletDesigner.tsx
@@ -52,7 +52,7 @@ export function KameletDesigner() {
}
function deleteBean() {
- const i = CamelDefinitionApiExt.deleteBeanFromIntegration(integration, selectedStep);
+ const i = CamelDefinitionApiExt.deleteBeanFromIntegration(integration, selectedStep as RegistryBeanDefinition);
setIntegration(i, false);
setShowDeleteConfirmation(false);
setSelectedStep(undefined);
diff --git a/karavan-space/src/designer/route/usePropertiesHook.tsx b/karavan-space/src/designer/route/usePropertiesHook.tsx
index eba82bf2..87513b18 100644
--- a/karavan-space/src/designer/route/usePropertiesHook.tsx
+++ b/karavan-space/src/designer/route/usePropertiesHook.tsx
@@ -75,6 +75,7 @@ export function usePropertiesHook (isRouteDesigner: boolean = true) {
}
function onPropertyChange (fieldId: string, value: string | number | boolean | any, newRoute?: RouteToCreate){
+ value = value === '' ? undefined : value;
if (selectedStep) {
const clone = CamelUtil.cloneStep(selectedStep);
(clone as any)[fieldId] = value;
@@ -99,7 +100,8 @@ export function usePropertiesHook (isRouteDesigner: boolean = true) {
}
function onParametersChange (parameter: string, value: string | number | boolean | any, pathParameter?: boolean, newRoute?: RouteToCreate) {
- if (selectedStep && selectedStep) {
+ value = value === '' ? undefined : value;
+ if (selectedStep) {
const clone = (CamelUtil.cloneStep(selectedStep));
const parameters: any = {...(clone as any).parameters};
parameters[parameter] = value;
diff --git a/karavan-space/src/topology/CustomNode.tsx b/karavan-space/src/topology/CustomNode.tsx
index fb517ae9..d683d04f 100644
--- a/karavan-space/src/topology/CustomNode.tsx
+++ b/karavan-space/src/topology/CustomNode.tsx
@@ -43,11 +43,16 @@ function getIcon(data: any) {
const CustomNode: React.FC<any> = observer(({ element, ...rest }) => {
const data = element.getData();
+ const badge:string = data.badge?.substring(0,1).toUpperCase();
return (
<DefaultNode
+ badge={badge}
+ showStatusDecorator
className="common-node"
- element={element} {...rest}
+ scaleLabel={false}
+ element={element}
+ {...rest}
>
{getIcon(data)}
</DefaultNode>
diff --git a/karavan-space/src/topology/TopologyApi.tsx b/karavan-space/src/topology/TopologyApi.tsx
index 44ff57a2..c60c197b 100644
--- a/karavan-space/src/topology/TopologyApi.tsx
+++ b/karavan-space/src/topology/TopologyApi.tsx
@@ -38,9 +38,9 @@ import {
TopologyRestNode,
TopologyRouteNode
} from "karavan-core/lib/model/TopologyDefinition";
-import CustomGroup from "./CustomGroup";
import CustomEdge from "./CustomEdge";
import {IntegrationFile} from "./TopologyStore";
+import CustomGroup from "./CustomGroup";
const NODE_DIAMETER = 60;
@@ -62,7 +62,7 @@ export function getIncomingNodes(tins: TopologyIncomingNode[]): NodeModel[] {
status: NodeStatus.default,
data: {
isAlternate: false,
- badge: tin.type,
+ badge: tin.connectorType,
icon: 'element',
type: 'step',
step: tin.from,
@@ -110,7 +110,7 @@ export function getOutgoingNodes(tons: TopologyOutgoingNode[]): NodeModel[] {
icon: 'element',
type: 'step',
step: tin.step,
- badge: tin.type,
+ badge: tin.connectorType,
fileName: tin.fileName
}
}
@@ -146,6 +146,26 @@ export function getOutgoingEdges(tons: TopologyOutgoingNode[]): EdgeModel[] {
});
}
+export function getExternalEdges(tons: TopologyOutgoingNode[], tins: TopologyIncomingNode[]): EdgeModel[] {
+ const result: EdgeModel[]= [];
+ 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);
+ }
+ });
+ return result;
+}
+
export function getRestNodes(tins: TopologyRestNode[]): NodeModel[] {
return tins.map(tin => {
return {
@@ -217,8 +237,8 @@ export function getModel(files: IntegrationFile[]): Model {
const nodes: NodeModel[] = [];
const groups: NodeModel[] = troutes.map(r => {
const children = [r.id]
- children.push(... tins.filter(i => i.routeId === r.routeId && i.type === 'external').map(i => i.id));
- children.push(... tons.filter(i => i.routeId === r.routeId && i.type === 'external').map(i => i.id));
+ children.push(...tins.filter(i => i.routeId === r.routeId && i.type === 'external').map(i => i.id));
+ children.push(...tons.filter(i => i.routeId === r.routeId && i.type === 'external').map(i => i.id));
return {
id: 'group-' + r.routeId,
children: children,
@@ -242,6 +262,7 @@ export function getModel(files: IntegrationFile[]): Model {
edges.push(...getOutgoingEdges(tons));
edges.push(...getRestEdges(trestns, tins));
edges.push(...getInternalEdges(tons, tins));
+ edges.push(...getExternalEdges(tons,tins));
return {nodes: nodes, edges: edges, graph: {id: 'g1', type: 'graph', layout: 'Dagre'}};
}
diff --git a/karavan-space/src/topology/TopologyTab.tsx b/karavan-space/src/topology/TopologyTab.tsx
index 306ca8fb..520bf8d2 100644
--- a/karavan-space/src/topology/TopologyTab.tsx
+++ b/karavan-space/src/topology/TopologyTab.tsx
@@ -68,7 +68,6 @@ export function TopologyTab (props: Props) {
}
const controller = React.useMemo(() => {
- console.log(props.files)
const model = getModel(props.files);
const newController = new Visualization();
newController.registerLayoutFactory((_, graph) => new DagreLayout(graph));