@truedat/df 4.48.3 → 4.48.4

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,11 @@
1
1
  # Changelog
2
2
 
3
+ ## [4.48.4] 2022-07-11
4
+
5
+ ### Changed
6
+
7
+ - [TD-4995] Support localization of template fields and fixed values
8
+
3
9
  ## [4.48.2] 2022-07-08
4
10
 
5
11
  ### Changed
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@truedat/df",
3
- "version": "4.48.3",
3
+ "version": "4.48.4",
4
4
  "description": "Truedat Web Data Quality Module",
5
5
  "sideEffects": false,
6
6
  "jsnext:main": "src/index.js",
@@ -87,8 +87,8 @@
87
87
  ]
88
88
  },
89
89
  "dependencies": {
90
- "@truedat/auth": "4.48.3",
91
- "@truedat/core": "4.48.3",
90
+ "@truedat/auth": "4.48.4",
91
+ "@truedat/core": "4.48.4",
92
92
  "axios": "^0.19.2",
93
93
  "path-to-regexp": "^1.7.0",
94
94
  "prop-types": "^15.8.1",
@@ -107,5 +107,5 @@
107
107
  "react-dom": ">= 16.8.6 < 17",
108
108
  "semantic-ui-react": ">= 0.88.2 < 2.1"
109
109
  },
110
- "gitHead": "5b30312f30c532988985ab9271d1e39ad0ad5c43"
110
+ "gitHead": "5e50a034469bf3ad8e02a64eb875ad2b710b6b03"
111
111
  }
