Skip to content
This repository has been archived by the owner on Oct 29, 2022. It is now read-only.

Commit

Permalink
feat: add optional edge types (#20)
Browse files Browse the repository at this point in the history
  • Loading branch information
jonaslagoni authored Sep 28, 2022
1 parent 7566ccd commit 581524c
Show file tree
Hide file tree
Showing 7 changed files with 130 additions and 75 deletions.
2 changes: 1 addition & 1 deletion examples/simple-react/src/SimpleAsyncapi.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ function Asyncapi() {
let node;
if (document !== undefined) {
node = (
<ApplicationView asyncapi={{ document }} />
<ApplicationView asyncapi={{ document }} edgeType={'default'} />
);
} else {
node = <h1>Wait...</h1>;
Expand Down
1 change: 1 addition & 0 deletions examples/simple-react/src/SimpleSystem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ function App() {
<div className="App">
<SystemView
includeControls={true}
edgeType={'smoothstep'}
applications={[
{
application: {
Expand Down
7 changes: 7 additions & 0 deletions library/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,3 +114,10 @@ export interface OutgoingNodeProps {
export interface LayoutProps {
elementsToRender: FlowElement[];
}

export type EdgeType =
| 'smoothstep'
| 'step'
| 'straight'
| 'floating'
| 'default';
142 changes: 85 additions & 57 deletions library/src/visualiser/helpers/collect-nodes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,78 +10,85 @@ import {
ApplicationServerData,
MessageData,
SystemViewData,
EdgeType,
} from '../../types';

export function collectApplicationNodes({
asyncapi,
application,
incomingOperations,
outgoingOperations,
}: ApplicationViewData): Array<FlowElement> {
export function collectApplicationNodes(
{
asyncapi,
application,
incomingOperations,
outgoingOperations,
}: ApplicationViewData,
edgeType: EdgeType = 'smoothstep',
): Array<FlowElement> {
const nodes: Array<FlowElement> = [];

if (asyncapi) {
nodes.push(...collectAsyncAPINodes(asyncapi));
nodes.push(...collectAsyncAPINodes(asyncapi, { edgeType }));
} else if (application) {
nodes.push(...createApplicationNode(application));
}

if (incomingOperations) {
incomingOperations.forEach(op => {
nodes.push(...createIncomingNode(op));
nodes.push(...createIncomingNode(op, edgeType));
});
}
if (outgoingOperations) {
outgoingOperations.forEach(op => {
nodes.push(...createOutgoingNode(op));
nodes.push(...createOutgoingNode(op, edgeType));
});
}

return nodes;
}

export function collectApplicationFocusNodes({
asyncapi,
application,
external,
incomingOperations,
outgoingOperations,
}: ApplicationFocusViewData): Array<FlowElement> {
export function collectApplicationFocusNodes(
{
asyncapi,
application,
external,
incomingOperations,
outgoingOperations,
}: ApplicationFocusViewData,
edgeType: EdgeType = 'smoothstep',
): Array<FlowElement> {
const nodes: Array<FlowElement> = [];
const leadApplicationIncomingChannels: string[] = [];
const leadApplicationOutgoingChannels: string[] = [];

if (asyncapi) {
const createIncomingNodeFn = (data: IncomingNodeData) => {
leadApplicationIncomingChannels.push(data.id);
return createIncomingNode(data);
return createIncomingNode(data, edgeType);
};
const createOutgoingNodeFn = (data: OutgoingNodeData) => {
leadApplicationOutgoingChannels.push(data.id);
return createOutgoingNode(data);
return createOutgoingNode(data, edgeType);
};

nodes.push(
...collectAsyncAPINodes(
asyncapi,
createApplicationNode,
...collectAsyncAPINodes(asyncapi, {
createApplicationNodeFn: createApplicationNode,
createIncomingNodeFn,
createOutgoingNodeFn,
),
edgeType,
}),
);
} else if (application) {
nodes.push(...createApplicationNode(application));
}

if (incomingOperations) {
incomingOperations.forEach(op => {
nodes.push(...createIncomingNode(op));
nodes.push(...createIncomingNode(op, edgeType));
leadApplicationIncomingChannels.push(op.id);
});
}
if (outgoingOperations) {
outgoingOperations.forEach(op => {
nodes.push(...createOutgoingNode(op));
nodes.push(...createOutgoingNode(op, edgeType));
leadApplicationOutgoingChannels.push(op.id);
});
}
Expand All @@ -106,12 +113,12 @@ export function collectApplicationFocusNodes({
external.forEach(externalApp => {
if (externalApp.asyncapi) {
nodes.push(
...collectAsyncAPINodes(
externalApp.asyncapi,
createExternalApplicationNode,
...collectAsyncAPINodes(externalApp.asyncapi, {
createApplicationNodeFn: createExternalApplicationNode,
createIncomingNodeFn,
createOutgoingNodeFn,
),
edgeType,
}),
);
} else if (externalApp.application) {
nodes.push(...createExternalApplicationNode(externalApp.application));
Expand All @@ -129,9 +136,10 @@ export function collectApplicationFocusNodes({
return nodes;
}

export function collectSystemNodes({
applications = [],
}: SystemViewData): Array<FlowElement> {
export function collectSystemNodes(
{ applications = [] }: SystemViewData,
edgeType: EdgeType = 'floating',
): Array<FlowElement> {
const nodes: Array<FlowElement> = [];
const outgoingConnections: { [key: string]: string[] } = {};
const incomingConnections: { [key: string]: string[] } = {};
Expand All @@ -158,12 +166,12 @@ export function collectSystemNodes({

applications.forEach(app => {
if (app.asyncapi) {
collectAsyncAPINodes(
app.asyncapi,
collectAsyncAPINodes(app.asyncapi, {
createApplicationNodeFn,
createOutgoingNodeFn,
createIncomingNodeFn,
);
edgeType,
});
} else if (app.application) {
nodes.push(...createApplicationNode(app.application));
}
Expand All @@ -182,7 +190,7 @@ export function collectSystemNodes({
for (const incomingApp of incomingConnections[uniqueChannel]) {
const edge = {
id: `${appId}-to-${incomingApp}`,
type: 'floating',
type: edgeType,
style: { stroke: 'orange', strokeWidth: 4 },
source: appId,
target: incomingApp,
Expand All @@ -196,11 +204,19 @@ export function collectSystemNodes({
return nodes;
}

export function collectAsyncAPINodes(
function collectAsyncAPINodes(
{ document, topExtended }: AsyncapiApplicationData,
createApplicationNodeFn: typeof createApplicationNode = createApplicationNode,
createIncomingNodeFn: typeof createIncomingNode = createIncomingNode,
createOutgoingNodeFn: typeof createOutgoingNode = createOutgoingNode,
{
createApplicationNodeFn = createApplicationNode,
createIncomingNodeFn = createIncomingNode,
createOutgoingNodeFn = createOutgoingNode,
edgeType = 'floating',
}: {
createApplicationNodeFn?: typeof createApplicationNode;
createIncomingNodeFn?: typeof createIncomingNode;
createOutgoingNodeFn?: typeof createOutgoingNode;
edgeType?: EdgeType;
},
): Array<FlowElement> {
const nodes: Array<FlowElement> = [];
const documentTitle = document.info().title();
Expand All @@ -216,13 +232,16 @@ export function collectAsyncAPINodes(
});

nodes.push(
...createIncomingNodeFn({
id: `incoming_${channelId}`,
channel: channelPath,
description: channel.description() || 'No description',
messages,
forApplication: documentTitle,
}),
...createIncomingNodeFn(
{
id: `incoming_${channelId}`,
channel: channelPath,
description: channel.description() || 'No description',
messages,
forApplication: documentTitle,
},
edgeType,
),
);
} else if (channel.hasSubscribe()) {
const messages: MessageData[] = channel
Expand All @@ -233,13 +252,16 @@ export function collectAsyncAPINodes(
});

nodes.push(
...createOutgoingNodeFn({
id: `outgoing_${channelId}`,
channel: channelPath,
description: channel.description() || 'No description',
messages,
forApplication: documentTitle,
}),
...createOutgoingNodeFn(
{
id: `outgoing_${channelId}`,
channel: channelPath,
description: channel.description() || 'No description',
messages,
forApplication: documentTitle,
},
edgeType,
),
);
}
}
Expand Down Expand Up @@ -323,7 +345,10 @@ export function createExternalApplicationNode(
return [externalOutgoing, externalIncoming];
}

export function createIncomingNode(data: IncomingNodeData): Array<FlowElement> {
export function createIncomingNode(
data: IncomingNodeData,
edgeType: EdgeType,
): Array<FlowElement> {
const appId = data.forApplication || '';
const incomingNode: Node = {
id: data.id,
Expand All @@ -333,7 +358,7 @@ export function createIncomingNode(data: IncomingNodeData): Array<FlowElement> {
};
const connectionEdge: Edge = {
id: `incoming-${appId}-${data.id}`,
type: 'smoothstep',
type: edgeType,
style: { stroke: '#7ee3be', strokeWidth: 4 },
target: appId,
source: data.id,
Expand All @@ -357,7 +382,10 @@ export function createExternalIncomingNode(
] as Edge[];
}

export function createOutgoingNode(data: OutgoingNodeData): Array<FlowElement> {
export function createOutgoingNode(
data: OutgoingNodeData,
edgeType: EdgeType,
): Array<FlowElement> {
const appId = data.forApplication || '';
const outgoingNode: Node = {
id: data.id,
Expand All @@ -367,7 +395,7 @@ export function createOutgoingNode(data: OutgoingNodeData): Array<FlowElement> {
};
const connectionEdge: Edge = {
id: `outgoing-${appId}-${data.id}`,
type: 'smoothstep',
type: edgeType,
style: { stroke: 'orange', strokeWidth: 4 },
source: appId,
target: data.id,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import nodeTypes from '../../components/react-flow-renderer-nodes';
import FloatingEdge from '../../components/react-flow-renderer-nodes/FloatingEdge';
import { collectApplicationFocusNodes } from '../helpers/collect-nodes';

import { ApplicationFocusViewData, LayoutProps } from '../../types';
import { ApplicationFocusViewData, EdgeType, LayoutProps } from '../../types';

const edgeTypes: EdgeTypesType = {
floating: FloatingEdge,
Expand All @@ -23,6 +23,7 @@ export interface ApplicationFocusViewProps extends ApplicationFocusViewData {
) => React.JSXElementConstructor<LayoutProps>;
sideMenu?: () => React.JSXElementConstructor<any>;
includeControls?: boolean;
edgeType?: EdgeType;
}

export const ApplicationFocusView: React.FunctionComponent<ApplicationFocusViewProps> = ({
Expand All @@ -44,15 +45,19 @@ export const ApplicationFocusView: React.FunctionComponent<ApplicationFocusViewP
);
},
includeControls = false,
edgeType = 'smoothstep',
}) => {
const [loaded, setLoaded] = useState(false);
const elements = collectApplicationFocusNodes({
asyncapi,
application,
external,
incomingOperations,
outgoingOperations,
});
const elements = collectApplicationFocusNodes(
{
asyncapi,
application,
external,
incomingOperations,
outgoingOperations,
},
edgeType,
);

const handleLoaded = (reactFlowInstance: any) => {
setLoaded(true);
Expand Down
Loading

0 comments on commit 581524c

Please sign in to comment.