@dhis2/analytics 26.2.0-alpha.1 → 26.2.0-cumulative-values-alpha.1
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/build/cjs/__demo__/PivotTable.stories.js +69 -29
- package/build/cjs/api/analytics/Analytics.js +0 -7
- package/build/cjs/api/analytics/AnalyticsBase.js +6 -24
- package/build/cjs/api/analytics/AnalyticsRequest.js +10 -33
- package/build/cjs/api/analytics/AnalyticsRequestBase.js +1 -3
- package/build/cjs/api/analytics/AnalyticsRequestPropertiesMixin.js +0 -19
- package/build/cjs/api/analytics/__tests__/AnalyticsTrackedEntities.spec.js +44 -0
- package/build/cjs/api/analytics/__tests__/__snapshots__/AnalyticsTrackedEntities.spec.js.snap +3 -0
- package/build/cjs/api/analytics/utils.js +2 -23
- package/build/cjs/components/Options/VisualizationOptions.js +1 -1
- package/build/cjs/components/Options/styles/VisualizationOptions.style.js +8 -1
- package/build/cjs/components/RichText/Editor.bk/Editor.js +40 -0
- package/build/cjs/components/RichText/Editor.bk/__tests__/Editor.spec.js +29 -0
- package/build/cjs/components/RichText/Editor.bk/__tests__/convertCtrlKey.spec.js +205 -0
- package/build/cjs/components/RichText/Editor.bk/convertCtrlKey.js +87 -0
- package/build/cjs/components/RichText/Parser.bk/MdParser.js +107 -0
- package/build/cjs/components/RichText/Parser.bk/Parser.js +34 -0
- package/build/cjs/components/RichText/Parser.bk/__tests__/MdParser.spec.js +34 -0
- package/build/cjs/components/RichText/Parser.bk/__tests__/Parser.spec.js +41 -0
- package/build/cjs/locales/uz_UZ_Cyrl/translations.json +2 -2
- package/build/cjs/modules/layout/dimension.js +2 -9
- package/build/cjs/modules/layout/dimensionCreate.js +0 -3
- package/build/cjs/modules/pivotTable/PivotTableEngine.js +119 -57
- package/build/cjs/visualizations/config/generators/dhis/singleValue.js.xp1 +478 -0
- package/build/es/__demo__/PivotTable.stories.js +69 -29
- package/build/es/api/analytics/Analytics.js +0 -7
- package/build/es/api/analytics/AnalyticsBase.js +6 -24
- package/build/es/api/analytics/AnalyticsRequest.js +10 -33
- package/build/es/api/analytics/AnalyticsRequestBase.js +1 -3
- package/build/es/api/analytics/AnalyticsRequestPropertiesMixin.js +0 -19
- package/build/es/api/analytics/__tests__/AnalyticsTrackedEntities.spec.js +41 -0
- package/build/es/api/analytics/__tests__/__snapshots__/AnalyticsTrackedEntities.spec.js.snap +3 -0
- package/build/es/api/analytics/utils.js +1 -20
- package/build/es/components/Options/VisualizationOptions.js +2 -2
- package/build/es/components/Options/styles/VisualizationOptions.style.js +6 -0
- package/build/es/components/RichText/Editor.bk/Editor.js +30 -0
- package/build/es/components/RichText/Editor.bk/__tests__/Editor.spec.js +26 -0
- package/build/es/components/RichText/Editor.bk/__tests__/convertCtrlKey.spec.js +202 -0
- package/build/es/components/RichText/Editor.bk/convertCtrlKey.js +80 -0
- package/build/es/components/RichText/Parser.bk/MdParser.js +99 -0
- package/build/es/components/RichText/Parser.bk/Parser.js +24 -0
- package/build/es/components/RichText/Parser.bk/__tests__/MdParser.spec.js +31 -0
- package/build/es/components/RichText/Parser.bk/__tests__/Parser.spec.js +38 -0
- package/build/es/locales/uz_UZ_Cyrl/translations.json +2 -2
- package/build/es/modules/layout/dimension.js +1 -7
- package/build/es/modules/layout/dimensionCreate.js +1 -4
- package/build/es/modules/pivotTable/PivotTableEngine.js +119 -57
- package/build/es/visualizations/config/generators/dhis/singleValue.js.xp1 +478 -0
- package/package.json +1 -1
- package/build/cjs/api/analytics/AnalyticsTrackedEntities.js +0 -31
- package/build/es/api/analytics/AnalyticsTrackedEntities.js +0 -24
|
@@ -6,15 +6,12 @@ import AnalyticsEnrollments from './AnalyticsEnrollments.js';
|
|
|
6
6
|
import AnalyticsEvents from './AnalyticsEvents.js';
|
|
7
7
|
import AnalyticsRequest from './AnalyticsRequest.js';
|
|
8
8
|
import AnalyticsResponse from './AnalyticsResponse.js';
|
|
9
|
-
import AnalyticsTrackedEntities from './AnalyticsTrackedEntities.js';
|
|
10
9
|
|
|
11
10
|
/**
|
|
12
11
|
* @description
|
|
13
12
|
* Analytics class used to request analytics data from Web API.
|
|
14
13
|
*
|
|
15
14
|
* @requires analytics.AnalyticsAggregate
|
|
16
|
-
* @requires analytics.AnalyticsTrackedEntities
|
|
17
|
-
* @requires analytics.AnalyticsEnrollments
|
|
18
15
|
* @requires analytics.AnalyticsEvents
|
|
19
16
|
* @requires analytics.AnalyticsRequest
|
|
20
17
|
* @requires analytics.AnalyticsResponse
|
|
@@ -34,7 +31,6 @@ import AnalyticsTrackedEntities from './AnalyticsTrackedEntities.js';
|
|
|
34
31
|
class Analytics {
|
|
35
32
|
/**
|
|
36
33
|
* @param {!module:analytics.AnalyticsAggregate} analyticsAggregate The AnalyticsAggregate instance
|
|
37
|
-
* @param {!module:analytics.AnalyticsTrackedEntities} analyticsTrackedEntities The AnalyticsTrackedEntities instance
|
|
38
34
|
* @param {!module:analytics.AnalyticsEnrollments} analyticsEnrollments The AnalyticsEnrollments instance
|
|
39
35
|
* @param {!module:analytics.AnalyticsEvents} analyticsEvents The AnalyticsEvents instance
|
|
40
36
|
* @param {!module:analytics.AnalyticsRequest} analyticsRequest The AnalyticsRequest class
|
|
@@ -43,14 +39,12 @@ class Analytics {
|
|
|
43
39
|
constructor(_ref) {
|
|
44
40
|
let {
|
|
45
41
|
aggregate,
|
|
46
|
-
trackedEntities,
|
|
47
42
|
enrollments,
|
|
48
43
|
events,
|
|
49
44
|
request,
|
|
50
45
|
response
|
|
51
46
|
} = _ref;
|
|
52
47
|
this.aggregate = aggregate;
|
|
53
|
-
this.trackedEntities = trackedEntities;
|
|
54
48
|
this.enrollments = enrollments;
|
|
55
49
|
this.events = events;
|
|
56
50
|
this.request = request;
|
|
@@ -73,7 +67,6 @@ class Analytics {
|
|
|
73
67
|
if (!Analytics.getAnalytics.analytics) {
|
|
74
68
|
Analytics.getAnalytics.analytics = new Analytics({
|
|
75
69
|
aggregate: new AnalyticsAggregate(dataEngine),
|
|
76
|
-
trackedEntities: new AnalyticsTrackedEntities(dataEngine),
|
|
77
70
|
enrollments: new AnalyticsEnrollments(dataEngine),
|
|
78
71
|
events: new AnalyticsEvents(dataEngine),
|
|
79
72
|
request: AnalyticsRequest,
|
|
@@ -1,19 +1,13 @@
|
|
|
1
1
|
import sortBy from 'lodash/sortBy';
|
|
2
2
|
import AnalyticsRequest from './AnalyticsRequest.js';
|
|
3
|
-
import { formatRequestPath } from './utils.js';
|
|
4
3
|
const analyticsQuery = {
|
|
5
4
|
resource: 'analytics',
|
|
6
5
|
id: _ref => {
|
|
7
6
|
let {
|
|
8
7
|
path,
|
|
9
|
-
program
|
|
10
|
-
trackedEntityType
|
|
8
|
+
program
|
|
11
9
|
} = _ref;
|
|
12
|
-
return
|
|
13
|
-
path,
|
|
14
|
-
program,
|
|
15
|
-
trackedEntityType
|
|
16
|
-
});
|
|
10
|
+
return [path, program].filter(Boolean).join('/');
|
|
17
11
|
},
|
|
18
12
|
params: _ref2 => {
|
|
19
13
|
let {
|
|
@@ -33,14 +27,9 @@ const analyticsDataQuery = {
|
|
|
33
27
|
id: _ref3 => {
|
|
34
28
|
let {
|
|
35
29
|
path,
|
|
36
|
-
program
|
|
37
|
-
trackedEntityType
|
|
30
|
+
program
|
|
38
31
|
} = _ref3;
|
|
39
|
-
return
|
|
40
|
-
path,
|
|
41
|
-
program,
|
|
42
|
-
trackedEntityType
|
|
43
|
-
});
|
|
32
|
+
return [path, program].filter(Boolean).join('/');
|
|
44
33
|
},
|
|
45
34
|
params: _ref4 => {
|
|
46
35
|
let {
|
|
@@ -62,14 +51,9 @@ const analyticsMetaDataQuery = {
|
|
|
62
51
|
id: _ref5 => {
|
|
63
52
|
let {
|
|
64
53
|
path,
|
|
65
|
-
program
|
|
66
|
-
trackedEntityType
|
|
54
|
+
program
|
|
67
55
|
} = _ref5;
|
|
68
|
-
return
|
|
69
|
-
path,
|
|
70
|
-
program,
|
|
71
|
-
trackedEntityType
|
|
72
|
-
});
|
|
56
|
+
return [path, program].filter(Boolean).join('/');
|
|
73
57
|
},
|
|
74
58
|
params: _ref6 => {
|
|
75
59
|
let {
|
|
@@ -161,7 +145,6 @@ class AnalyticsBase {
|
|
|
161
145
|
variables: {
|
|
162
146
|
path: req.path,
|
|
163
147
|
program: req.program,
|
|
164
|
-
trackedEntityType: req.trackedEntityType,
|
|
165
148
|
dimensions: generateDimensionStrings(req.dimensions),
|
|
166
149
|
filters: generateDimensionStrings(req.filters),
|
|
167
150
|
parameters: req.parameters,
|
|
@@ -204,7 +187,6 @@ class AnalyticsBase {
|
|
|
204
187
|
variables: {
|
|
205
188
|
path: req.path,
|
|
206
189
|
program: req.program,
|
|
207
|
-
trackedEntityType: req.trackedEntityType,
|
|
208
190
|
dimensions: generateDimensionStrings(req.dimensions, options),
|
|
209
191
|
filters: generateDimensionStrings(req.filters, options),
|
|
210
192
|
parameters: req.parameters
|
|
@@ -4,7 +4,6 @@ import AnalyticsRequestBase from './AnalyticsRequestBase.js';
|
|
|
4
4
|
import AnalyticsRequestDimensionsMixin from './AnalyticsRequestDimensionsMixin.js';
|
|
5
5
|
import AnalyticsRequestFiltersMixin from './AnalyticsRequestFiltersMixin.js';
|
|
6
6
|
import AnalyticsRequestPropertiesMixin from './AnalyticsRequestPropertiesMixin.js';
|
|
7
|
-
import { formatDimension } from './utils.js';
|
|
8
7
|
|
|
9
8
|
/**
|
|
10
9
|
* @description
|
|
@@ -42,7 +41,6 @@ class AnalyticsRequest extends AnalyticsRequestDimensionsMixin(AnalyticsRequestF
|
|
|
42
41
|
fromVisualization(visualization) {
|
|
43
42
|
let passFilterAsDimension = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
|
|
44
43
|
let request = this;
|
|
45
|
-
const outputType = visualization.outputType;
|
|
46
44
|
|
|
47
45
|
// extract dimensions from visualization
|
|
48
46
|
const columns = visualization.columns || [];
|
|
@@ -53,28 +51,19 @@ class AnalyticsRequest extends AnalyticsRequestDimensionsMixin(AnalyticsRequestF
|
|
|
53
51
|
if ((_d$legendSet = d.legendSet) !== null && _d$legendSet !== void 0 && _d$legendSet.id) {
|
|
54
52
|
dimension += `-${d.legendSet.id}`;
|
|
55
53
|
}
|
|
54
|
+
if ((_d$programStage = d.programStage) !== null && _d$programStage !== void 0 && _d$programStage.id) {
|
|
55
|
+
dimension = `${d.programStage.id}.${dimension}`;
|
|
56
|
+
}
|
|
56
57
|
if (d.filter) {
|
|
57
58
|
dimension += `:${d.filter}`;
|
|
58
59
|
}
|
|
59
|
-
const programStageId = (_d$programStage = d.programStage) === null || _d$programStage === void 0 ? void 0 : _d$programStage.id;
|
|
60
60
|
if ((_d$repetition = d.repetition) !== null && _d$repetition !== void 0 && (_d$repetition$indexes = _d$repetition.indexes) !== null && _d$repetition$indexes !== void 0 && _d$repetition$indexes.length) {
|
|
61
61
|
d.repetition.indexes.forEach(index => {
|
|
62
|
-
|
|
63
|
-
request = request.addDimension(formatDimension({
|
|
64
|
-
programId: (_d$program = d.program) === null || _d$program === void 0 ? void 0 : _d$program.id,
|
|
65
|
-
programStageId: `${programStageId}[${index}]`,
|
|
66
|
-
dimension,
|
|
67
|
-
outputType
|
|
68
|
-
}));
|
|
62
|
+
request = request.addDimension(dimension.replace(/\./, `[${index}].`));
|
|
69
63
|
});
|
|
70
64
|
} else {
|
|
71
|
-
var _d$
|
|
72
|
-
request = request.addDimension(
|
|
73
|
-
programId: (_d$program2 = d.program) === null || _d$program2 === void 0 ? void 0 : _d$program2.id,
|
|
74
|
-
programStageId,
|
|
75
|
-
dimension,
|
|
76
|
-
outputType
|
|
77
|
-
}), (_d$items = d.items) === null || _d$items === void 0 ? void 0 : _d$items.map(item => item.id));
|
|
65
|
+
var _d$items;
|
|
66
|
+
request = request.addDimension(dimension, (_d$items = d.items) === null || _d$items === void 0 ? void 0 : _d$items.map(item => item.id));
|
|
78
67
|
}
|
|
79
68
|
});
|
|
80
69
|
|
|
@@ -89,29 +78,17 @@ class AnalyticsRequest extends AnalyticsRequestDimensionsMixin(AnalyticsRequestF
|
|
|
89
78
|
request = request.addDimension(f.dimension, (_f$items = f.items) === null || _f$items === void 0 ? void 0 : _f$items.map(item => item.id));
|
|
90
79
|
} else {
|
|
91
80
|
var _f$programStage, _f$repetition, _f$repetition$indexes;
|
|
92
|
-
let filterString = f.dimension;
|
|
81
|
+
let filterString = (_f$programStage = f.programStage) !== null && _f$programStage !== void 0 && _f$programStage.id ? `${f.programStage.id}.${f.dimension}` : f.dimension;
|
|
93
82
|
if (f.filter) {
|
|
94
83
|
filterString += `:${f.filter}`;
|
|
95
84
|
}
|
|
96
|
-
const programStageId = (_f$programStage = f.programStage) === null || _f$programStage === void 0 ? void 0 : _f$programStage.id;
|
|
97
85
|
if ((_f$repetition = f.repetition) !== null && _f$repetition !== void 0 && (_f$repetition$indexes = _f$repetition.indexes) !== null && _f$repetition$indexes !== void 0 && _f$repetition$indexes.length) {
|
|
98
86
|
f.repetition.indexes.forEach(index => {
|
|
99
|
-
|
|
100
|
-
request = request.addFilter(formatDimension({
|
|
101
|
-
programId: (_f$program = f.program) === null || _f$program === void 0 ? void 0 : _f$program.id,
|
|
102
|
-
programStageId: `${programStageId}[${index}]`,
|
|
103
|
-
dimension: filterString,
|
|
104
|
-
outputType
|
|
105
|
-
}));
|
|
87
|
+
request = request.addFilter(filterString.replace(/\./, `[${index}].`));
|
|
106
88
|
});
|
|
107
89
|
} else {
|
|
108
|
-
var _f$
|
|
109
|
-
request = request.addFilter(
|
|
110
|
-
programId: (_f$program2 = f.program) === null || _f$program2 === void 0 ? void 0 : _f$program2.id,
|
|
111
|
-
programStageId,
|
|
112
|
-
dimension: filterString,
|
|
113
|
-
outputType
|
|
114
|
-
}), (_f$items2 = f.items) === null || _f$items2 === void 0 ? void 0 : _f$items2.map(item => item.id));
|
|
90
|
+
var _f$items2;
|
|
91
|
+
request = request.addFilter(filterString, (_f$items2 = f.items) === null || _f$items2 === void 0 ? void 0 : _f$items2.map(item => item.id));
|
|
115
92
|
}
|
|
116
93
|
}
|
|
117
94
|
});
|
|
@@ -18,7 +18,6 @@ class AnalyticsRequestBase {
|
|
|
18
18
|
format = 'json',
|
|
19
19
|
path,
|
|
20
20
|
program,
|
|
21
|
-
trackedEntityType,
|
|
22
21
|
dimensions = [],
|
|
23
22
|
filters = [],
|
|
24
23
|
parameters = {}
|
|
@@ -27,7 +26,6 @@ class AnalyticsRequestBase {
|
|
|
27
26
|
this.format = format.toLowerCase();
|
|
28
27
|
this.path = path;
|
|
29
28
|
this.program = program;
|
|
30
|
-
this.trackedEntityType = trackedEntityType;
|
|
31
29
|
this.dimensions = dimensions;
|
|
32
30
|
this.filters = filters;
|
|
33
31
|
this.parameters = {
|
|
@@ -66,7 +64,7 @@ class AnalyticsRequestBase {
|
|
|
66
64
|
}
|
|
67
65
|
return dimension;
|
|
68
66
|
});
|
|
69
|
-
const endPoint = [this.endPoint, this.path, this.program
|
|
67
|
+
const endPoint = [this.endPoint, this.path, this.program].filter(e => !!e).join('/');
|
|
70
68
|
return `${endPoint}.${this.format}?dimension=${encodedDimensions.join('&dimension=')}`;
|
|
71
69
|
}
|
|
72
70
|
|
|
@@ -491,25 +491,6 @@ class extends base {
|
|
|
491
491
|
return new AnalyticsRequest(this);
|
|
492
492
|
}
|
|
493
493
|
|
|
494
|
-
/**
|
|
495
|
-
* Sets the tracked entity type for the request.
|
|
496
|
-
* It appends the tracked entity type id to the request's path.
|
|
497
|
-
*
|
|
498
|
-
* @param {!String} trackedEntityType The tracked entity type id
|
|
499
|
-
*
|
|
500
|
-
* @returns {AnalyticsRequest} A new instance of the class for chaining purposes
|
|
501
|
-
*
|
|
502
|
-
* @example
|
|
503
|
-
* const req = new analytics.request()
|
|
504
|
-
* .withTrackedEntityType('nEenWmSyUEp');
|
|
505
|
-
*/
|
|
506
|
-
withTrackedEntityType(trackedEntityType) {
|
|
507
|
-
if (trackedEntityType) {
|
|
508
|
-
this.trackedEntityType = trackedEntityType;
|
|
509
|
-
}
|
|
510
|
-
return new AnalyticsRequest(this);
|
|
511
|
-
}
|
|
512
|
-
|
|
513
494
|
/**
|
|
514
495
|
* Sets the program for the request.
|
|
515
496
|
* It appends the program id to the request's path.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import fixtures from '../../../__fixtures__/fixtures.js';
|
|
2
|
+
import DataEngineMock from '../__mocks__/DataEngine.js';
|
|
3
|
+
import AnalyticsRequest from '../AnalyticsRequest.js';
|
|
4
|
+
import AnalyticsTrackedEntities from '../AnalyticsTrackedEntities.js';
|
|
5
|
+
describe.skip('analytics.trackedEntity', () => {
|
|
6
|
+
let enrollments;
|
|
7
|
+
let request;
|
|
8
|
+
let dataEngineMock;
|
|
9
|
+
let fixture;
|
|
10
|
+
beforeEach(() => {
|
|
11
|
+
dataEngineMock = new DataEngineMock();
|
|
12
|
+
DataEngineMock.mockClear();
|
|
13
|
+
enrollments = new AnalyticsTrackedEntities();
|
|
14
|
+
});
|
|
15
|
+
it('should not be allowed to be called without new', () => {
|
|
16
|
+
expect(() => AnalyticsTrackedEntities()).toThrowErrorMatchingSnapshot();
|
|
17
|
+
});
|
|
18
|
+
it('should use the dataEngine object when it is passed', () => {
|
|
19
|
+
const dataEngineMockObject = {};
|
|
20
|
+
enrollments = new AnalyticsTrackedEntities(dataEngineMockObject);
|
|
21
|
+
expect(enrollments.dataEngine).toBe(dataEngineMockObject);
|
|
22
|
+
});
|
|
23
|
+
describe('.getQuery()', () => {
|
|
24
|
+
beforeEach(() => {
|
|
25
|
+
enrollments = new AnalyticsTrackedEntities(new DataEngineMock());
|
|
26
|
+
request = new AnalyticsRequest().addOrgUnitDimension('ImspTQPwCqd').addDimension('WZbXY0S00lP.de0FEHSIoxh').addDimension('WZbXY0S00lP.sWoqcoByYmD').addPeriodFilter('LAST_MONTH').withTrackedEntity('nEenWmSyUEp').withAsc('ENROLLMENTDATE').withOuMode('DESCENDANTS').withColumns('w75KJ2mc4zz').withPage(1).withPageSize(10);
|
|
27
|
+
fixture = fixtures.get('/api/analytics/enrollments'); // XXX
|
|
28
|
+
|
|
29
|
+
dataEngineMock.query.mockReturnValue(Promise.resolve({
|
|
30
|
+
data: fixture
|
|
31
|
+
}));
|
|
32
|
+
});
|
|
33
|
+
it('should be a function', () => {
|
|
34
|
+
expect(enrollments.getQuery).toBeInstanceOf(Function);
|
|
35
|
+
});
|
|
36
|
+
it('should resolve a promise with data', () => enrollments.getQuery(request).then(data => {
|
|
37
|
+
expect(data.width).toEqual(fixture.width);
|
|
38
|
+
expect(data.height).toEqual(fixture.height);
|
|
39
|
+
}));
|
|
40
|
+
});
|
|
41
|
+
});
|
|
@@ -2,23 +2,4 @@
|
|
|
2
2
|
const whitelistURI = ',&$=/;:';
|
|
3
3
|
const whitelistURICodes = whitelistURI.split('').map(c => encodeURIComponent(c));
|
|
4
4
|
const whitelistRegExp = new RegExp(`(?:${whitelistURICodes.join('|')})`, 'g');
|
|
5
|
-
export const customEncodeURIComponent = uri => encodeURIComponent(uri).replace(whitelistRegExp, decodeURIComponent);
|
|
6
|
-
export const formatRequestPath = _ref => {
|
|
7
|
-
let {
|
|
8
|
-
path,
|
|
9
|
-
program,
|
|
10
|
-
trackedEntityType
|
|
11
|
-
} = _ref;
|
|
12
|
-
return [path, program, trackedEntityType].filter(Boolean).join('/');
|
|
13
|
-
};
|
|
14
|
-
export const formatDimension = _ref2 => {
|
|
15
|
-
let {
|
|
16
|
-
outputType,
|
|
17
|
-
programId,
|
|
18
|
-
programStageId,
|
|
19
|
-
dimension
|
|
20
|
-
} = _ref2;
|
|
21
|
-
return [
|
|
22
|
-
// XXX it would be clearer to have this consistent with what is sent in the request as for EVENT/ENROLLMENT
|
|
23
|
-
outputType === 'TRACKED_ENTITY' ? programId : undefined, programStageId, dimension].filter(Boolean).join('.');
|
|
24
|
-
};
|
|
5
|
+
export const customEncodeURIComponent = uri => encodeURIComponent(uri).replace(whitelistRegExp, decodeURIComponent);
|
|
@@ -2,7 +2,7 @@ import i18n from '@dhis2/d2-i18n';
|
|
|
2
2
|
import { ButtonStrip, Modal, ModalTitle, ModalContent, ModalActions, Button, FieldSet, Legend, TabBar, Tab, Help } from '@dhis2/ui';
|
|
3
3
|
import PropTypes from 'prop-types';
|
|
4
4
|
import React, { useState } from 'react';
|
|
5
|
-
import { modalContent, tabSection, tabSectionTitle, tabSectionTitleMargin, tabSectionOption, tabSectionOptionItem, tabSectionOptionToggleable, tabSectionToggleableSubsection, tabSectionOptionComplexInline, tabSectionOptionText, tabBar, tabContent, tabSectionOptionIcon } from './styles/VisualizationOptions.style.js';
|
|
5
|
+
import { modalContent, tabSection, tabSectionTitle, tabSectionTitleDisabled, tabSectionTitleMargin, tabSectionOption, tabSectionOptionItem, tabSectionOptionToggleable, tabSectionToggleableSubsection, tabSectionOptionComplexInline, tabSectionOptionText, tabBar, tabContent, tabSectionOptionIcon } from './styles/VisualizationOptions.style.js';
|
|
6
6
|
const VisualizationOptions = _ref => {
|
|
7
7
|
let {
|
|
8
8
|
initiallyActiveTabKey,
|
|
@@ -59,7 +59,7 @@ const VisualizationOptions = _ref => {
|
|
|
59
59
|
}, label);
|
|
60
60
|
})), tabBar.styles), /*#__PURE__*/React.createElement("div", {
|
|
61
61
|
className: tabContent.className
|
|
62
|
-
}, tabs[activeTabIndex].content, tabContent.styles, tabSection.styles, tabSectionTitle.styles, tabSectionTitleMargin.styles, tabSectionOption.styles, tabSectionOptionItem.styles, tabSectionOptionToggleable.styles, tabSectionToggleableSubsection.styles, tabSectionOptionComplexInline.styles, tabSectionOptionText.styles, tabSectionOptionIcon.styles));
|
|
62
|
+
}, tabs[activeTabIndex].content, tabContent.styles, tabSection.styles, tabSectionTitle.styles, tabSectionTitleDisabled.styles, tabSectionTitleMargin.styles, tabSectionOption.styles, tabSectionOptionItem.styles, tabSectionOptionToggleable.styles, tabSectionToggleableSubsection.styles, tabSectionOptionComplexInline.styles, tabSectionOptionText.styles, tabSectionOptionIcon.styles));
|
|
63
63
|
};
|
|
64
64
|
return /*#__PURE__*/React.createElement(Modal, {
|
|
65
65
|
onClose: onClose,
|
|
@@ -38,6 +38,12 @@ export const tabSectionTitle = {
|
|
|
38
38
|
}, [`span.jsx-3115295887{display:inline-block;padding-bottom:${spacers.dp12};font-size:15px;color:${colors.grey900};font-weight:500;-webkit-letter-spacing:0.2px;-moz-letter-spacing:0.2px;-ms-letter-spacing:0.2px;letter-spacing:0.2px;}`]),
|
|
39
39
|
className: "jsx-3115295887"
|
|
40
40
|
};
|
|
41
|
+
export const tabSectionTitleDisabled = {
|
|
42
|
+
styles: /*#__PURE__*/React.createElement(_JSXStyle, {
|
|
43
|
+
id: "3352433486"
|
|
44
|
+
}, [`span.jsx-3352433486{color:${colors.grey600};}`]),
|
|
45
|
+
className: "jsx-3352433486"
|
|
46
|
+
};
|
|
41
47
|
export const tabSectionTitleMargin = {
|
|
42
48
|
styles: /*#__PURE__*/React.createElement(_JSXStyle, {
|
|
43
49
|
id: "642558349"
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
2
|
+
function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
|
|
3
|
+
function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
|
|
4
|
+
import PropTypes from 'prop-types';
|
|
5
|
+
import React, { Component } from 'react';
|
|
6
|
+
import convertCtrlKey from './convertCtrlKey.js';
|
|
7
|
+
class Editor extends Component {
|
|
8
|
+
constructor() {
|
|
9
|
+
super(...arguments);
|
|
10
|
+
_defineProperty(this, "onKeyDown", event => {
|
|
11
|
+
convertCtrlKey(event, this.props.onEdit);
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
render() {
|
|
15
|
+
const {
|
|
16
|
+
children
|
|
17
|
+
} = this.props;
|
|
18
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
19
|
+
onKeyDown: this.onKeyDown
|
|
20
|
+
}, children);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
Editor.defaultProps = {
|
|
24
|
+
onEdit: null
|
|
25
|
+
};
|
|
26
|
+
Editor.propTypes = {
|
|
27
|
+
children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node]),
|
|
28
|
+
onEdit: PropTypes.func
|
|
29
|
+
};
|
|
30
|
+
export default Editor;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { shallow } from 'enzyme';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import convertCtrlKey from '../convertCtrlKey.js';
|
|
4
|
+
import Editor from '../Editor.js';
|
|
5
|
+
jest.mock('../convertCtrlKey');
|
|
6
|
+
describe('RichText: Editor component', () => {
|
|
7
|
+
let richTextEditor;
|
|
8
|
+
const componentProps = {
|
|
9
|
+
onEdit: jest.fn()
|
|
10
|
+
};
|
|
11
|
+
beforeEach(() => {
|
|
12
|
+
convertCtrlKey.mockClear();
|
|
13
|
+
});
|
|
14
|
+
const renderComponent = props => {
|
|
15
|
+
return shallow( /*#__PURE__*/React.createElement(Editor, props, /*#__PURE__*/React.createElement("input", null)));
|
|
16
|
+
};
|
|
17
|
+
it('renders a result', () => {
|
|
18
|
+
richTextEditor = renderComponent(componentProps);
|
|
19
|
+
expect(richTextEditor).toHaveLength(1);
|
|
20
|
+
});
|
|
21
|
+
it('calls convertCtrlKey on keydown', () => {
|
|
22
|
+
richTextEditor = renderComponent(componentProps);
|
|
23
|
+
richTextEditor.simulate('keyDown');
|
|
24
|
+
expect(convertCtrlKey).toHaveBeenCalled();
|
|
25
|
+
});
|
|
26
|
+
});
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import convertCtrlKey from '../convertCtrlKey.js';
|
|
2
|
+
describe('convertCtrlKey', () => {
|
|
3
|
+
it('does not trigger callback if no ctrl key', () => {
|
|
4
|
+
const cb = jest.fn();
|
|
5
|
+
const e = {
|
|
6
|
+
key: 'j',
|
|
7
|
+
preventDefault: () => {}
|
|
8
|
+
};
|
|
9
|
+
convertCtrlKey(e, cb);
|
|
10
|
+
expect(cb).not.toHaveBeenCalled();
|
|
11
|
+
});
|
|
12
|
+
describe('when ctrl key + "b" pressed', () => {
|
|
13
|
+
it('triggers callback with open/close markers and caret pos in between', () => {
|
|
14
|
+
const cb = jest.fn();
|
|
15
|
+
const e = {
|
|
16
|
+
key: 'b',
|
|
17
|
+
ctrlKey: true,
|
|
18
|
+
target: {
|
|
19
|
+
selectionStart: 0,
|
|
20
|
+
selectionEnd: 0,
|
|
21
|
+
value: 'rainbow dash'
|
|
22
|
+
},
|
|
23
|
+
preventDefault: () => {}
|
|
24
|
+
};
|
|
25
|
+
convertCtrlKey(e, cb);
|
|
26
|
+
expect(cb).toHaveBeenCalled();
|
|
27
|
+
expect(cb).toHaveBeenCalledWith('** rainbow dash', 1);
|
|
28
|
+
});
|
|
29
|
+
it('triggers callback with open/close markers and caret pos in between (end of text)', () => {
|
|
30
|
+
const cb = jest.fn();
|
|
31
|
+
const e = {
|
|
32
|
+
key: 'b',
|
|
33
|
+
ctrlKey: true,
|
|
34
|
+
target: {
|
|
35
|
+
selectionStart: 22,
|
|
36
|
+
selectionEnd: 22,
|
|
37
|
+
value: 'rainbow dash is purple'
|
|
38
|
+
},
|
|
39
|
+
preventDefault: () => {}
|
|
40
|
+
};
|
|
41
|
+
convertCtrlKey(e, cb);
|
|
42
|
+
expect(cb).toHaveBeenCalled();
|
|
43
|
+
expect(cb).toHaveBeenCalledWith('rainbow dash is purple **', 24);
|
|
44
|
+
});
|
|
45
|
+
it('triggers callback with open/close markers mid-text with surrounding spaces (1)', () => {
|
|
46
|
+
const cb = jest.fn();
|
|
47
|
+
const e = {
|
|
48
|
+
key: 'b',
|
|
49
|
+
metaKey: true,
|
|
50
|
+
target: {
|
|
51
|
+
selectionStart: 4,
|
|
52
|
+
// caret located just before "quick"
|
|
53
|
+
selectionEnd: 4,
|
|
54
|
+
value: 'the quick brown fox'
|
|
55
|
+
},
|
|
56
|
+
preventDefault: () => {}
|
|
57
|
+
};
|
|
58
|
+
convertCtrlKey(e, cb);
|
|
59
|
+
expect(cb).toHaveBeenCalled();
|
|
60
|
+
expect(cb).toHaveBeenCalledWith('the ** quick brown fox', 5);
|
|
61
|
+
});
|
|
62
|
+
it('triggers callback with open/close markers mid-text with surrounding spaces (2)', () => {
|
|
63
|
+
const cb = jest.fn();
|
|
64
|
+
const e = {
|
|
65
|
+
key: 'b',
|
|
66
|
+
metaKey: true,
|
|
67
|
+
target: {
|
|
68
|
+
selectionStart: 3,
|
|
69
|
+
// caret located just after "the"
|
|
70
|
+
selectionEnd: 3,
|
|
71
|
+
value: 'the quick brown fox'
|
|
72
|
+
},
|
|
73
|
+
preventDefault: () => {}
|
|
74
|
+
};
|
|
75
|
+
convertCtrlKey(e, cb);
|
|
76
|
+
expect(cb).toHaveBeenCalled();
|
|
77
|
+
expect(cb).toHaveBeenCalledWith('the ** quick brown fox', 5);
|
|
78
|
+
});
|
|
79
|
+
it('triggers callback with correct double markers and padding', () => {
|
|
80
|
+
const cb = jest.fn();
|
|
81
|
+
const e = {
|
|
82
|
+
key: 'b',
|
|
83
|
+
metaKey: true,
|
|
84
|
+
target: {
|
|
85
|
+
selectionStart: 9,
|
|
86
|
+
// between the underscores
|
|
87
|
+
selectionEnd: 9,
|
|
88
|
+
value: 'rainbow __'
|
|
89
|
+
},
|
|
90
|
+
preventDefault: () => {}
|
|
91
|
+
};
|
|
92
|
+
convertCtrlKey(e, cb);
|
|
93
|
+
expect(cb).toHaveBeenCalled();
|
|
94
|
+
expect(cb).toHaveBeenCalledWith('rainbow _**_', 10);
|
|
95
|
+
});
|
|
96
|
+
describe('selected text', () => {
|
|
97
|
+
it('triggers callback with open/close markers around text and caret pos after closing marker', () => {
|
|
98
|
+
const cb = jest.fn();
|
|
99
|
+
const e = {
|
|
100
|
+
key: 'b',
|
|
101
|
+
metaKey: true,
|
|
102
|
+
target: {
|
|
103
|
+
selectionStart: 5,
|
|
104
|
+
// "ow da" is selected
|
|
105
|
+
selectionEnd: 10,
|
|
106
|
+
value: 'rainbow dash is purple'
|
|
107
|
+
},
|
|
108
|
+
preventDefault: () => {}
|
|
109
|
+
};
|
|
110
|
+
convertCtrlKey(e, cb);
|
|
111
|
+
expect(cb).toHaveBeenCalled();
|
|
112
|
+
expect(cb).toHaveBeenCalledWith('rainb *ow da* sh is purple', 13);
|
|
113
|
+
});
|
|
114
|
+
it('triggers callback with open/close markers around text when starting at beginning of line', () => {
|
|
115
|
+
const cb = jest.fn();
|
|
116
|
+
const e = {
|
|
117
|
+
key: 'b',
|
|
118
|
+
metaKey: true,
|
|
119
|
+
target: {
|
|
120
|
+
selectionStart: 0,
|
|
121
|
+
// "rainbow" is selected
|
|
122
|
+
selectionEnd: 7,
|
|
123
|
+
value: 'rainbow dash is purple'
|
|
124
|
+
},
|
|
125
|
+
preventDefault: () => {}
|
|
126
|
+
};
|
|
127
|
+
convertCtrlKey(e, cb);
|
|
128
|
+
expect(cb).toHaveBeenCalled();
|
|
129
|
+
expect(cb).toHaveBeenCalledWith('*rainbow* dash is purple', 9);
|
|
130
|
+
});
|
|
131
|
+
it('triggers callback with open/close markers around text when ending at end of line', () => {
|
|
132
|
+
const cb = jest.fn();
|
|
133
|
+
const e = {
|
|
134
|
+
key: 'b',
|
|
135
|
+
metaKey: true,
|
|
136
|
+
target: {
|
|
137
|
+
selectionStart: 16,
|
|
138
|
+
// "purple" is selected
|
|
139
|
+
selectionEnd: 22,
|
|
140
|
+
value: 'rainbow dash is purple'
|
|
141
|
+
},
|
|
142
|
+
preventDefault: () => {}
|
|
143
|
+
};
|
|
144
|
+
convertCtrlKey(e, cb);
|
|
145
|
+
expect(cb).toHaveBeenCalled();
|
|
146
|
+
expect(cb).toHaveBeenCalledWith('rainbow dash is *purple*', 24);
|
|
147
|
+
});
|
|
148
|
+
it('triggers callback with open/close markers around word', () => {
|
|
149
|
+
const cb = jest.fn();
|
|
150
|
+
const e = {
|
|
151
|
+
key: 'b',
|
|
152
|
+
metaKey: true,
|
|
153
|
+
target: {
|
|
154
|
+
selectionStart: 8,
|
|
155
|
+
// "dash" is selected
|
|
156
|
+
selectionEnd: 12,
|
|
157
|
+
value: 'rainbow dash is purple'
|
|
158
|
+
},
|
|
159
|
+
preventDefault: () => {}
|
|
160
|
+
};
|
|
161
|
+
convertCtrlKey(e, cb);
|
|
162
|
+
expect(cb).toHaveBeenCalled();
|
|
163
|
+
expect(cb).toHaveBeenCalledWith('rainbow *dash* is purple', 14);
|
|
164
|
+
});
|
|
165
|
+
it('triggers callback with leading/trailing spaces trimmed from selection', () => {
|
|
166
|
+
const cb = jest.fn();
|
|
167
|
+
const e = {
|
|
168
|
+
key: 'b',
|
|
169
|
+
metaKey: true,
|
|
170
|
+
target: {
|
|
171
|
+
selectionStart: 8,
|
|
172
|
+
// " dash " is selected (note leading and trailing space)
|
|
173
|
+
selectionEnd: 13,
|
|
174
|
+
value: 'rainbow dash is purple'
|
|
175
|
+
},
|
|
176
|
+
preventDefault: () => {}
|
|
177
|
+
};
|
|
178
|
+
convertCtrlKey(e, cb);
|
|
179
|
+
expect(cb).toHaveBeenCalled();
|
|
180
|
+
expect(cb).toHaveBeenCalledWith('rainbow *dash* is purple', 14);
|
|
181
|
+
});
|
|
182
|
+
});
|
|
183
|
+
});
|
|
184
|
+
describe('when ctrl key + "i" pressed', () => {
|
|
185
|
+
it('triggers callback with open/close italics markers and caret pos in between', () => {
|
|
186
|
+
const cb = jest.fn();
|
|
187
|
+
const e = {
|
|
188
|
+
key: 'i',
|
|
189
|
+
ctrlKey: true,
|
|
190
|
+
target: {
|
|
191
|
+
selectionStart: 0,
|
|
192
|
+
selectionEnd: 0,
|
|
193
|
+
value: ''
|
|
194
|
+
},
|
|
195
|
+
preventDefault: () => {}
|
|
196
|
+
};
|
|
197
|
+
convertCtrlKey(e, cb);
|
|
198
|
+
expect(cb).toHaveBeenCalled();
|
|
199
|
+
expect(cb).toHaveBeenCalledWith('__', 1);
|
|
200
|
+
});
|
|
201
|
+
});
|
|
202
|
+
});
|