Skip to content

Commit

Permalink
Merge branch 'patternfly:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
wise-king-sullyman authored Mar 18, 2024
2 parents 654af73 + 0b25c55 commit 209b905
Show file tree
Hide file tree
Showing 24 changed files with 1,112 additions and 127 deletions.
4 changes: 3 additions & 1 deletion packages/demo-app-ts/src/Demo.css
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,9 @@
fill: var(--pf-v5-global--palette--light-blue-200);
}

.pf-v5-c-page__main-section#\/topology-demo-page-section, .pf-v5-c-page__main-section#\/topology-pipelines-demo-page-section {
.pf-v5-c-page__main-section#\/topology-demo-page-section,
.pf-v5-c-page__main-section#\/topology-pipelines-demo-page-section,
.pf-v5-c-page__main-section#\/topology-pipelines-groups-demo-page-section {
--pf-v5-c-page__main-section--PaddingTop: 0;
--pf-v5-c-page__main-section--PaddingRight: 0;
--pf-v5-c-page__main-section--PaddingLeft: 0;
Expand Down
26 changes: 22 additions & 4 deletions packages/demo-app-ts/src/Demos.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { TopologyPipelineDemo } from './demos/pipelinesDemo/TopologyPipelineDemo';
import { PipelineTasksDemo } from './demos/pipelinesDemo/PipelineTasksDemo';
import { PipelineLayoutDemo } from './demos/pipelinesDemo/PipelineLayoutDemo';
import { PipelineGroupsDemo } from './demos/pipelineGroupsDemo/PipelineGroupsDemo';
import { Basics } from './demos/Basics';
import { StyleEdges, StyleGroups, StyleLabels, StyleNodes } from './demos/stylesDemo/Styles';
import { Selection } from './demos/Selection';
Expand Down Expand Up @@ -36,9 +38,25 @@ export const Demos: DemoInterface[] = [
isDefault: true,
},
{
id: 'topology-pipelines-demo',
name: 'Topology Pipelines',
componentType: TopologyPipelineDemo
id: 'pipelines',
name: 'Pipelines',
demos: [
{
id: 'pipelines-tasks-demo',
name: 'Task Nodes',
componentType: PipelineTasksDemo
},
{
id: 'pipelines-layout-demo',
name: 'Pipeline Layout',
componentType: PipelineLayoutDemo
},
{
id: 'pipelines-groups-layout-demo',
name: 'Pipeline Groups Layout',
componentType: PipelineGroupsDemo,
},
]
},
{
id: 'status-connectors',
Expand Down
29 changes: 2 additions & 27 deletions packages/demo-app-ts/src/demos/CollapsibleGroups.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,6 @@ import * as React from 'react';
import { action } from 'mobx';
import {
TopologyView,
TopologyControlBar,
createTopologyControlButtons,
defaultControlButtonsOptions,
EdgeModel,
Model,
ModelKind,
Expand All @@ -28,6 +25,7 @@ import GroupHull from '../components/GroupHull';
import Group from '../components/DemoDefaultGroup';
import DemoDefaultNode from '../components/DemoDefaultNode';
import defaultComponentFactory from '../components/defaultComponentFactory';
import DemoControlBar from './DemoControlBar';

const getModel = (collapseTypes: string[] = []): Model => {
// create nodes from data
Expand Down Expand Up @@ -209,30 +207,7 @@ const TopologyViewComponent: React.FunctionComponent<TopologyViewComponentProps>
}, [vis, collapseBlue, collapseLightBlue, collapseCyan, collapseOrange, collapsePink]);

return (
<TopologyView
controlBar={
<TopologyControlBar
controlButtons={createTopologyControlButtons({
...defaultControlButtonsOptions,
zoomInCallback: action(() => {
vis.getGraph().scaleBy(4 / 3);
}),
zoomOutCallback: action(() => {
vis.getGraph().scaleBy(0.75);
}),
fitToScreenCallback: action(() => {
vis.getGraph().fit(80);
}),
resetViewCallback: action(() => {
vis.getGraph().reset();
vis.getGraph().layout();
}),
legend: false
})}
/>
}
viewToolbar={viewToolbar}
>
<TopologyView controlBar={<DemoControlBar />} viewToolbar={viewToolbar}>
<VisualizationSurface state={{ selectedIds }} />
</TopologyView>
);
Expand Down
36 changes: 36 additions & 0 deletions packages/demo-app-ts/src/demos/DemoControlBar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import React from 'react';
import {
createTopologyControlButtons,
defaultControlButtonsOptions,
TopologyControlBar,
useVisualizationController,
action,
} from '@patternfly/react-topology';

const DemoControlBar: React.FC = () => {
const controller = useVisualizationController();

return (
<TopologyControlBar
controlButtons={createTopologyControlButtons({
...defaultControlButtonsOptions,
zoomInCallback: action(() => {
controller.getGraph().scaleBy(4 / 3);
}),
zoomOutCallback: action(() => {
controller.getGraph().scaleBy(0.75);
}),
fitToScreenCallback: action(() => {
controller.getGraph().fit(80);
}),
resetViewCallback: action(() => {
controller.getGraph().reset();
controller.getGraph().layout();
}),
legend: false
})}
/>
);
};

export default DemoControlBar;
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import * as React from 'react';
import { observer } from 'mobx-react';
import {
AnchorEnd,
DagreLayoutOptions,
DefaultGroup,
GraphElement,
isNode,
LabelPosition,
Node,
TOP_TO_BOTTOM,
useAnchor,
} from '@patternfly/react-topology';
import TaskGroupSourceAnchor from './TaskGroupSourceAnchor';
import TaskGroupTargetAnchor from './TaskGroupTargetAnchor';

interface DemoTaskNodeProps {
element: GraphElement;
}

const DemoTaskGroup: React.FunctionComponent<DemoTaskNodeProps> = ({ element, ...rest }) => {
const verticalLayout = (element.getGraph().getLayoutOptions?.() as DagreLayoutOptions)?.rankdir === TOP_TO_BOTTOM;

useAnchor(
React.useCallback((node: Node) =>new TaskGroupSourceAnchor(node, verticalLayout), [verticalLayout]),
AnchorEnd.source
);
useAnchor(
React.useCallback((node: Node) => new TaskGroupTargetAnchor(node, verticalLayout),[verticalLayout]),
AnchorEnd.target
);
if (!isNode(element)) {
return null;
}
return (
<DefaultGroup hulledOutline={false} labelPosition={verticalLayout ? LabelPosition.top : LabelPosition.bottom} element={element as Node} {...rest} />
);
};

export default observer(DemoTaskGroup);
40 changes: 40 additions & 0 deletions packages/demo-app-ts/src/demos/pipelineGroupsDemo/DemoTaskNode.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import * as React from 'react';
import { observer } from 'mobx-react';
import {
DEFAULT_LAYER,
GraphElement,
Layer,
ScaleDetailsLevel,
TaskNode,
TOP_LAYER,
useHover,
WithContextMenuProps,
WithSelectionProps
} from '@patternfly/react-topology';

type DemoTaskNodeProps = {
element: GraphElement;
} & WithContextMenuProps & WithSelectionProps;

const DemoTaskNode: React.FunctionComponent<DemoTaskNodeProps> = ({ element, ...rest }) => {
const data = element.getData();
const [hover, hoverRef] = useHover();
const detailsLevel = element.getGraph().getDetailsLevel();

return (
<Layer id={detailsLevel !== ScaleDetailsLevel.high && hover ? TOP_LAYER : DEFAULT_LAYER}>
<g ref={hoverRef}>
<TaskNode
element={element}
scaleNode={hover && detailsLevel !== ScaleDetailsLevel.high}
showStatusState
status={data.status}
hideDetailsAtMedium
{...rest}
/>
</g>
</Layer>
);
};

export default observer(DemoTaskNode);
36 changes: 36 additions & 0 deletions packages/demo-app-ts/src/demos/pipelineGroupsDemo/OptionsBar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import React from 'react';
import { Radio, Text, ToolbarItem } from '@patternfly/react-core';
import { observer } from '@patternfly/react-topology';
import { PipelineGroupsDemoContext } from './PipelineGroupsDemoContext';

const OptionsBar: React.FC = observer(() => {
const pipelineOptions = React.useContext(PipelineGroupsDemoContext);

return (
<>
<ToolbarItem>
<Text className="pf-u-mr-sm">Layout:</Text>
</ToolbarItem>
<ToolbarItem>
<Radio
id="horizontal-layout-radio"
name="horizontalLayout"
isChecked={!pipelineOptions.verticalLayout}
onChange={() => pipelineOptions.setVerticalLayout(false)}
label="Horizontal"
/>
</ToolbarItem>
<ToolbarItem>
<Radio
id="vertical-layout-radio"
name="verticalLayout"
isChecked={pipelineOptions.verticalLayout}
onChange={() => pipelineOptions.setVerticalLayout(true)}
label="Vertical"
/>
</ToolbarItem>
</>
);
});

export default OptionsBar;
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import React from 'react';
import {
Graph,
Layout,
PipelineDagreGroupsLayout,
Visualization,
VisualizationProvider,
useEventListener,
SelectionEventListener,
SELECTION_EVENT,
TopologyView,
VisualizationSurface,
getEdgesFromNodes,
DEFAULT_SPACER_NODE_TYPE,
observer,
NODE_SEPARATION_HORIZONTAL,
NODE_SEPARATION_VERTICAL,
LEFT_TO_RIGHT,
TOP_TO_BOTTOM,
PipelineNodeModel,
useVisualizationController,
} from '@patternfly/react-topology';
import pipelineGroupsComponentFactory from './pipelineGroupsComponentFactory';
import { createDemoPipelineGroupsNodes } from './createDemoPipelineGroupsNodes';
import { PipelineGroupsDemoContext, PipelineGroupsDemoModel } from './PipelineGroupsDemoContext';
import OptionsBar from './OptionsBar';
import DemoControlBar from '../DemoControlBar';

const TopologyPipelineGroups: React.FC<{ nodes: PipelineNodeModel[] }> = observer(({ nodes }) => {
const controller = useVisualizationController();
const options = React.useContext(PipelineGroupsDemoContext);
const [selectedIds, setSelectedIds] = React.useState<string[]>();

useEventListener<SelectionEventListener>(SELECTION_EVENT, ids => {
setSelectedIds(ids);
});

React.useEffect(() => {
const edges = getEdgesFromNodes(nodes, DEFAULT_SPACER_NODE_TYPE, 'edge', 'edge');
controller.fromModel(
{
graph: {
id: 'g1',
type: 'graph',
x: 25,
y: 25,
layout: options.verticalLayout ? TOP_TO_BOTTOM : LEFT_TO_RIGHT
},
nodes,
edges,
},
false
);
}, [controller, nodes, options.verticalLayout]);

return (
<TopologyView contextToolbar={<OptionsBar />} controlBar={<DemoControlBar />}>
<VisualizationSurface state={{ selectedIds }} />
</TopologyView>
);
});

TopologyPipelineGroups.displayName = 'TopologyPipelineLayout';

export const PipelineGroupsDemo = observer(() => {
const controller = new Visualization();
controller.registerComponentFactory(pipelineGroupsComponentFactory);
controller.registerLayoutFactory(
(type: string, graph: Graph): Layout | undefined =>
new PipelineDagreGroupsLayout(graph, {
nodesep: NODE_SEPARATION_HORIZONTAL,
ranksep: NODE_SEPARATION_VERTICAL + 40,
rankdir: type,
ignoreGroups: true,
})
);
const nodes = createDemoPipelineGroupsNodes();
return (
<div className="pf-ri__topology-demo">
<VisualizationProvider controller={controller}>
<PipelineGroupsDemoContext.Provider value={new PipelineGroupsDemoModel()}>
<TopologyPipelineGroups nodes={nodes} />
</PipelineGroupsDemoContext.Provider>
</VisualizationProvider>
</div>
);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import * as React from 'react';
import { makeObservable, observable, action } from 'mobx';

export class PipelineGroupsDemoModel {
protected verticalLayoutP: boolean = false;

constructor() {
makeObservable<
PipelineGroupsDemoModel,
| 'verticalLayoutP'
>(this, {
verticalLayoutP: observable,
setVerticalLayout: action,
});
}

public get verticalLayout(): boolean {
return this.verticalLayoutP;
}
public setVerticalLayout = (show: boolean): void => {
this.verticalLayoutP = show;
}
}

export const PipelineGroupsDemoContext = React.createContext<PipelineGroupsDemoModel>(new PipelineGroupsDemoModel());
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { AbstractAnchor, Point, Node } from '@patternfly/react-topology';

export default class TaskGroupSourceAnchor<E extends Node = Node> extends AbstractAnchor {
private vertical = false;

constructor(owner: E, vertical: boolean = true) {
super(owner);
this.vertical = vertical;
}

getLocation(): Point {
return this.getReferencePoint();
}

getReferencePoint(): Point {
const bounds = this.owner.getBounds();
if (this.vertical) {
return new Point(bounds.x + bounds.width / 2, bounds.bottom());
}
return new Point(bounds.right(), bounds.y + bounds.height / 2);
}
}
Loading

0 comments on commit 209b905

Please sign in to comment.