@truedat/dd 4.49.10 → 4.50.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.
Files changed (38) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/package.json +5 -5
  3. package/src/api/queries.js +16 -0
  4. package/src/api.js +2 -0
  5. package/src/components/GrantChangeRequest.js +32 -0
  6. package/src/components/GrantRequestCancel.js +47 -0
  7. package/src/components/GrantRequestHeader.js +9 -1
  8. package/src/components/MyGrantRequests.js +1 -0
  9. package/src/components/StructureGrantButton.js +24 -44
  10. package/src/components/StructureGrantCart.js +2 -2
  11. package/src/components/StructureGrantCartCheckout.js +20 -15
  12. package/src/components/StructureGrantCartTemplate.js +15 -61
  13. package/src/components/StructureGrantDropdown.js +201 -0
  14. package/src/components/StructureGrantRequestButton.js +15 -14
  15. package/src/components/StructureGrants.js +1 -1
  16. package/src/components/StructureSummary.js +13 -6
  17. package/src/components/StructureView.js +7 -8
  18. package/src/components/__tests__/MyGrantRequests.spec.js +5 -0
  19. package/src/components/__tests__/StructureGrantButton.spec.js +107 -34
  20. package/src/components/__tests__/StructureGrantCartTemplate.spec.js +11 -100
  21. package/src/components/__tests__/StructureGrantDropdown.spec.js +148 -0
  22. package/src/components/__tests__/StructureGrantRequestButton.spec.js +9 -10
  23. package/src/components/__tests__/__snapshots__/MyGrantRequests.spec.js.snap +14 -0
  24. package/src/components/__tests__/__snapshots__/StructureGrantButton.spec.js.snap +162 -16
  25. package/src/components/__tests__/__snapshots__/StructureGrantCartTemplate.spec.js.snap +0 -3
  26. package/src/components/__tests__/__snapshots__/StructureGrantDropdown.spec.js.snap +271 -0
  27. package/src/components/__tests__/__snapshots__/StructureGrantRequestButton.spec.js.snap +11 -10
  28. package/src/components/__tests__/__snapshots__/StructureSummary.spec.js.snap +6 -0
  29. package/src/messages/en.js +17 -1
  30. package/src/messages/es.js +17 -3
  31. package/src/reducers/__tests__/grantRequestsCart.spec.js +223 -9
  32. package/src/reducers/grantRequestsCart.js +20 -26
  33. package/src/routines.js +2 -1
  34. package/src/sagas/__tests__/createGrantRequestStatus.spec.js +82 -0
  35. package/src/sagas/createGrantRequestStatus.js +32 -0
  36. package/src/sagas/index.js +3 -0
  37. package/src/sagas/operateGrantRequestCart.js +2 -27
  38. package/src/selectors/getGrantRequestsColumns.js +18 -3
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## [4.50.2] 2022-08-26
4
+
5
+ ### Added
6
+
7
+ - [TD-5078] Support for creating a modification GrantRequestGroup
8
+
3
9
  ## [4.49.5] 2022-08-03
4
10
 
5
11
  ### Changed
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@truedat/dd",
3
- "version": "4.49.10",
3
+ "version": "4.50.2",
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.6.4",
91
- "@truedat/auth": "4.49.10",
92
- "@truedat/core": "4.49.10",
93
- "@truedat/df": "4.49.10",
91
+ "@truedat/auth": "4.50.2",
92
+ "@truedat/core": "4.50.2",
93
+ "@truedat/df": "4.50.2",
94
94
  "lodash": "^4.17.21",
95
95
  "path-to-regexp": "^1.7.0",
96
96
  "prop-types": "^15.8.1",
@@ -112,5 +112,5 @@
112
112
  "react-dom": ">= 16.8.6 < 17",
113
113
  "semantic-ui-react": ">= 0.88.2 < 2.1"
114
114
  },
115
- "gitHead": "fb6fcd549a722d777d692f2938dbc991c72dd3a1"
115
+ "gitHead": "5785ca8828b3c25947e8d2587c909f729fbee317"
116
116
  }
@@ -79,3 +79,19 @@ export const REFERENCE_DATASET_QUERY = gql`
79
79
  }
80
80
  }
81
81
  `;
