@dhis2/analytics 24.10.0 → 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.
- package/CHANGELOG.md +19 -0
- package/build/cjs/__demo__/CalculationModal.stories.js +448 -0
- package/build/cjs/api/analytics/AnalyticsRequest.js +12 -1
- package/build/cjs/api/dimensions.js +1 -1
- package/build/cjs/api/expression.js +67 -0
- package/build/cjs/assets/DimensionItemIcons/CalculationIcon.js +25 -0
- package/build/cjs/assets/FormulaIcon.js +40 -0
- package/build/cjs/components/DataDimension/Calculation/CalculationModal.js +447 -0
- package/build/cjs/components/DataDimension/Calculation/DataElementOption.js +77 -0
- package/build/cjs/components/DataDimension/Calculation/DataElementSelector.js +306 -0
- package/build/cjs/components/DataDimension/Calculation/DndContext.js +213 -0
- package/build/cjs/components/DataDimension/Calculation/DragHandleIcon.js +23 -0
- package/build/cjs/components/DataDimension/Calculation/DraggingItem.js +58 -0
- package/build/cjs/components/DataDimension/Calculation/DropZone.js +58 -0
- package/build/cjs/components/DataDimension/Calculation/FormulaField.js +121 -0
- package/build/cjs/components/DataDimension/Calculation/FormulaItem.js +232 -0
- package/build/cjs/components/DataDimension/Calculation/MathOperatorSelector.js +57 -0
- package/build/cjs/components/DataDimension/Calculation/Operator.js +81 -0
- package/build/cjs/components/DataDimension/Calculation/styles/CalculationModal.style.js +13 -0
- package/build/cjs/components/DataDimension/Calculation/styles/DataElementOption.style.js +13 -0
- package/build/cjs/components/DataDimension/Calculation/styles/DataElementSelector.style.js +13 -0
- package/build/cjs/components/DataDimension/Calculation/styles/DraggingItem.style.js +13 -0
- package/build/cjs/components/DataDimension/Calculation/styles/DropZone.style.js +13 -0
- package/build/cjs/components/DataDimension/Calculation/styles/FormulaField.style.js +13 -0
- package/build/cjs/components/DataDimension/Calculation/styles/FormulaItem.style.js +13 -0
- package/build/cjs/components/DataDimension/Calculation/styles/MathOperatorSelector.style.js +13 -0
- package/build/cjs/components/DataDimension/Calculation/styles/Operator.style.js +13 -0
- package/build/cjs/components/DataDimension/DataDimension.js +22 -6
- package/build/cjs/components/DataDimension/DataTypeSelector.js +5 -3
- package/build/cjs/components/DataDimension/ItemSelector.js +111 -73
- package/build/cjs/components/TransferOption.js +13 -4
- package/build/cjs/components/styles/DimensionSelector.style.js +2 -2
- package/build/cjs/components/styles/TransferOption.style.js +2 -2
- package/build/cjs/index.js +6 -0
- package/build/cjs/locales/en/translations.json +32 -7
- package/build/cjs/modules/__tests__/expressions.spec.js +139 -0
- package/build/cjs/modules/__tests__/hash.spec.js +92 -0
- package/build/cjs/modules/__tests__/parseExpression.spec.js +46 -0
- package/build/cjs/modules/dataTypes.js +8 -1
- package/build/cjs/modules/dimensionListItem.js +82 -0
- package/build/cjs/modules/expressions.js +164 -0
- package/build/cjs/modules/hash.js +28 -0
- package/build/cjs/visualizations/config/generators/dhis/singleValue.js +2 -2
- package/build/es/__demo__/CalculationModal.stories.js +440 -0
- package/build/es/api/analytics/AnalyticsRequest.js +11 -1
- package/build/es/api/dimensions.js +1 -1
- package/build/es/api/expression.js +57 -0
- package/build/es/assets/DimensionItemIcons/CalculationIcon.js +13 -0
- package/build/es/assets/FormulaIcon.js +30 -0
- package/build/es/components/DataDimension/Calculation/CalculationModal.js +418 -0
- package/build/es/components/DataDimension/Calculation/DataElementOption.js +60 -0
- package/build/es/components/DataDimension/Calculation/DataElementSelector.js +280 -0
- package/build/es/components/DataDimension/Calculation/DndContext.js +194 -0
- package/build/es/components/DataDimension/Calculation/DragHandleIcon.js +11 -0
- package/build/es/components/DataDimension/Calculation/DraggingItem.js +40 -0
- package/build/es/components/DataDimension/Calculation/DropZone.js +43 -0
- package/build/es/components/DataDimension/Calculation/FormulaField.js +98 -0
- package/build/es/components/DataDimension/Calculation/FormulaItem.js +207 -0
- package/build/es/components/DataDimension/Calculation/MathOperatorSelector.js +41 -0
- package/build/es/components/DataDimension/Calculation/Operator.js +64 -0
- package/build/es/components/DataDimension/Calculation/styles/CalculationModal.style.js +4 -0
- package/build/es/components/DataDimension/Calculation/styles/DataElementOption.style.js +4 -0
- package/build/es/components/DataDimension/Calculation/styles/DataElementSelector.style.js +4 -0
- package/build/es/components/DataDimension/Calculation/styles/DraggingItem.style.js +4 -0
- package/build/es/components/DataDimension/Calculation/styles/DropZone.style.js +4 -0
- package/build/es/components/DataDimension/Calculation/styles/FormulaField.style.js +4 -0
- package/build/es/components/DataDimension/Calculation/styles/FormulaItem.style.js +4 -0
- package/build/es/components/DataDimension/Calculation/styles/MathOperatorSelector.style.js +4 -0
- package/build/es/components/DataDimension/Calculation/styles/Operator.style.js +4 -0
- package/build/es/components/DataDimension/DataDimension.js +21 -6
- package/build/es/components/DataDimension/DataTypeSelector.js +6 -4
- package/build/es/components/DataDimension/ItemSelector.js +111 -73
- package/build/es/components/TransferOption.js +14 -5
- package/build/es/components/styles/DimensionSelector.style.js +2 -2
- package/build/es/components/styles/TransferOption.style.js +2 -2
- package/build/es/index.js +1 -1
- package/build/es/locales/en/translations.json +32 -7
- package/build/es/modules/__tests__/expressions.spec.js +136 -0
- package/build/es/modules/__tests__/hash.spec.js +88 -0
- package/build/es/modules/__tests__/parseExpression.spec.js +43 -0
- package/build/es/modules/dataTypes.js +6 -0
- package/build/es/modules/dimensionListItem.js +61 -0
- package/build/es/modules/expressions.js +131 -0
- package/build/es/modules/hash.js +12 -0
- package/build/es/visualizations/config/generators/dhis/singleValue.js +2 -2
- package/package.json +6 -1
|
@@ -3,19 +3,19 @@ import _JSXStyle from "styled-jsx/style";
|
|
|
3
3
|
function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
|
|
4
4
|
|
|
5
5
|
import { useDataEngine } from '@dhis2/app-runtime';
|
|
6
|
-
import { Transfer, InputField, IconInfo16,
|
|
6
|
+
import { Transfer, InputField, IconInfo16, Button, IconAdd24 } from '@dhis2/ui';
|
|
7
7
|
import PropTypes from 'prop-types';
|
|
8
8
|
import React, { useState } from 'react';
|
|
9
9
|
import { apiFetchOptions } from '../../api/dimensions.js';
|
|
10
|
-
import DataElementIcon from '../../assets/DimensionItemIcons/DataElementIcon.js';
|
|
11
|
-
import GenericIcon from '../../assets/DimensionItemIcons/GenericIcon.js';
|
|
12
10
|
import i18n from '../../locales/index.js';
|
|
13
11
|
import { DATA_SETS_CONSTANTS, REPORTING_RATE } from '../../modules/dataSets.js';
|
|
14
|
-
import { dataTypeMap as dataTypes, DIMENSION_TYPE_ALL, DIMENSION_TYPE_DATA_ELEMENT,
|
|
12
|
+
import { dataTypeMap as dataTypes, DIMENSION_TYPE_ALL, DIMENSION_TYPE_DATA_ELEMENT, DIMENSION_TYPE_DATA_SET, DIMENSION_TYPE_EVENT_DATA_ITEM, DIMENSION_TYPE_PROGRAM_INDICATOR, DIMENSION_TYPE_INDICATOR, TOTALS, DIMENSION_TYPE_EXPRESSION_DIMENSION_ITEM } from '../../modules/dataTypes.js';
|
|
13
|
+
import { getIcon, getTooltipText } from '../../modules/dimensionListItem.js';
|
|
15
14
|
import { TRANSFER_HEIGHT, TRANSFER_OPTIONS_WIDTH, TRANSFER_SELECTED_WIDTH } from '../../modules/dimensionSelectorHelper.js';
|
|
16
15
|
import { useDebounce, useDidUpdateEffect } from '../../modules/utils.js';
|
|
17
16
|
import styles from '../styles/DimensionSelector.style.js';
|
|
18
17
|
import { TransferOption } from '../TransferOption.js';
|
|
18
|
+
import CalculationModal from './Calculation/CalculationModal.js';
|
|
19
19
|
import DataTypeSelector from './DataTypeSelector.js';
|
|
20
20
|
import GroupSelector from './GroupSelector.js';
|
|
21
21
|
|
|
@@ -30,7 +30,8 @@ const LeftHeader = _ref => {
|
|
|
30
30
|
subGroup,
|
|
31
31
|
setSubGroup,
|
|
32
32
|
displayNameProp,
|
|
33
|
-
dataTest
|
|
33
|
+
dataTest,
|
|
34
|
+
supportsEDI
|
|
34
35
|
} = _ref;
|
|
35
36
|
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
|
|
36
37
|
className: "jsx-".concat(styles.__hash) + " " + "leftHeader"
|
|
@@ -50,8 +51,9 @@ const LeftHeader = _ref => {
|
|
|
50
51
|
}), /*#__PURE__*/React.createElement(DataTypeSelector, {
|
|
51
52
|
currentDataType: dataType,
|
|
52
53
|
onChange: setDataType,
|
|
53
|
-
dataTest: "".concat(dataTest, "-data-types-select-field")
|
|
54
|
-
|
|
54
|
+
dataTest: "".concat(dataTest, "-data-types-select-field"),
|
|
55
|
+
includeCalculations: supportsEDI
|
|
56
|
+
}), dataTypes[dataType] && dataType !== DIMENSION_TYPE_EXPRESSION_DIMENSION_ITEM && /*#__PURE__*/React.createElement(GroupSelector, {
|
|
55
57
|
dataType: dataType,
|
|
56
58
|
displayNameProp: displayNameProp,
|
|
57
59
|
currentGroup: group,
|
|
@@ -74,7 +76,8 @@ LeftHeader.propTypes = {
|
|
|
74
76
|
setGroup: PropTypes.func,
|
|
75
77
|
setSearchTerm: PropTypes.func,
|
|
76
78
|
setSubGroup: PropTypes.func,
|
|
77
|
-
subGroup: PropTypes.string
|
|
79
|
+
subGroup: PropTypes.string,
|
|
80
|
+
supportsEDI: PropTypes.bool
|
|
78
81
|
};
|
|
79
82
|
|
|
80
83
|
const EmptySelection = () => /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("p", {
|
|
@@ -210,7 +213,9 @@ const ItemSelector = _ref5 => {
|
|
|
210
213
|
rightFooter,
|
|
211
214
|
displayNameProp,
|
|
212
215
|
infoBoxMessage,
|
|
213
|
-
dataTest
|
|
216
|
+
dataTest,
|
|
217
|
+
supportsEDI,
|
|
218
|
+
onEDISave
|
|
214
219
|
} = _ref5;
|
|
215
220
|
const [state, setState] = useState({
|
|
216
221
|
searchTerm: '',
|
|
@@ -221,6 +226,7 @@ const ItemSelector = _ref5 => {
|
|
|
221
226
|
loading: true,
|
|
222
227
|
nextPage: 1
|
|
223
228
|
});
|
|
229
|
+
const [currentCalculation, setCurrentCalculation] = useState();
|
|
224
230
|
const dataEngine = useDataEngine();
|
|
225
231
|
|
|
226
232
|
const setSearchTerm = searchTerm => setState(state => ({ ...state,
|
|
@@ -231,7 +237,7 @@ const ItemSelector = _ref5 => {
|
|
|
231
237
|
filter
|
|
232
238
|
}));
|
|
233
239
|
|
|
234
|
-
const debouncedSearchTerm = useDebounce(state.searchTerm,
|
|
240
|
+
const debouncedSearchTerm = useDebounce(state.searchTerm, 500);
|
|
235
241
|
|
|
236
242
|
const fetchItems = async page => {
|
|
237
243
|
var _result$dimensionItem;
|
|
@@ -255,7 +261,8 @@ const ItemSelector = _ref5 => {
|
|
|
255
261
|
label: "".concat(item.name, " - ").concat(metric.getName()),
|
|
256
262
|
value: "".concat(item.id, ".").concat(metric.id),
|
|
257
263
|
disabled: item.disabled,
|
|
258
|
-
type: item.dimensionItemType
|
|
264
|
+
type: item.dimensionItemType,
|
|
265
|
+
expression: item.expression
|
|
259
266
|
});
|
|
260
267
|
} else {
|
|
261
268
|
DATA_SETS_CONSTANTS.forEach(metric => {
|
|
@@ -263,7 +270,8 @@ const ItemSelector = _ref5 => {
|
|
|
263
270
|
label: "".concat(item.name, " - ").concat(metric.getName()),
|
|
264
271
|
value: "".concat(item.id, ".").concat(metric.id),
|
|
265
272
|
disabled: item.disabled,
|
|
266
|
-
type: item.dimensionItemType
|
|
273
|
+
type: item.dimensionItemType,
|
|
274
|
+
expression: item.expression
|
|
267
275
|
});
|
|
268
276
|
});
|
|
269
277
|
}
|
|
@@ -272,7 +280,8 @@ const ItemSelector = _ref5 => {
|
|
|
272
280
|
label: item.name,
|
|
273
281
|
value: item.id,
|
|
274
282
|
disabled: item.disabled,
|
|
275
|
-
type: item.dimensionItemType
|
|
283
|
+
type: item.dimensionItemType,
|
|
284
|
+
expression: item.expression
|
|
276
285
|
});
|
|
277
286
|
}
|
|
278
287
|
});
|
|
@@ -281,11 +290,11 @@ const ItemSelector = _ref5 => {
|
|
|
281
290
|
options: page > 1 ? [...state.options, ...newOptions] : newOptions,
|
|
282
291
|
nextPage: result.nextPage
|
|
283
292
|
}));
|
|
284
|
-
/* The following handles a very specific edge-case where the user can select all items from a
|
|
285
|
-
page and then reopen the modal. Usually Transfer triggers the onEndReached when the end of
|
|
286
|
-
the page is reached (scrolling down) or if too few items are on the left side (e.g. selecting
|
|
287
|
-
49 items from page 1, leaving only 1 item on the left side). However, due to the way Transfer
|
|
288
|
-
works, if 0 items are available, more items are fetched, but all items are already selected
|
|
293
|
+
/* The following handles a very specific edge-case where the user can select all items from a
|
|
294
|
+
page and then reopen the modal. Usually Transfer triggers the onEndReached when the end of
|
|
295
|
+
the page is reached (scrolling down) or if too few items are on the left side (e.g. selecting
|
|
296
|
+
49 items from page 1, leaving only 1 item on the left side). However, due to the way Transfer
|
|
297
|
+
works, if 0 items are available, more items are fetched, but all items are already selected
|
|
289
298
|
(leaving 0 items on the left side still), the onReachedEnd won't trigger. Hence the code below:
|
|
290
299
|
IF there is a next page AND some options were just fetched AND you have the same or more
|
|
291
300
|
selected items than fetched items AND all fetched items are already selected -> fetch more!
|
|
@@ -310,7 +319,10 @@ const ItemSelector = _ref5 => {
|
|
|
310
319
|
return {
|
|
311
320
|
value,
|
|
312
321
|
label: matchingItem.label,
|
|
313
|
-
type: matchingItem.type
|
|
322
|
+
type: matchingItem.type,
|
|
323
|
+
...(matchingItem.expression ? {
|
|
324
|
+
expression: matchingItem.expression
|
|
325
|
+
} : {})
|
|
314
326
|
};
|
|
315
327
|
}));
|
|
316
328
|
};
|
|
@@ -332,55 +344,52 @@ const ItemSelector = _ref5 => {
|
|
|
332
344
|
return (_find = [...state.options, ...selectedItems].find(item => item.value === value)) === null || _find === void 0 ? void 0 : _find.type;
|
|
333
345
|
};
|
|
334
346
|
|
|
335
|
-
const
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
347
|
+
const onSaveCalculation = async _ref6 => {
|
|
348
|
+
let {
|
|
349
|
+
id,
|
|
350
|
+
name,
|
|
351
|
+
expression,
|
|
352
|
+
isNew
|
|
353
|
+
} = _ref6;
|
|
354
|
+
onEDISave({
|
|
355
|
+
id,
|
|
356
|
+
name,
|
|
357
|
+
expression,
|
|
358
|
+
type: DIMENSION_TYPE_EXPRESSION_DIMENSION_ITEM
|
|
359
|
+
}); // close the modal
|
|
360
|
+
|
|
361
|
+
setCurrentCalculation(); // reload the list of options
|
|
341
362
|
|
|
342
|
-
|
|
343
|
-
return dataTypes[DIMENSION_TYPE_DATA_SET].getItemName();
|
|
344
|
-
|
|
345
|
-
case DIMENSION_TYPE_PROGRAM_DATA_ELEMENT:
|
|
346
|
-
case DIMENSION_TYPE_PROGRAM_ATTRIBUTE:
|
|
347
|
-
return dataTypes[DIMENSION_TYPE_EVENT_DATA_ITEM].getItemName();
|
|
363
|
+
fetchItems(1);
|
|
348
364
|
|
|
349
|
-
|
|
350
|
-
|
|
365
|
+
if (isNew) {
|
|
366
|
+
// select the new calculation
|
|
367
|
+
onSelect([...selectedItems, {
|
|
368
|
+
value: id,
|
|
369
|
+
label: name,
|
|
370
|
+
expression,
|
|
371
|
+
type: DIMENSION_TYPE_EXPRESSION_DIMENSION_ITEM
|
|
372
|
+
}]);
|
|
351
373
|
}
|
|
352
374
|
};
|
|
353
375
|
|
|
354
|
-
const
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
376
|
+
const onDeleteCalculation = _ref7 => {
|
|
377
|
+
let {
|
|
378
|
+
id
|
|
379
|
+
} = _ref7;
|
|
380
|
+
// close the modal
|
|
381
|
+
setCurrentCalculation(); // reload the list of options
|
|
358
382
|
|
|
359
|
-
|
|
360
|
-
case DIMENSION_TYPE_DATA_ELEMENT:
|
|
361
|
-
return DataElementIcon;
|
|
383
|
+
fetchItems(1); // unselect the deleted calculation
|
|
362
384
|
|
|
363
|
-
|
|
364
|
-
return /*#__PURE__*/React.createElement(IconDimensionDataSet16, null);
|
|
365
|
-
|
|
366
|
-
case DIMENSION_TYPE_EVENT_DATA_ITEM:
|
|
367
|
-
case DIMENSION_TYPE_PROGRAM_DATA_ELEMENT:
|
|
368
|
-
case DIMENSION_TYPE_PROGRAM_ATTRIBUTE:
|
|
369
|
-
return /*#__PURE__*/React.createElement(IconDimensionEventDataItem16, null);
|
|
370
|
-
|
|
371
|
-
case DIMENSION_TYPE_PROGRAM_INDICATOR:
|
|
372
|
-
return /*#__PURE__*/React.createElement(IconDimensionProgramIndicator16, null);
|
|
373
|
-
|
|
374
|
-
default:
|
|
375
|
-
return GenericIcon;
|
|
376
|
-
}
|
|
385
|
+
onSelect([...selectedItems.filter(item => item.value !== id)]);
|
|
377
386
|
};
|
|
378
387
|
|
|
379
|
-
return /*#__PURE__*/React.createElement(Transfer, {
|
|
380
|
-
onChange:
|
|
388
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Transfer, {
|
|
389
|
+
onChange: _ref8 => {
|
|
381
390
|
let {
|
|
382
391
|
selected
|
|
383
|
-
} =
|
|
392
|
+
} = _ref8;
|
|
384
393
|
return onChange(selected);
|
|
385
394
|
},
|
|
386
395
|
selected: selectedItems.map(item => item.value),
|
|
@@ -420,8 +429,16 @@ const ItemSelector = _ref5 => {
|
|
|
420
429
|
searchTerm: state.searchTerm,
|
|
421
430
|
setSearchTerm: setSearchTerm,
|
|
422
431
|
displayNameProp: displayNameProp,
|
|
423
|
-
dataTest: "".concat(dataTest, "-left-header")
|
|
432
|
+
dataTest: "".concat(dataTest, "-left-header"),
|
|
433
|
+
supportsEDI: supportsEDI
|
|
424
434
|
}),
|
|
435
|
+
leftFooter: supportsEDI ? /*#__PURE__*/React.createElement("div", {
|
|
436
|
+
className: "jsx-".concat(styles.__hash) + " " + "calculation-button"
|
|
437
|
+
}, /*#__PURE__*/React.createElement(Button, {
|
|
438
|
+
icon: /*#__PURE__*/React.createElement(IconAdd24, null),
|
|
439
|
+
onClick: () => setCurrentCalculation({}),
|
|
440
|
+
small: true
|
|
441
|
+
}, i18n.t('Calculation'))) : undefined,
|
|
425
442
|
enableOrderChange: true,
|
|
426
443
|
height: TRANSFER_HEIGHT,
|
|
427
444
|
optionsWidth: TRANSFER_OPTIONS_WIDTH,
|
|
@@ -431,20 +448,38 @@ const ItemSelector = _ref5 => {
|
|
|
431
448
|
infoText: infoBoxMessage
|
|
432
449
|
}),
|
|
433
450
|
rightFooter: rightFooter,
|
|
434
|
-
renderOption: props =>
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
451
|
+
renderOption: props => {
|
|
452
|
+
var _props$access;
|
|
453
|
+
|
|
454
|
+
return /*#__PURE__*/React.createElement(TransferOption
|
|
455
|
+
/* eslint-disable react/prop-types */
|
|
456
|
+
, _extends({}, props, {
|
|
457
|
+
active: isActive(props.value),
|
|
458
|
+
icon: getIcon(getItemType(props.value)),
|
|
459
|
+
tooltipText: getTooltipText({
|
|
460
|
+
type: getItemType(props.value),
|
|
461
|
+
expression: props.expression
|
|
462
|
+
}),
|
|
463
|
+
dataTest: "".concat(dataTest, "-transfer-option"),
|
|
464
|
+
onEditClick: getItemType(props.value) === DIMENSION_TYPE_EXPRESSION_DIMENSION_ITEM && !(((_props$access = props.access) === null || _props$access === void 0 ? void 0 : _props$access.write) === false) && supportsEDI ? () => setCurrentCalculation({
|
|
465
|
+
id: props.value,
|
|
466
|
+
name: props.label,
|
|
467
|
+
expression: props.expression
|
|
468
|
+
}) : undefined
|
|
469
|
+
/* eslint-enable react/prop-types */
|
|
470
|
+
|
|
471
|
+
}));
|
|
472
|
+
},
|
|
446
473
|
dataTest: "".concat(dataTest, "-transfer")
|
|
447
|
-
})
|
|
474
|
+
}), currentCalculation && supportsEDI && /*#__PURE__*/React.createElement(CalculationModal, {
|
|
475
|
+
calculation: currentCalculation,
|
|
476
|
+
onSave: onSaveCalculation,
|
|
477
|
+
onClose: () => setCurrentCalculation(),
|
|
478
|
+
onDelete: onDeleteCalculation,
|
|
479
|
+
displayNameProp: displayNameProp
|
|
480
|
+
}), /*#__PURE__*/React.createElement(_JSXStyle, {
|
|
481
|
+
id: styles.__hash
|
|
482
|
+
}, styles));
|
|
448
483
|
};
|
|
449
484
|
|
|
450
485
|
ItemSelector.propTypes = {
|
|
@@ -458,8 +493,11 @@ ItemSelector.propTypes = {
|
|
|
458
493
|
label: PropTypes.string.isRequired,
|
|
459
494
|
value: PropTypes.string.isRequired,
|
|
460
495
|
isActive: PropTypes.bool,
|
|
461
|
-
type: PropTypes.string
|
|
462
|
-
|
|
496
|
+
type: PropTypes.string,
|
|
497
|
+
expression: PropTypes.string
|
|
498
|
+
})),
|
|
499
|
+
supportsEDI: PropTypes.bool,
|
|
500
|
+
onEDISave: PropTypes.func
|
|
463
501
|
};
|
|
464
502
|
ItemSelector.defaultProps = {
|
|
465
503
|
selectedItems: []
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import _JSXStyle from "styled-jsx/style";
|
|
2
|
-
import { Tooltip } from '@dhis2/ui';
|
|
2
|
+
import { Tooltip, IconEdit16 } from '@dhis2/ui';
|
|
3
3
|
import cx from 'classnames';
|
|
4
4
|
import PropTypes from 'prop-types';
|
|
5
5
|
import React from 'react';
|
|
@@ -16,10 +16,12 @@ export const TransferOption = _ref => {
|
|
|
16
16
|
icon,
|
|
17
17
|
active,
|
|
18
18
|
tooltipText,
|
|
19
|
-
dataTest
|
|
19
|
+
dataTest,
|
|
20
|
+
onEditClick
|
|
20
21
|
} = _ref;
|
|
21
22
|
|
|
22
23
|
const renderContent = () => /*#__PURE__*/React.createElement("div", {
|
|
24
|
+
"data-test": "".concat(dataTest, "-content"),
|
|
23
25
|
onClick: event => {
|
|
24
26
|
if (disabled) {
|
|
25
27
|
return;
|
|
@@ -40,7 +42,6 @@ export const TransferOption = _ref => {
|
|
|
40
42
|
value
|
|
41
43
|
}, event);
|
|
42
44
|
},
|
|
43
|
-
"data-test": "".concat(dataTest, "-content"),
|
|
44
45
|
className: "jsx-".concat(styles.__hash) + " " + (cx('chip', {
|
|
45
46
|
highlighted,
|
|
46
47
|
disabled,
|
|
@@ -51,7 +52,14 @@ export const TransferOption = _ref => {
|
|
|
51
52
|
className: "jsx-".concat(styles.__hash) + " " + "icon"
|
|
52
53
|
}, icon), /*#__PURE__*/React.createElement("span", {
|
|
53
54
|
className: "jsx-".concat(styles.__hash) + " " + "label"
|
|
54
|
-
}, label), /*#__PURE__*/React.createElement(
|
|
55
|
+
}, label), onEditClick && /*#__PURE__*/React.createElement("span", {
|
|
56
|
+
onClick: e => {
|
|
57
|
+
e.stopPropagation();
|
|
58
|
+
onEditClick();
|
|
59
|
+
},
|
|
60
|
+
"data-test": "".concat(dataTest, "-edit-button"),
|
|
61
|
+
className: "jsx-".concat(styles.__hash) + " " + "edit"
|
|
62
|
+
}, /*#__PURE__*/React.createElement(IconEdit16, null)), /*#__PURE__*/React.createElement(_JSXStyle, {
|
|
55
63
|
id: styles.__hash
|
|
56
64
|
}, styles));
|
|
57
65
|
|
|
@@ -78,5 +86,6 @@ TransferOption.propTypes = {
|
|
|
78
86
|
selected: PropTypes.bool,
|
|
79
87
|
tooltipText: PropTypes.string,
|
|
80
88
|
onClick: PropTypes.func,
|
|
81
|
-
onDoubleClick: PropTypes.func
|
|
89
|
+
onDoubleClick: PropTypes.func,
|
|
90
|
+
onEditClick: PropTypes.func
|
|
82
91
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { spacers, colors } from '@dhis2/ui';
|
|
2
|
-
const _defaultExport = [".filterContainer.jsx-
|
|
3
|
-
_defaultExport.__hash = "
|
|
2
|
+
const _defaultExport = [".filterContainer.jsx-336728173{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;margin-bottom:".concat(spacers.dp12, ";margin-top:").concat(spacers.dp8, ";}"), ".emptyList.jsx-336728173{text-align:center;font-size:14px;line-height:16px;margin:".concat(spacers.dp24, " 0 0;color:").concat(colors.grey700, ";}"), ".rightHeader.jsx-336728173{font-size:14px;font-weight:400;}", ".leftHeader.jsx-336728173{padding:".concat(spacers.dp12, " ").concat(spacers.dp4, ";}"), ".info-container.jsx-336728173{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;margin-bottom:".concat(spacers.dp8, ";padding:").concat(spacers.dp8, ";background-color:").concat(colors.grey200, ";border-radius:3px;}"), ".info-text.jsx-336728173{padding-left:".concat(spacers.dp8, ";color:").concat(colors.grey900, ";font-size:12px;line-height:16px;}"), ".calculation-button.jsx-336728173{margin:".concat(spacers.dp8, " 0;}")];
|
|
3
|
+
_defaultExport.__hash = "336728173";
|
|
4
4
|
export default _defaultExport;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { colors, spacers, theme } from '@dhis2/ui';
|
|
2
|
-
const _defaultExport = [".wrapper.jsx-
|
|
3
|
-
_defaultExport.__hash = "
|
|
2
|
+
const _defaultExport = [".wrapper.jsx-1302852599:last-child{margin-bottom:".concat(spacers.dp4, ";}"), ".chip.jsx-1302852599{display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;background:".concat(colors.grey200, ";font-size:14px;line-height:16px;padding:2px ").concat(spacers.dp8, " 2px ").concat(spacers.dp4, ";margin:").concat(spacers.dp4, " ").concat(spacers.dp8, " 0 ").concat(spacers.dp8, ";border-radius:3px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;}"), ".chip.jsx-1302852599:hover{background:".concat(colors.grey300, ";}"), ".selected.jsx-1302852599{background:".concat(theme.secondary100, ";color:").concat(theme.secondary900, ";}"), ".selected.jsx-1302852599 .icon path{fill:".concat(theme.secondary700, ";}"), ".selected.jsx-1302852599:hover{background:#c9edeb;}", ".highlighted.jsx-1302852599,.highlighted.jsx-1302852599:hover{background:".concat(theme.secondary800, ";color:").concat(colors.white, ";}"), ".highlighted.jsx-1302852599 .icon path{fill:".concat(colors.white, ";}"), ".disabled.jsx-1302852599{opacity:0.3;cursor:not-allowed;}", ".inactive.jsx-1302852599{opacity:0.3;}", ".icon.jsx-1302852599,.label.jsx-1302852599{line-height:18px;}", ".icon.jsx-1302852599{margin-right:".concat(spacers.dp4, ";display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;vertical-align:text-bottom;padding-top:1px;}"), ".label.jsx-1302852599{font-size:14px;}", ".edit.jsx-1302852599{height:16px;margin-top:1px;margin-left:".concat(spacers.dp8, ";cursor:pointer;}"), ".edit.jsx-1302852599:hover{background-color:rgba(0,0,0,0.12);outline:1px solid rgba(0,0,0,0.12);border-radius:3px;}", ".highlighted.jsx-1302852599 .edit.jsx-1302852599:hover{background-color:rgba(255,255,255,0.12);outline:1px solid rgba(255,255,255,0.12);}"];
|
|
3
|
+
_defaultExport.__hash = "1302852599";
|
|
4
4
|
export default _defaultExport;
|
package/build/es/index.js
CHANGED
|
@@ -95,4 +95,4 @@ export { DAILY, WEEKLY, WEEKLYWED, WEEKLYTHU, WEEKLYSAT, WEEKLYSUN, WEEKS_THIS_Y
|
|
|
95
95
|
export { getRelativePeriodsOptionsById } from './components/PeriodDimension/utils/relativePeriods.js';
|
|
96
96
|
export { getFixedPeriodsOptionsById } from './components/PeriodDimension/utils/fixedPeriods.js';
|
|
97
97
|
export { default as VisualizationOptions } from './components/Options/VisualizationOptions.js';
|
|
98
|
-
export { DIMENSION_TYPE_INDICATOR, DIMENSION_TYPE_DATA_ELEMENT, DIMENSION_TYPE_DATA_SET, DIMENSION_TYPE_EVENT_DATA_ITEM, DIMENSION_TYPE_PROGRAM_INDICATOR, DIMENSION_TYPE_PROGRAM_DATA_ELEMENT, DIMENSION_TYPE_PROGRAM_ATTRIBUTE, DIMENSION_TYPE_DATA_ELEMENT_OPERAND, DIMENSION_TYPE_CATEGORY, DIMENSION_TYPE_CATEGORY_OPTION_GROUP_SET, DIMENSION_TYPE_ALL, DIMENSION_TYPE_DATA, DIMENSION_TYPE_DATA_ELEMENT_GROUP_SET, DIMENSION_TYPE_ORGANISATION_UNIT, DIMENSION_TYPE_PERIOD, DIMENSION_TYPE_ORGANISATION_UNIT_GROUP_SET } from './modules/dataTypes.js';
|
|
98
|
+
export { DIMENSION_TYPE_INDICATOR, DIMENSION_TYPE_DATA_ELEMENT, DIMENSION_TYPE_DATA_SET, DIMENSION_TYPE_EVENT_DATA_ITEM, DIMENSION_TYPE_PROGRAM_INDICATOR, DIMENSION_TYPE_PROGRAM_DATA_ELEMENT, DIMENSION_TYPE_PROGRAM_ATTRIBUTE, DIMENSION_TYPE_DATA_ELEMENT_OPERAND, DIMENSION_TYPE_CATEGORY, DIMENSION_TYPE_CATEGORY_OPTION_GROUP_SET, DIMENSION_TYPE_ALL, DIMENSION_TYPE_DATA, DIMENSION_TYPE_DATA_ELEMENT_GROUP_SET, DIMENSION_TYPE_ORGANISATION_UNIT, DIMENSION_TYPE_PERIOD, DIMENSION_TYPE_ORGANISATION_UNIT_GROUP_SET, DIMENSION_TYPE_EXPRESSION_DIMENSION_ITEM } from './modules/dataTypes.js';
|
|
@@ -21,27 +21,45 @@
|
|
|
21
21
|
"About this visualization": "About this visualization",
|
|
22
22
|
"This app could not retrieve required data.": "This app could not retrieve required data.",
|
|
23
23
|
"Network error": "Network error",
|
|
24
|
-
"Data
|
|
25
|
-
"
|
|
24
|
+
"Data / Edit calculation": "Data / Edit calculation",
|
|
25
|
+
"Data / New calculation": "Data / New calculation",
|
|
26
|
+
"Remove item": "Remove item",
|
|
27
|
+
"Check formula": "Check formula",
|
|
28
|
+
"Calculation name": "Calculation name",
|
|
29
|
+
"Shown in table headers and chart axes/legends": "Shown in table headers and chart axes/legends",
|
|
30
|
+
"Delete calculation": "Delete calculation",
|
|
31
|
+
"Cancel": "Cancel",
|
|
32
|
+
"The calculation can only be saved with a valid formula": "The calculation can only be saved with a valid formula",
|
|
33
|
+
"Add a name to save this calculation": "Add a name to save this calculation",
|
|
34
|
+
"Save calculation": "Save calculation",
|
|
35
|
+
"Are you sure you want to delete this calculation? It may be used by other visualizations.": "Are you sure you want to delete this calculation? It may be used by other visualizations.",
|
|
36
|
+
"Yes, delete": "Yes, delete",
|
|
26
37
|
"Totals only": "Totals only",
|
|
27
38
|
"Details only": "Details only",
|
|
39
|
+
"Loading": "Loading",
|
|
40
|
+
"Data elements": "Data elements",
|
|
41
|
+
"Search by data element name": "Search by data element name",
|
|
42
|
+
"No data elements found for \"{{- searchTerm}}\"": "No data elements found for \"{{- searchTerm}}\"",
|
|
43
|
+
"No data elements found": "No data elements found",
|
|
44
|
+
"Drag items here, or double click in the list, to start building a calculation formula": "Drag items here, or double click in the list, to start building a calculation formula",
|
|
45
|
+
"Math operators": "Math operators",
|
|
46
|
+
"Data Type": "Data Type",
|
|
47
|
+
"All types": "All types",
|
|
28
48
|
"Disaggregation": "Disaggregation",
|
|
29
49
|
"No data": "No data",
|
|
30
|
-
"Loading": "Loading",
|
|
31
50
|
"Search by data item name": "Search by data item name",
|
|
32
51
|
"No items selected": "No items selected",
|
|
33
52
|
"Selected Items": "Selected Items",
|
|
34
53
|
"No indicators found": "No indicators found",
|
|
35
|
-
"No data elements found": "No data elements found",
|
|
36
54
|
"No data sets found": "No data sets found",
|
|
37
55
|
"No event data items found": "No event data items found",
|
|
38
56
|
"No program indicators found": "No program indicators found",
|
|
39
57
|
"No indicators found for \"{{- searchTerm}}\"": "No indicators found for \"{{- searchTerm}}\"",
|
|
40
|
-
"No data elements found for \"{{- searchTerm}}\"": "No data elements found for \"{{- searchTerm}}\"",
|
|
41
58
|
"No data sets found for \"{{- searchTerm}}\"": "No data sets found for \"{{- searchTerm}}\"",
|
|
42
59
|
"No event data items found for \"{{- searchTerm}}\"": "No event data items found for \"{{- searchTerm}}\"",
|
|
43
60
|
"No program indicators found for \"{{- searchTerm}}\"": "No program indicators found for \"{{- searchTerm}}\"",
|
|
44
61
|
"Nothing found for \"{{- searchTerm}}\"": "Nothing found for \"{{- searchTerm}}\"",
|
|
62
|
+
"Calculation": "Calculation",
|
|
45
63
|
"Metric type": "Metric type",
|
|
46
64
|
"All metrics": "All metrics",
|
|
47
65
|
"Move to {{axisName}}": "Move to {{axisName}}",
|
|
@@ -63,7 +81,6 @@
|
|
|
63
81
|
"Nothing found for {{- searchTerm}}": "Nothing found for {{- searchTerm}}",
|
|
64
82
|
"Delete {{fileType}}": "Delete {{fileType}}",
|
|
65
83
|
"This {{fileType}} and related interpretations will be deleted. Continue?": "This {{fileType}} and related interpretations will be deleted. Continue?",
|
|
66
|
-
"Cancel": "Cancel",
|
|
67
84
|
"Delete": "Delete",
|
|
68
85
|
"File": "File",
|
|
69
86
|
"New": "New",
|
|
@@ -278,7 +295,6 @@
|
|
|
278
295
|
"Indicator": "Indicator",
|
|
279
296
|
"No indicator groups found": "No indicator groups found",
|
|
280
297
|
"Loading indicator groups": "Loading indicator groups",
|
|
281
|
-
"Data elements": "Data elements",
|
|
282
298
|
"Data element group": "Data element group",
|
|
283
299
|
"Data element": "Data element",
|
|
284
300
|
"No data element groups found": "No data element groups found",
|
|
@@ -294,6 +310,15 @@
|
|
|
294
310
|
"Loading programs": "Loading programs",
|
|
295
311
|
"Program indicators": "Program indicators",
|
|
296
312
|
"Program indicator": "Program indicator",
|
|
313
|
+
"Calculations": "Calculations",
|
|
314
|
+
"Number": "Number",
|
|
315
|
+
"Formula is empty. Add items to the formula from the lists on the left.": "Formula is empty. Add items to the formula from the lists on the left.",
|
|
316
|
+
"Consecutive math operators": "Consecutive math operators",
|
|
317
|
+
"Consecutive data elements": "Consecutive data elements",
|
|
318
|
+
"Starts or ends with a math operator": "Starts or ends with a math operator",
|
|
319
|
+
"Empty parentheses": "Empty parentheses",
|
|
320
|
+
"Missing right parenthesis )": "Missing right parenthesis )",
|
|
321
|
+
"Missing left parenthesis (": "Missing left parenthesis (",
|
|
297
322
|
"Extra Small": "Extra Small",
|
|
298
323
|
"Small": "Small",
|
|
299
324
|
"Regular": "Regular",
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { validateExpression, parseArrayToExpression, parseExpressionToArray, EXPRESSION_TYPE_DATA, EXPRESSION_TYPE_NUMBER, EXPRESSION_TYPE_OPERATOR, INVALID_EXPRESSION, getItemIdsFromExpression } from '../expressions.js';
|
|
2
|
+
const invalidTestExpressions = [{
|
|
3
|
+
message: 'Formula is empty. Add items to the formula from the lists on the left.',
|
|
4
|
+
expressions: ['']
|
|
5
|
+
}, // {
|
|
6
|
+
// message: 'Consecutive math operators',
|
|
7
|
+
// expressions: ['5+-', '5+++', '4+9-*', '5++9'],
|
|
8
|
+
// },
|
|
9
|
+
{
|
|
10
|
+
message: 'Consecutive data elements',
|
|
11
|
+
expressions: ['#{cYeuwXTCPkU}#{Jtf34kNZhzP}']
|
|
12
|
+
}, {
|
|
13
|
+
message: 'Starts or ends with a math operator',
|
|
14
|
+
expressions: ['+', '+1', '1-2/', '*((#{cYeuwXTCPkU}*#{Jtf34kNZhzP})))']
|
|
15
|
+
}, {
|
|
16
|
+
message: 'Empty parentheses',
|
|
17
|
+
expressions: ['#{cYeuwXTCPkU}*()']
|
|
18
|
+
}, {
|
|
19
|
+
message: 'Missing left parenthesis (',
|
|
20
|
+
expressions: [')', '5)', '((#{cYeuwXTCPkU}*#{P3jJH5Tu5VC.S34ULMcHMca})))']
|
|
21
|
+
}, {
|
|
22
|
+
message: 'Missing right parenthesis )',
|
|
23
|
+
expressions: ['(', '(5', '((#{cYeuwXTCPkU}*#{Jtf34kNZhzP})']
|
|
24
|
+
}];
|
|
25
|
+
const validTestExpressions = ['5+9', '((#{cYeuwXTCPkU}*#{Jtf34kNZhzP}))#{iKGjnOOaPlE}', '#{P3jJH5Tu5VC.S34ULMcHMca}*#{Jtf34kNZhzP}', '(5)+9', '(5+9)', '10/-5'];
|
|
26
|
+
describe('validateExpression', () => {
|
|
27
|
+
invalidTestExpressions.forEach(_ref => {
|
|
28
|
+
let {
|
|
29
|
+
expressions,
|
|
30
|
+
message
|
|
31
|
+
} = _ref;
|
|
32
|
+
expressions.forEach(exp => {
|
|
33
|
+
test("Fails: ".concat(message), () => {
|
|
34
|
+
expect(validateExpression(exp)).toEqual({
|
|
35
|
+
status: INVALID_EXPRESSION,
|
|
36
|
+
message
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
validTestExpressions.forEach(exp => {
|
|
42
|
+
test("Passes validation: ".concat(exp), () => {
|
|
43
|
+
expect(validateExpression(exp)).toEqual(undefined);
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
describe('parseArrayToExpression', () => {
|
|
48
|
+
test('exp 1', () => {
|
|
49
|
+
const expressionArray = [{
|
|
50
|
+
label: 'abc123',
|
|
51
|
+
value: '#{abc123}',
|
|
52
|
+
type: EXPRESSION_TYPE_DATA
|
|
53
|
+
}, {
|
|
54
|
+
label: '+',
|
|
55
|
+
value: '+',
|
|
56
|
+
type: EXPRESSION_TYPE_OPERATOR
|
|
57
|
+
}, {
|
|
58
|
+
label: 'def456.xyz999',
|
|
59
|
+
value: '#{def456.xyz999}',
|
|
60
|
+
type: EXPRESSION_TYPE_DATA
|
|
61
|
+
}, {
|
|
62
|
+
label: '/',
|
|
63
|
+
value: '/',
|
|
64
|
+
type: EXPRESSION_TYPE_OPERATOR
|
|
65
|
+
}, {
|
|
66
|
+
label: '10',
|
|
67
|
+
value: '10',
|
|
68
|
+
type: EXPRESSION_TYPE_NUMBER
|
|
69
|
+
}];
|
|
70
|
+
const expected = '#{abc123}+#{def456.xyz999}/10';
|
|
71
|
+
expect(parseArrayToExpression(expressionArray)).toEqual(expected);
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
describe('parseExpressionToArray', () => {
|
|
75
|
+
test('exp 1', () => {
|
|
76
|
+
const expression = '#{abc123}/10*99';
|
|
77
|
+
const expected = [{
|
|
78
|
+
label: 'abc123',
|
|
79
|
+
value: '#{abc123}',
|
|
80
|
+
type: EXPRESSION_TYPE_DATA
|
|
81
|
+
}, {
|
|
82
|
+
label: '/',
|
|
83
|
+
value: '/',
|
|
84
|
+
type: EXPRESSION_TYPE_OPERATOR
|
|
85
|
+
}, {
|
|
86
|
+
label: '10',
|
|
87
|
+
value: '10',
|
|
88
|
+
type: EXPRESSION_TYPE_NUMBER
|
|
89
|
+
}, {
|
|
90
|
+
label: '×',
|
|
91
|
+
value: '*',
|
|
92
|
+
type: EXPRESSION_TYPE_OPERATOR
|
|
93
|
+
}, {
|
|
94
|
+
label: '99',
|
|
95
|
+
value: '99',
|
|
96
|
+
type: EXPRESSION_TYPE_NUMBER
|
|
97
|
+
}];
|
|
98
|
+
expect(parseExpressionToArray(expression)).toEqual(expected);
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
describe('getItemIdsFromExpression', () => {
|
|
102
|
+
test('exp 1', () => {
|
|
103
|
+
const expression = '#{abc123}/10*99';
|
|
104
|
+
const expected = ['abc123'];
|
|
105
|
+
expect(getItemIdsFromExpression(expression)).toEqual(expected);
|
|
106
|
+
});
|
|
107
|
+
test('exp 2', () => {
|
|
108
|
+
const expression = '#{abc123}/10*#{def456}';
|
|
109
|
+
const expected = ['abc123', 'def456'];
|
|
110
|
+
expect(getItemIdsFromExpression(expression)).toEqual(expected);
|
|
111
|
+
});
|
|
112
|
+
test('exp 3', () => {
|
|
113
|
+
const expression = '#{abc123}/10*#{def456.xyz999}';
|
|
114
|
+
const expected = ['abc123', 'def456.xyz999'];
|
|
115
|
+
expect(getItemIdsFromExpression(expression)).toEqual(expected);
|
|
116
|
+
});
|
|
117
|
+
test('exp 4', () => {
|
|
118
|
+
const expression = '#{abc123}/10*#{def456.xyz999}+#{ghi789}';
|
|
119
|
+
const expected = ['abc123', 'def456.xyz999', 'ghi789'];
|
|
120
|
+
expect(getItemIdsFromExpression(expression)).toEqual(expected);
|
|
121
|
+
});
|
|
122
|
+
test('exp 5', () => {
|
|
123
|
+
const expression = '#{abc123}/10*#{def456.xyz999}+#{ghi789}+#{jkl000}';
|
|
124
|
+
const expected = ['abc123', 'def456.xyz999', 'ghi789', 'jkl000'];
|
|
125
|
+
expect(getItemIdsFromExpression(expression)).toEqual(expected);
|
|
126
|
+
});
|
|
127
|
+
test('exp 6', () => {
|
|
128
|
+
const expression = '5/10';
|
|
129
|
+
const expected = [];
|
|
130
|
+
expect(getItemIdsFromExpression(expression)).toEqual(expected);
|
|
131
|
+
});
|
|
132
|
+
test('exp 6', () => {
|
|
133
|
+
const expected = [];
|
|
134
|
+
expect(getItemIdsFromExpression()).toEqual(expected);
|
|
135
|
+
});
|
|
136
|
+
});
|