@@ -15,6 +15,7 @@ interface InputBoxStepOptions {
15
15
type : "inputBox" ;
16
16
title : string ;
17
17
placeholder ?: string ;
18
+ prompt ?: string ;
18
19
validateInput ?( value : string ) : string | undefined | Promise < string | undefined > ;
19
20
}
20
21
@@ -50,6 +51,7 @@ async function multiStepInput(steps: InputStepOptions[]): Promise<string[] | und
50
51
inputBox . totalSteps = steps . length ;
51
52
inputBox . buttons = step > 0 ? [ vscode . QuickInputButtons . Back ] : [ ] ;
52
53
inputBox . placeholder = stepOptions . placeholder ;
54
+ inputBox . prompt = stepOptions . prompt ;
53
55
inputBox . title = stepOptions . title ;
54
56
if ( results [ step ] != undefined ) {
55
57
// Restore the past input
@@ -221,6 +223,7 @@ export enum NewFileType {
221
223
BPL = "Business Process" ,
222
224
DTL = "Data Transformation" ,
223
225
Rule = "Business Rule" ,
226
+ KPI = "Business Intelligence KPI" ,
224
227
}
225
228
226
229
interface RuleAssistClasses {
@@ -264,16 +267,18 @@ export async function newFile(type: NewFileType): Promise<void> {
264
267
api = undefined ;
265
268
}
266
269
267
- // Check if we're connected to an Interoperability namespace
268
- const ensemble : boolean = api
269
- ? await api . getNamespace ( ) . then ( ( data ) => data . result . content . features [ 0 ] . enabled )
270
- : true ;
271
- if ( ! ensemble ) {
272
- vscode . window . showErrorMessage (
273
- `Workspace folder '${ wsFolder . name } ' is not connected to an Interoperability namespace.` ,
274
- "Dismiss"
275
- ) ;
276
- return ;
270
+ if ( type != NewFileType . KPI ) {
271
+ // Check if we're connected to an Interoperability namespace
272
+ const ensemble : boolean = api
273
+ ? await api . getNamespace ( ) . then ( ( data ) => data . result . content . features [ 0 ] . enabled )
274
+ : true ;
275
+ if ( ! ensemble ) {
276
+ vscode . window . showErrorMessage (
277
+ `Workspace folder '${ wsFolder . name } ' is not connected to an Interoperability namespace.` ,
278
+ "Dismiss"
279
+ ) ;
280
+ return ;
281
+ }
277
282
}
278
283
279
284
const inputSteps : InputStepOptions [ ] = [ ] ;
@@ -282,6 +287,7 @@ export async function newFile(type: NewFileType): Promise<void> {
282
287
let classes : string [ ] = [ ] ;
283
288
let ruleAssists : RuleAssistClasses = { } ;
284
289
let dtlClassQPItems : vscode . QuickPickItem [ ] = [ ] ;
290
+ let serverResources : vscode . QuickPickItem [ ] = [ ] ;
285
291
if ( api ) {
286
292
const classesPromise : Promise < string [ ] > = api
287
293
. actionQuery ( "SELECT Name FROM %Dictionary.ClassDefinition" , [ ] )
@@ -377,6 +383,20 @@ export async function newFile(type: NewFileType): Promise<void> {
377
383
} ) ,
378
384
classesPromise ,
379
385
] ) ;
386
+ } else if ( type == NewFileType . KPI ) {
387
+ // Get a list of classes on the server to validate the name
388
+ classes = await classesPromise ;
389
+ // Get a list of server resources
390
+ const originalNs = api . ns ;
391
+ api . setNamespace ( "%SYS" ) ;
392
+ serverResources = await api
393
+ . actionQuery (
394
+ "SELECT Name AS label, Description AS detail, 'Public Permission: '||PublicPermission AS description FROM Security.Resources_List()" ,
395
+ [ ]
396
+ )
397
+ . then ( ( data ) => data . result . content )
398
+ . catch ( ( ) => [ ] ) ;
399
+ api . setNamespace ( originalNs ) ;
380
400
} else {
381
401
// Get a list of classes on the server to validate the name
382
402
classes = await classesPromise ;
@@ -466,7 +486,7 @@ Parameter INVOCATION = "${invocation}";
466
486
/// for tips on how to implement operation methods.
467
487
Method SampleCall(pRequest As Ens.Request, Output pResponse As Ens.Response) As %Status
468
488
{
469
- Quit $$$ERROR($$$NotImplemented)
489
+ Return $$$ERROR($$$NotImplemented)
470
490
}
471
491
472
492
XData MessageMap
@@ -508,7 +528,7 @@ Parameter ADAPTER = "${adapter}";
508
528
/// for tips on how to implement this method.
509
529
Method OnProcessInput(pInput As %RegisteredObject, pOutput As %RegisteredObject) As %Status
510
530
{
511
- Quit $$$ERROR($$$NotImplemented)
531
+ Return $$$ERROR($$$NotImplemented)
512
532
}
513
533
514
534
}
@@ -572,7 +592,7 @@ Class ${cls} Extends Ens.BusinessProcess [ ClassType = persistent ]
572
592
/// for tips on how to implement this method.
573
593
Method OnRequest(pRequest As Ens.Request, Output pResponse As Ens.Response) As %Status
574
594
{
575
- Quit $$$ERROR($$$NotImplemented)
595
+ Return $$$ERROR($$$NotImplemented)
576
596
}
577
597
578
598
}
@@ -667,7 +687,7 @@ Class ${cls} Extends Ens.DataTransform
667
687
/// for tips on how to implement this method.
668
688
ClassMethod Transform(source As ${ sourceCls } , ByRef target As ${ targetCls } ) As %Status
669
689
{
670
- Quit $$$ERROR($$$NotImplemented)
690
+ Return $$$ERROR($$$NotImplemented)
671
691
}
672
692
673
693
}
@@ -749,6 +769,81 @@ XData RuleDefinition [ XMLNamespace = "http://www.intersystems.com/rule" ]
749
769
</ruleDefinition>
750
770
}
751
771
772
+ }
773
+ ` ;
774
+ } else if ( type == NewFileType . KPI ) {
775
+ // Create the prompt for the name, domain, resource, and type
776
+ inputSteps . push (
777
+ {
778
+ type : "inputBox" ,
779
+ title : "Name" ,
780
+ placeholder : "MyFolder/MyKPI" ,
781
+ prompt : "Logical name of the KPI." ,
782
+ } ,
783
+ {
784
+ type : "inputBox" ,
785
+ title : "Domain" ,
786
+ prompt : "Localization domain to which this KPI belongs." ,
787
+ } ,
788
+ serverResources . length
789
+ ? {
790
+ type : "quickPick" ,
791
+ title : "Resource" ,
792
+ items : serverResources ,
793
+ }
794
+ : {
795
+ type : "inputBox" ,
796
+ title : "Resource" ,
797
+ prompt : "Resource that secures this KPI." ,
798
+ } ,
799
+ {
800
+ type : "quickPick" ,
801
+ title : "Source Type" ,
802
+ items : [ { label : "mdx" } , { label : "sql" } , { label : "manual" } ] ,
803
+ }
804
+ ) ;
805
+
806
+ // Prompt the user
807
+ const results = await multiStepInput ( inputSteps ) ;
808
+ if ( ! results ) {
809
+ return ;
810
+ }
811
+ cls = results [ 0 ] ;
812
+ const [ , desc , kpiName , kpiDomain , kpiResource , kpiType ] = results ;
813
+
814
+ // Generate the file's content
815
+ clsContent = `
816
+ ${ typeof desc == "string" ? "/// " + desc . replace ( / \n / g, "\n/// " ) : "" }
817
+ Class ${ cls } Extends %DeepSee.KPI
818
+ {
819
+
820
+ Parameter DOMAIN = "${ kpiDomain } ";
821
+
822
+ Parameter RESOURCE = "${ kpiResource } ";
823
+
824
+ /// This XData definition defines the KPI.
825
+ XData KPI [ XMLNamespace = "http://www.intersystems.com/deepsee/kpi" ]
826
+ {
827
+ <kpi xmlns="http://www.intersystems.com/deepsee/kpi" name="${ kpiName } " sourceType="${ kpiType } " >
828
+ </kpi>
829
+ }
830
+
831
+ /// Notification that this KPI is being executed.
832
+ /// This is a good place to override properties, such as range and threshold.
833
+ Method %OnLoadKPI() As %Status
834
+ {
835
+ Return $$$OK
836
+ }
837
+
838
+ /// This callback is invoked from a dashboard when an action defined by this dashboard is invoked.
839
+ ClassMethod %OnDashboardAction(pAction As %String, pContext As %ZEN.proxyObject) As %Status
840
+ {
841
+ #; pAction is the name of the action (as defined in the XML list).
842
+ #; pContext contains information from the client
843
+ #; and can be used to return information.
844
+ Return $$$OK
845
+ }
846
+
752
847
}
753
848
` ;
754
849
}
0 commit comments