@truedat/dq 4.53.0 → 4.53.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # Changelog
2
2
 
3
+ ## [4.53.2] 2022-10-07
4
+
5
+ ### Changed
6
+
7
+ - [TD-5226] Use `useOperators` hook to load operators
8
+
9
+ ## [4.53.1] 2022-10-05
10
+
11
+ ### Changed
12
+
13
+ - [TD-5098] Improve modifiers behaviour
14
+ - Fix field type selector for StructureFieldsDrowdown
15
+ - Fix fields applied modifiers for StructureFieldsDrowdown
16
+ - Allow multiple modifiers in ruleImplementationOperators reducer
17
+
3
18
  ## [4.53.0] 2022-10-04
4
19
 
5
20
  ### Added
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@truedat/dq",
3
- "version": "4.53.0",
3
+ "version": "4.53.2",
4
4
  "description": "Truedat Web Data Quality Module",
5
5
  "sideEffects": false,
6
6
  "jsnext:main": "src/index.js",
@@ -34,7 +34,7 @@
34
34
  "@testing-library/jest-dom": "^5.16.4",
35
35
  "@testing-library/react": "^12.0.0",
36
36
  "@testing-library/user-event": "^13.2.1",
37
- "@truedat/test": "4.53.0",
37
+ "@truedat/test": "4.53.2",
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",
@@ -93,8 +93,8 @@
93
93
  },
94
94
  "dependencies": {
95
95
  "@apollo/client": "^3.6.4",
96
- "@truedat/core": "4.53.0",
97
- "@truedat/df": "4.53.0",
96
+ "@truedat/core": "4.53.2",
97
+ "@truedat/df": "4.53.2",
98
98
  "graphql": "^15.5.3",
99
99
  "path-to-regexp": "^1.7.0",
100
100
  "prop-types": "^15.8.1",
@@ -114,5 +114,5 @@
114
114
  "react-dom": ">= 16.8.6 < 17",
115
115
  "semantic-ui-react": ">= 0.88.2 < 2.1"
116
116
  },
117
- "gitHead": "c13d72dea3b93ba4f21b455dc2aaf9f289261dd3"
117
+ "gitHead": "e29af66624aad6ecce065ced88c8cc2e320d67e2"
118
118
  }
@@ -4,6 +4,7 @@ import PropTypes from "prop-types";
4
4
  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
+ import { useIntl } from "react-intl";
7
8
  import { linkTo } from "@truedat/core/routes";
8
9
 
9
10
  const concatValues = (values, link) => _.join(link)(values);
