@truedat/dq 7.11.0 → 7.11.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 (52) hide show
  1. package/package.json +3 -3
  2. package/src/api.js +12 -0
  3. package/src/components/ImplementationSearchResults.js +24 -42
  4. package/src/components/ImplementationUploadJobBreadcrumbs.js +25 -0
  5. package/src/components/Implementations.js +31 -17
  6. package/src/components/ImplementationsRoutes.js +9 -0
  7. package/src/components/ImplementationsUploadButton.js +38 -50
  8. package/src/components/ImplementationsUploadJob.js +217 -0
  9. package/src/components/ImplementationsUploadJobs.js +128 -0
  10. package/src/components/RuleFormImplementations.js +29 -10
  11. package/src/components/RuleImplementationActions.js +10 -20
  12. package/src/components/RuleImplementationsActions.js +15 -37
  13. package/src/components/RuleImplementationsDownload.js +26 -31
  14. package/src/components/RuleImplementationsDownloadXlsx.js +47 -0
  15. package/src/components/RuleImplementationsLabelResults.js +30 -39
  16. package/src/components/RuleImplementationsOptions.js +5 -3
  17. package/src/components/RuleImplementationsTable.js +7 -3
  18. package/src/components/RuleRoutes.js +1 -4
  19. package/src/components/SimpleRuleImplementationsTable.js +68 -0
  20. package/src/components/__tests__/ImplementationSearchResults.spec.js +32 -4
  21. package/src/components/__tests__/ImplementationUploadJobBreadcrumbs.spec.js +28 -0
  22. package/src/components/__tests__/Implementations.spec.js +43 -0
  23. package/src/components/__tests__/ImplementationsUploadButton.spec.js +67 -40
  24. package/src/components/__tests__/ImplementationsUploadJob.spec.js +112 -0
  25. package/src/components/__tests__/ImplementationsUploadJobs.spec.js +60 -0
  26. package/src/components/__tests__/RuleImplementationsActions.spec.js +71 -56
  27. package/src/components/__tests__/RuleImplementationsOptions.spec.js +28 -3
  28. package/src/components/__tests__/RuleImplementationsTable.spec.js +24 -0
  29. package/src/components/__tests__/__snapshots__/ImplementationSearchResults.spec.js.snap +113 -46
  30. package/src/components/__tests__/__snapshots__/ImplementationUploadJobBreadcrumbs.spec.js.snap +42 -0
  31. package/src/components/__tests__/__snapshots__/Implementations.spec.js.snap +125 -24
  32. package/src/components/__tests__/__snapshots__/RuleImplementationsActions.spec.js.snap +4 -8
  33. package/src/components/__tests__/__snapshots__/RuleImplementationsOptions.spec.js.snap +5 -8
  34. package/src/components/__tests__/implementationsUploadJobParser.spec.js +105 -0
  35. package/src/components/implementationsUploadJobParser.js +276 -0
  36. package/src/components/index.js +0 -2
  37. package/src/hooks/useImplementations.js +80 -0
  38. package/src/reducers/index.js +2 -0
  39. package/src/reducers/ruleImplementationSelectedFilter.js +1 -1
  40. package/src/reducers/ruleImplementationsDownloadingXlsx.js +14 -0
  41. package/src/routines.js +3 -0
  42. package/src/sagas/downloadRuleImplementationsXlsx.js +52 -0
  43. package/src/sagas/index.js +3 -0
  44. package/src/components/RuleImplementationFilters.js +0 -25
  45. package/src/components/RuleImplementationSelectedFilters.js +0 -99
  46. package/src/components/RuleImplementationsFromRuleLoader.js +0 -60
  47. package/src/components/RuleImplementationsPagination.js +0 -18
  48. package/src/components/RuleImplementationsSearch.js +0 -39
  49. package/src/components/__tests__/RuleImplementationsFromRuleLoader.spec.js +0 -63
  50. package/src/components/__tests__/RuleImplementationsSearch.spec.js +0 -29
  51. package/src/components/__tests__/__snapshots__/RuleImplementationsFromRuleLoader.spec.js.snap +0 -3
  52. package/src/components/__tests__/__snapshots__/RuleImplementationsSearch.spec.js.snap +0 -50
