@truedat/dq 4.41.3 → 4.42.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.
Files changed (22) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/package.json +5 -5
  3. package/src/components/ConditionSummary.js +41 -27
  4. package/src/components/ImplementationSummary.js +5 -5
  5. package/src/components/NewRuleImplementation.js +76 -17
  6. package/src/components/RuleImplementationProperties.js +2 -1
  7. package/src/components/__test_samples__/NewRuleImplementationProps.js +44 -42
  8. package/src/components/__tests__/ImplementationSummary.spec.js +4 -4
  9. package/src/components/__tests__/__snapshots__/ImplementationSummary.spec.js.snap +68 -3
  10. package/src/components/__tests__/__snapshots__/NewRuleImplementation.spec.js.snap +108 -100
  11. package/src/components/__tests__/__snapshots__/RuleImplementationProperties.spec.js.snap +1 -1
  12. package/src/components/ruleImplementationForm/PopulationForm.js +1 -27
  13. package/src/components/ruleImplementationForm/RuleImplementationForm.js +69 -20
  14. package/src/components/ruleImplementationForm/RuleImplementationRawForm.js +163 -177
  15. package/src/components/ruleImplementationForm/__tests__/RuleImplementationRawForm.spec.js +3 -3
  16. package/src/components/ruleImplementationForm/__tests__/__snapshots__/RuleImplementationForm.spec.js.snap +1 -1
  17. package/src/components/ruleImplementationForm/__tests__/__snapshots__/RuleImplementationRawForm.spec.js.snap +159 -156
  18. package/src/messages/en.js +4 -2
  19. package/src/messages/es.js +3 -1
  20. package/src/reducers/ruleImplementation.js +1 -1
  21. package/src/sagas/__tests__/createRuleImplementation.spec.js +12 -10
  22. package/src/sagas/__tests__/updateRuleImplementation.spec.js +8 -6
@@ -5,6 +5,7 @@ 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 { accentInsensitivePathOrder } from "@truedat/core/services/sort";
8
9
  import { validateContent as validDfContent } from "@truedat/df/utils";
9
10
  import { selectTemplate } from "@truedat/df/routines";
10
11
  import LimitsForm from "./LimitsForm";
