@truedat/dd 4.58.6 → 4.59.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/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## [4.58.7] 2022-12-27
4
+
5
+ ### Added
6
+
7
+ - [TD-5348] Update grant from grant detail
8
+
3
9
  ## [4.58.5] 2022-12-23
4
10
 
5
11
  ### Added
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@truedat/dd",
3
- "version": "4.58.6",
3
+ "version": "4.59.0",
4
4
  "description": "Truedat Web Data Dictionary",
5
5
  "sideEffects": false,
6
6
  "jsnext:main": "src/index.js",
@@ -34,7 +34,7 @@
34
34
  "@testing-library/jest-dom": "^5.16.5",
35
35
  "@testing-library/react": "^12.0.0",
36
36
  "@testing-library/user-event": "^13.2.1",
37
- "@truedat/test": "4.58.6",
37
+ "@truedat/test": "4.58.7",
38
38
  "babel-jest": "^28.1.0",
39
39
  "babel-plugin-dynamic-import-node": "^2.3.3",
40
40
  "babel-plugin-lodash": "^3.3.4",
@@ -87,9 +87,9 @@
87
87
  },
88
88
  "dependencies": {
89
89
  "@apollo/client": "^3.7.1",
90
- "@truedat/auth": "4.58.6",
91
- "@truedat/core": "4.58.6",
92
- "@truedat/df": "4.58.6",
90
+ "@truedat/auth": "4.59.0",
91
+ "@truedat/core": "4.59.0",
92
+ "@truedat/df": "4.59.0",
93
93
  "lodash": "^4.17.21",
94
94
  "moment": "^2.29.4",
95
95
  "path-to-regexp": "^1.7.0",
@@ -114,5 +114,5 @@
114
114
  "react-dom": ">= 16.8.6 < 17",
115
115
  "semantic-ui-react": ">= 2.0.3 < 2.2"
116
116
  },
117
- "gitHead": "6d62fbef2dea9d23cb1f3908bdc48ba36f4fd55d"
117
+ "gitHead": "7d2cd52d47210cdd67cf3521697dab38c963a570"
118
118
  }
@@ -8,9 +8,10 @@ import Moment from "react-moment";
8
8
  import { Grid, Segment, Header, Icon, List, Button } from "semantic-ui-react";
9
9
 
10
10
  import { linkTo } from "@truedat/core/routes";
11
- import { useGrant, useGrantRemoval } from "../hooks/useGrant";
11
+ import { useGrant, useGrantRemoval, useStructure } from "../hooks/useGrant";
12
12
  import GrantCrumbs from "./GrantCrumbs";
13
13
  import GrantRemoval from "./GrantRemoval";
14
+ import GrantChangeRequest from "./GrantChangeRequest";
14
15
  const DynamicFieldValue = React.lazy(() =>
15
16
  import("@truedat/df/components/DynamicFieldValue")
16
17
  );
@@ -31,6 +32,13 @@ const GrantView = () => {
31
32
  };
32
33
 
