@truedat/qx 6.12.2 → 6.12.4
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/package.json +3 -3
- package/src/api.js +2 -0
- package/src/components/common/ResourceSelector.js +12 -2
- package/src/components/common/__tests__/ResourceSelector.spec.js +3 -2
- package/src/components/common/__tests__/__snapshots__/ResourceSelector.spec.js.snap +0 -78
- package/src/components/common/resourceSelectors/DataStructureSelector.js +2 -2
- package/src/components/common/resourceSelectors/DataViewSelector.js +7 -3
- package/src/components/common/resourceSelectors/__tests__/DataViewSelector.spec.js +12 -6
- package/src/components/dataViews/DataViewEditor.js +28 -4
- package/src/components/dataViews/__tests__/DataViewEditor.spec.js +18 -8
- package/src/components/dataViews/__tests__/__snapshots__/DataViewEditor.spec.js.snap +18 -39
- package/src/components/dataViews/__tests__/__snapshots__/Queryable.spec.js.snap +3 -107
- package/src/components/dataViews/__tests__/__snapshots__/Queryables.spec.js.snap +0 -78
- package/src/components/dataViews/queryableProperties/__tests__/__snapshots__/From.spec.js.snap +0 -26
- package/src/components/dataViews/queryableProperties/__tests__/__snapshots__/Join.spec.js.snap +0 -26
- package/src/components/qualityControls/QualityControl.js +1 -1
- package/src/components/qualityControls/QualityControlActions.js +6 -0
- package/src/components/qualityControls/QualityControlEditor.js +45 -9
- package/src/components/qualityControls/QualityControlHeader.js +2 -2
- package/src/components/qualityControls/QualityControlQueryModal.js +83 -0
- package/src/components/qualityControls/QualityControlRoutes.js +0 -1
- package/src/hooks/useQualityControls.js +6 -0
- package/src/styles/Expression.less +12 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@truedat/qx",
|
|
3
|
-
"version": "6.12.
|
|
3
|
+
"version": "6.12.4",
|
|
4
4
|
"description": "Truedat Web Quality Experience package",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"jsnext:main": "src/index.js",
|
|
@@ -84,7 +84,7 @@
|
|
|
84
84
|
]
|
|
85
85
|
},
|
|
86
86
|
"dependencies": {
|
|
87
|
-
"@truedat/core": "6.12.
|
|
87
|
+
"@truedat/core": "6.12.4",
|
|
88
88
|
"prop-types": "^15.8.1",
|
|
89
89
|
"react-hook-form": "^7.45.4",
|
|
90
90
|
"react-intl": "^5.20.10",
|
|
@@ -97,5 +97,5 @@
|
|
|
97
97
|
"react-dom": ">= 16.8.6 < 17",
|
|
98
98
|
"semantic-ui-react": ">= 2.0.3 < 2.2"
|
|
99
99
|
},
|
|
100
|
-
"gitHead": "
|
|
100
|
+
"gitHead": "0d67a012c6b0337f9c82db464137cf76062cbd81"
|
|
101
101
|
}
|
package/src/api.js
CHANGED
|
@@ -9,6 +9,7 @@ const API_QUALITY_CONTROL_PUBLISHED = "/api/quality_controls/:id/published";
|
|
|
9
9
|
const API_QUALITY_CONTROL_DRAFT = "/api/quality_controls/:id/draft";
|
|
10
10
|
const API_QUALITY_CONTROL_STATUS = "/api/quality_controls/:id/status";
|
|
11
11
|
const API_QUALITY_CONTROL_DOMAINS = "/api/quality_controls/:id/domains";
|
|
12
|
+
const API_QUALITY_CONTROL_QUERIES = "/api/quality_controls/:id/queries";
|
|
12
13
|
const API_QUALITY_CONTROL_SEARCH = "/api/quality_controls/search";
|
|
13
14
|
const API_QUALITY_CONTROL_FILTERS = "/api/quality_controls/filters";
|
|
14
15
|
const API_QUALITY_CONTROL_EXECUTION_GROUPS =
|
|
@@ -28,6 +29,7 @@ export {
|
|
|
28
29
|
API_QUALITY_CONTROL_DRAFT,
|
|
29
30
|
API_QUALITY_CONTROL_STATUS,
|
|
30
31
|
API_QUALITY_CONTROL_DOMAINS,
|
|
32
|
+
API_QUALITY_CONTROL_QUERIES,
|
|
31
33
|
API_QUALITY_CONTROL_SEARCH,
|
|
32
34
|
API_QUALITY_CONTROL_FILTERS,
|
|
33
35
|
API_QUALITY_CONTROL_EXECUTION_GROUPS,
|
|
@@ -13,15 +13,25 @@ import {
|
|
|
13
13
|
|
|
14
14
|
export default function ResourceSelector({ required, labelId }) {
|
|
15
15
|
const { formatMessage } = useIntl();
|
|
16
|
-
const { field } =
|
|
16
|
+
const { field, referenceDatasets, dataViews, sourceId } =
|
|
17
|
+
useContext(QxContext);
|
|
17
18
|
const { control, setValue, watch } = useFormContext();
|
|
18
19
|
|
|
20
|
+
const sourceDataViews = _.filter({ source_id: parseInt(sourceId) })(
|
|
21
|
+
dataViews
|
|
22
|
+
);
|
|
23
|
+
const resourceTypes = [
|
|
24
|
+
"data_structure",
|
|
25
|
+
...(!_.isEmpty(referenceDatasets) ? ["reference_dataset"] : []),
|
|
26
|
+
...(!_.isEmpty(sourceDataViews) ? ["data_view"] : []),
|
|
27
|
+
];
|
|
28
|
+
|
|
19
29
|
const type = watch(`${field}.type`);
|
|
20
30
|
const resourceTypeOptions = _.map((v) => ({
|
|
21
31
|
key: v,
|
|
22
32
|
value: v,
|
|
23
33
|
text: formatMessage({ id: `queryables.resource.type.${v}` }),
|
|
24
|
-
}))(
|
|
34
|
+
}))(resourceTypes);
|
|
25
35
|
|
|
26
36
|
const resourceSelectorForType = {
|
|
27
37
|
data_view: DataViewSelector,
|
|
@@ -53,7 +53,6 @@ const renderOpts = {
|
|
|
53
53
|
};
|
|
54
54
|
|
|
55
55
|
const searchProps = {
|
|
56
|
-
userFiltersType: "foo",
|
|
57
56
|
useFilters: jest.fn(),
|
|
58
57
|
useSearch: jest.fn(),
|
|
59
58
|
loadingFilters: false,
|
|
@@ -80,7 +79,8 @@ describe("<ResourceSelector />", () => {
|
|
|
80
79
|
const { container, getByRole } = render(
|
|
81
80
|
<TestFormWrapper
|
|
82
81
|
context={{
|
|
83
|
-
dataViews: [{ name: "UserDataView", id: 1 }],
|
|
82
|
+
dataViews: [{ name: "UserDataView", id: 1, source_id: 10 }],
|
|
83
|
+
sourceId: 10,
|
|
84
84
|
}}
|
|
85
85
|
watcher={watcher}
|
|
86
86
|
>
|
|
@@ -105,6 +105,7 @@ describe("<ResourceSelector />", () => {
|
|
|
105
105
|
fields: [],
|
|
106
106
|
id: 1,
|
|
107
107
|
name: "UserDataView",
|
|
108
|
+
source_id: 10,
|
|
108
109
|
},
|
|
109
110
|
id: 1,
|
|
110
111
|
type: "data_view",
|
|
@@ -42,32 +42,6 @@ exports[`<ResourceSelector /> matches the latest snapshot 1`] = `
|
|
|
42
42
|
data_structure
|
|
43
43
|
</span>
|
|
44
44
|
</div>
|
|
45
|
-
<div
|
|
46
|
-
aria-checked="false"
|
|
47
|
-
aria-selected="false"
|
|
48
|
-
class="item"
|
|
49
|
-
role="option"
|
|
50
|
-
style="pointer-events: all;"
|
|
51
|
-
>
|
|
52
|
-
<span
|
|
53
|
-
class="text"
|
|
54
|
-
>
|
|
55
|
-
reference_dataset
|
|
56
|
-
</span>
|
|
57
|
-
</div>
|
|
58
|
-
<div
|
|
59
|
-
aria-checked="false"
|
|
60
|
-
aria-selected="false"
|
|
61
|
-
class="item"
|
|
62
|
-
role="option"
|
|
63
|
-
style="pointer-events: all;"
|
|
64
|
-
>
|
|
65
|
-
<span
|
|
66
|
-
class="text"
|
|
67
|
-
>
|
|
68
|
-
data_view
|
|
69
|
-
</span>
|
|
70
|
-
</div>
|
|
71
45
|
</div>
|
|
72
46
|
</div>
|
|
73
47
|
</div>
|
|
@@ -116,32 +90,6 @@ exports[`<ResourceSelector /> select data_structure 1`] = `
|
|
|
116
90
|
data_structure
|
|
117
91
|
</span>
|
|
118
92
|
</div>
|
|
119
|
-
<div
|
|
120
|
-
aria-checked="false"
|
|
121
|
-
aria-selected="false"
|
|
122
|
-
class="item"
|
|
123
|
-
role="option"
|
|
124
|
-
style="pointer-events: all;"
|
|
125
|
-
>
|
|
126
|
-
<span
|
|
127
|
-
class="text"
|
|
128
|
-
>
|
|
129
|
-
reference_dataset
|
|
130
|
-
</span>
|
|
131
|
-
</div>
|
|
132
|
-
<div
|
|
133
|
-
aria-checked="false"
|
|
134
|
-
aria-selected="false"
|
|
135
|
-
class="item"
|
|
136
|
-
role="option"
|
|
137
|
-
style="pointer-events: all;"
|
|
138
|
-
>
|
|
139
|
-
<span
|
|
140
|
-
class="text"
|
|
141
|
-
>
|
|
142
|
-
data_view
|
|
143
|
-
</span>
|
|
144
|
-
</div>
|
|
145
93
|
</div>
|
|
146
94
|
</div>
|
|
147
95
|
</div>
|
|
@@ -292,19 +240,6 @@ exports[`<ResourceSelector /> select data_view 1`] = `
|
|
|
292
240
|
data_structure
|
|
293
241
|
</span>
|
|
294
242
|
</div>
|
|
295
|
-
<div
|
|
296
|
-
aria-checked="false"
|
|
297
|
-
aria-selected="false"
|
|
298
|
-
class="item"
|
|
299
|
-
role="option"
|
|
300
|
-
style="pointer-events: all;"
|
|
301
|
-
>
|
|
302
|
-
<span
|
|
303
|
-
class="text"
|
|
304
|
-
>
|
|
305
|
-
reference_dataset
|
|
306
|
-
</span>
|
|
307
|
-
</div>
|
|
308
243
|
<div
|
|
309
244
|
aria-checked="true"
|
|
310
245
|
aria-selected="true"
|
|
@@ -423,19 +358,6 @@ exports[`<ResourceSelector /> select reference_dataset 1`] = `
|
|
|
423
358
|
reference_dataset
|
|
424
359
|
</span>
|
|
425
360
|
</div>
|
|
426
|
-
<div
|
|
427
|
-
aria-checked="false"
|
|
428
|
-
aria-selected="false"
|
|
429
|
-
class="item"
|
|
430
|
-
role="option"
|
|
431
|
-
style="pointer-events: all;"
|
|
432
|
-
>
|
|
433
|
-
<span
|
|
434
|
-
class="text"
|
|
435
|
-
>
|
|
436
|
-
data_view
|
|
437
|
-
</span>
|
|
438
|
-
</div>
|
|
439
361
|
</div>
|
|
440
362
|
</div>
|
|
441
363
|
</div>
|
|
@@ -8,7 +8,7 @@ import StructureSelector from "@truedat/dd/components/StructureSelector";
|
|
|
8
8
|
|
|
9
9
|
export default function DataStructureSelector({ onChange }) {
|
|
10
10
|
const { formatMessage } = useIntl();
|
|
11
|
-
const { field } = useContext(QxContext);
|
|
11
|
+
const { field, sourceId } = useContext(QxContext);
|
|
12
12
|
const { watch } = useFormContext();
|
|
13
13
|
const selectedStructure = watch(`${field}.embedded`);
|
|
14
14
|
|
|
@@ -54,7 +54,7 @@ export default function DataStructureSelector({ onChange }) {
|
|
|
54
54
|
<StructureSelector
|
|
55
55
|
withDataFields
|
|
56
56
|
pageSize={20}
|
|
57
|
-
defaultFilters={{ "class.raw": ["table"] }}
|
|
57
|
+
defaultFilters={{ "class.raw": ["table"], source_id: [sourceId] }}
|
|
58
58
|
selectedStructure={selectedStructure}
|
|
59
59
|
onSelect={handleSelect}
|
|
60
60
|
/>
|
|
@@ -8,7 +8,7 @@ import QxContext from "@truedat/qx/components/QxContext";
|
|
|
8
8
|
export default function DataViewSelector({ onChange, onBlur, value }) {
|
|
9
9
|
const { formatMessage } = useIntl();
|
|
10
10
|
const [searchTerm, setSearchTerm] = useState("");
|
|
11
|
-
const { dataViews, currentDataViewId } = useContext(QxContext);
|
|
11
|
+
const { dataViews, sourceId, currentDataViewId } = useContext(QxContext);
|
|
12
12
|
|
|
13
13
|
const matchSorterFp = (items) =>
|
|
14
14
|
matchSorter(items, searchTerm, {
|
|
@@ -16,6 +16,10 @@ export default function DataViewSelector({ onChange, onBlur, value }) {
|
|
|
16
16
|
threshold: matchSorter.rankings.CONTAINS,
|
|
17
17
|
});
|
|
18
18
|
|
|
19
|
+
const sourceDataViews = _.filter({ source_id: parseInt(sourceId) })(
|
|
20
|
+
dataViews
|
|
21
|
+
);
|
|
22
|
+
|
|
19
23
|
const options = _.flow(
|
|
20
24
|
_.reject(({ id }) => currentDataViewId && currentDataViewId == id),
|
|
21
25
|
_.cond([
|
|
@@ -27,7 +31,7 @@ export default function DataViewSelector({ onChange, onBlur, value }) {
|
|
|
27
31
|
value: id,
|
|
28
32
|
text: name,
|
|
29
33
|
}))
|
|
30
|
-
)(
|
|
34
|
+
)(sourceDataViews);
|
|
31
35
|
|
|
32
36
|
const buildEmbedded = (id) =>
|
|
33
37
|
_.flow(_.find({ id }), (dataView) => ({
|
|
@@ -41,7 +45,7 @@ export default function DataViewSelector({ onChange, onBlur, value }) {
|
|
|
41
45
|
parent_name: dataView.name,
|
|
42
46
|
}))
|
|
43
47
|
)(dataView),
|
|
44
|
-
}))(
|
|
48
|
+
}))(sourceDataViews);
|
|
45
49
|
|
|
46
50
|
const handleSearchChange = (_e, { searchQuery }) =>
|
|
47
51
|
setSearchTerm(searchQuery);
|
|
@@ -19,7 +19,8 @@ describe("<DataViewSelector />", () => {
|
|
|
19
19
|
const { container } = render(
|
|
20
20
|
<TestFormWrapper
|
|
21
21
|
context={{
|
|
22
|
-
|
|
22
|
+
sourceId: 10,
|
|
23
|
+
dataViews: [{ name: "UserDataView", id: 1, source_id: 10 }],
|
|
23
24
|
}}
|
|
24
25
|
>
|
|
25
26
|
<DataViewSelector />
|
|
@@ -35,9 +36,10 @@ describe("<DataViewSelector />", () => {
|
|
|
35
36
|
const { queryByText } = render(
|
|
36
37
|
<TestFormWrapper
|
|
37
38
|
context={{
|
|
39
|
+
sourceId: 10,
|
|
38
40
|
dataViews: [
|
|
39
|
-
{ name: "UserDataView", id: 1 },
|
|
40
|
-
{ name: "SelectedDataView", id: 2 },
|
|
41
|
+
{ name: "UserDataView", id: 1, source_id: 10 },
|
|
42
|
+
{ name: "SelectedDataView", id: 2, source_id: 10 },
|
|
41
43
|
],
|
|
42
44
|
currentDataViewId: 2,
|
|
43
45
|
}}
|
|
@@ -56,11 +58,13 @@ describe("<DataViewSelector />", () => {
|
|
|
56
58
|
const { getByRole } = render(
|
|
57
59
|
<TestFormWrapper
|
|
58
60
|
context={{
|
|
61
|
+
sourceId: 10,
|
|
59
62
|
dataViews: [
|
|
60
|
-
{ name: "UserDataView", id: 1 },
|
|
63
|
+
{ name: "UserDataView", id: 1, source_id: 10 },
|
|
61
64
|
{
|
|
62
65
|
name: "SelectedDataView",
|
|
63
66
|
id: 2,
|
|
67
|
+
source_id: 10,
|
|
64
68
|
select: {
|
|
65
69
|
properties: {
|
|
66
70
|
fields: [
|
|
@@ -95,6 +99,7 @@ describe("<DataViewSelector />", () => {
|
|
|
95
99
|
},
|
|
96
100
|
],
|
|
97
101
|
id: 2,
|
|
102
|
+
source_id: 10,
|
|
98
103
|
name: "SelectedDataView",
|
|
99
104
|
select: {
|
|
100
105
|
properties: {
|
|
@@ -114,9 +119,10 @@ describe("<DataViewSelector />", () => {
|
|
|
114
119
|
const { getByRole, queryByText } = render(
|
|
115
120
|
<TestFormWrapper
|
|
116
121
|
context={{
|
|
122
|
+
sourceId: 10,
|
|
117
123
|
dataViews: [
|
|
118
|
-
{ name: "UserDataView", id: 1 },
|
|
119
|
-
{ name: "SelectedDataView", id: 2 },
|
|
124
|
+
{ name: "UserDataView", id: 1, source_id: 10 },
|
|
125
|
+
{ name: "SelectedDataView", id: 2, source_id: 10 },
|
|
120
126
|
],
|
|
121
127
|
}}
|
|
122
128
|
>
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import _ from "lodash/fp";
|
|
1
2
|
import React, { Fragment, useEffect } from "react";
|
|
2
3
|
import PropTypes from "prop-types";
|
|
3
4
|
import { useIntl } from "react-intl";
|
|
@@ -17,6 +18,10 @@ import QxContext from "@truedat/qx/components/QxContext";
|
|
|
17
18
|
import DataViewSelect from "./DataViewSelect";
|
|
18
19
|
import Queryables from "./Queryables";
|
|
19
20
|
|
|
21
|
+
const SourceSelector = React.lazy(() =>
|
|
22
|
+
import("@truedat/cx/sources/components/SourceSelector")
|
|
23
|
+
);
|
|
24
|
+
|
|
20
25
|
export default function DataViewEditor({
|
|
21
26
|
selectedDataView,
|
|
22
27
|
context,
|
|
@@ -38,6 +43,8 @@ export default function DataViewEditor({
|
|
|
38
43
|
setDirty(isDirty);
|
|
39
44
|
}, [setDirty, isDirty]);
|
|
40
45
|
|
|
46
|
+
const isEditForm = !_.isNil(selectedDataView?.id);
|
|
47
|
+
const sourceId = watch("source_id");
|
|
41
48
|
if (!selectedDataView) return null;
|
|
42
49
|
|
|
43
50
|
return (
|
|
@@ -94,11 +101,28 @@ export default function DataViewEditor({
|
|
|
94
101
|
</Grid.Row>
|
|
95
102
|
</GridColumn>
|
|
96
103
|
</Grid>
|
|
97
|
-
<
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
104
|
+
<Controller
|
|
105
|
+
control={control}
|
|
106
|
+
name="source_id"
|
|
107
|
+
rules={{ required: true }}
|
|
108
|
+
render={({ field: { onChange, value } }) => (
|
|
109
|
+
<Form.Field required>
|
|
110
|
+
<label>{formatMessage({ id: "dataViews.form.source" })}</label>
|
|
101
111
|
|
|
112
|
+
<SourceSelector
|
|
113
|
+
disabled={isEditForm}
|
|
114
|
+
value={value + ""}
|
|
115
|
+
onChange={(_e, { value }) => onChange(value)}
|
|
116
|
+
/>
|
|
117
|
+
</Form.Field>
|
|
118
|
+
)}
|
|
119
|
+
/>
|
|
120
|
+
{!_.isNil(sourceId) ? (
|
|
121
|
+
<QxContext.Provider value={{ ...context, sourceId }}>
|
|
122
|
+
<Queryables />
|
|
123
|
+
<DataViewSelect />
|
|
124
|
+
</QxContext.Provider>
|
|
125
|
+
) : null}
|
|
102
126
|
<Divider hidden />
|
|
103
127
|
<Container textAlign="right">
|
|
104
128
|
<Button
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React from "react";
|
|
1
|
+
import React, { Suspense } from "react";
|
|
2
2
|
import { act } from "react-dom/test-utils";
|
|
3
3
|
import userEvent from "@testing-library/user-event";
|
|
4
4
|
import { render } from "@truedat/test/render";
|
|
@@ -48,13 +48,15 @@ const renderOpts = {
|
|
|
48
48
|
"queryables.select.form.add_all_select_fields": "add_all_select_fields",
|
|
49
49
|
"queryables.select.form.add_select_field": "add_select_field",
|
|
50
50
|
"queryables.select.form.alias": "alias",
|
|
51
|
+
"source.search.placeholder": "placeholder",
|
|
52
|
+
"dataViews.form.source": "source",
|
|
51
53
|
},
|
|
52
54
|
},
|
|
53
55
|
};
|
|
54
56
|
|
|
55
57
|
const defaultProps = {
|
|
56
58
|
selectedDataView: null,
|
|
57
|
-
context: {},
|
|
59
|
+
context: { sourceId: 10 },
|
|
58
60
|
onSubmit: jest.fn(),
|
|
59
61
|
onCancel: jest.fn(),
|
|
60
62
|
onDelete: jest.fn(),
|
|
@@ -78,6 +80,7 @@ describe("<DataViewEditor />", () => {
|
|
|
78
80
|
...defaultProps,
|
|
79
81
|
selectedDataView: {
|
|
80
82
|
id: 4,
|
|
83
|
+
source_id: 10,
|
|
81
84
|
description: "Description",
|
|
82
85
|
name: "StructureView",
|
|
83
86
|
queryables: [
|
|
@@ -126,7 +129,12 @@ describe("<DataViewEditor />", () => {
|
|
|
126
129
|
},
|
|
127
130
|
},
|
|
128
131
|
};
|
|
129
|
-
const { container } = render(
|
|
132
|
+
const { container } = render(
|
|
133
|
+
<Suspense fallback={<p>Loading selector</p>}>
|
|
134
|
+
<DataViewEditor {...props} />
|
|
135
|
+
</Suspense>,
|
|
136
|
+
renderOpts
|
|
137
|
+
);
|
|
130
138
|
|
|
131
139
|
await act(async () => {
|
|
132
140
|
expect(container).toMatchSnapshot();
|
|
@@ -140,6 +148,7 @@ describe("<DataViewEditor />", () => {
|
|
|
140
148
|
onSubmit,
|
|
141
149
|
selectedDataView: {
|
|
142
150
|
name: "",
|
|
151
|
+
source_id: 10,
|
|
143
152
|
description: "",
|
|
144
153
|
queryables: [
|
|
145
154
|
{
|
|
@@ -159,6 +168,7 @@ describe("<DataViewEditor />", () => {
|
|
|
159
168
|
dataViews: [
|
|
160
169
|
{
|
|
161
170
|
id: 4,
|
|
171
|
+
source_id: 10,
|
|
162
172
|
description: "Description",
|
|
163
173
|
name: "AnotherDataView",
|
|
164
174
|
select: {
|
|
@@ -185,16 +195,14 @@ describe("<DataViewEditor />", () => {
|
|
|
185
195
|
],
|
|
186
196
|
},
|
|
187
197
|
};
|
|
188
|
-
const { container, getAllByRole, getByRole } =
|
|
189
|
-
<DataViewEditor {...props} />,
|
|
190
|
-
renderOpts
|
|
191
|
-
);
|
|
198
|
+
const { container, getAllByRole, getByRole, getByPlaceholderText, debug } =
|
|
199
|
+
render(<DataViewEditor {...props} />, renderOpts);
|
|
192
200
|
|
|
193
201
|
// Insert name
|
|
194
202
|
userEvent.type(getAllByRole("textbox")[0], "data_view_name");
|
|
195
203
|
|
|
196
204
|
// Insert From information
|
|
197
|
-
userEvent.type(
|
|
205
|
+
userEvent.type(getByPlaceholderText("alias"), "from_alias");
|
|
198
206
|
userEvent.click(getByRole("option", { name: /data_view/i }));
|
|
199
207
|
userEvent.click(getByRole("option", { name: /AnotherDataView/i }));
|
|
200
208
|
|
|
@@ -221,6 +229,7 @@ describe("<DataViewEditor />", () => {
|
|
|
221
229
|
|
|
222
230
|
expect(onSubmit).toHaveBeenCalledWith({
|
|
223
231
|
description: "",
|
|
232
|
+
source_id: 10,
|
|
224
233
|
name: "data_view_name",
|
|
225
234
|
queryables: [
|
|
226
235
|
{
|
|
@@ -260,6 +269,7 @@ describe("<DataViewEditor />", () => {
|
|
|
260
269
|
},
|
|
261
270
|
type: "select",
|
|
262
271
|
},
|
|
272
|
+
source_id: 10,
|
|
263
273
|
},
|
|
264
274
|
id: 4,
|
|
265
275
|
type: "data_view",
|
|
@@ -60,6 +60,13 @@ exports[`<DataViewEditor /> handles user interaction 1`] = `
|
|
|
60
60
|
</div>
|
|
61
61
|
</div>
|
|
62
62
|
</div>
|
|
63
|
+
<div
|
|
64
|
+
class="required field"
|
|
65
|
+
>
|
|
66
|
+
<label>
|
|
67
|
+
source
|
|
68
|
+
</label>
|
|
69
|
+
</div>
|
|
63
70
|
<div
|
|
64
71
|
class="ui list"
|
|
65
72
|
role="list"
|
|
@@ -151,19 +158,6 @@ exports[`<DataViewEditor /> handles user interaction 1`] = `
|
|
|
151
158
|
data_structure
|
|
152
159
|
</span>
|
|
153
160
|
</div>
|
|
154
|
-
<div
|
|
155
|
-
aria-checked="false"
|
|
156
|
-
aria-selected="false"
|
|
157
|
-
class="item"
|
|
158
|
-
role="option"
|
|
159
|
-
style="pointer-events: all;"
|
|
160
|
-
>
|
|
161
|
-
<span
|
|
162
|
-
class="text"
|
|
163
|
-
>
|
|
164
|
-
reference_dataset
|
|
165
|
-
</span>
|
|
166
|
-
</div>
|
|
167
161
|
<div
|
|
168
162
|
aria-checked="true"
|
|
169
163
|
aria-selected="true"
|
|
@@ -518,6 +512,7 @@ exports[`<DataViewEditor /> matches the latest snapshot with content 1`] = `
|
|
|
518
512
|
<div>
|
|
519
513
|
<form
|
|
520
514
|
class="ui form"
|
|
515
|
+
style="display: none;"
|
|
521
516
|
>
|
|
522
517
|
<h3
|
|
523
518
|
class="ui dividing header"
|
|
@@ -574,6 +569,13 @@ exports[`<DataViewEditor /> matches the latest snapshot with content 1`] = `
|
|
|
574
569
|
</div>
|
|
575
570
|
</div>
|
|
576
571
|
</div>
|
|
572
|
+
<div
|
|
573
|
+
class="required field"
|
|
574
|
+
>
|
|
575
|
+
<label>
|
|
576
|
+
source
|
|
577
|
+
</label>
|
|
578
|
+
</div>
|
|
577
579
|
<div
|
|
578
580
|
class="ui list"
|
|
579
581
|
role="list"
|
|
@@ -665,32 +667,6 @@ exports[`<DataViewEditor /> matches the latest snapshot with content 1`] = `
|
|
|
665
667
|
data_structure
|
|
666
668
|
</span>
|
|
667
669
|
</div>
|
|
668
|
-
<div
|
|
669
|
-
aria-checked="false"
|
|
670
|
-
aria-selected="false"
|
|
671
|
-
class="item"
|
|
672
|
-
role="option"
|
|
673
|
-
style="pointer-events: all;"
|
|
674
|
-
>
|
|
675
|
-
<span
|
|
676
|
-
class="text"
|
|
677
|
-
>
|
|
678
|
-
reference_dataset
|
|
679
|
-
</span>
|
|
680
|
-
</div>
|
|
681
|
-
<div
|
|
682
|
-
aria-checked="false"
|
|
683
|
-
aria-selected="false"
|
|
684
|
-
class="item"
|
|
685
|
-
role="option"
|
|
686
|
-
style="pointer-events: all;"
|
|
687
|
-
>
|
|
688
|
-
<span
|
|
689
|
-
class="text"
|
|
690
|
-
>
|
|
691
|
-
data_view
|
|
692
|
-
</span>
|
|
693
|
-
</div>
|
|
694
670
|
</div>
|
|
695
671
|
</div>
|
|
696
672
|
</div>
|
|
@@ -996,5 +972,8 @@ exports[`<DataViewEditor /> matches the latest snapshot with content 1`] = `
|
|
|
996
972
|
</button>
|
|
997
973
|
</div>
|
|
998
974
|
</form>
|
|
975
|
+
<p>
|
|
976
|
+
Loading selector
|
|
977
|
+
</p>
|
|
999
978
|
</div>
|
|
1000
979
|
`;
|
|
@@ -85,32 +85,6 @@ exports[`<Queryable /> matches the latest snapshot with duplicated alias 1`] = `
|
|
|
85
85
|
data_structure
|
|
86
86
|
</span>
|
|
87
87
|
</div>
|
|
88
|
-
<div
|
|
89
|
-
aria-checked="false"
|
|
90
|
-
aria-selected="false"
|
|
91
|
-
class="item"
|
|
92
|
-
role="option"
|
|
93
|
-
style="pointer-events: all;"
|
|
94
|
-
>
|
|
95
|
-
<span
|
|
96
|
-
class="text"
|
|
97
|
-
>
|
|
98
|
-
reference_dataset
|
|
99
|
-
</span>
|
|
100
|
-
</div>
|
|
101
|
-
<div
|
|
102
|
-
aria-checked="false"
|
|
103
|
-
aria-selected="false"
|
|
104
|
-
class="item"
|
|
105
|
-
role="option"
|
|
106
|
-
style="pointer-events: all;"
|
|
107
|
-
>
|
|
108
|
-
<span
|
|
109
|
-
class="text"
|
|
110
|
-
>
|
|
111
|
-
data_view
|
|
112
|
-
</span>
|
|
113
|
-
</div>
|
|
114
88
|
</div>
|
|
115
89
|
</div>
|
|
116
90
|
</div>
|
|
@@ -185,7 +159,7 @@ exports[`<Queryable /> matches the latest snapshot with duplicated resource 1`]
|
|
|
185
159
|
class="divider text"
|
|
186
160
|
role="alert"
|
|
187
161
|
>
|
|
188
|
-
|
|
162
|
+
type
|
|
189
163
|
</div>
|
|
190
164
|
<i
|
|
191
165
|
aria-hidden="true"
|
|
@@ -196,41 +170,15 @@ exports[`<Queryable /> matches the latest snapshot with duplicated resource 1`]
|
|
|
196
170
|
>
|
|
197
171
|
<div
|
|
198
172
|
aria-checked="false"
|
|
199
|
-
aria-selected="false"
|
|
200
|
-
class="item"
|
|
201
|
-
role="option"
|
|
202
|
-
style="pointer-events: all;"
|
|
203
|
-
>
|
|
204
|
-
<span
|
|
205
|
-
class="text"
|
|
206
|
-
>
|
|
207
|
-
data_structure
|
|
208
|
-
</span>
|
|
209
|
-
</div>
|
|
210
|
-
<div
|
|
211
|
-
aria-checked="false"
|
|
212
|
-
aria-selected="false"
|
|
213
|
-
class="item"
|
|
214
|
-
role="option"
|
|
215
|
-
style="pointer-events: all;"
|
|
216
|
-
>
|
|
217
|
-
<span
|
|
218
|
-
class="text"
|
|
219
|
-
>
|
|
220
|
-
reference_dataset
|
|
221
|
-
</span>
|
|
222
|
-
</div>
|
|
223
|
-
<div
|
|
224
|
-
aria-checked="true"
|
|
225
173
|
aria-selected="true"
|
|
226
|
-
class="
|
|
174
|
+
class="selected item"
|
|
227
175
|
role="option"
|
|
228
176
|
style="pointer-events: all;"
|
|
229
177
|
>
|
|
230
178
|
<span
|
|
231
179
|
class="text"
|
|
232
180
|
>
|
|
233
|
-
|
|
181
|
+
data_structure
|
|
234
182
|
</span>
|
|
235
183
|
</div>
|
|
236
184
|
</div>
|
|
@@ -365,32 +313,6 @@ exports[`<Queryable /> matches the latest snapshot with from queryable 1`] = `
|
|
|
365
313
|
data_structure
|
|
366
314
|
</span>
|
|
367
315
|
</div>
|
|
368
|
-
<div
|
|
369
|
-
aria-checked="false"
|
|
370
|
-
aria-selected="false"
|
|
371
|
-
class="item"
|
|
372
|
-
role="option"
|
|
373
|
-
style="pointer-events: all;"
|
|
374
|
-
>
|
|
375
|
-
<span
|
|
376
|
-
class="text"
|
|
377
|
-
>
|
|
378
|
-
reference_dataset
|
|
379
|
-
</span>
|
|
380
|
-
</div>
|
|
381
|
-
<div
|
|
382
|
-
aria-checked="false"
|
|
383
|
-
aria-selected="false"
|
|
384
|
-
class="item"
|
|
385
|
-
role="option"
|
|
386
|
-
style="pointer-events: all;"
|
|
387
|
-
>
|
|
388
|
-
<span
|
|
389
|
-
class="text"
|
|
390
|
-
>
|
|
391
|
-
data_view
|
|
392
|
-
</span>
|
|
393
|
-
</div>
|
|
394
316
|
</div>
|
|
395
317
|
</div>
|
|
396
318
|
</div>
|
|
@@ -584,32 +506,6 @@ exports[`<Queryable /> matches the latest snapshot with join queryable 1`] = `
|
|
|
584
506
|
data_structure
|
|
585
507
|
</span>
|
|
586
508
|
</div>
|
|
587
|
-
<div
|
|
588
|
-
aria-checked="false"
|
|
589
|
-
aria-selected="false"
|
|
590
|
-
class="item"
|
|
591
|
-
role="option"
|
|
592
|
-
style="pointer-events: all;"
|
|
593
|
-
>
|
|
594
|
-
<span
|
|
595
|
-
class="text"
|
|
596
|
-
>
|
|
597
|
-
reference_dataset
|
|
598
|
-
</span>
|
|
599
|
-
</div>
|
|
600
|
-
<div
|
|
601
|
-
aria-checked="false"
|
|
602
|
-
aria-selected="false"
|
|
603
|
-
class="item"
|
|
604
|
-
role="option"
|
|
605
|
-
style="pointer-events: all;"
|
|
606
|
-
>
|
|
607
|
-
<span
|
|
608
|
-
class="text"
|
|
609
|
-
>
|
|
610
|
-
data_view
|
|
611
|
-
</span>
|
|
612
|
-
</div>
|
|
613
509
|
</div>
|
|
614
510
|
</div>
|
|
615
511
|
</div>
|
|
@@ -93,32 +93,6 @@ exports[`<Queryables /> matches the latest snapshot with from queryable 1`] = `
|
|
|
93
93
|
data_structure
|
|
94
94
|
</span>
|
|
95
95
|
</div>
|
|
96
|
-
<div
|
|
97
|
-
aria-checked="false"
|
|
98
|
-
aria-selected="false"
|
|
99
|
-
class="item"
|
|
100
|
-
role="option"
|
|
101
|
-
style="pointer-events: all;"
|
|
102
|
-
>
|
|
103
|
-
<span
|
|
104
|
-
class="text"
|
|
105
|
-
>
|
|
106
|
-
reference_dataset
|
|
107
|
-
</span>
|
|
108
|
-
</div>
|
|
109
|
-
<div
|
|
110
|
-
aria-checked="false"
|
|
111
|
-
aria-selected="false"
|
|
112
|
-
class="item"
|
|
113
|
-
role="option"
|
|
114
|
-
style="pointer-events: all;"
|
|
115
|
-
>
|
|
116
|
-
<span
|
|
117
|
-
class="text"
|
|
118
|
-
>
|
|
119
|
-
data_view
|
|
120
|
-
</span>
|
|
121
|
-
</div>
|
|
122
96
|
</div>
|
|
123
97
|
</div>
|
|
124
98
|
</div>
|
|
@@ -390,32 +364,6 @@ exports[`<Queryables /> matches the latest snapshot with join queryable 1`] = `
|
|
|
390
364
|
data_structure
|
|
391
365
|
</span>
|
|
392
366
|
</div>
|
|
393
|
-
<div
|
|
394
|
-
aria-checked="false"
|
|
395
|
-
aria-selected="false"
|
|
396
|
-
class="item"
|
|
397
|
-
role="option"
|
|
398
|
-
style="pointer-events: all;"
|
|
399
|
-
>
|
|
400
|
-
<span
|
|
401
|
-
class="text"
|
|
402
|
-
>
|
|
403
|
-
reference_dataset
|
|
404
|
-
</span>
|
|
405
|
-
</div>
|
|
406
|
-
<div
|
|
407
|
-
aria-checked="false"
|
|
408
|
-
aria-selected="false"
|
|
409
|
-
class="item"
|
|
410
|
-
role="option"
|
|
411
|
-
style="pointer-events: all;"
|
|
412
|
-
>
|
|
413
|
-
<span
|
|
414
|
-
class="text"
|
|
415
|
-
>
|
|
416
|
-
data_view
|
|
417
|
-
</span>
|
|
418
|
-
</div>
|
|
419
367
|
</div>
|
|
420
368
|
</div>
|
|
421
369
|
</div>
|
|
@@ -842,32 +790,6 @@ exports[`<Queryables /> test delete queryable 1`] = `
|
|
|
842
790
|
data_structure
|
|
843
791
|
</span>
|
|
844
792
|
</div>
|
|
845
|
-
<div
|
|
846
|
-
aria-checked="false"
|
|
847
|
-
aria-selected="false"
|
|
848
|
-
class="item"
|
|
849
|
-
role="option"
|
|
850
|
-
style="pointer-events: all;"
|
|
851
|
-
>
|
|
852
|
-
<span
|
|
853
|
-
class="text"
|
|
854
|
-
>
|
|
855
|
-
reference_dataset
|
|
856
|
-
</span>
|
|
857
|
-
</div>
|
|
858
|
-
<div
|
|
859
|
-
aria-checked="false"
|
|
860
|
-
aria-selected="false"
|
|
861
|
-
class="item"
|
|
862
|
-
role="option"
|
|
863
|
-
style="pointer-events: all;"
|
|
864
|
-
>
|
|
865
|
-
<span
|
|
866
|
-
class="text"
|
|
867
|
-
>
|
|
868
|
-
data_view
|
|
869
|
-
</span>
|
|
870
|
-
</div>
|
|
871
793
|
</div>
|
|
872
794
|
</div>
|
|
873
795
|
</div>
|
package/src/components/dataViews/queryableProperties/__tests__/__snapshots__/From.spec.js.snap
CHANGED
|
@@ -42,32 +42,6 @@ exports[`<From /> matches the latest snapshot 1`] = `
|
|
|
42
42
|
data_structure
|
|
43
43
|
</span>
|
|
44
44
|
</div>
|
|
45
|
-
<div
|
|
46
|
-
aria-checked="false"
|
|
47
|
-
aria-selected="false"
|
|
48
|
-
class="item"
|
|
49
|
-
role="option"
|
|
50
|
-
style="pointer-events: all;"
|
|
51
|
-
>
|
|
52
|
-
<span
|
|
53
|
-
class="text"
|
|
54
|
-
>
|
|
55
|
-
reference_dataset
|
|
56
|
-
</span>
|
|
57
|
-
</div>
|
|
58
|
-
<div
|
|
59
|
-
aria-checked="false"
|
|
60
|
-
aria-selected="false"
|
|
61
|
-
class="item"
|
|
62
|
-
role="option"
|
|
63
|
-
style="pointer-events: all;"
|
|
64
|
-
>
|
|
65
|
-
<span
|
|
66
|
-
class="text"
|
|
67
|
-
>
|
|
68
|
-
data_view
|
|
69
|
-
</span>
|
|
70
|
-
</div>
|
|
71
45
|
</div>
|
|
72
46
|
</div>
|
|
73
47
|
</div>
|
package/src/components/dataViews/queryableProperties/__tests__/__snapshots__/Join.spec.js.snap
CHANGED
|
@@ -42,32 +42,6 @@ exports[`<Join /> matches the latest snapshot 1`] = `
|
|
|
42
42
|
data_structure
|
|
43
43
|
</span>
|
|
44
44
|
</div>
|
|
45
|
-
<div
|
|
46
|
-
aria-checked="false"
|
|
47
|
-
aria-selected="false"
|
|
48
|
-
class="item"
|
|
49
|
-
role="option"
|
|
50
|
-
style="pointer-events: all;"
|
|
51
|
-
>
|
|
52
|
-
<span
|
|
53
|
-
class="text"
|
|
54
|
-
>
|
|
55
|
-
reference_dataset
|
|
56
|
-
</span>
|
|
57
|
-
</div>
|
|
58
|
-
<div
|
|
59
|
-
aria-checked="false"
|
|
60
|
-
aria-selected="false"
|
|
61
|
-
class="item"
|
|
62
|
-
role="option"
|
|
63
|
-
style="pointer-events: all;"
|
|
64
|
-
>
|
|
65
|
-
<span
|
|
66
|
-
class="text"
|
|
67
|
-
>
|
|
68
|
-
data_view
|
|
69
|
-
</span>
|
|
70
|
-
</div>
|
|
71
45
|
</div>
|
|
72
46
|
</div>
|
|
73
47
|
</div>
|
|
@@ -5,7 +5,9 @@ import { useIntl } from "react-intl";
|
|
|
5
5
|
import { Link } from "react-router-dom";
|
|
6
6
|
import { Button, Container } from "semantic-ui-react";
|
|
7
7
|
import { linkTo } from "@truedat/core/routes";
|
|
8
|
+
import { useAuthorized } from "@truedat/core/hooks";
|
|
8
9
|
import { useQualityControlUpdateStatus } from "../../hooks/useQualityControls";
|
|
10
|
+
import QualityControlQueryModal from "./QualityControlQueryModal";
|
|
9
11
|
|
|
10
12
|
export default function QualityControlActions({
|
|
11
13
|
actions,
|
|
@@ -16,11 +18,15 @@ export default function QualityControlActions({
|
|
|
16
18
|
const { trigger, isMutating } = useQualityControlUpdateStatus(
|
|
17
19
|
qualityControl.id
|
|
18
20
|
);
|
|
21
|
+
const authorized = useAuthorized();
|
|
19
22
|
|
|
20
23
|
const updateStatus = (action) => trigger({ action }).then(() => mutate());
|
|
21
24
|
|
|
22
25
|
return (
|
|
23
26
|
<Container textAlign="right">
|
|
27
|
+
{authorized ? (
|
|
28
|
+
<QualityControlQueryModal qualityControlId={qualityControl.id} />
|
|
29
|
+
) : null}
|
|
24
30
|
{_.map((action) =>
|
|
25
31
|
action === "create_draft" ? (
|
|
26
32
|
<Button
|
|
@@ -24,6 +24,9 @@ import ResultType from "./ResultType";
|
|
|
24
24
|
const SelectableDynamicForm = React.lazy(() =>
|
|
25
25
|
import("@truedat/df/components/SelectableDynamicForm")
|
|
26
26
|
);
|
|
27
|
+
const SourceSelector = React.lazy(() =>
|
|
28
|
+
import("@truedat/cx/sources/components/SourceSelector")
|
|
29
|
+
);
|
|
27
30
|
|
|
28
31
|
export default function QualityControlEditor({
|
|
29
32
|
value,
|
|
@@ -82,10 +85,13 @@ export default function QualityControlEditor({
|
|
|
82
85
|
|
|
83
86
|
const formData = watch();
|
|
84
87
|
|
|
88
|
+
console.log("formData", formData);
|
|
89
|
+
|
|
85
90
|
const {
|
|
86
91
|
resource,
|
|
87
92
|
name,
|
|
88
|
-
|
|
93
|
+
source_id: sourceId,
|
|
94
|
+
df_content: dfContent,
|
|
89
95
|
domain_ids: domainIds,
|
|
90
96
|
} = formData;
|
|
91
97
|
|
|
@@ -196,17 +202,47 @@ export default function QualityControlEditor({
|
|
|
196
202
|
)}
|
|
197
203
|
/>
|
|
198
204
|
|
|
199
|
-
<
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
205
|
+
<Controller
|
|
206
|
+
control={control}
|
|
207
|
+
name="source_id"
|
|
208
|
+
rules={{ required: true }}
|
|
209
|
+
render={({ field: { onChange, value } }) => (
|
|
210
|
+
<Form.Field required>
|
|
211
|
+
<label>{formatMessage({ id: "dataViews.form.source" })}</label>
|
|
212
|
+
|
|
213
|
+
<SourceSelector
|
|
214
|
+
disabled={isModification}
|
|
215
|
+
value={value + ""}
|
|
216
|
+
onChange={(_e, { value }) => onChange(value)}
|
|
217
|
+
/>
|
|
218
|
+
</Form.Field>
|
|
219
|
+
)}
|
|
220
|
+
/>
|
|
221
|
+
{!_.isNil(sourceId) ? (
|
|
222
|
+
<>
|
|
204
223
|
<QxContext.Provider
|
|
205
|
-
value={{ ...context,
|
|
224
|
+
value={{ ...context, sourceId, field: "resource" }}
|
|
206
225
|
>
|
|
207
|
-
<
|
|
226
|
+
<ResourceSelector
|
|
227
|
+
required
|
|
228
|
+
labelId="quality_control.form.dataset"
|
|
229
|
+
/>
|
|
208
230
|
</QxContext.Provider>
|
|
209
|
-
|
|
231
|
+
{resource?.id ? (
|
|
232
|
+
<div className="vertical-space">
|
|
233
|
+
<QxContext.Provider
|
|
234
|
+
value={{
|
|
235
|
+
...context,
|
|
236
|
+
sourceId,
|
|
237
|
+
fields,
|
|
238
|
+
field: "validation",
|
|
239
|
+
}}
|
|
240
|
+
>
|
|
241
|
+
<Clauses labelId="quality_control.form.validation" />
|
|
242
|
+
</QxContext.Provider>
|
|
243
|
+
</div>
|
|
244
|
+
) : null}
|
|
245
|
+
</>
|
|
210
246
|
) : null}
|
|
211
247
|
|
|
212
248
|
<Divider hidden />
|
|
@@ -12,7 +12,7 @@ import QualityControlCrumbs from "./QualityControlCrumbs";
|
|
|
12
12
|
import QualityControlActions from "./QualityControlActions";
|
|
13
13
|
import QualityControlTabs from "./QualityControlTabs";
|
|
14
14
|
|
|
15
|
-
export default function
|
|
15
|
+
export default function QualityControlHeader({ children }) {
|
|
16
16
|
const { id } = useParams();
|
|
17
17
|
const { data, loading, mutate } = useQualityControl(id);
|
|
18
18
|
|
|
@@ -59,6 +59,6 @@ export default function QualityControl({ children }) {
|
|
|
59
59
|
);
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
-
|
|
62
|
+
QualityControlHeader.propTypes = {
|
|
63
63
|
children: PropTypes.node,
|
|
64
64
|
};
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import React, { useState } from "react";
|
|
2
|
+
import PropTypes from "prop-types";
|
|
3
|
+
import {
|
|
4
|
+
Accordion,
|
|
5
|
+
AccordionTitle,
|
|
6
|
+
AccordionContent,
|
|
7
|
+
Icon,
|
|
8
|
+
TextArea,
|
|
9
|
+
Button,
|
|
10
|
+
Modal,
|
|
11
|
+
Divider,
|
|
12
|
+
} from "semantic-ui-react";
|
|
13
|
+
import { FormattedMessage } from "react-intl";
|
|
14
|
+
import { useQualityControlQueries } from "../../hooks/useQualityControls";
|
|
15
|
+
|
|
16
|
+
const JsonBox = ({ title, content }) => {
|
|
17
|
+
const [expanded, setExpanded] = useState(false);
|
|
18
|
+
const [copied, setCopied] = useState(false);
|
|
19
|
+
const contentString = JSON.stringify(content, null, 2);
|
|
20
|
+
return (
|
|
21
|
+
<>
|
|
22
|
+
<AccordionTitle active={expanded} onClick={() => setExpanded(!expanded)}>
|
|
23
|
+
<div className="json-box-title">
|
|
24
|
+
<span>
|
|
25
|
+
<Icon name="dropdown" />
|
|
26
|
+
{title}
|
|
27
|
+
</span>
|
|
28
|
+
<Button
|
|
29
|
+
icon={copied ? "check" : "copy"}
|
|
30
|
+
color={copied && "green"}
|
|
31
|
+
onClick={(e) => {
|
|
32
|
+
e.stopPropagation();
|
|
33
|
+
setCopied(true);
|
|
34
|
+
setTimeout(() => setCopied(false), 2000);
|
|
35
|
+
navigator.clipboard.writeText(contentString);
|
|
36
|
+
}}
|
|
37
|
+
/>
|
|
38
|
+
</div>
|
|
39
|
+
</AccordionTitle>
|
|
40
|
+
<AccordionContent active={expanded}>
|
|
41
|
+
<TextArea
|
|
42
|
+
className="json-box"
|
|
43
|
+
fluid
|
|
44
|
+
editable={false}
|
|
45
|
+
rows={10}
|
|
46
|
+
size="small"
|
|
47
|
+
value={contentString}
|
|
48
|
+
/>
|
|
49
|
+
</AccordionContent>
|
|
50
|
+
</>
|
|
51
|
+
);
|
|
52
|
+
};
|
|
53
|
+
const ModalContent = ({ id }) => {
|
|
54
|
+
const { data, loading } = useQualityControlQueries(id);
|
|
55
|
+
return loading ? (
|
|
56
|
+
<FormattedMessage id={`quality_control.queries.loading`} />
|
|
57
|
+
) : (
|
|
58
|
+
<Accordion styled>
|
|
59
|
+
{data?.data?.queries.map((json, id) => (
|
|
60
|
+
<JsonBox key={id} title={`Query ${id}`} content={json} />
|
|
61
|
+
))}
|
|
62
|
+
<JsonBox
|
|
63
|
+
title="Resources Lookup"
|
|
64
|
+
content={data?.data?.resources_lookup}
|
|
65
|
+
/>
|
|
66
|
+
</Accordion>
|
|
67
|
+
);
|
|
68
|
+
};
|
|
69
|
+
export default function QualityControlQueryModal({ qualityControlId: id }) {
|
|
70
|
+
const [open, setOpen] = useState(open);
|
|
71
|
+
return (
|
|
72
|
+
<Modal
|
|
73
|
+
open={open}
|
|
74
|
+
onOpen={() => setOpen(true)}
|
|
75
|
+
onClose={() => setOpen(false)}
|
|
76
|
+
trigger={<Button icon="file code outline" />}
|
|
77
|
+
closeIcon
|
|
78
|
+
size={"small"}
|
|
79
|
+
content={<ModalContent id={id} />}
|
|
80
|
+
role="dialog"
|
|
81
|
+
/>
|
|
82
|
+
);
|
|
83
|
+
}
|
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
API_QUALITY_CONTROL_DOMAINS,
|
|
18
18
|
API_QUALITY_CONTROL_SEARCH,
|
|
19
19
|
API_QUALITY_CONTROL_FILTERS,
|
|
20
|
+
API_QUALITY_CONTROL_QUERIES,
|
|
20
21
|
} from "../api";
|
|
21
22
|
|
|
22
23
|
export const useQualityControls = () => {
|
|
@@ -72,3 +73,8 @@ export const useQualityControlsFilters = () => {
|
|
|
72
73
|
apiJsonPost(url, arg)
|
|
73
74
|
);
|
|
74
75
|
};
|
|
76
|
+
export const useQualityControlQueries = (id) => {
|
|
77
|
+
const url = compile(API_QUALITY_CONTROL_QUERIES)({ id });
|
|
78
|
+
const { data, error, mutate } = useSWR(url, apiJson);
|
|
79
|
+
return { data: data?.data, error, loading: !error && !data, mutate };
|
|
80
|
+
};
|
|
@@ -284,4 +284,16 @@ ul.function-tree {
|
|
|
284
284
|
display: flex;
|
|
285
285
|
justify-content: center;
|
|
286
286
|
align-items: center;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
.json-box {
|
|
290
|
+
font-family: monospace;
|
|
291
|
+
font-size: smaller;
|
|
292
|
+
width: 100%;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
.json-box-title {
|
|
296
|
+
display: flex;
|
|
297
|
+
justify-content: space-between;
|
|
298
|
+
align-items: center;
|
|
287
299
|
}
|