@dhis2/analytics 26.4.0 → 26.5.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 (79) hide show
  1. package/build/cjs/__fixtures__/fixtures.js +1 -0
  2. package/build/cjs/__fixtures__/json/api/analytics/outlierDetection.json +213 -0
  3. package/build/cjs/api/analytics/AnalyticsAggregate.js +27 -1
  4. package/build/cjs/api/analytics/AnalyticsBase.js +8 -7
  5. package/build/cjs/api/analytics/AnalyticsRequestBase.js +9 -5
  6. package/build/cjs/api/analytics/AnalyticsResponse.js +42 -39
  7. package/build/cjs/api/analytics/__tests__/Analytics.spec.js +5 -0
  8. package/build/cjs/api/analytics/__tests__/AnalyticsAggregate.spec.js +29 -0
  9. package/build/cjs/api/analytics/__tests__/AnalyticsBase.spec.js +36 -2
  10. package/build/cjs/components/DataDimension/DataDimension.js +31 -7
  11. package/build/cjs/components/DataDimension/DataTypeSelector.js +29 -8
  12. package/build/cjs/components/DataDimension/GroupSelector.js +7 -7
  13. package/build/cjs/components/DataDimension/ItemSelector.js +79 -61
  14. package/build/cjs/components/Interpretations/InterpretationModal/InterpretationModal.js +13 -4
  15. package/build/cjs/components/Interpretations/InterpretationModal/InterpretationThread.js +3 -0
  16. package/build/cjs/components/Interpretations/InterpretationsUnit/InterpretationList.js +3 -0
  17. package/build/cjs/components/Interpretations/InterpretationsUnit/InterpretationsUnit.js +15 -4
  18. package/build/cjs/components/Interpretations/common/Interpretation/Interpretation.js +7 -2
  19. package/build/cjs/components/Interpretations/common/Interpretation/useLike.js +12 -2
  20. package/build/cjs/components/PeriodDimension/PeriodDimension.js +5 -2
  21. package/build/cjs/components/PeriodDimension/PeriodTransfer.js +64 -31
  22. package/build/cjs/components/PeriodDimension/__tests__/__snapshots__/PeriodDimension.spec.js.snap +1 -1
  23. package/build/cjs/components/PeriodDimension/__tests__/__snapshots__/PeriodSelector.spec.js.snap +1 -12
  24. package/build/cjs/components/VisTypeIcon.js +6 -1
  25. package/build/cjs/index.js +43 -1
  26. package/build/cjs/locales/en/translations.json +5 -1
  27. package/build/cjs/modules/__tests__/getAdaptedUiLayoutByType.spec.js +15 -0
  28. package/build/cjs/modules/axis.js +4 -0
  29. package/build/cjs/modules/getAdaptedUiLayoutByType.js +9 -0
  30. package/build/cjs/modules/layoutTypes.js +4 -2
  31. package/build/cjs/modules/layoutUiRules/__tests__/rules.spec.js +13 -1
  32. package/build/cjs/modules/layoutUiRules/index.js +12 -0
  33. package/build/cjs/modules/layoutUiRules/rules.js +22 -2
  34. package/build/cjs/modules/layoutUiRules/rulesHelper.js +4 -2
  35. package/build/cjs/modules/layoutUiRules/rulesUtils.js +7 -2
  36. package/build/cjs/modules/visTypeToLayoutType.js +2 -1
  37. package/build/cjs/modules/visTypes.js +9 -3
  38. package/build/cjs/visualizations/config/adapters/dhis_highcharts/subtitle/index.js +3 -2
  39. package/build/cjs/visualizations/config/adapters/dhis_highcharts/title/index.js +3 -2
  40. package/build/es/__fixtures__/fixtures.js +1 -0
  41. package/build/es/__fixtures__/json/api/analytics/outlierDetection.json +213 -0
  42. package/build/es/api/analytics/AnalyticsAggregate.js +27 -1
  43. package/build/es/api/analytics/AnalyticsBase.js +7 -7
  44. package/build/es/api/analytics/AnalyticsRequestBase.js +9 -5
  45. package/build/es/api/analytics/AnalyticsResponse.js +42 -39
  46. package/build/es/api/analytics/__tests__/Analytics.spec.js +5 -0
  47. package/build/es/api/analytics/__tests__/AnalyticsAggregate.spec.js +29 -0
  48. package/build/es/api/analytics/__tests__/AnalyticsBase.spec.js +34 -1
  49. package/build/es/components/DataDimension/DataDimension.js +27 -6
  50. package/build/es/components/DataDimension/DataTypeSelector.js +30 -9
  51. package/build/es/components/DataDimension/GroupSelector.js +7 -7
  52. package/build/es/components/DataDimension/ItemSelector.js +80 -62
  53. package/build/es/components/Interpretations/InterpretationModal/InterpretationModal.js +13 -4
  54. package/build/es/components/Interpretations/InterpretationModal/InterpretationThread.js +3 -0
  55. package/build/es/components/Interpretations/InterpretationsUnit/InterpretationList.js +3 -0
  56. package/build/es/components/Interpretations/InterpretationsUnit/InterpretationsUnit.js +15 -4
  57. package/build/es/components/Interpretations/common/Interpretation/Interpretation.js +7 -2
  58. package/build/es/components/Interpretations/common/Interpretation/useLike.js +12 -2
  59. package/build/es/components/PeriodDimension/PeriodDimension.js +5 -2
  60. package/build/es/components/PeriodDimension/PeriodTransfer.js +65 -32
  61. package/build/es/components/PeriodDimension/__tests__/__snapshots__/PeriodDimension.spec.js.snap +1 -1
  62. package/build/es/components/PeriodDimension/__tests__/__snapshots__/PeriodSelector.spec.js.snap +1 -12
  63. package/build/es/components/VisTypeIcon.js +8 -3
  64. package/build/es/index.js +4 -4
  65. package/build/es/locales/en/translations.json +5 -1
  66. package/build/es/modules/__tests__/getAdaptedUiLayoutByType.spec.js +16 -1
  67. package/build/es/modules/axis.js +5 -1
  68. package/build/es/modules/getAdaptedUiLayoutByType.js +10 -1
  69. package/build/es/modules/layoutTypes.js +2 -1
  70. package/build/es/modules/layoutUiRules/__tests__/rules.spec.js +14 -2
  71. package/build/es/modules/layoutUiRules/index.js +2 -2
  72. package/build/es/modules/layoutUiRules/rules.js +22 -3
  73. package/build/es/modules/layoutUiRules/rulesHelper.js +3 -2
  74. package/build/es/modules/layoutUiRules/rulesUtils.js +6 -2
  75. package/build/es/modules/visTypeToLayoutType.js +4 -3
  76. package/build/es/modules/visTypes.js +7 -3
  77. package/build/es/visualizations/config/adapters/dhis_highcharts/subtitle/index.js +3 -2
  78. package/build/es/visualizations/config/adapters/dhis_highcharts/title/index.js +3 -2
  79. package/package.json +6 -3
@@ -16,7 +16,8 @@ export const Interpretation = _ref => {
16
16
  disabled,
17
17
  onReplyIconClick,
18
18
  dashboardRedirectUrl,
19
- isInThread
19
+ isInThread,
20
+ onLikeToggled
20
21
  } = _ref;
