@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.
Files changed (102) hide show
  1. package/CHANGELOG.md +3009 -0
  2. package/build/cjs/__demo__/OpenFileDialog.stories.js +39 -6
  3. package/build/cjs/__fixtures__/fixtures.js +1 -0
  4. package/build/cjs/__fixtures__/json/api/analytics/enrollments.json +206 -0
  5. package/build/cjs/api/analytics/Analytics.js +6 -0
  6. package/build/cjs/api/analytics/AnalyticsEnrollments.js +48 -0
  7. package/build/cjs/api/analytics/__tests__/AnalyticsEnrollments.spec.js +50 -0
  8. package/build/cjs/api/analytics/__tests__/__snapshots__/AnalyticsEnrollments.spec.js.snap +3 -0
  9. package/build/cjs/components/CachedDataQueryProvider.js +4 -10
  10. package/build/cjs/components/FileMenu/FileMenu.js +6 -0
  11. package/build/cjs/components/OpenFileDialog/CustomSelectOption.js +18 -4
  12. package/build/cjs/components/OpenFileDialog/FileList.js +5 -5
  13. package/build/cjs/components/OpenFileDialog/OpenFileDialog.js +26 -21
  14. package/build/cjs/components/OpenFileDialog/OpenFileDialog.styles.js +2 -2
  15. package/build/cjs/components/OpenFileDialog/VisTypeFilter.js +17 -16
  16. package/build/cjs/components/OpenFileDialog/utils.js +33 -74
  17. package/build/cjs/index.js +16 -4
  18. package/build/cjs/locales/ar/translations.json +9 -0
  19. package/build/cjs/locales/ar_EG/translations.json +9 -0
  20. package/build/cjs/locales/ar_IQ/translations.json +9 -0
  21. package/build/cjs/locales/ckb/translations.json +9 -0
  22. package/build/cjs/locales/cs/translations.json +9 -0
  23. package/build/cjs/locales/da/translations.json +9 -0
  24. package/build/cjs/locales/en/translations.json +3 -21
  25. package/build/cjs/locales/es/translations.json +9 -0
  26. package/build/cjs/locales/fr/translations.json +9 -0
  27. package/build/cjs/locales/id/translations.json +9 -0
  28. package/build/cjs/locales/km/translations.json +9 -0
  29. package/build/cjs/locales/lo/translations.json +9 -0
  30. package/build/cjs/locales/my/translations.json +9 -0
  31. package/build/cjs/locales/nb/translations.json +9 -0
  32. package/build/cjs/locales/nl/translations.json +9 -0
  33. package/build/cjs/locales/prs/translations.json +9 -0
  34. package/build/cjs/locales/ps/translations.json +9 -0
  35. package/build/cjs/locales/pt/translations.json +9 -0
  36. package/build/cjs/locales/pt_BR/translations.json +9 -0
  37. package/build/cjs/locales/ru/translations.json +9 -0
  38. package/build/cjs/locales/sv/translations.json +9 -0
  39. package/build/cjs/locales/tet/translations.json +9 -0
  40. package/build/cjs/locales/tg/translations.json +9 -0
  41. package/build/cjs/locales/uk/translations.json +9 -0
  42. package/build/cjs/locales/ur/translations.json +9 -0
  43. package/build/cjs/locales/uz/translations.json +9 -0
  44. package/build/cjs/locales/uz_Latn/translations.json +9 -0
  45. package/build/cjs/locales/vi/translations.json +9 -0
  46. package/build/cjs/locales/zh/translations.json +10 -1
  47. package/build/cjs/locales/zh_CN/translations.json +9 -0
  48. package/build/cjs/modules/layoutUiRules/rules.js +5 -1
  49. package/build/cjs/modules/visTypes.js +14 -21
  50. package/build/es/__demo__/OpenFileDialog.stories.js +38 -6
  51. package/build/es/__fixtures__/fixtures.js +1 -0
  52. package/build/es/__fixtures__/json/api/analytics/enrollments.json +206 -0
  53. package/build/es/api/analytics/Analytics.js +5 -0
  54. package/build/es/api/analytics/AnalyticsEnrollments.js +38 -0
  55. package/build/es/api/analytics/__tests__/AnalyticsEnrollments.spec.js +40 -0
  56. package/build/es/api/analytics/__tests__/__snapshots__/AnalyticsEnrollments.spec.js.snap +3 -0
  57. package/build/es/components/CachedDataQueryProvider.js +4 -10
  58. package/build/es/components/FileMenu/FileMenu.js +6 -0
  59. package/build/es/components/OpenFileDialog/CustomSelectOption.js +17 -4
  60. package/build/es/components/OpenFileDialog/FileList.js +5 -5
  61. package/build/es/components/OpenFileDialog/OpenFileDialog.js +27 -23
  62. package/build/es/components/OpenFileDialog/OpenFileDialog.styles.js +2 -2
  63. package/build/es/components/OpenFileDialog/VisTypeFilter.js +18 -14
  64. package/build/es/components/OpenFileDialog/utils.js +32 -71
  65. package/build/es/index.js +1 -1
  66. package/build/es/locales/ar/translations.json +9 -0
  67. package/build/es/locales/ar_EG/translations.json +9 -0
  68. package/build/es/locales/ar_IQ/translations.json +9 -0
  69. package/build/es/locales/ckb/translations.json +9 -0
  70. package/build/es/locales/cs/translations.json +9 -0
  71. package/build/es/locales/da/translations.json +9 -0
  72. package/build/es/locales/en/translations.json +3 -21
  73. package/build/es/locales/es/translations.json +9 -0
  74. package/build/es/locales/fr/translations.json +9 -0
  75. package/build/es/locales/id/translations.json +9 -0
  76. package/build/es/locales/km/translations.json +9 -0
  77. package/build/es/locales/lo/translations.json +9 -0
  78. package/build/es/locales/my/translations.json +9 -0
  79. package/build/es/locales/nb/translations.json +9 -0
  80. package/build/es/locales/nl/translations.json +9 -0
  81. package/build/es/locales/prs/translations.json +9 -0
  82. package/build/es/locales/ps/translations.json +9 -0
  83. package/build/es/locales/pt/translations.json +9 -0
  84. package/build/es/locales/pt_BR/translations.json +9 -0
  85. package/build/es/locales/ru/translations.json +9 -0
  86. package/build/es/locales/sv/translations.json +9 -0
  87. package/build/es/locales/tet/translations.json +9 -0
  88. package/build/es/locales/tg/translations.json +9 -0
  89. package/build/es/locales/uk/translations.json +9 -0
  90. package/build/es/locales/ur/translations.json +9 -0
  91. package/build/es/locales/uz/translations.json +9 -0
  92. package/build/es/locales/uz_Latn/translations.json +9 -0
  93. package/build/es/locales/vi/translations.json +9 -0
  94. package/build/es/locales/zh/translations.json +10 -1
  95. package/build/es/locales/zh_CN/translations.json +9 -0
  96. package/build/es/modules/layoutUiRules/rules.js +6 -2
  97. package/build/es/modules/visTypes.js +10 -19
  98. package/package.json +2 -2
  99. package/build/cjs/components/OpenFileDialog/styles/FileList.style.js +0 -10
  100. package/build/cjs/visualizations/package-lock.json +0 -1788
  101. package/build/es/components/OpenFileDialog/styles/FileList.style.js +0 -3
  102. 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
