@truedat/dq 4.33.10 → 4.35.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/package.json +5 -5
  3. package/src/api.js +7 -1
  4. package/src/components/ConditionSummary.js +23 -21
  5. package/src/components/ExecutionDetails.js +11 -14
  6. package/src/components/ExecutionGroup.js +24 -15
  7. package/src/components/ImplementationResultBar.js +80 -0
  8. package/src/components/ImplementationSummary.js +33 -72
  9. package/src/components/ImplementationsUploadButton.js +61 -0
  10. package/src/components/InformationSummary.js +68 -0
  11. package/src/components/NewRuleImplementation.js +12 -0
  12. package/src/components/RuleForm.js +0 -178
  13. package/src/components/RuleImplementation.js +10 -6
  14. package/src/components/RuleImplementationProperties.js +31 -64
  15. package/src/components/RuleImplementationResults.js +87 -53
  16. package/src/components/RuleImplementationsActions.js +3 -59
  17. package/src/components/RuleImplementationsDownload.js +86 -0
  18. package/src/components/RuleImplementationsOptions.js +28 -0
  19. package/src/components/RuleProperties.js +1 -10
  20. package/src/components/RuleResultDecorator.js +43 -26
  21. package/src/components/RuleResultRow.js +4 -1
  22. package/src/components/RuleResultsUpload.js +47 -0
  23. package/src/components/RuleRoutes.js +0 -13
  24. package/src/components/RuleSummary.js +15 -2
  25. package/src/components/RulesActions.js +17 -10
  26. package/src/components/RulesUploadButton.js +58 -0
  27. package/src/components/__tests__/ExecutionGroup.spec.js +11 -7
  28. package/src/components/__tests__/ImplementationResultBar.spec.js +98 -0
  29. package/src/components/__tests__/ImplementationSummary.spec.js +9 -26
  30. package/src/components/__tests__/InformationSummary.spec.js +35 -0
  31. package/src/components/__tests__/NewRuleImplementation.spec.js +1 -1
  32. package/src/components/__tests__/RuleForm.spec.js +0 -191
  33. package/src/components/__tests__/RuleImplementation.spec.js +1 -0
  34. package/src/components/__tests__/RuleImplementationProperties.spec.js +23 -33
  35. package/src/components/__tests__/RuleImplementationsActions.spec.js +0 -9
  36. package/src/components/__tests__/RuleImplementationsOptions.spec.js +18 -0
  37. package/src/components/__tests__/RuleProperties.spec.js +7 -9
  38. package/src/components/__tests__/RuleResultDecorator.spec.js +17 -11
  39. package/src/components/__tests__/RuleResultRow.spec.js +25 -46
  40. package/src/components/__tests__/RuleResultsUpload.spec.js +18 -0
  41. package/src/components/__tests__/RuleRow.spec.js +0 -4
  42. package/src/components/__tests__/RuleSummary.spec.js +6 -6
  43. package/src/components/__tests__/Rules.spec.js +15 -39
  44. package/src/components/__tests__/__snapshots__/ConditionSummary.spec.js.snap +55 -51
  45. package/src/components/__tests__/__snapshots__/ExecutionGroup.spec.js.snap +5 -4
  46. package/src/components/__tests__/__snapshots__/ImplementationResultBar.spec.js.snap +141 -0
  47. package/src/components/__tests__/__snapshots__/ImplementationSummary.spec.js.snap +194 -457
  48. package/src/components/__tests__/__snapshots__/InformationSummary.spec.js.snap +185 -0
  49. package/src/components/__tests__/__snapshots__/NewRuleImplementation.spec.js.snap +6 -0
  50. package/src/components/__tests__/__snapshots__/RuleForm.spec.js.snap +0 -148
  51. package/src/components/__tests__/__snapshots__/RuleImplementation.spec.js.snap +20 -0
  52. package/src/components/__tests__/__snapshots__/RuleImplementationProperties.spec.js.snap +43 -49
  53. package/src/components/__tests__/__snapshots__/RuleImplementationResults.spec.js.snap +63 -61
  54. package/src/components/__tests__/__snapshots__/RuleImplementationsActions.spec.js.snap +1 -7
  55. package/src/components/__tests__/__snapshots__/RuleImplementationsOptions.spec.js.snap +58 -0
  56. package/src/components/__tests__/__snapshots__/RuleProperties.spec.js.snap +0 -1
  57. package/src/components/__tests__/__snapshots__/RuleResultsUpload.spec.js.snap +18 -0
  58. package/src/components/__tests__/__snapshots__/RuleRow.spec.js.snap +0 -28
  59. package/src/components/__tests__/__snapshots__/Rules.spec.js.snap +0 -101
  60. package/src/components/ruleImplementationForm/FiltersGroup.js +1 -0
  61. package/src/components/ruleImplementationForm/InformationForm.js +5 -5
  62. package/src/components/ruleImplementationForm/LimitsForm.js +142 -0
  63. package/src/components/ruleImplementationForm/RuleImplementationForm.js +14 -4
  64. package/src/components/ruleImplementationForm/RuleImplementationRawForm.js +16 -6
  65. package/src/components/ruleImplementationForm/ValueConditions.js +11 -0
  66. package/src/components/ruleImplementationForm/__tests__/LimitsForm.spec.js +186 -0
  67. package/src/components/ruleImplementationForm/__tests__/RuleImplementationRawForm.spec.js +42 -35
  68. package/src/components/ruleImplementationForm/__tests__/__snapshots__/LimitsForm.spec.js.snap +1104 -0
  69. package/src/components/ruleImplementationForm/__tests__/__snapshots__/RuleImplementationForm.spec.js.snap +4 -1
  70. package/src/components/ruleImplementationForm/__tests__/__snapshots__/RuleImplementationRawForm.spec.js.snap +12 -1
  71. package/src/components/ruleImplementationForm/limitsValidation.js +72 -0
  72. package/src/messages/en.js +167 -76
  73. package/src/messages/es.js +292 -185
  74. package/src/reducers/__tests__/rule.spec.js +2 -4
  75. package/src/reducers/__tests__/ruleImplementation.spec.js +2 -0
  76. package/src/reducers/__tests__/ruleImplementations.spec.js +12 -8
  77. package/src/reducers/__tests__/uploadingResults.spec.js +28 -0
  78. package/src/reducers/dqMessage.js +121 -1
  79. package/src/reducers/index.js +6 -0
  80. package/src/reducers/rule.js +0 -3
  81. package/src/reducers/ruleImplementation.js +3 -0
  82. package/src/reducers/ruleImplementationRedirect.js +6 -1
  83. package/src/reducers/ruleImplementations.js +3 -0
  84. package/src/reducers/ruleRedirect.js +5 -0
  85. package/src/reducers/uploadImplementationsFile.js +28 -0
  86. package/src/reducers/uploadRulesFile.js +25 -0
  87. package/src/reducers/uploadingResults.js +16 -0
  88. package/src/routines.js +3 -0
  89. package/src/sagas/__tests__/uploadResults.spec.js +65 -0
  90. package/src/sagas/index.js +9 -0
  91. package/src/sagas/uploadImplementations.js +28 -0
  92. package/src/sagas/uploadResults.js +32 -0
  93. package/src/sagas/uploadRules.js +28 -0
  94. package/src/selectors/getRuleImplementationColumns.js +38 -3
  95. package/src/selectors/ruleColumnsSelector.js +0 -31
  96. package/src/styles/ruleSummary.less +17 -10
