@sis-cc/dotstatsuite-components 9.1.0 → 9.2.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 (80) hide show
  1. package/lib/rules/src/preparators/enhanceObservations.js +155 -0
  2. package/lib/rules/src/preparators/formatValue.js +77 -0
  3. package/lib/rules/src/preparators/getDimensions.js +55 -0
  4. package/lib/rules/src/preparators/getDisplay.js +32 -0
  5. package/lib/rules/src/preparators/getObservations.js +27 -0
  6. package/lib/rules/src/table/factories/getCells.js +1 -3
  7. package/lib/rules/src/table/factories/getLayoutData.js +102 -161
  8. package/lib/rules/src/table/factories/getSortedLayoutIndexes.js +118 -0
  9. package/lib/rules/src/table/factories/getTableData.js +12 -10
  10. package/lib/rules/src/table/factories/refineLayoutSize.js +210 -0
  11. package/lib/rules/src/table/preparators/prepareData.js +23 -23
  12. package/lib/rules/src/table/units/appendUnitsInLayoutDataEntry.js +10 -10
  13. package/lib/rules/src/table/units/getAttachmentSeriesIndexes.js +1 -1
  14. package/lib/rules/src/table/units/getUnitsSeries.js +31 -0
  15. package/lib/rules/src/v8-transformer.js +3 -2
  16. package/package.json +2 -2
  17. package/src/rules/src/preparators/enhanceObservations.js +163 -0
  18. package/src/rules/src/preparators/formatValue.js +73 -0
  19. package/src/rules/src/preparators/getDimensions.js +49 -0
  20. package/src/rules/src/preparators/getDisplay.js +20 -0
  21. package/src/rules/src/preparators/getObservations.js +19 -0
  22. package/src/rules/src/table/factories/getCells.js +3 -7
  23. package/src/rules/src/table/factories/getLayoutData.js +135 -184
  24. package/src/rules/src/table/factories/getSortedLayoutIndexes.js +108 -0
  25. package/src/rules/src/table/factories/getTableData.js +10 -10
  26. package/src/rules/src/table/factories/refineLayoutSize.js +224 -0
  27. package/src/rules/src/table/preparators/prepareData.js +23 -32
  28. package/src/rules/src/table/units/appendUnitsInLayoutDataEntry.js +15 -18
  29. package/src/rules/src/table/units/getAttachmentSeriesIndexes.js +2 -1
  30. package/src/rules/src/table/units/getUnitsSeries.js +20 -0
  31. package/src/rules/src/v8-transformer.js +4 -2
  32. package/test/appendUnitsInLayoutDataEntry.test.js +3 -3
  33. package/test/enhanceObservations.test.js +270 -0
  34. package/test/getAttachmentSeriesIndexes.test.js +1 -1
  35. package/test/getCells.test.js +4 -39
  36. package/test/getLayoutData2.test.js +194 -0
  37. package/test/getOneValueDimensions.test.js +1 -1
  38. package/test/getSortedLayoutIndexes.test.js +80 -0
  39. package/test/getUnitsArtefacts.test.js +1 -1
  40. package/test/getUnitsSeries.test.js +64 -0
  41. package/test/mocks/table-layout-multi-hierarchies--layout.json +621 -0
  42. package/test/mocks/table-layout-multi-hierarchies--layoutData.json +32410 -0
  43. package/test/mocks/table-layout-multi-hierarchies--layoutIndexes.json +2760 -0
  44. package/test/mocks/table-layout-multi-hierarchies--observations.json +30688 -0
  45. package/test/mocks/table-layout-multi-hierarchies--sizedIndexes.json +2761 -0
  46. package/test/mocks/table-layout-truncation1--layout.json +27469 -0
  47. package/test/mocks/table-layout-truncation1--layoutData.json +19413 -0
  48. package/test/mocks/table-layout-truncation1--layoutIndexes.json +7512 -0
  49. package/test/mocks/table-layout-truncation1--observations.json +70002 -0
  50. package/test/mocks/table-layout-truncation1--sizedIndexes.json +3010 -0
  51. package/test/mocks/table-prep-multi-hierarchies--attributes.json +44 -0
  52. package/test/mocks/table-prep-multi-hierarchies--dimensions.json +688 -0
  53. package/test/mocks/table-prep-multi-hierarchies--enhancedObservations.json +19696 -0
  54. package/test/mocks/table-prep-multi-hierarchies--observations.json +8246 -0
  55. package/test/mocks/table-prep-multi-hierarchies--sdmxJson.json +2985 -0
  56. package/test/mocks/table-prep-truncation1--dimensions.json +35057 -0
  57. package/test/mocks/table-prep-truncation1--enhancedObservations.json +70002 -0
  58. package/test/mocks/table-prep-truncation1--observations.json +27502 -0
  59. package/test/mocks/table-prep-truncation1--sdmxJson.json +55103 -0
  60. package/test/mocks/table-prep-units--observations.json +284286 -0
  61. package/test/mocks/table-prep-units--unitsSeries.json +41042 -0
  62. package/test/parseAttributes.test.js +1 -1
  63. package/test/refineLayoutSize.test.js +415 -0
  64. package/test/table-layout-perf.test.js +74 -0
  65. package/test/table-prep-perf.test.js +65 -0
  66. package/lib/rules/src/table/factories/getSortedLayoutData.js +0 -145
  67. package/lib/rules/src/table/factories/refineLayoutHierarchy.js +0 -61
  68. package/lib/rules/src/table/preparators/parseObservations.js +0 -76
  69. package/lib/rules/src/table/units/getUnitsSeriesOccurences.js +0 -39
  70. package/src/rules/src/table/factories/getSortedLayoutData.js +0 -133
  71. package/src/rules/src/table/factories/refineLayoutHierarchy.js +0 -64
  72. package/src/rules/src/table/preparators/parseObservations.js +0 -81
  73. package/src/rules/src/table/units/getUnitsSeriesOccurences.js +0 -51
  74. package/test/appendUnitsInLayoutData.test.js +0 -248
  75. package/test/getLayoutData.test.js +0 -311
  76. package/test/getSortedLayoutData.test.js +0 -382
  77. package/test/getUnitsSeriesOccurences.test.js +0 -133
  78. package/test/parseObservations.test.js +0 -116
  79. package/test/refineDimSeriesUnits.test.js +0 -24
  80. package/test/refineLayoutHierarchy.test.js +0 -79
