@truedat/dd 5.19.0 → 5.20.0

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.
Files changed (43) hide show
  1. package/package.json +5 -5
  2. package/src/api/queries.js +19 -1
  3. package/src/components/Grant.js +9 -27
  4. package/src/components/GrantRemoval.js +26 -34
  5. package/src/components/GrantRemovalDirectButton.js +89 -0
  6. package/src/components/GrantRemovalWorkflow.js +107 -0
  7. package/src/components/GrantRemovalWorkflowDropdown.js +144 -0
  8. package/src/components/GrantRequest.js +2 -1
  9. package/src/components/GrantRequestCancel.js +5 -2
  10. package/src/components/GrantRequestHeader.js +13 -7
  11. package/src/components/GrantRequestRow.js +8 -1
  12. package/src/components/GrantRequests.js +8 -3
  13. package/src/components/GrantRequestsTable.js +1 -1
  14. package/src/components/StructureGrantDropdown.js +7 -40
  15. package/src/components/StructureGrantSummaryButton.js +2 -2
  16. package/src/components/StructureGrants.js +21 -17
  17. package/src/components/__tests__/Grant.spec.js +11 -7
  18. package/src/components/__tests__/GrantRemoval.spec.js +19 -54
  19. package/src/components/__tests__/GrantRemovalDirectButton.spec.js +66 -0
  20. package/src/components/__tests__/GrantRemovalWorkflow.spec.js +157 -0
  21. package/src/components/__tests__/GrantRequest.spec.js +2 -0
  22. package/src/components/__tests__/GrantRequestHeader.spec.js +2 -5
  23. package/src/components/__tests__/StructureGrantDropdown.spec.js +1 -16
  24. package/src/components/__tests__/StructureGrantSummaryButton.spec.js +3 -2
  25. package/src/components/__tests__/StructureGrants.spec.js +5 -1
  26. package/src/components/__tests__/__snapshots__/Grant.spec.js.snap +5 -4
  27. package/src/components/__tests__/__snapshots__/GrantRequest.spec.js.snap +3 -3
  28. package/src/components/__tests__/__snapshots__/GrantRequestHeader.spec.js.snap +4 -4
  29. package/src/components/__tests__/__snapshots__/GrantRequestsSearchResults.spec.js.snap +1 -1
  30. package/src/components/__tests__/__snapshots__/StructureGrantDropdown.spec.js.snap +0 -52
  31. package/src/components/__tests__/__snapshots__/StructureGrantListButton.spec.js.snap +0 -14
  32. package/src/components/__tests__/__snapshots__/StructureGrantSummaryButton.spec.js.snap +0 -14
  33. package/src/components/__tests__/__snapshots__/StructureGrants.spec.js.snap +4 -5
  34. package/src/hooks/useGrantRequest.js +10 -1
  35. package/src/messages/en.js +23 -8
  36. package/src/messages/es.js +26 -9
  37. package/src/reducers/structure.js +1 -0
  38. package/src/sagas/__tests__/createGrantRequestStatus.spec.js +1 -1
  39. package/src/sagas/createGrantRequestStatus.js +24 -8
  40. package/src/selectors/getGrantRequestsColumns.js +32 -5
  41. package/src/selectors/getGrantRequestsSearchColumns.js +20 -14
  42. package/src/selectors/utils/decorators.js +68 -0
  43. package/src/components/__tests__/__snapshots__/GrantRemoval.spec.js.snap +0 -9
@@ -47,18 +47,22 @@ describe("<StructureGrants />", () => {
47
47
  user: { id: 1, full_name: "foo user" },
48
48
  data_structure: structure,
49
49
  end_date: "2021/08/02",
50
+ pending_removal: false,
50
51
  },
51
52
  {
52
53
  id: 2,
53
54
  user: { id: 2, full_name: "bar user" },
54
55
  data_structure: { name: "bar structure" },
55
56
  end_date: "2021/09/02",
57
+ pending_removal: false,
56
58
  },
57
59
  ];
58
60
 
59
61
  const userPermissions = { update_grant_removal: {} };
60
62
 
