@truedat/dd 8.10.8 → 8.11.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +3 -3
- package/src/api/queries.js +4 -0
- package/src/components/GrantRequest.js +74 -8
- package/src/components/GrantRequestCancel.js +3 -0
- package/src/components/GrantRequestHeader.js +45 -14
- package/src/components/GrantRequestsDownloadButton.js +9 -1
- package/src/components/GrantRequestsTable.js +4 -1
- package/src/components/StructureGrantCartCheckout.js +9 -4
- package/src/components/StructureGrantCartUserSelector.js +19 -4
- package/src/components/StructureGrantDropdown.js +29 -3
- package/src/components/StructureGrantListButton.js +3 -1
- package/src/components/StructureGrantSummaryButton.js +8 -4
- package/src/components/__tests__/GrantRequest.spec.js +437 -0
- package/src/components/__tests__/GrantRequestHeader.spec.js +89 -2
- package/src/components/__tests__/GrantRequestsDownloadButton.spec.js +52 -0
- package/src/components/__tests__/GrantRequestsTable.spec.js +18 -0
- package/src/components/__tests__/StructureGrantCartCheckout.spec.js +41 -0
- package/src/components/__tests__/StructureGrantCartUserSelector.spec.js +105 -0
- package/src/components/__tests__/StructureGrantDropdown.spec.js +126 -0
- package/src/components/__tests__/StructureGrantListButton.spec.js +36 -1
- package/src/components/__tests__/StructureGrantSummaryButton.spec.js +89 -1
- package/src/components/__tests__/__snapshots__/GrantRequest.spec.js.snap +28 -0
- package/src/components/__tests__/__snapshots__/GrantRequestHeader.spec.js.snap +5 -0
- package/src/messages/en.js +5 -0
- package/src/messages/es.js +5 -0
- package/src/reducers/__tests__/grantRequestsCart.spec.js +12 -0
- package/src/reducers/grantRequestsCart.js +12 -0
- package/src/sagas/__tests__/createGrantRequestStatus.spec.js +67 -1
- package/src/sagas/__tests__/fetchGrantRequest.spec.js +26 -0
- package/src/sagas/createGrantRequestStatus.js +5 -0
- package/src/sagas/fetchGrantRequest.js +1 -1
- package/src/selectors/__tests__/getGrantRequestsSearchColumns.spec.js +82 -0
- package/src/selectors/getGrantRequestsSearchColumns.js +51 -8
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { waitFor } from "@testing-library/react";
|
|
2
|
+
import userEvent from "@testing-library/user-event";
|
|
1
3
|
import { render, waitForLoad } from "@truedat/test/render";
|
|
2
4
|
import { useGrantRequestableUsers } from "@truedat/auth/hooks/useUsers";
|
|
3
5
|
import StructureGrantCartUserSelector from "../StructureGrantCartUserSelector";
|
|
@@ -74,4 +76,107 @@ describe("<StructureGrantCartUserSelector />", () => {
|
|
|
74
76
|
await waitForLoad(rendered);
|
|
75
77
|
expect(rendered.container).toMatchSnapshot();
|
|
76
78
|
});
|
|
79
|
+
|
|
80
|
+
it("shows group alias or name in the selector", async () => {
|
|
81
|
+
const user = userEvent.setup({ delay: null });
|
|
82
|
+
useGrantRequestableUsers.mockImplementation(() => ({
|
|
83
|
+
users: [{ id: 1, full_name: "Ada" }],
|
|
84
|
+
groups: [
|
|
85
|
+
{ id: 10, name: "finance", alias: "Fin" },
|
|
86
|
+
{ id: 11, name: "legal", alias: "" },
|
|
87
|
+
],
|
|
88
|
+
trigger: jest.fn(),
|
|
89
|
+
}));
|
|
90
|
+
|
|
91
|
+
const rendered = render(
|
|
92
|
+
<StructureGrantCartUserSelector />,
|
|
93
|
+
defaultRenderOpts,
|
|
94
|
+
);
|
|
95
|
+
await waitForLoad(rendered);
|
|
96
|
+
await user.click(rendered.getByRole("combobox"));
|
|
97
|
+
|
|
98
|
+
expect(rendered.getByText(/fin/i)).toBeInTheDocument();
|
|
99
|
+
expect(rendered.getByText(/legal/i)).toBeInTheDocument();
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
it("uses users icon for group options and user icon for users", async () => {
|
|
103
|
+
const user = userEvent.setup({ delay: null });
|
|
104
|
+
useGrantRequestableUsers.mockImplementation(() => ({
|
|
105
|
+
users: [{ id: 1, full_name: "Ada" }],
|
|
106
|
+
groups: [
|
|
107
|
+
{ id: 10, name: "finance", alias: "Fin" },
|
|
108
|
+
{ id: 11, name: "legal", alias: "" },
|
|
109
|
+
],
|
|
110
|
+
trigger: jest.fn(),
|
|
111
|
+
}));
|
|
112
|
+
|
|
113
|
+
const rendered = render(
|
|
114
|
+
<StructureGrantCartUserSelector />,
|
|
115
|
+
defaultRenderOpts,
|
|
116
|
+
);
|
|
117
|
+
await waitForLoad(rendered);
|
|
118
|
+
await user.click(rendered.getByRole("combobox"));
|
|
119
|
+
|
|
120
|
+
const groupOption = rendered.getByRole("option", { name: /fin/i });
|
|
121
|
+
expect(groupOption.querySelector(".users.icon")).toBeInTheDocument();
|
|
122
|
+
|
|
123
|
+
const userOption = rendered.getByRole("option", { name: /ada/i });
|
|
124
|
+
expect(userOption.querySelector(".user.icon")).toBeInTheDocument();
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
it("still shows requestable user full name", async () => {
|
|
128
|
+
const user = userEvent.setup({ delay: null });
|
|
129
|
+
useGrantRequestableUsers.mockImplementation(() => ({
|
|
130
|
+
users: [{ id: 1, full_name: "Ada" }],
|
|
131
|
+
groups: [
|
|
132
|
+
{ id: 10, name: "finance", alias: "Fin" },
|
|
133
|
+
{ id: 11, name: "legal", alias: "" },
|
|
134
|
+
],
|
|
135
|
+
trigger: jest.fn(),
|
|
136
|
+
}));
|
|
137
|
+
|
|
138
|
+
const rendered = render(
|
|
139
|
+
<StructureGrantCartUserSelector />,
|
|
140
|
+
defaultRenderOpts,
|
|
141
|
+
);
|
|
142
|
+
await waitForLoad(rendered);
|
|
143
|
+
await user.click(rendered.getByRole("combobox"));
|
|
144
|
+
|
|
145
|
+
expect(rendered.getByRole("option", { name: /ada/i })).toBeInTheDocument();
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
it("dispatches user_group_id when selecting a group", async () => {
|
|
149
|
+
const user = userEvent.setup({ delay: null });
|
|
150
|
+
const dispatch = jest.fn();
|
|
151
|
+
useGrantRequestableUsers.mockImplementation(() => ({
|
|
152
|
+
users: [{ id: 1, full_name: "Ada" }],
|
|
153
|
+
groups: [
|
|
154
|
+
{ id: 10, name: "finance", alias: "Fin" },
|
|
155
|
+
{ id: 11, name: "legal", alias: "" },
|
|
156
|
+
],
|
|
157
|
+
trigger: jest.fn(),
|
|
158
|
+
}));
|
|
159
|
+
|
|
160
|
+
const rendered = render(<StructureGrantCartUserSelector />, {
|
|
161
|
+
...defaultRenderOpts,
|
|
162
|
+
dispatch,
|
|
163
|
+
});
|
|
164
|
+
await waitForLoad(rendered);
|
|
165
|
+
await user.click(rendered.getByRole("combobox"));
|
|
166
|
+
await user.click(rendered.getByRole("option", { name: /fin/i }));
|
|
167
|
+
|
|
168
|
+
await waitFor(() => {
|
|
169
|
+
const payloads = dispatch.mock.calls.map(
|
|
170
|
+
([action]) => action?.payload ?? action,
|
|
171
|
+
);
|
|
172
|
+
expect(payloads.some((payload) => payload?.user_group_id === 10)).toBe(
|
|
173
|
+
true,
|
|
174
|
+
);
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
const payloads = dispatch.mock.calls.map(
|
|
178
|
+
([action]) => action?.payload ?? action,
|
|
179
|
+
);
|
|
180
|
+
expect(payloads.some((payload) => payload?.id === "group:10")).toBe(false);
|
|
181
|
+
});
|
|
77
182
|
});
|
|
@@ -150,4 +150,130 @@ describe("<StructureGrantDropdown />", () => {
|
|
|
150
150
|
|
|
151
151
|
expect(mockHistory).toHaveBeenCalledWith("/grantRequests/8");
|
|
152
152
|
});
|
|
153
|
+
|
|
154
|
+
it("shows cancel and view request when current user created the group grant request", async () => {
|
|
155
|
+
const grantRequest = {
|
|
156
|
+
id: 8,
|
|
157
|
+
group: {
|
|
158
|
+
user_group_id: 10,
|
|
159
|
+
created_by_id: 7,
|
|
160
|
+
_embedded: {
|
|
161
|
+
user_group: { id: 10, name: "finance" },
|
|
162
|
+
created_by: { user_name: "ada" },
|
|
163
|
+
},
|
|
164
|
+
},
|
|
165
|
+
};
|
|
166
|
+
const props = {
|
|
167
|
+
...propsBuilder({}),
|
|
168
|
+
grantRequest,
|
|
169
|
+
grantRequestStatus: "pending",
|
|
170
|
+
};
|
|
171
|
+
const rendered = render(<StructureGrantDropdown {...props} />, {
|
|
172
|
+
state: { authentication: { user_name: "ada" } },
|
|
173
|
+
});
|
|
174
|
+
await waitForLoad(rendered);
|
|
175
|
+
|
|
176
|
+
expect(rendered.getByText(/cancel_grant_request/i)).toBeInTheDocument();
|
|
177
|
+
expect(
|
|
178
|
+
rendered.getByText(/grant.actions.viewrequest.confirmation.header/i),
|
|
179
|
+
).toBeInTheDocument();
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
it("does not show cancel when current user is a group member and not the creator", async () => {
|
|
183
|
+
const grantRequest = {
|
|
184
|
+
id: 8,
|
|
185
|
+
group: {
|
|
186
|
+
user_group_id: 10,
|
|
187
|
+
created_by_id: 7,
|
|
188
|
+
_embedded: {
|
|
189
|
+
user_group: { id: 10, name: "finance" },
|
|
190
|
+
created_by: { user_name: "ada" },
|
|
191
|
+
},
|
|
192
|
+
},
|
|
193
|
+
};
|
|
194
|
+
const props = {
|
|
195
|
+
...propsBuilder({}),
|
|
196
|
+
grantRequest,
|
|
197
|
+
grantRequestStatus: "pending",
|
|
198
|
+
};
|
|
199
|
+
const rendered = render(<StructureGrantDropdown {...props} />, {
|
|
200
|
+
state: { authentication: { user_name: "bob" } },
|
|
201
|
+
});
|
|
202
|
+
await waitForLoad(rendered);
|
|
203
|
+
|
|
204
|
+
expect(
|
|
205
|
+
rendered.queryByText(/cancel_grant_request/i),
|
|
206
|
+
).not.toBeInTheDocument();
|
|
207
|
+
expect(
|
|
208
|
+
rendered.getByText(/grant.actions.viewrequest.confirmation.header/i),
|
|
209
|
+
).toBeInTheDocument();
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
it("shows cancel when grant request is for a user", async () => {
|
|
213
|
+
const status = "pending";
|
|
214
|
+
const grantRequest = {
|
|
215
|
+
status: { status },
|
|
216
|
+
};
|
|
217
|
+
const props = {
|
|
218
|
+
...propsBuilder({}),
|
|
219
|
+
grantRequest,
|
|
220
|
+
grantRequestStatus: status,
|
|
221
|
+
};
|
|
222
|
+
const rendered = render(<StructureGrantDropdown {...props} />, {
|
|
223
|
+
state: { authentication: { user_name: "bob" } },
|
|
224
|
+
});
|
|
225
|
+
await waitForLoad(rendered);
|
|
226
|
+
|
|
227
|
+
expect(rendered.getByText(/cancel_grant_request/i)).toBeInTheDocument();
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
it("shows cancel and view request when current user created the group grant request with camelCase group", async () => {
|
|
231
|
+
const grantRequest = {
|
|
232
|
+
id: 8,
|
|
233
|
+
group: {
|
|
234
|
+
userGroupId: 10,
|
|
235
|
+
createdBy: { userName: "ada" },
|
|
236
|
+
},
|
|
237
|
+
};
|
|
238
|
+
const props = {
|
|
239
|
+
...propsBuilder({}),
|
|
240
|
+
grantRequest,
|
|
241
|
+
grantRequestStatus: "pending",
|
|
242
|
+
};
|
|
243
|
+
const rendered = render(<StructureGrantDropdown {...props} />, {
|
|
244
|
+
state: { authentication: { user_name: "ada" } },
|
|
245
|
+
});
|
|
246
|
+
await waitForLoad(rendered);
|
|
247
|
+
|
|
248
|
+
expect(rendered.getByText(/cancel_grant_request/i)).toBeInTheDocument();
|
|
249
|
+
expect(
|
|
250
|
+
rendered.getByText(/grant.actions.viewrequest.confirmation.header/i),
|
|
251
|
+
).toBeInTheDocument();
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
it("does not show cancel when current user is a group member and not the creator with camelCase group", async () => {
|
|
255
|
+
const grantRequest = {
|
|
256
|
+
id: 8,
|
|
257
|
+
group: {
|
|
258
|
+
userGroupId: 10,
|
|
259
|
+
createdBy: { userName: "ada" },
|
|
260
|
+
},
|
|
261
|
+
};
|
|
262
|
+
const props = {
|
|
263
|
+
...propsBuilder({}),
|
|
264
|
+
grantRequest,
|
|
265
|
+
grantRequestStatus: "pending",
|
|
266
|
+
};
|
|
267
|
+
const rendered = render(<StructureGrantDropdown {...props} />, {
|
|
268
|
+
state: { authentication: { user_name: "bob" } },
|
|
269
|
+
});
|
|
270
|
+
await waitForLoad(rendered);
|
|
271
|
+
|
|
272
|
+
expect(
|
|
273
|
+
rendered.queryByText(/cancel_grant_request/i),
|
|
274
|
+
).not.toBeInTheDocument();
|
|
275
|
+
expect(
|
|
276
|
+
rendered.getByText(/grant.actions.viewrequest.confirmation.header/i),
|
|
277
|
+
).toBeInTheDocument();
|
|
278
|
+
});
|
|
153
279
|
});
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import
|
|
1
|
+
import userEvent from "@testing-library/user-event";
|
|
2
|
+
import { render, waitForLoad } from "@truedat/test/render";
|
|
2
3
|
import SearchContextWrapper from "@truedat/core/components/common/SearchContextWrapper";
|
|
3
4
|
import StructureGrantListButton from "../StructureGrantListButton";
|
|
5
|
+
import { createGrantRequestStatus } from "../../routines";
|
|
4
6
|
|
|
5
7
|
const structure = {
|
|
6
8
|
id: 151596,
|
|
@@ -82,4 +84,37 @@ describe("<StructureGrantListButton />", () => {
|
|
|
82
84
|
);
|
|
83
85
|
expect(container).toMatchSnapshot();
|
|
84
86
|
});
|
|
87
|
+
|
|
88
|
+
it("cancelling a grant request refreshes the search results", async () => {
|
|
89
|
+
const user = userEvent.setup({ delay: null });
|
|
90
|
+
const refreshSearch = jest.fn();
|
|
91
|
+
const dispatch = jest.fn();
|
|
92
|
+
const pendingStructure = {
|
|
93
|
+
...structure,
|
|
94
|
+
my_grant_request: { status: "pending" },
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
const rendered = render(
|
|
98
|
+
<SearchContextWrapper
|
|
99
|
+
props={{ filterParams: { foo: "bar" }, refreshSearch }}
|
|
100
|
+
>
|
|
101
|
+
<StructureGrantListButton structure={pendingStructure} />
|
|
102
|
+
</SearchContextWrapper>,
|
|
103
|
+
{ ...renderOpts, dispatch },
|
|
104
|
+
);
|
|
105
|
+
await waitForLoad(rendered);
|
|
106
|
+
|
|
107
|
+
await user.click(rendered.getByText(/cancel_grant_request/i));
|
|
108
|
+
await user.click(
|
|
109
|
+
rendered.getByRole("button", { name: /modal-affirmative-action/i }),
|
|
110
|
+
);
|
|
111
|
+
|
|
112
|
+
const cancelAction = dispatch.mock.calls.find(
|
|
113
|
+
([action]) => action.type === createGrantRequestStatus().type,
|
|
114
|
+
);
|
|
115
|
+
const { onSuccess } = cancelAction[0].payload;
|
|
116
|
+
expect(onSuccess).toBeDefined();
|
|
117
|
+
onSuccess();
|
|
118
|
+
expect(refreshSearch).toHaveBeenCalled();
|
|
119
|
+
});
|
|
85
120
|
});
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { waitFor } from "@testing-library/react";
|
|
2
|
-
import
|
|
2
|
+
import userEvent from "@testing-library/user-event";
|
|
3
|
+
import { render, waitForLoad } from "@truedat/test/render";
|
|
3
4
|
import { LATEST_GRANT_REQUEST_BY_DS_QUERY } from "../../api/queries";
|
|
4
5
|
import StructureGrantSummaryButton from "../StructureGrantSummaryButton";
|
|
6
|
+
import { createGrantRequestStatus } from "../../routines";
|
|
5
7
|
import en from "../../messages/en";
|
|
6
8
|
|
|
7
9
|
const latestGrantMockBuilder = (status) => ({
|
|
@@ -16,6 +18,8 @@ const latestGrantMockBuilder = (status) => ({
|
|
|
16
18
|
grant: {
|
|
17
19
|
id: 1,
|
|
18
20
|
},
|
|
21
|
+
userGroupId: null,
|
|
22
|
+
createdBy: null,
|
|
19
23
|
},
|
|
20
24
|
status: { status },
|
|
21
25
|
}
|
|
@@ -121,4 +125,88 @@ describe("<StructureGrantSummaryButton />", () => {
|
|
|
121
125
|
await expectToRenderRequestButton(container, getByRole);
|
|
122
126
|
expect(container).toMatchSnapshot();
|
|
123
127
|
});
|
|
128
|
+
|
|
129
|
+
it("requests userGroupId and createdBy userName in latest grant request by data structure query", () => {
|
|
130
|
+
const query = LATEST_GRANT_REQUEST_BY_DS_QUERY.loc.source.body;
|
|
131
|
+
expect(query).toContain("userGroupId");
|
|
132
|
+
expect(query).toContain("createdBy");
|
|
133
|
+
expect(query).toContain("userName");
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
it("cancelling refetches the latest grant request of the structure", async () => {
|
|
137
|
+
const user = userEvent.setup({ delay: null });
|
|
138
|
+
const dispatch = jest.fn();
|
|
139
|
+
|
|
140
|
+
const pendingMock = {
|
|
141
|
+
request: { query: LATEST_GRANT_REQUEST_BY_DS_QUERY },
|
|
142
|
+
result: {
|
|
143
|
+
data: {
|
|
144
|
+
latestGrantRequest: {
|
|
145
|
+
id: 1,
|
|
146
|
+
requestType: "ACCESS",
|
|
147
|
+
group: {
|
|
148
|
+
grant: null,
|
|
149
|
+
userGroupId: null,
|
|
150
|
+
createdBy: null,
|
|
151
|
+
},
|
|
152
|
+
status: { status: "pending" },
|
|
153
|
+
},
|
|
154
|
+
},
|
|
155
|
+
},
|
|
156
|
+
};
|
|
157
|
+
const cancelledMock = {
|
|
158
|
+
request: { query: LATEST_GRANT_REQUEST_BY_DS_QUERY },
|
|
159
|
+
result: {
|
|
160
|
+
data: {
|
|
161
|
+
latestGrantRequest: {
|
|
162
|
+
id: 1,
|
|
163
|
+
requestType: "ACCESS",
|
|
164
|
+
group: {
|
|
165
|
+
grant: null,
|
|
166
|
+
userGroupId: null,
|
|
167
|
+
createdBy: null,
|
|
168
|
+
},
|
|
169
|
+
status: { status: "cancelled" },
|
|
170
|
+
},
|
|
171
|
+
},
|
|
172
|
+
},
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
const rendered = render(<StructureGrantSummaryButton />, {
|
|
176
|
+
mocks: [pendingMock, cancelledMock],
|
|
177
|
+
state: {
|
|
178
|
+
structure: { grant: null },
|
|
179
|
+
userPermissions: { request_grant: true },
|
|
180
|
+
},
|
|
181
|
+
messages: { en },
|
|
182
|
+
dispatch,
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
await waitFor(() => {
|
|
186
|
+
expect(rendered.queryByText(/lazy/i)).not.toBeInTheDocument();
|
|
187
|
+
expect(
|
|
188
|
+
rendered.container.querySelector(".loader"),
|
|
189
|
+
).not.toBeInTheDocument();
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
expectToRenderDropdownComponent(rendered.container);
|
|
193
|
+
|
|
194
|
+
await user.click(rendered.getByText(/cancel request/i));
|
|
195
|
+
await user.click(
|
|
196
|
+
rendered.getByRole("button", { name: /modal-affirmative-action/i }),
|
|
197
|
+
);
|
|
198
|
+
|
|
199
|
+
const cancelAction = dispatch.mock.calls.find(
|
|
200
|
+
([action]) => action.type === createGrantRequestStatus().type,
|
|
201
|
+
);
|
|
202
|
+
const { onSuccess } = cancelAction[0].payload;
|
|
203
|
+
expect(onSuccess).toBeDefined();
|
|
204
|
+
onSuccess();
|
|
205
|
+
|
|
206
|
+
await waitFor(() => {
|
|
207
|
+
expect(
|
|
208
|
+
rendered.container.getElementsByClassName("dropdown"),
|
|
209
|
+
).toHaveLength(0);
|
|
210
|
+
});
|
|
211
|
+
});
|
|
124
212
|
});
|
|
@@ -50,6 +50,15 @@ exports[`<GrantRequest /> matches the latest snapshot 1`] = `
|
|
|
50
50
|
</div>
|
|
51
51
|
</h2>
|
|
52
52
|
</div>
|
|
53
|
+
<div
|
|
54
|
+
class="right aligned four wide column"
|
|
55
|
+
>
|
|
56
|
+
<button
|
|
57
|
+
class="ui button"
|
|
58
|
+
>
|
|
59
|
+
structure.grant.cancel_grant_request
|
|
60
|
+
</button>
|
|
61
|
+
</div>
|
|
53
62
|
</div>
|
|
54
63
|
<div
|
|
55
64
|
class="ui big very relaxed list"
|
|
@@ -319,6 +328,25 @@ exports[`<GrantRequest /> matches the latest snapshot with approve actions 1`] =
|
|
|
319
328
|
</div>
|
|
320
329
|
</h2>
|
|
321
330
|
</div>
|
|
331
|
+
<div
|
|
332
|
+
class="right aligned four wide column"
|
|
333
|
+
>
|
|
334
|
+
<button
|
|
335
|
+
class="ui primary button button icon group-actions"
|
|
336
|
+
>
|
|
337
|
+
grantRequest.actions.approve
|
|
338
|
+
</button>
|
|
339
|
+
<button
|
|
340
|
+
class="ui secondary button button icon group-actions"
|
|
341
|
+
>
|
|
342
|
+
grantRequest.actions.reject
|
|
343
|
+
</button>
|
|
344
|
+
<button
|
|
345
|
+
class="ui button"
|
|
346
|
+
>
|
|
347
|
+
structure.grant.cancel_grant_request
|
|
348
|
+
</button>
|
|
349
|
+
</div>
|
|
322
350
|
</div>
|
|
323
351
|
<div
|
|
324
352
|
class="ui big very relaxed list"
|
package/src/messages/en.js
CHANGED
|
@@ -131,6 +131,9 @@ export default {
|
|
|
131
131
|
"grantRequest.header.status": "Status",
|
|
132
132
|
"grantRequest.header.updated_at": "Updated",
|
|
133
133
|
"grantRequest.header.user": "User",
|
|
134
|
+
"grantRequest.header.group": "User group",
|
|
135
|
+
"grantRequest.deleted.user": "Deleted user",
|
|
136
|
+
"grantRequest.deleted.group": "Deleted group",
|
|
134
137
|
"grantRequest.header.createdBy": "Created by",
|
|
135
138
|
"grantRequest.header.create": "Create grant request",
|
|
136
139
|
"grantRequest.header.type": "Request type",
|
|
@@ -161,6 +164,8 @@ export default {
|
|
|
161
164
|
"grantRequests.subheader.approve": "Grant requests pending approval",
|
|
162
165
|
"grantRequests.subheader.me": "Grant requests requested by me",
|
|
163
166
|
"grantRequests.subheader": "Pending approval grant requests",
|
|
167
|
+
"grantRequests.props.user_full_name": "User",
|
|
168
|
+
"grantRequests.props.user_or_group": "User / Group",
|
|
164
169
|
"grants.actions.download.popup": "Select a grant",
|
|
165
170
|
"grants.actions.download.tooltip": "Download to XLSX",
|
|
166
171
|
"grants.header": "Grants",
|
package/src/messages/es.js
CHANGED
|
@@ -134,6 +134,9 @@ export default {
|
|
|
134
134
|
"grantRequest.header.status": "Estado",
|
|
135
135
|
"grantRequest.header.updated_at": "Actualizado",
|
|
136
136
|
"grantRequest.header.user": "Usuario",
|
|
137
|
+
"grantRequest.header.group": "Grupo de usuarios",
|
|
138
|
+
"grantRequest.deleted.user": "Usuario eliminado",
|
|
139
|
+
"grantRequest.deleted.group": "Grupo eliminado",
|
|
137
140
|
"grantRequest.header.createdBy": "Creado por",
|
|
138
141
|
"grantRequest.header.create": "Crear petición de acceso",
|
|
139
142
|
"grantRequest.header.type": "Tipo de petición",
|
|
@@ -165,6 +168,8 @@ export default {
|
|
|
165
168
|
"Peticiones de acceso pendientes de aprobación",
|
|
166
169
|
"grantRequests.subheader.me": "Peticiones de acceso demandadas por mí",
|
|
167
170
|
"grantRequests.subheader": "Peticiones de acceso pendientes de aprobación",
|
|
171
|
+
"grantRequests.props.user_full_name": "Usuario",
|
|
172
|
+
"grantRequests.props.user_or_group": "Usuario / Grupo",
|
|
168
173
|
"grants.actions.download.popup": "Seleccione un acceso",
|
|
169
174
|
"grants.actions.download.tooltip": "Descargar a XLSX",
|
|
170
175
|
"grants.header": "Accesos",
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
initGroupTemplates,
|
|
10
10
|
selectGrantRequestTemplateForGroup,
|
|
11
11
|
updateGrantRequestTemplateContentForGroup,
|
|
12
|
+
updateGrantRequestUser,
|
|
12
13
|
} from "../../routines";
|
|
13
14
|
import { initialState, grantRequestsCart } from "../grantRequestsCart";
|
|
14
15
|
|
|
@@ -416,4 +417,15 @@ describe("reducers: grantRequestsCart", () => {
|
|
|
416
417
|
it("should ignore unknown actions", () => {
|
|
417
418
|
expect(grantRequestsCart(initialState, { type: "FOO" })).toBe(initialState);
|
|
418
419
|
});
|
|
420
|
+
|
|
421
|
+
it("stores user_group_id and clears user id when selecting a user group", () => {
|
|
422
|
+
const state = grantRequestsCart(initialState, {
|
|
423
|
+
type: updateGrantRequestUser.TRIGGER,
|
|
424
|
+
payload: { user_group_id: 10, valid: true },
|
|
425
|
+
});
|
|
426
|
+
|
|
427
|
+
expect(state.user_group_id).toBe(10);
|
|
428
|
+
expect([null, undefined, ""]).toContain(state.user?.id);
|
|
429
|
+
expect(state.user?.id).not.toBe("group:10");
|
|
430
|
+
});
|
|
419
431
|
});
|
|
@@ -22,6 +22,7 @@ const initialState = {
|
|
|
22
22
|
templateContent: {},
|
|
23
23
|
modificationGrant: null,
|
|
24
24
|
user: { id: null, valid: true },
|
|
25
|
+
user_group_id: null,
|
|
25
26
|
groupUsers: {},
|
|
26
27
|
};
|
|
27
28
|
const mapPayload = (payload) =>
|
|
@@ -77,8 +78,19 @@ const grantRequestsCart = (state = initialState, { type, payload }) => {
|
|
|
77
78
|
validCart: state.template && _.size(valid) === 0,
|
|
78
79
|
};
|
|
79
80
|
case updateGrantRequestUser.TRIGGER:
|
|
81
|
+
if (!_.isNil(payload.user_group_id)) {
|
|
82
|
+
return {
|
|
83
|
+
...state,
|
|
84
|
+
user_group_id: payload.user_group_id,
|
|
85
|
+
user: {
|
|
86
|
+
id: null,
|
|
87
|
+
valid: payload.valid,
|
|
88
|
+
},
|
|
89
|
+
};
|
|
90
|
+
}
|
|
80
91
|
return {
|
|
81
92
|
...state,
|
|
93
|
+
user_group_id: null,
|
|
82
94
|
user: {
|
|
83
95
|
id: payload.id,
|
|
84
96
|
valid: payload.valid,
|
|
@@ -5,7 +5,11 @@ import {
|
|
|
5
5
|
createGrantRequestStatusRequestSaga,
|
|
6
6
|
createGrantRequestStatusSaga,
|
|
7
7
|
} from "../createGrantRequestStatus";
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
createGrantRequestStatus,
|
|
10
|
+
fetchStructure,
|
|
11
|
+
fetchStructures,
|
|
12
|
+
} from "../../routines";
|
|
9
13
|
import { API_GRANT_REQUEST_STATUS } from "../../api";
|
|
10
14
|
|
|
11
15
|
describe("sagas: createGrantRequestStatusRequestSaga", () => {
|
|
@@ -79,4 +83,66 @@ describe("sagas: createGrantRequestStatusSaga", () => {
|
|
|
79
83
|
.isDone();
|
|
80
84
|
}).not.toThrow();
|
|
81
85
|
});
|
|
86
|
+
|
|
87
|
+
it("calls onSuccess after refreshing the structure", () => {
|
|
88
|
+
const onSuccess = jest.fn();
|
|
89
|
+
const payloadWithOnSuccess = {
|
|
90
|
+
grantRequest: { id: "8", request_type: "ACCESS" },
|
|
91
|
+
status: "cancelled",
|
|
92
|
+
structureId: "3",
|
|
93
|
+
onSuccess,
|
|
94
|
+
};
|
|
95
|
+
const url = compile(API_GRANT_REQUEST_STATUS)({ id: "8" });
|
|
96
|
+
|
|
97
|
+
expect(() => {
|
|
98
|
+
testSaga(createGrantRequestStatusSaga, {
|
|
99
|
+
payload: payloadWithOnSuccess,
|
|
100
|
+
})
|
|
101
|
+
.next()
|
|
102
|
+
.put(createGrantRequestStatus.request({ status: "cancelled" }))
|
|
103
|
+
.next()
|
|
104
|
+
.call(apiJsonPost, url, { status: "cancelled" }, JSON_OPTS)
|
|
105
|
+
.next({ data: "result" })
|
|
106
|
+
.put(createGrantRequestStatus.success("result"))
|
|
107
|
+
.next()
|
|
108
|
+
.put(fetchStructure.trigger({ id: "3" }))
|
|
109
|
+
.next()
|
|
110
|
+
.call(onSuccess)
|
|
111
|
+
.next()
|
|
112
|
+
.put(createGrantRequestStatus.fulfill())
|
|
113
|
+
.next()
|
|
114
|
+
.isDone();
|
|
115
|
+
}).not.toThrow();
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
it("calls onSuccess after refreshing the previous structure query", () => {
|
|
119
|
+
const onSuccess = jest.fn();
|
|
120
|
+
const payloadWithOnSuccess = {
|
|
121
|
+
grantRequest: { id: "8", request_type: "ACCESS" },
|
|
122
|
+
status: "cancelled",
|
|
123
|
+
previousStructureQuery: { foo: "bar" },
|
|
124
|
+
onSuccess,
|
|
125
|
+
};
|
|
126
|
+
const url = compile(API_GRANT_REQUEST_STATUS)({ id: "8" });
|
|
127
|
+
|
|
128
|
+
expect(() => {
|
|
129
|
+
testSaga(createGrantRequestStatusSaga, {
|
|
130
|
+
payload: payloadWithOnSuccess,
|
|
131
|
+
})
|
|
132
|
+
.next()
|
|
133
|
+
.put(createGrantRequestStatus.request({ status: "cancelled" }))
|
|
134
|
+
.next()
|
|
135
|
+
.call(apiJsonPost, url, { status: "cancelled" }, JSON_OPTS)
|
|
136
|
+
.next({ data: "result" })
|
|
137
|
+
.put(createGrantRequestStatus.success("result"))
|
|
138
|
+
.next()
|
|
139
|
+
.put(fetchStructures.trigger({ foo: "bar" }))
|
|
140
|
+
.next()
|
|
141
|
+
.call(onSuccess)
|
|
142
|
+
.next()
|
|
143
|
+
.put(createGrantRequestStatus.fulfill())
|
|
144
|
+
.next()
|
|
145
|
+
.isDone();
|
|
146
|
+
}).not.toThrow();
|
|
147
|
+
});
|
|
82
148
|
});
|
|
@@ -92,3 +92,29 @@ describe("sagas: fetchGrantRequestSaga", () => {
|
|
|
92
92
|
}).not.toThrow();
|
|
93
93
|
});
|
|
94
94
|
});
|
|
95
|
+
|
|
96
|
+
describe("sagas: fetchGrantRequestSaga with numeric id", () => {
|
|
97
|
+
const data = {
|
|
98
|
+
data_structure_id: "1",
|
|
99
|
+
medatada: { foo: "bar " },
|
|
100
|
+
filters: { bar: "baz" },
|
|
101
|
+
};
|
|
102
|
+
const id = 4751;
|
|
103
|
+
const payload = { id };
|
|
104
|
+
const url = compile(API_GRANT_REQUEST)({ id: `${id}` });
|
|
105
|
+
it("should put a success action when id is numeric", () => {
|
|
106
|
+
expect(() => {
|
|
107
|
+
testSaga(fetchGrantRequestSaga, { payload })
|
|
108
|
+
.next()
|
|
109
|
+
.put(fetchGrantRequest.request())
|
|
110
|
+
.next()
|
|
111
|
+
.call(apiJson, url, JSON_OPTS)
|
|
112
|
+
.next({ data })
|
|
113
|
+
.put(fetchGrantRequest.success(data))
|
|
114
|
+
.next()
|
|
115
|
+
.put(fetchGrantRequest.fulfill())
|
|
116
|
+
.next()
|
|
117
|
+
.isDone();
|
|
118
|
+
}).not.toThrow();
|
|
119
|
+
});
|
|
120
|
+
});
|
|
@@ -16,6 +16,7 @@ export function* createGrantRequestStatusSaga({ payload }) {
|
|
|
16
16
|
status,
|
|
17
17
|
structureId,
|
|
18
18
|
previousStructureQuery,
|
|
19
|
+
onSuccess,
|
|
19
20
|
} = payload;
|
|
20
21
|
|
|
21
22
|
const url = compile(API_GRANT_REQUEST_STATUS)({
|
|
@@ -40,6 +41,10 @@ export function* createGrantRequestStatusSaga({ payload }) {
|
|
|
40
41
|
},
|
|
41
42
|
});
|
|
42
43
|
}
|
|
44
|
+
|
|
45
|
+
if (typeof onSuccess === "function") {
|
|
46
|
+
yield call(onSuccess);
|
|
47
|
+
}
|
|
43
48
|
} catch (error) {
|
|
44
49
|
if (error.response) {
|
|
45
50
|
const { status, data } = error.response;
|
|
@@ -6,7 +6,7 @@ import { API_GRANT_REQUEST } from "../api";
|
|
|
6
6
|
|
|
7
7
|
export function* fetchGrantRequestSaga({ payload }) {
|
|
8
8
|
try {
|
|
9
|
-
const url = compile(API_GRANT_REQUEST)(payload);
|
|
9
|
+
const url = compile(API_GRANT_REQUEST)({ id: payload?.id?.toString() });
|
|
10
10
|
yield put(fetchGrantRequest.request());
|
|
11
11
|
const { data } = yield call(apiJson, url, JSON_OPTS);
|
|
12
12
|
yield put(fetchGrantRequest.success(data));
|