@dhis2/analytics 26.12.2 → 26.13.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 (117) hide show
  1. package/build/cjs/__demo__/DimensionsPanel.stories.js +29 -4
  2. package/build/cjs/__demo__/FileMenu.stories.js +1 -9
  3. package/build/cjs/__demo__/data/avgTotalAggregationType.visualization.json +256 -1
  4. package/build/cjs/__demo__/data/deep.visualization.json +613 -310
  5. package/build/cjs/__demo__/data/deepWithFilters.visualization.json +0 -3
  6. package/build/cjs/__demo__/data/degs.visualization.json +2 -7
  7. package/build/cjs/__demo__/data/diseaseWeeks.visualization.json +317 -153
  8. package/build/cjs/__demo__/data/emptyColumns.visualization.json +2 -7
  9. package/build/cjs/__demo__/data/emptyRows.visualization.json +292 -297
  10. package/build/cjs/__demo__/data/hierarchy.visualization.json +197 -1
  11. package/build/cjs/__demo__/data/lastFiveYears.visualization.json +2 -7
  12. package/build/cjs/__demo__/data/narrative.visualization.json +2 -7
  13. package/build/cjs/__demo__/data/simple.visualization.json +115 -105
  14. package/build/cjs/__demo__/data/target-with-legend.visualization.json +370 -115
  15. package/build/cjs/__demo__/data/under-above-100.legendSet.json +87 -103
  16. package/build/cjs/__demo__/data/weeklyColumns.visualization.json +2 -7
  17. package/build/cjs/__fixtures__/json/chartAllFields.json +8 -33
  18. package/build/cjs/api/dimensions.js +11 -1
  19. package/build/cjs/api/expression.js +19 -9
  20. package/build/cjs/assets/DimensionItemIcons/CalculationIcon.js +1 -1
  21. package/build/cjs/assets/DimensionItemIcons/DataElementIcon.js +1 -1
  22. package/build/cjs/assets/DimensionItemIcons/GenericIcon.js +1 -1
  23. package/build/cjs/assets/DimensionItemIcons/PeriodIcon.js +1 -1
  24. package/build/cjs/components/DataDimension/DataDimension.js +68 -10
  25. package/build/cjs/components/DataDimension/Info/CalculationInfo.js +3 -3
  26. package/build/cjs/components/DataDimension/Info/DataElementInfo.js +4 -4
  27. package/build/cjs/components/DataDimension/Info/DataElementOperandInfo.js +5 -5
  28. package/build/cjs/components/DataDimension/Info/DataSetInfo.js +3 -3
  29. package/build/cjs/components/DataDimension/Info/EventDataItemInfo.js +6 -6
  30. package/build/cjs/components/DataDimension/Info/IndicatorInfo.js +3 -3
  31. package/build/cjs/components/DataDimension/Info/InfoPopover.js +7 -3
  32. package/build/cjs/components/DataDimension/Info/InfoTable.js +1 -1
  33. package/build/cjs/components/DataDimension/Info/OptionInfo.js +70 -0
  34. package/build/cjs/components/DataDimension/Info/ProgramIndicatorInfo.js +9 -6
  35. package/build/cjs/components/DataDimension/ItemOptionsSelector/ItemOptionsSelector.js +257 -0
  36. package/build/cjs/components/DataDimension/ItemOptionsSelector/styles/ItemOptionSelector.style.js +10 -0
  37. package/build/cjs/components/DataDimension/{DataTypeSelector.js → ItemSelector/DataTypeSelector.js} +4 -4
  38. package/build/cjs/components/DataDimension/{DetailSelector.js → ItemSelector/DetailSelector.js} +2 -2
  39. package/build/cjs/components/DataDimension/{GroupSelector.js → ItemSelector/GroupSelector.js} +3 -3
  40. package/build/cjs/components/DataDimension/{ItemSelector.js → ItemSelector/ItemSelector.js} +76 -163
  41. package/build/cjs/components/DataDimension/{MetricSelector.js → ItemSelector/MetricSelector.js} +3 -3
  42. package/build/cjs/components/DataDimension/SelectedEmptyPlaceholder.js +17 -0
  43. package/build/cjs/components/DataDimension/SourceEmptyPlaceholder.js +113 -0
  44. package/build/cjs/components/DataDimension/TransferOption.js +34 -3
  45. package/build/cjs/components/DataDimension/styles/EmptyPlaceholder.style.js +10 -0
  46. package/build/cjs/components/DataDimension/styles/TransferOption.style.js +2 -2
  47. package/build/cjs/components/DimensionsPanel/List/OptionsButton.js +3 -3
  48. package/build/cjs/components/DimensionsPanel/List/styles/DimensionItem.style.js +2 -2
  49. package/build/cjs/components/DynamicDimension/DynamicDimension.js +1 -1
  50. package/build/cjs/components/DynamicDimension/ItemSelector.js +64 -111
  51. package/build/cjs/components/styles/DimensionSelector.style.js +2 -2
  52. package/build/cjs/locales/en/translations.json +18 -11
  53. package/build/cjs/modules/dataTypes.js +3 -1
  54. package/build/cjs/modules/dimensionListItem.js +4 -0
  55. package/build/es/__demo__/DimensionsPanel.stories.js +27 -3
  56. package/build/es/__demo__/FileMenu.stories.js +1 -9
  57. package/build/es/__demo__/data/avgTotalAggregationType.visualization.json +256 -1
  58. package/build/es/__demo__/data/deep.visualization.json +613 -310
  59. package/build/es/__demo__/data/deepWithFilters.visualization.json +0 -3
  60. package/build/es/__demo__/data/degs.visualization.json +2 -7
  61. package/build/es/__demo__/data/diseaseWeeks.visualization.json +317 -153
  62. package/build/es/__demo__/data/emptyColumns.visualization.json +2 -7
  63. package/build/es/__demo__/data/emptyRows.visualization.json +292 -297
  64. package/build/es/__demo__/data/hierarchy.visualization.json +197 -1
  65. package/build/es/__demo__/data/lastFiveYears.visualization.json +2 -7
  66. package/build/es/__demo__/data/narrative.visualization.json +2 -7
  67. package/build/es/__demo__/data/simple.visualization.json +115 -105
  68. package/build/es/__demo__/data/target-with-legend.visualization.json +370 -115
  69. package/build/es/__demo__/data/under-above-100.legendSet.json +87 -103
  70. package/build/es/__demo__/data/weeklyColumns.visualization.json +2 -7
  71. package/build/es/__fixtures__/json/chartAllFields.json +8 -33
  72. package/build/es/api/dimensions.js +12 -2
  73. package/build/es/api/expression.js +18 -8
  74. package/build/es/assets/DimensionItemIcons/CalculationIcon.js +1 -1
  75. package/build/es/assets/DimensionItemIcons/DataElementIcon.js +1 -1
  76. package/build/es/assets/DimensionItemIcons/GenericIcon.js +1 -1
  77. package/build/es/assets/DimensionItemIcons/PeriodIcon.js +1 -1
  78. package/build/es/components/DataDimension/DataDimension.js +69 -11
  79. package/build/es/components/DataDimension/Info/CalculationInfo.js +3 -3
  80. package/build/es/components/DataDimension/Info/DataElementInfo.js +4 -4
  81. package/build/es/components/DataDimension/Info/DataElementOperandInfo.js +5 -5
  82. package/build/es/components/DataDimension/Info/DataSetInfo.js +3 -3
  83. package/build/es/components/DataDimension/Info/EventDataItemInfo.js +6 -6
  84. package/build/es/components/DataDimension/Info/IndicatorInfo.js +3 -3
  85. package/build/es/components/DataDimension/Info/InfoPopover.js +9 -5
  86. package/build/es/components/DataDimension/Info/InfoTable.js +1 -1
  87. package/build/es/components/DataDimension/Info/OptionInfo.js +62 -0
  88. package/build/es/components/DataDimension/Info/ProgramIndicatorInfo.js +10 -7
  89. package/build/es/components/DataDimension/ItemOptionsSelector/ItemOptionsSelector.js +247 -0
  90. package/build/es/components/DataDimension/ItemOptionsSelector/styles/ItemOptionSelector.style.js +4 -0
  91. package/build/es/components/DataDimension/{DataTypeSelector.js → ItemSelector/DataTypeSelector.js} +4 -4
  92. package/build/es/components/DataDimension/{DetailSelector.js → ItemSelector/DetailSelector.js} +2 -2
  93. package/build/es/components/DataDimension/{GroupSelector.js → ItemSelector/GroupSelector.js} +3 -3
  94. package/build/es/components/DataDimension/{ItemSelector.js → ItemSelector/ItemSelector.js} +76 -163
  95. package/build/es/components/DataDimension/{MetricSelector.js → ItemSelector/MetricSelector.js} +3 -3
  96. package/build/es/components/DataDimension/SelectedEmptyPlaceholder.js +9 -0
  97. package/build/es/components/DataDimension/SourceEmptyPlaceholder.js +105 -0
  98. package/build/es/components/DataDimension/TransferOption.js +35 -4
  99. package/build/es/components/DataDimension/styles/EmptyPlaceholder.style.js +4 -0
  100. package/build/es/components/DataDimension/styles/TransferOption.style.js +2 -2
  101. package/build/es/components/DimensionsPanel/List/OptionsButton.js +3 -3
  102. package/build/es/components/DimensionsPanel/List/styles/DimensionItem.style.js +2 -2
  103. package/build/es/components/DynamicDimension/DynamicDimension.js +1 -1
  104. package/build/es/components/DynamicDimension/ItemSelector.js +66 -113
  105. package/build/es/components/styles/DimensionSelector.style.js +2 -2
  106. package/build/es/locales/en/translations.json +18 -11
  107. package/build/es/modules/dataTypes.js +2 -0
  108. package/build/es/modules/dimensionListItem.js +5 -1
  109. package/package.json +2 -2
  110. /package/build/cjs/components/DataDimension/{styles → ItemSelector/styles}/DataTypeSelector.style.js +0 -0
  111. /package/build/cjs/components/DataDimension/{styles → ItemSelector/styles}/DetailSelector.style.js +0 -0
  112. /package/build/cjs/components/DataDimension/{styles → ItemSelector/styles}/GroupSelector.style.js +0 -0
  113. /package/build/cjs/components/DataDimension/{styles → ItemSelector/styles}/MetricSelector.style.js +0 -0
  114. /package/build/es/components/DataDimension/{styles → ItemSelector/styles}/DataTypeSelector.style.js +0 -0
  115. /package/build/es/components/DataDimension/{styles → ItemSelector/styles}/DetailSelector.style.js +0 -0
  116. /package/build/es/components/DataDimension/{styles → ItemSelector/styles}/GroupSelector.style.js +0 -0
  117. /package/build/es/components/DataDimension/{styles → ItemSelector/styles}/MetricSelector.style.js +0 -0
