Skip to content

Commit e37f0c1

Browse files
timbrown5timja
andauthored
Add clickable line numbers to console view (#90)
Co-authored-by: Tim Jacomb <[email protected]>
1 parent 8bef571 commit e37f0c1

File tree

10 files changed

+582
-369
lines changed

10 files changed

+582
-369
lines changed

package-lock.json

Lines changed: 217 additions & 218 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/main/frontend/pipeline-console-view/app.tsx

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,6 @@ import { FunctionComponent } from "react";
44

55
import { PipelineConsole } from "./pipeline-console/main/";
66

7-
//const rootElement = document.getElementById("root");
8-
//ReactDOM.render(<DataTreeView />, rootElement);
9-
107
const App: FunctionComponent = () => {
118
return (
129
<React.Fragment>

src/main/frontend/pipeline-console-view/pipeline-console/main/DataTreeView.tsx

Lines changed: 40 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,8 @@
1-
import React, { useEffect, useState } from "react";
21

3-
import TreeView from "@material-ui/lab/TreeView";
2+
import React from "react";
3+
4+
import TreeView from "@material-ui/lab/TreeView/";
45

5-
import {
6-
fade,
7-
makeStyles,
8-
withStyles,
9-
Theme,
10-
createStyles,
11-
} from "@material-ui/core/styles";
126
import TreeItem, { TreeItemProps } from "@material-ui/lab/TreeItem";
137
import ExpandMoreIcon from "@material-ui/icons/ExpandMore";
148
import ChevronRightIcon from "@material-ui/icons/ChevronRight";
@@ -17,6 +11,12 @@ import {
1711
Result,
1812
} from "../../../pipeline-graph-view/pipeline-graph/main/";
1913

14+
import {
15+
fade,
16+
withStyles,
17+
Theme,
18+
createStyles,
19+
} from "@material-ui/core/styles";
2020
/**
2121
* StageInfo is the input, in the form of an Array<StageInfo> of the top-level stages of a pipeline
2222
*/
@@ -27,12 +27,7 @@ export interface StepInfo {
2727
completePercent: number;
2828
id: number;
2929
type: string;
30-
}
31-
32-
export interface TreeItemData {
33-
id: string;
34-
name: string;
35-
children: TreeItemData[];
30+
stageId: string;
3631
}
3732

3833
// Tree Item for stages
@@ -68,24 +63,38 @@ const getTreeItemsFromStepList = (stepsItems: StepInfo[]) => {
6863
<StepTreeItem
6964
key={stepItemData.id}
7065
nodeId={String(stepItemData.id)}
71-
label={stepItemData.name}
66+
label={stepItemData.name.replace(/[^ -~]+/g, "")}
7267
/>
7368
);
7469
});
7570
};
7671

