@truedat/dd 4.45.5 → 4.45.8
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 +6 -0
- package/package.json +6 -6
- package/src/api.js +2 -0
- package/src/components/GrantRemoval.js +44 -0
- package/src/components/Grants.js +1 -4
- package/src/components/LineageGroup.js +5 -5
- package/src/components/LineageResource.js +4 -4
- package/src/components/StructureDeleteButton.js +1 -1
- package/src/components/StructureGrantButton.js +63 -0
- package/src/components/StructureGrantCart.js +2 -2
- package/src/components/StructureGrants.js +38 -10
- package/src/components/StructureSummary.js +2 -24
- package/src/components/__tests__/GrantRemoval.spec.js +47 -0
- package/src/components/__tests__/StructureGrantButton.spec.js +52 -0
- package/src/components/__tests__/StructureSummary.spec.js +31 -104
- package/src/components/__tests__/__snapshots__/GrantRemoval.spec.js.snap +9 -0
- package/src/components/__tests__/__snapshots__/StructureGrantButton.spec.js.snap +37 -0
- package/src/components/__tests__/__snapshots__/StructureSummary.spec.js.snap +34 -160
- package/src/messages/en.js +12 -1
- package/src/messages/es.js +14 -1
- package/src/routines.js +2 -1
- package/src/sagas/index.js +3 -0
- package/src/sagas/requestGrantRemoval.js +31 -0
- package/src/selectors/getGrantsColumns.js +18 -10
package/CHANGELOG.md
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@truedat/dd",
|
|
3
|
-
"version": "4.45.
|
|
3
|
+
"version": "4.45.8",
|
|
4
4
|
"description": "Truedat Web Data Dictionary",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"jsnext:main": "src/index.js",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"@testing-library/jest-dom": "^5.16.4",
|
|
35
35
|
"@testing-library/react": "^12.0.0",
|
|
36
36
|
"@testing-library/user-event": "^13.2.1",
|
|
37
|
-
"@truedat/test": "4.45.
|
|
37
|
+
"@truedat/test": "4.45.8",
|
|
38
38
|
"babel-jest": "^28.1.0",
|
|
39
39
|
"babel-plugin-dynamic-import-node": "^2.3.3",
|
|
40
40
|
"babel-plugin-lodash": "^3.3.4",
|
|
@@ -88,9 +88,9 @@
|
|
|
88
88
|
},
|
|
89
89
|
"dependencies": {
|
|
90
90
|
"@apollo/client": "^3.6.4",
|
|
91
|
-
"@truedat/auth": "4.45.
|
|
92
|
-
"@truedat/core": "4.45.
|
|
93
|
-
"@truedat/df": "4.45.
|
|
91
|
+
"@truedat/auth": "4.45.8",
|
|
92
|
+
"@truedat/core": "4.45.8",
|
|
93
|
+
"@truedat/df": "4.45.8",
|
|
94
94
|
"lodash": "^4.17.21",
|
|
95
95
|
"path-to-regexp": "^1.7.0",
|
|
96
96
|
"prop-types": "^15.8.1",
|
|
@@ -111,5 +111,5 @@
|
|
|
111
111
|
"react-dom": ">= 16.8.6 < 17",
|
|
112
112
|
"semantic-ui-react": ">= 0.88.2 < 2.1"
|
|
113
113
|
},
|
|
114
|
-
"gitHead": "
|
|
114
|
+
"gitHead": "1b5acb1dc1233181e5a47353fd8a5da1424e7a47"
|
|
115
115
|
}
|
package/src/api.js
CHANGED
|
@@ -12,6 +12,7 @@ const API_GRANT_REQUEST = "/api/grant_requests/:id";
|
|
|
12
12
|
const API_GRANT_REQUEST_APPROVALS = "/api/grant_requests/:id/approvals";
|
|
13
13
|
const API_GRANT_REQUEST_GROUP = "/api/grant_request_groups";
|
|
14
14
|
const API_GRANT_REQUESTS = "/api/grant_requests";
|
|
15
|
+
const API_GRANT = "/api/grants/:id";
|
|
15
16
|
const API_GRANTS_CSV = "/api/grants/csv";
|
|
16
17
|
const API_GRANTS_SEARCH = "/api/grants/search";
|
|
17
18
|
const API_GRAPH = "/api/graphs/:id";
|
|
@@ -54,6 +55,7 @@ export {
|
|
|
54
55
|
API_DATA_STRUCTURE_FILTERS_SEARCH,
|
|
55
56
|
API_DATA_STRUCTURE_VERSION,
|
|
56
57
|
API_PROFILE_EXECUTION,
|
|
58
|
+
API_GRANT,
|
|
57
59
|
API_GRANT_FILTERS_SEARCH,
|
|
58
60
|
API_GRANT_REQUEST,
|
|
59
61
|
API_GRANT_REQUEST_APPROVALS,
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import PropTypes from "prop-types";
|
|
3
|
+
import { connect } from "react-redux";
|
|
4
|
+
import { useIntl } from "react-intl";
|
|
5
|
+
import { ConfirmModal } from "@truedat/core/components";
|
|
6
|
+
import { requestGrantRemoval } from "../routines";
|
|
7
|
+
|
|
8
|
+
export const GrantRemoval = ({ grant, requestGrantRemoval, children }) => {
|
|
9
|
+
const { formatMessage } = useIntl();
|
|
10
|
+
|
|
11
|
+
if (!grant) return;
|
|
12
|
+
|
|
13
|
+
const action = grant.pending_removal ? "cancel_removal" : "request_removal";
|
|
14
|
+
|
|
15
|
+
return (
|
|
16
|
+
<ConfirmModal
|
|
17
|
+
trigger={children}
|
|
18
|
+
header={formatMessage({
|
|
19
|
+
id: `grant.actions.${action}.confirmation.header`,
|
|
20
|
+
})}
|
|
21
|
+
content={formatMessage({
|
|
22
|
+
id: `grant.actions.${action}.confirmation.content`,
|
|
23
|
+
})}
|
|
24
|
+
onConfirm={() =>
|
|
25
|
+
requestGrantRemoval({
|
|
26
|
+
id: grant.id,
|
|
27
|
+
action,
|
|
28
|
+
data_structure_id: grant.data_structure.id,
|
|
29
|
+
version: grant.data_structure_version.id,
|
|
30
|
+
})
|
|
31
|
+
}
|
|
32
|
+
onOpen={(e) => e.stopPropagation()}
|
|
33
|
+
onClose={(e) => e.stopPropagation()}
|
|
34
|
+
/>
|
|
35
|
+
);
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
GrantRemoval.propTypes = {
|
|
39
|
+
grant: PropTypes.object,
|
|
40
|
+
requestGrantRemoval: PropTypes.func,
|
|
41
|
+
children: PropTypes.node,
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export default connect(null, { requestGrantRemoval })(GrantRemoval);
|
package/src/components/Grants.js
CHANGED
|
@@ -29,10 +29,7 @@ export const Grants = ({ grantsLoading, onlyMyGrants }) => (
|
|
|
29
29
|
</Header.Content>
|
|
30
30
|
</Header>
|
|
31
31
|
<Segment attached="bottom">
|
|
32
|
-
<GrantsDownloadButton
|
|
33
|
-
onlyMyGrants={onlyMyGrants}
|
|
34
|
-
hasFilterApplied={true}
|
|
35
|
-
/>
|
|
32
|
+
<GrantsDownloadButton onlyMyGrants={onlyMyGrants} hasFilterApplied />
|
|
36
33
|
<GrantsSearch />
|
|
37
34
|
<GrantSelectedFilters />
|
|
38
35
|
<GrantDateFilter />
|
|
@@ -20,11 +20,11 @@ export const LineageGroup = ({
|
|
|
20
20
|
structure_id: structureId,
|
|
21
21
|
onClick,
|
|
22
22
|
selected,
|
|
23
|
-
onHover
|
|
23
|
+
onHover,
|
|
24
24
|
}) => {
|
|
25
25
|
const handleClick =
|
|
26
26
|
structureId && onClick
|
|
27
|
-
? e => {
|
|
27
|
+
? (e) => {
|
|
28
28
|
e.preventDefault();
|
|
29
29
|
e.stopPropagation();
|
|
30
30
|
onClick();
|
|
@@ -47,7 +47,7 @@ export const LineageGroup = ({
|
|
|
47
47
|
const content = selected ? (
|
|
48
48
|
<Popup
|
|
49
49
|
size="small"
|
|
50
|
-
open
|
|
50
|
+
open
|
|
51
51
|
content={
|
|
52
52
|
<LineageContextMenu
|
|
53
53
|
id={id}
|
|
@@ -67,7 +67,7 @@ export const LineageGroup = ({
|
|
|
67
67
|
)([
|
|
68
68
|
["group", `z${z}`],
|
|
69
69
|
type ? [lowerDeburr(type)] : [],
|
|
70
|
-
active ? ["active"] : []
|
|
70
|
+
active ? ["active"] : [],
|
|
71
71
|
]);
|
|
72
72
|
return (
|
|
73
73
|
<g className={classNames} onMouseOver={onHover} onContextMenu={handleClick}>
|
|
@@ -91,7 +91,7 @@ LineageGroup.propTypes = {
|
|
|
91
91
|
structure_id: PropTypes.number,
|
|
92
92
|
type: PropTypes.string,
|
|
93
93
|
onClick: PropTypes.func,
|
|
94
|
-
onHover: PropTypes.func
|
|
94
|
+
onHover: PropTypes.func,
|
|
95
95
|
};
|
|
96
96
|
|
|
97
97
|
export default LineageGroup;
|
|
@@ -17,10 +17,10 @@ export const LineageResource = ({
|
|
|
17
17
|
structure_id: structureId,
|
|
18
18
|
onClick,
|
|
19
19
|
selected,
|
|
20
|
-
onHover
|
|
20
|
+
onHover,
|
|
21
21
|
}) => {
|
|
22
22
|
const handleClick = onClick
|
|
23
|
-
? e => {
|
|
23
|
+
? (e) => {
|
|
24
24
|
e.preventDefault();
|
|
25
25
|
e.stopPropagation();
|
|
26
26
|
onClick();
|
|
@@ -37,7 +37,7 @@ export const LineageResource = ({
|
|
|
37
37
|
const content = selected ? (
|
|
38
38
|
<Popup
|
|
39
39
|
size="small"
|
|
40
|
-
open
|
|
40
|
+
open
|
|
41
41
|
content={
|
|
42
42
|
<LineageContextMenu
|
|
43
43
|
id={id}
|
|
@@ -72,7 +72,7 @@ LineageResource.propTypes = {
|
|
|
72
72
|
id: PropTypes.string,
|
|
73
73
|
name: PropTypes.string,
|
|
74
74
|
selected: PropTypes.bool,
|
|
75
|
-
onHover: PropTypes.func
|
|
75
|
+
onHover: PropTypes.func,
|
|
76
76
|
};
|
|
77
77
|
|
|
78
78
|
export default LineageResource;
|
|
@@ -25,7 +25,7 @@ export const StructureDeleteButton = ({ structure, deleteStructure }) => {
|
|
|
25
25
|
})}
|
|
26
26
|
onConfirm={() => deleteStructure({ id: structure.id })}
|
|
27
27
|
onOpen={(e) => e.stopPropagation()}
|
|
28
|
-
|
|
28
|
+
onClose={(e) => e.stopPropagation()}
|
|
29
29
|
/>
|
|
30
30
|
);
|
|
31
31
|
};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import _ from "lodash/fp";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import PropTypes from "prop-types";
|
|
4
|
+
import { Icon, Label, Popup } from "semantic-ui-react";
|
|
5
|
+
import { connect } from "react-redux";
|
|
6
|
+
import { useIntl } from "react-intl";
|
|
7
|
+
import { DateTime } from "@truedat/core/components";
|
|
8
|
+
import GrantRemoval from "./GrantRemoval";
|
|
9
|
+
import StructureGrantRequestButton from "./StructureGrantRequestButton";
|
|
10
|
+
|
|
11
|
+
const isNilOrEmpty = (value) => _.isEmpty(value) || _.isNil(value);
|
|
12
|
+
export const StructureGrantButton = ({ structure, structureGrantPopup }) => {
|
|
13
|
+
const { formatMessage } = useIntl();
|
|
14
|
+
const { grant } = structure;
|
|
15
|
+
|
|
16
|
+
const popupContent = _.flow(
|
|
17
|
+
_.reject(({ field }) => isNilOrEmpty(_.get(field)(grant))),
|
|
18
|
+
_.map(({ field, type }) => {
|
|
19
|
+
switch (type) {
|
|
20
|
+
case "datetime":
|
|
21
|
+
return <DateTime value={_.get(field)(grant)} key={field} />;
|
|
22
|
+
default:
|
|
23
|
+
return <div key={field}>{_.get(field)(grant)}</div>;
|
|
24
|
+
}
|
|
25
|
+
})
|
|
26
|
+
)(structureGrantPopup);
|
|
27
|
+
|
|
28
|
+
const label = grant ? (
|
|
29
|
+
grant.pending_removal ? (
|
|
30
|
+
<Label color="orange">
|
|
31
|
+
<Icon name="shield" />
|
|
32
|
+
{formatMessage({ id: "structure.grant.has_grant_pending_removal" })}
|
|
33
|
+
<GrantRemoval grant={grant}>
|
|
34
|
+
<Icon name="undo" />
|
|
35
|
+
</GrantRemoval>
|
|
36
|
+
</Label>
|
|
37
|
+
) : (
|
|
38
|
+
<Label color="green">
|
|
39
|
+
<Icon name="shield" />
|
|
40
|
+
{formatMessage({ id: "structure.grant.has_grant" })}
|
|
41
|
+
<GrantRemoval grant={grant}>
|
|
42
|
+
<Icon name="delete" />
|
|
43
|
+
</GrantRemoval>
|
|
44
|
+
</Label>
|
|
45
|
+
)
|
|
46
|
+
) : (
|
|
47
|
+
<StructureGrantRequestButton />
|
|
48
|
+
);
|
|
49
|
+
return _.isEmpty(popupContent) ? (
|
|
50
|
+
label
|
|
51
|
+
) : (
|
|
52
|
+
<Popup content={popupContent} trigger={label} />
|
|
53
|
+
);
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
StructureGrantButton.propTypes = {
|
|
57
|
+
structure: PropTypes.object,
|
|
58
|
+
structureGrantPopup: PropTypes.array,
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const mapStateToProps = _.pick(["structure", "structureGrantPopup"]);
|
|
62
|
+
|
|
63
|
+
export default connect(mapStateToProps)(StructureGrantButton);
|
|
@@ -87,7 +87,7 @@ export const StructureGrantCart = ({
|
|
|
87
87
|
{canHasFilters(s) && inCartCheckout ? (
|
|
88
88
|
<Button
|
|
89
89
|
compact
|
|
90
|
-
basic
|
|
90
|
+
basic
|
|
91
91
|
icon="filter"
|
|
92
92
|
color={hasFilters(s) ? "blue" : null}
|
|
93
93
|
onClick={() => setOpenedStructureFilter(s.id)}
|
|
@@ -96,7 +96,7 @@ export const StructureGrantCart = ({
|
|
|
96
96
|
<Button
|
|
97
97
|
onClick={removeRequest(s)}
|
|
98
98
|
compact
|
|
99
|
-
basic
|
|
99
|
+
basic
|
|
100
100
|
icon="trash alternate outline"
|
|
101
101
|
color="red"
|
|
102
102
|
/>
|
|
@@ -2,16 +2,43 @@ import _ from "lodash/fp";
|
|
|
2
2
|
import React from "react";
|
|
3
3
|
import PropTypes from "prop-types";
|
|
4
4
|
import { useIntl } from "react-intl";
|
|
5
|
-
import { Table } from "semantic-ui-react";
|
|
5
|
+
import { Table, Button } from "semantic-ui-react";
|
|
6
6
|
import { connect } from "react-redux";
|
|
7
7
|
import { columnDecorator } from "@truedat/core/services";
|
|
8
8
|
import { getGrantsColumns } from "../selectors";
|
|
9
|
+
import GrantRemoval from "./GrantRemoval";
|
|
9
10
|
|
|
10
|
-
export const
|
|
11
|
+
export const RemovalButtonDecorator = (grant) => (
|
|
12
|
+
<GrantRemoval grant={grant}>
|
|
13
|
+
{grant.pending_removal ? (
|
|
14
|
+
<Button size="mini" color="olive" icon="undo" />
|
|
15
|
+
) : (
|
|
16
|
+
<Button size="mini" color="red" icon="delete" />
|
|
17
|
+
)}
|
|
18
|
+
</GrantRemoval>
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
export const StructureGrants = ({ columns, grants, userPermissions }) => {
|
|
11
22
|
const { formatMessage } = useIntl();
|
|
12
23
|
const filteredColumns = _.filter((c) => _.any(_.prop(c.name))(grants))(
|
|
13
24
|
columns
|
|
14
25
|
);
|
|
26
|
+
const canUpdateRemoval = _.getOr(
|
|
27
|
+
false,
|
|
28
|
+
"update_grant_removal"
|
|
29
|
+
)(userPermissions);
|
|
30
|
+
|
|
31
|
+
const columnsWithActions = [
|
|
32
|
+
...columns,
|
|
33
|
+
...(canUpdateRemoval
|
|
34
|
+
? [
|
|
35
|
+
{
|
|
36
|
+
fieldSelector: _.identity,
|
|
37
|
+
fieldDecorator: RemovalButtonDecorator,
|
|
38
|
+
},
|
|
39
|
+
]
|
|
40
|
+
: []),
|
|
41
|
+
];
|
|
15
42
|
|
|
16
43
|
return (
|
|
17
44
|
grants && (
|
|
@@ -33,14 +60,13 @@ export const StructureGrants = ({ columns, grants }) => {
|
|
|
33
60
|
<Table.Body>
|
|
34
61
|
{grants.map((grant, i) => (
|
|
35
62
|
<Table.Row key={i}>
|
|
36
|
-
{
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
))}
|
|
63
|
+
{columnsWithActions.map((column, key) => (
|
|
64
|
+
<Table.Cell
|
|
65
|
+
key={key}
|
|
66
|
+
textAlign={column.textAlign}
|
|
67
|
+
content={columnDecorator(column)(grant)}
|
|
68
|
+
/>
|
|
69
|
+
))}
|
|
44
70
|
</Table.Row>
|
|
45
71
|
))}
|
|
46
72
|
</Table.Body>
|
|
@@ -52,11 +78,13 @@ export const StructureGrants = ({ columns, grants }) => {
|
|
|
52
78
|
StructureGrants.propTypes = {
|
|
53
79
|
columns: PropTypes.array,
|
|
54
80
|
grants: PropTypes.array,
|
|
81
|
+
userPermissions: PropTypes.object,
|
|
55
82
|
};
|
|
56
83
|
|
|
57
84
|
const mapStateToProps = (state) => ({
|
|
58
85
|
grants: state.structure.grants,
|
|
59
86
|
columns: getGrantsColumns(state),
|
|
87
|
+
userPermissions: state.userPermissions,
|
|
60
88
|
});
|
|
61
89
|
|
|
62
90
|
export default connect(mapStateToProps)(StructureGrants);
|
|
@@ -10,7 +10,7 @@ import { getStructureUpdatedAt } from "../selectors";
|
|
|
10
10
|
import StructureProperties from "./StructureProperties";
|
|
11
11
|
import StructureConfidentialButton from "./StructureConfidentialButton";
|
|
12
12
|
import StructureDeleteButton from "./StructureDeleteButton";
|
|
13
|
-
import
|
|
13
|
+
import StructureGrantButton from "./StructureGrantButton";
|
|
14
14
|
import StructureProfileButton from "./StructureProfileButton";
|
|
15
15
|
import StructuresProfileButton from "./StructuresProfileButton";
|
|
16
16
|
import TagsHeader from "./TagsHeader";
|
|
@@ -58,14 +58,10 @@ export const StructureSummary = ({
|
|
|
58
58
|
name,
|
|
59
59
|
published_note,
|
|
60
60
|
description,
|
|
61
|
-
type,
|
|
62
61
|
userPermissions,
|
|
63
62
|
updatedAt,
|
|
64
63
|
deleted_at,
|
|
65
|
-
data_structure_type,
|
|
66
|
-
grant,
|
|
67
64
|
linkedStructureTagsLoading,
|
|
68
|
-
structureGrant,
|
|
69
65
|
isAdmin,
|
|
70
66
|
}) => {
|
|
71
67
|
const { formatMessage } = useIntl();
|
|
@@ -83,18 +79,7 @@ export const StructureSummary = ({
|
|
|
83
79
|
{_.isEmpty(published_note?.alias)
|
|
84
80
|
? name
|
|
85
81
|
: published_note.alias}
|
|
86
|
-
|
|
87
|
-
structureGrant ? (
|
|
88
|
-
structureGrant(grant)
|
|
89
|
-
) : (
|
|
90
|
-
<Label color="green">
|
|
91
|
-
<Icon name="shield" />
|
|
92
|
-
{formatMessage({ id: "structure.grant.has_grant" })}
|
|
93
|
-
</Label>
|
|
94
|
-
)
|
|
95
|
-
) : (
|
|
96
|
-
<StructureGrantRequestButton />
|
|
97
|
-
)}
|
|
82
|
+
<StructureGrantButton />
|
|
98
83
|
{!_.isEmpty(published_note?.alias) && (
|
|
99
84
|
<Header.Subheader>{name}</Header.Subheader>
|
|
100
85
|
)}
|
|
@@ -135,15 +120,10 @@ StructureSummary.propTypes = {
|
|
|
135
120
|
name: PropTypes.string,
|
|
136
121
|
published_note: PropTypes.object,
|
|
137
122
|
description: PropTypes.string,
|
|
138
|
-
type: PropTypes.string,
|
|
139
123
|
userPermissions: PropTypes.object,
|
|
140
124
|
updatedAt: PropTypes.string,
|
|
141
125
|
deleted_at: PropTypes.string,
|
|
142
|
-
grant: PropTypes.object,
|
|
143
|
-
data_structure_type: PropTypes.object,
|
|
144
126
|
linkedStructureTagsLoading: PropTypes.bool,
|
|
145
|
-
structureGrant: PropTypes.func,
|
|
146
|
-
structureTags: PropTypes.array,
|
|
147
127
|
isAdmin: PropTypes.bool,
|
|
148
128
|
};
|
|
149
129
|
|
|
@@ -151,8 +131,6 @@ const mapStateToProps = (state) => ({
|
|
|
151
131
|
userPermissions: state.userPermissions,
|
|
152
132
|
linkedStructureTagsLoading: state.linkedStructureTagsLoading,
|
|
153
133
|
updatedAt: getStructureUpdatedAt(state),
|
|
154
|
-
structureTags: state.editableStructureTags,
|
|
155
|
-
structureGrant: state.structureGrant,
|
|
156
134
|
...state.structure,
|
|
157
135
|
isAdmin: state.authentication.role === "admin",
|
|
158
136
|
});
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { fireEvent } from "@testing-library/react";
|
|
3
|
+
import { render } from "@truedat/test/render";
|
|
4
|
+
import { requestGrantRemoval } from "../../routines";
|
|
5
|
+
import GrantRemoval from "../GrantRemoval";
|
|
6
|
+
|
|
7
|
+
describe("<GrantRemoval />", () => {
|
|
8
|
+
const grant = {
|
|
9
|
+
id: 1,
|
|
10
|
+
detail: { foo: "bar" },
|
|
11
|
+
data_structure: { id: 2 },
|
|
12
|
+
data_structure_version: { id: 3 },
|
|
13
|
+
};
|
|
14
|
+
it("matches the latest snapshot", () => {
|
|
15
|
+
const { container } = render(
|
|
16
|
+
<GrantRemoval grant={grant}>
|
|
17
|
+
<p>child</p>
|
|
18
|
+
</GrantRemoval>
|
|
19
|
+
);
|
|
20
|
+
expect(container).toMatchSnapshot();
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it("on click calls requestGrantRemoval routine", async () => {
|
|
24
|
+
const dispatch = jest.fn();
|
|
25
|
+
const { findByText } = render(
|
|
26
|
+
<GrantRemoval grant={grant}>
|
|
27
|
+
<p>child</p>
|
|
28
|
+
</GrantRemoval>,
|
|
29
|
+
{ dispatch }
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
fireEvent.click(await findByText("child"));
|
|
33
|
+
expect(await findByText("Request grant removal")).toBeInTheDocument();
|
|
34
|
+
|
|
35
|
+
fireEvent.click(await findByText("Yes"));
|
|
36
|
+
|
|
37
|
+
expect(dispatch).toHaveBeenLastCalledWith({
|
|
38
|
+
...requestGrantRemoval(),
|
|
39
|
+
payload: {
|
|
40
|
+
action: "request_removal",
|
|
41
|
+
data_structure_id: 2,
|
|
42
|
+
id: 1,
|
|
43
|
+
version: 3,
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
});
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import _ from "lodash/fp";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import { fireEvent } from "@testing-library/react";
|
|
4
|
+
import { render } from "@truedat/test/render";
|
|
5
|
+
import StructureGrantButton from "../StructureGrantButton";
|
|
6
|
+
|
|
7
|
+
describe("<StructureGrantButton />", () => {
|
|
8
|
+
const state = {
|
|
9
|
+
structure: {
|
|
10
|
+
grant: {
|
|
11
|
+
detail: { foo: "bar" },
|
|
12
|
+
pending_removal: false,
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
structureGrantPopup: [],
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
it("matches the latest snapshot", async () => {
|
|
19
|
+
const { findByText, container } = render(<StructureGrantButton />, {
|
|
20
|
+
state,
|
|
21
|
+
});
|
|
22
|
+
expect(container).toMatchSnapshot();
|
|
23
|
+
expect(
|
|
24
|
+
await findByText("You have granted access on this structure")
|
|
25
|
+
).toBeTruthy();
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it("matches the latest snapshot pending_removal", async () => {
|
|
29
|
+
const customState = _.set("structure.grant.pending_removal", true)(state);
|
|
30
|
+
const { findByText, container } = render(<StructureGrantButton />, {
|
|
31
|
+
state: customState,
|
|
32
|
+
});
|
|
33
|
+
expect(container).toMatchSnapshot();
|
|
34
|
+
expect(
|
|
35
|
+
await findByText("You have granted access pending removal")
|
|
36
|
+
).toBeTruthy();
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it("matches the latest snapshot with popup", async () => {
|
|
40
|
+
const customState = _.set("structureGrantPopup", [{ field: "detail.foo" }])(
|
|
41
|
+
state
|
|
42
|
+
);
|
|
43
|
+
const { findByText } = render(<StructureGrantButton />, {
|
|
44
|
+
state: customState,
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
fireEvent.mouseOver(
|
|
48
|
+
await findByText("You have granted access on this structure")
|
|
49
|
+
);
|
|
50
|
+
expect(await findByText("bar")).toBeInTheDocument();
|
|
51
|
+
});
|
|
52
|
+
});
|
|
@@ -1,24 +1,14 @@
|
|
|
1
|
+
import _ from "lodash/fp";
|
|
1
2
|
import React from "react";
|
|
2
|
-
import { shallow } from "enzyme";
|
|
3
|
-
import { intl } from "@truedat/test/intl-stub";
|
|
4
3
|
import { render } from "@truedat/test/render";
|
|
5
|
-
import
|
|
6
|
-
import { Provider } from "react-redux";
|
|
7
|
-
import { StructureSummary } from "../StructureSummary";
|
|
8
|
-
import { defaultStructureProperties } from "../../selectors/getStructureProperties";
|
|
9
|
-
|
|
10
|
-
// workaround for enzyme issue with React.useContext
|
|
11
|
-
// see https://github.com/airbnb/enzyme/issues/2176#issuecomment-532361526
|
|
12
|
-
jest.spyOn(React, "useContext").mockImplementation(() => intl);
|
|
4
|
+
import StructureSummary from "../StructureSummary";
|
|
13
5
|
|
|
14
6
|
describe("<StructureSummary />", () => {
|
|
15
|
-
const system = { name: "system" };
|
|
16
7
|
const structure = {
|
|
17
8
|
id: 1,
|
|
18
9
|
name: "s1",
|
|
19
10
|
description: "dd",
|
|
20
11
|
group: "gp",
|
|
21
|
-
system: "sys",
|
|
22
12
|
userPermissions: {
|
|
23
13
|
update: true,
|
|
24
14
|
confidential: true,
|
|
@@ -26,110 +16,47 @@ describe("<StructureSummary />", () => {
|
|
|
26
16
|
},
|
|
27
17
|
class: "table",
|
|
28
18
|
type: "foo",
|
|
29
|
-
system,
|
|
19
|
+
system: { name: "system" },
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const state = {
|
|
23
|
+
userPermissions: {
|
|
24
|
+
profile_permission: true,
|
|
25
|
+
confidential: true,
|
|
26
|
+
},
|
|
27
|
+
linkedStructureTagsLoading: false,
|
|
28
|
+
structureVersions: [{ updated_at: "2019-01-02T03:04:05Z" }],
|
|
29
|
+
structure,
|
|
30
|
+
authentication: { role: "admin" },
|
|
30
31
|
};
|
|
31
|
-
const updatedAt = "2019-01-02T03:04:05Z";
|
|
32
|
-
const deleted_at = "2019-01-02T03:04:05Z";
|
|
33
|
-
const structureFields = [{ external_id: "external_id " }];
|
|
34
32
|
|
|
35
33
|
it("matches the latest snapshot", () => {
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
updatedAt,
|
|
39
|
-
deleted_at,
|
|
40
|
-
structureFields,
|
|
41
|
-
linkedStructureTagsLoading: false,
|
|
42
|
-
};
|
|
43
|
-
const wrapper = shallow(<StructureSummary {...props} />);
|
|
44
|
-
expect(wrapper).toMatchSnapshot();
|
|
34
|
+
const { container } = render(<StructureSummary />, { state });
|
|
35
|
+
expect(container).toMatchSnapshot();
|
|
45
36
|
});
|
|
46
37
|
|
|
47
38
|
it("matches the latest snapshot with alias", () => {
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
linkedStructureTagsLoading: false,
|
|
55
|
-
};
|
|
56
|
-
const wrapper = shallow(<StructureSummary {...props} />);
|
|
57
|
-
expect(wrapper).toMatchSnapshot();
|
|
39
|
+
const customState = _.set("structure.published_note", {
|
|
40
|
+
alias: "some alias",
|
|
41
|
+
})(state);
|
|
42
|
+
|
|
43
|
+
const { container } = render(<StructureSummary />, { state: customState });
|
|
44
|
+
expect(container).toMatchSnapshot();
|
|
58
45
|
});
|
|
59
46
|
|
|
60
47
|
it("renders loading when linkedStructureTagsLoading is true", () => {
|
|
61
|
-
const
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
deleted_at,
|
|
65
|
-
structureFields,
|
|
66
|
-
linkedStructureTagsLoading: true,
|
|
67
|
-
};
|
|
68
|
-
const wrapper = shallow(<StructureSummary {...props} />);
|
|
69
|
-
expect(wrapper.find("Loading")).toBeTruthy();
|
|
48
|
+
const customState = _.set("linkedStructureTagsLoading", true)(state);
|
|
49
|
+
const { findByText } = render(<StructureSummary />, { state: customState });
|
|
50
|
+
expect(findByText("Loading")).toBeTruthy();
|
|
70
51
|
});
|
|
71
52
|
|
|
72
|
-
const messages = {
|
|
73
|
-
en: {
|
|
74
|
-
"structure.grant.has_grant": "Grant",
|
|
75
|
-
"structure.share.title": "Share",
|
|
76
|
-
"structure.type.foo.text": "Foo",
|
|
77
|
-
"structure.domain": "Domain",
|
|
78
|
-
"structure.group": "Group",
|
|
79
|
-
},
|
|
80
|
-
};
|
|
81
|
-
|
|
82
53
|
it("renders label when grant provided", async () => {
|
|
83
|
-
const
|
|
84
|
-
|
|
85
|
-
properties: defaultStructureProperties,
|
|
86
|
-
userPermissions: { update: true, update_domain: true },
|
|
87
|
-
};
|
|
88
|
-
const store = createStore(() => ({ ...storeProps }));
|
|
89
|
-
|
|
90
|
-
const props = {
|
|
91
|
-
...structure,
|
|
92
|
-
updatedAt,
|
|
93
|
-
deleted_at,
|
|
94
|
-
structureFields,
|
|
95
|
-
grant: { detail: { foo: "bar" }, end_date: "2022-01-02T03:04:05Z" },
|
|
96
|
-
};
|
|
97
|
-
const { container } = render(
|
|
98
|
-
<Provider store={store}>
|
|
99
|
-
<StructureSummary {...props} />
|
|
100
|
-
</Provider>,
|
|
101
|
-
{
|
|
102
|
-
messages,
|
|
103
|
-
}
|
|
54
|
+
const customState = _.set("structure.grant", { detail: { foo: "bar" } })(
|
|
55
|
+
state
|
|
104
56
|
);
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
const grant = (grant) => <p>{grant.detail.foo}</p>;
|
|
110
|
-
const storeProps = {
|
|
111
|
-
structure,
|
|
112
|
-
properties: defaultStructureProperties,
|
|
113
|
-
userPermissions: { update: true, update_domain: true },
|
|
114
|
-
};
|
|
115
|
-
const store = createStore(() => ({ ...storeProps }));
|
|
116
|
-
|
|
117
|
-
const props = {
|
|
118
|
-
...structure,
|
|
119
|
-
updatedAt,
|
|
120
|
-
deleted_at,
|
|
121
|
-
structureFields,
|
|
122
|
-
grant: { detail: { foo: "bar" }, end_date: "2022-01-02T03:04:05Z" },
|
|
123
|
-
structureGrant: grant,
|
|
124
|
-
};
|
|
125
|
-
const { container } = render(
|
|
126
|
-
<Provider store={store}>
|
|
127
|
-
<StructureSummary {...props} />
|
|
128
|
-
</Provider>,
|
|
129
|
-
{
|
|
130
|
-
messages,
|
|
131
|
-
}
|
|
132
|
-
);
|
|
133
|
-
expect(container).toMatchSnapshot();
|
|
57
|
+
const { findByText } = render(<StructureSummary />, { state: customState });
|
|
58
|
+
expect(
|
|
59
|
+
findByText("You have granted access on this structure")
|
|
60
|
+
).toBeTruthy();
|
|
134
61
|
});
|
|
135
62
|
});
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
+
|
|
3
|
+
exports[`<StructureGrantButton /> matches the latest snapshot 1`] = `
|
|
4
|
+
<div>
|
|
5
|
+
<div
|
|
6
|
+
class="ui green label"
|
|
7
|
+
>
|
|
8
|
+
<i
|
|
9
|
+
aria-hidden="true"
|
|
10
|
+
class="shield icon"
|
|
11
|
+
/>
|
|
12
|
+
You have granted access on this structure
|
|
13
|
+
<i
|
|
14
|
+
aria-hidden="true"
|
|
15
|
+
class="delete icon"
|
|
16
|
+
/>
|
|
17
|
+
</div>
|
|
18
|
+
</div>
|
|
19
|
+
`;
|
|
20
|
+
|
|
21
|
+
exports[`<StructureGrantButton /> matches the latest snapshot pending_removal 1`] = `
|
|
22
|
+
<div>
|
|
23
|
+
<div
|
|
24
|
+
class="ui orange label"
|
|
25
|
+
>
|
|
26
|
+
<i
|
|
27
|
+
aria-hidden="true"
|
|
28
|
+
class="shield icon"
|
|
29
|
+
/>
|
|
30
|
+
You have granted access pending removal
|
|
31
|
+
<i
|
|
32
|
+
aria-hidden="true"
|
|
33
|
+
class="undo icon"
|
|
34
|
+
/>
|
|
35
|
+
</div>
|
|
36
|
+
</div>
|
|
37
|
+
`;
|
|
@@ -1,123 +1,6 @@
|
|
|
1
1
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
2
|
|
|
3
3
|
exports[`<StructureSummary /> matches the latest snapshot 1`] = `
|
|
4
|
-
<Fragment>
|
|
5
|
-
<Grid>
|
|
6
|
-
<GridRow>
|
|
7
|
-
<GridColumn
|
|
8
|
-
width={10}
|
|
9
|
-
>
|
|
10
|
-
<DimmerDimmable
|
|
11
|
-
dimmed={false}
|
|
12
|
-
>
|
|
13
|
-
<Header
|
|
14
|
-
as="h2"
|
|
15
|
-
>
|
|
16
|
-
<HeaderContent>
|
|
17
|
-
s1
|
|
18
|
-
<Connect(StructureGrantRequestButton) />
|
|
19
|
-
</HeaderContent>
|
|
20
|
-
</Header>
|
|
21
|
-
<Dimmer
|
|
22
|
-
active={false}
|
|
23
|
-
inverted={true}
|
|
24
|
-
>
|
|
25
|
-
<Loader />
|
|
26
|
-
</Dimmer>
|
|
27
|
-
</DimmerDimmable>
|
|
28
|
-
</GridColumn>
|
|
29
|
-
<GridColumn
|
|
30
|
-
textAlign="right"
|
|
31
|
-
width={6}
|
|
32
|
-
>
|
|
33
|
-
<Date
|
|
34
|
-
className="alert warning"
|
|
35
|
-
date="2019-01-02T03:04:05Z"
|
|
36
|
-
icon={
|
|
37
|
-
<Icon
|
|
38
|
-
as="i"
|
|
39
|
-
color="red"
|
|
40
|
-
name="warning circle"
|
|
41
|
-
/>
|
|
42
|
-
}
|
|
43
|
-
label="deleted_at"
|
|
44
|
-
/>
|
|
45
|
-
<Connect(ShareLinkPopup)
|
|
46
|
-
description="dd"
|
|
47
|
-
name="s1"
|
|
48
|
-
title="structure.share.title"
|
|
49
|
-
url="http://localhost/"
|
|
50
|
-
/>
|
|
51
|
-
<injectIntl(Connect(StructureConfidentialButton)) />
|
|
52
|
-
</GridColumn>
|
|
53
|
-
</GridRow>
|
|
54
|
-
</Grid>
|
|
55
|
-
<Connect(TagsHeader) />
|
|
56
|
-
<Connect(StructureProperties) />
|
|
57
|
-
</Fragment>
|
|
58
|
-
`;
|
|
59
|
-
|
|
60
|
-
exports[`<StructureSummary /> matches the latest snapshot with alias 1`] = `
|
|
61
|
-
<Fragment>
|
|
62
|
-
<Grid>
|
|
63
|
-
<GridRow>
|
|
64
|
-
<GridColumn
|
|
65
|
-
width={10}
|
|
66
|
-
>
|
|
67
|
-
<DimmerDimmable
|
|
68
|
-
dimmed={false}
|
|
69
|
-
>
|
|
70
|
-
<Header
|
|
71
|
-
as="h2"
|
|
72
|
-
>
|
|
73
|
-
<HeaderContent>
|
|
74
|
-
some alias
|
|
75
|
-
<Connect(StructureGrantRequestButton) />
|
|
76
|
-
<HeaderSubheader>
|
|
77
|
-
s1
|
|
78
|
-
</HeaderSubheader>
|
|
79
|
-
</HeaderContent>
|
|
80
|
-
</Header>
|
|
81
|
-
<Dimmer
|
|
82
|
-
active={false}
|
|
83
|
-
inverted={true}
|
|
84
|
-
>
|
|
85
|
-
<Loader />
|
|
86
|
-
</Dimmer>
|
|
87
|
-
</DimmerDimmable>
|
|
88
|
-
</GridColumn>
|
|
89
|
-
<GridColumn
|
|
90
|
-
textAlign="right"
|
|
91
|
-
width={6}
|
|
92
|
-
>
|
|
93
|
-
<Date
|
|
94
|
-
className="alert warning"
|
|
95
|
-
date="2019-01-02T03:04:05Z"
|
|
96
|
-
icon={
|
|
97
|
-
<Icon
|
|
98
|
-
as="i"
|
|
99
|
-
color="red"
|
|
100
|
-
name="warning circle"
|
|
101
|
-
/>
|
|
102
|
-
}
|
|
103
|
-
label="deleted_at"
|
|
104
|
-
/>
|
|
105
|
-
<Connect(ShareLinkPopup)
|
|
106
|
-
description="dd"
|
|
107
|
-
name="s1"
|
|
108
|
-
title="structure.share.title"
|
|
109
|
-
url="http://localhost/"
|
|
110
|
-
/>
|
|
111
|
-
<injectIntl(Connect(StructureConfidentialButton)) />
|
|
112
|
-
</GridColumn>
|
|
113
|
-
</GridRow>
|
|
114
|
-
</Grid>
|
|
115
|
-
<Connect(TagsHeader) />
|
|
116
|
-
<Connect(StructureProperties) />
|
|
117
|
-
</Fragment>
|
|
118
|
-
`;
|
|
119
|
-
|
|
120
|
-
exports[`<StructureSummary /> renders custom grant label when grant provided 1`] = `
|
|
121
4
|
<div>
|
|
122
5
|
<div
|
|
123
6
|
class="ui grid"
|
|
@@ -138,9 +21,6 @@ exports[`<StructureSummary /> renders custom grant label when grant provided 1`]
|
|
|
138
21
|
class="content"
|
|
139
22
|
>
|
|
140
23
|
s1
|
|
141
|
-
<p>
|
|
142
|
-
bar
|
|
143
|
-
</p>
|
|
144
24
|
</div>
|
|
145
25
|
</h2>
|
|
146
26
|
<div
|
|
@@ -160,14 +40,14 @@ exports[`<StructureSummary /> renders custom grant label when grant provided 1`]
|
|
|
160
40
|
class="right aligned six wide column"
|
|
161
41
|
>
|
|
162
42
|
<div
|
|
163
|
-
class="ui label
|
|
164
|
-
title="
|
|
43
|
+
class="ui label basic"
|
|
44
|
+
title="Last changed 2019-01-02T03:04:05Z"
|
|
165
45
|
>
|
|
166
46
|
<i
|
|
167
47
|
aria-hidden="true"
|
|
168
|
-
class="
|
|
48
|
+
class="sync alternate icon"
|
|
169
49
|
/>
|
|
170
|
-
|
|
50
|
+
Last changed
|
|
171
51
|
:
|
|
172
52
|
<time
|
|
173
53
|
datetime="1546398245000"
|
|
@@ -183,6 +63,14 @@ exports[`<StructureSummary /> renders custom grant label when grant provided 1`]
|
|
|
183
63
|
class="share alternate icon"
|
|
184
64
|
/>
|
|
185
65
|
</button>
|
|
66
|
+
<button
|
|
67
|
+
class="ui icon button basic"
|
|
68
|
+
>
|
|
69
|
+
<i
|
|
70
|
+
aria-hidden="true"
|
|
71
|
+
class="red trash alternate icon"
|
|
72
|
+
/>
|
|
73
|
+
</button>
|
|
186
74
|
</div>
|
|
187
75
|
</div>
|
|
188
76
|
</div>
|
|
@@ -209,21 +97,12 @@ exports[`<StructureSummary /> renders custom grant label when grant provided 1`]
|
|
|
209
97
|
<h5
|
|
210
98
|
class="header"
|
|
211
99
|
>
|
|
212
|
-
|
|
100
|
+
Domain
|
|
213
101
|
</h5>
|
|
214
102
|
<div
|
|
215
103
|
class="description"
|
|
216
104
|
>
|
|
217
105
|
|
|
218
|
-
<button
|
|
219
|
-
class="ui basic icon button"
|
|
220
|
-
style="box-shadow: none;"
|
|
221
|
-
>
|
|
222
|
-
<i
|
|
223
|
-
aria-hidden="true"
|
|
224
|
-
class="pencil alternate icon"
|
|
225
|
-
/>
|
|
226
|
-
</button>
|
|
227
106
|
</div>
|
|
228
107
|
</div>
|
|
229
108
|
</div>
|
|
@@ -240,7 +119,7 @@ exports[`<StructureSummary /> renders custom grant label when grant provided 1`]
|
|
|
240
119
|
<h5
|
|
241
120
|
class="header"
|
|
242
121
|
>
|
|
243
|
-
|
|
122
|
+
Group
|
|
244
123
|
</h5>
|
|
245
124
|
<div
|
|
246
125
|
class="description"
|
|
@@ -262,7 +141,7 @@ exports[`<StructureSummary /> renders custom grant label when grant provided 1`]
|
|
|
262
141
|
<h5
|
|
263
142
|
class="header"
|
|
264
143
|
>
|
|
265
|
-
|
|
144
|
+
Type
|
|
266
145
|
</h5>
|
|
267
146
|
<div
|
|
268
147
|
class="description"
|
|
@@ -277,7 +156,7 @@ exports[`<StructureSummary /> renders custom grant label when grant provided 1`]
|
|
|
277
156
|
</div>
|
|
278
157
|
`;
|
|
279
158
|
|
|
280
|
-
exports[`<StructureSummary />
|
|
159
|
+
exports[`<StructureSummary /> matches the latest snapshot with alias 1`] = `
|
|
281
160
|
<div>
|
|
282
161
|
<div
|
|
283
162
|
class="ui grid"
|
|
@@ -297,15 +176,11 @@ exports[`<StructureSummary /> renders label when grant provided 1`] = `
|
|
|
297
176
|
<div
|
|
298
177
|
class="content"
|
|
299
178
|
>
|
|
300
|
-
|
|
179
|
+
some alias
|
|
301
180
|
<div
|
|
302
|
-
class="
|
|
181
|
+
class="sub header"
|
|
303
182
|
>
|
|
304
|
-
|
|
305
|
-
aria-hidden="true"
|
|
306
|
-
class="shield icon"
|
|
307
|
-
/>
|
|
308
|
-
structure.grant.has_grant
|
|
183
|
+
s1
|
|
309
184
|
</div>
|
|
310
185
|
</div>
|
|
311
186
|
</h2>
|
|
@@ -326,14 +201,14 @@ exports[`<StructureSummary /> renders label when grant provided 1`] = `
|
|
|
326
201
|
class="right aligned six wide column"
|
|
327
202
|
>
|
|
328
203
|
<div
|
|
329
|
-
class="ui label
|
|
330
|
-
title="
|
|
204
|
+
class="ui label basic"
|
|
205
|
+
title="Last changed 2019-01-02T03:04:05Z"
|
|
331
206
|
>
|
|
332
207
|
<i
|
|
333
208
|
aria-hidden="true"
|
|
334
|
-
class="
|
|
209
|
+
class="sync alternate icon"
|
|
335
210
|
/>
|
|
336
|
-
|
|
211
|
+
Last changed
|
|
337
212
|
:
|
|
338
213
|
<time
|
|
339
214
|
datetime="1546398245000"
|
|
@@ -349,6 +224,14 @@ exports[`<StructureSummary /> renders label when grant provided 1`] = `
|
|
|
349
224
|
class="share alternate icon"
|
|
350
225
|
/>
|
|
351
226
|
</button>
|
|
227
|
+
<button
|
|
228
|
+
class="ui icon button basic"
|
|
229
|
+
>
|
|
230
|
+
<i
|
|
231
|
+
aria-hidden="true"
|
|
232
|
+
class="red trash alternate icon"
|
|
233
|
+
/>
|
|
234
|
+
</button>
|
|
352
235
|
</div>
|
|
353
236
|
</div>
|
|
354
237
|
</div>
|
|
@@ -375,21 +258,12 @@ exports[`<StructureSummary /> renders label when grant provided 1`] = `
|
|
|
375
258
|
<h5
|
|
376
259
|
class="header"
|
|
377
260
|
>
|
|
378
|
-
|
|
261
|
+
Domain
|
|
379
262
|
</h5>
|
|
380
263
|
<div
|
|
381
264
|
class="description"
|
|
382
265
|
>
|
|
383
266
|
|
|
384
|
-
<button
|
|
385
|
-
class="ui basic icon button"
|
|
386
|
-
style="box-shadow: none;"
|
|
387
|
-
>
|
|
388
|
-
<i
|
|
389
|
-
aria-hidden="true"
|
|
390
|
-
class="pencil alternate icon"
|
|
391
|
-
/>
|
|
392
|
-
</button>
|
|
393
267
|
</div>
|
|
394
268
|
</div>
|
|
395
269
|
</div>
|
|
@@ -406,7 +280,7 @@ exports[`<StructureSummary /> renders label when grant provided 1`] = `
|
|
|
406
280
|
<h5
|
|
407
281
|
class="header"
|
|
408
282
|
>
|
|
409
|
-
|
|
283
|
+
Group
|
|
410
284
|
</h5>
|
|
411
285
|
<div
|
|
412
286
|
class="description"
|
|
@@ -428,7 +302,7 @@ exports[`<StructureSummary /> renders label when grant provided 1`] = `
|
|
|
428
302
|
<h5
|
|
429
303
|
class="header"
|
|
430
304
|
>
|
|
431
|
-
|
|
305
|
+
Type
|
|
432
306
|
</h5>
|
|
433
307
|
<div
|
|
434
308
|
class="description"
|
package/src/messages/en.js
CHANGED
|
@@ -29,6 +29,9 @@ export default {
|
|
|
29
29
|
"filters.system.name.raw": "System",
|
|
30
30
|
"filters.tags.raw": "Tags",
|
|
31
31
|
"filters.type.raw": "Type",
|
|
32
|
+
"filters.pending_removal.raw": "Pending Removal",
|
|
33
|
+
"filters.pending_removal.raw.true": "Pending removal",
|
|
34
|
+
"filters.pending_removal.raw.false": "Not pending removal",
|
|
32
35
|
"filters.system_external_id": "System",
|
|
33
36
|
"filters.user_name": "User",
|
|
34
37
|
"filters.with_content.raw": "Extra Info",
|
|
@@ -36,8 +39,15 @@ export default {
|
|
|
36
39
|
"filters.with_profiling.raw": "Profile",
|
|
37
40
|
"filters.with_profiling.raw.false": "Without profile",
|
|
38
41
|
"filters.with_profiling.raw.true": "With profile",
|
|
42
|
+
"grant.actions.cancel_removal.confirmation.content":
|
|
43
|
+
"Cancelling grant removal. Are you sure?",
|
|
44
|
+
"grant.actions.cancel_removal.confirmation.header": "Cancel grant removal",
|
|
45
|
+
"grant.actions.request_removal.confirmation.content":
|
|
46
|
+
"Requesting this grant to be revoked. Are you sure?",
|
|
47
|
+
"grant.actions.request_removal.confirmation.header": "Request grant removal",
|
|
39
48
|
"grant.cell.direct_access": "Direct access",
|
|
40
49
|
"grant.cell.end_date.null": "No expiration set",
|
|
50
|
+
"grant.cell.end_date.pending_removal": "Grant pending removal",
|
|
41
51
|
"grant.cell.end_date.same_user": "It's you",
|
|
42
52
|
"grant.header.user": "Account",
|
|
43
53
|
"grant.header.data_structure_version": "Structure",
|
|
@@ -231,6 +241,8 @@ export default {
|
|
|
231
241
|
"structure.fields.empty": "No field information available for this structure",
|
|
232
242
|
"structure.filter.empty": "Empty",
|
|
233
243
|
"structure.grant.has_grant": "You have granted access on this structure",
|
|
244
|
+
"structure.grant.has_grant_pending_removal":
|
|
245
|
+
"You have granted access pending removal",
|
|
234
246
|
"structure.grant.request_grant": "Request grant",
|
|
235
247
|
"structure.grant.requested_grant": "Pending request",
|
|
236
248
|
"structure.grant.cart": "Requested grants",
|
|
@@ -542,7 +554,6 @@ export default {
|
|
|
542
554
|
"A Structure Tag with this name already exists",
|
|
543
555
|
"updateStructureType.success.header": "Structure type updated",
|
|
544
556
|
"updateSystem.error.df_content.invalid content": "Invalid template content",
|
|
545
|
-
"structure.grant.has_grant": "You have granted access on this structure",
|
|
546
557
|
"visualization.title.impact": "Impact Analysis",
|
|
547
558
|
"visualization.title.lineage": "Lineage Analysis",
|
|
548
559
|
};
|
package/src/messages/es.js
CHANGED
|
@@ -34,13 +34,25 @@ export default {
|
|
|
34
34
|
"filters.type.raw": "Tipo",
|
|
35
35
|
"filters.system_external_id": "Sistema",
|
|
36
36
|
"filters.user_name": "Usuario",
|
|
37
|
+
"filters.pending_removal.raw": "Pendiente de eliminar",
|
|
38
|
+
"filters.pending_removal.raw.true": "Pendiente de eliminar",
|
|
39
|
+
"filters.pending_removal.raw.false": "No pendiente de eliminar",
|
|
37
40
|
"filters.with_content.raw": "Extra Info",
|
|
38
41
|
"filters.with_content.raw.false": "Sin información extra",
|
|
39
42
|
"filters.with_profiling.raw": "Perfilado",
|
|
40
43
|
"filters.with_profiling.raw.false": "Sin perfilado",
|
|
41
44
|
"filters.with_profiling.raw.true": "Contiene perfilado",
|
|
45
|
+
"grant.actions.cancel_removal.confirmation.content":
|
|
46
|
+
"Cancelar solicitud de eliminar acceso. ¿Estás seguro?",
|
|
47
|
+
"grant.actions.cancel_removal.confirmation.header":
|
|
48
|
+
"Cancelar retirada de acceso",
|
|
49
|
+
"grant.actions.request_removal.confirmation.content":
|
|
50
|
+
"El acceso será eliminado. ¿Estás seguro?",
|
|
51
|
+
"grant.actions.request_removal.confirmation.header":
|
|
52
|
+
"Solicitar eliminación de acceso",
|
|
42
53
|
"grant.cell.direct_access": "Acceso Directo",
|
|
43
54
|
"grant.cell.end_date.null": "Sin fecha de expiración",
|
|
55
|
+
"grant.cell.end_date.pending_removal": "Solicitada expiración del acceso",
|
|
44
56
|
"grant.cell.end_date.same_user": "Eres tú",
|
|
45
57
|
"grant.header.data_structure_version": "Estructura",
|
|
46
58
|
"grant.header.end_date": "Expira",
|
|
@@ -238,6 +250,8 @@ export default {
|
|
|
238
250
|
"No se dispone de información sobre los campos de esta estructura",
|
|
239
251
|
"structure.filter.empty": "Vacío",
|
|
240
252
|
"structure.grant.has_grant": "Tienes acceso a la estructura",
|
|
253
|
+
"structure.grant.has_grant_pending_removal":
|
|
254
|
+
"Tienes acceso pendiente de eliminarse",
|
|
241
255
|
"structure.grant.request_grant": "Solicitar acceso",
|
|
242
256
|
"structure.grant.requested_grant": "Solicitud pendiente",
|
|
243
257
|
"structure.grant.cart": "Accesos a solicitar",
|
|
@@ -558,7 +572,6 @@ export default {
|
|
|
558
572
|
"updateStructureType.success.header": "Tipo actualizado correctamente",
|
|
559
573
|
"updateSystem.error.df_content.invalid content":
|
|
560
574
|
"Contenido de plantilla inválido",
|
|
561
|
-
"structure.grant.has_grant": "Tienes acceso a la estructura",
|
|
562
575
|
"visualization.title.impact": "Análisis de Impacto",
|
|
563
576
|
"visualization.title.lineage": "Análisis de Linaje",
|
|
564
577
|
};
|
package/src/routines.js
CHANGED
|
@@ -57,7 +57,7 @@ export const downloadGrants = createRoutine("DOWNLOAD_GRANTS");
|
|
|
57
57
|
export const downloadReferenceDataset = createRoutine("DOWNLOAD_REFERENCE_DATASET");
|
|
58
58
|
export const downloadStructures = createRoutine("DOWNLOAD_STRUCTURES");
|
|
59
59
|
export const excludeNode = createRoutine("EXCLUDE_NODE");
|
|
60
|
-
export const fetchDomains = createRoutine("FETCH_DOMAINS");
|
|
60
|
+
export const fetchDomains = createRoutine("FETCH_DOMAINS");
|
|
61
61
|
export const fetchGrant = createRoutine("FETCH_GRANT");
|
|
62
62
|
export const fetchGrantFilters = createRoutine("FETCH_GRANT_FILTERS");
|
|
63
63
|
export const fetchGrantRequest = createRoutine("FETCH_GRANT_REQUEST");
|
|
@@ -90,6 +90,7 @@ export const linkStructureTag = createRoutine("LINK_STRUCTURE_TAG");
|
|
|
90
90
|
export const loadLineageEvents = createRoutine("LOAD_LINEAGE_EVENTS");
|
|
91
91
|
export const openGrantFilter = createRoutine("OPEN_GRANT_FILTER");
|
|
92
92
|
export const openStructureFilter = createRoutine("OPEN_STRUCTURE_FILTER");
|
|
93
|
+
export const requestGrantRemoval = createRoutine("REQUEST_GRANT_REMOVAL");
|
|
93
94
|
export const removeGrantFilter = createRoutine("REMOVE_GRANT_FILTER");
|
|
94
95
|
export const removeGrantRequestFromCart = createRoutine("REMOVE_GRANT_REQUEST_FROM_CART");
|
|
95
96
|
export const removeGrantRequestsQuery = createRoutine("REMOVE_GRANT_REQUESTS_QUERY");
|
package/src/sagas/index.js
CHANGED
|
@@ -42,6 +42,7 @@ import { fetchUnitDomainsRequestSaga } from "./fetchUnitDomains";
|
|
|
42
42
|
import { fetchUserSearchFiltersRequestSaga } from "./fetchUserSearchFilters";
|
|
43
43
|
import { linkStructureTagRequestSaga } from "./linkStructureTag";
|
|
44
44
|
import { operateGrantRequestToCartRequestSaga } from "./operateGrantRequestCart";
|
|
45
|
+
import { requestGrantRemovalRequestSaga } from "./requestGrantRemoval";
|
|
45
46
|
import { saveUserSearchFiltersRequestSaga } from "./saveUserSearchFilters";
|
|
46
47
|
import { updateReferenceDatasetRequestSaga } from "./updateReferenceDataset";
|
|
47
48
|
import { updateStructureRequestSaga } from "./updateStructure";
|
|
@@ -96,6 +97,7 @@ export {
|
|
|
96
97
|
fetchUserSearchFiltersRequestSaga,
|
|
97
98
|
linkStructureTagRequestSaga,
|
|
98
99
|
operateGrantRequestToCartRequestSaga,
|
|
100
|
+
requestGrantRemovalRequestSaga,
|
|
99
101
|
saveUserSearchFiltersRequestSaga,
|
|
100
102
|
updateReferenceDatasetRequestSaga,
|
|
101
103
|
updateStructureRequestSaga,
|
|
@@ -151,6 +153,7 @@ export default [
|
|
|
151
153
|
fetchUserSearchFiltersRequestSaga(),
|
|
152
154
|
linkStructureTagRequestSaga(),
|
|
153
155
|
operateGrantRequestToCartRequestSaga(),
|
|
156
|
+
requestGrantRemovalRequestSaga(),
|
|
154
157
|
saveUserSearchFiltersRequestSaga(),
|
|
155
158
|
updateReferenceDatasetRequestSaga(),
|
|
156
159
|
updateStructureRequestSaga(),
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { compile } from "path-to-regexp";
|
|
2
|
+
import { call, put, takeLatest } from "redux-saga/effects";
|
|
3
|
+
import { apiJsonPatch, JSON_OPTS } from "@truedat/core/services/api";
|
|
4
|
+
import { requestGrantRemoval, fetchStructure } from "../routines";
|
|
5
|
+
import { API_GRANT } from "../api";
|
|
6
|
+
|
|
7
|
+
export function* requestGrantRemovalSaga({ payload }) {
|
|
8
|
+
try {
|
|
9
|
+
const { id, action, data_structure_id, version } = payload;
|
|
10
|
+
const url = compile(API_GRANT)({ id });
|
|
11
|
+
const requestData = { action };
|
|
12
|
+
yield put(requestGrantRemoval.request());
|
|
13
|
+
const { data } = yield call(apiJsonPatch, url, requestData, JSON_OPTS);
|
|
14
|
+
yield put(requestGrantRemoval.success(data));
|
|
15
|
+
yield put(fetchStructure.trigger({ id: data_structure_id, version }));
|
|
16
|
+
} catch (error) {
|
|
17
|
+
console.error("error", error);
|
|
18
|
+
if (error.response) {
|
|
19
|
+
const { status, data } = error.response;
|
|
20
|
+
yield put(requestGrantRemoval.failure({ status, data }));
|
|
21
|
+
} else {
|
|
22
|
+
yield put(requestGrantRemoval.failure(error.message));
|
|
23
|
+
}
|
|
24
|
+
} finally {
|
|
25
|
+
yield put(requestGrantRemoval.fulfill());
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function* requestGrantRemovalRequestSaga() {
|
|
30
|
+
yield takeLatest(requestGrantRemoval.TRIGGER, requestGrantRemovalSaga);
|
|
31
|
+
}
|
|
@@ -6,6 +6,7 @@ import { Link } from "react-router-dom";
|
|
|
6
6
|
import { linkTo } from "@truedat/core/routes";
|
|
7
7
|
import { useIntl } from "react-intl";
|
|
8
8
|
import Moment from "react-moment";
|
|
9
|
+
import moment from "moment";
|
|
9
10
|
import PropTypes from "prop-types";
|
|
10
11
|
|
|
11
12
|
export const GrantUserDecorator = ({ authentication, user }) => {
|
|
@@ -124,19 +125,25 @@ StartDateDecorator.propTypes = {
|
|
|
124
125
|
start_date: PropTypes.string,
|
|
125
126
|
};
|
|
126
127
|
|
|
127
|
-
export const EndDateDecorator = ({ end_date }) => {
|
|
128
|
+
export const EndDateDecorator = ({ end_date, pending_removal }) => {
|
|
128
129
|
const { locale, formatMessage } = useIntl();
|
|
129
|
-
return
|
|
130
|
+
return pending_removal ? (
|
|
131
|
+
<Header>
|
|
132
|
+
<Header.Subheader>
|
|
133
|
+
{formatMessage({ id: "grant.cell.end_date.pending_removal" })}
|
|
134
|
+
</Header.Subheader>
|
|
135
|
+
</Header>
|
|
136
|
+
) : end_date ? (
|
|
130
137
|
<Popup
|
|
131
|
-
content={
|
|
132
|
-
<Moment locale={locale} date={end_date} format="YYYY-MM-DD HH:mm" />
|
|
133
|
-
}
|
|
138
|
+
content={<Moment locale={locale} date={end_date} format="YYYY-MM-DD" />}
|
|
134
139
|
trigger={
|
|
135
140
|
<Header>
|
|
136
141
|
<Header.Subheader>
|
|
137
|
-
<Moment
|
|
138
|
-
{
|
|
139
|
-
|
|
142
|
+
<Moment
|
|
143
|
+
locale={locale}
|
|
144
|
+
date={end_date}
|
|
145
|
+
from={moment().format("L")}
|
|
146
|
+
/>
|
|
140
147
|
</Header.Subheader>
|
|
141
148
|
</Header>
|
|
142
149
|
}
|
|
@@ -152,6 +159,7 @@ export const EndDateDecorator = ({ end_date }) => {
|
|
|
152
159
|
|
|
153
160
|
EndDateDecorator.propTypes = {
|
|
154
161
|
end_date: PropTypes.string,
|
|
162
|
+
pending_removal: PropTypes.bool,
|
|
155
163
|
};
|
|
156
164
|
|
|
157
165
|
export const defaultGrantsColumns = [
|
|
@@ -172,7 +180,7 @@ export const defaultGrantsColumns = [
|
|
|
172
180
|
},
|
|
173
181
|
{
|
|
174
182
|
name: "end_date",
|
|
175
|
-
fieldSelector: _.pick(["end_date"]),
|
|
183
|
+
fieldSelector: _.pick(["end_date", "pending_removal"]),
|
|
176
184
|
fieldDecorator: EndDateDecorator,
|
|
177
185
|
},
|
|
178
186
|
];
|
|
@@ -214,7 +222,7 @@ export const defaultGrantsTableColumns = [
|
|
|
214
222
|
{
|
|
215
223
|
name: "end_date",
|
|
216
224
|
sort: { name: "end_date" },
|
|
217
|
-
fieldSelector: _.pick(["end_date"]),
|
|
225
|
+
fieldSelector: _.pick(["end_date", "pending_removal"]),
|
|
218
226
|
fieldDecorator: EndDateDecorator,
|
|
219
227
|
},
|
|
220
228
|
{
|