@truedat/auth 7.5.7 → 7.5.10

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 (160) hide show
  1. package/package.json +40 -64
  2. package/src/groups/components/EditGroup.js +0 -1
  3. package/src/groups/components/Group.js +0 -1
  4. package/src/groups/components/GroupBreadcrumbs.js +1 -2
  5. package/src/groups/components/GroupCard.js +3 -3
  6. package/src/groups/components/GroupCards.js +2 -3
  7. package/src/groups/components/GroupForm.js +0 -1
  8. package/src/groups/components/GroupLoader.js +19 -51
  9. package/src/groups/components/GroupUsers.js +4 -3
  10. package/src/groups/components/GroupUsersTable.js +4 -4
  11. package/src/groups/components/GroupsLoader.js +2 -2
  12. package/src/groups/components/GroupsSearchLoader.js +1 -1
  13. package/src/groups/components/NewGroup.js +0 -1
  14. package/src/groups/components/__tests__/Group.spec.js +0 -1
  15. package/src/groups/components/__tests__/GroupCard.spec.js +23 -7
  16. package/src/groups/components/__tests__/GroupCards.spec.js +9 -6
  17. package/src/groups/components/__tests__/GroupLoader.spec.js +71 -0
  18. package/src/groups/components/__tests__/GroupUsers.spec.js +8 -12
  19. package/src/groups/components/__tests__/GroupUsersTable.spec.js +34 -42
  20. package/src/groups/components/__tests__/GroupsSearchLoader.spec.js +0 -1
  21. package/src/groups/components/__tests__/__snapshots__/Group.spec.js.snap +1 -2
  22. package/src/groups/components/__tests__/__snapshots__/GroupCard.spec.js.snap +43 -94
  23. package/src/groups/components/__tests__/__snapshots__/GroupCards.spec.js.snap +118 -53
  24. package/src/groups/components/__tests__/__snapshots__/GroupLoader.spec.js.snap +11 -0
  25. package/src/groups/components/__tests__/__snapshots__/GroupUsers.spec.js.snap +38 -45
  26. package/src/groups/components/__tests__/__snapshots__/GroupUsersTable.spec.js.snap +121 -213
  27. package/src/groups/components/index.js +1 -1
  28. package/src/groups/sagas/__tests__/deleteGroupUser.spec.js +6 -6
  29. package/src/groups/sagas/deleteGroup.js +1 -1
  30. package/src/groups/sagas/deleteGroupUser.js +2 -2
  31. package/src/groups/sagas/fetchGroup.js +1 -1
  32. package/src/groups/sagas/updateGroup.js +1 -1
  33. package/src/roles/components/NewRole.js +0 -1
  34. package/src/roles/components/PermissionGroup.js +0 -1
  35. package/src/roles/components/Role.js +8 -3
  36. package/src/roles/components/RoleCards.js +2 -3
  37. package/src/roles/components/RoleForm.js +1 -1
  38. package/src/roles/components/RoleLoader.js +26 -39
  39. package/src/roles/components/RoleRoutes.js +29 -32
  40. package/src/roles/components/RoleSelector.js +0 -1
  41. package/src/roles/components/Roles.js +1 -3
  42. package/src/roles/components/RolesLoader.js +2 -2
  43. package/src/roles/components/__tests__/PermissionGroup.spec.js +7 -17
  44. package/src/roles/components/__tests__/Role.spec.js +0 -1
  45. package/src/roles/components/__tests__/RoleCards.spec.js +11 -10
  46. package/src/roles/components/__tests__/RoleRoutes.spec.js +53 -7
  47. package/src/roles/components/__tests__/RoleSelector.spec.js +0 -1
  48. package/src/roles/components/__tests__/Roles.spec.js +2 -3
  49. package/src/roles/components/__tests__/__snapshots__/PermissionGroup.spec.js.snap +3 -5
  50. package/src/roles/components/__tests__/__snapshots__/Role.spec.js.snap +4 -4
  51. package/src/roles/components/__tests__/__snapshots__/RoleCards.spec.js.snap +57 -127
  52. package/src/roles/components/__tests__/__snapshots__/RoleRoutes.spec.js.snap +38 -5
  53. package/src/roles/components/__tests__/__snapshots__/RoleSelector.spec.js.snap +1 -1
  54. package/src/roles/components/__tests__/__snapshots__/Roles.spec.js.snap +6 -3
  55. package/src/roles/components/index.js +1 -1
  56. package/src/roles/reducers/rolePermissions.js +1 -1
  57. package/src/roles/reducers/roleRedirect.js +1 -1
  58. package/src/roles/sagas/deleteRole.js +1 -1
  59. package/src/roles/sagas/fetchRole.js +1 -1
  60. package/src/roles/sagas/fetchRolePermissions.js +1 -1
  61. package/src/roles/sagas/updateRole.js +1 -1
  62. package/src/roles/sagas/updateRolePermissions.js +1 -1
  63. package/src/sessions/components/Auth0Callback.js +5 -4
  64. package/src/sessions/components/Auth0LoginButton.js +2 -2
  65. package/src/sessions/components/AuthMethodsLoader.js +10 -19
  66. package/src/sessions/components/LoginButtons.js +4 -4
  67. package/src/sessions/components/NonceCallback.js +21 -38
  68. package/src/sessions/components/OidcLoginButton.js +0 -1
  69. package/src/sessions/components/OpenIDConnect.js +5 -4
  70. package/src/sessions/components/PrivateRoute.js +25 -57
  71. package/src/sessions/components/ProxyLoginCallback.js +0 -2
  72. package/src/sessions/components/SamlCallback.js +0 -2
  73. package/src/sessions/components/UnauthorizedRoute.js +28 -31
  74. package/src/sessions/components/__tests__/Auth0LoginButton.spec.js +12 -12
  75. package/src/sessions/components/__tests__/AuthMethodsLoader.spec.js +15 -12
  76. package/src/sessions/components/__tests__/NonceCallback.spec.js +84 -0
  77. package/src/sessions/components/__tests__/OidcLoginButton.spec.js +10 -10
  78. package/src/sessions/components/__tests__/OpenIDConnect.spec.js +7 -8
  79. package/src/sessions/components/__tests__/PrivateRoute.spec.js +90 -0
  80. package/src/sessions/components/__tests__/UnauthorizedRoute.spec.js +88 -0
  81. package/src/sessions/components/__tests__/__snapshots__/Auth0LoginButton.spec.js.snap +22 -24
  82. package/src/sessions/components/__tests__/__snapshots__/NonceCallback.spec.js.snap +18 -0
  83. package/src/sessions/components/__tests__/__snapshots__/OidcLoginButton.spec.js.snap +18 -18
  84. package/src/sessions/components/__tests__/__snapshots__/PrivateRoute.spec.js.snap +9 -0
  85. package/src/sessions/components/__tests__/__snapshots__/UnauthorizedRoute.spec.js.snap +9 -0
  86. package/src/sessions/components/index.js +1 -1
  87. package/src/sessions/sagas/__tests__/login.spec.js +4 -4
  88. package/src/sessions/sagas/__tests__/refresh.spec.js +2 -2
  89. package/src/sessions/sagas/__tests__/token.spec.js +4 -4
  90. package/src/sessions/sagas/login.js +5 -5
  91. package/src/sessions/sagas/refresh.js +2 -2
  92. package/src/sessions/sagas/token.js +2 -2
  93. package/src/users/components/AdminUserRoutes.js +35 -51
  94. package/src/users/components/EditUser.js +0 -1
  95. package/src/users/components/GroupUserCrumbs.js +8 -8
  96. package/src/users/components/InitialUser.js +0 -1
  97. package/src/users/components/NewUser.js +0 -1
  98. package/src/users/components/Password.js +0 -1
  99. package/src/users/components/User.js +2 -2
  100. package/src/users/components/UserAclRow.js +1 -2
  101. package/src/users/components/UserAcls.js +0 -1
  102. package/src/users/components/UserActions.js +1 -2
  103. package/src/users/components/UserBreadcrumbs.js +2 -3
  104. package/src/users/components/UserCard.js +3 -3
  105. package/src/users/components/UserCards.js +5 -4
  106. package/src/users/components/UserDomainsFilter.js +2 -5
  107. package/src/users/components/UserForm.js +8 -33
  108. package/src/users/components/UserGroupAclRow.js +1 -2
  109. package/src/users/components/UserGroupAcls.js +0 -1
  110. package/src/users/components/UserLoader.js +21 -48
  111. package/src/users/components/UserPassword.js +0 -1
  112. package/src/users/components/UserRoutes.js +73 -7
  113. package/src/users/components/UserSelector.js +0 -1
  114. package/src/users/components/UserTabs.js +1 -2
  115. package/src/users/components/UsersAndGroups.js +6 -6
  116. package/src/users/components/UsersLoader.js +2 -2
  117. package/src/users/components/UsersSearchLoader.js +2 -1
  118. package/src/users/components/__tests__/CanInitLoader.spec.js +6 -13
  119. package/src/users/components/__tests__/EditUser.spec.js +4 -33
  120. package/src/users/components/__tests__/InitialUser.spec.js +4 -34
  121. package/src/users/components/__tests__/NewUser.spec.js +4 -35
  122. package/src/users/components/__tests__/Password.spec.js +59 -69
  123. package/src/users/components/__tests__/User.spec.js +1 -2
  124. package/src/users/components/__tests__/UserAclRow.spec.js +5 -7
  125. package/src/users/components/__tests__/UserAcls.spec.js +8 -9
  126. package/src/users/components/__tests__/UserActions.spec.js +4 -5
  127. package/src/users/components/__tests__/UserCard.spec.js +11 -11
  128. package/src/users/components/__tests__/UserCards.spec.js +39 -31
  129. package/src/users/components/__tests__/UserDomainsFilter.spec.js +12 -22
  130. package/src/users/components/__tests__/UserForm.spec.js +24 -44
  131. package/src/users/components/__tests__/UserGroupAclRow.spec.js +1 -2
  132. package/src/users/components/__tests__/UserGroupAcls.spec.js +8 -9
  133. package/src/users/components/__tests__/UserLoader.spec.js +85 -0
  134. package/src/users/components/__tests__/UserPassword.spec.js +8 -21
  135. package/src/users/components/__tests__/UserRoutes.spec.js +129 -4
  136. package/src/users/components/__tests__/UserSelector.spec.js +0 -1
  137. package/src/users/components/__tests__/UsersAndGroups.spec.js +45 -5
  138. package/src/users/components/__tests__/UsersSearchLoader.spec.js +0 -1
  139. package/src/users/components/__tests__/__snapshots__/EditUser.spec.js.snap +23 -21
  140. package/src/users/components/__tests__/__snapshots__/InitialUser.spec.js.snap +22 -21
  141. package/src/users/components/__tests__/__snapshots__/NewUser.spec.js.snap +25 -23
  142. package/src/users/components/__tests__/__snapshots__/Password.spec.js.snap +8 -7
  143. package/src/users/components/__tests__/__snapshots__/User.spec.js.snap +7 -6
  144. package/src/users/components/__tests__/__snapshots__/UserAclRow.spec.js.snap +12 -11
  145. package/src/users/components/__tests__/__snapshots__/UserActions.spec.js.snap +56 -67
  146. package/src/users/components/__tests__/__snapshots__/UserCard.spec.js.snap +56 -70
  147. package/src/users/components/__tests__/__snapshots__/UserCards.spec.js.snap +117 -83
  148. package/src/users/components/__tests__/__snapshots__/UserDomainsFilter.spec.js.snap +2 -2
  149. package/src/users/components/__tests__/__snapshots__/UserForm.spec.js.snap +21 -20
  150. package/src/users/components/__tests__/__snapshots__/UserLoader.spec.js.snap +3 -0
  151. package/src/users/components/__tests__/__snapshots__/UserPassword.spec.js.snap +9 -7
  152. package/src/users/components/__tests__/__snapshots__/UserRoutes.spec.js.snap +170 -16
  153. package/src/users/components/__tests__/__snapshots__/UserSelector.spec.js.snap +1 -1
  154. package/src/users/components/__tests__/__snapshots__/UsersAndGroups.spec.js.snap +75 -14
  155. package/src/users/sagas/__tests__/fetchUser.spec.js +3 -5
  156. package/src/users/sagas/__tests__/updateUser.spec.js +1 -1
  157. package/src/users/sagas/deleteUser.js +1 -1
  158. package/src/users/sagas/fetchUser.js +1 -1
  159. package/src/users/sagas/updateUser.js +1 -1
  160. package/src/users/components/__tests__/__snapshots__/CanInitLoader.spec.js.snap +0 -3