33
34
  export const GrantHeader = ({ grant, title, actions, onStatusChange }) => {
35
+ const { data: structure, loading } = useStructure(grant?.data_structure.id);
36
+ const data_structure = loading
37
+ ? null
38
+ : {
39
+ ...structure.data,
40
+ ...structure.data.data_structure,
41
+ };
34
42
  const { formatMessage } = useIntl();
35
43
  return (
36
44
  <Grid>
@@ -44,6 +52,20 @@ export const GrantHeader = ({ grant, title, actions, onStatusChange }) => {
44
52
  })} ${title}`}
45
53
  </Header.Content>
46
54
  </Header>
55
+ {actions?.update && !loading ? (
56
+ <GrantChangeRequest
57
+ structure={data_structure}
58
+ grant={grant}
59
+ key="requestChange"
60
+ >
61
+ <Button
62
+ className="button icon group-actions"
63
+ content={formatMessage({
64
+ id: "structure.grant.request_grant_change",
65
+ })}
66
+ />
67
+ </GrantChangeRequest>
68
+ ) : null}
47
69
  </Grid.Column>
48
70
  <Grid.Column width={4} textAlign="right">
49
71
  {actions?.request_removal ? (
@@ -1,7 +1,7 @@
1
1
  import _ from "lodash/fp";
2
2
  import React, { useEffect, useState } from "react";
3
3
  import PropTypes from "prop-types";
4
- import { Form, Checkbox } from "semantic-ui-react";
4
+ import { Form, Checkbox, Header } from "semantic-ui-react";
5
5
  import { connect } from "react-redux";
6
6
  import { useIntl } from "react-intl";
7
7
  import { lowerDeburrTrim } from "@truedat/core/services/sort";
@@ -21,12 +21,17 @@ export const StructureGrantCartUserSelector = ({
21
21
  const [thirdParty, setThirdParty] = useState(false);
22
22
  const [userId, setUserId] = useState(_.path("user.id")(grantRequestsCart));
23
23
 
24
+ const { modificationGrant } = grantRequestsCart;
25
+ const updateGrant = !_.isEmpty(modificationGrant);
26
+
24
27
  useEffect(() => {
25
28
  updateGrantRequestUser({
26
29
  id: userId,
27
30
  valid:
28
31
  !thirdParty || (thirdParty && !(_.isNil(userId) && _.isEmpty(userId))),
29
32
  });
33
+ if (updateGrant && modificationGrant.user_id)
34
+ setUserId(modificationGrant.user_id);
30
35
  }, [userId, thirdParty]);
31
36
 
32
37
  const onSearch = (_currentOptions, { searchQuery }) =>
@@ -38,7 +43,15 @@ export const StructureGrantCartUserSelector = ({
38
43
  if (userId === "") setThirdParty(false);
39
44
  };
40
45
 
41
- return (
46
+ return updateGrant ? (
47
+ <Header as="h4">
48
+ <Header.Content>
49
+ {`${formatMessage({ id: "grantRequestCart.user.label" })} ${
50
+ modificationGrant.user?.full_name
51
+ }`}
52
+ </Header.Content>
53
+ </Header>
54
+ ) : (
42
55
  <>
43
56
  <UsersSearchLoader
44
57
  query={usersGroupsQuery}
@@ -4,6 +4,23 @@ import { render } from "@truedat/test/render";
4
4
  import { Grant } from "../Grant";
5
5
  import en from "../../messages/en";
6
6
 
7
+ jest.mock("../../hooks/useGrant.js", () => {
8
+ const originalModule = jest.requireActual("../../hooks/useGrant.js");
9
+
10
+ return {
11
+ __esModule: true,
12
+ ...originalModule,
13
+ useStructure: jest.fn(() => ({
14
+ data: {
15
+ data: {
16
+ data_structure: {},
17
+ },
18
+ },
19
+ loading: false,
20
+ })),
21
+ };
22
+ });
23
+
7
24
  describe("<Grant />", () => {
8
25
  const grant = {
9
26
  data_structure: {
@@ -64,6 +81,17 @@ describe("<Grant />", () => {
64
81
  expect(container).toMatchSnapshot();
65
82
  });
66
83
 
84
+ it("matches the latest snapshot with update action", () => {
85
+ const props = {
86
+ ...defaultProps,
87
+ actions: {
88
+ update: {},
89
+ },
90
+ };
91
+ const { container } = render(<Grant {...props} />, renderOpts);
92
+ expect(container).toMatchSnapshot();
93
+ });
94
+
67
95
  it("on click removal onStatusChange is called", async () => {
68
96
  const { findByText } = render(<Grant {...defaultProps} />, renderOpts);
69
97
 
@@ -0,0 +1,44 @@
1
+ import React from "react";
2
+ import { render } from "@truedat/test/render";
3
+ import StructureGrantCartUserSelector from "../StructureGrantCartUserSelector";
4
+
5
+ const defaultRenderOpts = {
6
+ state: {
7
+ grantRequestsCart: { user: { id: 5 } },
8
+ usersSearch: [{ full_name: "name", id: 1 }],
9
+ },
10
+ fallback: "lazy",
11
+ };
12
+
13
+ describe("<StructureGrantCartUserSelector />", () => {
14
+ it("matches the latest snapshot", () => {
15
+ const { container } = render(
16
+ <StructureGrantCartUserSelector query="abc" />,
17
+ defaultRenderOpts
18
+ );
19
+ expect(container).toMatchSnapshot();
20
+ });
21
+
22
+ it("matches the latest snapshot on update grant", () => {
23
+ const renderOpts = {
24
+ ...defaultRenderOpts,
25
+ state: {
26
+ ...defaultRenderOpts.state,
27
+ grantRequestsCart: {
28
+ modificationGrant: {
29
+ user_id: 1,
30
+ user: {
31
+ full_name: "foo",
32
+ },
33
+ },
34
+ },
35
+ },
36
+ };
37
+
38
+ const { container } = render(
39
+ <StructureGrantCartUserSelector query="abc" />,
40
+ renderOpts
41
+ );
42
+ expect(container).toMatchSnapshot();
43
+ });
44
+ });
@@ -466,3 +466,261 @@ exports[`<Grant /> matches the latest snapshot with cancel_removal action 1`] =
466
466
  </div>
467
467
  </div>
468
468
  `;
