@truedat/bg 6.0.2 → 6.0.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 +6 -6
- package/src/concepts/api.js +3 -0
- package/src/concepts/components/ConceptDetails.js +1 -3
- package/src/concepts/components/ConceptEdit.js +124 -110
- package/src/concepts/components/ConceptForm.js +154 -123
- package/src/concepts/components/ConceptRoutes.js +9 -0
- package/src/concepts/components/ConceptsActions.js +4 -1
- package/src/concepts/components/ConceptsUpdateButton.js +3 -2
- package/src/concepts/components/ConceptsUploadButton.js +21 -2
- package/src/concepts/components/ConceptsUploadEvents.js +24 -0
- package/src/concepts/components/ConceptsUploadEventsTable.js +166 -0
- package/src/concepts/components/__tests__/ConceptForm.spec.js +23 -1
- package/src/concepts/components/__tests__/ConceptsActions.spec.js +1 -0
- package/src/concepts/components/__tests__/ConceptsUploadButton.spec.js +35 -13
- package/src/concepts/components/__tests__/ConceptsUploadEventsTable.spec.js +98 -0
- package/src/concepts/components/__tests__/__snapshots__/ConceptsUploadButton.spec.js.snap +75 -24
- package/src/concepts/components/__tests__/__snapshots__/ConceptsUploadEventsTable.spec.js.snap +115 -0
- package/src/concepts/hooks/useUploadEvents.js +11 -0
- package/src/concepts/reducers/uploadConceptsFile.js +0 -1
- package/src/concepts/selectors/__tests__/getConceptUploadEventColumns.spec.js +20 -0
- package/src/concepts/selectors/getConceptUploadEventColumns.js +72 -0
- package/src/concepts/selectors/index.js +4 -0
- package/src/concepts/styles/conceptsUploadEventColumns.less +24 -0
- package/src/messages/en.js +45 -9
- package/src/messages/es.js +46 -9
- package/src/reducers/__tests__/bgMessage.spec.js +12 -9
- package/src/reducers/bgMessage.js +12 -9
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
CONCEPT_LINKS_MANAGEMENT,
|
|
11
11
|
CONCEPT_VERSION,
|
|
12
12
|
CONCEPTS_BULK_UPDATE,
|
|
13
|
+
CONCEPTS_BULK_UPLOAD_EVENTS,
|
|
13
14
|
CONCEPTS_NEW,
|
|
14
15
|
CONCEPTS_PENDING,
|
|
15
16
|
CONCEPTS_DEPRECATED,
|
|
@@ -29,6 +30,7 @@ import Concepts from "./Concepts";
|
|
|
29
30
|
import ConceptsBulkUpdate from "./ConceptsBulkUpdate";
|
|
30
31
|
import ConceptsLoader from "./ConceptsLoader";
|
|
31
32
|
import ConceptSubscriptionLoader from "./ConceptSubscriptionLoader";
|
|
33
|
+
import ConceptsUploadEvents from "./ConceptsUploadEvents";
|
|
32
34
|
|
|
33
35
|
const RelationTagsLoader = React.lazy(() =>
|
|
34
36
|
import("@truedat/lm/components/RelationTagsLoader")
|
|
@@ -56,6 +58,13 @@ export const ConceptRoutes = ({ concept, conceptLoaded, templatesLoaded }) => {
|
|
|
56
58
|
};
|
|
57
59
|
return (
|
|
58
60
|
<>
|
|
61
|
+
<Route
|
|
62
|
+
exact
|
|
63
|
+
path={CONCEPTS_BULK_UPLOAD_EVENTS}
|
|
64
|
+
render={() =>
|
|
65
|
+
authorized ? <ConceptsUploadEvents /> : <Unauthorized />
|
|
66
|
+
}
|
|
67
|
+
/>
|
|
59
68
|
<Route
|
|
60
69
|
exact
|
|
61
70
|
path={CONCEPT_LINKS_MANAGEMENT}
|
|
@@ -18,6 +18,7 @@ export const ConceptsActions = ({
|
|
|
18
18
|
hidden,
|
|
19
19
|
upload,
|
|
20
20
|
update,
|
|
21
|
+
canAutoPublish,
|
|
21
22
|
}) => {
|
|
22
23
|
const { formatMessage, locale } = useIntl();
|
|
23
24
|
|
|
@@ -42,7 +43,7 @@ export const ConceptsActions = ({
|
|
|
42
43
|
id: "concepts.actions.download.tooltip",
|
|
43
44
|
})}
|
|
44
45
|
/>
|
|
45
|
-
{upload ? <ConceptsUploadButton /> : null}
|
|
46
|
+
{upload ? <ConceptsUploadButton canAutoPublish={canAutoPublish} /> : null}
|
|
46
47
|
{update ? <ConceptsUpdateButton /> : null}
|
|
47
48
|
</div>
|
|
48
49
|
);
|
|
@@ -56,6 +57,7 @@ ConceptsActions.propTypes = {
|
|
|
56
57
|
downloadConcepts: PropTypes.func,
|
|
57
58
|
upload: PropTypes.bool,
|
|
58
59
|
update: PropTypes.bool,
|
|
60
|
+
canAutoPublish: PropTypes.bool,
|
|
59
61
|
};
|
|
60
62
|
|
|
61
63
|
ConceptsActions.defaultProps = {
|
|
@@ -71,6 +73,7 @@ const mapStateToProps = ({
|
|
|
71
73
|
_.isEmpty(conceptActions) && conceptsActions?.create ? CONCEPTS_NEW : null,
|
|
72
74
|
conceptsDownloading: conceptsDownloading,
|
|
73
75
|
hidden: _.isEmpty(conceptsActions),
|
|
76
|
+
canAutoPublish: conceptsActions?.autoPublish && true,
|
|
74
77
|
});
|
|
75
78
|
|
|
76
79
|
export default connect(mapStateToProps, { downloadConcepts, uploadConcepts })(
|
|
@@ -58,8 +58,9 @@ const mapStateToProps = ({
|
|
|
58
58
|
updateUrl:
|
|
59
59
|
conceptCount !== 0 &&
|
|
60
60
|
!conceptsLoading &&
|
|
61
|
-
existingTemplate(conceptFilters, conceptActiveFilters)
|
|
62
|
-
|
|
61
|
+
existingTemplate(conceptFilters, conceptActiveFilters)
|
|
62
|
+
? CONCEPTS_BULK_UPDATE
|
|
63
|
+
: null,
|
|
63
64
|
});
|
|
64
65
|
|
|
65
66
|
export default connect(mapStateToProps)(ConceptsUpdateButton);
|
|
@@ -11,11 +11,29 @@ const uploadAction = {
|
|
|
11
11
|
method: "POST",
|
|
12
12
|
href: API_BUSINESS_CONCEPT_VERSIONS_UPLOAD,
|
|
13
13
|
};
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
export const ConceptsUploadButton = ({
|
|
15
|
+
uploadConcepts,
|
|
16
|
+
loading,
|
|
17
|
+
canAutoPublish,
|
|
18
|
+
}) => {
|
|
16
19
|
const { formatMessage, locale } = useIntl();
|
|
20
|
+
const extraAction = {
|
|
21
|
+
key: "yesWithAutoPublish",
|
|
22
|
+
primary: true,
|
|
23
|
+
content: formatMessage({ id: "uploadModal.accept.publish" }),
|
|
24
|
+
onClick: (data) => {
|
|
25
|
+
data.append("auto_publish", canAutoPublish);
|
|
26
|
+
return uploadConcepts({
|
|
27
|
+
action: "upload",
|
|
28
|
+
data,
|
|
29
|
+
lang: locale,
|
|
30
|
+
...uploadAction,
|
|
31
|
+
});
|
|
32
|
+
},
|
|
33
|
+
};
|
|
17
34
|
return (
|
|
18
35
|
<UploadModal
|
|
36
|
+
extraAction={canAutoPublish && extraAction}
|
|
19
37
|
icon="upload"
|
|
20
38
|
trigger={
|
|
21
39
|
<Button
|
|
@@ -50,6 +68,7 @@ export const ConceptsUploadButton = ({ uploadConcepts, loading }) => {
|
|
|
50
68
|
ConceptsUploadButton.propTypes = {
|
|
51
69
|
uploadConcepts: PropTypes.func,
|
|
52
70
|
loading: PropTypes.bool,
|
|
71
|
+
canAutoPublish: PropTypes.bool,
|
|
53
72
|
};
|
|
54
73
|
|
|
55
74
|
const mapStateToProps = ({ uploadConceptsFile: { loading } }) => ({
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
import { Header, Icon, Segment } from "semantic-ui-react";
|
|
4
|
+
import { FormattedMessage } from "react-intl";
|
|
5
|
+
import ConceptsUploadEventsTable from "./ConceptsUploadEventsTable";
|
|
6
|
+
|
|
7
|
+
export const ConceptsUploadEvents = () => (
|
|
8
|
+
<Segment>
|
|
9
|
+
<Header as="h2">
|
|
10
|
+
<Icon circular name="cogs" />
|
|
11
|
+
<Header.Content>
|
|
12
|
+
<FormattedMessage id="concepts.upload.header" />
|
|
13
|
+
<Header.Subheader>
|
|
14
|
+
<FormattedMessage id="concepts.upload.subheader" />
|
|
15
|
+
</Header.Subheader>
|
|
16
|
+
</Header.Content>
|
|
17
|
+
</Header>
|
|
18
|
+
<Segment attached="bottom">
|
|
19
|
+
<ConceptsUploadEventsTable />
|
|
20
|
+
</Segment>
|
|
21
|
+
</Segment>
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
export default ConceptsUploadEvents;
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import React, { useState } from "react";
|
|
2
|
+
import PropTypes from "prop-types";
|
|
3
|
+
import { connect } from "react-redux";
|
|
4
|
+
|
|
5
|
+
import _ from "lodash/fp";
|
|
6
|
+
|
|
7
|
+
import { FormattedMessage } from "react-intl";
|
|
8
|
+
import { Table } from "semantic-ui-react";
|
|
9
|
+
import { useIntl } from "react-intl";
|
|
10
|
+
import { columnDecorator } from "@truedat/core/services";
|
|
11
|
+
|
|
12
|
+
import { useUploadEvents } from "../hooks/useUploadEvents";
|
|
13
|
+
import { getConceptUploadEventColumns } from "../selectors";
|
|
14
|
+
|
|
15
|
+
import "../styles/conceptsUploadEventColumns.less";
|
|
16
|
+
|
|
17
|
+
const getColumnsWithData = (conceptsResults, columns) =>
|
|
18
|
+
_.filter((column) =>
|
|
19
|
+
_.any(_.flow(columnDecorator(column), _.negate(_.isEmpty)))(conceptsResults)
|
|
20
|
+
)(columns);
|
|
21
|
+
|
|
22
|
+
const messagesImp = (data) => {
|
|
23
|
+
return _.has("errors")(data)
|
|
24
|
+
? _.flow(
|
|
25
|
+
_.propOr([], "errors"),
|
|
26
|
+
_.map((error) => ({
|
|
27
|
+
id: error.body.message,
|
|
28
|
+
context: {
|
|
29
|
+
...error.body.context,
|
|
30
|
+
},
|
|
31
|
+
defaultMessage: "concepts.upload.failed.success.errors",
|
|
32
|
+
}))
|
|
33
|
+
)(data)
|
|
34
|
+
: [];
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const ConceptsUploadEventsTable = ({ getColumns }) => {
|
|
38
|
+
const { formatMessage } = useIntl();
|
|
39
|
+
const [eventExpandedIndex, setEventExpandedIndex] = useState(null);
|
|
40
|
+
|
|
41
|
+
const { data, loading } = useUploadEvents();
|
|
42
|
+
|
|
43
|
+
const events =
|
|
44
|
+
data && !loading
|
|
45
|
+
? _.reduce(
|
|
46
|
+
(acc, event) => ({
|
|
47
|
+
...acc,
|
|
48
|
+
[`${event.task_reference}_${event.status}`]: {
|
|
49
|
+
...event,
|
|
50
|
+
response: {
|
|
51
|
+
...event.response,
|
|
52
|
+
translatedHeader: !event.response
|
|
53
|
+
? ""
|
|
54
|
+
: formatMessage(
|
|
55
|
+
{
|
|
56
|
+
id: _.isEmpty(event.response.errors)
|
|
57
|
+
? "concepts.upload.success.header"
|
|
58
|
+
: "concepts.upload.success.header_with_errors",
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
count_created: event.response.created.length,
|
|
62
|
+
count_updated: event.response.updated.length,
|
|
63
|
+
count_errors: event.response.errors.length,
|
|
64
|
+
}
|
|
65
|
+
),
|
|
66
|
+
translatedErrors: _.map((error) =>
|
|
67
|
+
formatMessage({ id: error.id }, error.context)
|
|
68
|
+
)(messagesImp(event.response)),
|
|
69
|
+
},
|
|
70
|
+
expanded: false,
|
|
71
|
+
},
|
|
72
|
+
}),
|
|
73
|
+
{},
|
|
74
|
+
data.data
|
|
75
|
+
)
|
|
76
|
+
: [];
|
|
77
|
+
|
|
78
|
+
const columns = getColumnsWithData(events, getColumns());
|
|
79
|
+
|
|
80
|
+
const toggleExpanded = (eventKey) =>
|
|
81
|
+
eventExpandedIndex === eventKey
|
|
82
|
+
? setEventExpandedIndex(null)
|
|
83
|
+
: setEventExpandedIndex(eventKey);
|
|
84
|
+
|
|
85
|
+
return (
|
|
86
|
+
<>
|
|
87
|
+
{!_.isEmpty(events) && (
|
|
88
|
+
<Table sortable selectable>
|
|
89
|
+
<Table.Header>
|
|
90
|
+
<Table.Row>
|
|
91
|
+
{columns.map((column, i) => {
|
|
92
|
+
return (
|
|
93
|
+
<Table.HeaderCell
|
|
94
|
+
key={i}
|
|
95
|
+
width={column.width}
|
|
96
|
+
content={formatMessage({
|
|
97
|
+
id: `concepts.upload.props.${column.name}`,
|
|
98
|
+
defaultMessage: column.name,
|
|
99
|
+
})}
|
|
100
|
+
/>
|
|
101
|
+
);
|
|
102
|
+
})}
|
|
103
|
+
</Table.Row>
|
|
104
|
+
</Table.Header>
|
|
105
|
+
<Table.Body>
|
|
106
|
+
{_.map(
|
|
107
|
+
(eventKey) => (
|
|
108
|
+
<Table.Row
|
|
109
|
+
className={
|
|
110
|
+
eventKey === eventExpandedIndex ? "expanded" : "contracted"
|
|
111
|
+
}
|
|
112
|
+
key={eventKey}
|
|
113
|
+
onClick={() => toggleExpanded(eventKey)}
|
|
114
|
+
>
|
|
115
|
+
{eventKey !== eventExpandedIndex ? (
|
|
116
|
+
columns &&
|
|
117
|
+
columns.map((column, key) => (
|
|
118
|
+
<Table.Cell
|
|
119
|
+
key={key}
|
|
120
|
+
textAlign={column.textAlign}
|
|
121
|
+
content={columnDecorator(column)({
|
|
122
|
+
...events[eventKey],
|
|
123
|
+
formatMessage,
|
|
124
|
+
})}
|
|
125
|
+
/>
|
|
126
|
+
))
|
|
127
|
+
) : (
|
|
128
|
+
<Table.Cell colSpan={columns.length}>
|
|
129
|
+
{events[eventKey].file_hash ? (
|
|
130
|
+
<>
|
|
131
|
+
<FormattedMessage
|
|
132
|
+
id={`concepts.upload.props.file_hash`}
|
|
133
|
+
/>
|
|
134
|
+
: {events[eventKey].file_hash}
|
|
135
|
+
</>
|
|
136
|
+
) : null}
|
|
137
|
+
{columns.map((column, key) => (
|
|
138
|
+
<div key={key}>
|
|
139
|
+
{columnDecorator(column)({
|
|
140
|
+
...events[eventKey],
|
|
141
|
+
formatMessage,
|
|
142
|
+
})}
|
|
143
|
+
</div>
|
|
144
|
+
))}
|
|
145
|
+
</Table.Cell>
|
|
146
|
+
)}
|
|
147
|
+
</Table.Row>
|
|
148
|
+
),
|
|
149
|
+
Object.keys(events)
|
|
150
|
+
)}
|
|
151
|
+
</Table.Body>
|
|
152
|
+
</Table>
|
|
153
|
+
)}
|
|
154
|
+
</>
|
|
155
|
+
);
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
ConceptsUploadEventsTable.propTypes = {
|
|
159
|
+
getColumns: PropTypes.func,
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
const mapStateToProps = (state) => ({
|
|
163
|
+
getColumns: () => getConceptUploadEventColumns(state),
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
export default connect(mapStateToProps)(ConceptsUploadEventsTable);
|
|
@@ -9,6 +9,27 @@ import {
|
|
|
9
9
|
} from "@truedat/test/mocks";
|
|
10
10
|
import ConceptForm from "../ConceptForm";
|
|
11
11
|
|
|
12
|
+
jest.mock("@truedat/ai/hooks/useSuggestions", () => {
|
|
13
|
+
const originalModule = jest.requireActual("@truedat/ai/hooks/useSuggestions");
|
|
14
|
+
|
|
15
|
+
return {
|
|
16
|
+
__esModule: true,
|
|
17
|
+
...originalModule,
|
|
18
|
+
useAvailabilityCheck: () => ({
|
|
19
|
+
trigger: jest.fn(
|
|
20
|
+
() =>
|
|
21
|
+
new Promise(() => ({
|
|
22
|
+
data: {
|
|
23
|
+
data: {
|
|
24
|
+
status: "ok",
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
}))
|
|
28
|
+
),
|
|
29
|
+
}),
|
|
30
|
+
};
|
|
31
|
+
});
|
|
32
|
+
|
|
12
33
|
const state = {
|
|
13
34
|
conceptActions: { create: {} },
|
|
14
35
|
conceptActionLoading: "",
|
|
@@ -39,13 +60,14 @@ describe("<ConceptForm />", () => {
|
|
|
39
60
|
});
|
|
40
61
|
|
|
41
62
|
it("renders dynamic fields when template is selected", async () => {
|
|
42
|
-
const { findByText, getByText, queryByText } = render(
|
|
63
|
+
const { findByText, getByText, queryByText, getAllByRole } = render(
|
|
43
64
|
<ConceptForm />,
|
|
44
65
|
renderOpts
|
|
45
66
|
);
|
|
46
67
|
await waitFor(() => expect(queryByText(/lazy/i)).not.toBeInTheDocument());
|
|
47
68
|
await waitFor(() => expect(queryByText(/fooDomain/)).toBeInTheDocument());
|
|
48
69
|
userEvent.click(await findByText("fooDomain"));
|
|
70
|
+
userEvent.type(getAllByRole("textbox")[1], "name");
|
|
49
71
|
userEvent.click(await findByText("template1"));
|
|
50
72
|
expect(getByText("field1")).toBeInTheDocument();
|
|
51
73
|
});
|
|
@@ -1,23 +1,45 @@
|
|
|
1
1
|
// only admin user
|
|
2
2
|
import React from "react";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import
|
|
3
|
+
import { render } from "@truedat/test/render";
|
|
4
|
+
import { screen, waitFor } from "@testing-library/react";
|
|
5
|
+
import userEvent from "@testing-library/user-event";
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
// see https://github.com/airbnb/enzyme/issues/2176#issuecomment-532361526
|
|
9
|
-
jest.spyOn(React, "useContext").mockImplementation(() => intl);
|
|
7
|
+
import { ConceptsUploadButton } from "../ConceptsUploadButton";
|
|
10
8
|
|
|
11
9
|
jest.mock("@truedat/core/hooks", () => ({
|
|
12
|
-
useAuthorized: jest.fn(() => true)
|
|
10
|
+
useAuthorized: jest.fn(() => true),
|
|
13
11
|
}));
|
|
14
12
|
|
|
13
|
+
const props = {
|
|
14
|
+
uploadConcepts: jest.fn(),
|
|
15
|
+
loading: false,
|
|
16
|
+
canAutoPublish: false,
|
|
17
|
+
};
|
|
18
|
+
|
|
15
19
|
describe("<ConceptsUploadButton />", () => {
|
|
16
|
-
it("matches the latest snapshot", () => {
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
it("matches the latest snapshot", async () => {
|
|
21
|
+
const { getByRole } = render(<ConceptsUploadButton {...props} />);
|
|
22
|
+
userEvent.click(getByRole("button"));
|
|
23
|
+
await waitFor(() =>
|
|
24
|
+
expect(screen.getByRole("presentation")).toBeInTheDocument()
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
expect(screen.getByRole("presentation")).toMatchSnapshot();
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it("autopublish button is displayed if canAutoPublish is true", async () => {
|
|
31
|
+
const customProps = {
|
|
32
|
+
...props,
|
|
33
|
+
canAutoPublish: true,
|
|
34
|
+
};
|
|
35
|
+
const { getByRole } = render(<ConceptsUploadButton {...customProps} />);
|
|
36
|
+
userEvent.click(getByRole("button"));
|
|
37
|
+
await waitFor(() =>
|
|
38
|
+
expect(screen.getByRole("presentation")).toBeInTheDocument()
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
expect(
|
|
42
|
+
screen.getByRole("button", { name: /publish/i })
|
|
43
|
+
).toBeInTheDocument();
|
|
22
44
|
});
|
|
23
45
|
});
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import userEvent from "@testing-library/user-event";
|
|
3
|
+
import { render } from "@truedat/test/render";
|
|
4
|
+
import ConceptsUploadEventsTable from "../ConceptsUploadEventsTable";
|
|
5
|
+
|
|
6
|
+
const events = [
|
|
7
|
+
{
|
|
8
|
+
file_hash: "99E400B91D164F8F0A39F400CA323C8F",
|
|
9
|
+
inserted_at: "2022-04-23T15:53:24.638484Z",
|
|
10
|
+
message: null,
|
|
11
|
+
response: {
|
|
12
|
+
errors: [],
|
|
13
|
+
created: [4825521, 4825561, 4825593],
|
|
14
|
+
updated: [4825522, 4825562, 4825594],
|
|
15
|
+
},
|
|
16
|
+
status: "COMPLETED",
|
|
17
|
+
task_reference: "0.3225053307.1609564164.100549",
|
|
18
|
+
user_id: 467,
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
file_hash: "47D90FDF1AD967BD7DBBDAE28664278E",
|
|
22
|
+
inserted_at: "2022-04-23T15:14:48.770275Z",
|
|
23
|
+
message: null,
|
|
24
|
+
response: {
|
|
25
|
+
errors: [
|
|
26
|
+
{
|
|
27
|
+
error_type: "test_field_error",
|
|
28
|
+
body: {
|
|
29
|
+
message: "concepts.upload.failed.invalid_field_value",
|
|
30
|
+
context: {
|
|
31
|
+
field: "gdpr",
|
|
32
|
+
type: "grpd_template",
|
|
33
|
+
row: 4,
|
|
34
|
+
error: "Missing value",
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
error_type: "test_forbidden_update",
|
|
40
|
+
body: {
|
|
41
|
+
message: "concepts.upload.failed.forbidden_update",
|
|
42
|
+
context: {
|
|
43
|
+
type: "test_template",
|
|
44
|
+
row: 2,
|
|
45
|
+
domain: "forbidden_domain",
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
error_type: "test_name_not_available",
|
|
51
|
+
body: {
|
|
52
|
+
message: "concepts.upload.failed.name_not_available",
|
|
53
|
+
context: {
|
|
54
|
+
type: "test_template",
|
|
55
|
+
row: 7,
|
|
56
|
+
name: "test_name_not_available",
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
],
|
|
61
|
+
created: [],
|
|
62
|
+
updated: [],
|
|
63
|
+
},
|
|
64
|
+
status: "COMPLETED",
|
|
65
|
+
task_reference: "0.3225053307.1609564162.101463",
|
|
66
|
+
user_id: 467,
|
|
67
|
+
},
|
|
68
|
+
];
|
|
69
|
+
|
|
70
|
+
jest.mock("../../hooks/useUploadEvents.js", () => {
|
|
71
|
+
const originalModule = jest.requireActual("../../hooks/useUploadEvents.js");
|
|
72
|
+
|
|
73
|
+
return {
|
|
74
|
+
__esModule: true,
|
|
75
|
+
...originalModule,
|
|
76
|
+
useUploadEvents: jest.fn(() => ({
|
|
77
|
+
data: {
|
|
78
|
+
data: events,
|
|
79
|
+
},
|
|
80
|
+
loading: false,
|
|
81
|
+
})),
|
|
82
|
+
};
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
describe("<ConceptsUploadEventsTable />", () => {
|
|
86
|
+
it("matches the latest snapshot", () => {
|
|
87
|
+
const { container } = render(<ConceptsUploadEventsTable />);
|
|
88
|
+
expect(container).toMatchSnapshot();
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it("toggles row horizontal view when row is clicked", () => {
|
|
92
|
+
const { getAllByRole } = render(<ConceptsUploadEventsTable />);
|
|
93
|
+
const dataRow = getAllByRole("row")[1];
|
|
94
|
+
expect(dataRow).toHaveClass("contracted");
|
|
95
|
+
userEvent.click(dataRow);
|
|
96
|
+
expect(dataRow).toHaveClass("expanded");
|
|
97
|
+
});
|
|
98
|
+
});
|
|
@@ -1,29 +1,80 @@
|
|
|
1
1
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
2
|
|
|
3
3
|
exports[`<ConceptsUploadButton /> matches the latest snapshot 1`] = `
|
|
4
|
-
<
|
|
5
|
-
|
|
6
|
-
<Memo(MemoizedFormattedMessage)
|
|
7
|
-
id="concepts.actions.upload.confirmation.content"
|
|
8
|
-
/>
|
|
9
|
-
}
|
|
10
|
-
handleSubmit={[Function]}
|
|
11
|
-
header={
|
|
12
|
-
<Memo(MemoizedFormattedMessage)
|
|
13
|
-
id="concepts.actions.upload.confirmation.header"
|
|
14
|
-
/>
|
|
15
|
-
}
|
|
4
|
+
<div
|
|
5
|
+
class="ui small modal transition visible active"
|
|
16
6
|
icon="upload"
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
7
|
+
role="presentation"
|
|
8
|
+
>
|
|
9
|
+
<i
|
|
10
|
+
aria-hidden="true"
|
|
11
|
+
class="close icon"
|
|
12
|
+
/>
|
|
13
|
+
<div
|
|
14
|
+
class="header"
|
|
15
|
+
>
|
|
16
|
+
Confirm bulk upload
|
|
17
|
+
</div>
|
|
18
|
+
<div
|
|
19
|
+
class="content"
|
|
20
|
+
>
|
|
21
|
+
<div
|
|
22
|
+
aria-disabled="false"
|
|
23
|
+
class=""
|
|
24
|
+
data-testid="fileDropZone"
|
|
25
|
+
style="position: relative; width: 100%; margin-bottom: 10px; border: 1px dashed gray; border-radius: 5px;"
|
|
26
|
+
>
|
|
27
|
+
<div
|
|
28
|
+
style="padding: 20px; width: 100%; height: 100%;"
|
|
29
|
+
>
|
|
30
|
+
<div
|
|
31
|
+
class="ui center aligned container"
|
|
32
|
+
>
|
|
33
|
+
<i
|
|
34
|
+
aria-hidden="true"
|
|
35
|
+
class="cloud upload huge icon"
|
|
36
|
+
/>
|
|
37
|
+
<p>
|
|
38
|
+
Drag an drop file or click to select file
|
|
39
|
+
</p>
|
|
40
|
+
<button
|
|
41
|
+
class="ui secondary button"
|
|
42
|
+
>
|
|
43
|
+
<i
|
|
44
|
+
aria-hidden="true"
|
|
45
|
+
class="upload icon"
|
|
46
|
+
/>
|
|
47
|
+
Upload file
|
|
48
|
+
</button>
|
|
49
|
+
</div>
|
|
50
|
+
</div>
|
|
51
|
+
<input
|
|
52
|
+
autocomplete="off"
|
|
53
|
+
multiple=""
|
|
54
|
+
style="position: absolute; top: 0px; right: 0px; bottom: 0px; left: 0px; opacity: 0.00001; pointer-events: none;"
|
|
55
|
+
type="file"
|
|
56
|
+
/>
|
|
57
|
+
</div>
|
|
58
|
+
<h2>
|
|
59
|
+
Selected file
|
|
60
|
+
</h2>
|
|
61
|
+
<ul />
|
|
62
|
+
</div>
|
|
63
|
+
<div
|
|
64
|
+
class="actions"
|
|
65
|
+
>
|
|
66
|
+
<button
|
|
67
|
+
class="ui secondary button"
|
|
68
|
+
>
|
|
69
|
+
Cancel
|
|
70
|
+
</button>
|
|
71
|
+
<button
|
|
72
|
+
class="ui primary disabled button"
|
|
73
|
+
disabled=""
|
|
74
|
+
tabindex="-1"
|
|
75
|
+
>
|
|
76
|
+
Upload and update
|
|
77
|
+
</button>
|
|
78
|
+
</div>
|
|
79
|
+
</div>
|
|
29
80
|
`;
|