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 c9b523f7 Fix #1309
c9b523f7 is described below
commit c9b523f756f98509b08688c0fca5fb17bc33b710
Author: Marat Gubaidullin <[email protected]>
AuthorDate: Mon Jun 3 17:17:08 2024 -0400
Fix #1309
---
.../webui/src/designer/route/DslConnections.tsx | 2 +-
.../src/main/webui/src/topology/CustomNode.tsx | 2 +-
.../src/main/webui/src/topology/TopologyApi.tsx | 84 +++++++++++++++++-----
.../webui/src/topology/TopologyPropertiesPanel.tsx | 21 +++++-
.../src/main/webui/src/topology/TopologyStore.ts | 15 ++--
.../src/main/webui/src/topology/TopologyTab.tsx | 14 ++--
.../main/webui/src/topology/TopologyToolbar.tsx | 22 +++++-
.../src/main/webui/src/topology/topology.css | 17 ++++-
.../src/designer/route/DslConnections.tsx | 2 +-
karavan-space/src/topology/CustomNode.tsx | 2 +-
karavan-space/src/topology/TopologyApi.tsx | 84 +++++++++++++++++-----
.../src/topology/TopologyPropertiesPanel.tsx | 21 +++++-
karavan-space/src/topology/TopologyStore.ts | 15 ++--
karavan-space/src/topology/TopologyTab.tsx | 14 ++--
karavan-space/src/topology/TopologyToolbar.tsx | 22 +++++-
karavan-space/src/topology/topology.css | 17 ++++-
16 files changed, 274 insertions(+), 80 deletions(-)
diff --git a/karavan-app/src/main/webui/src/designer/route/DslConnections.tsx
b/karavan-app/src/main/webui/src/designer/route/DslConnections.tsx
index 718f60be..f0b0ff7a 100644
--- a/karavan-app/src/main/webui/src/designer/route/DslConnections.tsx
+++ b/karavan-app/src/main/webui/src/designer/route/DslConnections.tsx
@@ -46,7 +46,7 @@ export function DslConnections() {
const integrations = getIntegrations(files);
setTons(prevState => {
const data = new Map<string, string[]>();
- TopologyUtils.findTopologyOutgoingNodes(integrations).forEach(t =>
{
+
TopologyUtils.findTopologyRouteOutgoingNodes(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) || [];
diff --git a/karavan-app/src/main/webui/src/topology/CustomNode.tsx
b/karavan-app/src/main/webui/src/topology/CustomNode.tsx
index d683d04f..88263966 100644
--- a/karavan-app/src/main/webui/src/topology/CustomNode.tsx
+++ b/karavan-app/src/main/webui/src/topology/CustomNode.tsx
@@ -24,7 +24,7 @@ import {CamelUi} from "../designer/utils/CamelUi";
import './topology.css';
function getIcon(data: any) {
- if (['route', 'rest'].includes(data.icon)) {
+ if (['route', 'rest', 'routeConfiguration'].includes(data.icon)) {
return (
<g transform={`translate(14, 14)`}>
{getDesignerIcon(data.icon)}
diff --git a/karavan-app/src/main/webui/src/topology/TopologyApi.tsx
b/karavan-app/src/main/webui/src/topology/TopologyApi.tsx
index a640d508..d24b38f8 100644
--- a/karavan-app/src/main/webui/src/topology/TopologyApi.tsx
+++ b/karavan-app/src/main/webui/src/topology/TopologyApi.tsx
@@ -26,20 +26,21 @@ import {
NodeModel,
NodeShape,
NodeStatus,
- withPanZoom, withSelection
+ withPanZoom,
+ withSelection
} from '@patternfly/react-topology';
import CustomNode from "./CustomNode";
-import {Integration} from "karavan-core/lib/model/IntegrationDefinition";
+import {Integration, IntegrationFile} from
"karavan-core/lib/model/IntegrationDefinition";
import {CamelDefinitionYaml} from "karavan-core/lib/api/CamelDefinitionYaml";
import {TopologyUtils} from "karavan-core/lib/api/TopologyUtils";
import {
TopologyIncomingNode,
TopologyOutgoingNode,
TopologyRestNode,
+ TopologyRouteConfigurationNode,
TopologyRouteNode
} from "karavan-core/lib/model/TopologyDefinition";
import CustomEdge from "./CustomEdge";
-import {IntegrationFile} from "karavan-core/lib/model/IntegrationDefinition";
import CustomGroup from "./CustomGroup";
const NODE_DIAMETER = 60;
@@ -94,6 +95,28 @@ export function getRoutes(tins: TopologyRouteNode[]):
NodeModel[] {
return node;
});
}
+export function getRouteConfigurations(trcs:
TopologyRouteConfigurationNode[]): NodeModel[] {
+ return trcs.map(tin => {
+ const node: NodeModel = {
+ id: tin.id,
+ type: 'node',
+ label: tin.title,
+ width: NODE_DIAMETER,
+ height: NODE_DIAMETER,
+ shape: NodeShape.rect,
+ status: NodeStatus.default,
+ data: {
+ isAlternate: false,
+ type: 'routeConfiguration',
+ icon: 'routeConfiguration',
+ step: tin.routeConfiguration,
+ routeConfigurationId: tin.routeConfigurationId,
+ fileName: tin.fileName,
+ }
+ }
+ return node;
+ });
+}
export function getOutgoingNodes(tons: TopologyOutgoingNode[]): NodeModel[] {
return tons.filter(tin => tin.type === 'external').map(tin => {
@@ -227,41 +250,64 @@ export function getInternalEdges(tons:
TopologyOutgoingNode[], tins: TopologyInc
return result;
}
-export function getModel(files: IntegrationFile[]): Model {
+export function getModel(files: IntegrationFile[], grouping?: boolean): Model {
const integrations = getIntegrations(files);
const tins = TopologyUtils.findTopologyIncomingNodes(integrations);
const troutes = TopologyUtils.findTopologyRouteNodes(integrations);
- const tons = TopologyUtils.findTopologyOutgoingNodes(integrations);
+ const tons = TopologyUtils.findTopologyRouteOutgoingNodes(integrations);
const trestns = TopologyUtils.findTopologyRestNodes(integrations);
+ const trcs =
TopologyUtils.findTopologyRouteConfigurationNodes(integrations);
+ const trcons =
TopologyUtils.findTopologyRouteConfigurationOutgoingNodes(integrations);
+
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));
- return {
- id: 'group-' + r.routeId,
- children: children,
- type: 'group',
- group: true,
- label: r.title,
- style: {
- padding: 40
- }
+ const groups: NodeModel[] = [];
+
+ const children1 = []
+ 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: 10,
+ strokeWidth: "2px",
+ }
+ })
+
+ 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: 10,
+ strokeWidth: "2px"
}
})
nodes.push(...getRestNodes(trestns))
nodes.push(...getIncomingNodes(tins))
nodes.push(...getRoutes(troutes))
+ nodes.push(...getRouteConfigurations(trcs))
nodes.push(...getOutgoingNodes(tons))
- // nodes.push(...groups)
+ 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));
return {nodes: nodes, edges: edges, graph: {id: 'g1', type: 'graph',
layout: 'Dagre'}};
diff --git
a/karavan-app/src/main/webui/src/topology/TopologyPropertiesPanel.tsx
b/karavan-app/src/main/webui/src/topology/TopologyPropertiesPanel.tsx
index 27ef71b5..a32d6969 100644
--- a/karavan-app/src/main/webui/src/topology/TopologyPropertiesPanel.tsx
+++ b/karavan-app/src/main/webui/src/topology/TopologyPropertiesPanel.tsx
@@ -48,6 +48,14 @@ export function TopologyPropertiesPanel(props: Props) {
return false;
}
+ function isRouteConfiguration() {
+ return (nodeData && nodeData.type === 'routeConfiguration');
+ }
+
+ function isRest() {
+ return (nodeData && nodeData.type === 'rest');
+ }
+
function isKamelet() {
if (nodeData && nodeData.type === 'step') {
const uri: string = nodeData?.step?.uri || '';
@@ -70,7 +78,16 @@ export function TopologyPropertiesPanel(props: Props) {
}
function getTitle () {
- return isRoute() ? "Route" : (isKamelet() ? "Kamelet" : "Component");
+ if (isRoute()) {
+ return "Route";
+ } else if (isKamelet()) {
+ return "Kamelet";
+ } else if (isRouteConfiguration()) {
+ return "Route Configuration";
+ } else if (isRest()) {
+ return "REST";
+ }
+ return "Component";
}
function getHeader() {
@@ -118,7 +135,7 @@ export function TopologyPropertiesPanel(props: Props) {
return (
<TopologySideBar
className="topology-sidebar"
- show={selectedIds.length > 0}
+ show={selectedIds.length > 0 && nodeData}
header={getHeader()}
>
<DslProperties designerType={'routes'}/>
diff --git a/karavan-app/src/main/webui/src/topology/TopologyStore.ts
b/karavan-app/src/main/webui/src/topology/TopologyStore.ts
index 517e2794..514f1b37 100644
--- a/karavan-app/src/main/webui/src/topology/TopologyStore.ts
+++ b/karavan-app/src/main/webui/src/topology/TopologyStore.ts
@@ -28,6 +28,8 @@ interface TopologyState {
setRanker: (ranker: string) => void
nodeData: any
setNodeData: (nodeData: any) => void
+ showGroups?: boolean
+ setShowGroups: (showGroups: boolean) => void
}
export const useTopologyStore = createWithEqualityFn<TopologyState>((set) => ({
@@ -50,8 +52,13 @@ export const useTopologyStore =
createWithEqualityFn<TopologyState>((set) => ({
},
nodeData: undefined,
setNodeData: (nodeData: any) => {
- set((state: TopologyState) => {
- return {nodeData: nodeData};
- });
-},
+ set((state: TopologyState) => {
+ return {nodeData: nodeData};
+ });
+ },
+ setShowGroups: (showGroups: boolean) => {
+ set((state: TopologyState) => {
+ return {showGroups: showGroups};
+ });
+ },
}), shallow)
diff --git a/karavan-app/src/main/webui/src/topology/TopologyTab.tsx
b/karavan-app/src/main/webui/src/topology/TopologyTab.tsx
index e9587444..cc189e29 100644
--- a/karavan-app/src/main/webui/src/topology/TopologyTab.tsx
+++ b/karavan-app/src/main/webui/src/topology/TopologyTab.tsx
@@ -49,8 +49,8 @@ interface Props {
export function TopologyTab(props: Props) {
- const [selectedIds, setSelectedIds, setFileName, ranker, setRanker,
setNodeData] = useTopologyStore((s) =>
- [s.selectedIds, s.setSelectedIds, s.setFileName, s.ranker,
s.setRanker, s.setNodeData], shallow);
+ const [selectedIds, setSelectedIds, setFileName, ranker, setRanker,
setNodeData, showGroups] = useTopologyStore((s) =>
+ [s.selectedIds, s.setSelectedIds, s.setFileName, s.ranker,
s.setRanker, s.setNodeData, s.showGroups], shallow);
const [setSelectedStep] = useDesignerStore((s) => [s.setSelectedStep],
shallow)
function setTopologySelected(model: Model, ids: string []) {
@@ -60,8 +60,8 @@ export function TopologyTab(props: Props) {
if (node && node.length > 0) {
const data = node[0].data;
setNodeData(data);
- setFileName(data.fileName)
- if (data.step) {
+ if (data && data.step) {
+ setFileName(data.fileName)
setSelectedStep(data.step)
} else {
setSelectedStep(undefined);
@@ -72,7 +72,7 @@ export function TopologyTab(props: Props) {
}
const controller = React.useMemo(() => {
- const model = getModel(props.files);
+ const model = getModel(props.files, showGroups);
const newController = new Visualization();
newController.registerLayoutFactory((_, graph) =>
new DagreLayout(graph, {
@@ -99,9 +99,9 @@ export function TopologyTab(props: Props) {
React.useEffect(() => {
setSelectedIds([])
- const model = getModel(props.files);
+ const model = getModel(props.files, showGroups);
controller.fromModel(model, false);
- }, [ranker, controller, setSelectedIds, props.files]);
+ }, [ranker, controller, setSelectedIds, props.files, showGroups]);
const controlButtons = React.useMemo(() => {
// const customButtons = [
diff --git a/karavan-app/src/main/webui/src/topology/TopologyToolbar.tsx
b/karavan-app/src/main/webui/src/topology/TopologyToolbar.tsx
index 5dbe4949..0de61fee 100644
--- a/karavan-app/src/main/webui/src/topology/TopologyToolbar.tsx
+++ b/karavan-app/src/main/webui/src/topology/TopologyToolbar.tsx
@@ -17,10 +17,12 @@
import * as React from 'react';
import {
- Button, ToolbarContent,
+ Button, Switch, ToolbarContent,
ToolbarItem, Tooltip
} from '@patternfly/react-core';
import PlusIcon from "@patternfly/react-icons/dist/esm/icons/plus-icon";
+import {useTopologyStore} from "./TopologyStore";
+import {shallow} from "zustand/shallow";
interface Props {
onClickAddRoute: () => void
@@ -31,8 +33,22 @@ interface Props {
export function TopologyToolbar (props: Props) {
+ const [showGroups, setShowGroups] = useTopologyStore((s) =>
+ [s.showGroups, s.setShowGroups], shallow);
+
return (
- <ToolbarContent>
+ <div className='topology-toolbar'>
+ <ToolbarItem className="group-switch">
+ <Tooltip content={"Show Consumer and Producer Groups"}
position={"bottom-start"}>
+ <Switch
+ id="reversed-switch"
+ label="Groups"
+ isChecked={showGroups}
+ onChange={(_, checked) => setShowGroups(checked)}
+ isReversed
+ />
+ </Tooltip>
+ </ToolbarItem>
<ToolbarItem align={{default:"alignRight"}}>
<Tooltip content={"Add Integration Route"} position={"bottom"}>
<Button className="dev-action-button" size="sm"
@@ -77,6 +93,6 @@ export function TopologyToolbar (props: Props) {
</Button>
</Tooltip>
</ToolbarItem>
- </ToolbarContent>
+ </div>
)
}
\ No newline at end of file
diff --git a/karavan-app/src/main/webui/src/topology/topology.css
b/karavan-app/src/main/webui/src/topology/topology.css
index 24fe7679..7d21c7b2 100644
--- a/karavan-app/src/main/webui/src/topology/topology.css
+++ b/karavan-app/src/main/webui/src/topology/topology.css
@@ -15,17 +15,28 @@
* limitations under the License.
*/
+.karavan .topology-panel .topology-toolbar {
+ width: 100%;
+ display: flex;
+ flex-direction: row;
+}
+
+.karavan .topology-panel .topology-toolbar .group-switch {
+ flex-grow: 4;
+ margin-top: auto;
+ margin-bottom: auto;
+ margin-left: 6px;
+}
+
.karavan .topology-panel .pf-v5-c-toolbar {
padding: 0;
- display: flex;
- flex-direction: column;
- align-items: flex-end;
height: fit-content;
row-gap: 0;
}
.karavan .topology-panel .pf-v5-c-toolbar .pf-v5-c-toolbar__content {
padding: 0 6px 0 0;
+ width: 100%;
}
.karavan .topology-panel .pf-v5-c-toolbar .pf-v5-c-toolbar__content-section {
diff --git a/karavan-space/src/designer/route/DslConnections.tsx
b/karavan-space/src/designer/route/DslConnections.tsx
index 718f60be..f0b0ff7a 100644
--- a/karavan-space/src/designer/route/DslConnections.tsx
+++ b/karavan-space/src/designer/route/DslConnections.tsx
@@ -46,7 +46,7 @@ export function DslConnections() {
const integrations = getIntegrations(files);
setTons(prevState => {
const data = new Map<string, string[]>();
- TopologyUtils.findTopologyOutgoingNodes(integrations).forEach(t =>
{
+
TopologyUtils.findTopologyRouteOutgoingNodes(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) || [];
diff --git a/karavan-space/src/topology/CustomNode.tsx
b/karavan-space/src/topology/CustomNode.tsx
index d683d04f..88263966 100644
--- a/karavan-space/src/topology/CustomNode.tsx
+++ b/karavan-space/src/topology/CustomNode.tsx
@@ -24,7 +24,7 @@ import {CamelUi} from "../designer/utils/CamelUi";
import './topology.css';
function getIcon(data: any) {
- if (['route', 'rest'].includes(data.icon)) {
+ if (['route', 'rest', 'routeConfiguration'].includes(data.icon)) {
return (
<g transform={`translate(14, 14)`}>
{getDesignerIcon(data.icon)}
diff --git a/karavan-space/src/topology/TopologyApi.tsx
b/karavan-space/src/topology/TopologyApi.tsx
index a640d508..d24b38f8 100644
--- a/karavan-space/src/topology/TopologyApi.tsx
+++ b/karavan-space/src/topology/TopologyApi.tsx
@@ -26,20 +26,21 @@ import {
NodeModel,
NodeShape,
NodeStatus,
- withPanZoom, withSelection
+ withPanZoom,
+ withSelection
} from '@patternfly/react-topology';
import CustomNode from "./CustomNode";
-import {Integration} from "karavan-core/lib/model/IntegrationDefinition";
+import {Integration, IntegrationFile} from
"karavan-core/lib/model/IntegrationDefinition";
import {CamelDefinitionYaml} from "karavan-core/lib/api/CamelDefinitionYaml";
import {TopologyUtils} from "karavan-core/lib/api/TopologyUtils";
import {
TopologyIncomingNode,
TopologyOutgoingNode,
TopologyRestNode,
+ TopologyRouteConfigurationNode,
TopologyRouteNode
} from "karavan-core/lib/model/TopologyDefinition";
import CustomEdge from "./CustomEdge";
-import {IntegrationFile} from "karavan-core/lib/model/IntegrationDefinition";
import CustomGroup from "./CustomGroup";
const NODE_DIAMETER = 60;
@@ -94,6 +95,28 @@ export function getRoutes(tins: TopologyRouteNode[]):
NodeModel[] {
return node;
});
}
+export function getRouteConfigurations(trcs:
TopologyRouteConfigurationNode[]): NodeModel[] {
+ return trcs.map(tin => {
+ const node: NodeModel = {
+ id: tin.id,
+ type: 'node',
+ label: tin.title,
+ width: NODE_DIAMETER,
+ height: NODE_DIAMETER,
+ shape: NodeShape.rect,
+ status: NodeStatus.default,
+ data: {
+ isAlternate: false,
+ type: 'routeConfiguration',
+ icon: 'routeConfiguration',
+ step: tin.routeConfiguration,
+ routeConfigurationId: tin.routeConfigurationId,
+ fileName: tin.fileName,
+ }
+ }
+ return node;
+ });
+}
export function getOutgoingNodes(tons: TopologyOutgoingNode[]): NodeModel[] {
return tons.filter(tin => tin.type === 'external').map(tin => {
@@ -227,41 +250,64 @@ export function getInternalEdges(tons:
TopologyOutgoingNode[], tins: TopologyInc
return result;
}
-export function getModel(files: IntegrationFile[]): Model {
+export function getModel(files: IntegrationFile[], grouping?: boolean): Model {
const integrations = getIntegrations(files);
const tins = TopologyUtils.findTopologyIncomingNodes(integrations);
const troutes = TopologyUtils.findTopologyRouteNodes(integrations);
- const tons = TopologyUtils.findTopologyOutgoingNodes(integrations);
+ const tons = TopologyUtils.findTopologyRouteOutgoingNodes(integrations);
const trestns = TopologyUtils.findTopologyRestNodes(integrations);
+ const trcs =
TopologyUtils.findTopologyRouteConfigurationNodes(integrations);
+ const trcons =
TopologyUtils.findTopologyRouteConfigurationOutgoingNodes(integrations);
+
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));
- return {
- id: 'group-' + r.routeId,
- children: children,
- type: 'group',
- group: true,
- label: r.title,
- style: {
- padding: 40
- }
+ const groups: NodeModel[] = [];
+
+ const children1 = []
+ 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: 10,
+ strokeWidth: "2px",
+ }
+ })
+
+ 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: 10,
+ strokeWidth: "2px"
}
})
nodes.push(...getRestNodes(trestns))
nodes.push(...getIncomingNodes(tins))
nodes.push(...getRoutes(troutes))
+ nodes.push(...getRouteConfigurations(trcs))
nodes.push(...getOutgoingNodes(tons))
- // nodes.push(...groups)
+ 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));
return {nodes: nodes, edges: edges, graph: {id: 'g1', type: 'graph',
layout: 'Dagre'}};
diff --git a/karavan-space/src/topology/TopologyPropertiesPanel.tsx
b/karavan-space/src/topology/TopologyPropertiesPanel.tsx
index 27ef71b5..a32d6969 100644
--- a/karavan-space/src/topology/TopologyPropertiesPanel.tsx
+++ b/karavan-space/src/topology/TopologyPropertiesPanel.tsx
@@ -48,6 +48,14 @@ export function TopologyPropertiesPanel(props: Props) {
return false;
}
+ function isRouteConfiguration() {
+ return (nodeData && nodeData.type === 'routeConfiguration');
+ }
+
+ function isRest() {
+ return (nodeData && nodeData.type === 'rest');
+ }
+
function isKamelet() {
if (nodeData && nodeData.type === 'step') {
const uri: string = nodeData?.step?.uri || '';
@@ -70,7 +78,16 @@ export function TopologyPropertiesPanel(props: Props) {
}
function getTitle () {
- return isRoute() ? "Route" : (isKamelet() ? "Kamelet" : "Component");
+ if (isRoute()) {
+ return "Route";
+ } else if (isKamelet()) {
+ return "Kamelet";
+ } else if (isRouteConfiguration()) {
+ return "Route Configuration";
+ } else if (isRest()) {
+ return "REST";
+ }
+ return "Component";
}
function getHeader() {
@@ -118,7 +135,7 @@ export function TopologyPropertiesPanel(props: Props) {
return (
<TopologySideBar
className="topology-sidebar"
- show={selectedIds.length > 0}
+ show={selectedIds.length > 0 && nodeData}
header={getHeader()}
>
<DslProperties designerType={'routes'}/>
diff --git a/karavan-space/src/topology/TopologyStore.ts
b/karavan-space/src/topology/TopologyStore.ts
index 517e2794..514f1b37 100644
--- a/karavan-space/src/topology/TopologyStore.ts
+++ b/karavan-space/src/topology/TopologyStore.ts
@@ -28,6 +28,8 @@ interface TopologyState {
setRanker: (ranker: string) => void
nodeData: any
setNodeData: (nodeData: any) => void
+ showGroups?: boolean
+ setShowGroups: (showGroups: boolean) => void
}
export const useTopologyStore = createWithEqualityFn<TopologyState>((set) => ({
@@ -50,8 +52,13 @@ export const useTopologyStore =
createWithEqualityFn<TopologyState>((set) => ({
},
nodeData: undefined,
setNodeData: (nodeData: any) => {
- set((state: TopologyState) => {
- return {nodeData: nodeData};
- });
-},
+ set((state: TopologyState) => {
+ return {nodeData: nodeData};
+ });
+ },
+ setShowGroups: (showGroups: boolean) => {
+ set((state: TopologyState) => {
+ return {showGroups: showGroups};
+ });
+ },
}), shallow)
diff --git a/karavan-space/src/topology/TopologyTab.tsx
b/karavan-space/src/topology/TopologyTab.tsx
index e9587444..cc189e29 100644
--- a/karavan-space/src/topology/TopologyTab.tsx
+++ b/karavan-space/src/topology/TopologyTab.tsx
@@ -49,8 +49,8 @@ interface Props {
export function TopologyTab(props: Props) {
- const [selectedIds, setSelectedIds, setFileName, ranker, setRanker,
setNodeData] = useTopologyStore((s) =>
- [s.selectedIds, s.setSelectedIds, s.setFileName, s.ranker,
s.setRanker, s.setNodeData], shallow);
+ const [selectedIds, setSelectedIds, setFileName, ranker, setRanker,
setNodeData, showGroups] = useTopologyStore((s) =>
+ [s.selectedIds, s.setSelectedIds, s.setFileName, s.ranker,
s.setRanker, s.setNodeData, s.showGroups], shallow);
const [setSelectedStep] = useDesignerStore((s) => [s.setSelectedStep],
shallow)
function setTopologySelected(model: Model, ids: string []) {
@@ -60,8 +60,8 @@ export function TopologyTab(props: Props) {
if (node && node.length > 0) {
const data = node[0].data;
setNodeData(data);
- setFileName(data.fileName)
- if (data.step) {
+ if (data && data.step) {
+ setFileName(data.fileName)
setSelectedStep(data.step)
} else {
setSelectedStep(undefined);
@@ -72,7 +72,7 @@ export function TopologyTab(props: Props) {
}
const controller = React.useMemo(() => {
- const model = getModel(props.files);
+ const model = getModel(props.files, showGroups);
const newController = new Visualization();
newController.registerLayoutFactory((_, graph) =>
new DagreLayout(graph, {
@@ -99,9 +99,9 @@ export function TopologyTab(props: Props) {
React.useEffect(() => {
setSelectedIds([])
- const model = getModel(props.files);
+ const model = getModel(props.files, showGroups);
controller.fromModel(model, false);
- }, [ranker, controller, setSelectedIds, props.files]);
+ }, [ranker, controller, setSelectedIds, props.files, showGroups]);
const controlButtons = React.useMemo(() => {
// const customButtons = [
diff --git a/karavan-space/src/topology/TopologyToolbar.tsx
b/karavan-space/src/topology/TopologyToolbar.tsx
index 5dbe4949..0de61fee 100644
--- a/karavan-space/src/topology/TopologyToolbar.tsx
+++ b/karavan-space/src/topology/TopologyToolbar.tsx
@@ -17,10 +17,12 @@
import * as React from 'react';
import {
- Button, ToolbarContent,
+ Button, Switch, ToolbarContent,
ToolbarItem, Tooltip
} from '@patternfly/react-core';
import PlusIcon from "@patternfly/react-icons/dist/esm/icons/plus-icon";
+import {useTopologyStore} from "./TopologyStore";
+import {shallow} from "zustand/shallow";
interface Props {
onClickAddRoute: () => void
@@ -31,8 +33,22 @@ interface Props {
export function TopologyToolbar (props: Props) {
+ const [showGroups, setShowGroups] = useTopologyStore((s) =>
+ [s.showGroups, s.setShowGroups], shallow);
+
return (
- <ToolbarContent>
+ <div className='topology-toolbar'>
+ <ToolbarItem className="group-switch">
+ <Tooltip content={"Show Consumer and Producer Groups"}
position={"bottom-start"}>
+ <Switch
+ id="reversed-switch"
+ label="Groups"
+ isChecked={showGroups}
+ onChange={(_, checked) => setShowGroups(checked)}
+ isReversed
+ />
+ </Tooltip>
+ </ToolbarItem>
<ToolbarItem align={{default:"alignRight"}}>
<Tooltip content={"Add Integration Route"} position={"bottom"}>
<Button className="dev-action-button" size="sm"
@@ -77,6 +93,6 @@ export function TopologyToolbar (props: Props) {
</Button>
</Tooltip>
</ToolbarItem>
- </ToolbarContent>
+ </div>
)
}
\ No newline at end of file
diff --git a/karavan-space/src/topology/topology.css
b/karavan-space/src/topology/topology.css
index 24fe7679..7d21c7b2 100644
--- a/karavan-space/src/topology/topology.css
+++ b/karavan-space/src/topology/topology.css
@@ -15,17 +15,28 @@
* limitations under the License.
*/
+.karavan .topology-panel .topology-toolbar {
+ width: 100%;
+ display: flex;
+ flex-direction: row;
+}
+
+.karavan .topology-panel .topology-toolbar .group-switch {
+ flex-grow: 4;
+ margin-top: auto;
+ margin-bottom: auto;
+ margin-left: 6px;
+}
+
.karavan .topology-panel .pf-v5-c-toolbar {
padding: 0;
- display: flex;
- flex-direction: column;
- align-items: flex-end;
height: fit-content;
row-gap: 0;
}
.karavan .topology-panel .pf-v5-c-toolbar .pf-v5-c-toolbar__content {
padding: 0 6px 0 0;
+ width: 100%;
}
.karavan .topology-panel .pf-v5-c-toolbar .pf-v5-c-toolbar__content-section {