61
- const props = { grants, columns, structure, userPermissions };
63
+ const grantsActions = { manage_grant_removal: {} };
64
+
65
+ const props = { grants, columns, structure, userPermissions, grantsActions };
62
66
 
63
67
  it("matches the latest snapshot", () => {
64
68
  const { container } = render(<StructureGrants {...props} />);
@@ -223,7 +223,7 @@ exports[`<Grant /> matches the latest snapshot 1`] = `
223
223
  </div>
224
224
  `;
225
225
 
226
- exports[`<Grant /> matches the latest snapshot with cancel_removal action 1`] = `
226
+ exports[`<Grant /> matches the latest snapshot with manage_grant_removal action 1`] = `
227
227
  <div>
228
228
  <div
229
229
  class="ui breadcrumb"
@@ -552,15 +552,16 @@ exports[`<Grant /> matches the latest snapshot with update action 1`] = `
552
552
  Grants -&gt; foo
553
553
  </div>
554
554
  </h2>
555
+ </div>
556
+ <div
557
+ class="right aligned four wide column"
558
+ >
555
559
  <button
556
560
  class="ui button button icon group-actions"
557
561
  >
558
562
  Request grant change
559
563
  </button>
560
564
  </div>
561
- <div
562
- class="right aligned four wide column"
563
- />
564
565
  </div>
565
566
  </div>
566
567
  <div
@@ -47,7 +47,7 @@ exports[`<GrantRequest /> matches the latest snapshot 1`] = `
47
47
  <div
48
48
  class="content"
49
49
  >
50
- header
50
+ Structure access
51
51
  </div>
52
52
  </h2>
53
53
  </div>
@@ -198,7 +198,7 @@ exports[`<GrantRequest /> matches the latest snapshot with approve actions 1`] =
198
198
  <div
199
199
  class="content"
200
200
  >
201
- header
201
+ Structure access
202
202
  </div>
203
203
  </h2>
204
204
  </div>
@@ -465,7 +465,7 @@ exports[`<GrantRequest /> matches the latest snapshot with failed status 1`] = `
465
465
  <div
466
466
  class="content"
467
467
  >
468
- header
468
+ Structure access
469
469
  </div>
470
470
  </h2>
471
471
  </div>
@@ -18,7 +18,7 @@ exports[`<GrantRequestHeader /> matches the latest snapshot (pending) 1`] = `
18
18
  <div
19
19
  class="content"
20
20
  >
21
- header
21
+ Structure access request
22
22
  </div>
23
23
  </h2>
24
24
  </div>
@@ -28,12 +28,12 @@ exports[`<GrantRequestHeader /> matches the latest snapshot (pending) 1`] = `
28
28
  <button
29
29
  class="ui primary button button icon group-actions"
30
30
  >
31
- approve
31
+ Approve
32
32
  </button>
33
33
  <button
34
34
  class="ui secondary button button icon group-actions"
35
35
  >
36
- reject
36
+ Reject
37
37
  </button>
38
38
  </div>
39
39
  </div>
@@ -58,7 +58,7 @@ exports[`<GrantRequestHeader /> matches the latest snapshot 1`] = `
58
58
  <div
59
59
  class="content"
60
60
  >
61
- header
61
+ Structure access request
62
62
  </div>
63
63
  </h2>
64
64
  </div>
@@ -165,7 +165,7 @@ exports[`<GrantRequestsSearchResults /> matches the latest snapshot 1`] = `
165
165
  results
166
166
  </div>
167
167
  <table
168
- class="ui sortable table"
168
+ class="ui selectable sortable table"
169
169
  >
170
170
  <thead
171
171
  class=""
@@ -33,58 +33,6 @@ exports[`<StructureGrantDropdown /> matches the latest snapshot for activeGrant
33
33
  Request grant change
34
34
  </span>
35
35
  </div>
36
- <div
37
- class="item"
38
- role="option"
39
- >
40
- <i
41
- aria-hidden="true"
42
- class="delete icon"
43
- />
44
- <span
45
- class="text"
46
- >
47
- Request grant removal
48
- </span>
49
- </div>
50
- </div>
51
- </div>
52
- </div>
53
- `;
54
-
55
- exports[`<StructureGrantDropdown /> matches the latest snapshot for pendingRemovalGrant state 1`] = `
56
- <div>
57
- <div
58
- aria-expanded="false"
59
- class="ui floating dropdown"
60
- role="listbox"
61
- tabindex="0"
62
- >
63
- <button
64
- class="ui red icon button button basic icon group-actions"
65
- >
66
- <i
67
- aria-hidden="true"
68
- class="shield icon"
69
- />
70
- </button>
71
- <div
72
- class="menu transition left"
73
- >
74
- <div
75
- class="item"
76
- role="option"
77
- >
78
- <i
79
- aria-hidden="true"
80
- class="delete icon"
81
- />
82
- <span
83
- class="text"
84
- >
85
- Cancel grant removal
86
- </span>
87
- </div>
88
36
  </div>
89
37
  </div>
90
38
  </div>
@@ -73,20 +73,6 @@ exports[`<StructureGrantListButton /> matches the latest snapshot with grant 1`]
73
73
  Request grant change
74
74
  </span>
75
75
  </div>
76
- <div
77
- class="item"
78
- role="option"
79
- >
80
- <i
81
- aria-hidden="true"
82
- class="delete icon"
83
- />
84
- <span
85
- class="text"
86
- >
87
- Request grant removal
88
- </span>
89
- </div>
90
76
  </div>
91
77
  </div>
92
78
  </div>
@@ -85,20 +85,6 @@ exports[`<StructureGrantSummaryButton /> matches snapshot for active grant and i
85
85
  Request grant change
86
86
  </span>
87
87
  </div>
88
- <div
89
- class="item"
90
- role="option"
91
- >
92
- <i
93
- aria-hidden="true"
94
- class="delete icon"
95
- />
96
- <span
97
- class="text"
98
- >
99
- Request grant removal
100
- </span>
101
- </div>
102
88
  </div>
103
89
  </div>
104
90
  </div>
@@ -46,6 +46,7 @@ exports[`<StructureGrants /> matches the latest snapshot 1`] = `
46
46
  >
47
47
  <tr
48
48
  class=""
49
+ style="cursor: pointer;"
49
50
  >
50
51
  <td
51
52
  class=""
@@ -82,17 +83,15 @@ exports[`<StructureGrants /> matches the latest snapshot 1`] = `
82
83
  class=""
83
84
  >
84
85
  <button
85
- class="ui red mini icon button"
86
+ class="ui red button button icon group-actions"
86
87
  >
87
- <i
88
- aria-hidden="true"
89
- class="delete icon"
90
- />
88
+ Remove
91
89
  </button>
92
90
  </td>
93
91
  </tr>
94
92
  <tr
95
93
  class=""
94
+ style="cursor: pointer;"
96
95
  >
97
96
  <td
98
97
  class=""
@@ -1,9 +1,18 @@
1
1
  import useSWRMutations from "swr/mutation";
2
2
  import { apiJsonPost } from "@truedat/core/services/api";
3
- import { API_GRANT_REQUEST_BULK_APPROVAL } from "../api";
3
+ import {
4
+ API_GRANT_REQUEST_BULK_APPROVAL,
5
+ API_GRANT_REQUEST_GROUP,
6
+ } from "../api";
4
7
 
5
8
  export const useGrantRequestBulkApproval = () => {
6
9
  return useSWRMutations(API_GRANT_REQUEST_BULK_APPROVAL, (url, { arg }) =>
7
10
  apiJsonPost(url, arg)
8
11
  );
9
12
  };
13
+
14
+ export const useGrantRequestGroup = () => {
15
+ return useSWRMutations(API_GRANT_REQUEST_GROUP, (url, { arg }) =>
16
+ apiJsonPost(url, arg)
17
+ );
18
+ };
@@ -41,15 +41,15 @@ export default {
41
41
  "filters.with_profiling.raw": "Profile",
42
42
  "filters.with_profiling.raw.false": "Without profile",
43
43
  "filters.with_profiling.raw.true": "With profile",
44
- "grant.actions.cancel_removal.confirmation.content":
44
+ "grant.actions.markPendingRemoval.button": "Remove",
45
+ "grant.actions.markPendingRemoval.confirmation.content":
46
+ "Requesting this grant to be revoked. Are you sure?",
47
+ "grant.actions.markPendingRemoval.confirmation.header": "Request grant removal",
48
+ "grant.actions.unmarkPendingRemoval.confirmation.content":
45
49
  "Cancelling grant removal. Are you sure?",
46
- "grant.actions.cancel_removal.confirmation.header": "Cancel grant removal",
47
- "grant.actions.request_removal.button": "Remove",
48
- "grant.actions.cancel_removal.button": "Reactivate",
49
- "grant.actions.request_removal.confirmation.content":
50
- "Requesting this grant to be revoked. Are you sure?",
51
- "grant.actions.request_removal.confirmation.header": "Request grant removal",
52
- "grant.actions.view_request.confirmation.header": "View detail",
50
+ "grant.actions.unmarkPendingRemoval.button": "Reactivate",
51
+ "grant.actions.unmarkPendingRemoval.confirmation.header": "Cancel grant removal",
52
+ "grant.actions.viewRequest.confirmation.header": "View detail",
53
53
  "grant.cell.direct_access": "Direct access",
54
54
  "grant.cell.end_date.null": "No expiration set",
55
55
  "grant.cell.end_date.pending_removal": "Grant pending removal",
@@ -129,6 +129,7 @@ export default {
129
129
  "grantRequest.header.user": "User",
130
130
  "grantRequest.header.createdBy": "Created by",
131
131
  "grantRequest.header.create": "Create grant request",
132
+ "grantRequest.header.type": "Request type",
132
133
  "grantRequest.header.update": "Request grant change",
133
134
  "grantRequest.summary.emptyApprovals": "No approves",
134
135
  "grantRequest.summary.pendingRoles": "Pending roles",
@@ -270,6 +271,20 @@ export default {
270
271
  "referenceDatasets.header": "Reference Data",
271
272
  "referenceDatasets.search.placeholder": "Search datasets...",
272
273
  "referenceDatasets.subheader": "Manage reference datasets",
274
+ "request.grantAccess": "Structure access request",
275
+ "request.grantRemoval": "Grant removal request",
276
+ "request.grantRemoval.action.start.description": "Request grant removal",
277
+ "request.grantRemoval.state.approvedAndGrantPendingRemoval.description":
278
+ "Pending grant removal",
279
+ "request.grantRemoval.state.pending.description": "Grant removal requested",
280
+ "request.grantRemoval.state.rejected.description":
281
+ "Grant removal request has been rejected",
282
+ "request.grantRemoval.state.processing.description":
283
+ "Grant removal being attended by operators",
284
+ "request.grantRemoval.state.workflowBypassedActive.description":
285
+ "Directly set to active, grant request bypassed",
286
+ "request.grantRemoval.state.workflowBypassedPendingRemoval.description":
287
+ "Directly removed, grant request bypassed.",
273
288
  "saveUserSearchFilters.error.name.duplicated": "Duplicated name",
274
289
  "structure._actions": " ",
275
290
  "structure.actions.delete.confirmation.content":
@@ -43,17 +43,17 @@ export default {
43
43
  "filters.with_profiling.raw": "Perfilado",
44
44
  "filters.with_profiling.raw.false": "Sin perfilado",
45
45
  "filters.with_profiling.raw.true": "Contiene perfilado",
46
- "grant.actions.cancel_removal.confirmation.content":
47
- "Cancelar solicitud de eliminar acceso. ¿Estás seguro?",
48
- "grant.actions.cancel_removal.confirmation.header":
49
- "Cancelar retirada de acceso",
50
- "grant.actions.request_removal.button": "Eliminar",
51
- "grant.actions.cancel_removal.button": "Reactivar",
52
- "grant.actions.request_removal.confirmation.content":
46
+ "grant.actions.markPendingRemoval.button": "Eliminar",
47
+ "grant.actions.markPendingRemoval.confirmation.content":
53
48
  "El acceso será eliminado. ¿Estás seguro?",
54
- "grant.actions.request_removal.confirmation.header":
49
+ "grant.actions.markPendingRemoval.confirmation.header":
55
50
  "Solicitar eliminación de acceso",
56
- "grant.actions.view_request.confirmation.header": "Ver detalle",
51
+ "grant.actions.unmarkPendingRemoval.button": "Reactivar",
52
+ "grant.actions.unmarkPendingRemoval.confirmation.content":
53
+ "Cancelar solicitud de eliminar acceso. ¿Estás seguro?",
54
+ "grant.actions.unmarkPendingRemoval.confirmation.header":
55
+ "Cancelar retirada de acceso",
56
+ "grant.actions.viewRequest.confirmation.header": "Ver detalle",
57
57
  "grant.cell.direct_access": "Acceso Directo",
58
58
  "grant.cell.end_date.null": "Sin fecha de expiración",
59
59
  "grant.cell.end_date.pending_removal": "Solicitada expiración del acceso",
@@ -134,6 +134,7 @@ export default {
134
134
  "grantRequest.header.user": "Usuario",
135
135
  "grantRequest.header.createdBy": "Creado por",
136
136
  "grantRequest.header.create": "Crear petición de acceso",
137
+ "grantRequest.header.type": "Tipo de petición",
137
138
  "grantRequest.header.update": "Petición de modificación de acceso",
138
139
  "grantRequest.summary.emptyApprovals": "Sin aprobaciones",
139
140
  "grantRequest.summary.pendingRoles": "Roles pendientes",
@@ -278,6 +279,22 @@ export default {
278
279
  "referenceDatasets.header": "Datos de referencia",
279
280
  "referenceDatasets.search.placeholder": "Buscar datasets...",
280
281
  "referenceDatasets.subheader": "Gestionar conjuntos de datos de referencia",
282
+ "request.grantAccess": "Petición de acceso a estructura",
283
+ "request.grantRemoval": "Petición de borrado de acceso a estructura",
284
+ "request.grantRemoval.action.start.description":
285
+ "Solicitar borrado de acceso",
286
+ "request.grantRemoval.state.approvedAndGrantPendingRemoval.description":
287
+ "Acceso pendiente de eliminación",
288
+ "request.grantRemoval.state.pending.description":
289
+ "Borrado de acceso solicitado",
290
+ "request.grantRemoval.state.rejected.description":
291
+ "Petición de borrado de acceso rechazada",
292
+ "request.grantRemoval.state.processing.description":
293
+ "Borrado de acceso siendo atendido por operadores",
294
+ "request.grantRemoval.state.workflowBypassedActive.description":
295
+ "Activado directamente, petición ignorada",
296
+ "request.grantRemoval.state.workflowBypassedPendingRemoval.description":
297
+ "Borrado directamente, petición ignorada",
281
298
  "saveUserSearchFilters.error.name.duplicated": "Nombre duplicado",
282
299
  "structure._actions": " ",
283
300
  "structure.actions.delete.confirmation.content":
@@ -39,6 +39,7 @@ const structureVersionFields = _.pick([
39
39
  "source",
40
40
  "system",
41
41
  "type",
42
+ "_actions",
42
43
  ]);
43
44
 
44
45
  const structure = (state = initialState, { type, payload }) => {
@@ -35,7 +35,7 @@ describe("sagas: createGrantRequestStatusSaga", () => {
35
35
  const status = "cancelled";
36
36
  const structureId = 3;
37
37
  const payload = {
38
- grantRequestId: 8,
38
+ grantRequest: { id: 8, request_type: "ACCESS" },
39
39
  status,
40
40
  structureId,
41
41
  };
@@ -10,17 +10,33 @@ import { API_GRANT_REQUEST_STATUS } from "../api";
10
10
 
11
11
  export function* createGrantRequestStatusSaga({ payload }) {
12
12
  try {
13
- const { grantRequestId, status, structureId, previousStructureQuery } =
14
- payload;
15
- const url = compile(API_GRANT_REQUEST_STATUS)({ id: grantRequestId });
13
+ const {
14
+ grantRequest,
15
+ setLatestGrantRequest,
16
+ status,
17
+ structureId,
18
+ previousStructureQuery,
19
+ } = payload;
20
+ const url = compile(API_GRANT_REQUEST_STATUS)({ id: grantRequest.id });
16
21
  yield put(createGrantRequestStatus.request({ status }));
17
22
  const { data } = yield call(apiJsonPost, url, { status }, JSON_OPTS);
23
+
18
24
  yield put(createGrantRequestStatus.success(data));
19
- yield put(
20
- previousStructureQuery
21
- ? fetchStructures.trigger(previousStructureQuery)
22
- : fetchStructure.trigger({ id: structureId })
23
- );
25
+
26
+ if (previousStructureQuery || structureId) {
27
+ yield put(
28
+ previousStructureQuery
29
+ ? fetchStructures.trigger(previousStructureQuery)
30
+ : structureId && fetchStructure.trigger({ id: structureId })
31
+ );
32
+ } else if (grantRequest.requestType === "GRANT_REMOVAL") {
33
+ setLatestGrantRequest({
34
+ ...{
35
+ ...grantRequest,
36
+ status: { ...grantRequest.status, status: data.data.status },
37
+ },
38
+ });
39
+ }
24
40
  } catch (error) {
25
41
  if (error.response) {
26
42
  const { status, data } = error.response;
@@ -2,6 +2,8 @@ import _ from "lodash/fp";
2
2
  import React from "react";
3
3
  import { Header, Icon, Popup } from "semantic-ui-react";
4
4
  import { createSelector } from "reselect";
5
+ import { linkTo } from "@truedat/core/routes";
6
+ import { Link } from "react-router-dom";
5
7
  import { useIntl } from "react-intl";
6
8
  import PropTypes from "prop-types";
7
9
  import Moment from "react-moment";
@@ -19,12 +21,13 @@ UserDecorator.propTypes = {
19
21
  user: PropTypes.object,
20
22
  };
21
23
 
22
- export const PathDecorator = ({ data_structure }) => {
24
+ export const PathDecorator = ({ data_structure, data_structure_version }) => {
23
25
  const path = _.flow(
24
- _.prop("path"),
26
+ ({ data_structure, data_structure_version }) =>
27
+ data_structure?.path || data_structure_version?.path,
25
28
  _.map("name"),
26
29
  _.join(" › ")
27
- )(data_structure);
30
+ )({ data_structure, data_structure_version });
28
31
  return <>{path}</>;
29
32
  };
30
33
 
@@ -32,7 +35,13 @@ PathDecorator.propTypes = {
32
35
  data_structure: PropTypes.object,
33
36
  };
34
37
 
35
- export const StructureDecorator = ({ data_structure, modificationGrant }) => {
38
+ export const StructureDecorator = ({
39
+ request_type,
40
+ data_structure,
41
+ data_structure_version,
42
+ modificationGrant,
43
+ grant,
44
+ }) => {
36
45
  const { formatMessage } = useIntl();
37
46
  return (
38
47
  <>
@@ -41,15 +50,27 @@ export const StructureDecorator = ({ data_structure, modificationGrant }) => {
41
50
  content={formatMessage({ id: "grantRequest.isModification" })}
42
51
  trigger={<Icon name="edit" />}
43
52
  />
53
+ ) : request_type === "grant_removal" ? (
54
+ <Popup
55
+ content={formatMessage({ id: "request.grantRemoval" })}
56
+ trigger={
57
+ <Link to={linkTo.GRANT({ id: grant.id })}>
58
+ <Icon name="key" />
59
+ </Link>
60
+ }
61
+ />
44
62
  ) : null}
45
- {data_structure.name}
63
+ {data_structure?.name || data_structure_version?.name}
46
64
  </>
47
65
  );
48
66
  };
49
67
 
50
68
  StructureDecorator.propTypes = {
69
+ request_type: PropTypes.string,
51
70
  data_structure: PropTypes.object,
71
+ data_structure_version: PropTypes.object,
52
72
  modificationGrant: PropTypes.object,
73
+ grant: PropTypes.object,
53
74
  };
54
75
 
55
76
  const DateDecorator = ({ date }) => {
@@ -85,10 +106,14 @@ export const defaultGrantRequestsTableColumns = [
85
106
  {
86
107
  name: "data_structure",
87
108
  fieldSelector: (grantRequest) => ({
109
+ request_type: grantRequest?.request_type,
88
110
  data_structure: grantRequest?._embedded?.data_structure,
111
+ data_structure_version:
112
+ grantRequest?._embedded?.grant?.data_structure_version,
89
113
  modificationGrant: _.prop("_embedded.group._embedded.modification_grant")(
90
114
  grantRequest
91
115
  ),
116
+ grant: grantRequest?._embedded?.grant,
92
117
  }),
93
118
  fieldDecorator: StructureDecorator,
94
119
  },
@@ -96,6 +121,8 @@ export const defaultGrantRequestsTableColumns = [
96
121
  name: "path",
97
122
  fieldSelector: (grantRequest) => ({
98
123
  data_structure: grantRequest?._embedded?.data_structure,
124
+ data_structure_version:
125
+ grantRequest?._embedded?.grant?.data_structure_version,
99
126
  }),
100
127
  fieldDecorator: PathDecorator,
101
128
  },
@@ -2,6 +2,8 @@ import _ from "lodash/fp";
2
2
  import React from "react";
3
3
  import { Header, Icon, Popup } from "semantic-ui-react";
4
4
  import { createSelector } from "reselect";
5
+ import { linkTo } from "@truedat/core/routes";
6
+ import { Link } from "react-router-dom";
5
7
  import { useIntl } from "react-intl";
6
8
  import PropTypes from "prop-types";
7
9
  import Moment from "react-moment";
@@ -26,29 +28,34 @@ export const PathDecorator = ({ data_structure_version }) => {
26
28
  };
27
29
 
28
30
  PathDecorator.propTypes = {
29
- data_structure: PropTypes.object,
31
+ data_structure_version: PropTypes.object,
30
32
  };
31
33
 
32
- export const StructureDecorator = ({ name, modificationGrant }) => {
34
+ export const StructureDecorator = (grantRequest) => {
33
35
  const { formatMessage } = useIntl();
34
36
  return (
35
37
  <>
36
- {modificationGrant ? (
38
+ {grantRequest.modification_grant_id ? (
37
39
  <Popup
38
40
  content={formatMessage({ id: "grantRequest.modification_grant_id" })}
39
41
  trigger={<Icon name="edit" />}
40
42
  />
43
+ ) : grantRequest.request_type === "grant_removal" ? (
44
+ <Popup
45
+ content={formatMessage({ id: "request.grantRemoval" })}
46
+ trigger={
47
+ <Link to={linkTo.GRANT({ id: grantRequest.grant.id })}>
48
+ <Icon name="key" />
49
+ </Link>
50
+ }
51
+ />
41
52
  ) : null}
42
- {name}
53
+ {grantRequest?.data_structure_version?.name ||
54
+ grantRequest?.grant?.data_structure_version?.name}
43
55
  </>
44
56
  );
45
57
  };
46
58
 
47
- StructureDecorator.propTypes = {
48
- name: PropTypes.string,
49
- modificationGrant: PropTypes.string,
50
- };
51
-
52
59
  const DateDecorator = ({ date }) => {
53
60
  const { locale } = useIntl();
54
61
  return date ? (
@@ -83,16 +90,15 @@ export const defaultGrantRequestsSearchTableColumns = [
83
90
  {
84
91
  name: "data_structure",
85
92
  sort: { name: "data_structure_version.name.raw" },
86
- fieldSelector: (grantRequest) => ({
87
- name: grantRequest?.data_structure_version?.name,
88
- modificationGrant: _.prop("modification_grant_id")(grantRequest),
89
- }),
93
+ fieldSelector: (grantRequest) => grantRequest,
90
94
  fieldDecorator: StructureDecorator,
91
95
  },
92
96
  {
93
97
  name: "path",
94
98
  fieldSelector: (grantRequest) => ({
95
- data_structure_version: grantRequest?.data_structure_version,
99
+ data_structure_version:
100
+ grantRequest?.data_structure_version ||
101
+ grantRequest?.grant?.data_structure_version,
96
102
  }),
97
103
  fieldDecorator: PathDecorator,
98
104
  },