21
22
  const [isUpdateMode, setIsUpdateMode] = useState(false);
22
23
  const [showSharingDialog, setShowSharingDialog] = useState(false);
@@ -27,7 +28,10 @@ export const Interpretation = _ref => {
27
28
  } = useLike({
28
29
  interpretation,
29
30
  currentUser,
30
- onComplete: onUpdated
31
+ onComplete: likedBy => onLikeToggled({
32
+ id: interpretation.id,
33
+ likedBy
34
+ })
31
35
  });
32
36
  const shouldShowButton = Boolean(!!onClick && !disabled & !dashboardRedirectUrl);
33
37
  const interpretationAccess = getInterpretationAccess(interpretation, currentUser);
@@ -113,6 +117,7 @@ Interpretation.propTypes = {
113
117
  currentUser: PropTypes.object.isRequired,
114
118
  interpretation: PropTypes.object.isRequired,
115
119
  onDeleted: PropTypes.func.isRequired,
120
+ onLikeToggled: PropTypes.func.isRequired,
116
121
  onReplyIconClick: PropTypes.func.isRequired,
117
122
  onUpdated: PropTypes.func.isRequired,
118
123
  dashboardRedirectUrl: PropTypes.string,
@@ -18,12 +18,22 @@ const useLike = _ref => {
18
18
  const [like, {
19
19
  loading: likeLoading
20
20
  }] = useDataMutation(likeMutationRef.current, {
21
- onComplete
21
+ onComplete: () => {
22
+ const newLikedBy = interpretation.likedBy.concat({
23
+ id: currentUser.id
24
+ });
25
+ setIsLikedByCurrentUser(true);
26
+ onComplete(newLikedBy);
27
+ }
22
28
  });
23
29
  const [unlike, {
24
30
  loading: unlikeLoading
25
31
  }] = useDataMutation(unlikeMutationRef.current, {
26
- onComplete
32
+ onComplete: () => {
33
+ const newLikedBy = interpretation.likedBy.filter(lb => lb.id !== currentUser.id);
34
+ setIsLikedByCurrentUser(false);
35
+ onComplete(newLikedBy);
36
+ }
27
37
  });
28
38
  const [isLikedByCurrentUser, setIsLikedByCurrentUser] = useState(false);
29
39
  const toggleLike = () => {
@@ -16,7 +16,8 @@ const PeriodDimension = _ref => {
16
16
  onSelect,
17
17
  selectedPeriods,
18
18
  rightFooter,
19
- excludedPeriodTypes
19
+ excludedPeriodTypes,
20
+ infoBoxMessage
20
21
  } = _ref;
21
22
  const {
22
23
  systemInfo
@@ -44,7 +45,8 @@ const PeriodDimension = _ref => {
44
45
  };
45
46
  return /*#__PURE__*/React.createElement(PeriodTransfer, {
46
47
  onSelect: selectPeriods,
47
- initialSelectedPeriods: selectedPeriods,
48
+ selectedItems: selectedPeriods,
49
+ infoBoxMessage: infoBoxMessage,
48
50
  rightFooter: rightFooter,
49
51
  dataTest: 'period-dimension',
50
52
  excludedPeriodTypes: excludedPeriodTypes,
@@ -54,6 +56,7 @@ const PeriodDimension = _ref => {
54
56
  PeriodDimension.propTypes = {
55
57
  onSelect: PropTypes.func.isRequired,
56
58
  excludedPeriodTypes: PropTypes.arrayOf(PropTypes.string),
59
+ infoBoxMessage: PropTypes.string,
57
60
  rightFooter: PropTypes.node,
58
61
  selectedPeriods: PropTypes.array
59
62
  };
@@ -1,7 +1,7 @@
1
1
  import _JSXStyle from "styled-jsx/style";
2
2
  function _extends() { _extends = Object.assign ? Object.assign.bind() : 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); }
3
3
  import { getNowInCalendar } from '@dhis2/multi-calendar-dates';
4
- import { TabBar, Tab, Transfer } from '@dhis2/ui';
4
+ import { IconInfo16, TabBar, Tab, Transfer } from '@dhis2/ui';
5
5
  import PropTypes from 'prop-types';
6
6
  import React, { useState } from 'react';
7
7
  import PeriodIcon from '../../assets/DimensionItemIcons/PeriodIcon.js'; //TODO: Reimplement the icon.js
@@ -14,15 +14,35 @@ import RelativePeriodFilter from './RelativePeriodFilter.js';
14
14
  import { getFixedPeriodsOptionsById } from './utils/fixedPeriods.js';
15
15
  import { MONTHLY, QUARTERLY } from './utils/index.js';
16
16
  import { getRelativePeriodsOptionsById } from './utils/relativePeriods.js';
17
- const PeriodTransfer = _ref => {
17
+ const RightHeader = _ref => {
18
+ let {
19
+ infoBoxMessage
20
+ } = _ref;
21
+ return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("p", {
22
+ className: `jsx-${styles.__hash}` + " " + "rightHeader"
23
+ }, i18n.t('Selected Periods')), infoBoxMessage && /*#__PURE__*/React.createElement("div", {
24
+ className: `jsx-${styles.__hash}` + " " + "info-container"
25
+ }, /*#__PURE__*/React.createElement("div", {
26
+ className: `jsx-${styles.__hash}`
27
+ }, /*#__PURE__*/React.createElement(IconInfo16, null)), /*#__PURE__*/React.createElement("span", {
28
+ className: `jsx-${styles.__hash}` + " " + "info-text"
29
+ }, infoBoxMessage)), /*#__PURE__*/React.createElement(_JSXStyle, {
30
+ id: styles.__hash
31
+ }, styles));
32
+ };
33
+ RightHeader.propTypes = {
34
+ infoBoxMessage: PropTypes.string
35
+ };
36
+ const PeriodTransfer = _ref2 => {
18
37
  let {
19
38
  onSelect,
20
39
  dataTest,
21
- initialSelectedPeriods,
40
+ selectedItems,
22
41
  rightFooter,
23
42
  excludedPeriodTypes,
24
- periodsSettings
25
- } = _ref;
43
+ periodsSettings,
44
+ infoBoxMessage
45
+ } = _ref2;
26
46
  const defaultRelativePeriodType = excludedPeriodTypes.includes(MONTHLY) ? getRelativePeriodsOptionsById(QUARTERLY) : getRelativePeriodsOptionsById(MONTHLY);
27
47
  const defaultFixedPeriodType = excludedPeriodTypes.includes(MONTHLY) ? getFixedPeriodsOptionsById(QUARTERLY, periodsSettings) : getFixedPeriodsOptionsById(MONTHLY, periodsSettings);
28
48
  const now = getNowInCalendar(periodsSettings.calendar);
@@ -35,7 +55,6 @@ const PeriodTransfer = _ref => {
35
55
  reversePeriods: false
36
56
  });
37
57
  const [allPeriods, setAllPeriods] = useState(defaultRelativePeriodType.getPeriods());
38
- const [selectedPeriods, setSelectedPeriods] = useState(initialSelectedPeriods);
39
58
  const [isRelative, setIsRelative] = useState(true);
40
59
  const [relativeFilter, setRelativeFilter] = useState({
41
60
  periodType: defaultRelativePeriodType.id
@@ -44,6 +63,10 @@ const PeriodTransfer = _ref => {
44
63
  periodType: defaultFixedPeriodType.id,
45
64
  year: defaultFixedPeriodYear.toString()
46
65
  });
66
+ const isActive = value => {
67
+ const item = selectedItems.find(item => item.id === value);
68
+ return !item || item.isActive;
69
+ };
47
70
  const onIsRelativeClick = state => {
48
71
  if (state !== isRelative) {
49
72
  setIsRelative(state);
@@ -90,11 +113,6 @@ const PeriodTransfer = _ref => {
90
113
  })), /*#__PURE__*/React.createElement(_JSXStyle, {
91
114
  id: styles.__hash
92
115
  }, styles));
93
- const renderRightHeader = () => /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("p", {
94
- className: `jsx-${styles.__hash}` + " " + "rightHeader"
95
- }, i18n.t('Selected Periods')), /*#__PURE__*/React.createElement(_JSXStyle, {
96
- id: styles.__hash
97
- }, styles));
98
116
  const onSelectFixedPeriods = filter => {
99
117
  setFixedFilter(filter);
100
118
  setAllPeriods(getFixedPeriodsOptionsById(filter.periodType, periodsSettings).getPeriods(fixedPeriodConfig(Number(filter.year)), periodsSettings));
@@ -105,45 +123,58 @@ const PeriodTransfer = _ref => {
105
123
  id: styles.__hash
106
124
  }, styles));
107
125
  return /*#__PURE__*/React.createElement(Transfer, {
108
- onChange: _ref2 => {
126
+ onChange: _ref3 => {
109
127
  let {
110
128
  selected
111
- } = _ref2;
112
- const formattedItems = selected.map(id => ({
113
- id,
114
- name: [...allPeriods, ...selectedPeriods].find(item => item.id === id).name
115
- }));
116
- setSelectedPeriods(formattedItems);
129
+ } = _ref3;
130
+ const formattedItems = selected.map(id => {
131
+ const matchingItem = [...allPeriods, ...selectedItems].find(item => item.id === id);
132
+ return {
133
+ id,
134
+ name: matchingItem.name,
135
+ isActive: matchingItem.isActive
136
+ };
137
+ });
117
138
  onSelect(formattedItems);
118
139
  },
119
- selected: selectedPeriods.map(period => period.id),
140
+ selected: selectedItems.map(period => period.id),
120
141
  leftHeader: renderLeftHeader(),
121
142
  enableOrderChange: true,
122
143
  height: TRANSFER_HEIGHT,
123
144
  optionsWidth: TRANSFER_OPTIONS_WIDTH,
124
145
  selectedWidth: TRANSFER_SELECTED_WIDTH,
125
146
  selectedEmptyComponent: renderEmptySelection(),
126
- rightHeader: renderRightHeader(),
147
+ rightHeader: /*#__PURE__*/React.createElement(RightHeader, {
148
+ infoBoxMessage: infoBoxMessage
149
+ }),
127
150
  rightFooter: rightFooter,
128
- options: [...allPeriods, ...selectedPeriods].map(_ref3 => {
151
+ options: [...allPeriods, ...selectedItems].map(_ref4 => {
129
152
  let {
130
153
  id,
131
154
  name
132
- } = _ref3;
155
+ } = _ref4;
133
156
  return {
134
157
  label: name,
135
158
  value: id
136
159
  };
137
160
  }),
138
- renderOption: props => /*#__PURE__*/React.createElement(TransferOption, _extends({}, props, {
139
- icon: PeriodIcon,
140
- dataTest: `${dataTest}-transfer-option`
141
- })),
161
+ renderOption: _ref5 => {
162
+ let {
163
+ value,
164
+ ...props
165
+ } = _ref5;
166
+ return /*#__PURE__*/React.createElement(TransferOption, _extends({}, props, {
167
+ value: value,
168
+ active: isActive(value),
169
+ icon: PeriodIcon,
170
+ dataTest: `${dataTest}-transfer-option`
171
+ }));
172
+ },
142
173
  dataTest: `${dataTest}-transfer`
143
174
  });
144
175
  };
145
176
  PeriodTransfer.defaultProps = {
146
- initialSelectedPeriods: [],
177
+ selectedItems: [],
147
178
  excludedPeriodTypes: [],
148
179
  periodsSettings: {
149
180
  calendar: 'gregory',
@@ -154,14 +185,16 @@ PeriodTransfer.propTypes = {
154
185
  onSelect: PropTypes.func.isRequired,
155
186
  dataTest: PropTypes.string,
156
187
  excludedPeriodTypes: PropTypes.arrayOf(PropTypes.string),
157
- initialSelectedPeriods: PropTypes.arrayOf(PropTypes.shape({
158
- id: PropTypes.string,
159
- name: PropTypes.string
160
- })),
188
+ infoBoxMessage: PropTypes.string,
161
189
  periodsSettings: PropTypes.shape({
162
190
  calendar: PropTypes.string,
163
191
  locale: PropTypes.string
164
192
  }),
165
- rightFooter: PropTypes.node
193
+ rightFooter: PropTypes.node,
194
+ selectedItems: PropTypes.arrayOf(PropTypes.shape({
195
+ id: PropTypes.string,
196
+ isActive: PropTypes.bool,
197
+ name: PropTypes.string
198
+ }))
166
199
  };
167
200
  export default PeriodTransfer;
@@ -4,7 +4,6 @@ exports[`The Period Dimension component matches the snapshot 1`] = `
4
4
  <PeriodTransfer
5
5
  dataTest="period-dimension"
6
6
  excludedPeriodTypes={Array []}
7
- initialSelectedPeriods={Array []}
8
7
  onSelect={[Function]}
9
8
  periodsSettings={
10
9
  Object {
@@ -13,5 +12,6 @@ exports[`The Period Dimension component matches the snapshot 1`] = `
13
12
  }
14
13
  }
15
14
  rightFooter={<React.Fragment />}
15
+ selectedItems={Array []}
16
16
  />
17
17
  `;
@@ -77,18 +77,7 @@ exports[`The Period Selector component matches the snapshot 1`] = `
77
77
  optionsWidth="420px"
78
78
  renderOption={[Function]}
79
79
  rightFooter={<React.Fragment />}
80
- rightHeader={
81
- <React.Fragment>
82
- <p
83
- className="rightHeader"
84
- >
85
- Selected Periods
86
- </p>
87
- <style>
88
-
89
- </style>
90
- </React.Fragment>
91
- }
80
+ rightHeader={<RightHeader />}
92
81
  selected={Array []}
93
82
  selectedEmptyComponent={
94
83
  <React.Fragment>
@@ -1,7 +1,7 @@
1
- import { IconTable16, IconVisualizationArea16, IconVisualizationAreaStacked16, IconVisualizationBar16, IconVisualizationBarStacked16, IconVisualizationColumn16, IconVisualizationColumnMulti16, IconVisualizationColumnStacked16, IconVisualizationGauge16, IconVisualizationLine16, IconVisualizationLinelist16, IconVisualizationLineMulti16, IconVisualizationPie16, IconVisualizationRadar16, IconVisualizationScatter16, IconVisualizationSingleValue16, IconTable24, IconVisualizationArea24, IconVisualizationAreaStacked24, IconVisualizationBar24, IconVisualizationBarStacked24, IconVisualizationColumn24, IconVisualizationLinelist24, IconVisualizationColumnMulti24, IconVisualizationColumnStacked24, IconVisualizationGauge24, IconVisualizationLine24, IconVisualizationLineMulti24, IconVisualizationPie24, IconVisualizationRadar24, IconVisualizationScatter24, IconVisualizationSingleValue24 } from '@dhis2/ui';
1
+ import { IconVisualizationArea16, IconVisualizationAreaStacked16, IconVisualizationBar16, IconVisualizationBarStacked16, IconVisualizationColumn16, IconVisualizationColumnMulti16, IconVisualizationColumnStacked16, IconVisualizationGauge16, IconVisualizationLine16, IconVisualizationLinelist16, IconVisualizationLineMulti16, IconVisualizationOutlierTable16, IconVisualizationPie16, IconVisualizationPivotTable16, IconVisualizationRadar16, IconVisualizationScatter16, IconVisualizationSingleValue16, IconVisualizationArea24, IconVisualizationAreaStacked24, IconVisualizationBar24, IconVisualizationBarStacked24, IconVisualizationColumn24, IconVisualizationLinelist24, IconVisualizationColumnMulti24, IconVisualizationColumnStacked24, IconVisualizationGauge24, IconVisualizationLine24, IconVisualizationLineMulti24, IconVisualizationOutlierTable24, IconVisualizationPie24, IconVisualizationPivotTable24, IconVisualizationRadar24, IconVisualizationScatter24, IconVisualizationSingleValue24 } from '@dhis2/ui';
2
2
  import PropTypes from 'prop-types';
3
3
  import React from 'react';
4
- import { VIS_TYPE_LINE_LIST, VIS_TYPE_PIVOT_TABLE, VIS_TYPE_COLUMN, VIS_TYPE_STACKED_COLUMN, VIS_TYPE_BAR, VIS_TYPE_STACKED_BAR, VIS_TYPE_LINE, VIS_TYPE_AREA, VIS_TYPE_STACKED_AREA, VIS_TYPE_PIE, VIS_TYPE_RADAR, VIS_TYPE_GAUGE, VIS_TYPE_YEAR_OVER_YEAR_LINE, VIS_TYPE_YEAR_OVER_YEAR_COLUMN, VIS_TYPE_SINGLE_VALUE, VIS_TYPE_SCATTER } from '../modules/visTypes.js';
4
+ import { VIS_TYPE_LINE_LIST, VIS_TYPE_PIVOT_TABLE, VIS_TYPE_COLUMN, VIS_TYPE_STACKED_COLUMN, VIS_TYPE_BAR, VIS_TYPE_STACKED_BAR, VIS_TYPE_LINE, VIS_TYPE_AREA, VIS_TYPE_STACKED_AREA, VIS_TYPE_PIE, VIS_TYPE_RADAR, VIS_TYPE_GAUGE, VIS_TYPE_YEAR_OVER_YEAR_LINE, VIS_TYPE_YEAR_OVER_YEAR_COLUMN, VIS_TYPE_SINGLE_VALUE, VIS_TYPE_SCATTER, VIS_TYPE_OUTLIER_TABLE } from '../modules/visTypes.js';
5
5
  export const VisTypeIcon = _ref => {
6
6
  let {
7
7
  type,
@@ -17,7 +17,7 @@ export const VisTypeIcon = _ref => {
17
17
  }
18
18
  case VIS_TYPE_PIVOT_TABLE:
19
19
  {
20
- VisIcon = useSmall ? IconTable16 : IconTable24;
20
+ VisIcon = useSmall ? IconVisualizationPivotTable16 : IconVisualizationPivotTable24;
21
21
  break;
22
22
  }
23
23
  case VIS_TYPE_BAR:
@@ -85,6 +85,11 @@ export const VisTypeIcon = _ref => {
85
85
  VisIcon = useSmall ? IconVisualizationScatter16 : IconVisualizationScatter24;
86
86
  break;
87
87
  }
88
+ case VIS_TYPE_OUTLIER_TABLE:
89
+ {
90
+ VisIcon = useSmall ? IconVisualizationOutlierTable16 : IconVisualizationOutlierTable24;
91
+ break;
92
+ }
88
93
  case VIS_TYPE_COLUMN:
89
94
  default:
90
95
  {
package/build/es/index.js CHANGED
@@ -97,15 +97,15 @@ export { getLayoutTypeByVisType } from './modules/visTypeToLayoutType.js';
97
97
 
98
98
  // Modules: visTypes
99
99
 
100
- export { VIS_TYPE_GROUP_ALL, VIS_TYPE_GROUP_CHARTS, VIS_TYPE_COLUMN, VIS_TYPE_STACKED_COLUMN, VIS_TYPE_BAR, VIS_TYPE_STACKED_BAR, VIS_TYPE_LINE, VIS_TYPE_AREA, VIS_TYPE_STACKED_AREA, VIS_TYPE_PIE, VIS_TYPE_RADAR, VIS_TYPE_GAUGE, VIS_TYPE_BUBBLE, VIS_TYPE_YEAR_OVER_YEAR_LINE, VIS_TYPE_YEAR_OVER_YEAR_COLUMN, VIS_TYPE_SINGLE_VALUE, VIS_TYPE_PIVOT_TABLE, VIS_TYPE_SCATTER, VIS_TYPE_LINE_LIST, visTypeDisplayNames, visTypeIcons, getDisplayNameByVisType, defaultVisType, isStacked, isMultiType, isYearOverYear, isDualAxisType, isSingleValue, isTwoCategoryChartType, isLegendSetType, isColumnBasedType, isVerticalType } from './modules/visTypes.js';
100
+ export { VIS_TYPE_GROUP_ALL, VIS_TYPE_GROUP_CHARTS, VIS_TYPE_COLUMN, VIS_TYPE_STACKED_COLUMN, VIS_TYPE_BAR, VIS_TYPE_STACKED_BAR, VIS_TYPE_LINE, VIS_TYPE_AREA, VIS_TYPE_STACKED_AREA, VIS_TYPE_PIE, VIS_TYPE_RADAR, VIS_TYPE_GAUGE, VIS_TYPE_BUBBLE, VIS_TYPE_YEAR_OVER_YEAR_LINE, VIS_TYPE_YEAR_OVER_YEAR_COLUMN, VIS_TYPE_SINGLE_VALUE, VIS_TYPE_PIVOT_TABLE, VIS_TYPE_SCATTER, VIS_TYPE_LINE_LIST, VIS_TYPE_OUTLIER_TABLE, visTypeDisplayNames, visTypeIcons, getDisplayNameByVisType, defaultVisType, isStacked, isMultiType, isYearOverYear, isDualAxisType, isSingleValue, isOutlierTable, isTwoCategoryChartType, isLegendSetType, isColumnBasedType, isVerticalType } from './modules/visTypes.js';
101
101
 
102
102
  // Modules: layoutTypes
103
103
 
104
- export { LAYOUT_TYPE_DEFAULT, LAYOUT_TYPE_PIE, LAYOUT_TYPE_SINGLE_VALUE, LAYOUT_TYPE_YEAR_OVER_YEAR, LAYOUT_TYPE_PIVOT_TABLE, LAYOUT_TYPE_SCATTER, LAYOUT_TYPE_LINE_LIST } from './modules/layoutTypes.js';
104
+ export { LAYOUT_TYPE_DEFAULT, LAYOUT_TYPE_PIE, LAYOUT_TYPE_SINGLE_VALUE, LAYOUT_TYPE_YEAR_OVER_YEAR, LAYOUT_TYPE_PIVOT_TABLE, LAYOUT_TYPE_SCATTER, LAYOUT_TYPE_LINE_LIST, LAYOUT_TYPE_OUTLIER_TABLE } from './modules/layoutTypes.js';
105
105
 
106
106
  // Modules: layoutUiRules
107
107
 
108
- export { getAvailableAxes, getDisallowedDimensions, getAxisMaxNumberOfItems, getAxisMaxNumberOfDimensions, getAxisMinNumberOfDimensions, hasAxisTooManyItems, getAxisPerLockedDimension, getAllLockedDimensionIds, canDimensionBeAddedToAxis, isDimensionLocked, isAxisFull, getTransferableDimension } from './modules/layoutUiRules/index.js';
108
+ export { getAvailableAxes, getDisallowedDimensions, getDimensionMaxNumberOfItems, getAxisMaxNumberOfItems, getAxisMaxNumberOfDimensions, getAxisMinNumberOfDimensions, hasAxisTooManyItems, hasDimensionTooManyItems, getAxisPerLockedDimension, getAllLockedDimensionIds, canDimensionBeAddedToAxis, isDimensionLocked, isAxisFull, getTransferableDimension } from './modules/layoutUiRules/index.js';
109
109
 
110
110
  // Visualizations
111
111
 
@@ -131,4 +131,4 @@ export { DAILY, WEEKLY, WEEKLYWED, WEEKLYTHU, WEEKLYSAT, WEEKLYSUN, WEEKS_THIS_Y
131
131
  export { getRelativePeriodsOptionsById } from './components/PeriodDimension/utils/relativePeriods.js';
132
132
  export { getFixedPeriodsOptionsById } from './components/PeriodDimension/utils/fixedPeriods.js';
133
133
  export { default as VisualizationOptions } from './components/Options/VisualizationOptions.js';
134
- 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';
134
+ 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, dataTypeMap } from './modules/dataTypes.js';
@@ -44,6 +44,7 @@
44
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
45
  "Math operators": "Math operators",
46
46
  "Data Type": "Data Type",
47
+ "Only {{dataType}} can be used in {{visType}}": "Only {{dataType}} can be used in {{visType}}",
47
48
  "All types": "All types",
48
49
  "Disaggregation": "Disaggregation",
49
50
  "No data": "No data",
@@ -54,10 +55,12 @@
54
55
  "No data sets found": "No data sets found",
55
56
  "No event data items found": "No event data items found",
56
57
  "No program indicators found": "No program indicators found",
58
+ "No calculations found": "No calculations found",
57
59
  "No indicators found for \"{{- searchTerm}}\"": "No indicators found for \"{{- searchTerm}}\"",
58
60
  "No data sets found for \"{{- searchTerm}}\"": "No data sets found for \"{{- searchTerm}}\"",
59
61
  "No event data items found for \"{{- searchTerm}}\"": "No event data items found for \"{{- searchTerm}}\"",
60
62
  "No program indicators found for \"{{- searchTerm}}\"": "No program indicators found for \"{{- searchTerm}}\"",
63
+ "No calculations found for \"{{- searchTerm}}\"": "No calculations found for \"{{- searchTerm}}\"",
61
64
  "Nothing found for \"{{- searchTerm}}\"": "Nothing found for \"{{- searchTerm}}\"",
62
65
  "Calculation": "Calculation",
63
66
  "Metric type": "Metric type",
@@ -201,9 +204,9 @@
201
204
  "Year": "Year",
202
205
  "Select year": "Select year",
203
206
  "Period": "Period",
207
+ "Selected Periods": "Selected Periods",
204
208
  "Relative periods": "Relative periods",
205
209
  "Fixed periods": "Fixed periods",
206
- "Selected Periods": "Selected Periods",
207
210
  "No periods selected": "No periods selected",
208
211
  "Daily": "Daily",
209
212
  "Weekly": "Weekly",
@@ -371,6 +374,7 @@
371
374
  "Radar": "Radar",
372
375
  "Scatter": "Scatter",
373
376
  "Single value": "Single value",
377
+ "Outlier table": "Outlier table",
374
378
  "All charts": "All charts",
375
379
  "{{seriesName}} (trend)": "{{seriesName}} (trend)",
376
380
  "Trend": "Trend",
@@ -1,9 +1,10 @@
1
1
  import { getAdaptedUiLayoutByType } from '../getAdaptedUiLayoutByType.js';
2
2
  import { AXIS_ID_COLUMNS, AXIS_ID_ROWS, AXIS_ID_FILTERS } from '../layout/axis.js';
3
3
  import { DIMENSION_ID_DATA, DIMENSION_ID_PERIOD, DIMENSION_ID_ORGUNIT } from '../predefinedDimensions.js';
4
- import { VIS_TYPE_COLUMN, VIS_TYPE_YEAR_OVER_YEAR_LINE, VIS_TYPE_BAR, VIS_TYPE_PIE, VIS_TYPE_SINGLE_VALUE } from '../visTypes.js';
4
+ import { VIS_TYPE_COLUMN, VIS_TYPE_YEAR_OVER_YEAR_LINE, VIS_TYPE_BAR, VIS_TYPE_PIE, VIS_TYPE_SINGLE_VALUE, VIS_TYPE_OUTLIER_TABLE } from '../visTypes.js';
5
5
  const someId = 'someId';
6
6
  const otherId = 'otherId';
7
+ const thirdId = 'thirdId';
7
8
  describe('getAdaptedUiLayoutByType', () => {
8
9
  it('column: moves all extra dimensions in columns and rows to filters', () => {
9
10
  const initialState = {
@@ -107,6 +108,20 @@ describe('getAdaptedUiLayoutByType', () => {
107
108
  };
108
109
  expect(actualState).toEqual(expectedState);
109
110
  });
111
+ it('outlier table: removes all dimensions but dx,pe,ou which are moved to columns', () => {
112
+ const initialState = {
113
+ [AXIS_ID_COLUMNS]: [DIMENSION_ID_DATA, someId],
114
+ [AXIS_ID_ROWS]: [DIMENSION_ID_PERIOD, otherId],
115
+ [AXIS_ID_FILTERS]: [DIMENSION_ID_ORGUNIT, thirdId]
116
+ };
117
+ const actualState = getAdaptedUiLayoutByType(initialState, VIS_TYPE_OUTLIER_TABLE);
118
+ const expectedState = {
119
+ [AXIS_ID_COLUMNS]: [DIMENSION_ID_DATA, DIMENSION_ID_PERIOD, DIMENSION_ID_ORGUNIT],
120
+ [AXIS_ID_ROWS]: [],
121
+ [AXIS_ID_FILTERS]: []
122
+ };
123
+ expect(actualState).toEqual(expectedState);
124
+ });
110
125
  it('pivot -> sv with dimension strings', () => {
111
126
  const initialLayout = {
112
127
  [AXIS_ID_COLUMNS]: [DIMENSION_ID_DATA, DIMENSION_ID_PERIOD],
@@ -1,6 +1,6 @@
1
1
  import i18n from '../locales/index.js';
2
2
  import { AXIS_ID_COLUMNS, AXIS_ID_ROWS, AXIS_ID_FILTERS } from './layout/axis.js';
3
- import { LAYOUT_TYPE_DEFAULT, LAYOUT_TYPE_PIE, LAYOUT_TYPE_YEAR_OVER_YEAR, LAYOUT_TYPE_PIVOT_TABLE, LAYOUT_TYPE_SCATTER, LAYOUT_TYPE_LINE_LIST } from './layoutTypes.js';
3
+ import { LAYOUT_TYPE_DEFAULT, LAYOUT_TYPE_PIE, LAYOUT_TYPE_YEAR_OVER_YEAR, LAYOUT_TYPE_PIVOT_TABLE, LAYOUT_TYPE_SCATTER, LAYOUT_TYPE_LINE_LIST, LAYOUT_TYPE_OUTLIER_TABLE } from './layoutTypes.js';
4
4
  const getAxisNamesByLayoutType = layoutType => {
5
5
  switch (layoutType) {
6
6
  case LAYOUT_TYPE_DEFAULT:
@@ -28,6 +28,10 @@ const getAxisNamesByLayoutType = layoutType => {
28
28
  [AXIS_ID_ROWS]: i18n.t('Points'),
29
29
  [AXIS_ID_FILTERS]: i18n.t('Filter')
30
30
  };
31
+ case LAYOUT_TYPE_OUTLIER_TABLE:
32
+ return {
33
+ [AXIS_ID_COLUMNS]: i18n.t('Columns')
34
+ };
31
35
  }
32
36
  };
33
37
  export const getAxisNameByLayoutType = (axisId, layoutType) => {
@@ -1,7 +1,7 @@
1
1
  import isObject from 'lodash/isObject';
2
2
  import { AXIS_ID_COLUMNS, AXIS_ID_ROWS, AXIS_ID_FILTERS } from './layout/axis.js';
3
3
  import { DIMENSION_ID_DATA, DIMENSION_ID_ORGUNIT, DIMENSION_ID_PERIOD } from './predefinedDimensions.js';
4
- import { VIS_TYPE_YEAR_OVER_YEAR_LINE, VIS_TYPE_YEAR_OVER_YEAR_COLUMN, VIS_TYPE_PIE, VIS_TYPE_GAUGE, VIS_TYPE_SINGLE_VALUE, VIS_TYPE_PIVOT_TABLE, VIS_TYPE_SCATTER, isTwoCategoryChartType } from './visTypes.js';
4
+ import { VIS_TYPE_YEAR_OVER_YEAR_LINE, VIS_TYPE_YEAR_OVER_YEAR_COLUMN, VIS_TYPE_PIE, VIS_TYPE_GAUGE, VIS_TYPE_SINGLE_VALUE, VIS_TYPE_PIVOT_TABLE, VIS_TYPE_SCATTER, VIS_TYPE_OUTLIER_TABLE, isTwoCategoryChartType } from './visTypes.js';
5
5
  export const getAdaptedUiLayoutByType = (layout, type) => {
6
6
  var _layout$rows;
7
7
  if (isTwoCategoryChartType(type) && ((_layout$rows = layout.rows) === null || _layout$rows === void 0 ? void 0 : _layout$rows.length) > 1) {
@@ -26,6 +26,8 @@ export const getAdaptedUiLayoutByType = (layout, type) => {
26
26
  return layout;
27
27
  case VIS_TYPE_SCATTER:
28
28
  return getScatterLayout(layout);
29
+ case VIS_TYPE_OUTLIER_TABLE:
30
+ return getOutlierTableLayout(layout);
29
31
  default:
30
32
  return getDefaultLayout(layout);
31
33
  }
@@ -99,6 +101,13 @@ const getSingleValueLayout = layout => {
99
101
  };
100
102
  };
101
103
 
104
+ // Transform from ui.layout to outlier table layout format
105
+ const getOutlierTableLayout = () => ({
106
+ [AXIS_ID_COLUMNS]: [DIMENSION_ID_DATA, DIMENSION_ID_PERIOD, DIMENSION_ID_ORGUNIT],
107
+ [AXIS_ID_ROWS]: [],
108
+ [AXIS_ID_FILTERS]: []
109
+ });
110
+
102
111
  /**
103
112
  *
104
113
  * @param {string|object} dimension
@@ -4,4 +4,5 @@ export const LAYOUT_TYPE_SINGLE_VALUE = 'LAYOUT_TYPE_SINGLE_VALUE';
4
4
  export const LAYOUT_TYPE_YEAR_OVER_YEAR = 'LAYOUT_TYPE_YEAR_OVER_YEAR';
5
5
  export const LAYOUT_TYPE_PIVOT_TABLE = 'LAYOUT_TYPE_PIVOT_TABLE';
6
6
  export const LAYOUT_TYPE_SCATTER = 'LAYOUT_TYPE_SCATTER';
7
- export const LAYOUT_TYPE_LINE_LIST = 'LAYOUT_TYPE_LINE_LIST';
7
+ export const LAYOUT_TYPE_LINE_LIST = 'LAYOUT_TYPE_LINE_LIST';
8
+ export const LAYOUT_TYPE_OUTLIER_TABLE = 'LAYOUT_TYPE_OUTLIER_TABLE';
@@ -1,14 +1,16 @@
1
1
  import { ALL_AXIS_IDS } from '../../layout/axis.js';
2
- import { DIMENSION_ID_DATA, DIMENSION_ID_ORGUNIT, DIMENSION_ID_PERIOD } from '../../predefinedDimensions.js';
2
+ import { DIMENSION_ID_DATA, DIMENSION_ID_ORGUNIT, DIMENSION_ID_PERIOD, DIMENSION_ID_ASSIGNED_CATEGORIES } from '../../predefinedDimensions.js';
3
3
  import { testResourceRules, testResourceRequiredProps, testResourceAllRuleProps } from '../rules.js';
4
4
 
5
5
  // Consts
6
+ const validDims = [DIMENSION_ID_DATA, DIMENSION_ID_PERIOD, DIMENSION_ID_ORGUNIT];
6
7
  const lockableDims = [DIMENSION_ID_DATA, DIMENSION_ID_PERIOD, DIMENSION_ID_ORGUNIT];
7
- const disallowableDims = [DIMENSION_ID_DATA, DIMENSION_ID_PERIOD];
8
+ const disallowableDims = [DIMENSION_ID_DATA, DIMENSION_ID_PERIOD, DIMENSION_ID_ASSIGNED_CATEGORIES];
8
9
 
9
10
  // Helper fns
10
11
  const allArrayItemsAreValid = (allItems, validItems) => allItems.every(value => validItems.includes(value));
11
12
  const allArrayItemsAreValidAxisIds = array => allArrayItemsAreValid(array, ALL_AXIS_IDS);
13
+ const allArrayItemsAreValidDimensionIds = array => allArrayItemsAreValid(array, validDims);
12
14
  const onlyRulesWithProp = ruleProp => testResourceRules.filter(rule => rule[ruleProp]);
13
15
 
14
16
  // Partial tests
@@ -18,6 +20,9 @@ const testPropHasKeysAndValues = ruleProp => it('has keys and values', () => {
18
20
  const testPropIsArray = ruleProp => it('is an array', () => {
19
21
  expect(onlyRulesWithProp(ruleProp).every(rule => Array.isArray(rule[ruleProp]))).toBe(true);
20
22
  });
23
+ const testKeysAreValidDimensionIds = ruleProp => it('keys should be valid dimension ids', () => {
24
+ expect(onlyRulesWithProp(ruleProp).every(rule => allArrayItemsAreValidDimensionIds(Object.keys(rule[ruleProp])))).toBe(true);
25
+ });
21
26
  const testKeysAreValidAxisIds = ruleProp => it('keys should be valid axis ids', () => {
22
27
  expect(onlyRulesWithProp(ruleProp).every(rule => allArrayItemsAreValidAxisIds(Object.keys(rule[ruleProp])))).toBe(true);
23
28
  });
@@ -56,6 +61,13 @@ describe("verify each rule's ", () => {
56
61
  testNoValuesNegative(ruleProp);
57
62
  });
58
63
  });
64
+ describe('MAX_ITEMS_PER_DIM', () => {
65
+ const ruleProp = testResourceAllRuleProps['MAX_ITEMS_PER_DIM'];
66
+ testPropHasKeysAndValues(ruleProp);
67
+ testKeysAreValidDimensionIds(ruleProp);
68
+ testNoValuesZero(ruleProp);
69
+ testNoValuesNegative(ruleProp);
70
+ });
59
71
  describe('AVAILABLE_AXES', () => {
60
72
  const ruleProp = testResourceAllRuleProps['AVAILABLE_AXES'];
61
73
  testPropIsArray(ruleProp);
@@ -1,2 +1,2 @@
1
- export { getAvailableAxesByVisType as getAvailableAxes, getDisallowedDimsByVisType as getDisallowedDimensions, getAxisMaxNumberOfItemsByVisType as getAxisMaxNumberOfItems, getAxisMaxNumberOfDimsByVisType as getAxisMaxNumberOfDimensions, getAxisMinNumberOfDimsByVisType as getAxisMinNumberOfDimensions, getAxisPerLockedDimByVisType as getAxisPerLockedDimension, getAllLockedDimIdsByVisType as getAllLockedDimensionIds } from './rulesHelper.js';
2
- export { hasAxisTooManyItemsByVisType as hasAxisTooManyItems, isDimensionLockedByVisType as isDimensionLocked, isAxisFullByVisType as isAxisFull, canDimensionBeAddedToAxisByVisType as canDimensionBeAddedToAxis, getTransferableDimensionPerAxisByVisType as getTransferableDimension } from './rulesUtils.js';
1
+ export { getAvailableAxesByVisType as getAvailableAxes, getDisallowedDimsByVisType as getDisallowedDimensions, getAxisMaxNumberOfItemsByVisType as getAxisMaxNumberOfItems, getAxisMaxNumberOfDimsByVisType as getAxisMaxNumberOfDimensions, getAxisMinNumberOfDimsByVisType as getAxisMinNumberOfDimensions, getAxisPerLockedDimByVisType as getAxisPerLockedDimension, getAllLockedDimIdsByVisType as getAllLockedDimensionIds, getDimMaxNumberOfItemsByVisType as getDimensionMaxNumberOfItems } from './rulesHelper.js';
2
+ export { hasAxisTooManyItemsByVisType as hasAxisTooManyItems, hasDimensionTooManyItemsByVisType as hasDimensionTooManyItems, isDimensionLockedByVisType as isDimensionLocked, isAxisFullByVisType as isAxisFull, canDimensionBeAddedToAxisByVisType as canDimensionBeAddedToAxis, getTransferableDimensionPerAxisByVisType as getTransferableDimension } from './rulesUtils.js';
@@ -1,10 +1,11 @@
1
1
  import { AXIS_ID_COLUMNS, AXIS_ID_ROWS, AXIS_ID_FILTERS } from '../layout/axis.js';
2
- import { DIMENSION_ID_PERIOD, DIMENSION_ID_DATA, DIMENSION_ID_ORGUNIT } from '../predefinedDimensions.js';
3
- import { VIS_TYPE_COLUMN, VIS_TYPE_STACKED_COLUMN, VIS_TYPE_BAR, VIS_TYPE_STACKED_BAR, VIS_TYPE_LINE, VIS_TYPE_AREA, VIS_TYPE_STACKED_AREA, VIS_TYPE_RADAR, VIS_TYPE_GAUGE, VIS_TYPE_PIE, VIS_TYPE_SINGLE_VALUE, VIS_TYPE_YEAR_OVER_YEAR_LINE, VIS_TYPE_YEAR_OVER_YEAR_COLUMN, VIS_TYPE_PIVOT_TABLE, VIS_TYPE_SCATTER, VIS_TYPE_LINE_LIST } from '../visTypes.js';
2
+ import { DIMENSION_ID_PERIOD, DIMENSION_ID_DATA, DIMENSION_ID_ORGUNIT, DIMENSION_ID_ASSIGNED_CATEGORIES } from '../predefinedDimensions.js';
3
+ import { VIS_TYPE_COLUMN, VIS_TYPE_STACKED_COLUMN, VIS_TYPE_BAR, VIS_TYPE_STACKED_BAR, VIS_TYPE_LINE, VIS_TYPE_AREA, VIS_TYPE_STACKED_AREA, VIS_TYPE_RADAR, VIS_TYPE_GAUGE, VIS_TYPE_PIE, VIS_TYPE_SINGLE_VALUE, VIS_TYPE_YEAR_OVER_YEAR_LINE, VIS_TYPE_YEAR_OVER_YEAR_COLUMN, VIS_TYPE_PIVOT_TABLE, VIS_TYPE_SCATTER, VIS_TYPE_LINE_LIST, VIS_TYPE_OUTLIER_TABLE } from '../visTypes.js';
4
4
  const RULE_PROP_AVAILABLE_AXES = 'availableAxes',
5
5
  RULE_PROP_MAX_DIMS_PER_AXIS = 'maxNumberOfDimsPerAxis',
6
6
  RULE_PROP_MIN_DIMS_PER_AXIS = 'minNumberOfDimsPerAxis',
7
7
  RULE_PROP_MAX_ITEMS_PER_AXIS = 'maxNumberOfItemsPerAxis',
8
+ RULE_PROP_MAX_ITEMS_PER_DIM = 'maxNumberOfItemsPerDim',
8
9
  RULE_PROP_DISALLOWED_DIMS = 'disallowedDims',
9
10
  RULE_PROP_LOCKED_DIMS = 'lockedDims';
10
11
  const defaultRules = {
@@ -82,6 +83,21 @@ const scatterRules = {
82
83
  const lineListRules = {
83
84
  [RULE_PROP_AVAILABLE_AXES]: [AXIS_ID_COLUMNS, AXIS_ID_FILTERS]
84
85
  };
86
+ const outlierTableRules = {
87
+ [RULE_PROP_AVAILABLE_AXES]: [AXIS_ID_COLUMNS],
88
+ [RULE_PROP_MIN_DIMS_PER_AXIS]: {
89
+ [AXIS_ID_COLUMNS]: 3
90
+ },
91
+ [RULE_PROP_MAX_ITEMS_PER_DIM]: {
92
+ [DIMENSION_ID_PERIOD]: 1
93
+ },
94
+ [RULE_PROP_LOCKED_DIMS]: {
95
+ [DIMENSION_ID_DATA]: AXIS_ID_COLUMNS,
96
+ [DIMENSION_ID_PERIOD]: AXIS_ID_COLUMNS,
97
+ [DIMENSION_ID_ORGUNIT]: AXIS_ID_COLUMNS
98
+ },
99
+ [RULE_PROP_DISALLOWED_DIMS]: [DIMENSION_ID_ASSIGNED_CATEGORIES]
100
+ };
85
101
  const visTypeToRules = {
86
102
  [VIS_TYPE_COLUMN]: defaultRules,
87
103
  [VIS_TYPE_STACKED_COLUMN]: defaultRules,
@@ -98,7 +114,8 @@ const visTypeToRules = {
98
114
  [VIS_TYPE_YEAR_OVER_YEAR_COLUMN]: yearOverYearRules,
99
115
  [VIS_TYPE_PIVOT_TABLE]: pivotTableRules,
100
116
  [VIS_TYPE_SCATTER]: scatterRules,
101
- [VIS_TYPE_LINE_LIST]: lineListRules
117
+ [VIS_TYPE_LINE_LIST]: lineListRules,
118
+ [VIS_TYPE_OUTLIER_TABLE]: outlierTableRules
102
119
  };
103
120
  const getRulesByVisType = visType => {
104
121
  const rules = visTypeToRules[visType];
@@ -113,6 +130,7 @@ const getRulesByVisType = visType => {
113
130
  export const getAvailableAxesByVisType = visType => getRulesByVisType(visType)[RULE_PROP_AVAILABLE_AXES] || [];
114
131
  export const getMaxNumberOfDimsPerAxisByVisType = visType => getRulesByVisType(visType)[RULE_PROP_MAX_DIMS_PER_AXIS] || {};
115
132
  export const getMinNumberOfDimsPerAxisByVisType = visType => getRulesByVisType(visType)[RULE_PROP_MIN_DIMS_PER_AXIS] || {};
133
+ export const getMaxNumberOfItemsPerDimByVisType = visType => getRulesByVisType(visType)[RULE_PROP_MAX_ITEMS_PER_DIM] || {};
116
134
  export const getMaxNumberOfItemsPerAxisByVisType = visType => getRulesByVisType(visType)[RULE_PROP_MAX_ITEMS_PER_AXIS] || {};
117
135
  export const getDisallowedDimsByVisType = visType => getRulesByVisType(visType)[RULE_PROP_DISALLOWED_DIMS] || [];
118
136
  export const getLockedDimsByVisType = visType => getRulesByVisType(visType)[RULE_PROP_LOCKED_DIMS] || {};
@@ -126,6 +144,7 @@ export const testResourceAllRuleProps = {
126
144
  MAX_DIMS_PER_AXIS: RULE_PROP_MAX_DIMS_PER_AXIS,
127
145
  MIN_DIMS_PER_AXIS: RULE_PROP_MIN_DIMS_PER_AXIS,
128
146
  MAX_ITEMS_PER_AXIS: RULE_PROP_MAX_ITEMS_PER_AXIS,
147
+ MAX_ITEMS_PER_DIM: RULE_PROP_MAX_ITEMS_PER_DIM,
129
148
  DISALLOWED_DIMS: RULE_PROP_DISALLOWED_DIMS,
130
149
  LOCKED_DIMS: RULE_PROP_LOCKED_DIMS
131
150
  };
@@ -1,4 +1,4 @@
1
- import { getMaxNumberOfItemsPerAxisByVisType, getMaxNumberOfDimsPerAxisByVisType, getMinNumberOfDimsPerAxisByVisType, getLockedDimsByVisType } from './rules.js';
1
+ import { getMaxNumberOfItemsPerDimByVisType, getMaxNumberOfItemsPerAxisByVisType, getMaxNumberOfDimsPerAxisByVisType, getMinNumberOfDimsPerAxisByVisType, getLockedDimsByVisType } from './rules.js';
2
2
 
3
3
  // Selectors
4
4
 
@@ -7,4 +7,5 @@ export const getAxisMaxNumberOfItemsByVisType = (visType, axisId) => getMaxNumbe
7
7
  export const getAxisMaxNumberOfDimsByVisType = (visType, axisId) => getMaxNumberOfDimsPerAxisByVisType(visType)[axisId];
8
8
  export const getAxisMinNumberOfDimsByVisType = (visType, axisId) => getMinNumberOfDimsPerAxisByVisType(visType)[axisId];
9
9
  export const getAxisPerLockedDimByVisType = (visType, dimensionId) => getLockedDimsByVisType(visType)[dimensionId];
10
- export const getAllLockedDimIdsByVisType = visType => Object.keys(getLockedDimsByVisType(visType));
10
+ export const getAllLockedDimIdsByVisType = visType => Object.keys(getLockedDimsByVisType(visType));
11
+ export const getDimMaxNumberOfItemsByVisType = (visType, dimensionId) => getMaxNumberOfItemsPerDimByVisType(visType)[dimensionId];
@@ -1,8 +1,12 @@
1
1
  import { getLockedDimsByVisType } from './rules.js';
2
- import { getAxisMaxNumberOfDimsByVisType, getAxisMaxNumberOfItemsByVisType, getAllLockedDimIdsByVisType } from './rulesHelper.js';
2
+ import { getAxisMaxNumberOfDimsByVisType, getAxisMaxNumberOfItemsByVisType, getDimMaxNumberOfItemsByVisType, getAllLockedDimIdsByVisType } from './rulesHelper.js';
3
3
  export const hasAxisTooManyItemsByVisType = (visType, axisId, numberOfItems) => {
4
4
  const maxNumberOfItemsPerAxis = getAxisMaxNumberOfItemsByVisType(visType, axisId);
5
- return maxNumberOfItemsPerAxis ? numberOfItems > maxNumberOfItemsPerAxis : false;
5
+ return maxNumberOfItemsPerAxis && numberOfItems > maxNumberOfItemsPerAxis;
6
+ };
7
+ export const hasDimensionTooManyItemsByVisType = (visType, dimensionId, numberOfItems) => {
8
+ const maxNumberOfItemsPerDimension = getDimMaxNumberOfItemsByVisType(visType, dimensionId);
9
+ return maxNumberOfItemsPerDimension && numberOfItems > maxNumberOfItemsPerDimension;
6
10
  };
7
11
  export const isDimensionLockedByVisType = (visType, dimensionId) => getAllLockedDimIdsByVisType(visType).includes(dimensionId);
8
12
  export const isAxisFullByVisType = (visType, axisId, axisDimensionsCount) => axisDimensionsCount >= getAxisMaxNumberOfDimsByVisType(visType, axisId);