@truedat/dd 8.12.2 → 8.12.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. package/package.json +3 -3
  2. package/src/api/__tests__/queries.spec.js +55 -0
  3. package/src/api/queries.js +31 -0
  4. package/src/components/Grant.js +106 -16
  5. package/src/components/GrantRequest.js +2 -2
  6. package/src/components/GrantRequestBulkApprovalPopup.js +0 -1
  7. package/src/components/GrantsDownloadButton.js +9 -1
  8. package/src/components/GrantsTable.js +4 -1
  9. package/src/components/StructureFields.js +7 -4
  10. package/src/components/StructureGrantCartUserSelector.js +29 -4
  11. package/src/components/StructureGrantDropdown.js +7 -1
  12. package/src/components/StructureGrants.js +4 -1
  13. package/src/components/StructureNoteActions.js +10 -1
  14. package/src/components/StructureNotes.js +42 -6
  15. package/src/components/StructureNotesEdit.js +38 -8
  16. package/src/components/StructuresUpdateOption.js +2 -2
  17. package/src/components/SystemStructures.js +3 -3
  18. package/src/components/__tests__/CatalogViewConfigForm.spec.js +2 -0
  19. package/src/components/__tests__/EditDomainForm.spec.js +3 -1
  20. package/src/components/__tests__/Grant.spec.js +171 -0
  21. package/src/components/__tests__/GrantApprovalRuleForm.spec.js +2 -0
  22. package/src/components/__tests__/GrantApprovalRuleNew.spec.js +8 -0
  23. package/src/components/__tests__/GrantApprovalRules.spec.js +4 -0
  24. package/src/components/__tests__/GrantRequest.spec.js +4 -4
  25. package/src/components/__tests__/GrantRequestBulkActions.spec.js +1 -4
  26. package/src/components/__tests__/GrantRequestsSearchResults.spec.js +2 -0
  27. package/src/components/__tests__/GrantsDownloadButton.spec.js +58 -2
  28. package/src/components/__tests__/GrantsTable.spec.js +22 -2
  29. package/src/components/__tests__/LineageDefs.spec.js +6 -1
  30. package/src/components/__tests__/LineageForm.spec.js +1 -0
  31. package/src/components/__tests__/LineageGraphToolbar.spec.js +19 -17
  32. package/src/components/__tests__/LineageInspectorPanel.spec.js +17 -9
  33. package/src/components/__tests__/ProfileGroup.spec.js +7 -1
  34. package/src/components/__tests__/ReferenceDatasetForm.spec.js +2 -0
  35. package/src/components/__tests__/ReferenceDatasetRoutes.spec.js +9 -0
  36. package/src/components/__tests__/StructureGrantCartCheckout.spec.js +39 -1
  37. package/src/components/__tests__/StructureGrantCartInformation.spec.js +5 -2
  38. package/src/components/__tests__/StructureGrantCartUserSelector.spec.js +128 -0
  39. package/src/components/__tests__/StructureGrantDropdown.spec.js +92 -0
  40. package/src/components/__tests__/StructureGrantListButton.spec.js +70 -0
  41. package/src/components/__tests__/StructureGrantSummaryButton.spec.js +36 -1
  42. package/src/components/__tests__/StructureGrants.spec.js +12 -0
  43. package/src/components/__tests__/StructureNoteActions.spec.js +96 -0
  44. package/src/components/__tests__/StructureNotes.spec.js +170 -1
  45. package/src/components/__tests__/StructureNotesEdit.spec.js +185 -1
  46. package/src/components/__tests__/StructureRelationRow.spec.js +72 -4
  47. package/src/components/__tests__/StructureRelations.spec.js +18 -0
  48. package/src/components/__tests__/StructureRoles.spec.js +9 -0
  49. package/src/components/__tests__/StructureRow.spec.js +13 -4
  50. package/src/components/__tests__/StructureSelector.spec.js +2 -0
  51. package/src/components/__tests__/StructureTag.spec.js +2 -0
  52. package/src/components/__tests__/StructureTagForm.spec.js +2 -0
  53. package/src/components/__tests__/StructureType.spec.js +3 -1
  54. package/src/components/__tests__/StructureTypeForm.spec.js +3 -1
  55. package/src/components/__tests__/StructureView.spec.js +17 -1
  56. package/src/components/__tests__/StructuresGrantRequestView.spec.js +2 -0
  57. package/src/components/__tests__/StructuresView.spec.js +2 -1
  58. package/src/components/__tests__/Tag.spec.js +4 -1
  59. package/src/components/__tests__/Tags.spec.js +7 -1
  60. package/src/components/__tests__/__snapshots__/GrantsTable.spec.js.snap +34 -2
  61. package/src/components/__tests__/__snapshots__/LineageDefs.spec.js.snap +32 -30
  62. package/src/components/__tests__/__snapshots__/StructureFields.spec.js.snap +1 -16
  63. package/src/components/__tests__/__snapshots__/StructureNoteActions.spec.js.snap +2 -1
  64. package/src/components/__tests__/__snapshots__/StructureNotesEdit.spec.js.snap +3 -0
  65. package/src/components/__tests__/__snapshots__/StructureRelationRow.spec.js.snap +23 -19
  66. package/src/components/__tests__/__snapshots__/StructureRow.spec.js.snap +28 -24
  67. package/src/components/__tests__/__snapshots__/StructuresUpdateOption.spec.js.snap +7 -3
  68. package/src/messages/en.js +2 -2
  69. package/src/messages/es.js +2 -2
  70. package/src/reducers/__tests__/ddMessage.spec.js +48 -0
  71. package/src/reducers/__tests__/grantRequestsCart.spec.js +17 -0
  72. package/src/reducers/__tests__/structureRedirect.spec.js +22 -0
  73. package/src/reducers/__tests__/structureRelations.spec.js +28 -0
  74. package/src/reducers/ddMessage.js +32 -0
  75. package/src/reducers/grantRequestsCart.js +3 -0
  76. package/src/reducers/structureRedirect.js +7 -2
  77. package/src/selectors/__tests__/__snapshots__/getGrantsColumns.spec.js.snap +1 -9
  78. package/src/selectors/__tests__/getGrantRequestsSearchColumns.spec.js +11 -4
  79. package/src/selectors/__tests__/getGrantsColumns.spec.js +295 -0
  80. package/src/selectors/__tests__/messages.spec.js +14 -0
  81. package/src/selectors/getBusinessConceptsLinksToStructuresColumnsSelector.js +3 -5
  82. package/src/selectors/getGrantRequestsSearchColumns.js +3 -5
  83. package/src/selectors/getGrantsColumns.js +85 -11
  84. package/src/selectors/getLinkedImplementationsToStructuresColumns.js +3 -7
  85. package/src/selectors/getStructureFieldColumns.js +7 -6
  86. package/src/selectors/getStructureProperties.js +2 -5
  87. package/src/selectors/getStructuresUploadEventColumns.js +2 -7
  88. package/src/selectors/messages.js +30 -0
  89. package/src/selectors/structureColumnsSelector.js +13 -16
  90. package/src/utils/__tests__/structureNoteActions.spec.js +196 -0
  91. package/src/utils/structureNoteActions.js +22 -0