@@ -59,7 +59,7 @@ export const DataElementOperandInfo = _ref2 => {
59
59
  dataElementOperand
60
60
  });
61
61
  setLoading(false);
62
- }, [displayNameProp, engine, id]);
62
+ }, [apiVersion, baseUrl, displayNameProp, engine, id]);
63
63
  useEffect(() => {
64
64
  fetchData();
65
65
  }, [fetchData]);
@@ -122,7 +122,7 @@ export const DataElementOperandInfo = _ref2 => {
122
122
  }, displayName);
123
123
  }))))), (data === null || data === void 0 ? void 0 : data.dataElementOperand.dataElement.optionSet) && /*#__PURE__*/React.createElement("tr", {
124
124
  className: `jsx-${styles.__hash}`
125
- }, /*#__PURE__*/React.createElement("td", {
125
+ }, /*#__PURE__*/React.createElement("th", {
126
126
  className: `jsx-${styles.__hash}`
127
127
  }, i18n.t('Option set')), /*#__PURE__*/React.createElement("td", {
128
128
  className: `jsx-${styles.__hash}`
@@ -172,7 +172,7 @@ export const DataElementOperandInfo = _ref2 => {
172
172
  }, styles));
173
173
  };
174
174
  DataElementOperandInfo.propTypes = {
175
- displayNameProp: PropTypes.string,
176
- id: PropTypes.string,
177
- type: PropTypes.string
175
+ displayNameProp: PropTypes.string.isRequired,
176
+ id: PropTypes.string.isRequired,
177
+ type: PropTypes.string.isRequired
178
178
  };
@@ -101,7 +101,7 @@ export const DataSetInfo = _ref3 => {
101
101
  }, styles));