469
+
470
+ exports[`<Grant /> matches the latest snapshot with update action 1`] = `
471
+ <div>
472
+ <div
473
+ class="ui breadcrumb"
474
+ >
475
+ <a
476
+ class="section"
477
+ href="/grants"
478
+ >
479
+ Grants
480
+ </a>
481
+ <i
482
+ aria-hidden="true"
483
+ class="right angle icon divider"
484
+ />
485
+ <div
486
+ class="active section"
487
+ >
488
+ -&gt; foo
489
+ </div>
490
+ </div>
491
+ <div
492
+ class="ui segment"
493
+ >
494
+ <div
495
+ class="ui grid"
496
+ >
497
+ <div
498
+ class="row"
499
+ >
500
+ <div
501
+ class="sixteen wide column"
502
+ >
503
+ <div
504
+ class="ui grid"
505
+ >
506
+ <div
507
+ class="row"
508
+ >
509
+ <div
510
+ class="twelve wide column"
511
+ >
512
+ <h2
513
+ class="ui header"
514
+ >
515
+ <i
516
+ aria-hidden="true"
517
+ class="key circular icon"
518
+ />
519
+ <div
520
+ class="content"
521
+ >
522
+ Grants -&gt; foo
523
+ </div>
524
+ </h2>
525
+ <button
526
+ class="ui button button icon group-actions"
527
+ >
528
+ Request grant change
529
+ </button>
530
+ </div>
531
+ <div
532
+ class="right aligned four wide column"
533
+ />
534
+ </div>
535
+ </div>
536
+ <div
537
+ class="ui big very relaxed list"
538
+ role="list"
539
+ >
540
+ <div
541
+ class="item"
542
+ role="listitem"
543
+ >
544
+ <div
545
+ class="content"
546
+ >
547
+ <div
548
+ class="header"
549
+ >
550
+ Structure
551
+ </div>
552
+ <div
553
+ class="description"
554
+ >
555
+ <a
556
+ href="/structures/2/grants"
557
+ >
558
+ foo
559
+ </a>
560
+ </div>
561
+ </div>
562
+ </div>
563
+ <div
564
+ class="item"
565
+ role="listitem"
566
+ >
567
+ <div
568
+ class="header"
569
+ >
570
+ Account
571
+ </div>
572
+ <div
573
+ class="description"
574
+ >
575
+ <h4
576
+ class="ui header"
577
+ >
578
+ <div
579
+ class="content"
580
+ >
581
+ foo user
582
+ <div
583
+ class="sub header"
584
+ >
585
+ foo@gmail.com
586
+ </div>
587
+ </div>
588
+ </h4>
589
+ </div>
590
+ </div>
591
+ <div
592
+ class="item"
593
+ role="listitem"
594
+ >
595
+ <div
596
+ class="header"
597
+ >
598
+ Grant created
599
+ </div>
600
+ <div
601
+ class="description"
602
+ >
603
+ <time
604
+ datetime="1670849349789"
605
+ >
606
+ 2022-12-12 12:49
607
+ </time>
608
+ </div>
609
+ </div>
610
+ <div
611
+ class="item"
612
+ role="listitem"
613
+ >
614
+ <div
615
+ class="header"
616
+ >
617
+ Access granted
618
+ </div>
619
+ <div
620
+ class="description"
621
+ >
622
+ <time
623
+ datetime="1543622400000"
624
+ >
625
+ 2018-12-01
626
+ </time>
627
+ </div>
628
+ </div>
629
+ <div
630
+ class="item"
631
+ role="listitem"
632
+ >
633
+ <div
634
+ class="header"
635
+ >
636
+ Expires
637
+ </div>
638
+ <div
639
+ class="description"
640
+ >
641
+ <time
642
+ datetime="1577750400000"
643
+ >
644
+ 2019-12-31
645
+ </time>
646
+ </div>
647
+ </div>
648
+ <div
649
+ class="item"
650
+ role="listitem"
651
+ >
652
+ <div
653
+ class="header"
654
+ >
655
+ Details
656
+ </div>
657
+ <div
658
+ class="description"
659
+ >
660
+ <div
661
+ class="ui list"
662
+ role="list"
663
+ >
664
+ <div
665
+ class="item"
666
+ role="listitem"
667
+ >
668
+ <div
669
+ class="header dynamic-field-header"
670
+ >
671
+ foo
672
+ </div>
673
+ <div
674
+ class="description"
675
+ >
676
+ <div
677
+ class="ui label"
678
+ >
679
+ 1
680
+ </div>
681
+ <div
682
+ class="ui label"
683
+ >
684
+ 2
685
+ </div>
686
+ <div
687
+ class="ui label"
688
+ >
689
+ 3
690
+ </div>
691
+ <div
692
+ class="ui label"
693
+ >
694
+ 4
695
+ </div>
696
+ </div>
697
+ </div>
698
+ <div
699
+ class="item"
700
+ role="listitem"
701
+ >
702
+ <div
703
+ class="header dynamic-field-header"
704
+ >
705
+ bar
706
+ </div>
707
+ <div
708
+ class="description"
709
+ >
710
+ <div
711
+ class="default-value"
712
+ >
713
+ baz
714
+ </div>
715
+ </div>
716
+ </div>
717
+ </div>
718
+ </div>
719
+ </div>
720
+ </div>
721
+ </div>
722
+ </div>
723
+ </div>
724
+ </div>
725
+ </div>
726
+ `;
@@ -72,3 +72,17 @@ exports[`<StructureGrantCartUserSelector /> matches the latest snapshot 1`] = `
72
72
  lazy
73
73
  </div>
74
74
  `;