@@ -17,9 +18,7 @@ const Help = ({ message }) => {
17
18
  trigger={
18
19
  <Icon className="rule-form-popup" name="question circle outline" />
19
20
  }
20
- content={formatMessage({
21
- id: message,
22
- })}
21
+ content={formatMessage({ id: message })}
23
22
  on="click"
24
23
  hideOnScroll
25
24
  />
@@ -38,10 +37,6 @@ const DynamicForm = React.lazy(() =>
38
37
  import("@truedat/df/components/DynamicForm")
39
38
  );
40
39
 
41
- const SourcesLoader = React.lazy(() =>
42
- import("@truedat/cx/sources/components/SourcesLoader")
43
- );
44
-
45
40
  const ImplementationDynamicForm = ({
46
41
  ruleImplementation,
47
42
  onChange,
@@ -89,8 +84,9 @@ export const RuleImplementationRawForm = ({
89
84
  rawContent,
90
85
  setImplementationKey,
91
86
  setImplementationRawContent,
92
- sources,
93
87
  selectTemplate,
88
+ sources,
89
+ sourcesLoading,
94
90
  template = {},
95
91
  templates,
96
92
  onChange,
@@ -115,33 +111,29 @@ export const RuleImplementationRawForm = ({
115
111
  const onChangeImplementation = (prop, value) =>
116
112
  setImplementationRawContent({ ...rawContent, [prop]: value });
117
113
 
118
- const onChangeSource = (id) =>
114
+ const onChangeSource = (value) => {
119
115
  setImplementationRawContent({
120
116
  ...rawContent,
121
- source_id: id,
117
+ source_id: value,
122
118
  database: "",
123
119
  });
120
+ };
121
+
122
+ const selectedSourceId = rawContent?.source_id?.toString();
124
123
 
125
- const sourcesOptions = _.flow(
126
- _.filter((source) =>
127
- _.includes("quality")(_.getOr([], "config.job_types")(source))
128
- ),
129
- _.map(({ id, external_id }) => ({
124
+ const sourceOptions = _.flow(
125
+ _.sortBy(accentInsensitivePathOrder("externalId")),
126
+ _.map(({ id, externalId }) => ({
130
127
  key: id,
131
- text: external_id,
132
128
  value: id,
129
+ text: externalId,
133
130
  }))
134
131
  )(sources);
135
- const selectedSourceId = _.prop("source_id")(rawContent);
136
-
137
- const databasesOptions = _.flow(
132
+ const databaseOptions = _.flow(
138
133
  _.find({ id: selectedSourceId }),
139
- _.getOr([], "config.databases"),
140
- _.map((database) => ({
141
- key: database,
142
- text: database,
143
- value: database,
144
- }))
134
+ _.path(["config", "databases"]),
135
+ _.sortedUniq,
136
+ _.map((value) => ({ key: value, text: value, value }))
145
137
  )(sources);
146
138
 
147
139
  const getBannedWordsAndChars = (text) => {
@@ -159,7 +151,7 @@ export const RuleImplementationRawForm = ({
159
151
  return (
160
152
  validInformation() &&
161
153
  isNotEmptyProp("source_id") &&
162
- (_.isEmpty(databasesOptions) || isNotEmptyProp("database")) &&
154
+ (_.isEmpty(databaseOptions) || isNotEmptyProp("database")) &&
163
155
  _.every(isNotEmptyProp)(["dataset", "validations"]) &&
164
156
  _.every(hasNoErrors)(["dataset", "population", "validations"])
165
157
  );
@@ -193,183 +185,178 @@ export const RuleImplementationRawForm = ({
193
185
  const errors = getErrors();
194
186
 
195
187
  return (
196
- <>
197
- <SourcesLoader />
198
- <Form className="rule">
199
- <Form.Radio
200
- checked={ruleImplementation.executable}
201
- name="executable"
202
- label={formatMessage({ id: "ruleImplementation.props.executable" })}
203
- onChange={(_e, { checked }) => onChange("executable", checked)}
204
- toggle
188
+ <Form className="rule">
189
+ <Form.Radio
190
+ checked={ruleImplementation.executable}
191
+ name="executable"
192
+ label={formatMessage({ id: "ruleImplementation.props.executable" })}
193
+ onChange={(_e, { checked }) => onChange("executable", checked)}
194
+ toggle
195
+ />
196
+ <Form.Field>
197
+ <label>
198
+ {formatMessage({ id: "ruleImplementation.props.name" })}
199
+ <Help message="datasetForm.implementation_key.tooltip" />
200
+ </label>
201
+ <Form.Input
202
+ autoComplete="off"
203
+ name="implementation_key"
204
+ onChange={(_e, { value }) => setImplementationKey(value)}
205
+ placeholder={formatMessage({
206
+ id: "ruleImplementation.props.name.placeholder",
207
+ })}
208
+ required
209
+ value={implementationKey}
205
210
  />
206
- <Form.Field>
207
- <label>
208
- {formatMessage({ id: "ruleImplementation.props.name" })}
209
- <Help message="datasetForm.implementation_key.tooltip" />
210
- </label>
211
- <Form.Input
212
- autoComplete="off"
213
- name="implementation_key"
214
- onChange={(_e, { value }) => setImplementationKey(value)}
215
- placeholder={formatMessage({
216
- id: "ruleImplementation.props.name.placeholder",
217
- })}
218
- required
219
- value={implementationKey}
220
- />
221
- </Form.Field>
222
- <LimitsForm
223
- onChange={onChange}
211
+ </Form.Field>
212
+ <LimitsForm onChange={onChange} ruleImplementation={ruleImplementation} />
213
+ {!_.isEmpty(templates) && (
214
+ <ImplementationDynamicForm
215
+ selectTemplate={selectTemplate}
216
+ template={template}
217
+ templates={templates}
224
218
  ruleImplementation={ruleImplementation}
219
+ onChange={onChange}
225
220
  />
226
- {!_.isEmpty(templates) && (
227
- <ImplementationDynamicForm
228
- selectTemplate={selectTemplate}
229
- template={template}
230
- templates={templates}
231
- ruleImplementation={ruleImplementation}
232
- onChange={onChange}
233
- />
234
- )}
221
+ )}
222
+ <Form.Dropdown
223
+ label={
224
+ <label>
225
+ <FormattedMessage id="ruleImplementationRawForm.props.source" />
226
+ </label>
227
+ }
228
+ loading={sourcesLoading}
229
+ name="source_id"
230
+ onChange={(_e, { value }) => onChangeSource(value)}
231
+ options={sourceOptions}
232
+ placeholder={formatMessage({
233
+ id: "ruleImplementationRawForm.props.source.placeholder",
234
+ })}
235
+ required
236
+ search
237
+ selection
238
+ value={selectedSourceId}
239
+ />
240
+ {selectedSourceId && !_.isEmpty(databaseOptions) ? (
235
241
  <Form.Dropdown
236
242
  label={
237
243
  <label>
238
- <FormattedMessage id="ruleImplementationRawForm.props.source" />
244
+ <FormattedMessage id="ruleImplementationRawForm.props.database" />
239
245
  </label>
240
246
  }
247
+ loading={sourcesLoading}
248
+ name="database"
241
249
  placeholder={formatMessage({
242
- id: "ruleImplementationRawForm.props.source.placeholder",
250
+ id: "ruleImplementationRawForm.props.database.placeholder",
243
251
  })}
244
- name="source_id"
245
- onChange={(_e, { value }) => onChangeSource(value)}
246
- options={sourcesOptions}
247
- required
248
- selection
249
- value={selectedSourceId}
250
- />
251
- {selectedSourceId && !_.isEmpty(databasesOptions) && (
252
- <Form.Dropdown
253
- label={
254
- <label>
255
- <FormattedMessage id="ruleImplementationRawForm.props.database" />
256
- </label>
257
- }
258
- name="database"
259
- placeholder={formatMessage({
260
- id: "ruleImplementationRawForm.props.database.placeholder",
261
- })}
262
- onChange={(_e, { value }) =>
263
- onChangeImplementation("database", value)
264
- }
265
- options={databasesOptions}
266
- required
267
- selection
268
- value={_.prop("database")(rawContent)}
269
- />
270
- )}
271
- <Form.TextArea
272
- className="raw"
273
- error={
274
- _.path("dataset.hasErrors")(errors) && {
275
- content: _.path("dataset.errorMessage")(errors),
276
- }
252
+ onChange={(_e, { value }) =>
253
+ onChangeImplementation("database", value)
277
254
  }
278
- label={
279
- <label>
280
- <FormattedMessage id="ruleImplementationRawForm.props.dataset" />
281
- <Help message="ruleImplementationRawForm.props.dataset.help"></Help>
282
- </label>
283
- }
284
- name="dataset"
285
- onChange={(e, { value }) => onChangeImplementation("dataset", value)}
286
- placeholder={formatMessage({
287
- id: "ruleImplementationRawForm.props.dataset.placeholder",
288
- })}
255
+ options={databaseOptions}
289
256
  required
290
- rows={4}
291
- size="small"
292
- value={_.prop("dataset")(rawContent) || ""}
293
- />
294
- <Form.TextArea
295
- className="raw"
296
- error={
297
- _.path("population.hasErrors")(errors) && {
298
- content: _.path("population.errorMessage")(errors),
299
- }
300
- }
301
- label={
302
- <label>
303
- <FormattedMessage id="ruleImplementationRawForm.props.population" />
304
- <Help message="ruleImplementationRawForm.props.population.help"></Help>
305
- </label>
306
- }
307
- name="population"
308
- onChange={(e, { value }) =>
309
- onChangeImplementation("population", value)
310
- }
311
- placeholder={formatMessage({
312
- id: "ruleImplementationRawForm.props.population.placeholder",
313
- })}
314
- rows={4}
315
- size="small"
316
- value={_.prop("population")(rawContent) || ""}
257
+ selection
258
+ value={_.prop("database")(rawContent)}
317
259
  />
318
- <Form.TextArea
319
- className="raw"
320
- error={
321
- _.path("validations.hasErrors")(errors) && {
322
- content: _.path("validations.errorMessage")(errors),
323
- }
260
+ ) : null}
261
+ <Form.TextArea
262
+ className="raw"
263
+ error={
264
+ _.path("dataset.hasErrors")(errors) && {
265
+ content: _.path("dataset.errorMessage")(errors),
324
266
  }
325
- label={
326
- <label>
327
- <FormattedMessage id="ruleImplementationRawForm.props.validations" />
328
- <Help message="ruleImplementationRawForm.props.validations.help"></Help>
329
- </label>
267
+ }
268
+ label={
269
+ <label>
270
+ <FormattedMessage id="ruleImplementationRawForm.props.dataset" />
271
+ <Help message="ruleImplementationRawForm.props.dataset.help"></Help>
272
+ </label>
273
+ }
274
+ name="dataset"
275
+ onChange={(e, { value }) => onChangeImplementation("dataset", value)}
276
+ placeholder={formatMessage({
277
+ id: "ruleImplementationRawForm.props.dataset.placeholder",
278
+ })}
279
+ required
280
+ rows={4}
281
+ size="small"
282
+ value={_.prop("dataset")(rawContent) || ""}
283
+ />
284
+ <Form.TextArea
285
+ className="raw"
286
+ error={
287
+ _.path("population.hasErrors")(errors) && {
288
+ content: _.path("population.errorMessage")(errors),
330
289
  }
331
- name="validations"
332
- onChange={(e, { value }) =>
333
- onChangeImplementation("validations", value)
290
+ }
291
+ label={
292
+ <label>
293
+ <FormattedMessage id="ruleImplementationRawForm.props.population" />
294
+ <Help message="ruleImplementationRawForm.props.population.help"></Help>
295
+ </label>
296
+ }
297
+ name="population"
298
+ onChange={(e, { value }) => onChangeImplementation("population", value)}
299
+ placeholder={formatMessage({
300
+ id: "ruleImplementationRawForm.props.population.placeholder",
301
+ })}
302
+ rows={4}
303
+ size="small"
304
+ value={_.prop("population")(rawContent) || ""}
305
+ />
306
+ <Form.TextArea
307
+ className="raw"
308
+ error={
309
+ _.path("validations.hasErrors")(errors) && {
310
+ content: _.path("validations.errorMessage")(errors),
334
311
  }
335
- placeholder={formatMessage({
336
- id: "ruleImplementationRawForm.props.validations.placeholder",
337
- })}
338
- required
339
- rows={4}
340
- size="small"
341
- value={_.prop("validations")(rawContent) || ""}
342
- />
343
- <Form.Button
344
- floated="right"
345
- disabled={!isValidForm()}
346
- type="submit"
347
- primary
348
- loading={isSubmitting}
349
- onClick={() => doSubmit()}
350
- content={formatMessage({ id: "actions.submit" })}
351
- />
352
- <Button
353
- content={formatMessage({ id: "actions.cancel" })}
354
- floated="right"
355
- onClick={() => doCancel()}
356
- secondary
357
- />
358
- </Form>
359
- </>
312
+ }
313
+ label={
314
+ <label>
315
+ <FormattedMessage id="ruleImplementationRawForm.props.validations" />
316
+ <Help message="ruleImplementationRawForm.props.validations.help"></Help>
317
+ </label>
318
+ }
319
+ name="validations"
320
+ onChange={(e, { value }) =>
321
+ onChangeImplementation("validations", value)
322
+ }
323
+ placeholder={formatMessage({
324
+ id: "ruleImplementationRawForm.props.validations.placeholder",
325
+ })}
326
+ required
327
+ rows={4}
328
+ size="small"
329
+ value={_.prop("validations")(rawContent) || ""}
330
+ />
331
+ <Form.Button
332
+ floated="right"
333
+ disabled={!isValidForm()}
334
+ type="submit"
335
+ primary
336
+ loading={isSubmitting}
337
+ onClick={() => doSubmit()}
338
+ content={formatMessage({ id: "actions.submit" })}
339
+ />
340
+ <Button
341
+ content={formatMessage({ id: "actions.cancel" })}
342
+ floated="right"
343
+ onClick={() => doCancel()}
344
+ secondary
345
+ />
346
+ </Form>
360
347
  );
361
348
  };
362
349
 
363
350
  RuleImplementationRawForm.propTypes = {
364
- mode: PropTypes.string,
365
351
  handleSubmit: PropTypes.func.isRequired,
366
352
  implementationKey: PropTypes.string,
367
353
  isSubmitting: PropTypes.bool,
368
354
  rawContent: PropTypes.object,
369
355
  setImplementationKey: PropTypes.func,
370
356
  setImplementationRawContent: PropTypes.func,
371
- sources: PropTypes.array,
372
357
  selectTemplate: PropTypes.func,
358
+ sources: PropTypes.array,
359
+ sourcesLoading: PropTypes.bool,
373
360
  template: PropTypes.object,
374
361
  templates: PropTypes.object,
375
362
  ruleImplementation: PropTypes.object,
@@ -378,7 +365,6 @@ RuleImplementationRawForm.propTypes = {
378
365
 
379
366
  const mapStateToProps = (state) => ({
380
367
  isSubmitting: state.ruleImplementationCreating,
381
- sources: _.get("sources")(state),
382
368
  templates: state.templates,
383
369
  template: getTemplate(state),
384
370
  });
@@ -18,12 +18,12 @@ describe("<RuleImplementationRawForm />", () => {
18
18
  const isSubmitting = false;
19
19
  const sources = [
20
20
  {
21
- id: 1,
21
+ id: "1",
22
22
  config: { alias: "source1", job_types: ["quality"] },
23
23
  external_id: "ext_id_1",
24
24
  },
25
25
  {
26
- id: 2,
26
+ id: "2",
27
27
  config: {
28
28
  alias: "source2",
29
29
  job_types: ["quality"],
@@ -31,7 +31,7 @@ describe("<RuleImplementationRawForm />", () => {
31
31
  },
32
32
  external_id: "ext_id_2",
33
33
  },
34
- { id: 3, config: {}, external_id: "ext_id_3" },
34
+ { id: "3", config: {}, external_id: "ext_id_3" },
35
35
  ];
36
36
  const setImplementationRawContent = jest.fn();
37
37
 
@@ -37,7 +37,7 @@ exports[`<RuleImplementationForm /> matches the latest snapshot 1`] = `
37
37
  }
38
38
  }
39
39
  key="2"
40
- name="population"
40
+ name="populations"
41
41
  />
42
42
  <RuleImplementationStep
43
43
  activeStep="information"