@truedat/df 4.48.0 → 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.
Files changed (32) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/package.json +4 -4
  3. package/src/components/DynamicFieldValue.js +52 -44
  4. package/src/components/DynamicForm.js +18 -13
  5. package/src/components/DynamicFormViewer.js +22 -20
  6. package/src/components/EditableDynamicFieldValue.js +21 -22
  7. package/src/components/FieldGroupSegment.js +2 -2
  8. package/src/components/FieldGroupSubSegment/__tests__/FieldGroupSubSegment.spec.js +2 -2
  9. package/src/components/FieldGroupSubSegment/__tests__/__snapshots__/FieldGroupSubSegment.spec.js.snap +4 -4
  10. package/src/components/FieldGroupSubSegment/handleCopyModule.js +18 -18
  11. package/src/components/__tests__/__snapshots__/DynamicForm.spec.js.snap +74 -80
  12. package/src/components/widgets/CheckboxField.js +17 -9
  13. package/src/components/widgets/DynamicField.js +3 -1
  14. package/src/components/widgets/RadioField.js +16 -8
  15. package/src/components/widgets/__tests__/CheckboxField.spec.js +4 -7
  16. package/src/components/widgets/__tests__/RadioField.spec.js +3 -3
  17. package/src/components/widgets/__tests__/__snapshots__/CheckboxField.spec.js.snap +12 -2
  18. package/src/components/widgets/__tests__/__snapshots__/RadioField.spec.js.snap +2 -0
  19. package/src/selectors/__tests__/getOptions.spec.js +2 -2
  20. package/src/selectors/getOptions.js +1 -1
  21. package/src/templates/components/Template.js +7 -2
  22. package/src/templates/components/TemplateCard.js +2 -1
  23. package/src/templates/components/__tests__/Template.spec.js +12 -10
  24. package/src/templates/components/__tests__/__snapshots__/Template.spec.js.snap +278 -27
  25. package/src/templates/components/templateForm/ActiveGroupForm.js +8 -7
  26. package/src/templates/components/templateForm/ConditionalFieldForm.js +12 -4
  27. package/src/templates/components/templateForm/GroupsList.js +2 -2
  28. package/src/templates/components/templateForm/__tests__/__snapshots__/ActiveGroupForm.spec.js.snap +1 -1
  29. package/src/templates/utils/__tests__/parseFieldOptions.spec.js +5 -5
  30. package/src/templates/utils/__tests__/parseGroups.spec.js +10 -4
  31. package/src/templates/utils/parseFieldOptions.js +4 -5
  32. package/src/templates/utils/parseGroups.js +2 -3
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
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
+
3
9
  ## [4.47.3] 2022-06-28
4
10
 
5
11
  ### Added
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@truedat/df",
3
- "version": "4.48.0",
3
+ "version": "4.48.2",
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.0",
91
- "@truedat/core": "4.48.0",
90
+ "@truedat/auth": "4.48.2",
91
+ "@truedat/core": "4.48.2",
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": "c4587d045fa6c9028082bdfbcfb35e4383f117ed"
110
+ "gitHead": "93133e957332713e64c97eecdf45cc283c29bd32"
111
111
  }
@@ -7,51 +7,58 @@ import SystemPreview from "./widgets/SystemPreview";
7
7
  import FieldViewerValue from "./FieldViewerValue";
8
8
  import "../styles/fieldGroupDetail.less";
9
9
 