@@ -0,0 +1,224 @@
1
+ import * as R from 'ramda';
2
+
3
+ const getPivotKey = indexes => R.pipe(
4
+ R.props(indexes),
5
+ R.join(':')
6
+ );
7
+
8
+ const getPivots = (layout, shape) => R.pipe(
9
+ R.props(shape),
10
+ R.map(R.pipe(R.pluck('__index'), getPivotKey))
11
+ )(layout);
12
+
13
+ const indexWithPivots = (pivots, observations) => R.pipe(
14
+ R.values,
15
+ R.reduce(
16
+ (acc, obs) => {
17
+ const path = R.map(
18
+ pivot => pivot(obs.orderedDimIndexes),
19
+ pivots
20
+ );
21
+ return R.over(
22
+ R.lensPath(path),
23
+ R.ifElse(R.isNil, R.always([obs]), R.append(obs))
24
+ )(acc);
25
+ },
26
+ {}
27
+ )
28
+ )(observations);
29
+
30
+ export const getCuratedCells = ({ layout, observations, shape }) => {
31
+ const pivots = getPivots(layout, shape);
32
+ return indexWithPivots(pivots, observations);
33
+ };
34
+
35
+ export const refineSections = (sections, extractedKeys, curatedObs) => R.pipe(
36
+ R.map(
37
+ (section) => {
38
+ const sectionKey = R.join(':', R.head(section) || []);
39
+ return R.over(
40
+ R.lensIndex(1),
41
+ R.filter(
42
+ rowData => {
43
+ const rowKey = R.join(':', rowData);
44
+ return R.pipe(
45
+ R.path([sectionKey, rowKey]),
46
+ R.omit(extractedKeys),
47
+ R.isEmpty,
48
+ R.not
49
+ )(curatedObs);
50
+ }
51
+ )
52
+ )(section);
53
+ }
54
+ ),
55
+ R.filter(
56
+ R.pipe(R.nth(1), R.isEmpty, R.not)
57
+ )
58
+ )(sections);
59
+
60
+ export const refineHeader = (header, extractedKeys, curatedObs) => R.filter( // extracted : { [sectionKey]: [...rowKeys] }
61
+ (header) => {
62
+ const headerKey = R.join(':', header);
63
+ return R.pipe(
64
+ R.prop(headerKey),
65
+ (sections) => {
66
+ return R.pickBy(
67
+ (rows, section) => R.pipe(
68
+ R.omit(R.propOr([], section, extractedKeys)),
69
+ R.isEmpty,
70
+ R.not
71
+ )(rows),
72
+ sections
73
+ );
74
+ },
75
+ R.isEmpty,
76
+ R.not
77
+ )(curatedObs);
78
+ }
79
+ )(header);
80
+
81
+ export const truncateSectionRows = (n, sectionsData) => {
82
+ const [rest, extracted] = R.pipe(
83
+ R.last, // last section
84
+ R.nth(1), // rows
85
+ R.splitAt(R.negate(n)) // truncate from the end
86
+ )(sectionsData);
87
+
88
+ const truncatedData = R.isEmpty(rest)
89
+ ? R.dropLast(1, sectionsData) // remove section if no more rows
90
+ : R.adjust(-1, R.adjust(1, R.always(rest)), sectionsData)
91
+
92
+ const sectionKey = R.join(':', R.pipe(R.last, R.head)(sectionsData) || []);
93
+ const rowKeys = R.map(R.join(':'), extracted);
94
+
95
+ const extractedLength = R.length(extracted);
96
+ if (extractedLength < n) {
97
+ const { truncated, extractedKeys } = truncateSectionRows(
98
+ n - extractedLength,
99
+ truncatedData
100
+ );
101
+ return ({ truncated, extractedKeys: { ...extractedKeys, [sectionKey]: rowKeys } });
102
+ }
103
+
104
+ return ({ truncated: truncatedData, extractedKeys: { [sectionKey]: rowKeys } });
105
+ };
106
+
107
+ export const truncateHeader = (n, headerData) => {
108
+ const [truncated, extracted] = R.splitAt(R.negate(n))(headerData);
109
+ return ({ truncated, extractedKeys: R.map(R.join(':'), extracted) });
110
+ };
111
+
112
+ const refineLength = length => length === 0 ? 1 : length;
113
+
114
+ const truncateLayout = (isVertical) => R.ifElse(
115
+ R.always(isVertical),
116
+ truncateSectionRows,
117
+ truncateHeader,
118
+ );
119
+
120
+ const refineLayout = (isVertical) => R.ifElse(
121
+ R.always(isVertical),
122
+ refineHeader,
123
+ refineSections
124
+ )
125
+
126
+ const getShape = isVertical => isVertical ? ['header', 'sections', 'rows'] : ['sections', 'rows', 'header'];
127
+
128
+ const getRefinedLayout = (isVertical, truncated, refined) => R.ifElse(
129
+ R.always(isVertical),
130
+ R.pipe(R.assoc('sections', truncated), R.assoc('header', refined)),
131
+ R.pipe(R.assoc('header', truncated), R.assoc('sections', refined)),
132
+ )({});
133
+
134
+ const segregateLayout = (isVertical) => R.ifElse(
135
+ R.always(isVertical),
136
+ R.props(['sections', 'header']),
137
+ R.props(['header', 'sections'])
138
+ );
139
+
140
+ export const refineLayoutSize = ({ layout, observations, limit }) => layoutIndexes => {
141
+ const { header, sections } = layoutIndexes;
142
+ if (R.isNil(limit) || limit === 0 || R.all(R.isEmpty, [header, sections])) {
143
+ return R.assoc('truncated', false, layoutIndexes);
144
+ }
145
+
146
+ //number of dimensions in header
147
+ const headerDimCount = R.pipe(
148
+ R.head, // first column
149
+ R.when(R.isNil, R.always([])),
150
+ R.length // number of dims
151
+ )(header);
152
+
153
+ //number of columns for values
154
+ const headerValuesCount = R.pipe(
155
+ R.length,
156
+ R.when(R.equals(0), R.always(1))
157
+ )(header);
158
+
159
+ //total of cells in header
160
+ const headerCellsCount = headerDimCount * (headerValuesCount + 1);
161
+
162
+ // number of dimensions in a row
163
+ const rowDimCount = R.pipe(
164
+ R.head, // firstSection
165
+ R.last, // rows,
166
+ R.head, // first row
167
+ R.length
168
+ )(sections);
169
+
170
+ // number of cells in a row
171
+ const rowCellsCount = rowDimCount + headerValuesCount + 1;
172
+
173
+ // number of rows
174
+ const rowsCount = R.pipe(
175
+ R.map(R.last),
176
+ R.unnest,
177
+ R.length,
178
+ R.add(1)
179
+ )(sections);
180
+
181
+ // total of cells in all rows
182
+ const rowsCellsCount = rowCellsCount * rowsCount;
183
+
184
+ // number of sections cells
185
+ const sectionsCellsCount = R.ifElse(
186
+ R.pipe(R.head, R.head, R.length, R.equals(0)),
187
+ R.always(0),
188
+ R.length
189
+ )(sections);
190
+
191
+ const total = rowsCellsCount + sectionsCellsCount + headerCellsCount;
192
+
193
+ const excess = total - limit;
194
+ if (excess <= 0) {
195
+ return R.assoc('truncated', false, layoutIndexes);
196
+ }
197
+
198
+ // total of cells in one column
199
+ const columnCellsCount = headerDimCount + rowsCount;
200
+
201
+ const isVertical = columnCellsCount > rowCellsCount
202
+
203
+ const [toTruncate, toRefine] = segregateLayout(isVertical)(layoutIndexes);
204
+
205
+
206
+ const cutLength = R.pipe(
207
+ R.ifElse(R.identity, R.always(rowCellsCount), R.always(columnCellsCount)),
208
+ R.divide(excess),
209
+ Math.ceil
210
+ )(isVertical);
211
+
212
+ const { truncated, extractedKeys } = truncateLayout(isVertical)(cutLength, toTruncate);
213
+
214
+ const curatedObs = R.pipe(
215
+ getShape,
216
+ (shape) => getCuratedCells({ layout, observations, shape })
217
+ )(isVertical);
218
+
219
+ const refined = refineLayout(isVertical)(toRefine, extractedKeys, curatedObs);
220
+
221
+ const result = getRefinedLayout(isVertical, truncated, refined);
222
+
223
+ return R.assoc('truncated', true, result);
224
+ };
@@ -3,11 +3,9 @@ import { getObservationsType } from '../../properties/getObservationsType';
3
3
  import { parseDimensionsIds } from './parseDimensionsIds';
