@dhis2/analytics 26.8.6 → 26.8.7

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.
@@ -4,6 +4,7 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.PivotTableValueCell = void 0;
7
+ var _d2I18n = _interopRequireDefault(require("@dhis2/d2-i18n"));
7
8
  var _propTypes = _interopRequireDefault(require("prop-types"));
8
9
  var _react = _interopRequireWildcard(require("react"));
9
10
  var _applyLegendSet = require("../../modules/pivotTable/applyLegendSet.js");
@@ -16,7 +17,7 @@ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "functio
16
17
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
17
18
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
18
19
  const PivotTableValueCell = _ref => {
19
- var _cellContent$rendered;
20
+ var _cellContent$titleVal, _cellContent$rendered;
20
21
  let {
21
22
  row,
22
23
  column,
@@ -54,7 +55,10 @@ const PivotTableValueCell = _ref => {
54
55
  return /*#__PURE__*/_react.default.createElement(_PivotTableCell.PivotTableCell, {
55
56
  key: column,
56
57
  classes: classes,
57
- title: cellContent.renderedValue,
58
+ title: (_cellContent$titleVal = cellContent.titleValue) !== null && _cellContent$titleVal !== void 0 ? _cellContent$titleVal : _d2I18n.default.t('Value: {{value}}', {
59
+ value: cellContent.renderedValue,
60
+ nsSeparator: '^^'
61
+ }),
58
62
  style: style,
59
63
  onClick: isClickable ? onClick : undefined,
60
64
  ref: cellRef,
@@ -9,9 +9,9 @@ var _pivotTableConstants = require("../../../modules/pivotTable/pivotTableConsta
9
9
  const table = [`div.pivot-table-container.jsx-3572446209{font-family:'Roboto',Arial,sans-serif;overflow:auto;color:${_ui.colors.grey900};}`, `div.pivot-table-container.jsx-3572446209 table{border-spacing:0;white-space:nowrap;box-sizing:border-box;text-align:center;border:1px solid ${_pivotTableConstants.BORDER_COLOR};border-width:1px 1px 0 0;}`, "div.pivot-table-container.jsx-3572446209 table.fixed-headers{border-width:0 0 0 1px;}", "div.pivot-table-container.jsx-3572446209 table.fixed-headers tr th,div.pivot-table-container.jsx-3572446209 table.fixed-headers tr td{border-width:0 1px 1px 0;}", "div.pivot-table-container.jsx-3572446209 table.fixed-column-headers{border-width:0 1px 0 0;}", "div.pivot-table-container.jsx-3572446209 table.fixed-column-headers tr th,div.pivot-table-container.jsx-3572446209 table.fixed-column-headers tr td{border-width:0 0 1px 1px;}", `div.pivot-table-container.jsx-3572446209 table.fixed-headers thead tr:first-of-type th,div.pivot-table-container.jsx-3572446209 table.fixed-column-headers thead tr:first-of-type th{border-top:1px solid ${_pivotTableConstants.BORDER_COLOR};}`, "div.pivot-table-container.jsx-3572446209 table.fixed-row-headers{border-width:0 0 1px 1px;}", "div.pivot-table-container.jsx-3572446209 table.fixed-row-headers tr th,div.pivot-table-container.jsx-3572446209 table.fixed-row-headers tr td{border-width:1px 1px 0 0;}"];
10
10
  exports.table = table;
11
11
  table.__hash = "3572446209";
12
- const cell = [`td.jsx-3234356038,th.jsx-3234356038{box-sizing:border-box;font-weight:normal;overflow:hidden;text-overflow:ellipsis;border:1px solid ${_pivotTableConstants.BORDER_COLOR};border-width:0 0 1px 1px;cursor:default;}`, "th.fixed-header.jsx-3234356038{position:-webkit-sticky;position:sticky;z-index:1;top:0;left:0;}", `.fontsize-SMALL.jsx-3234356038{font-size:${_pivotTableConstants.FONT_SIZE_SMALL}px;line-height:${_pivotTableConstants.FONT_SIZE_SMALL}px;}`, `.fontsize-NORMAL.jsx-3234356038{font-size:${_pivotTableConstants.FONT_SIZE_NORMAL}px;line-height:${_pivotTableConstants.FONT_SIZE_NORMAL}px;}`, `.fontsize-LARGE.jsx-3234356038{font-size:${_pivotTableConstants.FONT_SIZE_LARGE}px;line-height:${_pivotTableConstants.FONT_SIZE_LARGE}px;}`, `.displaydensity-COMPACT.jsx-3234356038{padding:${_pivotTableConstants.DISPLAY_DENSITY_PADDING_COMPACT}px;}`, `.displaydensity-NORMAL.jsx-3234356038{padding:${_pivotTableConstants.DISPLAY_DENSITY_PADDING_NORMAL}px;}`, `.displaydensity-COMFORTABLE.jsx-3234356038{padding:${_pivotTableConstants.DISPLAY_DENSITY_PADDING_COMFORTABLE}px;}`, ".column-header.jsx-3234356038{background-color:#dae6f8;}", "div.column-header-inner.jsx-3234356038{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;}", ".title-cell.jsx-3234356038{font-weight:bold;background-color:#cddaed;padding:0;}", ".title-cell-content.jsx-3234356038{text-align:center;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}", `.title-cell.displaydensity-COMPACT.jsx-3234356038>.title-cell-content.jsx-3234356038{padding:${_pivotTableConstants.DISPLAY_DENSITY_PADDING_COMPACT}px;}`, `.title-cell.displaydensity-NORMAL.jsx-3234356038>.title-cell-content.jsx-3234356038{padding:${_pivotTableConstants.DISPLAY_DENSITY_PADDING_NORMAL}px;}`, `.title-cell.displaydensity-COMFORTABLE.jsx-3234356038>.title-cell-content.jsx-3234356038{padding:${_pivotTableConstants.DISPLAY_DENSITY_PADDING_COMFORTABLE}px;}`, ".row-header.jsx-3234356038{background-color:#dae6f8;}", ".row-header-hierarchy.jsx-3234356038{text-align:left;}", ".empty-header.jsx-3234356038{background-color:#cddaed;}", ".total-header.jsx-3234356038{background-color:#bac6d8;}", ".value.jsx-3234356038{background-color:#ffffff;text-align:left;}", ".NUMBER.jsx-3234356038,.INTEGER.jsx-3234356038,.INTEGER_POSITIVE.jsx-3234356038,.INTEGER_NEGATIVE.jsx-3234356038,.INTEGER_ZERO_OR_POSITIVE.jsx-3234356038,.UNIT_INTERVAL.jsx-3234356038,.PERCENTAGE.jsx-3234356038,.BOOLEAN.jsx-3234356038,.TRUE_ONLY.jsx-3234356038{text-align:right;}", ".clickable.jsx-3234356038{cursor:pointer;}", ".value.jsx-3234356038:hover{background-color:#f3f3f3;}", ".subtotal.jsx-3234356038{background-color:#f4f4f4;}", ".total.jsx-3234356038{background-color:#d8d8d8;}", ".column-header-label.jsx-3234356038{overflow:hidden;text-overflow:ellipsis;}"];
12
+ const cell = [`td.jsx-2444037071,th.jsx-2444037071{box-sizing:border-box;font-weight:normal;overflow:hidden;text-overflow:ellipsis;border:1px solid ${_pivotTableConstants.BORDER_COLOR};border-width:0 0 1px 1px;cursor:default;}`, "th.fixed-header.jsx-2444037071{position:-webkit-sticky;position:sticky;z-index:1;top:0;left:0;}", `.fontsize-SMALL.jsx-2444037071{font-size:${_pivotTableConstants.FONT_SIZE_SMALL}px;line-height:${_pivotTableConstants.FONT_SIZE_SMALL}px;}`, `.fontsize-NORMAL.jsx-2444037071{font-size:${_pivotTableConstants.FONT_SIZE_NORMAL}px;line-height:${_pivotTableConstants.FONT_SIZE_NORMAL}px;}`, `.fontsize-LARGE.jsx-2444037071{font-size:${_pivotTableConstants.FONT_SIZE_LARGE}px;line-height:${_pivotTableConstants.FONT_SIZE_LARGE}px;}`, `.displaydensity-COMPACT.jsx-2444037071{padding:${_pivotTableConstants.DISPLAY_DENSITY_PADDING_COMPACT}px;}`, `.displaydensity-NORMAL.jsx-2444037071{padding:${_pivotTableConstants.DISPLAY_DENSITY_PADDING_NORMAL}px;}`, `.displaydensity-COMFORTABLE.jsx-2444037071{padding:${_pivotTableConstants.DISPLAY_DENSITY_PADDING_COMFORTABLE}px;}`, ".column-header.jsx-2444037071{background-color:#dae6f8;}", "div.column-header-inner.jsx-2444037071{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;}", ".title-cell.jsx-2444037071{font-weight:bold;background-color:#cddaed;padding:0;}", ".title-cell-content.jsx-2444037071{text-align:center;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}", `.title-cell.displaydensity-COMPACT.jsx-2444037071>.title-cell-content.jsx-2444037071{padding:${_pivotTableConstants.DISPLAY_DENSITY_PADDING_COMPACT}px;}`, `.title-cell.displaydensity-NORMAL.jsx-2444037071>.title-cell-content.jsx-2444037071{padding:${_pivotTableConstants.DISPLAY_DENSITY_PADDING_NORMAL}px;}`, `.title-cell.displaydensity-COMFORTABLE.jsx-2444037071>.title-cell-content.jsx-2444037071{padding:${_pivotTableConstants.DISPLAY_DENSITY_PADDING_COMFORTABLE}px;}`, ".row-header.jsx-2444037071{background-color:#dae6f8;}", ".row-header-hierarchy.jsx-2444037071{text-align:left;}", ".empty-header.jsx-2444037071{background-color:#cddaed;}", ".total-header.jsx-2444037071{background-color:#bac6d8;}", ".value.jsx-2444037071{background-color:#ffffff;text-align:left;}", ".NUMBER.jsx-2444037071,.INTEGER.jsx-2444037071,.INTEGER_POSITIVE.jsx-2444037071,.INTEGER_NEGATIVE.jsx-2444037071,.INTEGER_ZERO_OR_POSITIVE.jsx-2444037071,.UNIT_INTERVAL.jsx-2444037071,.PERCENTAGE.jsx-2444037071,.BOOLEAN.jsx-2444037071,.TRUE_ONLY.jsx-2444037071{text-align:right;}", `.N_A.jsx-2444037071{text-align:center;color:${_ui.colors.grey600};}`, ".clickable.jsx-2444037071{cursor:pointer;}", ".value.jsx-2444037071:hover{background-color:#f3f3f3;}", ".subtotal.jsx-2444037071{background-color:#f4f4f4;}", ".total.jsx-2444037071{background-color:#d8d8d8;}", ".column-header-label.jsx-2444037071{overflow:hidden;text-overflow:ellipsis;}"];
13
13
  exports.cell = cell;
14
- cell.__hash = "3234356038";
14
+ cell.__hash = "2444037071";
15
15
  const sortIcon = [`.fontsize-SMALL.jsx-2877616992{height:${_pivotTableConstants.FONT_SIZE_SMALL}px;margin-bottom:1px;margin-left:5px;}`, `.fontsize-NORMAL.jsx-2877616992{height:${_pivotTableConstants.FONT_SIZE_NORMAL}px;max-height:11px;margin-bottom:2px;margin-left:6px;}`, `.fontsize-LARGE.jsx-2877616992{height:${_pivotTableConstants.FONT_SIZE_LARGE}px;margin-bottom:2px;margin-left:7px;}`];
16
16
  exports.sortIcon = sortIcon;
17
17
  sortIcon.__hash = "2877616992";
@@ -267,6 +267,7 @@
267
267
  "Six-months": "Six-months",
268
268
  "Financial Years": "Financial Years",
269
269
  "Years": "Years",
270
+ "Value: {{value}}": "Value: {{value}}",
270
271
  "Bold text": "Bold text",
271
272
  "Italic text": "Italic text",
272
273
  "Link to a URL": "Link to a URL",
@@ -357,6 +358,7 @@
357
358
  "{{thresholdFactor}} × Modified Z-score high": "{{thresholdFactor}} × Modified Z-score high",
358
359
  "{{thresholdFactor}} × Z-score low": "{{thresholdFactor}} × Z-score low",
359
360
  "{{thresholdFactor}} × Z-score high": "{{thresholdFactor}} × Z-score high",
361
+ "Not applicable": "Not applicable",
360
362
  "Data": "Data",
361
363
  "Organisation unit": "Organisation unit",
362
364
  "Assigned Categories": "Assigned Categories",
@@ -160,7 +160,7 @@ const applyTotalAggregationType = (_ref2, overrideTotalAggregationType) => {
160
160
  } = _ref2;
161
161
  switch (overrideTotalAggregationType || totalAggregationType) {
162
162
  case _pivotTableConstants.AGGREGATE_TYPE_NA:
163
- return 'N/A';
163
+ return _pivotTableConstants.VALUE_NA;
164
164
  case _pivotTableConstants.AGGREGATE_TYPE_AVERAGE:
165
165
  return (numerator || value) * multiplier / (denominator * divisor || 1);
166
166
  case _pivotTableConstants.AGGREGATE_TYPE_SUM:
@@ -265,15 +265,29 @@ class PivotTableEngine {
265
265
  rawCell.rawValue = rawValue;
266
266
  rawCell.renderedValue = renderedValue;
267
267
  }
268
+ if ([_pivotTableConstants.CELL_TYPE_TOTAL, _pivotTableConstants.CELL_TYPE_SUBTOTAL].includes(rawCell.cellType) && rawCell.rawValue === _pivotTableConstants.AGGREGATE_TYPE_NA) {
269
+ rawCell.titleValue = _d2I18n.default.t('Not applicable');
270
+ }
268
271
  if (this.options.cumulativeValues) {
272
+ let titleValue;
273
+ if (this.data[row] && this.data[row][column]) {
274
+ const dataRow = this.data[row][column];
275
+ const rawValue = cellType === _pivotTableConstants.CELL_TYPE_VALUE ? dataRow[this.dimensionLookup.dataHeaders.value] : dataRow.value;
276
+ titleValue = _d2I18n.default.t('Value: {{value}}', {
277
+ value: (0, _renderValue.renderValue)(rawValue, valueType, this.visualization),
278
+ nsSeparator: '^^'
279
+ });
280
+ }
269
281
  const cumulativeValue = this.getCumulative({
270
282
  row,
271
283
  column
272
284
  });
273
285
  if (cumulativeValue !== undefined && cumulativeValue !== null) {
274
- // force to NUMBER for accumulated values
275
- rawCell.valueType = valueType === undefined || valueType === null ? _valueTypes.VALUE_TYPE_NUMBER : valueType;
286
+ // force to TEXT for N/A (accumulated) values
287
+ // force to NUMBER for accumulated values if no valueType present
288
+ rawCell.valueType = cumulativeValue === _pivotTableConstants.VALUE_NA ? _pivotTableConstants.VALUE_TYPE_NA : valueType === undefined || valueType === null ? _valueTypes.VALUE_TYPE_NUMBER : valueType;
276
289
  rawCell.empty = false;
290
+ rawCell.titleValue = titleValue;
277
291
  rawCell.rawValue = cumulativeValue;
278
292
  rawCell.renderedValue = (0, _renderValue.renderValue)(cumulativeValue, valueType, this.visualization);
279
293
  }
@@ -372,15 +386,12 @@ class PivotTableEngine {
372
386
  return undefined;
373
387
  }
374
388
  const cellValue = this.data[row][column];
389
+
390
+ // empty cell
375
391
  if (!cellValue) {
376
- // Empty cell
377
- // The cell still needs to get the valueType to render correctly 0 and cumulative values
378
- return {
379
- valueType: _valueTypes.VALUE_TYPE_NUMBER,
380
- totalAggregationType: _pivotTableConstants.AGGREGATE_TYPE_SUM
381
- };
392
+ return undefined;
382
393
  }
383
- if (!Array.isArray(cellValue)) {
394
+ if (cellValue && !Array.isArray(cellValue)) {
384
395
  // This is a total cell
385
396
  return {
386
397
  valueType: cellValue.valueType,
@@ -543,19 +554,26 @@ class PivotTableEngine {
543
554
  } else {
544
555
  totalCell.totalAggregationType = currentAggType;
545
556
  }
546
- const currentValueType = dxDimension === null || dxDimension === void 0 ? void 0 : dxDimension.valueType;
557
+
558
+ // Force value type of total cells to NUMBER for value cells with numeric or boolean types.
559
+ // This is to simplify the code below where we compare the previous value type.
560
+ // All numeric/boolean value types use the same style for rendering the total cell (right aligned content)
561
+ // and using NUMBER for the total cell is enough for that.
562
+ // (see DHIS2-9155)
563
+ const currentValueType = (0, _valueTypes.isNumericValueType)(dxDimension === null || dxDimension === void 0 ? void 0 : dxDimension.valueType) || (0, _valueTypes.isBooleanValueType)(dxDimension === null || dxDimension === void 0 ? void 0 : dxDimension.valueType) ? _valueTypes.VALUE_TYPE_NUMBER : dxDimension === null || dxDimension === void 0 ? void 0 : dxDimension.valueType;
547
564
  const previousValueType = totalCell.valueType;
548
565
  if (previousValueType && currentValueType !== previousValueType) {
549
- totalCell.valueType = _pivotTableConstants.AGGREGATE_TYPE_NA;
566
+ totalCell.valueType = _pivotTableConstants.VALUE_TYPE_NA;
550
567
  } else {
551
568
  totalCell.valueType = currentValueType;
552
569
  }
553
570
 
554
- // compute subtotals and totals for all numeric and boolean value types
555
- // in that case, force value type of subtotal and total cells to NUMBER to format them correctly
571
+ // Compute totals for all numeric and boolean value types only.
572
+ // In practice valueType here is NUMBER (see the comment above).
573
+ // When is not, it means there is some value cell with a valueType other than numeric/boolean,
574
+ // the total should not be computed then.
556
575
  // (see DHIS2-9155)
557
- if ((0, _valueTypes.isNumericValueType)(dxDimension === null || dxDimension === void 0 ? void 0 : dxDimension.valueType) || (0, _valueTypes.isBooleanValueType)(dxDimension === null || dxDimension === void 0 ? void 0 : dxDimension.valueType)) {
558
- totalCell.valueType = _valueTypes.VALUE_TYPE_NUMBER;
576
+ if ((0, _valueTypes.isNumericValueType)(totalCell.valueType)) {
559
577
  dataFields.forEach(field => {
560
578
  const headerIndex = this.dimensionLookup.dataHeaders[field];
561
579
  const value = (0, _parseValue.parseValue)(dataRow[headerIndex]);
@@ -649,6 +667,17 @@ class PivotTableEngine {
649
667
  }
650
668
  }
651
669
  }
670
+ computeOverrideTotalAggregationType(totalCell, visualization) {
671
+ // Avoid undefined on total cells with valueTypes that cannot be totalized.
672
+ // This happens for example when a column/row has all value cells of type TEXT.
673
+ if (!((0, _valueTypes.isNumericValueType)(totalCell.valueType) || (0, _valueTypes.isBooleanValueType)(totalCell.valueType))) {
674
+ return _pivotTableConstants.AGGREGATE_TYPE_NA;
675
+ }
676
+
677
+ // DHIS2-15698: do not override total aggregation type when numberType option is not present
678
+ // (numberType option default is VALUE)
679
+ return visualization.numberType && visualization.numberType !== _pivotTableConstants.NUMBER_TYPE_VALUE && _pivotTableConstants.AGGREGATE_TYPE_SUM;
680
+ }
652
681
  finalizeTotal(_ref11) {
653
682
  let {
654
683
  row,
@@ -659,10 +688,12 @@ class PivotTableEngine {
659
688
  }
660
689
  const totalCell = this.data[row][column];
661
690
  if (totalCell && totalCell.count) {
662
- totalCell.value = applyTotalAggregationType(totalCell,
663
- // DHIS2-15698: do not override total aggregation type when numberType option is not present
664
- // (numberType option default is VALUE)
665
- this.visualization.numberType && this.visualization.numberType !== _pivotTableConstants.NUMBER_TYPE_VALUE && _pivotTableConstants.AGGREGATE_TYPE_SUM);
691
+ totalCell.value = applyTotalAggregationType(totalCell, this.computeOverrideTotalAggregationType(totalCell, this.visualization));
692
+
693
+ // override valueType for styling cells with N/A value
694
+ if (totalCell.value === _pivotTableConstants.AGGREGATE_TYPE_NA) {
695
+ totalCell.valueType = _pivotTableConstants.VALUE_TYPE_NA;
696
+ }
666
697
  this.adaptiveClippingController.add({
667
698
  row,
668
699
  column
@@ -763,10 +794,14 @@ class PivotTableEngine {
763
794
  column
764
795
  });
765
796
  const valueType = (dxDimension === null || dxDimension === void 0 ? void 0 : dxDimension.valueType) || _valueTypes.VALUE_TYPE_TEXT;
797
+ const totalAggregationType = dxDimension === null || dxDimension === void 0 ? void 0 : dxDimension.totalAggregationType;
766
798
 
767
- // only accumulate numeric values
768
- // accumulating text values does not make sense
769
- if (valueType === _valueTypes.VALUE_TYPE_NUMBER) {
799
+ // only accumulate numeric (except for PERCENTAGE and UNIT_INTERVAL) and boolean values
800
+ // accumulating other value types like text values does not make sense
801
+ if ((0, _valueTypes.isCumulativeValueType)(valueType) && totalAggregationType === _pivotTableConstants.AGGREGATE_TYPE_SUM) {
802
+ // initialise to 0 for cumulative types
803
+ // (||= is not transformed correctly in Babel with the current setup)
804
+ acc || (acc = 0);
770
805
  if (this.data[row] && this.data[row][column]) {
771
806
  const dataRow = this.data[row][column];
772
807
  const rawValue = cellType === _pivotTableConstants.CELL_TYPE_VALUE ? dataRow[this.dimensionLookup.dataHeaders.value] : dataRow.value;
@@ -775,7 +810,7 @@ class PivotTableEngine {
775
810
  this.accumulators.rows[row][column] = acc;
776
811
  }
777
812
  return acc;
778
- }, 0);
813
+ }, '');
779
814
  });
780
815
  } else {
781
816
  this.accumulators = {
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.WRAPPED_TEXT_LINE_HEIGHT = exports.WRAPPED_TEXT_JUSTIFY_BUFFER = exports.SORT_ORDER_DESCENDING = exports.SORT_ORDER_ASCENDING = exports.NUMBER_TYPE_VALUE = exports.NUMBER_TYPE_ROW_PERCENTAGE = exports.NUMBER_TYPE_COLUMN_PERCENTAGE = exports.FONT_SIZE_SMALL = exports.FONT_SIZE_OPTION_SMALL = exports.FONT_SIZE_OPTION_NORMAL = exports.FONT_SIZE_OPTION_LARGE = exports.FONT_SIZE_NORMAL = exports.FONT_SIZE_LARGE = exports.DISPLAY_DENSITY_PADDING_NORMAL = exports.DISPLAY_DENSITY_PADDING_COMPACT = exports.DISPLAY_DENSITY_PADDING_COMFORTABLE = exports.DISPLAY_DENSITY_OPTION_NORMAL = exports.DISPLAY_DENSITY_OPTION_COMPACT = exports.DISPLAY_DENSITY_OPTION_COMFORTABLE = exports.CLIPPED_CELL_MIN_SIZE = exports.CLIPPED_CELL_MAX_SIZE = exports.CLIPPED_AXIS_PARTITION_SIZE_PX = exports.CELL_TYPE_VALUE = exports.CELL_TYPE_TOTAL = exports.CELL_TYPE_SUBTOTAL = exports.BORDER_COLOR = exports.AGGREGATE_TYPE_SUM = exports.AGGREGATE_TYPE_NA = exports.AGGREGATE_TYPE_AVERAGE = void 0;
6
+ exports.WRAPPED_TEXT_LINE_HEIGHT = exports.WRAPPED_TEXT_JUSTIFY_BUFFER = exports.VALUE_TYPE_NA = exports.VALUE_NA = exports.SORT_ORDER_DESCENDING = exports.SORT_ORDER_ASCENDING = exports.NUMBER_TYPE_VALUE = exports.NUMBER_TYPE_ROW_PERCENTAGE = exports.NUMBER_TYPE_COLUMN_PERCENTAGE = exports.FONT_SIZE_SMALL = exports.FONT_SIZE_OPTION_SMALL = exports.FONT_SIZE_OPTION_NORMAL = exports.FONT_SIZE_OPTION_LARGE = exports.FONT_SIZE_NORMAL = exports.FONT_SIZE_LARGE = exports.DISPLAY_DENSITY_PADDING_NORMAL = exports.DISPLAY_DENSITY_PADDING_COMPACT = exports.DISPLAY_DENSITY_PADDING_COMFORTABLE = exports.DISPLAY_DENSITY_OPTION_NORMAL = exports.DISPLAY_DENSITY_OPTION_COMPACT = exports.DISPLAY_DENSITY_OPTION_COMFORTABLE = exports.CLIPPED_CELL_MIN_SIZE = exports.CLIPPED_CELL_MAX_SIZE = exports.CLIPPED_AXIS_PARTITION_SIZE_PX = exports.CELL_TYPE_VALUE = exports.CELL_TYPE_TOTAL = exports.CELL_TYPE_SUBTOTAL = exports.BORDER_COLOR = exports.AGGREGATE_TYPE_SUM = exports.AGGREGATE_TYPE_NA = exports.AGGREGATE_TYPE_AVERAGE = void 0;
7
7
  const SORT_ORDER_ASCENDING = 1;
8
8
  exports.SORT_ORDER_ASCENDING = SORT_ORDER_ASCENDING;
9
9
  const SORT_ORDER_DESCENDING = -1;
@@ -20,6 +20,8 @@ const AGGREGATE_TYPE_AVERAGE = 'AVERAGE';
20
20
  exports.AGGREGATE_TYPE_AVERAGE = AGGREGATE_TYPE_AVERAGE;
21
21
  const AGGREGATE_TYPE_NA = 'N/A';
22
22
  exports.AGGREGATE_TYPE_NA = AGGREGATE_TYPE_NA;
23
+ const VALUE_TYPE_NA = 'N_A'; // this ends up as CSS class and / is problematic
24
+ exports.VALUE_TYPE_NA = VALUE_TYPE_NA;
23
25
  const NUMBER_TYPE_VALUE = 'VALUE';
24
26
  exports.NUMBER_TYPE_VALUE = NUMBER_TYPE_VALUE;
25
27
  const NUMBER_TYPE_ROW_PERCENTAGE = 'ROW_PERCENTAGE';
@@ -61,4 +63,6 @@ exports.WRAPPED_TEXT_JUSTIFY_BUFFER = WRAPPED_TEXT_JUSTIFY_BUFFER;
61
63
  const WRAPPED_TEXT_LINE_HEIGHT = 1.0;
62
64
  exports.WRAPPED_TEXT_LINE_HEIGHT = WRAPPED_TEXT_LINE_HEIGHT;
63
65
  const CLIPPED_AXIS_PARTITION_SIZE_PX = 1000;
64
- exports.CLIPPED_AXIS_PARTITION_SIZE_PX = CLIPPED_AXIS_PARTITION_SIZE_PX;
66
+ exports.CLIPPED_AXIS_PARTITION_SIZE_PX = CLIPPED_AXIS_PARTITION_SIZE_PX;
67
+ const VALUE_NA = 'N/A';
68
+ exports.VALUE_NA = VALUE_NA;
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.isNumericValueType = exports.isBooleanValueType = exports.VALUE_TYPE_USERNAME = exports.VALUE_TYPE_URL = exports.VALUE_TYPE_UNIT_INTERVAL = exports.VALUE_TYPE_TRUE_ONLY = exports.VALUE_TYPE_TIME = exports.VALUE_TYPE_TEXT = exports.VALUE_TYPE_PHONE_NUMBER = exports.VALUE_TYPE_PERCENTAGE = exports.VALUE_TYPE_ORGANISATION_UNIT = exports.VALUE_TYPE_NUMBER = exports.VALUE_TYPE_LONG_TEXT = exports.VALUE_TYPE_LETTER = exports.VALUE_TYPE_INTEGER_ZERO_OR_POSITIVE = exports.VALUE_TYPE_INTEGER_POSITIVE = exports.VALUE_TYPE_INTEGER_NEGATIVE = exports.VALUE_TYPE_INTEGER = exports.VALUE_TYPE_EMAIL = exports.VALUE_TYPE_DATETIME = exports.VALUE_TYPE_DATE = exports.VALUE_TYPE_BOOLEAN = exports.VALUE_TYPE_AGE = void 0;
6
+ exports.isNumericValueType = exports.isCumulativeValueType = exports.isBooleanValueType = exports.VALUE_TYPE_USERNAME = exports.VALUE_TYPE_URL = exports.VALUE_TYPE_UNIT_INTERVAL = exports.VALUE_TYPE_TRUE_ONLY = exports.VALUE_TYPE_TIME = exports.VALUE_TYPE_TEXT = exports.VALUE_TYPE_PHONE_NUMBER = exports.VALUE_TYPE_PERCENTAGE = exports.VALUE_TYPE_ORGANISATION_UNIT = exports.VALUE_TYPE_NUMBER = exports.VALUE_TYPE_LONG_TEXT = exports.VALUE_TYPE_LETTER = exports.VALUE_TYPE_INTEGER_ZERO_OR_POSITIVE = exports.VALUE_TYPE_INTEGER_POSITIVE = exports.VALUE_TYPE_INTEGER_NEGATIVE = exports.VALUE_TYPE_INTEGER = exports.VALUE_TYPE_EMAIL = exports.VALUE_TYPE_DATETIME = exports.VALUE_TYPE_DATE = exports.VALUE_TYPE_BOOLEAN = exports.VALUE_TYPE_AGE = void 0;
7
7
  /* These types match the types in the backend
8
8
  https://github.com/dhis2/dhis2-core/blob/master/dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/ValueType.java
9
9
  */
@@ -52,6 +52,9 @@ const VALUE_TYPE_AGE = 'AGE';
52
52
  exports.VALUE_TYPE_AGE = VALUE_TYPE_AGE;
53
53
  const NUMERIC_VALUE_TYPES = [VALUE_TYPE_NUMBER, VALUE_TYPE_UNIT_INTERVAL, VALUE_TYPE_PERCENTAGE, VALUE_TYPE_INTEGER, VALUE_TYPE_INTEGER_POSITIVE, VALUE_TYPE_INTEGER_NEGATIVE, VALUE_TYPE_INTEGER_ZERO_OR_POSITIVE];
54
54
  const BOOLEAN_VALUE_TYPES = [VALUE_TYPE_BOOLEAN, VALUE_TYPE_TRUE_ONLY];
55
+ const CUMULATIVE_VALUE_TYPES = [VALUE_TYPE_NUMBER, VALUE_TYPE_INTEGER, VALUE_TYPE_INTEGER_POSITIVE, VALUE_TYPE_INTEGER_NEGATIVE, VALUE_TYPE_INTEGER_ZERO_OR_POSITIVE, ...BOOLEAN_VALUE_TYPES];
56
+ const isCumulativeValueType = type => CUMULATIVE_VALUE_TYPES.includes(type);
57
+ exports.isCumulativeValueType = isCumulativeValueType;
55
58
  const isNumericValueType = type => NUMERIC_VALUE_TYPES.includes(type);
56
59
  exports.isNumericValueType = isNumericValueType;
57
60
  const isBooleanValueType = type => BOOLEAN_VALUE_TYPES.includes(type);
@@ -1,3 +1,4 @@
1
+ import i18n from '@dhis2/d2-i18n';
1
2
  import PropTypes from 'prop-types';
2
3
  import React, { useRef } from 'react';
3
4
  import { applyLegendSet } from '../../modules/pivotTable/applyLegendSet.js';
@@ -7,7 +8,7 @@ import { PivotTableCell } from './PivotTableCell.js';
7
8
  import { PivotTableEmptyCell } from './PivotTableEmptyCell.js';
8
9
  import { usePivotTableEngine } from './PivotTableEngineContext.js';
9
10
  export const PivotTableValueCell = _ref => {
10
- var _cellContent$rendered;
11
+ var _cellContent$titleVal, _cellContent$rendered;
11
12
  let {
12
13
  row,
13
14
  column,
@@ -45,7 +46,10 @@ export const PivotTableValueCell = _ref => {
45
46
  return /*#__PURE__*/React.createElement(PivotTableCell, {
46
47
  key: column,
47
48
  classes: classes,
48
- title: cellContent.renderedValue,
49
+ title: (_cellContent$titleVal = cellContent.titleValue) !== null && _cellContent$titleVal !== void 0 ? _cellContent$titleVal : i18n.t('Value: {{value}}', {
50
+ value: cellContent.renderedValue,
51
+ nsSeparator: '^^'
52
+ }),
49
53
  style: style,
50
54
  onClick: isClickable ? onClick : undefined,
51
55
  ref: cellRef,
@@ -2,7 +2,7 @@ import { colors } from '@dhis2/ui';
2
2
  import { BORDER_COLOR, DISPLAY_DENSITY_PADDING_COMPACT, DISPLAY_DENSITY_PADDING_NORMAL, DISPLAY_DENSITY_PADDING_COMFORTABLE, FONT_SIZE_SMALL, FONT_SIZE_NORMAL, FONT_SIZE_LARGE } from '../../../modules/pivotTable/pivotTableConstants.js';
3
3
  export const table = [`div.pivot-table-container.jsx-3572446209{font-family:'Roboto',Arial,sans-serif;overflow:auto;color:${colors.grey900};}`, `div.pivot-table-container.jsx-3572446209 table{border-spacing:0;white-space:nowrap;box-sizing:border-box;text-align:center;border:1px solid ${BORDER_COLOR};border-width:1px 1px 0 0;}`, "div.pivot-table-container.jsx-3572446209 table.fixed-headers{border-width:0 0 0 1px;}", "div.pivot-table-container.jsx-3572446209 table.fixed-headers tr th,div.pivot-table-container.jsx-3572446209 table.fixed-headers tr td{border-width:0 1px 1px 0;}", "div.pivot-table-container.jsx-3572446209 table.fixed-column-headers{border-width:0 1px 0 0;}", "div.pivot-table-container.jsx-3572446209 table.fixed-column-headers tr th,div.pivot-table-container.jsx-3572446209 table.fixed-column-headers tr td{border-width:0 0 1px 1px;}", `div.pivot-table-container.jsx-3572446209 table.fixed-headers thead tr:first-of-type th,div.pivot-table-container.jsx-3572446209 table.fixed-column-headers thead tr:first-of-type th{border-top:1px solid ${BORDER_COLOR};}`, "div.pivot-table-container.jsx-3572446209 table.fixed-row-headers{border-width:0 0 1px 1px;}", "div.pivot-table-container.jsx-3572446209 table.fixed-row-headers tr th,div.pivot-table-container.jsx-3572446209 table.fixed-row-headers tr td{border-width:1px 1px 0 0;}"];
4
4
  table.__hash = "3572446209";
5
- export const cell = [`td.jsx-3234356038,th.jsx-3234356038{box-sizing:border-box;font-weight:normal;overflow:hidden;text-overflow:ellipsis;border:1px solid ${BORDER_COLOR};border-width:0 0 1px 1px;cursor:default;}`, "th.fixed-header.jsx-3234356038{position:-webkit-sticky;position:sticky;z-index:1;top:0;left:0;}", `.fontsize-SMALL.jsx-3234356038{font-size:${FONT_SIZE_SMALL}px;line-height:${FONT_SIZE_SMALL}px;}`, `.fontsize-NORMAL.jsx-3234356038{font-size:${FONT_SIZE_NORMAL}px;line-height:${FONT_SIZE_NORMAL}px;}`, `.fontsize-LARGE.jsx-3234356038{font-size:${FONT_SIZE_LARGE}px;line-height:${FONT_SIZE_LARGE}px;}`, `.displaydensity-COMPACT.jsx-3234356038{padding:${DISPLAY_DENSITY_PADDING_COMPACT}px;}`, `.displaydensity-NORMAL.jsx-3234356038{padding:${DISPLAY_DENSITY_PADDING_NORMAL}px;}`, `.displaydensity-COMFORTABLE.jsx-3234356038{padding:${DISPLAY_DENSITY_PADDING_COMFORTABLE}px;}`, ".column-header.jsx-3234356038{background-color:#dae6f8;}", "div.column-header-inner.jsx-3234356038{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;}", ".title-cell.jsx-3234356038{font-weight:bold;background-color:#cddaed;padding:0;}", ".title-cell-content.jsx-3234356038{text-align:center;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}", `.title-cell.displaydensity-COMPACT.jsx-3234356038>.title-cell-content.jsx-3234356038{padding:${DISPLAY_DENSITY_PADDING_COMPACT}px;}`, `.title-cell.displaydensity-NORMAL.jsx-3234356038>.title-cell-content.jsx-3234356038{padding:${DISPLAY_DENSITY_PADDING_NORMAL}px;}`, `.title-cell.displaydensity-COMFORTABLE.jsx-3234356038>.title-cell-content.jsx-3234356038{padding:${DISPLAY_DENSITY_PADDING_COMFORTABLE}px;}`, ".row-header.jsx-3234356038{background-color:#dae6f8;}", ".row-header-hierarchy.jsx-3234356038{text-align:left;}", ".empty-header.jsx-3234356038{background-color:#cddaed;}", ".total-header.jsx-3234356038{background-color:#bac6d8;}", ".value.jsx-3234356038{background-color:#ffffff;text-align:left;}", ".NUMBER.jsx-3234356038,.INTEGER.jsx-3234356038,.INTEGER_POSITIVE.jsx-3234356038,.INTEGER_NEGATIVE.jsx-3234356038,.INTEGER_ZERO_OR_POSITIVE.jsx-3234356038,.UNIT_INTERVAL.jsx-3234356038,.PERCENTAGE.jsx-3234356038,.BOOLEAN.jsx-3234356038,.TRUE_ONLY.jsx-3234356038{text-align:right;}", ".clickable.jsx-3234356038{cursor:pointer;}", ".value.jsx-3234356038:hover{background-color:#f3f3f3;}", ".subtotal.jsx-3234356038{background-color:#f4f4f4;}", ".total.jsx-3234356038{background-color:#d8d8d8;}", ".column-header-label.jsx-3234356038{overflow:hidden;text-overflow:ellipsis;}"];
6
- cell.__hash = "3234356038";
5
+ export const cell = [`td.jsx-2444037071,th.jsx-2444037071{box-sizing:border-box;font-weight:normal;overflow:hidden;text-overflow:ellipsis;border:1px solid ${BORDER_COLOR};border-width:0 0 1px 1px;cursor:default;}`, "th.fixed-header.jsx-2444037071{position:-webkit-sticky;position:sticky;z-index:1;top:0;left:0;}", `.fontsize-SMALL.jsx-2444037071{font-size:${FONT_SIZE_SMALL}px;line-height:${FONT_SIZE_SMALL}px;}`, `.fontsize-NORMAL.jsx-2444037071{font-size:${FONT_SIZE_NORMAL}px;line-height:${FONT_SIZE_NORMAL}px;}`, `.fontsize-LARGE.jsx-2444037071{font-size:${FONT_SIZE_LARGE}px;line-height:${FONT_SIZE_LARGE}px;}`, `.displaydensity-COMPACT.jsx-2444037071{padding:${DISPLAY_DENSITY_PADDING_COMPACT}px;}`, `.displaydensity-NORMAL.jsx-2444037071{padding:${DISPLAY_DENSITY_PADDING_NORMAL}px;}`, `.displaydensity-COMFORTABLE.jsx-2444037071{padding:${DISPLAY_DENSITY_PADDING_COMFORTABLE}px;}`, ".column-header.jsx-2444037071{background-color:#dae6f8;}", "div.column-header-inner.jsx-2444037071{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;}", ".title-cell.jsx-2444037071{font-weight:bold;background-color:#cddaed;padding:0;}", ".title-cell-content.jsx-2444037071{text-align:center;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}", `.title-cell.displaydensity-COMPACT.jsx-2444037071>.title-cell-content.jsx-2444037071{padding:${DISPLAY_DENSITY_PADDING_COMPACT}px;}`, `.title-cell.displaydensity-NORMAL.jsx-2444037071>.title-cell-content.jsx-2444037071{padding:${DISPLAY_DENSITY_PADDING_NORMAL}px;}`, `.title-cell.displaydensity-COMFORTABLE.jsx-2444037071>.title-cell-content.jsx-2444037071{padding:${DISPLAY_DENSITY_PADDING_COMFORTABLE}px;}`, ".row-header.jsx-2444037071{background-color:#dae6f8;}", ".row-header-hierarchy.jsx-2444037071{text-align:left;}", ".empty-header.jsx-2444037071{background-color:#cddaed;}", ".total-header.jsx-2444037071{background-color:#bac6d8;}", ".value.jsx-2444037071{background-color:#ffffff;text-align:left;}", ".NUMBER.jsx-2444037071,.INTEGER.jsx-2444037071,.INTEGER_POSITIVE.jsx-2444037071,.INTEGER_NEGATIVE.jsx-2444037071,.INTEGER_ZERO_OR_POSITIVE.jsx-2444037071,.UNIT_INTERVAL.jsx-2444037071,.PERCENTAGE.jsx-2444037071,.BOOLEAN.jsx-2444037071,.TRUE_ONLY.jsx-2444037071{text-align:right;}", `.N_A.jsx-2444037071{text-align:center;color:${colors.grey600};}`, ".clickable.jsx-2444037071{cursor:pointer;}", ".value.jsx-2444037071:hover{background-color:#f3f3f3;}", ".subtotal.jsx-2444037071{background-color:#f4f4f4;}", ".total.jsx-2444037071{background-color:#d8d8d8;}", ".column-header-label.jsx-2444037071{overflow:hidden;text-overflow:ellipsis;}"];
6
+ cell.__hash = "2444037071";
7
7
  export const sortIcon = [`.fontsize-SMALL.jsx-2877616992{height:${FONT_SIZE_SMALL}px;margin-bottom:1px;margin-left:5px;}`, `.fontsize-NORMAL.jsx-2877616992{height:${FONT_SIZE_NORMAL}px;max-height:11px;margin-bottom:2px;margin-left:6px;}`, `.fontsize-LARGE.jsx-2877616992{height:${FONT_SIZE_LARGE}px;margin-bottom:2px;margin-left:7px;}`];
8
8
  sortIcon.__hash = "2877616992";
@@ -267,6 +267,7 @@
267
267
  "Six-months": "Six-months",
268
268
  "Financial Years": "Financial Years",
269
269
  "Years": "Years",
270
+ "Value: {{value}}": "Value: {{value}}",
270
271
  "Bold text": "Bold text",
271
272
  "Italic text": "Italic text",
272
273
  "Link to a URL": "Link to a URL",
@@ -357,6 +358,7 @@
357
358
  "{{thresholdFactor}} × Modified Z-score high": "{{thresholdFactor}} × Modified Z-score high",
358
359
  "{{thresholdFactor}} × Z-score low": "{{thresholdFactor}} × Z-score low",
359
360
  "{{thresholdFactor}} × Z-score high": "{{thresholdFactor}} × Z-score high",
361
+ "Not applicable": "Not applicable",
360
362
  "Data": "Data",
361
363
  "Organisation unit": "Organisation unit",
362
364
  "Assigned Categories": "Assigned Categories",
@@ -6,11 +6,11 @@ import times from 'lodash/times';
6
6
  import { DIMENSION_TYPE_DATA, DIMENSION_TYPE_DATA_ELEMENT_GROUP_SET, DIMENSION_TYPE_ORGANISATION_UNIT, DIMENSION_TYPE_PERIOD } from '../dataTypes.js';
7
7
  import { DIMENSION_ID_ORGUNIT } from '../predefinedDimensions.js';
8
8
  import { renderValue } from '../renderValue.js';
9
- import { VALUE_TYPE_NUMBER, VALUE_TYPE_TEXT, isBooleanValueType, isNumericValueType } from '../valueTypes.js';
9
+ import { VALUE_TYPE_NUMBER, VALUE_TYPE_TEXT, isBooleanValueType, isCumulativeValueType, isNumericValueType } from '../valueTypes.js';
10
10
  import { AdaptiveClippingController } from './AdaptiveClippingController.js';
11
11
  import { addToTotalIfNumber } from './addToTotalIfNumber.js';
12
12
  import { parseValue } from './parseValue.js';
13
- import { AGGREGATE_TYPE_NA, AGGREGATE_TYPE_AVERAGE, AGGREGATE_TYPE_SUM, CELL_TYPE_VALUE, CELL_TYPE_TOTAL, CELL_TYPE_SUBTOTAL, SORT_ORDER_ASCENDING, SORT_ORDER_DESCENDING, DISPLAY_DENSITY_PADDING_COMPACT, DISPLAY_DENSITY_PADDING_COMFORTABLE, DISPLAY_DENSITY_OPTION_COMFORTABLE, DISPLAY_DENSITY_OPTION_COMPACT, DISPLAY_DENSITY_OPTION_NORMAL, DISPLAY_DENSITY_PADDING_NORMAL, FONT_SIZE_OPTION_SMALL, FONT_SIZE_SMALL, FONT_SIZE_OPTION_LARGE, FONT_SIZE_LARGE, FONT_SIZE_OPTION_NORMAL, FONT_SIZE_NORMAL, NUMBER_TYPE_COLUMN_PERCENTAGE, NUMBER_TYPE_ROW_PERCENTAGE, NUMBER_TYPE_VALUE } from './pivotTableConstants.js';
13
+ import { AGGREGATE_TYPE_NA, AGGREGATE_TYPE_AVERAGE, AGGREGATE_TYPE_SUM, CELL_TYPE_VALUE, CELL_TYPE_TOTAL, CELL_TYPE_SUBTOTAL, SORT_ORDER_ASCENDING, SORT_ORDER_DESCENDING, DISPLAY_DENSITY_PADDING_COMPACT, DISPLAY_DENSITY_PADDING_COMFORTABLE, DISPLAY_DENSITY_OPTION_COMFORTABLE, DISPLAY_DENSITY_OPTION_COMPACT, DISPLAY_DENSITY_OPTION_NORMAL, DISPLAY_DENSITY_PADDING_NORMAL, FONT_SIZE_OPTION_SMALL, FONT_SIZE_SMALL, FONT_SIZE_OPTION_LARGE, FONT_SIZE_LARGE, FONT_SIZE_OPTION_NORMAL, FONT_SIZE_NORMAL, NUMBER_TYPE_COLUMN_PERCENTAGE, NUMBER_TYPE_ROW_PERCENTAGE, NUMBER_TYPE_VALUE, VALUE_TYPE_NA, VALUE_NA } from './pivotTableConstants.js';
14
14
  const dataFields = ['value', 'numerator', 'denominator', 'factor', 'multiplier', 'divisor'];
15
15
  const defaultOptions = {
16
16
  hideEmptyColumns: false,
@@ -153,7 +153,7 @@ const applyTotalAggregationType = (_ref2, overrideTotalAggregationType) => {
153
153
  } = _ref2;
154
154
  switch (overrideTotalAggregationType || totalAggregationType) {
155
155
  case AGGREGATE_TYPE_NA:
156
- return 'N/A';
156
+ return VALUE_NA;
157
157
  case AGGREGATE_TYPE_AVERAGE:
158
158
  return (numerator || value) * multiplier / (denominator * divisor || 1);
159
159
  case AGGREGATE_TYPE_SUM:
@@ -258,15 +258,29 @@ export class PivotTableEngine {
258
258
  rawCell.rawValue = rawValue;
259
259
  rawCell.renderedValue = renderedValue;
260
260
  }
261
+ if ([CELL_TYPE_TOTAL, CELL_TYPE_SUBTOTAL].includes(rawCell.cellType) && rawCell.rawValue === AGGREGATE_TYPE_NA) {
262
+ rawCell.titleValue = i18n.t('Not applicable');
263
+ }
261
264
  if (this.options.cumulativeValues) {
265
+ let titleValue;
266
+ if (this.data[row] && this.data[row][column]) {
267
+ const dataRow = this.data[row][column];
268
+ const rawValue = cellType === CELL_TYPE_VALUE ? dataRow[this.dimensionLookup.dataHeaders.value] : dataRow.value;
269
+ titleValue = i18n.t('Value: {{value}}', {
270
+ value: renderValue(rawValue, valueType, this.visualization),
271
+ nsSeparator: '^^'
272
+ });
273
+ }
262
274
  const cumulativeValue = this.getCumulative({
263
275
  row,
264
276
  column
265
277
  });
266
278
  if (cumulativeValue !== undefined && cumulativeValue !== null) {
267
- // force to NUMBER for accumulated values
268
- rawCell.valueType = valueType === undefined || valueType === null ? VALUE_TYPE_NUMBER : valueType;
279
+ // force to TEXT for N/A (accumulated) values
280
+ // force to NUMBER for accumulated values if no valueType present
281
+ rawCell.valueType = cumulativeValue === VALUE_NA ? VALUE_TYPE_NA : valueType === undefined || valueType === null ? VALUE_TYPE_NUMBER : valueType;
269
282
  rawCell.empty = false;
283
+ rawCell.titleValue = titleValue;
270
284
  rawCell.rawValue = cumulativeValue;
271
285
  rawCell.renderedValue = renderValue(cumulativeValue, valueType, this.visualization);
272
286
  }
@@ -365,15 +379,12 @@ export class PivotTableEngine {
365
379
  return undefined;
366
380
  }
367
381
  const cellValue = this.data[row][column];
382
+
383
+ // empty cell
368
384
  if (!cellValue) {
369
- // Empty cell
370
- // The cell still needs to get the valueType to render correctly 0 and cumulative values
371
- return {
372
- valueType: VALUE_TYPE_NUMBER,
373
- totalAggregationType: AGGREGATE_TYPE_SUM
374
- };
385
+ return undefined;
375
386
  }
376
- if (!Array.isArray(cellValue)) {
387
+ if (cellValue && !Array.isArray(cellValue)) {
377
388
  // This is a total cell
378
389
  return {
379
390
  valueType: cellValue.valueType,
@@ -536,19 +547,26 @@ export class PivotTableEngine {
536
547
  } else {
537
548
  totalCell.totalAggregationType = currentAggType;
538
549
  }
539
- const currentValueType = dxDimension === null || dxDimension === void 0 ? void 0 : dxDimension.valueType;
550
+
551
+ // Force value type of total cells to NUMBER for value cells with numeric or boolean types.
552
+ // This is to simplify the code below where we compare the previous value type.
553
+ // All numeric/boolean value types use the same style for rendering the total cell (right aligned content)
554
+ // and using NUMBER for the total cell is enough for that.
555
+ // (see DHIS2-9155)
556
+ const currentValueType = isNumericValueType(dxDimension === null || dxDimension === void 0 ? void 0 : dxDimension.valueType) || isBooleanValueType(dxDimension === null || dxDimension === void 0 ? void 0 : dxDimension.valueType) ? VALUE_TYPE_NUMBER : dxDimension === null || dxDimension === void 0 ? void 0 : dxDimension.valueType;
540
557
  const previousValueType = totalCell.valueType;
541
558
  if (previousValueType && currentValueType !== previousValueType) {
542
- totalCell.valueType = AGGREGATE_TYPE_NA;
559
+ totalCell.valueType = VALUE_TYPE_NA;
543
560
  } else {
544
561
  totalCell.valueType = currentValueType;
545
562
  }
546
563
 
547
- // compute subtotals and totals for all numeric and boolean value types
548
- // in that case, force value type of subtotal and total cells to NUMBER to format them correctly
564
+ // Compute totals for all numeric and boolean value types only.
565
+ // In practice valueType here is NUMBER (see the comment above).
566
+ // When is not, it means there is some value cell with a valueType other than numeric/boolean,
567
+ // the total should not be computed then.
549
568
  // (see DHIS2-9155)
550
- if (isNumericValueType(dxDimension === null || dxDimension === void 0 ? void 0 : dxDimension.valueType) || isBooleanValueType(dxDimension === null || dxDimension === void 0 ? void 0 : dxDimension.valueType)) {
551
- totalCell.valueType = VALUE_TYPE_NUMBER;
569
+ if (isNumericValueType(totalCell.valueType)) {
552
570
  dataFields.forEach(field => {
553
571
  const headerIndex = this.dimensionLookup.dataHeaders[field];
554
572
  const value = parseValue(dataRow[headerIndex]);
@@ -642,6 +660,17 @@ export class PivotTableEngine {
642
660
  }
643
661
  }
644
662
  }
663
+ computeOverrideTotalAggregationType(totalCell, visualization) {
664
+ // Avoid undefined on total cells with valueTypes that cannot be totalized.
665
+ // This happens for example when a column/row has all value cells of type TEXT.
666
+ if (!(isNumericValueType(totalCell.valueType) || isBooleanValueType(totalCell.valueType))) {
667
+ return AGGREGATE_TYPE_NA;
668
+ }
669
+
670
+ // DHIS2-15698: do not override total aggregation type when numberType option is not present
671
+ // (numberType option default is VALUE)
672
+ return visualization.numberType && visualization.numberType !== NUMBER_TYPE_VALUE && AGGREGATE_TYPE_SUM;
673
+ }
645
674
  finalizeTotal(_ref11) {
646
675
  let {
647
676
  row,
@@ -652,10 +681,12 @@ export class PivotTableEngine {
652
681
  }
653
682
  const totalCell = this.data[row][column];
654
683
  if (totalCell && totalCell.count) {
655
- totalCell.value = applyTotalAggregationType(totalCell,
656
- // DHIS2-15698: do not override total aggregation type when numberType option is not present
657
- // (numberType option default is VALUE)
658
- this.visualization.numberType && this.visualization.numberType !== NUMBER_TYPE_VALUE && AGGREGATE_TYPE_SUM);
684
+ totalCell.value = applyTotalAggregationType(totalCell, this.computeOverrideTotalAggregationType(totalCell, this.visualization));
685
+
686
+ // override valueType for styling cells with N/A value
687
+ if (totalCell.value === AGGREGATE_TYPE_NA) {
688
+ totalCell.valueType = VALUE_TYPE_NA;
689
+ }
659
690
  this.adaptiveClippingController.add({
660
691
  row,
661
692
  column
@@ -756,10 +787,14 @@ export class PivotTableEngine {
756
787
  column
757
788
  });
758
789
  const valueType = (dxDimension === null || dxDimension === void 0 ? void 0 : dxDimension.valueType) || VALUE_TYPE_TEXT;
790
+ const totalAggregationType = dxDimension === null || dxDimension === void 0 ? void 0 : dxDimension.totalAggregationType;
759
791
 
760
- // only accumulate numeric values
761
- // accumulating text values does not make sense
762
- if (valueType === VALUE_TYPE_NUMBER) {
792
+ // only accumulate numeric (except for PERCENTAGE and UNIT_INTERVAL) and boolean values
793
+ // accumulating other value types like text values does not make sense
794
+ if (isCumulativeValueType(valueType) && totalAggregationType === AGGREGATE_TYPE_SUM) {
795
+ // initialise to 0 for cumulative types
796
+ // (||= is not transformed correctly in Babel with the current setup)
797
+ acc || (acc = 0);
763
798
  if (this.data[row] && this.data[row][column]) {
764
799
  const dataRow = this.data[row][column];
765
800
  const rawValue = cellType === CELL_TYPE_VALUE ? dataRow[this.dimensionLookup.dataHeaders.value] : dataRow.value;
@@ -768,7 +803,7 @@ export class PivotTableEngine {
768
803
  this.accumulators.rows[row][column] = acc;
769
804
  }
770
805
  return acc;
771
- }, 0);
806
+ }, '');
772
807
  });
773
808
  } else {
774
809
  this.accumulators = {
@@ -6,6 +6,8 @@ export const CELL_TYPE_TOTAL = 'total';
6
6
  export const AGGREGATE_TYPE_SUM = 'SUM';
7
7
  export const AGGREGATE_TYPE_AVERAGE = 'AVERAGE';
8
8
  export const AGGREGATE_TYPE_NA = 'N/A';
9
+ export const VALUE_TYPE_NA = 'N_A'; // this ends up as CSS class and / is problematic
10
+
9
11
  export const NUMBER_TYPE_VALUE = 'VALUE';
10
12
  export const NUMBER_TYPE_ROW_PERCENTAGE = 'ROW_PERCENTAGE';
11
13
  export const NUMBER_TYPE_COLUMN_PERCENTAGE = 'COLUMN_PERCENTAGE';
@@ -26,4 +28,5 @@ export const CLIPPED_CELL_MAX_SIZE = 360;
26
28
  export const CLIPPED_CELL_MIN_SIZE = 36;
27
29
  export const WRAPPED_TEXT_JUSTIFY_BUFFER = 25;
28
30
  export const WRAPPED_TEXT_LINE_HEIGHT = 1.0;
29
- export const CLIPPED_AXIS_PARTITION_SIZE_PX = 1000;
31
+ export const CLIPPED_AXIS_PARTITION_SIZE_PX = 1000;
32
+ export const VALUE_NA = 'N/A';
@@ -25,5 +25,7 @@ export const VALUE_TYPE_ORGANISATION_UNIT = 'ORGANISATION_UNIT';
25
25
  export const VALUE_TYPE_AGE = 'AGE';
26
26
  const NUMERIC_VALUE_TYPES = [VALUE_TYPE_NUMBER, VALUE_TYPE_UNIT_INTERVAL, VALUE_TYPE_PERCENTAGE, VALUE_TYPE_INTEGER, VALUE_TYPE_INTEGER_POSITIVE, VALUE_TYPE_INTEGER_NEGATIVE, VALUE_TYPE_INTEGER_ZERO_OR_POSITIVE];
27
27
  const BOOLEAN_VALUE_TYPES = [VALUE_TYPE_BOOLEAN, VALUE_TYPE_TRUE_ONLY];
28
+ const CUMULATIVE_VALUE_TYPES = [VALUE_TYPE_NUMBER, VALUE_TYPE_INTEGER, VALUE_TYPE_INTEGER_POSITIVE, VALUE_TYPE_INTEGER_NEGATIVE, VALUE_TYPE_INTEGER_ZERO_OR_POSITIVE, ...BOOLEAN_VALUE_TYPES];
29
+ export const isCumulativeValueType = type => CUMULATIVE_VALUE_TYPES.includes(type);
28
30
  export const isNumericValueType = type => NUMERIC_VALUE_TYPES.includes(type);
29
31
  export const isBooleanValueType = type => BOOLEAN_VALUE_TYPES.includes(type);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dhis2/analytics",
3
- "version": "26.8.6",
3
+ "version": "26.8.7",
4
4
  "main": "./build/cjs/index.js",
5
5
  "module": "./build/es/index.js",
6
6
  "exports": {
@@ -20,7 +20,6 @@
20
20
  },
21
21
  "scripts": {
22
22
  "build": "d2-app-scripts build",
23
- "postbuild": "yarn build-storybook",
24
23
  "build-storybook": "build-storybook",
25
24
  "start-storybook": "start-storybook --port 5000",
26
25
  "start": "yarn start-storybook",