From 4f6b0b9a3f73f1d31d10184e90a8e4c0b7c2ef74 Mon Sep 17 00:00:00 2001 From: Frisle <47441164+Frisle@users.noreply.github.com> Date: Wed, 5 Apr 2023 14:23:46 +0600 Subject: [PATCH 01/77] ADD: new method to execute KPI Add method to execute listing and display KPI data --- MDX2JSON/REST.cls | 29 ++++++++++++++++++++++++++++- MDX2JSON/Utils.cls | 22 ++++++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/MDX2JSON/REST.cls b/MDX2JSON/REST.cls index d478171..e0998eb 100644 --- a/MDX2JSON/REST.cls +++ b/MDX2JSON/REST.cls @@ -49,6 +49,7 @@ XData UrlMap + @@ -85,7 +86,6 @@ XData UrlMap - @@ -220,6 +220,33 @@ 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") + 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 diff --git a/MDX2JSON/Utils.cls b/MDX2JSON/Utils.cls index 806010d..60c3b11 100644 --- a/MDX2JSON/Utils.cls +++ b/MDX2JSON/Utils.cls @@ -89,6 +89,28 @@ ClassMethod WriteJSONfromQuery(CubeKey As %String, QueryKey As %String, Timeout return $$$OK } +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 + + }else{ + + quit $$$ERROR($$$GeneralError, "KPI type " _ kpitype _ " not supported") + } + + set st = ##class(%ZEN.Auxiliary.altJSONSQLProvider).%WriteJSONFromSQL(,pSQL,,$$$MaxCacheInt) // receiving sql and process it + return:$$$ISERR(st) st + + return st +} + /// Automatic processing of MDX query and outputting resulting JSONP.
/// pMDX - String containing MDX query.
ClassMethod WriteJSONPfromMDX(pMDX As %String) As %Status From 352f321bf1e5d6e04a094ea812c71752fe87b7ee Mon Sep 17 00:00:00 2001 From: ProjectBot Date: Wed, 5 Apr 2023 08:35:17 +0000 Subject: [PATCH 02/77] auto bump version --- module.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module.xml b/module.xml index 73b27b1..ddfdd6f 100644 --- a/module.xml +++ b/module.xml @@ -2,7 +2,7 @@ MDX2JSON - 3.2.18 + 3.2.19 RESTful web api for MDX to JSON transformation (plus JSONP and XML/A) for InterSystems IRIS. Also provides information about DeepSee objects. module ./ From c8282a129f2ea1c7ebb6a2b0a4dd037bfc2eb28f Mon Sep 17 00:00:00 2001 From: Dmitrij Vladimirov <47441164+Frisle@users.noreply.github.com> Date: Thu, 13 Apr 2023 18:28:28 +0600 Subject: [PATCH 03/77] ADD: New method to get dimension data type Method get data type for time measure. If measure is not time kind of measure it shows fact table(?). Method tested on other widgets. --- MDX2JSON/Dashboard.cls | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/MDX2JSON/Dashboard.cls b/MDX2JSON/Dashboard.cls index 20f8156..1094834 100644 --- a/MDX2JSON/Dashboard.cls +++ b/MDX2JSON/Dashboard.cls @@ -96,6 +96,39 @@ 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 obj = $$$NewDynObj + set st = Widget.controls.GetAt(Number).%CopyTo(obj) // copy widget control properties to proxyObj + set dataSource = $piece(Widget.dataSource, ".", *) // get dataSource type + + + if (dataSource '= "kpi"){ + if ($FIND(obj.targetProperty, "[")){ + set tMeasure = $TRANSLATE(obj.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 + }else{ + + set DataType = "" + } + }else{ + + set DataType = "" + } + + 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 ] { @@ -253,6 +286,9 @@ ClassMethod WidgetControlToProxyObject(Widget As %DeepSee.Dashboard.Widget, Numb set obj.label = ##class(%DeepSee.UserPortal.Utils).%ResolveText(obj.label) set obj.source = Widget.name + set filterDataType = ..GetCubeMeasuresDataType(Widget,Number,CubeName,.fDataType) + set obj.targetPropertyDataType = fDataType + set:(obj.target="") obj.target = Widget.name if ($e(obj.value)="@") { From f33435bf9c3b8c5aae8076a4fabfa47114acd09e Mon Sep 17 00:00:00 2001 From: Dmitrij Vladimirov <47441164+Frisle@users.noreply.github.com> Date: Mon, 17 Apr 2023 10:20:48 +0600 Subject: [PATCH 04/77] Update Dashboard.cls Small change to fix cube fast return --- MDX2JSON/Dashboard.cls | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/MDX2JSON/Dashboard.cls b/MDX2JSON/Dashboard.cls index 1094834..6ad63e2 100644 --- a/MDX2JSON/Dashboard.cls +++ b/MDX2JSON/Dashboard.cls @@ -117,6 +117,10 @@ ClassMethod GetCubeMeasuresDataType(Widget, Number, CubeName, Output DataType As 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 = "" From b2fa8a993518546cf879befdbe8f8bf8d686a7bd Mon Sep 17 00:00:00 2001 From: Dmitrij Vladimirov <47441164+Frisle@users.noreply.github.com> Date: Tue, 18 Apr 2023 09:41:00 +0600 Subject: [PATCH 05/77] Update Dashboard.cls removed %CopyTo() --- MDX2JSON/Dashboard.cls | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/MDX2JSON/Dashboard.cls b/MDX2JSON/Dashboard.cls index 6ad63e2..dac7f4a 100644 --- a/MDX2JSON/Dashboard.cls +++ b/MDX2JSON/Dashboard.cls @@ -104,14 +104,11 @@ ClassMethod GetCubeMeasuresDataType(Widget, Number, CubeName, Output DataType As { set st = $$$OK - set obj = $$$NewDynObj - set st = Widget.controls.GetAt(Number).%CopyTo(obj) // copy widget control properties to proxyObj set dataSource = $piece(Widget.dataSource, ".", *) // get dataSource type - if (dataSource '= "kpi"){ - if ($FIND(obj.targetProperty, "[")){ - set tMeasure = $TRANSLATE(obj.targetProperty, "[]", "") + if ($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 From ea106f2c3a59496f773f4c43d1393ea82bd77506 Mon Sep 17 00:00:00 2001 From: ProjectBot Date: Tue, 18 Apr 2023 17:25:57 +0000 Subject: [PATCH 06/77] auto bump version --- module.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module.xml b/module.xml index ddfdd6f..65f9608 100644 --- a/module.xml +++ b/module.xml @@ -2,7 +2,7 @@ MDX2JSON - 3.2.19 + 3.2.20 RESTful web api for MDX to JSON transformation (plus JSONP and XML/A) for InterSystems IRIS. Also provides information about DeepSee objects. module ./ From 79c82861ea175e7930f545d7a0f7113a26cdf153 Mon Sep 17 00:00:00 2001 From: Dmitrij Vladimirov <47441164+Frisle@users.noreply.github.com> Date: Thu, 20 Apr 2023 18:35:51 +0600 Subject: [PATCH 07/77] Update Dashboard.cls Add new parameter to showing kpi class for context menu button --- MDX2JSON/Dashboard.cls | 1 + 1 file changed, 1 insertion(+) diff --git a/MDX2JSON/Dashboard.cls b/MDX2JSON/Dashboard.cls index dac7f4a..ba46f62 100644 --- a/MDX2JSON/Dashboard.cls +++ b/MDX2JSON/Dashboard.cls @@ -149,6 +149,7 @@ ClassMethod WidgetToProxyObject(Widget As %DeepSee.Dashboard.Widget, CubeName As 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 } From 4616b03428b79516804bcd7263d1ba07e44a7472 Mon Sep 17 00:00:00 2001 From: ProjectBot Date: Fri, 21 Apr 2023 06:13:41 +0000 Subject: [PATCH 08/77] auto bump version --- module.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module.xml b/module.xml index 65f9608..22486da 100644 --- a/module.xml +++ b/module.xml @@ -2,7 +2,7 @@ MDX2JSON - 3.2.20 + 3.2.21 RESTful web api for MDX to JSON transformation (plus JSONP and XML/A) for InterSystems IRIS. Also provides information about DeepSee objects. module ./ From aeb11808159455cad3fb41ba01b01aa2c2c3a8ad Mon Sep 17 00:00:00 2001 From: Dmitrij Vladimirov <47441164+Frisle@users.noreply.github.com> Date: Tue, 25 Apr 2023 15:49:13 +0600 Subject: [PATCH 09/77] Update Utils.cls Improved method. Now it provides complete result set with series and properties based on SQL. Part of this was taken from ##class(%DeepSee.REST.v1.DataServer).WriteJSONfromKPI --- MDX2JSON/Utils.cls | 75 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 71 insertions(+), 4 deletions(-) diff --git a/MDX2JSON/Utils.cls b/MDX2JSON/Utils.cls index 60c3b11..affbb16 100644 --- a/MDX2JSON/Utils.cls +++ b/MDX2JSON/Utils.cls @@ -89,6 +89,35 @@ 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) 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 { @@ -98,15 +127,53 @@ ClassMethod WriteDrillthroughJSONKPI(tKPI As %String, pFilters As %String, pSele 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 pSQL = $classmethod(tKpiClassName,"%OnGetListingSQL",pFilters,pSelection) // invoke corresponding method from given kpi and get sql query + Set stmt = ##class(%SQL.Statement).%ExecDirect(,pSQL) + set values = ..getSQLValues(pSQL, .pValue) + + for i=1:1:stmt.%GetMetadata().columnCount + { + set pList(i) = stmt.%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") } - - set st = ##class(%ZEN.Auxiliary.altJSONSQLProvider).%WriteJSONFromSQL(,pSQL,,$$$MaxCacheInt) // receiving sql and process it - return:$$$ISERR(st) st return st } From eab95ba8a3f18253cde04e1898d63b0aed8001cb Mon Sep 17 00:00:00 2001 From: Dmitrij Vladimirov <47441164+Frisle@users.noreply.github.com> Date: Tue, 25 Apr 2023 15:59:12 +0600 Subject: [PATCH 10/77] Update Dashboard.cls Fix for the issue https://github.com/intersystems-community/DeepSeeWeb/issues/365 --- MDX2JSON/Dashboard.cls | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MDX2JSON/Dashboard.cls b/MDX2JSON/Dashboard.cls index ba46f62..b79ff65 100644 --- a/MDX2JSON/Dashboard.cls +++ b/MDX2JSON/Dashboard.cls @@ -107,7 +107,7 @@ ClassMethod GetCubeMeasuresDataType(Widget, Number, CubeName, Output DataType As set dataSource = $piece(Widget.dataSource, ".", *) // get dataSource type if (dataSource '= "kpi"){ - if ($FIND(Widget.controls.GetAt(Number).targetProperty, "[")){ + 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 From 0d32fa96bcd15b7b31b7d5953ec76118f1771b58 Mon Sep 17 00:00:00 2001 From: ProjectBot Date: Wed, 26 Apr 2023 17:20:42 +0000 Subject: [PATCH 11/77] auto bump version --- module.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module.xml b/module.xml index 22486da..ea259ff 100644 --- a/module.xml +++ b/module.xml @@ -2,7 +2,7 @@ MDX2JSON - 3.2.21 + 3.2.22 RESTful web api for MDX to JSON transformation (plus JSONP and XML/A) for InterSystems IRIS. Also provides information about DeepSee objects. module ./ From c027f351293ec156247bd628aa5f929693f31484 Mon Sep 17 00:00:00 2001 From: Dmitrij Vladimirov <47441164+Frisle@users.noreply.github.com> Date: Fri, 28 Apr 2023 20:05:59 +0600 Subject: [PATCH 12/77] Update Utils.cls Additional changes to improve execution speed --- MDX2JSON/Utils.cls | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/MDX2JSON/Utils.cls b/MDX2JSON/Utils.cls index affbb16..d302b55 100644 --- a/MDX2JSON/Utils.cls +++ b/MDX2JSON/Utils.cls @@ -92,7 +92,7 @@ ClassMethod WriteJSONfromQuery(CubeKey As %String, QueryKey As %String, Timeout /// 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) As %Status +ClassMethod GetSQLValues(pSQL, Output pValues As %String, Output tResultSet As %SQL.Statement) As %Status { set st = $$$OK @@ -128,12 +128,11 @@ ClassMethod WriteDrillthroughJSONKPI(tKPI As %String, pFilters As %String, pSele if (kpitype="sql") { set pSQL = $classmethod(tKpiClassName,"%OnGetListingSQL",pFilters,pSelection) // invoke corresponding method from given kpi and get sql query - Set stmt = ##class(%SQL.Statement).%ExecDirect(,pSQL) - set values = ..getSQLValues(pSQL, .pValue) + set values = ..GetSQLValues(pSQL, .pValue, .tResultSet) - for i=1:1:stmt.%GetMetadata().columnCount + for i=1:1:tResultSet.%GetMetadata().columnCount { - set pList(i) = stmt.%GetMetadata().columns.GetAt(i).label + set pList(i) = tResultSet.%GetMetadata().columns.GetAt(i).label set pList(i, "columnNo") = i Set tKpiPropIdx = $O(pList(""),1,tProperty) Set tKpiPropList = "" From 391b8277d0233e3057d79387d77f46d939dd710d Mon Sep 17 00:00:00 2001 From: ProjectBot Date: Sat, 29 Apr 2023 07:17:19 +0000 Subject: [PATCH 13/77] auto bump version --- module.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module.xml b/module.xml index ea259ff..d99f1dc 100644 --- a/module.xml +++ b/module.xml @@ -2,7 +2,7 @@ MDX2JSON - 3.2.22 + 3.2.23 RESTful web api for MDX to JSON transformation (plus JSONP and XML/A) for InterSystems IRIS. Also provides information about DeepSee objects. module ./ From dedbf9c3b4c1a5fe3e5ab01a01520f2f979632e2 Mon Sep 17 00:00:00 2001 From: Dmitrij Vladimirov <47441164+Frisle@users.noreply.github.com> Date: Fri, 5 May 2023 19:30:32 +0600 Subject: [PATCH 14/77] Update ResultSet.cls Reduced the number of steps taken to check what cell it is --- MDX2JSON/ResultSet.cls | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/MDX2JSON/ResultSet.cls b/MDX2JSON/ResultSet.cls index 7f7db4b..19e85cd 100644 --- a/MDX2JSON/ResultSet.cls +++ b/MDX2JSON/ResultSet.cls @@ -151,7 +151,7 @@ Method ProcessOneAxisCell(CubeIndex, AxisKey, CubeName, QueryKey, AxisNumber, No } //To filter out invisible сells - if (..IsCellNull(cell, AxisNumber, Node)=1) { + if (..IsCellNull(cell)=1) { return cell.children } @@ -198,11 +198,10 @@ Method ProcessOneAxisCell(CubeIndex, AxisKey, CubeName, QueryKey, AxisNumber, No return cell } -/// Determine if cell is an invisyble system cell. -Method IsCellNull(Cell, AxisNumber, Node) +/// Determine if cell is an invisible system cell. +Method IsCellNull(Cell) { - return:((Cell.type = "axis") || (Cell.type = "set")) 1 // for top-level cells - + return:(Cell.caption=0) 1 // typical caption for top-level cell return:(Cell.caption=1) 1 // typical caption for top-level cell return:(Cell.caption="") 1 // typical caption for top-level cell @@ -210,18 +209,11 @@ Method IsCellNull(Cell, AxisNumber, Node) //return:(path="") 1 set children = Cell.children return:(($isobject(children)) && ($$$ListSize(children)>0)) 0 // cell has children - - if (Cell.type'="lit") { - set key = $O($$$DeepSeeResultsGLVN(..%CubeKey, ..%QueryKey, "leaf", AxisNumber, "")) - while (key'="") { - return:(Node=$$$DeepSeeResultsGLVN(..%CubeKey, ..%QueryKey, "leaf", AxisNumber, key)) 0 //for leafs - set key = $O($$$DeepSeeResultsGLVN(..%CubeKey, ..%QueryKey, "leaf", AxisNumber, key)) - } - } else { - /// lit cell: SELECT %LABEL("Const","Title") ON 0 FROM [HoleFoodsBudget] - /// but also a lot of top-pevel cells - return 'Cell.vis - } + + // in case of cell type='lit'. the 'lit' cell always has the value vis=0, so we can skip it + // this is also true for type='axis' and type='set' so there is no need to check everything individually + return:(Cell.vis '= 0) 0 + return 1 } From 1703843219890f93c7c2001d570676bc93fdeb8a Mon Sep 17 00:00:00 2001 From: ProjectBot Date: Fri, 5 May 2023 13:54:41 +0000 Subject: [PATCH 15/77] auto bump version --- module.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module.xml b/module.xml index d99f1dc..2d07714 100644 --- a/module.xml +++ b/module.xml @@ -2,7 +2,7 @@ MDX2JSON - 3.2.23 + 3.2.24 RESTful web api for MDX to JSON transformation (plus JSONP and XML/A) for InterSystems IRIS. Also provides information about DeepSee objects. module ./ From ef8bd84c33d4156869e8fd3d37bf7ccc2c9f18cd Mon Sep 17 00:00:00 2001 From: Dmitrij Vladimirov <47441164+Frisle@users.noreply.github.com> Date: Thu, 11 May 2023 15:57:23 +0600 Subject: [PATCH 16/77] Update REST.cls New end point and corresponding method for https://github.com/intersystems-community/DeepSeeWeb/issues/121 Method simply return json containing data sources --- MDX2JSON/REST.cls | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/MDX2JSON/REST.cls b/MDX2JSON/REST.cls index e0998eb..d7f8d11 100644 --- a/MDX2JSON/REST.cls +++ b/MDX2JSON/REST.cls @@ -66,6 +66,7 @@ XData UrlMap + @@ -132,6 +133,41 @@ ClassMethod Test() As %Status return $$$OK } + +/// Get all data sources including "pivot", "kpi", "worksheets","metrics" +ClassMethod GetListDataSources() As %Status +{ + set st = $$$OK + + Set tProvider = ##class(%ZEN.Auxiliary.jsonMDXProvider).%New() + + if $$$R("dataSource") = "pivot" + { + Set tSC = ##class(%DeepSee.Utils).%GetPivotListArray(.tParms,.pMetaData,.pData) + Quit tSC + } + elseif $$$R("dataSource") = "kpi" + { + Set tSC = ##class(%DeepSee.Utils).%GetKPIListArray(.tParms,.pMetaData,.pData) + Quit tSC + } + elseif $$$R("dataSource") = "worksheets" + { + Set tSC = ##class(%DeepSee.Utils).%GetWorksheetListArray(.tParms,.pMetaData,.pData) + Quit tSC + } + elseif $$$R("datasource") = "metrics" + { + Set tSC = ##class(%DeepSee.Utils).%GetMetricListArray(.tParms,.pMetaData,.pData) + Quit tSC + } + Set tSC = ##class(%DeepSee.REST.v1.DataServer).%CreateObjectFromArray(.pData,pMetaData,.tSourceObj) + Set tSC = tProvider.%ObjectToJSON(tSourceObj) + + return st +} + + ClassMethod GetDataSource() As %Status { return ##class(MDX2JSON.Utils).GetDataSource($$$R("DataSource")) From 24a4451d62feb2ca46d1aaae6d7f902d7060c6d6 Mon Sep 17 00:00:00 2001 From: Dmitrij Vladimirov <47441164+Frisle@users.noreply.github.com> Date: Thu, 11 May 2023 16:25:25 +0600 Subject: [PATCH 17/77] Update REST.cls MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Внес правки --- MDX2JSON/REST.cls | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/MDX2JSON/REST.cls b/MDX2JSON/REST.cls index d7f8d11..c0546c9 100644 --- a/MDX2JSON/REST.cls +++ b/MDX2JSON/REST.cls @@ -137,34 +137,37 @@ ClassMethod Test() As %Status /// Get all data sources including "pivot", "kpi", "worksheets","metrics" ClassMethod GetListDataSources() As %Status { - set st = $$$OK - - Set tProvider = ##class(%ZEN.Auxiliary.jsonMDXProvider).%New() if $$$R("dataSource") = "pivot" { Set tSC = ##class(%DeepSee.Utils).%GetPivotListArray(.tParms,.pMetaData,.pData) - Quit tSC + } elseif $$$R("dataSource") = "kpi" { Set tSC = ##class(%DeepSee.Utils).%GetKPIListArray(.tParms,.pMetaData,.pData) - Quit tSC + } elseif $$$R("dataSource") = "worksheets" { Set tSC = ##class(%DeepSee.Utils).%GetWorksheetListArray(.tParms,.pMetaData,.pData) - Quit tSC + } elseif $$$R("datasource") = "metrics" { Set tSC = ##class(%DeepSee.Utils).%GetMetricListArray(.tParms,.pMetaData,.pData) - Quit tSC + } + + quit:$$$ISERR(tSC) tSC + Set tSC = ##class(%DeepSee.REST.v1.DataServer).%CreateObjectFromArray(.pData,pMetaData,.tSourceObj) - Set tSC = tProvider.%ObjectToJSON(tSourceObj) - return st + quit:$$$ISERR(tSC) tSC + + do tSourceObj.%ToJSON() + + quit tSC } From d7f9b4f5a00c68356ac87caeaae372b30d77475d Mon Sep 17 00:00:00 2001 From: ProjectBot Date: Thu, 11 May 2023 10:29:39 +0000 Subject: [PATCH 18/77] auto bump version --- module.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module.xml b/module.xml index 2d07714..7385252 100644 --- a/module.xml +++ b/module.xml @@ -2,7 +2,7 @@ MDX2JSON - 3.2.24 + 3.2.25 RESTful web api for MDX to JSON transformation (plus JSONP and XML/A) for InterSystems IRIS. Also provides information about DeepSee objects. module ./ From 7599790428fc661d603e16bb4d648f7e57648203 Mon Sep 17 00:00:00 2001 From: Dmitrij Vladimirov <47441164+Frisle@users.noreply.github.com> Date: Thu, 11 May 2023 17:48:25 +0600 Subject: [PATCH 19/77] Update REST.cls Changed the way arguments are passed to /:type --- MDX2JSON/REST.cls | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/MDX2JSON/REST.cls b/MDX2JSON/REST.cls index c0546c9..9f04ae5 100644 --- a/MDX2JSON/REST.cls +++ b/MDX2JSON/REST.cls @@ -66,7 +66,7 @@ XData UrlMap - + @@ -135,25 +135,27 @@ ClassMethod Test() As %Status /// Get all data sources including "pivot", "kpi", "worksheets","metrics" -ClassMethod GetListDataSources() As %Status +ClassMethod GetListDataSources(Source) As %Status { - if $$$R("dataSource") = "pivot" + set Source = $ZCONVERT($ZCONVERT(Source ,"I","URL") ,"I","UTF8") + + if (Source = "pivot") { Set tSC = ##class(%DeepSee.Utils).%GetPivotListArray(.tParms,.pMetaData,.pData) } - elseif $$$R("dataSource") = "kpi" + elseif (Source = "kpi") { Set tSC = ##class(%DeepSee.Utils).%GetKPIListArray(.tParms,.pMetaData,.pData) - + } - elseif $$$R("dataSource") = "worksheets" + elseif (Source = "worksheets") { Set tSC = ##class(%DeepSee.Utils).%GetWorksheetListArray(.tParms,.pMetaData,.pData) } - elseif $$$R("datasource") = "metrics" + elseif (Source = "metrics") { Set tSC = ##class(%DeepSee.Utils).%GetMetricListArray(.tParms,.pMetaData,.pData) From 65be5d3b85f9e509dbcacec09b6b2f5f38f7f0a0 Mon Sep 17 00:00:00 2001 From: ProjectBot Date: Fri, 12 May 2023 06:34:31 +0000 Subject: [PATCH 20/77] auto bump version --- module.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module.xml b/module.xml index 7385252..5c8c866 100644 --- a/module.xml +++ b/module.xml @@ -2,7 +2,7 @@ MDX2JSON - 3.2.25 + 3.2.26 RESTful web api for MDX to JSON transformation (plus JSONP and XML/A) for InterSystems IRIS. Also provides information about DeepSee objects. module ./ From 66abef4d73f5c410d794e219078d98037a119fff Mon Sep 17 00:00:00 2001 From: Dmitrij Vladimirov <47441164+Frisle@users.noreply.github.com> Date: Tue, 16 May 2023 19:35:12 +0600 Subject: [PATCH 21/77] FIX: issue when DataSource request is empty If client requested empty string in DataSource endpoint ClassMethod GetDataSource() return status 200 --- MDX2JSON/Utils.cls | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MDX2JSON/Utils.cls b/MDX2JSON/Utils.cls index d302b55..6c3e586 100644 --- a/MDX2JSON/Utils.cls +++ b/MDX2JSON/Utils.cls @@ -291,7 +291,7 @@ 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 From 1cdae296c120e61e2fb920f6117c7ceab3722e9f Mon Sep 17 00:00:00 2001 From: Frisle <47441164+Frisle@users.noreply.github.com> Date: Fri, 19 May 2023 21:43:05 +0600 Subject: [PATCH 22/77] ADD: new features: install and edit widgets in DSW The new method and endpoint adds the ability to install and edit widgets directly from DSW. Related issue https://github.com/intersystems-community/DeepSeeWeb/issues/121 --- MDX2JSON/REST.cls | 12 ++++++++ MDX2JSON/Utils.cls | 74 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+) diff --git a/MDX2JSON/REST.cls b/MDX2JSON/REST.cls index 9f04ae5..b7f7042 100644 --- a/MDX2JSON/REST.cls +++ b/MDX2JSON/REST.cls @@ -61,6 +61,9 @@ XData UrlMap + + + @@ -133,6 +136,15 @@ ClassMethod Test() As %Status return $$$OK } +ClassMethod saveWidget() +{ + 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 diff --git a/MDX2JSON/Utils.cls b/MDX2JSON/Utils.cls index d302b55..359cd27 100644 --- a/MDX2JSON/Utils.cls +++ b/MDX2JSON/Utils.cls @@ -538,4 +538,78 @@ ClassMethod CreateAddonClass(Class As %Dictionary.CacheClassname) As %Status quit classObj.%Save() } +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 exist + If (dExist = 1) + { + Set tDash=##class(%DeepSee.Dashboard.Utils).%OpenDashboard(sDashboard, .st) + set tWidgets = ##class(%DeepSee.Dashboard.Widget).%New() + set tWidgets.name = sWidget.name + quit:sWidget.name="" + set tWidgets.title = sWidget.title + set tWidgets.dataSource = sWidget.dataSource + + // logic to work around weird line in ##classMDX2JSON.Dashboard.WidgetToProxyObject: + // "set obj.type = Widget.subtype" + if (sWidget.type = "pivot") + { + set tWidgets.type = "pivot" + set tWidgets.subtype = "pivot" + } + elseif (sWidget.type '= "pivot") + { + set tWidgets.type = "pivot" + set tWidgets.subtype = sWidget.type + } + + set count = 0 // indicates wether or not the same name as key exists + for i=1:1:tDash.widgets.Count() + { + if (tDash.widgets.GetAt(i).name = sWidget.name) + { + set count = 1 + return $$$ERROR() + } + } + + + if (($LENGTH(key) = 0) & (count = 0)) // if key is empty and count = 1 widget is not insert + { + $$$Insert(tDash.widgets, tWidgets) + do tDash.%Save() + + }elseif ($LENGTH(key) > 0) + { + + for i=1:1:tDash.widgets.Count() + { + if (tDash.widgets.GetAt(i).name = key) + { + set tDash.widgets.GetAt(i).name = sWidget.name + set tDash.widgets.GetAt(i).title = sWidget.title + set tDash.widgets.GetAt(i).dataSource = sWidget.dataSource + + if (sWidget.type = "pivot") + { + set tDash.widgets.GetAt(i).type = "pivot" + set tDash.widgets.GetAt(i).subtype = "pivot" + } + elseif (sWidget.type '= "pivot") + { + set tDash.widgets.GetAt(i).type = "pivot" + set tDash.widgets.GetAt(i).subtype = sWidget.type + } + do tDash.%Save() + + } + } + } + + + } + return st +} + } From 9748312652964ab7a1a63e8d74d1302e9e041e30 Mon Sep 17 00:00:00 2001 From: Dmitrij Vladimirov <47441164+Frisle@users.noreply.github.com> Date: Fri, 19 May 2023 21:47:12 +0600 Subject: [PATCH 23/77] FIX: change return mode --- MDX2JSON/REST.cls | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MDX2JSON/REST.cls b/MDX2JSON/REST.cls index b7f7042..e08470e 100644 --- a/MDX2JSON/REST.cls +++ b/MDX2JSON/REST.cls @@ -136,7 +136,7 @@ ClassMethod Test() As %Status return $$$OK } -ClassMethod saveWidget() +ClassMethod saveWidget() As %Status { set key = $$$R("key") set widgetData= $$$R("WidgetData") From 39bfc8c54ce5fac0ac1811d190dba04b0346080c Mon Sep 17 00:00:00 2001 From: ProjectBot Date: Fri, 19 May 2023 15:50:30 +0000 Subject: [PATCH 24/77] auto bump version --- module.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module.xml b/module.xml index 5c8c866..d59267f 100644 --- a/module.xml +++ b/module.xml @@ -2,7 +2,7 @@ MDX2JSON - 3.2.26 + 3.2.27 RESTful web api for MDX to JSON transformation (plus JSONP and XML/A) for InterSystems IRIS. Also provides information about DeepSee objects. module ./ From 8244eb952719686bc5702fb4188fdee83f60cfc0 Mon Sep 17 00:00:00 2001 From: ProjectBot Date: Fri, 19 May 2023 15:50:56 +0000 Subject: [PATCH 25/77] auto bump version --- module.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module.xml b/module.xml index d59267f..91d0792 100644 --- a/module.xml +++ b/module.xml @@ -2,7 +2,7 @@ MDX2JSON - 3.2.27 + 3.2.28 RESTful web api for MDX to JSON transformation (plus JSONP and XML/A) for InterSystems IRIS. Also provides information about DeepSee objects. module ./ From 53801bb228cf9c79d284475aad83d9a0f97f6a8d Mon Sep 17 00:00:00 2001 From: Dmitrij Vladimirov <47441164+Frisle@users.noreply.github.com> Date: Sat, 20 May 2023 18:25:54 +0600 Subject: [PATCH 26/77] FIX: remove breaking return statement No need to exit from method when names of widgets are similar --- MDX2JSON/Utils.cls | 1 - 1 file changed, 1 deletion(-) diff --git a/MDX2JSON/Utils.cls b/MDX2JSON/Utils.cls index d460c2b..ca03f54 100644 --- a/MDX2JSON/Utils.cls +++ b/MDX2JSON/Utils.cls @@ -570,7 +570,6 @@ ClassMethod AddWidget(sWidget As %String, sDashboard As %String, key As %String) if (tDash.widgets.GetAt(i).name = sWidget.name) { set count = 1 - return $$$ERROR() } } From 929634bf0d3e3076ac3d1f0b22e5f76cf5eaf666 Mon Sep 17 00:00:00 2001 From: ProjectBot Date: Sat, 20 May 2023 12:29:36 +0000 Subject: [PATCH 27/77] auto bump version --- module.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module.xml b/module.xml index 91d0792..660c8e1 100644 --- a/module.xml +++ b/module.xml @@ -2,7 +2,7 @@ MDX2JSON - 3.2.28 + 3.2.29 RESTful web api for MDX to JSON transformation (plus JSONP and XML/A) for InterSystems IRIS. Also provides information about DeepSee objects. module ./ From 3e275b82376ec51378b843fdbc54f6a981df125f Mon Sep 17 00:00:00 2001 From: Frisle <47441164+Frisle@users.noreply.github.com> Date: Mon, 22 May 2023 16:54:18 +0600 Subject: [PATCH 28/77] FIX: edited AddWidget method, remove redundant Http500 method. ADD: new method to hold all widget parameters. Rewrite method AddWidget, add new method UpdateWidget for convenience, remove method Http500 and all its instances --- MDX2JSON/AbstractREST.cls | 20 +------ MDX2JSON/Utils.cls | 121 ++++++++++++++++++++------------------ 2 files changed, 66 insertions(+), 75 deletions(-) diff --git a/MDX2JSON/AbstractREST.cls b/MDX2JSON/AbstractREST.cls index f13c873..3cad053 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,7 +37,7 @@ 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 } @@ -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/Utils.cls b/MDX2JSON/Utils.cls index 359cd27..d3475fc 100644 --- a/MDX2JSON/Utils.cls +++ b/MDX2JSON/Utils.cls @@ -538,78 +538,85 @@ ClassMethod CreateAddonClass(Class As %Dictionary.CacheClassname) As %Status quit classObj.%Save() } +/// Add new widgets and edit existing ones. 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 exist - If (dExist = 1) + set dExist=##class(%DeepSee.Dashboard.Utils).%DashboardExists(sDashboard) + + // Check if dashboard exists + If (dExist '= 1) { - Set tDash=##class(%DeepSee.Dashboard.Utils).%OpenDashboard(sDashboard, .st) - set tWidgets = ##class(%DeepSee.Dashboard.Widget).%New() - set tWidgets.name = sWidget.name - quit:sWidget.name="" - set tWidgets.title = sWidget.title - set tWidgets.dataSource = sWidget.dataSource - - // logic to work around weird line in ##classMDX2JSON.Dashboard.WidgetToProxyObject: - // "set obj.type = Widget.subtype" - if (sWidget.type = "pivot") - { - set tWidgets.type = "pivot" - set tWidgets.subtype = "pivot" + 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") } - elseif (sWidget.type '= "pivot") - { - set tWidgets.type = "pivot" - set tWidgets.subtype = sWidget.type - } - set count = 0 // indicates wether or not the same name as key exists + set tWidgets = ##class(%DeepSee.Dashboard.Widget).%New() + do ..UpdateWidget(tWidgets, sWidget) + + $$$Insert(tDash.widgets, tWidgets) + do tDash.%Save() + + } else { + // Edit exists widget for i=1:1:tDash.widgets.Count() { - if (tDash.widgets.GetAt(i).name = sWidget.name) - { - set count = 1 - return $$$ERROR() + 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 (($LENGTH(key) = 0) & (count = 0)) // if key is empty and count = 1 widget is not insert - { - $$$Insert(tDash.widgets, tWidgets) - do tDash.%Save() - - }elseif ($LENGTH(key) > 0) - { - - for i=1:1:tDash.widgets.Count() + if (dWidgets.name = key) { - if (tDash.widgets.GetAt(i).name = key) - { - set tDash.widgets.GetAt(i).name = sWidget.name - set tDash.widgets.GetAt(i).title = sWidget.title - set tDash.widgets.GetAt(i).dataSource = sWidget.dataSource - - if (sWidget.type = "pivot") - { - set tDash.widgets.GetAt(i).type = "pivot" - set tDash.widgets.GetAt(i).subtype = "pivot" - } - elseif (sWidget.type '= "pivot") - { - set tDash.widgets.GetAt(i).type = "pivot" - set tDash.widgets.GetAt(i).subtype = sWidget.type - } - do tDash.%Save() - - } + set changed = dWidgets } } + if (changed '= "") { + do ..UpdateWidget(changed, sWidget) + do tDash.%Save() + } + } + + return st +} +/// the collection of necessary parameters for building widget +ClassMethod UpdateWidget(widgetToUpdate As %DeepSee.Dashboard.Widget, data As %ZEN.proxyObject) +{ + set widgetToUpdate.name = data.name + set widgetToUpdate.title = data.title + set widgetToUpdate.dataSource = data.dataSource + set widgetToUpdate.dataLink = data.dataLink - } - return st + 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 + } } } From d9d63936fef1404087f62713fb1b945bb9edcc62 Mon Sep 17 00:00:00 2001 From: Dmitrij Vladimirov <47441164+Frisle@users.noreply.github.com> Date: Mon, 22 May 2023 17:01:09 +0600 Subject: [PATCH 29/77] ADD: new parameters Add positional parameters --- MDX2JSON/Utils.cls | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/MDX2JSON/Utils.cls b/MDX2JSON/Utils.cls index d3475fc..cc6b02a 100644 --- a/MDX2JSON/Utils.cls +++ b/MDX2JSON/Utils.cls @@ -607,6 +607,17 @@ ClassMethod UpdateWidget(widgetToUpdate As %DeepSee.Dashboard.Widget, data As %Z set widgetToUpdate.dataSource = data.dataSource set widgetToUpdate.dataLink = data.dataLink + 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 + } + if (data.type = "pivot") { set widgetToUpdate.type = "pivot" From 04519fd873e5ba59f1ee82ec9a38af96c709e6e3 Mon Sep 17 00:00:00 2001 From: ProjectBot Date: Mon, 22 May 2023 11:19:54 +0000 Subject: [PATCH 30/77] auto bump version --- module.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module.xml b/module.xml index 660c8e1..8035ffe 100644 --- a/module.xml +++ b/module.xml @@ -2,7 +2,7 @@ MDX2JSON - 3.2.29 + 3.2.30 RESTful web api for MDX to JSON transformation (plus JSONP and XML/A) for InterSystems IRIS. Also provides information about DeepSee objects. module ./ From 740c0e27aa420503710697e460be824c7088a149 Mon Sep 17 00:00:00 2001 From: Dmitrij Vladimirov <47441164+Frisle@users.noreply.github.com> Date: Mon, 22 May 2023 17:39:27 +0600 Subject: [PATCH 31/77] FIX: replace wrong parameter name Parameter dataLink is not received because of this line --- MDX2JSON/Dashboard.cls | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MDX2JSON/Dashboard.cls b/MDX2JSON/Dashboard.cls index b79ff65..ccaa6da 100644 --- a/MDX2JSON/Dashboard.cls +++ b/MDX2JSON/Dashboard.cls @@ -142,7 +142,7 @@ 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 From 694b312951ea8941613182146cb2b2faca708381 Mon Sep 17 00:00:00 2001 From: ProjectBot Date: Mon, 22 May 2023 14:08:07 +0000 Subject: [PATCH 32/77] auto bump version --- module.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module.xml b/module.xml index 8035ffe..931dc90 100644 --- a/module.xml +++ b/module.xml @@ -2,7 +2,7 @@ MDX2JSON - 3.2.30 + 3.2.31 RESTful web api for MDX to JSON transformation (plus JSONP and XML/A) for InterSystems IRIS. Also provides information about DeepSee objects. module ./ From 73ccdfcc0c1b531455418a9599faa7f1aac18843 Mon Sep 17 00:00:00 2001 From: Frisle <47441164+Frisle@users.noreply.github.com> Date: Tue, 23 May 2023 10:15:42 +0600 Subject: [PATCH 33/77] ADD: new method DeleteWidget, new endpoint, dataSource check Add widget deletion, add logic when dataSource is not present in parameters. Add new endpoint as well --- MDX2JSON/Dashboard.cls | 2 +- MDX2JSON/REST.cls | 9 +++++ MDX2JSON/Utils.cls | 88 +++++++++++++++++++++++++++++++++++------- 3 files changed, 83 insertions(+), 16 deletions(-) diff --git a/MDX2JSON/Dashboard.cls b/MDX2JSON/Dashboard.cls index b79ff65..9cf1872 100644 --- a/MDX2JSON/Dashboard.cls +++ b/MDX2JSON/Dashboard.cls @@ -106,7 +106,7 @@ ClassMethod GetCubeMeasuresDataType(Widget, Number, CubeName, Output DataType As set st = $$$OK set dataSource = $piece(Widget.dataSource, ".", *) // get dataSource type - if (dataSource '= "kpi"){ + 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, "[]", "") diff --git a/MDX2JSON/REST.cls b/MDX2JSON/REST.cls index e08470e..00a1cea 100644 --- a/MDX2JSON/REST.cls +++ b/MDX2JSON/REST.cls @@ -63,6 +63,7 @@ XData UrlMap + @@ -136,6 +137,14 @@ 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") diff --git a/MDX2JSON/Utils.cls b/MDX2JSON/Utils.cls index 3ebc1ee..af7fbfd 100644 --- a/MDX2JSON/Utils.cls +++ b/MDX2JSON/Utils.cls @@ -538,7 +538,9 @@ ClassMethod CreateAddonClass(Class As %Dictionary.CacheClassname) As %Status quit classObj.%Save() } -/// Add new widgets and edit existing ones. +/// 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 @@ -569,7 +571,7 @@ ClassMethod AddWidget(sWidget As %String, sDashboard As %String, key As %String) } set tWidgets = ##class(%DeepSee.Dashboard.Widget).%New() - do ..UpdateWidget(tWidgets, sWidget) + set st = ..UpdateWidget(tWidgets, sWidget) $$$Insert(tDash.widgets, tWidgets) do tDash.%Save() @@ -593,7 +595,7 @@ ClassMethod AddWidget(sWidget As %String, sDashboard As %String, key As %String) } } if (changed '= "") { - do ..UpdateWidget(changed, sWidget) + set st = ..UpdateWidget(changed, sWidget) do tDash.%Save() } } @@ -601,13 +603,78 @@ ClassMethod AddWidget(sWidget As %String, sDashboard As %String, key As %String) 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) +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 - set widgetToUpdate.dataSource = data.dataSource + 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 @@ -620,16 +687,7 @@ ClassMethod UpdateWidget(widgetToUpdate As %DeepSee.Dashboard.Widget, data As %Z set widgetToUpdate.rowSpanL = data.displayInfo.rowHeight } - 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 - } + return st } } From 978769779ed5d20a83e6f59ddbc7d03272c8e94b Mon Sep 17 00:00:00 2001 From: ProjectBot Date: Tue, 23 May 2023 06:53:26 +0000 Subject: [PATCH 34/77] auto bump version --- module.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module.xml b/module.xml index 931dc90..0eec02f 100644 --- a/module.xml +++ b/module.xml @@ -2,7 +2,7 @@ MDX2JSON - 3.2.31 + 3.2.32 RESTful web api for MDX to JSON transformation (plus JSONP and XML/A) for InterSystems IRIS. Also provides information about DeepSee objects. module ./ From 4174f0b680599afb8a3625e5d395bae48b16070a Mon Sep 17 00:00:00 2001 From: Dmitrij Vladimirov <47441164+Frisle@users.noreply.github.com> Date: Tue, 23 May 2023 13:12:19 +0600 Subject: [PATCH 35/77] FIX: not documented issue. Crash when accessed to specific global Add try except block to prevent dashboad to crash when globals are missing or wrong --- MDX2JSON/Dashboard.cls | 42 ++++++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/MDX2JSON/Dashboard.cls b/MDX2JSON/Dashboard.cls index 1739529..a7dcd58 100644 --- a/MDX2JSON/Dashboard.cls +++ b/MDX2JSON/Dashboard.cls @@ -105,28 +105,30 @@ ClassMethod GetCubeMeasuresDataType(Widget, Number, CubeName, Output DataType As 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{ - 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 = "" + set DataType = "" + } + }catch ex { + set st = ex.AsStatus() } - return st } From ace7c55cbff16b619cd9ef9e93bef599216cc502 Mon Sep 17 00:00:00 2001 From: ProjectBot Date: Tue, 23 May 2023 08:59:31 +0000 Subject: [PATCH 36/77] auto bump version --- module.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module.xml b/module.xml index 0eec02f..25d410b 100644 --- a/module.xml +++ b/module.xml @@ -2,7 +2,7 @@ MDX2JSON - 3.2.32 + 3.2.33 RESTful web api for MDX to JSON transformation (plus JSONP and XML/A) for InterSystems IRIS. Also provides information about DeepSee objects. module ./ From 0a7bdcb9158650b90b7f6577b1c6ffcb85891988 Mon Sep 17 00:00:00 2001 From: Frisle <47441164+Frisle@users.noreply.github.com> Date: Mon, 29 May 2023 10:00:11 +0600 Subject: [PATCH 37/77] FIX: dataSource error Throw an error and exit from method when dataSource is not present --- MDX2JSON/Utils.cls | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/MDX2JSON/Utils.cls b/MDX2JSON/Utils.cls index af7fbfd..2adc97e 100644 --- a/MDX2JSON/Utils.cls +++ b/MDX2JSON/Utils.cls @@ -573,8 +573,11 @@ ClassMethod AddWidget(sWidget As %String, sDashboard As %String, key As %String) set tWidgets = ##class(%DeepSee.Dashboard.Widget).%New() set st = ..UpdateWidget(tWidgets, sWidget) - $$$Insert(tDash.widgets, tWidgets) - do tDash.%Save() + if (st = $$$OK) + { + $$$Insert(tDash.widgets, tWidgets) + do tDash.%Save() + } } else { // Edit exists widget @@ -596,7 +599,10 @@ ClassMethod AddWidget(sWidget As %String, sDashboard As %String, key As %String) } if (changed '= "") { set st = ..UpdateWidget(changed, sWidget) - do tDash.%Save() + if (st = $$$OK) + { + do tDash.%Save() + } } } From 999196e06cb5d932d08d441b0b57f86419b4926d Mon Sep 17 00:00:00 2001 From: Dmitrij Vladimirov <47441164+Frisle@users.noreply.github.com> Date: Mon, 29 May 2023 10:51:59 +0600 Subject: [PATCH 38/77] ADD: commentary Comment new logic --- MDX2JSON/Utils.cls | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MDX2JSON/Utils.cls b/MDX2JSON/Utils.cls index 2adc97e..9b5109f 100644 --- a/MDX2JSON/Utils.cls +++ b/MDX2JSON/Utils.cls @@ -573,7 +573,7 @@ ClassMethod AddWidget(sWidget As %String, sDashboard As %String, key As %String) set tWidgets = ##class(%DeepSee.Dashboard.Widget).%New() set st = ..UpdateWidget(tWidgets, sWidget) - if (st = $$$OK) + if (st = $$$OK) // checking for errors in UpdateWidget { $$$Insert(tDash.widgets, tWidgets) do tDash.%Save() @@ -599,7 +599,7 @@ ClassMethod AddWidget(sWidget As %String, sDashboard As %String, key As %String) } if (changed '= "") { set st = ..UpdateWidget(changed, sWidget) - if (st = $$$OK) + if (st = $$$OK) // checking for errors in UpdateWidget { do tDash.%Save() } From e7258f0311b25126aa90b03b9b744b56b72c8b6d Mon Sep 17 00:00:00 2001 From: Frisle <47441164+Frisle@users.noreply.github.com> Date: Mon, 29 May 2023 12:51:26 +0600 Subject: [PATCH 39/77] FIX: add logic to filter DataType add logic to fix specific bug on TRAK --- MDX2JSON/Dashboard.cls | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/MDX2JSON/Dashboard.cls b/MDX2JSON/Dashboard.cls index a7dcd58..060a64b 100644 --- a/MDX2JSON/Dashboard.cls +++ b/MDX2JSON/Dashboard.cls @@ -291,7 +291,11 @@ ClassMethod WidgetControlToProxyObject(Widget As %DeepSee.Dashboard.Widget, Numb set obj.source = Widget.name set filterDataType = ..GetCubeMeasuresDataType(Widget,Number,CubeName,.fDataType) - set obj.targetPropertyDataType = fDataType + + if ('fDataType) + { + set obj.targetPropertyDataType = fDataType + } set:(obj.target="") obj.target = Widget.name From 09048aa94d5e528f0ada61f320c980d12ceae796 Mon Sep 17 00:00:00 2001 From: Frisle <47441164+Frisle@users.noreply.github.com> Date: Mon, 29 May 2023 17:27:45 +0600 Subject: [PATCH 40/77] FIX: add check for error in GetCubeMeasuresDataType Add check in case of missing or wrong cubeName --- .gitignore | 1 + MDX2JSON/Dashboard.cls | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) 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/Dashboard.cls b/MDX2JSON/Dashboard.cls index 060a64b..1a9139f 100644 --- a/MDX2JSON/Dashboard.cls +++ b/MDX2JSON/Dashboard.cls @@ -290,9 +290,9 @@ ClassMethod WidgetControlToProxyObject(Widget As %DeepSee.Dashboard.Widget, Numb set obj.label = ##class(%DeepSee.UserPortal.Utils).%ResolveText(obj.label) set obj.source = Widget.name - set filterDataType = ..GetCubeMeasuresDataType(Widget,Number,CubeName,.fDataType) - - if ('fDataType) + set st = ..GetCubeMeasuresDataType(Widget,Number,CubeName,.fDataType) + + if (st = $$$OK) { set obj.targetPropertyDataType = fDataType } From a3d0e4c542d097a5c3d089bc9f8fd08fc0663dd8 Mon Sep 17 00:00:00 2001 From: ProjectBot Date: Tue, 13 Jun 2023 06:47:46 +0000 Subject: [PATCH 41/77] auto bump version --- module.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module.xml b/module.xml index 25d410b..5fbb819 100644 --- a/module.xml +++ b/module.xml @@ -2,7 +2,7 @@ MDX2JSON - 3.2.33 + 3.2.34 RESTful web api for MDX to JSON transformation (plus JSONP and XML/A) for InterSystems IRIS. Also provides information about DeepSee objects. module ./ From 16c2efa54ed073684725e6a5abdbec7d9ed6ecf6 Mon Sep 17 00:00:00 2001 From: Dmitrij Vladimirov <47441164+Frisle@users.noreply.github.com> Date: Mon, 25 Sep 2023 12:16:58 +0600 Subject: [PATCH 42/77] FIX: Add support for compound calculation FIx issue when dimension derived from compound cube and need time to calculate before display --- MDX2JSON/Utils.cls | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/MDX2JSON/Utils.cls b/MDX2JSON/Utils.cls index 9b5109f..0f054a5 100644 --- a/MDX2JSON/Utils.cls +++ b/MDX2JSON/Utils.cls @@ -57,17 +57,36 @@ ClassMethod ExecuteResultSet(RS As MDX2JSON.ResultSet, QueryKey As %String = "", /// 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 + $$$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 + $$$DynObjToJSON(obj) + } return $$$OK } From 54a730b3ee6a804c8fb36f196a50095166f70ce8 Mon Sep 17 00:00:00 2001 From: ProjectBot Date: Mon, 25 Sep 2023 08:37:57 +0000 Subject: [PATCH 43/77] auto bump version --- module.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module.xml b/module.xml index 5fbb819..b433434 100644 --- a/module.xml +++ b/module.xml @@ -2,7 +2,7 @@ MDX2JSON - 3.2.34 + 3.2.35 RESTful web api for MDX to JSON transformation (plus JSONP and XML/A) for InterSystems IRIS. Also provides information about DeepSee objects. module ./ From 48071f7ea4b89bb48ce8057644e050369991a324 Mon Sep 17 00:00:00 2001 From: Evgeniy Potapov <41373877+jakcpto@users.noreply.github.com> Date: Wed, 11 Oct 2023 09:20:26 +0400 Subject: [PATCH 44/77] Update REST.cls Version Bump --- MDX2JSON/REST.cls | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MDX2JSON/REST.cls b/MDX2JSON/REST.cls index 00a1cea..00de236 100644 --- a/MDX2JSON/REST.cls +++ b/MDX2JSON/REST.cls @@ -119,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.35" set obj.Parent = ##class(MDX2JSON.Tests).#LastCommit set obj.ParentTS = ##class(MDX2JSON.Tests).#LastCommitTS set obj.DefaultApp = $System.CSP.GetDefaultApp($Namespace) From 17765cf9f8c200a0e9f35395e6fcbd4aa503a8b4 Mon Sep 17 00:00:00 2001 From: ProjectBot Date: Fri, 13 Oct 2023 17:08:59 +0000 Subject: [PATCH 45/77] auto bump version --- module.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module.xml b/module.xml index b433434..c82efea 100644 --- a/module.xml +++ b/module.xml @@ -2,7 +2,7 @@ MDX2JSON - 3.2.35 + 3.2.36 RESTful web api for MDX to JSON transformation (plus JSONP and XML/A) for InterSystems IRIS. Also provides information about DeepSee objects. module ./ From a8ba607dd40a8b2ab9dcd4db3830041d191cd4cd Mon Sep 17 00:00:00 2001 From: Eduard Date: Fri, 13 Oct 2023 20:09:20 +0300 Subject: [PATCH 46/77] Update REST.cls --- MDX2JSON/REST.cls | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MDX2JSON/REST.cls b/MDX2JSON/REST.cls index 00de236..97bba04 100644 --- a/MDX2JSON/REST.cls +++ b/MDX2JSON/REST.cls @@ -119,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.35" + set obj.Version = "3.2.36" set obj.Parent = ##class(MDX2JSON.Tests).#LastCommit set obj.ParentTS = ##class(MDX2JSON.Tests).#LastCommitTS set obj.DefaultApp = $System.CSP.GetDefaultApp($Namespace) From a78a060a3ca91b805a84f439617349598f332594 Mon Sep 17 00:00:00 2001 From: ProjectBot Date: Fri, 13 Oct 2023 17:09:32 +0000 Subject: [PATCH 47/77] auto bump version --- module.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module.xml b/module.xml index c82efea..b369c34 100644 --- a/module.xml +++ b/module.xml @@ -2,7 +2,7 @@ MDX2JSON - 3.2.36 + 3.2.37 RESTful web api for MDX to JSON transformation (plus JSONP and XML/A) for InterSystems IRIS. Also provides information about DeepSee objects. module ./ From 02253dbec66b087c849e645fdafd3ebc0e941455 Mon Sep 17 00:00:00 2001 From: Eduard Date: Fri, 13 Oct 2023 20:10:35 +0300 Subject: [PATCH 48/77] 2.3.36 --- module.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module.xml b/module.xml index b369c34..c82efea 100644 --- a/module.xml +++ b/module.xml @@ -2,7 +2,7 @@ MDX2JSON - 3.2.37 + 3.2.36 RESTful web api for MDX to JSON transformation (plus JSONP and XML/A) for InterSystems IRIS. Also provides information about DeepSee objects. module ./ From 130b8cd1fe5a355df7ba5e5144a8c6a5f989b513 Mon Sep 17 00:00:00 2001 From: ProjectBot Date: Fri, 13 Oct 2023 17:13:09 +0000 Subject: [PATCH 49/77] auto bump version --- module.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module.xml b/module.xml index c82efea..b369c34 100644 --- a/module.xml +++ b/module.xml @@ -2,7 +2,7 @@ MDX2JSON - 3.2.36 + 3.2.37 RESTful web api for MDX to JSON transformation (plus JSONP and XML/A) for InterSystems IRIS. Also provides information about DeepSee objects. module ./ From 767de6a62f40111ff14aa8de9747b2d9255c77b3 Mon Sep 17 00:00:00 2001 From: Eduard Date: Fri, 13 Oct 2023 20:14:21 +0300 Subject: [PATCH 50/77] Set version to 2.3.38 --- MDX2JSON/REST.cls | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MDX2JSON/REST.cls b/MDX2JSON/REST.cls index 97bba04..0a23d79 100644 --- a/MDX2JSON/REST.cls +++ b/MDX2JSON/REST.cls @@ -119,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.36" + 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) From fde790905e38d21bfdf9c93c4262e919eff131d0 Mon Sep 17 00:00:00 2001 From: ProjectBot Date: Fri, 13 Oct 2023 17:14:32 +0000 Subject: [PATCH 51/77] auto bump version --- module.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module.xml b/module.xml index b369c34..2fd4417 100644 --- a/module.xml +++ b/module.xml @@ -2,7 +2,7 @@ MDX2JSON - 3.2.37 + 3.2.38 RESTful web api for MDX to JSON transformation (plus JSONP and XML/A) for InterSystems IRIS. Also provides information about DeepSee objects. module ./ From 3658268de80339601adb9447dbe8a35cceff4b2f Mon Sep 17 00:00:00 2001 From: Dmitrij Vladimirov <47441164+Frisle@users.noreply.github.com> Date: Tue, 21 Nov 2023 18:14:49 +0600 Subject: [PATCH 52/77] FIX: hot fix for AbstractREST method --- MDX2JSON/AbstractREST.cls | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MDX2JSON/AbstractREST.cls b/MDX2JSON/AbstractREST.cls index 3cad053..5b1f394 100644 --- a/MDX2JSON/AbstractREST.cls +++ b/MDX2JSON/AbstractREST.cls @@ -47,7 +47,7 @@ ClassMethod OnPreDispatch(pUrl As %String, pMethod As %String, ByRef pContinue A zn Namespace } - Quit $$$OK + return pContinue } /// Converts request into UTF8. Converts request into proxyObject. From 74e625b3378f5a1342a4f971587550c3924b3939 Mon Sep 17 00:00:00 2001 From: Dmitrij Vladimirov <47441164+Frisle@users.noreply.github.com> Date: Tue, 21 Nov 2023 20:47:43 +0600 Subject: [PATCH 53/77] FIX: hot fix. method without return --- MDX2JSON/AbstractREST.cls | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MDX2JSON/AbstractREST.cls b/MDX2JSON/AbstractREST.cls index 5b1f394..c9be0b7 100644 --- a/MDX2JSON/AbstractREST.cls +++ b/MDX2JSON/AbstractREST.cls @@ -39,7 +39,7 @@ ClassMethod OnPreDispatch(pUrl As %String, pMethod As %String, ByRef pContinue A If $$$ISERR(st) { #; Do ..Http500(st) Set pContinue = $$$NO - Quit + Quit st } #; Dispatch @@ -47,7 +47,7 @@ ClassMethod OnPreDispatch(pUrl As %String, pMethod As %String, ByRef pContinue A zn Namespace } - return pContinue + Quit $$$OK } /// Converts request into UTF8. Converts request into proxyObject. From bbd9ebb32b3ceb69be80e26ee0de05693f7c38d2 Mon Sep 17 00:00:00 2001 From: ProjectBot Date: Tue, 21 Nov 2023 14:49:34 +0000 Subject: [PATCH 54/77] auto bump version --- module.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module.xml b/module.xml index 2fd4417..2e7f86e 100644 --- a/module.xml +++ b/module.xml @@ -2,7 +2,7 @@ MDX2JSON - 3.2.38 + 3.2.39 RESTful web api for MDX to JSON transformation (plus JSONP and XML/A) for InterSystems IRIS. Also provides information about DeepSee objects. module ./ From 7b5cfb84fb5315bfc5c4b22a44448c1f3f5453f8 Mon Sep 17 00:00:00 2001 From: Dmitrij Vladimirov <47441164+Frisle@users.noreply.github.com> Date: Tue, 23 Apr 2024 12:52:05 +0500 Subject: [PATCH 55/77] REFACTOR: changed case of the parameter Filter Changed "Filter" to UPPERCASE "FILTER" --- MDX2JSON/REST.cls | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MDX2JSON/REST.cls b/MDX2JSON/REST.cls index 0a23d79..7d1d94b 100644 --- a/MDX2JSON/REST.cls +++ b/MDX2JSON/REST.cls @@ -292,7 +292,7 @@ ClassMethod KPIExecute() As %Status if (Drillthrough = 1){ set SortOrder = $$$R("SortOrder") - set Filters = $$$R("Filters") + set Filters = $$$R("FILTERS") set SortColumn = $$$R("SortColumn") set pSelection = SortColumn _ "," _ SortOrder From a59b8b755f5ca1b3bcc66e1b35b61554c8187a6d Mon Sep 17 00:00:00 2001 From: Dmitrij Vladimirov <47441164+Frisle@users.noreply.github.com> Date: Wed, 24 Apr 2024 07:56:52 +0500 Subject: [PATCH 56/77] REFACTOR: added logic in case of different letter case --- MDX2JSON/REST.cls | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/MDX2JSON/REST.cls b/MDX2JSON/REST.cls index 7d1d94b..170e603 100644 --- a/MDX2JSON/REST.cls +++ b/MDX2JSON/REST.cls @@ -292,7 +292,15 @@ ClassMethod KPIExecute() As %Status if (Drillthrough = 1){ set SortOrder = $$$R("SortOrder") - set Filters = $$$R("FILTERS") + + if %request.Content.FILTERS + { + set Filters = $$$R("FILTERS") + + }else{ + set Filters = $$$R("Filters") + } + set SortColumn = $$$R("SortColumn") set pSelection = SortColumn _ "," _ SortOrder From 3564bd0a2f321a88ef45f3a0b6a4e7d255dc0aa9 Mon Sep 17 00:00:00 2001 From: ProjectBot Date: Wed, 24 Apr 2024 16:56:22 +0000 Subject: [PATCH 57/77] auto bump version --- module.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module.xml b/module.xml index 2e7f86e..36d0abf 100644 --- a/module.xml +++ b/module.xml @@ -2,7 +2,7 @@ MDX2JSON - 3.2.39 + 3.2.40 RESTful web api for MDX to JSON transformation (plus JSONP and XML/A) for InterSystems IRIS. Also provides information about DeepSee objects. module ./ From 19ace35857d37fdc391574b5ad9047f3caecb23c Mon Sep 17 00:00:00 2001 From: Frisle <47441164+Frisle@users.noreply.github.com> Date: Tue, 9 Jul 2024 10:46:06 +0600 Subject: [PATCH 58/77] FEAT: add audit system Audit mechanism is simple the globals holding the runtime date each time when elements are called --- MDX2JSON/Utils.cls | 143 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 139 insertions(+), 4 deletions(-) diff --git a/MDX2JSON/Utils.cls b/MDX2JSON/Utils.cls index 0f054a5..9d99805 100644 --- a/MDX2JSON/Utils.cls +++ b/MDX2JSON/Utils.cls @@ -60,6 +60,8 @@ ClassMethod WriteJSONfromMDX(MDX As %String, Timeout As %Integer = 0) As %Status Set tSC = $$$OK #dim RS As MDX2JSON.ResultSet + set start = $PIECE($NOW(),",",2) + set RS = ..GetResultSet(MDX, .tSC) set cube = ##class(%DeepSee.Utils).%IsCubeCompound(RS.%Cube) // check if cube is compound type return:$$$ISERR(tSC) tSC @@ -87,6 +89,14 @@ ClassMethod WriteJSONfromMDX(MDX As %String, Timeout As %Integer = 0) As %Status return:$$$ISERR(tSC) tSC $$$DynObjToJSON(obj) } + + set stop = $PIECE($NOW(),",",2) + + set executionTime = stop - start + set query = RS.%GetQuery() + + set audit = ..WriteAudit(MDX, "query", executionTime) + return $$$OK } @@ -108,7 +118,6 @@ 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 @@ -133,7 +142,6 @@ ClassMethod GetSQLValues(pSQL, Output pValues As %String, Output tResultSet As % 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. @@ -309,7 +317,8 @@ ClassMethod GetDataSource(pDataSource As %String) set st = $$$OK try { - + set start = $PIECE($NOW(),",",2) + if ($FIND(pDataSource, ".pivot") = ($LENGTH(pDataSource) + 1) && pDataSource '="") { set st = ..OpenPivotByName(pDataSource, .dataSource) return:($$$ISERR(st)) st @@ -320,8 +329,16 @@ ClassMethod GetDataSource(pDataSource As %String) set dataSource.mdx = mdx } set st = ##class(%ZEN.Auxiliary.jsonProvider).%ObjectToJSON(dataSource, .out) + + set stop = $PIECE($NOW(),",",2) + + set executionTime = stop - start + + set audit = ..WriteAudit(pDataSource, "pivot", executionTime) + } + } catch ex { set st = ex.AsStatus() @@ -409,12 +426,22 @@ ClassMethod GetWidgetsList(pDashName As %String) As %Status ClassMethod GetDashboard(pDashName As %String) As %Status { try { + set start = $PIECE($NOW(),",",2) + 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 stop = $PIECE($NOW(),",",2) + + set executionTime = stop - start + + set audit = ..WriteAudit(pDashName, "dashboard", executionTime) + + $$$DynObjToJSON(widgetlist) } catch ex { set st = ex.AsStatus() @@ -557,6 +584,115 @@ ClassMethod CreateAddonClass(Class As %Dictionary.CacheClassname) As %Status quit classObj.%Save() } +ClassMethod WriteAudit(element, elementName, executionTime = 0) As %Status +{ + set st = $$$OK + + set ^CallAmount($INCREMENT(^CallAmount)) = 1 + + + if ^AuditState = "on" + { + if elementName = "dashboard" + { + set ^MyBIAuditLogDash($INCREMENT(^MyBIAuditLogDash)) = $lb($ZDT($H,3), $USERNAME, element, executionTime) + } + elseif elementName = "pivot" + { + set ^MyBIAuditLogPivot($INCREMENT(^MyBIAuditLogPivot)) = $lb($ZDT($H,3), $USERNAME, element, executionTime) + } + elseif elementName = "query" + { + set ^MyBIAuditLogQuery($INCREMENT(^MyBIAuditLogQuery)) = $lb($ZDT($H,3), $USERNAME, element, executionTime) + } + + + }else{ + + quit st + } + + + return st +} + +ClassMethod ReadAudit(metricName) As %Status +{ + set st = $$$OK + + if ^AuditState = "on" + { + if metricName = "query" + { + + set len = $order(^MyBIAuditLogQuery(""),-1) + for n=1:1:len + { + set log = $Get(^MyBIAuditLogQuery(n)) + write ! + write "Element call time: ", $lg(log, 1), ! + write "User: ", $lg(log, 2), ! + write "Execution time in sec.: ", $lg(log, 4), ! + write "Query: ", $lg(log, 3), ! + } + } + elseif metricName = "pivot" + { + + set len = $order(^MyBIAuditLogPivot(""),-1) + for n=1:1:len + { + set log = $Get(^MyBIAuditLogPivot(n)) + write ! + write "Element call time: ", $lg(log, 1), ! + write "User: ", $lg(log, 2), ! + write "Execution time in sec.: ", $lg(log, 4), ! + write "Pivot: ", $lg(log, 3), ! + } + } + elseif metricName = "dashboard" + { + set len = $order(^MyBIAuditLogDash(""),-1) + for n=1:1:len + { + set log = $Get(^MyBIAuditLogDash(n)) + write ! + write "Element call time: ", $lg(log, 1), ! + write "User: ", $lg(log, 2), ! + write "Execution time in sec.: ", $lg(log, 4), ! + write "Dashboard: ", $lg(log, 3), ! + } + } + } + + quit st +} + +ClassMethod AuditStateSwitch(auditstate = 0) As %Status +{ + set st = $$$OK + + if auditstate = 0 + { + set ^AuditState = "off" + + }else{ + + set ^AuditState = "on" + } + + write "Audit state: " _ ^AuditState +} + +ClassMethod AuditKill() As %Status +{ + kill ^MyBIAuditLogDash + kill ^MyBIAuditLogPivot + kill ^MyBIAuditLogQuery + + write "All globals are cleaned" +} + /// 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 @@ -672,7 +808,6 @@ ClassMethod DeleteWidget(wName As %String, sDashboard As %String) As %Status return st } - /// the collection of necessary parameters for building widget ClassMethod UpdateWidget(widgetToUpdate As %DeepSee.Dashboard.Widget, data As %ZEN.proxyObject) As %Status { From 281d8df66dec42ec8d2553aa28602d958c40ef00 Mon Sep 17 00:00:00 2001 From: Frisle <47441164+Frisle@users.noreply.github.com> Date: Thu, 11 Jul 2024 08:59:32 +0600 Subject: [PATCH 59/77] FEAT: added globals check to corresponding methods --- MDX2JSON/Utils.cls | 146 ++++----------------------------------------- 1 file changed, 11 insertions(+), 135 deletions(-) diff --git a/MDX2JSON/Utils.cls b/MDX2JSON/Utils.cls index 9d99805..efaf587 100644 --- a/MDX2JSON/Utils.cls +++ b/MDX2JSON/Utils.cls @@ -60,8 +60,6 @@ ClassMethod WriteJSONfromMDX(MDX As %String, Timeout As %Integer = 0) As %Status Set tSC = $$$OK #dim RS As MDX2JSON.ResultSet - set start = $PIECE($NOW(),",",2) - set RS = ..GetResultSet(MDX, .tSC) set cube = ##class(%DeepSee.Utils).%IsCubeCompound(RS.%Cube) // check if cube is compound type return:$$$ISERR(tSC) tSC @@ -78,6 +76,10 @@ ClassMethod WriteJSONfromMDX(MDX As %String, Timeout As %Integer = 0) As %Status set obj = RS.ToProxyObject(.tSC) return:$$$ISERR(tSC) tSC + + // 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 @@ -87,15 +89,12 @@ ClassMethod WriteJSONfromMDX(MDX As %String, Timeout As %Integer = 0) As %Status set obj = RS.ToProxyObject(.tSC) return:$$$ISERR(tSC) tSC - $$$DynObjToJSON(obj) - } - set stop = $PIECE($NOW(),",",2) + // check if audit global hold something and execute it + try {xecute ^DeepSee.AuditQueryCode} catch {} - set executionTime = stop - start - set query = RS.%GetQuery() - - set audit = ..WriteAudit(MDX, "query", executionTime) + $$$DynObjToJSON(obj) + } return $$$OK } @@ -317,7 +316,6 @@ ClassMethod GetDataSource(pDataSource As %String) set st = $$$OK try { - set start = $PIECE($NOW(),",",2) if ($FIND(pDataSource, ".pivot") = ($LENGTH(pDataSource) + 1) && pDataSource '="") { set st = ..OpenPivotByName(pDataSource, .dataSource) @@ -329,13 +327,6 @@ ClassMethod GetDataSource(pDataSource As %String) set dataSource.mdx = mdx } set st = ##class(%ZEN.Auxiliary.jsonProvider).%ObjectToJSON(dataSource, .out) - - set stop = $PIECE($NOW(),",",2) - - set executionTime = stop - start - - set audit = ..WriteAudit(pDataSource, "pivot", executionTime) - } @@ -426,22 +417,16 @@ ClassMethod GetWidgetsList(pDashName As %String) As %Status ClassMethod GetDashboard(pDashName As %String) As %Status { try { - set start = $PIECE($NOW(),",",2) - 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 stop = $PIECE($NOW(),",",2) - - set executionTime = stop - start - - set audit = ..WriteAudit(pDashName, "dashboard", executionTime) - + // check if audit global hold something and execute it + try {xecute ^DeepSee.AuditCode} catch {} + $$$DynObjToJSON(widgetlist) } catch ex { set st = ex.AsStatus() @@ -584,115 +569,6 @@ ClassMethod CreateAddonClass(Class As %Dictionary.CacheClassname) As %Status quit classObj.%Save() } -ClassMethod WriteAudit(element, elementName, executionTime = 0) As %Status -{ - set st = $$$OK - - set ^CallAmount($INCREMENT(^CallAmount)) = 1 - - - if ^AuditState = "on" - { - if elementName = "dashboard" - { - set ^MyBIAuditLogDash($INCREMENT(^MyBIAuditLogDash)) = $lb($ZDT($H,3), $USERNAME, element, executionTime) - } - elseif elementName = "pivot" - { - set ^MyBIAuditLogPivot($INCREMENT(^MyBIAuditLogPivot)) = $lb($ZDT($H,3), $USERNAME, element, executionTime) - } - elseif elementName = "query" - { - set ^MyBIAuditLogQuery($INCREMENT(^MyBIAuditLogQuery)) = $lb($ZDT($H,3), $USERNAME, element, executionTime) - } - - - }else{ - - quit st - } - - - return st -} - -ClassMethod ReadAudit(metricName) As %Status -{ - set st = $$$OK - - if ^AuditState = "on" - { - if metricName = "query" - { - - set len = $order(^MyBIAuditLogQuery(""),-1) - for n=1:1:len - { - set log = $Get(^MyBIAuditLogQuery(n)) - write ! - write "Element call time: ", $lg(log, 1), ! - write "User: ", $lg(log, 2), ! - write "Execution time in sec.: ", $lg(log, 4), ! - write "Query: ", $lg(log, 3), ! - } - } - elseif metricName = "pivot" - { - - set len = $order(^MyBIAuditLogPivot(""),-1) - for n=1:1:len - { - set log = $Get(^MyBIAuditLogPivot(n)) - write ! - write "Element call time: ", $lg(log, 1), ! - write "User: ", $lg(log, 2), ! - write "Execution time in sec.: ", $lg(log, 4), ! - write "Pivot: ", $lg(log, 3), ! - } - } - elseif metricName = "dashboard" - { - set len = $order(^MyBIAuditLogDash(""),-1) - for n=1:1:len - { - set log = $Get(^MyBIAuditLogDash(n)) - write ! - write "Element call time: ", $lg(log, 1), ! - write "User: ", $lg(log, 2), ! - write "Execution time in sec.: ", $lg(log, 4), ! - write "Dashboard: ", $lg(log, 3), ! - } - } - } - - quit st -} - -ClassMethod AuditStateSwitch(auditstate = 0) As %Status -{ - set st = $$$OK - - if auditstate = 0 - { - set ^AuditState = "off" - - }else{ - - set ^AuditState = "on" - } - - write "Audit state: " _ ^AuditState -} - -ClassMethod AuditKill() As %Status -{ - kill ^MyBIAuditLogDash - kill ^MyBIAuditLogPivot - kill ^MyBIAuditLogQuery - - write "All globals are cleaned" -} - /// 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 From 87840c0544aba7bcc6bb323326e99ec55393126d Mon Sep 17 00:00:00 2001 From: Frisle <47441164+Frisle@users.noreply.github.com> Date: Fri, 12 Jul 2024 15:14:55 +0600 Subject: [PATCH 60/77] FEAT: add audit callback and global audit globals --- MDX2JSON/Utils.cls | 57 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/MDX2JSON/Utils.cls b/MDX2JSON/Utils.cls index efaf587..88201d1 100644 --- a/MDX2JSON/Utils.cls +++ b/MDX2JSON/Utils.cls @@ -53,6 +53,11 @@ 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 @@ -77,6 +82,13 @@ ClassMethod WriteJSONfromMDX(MDX As %String, Timeout As %Integer = 0) As %Status 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 {} @@ -90,12 +102,16 @@ ClassMethod WriteJSONfromMDX(MDX As %String, Timeout As %Integer = 0) As %Status 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 } @@ -417,13 +433,16 @@ 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 {} @@ -435,6 +454,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 { From cf70593f93038d86f30d6864a61b0a5fbc13a7ff Mon Sep 17 00:00:00 2001 From: ProjectBot Date: Fri, 12 Jul 2024 15:48:28 +0000 Subject: [PATCH 61/77] auto bump version --- module.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module.xml b/module.xml index 36d0abf..f86dfbe 100644 --- a/module.xml +++ b/module.xml @@ -2,7 +2,7 @@ MDX2JSON - 3.2.40 + 3.2.41 RESTful web api for MDX to JSON transformation (plus JSONP and XML/A) for InterSystems IRIS. Also provides information about DeepSee objects. module ./ From 9564f84030c600facbed7e4084abb6531430d7c2 Mon Sep 17 00:00:00 2001 From: Jakcpto <41373877+jakcpto@users.noreply.github.com> Date: Fri, 6 Jun 2025 09:13:52 +0400 Subject: [PATCH 62/77] add prefix to Addons --- MDX2JSON/REST.cls | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/MDX2JSON/REST.cls b/MDX2JSON/REST.cls index 170e603..cc22744 100644 --- a/MDX2JSON/REST.cls +++ b/MDX2JSON/REST.cls @@ -422,7 +422,9 @@ ClassMethod WriteAddons() As %Status { #dim sc As %Status = $$$OK - set app = "/dsw" + set defaultApp = $System.CSP.GetDefaultApp($Namespace) + set prefix = $piece(defaultApp, "/csp", 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) @@ -447,7 +449,9 @@ ClassMethod WriteThemes() As %Status { #dim sc As %Status = $$$OK - set app = "/dsw" + set defaultApp = $System.CSP.GetDefaultApp($Namespace) + set prefix = $piece(defaultApp, "/csp", 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) From 55523daec9f0d7b65197c8524818582449385101 Mon Sep 17 00:00:00 2001 From: Jakcpto Date: Fri, 6 Jun 2025 16:06:08 +0400 Subject: [PATCH 63/77] CurrentApp for Debugging print --- MDX2JSON/REST.cls | 5 ++--- docker-compose.yaml | 13 +++++++++++++ 2 files changed, 15 insertions(+), 3 deletions(-) create mode 100644 docker-compose.yaml diff --git a/MDX2JSON/REST.cls b/MDX2JSON/REST.cls index cc22744..881cc94 100644 --- a/MDX2JSON/REST.cls +++ b/MDX2JSON/REST.cls @@ -123,6 +123,7 @@ ClassMethod Test() As %Status set obj.Parent = ##class(MDX2JSON.Tests).#LastCommit set obj.ParentTS = ##class(MDX2JSON.Tests).#LastCommitTS set obj.DefaultApp = $System.CSP.GetDefaultApp($Namespace) + set obj.CurrentApp = $get(%request.Application) set obj.Mappings = ..GetMappings() if $$$Debug { set obj.Roles = $Roles @@ -154,7 +155,6 @@ ClassMethod saveWidget() As %Status return ##class(MDX2JSON.Utils).AddWidget(widgetData,dashboardData,key) } - /// Get all data sources including "pivot", "kpi", "worksheets","metrics" ClassMethod GetListDataSources(Source) As %Status { @@ -193,7 +193,6 @@ ClassMethod GetListDataSources(Source) As %Status quit tSC } - ClassMethod GetDataSource() As %Status { return ##class(MDX2JSON.Utils).GetDataSource($$$R("DataSource")) @@ -282,7 +281,7 @@ ClassMethod WriteFiltersForDataSource() As %Status return st } -///Execute requests from kpi +/// Execute requests from kpi ClassMethod KPIExecute() As %Status { try{ diff --git a/docker-compose.yaml b/docker-compose.yaml new file mode 100644 index 0000000..b811c4f --- /dev/null +++ b/docker-compose.yaml @@ -0,0 +1,13 @@ +version: '3.8' +services: + iris: + image: intersystemsdc/iris-community:latest + container_name: iris + ports: + - "52773:52773" # Management Portal + - "1972:1972" # SuperServer + volumes: + - ./:/irisdev/app # Примонтировать исходники в контейнер + # environment: + # - ISC_DATA_DIRECTORY=/irisdev/data + command: --check-caps false From 79254da3c444e94309514bd8876d78238499a8ff Mon Sep 17 00:00:00 2001 From: Jakcpto Date: Mon, 9 Jun 2025 21:53:36 +0400 Subject: [PATCH 64/77] Prefix Support for Addons and Themes --- MDX2JSON/REST.cls | 29 +++++++++++++++++++++-------- docker-compose.yaml | 13 ------------- 2 files changed, 21 insertions(+), 21 deletions(-) delete mode 100644 docker-compose.yaml diff --git a/MDX2JSON/REST.cls b/MDX2JSON/REST.cls index 881cc94..a39dae3 100644 --- a/MDX2JSON/REST.cls +++ b/MDX2JSON/REST.cls @@ -123,7 +123,6 @@ ClassMethod Test() As %Status set obj.Parent = ##class(MDX2JSON.Tests).#LastCommit set obj.ParentTS = ##class(MDX2JSON.Tests).#LastCommitTS set obj.DefaultApp = $System.CSP.GetDefaultApp($Namespace) - set obj.CurrentApp = $get(%request.Application) set obj.Mappings = ..GetMappings() if $$$Debug { set obj.Roles = $Roles @@ -155,6 +154,7 @@ ClassMethod saveWidget() As %Status return ##class(MDX2JSON.Utils).AddWidget(widgetData,dashboardData,key) } + /// Get all data sources including "pivot", "kpi", "worksheets","metrics" ClassMethod GetListDataSources(Source) As %Status { @@ -193,6 +193,7 @@ ClassMethod GetListDataSources(Source) As %Status quit tSC } + ClassMethod GetDataSource() As %Status { return ##class(MDX2JSON.Utils).GetDataSource($$$R("DataSource")) @@ -281,7 +282,7 @@ ClassMethod WriteFiltersForDataSource() As %Status return st } -/// Execute requests from kpi +///Execute requests from kpi ClassMethod KPIExecute() As %Status { try{ @@ -420,14 +421,20 @@ ClassMethod WritePivotVariablesForCube(Cube As %String) As %Status ClassMethod WriteAddons() As %Status { #dim sc As %Status = $$$OK - - set defaultApp = $System.CSP.GetDefaultApp($Namespace) - set prefix = $piece(defaultApp, "/csp", 1) + + 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") @@ -448,14 +455,20 @@ ClassMethod WriteThemes() As %Status { #dim sc As %Status = $$$OK - set defaultApp = $System.CSP.GetDefaultApp($Namespace) - set prefix = $piece(defaultApp, "/csp", 1) + 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 @@ -477,4 +490,4 @@ ClassMethod WriteJSONfromKPI() As %Status [ CodeMode = objectgenerator ] do %code.Write(base) } -} +} \ No newline at end of file diff --git a/docker-compose.yaml b/docker-compose.yaml deleted file mode 100644 index b811c4f..0000000 --- a/docker-compose.yaml +++ /dev/null @@ -1,13 +0,0 @@ -version: '3.8' -services: - iris: - image: intersystemsdc/iris-community:latest - container_name: iris - ports: - - "52773:52773" # Management Portal - - "1972:1972" # SuperServer - volumes: - - ./:/irisdev/app # Примонтировать исходники в контейнер - # environment: - # - ISC_DATA_DIRECTORY=/irisdev/data - command: --check-caps false From 3b9aab1383a13aa1e29aa2f5dbe7489c1e717286 Mon Sep 17 00:00:00 2001 From: ProjectBot Date: Tue, 10 Jun 2025 08:07:04 +0000 Subject: [PATCH 65/77] auto bump version --- module.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module.xml b/module.xml index f86dfbe..d10a615 100644 --- a/module.xml +++ b/module.xml @@ -2,7 +2,7 @@ MDX2JSON - 3.2.41 + 3.2.42 RESTful web api for MDX to JSON transformation (plus JSONP and XML/A) for InterSystems IRIS. Also provides information about DeepSee objects. module ./ From 6f4bdafd4358bb6db5274f1ec9322c182488964d Mon Sep 17 00:00:00 2001 From: Frisle <47441164+Frisle@users.noreply.github.com> Date: Sat, 5 Jul 2025 16:49:14 +0500 Subject: [PATCH 66/77] FIX: fixed issue when series were procesed even they filtered out --- MDX2JSON/ResultSet.cls | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/MDX2JSON/ResultSet.cls b/MDX2JSON/ResultSet.cls index 19e85cd..624554a 100644 --- a/MDX2JSON/ResultSet.cls +++ b/MDX2JSON/ResultSet.cls @@ -19,8 +19,6 @@ Method ToProxyObject(Output pStatus As %Status) As %ZEN.proxyObject return "" } - set tQueryKey = ..%QueryKey - /*set st = ..%GetQueryStatus(..%Cube,tQueryKey) if (st < 100) { hang 1 @@ -95,11 +93,10 @@ Method AxesToListOfObjects() As %ListOfObjects } set axes=$$$NewDynObjList - for a = 1:1:tAxisCount { set tAxisSize(a) = ..%GetAxisSize(a) set tAxisKeys(a) = $G($$$DeepSeeResultsGLVN(tCubeIndex,tQueryKey,"axis",a)) - $$$Insert(axes,..ProcessOneAxis(tCubeIndex,tAxisKeys(a),a)) + $$$Insert(axes,..ProcessOneAxis(tCubeIndex,tAxisKeys(a),a,tAxisSize(a))) } if ($$$ListSize(axes)=0) { @@ -109,32 +106,31 @@ Method AxesToListOfObjects() As %ListOfObjects return axes } -Method ProcessOneAxis(CubeIndex, AxisKey, AxisNumber) As %ZEN.proxyObject [ Internal ] +Method ProcessOneAxis(CubeIndex, AxisKey, AxisNumber, AxisSize) As %ZEN.proxyObject [ Internal ] { set tCubeName = $$$UPPER(..%Cube) set tQueryKey = ..%QueryKey set axis=$$$NewDynObj - set axis.tuples = ..ProcessOneAxisCell(CubeIndex, AxisKey, tCubeName, tQueryKey, AxisNumber, 1) + set axis.tuples = ..ProcessOneAxisCell(CubeIndex, AxisKey, tCubeName, tQueryKey, AxisNumber, 1, AxisSize) return axis } -Method ProcessOneAxisCell(CubeIndex, AxisKey, CubeName, QueryKey, AxisNumber, Node) As %ZEN.proxyObject [ Internal ] +Method ProcessOneAxisCell(CubeIndex, AxisKey, CubeName, QueryKey, AxisNumber, Node, AxisSize) As %ZEN.proxyObject [ Internal ] { set cell=$$$NewDynObj set tNode = $G($$$DeepSeeAxisGLVN(CubeIndex,AxisKey,"axes",Node)) - set cell.caption = ##class(%DeepSee.UserPortal.Utils).%ResolveText($LG(tNode,5)) // text caption 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) { set cell.children = $$$NewDynObjList - set key = $O($$$DeepSeeAxisGLVN(CubeIndex, AxisKey, "axes", Node, "ch", "")) - while (key'="") { - set children = ..ProcessOneAxisCell(CubeIndex, AxisKey, CubeName, QueryKey, AxisNumber, key) + for i=1:1:AxisSize + { + set key = $G(@..%ResultCacheLocation@(..%CubeKey,..%QueryKey,"leaf",AxisNumber,i)) + set children = ..ProcessOneAxisCell(CubeIndex, AxisKey, CubeName, QueryKey, AxisNumber, key,) // Append children to cell if $isobject(children) { if ((children.%IsA("%ZEN.proxyObject")) || (children.%IsA("%Library.Object"))) { @@ -145,8 +141,6 @@ Method ProcessOneAxisCell(CubeIndex, AxisKey, CubeName, QueryKey, AxisNumber, No } } } - - set key = $O($$$DeepSeeAxisGLVN(CubeIndex, AxisKey, "axes", Node, "ch", key)) } } From 830c9ce83d2bf4948e05748a6bd05f8577455fb7 Mon Sep 17 00:00:00 2001 From: ProjectBot Date: Mon, 7 Jul 2025 23:28:59 +0000 Subject: [PATCH 67/77] auto bump version --- module.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module.xml b/module.xml index d10a615..6adbd96 100644 --- a/module.xml +++ b/module.xml @@ -2,7 +2,7 @@ MDX2JSON - 3.2.42 + 3.2.43 RESTful web api for MDX to JSON transformation (plus JSONP and XML/A) for InterSystems IRIS. Also provides information about DeepSee objects. module ./ From bba3c1decb09c9e4ec61c70f5d9e67f468f7f6ea Mon Sep 17 00:00:00 2001 From: Eduard Date: Tue, 8 Jul 2025 02:29:10 +0300 Subject: [PATCH 68/77] Update module.xml --- module.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module.xml b/module.xml index 6adbd96..a7100f3 100644 --- a/module.xml +++ b/module.xml @@ -2,7 +2,7 @@ MDX2JSON - 3.2.43 + 3.2.44 RESTful web api for MDX to JSON transformation (plus JSONP and XML/A) for InterSystems IRIS. Also provides information about DeepSee objects. module ./ From f7b5bc997ec655aa2f5bf15f1b6ef5e6e6125640 Mon Sep 17 00:00:00 2001 From: ProjectBot Date: Mon, 7 Jul 2025 23:29:18 +0000 Subject: [PATCH 69/77] auto bump version --- module.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module.xml b/module.xml index a7100f3..9551185 100644 --- a/module.xml +++ b/module.xml @@ -2,7 +2,7 @@ MDX2JSON - 3.2.44 + 3.2.45 RESTful web api for MDX to JSON transformation (plus JSONP and XML/A) for InterSystems IRIS. Also provides information about DeepSee objects. module ./ From 459d70ca2ad11308faffe0f4ff069a800d578bde Mon Sep 17 00:00:00 2001 From: Frisle <47441164+Frisle@users.noreply.github.com> Date: Wed, 9 Jul 2025 12:39:37 +0500 Subject: [PATCH 70/77] FIX: new round of fixing. this time the new version were tested on a client machine and fix works --- MDX2JSON/ResultSet.cls | 30 ++++++++++++++++++------------ module.xml | 2 +- 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/MDX2JSON/ResultSet.cls b/MDX2JSON/ResultSet.cls index 624554a..0e8b8db 100644 --- a/MDX2JSON/ResultSet.cls +++ b/MDX2JSON/ResultSet.cls @@ -111,39 +111,45 @@ Method ProcessOneAxis(CubeIndex, AxisKey, AxisNumber, AxisSize) As %ZEN.proxyObj set tCubeName = $$$UPPER(..%Cube) set tQueryKey = ..%QueryKey - set axis=$$$NewDynObj - set axis.tuples = ..ProcessOneAxisCell(CubeIndex, AxisKey, tCubeName, tQueryKey, AxisNumber, 1, AxisSize) + set axis = ..LoopProcessingAxisCells(CubeIndex, AxisKey, tCubeName, tQueryKey, AxisNumber, 1,AxisSize) return axis } -Method ProcessOneAxisCell(CubeIndex, AxisKey, CubeName, QueryKey, AxisNumber, Node, AxisSize) As %ZEN.proxyObject [ Internal ] +Method LoopProcessingAxisCells(CubeIndex, AxisKey, CubeName, QueryKey, AxisNumber, Node, AxisSize) As %ZEN.proxyObject [ Internal ] { - set cell=$$$NewDynObj - set tNode = $G($$$DeepSeeAxisGLVN(CubeIndex,AxisKey,"axes",Node)) - set cell.caption = ##class(%DeepSee.UserPortal.Utils).%ResolveText($LG(tNode,5)) // text caption - 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 + set axis=$$$NewDynObj + if ($D($$$DeepSeeAxisGLVN(CubeIndex, AxisKey, "axes", Node, "ch")) = 10) { - set cell.children = $$$NewDynObjList + set axis.tuples = $$$NewDynObjList for i=1:1:AxisSize { set key = $G(@..%ResultCacheLocation@(..%CubeKey,..%QueryKey,"leaf",AxisNumber,i)) - set children = ..ProcessOneAxisCell(CubeIndex, AxisKey, CubeName, QueryKey, AxisNumber, key,) + set children = ..ProcessOneAxisCell(CubeIndex, AxisKey, CubeName, QueryKey, AxisNumber, key) // Append children to cell if $isobject(children) { if ((children.%IsA("%ZEN.proxyObject")) || (children.%IsA("%Library.Object"))) { - $$$Insert(cell.children,children) + $$$Insert(axis.tuples,children) } elseif ((children.%IsA("%Collection.AbstractList")) || (children.%IsA("%Library.Array"))) { for i=1:1:$$$ListSize(children) { - $$$Insert(cell.children,$$$ListGet(children,i)) + $$$Insert(axis.tuples,$$$ListGet(children,i)) } } } } } + return axis +} + +Method ProcessOneAxisCell(CubeIndex, AxisKey, CubeName, QueryKey, AxisNumber, Node) As %ZEN.proxyObject [ Internal ] +{ + set cell=$$$NewDynObj + set tNode = $G($$$DeepSeeAxisGLVN(CubeIndex,AxisKey,"axes",Node)) + set cell.caption = ##class(%DeepSee.UserPortal.Utils).%ResolveText($LG(tNode,5)) // text caption + set cell.vis = $LG(tNode,2) // visibility helper - does not help (apperently it shows if the cell is the lowest level) + //To filter out invisible сells if (..IsCellNull(cell)=1) { return cell.children diff --git a/module.xml b/module.xml index 9551185..9ebab46 100644 --- a/module.xml +++ b/module.xml @@ -2,7 +2,7 @@ MDX2JSON - 3.2.45 + 3.2.46 RESTful web api for MDX to JSON transformation (plus JSONP and XML/A) for InterSystems IRIS. Also provides information about DeepSee objects. module ./ From 546c31f6ffa07b37b43c6853018c053411c56ecd Mon Sep 17 00:00:00 2001 From: ProjectBot Date: Wed, 9 Jul 2025 12:27:21 +0000 Subject: [PATCH 71/77] auto bump version --- module.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module.xml b/module.xml index 9ebab46..9d5923f 100644 --- a/module.xml +++ b/module.xml @@ -2,7 +2,7 @@ MDX2JSON - 3.2.46 + 3.2.47 RESTful web api for MDX to JSON transformation (plus JSONP and XML/A) for InterSystems IRIS. Also provides information about DeepSee objects. module ./ From eb6c186f94762fd7ed006fb0c54b9a36bcdec72a Mon Sep 17 00:00:00 2001 From: Frisle <47441164+Frisle@users.noreply.github.com> Date: Mon, 8 Sep 2025 21:03:40 +0500 Subject: [PATCH 72/77] FIX: rollback to the state of 3.2.23 version A lot of the optimization in this version has led to serious issues with child cells. It's slow in some scenarios, but at least it's accurate. --- MDX2JSON/ResultSet.cls | 84 +++++++++++++++++++++++------------------- 1 file changed, 46 insertions(+), 38 deletions(-) diff --git a/MDX2JSON/ResultSet.cls b/MDX2JSON/ResultSet.cls index 0e8b8db..4fe3ba8 100644 --- a/MDX2JSON/ResultSet.cls +++ b/MDX2JSON/ResultSet.cls @@ -19,6 +19,8 @@ Method ToProxyObject(Output pStatus As %Status) As %ZEN.proxyObject return "" } + set tQueryKey = ..%QueryKey + /*set st = ..%GetQueryStatus(..%Cube,tQueryKey) if (st < 100) { hang 1 @@ -33,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 { @@ -77,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 } @@ -93,10 +95,11 @@ Method AxesToListOfObjects() As %ListOfObjects } set axes=$$$NewDynObjList + for a = 1:1:tAxisCount { set tAxisSize(a) = ..%GetAxisSize(a) set tAxisKeys(a) = $G($$$DeepSeeResultsGLVN(tCubeIndex,tQueryKey,"axis",a)) - $$$Insert(axes,..ProcessOneAxis(tCubeIndex,tAxisKeys(a),a,tAxisSize(a))) + $$$Insert(axes,..ProcessOneAxis(tCubeIndex,tAxisKeys(a),a)) } if ($$$ListSize(axes)=0) { @@ -106,71 +109,68 @@ Method AxesToListOfObjects() As %ListOfObjects return axes } -Method ProcessOneAxis(CubeIndex, AxisKey, AxisNumber, AxisSize) As %ZEN.proxyObject [ Internal ] +Method ProcessOneAxis(CubeIndex, AxisKey, AxisNumber) As %ZEN.proxyObject [ Internal ] { set tCubeName = $$$UPPER(..%Cube) set tQueryKey = ..%QueryKey - set axis = ..LoopProcessingAxisCells(CubeIndex, AxisKey, tCubeName, tQueryKey, AxisNumber, 1,AxisSize) + set axis=$$$NewDynObj + set axis.tuples = ..ProcessOneAxisCell(CubeIndex, AxisKey, tCubeName, tQueryKey, AxisNumber, 1) return axis } -Method LoopProcessingAxisCells(CubeIndex, AxisKey, CubeName, QueryKey, AxisNumber, Node, AxisSize) As %ZEN.proxyObject [ Internal ] +Method ProcessOneAxisCell(CubeIndex, AxisKey, CubeName, QueryKey, AxisNumber, Node) As %ZEN.proxyObject [ Internal ] { + set cell=$$$NewDynObj - set axis=$$$NewDynObj + set tNode = $G($$$DeepSeeAxisGLVN(CubeIndex,AxisKey,"axes",Node)) + + set cell.caption = ##class(%DeepSee.UserPortal.Utils).%ResolveText($LG(tNode,5)) // text caption + 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) { - set axis.tuples = $$$NewDynObjList - for i=1:1:AxisSize - { - set key = $G(@..%ResultCacheLocation@(..%CubeKey,..%QueryKey,"leaf",AxisNumber,i)) + set cell.children = $$$NewDynObjList + set key = $O($$$DeepSeeAxisGLVN(CubeIndex, AxisKey, "axes", Node, "ch", "")) + while (key'="") { set children = ..ProcessOneAxisCell(CubeIndex, AxisKey, CubeName, QueryKey, AxisNumber, key) // Append children to cell if $isobject(children) { if ((children.%IsA("%ZEN.proxyObject")) || (children.%IsA("%Library.Object"))) { - $$$Insert(axis.tuples,children) + $$$Insert(cell.children,children) } elseif ((children.%IsA("%Collection.AbstractList")) || (children.%IsA("%Library.Array"))) { for i=1:1:$$$ListSize(children) { - $$$Insert(axis.tuples,$$$ListGet(children,i)) + $$$Insert(cell.children,$$$ListGet(children,i)) } } } + + set key = $O($$$DeepSeeAxisGLVN(CubeIndex, AxisKey, "axes", Node, "ch", key)) } } - return axis -} - -Method ProcessOneAxisCell(CubeIndex, AxisKey, CubeName, QueryKey, AxisNumber, Node) As %ZEN.proxyObject [ Internal ] -{ - set cell=$$$NewDynObj - set tNode = $G($$$DeepSeeAxisGLVN(CubeIndex,AxisKey,"axes",Node)) - set cell.caption = ##class(%DeepSee.UserPortal.Utils).%ResolveText($LG(tNode,5)) // text caption - set cell.vis = $LG(tNode,2) // visibility helper - does not help (apperently it shows if the cell is the lowest level) - //To filter out invisible сells - if (..IsCellNull(cell)=1) { + 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 @@ -198,10 +198,11 @@ Method ProcessOneAxisCell(CubeIndex, AxisKey, CubeName, QueryKey, AxisNumber, No return cell } -/// Determine if cell is an invisible system cell. -Method IsCellNull(Cell) +/// Determine if cell is an invisyble system cell. +Method IsCellNull(Cell, AxisNumber, Node) { - + return:((Cell.type = "axis") || (Cell.type = "set")) 1 // for top-level cells + return:(Cell.caption=0) 1 // typical caption for top-level cell return:(Cell.caption=1) 1 // typical caption for top-level cell return:(Cell.caption="") 1 // typical caption for top-level cell @@ -209,11 +210,18 @@ Method IsCellNull(Cell) //return:(path="") 1 set children = Cell.children return:(($isobject(children)) && ($$$ListSize(children)>0)) 0 // cell has children - - // in case of cell type='lit'. the 'lit' cell always has the value vis=0, so we can skip it - // this is also true for type='axis' and type='set' so there is no need to check everything individually - return:(Cell.vis '= 0) 0 - + + if (Cell.type'="lit") { + set key = $O($$$DeepSeeResultsGLVN(..%CubeKey, ..%QueryKey, "leaf", AxisNumber, "")) + while (key'="") { + return:(Node=$$$DeepSeeResultsGLVN(..%CubeKey, ..%QueryKey, "leaf", AxisNumber, key)) 0 //for leafs + set key = $O($$$DeepSeeResultsGLVN(..%CubeKey, ..%QueryKey, "leaf", AxisNumber, key)) + } + } else { + /// lit cell: SELECT %LABEL("Const","Title") ON 0 FROM [HoleFoodsBudget] + /// but also a lot of top-pevel cells + return 'Cell.vis + } return 1 } From d03566b362ac2e2706f9492996fbdd2c075ec2b4 Mon Sep 17 00:00:00 2001 From: ProjectBot Date: Mon, 8 Sep 2025 19:46:11 +0000 Subject: [PATCH 73/77] auto bump version --- module.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module.xml b/module.xml index 9d5923f..5239026 100644 --- a/module.xml +++ b/module.xml @@ -2,7 +2,7 @@ MDX2JSON - 3.2.47 + 3.2.48 RESTful web api for MDX to JSON transformation (plus JSONP and XML/A) for InterSystems IRIS. Also provides information about DeepSee objects. module ./ From 6625964930f870ecda37cdaf5eb5c7053e22818e Mon Sep 17 00:00:00 2001 From: Dmitrij Vladimirov <47441164+Frisle@users.noreply.github.com> Date: Wed, 8 Oct 2025 12:52:05 +0500 Subject: [PATCH 74/77] FIX: when axis with "agg" type received a children object --- MDX2JSON/ResultSet.cls | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MDX2JSON/ResultSet.cls b/MDX2JSON/ResultSet.cls index 4fe3ba8..210c64f 100644 --- a/MDX2JSON/ResultSet.cls +++ b/MDX2JSON/ResultSet.cls @@ -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'="") { From e2e895a6dfcc2f697e56187b3c801654583e6c72 Mon Sep 17 00:00:00 2001 From: ProjectBot Date: Wed, 8 Oct 2025 21:21:24 +0000 Subject: [PATCH 75/77] auto bump version --- module.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module.xml b/module.xml index 5239026..eda99e2 100644 --- a/module.xml +++ b/module.xml @@ -2,7 +2,7 @@ MDX2JSON - 3.2.48 + 3.2.49 RESTful web api for MDX to JSON transformation (plus JSONP and XML/A) for InterSystems IRIS. Also provides information about DeepSee objects. module ./ From 8ae5f4e1921ce8133bd54f7aeee1c954d599656f Mon Sep 17 00:00:00 2001 From: Dmitrij Vladimirov <47441164+Frisle@users.noreply.github.com> Date: Fri, 13 Feb 2026 11:00:06 +0500 Subject: [PATCH 76/77] REFACTOR: rework drillthrough processing Replaced deprecated class %ZEN.Auxilary with custom processing script. Fix error when SQL contain more that 13500 rows --- MDX2JSON/Utils.cls | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/MDX2JSON/Utils.cls b/MDX2JSON/Utils.cls index 88201d1..835322d 100644 --- a/MDX2JSON/Utils.cls +++ b/MDX2JSON/Utils.cls @@ -258,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 } @@ -782,3 +800,4 @@ ClassMethod UpdateWidget(widgetToUpdate As %DeepSee.Dashboard.Widget, data As %Z } } + From 79d5775c5f02d32db8b46421e0f56e8570415bd3 Mon Sep 17 00:00:00 2001 From: ProjectBot Date: Fri, 13 Feb 2026 06:05:32 +0000 Subject: [PATCH 77/77] auto bump version --- module.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module.xml b/module.xml index eda99e2..421185b 100644 --- a/module.xml +++ b/module.xml @@ -2,7 +2,7 @@ MDX2JSON - 3.2.49 + 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 ./