@truedat/dd 5.18.3 → 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 (50) 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/StructureNoteActions.js +1 -0
  18. package/src/components/StructureNoteSuggestions.js +179 -0
  19. package/src/components/StructureNotesEdit.js +19 -2
  20. package/src/components/__tests__/Grant.spec.js +11 -7
  21. package/src/components/__tests__/GrantRemoval.spec.js +19 -54
  22. package/src/components/__tests__/GrantRemovalDirectButton.spec.js +66 -0
  23. package/src/components/__tests__/GrantRemovalWorkflow.spec.js +157 -0
  24. package/src/components/__tests__/GrantRequest.spec.js +2 -0
  25. package/src/components/__tests__/GrantRequestHeader.spec.js +2 -5
  26. package/src/components/__tests__/StructureGrantDropdown.spec.js +1 -16
  27. package/src/components/__tests__/StructureGrantSummaryButton.spec.js +3 -2
  28. package/src/components/__tests__/StructureGrants.spec.js +5 -1
  29. package/src/components/__tests__/StructureNoteSuggestions.spec.js +151 -0
  30. package/src/components/__tests__/StructureNotesEdit.spec.js +34 -0
  31. package/src/components/__tests__/__snapshots__/Grant.spec.js.snap +5 -4
  32. package/src/components/__tests__/__snapshots__/GrantRequest.spec.js.snap +3 -3
  33. package/src/components/__tests__/__snapshots__/GrantRequestHeader.spec.js.snap +4 -4
  34. package/src/components/__tests__/__snapshots__/GrantRequestsSearchResults.spec.js.snap +1 -1
  35. package/src/components/__tests__/__snapshots__/StructureGrantDropdown.spec.js.snap +0 -52
  36. package/src/components/__tests__/__snapshots__/StructureGrantListButton.spec.js.snap +0 -14
  37. package/src/components/__tests__/__snapshots__/StructureGrantSummaryButton.spec.js.snap +0 -14
  38. package/src/components/__tests__/__snapshots__/StructureGrants.spec.js.snap +4 -5
  39. package/src/components/__tests__/__snapshots__/StructureNoteSuggestions.spec.js.snap +316 -0
  40. package/src/components/__tests__/__snapshots__/StructureNotesEdit.spec.js.snap +49 -0
  41. package/src/hooks/useGrantRequest.js +10 -1
  42. package/src/messages/en.js +23 -8
  43. package/src/messages/es.js +26 -9
  44. package/src/reducers/structure.js +1 -0
  45. package/src/sagas/__tests__/createGrantRequestStatus.spec.js +1 -1
  46. package/src/sagas/createGrantRequestStatus.js +24 -8
  47. package/src/selectors/getGrantRequestsColumns.js +32 -5
  48. package/src/selectors/getGrantRequestsSearchColumns.js +20 -14
  49. package/src/selectors/utils/decorators.js +68 -0
  50. package/src/components/__tests__/__snapshots__/GrantRemoval.spec.js.snap +0 -9
@@ -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=""
@@ -0,0 +1,316 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`<StructureNoteSuggestions /> component lifecycle 1`] = `
4
+ <div>
5
+ <div
6
+ class="ui segment"
7
+ >
8
+ <div
9
+ class="ui container"
10
+ style="display: flex; justify-content: space-between;"
11
+ >
12
+ <h4>
13
+ <i
14
+ aria-hidden="true"
15
+ class="lightbulb outline icon"
16
+ />
17
+ header
18
+ </h4>
19
+ <div
20
+ class="ui hidden divider"
21
+ />
22
+ </div>
23
+ <div
24
+ class="ui container"
25
+ >
26
+ <h5 />
27
+ <div
28
+ class="ui list"
29
+ role="list"
30
+ >
31
+ <div
32
+ class="item"
33
+ role="listitem"
34
+ style="display: flex; align-items: center; gap: 12px;"
35
+ >
36
+ <div
37
+ class="ui checked fitted checkbox"
38
+ >
39
+ <input
40
+ checked=""
41
+ class="hidden"
42
+ id="editable_field"
43
+ readonly=""
44
+ tabindex="0"
45
+ type="checkbox"
46
+ value=""
47
+ />
48
+ <label
49
+ for="editable_field"
50
+ />
51
+ </div>
52
+ <label
53
+ disabled=""
54
+ for="editable_field"
55
+ style="cursor: pointer;"
56
+ >
57
+ <div
58
+ class="header"
59
+ >
60
+ EditableField
61
+ </div>
62
+ <div
63
+ class="description"
64
+ >
65
+ editable_field_value
66
+ </div>
67
+ </label>
68
+ </div>
69
+ </div>
70
+ <div
71
+ class="ui hidden divider"
72
+ />
73
+ </div>
74
+ <div
75
+ class="ui container"
76
+ >
77
+ <h5>
78
+ Group2
79
+ </h5>
80
+ <div
81
+ class="ui list"
82
+ role="list"
83
+ >
84
+ <div
85
+ class="item"
86
+ role="listitem"
87
+ style="display: flex; align-items: center; gap: 12px;"
88
+ >
89
+ <div
90
+ class="ui disabled fitted checkbox"
91
+ >
92
+ <input
93
+ class="hidden"
94
+ disabled=""
95
+ id="non_editable_field"
96
+ readonly=""
97
+ tabindex="-1"
98
+ type="checkbox"
99
+ value=""
100
+ />
101
+ <label
102
+ for="non_editable_field"
103
+ />
104
+ </div>
105
+ <label
106
+ disabled=""
107
+ for="non_editable_field"
108
+ style="cursor: pointer;"
109
+ >
110
+ <div
111
+ class="header"
112
+ >
113
+ NonEditableField
114
+ </div>
115
+ <div
116
+ class="description"
117
+ >
118
+ non_editable_field_value
119
+ </div>
120
+ </label>
121
+ </div>
122
+ <div
123
+ class="item"
124
+ role="listitem"
125
+ style="display: flex; align-items: center; gap: 12px;"
126
+ >
127
+ <div
128
+ class="ui checked fitted checkbox"
129
+ >
130
+ <input
131
+ checked=""
132
+ class="hidden"
133
+ id="unselect_field"
134
+ readonly=""
135
+ tabindex="0"
136
+ type="checkbox"
137
+ value=""
138
+ />
139
+ <label
140
+ for="unselect_field"
141
+ />
142
+ </div>
143
+ <label
144
+ disabled=""
145
+ for="unselect_field"
146
+ style="cursor: pointer;"
147
+ >
148
+ <div
149
+ class="header"
150
+ >
151
+ UnselectedField
152
+ </div>
153
+ <div
154
+ class="description"
155
+ >
156
+ unselect_field_value
157
+ </div>
158
+ </label>
159
+ </div>
160
+ </div>
161
+ <div
162
+ class="ui hidden divider"
163
+ />
164
+ </div>
165
+ <div
166
+ class="ui right aligned container"
167
+ >
168
+ <button
169
+ class="ui primary button"
170
+ >
171
+ actions.apply_ai_suggestion
172
+ </button>
173
+ </div>
174
+ </div>
175
+ </div>
176
+ `;
177
+
178
+ exports[`<StructureNoteSuggestions /> component lifecycle 2`] = `
179
+ <div>
180
+ <div
181
+ class="ui segment"
182
+ >
183
+ <div
184
+ class="ui container"
185
+ style="display: flex; justify-content: space-between;"
186
+ >
187
+ <h4>
188
+ <i
189
+ aria-hidden="true"
190
+ class="lightbulb icon"
191
+ />
192
+ header
193
+ </h4>
194
+ <div
195
+ class="ui hidden divider"
196
+ />
197
+ <button
198
+ class="ui button"
199
+ >
200
+ actions.ai_suggestion
201
+ </button>
202
+ </div>
203
+ </div>
204
+ </div>
205
+ `;
206
+
207
+ exports[`<StructureNoteSuggestions /> matches the latest snapshot 1`] = `
208
+ <div>
209
+ <div
210
+ class="ui segment"
211
+ >
212
+ <div
213
+ class="ui container"
214
+ style="display: flex; justify-content: space-between;"
215
+ >
216
+ <h4>
217
+ <i
218
+ aria-hidden="true"
219
+ class="lightbulb icon"
220
+ />
221
+ header
222
+ </h4>
223
+ <div
224
+ class="ui hidden divider"
225
+ />
226
+ <button
227
+ class="ui button"
228
+ >
229
+ actions.ai_suggestion
230
+ </button>
231
+ </div>
232
+ </div>
233
+ </div>
234
+ `;
235
+
236
+ exports[`<StructureNoteSuggestions /> renders error with message 1`] = `
237
+ <div>
238
+ <div
239
+ class="ui segment"
240
+ >
241
+ <div
242
+ class="ui container"
243
+ style="display: flex; justify-content: space-between;"
244
+ >
245
+ <h4>
246
+ <i
247
+ aria-hidden="true"
248
+ class="lightbulb icon"
249
+ />
250
+ header
251
+ </h4>
252
+ <div
253
+ class="ui hidden divider"
254
+ />
255
+ <button
256
+ class="ui button"
257
+ >
258
+ actions.ai_suggestion
259
+ </button>
260
+ </div>
261
+ <div
262
+ class="ui negative message"
263
+ >
264
+ <div
265
+ class="header"
266
+ >
267
+ error
268
+ </div>
269
+ <p>
270
+ ERROR MESSAGE
271
+ </p>
272
+ </div>
273
+ </div>
274
+ </div>
275
+ `;
276
+
277
+ exports[`<StructureNoteSuggestions /> renders error with message 2`] = `
278
+ <div>
279
+ <div
280
+ class="ui segment"
281
+ >
282
+ <div
283
+ class="ui container"
284
+ style="display: flex; justify-content: space-between;"
285
+ >
286
+ <h4>
287
+ <i
288
+ aria-hidden="true"
289
+ class="lightbulb icon"
290
+ />
291
+ header
292
+ </h4>
293
+ <div
294
+ class="ui hidden divider"
295
+ />
296
+ <button
297
+ class="ui button"
298
+ >
299
+ actions.ai_suggestion
300
+ </button>
301
+ </div>
302
+ <div
303
+ class="ui negative message"
304
+ >
305
+ <div
306
+ class="header"
307
+ >
308
+ error
309
+ </div>
310
+ <p>
311
+ ERROR TEXT
312
+ </p>
313
+ </div>
314
+ </div>
315
+ </div>
316
+ `;
@@ -25,3 +25,52 @@ exports[`<StructureNotesEdit /> matches the latest snapshot 1`] = `
25
25
  </div>
26
26
  </div>
27
27
  `;
28
+
29
+ exports[`<StructureNotesEdit /> matches the latest snapshot with ai suggestion action 1`] = `
30
+ <div>
31
+ <div
32
+ class="ui bottom attached segment"
33
+ >
34
+ <div
35
+ class="ui segment"
36
+ >
37
+ <div
38
+ class="ui container"
39
+ style="display: flex; justify-content: space-between;"
40
+ >
41
+ <h4>
42
+ <i
43
+ aria-hidden="true"
44
+ class="lightbulb icon"
45
+ />
46
+ header
47
+ </h4>
48
+ <div
49
+ class="ui hidden divider"
50
+ />
51
+ <button
52
+ class="ui button"
53
+ >
54
+ ai_suggestion
55
+ </button>
56
+ </div>
57
+ </div>
58
+ <form
59
+ class="ui form"
60
+ >
61
+ <button
62
+ class="ui primary button"
63
+ >
64
+ save
65
+ </button>
66
+ <a
67
+ class="ui secondary button"
68
+ href="/"
69
+ role="button"
70
+ >
71
+ cancel
72
+ </a>
73
+ </form>
74
+ </div>
75
+ </div>
76
+ `;
@@ -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
  },