@truedat/dq 4.56.4 → 4.56.6
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 +5 -5
- package/src/components/ConditionCell.js +268 -0
- package/src/components/ConditionSummary.js +2 -272
- package/src/components/FieldSummary.js +1 -34
- package/src/components/__tests__/ImplementationSummary.spec.js +1 -1
- package/src/components/__tests__/__snapshots__/ConditionSummary.spec.js.snap +3 -2
- package/src/components/__tests__/__snapshots__/ImplementationSummary.spec.js.snap +3 -2
- package/src/components/__tests__/__snapshots__/NewRuleImplementation.spec.js.snap +16 -9
- package/src/components/index.js +2 -0
- package/src/components/ruleImplementationForm/FieldsGrid.js +3 -1
- package/src/components/ruleImplementationForm/FiltersFormGroup.js +1 -0
- package/src/messages/en.js +5 -5
- package/src/messages/es.js +4 -4
- package/src/reducers/dqMessage.js +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [4.56.6] 2022-11-28
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- [TD-5247] FieldSummary and reference dataset table name
|
|
8
|
+
|
|
9
|
+
## [4.56.5] 2022-11-28
|
|
10
|
+
|
|
11
|
+
### Changed
|
|
12
|
+
|
|
13
|
+
- [TD-4711] Improve error reporting for implementation upload
|
|
14
|
+
|
|
3
15
|
## [4.56.4] 2022-11-26
|
|
4
16
|
|
|
5
17
|
### Fixed
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@truedat/dq",
|
|
3
|
-
"version": "4.56.
|
|
3
|
+
"version": "4.56.6",
|
|
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.56.
|
|
37
|
+
"@truedat/test": "4.56.6",
|
|
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",
|
|
@@ -93,8 +93,8 @@
|
|
|
93
93
|
},
|
|
94
94
|
"dependencies": {
|
|
95
95
|
"@apollo/client": "^3.7.0",
|
|
96
|
-
"@truedat/core": "4.56.
|
|
97
|
-
"@truedat/df": "4.56.
|
|
96
|
+
"@truedat/core": "4.56.6",
|
|
97
|
+
"@truedat/df": "4.56.6",
|
|
98
98
|
"graphql": "^15.5.3",
|
|
99
99
|
"path-to-regexp": "^1.7.0",
|
|
100
100
|
"prop-types": "^15.8.1",
|
|
@@ -114,5 +114,5 @@
|
|
|
114
114
|
"react-dom": ">= 16.8.6 < 17",
|
|
115
115
|
"semantic-ui-react": ">= 0.88.2 < 2.1"
|
|
116
116
|
},
|
|
117
|
-
"gitHead": "
|
|
117
|
+
"gitHead": "4291488ebae029cd8910dbd45ada4ef2e66bfecc"
|
|
118
118
|
}
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
import _ from "lodash/fp";
|
|
2
|
+
import React, { Fragment } from "react";
|
|
3
|
+
import PropTypes from "prop-types";
|
|
4
|
+
import { Icon, Table } from "semantic-ui-react";
|
|
5
|
+
import { useIntl } from "react-intl";
|
|
6
|
+
import { linkTo } from "@truedat/core/routes";
|
|
7
|
+
import { Link } from "react-router-dom";
|
|
8
|
+
import { FormattedMessage } from "react-intl";
|
|
9
|
+
|
|
10
|
+
const QualifyAndLinkStructure = ({ value, aliasArray }) =>
|
|
11
|
+
value?.id || value?.data_structure_id ? (
|
|
12
|
+
<Link to={linkTo.STRUCTURE({ id: value?.id || value?.data_structure_id })}>
|
|
13
|
+
<div className="highlighted">
|
|
14
|
+
{qualifySqlIdentifier({ aliasArray, value })}
|
|
15
|
+
</div>{" "}
|
|
16
|
+
</Link>
|
|
17
|
+
) : (
|
|
18
|
+
<div>{qualifySqlIdentifier({ aliasArray, value })}</div>
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
QualifyAndLinkStructure.propTypes = {
|
|
22
|
+
value: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
|
|
23
|
+
aliasArray: PropTypes.array,
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const FormattedLink = ({ value, aliasArray, operator = {} }) => {
|
|
27
|
+
switch (operator?.value_type) {
|
|
28
|
+
case "field":
|
|
29
|
+
return <QualifyAndLinkStructure value={value} aliasArray={aliasArray} />;
|
|
30
|
+
case "field_list":
|
|
31
|
+
return (
|
|
32
|
+
<>
|
|
33
|
+
{_.map.convert({ cap: false })((v, i) => (
|
|
34
|
+
<QualifyAndLinkStructure
|
|
35
|
+
key={i}
|
|
36
|
+
value={v}
|
|
37
|
+
aliasArray={aliasArray}
|
|
38
|
+
/>
|
|
39
|
+
))(value)}
|
|
40
|
+
</>
|
|
41
|
+
);
|
|
42
|
+
default:
|
|
43
|
+
return (
|
|
44
|
+
<span className="highlighted">
|
|
45
|
+
<FormattedMessage
|
|
46
|
+
id={`ruleImplementation.filtersField.${value.raw}`}
|
|
47
|
+
defaultMessage={`"${
|
|
48
|
+
_.isArray(value.raw) ? _.join(", ")(value.raw) : value.raw
|
|
49
|
+
}"`}
|
|
50
|
+
></FormattedMessage>
|
|
51
|
+
</span>
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
FormattedLink.propTypes = {
|
|
57
|
+
value: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
|
|
58
|
+
operator: PropTypes.object,
|
|
59
|
+
aliasArray: PropTypes.array,
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
const nilOrEmpty = (v) => _.isNil(v) || v === "";
|
|
63
|
+
|
|
64
|
+
const filterNilOrEmpties = (values, keys) => {
|
|
65
|
+
if ("kv" in values) {
|
|
66
|
+
return _.every((k) => !nilOrEmpty(values.kv[k]))(keys) ? values : null;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return _.flow(
|
|
70
|
+
_.map((v) => filterNilOrEmpties(v, keys)),
|
|
71
|
+
_.filter((v) => !!v)
|
|
72
|
+
)(values);
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const pick = (value, keys, optionalKeys) => ({
|
|
76
|
+
kv: _.pick(keys)(value),
|
|
77
|
+
optv: _.pick(optionalKeys)(value),
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
const convert = (v, index, value_modifier) => {
|
|
81
|
+
if (_.has("kv")(v)) {
|
|
82
|
+
return { ...v.kv, ...v.optv, modifier: _.nth(index)(value_modifier) };
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return _.map.convert({ cap: false })((v, i) => {
|
|
86
|
+
return convert(v, i, value_modifier);
|
|
87
|
+
})(v);
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
const valuesFromKeys = (values, keys, optionalKeys, value_modifier) =>
|
|
91
|
+
_.flow(
|
|
92
|
+
_.map((value) => {
|
|
93
|
+
return Array.isArray(value?.fields)
|
|
94
|
+
? _.map((innerValue) => pick(innerValue, keys, optionalKeys))(
|
|
95
|
+
value?.fields
|
|
96
|
+
)
|
|
97
|
+
: pick(value, keys, optionalKeys);
|
|
98
|
+
}),
|
|
99
|
+
(v) => filterNilOrEmpties(v, keys),
|
|
100
|
+
(v) => convert(v, 0, value_modifier)
|
|
101
|
+
)(values);
|
|
102
|
+
|
|
103
|
+
export const getValues = ({ value = [], operator = {}, value_modifier }) => {
|
|
104
|
+
const defaultOrValue = value || [];
|
|
105
|
+
return ["field", "field_list"].includes(operator?.value_type)
|
|
106
|
+
? valuesFromKeys(
|
|
107
|
+
defaultOrValue,
|
|
108
|
+
["name"],
|
|
109
|
+
["path", "metadata", "id", "type", "parent_index"],
|
|
110
|
+
value_modifier
|
|
111
|
+
)
|
|
112
|
+
: valuesFromKeys(defaultOrValue, ["raw"], [], value_modifier);
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
const OperatorMessage = ({ operator }) =>
|
|
116
|
+
_.negate(_.isNil)(_.prop("name")(operator)) ? (
|
|
117
|
+
<FormattedMessage
|
|
118
|
+
id={`ruleImplementation.operator.${_.prop("name")(operator)}`}
|
|
119
|
+
defaultMessage={_.prop("name")(operator)}
|
|
120
|
+
>
|
|
121
|
+
{(message) => <span className="highlighted">{`"${message}"`}</span>}
|
|
122
|
+
</FormattedMessage>
|
|
123
|
+
) : null;
|
|
124
|
+
|
|
125
|
+
OperatorMessage.propTypes = {
|
|
126
|
+
operator: PropTypes.object,
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
const qualifySqlIdentifier = ({ aliasArray, value }) =>
|
|
130
|
+
_.flow(
|
|
131
|
+
_.find({ index: value?.parent_index }),
|
|
132
|
+
_.propOr(null, "text"),
|
|
133
|
+
_.defaultTo(value?.metadata?.table || _.last(value?.path)),
|
|
134
|
+
(qualifier) => (qualifier ? `(${qualifier}).${value?.name}` : value?.name)
|
|
135
|
+
)(aliasArray);
|
|
136
|
+
|
|
137
|
+
export const ConditionCell = ({
|
|
138
|
+
row,
|
|
139
|
+
alias,
|
|
140
|
+
validationPopulationCondition,
|
|
141
|
+
}) => {
|
|
142
|
+
const values = getValues(row);
|
|
143
|
+
const operator = _.prop("operator")(row);
|
|
144
|
+
const { formatMessage } = useIntl();
|
|
145
|
+
return (
|
|
146
|
+
<>
|
|
147
|
+
<Table.Row
|
|
148
|
+
className={
|
|
149
|
+
validationPopulationCondition ? "validation-population-condition" : ""
|
|
150
|
+
}
|
|
151
|
+
>
|
|
152
|
+
<Table.Cell width={5}>
|
|
153
|
+
{row?.structure && (
|
|
154
|
+
<>
|
|
155
|
+
{validationPopulationCondition ? (
|
|
156
|
+
<Icon className="filter" />
|
|
157
|
+
) : null}
|
|
158
|
+
{
|
|
159
|
+
<QualifyAndLinkStructure
|
|
160
|
+
value={row.structure}
|
|
161
|
+
aliasArray={alias}
|
|
162
|
+
/>
|
|
163
|
+
}
|
|
164
|
+
{row?.modifier && (
|
|
165
|
+
<>
|
|
166
|
+
<div className="smaller">
|
|
167
|
+
<FormattedMessage
|
|
168
|
+
id={`filtersGrid.field.modifier.${row.modifier.name}`}
|
|
169
|
+
defaultMessage={row.modifier.name}
|
|
170
|
+
/>
|
|
171
|
+
</div>
|
|
172
|
+
{_.flow(
|
|
173
|
+
_.prop("modifier.params"),
|
|
174
|
+
_.toPairs,
|
|
175
|
+
_.map(([paramName, paramValue]) => (
|
|
176
|
+
<div key={paramName} className="smaller">
|
|
177
|
+
{`${formatMessage({
|
|
178
|
+
id: `filtersGrid.field.modifier.${row.modifier.name}.${paramName}`,
|
|
179
|
+
defaultMessage: paramName,
|
|
180
|
+
})}:`}
|
|
181
|
+
{_.isArray(paramValue)
|
|
182
|
+
? paramValue.map((paramValueItem, i) =>
|
|
183
|
+
paramValueItem?.id ||
|
|
184
|
+
paramValueItem?.data_structure_id ||
|
|
185
|
+
paramValueItem?.type ? (
|
|
186
|
+
<QualifyAndLinkStructure
|
|
187
|
+
key={`${paramName}_${i}`}
|
|
188
|
+
value={paramValueItem}
|
|
189
|
+
aliasArray={alias}
|
|
190
|
+
/>
|
|
191
|
+
) : (
|
|
192
|
+
<div key={`${paramName}_${i}`}>
|
|
193
|
+
`${paramValueItem}`
|
|
194
|
+
</div>
|
|
195
|
+
)
|
|
196
|
+
)
|
|
197
|
+
: `${paramValue}`}
|
|
198
|
+
</div>
|
|
199
|
+
))
|
|
200
|
+
)(row)}
|
|
201
|
+
</>
|
|
202
|
+
)}
|
|
203
|
+
</>
|
|
204
|
+
)}
|
|
205
|
+
</Table.Cell>
|
|
206
|
+
<Table.Cell width={5}>
|
|
207
|
+
{operator && <OperatorMessage operator={operator} />}
|
|
208
|
+
</Table.Cell>
|
|
209
|
+
<Table.Cell width={5}>
|
|
210
|
+
{_.map.convert({ cap: false })((value, i) => (
|
|
211
|
+
<Fragment key={i}>
|
|
212
|
+
<FormattedLink
|
|
213
|
+
value={value}
|
|
214
|
+
operator={operator}
|
|
215
|
+
aliasArray={alias}
|
|
216
|
+
/>
|
|
217
|
+
{i + 1 < _.size(values) && (
|
|
218
|
+
<span>
|
|
219
|
+
{" "}
|
|
220
|
+
<FormattedMessage id="summary.link.and" />{" "}
|
|
221
|
+
</span>
|
|
222
|
+
)}
|
|
223
|
+
{value?.modifier && (
|
|
224
|
+
<>
|
|
225
|
+
<div className="smaller">
|
|
226
|
+
<FormattedMessage
|
|
227
|
+
id={`filtersGrid.field.modifier.${value.modifier.name}`}
|
|
228
|
+
defaultMessage={value.modifier.name}
|
|
229
|
+
/>
|
|
230
|
+
</div>
|
|
231
|
+
{_.flow(
|
|
232
|
+
_.prop("modifier.params"),
|
|
233
|
+
_.toPairs,
|
|
234
|
+
_.map(([paramName, paramValue]) => (
|
|
235
|
+
<div key={paramName} className="smaller">
|
|
236
|
+
{`${formatMessage({
|
|
237
|
+
id: `filtersGrid.field.modifier.${value.modifier.name}.${paramName}`,
|
|
238
|
+
defaultMessage: paramName,
|
|
239
|
+
})}: ${paramValue}`}
|
|
240
|
+
</div>
|
|
241
|
+
))
|
|
242
|
+
)(value)}
|
|
243
|
+
</>
|
|
244
|
+
)}
|
|
245
|
+
</Fragment>
|
|
246
|
+
))(values)}
|
|
247
|
+
</Table.Cell>
|
|
248
|
+
</Table.Row>
|
|
249
|
+
{row?.population
|
|
250
|
+
? row.population.map((validationPopulationCondition, i) => (
|
|
251
|
+
<ConditionCell
|
|
252
|
+
validationPopulationCondition
|
|
253
|
+
row={validationPopulationCondition}
|
|
254
|
+
key={i}
|
|
255
|
+
/>
|
|
256
|
+
))
|
|
257
|
+
: null}
|
|
258
|
+
</>
|
|
259
|
+
);
|
|
260
|
+
};
|
|
261
|
+
|
|
262
|
+
ConditionCell.propTypes = {
|
|
263
|
+
row: PropTypes.object,
|
|
264
|
+
alias: PropTypes.array,
|
|
265
|
+
validationPopulationCondition: PropTypes.bool,
|
|
266
|
+
};
|
|
267
|
+
|
|
268
|
+
export default ConditionCell;
|
|
@@ -2,286 +2,16 @@ import _ from "lodash/fp";
|
|
|
2
2
|
import React, { Fragment } from "react";
|
|
3
3
|
import PropTypes from "prop-types";
|
|
4
4
|
import { Divider, Header, Icon, Segment, Table } from "semantic-ui-react";
|
|
5
|
-
import { Link } from "react-router-dom";
|
|
6
5
|
import { FormattedMessage } from "react-intl";
|
|
7
|
-
import
|
|
8
|
-
import { linkTo } from "@truedat/core/routes";
|
|
9
|
-
|
|
10
|
-
const concatValues = (values, link) => _.join(link)(values);
|
|
11
|
-
|
|
12
|
-
const LinkToStructure = ({ value, aliasArray }) =>
|
|
13
|
-
value?.id ? (
|
|
14
|
-
<Link to={linkTo.STRUCTURE({ id: value.id })}>
|
|
15
|
-
<div className="highlighted">
|
|
16
|
-
{qualifySqlIdentifier({ aliasArray, value })}
|
|
17
|
-
</div>{" "}
|
|
18
|
-
</Link>
|
|
19
|
-
) : (
|
|
20
|
-
<span>{value.name}</span>
|
|
21
|
-
);
|
|
22
|
-
|
|
23
|
-
LinkToStructure.propTypes = {
|
|
24
|
-
value: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
|
|
25
|
-
aliasArray: PropTypes.array,
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
const FormattedLink = ({ value, aliasArray, operator = {} }) => {
|
|
29
|
-
switch (operator?.value_type) {
|
|
30
|
-
case "field":
|
|
31
|
-
return <LinkToStructure value={value} aliasArray={aliasArray} />;
|
|
32
|
-
case "field_list":
|
|
33
|
-
return (
|
|
34
|
-
<>
|
|
35
|
-
{_.map.convert({ cap: false })((v, i) => (
|
|
36
|
-
<LinkToStructure key={i} value={v} aliasArray={aliasArray} />
|
|
37
|
-
))(value)}
|
|
38
|
-
</>
|
|
39
|
-
);
|
|
40
|
-
default:
|
|
41
|
-
return (
|
|
42
|
-
<span className="highlighted">
|
|
43
|
-
<FormattedMessage
|
|
44
|
-
id={`ruleImplementation.filtersField.${value.raw}`}
|
|
45
|
-
defaultMessage={`"${
|
|
46
|
-
_.isArray(value.raw) ? _.join(", ")(value.raw) : value.raw
|
|
47
|
-
}"`}
|
|
48
|
-
></FormattedMessage>
|
|
49
|
-
</span>
|
|
50
|
-
);
|
|
51
|
-
}
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
FormattedLink.propTypes = {
|
|
55
|
-
value: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
|
|
56
|
-
operator: PropTypes.object,
|
|
57
|
-
aliasArray: PropTypes.array,
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
const nilOrEmpty = (v) => _.isNil(v) || v === "";
|
|
61
|
-
|
|
62
|
-
const filterNilOrEmpties = (values, keys) => {
|
|
63
|
-
if ("kv" in values) {
|
|
64
|
-
return _.every((k) => !nilOrEmpty(values.kv[k]))(keys) ? values : null;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
return _.flow(
|
|
68
|
-
_.map((v) => filterNilOrEmpties(v, keys)),
|
|
69
|
-
_.filter((v) => !!v)
|
|
70
|
-
)(values);
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
const pick = (value, keys, optionalKeys) => ({
|
|
74
|
-
kv: _.pick(keys)(value),
|
|
75
|
-
optv: _.pick(optionalKeys)(value),
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
const convert = (v, index, value_modifier) => {
|
|
79
|
-
if (_.has("kv")(v)) {
|
|
80
|
-
return { ...v.kv, ...v.optv, modifier: _.nth(index)(value_modifier) };
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
return _.map.convert({ cap: false })((v, i) => {
|
|
84
|
-
return convert(v, i, value_modifier);
|
|
85
|
-
})(v);
|
|
86
|
-
};
|
|
87
|
-
|
|
88
|
-
const valuesFromKeys = (values, keys, optionalKeys, value_modifier) =>
|
|
89
|
-
_.flow(
|
|
90
|
-
_.map((value) => {
|
|
91
|
-
return Array.isArray(value?.fields)
|
|
92
|
-
? _.map((innerValue) => pick(innerValue, keys, optionalKeys))(
|
|
93
|
-
value?.fields
|
|
94
|
-
)
|
|
95
|
-
: pick(value, keys, optionalKeys);
|
|
96
|
-
}),
|
|
97
|
-
(v) => filterNilOrEmpties(v, keys),
|
|
98
|
-
(v) => convert(v, 0, value_modifier)
|
|
99
|
-
)(values);
|
|
6
|
+
import ConditionCell from "./ConditionCell";
|
|
100
7
|
|
|
101
8
|
export const empty = (rows) =>
|
|
102
9
|
rows && _.every((r) => _.isEmpty(r) || _.isNil(r))(rows);
|
|
103
10
|
|
|
104
|
-
export const getValues = ({ value = [], operator = {}, value_modifier }) => {
|
|
105
|
-
const defaultOrValue = value || [];
|
|
106
|
-
return ["field", "field_list"].includes(operator?.value_type)
|
|
107
|
-
? valuesFromKeys(
|
|
108
|
-
defaultOrValue,
|
|
109
|
-
["name"],
|
|
110
|
-
["path", "metadata", "id", "type", "parent_index"],
|
|
111
|
-
value_modifier
|
|
112
|
-
)
|
|
113
|
-
: valuesFromKeys(defaultOrValue, ["raw"], [], value_modifier);
|
|
114
|
-
};
|
|
115
|
-
|
|
116
11
|
export const path = ({ name, path = [] }) =>
|
|
117
12
|
concatValues([...path, name], " > ");
|
|
118
13
|
|
|
119
|
-
const
|
|
120
|
-
_.negate(_.isNil)(_.prop("name")(operator)) ? (
|
|
121
|
-
<FormattedMessage
|
|
122
|
-
id={`ruleImplementation.operator.${_.prop("name")(operator)}`}
|
|
123
|
-
defaultMessage={_.prop("name")(operator)}
|
|
124
|
-
>
|
|
125
|
-
{(message) => <span className="highlighted">{`"${message}"`}</span>}
|
|
126
|
-
</FormattedMessage>
|
|
127
|
-
) : null;
|
|
128
|
-
|
|
129
|
-
OperatorMessage.propTypes = {
|
|
130
|
-
operator: PropTypes.object,
|
|
131
|
-
};
|
|
132
|
-
|
|
133
|
-
const qualifySqlIdentifier = ({ aliasArray, value }) =>
|
|
134
|
-
_.flow(
|
|
135
|
-
_.find({ index: value?.parent_index }),
|
|
136
|
-
_.propOr(null, "text"),
|
|
137
|
-
_.defaultTo(value?.metadata?.table || _.last(value?.path)),
|
|
138
|
-
(qualifier) => (qualifier ? `(${qualifier}).${value?.name}` : value?.name)
|
|
139
|
-
)(aliasArray);
|
|
140
|
-
|
|
141
|
-
const ConditionCell = ({ row, alias, validationPopulationCondition }) => {
|
|
142
|
-
const values = getValues(row);
|
|
143
|
-
const operator = _.prop("operator")(row);
|
|
144
|
-
const { formatMessage } = useIntl();
|
|
145
|
-
return (
|
|
146
|
-
<>
|
|
147
|
-
<Table.Row
|
|
148
|
-
className={
|
|
149
|
-
validationPopulationCondition ? "validation-population-condition" : ""
|
|
150
|
-
}
|
|
151
|
-
>
|
|
152
|
-
<Table.Cell width={5}>
|
|
153
|
-
{_.has("structure")(row) && (
|
|
154
|
-
<>
|
|
155
|
-
{_.path("structure.id")(row) ? (
|
|
156
|
-
<>
|
|
157
|
-
{validationPopulationCondition ? (
|
|
158
|
-
<Icon className="filter" />
|
|
159
|
-
) : null}
|
|
160
|
-
<Link
|
|
161
|
-
to={linkTo.STRUCTURE({
|
|
162
|
-
id: _.path("structure.id")(row),
|
|
163
|
-
})}
|
|
164
|
-
>
|
|
165
|
-
<span className="highlighted">
|
|
166
|
-
{qualifySqlIdentifier({
|
|
167
|
-
aliasArray: alias,
|
|
168
|
-
value: row.structure,
|
|
169
|
-
})}
|
|
170
|
-
</span>
|
|
171
|
-
</Link>
|
|
172
|
-
</>
|
|
173
|
-
) : (
|
|
174
|
-
<span>{_.path("structure.name")(row)}</span>
|
|
175
|
-
)}
|
|
176
|
-
{row?.modifier && (
|
|
177
|
-
<>
|
|
178
|
-
<div className="smaller">
|
|
179
|
-
<FormattedMessage
|
|
180
|
-
id={`filtersGrid.field.modifier.${row.modifier.name}`}
|
|
181
|
-
defaultMessage={row.modifier.name}
|
|
182
|
-
/>
|
|
183
|
-
</div>
|
|
184
|
-
{_.flow(
|
|
185
|
-
_.prop("modifier.params"),
|
|
186
|
-
_.toPairs,
|
|
187
|
-
_.map(([paramName, paramValue]) => (
|
|
188
|
-
<div key={paramName} className="smaller">
|
|
189
|
-
{`${formatMessage({
|
|
190
|
-
id: `filtersGrid.field.modifier.${row.modifier.name}.${paramName}`,
|
|
191
|
-
defaultMessage: paramName,
|
|
192
|
-
})}:`}
|
|
193
|
-
{_.isArray(paramValue)
|
|
194
|
-
? paramValue.map((row, i) =>
|
|
195
|
-
_.isObject(row) ? (
|
|
196
|
-
_.path("data_structure_id")(row) ? (
|
|
197
|
-
<Link
|
|
198
|
-
key={i}
|
|
199
|
-
to={linkTo.STRUCTURE({
|
|
200
|
-
id: _.path("data_structure_id")(row),
|
|
201
|
-
})}
|
|
202
|
-
>
|
|
203
|
-
<span className="highlighted">
|
|
204
|
-
{qualifySqlIdentifier({
|
|
205
|
-
aliasArray: alias,
|
|
206
|
-
value: row,
|
|
207
|
-
})}
|
|
208
|
-
</span>
|
|
209
|
-
</Link>
|
|
210
|
-
) : (
|
|
211
|
-
<span key={i}>{_.path("name")(row)}</span>
|
|
212
|
-
)
|
|
213
|
-
) : null
|
|
214
|
-
)
|
|
215
|
-
: `${paramValue}`}
|
|
216
|
-
</div>
|
|
217
|
-
))
|
|
218
|
-
)(row)}
|
|
219
|
-
</>
|
|
220
|
-
)}
|
|
221
|
-
</>
|
|
222
|
-
)}
|
|
223
|
-
</Table.Cell>
|
|
224
|
-
<Table.Cell width={5}>
|
|
225
|
-
{operator && <OperatorMessage operator={operator} />}
|
|
226
|
-
</Table.Cell>
|
|
227
|
-
<Table.Cell width={5}>
|
|
228
|
-
{_.map.convert({ cap: false })((value, i) => (
|
|
229
|
-
<Fragment key={i}>
|
|
230
|
-
<FormattedLink
|
|
231
|
-
value={value}
|
|
232
|
-
operator={operator}
|
|
233
|
-
aliasArray={alias}
|
|
234
|
-
/>
|
|
235
|
-
{i + 1 < _.size(values) && (
|
|
236
|
-
<span>
|
|
237
|
-
{" "}
|
|
238
|
-
<FormattedMessage id="summary.link.and" />{" "}
|
|
239
|
-
</span>
|
|
240
|
-
)}
|
|
241
|
-
{value?.modifier && (
|
|
242
|
-
<>
|
|
243
|
-
<div className="smaller">
|
|
244
|
-
<FormattedMessage
|
|
245
|
-
id={`filtersGrid.field.modifier.${value.modifier.name}`}
|
|
246
|
-
defaultMessage={value.modifier.name}
|
|
247
|
-
/>
|
|
248
|
-
</div>
|
|
249
|
-
{_.flow(
|
|
250
|
-
_.prop("modifier.params"),
|
|
251
|
-
_.toPairs,
|
|
252
|
-
_.map(([paramName, paramValue]) => (
|
|
253
|
-
<div key={paramName} className="smaller">
|
|
254
|
-
{`${formatMessage({
|
|
255
|
-
id: `filtersGrid.field.modifier.${value.modifier.name}.${paramName}`,
|
|
256
|
-
defaultMessage: paramName,
|
|
257
|
-
})}: ${paramValue}`}
|
|
258
|
-
</div>
|
|
259
|
-
))
|
|
260
|
-
)(value)}
|
|
261
|
-
</>
|
|
262
|
-
)}
|
|
263
|
-
</Fragment>
|
|
264
|
-
))(values)}
|
|
265
|
-
</Table.Cell>
|
|
266
|
-
</Table.Row>
|
|
267
|
-
{row?.population
|
|
268
|
-
? row.population.map((validationPopulationCondition, i) => (
|
|
269
|
-
<ConditionCell
|
|
270
|
-
validationPopulationCondition
|
|
271
|
-
row={validationPopulationCondition}
|
|
272
|
-
key={i}
|
|
273
|
-
/>
|
|
274
|
-
))
|
|
275
|
-
: null}
|
|
276
|
-
</>
|
|
277
|
-
);
|
|
278
|
-
};
|
|
279
|
-
|
|
280
|
-
ConditionCell.propTypes = {
|
|
281
|
-
row: PropTypes.object,
|
|
282
|
-
alias: PropTypes.array,
|
|
283
|
-
validationPopulationCondition: PropTypes.bool,
|
|
284
|
-
};
|
|
14
|
+
const concatValues = (values, link) => _.join(link)(values);
|
|
285
15
|
|
|
286
16
|
export const ConditionSummary = ({ rows, type, icon, alias }) => {
|
|
287
17
|
const areMultidimensionalRows =
|
|
@@ -5,44 +5,11 @@ import { Header, Icon, Segment, Table } 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
|
+
import ConditionCell from "./ConditionCell";
|
|
8
9
|
|
|
9
10
|
export const empty = (rows) =>
|
|
10
11
|
rows && _.every((r) => _.isEmpty(r) || _.isNil(r))(rows);
|
|
11
12
|
|
|
12
|
-
const ConditionCell = ({ row, alias }) => {
|
|
13
|
-
const alias_text = _.flow(
|
|
14
|
-
_.find({ index: row.structure?.parent_index }),
|
|
15
|
-
_.propOr(null, "text")
|
|
16
|
-
)(alias);
|
|
17
|
-
|
|
18
|
-
return (
|
|
19
|
-
<Table.Row>
|
|
20
|
-
<Table.Cell width={5}>
|
|
21
|
-
{_.has("structure")(row) &&
|
|
22
|
-
(_.prop("structure.id")(row) ? (
|
|
23
|
-
<Link
|
|
24
|
-
to={linkTo.STRUCTURE({
|
|
25
|
-
id: _.path("structure.id")(row),
|
|
26
|
-
})}
|
|
27
|
-
>
|
|
28
|
-
<span className="highlighted">
|
|
29
|
-
{alias_text && `(${alias_text}).`}{" "}
|
|
30
|
-
{`"${_.pathOr("", "structure.name")(row)}"`}
|
|
31
|
-
</span>
|
|
32
|
-
</Link>
|
|
33
|
-
) : (
|
|
34
|
-
<span>{_.prop("structure.name")(row)}</span>
|
|
35
|
-
))}
|
|
36
|
-
</Table.Cell>
|
|
37
|
-
</Table.Row>
|
|
38
|
-
);
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
ConditionCell.propTypes = {
|
|
42
|
-
row: PropTypes.object,
|
|
43
|
-
alias: PropTypes.array,
|
|
44
|
-
};
|
|
45
|
-
|
|
46
13
|
export const FieldSummary = ({ rows, type, icon, alias }) => {
|
|
47
14
|
const wrappedRows = [rows];
|
|
48
15
|
return empty(rows) ? null : (
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { shallow } from "enzyme";
|
|
3
3
|
import { render } from "@truedat/test/render";
|
|
4
|
-
import { getValues } from "../
|
|
4
|
+
import { getValues } from "../ConditionCell";
|
|
5
5
|
import { ImplementationSummary } from "../ImplementationSummary";
|
|
6
6
|
|
|
7
7
|
const renderOpts = {
|
|
@@ -263,11 +263,12 @@ exports[`<ImplementationSummary /> displays correctly validations values of list
|
|
|
263
263
|
<a
|
|
264
264
|
href="/structures/2598"
|
|
265
265
|
>
|
|
266
|
-
<
|
|
266
|
+
<div
|
|
267
267
|
class="highlighted"
|
|
268
268
|
>
|
|
269
269
|
Mes
|
|
270
|
-
</
|
|
270
|
+
</div>
|
|
271
|
+
|
|
271
272
|
</a>
|
|
272
273
|
</td>
|
|
273
274
|
<td
|
|
@@ -626,11 +626,12 @@ exports[`<NewRuleImplementation /> calculate aliases when not informed 1`] = `
|
|
|
626
626
|
<a
|
|
627
627
|
href="/structures/4817544"
|
|
628
628
|
>
|
|
629
|
-
<
|
|
629
|
+
<div
|
|
630
630
|
class="highlighted"
|
|
631
631
|
>
|
|
632
632
|
(table2).descripcion
|
|
633
|
-
</
|
|
633
|
+
</div>
|
|
634
|
+
|
|
634
635
|
</a>
|
|
635
636
|
</td>
|
|
636
637
|
<td
|
|
@@ -714,11 +715,12 @@ exports[`<NewRuleImplementation /> calculate aliases when not informed 1`] = `
|
|
|
714
715
|
<a
|
|
715
716
|
href="/structures/4814766"
|
|
716
717
|
>
|
|
717
|
-
<
|
|
718
|
+
<div
|
|
718
719
|
class="highlighted"
|
|
719
720
|
>
|
|
720
721
|
(FS).agent
|
|
721
|
-
</
|
|
722
|
+
</div>
|
|
723
|
+
|
|
722
724
|
</a>
|
|
723
725
|
</td>
|
|
724
726
|
<td
|
|
@@ -787,15 +789,20 @@ exports[`<NewRuleImplementation /> calculate aliases when not informed 1`] = `
|
|
|
787
789
|
<a
|
|
788
790
|
href="/structures/4814766"
|
|
789
791
|
>
|
|
790
|
-
<
|
|
792
|
+
<div
|
|
791
793
|
class="highlighted"
|
|
792
794
|
>
|
|
793
|
-
(FS).
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
</span>
|
|
795
|
+
(FS).agent
|
|
796
|
+
</div>
|
|
797
|
+
|
|
797
798
|
</a>
|
|
798
799
|
</td>
|
|
800
|
+
<td
|
|
801
|
+
class="five wide"
|
|
802
|
+
/>
|
|
803
|
+
<td
|
|
804
|
+
class="five wide"
|
|
805
|
+
/>
|
|
799
806
|
</tr>
|
|
800
807
|
</tbody>
|
|
801
808
|
</table>
|
package/src/components/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import ConceptRules from "./ConceptRules";
|
|
2
|
+
import ConditionCell from "./ConditionCell";
|
|
2
3
|
import EditRule from "./EditRule";
|
|
3
4
|
import RuleResultDetails from "./RuleResultDetails";
|
|
4
5
|
import ExecutionGroup from "./ExecutionGroup";
|
|
@@ -21,6 +22,7 @@ import RulesLoader from "./RulesLoader";
|
|
|
21
22
|
|
|
22
23
|
export {
|
|
23
24
|
ConceptRules,
|
|
25
|
+
ConditionCell,
|
|
24
26
|
EditRule,
|
|
25
27
|
RuleResultDetails,
|
|
26
28
|
ExecutionGroup,
|
|
@@ -15,7 +15,9 @@ export const FieldsGrid = ({ rows, setRowValue, structures }) => {
|
|
|
15
15
|
|
|
16
16
|
const onStructureChange = (index, value) => {
|
|
17
17
|
const structure = {
|
|
18
|
-
..._.pick(["field_type", "name", "parent_index", "type"])(
|
|
18
|
+
..._.pick(["field_type", "name", "parent_index", "type", "metadata"])(
|
|
19
|
+
value
|
|
20
|
+
),
|
|
19
21
|
id: value.data_structure_id,
|
|
20
22
|
};
|
|
21
23
|
setRowValue({
|
package/src/messages/en.js
CHANGED
|
@@ -572,10 +572,10 @@ export default {
|
|
|
572
572
|
"The implementation has not changed",
|
|
573
573
|
"ruleImplementations.upload.failed.header":
|
|
574
574
|
"Error uploading file. No rules have been created.",
|
|
575
|
-
"ruleImplementations.upload.failed.
|
|
576
|
-
"
|
|
575
|
+
"ruleImplementations.upload.failed.missing_required_columns":
|
|
576
|
+
"Missing required columns. Expected [{expected}]. Found [{found}].",
|
|
577
577
|
"ruleImplementations.upload.success.errors":
|
|
578
|
-
"Error in {implementation_key} attribute: {key} message: {message}
|
|
578
|
+
"Error in {implementation_key} attribute: {key} message: {message}",
|
|
579
579
|
"ruleImplementations.upload.success.header":
|
|
580
580
|
"Upload success! Loaded {count_ids} omitted {count_errors}",
|
|
581
581
|
"ruleResult": "Rule execution result",
|
|
@@ -614,10 +614,10 @@ export default {
|
|
|
614
614
|
"rules.searching": "Searching...",
|
|
615
615
|
"rules.upload.failed.header":
|
|
616
616
|
"Error uploading file. No rules have been created.",
|
|
617
|
-
"rules.upload.failed.
|
|
617
|
+
"rules.upload.failed.missing_required_columns":
|
|
618
618
|
"Missing required columns. Expected [{expected}]. Found [{found}].",
|
|
619
619
|
"rules.upload.success.errors":
|
|
620
|
-
"Error in {rule_name} attribute: {key} message: {message}
|
|
620
|
+
"Error in {rule_name} attribute: {key} message: {message}",
|
|
621
621
|
"rules.upload.success.header":
|
|
622
622
|
"Upload successful! Loaded {count_ids} omitted {count_errors}",
|
|
623
623
|
"segmentsForm.add.text": "Add Segment",
|
package/src/messages/es.js
CHANGED
|
@@ -593,10 +593,10 @@ export default {
|
|
|
593
593
|
"La implementación no ha cambiado",
|
|
594
594
|
"ruleImplementations.upload.failed.header":
|
|
595
595
|
"Error al subir el fichero. No se ha realizado ninguna inserción.",
|
|
596
|
-
"ruleImplementations.upload.failed.
|
|
596
|
+
"ruleImplementations.upload.failed.missing_required_columns":
|
|
597
597
|
"Faltan columnas obligatorias en el fichero. Esperado [{expected}]. Recibido [{found}].",
|
|
598
598
|
"ruleImplementations.upload.success.errors":
|
|
599
|
-
"Error en {
|
|
599
|
+
"Error en {implementation_key} atributo: {key} mensaje: {message}",
|
|
600
600
|
"ruleImplementations.upload.success.header":
|
|
601
601
|
"¡Fichero subido correctamente! subidos {count_ids} errores {count_errors}",
|
|
602
602
|
"ruleResult": "Resultado de ejecución de regla",
|
|
@@ -636,10 +636,10 @@ export default {
|
|
|
636
636
|
"rules.searching": "Buscando...",
|
|
637
637
|
"rules.upload.failed.header":
|
|
638
638
|
"Error al subir el fichero. No se ha realizado ninguna inserción.",
|
|
639
|
-
"rules.upload.failed.
|
|
639
|
+
"rules.upload.failed.missing_required_columns":
|
|
640
640
|
"Faltan columnas obligatorias en el fichero. Esperado [{expected}]. Recibido [{found}].",
|
|
641
641
|
"rules.upload.success.errors":
|
|
642
|
-
"Error en {rule_name} atributo: {key} mensaje: {message}
|
|
642
|
+
"Error en {rule_name} atributo: {key} mensaje: {message}",
|
|
643
643
|
"rules.upload.success.header":
|
|
644
644
|
"¡Fichero subido correctamente! subidos {count_ids} errores {count_errors}",
|
|
645
645
|
"segmentsForm.add.text": "Añadir segmentación",
|
|
@@ -61,12 +61,12 @@ const dqMessage = (state = initialState, { type, payload }) => {
|
|
|
61
61
|
const messagesImp = _.has("errors")(payload.data)
|
|
62
62
|
? _.flow(
|
|
63
63
|
_.propOr([], "errors"),
|
|
64
|
-
_.map((
|
|
64
|
+
_.map(({ implementation_key, message }) => ({
|
|
65
65
|
id: "ruleImplementations.upload.success.errors",
|
|
66
66
|
fields: {
|
|
67
|
-
|
|
68
|
-
key: Object.keys(
|
|
69
|
-
message:
|
|
67
|
+
implementation_key,
|
|
68
|
+
key: Object.keys(message)[0],
|
|
69
|
+
message: message[Object.keys(message)[0]][0],
|
|
70
70
|
},
|
|
71
71
|
defaultMessage:
|
|
72
72
|
"ruleImplementations.upload.success.errors.default",
|