@dhis2/analytics 24.10.1 → 25.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 (84) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/build/cjs/__demo__/CalculationModal.stories.js +448 -0
  3. package/build/cjs/api/analytics/AnalyticsRequest.js +12 -1
  4. package/build/cjs/api/dimensions.js +1 -1
  5. package/build/cjs/api/expression.js +67 -0
  6. package/build/cjs/assets/DimensionItemIcons/CalculationIcon.js +25 -0
  7. package/build/cjs/assets/FormulaIcon.js +40 -0
  8. package/build/cjs/components/DataDimension/Calculation/CalculationModal.js +447 -0
  9. package/build/cjs/components/DataDimension/Calculation/DataElementOption.js +77 -0
  10. package/build/cjs/components/DataDimension/Calculation/DataElementSelector.js +306 -0
  11. package/build/cjs/components/DataDimension/Calculation/DndContext.js +213 -0
  12. package/build/cjs/components/DataDimension/Calculation/DragHandleIcon.js +23 -0
  13. package/build/cjs/components/DataDimension/Calculation/DraggingItem.js +58 -0
  14. package/build/cjs/components/DataDimension/Calculation/DropZone.js +58 -0
  15. package/build/cjs/components/DataDimension/Calculation/FormulaField.js +121 -0
  16. package/build/cjs/components/DataDimension/Calculation/FormulaItem.js +232 -0
  17. package/build/cjs/components/DataDimension/Calculation/MathOperatorSelector.js +57 -0
  18. package/build/cjs/components/DataDimension/Calculation/Operator.js +81 -0
  19. package/build/cjs/components/DataDimension/Calculation/styles/CalculationModal.style.js +13 -0
  20. package/build/cjs/components/DataDimension/Calculation/styles/DataElementOption.style.js +13 -0
  21. package/build/cjs/components/DataDimension/Calculation/styles/DataElementSelector.style.js +13 -0
  22. package/build/cjs/components/DataDimension/Calculation/styles/DraggingItem.style.js +13 -0
  23. package/build/cjs/components/DataDimension/Calculation/styles/DropZone.style.js +13 -0
  24. package/build/cjs/components/DataDimension/Calculation/styles/FormulaField.style.js +13 -0
  25. package/build/cjs/components/DataDimension/Calculation/styles/FormulaItem.style.js +13 -0
  26. package/build/cjs/components/DataDimension/Calculation/styles/MathOperatorSelector.style.js +13 -0
  27. package/build/cjs/components/DataDimension/Calculation/styles/Operator.style.js +13 -0
  28. package/build/cjs/components/DataDimension/DataDimension.js +22 -6
  29. package/build/cjs/components/DataDimension/DataTypeSelector.js +5 -3
  30. package/build/cjs/components/DataDimension/ItemSelector.js +111 -73
  31. package/build/cjs/components/TransferOption.js +13 -4
  32. package/build/cjs/components/styles/DimensionSelector.style.js +2 -2
  33. package/build/cjs/components/styles/TransferOption.style.js +2 -2
  34. package/build/cjs/index.js +6 -0
  35. package/build/cjs/locales/en/translations.json +32 -7
  36. package/build/cjs/modules/__tests__/expressions.spec.js +139 -0
  37. package/build/cjs/modules/__tests__/hash.spec.js +92 -0
  38. package/build/cjs/modules/__tests__/parseExpression.spec.js +46 -0
  39. package/build/cjs/modules/dataTypes.js +8 -1
  40. package/build/cjs/modules/dimensionListItem.js +82 -0
  41. package/build/cjs/modules/expressions.js +164 -0
  42. package/build/cjs/modules/hash.js +28 -0
  43. package/build/es/__demo__/CalculationModal.stories.js +440 -0
  44. package/build/es/api/analytics/AnalyticsRequest.js +11 -1
  45. package/build/es/api/dimensions.js +1 -1
  46. package/build/es/api/expression.js +57 -0
  47. package/build/es/assets/DimensionItemIcons/CalculationIcon.js +13 -0
  48. package/build/es/assets/FormulaIcon.js +30 -0
  49. package/build/es/components/DataDimension/Calculation/CalculationModal.js +418 -0
  50. package/build/es/components/DataDimension/Calculation/DataElementOption.js +60 -0
  51. package/build/es/components/DataDimension/Calculation/DataElementSelector.js +280 -0
  52. package/build/es/components/DataDimension/Calculation/DndContext.js +194 -0
  53. package/build/es/components/DataDimension/Calculation/DragHandleIcon.js +11 -0
  54. package/build/es/components/DataDimension/Calculation/DraggingItem.js +40 -0
  55. package/build/es/components/DataDimension/Calculation/DropZone.js +43 -0
  56. package/build/es/components/DataDimension/Calculation/FormulaField.js +98 -0
  57. package/build/es/components/DataDimension/Calculation/FormulaItem.js +207 -0
  58. package/build/es/components/DataDimension/Calculation/MathOperatorSelector.js +41 -0
  59. package/build/es/components/DataDimension/Calculation/Operator.js +64 -0
  60. package/build/es/components/DataDimension/Calculation/styles/CalculationModal.style.js +4 -0
  61. package/build/es/components/DataDimension/Calculation/styles/DataElementOption.style.js +4 -0
  62. package/build/es/components/DataDimension/Calculation/styles/DataElementSelector.style.js +4 -0
  63. package/build/es/components/DataDimension/Calculation/styles/DraggingItem.style.js +4 -0
  64. package/build/es/components/DataDimension/Calculation/styles/DropZone.style.js +4 -0
  65. package/build/es/components/DataDimension/Calculation/styles/FormulaField.style.js +4 -0
  66. package/build/es/components/DataDimension/Calculation/styles/FormulaItem.style.js +4 -0
  67. package/build/es/components/DataDimension/Calculation/styles/MathOperatorSelector.style.js +4 -0
  68. package/build/es/components/DataDimension/Calculation/styles/Operator.style.js +4 -0
  69. package/build/es/components/DataDimension/DataDimension.js +21 -6
  70. package/build/es/components/DataDimension/DataTypeSelector.js +6 -4
  71. package/build/es/components/DataDimension/ItemSelector.js +111 -73
  72. package/build/es/components/TransferOption.js +14 -5
  73. package/build/es/components/styles/DimensionSelector.style.js +2 -2
  74. package/build/es/components/styles/TransferOption.style.js +2 -2
  75. package/build/es/index.js +1 -1
  76. package/build/es/locales/en/translations.json +32 -7
  77. package/build/es/modules/__tests__/expressions.spec.js +136 -0
  78. package/build/es/modules/__tests__/hash.spec.js +88 -0
  79. package/build/es/modules/__tests__/parseExpression.spec.js +43 -0
  80. package/build/es/modules/dataTypes.js +6 -0
  81. package/build/es/modules/dimensionListItem.js +61 -0
  82. package/build/es/modules/expressions.js +131 -0
  83. package/build/es/modules/hash.js +12 -0
  84. package/package.json +6 -1
