Skip to content

Commit

Permalink
Merge pull request #162 from jenny-s51/iss153
Browse files Browse the repository at this point in the history
feat(pipelines): add support for collapsible groups
  • Loading branch information
jessiehuff authored Mar 26, 2024
2 parents 3b004ac + 620de54 commit 129c309
Show file tree
Hide file tree
Showing 19 changed files with 723 additions and 193 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,37 +3,67 @@ import { observer } from 'mobx-react';
import {
AnchorEnd,
DagreLayoutOptions,
DefaultGroup,
DefaultTaskGroup,
GraphElement,
isNode,
LabelPosition,
Node,
TOP_TO_BOTTOM,
useAnchor,
WithContextMenuProps,
WithSelectionProps,
ShapeProps,
WithDragNodeProps,
EdgeCreationTypes,
} from '@patternfly/react-topology';
import TaskGroupSourceAnchor from './TaskGroupSourceAnchor';
import TaskGroupTargetAnchor from './TaskGroupTargetAnchor';

interface DemoTaskNodeProps {
type DemoTaskGroupProps = {
element: GraphElement;
}
collapsible?: boolean;
collapsedWidth?: number;
collapsedHeight?: number;
onCollapseChange?: (group: Node, collapsed: boolean) => void;
getCollapsedShape?: (node: Node) => React.FunctionComponent<ShapeProps>;
collapsedShadowOffset?: number; // defaults to 10
} & WithContextMenuProps &
WithDragNodeProps &
WithSelectionProps;

const DemoTaskGroup: React.FunctionComponent<DemoTaskNodeProps> = ({ element, ...rest }) => {
export const DEFAULT_TASK_WIDTH = 180;
export const DEFAULT_TASK_HEIGHT = 32;

const getEdgeCreationTypes = (): EdgeCreationTypes => ({
edgeType: 'edge',
spacerEdgeType: 'edge'
});

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

useAnchor(
React.useCallback((node: Node) =>new TaskGroupSourceAnchor(node, verticalLayout), [verticalLayout]),
React.useCallback((node: Node) => new TaskGroupSourceAnchor(node, verticalLayout), [verticalLayout]),
AnchorEnd.source
);
useAnchor(
React.useCallback((node: Node) => new TaskGroupTargetAnchor(node, verticalLayout),[verticalLayout]),
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} />
<DefaultTaskGroup
labelPosition={verticalLayout ? LabelPosition.top : LabelPosition.bottom}
collapsible
collapsedWidth={DEFAULT_TASK_WIDTH}
collapsedHeight={DEFAULT_TASK_HEIGHT}
element={element as Node}
recreateLayoutOnCollapseChange
getEdgeCreationTypes={getEdgeCreationTypes}
{...rest}
/>
);
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ import { createDemoPipelineGroupsNodes } from './createDemoPipelineGroupsNodes';
import { PipelineGroupsDemoContext, PipelineGroupsDemoModel } from './PipelineGroupsDemoContext';
import OptionsBar from './OptionsBar';
import DemoControlBar from '../DemoControlBar';
import pipelineElementFactory
from '@patternfly/react-topology/dist/esm/pipelines/elements/pipelineElementFactory';

