11import * as vscode from "vscode" ;
22import { AtelierAPI } from "../api" ;
3- import { cspApps , currentWorkspaceFolder , notIsfs , uriOfWorkspaceFolder } from "../utils" ;
3+ import { cspApps , currentWorkspaceFolder , notIsfs , stringifyError , uriOfWorkspaceFolder } from "../utils" ;
44import { StudioActions , OtherStudioAction } from "../commands/studio" ;
55import { config , workspaceState } from "../extension" ;
66import { DocumentContentProvider } from "../providers/DocumentContentProvider" ;
77
8- type IconPath =
9- | string
10- | vscode . Uri
11- | {
12- light : string | vscode . Uri ;
13- dark : string | vscode . Uri ;
14- }
15- | vscode . ThemeIcon ;
16-
178interface NodeOptions {
189 extraNode ?: boolean ;
1910 generated ?: boolean ;
@@ -49,6 +40,8 @@ function getLeafNodeUri(node: NodeBase, forceServerCopy = false): vscode.Uri {
4940 }
5041}
5142
43+ const inactiveMsg = "Server connection is inactive" ;
44+
5245export class NodeBase {
5346 public readonly options : NodeOptions ;
5447 public readonly label : string ;
@@ -104,7 +97,7 @@ export class RootNode extends NodeBase {
10497 public readonly contextValue : string ;
10598 private readonly _category : string ;
10699 private readonly isCsp : boolean ;
107- private readonly iconPath : IconPath ;
100+ private readonly iconPath : vscode . ThemeIcon ;
108101
109102 public constructor (
110103 label : string ,
@@ -113,7 +106,7 @@ export class RootNode extends NodeBase {
113106 category : string ,
114107 options : NodeOptions ,
115108 isCsp = false ,
116- iconPath ?: IconPath
109+ iconPath ?: vscode . ThemeIcon
117110 ) {
118111 super ( label , fullName , options ) ;
119112 this . contextValue = contextValue ;
@@ -138,7 +131,51 @@ export class RootNode extends NodeBase {
138131
139132 public async getChildren ( element : NodeBase ) : Promise < NodeBase [ ] > {
140133 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+ ] ) ;
142179 }
143180
144181 public async getList (
@@ -180,6 +217,7 @@ export class RootNode extends NodeBase {
180217 const systemFiles = this . options . system || this . namespace === "%SYS" ? "1" : "0" ;
181218
182219 const api = new AtelierAPI ( this . workspaceFolder ) ;
220+ if ( ! api . active ) throw inactiveMsg ;
183221 api . setNamespace ( this . namespace ) ;
184222 if ( category == "CSP" && path == "" ) {
185223 // Use the results from the getCSPApps() API
@@ -219,43 +257,6 @@ export class RootNode extends NodeBase {
219257 }
220258 }
221259
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-
259260 public getItems4Export ( ) : Promise < string [ ] > {
260261 const path = this instanceof PackageNode || this . isCsp ? this . fullName + "/" : "" ;
261262 const cat = this . isCsp ? "CSP" : "ALL" ;
@@ -399,6 +400,7 @@ export class WorkspaceNode extends NodeBase {
399400 }
400401
401402 public async getChildren ( _element : NodeBase ) : Promise < NodeBase [ ] > {
403+ if ( ! new AtelierAPI ( this . workspaceFolder ) . active ) return [ new InactiveNode ( "" , "" , { } ) ] ;
402404 const children = [ ] ;
403405 let node : RootNode ;
404406
@@ -553,8 +555,9 @@ export class ProjectNode extends NodeBase {
553555}
554556
555557export class ProjectRootNode extends RootNode {
556- public getChildren ( element : NodeBase ) : Promise < NodeBase [ ] > {
558+ public async getChildren ( element : NodeBase ) : Promise < NodeBase [ ] > {
557559 const api = new AtelierAPI ( this . workspaceFolderUri ) ;
560+ if ( ! api . active ) return [ new InactiveNode ( "" , "" , { } ) ] ;
558561 api . setNamespace ( this . namespace ) ;
559562 let query : string ;
560563 let parameters : string [ ] ;
@@ -646,27 +649,27 @@ export class ProjectRootNode extends RootNode {
646649 }
647650 }
648651 } )
649- ) ;
652+ )
653+ . catch ( ( error ) => [ new ErrorNode ( stringifyError ( error ) , "" , { } ) ] ) ;
650654 }
651655 public getItems4Export ( ) : Promise < string [ ] > {
652656 return Promise . resolve ( [ ] ) ;
653657 }
654658}
655659
656- export class ProjectsServerNode extends NodeBase {
660+ export class ProjectsServerNsNode extends NodeBase {
657661 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 } ) ;
662665 this . eventEmitter = eventEmitter ;
663666 }
664667
665668 public getTreeItem ( ) : vscode . TreeItem {
666669 const { host, port, pathPrefix, serverName } = this . conn ;
667670 return {
668671 collapsibleState : vscode . TreeItemCollapsibleState . Expanded ,
669- contextValue : this . uniqueId ,
672+ contextValue : `projectsServerNsNode ${ this . extraNode ? ":extra" : "" } ` ,
670673 label : `${
671674 serverName && serverName . length ? serverName : `${ host } :${ port } ${ pathPrefix } `
672675 } :${ this . namespace . toUpperCase ( ) } `,
@@ -677,47 +680,52 @@ export class ProjectsServerNode extends NodeBase {
677680
678681 public async getChildren ( element : NodeBase ) : Promise < NodeBase [ ] > {
679682 const api = new AtelierAPI ( this . workspaceFolderUri ) ;
683+ if ( ! api . active ) return [ new InactiveNode ( "" , "" , { } ) ] ;
680684 api . setNamespace ( this . namespace ) ;
681685 return api
682686 . actionQuery ( "SELECT Name, Description FROM %Studio.Project" , [ ] )
683687 . then ( ( data ) =>
684688 data . result . content . map (
685689 ( project ) => new ProjectNode ( project . Name , { project : project . Name , ...this . options } , project . Description )
686690 )
687- ) ;
691+ )
692+ . catch ( ( error ) => [ new ErrorNode ( stringifyError ( error ) , "" , { } ) ] ) ;
688693 }
689694}
690695
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 ) ;
697700 }
698-
699701 public getTreeItem ( ) : vscode . TreeItem {
700- const { host, port, pathPrefix, serverName } = this . conn ;
701702 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" ) ) ,
709707 } ;
710708 }
709+ public getItems4Export ( ) : Promise < string [ ] > {
710+ return Promise . resolve ( [ ] ) ;
711+ }
712+ }
711713
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 ( [ ] ) ;
722730 }
723731}
0 commit comments