82
+
83
+ export const LATEST_GRANT_REQUEST_QUERY = gql`
84
+ query latestGrantRequest($id: ID!) {
85
+ latestGrantRequest(data_structure_id: $id) {
86
+ id
87
+ group {
88
+ grant {
89
+ id
90
+ }
91
+ }
92
+ status {
93
+ status
94
+ }
95
+ }
96
+ }
97
+ `;
package/src/api.js CHANGED
@@ -10,6 +10,7 @@ const API_PROFILE_EXECUTION = "/api/profile_executions/:id";
10
10
  const API_REFERENCE_DATA_DOWNLOAD = "/api/reference_data/:id/csv";
11
11
  const API_GRANT_REQUEST = "/api/grant_requests/:id";
12
12
  const API_GRANT_REQUEST_APPROVALS = "/api/grant_requests/:id/approvals";
13
+ const API_GRANT_REQUEST_STATUS = "/api/grant_requests/:id/status";
13
14
  const API_GRANT_REQUEST_GROUP = "/api/grant_request_groups";
14
15
  const API_GRANT_REQUESTS = "/api/grant_requests";
15
16
  const API_GRANT = "/api/grants/:id";
@@ -57,6 +58,7 @@ export {
57
58
  API_GRANT_FILTERS_SEARCH,
58
59
  API_GRANT_REQUEST,
59
60
  API_GRANT_REQUEST_APPROVALS,
61
+ API_GRANT_REQUEST_STATUS,
60
62
  API_GRANT_REQUEST_GROUP,
61
63
  API_GRANT_REQUESTS,
62
64
  API_GRANTS_SEARCH,
@@ -0,0 +1,32 @@
1
+ import React from "react";
2
+ import PropTypes from "prop-types";
3
+ import { connect } from "react-redux";
4
+ import { useHistory } from "react-router-dom";
5
+ import { linkTo } from "@truedat/core/routes";
6
+ import { setGrantChangeRequestCart } from "../routines";
7
+
8
+ export const GrantChangeRequest = ({
9
+ structure,
10
+ grant,
11
+ setGrantChangeRequestCart,
12
+ children,
13
+ }) => {
14
+ const history = useHistory();
15
+ if (!structure) return;
16
+
17
+ return React.cloneElement(children, {
18
+ onClick: () => {
19
+ setGrantChangeRequestCart({ structure, grant });
20
+ history.push(linkTo.GRANTS_REQUESTS_CHECKOUT());
21
+ },
22
+ });
23
+ };
24
+
25
+ GrantChangeRequest.propTypes = {
26
+ structure: PropTypes.object,
27
+ grant: PropTypes.object,
28
+ setGrantChangeRequestCart: PropTypes.func,
29
+ children: PropTypes.node,
30
+ };
31
+
32
+ export default connect(null, { setGrantChangeRequestCart })(GrantChangeRequest);
@@ -0,0 +1,47 @@
1
+ import React from "react";
2
+ import PropTypes from "prop-types";
3
+ import { connect } from "react-redux";
4
+ import { useIntl } from "react-intl";
5
+ import { ConfirmModal } from "@truedat/core/components";
6
+ import { createGrantRequestStatus } from "../routines";
7
+
8
+ export const GrantRequestCancel = ({
9
+ structureId,
10
+ grantRequest,
11
+ createGrantRequestStatus,
12
+ children,
13
+ }) => {
14
+ const { formatMessage } = useIntl();
15
+
16
+ if (!grantRequest) return;
17
+
18
+ return (
19
+ <ConfirmModal
20
+ trigger={children}
21
+ header={formatMessage({
22
+ id: "grantRequest.actions.cancel.confirmation.header",
23
+ })}
24
+ content={formatMessage({
25
+ id: "grantRequest.actions.cancel.confirmation.content",
26
+ })}
27
+ onConfirm={() =>
28
+ createGrantRequestStatus({
29
+ structureId,
30
+ grantRequestId: grantRequest.id,
31
+ status: "cancelled",
32
+ })
33
+ }
34
+ onOpen={(e) => e.stopPropagation()}
35
+ onClose={(e) => e.stopPropagation()}
36
+ />
37
+ );
38
+ };
39
+
40
+ GrantRequestCancel.propTypes = {
41
+ structureId: PropTypes.number,
42
+ grantRequest: PropTypes.object,
43
+ createGrantRequestStatus: PropTypes.func,
44
+ children: PropTypes.node,
45
+ };
46
+
47
+ export default connect(null, { createGrantRequestStatus })(GrantRequestCancel);
@@ -7,6 +7,10 @@ import { Header, Grid, Icon } from "semantic-ui-react";
7
7
  import GrantRequestApprovalPopup from "./GrantRequestApprovalPopup";
8
8
 
9
9
  export const GrantRequestHeader = ({ grantRequest }) => {
10
+ const isModification = _.prop("_embedded.group._embedded.modification_grant")(
11
+ grantRequest
12
+ );
13
+
10
14
  const { formatMessage } = useIntl();
11
15
  const canApprove =
12
16
  grantRequest?.status === "pending" &&
@@ -17,7 +21,11 @@ export const GrantRequestHeader = ({ grantRequest }) => {
17
21
  <Header as="h2">
18
22
  <Icon circular name="key" />
19
23
  <Header.Content>
20
- {formatMessage({ id: "grantRequest.header" })}
24
+ {formatMessage({
25
+ id: isModification
26
+ ? "grantRequest.header.modification"
27
+ : "grantRequest.header",
28
+ })}
21
29
  </Header.Content>
22
30
  </Header>
23
31
  </Grid.Column>
@@ -16,6 +16,7 @@ const STATUS = [
16
16
  "processing",
17
17
  "processed",
18
18
  "failed",
19
+ "cancelled",
19
20
  ];
20
21
  const DEFAULT_STATUS = ["pending", "approved", "rejected", "processing"];
21
22
 
@@ -1,63 +1,43 @@
1
1
  import _ from "lodash/fp";
2
2
  import React from "react";
3
3
  import PropTypes from "prop-types";
4
- import { Icon, Label, Popup } from "semantic-ui-react";
4
+ import { useQuery } from "@apollo/client";
5
5
  import { connect } from "react-redux";
6
- import { useIntl } from "react-intl";
7
- import { DateTime } from "@truedat/core/components";
8
- import GrantRemoval from "./GrantRemoval";
6
+ import { Loading } from "@truedat/core/components";
7
+ import { LATEST_GRANT_REQUEST_QUERY } from "../api/queries";
9
8
  import StructureGrantRequestButton from "./StructureGrantRequestButton";
9
+ import StructureGrantDropdown from "./StructureGrantDropdown";
10
10
 
11
- const isNilOrEmpty = (value) => _.isEmpty(value) || _.isNil(value);
12
- export const StructureGrantButton = ({ structure, structureGrantPopup }) => {
13
- const { formatMessage } = useIntl();
14
- const { grant } = structure;
11
+ export const StructureGrantButton = ({ structure }) => {
12
+ const { grant, id } = structure;
15
13
 
16
- const popupContent = _.flow(
17
- _.reject(({ field }) => isNilOrEmpty(_.get(field)(grant))),
18
- _.map(({ field, type }) => {
19
- switch (type) {
20
- case "datetime":
21
- return <DateTime value={_.get(field)(grant)} key={field} />;
22
- default:
23
- return <div key={field}>{_.get(field)(grant)}</div>;
24
- }
25
- })
26
- )(structureGrantPopup);
14
+ const { loading, error, data } = useQuery(LATEST_GRANT_REQUEST_QUERY, {
15
+ fetchPolicy: "cache-and-network",
16
+ variables: { id },
17
+ });
18
+ if (error) return null;
19
+ if (loading) return <Loading />;
27
20
 
28
- const label = grant ? (
29
- grant.pending_removal ? (
30
- <Label color="orange">
31
- <Icon name="shield" />
32
- {formatMessage({ id: "structure.grant.has_grant_pending_removal" })}
33
- <GrantRemoval grant={grant}>
34
- <Icon name="undo" />
35
- </GrantRemoval>
36
- </Label>
37
- ) : (
38
- <Label color="green">
39
- <Icon name="shield" />
40
- {formatMessage({ id: "structure.grant.has_grant" })}
41
- <GrantRemoval grant={grant}>
42
- <Icon name="delete" />
43
- </GrantRemoval>
44
- </Label>
45
- )
21
+ const grantRequest = _.prop("latestGrantRequest")(data);
22
+ const isActiveRequest = _.includes(_.prop("status.status")(grantRequest))([
23
+ "pending",
24
+ "approved",
25
+ "processing",
26
+ ]);
27
+
28
+ return grant || isActiveRequest ? (
29
+ <StructureGrantDropdown
30
+ grantRequest={isActiveRequest ? grantRequest : null}
31
+ />
46
32
  ) : (
47
33
  <StructureGrantRequestButton />
48
34
  );
49
- return _.isEmpty(popupContent) ? (
50
- label
51
- ) : (
52
- <Popup content={popupContent} trigger={label} />
53
- );
54
35
  };
55
36
 
56
37
  StructureGrantButton.propTypes = {
57
38
  structure: PropTypes.object,
58
- structureGrantPopup: PropTypes.array,
59
39
  };
60
40
 
61
- const mapStateToProps = _.pick(["structure", "structureGrantPopup"]);
41
+ const mapStateToProps = ({ structure }) => ({ structure });
62
42
 
63
43
  export default connect(mapStateToProps)(StructureGrantButton);
@@ -53,9 +53,9 @@ export const StructureGrantCart = ({
53
53
  const hasFilters = _.flow(_.pathOr([], "filters"), _.negate(_.isEmpty));
54
54
 
55
55
  const setRowValue =
56
- (structure_id) =>
56
+ (structureId) =>
57
57
  ({ index, value }) => {
58
- updateGrantRequestFilter({ index, value, structure_id });
58
+ updateGrantRequestFilter({ index, value, structureId });
59
59
  };
60
60
 
61
61
  return (
@@ -1,12 +1,11 @@
1
1
  import _ from "lodash/fp";
2
2
  import React from "react";
3
3
  import PropTypes from "prop-types";
4
- import { Segment, Grid, Button, GridColumn } from "semantic-ui-react";
4
+ import { Header, Segment, Grid, Button, GridColumn } from "semantic-ui-react";
5
5
  import { bindActionCreators } from "redux";
6
6
  import { connect } from "react-redux";
7
7
  import { HistoryBackButton } from "@truedat/core/components";
8
- import { useIntl } from "react-intl";
9
- import { applyTemplate, validateContent } from "@truedat/df/utils";
8
+ import { useIntl, FormattedMessage } from "react-intl";
10
9
  import { checkoutGrantRequest } from "../routines";
11
10
  import StructureGrantCart from "./StructureGrantCart";
12
11
  import StructureGrantCartTemplate from "./StructureGrantCartTemplate";
@@ -17,29 +16,24 @@ export const StructureGrantCartCheckout = ({
17
16
  }) => {
18
17
  const { formatMessage } = useIntl();
19
18
 
20
- const template = grantRequestsCart.template;
21
- const content = grantRequestsCart.templateContent;
22
-
23
- const is_invalid_template =
24
- !template || _.size(validateContent(template)(content)) > 0;
25
-
26
- const valid_cart = !is_invalid_template;
19
+ const { template, templateContent, modificationGrant, validCart } =
20
+ grantRequestsCart;
27
21
 
28
22
  const checkout = () => {
29
- const metadata = applyTemplate(template)(content);
30
23
  const requests = _.map((structure) => {
31
24
  return {
32
25
  data_structure_id: structure.id,
33
26
  filters: {
34
27
  rows: structure.filters,
35
28
  },
36
- metadata: metadata,
29
+ metadata: templateContent,
37
30
  };
38
31
  })(grantRequestsCart.structures);
39
32
  const payload = {
40
33
  grant_request_group: {
41
34
  requests,
42
- type: template.name,
35
+ type: template,
36
+ modification_grant_id: modificationGrant ? modificationGrant.id : null,
43
37
  },
44
38
  };
45
39
  checkoutGrantRequest(payload);
@@ -49,14 +43,25 @@ export const StructureGrantCartCheckout = ({
49
43
  <Segment className="structures">
50
44
  <Grid>
51
45
  <Grid.Row>
52
- <GridColumn floated="right" textAlign="right">
46
+ <GridColumn width={8}>
47
+ <Header as="h2">
48
+ <Header.Content>
49
+ <FormattedMessage
50
+ id={`grantRequest.header.${
51
+ modificationGrant ? "update" : "create"
52
+ }`}
53
+ />
54
+ </Header.Content>
55
+ </Header>
56
+ </GridColumn>
57
+ <GridColumn width={8} textAlign="right">
53
58
  <HistoryBackButton
54
59
  content={formatMessage({ id: "actions.cancel" })}
55
60
  />
56
61
  <Button
57
62
  primary
58
63
  onClick={checkout}
59
- disabled={!valid_cart}
64
+ disabled={!validCart}
60
65
  content={formatMessage({ id: "actions.save" })}
61
66
  />
62
67
  </GridColumn>
@@ -1,51 +1,26 @@
1
1
  import _ from "lodash/fp";
2
- import React, { useEffect } from "react";
2
+ import React from "react";
3
3
  import PropTypes from "prop-types";
4
- import { Segment, Dropdown, Divider, Form, Header } from "semantic-ui-react";
4
+ import { Segment, Divider, Form, Header } from "semantic-ui-react";
5
5
  import { connect } from "react-redux";
6
6
  import { useIntl } from "react-intl";
7
7
  import {
8
- fetchGrantRequestTemplates,
9
8
  selectGrantRequestTemplate,
10
9
  updateGrantRequestTemplateContent,
11
10
  } from "../routines";
12
11
 
13
- const DynamicForm = React.lazy(() =>
14
- import("@truedat/df/components/DynamicForm")
12
+ const SelectableDynamicForm = React.lazy(() =>
13
+ import("@truedat/df/components/SelectableDynamicForm")
15
14
  );
16
15
 
17
16
  export const StructureGrantCartTemplate = ({
18
17
  grantRequestsCart,
19
- templateContent,
20
- fetchGrantRequestTemplates,
21
18
  selectGrantRequestTemplate,
22
19
  updateGrantRequestTemplateContent,
23
20
  }) => {
24
21
  const { formatMessage } = useIntl();
25
22
 
26
- const template = _.pathOr(null, "template")(grantRequestsCart);
27
- const templates = _.pathOr(null, "templates")(grantRequestsCart);
28
- const templatesLoading = _.pathOr(
29
- false,
30
- "templatesLoading"
31
- )(grantRequestsCart);
32
- const singleTemplate = _.size(templates) === 1;
33
-
34
- useEffect(() => {
35
- fetchGrantRequestTemplates();
36
- }, [fetchGrantRequestTemplates]);
37
-
38
- useEffect(() => {
39
- if (singleTemplate) {
40
- const defaultTemplate = _.head(templates);
41
- selectGrantRequestTemplate(defaultTemplate?.id);
42
- }
43
- }, [singleTemplate, selectGrantRequestTemplate, templates]);
44
-
45
- const getOptions = _.map((template) => {
46
- const { id, name } = _.pick(["id", "name"])(template);
47
- return { key: id, value: id, text: name };
48
- });
23
+ const templateContent = _.pathOr({}, "templateContent")(grantRequestsCart);
49
24
 
50
25
  return (
51
26
  <Segment>
@@ -55,53 +30,32 @@ export const StructureGrantCartTemplate = ({
55
30
  {formatMessage({ id: `structure.grant.cart.template` })}
56
31
  </Header>
57
32
  <Divider />
58
- {!singleTemplate && (
59
- <Dropdown
33
+ <Form>
34
+ <SelectableDynamicForm
35
+ scope="gr"
36
+ required
37
+ content={templateContent}
38
+ onChange={updateGrantRequestTemplateContent}
39
+ onNameChange={selectGrantRequestTemplate}
60
40
  placeholder={formatMessage({
61
41
  id: `structure.grant.cart.template.placeholder`,
62
42
  })}
63
- label={formatMessage({ id: "structureType.template" })}
64
- name="template_id"
65
- fluid
66
- onChange={(_e, { value }) => selectGrantRequestTemplate(value)}
67
- options={getOptions(templates) || []}
68
- selection
69
- clearable
70
- loading={templatesLoading}
71
- value={template?.id || ""}
43
+ hideLabel
72
44
  />
73
- )}
74
- {template ? (
75
- <>
76
- <Divider />
77
- <Form>
78
- <DynamicForm
79
- onChange={updateGrantRequestTemplateContent}
80
- template={template}
81
- content={templateContent}
82
- />
83
- </Form>
84
- </>
85
- ) : null}
45
+ </Form>
86
46
  </Segment>
87
47
  );
88
48
  };
89
49
 
90
50
  StructureGrantCartTemplate.propTypes = {
91
51
  grantRequestsCart: PropTypes.object,
92
- templateContent: PropTypes.object,
93
- fetchGrantRequestTemplates: PropTypes.func,
94
52
  selectGrantRequestTemplate: PropTypes.func,
95
53
  updateGrantRequestTemplateContent: PropTypes.func,
96
54
  };
97
55
 
98
- const mapStateToProps = ({ grantRequestsCart }) => ({
99
- grantRequestsCart,
100
- templateContent: _.pathOr({}, "templateContent")(grantRequestsCart),
101
- });
56
+ const mapStateToProps = ({ grantRequestsCart }) => ({ grantRequestsCart });
102
57
 
103
58
  export default connect(mapStateToProps, {
104
- fetchGrantRequestTemplates,
105
59
  selectGrantRequestTemplate,
106
60
  updateGrantRequestTemplateContent,
107
61
  })(StructureGrantCartTemplate);