@truedat/dd 8.9.1 → 8.10.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.
- package/package.json +3 -3
- package/src/api.js +2 -0
- package/src/components/GrantRequestBulkActions.js +68 -33
- package/src/components/GrantRequestBulkApprovalPopup.js +25 -14
- package/src/components/GrantRequestRow.js +1 -5
- package/src/components/GrantRequestsDownloadButton.js +81 -0
- package/src/components/GrantRequestsLabelResults.js +17 -11
- package/src/components/GrantRequestsSearchResults.js +72 -62
- package/src/components/GrantRequestsTable.js +61 -57
- package/src/components/__tests__/GrantRequestBulkActions.spec.js +4 -0
- package/src/components/__tests__/GrantRequestRow.spec.js +8 -4
- package/src/components/__tests__/GrantRequestsDownloadButton.spec.js +198 -0
- package/src/components/__tests__/__snapshots__/GrantRequestBulkActions.spec.js.snap +17 -3
- package/src/components/__tests__/__snapshots__/GrantRequestBulkApprovalPopup.spec.js.snap +1 -1
- package/src/components/__tests__/__snapshots__/GrantRequestsDownloadButton.spec.js.snap +16 -0
- package/src/components/__tests__/__snapshots__/GrantRequestsLabelResults.spec.js.snap +6 -1
- package/src/components/__tests__/__snapshots__/GrantRequestsSearchResults.spec.js.snap +128 -100
- package/src/hooks/useGrantRequest.js +20 -1
|
@@ -26,65 +26,69 @@ export const GrantRequestsTable = ({
|
|
|
26
26
|
|
|
27
27
|
const grantRequests = _.propOr([], "data")(searchData);
|
|
28
28
|
|
|
29
|
+
const showEmpty = _.isEmpty(grantRequests) && !loading;
|
|
30
|
+
|
|
29
31
|
return (
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
<Table
|
|
33
|
-
|
|
34
|
-
<Table.
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
onChange={addAll}
|
|
40
|
-
checked={checkedAll}
|
|
41
|
-
/>
|
|
42
|
-
</Table.HeaderCell>
|
|
43
|
-
) : null}
|
|
44
|
-
{columns.map((column, key) => (
|
|
45
|
-
<Table.HeaderCell
|
|
46
|
-
key={key}
|
|
47
|
-
width={column.width}
|
|
48
|
-
content={formatMessage({
|
|
49
|
-
id: `grantRequest.header.${column.name}`,
|
|
50
|
-
defaultMessage: column.name,
|
|
51
|
-
})}
|
|
52
|
-
sorted={
|
|
53
|
-
_.path("sort.name")(column) === sortColumn
|
|
54
|
-
? sortDirection
|
|
55
|
-
: null
|
|
56
|
-
}
|
|
57
|
-
className={_.path("sort.name")(column) ? "" : "disabled"}
|
|
58
|
-
onClick={() =>
|
|
59
|
-
handleSortSelection(_.path("sort.name")(column))
|
|
60
|
-
}
|
|
61
|
-
/>
|
|
62
|
-
))}
|
|
63
|
-
</Table.Row>
|
|
64
|
-
</Table.Header>
|
|
65
|
-
<Table.Body>
|
|
66
|
-
{grantRequests.map((gr, key) => (
|
|
67
|
-
<GrantRequestRow
|
|
68
|
-
key={key}
|
|
69
|
-
checked={isRowChecked && isRowChecked(gr)}
|
|
70
|
-
grantRequest={gr}
|
|
71
|
-
columns={columns}
|
|
72
|
-
approveView={approveView}
|
|
73
|
-
onCheckboxChange={() => checkRow && checkRow(gr)}
|
|
32
|
+
<Table sortable={!showEmpty} selectable={!showEmpty}>
|
|
33
|
+
<Table.Header>
|
|
34
|
+
<Table.Row>
|
|
35
|
+
{approveView ? (
|
|
36
|
+
<Table.HeaderCell textAlign="center">
|
|
37
|
+
<Checkbox
|
|
38
|
+
id="selectGrantRequest"
|
|
39
|
+
onChange={addAll}
|
|
40
|
+
checked={checkedAll}
|
|
74
41
|
/>
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
42
|
+
</Table.HeaderCell>
|
|
43
|
+
) : null}
|
|
44
|
+
{columns.map((column, key) => (
|
|
45
|
+
<Table.HeaderCell
|
|
46
|
+
key={key}
|
|
47
|
+
width={column.width}
|
|
48
|
+
content={formatMessage({
|
|
49
|
+
id: `grantRequest.header.${column.name}`,
|
|
50
|
+
defaultMessage: column.name,
|
|
51
|
+
})}
|
|
52
|
+
sorted={
|
|
53
|
+
_.path("sort.name")(column) === sortColumn
|
|
54
|
+
? sortDirection
|
|
55
|
+
: null
|
|
56
|
+
}
|
|
57
|
+
className={_.path("sort.name")(column) ? "" : "disabled"}
|
|
58
|
+
onClick={() => handleSortSelection(_.path("sort.name")(column))}
|
|
59
|
+
/>
|
|
60
|
+
))}
|
|
61
|
+
</Table.Row>
|
|
62
|
+
</Table.Header>
|
|
63
|
+
<Table.Body>
|
|
64
|
+
{showEmpty ? (
|
|
65
|
+
<Table.Row>
|
|
66
|
+
<Table.Cell
|
|
67
|
+
colSpan={columns.length + (approveView ? 1 : 0)}
|
|
68
|
+
textAlign="center"
|
|
69
|
+
>
|
|
70
|
+
<Header as="h4">
|
|
71
|
+
<Icon name="search" />
|
|
72
|
+
<Header.Content>
|
|
73
|
+
{formatMessage({ id: "grantRequests.empty" })}
|
|
74
|
+
</Header.Content>
|
|
75
|
+
</Header>
|
|
76
|
+
</Table.Cell>
|
|
77
|
+
</Table.Row>
|
|
78
|
+
) : (
|
|
79
|
+
grantRequests.map((gr, key) => (
|
|
80
|
+
<GrantRequestRow
|
|
81
|
+
key={key}
|
|
82
|
+
checked={isRowChecked && isRowChecked(gr)}
|
|
83
|
+
grantRequest={gr}
|
|
84
|
+
columns={columns}
|
|
85
|
+
approveView={approveView}
|
|
86
|
+
onCheckboxChange={() => checkRow && checkRow(gr)}
|
|
87
|
+
/>
|
|
88
|
+
))
|
|
89
|
+
)}
|
|
90
|
+
</Table.Body>
|
|
91
|
+
</Table>
|
|
88
92
|
);
|
|
89
93
|
};
|
|
90
94
|
|
|
@@ -40,6 +40,7 @@ describe("<GrantRequestBulkActions />", () => {
|
|
|
40
40
|
loading: false,
|
|
41
41
|
toggleHiddenFilterValue: jest.fn(),
|
|
42
42
|
resetFilters: jest.fn(),
|
|
43
|
+
setHiddenFilters: jest.fn(),
|
|
43
44
|
searchMust: { foo: "bar" },
|
|
44
45
|
cleanQuery: jest.fn(),
|
|
45
46
|
};
|
|
@@ -52,6 +53,7 @@ describe("<GrantRequestBulkActions />", () => {
|
|
|
52
53
|
loading: false,
|
|
53
54
|
toggleHiddenFilterValue: jest.fn(),
|
|
54
55
|
resetFilters: jest.fn(),
|
|
56
|
+
setHiddenFilters: jest.fn(),
|
|
55
57
|
searchMust: { foo: "bar" },
|
|
56
58
|
cleanQuery: jest.fn(),
|
|
57
59
|
};
|
|
@@ -88,6 +90,8 @@ describe("<GrantRequestBulkActions />", () => {
|
|
|
88
90
|
renderOpts,
|
|
89
91
|
);
|
|
90
92
|
await waitForLoad(rendered);
|
|
93
|
+
const user = userEvent.setup({ delay: null });
|
|
94
|
+
await user.click(rendered.getByRole("option", { name: /role1/i }));
|
|
91
95
|
expect(
|
|
92
96
|
rendered.getByRole("button", { name: /approve_request/i }),
|
|
93
97
|
).toBeEnabled();
|
|
@@ -5,11 +5,11 @@ import { linkTo } from "@truedat/core/routes";
|
|
|
5
5
|
|
|
6
6
|
import GrantRequestRow from "../GrantRequestRow";
|
|
7
7
|
|
|
8
|
-
const
|
|
8
|
+
const mockNavigate = jest.fn();
|
|
9
9
|
|
|
10
10
|
jest.mock("react-router", () => ({
|
|
11
11
|
...jest.requireActual("react-router"),
|
|
12
|
-
useNavigate: () =>
|
|
12
|
+
useNavigate: () => mockNavigate,
|
|
13
13
|
}));
|
|
14
14
|
|
|
15
15
|
const columns = [
|
|
@@ -33,6 +33,10 @@ describe("<GrantRequestRow />", () => {
|
|
|
33
33
|
const onCheckboxChange = jest.fn();
|
|
34
34
|
const onClick = jest.fn();
|
|
35
35
|
|
|
36
|
+
beforeEach(() => {
|
|
37
|
+
mockNavigate.mockClear();
|
|
38
|
+
});
|
|
39
|
+
|
|
36
40
|
const props = {
|
|
37
41
|
active: true,
|
|
38
42
|
checked: true,
|
|
@@ -90,7 +94,7 @@ describe("<GrantRequestRow />", () => {
|
|
|
90
94
|
});
|
|
91
95
|
});
|
|
92
96
|
|
|
93
|
-
it("navigates to grant request", async () => {
|
|
97
|
+
it("navigates to grant request in the same window", async () => {
|
|
94
98
|
const rendered = render(
|
|
95
99
|
<table>
|
|
96
100
|
<tbody>
|
|
@@ -105,6 +109,6 @@ describe("<GrantRequestRow />", () => {
|
|
|
105
109
|
});
|
|
106
110
|
|
|
107
111
|
await user.click(rendered.queryByText(/blah/i));
|
|
108
|
-
expect(
|
|
112
|
+
expect(mockNavigate).toHaveBeenCalledWith(linkTo.GRANT_REQUEST({ id: 1 }));
|
|
109
113
|
});
|
|
110
114
|
});
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import { render, waitForLoad } from "@truedat/test/render";
|
|
2
|
+
import { screen } from "@testing-library/react";
|
|
3
|
+
import SearchContext from "@truedat/core/search/SearchContext";
|
|
4
|
+
import { GrantRequestsDownloadButton } from "../GrantRequestsDownloadButton";
|
|
5
|
+
|
|
6
|
+
jest.mock("@truedat/dd/hooks/useGrantRequest", () => ({
|
|
7
|
+
useGrantRequestsDownload: jest.fn(() => ({
|
|
8
|
+
trigger: jest.fn(),
|
|
9
|
+
isMutating: false,
|
|
10
|
+
})),
|
|
11
|
+
}));
|
|
12
|
+
|
|
13
|
+
describe("<GrantRequestsDownloadButton />", () => {
|
|
14
|
+
const renderOpts = {
|
|
15
|
+
messages: {
|
|
16
|
+
en: {
|
|
17
|
+
"grantRequest.actions.download.tooltip": "Descargar / Download",
|
|
18
|
+
"grantRequest.actions.download.popup":
|
|
19
|
+
"Search or apply a filter to download grant requests",
|
|
20
|
+
"grantRequests.props.current_status": "Status",
|
|
21
|
+
"grantRequests.props.user_full_name": "User",
|
|
22
|
+
"grantRequests.props.created_by_full_name": "Created by",
|
|
23
|
+
"grantRequests.props.structure_external_id": "Structure",
|
|
24
|
+
"grantRequests.props.domains": "Domains",
|
|
25
|
+
"grantRequests.props.system_name": "System",
|
|
26
|
+
"grantRequests.props.structure_path": "Path",
|
|
27
|
+
"grantRequests.props.request_type": "Request type",
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const buildSearchContext = (filterParams = {}) => ({
|
|
33
|
+
searchData: {
|
|
34
|
+
data: [
|
|
35
|
+
{
|
|
36
|
+
id: 1,
|
|
37
|
+
current_status: "pending",
|
|
38
|
+
user: { full_name: "Jane Doe" },
|
|
39
|
+
created_by: { full_name: "Admin" },
|
|
40
|
+
data_structure_version: {
|
|
41
|
+
name: "country",
|
|
42
|
+
path: ["postgres", "public"],
|
|
43
|
+
domain: { name: "demo", id: 5 },
|
|
44
|
+
system: { name: "PostgreSQL", id: 7 },
|
|
45
|
+
external_id: "postgres/postgres/public/country",
|
|
46
|
+
data_structure_id: 241939,
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
],
|
|
50
|
+
},
|
|
51
|
+
loading: false,
|
|
52
|
+
filterParams,
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it("matches the latest snapshot", async () => {
|
|
56
|
+
const props = {
|
|
57
|
+
hasFilterApplied: true,
|
|
58
|
+
searchBy: "approve",
|
|
59
|
+
setDownloading: jest.fn(),
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
const rendered = render(
|
|
63
|
+
<SearchContext value={buildSearchContext({ status: ["pending"] })}>
|
|
64
|
+
<GrantRequestsDownloadButton {...props} />
|
|
65
|
+
</SearchContext>,
|
|
66
|
+
renderOpts,
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
await waitForLoad(rendered);
|
|
70
|
+
expect(rendered.container).toMatchSnapshot();
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it("is enabled if there are results and a filter applied", async () => {
|
|
74
|
+
const props = {
|
|
75
|
+
hasFilterApplied: true,
|
|
76
|
+
searchBy: "all",
|
|
77
|
+
setDownloading: jest.fn(),
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
render(
|
|
81
|
+
<SearchContext value={buildSearchContext({ status: ["pending"] })}>
|
|
82
|
+
<GrantRequestsDownloadButton {...props} />
|
|
83
|
+
</SearchContext>,
|
|
84
|
+
renderOpts,
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
const button = await screen.findByRole("button");
|
|
88
|
+
expect(button).toBeEnabled();
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it("is disabled when there are no results", async () => {
|
|
92
|
+
const props = {
|
|
93
|
+
hasFilterApplied: true,
|
|
94
|
+
searchBy: "all",
|
|
95
|
+
setDownloading: jest.fn(),
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
render(
|
|
99
|
+
<SearchContext
|
|
100
|
+
value={{
|
|
101
|
+
searchData: { data: [] },
|
|
102
|
+
loading: false,
|
|
103
|
+
filterParams: { status: ["pending"] },
|
|
104
|
+
}}
|
|
105
|
+
>
|
|
106
|
+
<GrantRequestsDownloadButton {...props} />
|
|
107
|
+
</SearchContext>,
|
|
108
|
+
renderOpts,
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
const button = await screen.getByRole("button");
|
|
112
|
+
expect(button).toBeDisabled();
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
it("is disabled when no filter is applied", async () => {
|
|
116
|
+
const props = {
|
|
117
|
+
hasFilterApplied: false,
|
|
118
|
+
searchBy: "all",
|
|
119
|
+
setDownloading: jest.fn(),
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
render(
|
|
123
|
+
<SearchContext value={buildSearchContext({})}>
|
|
124
|
+
<GrantRequestsDownloadButton {...props} />
|
|
125
|
+
</SearchContext>,
|
|
126
|
+
renderOpts,
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
const button = await screen.getByRole("button");
|
|
130
|
+
expect(button).toBeDisabled();
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
it("calls triggerDownload with search_by 'approve' from approve view", async () => {
|
|
134
|
+
const triggerMock = jest.fn();
|
|
135
|
+
const grantRequestHook = require("@truedat/dd/hooks/useGrantRequest");
|
|
136
|
+
grantRequestHook.useGrantRequestsDownload.mockReturnValue({
|
|
137
|
+
trigger: triggerMock,
|
|
138
|
+
isMutating: false,
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
const props = {
|
|
142
|
+
hasFilterApplied: true,
|
|
143
|
+
searchBy: "approve",
|
|
144
|
+
setDownloading: jest.fn(),
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
render(
|
|
148
|
+
<SearchContext value={buildSearchContext({ status: ["pending"] })}>
|
|
149
|
+
<GrantRequestsDownloadButton {...props} />
|
|
150
|
+
</SearchContext>,
|
|
151
|
+
renderOpts,
|
|
152
|
+
);
|
|
153
|
+
|
|
154
|
+
const button = await screen.findByRole("button");
|
|
155
|
+
button.click();
|
|
156
|
+
|
|
157
|
+
expect(triggerMock).toHaveBeenCalledWith(
|
|
158
|
+
expect.objectContaining({
|
|
159
|
+
search_by: "approve",
|
|
160
|
+
header_labels: expect.any(Object),
|
|
161
|
+
lang: "en",
|
|
162
|
+
status: ["pending"],
|
|
163
|
+
}),
|
|
164
|
+
);
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
it("calls triggerDownload with search_by 'all' from search view", async () => {
|
|
168
|
+
const triggerMock = jest.fn();
|
|
169
|
+
const grantRequestHook = require("@truedat/dd/hooks/useGrantRequest");
|
|
170
|
+
grantRequestHook.useGrantRequestsDownload.mockReturnValue({
|
|
171
|
+
trigger: triggerMock,
|
|
172
|
+
isMutating: false,
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
const props = {
|
|
176
|
+
hasFilterApplied: true,
|
|
177
|
+
searchBy: "all",
|
|
178
|
+
setDownloading: jest.fn(),
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
render(
|
|
182
|
+
<SearchContext value={buildSearchContext({ query: "foo" })}>
|
|
183
|
+
<GrantRequestsDownloadButton {...props} />
|
|
184
|
+
</SearchContext>,
|
|
185
|
+
renderOpts,
|
|
186
|
+
);
|
|
187
|
+
|
|
188
|
+
const button = await screen.findByRole("button");
|
|
189
|
+
button.click();
|
|
190
|
+
|
|
191
|
+
expect(triggerMock).toHaveBeenCalledWith(
|
|
192
|
+
expect.objectContaining({
|
|
193
|
+
search_by: "all",
|
|
194
|
+
query: "foo",
|
|
195
|
+
}),
|
|
196
|
+
);
|
|
197
|
+
});
|
|
198
|
+
});
|
|
@@ -4,7 +4,7 @@ exports[`<GrantRequestBulkActions /> matches the latest snapshot 1`] = `
|
|
|
4
4
|
<div>
|
|
5
5
|
<div
|
|
6
6
|
aria-expanded="false"
|
|
7
|
-
class="ui selection dropdown grant-requests-bulk-role-selector"
|
|
7
|
+
class="ui selection dropdown grant-requests-bulk-role-selector "
|
|
8
8
|
role="listbox"
|
|
9
9
|
tabindex="0"
|
|
10
10
|
>
|
|
@@ -23,6 +23,20 @@ exports[`<GrantRequestBulkActions /> matches the latest snapshot 1`] = `
|
|
|
23
23
|
<div
|
|
24
24
|
class="menu transition"
|
|
25
25
|
>
|
|
26
|
+
<div
|
|
27
|
+
aria-checked="false"
|
|
28
|
+
aria-disabled="true"
|
|
29
|
+
aria-selected="false"
|
|
30
|
+
class="disabled item header"
|
|
31
|
+
role="option"
|
|
32
|
+
style="pointer-events: all;"
|
|
33
|
+
>
|
|
34
|
+
<span
|
|
35
|
+
class="text"
|
|
36
|
+
>
|
|
37
|
+
select
|
|
38
|
+
</span>
|
|
39
|
+
</div>
|
|
26
40
|
<div
|
|
27
41
|
aria-checked="true"
|
|
28
42
|
aria-selected="true"
|
|
@@ -52,12 +66,12 @@ exports[`<GrantRequestBulkActions /> matches the latest snapshot 1`] = `
|
|
|
52
66
|
</div>
|
|
53
67
|
</div>
|
|
54
68
|
<button
|
|
55
|
-
class="ui primary button button icon group-actions"
|
|
69
|
+
class="ui primary button button icon group-actions grant-requests-approval-button"
|
|
56
70
|
>
|
|
57
71
|
approve_request
|
|
58
72
|
</button>
|
|
59
73
|
<button
|
|
60
|
-
class="ui secondary button button icon group-actions"
|
|
74
|
+
class="ui secondary button button icon group-actions grant-requests-approval-button"
|
|
61
75
|
>
|
|
62
76
|
reject
|
|
63
77
|
</button>
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
exports[`<GrantRequestBulkApprovalPopup /> matches the latest snapshot 1`] = `
|
|
4
4
|
<div>
|
|
5
5
|
<button
|
|
6
|
-
class="ui primary button button icon group-actions"
|
|
6
|
+
class="ui primary button button icon group-actions grant-requests-approval-button"
|
|
7
7
|
>
|
|
8
8
|
button content
|
|
9
9
|
</button>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
+
|
|
3
|
+
exports[`<GrantRequestsDownloadButton /> matches the latest snapshot 1`] = `
|
|
4
|
+
<div>
|
|
5
|
+
<button
|
|
6
|
+
class="ui icon secondary button"
|
|
7
|
+
data-position="top right"
|
|
8
|
+
data-tooltip="Descargar / Download"
|
|
9
|
+
>
|
|
10
|
+
<i
|
|
11
|
+
aria-hidden="true"
|
|
12
|
+
class="download icon"
|
|
13
|
+
/>
|
|
14
|
+
</button>
|
|
15
|
+
</div>
|
|
16
|
+
`;
|