@sis-cc/dotstatsuite-components 15.0.21 → 16.1.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 (165) hide show
  1. package/lib/rules/src/index.js +1 -145
  2. package/lib/rules/src/table/index.js +0 -42
  3. package/lib/rules2/src/constants.js +4 -1
  4. package/lib/rules2/src/enhanceObservations.js +98 -0
  5. package/lib/rules2/src/getAttributesSeries.js +33 -0
  6. package/lib/rules2/src/getCombinationDefinitions.js +48 -0
  7. package/lib/rules2/src/getHeaderCombinations.js +42 -0
  8. package/lib/rules2/src/getHeaderSubtitle.js +41 -0
  9. package/lib/rules2/src/getManyValuesDimensions.js +39 -0
  10. package/lib/rules2/src/getOneValueDimensions.js +46 -0
  11. package/lib/rules2/src/hasCellMetadata.js +1 -1
  12. package/lib/rules2/src/index.js +186 -18
  13. package/lib/rules2/src/parseAttributes.js +50 -0
  14. package/lib/rules2/src/parseCombinations.js +54 -0
  15. package/lib/rules2/src/parseMetadataSeries.js +4 -2
  16. package/lib/rules2/src/prepareData.js +74 -0
  17. package/lib/{rules/src/table/preparators/getAttributeValue.js → rules2/src/refineAttributes.js} +13 -11
  18. package/lib/rules2/src/table/getCells.js +74 -0
  19. package/lib/rules2/src/table/getCellsAttributesIds.js +63 -0
  20. package/lib/rules2/src/table/getCombinationDimensionsData.js +47 -0
  21. package/lib/rules2/src/table/getCuratedCells.js +28 -0
  22. package/lib/rules2/src/table/getFlagsAndNotes.js +28 -0
  23. package/lib/rules2/src/table/getIndexedCombinationsByDisplay.js +31 -0
  24. package/lib/rules2/src/table/getLayout.js +93 -0
  25. package/lib/rules2/src/table/getLayoutData.js +202 -0
  26. package/lib/{rules/src/table/factories → rules2/src/table}/getSortedLayoutIndexes.js +55 -40
  27. package/lib/rules2/src/table/getTableProps.js +64 -0
  28. package/lib/rules2/src/table/parseValueHierarchy.js +55 -0
  29. package/lib/{rules/src/table/factories → rules2/src/table}/refineLayoutSize.js +17 -8
  30. package/lib/rules2/src/{hasLayoutEntryMetadata.js → utils.js} +9 -6
  31. package/package.json +1 -1
  32. package/src/rules/src/index.js +1 -19
  33. package/src/rules/src/table/index.js +0 -4
  34. package/src/rules2/src/constants.js +3 -0
  35. package/src/rules2/src/enhanceObservations.js +88 -0
  36. package/src/rules2/src/getAttributesSeries.js +29 -0
  37. package/src/rules2/src/getCombinationDefinitions.js +29 -0
  38. package/src/rules2/src/getHeaderCombinations.js +39 -0
  39. package/src/rules2/src/getHeaderSubtitle.js +34 -0
  40. package/src/rules2/src/getManyValuesDimensions.js +34 -0
  41. package/src/rules2/src/getOneValueDimensions.js +33 -0
  42. package/src/rules2/src/hasCellMetadata.js +1 -1
  43. package/src/rules2/src/index.js +21 -6
  44. package/src/rules2/src/parseAttributes.js +36 -0
  45. package/src/rules2/src/parseCombinations.js +36 -0
  46. package/src/rules2/src/parseMetadataSeries.js +3 -2
  47. package/src/rules2/src/prepareData.js +50 -0
  48. package/src/rules2/src/refineAttributes.js +16 -0
  49. package/src/rules2/src/table/getCells.js +72 -0
  50. package/src/rules2/src/table/getCellsAttributesIds.js +38 -0
  51. package/src/rules2/src/table/getCombinationDimensionsData.js +38 -0
  52. package/src/rules2/src/table/getCuratedCells.js +33 -0
  53. package/src/rules2/src/table/getFlagsAndNotes.js +21 -0
  54. package/src/rules2/src/table/getIndexedCombinationsByDisplay.js +16 -0
  55. package/src/rules2/src/table/getLayout.js +80 -0
  56. package/src/rules2/src/table/getLayoutData.js +183 -0
  57. package/src/rules2/src/table/getSortedLayoutIndexes.js +119 -0
  58. package/src/rules2/src/table/getTableProps.js +36 -0
  59. package/src/rules2/src/table/parseValueHierarchy.js +27 -0
  60. package/src/{rules/src/table/factories → rules2/src/table}/refineLayoutSize.js +24 -8
  61. package/src/rules2/src/utils.js +12 -0
  62. package/test/enhanceObservations2.test.js +219 -0
  63. package/test/getAttributesSeries.test.js +58 -0
  64. package/test/getCells.test.js +6 -40
  65. package/test/getCombinationDimensionsData.test.js +48 -0
  66. package/test/getSortedLayoutIndexes.test.js +1025 -3
  67. package/test/mocks/OECD_SNA_TABLE1_1.0_-_AUS_V_metadata.json +2 -2
  68. package/test/parseAttributes.test.js +17 -62
  69. package/test/parseMetadataSeries.test.js +1 -1
  70. package/test/parseValueHierarchy.test.js +88 -0
  71. package/test/refineLayoutSize.test.js +2621 -1
  72. package/lib/rules/src/table/factories/getCells.js +0 -97
  73. package/lib/rules/src/table/factories/getConfirmedSeriesAttributesIds.js +0 -26
  74. package/lib/rules/src/table/factories/getCuratedCells.js +0 -45
  75. package/lib/rules/src/table/factories/getLayoutData.js +0 -168
  76. package/lib/rules/src/table/factories/getLayoutWithFlags.js +0 -133
  77. package/lib/rules/src/table/factories/getTableCells.js +0 -24
  78. package/lib/rules/src/table/factories/getTableData.js +0 -98
  79. package/lib/rules/src/table/preparators/getDimensionsAttributesRegisters.js +0 -43
  80. package/lib/rules/src/table/preparators/getManyValuesDimensions.js +0 -33
  81. package/lib/rules/src/table/preparators/getOneValueDimensions.js +0 -24
  82. package/lib/rules/src/table/preparators/getUniqValuesAttributes.js +0 -36
  83. package/lib/rules/src/table/preparators/parseAttributes.js +0 -84
  84. package/lib/rules/src/table/preparators/parseAttributesValuesFromObservations.js +0 -22
  85. package/lib/rules/src/table/preparators/parseDimensionsIds.js +0 -22
  86. package/lib/rules/src/table/preparators/prepareData.js +0 -191
  87. package/lib/rules/src/table/preparators/refineObservationsAttributesValues.js +0 -31
  88. package/lib/rules/src/table/preparators/refineSeriesAttributesValues.js +0 -23
  89. package/lib/rules/src/table/units/appendUnitsInLayoutData.js +0 -82
  90. package/lib/rules/src/table/units/appendUnitsInLayoutDataEntry.js +0 -45
  91. package/lib/rules/src/table/units/cleanUnitsInLayoutData.js +0 -66
  92. package/lib/rules/src/table/units/getAttachmentSeriesIndexes.js +0 -25
  93. package/lib/rules/src/table/units/getHeaderUnits.js +0 -35
  94. package/lib/rules/src/table/units/getUnitsArtefacts.js +0 -85
  95. package/lib/rules/src/table/units/getUnitsCodes.js +0 -23
  96. package/lib/rules/src/table/units/getUnitsDefinition.js +0 -33
  97. package/lib/rules/src/table/units/getUnitsDisplay.js +0 -33
  98. package/lib/rules/src/table/units/getUnitsSerieIndexes.js +0 -23
  99. package/lib/rules/src/table/units/getUnitsSeries.js +0 -49
  100. package/lib/rules/src/table/units/getUnitsinLayout.js +0 -74
  101. package/lib/rules/src/table/units/refineDimSeriesUnits.js +0 -44
  102. package/lib/rules2/src/getAdvancedAttributes.js +0 -124
  103. package/lib/rules2/src/invertTime.js +0 -33
  104. package/src/rules/src/table/factories/getCells.js +0 -102
  105. package/src/rules/src/table/factories/getConfirmedSeriesAttributesIds.js +0 -27
  106. package/src/rules/src/table/factories/getCuratedCells.js +0 -40
  107. package/src/rules/src/table/factories/getLayoutData.js +0 -171
  108. package/src/rules/src/table/factories/getLayoutWithFlags.js +0 -137
  109. package/src/rules/src/table/factories/getSortedLayoutIndexes.js +0 -108
  110. package/src/rules/src/table/factories/getTableCells.js +0 -16
  111. package/src/rules/src/table/factories/getTableData.js +0 -86
  112. package/src/rules/src/table/preparators/getAttributeValue.js +0 -17
  113. package/src/rules/src/table/preparators/getDimensionsAttributesRegisters.js +0 -51
  114. package/src/rules/src/table/preparators/getManyValuesDimensions.js +0 -19
  115. package/src/rules/src/table/preparators/getOneValueDimensions.js +0 -17
  116. package/src/rules/src/table/preparators/getUniqValuesAttributes.js +0 -24
  117. package/src/rules/src/table/preparators/parseAttributes.js +0 -113
  118. package/src/rules/src/table/preparators/parseAttributesValuesFromObservations.js +0 -16
  119. package/src/rules/src/table/preparators/parseDimensionsIds.js +0 -17
  120. package/src/rules/src/table/preparators/prepareData.js +0 -197
  121. package/src/rules/src/table/preparators/refineObservationsAttributesValues.js +0 -22
  122. package/src/rules/src/table/preparators/refineSeriesAttributesValues.js +0 -11
  123. package/src/rules/src/table/units/appendUnitsInLayoutData.js +0 -56
  124. package/src/rules/src/table/units/appendUnitsInLayoutDataEntry.js +0 -38
  125. package/src/rules/src/table/units/cleanUnitsInLayoutData.js +0 -65
  126. package/src/rules/src/table/units/getAttachmentSeriesIndexes.js +0 -27
  127. package/src/rules/src/table/units/getHeaderUnits.js +0 -32
  128. package/src/rules/src/table/units/getUnitsArtefacts.js +0 -90
  129. package/src/rules/src/table/units/getUnitsCodes.js +0 -22
  130. package/src/rules/src/table/units/getUnitsDefinition.js +0 -34
  131. package/src/rules/src/table/units/getUnitsDisplay.js +0 -19
  132. package/src/rules/src/table/units/getUnitsSerieIndexes.js +0 -12
  133. package/src/rules/src/table/units/getUnitsSeries.js +0 -41
  134. package/src/rules/src/table/units/getUnitsinLayout.js +0 -71
  135. package/src/rules/src/table/units/refineDimSeriesUnits.js +0 -26
  136. package/src/rules2/src/getAdvancedAttributes.js +0 -111
  137. package/src/rules2/src/hasLayoutEntryMetadata.js +0 -9
  138. package/src/rules2/src/invertTime.js +0 -22
  139. package/test/advanced-attributes-parsing-perf.test.js +0 -16
  140. package/test/appendUnitsInLayoutDataEntry.test.js +0 -65
  141. package/test/cleanUnitsInLayoutData.test.js +0 -85
  142. package/test/enhanceObservations.test.js +0 -340
  143. package/test/getAttachmentSeriesIndexes.test.js +0 -35
  144. package/test/getConfirmedSeriesAttributesIds.test.js +0 -27
  145. package/test/getDataflowAdvancedAttributes.test.js +0 -32
  146. package/test/getHeaderUnits.test.js +0 -51
  147. package/test/getLayoutData.test.js +0 -206
  148. package/test/getLayoutDataWithFlags.test.js +0 -142
  149. package/test/getOneValueDimensions.test.js +0 -26
  150. package/test/getSeriesAdvancedAttributes.test.js +0 -32
  151. package/test/getSubtitleFlags.test.js +0 -42
  152. package/test/getTableData.test.js +0 -1317
  153. package/test/getUnitsArtefacts.test.js +0 -117
  154. package/test/getUnitsDefinition.test.js +0 -37
  155. package/test/getUnitsInLayout.test.js +0 -77
  156. package/test/getUnitsSeries.test.js +0 -154
  157. package/test/invertTime.test.js +0 -77
  158. package/test/parseAttributesValuesFromObservations.test.js +0 -45
  159. package/test/parseDimensionsIds.test.js +0 -20
  160. package/test/prepareData.test.js +0 -29
  161. package/test/refineObservationsAttributesValues.test.js +0 -33
  162. package/test/table-invert-time-perf.test.js +0 -11
  163. package/test/table-layout-perf.test.js +0 -74
  164. package/test/table-prep-duplicate-perf.test.js +0 -15
  165. package/test/table-prep-perf.test.js +0 -61