102
102
  };
103
103
  DataSetInfo.propTypes = {
104
- displayNameProp: PropTypes.string,
105
- id: PropTypes.string,
106
- type: PropTypes.string
104
+ displayNameProp: PropTypes.string.isRequired,
105
+ id: PropTypes.string.isRequired,
106
+ type: PropTypes.string.isRequired
107
107
  };
@@ -21,7 +21,7 @@ const programDataElementQuery = {
21
21
  displayNameProp
22
22
  } = _ref2;
23
23
  return {
24
- fields: `${getCommonFields(displayNameProp)},aggregationType,dimensionItemType,legendSets[id,displayName],optionsSet[displayName],valueType,zeroIsSignificant`
24
+ fields: `${getCommonFields(displayNameProp)},aggregationType,dimensionItemType,legendSets[id,displayName],optionSet[displayName],valueType,zeroIsSignificant`
25
25
  };
26
26
  }
27
27
  }
@@ -40,7 +40,7 @@ const programAttributeQuery = {
40
40
  displayNameProp
41
41
  } = _ref4;
42
42
  return {
43
- fields: `${getCommonFields(displayNameProp)},aggregationType,dimensionItemType,legendSets[id,displayName],optionsSet[displayName],valueType,zeroIsSignificant`
43
+ fields: `${getCommonFields(displayNameProp)},aggregationType,dimensionItemType,legendSets[id,displayName],optionSet[displayName],valueType,zeroIsSignificant`
44
44
  };
45
45
  }
46
46
  }
@@ -81,7 +81,7 @@ export const EventDataItemInfo = _ref5 => {
81
81
  className: `jsx-${styles.__hash}`
82
82
  }, valueTypeDisplayNames[data === null || data === void 0 ? void 0 : data.valueType])), (data === null || data === void 0 ? void 0 : data.optionSet) && /*#__PURE__*/React.createElement("tr", {
83
83
  className: `jsx-${styles.__hash}`
84
- }, /*#__PURE__*/React.createElement("td", {
84
+ }, /*#__PURE__*/React.createElement("th", {
85
85
  className: `jsx-${styles.__hash}`
86
86
  }, i18n.t('Option set')), /*#__PURE__*/React.createElement("td", {
87
87
  className: `jsx-${styles.__hash}`
@@ -97,7 +97,7 @@ export const EventDataItemInfo = _ref5 => {
97
97
  return type === DIMENSION_TYPE_PROGRAM_DATA_ELEMENT ? renderInfoTable(data === null || data === void 0 ? void 0 : data.programDataElement) : renderInfoTable(data === null || data === void 0 ? void 0 : data.programAttribute);
98
98
  };
99
99
  EventDataItemInfo.propTypes = {
100
- displayNameProp: PropTypes.string,
101
- id: PropTypes.string,
102
- type: PropTypes.string
100
+ displayNameProp: PropTypes.string.isRequired,
101
+ id: PropTypes.string.isRequired,
102
+ type: PropTypes.string.isRequired
103
103
  };
@@ -163,7 +163,7 @@ export const IndicatorInfo = _ref3 => {
163
163
  }, styles));
164
164
  };
165
165
  IndicatorInfo.propTypes = {
166
- displayNameProp: PropTypes.string,
167
- id: PropTypes.string,
168
- type: PropTypes.string
166
+ displayNameProp: PropTypes.string.isRequired,
167
+ id: PropTypes.string.isRequired,
168
+ type: PropTypes.string.isRequired
169
169
  };
@@ -7,15 +7,16 @@ import { DIMENSION_TYPE_DATA_ELEMENT, DIMENSION_TYPE_DATA_ELEMENT_OPERAND, DIMEN
7
7
  // calculation
8
8
  DIMENSION_TYPE_INDICATOR, DIMENSION_TYPE_PROGRAM_ATTRIBUTE,
9
9
  // event data items
10
- DIMENSION_TYPE_PROGRAM_DATA_ELEMENT,
10
+ DIMENSION_TYPE_PROGRAM_ATTRIBUTE_OPTION, DIMENSION_TYPE_PROGRAM_DATA_ELEMENT,
11
11
  // event data items
12
- DIMENSION_TYPE_PROGRAM_INDICATOR } from '../../../modules/dataTypes.js';
12
+ DIMENSION_TYPE_PROGRAM_DATA_ELEMENT_OPTION, DIMENSION_TYPE_PROGRAM_INDICATOR } from '../../../modules/dataTypes.js';
13
13
  import { CalculationInfo } from './CalculationInfo.js';