@@ -131,6 +132,7 @@ const ConditionCell = ({ row, alias }) => {
131
132
 
132
133
  const values = getValues(row);
133
134
  const operator = _.prop("operator")(row);
135
+ const { formatMessage } = useIntl();
134
136
  return (
135
137
  <Table.Row>
136
138
  <Table.Cell width={5}>
@@ -163,7 +165,10 @@ const ConditionCell = ({ row, alias }) => {
163
165
  _.toPairs,
164
166
  _.map(([key, value]) => (
165
167
  <div key={key} className="smaller">
166
- {value}
168
+ {`${formatMessage({
169
+ id: `filtersGrid.field.modifier.${row.modifier.name}.${key}`,
170
+ defaultMessage: key,
171
+ })}: ${value}`}
167
172
  </div>
168
173
  ))
169
174
  )(row)}
@@ -4,12 +4,13 @@ import PropTypes from "prop-types";
4
4
  import { connect } from "react-redux";
5
5
  import { Divider, Header, Grid } from "semantic-ui-react";
6
6
  import { FormattedMessage } from "react-intl";
7
+ import { Loading } from "@truedat/core/components";
8
+ import { useOperators } from "@truedat/core/hooks";
7
9
  import { getFieldType } from "@truedat/core/services/fieldType";
8
10
  import {
9
11
  createRuleImplementation,
10
12
  updateRuleImplementation,
11
13
  } from "../routines";
12
- import { getRuleImplementationOperators } from "../selectors/getRuleImplementationOperators";
13
14
  import RuleImplementationForm from "./ruleImplementationForm/RuleImplementationForm";
14
15
  import RuleImplementationRawForm from "./ruleImplementationForm/RuleImplementationRawForm";
15
16
  import ImplementationSummary from "./ImplementationSummary";
@@ -598,10 +599,16 @@ const mapStateToProps = (state) => ({
598
599
  ruleImplementationRaw: state.ruleImplementationRaw,
599
600
  structuresFields: state.structuresFields,
600
601
  structuresSiblings: state.structuresSiblings,
601
- operators: getRuleImplementationOperators(state),
602
602
  });
603
603
 
604
+ export const ImplementationLoader = (props) => {
605
+ const { data, error, loading } = useOperators();
606
+ if (error) return null;
607
+ if (loading) return <Loading />;
608
+ return <NewRuleImplementation operators={data} {...props} />;
609
+ };
610
+
604
611
  export default connect(mapStateToProps, {
605
612
  createRuleImplementation,
606
613
  updateRuleImplementation,
607
- })(NewRuleImplementation);
614
+ })(ImplementationLoader);
@@ -3,9 +3,8 @@ import React from "react";
3
3
  import { waitFor, within } from "@testing-library/react";
4
4
  import { render } from "@truedat/test/render";
5
5
  import { DOMAIN_QUERY, DOMAINS_QUERY } from "@truedat/core/api/queries";
6
- import { multipleTemplatesMock } from "@truedat/test/mocks";
6
+ import { functionsMock, multipleTemplatesMock } from "@truedat/test/mocks";
7
7
  import userEvent from "@testing-library/user-event";
8
- import defaultMessages from "@truedat/test/messages";
9
8
  import NewRuleImplementation, {
10
9
  NewRuleImplementation as NewRuleImplementationComponent,
11
10
  } from "../NewRuleImplementation";
@@ -41,10 +40,6 @@ const domainMock = {
41
40
  result: { data: { domain: { id: "2", actions: domainActions } } },
42
41
  };
43
42
 
