@dhis2/analytics 22.0.0-alpha.3 → 23.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +3009 -0
- package/build/cjs/__demo__/OpenFileDialog.stories.js +39 -6
- package/build/cjs/__fixtures__/fixtures.js +1 -0
- package/build/cjs/__fixtures__/json/api/analytics/enrollments.json +206 -0
- package/build/cjs/api/analytics/Analytics.js +6 -0
- package/build/cjs/api/analytics/AnalyticsEnrollments.js +48 -0
- package/build/cjs/api/analytics/__tests__/AnalyticsEnrollments.spec.js +50 -0
- package/build/cjs/api/analytics/__tests__/__snapshots__/AnalyticsEnrollments.spec.js.snap +3 -0
- package/build/cjs/components/CachedDataQueryProvider.js +4 -10
- package/build/cjs/components/FileMenu/FileMenu.js +6 -0
- package/build/cjs/components/OpenFileDialog/CustomSelectOption.js +18 -4
- package/build/cjs/components/OpenFileDialog/FileList.js +5 -5
- package/build/cjs/components/OpenFileDialog/OpenFileDialog.js +26 -21
- package/build/cjs/components/OpenFileDialog/OpenFileDialog.styles.js +2 -2
- package/build/cjs/components/OpenFileDialog/VisTypeFilter.js +17 -16
- package/build/cjs/components/OpenFileDialog/utils.js +33 -74
- package/build/cjs/index.js +16 -4
- package/build/cjs/locales/ar/translations.json +9 -0
- package/build/cjs/locales/ar_EG/translations.json +9 -0
- package/build/cjs/locales/ar_IQ/translations.json +9 -0
- package/build/cjs/locales/ckb/translations.json +9 -0
- package/build/cjs/locales/cs/translations.json +9 -0
- package/build/cjs/locales/da/translations.json +9 -0
- package/build/cjs/locales/en/translations.json +3 -21
- package/build/cjs/locales/es/translations.json +9 -0
- package/build/cjs/locales/fr/translations.json +9 -0
- package/build/cjs/locales/id/translations.json +9 -0
- package/build/cjs/locales/km/translations.json +9 -0
- package/build/cjs/locales/lo/translations.json +9 -0
- package/build/cjs/locales/my/translations.json +9 -0
- package/build/cjs/locales/nb/translations.json +9 -0
- package/build/cjs/locales/nl/translations.json +9 -0
- package/build/cjs/locales/prs/translations.json +9 -0
- package/build/cjs/locales/ps/translations.json +9 -0
- package/build/cjs/locales/pt/translations.json +9 -0
- package/build/cjs/locales/pt_BR/translations.json +9 -0
- package/build/cjs/locales/ru/translations.json +9 -0
- package/build/cjs/locales/sv/translations.json +9 -0
- package/build/cjs/locales/tet/translations.json +9 -0
- package/build/cjs/locales/tg/translations.json +9 -0
- package/build/cjs/locales/uk/translations.json +9 -0
- package/build/cjs/locales/ur/translations.json +9 -0
- package/build/cjs/locales/uz/translations.json +9 -0
- package/build/cjs/locales/uz_Latn/translations.json +9 -0
- package/build/cjs/locales/vi/translations.json +9 -0
- package/build/cjs/locales/zh/translations.json +10 -1
- package/build/cjs/locales/zh_CN/translations.json +9 -0
- package/build/cjs/modules/layoutUiRules/rules.js +5 -1
- package/build/cjs/modules/visTypes.js +14 -21
- package/build/es/__demo__/OpenFileDialog.stories.js +38 -6
- package/build/es/__fixtures__/fixtures.js +1 -0
- package/build/es/__fixtures__/json/api/analytics/enrollments.json +206 -0
- package/build/es/api/analytics/Analytics.js +5 -0
- package/build/es/api/analytics/AnalyticsEnrollments.js +38 -0
- package/build/es/api/analytics/__tests__/AnalyticsEnrollments.spec.js +40 -0
- package/build/es/api/analytics/__tests__/__snapshots__/AnalyticsEnrollments.spec.js.snap +3 -0
- package/build/es/components/CachedDataQueryProvider.js +4 -10
- package/build/es/components/FileMenu/FileMenu.js +6 -0
- package/build/es/components/OpenFileDialog/CustomSelectOption.js +17 -4
- package/build/es/components/OpenFileDialog/FileList.js +5 -5
- package/build/es/components/OpenFileDialog/OpenFileDialog.js +27 -23
- package/build/es/components/OpenFileDialog/OpenFileDialog.styles.js +2 -2
- package/build/es/components/OpenFileDialog/VisTypeFilter.js +18 -14
- package/build/es/components/OpenFileDialog/utils.js +32 -71
- package/build/es/index.js +1 -1
- package/build/es/locales/ar/translations.json +9 -0
- package/build/es/locales/ar_EG/translations.json +9 -0
- package/build/es/locales/ar_IQ/translations.json +9 -0
- package/build/es/locales/ckb/translations.json +9 -0
- package/build/es/locales/cs/translations.json +9 -0
- package/build/es/locales/da/translations.json +9 -0
- package/build/es/locales/en/translations.json +3 -21
- package/build/es/locales/es/translations.json +9 -0
- package/build/es/locales/fr/translations.json +9 -0
- package/build/es/locales/id/translations.json +9 -0
- package/build/es/locales/km/translations.json +9 -0
- package/build/es/locales/lo/translations.json +9 -0
- package/build/es/locales/my/translations.json +9 -0
- package/build/es/locales/nb/translations.json +9 -0
- package/build/es/locales/nl/translations.json +9 -0
- package/build/es/locales/prs/translations.json +9 -0
- package/build/es/locales/ps/translations.json +9 -0
- package/build/es/locales/pt/translations.json +9 -0
- package/build/es/locales/pt_BR/translations.json +9 -0
- package/build/es/locales/ru/translations.json +9 -0
- package/build/es/locales/sv/translations.json +9 -0
- package/build/es/locales/tet/translations.json +9 -0
- package/build/es/locales/tg/translations.json +9 -0
- package/build/es/locales/uk/translations.json +9 -0
- package/build/es/locales/ur/translations.json +9 -0
- package/build/es/locales/uz/translations.json +9 -0
- package/build/es/locales/uz_Latn/translations.json +9 -0
- package/build/es/locales/vi/translations.json +9 -0
- package/build/es/locales/zh/translations.json +10 -1
- package/build/es/locales/zh_CN/translations.json +9 -0
- package/build/es/modules/layoutUiRules/rules.js +6 -2
- package/build/es/modules/visTypes.js +10 -19
- package/package.json +2 -2
- package/build/cjs/components/OpenFileDialog/styles/FileList.style.js +0 -10
- package/build/cjs/visualizations/package-lock.json +0 -1788
- package/build/es/components/OpenFileDialog/styles/FileList.style.js +0 -3
- package/build/es/visualizations/package-lock.json +0 -1788
|
@@ -2,6 +2,7 @@ import { Provider } from '@dhis2/app-runtime';
|
|
|
2
2
|
import { storiesOf } from '@storybook/react';
|
|
3
3
|
import React from 'react';
|
|
4
4
|
import { OpenFileDialog } from '../components/OpenFileDialog/OpenFileDialog.js';
|
|
5
|
+
import { VIS_TYPE_GROUP_ALL, VIS_TYPE_GROUP_CHARTS, VIS_TYPE_PIVOT_TABLE, VIS_TYPE_COLUMN, VIS_TYPE_BAR, VIS_TYPE_LINE_LIST } from '../modules/visTypes.js';
|
|
5
6
|
const configMock = {
|
|
6
7
|
baseUrl: 'https://debug.dhis2.org/dev',
|
|
7
8
|
apiVersion: 37
|
|
@@ -14,17 +15,30 @@ const user = {
|
|
|
14
15
|
|
|
15
16
|
const onFileSelect = id => alert("Opening ".concat(id));
|
|
16
17
|
|
|
17
|
-
|
|
18
|
+
const filterVisTypesWithGroupsAndDivider = [{
|
|
19
|
+
type: VIS_TYPE_GROUP_ALL
|
|
20
|
+
}, {
|
|
21
|
+
type: VIS_TYPE_GROUP_CHARTS,
|
|
22
|
+
insertDivider: true
|
|
23
|
+
}, {
|
|
24
|
+
type: VIS_TYPE_PIVOT_TABLE
|
|
25
|
+
}, {
|
|
26
|
+
type: VIS_TYPE_COLUMN
|
|
27
|
+
}, {
|
|
28
|
+
type: VIS_TYPE_BAR
|
|
29
|
+
}];
|
|
30
|
+
storiesOf('OpenFileDialog', module).add('List of visualizations with vis type filter and divider (no default vis type)', () => /*#__PURE__*/React.createElement(Provider, {
|
|
18
31
|
config: configMock
|
|
19
32
|
}, /*#__PURE__*/React.createElement(OpenFileDialog, {
|
|
20
33
|
type: "visualization",
|
|
34
|
+
filterVisTypes: filterVisTypesWithGroupsAndDivider,
|
|
21
35
|
onClose: Function.prototype,
|
|
22
36
|
onFileSelect: onFileSelect,
|
|
23
37
|
onNew: Function.prototype,
|
|
24
38
|
open: true,
|
|
25
39
|
currentUser: user
|
|
26
40
|
})));
|
|
27
|
-
storiesOf('OpenFileDialog', module).add('List of maps', () => /*#__PURE__*/React.createElement(Provider, {
|
|
41
|
+
storiesOf('OpenFileDialog', module).add('List of maps (no vis type filter)', () => /*#__PURE__*/React.createElement(Provider, {
|
|
28
42
|
config: configMock
|
|
29
43
|
}, /*#__PURE__*/React.createElement(OpenFileDialog, {
|
|
30
44
|
type: "map",
|
|
@@ -34,20 +48,38 @@ storiesOf('OpenFileDialog', module).add('List of maps', () => /*#__PURE__*/React
|
|
|
34
48
|
open: true,
|
|
35
49
|
currentUser: user
|
|
36
50
|
})));
|
|
37
|
-
|
|
51
|
+
const filterVisTypesWithDisabled = [{
|
|
52
|
+
type: VIS_TYPE_PIVOT_TABLE,
|
|
53
|
+
disabled: true
|
|
54
|
+
}, {
|
|
55
|
+
type: VIS_TYPE_LINE_LIST
|
|
56
|
+
}];
|
|
57
|
+
storiesOf('OpenFileDialog', module).add('List of event visualizations with vis type filter, disabled type and default vis type', () => /*#__PURE__*/React.createElement(Provider, {
|
|
38
58
|
config: configMock
|
|
39
59
|
}, /*#__PURE__*/React.createElement(OpenFileDialog, {
|
|
40
|
-
type: "
|
|
60
|
+
type: "eventVisualization",
|
|
61
|
+
filterVisTypes: filterVisTypesWithDisabled,
|
|
62
|
+
defaultFilterVisType: VIS_TYPE_LINE_LIST,
|
|
41
63
|
onClose: Function.prototype,
|
|
42
64
|
onFileSelect: onFileSelect,
|
|
43
65
|
onNew: Function.prototype,
|
|
44
66
|
open: true,
|
|
45
67
|
currentUser: user
|
|
46
68
|
})));
|
|
47
|
-
|
|
69
|
+
const filterVisTypesWithGroupDividerAndDisabled = [{
|
|
70
|
+
type: VIS_TYPE_GROUP_ALL
|
|
71
|
+
}, {
|
|
72
|
+
type: VIS_TYPE_BAR,
|
|
73
|
+
insertDivider: true
|
|
74
|
+
}, {
|
|
75
|
+
type: VIS_TYPE_COLUMN,
|
|
76
|
+
disabled: true
|
|
77
|
+
}];
|
|
78
|
+
storiesOf('OpenFileDialog', module).add('List of visualizations with vis type filter with group type, divider and disabled option (no default vis type)', () => /*#__PURE__*/React.createElement(Provider, {
|
|
48
79
|
config: configMock
|
|
49
80
|
}, /*#__PURE__*/React.createElement(OpenFileDialog, {
|
|
50
|
-
type: "
|
|
81
|
+
type: "visualization",
|
|
82
|
+
filterVisTypes: filterVisTypesWithGroupDividerAndDisabled,
|
|
51
83
|
onClose: Function.prototype,
|
|
52
84
|
onFileSelect: onFileSelect,
|
|
53
85
|
onNew: Function.prototype,
|
|
@@ -91,6 +91,7 @@ export default (function x() {
|
|
|
91
91
|
addFixture('/api/analytics/query', require('./json/api/analytics/query.json'));
|
|
92
92
|
addFixture('/api/analytics/cluster', require('./json/api/analytics/cluster.json'));
|
|
93
93
|
addFixture('/api/analytics/response', require('./json/api/analytics/response.json'));
|
|
94
|
+
addFixture('/api/analytics/enrollments', require('./json/api/analytics/enrollments.json'));
|
|
94
95
|
return {
|
|
95
96
|
get: getFixture,
|
|
96
97
|
add: addFixture
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
{
|
|
2
|
+
"headers": [
|
|
3
|
+
{
|
|
4
|
+
"name": "pi",
|
|
5
|
+
"column": "Enrollment",
|
|
6
|
+
"valueType": "TEXT",
|
|
7
|
+
"type": "java.lang.String",
|
|
8
|
+
"hidden": false,
|
|
9
|
+
"meta": true
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"name": "tei",
|
|
13
|
+
"column": "Tracked entity instance",
|
|
14
|
+
"valueType": "TEXT",
|
|
15
|
+
"type": "java.lang.String",
|
|
16
|
+
"hidden": false,
|
|
17
|
+
"meta": true
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"name": "enrollmentdate",
|
|
21
|
+
"column": "Enrollment date",
|
|
22
|
+
"valueType": "DATE",
|
|
23
|
+
"type": "java.util.Date",
|
|
24
|
+
"hidden": false,
|
|
25
|
+
"meta": true
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"name": "incidentdate",
|
|
29
|
+
"column": "Incident date",
|
|
30
|
+
"valueType": "DATE",
|
|
31
|
+
"type": "java.util.Date",
|
|
32
|
+
"hidden": false,
|
|
33
|
+
"meta": true
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"name": "geometry",
|
|
37
|
+
"column": "Geometry",
|
|
38
|
+
"valueType": "TEXT",
|
|
39
|
+
"type": "java.lang.String",
|
|
40
|
+
"hidden": false,
|
|
41
|
+
"meta": true
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"name": "longitude",
|
|
45
|
+
"column": "Longitude",
|
|
46
|
+
"valueType": "NUMBER",
|
|
47
|
+
"type": "java.lang.Double",
|
|
48
|
+
"hidden": false,
|
|
49
|
+
"meta": true
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"name": "latitude",
|
|
53
|
+
"column": "Latitude",
|
|
54
|
+
"valueType": "NUMBER",
|
|
55
|
+
"type": "java.lang.Double",
|
|
56
|
+
"hidden": false,
|
|
57
|
+
"meta": true
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"name": "ouname",
|
|
61
|
+
"column": "Organisation unit name",
|
|
62
|
+
"valueType": "TEXT",
|
|
63
|
+
"type": "java.lang.String",
|
|
64
|
+
"hidden": false,
|
|
65
|
+
"meta": true
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
"name": "oucode",
|
|
69
|
+
"column": "Organisation unit code",
|
|
70
|
+
"valueType": "TEXT",
|
|
71
|
+
"type": "java.lang.String",
|
|
72
|
+
"hidden": false,
|
|
73
|
+
"meta": true
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
"name": "ou",
|
|
77
|
+
"column": "Organisation unit",
|
|
78
|
+
"valueType": "TEXT",
|
|
79
|
+
"type": "java.lang.String",
|
|
80
|
+
"hidden": false,
|
|
81
|
+
"meta": true
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
"name": "de0FEHSIoxh",
|
|
85
|
+
"column": "WHOMCH Chronic conditions",
|
|
86
|
+
"valueType": "BOOLEAN",
|
|
87
|
+
"type": "java.lang.Boolean",
|
|
88
|
+
"hidden": false,
|
|
89
|
+
"meta": true
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
"name": "sWoqcoByYmD",
|
|
93
|
+
"column": "WHOMCH Smoking",
|
|
94
|
+
"valueType": "BOOLEAN",
|
|
95
|
+
"type": "java.lang.Boolean",
|
|
96
|
+
"hidden": false,
|
|
97
|
+
"meta": true
|
|
98
|
+
}
|
|
99
|
+
],
|
|
100
|
+
"metaData": {
|
|
101
|
+
"pager": {
|
|
102
|
+
"page": 2,
|
|
103
|
+
"total": 163,
|
|
104
|
+
"pageSize": 4,
|
|
105
|
+
"pageCount": 41
|
|
106
|
+
},
|
|
107
|
+
"items": {
|
|
108
|
+
"ImspTQPwCqd": {
|
|
109
|
+
"name": "Sierra Leone"
|
|
110
|
+
},
|
|
111
|
+
"PFDfvmGpsR3": {
|
|
112
|
+
"name": "Care at birth"
|
|
113
|
+
},
|
|
114
|
+
"bbKtnxRZKEP": {
|
|
115
|
+
"name": "Postpartum care visit"
|
|
116
|
+
},
|
|
117
|
+
"ou": {
|
|
118
|
+
"name": "Organisation unit"
|
|
119
|
+
},
|
|
120
|
+
"PUZaKR0Jh2k": {
|
|
121
|
+
"name": "Previous deliveries"
|
|
122
|
+
},
|
|
123
|
+
"edqlbukwRfQ": {
|
|
124
|
+
"name": "Antenatal care visit"
|
|
125
|
+
},
|
|
126
|
+
"WZbXY0S00lP": {
|
|
127
|
+
"name": "First antenatal care visit"
|
|
128
|
+
},
|
|
129
|
+
"sWoqcoByYmD": {
|
|
130
|
+
"name": "WHOMCH Smoking"
|
|
131
|
+
},
|
|
132
|
+
"WSGAb5XwJ3Y": {
|
|
133
|
+
"name": "WHO RMNCH Tracker"
|
|
134
|
+
},
|
|
135
|
+
"de0FEHSIoxh": {
|
|
136
|
+
"name": "WHOMCH Chronic conditions"
|
|
137
|
+
}
|
|
138
|
+
},
|
|
139
|
+
"dimensions": {
|
|
140
|
+
"pe": [],
|
|
141
|
+
"ou": ["ImspTQPwCqd"],
|
|
142
|
+
"sWoqcoByYmD": [],
|
|
143
|
+
"de0FEHSIoxh": []
|
|
144
|
+
}
|
|
145
|
+
},
|
|
146
|
+
"width": 12,
|
|
147
|
+
"rows": [
|
|
148
|
+
[
|
|
149
|
+
"A0cP533hIQv",
|
|
150
|
+
"to8G9jAprnx",
|
|
151
|
+
"2019-02-02 12:05:00.0",
|
|
152
|
+
"2019-02-02 12:05:00.0",
|
|
153
|
+
"",
|
|
154
|
+
"0.0",
|
|
155
|
+
"0.0",
|
|
156
|
+
"Tonkomba MCHP",
|
|
157
|
+
"OU_193264",
|
|
158
|
+
"xIMxph4NMP1",
|
|
159
|
+
"0",
|
|
160
|
+
"1"
|
|
161
|
+
],
|
|
162
|
+
[
|
|
163
|
+
"ZqiUn2uXmBi",
|
|
164
|
+
"SJtv0WzoYki",
|
|
165
|
+
"2019-02-02 12:05:00.0",
|
|
166
|
+
"2019-02-02 12:05:00.0",
|
|
167
|
+
"",
|
|
168
|
+
"0.0",
|
|
169
|
+
"0.0",
|
|
170
|
+
"Mawoma MCHP",
|
|
171
|
+
"OU_254973",
|
|
172
|
+
"Srnpwq8jKbp",
|
|
173
|
+
"0",
|
|
174
|
+
"0"
|
|
175
|
+
],
|
|
176
|
+
[
|
|
177
|
+
"lE747mUAtbz",
|
|
178
|
+
"PGzTv2A1xzn",
|
|
179
|
+
"2019-02-02 12:05:00.0",
|
|
180
|
+
"2019-02-02 12:05:00.0",
|
|
181
|
+
"",
|
|
182
|
+
"0.0",
|
|
183
|
+
"0.0",
|
|
184
|
+
"Kunsho CHP",
|
|
185
|
+
"OU_193254",
|
|
186
|
+
"tdhB1JXYBx2",
|
|
187
|
+
"",
|
|
188
|
+
"0"
|
|
189
|
+
],
|
|
190
|
+
[
|
|
191
|
+
"nmcqu9QF8ow",
|
|
192
|
+
"pav3tGLjYuq",
|
|
193
|
+
"2019-02-03 12:05:00.0",
|
|
194
|
+
"2019-02-03 12:05:00.0",
|
|
195
|
+
"",
|
|
196
|
+
"0.0",
|
|
197
|
+
"0.0",
|
|
198
|
+
"Korbu MCHP",
|
|
199
|
+
"OU_678893",
|
|
200
|
+
"m73lWmo5BDG",
|
|
201
|
+
"",
|
|
202
|
+
"1"
|
|
203
|
+
]
|
|
204
|
+
],
|
|
205
|
+
"height": 4
|
|
206
|
+
}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* @module analytics
|
|
3
3
|
*/
|
|
4
4
|
import AnalyticsAggregate from './AnalyticsAggregate.js';
|
|
5
|
+
import AnalyticsEnrollments from './AnalyticsEnrollments.js';
|
|
5
6
|
import AnalyticsEvents from './AnalyticsEvents.js';
|
|
6
7
|
import AnalyticsRequest from './AnalyticsRequest.js';
|
|
7
8
|
import AnalyticsResponse from './AnalyticsResponse.js';
|
|
@@ -30,17 +31,20 @@ import AnalyticsResponse from './AnalyticsResponse.js';
|
|
|
30
31
|
class Analytics {
|
|
31
32
|
/**
|
|
32
33
|
* @param {!module:analytics.AnalyticsAggregate} analyticsAggregate The AnalyticsAggregate instance
|
|
34
|
+
* @param {!module:analytics.AnalyticsEnrollments} analyticsEnrollments The AnalyticsEnrollments instance
|
|
33
35
|
* @param {!module:analytics.AnalyticsEvents} analyticsEvents The AnalyticsEvents instance
|
|
34
36
|
* @param {!module:analytics.AnalyticsRequest} analyticsRequest The AnalyticsRequest class
|
|
35
37
|
* @param {!module:analytics.AnalyticsResponse} analyticsResponse The AnalyticsResponse class
|
|
36
38
|
*/
|
|
37
39
|
constructor({
|
|
38
40
|
aggregate,
|
|
41
|
+
enrollments,
|
|
39
42
|
events,
|
|
40
43
|
request,
|
|
41
44
|
response
|
|
42
45
|
}) {
|
|
43
46
|
this.aggregate = aggregate;
|
|
47
|
+
this.enrollments = enrollments;
|
|
44
48
|
this.events = events;
|
|
45
49
|
this.request = request;
|
|
46
50
|
this.response = response;
|
|
@@ -63,6 +67,7 @@ class Analytics {
|
|
|
63
67
|
if (!Analytics.getAnalytics.analytics) {
|
|
64
68
|
Analytics.getAnalytics.analytics = new Analytics({
|
|
65
69
|
aggregate: new AnalyticsAggregate(dataEngine),
|
|
70
|
+
enrollments: new AnalyticsEnrollments(dataEngine),
|
|
66
71
|
events: new AnalyticsEvents(dataEngine),
|
|
67
72
|
request: AnalyticsRequest,
|
|
68
73
|
response: AnalyticsResponse
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import AnalyticsBase from './AnalyticsBase.js';
|
|
2
|
+
/**
|
|
3
|
+
* @extends module:analytics.AnalyticsBase
|
|
4
|
+
*
|
|
5
|
+
* @description
|
|
6
|
+
* Analytics enrollments class used to request analytics enrollments data from Web API.
|
|
7
|
+
*
|
|
8
|
+
* @memberof module:analytics
|
|
9
|
+
*
|
|
10
|
+
* @see https://docs.dhis2.org/en/develop/using-the-api/dhis-core-version-236/analytics.html#webapi_enrollment_analytics
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
class AnalyticsEnrollments extends AnalyticsBase {
|
|
14
|
+
/**
|
|
15
|
+
* @param {!AnalyticsRequest} req Request object
|
|
16
|
+
*
|
|
17
|
+
* @returns {Promise} Promise that resolves with the analytics query data from the api.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* const req = new analytics.request()
|
|
21
|
+
* .withProgram('eBAyeGv0exc')
|
|
22
|
+
* .addDataDimension(['Uvn6LCg7dVU','OdiHJayrsKo'])
|
|
23
|
+
* .addPeriodDimension('LAST_4_QUARTERS')
|
|
24
|
+
* .addOrgUnitDimension(['lc3eMKXaEfw','PMa2VCrupOd'])
|
|
25
|
+
* .addOrgUnitFilter('O6uvpzGd5pu')
|
|
26
|
+
* .withStartDate('2017-10-01')
|
|
27
|
+
* .withEndDate('2017-10-31');
|
|
28
|
+
*
|
|
29
|
+
* analytics.enrollments.getQuery(req)
|
|
30
|
+
* .then(console.log);
|
|
31
|
+
*/
|
|
32
|
+
getQuery(req) {
|
|
33
|
+
return this.fetch(req.withPath('enrollments/query'));
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export default AnalyticsEnrollments;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import fixtures from '../../../__fixtures__/fixtures.js';
|
|
2
|
+
import DataEngineMock from '../__mocks__/DataEngine.js';
|
|
3
|
+
import AnalyticsEnrollments from '../AnalyticsEnrollments.js';
|
|
4
|
+
import AnalyticsRequest from '../AnalyticsRequest.js';
|
|
5
|
+
describe('analytics.enrollments', () => {
|
|
6
|
+
let enrollments;
|
|
7
|
+
let request;
|
|
8
|
+
let dataEngineMock;
|
|
9
|
+
let fixture;
|
|
10
|
+
beforeEach(() => {
|
|
11
|
+
dataEngineMock = new DataEngineMock();
|
|
12
|
+
DataEngineMock.mockClear();
|
|
13
|
+
enrollments = new AnalyticsEnrollments();
|
|
14
|
+
});
|
|
15
|
+
it('should not be allowed to be called without new', () => {
|
|
16
|
+
expect(() => AnalyticsEnrollments()).toThrowErrorMatchingSnapshot();
|
|
17
|
+
});
|
|
18
|
+
it('should use the dataEngine object when it is passed', () => {
|
|
19
|
+
const dataEngineMockObject = {};
|
|
20
|
+
enrollments = new AnalyticsEnrollments(dataEngineMockObject);
|
|
21
|
+
expect(enrollments.dataEngine).toBe(dataEngineMockObject);
|
|
22
|
+
});
|
|
23
|
+
describe('.getQuery()', () => {
|
|
24
|
+
beforeEach(() => {
|
|
25
|
+
enrollments = new AnalyticsEnrollments(new DataEngineMock());
|
|
26
|
+
request = new AnalyticsRequest().addOrgUnitDimension('ImspTQPwCqd').addDimension('WZbXY0S00lP.de0FEHSIoxh').addDimension('WZbXY0S00lP.sWoqcoByYmD').addPeriodFilter('LAST_MONTH').withProgram('WSGAb5XwJ3Y').withStage('WZbXY0S00lP').withAsc('ENROLLMENTDATE').withOuMode('DESCENDANTS').withColumns('w75KJ2mc4zz').withPage(1).withPageSize(10);
|
|
27
|
+
fixture = fixtures.get('/api/analytics/enrollments');
|
|
28
|
+
dataEngineMock.query.mockReturnValue(Promise.resolve({
|
|
29
|
+
data: fixture
|
|
30
|
+
}));
|
|
31
|
+
});
|
|
32
|
+
it('should be a function', () => {
|
|
33
|
+
expect(enrollments.getQuery).toBeInstanceOf(Function);
|
|
34
|
+
});
|
|
35
|
+
it('should resolve a promise with data', () => enrollments.getQuery(request).then(data => {
|
|
36
|
+
expect(data.width).toEqual(fixture.width);
|
|
37
|
+
expect(data.height).toEqual(fixture.height);
|
|
38
|
+
}));
|
|
39
|
+
});
|
|
40
|
+
});
|
|
@@ -16,20 +16,14 @@ const CachedDataQueryProvider = ({
|
|
|
16
16
|
} = useDataQuery(query);
|
|
17
17
|
const {
|
|
18
18
|
error,
|
|
19
|
-
loading
|
|
20
|
-
fetching
|
|
19
|
+
loading
|
|
21
20
|
} = rest;
|
|
22
21
|
const data = rawData && dataTransformation ? dataTransformation(rawData) : rawData;
|
|
23
|
-
/*
|
|
24
|
-
* Render loader only when data is unavailable
|
|
25
|
-
*/
|
|
26
22
|
|
|
27
|
-
if (loading
|
|
28
|
-
return /*#__PURE__*/React.createElement(
|
|
23
|
+
if (loading) {
|
|
24
|
+
return /*#__PURE__*/React.createElement(Layer, {
|
|
29
25
|
translucent: true
|
|
30
|
-
}, /*#__PURE__*/React.createElement(CenteredContent, null, /*#__PURE__*/React.createElement(CircularLoader, null)))
|
|
31
|
-
value: data
|
|
32
|
-
}, children));
|
|
26
|
+
}, /*#__PURE__*/React.createElement(CenteredContent, null, /*#__PURE__*/React.createElement(CircularLoader, null)));
|
|
33
27
|
}
|
|
34
28
|
|
|
35
29
|
if (error) {
|
|
@@ -13,8 +13,10 @@ import { SaveAsDialog } from './SaveAsDialog.js';
|
|
|
13
13
|
import { supportedFileTypes } from './utils.js';
|
|
14
14
|
export const FileMenu = ({
|
|
15
15
|
currentUser,
|
|
16
|
+
defaultFilterVisType,
|
|
16
17
|
fileType,
|
|
17
18
|
fileObject,
|
|
19
|
+
filterVisTypes,
|
|
18
20
|
onNew,
|
|
19
21
|
onOpen,
|
|
20
22
|
onSave,
|
|
@@ -129,6 +131,8 @@ export const FileMenu = ({
|
|
|
129
131
|
}, i18n.t('File'))), /*#__PURE__*/React.createElement(OpenFileDialog, {
|
|
130
132
|
open: currentDialog === 'open',
|
|
131
133
|
type: fileType,
|
|
134
|
+
filterVisTypes: filterVisTypes,
|
|
135
|
+
defaultFilterVisType: defaultFilterVisType,
|
|
132
136
|
onClose: onDialogClose,
|
|
133
137
|
onFileSelect: id => {
|
|
134
138
|
onOpen(id);
|
|
@@ -237,8 +241,10 @@ FileMenu.defaultProps = {
|
|
|
237
241
|
};
|
|
238
242
|
FileMenu.propTypes = {
|
|
239
243
|
currentUser: PropTypes.object,
|
|
244
|
+
defaultFilterVisType: PropTypes.string,
|
|
240
245
|
fileObject: PropTypes.object,
|
|
241
246
|
fileType: PropTypes.oneOf(supportedFileTypes),
|
|
247
|
+
filterVisTypes: PropTypes.array,
|
|
242
248
|
onDelete: PropTypes.func,
|
|
243
249
|
onError: PropTypes.func,
|
|
244
250
|
onNew: PropTypes.func,
|
|
@@ -1,16 +1,20 @@
|
|
|
1
1
|
import _JSXStyle from "styled-jsx/style";
|
|
2
|
+
import i18n from '@dhis2/d2-i18n';
|
|
3
|
+
import { MenuDivider, Tooltip } from '@dhis2/ui';
|
|
2
4
|
import cx from 'classnames';
|
|
3
5
|
import PropTypes from 'prop-types';
|
|
4
6
|
import React from 'react';
|
|
5
7
|
import styles from './styles/CustomSelectOption.style.js';
|
|
6
|
-
|
|
8
|
+
|
|
9
|
+
const CustomSelectOptionItem = ({
|
|
7
10
|
value,
|
|
8
11
|
label,
|
|
9
12
|
icon,
|
|
13
|
+
insertDivider,
|
|
10
14
|
onClick,
|
|
11
15
|
active,
|
|
12
16
|
disabled
|
|
13
|
-
}) => /*#__PURE__*/React.createElement("div", {
|
|
17
|
+
}) => /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
|
|
14
18
|
onClick: e => onClick({}, e),
|
|
15
19
|
"data-value": value,
|
|
16
20
|
"data-label": label,
|
|
@@ -19,10 +23,18 @@ export const CustomSelectOption = ({
|
|
|
19
23
|
disabled
|
|
20
24
|
}) || "")
|
|
21
25
|
}, icon, /*#__PURE__*/React.createElement("span", {
|
|
22
|
-
className: "jsx-".concat(styles.__hash) + " " +
|
|
26
|
+
className: "jsx-".concat(styles.__hash) + " " + (cx({
|
|
27
|
+
label: icon
|
|
28
|
+
}) || "")
|
|
23
29
|
}, label), /*#__PURE__*/React.createElement(_JSXStyle, {
|
|
24
30
|
id: styles.__hash
|
|
25
|
-
}, styles))
|
|
31
|
+
}, styles)), insertDivider && /*#__PURE__*/React.createElement(MenuDivider, {
|
|
32
|
+
dense: true
|
|
33
|
+
}));
|
|
34
|
+
|
|
35
|
+
export const CustomSelectOption = props => props.disabled ? /*#__PURE__*/React.createElement(Tooltip, {
|
|
36
|
+
content: i18n.t('Not supported by this app yet')
|
|
37
|
+
}, /*#__PURE__*/React.createElement(CustomSelectOptionItem, props)) : /*#__PURE__*/React.createElement(CustomSelectOptionItem, props);
|
|
26
38
|
CustomSelectOption.propTypes = {
|
|
27
39
|
icon: PropTypes.element.isRequired,
|
|
28
40
|
label: PropTypes.string.isRequired,
|
|
@@ -31,4 +43,5 @@ CustomSelectOption.propTypes = {
|
|
|
31
43
|
disabled: PropTypes.bool,
|
|
32
44
|
onClick: PropTypes.func
|
|
33
45
|
};
|
|
46
|
+
CustomSelectOptionItem.propTypes = CustomSelectOption.propTypes;
|
|
34
47
|
export default CustomSelectOption;
|
|
@@ -4,14 +4,14 @@ import React from 'react';
|
|
|
4
4
|
import { VisTypeIcon } from '../VisTypeIcon.js';
|
|
5
5
|
import { DateField } from './DateField.js';
|
|
6
6
|
export const FileList = ({
|
|
7
|
-
type,
|
|
8
7
|
data,
|
|
9
|
-
onSelect
|
|
8
|
+
onSelect,
|
|
9
|
+
showVisTypeColumn
|
|
10
10
|
}) => /*#__PURE__*/React.createElement(React.Fragment, null, data.map(visualization => /*#__PURE__*/React.createElement(DataTableRow, {
|
|
11
11
|
key: visualization.id
|
|
12
12
|
}, /*#__PURE__*/React.createElement(DataTableCell, {
|
|
13
13
|
onClick: () => onSelect(visualization.id)
|
|
14
|
-
}, visualization.displayName),
|
|
14
|
+
}, visualization.displayName), showVisTypeColumn && /*#__PURE__*/React.createElement(DataTableCell, {
|
|
15
15
|
align: "center"
|
|
16
16
|
}, /*#__PURE__*/React.createElement(VisTypeIcon, {
|
|
17
17
|
type: visualization.type,
|
|
@@ -30,7 +30,7 @@ FileList.propTypes = {
|
|
|
30
30
|
lastUpdated: PropTypes.string.isRequired,
|
|
31
31
|
type: PropTypes.string
|
|
32
32
|
})).isRequired,
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
onSelect: PropTypes.func.isRequired,
|
|
34
|
+
showVisTypeColumn: PropTypes.bool
|
|
35
35
|
};
|
|
36
36
|
export default FileList;
|
|
@@ -5,13 +5,14 @@ import { Box, Modal, ModalTitle, ModalContent, DataTable, DataTableHead, DataTab
|
|
|
5
5
|
import isEqual from 'lodash/isEqual';
|
|
6
6
|
import PropTypes from 'prop-types';
|
|
7
7
|
import React, { useEffect, useMemo, useState } from 'react';
|
|
8
|
+
import { VIS_TYPE_GROUP_ALL, VIS_TYPE_GROUP_CHARTS } from '../../modules/visTypes.js';
|
|
8
9
|
import { CreatedByFilter, CREATED_BY_ALL, CREATED_BY_ALL_BUT_CURRENT_USER, CREATED_BY_CURRENT_USER } from './CreatedByFilter.js';
|
|
9
10
|
import { FileList } from './FileList.js';
|
|
10
11
|
import { NameFilter } from './NameFilter.js';
|
|
11
12
|
import { styles } from './OpenFileDialog.styles.js';
|
|
12
13
|
import { PaginationControls } from './PaginationControls.js';
|
|
13
|
-
import { getTranslatedString,
|
|
14
|
-
import { VisTypeFilter
|
|
14
|
+
import { getTranslatedString, AOTypeMap } from './utils.js';
|
|
15
|
+
import { VisTypeFilter } from './VisTypeFilter.js';
|
|
15
16
|
|
|
16
17
|
const getQuery = type => ({
|
|
17
18
|
files: {
|
|
@@ -42,6 +43,8 @@ const getQuery = type => ({
|
|
|
42
43
|
export const OpenFileDialog = ({
|
|
43
44
|
type,
|
|
44
45
|
open,
|
|
46
|
+
filterVisTypes,
|
|
47
|
+
defaultFilterVisType,
|
|
45
48
|
onClose,
|
|
46
49
|
onFileSelect,
|
|
47
50
|
onNew,
|
|
@@ -51,7 +54,7 @@ export const OpenFileDialog = ({
|
|
|
51
54
|
const defaultFilters = {
|
|
52
55
|
searchTerm: '',
|
|
53
56
|
createdBy: CREATED_BY_ALL,
|
|
54
|
-
visType:
|
|
57
|
+
visType: defaultFilterVisType
|
|
55
58
|
};
|
|
56
59
|
const [{
|
|
57
60
|
sortField,
|
|
@@ -82,26 +85,23 @@ export const OpenFileDialog = ({
|
|
|
82
85
|
break;
|
|
83
86
|
}
|
|
84
87
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
+
if (filters.visType) {
|
|
89
|
+
switch (filters.visType) {
|
|
90
|
+
case VIS_TYPE_GROUP_ALL:
|
|
91
|
+
break;
|
|
88
92
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
93
|
+
case VIS_TYPE_GROUP_CHARTS:
|
|
94
|
+
queryFilters.push('type:!eq:PIVOT_TABLE');
|
|
95
|
+
break;
|
|
92
96
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
97
|
+
default:
|
|
98
|
+
queryFilters.push("type:eq:".concat(filters.visType));
|
|
99
|
+
break;
|
|
100
|
+
}
|
|
96
101
|
}
|
|
97
102
|
|
|
98
103
|
if (filters.searchTerm) {
|
|
99
104
|
queryFilters.push("name:ilike:".concat(filters.searchTerm));
|
|
100
|
-
} // for ER 2.38 only show line list ER types
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
if (type === AO_TYPE_EVENT_REPORT || type === AO_TYPE_EVENT_VISUALIZATION) {
|
|
104
|
-
queryFilters.push('dataType:eq:EVENTS');
|
|
105
105
|
}
|
|
106
106
|
|
|
107
107
|
return queryFilters;
|
|
@@ -127,7 +127,8 @@ export const OpenFileDialog = ({
|
|
|
127
127
|
refetch({
|
|
128
128
|
page,
|
|
129
129
|
sortField,
|
|
130
|
-
sortDirection
|
|
130
|
+
sortDirection,
|
|
131
|
+
filters: formatFilters()
|
|
131
132
|
});
|
|
132
133
|
}
|
|
133
134
|
}, [open, page, sortField, sortDirection]);
|
|
@@ -157,7 +158,7 @@ export const OpenFileDialog = ({
|
|
|
157
158
|
width: '110px'
|
|
158
159
|
}];
|
|
159
160
|
|
|
160
|
-
if (
|
|
161
|
+
if (filterVisTypes !== null && filterVisTypes !== void 0 && filterVisTypes.length) {
|
|
161
162
|
headers.splice(1, 0, {
|
|
162
163
|
field: 'type',
|
|
163
164
|
label: i18n.t('Type'),
|
|
@@ -190,9 +191,10 @@ export const OpenFileDialog = ({
|
|
|
190
191
|
searchTerm: value
|
|
191
192
|
}), 200));
|
|
192
193
|
}
|
|
193
|
-
})),
|
|
194
|
+
})), (filterVisTypes === null || filterVisTypes === void 0 ? void 0 : filterVisTypes.length) && /*#__PURE__*/React.createElement("div", {
|
|
194
195
|
className: "jsx-".concat(styles.__hash) + " " + "type-field-container"
|
|
195
196
|
}, /*#__PURE__*/React.createElement(VisTypeFilter, {
|
|
197
|
+
visTypes: filterVisTypes,
|
|
196
198
|
selected: filters.visType,
|
|
197
199
|
onChange: value => setFilters({ ...filters,
|
|
198
200
|
visType: value
|
|
@@ -261,9 +263,9 @@ export const OpenFileDialog = ({
|
|
|
261
263
|
onClose();
|
|
262
264
|
}
|
|
263
265
|
}, getTranslatedString(type, 'newButtonLabel'))))))))), (data === null || data === void 0 ? void 0 : data.files[AOTypeMap[type].apiEndpoint].length) > 0 && /*#__PURE__*/React.createElement(FileList, {
|
|
264
|
-
type: type,
|
|
265
266
|
data: data.files[AOTypeMap[type].apiEndpoint],
|
|
266
|
-
onSelect: onFileSelect
|
|
267
|
+
onSelect: onFileSelect,
|
|
268
|
+
showVisTypeColumn: Boolean(filterVisTypes === null || filterVisTypes === void 0 ? void 0 : filterVisTypes.length)
|
|
267
269
|
}))), (data === null || data === void 0 ? void 0 : data.files[AOTypeMap[type].apiEndpoint].length) > 0 && /*#__PURE__*/React.createElement(DataTableToolbar, {
|
|
268
270
|
position: "bottom"
|
|
269
271
|
}, /*#__PURE__*/React.createElement("div", {
|
|
@@ -282,6 +284,8 @@ OpenFileDialog.propTypes = {
|
|
|
282
284
|
type: PropTypes.oneOf(Object.keys(AOTypeMap)).isRequired,
|
|
283
285
|
onClose: PropTypes.func.isRequired,
|
|
284
286
|
onFileSelect: PropTypes.func.isRequired,
|
|
285
|
-
onNew: PropTypes.func.isRequired
|
|
287
|
+
onNew: PropTypes.func.isRequired,
|
|
288
|
+
defaultFilterVisType: PropTypes.string,
|
|
289
|
+
filterVisTypes: PropTypes.array
|
|
286
290
|
};
|
|
287
291
|
export default OpenFileDialog;
|