14
14
  import { DataElementInfo } from './DataElementInfo.js';
15
15
  import { DataElementOperandInfo } from './DataElementOperandInfo.js';
16
16
  import { DataSetInfo } from './DataSetInfo.js';
17
17
  import { EventDataItemInfo } from './EventDataItemInfo.js';
18
18
  import { IndicatorInfo } from './IndicatorInfo.js';
19
+ import { OptionInfo } from './OptionInfo.js';
19
20
  import { ProgramIndicatorInfo } from './ProgramIndicatorInfo.js';
20
21
  import styles from './styles/InfoPopover.style.js';
21
22
  export const InfoPopover = _ref => {
@@ -41,14 +42,17 @@ export const InfoPopover = _ref => {
41
42
  }, /*#__PURE__*/React.createElement("div", {
42
43
  "data-test": `${dataTest}-table`,
43
44
  className: `jsx-${styles.__hash}` + " " + "popover"
44
- }, type === DIMENSION_TYPE_DATA_ELEMENT && /*#__PURE__*/React.createElement(DataElementInfo, infoProps), type === DIMENSION_TYPE_DATA_ELEMENT_OPERAND && /*#__PURE__*/React.createElement(DataElementOperandInfo, infoProps), type === DIMENSION_TYPE_EXPRESSION_DIMENSION_ITEM && /*#__PURE__*/React.createElement(CalculationInfo, infoProps), type === REPORTING_RATE /* TODO: verify this! */ && /*#__PURE__*/React.createElement(DataSetInfo, infoProps), type === DIMENSION_TYPE_INDICATOR && /*#__PURE__*/React.createElement(IndicatorInfo, infoProps), [DIMENSION_TYPE_PROGRAM_ATTRIBUTE, DIMENSION_TYPE_PROGRAM_DATA_ELEMENT].includes(type) && /*#__PURE__*/React.createElement(EventDataItemInfo, infoProps), type === DIMENSION_TYPE_PROGRAM_INDICATOR && /*#__PURE__*/React.createElement(ProgramIndicatorInfo, infoProps))), /*#__PURE__*/React.createElement(_JSXStyle, {
45
+ }, type === DIMENSION_TYPE_DATA_ELEMENT && /*#__PURE__*/React.createElement(DataElementInfo, infoProps), type === DIMENSION_TYPE_DATA_ELEMENT_OPERAND && /*#__PURE__*/React.createElement(DataElementOperandInfo, infoProps), type === DIMENSION_TYPE_EXPRESSION_DIMENSION_ITEM && /*#__PURE__*/React.createElement(CalculationInfo, infoProps), type === REPORTING_RATE /* TODO: verify this! */ && /*#__PURE__*/React.createElement(DataSetInfo, infoProps), type === DIMENSION_TYPE_INDICATOR && /*#__PURE__*/React.createElement(IndicatorInfo, infoProps), [DIMENSION_TYPE_PROGRAM_ATTRIBUTE, DIMENSION_TYPE_PROGRAM_DATA_ELEMENT].includes(type) && /*#__PURE__*/React.createElement(EventDataItemInfo, infoProps), type === DIMENSION_TYPE_PROGRAM_INDICATOR && /*#__PURE__*/React.createElement(ProgramIndicatorInfo, infoProps), [DIMENSION_TYPE_PROGRAM_DATA_ELEMENT_OPTION, DIMENSION_TYPE_PROGRAM_ATTRIBUTE_OPTION].includes(type) && /*#__PURE__*/React.createElement(OptionInfo, infoProps))), /*#__PURE__*/React.createElement(_JSXStyle, {
45
46
  id: styles.__hash
46
47
  }, styles));
47
48
  };
48
49
  InfoPopover.propTypes = {
50
+ displayNameProp: PropTypes.string.isRequired,
51
+ item: PropTypes.shape({
52
+ id: PropTypes.string.isRequired,
53
+ type: PropTypes.string.isRequired
54
+ }).isRequired,
49
55
  dataTest: PropTypes.string,
50
- displayNameProp: PropTypes.string,
51
- item: PropTypes.object,
52
56
  reference: PropTypes.object,
53
57
  onClose: PropTypes.func
54
58
  };