@@ -1,4 +1,3 @@
1
- import React from "react";
2
1
  import PropTypes from "prop-types";
3
2
  import { Header, Container, Segment } from "semantic-ui-react";
4
3
  import { connect } from "react-redux";
@@ -1,5 +1,4 @@
1
1
  import _ from "lodash/fp";
2
- import React from "react";
3
2
  import PropTypes from "prop-types";
4
3
  import { Container, Header, Icon, Segment } from "semantic-ui-react";
5
4
  import { FormattedMessage, useIntl } from "react-intl";
@@ -1,5 +1,4 @@
1
1
  import _ from "lodash/fp";
2
- import React from "react";
3
2
  import PropTypes from "prop-types";
4
3
  import { Divider, Header, Grid, Icon, Segment } from "semantic-ui-react";
5
4
  import { connect } from "react-redux";
@@ -41,7 +40,8 @@ export const User = ({ user }) => {
41
40
  user.external_id
42
41
  ) : (
43
42
  <>
44
- {user.external_id} <br />
43
+ {user.external_id}
44
+ <br />
45
45
  </>
46
46
  )}
47
47
  {user.full_name}
@@ -1,4 +1,3 @@
1
- import React from "react";
2
1
  import PropTypes from "prop-types";
3
2
  import { Table } from "semantic-ui-react";
