1
1
import * as vscode from "vscode" ;
2
2
import { AtelierAPI } from "../api" ;
3
- import { cspApps , currentWorkspaceFolder , notIsfs , uriOfWorkspaceFolder } from "../utils" ;
3
+ import { cspApps , currentWorkspaceFolder , notIsfs , stringifyError , uriOfWorkspaceFolder } from "../utils" ;
4
4
import { StudioActions , OtherStudioAction } from "../commands/studio" ;
5
5
import { config , workspaceState } from "../extension" ;
6
6
import { DocumentContentProvider } from "../providers/DocumentContentProvider" ;
7
7
8
- type IconPath =
9
- | string
10
- | vscode . Uri
11
- | {
12
- light : string | vscode . Uri ;
13
- dark : string | vscode . Uri ;
14
- }
15
- | vscode . ThemeIcon ;
16
-
17
8
interface NodeOptions {
18
9
extraNode ?: boolean ;
19
10
generated ?: boolean ;
@@ -49,6 +40,8 @@ function getLeafNodeUri(node: NodeBase, forceServerCopy = false): vscode.Uri {
49
40
}
50
41
}
51
42
43
+ const inactiveMsg = "Server connection is inactive" ;
44
+
52
45
export class NodeBase {
53
46
public readonly options : NodeOptions ;
54
47
public readonly label : string ;
@@ -104,7 +97,7 @@ export class RootNode extends NodeBase {
104
97
public readonly contextValue : string ;
105
98
private readonly _category : string ;
106
99
private readonly isCsp : boolean ;
107
- private readonly iconPath : IconPath ;
100
+ private readonly iconPath : vscode . ThemeIcon ;
108
101
109
102
public constructor (
110
103
label : string ,
@@ -113,7 +106,7 @@ export class RootNode extends NodeBase {
113
106
category : string ,
114
107
options : NodeOptions ,
115
108
isCsp = false ,
116
- iconPath ?: IconPath
109
+ iconPath ?: vscode . ThemeIcon
117
110
) {
118
111
super ( label , fullName , options ) ;
119
112
this . contextValue = contextValue ;
@@ -138,7 +131,51 @@ export class RootNode extends NodeBase {
138
131
139
132
public async getChildren ( element : NodeBase ) : Promise < NodeBase [ ] > {
140
133
const path = this instanceof PackageNode || this . isCsp ? this . fullName + "/" : "" ;
141
- return this . getItems ( path , this . _category ) ;
134
+ return this . getList ( path , this . _category , false )
135
+ . then ( ( data ) =>
136
+ data
137
+ . filter ( ( el ) => {
138
+ if ( this . _category === "OTH" ) {
139
+ return el . Type === "100" ;
140
+ } else if ( this . _category === "CSP" ) {
141
+ return el . Type === "10" || el . Type === "5" ;
142
+ } else {
143
+ return true ;
144
+ }
145
+ } )
146
+ . map ( ( el ) => {
147
+ switch ( el . Type ) {
148
+ case "9" :
149
+ return new PackageNode ( el . Name , el . fullName , this . _category , this . options ) ;
150
+ case "4" :
151
+ case "100" :
152
+ return new ClassNode ( el . Name , el . fullName , this . options ) ;
153
+ case "5" :
154
+ return new CSPFileNode ( el . Name , el . fullName , this . options ) ;
155
+ case "0" :
156
+ case "1" :
157
+ case "2" :
158
+ case "3" :
159
+ case "11" :
160
+ return new RoutineNode ( el . Name , el . fullName , this . options ) ;
161
+ case "10" :
162
+ return new RootNode (
163
+ el . Name ,
164
+ el . fullName ,
165
+ "dataNode:cspApplication" ,
166
+ this . _category ,
167
+ this . options ,
168
+ true
169
+ ) ;
170
+ default :
171
+ return null ;
172
+ }
173
+ } )
174
+ . filter ( ( el ) => el !== null )
175
+ )
176
+ . catch ( ( error ) => [
177
+ error == inactiveMsg ? new InactiveNode ( "" , "" , { } ) : new ErrorNode ( stringifyError ( error ) , "" , { } ) ,
178
+ ] ) ;
142
179
}
143
180
144
181
public async getList (
@@ -180,6 +217,7 @@ export class RootNode extends NodeBase {
180
217
const systemFiles = this . options . system || this . namespace === "%SYS" ? "1" : "0" ;
181
218
182
219
const api = new AtelierAPI ( this . workspaceFolder ) ;
220
+ if ( ! api . active ) throw inactiveMsg ;
183
221
api . setNamespace ( this . namespace ) ;
184
222
if ( category == "CSP" && path == "" ) {
185
223
// Use the results from the getCSPApps() API
@@ -219,43 +257,6 @@ export class RootNode extends NodeBase {
219
257
}
220
258
}
221
259
222
- public getItems ( path : string , category : string ) : Promise < NodeBase [ ] > {
223
- return this . getList ( path , category , false ) . then ( ( data ) =>
224
- data
225
- . filter ( ( el ) => {
226
- if ( category === "OTH" ) {
227
- return el . Type === "100" ;
228
- } else if ( category === "CSP" ) {
229
- return el . Type === "10" || el . Type === "5" ;
230
- } else {
231
- return true ;
232
- }
233
- } )
234
- . map ( ( el ) => {
235
- switch ( el . Type ) {
236
- case "9" :
237
- return new PackageNode ( el . Name , el . fullName , category , this . options ) ;
238
- case "4" :
239
- case "100" :
240
- return new ClassNode ( el . Name , el . fullName , this . options ) ;
241
- case "5" :
242
- return new CSPFileNode ( el . Name , el . fullName , this . options ) ;
243
- case "0" :
244
- case "1" :
245
- case "2" :
246
- case "3" :
247
- case "11" :
248
- return new RoutineNode ( el . Name , el . fullName , this . options ) ;
249
- case "10" :
250
- return new RootNode ( el . Name , el . fullName , "dataNode:cspApplication" , this . _category , this . options , true ) ;
251
- default :
252
- return null ;
253
- }
254
- } )
255
- . filter ( ( el ) => el !== null )
256
- ) ;
257
- }
258
-
259
260
public getItems4Export ( ) : Promise < string [ ] > {
260
261
const path = this instanceof PackageNode || this . isCsp ? this . fullName + "/" : "" ;
261
262
const cat = this . isCsp ? "CSP" : "ALL" ;
@@ -399,6 +400,7 @@ export class WorkspaceNode extends NodeBase {
399
400
}
400
401
401
402
public async getChildren ( _element : NodeBase ) : Promise < NodeBase [ ] > {
403
+ if ( ! new AtelierAPI ( this . workspaceFolder ) . active ) return [ new InactiveNode ( "" , "" , { } ) ] ;
402
404
const children = [ ] ;
403
405
let node : RootNode ;
404
406
@@ -553,8 +555,9 @@ export class ProjectNode extends NodeBase {
553
555
}
554
556
555
557
export class ProjectRootNode extends RootNode {
556
- public getChildren ( element : NodeBase ) : Promise < NodeBase [ ] > {
558
+ public async getChildren ( element : NodeBase ) : Promise < NodeBase [ ] > {
557
559
const api = new AtelierAPI ( this . workspaceFolderUri ) ;
560
+ if ( ! api . active ) return [ new InactiveNode ( "" , "" , { } ) ] ;
558
561
api . setNamespace ( this . namespace ) ;
559
562
let query : string ;
560
563
let parameters : string [ ] ;
@@ -646,27 +649,27 @@ export class ProjectRootNode extends RootNode {
646
649
}
647
650
}
648
651
} )
649
- ) ;
652
+ )
653
+ . catch ( ( error ) => [ new ErrorNode ( stringifyError ( error ) , "" , { } ) ] ) ;
650
654
}
651
655
public getItems4Export ( ) : Promise < string [ ] > {
652
656
return Promise . resolve ( [ ] ) ;
653
657
}
654
658
}
655
659
656
- export class ProjectsServerNode extends NodeBase {
660
+ export class ProjectsServerNsNode extends NodeBase {
657
661
public eventEmitter : vscode . EventEmitter < NodeBase > ;
658
- public uniqueId : string ;
659
- public constructor ( label : string , eventEmitter : vscode . EventEmitter < NodeBase > , wsUri : vscode . Uri ) {
660
- super ( label , label , { workspaceFolderUri : wsUri } ) ;
661
- this . uniqueId = `projectsServerNode:${ this . workspaceFolder } ` ;
662
+
663
+ public constructor ( label : string , eventEmitter : vscode . EventEmitter < NodeBase > , wsUri : vscode . Uri , extra = false ) {
664
+ super ( label , label , { workspaceFolderUri : wsUri , extraNode : extra } ) ;
662
665
this . eventEmitter = eventEmitter ;
663
666
}
664
667
665
668
public getTreeItem ( ) : vscode . TreeItem {
666
669
const { host, port, pathPrefix, serverName } = this . conn ;
667
670
return {
668
671
collapsibleState : vscode . TreeItemCollapsibleState . Expanded ,
669
- contextValue : this . uniqueId ,
672
+ contextValue : `projectsServerNsNode ${ this . extraNode ? ":extra" : "" } ` ,
670
673
label : `${
671
674
serverName && serverName . length ? serverName : `${ host } :${ port } ${ pathPrefix } `
672
675
} :${ this . namespace . toUpperCase ( ) } `,
@@ -677,47 +680,52 @@ export class ProjectsServerNode extends NodeBase {
677
680
678
681
public async getChildren ( element : NodeBase ) : Promise < NodeBase [ ] > {
679
682
const api = new AtelierAPI ( this . workspaceFolderUri ) ;
683
+ if ( ! api . active ) return [ new InactiveNode ( "" , "" , { } ) ] ;
680
684
api . setNamespace ( this . namespace ) ;
681
685
return api
682
686
. actionQuery ( "SELECT Name, Description FROM %Studio.Project" , [ ] )
683
687
. then ( ( data ) =>
684
688
data . result . content . map (
685
689
( project ) => new ProjectNode ( project . Name , { project : project . Name , ...this . options } , project . Description )
686
690
)
687
- ) ;
691
+ )
692
+ . catch ( ( error ) => [ new ErrorNode ( stringifyError ( error ) , "" , { } ) ] ) ;
688
693
}
689
694
}
690
695
691
- export class ProjectsServerNsNode extends NodeBase {
692
- public eventEmitter : vscode . EventEmitter < NodeBase > ;
693
-
694
- public constructor ( label : string , eventEmitter : vscode . EventEmitter < NodeBase > , wsUri : vscode . Uri , extra = false ) {
695
- super ( label , label , { workspaceFolderUri : wsUri , extraNode : extra } ) ;
696
- this . eventEmitter = eventEmitter ;
696
+ /** Used to show that a server connection is inactive */
697
+ class InactiveNode extends NodeBase {
698
+ public constructor ( label : string , fullName : string , options : NodeOptions ) {
699
+ super ( label , fullName , options ) ;
697
700
}
698
-
699
701
public getTreeItem ( ) : vscode . TreeItem {
700
- const { host, port, pathPrefix, serverName } = this . conn ;
701
702
return {
702
- collapsibleState : vscode . TreeItemCollapsibleState . Expanded ,
703
- contextValue : `projectsServerNsNode${ this . extraNode ? ":extra" : "" } ` ,
704
- label : `${
705
- serverName && serverName . length ? serverName : `${ host } :${ port } ${ pathPrefix } `
706
- } :${ this . namespace . toUpperCase ( ) } `,
707
- iconPath : new vscode . ThemeIcon ( "server-environment" ) ,
708
- tooltip : "Explore projects in this server namespace" ,
703
+ collapsibleState : vscode . TreeItemCollapsibleState . None ,
704
+ contextValue : "inactiveNode" ,
705
+ label : inactiveMsg ,
706
+ iconPath : new vscode . ThemeIcon ( "warning" , new vscode . ThemeColor ( "problemsWarningIcon.foreground" ) ) ,
709
707
} ;
710
708
}
709
+ public getItems4Export ( ) : Promise < string [ ] > {
710
+ return Promise . resolve ( [ ] ) ;
711
+ }
712
+ }
711
713
712
- public async getChildren ( element : NodeBase ) : Promise < NodeBase [ ] > {
713
- const api = new AtelierAPI ( this . workspaceFolderUri ) ;
714
- api . setNamespace ( this . namespace ) ;
715
- return api
716
- . actionQuery ( "SELECT Name, Description FROM %Studio.Project" , [ ] )
717
- . then ( ( data ) =>
718
- data . result . content . map (
719
- ( project ) => new ProjectNode ( project . Name , { project : project . Name , ...this . options } , project . Description )
720
- )
721
- ) ;
714
+ /** Used to bubble up an error to the user */
715
+ class ErrorNode extends NodeBase {
716
+ public constructor ( label : string , fullName : string , options : NodeOptions ) {
717
+ super ( label , fullName , options ) ;
718
+ }
719
+ public getTreeItem ( ) : vscode . TreeItem {
720
+ return {
721
+ collapsibleState : vscode . TreeItemCollapsibleState . None ,
722
+ contextValue : "errorNode" ,
723
+ label : "Error fetching children" ,
724
+ tooltip : new vscode . MarkdownString ( this . label ) ,
725
+ iconPath : new vscode . ThemeIcon ( "error" , new vscode . ThemeColor ( "problemsErrorIcon.foreground" ) ) ,
726
+ } ;
727
+ }
728
+ public getItems4Export ( ) : Promise < string [ ] > {
729
+ return Promise . resolve ( [ ] ) ;
722
730
}
723
731
}
0 commit comments