@@ -173,7 +173,7 @@ export const InfoTable = _ref4 => {
173
173
  className: `jsx-${styles.__hash}`
174
174
  }, i18n.t('Created date')), /*#__PURE__*/React.createElement("td", {
175
175
  className: `jsx-${styles.__hash}`
176
- }, `${moment(fromServerDate(data.created)).fromNow()} (${moment(fromServerDate(data.created)).format('YYYY-MM-DD')})`)), /*#__PURE__*/React.createElement("tr", {
176
+ }, `${moment(fromServerDate(data.created)).fromNow()} (${moment(fromServerDate(data.created)).format('YYYY-MM-DD')})`)), data.createdBy && /*#__PURE__*/React.createElement("tr", {
177
177
  className: `jsx-${styles.__hash}`
178
178
  }, /*#__PURE__*/React.createElement("th", {
179
179
  className: `jsx-${styles.__hash}`
@@ -0,0 +1,62 @@
1
+ import _JSXStyle from "styled-jsx/style";
2
+ import { useDataQuery } from '@dhis2/app-runtime';
3
+ import PropTypes from 'prop-types';
4
+ import React from 'react';
5
+ import i18n from '../../../locales/index.js';
6
+ import { getCommonFields, InfoTable } from './InfoTable.js';
7
+ import styles from './styles/InfoPopover.style.js';
8
+ const optionQuery = {
9
+ option: {
10
+ resource: 'options',
11
+ id: _ref => {
12
+ let {
13
+ id
14
+ } = _ref;
15
+ return id;
16
+ },
17
+ params: _ref2 => {
18
+ let {
19
+ displayNameProp
20
+ } = _ref2;
21
+ return {
22
+ fields: `${getCommonFields(displayNameProp)},optionSet[displayName]`
23
+ };
24
+ }
25
+ }
26
+ };
27
+ export const OptionInfo = _ref3 => {
28
+ let {
29
+ type,
30
+ id,
31
+ displayNameProp
32
+ } = _ref3;
33
+ const {
34
+ loading,
35
+ error,
36
+ data
37
+ } = useDataQuery(optionQuery, {
38
+ variables: {
39
+ id: id.split('.').reverse()[0],
40
+ displayNameProp
41
+ }
42
+ });
43
+ return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(InfoTable, {
44
+ dataType: type,
45
+ data: data === null || data === void 0 ? void 0 : data.option,
46
+ loading: loading,
47
+ error: error
48
+ }, (data === null || data === void 0 ? void 0 : data.option.optionSet) && /*#__PURE__*/React.createElement("tr", {
49
+ className: `jsx-${styles.__hash}`
50
+ }, /*#__PURE__*/React.createElement("th", {
51
+ className: `jsx-${styles.__hash}`
52
+ }, i18n.t('Option set')), /*#__PURE__*/React.createElement("td", {
53
+ className: `jsx-${styles.__hash}`
54
+ }, data.option.optionSet.displayName))), /*#__PURE__*/React.createElement(_JSXStyle, {
55
+ id: styles.__hash
56
+ }, styles));
57
+ };
58
+ OptionInfo.propTypes = {
59
+ displayNameProp: PropTypes.string.isRequired,
60
+ id: PropTypes.string.isRequired,
61
+ type: PropTypes.string.isRequired
62
+ };
@@ -2,7 +2,7 @@ import _JSXStyle from "styled-jsx/style";
2
2
  import { useDataMutation, useDataEngine } from '@dhis2/app-runtime';
3
3
  import PropTypes from 'prop-types';
4
4
  import React, { useCallback, useEffect, useState } from 'react';
5
- import { validateProgramIndicatorExpressionMutation } from '../../../api/expression.js';
5
+ import { validateProgramIndicatorExpressionMutation, validateProgramIndicatorFilterMutation } from '../../../api/expression.js';
6
6
  import i18n from '../../../locales/index.js';
7
7
  import { getCommonFields, renderHumanReadableExpression, renderLegendSets, sentenceCaseText, InfoTable } from './InfoTable.js';
8
8
  import styles from './styles/InfoPopover.style.js';
@@ -38,6 +38,9 @@ export const ProgramIndicatorInfo = _ref3 => {
38
38
  const [getHumanReadableExpression] = useDataMutation(validateProgramIndicatorExpressionMutation, {
39
39
  onError: setError
40
40
  });
41
+ const [getHumanReadableFilter] = useDataMutation(validateProgramIndicatorFilterMutation, {
42
+ onError: setError
43
+ });
41
44
  const fetchData = useCallback(async () => {
42
45
  const {
43
46
  programIndicator
@@ -57,8 +60,8 @@ export const ProgramIndicatorInfo = _ref3 => {
57
60
  }
58
61
  }
59
62
  if (programIndicator.filter) {
60
- const result = await getHumanReadableExpression({
61
- expression: programIndicator.filter
63
+ const result = await getHumanReadableFilter({
64
+ filter: programIndicator.filter
62
65
  });
63
66
  if (result) {
64
67
  programIndicator.humanReadableFilter = result;
@@ -74,7 +77,7 @@ export const ProgramIndicatorInfo = _ref3 => {
74
77
  programIndicator
75
78
  });
76
79
  setLoading(false);
77
- }, [displayNameProp, engine, id, getHumanReadableExpression]);
80
+ }, [displayNameProp, engine, id, getHumanReadableExpression, getHumanReadableFilter]);
78
81
  useEffect(() => {
79
82
  fetchData();
80
83
  }, [fetchData]);
@@ -175,7 +178,7 @@ export const ProgramIndicatorInfo = _ref3 => {
175
178
  }, styles));
176
179
  };
177
180
  ProgramIndicatorInfo.propTypes = {
178
- displayNameProp: PropTypes.string,
179
- id: PropTypes.string,
180
- type: PropTypes.string
181
+ displayNameProp: PropTypes.string.isRequired,
182
+ id: PropTypes.string.isRequired,
183
+ type: PropTypes.string.isRequired
181
184
  };
@@ -0,0 +1,247 @@
1
+ import _JSXStyle from "styled-jsx/style";
2
+ function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
3
+ import { useDataEngine } from '@dhis2/app-runtime';
4
+ import { Button, IconArrowLeft16, Transfer } from '@dhis2/ui';
5
+ import PropTypes from 'prop-types';
6
+ import React, { useEffect, useState } from 'react';
7
+ import { apiFetchOptions } from '../../../api/dimensions.js';
8
+ import i18n from '../../../locales/index.js';
9
+ import { DIMENSION_TYPE_PROGRAM_DATA_ELEMENT, DIMENSION_TYPE_PROGRAM_ATTRIBUTE_OPTION, DIMENSION_TYPE_PROGRAM_DATA_ELEMENT_OPTION, DIMENSION_TYPE_PROGRAM_ATTRIBUTE } from '../../../modules/dataTypes.js';
10
+ import { getIcon, getDimensionType } from '../../../modules/dimensionListItem.js';
11
+ import { TRANSFER_HEIGHT, TRANSFER_OPTIONS_WIDTH, TRANSFER_SELECTED_WIDTH } from '../../../modules/dimensionSelectorHelper.js';
12
+ import { useDebounce, useDidUpdateEffect } from '../../../modules/utils.js';
13
+ import styles from '../../styles/DimensionSelector.style.js';
14
+ import { SelectedEmptyPlaceholder } from '../SelectedEmptyPlaceholder.js';
15
+ import { SourceEmptyPlaceholder } from '../SourceEmptyPlaceholder.js';
16
+ import { TransferOption } from '../TransferOption.js';
17
+ import itemOptionSelectorStyles from './styles/ItemOptionSelector.style.js';
18
+ const formatOptionsFilters = (dataItemType, dataItemId) => {
19
+ const optionsFilters = {
20
+ dataItemId
21
+ };
22
+ if (dataItemType === DIMENSION_TYPE_PROGRAM_DATA_ELEMENT) {
23
+ optionsFilters.dataType = DIMENSION_TYPE_PROGRAM_DATA_ELEMENT_OPTION;
24
+ } else if (dataItemType === DIMENSION_TYPE_PROGRAM_ATTRIBUTE) {
25
+ optionsFilters.dataType = DIMENSION_TYPE_PROGRAM_ATTRIBUTE_OPTION;
26
+ }
27
+ return optionsFilters;
28
+ };
29
+ export const ItemOptionsSelector = _ref => {
30
+ var _state$filter;
31
+ let {
32
+ id: dataItemId,
33
+ name: dataItemName,
34
+ type: dataItemType,
35
+ selectedItems,
36
+ infoDataItem,
37
+ setInfoDataItem,
38
+ displayNameProp,
39
+ itemsRef,
40
+ onEditClick,
41
+ onSelect,
42
+ onClose,
43
+ dataTest
44
+ } = _ref;
45
+ const [state, setState] = useState({
46
+ searchTerm: '',
47
+ filter: formatOptionsFilters(dataItemType, dataItemId),
48
+ options: [],
49
+ loading: true,
50
+ nextPage: 1
51
+ });
52
+ const debouncedSearchTerm = useDebounce(state.searchTerm, 500);
53
+ const dataEngine = useDataEngine();
54
+ const setSearchTerm = searchTerm => setState(state => ({
55
+ ...state,
56
+ searchTerm
57
+ }));
58
+ const fetchItems = async page => {
59
+ var _result$dimensionItem;
60
+ setState(state => ({
61
+ ...state,
62
+ nextPage: page === 1 ? 1 : state.nextPage,
63
+ loading: true
64
+ }));
65
+ const result = await apiFetchOptions({
66
+ dataEngine,
67
+ nameProp: displayNameProp,
68
+ page,
69
+ filter: state.filter,
70
+ searchTerm: state.searchTerm
71
+ });
72
+ const newOptions = [];
73
+ (_result$dimensionItem = result.dimensionItems) === null || _result$dimensionItem === void 0 ? void 0 : _result$dimensionItem.forEach(item => {
74
+ newOptions.push({
75
+ label: item.name,
76
+ value: item.id,
77
+ disabled: item.disabled,
78
+ // XXX is this returned by the api?!
79
+ type: item.dimensionItemType,
80
+ expression: item.expression,
81
+ optionSetId: item.optionSetId
82
+ });
83
+ });
84
+ setState(state => ({
85
+ ...state,
86
+ loading: false,
87
+ options: page > 1 ? [...state.options, ...newOptions] : newOptions,
88
+ nextPage: result.nextPage
89
+ }));
90
+ /* The following handles a very specific edge-case where the user can select all items from a
91
+ page and then reopen the modal. Usually Transfer triggers the onEndReached when the end of
92
+ the page is reached (scrolling down) or if too few items are on the left side (e.g. selecting
93
+ 49 items from page 1, leaving only 1 item on the left side). However, due to the way Transfer
94
+ works, if 0 items are available, more items are fetched, but all items are already selected
95
+ (leaving 0 items on the left side still), the onReachedEnd won't trigger. Hence the code below:
96
+ IF there is a next page AND some options were just fetched AND you have the same or more
97
+ selected items than fetched items AND all fetched items are already selected -> fetch more!
98
+ */
99
+ if (result.nextPage && newOptions.length && selectedItems.length >= newOptions.length && newOptions.every(newOption => selectedItems.find(selectedItem => selectedItem.value === newOption.value))) {
100
+ fetchItems(result.nextPage);
101
+ }
102
+ };
103
+ useEffect(() => {
104
+ setState(state => ({
105
+ ...state,
106
+ filter: {
107
+ ...state.filter,
108
+ ...formatOptionsFilters(dataItemType, dataItemId)
109
+ }
110
+ }));
111
+ }, [dataItemId, dataItemType]);
112
+ useDidUpdateEffect(() => {
113
+ fetchItems(1);
114
+ }, [debouncedSearchTerm, (_state$filter = state.filter) === null || _state$filter === void 0 ? void 0 : _state$filter.dataItemId]);
115
+ const onChange = selectedIds => {
116
+ const newSelectedItems = selectedIds.map(id => {
117
+ const matchingItem = [...state.options, ...selectedItems].find(item => item.value === id);
118
+ return {
119
+ value: id,
120
+ label: matchingItem.label,
121
+ type: matchingItem.type,
122
+ optionSetId: matchingItem.optionSetId,
123
+ ...(matchingItem.expression ? {
124
+ expression: matchingItem.expression
125
+ } : {})
126
+ };
127
+ });
128
+ onSelect(newSelectedItems);
129
+ };
130
+ const onEndReached = () => {
131
+ if (state.nextPage) {
132
+ fetchItems(state.nextPage);
133
+ }
134
+ };
135
+ const isActive = value => {
136
+ const item = selectedItems.find(item => item.value === value);
137
+ return !item || item.isActive;
138
+ };
139
+ return /*#__PURE__*/React.createElement("div", {
140
+ className: `jsx-${styles.__hash} jsx-${itemOptionSelectorStyles.__hash}` + " " + "transfer-container"
141
+ }, /*#__PURE__*/React.createElement(Transfer, {
142
+ onChange: _ref2 => {
143
+ let {
144
+ selected
145
+ } = _ref2;
146
+ return onChange(selected);
147
+ },
148
+ selected: selectedItems.map(item => item.value),
149
+ options: [...state.options,
150
+ // remove items already in the options list
151
+ ...selectedItems.filter(selectedItem => {
152
+ var _state$options;
153
+ return !((_state$options = state.options) !== null && _state$options !== void 0 && _state$options.find(option => option.value === selectedItem.value));
154
+ })],
155
+ loading: state.loading,
156
+ loadingPicked: state.loading,
157
+ sourceEmptyPlaceholder: /*#__PURE__*/React.createElement(SourceEmptyPlaceholder, {
158
+ loading: state.loading,
159
+ searchTerm: debouncedSearchTerm,
160
+ options: state.options,
161
+ allItemsSelectedMessage: state.options.every(sourceItem => Boolean(selectedItems === null || selectedItems === void 0 ? void 0 : selectedItems.find(selectedItem => sourceItem.value === selectedItem.value))) && !state.nextPage ? i18n.t('All available options are already selected') : '',
162
+ noItemsMessage: i18n.t('No available options for this item'),
163
+ dataType: state.filter.dataType,
164
+ dataTest: `${dataTest}-empty-source`
165
+ }),
166
+ onEndReached: onEndReached,
167
+ filterable: true,
168
+ filterPlaceholder: i18n.t('Search by option name'),
169
+ filterablePicked: false,
170
+ searchTerm: state.searchTerm,
171
+ onFilterChange: _ref3 => {
172
+ let {
173
+ value
174
+ } = _ref3;
175
+ return setSearchTerm(value);
176
+ },
177
+ leftHeader: /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
178
+ className: `jsx-${styles.__hash} jsx-${itemOptionSelectorStyles.__hash}` + " " + "option-set-back-button"
179
+ }, /*#__PURE__*/React.createElement(Button, {
180
+ onClick: onClose,
181
+ icon: /*#__PURE__*/React.createElement(IconArrowLeft16, null),
182
+ small: true,
183
+ dataTest: `${dataTest}-option-set-back-button`
184
+ }, i18n.t('Back to all items'))), /*#__PURE__*/React.createElement("div", {
185
+ className: `jsx-${styles.__hash} jsx-${itemOptionSelectorStyles.__hash}` + " " + "option-set-name"
186
+ }, dataItemName, ": ", i18n.t('Options'))),
187
+ rightHeader: /*#__PURE__*/React.createElement("p", {
188
+ className: `jsx-${styles.__hash} jsx-${itemOptionSelectorStyles.__hash}` + " " + "rightHeader"
189
+ }, i18n.t('Selected items')),
190
+ enableOrderChange: true,
191
+ height: TRANSFER_HEIGHT,
192
+ optionsWidth: TRANSFER_OPTIONS_WIDTH,
193
+ selectedWidth: TRANSFER_SELECTED_WIDTH,
194
+ selectedEmptyComponent: /*#__PURE__*/React.createElement(SelectedEmptyPlaceholder, null),
195
+ renderOption: props => {
196
+ return /*#__PURE__*/React.createElement(TransferOption
197
+ /* eslint-disable react/prop-types */, _extends({}, props, {
198
+ active: isActive(props.value),
199
+ showingInfo: (infoDataItem === null || infoDataItem === void 0 ? void 0 : infoDataItem.id) === props.value,
200
+ icon: getIcon(props.type),
201
+ dataItemType: props.type,
202
+ dimensionType: getDimensionType({
203
+ type: props.type,
204
+ expression: props.expression
205
+ }),
206
+ dataTest: `${dataTest}-transfer-option`,
207
+ itemsRef: itemsRef,
208
+ onEditClick: () => onEditClick(props),
209
+ onInfoClick: () => setInfoDataItem({
210
+ id: props.value,
211
+ type: props.type
212
+ })
213
+ /* eslint-enable react/prop-types */
214
+ }));
215
+ },
216
+ dataTest: `${dataTest}-option-view-mode-transfer`
217
+ }), /*#__PURE__*/React.createElement(_JSXStyle, {
218
+ id: styles.__hash
219
+ }, styles), /*#__PURE__*/React.createElement(_JSXStyle, {
220
+ id: itemOptionSelectorStyles.__hash
221
+ }, itemOptionSelectorStyles));
222
+ };
223
+ ItemOptionsSelector.propTypes = {
224
+ displayNameProp: PropTypes.string.isRequired,
225
+ id: PropTypes.string.isRequired,
226
+ name: PropTypes.string.isRequired,
227
+ type: PropTypes.string.isRequired,
228
+ onClose: PropTypes.func.isRequired,
229
+ onSelect: PropTypes.func.isRequired,
230
+ dataTest: PropTypes.string,
231
+ infoDataItem: PropTypes.object,
232
+ itemsRef: PropTypes.object,
233
+ selectedItems: PropTypes.arrayOf(PropTypes.exact({
234
+ label: PropTypes.string.isRequired,
235
+ value: PropTypes.string.isRequired,
236
+ access: PropTypes.object,
237
+ isActive: PropTypes.bool,
238
+ type: PropTypes.string,
239
+ expression: PropTypes.string,
240
+ optionSetId: PropTypes.string
241
+ })),
242
+ setInfoDataItem: PropTypes.func,
243
+ onEditClick: PropTypes.func
244
+ };
245
+ ItemOptionsSelector.defaultProps = {
246
+ selectedItems: []
247
+ };
@@ -0,0 +1,4 @@
1
+ import { colors, spacers } from '@dhis2/ui';
2
+ const _defaultExport = [`.option-set-back-button.jsx-3422805239{margin:0 -${spacers.dp8};padding:${spacers.dp8};background:${colors.grey200};border-bottom:1px solid ${colors.grey400};}`, `.option-set-name.jsx-3422805239{font-size:14px;font-weight:500;padding:${spacers.dp12} 0;}`];
3
+ _defaultExport.__hash = "3422805239";
4
+ export default _defaultExport;
@@ -2,10 +2,10 @@ import _JSXStyle from "styled-jsx/style";
2
2
  import { SingleSelectField, SingleSelectOption } from '@dhis2/ui';
