@@ -15,6 +15,7 @@ interface InputBoxStepOptions {
1515 type : "inputBox" ;
1616 title : string ;
1717 placeholder ?: string ;
18+ prompt ?: string ;
1819 validateInput ?( value : string ) : string | undefined | Promise < string | undefined > ;
1920}
2021
@@ -50,6 +51,7 @@ async function multiStepInput(steps: InputStepOptions[]): Promise<string[] | und
5051 inputBox . totalSteps = steps . length ;
5152 inputBox . buttons = step > 0 ? [ vscode . QuickInputButtons . Back ] : [ ] ;
5253 inputBox . placeholder = stepOptions . placeholder ;
54+ inputBox . prompt = stepOptions . prompt ;
5355 inputBox . title = stepOptions . title ;
5456 if ( results [ step ] != undefined ) {
5557 // Restore the past input
@@ -221,6 +223,7 @@ export enum NewFileType {
221223 BPL = "Business Process" ,
222224 DTL = "Data Transformation" ,
223225 Rule = "Business Rule" ,
226+ KPI = "Business Intelligence KPI" ,
224227}
225228
226229interface RuleAssistClasses {
@@ -264,16 +267,18 @@ export async function newFile(type: NewFileType): Promise<void> {
264267 api = undefined ;
265268 }
266269
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+ }
277282 }
278283
279284 const inputSteps : InputStepOptions [ ] = [ ] ;
@@ -282,6 +287,7 @@ export async function newFile(type: NewFileType): Promise<void> {
282287 let classes : string [ ] = [ ] ;
283288 let ruleAssists : RuleAssistClasses = { } ;
284289 let dtlClassQPItems : vscode . QuickPickItem [ ] = [ ] ;
290+ let serverResources : vscode . QuickPickItem [ ] = [ ] ;
285291 if ( api ) {
286292 const classesPromise : Promise < string [ ] > = api
287293 . actionQuery ( "SELECT Name FROM %Dictionary.ClassDefinition" , [ ] )
@@ -377,6 +383,20 @@ export async function newFile(type: NewFileType): Promise<void> {
377383 } ) ,
378384 classesPromise ,
379385 ] ) ;
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 ) ;
380400 } else {
381401 // Get a list of classes on the server to validate the name
382402 classes = await classesPromise ;
@@ -466,7 +486,7 @@ Parameter INVOCATION = "${invocation}";
466486/// for tips on how to implement operation methods.
467487Method SampleCall(pRequest As Ens.Request, Output pResponse As Ens.Response) As %Status
468488{
469- Quit $$$ERROR($$$NotImplemented)
489+ Return $$$ERROR($$$NotImplemented)
470490}
471491
472492XData MessageMap
@@ -508,7 +528,7 @@ Parameter ADAPTER = "${adapter}";
508528/// for tips on how to implement this method.
509529Method OnProcessInput(pInput As %RegisteredObject, pOutput As %RegisteredObject) As %Status
510530{
511- Quit $$$ERROR($$$NotImplemented)
531+ Return $$$ERROR($$$NotImplemented)
512532}
513533
514534}
@@ -572,7 +592,7 @@ Class ${cls} Extends Ens.BusinessProcess [ ClassType = persistent ]
572592/// for tips on how to implement this method.
573593Method OnRequest(pRequest As Ens.Request, Output pResponse As Ens.Response) As %Status
574594{
575- Quit $$$ERROR($$$NotImplemented)
595+ Return $$$ERROR($$$NotImplemented)
576596}
577597
578598}
@@ -667,7 +687,7 @@ Class ${cls} Extends Ens.DataTransform
667687/// for tips on how to implement this method.
668688ClassMethod Transform(source As ${ sourceCls } , ByRef target As ${ targetCls } ) As %Status
669689{
670- Quit $$$ERROR($$$NotImplemented)
690+ Return $$$ERROR($$$NotImplemented)
671691}
672692
673693}
@@ -749,6 +769,81 @@ XData RuleDefinition [ XMLNamespace = "http://www.intersystems.com/rule" ]
749769</ruleDefinition>
750770}
751771
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+
752847}
753848` ;
754849 }
0 commit comments