@truedat/dq 4.44.4 → 4.44.5
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 +11 -0
- package/package.json +24 -17
- package/src/components/NewRuleImplementation.js +6 -29
- package/src/components/RemediationForm.js +20 -47
- package/src/components/RemediationPlan.js +1 -1
- package/src/components/RuleFilters.js +1 -5
- package/src/components/RuleForm.js +20 -59
- package/src/components/RuleImplementationFilters.js +1 -5
- package/src/components/__tests__/ExecutionForm.spec.js +14 -12
- package/src/components/__tests__/NewRuleImplementation.spec.js +27 -15
- package/src/components/__tests__/RemediationForm.spec.js +11 -46
- package/src/components/__tests__/RemediationPlan.spec.js +49 -73
- package/src/components/__tests__/RuleForm.spec.js +22 -52
- package/src/components/__tests__/RuleProperties.spec.js +39 -27
- package/src/components/__tests__/__snapshots__/ExecutionForm.spec.js.snap +75 -5
- package/src/components/__tests__/__snapshots__/NewRuleImplementation.spec.js.snap +202 -2
- package/src/components/__tests__/__snapshots__/RemediationForm.spec.js.snap +77 -3
- package/src/components/__tests__/__snapshots__/RemediationPlan.spec.js.snap +40 -1
- package/src/components/__tests__/__snapshots__/RuleForm.spec.js.snap +156 -6
- package/src/components/__tests__/__snapshots__/RuleImplementationsSearch.spec.js.snap +1 -1
- package/src/components/__tests__/__snapshots__/RuleProperties.spec.js.snap +68 -56
- package/src/components/__tests__/__snapshots__/RuleSearch.spec.js.snap +1 -1
- package/src/components/ruleImplementationForm/InformationForm.js +14 -33
- package/src/components/ruleImplementationForm/RuleImplementationForm.js +7 -11
- package/src/components/ruleImplementationForm/RuleImplementationRawForm.js +20 -39
- package/src/components/ruleImplementationForm/__tests__/RuleImplementationForm.spec.js +11 -7
- package/src/components/ruleImplementationForm/__tests__/RuleImplementationRawForm.spec.js +175 -156
- package/src/components/ruleImplementationForm/__tests__/__snapshots__/RuleImplementationForm.spec.js.snap +75 -0
- package/src/components/ruleImplementationForm/__tests__/__snapshots__/RuleImplementationRawForm.spec.js.snap +412 -165
|
@@ -1,62 +1,74 @@
|
|
|
1
1
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
2
|
|
|
3
3
|
exports[`<RuleProperties /> matches the latest snapshot 1`] = `
|
|
4
|
-
<
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
color="grey"
|
|
4
|
+
<div>
|
|
5
|
+
<div
|
|
6
|
+
class="ui big relaxed list"
|
|
7
|
+
role="list"
|
|
8
|
+
style=""
|
|
10
9
|
>
|
|
11
|
-
<
|
|
12
|
-
|
|
13
|
-
/>
|
|
14
|
-
</Label>
|
|
15
|
-
<ListItem>
|
|
16
|
-
<ListHeader
|
|
17
|
-
as="h3"
|
|
10
|
+
<div
|
|
11
|
+
class="ui olive label"
|
|
18
12
|
>
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
</
|
|
13
|
+
Active
|
|
14
|
+
</div>
|
|
15
|
+
<div
|
|
16
|
+
class="item"
|
|
17
|
+
role="listitem"
|
|
18
|
+
>
|
|
19
|
+
<h3
|
|
20
|
+
class="header"
|
|
21
|
+
>
|
|
22
|
+
Description
|
|
23
|
+
</h3>
|
|
24
|
+
<div>
|
|
25
|
+
<div
|
|
26
|
+
autocorrect="on"
|
|
27
|
+
data-gramm="false"
|
|
28
|
+
data-key="0"
|
|
29
|
+
data-slate-editor="true"
|
|
30
|
+
spellcheck="true"
|
|
31
|
+
style="outline: none; white-space: pre-wrap; word-wrap: break-word;"
|
|
32
|
+
>
|
|
33
|
+
<div
|
|
34
|
+
data-key="1"
|
|
35
|
+
data-slate-object="block"
|
|
36
|
+
style="position: relative;"
|
|
37
|
+
>
|
|
38
|
+
<span
|
|
39
|
+
data-key="2"
|
|
40
|
+
data-slate-object="text"
|
|
41
|
+
>
|
|
42
|
+
<span
|
|
43
|
+
data-offset-key="2:0"
|
|
44
|
+
data-slate-leaf="true"
|
|
45
|
+
>
|
|
46
|
+
<span
|
|
47
|
+
data-slate-string="true"
|
|
48
|
+
>
|
|
49
|
+
desc
|
|
50
|
+
</span>
|
|
51
|
+
</span>
|
|
52
|
+
</span>
|
|
53
|
+
</div>
|
|
54
|
+
</div>
|
|
55
|
+
</div>
|
|
56
|
+
</div>
|
|
57
|
+
<div
|
|
58
|
+
class="item"
|
|
59
|
+
role="listitem"
|
|
60
|
+
>
|
|
61
|
+
<div
|
|
62
|
+
class="header"
|
|
63
|
+
>
|
|
64
|
+
Domain
|
|
65
|
+
</div>
|
|
66
|
+
<div
|
|
67
|
+
class="content"
|
|
68
|
+
>
|
|
69
|
+
foo
|
|
70
|
+
</div>
|
|
71
|
+
</div>
|
|
72
|
+
</div>
|
|
73
|
+
</div>
|
|
62
74
|
`;
|
|
@@ -4,43 +4,30 @@ import { connect } from "react-redux";
|
|
|
4
4
|
import PropTypes from "prop-types";
|
|
5
5
|
import { useIntl, FormattedMessage } from "react-intl";
|
|
6
6
|
import { Form, Icon, Popup } from "semantic-ui-react";
|
|
7
|
-
import { TemplateSelector } from "@truedat/core/components";
|
|
8
7
|
import LimitsForm from "./LimitsForm";
|
|
9
8
|
|
|
10
9
|
const DomainDropdownSelector = React.lazy(() =>
|
|
11
10
|
import("@truedat/bg/taxonomy/components/DomainDropdownSelector")
|
|
12
11
|
);
|
|
13
12
|
|
|
14
|
-
const
|
|
15
|
-
import("@truedat/df/components/
|
|
13
|
+
const SelectableDynamicForm = React.lazy(() =>
|
|
14
|
+
import("@truedat/df/components/SelectableDynamicForm")
|
|
16
15
|
);
|
|
17
16
|
|
|
18
17
|
export const InformationForm = ({
|
|
19
18
|
setImplementationKey,
|
|
20
19
|
onChange,
|
|
21
20
|
ruleImplementation,
|
|
22
|
-
|
|
23
|
-
setTemplate,
|
|
21
|
+
setIsValid,
|
|
24
22
|
rule,
|
|
25
23
|
}) => {
|
|
26
24
|
const { formatMessage } = useIntl();
|
|
27
25
|
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
? _.find(_.propEq("name", name))(templates)
|
|
32
|
-
: _.size(templates) == 1
|
|
33
|
-
? templates[0]
|
|
34
|
-
: null;
|
|
35
|
-
setTemplate(template);
|
|
26
|
+
const handleContentChange = ({ content, valid }) => {
|
|
27
|
+
onChange("dfContent", content);
|
|
28
|
+
setIsValid(_.isEmpty(valid));
|
|
36
29
|
};
|
|
37
|
-
|
|
38
|
-
const handleTemplateSelected = (e, { template }) => {
|
|
39
|
-
setTemplate(template);
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
const handleContentChange = (content) => onChange("dfContent", content);
|
|
43
|
-
|
|
30
|
+
const domainId = ruleImplementation?.domain_id || rule?.domain_id;
|
|
44
31
|
return (
|
|
45
32
|
<>
|
|
46
33
|
<Form.Radio
|
|
@@ -86,20 +73,15 @@ export const InformationForm = ({
|
|
|
86
73
|
</Form.Field>
|
|
87
74
|
) : null}
|
|
88
75
|
<LimitsForm onChange={onChange} ruleImplementation={ruleImplementation} />
|
|
89
|
-
<
|
|
76
|
+
<SelectableDynamicForm
|
|
90
77
|
scope="ri"
|
|
91
|
-
|
|
92
|
-
onChange={handleTemplateSelected}
|
|
93
|
-
onLoad={handleTemplatesLoaded}
|
|
78
|
+
domainIds={_.isNil(domainId) ? null : [domainId]}
|
|
94
79
|
required
|
|
80
|
+
content={ruleImplementation?.dfContent}
|
|
81
|
+
name={ruleImplementation?.dfName}
|
|
82
|
+
onChange={handleContentChange}
|
|
83
|
+
onNameChange={(dfName) => onChange("dfName", dfName)}
|
|
95
84
|
/>
|
|
96
|
-
{template === null ? null : (
|
|
97
|
-
<DynamicForm
|
|
98
|
-
template={template}
|
|
99
|
-
content={ruleImplementation?.dfContent}
|
|
100
|
-
onChange={handleContentChange}
|
|
101
|
-
/>
|
|
102
|
-
)}
|
|
103
85
|
</>
|
|
104
86
|
);
|
|
105
87
|
};
|
|
@@ -109,8 +91,7 @@ InformationForm.propTypes = {
|
|
|
109
91
|
rule: PropTypes.object,
|
|
110
92
|
ruleImplementation: PropTypes.object,
|
|
111
93
|
setImplementationKey: PropTypes.func,
|
|
112
|
-
|
|
113
|
-
template: PropTypes.object,
|
|
94
|
+
setIsValid: PropTypes.func,
|
|
114
95
|
};
|
|
115
96
|
|
|
116
97
|
const mapStateToProps = ({ rule }) => ({ rule });
|
|
@@ -13,7 +13,6 @@ import {
|
|
|
13
13
|
Step,
|
|
14
14
|
Segment,
|
|
15
15
|
} from "semantic-ui-react";
|
|
16
|
-
import { validateContent } from "@truedat/df/utils";
|
|
17
16
|
import PopulationForm from "./PopulationForm";
|
|
18
17
|
import DatasetForm from "./DatasetForm";
|
|
19
18
|
import ValidationsForm from "./ValidationsForm";
|
|
@@ -52,9 +51,7 @@ export const RuleImplementationForm = ({
|
|
|
52
51
|
setPopulations,
|
|
53
52
|
setSegments,
|
|
54
53
|
setStructures,
|
|
55
|
-
setTemplate,
|
|
56
54
|
setValidations,
|
|
57
|
-
template,
|
|
58
55
|
}) => {
|
|
59
56
|
const { formatMessage } = useIntl();
|
|
60
57
|
const history = useHistory();
|
|
@@ -76,18 +73,20 @@ export const RuleImplementationForm = ({
|
|
|
76
73
|
|
|
77
74
|
const [activeStep, setActiveStep] = useState("information");
|
|
78
75
|
const [selector, setSelector] = useState();
|
|
76
|
+
const [isContentValid, setContentIsValid] = useState();
|
|
79
77
|
|
|
80
78
|
const {
|
|
81
79
|
dataset: structures,
|
|
82
80
|
populations,
|
|
83
81
|
validations,
|
|
84
|
-
|
|
82
|
+
dfName,
|
|
85
83
|
segments,
|
|
86
84
|
} = ruleImplementation || {};
|
|
87
85
|
|
|
88
86
|
const validInformation = () =>
|
|
89
|
-
|
|
90
|
-
_.
|
|
87
|
+
dfName &&
|
|
88
|
+
!_.isEmpty(dfName) &&
|
|
89
|
+
isContentValid &&
|
|
91
90
|
(!_.isEmpty(rule) || _.isNumber(_.prop("domain_id")(ruleImplementation))) &&
|
|
92
91
|
areLimitsValid(ruleImplementation);
|
|
93
92
|
|
|
@@ -242,8 +241,7 @@ export const RuleImplementationForm = ({
|
|
|
242
241
|
onChange,
|
|
243
242
|
ruleImplementation,
|
|
244
243
|
setImplementationKey,
|
|
245
|
-
|
|
246
|
-
template,
|
|
244
|
+
setIsValid: setContentIsValid,
|
|
247
245
|
}}
|
|
248
246
|
/>
|
|
249
247
|
)}
|
|
@@ -358,9 +356,7 @@ RuleImplementationForm.propTypes = {
|
|
|
358
356
|
setPopulations: PropTypes.func,
|
|
359
357
|
setSegments: PropTypes.func,
|
|
360
358
|
setStructures: PropTypes.func,
|
|
361
|
-
setTemplate: PropTypes.func,
|
|
362
359
|
setValidations: PropTypes.func,
|
|
363
|
-
template: PropTypes.object,
|
|
364
360
|
rule: PropTypes.object,
|
|
365
361
|
};
|
|
366
362
|
|
|
@@ -370,7 +366,7 @@ const mapStateToProps = ({
|
|
|
370
366
|
userRulePermissions,
|
|
371
367
|
implementationActions,
|
|
372
368
|
}) => ({
|
|
373
|
-
rule
|
|
369
|
+
rule,
|
|
374
370
|
isSubmitting: ruleImplementationCreating,
|
|
375
371
|
authManageSegments:
|
|
376
372
|
!!userRulePermissions?.manage_segments ||
|
|
@@ -1,18 +1,16 @@
|
|
|
1
1
|
import _ from "lodash/fp";
|
|
2
|
-
import React from "react";
|
|
2
|
+
import React, { useState } from "react";
|
|
3
3
|
import PropTypes from "prop-types";
|
|
4
4
|
import { connect } from "react-redux";
|
|
5
5
|
import { useHistory } from "react-router-dom";
|
|
6
6
|
import { FormattedMessage, useIntl } from "react-intl";
|
|
7
7
|
import { Button, Form, Icon, Popup } from "semantic-ui-react";
|
|
8
|
-
import { TemplateSelector } from "@truedat/core/components";
|
|
9
8
|
import { accentInsensitivePathOrder } from "@truedat/core/services/sort";
|
|
10
|
-
import { validateContent as validDfContent } from "@truedat/df/utils";
|
|
11
9
|
import LimitsForm from "./LimitsForm";
|
|
12
10
|
import { areLimitsValid } from "./limitsValidation";
|
|
13
11
|
|
|
14
|
-
const
|
|
15
|
-
import("@truedat/df/components/
|
|
12
|
+
const SelectableDynamicForm = React.lazy(() =>
|
|
13
|
+
import("@truedat/df/components/SelectableDynamicForm")
|
|
16
14
|
);
|
|
17
15
|
|
|
18
16
|
const DomainDropdownSelector = React.lazy(() =>
|
|
@@ -47,30 +45,18 @@ export const RuleImplementationRawForm = ({
|
|
|
47
45
|
ruleImplementation,
|
|
48
46
|
setImplementationKey,
|
|
49
47
|
setImplementationRawContent,
|
|
50
|
-
setTemplate,
|
|
51
48
|
sources,
|
|
52
49
|
sourcesLoading,
|
|
53
|
-
template = {},
|
|
54
50
|
}) => {
|
|
55
51
|
const { formatMessage } = useIntl();
|
|
56
52
|
const history = useHistory();
|
|
53
|
+
const [isContentValid, setIsContentValid] = useState();
|
|
57
54
|
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
? _.find(_.propEq("name", name))(templates)
|
|
62
|
-
: _.size(templates) == 1
|
|
63
|
-
? templates[0]
|
|
64
|
-
: null;
|
|
65
|
-
setTemplate(template);
|
|
55
|
+
const handleContentChange = ({ content, valid }) => {
|
|
56
|
+
onChange("dfContent", content);
|
|
57
|
+
setIsContentValid(_.isEmpty(valid));
|
|
66
58
|
};
|
|
67
59
|
|
|
68
|
-
const handleTemplateSelected = (e, { template }) => {
|
|
69
|
-
setTemplate(template);
|
|
70
|
-
};
|
|
71
|
-
|
|
72
|
-
const handleContentChange = (content) => onChange("dfContent", content);
|
|
73
|
-
|
|
74
60
|
const isNilOrEmpty = (propName) =>
|
|
75
61
|
_.isNil(_.prop(propName)(rawContent)) ||
|
|
76
62
|
_.prop(propName)(rawContent) === "";
|
|
@@ -119,9 +105,9 @@ export const RuleImplementationRawForm = ({
|
|
|
119
105
|
return text ? text.match(re) : [];
|
|
120
106
|
};
|
|
121
107
|
const validInformation = () =>
|
|
122
|
-
|
|
123
|
-
!_.isEmpty(
|
|
124
|
-
|
|
108
|
+
ruleImplementation?.dfName &&
|
|
109
|
+
!_.isEmpty(ruleImplementation?.dfName) &&
|
|
110
|
+
isContentValid &&
|
|
125
111
|
(!_.isEmpty(rule) || _.isNumber(_.prop("domain_id")(ruleImplementation))) &&
|
|
126
112
|
areLimitsValid(ruleImplementation);
|
|
127
113
|
|
|
@@ -157,6 +143,7 @@ export const RuleImplementationRawForm = ({
|
|
|
157
143
|
const doCancel = () => history.goBack();
|
|
158
144
|
const errors = getErrors();
|
|
159
145
|
|
|
146
|
+
const domainId = ruleImplementation?.domain_id || rule?.domain_id;
|
|
160
147
|
return (
|
|
161
148
|
<Form className="rule">
|
|
162
149
|
<Form.Radio
|
|
@@ -185,26 +172,21 @@ export const RuleImplementationRawForm = ({
|
|
|
185
172
|
{_.isEmpty(rule) && !ruleImplementation?.rule_id && (
|
|
186
173
|
<Form.Field>
|
|
187
174
|
<DomainDropdownSelector
|
|
188
|
-
value={
|
|
175
|
+
value={domainId}
|
|
189
176
|
onChange={(_e, { value }) => onChange("domain_id", value)}
|
|
190
177
|
/>
|
|
191
178
|
</Form.Field>
|
|
192
179
|
)}
|
|
193
180
|
<LimitsForm onChange={onChange} ruleImplementation={ruleImplementation} />
|
|
194
|
-
<
|
|
181
|
+
<SelectableDynamicForm
|
|
195
182
|
scope="ri"
|
|
196
|
-
|
|
197
|
-
onChange={handleTemplateSelected}
|
|
198
|
-
onLoad={handleTemplatesLoaded}
|
|
183
|
+
domainIds={_.isNil(domainId) ? null : [domainId]}
|
|
199
184
|
required
|
|
185
|
+
content={ruleImplementation?.dfContent}
|
|
186
|
+
name={ruleImplementation?.dfName}
|
|
187
|
+
onChange={handleContentChange}
|
|
188
|
+
onNameChange={(dfName) => onChange("dfName", dfName)}
|
|
200
189
|
/>
|
|
201
|
-
{template?.id ? (
|
|
202
|
-
<DynamicForm
|
|
203
|
-
template={template}
|
|
204
|
-
content={_.prop("dfContent")(ruleImplementation)}
|
|
205
|
-
onChange={handleContentChange}
|
|
206
|
-
/>
|
|
207
|
-
) : null}
|
|
208
190
|
<Form.Dropdown
|
|
209
191
|
label={
|
|
210
192
|
<label>
|
|
@@ -252,11 +234,12 @@ export const RuleImplementationRawForm = ({
|
|
|
252
234
|
}
|
|
253
235
|
}
|
|
254
236
|
label={
|
|
255
|
-
<label>
|
|
237
|
+
<label htmlFor="dataset">
|
|
256
238
|
<FormattedMessage id="ruleImplementationRawForm.props.dataset" />
|
|
257
239
|
<Help message="ruleImplementationRawForm.props.dataset.help"></Help>
|
|
258
240
|
</label>
|
|
259
241
|
}
|
|
242
|
+
id="dataset"
|
|
260
243
|
name="dataset"
|
|
261
244
|
onChange={(e, { value }) => onChangeImplementation("dataset", value)}
|
|
262
245
|
placeholder={formatMessage({
|
|
@@ -343,10 +326,8 @@ RuleImplementationRawForm.propTypes = {
|
|
|
343
326
|
ruleImplementation: PropTypes.object,
|
|
344
327
|
setImplementationKey: PropTypes.func,
|
|
345
328
|
setImplementationRawContent: PropTypes.func,
|
|
346
|
-
setTemplate: PropTypes.func,
|
|
347
329
|
sources: PropTypes.array,
|
|
348
330
|
sourcesLoading: PropTypes.bool,
|
|
349
|
-
template: PropTypes.object,
|
|
350
331
|
};
|
|
351
332
|
|
|
352
333
|
const mapStateToProps = ({ rule, ruleImplementationCreating }) => ({
|
|
@@ -1,19 +1,23 @@
|
|
|
1
|
-
import React
|
|
1
|
+
import React from "react";
|
|
2
2
|
import { waitFor } from "@testing-library/react";
|
|
3
3
|
import { render } from "@truedat/test/render";
|
|
4
|
+
import { multipleTemplatesMock } from "@truedat/test/mocks";
|
|
4
5
|
import RuleImplementationForm from "../RuleImplementationForm";
|
|
5
6
|
|
|
6
7
|
const renderOpts = {
|
|
8
|
+
mocks: [multipleTemplatesMock({ scope: "ri", domainIds: null })],
|
|
7
9
|
state: {
|
|
8
10
|
rule: {},
|
|
9
11
|
implementationActions: { manage_segments: {} },
|
|
10
12
|
ruleImplementationCreating: true,
|
|
11
13
|
},
|
|
14
|
+
fallback: "lazy",
|
|
12
15
|
};
|
|
13
16
|
|
|
14
17
|
describe("<RuleImplementationForm />", () => {
|
|
15
18
|
const props = {
|
|
16
19
|
onSubmit: jest.fn(),
|
|
20
|
+
onChange: jest.fn(),
|
|
17
21
|
ruleImplementation: {
|
|
18
22
|
implementationKey: "foo",
|
|
19
23
|
executable: true,
|
|
@@ -25,14 +29,14 @@ describe("<RuleImplementationForm />", () => {
|
|
|
25
29
|
|
|
26
30
|
it("matches the latest snapshot", async () => {
|
|
27
31
|
const { container, queryByText } = render(
|
|
28
|
-
<
|
|
29
|
-
<RuleImplementationForm {...props} />
|
|
30
|
-
</Suspense>,
|
|
32
|
+
<RuleImplementationForm {...props} />,
|
|
31
33
|
renderOpts
|
|
32
34
|
);
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
35
|
+
|
|
36
|
+
await waitFor(() =>
|
|
37
|
+
expect(queryByText(/loading/i)).not.toBeInTheDocument()
|
|
38
|
+
);
|
|
39
|
+
await waitFor(() => expect(queryByText(/lazy/i)).not.toBeInTheDocument());
|
|
36
40
|
expect(container).toMatchSnapshot();
|
|
37
41
|
});
|
|
38
42
|
});
|