- storiesOf('OpenFileDialog', module).add('List of visualizations', () => /*#__PURE__*/React.createElement(Provider, {
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
- storiesOf('OpenFileDialog', module).add('List of event reports (Line list only)', () => /*#__PURE__*/React.createElement(Provider, {
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: "eventReport",
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
- storiesOf('OpenFileDialog', module).add('List of a supported type without custom titles/texts', () => /*#__PURE__*/React.createElement(Provider, {
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: "eventChart",
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
+ });
@@ -0,0 +1,3 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`analytics.enrollments should not be allowed to be called without new 1`] = `"Class constructor AnalyticsEnrollments cannot be invoked without 'new'"`;
@@ -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 || fetching) {
28
- return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Layer, {
23
+ if (loading) {
24
+ return /*#__PURE__*/React.createElement(Layer, {
29
25
  translucent: true
30
- }, /*#__PURE__*/React.createElement(CenteredContent, null, /*#__PURE__*/React.createElement(CircularLoader, null))), !loading && /*#__PURE__*/React.createElement(CachedDataQueryCtx.Provider, {
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
- export const CustomSelectOption = ({
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) + " " + "label"
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), type === 'visualization' && /*#__PURE__*/React.createElement(DataTableCell, {
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
- type: PropTypes.string.isRequired,
34
- onSelect: PropTypes.func.isRequired
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, AO_TYPE_VISUALIZATION, AO_TYPE_EVENT_REPORT, AO_TYPE_EVENT_VISUALIZATION, AOTypeMap } from './utils.js';
14
- import { VisTypeFilter, VIS_TYPE_ALL, VIS_TYPE_CHARTS } from './VisTypeFilter.js';
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: VIS_TYPE_ALL
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
- switch (filters.visType) {
86
- case VIS_TYPE_ALL:
87
- break;
88
+ if (filters.visType) {
89
+ switch (filters.visType) {
90
+ case VIS_TYPE_GROUP_ALL:
91
+ break;
88
92
 
89
- case VIS_TYPE_CHARTS:
90
- queryFilters.push('type:!eq:PIVOT_TABLE');
91
- break;
93
+ case VIS_TYPE_GROUP_CHARTS:
94
+ queryFilters.push('type:!eq:PIVOT_TABLE');
95
+ break;
92
96
 
93
- default:
94
- queryFilters.push("type:eq:".concat(filters.visType));
95
- break;
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 (type === AO_TYPE_VISUALIZATION) {
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
- })), type === AO_TYPE_VISUALIZATION && /*#__PURE__*/React.createElement("div", {
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;