@truedat/dd 4.47.8 → 4.48.2

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## [4.48.2] 2022-07-08
4
+
5
+ ### Changed
6
+
7
+ - [TD-4995] Support localization of template fields and fixed values
8
+
9
+ ## [4.47.9] 2022-07-05
10
+
11
+ ### Added
12
+
13
+ - [TD-4661] Support for ReferenceDatasets on Implementations
14
+
3
15
  ## [4.47.8] 2022-07-02
4
16
 
5
17
  ## Changed
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@truedat/dd",
3
- "version": "4.47.8",
3
+ "version": "4.48.2",
4
4
  "description": "Truedat Web Data Dictionary",
5
5
  "sideEffects": false,
6
6
  "jsnext:main": "src/index.js",
@@ -34,7 +34,7 @@
34
34
  "@testing-library/jest-dom": "^5.16.4",
35
35
  "@testing-library/react": "^12.0.0",
36
36
  "@testing-library/user-event": "^13.2.1",
37
- "@truedat/test": "4.47.8",
37
+ "@truedat/test": "4.47.9",
38
38
  "babel-jest": "^28.1.0",
39
39
  "babel-plugin-dynamic-import-node": "^2.3.3",
40
40
  "babel-plugin-lodash": "^3.3.4",
@@ -88,9 +88,9 @@
88
88
  },
89
89
  "dependencies": {
90
90
  "@apollo/client": "^3.6.4",
91
- "@truedat/auth": "4.47.8",
92
- "@truedat/core": "4.47.8",
93
- "@truedat/df": "4.47.8",
91
+ "@truedat/auth": "4.48.2",
92
+ "@truedat/core": "4.48.2",
93
+ "@truedat/df": "4.48.2",
94
94
  "lodash": "^4.17.21",
95
95
  "path-to-regexp": "^1.7.0",
96
96
  "prop-types": "^15.8.1",
@@ -112,5 +112,5 @@
112
112
  "react-dom": ">= 16.8.6 < 17",
113
113
  "semantic-ui-react": ">= 0.88.2 < 2.1"
114
114
  },
115
- "gitHead": "dccc0d92c419a5ee257a8e15b64c1b98d909809a"
115
+ "gitHead": "93133e957332713e64c97eecdf45cc283c29bd32"
116
116
  }
@@ -31,6 +31,16 @@ export const REFERENCE_DATASETS_QUERY = gql`
31
31
  }
32
32
  `;
33
33
 