@@ -0,0 +1,88 @@
1
+ import { DIMENSION_TYPE_EXPRESSION_DIMENSION_ITEM } from '../dataTypes.js';
2
+ import { getExpressionHashFromVisualization, getHash } from '../hash.js';
3
+ describe('getHash', () => {
4
+ const textInput = 'Raymond Luxury Yacht';
5
+ it('accepts a string and returns a hash', () => {
6
+ const hash = getHash(textInput);
7
+ expect(typeof hash).toBe('string');
8
+ expect(hash).not.toBe(textInput);
9
+ });
10
+ it('is deterministic', () => {
11
+ expect(getHash(textInput)).toBe(getHash(textInput));
12
+ });
13
+ it('returns undefined for invalid input', () => {
14
+ const unsupportedTypes = ['', 1, true, null, undefined, {}, []];
15
+ unsupportedTypes.forEach(type => expect(getHash(type)).toBe(undefined));
16
+ });
17
+ });
18
+ describe('getExpressionHashFromVisualization', () => {
19
+ const edi1 = {
20
+ id: 'OdiHJayrsKo',
21
+ dimensionItemType: DIMENSION_TYPE_EXPRESSION_DIMENSION_ITEM,
22
+ expression: '#{abc} * 10'
23
+ };
24
+ const edi2 = {
25
+ id: 'Uvn6LCg7dVU',
26
+ dimensionItemType: DIMENSION_TYPE_EXPRESSION_DIMENSION_ITEM,
27
+ expression: '#{abc} * 20'
28
+ };
29
+ const dxWithEdi = {
30
+ dimension: 'dx',
31
+ items: [edi1, edi2]
32
+ };
33
+ it('generates a hash (columns)', () => {
34
+ expect(typeof getExpressionHashFromVisualization({
35
+ columns: [dxWithEdi],
36
+ rows: [],
37
+ filters: []
38
+ })).toBe('string');
39
+ });
40
+ it('generates a hash (rows)', () => {
41
+ expect(typeof getExpressionHashFromVisualization({
42
+ columns: [],
43
+ rows: [dxWithEdi],
44
+ filters: []
45
+ })).toBe('string');
46
+ });
47
+ it('generates a hash (filters)', () => {
48
+ expect(typeof getExpressionHashFromVisualization({
49
+ columns: [],
50
+ rows: [],
51
+ filters: [dxWithEdi]
52
+ })).toBe('string');
53
+ });
54
+ it('does not generate a hash when there are no dimensions', () => {
55
+ expect(getExpressionHashFromVisualization({
56
+ columns: [],
57
+ rows: [],
58
+ filters: []
59
+ })).toBe(undefined);
60
+ });
61
+ it('does not generate a hash when there are no EDI dimensions', () => {
62
+ expect(getExpressionHashFromVisualization({
63
+ columns: [{
64
+ id: 'OdiHJayrsKo',
65
+ dimensionItemType: 'INDICATOR'
66
+ }],
67
+ rows: [],
68
+ filters: []
69
+ })).toBe(undefined);
70
+ });
71
+ it('sorts the edi objects by id before generating the hash to optimize caching', () => {
72
+ expect(getExpressionHashFromVisualization({
73
+ columns: [{
74
+ dimension: 'dx',
75
+ items: [edi1, edi2]
76
+ }],
77
+ rows: [],
78
+ filters: []
79
+ })).toBe(getExpressionHashFromVisualization({
80
+ columns: [{
81
+ dimension: 'dx',
82
+ items: [edi2, edi1]
83
+ }],
84
+ rows: [],
85
+ filters: []
86
+ }));
87
+ });
88
+ });
@@ -0,0 +1,43 @@
1
+ import { parseExpression } from '../expressions.js';
2
+ test('matches numbers and operators', () => {
3
+ expect(parseExpression('1+2-3*4/5')).toEqual(['1', '+', '2', '-', '3', '*', '4', '/', '5']);
4
+ });
5
+ test('matches #{} with letters, numbers and operators', () => {
6
+ expect(parseExpression('#{abc123}+100-200*300/400')).toEqual(['#{abc123}', '+', '100', '-', '200', '*', '300', '/', '400']);
7
+ });
8
+ test('matches numbers and operators with brackets', () => {
9
+ expect(parseExpression('1+(2-3)*4/5')).toEqual(['1', '+', '(', '2', '-', '3', ')', '*', '4', '/', '5']);
10
+ });
11
+ test('matches #{} with letters, numbers and operators with brackets', () => {
12
+ expect(parseExpression('(100-200)+#{abc123}*300/400')).toEqual(['(', '100', '-', '200', ')', '+', '#{abc123}', '*', '300', '/', '400']);
13
+ });
14
+ test('matches #{} with numbers and operators with brackets', () => {
15
+ expect(parseExpression('#{123}+(10-200)*3000/40000')).toEqual(['#{123}', '+', '(', '10', '-', '200', ')', '*', '3000', '/', '40000']);
16
+ });
17
+ test('matches #{} with letters and numbers only', () => {
18
+ expect(parseExpression('#{abc123}')).toEqual(['#{abc123}']);
19
+ });
20
+ test('matches #{} with numbers only', () => {
21
+ expect(parseExpression('#{123}')).toEqual(['#{123}']);
22
+ });
23
+ test('matches #{} with letters only', () => {
24
+ expect(parseExpression('#{abc}')).toEqual(['#{abc}']);
25
+ });
26
+ test('matches #{} with no input', () => {
27
+ expect(parseExpression('')).toEqual([]);
28
+ });
29
+ test('matches multiple #{} with operators', () => {
30
+ expect(parseExpression('#{abc123}+#{def456}')).toEqual(['#{abc123}', '+', '#{def456}']);
31
+ });
32
+ test('matches multiple #{} containing dots with operators', () => {
33
+ expect(parseExpression('#{abc123.xyz999}+#{def456.xyz999}')).toEqual(['#{abc123.xyz999}', '+', '#{def456.xyz999}']);
34
+ });
35
+ test('matches multiple #{} with operators with brackets', () => {
36
+ expect(parseExpression('(#{abc123}/#{def456})*#{ghi789}')).toEqual(['(', '#{abc123}', '/', '#{def456}', ')', '*', '#{ghi789}']);
37
+ });
38
+ test('matches on decimal numbers', () => {
39
+ expect(parseExpression('#{abc123}*1.2/#{def456}')).toEqual(['#{abc123}', '*', '1.2', '/', '#{def456}']);
40
+ });
41
+ test('matches on decimal numbers with #{} containing dots', () => {
42
+ expect(parseExpression('1.2+#{abc123.xyz999}')).toEqual(['1.2', '+', '#{abc123.xyz999}']);
43
+ });
@@ -15,6 +15,7 @@ export const DIMENSION_TYPE_DATA = 'DATA_X';
15
15
  export const DIMENSION_TYPE_PERIOD = 'PERIOD';
