@sis-cc/dotstatsuite-components 9.3.5 → 12.0.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 (56) hide show
  1. package/lib/index.js +8 -3
  2. package/lib/rules/src/table/factories/getCells.js +22 -4
  3. package/lib/rules/src/table/factories/getLayoutWithFlags.js +32 -5
  4. package/lib/rules/src/table/factories/getTableData.js +9 -2
  5. package/lib/rules/src/table/preparators/prepareData.js +37 -2
  6. package/lib/rules/src/v8-transformer.js +5 -9
  7. package/lib/rules2/src/constants.js +7 -0
  8. package/lib/rules2/src/getAdvAttrSeriesAtCoordinates.js +39 -0
  9. package/lib/rules2/src/getAdvancedAttributes.js +126 -0
  10. package/lib/rules2/src/getMetadataCoordinates.js +38 -0
  11. package/lib/rules2/src/getMetadataStructureFromData.js +23 -0
  12. package/lib/rules2/src/getSidebarData.js +76 -0
  13. package/lib/rules2/src/hasCellMetadata.js +19 -0
  14. package/lib/rules2/src/hasLayoutEntryMetadata.js +18 -0
  15. package/lib/rules2/src/index.js +47 -0
  16. package/lib/rules2/src/parseMetadataSeries.js +83 -0
  17. package/lib/rules2/src/refineMetadataCoordinates.js +34 -0
  18. package/lib/rules2/src/sdmx3.0DataFormatPatch.js +20 -0
  19. package/lib/viewer/src/chart.js +48 -41
  20. package/lib/viewer/src/index.js +76 -56
  21. package/package.json +9 -10
  22. package/src/index.js +2 -0
  23. package/src/rules/src/table/factories/getCells.js +13 -4
  24. package/src/rules/src/table/factories/getLayoutWithFlags.js +36 -10
  25. package/src/rules/src/table/factories/getTableData.js +12 -3
  26. package/src/rules/src/table/preparators/prepareData.js +45 -4
  27. package/src/rules/src/v8-transformer.js +3 -8
  28. package/src/rules2/src/constants.js +2 -0
  29. package/src/rules2/src/getAdvAttrSeriesAtCoordinates.js +29 -0
  30. package/src/rules2/src/getAdvancedAttributes.js +113 -0
  31. package/src/rules2/src/getMetadataCoordinates.js +37 -0
  32. package/src/rules2/src/getMetadataStructureFromData.js +17 -0
  33. package/src/rules2/src/getSidebarData.js +73 -0
  34. package/src/rules2/src/hasCellMetadata.js +11 -0
  35. package/src/rules2/src/hasLayoutEntryMetadata.js +9 -0
  36. package/src/rules2/src/index.js +8 -0
  37. package/src/rules2/src/parseMetadataSeries.js +80 -0
  38. package/src/rules2/src/refineMetadataCoordinates.js +27 -0
  39. package/src/rules2/src/sdmx3.0DataFormatPatch.js +9 -0
  40. package/src/viewer/src/chart.js +15 -14
  41. package/src/viewer/src/index.js +35 -26
  42. package/test/advanced-attributes-parsing-perf.test.js +16 -0
  43. package/test/getCells.test.js +7 -5
  44. package/test/getDataflowAdvancedAttributes.test.js +32 -0
  45. package/test/getLayoutDataWithFlags.test.js +22 -12
  46. package/test/getMetadataCoordinates.test.js +0 -0
  47. package/test/getSeriesAdvancedAttributes.test.js +30 -0
  48. package/test/getSidebarData.test.js +116 -0
  49. package/test/getSubtitleFlags.test.js +1 -1
  50. package/test/getTableData.test.js +2 -1
  51. package/test/metadata-parsing-perf.test.js +487 -0
  52. package/test/mocks/OECD_SNA_TABLE1_1.0_-_AUS_V_metadata.json +152 -0
  53. package/test/mocks/large_metadata_series.json +701 -0
  54. package/test/mocks/observations-advanced-attributes.json +55382 -0
  55. package/test/parseMetadataSeries.test.js +55 -0
  56. package/test/prepareData.test.js +2 -0
@@ -1,6 +1,7 @@
1
1
  import * as R from 'ramda';
2
2
  import { getFlags } from './getCells';
3
3
  import { dimensionValueDisplay } from '../../dimension-utils';
4
+ import { hasCellMetadata } from '../../../../rules2/src/hasCellMetadata';
4
5
 