34
+ export const REFERENCE_DATASETS_HEADERS_QUERY = gql`
35
+ query ReferenceDatasetsHeaders {
36
+ referenceDatasets {
37
+ id
38
+ name
39
+ headers
40
+ }
41
+ }
42
+ `;
43
+
34
44
  export const REFERENCE_DATASET_QUERY = gql`
35
45
  query ReferenceDataset($id: ID!) {
36
46
  referenceDataset(id: $id) {
@@ -61,7 +61,10 @@ export const MyGrantRequests = ({
61
61
  key={idx}
62
62
  label={
63
63
  <label>
64
- {formatMessage({ id: `grantRequest.content.${type}` })}
64
+ {formatMessage({
65
+ id: `grantRequest.content.${type}`,
66
+ defaultMessage: type,
67
+ })}
65
68
  </label>
66
69
  }
67
70
  onChange={() => {
@@ -77,7 +77,7 @@ export const PendingStructureNotes = ({ systems }) => {
77
77
  render={({ field: { onBlur, onChange, value } }) => (
78
78
  <Form.Field className="subscriptions-checkbox-filters">
79
79
  <label>
80
- {formatMessage({ id: "pendingStructureNotes.props.status" })}
80
+ <FormattedMessage id="pendingStructureNotes.props.status" />
81
81
  </label>
82
82
  {STATUS.map((type, idx) => (
83
83
  <Checkbox
@@ -85,7 +85,10 @@ export const PendingStructureNotes = ({ systems }) => {
85
85
  key={idx}
86
86
  label={
87
87
  <label>
88
- {formatMessage({ id: `structure.notes.status.${type}` })}
88
+ <FormattedMessage
89
+ id={`structure.notes.status.${type}`}
90
+ defaultMessage={type}
91
+ />
89
92
  </label>
90
93
  }
91
94
  onChange={() => {
@@ -0,0 +1,107 @@
1
+ import _ from "lodash/fp";
2
+ import React, { useState } from "react";
3
+ import PropTypes from "prop-types";
4
+
5
+ import { matchSorter } from "match-sorter";
6
+ import { useIntl } from "react-intl";
7
+ import { Container, Form, Dropdown, Icon } from "semantic-ui-react";
8
+
9
+ import StructureSelectorInputFieldJoin from "./StructureSelectorInputFieldJoin";
10
+
11
+ export const ReferenceDatasetSelectorInputField = ({
12
+ onChange,
13
+ onChangeField,
14
+ onDelete,
15
+ structures,
16
+ selectedStructure,
17
+ fieldWidth,
18
+ referenceDatasets,
19
+ }) => {
20
+ const [searchTerm, setSearchTerm] = useState("");
21
+ const { formatMessage } = useIntl();
22
+
23
+ const matchSorterFp = (items) =>
24
+ matchSorter(items, searchTerm, {
25
+ keys: ["name", "headers"],
26
+ threshold: matchSorter.rankings.CONTAINS,
27
+ });
28
+
29
+ const datasets = _.flow(
30
+ _.reject(
31
+ ({ id }) =>
32
+ _.any({
33
+ structure: {
34
+ type: "reference_dataset",
35
+ id,
36
+ },
37
+ })(structures) && id !== selectedStructure?.structure?.id
38
+ ),
39
+ _.cond([
40
+ [() => _.isEmpty(searchTerm), _.identity],
41
+ [_.stubTrue, matchSorterFp],
42
+ ])
43
+ )(referenceDatasets);
44
+
45
+ const options = _.map(({ id, name }) => ({ key: id, value: id, text: name }))(
46
+ datasets
47
+ );
48
+
49
+ const handleChange = (_e, { value }) =>
50
+ onChange(_.find({ id: value })(datasets));
51
+ const handleSearchChange = (_e, { searchQuery }) =>
52
+ setSearchTerm(searchQuery);
53
+ const handleSelectField = (clauses) => {
54
+ onChangeField({ ...selectedStructure, clauses });
55
+ };
56
+
57
+ return (
58
+ <>
59
+ <Form.Field width={fieldWidth ? fieldWidth : 7}>
60
+ <label>
61
+ {formatMessage({ id: `ruleImplementation.props.reference_dataset` })}
62
+ <Icon name="close" className="selectable" onClick={onDelete} />
63
+ </label>
64
+ <Dropdown
65
+ onChange={handleChange}
66
+ onSearchChange={handleSearchChange}
67
+ options={options}
68
+ placeholder={formatMessage({
69
+ id: `ruleImplementation.props.reference_dataset.placeholder`,
70
+ })}
71
+ search
72
+ searchQuery={searchTerm}
73
+ selection
74
+ value={selectedStructure?.structure?.id}
75
+ />
76
+ </Form.Field>
77
+ {_.prop("structure")(selectedStructure) && (
78
+ <Container style={{ paddingLeft: "8em" }}>
79
+ <Form.Field>
80
+ <label>
81
+ {formatMessage({
82
+ id: "structureSelector.union.criteria",
83
+ })}
84
+ </label>
85
+ <StructureSelectorInputFieldJoin
86
+ structures={structures}
87
+ selectedStructure={selectedStructure}
88
+ handleSelectField={handleSelectField}
89
+ />
90
+ </Form.Field>
91
+ </Container>
92
+ )}
93
+ </>
94
+ );
95
+ };
96
+
97
+ ReferenceDatasetSelectorInputField.propTypes = {
98
+ onChange: PropTypes.func,
99
+ onChangeField: PropTypes.func,
100
+ onDelete: PropTypes.func,
101
+ structures: PropTypes.array,
102
+ selectedStructure: PropTypes.object,
103
+ fieldWidth: PropTypes.number,
104
+ referenceDatasets: PropTypes.array,
105
+ };
106
+
107
+ export default ReferenceDatasetSelectorInputField;
@@ -19,34 +19,43 @@ export const StructureFieldsDropdown = ({
19
19
  multiple,
20
20
  }) => {
21
21
  const { formatMessage } = useIntl();
22
+
22
23
  const onClick = ({ value, modifier }) => {
23
- onSelectField(dropdownItemToField(value), modifier);
24
+ if (!multiple) onSelectField(dropdownItemToField(value), modifier);
24
25
  };
25
26
 
26
27
  const onChangeStructureFieldsDropdown = (valueOrValues) => {
27
28
  return _.flow(
28
- _.map((value) => {
29
- return dropdownItemToField(value);
30
- }),
29
+ _.map(dropdownItemToField),
31
30
  multiple ? onSelectFields : onSelectField
32
31
  )(Array.isArray(valueOrValues) ? valueOrValues : [valueOrValues]);
33
32
  };
34
33
 
35
34
  const dropdownItemToField = (value) => {
36
- const [data_structure_id, parent_index] = _.isString(value)
37
- ? value.split("/").map(Number)
35
+ const [fieldIdentifier, parentIndex] = _.isString(value)
36
+ ? value.split("/")
38
37
  : [value, undefined];
39
- return _.isNil(parent_index)
40
- ? _.find({ data_structure_id: data_structure_id })(structureFields)
38
+ return _.isNil(parentIndex)
39
+ ? _.find({ data_structure_id: Number(fieldIdentifier) })(structureFields)
40
+ : _.any({
41
+ type: "reference_dataset_field",
42
+ parent_index: Number(parentIndex),
43
+ })(structureFields)
44
+ ? _.find({
45
+ name: fieldIdentifier,
46
+ parent_index: Number(parentIndex),
47
+ })(structureFields)
41
48
  : _.find({
42
- data_structure_id: data_structure_id,
43
- parent_index: parent_index,
49
+ data_structure_id: Number(fieldIdentifier),
50
+ parent_index: Number(parentIndex),
44
51
  })(structureFields);
45
52
  };
46
53
 
47
54
  const formatOption = (field) => {
48
55
  const value = _.isNil(field?.parent_index)
49
56
  ? field.data_structure_id
57
+ : field?.type === "reference_dataset_field"
58
+ ? `${field.name}/${field.parent_index}`
50
59
  : `${field.data_structure_id}/${field.parent_index}`;
51
60
  const modifier = _.find({ sourceType: field.field_type })(
52
61
  typeCastModifiers
@@ -79,7 +88,7 @@ export const StructureFieldsDropdown = ({
79
88
  const toFieldOption = (field) =>
80
89
  _.has("options")(field)
81
90
  ? {
82
- icon: "table",
91
+ icon: field?.isReferenceDataset ? "list ol" : "table",
83
92
  label: field.label,
84
93
  options: _.map(formatOption)(field.options),
85
94
  }
@@ -92,7 +101,16 @@ export const StructureFieldsDropdown = ({
92
101
  (acc, v, k) =>
93
102
  _.isNil(k) || k === "undefined"
94
103
  ? [...acc, ...v]
95
- : [...acc, { label: k, options: v }],
104
+ : [
105
+ ...acc,
106
+ {
107
+ label: k,
108
+ options: v,
109
+ isReferenceDataset: _.any({ type: "reference_dataset_field" })(
110
+ v
111
+ ),
112
+ },
113
+ ],
96
114
  []
97
115
  ),
98
116
  _.map(toFieldOption)
@@ -44,7 +44,7 @@ export const StructureSelectorInputField = ({
44
44
  <>
45
45
  <Form.Field>
46
46
  <label>
47
- {formatMessage({ id: `ruleImplementation.props.structure` })}
47
+ {formatMessage({ id: "ruleImplementation.props.structure" })}
48
48
  {joined && (
49
49
  <Icon name="close" className="selectable" onClick={onDelete} />
50
50
  )}
@@ -59,7 +59,7 @@ export const StructureSelectorInputField = ({
59
59
  icon
60
60
  value={_.path("structure.name")(selectedStructure) || ""}
61
61
  placeholder={formatMessage({
62
- id: `ruleImplementation.props.structure.placeholder`,
62
+ id: "ruleImplementation.props.structure.placeholder",
63
63
  })}
64
64
  required
65
65
  fluid
@@ -68,7 +68,6 @@ export const StructureSelectorInputField = ({
68
68
  width={fieldWidth ? fieldWidth : 7}
69
69
  >
70
70
  <input className="action-pointer" />
71
- <Icon name={active ? "minus circle" : "plus circle"} />
72
71
  </Form.Input>
73
72
  )}
74
73
  {active && (
@@ -85,7 +84,7 @@ export const StructureSelectorInputField = ({
85
84
  <Form.Field>
86
85
  <label>
87
86
  {formatMessage({
88
- id: `ruleImplementation.props.structure.alias`,
87
+ id: "ruleImplementation.props.structure.alias",
89
88
  })}
90
89
  </label>
91
90
  <Form.Input
@@ -108,9 +107,7 @@ export const StructureSelectorInputField = ({
108
107
  <Container style={{ paddingLeft: "8em" }}>
109
108
  <Form.Field>
110
109
  <label>
111
- {formatMessage({
112
- id: "structureSelector.union.criteria",
113
- })}
110
+ {formatMessage({ id: "structureSelector.union.criteria" })}
114
111
  </label>
115
112
  <StructureSelectorInputFieldJoin
116
113
  structures={structures}
@@ -3,6 +3,7 @@ import React from "react";
3
3
  import PropTypes from "prop-types";
4
4
  import { useIntl } from "react-intl";
5
5
  import { Grid, Icon, Popup } from "semantic-ui-react";
6
+ import { getStructureFieldOptionValue } from "../selectors/getStructureFieldOptionValue";
6
7
  import StructureFieldsDropdown from "./StructureFieldsDropdown";
7
8
 
8
9
  const getClauses = (selectedStructure) => {
@@ -41,31 +42,29 @@ const JoinClause = ({
41
42
  }) => {
42
43
  const addActionDisabled = _.isEmpty(left) || _.isEmpty(right);
43
44
  const { formatMessage } = useIntl();
45
+
44
46
  return (
45
- <Grid>
47
+ <Grid style={{ display: "flex", alignItems: "center" }}>
46
48
  <Grid.Column width={4}>
47
49
  <StructureFieldsDropdown
48
50
  fluid
49
51
  parentStructures={structureToFieldDropdown([selectedStructure])}
50
52
  onSelectField={handleChange("left", idx)}
51
- value={
52
- _.isNil(_.prop("parent_index")(left))
53
- ? _.prop("id")(left)
54
- : `${_.prop("id")(left)}/${_.prop("parent_index")(left)}`
55
- }
53
+ value={getStructureFieldOptionValue(left)}
56
54
  />
57
55
  </Grid.Column>
58
- <Grid.Column width={1}>{"="}</Grid.Column>
56
+ <Grid.Column
57
+ width={1}
58
+ style={{ textAlign: "center", fontSize: "x-large" }}
59
+ >
60
+ {"="}
61
+ </Grid.Column>
59
62
  <Grid.Column width={4}>
60
63
  <StructureFieldsDropdown
61
64
  fluid
62
65
  parentStructures={structureToFieldDropdown(parentStructures)}
63
66
  onSelectField={handleChange("right", idx)}
64
- value={
65
- _.isNil(_.prop("parent_index")(right))
66
- ? _.prop("id")(right)
67
- : `${_.prop("id")(right)}/${_.prop("parent_index")(right)}`
68
- }
67
+ value={getStructureFieldOptionValue(right)}
69
68
  />
70
69
  </Grid.Column>
71
70
  <Grid.Column width={1}>
@@ -128,15 +127,16 @@ export const StructureSelectorInputFieldJoin = ({
128
127
  data_structure_id: id,
129
128
  parent_index: parent_index,
130
129
  name: name,
130
+ type: type,
131
131
  } = data;
132
132
  const newClause = _.isNil(parent_index)
133
133
  ? { ...clauses[idx], [prop]: { id, name } }
134
- : { ...clauses[idx], [prop]: { id, parent_index, name } };
134
+ : { ...clauses[idx], [prop]: { id, parent_index, name, type } };
135
135
  const newClauses = _.set(`[${idx}]`, newClause)(clauses);
136
136
  handleSelectField(newClauses);
137
137
  };
138
138
  return (
139
- <>
139
+ <div style={{ marginBottom: "1em" }}>
140
140
  {clauses.map(({ left, right }, idx) => (
141
141
  <JoinClause
142
142
  key={idx}
@@ -150,7 +150,7 @@ export const StructureSelectorInputFieldJoin = ({
150
150
  selectedStructure={selectedStructure}
151
151
  />
152
152
  ))}
153
- </>
153
+ </div>
154
154
  );
155
155
  };
156
156
 
@@ -23,9 +23,7 @@ const Date = ({ className, icon, label, date }) => {
23
23
  className={className}
24
24
  >
25
25
  {icon}
26
- {formatMessage({
27
- id: `structure.${label}`,
28
- })}
26
+ {formatMessage({ id: `structure.${label}` })}
29
27
  : <Moment locale="es" date={date} format="YYYY-MM-DD HH:mm" />
30
28
  </Label>
31
29
  );
@@ -4,7 +4,6 @@ import PropTypes from "prop-types";
4
4
  import { connect } from "react-redux";
5
5
  import { useIntl } from "react-intl";
6
6
  import { getFieldType } from "@truedat/core/services/fieldType";
7
- import { fetchStructure } from "../routines";
8
7
  import StructureFieldsDropdown from "./StructureFieldsDropdown";
9
8
 
10
9
  export const ValueConditionStructure = ({
@@ -52,15 +51,10 @@ const mapStateToProps = (state) => ({
52
51
  structuresSiblings: state.structuresSiblings,
53
52
  });
54
53
 
55
- const mapDispatchToProps = { fetchStructure };
56
-
57
54
  ValueConditionStructure.propTypes = {
58
55
  onChange: PropTypes.func,
59
56
  siblings: PropTypes.array,
60
57
  structuresSiblings: PropTypes.object,
61
58
  value: PropTypes.number,
62
59
  };
63
- export default connect(
64
- mapStateToProps,
65
- mapDispatchToProps
66
- )(ValueConditionStructure);
60
+ export default connect(mapStateToProps)(ValueConditionStructure);
@@ -1,7 +1,14 @@
1
1
  // Jest Snapshot v1, https://goo.gl/fbAQLP
2
2
 
3
3
  exports[`<StructureSelectorInputFieldJoin /> matches the latest JoinClause snapshot 1`] = `
