Skip to content

Commit

Permalink
Add graph model generator and update UI components
Browse files Browse the repository at this point in the history
- add code to generate graph data model from set of Tekton resources
  representing a PipelineRun
- simplify graph model to remove unecessary fields
- add TaskRun / step status to nodes
- update UI components to support dynamically redrawing the diagram
- add click handlers so consumers can hook into graph interaction (Task / step
  selected)
  • Loading branch information
AlanGreene committed Nov 18, 2019
1 parent aad762d commit 03781fa
Show file tree
Hide file tree
Showing 9 changed files with 1,020 additions and 26 deletions.
25 changes: 19 additions & 6 deletions packages/components/src/components/Graph/Graph.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,28 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
/* istanbul ignore file */
import React, { PureComponent } from 'react';
import React, { Component } from 'react';
import { Graph as VXGraph } from '@vx/network';
import ELK from 'elkjs/lib/elk.bundled';

import Node from './Node'; // eslint-disable-line import/no-cycle
import NodeLink from './NodeLink';

export default class Graph extends PureComponent {
export default class Graph extends Component {
state = {};

componentDidMount() {
this.layout();
}

componentDidUpdate(prevProps) {
const { graph } = this.props;
const { graph: prevGraph } = prevProps;
if (graph !== prevGraph) {
this.layout();
}
}

layout = () => {
const { graph, isSubGraph } = this.props;

Expand Down Expand Up @@ -59,7 +67,7 @@ export default class Graph extends PureComponent {
};

render() {
const { height, isSubGraph, width, y } = this.props;
const { height, isSubGraph, onClickStep, onClickTask, width } = this.props;
const { links, margin, nodes } = this.state;

if (!nodes) {
Expand All @@ -74,7 +82,6 @@ export default class Graph extends PureComponent {
width={width}
viewBox={`0 0 ${width} ${height}`}
preserveAspectRatio="xMidYMin meet"
y={y}
>
<defs>
<marker
Expand All @@ -93,7 +100,11 @@ export default class Graph extends PureComponent {
<VXGraph
graph={{ links, nodes }}
nodeComponent={c => (
<Node onClick={n => console.log('onClick', n)} {...c.node} />
<Node
onClick={isSubGraph ? onClickStep : onClickTask}
onClickStep={isSubGraph ? undefined : onClickStep}
{...c.node}
/>
)}
linkComponent={isSubGraph ? () => null : NodeLink}
/>
Expand All @@ -103,5 +114,7 @@ export default class Graph extends PureComponent {
}

Graph.defaultProps = {
isSubGraph: false
isSubGraph: false,
onClickStep: () => {},
onClickTask: () => {}
};
24 changes: 20 additions & 4 deletions packages/components/src/components/Graph/Graph.stories.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,16 @@ limitations under the License.

import React from 'react';
import { storiesOf } from '@storybook/react';
import { action } from '@storybook/addon-actions';

import Node from './Node';
import Graph from './Graph';
import graph from './sample.json';
import PipelineGraph from './PipelineGraph';

import graph from './examples/graph.json';
import pipeline from './examples/pipeline.json';
import pipelineRun from './examples/pipelineRun.json';
import tasks from './examples/tasks.json';

/*
TODO:
Expand Down Expand Up @@ -44,19 +50,19 @@ const expandedProps = {
type: 'Step',
id: '__step_build-and-push__build-image',
label: 'build-image',
width: 110,
width: 160,
height: 26
},
{
type: 'Step',
id: '__step_build-and-push__push-image',
label: 'push-image',
width: 110,
width: 160,
height: 26
}
],
edges: [],
height: 82
height: 79
};

storiesOf('Graph/Node', module)
Expand All @@ -79,3 +85,13 @@ storiesOf('Graph/Node', module)
storiesOf('Graph/Graph', module).add('default', () => (
<Graph graph={graph} width={450} height={550} />
));

storiesOf('Graph/PipelineGraph', module).add('default', () => (
<PipelineGraph
onClickStep={action('onClickStep')}
onClickTask={action('onClickTask')}
pipeline={pipeline}
pipelineRun={pipelineRun}
tasks={tasks}
/>
));
13 changes: 9 additions & 4 deletions packages/components/src/components/Graph/Node.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
/* istanbul ignore file */
import React, { PureComponent } from 'react';
import React, { Component } from 'react';
import classNames from 'classnames';

import CheckmarkFilled from '@carbon/icons-react/lib/checkmark--filled/16';
Expand All @@ -24,9 +24,13 @@ import Graph from './Graph'; // eslint-disable-line import/no-cycle
import InlineLoading from './InlineLoading';
import './Graph.scss';

export default class Node extends PureComponent {
export default class Node extends Component {
handleClick = () => {
this.props.onClick(this.props.id);
this.props.onClick(this.props.label);
};

handleClickStep = stepName => {
this.props.onClickStep(this.props.label, stepName);
};

render() {
Expand Down Expand Up @@ -123,9 +127,9 @@ export default class Node extends PureComponent {
<Graph
graph={{ id: `${id}_subgraph`, children, edges }}
isSubGraph
onClickStep={this.handleClickStep}
width={width}
height={height}
y={1}
/>
)}
</g>
Expand All @@ -137,5 +141,6 @@ export default class Node extends PureComponent {
Node.defaultProps = {
height: 100,
onClick: () => {},
onClickStep: () => {},
width: 100
};
72 changes: 72 additions & 0 deletions packages/components/src/components/Graph/PipelineGraph.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
Copyright 2019 The Tekton Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/* istanbul ignore file */
import React, { Component } from 'react';

import Graph from './Graph';
import buildGraphData from './buildGraphData';

export default class PipelineGraph extends Component {
state = {
expanded: {},
graph: null
};

componentDidMount() {
this.buildGraph();
}

componentDidUpdate(prevProps, prevState) {
const { expanded } = this.state;
const { expanded: prevExpanded } = prevState;
if (expanded !== prevExpanded) {
this.buildGraph();
}
}

onClickTask = taskName => {
const { expanded } = this.state;
this.setState({
expanded: {
...expanded,
[taskName]: !expanded[taskName]
}
});
this.props.onClickTask(taskName);
};

buildGraph() {
const { pipeline, pipelineRun, tasks } = this.props;
const { expanded } = this.state;
const graph = buildGraphData({ expanded, pipeline, pipelineRun, tasks });
this.setState({ graph });
}

render() {
const { graph } = this.state;
return graph ? (
<Graph
graph={graph}
width={500}
height={600}
onClickStep={this.props.onClickStep}
onClickTask={this.onClickTask}
/>
) : null;
}
}

PipelineGraph.defaultProps = {
onClickStep: () => {},
onClickTask: () => {}
};
Loading

0 comments on commit 03781fa

Please sign in to comment.