75
+
76
+ exports[`<StructureGrantCartUserSelector /> matches the latest snapshot on update grant 1`] = `
77
+ <div>
78
+ <h4
79
+ class="ui header"
80
+ >
81
+ <div
82
+ class="content"
83
+ >
84
+ Request for: foo
85
+ </div>
86
+ </h4>
87
+ </div>
88
+ `;
@@ -2,7 +2,7 @@ import { compile } from "path-to-regexp";
2
2
  import useSWR from "swr";
3
3
  import useSWRMutations from "swr/mutation";
4
4
  import { apiJson, apiJsonPatch } from "@truedat/core/services/api";
5
- import { API_GRANT } from "../api";
5
+ import { API_GRANT, API_DATA_STRUCTURE_VERSION } from "../api";
6
6
 
7
7
  const toApiPath = compile(API_GRANT);
8
8
 
@@ -16,3 +16,9 @@ export const useGrantRemoval = (id) => {
16
16
  const url = toApiPath({ id });
17
17
  return useSWRMutations(url, (url, { arg }) => apiJsonPatch(url, arg));
18
18
  };
19
+
20
+ export const useStructure = (id) => {
21
+ const url = compile(API_DATA_STRUCTURE_VERSION)({ id, version: "latest" });
22
+ const { data, error } = useSWR(url, apiJson);
23
+ return { data: data?.data, error, loading: !error && !data };
24
+ };
@@ -213,6 +213,29 @@ describe("reducers: structureVersion", () => {
213
213
  ).toEqual(expectedState);
214
214
  });
215
215
 
216
+ it("on setGrantChangeRequestCart.TRIGGER fill templateContent with grant.detail", () => {
217
+ const structure = { id: 1 };
218
+ const grantDetail = {
219
+ foo: "bar",
220
+ };
221
+ const grant = {
222
+ id: 2,
223
+ detail: grantDetail,
224
+ };
225
+ const expectedState = {
226
+ ...initialState,
227
+ modificationGrant: grant,
228
+ templateContent: grantDetail,
229
+ structures: [structure],
230
+ };
231
+ expect(
232
+ grantRequestsCart(initialState, {
233
+ type: setGrantChangeRequestCart.TRIGGER,
234
+ payload: { structure, grant },
235
+ })
236
+ ).toEqual(expectedState);
237
+ });
238
+
216
239
  it("on updateGrantRequestFilter.TRIGGER adds a empty filter to structure when no index is passed", () => {
217
240
  const stateWithPopulation = {
218
241
  ...initialState,
@@ -76,6 +76,7 @@ const grantRequestsCart = (state = initialState, { type, payload }) => {
76
76
  const { structure, grant } = payload;
77
77
  return {
78
78
  ...initialState,
79
+ templateContent: { ...grant.detail },
79
80
  modificationGrant: grant,
80
81
  structures: [mapPayload(structure)],
81
82
  };
@@ -1,21 +0,0 @@
1
- import React from "react";
2
- import { render } from "@truedat/test/render";
3
- import StructureGrantCartUserSelector from "../StructureGrantCartUserSelector";
4
-
5
- const renderOpts = {
6
- state: {
7
- grantRequestsCart: { user: { id: 5 } },
8
- usersSearch: [{ full_name: "name", id: 1 }],
9
- },
10
- fallback: "lazy",
11
- };
12
-
13
- describe("<StructureGrantCartUserSelector />", () => {
14
- it("matches the latest snapshot", () => {
15
- const { container } = render(
16
- <StructureGrantCartUserSelector query="abc" />,
17
- renderOpts
18
- );
19
- expect(container).toMatchSnapshot();
20
- });
21
- });