diff --git a/.gitignore b/.gitignore
index 3d73590..906cac3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
sc-list.txt
+.vscode/settings.json
diff --git a/MDX2JSON/AbstractREST.cls b/MDX2JSON/AbstractREST.cls
index f13c873..c9be0b7 100644
--- a/MDX2JSON/AbstractREST.cls
+++ b/MDX2JSON/AbstractREST.cls
@@ -28,7 +28,7 @@ ClassMethod OnPreDispatch(pUrl As %String, pMethod As %String, ByRef pContinue A
Set st = ..ConvertRequestBody()
If $$$ISERR(st) {
- Do ..Http500(st)
+ #; Do ..Http500(st)
Set pContinue = $$$NO
Quit st
}
@@ -37,9 +37,9 @@ ClassMethod OnPreDispatch(pUrl As %String, pMethod As %String, ByRef pContinue A
Set Namespace = %request.Get("Namespace", $namespace)
Set st = ..CheckNamespace(.Namespace)
If $$$ISERR(st) {
- Do ..Http500(st)
+ #; Do ..Http500(st)
Set pContinue = $$$NO
- Quit
+ Quit st
}
#; Dispatch
@@ -114,22 +114,6 @@ ClassMethod Login(skipheader As %Boolean = 1) As %Status
Return $$$OK
}
-/// Issue an '500' error and give some indication as to what occurred.
-/// pStatus - %status, not %Exception.AbstractException.
-ClassMethod Http500(pStatus As %Exception.AbstractException) As %Status
-{
- // we are expecting status
- #; Set the response Http status
- Set %response.Status="500 Internal Server Error"
-
- #; Skip duplicate calls
- Quit:$isObject(pStatus) $$$OK
-
- #; Return a helpful error string
- Write "{""Error"":"_$$$ZENJSSTR($System.Status.GetErrorText(pStatus,%session.Language))_"}"
-
- Quit $$$OK
-}
/// Returns info about MDX2JSON package mapping
ClassMethod GetMappings() As %ArrayOfObjects
diff --git a/MDX2JSON/Dashboard.cls b/MDX2JSON/Dashboard.cls
index 20f8156..1a9139f 100644
--- a/MDX2JSON/Dashboard.cls
+++ b/MDX2JSON/Dashboard.cls
@@ -96,6 +96,42 @@ ClassMethod WidgetsToProxyObject(Dashboard As %DeepSee.Dashboard.Definition, Out
return st
}
+
+/// A very specific method of displaying the data type for cube measures.
+/// Serves for the convenience of front-end development of the filter widget.
+/// The return is something like this %DeepSee.Time.DayMonthYear
+ClassMethod GetCubeMeasuresDataType(Widget, Number, CubeName, Output DataType As %String) As %Status
+{
+
+ set st = $$$OK
+ set dataSource = $piece(Widget.dataSource, ".", *) // get dataSource type
+ try{
+ if ((dataSource '= "kpi") && (dataSource '= "")){
+ if ($FIND(Widget.controls.GetAt(Number).targetProperty, "[") && $FIND(Widget.controls.GetAt(Number).targetProperty, ".")){
+ set tMeasure = $TRANSLATE(Widget.controls.GetAt(Number).targetProperty, "[]", "")
+
+ set st = ##class(%DeepSee.Utils).%GetDimensionInfo(CubeName,tMeasure,.pDimNo,.pHierNo,.pLevelNo) // get positional info about dimension
+
+ Set tMbrInfo = $G($$$DeepSeeMetaGLVN("cubes",$$$UPPER(CubeName),"mbr#",pDimNo,pHierNo,pLevelNo))
+ set DataType = $LG(tMbrInfo,6) // get data type
+ if '($FIND(DataType, "%")){ // if DataType return cube fact search for dataType in "star"
+ Set tMbrInfo = $G($$$DeepSeeMetaGLVN("cubes", $$$UPPER(CubeName), "star", DataType, "prop", $LG(tMbrInfo,7), "type"))
+ set DataType = tMbrInfo
+ }
+ }else{
+
+ set DataType = ""
+ }
+ }else{
+
+ set DataType = ""
+ }
+ }catch ex {
+ set st = ex.AsStatus()
+ }
+ return st
+}
+
/// Converts relevant parts of %DeepSee.Dashboard.Widget object into %ZEN.proxyObject.
ClassMethod WidgetToProxyObject(Widget As %DeepSee.Dashboard.Widget, CubeName As %String) As %ZEN.proxyObject [ Internal ]
{
@@ -108,13 +144,14 @@ ClassMethod WidgetToProxyObject(Widget As %DeepSee.Dashboard.Widget, CubeName As
// Linked widgets processing
set mdx = ""
set basemdx = ""
- set obj.Link = Widget.dataLink
+ set obj.dataLink = Widget.dataLink
}
// datasource is a kpi
if $piece(Widget.dataSource, ".", *) = "kpi" {
set kpiClass = ##class(%DeepSee.Utils).%GetKPIClass(Widget.dataSource)
set obj.kpitype = $classmethod(kpiClass, "%GetSourceType")
+ set obj.kpiclass = kpiClass // showing kpi class for implementing context menu button for kpi
}
@@ -253,6 +290,13 @@ ClassMethod WidgetControlToProxyObject(Widget As %DeepSee.Dashboard.Widget, Numb
set obj.label = ##class(%DeepSee.UserPortal.Utils).%ResolveText(obj.label)
set obj.source = Widget.name
+ set st = ..GetCubeMeasuresDataType(Widget,Number,CubeName,.fDataType)
+
+ if (st = $$$OK)
+ {
+ set obj.targetPropertyDataType = fDataType
+ }
+
set:(obj.target="") obj.target = Widget.name
if ($e(obj.value)="@") {
diff --git a/MDX2JSON/REST.cls b/MDX2JSON/REST.cls
index d478171..a39dae3 100644
--- a/MDX2JSON/REST.cls
+++ b/MDX2JSON/REST.cls
@@ -49,6 +49,7 @@ XData UrlMap
+
@@ -60,11 +61,16 @@ XData UrlMap
+
+
+
+
+
@@ -85,7 +91,6 @@ XData UrlMap
-
@@ -114,7 +119,7 @@ ClassMethod Test() As %Status
set obj.Status = "OK"
set obj.Embed = $g(^MDX2JSON.Embed, $g(^%MDX2JSON.Embed, ""))
set obj.User = $Username
- set obj.Version = "3.2.5"
+ set obj.Version = "3.2.38"
set obj.Parent = ##class(MDX2JSON.Tests).#LastCommit
set obj.ParentTS = ##class(MDX2JSON.Tests).#LastCommitTS
set obj.DefaultApp = $System.CSP.GetDefaultApp($Namespace)
@@ -132,6 +137,63 @@ ClassMethod Test() As %Status
return $$$OK
}
+ClassMethod deleteWidget() As %Status
+{
+ set name = $$$R("key")
+ set dashboardData = $$$R("Dashboard")
+
+ return ##class(MDX2JSON.Utils).DeleteWidget(name,dashboardData)
+}
+
+ClassMethod saveWidget() As %Status
+{
+ set key = $$$R("key")
+ set widgetData= $$$R("WidgetData")
+ set dashboardData = $$$R("Dashboard")
+
+ return ##class(MDX2JSON.Utils).AddWidget(widgetData,dashboardData,key)
+}
+
+
+/// Get all data sources including "pivot", "kpi", "worksheets","metrics"
+ClassMethod GetListDataSources(Source) As %Status
+{
+
+ set Source = $ZCONVERT($ZCONVERT(Source ,"I","URL") ,"I","UTF8")
+
+ if (Source = "pivot")
+ {
+ Set tSC = ##class(%DeepSee.Utils).%GetPivotListArray(.tParms,.pMetaData,.pData)
+
+ }
+ elseif (Source = "kpi")
+ {
+ Set tSC = ##class(%DeepSee.Utils).%GetKPIListArray(.tParms,.pMetaData,.pData)
+
+ }
+ elseif (Source = "worksheets")
+ {
+ Set tSC = ##class(%DeepSee.Utils).%GetWorksheetListArray(.tParms,.pMetaData,.pData)
+
+ }
+ elseif (Source = "metrics")
+ {
+ Set tSC = ##class(%DeepSee.Utils).%GetMetricListArray(.tParms,.pMetaData,.pData)
+
+ }
+
+ quit:$$$ISERR(tSC) tSC
+
+ Set tSC = ##class(%DeepSee.REST.v1.DataServer).%CreateObjectFromArray(.pData,pMetaData,.tSourceObj)
+
+ quit:$$$ISERR(tSC) tSC
+
+ do tSourceObj.%ToJSON()
+
+ quit tSC
+}
+
+
ClassMethod GetDataSource() As %Status
{
return ##class(MDX2JSON.Utils).GetDataSource($$$R("DataSource"))
@@ -220,6 +282,41 @@ ClassMethod WriteFiltersForDataSource() As %Status
return st
}
+///Execute requests from kpi
+ClassMethod KPIExecute() As %Status
+{
+ try{
+ set KPI = $$$R("KPI")
+ set Drillthrough = $$$R("Drillthrough")
+
+
+ if (Drillthrough = 1){
+ set SortOrder = $$$R("SortOrder")
+
+ if %request.Content.FILTERS
+ {
+ set Filters = $$$R("FILTERS")
+
+ }else{
+ set Filters = $$$R("Filters")
+ }
+
+ set SortColumn = $$$R("SortColumn")
+ set pSelection = SortColumn _ "," _ SortOrder
+
+ set st = ##class(MDX2JSON.Utils).WriteDrillthroughJSONKPI(KPI, Filters, pSelection)
+ }
+ else {
+ set st = ##class(%DeepSee.REST.v1.DataServer).WriteJSONfromKPI(KPI)
+ }
+
+ }catch ex {
+ set st=ex.AsStatus()
+ }
+
+ return st
+}
+
/// Wrapper for ##class(MDX2JSON.Utils).WriteJSONPfromMDX(pMDX)
/// Converts incoming request object and calls abovementioned method.
ClassMethod WriteJSONfromMDX() As %Status
@@ -324,12 +421,20 @@ ClassMethod WritePivotVariablesForCube(Cube As %String) As %Status
ClassMethod WriteAddons() As %Status
{
#dim sc As %Status = $$$OK
-
- set app = "/dsw"
+
+ set currentApp = $ZConvert($Get(%request.CgiEnvs("SCRIPT_NAME"), ""), "L")
+ set prefix = $piece(currentApp, "/mdx2json", 1)
+ set app = prefix _ "/dsw"
set path = $system.CSP.GetFileName(app _ "/")
set path = ##class(%File).NormalizeDirectory(path)
set path = ##class(%File).SubDirectoryName(path, "addons", $$$YES)
set url = app _ "/addons/"
+
+ // Check if path exists
+ if '##class(%File).Exists(path) {
+ set sc = $$$ERROR($$$GeneralError, "Addons directory does not exist: "_path_". Probably different prefixes for MDX2JSON and DSW applications.")
+ quit sc
+ }
#dim rs As %SQL.ClassQueryResultSet = ##class(%File).FileSetFunc(path, "*.js")
@@ -350,12 +455,20 @@ ClassMethod WriteThemes() As %Status
{
#dim sc As %Status = $$$OK
- set app = "/dsw"
+ set currentApp = $ZConvert($Get(%request.CgiEnvs("SCRIPT_NAME"), ""), "L")
+ set prefix = $piece(currentApp, "/mdx2json", 1)
+ set app = prefix _ "/dsw"
set path = $system.CSP.GetFileName(app _ "/")
set path = ##class(%File).NormalizeDirectory(path)
set path = ##class(%File).SubDirectoryName(path, "themes", $$$YES)
set url = app _ "/themes/"
+ // Check if path exists
+ if '##class(%File).Exists(path) {
+ set sc = $$$ERROR($$$GeneralError, "Themes directory does not exist: "_path_". Probably different prefixes for MDX2JSON and DSW applications.")
+ quit sc
+ }
+
#dim rs As %SQL.ClassQueryResultSet = ##class(%File).FileSetFunc(path, "*.css")
set list = $$$NewDynDTList
@@ -377,4 +490,4 @@ ClassMethod WriteJSONfromKPI() As %Status [ CodeMode = objectgenerator ]
do %code.Write(base)
}
-}
+}
\ No newline at end of file
diff --git a/MDX2JSON/ResultSet.cls b/MDX2JSON/ResultSet.cls
index 7f7db4b..210c64f 100644
--- a/MDX2JSON/ResultSet.cls
+++ b/MDX2JSON/ResultSet.cls
@@ -35,7 +35,7 @@ Method ToProxyObject(Output pStatus As %Status) As %ZEN.proxyObject
try {
set obj.Info = ..InfoToProxyObject() // basic info about cube and query
quit:obj.Info.percentDone<100
-
+
set obj.Cols = ..AxesToListOfObjects() // all axes
set obj.Data = ..DataToListOfDataTypes() // array of all cells, left-to-right, up-to-down
} catch ex {
@@ -79,7 +79,7 @@ Method InfoToProxyObject() As %ZEN.proxyObject
set info.numericGroupSeparator = ##class(%SYS.NLS.Format).GetFormatItem("NumericGroupSeparator")
set info.numericGroupSize = ##class(%SYS.NLS.Format).GetFormatItem("NumericGroupSize")
set info.decimalSeparator = ##class(%SYS.NLS.Format).GetFormatItem("DecimalSeparator")
-
+
return info
}
@@ -130,7 +130,7 @@ Method ProcessOneAxisCell(CubeIndex, AxisKey, CubeName, QueryKey, AxisNumber, No
set cell.vis = $LG(tNode,2) // visibility helper - does not help (apperently it shows if the cell is the lowest level)
// now we process cell children, if any exist
- if ($D($$$DeepSeeAxisGLVN(CubeIndex, AxisKey, "axes", Node, "ch")) = 10) {
+ if ($D($$$DeepSeeAxisGLVN(CubeIndex, AxisKey, "axes", Node, "ch")) = 10) && ($LG(tNode, 1)'="agg") {
set cell.children = $$$NewDynObjList
set key = $O($$$DeepSeeAxisGLVN(CubeIndex, AxisKey, "axes", Node, "ch", ""))
while (key'="") {
@@ -154,23 +154,23 @@ Method ProcessOneAxisCell(CubeIndex, AxisKey, CubeName, QueryKey, AxisNumber, No
if (..IsCellNull(cell, AxisNumber, Node)=1) {
return cell.children
}
-
+
try {
set cell.path = ##class(%DeepSee.Query.Engine).%GetSpecForAxisNode(CubeName, QueryKey, AxisNumber, Node) // MDX cell path
set:$e(cell.path)="(" cell.path = $e(cell.path, 2, *-1) // removing redundant parentheses
} catch ex {
set cell.path = "path too long"
}
-
+
set cell.format = $LG(tNode,12) // format for numbers, eg: $## ###.##
set cell.total = $LG(tNode,8) //COUNT,AVG function
set cell.type = $LG(tNode,1) // mbr,cmbr,lit,exp
set cell.valueID = $LG(tNode,6) // id in mdx dimension for mbr, path for cmbr
set cell.title = $LG(tNode,23)
-
+
set cell.headerStyle = $LG(tNode,19)
set cell.cellStyle = $LG(tNode,18)
-
+
set info = $LG(tNode,18)
if info'="" { // extract aggregation information, leave the rest as css
set summaryposition = $f(info,"summary")
@@ -181,7 +181,7 @@ Method ProcessOneAxisCell(CubeIndex, AxisKey, CubeName, QueryKey, AxisNumber, No
}
set cell.style = info // css
}
-
+
set tDimNo = $LG(tNode,9)
set tHierNo = $LG(tNode,10)
set tLevelNo = $LG(tNode,11)
@@ -190,7 +190,7 @@ Method ProcessOneAxisCell(CubeIndex, AxisKey, CubeName, QueryKey, AxisNumber, No
do ##class(%DeepSee.Utils).%GetDimensionCaption(CubeName,tDimNo, tHierNo,tLevelNo, .tAxisCaption)
set cell.dimension = tCaption // cube dimension taken from the name of the axes.
if (cell.dimension = "") {set cell.dimension = tCaption} // hack for assigne dimension property in case of empty dimension
-
+
set:$$$Debug cell.visible = '..IsCellNull(cell,AxisNumber,Node)
set:$$$Debug cell.node = Node
diff --git a/MDX2JSON/Utils.cls b/MDX2JSON/Utils.cls
index 806010d..835322d 100644
--- a/MDX2JSON/Utils.cls
+++ b/MDX2JSON/Utils.cls
@@ -53,21 +53,65 @@ ClassMethod ExecuteResultSet(RS As MDX2JSON.ResultSet, QueryKey As %String = "",
quit Status
}
+ClassMethod QuerySet(MDX) As %Status
+{
+ set ^Query($I(^Query), "%dsQuery") = MDX
+}
+
/// Automatic processing of MDX query and outputting resulting JSON.
/// MDX - String containing MDX query.
ClassMethod WriteJSONfromMDX(MDX As %String, Timeout As %Integer = 0) As %Status
{
+ Set tSC = $$$OK
#dim RS As MDX2JSON.ResultSet
- set RS = ..GetResultSet(MDX, .st)
- return:$$$ISERR(st) st
+
+ set RS = ..GetResultSet(MDX, .tSC)
+ set cube = ##class(%DeepSee.Utils).%IsCubeCompound(RS.%Cube) // check if cube is compound type
+ return:$$$ISERR(tSC) tSC
+
+ if cube // if cube is compound then we prepare it using %ZEN.Auxiliary.jsonMDXProvider
+ {
+ Set tProvider = ##class(%ZEN.Auxiliary.jsonMDXProvider).%New()
+ Set tProvider.mdxQuery = MDX
+ Set tWait = %session.AppTimeout - $S(%session.AppTimeout>2:2,1:0) // Send something back jst before the appTimeout is reached
+ Set tSC = ##class(%DeepSee.REST.v1.DataServer).%WaitForProviderResults(tProvider,tWait)
- set st = ..ExecuteResultSet(RS, , Timeout)
- return:$$$ISERR(st) st
+ set tSC = ..ExecuteResultSet(RS, ,Timeout)
+ return:$$$ISERR(tSC) tSC
- set obj = RS.ToProxyObject(.st)
- return:$$$ISERR(st) st
- $$$DynObjToJSON(obj)
+ set obj = RS.ToProxyObject(.tSC)
+ return:$$$ISERR(tSC) tSC
+
+ set %dsQuery = MDX
+
+ // initiate an RS object to a global variable %dsResultSet
+ set %dsResultSet = RS
+
+ set %dsCubeName = RS.%Cube
+
+ // check if audit global hold something and execute it
+ try {xecute ^DeepSee.AuditQueryCode} catch {}
+
+ $$$DynObjToJSON(obj)
+ }else{ // if cube is not compound execute the query in usual way
+
+ set tSC = ..ExecuteResultSet(RS, ,Timeout)
+ return:$$$ISERR(tSC) tSC
+
+ set obj = RS.ToProxyObject(.tSC)
+ return:$$$ISERR(tSC) tSC
+
+ set %dsQuery = MDX
+ set %dsResultSet = RS
+
+ // check if audit global hold something and execute it
+ try {xecute ^DeepSee.AuditQueryCode} catch {}
+
+ $$$DynObjToJSON(obj)
+ }
+
+
return $$$OK
}
@@ -89,6 +133,92 @@ ClassMethod WriteJSONfromQuery(CubeKey As %String, QueryKey As %String, Timeout
return $$$OK
}
+/// Execute SQL query taken from KPI and extract column values by name of column
+/// Output array with list of values like so pValue(n) = $LB(sNameList(i)...)
+ClassMethod GetSQLValues(pSQL, Output pValues As %String, Output tResultSet As %SQL.Statement) As %Status
+{
+
+ set st = $$$OK
+ Set tResultSet = ##class(%SQL.Statement).%ExecDirect(,pSQL)
+ set tCount = 0
+
+ while tResultSet.%Next()
+ {
+ set lValue = ""
+ for i=1:1:tResultSet.%GetMetadata().columnCount
+ {
+ set sNameList(i) = tResultSet.%GetMetadata().columns.GetAt(i).label
+ set lValue = lValue _ $lb(tResultSet.%Get(sNameList(i))) // append next column to the list
+ }
+
+ Set tCount = tCount + 1
+ set pValues(tCount) = lValue
+ }
+ return st
+}
+
+/// This method provides listing execution for KPI.
+/// tKPI as a name of KPI class. pFilters not yet implemented
+/// as a pSelection. Thats for future use.
+ClassMethod WriteDrillthroughJSONKPI(tKPI As %String, pFilters As %String, pSelection As %String) As %Status
+{
+
+ Set st = $$$OK
+
+ Set tKpiClassName = ##class(%DeepSee.Utils).%GetKPIClass(tKPI,.tSC) // get name of a kpi from REST
+ set kpitype = $classmethod(tKpiClassName, "%GetSourceType")
+
+ if (kpitype="sql") {
+ set pSQL = $classmethod(tKpiClassName,"%OnGetListingSQL",pFilters,pSelection) // invoke corresponding method from given kpi and get sql query
+ set values = ..GetSQLValues(pSQL, .pValue, .tResultSet)
+
+ for i=1:1:tResultSet.%GetMetadata().columnCount
+ {
+ set pList(i) = tResultSet.%GetMetadata().columns.GetAt(i).label
+ set pList(i, "columnNo") = i
+ Set tKpiPropIdx = $O(pList(""),1,tProperty)
+ Set tKpiPropList = ""
+ While (tKpiPropIdx'="") {
+ Set tKpiPropList = tKpiPropList _ $LB(tProperty)
+ Set tKpiPropArray(tKpiPropIdx) = $LB(tProperty,$G(pList(tKpiPropIdx,"name")),$G(pList(tKpiPropIdx,"columnNo")))
+ Set tKpiPropIdx = $O(pList(tKpiPropIdx),1,tProperty)
+
+ }
+
+ }
+ Set tKpiSC = $classmethod(tKpiClassName,"%GetKPIValueArray",tKpiClassName,,.tKpiPropList,.tFilters)
+
+ Set tSC = ##class(%DeepSee.REST.v1.DataServer).%CreateObjectFromArray(.pValue,tKpiPropList,.tValueObj)
+ If $$$ISERR(tSC) Quit
+
+ Set tSC = ##class(%DeepSee.REST.v1.DataServer).%CreateObjectFromArray(.tKpiPropArray,$LB("name","caption","columnNo"),.tPropObj)
+ If $$$ISERR(tSC)
+
+ // Use consistent objects for normalized return
+ Set tProvider = ##class(%ZEN.Auxiliary.jsonMDXProvider).%New()
+ Set tInfoObj = tProvider.%ConstructNewDynamicObject()
+ Set tResultObj = tProvider.%ConstructNewDynamicObject()
+
+ Set:$IsObject(tPropObj.children) tResultObj.Properties = tPropObj.children
+ Set:$IsObject(tValueObj.children) tResultObj.Series = tValueObj.children
+
+ Set tInfoObj.Error = tProvider.%StatusToDynamicObject(tKpiSC)
+ Set tInfoObj.KpiName = tKpiClassName
+
+ Set tKpiObj = tProvider.%ConstructNewDynamicObject()
+ Set tKpiObj.Info = tInfoObj
+ Set tKpiObj.Result = tResultObj
+
+ Set tSC = tProvider.%ObjectToJSON(tKpiObj)
+
+ }else{
+
+ quit $$$ERROR($$$GeneralError, "KPI type " _ kpitype _ " not supported")
+ }
+
+ return st
+}
+
/// Automatic processing of MDX query and outputting resulting JSONP.
/// pMDX - String containing MDX query.
ClassMethod WriteJSONPfromMDX(pMDX As %String) As %Status
@@ -128,7 +258,25 @@ ClassMethod WriteDrillthroughJSON(pMDX As %String) As %Status
return:$$$ISERR(st) st
set SQL = RS.%GetListingSQL()
- do ##class(%ZEN.Auxiliary.altJSONSQLProvider).%WriteJSONFromSQL(,SQL,,$$$MaxCacheInt)
+
+ set rs = ##class(%SQL.Statement).%ExecDirect(, SQL)
+ set list = []
+
+ while rs.%Next() {
+ set row = {}
+ for i=1:1:rs.%ResultColumnCount {
+ set colName = rs.%GetMetadata().columns.GetAt(i).colName
+ set colValue = rs.%GetData(i)
+ do row.%Set(colName, colValue)
+ }
+ do list.%Push(row)
+ }
+
+ set result = {
+ "children": (list)
+ }
+
+ do result.%ToJSON(.stream)
return $$$OK
}
@@ -202,8 +350,8 @@ ClassMethod GetDataSource(pDataSource As %String)
set st = $$$OK
try {
-
- if ($FIND(pDataSource, ".pivot") = ($LENGTH(pDataSource) + 1)) {
+
+ if ($FIND(pDataSource, ".pivot") = ($LENGTH(pDataSource) + 1) && pDataSource '="") {
set st = ..OpenPivotByName(pDataSource, .dataSource)
return:($$$ISERR(st)) st
@@ -215,6 +363,7 @@ ClassMethod GetDataSource(pDataSource As %String)
set st = ##class(%ZEN.Auxiliary.jsonProvider).%ObjectToJSON(dataSource, .out)
}
+
} catch ex {
set st = ex.AsStatus()
@@ -302,12 +451,19 @@ ClassMethod GetWidgetsList(pDashName As %String) As %Status
ClassMethod GetDashboard(pDashName As %String) As %Status
{
try {
+
set st = ##class(MDX2JSON.DashboardFilters).OpenDashboardByName(pDashName, .dash)
return:($$$ISERR(st)) st
set st = ##class(MDX2JSON.DashboardFilters).WidgetsToProxyObject(dash, .widgetlist)
return:($$$ISERR(st)) st
w "" // weird hack required for 15.3
+
+ set %dsDashboard = pDashName
+
+ // check if audit global hold something and execute it
+ try {xecute ^DeepSee.AuditCode} catch {}
+
$$$DynObjToJSON(widgetlist)
} catch ex {
set st = ex.AsStatus()
@@ -316,6 +472,42 @@ ClassMethod GetDashboard(pDashName As %String) As %Status
return st
}
+/// the method initiate the audit for %dsDashboard
+ClassMethod SetAuditCode() As %Status
+{
+ set ^DeepSee.AuditCode = "Do ##class(MDX2JSON.Utils).SetAuditDash()"
+
+ quit $$$OK
+}
+
+/// the method initiate the audit for %dsQueryText, %dsCubeName, %dsResultSet
+ClassMethod SetAuditQueryCode() As %Status
+{
+ set ^DeepSee.AuditQueryCode = "Do ##class(MDX2JSON.Utils).SetAuditQuery()"
+
+ quit $$$OK
+}
+
+/// zw ^AuditLogDash to get the dashboard audit dashboard readings
+ClassMethod SetAuditDash() As %Status
+{
+ set ^AuditLogDash($INCREMENT(^AuditLogDash),"%dsDashoard") = %dsDashboard
+
+ quit $$$OK
+}
+
+/// zw ^AuditLogQuery to get the query audit readings
+/// zw ^AuditLogCube to get the cube audit readings
+/// zw ^AuditLogRS to get the RS audit readings
+ClassMethod SetAuditQuery() As %Status
+{
+ set ^AuditLogQuery($INCREMENT(^AuditLogQuery),"%dsQueryText") = %dsQueryText
+ set ^AuditLogCube($INCREMENT(^AuditLogQuery),"%dsCubeName") = %dsCubeName
+ set ^AuditLogRS($INCREMENT(^AuditLogRS),"%dsResultSet") = %dsResultSet
+
+ quit $$$OK
+}
+
/// Get format defaults.
ClassMethod GetFormat() As %Status
{
@@ -450,4 +642,162 @@ ClassMethod CreateAddonClass(Class As %Dictionary.CacheClassname) As %Status
quit classObj.%Save()
}
+/// Add new widgets and edit existing ones directly from DeepSeeWeb
+/// it takes widget name(key) as unique identifier as string, dashboard name as string
+/// and object with parameters as zen.proxyObject
+ClassMethod AddWidget(sWidget As %String, sDashboard As %String, key As %String) As %Status
+{
+ set st = $$$OK
+ set dExist=##class(%DeepSee.Dashboard.Utils).%DashboardExists(sDashboard)
+
+ // Check if dashboard exists
+ If (dExist '= 1)
+ {
+ Quit $$$ERROR($$$GeneralError,"Dashboard " _ sDashboard _ " does not exists")
+ }
+ Set tDash=##class(%DeepSee.Dashboard.Utils).%OpenDashboard(sDashboard, .st)
+
+ // Check if widget with name is exists
+ set isExists = 0
+ for i=1:1:tDash.widgets.Count()
+ {
+ if (tDash.widgets.GetAt(i).name = sWidget.name)
+ {
+ set isExists = 1
+ }
+ }
+
+ // Adding new widget
+ if ($LENGTH(key) = 0) { // if key received empty then we expect new widget if not then else logic is working
+ // Check if we trying to create widget with exists name
+ if (isExists = 1) {
+ return $$$ERROR($$$GeneralError,"Widget " _ sWidget.name _ " already exists")
+ }
+
+ set tWidgets = ##class(%DeepSee.Dashboard.Widget).%New()
+ set st = ..UpdateWidget(tWidgets, sWidget)
+
+ if (st = $$$OK) // checking for errors in UpdateWidget
+ {
+ $$$Insert(tDash.widgets, tWidgets)
+ do tDash.%Save()
+ }
+
+ } else {
+ // Edit exists widget
+ for i=1:1:tDash.widgets.Count()
+ {
+
+ set dWidgets = tDash.widgets.GetAt(i)
+
+ // Check if we trying to change widget name with exists one
+ if ((dWidgets.name '= key) && (dWidgets.name = sWidget.name)) {
+ return $$$ERROR($$$GeneralError,"Widget " _ sWidget.name _ " already exists")
+
+ }
+
+ if (dWidgets.name = key)
+ {
+ set changed = dWidgets
+ }
+ }
+ if (changed '= "") {
+ set st = ..UpdateWidget(changed, sWidget)
+ if (st = $$$OK) // checking for errors in UpdateWidget
+ {
+ do tDash.%Save()
+ }
+ }
+ }
+
+ return st
+}
+
+/// This method remove widget from dashboard directly from DeepSeeWeb
+/// it takes widget name as unique identifier and dashboard name
+ClassMethod DeleteWidget(wName As %String, sDashboard As %String) As %Status
+{
+ set st = $$$OK
+
+ set dExist=##class(%DeepSee.Dashboard.Utils).%DashboardExists(sDashboard)
+
+ // Check if dashboard exists
+ If (dExist '= 1)
+ {
+ Quit $$$ERROR($$$GeneralError,"Dashboard " _ sDashboard _ " does not exists")
+ }
+ Set tDash=##class(%DeepSee.Dashboard.Utils).%OpenDashboard(sDashboard, .st)
+
+ // Check if widget with name is exists
+ set isExists = 0
+ for i=1:1:tDash.widgets.Count()
+ {
+ if (tDash.widgets.GetAt(i).name = wName)
+ {
+ set isExists = 1
+ }
+ }
+
+ if (isExists = 1)
+ {
+ for i=1:1:tDash.widgets.Count()
+ {
+ if (tDash.widgets.GetAt(i).name = wName)
+ {
+ do tDash.widgets.RemoveAt(i)
+ do tDash.%Save()
+ }
+ }
+ }else
+ {
+ quit $$$ERROR($$$GeneralError,"Widget " _ wName _ " is not exists")
+
+ }
+
+ return st
}
+
+/// the collection of necessary parameters for building widget
+ClassMethod UpdateWidget(widgetToUpdate As %DeepSee.Dashboard.Widget, data As %ZEN.proxyObject) As %Status
+{
+ set st = $$$OK
+
+ set widgetToUpdate.name = data.name
+ set widgetToUpdate.title = data.title
+ if (data.dataSource = "")
+ {
+ quit $$$ERROR($$$GeneralError,"Parameter DataSource is not set")
+ }else
+ {
+ set widgetToUpdate.dataSource = data.dataSource
+ }
+
+ set widgetToUpdate.dataLink = data.dataLink
+
+ if (data.type = "pivot")
+ {
+ set widgetToUpdate.type = "pivot"
+ set widgetToUpdate.subtype = "pivot"
+ }
+ elseif (data.type '= "pivot")
+ {
+ set widgetToUpdate.type = "pivot"
+ set widgetToUpdate.subtype = data.type
+ }
+
+ if (data.displayInfo '= "") {
+ set widgetToUpdate.top = data.displayInfo.top
+ set widgetToUpdate.left = data.displayInfo.left
+ set widgetToUpdate.width = data.displayInfo.width
+ set widgetToUpdate.height = data.displayInfo.height
+ set widgetToUpdate.homeColL = data.displayInfo.topCol
+ set widgetToUpdate.homeRowL = data.displayInfo.leftRow
+ set widgetToUpdate.colSpanL = data.displayInfo.colWidth
+ set widgetToUpdate.rowSpanL = data.displayInfo.rowHeight
+ }
+
+ return st
+}
+
+}
+
diff --git a/module.xml b/module.xml
index 73b27b1..421185b 100644
--- a/module.xml
+++ b/module.xml
@@ -2,7 +2,7 @@
MDX2JSON
- 3.2.18
+ 3.2.50
RESTful web api for MDX to JSON transformation (plus JSONP and XML/A) for InterSystems IRIS. Also provides information about DeepSee objects.
module
./