@truedat/cx 4.41.3 → 4.41.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/CHANGELOG.md +11 -0
- package/package.json +4 -4
- package/src/jobs/components/Job.js +11 -11
- package/src/jobs/components/JobRoutes.js +2 -2
- package/src/jobs/components/JobRow.js +7 -3
- package/src/jobs/components/Jobs.js +16 -28
- package/src/jobs/components/JobsTable.js +80 -92
- package/src/jobs/components/JobsView.js +23 -0
- package/src/jobs/components/SourceJobs.js +29 -0
- package/src/jobs/components/__tests__/JobRow.spec.js +44 -23
- package/src/jobs/components/__tests__/Jobs.spec.js +33 -8
- package/src/jobs/components/__tests__/JobsTable.spec.js +50 -81
- package/src/jobs/components/__tests__/JobsView.spec.js +39 -0
- package/src/jobs/components/__tests__/SourceJobs.spec.js +38 -0
- package/src/jobs/components/__tests__/__snapshots__/Job.spec.js.snap +3 -4
- package/src/jobs/components/__tests__/__snapshots__/JobRow.spec.js.snap +40 -32
- package/src/jobs/components/__tests__/__snapshots__/Jobs.spec.js.snap +136 -35
- package/src/jobs/components/__tests__/__snapshots__/JobsTable.spec.js.snap +104 -227
- package/src/jobs/components/__tests__/__snapshots__/JobsView.spec.js.snap +167 -0
- package/src/jobs/components/__tests__/__snapshots__/SourceJobs.spec.js.snap +115 -0
- package/src/jobs/components/index.js +1 -3
- package/src/jobs/selectors/index.js +4 -2
- package/src/jobs/selectors/{getJobColumns.js → jobColumnsSelector.js} +11 -27
- package/src/jobs/selectors/jobRowsSelector.js +14 -0
- package/src/jobs/selectors/sourceJobColumnsSelector.js +35 -0
- package/src/messages/en.js +9 -1
- package/src/messages/es.js +9 -1
- package/src/reducers/cxMessage.js +15 -1
- package/src/sources/api/fragments.js +48 -0
- package/src/sources/api/mutations.js +51 -0
- package/src/sources/api/queries.js +52 -0
- package/src/sources/api.js +1 -2
- package/src/sources/components/EditSource.js +5 -29
- package/src/sources/components/JobForm.js +2 -2
- package/src/sources/components/NewJob.js +10 -23
- package/src/sources/components/Source.js +12 -76
- package/src/sources/components/SourceActions.js +13 -21
- package/src/sources/components/SourceBreadcrumbs.js +1 -1
- package/src/sources/components/SourceConfiguration.js +60 -0
- package/src/sources/components/SourceDetail.js +90 -0
- package/src/sources/components/SourceForm.js +50 -53
- package/src/sources/components/SourceHeader.js +29 -0
- package/src/sources/components/SourceRoutes.js +25 -89
- package/src/sources/components/SourceSelector.js +53 -44
- package/src/sources/components/SourceTabs.js +54 -0
- package/src/sources/components/Sources.js +7 -20
- package/src/sources/components/SourcesTable.js +3 -4
- package/src/sources/components/__tests__/EditSource.spec.js +1 -2
- package/src/sources/components/__tests__/Source.spec.js +1 -1
- package/src/sources/components/__tests__/SourceActions.spec.js +3 -1
- package/src/sources/components/__tests__/SourceDetail.spec.js +45 -0
- package/src/sources/components/__tests__/SourceForm.spec.js +16 -31
- package/src/sources/components/__tests__/SourceHeader.spec.js +16 -0
- package/src/sources/components/__tests__/SourceSelector.spec.js +44 -0
- package/src/sources/components/__tests__/SourceTabs.spec.js +21 -0
- package/src/sources/components/__tests__/Sources.spec.js +5 -2
- package/src/sources/components/__tests__/__snapshots__/EditSource.spec.js.snap +12 -35
- package/src/sources/components/__tests__/__snapshots__/NewSource.spec.js.snap +1 -1
- package/src/sources/components/__tests__/__snapshots__/Source.spec.js.snap +23 -65
- package/src/sources/components/__tests__/__snapshots__/SourceActions.spec.js.snap +1 -1
- package/src/sources/components/__tests__/__snapshots__/SourceDetail.spec.js.snap +154 -0
- package/src/sources/components/__tests__/__snapshots__/SourceForm.spec.js.snap +37 -14
- package/src/sources/components/__tests__/__snapshots__/SourceHeader.spec.js.snap +85 -0
- package/src/sources/components/__tests__/__snapshots__/SourceSelector.spec.js.snap +68 -0
- package/src/sources/components/__tests__/__snapshots__/SourceTabs.spec.js.snap +22 -0
- package/src/sources/components/__tests__/__snapshots__/Sources.spec.js.snap +2 -2
- package/src/sources/components/__tests__/__snapshots__/SourcesTable.spec.js.snap +5 -5
- package/src/sources/components/index.js +1 -4
- package/src/sources/reducers/__tests__/sourceRedirect.spec.js +26 -21
- package/src/sources/reducers/__tests__/sourceUpdateStatus.spec.js +9 -9
- package/src/sources/reducers/index.js +1 -12
- package/src/sources/reducers/sourceRedirect.js +20 -10
- package/src/sources/reducers/sourceUpdateStatus.js +5 -5
- package/src/sources/routines.js +0 -3
- package/src/sources/sagas/__tests__/createSource.spec.js +35 -20
- package/src/sources/sagas/__tests__/deleteSource.spec.js +29 -14
- package/src/sources/sagas/__tests__/disableSource.spec.js +2 -8
- package/src/sources/sagas/__tests__/enableSource.spec.js +2 -8
- package/src/sources/sagas/__tests__/updateSource.spec.js +33 -15
- package/src/sources/sagas/createSource.js +24 -14
- package/src/sources/sagas/deleteSource.js +14 -15
- package/src/sources/sagas/disableSource.js +1 -17
- package/src/sources/sagas/enableSource.js +1 -17
- package/src/sources/sagas/index.js +0 -9
- package/src/sources/sagas/updateSource.js +18 -15
- package/src/sources/components/DynamicSourceForm.js +0 -60
- package/src/sources/components/SourceLoader.js +0 -59
- package/src/sources/components/SourcesLoader.js +0 -39
- package/src/sources/components/__tests__/DynamicSourceForm.spec.js +0 -89
- package/src/sources/components/__tests__/SourceLoader.spec.js +0 -54
- package/src/sources/components/__tests__/SourcesLoader.spec.js +0 -53
- package/src/sources/components/__tests__/__snapshots__/DynamicSourceForm.spec.js.snap +0 -8
- package/src/sources/components/__tests__/__snapshots__/SourceLoader.spec.js.snap +0 -3
- package/src/sources/components/__tests__/__snapshots__/SourcesLoader.spec.js.snap +0 -3
- package/src/sources/reducers/__tests__/source.spec.js +0 -44
- package/src/sources/reducers/__tests__/sourceLoading.spec.js +0 -30
- package/src/sources/reducers/__tests__/sources.spec.js +0 -37
- package/src/sources/reducers/__tests__/sourcesLoading.spec.js +0 -30
- package/src/sources/reducers/source.js +0 -35
- package/src/sources/reducers/sourceLoading.js +0 -16
- package/src/sources/reducers/sources.js +0 -28
- package/src/sources/reducers/sourcesLoading.js +0 -16
- package/src/sources/sagas/__tests__/fetchSource.spec.js +0 -71
- package/src/sources/sagas/__tests__/fetchSources.spec.js +0 -69
- package/src/sources/sagas/__tests__/updateSourceConfig.spec.js +0 -73
- package/src/sources/sagas/fetchSource.js +0 -30
- package/src/sources/sagas/fetchSources.js +0 -26
- package/src/sources/sagas/updateSourceConfig.js +0 -29
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [4.41.4] 2022-04-04
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- [TD-4126] Improved source views to include a tab with the source's jobs
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
|
|
11
|
+
- [TD-4450] Use GraphQL API for querying and mutating sources, avoiding use of
|
|
12
|
+
global state
|
|
13
|
+
|
|
3
14
|
## [4.38.2]
|
|
4
15
|
|
|
5
16
|
### Changed
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@truedat/cx",
|
|
3
|
-
"version": "4.41.
|
|
3
|
+
"version": "4.41.4",
|
|
4
4
|
"description": "Truedat Web Connectors",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"jsnext:main": "src/index.js",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"@babel/plugin-transform-modules-commonjs": "^7.15.0",
|
|
32
32
|
"@babel/preset-env": "^7.15.0",
|
|
33
33
|
"@babel/preset-react": "^7.14.5",
|
|
34
|
-
"@truedat/test": "4.41.
|
|
34
|
+
"@truedat/test": "4.41.4",
|
|
35
35
|
"babel-jest": "^27.0.6",
|
|
36
36
|
"babel-plugin-dynamic-import-node": "^2.3.3",
|
|
37
37
|
"babel-plugin-lodash": "^3.3.4",
|
|
@@ -85,7 +85,7 @@
|
|
|
85
85
|
]
|
|
86
86
|
},
|
|
87
87
|
"dependencies": {
|
|
88
|
-
"@truedat/core": "4.41.
|
|
88
|
+
"@truedat/core": "4.41.4",
|
|
89
89
|
"lodash": "^4.17.21",
|
|
90
90
|
"match-sorter": "^6.3.1",
|
|
91
91
|
"path-to-regexp": "^1.7.0",
|
|
@@ -103,5 +103,5 @@
|
|
|
103
103
|
"react-dom": ">= 16.8.6 < 17",
|
|
104
104
|
"semantic-ui-react": ">= 0.88.2 < 2.1"
|
|
105
105
|
},
|
|
106
|
-
"gitHead": "
|
|
106
|
+
"gitHead": "c7038921dceb3cb9d6950fd9f57b23126ee0d8b0"
|
|
107
107
|
}
|
|
@@ -4,15 +4,15 @@ import PropTypes from "prop-types";
|
|
|
4
4
|
import { useIntl } from "react-intl";
|
|
5
5
|
import Moment from "react-moment";
|
|
6
6
|
import { connect } from "react-redux";
|
|
7
|
-
import { Header, Message,
|
|
7
|
+
import { Header, Message, Feed } from "semantic-ui-react";
|
|
8
8
|
|
|
9
|
-
const dateDecorator = date =>
|
|
9
|
+
const dateDecorator = (date) =>
|
|
10
10
|
date && <Moment locale="es" date={date} format="YYYY-MM-DD HH:mm:ss.SSS" />;
|
|
11
11
|
|
|
12
12
|
export const icons = {
|
|
13
13
|
STARTED: { name: "play circle outline", color: "green" },
|
|
14
14
|
SUCCEEDED: { name: "check circle outline", color: "green" },
|
|
15
|
-
FAILED: { name: "warning circle", color: "red" }
|
|
15
|
+
FAILED: { name: "warning circle", color: "red" },
|
|
16
16
|
};
|
|
17
17
|
|
|
18
18
|
export const Event = ({ inserted_at, message, type }) => (
|
|
@@ -29,7 +29,7 @@ export const Event = ({ inserted_at, message, type }) => (
|
|
|
29
29
|
Event.propTypes = {
|
|
30
30
|
inserted_at: PropTypes.string,
|
|
31
31
|
message: PropTypes.string,
|
|
32
|
-
type: PropTypes.string
|
|
32
|
+
type: PropTypes.string,
|
|
33
33
|
};
|
|
34
34
|
|
|
35
35
|
export const EventFeed = ({ events }) =>
|
|
@@ -42,7 +42,7 @@ export const EventFeed = ({ events }) =>
|
|
|
42
42
|
) : null;
|
|
43
43
|
|
|
44
44
|
EventFeed.propTypes = {
|
|
45
|
-
events: PropTypes.array
|
|
45
|
+
events: PropTypes.array,
|
|
46
46
|
};
|
|
47
47
|
|
|
48
48
|
export const JobPendingMessage = () => {
|
|
@@ -58,13 +58,13 @@ export const JobPendingMessage = () => {
|
|
|
58
58
|
export const Job = ({ job }) => {
|
|
59
59
|
const { formatMessage } = useIntl();
|
|
60
60
|
return job ? (
|
|
61
|
-
|
|
61
|
+
<>
|
|
62
62
|
<Header
|
|
63
|
-
as="
|
|
64
|
-
content={job?.
|
|
63
|
+
as="h4"
|
|
64
|
+
content={job?.external_id}
|
|
65
65
|
subheader={formatMessage({
|
|
66
66
|
id: `jobType.${job?.type}.label`,
|
|
67
|
-
defaultMessage: job?.type
|
|
67
|
+
defaultMessage: job?.type,
|
|
68
68
|
})}
|
|
69
69
|
/>
|
|
70
70
|
{isEmpty(job?._embedded?.events) ? (
|
|
@@ -72,12 +72,12 @@ export const Job = ({ job }) => {
|
|
|
72
72
|
) : (
|
|
73
73
|
<EventFeed events={job?._embedded?.events} />
|
|
74
74
|
)}
|
|
75
|
-
|
|
75
|
+
</>
|
|
76
76
|
) : null;
|
|
77
77
|
};
|
|
78
78
|
|
|
79
79
|
Job.propTypes = {
|
|
80
|
-
job: PropTypes.object
|
|
80
|
+
job: PropTypes.object,
|
|
81
81
|
};
|
|
82
82
|
|
|
83
83
|
export const mapStateToProps = ({ job }) => ({ job });
|
|
@@ -7,7 +7,7 @@ import Job from "./Job";
|
|
|
7
7
|
import JobBreadcrumbs from "./JobBreadcrumbs";
|
|
8
8
|
import JobFiltersLoader from "./JobFiltersLoader";
|
|
9
9
|
import JobLoader from "./JobLoader";
|
|
10
|
-
import
|
|
10
|
+
import JobsView from "./JobsView";
|
|
11
11
|
import JobsLoader from "./JobsLoader";
|
|
12
12
|
|
|
13
13
|
export const JobRoutes = () => {
|
|
@@ -34,7 +34,7 @@ export const JobRoutes = () => {
|
|
|
34
34
|
<>
|
|
35
35
|
<JobsLoader />
|
|
36
36
|
<JobFiltersLoader />
|
|
37
|
-
<
|
|
37
|
+
<JobsView />
|
|
38
38
|
</>
|
|
39
39
|
) : (
|
|
40
40
|
<Unauthorized />
|
|
@@ -8,9 +8,13 @@ import { linkTo } from "@truedat/core/routes";
|
|
|
8
8
|
|
|
9
9
|
export const JobRow = ({ job, columns }) => {
|
|
10
10
|
const history = useHistory();
|
|
11
|
-
const id =
|
|
11
|
+
const id = job?.externalId || job?.external_id;
|
|
12
|
+
const sourceId = job?.source_id;
|
|
13
|
+
const url = sourceId
|
|
14
|
+
? linkTo.SOURCE_JOB({ sourceId, id })
|
|
15
|
+
: linkTo.JOB({ id });
|
|
12
16
|
return _.isEmpty(columns) || _.isEmpty(job) ? null : (
|
|
13
|
-
<Table.Row key={id} onClick={() => history.push(
|
|
17
|
+
<Table.Row key={id} onClick={() => history.push(url)}>
|
|
14
18
|
{columns.map((column, i) => (
|
|
15
19
|
<Table.Cell
|
|
16
20
|
key={i}
|
|
@@ -24,7 +28,7 @@ export const JobRow = ({ job, columns }) => {
|
|
|
24
28
|
|
|
25
29
|
JobRow.propTypes = {
|
|
26
30
|
job: PropTypes.object.isRequired,
|
|
27
|
-
columns: PropTypes.array.isRequired
|
|
31
|
+
columns: PropTypes.array.isRequired,
|
|
28
32
|
};
|
|
29
33
|
|
|
30
34
|
export default JobRow;
|
|
@@ -1,43 +1,31 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import PropTypes from "prop-types";
|
|
3
3
|
import { connect } from "react-redux";
|
|
4
|
-
import {
|
|
5
|
-
import { FormattedMessage } from "react-intl";
|
|
6
|
-
|
|
4
|
+
import { Dimmer, Loader } from "semantic-ui-react";
|
|
7
5
|
import JobsSearch from "./JobsSearch";
|
|
8
6
|
import JobsTable from "./JobsTable";
|
|
9
7
|
import JobsLabelResults from "./JobsLabelResults";
|
|
10
8
|
import JobSelectedFilters from "./JobSelectedFilters";
|
|
11
9
|
import JobsPagination from "./JobsPagination";
|
|
12
10
|
|
|
13
|
-
export const Jobs = ({ jobsLoading }) => (
|
|
14
|
-
|
|
15
|
-
<
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
<
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
<
|
|
25
|
-
|
|
26
|
-
<JobSelectedFilters />
|
|
27
|
-
<Dimmer.Dimmable dimmed={jobsLoading}>
|
|
28
|
-
<Dimmer active={jobsLoading} inverted>
|
|
29
|
-
<Loader />
|
|
30
|
-
</Dimmer>
|
|
31
|
-
</Dimmer.Dimmable>
|
|
32
|
-
<JobsLabelResults />
|
|
33
|
-
<JobsTable />
|
|
34
|
-
<JobsPagination />
|
|
35
|
-
</Segment>
|
|
36
|
-
</Segment>
|
|
11
|
+
export const Jobs = ({ columns, jobsLoading }) => (
|
|
12
|
+
<>
|
|
13
|
+
<JobsSearch />
|
|
14
|
+
<JobSelectedFilters />
|
|
15
|
+
<Dimmer.Dimmable dimmed={jobsLoading}>
|
|
16
|
+
<Dimmer active={jobsLoading} inverted>
|
|
17
|
+
<Loader />
|
|
18
|
+
</Dimmer>
|
|
19
|
+
</Dimmer.Dimmable>
|
|
20
|
+
<JobsLabelResults />
|
|
21
|
+
<JobsTable columns={columns} />
|
|
22
|
+
<JobsPagination />
|
|
23
|
+
</>
|
|
37
24
|
);
|
|
38
25
|
|
|
39
26
|
Jobs.propTypes = {
|
|
40
|
-
jobsLoading: PropTypes.bool
|
|
27
|
+
jobsLoading: PropTypes.bool,
|
|
28
|
+
columns: PropTypes.array,
|
|
41
29
|
};
|
|
42
30
|
|
|
43
31
|
const mapStateToProps = ({ jobsLoading }) => ({ jobsLoading });
|
|
@@ -1,108 +1,96 @@
|
|
|
1
1
|
import _ from "lodash/fp";
|
|
2
|
-
import React from "react";
|
|
2
|
+
import React, { useEffect } from "react";
|
|
3
3
|
import PropTypes from "prop-types";
|
|
4
4
|
import { connect } from "react-redux";
|
|
5
5
|
import { Table, Header, Icon } from "semantic-ui-react";
|
|
6
6
|
import { FormattedMessage } from "react-intl";
|
|
7
7
|
import { getSortInfo, sortColumn } from "@truedat/core/services/sort";
|
|
8
8
|
import { sortJobs } from "../routines";
|
|
9
|
-
import {
|
|
9
|
+
import { jobRowsSelector, jobColumnsSelector } from "../selectors";
|
|
10
10
|
import JobRow from "./JobRow";
|
|
11
11
|
|
|
12
|
-
export
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
12
|
+
export const JobsTable = ({
|
|
13
|
+
columns,
|
|
14
|
+
jobs,
|
|
15
|
+
jobsLoading,
|
|
16
|
+
jobsSorting,
|
|
17
|
+
sortJobs,
|
|
18
|
+
}) => {
|
|
19
|
+
const [sortBy, setSortBy] = React.useState(null);
|
|
20
|
+
const [direction, setDirection] = React.useState(null);
|
|
21
|
+
useEffect(() => {
|
|
22
|
+
const { column, direction } = getSortInfo(jobsSorting);
|
|
23
|
+
setSortBy(column);
|
|
24
|
+
setDirection(direction);
|
|
25
|
+
}, [jobsSorting]);
|
|
19
26
|
|
|
20
|
-
|
|
21
|
-
state = {
|
|
22
|
-
sortedColumn: _.prop("column")(getSortInfo(this.props.jobsSorting)),
|
|
23
|
-
direction: _.prop("direction")(getSortInfo(this.props.jobsSorting)),
|
|
24
|
-
};
|
|
27
|
+
const sortable = _.some(_.path("sort.name"))(columns);
|
|
25
28
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
+
return (
|
|
30
|
+
<>
|
|
31
|
+
{!_.isEmpty(jobs) && (
|
|
32
|
+
<Table sortable={sortable} selectable>
|
|
33
|
+
<Table.Header>
|
|
34
|
+
<Table.Row>
|
|
35
|
+
{columns &&
|
|
36
|
+
columns.map((column, key) => (
|
|
37
|
+
<Table.HeaderCell
|
|
38
|
+
key={key}
|
|
39
|
+
width={column.width}
|
|
40
|
+
content={
|
|
41
|
+
<FormattedMessage
|
|
42
|
+
id={`jobs.props.${column.header || column.name}`}
|
|
43
|
+
defaultMessage={column.header || column.name}
|
|
44
|
+
/>
|
|
45
|
+
}
|
|
46
|
+
sorted={
|
|
47
|
+
_.path("sort.name")(column) === sortBy ? direction : null
|
|
48
|
+
}
|
|
49
|
+
className={_.path("sort.name")(column) ? "" : "disabled"}
|
|
50
|
+
onClick={() =>
|
|
51
|
+
sortColumn(
|
|
52
|
+
column,
|
|
53
|
+
sortJobs,
|
|
54
|
+
setDirection,
|
|
55
|
+
setSortBy,
|
|
56
|
+
direction,
|
|
57
|
+
sortBy
|
|
58
|
+
)
|
|
59
|
+
}
|
|
60
|
+
/>
|
|
61
|
+
))}
|
|
62
|
+
</Table.Row>
|
|
63
|
+
</Table.Header>
|
|
64
|
+
<Table.Body>
|
|
65
|
+
{jobs.map((c, i) => (
|
|
66
|
+
<JobRow key={i} job={c} columns={columns} />
|
|
67
|
+
))}
|
|
68
|
+
</Table.Body>
|
|
69
|
+
</Table>
|
|
70
|
+
)}
|
|
71
|
+
{_.isEmpty(jobs) && !jobsLoading && (
|
|
72
|
+
<Header as="h4">
|
|
73
|
+
<Icon name="search" />
|
|
74
|
+
<Header.Content>
|
|
75
|
+
<FormattedMessage id="jobs.search.results.empty" />
|
|
76
|
+
</Header.Content>
|
|
77
|
+
</Header>
|
|
78
|
+
)}
|
|
79
|
+
</>
|
|
80
|
+
);
|
|
81
|
+
};
|
|
29
82
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
83
|
+
JobsTable.propTypes = {
|
|
84
|
+
jobsLoading: PropTypes.bool,
|
|
85
|
+
jobsSorting: PropTypes.array,
|
|
86
|
+
jobs: PropTypes.array,
|
|
87
|
+
columns: PropTypes.array,
|
|
88
|
+
sortJobs: PropTypes.func,
|
|
89
|
+
};
|
|
33
90
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
this.props.jobsSorting
|
|
38
|
-
);
|
|
39
|
-
this.setState({ sortedColumn, direction });
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
render() {
|
|
44
|
-
const { jobs, columns, jobsLoading, sortJobs } = this.props;
|
|
45
|
-
const { sortedColumn, direction } = this.state;
|
|
46
|
-
|
|
47
|
-
return (
|
|
48
|
-
<>
|
|
49
|
-
{!_.isEmpty(jobs) && (
|
|
50
|
-
<Table sortable selectable>
|
|
51
|
-
<Table.Header>
|
|
52
|
-
<Table.Row>
|
|
53
|
-
{columns &&
|
|
54
|
-
columns.map((column, key) => (
|
|
55
|
-
<Table.HeaderCell
|
|
56
|
-
key={key}
|
|
57
|
-
width={column.width}
|
|
58
|
-
content={
|
|
59
|
-
<FormattedMessage
|
|
60
|
-
id={`jobs.props.${column.header || column.name}`}
|
|
61
|
-
/>
|
|
62
|
-
}
|
|
63
|
-
sorted={
|
|
64
|
-
_.path("sort.name")(column) === sortedColumn
|
|
65
|
-
? direction
|
|
66
|
-
: null
|
|
67
|
-
}
|
|
68
|
-
className={_.path("sort.name")(column) ? "" : "disabled"}
|
|
69
|
-
onClick={() =>
|
|
70
|
-
sortColumn(
|
|
71
|
-
column,
|
|
72
|
-
sortJobs,
|
|
73
|
-
this.setDirection,
|
|
74
|
-
this.setColumn,
|
|
75
|
-
direction,
|
|
76
|
-
sortedColumn
|
|
77
|
-
)
|
|
78
|
-
}
|
|
79
|
-
/>
|
|
80
|
-
))}
|
|
81
|
-
</Table.Row>
|
|
82
|
-
</Table.Header>
|
|
83
|
-
<Table.Body>
|
|
84
|
-
{jobs.map((c, i) => (
|
|
85
|
-
<JobRow key={i} job={c} columns={columns} />
|
|
86
|
-
))}
|
|
87
|
-
</Table.Body>
|
|
88
|
-
</Table>
|
|
89
|
-
)}
|
|
90
|
-
{_.isEmpty(jobs) && !jobsLoading && (
|
|
91
|
-
<Header as="h4">
|
|
92
|
-
<Icon name="search" />
|
|
93
|
-
<Header.Content>
|
|
94
|
-
<FormattedMessage id="jobs.search.results.empty" />
|
|
95
|
-
</Header.Content>
|
|
96
|
-
</Header>
|
|
97
|
-
)}
|
|
98
|
-
</>
|
|
99
|
-
);
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
const mapStateToProps = (state) => ({
|
|
104
|
-
columns: getJobColumns(state),
|
|
105
|
-
jobs: getJobsRows(state),
|
|
91
|
+
const mapStateToProps = (state, { columns }) => ({
|
|
92
|
+
columns: columns || jobColumnsSelector(state),
|
|
93
|
+
jobs: jobRowsSelector(state),
|
|
106
94
|
jobsLoading: state.jobsLoading,
|
|
107
95
|
jobsSorting: _.path("jobQuery.sort")(state),
|
|
108
96
|
});
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Header, Icon, Segment } from "semantic-ui-react";
|
|
3
|
+
import { FormattedMessage } from "react-intl";
|
|
4
|
+
import Jobs from "./Jobs";
|
|
5
|
+
|
|
6
|
+
export const JobsView = () => (
|
|
7
|
+
<Segment>
|
|
8
|
+
<Header as="h2">
|
|
9
|
+
<Icon circular name="cogs" />
|
|
10
|
+
<Header.Content>
|
|
11
|
+
<FormattedMessage id="jobs.header" />
|
|
12
|
+
<Header.Subheader>
|
|
13
|
+
<FormattedMessage id="jobs.subheader" />
|
|
14
|
+
</Header.Subheader>
|
|
15
|
+
</Header.Content>
|
|
16
|
+
</Header>
|
|
17
|
+
<Segment attached="bottom">
|
|
18
|
+
<Jobs />
|
|
19
|
+
</Segment>
|
|
20
|
+
</Segment>
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
export default JobsView;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import PropTypes from "prop-types";
|
|
3
|
+
import { connect } from "react-redux";
|
|
4
|
+
import { sourceJobColumnsSelector } from "../selectors";
|
|
5
|
+
import JobFiltersLoader from "./JobFiltersLoader";
|
|
6
|
+
import JobsLoader from "./JobsLoader";
|
|
7
|
+
import Jobs from "./Jobs";
|
|
8
|
+
|
|
9
|
+
export const SourceJobs = ({ source, columns }) => {
|
|
10
|
+
const defaultFilters = { source_id: [source?.id] };
|
|
11
|
+
return (
|
|
12
|
+
<>
|
|
13
|
+
<JobsLoader defaultFilters={defaultFilters} />
|
|
14
|
+
<JobFiltersLoader defaultFilters={defaultFilters} />
|
|
15
|
+
<Jobs columns={columns} />
|
|
16
|
+
</>
|
|
17
|
+
);
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
SourceJobs.propTypes = {
|
|
21
|
+
source: PropTypes.object,
|
|
22
|
+
columns: PropTypes.array,
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const mapStateToProps = (state) => ({
|
|
26
|
+
columns: sourceJobColumnsSelector(state),
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
export default connect(mapStateToProps)(SourceJobs);
|
|
@@ -1,37 +1,58 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
2
|
+
import userEvent from "@testing-library/user-event";
|
|
3
|
+
import { render } from "@truedat/test/render";
|
|
4
|
+
import { jobColumnsSelector } from "../../selectors";
|
|
5
|
+
import JobRow from "../JobRow";
|
|
6
|
+
|
|
7
|
+
const columns = jobColumnsSelector({});
|
|
8
|
+
const job = {
|
|
9
|
+
source: {
|
|
10
|
+
externalId: "source external_id_2",
|
|
11
|
+
type: "source_type_2",
|
|
12
|
+
},
|
|
13
|
+
source_id: 123,
|
|
14
|
+
status: "init",
|
|
15
|
+
message: "Job started",
|
|
16
|
+
end_date: "2020-01-21 16:31",
|
|
17
|
+
external_id: "foo",
|
|
18
|
+
};
|
|
19
|
+
const renderOpts = {};
|
|
4
20
|
|
|
5
21
|
const mockHistory = {
|
|
6
|
-
push: jest.fn()
|
|
22
|
+
push: jest.fn(),
|
|
7
23
|
};
|
|
8
24
|
|
|
9
25
|
jest.mock("react-router-dom", () => ({
|
|
10
26
|
...jest.requireActual("react-router-dom"),
|
|
11
|
-
useHistory: () => mockHistory
|
|
27
|
+
useHistory: () => mockHistory,
|
|
12
28
|
}));
|
|
13
29
|
|
|
14
30
|
describe("<JobRow />", () => {
|
|
15
31
|
it("matches the latest snapshot", () => {
|
|
16
|
-
const columns = [
|
|
17
|
-
{ name: "source.external_id" },
|
|
18
|
-
{ name: "source.type" },
|
|
19
|
-
{ name: "status" },
|
|
20
|
-
{ name: "message" },
|
|
21
|
-
{ name: "end_date" }
|
|
22
|
-
];
|
|
23
|
-
const job = {
|
|
24
|
-
source: {
|
|
25
|
-
external_id: "source external_id_2",
|
|
26
|
-
type: "source_type_2"
|
|
27
|
-
},
|
|
28
|
-
status: "init",
|
|
29
|
-
message: "Job started",
|
|
30
|
-
end_date: "2020-01-21 16:31",
|
|
31
|
-
external_id: "foo"
|
|
32
|
-
};
|
|
33
32
|
const props = { columns, job };
|
|
34
|
-
const
|
|
35
|
-
|
|
33
|
+
const { container } = render(
|
|
34
|
+
<table>
|
|
35
|
+
<tbody>
|
|
36
|
+
<JobRow {...props} />
|
|
37
|
+
</tbody>
|
|
38
|
+
</table>,
|
|
39
|
+
renderOpts
|
|
40
|
+
);
|
|
41
|
+
expect(container).toMatchSnapshot();
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it("navigates to the job route when row is clicked", () => {
|
|
45
|
+
const props = { columns, job };
|
|
46
|
+
const { getByText } = render(
|
|
47
|
+
<table>
|
|
48
|
+
<tbody>
|
|
49
|
+
<JobRow {...props} />
|
|
50
|
+
</tbody>
|
|
51
|
+
</table>,
|
|
52
|
+
renderOpts
|
|
53
|
+
);
|
|
54
|
+
userEvent.click(getByText(/source_type_2/));
|
|
55
|
+
expect(mockHistory.push.mock.calls.length).toBe(1);
|
|
56
|
+
expect(mockHistory.push.mock.calls[0][0]).toBe("/sources/123/jobs/foo");
|
|
36
57
|
});
|
|
37
58
|
});
|
|
@@ -1,13 +1,38 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
1
|
+
import React, { Suspense } from "react";
|
|
2
|
+
import { render } from "@truedat/test/render";
|
|
3
|
+
import en from "../../../messages/en";
|
|
4
|
+
import Jobs from "../Jobs";
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
|
|
6
|
+
const jobs = [
|
|
7
|
+
{
|
|
8
|
+
external_id: "external_id",
|
|
9
|
+
source: {
|
|
10
|
+
external_id: "source external_id",
|
|
11
|
+
type: "source_type",
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
external_id: "external_id_2",
|
|
16
|
+
source: {
|
|
17
|
+
external_id: "source external_id_2",
|
|
18
|
+
type: "source_type_2",
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
];
|
|
22
|
+
const state = { jobs, jobCount: 42 };
|
|
23
|
+
const renderOpts = {
|
|
24
|
+
messages: { en },
|
|
25
|
+
state,
|
|
26
|
+
};
|
|
7
27
|
|
|
28
|
+
describe("<Jobs />", () => {
|
|
8
29
|
it("matches the latest snapshot", () => {
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
30
|
+
const { container } = render(
|
|
31
|
+
<Suspense fallback={null}>
|
|
32
|
+
<Jobs />
|
|
33
|
+
</Suspense>,
|
|
34
|
+
renderOpts
|
|
35
|
+
);
|
|
36
|
+
expect(container).toMatchSnapshot();
|
|
12
37
|
});
|
|
13
38
|
});
|