@truedat/df 7.4.5 → 7.5.1

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 (31) hide show
  1. package/package.json +5 -5
  2. package/src/messages/en.js +4 -0
  3. package/src/messages/es.js +5 -1
  4. package/src/styles/template.less +12 -0
  5. package/src/templates/components/__tests__/Template.spec.js +25 -9
  6. package/src/templates/components/__tests__/__snapshots__/Template.spec.js.snap +364 -5
  7. package/src/templates/components/templateForm/ActiveGroupForm.js +16 -2
  8. package/src/templates/components/templateForm/ConditionalFieldForm.js +28 -4
  9. package/src/templates/components/templateForm/DependentDomain.js +27 -1
  10. package/src/templates/components/templateForm/DependentFormField.js +1 -1
  11. package/src/templates/components/templateForm/FieldForm.js +33 -5
  12. package/src/templates/components/templateForm/HierarchiesList.js +0 -1
  13. package/src/templates/components/templateForm/MandatoryConditional.js +28 -5
  14. package/src/templates/components/templateForm/SwitchListForm.js +48 -2
  15. package/src/templates/components/templateForm/TemplateForm.js +58 -11
  16. package/src/templates/components/templateForm/TemplateFormActions.js +3 -2
  17. package/src/templates/components/templateForm/ValuesListForm.js +72 -1
  18. package/src/templates/components/templateForm/ValuesSelector.js +46 -7
  19. package/src/templates/components/templateForm/__tests__/DependentDomain.spec.js +2 -0
  20. package/src/templates/components/templateForm/__tests__/SwitchSegment.spec.js +1 -0
  21. package/src/templates/components/templateForm/__tests__/TemplateForm.spec.js +46 -2
  22. package/src/templates/components/templateForm/__tests__/TemplateFormActions.spec.js +7 -0
  23. package/src/templates/components/templateForm/__tests__/__snapshots__/ActiveGroupForm.spec.js.snap +6 -1
  24. package/src/templates/components/templateForm/__tests__/__snapshots__/DependentDomain.spec.js.snap +3 -0
  25. package/src/templates/components/templateForm/__tests__/__snapshots__/FieldForm.spec.js.snap +33 -7
  26. package/src/templates/components/templateForm/__tests__/__snapshots__/MandatoryConditional.spec.js.snap +3 -1
  27. package/src/templates/components/templateForm/__tests__/__snapshots__/SwitchListForm.spec.js.snap +10 -0
  28. package/src/templates/components/templateForm/__tests__/__snapshots__/TemplateForm.spec.js.snap +1250 -4
  29. package/src/templates/components/templateForm/__tests__/__snapshots__/TemplateFormActions.spec.js.snap +28 -0
  30. package/src/templates/components/templateForm/__tests__/__snapshots__/ValuesListForm.spec.js.snap +4 -0
  31. package/src/templates/components/templateForm/contentValidation.js +100 -15
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@truedat/df",
3
- "version": "7.4.5",
3
+ "version": "7.5.1",
4
4
  "description": "Truedat Web Data Quality Module",
5
5
  "sideEffects": false,
6
6
  "jsnext:main": "src/index.js",
@@ -34,7 +34,7 @@
34
34
  "@testing-library/jest-dom": "^5.16.5",
35
35
  "@testing-library/react": "^12.0.0",
36
36
  "@testing-library/user-event": "^13.2.1",
37
- "@truedat/test": "7.4.5",
37
+ "@truedat/test": "7.5.1",
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",
@@ -87,8 +87,8 @@
87
87
  },
88
88
  "dependencies": {
89
89
  "@apollo/client": "^3.7.1",
90
- "@truedat/auth": "7.4.5",
91
- "@truedat/core": "7.4.5",
90
+ "@truedat/auth": "7.5.1",
91
+ "@truedat/core": "7.5.1",
92
92
  "decode-uri-component": "^0.2.2",
93
93
  "path-to-regexp": "^1.7.0",
94
94
  "prop-types": "^15.8.1",
@@ -109,5 +109,5 @@
109
109
  "react-dom": ">= 16.8.6 < 17",
110
110
  "semantic-ui-react": ">= 2.0.3 < 2.2"
111
111
  },
