@truedat/dd 4.44.2 → 4.44.5
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 +10 -0
- package/package.json +23 -19
- package/src/api/mutations.js +27 -0
- package/src/api/queries.js +24 -0
- package/src/api.js +2 -0
- package/src/components/DictionaryRoutes.js +7 -5
- package/src/components/EditDomainPopup.js +1 -1
- package/src/components/FilteredNav.js +9 -9
- package/src/components/GrantFilters.js +1 -5
- package/src/components/GrantRequestApprovalPopup.js +0 -1
- package/src/components/ImplementationStructuresLoader.js +14 -11
- package/src/components/PendingStructureNotes.js +11 -5
- package/src/components/ReferenceDataset.js +23 -0
- package/src/components/ReferenceDatasetActions.js +88 -0
- package/src/components/ReferenceDatasetBreadcrumbs.js +22 -0
- package/src/components/ReferenceDatasetCreate.js +36 -0
- package/src/components/ReferenceDatasetDetail.js +42 -0
- package/src/components/ReferenceDatasetForm.js +109 -0
- package/src/components/ReferenceDatasetHeader.js +32 -0
- package/src/components/ReferenceDatasetRoutes.js +56 -0
- package/src/components/ReferenceDatasetTable.js +42 -0
- package/src/components/ReferenceDatasets.js +61 -0
- package/src/components/ReferenceDatasetsTable.js +105 -0
- package/src/components/StructureConfidentialButton.js +1 -1
- package/src/components/StructureFilters.js +1 -5
- package/src/components/StructureNotesEdit.js +6 -6
- package/src/components/StructureProperties.js +4 -1
- package/src/components/StructureTagsRoutes.js +0 -1
- package/src/components/StructureTypesCrumbs.js +0 -1
- package/src/components/StructureVersionListItem.js +2 -2
- package/src/components/StructureView.js +1 -3
- package/src/components/SystemForm.js +1 -1
- package/src/components/__tests__/ImplementationStructuresLoader.spec.js +12 -54
- package/src/components/__tests__/LineageEventsTable.spec.js +2 -7
- package/src/components/__tests__/LineageRoutes.spec.js +4 -4
- package/src/components/__tests__/PendingStructureNoteRow.spec.js +1 -17
- package/src/components/__tests__/PendingStructureNotes.spec.js +5 -33
- package/src/components/__tests__/ReferenceDataset.spec.js +64 -0
- package/src/components/__tests__/ReferenceDatasetActions.spec.js +17 -0
- package/src/components/__tests__/ReferenceDatasetBreadcrumbs.spec.js +12 -0
- package/src/components/__tests__/ReferenceDatasetCreate.spec.js +12 -0
- package/src/components/__tests__/ReferenceDatasetDetail.spec.js +37 -0
- package/src/components/__tests__/ReferenceDatasetForm.spec.js +51 -0
- package/src/components/__tests__/ReferenceDatasetHeader.spec.js +17 -0
- package/src/components/__tests__/ReferenceDatasetRoutes.spec.js +74 -0
- package/src/components/__tests__/ReferenceDatasetTable.spec.js +18 -0
- package/src/components/__tests__/ReferenceDatasets.spec.js +32 -0
- package/src/components/__tests__/ReferenceDatasetsTable.spec.js +22 -0
- package/src/components/__tests__/StructureConfidentialButton.spec.js +26 -30
- package/src/components/__tests__/StructureGrantRequestButton.spec.js +4 -23
- package/src/components/__tests__/StructureNoteActions.spec.js +2 -19
- package/src/components/__tests__/StructureNotes.spec.js +3 -15
- package/src/components/__tests__/StructureNotesEdit.spec.js +5 -25
- package/src/components/__tests__/StructureProperties.spec.js +6 -8
- package/src/components/__tests__/StructureTagForm.spec.js +1 -3
- package/src/components/__tests__/StructureVersionListItem.spec.js +4 -4
- package/src/components/__tests__/StructuresOptions.spec.js +1 -7
- package/src/components/__tests__/StructuresUploadEventsTable.spec.js +3 -4
- package/src/components/__tests__/__snapshots__/DictionaryRoutes.spec.js.snap +4 -0
- package/src/components/__tests__/__snapshots__/LineageRoutes.spec.js.snap +1 -20
- package/src/components/__tests__/__snapshots__/PendingStructureNotes.spec.js.snap +3 -3
- package/src/components/__tests__/__snapshots__/ProfileExecution.spec.js.snap +2 -1
- package/src/components/__tests__/__snapshots__/ReferenceDataset.spec.js.snap +365 -0
- package/src/components/__tests__/__snapshots__/ReferenceDatasetActions.spec.js.snap +65 -0
- package/src/components/__tests__/__snapshots__/ReferenceDatasetBreadcrumbs.spec.js.snap +25 -0
- package/src/components/__tests__/__snapshots__/ReferenceDatasetCreate.spec.js.snap +98 -0
- package/src/components/__tests__/__snapshots__/ReferenceDatasetDetail.spec.js.snap +135 -0
- package/src/components/__tests__/__snapshots__/ReferenceDatasetForm.spec.js.snap +61 -0
- package/src/components/__tests__/__snapshots__/ReferenceDatasetHeader.spec.js.snap +95 -0
- package/src/components/__tests__/__snapshots__/ReferenceDatasetRoutes.spec.js.snap +414 -0
- package/src/components/__tests__/__snapshots__/ReferenceDatasetTable.spec.js.snap +75 -0
- package/src/components/__tests__/__snapshots__/ReferenceDatasets.spec.js.snap +128 -0
- package/src/components/__tests__/__snapshots__/ReferenceDatasetsTable.spec.js.snap +86 -0
- package/src/components/__tests__/__snapshots__/StructureConfidentialButton.spec.js.snap +13 -33
- package/src/components/__tests__/__snapshots__/StructureNavClassified.spec.js.snap +2 -2
- package/src/components/__tests__/__snapshots__/StructureNotes.spec.js.snap +9 -9
- package/src/components/__tests__/__snapshots__/StructureNotesEdit.spec.js.snap +2 -2
- package/src/components/__tests__/__snapshots__/StructureProperties.spec.js.snap +76 -71
- package/src/components/__tests__/__snapshots__/StructureVersionListItem.spec.js.snap +31 -64
- package/src/messages/en.js +18 -0
- package/src/messages/es.js +20 -0
- package/src/reducers/__tests__/ddMessage.spec.js +26 -5
- package/src/reducers/__tests__/graph.spec.js +1 -6
- package/src/reducers/__tests__/referenceDatasetSaving.spec.js +44 -0
- package/src/reducers/__tests__/structureRedirect.spec.js +37 -13
- package/src/reducers/ddMessage.js +26 -1
- package/src/reducers/index.js +2 -0
- package/src/reducers/referenceDatasetSaving.js +16 -0
- package/src/reducers/structureRedirect.js +36 -15
- package/src/reducers/structuresUploadEvents.js +0 -1
- package/src/routines.js +35 -74
- package/src/sagas/__tests__/createReferenceDataset.spec.js +90 -0
- package/src/sagas/__tests__/deleteReferenceDataset.spec.js +81 -0
- package/src/sagas/__tests__/updateReferenceDataset.spec.js +116 -0
- package/src/sagas/createReferenceDataset.js +34 -0
- package/src/sagas/deleteReferenceDataset.js +29 -0
- package/src/sagas/downloadReferenceDataset.js +44 -0
- package/src/sagas/index.js +31 -22
- package/src/sagas/updateReferenceDataset.js +35 -0
- package/src/selectors/getRelationSortingCriteria.js +3 -5
- package/src/selectors/getTabVisibility.js +1 -4
- package/src/components/__tests__/__snapshots__/ImplementationStructuresLoader.spec.js.snap +0 -30
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import _ from "lodash/fp";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import PropTypes from "prop-types";
|
|
4
|
+
import { useForm, Controller } from "react-hook-form";
|
|
5
|
+
import { connect } from "react-redux";
|
|
6
|
+
import { Button, Form } from "semantic-ui-react";
|
|
7
|
+
import { useIntl } from "react-intl";
|
|
8
|
+
import { HistoryBackButton } from "@truedat/core/components";
|
|
9
|
+
|
|
10
|
+
const MAX_SIZE_MB = 2;
|
|
11
|
+
const MAX_SIZE = MAX_SIZE_MB * 1024 * 1024; // 2MB
|
|
12
|
+
|
|
13
|
+
const datasetValidator = (formatMessage) => (value) =>
|
|
14
|
+
_.isNull(value)
|
|
15
|
+
? true
|
|
16
|
+
: value.size > MAX_SIZE
|
|
17
|
+
? formatMessage(
|
|
18
|
+
{ id: "widget.image.error.too_big" },
|
|
19
|
+
{ size_mb: MAX_SIZE_MB }
|
|
20
|
+
)
|
|
21
|
+
: true;
|
|
22
|
+
|
|
23
|
+
export const ReferenceDatasetForm = ({ saving, dataset = {}, onSubmit }) => {
|
|
24
|
+
const { formatMessage } = useIntl();
|
|
25
|
+
const { handleSubmit, control, formState } = useForm({
|
|
26
|
+
mode: "all",
|
|
27
|
+
defaultValues: { name: dataset?.name || "", file: null },
|
|
28
|
+
});
|
|
29
|
+
const { isDirty, isValid } = formState;
|
|
30
|
+
const disabled = saving || !isDirty || !isValid;
|
|
31
|
+
return (
|
|
32
|
+
<Form onSubmit={handleSubmit(onSubmit)}>
|
|
33
|
+
<Controller
|
|
34
|
+
control={control}
|
|
35
|
+
name="name"
|
|
36
|
+
rules={{
|
|
37
|
+
required: formatMessage(
|
|
38
|
+
{ id: "form.validation.required" },
|
|
39
|
+
{ prop: formatMessage({ id: "referenceDataset.name" }) }
|
|
40
|
+
),
|
|
41
|
+
}}
|
|
42
|
+
render={({
|
|
43
|
+
field: { onBlur, onChange, value },
|
|
44
|
+
fieldState: { error },
|
|
45
|
+
}) => (
|
|
46
|
+
<Form.Input
|
|
47
|
+
autoComplete="off"
|
|
48
|
+
error={!!error}
|
|
49
|
+
label={formatMessage({ id: "referenceDataset.name" })}
|
|
50
|
+
onBlur={onBlur}
|
|
51
|
+
onChange={(_e, { value }) => onChange(value)}
|
|
52
|
+
value={value || ""}
|
|
53
|
+
required
|
|
54
|
+
/>
|
|
55
|
+
)}
|
|
56
|
+
/>
|
|
57
|
+
<Controller
|
|
58
|
+
control={control}
|
|
59
|
+
name="file"
|
|
60
|
+
rules={{
|
|
61
|
+
validate: datasetValidator(formatMessage),
|
|
62
|
+
required: dataset?.id
|
|
63
|
+
? false
|
|
64
|
+
: formatMessage(
|
|
65
|
+
{ id: "form.validation.required" },
|
|
66
|
+
{ prop: formatMessage({ id: "referenceDataset.file" }) }
|
|
67
|
+
),
|
|
68
|
+
}}
|
|
69
|
+
render={({ field: { onBlur, onChange }, fieldState: { error } }) => (
|
|
70
|
+
<Form.Input
|
|
71
|
+
type="file"
|
|
72
|
+
error={error?.message}
|
|
73
|
+
label={formatMessage({ id: "referenceDataset.file" })}
|
|
74
|
+
onBlur={onBlur}
|
|
75
|
+
onChange={(e) => onChange(e.target.files[0])}
|
|
76
|
+
required={!dataset?.id}
|
|
77
|
+
input={{ accept: "text/*,.csv,.txt" }}
|
|
78
|
+
/>
|
|
79
|
+
)}
|
|
80
|
+
/>
|
|
81
|
+
<div className="actions">
|
|
82
|
+
<Button
|
|
83
|
+
floated="right"
|
|
84
|
+
type="submit"
|
|
85
|
+
primary
|
|
86
|
+
loading={saving}
|
|
87
|
+
disabled={disabled}
|
|
88
|
+
content={formatMessage({ id: "actions.save" })}
|
|
89
|
+
/>
|
|
90
|
+
<HistoryBackButton
|
|
91
|
+
content={formatMessage({ id: "actions.cancel" })}
|
|
92
|
+
disabled={saving}
|
|
93
|
+
/>
|
|
94
|
+
</div>
|
|
95
|
+
</Form>
|
|
96
|
+
);
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
ReferenceDatasetForm.propTypes = {
|
|
100
|
+
onSubmit: PropTypes.func,
|
|
101
|
+
saving: PropTypes.bool,
|
|
102
|
+
dataset: PropTypes.object,
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
export const mapStateToProps = ({ referenceDatasetSaving }) => ({
|
|
106
|
+
saving: !!referenceDatasetSaving,
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
export default connect(mapStateToProps)(ReferenceDatasetForm);
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import _ from "lodash/fp";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import PropTypes from "prop-types";
|
|
4
|
+
import { FormattedMessage } from "react-intl";
|
|
5
|
+
import { Header, Icon, Grid } from "semantic-ui-react";
|
|
6
|
+
import ReferenceDatasetActions from "./ReferenceDatasetActions";
|
|
7
|
+
|
|
8
|
+
export const ReferenceDatasetHeader = ({ dataset }) =>
|
|
9
|
+
_.isEmpty(dataset) ? null : (
|
|
10
|
+
<Grid>
|
|
11
|
+
<Grid.Column width={8}>
|
|
12
|
+
<Header as="h2">
|
|
13
|
+
<Icon circular name="list ol" />
|
|
14
|
+
<Header.Content>
|
|
15
|
+
{dataset.name}
|
|
16
|
+
<Header.Subheader>
|
|
17
|
+
<FormattedMessage id="referenceDataset" />
|
|
18
|
+
</Header.Subheader>
|
|
19
|
+
</Header.Content>
|
|
20
|
+
</Header>
|
|
21
|
+
</Grid.Column>
|
|
22
|
+
<Grid.Column width={8} textAlign="right">
|
|
23
|
+
<ReferenceDatasetActions dataset={dataset} />
|
|
24
|
+
</Grid.Column>
|
|
25
|
+
</Grid>
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
ReferenceDatasetHeader.propTypes = {
|
|
29
|
+
dataset: PropTypes.object.isRequired,
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export default ReferenceDatasetHeader;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import _ from "lodash/fp";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import { Route, Switch, useParams } from "react-router-dom";
|
|
4
|
+
import { useQuery } from "@apollo/client";
|
|
5
|
+
import { Unauthorized, Loading } from "@truedat/core/components";
|
|
6
|
+
import { useAuthorized } from "@truedat/core/hooks";
|
|
7
|
+
import {
|
|
8
|
+
REFERENCE_DATASETS,
|
|
9
|
+
REFERENCE_DATASET_NEW,
|
|
10
|
+
REFERENCE_DATASET,
|
|
11
|
+
} from "@truedat/core/routes";
|
|
12
|
+
import { REFERENCE_DATASET_QUERY } from "../api/queries";
|
|
13
|
+
import ReferenceDataset from "./ReferenceDataset";
|
|
14
|
+
import ReferenceDatasets from "./ReferenceDatasets";
|
|
15
|
+
import ReferenceDatasetCreate from "./ReferenceDatasetCreate";
|
|
16
|
+
|
|
17
|
+
export const DatasetLoader = () => {
|
|
18
|
+
const { id } = useParams();
|
|
19
|
+
const { loading, error, data } = useQuery(REFERENCE_DATASET_QUERY, {
|
|
20
|
+
variables: { id },
|
|
21
|
+
});
|
|
22
|
+
if (error) return null;
|
|
23
|
+
if (loading) return <Loading />;
|
|
24
|
+
const dataset = data?.referenceDataset;
|
|
25
|
+
return _.isEmpty(dataset) ? null : <ReferenceDataset dataset={dataset} />;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export const AuthorizedReferenceDatasetRoutes = () => (
|
|
29
|
+
<Switch>
|
|
30
|
+
<Route
|
|
31
|
+
path={REFERENCE_DATASET_NEW}
|
|
32
|
+
exact
|
|
33
|
+
render={() => <ReferenceDatasetCreate />}
|
|
34
|
+
/>
|
|
35
|
+
<Route
|
|
36
|
+
path={REFERENCE_DATASETS}
|
|
37
|
+
exact
|
|
38
|
+
render={() => <ReferenceDatasets />}
|
|
39
|
+
/>
|
|
40
|
+
<Route path={REFERENCE_DATASET} render={() => <DatasetLoader />} />
|
|
41
|
+
</Switch>
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
export const ReferenceDatasetRoutes = () => {
|
|
45
|
+
const authorized = useAuthorized();
|
|
46
|
+
return (
|
|
47
|
+
<Route
|
|
48
|
+
path={REFERENCE_DATASETS}
|
|
49
|
+
render={() =>
|
|
50
|
+
authorized ? <AuthorizedReferenceDatasetRoutes /> : <Unauthorized />
|
|
51
|
+
}
|
|
52
|
+
/>
|
|
53
|
+
);
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export default ReferenceDatasetRoutes;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import _ from "lodash/fp";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import PropTypes from "prop-types";
|
|
4
|
+
import { Table } from "semantic-ui-react";
|
|
5
|
+
|
|
6
|
+
const truncateOpts = { length: 100 };
|
|
7
|
+
|
|
8
|
+
export const DataRow = ({ values }) => (
|
|
9
|
+
<Table.Row>
|
|
10
|
+
{values.map((value, key) => (
|
|
11
|
+
<Table.Cell key={key}>{_.truncate(truncateOpts)(value)}</Table.Cell>
|
|
12
|
+
))}
|
|
13
|
+
</Table.Row>
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
DataRow.propTypes = {
|
|
17
|
+
values: PropTypes.arrayOf(PropTypes.string),
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export const ReferenceDatasetTable = ({ headers = [], rows = [] }) => (
|
|
21
|
+
<Table compact basic="very">
|
|
22
|
+
<Table.Header>
|
|
23
|
+
<Table.Row>
|
|
24
|
+
{headers.map((text, key) => (
|
|
25
|
+
<Table.HeaderCell key={key} content={text} />
|
|
26
|
+
))}
|
|
27
|
+
</Table.Row>
|
|
28
|
+
</Table.Header>
|
|
29
|
+
<Table.Body>
|
|
30
|
+
{rows.map((values, key) => (
|
|
31
|
+
<DataRow key={key} values={values} />
|
|
32
|
+
))}
|
|
33
|
+
</Table.Body>
|
|
34
|
+
</Table>
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
ReferenceDatasetTable.propTypes = {
|
|
38
|
+
headers: PropTypes.arrayOf(PropTypes.string).isRequired,
|
|
39
|
+
rows: PropTypes.arrayOf(PropTypes.arrayOf(PropTypes.string)).isRequired,
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export default ReferenceDatasetTable;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import _ from "lodash/fp";
|
|
2
|
+
import React, { useState } from "react";
|
|
3
|
+
import { matchSorter } from "match-sorter";
|
|
4
|
+
import { useIntl, FormattedMessage } from "react-intl";
|
|
5
|
+
import { Link } from "react-router-dom";
|
|
6
|
+
import { Button, Header, Icon, Input, Segment } from "semantic-ui-react";
|
|
7
|
+
import { useQuery } from "@apollo/client";
|
|
8
|
+
import { Loading } from "@truedat/core/components";
|
|
9
|
+
import { REFERENCE_DATASET_NEW } from "@truedat/core/routes";
|
|
10
|
+
import { lowerDeburrTrim } from "@truedat/core/services/sort";
|
|
11
|
+
import { REFERENCE_DATASETS_QUERY } from "../api/queries";
|
|
12
|
+
import ReferenceDatasetsTable from "./ReferenceDatasetsTable";
|
|
13
|
+
|
|
14
|
+
const sortByName = _.sortBy([({ name }) => lowerDeburrTrim(name), "name"]);
|
|
15
|
+
|
|
16
|
+
export const ReferenceDatasets = () => {
|
|
17
|
+
const [searchTerm, setSearchTerm] = useState("");
|
|
18
|
+
const { formatMessage } = useIntl();
|
|
19
|
+
const { loading, error, data } = useQuery(REFERENCE_DATASETS_QUERY);
|
|
20
|
+
if (error) return null;
|
|
21
|
+
if (loading) return <Loading />;
|
|
22
|
+
const items = data?.referenceDatasets;
|
|
23
|
+
const datasets =
|
|
24
|
+
searchTerm === ""
|
|
25
|
+
? sortByName(items)
|
|
26
|
+
: matchSorter(items, searchTerm, {
|
|
27
|
+
keys: ["name", "headers", "rowCount", "updatedAt"],
|
|
28
|
+
threshold: matchSorter.rankings.CONTAINS,
|
|
29
|
+
});
|
|
30
|
+
return (
|
|
31
|
+
<Segment>
|
|
32
|
+
<Header as="h2">
|
|
33
|
+
<Button
|
|
34
|
+
floated="right"
|
|
35
|
+
primary
|
|
36
|
+
as={Link}
|
|
37
|
+
to={REFERENCE_DATASET_NEW}
|
|
38
|
+
content={formatMessage({ id: "referenceDatasets.actions.create" })}
|
|
39
|
+
/>
|
|
40
|
+
<Icon name="list ol" circular />
|
|
41
|
+
<Header.Content>
|
|
42
|
+
<FormattedMessage id="referenceDatasets.header" />
|
|
43
|
+
<Header.Subheader>
|
|
44
|
+
<FormattedMessage id="referenceDatasets.subheader" />
|
|
45
|
+
</Header.Subheader>
|
|
46
|
+
</Header.Content>
|
|
47
|
+
</Header>
|
|
48
|
+
<Input
|
|
49
|
+
onChange={(_e, { value }) => setSearchTerm(value)}
|
|
50
|
+
value={searchTerm}
|
|
51
|
+
icon={{ name: "search", link: true }}
|
|
52
|
+
placeholder={formatMessage({
|
|
53
|
+
id: "referenceDatasets.search.placeholder",
|
|
54
|
+
})}
|
|
55
|
+
/>
|
|
56
|
+
<ReferenceDatasetsTable datasets={datasets} />
|
|
57
|
+
</Segment>
|
|
58
|
+
);
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
export default ReferenceDatasets;
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import _ from "lodash/fp";
|
|
2
|
+
import React, { useState } from "react";
|
|
3
|
+
import PropTypes from "prop-types";
|
|
4
|
+
import { Icon, Table } from "semantic-ui-react";
|
|
5
|
+
import { Link } from "react-router-dom";
|
|
6
|
+
import { useIntl } from "react-intl";
|
|
7
|
+
import Moment from "react-moment";
|
|
8
|
+
import { DateTime } from "@truedat/core/components";
|
|
9
|
+
import { linkTo } from "@truedat/core/routes";
|
|
10
|
+
|
|
11
|
+
export const HeaderRow = ({ onDateClick, relative }) => {
|
|
12
|
+
const { formatMessage } = useIntl();
|
|
13
|
+
return (
|
|
14
|
+
<Table.Row>
|
|
15
|
+
<Table.HeaderCell
|
|
16
|
+
content={formatMessage({ id: "referenceDataset.name" })}
|
|
17
|
+
/>
|
|
18
|
+
<Table.HeaderCell
|
|
19
|
+
content={formatMessage({ id: "referenceDataset.headers" })}
|
|
20
|
+
/>
|
|
21
|
+
<Table.HeaderCell
|
|
22
|
+
content={formatMessage({ id: "referenceDataset.rowCount" })}
|
|
23
|
+
textAlign="right"
|
|
24
|
+
/>
|
|
25
|
+
<Table.HeaderCell textAlign="right">
|
|
26
|
+
{formatMessage({ id: "referenceDataset.updatedAt" })}{" "}
|
|
27
|
+
<a onClick={onDateClick}>
|
|
28
|
+
<Icon name={relative ? "calendar outline" : "clock outline"} />
|
|
29
|
+
</a>
|
|
30
|
+
</Table.HeaderCell>
|
|
31
|
+
</Table.Row>
|
|
32
|
+
);
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
HeaderRow.propTypes = {
|
|
36
|
+
relative: PropTypes.bool,
|
|
37
|
+
onDateClick: PropTypes.func,
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export const DatasetRow = ({
|
|
41
|
+
name,
|
|
42
|
+
id,
|
|
43
|
+
relative,
|
|
44
|
+
rowCount,
|
|
45
|
+
headers,
|
|
46
|
+
updatedAt,
|
|
47
|
+
}) => {
|
|
48
|
+
const { locale } = useIntl();
|
|
49
|
+
return (
|
|
50
|
+
<Table.Row>
|
|
51
|
+
<Table.Cell>
|
|
52
|
+
<Link to={linkTo.REFERENCE_DATASET({ id })}>{name}</Link>
|
|
53
|
+
</Table.Cell>
|
|
54
|
+
<Table.Cell content={_.truncate({ length: 90 })(_.join(", ")(headers))} />
|
|
55
|
+
<Table.Cell textAlign="right" width={1} content={rowCount} />
|
|
56
|
+
<Table.Cell textAlign="right" width={3}>
|
|
57
|
+
{relative ? (
|
|
58
|
+
<Moment locale={locale} fromNow date={updatedAt} />
|
|
59
|
+
) : (
|
|
60
|
+
<DateTime value={updatedAt} locale={locale} />
|
|
61
|
+
)}
|
|
62
|
+
</Table.Cell>
|
|
63
|
+
</Table.Row>
|
|
64
|
+
);
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
DatasetRow.propTypes = {
|
|
68
|
+
headers: PropTypes.arrayOf(PropTypes.string),
|
|
69
|
+
id: PropTypes.string,
|
|
70
|
+
name: PropTypes.string,
|
|
71
|
+
relative: PropTypes.bool,
|
|
72
|
+
rowCount: PropTypes.number,
|
|
73
|
+
updatedAt: PropTypes.string,
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
export const ReferenceDatasetsTable = ({ datasets }) => {
|
|
77
|
+
const { formatMessage } = useIntl();
|
|
78
|
+
const [relative, setRelative] = useState(true);
|
|
79
|
+
|
|
80
|
+
return (
|
|
81
|
+
<Table>
|
|
82
|
+
<caption className="text-right">
|
|
83
|
+
{formatMessage(
|
|
84
|
+
{ id: "referenceDatasets.count" },
|
|
85
|
+
{ count: _.size(datasets) }
|
|
86
|
+
)}
|
|
87
|
+
</caption>
|
|
88
|
+
<Table.Header>
|
|
89
|
+
<HeaderRow
|
|
90
|
+
relative={relative}
|
|
91
|
+
onDateClick={() => setRelative((value) => !value)}
|
|
92
|
+
/>
|
|
93
|
+
</Table.Header>
|
|
94
|
+
<Table.Body>
|
|
95
|
+
{datasets.map((props, key) => (
|
|
96
|
+
<DatasetRow key={key} relative={relative} {...props} />
|
|
97
|
+
))}
|
|
98
|
+
</Table.Body>
|
|
99
|
+
</Table>
|
|
100
|
+
);
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
ReferenceDatasetsTable.propTypes = { datasets: PropTypes.array };
|
|
104
|
+
|
|
105
|
+
export default ReferenceDatasetsTable;
|
|
@@ -34,7 +34,7 @@ export class StructureConfidentialButton extends React.Component {
|
|
|
34
34
|
userPermissions,
|
|
35
35
|
} = this.props;
|
|
36
36
|
|
|
37
|
-
if (!userPermissions
|
|
37
|
+
if (!userPermissions?.confidential || !userPermissions?.update) return null;
|
|
38
38
|
|
|
39
39
|
const buttonText = structure.confidential
|
|
40
40
|
? formatMessage({ id: "structure.mark_as_public" })
|
|
@@ -1,13 +1,9 @@
|
|
|
1
|
-
import React from "react";
|
|
2
1
|
import { bindActionCreators } from "redux";
|
|
3
2
|
import { connect } from "react-redux";
|
|
3
|
+
import { AvailableFilters } from "@truedat/core/components";
|
|
4
4
|
import { addStructureFilter, resetStructureFilters } from "../routines";
|
|
5
5
|
import { getStructureAvailableFilters } from "../selectors";
|
|
6
6
|
|
|
7
|
-
const AvailableFilters = React.lazy(() =>
|
|
8
|
-
import("@truedat/core/components/AvailableFilters")
|
|
9
|
-
);
|
|
10
|
-
|
|
11
7
|
const mapStateToProps = (state) => ({
|
|
12
8
|
filters: getStructureAvailableFilters(state),
|
|
13
9
|
disabled: state.structureFiltersLoading,
|
|
@@ -5,7 +5,7 @@ import { connect } from "react-redux";
|
|
|
5
5
|
import { Button, Form, Segment } from "semantic-ui-react";
|
|
6
6
|
import { useIntl } from "react-intl";
|
|
7
7
|
import { HistoryBackButton } from "@truedat/core/components";
|
|
8
|
-
import { selectTemplate,
|
|
8
|
+
import { selectTemplate, selectDomains } from "@truedat/df/routines";
|
|
9
9
|
import { applyTemplate, validateContent } from "@truedat/df/utils";
|
|
10
10
|
import { doStructureNoteAction } from "../routines";
|
|
11
11
|
import { getLatestDfContent } from "../selectors/getSortedStructureNotes";
|
|
@@ -24,16 +24,16 @@ export const StructureNotesEdit = ({
|
|
|
24
24
|
template,
|
|
25
25
|
doStructureNoteAction,
|
|
26
26
|
selectTemplate,
|
|
27
|
-
|
|
27
|
+
selectDomains,
|
|
28
28
|
structureNotes,
|
|
29
29
|
latestDfContent,
|
|
30
30
|
}) => {
|
|
31
31
|
const [content, setContent] = useState(latestDfContent);
|
|
32
32
|
|
|
33
33
|
useEffect(() => {
|
|
34
|
-
|
|
34
|
+
selectDomains(structure.domain_ids);
|
|
35
35
|
if (template) selectTemplate(template);
|
|
36
|
-
}, [template, structure, selectTemplate,
|
|
36
|
+
}, [template, structure, selectTemplate, selectDomains]);
|
|
37
37
|
|
|
38
38
|
useEffect(() => {
|
|
39
39
|
if (template && latestDfContent) {
|
|
@@ -90,7 +90,7 @@ StructureNotesEdit.propTypes = {
|
|
|
90
90
|
template: PropTypes.object,
|
|
91
91
|
doStructureNoteAction: PropTypes.func,
|
|
92
92
|
selectTemplate: PropTypes.func,
|
|
93
|
-
|
|
93
|
+
selectDomains: PropTypes.func,
|
|
94
94
|
structureNotes: PropTypes.object,
|
|
95
95
|
latestDfContent: PropTypes.object,
|
|
96
96
|
};
|
|
@@ -118,6 +118,6 @@ const mapStateToProps = (state) => {
|
|
|
118
118
|
|
|
119
119
|
export default connect(mapStateToProps, {
|
|
120
120
|
selectTemplate,
|
|
121
|
-
|
|
121
|
+
selectDomains,
|
|
122
122
|
doStructureNoteAction,
|
|
123
123
|
})(StructureNotesEdit);
|
|
@@ -21,7 +21,10 @@ export const StructureProperties = ({ properties, structure }) => {
|
|
|
21
21
|
<Item>
|
|
22
22
|
<Item.Content>
|
|
23
23
|
<Item.Header as="h5">
|
|
24
|
-
<FormattedMessage
|
|
24
|
+
<FormattedMessage
|
|
25
|
+
id={`structure.${property.name}`}
|
|
26
|
+
defaultMessage={property.name}
|
|
27
|
+
/>
|
|
25
28
|
</Item.Header>
|
|
26
29
|
<Item.Description>
|
|
27
30
|
{columnDecorator(property)(structure)}
|
|
@@ -6,7 +6,7 @@ import { List } from "semantic-ui-react";
|
|
|
6
6
|
import Moment from "react-moment";
|
|
7
7
|
import { linkTo } from "@truedat/core/routes";
|
|
8
8
|
|
|
9
|
-
const dateDecorator = date => (
|
|
9
|
+
const dateDecorator = (date) => (
|
|
10
10
|
<Moment locale="es" date={date} format="YYYY-MM-DD HH:mm" />
|
|
11
11
|
);
|
|
12
12
|
|
|
@@ -30,7 +30,7 @@ export const StructureVersionListItem = ({ id, version, inserted_at }) => (
|
|
|
30
30
|
StructureVersionListItem.propTypes = {
|
|
31
31
|
id: PropTypes.number,
|
|
32
32
|
version: PropTypes.number,
|
|
33
|
-
inserted_at: PropTypes.string
|
|
33
|
+
inserted_at: PropTypes.string,
|
|
34
34
|
};
|
|
35
35
|
|
|
36
36
|
export default StructureVersionListItem;
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import _ from "lodash/fp";
|
|
2
|
-
import { linkTo } from "@truedat/core/routes";
|
|
3
|
-
import { Link } from "react-router-dom";
|
|
4
2
|
import React from "react";
|
|
5
3
|
import PropTypes from "prop-types";
|
|
6
4
|
import { connect } from "react-redux";
|
|
7
|
-
import { Grid, Segment
|
|
5
|
+
import { Grid, Segment } from "semantic-ui-react";
|
|
8
6
|
import FilteredNav from "./FilteredNav";
|
|
9
7
|
import StructureCrumbs from "./StructureCrumbs";
|
|
10
8
|
import StructureGrantCart from "./StructureGrantCart";
|
|
@@ -1,63 +1,21 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import {
|
|
2
|
+
import { render } from "@truedat/test/render";
|
|
3
3
|
import { ImplementationStructuresLoader } from "../ImplementationStructuresLoader";
|
|
4
4
|
|
|
5
|
-
jest.mock("@fluentui/react-component-event-listener", () => ({
|
|
6
|
-
documentRef: null,
|
|
7
|
-
windowRef: null,
|
|
8
|
-
}));
|
|
9
|
-
|
|
10
|
-
jest.mock("react-redux", () => ({
|
|
11
|
-
...jest.requireActual("react-redux"),
|
|
12
|
-
useSelector: jest.fn(() => [1]),
|
|
13
|
-
}));
|
|
14
|
-
|
|
15
|
-
const getProps = () => ({
|
|
16
|
-
fetchStructure: jest.fn(),
|
|
17
|
-
structureIds: [1, 2],
|
|
18
|
-
clearStructure: jest.fn(),
|
|
19
|
-
});
|
|
20
|
-
|
|
21
5
|
describe("<ImplementationStructuresLoader/>", () => {
|
|
22
|
-
it("
|
|
23
|
-
const props =
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
const wrapper = mount(<ImplementationStructuresLoader {...props} />);
|
|
31
|
-
expect(props.fetchStructure).toHaveBeenCalledTimes(1);
|
|
32
|
-
expect(props.fetchStructure).toHaveBeenCalledWith({ id: 2 });
|
|
33
|
-
|
|
34
|
-
wrapper.unmount();
|
|
35
|
-
expect(props.fetchStructure).toHaveBeenCalledTimes(1);
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
it("call fetchStructure when next id of structures when field id is already in structures fields", () => {
|
|
39
|
-
const props = { ...getProps(), structureIds: [1, 2] };
|
|
40
|
-
const wrapper = mount(<ImplementationStructuresLoader {...props} />);
|
|
41
|
-
expect(props.fetchStructure).toHaveBeenCalledTimes(1);
|
|
42
|
-
expect(props.fetchStructure).toHaveBeenCalledWith({ id: 2 });
|
|
43
|
-
|
|
44
|
-
wrapper.unmount();
|
|
6
|
+
it("calls fetchStructure on mount and clearStructure on unmount", () => {
|
|
7
|
+
const props = {
|
|
8
|
+
clearStructure: jest.fn(),
|
|
9
|
+
fetchStructure: jest.fn(),
|
|
10
|
+
structureIds: [42],
|
|
11
|
+
};
|
|
12
|
+
const { unmount } = render(<ImplementationStructuresLoader {...props} />);
|
|
13
|
+
expect(props.clearStructure).toHaveBeenCalledTimes(0);
|
|
45
14
|
expect(props.fetchStructure).toHaveBeenCalledTimes(1);
|
|
46
|
-
|
|
15
|
+
expect(props.fetchStructure).toHaveBeenCalledWith({ id: 42 });
|
|
47
16
|
|
|
48
|
-
|
|
49
|
-
const props = getProps();
|
|
50
|
-
const wrapper = mount(<ImplementationStructuresLoader {...props} />);
|
|
51
|
-
expect(props.clearStructure).toHaveBeenCalledTimes(0);
|
|
52
|
-
wrapper.unmount();
|
|
17
|
+
unmount();
|
|
53
18
|
expect(props.clearStructure).toHaveBeenCalledTimes(1);
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
it("calls fetchStructures when structureIds is updated", () => {
|
|
57
|
-
const props = getProps();
|
|
58
|
-
const wrapper = mount(<ImplementationStructuresLoader {...props} />);
|
|
59
|
-
wrapper.setProps({ structureIds: [6, 5] });
|
|
60
|
-
expect(props.fetchStructure).toHaveBeenCalledTimes(2);
|
|
61
|
-
expect(props.fetchStructure).toHaveBeenCalledWith({ id: 5 });
|
|
19
|
+
expect(props.fetchStructure).toHaveBeenCalledTimes(1);
|
|
62
20
|
});
|
|
63
21
|
});
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { render } from "@truedat/test/render";
|
|
3
3
|
import { LineageEventsTable } from "../LineageEventsTable";
|
|
4
|
-
import en from "../../messages/en";
|
|
5
4
|
|
|
6
5
|
describe("<LineageEventsTable />", () => {
|
|
7
6
|
const lineageEvents = [
|
|
@@ -19,9 +18,7 @@ describe("<LineageEventsTable />", () => {
|
|
|
19
18
|
|
|
20
19
|
it("matches the latest snapshot", () => {
|
|
21
20
|
const props = { fetchLineageEvents, lineageEvents, lineageEventsLoading };
|
|
22
|
-
const { container } = render(<LineageEventsTable {...props}
|
|
23
|
-
messages: { en },
|
|
24
|
-
});
|
|
21
|
+
const { container } = render(<LineageEventsTable {...props} />);
|
|
25
22
|
expect(container).toMatchSnapshot();
|
|
26
23
|
});
|
|
27
24
|
|
|
@@ -31,9 +28,7 @@ describe("<LineageEventsTable />", () => {
|
|
|
31
28
|
lineageEvents: [],
|
|
32
29
|
lineageEventsLoading,
|
|
33
30
|
};
|
|
34
|
-
const { container } = render(<LineageEventsTable {...props}
|
|
35
|
-
messages: { en },
|
|
36
|
-
});
|
|
31
|
+
const { container } = render(<LineageEventsTable {...props} />);
|
|
37
32
|
expect(container).toMatchSnapshot();
|
|
38
33
|
});
|
|
39
34
|
});
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import {
|
|
2
|
+
import { render } from "@truedat/test/render";
|
|
3
3
|
import { LineageRoutes } from "../LineageRoutes";
|
|
4
4
|
|
|
5
5
|
jest.mock("@truedat/core/hooks", () => ({
|
|
6
|
-
useAuthorized: jest.fn(() => true)
|
|
6
|
+
useAuthorized: jest.fn(() => true),
|
|
7
7
|
}));
|
|
8
8
|
|
|
9
9
|
describe("<LineageRoutes />", () => {
|
|
10
10
|
it("matches the latest snapshot", () => {
|
|
11
|
-
const
|
|
12
|
-
expect(
|
|
11
|
+
const { container } = render(<LineageRoutes />);
|
|
12
|
+
expect(container).toMatchSnapshot();
|
|
13
13
|
});
|
|
14
14
|
});
|