4
- <Grid>
4
+ <Grid
5
+ style={
6
+ Object {
7
+ "alignItems": "center",
8
+ "display": "flex",
9
+ }
10
+ }
11
+ >
5
12
  <GridColumn
6
13
  width={4}
7
14
  >
@@ -19,6 +26,12 @@ exports[`<StructureSelectorInputFieldJoin /> matches the latest JoinClause snaps
19
26
  />
20
27
  </GridColumn>
21
28
  <GridColumn
29
+ style={
30
+ Object {
31
+ "fontSize": "x-large",
32
+ "textAlign": "center",
33
+ }
34
+ }
22
35
  width={1}
23
36
  >
24
37
  =
@@ -74,7 +87,13 @@ exports[`<StructureSelectorInputFieldJoin /> matches the latest JoinClause snaps
74
87
  `;
75
88
 
76
89
  exports[`<StructureSelectorInputFieldJoin /> matches the latest snapshot 1`] = `
77
- <Fragment>
90
+ <div
91
+ style={
92
+ Object {
93
+ "marginBottom": "1em",
94
+ }
95
+ }
96
+ >
78
97
  <JoinClause
79
98
  createClause={[Function]}
80
99
  deleteClause={[Function]}
@@ -88,11 +107,17 @@ exports[`<StructureSelectorInputFieldJoin /> matches the latest snapshot 1`] = `
88
107
  }
89
108
  }
90
109
  />
91
- </Fragment>
110
+ </div>
92
111
  `;
93
112
 
94
113
  exports[`<StructureSelectorInputFieldJoin /> matches the latest snapshot with various clauses 1`] = `
95
- <Fragment>
114
+ <div
115
+ style={
116
+ Object {
117
+ "marginBottom": "1em",
118
+ }
119
+ }
120
+ >
96
121
  <JoinClause
97
122
  createClause={[Function]}
98
123
  deleteClause={[Function]}
@@ -175,5 +200,5 @@ exports[`<StructureSelectorInputFieldJoin /> matches the latest snapshot with va
175
200
  }