const TopologyPipelineGroups: React.FC<{ nodes: PipelineNodeModel[] }> = observer(({ nodes }) => {
const controller = useVisualizationController();
Expand Down Expand Up @@ -64,6 +66,7 @@ TopologyPipelineGroups.displayName = 'TopologyPipelineLayout';

export const PipelineGroupsDemo = observer(() => {
const controller = new Visualization();
controller.registerElementFactory(pipelineElementFactory);
controller.registerComponentFactory(pipelineGroupsComponentFactory);
controller.registerLayoutFactory(
(type: string, graph: Graph): Layout | undefined =>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
/* eslint-disable camelcase */
import { PipelineNodeModel, RunStatus } from '@patternfly/react-topology';

export const NODE_PADDING_VERTICAL = 15;
export const NODE_PADDING_VERTICAL = 0;
export const NODE_PADDING_HORIZONTAL = 15;

export const GROUP_PADDING_VERTICAL = 15;
export const GROUP_PADDING_VERTICAL = 40;
export const GROUP_PADDING_HORIZONTAL = 25;

export const DEFAULT_TASK_WIDTH = 180;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const pipelineGroupsComponentFactory: ComponentFactory = (
}
switch (type) {
case 'Execution':
return DemoTaskGroup;
return withSelection()(DemoTaskGroup);
case 'Task':
return withSelection()(DemoTaskNode);
case DEFAULT_SPACER_NODE_TYPE:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import * as React from 'react';
import {
DefaultTaskGroup,
GraphElement,
LabelPosition,
observer,
ScaleDetailsLevel,
WithContextMenuProps,
WithDragNodeProps,
WithSelectionProps,
} from '@patternfly/react-topology';

type DemoPipelinesGroupProps = {
element: GraphElement;
} & WithContextMenuProps &
WithDragNodeProps &
WithSelectionProps;

const DemoPipelinesGroup: React.FunctionComponent<DemoPipelinesGroupProps> = ({ element }) => {
const data = element.getData();
const detailsLevel = element.getGraph().getDetailsLevel()

return (
<DefaultTaskGroup
element={element}
collapsible={false}
showLabel={detailsLevel === ScaleDetailsLevel.high}
labelPosition={LabelPosition.top}
badge={data?.badge}
/>
);
};

export default observer(DemoPipelinesGroup);
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import DemoTaskNode from './DemoTaskNode';
import DemoFinallyNode from './DemoFinallyNode';
import DemoTaskGroupEdge from './DemoTaskGroupEdge';
import DemoTaskEdge from './DemoTaskEdge';
import DemoPipelinesGroup from "./DemoPipelinesGroup";

export const GROUPED_EDGE_TYPE = 'GROUPED_EDGE';
export const SPACER_EDGE_TYPE = 'spacer-edge';
Expand Down Expand Up @@ -55,7 +56,7 @@ const pipelineComponentFactory: ComponentFactory = (
case DEFAULT_FINALLY_NODE_TYPE:
return withContextMenu(() => defaultMenu)(withSelection()(DemoFinallyNode));
case 'task-group':
return DefaultTaskGroup;
return withSelection()(DemoPipelinesGroup);
case 'finally-group':
return DefaultTaskGroup;
case DEFAULT_SPACER_NODE_TYPE:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
DEFAULT_TASK_NODE_TYPE,
DEFAULT_WHEN_OFFSET,
DEFAULT_WHEN_SIZE,
LabelPosition,
PipelineNodeModel,
RunStatus,
WhenStatus
Expand Down Expand Up @@ -149,7 +150,10 @@ export const useDemoPipelineNodes = (
type: 'task-group',
children: parallelTasks.map((t) => t.id),
group: true,
label: 'Parallel tasks'
label: 'Parallel tasks',
data: {
badge: 'Label',
}
});
}
}
Expand Down Expand Up @@ -190,7 +194,8 @@ export const useDemoPipelineNodes = (
type: 'task-group',
children: [],
group: true,
label: `Group ${task.data.columnGroup}`
label: `Group ${task.data.columnGroup}`,
labelPosition: LabelPosition.top
};
acc.push(taskGroup);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,4 +140,4 @@ const stylesComponentFactory: ComponentFactory = (
}
};

export default stylesComponentFactory;
export default stylesComponentFactory;
1 change: 1 addition & 0 deletions packages/module/src/components/nodes/labels/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ export { default as LabelBadge } from './LabelBadge';
export { default as LabelContextMenu } from './LabelContextMenu';
export { default as LabelIcon } from './LabelIcon';
export { default as NodeLabel } from './NodeLabel';

Loading

0 comments on commit 129c309

Please sign in to comment.