@truedat/dq 4.42.5 → 4.43.1
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/api.js +8 -0
- package/src/components/ConditionSummary.js +1 -0
- package/src/components/FieldSummary.js +86 -0
- package/src/components/ImplementationStructureDelete.js +41 -0
- package/src/components/ImplementationStructureLink.js +24 -0
- package/src/components/ImplementationStructures.js +138 -0
- package/src/components/ImplementationStructuresNew.js +125 -0
- package/src/components/ImplementationSummary.js +11 -1
- package/src/components/NewRemediation.js +27 -20
- package/src/components/NewRuleImplementation.js +42 -6
- package/src/components/RemediationPlan.js +47 -78
- package/src/components/RuleImplementationProperties.js +2 -1
- package/src/components/RuleImplementationResultTabs.js +113 -0
- package/src/components/RuleImplementationResults.js +1 -1
- package/src/components/RuleImplementationTabs.js +16 -1
- package/src/components/RuleImplementationsTable.js +10 -3
- package/src/components/RuleResult.js +108 -0
- package/src/components/{ExecutionDetails.js → RuleResultDetails.js} +4 -21
- package/src/components/RuleResultRemediationLoader.js +44 -0
- package/src/components/RuleResultRemediations.js +47 -0
- package/src/components/RuleResultRow.js +0 -3
- package/src/components/RuleResultSegmentRow.js +83 -0
- package/src/components/RuleResultSegments.js +102 -0
- package/src/components/RuleResultSegmentsLoader.js +34 -0
- package/src/components/RuleResultsRoutes.js +73 -0
- package/src/components/RuleRoutes.js +38 -12
- package/src/components/__test_samples__/NewRuleImplementationProps.js +22 -2
- package/src/components/__tests__/ExecutionDetails.spec.js +5 -5
- package/src/components/__tests__/ImplementationStructureDelete.spec.js +27 -0
- package/src/components/__tests__/ImplementationStructureLink.spec.js +23 -0
- package/src/components/__tests__/ImplementationStructures.spec.js +88 -0
- package/src/components/__tests__/ImplementationStructuresNew.spec.js +34 -0
- package/src/components/__tests__/NewRuleImplementation.spec.js +27 -7
- package/src/components/__tests__/RuleImplementation.spec.js +2 -1
- package/src/components/__tests__/RuleImplementationTabs.spec.js +2 -1
- package/src/components/__tests__/RuleResultSegmentsLoader.spec.js +32 -0
- package/src/components/__tests__/__snapshots__/ExecutionDetails.spec.js.snap +2 -30
- package/src/components/__tests__/__snapshots__/ImplementationStructureDelete.spec.js.snap +10 -0
- package/src/components/__tests__/__snapshots__/ImplementationStructureLink.spec.js.snap +11 -0
- package/src/components/__tests__/__snapshots__/ImplementationStructures.spec.js.snap +208 -0
- package/src/components/__tests__/__snapshots__/ImplementationStructuresNew.spec.js.snap +106 -0
- package/src/components/__tests__/__snapshots__/NewRuleImplementation.spec.js.snap +1211 -1217
- package/src/components/__tests__/__snapshots__/RuleImplementation.spec.js.snap +7 -1
- package/src/components/__tests__/__snapshots__/RuleImplementationProperties.spec.js.snap +1 -0
- package/src/components/__tests__/__snapshots__/RuleImplementationTabs.spec.js.snap +8 -2
- package/src/components/index.js +2 -2
- package/src/components/ruleImplementationForm/FieldsGrid.js +57 -0
- package/src/components/ruleImplementationForm/FieldsGroup.js +107 -0
- package/src/components/ruleImplementationForm/RuleImplementationForm.js +45 -0
- package/src/components/ruleImplementationForm/SegmentsForm.js +35 -0
- package/src/components/ruleImplementationForm/__tests__/RuleImplementationForm.spec.js +27 -10
- package/src/components/ruleImplementationForm/__tests__/__snapshots__/RuleImplementationForm.spec.js.snap +315 -91
- package/src/messages/en.js +20 -1
- package/src/messages/es.js +21 -1
- package/src/reducers/__tests__/segmentResult.spec.js +46 -0
- package/src/reducers/index.js +2 -0
- package/src/reducers/ruleImplementation.js +2 -0
- package/src/reducers/ruleImplementationRedirect.js +4 -0
- package/src/reducers/segmentResults.js +19 -0
- package/src/routines.js +10 -0
- package/src/sagas/__tests__/createImplementationStructure.spec.js +86 -0
- package/src/sagas/__tests__/deleteImplementationStructure.spec.js +84 -0
- package/src/sagas/__tests__/fetchSegmentResults.spec.js +78 -0
- package/src/sagas/createImplementationStructure.js +32 -0
- package/src/sagas/deleteImplementationStructure.js +37 -0
- package/src/sagas/fetchSegmentResults.js +30 -0
- package/src/sagas/index.js +19 -10
- package/src/services/encodeRawContent.js +5 -5
- package/src/styles/remediationPlan.less +5 -0
- package/src/styles/ruleImplementationForm/DatasetForm.less +5 -0
|
@@ -224,8 +224,8 @@ const updateStructureParentIndex = (structures) => (structure) => {
|
|
|
224
224
|
return structure;
|
|
225
225
|
};
|
|
226
226
|
|
|
227
|
-
const withConditionDefaultAlias = (conditions, structures) =>
|
|
228
|
-
_.map((p) => {
|
|
227
|
+
const withConditionDefaultAlias = (conditions, structures) => {
|
|
228
|
+
return _.map((p) => {
|
|
229
229
|
return {
|
|
230
230
|
...p,
|
|
231
231
|
structure: updateStructureParentIndex(structures)(p.structure),
|
|
@@ -235,6 +235,7 @@ const withConditionDefaultAlias = (conditions, structures) =>
|
|
|
235
235
|
: p.value,
|
|
236
236
|
};
|
|
237
237
|
})(conditions);
|
|
238
|
+
};
|
|
238
239
|
|
|
239
240
|
export const NewRuleImplementation = ({
|
|
240
241
|
canManageRaw,
|
|
@@ -296,6 +297,18 @@ export const NewRuleImplementation = ({
|
|
|
296
297
|
),
|
|
297
298
|
precalculatedDataset
|
|
298
299
|
),
|
|
300
|
+
segments: withConditionDefaultAlias(
|
|
301
|
+
addFieldType(
|
|
302
|
+
ruleImplementationProps,
|
|
303
|
+
structuresFields,
|
|
304
|
+
structuresSiblings,
|
|
305
|
+
"segments",
|
|
306
|
+
"segment",
|
|
307
|
+
{ name: "" }
|
|
308
|
+
),
|
|
309
|
+
precalculatedDataset
|
|
310
|
+
),
|
|
311
|
+
|
|
299
312
|
rawContent: {
|
|
300
313
|
..._.prop("raw_content")(ruleImplementationProps),
|
|
301
314
|
},
|
|
@@ -313,12 +326,14 @@ export const NewRuleImplementation = ({
|
|
|
313
326
|
population: [],
|
|
314
327
|
populations: [],
|
|
315
328
|
validations: [{}],
|
|
329
|
+
segments: [{}],
|
|
316
330
|
rawContent: {
|
|
317
331
|
database: "",
|
|
318
332
|
source_id: null,
|
|
319
333
|
dataset: "",
|
|
320
334
|
population: "",
|
|
321
335
|
validations: "",
|
|
336
|
+
segments: "",
|
|
322
337
|
},
|
|
323
338
|
dfName: "",
|
|
324
339
|
dfContent: {},
|
|
@@ -380,6 +395,12 @@ export const NewRuleImplementation = ({
|
|
|
380
395
|
_.filter((val) => valueInDataset(val))
|
|
381
396
|
)(ruleImplementation);
|
|
382
397
|
|
|
398
|
+
const segments_within_dataset = _.flow(
|
|
399
|
+
_.prop("segments"),
|
|
400
|
+
_.filter((val) => belongsToDataset(_.path("structure.id")(val))),
|
|
401
|
+
_.filter((val) => valueInDataset(val))
|
|
402
|
+
)(ruleImplementation);
|
|
403
|
+
|
|
383
404
|
const population_within_dataset = _.flow(
|
|
384
405
|
_.prop("population"),
|
|
385
406
|
_.filter((val) => belongsToDataset(_.path("structure.id")(val))),
|
|
@@ -395,16 +416,15 @@ export const NewRuleImplementation = ({
|
|
|
395
416
|
validations: _.isEmpty(validations_within_dataset)
|
|
396
417
|
? [{}]
|
|
397
418
|
: validations_within_dataset,
|
|
419
|
+
segments: _.isEmpty(segments_within_dataset)
|
|
420
|
+
? []
|
|
421
|
+
: segments_within_dataset,
|
|
398
422
|
});
|
|
399
423
|
};
|
|
400
424
|
|
|
401
425
|
const onChange = (prop, value) =>
|
|
402
426
|
setRuleImplementation({ ...ruleImplementation, [prop]: value });
|
|
403
427
|
|
|
404
|
-
const setPopulation = (population) => {
|
|
405
|
-
setRuleImplementation({ ...ruleImplementation, population });
|
|
406
|
-
};
|
|
407
|
-
|
|
408
428
|
const addPopulation = () => {
|
|
409
429
|
const populations = _.concat(
|
|
410
430
|
_.pathOr([], "populations")(ruleImplementation)
|
|
@@ -426,6 +446,18 @@ export const NewRuleImplementation = ({
|
|
|
426
446
|
setRuleImplementation({ ...ruleImplementation, validations });
|
|
427
447
|
};
|
|
428
448
|
|
|
449
|
+
const addSegments = () => {
|
|
450
|
+
const segments = _.concat(_.pathOr([], "segments")(ruleImplementation))([
|
|
451
|
+
{},
|
|
452
|
+
]);
|
|
453
|
+
setRuleImplementation({ ...ruleImplementation, segments });
|
|
454
|
+
};
|
|
455
|
+
|
|
456
|
+
const setSegments = (segments) => {
|
|
457
|
+
const newSegments = _.isEqual([{}])(segments) ? [] : segments;
|
|
458
|
+
setRuleImplementation({ ...ruleImplementation, segments: newSegments });
|
|
459
|
+
};
|
|
460
|
+
|
|
429
461
|
const setImplementationKey = (implementationKey) =>
|
|
430
462
|
setRuleImplementation({ ...ruleImplementation, implementationKey });
|
|
431
463
|
|
|
@@ -449,6 +481,7 @@ export const NewRuleImplementation = ({
|
|
|
449
481
|
const validations = _.filter(_.negate(_.isEmpty))(
|
|
450
482
|
ruleImplementation.validations
|
|
451
483
|
);
|
|
484
|
+
const segments = _.filter(_.negate(_.isEmpty))(ruleImplementation.segments);
|
|
452
485
|
|
|
453
486
|
const dfContent = _.flow(
|
|
454
487
|
_.prop("dfContent"),
|
|
@@ -481,6 +514,7 @@ export const NewRuleImplementation = ({
|
|
|
481
514
|
dataset: datasetAttributes(_.prop("dataset")(ruleImplementation)),
|
|
482
515
|
populations: populationsAttributes(populations),
|
|
483
516
|
validations: conditionAttributes(validations),
|
|
517
|
+
segments,
|
|
484
518
|
implementation_key: _.prop("implementationKey")(ruleImplementation),
|
|
485
519
|
implementation_type:
|
|
486
520
|
_.prop("implementationType")(ruleImplementation),
|
|
@@ -562,6 +596,8 @@ export const NewRuleImplementation = ({
|
|
|
562
596
|
addPopulation={addPopulation}
|
|
563
597
|
setPopulations={setPopulations}
|
|
564
598
|
setValidations={setValidations}
|
|
599
|
+
addSegments={addSegments}
|
|
600
|
+
setSegments={setSegments}
|
|
565
601
|
operators={operators}
|
|
566
602
|
setImplementationKey={setImplementationKey}
|
|
567
603
|
onChange={onChange}
|
|
@@ -4,17 +4,14 @@ import PropTypes from "prop-types";
|
|
|
4
4
|
import { connect } from "react-redux";
|
|
5
5
|
import { useIntl } from "react-intl";
|
|
6
6
|
import { useParams } from "react-router-dom";
|
|
7
|
-
import { Button,
|
|
7
|
+
import { Button, Grid, Container } from "semantic-ui-react";
|
|
8
8
|
import { FormattedMessage } from "react-intl";
|
|
9
9
|
import { Loading } from "@truedat/core/components";
|
|
10
10
|
import { ConfirmModal } from "@truedat/core/components";
|
|
11
|
-
import {
|
|
12
|
-
fetchRemediation,
|
|
13
|
-
clearRemediation,
|
|
14
|
-
deleteRemediation,
|
|
15
|
-
} from "../routines";
|
|
11
|
+
import { deleteRemediation } from "../routines";
|
|
16
12
|
import NewRemediation from "./NewRemediation";
|
|
17
13
|
import RemediationForm from "./RemediationForm";
|
|
14
|
+
|
|
18
15
|
import "../styles/remediationPlan.less";
|
|
19
16
|
|
|
20
17
|
const DynamicFormViewer = React.lazy(() =>
|
|
@@ -23,10 +20,7 @@ const DynamicFormViewer = React.lazy(() =>
|
|
|
23
20
|
|
|
24
21
|
export const RemediationPlan = ({
|
|
25
22
|
isLoading,
|
|
26
|
-
className,
|
|
27
23
|
deleteRemediation,
|
|
28
|
-
fetchRemediation,
|
|
29
|
-
clearRemediation,
|
|
30
24
|
remediation,
|
|
31
25
|
templates,
|
|
32
26
|
latestResultId,
|
|
@@ -44,17 +38,6 @@ export const RemediationPlan = ({
|
|
|
44
38
|
setRuleResultId(paramsRuleResultId || latestResultId);
|
|
45
39
|
}, [paramsRuleResultId, latestResultId]);
|
|
46
40
|
|
|
47
|
-
useEffect(() => {
|
|
48
|
-
ruleResultId && fetchRemediation({ rule_result_id: ruleResultId });
|
|
49
|
-
}, [fetchRemediation, ruleResultId]);
|
|
50
|
-
|
|
51
|
-
useEffect(
|
|
52
|
-
() => () => {
|
|
53
|
-
clearRemediation();
|
|
54
|
-
},
|
|
55
|
-
[clearRemediation]
|
|
56
|
-
);
|
|
57
|
-
|
|
58
41
|
const onSave = () => {
|
|
59
42
|
setIsEdit(false);
|
|
60
43
|
};
|
|
@@ -70,67 +53,58 @@ export const RemediationPlan = ({
|
|
|
70
53
|
<>
|
|
71
54
|
{!_.isEmpty(remediation) ? (
|
|
72
55
|
<>
|
|
73
|
-
|
|
74
|
-
<
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
56
|
+
{manageRemediations ? (
|
|
57
|
+
<div className="ui actions remediation">
|
|
58
|
+
<ConfirmModal
|
|
59
|
+
icon="trash"
|
|
60
|
+
trigger={<Button secondary icon="trash" basic color="red" />}
|
|
61
|
+
header={
|
|
62
|
+
<FormattedMessage id="remediation.actions.delete.confirmation.header" />
|
|
63
|
+
}
|
|
64
|
+
content={
|
|
65
|
+
<FormattedMessage
|
|
66
|
+
id="remediation.actions.delete.confirmation.content"
|
|
67
|
+
values={{ ruleResultId: <b>{ruleResultId}</b> }}
|
|
68
|
+
/>
|
|
69
|
+
}
|
|
70
|
+
onConfirm={() =>
|
|
71
|
+
deleteRemediation({
|
|
72
|
+
implementation_id: implementationId,
|
|
73
|
+
rule_result_id: ruleResultId,
|
|
74
|
+
})
|
|
75
|
+
}
|
|
76
|
+
/>
|
|
77
|
+
<Button
|
|
78
|
+
className="button-edit-remediation"
|
|
79
|
+
primary
|
|
80
|
+
onClick={() => setIsEdit(!isEdit)}
|
|
81
|
+
content={formatMessage({
|
|
82
|
+
id: !isEdit ? "actions.edit" : "actions.cancel",
|
|
83
|
+
})}
|
|
78
84
|
/>
|
|
79
|
-
</
|
|
80
|
-
|
|
85
|
+
</div>
|
|
86
|
+
) : null}
|
|
81
87
|
|
|
82
|
-
<
|
|
83
|
-
{
|
|
84
|
-
|
|
85
|
-
<
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
}
|
|
91
|
-
content={
|
|
92
|
-
<FormattedMessage
|
|
93
|
-
id="remediation.actions.delete.confirmation.content"
|
|
94
|
-
values={{ ruleResultId: <b>{ruleResultId}</b> }}
|
|
95
|
-
/>
|
|
96
|
-
}
|
|
97
|
-
onConfirm={() =>
|
|
98
|
-
deleteRemediation({
|
|
99
|
-
implementation_id: implementationId,
|
|
100
|
-
rule_result_id: ruleResultId,
|
|
101
|
-
})
|
|
102
|
-
}
|
|
103
|
-
/>
|
|
104
|
-
<Button
|
|
105
|
-
className="button-edit-remediation"
|
|
106
|
-
primary
|
|
107
|
-
onClick={() => setIsEdit(!isEdit)}
|
|
108
|
-
content={formatMessage({
|
|
109
|
-
id: !isEdit ? "actions.edit" : "actions.cancel",
|
|
110
|
-
})}
|
|
88
|
+
<Grid>
|
|
89
|
+
<Grid.Column width={8}>
|
|
90
|
+
{!isEdit && remediation?.df_name ? (
|
|
91
|
+
<DynamicFormViewer
|
|
92
|
+
template={_.find(_.propEq("name", remediation.df_name))(
|
|
93
|
+
templates
|
|
94
|
+
)}
|
|
95
|
+
content={remediation.df_content}
|
|
111
96
|
/>
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
<Grid>
|
|
116
|
-
<Grid.Column width={8}>
|
|
117
|
-
{!isEdit && remediation?.df_name ? (
|
|
118
|
-
<DynamicFormViewer
|
|
119
|
-
template={_.find(_.propEq("name", remediation.df_name))(
|
|
120
|
-
templates
|
|
121
|
-
)}
|
|
122
|
-
content={remediation.df_content}
|
|
123
|
-
/>
|
|
124
|
-
) : (
|
|
97
|
+
) : (
|
|
98
|
+
<Container className="new-remedation-container" fluid>
|
|
125
99
|
<RemediationForm
|
|
126
100
|
onSave={onSave}
|
|
127
101
|
remediation={remediation}
|
|
128
102
|
latestResultId={latestResultId}
|
|
129
103
|
/>
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
</Grid>
|
|
133
|
-
</
|
|
104
|
+
</Container>
|
|
105
|
+
)}
|
|
106
|
+
</Grid.Column>
|
|
107
|
+
</Grid>
|
|
134
108
|
</>
|
|
135
109
|
) : null}
|
|
136
110
|
</>
|
|
@@ -139,10 +113,7 @@ export const RemediationPlan = ({
|
|
|
139
113
|
|
|
140
114
|
RemediationPlan.propTypes = {
|
|
141
115
|
isLoading: PropTypes.bool,
|
|
142
|
-
className: PropTypes.string,
|
|
143
116
|
deleteRemediation: PropTypes.func,
|
|
144
|
-
clearRemediation: PropTypes.func,
|
|
145
|
-
fetchRemediation: PropTypes.func,
|
|
146
117
|
remediation: PropTypes.object,
|
|
147
118
|
templates: PropTypes.array,
|
|
148
119
|
latestResultId: PropTypes.number,
|
|
@@ -164,6 +135,4 @@ const mapStateToProps = ({
|
|
|
164
135
|
|
|
165
136
|
export default connect(mapStateToProps, {
|
|
166
137
|
deleteRemediation,
|
|
167
|
-
fetchRemediation,
|
|
168
|
-
clearRemediation,
|
|
169
138
|
})(RemediationPlan);
|
|
@@ -12,7 +12,7 @@ const DynamicFormViewer = React.lazy(() =>
|
|
|
12
12
|
import("@truedat/df/components/DynamicFormViewer")
|
|
13
13
|
);
|
|
14
14
|
|
|
15
|
-
const summarySteps = ["dataset", "populations", "validations"];
|
|
15
|
+
const summarySteps = ["dataset", "populations", "validations", "segments"];
|
|
16
16
|
|
|
17
17
|
export const RuleImplementationProperties = ({
|
|
18
18
|
ruleImplementation,
|
|
@@ -75,6 +75,7 @@ const mapStateToProps = ({
|
|
|
75
75
|
ruleImplementation: _.pick([
|
|
76
76
|
...summarySteps,
|
|
77
77
|
"populations",
|
|
78
|
+
"segments",
|
|
78
79
|
"executable",
|
|
79
80
|
"event_type",
|
|
80
81
|
"event_message",
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import _ from "lodash/fp";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import PropTypes from "prop-types";
|
|
4
|
+
import { Menu } from "semantic-ui-react";
|
|
5
|
+
import { Link, withRouter } from "react-router-dom";
|
|
6
|
+
import { compose } from "redux";
|
|
7
|
+
import { connect } from "react-redux";
|
|
8
|
+
import { FormattedMessage } from "react-intl";
|
|
9
|
+
import {
|
|
10
|
+
RULE_IMPLEMENTATION_RESULT_DETAILS,
|
|
11
|
+
RULE_IMPLEMENTATION_RESULT_SEGMENTS_RESULTS,
|
|
12
|
+
//TODO: change name route
|
|
13
|
+
RULE_IMPLEMENTATION_RESULT_DETAILS_REMEDIATION_PLAN,
|
|
14
|
+
linkTo,
|
|
15
|
+
} from "@truedat/core/routes";
|
|
16
|
+
|
|
17
|
+
import RuleResultRemediationLoader from "./RuleResultRemediationLoader";
|
|
18
|
+
const TemplatesLoader = React.lazy(() =>
|
|
19
|
+
import("@truedat/df/templates/components/TemplatesLoader")
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
export const RuleImplementationResultTabs = ({
|
|
23
|
+
rule,
|
|
24
|
+
ruleImplementation,
|
|
25
|
+
ruleResult,
|
|
26
|
+
match,
|
|
27
|
+
authCreateRemediation,
|
|
28
|
+
templates,
|
|
29
|
+
}) => {
|
|
30
|
+
const renderSegmentResult = () => {
|
|
31
|
+
return ruleResult.has_segments ? (
|
|
32
|
+
<Menu.Item
|
|
33
|
+
active={match.path === RULE_IMPLEMENTATION_RESULT_SEGMENTS_RESULTS}
|
|
34
|
+
as={Link}
|
|
35
|
+
to={linkTo.RULE_IMPLEMENTATION_RESULT_SEGMENTS_RESULTS({
|
|
36
|
+
id: rule.id,
|
|
37
|
+
implementation_id: ruleImplementation.id,
|
|
38
|
+
rule_result_id: ruleResult.id,
|
|
39
|
+
})}
|
|
40
|
+
>
|
|
41
|
+
<FormattedMessage id="tabs.dq.ruleImplementationResult.segmentResult" />
|
|
42
|
+
</Menu.Item>
|
|
43
|
+
) : null;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const renderRemediationPlan = () => {
|
|
47
|
+
const canCreateRemediation = authCreateRemediation && !_.isEmpty(templates);
|
|
48
|
+
const renderCondition = ruleResult.has_remediation || canCreateRemediation;
|
|
49
|
+
|
|
50
|
+
return renderCondition ? (
|
|
51
|
+
<Menu.Item
|
|
52
|
+
active={
|
|
53
|
+
match.path === RULE_IMPLEMENTATION_RESULT_DETAILS_REMEDIATION_PLAN
|
|
54
|
+
}
|
|
55
|
+
as={Link}
|
|
56
|
+
to={linkTo.RULE_IMPLEMENTATION_RESULT_DETAILS_REMEDIATION_PLAN({
|
|
57
|
+
id: rule.id,
|
|
58
|
+
implementation_id: ruleImplementation.id,
|
|
59
|
+
rule_result_id: ruleResult.id,
|
|
60
|
+
})}
|
|
61
|
+
>
|
|
62
|
+
<FormattedMessage id="tabs.dq.ruleImplementationResult.remediationPlan" />
|
|
63
|
+
</Menu.Item>
|
|
64
|
+
) : null;
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
return _.isEmpty(ruleImplementation) || _.isEmpty(rule) ? null : (
|
|
68
|
+
<>
|
|
69
|
+
<RuleResultRemediationLoader propRuleResultId={ruleResult.id} />
|
|
70
|
+
<TemplatesLoader scope="remediation" />
|
|
71
|
+
<Menu attached="top" pointing secondary tabular>
|
|
72
|
+
<Menu.Item
|
|
73
|
+
active={match.path === RULE_IMPLEMENTATION_RESULT_DETAILS}
|
|
74
|
+
as={Link}
|
|
75
|
+
to={linkTo.RULE_IMPLEMENTATION_RESULT_DETAILS({
|
|
76
|
+
id: rule.id,
|
|
77
|
+
implementation_id: ruleImplementation.id,
|
|
78
|
+
rule_result_id: ruleResult.id,
|
|
79
|
+
})}
|
|
80
|
+
>
|
|
81
|
+
<FormattedMessage id="tabs.dq.ruleImplementationResult.info" />
|
|
82
|
+
</Menu.Item>
|
|
83
|
+
{renderSegmentResult()}
|
|
84
|
+
{renderRemediationPlan()}
|
|
85
|
+
</Menu>
|
|
86
|
+
</>
|
|
87
|
+
);
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
RuleImplementationResultTabs.propTypes = {
|
|
91
|
+
rule: PropTypes.object,
|
|
92
|
+
ruleResult: PropTypes.object,
|
|
93
|
+
ruleImplementation: PropTypes.object,
|
|
94
|
+
match: PropTypes.object,
|
|
95
|
+
authCreateRemediation: PropTypes.bool,
|
|
96
|
+
templates: PropTypes.array,
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
const mapStateToProps = (
|
|
100
|
+
{ rule, ruleImplementation, remediationActions, templates },
|
|
101
|
+
ownProps
|
|
102
|
+
) => ({
|
|
103
|
+
rule,
|
|
104
|
+
ruleResult: ownProps.ruleResult,
|
|
105
|
+
ruleImplementation,
|
|
106
|
+
authCreateRemediation: _.has("create")(remediationActions),
|
|
107
|
+
templates,
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
export default compose(
|
|
111
|
+
withRouter,
|
|
112
|
+
connect(mapStateToProps)
|
|
113
|
+
)(RuleImplementationResultTabs);
|
|
@@ -10,6 +10,8 @@ import {
|
|
|
10
10
|
RULE_IMPLEMENTATION_EVENTS,
|
|
11
11
|
IMPLEMENTATION_CONCEPT_LINKS,
|
|
12
12
|
IMPLEMENTATION_CONCEPT_LINKS_NEW,
|
|
13
|
+
IMPLEMENTATION_STRUCTURES,
|
|
14
|
+
IMPLEMENTATION_STRUCTURES_NEW,
|
|
13
15
|
RULE_IMPLEMENTATION_MOVE,
|
|
14
16
|
RULE_IMPLEMENTATION_RESULTS_DETAILS,
|
|
15
17
|
RULE_IMPLEMENTATION_RESULTS,
|
|
@@ -57,9 +59,22 @@ export const RuleImplementationTabs = ({
|
|
|
57
59
|
implementation_id: ruleImplementation.id,
|
|
58
60
|
})}
|
|
59
61
|
>
|
|
60
|
-
<FormattedMessage id="tabs.dq.implementation.links" />
|
|
62
|
+
<FormattedMessage id="tabs.dq.implementation.links.concepts" />
|
|
61
63
|
</Menu.Item>
|
|
62
64
|
)}
|
|
65
|
+
<Menu.Item
|
|
66
|
+
active={
|
|
67
|
+
match.path === IMPLEMENTATION_STRUCTURES ||
|
|
68
|
+
match.path === IMPLEMENTATION_STRUCTURES_NEW
|
|
69
|
+
}
|
|
70
|
+
as={Link}
|
|
71
|
+
to={linkTo.IMPLEMENTATION_STRUCTURES({
|
|
72
|
+
id: rule.id,
|
|
73
|
+
implementation_id: ruleImplementation.id,
|
|
74
|
+
})}
|
|
75
|
+
>
|
|
76
|
+
<FormattedMessage id="tabs.dq.implementation.structures" />
|
|
77
|
+
</Menu.Item>
|
|
63
78
|
<Menu.Item
|
|
64
79
|
active={match.path === RULE_IMPLEMENTATION_RESULTS}
|
|
65
80
|
as={Link}
|
|
@@ -15,6 +15,7 @@ export const RuleImplementationsTable = ({
|
|
|
15
15
|
additionalColumns = [],
|
|
16
16
|
checkedAll,
|
|
17
17
|
checkRow,
|
|
18
|
+
structure,
|
|
18
19
|
executeImplementationsOn,
|
|
19
20
|
implementationsSort,
|
|
20
21
|
sortImplementations,
|
|
@@ -127,6 +128,7 @@ RuleImplementationsTable.propTypes = {
|
|
|
127
128
|
isRowChecked: PropTypes.bool,
|
|
128
129
|
ruleImplementationsLoading: PropTypes.bool,
|
|
129
130
|
sortImplementations: PropTypes.func,
|
|
131
|
+
structure: PropTypes.object,
|
|
130
132
|
ruleImplementations: PropTypes.array,
|
|
131
133
|
columns: PropTypes.array,
|
|
132
134
|
withoutColumns: PropTypes.array,
|
|
@@ -134,11 +136,16 @@ RuleImplementationsTable.propTypes = {
|
|
|
134
136
|
|
|
135
137
|
const mapStateToProps = (state, props) => ({
|
|
136
138
|
columns: getRuleImplementationColumns(state),
|
|
137
|
-
ruleImplementations:
|
|
139
|
+
ruleImplementations:
|
|
140
|
+
props.ruleImplementations ||
|
|
141
|
+
(state?.structure?.implementations &&
|
|
142
|
+
_.map(({ implementation, type }) => ({
|
|
143
|
+
...implementation,
|
|
144
|
+
implementation_structure_structure_type: type,
|
|
145
|
+
}))(state.structure.implementations)) ||
|
|
138
146
|
state.ruleImplementations,
|
|
139
|
-
"ruleImplementations"
|
|
140
|
-
)(props),
|
|
141
147
|
ruleImplementationsLoading: state.ruleImplementationsLoading,
|
|
148
|
+
structure: state.structure,
|
|
142
149
|
implementationsSort: _.path("ruleImplementationQuery.sort")(state),
|
|
143
150
|
});
|
|
144
151
|
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import _ from "lodash/fp";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import PropTypes from "prop-types";
|
|
4
|
+
import { useIntl } from "react-intl";
|
|
5
|
+
import { connect } from "react-redux";
|
|
6
|
+
import { useParams } from "react-router-dom";
|
|
7
|
+
import { Header, Table, Icon } from "semantic-ui-react";
|
|
8
|
+
import { DateTime } from "@truedat/core/components";
|
|
9
|
+
import { FormattedMessage } from "react-intl";
|
|
10
|
+
import { selectColor } from "../functions/selectors";
|
|
11
|
+
import RuleImplementationResultTabs from "./RuleImplementationResultTabs";
|
|
12
|
+
|
|
13
|
+
const GeneralInformation = ({ ruleImplementation, ruleResult }) => {
|
|
14
|
+
const { formatMessage, formatNumber: _formatNumber } = useIntl();
|
|
15
|
+
const formatNumber = (num) => (_.isNil(num) ? num : _formatNumber(num));
|
|
16
|
+
return (
|
|
17
|
+
<>
|
|
18
|
+
<Table.Row>
|
|
19
|
+
<Table.Cell>
|
|
20
|
+
{formatMessage({ id: "ruleResult.props.quality" })}
|
|
21
|
+
</Table.Cell>
|
|
22
|
+
<Table.Cell>
|
|
23
|
+
<Icon
|
|
24
|
+
name="circle"
|
|
25
|
+
color={selectColor({ ...ruleImplementation, ...ruleResult })}
|
|
26
|
+
/>
|
|
27
|
+
{`${parseFloat(ruleResult.result)} %`}
|
|
28
|
+
</Table.Cell>
|
|
29
|
+
</Table.Row>
|
|
30
|
+
|
|
31
|
+
<Table.Row>
|
|
32
|
+
<Table.Cell>
|
|
33
|
+
{formatMessage({ id: "ruleResult.props.date" })}
|
|
34
|
+
</Table.Cell>
|
|
35
|
+
<Table.Cell>
|
|
36
|
+
<DateTime value={ruleResult.date} />
|
|
37
|
+
</Table.Cell>
|
|
38
|
+
</Table.Row>
|
|
39
|
+
|
|
40
|
+
<Table.Row>
|
|
41
|
+
<Table.Cell>
|
|
42
|
+
{formatMessage({ id: "ruleResult.props.records" })}
|
|
43
|
+
</Table.Cell>
|
|
44
|
+
<Table.Cell>{formatNumber(ruleResult.records)}</Table.Cell>
|
|
45
|
+
</Table.Row>
|
|
46
|
+
|
|
47
|
+
<Table.Row>
|
|
48
|
+
<Table.Cell>
|
|
49
|
+
{formatMessage({ id: "ruleResult.props.errors" })}
|
|
50
|
+
</Table.Cell>
|
|
51
|
+
<Table.Cell>{formatNumber(ruleResult.errors)}</Table.Cell>
|
|
52
|
+
</Table.Row>
|
|
53
|
+
</>
|
|
54
|
+
);
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
GeneralInformation.propTypes = {
|
|
58
|
+
ruleImplementation: PropTypes.object,
|
|
59
|
+
ruleResult: PropTypes.object,
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
export const RuleResult = ({ ruleImplementation, ruleResultId, children }) => {
|
|
63
|
+
const { rule_result_id: paramsId } = useParams();
|
|
64
|
+
|
|
65
|
+
const resultId = _.defaultTo(_.toNumber(paramsId))(ruleResultId);
|
|
66
|
+
|
|
67
|
+
const ruleResult = _.find(_.propEq("id", resultId))(
|
|
68
|
+
ruleImplementation.results
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
const renderRuleResult = () => {
|
|
72
|
+
return (
|
|
73
|
+
<>
|
|
74
|
+
<Header as="h2">
|
|
75
|
+
<Icon circular name="chart pie" />
|
|
76
|
+
<Header.Content>
|
|
77
|
+
<FormattedMessage id="ruleResult" />
|
|
78
|
+
</Header.Content>
|
|
79
|
+
</Header>
|
|
80
|
+
<RuleImplementationResultTabs ruleResult={ruleResult} />
|
|
81
|
+
{children}
|
|
82
|
+
</>
|
|
83
|
+
);
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
return _.isEmpty(ruleResult) ? null : renderRuleResult();
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
RuleResult.propTypes = {
|
|
90
|
+
ruleImplementation: PropTypes.object,
|
|
91
|
+
ruleResultId: PropTypes.number,
|
|
92
|
+
children: PropTypes.oneOfType([
|
|
93
|
+
PropTypes.node,
|
|
94
|
+
PropTypes.arrayOf(PropTypes.node),
|
|
95
|
+
]),
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
const mapStateToProps = (
|
|
99
|
+
{ ruleImplementation, remediationLoading, templatesLoading },
|
|
100
|
+
ownProps
|
|
101
|
+
) => ({
|
|
102
|
+
ruleImplementation,
|
|
103
|
+
remediationLoading,
|
|
104
|
+
templatesLoading,
|
|
105
|
+
...ownProps,
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
export default connect(mapStateToProps)(RuleResult);
|
|
@@ -4,11 +4,9 @@ import PropTypes from "prop-types";
|
|
|
4
4
|
import { useIntl } from "react-intl";
|
|
5
5
|
import { connect } from "react-redux";
|
|
6
6
|
import { useParams } from "react-router-dom";
|
|
7
|
-
import {
|
|
7
|
+
import { Table, Icon } from "semantic-ui-react";
|
|
8
8
|
import { DateTime } from "@truedat/core/components";
|
|
9
|
-
import { FormattedMessage } from "react-intl";
|
|
10
9
|
import { selectColor } from "../functions/selectors";
|
|
11
|
-
import RemediationPlan from "./RemediationPlan";
|
|
12
10
|
import "../styles/executionDetails.less";
|
|
13
11
|
|
|
14
12
|
const GeneralInformation = ({ ruleImplementation, ruleResult }) => {
|
|
@@ -84,11 +82,7 @@ const DetailRow = ({ details }) => {
|
|
|
84
82
|
|
|
85
83
|
DetailRow.propTypes = { details: PropTypes.object };
|
|
86
84
|
|
|
87
|
-
const
|
|
88
|
-
import("@truedat/df/templates/components/TemplatesLoader")
|
|
89
|
-
);
|
|
90
|
-
|
|
91
|
-
export const ExecutionDetails = ({ ruleImplementation, ruleResultId }) => {
|
|
85
|
+
export const RuleResultDetails = ({ ruleImplementation, ruleResultId }) => {
|
|
92
86
|
const { formatMessage } = useIntl();
|
|
93
87
|
const { rule_result_id: paramsId } = useParams();
|
|
94
88
|
|
|
@@ -100,12 +94,6 @@ export const ExecutionDetails = ({ ruleImplementation, ruleResultId }) => {
|
|
|
100
94
|
|
|
101
95
|
return _.isEmpty(ruleResult) ? null : (
|
|
102
96
|
<>
|
|
103
|
-
<Header as="h2">
|
|
104
|
-
<Icon circular name="chart pie" />
|
|
105
|
-
<Header.Content>
|
|
106
|
-
<FormattedMessage id="ruleResult" />
|
|
107
|
-
</Header.Content>
|
|
108
|
-
</Header>
|
|
109
97
|
<Table className="implementation-results medium">
|
|
110
98
|
<Table.Header>
|
|
111
99
|
<Table.Row>
|
|
@@ -141,16 +129,11 @@ export const ExecutionDetails = ({ ruleImplementation, ruleResultId }) => {
|
|
|
141
129
|
</>
|
|
142
130
|
) : null}
|
|
143
131
|
</Table>
|
|
144
|
-
<TemplatesLoader scope="remediation" />
|
|
145
|
-
<RemediationPlan
|
|
146
|
-
className="execution-details-remediation"
|
|
147
|
-
latestResultId={resultId}
|
|
148
|
-
/>
|
|
149
132
|
</>
|
|
150
133
|
);
|
|
151
134
|
};
|
|
152
135
|
|
|
153
|
-
|
|
136
|
+
RuleResultDetails.propTypes = {
|
|
154
137
|
ruleImplementation: PropTypes.object,
|
|
155
138
|
ruleResultId: PropTypes.number,
|
|
156
139
|
};
|
|
@@ -159,4 +142,4 @@ const mapStateToProps = ({ ruleImplementation }) => ({
|
|
|
159
142
|
ruleImplementation,
|
|
160
143
|
});
|
|
161
144
|
|
|
162
|
-
export default connect(mapStateToProps)(
|
|
145
|
+
export default connect(mapStateToProps)(RuleResultDetails);
|