@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 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.35.7",
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.35.7",
86
- "@truedat/df": "4.35.7",
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": "99812619b928d7802bb2f33df3f3321c9c36995e"
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">{`"${_.pathOr(
91
- "",
92
- "structure.name"
93
- )(row)}"`}</span>
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 DatasetSummary = ({ rows }) =>
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 key={i}>
103
+ <Table.Cell>
65
104
  <Link
66
105
  to={linkTo.STRUCTURE({
67
106
  id: _.pathOr("", "structure.id")(row),
68
107
  })}
69
108
  >
70
- <span key={i} className="highlighted">{`"${path(
109
+ <p className="highlighted">{`"${path(
71
110
  _.propOr({}, "structure")(row)
72
- )}"`}</span>
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 type="population" icon="user" rows={population} />
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") return _.set(key, _.pick(["id"])(value))(acc);
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) => (_.has("id")(v) ? _.pick(["id"])(v) : _.pick(["raw"])(v)))(
56
- value
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: _.propOr([{}], "dataset")(ruleImplementationProps),
202
- population: addFieldType(
203
- ruleImplementationProps,
204
- structuresFields,
205
- structuresSiblings,
206
- "population",
207
- "population",
208
- operators
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: addFieldType(
211
- ruleImplementationProps,
212
- structuresFields,
213
- structuresSiblings,
214
- "validations",
215
- "validation",
216
- operators
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"))(dataset);
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,