@@ -0,0 +1,72 @@
1
+ import * as R from 'ramda';
2
+ import { getFlagsAndNotes } from './getFlagsAndNotes';
3
+ import { hasCellMetadata } from '../hasCellMetadata';
4
+ import { trimedProps } from '../utils';
5
+
6
+ export const getCellRelevantAttributes = (attributes, attributesSeries, cellAttributeIds) => R.filter(
7
+ (attr) => {
8
+ if (R.has(attr.id, cellAttributeIds)) {
9
+ return true;
10
+ }
11
+ const attrInSerie = R.path([attr.serieKey, attr.id], attributesSeries);
12
+ return R.isNil(attrInSerie);
13
+ },
14
+ attributes
15
+ );
16
+
17
+ export const getCellCombinedAttributes = (attributes, combinations) => R.reduce(
18
+ (acc, comb) => {
19
+ const values = trimedProps(comb.concepts, attributes);
20
+ if (R.isEmpty(values)) {
21
+ return acc;
22
+ }
23
+ return R.append({ ...R.pick(['id', 'name'], comb), values: R.pluck('value', values) }, acc);
24
+ },
25
+ [],
26
+ combinations
27
+ )
28
+
29
+ // combinations = { cells, layout };
30
+ export const getCells = (customAttributes, cellsAttributesId, combinations, attributesSeries, metadataCoordinates) => observations => {
31
+ const attributesInLayoutCombination = R.pipe(
32
+ R.propOr([], 'layout'),
33
+ R.pluck('concepts'),
34
+ R.unnest
35
+ )(combinations);
36
+
37
+ const attributesInCellsCombination = R.pipe(
38
+ R.propOr([], 'cells'),
39
+ R.pluck('concepts'),
40
+ R.unnest
41
+ )(combinations);
42
+
43
+ const _customAttributes = R.over(
44
+ R.lensProp('notes'),
45
+ notes => R.concat(notes || [], attributesInLayoutCombination)
46
+ )(customAttributes);
47
+
48
+ return R.mapObjIndexed(
49
+ obs => {
50
+ const relevantAttributes = getCellRelevantAttributes(obs.attributes, attributesSeries, cellsAttributesId);
51
+ const flagsAndNotes = getFlagsAndNotes(relevantAttributes, _customAttributes);
52
+ const combinedAttributes = getCellCombinedAttributes(relevantAttributes, combinations.cells || []);
53
+
54
+ const hasAdvancedAttributes = R.pipe(
55
+ R.omit(R.unnest([_customAttributes.flags || [], _customAttributes.notes || [], attributesInCellsCombination])),
56
+ R.isEmpty,
57
+ R.not
58
+ )(relevantAttributes);
59
+
60
+ const hasMetadata = hasCellMetadata(metadataCoordinates, obs.indexedDimValIds);
61
+
62
+ return ({
63
+ ...R.pick(['indexedDimValIds', 'key'], obs),
64
+ flags: R.concat(flagsAndNotes, combinedAttributes),
65
+ sideProps: hasAdvancedAttributes || hasMetadata ? { hasAdvancedAttributes, hasMetadata, coordinates: obs.indexedDimValIds } : null,
66
+ intValue: R.is(Number, obs.value) ? obs.value : null,
67
+ value: obs.formattedValue,
68
+ });
69
+ },
70
+ observations
71
+ );
72
+ };
@@ -0,0 +1,38 @@
1
+ import * as R from 'ramda';
2
+
3
+ export const getCellsAttributesIds = (layoutIds, attributes) => {
4
+ return R.reduce(
5
+ (acc, attr) => {
6
+ if (!attr.series) {
7
+ return acc;
8
+ }
9
+ if (R.isEmpty(attr.relationship || [])) {
10
+ return R.assoc(attr.id, attr.id, acc);
11
+ }
12
+ const indexedHeaderIds = R.indexBy(R.identity, layoutIds.header);
13
+ const indexedSectionsIds = R.indexBy(R.identity, layoutIds.sections);
14
+ const indexedRowsIds = { ...indexedSectionsIds, ...R.indexBy(R.identity, layoutIds.rows) };
15
+ const [idsInHeader, rest] = R.partition(
16
+ id => R.has(id, indexedHeaderIds),
17
+ attr.relationship,
18
+ );
19
+ if (R.isEmpty(rest)) {
20
+ return acc;
21
+ } else if (!R.isEmpty(idsInHeader)) {
22
+ return R.assoc(attr.id, attr.id, acc);
23
+ } else {
24
+ const idsNotInSections = R.reject(id => R.has(id, indexedSectionsIds), attr.relationship);
25
+ if (R.isEmpty(idsNotInSections)) {
26
+ return acc;
27
+ }
28
+ const idsNotInRows = R.reject(id => R.has(id, indexedRowsIds), idsNotInSections);
29
+ if (R.isEmpty(idsNotInRows)) {
30
+ return acc;
31
+ }
32
+ }
33
+ return R.assoc(attr.id, attr.id, acc);
34
+ },
35
+ {},
36
+ attributes,
37
+ );
38
+ };
@@ -0,0 +1,38 @@
1
+ import * as R from 'ramda';
2
+ import { parseValueHierarchy } from './parseValueHierarchy';
3
+
4
+ export const getCombinationDimensionsData = (indexes, combination, previous, sameSerie) => {
5
+ let coordinates = {};
6
+ let ids = [];
7
+ let _sameSerie = sameSerie;
8
+ let hasAdvancedAttributes = false;
9
+
10
+ const { dimensions=[] } = combination;
11
+ const dimValues = R.addIndex(R.reduce)(
12
+ (acc, valIndex, dimIndex) => {
13
+ const dimension = R.nth(dimIndex, dimensions);
14
+ const value = R.nth(Math.abs(valIndex), R.propOr([], 'values', dimension));
15
+ hasAdvancedAttributes = !hasAdvancedAttributes ? value.hasAdvancedAttributes : true;
16
+ if (!value) {
17
+ return acc;
18
+ }
19
+ coordinates = R.assoc(dimension.id, value.id, coordinates);
20
+ ids = R.append(`${dimension.id}=${value.id}`, ids);
21
+ const previousValue = R.propOr({}, dimension.id, previous);
22
+ if (value.id === R.prop('id', previousValue || {}) && _sameSerie) {
23
+ return R.assoc(dimension.id, previousValue, acc);
24
+ }
25
+ else {
26
+ const parsedValue = parseValueHierarchy(value, _sameSerie ? previousValue || {} : {}, dimension.indexedValues);
27
+ if (!R.isNil(previous)) {
28
+ _sameSerie = false;
29
+ }
30
+ return R.assoc(dimension.id, parsedValue, acc);
31
+ }
32
+ },
33
+ {},
34
+ indexes
35
+ );
36
+
37
+ return ({ dimValues, coordinates, ids, sameSerie: _sameSerie, hasAdvancedAttributes });
38
+ };
@@ -0,0 +1,33 @@
1
+ import * as R from 'ramda';
2
+
3
+ export const getCuratedCells = (cells, layout) => {
4
+ const layoutIds = R.map(
5
+ R.pipe(
6
+ R.map(entry =>
7
+ R.has('dimensions', entry) ? R.pluck('id', entry.dimensions || []) : entry.id,
8
+ ),
9
+ R.unnest,
10
+ ),
11
+ )(layout);
12
+ return R.pipe(
13
+ R.values,
14
+ R.reduce((acc, cell) => {
15
+ const keys = R.map(
16
+ R.pipe(
17
+ R.map(dim => {
18
+ const val = R.prop(dim, cell.indexedDimValIds);
19
+ return `${dim}=${val}`;
20
+ }),
21
+ R.join(':'),
22
+ ),
23
+ layoutIds,
24
+ );
25
+
26
+ return R.over(
27
+ R.lensPath(R.props(['header', 'sections', 'rows'], keys)),
28
+ cells => (R.isNil(cells) ? [cell] : R.append(cell, cells)),
29
+ acc,
30
+ );
31
+ }, {}),
32
+ )(cells);
33
+ };
@@ -0,0 +1,21 @@
1
+ import * as R from 'ramda';
2
+
3
+ export const getFlagsAndNotes = (attributesValues, customAttributes) => {
4
+ const flagsIds = R.propOr([], 'flags', customAttributes);
5
+ const notesIds = R.propOr([], 'notes', customAttributes);
6
+
7
+ return R.addIndex(R.reduce)(
8
+ (acc, id, index) => {
9
+ if (!R.has(id, attributesValues)) {
10
+ return acc;
11
+ }
12
+ const attr = R.prop(id, attributesValues);
13
+ if (R.isNil(attr.value)) {
14
+ return acc;
15
+ }
16
+ return R.append(index < flagsIds.length ? R.assoc('code', R.path(['value', 'id'], attr), attr) : attr, acc);
17
+ },
18
+ [],
19
+ R.concat(flagsIds, notesIds)
20
+ );
21
+ };
@@ -0,0 +1,16 @@
1
+ import * as R from 'ramda';
2
+
3
+ export const getIndexedCombinationsByDisplay = (layout, combinations) => {
4
+ const layoutIds = R.pipe(
5
+ R.map(R.pluck('id')),
6
+ R.values,
7
+ R.unnest,
8
+ R.indexBy(R.identity),
9
+ )(layout);
10
+
11
+ const [combsInLayout, combsInCells] = R.partition(
12
+ comb => R.has(comb.id, layoutIds),
13
+ combinations,
14
+ );
15
+ return { cells: combsInCells, layout: combsInLayout };
16
+ };
@@ -0,0 +1,80 @@
1
+ import * as R from 'ramda';
2
+ import { isTimePeriodDimension } from '@sis-cc/dotstatsuite-sdmxjs';
3
+ import { trimedProps } from '../utils';
4
+
5
+ export const getLayout = (layoutIds, dimensions, combinations, isTimeInverted, fixedDimensions) => {
6
+ const indexedDimensions = R.pipe(
7
+ R.indexBy(R.prop('id')),
8
+ R.map(d => (isTimePeriodDimension(d) && isTimeInverted ? R.assoc('isInverted', true, d) : d)),
9
+ )(dimensions);
10
+ const indexedFixedDimsValues = R.reduce(
11
+ (acc, dim) => {
12
+ const value = R.head(dim.values);
13
+ return !dim.display || !value.display ? acc : R.assoc(dim.id, R.head(dim.values), acc);
14
+ },
15
+ {},
16
+ fixedDimensions,
17
+ );
18
+ const indexedHeaderIds = R.indexBy(R.identity, layoutIds.header);
19
+ const indexedSectionsIds = R.indexBy(R.identity, layoutIds.sections);
20
+ const indexedRowsIds = { ...indexedSectionsIds, ...R.indexBy(R.identity, layoutIds.rows) };
21
+ let layout = { header: [], sections: [], rows: [] };
22
+ R.forEach(comb => {
23
+ if (R.isEmpty(comb.relationship)) {
24
+ return;
25
+ }
26
+ const [idsInHeader, rest] = R.partition(id => R.has(id, indexedHeaderIds), comb.relationship);
27
+ if (R.isEmpty(rest)) {
28
+ layout = R.over(
29
+ R.lensProp('header'),
30
+ R.append({
31
+ ...comb,
32
+ dimensions: trimedProps(comb.concepts, indexedDimensions),
33
+ fixedDimValues: R.pick(comb.concepts, indexedFixedDimsValues),
34
+ }),
35
+ )(layout);
36
+ } else if (!R.isEmpty(idsInHeader)) {
37
+ return;
38
+ } else {
39
+ const idsNotInSections = R.reject(id => R.has(id, indexedSectionsIds), comb.relationship);
40
+ if (R.isEmpty(idsNotInSections)) {
41
+ layout = R.over(
42
+ R.lensProp('sections'),
43
+ R.append({
44
+ ...comb,
45
+ dimensions: trimedProps(comb.concepts, indexedDimensions),
46
+ fixedDimValues: R.pick(comb.concepts, indexedFixedDimsValues),
47
+ }),
48
+ )(layout);
49
+ } else {
50
+ const idsNotInRows = R.reject(id => R.has(id, indexedRowsIds), comb.relationship);
51
+ if (R.isEmpty(idsNotInRows)) {
52
+ layout = R.over(
53
+ R.lensProp('rows'),
54
+ R.append({
55
+ ...comb,
56
+ dimensions: R.pipe(R.omit(layoutIds.sections), o => trimedProps(comb.concepts, o))(
57
+ indexedDimensions,
58
+ ),
59
+ fixedDimValues: R.pick(comb.concepts, indexedFixedDimsValues),
60
+ }),
61
+ )(layout);
62
+ }
63
+ }
64
+ }
65
+ }, combinations);
66
+ return R.mapObjIndexed((combs, key) => {
67
+ const conceptIds = R.pipe(R.pluck('concepts'), R.unnest, R.indexBy(R.identity))(combs);
68
+ const rest = R.reduce(
69
+ (acc, id) => {
70
+ if (R.has(id, conceptIds)) {
71
+ return acc;
72
+ }
73
+ return R.append(R.prop(id, indexedDimensions), acc);
74
+ },
75
+ [],
76
+ layoutIds[key],
77
+ );
78
+ return R.concat(rest, combs);
79
+ }, layout);
80
+ };
@@ -0,0 +1,183 @@
1
+ import * as R from 'ramda';
2
+ import { getFlagsAndNotes } from './getFlagsAndNotes';
3
+ import { hasCellMetadata } from '../hasCellMetadata';
4
+ import { getCombinationDimensionsData } from './getCombinationDimensionsData';
5
+ import { parseValueHierarchy } from './parseValueHierarchy';
6
+
7
+ const getSubLayoutData = (series, _definition, { metadataCoordinates, attributesSeries, customAttributes }) => {
8
+ const getHasAdvancedAttributes = (attrValues) => R.pipe(
9
+ R.omit(R.concat(customAttributes.flags, customAttributes.notes)),
10
+ R.isEmpty,
11
+ R.not
12
+ )(attrValues);
13
+
14
+ const combinationConceptIds = R.reduce(
15
+ (acc, def) => {
16
+ const concepts = R.propOr([], 'concepts', def);
17
+ if (R.isEmpty(concepts)) {
18
+ return acc;
19
+ }
20
+ return R.concat(acc, concepts);
21
+ },
22
+ [],
23
+ _definition
24
+ );
25
+
26
+ const definition = R.map( //used for parseValueHierarchy ...
27
+ (entry) => {
28
+ if (R.has('dimensions', entry)) {
29
+ return ({
30
+ ...entry,
31
+ dimensions: R.map(
32
+ dim => R.assoc('indexedValues', R.indexBy(R.prop('id'), dim.values || []), dim),
33
+ entry.dimensions
34
+ )
35
+ });
36
+ }
37
+ return R.assoc('indexedValues', R.indexBy(R.prop('id'), entry.values || []), entry);
38
+ },
39
+ _definition
40
+ );
41
+
42
+ const { res } = R.reduce(
43
+ (acc, serie) => {
44
+ let data = [];
45
+ let next = [];
46
+ let sameSerie = true;
47
+ let i = 0;
48
+ let hasAdvancedAttributes = false;
49
+ let coordinates = {};
50
+ let ids = [];
51
+ while (i < serie.length) {
52
+ const entry = serie[i];
53
+ if (R.is(Array, entry)) {
54
+ const combination = definition[i];
55
+ const previousDimValues = R.nth(i, acc.previous);
56
+ const combData = getCombinationDimensionsData(entry, combination, previousDimValues, sameSerie);
57
+ data = R.append({
58
+ dimension: R.pick(['id', 'name'], combination),
59
+ dimValues: combData.dimValues
60
+ }, data);
61
+ next = R.append(combData.dimValues, next);
62
+ hasAdvancedAttributes = !hasAdvancedAttributes ? combData.hasAdvancedAttributes : true;
63
+ sameSerie = combData.sameSerie;
64
+ coordinates = { ...coordinates, ...combData.coordinates };
65
+ ids = R.concat(ids, combData.ids);
66
+ }
67
+ else {
68
+ const dimension = definition[i];
69
+ const value = R.nth(Math.abs(entry), dimension.values || []);
70
+ const previousValue = R.nth(i, acc.previous) || {};
71
+ coordinates = R.assoc(dimension.id, value.id, coordinates);
72
+ ids = R.append(`${dimension.id}=${value.id}`, ids);
73
+ if (value.id === R.prop('id', previousValue || {}) && sameSerie) {
74
+ next = R.append(previousValue, next);
75
+ data = R.append({
76
+ dimension: R.pick(['id', 'name', '__index'], dimension),
77
+ value: previousValue,
78
+ }, data);
79
+ }
80
+ else {
81
+ hasAdvancedAttributes = !hasAdvancedAttributes ? value.hasAdvancedAttributes : true;
82
+ const parsedValue = parseValueHierarchy(value, sameSerie ? previousValue || {} : {}, dimension.indexedValues);
83
+ next = R.append(parsedValue, next);
84
+ data = R.append({
85
+ dimension: R.pick(['id', 'name', '__index'], dimension),
86
+ value: parsedValue,
87
+ }, data);
88
+ if (!R.isNil(acc.previous)) {
89
+ sameSerie = false;
90
+ }
91
+ }
92
+ }
93
+ i++;
94
+ }
95
+
96
+ const attributesValues = R.reduce(
97
+ (acc, key) => {
98
+ const splitKey = R.split(':', key);
99
+ const isValid = R.all(entry => {
100
+ const [d, v] = R.split('=', entry);
101
+ return R.propEq(d, v, coordinates);
102
+ }, splitKey);
103
+ return isValid ? { ...acc, ...(R.length(splitKey) === 1 ? R.pick(combinationConceptIds, R.prop(key, attributesSeries)) : R.prop(key, attributesSeries)) } : acc;
104
+ },
105
+ {},
106
+ R.keys(attributesSeries)
107
+ );
108
+
109
+ data = R.addIndex(R.map)(
110
+ (entry, ind) => {
111
+ if (!R.has('dimValues', entry)) {
112
+ return entry;
113
+ }
114
+ const { dimValues, dimension } = entry;
115
+ const def = R.nth(ind, definition);
116
+ const fixedDimValues = R.propOr([], 'fixedDimValues', def);
117
+ const values = R.reduce(
118
+ (_acc, id) => {
119
+ if (R.has(id, dimValues)) {
120
+ return R.append(R.prop(id, dimValues), _acc);
121
+ }
122
+ if (R.has(id, fixedDimValues)) {
123
+ return R.append(R.prop(id, fixedDimValues), _acc);
124
+ }
125
+ if (!R.has(id, attributesValues)) {
126
+ return _acc;
127
+ }
128
+ return R.append(R.path([id, 'value'], attributesValues), _acc);
129
+ },
130
+ [],
131
+ def.concepts
132
+ );
133
+ return ({ dimension, values });
134
+ },
135
+ data
136
+ );
137
+
138
+ const layoutAttrValues = R.pipe(
139
+ R.omit(combinationConceptIds),
140
+ R.reject(R.prop('isObs'))
141
+ )(attributesValues);
142
+
143
+ const flags = getFlagsAndNotes(layoutAttrValues, customAttributes);
144
+ const hasMetadata = hasCellMetadata(metadataCoordinates, coordinates);
145
+
146
+ if (!hasAdvancedAttributes) {
147
+ hasAdvancedAttributes = getHasAdvancedAttributes(layoutAttrValues);
148
+ }
149
+
150
+ const sideProps = hasMetadata || hasAdvancedAttributes
151
+ ? { hasMetadata, hasAdvancedAttributes, coordinates } : null;
152
+
153
+ return {
154
+ res: R.append({ data, key: R.join(':', ids), flags, sideProps }, acc.res),
155
+ previous: next,
156
+ };
157
+ },
158
+ { res: [], previous: [] },
159
+ series
160
+ );
161
+
162
+ return res;
163
+ };
164
+
165
+ export const getLayoutData = (layoutIndexes, layout, { metadataCoordinates, attributesSeries, customAttributes }) => {
166
+ const { header, sections, ...rest } = layoutIndexes;
167
+ const opts = { metadataCoordinates, attributesSeries, customAttributes };
168
+ const headerData = getSubLayoutData(header, layout.header, opts);
169
+ const sectionsData = R.pipe(
170
+ R.transpose,
171
+ ([sections, sectionsRows]) => {
172
+ if (R.isNil(sections)) {
173
+ return [];
174
+ }
175
+ const _sectionsData = getSubLayoutData(sections, layout.sections, opts);
176
+ const rowsData = R.map(rows => getSubLayoutData(rows, layout.rows, opts), sectionsRows);
177
+
178
+ return R.transpose([_sectionsData, rowsData]);
179
+ }
180
+ )(sections);
181
+
182
+ return ({ headerData, sectionsData, ...rest });
183
+ };
@@ -0,0 +1,119 @@
1
+ import * as R from 'ramda';
2
+
3
+ /*
4
+ const layout = {
5
+ header: [
6
+ { id, __index },
7
+ { id: COMB, dimensions: [{ id, __index }] }
8
+ ],
9
+ sections: [],
10
+ rows: []
11
+ }
12
+
13
+ */
14
+
15
+ const getLayoutPivots = layoutEntry => {
16
+ const valIndexGetter = d => R.pipe(
17
+ R.nth(R.prop('__index', d)),
18
+ ind => d.isInverted ? R.negate(ind) : ind
19
+ );
20
+ return indexes => R.map(
21
+ R.ifElse(
22
+ R.has('dimensions'),
23
+ c => R.map(d => valIndexGetter(d)(indexes), R.prop('dimensions', c)),
24
+ d => valIndexGetter(d)(indexes)
25
+ ),
26
+ layoutEntry
27
+ );
28
+ };
29
+
30
+ const comparator = (a, b) => {
31
+ const size = R.length(a);
32
+ let i = 0;
33
+ while (i < size) {
34
+ if (R.is(Array, a[i])) {
35
+ const _a = a[i];
36
+ const _b = b[i];
37
+ const _size = R.length(_a);
38
+ let j = 0;
39
+ while (_a[j] === _b[j] && j < _size) {
40
+ j++;
41
+ }
42
+ if (_a[j] !== _b[j]) {
43
+ return _a[j] - _b[j];
44
+ }
45
+ }
46
+ else if (a[i] !== b[i]) {
47
+ return a[i] - b[i];
48
+ }
49
+ i++;
50
+ }
51
+ return a[i] - b[i];
52
+ };
53
+
54
+ // simple call to ramda uniq method is very slow regarding performance
55
+ const uniqIndexes = (indexes) => R.pipe(
56
+ R.reduce(
57
+ (acc, i) => {
58
+ const key = R.join(':', R.unnest(i));
59
+ if (R.has(key, acc.keys)) {
60
+ return acc;
61
+ }
62
+ return ({
63
+ indexes: R.append(i, acc.indexes),
64
+ keys: R.assoc(key, key, acc.keys)
65
+ });
66
+ },
67
+ { indexes: [], keys: {} },
68
+ ),
69
+ R.prop('indexes')
70
+ )(indexes);
71
+
72
+ export const getSortedLayoutIndexes = (layout, observations) => {
73
+ const dimIndexes = R.pipe(R.values, R.map(R.propOr([], 'orderedDimIndexes')))(observations);
74
+
75
+ const headerPivots = getLayoutPivots(layout.header);
76
+ const sectionsPivots = getLayoutPivots(R.concat(layout.sections, layout.rows));
77
+
78
+ const sectionLength = R.length(layout.sections);
79
+ const { header, sections } = R.pipe(
80
+ R.reduce(
81
+ (acc, indexes) => {
82
+ const headerIndexes = headerPivots(indexes);
83
+ const sectionsIndexes = sectionsPivots(indexes);
84
+
85
+ return ({
86
+ header: R.append(headerIndexes, acc.header),
87
+ sections: R.append(sectionsIndexes, acc.sections)
88
+ });
89
+ },
90
+ { header: [], sections: [] },
91
+ ),
92
+ R.mapObjIndexed(uniqIndexes),
93
+ R.evolve({
94
+ header: R.sort(comparator),
95
+ sections: R.sort(comparator)
96
+ }),
97
+ indexes => ({
98
+ ...indexes,
99
+ sections: R.reduce(
100
+ (acc, i) => {
101
+ const [sectionIndexes, rowIndexes] = R.splitAt(sectionLength, i);
102
+ const previousSecIndexes = R.pipe(R.nth(-1), i => R.isNil(i) ? null : R.head(i))(acc);
103
+ if (R.equals(R.unnest(sectionIndexes), previousSecIndexes ? R.unnest(previousSecIndexes) : null)) { //perhaps a bit dirty ...
104
+ return R.over(
105
+ R.lensIndex(-1),
106
+ R.over(R.lensIndex(1), R.append(rowIndexes))
107
+ )(acc);
108
+ }
109
+
110
+ return R.append([sectionIndexes, [rowIndexes]], acc);
111
+ },
112
+ [],
113
+ indexes.sections
114
+ )
115
+ })
116
+ )(dimIndexes);
117
+
118
+ return ({ header, sections });
119
+ };
@@ -0,0 +1,36 @@
1
+ import * as R from 'ramda';
2
+ import { getLayout } from './getLayout';
3
+ import { getSortedLayoutIndexes } from './getSortedLayoutIndexes';
4
+ import { refineLayoutSize } from './refineLayoutSize';
5
+ import { getLayoutData } from './getLayoutData';
6
+ import { getCellsAttributesIds } from './getCellsAttributesIds';
7
+ import { getIndexedCombinationsByDisplay } from './getIndexedCombinationsByDisplay';
8
+ import { getCells } from './getCells';
9
+ import { getCuratedCells } from './getCuratedCells';
10
+
11
+ export const getTableProps = ({ data, layoutIds, customAttributes, limit, isTimeInverted }) => {
12
+ const {
13
+ observations,
14
+ dimensions,
15
+ combinations,
16
+ oneValueDimensions,
17
+ attributesSeries,
18
+ metadataCoordinates,
19
+ attributes
20
+ } = data;
21
+
22
+ const seriesCombinations = R.filter(R.prop('series'), combinations);
23
+ const layout = getLayout(layoutIds, dimensions, seriesCombinations, isTimeInverted, oneValueDimensions);
24
+ const layoutIndexes = getSortedLayoutIndexes(layout, observations);
25
+ const refinedLayoutIndexes = refineLayoutSize({ layout, observations, limit })(layoutIndexes);
26
+ const layoutData = getLayoutData(refinedLayoutIndexes, layout, { metadataCoordinates, attributesSeries, customAttributes });
27
+
28
+ const cellsAttributesIds = getCellsAttributesIds(layoutIds, attributes);
29
+ const indexedCombinations = getIndexedCombinationsByDisplay(layout, seriesCombinations);
30
+ const cells = getCells(customAttributes, cellsAttributesIds, indexedCombinations, attributesSeries, metadataCoordinates)(observations);
31
+
32
+ return ({
33
+ ...layoutData,
34
+ cells: getCuratedCells(cells, layout)
35
+ });
36
+ };
@@ -0,0 +1,27 @@
1
+ import * as R from 'ramda';
2
+
3
+ export const parseValueHierarchy = (value, previousValue, indexedValues) => {
4
+ const parentsIds = R.propOr([], 'parents', value);
5
+ if (R.isEmpty(parentsIds)) {
6
+ return value;
7
+ }
8
+ const _previousParentsIds = R.propOr([], 'parentsIds', previousValue);
9
+ const previousParentsIds = R.isNil(previousValue) ? [] : R.append(R.prop('id', previousValue), _previousParentsIds);
10
+ const [presentIds, missingIds] = R.addIndex(R.splitWhen)((val, ind) => R.nth(ind, previousParentsIds) !== val, parentsIds);
11
+ //console.log({ presentIds, missingIds });
12
+ const _previousParents = R.propOr([], 'parents', previousValue);
13
+ const previousParents = R.isNil(previousValue) ? [] : R.append(R.pick(['id', 'name'], previousValue), _previousParents);
14
+ //console.log('previousParents', previousParents);
15
+ const parents = R.takeWhile(p => R.includes(p.id, presentIds), previousParents);
16
+ const missingParents = R.concat(
17
+ R.includes(R.prop('id', previousValue), presentIds)
18
+ ? [] : R.takeWhile(p => R.includes(p.id, presentIds), R.propOr([], 'missingParents', previousValue)),
19
+ R.props(missingIds, indexedValues)
20
+ );
21
+ return ({
22
+ ...value,
23
+ parents,
24
+ parentsIds,
25
+ missingParents
26
+ });
27
+ };