112
- "gitHead": "2deeffe70bf878df0ea47917f1c8258d7e476914"
112
+ "gitHead": "dd78383f466a9151664396b76163d13c0a5c641c"
113
113
  }
@@ -94,6 +94,7 @@ export default {
94
94
  "template.field.values.add_file_config": "Add file config",
95
95
  "template.field.values.add_format": "Add format",
96
96
  "template.field.values.add_switch_value": "Add field value",
97
+ "template.field.values.add_switch_value.label": "Field value",
97
98
  "template.field.values.add_text": "Add text",
98
99
  "template.field.values.add_value": "Add value to the list",
99
100
  "template.field.values.column_mandatory": "Mandatory",
@@ -102,6 +103,7 @@ export default {
102
103
  "template.field.values.default.omit": "Undo default option",
103
104
  "template.field.values.default": "Select as default option",
104
105
  "template.field.values.domain_field": "Select domain",
106
+ "template.field.values.domain_label": "Associated domain",
105
107
  "template.field.values.domain": "Dependent on domain",
106
108
  "template.field.values.file_types": "File types",
107
109
  "template.field.values.fixed_tuple": "Key/Value list",
@@ -110,7 +112,9 @@ export default {
110
112
  "template.field.values.none": "Free text",
111
113
  "template.field.values.role_groups": "Users or Groups of a Role",
112
114
  "template.field.values.role_users": "Users of a Role",
115
+ "template.field.values.role.label": "Role",
113
116
  "template.field.values.switch_field": "In funtion of the field",
117
+ "template.field.values.switch_field.label": "Associated field",
114
118
  "template.field.values.switch": "Dependent on other field",
115
119
  "template.field.values.table_columns": "Columns of the table",
116
120
  "template.field.values": "Values",
@@ -94,6 +94,7 @@ export default {
94
94
  "template.field.values.add_file_config": "Añadir configuración de fichero",
95
95
  "template.field.values.add_format": "Añadir formato",
96
96
  "template.field.values.add_switch_value": "Añadir valor del campo",
97
+ "template.field.values.add_switch_value.label": "Valor del campo",
97
98
  "template.field.values.add_text": "Añadir texto",
98
99
  "template.field.values.add_value": "Añadir valor a la lista",
99
100
  "template.field.values.column_mandatory": "Obligatorio",
@@ -102,7 +103,8 @@ export default {
102
103
  "template.field.values.default.omit": "Deshacer opción por defecto",
103
104
  "template.field.values.default": "Seleccionar como opción por defecto",
104
105
  "template.field.values.domain_field": "Seleccionar dominio",
105
- "template.field.values.domain": "Seleccionar en función de dominio",
106
+ "template.field.values.domain_label": "Dominio asociado",
107
+ "template.field.values.domain": "En función de dominio",
106
108
  "template.field.values.file_types": "Tipos de ficheros",
107
109
  "template.field.values.fixed_tuple": "Lista de código/descripción",
108
110
  "template.field.values.fixed": "Lista fija",
@@ -110,7 +112,9 @@ export default {
110
112
  "template.field.values.none": "Texto libre",
111
113
  "template.field.values.role_groups": "Usuarios o grupos de un Role",
112
114
  "template.field.values.role_users": "Usuarios de un Role",
115
+ "template.field.values.role.label": "Role",
113
116
  "template.field.values.switch_field": "En función del campo",
117
+ "template.field.values.switch_field.label": "Campo asociado",
114
118
  "template.field.values.switch": "En función de otro campo",
115
119
  "template.field.values.table_columns": "Columnas de la tabla",
116
120
  "template.field.values": "Valores",
@@ -0,0 +1,12 @@
1
+ .ui.form.template-form{
2
+
3
+ .field > label{
4
+ padding-top: 0.1875rem;
5
+ padding-bottom: 0.1875rem;
6
+
7
+ .ui.pointing.label {
8
+ margin-top: -0.125rem;
9
+ margin-bottom: -0.25rem;
10
+ }
11
+ }
12
+ }
@@ -2,16 +2,32 @@ import React from "react";
2
2
  import { render } from "@truedat/test/render";
3
3
  import Template from "../Template";
4
4
 
5
- const renderOpts = {
6
- state: {
7
- template: { id: 1, label: "My Template", name: "template1" },
8
- templateDeleting: false,
9
- templateSaving: false,
10
- },
11
- };
12
-
13
5
  describe("<Template />", () => {
14
- it("matches the latest snapshot", () => {
6
+ it("matches the latest snapshot for empty data", () => {
7
+ const renderOpts = {
8
+ state: {
9
+ template: { id: null, label: "", name: "", scope: "" },
10
+ templateDeleting: false,
11
+ templateSaving: false,
12
+ },
13
+ };
14
+ const { container } = render(<Template />, renderOpts);
15
+ expect(container).toMatchSnapshot();
16
+ });
17
+
18
+ it("matches the latest snapshot with previous data", () => {
19
+ const renderOpts = {
20
+ state: {
21
+ template: {
22
+ id: 1,
23
+ label: "My Template",
24
+ name: "template1",
25
+ scope: "td",
26
+ },
27
+ templateDeleting: false,
28
+ templateSaving: false,
29
+ },
30
+ };
15
31
  const { container } = render(<Template />, renderOpts);
16
32
  expect(container).toMatchSnapshot();
17
33
  });
@@ -1,6 +1,363 @@
1
1
  // Jest Snapshot v1, https://goo.gl/fbAQLP
2
2
 
3
- exports[`<Template /> matches the latest snapshot 1`] = `
3
+ exports[`<Template /> matches the latest snapshot for empty data 1`] = `
4
+ <div>
5
+ <div
6
+ class="ui breadcrumb"
7
+ >
8
+ <a
9
+ class="section"
10
+ href="/templates"
11
+ >
12
+ Templates
13
+ </a>
14
+ <i
15
+ aria-hidden="true"
16
+ class="right angle icon divider"
17
+ />
18
+ <div
19
+ class="active section"
20
+ />
21
+ </div>
22
+ <div
23
+ class="ui segment"
24
+ >
25
+ <div
26
+ class="ui grid"
27
+ >
28
+ <div
29
+ class="eight wide column"
30
+ >
31
+ <h2
32
+ class="ui header"
33
+ >
34
+ <i
35
+ aria-hidden="true"
36
+ class="file code outline circular icon"
37
+ />
38
+ <div
39
+ class="content"
40
+ >
41
+
42
+ <div
43
+ class="sub header"
44
+ />
45
+ </div>
46
+ </h2>
47
+ </div>
48
+ <div
49
+ class="eight wide column"
50
+ >
51
+ <div
52
+ class="ui right aligned container"
53
+ />
54
+ </div>
55
+ </div>
56
+ <form
57
+ class="ui form template-form"
58
+ >
59
+ <div
60
+ class="ui horizontal divider"
61
+ >
62
+ <h4
63
+ class="ui header"
64
+ >
65
+ Template
66
+ </h4>
67
+ </div>
68
+ <div
69
+ class="fields"
70
+ >
71
+ <div
72
+ class="required six wide field"
73
+ >
74
+ <label>
75
+ Name
76
+ <div
77
+ class="ui left pointing label"
78
+ >
79
+ Empty required field
80
+ </div>
81
+ </label>
82
+ <div
83
+ class="ui input"
84
+ >
85
+ <input
86
+ name="name"
87
+ readonly=""
88
+ required=""
89
+ type="text"
90
+ value=""
91
+ />
92
+ </div>
93
+ </div>
94
+ <div
95
+ class="required six wide field"
96
+ >
97
+ <label>
98
+ Label
99
+ <div
100
+ class="ui left pointing label"
101
+ >
102
+ Empty required field
103
+ </div>
104
+ </label>
105
+ <div
106
+ class="ui input"
107
+ >
108
+ <input
109
+ name="label"
110
+ required=""
111
+ type="text"
112
+ value=""
113
+ />
114
+ </div>
115
+ </div>
116
+ <div
117
+ class="required four wide field"
118
+ >
119
+ <label>
120
+ Scope
121
+ <div
122
+ class="ui left pointing label"
123
+ >
124
+ Empty required field
125
+ </div>
126
+ </label>
127
+ <div
128
+ aria-expanded="false"
129
+ class="ui selection dropdown"
130
+ name="scope"
131
+ required=""
132
+ role="listbox"
133
+ tabindex="0"
134
+ >
135
+ <div
136
+ aria-atomic="true"
137
+ aria-live="polite"
138
+ class="divider default text"
139
+ role="alert"
140
+ >
141
+ Select scope...
142
+ </div>
143
+ <i
144
+ aria-hidden="true"
145
+ class="dropdown icon"
146
+ />
147
+ <div
148
+ class="menu transition"
149
+ >
150
+ <div
151
+ aria-checked="false"
152
+ aria-selected="true"
153
+ class="selected item"
154
+ role="option"
155
+ style="pointer-events: all;"
156
+ >
157
+ <span
158
+ class="text"
159
+ >
160
+ Business Concept
161
+ </span>
162
+ </div>
163
+ <div
164
+ aria-checked="false"
165
+ aria-selected="false"
166
+ class="item"
167
+ role="option"
168
+ style="pointer-events: all;"
169
+ >
170
+ <span
171
+ class="text"
172
+ >
173
+ Data Catalog
174
+ </span>
175
+ </div>
176
+ <div
177
+ aria-checked="false"
178
+ aria-selected="false"
179
+ class="item"
180
+ role="option"
181
+ style="pointer-events: all;"
182
+ >
183
+ <span
184
+ class="text"
185
+ >
186
+ Data Request
187
+ </span>
188
+ </div>
189
+ <div
190
+ aria-checked="false"
191
+ aria-selected="false"
192
+ class="item"
193
+ role="option"
194
+ style="pointer-events: all;"
195
+ >
196
+ <span
197
+ class="text"
198
+ >
199
+ Grants
200
+ </span>
201
+ </div>
202
+ <div
203
+ aria-checked="false"
204
+ aria-selected="false"
205
+ class="item"
206
+ role="option"
207
+ style="pointer-events: all;"
208
+ >
209
+ <span
210
+ class="text"
211
+ >
212
+ Quality Control
213
+ </span>
214
+ </div>
215
+ <div
216
+ aria-checked="false"
217
+ aria-selected="false"
218
+ class="item"
219
+ role="option"
220
+ style="pointer-events: all;"
221
+ >
222
+ <span
223
+ class="text"
224
+ >
225
+ Quality Executions
226
+ </span>
227
+ </div>
228
+ <div
229
+ aria-checked="false"
230
+ aria-selected="false"
231
+ class="item"
232
+ role="option"
233
+ style="pointer-events: all;"
234
+ >
235
+ <span
236
+ class="text"
237
+ >
238
+ Quality Implementation
239
+ </span>
240
+ </div>
241
+ <div
242
+ aria-checked="false"
243
+ aria-selected="false"
244
+ class="item"
245
+ role="option"
246
+ style="pointer-events: all;"
247
+ >
248
+ <span
249
+ class="text"
250
+ >
251
+ Quality Rule
252
+ </span>
253
+ </div>
254
+ <div
255
+ aria-checked="false"
256
+ aria-selected="false"
257
+ class="item"
258
+ role="option"
259
+ style="pointer-events: all;"
260
+ >
261
+ <span
262
+ class="text"
263
+ >
264
+ Remediation plan
265
+ </span>
266
+ </div>
267
+ <div
268
+ aria-checked="false"
269
+ aria-selected="false"
270
+ class="item"
271
+ role="option"
272
+ style="pointer-events: all;"
273
+ >
274
+ <span
275
+ class="text"
276
+ >
277
+ template.scope.qxe
278
+ </span>
279
+ </div>
280
+ </div>
281
+ </div>
282
+ </div>
283
+ <div
284
+ class="disabled six wide field"
285
+ >
286
+ <label>
287
+ Subscope
288
+ </label>
289
+ <div
290
+ class="ui disabled input"
291
+ >
292
+ <input
293
+ disabled=""
294
+ name="subscope"
295
+ placeholder="Type a subscope..."
296
+ tabindex="-1"
297
+ type="text"
298
+ value=""
299
+ />
300
+ </div>
301
+ </div>
302
+ </div>
303
+ <div
304
+ class="ui horizontal divider"
305
+ >
306
+ <h4
307
+ class="ui header"
308
+ >
309
+ Field Groups
310
+ </h4>
311
+ </div>
312
+ <div
313
+ class="ui grid"
314
+ >
315
+ <div
316
+ class="four wide column"
317
+ >
318
+ <div
319
+ class="ui pointing vertical menu"
320
+ >
321
+ <a
322
+ class="item"
323
+ >
324
+ <i
325
+ aria-hidden="true"
326
+ class="square plus icon"
327
+ />
328
+ Add Group
329
+ </a>
330
+ </div>
331
+ </div>
332
+ <div
333
+ class="twelve wide column"
334
+ />
335
+ </div>
336
+ <div
337
+ class="ui divider"
338
+ />
339
+ <div
340
+ class="ui right aligned container"
341
+ >
342
+ <button
343
+ class="ui primary disabled button"
344
+ disabled=""
345
+ tabindex="-1"
346
+ >
347
+ Save
348
+ </button>
349
+ <button
350
+ class="ui button"
351
+ >
352
+ Cancel
353
+ </button>
354
+ </div>
355
+ </form>
356
+ </div>
357
+ </div>
358
+ `;
359
+
360
+ exports[`<Template /> matches the latest snapshot with previous data 1`] = `
4
361
  <div>
5
362
  <div
6
363
  class="ui breadcrumb"
@@ -67,7 +424,7 @@ exports[`<Template /> matches the latest snapshot 1`] = `
67
424
  </div>
68
425
  </div>
69
426
  <form
70
- class="ui form"
427
+ class="ui form template-form"
71
428
  >
72
429
  <div
73
430
  class="ui horizontal divider"
@@ -133,14 +490,14 @@ exports[`<Template /> matches the latest snapshot 1`] = `
133
490
  <div
134
491
  aria-atomic="true"
135
492
  aria-live="polite"
136
- class="divider default text"
493
+ class="divider text"
137
494
  role="alert"
138
495
  >
139
496
  Select scope...
140
497
  </div>
141
498
  <i
142
499
  aria-hidden="true"
143
- class="dropdown icon"
500
+ class="dropdown icon clear"
144
501
  />
145
502
  <div
146
503
  class="menu transition"
@@ -338,7 +695,9 @@ exports[`<Template /> matches the latest snapshot 1`] = `
338
695
  class="ui right aligned container"
339
696
  >
340
697
  <button
341
- class="ui primary button"
698
+ class="ui primary disabled button"
699
+ disabled=""
700
+ tabindex="-1"
342
701
  >
343
702
  Save
344
703
  </button>
@@ -10,7 +10,7 @@ import {
10
10
  Input,
11
11
  Icon,
12
12
  } from "semantic-ui-react";
13
- import { useIntl } from "react-intl";
13
+ import { FormattedMessage, useIntl } from "react-intl";
14
14
  import { dropAt, swap } from "@truedat/core/services/arrays";
15
15
  import FieldForm from "./FieldForm";
16
16
 
@@ -66,6 +66,7 @@ export const ActiveGroupForm = ({
66
66
  };
67
67
  const name = `${groupNamePrefix}.fields`;
68
68
  onChange(null, { name, value: [...fields, newField] });
69
+ setActiveField(fields.length);
69
70
  };
70
71
 
71
72
  const onSelectField = (e, { index }) =>
@@ -94,6 +95,9 @@ export const ActiveGroupForm = ({
94
95
 
95
96
  const { formatMessage } = useIntl();
96
97
 
98
+ const isNullOrEmpty = (value) =>
99
+ !_.isNumber(value) && (!value || _.isEmpty(value));
100
+
97
101
  return (
98
102
  <>
99
103
  <Button.Group
@@ -134,7 +138,17 @@ export const ActiveGroupForm = ({
134
138
  <Form.Field
135
139
  control={Input}
136
140
  name={`${groupNamePrefix}.name`}
137
- label={formatMessage({ id: "template.form.group.name" })}
141
+ required
142
+ label={
143
+ <label>
144
+ {formatMessage({ id: "template.form.group.name" })}
145
+ {isNullOrEmpty(name) ? (
146
+ <Label pointing="left">
147
+ <FormattedMessage id="template.form.validation.empty_required" />
148
+ </Label>
149
+ ) : null}
150
+ </label>
151
+ }
138
152
  value={name}
139
153
  onChange={onChange}
140
154
  error={
@@ -1,7 +1,8 @@
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
+ import { FormattedMessage, useIntl } from "react-intl";
5
+ import { Label } from "semantic-ui-react";
5
6
  import DependentFormField from "./DependentFormField";
6
7
 
7
8
  const nilOrEmpty = (value) => _.isEmpty(value) || _.isNil(value);
@@ -47,15 +48,38 @@ const ConditionalFieldForm = ({
47
48
 
48
49
  onChange(e, { name, value });
49
50
  };
51
+ const value = _.propOr([], "to_be")(depends);
52
+ const fieldValue = _.propOr("", "on")(depends);
53
+ const isNullOrEmpty = (value) =>
54
+ !_.isNumber(value) && (!value || _.isEmpty(value));
50
55
  return (
51
56
  <DependentFormField
52
- label={formatMessage({ id: "template.field.depends" })}
57
+ label={
58
+ <label>
59
+ {formatMessage({ id: "template.field.depends" })}
60
+ {!isNullOrEmpty(fieldValue) && isNullOrEmpty(value) ? (
61
+ <>
62
+ <span
63
+ style={{
64
+ color: "#D95C5C",
65
+ marginLeft: "3px",
66
+ }}
67
+ >
68
+ *
69
+ </span>
70
+ <Label pointing="left">
71
+ <FormattedMessage id="template.form.validation.empty_required" />
72
+ </Label>
73
+ </>
74
+ ) : null}
75
+ </label>
76
+ }
53
77
  fieldName={`${fieldNamePrefix}.depends.on`}
54
78
  fieldOptions={optionFields}
55
79
  fieldPlaceholder={formatMessage({ id: "template.field.depends.on" })}
56
- fieldValue={_.propOr("", "on")(depends)}
80
+ fieldValue={fieldValue}
57
81
  onChange={handleChange}
58
- value={_.propOr([], "to_be")(depends)}
82
+ value={value}
59
83
  valueName={`${fieldNamePrefix}.depends.to_be`}
60
84
  valueOptions={optionValues}
61
85
  valuePlaceholder={formatMessage({ id: "template.field.depends.to_be" })}
@@ -1,9 +1,10 @@
1
1
  import _ from "lodash/fp";
2
2
  import React from "react";
3
3
  import PropTypes from "prop-types";
4
+ import { FormattedMessage } from "react-intl";
4
5
  import { useQuery } from "@apollo/client";
5
6
  import { useIntl } from "react-intl";
6
- import { Form, List } from "semantic-ui-react";
7
+ import { Form, List, Label } from "semantic-ui-react";
7
8
  import { DOMAINS_QUERY } from "../../../api/queries";
8
9
  import SwitchSegment from "./SwitchSegment";
9
10
 
@@ -37,6 +38,9 @@ export const DependentDomain = ({
37
38
  _.sortBy("text")
38
39
  )(domains);
39
40
 
41
+ const isNullOrEmpty = (value) =>
42
+ !_.isNumber(value) && (!value || _.isEmpty(value));
43
+
40
44
  return (
41
45
  <List verticalAlign="middle">
42
46
  {_.flow(
@@ -59,6 +63,28 @@ export const DependentDomain = ({
59
63
  <Form.Dropdown
60
64
  loading={loading}
61
65
  selection
66
+ label={
67
+ <label>
68
+ {formatMessage({
69
+ id: "template.field.values.domain_label",
70
+ })}
71
+ {isNullOrEmpty(values) ? (
72
+ <>
73
+ <Label pointing="left">
74
+ <FormattedMessage id="template.form.validation.empty_required" />
75
+ </Label>
76
+ <span
77
+ style={{
78
+ color: "#D95C5C",
79
+ marginLeft: "3px",
80
+ }}
81
+ >
82
+ *
83
+ </span>
84
+ </>
85
+ ) : null}
86
+ </label>
87
+ }
62
88
  placeholder={formatMessage({
63
89
  id: "template.field.values.domain_field",
64
90
  })}