@truedat/dd 5.16.2 → 5.16.4

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 (87) hide show
  1. package/package.json +5 -5
  2. package/src/api.js +6 -0
  3. package/src/components/GrantRequestApprovalResults.js +40 -0
  4. package/src/components/GrantRequestBulkActions.js +136 -0
  5. package/src/components/GrantRequestBulkApprovalForm.js +69 -0
  6. package/src/components/GrantRequestBulkApprovalPopup.js +43 -0
  7. package/src/components/GrantRequestBulkRoleSelector.js +41 -0
  8. package/src/components/GrantRequestRow.js +62 -0
  9. package/src/components/GrantRequestSearchFilters.js +22 -0
  10. package/src/components/GrantRequestsFiltersLoader.js +33 -0
  11. package/src/components/GrantRequestsLabelResults.js +52 -0
  12. package/src/components/GrantRequestsSearch.js +35 -0
  13. package/src/components/GrantRequestsSearchLoader.js +47 -0
  14. package/src/components/GrantRequestsSearchResults.js +156 -0
  15. package/src/components/GrantRequestsSelectedFilters.js +54 -0
  16. package/src/components/GrantRequestsTable.js +131 -0
  17. package/src/components/GrantRoutes.js +34 -16
  18. package/src/components/Grants.js +1 -0
  19. package/src/components/__tests__/GrantRequestApprovalResults.spec.js +30 -0
  20. package/src/components/__tests__/GrantRequestBulkActions.spec.js +31 -0
  21. package/src/components/__tests__/GrantRequestBulkApprovalForm.spec.js +54 -0
  22. package/src/components/__tests__/GrantRequestBulkApprovalPopup.spec.js +17 -0
  23. package/src/components/__tests__/GrantRequestBulkRoleSelector.spec.js +48 -0
  24. package/src/components/__tests__/GrantRequestFiltersLoader.spec.js +20 -0
  25. package/src/components/__tests__/GrantRequestRow.spec.js +95 -0
  26. package/src/components/__tests__/GrantRequestSearchFilters.spec.js +19 -0
  27. package/src/components/__tests__/GrantRequestsLabelResults.spec.js +45 -0
  28. package/src/components/__tests__/GrantRequestsSearch.spec.js +23 -0
  29. package/src/components/__tests__/GrantRequestsSearchLoader.spec.js +15 -0
  30. package/src/components/__tests__/GrantRequestsSearchResults.spec.js +59 -0
  31. package/src/components/__tests__/GrantRequestsTable.spec.js +35 -0
  32. package/src/components/__tests__/__snapshots__/GrantRequestApprovalResults.spec.js.snap +69 -0
  33. package/src/components/__tests__/__snapshots__/GrantRequestBulkActions.spec.js.snap +51 -0
  34. package/src/components/__tests__/__snapshots__/GrantRequestBulkApprovalForm.spec.js.snap +41 -0
  35. package/src/components/__tests__/__snapshots__/GrantRequestBulkApprovalPopup.spec.js.snap +11 -0
  36. package/src/components/__tests__/__snapshots__/GrantRequestBulkRoleSelector.spec.js.snap +56 -0
  37. package/src/components/__tests__/__snapshots__/GrantRequestRow.spec.js.snap +55 -0
  38. package/src/components/__tests__/__snapshots__/GrantRequestSearchFilters.spec.js.snap +47 -0
  39. package/src/components/__tests__/__snapshots__/GrantRequestsLabelResults.spec.js.snap +36 -0
  40. package/src/components/__tests__/__snapshots__/GrantRequestsSearch.spec.js.snap +50 -0
  41. package/src/components/__tests__/__snapshots__/GrantRequestsSearchLoader.spec.js.snap +3 -0
  42. package/src/components/__tests__/__snapshots__/GrantRequestsSearchResults.spec.js.snap +247 -0
  43. package/src/components/__tests__/__snapshots__/GrantRequestsTable.spec.js.snap +19 -0
  44. package/src/components/__tests__/__snapshots__/GrantRoutes.spec.js.snap +0 -4
  45. package/src/components/index.js +8 -0
  46. package/src/hooks/useGrantRequest.js +9 -0
  47. package/src/reducers/__tests__/grantRequestCount.spec.js +38 -0
  48. package/src/reducers/__tests__/grantRequestPermissions.spec.js +66 -0
  49. package/src/reducers/__tests__/grantRequestsActiveFilters.spec.js +90 -0
  50. package/src/reducers/__tests__/grantRequestsFiltersLoading.spec.js +34 -0
  51. package/src/reducers/__tests__/grantRequestsSearch.spec.js +38 -0
  52. package/src/reducers/__tests__/grantRequestsSearchLoading.spec.js +36 -0
  53. package/src/reducers/__tests__/grantRequestsSearchQuery.spec.js +96 -0
  54. package/src/reducers/__tests__/grantRequestsSelectedFilter.spec.js +72 -0
  55. package/src/reducers/grantRequestCount.js +23 -0
  56. package/src/reducers/grantRequestPermissions.js +36 -0
  57. package/src/reducers/grantRequestSearchQuery.js +55 -0
  58. package/src/reducers/grantRequestsActiveFilters.js +56 -0
  59. package/src/reducers/grantRequestsFilters.js +23 -0
  60. package/src/reducers/grantRequestsFiltersLoading.js +14 -0
  61. package/src/reducers/grantRequestsSearch.js +19 -0
  62. package/src/reducers/grantRequestsSearchLoading.js +14 -0
  63. package/src/reducers/grantRequestsSelectedFilter.js +34 -0
  64. package/src/reducers/index.js +22 -0
  65. package/src/reducers/structureRedirect.js +2 -3
  66. package/src/routines.js +13 -0
  67. package/src/sagas/__tests__/fetchGrantRequestsFilters.spec.js +91 -0
  68. package/src/sagas/__tests__/fetchGrantRequestsSearch.spec.js +92 -0
  69. package/src/sagas/fetchGrantRequestsFilters.js +32 -0
  70. package/src/sagas/fetchGrantRequestsSearch.js +30 -0
  71. package/src/sagas/index.js +6 -0
  72. package/src/selectors/__tests__/getGrantRequestsAvailableFilters.spec.js +15 -0
  73. package/src/selectors/__tests__/getGrantRequestsFilterTypes.spec.js +19 -0
  74. package/src/selectors/__tests__/getGrantRequestsSearchColumns.spec.js +30 -0
  75. package/src/selectors/__tests__/getGrantRequestsSearchQuery.spec.js +24 -0
  76. package/src/selectors/__tests__/getGrantRequestsSelectedFilterActiveValues.spec.js +15 -0
  77. package/src/selectors/__tests__/getGrantRequestsSelectedFilterValues.spec.js +15 -0
  78. package/src/selectors/__tests__/getGrantRequestsSelectedFilters.spec.js +13 -0
  79. package/src/selectors/getGrantRequestsAvailableFilters.js +17 -0
  80. package/src/selectors/getGrantRequestsFilterTypes.js +7 -0
  81. package/src/selectors/getGrantRequestsSearchColumns.js +119 -0
  82. package/src/selectors/getGrantRequestsSearchQuery.js +19 -0
  83. package/src/selectors/getGrantRequestsSelectedFilterActiveValues.js +8 -0
  84. package/src/selectors/getGrantRequestsSelectedFilterValues.js +12 -0
  85. package/src/selectors/getGrantRequestsSelectedFilters.js +8 -0
  86. package/src/selectors/index.js +10 -0
  87. package/src/components/GrantRequestApprovals.js +0 -41
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@truedat/dd",
3
- "version": "5.16.2",
3
+ "version": "5.16.4",
4
4
  "description": "Truedat Web Data Dictionary",
