1
- import React , { useEffect , useState } from "react" ;
2
1
3
- import TreeView from "@material-ui/lab/TreeView" ;
2
+ import React from "react" ;
3
+
4
+ import TreeView from "@material-ui/lab/TreeView/" ;
4
5
5
- import {
6
- fade ,
7
- makeStyles ,
8
- withStyles ,
9
- Theme ,
10
- createStyles ,
11
- } from "@material-ui/core/styles" ;
12
6
import TreeItem , { TreeItemProps } from "@material-ui/lab/TreeItem" ;
13
7
import ExpandMoreIcon from "@material-ui/icons/ExpandMore" ;
14
8
import ChevronRightIcon from "@material-ui/icons/ChevronRight" ;
@@ -17,6 +11,12 @@ import {
17
11
Result ,
18
12
} from "../../../pipeline-graph-view/pipeline-graph/main/" ;
19
13
14
+ import {
15
+ fade ,
16
+ withStyles ,
17
+ Theme ,
18
+ createStyles ,
19
+ } from "@material-ui/core/styles" ;
20
20
/**
21
21
* StageInfo is the input, in the form of an Array<StageInfo> of the top-level stages of a pipeline
22
22
*/
@@ -27,12 +27,7 @@ export interface StepInfo {
27
27
completePercent : number ;
28
28
id : number ;
29
29
type : string ;
30
- }
31
-
32
- export interface TreeItemData {
33
- id : string ;
34
- name : string ;
35
- children : TreeItemData [ ] ;
30
+ stageId : string ;
36
31
}
37
32
38
33
// Tree Item for stages
@@ -68,24 +63,38 @@ const getTreeItemsFromStepList = (stepsItems: StepInfo[]) => {
68
63
< StepTreeItem
69
64
key = { stepItemData . id }
70
65
nodeId = { String ( stepItemData . id ) }
71
- label = { stepItemData . name }
66
+ label = { stepItemData . name . replace ( / [ ^ - ~ ] + / g , "" ) }
72
67
/>
73
68
) ;
74
69
} ) ;
75
70
} ;
76
71
77
72
const getTreeItemsFromStage = (
78
73
stageItems : StageInfo [ ] ,
79
- stageSteps : Map < string , StepInfo [ ] >
74
+ steps : StepInfo [ ] ,
80
75
) => {
76
+ // Copy steps so we don't affect props.steps.
77
+ let stepsCopy = [ ...steps ] ;
81
78
return stageItems . map ( ( stageItemData ) => {
82
79
let children : JSX . Element [ ] = [ ] ;
80
+ let stageSteps = [ ] as StepInfo [ ] ;
81
+ // Handle leaf nodes first.
83
82
if ( stageItemData . children && stageItemData . children . length > 0 ) {
84
- children = [ ... getTreeItemsFromStage ( stageItemData . children , stageSteps ) ] ;
83
+ children = getTreeItemsFromStage ( stageItemData . children , stepsCopy ) ;
85
84
}
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 ) ;
89
98
children = [ ...children , ...stepsItems ] ;
90
99
}
91
100
return (
@@ -106,108 +115,31 @@ const getTreeItemsFromStage = (
106
115
107
116
interface DataTreeViewProps {
108
117
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 [ ] ;
116
123
}
117
124
118
125
export class DataTreeView extends React . Component {
119
126
props ! : DataTreeViewProps ;
120
- state : State ;
121
127
122
128
constructor ( props : DataTreeViewProps ) {
123
129
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 ;
199
130
}
200
131
201
132
render ( ) {
202
133
return (
203
134
< TreeView
204
135
defaultCollapseIcon = { < ExpandMoreIcon /> }
205
136
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 }
209
141
>
210
- { getTreeItemsFromStage ( this . state . stages , this . state . steps ) }
142
+ { getTreeItemsFromStage ( this . props . stages , this . props . steps ) }
211
143
</ TreeView >
212
144
) ;
213
145
}
0 commit comments