5
6
  export const getLayoutSerieAttributes = (layoutSerie, seriesAttributes) => {
6
7
  const length = R.length(layoutSerie);
@@ -72,15 +73,39 @@ const getSerieKey = R.pipe(R.reduce(
72
73
  []
73
74
  ), R.join(':'));
74
75
 
75
- export const getLayoutDataWithFlags = (seriesAttributes, display, customAttributes) => {
76
- const formatSublayout = getAttributes => R.converge(
77
- (data, key, flags) => ({ data, key, flags }),
78
- [
79
- getSublayoutDataCells(display, customAttributes),
80
- getSerieKey,
81
- R.pipe(getAttributes, getFlagsFromSeriesAttributes(display, customAttributes))
82
- ]
83
- );
76
+ const getCoordinates = (data, unitsId) => R.reduce(
77
+ (acc, entry) => {
78
+ const dimId = R.path(['dimension', 'id'], entry);
79
+ const valId = R.path(['value', 'id'], entry);
80
+ if (dimId === unitsId) {
81
+ return acc;
82
+ }
83
+ return R.assoc(dimId, valId, acc);
84
+ },
85
+ {},
86
+ data
87
+ );
88
+
89
+ export const getLayoutDataWithFlags = (seriesAttributes, display, customAttributes, metadataCoordinates, unitsId) => {
90
+ const regularAttrsIds = R.concat(customAttributes.flags || [], customAttributes.footnotes || []);
91
+ const formatSublayout = (getAttributes, supplData = []) => data => {
92
+ const attributes = getAttributes(data);
93
+ const key = getSerieKey(data);
94
+ const cells = getSublayoutDataCells(display, customAttributes)(data);
95
+ const flags = getFlagsFromSeriesAttributes(display, customAttributes)(attributes);
96
+ const coordinates = getCoordinates(R.concat(supplData, data), unitsId);
97
+ const hasMetadata = hasCellMetadata(metadataCoordinates, coordinates);
98
+ const advancedAttributesSeries = R.isNil(attributes)
99
+ ? {}
100
+ : R.filter(
101
+ serie => !R.isEmpty(R.omit(regularAttrsIds, R.propOr({}, 'attributes', serie))),
102
+ attributes
103
+ );
104
+ const hasAdvancedAttributes = !R.isEmpty(advancedAttributesSeries);
105
+ const sideProps = hasMetadata || hasAdvancedAttributes ? { hasAdvancedAttributes, hasMetadata, coordinates } : null;
106
+
107
+ return ({ data: cells, key, flags, sideProps });
108
+ };
84
109
 
85
110
  return R.evolve({
86
111
  headerData: R.map(formatSublayout(data => getLayoutSerieAttributes(data, seriesAttributes))),
@@ -91,7 +116,8 @@ export const getLayoutDataWithFlags = (seriesAttributes, display, customAttribut
91
116
  return ([
92
117
  formatSublayout(() => sectionAttributes)(sectionSerie),
93
118
  R.map(
94
- formatSublayout(rowData => getLayoutSerieAttributes(R.concat(sectionSerie, rowData), R.omit(R.keys(sectionAttributes), seriesAttributes)))
119
+ formatSublayout(rowData => getLayoutSerieAttributes(R.concat(sectionSerie, rowData), R.omit(R.keys(sectionAttributes), seriesAttributes)),
120
+ sectionSerie)
95
121
  )(R.last(sectionData))
96
122
  ]);
97
123
  }
@@ -13,6 +13,7 @@ import { cleanUnitsInLayoutData } from '../units/cleanUnitsInLayoutData';
13
13
  import { getSortedLayoutIndexes } from './getSortedLayoutIndexes';
14
14
  import { refineLayoutSize } from './refineLayoutSize';
15
15
  import { getLayoutData } from './getLayoutData';
16
+ import { refineMetadataCoordinates } from '../../../../rules2/src/refineMetadataCoordinates';
16
17
 
17
18
  export const getTableProps = ({ data, layoutIds, display, customAttributes, limit, isTimeInverted }) => {
18
19
  const seriesAttributes = R.propOr({}, 'seriesAttributes', data);
@@ -22,6 +23,12 @@ export const getTableProps = ({ data, layoutIds, display, customAttributes, limi
22
23
  layoutIds
23
24
  );
24
25
 
26
+ const headerDimensionsIds = R.pluck('id',
27
+ R.concat(R.pathOr([], ['units', 'headerUnits'], data), R.values(R.pathOr({}, ['dimensions', 'one'], data)))
28
+ );
29
+
30
+ const refinedMetadataCoordinates = refineMetadataCoordinates(data.metadataCoordinates, layoutIds, headerDimensionsIds);
31
+
25
32
  const {
26
33
  rejectedValueIds,
27
34
  unitDimension,
@@ -45,7 +52,8 @@ export const getTableProps = ({ data, layoutIds, display, customAttributes, limi
45
52
  unitsDefinitionCodes, unitsSeries, unitsDisplay: unitsLevelDisplay,
46
53
  unitDimension, rejectedValueIds, layoutDimsIds
47
54
  },
48
- data.observationsType
55
+ refinedMetadataCoordinates.cells,
56
+ data.observationsType,
49
57
  );
50
58
 
51
59
  const dimensions = R.mapObjIndexed(
@@ -89,9 +97,10 @@ export const getTableProps = ({ data, layoutIds, display, customAttributes, limi
89
97
  unitsDefinitionCodes, unitsIndexes: unitsAttachmentIndexesInLayout,
90
98
  partialUnitSerieIndexes, rejectedValueIds, layoutIds
91
99
  }),
92
- getLayoutDataWithFlags(seriesAttributesValues, display, customAttributes),
93
- cleanUnitsInLayoutData({ unitsDisplay: unitsLevelDisplay, unitsLayoutIndexes: unitsIndexesInLayout })
100
+ getLayoutDataWithFlags(seriesAttributesValues, display, customAttributes, refinedMetadataCoordinates.layout, unitDimension.id),
101
+ cleanUnitsInLayoutData({ unitsDisplay: unitsLevelDisplay, unitsLayoutIndexes: unitsIndexesInLayout }),
94
102
  )(layout, R.propOr({}, 'observations', data));
103
+
95
104
  return ({
96
105
  cells: getCuratedCells({ layout, observations: cells, shape: ['header', 'sections', 'rows'] }),
97
106
  layout,
@@ -21,6 +21,13 @@ import { getDisplay } from '../../preparators/getDisplay';
21
21
  import { getObservations } from '../../preparators/getObservations';
22
22
  import { enhanceObservations } from '../../preparators/enhanceObservations';
23
23
 
24
+ import { getMetadataCoordinates } from '../../../../rules2/src/getMetadataCoordinates';
25
+ import {
26
+ getDataflowAdvancedAttributes,
27
+ getObservationsAdvancedAttributes,
28
+ getSeriesAdvancedAttributes
29
+ } from '../../../../rules2/src/getAdvancedAttributes';
30
+
24
31
  export const prepareData = (sdmxJson, customAttributes, unitsProps={}) => {
25
32
  const {
26
33
  defaultCodes=[],
@@ -127,10 +134,42 @@ export const prepareData = (sdmxJson, customAttributes, unitsProps={}) => {
127
134
  attributesIndexedByIds,
128
135
  );
129
136
 
130
- const seriesAttributesValues = refineSeriesAttributesValues(
131
- dimensionsAttributesValues.series,
132
- attributesIndexedByIds,
137
+ const seriesAttributesValues = R.map(
138
+ series => refineSeriesAttributesValues(series, attributesIndexedByIds),
139
+ dimensionsAttributesValues
140
+ );
141
+
142
+ const metadataCoordinates = getMetadataCoordinates(sdmxJson);
143
+ const headerAttributesIds = R.concat(attributesIdsIndexedByTargets.dataflow || [], attributesIdsIndexedByTargets.oneValueDimensions || []);
144
+ const headerAttributes = R.pick(headerAttributesIds, attributesIndexedByIds);
145
+ const headerAdvancedAttrIds = R.pipe(
146
+ R.filter(id => !R.includes(id, customAttributes.flags || []) && !R.includes(id, customAttributes.footnotes || [])),
147
+ )(headerAttributesIds);
148
+
149
+ const dataflowAdvancedAttributes = getDataflowAdvancedAttributes(
150
+ headerAttributes,
151
+ oneValueDimensions,
152
+ headerAdvancedAttrIds,
153
+ R.length(dimensions)
154
+ );
155
+
156
+ const observationsAdvancedAttributesIds = R.filter(
157
+ id => !R.includes(id, customAttributes.flags || []) && !R.includes(id, customAttributes.footnotes || []),
158
+ attributesIdsIndexedByTargets.observations || []
133
159
  );
160
+ const observationsAdvancedAttributes = getObservationsAdvancedAttributes(observations, observationsAdvancedAttributesIds);
161
+
162
+ const seriesAdvancedAttributesIds = R.filter(
163
+ id => !R.includes(id, customAttributes.flags || []) && !R.includes(id, customAttributes.footnotes || []),
164
+ R.concat(attributesIdsIndexedByTargets.series || [], attributesIdsIndexedByTargets.manyValuesDimensions || [])
165
+ );
166
+
167
+ const seriesAdvancedAttributes = getSeriesAdvancedAttributes(
168
+ seriesAttributesValues,
169
+ dimensions,
170
+ seriesAdvancedAttributesIds
171
+ );
172
+
134
173
  return ({
135
174
  dimensions: {
136
175
  one: oneValueDimensions,
@@ -144,11 +183,13 @@ export const prepareData = (sdmxJson, customAttributes, unitsProps={}) => {
144
183
  unitsAttachmentSeriesIds,
145
184
  unitsSeries,
146
185
  },
186
+ metadataCoordinates,
187
+ advancedAttributes: { ...dataflowAdvancedAttributes, ...observationsAdvancedAttributes, ...seriesAdvancedAttributes },
147
188
  observations,
148
189
  observationsType: getObservationsType(sdmxJson.data),
149
190
  dataflowAttributes,
150
191
  dataflowName: R.path(['data', 'structure', 'name'], sdmxJson),
151
192
  seriesAttributes: R.props(seriesAttributesIds, attributesIndexedByIds),
152
- seriesAttributesValues
193
+ seriesAttributesValues: seriesAttributesValues.series || {}
153
194
  });
154
195
  };
@@ -95,22 +95,17 @@ export const dataTransformer = (dataNew, options = {}) => {
95
95
  const getAttrObservations = R.propOr([], 'observation');
96
96
  const attrObservations = getAttrObservations(attributes);
97
97
 
98
- const getAttrDataset = R.propOr([], 'dataset')
99
- const attrDataset = getAttrDataset(attributes);
100
-
101
- const mergeAttr = R.concat(attrDataset, attrObservations);
102
-
103
98
  const resAttrObservations = R.map((observation) => ({
104
99
  ...observation,
105
100
  name: getLocalisedProp('names', observation),
106
- values: getValues(observation.values),
101
+ values: getValues(observation.values || []),
107
102
  roles: !R.isNil(observation.role) ? R.head(observation.role) : null,
108
- }), mergeAttr);
103
+ }), attrObservations);
109
104
 
110
105
  const resAttributes = {
111
106
  ...attributes,
112
107
  observation: resAttrObservations,
113
- }
108
+ };
114
109
 
115
110
  //----------------------------------------------------------------------------------------Dimensions
116
111
  const getDimensions = R.propOr({}, 'dimensions');
@@ -0,0 +1,2 @@
1
+ export const SDMX_3_0_JSON_DATA_FORMAT = 'application/vnd.sdmx.data+json;version=2.0';
2
+ export const SDMX_3_0_CSV_DATA_FORMAT = 'application/vnd.sdmx.data+csv;version=2.0';
@@ -0,0 +1,29 @@
1
+ import * as R from 'ramda';
2
+
3
+ const attribueValueDisplay = (display) => data => {
4
+ if (display === 'code') {
5
+ return R.prop('id', data);
6
+ }
7
+ if (display === 'both') {
8
+ return `${R.prop('id', data)}: ${R.prop('name', data)}`;
9
+ }
10
+ return R.prop('name', data);
11
+ };
12
+
13
+ export const getAdvAttrSeriesAtCoordinates = (coordinates, advancedAttributes, display) => R.pipe(
14
+ R.filter(serie => {
15
+ const mergedCoord = R.mergeLeft(serie.coordinates, coordinates);
16
+ return R.equals(mergedCoord, coordinates);
17
+ }),
18
+ R.map(serie => {
19
+ return R.pipe(
20
+ R.propOr({}, 'attributes'),
21
+ R.values,
22
+ R.map(attribute => ({
23
+ id: attribute.id,
24
+ label: attribueValueDisplay(display)(attribute),
25
+ value: attribueValueDisplay(display)(attribute.value)
26
+ }))
27
+ )(serie);
28
+ }),
29
+ )(advancedAttributes);
@@ -0,0 +1,113 @@
1
+ import * as R from 'ramda';
2
+
3
+ export const getObservationsAdvancedAttributes = (observations, advancedAttributesIds) => R.pipe(
4
+ R.map(obs => ({ attributes: R.pick(advancedAttributesIds, obs.attributes || {}), coordinates: obs.indexedDimValIds || {} })),
5
+ R.filter(entry => !R.isEmpty(entry.attributes))
6
+ )(observations);
7
+
8
+ export const getDataflowAdvancedAttributes = (attributes, dimensions, advancedAttributesIds, dimLength) => {
9
+ const advancedAttributes = R.pick(advancedAttributesIds, attributes);
10
+ const keyTemplate = R.times(R.always(''), dimLength);
11
+ return R.reduce(
12
+ (acc, attribute) => {
13
+ const value = R.head(attribute.values || []);
14
+ const attr = { ...R.pick(['id', 'name'], attribute), value };
15
+ let coordinates = {};
16
+ let key = keyTemplate;
17
+
18
+ if (!R.isEmpty(R.pathOr([], ['relationship', 'dimensions'], attribute))) {
19
+ const attrDimensionsIds = R.pathOr([], ['relationship', 'dimensions'], attribute);
20
+ const attrDimensions = R.props(attrDimensionsIds, dimensions);
21
+ R.forEach(
22
+ dim => {
23
+ const dId = dim.id;
24
+ const dIndex = dim.__index;
25
+ const vId = R.path(['values', 0, 'id'], dim);
26
+ coordinates = { ...coordinates, [dId]: vId };
27
+ key = R.set(R.lensIndex(dIndex), 0)(key);
28
+ },
29
+ attrDimensions
30
+ );
31
+ }
32
+
33
+ key = R.join(':', key);
34
+ return R.over(
35
+ R.lensProp(key),
36
+ entry => R.isNil(entry)
37
+ ? ({ attributes: { [attribute.id]: attr }, coordinates })
38
+ : R.over(R.lensProp('attributes'), R.assoc(attribute.id, attr))(entry)
39
+ )(acc);
40
+ },
41
+ {},
42
+ R.values(advancedAttributes)
43
+ )
44
+ };
45
+
46
+ /*
47
+ {
48
+ series: {
49
+ '0:0:x:x:x': { attributes: { a2: { id, value } } }
50
+ },
51
+ dimensions: {
52
+ '3:0': { attributes: { a1: { id, value } } },
53
+ }
54
+ }
55
+
56
+ */
57
+
58
+ export const getSeriesAdvancedAttributes = (seriesAttributes, dimensions, advancedAttributesIds) => {
59
+ const seriesAdvancedAttributes = R.pipe(
60
+ R.propOr({}, 'series'),
61
+ series => R.reduce(
62
+ (acc, key) => {
63
+ const serie = series[key];
64
+ const advancedAttributes = R.pick(advancedAttributesIds, serie.attributes);
65
+ if (R.isEmpty(advancedAttributes)) {
66
+ return acc;
67
+ }
68
+ const splitKey = R.split(':', key);
69
+ const { coordinates, refinedKey } = R.addIndex(R.reduce)(
70
+ (acc, vInd, dInd) => {
71
+ if (vInd === 'x') {
72
+ return ({ ...acc, refinedKey: R.append('', acc.refinedKey) });
73
+ }
74
+ const _refined = R.append(vInd, acc.refinedKey);
75
+ const dim = R.nth(dInd, dimensions);
76
+ const valId = R.path(['values', Number(vInd), 'id'], dim);
77
+ const _coordinates = R.assoc(dim.id, valId, acc.coordinates);
78
+ return ({ coordinates: _coordinates, refinedKey: _refined });
79
+ },
80
+ { coordinates: {}, refinedKey: [] },
81
+ splitKey
82
+ );
83
+ return R.assoc(R.join(':', refinedKey), { attributes: advancedAttributes, coordinates }, acc);
84
+ },
85
+ {},
86
+ R.keys(series)
87
+ )
88
+ )(seriesAttributes);
89
+ const keyTemplate = R.map(R.always(''), dimensions);
90
+ const dimensionsAdvancedAttributes = R.pipe(
91
+ R.propOr({}, 'dimensions'),
92
+ series => R.reduce(
93
+ (acc, key) => {
94
+ const serie = series[key];
95
+ const advancedAttributes = R.pick(advancedAttributesIds, serie.attributes);
96
+ if (R.isEmpty(advancedAttributes)) {
97
+ return acc;
98
+ }
99
+ const [dInd, vInd] = R.split(':', key);
100
+ const dim = R.nth(Number(dInd), dimensions);
101
+ const valId = R.path(['values', Number(vInd), 'id'], dim);
102
+ const coordinates = { [dim.id]: valId };
103
+ let refinedKey = keyTemplate;
104
+ refinedKey[Number(dInd)] = vInd;
105
+ return R.assoc(R.join(':', refinedKey), { attributes: advancedAttributes, coordinates }, acc);
106
+ },
107
+ {},
108
+ R.keys(series)
109
+ )
110
+ )(seriesAttributes);
111
+
112
+ return R.merge(seriesAdvancedAttributes, dimensionsAdvancedAttributes);
113
+ };
@@ -0,0 +1,37 @@
1
+ import * as R from 'ramda';
2
+
3
+ export const getMetadataCoordinates = (sdmxJson) => {
4
+ const dimensions = R.pathOr([], ['data', 'structure', 'dimensions', 'observation'], sdmxJson);
5
+ const annotations = R.pathOr([], ['data', 'structure', 'annotations'], sdmxJson);
6
+ const metadataAvailKeys = R.pipe(
7
+ R.pathOr([], ['data', 'dataSets', 0, 'dimensionGroupAttributes']),
8
+ R.map(indexes => R.props(indexes, annotations)),
9
+ R.filter(R.find(R.propEq('type', 'HAS_METADATA'))),
10
+ R.keys
11
+ )(sdmxJson);
12
+
13
+ return R.map(
14
+ key => {
15
+ const indexes = R.split(':', key);
16
+ return R.addIndex(R.reduce)(
17
+ (acc, vIndex, dimIndex) => {
18
+ if (R.isNil(vIndex) || R.isEmpty(vIndex)) {
19
+ return acc;
20
+ }
21
+ const dim = R.nth(dimIndex, dimensions);
22
+ if (R.isNil(dim)) {
23
+ return acc;
24
+ }
25
+ const val = R.path(['values', Number(vIndex)], dim);
26
+ if (R.isNil(val)) {
27
+ return acc;
28
+ }
29
+ return R.assoc(dim.id, val.id, acc);
30
+ },
31
+ {},
32
+ indexes
33
+ );
34
+ },
35
+ metadataAvailKeys
36
+ );
37
+ };
@@ -0,0 +1,17 @@
1
+ import * as R from 'ramda';
2
+
3
+ export const getDataflowMetadataStructure = sdmxJson => {
4
+ const annotations = R.pathOr([], ['data', 'stucture', 'annotations'], sdmxJson);
5
+ const dataSetAnnotIndexes = R.pathOr([], ['data', 'dataSets', 0, 'annotations'], sdmxJson);
6
+ const dataSetAnnotations = R.props(dataSetAnnotIndexes, annotations);
7
+ const metadataAnnotation = R.find(R.propEq('type', 'METADATA'), dataSetAnnotations);
8
+ if (!metadataAnnotation) {
9
+ return null;
10
+ }
11
+ return R.pipe(
12
+ R.propOr('', 'title'),
13
+ R.split('='),
14
+ R.last,
15
+
16
+ )(metadataAnnotation);
17
+ };
@@ -0,0 +1,73 @@
1
+ import * as R from 'ramda';
2
+
3
+ const dimensionValueDisplay = (display) => data => {
4
+ if (display === 'code') {
5
+ return R.prop('id', data);
6
+ }
7
+ if (display === 'both') {
8
+ return `${R.prop('id', data)}: ${R.prop('name', data)}`;
9
+ }
10
+ return R.prop('name', data);
11
+ };
12
+
13
+ const sortByCoordinates = (a, b) => {
14
+ const splitACoord = a.splitCoord;
15
+ const splitBCoord = b.splitCoord;
16
+
17
+ const aWeight = R.pipe(R.reject(R.isEmpty), R.length)(splitACoord);
18
+ const bWeight = R.pipe(R.reject(R.isEmpty), R.length)(splitBCoord);
19
+ if (aWeight !== bWeight) {
20
+ return bWeight - aWeight;
21
+ }
22
+
23
+ let ind = 0;
24
+ while (splitACoord[ind] === splitBCoord[ind]) {
25
+ ind++;
26
+ }
27
+ const _a = R.isEmpty(splitACoord[ind]) ? 0 : Number(splitACoord[ind]);
28
+ const _b = R.isEmpty(splitBCoord[ind]) ? 0 : Number(splitBCoord[ind]);
29
+ return _b - _a;
30
+ };
31
+
32
+ // options = { display, attributesLabel }
33
+ export const getSidebarData = (attributesSeries, metadataSeries, dataflow, dimensions, options) => {
34
+ const coordinates = R.uniq(R.concat(R.keys(attributesSeries), R.keys(metadataSeries)));
35
+ return R.pipe(
36
+ R.map(coordinate => {
37
+ const attributes = R.prop(coordinate, attributesSeries);
38
+ const metadata = R.prop(coordinate, metadataSeries);
39
+ const children = R.concat(
40
+ R.isNil(attributes) ? [] : [{ id: `${coordinate}-attr`, label: options.attributesLabel, children: attributes }],
41
+ R.isNil(metadata) ? [] : metadata,
42
+ );
43
+ const splitCoord = R.split(':', coordinate);
44
+ let label = null;
45
+ if (R.all(R.isEmpty, splitCoord)) {
46
+ label = dimensionValueDisplay(options.display)(dataflow);
47
+ }
48
+ else {
49
+ label = R.pipe(
50
+ R.addIndex(R.reduce)((acc, valIndex, dimIndex) => {
51
+ if (R.isEmpty(valIndex)) {
52
+ return acc;
53
+ }
54
+ const dim = R.nth(dimIndex, dimensions);
55
+ const dimLabel = dimensionValueDisplay(options.display)(dim);
56
+ const value = R.nth(Number(valIndex), dim.values);
57
+ const valLabel = dimensionValueDisplay(options.display)(value);
58
+ return R.append(`${dimLabel}: ${valLabel}`, acc);
59
+ }, []),
60
+ R.join(' - ')
61
+ )(splitCoord);
62
+ }
63
+
64
+ return ({
65
+ id: coordinate,
66
+ splitCoord,
67
+ label,
68
+ children: R.filter(R.identity, children),
69
+ });
70
+ }),
71
+ R.sort(sortByCoordinates)
72
+ )(coordinates);
73
+ };
@@ -0,0 +1,11 @@
1
+ import * as R from 'ramda';
2
+
3
+ export const hasCellMetadata = (metadataCoordinates, cellCoordinates) => {
4
+ return R.pipe(
5
+ R.find(coordinates => {
6
+ const mergedCoord = R.mergeLeft(coordinates, cellCoordinates);
7
+ return R.equals(mergedCoord, cellCoordinates);
8
+ }),
9
+ R.complement(R.isNil)
10
+ )(metadataCoordinates);
11
+ };
@@ -0,0 +1,9 @@
1
+ import * as R from 'ramda';
2
+
3
+ /*
4
+ const layoutData = [{ dimension: { id: 'D1', __index: 2 }, value: { id: 'V', __index: 0 } }];
5
+ */
6
+
7
+ export const getLayoutEntryMetadataCoordinates = (layoutData, metadataSeries) => {
8
+
9
+ };
@@ -0,0 +1,8 @@
1
+ export {
2
+ SDMX_3_0_JSON_DATA_FORMAT,
3
+ SDMX_3_0_CSV_DATA_FORMAT
4
+ } from './constants';
5
+
6
+ export { getSidebarData } from './getSidebarData';
7
+ export { parseMetadataSeries } from './parseMetadataSeries';
8
+ export { sdmx_3_0_DataFormatPatch } from './sdmx3.0DataFormatPatch';
@@ -0,0 +1,80 @@
1
+ import * as R from 'ramda';
2
+ import { getLocalisedName } from '@sis-cc/dotstatsuite-sdmxjs';
3
+
4
+ const dimensionValueDisplay = (locale, display) => data => {
5
+ if (display === 'code') {
6
+ return R.prop('id', data);
7
+ }
8
+ if (display === 'both') {
9
+ return `${R.prop('id', data)}: ${getLocalisedName(locale)(data)}`;
10
+ }
11
+ return getLocalisedName(locale)(data);
12
+ };
13
+ // options = { locale, display, dimensions = [] };
14
+ export const parseMetadataSeries = (metadataJson, options) => {
15
+ const metadataAttributes = R.pathOr([], ['data', 'structures', 0, 'attributes', 'dimensionGroup'], metadataJson);
16
+ const metaAttrLength = R.length(metadataAttributes);
17
+
18
+ if (!metaAttrLength) {
19
+ return ({});
20
+ }
21
+
22
+ const dimensions = R.pipe(
23
+ R.pathOr([], ['data', 'structures', 0, 'dimensions']),
24
+ ({ series = [], observation = [] }) => R.concat(series, observation),
25
+ dims => R.isEmpty(options.dimensions || [])
26
+ ? dims
27
+ : R.props(R.pluck('id', options.dimensions), R.indexBy(R.prop('id'), dims))
28
+ )(metadataJson);
29
+
30
+ const metadataSeries = R.pipe(
31
+ R.pathOr({}, ['data', 'dataSets', 0, 'dimensionGroupAttributes']),
32
+ series => R.reduce((acc, serieKey) => {
33
+ const indexes = series[serieKey];
34
+ const metaIndexes = R.take(metaAttrLength, indexes);
35
+
36
+ const evolvedKey = R.pipe(
37
+ R.split(':'),
38
+ R.addIndex(R.map)((vInd, dInd) => {
39
+ if (R.isEmpty(vInd)) {
40
+ return vInd;
41
+ }
42
+ const dim = R.nth(dInd, dimensions);
43
+ const val = R.nth(Number(vInd), dim.values || []);
44
+
45
+ const originalVal = R.find(
46
+ R.propEq('id', val.id),
47
+ )(R.propOr([], 'values', R.nth(dInd, options.dimensions)));
48
+ return R.propOr('', '__index', originalVal);
49
+ }),
50
+ R.join(':')
51
+ )(serieKey)
52
+
53
+ const attributes = R.addIndex(R.reduce)(
54
+ (acc, valueIndex, attrIndex) => {
55
+ if (R.isNil(valueIndex)) {
56
+ return acc;
57
+ }
58
+ const attribute = R.nth(attrIndex, metadataAttributes);
59
+ const label = dimensionValueDisplay(options.locale, options.display)(attribute);
60
+
61
+ const value = R.prop('value', R.nth(valueIndex, attribute.values || []));
62
+
63
+ return R.append({
64
+ id: attribute.id,
65
+ label,
66
+ value: R.is(Object, value) ? R.prop(options.locale, value) : value
67
+ }, acc);
68
+ },
69
+ [],
70
+ metaIndexes
71
+ );
72
+
73
+ return R.assoc(evolvedKey, attributes, acc);
74
+ },
75
+ {},
76
+ R.keys(series)
77
+ ))(metadataJson);
78
+
79
+ return metadataSeries;
80
+ };
@@ -0,0 +1,27 @@
1
+ import * as R from 'ramda';
2
+
3
+ export const refineMetadataCoordinates = (metadataCoordinates, layoutIds, headerDimensionsIds) => {
4
+ return R.reduce(
5
+ (acc, coordinates) => {
6
+ const refinedCoord = R.omit(headerDimensionsIds, coordinates);
7
+ if (R.isEmpty(refinedCoord)) {
8
+ return acc;
9
+ }
10
+ const removedHeaderCodes = R.omit(layoutIds.header, refinedCoord);
11
+ if (R.isEmpty(removedHeaderCodes)) {
12
+ return R.over(R.lensProp('layout'), R.append(refinedCoord))(acc);
13
+ }
14
+ const removedSectionCodes = R.omit(layoutIds.sections, refinedCoord);
15
+ if (R.isEmpty(removedSectionCodes)) {
16
+ return R.over(R.lensProp('layout'), R.append(refinedCoord))(acc);
17
+ }
18
+ const removedRowsCodes = R.omit(layoutIds.rows, removedSectionCodes);
19
+ if (R.isEmpty(removedRowsCodes)) {
20
+ return R.over(R.lensProp('layout'), R.append(refinedCoord))(acc);
21
+ }
22
+ return R.over(R.lensProp('cells'), R.append(refinedCoord))(acc);
23
+ },
24
+ { cells: [], layout: [] },
25
+ metadataCoordinates
26
+ );
27
+ };
@@ -0,0 +1,9 @@
1
+ import * as R from 'ramda';
2
+
3
+ export const sdmx_3_0_DataFormatPatch = (sdmxJson) => {
4
+ const dataSet = R.pipe(R.pathOr({}, ['data', 'dataSets']), R.head)(sdmxJson);
5
+ const structureIndex = R.prop('structure', dataSet);
6
+ const structure = R.pipe(R.pathOr([], ['data', 'structures']), R.nth(structureIndex))(sdmxJson);
7
+
8
+ return R.set(R.lensPath(['data', 'structure']), structure)(sdmxJson);
9
+ };