5
5
  "sideEffects": false,
6
6
  "jsnext:main": "src/index.js",
@@ -88,9 +88,9 @@
88
88
  },
89
89
  "dependencies": {
90
90
  "@apollo/client": "^3.7.1",
91
- "@truedat/auth": "5.15.2",
92
- "@truedat/core": "5.15.2",
93
- "@truedat/df": "5.15.2",
91
+ "@truedat/auth": "5.16.4",
92
+ "@truedat/core": "5.16.4",
93
+ "@truedat/df": "5.16.4",
94
94
  "lodash": "^4.17.21",
95
95
  "moment": "^2.29.4",
96
96
  "path-to-regexp": "^1.7.0",
@@ -115,5 +115,5 @@
115
115
  "react-dom": ">= 16.8.6 < 17",
116
116
  "semantic-ui-react": ">= 2.0.3 < 2.2"
117
117
  },
118
- "gitHead": "4f7b257765169d14b8415107ee59d8b76124f829"
118
+ "gitHead": "cf52894dd17d128c97fc65f97b6976fb07bcb171"
119
119
  }
package/src/api.js CHANGED
@@ -15,6 +15,9 @@ const API_GRANT_REQUEST_APPROVALS = "/api/grant_requests/:id/approvals";
15
15
  const API_GRANT_REQUEST_STATUS = "/api/grant_requests/:id/status";
