@@ -16,10 +16,8 @@ import { AWSTreeNodeBase } from '../../shared/treeview/nodes/awsTreeNodeBase'
16
16
import { PlaceholderNode } from '../../shared/treeview/nodes/placeholderNode'
17
17
import { makeChildrenNodes } from '../../shared/treeview/utils'
18
18
import { toArrayAsync , toMap , updateInPlace } from '../../shared/utilities/collectionUtils'
19
- import { listStateMachines } from '../../stepFunctions/utils'
20
- import { getIcon } from '../../shared/icons'
21
-
22
- export const contextValueStateMachine = 'awsStateMachineNode'
19
+ import { listStateMachines , listExecutions } from '../../stepFunctions/utils'
20
+ import { getIcon , IconPath } from '../../shared/icons'
23
21
24
22
const sfnNodeMap = new Map < string , StepFunctionsNode > ( )
25
23
@@ -74,20 +72,70 @@ export class StepFunctionsNode extends AWSTreeNodeBase {
74
72
this . stateMachineNodes ,
75
73
functions . keys ( ) ,
76
74
( key ) => this . stateMachineNodes . get ( key ) ! . update ( functions . get ( key ) ! ) ,
77
- ( key ) => makeStateMachineNode ( this , this . regionCode , functions . get ( key ) ! )
75
+ ( key ) => new StateMachineNode ( this , this . regionCode , functions . get ( key ) ! , this . client )
78
76
)
79
77
}
80
78
}
81
79
80
+ /**
81
+ * Represents a Step Functions state machine in the Explorer view. This node
82
+ * appears immediately underneath the "Step Functions" node. A StateMachineNode
83
+ * will contain children of type StateMachineExecutionNode, representing
84
+ * the most recent executions of that state machine.
85
+ */
82
86
export class StateMachineNode extends AWSTreeNodeBase implements AWSResourceNode {
87
+ public static readonly contextValue = 'awsStateMachineNode'
88
+ public static readonly maxExecutionsToShow = 10
89
+
90
+ private readonly stateMachineExecutionNodes : Map < string , StateMachineExecutionNode >
91
+
83
92
public constructor (
84
93
public readonly parent : AWSTreeNodeBase ,
85
94
public override readonly regionCode : string ,
86
- public details : StepFunctions . StateMachineListItem
95
+ public details : StepFunctions . StateMachineListItem ,
96
+ private readonly client : StepFunctionsClient
87
97
) {
88
- super ( '' )
98
+ super ( '' , vscode . TreeItemCollapsibleState . Collapsed )
99
+ this . stateMachineExecutionNodes = new Map < string , StateMachineExecutionNode > ( )
89
100
this . update ( details )
90
101
this . iconPath = getIcon ( 'aws-stepfunctions-preview' )
102
+ this . contextValue = StateMachineNode . contextValue
103
+ }
104
+
105
+ public override async getChildren ( ) : Promise < AWSTreeNodeBase [ ] > {
106
+ return await makeChildrenNodes ( {
107
+ getChildNodes : async ( ) => {
108
+ await this . updateChildren ( )
109
+ return [ ...this . stateMachineExecutionNodes . values ( ) ]
110
+ } ,
111
+ getNoChildrenPlaceholderNode : async ( ) =>
112
+ new PlaceholderNode (
113
+ this ,
114
+ localize ( 'AWS.explorerNode.stepfunctions.noStateMachineExecution' , '[No Executions found]' )
115
+ ) ,
116
+ /*
117
+ * Note: although Step Functions returns the executions in the correct order, this sorting
118
+ * is still needed to ensure newly added nodes (via updateChildren()) appear in the correct place.
119
+ */
120
+ sort : ( nodeA , nodeB ) => {
121
+ const dateA = nodeA . details . startDate as Date // startDate will never be undefined.
122
+ const dateB = nodeB . details . startDate as Date
123
+ return dateB . getTime ( ) - dateA . getTime ( )
124
+ } ,
125
+ } )
126
+ }
127
+
128
+ public async updateChildren ( ) : Promise < void > {
129
+ const executions : Map < string , StepFunctions . ExecutionListItem > = toMap (
130
+ await toArrayAsync ( listExecutions ( this . client , this . arn , StateMachineNode . maxExecutionsToShow ) ) ,
131
+ ( details ) => details . name
132
+ )
133
+ updateInPlace (
134
+ this . stateMachineExecutionNodes ,
135
+ executions . keys ( ) ,
136
+ ( key ) => this . stateMachineExecutionNodes . get ( key ) ! . update ( executions . get ( key ) ! ) ,
137
+ ( key ) => new StateMachineExecutionNode ( this , this . regionCode , executions . get ( key ) ! )
138
+ )
91
139
}
92
140
93
141
public update ( details : StepFunctions . StateMachineListItem ) : void {
@@ -113,13 +161,61 @@ export class StateMachineNode extends AWSTreeNodeBase implements AWSResourceNode
113
161
}
114
162
}
115
163
116
- function makeStateMachineNode (
117
- parent : AWSTreeNodeBase ,
118
- regionCode : string ,
119
- details : StepFunctions . StateMachineListItem
120
- ) : StateMachineNode {
121
- const node = new StateMachineNode ( parent , regionCode , details )
122
- node . contextValue = contextValueStateMachine
164
+ /**
165
+ * Represents a single execution of a Step Functions state machine in the Explorer
166
+ * view. This node appears immediately underneath the corresponding StateMachineNode.
167
+ */
168
+ export class StateMachineExecutionNode extends AWSTreeNodeBase implements AWSResourceNode {
169
+ public static contextValue = 'awsStateMachineExecutionNode'
170
+
171
+ public constructor (
172
+ public readonly parent : AWSTreeNodeBase ,
173
+ public override readonly regionCode : string ,
174
+ public details : StepFunctions . ExecutionListItem
175
+ ) {
176
+ super ( '' )
177
+ this . update ( details )
178
+ this . contextValue = StateMachineExecutionNode . contextValue
179
+ }
180
+
181
+ public update ( details : StepFunctions . ExecutionListItem ) : void {
182
+ this . details = details
183
+ this . label = this . details . name || ''
184
+ this . tooltip = this . getToolTip ( this . details )
185
+ this . iconPath = this . getIconPathForStatus ( this . details . status )
186
+ }
187
+
188
+ public get arn ( ) : string {
189
+ return this . details . executionArn || ''
190
+ }
123
191
124
- return node
192
+ public get name ( ) : string {
193
+ return this . details . name || ''
194
+ }
195
+
196
+ private getIconPathForStatus ( status ?: string ) : IconPath {
197
+ switch ( status ) {
198
+ case 'RUNNING' :
199
+ return getIcon ( 'vscode-sync' )
200
+ case 'SUCCEEDED' :
201
+ return getIcon ( 'vscode-check' )
202
+ default :
203
+ return getIcon ( 'vscode-error' )
204
+ }
205
+ }
206
+
207
+ private getToolTip ( details : StepFunctions . ExecutionListItem ) {
208
+ const startTimeText = localize ( 'AWS.explorerNode.stepfunctions.startTime' , 'Start Time' )
209
+ const endTimeText = localize ( 'AWS.explorerNode.stepfunctions.endTime' , 'End Time' )
210
+ const durationText = localize ( 'AWS.explorerNode.stepfunctions.duration' , 'Duration' )
211
+ const secondsText = localize ( 'AWS.explorerNode.stepfunctions.seconds' , 'seconds' )
212
+
213
+ let text : string = `${ details . status } ${ os . EOL } ${ startTimeText } : ${ details . startDate ?. toLocaleString ( ) } ${ os . EOL } `
214
+ if ( details . status !== 'RUNNING' ) {
215
+ text += `${ endTimeText } : ${ details . stopDate ?. toLocaleString ( ) } ${ os . EOL } `
216
+ const endDate = details . stopDate ? details . stopDate : new Date ( )
217
+ text += `${ durationText } : ${ Math . trunc ( ( endDate . getTime ( ) - details . startDate ! . getTime ( ) ) / 1000 ) } ${ secondsText } ${ os . EOL } `
218
+ }
219
+ return text
220
+ }
125
221
}
0 commit comments