@@ -27,12 +27,14 @@ exports[`<Implementations /> matches the latest snapshot 1`] = `
27
27
  class="ui bottom attached segment"
28
28
  >
29
29
  <div
30
+ border="1px red"
30
31
  class="ui bottom attached segment"
31
32
  >
32
33
  <div
33
34
  style="float: right;"
34
35
  >
35
36
  <div
37
+ aria-disabled="false"
36
38
  aria-expanded="false"
37
39
  class="ui floating dropdown button icon group-actions button-update"
38
40
  role="listbox"
@@ -46,8 +48,8 @@ exports[`<Implementations /> matches the latest snapshot 1`] = `
46
48
  class="menu transition left"
47
49
  >
48
50
  <div
49
- aria-disabled="true"
50
- class="disabled item"
51
+ aria-disabled="false"
52
+ class="item"
51
53
  role="option"
52
54
  >
53
55
  <i
@@ -55,15 +57,11 @@ exports[`<Implementations /> matches the latest snapshot 1`] = `
55
57
  class="download icon"
56
58
  />
57
59
  <span>
58
- implementations.actions.download.tooltip
60
+ implementations.actions.downloadXlsx.tooltip
59
61
  </span>
60
- <p
61
- class="menu-item-description"
62
- >
63
- implementations.actions.download.empty
64
- </p>
65
62
  </div>
66
63
  <div
64
+ aria-disabled="false"
67
65
  class="item"
68
66
  role="option"
69
67
  >
@@ -83,15 +81,14 @@ exports[`<Implementations /> matches the latest snapshot 1`] = `
83
81
  <div
84
82
  class="ui action left icon input"
85
83
  >
86
- <input
87
- placeholder="implementations.search.placeholder"
88
- type="text"
89
- value="foo"
90
- />
91
84
  <i
92
85
  aria-hidden="true"
93
86
  class="search link icon"
94
87
  />
88
+ <input
89
+ placeholder="search.placeholder"
90
+ type="text"
91
+ />
95
92
  <div
96
93
  aria-expanded="false"
97
94
  class="ui button floating labeled scrolling dropdown icon"
@@ -135,19 +132,123 @@ exports[`<Implementations /> matches the latest snapshot 1`] = `
135
132
  >
136
133
  ruleImplementations.retrieved.results
137
134
  </div>
138
- <h4
139
- class="ui header"
135
+ <div
136
+ class="implementations-table-overflow"
140
137
  >
141
- <i
142
- aria-hidden="true"
143
- class="search icon"
144
- />
145
- <div
146
- class="content"
138
+ <table
139
+ class="ui sortable table"
147
140
  >
148
- ruleImplementations.search.results.empty
149
- </div>
150
- </h4>
141
+ <thead
142
+ class=""
143
+ >
144
+ <tr
145
+ class=""
146
+ >
147
+ <th
148
+ class="two wide"
149
+ >
150
+ ruleImplementations.props.implementation_key
151
+ </th>
152
+ <th
153
+ class="two wide"
154
+ >
155
+ ruleImplementations.props.rule
156
+ </th>
157
+ <th
158
+ class="two wide ascending sorted disabled"
159
+ >
160
+ ruleImplementations.props.business_concepts
161
+ </th>
162
+ <th
163
+ class="two wide"
164
+ >
165
+ ruleImplementations.props.last_execution_at
166
+ </th>
167
+ <th
168
+ class="two wide"
169
+ >
170
+ ruleImplementations.props.result_type
171
+ </th>
172
+ <th
173
+ class="one wide"
174
+ >
175
+ ruleImplementations.props.minimum
176
+ </th>
177
+ <th
178
+ class="one wide"
179
+ >
180
+ ruleImplementations.props.goal
181
+ </th>
182
+ <th
183
+ class="two wide"
184
+ >
185
+ ruleImplementations.props.result
186
+ </th>
187
+ <th
188
+ class=""
189
+ >
190
+ ruleImplementations.props.inserted_at
191
+ </th>
192
+ <th
193
+ class=""
194
+ >
195
+ ruleImplementations.props.updated_at
196
+ </th>
197
+ </tr>
198
+ </thead>
199
+ <tbody
200
+ class=""
201
+ >
202
+ <tr
203
+ class=""
204
+ >
205
+ <td
206
+ class=""
207
+ >
208
+ <a
209
+ data-discover="true"
210
+ href="/implementations/1330"
211
+ >
212
+ bar_impl
213
+ </a>
214
+ </td>
215
+ <td
216
+ class=""
217
+ />
218
+ <td
219
+ class=""
220
+ />
221
+ <td
222
+ class=""
223
+ />
224
+ <td
225
+ class=""
226
+ >
227
+ ruleImplementations.props.result_type.percentage
228
+ </td>
229
+ <td
230
+ class="right aligned"
231
+ >
232
+ 10%
233
+ </td>
234
+ <td
235
+ class="right aligned"
236
+ >
237
+ 20%
238
+ </td>
239
+ <td
240
+ class="center aligned"
241
+ />
242
+ <td
243
+ class=""
244
+ />
245
+ <td
246
+ class=""
247
+ />
248
+ </tr>
249
+ </tbody>
250
+ </table>
251
+ </div>
151
252
  </div>
152
253
  </div>
153
254
  </div>
@@ -58,8 +58,8 @@ exports[`<RuleImplementationsActions /> matches the latest snapshot 1`] = `
58
58
  class="menu transition left"