10
- export const DynamicFieldValue = (field) => {
11
- const { label, value, type, values, widget, isSecret } = field;
12
- return (
13
- <List.Item>
14
- <List.Header className="dynamic-field-header">{label}</List.Header>
15
-
16
- <List.Description>
17
- {_.isNil(value) || (!_.isNumber(value) && _.isEmpty(value)) ? (
18
- isSecret ? (
19
- <Container className="hidden-secret-value">
20
- <FormattedMessage id="template.field.hidden_secret" />
21
- </Container>
22
- ) : (
23
- <Icon name="minus" color="grey" />
24
- )
25
- ) : _.isArray(value) ? (
26
- type == "table" ? (
27
- <FieldViewerValue value={value} type={type} values={values} />
28
- ) : type == "system" ? (
29
- <SystemPreview value={value} />
30
- ) : (
31
- _.map.convert({ cap: false })((v, i) => (
32
- <FieldViewerValue
33
- key={i}
34
- value={v}
35
- type={type}
36
- multiple
37
- values={values}
38
- />
39
- ))(value)
40
- )
41
- ) : widget === "password" ? (
42
- "*****"
10
+ export const DynamicFieldValue = ({
11
+ label,
12
+ value,
13
+ type,
14
+ values,
15
+ widget,
16
+ isSecret,
17
+ }) => (
18
+ <List.Item>
19
+ <List.Header className="dynamic-field-header">
20
+ {label ? (
21
+ <FormattedMessage id={`fields.${label}`} defaultMessage={label} />
22
+ ) : null}
23
+ </List.Header>
24
+ <List.Description>
25
+ {_.isNil(value) || (!_.isNumber(value) && _.isEmpty(value)) ? (
26
+ isSecret ? (
27
+ <Container className="hidden-secret-value">
28
+ <FormattedMessage id="template.field.hidden_secret" />
29
+ </Container>
43
30
  ) : (
44
- <FieldViewerValue
45
- value={value}
46
- type={type}
47
- values={values}
48
- widget={widget}
49
- />
50
- )}
51
- </List.Description>
52
- </List.Item>
53
- );
54
- };
31
+ <Icon name="minus" color="grey" />
32
+ )
33
+ ) : _.isArray(value) ? (
34
+ type == "table" ? (
35
+ <FieldViewerValue value={value} type={type} values={values} />
36
+ ) : type == "system" ? (
37
+ <SystemPreview value={value} />
38
+ ) : (
39
+ _.map.convert({ cap: false })((v, i) => (
40
+ <FieldViewerValue
41
+ key={i}
42
+ value={v}
43
+ type={type}
44
+ multiple
45
+ values={values}
46
+ />
47
+ ))(value)
48
+ )
49
+ ) : widget === "password" ? (
50
+ "*****"
51
+ ) : (
52
+ <FieldViewerValue
53
+ value={value}
54
+ type={type}
55
+ values={values}
56
+ widget={widget}
57
+ />
58
+ )}
59
+ </List.Description>
60
+ </List.Item>
61
+ );
55
62
 