4
4
  import { getNoDisplayAnnotationsIndexes } from './getNoDisplayAnnotationsIndexes';
5
5
  import { getNoDisplayCodes } from './getNoDisplayCodes';
6
- import { getDisplay } from './getDisplay';
7
6
  import { parseAttributes } from './parseAttributes';
8
7
  import { getDimensionsAttributesRegisters } from './getDimensionsAttributesRegisters';
9
8
  import { parseAttributesValuesFromObservations } from './parseAttributesValuesFromObservations';
10
- import { parseObservations } from './parseObservations';
11
9
  import { getOneValueDimensions } from './getOneValueDimensions';
12
10
  import { getManyValuesDimensions } from './getManyValuesDimensions';
13
11
  import { getAttributeValue } from './getAttributeValue';
@@ -17,8 +15,11 @@ import { getUnitsDefinition } from '../units/getUnitsDefinition';
17
15
  import { getUnitsArtefacts } from '../units/getUnitsArtefacts';
18
16
  import { getHeaderUnits } from '../units/getHeaderUnits';
19
17
  import { getAttachmentSeriesIndexes } from '../units/getAttachmentSeriesIndexes';
20
- import { getUnitsSeriesOccurences } from '../units/getUnitsSeriesOccurences';
21
- import { refineDimSeriesUnits } from '../units/refineDimSeriesUnits';
18
+ import { getUnitsSeries } from '../units/getUnitsSeries';
19
+
20
+ import { getDisplay } from '../../preparators/getDisplay';
21
+ import { getObservations } from '../../preparators/getObservations';
22
+ import { enhanceObservations } from '../../preparators/enhanceObservations';
22
23
 