59
59
  >
60
60
  <div
61
- aria-disabled="true"
62
- class="disabled item"
61
+ aria-disabled="false"
62
+ class="item"
63
63
  role="option"
64
64
  >
65
65
  <i
@@ -67,15 +67,11 @@ exports[`<RuleImplementationsActions /> matches the latest snapshot 1`] = `
67
67
  class="download icon"
68
68
  />
69
69
  <span>
70
- implementations.actions.download.tooltip
70
+ implementations.actions.downloadXlsx.tooltip
71
71
  </span>
72
- <p
73
- class="menu-item-description"
74
- >
75
- implementations.actions.download.empty
76
- </p>
77
72
  </div>
78
73
  <div
74
+ aria-disabled="false"
79
75
  class="item"
80
76
  role="option"
81
77
  >
@@ -3,6 +3,7 @@
3
3
  exports[`<RuleImplementationsOptions /> matches the latest snapshot 1`] = `
4
4
  <div>
5
5
  <div
6
+ aria-disabled="false"
6
7
  aria-expanded="false"
7
8
  class="ui floating dropdown button icon group-actions button-update"
8
9
  role="listbox"
@@ -16,8 +17,8 @@ exports[`<RuleImplementationsOptions /> matches the latest snapshot 1`] = `
16
17
  class="menu transition left"
17
18
  >
18
19
  <div
19
- aria-disabled="true"
20
- class="disabled item"
20
+ aria-disabled="false"
21
+ class="item"
21
22
  role="option"
22
23
  >
23
24
  <i
@@ -25,15 +26,11 @@ exports[`<RuleImplementationsOptions /> matches the latest snapshot 1`] = `
25
26
  class="download icon"
26
27
  />
27
28
  <span>
28
- implementations.actions.download.tooltip
29
+ implementations.actions.downloadXlsx.tooltip
29
30
  </span>
30
- <p
31
- class="menu-item-description"
32
- >
33
- implementations.actions.download.empty
34
- </p>
35
31
  </div>
36
32
  <div
33
+ aria-disabled="false"
37
34
  class="item"
38
35
  role="option"
39
36
  >
