@truedat/dq 4.56.5 → 4.56.7
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 +22 -21
- 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__/__fixtures__/NewRuleImplementationProps.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/DatasetForm.js +9 -2
- package/src/components/ruleImplementationForm/FieldsGrid.js +3 -1
- package/src/components/ruleImplementationForm/FiltersFormGroup.js +1 -0
- package/src/messages/en.js +1 -0
- package/src/messages/es.js +1 -0
- package/src/reducers/ruleImplementations.js +2 -0
- package/src/selectors/getRuleImplementationColumns.js +10 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [4.56.7] 2022-11-28
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- # [TD-4179] inserted_at and updated_at columns on Implementations
|
|
8
|
+
|
|
9
|
+
## [4.56.6] 2022-11-28
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- [TD-5247] FieldSummary and reference dataset table name
|
|
14
|
+
|
|
3
15
|
## [4.56.5] 2022-11-28
|
|
4
16
|
|
|
5
17
|
### Changed
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@truedat/dq",
|
|
3
|
-
"version": "4.56.
|
|
3
|
+
"version": "4.56.7",
|
|
4
4
|
"description": "Truedat Web Data Quality Module",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"jsnext:main": "src/index.js",
|
|
@@ -22,26 +22,25 @@
|
|
|
22
22
|
"eslint:fix": "eslint --fix src/**"
|
|
23
23
|
},
|
|
24
24
|
"devDependencies": {
|
|
25
|
-
"@babel/cli": "^7.
|
|
26
|
-
"@babel/core": "^7.
|
|
27
|
-
"@babel/plugin-proposal-class-properties": "^7.
|
|
28
|
-
"@babel/plugin-proposal-object-rest-spread": "^7.
|
|
29
|
-
"@babel/plugin-proposal-optional-chaining": "^7.
|
|
25
|
+
"@babel/cli": "^7.19.3",
|
|
26
|
+
"@babel/core": "^7.20.5",
|
|
27
|
+
"@babel/plugin-proposal-class-properties": "^7.18.6",
|
|
28
|
+
"@babel/plugin-proposal-object-rest-spread": "^7.20.2",
|
|
29
|
+
"@babel/plugin-proposal-optional-chaining": "^7.18.9",
|
|
30
30
|
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
|
|
31
|
-
"@babel/plugin-transform-modules-commonjs": "^7.
|
|
32
|
-
"@babel/preset-env": "^7.
|
|
33
|
-
"@babel/preset-react": "^7.
|
|
34
|
-
"@testing-library/jest-dom": "^5.16.
|
|
31
|
+
"@babel/plugin-transform-modules-commonjs": "^7.19.6",
|
|
32
|
+
"@babel/preset-env": "^7.20.2",
|
|
33
|
+
"@babel/preset-react": "^7.18.6",
|
|
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": "4.56.
|
|
37
|
+
"@truedat/test": "4.56.7",
|
|
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",
|
|
41
41
|
"babel-plugin-react-intl": "^5.1.18",
|
|
42
42
|
"babel-plugin-transform-semantic-ui-react-imports": "^1.4.1",
|
|
43
43
|
"enzyme": "^3.11.0",
|
|
44
|
-
"enzyme-adapter-react-16": "^1.15.6",
|
|
45
44
|
"enzyme-to-json": "^3.6.2",
|
|
46
45
|
"identity-obj-proxy": "^3.0.0",
|
|
47
46
|
"jest": "^28.1.0",
|
|
@@ -50,7 +49,7 @@
|
|
|
50
49
|
"react-dom": "^16.14.0",
|
|
51
50
|
"redux-saga-test-plan": "^4.0.4",
|
|
52
51
|
"rimraf": "^3.0.2",
|
|
53
|
-
"semantic-ui-react": "^2.
|
|
52
|
+
"semantic-ui-react": "^2.1.4"
|
|
54
53
|
},
|
|
55
54
|
"jest": {
|
|
56
55
|
"maxWorkers": "50%",
|
|
@@ -92,10 +91,11 @@
|
|
|
92
91
|
]
|
|
93
92
|
},
|
|
94
93
|
"dependencies": {
|
|
95
|
-
"@apollo/client": "^3.7.
|
|
96
|
-
"@truedat/core": "4.56.
|
|
97
|
-
"@truedat/df": "4.56.
|
|
94
|
+
"@apollo/client": "^3.7.1",
|
|
95
|
+
"@truedat/core": "4.56.7",
|
|
96
|
+
"@truedat/df": "4.56.7",
|
|
98
97
|
"graphql": "^15.5.3",
|
|
98
|
+
"moment": "^2.29.4",
|
|
99
99
|
"path-to-regexp": "^1.7.0",
|
|
100
100
|
"prop-types": "^15.8.1",
|
|
101
101
|
"rc-slider": "^8.6.1",
|
|
@@ -104,15 +104,16 @@
|
|
|
104
104
|
"react-redux": "^7.2.4",
|
|
105
105
|
"react-router-dom": "^5.2.0",
|
|
106
106
|
"redux": "^4.1.1",
|
|
107
|
-
"redux-saga": "^1.1
|
|
107
|
+
"redux-saga": "^1.2.1",
|
|
108
108
|
"redux-saga-routines": "^3.2.3",
|
|
109
|
-
"reselect": "^4.
|
|
110
|
-
"semantic-ui-calendar-react": "^0.15.3"
|
|
109
|
+
"reselect": "^4.1.7",
|
|
110
|
+
"semantic-ui-calendar-react": "^0.15.3",
|
|
111
|
+
"semantic-ui-react": "^2.1.4"
|
|
111
112
|
},
|
|
112
113
|
"peerDependencies": {
|
|
113
114
|
"react": ">= 16.8.6 < 17",
|
|
114
115
|
"react-dom": ">= 16.8.6 < 17",
|
|
115
|
-
"semantic-ui-react": ">= 0.
|
|
116
|
+
"semantic-ui-react": ">= 2.0.3 < 2.2"
|
|
116
117
|
},
|
|
117
|
-
"gitHead": "
|
|
118
|
+
"gitHead": "e321b6e541c2205813236081e4c9c5eab34f0007"
|
|
118
119
|
}
|
|
@@ -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,
|
|
@@ -58,8 +58,15 @@ export const DatasetForm = ({
|
|
|
58
58
|
});
|
|
59
59
|
};
|
|
60
60
|
|
|
61
|
-
const getStructureAttrs = (
|
|
62
|
-
|
|
61
|
+
const getStructureAttrs = ({
|
|
62
|
+
id,
|
|
63
|
+
name,
|
|
64
|
+
original_name,
|
|
65
|
+
path,
|
|
66
|
+
system,
|
|
67
|
+
type,
|
|
68
|
+
headers,
|
|
69
|
+
}) => ({ id, name: original_name || name, path, system, type, headers });
|
|
63
70
|
|
|
64
71
|
const hasChangedStructure = (index, value) =>
|
|
65
72
|
_.path("structure.id")(value) !==
|
|
@@ -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
|
@@ -537,6 +537,7 @@ export default {
|
|
|
537
537
|
"Implementation template",
|
|
538
538
|
"ruleImplementations.props.implementation_type": "Type",
|
|
539
539
|
"ruleImplementations.props.inserted_at": "Inserted at",
|
|
540
|
+
"ruleImplementations.props.updated_at": "Updated at",
|
|
540
541
|
"ruleImplementations.props.last_change_at": "Last change at",
|
|
541
542
|
"ruleImplementations.props.last_execution_at": "Last Execution",
|
|
542
543
|
"ruleImplementations.props.minimum": "Threshold",
|
package/src/messages/es.js
CHANGED
|
@@ -553,6 +553,7 @@ export default {
|
|
|
553
553
|
"Plantilla de implementación",
|
|
554
554
|
"ruleImplementations.props.implementation_type": "Tipo",
|
|
555
555
|
"ruleImplementations.props.inserted_at": "Insertado",
|
|
556
|
+
"ruleImplementations.props.updated_at": "Actualizado",
|
|
556
557
|
"ruleImplementations.props.last_change_at": "Fecha de última modificación",
|
|
557
558
|
"ruleImplementations.props.last_execution_at": "Última ejecución",
|
|
558
559
|
"ruleImplementations.props.minimum": "Valor umbral",
|
|
@@ -91,6 +91,16 @@ export const defaultImplementationColumns = [
|
|
|
91
91
|
sort: { name: "execution_result_info.result" },
|
|
92
92
|
width: 2,
|
|
93
93
|
},
|
|
94
|
+
{
|
|
95
|
+
name: "inserted_at",
|
|
96
|
+
fieldSelector: ({ inserted_at }) => ({ value: inserted_at }),
|
|
97
|
+
fieldDecorator: DateTime,
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
name: "updated_at",
|
|
101
|
+
fieldSelector: ({ updated_at }) => ({ value: updated_at }),
|
|
102
|
+
fieldDecorator: DateTime,
|
|
103
|
+
},
|
|
94
104
|
];
|
|
95
105
|
|
|
96
106
|
const getColumns = (state) => state.ruleImplementationColumns;
|