16
16
  const API_GRANT_REQUEST_GROUP = "/api/grant_request_groups";
17
17
  const API_GRANT_REQUESTS = "/api/grant_requests";
18
+ const API_GRANT_REQUEST_BULK_APPROVAL = "/api/grant_requests/bulk_approval";
19
+ const API_GRANT_REQUESTS_SEARCH = "/api/grant_requests/search";
20
+ const API_GRANT_REQUESTS_FILTERS_SEARCH = "/api/grant_requests_filters/search";
18
21
  const API_GRANT = "/api/grants/:id";
19
22
  const API_GRANTS_CSV = "/api/grants/csv";
20
23
  const API_GRANTS_SEARCH = "/api/grants/search";
@@ -63,10 +66,13 @@ export {
63
66
  API_GRANT,
64
67
  API_GRANT_FILTERS_SEARCH,
65
68
  API_GRANT_REQUEST,
69
+ API_GRANT_REQUEST_BULK_APPROVAL,
66
70
  API_GRANT_REQUEST_APPROVALS,
67
71
  API_GRANT_REQUEST_STATUS,
68
72
  API_GRANT_REQUEST_GROUP,
69
73
  API_GRANT_REQUESTS,
74
+ API_GRANT_REQUESTS_SEARCH,
75
+ API_GRANT_REQUESTS_FILTERS_SEARCH,
70
76
  API_GRANTS_SEARCH,
71
77
  API_GRAPH,
72
78
  API_GRAPH_HASH,
@@ -0,0 +1,40 @@
1
+ import _ from "lodash/fp";
2
+ import React from "react";
3
+ import { useIntl } from "react-intl";
4
+ import { Breadcrumb, Message } from "semantic-ui-react";
5
+ import { useLocation, Link } from "react-router-dom";
6
+ import { GRANT_REQUESTS } from "@truedat/core/routes";
7
+
8
+ export default function GrantRequestApprovalResults() {
9
+ const { state } = useLocation();
10
+ const { formatMessage } = useIntl();
11
+ const count = _.size(state);
12
+ const isRejection = _.prop("[0].is_rejection")(state);
13
+ return (
14
+ <>
15
+ <Breadcrumb>
16
+ <Breadcrumb.Section as={Link} to={GRANT_REQUESTS} active={false}>
17
+ {formatMessage({ id: "grantRequests.header.approve" })}
18
+ </Breadcrumb.Section>
19
+
20
+ <Breadcrumb.Divider icon="right angle" />
21
+ <Breadcrumb.Section active>
22
+ {formatMessage({ id: "grantRequests.header.approve.results" })}
23
+ </Breadcrumb.Section>
24
+ </Breadcrumb>
25
+ <Message positive={!isRejection} warning={isRejection}>
26
+ <Message.Header>
27
+ {formatMessage({
28
+ id: `grant_request.bulk_approval.${
29
+ isRejection ? "rejected" : "approved"
30
+ }.header`,
31
+ })}
32
+ </Message.Header>
33
+ {formatMessage(
34
+ { id: "grant_request.bulk_approval.content" },
35
+ { count }
36
+ )}
37
+ </Message>
38
+ </>
39
+ );
40
+ }
@@ -0,0 +1,136 @@
1
+ import _ from "lodash/fp";
2
+ import React, { useState, useEffect, useRef } from "react";
3
+ import { connect } from "react-redux";
4
+ import PropTypes from "prop-types";
5
+ import { useHistory } from "react-router-dom";
6
+ import { useIntl } from "react-intl";
7
+ import { Grid } from "semantic-ui-react";
8
+ import { makeSearchQuerySelector } from "@truedat/core/selectors";
9
+ import { GRANT_REQUESTS_APPROVALS_RESULT } from "@truedat/core/routes";
10
+ import { useGrantRequestBulkApproval } from "../hooks/useGrantRequest";
11
+ import { fetchGrantRequestsSearch } from "../routines";
12
+ import GrantRequestBulkApprovalPopup from "./GrantRequestBulkApprovalPopup";
13
+ import GrantRequestBulkRoleSelector from "./GrantRequestBulkRoleSelector";
14
+
15
+ const usePrevious = (value) => {
16
+ const ref = useRef();
17
+ useEffect(() => {
18
+ ref.current = value;
19
+ });
20
+ return ref.current;
21
+ };
22
+
23
+ export const GrantRequestBulkActions = ({
24
+ selectedGrantRequests,
25
+ loading,
26
+ onChangeRole,
27
+ rolesPermission,
28
+ roleSelected,
29
+ query,
30
+ cleanSelectedGrantRequests,
31
+ zeroResults,
32
+ }) => {
33
+ const history = useHistory();
34
+ const [saving, setSaving] = useState();
35
+ const { formatMessage } = useIntl();
36
+ const { trigger } = useGrantRequestBulkApproval();
37
+
38
+ const previousQuery = usePrevious(query);
39
+ const clean = !_.isEqual(query)(previousQuery);
40
+
41
+ useEffect(() => {
42
+ cleanSelectedGrantRequests();
43
+ }, [clean]);
44
+
45
+ const onSubmit = ({ comment, isRejection }) => {
46
+ setSaving(true);
47
+ const payload = {
48
+ comment,
49
+ is_rejection: isRejection,
50
+ role: roleSelected,
51
+ };
52
+ const must = _.prop("must")(query);
53
+ trigger(
54
+ _.isEmpty(selectedGrantRequests)
55
+ ? {
56
+ ...payload,
57
+ must,
58
+ }
59
+ : {
60
+ ...payload,
61
+ must: { id: selectedGrantRequests },
62
+ }
63
+ ).then((data) => {
64
+ history.push(GRANT_REQUESTS_APPROVALS_RESULT, _.prop("data.data")(data));
65
+ });
66
+ };
67
+
68
+ return (
69
+ <div className="grant-requests-bulk-actions">
70
+ <Grid.Column width={4} textAlign="right">
71
+ <GrantRequestBulkRoleSelector
72
+ roles={rolesPermission}
73
+ disabled={_.size(rolesPermission) == 1}
74
+ selectedRole={roleSelected}
75
+ onChange={onChangeRole}
76
+ />
77
+
78
+ <GrantRequestBulkApprovalPopup
79
+ onSubmit={onSubmit}
80
+ content={formatMessage({ id: "grantRequest.actions.approve" })}
81
+ disabled={
82
+ _.isNull(roleSelected) ||
83
+ loading ||
84
+ zeroResults ||
85
+ _.size(selectedGrantRequests) == 0
86
+ }
87
+ loading={saving}
88
+ primary
89
+ />
90
+ <GrantRequestBulkApprovalPopup
91
+ onSubmit={onSubmit}
92
+ isRejection
93
+ content={formatMessage({ id: "grantRequest.actions.reject" })}
94
+ disabled={
95
+ _.isNull(roleSelected) ||
96
+ loading ||
97
+ zeroResults ||
98
+ _.size(selectedGrantRequests) == 0
99
+ }
100
+ loading={saving}
101
+ secondary
102
+ />
103
+ </Grid.Column>
104
+ </div>
105
+ );
106
+ };
107
+
108
+ GrantRequestBulkActions.propTypes = {
109
+ roleSelected: PropTypes.string,
110
+ onChangeRole: PropTypes.func,
111
+ rolesPermission: PropTypes.array,
112
+ selectedGrantRequests: PropTypes.array,
113
+ role: PropTypes.string,
114
+ addGrantRequestsFilter: PropTypes.func,
115
+ toggleGrantRequestsFilterValue: PropTypes.func,
116
+ createGrantRequestBulkApproval: PropTypes.func,
117
+ closeGrantRequestsFilter: PropTypes.func,
118
+ loading: PropTypes.bool,
119
+ zeroResults: PropTypes.bool,
120
+ };
121
+
122
+ const makeMapStateToProps = () => {
123
+ const searchQuerySelector = makeSearchQuerySelector(
124
+ "grantRequestSearchQuery",
125
+ "grantRequestsActiveFilters"
126
+ );
127
+
128
+ const mapStateToProps = (state, props) => ({
129
+ query: searchQuerySelector(state, { ...props, pageSize: 1000 }),
130
+ });
131
+ return mapStateToProps;
132
+ };
133
+
134
+ export default connect(makeMapStateToProps, { fetchGrantRequestsSearch })(
135
+ GrantRequestBulkActions
136
+ );
@@ -0,0 +1,69 @@
1
+ import _ from "lodash/fp";
2
+ import React from "react";
3
+ import { useForm, Controller } from "react-hook-form";
4
+ import { Button, Container, Form, Header } from "semantic-ui-react";
5
+ import PropTypes from "prop-types";
6
+ import { useIntl } from "react-intl";
7
+
8
+ export const GrantRequestBulkApprovalForm = ({ isRejection, onSubmit }) => {
9
+ const { formatMessage } = useIntl();
10
+
11
+ const { handleSubmit, control } = useForm({
12
+ mode: "all",
13
+ defaultValues: {
14
+ comment: "",
15
+ isRejection,
16
+ },
17
+ });
18
+
19
+ return (
20
+ <Container className="grant-requests-bulk-approval-form">
21
+ <Header
22
+ as="h2"
23
+ content={formatMessage({
24
+ id: isRejection
25
+ ? "grantRequestApproval.form.reject"
26
+ : "grantRequestApproval.form.approve",
27
+ })}
28
+ />
29
+ <Form onSubmit={handleSubmit(onSubmit)}>
30
+ <Controller
31
+ control={control}
32
+ name="comment"
33
+ render={({ field: { onBlur, onChange, value } }) => (
34
+ <Form.TextArea
35
+ data-testid="comment-id"
36
+ label={formatMessage({
37
+ id: "grantRequestApproval.form.comment.label",
38
+ })}
39
+ placeholder={formatMessage({
40
+ id: "grantRequestApproval.form.comment.placeholder",
41
+ })}
42
+ value={value}
43
+ onBlur={onBlur}
44
+ onChange={(_, { value }) => onChange(value)}
45
+ />
46
+ )}
47
+ />
48
+ <div className="actions">
49
+ <Button
50
+ type="submit"
51
+ primary
52
+ content={formatMessage({
53
+ id: isRejection
54
+ ? "grantRequest.actions.reject"
55
+ : "grantRequest.actions.approve",
56
+ })}
57
+ />
58
+ </div>
59
+ </Form>
60
+ </Container>
61
+ );
62
+ };
63
+
64
+ GrantRequestBulkApprovalForm.propTypes = {
65
+ isRejection: PropTypes.bool,
66
+ onSubmit: PropTypes.func,
67
+ };
68
+
69
+ export default GrantRequestBulkApprovalForm;
@@ -0,0 +1,43 @@
1
+ import React, { useState } from "react";
2
+ import { Button, Popup } from "semantic-ui-react";
3
+ import PropTypes from "prop-types";
4
+ import GrantRequestBulkApprovalForm from "./GrantRequestBulkApprovalForm";
5
+
6
+ export const GrantRequestBulkApprovalPopup = ({
7
+ onSubmit,
8
+ isRejection,
9
+ ...buttonProps
10
+ }) => {
11
+ const [open, setOpen] = useState(false);
12
+
13
+ return (
14
+ <Popup
15
+ on="click"
16
+ basic
17
+ flowing
18
+ content={
19
+ <GrantRequestBulkApprovalForm
20
+ onSubmit={(item) => onSubmit(item, () => setOpen(false))}
21
+ isRejection={isRejection}
22
+ />
23
+ }
24
+ onOpen={() => setOpen(true)}
25
+ onClose={() => setOpen(false)}
26
+ open={open}
27
+ position="bottom right"
28
+ size="large"
29
+ positionFixed
30
+ trigger={
31
+ <Button className="button icon group-actions" {...buttonProps} />
32
+ }
33
+ />
34
+ );
35
+ };
36
+
37
+ GrantRequestBulkApprovalPopup.propTypes = {
38
+ grantRequest: PropTypes.object,
39
+ isRejection: PropTypes.bool,
40
+ saving: PropTypes.bool,
41
+ onSubmit: PropTypes.func,
42
+ };
43
+ export default GrantRequestBulkApprovalPopup;
@@ -0,0 +1,41 @@
1
+ import _ from "lodash/fp";
2
+ import React from "react";
3
+ import PropTypes from "prop-types";
4
+ import { useIntl } from "react-intl";
5
+ import { Dropdown } from "semantic-ui-react";
6
+
7
+ export const GrantRequestBulkRoleSelector = ({
8
+ roles,
9
+ selectedRole,
10
+ disabled,
11
+ onChange,
12
+ }) => {
13
+ const { formatMessage } = useIntl();
14
+ const options = _.flow(
15
+ _.sortBy(_.identity),
16
+ _.map((role) => ({ key: role, value: role, text: role }))
17
+ )(roles);
18
+
19
+ return (
20
+ <Dropdown
21
+ className="grant-requests-bulk-role-selector"
22
+ placeholder={formatMessage({
23
+ id: "grantRequestApproval.form.role.select",
24
+ })}
25
+ selection
26
+ disabled={disabled}
27
+ options={options}
28
+ onChange={(_e, { value }) => onChange(value)}
29
+ value={selectedRole}
30
+ />
31
+ );
32
+ };
33
+
34
+ GrantRequestBulkRoleSelector.propTypes = {
35
+ roles: PropTypes.array,
36
+ selectedRole: PropTypes.string,
37
+ disabled: PropTypes.bool,
38
+ onChange: PropTypes.func,
39
+ };
40
+
41
+ export default GrantRequestBulkRoleSelector;
@@ -0,0 +1,62 @@
1
+ import _ from "lodash/fp";
2
+ import React from "react";
3
+ import PropTypes from "prop-types";
4
+ import { Checkbox, Table } from "semantic-ui-react";
5
+ import { useHistory } from "react-router-dom";
6
+ import { linkTo } from "@truedat/core/routes";
7
+ import { columnDecoratorComponent } from "@truedat/core/services";
8
+
9
+ export const GrantRequestRow = ({
10
+ active,
11
+ checked,
12
+ columns,
13
+ disabled,
14
+ onClick,
15
+ onChange,
16
+ grantRequest,
17
+ roleSelected,
18
+ }) => {
19
+ const history = useHistory();
20
+ const createdById = _.path("created_by_id")(grantRequest);
21
+ const userId = _.path("user_id")(grantRequest);
22
+
23
+ return _.isEmpty(columns) || _.isEmpty(grantRequest) ? null : (
24
+ <Table.Row
25
+ active={active}
26
+ disabled={disabled}
27
+ onClick={() => onClick && onClick(grantRequest)}
28
+ warning={createdById !== userId}
29
+ >
30
+ {roleSelected ? (
31
+ <Table.Cell collapsing width="1" textAlign="center">
32
+ <Checkbox
33
+ id={grantRequest.id}
34
+ checked={checked}
35
+ onChange={onChange}
36
+ />
37
+ </Table.Cell>
38
+ ) : null}
39
+ {columns.map((column, key) => (
40
+ <Table.Cell
41
+ key={key}
42
+ textAlign={column.textAlign}
43
+ onClick={() => history.push(linkTo.GRANT_REQUEST(grantRequest))}
44
+ content={columnDecoratorComponent(column)(grantRequest)}
45
+ />
46
+ ))}
47
+ </Table.Row>
48
+ );
49
+ };
50
+
51
+ GrantRequestRow.propTypes = {
52
+ active: PropTypes.bool,
53
+ checked: PropTypes.bool,
54
+ disabled: PropTypes.bool,
55
+ grantRequest: PropTypes.object,
56
+ columns: PropTypes.array,
57
+ onChange: PropTypes.func,
58
+ onClick: PropTypes.func,
59
+ roleSelected: PropTypes.string,
60
+ };
61
+
62
+ export default GrantRequestRow;
@@ -0,0 +1,22 @@
1
+ import { connect } from "react-redux";
2
+ import { bindActionCreators } from "redux";
3
+ import { AvailableFilters } from "@truedat/core/components";
4
+ import { addGrantRequestsFilter, resetGrantRequestsFilters } from "../routines";
5
+ import { getGrantRequestsAvailableFilters } from "../selectors";
6
+
7
+ const mapStateToProps = (state) => ({
8
+ filters: getGrantRequestsAvailableFilters(state),
9
+ disabled: state.grantRequestsFiltersLoading,
10
+ loading: state.grantRequestsFiltersLoading,
11
+ });
12
+
13
+ const mapDispatchToProps = (dispatch) =>
14
+ bindActionCreators(
15
+ {
16
+ addFilter: addGrantRequestsFilter,
17
+ resetFilters: resetGrantRequestsFilters,
18
+ },
19
+ dispatch
20
+ );
21
+
22
+ export default connect(mapStateToProps, mapDispatchToProps)(AvailableFilters);
@@ -0,0 +1,33 @@
1
+ import { connect } from "react-redux";
2
+ import { bindActionCreators } from "redux";
3
+ import { FiltersLoader } from "@truedat/core/components";
4
+ import { makeActiveFiltersSelector } from "@truedat/core/selectors";
5
+ import {
6
+ clearGrantRequestsFilters,
7
+ fetchGrantRequestsFilters,
8
+ } from "../routines";
9
+
10
+ const mapDispatchToProps = (dispatch) =>
11
+ bindActionCreators(
12
+ {
13
+ clearFilters: clearGrantRequestsFilters,
14
+ fetchFilters: fetchGrantRequestsFilters,
15
+ },
16
+ dispatch
17
+ );
18
+
19
+ export const makeMapStateToProps = ({}) => {
20
+ const activeFiltersSelector = makeActiveFiltersSelector(
21
+ "grantRequestsActiveFilters"
22
+ );
23
+ const mapStateToProps = (state, props) => {
24
+ return {
25
+ selectedFilter: state.grantRequestsSelectedFilter,
26
+ filters: activeFiltersSelector(state, props),
27
+ defaultFilters: props?.defaultFilters,
28
+ };
29
+ };
30
+ return mapStateToProps;
31
+ };
32
+
33
+ export default connect(makeMapStateToProps, mapDispatchToProps)(FiltersLoader);
@@ -0,0 +1,52 @@
1
+ import React from "react";
2
+ import PropTypes from "prop-types";
3
+ import { connect } from "react-redux";
4
+ import { FormattedMessage } from "react-intl";
5
+ import { Label } from "semantic-ui-react";
6
+
7
+ export const GrantRequestsLabelResults = ({
8
+ grantRequestCount,
9
+ grantRequestsSearchLoading,
10
+ grantRequestToExecute,
11
+ roleSelected,
12
+ }) => (
13
+ <>
14
+ <Label className="grant-requests-bulk-label-results">
15
+ {grantRequestsSearchLoading ? (
16
+ <FormattedMessage id="grantRequests.searching" />
17
+ ) : (
18
+ <FormattedMessage
19
+ id="grantRequests.retrieved.results"
20
+ values={{ count: grantRequestCount }}
21
+ />
22
+ )}
23
+ </Label>
24
+ {!grantRequestsSearchLoading && roleSelected ? (
25
+ <Label className="grant-requests-bulk-label-results">
26
+ <FormattedMessage
27
+ id="grantRequests.bulk.selected"
28
+ values={{
29
+ count: grantRequestToExecute,
30
+ }}
31
+ />
32
+ </Label>
33
+ ) : null}
34
+ </>
35
+ );
36
+
37
+ GrantRequestsLabelResults.propTypes = {
38
+ grantRequestCount: PropTypes.number,
39
+ grantRequestToExecute: PropTypes.number,
40
+ grantRequestsSearchLoading: PropTypes.bool,
41
+ roleSelected: PropTypes.string,
42
+ };
43
+
44
+ const mapStateToProps = ({
45
+ grantRequestCount,
46
+ grantRequestsSearchLoading,
47
+ }) => ({
48
+ grantRequestCount,
49
+ grantRequestsSearchLoading,
50
+ });
51
+
52
+ export default connect(mapStateToProps)(GrantRequestsLabelResults);
@@ -0,0 +1,35 @@
1
+ import React from "react";
2
+ import PropTypes from "prop-types";
3
+ import { connect } from "react-redux";
4
+ import { Input } from "semantic-ui-react";
5
+ import { useIntl } from "react-intl";
6
+ import { searchGrantRequests } from "../routines";
7
+ import GrantRequestSearchFilters from "./GrantRequestSearchFilters";
8
+
9
+ export const GrantRequestsSearch = ({ query, searchGrantRequests }) => {
10
+ const { formatMessage } = useIntl();
11
+
12
+ return (
13
+ <Input
14
+ value={query}
15
+ onChange={(_e, data) => searchGrantRequests({ query: data.value })}
16
+ icon={{ name: "search", link: true }}
17
+ iconPosition="left"
18
+ action={<GrantRequestSearchFilters />}
19
+ placeholder={formatMessage({ id: "grantRequest.search.placeholder" })}
20
+ />
21
+ );
22
+ };
23
+
24
+ GrantRequestsSearch.propTypes = {
25
+ query: PropTypes.string,
26
+ searchGrantRequests: PropTypes.func,
27
+ };
28
+
29
+ const mapStateToProps = ({ grantRequestSearchQuery }) => ({
30
+ query: grantRequestSearchQuery?.query,
31
+ });
32
+
33
+ export default connect(mapStateToProps, {
34
+ searchGrantRequests,
35
+ })(GrantRequestsSearch);
@@ -0,0 +1,47 @@
1
+ import { useEffect } from "react";
2
+ import PropTypes from "prop-types";
3
+ import { connect } from "react-redux";
4
+ import { makeSearchQuerySelector } from "@truedat/core/selectors";
5
+ import {
6
+ clearGrantRequestsSearch,
7
+ fetchGrantRequestsSearch,
8
+ } from "../routines";
9
+
10
+ export const GrantRequestsSearchLoader = ({
11
+ clearGrantRequestsSearch,
12
+ fetchGrantRequestsSearch,
13
+ query,
14
+ }) => {
15
+ useEffect(() => {
16
+ return () => {
17
+ clearGrantRequestsSearch();
18
+ };
19
+ }, [clearGrantRequestsSearch]);
20
+ useEffect(() => {
21
+ fetchGrantRequestsSearch(query);
22
+ }, [fetchGrantRequestsSearch, query]);
23
+ return null;
24
+ };
25
+
26
+ GrantRequestsSearchLoader.propTypes = {
27
+ clearGrantRequestsSearch: PropTypes.func,
28
+ fetchGrantRequestsSearch: PropTypes.func,
29
+ query: PropTypes.object,
30
+ };
31
+
32
+ const makeMapStateToProps = () => {
33
+ const searchQuerySelector = makeSearchQuerySelector(
34
+ "grantRequestSearchQuery",
35
+ "grantRequestsActiveFilters"
36
+ );
37
+
38
+ const mapStateToProps = (state, props) => ({
39
+ query: searchQuerySelector(state, { ...props, pageSize: 1000 }),
40
+ });
41
+ return mapStateToProps;
42
+ };
43
+
44
+ export default connect(makeMapStateToProps, {
45
+ clearGrantRequestsSearch,
46
+ fetchGrantRequestsSearch,
47
+ })(GrantRequestsSearchLoader);