@@ -0,0 +1,68 @@
1
+ import React from "react";
2
+ import PropTypes from "prop-types";
3
+ import { FormattedMessage } from "react-intl";
4
+ import { Header, Icon, Segment, List } from "semantic-ui-react";
5
+
6
+ export default function InformationSummary({ ruleImplementation }) {
7
+ return (
8
+ <>
9
+ <Header as="h3">
10
+ <Icon name="info" size="small" />
11
+ <Header.Content>
12
+ <FormattedMessage id="ruleImplementationForm.step.information" />
13
+ </Header.Content>
14
+ </Header>
15
+ <Segment>
16
+ <List>
17
+ <List.Item>
18
+ <List.Header>
19
+ <FormattedMessage id="quality.thresholds" />
20
+ </List.Header>
21
+ <List.Content>
22
+ <List.Description>
23
+ <FormattedMessage
24
+ id={`ruleImplementations.props.result_type.${ruleImplementation.result_type}`}
25
+ />
26
+ </List.Description>
27
+ </List.Content>
28
+ </List.Item>
29
+ <List.Item>
30
+ <Icon name="circle" color="yellow" />
31
+ <List.Content>
32
+ <List.Header>
33
+ <FormattedMessage id="quality.threshold" />
34
+ </List.Header>
35
+ <List.Description>
36
+ {ruleImplementation.minimum &&
37
+ `${ruleImplementation.minimum} ${
38
+ ruleImplementation.result_type !== "errors_number"
39
+ ? "%"
40
+ : ""
41
+ }`}
42
+ </List.Description>
43
+ </List.Content>
44
+ </List.Item>
45
+ <List.Item>
46
+ <Icon name="circle" color="green" />
47
+ <List.Content>
48
+ <List.Header>
49
+ <FormattedMessage id="quality.goal" />
50
+ </List.Header>
51
+ <List.Description>
52
+ {ruleImplementation.goal &&
53
+ `${ruleImplementation.goal} ${
54
+ ruleImplementation.result_type !== "errors_number"
55
+ ? "%"
56
+ : ""
57
+ }`}
58
+ </List.Description>
59
+ </List.Content>
60
+ </List.Item>
61
+ </List>
62
+ </Segment>
63
+ </>
64
+ );
65
+ }
66
+ InformationSummary.propTypes = {
67
+ ruleImplementation: PropTypes.object.isRequired,
68
+ };
@@ -220,6 +220,9 @@ export const NewRuleImplementation = ({
220
220
  },
221
221
  dfName: _.prop("df_name")(ruleImplementationProps),
222
222
  dfContent: ruleImplementationProps.df_content,
223
+ result_type: ruleImplementationProps.result_type,
224
+ minimum: ruleImplementationProps.minimum,
225
+ goal: ruleImplementationProps.goal,
223
226
  }
224
227
  : {
225
228
  executable: true,
@@ -237,6 +240,9 @@ export const NewRuleImplementation = ({
237
240
  },
238
241
  dfName: "",
239
242
  dfContent: {},
243
+ result_type: "percentage",
244
+ minimum: null,
245
+ goal: null,
240
246
  }
241
247
  );
242
248
 
@@ -343,6 +349,9 @@ export const NewRuleImplementation = ({
343
349
  df_content: dfContent,
344
350
  rule_id: rule.id,
345
351
  raw_content: { ...raw_content, source },
352
+ result_type: ruleImplementation.result_type,
353
+ minimum: ruleImplementation.minimum,
354
+ goal: ruleImplementation.goal,
346
355
  }
347
356
  : {
348
357
  executable: ruleImplementation.executable,
@@ -355,6 +364,9 @@ export const NewRuleImplementation = ({
355
364
  df_name,
356
365
  df_content: dfContent,
357
366
  rule_id: rule.id,
367
+ result_type: ruleImplementation.result_type,
368
+ minimum: ruleImplementation.minimum,
369
+ goal: ruleImplementation.goal,
358
370
  };
359
371
 
360
372
  clone || !edition
@@ -85,12 +85,9 @@ export class RuleForm extends React.Component {
85
85
  domain_id: null,
86
86
  name: "",
87
87
  description: null,
88
- minimum: null,
89
- goal: null,
90
88
  type_params: {},
91
89
  df_name: "",
92
90
  df_content: {},
93
- result_type: "percentage",
94
91
  };
95
92
 
96
93
  componentDidMount() {
@@ -218,86 +215,6 @@ export class RuleForm extends React.Component {
218
215
  this.setState({ activeSelection: !activeSelection });
219
216
  };
220
217
 
221
- percentageResultValidationMessages = () => {
222
- const rule = this.state;
223
- const {
224
- intl: { formatMessage },
225
- } = this.props;
226
- const minimumMessages = [];
227
- const goalMessages = [];
228
- if (rule.goal > 100)
229
- goalMessages.push(formatMessage({ id: "rule.form.validation.max_goal" }));
230
-
231
- if (
232
- !_.isNil(rule.minimum) &&
233
- !_.isNil(rule.goal) &&
234
- rule.minimum > rule.goal
235
- ) {
236
- minimumMessages.push(
237
- formatMessage({ id: "rule.form.validation.minimum_greater" })
238
- );
239
- goalMessages.push(
240
- formatMessage({ id: "rule.form.validation.goal_less" })
241
- );
242
- }
243
- return { minimumMessages, goalMessages };
244
- };
245
-
246
- errorsNumberResultValidationMessages = () => {
247
- const rule = this.state;
248
- const {
249
- intl: { formatMessage },
250
- } = this.props;
251
- const minimumMessages = [];
252
- const goalMessages = [];
253
-
254
- if (
255
- !_.isNil(rule.minimum) &&
256
- !_.isNil(rule.goal) &&
257
- rule.minimum < rule.goal
258
- ) {
259
- minimumMessages.push(
260
- formatMessage({
261
- id: "rule.form.validation.minimum.greater_eq.goal",
262
- })
263
- );
264
- goalMessages.push(
265
- formatMessage({ id: "rule.form.validation.goal.less_eq.minimum" })
266
- );
267
- }
268
- return { minimumMessages, goalMessages };
269
- };
270
-
271
- deviationResultValidationMessages = () => {
272
- const rule = this.state;
273
- const {
274
- intl: { formatMessage },
275
- } = this.props;
276
- const minimumMessages = [];
277
- const goalMessages = [];
278
-
279
- if (rule.minimum > 100)
280
- minimumMessages.push(
281
- formatMessage({ id: "rule.form.validation.max_minimum" })
282
- );
283
-
284
- if (
285
- !_.isNil(rule.minimum) &&
286
- !_.isNil(rule.goal) &&
287
- rule.minimum < rule.goal
288
- ) {
289
- minimumMessages.push(
290
- formatMessage({
291
- id: "rule.form.validation.minimum.greater_eq.goal",
292
- })
293
- );
294
- goalMessages.push(
295
- formatMessage({ id: "rule.form.validation.goal.less_eq.minimum" })
296
- );
297
- }
298
- return { minimumMessages, goalMessages };
299
- };
300
-
301
218
  generateValidationMessages = () => {
302
219
  const rule = this.state;
303
220
  const {
@@ -311,30 +228,9 @@ export class RuleForm extends React.Component {
311
228
  : undefined;
312
229
  const domain = _.isNil(rule.domain_id) ? [requiredMessage] : undefined;
313
230
 
314
- const { minimumMessages, goalMessages } = (() => {
315
- switch (rule.result_type) {
316
- case "percentage":
317
- return this.percentageResultValidationMessages();
318
- case "errors_number":
319
- return this.errorsNumberResultValidationMessages();
320
- case "deviation":
321
- return this.deviationResultValidationMessages();
322
- }
323
- })();
324
-
325
- if (_.isNil(rule.minimum)) minimumMessages.push(requiredMessage);
326
- if (_.isNil(rule.goal)) goalMessages.push(requiredMessage);
327
-
328
- const minimum_validation = !_.isEmpty(minimumMessages)
329
- ? minimumMessages
330
- : undefined;
331
- const goal_validation = !_.isEmpty(goalMessages) ? goalMessages : undefined;
332
-
333
231
  return {
334
232
  domain,
335
233
  name: name_validation,
336
- minimum: minimum_validation,
337
- goal: goal_validation,
338
234
  };
339
235
  };
340
236
 
@@ -454,80 +350,6 @@ export class RuleForm extends React.Component {
454
350
  </Accordion>
455
351
  </Segment>
456
352
  )}
457
- <Segment>
458
- <FieldLabelWrapping
459
- label={formatMessage({ id: "rule.props.result_type" })}
460
- messages={_.prop("result_type")(messages)}
461
- required
462
- tooltip={formatMessage({ id: "rule.form.tooltip.result_type" })}
463
- >
464
- <Form.Group inline>
465
- <Form.Radio
466
- name={"result_type"}
467
- label={formatMessage({
468
- id: "rule.props.result_type.percentage",
469
- })}
470
- value={"percentage"}
471
- checked={rule.result_type == "percentage"}
472
- onChange={this.handleChange}
473
- />
474
- <Form.Radio
475
- name={"result_type"}
476
- label={formatMessage({
477
- id: "rule.props.result_type.deviation",
478
- })}
479
- value={"deviation"}
480
- checked={rule.result_type == "deviation"}
481
- onChange={this.handleChange}
482
- />
483
- <Form.Radio
484
- name={"result_type"}
485
- label={formatMessage({
486
- id: "rule.props.result_type.errors_number",
487
- })}
488
- value={"errors_number"}
489
- checked={rule.result_type == "errors_number"}
490
- onChange={this.handleChange}
491
- />
492
- </Form.Group>
493
- </FieldLabelWrapping>
494
- <FieldLabelWrapping
495
- label={formatMessage({ id: "rule.props.minimum" })}
496
- messages={_.prop("minimum")(messages)}
497
- required
498
- tooltip={formatMessage({
499
- id: `rule.form.tooltip.${rule.result_type}.minimum`,
500
- })}
501
- >
502
- <Form.Input
503
- name="minimum"
504
- onChange={this.handleChangeInteger}
505
- value={_.isNil(rule.minimum) ? "" : rule.minimum}
506
- placeholder={formatMessage({
507
- id: "rule.props.minimum.placeholder",
508
- })}
509
- autoComplete="off"
510
- />
511
- </FieldLabelWrapping>
512
- <FieldLabelWrapping
513
- label={formatMessage({ id: "rule.props.goal" })}
514
- messages={_.prop("goal")(messages)}
515
- required
516
- tooltip={formatMessage({
517
- id: `rule.form.tooltip.${rule.result_type}.goal`,
518
- })}
519
- >
520
- <Form.Input
521
- name="goal"
522
- onChange={this.handleChangeInteger}
523
- value={_.isNil(rule.goal) ? "" : rule.goal}
524
- placeholder={formatMessage({
525
- id: "rule.props.goal.placeholder",
526
- })}
527
- autoComplete="off"
528
- />
529
- </FieldLabelWrapping>
530
- </Segment>
531
353
  {!_.isNil(rule.df_content) && templatesLoaded && (
532
354
  <DynamicRuleForm
533
355
  name="dynamicForm"
@@ -4,12 +4,13 @@ import { Link } from "react-router-dom";
4
4
  import PropTypes from "prop-types";
5
5
  import { useIntl } from "react-intl";
6
6
  import { connect } from "react-redux";
7
- import { Header, Label, Menu, Grid } from "semantic-ui-react";
7
+ import { Header, Label, Menu, Grid, Icon } from "semantic-ui-react";
8
8
  import { ConfirmModal, GroupActions } from "@truedat/core/components";
9
9
  import { useAuthorized } from "@truedat/core/hooks";
10
10
  import { linkTo } from "@truedat/core/routes";
11
11
  import { setRuleImplementationStatus } from "../routines";
12
12
  import RuleImplementationTabs from "./RuleImplementationTabs";
13
+ import ImplementationResultBar from "./ImplementationResultBar";
13
14
 
14
15
  const getAvailableActions = (props, formatMessage) => {
15
16
  const contentActions = [
@@ -177,11 +178,13 @@ export const RuleImplementation = ({
177
178
  <>
178
179
  <Grid>
179
180
  <Grid.Column width={8}>
180
- <Header
181
- as="h2"
182
- content={ruleImplementation.implementation_key}
183
- icon={{ name: "clipboard check", circular: true }}
184
- />
181
+ <Header as="h2">
182
+ <Icon circular name="clipboard check" />
183
+ <Header.Content>
184
+ {ruleImplementation.implementation_key}
185
+ <ImplementationResultBar implementation={ruleImplementation} />
186
+ </Header.Content>
187
+ </Header>
185
188
  </Grid.Column>
186
189
  <Grid.Column width={8} textAlign="right">
187
190
  <>
@@ -215,6 +218,7 @@ RuleImplementation.propTypes = {
215
218
  rule: PropTypes.object,
216
219
  ruleImplementation: PropTypes.object,
217
220
  userRulePermissions: PropTypes.object,
221
+ children: PropTypes.node,
218
222
  };
219
223
 
220
224
  const mapStateToProps = ({
@@ -3,19 +3,22 @@ import React from "react";
3
3
  import PropTypes from "prop-types";
4
4
  import { FormattedMessage } from "react-intl";
5
5
  import { connect } from "react-redux";
6
- import { Header, Grid, Icon, Label, Segment, List } from "semantic-ui-react";
6
+ import { Grid, Label, Segment } from "semantic-ui-react";
7
+ import InformationSummary from "./InformationSummary";
7
8
  import ImplementationSummary from "./ImplementationSummary";
8
9
  import RawContent from "./RawContent";
9
- import RuleResultDecorator from "./RuleResultDecorator";
10
- import QualityEventError from "./QualityEventError";
10
+
11
+ const DynamicFormViewer = React.lazy(() =>
12
+ import("@truedat/df/components/DynamicFormViewer")
13
+ );
11
14
 
12
15
  const summarySteps = ["dataset", "population", "validations"];
13
16
 
14
17
  export const RuleImplementationProperties = ({
15
- rule,
16
18
  ruleImplementation,
17
19
  ruleImplementationRaw,
18
- ruleResult,
20
+ templateImpl,
21
+ ruleImplementationLoaded,
19
22
  }) => {
20
23
  return _.isEmpty(ruleImplementation) &&
21
24
  _.isEmpty(ruleImplementationRaw) ? null : (
@@ -30,6 +33,18 @@ export const RuleImplementationProperties = ({
30
33
  </Label>
31
34
  </Grid.Column>
32
35
  </Grid.Row>
36
+ <Grid.Row>
37
+ <Grid.Column width={10}>
38
+ <InformationSummary ruleImplementation={ruleImplementation} />
39
+ {!_.isEmpty(templateImpl) && ruleImplementationLoaded && (
40
+ <DynamicFormViewer
41
+ boxLayout
42
+ template={templateImpl}
43
+ content={ruleImplementation.df_content}
44
+ />
45
+ )}
46
+ </Grid.Column>
47
+ </Grid.Row>
33
48
  <Grid.Column width={10}>
34
49
  {_.isEmpty(ruleImplementationRaw) ? (
35
50
  <ImplementationSummary
@@ -41,85 +56,37 @@ export const RuleImplementationProperties = ({
41
56
  )}
42
57
  </Grid.Column>
43
58
  </Grid>
44
- <Header as="h3">
45
- <FormattedMessage id={`rule.props.result_type.${rule.result_type}`} />
46
- </Header>
47
- <List>
48
- <List.Item>
49
- <Icon name="circle" color="yellow" />
50
- <List.Content>
51
- <List.Description>
52
- <FormattedMessage id="quality.threshold" />
53
- {`: ${rule.minimum} ${
54
- rule.result_type !== "errors_number" ? "%" : ""
55
- }`}
56
- </List.Description>
57
- </List.Content>
58
- </List.Item>
59
- <List.Item>
60
- <Icon name="circle" color="green" />
61
- <List.Content>
62
- <List.Description>
63
- <FormattedMessage id="quality.goal" />
64
- {`: ${rule.goal} ${
65
- rule.result_type !== "errors_number" ? "%" : ""
66
- }`}
67
- </List.Description>
68
- </List.Content>
69
- </List.Item>
70
- </List>
71
- <Header as="h3">
72
- <FormattedMessage id="quality.rule.quality" />
73
- </Header>
74
- {ruleResult ? (
75
- <p>
76
- <RuleResultDecorator
77
- ruleResult={ruleResult}
78
- date={ruleResult?.date}
79
- rule={rule}
80
- />
81
- </p>
82
- ) : (
83
- <FormattedMessage id="quality.result.no.data" />
84
- )}
85
- {ruleImplementation.event_type !== "FAILED" ? null : (
86
- <>
87
- <Header as="h3">
88
- <Icon name="warning circle" color="red" size="small" />
89
- <FormattedMessage id="quality.error" />
90
- </Header>
91
- <QualityEventError
92
- inserted_at={ruleImplementation.event_inserted_at}
93
- message={ruleImplementation.event_message}
94
- type={ruleImplementation.event_type}
95
- />
96
- </>
97
- )}
98
59
  </Segment>
99
60
  );
100
61
  };
101
62
  RuleImplementationProperties.propTypes = {
102
- rule: PropTypes.object,
103
63
  ruleImplementation: PropTypes.object.isRequired,
104
64
  ruleImplementationRaw: PropTypes.object,
105
- ruleResult: PropTypes.array,
65
+ templateImpl: PropTypes.object,
66
+ ruleImplementationLoaded: PropTypes.bool,
106
67
  };
107
68
 
108
69
  const mapStateToProps = ({
109
- rule,
110
70
  ruleImplementation,
111
71
  ruleImplementationRaw,
72
+ templates,
73
+ ruleImplementationLoading,
112
74
  }) => ({
113
- rule,
114
75
  ruleImplementation: _.pick([
115
76
  ...summarySteps,
116
77
  "executable",
117
78
  "event_type",
118
79
  "event_message",
119
80
  "event_inserted_at",
81
+ "result_type",
82
+ "minimum",
83
+ "goal",
84
+ "df_content",
120
85
  ])(ruleImplementation),
121
86
  ruleImplementationRaw,
122
- ruleResult: _.head(ruleImplementation?.results),
87
+ templateImpl: _.find(_.propEq("name", ruleImplementation.df_name))(templates),
88
+ ruleImplementationLoaded:
89
+ !ruleImplementationLoading && !_.isEmpty(ruleImplementation),
123
90
  });
124
91
 
125
92
  export default connect(mapStateToProps)(RuleImplementationProperties);
@@ -3,8 +3,9 @@ import React from "react";
3
3
  import PropTypes from "prop-types";
4
4
  import { useIntl } from "react-intl";
5
5
  import { connect } from "react-redux";
6
- import { Table, Message } from "semantic-ui-react";
6
+ import { Table, Message, Divider } from "semantic-ui-react";
7
7
  import { columnDecorator } from "@truedat/core/services";
8
+ import Moment from "react-moment";
8
9
  import { getRuleResultsColumns } from "../selectors";
9
10
  import RuleResultRow from "./RuleResultRow";
10
11
 
@@ -25,65 +26,98 @@ export const RuleImplementationResults = ({
25
26
  customColumns,
26
27
  isAdmin,
27
28
  }) => {
28
- const { formatMessage } = useIntl();
29
+ const { formatMessage, locale } = useIntl();
29
30
 
30
31
  if (_.isEmpty(rule) || _.isEmpty(ruleImplementation)) return null;
31
32
 
32
33
  const ruleResults = ruleImplementation.results;
33
34
  const optionalColumns = getOptionalColumnsWithData(ruleResults);
34
35
 
35
- return _.isEmpty(ruleResults) ? (
36
- <Message
37
- style={{ marginTop: "14px" }}
38
- header={formatMessage({ id: "rule.ruleImplementation.results.empty" })}
39
- />
40
- ) : (
41
- <Table className="implementation-results small" selectable>
42
- <Table.Header>
43
- <Table.Row>
44
- <Table.HeaderCell
45
- content={formatMessage({ id: "ruleResult.props.quality" })}
36
+ return (
37
+ <>
38
+ {ruleImplementation.event_type === "FAILED" && (
39
+ <Message negative style={{ marginTop: "14px" }}>
40
+ <Message.Header>
41
+ {formatMessage({
42
+ id: "quality.error",
43
+ })}
44
+ </Message.Header>
45
+ <Divider />
46
+ <Moment
47
+ style={{
48
+ position: "absolute",
49
+ top: "14px",
50
+ right: "21px",
51
+ }}
52
+ locale={locale}
53
+ date={ruleImplementation.event_inserted_at}
54
+ format="YYYY-MM-DD HH:mm"
46
55
  />
47
- <Table.HeaderCell
48
- content={formatMessage({ id: "ruleResult.props.date" })}
49
- />
50
- {_.includes("records")(optionalColumns) && (
51
- <Table.HeaderCell
52
- content={formatMessage({ id: "ruleResult.props.records" })}
53
- />
54
- )}
55
- {_.includes("errors")(optionalColumns) && (
56
- <Table.HeaderCell
57
- content={formatMessage({ id: "ruleResult.props.errors" })}
58
- />
59
- )}
60
- {customColumns.map((column, index) => (
61
- <Table.HeaderCell
62
- key={index}
63
- content={formatMessage({
64
- id: `ruleResult.props.${column.name}`,
65
- defaultMessage: column.name,
66
- })}
67
- />
68
- ))}
69
- {<Table.HeaderCell />}
70
- {isAdmin && <Table.HeaderCell />}
71
- </Table.Row>
72
- </Table.Header>
73
- <Table.Body>
74
- {ruleResults.map((result, i) => (
75
- <RuleResultRow
76
- key={i}
77
- optionalColumns={optionalColumns}
78
- ruleResult={result}
79
- customColumns={customColumns}
80
- isAdmin={isAdmin}
81
- ruleImplementation={ruleImplementation}
82
- rule={rule}
83
- />
84
- ))}
85
- </Table.Body>
86
- </Table>
56
+ <p
57
+ style={{
58
+ whiteSpace: "pre-wrap",
59
+ }}
60
+ >
61
+ {ruleImplementation.event_message}
62
+ </p>
63
+ </Message>
64
+ )}
65
+ {_.isEmpty(ruleResults) ? (
66
+ <Message
67
+ style={{ marginTop: "14px" }}
68
+ header={formatMessage({
69
+ id: "rule.ruleImplementation.results.empty",
70
+ })}
71
+ />
72
+ ) : (
73
+ <Table className="implementation-results small" selectable>
74
+ <Table.Header>
75
+ <Table.Row>
76
+ <Table.HeaderCell
77
+ content={formatMessage({ id: "ruleResult.props.quality" })}
78
+ />
79
+ <Table.HeaderCell
80
+ content={formatMessage({ id: "ruleResult.props.date" })}
81
+ />
82
+ {_.includes("records")(optionalColumns) && (
83
+ <Table.HeaderCell
84
+ content={formatMessage({ id: "ruleResult.props.records" })}
85
+ />
86
+ )}
87
+ {_.includes("errors")(optionalColumns) && (
88
+ <Table.HeaderCell
89
+ content={formatMessage({ id: "ruleResult.props.errors" })}
90
+ />
91
+ )}
92
+ {customColumns.map((column, index) => (
93
+ <Table.HeaderCell
94
+ key={index}
95
+ content={formatMessage({
96
+ id: `ruleResult.props.${column.name}`,
97
+ defaultMessage: column.name,
98
+ })}
99
+ />
100
+ ))}
101
+ {<Table.HeaderCell />}
102
+ {isAdmin && <Table.HeaderCell />}
103
+ </Table.Row>
104
+ </Table.Header>
105
+ <Table.Body>
106
+ {ruleResults.map((result, i) => (
107
+ <RuleResultRow
108
+ key={i}
109
+ optionalColumns={optionalColumns}
110
+ ruleResult={result}
111
+ customColumns={customColumns}
112
+ isAdmin={isAdmin}
113
+ ruleImplementation={ruleImplementation}
114
+ rule={rule}
115
+ />
116
+ ))}
117
+ </Table.Body>
118
+ </Table>
119
+ )}
120
+ </>
87
121
  );
88
122
  };
89
123