@@ -0,0 +1,105 @@
1
+ import { render } from "@truedat/test/render";
2
+ import { StatusPill, ResponseCell } from "../implementationsUploadJobParser";
3
+
4
+ describe("<StatusPill />", () => {
5
+ it("renders with correct color based on status", async () => {
6
+ const statuses = ["COMPLETED", "FAILED", "ERROR", "INFO", "OTHER"];
7
+ const expectedColors = ["green", "red", "red", "blue", "grey"];
8
+
9
+ statuses.forEach((status, index) => {
10
+ const rendered = render(<StatusPill status={status} />);
11
+ const label = rendered.container.querySelector(".ui.label");
12
+ expect(label).toHaveClass(expectedColors[index]);
13
+ expect(
14
+ rendered.getByText(
15
+ new RegExp(`implementations.bulkUpload.event.status.${status}`, "i")
16
+ )
17
+ ).toBeInTheDocument();
18
+ });
19
+ });
20
+ });
21
+
22
+ describe("<ResponseCell />", () => {
23
+ it("returns null when response is empty", () => {
24
+ const rendered = render(
25
+ <ResponseCell response={null} status="COMPLETED" />
26
+ );
27
+ expect(rendered.container.firstChild).toBeNull();
28
+
29
+ const rendered2 = render(<ResponseCell response={{}} status="COMPLETED" />);
30
+ expect(rendered2.container.firstChild).toBeNull();
31
+ });
32
+
33
+ it("renders FAILED status with message", () => {
34
+ const response = { message: "missing_required_headers" };
35
+ const rendered = render(
36
+ <ResponseCell response={response} status="FAILED" />
37
+ );
38
+ expect(
39
+ rendered.getByText(
40
+ /implementations.bulkUpload.error.missing_required_headers/i
41
+ )
42
+ ).toBeInTheDocument();
43
+ });
44
+
45
+ it("renders ERROR status with details", () => {
46
+ const response = {
47
+ type: "missing_required_headers",
48
+ details: {
49
+ missing_headers: ["header1", "header2"],
50
+ },
51
+ };
52
+ const rendered = render(
53
+ <ResponseCell response={response} status="ERROR" />
54
+ );
55
+ expect(
56
+ rendered.getByText(
57
+ /implementations.bulkUpload.error.missing_required_headers/i
58
+ )
59
+ ).toBeInTheDocument();
60
+ expect(rendered.getByText(/header1, header2/i)).toBeInTheDocument();
61
+ });
62
+
63
+ it("renders COMPLETED status with summary", () => {
64
+ const response = {
65
+ insert_count: 2,
66
+ update_count: 1,
67
+ error_count: 0,
68
+ };
69
+ const rendered = render(
70
+ <ResponseCell response={response} status="COMPLETED" />
71
+ );
72
+ expect(
73
+ rendered.getByText(/implementations.bulkUpload.result.summary.created/i)
74
+ ).toBeInTheDocument();
75
+ expect(
76
+ rendered.getByText(/implementations.bulkUpload.result.summary.updated/i)
77
+ ).toBeInTheDocument();
78
+ });
79
+
80
+ it("renders INFO status with implementation details", () => {
81
+ const response = {
82
+ type: "implementation_updated",
83
+ details: {
84
+ id: 123,
85
+ changes: {
86
+ name: "new name",
87
+ },
88
+ },
89
+ };
90
+ const rendered = render(<ResponseCell response={response} status="INFO" />);
91
+ expect(
92
+ rendered.getByText(
93
+ /implementations.bulkUpload.info.implementation_updated/i
94
+ )
95
+ ).toBeInTheDocument();
96
+ });
97
+
98
+ it("renders default case for unknown status", () => {
99
+ const response = "some text";
100
+ const rendered = render(
101
+ <ResponseCell response={response} status="UNKNOWN" />
102
+ );
103
+ expect(rendered.getByText(/some text/i)).toBeInTheDocument();
104
+ });
105
+ });
@@ -0,0 +1,276 @@
1
+ import _ from "lodash/fp";
2
+ import { useState } from "react";
3
+ import { FormattedMessage, useIntl } from "react-intl";
4
+ import { Label } from "semantic-ui-react";
5
+ import { RichTextEditor } from "@truedat/core/components";
6
+
7
+ import RuleImplementationLink from "./RuleImplementationLink";
8
+
9
+ export const StatusPill = ({ status }) => (
10
+ <Label
11
+ color={_.cond([
12
+ [_.eq("COMPLETED"), _.constant("green")],
13
+ [_.eq("FAILED"), _.constant("red")],
14
+ [_.eq("ERROR"), _.constant("red")],
15
+ [_.eq("INFO"), _.constant("blue")],
16
+ [_.stubTrue, _.constant("grey")],
17
+ ])(status)}
18
+ size="small"
19
+ >
20
+ <FormattedMessage
21
+ id={`implementations.bulkUpload.event.status.${status}`}
22
+ />
23
+ </Label>
24
+ );
25
+
26
+ export const ResponseCell = ({ response, status }) => {
27
+ if (!response || (_.isObject(response) && _.isEmpty(response))) return null;
28
+
29
+ switch (status) {
30
+ case "FAILED":
31
+ return (
32
+ <FormattedMessage
33
+ id={`implementations.bulkUpload.error.${response.message}`}
34
+ />
35
+ );
36
+ case "ERROR":
37
+ return <ErrorDetail response={response} />;
38
+ case "COMPLETED":
39
+ return <CompletedDetail response={response} />;
40
+ case "INFO":
41
+ return <InfoDetail response={response} />;
42
+ default:
43
+ return (
44
+ <pre
45
+ style={{
46
+ whiteSpace: "pre-wrap",
47
+ wordBreak: "break-all",
48
+ margin: 0,
49
+ }}
50
+ >
51
+ {typeof response === "string"
52
+ ? response
53
+ : JSON.stringify(response, null, 2)}
54
+ </pre>
55
+ );
56
+ }
57
+ };
58
+
59
+ const SheetAndLine = ({ response }) => (
60
+ <Label size="small">
61
+ <span>{response.sheet}</span>
62
+ {response.row_number ? (
63
+ <span>
64
+ {" "}
65
+ -{" "}
66
+ <FormattedMessage id="implementations.bulkUpload.result.prop.row_number" />
67
+ : {response.row_number}
68
+ </span>
69
+ ) : null}
70
+ </Label>
71
+ );
72
+
73
+ const CellHeader = ({ header, response }) => (
74
+ <div style={{ display: "flex", justifyContent: "space-between" }}>
75
+ <b>
76
+ <FormattedMessage id={header} />
77
+ </b>
78
+ <div>
79
+ <SheetAndLine response={response} />
80
+ </div>
81
+ </div>
82
+ );
83
+
84
+ const ErrorDetail = ({ response }) => {
85
+ const { formatMessage } = useIntl();
86
+
87
+ if (!response || !response.type) {
88
+ return null;
89
+ }
90
+ const { type } = response;
91
+ const messagePrefix = "implementations.bulkUpload.detail";
92
+
93
+ const detailBuilders = {
94
+ missing_required_headers: (details) => [
95
+ [
96
+ formatMessage({ id: `${messagePrefix}.headers` }),
97
+ details.missing_headers?.join(", "),
98
+ ],
99
+ ],
100
+ invalid_template_name: (details) => [
101
+ [
102
+ formatMessage({ id: `${messagePrefix}.templateName` }),
103
+ details.template_name,
104
+ ],
105
+ ],
106
+ invalid_domain_external_id: (details) => [
107
+ [
108
+ formatMessage({ id: `${messagePrefix}.domainExternalId` }),
109
+ details.domain_external_id,
110
+ ],
111
+ ],
112
+ invalid_associated_rule: (details) => [
113
+ [formatMessage({ id: `${messagePrefix}.ruleName` }), details.rule_name],
114
+ ],
115
+ implementation_creation_error: (details) =>
116
+ details?.map(([field, [error]]) => [field, error]),
117
+ };
118
+
119
+ const detailBuilder = _.propOr(() => {}, type)(detailBuilders);
120
+
121
+ return (
122
+ <div>
123
+ <CellHeader
124
+ header={`implementations.bulkUpload.error.${type}`}
125
+ response={response}
126
+ />
127
+
128
+ {response.details
129
+ ? detailBuilder(response.details).map(([key, value], idx) => (
130
+ <div key={idx} style={{ paddingLeft: "10px" }}>
131
+ <span
132
+ style={{
133
+ fontSize: "0.85em",
134
+ fontWeight: "bold",
135
+ paddingRight: "5px",
136
+ }}
137
+ >
138
+ {key}:
139
+ </span>
140
+ {value}
141
+ </div>
142
+ ))
143
+ : null}
144
+ </div>
145
+ );
146
+ };
147
+ const summaryItems = [
148
+ {
149
+ key: "invalid_sheet_count",
150
+ messageId: "implementations.bulkUpload.result.summary.invalid_sheets",
151
+ },
152
+ {
153
+ key: "insert_count",
154
+ messageId: "implementations.bulkUpload.result.summary.created",
155
+ },
156
+ {
157
+ key: "update_count",
158
+ messageId: "implementations.bulkUpload.result.summary.updated",
159
+ },
160
+ {
161
+ key: "unchanged_count",
162
+ messageId: "implementations.bulkUpload.result.summary.unchanged",
163
+ },
164
+ {
165
+ key: "error_count",
166
+ messageId: "implementations.bulkUpload.result.summary.errors",
167
+ },
168
+ ];
169
+ const CompletedDetail = ({ response }) => (
170
+ <span style={{ display: "flex", gap: "5px" }}>
171
+ {_.flow([
172
+ _.filter((item) => _.get(item.key, response) > 0),
173
+ _.map((item) => (
174
+ <span
175
+ key={item.key}
176
+ // style={{
177
+ // border: "1px solid #ccc",
178
+ // padding: "5px",
179
+ // }}
180
+ >
181
+ <FormattedMessage id={item.messageId} />
182
+ {`: ${response[item.key]}`}
183
+ </span>
184
+ )),
185
+ ])(summaryItems)}
186
+ </span>
187
+ );
188
+
189
+ const InfoDetail = ({ response }) =>
190
+ !response || !response.type ? null : (
191
+ <div>
192
+ <CellHeader
193
+ header={`implementations.bulkUpload.info.${response.type}`}
194
+ response={response}
195
+ />
196
+ {response.details ? (
197
+ <div>
198
+ <RuleImplementationLink {...response.details} />{" "}
199
+ </div>
200
+ ) : null}
201
+ <ChangesDetail changes={response?.details?.changes} />
202
+ </div>
203
+ );
204
+ const ChangesDetail = ({
205
+ changes,
206
+ header = "implementations.bulkUpload.result.prop.changes",
207
+ }) => {
208
+ const [isExpanded, setIsExpanded] = useState(false);
209
+ if (!changes) return null;
210
+ const changesList = _.toPairs(changes);
211
+
212
+ return (
213
+ <div>
214
+ <div
215
+ onClick={() => setIsExpanded(!isExpanded)}
216
+ style={{
217
+ cursor: "pointer",
218
+ display: "flex",
219
+ gap: "5px",
220
+ alignItems: "center",
221
+ }}
222
+ >
223
+ <span>{isExpanded ? "▼" : "▶"}</span>
224
+ <span>
225
+ <FormattedMessage id={header} />
226
+ </span>
227
+ <span>({_.size(changesList)}) :</span>
228
+ </div>
229
+ {isExpanded &&
230
+ changesList.map(([key, value]) => (
231
+ <div key={key} style={{ paddingLeft: "10px" }}>
232
+ {key == "df_content" ? (
233
+ <ChangesDetail
234
+ changes={value}
235
+ header={`ruleImplementations.props.${key}`}
236
+ />
237
+ ) : (
238
+ <>
239
+ <span
240
+ style={{
241
+ fontSize: "0.85em",
242
+ fontWeight: "bold",
243
+ paddingRight: "5px",
244
+ }}
245
+ >
246
+ <FormattedMessage
247
+ id={`ruleImplementations.props.${key}`}
248
+ defaultMessage={key}
249
+ />
250
+ :
251
+ </span>
252
+ {formatValue(value)}
253
+ </>
254
+ )}
255
+ </div>
256
+ ))}
257
+ </div>
258
+ );
259
+ };
260
+
261
+ const formatValue = (value) => {
262
+ if (_.has("value")(value)) return formatValue(value.value);
263
+ if (_.isArray(value)) {
264
+ return _.flow(_.map(formatValue), _.join(", "))(value);
265
+ }
266
+ if (_.isObject(value)) {
267
+ if (_.has("document")(value))
268
+ return <RichTextEditor readOnly value={value} />;
269
+ if (_.has("url_value")(value))
270
+ return `[${value.url_name}] (${value.url_value})`;
271
+
272
+ return _.flow(_.keys, _.join(", "))(value);
273
+ }
274
+
275
+ return value;
276
+ };
@@ -12,7 +12,6 @@ import Rule from "./Rule";
12
12
  import RuleForm from "./RuleForm";
13
13
  import RuleFormImplementations from "./RuleFormImplementations";
14
14
  import RuleImplementationEvents from "./RuleImplementationEvents";
15
- import RuleImplementationsFromRuleLoader from "./RuleImplementationsFromRuleLoader";
16
15
  import RuleImplementationsLoader from "./RuleImplementationsLoader";
17
16
  import RuleLoader from "./RuleLoader";
18
17
  import RuleProperties from "./RuleProperties";
@@ -36,7 +35,6 @@ export {
36
35
  RuleFormImplementations,
37
36
  RuleImplementationEvents,
38
37
  RuleImplementationsLoader,
39
- RuleImplementationsFromRuleLoader,
40
38
  RuleLoader,
41
39
  RuleProperties,
42
40
  RuleRow,