@truedat/dq 4.35.7 → 4.36.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 +12 -0
- package/package.json +4 -4
- package/src/components/ConditionSummary.js +13 -7
- package/src/components/ImplementationSummary.js +57 -7
- package/src/components/NewRuleImplementation.js +115 -22
- package/src/components/__test_samples__/NewRuleImplementationProps.js +1917 -0
- package/src/components/__tests__/ImplementationSummary.spec.js +1 -0
- package/src/components/__tests__/NewRuleImplementation.spec.js +8 -0
- package/src/components/__tests__/__snapshots__/ConditionSummary.spec.js.snap +1 -0
- package/src/components/__tests__/__snapshots__/ImplementationSummary.spec.js.snap +30 -2
- package/src/components/__tests__/__snapshots__/NewRuleImplementation.spec.js.snap +1129 -0
- package/src/components/ruleImplementationForm/DatasetForm.js +26 -4
- package/src/components/ruleImplementationForm/FiltersField.js +6 -2
- package/src/components/ruleImplementationForm/FiltersFormGroup.js +7 -1
- package/src/components/ruleImplementationForm/FiltersGrid.js +7 -2
- package/src/components/ruleImplementationForm/__tests__/__snapshots__/DataSetForm.spec.js.snap +34 -1
- package/src/messages/en.js +2 -0
- package/src/messages/es.js +2 -0
- package/src/styles/ImplementationSummary.less +3 -0
- package/src/styles/ruleImplementationForm/DatasetForm.less +3 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [4.36.2] 2022-01-17
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- [TD-3178] Show join details in implementation summary
|
|
8
|
+
|
|
9
|
+
## [4.35.8] 2022-01-07
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- [TD-4390] Support for alias on Implementation
|
|
14
|
+
|
|
3
15
|
## [4.35.5] 2021-12-20
|
|
4
16
|
|
|
5
17
|
### Added
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@truedat/dq",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.36.2",
|
|
4
4
|
"description": "Truedat Web Data Quality Module",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"jsnext:main": "src/index.js",
|
|
@@ -82,8 +82,8 @@
|
|
|
82
82
|
},
|
|
83
83
|
"dependencies": {
|
|
84
84
|
"@apollo/client": "^3.4.10",
|
|
85
|
-
"@truedat/core": "4.
|
|
86
|
-
"@truedat/df": "4.
|
|
85
|
+
"@truedat/core": "4.36.2",
|
|
86
|
+
"@truedat/df": "4.36.2",
|
|
87
87
|
"axios": "^0.19.2",
|
|
88
88
|
"graphql": "^15.5.3",
|
|
89
89
|
"path-to-regexp": "^1.7.0",
|
|
@@ -103,5 +103,5 @@
|
|
|
103
103
|
"react-dom": ">= 16.8.6 < 17",
|
|
104
104
|
"semantic-ui-react": ">= 0.88.2 < 2.1"
|
|
105
105
|
},
|
|
106
|
-
"gitHead": "
|
|
106
|
+
"gitHead": "0f4c09d90582210ae7c98e945b8c0b7af0f9a61d"
|
|
107
107
|
}
|
|
@@ -74,7 +74,12 @@ OperatorMessage.propTypes = {
|
|
|
74
74
|
operator: PropTypes.object,
|
|
75
75
|
};
|
|
76
76
|
|
|
77
|
-
const ConditionCell = ({ row }) => {
|
|
77
|
+
const ConditionCell = ({ row, alias }) => {
|
|
78
|
+
const alias_text = _.flow(
|
|
79
|
+
_.find({ index: row.structure?.parent_index }),
|
|
80
|
+
_.propOr(null, "text")
|
|
81
|
+
)(alias);
|
|
82
|
+
|
|
78
83
|
const values = getValues(row);
|
|
79
84
|
const operator = _.prop("operator")(row);
|
|
80
85
|
return (
|
|
@@ -87,10 +92,10 @@ const ConditionCell = ({ row }) => {
|
|
|
87
92
|
id: _.path("structure.id")(row),
|
|
88
93
|
})}
|
|
89
94
|
>
|
|
90
|
-
<span className="highlighted">
|
|
91
|
-
""
|
|
92
|
-
"structure.name"
|
|
93
|
-
|
|
95
|
+
<span className="highlighted">
|
|
96
|
+
{alias_text && `(${alias_text}).`}{" "}
|
|
97
|
+
{`"${_.pathOr("", "structure.name")(row)}"`}
|
|
98
|
+
</span>
|
|
94
99
|
</Link>
|
|
95
100
|
{row?.modifier && (
|
|
96
101
|
<>
|
|
@@ -155,9 +160,10 @@ const ConditionCell = ({ row }) => {
|
|
|
155
160
|
|
|
156
161
|
ConditionCell.propTypes = {
|
|
157
162
|
row: PropTypes.object,
|
|
163
|
+
alias: PropTypes.array,
|
|
158
164
|
};
|
|
159
165
|
|
|
160
|
-
export const ConditionSummary = ({ rows, type, icon }) =>
|
|
166
|
+
export const ConditionSummary = ({ rows, type, icon, alias }) =>
|
|
161
167
|
empty(rows) ? null : (
|
|
162
168
|
<>
|
|
163
169
|
<Header as="h3">
|
|
@@ -185,7 +191,7 @@ export const ConditionSummary = ({ rows, type, icon }) =>
|
|
|
185
191
|
</Table.Header>
|
|
186
192
|
<Table.Body>
|
|
187
193
|
{rows.map((row, i) => (
|
|
188
|
-
<ConditionCell key={i} row={row} />
|
|
194
|
+
<ConditionCell key={i} row={row} alias={alias} />
|
|
189
195
|
))}
|
|
190
196
|
</Table.Body>
|
|
191
197
|
</Table>
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import _ from "lodash/fp";
|
|
2
2
|
import React from "react";
|
|
3
3
|
import PropTypes from "prop-types";
|
|
4
|
-
import { Header, Icon, Table, Segment } from "semantic-ui-react";
|
|
4
|
+
import { Header, Icon, Table, Segment, List } from "semantic-ui-react";
|
|
5
5
|
import { Link } from "react-router-dom";
|
|
6
6
|
import { FormattedMessage } from "react-intl";
|
|
7
7
|
import { linkTo } from "@truedat/core/routes";
|
|
8
8
|
import ConditionSummary, { empty, path } from "./ConditionSummary";
|
|
9
9
|
import InformationSummary from "./InformationSummary";
|
|
10
|
+
import "../styles/ImplementationSummary.less";
|
|
10
11
|
|
|
11
12
|
const defaults = [
|
|
12
13
|
"executable",
|
|
@@ -39,7 +40,45 @@ FormattedLink.propTypes = {
|
|
|
39
40
|
operator: PropTypes.object,
|
|
40
41
|
};
|
|
41
42
|
|
|
42
|
-
const
|
|
43
|
+
const AliasText = ({ alias, clause }) => {
|
|
44
|
+
const text = _.flow(
|
|
45
|
+
_.find({ index: clause?.parent_index }),
|
|
46
|
+
_.propOr(null, "text")
|
|
47
|
+
)(alias);
|
|
48
|
+
return _.isNull(text) ? clause?.name : `(${text}).${clause?.name}`;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
AliasText.propTypes = {
|
|
52
|
+
alias: PropTypes.array,
|
|
53
|
+
clause: PropTypes.object,
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const UnionSummary = ({ alias, row }) => {
|
|
57
|
+
return empty(row) || !(row?.clauses && _.size(row?.clauses) > 0) ? null : (
|
|
58
|
+
<List id="union-list">
|
|
59
|
+
<List.Item>
|
|
60
|
+
<List.Header>
|
|
61
|
+
<FormattedMessage id="structureSelector.union.criteria" />
|
|
62
|
+
</List.Header>
|
|
63
|
+
</List.Item>
|
|
64
|
+
{row.clauses.map((clause, k) =>
|
|
65
|
+
_.size(clause) > 0 ? (
|
|
66
|
+
<List.Item key={k}>
|
|
67
|
+
{clause.left && <AliasText alias={alias} clause={clause.left} />} ={" "}
|
|
68
|
+
{clause.right && <AliasText alias={alias} clause={clause.right} />}
|
|
69
|
+
</List.Item>
|
|
70
|
+
) : null
|
|
71
|
+
)}
|
|
72
|
+
</List>
|
|
73
|
+
);
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
UnionSummary.propTypes = {
|
|
77
|
+
row: PropTypes.object,
|
|
78
|
+
alias: PropTypes.array,
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
const DatasetSummary = ({ rows, alias }) =>
|
|
43
82
|
empty(rows) ? null : (
|
|
44
83
|
<>
|
|
45
84
|
<Header as="h3">
|
|
@@ -61,16 +100,19 @@ const DatasetSummary = ({ rows }) =>
|
|
|
61
100
|
{rows.map((row, i) => (
|
|
62
101
|
<Table.Row key={i}>
|
|
63
102
|
{_.has("structure")(row) && (
|
|
64
|
-
<Table.Cell
|
|
103
|
+
<Table.Cell>
|
|
65
104
|
<Link
|
|
66
105
|
to={linkTo.STRUCTURE({
|
|
67
106
|
id: _.pathOr("", "structure.id")(row),
|
|
68
107
|
})}
|
|
69
108
|
>
|
|
70
|
-
<
|
|
109
|
+
<p className="highlighted">{`"${path(
|
|
71
110
|
_.propOr({}, "structure")(row)
|
|
72
|
-
)}"`}</
|
|
111
|
+
)}"`}</p>
|
|
73
112
|
</Link>
|
|
113
|
+
|
|
114
|
+
{row.alias?.text && <span>({row.alias.text})</span>}
|
|
115
|
+
<UnionSummary alias={alias} row={row} />
|
|
74
116
|
</Table.Cell>
|
|
75
117
|
)}
|
|
76
118
|
</Table.Row>
|
|
@@ -83,12 +125,14 @@ const DatasetSummary = ({ rows }) =>
|
|
|
83
125
|
|
|
84
126
|
DatasetSummary.propTypes = {
|
|
85
127
|
rows: PropTypes.array,
|
|
128
|
+
alias: PropTypes.array,
|
|
86
129
|
};
|
|
87
130
|
|
|
88
131
|
export const ImplementationSummary = ({ ruleImplementation, activeSteps }) => {
|
|
89
132
|
const steps = _.isEmpty(activeSteps) ? defaults : activeSteps;
|
|
90
133
|
const { dataset, population, validations } =
|
|
91
134
|
_.pick(steps)(ruleImplementation);
|
|
135
|
+
const alias = _.map(_.propOr({}, "alias"))(dataset);
|
|
92
136
|
return (
|
|
93
137
|
<>
|
|
94
138
|
{(_.includes("implementationKey")(steps) ||
|
|
@@ -96,16 +140,22 @@ export const ImplementationSummary = ({ ruleImplementation, activeSteps }) => {
|
|
|
96
140
|
<InformationSummary ruleImplementation={ruleImplementation} />
|
|
97
141
|
)}
|
|
98
142
|
{dataset && _.includes("dataset")(steps) && (
|
|
99
|
-
<DatasetSummary rows={dataset} />
|
|
143
|
+
<DatasetSummary rows={dataset} alias={alias} />
|
|
100
144
|
)}
|
|
101
145
|
{population && _.includes("population")(steps) && (
|
|
102
|
-
<ConditionSummary
|
|
146
|
+
<ConditionSummary
|
|
147
|
+
type="population"
|
|
148
|
+
icon="user"
|
|
149
|
+
rows={population}
|
|
150
|
+
alias={alias}
|
|
151
|
+
/>
|
|
103
152
|
)}
|
|
104
153
|
{validations && _.includes("validations")(steps) && (
|
|
105
154
|
<ConditionSummary
|
|
106
155
|
type="validations"
|
|
107
156
|
icon="setting"
|
|
108
157
|
rows={validations}
|
|
158
|
+
alias={alias}
|
|
109
159
|
/>
|
|
110
160
|
)}
|
|
111
161
|
</>
|
|
@@ -29,7 +29,9 @@ const updateDatasetKey = (data) =>
|
|
|
29
29
|
)(data);
|
|
30
30
|
|
|
31
31
|
const updateConditionValue = (acc, value, key) => {
|
|
32
|
-
if (key === "structure")
|
|
32
|
+
if (key === "structure") {
|
|
33
|
+
return _.set(key, _.pick(["id", "parent_index"])(value))(acc);
|
|
34
|
+
}
|
|
33
35
|
if (key === "modifier")
|
|
34
36
|
return _.set(
|
|
35
37
|
key,
|
|
@@ -52,9 +54,9 @@ const updateConditionValue = (acc, value, key) => {
|
|
|
52
54
|
if (key == "value")
|
|
53
55
|
return _.set(
|
|
54
56
|
key,
|
|
55
|
-
_.map((v) =>
|
|
56
|
-
|
|
57
|
-
)
|
|
57
|
+
_.map((v) =>
|
|
58
|
+
_.has("id")(v) ? _.pick(["id", "parent_index"])(v) : _.pick(["raw"])(v)
|
|
59
|
+
)(value)
|
|
58
60
|
)(acc);
|
|
59
61
|
if (key === "population") return _.set(key, conditionAttributes(value))(acc);
|
|
60
62
|
|
|
@@ -69,7 +71,7 @@ const updateConditionKey = (condition) =>
|
|
|
69
71
|
|
|
70
72
|
const datasetAttributes = (dataset) =>
|
|
71
73
|
_.flow(
|
|
72
|
-
_.map(_.pickAll(["structure", "clauses", "join_type"])),
|
|
74
|
+
_.map(_.pickAll(["structure", "clauses", "join_type", "alias"])),
|
|
73
75
|
_.map(updateDatasetKey)
|
|
74
76
|
)(dataset);
|
|
75
77
|
|
|
@@ -172,6 +174,63 @@ const enrichOperator = (operators, scope, field_type, operator) => {
|
|
|
172
174
|
return { ...op_extra, ...operator };
|
|
173
175
|
};
|
|
174
176
|
|
|
177
|
+
const withDefaultAlias = (dataset) => {
|
|
178
|
+
const maxAliasIndex = _.max([
|
|
179
|
+
..._.flow(_.map("alias.index"), _.reject(_.isNil))(dataset),
|
|
180
|
+
0,
|
|
181
|
+
]);
|
|
182
|
+
const newDataset = dataset.map((s, index) => ({
|
|
183
|
+
...s,
|
|
184
|
+
alias: s.alias || {
|
|
185
|
+
index: index + maxAliasIndex,
|
|
186
|
+
text: `${s?.structure?.name} (${index + maxAliasIndex})`,
|
|
187
|
+
},
|
|
188
|
+
}));
|
|
189
|
+
|
|
190
|
+
const updateStructure = updateStructureParentIndex(newDataset);
|
|
191
|
+
return _.map((ds) => ({
|
|
192
|
+
...ds,
|
|
193
|
+
clauses:
|
|
194
|
+
ds.clauses &&
|
|
195
|
+
_.map(({ left, right }) => ({
|
|
196
|
+
left: updateStructure(left),
|
|
197
|
+
right: updateStructure(right),
|
|
198
|
+
}))(ds.clauses),
|
|
199
|
+
}))(newDataset);
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
const updateStructureParentIndex = (structures) => (structure) => {
|
|
203
|
+
if (
|
|
204
|
+
_.isArray(_.path("path")(structure)) &&
|
|
205
|
+
_.isNil(_.path("parent_index")(structure))
|
|
206
|
+
) {
|
|
207
|
+
const { path } = structure;
|
|
208
|
+
const parentPath = _.initial(path);
|
|
209
|
+
const parentName = _.last(path);
|
|
210
|
+
|
|
211
|
+
const parent = _.find(
|
|
212
|
+
(p) =>
|
|
213
|
+
_.isEqual(p.structure?.path)(parentPath) &&
|
|
214
|
+
_.isEqual(p.structure?.name)(parentName)
|
|
215
|
+
)(structures);
|
|
216
|
+
|
|
217
|
+
return { ...structure, parent_index: parent.alias.index };
|
|
218
|
+
}
|
|
219
|
+
return structure;
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
const withConditionDefaultAlias = (conditions, structures) =>
|
|
223
|
+
_.map((p) => {
|
|
224
|
+
return {
|
|
225
|
+
...p,
|
|
226
|
+
structure: updateStructureParentIndex(structures)(p.structure),
|
|
227
|
+
value:
|
|
228
|
+
!_.isEqual("references")(p.operator.group) && _.isArray(p.value)
|
|
229
|
+
? _.map(updateStructureParentIndex(structures))(p.value)
|
|
230
|
+
: p.value,
|
|
231
|
+
};
|
|
232
|
+
})(conditions);
|
|
233
|
+
|
|
175
234
|
export const NewRuleImplementation = ({
|
|
176
235
|
canManageRaw,
|
|
177
236
|
clone,
|
|
@@ -187,6 +246,10 @@ export const NewRuleImplementation = ({
|
|
|
187
246
|
template,
|
|
188
247
|
applyTemplate,
|
|
189
248
|
}) => {
|
|
249
|
+
const precalculatedDataset = _.flow(
|
|
250
|
+
_.propOr([{}], "dataset"),
|
|
251
|
+
withDefaultAlias
|
|
252
|
+
)(ruleImplementationProps);
|
|
190
253
|
const [ruleImplementation, setRuleImplementation] = useState(
|
|
191
254
|
edition
|
|
192
255
|
? {
|
|
@@ -198,22 +261,28 @@ export const NewRuleImplementation = ({
|
|
|
198
261
|
implementationType: _.prop("implementation_type")(
|
|
199
262
|
ruleImplementationProps
|
|
200
263
|
),
|
|
201
|
-
dataset:
|
|
202
|
-
population:
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
264
|
+
dataset: precalculatedDataset,
|
|
265
|
+
population: withConditionDefaultAlias(
|
|
266
|
+
addFieldType(
|
|
267
|
+
ruleImplementationProps,
|
|
268
|
+
structuresFields,
|
|
269
|
+
structuresSiblings,
|
|
270
|
+
"population",
|
|
271
|
+
"population",
|
|
272
|
+
operators
|
|
273
|
+
),
|
|
274
|
+
precalculatedDataset
|
|
209
275
|
),
|
|
210
|
-
validations:
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
276
|
+
validations: withConditionDefaultAlias(
|
|
277
|
+
addFieldType(
|
|
278
|
+
ruleImplementationProps,
|
|
279
|
+
structuresFields,
|
|
280
|
+
structuresSiblings,
|
|
281
|
+
"validations",
|
|
282
|
+
"validation",
|
|
283
|
+
operators
|
|
284
|
+
),
|
|
285
|
+
precalculatedDataset
|
|
217
286
|
),
|
|
218
287
|
rawContent: {
|
|
219
288
|
..._.prop("raw_content")(ruleImplementationProps),
|
|
@@ -246,9 +315,33 @@ export const NewRuleImplementation = ({
|
|
|
246
315
|
}
|
|
247
316
|
);
|
|
248
317
|
|
|
318
|
+
const withoutUnusedAliasText = (dataset) => {
|
|
319
|
+
const duplicatedStructures = _.flow(
|
|
320
|
+
_.groupBy("structure.id"),
|
|
321
|
+
_.pickBy((x) => x.length > 1),
|
|
322
|
+
_.keys,
|
|
323
|
+
_.map(Number)
|
|
324
|
+
)(dataset);
|
|
325
|
+
return _.map((ds) =>
|
|
326
|
+
_.has("structure.id")(ds) &&
|
|
327
|
+
_.includes(ds.structure.id)(duplicatedStructures)
|
|
328
|
+
? _.path("alias.text")(ds)
|
|
329
|
+
? ds
|
|
330
|
+
: {
|
|
331
|
+
...ds,
|
|
332
|
+
alias: {
|
|
333
|
+
...ds.alias,
|
|
334
|
+
text: `${ds.structure.name} (${ds.alias.index})`,
|
|
335
|
+
},
|
|
336
|
+
}
|
|
337
|
+
: { ...ds, alias: { ...ds.alias, text: null } }
|
|
338
|
+
)(dataset);
|
|
339
|
+
};
|
|
340
|
+
|
|
249
341
|
const setDataset = (dataset) => {
|
|
342
|
+
const cleanDataset = withoutUnusedAliasText(dataset);
|
|
250
343
|
//remove invalid references of fields in validations and populations after dataset edition
|
|
251
|
-
const datasetStructures = _.map(_.path("structure.id"))(
|
|
344
|
+
const datasetStructures = _.map(_.path("structure.id"))(cleanDataset);
|
|
252
345
|
const all_fields = _.flow(
|
|
253
346
|
_.pickAll(datasetStructures),
|
|
254
347
|
_.values,
|
|
@@ -282,7 +375,7 @@ export const NewRuleImplementation = ({
|
|
|
282
375
|
|
|
283
376
|
setRuleImplementation({
|
|
284
377
|
...ruleImplementation,
|
|
285
|
-
dataset,
|
|
378
|
+
dataset: cleanDataset,
|
|
286
379
|
population: _.isEmpty(population_within_dataset)
|
|
287
380
|
? []
|
|
288
381
|
: population_within_dataset,
|