56
63
  DynamicFieldValue.propTypes = {
57
64
  label: PropTypes.string,
@@ -59,6 +66,7 @@ DynamicFieldValue.propTypes = {
59
66
  type: PropTypes.string,
60
67
  values: PropTypes.any,
61
68
  widget: PropTypes.string,
69
+ isSecret: PropTypes.bool,
62
70
  };
63
71
 
64
72
  export default DynamicFieldValue;
@@ -1,6 +1,7 @@
1
1
  import _ from "lodash/fp";
2
2
  import React, { useEffect } 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 { makeGetApplyTemplate, makeGetTemplate } from "../selectors";
6
7
  import { parseGroups } from "../utils";
@@ -15,6 +16,7 @@ export const DynamicForm = ({
15
16
  fieldsToOmit,
16
17
  selectedDomain,
17
18
  }) => {
19
+ const { formatMessage } = useIntl();
18
20
  const domainId = selectedDomain?.id;
19
21
  useEffect(() => {
20
22
  if (!_.isNil(domainId) && !_.isEmpty(template)) {
@@ -45,19 +47,22 @@ export const DynamicForm = ({
45
47
  selectedDomain
46
48
  );
47
49
 
48
- return (
49
- <>
50
- {parsedGroups.map(({ name, fields }, i) => (
51
- <FieldGroupSegment
52
- key={i}
53
- onFieldChange={handleChange}
54
- name={name}
55
- fields={fields}
56
- scope={_.prop("scope")(template)}
57
- />
58
- ))}
59
- </>
60
- );
50
+ return parsedGroups.map(({ name, fields }, i) => (
51
+ <FieldGroupSegment
52
+ key={i}
53
+ onFieldChange={handleChange}
54
+ name={
55
+ name
56
+ ? formatMessage({
57
+ id: `templates.groups.${name}`,
58
+ defaultMessage: name,
59
+ })
60
+ : null
61
+ }
62
+ fields={fields}
63
+ scope={template?.scope}
64
+ />
65
+ ));
61
66
  };
62
67
 
63
68
  DynamicForm.propTypes = {
@@ -1,7 +1,6 @@
1
- import _ from "lodash/fp";
2
1
  import React from "react";
3
2
  import PropTypes from "prop-types";
4
- import { FormattedMessage } from "react-intl";
3
+ import { useIntl } from "react-intl";
5
4
  import { Message } from "semantic-ui-react";
6
5
  import { parseGroups } from "../utils";
7
6
  import FieldGroupDetail from "./FieldGroupDetail";
@@ -12,30 +11,33 @@ export const DynamicFormViewer = ({
12
11
  boxLayout,
13
12
  editFunctions,
14
13
  }) => {
14
+ const { formatMessage } = useIntl();
15
15
  if (!template)
16
16
  return (
17
- <Message negative>
18
- <Message.Header>
19
- <FormattedMessage id="template.not_found.message" />
20
- </Message.Header>
21
- </Message>
17
+ <Message
18
+ negative
19
+ header={formatMessage({ id: "template.not_found.message" })}
20
+ />
22
21
  );
23
22
 
24
23
  const parsedGroups = parseGroups(template, content);
25
24
 
26
- return (
27
- <>
28
- {parsedGroups.map(({ name, fields }, i) => (
29
- <FieldGroupDetail
30
- key={i}
31
- name={name}
32
- fields={fields}
33
- boxLayout={boxLayout}
34
- editFunctions={editFunctions}
35
- />
36
- ))}
37
- </>
38
- );
25
+ return parsedGroups.map(({ name, fields }, i) => (
26
+ <FieldGroupDetail
27
+ key={i}
28
+ name={
29
+ name
30
+ ? formatMessage({
31
+ id: `templates.groups.${name}`,
32
+ defaultMessage: name,
33
+ })
34
+ : null
35
+ }
36
+ fields={fields}
37
+ boxLayout={boxLayout}
38
+ editFunctions={editFunctions}
39
+ />
40
+ ));
39
41
  };
40
42
 
41
43
  DynamicFormViewer.propTypes = {
@@ -2,18 +2,16 @@ import _ from "lodash/fp";
2
2
  import React, { useState, useEffect } from "react";
3
3
  import PropTypes from "prop-types";
4
4
  import { FormattedMessage } from "react-intl";
5
- import { useIntl } from "react-intl";
6
5
  import { Icon, List, Button, Container } from "semantic-ui-react";
7
6
  import SystemPreview from "./widgets/SystemPreview";
8
7
  import DynamicField from "./widgets/DynamicField";
9
8
  import FieldViewerValue from "./FieldViewerValue";
10
9
  import "../styles/fieldGroupDetail.less";
11
10
 
12
- export const EditableDynamicFieldValue = (field) => {
13
- const { formatMessage } = useIntl();
11
+ export const EditableDynamicFieldValue = (props) => {
14
12
  const [updatedFailed, setUpdateFailed] = useState(false);
15
13
  const { label, name, value, type, values, widget, isSecret, editFunctions } =
16
- field;
14
+ props;
17
15
  const {
18
16
  onChange,
19
17
  onCancel,
@@ -25,17 +23,10 @@ export const EditableDynamicFieldValue = (field) => {
25
23
 
26
24
  useEffect(() => {
27
25
  if (editingField !== name) return;
28
- switch (updateStatus) {
29
- case "success":
30
- setEditingField(null);
31
- break;
32
- case "fail":
33
- setUpdateFailed(true);
34
- break;
35
- case "updating":
36
- setUpdateFailed(false);
37
- }
38
- }, [editingField, name, updateStatus]);
26
+ else if (updateStatus === "success") setEditingField(null);
27
+ else if (updateStatus === "fail") setUpdateFailed(true);
28
+ else if (updateStatus === "updating") setUpdateFailed(false);
29
+ }, [editingField, name, setEditingField, updateStatus]);
39
30
 
40
31
  const handleCancel = () => {
41
32
  setEditingField(null);
@@ -51,17 +42,23 @@ export const EditableDynamicFieldValue = (field) => {
51
42
  className="editable-dynamic-field-header"
52
43
  onClick={() => setEditingField(name)}
53
44
  >
54
- {label}
45
+ {label ? (
46
+ <FormattedMessage id={`fields.${label}`} defaultMessage={label} />
47
+ ) : null}
55
48
  <Icon name={"pencil alternate"} />
56
49
  </List.Header>
57
50
  ) : (
58
- <List.Header className="dynamic-field-header">{label}</List.Header>
51
+ <List.Header className="dynamic-field-header">
52
+ {label ? (
53
+ <FormattedMessage id={`fields.${label}`} defaultMessage={label} />
54
+ ) : null}
55
+ </List.Header>
59
56
  )}
60
57
 
61
58
  <List.Description>
62
59
  {editingField === name ? (
63
60
  <>
64
- <DynamicField onChange={onChange} field={field} />
61
+ <DynamicField onChange={onChange} field={props} />
65
62
  <Container className="editable-dynamic-field-buttons">
66
63
  <Button
67
64
  className={
@@ -73,7 +70,7 @@ export const EditableDynamicFieldValue = (field) => {
73
70
  size="mini"
74
71
  loading={updateStatus === "updating"}
75
72
  >
76
- {formatMessage({ id: "template.field.action.save" })}
73
+ <FormattedMessage id="template.field.action.save" />
77
74
  </Button>
78
75
  <Button
79
76
  onClick={handleCancel}
@@ -82,7 +79,7 @@ export const EditableDynamicFieldValue = (field) => {
82
79
  size="mini"
83
80
  disabled={updateStatus === "updating"}
84
81
  >
85
- {formatMessage({ id: "template.field.action.cancel" })}
82
+ <FormattedMessage id="template.field.action.cancel" />
86
83
  </Button>
87
84
  </Container>
88
85
  </>
@@ -126,12 +123,14 @@ export const EditableDynamicFieldValue = (field) => {
126
123
  };
127
124
 
128
125
  EditableDynamicFieldValue.propTypes = {
126
+ editFunctions: PropTypes.object,
127
+ isSecret: PropTypes.bool,
129
128
  label: PropTypes.string,
130
- value: PropTypes.any,
129
+ name: PropTypes.string,
131
130
  type: PropTypes.string,
131
+ value: PropTypes.any,
132
132
  values: PropTypes.any,
133
133
  widget: PropTypes.string,
134
- editFunctions: PropTypes.object,
135
134
  };
136
135
 
137
136
  export default EditableDynamicFieldValue;
@@ -6,7 +6,7 @@ import FieldGroupSubSegment from "./FieldGroupSubSegment/FieldGroupSubSegment";
6
6
 
7
7
  export const FieldGroupSegment = ({ onFieldChange, name, fields, scope }) => (
8
8
  <Segment>
9
- {name !== "undefined" && <Header as="h4" content={name} />}
9
+ {name && name !== "undefined" ? <Header as="h4" content={name} /> : null}
10
10
  {fields &&
11
11
  fields.map((field, i) =>
12
12
  field.widget === "copy" ? (
@@ -34,7 +34,7 @@ FieldGroupSegment.propTypes = {
34
34
  onFieldChange: PropTypes.func,
35
35
  name: PropTypes.string,
36
36
  fields: PropTypes.array,
37
- scope: PropTypes.string
37
+ scope: PropTypes.string,
38
38
  };
39
39
 
40
40
  export default FieldGroupSegment;
@@ -16,7 +16,7 @@ describe("<FieldGroupSubSegment />", () => {
16
16
  cardinality: "1",
17
17
  label: "Entidad",
18
18
  name: "entidad",
19
- parsed_values: undefined,
19
+ parsedValues: undefined,
20
20
  type: "string",
21
21
  value: "a",
22
22
  widget: "string"
@@ -27,7 +27,7 @@ describe("<FieldGroupSubSegment />", () => {
27
27
  description: "des",
28
28
  label: "copy",
29
29
  name: "copy",
30
- parsed_values: undefined,
30
+ parsedValues: undefined,
31
31
  type: "string",
32
32
  value:
33
33
  '{"fileFormat":"DAT","header":true,"compression":"brotli","fields":[{"name":"New3","type":"decimal","size":11,"scale":2,"precision":10},{"name":"New5","type":"datetime","size":10,"format":"%d-%m-%Y %H:%M:%S"},{"name":"New1","type":"string","size":40},{"name":"New0","type":"datetime","size":10,"format":"%d-%m-%Y %H:%M:%S"},{"name":"New4","type":"string","size":40}]}',
@@ -77,7 +77,7 @@ exports[`<FieldGroupSubSegment /> matches the latest snapshot 1`] = `
77
77
  "description": "",
78
78
  "label": "fileFormat",
79
79
  "name": "fileFormat",
80
- "parsed_values": Array [
80
+ "parsedValues": Array [
81
81
  Object {
82
82
  "text": "CSV",
83
83
  "value": "CSV",
@@ -119,7 +119,7 @@ exports[`<FieldGroupSubSegment /> matches the latest snapshot 1`] = `
119
119
  "description": "",
120
120
  "label": "header",
121
121
  "name": "header",
122
- "parsed_values": Array [
122
+ "parsedValues": Array [
123
123
  Object {
124
124
  "text": "true",
125
125
  "value": "true",
@@ -152,7 +152,7 @@ exports[`<FieldGroupSubSegment /> matches the latest snapshot 1`] = `
152
152
  "description": "",
153
153
  "label": "compression",
154
154
  "name": "compression",
155
- "parsed_values": Array [
155
+ "parsedValues": Array [
156
156
  Object {
157
157
  "text": "none",
158
158
  "value": "none",
@@ -186,7 +186,7 @@ exports[`<FieldGroupSubSegment /> matches the latest snapshot 1`] = `
186
186
  "description": "",
187
187
  "label": "fields",
188
188
  "name": "fields",
189
- "parsed_values": Array [],
189
+ "parsedValues": Array [],
190
190
  "type": "string",
191
191
  "value": Array [
192
192
  Object {
@@ -2,7 +2,7 @@ import _ from "lodash/fp";
2
2
  import {
3
3
  ENTRIES_FORMAT,
4
4
  REQUIRED_COPY_ENTRIES,
5
- VALID_COMPRESSION
5
+ VALID_COMPRESSION,
6
6
  } from "./constants";
7
7
 
8
8
  const getCopyForm = (field, fileFormat, formatOptions) => {
@@ -12,7 +12,7 @@ const getCopyForm = (field, fileFormat, formatOptions) => {
12
12
  );
13
13
 
14
14
  const fileFormatConfiguration = fileFormat
15
- ? formatOptions.find(option => option.text === fileFormat).value
15
+ ? formatOptions.find((option) => option.text === fileFormat).value
16
16
  : "";
17
17
 
18
18
  return Object.entries(copyEntries)
@@ -44,7 +44,7 @@ const getCopyForm = (field, fileFormat, formatOptions) => {
44
44
  type: "string",
45
45
  name: key,
46
46
  widget,
47
- description: ""
47
+ description: "",
48
48
  };
49
49
  const dropdownValues =
50
50
  key === "compression"
@@ -52,18 +52,18 @@ const getCopyForm = (field, fileFormat, formatOptions) => {
52
52
  : key === "header"
53
53
  ? { fixed: ["true", "false"] }
54
54
  : key === "fileFormat"
55
- ? { fixed: formatOptions.map(option => option.text) }
55
+ ? { fixed: formatOptions.map((option) => option.text) }
56
56
  : "";
57
57
 
58
- const parsed_values = dropdownValues
59
- ? dropdownValues.fixed.map(item => {
58
+ const parsedValues = dropdownValues
59
+ ? dropdownValues.fixed.map((item) => {
60
60
  return { value: item, text: item };
61
61
  })
62
62
  : [];
63
63
  const values =
64
64
  typeof value === "boolean" ? [{ true: true }, { false: false }] : [];
65
65
  const currentValue = setFormFieldValue(key, value, fileFormat);
66
- return { ...dynamicFormObj, values, value: currentValue, parsed_values };
66
+ return { ...dynamicFormObj, values, value: currentValue, parsedValues };
67
67
  });
68
68
  };
69
69
 
@@ -75,7 +75,7 @@ const setFormFieldValue = (key, value, fileFormat) => {
75
75
  case "compression":
76
76
  return !VALID_COMPRESSION.includes(value) ? "none" : value;
77
77
  case "fields":
78
- return value.map(field => _handleCopyFields(field, fileFormat));
78
+ return value.map((field) => _handleCopyFields(field, fileFormat));
79
79
  default:
80
80
  return value;
81
81
  }
@@ -91,8 +91,8 @@ const getCopyJson = (field, fileFormat, hasChangedFormat = false) => {
91
91
  _.map(([key, value]) => [
92
92
  key,
93
93
  key === "fields"
94
- ? value.map(field => _handleCopyFields(field, fileFormat))
95
- : value
94
+ ? value.map((field) => _handleCopyFields(field, fileFormat))
95
+ : value,
96
96
  ]),
97
97
  _.fromPairs
98
98
  )(copyEntries);
@@ -107,7 +107,7 @@ const getCopyEntriesOnFormat = (format, copyEntries) => {
107
107
  header: true,
108
108
  compression: "none",
109
109
  fields: [],
110
- ...copyEntries
110
+ ...copyEntries,
111
111
  };
112
112
  if (format === "CSV") {
113
113
  const {
@@ -117,7 +117,7 @@ const getCopyEntriesOnFormat = (format, copyEntries) => {
117
117
  fields,
118
118
  delimiter,
119
119
  escape_char,
120
- quoted
120
+ quoted,
121
121
  } = emptyCopy;
122
122
  return {
123
123
  fileFormat,
@@ -126,7 +126,7 @@ const getCopyEntriesOnFormat = (format, copyEntries) => {
126
126
  escape_char: escape_char === undefined ? "\\" : escape_char,
127
127
  quoted: quoted === undefined ? '"' : quoted,
128
128
  delimiter: delimiter === undefined ? "," : delimiter,
129
- fields
129
+ fields,
130
130
  };
131
131
  }
132
132
  if (format === "JSON") {
@@ -145,7 +145,7 @@ const _handleCopyFields = (field, fileFormat) => {
145
145
  name,
146
146
  type: type || "string",
147
147
  size: size || 40,
148
- ...field
148
+ ...field,
149
149
  };
150
150
  switch (type) {
151
151
  case "integer":
@@ -155,25 +155,25 @@ const _handleCopyFields = (field, fileFormat) => {
155
155
  Object.assign(copyField, {
156
156
  scale: scale || 2,
157
157
  precision: precision || 10,
158
- size: size || 11
158
+ size: size || 11,
159
159
  });
160
160
  break;
161
161
  case "date":
162
162
  Object.assign(copyField, {
163
163
  size: size || 10,
164
- format: fieldFormat || "%d-%m-%Y"
164
+ format: fieldFormat || "%d-%m-%Y",
165
165
  });
166
166
  break;
167
167
  case "time":
168
168
  Object.assign(copyField, {
169
169
  size: size || 10,
170
- format: fieldFormat || "%H:%M:%S"
170
+ format: fieldFormat || "%H:%M:%S",
171
171
  });
172
172
  break;
173
173
  case "datetime":
174
174
  Object.assign(copyField, {
175
175
  size: size || 10,
176
- format: fieldFormat || "%d-%m-%Y %H:%M:%S"
176
+ format: fieldFormat || "%d-%m-%Y %H:%M:%S",
177
177
  });
178
178
  break;
179
179
  }