176
201
  }
177
202
  />
178
- </Fragment>
203
+ </div>
179
204
  `;
package/src/index.js CHANGED
@@ -2,6 +2,7 @@ import * as components from "./components";
2
2
  import * as reducers from "./reducers";
3
3
  import * as routines from "./routines";
4
4
  import * as sagas from "./sagas";
5
+ import * as selectors from "./selectors";
5
6
  import * as messages from "./messages";
6
7
 
7
- export { components, reducers, routines, sagas, messages };
8
+ export { components, reducers, routines, sagas, selectors, messages };
@@ -14,7 +14,6 @@ export function* requestGrantRemovalSaga({ payload }) {
14
14
  yield put(requestGrantRemoval.success(data));
15
15
  yield put(fetchStructure.trigger({ id: data_structure_id, version }));
16
16
  } catch (error) {
17
- console.error("error", error);
18
17
  if (error.response) {
19
18
  const { status, data } = error.response;
20
19
  yield put(requestGrantRemoval.failure({ status, data }));
@@ -0,0 +1,8 @@
1
+ import _ from "lodash/fp";
2
+
3
+ export const getStructureFieldOptionValue = (structure) =>
4
+ _.isNil(_.prop("parent_index")(structure))
5
+ ? _.prop("id")(structure)
6
+ : structure?.type === "reference_dataset_field"
7
+ ? `${_.prop("name")(structure)}/${_.prop("parent_index")(structure)}`
8
+ : `${_.prop("id")(structure)}/${_.prop("parent_index")(structure)}`;
@@ -8,20 +8,34 @@ const withFieldType = (field) => ({
8
8
  });
9
9
 
10
10
  const getFields = (parent, structuresFields) =>
11
- _.flow(
12
- _.propOr([], _.path("id")(parent)),
13
- _.map((sf) => ({
14
- ...sf,
15
- label: _.prop("alias.text")(parent) || _.prop("name")(parent),
16
- parent_index: _.prop("alias.index")(parent),
17
- }))
18
- )(structuresFields);
19
-
11
+ parent?.type !== "reference_dataset"
12
+ ? _.flow(
13
+ _.propOr([], _.path("id")(parent)),
14
+ _.map((sf) => ({
15
+ ...sf,
16
+ label: _.prop("alias.text")(parent) || _.prop("name")(parent),
17
+ parent_index: _.prop("alias.index")(parent),
18
+ }))
19
+ )(structuresFields)
20
+ : _.flow(
21
+ _.get("headers"),
22
+ _.map((name) => ({
23
+ name,
24
+ type: "reference_dataset_field",
25
+ label: _.prop("name")(parent),
26
+ parent_index: _.prop("alias.index")(parent),
27
+ data_type_class: "string",
28
+ }))
29
+ )(parent);
20
30
  const getFieldsFromStructures = (structuresFields, parentStructures) =>
21
31
  _.flow(
22
32
  _.map((parent) => getFields(parent, structuresFields)),
23
33
  _.flatten,
24
- _.uniqBy((s) => `${s.data_structure_id}/${s.parent_index}`),
34
+ _.uniqBy((s) =>
35
+ s?.type === "reference_dataset_field"
36
+ ? `${s.name}/${s.parent_index}`
37
+ : `${s.data_structure_id}/${s.parent_index}`
38
+ ),
25
39
  _.map(withFieldType)
26
40
  )(parentStructures);
27
41