16
16
  export const DIMENSION_TYPE_ORGANISATION_UNIT = 'ORGANISATION_UNIT';
17
17
  export const DIMENSION_TYPE_ORGANISATION_UNIT_GROUP_SET = 'ORGANISATION_UNIT_GROUP_SET';
18
+ export const DIMENSION_TYPE_EXPRESSION_DIMENSION_ITEM = 'EXPRESSION_DIMENSION_ITEM';
18
19
  export const TOTALS = 'totals';
19
20
  export const DETAIL = 'detail';
20
21
  export const SUB_GROUP_DETAIL = 'DETAIL';
@@ -88,6 +89,11 @@ export const dataTypeMap = {
88
89
  getItemName: () => i18n.t('Program indicator'),
89
90
  getGroupEmptyLabel: () => i18n.t('No programs found'),
90
91
  getGroupLoadingLabel: () => i18n.t('Loading programs')
92
+ },
93
+ [DIMENSION_TYPE_EXPRESSION_DIMENSION_ITEM]: {
94
+ id: DIMENSION_TYPE_EXPRESSION_DIMENSION_ITEM,
95
+ getName: () => i18n.t('Calculations'),
96
+ getItemName: () => i18n.t('Calculation')
91
97
  }
92
98
  };
93
99
  export function defaultGroupId(dataType) {
@@ -0,0 +1,61 @@
1
+ import { IconDimensionDataSet16, IconDimensionIndicator16, IconDimensionEventDataItem16, IconDimensionProgramIndicator16 } from '@dhis2/ui';
2
+ import React from 'react';
3
+ import DataElementIcon from '../assets/DimensionItemIcons/DataElementIcon.js';
4
+ import GenericIcon from '../assets/DimensionItemIcons/GenericIcon.js';
5
+ import CalculationIcon from './../assets/DimensionItemIcons/CalculationIcon.js';
6
+ import { REPORTING_RATE } from './dataSets.js';
7
+ import { DIMENSION_TYPE_DATA_ELEMENT, DIMENSION_TYPE_DATA_ELEMENT_OPERAND, DIMENSION_TYPE_DATA_SET, DIMENSION_TYPE_EVENT_DATA_ITEM, DIMENSION_TYPE_EXPRESSION_DIMENSION_ITEM, DIMENSION_TYPE_PROGRAM_ATTRIBUTE, DIMENSION_TYPE_PROGRAM_DATA_ELEMENT, dataTypeMap as dataTypes, DIMENSION_TYPE_INDICATOR, DIMENSION_TYPE_PROGRAM_INDICATOR } from './dataTypes.js';
8
+ export const getTooltipText = _ref => {
9
+ var _dataTypes$type;
10
+
11
+ let {
12
+ type,
13
+ expression
14
+ } = _ref;
15
+
16
+ if (type === DIMENSION_TYPE_EXPRESSION_DIMENSION_ITEM && expression) {
17
+ return dataTypes[DIMENSION_TYPE_EXPRESSION_DIMENSION_ITEM].getItemName();
18
+ }
19
+
20
+ switch (type) {
21
+ case DIMENSION_TYPE_DATA_ELEMENT_OPERAND:
22
+ return dataTypes[DIMENSION_TYPE_DATA_ELEMENT].getItemName();
23
+
24
+ case REPORTING_RATE:
25
+ return dataTypes[DIMENSION_TYPE_DATA_SET].getItemName();
26
+
27
+ case DIMENSION_TYPE_PROGRAM_DATA_ELEMENT:
28
+ case DIMENSION_TYPE_PROGRAM_ATTRIBUTE:
29
+ return dataTypes[DIMENSION_TYPE_EVENT_DATA_ITEM].getItemName();
30
+
31
+ default:
32
+ return (_dataTypes$type = dataTypes[type]) === null || _dataTypes$type === void 0 ? void 0 : _dataTypes$type.getItemName();
33
+ }
34
+ };
35
+ export const getIcon = type => {
36
+ switch (type) {
37
+ case DIMENSION_TYPE_INDICATOR:
38
+ return /*#__PURE__*/React.createElement(IconDimensionIndicator16, null);
39
+
40
+ case DIMENSION_TYPE_DATA_ELEMENT_OPERAND:
41
+ case DIMENSION_TYPE_DATA_ELEMENT:
42
+ return DataElementIcon;
43
+
44
+ case REPORTING_RATE:
45
+ return /*#__PURE__*/React.createElement(IconDimensionDataSet16, null);
46
+
47
+ case DIMENSION_TYPE_EVENT_DATA_ITEM:
48
+ case DIMENSION_TYPE_PROGRAM_DATA_ELEMENT:
49
+ case DIMENSION_TYPE_PROGRAM_ATTRIBUTE:
50
+ return /*#__PURE__*/React.createElement(IconDimensionEventDataItem16, null);
51
+
52
+ case DIMENSION_TYPE_PROGRAM_INDICATOR:
53
+ return /*#__PURE__*/React.createElement(IconDimensionProgramIndicator16, null);
54
+
55
+ case DIMENSION_TYPE_EXPRESSION_DIMENSION_ITEM:
56
+ return CalculationIcon;
57
+
58
+ default:
59
+ return GenericIcon;
60
+ }
61
+ };
@@ -0,0 +1,131 @@
1
+ import i18n from '../locales/index.js';
2
+ export const EXPRESSION_TYPE_NUMBER = 'EXPRESSION_TYPE_NUMBER';
3
+ export const EXPRESSION_TYPE_OPERATOR = 'EXPRESSION_TYPE_OPERATOR';
4
+ export const EXPRESSION_TYPE_DATA = 'EXPRESSION_TYPE_DATA';
5
+ export const VALID_EXPRESSION = 'OK';
6
+ export const INVALID_EXPRESSION = 'ERROR';
7
+ export const getOperators = () => [{
8
+ value: '+',
9
+ label: '+',
10
+ type: EXPRESSION_TYPE_OPERATOR
11
+ }, {
12
+ value: '-',
13
+ label: '-',
14
+ type: EXPRESSION_TYPE_OPERATOR
15
+ }, {
16
+ value: '*',
17
+ label: '×',
18
+ type: EXPRESSION_TYPE_OPERATOR
19
+ }, {
20
+ value: '/',
21
+ label: '/',
22
+ type: EXPRESSION_TYPE_OPERATOR
23
+ }, {
24
+ value: '(',
25
+ label: '(',
26
+ type: EXPRESSION_TYPE_OPERATOR
27
+ }, {
28
+ value: ')',
29
+ label: ')',
30
+ type: EXPRESSION_TYPE_OPERATOR
31
+ }, {
32
+ value: '',
33
+ label: i18n.t('Number'),
34
+ type: EXPRESSION_TYPE_NUMBER
35
+ }];
36
+ export const parseExpression = input => {
37
+ const regex = /(#{[a-zA-Z0-9#.]+}|[+\-*/()])|(\d+(\.\d+)?)/g;
38
+ return input.match(regex) || [];
39
+ };
40
+ export const parseExpressionToArray = function () {
41
+ let expression = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
42
+ let metadata = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
43
+ return parseExpression(expression).map(value => {
44
+ if (value.startsWith('#{') && value.endsWith('}')) {
45
+ var _metadata$find;
46
+
47
+ const id = value.slice(2, -1);
48
+ const label = ((_metadata$find = metadata.find(item => item.id === id)) === null || _metadata$find === void 0 ? void 0 : _metadata$find.name) || id;
49
+ return {
50
+ value,
51
+ label,
52
+ type: EXPRESSION_TYPE_DATA
53
+ };
54
+ }
55
+
56
+ if (isNaN(value)) {
57
+ return {
58
+ value,
59
+ label: getOperators().find(op => op.value === value).label,
60
+ type: EXPRESSION_TYPE_OPERATOR
61
+ };
62
+ }
63
+
64
+ return {
65
+ value,
66
+ label: value,
67
+ type: EXPRESSION_TYPE_NUMBER
68
+ };
69
+ }) || [];
70
+ };
71
+ export const parseArrayToExpression = function () {
72
+ let input = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
73
+ return input.map(item => item.value).join('');
74
+ };
75
+ export const validateExpression = expression => {
76
+ let result;
77
+ const leftParenthesisCount = expression.split('(').length - 1;
78
+ const rightParenthesisCount = expression.split(')').length - 1;
79
+
80
+ if (!expression) {
81
+ // empty formula
82
+ result = {
83
+ status: INVALID_EXPRESSION,
84
+ message: i18n.t('Formula is empty. Add items to the formula from the lists on the left.')
85
+ }; // TODO: reimplement this but allow negative values, e.g. 10 / -5
86
+ // } else if (/[-+/*]{2,}/.test(expression)) {
87
+ // // two math operators next to each other
88
+ // result = {
89
+ // status: INVALID_EXPRESSION,
90
+ // message: i18n.t('Consecutive math operators'),
91
+ // }
92
+ } else if (/}#/.test(expression)) {
93
+ // two data elements next to each other
94
+ result = {
95
+ status: INVALID_EXPRESSION,
96
+ message: i18n.t('Consecutive data elements')
97
+ };
98
+ } else if (/^[+\-*/]|[+\-*/]$/.test(expression)) {
99
+ // starting or ending with a math operator
100
+ result = {
101
+ status: INVALID_EXPRESSION,
102
+ message: i18n.t('Starts or ends with a math operator')
103
+ };
104
+ } else if (/\(\)/.test(expression)) {
105
+ // contains an empty set of parentheses
106
+ result = {
107
+ status: INVALID_EXPRESSION,
108
+ message: i18n.t('Empty parentheses')
109
+ };
110
+ } else if (leftParenthesisCount > rightParenthesisCount) {
111
+ // ( but no )
112
+ result = {
113
+ status: INVALID_EXPRESSION,
114
+ message: i18n.t('Missing right parenthesis )')
115
+ };
116
+ } else if (rightParenthesisCount > leftParenthesisCount) {
117
+ // ) but no (
118
+ result = {
119
+ status: INVALID_EXPRESSION,
120
+ message: i18n.t('Missing left parenthesis (')
121
+ };
122
+ }
123
+
124
+ return result;
125
+ };
126
+ export const getItemIdsFromExpression = function () {
127
+ let expression = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
128
+ const regex = /#{([a-zA-Z0-9#]+.*?)}/g;
129
+ const matches = expression.match(regex);
130
+ return matches ? matches.map(match => match.slice(2, -1)) : [];
131
+ };
@@ -0,0 +1,12 @@
1
+ import SHA1 from 'crypto-js/sha1';
2
+ import { DIMENSION_TYPE_EXPRESSION_DIMENSION_ITEM } from './dataTypes.js';
3
+ import { layoutGetAllItems } from './layout/layoutGetAllItems.js';
4
+
5
+ const isValidValue = value => typeof value === 'string' && value.length;
6
+
7
+ export const getHash = value => isValidValue(value) ? SHA1(value).toString() : undefined;
8
+ export const getExpressionHashFromVisualization = visualization => {
9
+ var _layoutGetAllItems;
10
+
11
+ return getHash((_layoutGetAllItems = layoutGetAllItems(visualization)) === null || _layoutGetAllItems === void 0 ? void 0 : _layoutGetAllItems.filter(item => item.dimensionItemType === DIMENSION_TYPE_EXPRESSION_DIMENSION_ITEM && isValidValue(item.expression)).sort((i1, i2) => i1.id < i2.id ? -1 : i1.id > i2.id ? 1 : 0).map(edi => edi.expression).join(''));
12
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dhis2/analytics",
3
- "version": "24.10.1",
3
+ "version": "25.0.0",
4
4
  "main": "./build/cjs/index.js",
5
5
  "module": "./build/es/index.js",
6
6
  "exports": {
@@ -60,7 +60,12 @@
60
60
  "dependencies": {
61
61
  "@dhis2/d2-ui-rich-text": "^7.4.0",
62
62
  "@dhis2/multi-calendar-dates": "1.0.0",
63
+ "@dnd-kit/core": "^6.0.7",
64
+ "@dnd-kit/sortable": "^7.0.2",
65
+ "@dnd-kit/utilities": "^3.2.1",
66
+ "@react-hook/debounce": "^4.0.0",
63
67
  "classnames": "^2.3.1",
68
+ "crypto-js": "^4.1.1",
64
69
  "d2-utilizr": "^0.2.16",
65
70
  "d3-color": "^1.2.3",
66
71
  "highcharts": "^10.2.0",