@@ -4,6 +4,8 @@ import userEvent from "@testing-library/user-event";
4
4
  import { StructureTag } from "../StructureTag";
5
5
 
6
6
  describe("<StructureTag />", () => {
7
+ beforeEach(() => jest.useRealTimers());
8
+
7
9
  const tagName = "Tag 42";
8
10
  const structureTag = {
9
11
  id: "1",
@@ -4,6 +4,8 @@ import { render, waitForLoad } from "@truedat/test/render";
4
4
  import { StructureTagForm } from "../StructureTagForm";
5
5
 
6
6
  describe("<StructureTagForm />", () => {
7
+ beforeEach(() => jest.useRealTimers());
8
+
7
9
  const tags = [
8
10
  { id: "1", name: "Tag1", description: "desc1" },
9
11
  { id: "2", name: "Tag2", description: "desc2" },
@@ -1,3 +1,4 @@
1
+ import { act } from "@testing-library/react";
1
2
  import { render } from "@truedat/test/render";
2
3
  import StructureType from "../StructureType";
3
4
 
@@ -17,8 +18,9 @@ const renderOpts = {
17
18
  };
18
19
 
19
20
  describe("<StructureType />", () => {
20
- it("matches the latest snapshot", () => {
21
+ it("matches the latest snapshot", async () => {
21
22
  const { container } = render(<StructureType />, renderOpts);
23
+ await act(async () => {});
22
24
  expect(container).toMatchSnapshot();
23
25
  });
24
26
  });
@@ -1,3 +1,4 @@
1
+ import { act } from "@testing-library/react";
1
2
  import { render } from "@truedat/test/render";
2
3
  import StructureTypeForm from "../StructureTypeForm";
3
4
 
@@ -39,8 +40,9 @@ const renderOpts = {
39
40
  };
40
41
 
41
42
  describe("<StructureTypeForm />", () => {
42
- it("matches the latest snapshot", () => {
43
+ it("matches the latest snapshot", async () => {
43
44
  const { container } = render(<StructureTypeForm />, renderOpts);
45
+ await act(async () => {});
44
46
  expect(container).toMatchSnapshot();
45
47
  });
46
48
  });
@@ -1,7 +1,12 @@
1
1
  import { render } from "@truedat/test/render";
2
2
  import { waitFor } from "@testing-library/react";
3
+ import { STRUCTURE_TAGS_QUERY } from "../../api/queries";
3
4
  import StructureView from "../StructureView";
4
5
 
6
+ jest.mock("../../hooks/useBucketStructures", () => ({
7
+ useBucketStructures: () => ({ data: undefined, isLoading: true }),
8
+ }));
9
+
5
10
  jest.mock("react-router", () => ({
6
11
  ...jest.requireActual("react-router"),
7
12
  useParams: () => ({ id: 1 }),
@@ -33,6 +38,14 @@ const commonState = {
33
38
  };
34
39
 
35
40
  describe("<StructureView />", () => {
41
+ const structureTagsMock = {
42
+ request: { query: STRUCTURE_TAGS_QUERY, variables: { id: 1 } },
43
+ result: {
44
+ data: {
45
+ dataStructure: { id: 1, availableTags: [], structureTags: [] },
46
+ },
47
+ },
48
+ };
36
49
  it("Some inner component shows the structure name", () => {
37
50
  const renderOpts = {
38
51
  state: {
@@ -48,7 +61,10 @@ describe("<StructureView />", () => {
48
61
  },
49
62
  };
50
63
 
51
- const { getAllByText } = render(<StructureView />, renderOpts);
64
+ const { getAllByText } = render(<StructureView />, {
65
+ ...renderOpts,
66
+ mocks: [structureTagsMock],
67
+ });
52
68
  expect(getAllByText("some_db")[0]).toBeInTheDocument();
53
69
  });
54
70
 
@@ -6,6 +6,8 @@ import { functionsMock } from "@truedat/test/mocks";
6
6
  import { StructuresGrantRequestView } from "../StructuresGrantRequestView";
7
7
  import en from "../../messages/en";
8
8
 
9
+ jest.mock("@truedat/core/hooks/useUserFilters");
10
+
9
11
  const mockHistory = jest.fn();
10
12
 
11
13
  jest.mock("react-router", () => ({
@@ -1,10 +1,11 @@
1
- import _ from "lodash/fp";
2
1
  import { within } from "@testing-library/react";
3
2
  import { render, waitForLoad } from "@truedat/test/render";
4
3
  import SearchContext from "@truedat/core/search/SearchContext";
5
4
  import StructuresView from "../StructuresView";
6
5
  import { StructuresViewContent } from "../StructuresView";
7
6
 
7
+ jest.mock("@truedat/core/hooks/useUserFilters");
8
+
8
9
  const mockHistory = jest.fn();
9
10
 
10
11
  jest.mock("react-router", () => ({
@@ -1,10 +1,13 @@
1
1
  import { render } from "@truedat/test/render";
2
+ import { domainsMock } from "@truedat/test/mocks";
2
3
  import Tag from "../Tag";
3
4
 
4
5
  describe("<Tag />", () => {
5
6
  it("matches the latest snapshot", () => {
6
7
  const createTag = jest.fn();
7
- const { container } = render(<Tag createTag={createTag} />);
8
+ const { container } = render(<Tag createTag={createTag} />, {
9
+ mocks: [domainsMock({ action: "manageTags" })],
10
+ });
8
11
  expect(container).toMatchSnapshot();
9
12
  });
10
13
  });
@@ -1,9 +1,15 @@
1
1
  import { render } from "@truedat/test/render";
2
+ import { TAGS_QUERY } from "../../api/queries";
2
3
  import Tags from "../Tags";
3
4
 
5
+ const tagsMock = {
6
+ request: { query: TAGS_QUERY },
7
+ result: { data: { tags: [] } },
8
+ };
9
+
4
10
  describe("<Tags />", () => {
5
11
  it("matches the latest snapshot", () => {
6
- const { container } = render(<Tags />);
12
+ const { container } = render(<Tags />, { mocks: [tagsMock] });
7
13
  expect(container).toMatchSnapshot();
8
14
  });
9
15
  });
@@ -41,7 +41,23 @@ exports[`<GrantsTable /> matches the latest snapshot 1`] = `
41
41
  >
42
42
  <td
43
43
  class=""
44
- />
44
+ >
45
+ <h4
46
+ class="ui header"
47
+ >
48
+ <div
49
+ class="content"
50
+ >
51
+ user_full_name_1
52
+
53
+ <div
54
+ class="sub header"
55
+ >
56
+ user1@example.com
57
+ </div>
58
+ </div>
59
+ </h4>
60
+ </td>
45
61
  <td
46
62
  class=""
47
63
  >
@@ -92,7 +108,23 @@ exports[`<GrantsTable /> matches the latest snapshot 1`] = `
92
108
  >
93
109
  <td
94
110
  class=""
95
- />
111
+ >
112
+ <h4
113
+ class="ui header"
114
+ >
115
+ <div
116
+ class="content"
117
+ >
118
+ user_full_name_2
119
+
120
+ <div
121
+ class="sub header"
122
+ >
123
+ user2@example.com
124
+ </div>
125
+ </div>
126
+ </h4>
127
+ </td>
96
128
  <td
97
129
  class=""
98
130
  >
@@ -2,35 +2,37 @@
2
2
 
3
3
  exports[`<LineageDefs /> matches the latest snapshot 1`] = `
4
4
  <div>
5
- <defs>
6
- <marker
7
- id="end"
8
- markerheight="6"
9
- markerwidth="6"
10
- orient="auto"
11
- refx="10"
12
- refy="0"
13
- viewbox="0 -5 10 10"
14
- >
15
- <path
16
- d="M0,-5L10,0L0,5L0,-5"
17
- fill="#999"
18
- />
19
- </marker>
20
- <marker
21
- id="end-active"
22
- markerheight="6"
23
- markerwidth="6"
24
- orient="auto"
25
- refx="10"
26
- refy="0"
27
- viewbox="0 -5 10 10"
28
- >
29
- <path
30
- d="M0,-5L10,0L0,5L0,-5"
31
- fill="orangered"
32
- />
33
- </marker>
34
- </defs>
5
+ <svg>
6
+ <defs>
7
+ <marker
8
+ id="end"
9
+ markerHeight="6"
10
+ markerWidth="6"
11
+ orient="auto"
12
+ refX="10"
13
+ refY="0"
14
+ viewBox="0 -5 10 10"
15
+ >
16
+ <path
17
+ d="M0,-5L10,0L0,5L0,-5"
18
+ fill="#999"
19
+ />
20
+ </marker>
21
+ <marker
22
+ id="end-active"
23
+ markerHeight="6"
24
+ markerWidth="6"
25
+ orient="auto"
26
+ refX="10"
27
+ refY="0"
28
+ viewBox="0 -5 10 10"
29
+ >
30
+ <path
31
+ d="M0,-5L10,0L0,5L0,-5"
32
+ fill="orangered"
33
+ />
34
+ </marker>
35
+ </defs>
36
+ </svg>
35
37
  </div>
36
38
  `;
@@ -142,22 +142,7 @@ exports[`<StructureFields /> matches the latest snapshot 1`] = `
142
142
  </td>
143
143
  <td
144
144
  class=""
145
- >
146
- <div
147
- class="ui list"
148
- role="list"
149
- >
150
- <div
151
- class="item"
152
- role="listitem"
153
- >
154
- <a
155
- data-discover="true"
156
- href="/concepts/123/versions/current"
157
- />
158
- </div>
159
- </div>
160
- </td>
145
+ />
161
146
  </tr>
162
147
  <tr
163
148
  class=""
@@ -21,8 +21,9 @@ exports[`<StructureNoteActions /> matches the latest snapshot 1`] = `
21
21
  >
22
22
  <div
23
23
  aria-checked="false"
24
+ aria-disabled="false"
24
25
  aria-selected="true"
25
- class="selected item td-icon-text-control"
26
+ class="selected item td-structure-note-action td-icon-text-control"
26
27
  role="option"
27
28
  style="pointer-events: all;"
28
29
  >
@@ -8,6 +8,9 @@ exports[`<StructureNotesEdit /> matches the latest snapshot 1`] = `
8
8
  <form
9
9
  class="ui form"
10
10
  >
11
+ <div
12
+ data-testid="dynamic-form"
13
+ />
11
14
  <button
12
15
  class="ui primary button"
13
16
  >
@@ -2,24 +2,28 @@
2
2
 
3
3
  exports[`<StructureRelationRow /> matches the latest snapshot 1`] = `
4
4
  <div>
5
- <tr
6
- class=""
7
- >
8
- <td
9
- class=""
10
- >
11
- Structure 1
12
- </td>
13
- <td
14
- class=""
15
- >
16
- Some Type 1
17
- </td>
18
- <td
19
- class=""
20
- >
21
- used_by
22
- </td>
23
- </tr>
5
+ <table>
6
+ <tbody>
7
+ <tr
8
+ class=""
9
+ >
10
+ <td
11
+ class=""
12
+ >
13
+ Structure 1
14
+ </td>
15
+ <td
16
+ class=""
17
+ >
18
+ Some Type 1
19
+ </td>
20
+ <td
21
+ class=""
22
+ >
23
+ used_by
24
+ </td>
25
+ </tr>
26
+ </tbody>
27
+ </table>
24
28
  </div>
25
29
  `;
@@ -2,29 +2,33 @@
2
2
 
3
3
  exports[`<StructureRow /> matches the latest snapshot 1`] = `
4
4
  <div>
5
- <tr
6
- class=""
7
- >
8
- <td
9
- class="structure-cell-overflow"
10
- >
11
- s1
12
- </td>
13
- <td
14
- class=""
15
- >
16
- org
17
- </td>
18
- <td
19
- class=""
20
- >
21
- sys
22
- </td>
23
- <td
24
- class=""
25
- >
26
- gp
27
- </td>
28
- </tr>
5
+ <table>
6
+ <tbody>
7
+ <tr
8
+ class=""
9
+ >
10
+ <td
11
+ class="structure-cell-overflow"
12
+ >
13
+ s1
14
+ </td>
15
+ <td
16
+ class=""
17
+ >
18
+ org
19
+ </td>
20
+ <td
21
+ class=""
22
+ >
23
+ sys
24
+ </td>
25
+ <td
26
+ class=""
27
+ >
28
+ gp
29
+ </td>
30
+ </tr>
31
+ </tbody>
32
+ </table>
29
33
  </div>
30
34
  `;
@@ -11,9 +11,13 @@ exports[`<StructuresUpdateOption /> matches the latest snapshot 1`] = `
11
11
  aria-hidden="true"
12
12
  class="refresh icon"
13
13
  />
14
- <span>
15
- update
16
- </span>
14
+ <div
15
+ class="text"
16
+ >
17
+ <span>
18
+ update
19
+ </span>
20
+ </div>
17
21
  </div>
18
22
  </div>
19
23
  `;
@@ -132,8 +132,8 @@ export default {
132
132
  "grantRequest.header.updated_at": "Updated",
133
133
  "grantRequest.header.user": "User",
134
134
  "grantRequest.header.group": "User group",
135
- "grantRequest.deleted.user": "Deleted user",
136
- "grantRequest.deleted.group": "Deleted group",
135
+ "deleted.user": "Deleted user",
136
+ "deleted.group": "Deleted group",
137
137
  "grantRequest.header.createdBy": "Created by",
138
138
  "grantRequest.header.create": "Create grant request",
139
139
  "grantRequest.header.type": "Request type",
@@ -135,8 +135,8 @@ export default {
135
135
  "grantRequest.header.updated_at": "Actualizado",
136
136
  "grantRequest.header.user": "Usuario",
137
137
  "grantRequest.header.group": "Grupo de usuarios",
138
- "grantRequest.deleted.user": "Usuario eliminado",
139
- "grantRequest.deleted.group": "Grupo eliminado",
138
+ "deleted.user": "Usuario eliminado",
139
+ "deleted.group": "Grupo eliminado",
140
140
  "grantRequest.header.createdBy": "Creado por",
141
141
  "grantRequest.header.create": "Crear petición de acceso",
142
142
  "grantRequest.header.type": "Tipo de petición",
@@ -1,4 +1,5 @@
1
1
  import {
2
+ bulkUpdateStructures,
2
3
  createReferenceDataset,
3
4
  deleteReferenceDataset,
4
5
  updateReferenceDataset,
@@ -74,6 +75,53 @@ describe("reducers: ddMessage", () => {
74
75
  });
75
76
  });
76
77
 
78
+ it("should handle the bulkUpdateStructures.FAILURE action with error details", () => {
79
+ const ddMsg = ddMessage(fooState, {
80
+ type: bulkUpdateStructures.FAILURE,
81
+ payload: { status: 422, data: { error: { message: "some message" } } },
82
+ });
83
+ expect(ddMsg).toMatchObject({
84
+ error: true,
85
+ header: "structures.bulkUpdateStructures.failed.header",
86
+ content: "some message",
87
+ });
88
+ });
89
+
90
+ it("should handle bulkUpdateStructures.FAILURE with string payload (timeout)", () => {
91
+ const ddMsg = ddMessage(fooState, {
92
+ type: bulkUpdateStructures.FAILURE,
93
+ payload: "timeout of 0ms exceeded",
94
+ });
95
+ expect(ddMsg).toMatchObject({
96
+ error: true,
97
+ header: "structures.bulkUpdateStructures.failed.timeout.header",
98
+ content: "timeout of 0ms exceeded",
99
+ });
100
+ });
101
+
102
+ it("should handle bulkUpdateStructures.FAILURE with string payload (generic network error)", () => {
103
+ const ddMsg = ddMessage(fooState, {
104
+ type: bulkUpdateStructures.FAILURE,
105
+ payload: "Network Error",
106
+ });
107
+ expect(ddMsg).toMatchObject({
108
+ error: true,
109
+ header: "structures.bulkUpdateStructures.failed.header",
110
+ content: "Network Error",
111
+ });
112
+ });
113
+
114
+ it("should handle bulkUpdateStructures.FAILURE with 504 status as timeout", () => {
115
+ const ddMsg = ddMessage(fooState, {
116
+ type: bulkUpdateStructures.FAILURE,
117
+ payload: { status: 504, data: {} },
118
+ });
119
+ expect(ddMsg).toMatchObject({
120
+ error: true,
121
+ header: "structures.bulkUpdateStructures.failed.timeout.header",
122
+ });
123
+ });
124
+
77
125
  it("should handle the createReferenceDataset.SUCCESS action", () => {
78
126
  expect(ddMessage(fooState, createReferenceDataset.success())).toMatchObject(
79
127
  { header: "alert.createReferenceDataset.success.header" },
@@ -497,4 +497,21 @@ describe("reducers: grantRequestsCart", () => {
497
497
  expect([null, undefined, ""]).toContain(state.user?.id);
498
498
  expect(state.user?.id).not.toBe("group:10");
499
499
  });
500
+
501
+ it("sets user_group_id when setGrantChangeRequestCart.TRIGGER opens a group grant", () => {
502
+ const structure = { id: 1 };
503
+ const grant = {
504
+ id: 2,
505
+ user_id: null,
506
+ user_group_id: 10,
507
+ detail: {},
508
+ };
509
+ const state = grantRequestsCart(initialState, {
510
+ type: setGrantChangeRequestCart.TRIGGER,
511
+ payload: { structure, grant },
512
+ });
513
+
514
+ expect(state.user_group_id).toBe(10);
515
+ expect(state.user?.id ?? null).toBeNull();
516
+ });
500
517
  });
@@ -1,10 +1,12 @@
1
1
  import { clearRedirect } from "@truedat/core/routines";
2
+ import { STRUCTURES } from "@truedat/core/routes";
2
3
  import {
3
4
  createReferenceDataset,
4
5
  deleteReferenceDataset,
5
6
  updateReferenceDataset,
6
7
  updateStructureType,
7
8
  updateStructure,
9
+ bulkUpdateStructures,
8
10
  } from "../../routines";
9
11
  import { structureRedirect, initialState } from "../structureRedirect";
10
12
 
@@ -69,4 +71,24 @@ describe("reducers: structureRedirect", () => {
69
71
  ),
70
72
  ).toBe("/referenceDatasets/42");
71
73
  });
74
+
75
+ it("should redirect to STRUCTURES when bulkUpdateStructures.SUCCESS has no errors", () => {
76
+ const payload = { data: { errors: [] } };
77
+ expect(
78
+ structureRedirect(fooState, {
79
+ type: bulkUpdateStructures.SUCCESS,
80
+ payload,
81
+ }),
82
+ ).toBe(STRUCTURES);
83
+ });
84
+
85
+ it("should not redirect when bulkUpdateStructures.SUCCESS has errors", () => {
86
+ const payload = { data: { errors: [{ message: "err" }] } };
87
+ expect(
88
+ structureRedirect(fooState, {
89
+ type: bulkUpdateStructures.SUCCESS,
90
+ payload,
91
+ }),
92
+ ).toBe(fooState);
93
+ });
72
94
  });
@@ -95,3 +95,31 @@ describe("reducers: parentRelations", () => {
95
95
  expect(parentRelations(fooState, { type: "FOO" })).toBe(fooState);
96
96
  });
97
97
  });
98
+
99
+ describe("reducers: structure relation concept links", () => {
100
+ const links = [{ name: "foo concept", resource_id: "1" }];
101
+ const data = {
102
+ relations: {
103
+ children: [{ id: 1, links }],
104
+ parents: [{ id: 2, links }],
105
+ },
106
+ };
107
+
108
+ it("should keep concept links on children relations", () => {
109
+ expect(
110
+ childrenRelations([], {
111
+ type: fetchStructure.SUCCESS,
112
+ payload: { data },
113
+ }),
114
+ ).toEqual([{ id: 1, links }]);
115
+ });
116
+
117
+ it("should keep concept links on parent relations", () => {
118
+ expect(
119
+ parentRelations([], {
120
+ type: fetchStructure.SUCCESS,
121
+ payload: { data },
122
+ }),
123
+ ).toEqual([{ id: 2, links }]);
124
+ });
125
+ });
@@ -19,6 +19,38 @@ const ddMessage = (state = initialState, { type, payload }) => {
19
19
  return initialState;
20
20
  case bulkUpdateStructures.SUCCESS:
21
21
  return getUploadAlertMessage(payload);
22
+ case bulkUpdateStructures.FAILURE: {
23
+ const isTimeout =
24
+ typeof payload === "string"
25
+ ? /timeout|timed out|ECONNABORTED/i.test(payload)
26
+ : payload?.status === 504 ||
27
+ /timeout/i.test(payload?.data?.error?.message || "");
28
+
29
+ if (isTimeout) {
30
+ return {
31
+ error: true,
32
+ header: "structures.bulkUpdateStructures.failed.timeout.header",
33
+ icon: "attention",
34
+ content:
35
+ typeof payload === "string"
36
+ ? payload
37
+ : payload?.data?.error?.message,
38
+ initialMaxListItems: 5,
39
+ };
40
+ }
41
+
42
+ return {
43
+ error: true,
44
+ header: "structures.bulkUpdateStructures.failed.header",
45
+ icon: "attention",
46
+ content:
47
+ typeof payload === "string"
48
+ ? payload
49
+ : payload?.data?.error?.message ||
50
+ "structures.bulkUpdateStructures.failed.generic.content",
51
+ initialMaxListItems: 5,
52
+ };
53
+ }
22
54
  case uploadStructuresDomains.SUCCESS: {
23
55
  const messagesImp = _.has("errors")(payload.data)
24
56
  ? _.flow(
@@ -127,6 +127,9 @@ const grantRequestsCart = (state = initialState, { type, payload }) => {
127
127
  templateContent: formatLegacyContent(grant.detail),
128
128
  modificationGrant: grant,
129
129
  structures: [mapPayload(structure)],
130
+ ...(_.isNil(grant?.user_group_id)
131
+ ? {}
132
+ : { user_group_id: grant.user_group_id }),
130
133
  };
131
134
  }
132
135
  case updateGrantRequestFilter.TRIGGER: