@truedat/dd 4.49.9 → 4.50.3

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 (38) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/package.json +5 -5
  3. package/src/api/queries.js +16 -0
  4. package/src/api.js +2 -0
  5. package/src/components/GrantChangeRequest.js +32 -0
  6. package/src/components/GrantRequestCancel.js +47 -0
  7. package/src/components/GrantRequestHeader.js +9 -1
  8. package/src/components/MyGrantRequests.js +1 -0
  9. package/src/components/StructureGrantButton.js +24 -44
  10. package/src/components/StructureGrantCart.js +2 -2
  11. package/src/components/StructureGrantCartCheckout.js +20 -15
  12. package/src/components/StructureGrantCartTemplate.js +15 -61
  13. package/src/components/StructureGrantDropdown.js +201 -0
  14. package/src/components/StructureGrantRequestButton.js +15 -14
  15. package/src/components/StructureGrants.js +1 -1
  16. package/src/components/StructureSummary.js +13 -6
  17. package/src/components/StructureView.js +7 -8
  18. package/src/components/__tests__/MyGrantRequests.spec.js +5 -0
  19. package/src/components/__tests__/StructureGrantButton.spec.js +107 -34
  20. package/src/components/__tests__/StructureGrantCartTemplate.spec.js +11 -100
  21. package/src/components/__tests__/StructureGrantDropdown.spec.js +148 -0
  22. package/src/components/__tests__/StructureGrantRequestButton.spec.js +9 -10
  23. package/src/components/__tests__/__snapshots__/MyGrantRequests.spec.js.snap +14 -0
  24. package/src/components/__tests__/__snapshots__/StructureGrantButton.spec.js.snap +162 -16
  25. package/src/components/__tests__/__snapshots__/StructureGrantCartTemplate.spec.js.snap +0 -3
  26. package/src/components/__tests__/__snapshots__/StructureGrantDropdown.spec.js.snap +271 -0
  27. package/src/components/__tests__/__snapshots__/StructureGrantRequestButton.spec.js.snap +11 -10
  28. package/src/components/__tests__/__snapshots__/StructureSummary.spec.js.snap +6 -0
  29. package/src/messages/en.js +17 -1
  30. package/src/messages/es.js +17 -3
  31. package/src/reducers/__tests__/grantRequestsCart.spec.js +223 -9
  32. package/src/reducers/grantRequestsCart.js +20 -26
  33. package/src/routines.js +2 -1
  34. package/src/sagas/__tests__/createGrantRequestStatus.spec.js +82 -0
  35. package/src/sagas/createGrantRequestStatus.js +32 -0
  36. package/src/sagas/index.js +3 -0
  37. package/src/sagas/operateGrantRequestCart.js +2 -27
  38. package/src/selectors/getGrantRequestsColumns.js +18 -3
@@ -1,15 +1,16 @@
1
1
  // Jest Snapshot v1, https://goo.gl/fbAQLP
2
2
 
3
- exports[`<StructureGrantRequestButton /> render a button 1`] = `
4
- <a
5
- class="ui orange basic label"
6
- >
7
- <i
8
- aria-hidden="true"
9
- class="shield icon"
10
- />
11
- Request grant
12
- </a>
3
+ exports[`<StructureGrantRequestButton /> matches latest snapshot 1`] = `
4
+ <div>
5
+ <button
6
+ class="ui orange icon button button basic icon group-actions"
7
+ >
8
+ <i
9
+ aria-hidden="true"
10
+ class="shield icon"
11
+ />
12
+ </button>
13
+ </div>
13
14
  `;
14
15
 
15
16
  exports[`<StructureGrantRequestButton /> renders nothing if does not have permissions 1`] = `
@@ -40,6 +40,9 @@ exports[`<StructureSummary /> matches the latest snapshot 1`] = `
40
40
  2019-01-02 03:04
41
41
  </time>
42
42
  </div>
43
+ <div
44
+ class="ui fitted hidden divider"
45
+ />
43
46
  <button
44
47
  class="ui basic icon button button icon group-actions"
45
48
  >
@@ -189,6 +192,9 @@ exports[`<StructureSummary /> matches the latest snapshot with alias 1`] = `
189
192
  2019-01-02 03:04
190
193
  </time>
191
194
  </div>