@@ -40,7 +40,7 @@ export const DynamicForm = ({
40
40
  onChange(newContent, {});
41
41
  };
42
42
 
43
- const parsedGroups = parseGroups(
43
+ const parsedGroups = parseGroups(formatMessage)(
44
44
  template,
45
45
  content,
46
46
  fieldsToOmit,
@@ -20,7 +20,7 @@ export const DynamicFormViewer = ({
20
20
  />
21
21
  );
22
22
 
23
- const parsedGroups = parseGroups(template, content);
23
+ const parsedGroups = parseGroups(formatMessage)(template, content);
24
24
 
25
25
  return parsedGroups.map(({ name, fields }, i) => (
26
26
  <FieldGroupDetail
@@ -1,6 +1,5 @@
1
1
  import _ from "lodash/fp";
2
2
  import React from "react";
3
- import { FormattedMessage } from "react-intl";
4
3
  import PropTypes from "prop-types";
5
4
  import { Form } from "semantic-ui-react";
6
5
 
@@ -13,14 +12,7 @@ export const CheckboxField = ({
13
12
  <Form.Checkbox
14
13
  name={name}
15
14
  key={i}
16
- label={
17
- text ? (
18
- <FormattedMessage
19
- id={`fields.${name}.${text}`}
20
- defaultMessage={text}
21
- />
22
- ) : null
23
- }
15
+ label={text}
24
16
  value={value}
25
17
  checked={_.isArray(fieldValue) && _.includes(value)(fieldValue)}
26
18
  onChange={(e, { checked, value: thisValue, ...changes }) => {
@@ -1,6 +1,5 @@
1
1
  import _ from "lodash/fp";
2
2
  import React from "react";
3
- import { FormattedMessage } from "react-intl";
4
3
  import PropTypes from "prop-types";
5
4
  import { Form } from "semantic-ui-react";
6
5
 
@@ -12,14 +11,7 @@ export const RadioField = ({
12
11
  <Form.Radio
13
12
  name={name}
14
13
  key={i}
15
- label={
16
- text ? (
17
- <FormattedMessage
18
- id={`fields.${name}.${text}`}
19
- defaultMessage={text}
20
- />
21
- ) : null
22
- }
14
+ label={text}
23
15
  value={value}
24
16
  checked={fieldValue === value}
25
17
  onChange={onChange}
@@ -1,9 +1,9 @@
1
1
  import _ from "lodash/fp";
2
2
  import React from "react";
3
3
  import PropTypes from "prop-types";
4
+ import { useIntl } from "react-intl";
4
5
  import { connect } from "react-redux";
5
6
  import { Form } from "semantic-ui-react";
6
- import { useIntl } from "react-intl";
7
7
  import { makeGetDropdownOptions } from "../../selectors";
8
8
 
9
9
  const isMultiple = (cardinality) => _.includes(cardinality)(["+", "*"]);
@@ -22,8 +22,22 @@ const valueOrEmpty = (cardinality, type, value) =>
22
22
  : ""
23
23
  : valueFromType(type, value);
24
24
 
25
- const setOptions = (cardinality, values, text) =>
26
- isMultiple(cardinality) ? values : _.union(values, [{ text, value: null }]);
25
+ const translateValues = (formatMessage, label) => (values) =>
26
+ values?.map(({ text, ...rest }, key) => ({
27
+ key,
28
+ text: formatMessage({
29
+ id: `fields.${label}.${text}`,
30
+ defaultMessage: text,
31
+ }),
32
+ ...rest,
33
+ }));
34
+
35
+ const makeOptions = (formatMessage, label) => (cardinality, values) =>
36
+ isMultiple(cardinality)
37
+ ? translateValues(formatMessage, label)(values)
38
+ : _.union(translateValues(formatMessage, label)(values), [
39
+ { text: formatMessage({ id: "selector.no.selection" }), value: null },
40
+ ]);
27
41
 
28
42
  const singleValueType = (name, value, options) =>
29
43
  _.flow(
@@ -59,7 +73,7 @@ const cachedTypeValue = (data, options) => {
59
73
  };
60
74
 
61
75
  export const StandardDropdown = ({
62
- field: { name, cardinality, type, value },
76
+ field: { label, name, cardinality, type, value },
63
77
  onChange,
64
78
  options,
65
79
  }) => {
@@ -69,26 +83,22 @@ export const StandardDropdown = ({
69
83
  onChange(e, value);
70
84
  };
71
85
  return (
72
- <>
73
- <Form.Dropdown
74
- fluid
75
- search
76
- selection
77
- placeholder={formatMessage({ id: "fields.dropdown.placeholder" })}
78
- onChange={handleChange}
79
- name={name}
80
- value={valueOrEmpty(cardinality, type, value)}
81
- multiple={isMultiple(cardinality)}
82
- options={setOptions(
83
- cardinality,
84
- options,
85
- formatMessage({ id: "selector.no.selection" })
86
- ).map((o, key) => ({
86
+ <Form.Dropdown
87
+ fluid
88
+ search
89
+ selection
90
+ placeholder={formatMessage({ id: "fields.dropdown.placeholder" })}
91
+ onChange={handleChange}
92
+ name={name}
93
+ value={valueOrEmpty(cardinality, type, value)}
94
+ multiple={isMultiple(cardinality)}
95
+ options={makeOptions(formatMessage, label)(cardinality, options).map(
96
+ (o, key) => ({
87
97
  ...o,
88
98
  key,
89
- }))}
90
- />
91
- </>
99
+ })
100
+ )}
101
+ />
92
102
  );
93
103
  };
94
104
 
@@ -7,7 +7,7 @@ describe("<RadioField />", () => {
7
7
  const name = "name";
8
8
  const cardinality = "1";
9
9
  const value = "Foo";
10
- const parsedValues = ["Foo", "Bar"];
10
+ const parsedValues = ["Foo", "Bar"].map((v) => ({ value: v, text: v }));
11
11
  const onChange = jest.fn();
12
12
  const props = {
13
13
  field: { label, name, cardinality, value, parsedValues },
@@ -7,12 +7,7 @@ Array [
7
7
  checked={false}
8
8
  control={[Function]}
9
9
  key="0"
10
- label={
11
- <Memo(MemoizedFormattedMessage)
12
- defaultMessage="Foo"
13
- id="fields.name.Foo"
14
- />
15
- }
10
+ label="Foo"
16
11
  name="name"
17
12
  onChange={[Function]}
18
13
  value="foo"
@@ -22,12 +17,7 @@ Array [
22
17
  checked={false}
23
18
  control={[Function]}
24
19
  key="1"
25
- label={
26
- <Memo(MemoizedFormattedMessage)
27
- defaultMessage="Bar"
28
- id="fields.name.Bar"
29
- />
30
- }
20
+ label="Bar"
31
21
  name="name"
32
22
  onChange={[Function]}
33
23
  value="bar"
@@ -4,21 +4,23 @@ exports[`<RadioField /> matches the latest snapshot 1`] = `
4
4
  Array [
5
5
  <FormRadio
6
6
  as={[Function]}
7
- checked={false}
7
+ checked={true}
8
8
  control={[Function]}
9
9
  key="0"
10
- label={null}
10
+ label="Foo"
11
11
  name="name"
12
12
  onChange={[MockFunction]}
13
+ value="Foo"
13
14
  />,
14
15
  <FormRadio
15
16
  as={[Function]}
16
17
  checked={false}
17
18
  control={[Function]}
18
19
  key="1"
19
- label={null}
20
+ label="Bar"
20
21
  name="name"
21
22
  onChange={[MockFunction]}
23
+ value="Bar"
22
24
  />,
23
25
  ]
24
26
  `;
@@ -1,37 +1,35 @@
1
1
  // Jest Snapshot v1, https://goo.gl/fbAQLP
2
2
 
3
3
  exports[`<StandardDropdown /> matches the latest snapshot 1`] = `
4
- <Fragment>
5
- <FormDropdown
6
- as={[Function]}
7
- control={[Function]}
8
- fluid={true}
9
- multiple={false}
10
- name="name"
11
- onChange={[Function]}
12
- options={
13
- Array [
14
- Object {
15
- "key": 0,
16
- "text": "selector.no.selection",
17
- "value": null,
18
- },
19
- Object {
20
- "key": 1,
21
- "text": "Foo",
22
- "value": "Foo",
23
- },
24
- Object {
25
- "key": 2,
26
- "text": "Bar",
27
- "value": "Bar",
28
- },
29
- ]
30
- }
31
- placeholder="fields.dropdown.placeholder"
32
- search={true}
33
- selection={true}
34
- value="Foo"
35
- />
36
- </Fragment>
4
+ <FormDropdown
5
+ as={[Function]}
6
+ control={[Function]}
7
+ fluid={true}
8
+ multiple={false}
9
+ name="name"
10
+ onChange={[Function]}
11
+ options={
12
+ Array [
13
+ Object {
14
+ "key": 0,
15
+ "text": "selector.no.selection",
16
+ "value": null,
17
+ },
18
+ Object {
19
+ "key": 1,
20
+ "text": "Foo",
21
+ "value": "Foo",
22
+ },
23
+ Object {
24
+ "key": 2,
25
+ "text": "Bar",
26
+ "value": "Bar",
27
+ },
28
+ ]
29
+ }
30
+ placeholder="fields.dropdown.placeholder"
31
+ search={true}
32
+ selection={true}
33
+ value="Foo"
34
+ />
37
35
  `;
@@ -1,10 +1,13 @@
1
1
  import { parseFieldOptions } from "..";
2
2
 
3
+ const formatMessage = ({ defaultMessage }) => defaultMessage;
4
+ const parseFormatFieldOptions = parseFieldOptions(formatMessage);
5
+
3
6
  describe("utils: parseFieldOptions", () => {
4
7
  it("adds value to field", () => {
5
8
  const field = { name: "field" };
6
9
  const content = { field: "1" };
7
- const result = parseFieldOptions(content)(field);
10
+ const result = parseFormatFieldOptions(content)(field);
8
11
  expect(result).toEqual({ ...field, value: "1" });
9
12
  });
10
13
 
@@ -22,7 +25,7 @@ describe("utils: parseFieldOptions", () => {
22
25
  },
23
26
  };
24
27
  const content = { field: "1", switcher: "odd" };
25
- const result = parseFieldOptions(content)(field);
28
+ const result = parseFormatFieldOptions(content)(field);
26
29
  expect(result).toEqual({
27
30
  ...field,
28
31
  value: "1",
@@ -41,7 +44,7 @@ describe("utils: parseFieldOptions", () => {
41
44
  },
42
45
  };
43
46
  const content = { field: "b" };
44
- const result = parseFieldOptions(content)(field);
47
+ const result = parseFormatFieldOptions(content)(field);
45
48
  expect(result).toEqual({
46
49
  ...field,
47
50
  value: "b",
@@ -64,7 +67,7 @@ describe("utils: parseFieldOptions", () => {
64
67
  },
65
68
  };
66
69
  const content = { field: "a" };
67
- const result = parseFieldOptions(content)(field);
70
+ const result = parseFormatFieldOptions(content)(field);
68
71
  expect(result).toEqual({
69
72
  ...field,
70
73
  value: "a",
@@ -84,7 +87,7 @@ describe("utils: parseFieldOptions", () => {
84
87
  },
85
88
  };
86
89
  const content = { field: "y" };
87
- const result = parseFieldOptions(content)(field);
90
+ const result = parseFormatFieldOptions(content)(field);
88
91
  expect(result).toEqual({
89
92
  ...field,
90
93
  value: "y",
@@ -107,13 +110,13 @@ describe("utils: parseFieldOptions", () => {
107
110
  },
108
111
  };
109
112
  const content = { field: "bar" };
110
- const result = parseFieldOptions(content, selectedDomain)(field);
113
+ const result = parseFormatFieldOptions(content, selectedDomain)(field);
111
114
  expect(result).toEqual({
112
115
  ...field,
113
116
  value: "bar",
114
117
  parsedValues: [
115
- { text: "foo", value: "foo" },
116
118
  { text: "bar", value: "bar" },
119
+ { text: "foo", value: "foo" },
117
120
  ],
118
121
  });
119
122
  });
@@ -1,5 +1,8 @@
1
1
  import { parseGroups } from "..";
2
2
 
3
+ const formatMessage = ({ defaultMessage }) => defaultMessage;
4
+ const formatParseGroups = parseGroups(formatMessage);
5
+
3
6
  describe("utils: parseGroups", () => {
4
7
  it("adds required and value to field", () => {
5
8
  const template = {
@@ -14,7 +17,7 @@ describe("utils: parseGroups", () => {
14
17
  ],
15
18
  };
16
19
  const content = { field: "1", field_mandatory: "2" };
17
- const result = parseGroups(template, content);
20
+ const result = formatParseGroups(template, content);
18
21
  expect(result).toEqual([
19
22
  {
20
23
  fields: [
@@ -42,7 +45,7 @@ describe("utils: parseGroups", () => {
42
45
  };
43
46
  const content = { field: "1" };
44
47
  const fieldsToOmit = ["ommitedField"];
45
- const result = parseGroups(template, content, fieldsToOmit);
48
+ const result = formatParseGroups(template, content, fieldsToOmit);
46
49
  expect(result).toEqual([
47
50
  {
48
51
  fields: [{ name: "field", required: false, value: "1" }],
@@ -66,7 +69,7 @@ describe("utils: parseGroups", () => {
66
69
  };
67
70
  const content = { parent: "b", dependant: "value" };
68
71
  const fieldsToOmit = ["ommitedField"];
69
- const result = parseGroups(template, content, fieldsToOmit);
72
+ const result = formatParseGroups(template, content, fieldsToOmit);
70
73
  expect(result).toEqual([
71
74
  {
72
75
  fields: [
@@ -106,7 +109,7 @@ describe("utils: parseGroups", () => {
106
109
  };
107
110
  const content = { parent: ["b", "c"] };
108
111
  const fieldsToOmit = ["ommitedField"];
109
- const result = parseGroups(template, content, fieldsToOmit);
112
+ const result = formatParseGroups(template, content, fieldsToOmit);
110
113
  expect(result).toEqual([
111
114
  {
112
115
  fields: [
@@ -152,7 +155,7 @@ describe("utils: parseGroups", () => {
152
155
  };
153
156
  const content = { parent: "b", dependant: "1" };
154
157
  const fieldsToOmit = ["ommitedField"];
155
- const result = parseGroups(template, content, fieldsToOmit);
158
+ const result = formatParseGroups(template, content, fieldsToOmit);
156
159
  expect(result).toEqual([
157
160
  {
158
161
  fields: [
@@ -192,7 +195,7 @@ describe("utils: parseGroups", () => {
192
195
  ],
193
196
  };
194
197
  const content = { field: "1" };
195
- const result = parseGroups(template, content);
198
+ const result = formatParseGroups(template, content);
196
199
  expect(result).toEqual([
197
200
  {
198
201
  fields: [{ name: "field", required: false, value: "1" }],
@@ -216,7 +219,7 @@ describe("utils: parseGroups", () => {
216
219
  ],
217
220
  };
218
221
  const content = { secret: "1", not_secret: "2" };
219
- const result = parseGroups(template, content);
222
+ const result = formatParseGroups(template, content);
220
223
  expect(result).toEqual([
221
224
  {
222
225
  fields: [{ name: "not_secret", required: false, value: "2" }],
@@ -1,60 +1,72 @@
1
1
  import _ from "lodash/fp";
2
+ import { accentInsensitivePathOrder } from "@truedat/core/services/sort";
2
3
 
3
- const stringToValueTextList = _.map((v) => ({ value: v, text: v }));
4
+ const makeOptions = (formatMessage, label) =>
5
+ _.map((v) => ({
6
+ value: v,
7
+ text: formatMessage({ id: `fields.${label}.${v}`, defaultMessage: v }),
8
+ }));
4
9
 
5
- export const parseFieldOptions = (content, selectedDomain) => (field) => {
6
- const value = _.prop(field?.name)(content);
7
- if (!field?.values) return { ...field, value };
10
+ export const parseFieldOptions =
11
+ (formatMessage) => (content, selectedDomain) => (field) => {
12
+ const value = _.prop(field?.name)(content);
13
+ if (!field?.values) return { ...field, value };
8
14
 
9
- const parseSwitch = (values) => {
10
- const switchOn = _.prop("switch.on")(values);
11
- const switchedValues = _.prop(`switch.values.${content[switchOn]}`)(values);
12
- return stringToValueTextList(switchedValues);
13
- };
14
- const parseFixed = _.flow(_.get("fixed"), stringToValueTextList);
15
- const parseRoleUsers = _.flow(
16
- _.get("processed_users"),
17
- _.cond([
18
- [_.isArray, _.identity],
19
- [_.stubTrue, _.constant([])],
20
- ]),
21
- stringToValueTextList
22
- );
23
- const parseRoleGroups = (values) =>
24
- _.concat(
25
- _.flow(
26
- _.get("processed_users"),
27
- _.map((name) => ({
28
- value: `user:${name}`,
29
- text: name,
30
- icon: "user",
31
- }))
32
- )(values),
33
- _.flow(
34
- _.get("processed_groups"),
35
- _.map((name) => ({
36
- value: `group:${name}`,
37
- text: name,
38
- icon: "group",
39
- }))
40
- )(values)
15
+ const translateValues = _.flow(
16
+ makeOptions(formatMessage, field?.label),
17
+ _.sortBy(accentInsensitivePathOrder("text"))
18
+ );
19
+ const parseSwitch = (values) => {
20
+ const switchOn = _.prop("switch.on")(values);
21
+ const switchedValues = _.prop(`switch.values.${content[switchOn]}`)(
22
+ values
23
+ );
24
+ return translateValues(switchedValues);
25
+ };
26
+ const parseFixed = _.flow(_.get("fixed"), translateValues);
27
+ const parseRoleUsers = _.flow(
28
+ _.get("processed_users"),
29
+ _.cond([
30
+ [_.isArray, _.identity],
31
+ [_.stubTrue, _.constant([])],
32
+ ]),
33
+ translateValues
34
+ );
35
+ const parseRoleGroups = (values) =>
36
+ _.concat(
37
+ _.flow(
38
+ _.get("processed_users"),
39
+ _.map((name) => ({
40
+ value: `user:${name}`,
41
+ text: name,
42
+ icon: "user",
43
+ }))
44
+ )(values),
45
+ _.flow(
46
+ _.get("processed_groups"),
47
+ _.map((name) => ({
48
+ value: `group:${name}`,
49
+ text: name,
50
+ icon: "group",
51
+ }))
52
+ )(values)
53
+ );
54
+ const parseDomain = _.flow(
55
+ _.get("domain"),
56
+ _.propOr([], _.toString(selectedDomain?.id)),
57
+ translateValues
41
58
  );
42
- const parseDomain = _.flow(
43
- _.get("domain"),
44
- _.propOr([], _.toString(selectedDomain?.id)),
45
- stringToValueTextList
46
- );
47
59
 
48
- const parsedValues = _.flow(
49
- _.get("values"),
50
- _.cond([
51
- [_.has("switch"), parseSwitch],
52
- [_.has("fixed"), parseFixed],
53
- [_.has("fixed_tuple"), _.get("fixed_tuple")],
54
- [_.has("role_users"), parseRoleUsers],
55
- [_.has("role_groups"), parseRoleGroups],
56
- [_.has("domain"), parseDomain],
57
- ])
58
- )(field);
59
- return { ...field, value, parsedValues };
60
- };
60
+ const parsedValues = _.flow(
61
+ _.get("values"),
62
+ _.cond([
63
+ [_.has("switch"), parseSwitch],
64
+ [_.has("fixed"), parseFixed],
65
+ [_.has("fixed_tuple"), _.get("fixed_tuple")],
66
+ [_.has("role_users"), parseRoleUsers],
67
+ [_.has("role_groups"), parseRoleGroups],
68
+ [_.has("domain"), parseDomain],
69
+ ])
70
+ )(field);
71
+ return { ...field, value, parsedValues };
72
+ };
@@ -17,26 +17,27 @@ const checkDependency = (field, content) => {
17
17
  const enrichIsSecret = (isSecret) => (field) =>
18
18
  isSecret ? { ...field, isSecret } : field;
19
19
 
20
- export const parseGroups = (template, content, fieldsToOmit, selectedDomain) =>
21
- _.flow(
22
- _.getOr([], "content"),
23
- _.map((group) => {
24
- const fields = _.flow(
25
- _.get("fields"),
26
- _.reject((field) => _.includes(fieldsToOmit)(field?.name)),
27
- _.filter(
28
- (field) =>
29
- (!("depends" in field) ||
30
- (hasDependentKeys(field) && checkDependency(field, content))) &&
31
- (!(field.values && "switch" in field.values) ||
32
- _.prop(_.prop("values.switch.on")(field))(content) in
33
- _.prop("values.switch.values")(field))
34
- ),
35
- _.map(parseFieldOptions(content, selectedDomain)),
36
- _.map(enrichRequired(content)),
37
- _.map(enrichIsSecret(_.get("is_secret")(group)))
38
- )(group);
39
- return { ...group, fields };
40
- }),
41
- _.filter(({ fields }) => _.negate(_.isEmpty)(fields))
42
- )(template);
20
+ export const parseGroups =
21
+ (formatMessage) => (template, content, fieldsToOmit, selectedDomain) =>
22
+ _.flow(
23
+ _.getOr([], "content"),
24
+ _.map((group) => {
25
+ const fields = _.flow(
26
+ _.get("fields"),
27
+ _.reject((field) => _.includes(fieldsToOmit)(field?.name)),
28
+ _.filter(
29
+ (field) =>
30
+ (!("depends" in field) ||
31
+ (hasDependentKeys(field) && checkDependency(field, content))) &&
32
+ (!(field.values && "switch" in field.values) ||
33
+ _.prop(_.prop("values.switch.on")(field))(content) in
34
+ _.prop("values.switch.values")(field))
35
+ ),
36
+ _.map(parseFieldOptions(formatMessage)(content, selectedDomain)),
37
+ _.map(enrichRequired(content)),
38
+ _.map(enrichIsSecret(_.get("is_secret")(group)))
39
+ )(group);
40
+ return { ...group, fields };
41
+ }),
42
+ _.filter(({ fields }) => _.negate(_.isEmpty)(fields))
43
+ )(template);