44
- const messages = {
45
- en: { ...defaultMessages.en },
46
- };
47
-
48
43
  describe("<NewRuleImplementation />", () => {
49
44
  const createRuleImplementation = jest.fn();
50
45
  const updateRuleImplementation = jest.fn();
@@ -63,6 +58,7 @@ describe("<NewRuleImplementation />", () => {
63
58
  };
64
59
  const renderOpts = {
65
60
  mocks: [
61
+ functionsMock,
66
62
  multipleTemplatesMock({
67
63
  scope: "ri",
68
64
  domainIds: null,
@@ -71,7 +67,6 @@ describe("<NewRuleImplementation />", () => {
71
67
  domainMock,
72
68
  ],
73
69
  state: { ruleImplementationCreating: false },
74
- messages,
75
70
  fallback: "lazy",
76
71
  };
77
72
 
@@ -85,15 +80,15 @@ describe("<NewRuleImplementation />", () => {
85
80
  await waitFor(() =>
86
81
  expect(queryByText(/loading/i)).not.toBeInTheDocument()
87
82
  );
83
+ await waitFor(() =>
84
+ expect(queryByText(/Information/i)).toBeInTheDocument()
85
+ );
88
86
  expect(container).toMatchSnapshot();
89
87
  });
90
88
 
91
89
  it("calculate aliases when not informed", async () => {
92
- const props = {
93
- ...newRuleImplementationProps,
94
- };
95
90
  const { container, queryByText } = render(
96
- <NewRuleImplementationComponent {...props} />,
91
+ <NewRuleImplementationComponent {...newRuleImplementationProps} />,
97
92
  renderOpts
98
93
  );
99
94
  await waitFor(() => expect(queryByText(/lazy/i)).not.toBeInTheDocument());
@@ -109,6 +104,7 @@ describe("<NewRuleImplementation> NewRuleImplementation doSubmit", () => {
109
104
 
110
105
  const renderOptsImplementationEdit = {
111
106
  mocks: [
107
+ functionsMock,
112
108
  multipleTemplatesMock({
113
109
  scope: "ri",
114
110
  domainIds: [2],
@@ -116,13 +112,6 @@ describe("<NewRuleImplementation> NewRuleImplementation doSubmit", () => {
116
112
  domainsMock,
117
113
  domainMock,
118
114
  ],
119
- messages: {
120
- en: {
121
- ...defaultMessages.en,
122
- // This is in td-web
123
- "filtersGrid.field.modifier.cast_as_date": "Cast as date",
124
- },
125
- },
126
115
  state: ruleImplementationLoaderGlobalState,
127
116
  fallback: "lazy",
128
117
  dispatch,
@@ -1614,7 +1614,7 @@ export const newRuleImplementationProps = {
1614
1614
  modifiers: [
1615
1615
  {
1616
1616
  name: "cast_as_date",
1617
- cast_as: "date",
1617
+ type: "date",
1618
1618
  params: [
1619
1619
  {
1620
1620
  name: "format",
@@ -752,7 +752,7 @@ const ruleImplementationOperators = {
752
752
  modifiers: [
753
753
  {
754
754
  name: "cast_as_date",
755
- cast_as: "date",
755
+ type: "date",
756
756
  params: [
757
757
  {
758
758
  name: "format",
@@ -1,7 +1,8 @@
1
- import { getOr } from "lodash/fp";
1
+ import { getOr, isEmpty } from "lodash/fp";
2
+ import PropTypes from "prop-types";
2
3
  import React from "react";
3
4
  import { useIntl } from "react-intl";
4
- import { Form, Icon } from "semantic-ui-react";
5
+ import { Form, Icon, Segment } from "semantic-ui-react";
5
6
 
6
7
  export default function FieldModifier({
7
8
  modifier,
@@ -12,40 +13,56 @@ export default function FieldModifier({
12
13
  const { formatMessage } = useIntl();
13
14
 
14
15
  return (
15
- <div className={"flex-row-align-end"}>
16
- <Form.Field>
17
- <label>
18
- {formatMessage({ id: `filtersGrid.field.modifier.${modifier.name}` })}
19
- </label>
20
- {getOr(
21
- [],
22
- "params"
23
- )(modifier).map((param, key) => (
24
- <input
25
- key={key}
26
- placeholder={formatMessage({
27
- id: `filtersGrid.field.modifier.${modifier.name}.${param.name}`,
28
- })}
29
- value={getOr("", `params.${param.name}`)(value)}
30
- onChange={({ target }) => {
31
- onChange({
32
- ...value,
33
- params: {
34
- ...getOr({}, "params")(value),
35
- [param.name]: target.value,
36
- },
37
- });
38
- }}
16
+ <Form.Field className={"flex-column-align-end"}>
17
+ <label>
18
+ {formatMessage({ id: `filtersGrid.field.modifier.${modifier.name}` })}
19
+ {removable ? (
20
+ <Icon
21
+ name="delete"
22
+ className="selectable force-margin-bottom"
23
+ onClick={() => onChange(null)}
39
24
  />
40
- ))}
41
- </Form.Field>
42
- {removable && (
43
- <Icon
44
- name="x"
45
- className="selectable force-margin-bottom"
46
- onClick={() => onChange(null)}
47
- />
25
+ ) : null}
26
+ </label>
27
+ {isEmpty(modifier?.params) ? null : (
28
+ <Segment>
29
+ {getOr(
30
+ [],
31
+ "params"
32
+ )(modifier).map((param, key) => (
33
+ <>
34
+ <label>
35
+ {formatMessage({
36
+ id: `filtersGrid.field.modifier.${modifier.name}.${param.name}`,
37
+ })}
38
+ </label>
39
+ <input
40
+ key={key}
41
+ placeholder={formatMessage({
42
+ id: `filtersGrid.field.modifier.${modifier.name}.${param.name}`,
43
+ })}
44
+ value={getOr("", `params.${param.name}`)(value)}
45
+ onChange={({ target }) => {
46
+ onChange({
47
+ ...value,
48
+ params: {
49
+ ...getOr({}, "params")(value),
50
+ [param.name]: target.value,
51
+ },
52
+ });
53
+ }}
54
+ />
55
+ </>
56
+ ))}
57
+ </Segment>
48
58
  )}
49
- </div>
59
+ </Form.Field>
50
60
  );
51
61
  }
62
+
63
+ FieldModifier.propTypes = {
64
+ modifier: PropTypes.object,
65
+ value: PropTypes.object,
66
+ onChange: PropTypes.func,
67
+ removable: PropTypes.bool,
68
+ };
@@ -107,6 +107,7 @@ export const FiltersField = ({
107
107
  case "field":
108
108
  case "field_list":
109
109
  const structureFields = getStructureFields(parentStructures);
110
+ const isFieldList = value_type === "field_list";
110
111
  return value_type_filter == "any" ? (
111
112
  <StructureSelectorInputField
112
113
  active={active}
@@ -128,15 +129,17 @@ export const FiltersField = ({
128
129
  ) : (
129
130
  <>
130
131
  <StructureFieldsDropdown
131
- multiple={value_type === "field_list"}
132
+ multiple={isFieldList}
132
133
  label={label}
133
134
  inline={false}
134
135
  parentStructures={parentStructures}
135
136
  structureFields={structureFields}
136
- typeCastModifiers={typeCastModifiers}
137
- filters={
138
- value_type === "field_list" ? null : { field_type: [fieldType] }
137
+ typeCastModifiers={
138
+ isFieldList
139
+ ? _.filter(({ params }) => _.isEmpty(params))(typeCastModifiers)
140
+ : typeCastModifiers
139
141
  }
142
+ filters={{ field_type: [fieldType] }}
140
143
  onSelectField={(value, modifier) => {
141
144
  onChange(
142
145
  null,
@@ -34,9 +34,9 @@ export const FiltersFormGroup = ({
34
34
  const structureFieldType = clause?.structure?.field_type;
35
35
  const modifiers = _.path(`${structureFieldType}.modifiers`)(operators);
36
36
  const modifierValue = clause?.modifier;
37
- const modifier = _.find({ name: modifierValue?.name })(modifiers);
37
+ const selectedModifier = _.find({ name: modifierValue?.name })(modifiers);
38
38
 
39
- const fieldType = modifier?.cast_as || structureFieldType;
39
+ const fieldType = selectedModifier?.type || structureFieldType;
40
40
  const nestedCondition = !_.isEmpty(siblings);
41
41
  const structureFields = getStructureFields(parentStructures);
42
42
 
@@ -70,7 +70,9 @@ export const FiltersFormGroup = ({
70
70
  />
71
71
  )}
72
72
  </Form.Field>
73
- {clause?.structure && !_.isEmpty(modifiers) && (
73
+ {clause?.structure &&
74
+ !_.isEmpty(modifiers) &&
75
+ _.isEmpty(selectedModifier) ? (
74
76
  <Dropdown
75
77
  className={"icon-dropdown-margin"}
76
78
  size="mini"
@@ -81,9 +83,9 @@ export const FiltersFormGroup = ({
81
83
  <Dropdown.Item
82
84
  key={key}
83
85
  icon={
84
- modifier.cast_as
86
+ modifier.type
85
87
  ? formatMessage({
86
- id: `field_type.icon.${modifier.cast_as}`,
88
+ id: `field_type.icon.${modifier.type}`,
87
89
  defaultMessage: "hashtag",
88
90
  })
89
91
  : null
@@ -98,11 +100,11 @@ export const FiltersFormGroup = ({
98
100
  ))}
99
101
  </Dropdown.Menu>
100
102
  </Dropdown>
101
- )}
103
+ ) : null}
102
104
  </div>
103
- {modifier && (
105
+ {selectedModifier && (
104
106
  <FieldModifier
105
- modifier={modifier}
107
+ modifier={selectedModifier}
106
108
  value={modifierValue}
107
109
  onChange={(value) => onModifierChange(index, value)}
108
110
  removable
@@ -1,8 +1,6 @@
1
1
  import _ from "lodash/fp";
2
2
  import React from "react";
3
3
  import PropTypes from "prop-types";
4
- import { FormattedMessage } from "react-intl";
5
- import { Grid, Icon, Segment } from "semantic-ui-react";
6
4
  import { dropAt, replaceAt } from "@truedat/core/services/arrays";
7
5
  import { FiltersGrid } from "./FiltersGrid";
8
6
 
@@ -71,7 +71,7 @@ export default (operators, type, nested, scope, formatMessage) => {
71
71
  _.map((m) => ({ ...m, sourceType: key }))(value.modifiers || [])
72
72
  ),
73
73
  _.flatten,
74
- _.filter(({ cast_as }) => cast_as === type)
74
+ _.filter({ type: type })
75
75
  )(operators);
76
76
 
77
77
  return {
@@ -1,296 +0,0 @@
1
- import _ from "lodash/fp";
2
- import { createSelector } from "reselect";
3
-
4
- const defaultOperators = {
5
- any: {
6
- operators: [
7
- { name: "unique", scope: "validation" },
8
- { name: "unique", value_type: "field_list" },
9
- { name: "not_empty" },
10
- { name: "empty" },
11
- {
12
- group: "references",
13
- name: "references",
14
- value_type: "field",
15
- value_type_filter: "any",
16
- scope: "validation",
17
- },
18
- {
19
- group: "references",
20
- name: "not_references",
21
- value_type: "field",
22
- value_type_filter: "any",
23
- scope: "validation",
24
- },
25
- ],
26
- },
27
- boolean: {
28
- operators: [{ name: "is_true" }, { name: "is_false" }],
29
- },
30
- number: {
31
- operators: [
32
- { group: "eq", name: "eq", value_type: "number" },
33
- { group: "eq", name: "eq", value_type: "field" },
34
- { group: "not_eq", name: "not_eq", value_type: "number" },
35
- { group: "not_eq", name: "not_eq", value_type: "field" },
36
- { group: "gt", name: "gt", value_type: "number" },
37
- { group: "gt", name: "gt", value_type: "field" },
38
- { group: "lt", name: "lt", value_type: "number" },
39
- { group: "lt", name: "lt", value_type: "field" },
40
- { group: "gte", name: "gte", value_type: "number" },
41
- { group: "gte", name: "gte", value_type: "field" },
42
- { group: "lte", name: "lte", value_type: "number" },
43
- { group: "lte", name: "lte", value_type: "field" },
44
- {
45
- group: "between",
46
- name: "between",
47
- value_type: "number",
48
- arity: 2,
49
- },
50
- {
51
- group: "between",
52
- name: "between",
53
- value_type: "field",
54
- arity: 2,
55
- },
56
- {
57
- group: "format",
58
- name: "number_of_decimals",
59
- value_type: "number",
60
- scope: "validation",
61
- },
62
- ],
63
- },
64
- string: {
65
- operators: [
66
- { group: "eq", name: "eq", value_type: "string" },
67
- { group: "eq", name: "eq", value_type: "field" },
68
- { group: "not_eq", name: "not_eq", value_type: "string" },
69
- { group: "not_eq", name: "not_eq", value_type: "field" },
70
- { group: "length", name: "length_gt", value_type: "number" },
71
- { group: "length", name: "length_lt", value_type: "number" },
72
- {
73
- group: "length",
74
- name: "length_eq",
75
- value_type: "number",
76
- scope: "validation",
77
- },
78
- {
79
- group: "length",
80
- name: "length_not_eq",
81
- value_type: "number",
82
- scope: "validation",
83
- },
84
- {
85
- group: "length",
86
- name: "length_gte",
87
- value_type: "number",
88
- },
89
- {
90
- group: "length",
91
- name: "length_lte",
92
- value_type: "number",
93
- },
94
- {
95
- group: "length",
96
- name: "length_between",
97
- value_type: "number",
98
- arity: 2,
99
- },
100
- { name: "contains", value_type: "string" },
101
- {
102
- name: "not_contains",
103
- value_type: "string",
104
- },
105
-
106
- {
107
- name: "starts_with",
108
- value_type: "string",
109
- },
110
- { name: "ends_with", value_type: "string" },
111
- {
112
- name: "in_list",
113
- value_type: "string_list",
114
- },
115
- {
116
- name: "not_in_list",
117
- value_type: "string_list",
118
- },
119
- {
120
- group: "format",
121
- name: "number_of_decimals",
122
- value_type: "number",
123
- scope: "validation",
124
- },
125
- {
126
- name: "format_of",
127
- group: "format",
128
- value_type: "string",
129
- fixed_values: [
130
- "email",
131
- "phone",
132
- "number",
133
- "decimal",
134
- "date",
135
- "dni",
136
- "dni_or_cif",
137
- "season",
138
- "timestamp",
139
- ],
140
- scope: "validation",
141
- },
142
- {
143
- name: "regex_format",
144
- value_type: "string",
145
- },
146
- ],
147
- },
148
- date: {
149
- operators: [
150
- { group: "eq", name: "eq", value_type: "date" },
151
- { group: "eq", name: "eq", value_type: "field" },
152
- { group: "not_eq", name: "not_eq", value_type: "date" },
153
- { group: "not_eq", name: "not_eq", value_type: "field" },
154
- { group: "gt", name: "gt", value_type: "date" },
155
- { group: "gt", name: "gt", value_type: "field" },
156
- { group: "gte", name: "gte", value_type: "date" },
157
- { group: "gte", name: "gte", value_type: "field" },
158
- { group: "lt", name: "lt", value_type: "date" },
159
- { group: "lt", name: "lt", value_type: "field" },
160
- { group: "lte", name: "lte", value_type: "date" },
161
- { group: "lte", name: "lte", value_type: "field" },
162
- {
163
- name: "between",
164
- value_type: "date",
165
- arity: 2,
166
- },
167
- {
168
- group: "eq",
169
- name: "eq_var",
170
- value_type: "string",
171
- fixed_values: ["D-0", "D-1", "M-0", "M-1", "M-2", "Y-0", "Y-1"],
172
- },
173
- {
174
- group: "lt",
175
- name: "lt_var",
176
- value_type: "string",
177
- fixed_values: ["D-0", "D-1", "M-0", "M-1", "M-2", "Y-0", "Y-1"],
178
- },
179
- {
180
- group: "lte",
181
- name: "lte_var",
182
- value_type: "string",
183
- fixed_values: ["D-0", "D-1", "M-0", "M-1", "M-2", "Y-0", "Y-1"],
184
- },
185
- {
186
- group: "gt",
187
- name: "gt_var",
188
- value_type: "string",
189
- fixed_values: ["D-0", "D-1", "M-0", "M-1", "M-2", "Y-0", "Y-1"],
190
- },
191
- {
192
- group: "gte",
193
- name: "gte_var",
194
- value_type: "string",
195
- fixed_values: ["D-0", "D-1", "M-0", "M-1", "M-2", "Y-0", "Y-1"],
196
- },
197
- {
198
- name: "variation_on_count",
199
- value_type: "string",
200
- fixed_values: ["D-0", "D-1", "M-0", "M-1", "M-2", "Y-0", "Y-1"],
201
- scope: "validation",
202
- arity: 2,
203
- },
204
- ],
205
- },
206
- timestamp: {
207
- operators: [
208
- { group: "eq", name: "eq", value_type: "timestamp" },
209
- { group: "eq", name: "eq", value_type: "field" },
210
- { group: "not_eq", name: "not_eq", value_type: "timestamp" },
211
- { group: "not_eq", name: "not_eq", value_type: "field" },
212
- { group: "gt", name: "gt", value_type: "timestamp" },
213
- { group: "gt", name: "gt", value_type: "field" },
214
- { group: "gte", name: "gte", value_type: "timestamp" },
215
- { group: "gte", name: "gte", value_type: "field" },
216
- { group: "lt", name: "lt", value_type: "timestamp" },
217
- { group: "lt", name: "lt", value_type: "field" },
218
- { group: "lte", name: "lte", value_type: "timestamp" },
219
- { group: "lte", name: "lte", value_type: "field" },
220
- {
221
- name: "between",
222
- value_type: "timestamp",
223
- arity: 2,
224
- },
225
- {
226
- group: "eq",
227
- name: "eq_var",
228
- value_type: "string",
229
- fixed_values: ["D-0", "D-1", "M-0", "M-1", "M-2", "Y-0", "Y-1"],
230
- },
231
- {
232
- group: "not_eq",
233
- name: "not_eq_var",
234
- value_type: "string",
235
- fixed_values: ["D-0", "D-1", "M-0", "M-1", "M-2", "Y-0", "Y-1"],
236
- },
237
- {
238
- group: "lt",
239
- name: "lt_var",
240
- value_type: "string",
241
- fixed_values: ["D-0", "D-1", "M-0", "M-1", "M-2", "Y-0", "Y-1"],
242
- },
243
- {
244
- group: "lte",
245
- name: "lte_var",
246
- value_type: "string",
247
- fixed_values: ["D-0", "D-1", "M-0", "M-1", "M-2", "Y-0", "Y-1"],
248
- },
249
- {
250
- group: "gt",
251
- name: "gt_var",
252
- value_type: "string",
253
- fixed_values: ["D-0", "D-1", "M-0", "M-1", "M-2", "Y-0", "Y-1"],
254
- },
255
- {
256
- group: "gte",
257
- name: "gte_var",
258
- value_type: "string",
259
- fixed_values: ["D-0", "D-1", "M-0", "M-1", "M-2", "Y-0", "Y-1"],
260
- },
261
- {
262
- name: "variation_on_count",
263
- value_type: "string",
264
- fixed_values: ["D-0", "D-1", "M-0", "M-1", "M-2", "Y-0", "Y-1"],
265
- scope: "validation",
266
- arity: 2,
267
- },
268
- ],
269
- },
270
- };
271
-
272
- const ruleImplementationOperators = (state) =>
273
- state.ruleImplementationOperators;
274
-
275
- export const getRuleImplementationOperators = createSelector(
276
- [ruleImplementationOperators],
277
- (operators) =>
278
- _.flow(
279
- _.defaultTo(defaultOperators),
280
- _.toPairs,
281
- _.map(([key, value]) =>
282
- _.map((o) => ({ category: key, ...o }))(value.operators)
283
- ),
284
- _.flatten,
285
- _.map.convert({ cap: false })((o, i) => ({ id: i, ...o })),
286
- _.groupBy("category"),
287
- _.reduce.convert({ cap: false })(
288
- (acc, value, key) =>
289
- _.set(key, {
290
- operators: _.map((o) => _.omit(["category"])(o))(value),
291
- modifiers: _.propOr([], `${key}.modifiers`)(operators),
292
- })(acc),
293
- {}
294
- )
295
- )(operators)
296
- );