23
24
  export const prepareData = (sdmxJson, customAttributes, unitsProps={}) => {
24
25
  const {
@@ -30,10 +31,7 @@ export const prepareData = (sdmxJson, customAttributes, unitsProps={}) => {
30
31
  defaultCodes, annotationsDefinitionCodes, data: sdmxJson
31
32
  });
32
33
  const _customAttributes = R.assoc('units', unitsDefinitionCodes, customAttributes);
33
- const dimensions = R.pipe(
34
- R.pathOr([], ['data', 'structure', 'dimensions', 'observation']),
35
- R.addIndex(R.map)((dim, index) => R.assoc('__index', index, dim))
36
- )(sdmxJson);
34
+ const dimensions = R.pathOr([], ['data', 'structure', 'dimensions', 'observation'], sdmxJson);
37
35
 
38
36
  const dimensionsIndexedByIds = R.indexBy(R.prop('id'), dimensions);
39
37
 
@@ -60,40 +58,33 @@ export const prepareData = (sdmxJson, customAttributes, unitsProps={}) => {
60
58
  const attachmentSeriesIndexes = getAttachmentSeriesIndexes({ dimensions: _dimensions, unitsArtefacts });
61
59
  //------------------------------------------------------------------
62
60
 
61
+ const attributes = R.pathOr([], ['data', 'structure', 'attributes', 'observation'], sdmxJson);
62
+
63
63
  const { attributesIndexedByIds, attributesIdsIndexedByTargets } = parseAttributes({
64
64
  attributes: R.concat(
65
- R.pathOr([], ['data', 'structure', 'attributes', 'observation'], sdmxJson),
65
+ attributes,
66
66
  R.pathOr([], ['data', 'structure', 'attributes', 'dataSet'], sdmxJson),
67
67
  ),
68
68
  parsedDimensionsIds,
69
69
  getDisplay: _getDisplay,
70
70
  customAttributes: _customAttributes,
71
71
  });
72
-
72
+
73
73
  const seriesAttributesIds = R.propOr([], 'series', attributesIdsIndexedByTargets);
74
74
  const observationsAttributesIds = R.propOr([], 'observations', attributesIdsIndexedByTargets);
75
- const observations = parseObservations(
76
- R.pathOr({}, ['data', 'dataSets', 0, 'observations'], sdmxJson),
77
- dimensions,
78
- R.pick(R.concat(seriesAttributesIds, observationsAttributesIds), attributesIndexedByIds),
79
- R.pipe(
80
- R.pick(['prefscale', 'decimals']),
81
- R.mapObjIndexed(R.flip(R.prop)(attributesIndexedByIds))
82
- )(attributesIdsIndexedByTargets),
83
- unitsArtefacts,
84
- _getDisplay
85
- );
75
+ const options = {
76
+ attachmentSeriesIndexes,
77
+ customAttributes,
78
+ noDisplayIndexes,
79
+ notDisplayedCodes,
80
+ attributesIds: R.concat(seriesAttributesIds, observationsAttributesIds),
81
+ unitsIds: unitsDefinitionCodes,
82
+ };
83
+
84
+ const _observations = getObservations(sdmxJson);
85
+ const observations = enhanceObservations(dimensions, _observations, attributes, options);
86
86
  //------------------------------------------------------------------
87
- const { rawUnitsSeries, obs } = getUnitsSeriesOccurences({
88
- unitsArtefacts, attachmentSeriesIndexes
89
- })(observations);
90
- const unitsSeries = refineDimSeriesUnits({
91
- unitsArtefacts: R.merge(
92
- R.pathOr({}, ['dimensions', 'series'], unitsArtefacts),
93
- R.pathOr({}, ['attributes', 'series'], unitsArtefacts)
94
- ),
95
- rejectedValueIds
96
- })(rawUnitsSeries);
87
+ const unitsSeries = getUnitsSeries(observations);
97
88
  const unitsAttachmentSeriesIds = R.pipe(
98
89
  R.props(attachmentSeriesIndexes),
99
90
  R.pluck('id')
@@ -153,7 +144,7 @@ export const prepareData = (sdmxJson, customAttributes, unitsProps={}) => {
153
144
  unitsAttachmentSeriesIds,
154
145
  unitsSeries,
155
146
  },
156
- observations: obs,
147
+ observations,
157
148
  observationsType: getObservationsType(sdmxJson.data),
158
149
  dataflowAttributes,
159
150
  dataflowName: R.path(['data', 'structure', 'name'], sdmxJson),
@@ -16,26 +16,23 @@ export const appendUnitsInLayoutDataEntry = ({
16
16
  R.join(':'),
17
17
  R.flip(R.propOr({}))(unitsSeries)
18
18
  )(layoutDataEntry);
19
+
19
20
  const unitsData = {
20
21
  dimension: unitDimension,
21
- value: {
22
- id: 'VAL',
23
- unitsLabel: R.pipe(
24
- R.props(unitsDefinitionCodes),
25
- R.reduce(
26
- (label, unit) => {
27
- if (R.isNil(unit) || R.includes(R.path(['value', 'id'], unit), rejectedValueIds)) {
28
- return label;
29
- }
30
- const unitLabel = dimensionValueDisplay(display)(R.propOr({}, 'value', unit));
31
- return R.isEmpty(label)
32
- ? unitLabel
33
- : `${label}, ${unitLabel}`;
34
- },
35
- ''
36
- )
37
- )(unitsSerie)
38
- }
22
+ value: R.pipe(
23
+ R.props(unitsDefinitionCodes),
24
+ R.reduce((acc, unit) => {
25
+ const value = R.prop('value', unit);
26
+ if (R.isNil(unit) || R.includes(value.id, rejectedValueIds)) {
27
+ return acc;
28
+ }
29
+ const unitLabel = dimensionValueDisplay(display)(R.propOr({}, 'value', unit));
30
+ return R.isEmpty(acc.id)
31
+ ? { id: value.id, unitsLabel: unitLabel }
32
+ : { id: `${acc.id} - ${value.id}` , unitsLabel: `${acc.unitsLabel}, ${unitLabel}` };
33
+ }, { id: '', unitsLabel: '' })
34
+ )(unitsSerie)
39
35
  };
36
+
40
37
  return R.append(unitsData, layoutDataEntry);
41
38
  };
@@ -21,6 +21,7 @@ export const getAttachmentSeriesIndexes = ({
21
21
  R.props(R.concat(unitsDimensionsCodes, targettedDimensionsCodes)),
22
22
  R.filter(dim => !R.isNil(dim)),
23
23
  R.pluck('index'),
24
- R.uniq
24
+ R.uniq,
25
+ R.sortBy(R.identity)
25
26
  )(dimensions);
26
27
  };
@@ -0,0 +1,20 @@
1
+ import * as R from 'ramda';
2
+
3
+ /*
4
+ observations = { [obsKey]: { units: { serieKey: '', [id]: { id, name, value } } } };
5
+ */
6
+
7
+ export const getUnitsSeries = (observations) => {
8
+ let series = {};
9
+ R.map(obs => {
10
+ series = R.over(R.lensProp(obs.units.serieKey), R.ifElse(R.isNil, R.always([obs.units]), R.append(obs.units)))(series);
11
+ }, observations);
12
+
13
+ return R.map(
14
+ serie => R.reduce(
15
+ (acc, units) => R.mergeWith((a, b) => R.path(['value', 'index'], a) === R.path(['value', 'index'], b) ? a : null, acc, units),
16
+ {},
17
+ serie
18
+ )
19
+ )(series);
20
+ };
@@ -112,7 +112,7 @@ export const dataTransformer = (dataNew, options = {}) => {
112
112
  const getDimObservations = R.propOr([], 'observation');
113
113
  const dimObservations = getDimObservations(dimensions);
114
114
 
115
- const getObservations = locale => R.reduce((acc, observation) => {
115
+ const getObservations = locale => R.addIndex(R.reduce)((acc, observation, obsIndex) => {
116
116
  const id = R.prop('id')(observation);
117
117
  const dimAnnotations = getRelationnalAnnotations(R.propOr([],'annotations')(observation))(annotations)
118
118
  const isHidden = R.includes(id)(hiddenIds) ? hiddenFormat : getIsHidden(dimAnnotations);
@@ -140,12 +140,14 @@ export const dataTransformer = (dataNew, options = {}) => {
140
140
  const sortedValues = R.pipe(
141
141
  getReccursiveChildren,
142
142
  R.flatten,
143
- R.addIndex(R.map)((value, index) => R.assoc('__indexPosition', index, value))
143
+ R.addIndex(R.map)((value, index) => R.assoc('__indexPosition', index, value)),
144
+ R.sortBy(R.prop('__index'))
144
145
  )('##ROOT');
145
146
 
146
147
  return ({
147
148
  observation: R.append({
148
149
  ...observation,
150
+ __index: obsIndex,
149
151
  name: getLocalisedProp('names', observation),
150
152
  values: sortedValues,
151
153
  role: R.isNil(observation.roles) ? null : R.head(observation.roles),
@@ -29,7 +29,7 @@ describe('appendUnitsInLayoutDataEntry tests', () => {
29
29
  unitsDefinitionCodes: [],
30
30
  unitsIndexes: [],
31
31
  partialUnitSerieIndexes: []
32
- })([])).to.deep.equal([{ dimension: {}, value: { id: 'VAL', unitsLabel: '' } }]);
32
+ })([])).to.deep.equal([{ dimension: {}, value: { id: '', unitsLabel: '' } }]);
33
33
  });
34
34
  it('complete test', () => {
35
35
  expect(appendUnitsInLayoutDataEntry({
@@ -43,7 +43,7 @@ describe('appendUnitsInLayoutDataEntry tests', () => {
43
43
  { dimension: { id: 'D1', __index: 2 }, value: { id: 'V', __index: 0 } },
44
44
  { dimension: { id: 'D2', __index: 0 }, value: { id: 'V', __index: 0 } },
45
45
  { dimension: { id: 'D3', __index: 4 }, value: { id: 'V', __index: 0 } },
46
- { dimension: { id: 'U' }, value: { id: 'VAL', unitsLabel: 'U3V, U1V' } }
46
+ { dimension: { id: 'U' }, value: { id: 'U3V - U1V', unitsLabel: 'U3V, U1V' } }
47
47
  ]);
48
48
  });
49
49
  it('rejectedValues test', () => {
@@ -59,7 +59,7 @@ describe('appendUnitsInLayoutDataEntry tests', () => {
59
59
  { dimension: { id: 'D1', __index: 2 }, value: { id: 'V', __index: 0 } },
60
60
  { dimension: { id: 'D2', __index: 0 }, value: { id: 'V', __index: 0 } },
61
61
  { dimension: { id: 'D3', __index: 4 }, value: { id: 'V', __index: 0 } },
62
- { dimension: { id: 'U' }, value: { id: 'VAL', unitsLabel: 'U1V' } }
62
+ { dimension: { id: 'U' }, value: { id: 'U1V', unitsLabel: 'U1V' } }
63
63
  ]);
64
64
  })
65
65
  });