@truedat/auth 8.14.3 → 8.14.5
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 +4 -4
- package/src/groups/components/GroupCard.js +2 -2
- package/src/groups/components/GroupCards.js +129 -37
- package/src/groups/components/GroupForm.js +13 -7
- package/src/groups/components/GroupFormModal.js +8 -7
- package/src/groups/components/GroupInfoModal.js +6 -6
- package/src/groups/components/GroupMemberPicker.js +2 -4
- package/src/groups/components/GroupRouteModal.js +15 -10
- package/src/groups/components/__tests__/GroupCards.spec.js +94 -0
- package/src/groups/components/__tests__/GroupForm.spec.js +2 -2
- package/src/groups/components/__tests__/GroupModals.spec.js +42 -16
- package/src/groups/components/__tests__/__snapshots__/GroupCards.spec.js.snap +14 -0
- package/src/messages/en.js +6 -5
- package/src/messages/es.js +8 -7
- package/src/styles/Groups.less +96 -131
- package/src/styles/UserCard.less +416 -0
- package/src/styles/UserModals.less +831 -0
- package/src/styles/Users.less +313 -0
- package/src/users/components/AdminUserRoutes.js +7 -20
- package/src/users/components/EditUser.js +7 -34
- package/src/users/components/EditUserModal.js +150 -0
- package/src/users/components/NewUser.js +128 -17
- package/src/users/components/Password.js +11 -189
- package/src/users/components/UserAcls.js +117 -6
- package/src/users/components/UserActions.js +99 -34
- package/src/users/components/UserCard.js +171 -22
- package/src/users/components/UserCards.js +188 -35
- package/src/users/components/UserFormFields.js +206 -0
- package/src/users/components/UserGroupAclRow.js +8 -2
- package/src/users/components/UserGroupAcls.js +2 -2
- package/src/users/components/UserGroupLink.js +21 -0
- package/src/users/components/UserInfoModal.js +228 -0
- package/src/users/components/UserPasswordField.js +66 -0
- package/src/users/components/UserPasswordModal.js +210 -0
- package/src/users/components/UserRoutes.js +4 -13
- package/src/users/components/UserTabs.js +5 -2
- package/src/users/components/UserTypeSelector.js +109 -0
- package/src/users/components/UsersAndGroups.js +39 -5
- package/src/users/components/UsersTable.js +234 -0
- package/src/users/components/__tests__/EditUser.spec.js +84 -10
- package/src/users/components/__tests__/NewUser.spec.js +34 -4
- package/src/users/components/__tests__/Password.spec.js +53 -146
- package/src/users/components/__tests__/UserAcls.spec.js +62 -2
- package/src/users/components/__tests__/UserCard.spec.js +111 -5
- package/src/users/components/__tests__/UserCards.spec.js +149 -0
- package/src/users/components/__tests__/UserGroupAclRow.spec.js +19 -1
- package/src/users/components/__tests__/UserModals.spec.js +554 -0
- package/src/users/components/__tests__/UserRoutes.spec.js +8 -3
- package/src/users/components/__tests__/UserTypeSelector.spec.js +32 -0
- package/src/users/components/__tests__/UsersAndGroups.spec.js +17 -0
- package/src/users/components/__tests__/__snapshots__/UserCard.spec.js.snap +66 -37
- package/src/users/components/__tests__/__snapshots__/UserCards.spec.js.snap +375 -75
- package/src/users/components/__tests__/__snapshots__/UserGroupAclRow.spec.js.snap +7 -3
- package/src/users/components/__tests__/__snapshots__/UserRoutes.spec.js.snap +4 -13
- package/src/users/hooks/useSortedGroups.js +13 -0
- package/src/users/hooks/useUserModalOperation.js +55 -0
- package/src/users/reducers/__tests__/userRedirect.spec.js +14 -3
- package/src/users/reducers/index.js +1 -0
- package/src/users/reducers/userModalOperation.js +29 -0
- package/src/users/reducers/userRedirect.js +5 -4
- package/src/users/sagas/__tests__/updateUser.spec.js +19 -1
- package/src/users/sagas/createUser.js +12 -5
- package/src/users/sagas/deleteUser.js +12 -5
- package/src/users/sagas/updateUser.js +19 -8
- package/src/users/selectors/__tests__/filterUsers.spec.js +11 -0
- package/src/users/selectors/__tests__/getUserAcls.spec.js +1 -0
- package/src/users/selectors/__tests__/getUserGroupAcls.spec.js +2 -0
- package/src/users/selectors/filterUsers.js +9 -1
- package/src/users/selectors/getUserGroupAcls.js +1 -0
- package/src/users/components/User.js +0 -68
- package/src/users/components/UserPassword.js +0 -24
- package/src/users/components/__tests__/User.spec.js +0 -20
- package/src/users/components/__tests__/UserPassword.spec.js +0 -24
- package/src/users/components/__tests__/__snapshots__/EditUser.spec.js.snap +0 -281
- package/src/users/components/__tests__/__snapshots__/NewUser.spec.js.snap +0 -321
- package/src/users/components/__tests__/__snapshots__/Password.spec.js.snap +0 -128
- package/src/users/components/__tests__/__snapshots__/User.spec.js.snap +0 -129
- package/src/users/components/__tests__/__snapshots__/UserPassword.spec.js.snap +0 -124
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { useEffect, useId, useRef } from "react";
|
|
2
|
+
import { useDispatch, useSelector } from "react-redux";
|
|
3
|
+
import { useIntl } from "react-intl";
|
|
4
|
+
import { clearUserModalOperation } from "../reducers/userModalOperation";
|
|
5
|
+
|
|
6
|
+
export default function useUserModalOperation(
|
|
7
|
+
routine,
|
|
8
|
+
onClose,
|
|
9
|
+
onSuccess = onClose,
|
|
10
|
+
) {
|
|
11
|
+
const id = useId();
|
|
12
|
+
const dispatch = useDispatch();
|
|
13
|
+
const { formatMessage } = useIntl();
|
|
14
|
+
const request = useRef(0);
|
|
15
|
+
const pending = useRef(false);
|
|
16
|
+
const operation = useSelector((state) => state.userModalOperation?.[id]);
|
|
17
|
+
const isSubmitting = operation?.status === "pending";
|
|
18
|
+
|
|
19
|
+
useEffect(() => () => dispatch(clearUserModalOperation(id)), [dispatch, id]);
|
|
20
|
+
|
|
21
|
+
useEffect(() => {
|
|
22
|
+
if (operation?.requestId !== request.current || !pending.current) return;
|
|
23
|
+
if (operation.status === "error") pending.current = false;
|
|
24
|
+
if (operation.status === "success") {
|
|
25
|
+
pending.current = false;
|
|
26
|
+
onSuccess();
|
|
27
|
+
}
|
|
28
|
+
}, [operation, onSuccess]);
|
|
29
|
+
|
|
30
|
+
const submit = (payload) => {
|
|
31
|
+
if (pending.current) return;
|
|
32
|
+
pending.current = true;
|
|
33
|
+
request.current += 1;
|
|
34
|
+
dispatch({
|
|
35
|
+
...routine(payload),
|
|
36
|
+
meta: { userModalId: id, requestId: request.current },
|
|
37
|
+
});
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
return {
|
|
41
|
+
submit,
|
|
42
|
+
isSubmitting,
|
|
43
|
+
onClose: () => {
|
|
44
|
+
if (!pending.current) onClose();
|
|
45
|
+
},
|
|
46
|
+
error:
|
|
47
|
+
operation?.status === "error"
|
|
48
|
+
? formatMessage({
|
|
49
|
+
id: "user.modal.operation.error",
|
|
50
|
+
defaultMessage:
|
|
51
|
+
"The operation could not be completed. Please try again.",
|
|
52
|
+
})
|
|
53
|
+
: null,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { linkTo } from "@truedat/core/routes";
|
|
2
1
|
import { clearRedirect } from "@truedat/core/routines";
|
|
3
2
|
import { createUser, deleteUser, updateUser } from "../../routines";
|
|
4
3
|
import { userRedirect } from "..";
|
|
@@ -27,12 +26,24 @@ describe("reducers: userRedirect", () => {
|
|
|
27
26
|
|
|
28
27
|
it("should handle the updateUser.SUCCESS action", () => {
|
|
29
28
|
const payload = { data: { id: "1" } };
|
|
30
|
-
const url = linkTo.USER({ id: "1" });
|
|
31
29
|
expect(userRedirect("foo", { type: updateUser.SUCCESS, payload })).toBe(
|
|
32
|
-
|
|
30
|
+
"/users/1",
|
|
33
31
|
);
|
|
34
32
|
});
|
|
35
33
|
|
|
34
|
+
it.each([createUser.SUCCESS, updateUser.SUCCESS])(
|
|
35
|
+
"preserves the redirect for modal operation %s",
|
|
36
|
+
(type) => {
|
|
37
|
+
expect(
|
|
38
|
+
userRedirect("foo", {
|
|
39
|
+
type,
|
|
40
|
+
payload: { data: { id: "1" } },
|
|
41
|
+
meta: { userModalId: "modal", requestId: 1 },
|
|
42
|
+
}),
|
|
43
|
+
).toBe("foo");
|
|
44
|
+
},
|
|
45
|
+
);
|
|
46
|
+
|
|
36
47
|
it("should ignore unknown actions", () => {
|
|
37
48
|
expect(userRedirect("foo", { type: "bar", payload })).toEqual("foo");
|
|
38
49
|
});
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import _ from "lodash/fp";
|
|
2
|
+
import {
|
|
3
|
+
createUser,
|
|
4
|
+
updateUser,
|
|
5
|
+
updatePassword,
|
|
6
|
+
deleteUser,
|
|
7
|
+
} from "../routines";
|
|
8
|
+
|
|
9
|
+
export const clearUserModalOperation = (id) => ({
|
|
10
|
+
type: "CLEAR_USER_MODAL_OPERATION",
|
|
11
|
+
payload: id,
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
export const userModalOperation = (state = {}, { type, meta, payload }) => {
|
|
15
|
+
if (type === "CLEAR_USER_MODAL_OPERATION") return _.omit([payload])(state);
|
|
16
|
+
if (!meta?.userModalId) return state;
|
|
17
|
+
const { userModalId, requestId } = meta;
|
|
18
|
+
const routines = [createUser, updateUser, updatePassword, deleteUser];
|
|
19
|
+
if (routines.some((routine) => routine.TRIGGER === type)) {
|
|
20
|
+
return { ...state, [userModalId]: { requestId, status: "pending" } };
|
|
21
|
+
}
|
|
22
|
+
if (state[userModalId]?.requestId !== requestId) return state;
|
|
23
|
+
const status = routines.some((routine) => routine.SUCCESS === type)
|
|
24
|
+
? "success"
|
|
25
|
+
: routines.some((routine) => routine.FAILURE === type)
|
|
26
|
+
? "error"
|
|
27
|
+
: null;
|
|
28
|
+
return status ? { ...state, [userModalId]: { requestId, status } } : state;
|
|
29
|
+
};
|
|
@@ -5,15 +5,16 @@ import { createUser, deleteUser, updateUser } from "../routines";
|
|
|
5
5
|
|
|
6
6
|
const initialState = "";
|
|
7
7
|
|
|
8
|
-
export const userRedirect = (state = initialState, { type, payload }) => {
|
|
8
|
+
export const userRedirect = (state = initialState, { type, payload, meta }) => {
|
|
9
9
|
switch (type) {
|
|
10
10
|
case clearRedirect.TRIGGER:
|
|
11
11
|
return initialState;
|
|
12
12
|
case createUser.SUCCESS:
|
|
13
|
-
return USERS;
|
|
13
|
+
return meta?.userModalId ? state : USERS;
|
|
14
14
|
case updateUser.SUCCESS:
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
return meta?.userModalId
|
|
16
|
+
? state
|
|
17
|
+
: linkTo.USER({ ..._.get("data")(payload) });
|
|
17
18
|
case deleteUser.SUCCESS:
|
|
18
19
|
return state;
|
|
19
20
|
default:
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
updatePasswordSaga,
|
|
8
8
|
} from "../updateUser";
|
|
9
9
|
import { updateUser, updatePassword } from "../../routines";
|
|
10
|
-
import { API_USER } from "../../api";
|
|
10
|
+
import { API_USER, API_USER_CHANGE_PASSWORD } from "../../api";
|
|
11
11
|
|
|
12
12
|
describe("sagas: updateUserRequestSaga", () => {
|
|
13
13
|
it("should invoke updateUserSaga on updateUser.TRIGGER", () => {
|
|
@@ -94,3 +94,21 @@ describe("sagas: updateUserSaga", () => {
|
|
|
94
94
|
}).not.toThrow();
|
|
95
95
|
});
|
|
96
96
|
});
|
|
97
|
+
|
|
98
|
+
it("changes the current password without requesting the administrative user list", () => {
|
|
99
|
+
const payload = {
|
|
100
|
+
user: { old_password: "old-example", new_password: "new-example" },
|
|
101
|
+
};
|
|
102
|
+
const meta = { userModalId: "self-password", requestId: 1 };
|
|
103
|
+
testSaga(updatePasswordSaga, { payload, meta })
|
|
104
|
+
.next()
|
|
105
|
+
.put(updatePassword.request())
|
|
106
|
+
.next()
|
|
107
|
+
.call(apiJsonPut, API_USER_CHANGE_PASSWORD, payload, JSON_OPTS)
|
|
108
|
+
.next({ data: {} })
|
|
109
|
+
.put({ ...updatePassword.success({}), meta })
|
|
110
|
+
.next()
|
|
111
|
+
.put(updatePassword.fulfill())
|
|
112
|
+
.next()
|
|
113
|
+
.isDone();
|
|
114
|
+
});
|
|
@@ -1,21 +1,28 @@
|
|
|
1
1
|
import { call, put, takeLatest } from "redux-saga/effects";
|
|
2
2
|
import { apiJsonPost, JSON_OPTS } from "@truedat/core/services/api";
|
|
3
|
-
import { createUser } from "../routines";
|
|
3
|
+
import { createUser, fetchUsers } from "../routines";
|
|
4
4
|
import { API_USERS } from "../api";
|
|
5
5
|
|
|
6
|
-
export function* createUserSaga({ payload: user }) {
|
|
6
|
+
export function* createUserSaga({ payload: user, meta }) {
|
|
7
7
|
try {
|
|
8
8
|
const url = API_USERS;
|
|
9
9
|
const requestData = { user };
|
|
10
10
|
yield put(createUser.request());
|
|
11
11
|
const { data } = yield call(apiJsonPost, url, requestData, JSON_OPTS);
|
|
12
|
-
yield put(createUser.success(data));
|
|
12
|
+
yield put({ ...createUser.success(data), ...(meta ? { meta } : {}) });
|
|
13
|
+
if (meta?.userModalId) yield put(fetchUsers());
|
|
13
14
|
} catch (error) {
|
|
14
15
|
if (error.response) {
|
|
15
16
|
const { status, data } = error.response;
|
|
16
|
-
yield put(
|
|
17
|
+
yield put({
|
|
18
|
+
...createUser.failure({ status, data }),
|
|
19
|
+
...(meta ? { meta } : {}),
|
|
20
|
+
});
|
|
17
21
|
} else {
|
|
18
|
-
yield put(
|
|
22
|
+
yield put({
|
|
23
|
+
...createUser.failure(error.message),
|
|
24
|
+
...(meta ? { meta } : {}),
|
|
25
|
+
});
|
|
19
26
|
}
|
|
20
27
|
} finally {
|
|
21
28
|
yield put(createUser.fulfill());
|
|
@@ -1,24 +1,31 @@
|
|
|
1
1
|
import { compile } from "path-to-regexp";
|
|
2
2
|
import { call, put, takeLatest } from "redux-saga/effects";
|
|
3
3
|
import { apiJsonDelete, JSON_OPTS } from "@truedat/core/services/api";
|
|
4
|
-
import { deleteUser } from "../routines";
|
|
4
|
+
import { deleteUser, fetchUsers } from "../routines";
|
|
5
5
|
import { API_USER } from "../api";
|
|
6
6
|
|
|
7
7
|
const toApiPath = compile(API_USER);
|
|
8
8
|
|
|
9
|
-
export function* deleteUserSaga({ payload }) {
|
|
9
|
+
export function* deleteUserSaga({ payload, meta }) {
|
|
10
10
|
try {
|
|
11
11
|
const user = payload;
|
|
12
12
|
const url = toApiPath({ id: `${user.id}` });
|
|
13
13
|
yield put(deleteUser.request());
|
|
14
14
|
const { data } = yield call(apiJsonDelete, url, JSON_OPTS);
|
|
15
|
-
yield put(deleteUser.success(data));
|
|
15
|
+
yield put({ ...deleteUser.success(data), ...(meta ? { meta } : {}) });
|
|
16
|
+
if (meta?.userModalId) yield put(fetchUsers());
|
|
16
17
|
} catch (error) {
|
|
17
18
|
if (error.response) {
|
|
18
19
|
const { status, data } = error.response;
|
|
19
|
-
yield put(
|
|
20
|
+
yield put({
|
|
21
|
+
...deleteUser.failure({ status, data }),
|
|
22
|
+
...(meta ? { meta } : {}),
|
|
23
|
+
});
|
|
20
24
|
} else {
|
|
21
|
-
yield put(
|
|
25
|
+
yield put({
|
|
26
|
+
...deleteUser.failure(error.message),
|
|
27
|
+
...(meta ? { meta } : {}),
|
|
28
|
+
});
|
|
22
29
|
}
|
|
23
30
|
} finally {
|
|
24
31
|
yield put(deleteUser.fulfill());
|
|
@@ -1,36 +1,47 @@
|
|
|
1
1
|
import { compile } from "path-to-regexp";
|
|
2
2
|
import { all, call, put, takeLatest } from "redux-saga/effects";
|
|
3
3
|
import { apiJsonPut, JSON_OPTS } from "@truedat/core/services/api";
|
|
4
|
-
import { updateUser, updatePassword } from "../routines";
|
|
4
|
+
import { updateUser, updatePassword, fetchUsers } from "../routines";
|
|
5
5
|
import { API_USER, API_USER_CHANGE_PASSWORD } from "../api";
|
|
6
6
|
|
|
7
|
-
export function* updateUserSaga({ payload: user }) {
|
|
7
|
+
export function* updateUserSaga({ payload: user, meta }) {
|
|
8
8
|
try {
|
|
9
9
|
const url = compile(API_USER)({ id: `${user.id}` });
|
|
10
10
|
const requestData = { user };
|
|
11
11
|
yield put(updateUser.request());
|
|
12
12
|
const { data } = yield call(apiJsonPut, url, requestData, JSON_OPTS);
|
|
13
|
-
yield put(updateUser.success(data));
|
|
13
|
+
yield put({ ...updateUser.success(data), ...(meta ? { meta } : {}) });
|
|
14
|
+
if (meta?.userModalId) yield put(fetchUsers());
|
|
14
15
|
} catch (error) {
|
|
15
16
|
if (error.response) {
|
|
16
17
|
const { status, data } = error.response;
|
|
17
|
-
yield put(
|
|
18
|
+
yield put({
|
|
19
|
+
...updateUser.failure({ status, data }),
|
|
20
|
+
...(meta ? { meta } : {}),
|
|
21
|
+
});
|
|
18
22
|
} else {
|
|
19
|
-
yield put(
|
|
23
|
+
yield put({
|
|
24
|
+
...updateUser.failure(error.message),
|
|
25
|
+
...(meta ? { meta } : {}),
|
|
26
|
+
});
|
|
20
27
|
}
|
|
21
28
|
} finally {
|
|
22
29
|
yield put(updateUser.fulfill());
|
|
23
30
|
}
|
|
24
31
|
}
|
|
25
32
|
|
|
26
|
-
export function* updatePasswordSaga({ payload }) {
|
|
33
|
+
export function* updatePasswordSaga({ payload, meta }) {
|
|
27
34
|
try {
|
|
28
35
|
const url = API_USER_CHANGE_PASSWORD;
|
|
29
36
|
yield put(updatePassword.request());
|
|
30
37
|
const { data } = yield call(apiJsonPut, url, payload, JSON_OPTS);
|
|
31
|
-
yield put(updatePassword.success(data));
|
|
38
|
+
yield put({ ...updatePassword.success(data), ...(meta ? { meta } : {}) });
|
|
39
|
+
if (meta?.userModalId && payload.user.id) yield put(fetchUsers());
|
|
32
40
|
} catch (error) {
|
|
33
|
-
yield put(
|
|
41
|
+
yield put({
|
|
42
|
+
...updatePassword.failure(error.message),
|
|
43
|
+
...(meta ? { meta } : {}),
|
|
44
|
+
});
|
|
34
45
|
} finally {
|
|
35
46
|
yield put(updatePassword.fulfill());
|
|
36
47
|
}
|
|
@@ -42,3 +42,14 @@ describe("selectors: filterUsers", () => {
|
|
|
42
42
|
expect(filteredUsers).toEqual(expect.arrayContaining([miguel]));
|
|
43
43
|
});
|
|
44
44
|
});
|
|
45
|
+
|
|
46
|
+
it.each([" ext-1 ", "calidad", "data"])(
|
|
47
|
+
"searches external IDs and group names/aliases: %s",
|
|
48
|
+
(query) => {
|
|
49
|
+
const user = {
|
|
50
|
+
external_id: "EXT-1",
|
|
51
|
+
groups: [{ name: "data", alias: "Calidád" }],
|
|
52
|
+
};
|
|
53
|
+
expect(filterUsers(query)([user, { user_name: "other" }])).toEqual([user]);
|
|
54
|
+
},
|
|
55
|
+
);
|
|
@@ -28,11 +28,13 @@ describe("selectors: getUserGroupAcls", () => {
|
|
|
28
28
|
resource: aclWithAlias.resource,
|
|
29
29
|
role: aclWithAlias.role.name,
|
|
30
30
|
group: aclWithAlias.group.alias,
|
|
31
|
+
groupId: aclWithAlias.group.id,
|
|
31
32
|
},
|
|
32
33
|
{
|
|
33
34
|
resource: aclWithoutAlias.resource,
|
|
34
35
|
role: aclWithoutAlias.role.name,
|
|
35
36
|
group: aclWithoutAlias.group.name,
|
|
37
|
+
groupId: aclWithoutAlias.group.id,
|
|
36
38
|
},
|
|
37
39
|
]);
|
|
38
40
|
});
|
|
@@ -5,7 +5,15 @@ export const filterUsers = (usersFilter) =>
|
|
|
5
5
|
lowerDeburrTrim(usersFilter)
|
|
6
6
|
? _.filter(
|
|
7
7
|
_.flow(
|
|
8
|
-
|
|
8
|
+
(user) => [
|
|
9
|
+
user.user_name,
|
|
10
|
+
user.full_name,
|
|
11
|
+
user.email,
|
|
12
|
+
user.external_id,
|
|
13
|
+
...(user.groups || []).flatMap((group) =>
|
|
14
|
+
typeof group === "string" ? [group] : [group.name, group.alias],
|
|
15
|
+
),
|
|
16
|
+
],
|
|
9
17
|
_.map(lowerDeburrTrim),
|
|
10
18
|
_.some(_.includes(lowerDeburrTrim(usersFilter))),
|
|
11
19
|
),
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import _ from "lodash/fp";
|
|
2
|
-
import PropTypes from "prop-types";
|
|
3
|
-
import { Divider, Header, Grid, Icon, Segment } from "semantic-ui-react";
|
|
4
|
-
import { connect } from "react-redux";
|
|
5
|
-
import { FormattedMessage, useIntl } from "react-intl";
|
|
6
|
-
import UserActions from "./UserActions";
|
|
7
|
-
import UserAcls from "./UserAcls";
|
|
8
|
-
import UserBreadcrumbs from "./UserBreadcrumbs";
|
|
9
|
-
import UserGroupAcls from "./UserGroupAcls";
|
|
10
|
-
|
|
11
|
-
export const User = ({ user }) => {
|
|
12
|
-
const { formatMessage } = useIntl();
|
|
13
|
-
return _.isEmpty(user) ? null : (
|
|
14
|
-
<>
|
|
15
|
-
<UserBreadcrumbs name={user.user_name} />
|
|
16
|
-
<Segment>
|
|
17
|
-
<Grid>
|
|
18
|
-
<Grid.Column width={8}>
|
|
19
|
-
<Header floated="left" as="h2">
|
|
20
|
-
<Icon
|
|
21
|
-
circular
|
|
22
|
-
name={formatMessage({
|
|
23
|
-
id: "users.header.icon",
|
|
24
|
-
defaultMessage: "users",
|
|
25
|
-
})}
|
|
26
|
-
/>
|
|
27
|
-
<Header.Content>
|
|
28
|
-
{user.user_name}
|
|
29
|
-
<Header.Subheader>
|
|
30
|
-
<FormattedMessage id={`user.type.${user?.role}`} />
|
|
31
|
-
</Header.Subheader>
|
|
32
|
-
</Header.Content>
|
|
33
|
-
</Header>
|
|
34
|
-
</Grid.Column>
|
|
35
|
-
<Grid.Column width={8} textAlign="right">
|
|
36
|
-
<UserActions />
|
|
37
|
-
</Grid.Column>
|
|
38
|
-
<Grid.Column width={8}>
|
|
39
|
-
{user.external_id == null ? (
|
|
40
|
-
user.external_id
|
|
41
|
-
) : (
|
|
42
|
-
<>
|
|
43
|
-
{user.external_id}
|
|
44
|
-
<br />
|
|
45
|
-
</>
|
|
46
|
-
)}
|
|
47
|
-
{user.full_name}
|
|
48
|
-
<br />
|
|
49
|
-
{user.email}
|
|
50
|
-
<br />
|
|
51
|
-
{_.join(" ")(user.groups)}
|
|
52
|
-
<Divider hidden />
|
|
53
|
-
<UserAcls />
|
|
54
|
-
<UserGroupAcls />
|
|
55
|
-
</Grid.Column>
|
|
56
|
-
</Grid>
|
|
57
|
-
</Segment>
|
|
58
|
-
</>
|
|
59
|
-
);
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
User.propTypes = {
|
|
63
|
-
user: PropTypes.object,
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
const mapStateToProps = ({ user }) => ({ user });
|
|
67
|
-
|
|
68
|
-
export default connect(mapStateToProps)(User);
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import _ from "lodash/fp";
|
|
2
|
-
import { connect } from "react-redux";
|
|
3
|
-
import PropTypes from "prop-types";
|
|
4
|
-
import { useIntl } from "react-intl";
|
|
5
|
-
import UserBreadcrumbs from "./UserBreadcrumbs";
|
|
6
|
-
import Password from "./Password";
|
|
7
|
-
|
|
8
|
-
export const UserPassword = ({ user }) => {
|
|
9
|
-
const { formatMessage } = useIntl();
|
|
10
|
-
return (
|
|
11
|
-
<>
|
|
12
|
-
<UserBreadcrumbs name={formatMessage({ id: "user.password.change" })} />
|
|
13
|
-
<Password id={_.get("id")(user)} userName={_.get("user_name")(user)} />
|
|
14
|
-
</>
|
|
15
|
-
);
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
UserPassword.propTypes = {
|
|
19
|
-
user: PropTypes.object,
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
const mapStateToProps = ({ user }) => ({ user });
|
|
23
|
-
|
|
24
|
-
export default connect(mapStateToProps)(UserPassword);
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { render } from "@truedat/test/render";
|
|
2
|
-
import User from "../User";
|
|
3
|
-
|
|
4
|
-
describe("<User />", () => {
|
|
5
|
-
const user = {
|
|
6
|
-
id: "1",
|
|
7
|
-
user_name: "joe",
|
|
8
|
-
role: "admin",
|
|
9
|
-
full_name: "Joe Bloggs",
|
|
10
|
-
email: "joe@bloggs.net",
|
|
11
|
-
};
|
|
12
|
-
const renderOpts = {
|
|
13
|
-
state: { user },
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
it("matches the latest snapshot", () => {
|
|
17
|
-
const { container } = render(<User />, renderOpts);
|
|
18
|
-
expect(container).toMatchSnapshot();
|
|
19
|
-
});
|
|
20
|
-
});
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { render, waitForLoad } from "@truedat/test/render";
|
|
2
|
-
import { UserPassword } from "../UserPassword";
|
|
3
|
-
|
|
4
|
-
const renderOpts = {
|
|
5
|
-
state: {
|
|
6
|
-
authentication: {
|
|
7
|
-
user_name: "foo",
|
|
8
|
-
},
|
|
9
|
-
},
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
describe("<UserPassword />", () => {
|
|
13
|
-
const user = {
|
|
14
|
-
id: 1,
|
|
15
|
-
user_name: "joe",
|
|
16
|
-
};
|
|
17
|
-
const props = { user };
|
|
18
|
-
|
|
19
|
-
it("matches the latest snapshot", async () => {
|
|
20
|
-
const rendered = render(<UserPassword {...props} />, renderOpts);
|
|
21
|
-
await waitForLoad(rendered);
|
|
22
|
-
expect(rendered.container).toMatchSnapshot();
|
|
23
|
-
});
|
|
24
|
-
});
|