4
3
 
@@ -11,7 +10,7 @@ export const UserAclRow = ({ resource, role }) => (
11
10
 
12
11
  UserAclRow.propTypes = {
13
12
  resource: PropTypes.string,
14
- role: PropTypes.string
13
+ role: PropTypes.string,
15
14
  };
16
15
 
17
16
  export default UserAclRow;
@@ -1,5 +1,4 @@
1
1
  import _ from "lodash/fp";
2
- import React from "react";
3
2
  import PropTypes from "prop-types";
4
3
  import { connect } from "react-redux";
5
4
  import { Header, Table } from "semantic-ui-react";
@@ -1,6 +1,5 @@
1
1
  import _ from "lodash/fp";
2
- import React from "react";
3
- import { Link } from "react-router-dom";
2
+ import { Link } from "react-router";
4
3
  import { connect } from "react-redux";
5
4
  import PropTypes from "prop-types";
6
5
  import { Button, Icon } from "semantic-ui-react";
@@ -1,7 +1,6 @@
1
- import React from "react";
2
1
  import PropTypes from "prop-types";
3
2
  import { Breadcrumb } from "semantic-ui-react";
4
- import { Link } from "react-router-dom";
3
+ import { Link } from "react-router";
5
4
  import { FormattedMessage } from "react-intl";
6
5
  import { USERS } from "@truedat/core/routes";
7
6
 
@@ -16,7 +15,7 @@ export const UserBreadcrumbs = ({ name }) => (
16
15
  );
17
16
 
18
17
  UserBreadcrumbs.propTypes = {
19
- name: PropTypes.string
18
+ name: PropTypes.string,
20
19
  };
21
20
 
22
21
  export default UserBreadcrumbs;
@@ -1,8 +1,7 @@
1
- import React from "react";
2
1
  import PropTypes from "prop-types";
3
2
  import { connect } from "react-redux";
4
3
  import { Icon, Card } from "semantic-ui-react";
5
- import { Link } from "react-router-dom";
4
+ import { Link } from "react-router";
6
5
  import { linkTo } from "@truedat/core/routes";
7
6
  import { deleteUser } from "../routines";
8
7
 
@@ -13,7 +12,8 @@ export const UserCard = ({
13
12
  <Card key={id}>
14
13
  <Card.Content>
15
14
  <Card.Header as={Link} to={linkTo.USER({ id })}>
16
- <Icon name="user" /> {user_name}
15
+ <Icon name="user" />
16
+ {user_name}
17
17
  </Card.Header>
18
18
  <Card.Description>
19
19
  {showFullName ? full_name : external_id}
@@ -1,8 +1,8 @@
1
1
  import _ from "lodash/fp";
2
- import React, { useState } from "react";
2
+ import { Fragment, useState } from "react";
3
3
  import PropTypes from "prop-types";
4
4
  import { connect } from "react-redux";
5
- import { Link } from "react-router-dom";
5
+ import { Link } from "react-router";
6
6
  import { Button, Card, Header, Icon, Message } from "semantic-ui-react";
7
7
  import { FormattedMessage, useIntl } from "react-intl";
8
8
  import { SearchInput } from "@truedat/core/components";
@@ -19,6 +19,7 @@ export const UserCards = ({ users: allUsers, showFullName }) => {
19
19
  _.groupBy("role"),
20
20
  _.toPairs
21
21
  )(users);
22
+
22
23
  return (
23
24
  <>
24
25
  <SearchInput
@@ -35,7 +36,7 @@ export const UserCards = ({ users: allUsers, showFullName }) => {
35
36
  to={USERS_NEW}
36
37
  />
37
38
  {usersByRole.map(([role, users]) => (
38
- <React.Fragment key={role}>
39
+ <Fragment key={role}>
39
40
  <Header
40
41
  as="h3"
41
42
  dividing
@@ -46,7 +47,7 @@ export const UserCards = ({ users: allUsers, showFullName }) => {
46
47
  <UserCard key={i} user={user} showFullname={showFullName} />
47
48
  ))}
48
49
  </Card.Group>
49
- </React.Fragment>
50
+ </Fragment>
50
51
  ))}
51
52
  {_.trim(filter) !== "" && _.isEmpty(users) ? (
52
53
  <Message
@@ -1,5 +1,5 @@
1
1
  import _ from "lodash/fp";
2
- import React, { useState } from "react";
2
+ import { useState } from "react";
3
3
  import { connect } from "react-redux";
4
4
  import { Form } from "semantic-ui-react";
5
5
  import { setDashboardDomains } from "@truedat/core/routines";
@@ -45,10 +45,7 @@ export const UserDomainsFilter = ({
45
45
  disabled={domainIds === "loading"}
46
46
  onClick={onClick}
47
47
  >
48
- {formatMessage({
49
- id: "userDomainsFilter.button",
50
- defaultMessage: "Apply filters",
51
- })}
48
+ {formatMessage({ id: "userDomainsFilter.button" })}
52
49
  </Form.Button>
53
50
  </Form.Field>
54
51
  </Form.Group>
@@ -1,5 +1,4 @@
1
1
  import _ from "lodash/fp";
2
- import React from "react";
3
2
  import PropTypes from "prop-types";
4
3
  import { useIntl } from "react-intl";
5
4
  import { useForm, useWatch, Controller } from "react-hook-form";
@@ -9,6 +8,7 @@ import isEmail from "validator/lib/isEmail";
9
8
  import { HistoryBackButton } from "@truedat/core/components";
10
9
 
11
10
  const toOption = (g, i) => ({ key: i, text: g, value: g });
11
+
12
12
  const groupOptions = (groups, values) =>
13
13
  _.flow(
14
14
  _.concat(""),
@@ -20,27 +20,16 @@ const groupOptions = (groups, values) =>
20
20
  )(groups);
21
21
 
22
22
  const userTypeOptions = (formatMessage) => [
23
- {
24
- text: formatMessage({ id: "user.type.user" }),
25
- value: "user",
26
- },
27
- {
28
- text: formatMessage({ id: "user.type.admin" }),
29
- value: "admin",
30
- },
31
- {
32
- text: formatMessage({ id: "user.type.service" }),
33
- value: "service",
34
- },
35
- {
36
- text: formatMessage({ id: "user.type.agent" }),
37
- value: "agent",
38
- },
23
+ { text: formatMessage({ id: "user.type.user" }), value: "user" },
24
+ { text: formatMessage({ id: "user.type.admin" }), value: "admin" },
25
+ { text: formatMessage({ id: "user.type.service" }), value: "service" },
26
+ { text: formatMessage({ id: "user.type.agent" }), value: "agent" },
39
27
  ];
40
28
 
41
29
  export const PasswordFormFields = ({ control, errors }) => {
42
30
  const { formatMessage } = useIntl();
43
31
  const password = useWatch({ control, name: "password", defaultValue: "" });
32
+
44
33
  return (
45
34
  <>
46
35
  <Controller
@@ -55,10 +44,7 @@ export const PasswordFormFields = ({ control, errors }) => {
55
44
  value: 6,
56
45
  message: formatMessage(
57
46
  { id: "form.validation.minLength" },
58
- {
59
- prop: formatMessage({ id: "user.form.password" }),
60
- value: 6,
61
- }
47
+ { prop: formatMessage({ id: "user.form.password" }), value: 6 }
62
48
  ),
63
49
  },
64
50
  }}
@@ -130,22 +116,11 @@ export const UserForm = ({ isSubmitting, onSubmit, user, groups }) => {
130
116
  rep_password: "",
131
117
  ...user,
132
118
  },
133
- /*
134
- * Remove PasswordFormFields' inputs (password, rep_password) if it is not
135
- * mounted (user update). Keep them if it is mounted (user creation).
136
- * Otherwise, td-auth returns forbidden because password updates are handled
137
- * in the Password form, using /api/password, not in this UserForm that
138
- * PUTs to /api/users/<user_id>
139
- * https://stackoverflow.com/q/70105636
140
- * This was not needed in v6, but it is in v7:
141
- * https://react-hook-form.com/migrate-v6-to-v7/
142
- * Important: input value and reference will no longer get removed after
143
- * unmount unless shouldUnregister is true.
144
- */
145
119
  shouldUnregister: true,
146
120
  });
147
121
 
148
122
  const { errors, isDirty, isValid } = formState;
123
+
149
124
  return (
150
125
  <Form onSubmit={handleSubmit(onSubmit)}>
151
126
  <Controller
@@ -1,4 +1,3 @@
1
- import React from "react";
2
1
  import PropTypes from "prop-types";
3
2
  import { Table } from "semantic-ui-react";
4
3
 
@@ -13,7 +12,7 @@ export const UserGroupAclRow = ({ resource, role, group }) => (
13
12
  UserGroupAclRow.propTypes = {
14
13
  resource: PropTypes.string,
15
14
  role: PropTypes.string,
16
- group: PropTypes.string
15
+ group: PropTypes.string,
17
16
  };
18
17
 
19
18
  export default UserGroupAclRow;
@@ -1,5 +1,4 @@
1
1
  import _ from "lodash/fp";
2
- import React from "react";
3
2
  import PropTypes from "prop-types";
4
3
  import { connect } from "react-redux";
5
4
  import { Header, Table } from "semantic-ui-react";
@@ -1,59 +1,32 @@
1
- import React from "react";
2
- import { withRouter } from "react-router-dom";
1
+ import { useEffect } from "react";
2
+ import { useParams } from "react-router";
3
3
  import PropTypes from "prop-types";
4
- import { compose } from "redux";
5
- import { connect } from "react-redux";
4
+ import { useDispatch, useSelector } from "react-redux";
6
5
  import { Loading } from "@truedat/core/components";
7
6
  import { clearUser, fetchUser } from "../routines";
8
7
 
9
- class UserLoader extends React.Component {
10
- static propTypes = {
11
- fetchUser: PropTypes.func.isRequired,
12
- clearUser: PropTypes.func.isRequired,
13
- match: PropTypes.object.isRequired,
14
- userLoading: PropTypes.bool.isRequired,
15
- };
8
+ function UserLoader() {
9
+ const dispatch = useDispatch();
10
+ const userLoading = useSelector((state) => state.userLoading);
11
+ const { id } = useParams();
16
12
 
17
- componentDidMount() {
18
- const { clearUser, fetchUser, match } = this.props;
19
- if (match) {
20
- const { id } = match.params;
21
- if (id) {
22
- fetchUser({ id });
23
- } else {
24
- clearUser();
25
- }
13
+ useEffect(() => {
14
+ if (id) {
15
+ dispatch(fetchUser({ id }));
16
+ } else {
17
+ dispatch(clearUser());
26
18
  }
27
- }
28
19
 
29
- componentDidUpdate(prevProps) {
30
- const { clearUser, fetchUser, match } = this.props;
31
- if (match) {
32
- const { id } = match.params;
33
- if (prevProps.match.params.id !== id) {
34
- if (id) {
35
- fetchUser({ id });
36
- } else {
37
- clearUser();
38
- }
39
- }
40
- }
41
- }
42
-
43
- componentWillUnmount() {
44
- const { clearUser } = this.props;
45
- clearUser();
46
- }
20
+ return () => {
21
+ dispatch(clearUser());
22
+ };
23
+ }, [id, dispatch]);
47
24
 
48
- render() {
49
- const { userLoading } = this.props;
50
- return userLoading ? <Loading /> : null;
51
- }
25
+ return userLoading ? <Loading /> : null;
52
26
  }
53
27
 
54
- const mapStateToProps = ({ userLoading }) => ({ userLoading });
28
+ UserLoader.propTypes = {
29
+ userLoading: PropTypes.bool,
30
+ };
55
31
 
56
- export default compose(
57
- withRouter,
58
- connect(mapStateToProps, { clearUser, fetchUser })
59
- )(UserLoader);
32
+ export default UserLoader;
@@ -1,5 +1,4 @@
1
1
  import _ from "lodash/fp";
2
- import React from "react";
3
2
  import { connect } from "react-redux";
4
3
  import PropTypes from "prop-types";
5
4
  import { useIntl } from "react-intl";
@@ -1,14 +1,80 @@
1
- import React from "react";
2
- import { Route } from "react-router-dom";
3
- import { PASSWORD } from "@truedat/core/routes";
4
- import AdminUserRoutes from "./AdminUserRoutes";
1
+ import { Routes, Route } from "react-router";
2
+ import { ProtectedRoute, Loader } from "@truedat/core/router";
3
+ import { Divider, Segment } from "semantic-ui-react";
5
4
  import Password from "./Password";
6
5
 
7
- export const UserRoutes = () => (
6
+ import GroupsLoader from "../../groups/components/GroupsLoader";
7
+ import GroupLoader from "../../groups/components/GroupLoader";
8
+ import Group from "../../groups/components/Group";
9
+ import GroupUsers from "../../groups/components/GroupUsers";
10
+ import NewGroup from "../../groups/components/NewGroup";
11
+ import EditGroup from "../../groups/components/EditGroup";
12
+ import EditUser from "./EditUser";
13
+ import GroupUserCrumbs from "./GroupUserCrumbs";
14
+ import NewUser from "./NewUser";
15
+ import User from "./User";
16
+ import UserLoader from "./UserLoader";
17
+ import UsersAndGroups from "./UsersAndGroups";
18
+ import UsersLoader from "./UsersLoader";
19
+ import UserPassword from "./UserPassword";
20
+
21
+ const UsersGroupsLoader = () => (
8
22
  <>
9
- <AdminUserRoutes />
10
- <Route path={PASSWORD} component={Password} />
23
+ <UsersLoader />
24
+ <GroupsLoader />
11
25
  </>
12
26
  );
13
27
 
28
+ export const UserRoutes = () => (
29
+ <Routes>
30
+ <Route
31
+ path={"users"}
32
+ element={
33
+ <ProtectedRoute>
34
+ <Loader loaders={<UsersGroupsLoader />} />
35
+ </ProtectedRoute>
36
+ }
37
+ >
38
+ <Route index element={<UsersAndGroups />} />
39
+ <Route path={"new"} element={<NewUser />} />
40
+
41
+ <Route path={":id"} element={<Loader loaders={<UserLoader />} />}>
42
+ <Route index element={<User />} />
43
+ <Route path={"edit"} element={<EditUser />} />
44
+ <Route path={"password"} element={<UserPassword />} />
45
+ </Route>
46
+ </Route>
47
+ <Route
48
+ path={"groups"}
49
+ element={
50
+ <ProtectedRoute>
51
+ <Loader loaders={<UsersGroupsLoader />} />
52
+ </ProtectedRoute>
53
+ }
54
+ >
55
+ <Route index element={<UsersAndGroups />} />
56
+ <Route path={"new"} element={<NewGroup />} />
57
+
58
+ <Route path={":id"} element={<Loader loaders={<GroupLoader />} />}>
59
+ <Route
60
+ index
61
+ element={
62
+ <>
63
+ <GroupUserCrumbs action="show" />
64
+ <Segment>
65
+ <Group />
66
+ <Divider />
67
+ <GroupUsers />
68
+ </Segment>
69
+ </>
70
+ }
71
+ />
72
+ <Route path={"edit"} element={<EditGroup />} />
73
+ </Route>
74
+ </Route>
75
+ <Route path={"password"} element={<Password />} />
76
+ <Route path="*" element={null} />
77
+ </Routes>
78
+ );
79
+
14
80
  export default UserRoutes;
@@ -1,5 +1,4 @@
1
1
  import _ from "lodash/fp";
2
- import React from "react";
3
2
  import PropTypes from "prop-types";
4
3
  import { connect } from "react-redux";
5
4
  import { useIntl } from "react-intl";
@@ -1,5 +1,4 @@
1
- import React from "react";
2
- import { Link } from "react-router-dom";
1
+ import { Link } from "react-router";
3
2
  import { FormattedMessage } from "react-intl";
4
3
  import { Menu } from "semantic-ui-react";
5
4
  import { usePath } from "@truedat/core/hooks";
@@ -1,8 +1,8 @@
1
- import React from "react";
2
1
  import { connect } from "react-redux";
3
- import { Route, Switch } from "react-router-dom";
2
+ import { Route, Routes } from "react-router";
4
3
  import { Header, Icon, Segment } from "semantic-ui-react";
5
4
  import { FormattedMessage, useIntl } from "react-intl";
5
+ import { usePath } from "@truedat/core/hooks";
6
6
  import { GROUPS, USERS } from "@truedat/core/routes";
7
7
  import GroupCards from "../../groups/components/GroupCards";
8
8
  import UserCards from "./UserCards";
@@ -10,6 +10,8 @@ import UserTabs from "./UserTabs";
10
10
 
11
11
  export const UsersAndGroups = () => {
12
12
  const { formatMessage } = useIntl();
13
+ const path = usePath();
14
+
13
15
  return (
14
16
  <Segment>
15
17
  <Header as="h2">
@@ -29,10 +31,8 @@ export const UsersAndGroups = () => {
29
31
  </Header>
30
32
  <UserTabs />
31
33
  <Segment attached="bottom">
32
- <Switch>
33
- <Route path={USERS} render={() => <UserCards />} exact />
34
- <Route path={GROUPS} render={() => <GroupCards />} exact />
35
- </Switch>
34
+ {path === USERS && <UserCards />}
35
+ {path === GROUPS && <GroupCards />}
36
36
  </Segment>
37
37
  </Segment>
38
38
  );
@@ -1,10 +1,10 @@
1
- import React from "react";
1
+ import { Component } from "react";
2
2
  import PropTypes from "prop-types";
3
3
  import { connect } from "react-redux";
4
4
  import { Loading } from "@truedat/core/components";
5
5
  import { fetchUsers } from "../routines";
6
6
 
7
- class UsersLoader extends React.Component {
7
+ class UsersLoader extends Component {
8
8
  static propTypes = {
9
9
  fetchUsers: PropTypes.func,
10
10
  usersLoading: PropTypes.bool,
@@ -1,5 +1,5 @@
1
1
  import _ from "lodash/fp";
2
- import React, { useEffect } from "react";
2
+ import { useEffect } from "react";
3
3
  import PropTypes from "prop-types";
4
4
  import { connect } from "react-redux";
5
5
  import { Dimmer, Loader } from "semantic-ui-react";
@@ -28,6 +28,7 @@ export const UsersSearchLoader = ({
28
28
  clearUsersSearch();
29
29
  };
30
30
  }, [searchUsers, clearUsersSearch, query, domains, roles, permission]);
31
+
31
32
  return loading && !hideLoading ? (
32
33
  <Dimmer active inverted>
33
34
  <Loader size="massive" inverted />
@@ -1,21 +1,14 @@
1
- import React from "react";
2
- import { shallow, mount } from "enzyme";
1
+ import { render, waitForLoad } from "@truedat/test/render";
3
2
  import { CanInitLoader } from "../CanInitLoader";
4
3
 
5
4
  describe("<CanInitLoader />", () => {
6
- const fetchCanInit = jest.fn();
7
-
8
- it("matches the latest snapshot", () => {
5
+ it("triggers fetchCanInit on mount", async () => {
6
+ const fetchCanInit = jest.fn();
9
7
  const props = { fetchCanInit };
10
- const wrapper = shallow(<CanInitLoader {...props} />);
11
- expect(wrapper).toMatchSnapshot();
12
- });
13
8
 
14
- it("calls fetchCanInit when component mounts", () => {
15
- const fetchCanInit = jest.fn();
9
+ const rendered = render(<CanInitLoader {...props} />);
10
+ await waitForLoad(rendered);
16
11
 
17
- const props = { fetchCanInit };
18
- mount(<CanInitLoader {...props} />);
19
- expect(fetchCanInit.mock.calls.length).toBe(1);
12
+ expect(fetchCanInit).toHaveBeenCalledTimes(1);
20
13
  });
21
14
  });
@@ -1,37 +1,7 @@
1
- import React from "react";
2
- import { waitFor } from "@testing-library/react";
3
- import { render } from "@truedat/test/render";
1
+ import { render, waitForLoad } from "@truedat/test/render";
4
2
  import EditUser from "../EditUser";
5
3
 
6
4
  const renderOpts = {
7
- messages: {
8
- en: {
9
- "actions.cancel": "cancel",
10
- "actions.save": "save",
11
- "form.validation.minLength": "{prop} min length {value}",
12
- "form.validation.required": "{prop} required",
13
- "navigation.members.users": "Users",
14
- "user.form.email": "Email address",
15
- "user.form.external_id": "External ID",
16
- "user.form.full_name": "Full name",
17
- "user.form.groups": "Groups",
18
- "user.form.password": "password",
19
- "user.form.user_name": "Username",
20
- "user.form.password_confirmation": "confirm",
21
- "user.form.placeholder.email": "pperez@example.com",
22
- "user.form.placeholder.external_id": "pperez",
23
- "user.form.placeholder.full_name": "Pepe Perez",
24
- "user.form.placeholder.user_name": "pperez",
25
- "user.form.placeholder.groups": "Madrid DG",
26
- "user.form.role": "role",
27
- "user.type.admin": "admin",
28
- "user.type.service": "service",
29
- "user.type.user": "user",
30
- "user.type.agent": "Ai Agent",
31
- "users.actions.create": "create",
32
- "users.actions.edit": "edit",
33
- },
34
- },
35
5
  state: {
36
6
  user: { id: 123, user_name: "fred", full_name: "fredrik foobar" },
37
7
  },
@@ -39,7 +9,8 @@ const renderOpts = {
39
9
 
40
10
  describe("<EditUser />", () => {
41
11
  it("matches the latest snapshot", async () => {
42
- const { container } = render(<EditUser />, renderOpts);
43
- await waitFor(() => expect(container).toMatchSnapshot());
12
+ const rendered = render(<EditUser />, renderOpts);
13
+ await waitForLoad(rendered);
14
+ expect(rendered.container).toMatchSnapshot();
44
15
  });
45
16
  });
@@ -1,40 +1,10 @@
1
- import React from "react";
2
- import { waitFor } from "@testing-library/react";
3
- import { render } from "@truedat/test/render";
1
+ import { render, waitForLoad } from "@truedat/test/render";
4
2
  import InitialUser from "../InitialUser";
5
3
 
6
- const renderOpts = {
7
- messages: {
8
- en: {
9
- "actions.cancel": "cancel",
10
- "actions.save": "save",
11
- "form.validation.minLength": "{prop} min length {value}",
12
- "form.validation.required": "{prop} required",
13
- "users.actions.create_admin_account": "Configure Admin Account",
14
- "user.form.email": "Email address",
15
- "user.form.external_id": "External ID",
16
- "user.form.full_name": "Full name",
17
- "user.form.groups": "Groups",
18
- "user.form.password": "password",
19
- "user.form.user_name": "Username",
20
- "user.form.password_confirmation": "confirm",
21
- "user.form.placeholder.email": "pperez@example.com",
22
- "user.form.placeholder.external_id": "pperez",
23
- "user.form.placeholder.full_name": "Pepe Perez",
24
- "user.form.placeholder.user_name": "pperez",
25
- "user.form.placeholder.groups": "Madrid DG",
26
- "user.form.role": "role",
27
- "user.type.admin": "admin",
28
- "user.type.service": "service",
29
- "user.type.user": "user",
30
- "user.type.agent": "Ai Agent",
31
- },
32
- },
33
- };
34
-
35
4
  describe("<InitialUser />", () => {
36
5
  it("matches the latest snapshot", async () => {
37
- const { container } = render(<InitialUser />, renderOpts);
38
- await waitFor(() => expect(container).toMatchSnapshot());
6
+ const rendered = render(<InitialUser />);
7
+ await waitForLoad(rendered);
8
+ expect(rendered.container).toMatchSnapshot();
39
9
  });
40
10
  });