195
+ <div
196
+ class="ui fitted hidden divider"
197
+ />
192
198
  <button
193
199
  class="ui basic icon button button icon group-actions"
194
200
  >
@@ -45,6 +45,7 @@ export default {
45
45
  "grant.actions.request_removal.confirmation.content":
46
46
  "Requesting this grant to be revoked. Are you sure?",
47
47
  "grant.actions.request_removal.confirmation.header": "Request grant removal",
48
+ "grant.actions.view_request.confirmation.header": "View detail",
48
49
  "grant.cell.direct_access": "Direct access",
49
50
  "grant.cell.end_date.null": "No expiration set",
50
51
  "grant.cell.end_date.pending_removal": "Grant pending removal",
@@ -54,22 +55,30 @@ export default {
54
55
  "grant.header.end_date": "Expires",
55
56
  "grant.header.start_date": "Access granted",
56
57
  "grant.updated_at": "Last changed",
58
+ "grantRequest.actions.cancel.confirmation.content": "Are you sure?",
59
+ "grantRequest.actions.cancel.confirmation.header": "Cancel request",
57
60
  "grantRequest.actions.approve": "Approve",
58
61
  "grantRequest.actions.reject": "Reject",
59
62
  "grantRequest.content.approved": "Approved",
63
+ "grantRequest.content.cancelled": "Cancelled",
60
64
  "grantRequest.content.empty": "Empty",
61
65
  "grantRequest.content.failed": "Failed",
62
66
  "grantRequest.content.pending": "Pending",
63
67
  "grantRequest.content.processed": "Processed",
64
68
  "grantRequest.content.processing": "Processing",
65
69
  "grantRequest.content.rejected": "Rejected",
70
+ "grantRequest.isModification": "Grant modification",
66
71
  "grantRequest.crumb.title": "Request",
72
+ "grantRequest.header": "Grant request",
73
+ "grantRequest.header.modification": "Grant modification request",
67
74
  "grantRequest.header.data_structure": "Data Structure",
68
75
  "grantRequest.header.path": "Path",
69
76
  "grantRequest.header.status": "Status",
70
77
  "grantRequest.header.updated_at": "Updated",
71
78
  "grantRequest.header.user": "User",
72
- "grantRequest.header": "Grant request",
79
+
80
+ "grantRequest.header.create": "Create grant request",
81
+ "grantRequest.header.update": "Request grant change",
73
82
  "grantRequest.summary.emptyApprovals": "No approves",
74
83
  "grantRequest.summary.pendingRoles": "Pending roles",
75
84
  "grantRequestApproval.content.approved": "Approved",
@@ -238,16 +247,23 @@ export default {
238
247
  "structure.field.required": "Required",
239
248
  "structure.fields.empty": "No field information available for this structure",
240
249
  "structure.filter.empty": "Empty",
250
+ "structure.grant.access.attended": "Access being attended by operators",
241
251
  "structure.grant.has_grant": "You have granted access on this structure",
242
252
  "structure.grant.has_grant_pending_removal":
243
253
  "You have granted access pending removal",
244
254
  "structure.grant.request_grant": "Request grant",
255
+ "structure.grant.requested_access": "Requested access",
245
256
  "structure.grant.requested_grant": "Pending request",
257
+ "structure.grant.requested_modification": "Requested modification",
258
+ "structure.grant.request_grant_change": "Request grant change",
259
+ "structure.grant.cancel_grant_request": "Cancel request",
246
260
  "structure.grant.cart": "Requested grants",
247
261
  "structure.grant.cart.checkout": "Checkout",
248
262
  "structure.grant.cart.template": "Request information",
249
263
  "structure.grant.cart.template.placeholder": "Select request type",
250
264
  "structure.grant.cart.filters": "Filters for structure",
265
+ "structure.grant.modification.attended":
266
+ "Modification being attended by operators",
251
267
  "structure.group": "Group",
252
268
  "structure.inserted_at": "Created at",
253
269
  "structure.lineage": "Lineage",
@@ -4,8 +4,7 @@ export default {
4
4
  "alert.deleteReferenceDataset.success.header":
5
5
  "Dataset eliminado correctamente",
6
6
  "alert.export.csv": "Exportar a CSV",
7
- "alert.tagStructure.failed.header":
8
- "Error asociando etiqueta a estructura",
7
+ "alert.tagStructure.failed.header": "Error asociando etiqueta a estructura",
9
8
  "alert.saveUserSearchFilters.failed.header": "Error guardando filtro",
10
9
  "alert.show.more": "Mostrar más",
11
10
  "alert.updateReferenceDataset.success.header":
@@ -50,6 +49,7 @@ export default {
50
49
  "El acceso será eliminado. ¿Estás seguro?",
51
50
  "grant.actions.request_removal.confirmation.header":
52
51
  "Solicitar eliminación de acceso",
52
+ "grant.actions.view_request.confirmation.header": "Ver detalle",
53
53
  "grant.cell.direct_access": "Acceso Directo",
54
54
  "grant.cell.end_date.null": "Sin fecha de expiración",
55
55
  "grant.cell.end_date.pending_removal": "Solicitada expiración del acceso",
@@ -60,21 +60,28 @@ export default {
60
60
  "grant.header.user": "Cuenta",
61
61
  "grant.updated_at": "Actualizada",
62
62
  "grantRequest.actions.approve": "Aprobar",
63
+ "grantRequest.actions.cancel.confirmation.content": "¿Estás seguro?",
64
+ "grantRequest.actions.cancel.confirmation.header": "Cancelar solicitud",
63
65
  "grantRequest.actions.reject": "Rechazar",
64
66
  "grantRequest.content.approved": "Aprobada",
67
+ "grantRequest.content.cancelled": "Cancelada",
65
68
  "grantRequest.content.empty": "Vacío",
66
69
  "grantRequest.content.failed": "Error",
67
70
  "grantRequest.content.pending": "Pendiente",
68
71
  "grantRequest.content.processed": "Procesada",
69
72
  "grantRequest.content.processing": "Procesando",
70
73
  "grantRequest.content.rejected": "Rechazada",
74
+ "grantRequest.isModification": "Modificación de acceso",
71
75
  "grantRequest.crumb.title": "Petición",
76
+ "grantRequest.header": "Petición de acceso",
77
+ "grantRequest.header.modification": "Petición de modificación de acceso",
72
78
  "grantRequest.header.data_structure": "Estructura",
73
79
  "grantRequest.header.path": "Ruta",
74
80
  "grantRequest.header.status": "Estado",
75
81
  "grantRequest.header.updated_at": "Actualizado",
76
82
  "grantRequest.header.user": "Usuario",
77
- "grantRequest.header": "Petición de acceso",
83
+ "grantRequest.header.create": "Crear petición de acceso",
84
+ "grantRequest.header.update": "Petición de modificación de acceso",
78
85
  "grantRequest.summary.emptyApprovals": "Sin aprobaciones",
79
86
  "grantRequest.summary.pendingRoles": "Roles pendientes",
80
87
  "grantRequestApproval.content.approved": "Aprobada",
@@ -247,16 +254,23 @@ export default {
247
254
  "structure.fields.empty":
248
255
  "No se dispone de información sobre los campos de esta estructura",
249
256
  "structure.filter.empty": "Vacío",
257
+ "structure.grant.access.attended": "Acceso siendo atendido por operadores",
250
258
  "structure.grant.has_grant": "Tienes acceso a la estructura",
251
259
  "structure.grant.has_grant_pending_removal":
252
260
  "Tienes acceso pendiente de eliminarse",
253
261
  "structure.grant.request_grant": "Solicitar acceso",
262
+ "structure.grant.requested_access": "Acceso solicitado",
254
263
  "structure.grant.requested_grant": "Solicitud pendiente",
264
+ "structure.grant.requested_modification": "Modificación solicitada",
265
+ "structure.grant.request_grant_change": "Solicitar modificación de acceso",
266
+ "structure.grant.cancel_grant_request": "Cancelar solicitud",
255
267
  "structure.grant.cart": "Accesos a solicitar",
256
268
  "structure.grant.cart.checkout": "Checkout",
257
269
  "structure.grant.cart.template": "Información de solicitud",
258
270
  "structure.grant.cart.template.placeholder": "Seleccione tipo de solicitud",
259
271
  "structure.grant.cart.filters": "Filtros para la estructura",
272
+ "structure.grant.modification.attended":
273
+ "Modificación siendo atendida por operadores",
260
274
  "structure.group": "Grupo",
261
275
  "structure.inserted_at": "Importada",
262
276
  "structure.lineage": "Trazabilidad",
@@ -1,18 +1,15 @@
1
1
  import {
2
2
  addGrantRequestToCart,
3
3
  removeGrantRequestFromCart,
4
+ selectGrantRequestTemplate,
5
+ setGrantChangeRequestCart,
6
+ updateGrantRequestFilter,
7
+ updateGrantRequestTemplateContent,
8
+ checkoutGrantRequest,
4
9
  } from "../../routines";
5
- import { grantRequestsCart } from "..";
10
+ import { initialState, grantRequestsCart } from "../grantRequestsCart";
6
11
 
7
12
  describe("reducers: structureVersion", () => {
8
- const initialState = {
9
- structures: [],
10
- template: null,
11
- templateContent: {},
12
- templates: [],
13
- templatesLoading: false,
14
- };
15
-
16
13
  it("should provide the initial state", () => {
17
14
  expect(grantRequestsCart(undefined, {})).toEqual(initialState);
18
15
  });
@@ -31,6 +28,20 @@ describe("reducers: structureVersion", () => {
31
28
  ).toEqual(expectedState);
32
29
  });
33
30
 
31
+ it("on addGrantRequestToCart.TRIGGER adds filters property for class=field structure", () => {
32
+ const structure = { id: 4, class: "field" };
33
+ const expectedState = {
34
+ ...initialState,
35
+ structures: [{ ...structure, filters: [] }],
36
+ };
37
+ expect(
38
+ grantRequestsCart(initialState, {
39
+ type: addGrantRequestToCart.TRIGGER,
40
+ payload: structure,
41
+ })
42
+ ).toEqual(expectedState);
43
+ });
44
+
34
45
  it("should avoid duplicates when handling the addGrantRequestToCart.TRIGGER", () => {
35
46
  const structures = [{ id: 1 }, { id: 2 }, { id: 3 }];
36
47
  const structure = { id: 3 };
@@ -43,6 +54,25 @@ describe("reducers: structureVersion", () => {
43
54
  ).toEqual(expectedState);
44
55
  });
45
56
 
57
+ it("on addGrantRequestToCart.TRIGGER should remove modificationGrant and structure if exists", () => {
58
+ const stateWithModificationGrant = {
59
+ ...initialState,
60
+ modificationGrant: { id: 2 },
61
+ structures: [{ id: 1 }],
62
+ };
63
+ const structure = { id: 4 };
64
+ const expectedState = {
65
+ ...initialState,
66
+ structures: [structure],
67
+ };
68
+ expect(
69
+ grantRequestsCart(stateWithModificationGrant, {
70
+ type: addGrantRequestToCart.TRIGGER,
71
+ payload: structure,
72
+ })
73
+ ).toEqual(expectedState);
74
+ });
75
+
46
76
  it("should respect added order", () => {
47
77
  const structure_1 = { id: 234 };
48
78
  const structure_2 = { id: 12 };
@@ -93,6 +123,190 @@ describe("reducers: structureVersion", () => {
93
123
  ).toEqual(expectedState);
94
124
  });
95
125
 
126
+ it("should handle the selectGrantRequestTemplate.TRIGGER", () => {
127
+ const template = "new_template";
128
+ const expectedState = {
129
+ ...initialState,
130
+ template,
131
+ };
132
+ expect(
133
+ grantRequestsCart(initialState, {
134
+ type: selectGrantRequestTemplate.TRIGGER,
135
+ payload: template,
136
+ })
137
+ ).toEqual(expectedState);
138
+ });
139
+
140
+ it("should handle the updateGrantRequestTemplateContent.TRIGGER with valid content", () => {
141
+ const stateWithTemplate = {
142
+ ...initialState,
143
+ template: "template_name",
144
+ };
145
+ const content = { field: "content" };
146
+ const valid = [];
147
+ const expectedState = {
148
+ ...stateWithTemplate,
149
+ templateContent: content,
150
+ validCart: true,
151
+ };
152
+ expect(
153
+ grantRequestsCart(stateWithTemplate, {
154
+ type: updateGrantRequestTemplateContent.TRIGGER,
155
+ payload: { content, valid },
156
+ })
157
+ ).toEqual(expectedState);
158
+ });
159
+
160
+ it("should handle the updateGrantRequestTemplateContent.TRIGGER with invalid content", () => {
161
+ const stateWithTemplate = {
162
+ ...initialState,
163
+ template: "template_name",
164
+ };
165
+ const content = { field: "content" };
166
+ const valid = [{ validation: "error" }];
167
+ const expectedState = {
168
+ ...stateWithTemplate,
169
+ templateContent: content,
170
+ validCart: false,
171
+ };
172
+ expect(
173
+ grantRequestsCart(stateWithTemplate, {
174
+ type: updateGrantRequestTemplateContent.TRIGGER,
175
+ payload: { content, valid },
176
+ })
177
+ ).toEqual(expectedState);
178
+ });
179
+
180
+ it("should handle the setGrantChangeRequestCart.TRIGGER", () => {
181
+ const structure = { id: 1 };
182
+ const grant = { id: 2 };
183
+ const expectedState = {
184
+ ...initialState,
185
+ modificationGrant: grant,
186
+ structures: [structure],
187
+ };
188
+ expect(
189
+ grantRequestsCart(initialState, {
190
+ type: setGrantChangeRequestCart.TRIGGER,
191
+ payload: { structure, grant },
192
+ })
193
+ ).toEqual(expectedState);
194
+ });
195
+
196
+ it("on setGrantChangeRequestCart.TRIGGER should discard existing structures from state", () => {
197
+ const stateWithStructures = {
198
+ ...initialState,
199
+ structures: [{ id: 5 }, { id: 6 }],
200
+ };
201
+ const structure = { id: 1 };
202
+ const grant = { id: 2 };
203
+ const expectedState = {
204
+ ...initialState,
205
+ modificationGrant: grant,
206
+ structures: [structure],
207
+ };
208
+ expect(
209
+ grantRequestsCart(stateWithStructures, {
210
+ type: setGrantChangeRequestCart.TRIGGER,
211
+ payload: { structure, grant },
212
+ })
213
+ ).toEqual(expectedState);
214
+ });
215
+
216
+ it("on updateGrantRequestFilter.TRIGGER adds a empty filter to structure when no index is passed", () => {
217
+ const stateWithPopulation = {
218
+ ...initialState,
219
+ structures: [{ id: 1 }, { id: 2 }],
220
+ };
221
+ const payload = {
222
+ index: null,
223
+ value: null,
224
+ structureId: 1,
225
+ };
226
+ const expectedState = {
227
+ ...initialState,
228
+ structures: [{ id: 1, filters: [{}] }, { id: 2 }],
229
+ };
230
+ expect(
231
+ grantRequestsCart(stateWithPopulation, {
232
+ type: updateGrantRequestFilter.TRIGGER,
233
+ payload,
234
+ })
235
+ ).toEqual(expectedState);
236
+ });
237
+
238
+ it("on updateGrantRequestFilter.TRIGGER adds a empty filter already having filters", () => {
239
+ const stateWithPopulation = {
240
+ ...initialState,
241
+ structures: [{ id: 1, filters: [{ f: 1 }] }],
242
+ };
243
+ const payload = {
244
+ index: null,
245
+ value: null,
246
+ structureId: 1,
247
+ };
248
+ const expectedState = {
249
+ ...initialState,
250
+ structures: [{ id: 1, filters: [{ f: 1 }, {}] }],
251
+ };
252
+ expect(
253
+ grantRequestsCart(stateWithPopulation, {
254
+ type: updateGrantRequestFilter.TRIGGER,
255
+ payload,
256
+ })
257
+ ).toEqual(expectedState);
258
+ });
259
+
260
+ it("on updateGrantRequestFilter.TRIGGER changes value of existing filter", () => {
261
+ const stateWithPopulation = {
262
+ ...initialState,
263
+ structures: [{ id: 1, filters: [{ f: 1 }, { f: 2 }, { f: 3 }] }],
264
+ };
265
+ const payload = {
266
+ index: 1,
267
+ value: { new: 2 },
268
+ structureId: 1,
269
+ };
270
+ const expectedState = {
271
+ ...initialState,
272
+ structures: [{ id: 1, filters: [{ f: 1 }, { f: 2, new: 2 }, { f: 3 }] }],
273
+ };
274
+ expect(
275
+ grantRequestsCart(stateWithPopulation, {
276
+ type: updateGrantRequestFilter.TRIGGER,
277
+ payload,
278
+ })
279
+ ).toEqual(expectedState);
280
+ });
281
+
282
+ it("on updateGrantRequestFilter.TRIGGER removes filter if value is null", () => {
283
+ const stateWithPopulation = {
284
+ ...initialState,
285
+ structures: [{ id: 1, filters: [{ f: 1 }, { f: 2 }, { f: 3 }] }],
286
+ };
287
+ const payload = {
288
+ index: 1,
289
+ value: null,
290
+ structureId: 1,
291
+ };
292
+ const expectedState = {
293
+ ...initialState,
294
+ structures: [{ id: 1, filters: [{ f: 1 }, { f: 3 }] }],
295
+ };
296
+ expect(
297
+ grantRequestsCart(stateWithPopulation, {
298
+ type: updateGrantRequestFilter.TRIGGER,
299
+ payload,
300
+ })
301
+ ).toEqual(expectedState);
302
+ });
303
+
304
+ it("checkoutGrantRequest.SUCCESS should return the initialState", () => {
305
+ expect(
306
+ grantRequestsCart({ foo: "bar" }, { type: checkoutGrantRequest.SUCCESS })
307
+ ).toEqual(initialState);
308
+ });
309
+
96
310
  it("should ignore unknown actions", () => {
97
311
  expect(grantRequestsCart(initialState, { type: "FOO" })).toBe(initialState);
98
312
  });
@@ -2,20 +2,19 @@ import _ from "lodash/fp";
2
2
  import { dropAt, replaceAt } from "@truedat/core/services/arrays";
3
3
  import {
4
4
  addGrantRequestToCart,
5
+ checkoutGrantRequest,
5
6
  removeGrantRequestFromCart,
6
- fetchGrantRequestTemplates,
7
7
  selectGrantRequestTemplate,
8
- updateGrantRequestTemplateContent,
8
+ setGrantChangeRequestCart,
9
9
  updateGrantRequestFilter,
10
- checkoutGrantRequest,
10
+ updateGrantRequestTemplateContent,
11
11
  } from "../routines";
12
12
 
13
13
  const initialState = {
14
14
  structures: [],
15
- templates: [],
16
15
  template: null,
17
16
  templateContent: {},
18
- templatesLoading: false,
17
+ modificationGrant: null,
19
18
  };
20
19
  const mapPayload = (payload) =>
21
20
  payload?.class === "field" ? { ...payload, filters: [] } : payload;
@@ -34,13 +33,14 @@ const setRowValue = ({ index, value, population }) => {
34
33
  const grantRequestsCart = (state = initialState, { type, payload }) => {
35
34
  switch (type) {
36
35
  case addGrantRequestToCart.TRIGGER:
36
+ const baseState = state.modificationGrant ? initialState : state;
37
37
  return {
38
- ...state,
38
+ ...baseState,
39
39
  structures: _.flow(
40
40
  _.pathOr([], "structures"),
41
41
  inverseConcat(mapPayload(payload)),
42
42
  _.uniqBy("id")
43
- )(state),
43
+ )(baseState),
44
44
  };
45
45
  case removeGrantRequestFromCart.TRIGGER:
46
46
  return {
@@ -53,34 +53,28 @@ const grantRequestsCart = (state = initialState, { type, payload }) => {
53
53
  case selectGrantRequestTemplate.TRIGGER:
54
54
  return {
55
55
  ...state,
56
- template: _.find((t) => t.id === payload)(state.templates),
56
+ template: payload,
57
57
  };
58
- case fetchGrantRequestTemplates.REQUEST:
59
- return {
60
- ...state,
61
- templatesLoading: true,
62
- };
63
- case fetchGrantRequestTemplates.SUCCESS:
64
- return {
65
- ...state,
66
- templates: payload.data,
67
- };
68
- case fetchGrantRequestTemplates.FULFILL:
58
+ case updateGrantRequestTemplateContent.TRIGGER:
59
+ const { content, valid } = payload;
69
60
  return {
70
61
  ...state,
71
- templatesLoading: false,
62
+ templateContent: content,
63
+ validCart: state.template && _.size(valid) === 0,
72
64
  };
73
- case updateGrantRequestTemplateContent.TRIGGER:
65
+ case setGrantChangeRequestCart.TRIGGER:
66
+ const { structure, grant } = payload;
74
67
  return {
75
- ...state,
76
- templateContent: payload,
68
+ ...initialState,
69
+ modificationGrant: grant,
70
+ structures: [mapPayload(structure)],
77
71
  };
78
72
  case updateGrantRequestFilter.TRIGGER:
79
- const { index, value, structure_id } = payload;
73
+ const { index, value, structureId } = payload;
80
74
  return {
81
75
  ...state,
82
76
  structures: _.map((s) =>
83
- s.id === structure_id
77
+ s.id === structureId
84
78
  ? {
85
79
  ...s,
86
80
  filters: setRowValue({
@@ -99,4 +93,4 @@ const grantRequestsCart = (state = initialState, { type, payload }) => {
99
93
  }
100
94
  };
101
95
 
102
- export { grantRequestsCart };
96
+ export { grantRequestsCart, initialState };
package/src/routines.js CHANGED
@@ -38,6 +38,7 @@ export const clearUserSearchFilters = createRoutine("CLEAR_USER_SEARCH_FILTERS")
38
38
  export const closeGrantFilter = createRoutine("CLOSE_GRANT_FILTER");
39
39
  export const closeStructureFilter = createRoutine("CLOSE_STRUCTURE_FILTER");
40
40
  export const createGrantRequestApproval = createRoutine("CREATE_GRANT_REQUEST_APPROVAL");
41
+ export const createGrantRequestStatus = createRoutine("CREATE_GRANT_REQUEST_STATUS");
41
42
  export const createGraph = createRoutine("CREATE_GRAPH");
42
43
  export const createProfileGroup = createRoutine("CREATE_PROFILE_GROUP");
43
44
  export const createReferenceDataset = createRoutine("CREATE_REFERENCE_DATASET");
@@ -61,7 +62,6 @@ export const fetchDomains = createRoutine("FETCH_DOMAINS");
61
62
  export const fetchGrant = createRoutine("FETCH_GRANT");
62
63
  export const fetchGrantFilters = createRoutine("FETCH_GRANT_FILTERS");
63
64
  export const fetchGrantRequest = createRoutine("FETCH_GRANT_REQUEST");
64
- export const fetchGrantRequestTemplates = createRoutine("FETCH_GRANT_REQUEST_TEMPLATES");
65
65
  export const fetchGrantRequests = createRoutine("FETCH_GRANT_REQUESTS");
66
66
  export const fetchGrants = createRoutine("FETCH_GRANTS");
67
67
  export const fetchGraph = createRoutine("FETCH_GRAPH");
@@ -108,6 +108,7 @@ export const selectPath = createRoutine("SELECT_PATH");
108
108
  export const selectResources = createRoutine("SELECT_RESOURCES");
109
109
  export const selectStructure = createRoutine("SELECT_STRUCTURE");
110
110
  export const selectStructurePage = createRoutine("SELECT_STRUCTURE_PAGE");
111
+ export const setGrantChangeRequestCart = createRoutine("SET_GRANT_CHANGE_REQUEST_CART");
111
112
  export const setGrantRequestsQuery = createRoutine("SET_GRANT_REQUESTS_QUERY");
112
113
  export const sortGrants = createRoutine("SORT_GRANTS");
113
114
  export const sortStructures = createRoutine("SORT_STRUCTURES");
@@ -0,0 +1,82 @@
1
+ import { compile } from "path-to-regexp";
2
+ import { testSaga } from "redux-saga-test-plan";
3
+ import { apiJsonPost, JSON_OPTS } from "@truedat/core/services/api";
4
+ import {
5
+ createGrantRequestStatusRequestSaga,
6
+ createGrantRequestStatusSaga,
7
+ } from "../createGrantRequestStatus";
8
+ import { createGrantRequestStatus, fetchStructure } from "../../routines";
9
+ import { API_GRANT_REQUEST_STATUS } from "../../api";
10
+
11
+ describe("sagas: createGrantRequestStatusRequestSaga", () => {
12
+ it("should invoke createGrantRequestStatusSaga on createGrantRequestStatus.TRIGGER", () => {
13
+ expect(() => {
14
+ testSaga(createGrantRequestStatusRequestSaga)
15
+ .next()
16
+ .takeLatest(
17
+ createGrantRequestStatus.TRIGGER,
18
+ createGrantRequestStatusSaga
19
+ )
20
+ .finish()
21
+ .isDone();
22
+ }).not.toThrow();
23
+ });
24
+
25
+ it("should throw exception if an unhandled action is received", () => {
26
+ expect(() => {
27
+ testSaga(createGrantRequestStatusRequestSaga)
28
+ .next()
29
+ .takeLatest("FOO", createGrantRequestStatusRequestSaga);
30
+ }).toThrow();
31
+ });
32
+ });
33
+
34
+ describe("sagas: createGrantRequestStatusSaga", () => {
35
+ const status = "cancelled";
36
+ const structureId = 3;
37
+ const payload = {
38
+ grantRequestId: 8,
39
+ status,
40
+ structureId,
41
+ };
42
+ const requestData = { status };
43
+
44
+ const url = compile(API_GRANT_REQUEST_STATUS)({ id: 8 });
45
+
46
+ it("should put a success action when a response is returned", () => {
47
+ expect(() => {
48
+ testSaga(createGrantRequestStatusSaga, { payload })
49
+ .next()
50
+ .put(createGrantRequestStatus.request(requestData))
51
+ .next()
52
+ .call(apiJsonPost, url, requestData, JSON_OPTS)
53
+ .next({ data: "result" })
54
+ .put(createGrantRequestStatus.success("result"))
55
+ .next()
56
+ .put(fetchStructure.trigger({ id: structureId }))
57
+ .next()
58
+ .put(createGrantRequestStatus.fulfill())
59
+ .next()
60
+ .isDone();
61
+ }).not.toThrow();
62
+ });
63
+
64
+ it("should put a failure action when the call returns an error", () => {
65
+ const message = "Request failed";
66
+ const error = { message };
67
+
68
+ expect(() => {
69
+ testSaga(createGrantRequestStatusSaga, { payload })
70
+ .next()
71
+ .put(createGrantRequestStatus.request(requestData))
72
+ .next()
73
+ .call(apiJsonPost, url, requestData, JSON_OPTS)
74
+ .throw(error)
75
+ .put(createGrantRequestStatus.failure(message))
76
+ .next()
77
+ .put(createGrantRequestStatus.fulfill())
78
+ .next()
79
+ .isDone();
80
+ }).not.toThrow();
81
+ });
82
+ });
@@ -0,0 +1,32 @@
1
+ import { compile } from "path-to-regexp";
2
+ import { call, put, takeLatest } from "redux-saga/effects";
3
+ import { apiJsonPost, JSON_OPTS } from "@truedat/core/services/api";
4
+ import { createGrantRequestStatus, fetchStructure } from "../routines";
5
+ import { API_GRANT_REQUEST_STATUS } from "../api";
6
+
7
+ export function* createGrantRequestStatusSaga({ payload }) {
8
+ try {
9
+ const { grantRequestId, status, structureId } = payload;
10
+ const url = compile(API_GRANT_REQUEST_STATUS)({ id: grantRequestId });
11
+ yield put(createGrantRequestStatus.request({ status }));
12
+ const { data } = yield call(apiJsonPost, url, { status }, JSON_OPTS);
13
+ yield put(createGrantRequestStatus.success(data));
14
+ yield put(fetchStructure.trigger({ id: structureId }));
15
+ } catch (error) {
16
+ if (error.response) {
17
+ const { status, data } = error.response;
18
+ yield put(createGrantRequestStatus.failure({ status, data }));
19
+ } else {
20
+ yield put(createGrantRequestStatus.failure(error.message));
21
+ }
22
+ } finally {
23
+ yield put(createGrantRequestStatus.fulfill());
24
+ }
25
+ }
26
+
27
+ export function* createGrantRequestStatusRequestSaga() {
28
+ yield takeLatest(
29
+ createGrantRequestStatus.TRIGGER,
30
+ createGrantRequestStatusSaga
31
+ );
32
+ }