@truedat/dq 4.46.4 → 4.46.5
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 +6 -0
- package/package.json +5 -5
- package/src/components/ConditionSummary.js +66 -22
- package/src/components/NewRuleImplementation.js +23 -6
- package/src/components/ruleImplementationForm/FiltersField.js +35 -10
- package/src/components/ruleImplementationForm/FiltersFormGroup.js +6 -2
- package/src/components/ruleImplementationForm/FiltersGrid.js +14 -4
- package/src/components/ruleImplementationForm/__tests__/__snapshots__/FiltersFormGroup.spec.js.snap +7 -1
- package/src/components/ruleImplementationForm/__tests__/__snapshots__/FiltersGroup.spec.js.snap +7 -1
- package/src/components/ruleImplementationForm/__tests__/__snapshots__/ValueConditions.spec.js.snap +7 -1
- package/src/messages/en.js +2 -1
- package/src/messages/es.js +2 -1
- package/src/selectors/getRuleImplementationOperators.js +1 -0
package/CHANGELOG.md
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@truedat/dq",
|
|
3
|
-
"version": "4.46.
|
|
3
|
+
"version": "4.46.5",
|
|
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.4",
|
|
35
35
|
"@testing-library/react": "^12.0.0",
|
|
36
36
|
"@testing-library/user-event": "^13.2.1",
|
|
37
|
-
"@truedat/test": "4.46.
|
|
37
|
+
"@truedat/test": "4.46.5",
|
|
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,8 +88,8 @@
|
|
|
88
88
|
},
|
|
89
89
|
"dependencies": {
|
|
90
90
|
"@apollo/client": "^3.6.4",
|
|
91
|
-
"@truedat/core": "4.46.
|
|
92
|
-
"@truedat/df": "4.46.
|
|
91
|
+
"@truedat/core": "4.46.5",
|
|
92
|
+
"@truedat/df": "4.46.5",
|
|
93
93
|
"axios": "^0.19.2",
|
|
94
94
|
"graphql": "^15.5.3",
|
|
95
95
|
"path-to-regexp": "^1.7.0",
|
|
@@ -110,5 +110,5 @@
|
|
|
110
110
|
"react-dom": ">= 16.8.6 < 17",
|
|
111
111
|
"semantic-ui-react": ">= 0.88.2 < 2.1"
|
|
112
112
|
},
|
|
113
|
-
"gitHead": "
|
|
113
|
+
"gitHead": "cc6e42515345adf2926f47216622e0fc4f7a0d86"
|
|
114
114
|
}
|
|
@@ -8,23 +8,41 @@ import { linkTo } from "@truedat/core/routes";
|
|
|
8
8
|
|
|
9
9
|
const concatValues = (values, link) => _.join(link)(values);
|
|
10
10
|
|
|
11
|
-
const
|
|
12
|
-
|
|
11
|
+
const LinkToStructure = ({ value }) => {
|
|
12
|
+
return value?.id ? (
|
|
13
13
|
<Link to={linkTo.STRUCTURE({ id: value.id })}>
|
|
14
14
|
<span className="highlighted">{`"${
|
|
15
15
|
!_.isEmpty(value.path) ? path(value) : value.name
|
|
16
16
|
}"`}</span>{" "}
|
|
17
17
|
</Link>
|
|
18
|
-
) :
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
18
|
+
) : null;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const FormattedLink = ({ value, operator = {} }) => {
|
|
22
|
+
switch (operator?.value_type) {
|
|
23
|
+
case "field":
|
|
24
|
+
return <LinkToStructure value={value} />;
|
|
25
|
+
case "field_list":
|
|
26
|
+
return (
|
|
27
|
+
<>
|
|
28
|
+
{_.map.convert({ cap: false })((v, i) => (
|
|
29
|
+
<LinkToStructure key={i} value={v} />
|
|
30
|
+
))(value)}
|
|
31
|
+
</>
|
|
32
|
+
);
|
|
33
|
+
default:
|
|
34
|
+
return (
|
|
35
|
+
<span className="highlighted">
|
|
36
|
+
<FormattedMessage
|
|
37
|
+
id={`ruleImplementation.filtersField.${value.raw}`}
|
|
38
|
+
defaultMessage={`"${
|
|
39
|
+
_.isArray(value.raw) ? _.join(", ")(value.raw) : value.raw
|
|
40
|
+
}"`}
|
|
41
|
+
></FormattedMessage>
|
|
42
|
+
</span>
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
};
|
|
28
46
|
|
|
29
47
|
FormattedLink.propTypes = {
|
|
30
48
|
value: PropTypes.object,
|
|
@@ -33,26 +51,52 @@ FormattedLink.propTypes = {
|
|
|
33
51
|
|
|
34
52
|
const nilOrEmpty = (v) => _.isNil(v) || v === "";
|
|
35
53
|
|
|
36
|
-
const filterNilOrEmpties = (values, keys) =>
|
|
37
|
-
|
|
54
|
+
const filterNilOrEmpties = (values, keys) => {
|
|
55
|
+
if ("kv" in values) {
|
|
56
|
+
return _.every((k) => !nilOrEmpty(values.kv[k]))(keys) ? values : null;
|
|
57
|
+
}
|
|
38
58
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
_.
|
|
42
|
-
|
|
59
|
+
return _.flow(
|
|
60
|
+
_.map((v) => filterNilOrEmpties(v, keys)),
|
|
61
|
+
_.filter((v) => !!v)
|
|
62
|
+
)(values);
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const pick = (value, keys, optionalKeys) => ({
|
|
66
|
+
kv: _.pick(keys)(value),
|
|
67
|
+
optv: _.pick(optionalKeys)(value),
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
const convert = (v, index, value_modifier) => {
|
|
71
|
+
if (_.has("kv")(v)) {
|
|
72
|
+
return { ...v.kv, ...v.optv, modifier: _.nth(index)(value_modifier) };
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return _.map.convert({ cap: false })((v, i) => {
|
|
76
|
+
return convert(v, i, value_modifier);
|
|
77
|
+
})(v);
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
const valuesFromKeys = (values, keys, optionalKeys, value_modifier) => {
|
|
81
|
+
return _.flow(
|
|
82
|
+
_.map((value) => {
|
|
83
|
+
return Array.isArray(value?.fields)
|
|
84
|
+
? _.map((innerValue) => pick(innerValue, keys, optionalKeys))(
|
|
85
|
+
value?.fields
|
|
86
|
+
)
|
|
87
|
+
: pick(value, keys, optionalKeys);
|
|
43
88
|
}),
|
|
44
89
|
(v) => filterNilOrEmpties(v, keys),
|
|
45
|
-
|
|
46
|
-
return { ...v.kv, ...v.optv, modifier: _.nth(i)(value_modifier) };
|
|
47
|
-
})
|
|
90
|
+
(v) => convert(v, 0, value_modifier)
|
|
48
91
|
)(values);
|
|
92
|
+
};
|
|
49
93
|
|
|
50
94
|
export const empty = (rows) =>
|
|
51
95
|
rows && _.every((r) => _.isEmpty(r) || _.isNil(r))(rows);
|
|
52
96
|
|
|
53
97
|
export const getValues = ({ value = [], operator = {}, value_modifier }) => {
|
|
54
98
|
const defaultOrValue = value || [];
|
|
55
|
-
return
|
|
99
|
+
return ["field", "field_list"].includes(operator?.value_type)
|
|
56
100
|
? valuesFromKeys(defaultOrValue, ["id", "name"], ["path"], value_modifier)
|
|
57
101
|
: valuesFromKeys(defaultOrValue, ["raw"], [], value_modifier);
|
|
58
102
|
};
|
|
@@ -25,6 +25,24 @@ const updateDatasetKey = (data) =>
|
|
|
25
25
|
{}
|
|
26
26
|
)(data);
|
|
27
27
|
|
|
28
|
+
// https://stackoverflow.com/a/38417085
|
|
29
|
+
const updateValueKeyValue = (object) => {
|
|
30
|
+
if (object?.id || object?.raw || object?.fields) {
|
|
31
|
+
return object?.id
|
|
32
|
+
? _.pick(["id", "parent_index"])(object)
|
|
33
|
+
: _.pick(["raw", "fields"])(object);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return Object.keys(object).reduce(
|
|
37
|
+
(output, key) => {
|
|
38
|
+
// eslint-disable-next-line fp/no-mutation
|
|
39
|
+
output[key] = updateValueKeyValue(object[key]);
|
|
40
|
+
return output;
|
|
41
|
+
},
|
|
42
|
+
Array.isArray(object) ? [] : {}
|
|
43
|
+
);
|
|
44
|
+
};
|
|
45
|
+
|
|
28
46
|
const updateConditionValue = (acc, value, key) => {
|
|
29
47
|
if (key === "structure") {
|
|
30
48
|
return _.set(key, _.pick(["id", "parent_index"])(value))(acc);
|
|
@@ -49,12 +67,10 @@ const updateConditionValue = (acc, value, key) => {
|
|
|
49
67
|
)
|
|
50
68
|
)(acc);
|
|
51
69
|
if (key == "value")
|
|
52
|
-
return
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
)(value)
|
|
57
|
-
)(acc);
|
|
70
|
+
return {
|
|
71
|
+
...acc,
|
|
72
|
+
value: updateValueKeyValue(value),
|
|
73
|
+
};
|
|
58
74
|
if (key === "population") return _.set(key, conditionAttributes(value))(acc);
|
|
59
75
|
|
|
60
76
|
return acc;
|
|
@@ -103,6 +119,7 @@ const fieldTypeFromStructure = (row, structures, operators, scope) => {
|
|
|
103
119
|
field_type,
|
|
104
120
|
_.prop("operator")(row)
|
|
105
121
|
);
|
|
122
|
+
|
|
106
123
|
const updatedRow = {
|
|
107
124
|
...row,
|
|
108
125
|
operator,
|
|
@@ -48,6 +48,24 @@ export const FiltersField = ({
|
|
|
48
48
|
const { value_type, value_type_filter, fixed_values } = operator;
|
|
49
49
|
|
|
50
50
|
const modifierDef = _.find({ name: modifier?.name })(typeCastModifiers);
|
|
51
|
+
const pickFromValue = _.pick(["data_structure_id", "name", "parent_index"]);
|
|
52
|
+
|
|
53
|
+
const getVal = (value) => {
|
|
54
|
+
return _.isNil(_.prop("parent_index")(value))
|
|
55
|
+
? _.prop("id")(value)
|
|
56
|
+
: `${_.prop("id")(value)}/${_.prop("parent_index")(value)}`;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const getValue = (valueOrValues, operator) => {
|
|
60
|
+
const getValueResultado =
|
|
61
|
+
operator?.value_type === "field_list"
|
|
62
|
+
? (valueOrValues?.fields || []).map((v) => {
|
|
63
|
+
return getVal(v);
|
|
64
|
+
})
|
|
65
|
+
: getVal(valueOrValues);
|
|
66
|
+
|
|
67
|
+
return getValueResultado;
|
|
68
|
+
};
|
|
51
69
|
|
|
52
70
|
switch (value_type) {
|
|
53
71
|
case "string":
|
|
@@ -89,6 +107,7 @@ export const FiltersField = ({
|
|
|
89
107
|
case "timestamp":
|
|
90
108
|
return <DateTimeField label={label} value={value} onChange={onChange} />;
|
|
91
109
|
case "field":
|
|
110
|
+
case "field_list":
|
|
92
111
|
const structureFields = getStructureFields(parentStructures);
|
|
93
112
|
return value_type_filter == "any" ? (
|
|
94
113
|
<StructureSelectorInputField
|
|
@@ -111,24 +130,30 @@ export const FiltersField = ({
|
|
|
111
130
|
) : (
|
|
112
131
|
<>
|
|
113
132
|
<StructureFieldsDropdown
|
|
133
|
+
multiple={value_type === "field_list"}
|
|
114
134
|
label={label}
|
|
115
135
|
inline={false}
|
|
116
136
|
parentStructures={parentStructures}
|
|
117
137
|
structureFields={structureFields}
|
|
118
138
|
typeCastModifiers={typeCastModifiers}
|
|
119
|
-
filters={
|
|
120
|
-
|
|
139
|
+
filters={
|
|
140
|
+
value_type === "field_list" ? null : { field_type: [fieldType] }
|
|
141
|
+
}
|
|
142
|
+
onSelectField={(value, modifier) => {
|
|
121
143
|
onChange(
|
|
122
144
|
null,
|
|
123
|
-
|
|
145
|
+
pickFromValue(value),
|
|
124
146
|
modifier ? { name: modifier.name } : null
|
|
125
|
-
)
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
147
|
+
);
|
|
148
|
+
}}
|
|
149
|
+
onSelectFields={(values) => {
|
|
150
|
+
onChange(
|
|
151
|
+
null,
|
|
152
|
+
values.map((value) => pickFromValue(value)),
|
|
153
|
+
null
|
|
154
|
+
);
|
|
155
|
+
}}
|
|
156
|
+
value={getValue(value, operator)}
|
|
132
157
|
/>
|
|
133
158
|
{modifier && (
|
|
134
159
|
<FieldModifier
|
|
@@ -65,7 +65,9 @@ export const FiltersFormGroup = ({
|
|
|
65
65
|
inline={false}
|
|
66
66
|
parentStructures={parentStructures}
|
|
67
67
|
structureFields={structureFields}
|
|
68
|
-
onSelectField={(value) =>
|
|
68
|
+
onSelectField={(value) => {
|
|
69
|
+
return onStructureChange(index, value /*[0]*/);
|
|
70
|
+
}}
|
|
69
71
|
value={
|
|
70
72
|
_.isNil(_.prop("parent_index")(clause?.structure))
|
|
71
73
|
? _.prop("id")(clause?.structure)
|
|
@@ -122,7 +124,9 @@ export const FiltersFormGroup = ({
|
|
|
122
124
|
})}
|
|
123
125
|
options={operatorsOptions}
|
|
124
126
|
value={getOperatorValue(clause)}
|
|
125
|
-
onClick={(
|
|
127
|
+
onClick={(whatever) => {
|
|
128
|
+
onOperatorChange(index, whatever.id);
|
|
129
|
+
}}
|
|
126
130
|
placeholder={formatMessage({
|
|
127
131
|
id: "operator.dropdown.placeholder",
|
|
128
132
|
})}
|
|
@@ -56,13 +56,23 @@ export const FiltersGrid = ({
|
|
|
56
56
|
});
|
|
57
57
|
};
|
|
58
58
|
|
|
59
|
+
const composeFieldValue = (value) => {
|
|
60
|
+
return {
|
|
61
|
+
id: value.data_structure_id || value.id,
|
|
62
|
+
name: value.name,
|
|
63
|
+
path: value.path,
|
|
64
|
+
parent_index: value.parent_index,
|
|
65
|
+
};
|
|
66
|
+
};
|
|
67
|
+
|
|
59
68
|
const composeValue = (value_type, value) => {
|
|
60
69
|
if (value_type == "field") {
|
|
70
|
+
return composeFieldValue(value);
|
|
71
|
+
} else if (value_type === "field_list") {
|
|
61
72
|
return {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
parent_index: value.parent_index,
|
|
73
|
+
fields: _.map((v) => {
|
|
74
|
+
return composeFieldValue(v);
|
|
75
|
+
})(value),
|
|
66
76
|
};
|
|
67
77
|
} else {
|
|
68
78
|
return { raw: value };
|
package/src/messages/en.js
CHANGED
|
@@ -423,7 +423,8 @@ export default {
|
|
|
423
423
|
"matches regular expression",
|
|
424
424
|
"ruleImplementation.operator.starts_with": "starts with",
|
|
425
425
|
"ruleImplementation.operator.starts_with.string": "starts with",
|
|
426
|
-
"ruleImplementation.operator.unique": "
|
|
426
|
+
"ruleImplementation.operator.unique": "unique",
|
|
427
|
+
"ruleImplementation.operator.unique.field_list": "unique across fields",
|
|
427
428
|
"ruleImplementation.operator.variation_on_count": "count variation",
|
|
428
429
|
"ruleImplementation.operator.variation_on_count.string": "count variation",
|
|
429
430
|
"ruleImplementation.props.esquema": "Structure",
|
package/src/messages/es.js
CHANGED
|
@@ -435,7 +435,8 @@ export default {
|
|
|
435
435
|
"ruleImplementation.operator.regex_format": "cumple la expresión regular",
|
|
436
436
|
"ruleImplementation.operator.starts_with.string": "empieza por",
|
|
437
437
|
"ruleImplementation.operator.starts_with": "empieza por",
|
|
438
|
-
"ruleImplementation.operator.unique": "
|
|
438
|
+
"ruleImplementation.operator.unique": "único",
|
|
439
|
+
"ruleImplementation.operator.unique.field_list": "único en conjunto",
|
|
439
440
|
"ruleImplementation.operator.variation_on_count.string": "variación conteo",
|
|
440
441
|
"ruleImplementation.operator.variation_on_count": "variación conteo",
|
|
441
442
|
"ruleImplementation.props.esquema.placeholder": "añade una estructura",
|