3
3
  import PropTypes from 'prop-types';
4
4
  import React from 'react';
5
- import i18n from '../../locales/index.js';
6
- import { DIMENSION_TYPE_ALL, dataTypeMap } from '../../modules/dataTypes.js';
7
- import { getDisplayNameByVisType } from '../../modules/visTypes.js';
8
- import { useDataDimensionContext } from './DataDimension.js';
5
+ import i18n from '../../../locales/index.js';
6
+ import { DIMENSION_TYPE_ALL, dataTypeMap } from '../../../modules/dataTypes.js';
7
+ import { getDisplayNameByVisType } from '../../../modules/visTypes.js';
8
+ import { useDataDimensionContext } from '../DataDimension.js';
9
9
  import styles from './styles/DataTypeSelector.style.js';
10
10
  const DataTypeSelector = _ref => {
11
11
  let {
@@ -2,8 +2,8 @@ import _JSXStyle from "styled-jsx/style";
2
2
  import { SingleSelectField, SingleSelectOption } from '@dhis2/ui';
3
3
  import PropTypes from 'prop-types';
4
4
  import React from 'react';
5
- import i18n from '../../locales/index.js';
6
- import { TOTALS, DETAIL } from '../../modules/dataTypes.js';
5
+ import i18n from '../../../locales/index.js';
6
+ import { TOTALS, DETAIL } from '../../../modules/dataTypes.js';
7
7
  import styles from './styles/DetailSelector.style.js';
8
8
  const getOptions = () => ({
9
9
  [TOTALS]: i18n.t('Totals only'),
@@ -3,9 +3,9 @@ import { useDataEngine } from '@dhis2/app-runtime';
3
3
  import { SingleSelectField, SingleSelectOption } from '@dhis2/ui';
4
4
  import PropTypes from 'prop-types';
5
5
  import React, { useEffect, useState } from 'react';
6
- import { apiFetchGroups } from '../../api/dimensions.js';
7
- import i18n from '../../locales/index.js';
8
- import { dataTypeMap as dataTypes, SUB_GROUP_DETAIL, SUB_GROUP_METRIC } from '../../modules/dataTypes.js';
6
+ import { apiFetchGroups } from '../../../api/dimensions.js';
7
+ import i18n from '../../../locales/index.js';
8
+ import { dataTypeMap as dataTypes, SUB_GROUP_DETAIL, SUB_GROUP_METRIC } from '../../../modules/dataTypes.js';
9
9
  import { DetailSelector } from './DetailSelector.js';
10
10
  import { MetricSelector } from './MetricSelector.js';
11
11
  import styles from './styles/GroupSelector.style.js';