7772
const getTreeItemsFromStage = (
7873
stageItems: StageInfo[],
79-
stageSteps: Map<string, StepInfo[]>
74+
steps: StepInfo[],
8075
) => {
76+
// Copy steps so we don't affect props.steps.
77+
let stepsCopy = [...steps];
8178
return stageItems.map((stageItemData) => {
8279
let children: JSX.Element[] = [];
80+
let stageSteps = [] as StepInfo[];
81+
// Handle leaf nodes first.
8382
if (stageItemData.children && stageItemData.children.length > 0) {
84-
children = [...getTreeItemsFromStage(stageItemData.children, stageSteps)];
83+
children = getTreeItemsFromStage(stageItemData.children, stepsCopy);
8584
}
86-
let steps = stageSteps.get(`${stageItemData.id}`);
87-
if (steps) {
88-
let stepsItems = getTreeItemsFromStepList(steps);
85+
var i = stepsCopy.length
86+
while (i--) {
87+
let step = stepsCopy[i];
88+
if (step.stageId == String(stageItemData.id)) {
89+
// Prepend to array (as we are iterating in reverse).
90+
stageSteps.unshift(step);
91+
// Remove step from local copy - can only have one parent.
92+
// This should reduce the total number of loops required.
93+
stepsCopy.splice(i, 1);
94+
}
95+
};
96+
if (stageSteps) {
97+
let stepsItems = getTreeItemsFromStepList(stageSteps);
8998
children = [...children, ...stepsItems];
9099
}
91100
return (
@@ -106,108 +115,31 @@ const getTreeItemsFromStage = (
106115

107116
interface DataTreeViewProps {
108117
stages: Array<StageInfo>;
109-
onActionNodeSelect: (event: React.ChangeEvent<any>, nodeIds: string) => void;
110-
}
111-
112-
interface State {
113-
stages: Array<StageInfo>;
114-
steps: Map<string, StepInfo[]>;
115-
expanded: Array<string>;
118+
onNodeSelect: (event: React.ChangeEvent<any>, nodeId: string) => void;
119+
onNodeToggle: (event: React.ChangeEvent<any>, nodeIds: string[]) => void;
120+
selected: string;
121+
expanded: string[];
122+
steps: StepInfo[];
116123
}
117124

118125
export class DataTreeView extends React.Component {
119126
props!: DataTreeViewProps;
120-
state: State;
121127

122128
constructor(props: DataTreeViewProps) {
123129
super(props);
124-
this.state = {
125-
stages: [],
126-
steps: new Map(),
127-
expanded: [],
128-
};
129-
this.handleToggle = this.handleToggle.bind(this);
130-
}
131-
132-
handleToggle(event: React.ChangeEvent<{}>, nodeIds: string[]): void {
133-
this.setState({
134-
expanded: nodeIds,
135-
});
136-
}
137-
138-
getStepsForStageTree(stage: StageInfo): void {
139-
// TODO: This should change to getting all the steps in one API call.
140-
// Otherwise large Pipelines will make a lot of API calls (one per stage).
141-
fetch(`steps?nodeId=${stage.id}`)
142-
.then((step_res) => step_res.json())
143-
.then((step_result) => {
144-
this.setState({
145-
steps: new Map(
146-
this.state.steps.set(`${stage.id}`, step_result.steps)
147-
),
148-
});
149-
});
150-
if (stage.children && stage.children.length > 0) {
151-
stage.children.forEach((childStage) => {
152-
this.getStepsForStageTree(childStage);
153-
});
154-
}
155-
}
156-
157-
getNodeHierarchy(nodeId: string, stages: StageInfo[]): Array<string> {
158-
for (let i = 0; i < stages.length; i++) {
159-
let stage = stages[i];
160-
if (String(stage.id) == nodeId) {
161-
// Found the node, so start a list of expanded nodes - it will be this and it's ancestors.
162-
return [String(stage.id)];
163-
} else if (stage.children && stage.children.length > 0) {
164-
let expandedNodes = this.getNodeHierarchy(nodeId, stage.children);
165-
if (expandedNodes.length > 0) {
166-
// Our child is expanded, so we need to be expanded too.
167-
expandedNodes.push(String(stage.id));
168-
return expandedNodes;
169-
}
170-
}
171-
}
172-
return [];
173-
}
174-
175-
componentDidMount() {
176-
let params = new URLSearchParams(document.location.search.substring(1));
177-
let selectedNode = params.get("selected-node") || "";
178-
fetch("tree")
179-
.then((res) => res.json())
180-
.then((result) => {
181-
// Get steps for a each stage and add to 'steps' state
182-
this.setState(
183-
{
184-
stages: result.data.stages,
185-
expanded: this.getNodeHierarchy(selectedNode, result.data.stages),
186-
},
187-
() => {
188-
this.state.stages.forEach((stageData) => {
189-
this.getStepsForStageTree(stageData);
190-
});
191-
}
192-
);
193-
})
194-
.catch(console.log);
195-
}
196-
197-
handleOnNodeSelect() {
198-
this.props.onActionNodeSelect;
199130
}
200131

201132
render() {
202133
return (
203134
<TreeView
204135
defaultCollapseIcon={<ExpandMoreIcon />}
205136
defaultExpandIcon={<ChevronRightIcon />}
206-
onNodeSelect={this.props.onActionNodeSelect}
207-
expanded={this.state.expanded}
208-
onNodeToggle={this.handleToggle}
137+
onNodeSelect={this.props.onNodeSelect}
138+
expanded={this.props.expanded}
139+
selected={this.props.selected}
140+
onNodeToggle={this.props.onNodeToggle}
209141
>
210-
{getTreeItemsFromStage(this.state.stages, this.state.steps)}
142+
{getTreeItemsFromStage(this.props.stages, this.props.steps)}
211143
</TreeView>
212144
);
213145
}

0 commit comments

Comments
 (0)