413 lines
13 KiB
JavaScript
413 lines
13 KiB
JavaScript
import {
|
|
Button,
|
|
Popconfirm,
|
|
Popover,
|
|
Select,
|
|
Space,
|
|
Table,
|
|
Typography,
|
|
notification,
|
|
} from "antd";
|
|
import {
|
|
Constants,
|
|
FormatDatetime,
|
|
getConnectionStatusItem,
|
|
hasOnePermission,
|
|
hasPermission,
|
|
myFetch,
|
|
wsConnectionCustomEventName,
|
|
} from "../../utils";
|
|
import { useEffect, useState } from "react";
|
|
import { Link } from "react-router-dom";
|
|
import { UserAddOutlined } from "@ant-design/icons";
|
|
import CreateUserModal from "./CreateUserModal";
|
|
import { useTranslation } from "react-i18next";
|
|
import { MyAvatar } from "../../Components/MyAvatar";
|
|
import { useUsersContext } from "../../Contexts/UsersContext";
|
|
import { useAppContext } from "../../Contexts/AppContext";
|
|
import { useWebSocketContext } from "../../Contexts/WebSocketContext";
|
|
import { SentMessagesCommands } from "../../Handlers/WebSocketMessageHandler";
|
|
|
|
export default function AllUsers() {
|
|
const webSocketContext = useWebSocketContext();
|
|
const appContext = useAppContext();
|
|
const usersContext = useUsersContext();
|
|
const { t } = useTranslation();
|
|
const [selectedRoleId, setSelectedRoleId] = useState("");
|
|
const [notificationApi, notificationContextHolder] =
|
|
notification.useNotification();
|
|
const [isCreateUserModalOpen, setIsCreateUserModalOpen] = useState(false);
|
|
|
|
const getTableContent = () => {
|
|
let items = [
|
|
{
|
|
title: t("allUsers.column.avatar"),
|
|
dataIndex: "avatar",
|
|
key: "avatar",
|
|
},
|
|
{
|
|
title: t("allUsers.column.username"),
|
|
dataIndex: "username",
|
|
key: "username",
|
|
},
|
|
{
|
|
title: t("allUsers.column.role"),
|
|
dataIndex: "role",
|
|
key: "role",
|
|
},
|
|
{
|
|
title: t("allUsers.column.connectionStatus"),
|
|
dataIndex: "connectionStatus",
|
|
key: "connectionStatus",
|
|
},
|
|
{
|
|
title: t("allUsers.column.lastOnline"),
|
|
dataIndex: "lastOnline",
|
|
key: "lastOnline",
|
|
},
|
|
];
|
|
|
|
if (
|
|
hasOnePermission(
|
|
appContext.userPermissions,
|
|
Constants.PERMISSIONS.ALL_USERS.ACTION.CHANGE_ROLE,
|
|
Constants.PERMISSIONS.ALL_USERS.ACTION.DELETE_USER,
|
|
Constants.PERMISSIONS.ALL_USERS.ACTION.DEACTIVATE_USER
|
|
)
|
|
) {
|
|
items.push({
|
|
title: t("allUsers.column.action.title"),
|
|
key: "action",
|
|
render: (_, record) => (
|
|
<Space size="middle">
|
|
{hasPermission(
|
|
appContext.userPermissions,
|
|
Constants.PERMISSIONS.ALL_USERS.ACTION.CHANGE_ROLE
|
|
) &&
|
|
(usersContext.roles.find(
|
|
(role) => role.Id === usersContext.roleId
|
|
).SortingOrder <
|
|
usersContext.roles.find((role) => role.Id === record._roleId)
|
|
.SortingOrder ||
|
|
usersContext.roles.find(
|
|
(role) => role.Id === usersContext.roleId
|
|
).Master) && (
|
|
<Popconfirm
|
|
title={t(
|
|
"allUsers.column.action.roleChange.popconfirm.title"
|
|
)}
|
|
cancelText={t("common.button.cancel")}
|
|
okText={t(
|
|
"allUsers.column.action.roleChange.popconfirm.okText"
|
|
)}
|
|
onConfirm={() => onRoleChangeConfirm(record.key)}
|
|
okButtonProps={{
|
|
disabled:
|
|
selectedRoleId ===
|
|
usersContext.users.find((user) => user.Id === record.key)
|
|
.RoleId,
|
|
}}
|
|
description={
|
|
<Select
|
|
style={{ width: 250 }}
|
|
getPopupContainer={(node) => node.parentNode}
|
|
defaultValue={
|
|
usersContext.users.find(
|
|
(user) => user.Id === record.key
|
|
).RoleId
|
|
}
|
|
value={selectedRoleId}
|
|
onChange={(e) => setSelectedRoleId(e)}
|
|
>
|
|
{usersContext.roles.map((role) => {
|
|
if (
|
|
usersContext.roles.find(
|
|
(role) => role.Id === usersContext.roleId
|
|
).Master ||
|
|
usersContext.roles.find(
|
|
(role) => role.Id === usersContext.roleId
|
|
).SortingOrder < role.SortingOrder
|
|
) {
|
|
return (
|
|
<Select.Option key={role.Id}>
|
|
{role.DisplayName}
|
|
</Select.Option>
|
|
);
|
|
}
|
|
|
|
return null;
|
|
})}
|
|
</Select>
|
|
}
|
|
>
|
|
<Link
|
|
to="#"
|
|
onClick={() => {
|
|
setSelectedRoleId(
|
|
usersContext.users.find(
|
|
(user) => user.Id === record.key
|
|
).RoleId
|
|
);
|
|
}}
|
|
>
|
|
{t("allUsers.column.action.changeRole")}
|
|
</Link>
|
|
</Popconfirm>
|
|
)}
|
|
|
|
{hasPermission(
|
|
appContext.userPermissions,
|
|
Constants.PERMISSIONS.ALL_USERS.ACTION.DELETE_USER
|
|
) &&
|
|
(usersContext.roles.find(
|
|
(role) => role.Id === usersContext.roleId
|
|
).SortingOrder <
|
|
usersContext.roles.find((role) => role.Id === record._roleId)
|
|
.SortingOrder ||
|
|
usersContext.roles.find(
|
|
(role) => role.Id === usersContext.roleId
|
|
).Master) && (
|
|
<Popconfirm
|
|
placement="top"
|
|
cancelText={t("common.button.cancel")}
|
|
okText={t("allUsers.column.action.delete.popconfirm.okText")}
|
|
title={t("allUsers.column.action.delete.popconfirm.title")}
|
|
onConfirm={() => onUserDeletionConfirm(record.key)}
|
|
>
|
|
<Link to="#">{t("allUsers.column.action.delete.link")}</Link>
|
|
</Popconfirm>
|
|
)}
|
|
|
|
{!usersContext.users.find((user) => user.Id === record.key)
|
|
.Deactivated
|
|
? hasPermission(
|
|
appContext.userPermissions,
|
|
Constants.PERMISSIONS.ALL_USERS.ACTION.USER_DEACTIVATION
|
|
) &&
|
|
(usersContext.roles.find(
|
|
(role) => role.Id === usersContext.roleId
|
|
).SortingOrder <
|
|
usersContext.roles.find((role) => role.Id === record._roleId)
|
|
.SortingOrder ||
|
|
usersContext.roles.find(
|
|
(role) => role.Id === usersContext.roleId
|
|
).Master) && (
|
|
<Popconfirm
|
|
placement="top"
|
|
okText={t(
|
|
"allUsers.column.action.deactivate.popconfirm.okText"
|
|
)}
|
|
cancelText={t("common.button.cancel")}
|
|
title={t(
|
|
"allUsers.column.action.deactivate.popconfirm.title"
|
|
)}
|
|
onConfirm={() =>
|
|
onUserDeactivationConfirm(record.key, true)
|
|
}
|
|
>
|
|
<Link to="#">
|
|
{t("allUsers.column.action.deactivate.link")}
|
|
</Link>
|
|
</Popconfirm>
|
|
)
|
|
: hasPermission(
|
|
appContext.userPermissions,
|
|
Constants.PERMISSIONS.ALL_USERS.ACTION.USER_DEACTIVATION
|
|
) &&
|
|
(usersContext.roles.find(
|
|
(role) => role.Id === usersContext.roleId
|
|
).SortingOrder <
|
|
usersContext.roles.find((role) => role.Id === record._roleId)
|
|
.SortingOrder ||
|
|
usersContext.roles.find(
|
|
(role) => role.Id === usersContext.roleId
|
|
).Master) && (
|
|
<Popconfirm
|
|
placement="top"
|
|
okText={t(
|
|
"allUsers.column.action.activate.popconfirm.okText"
|
|
)}
|
|
title={t(
|
|
"allUsers.column.action.activate.popconfirm.title"
|
|
)}
|
|
cancelText={t("common.button.cancel")}
|
|
onConfirm={() =>
|
|
onUserDeactivationConfirm(record.key, false)
|
|
}
|
|
>
|
|
<Link to="#">
|
|
{t("allUsers.column.action.activate.link")}
|
|
</Link>
|
|
</Popconfirm>
|
|
)}
|
|
</Space>
|
|
),
|
|
});
|
|
}
|
|
|
|
return items;
|
|
};
|
|
|
|
const activatedUsers = usersContext.users.filter(
|
|
(user) => user.Deactivated === false
|
|
);
|
|
const deactivatedUsers = usersContext.users.filter(
|
|
(user) => user.Deactivated === true
|
|
);
|
|
|
|
const getTableItems = (users) => {
|
|
let items = [];
|
|
|
|
users.sort(
|
|
(a, b) =>
|
|
usersContext.roles.find((r) => r.Id === a.RoleId).SortingOrder -
|
|
usersContext.roles.find((r) => r.Id === b.RoleId).SortingOrder
|
|
);
|
|
|
|
users.forEach((user) => {
|
|
items.push({
|
|
key: user.Id,
|
|
avatar: (
|
|
<Popover
|
|
placement="right"
|
|
trigger="hover"
|
|
content={<MyAvatar avatar={user.Avatar} avatarWidth={256} />}
|
|
>
|
|
<>
|
|
<MyAvatar avatar={user.Avatar} />
|
|
</>
|
|
</Popover>
|
|
),
|
|
role: usersContext.roles.find((role) => role.Id === user.RoleId)
|
|
.DisplayName,
|
|
_roleId: user.RoleId, // used as reference for user deletion
|
|
connectionStatus: getConnectionStatusItem(user.ConnectionStatus),
|
|
username: user.Username,
|
|
lastOnline: FormatDatetime(user.LastOnline),
|
|
});
|
|
});
|
|
|
|
return items;
|
|
};
|
|
|
|
const onRoleChangeConfirm = (targetUserId) => {
|
|
const existsRole = usersContext.roles.find(
|
|
(role) => role.Id === selectedRoleId
|
|
);
|
|
|
|
if (existsRole === undefined) {
|
|
notificationApi["error"]({
|
|
message: t("allUsers.roleChangeError.notification.message"),
|
|
description: t("allUsers.roleChangeError.notification.description"),
|
|
});
|
|
return;
|
|
}
|
|
|
|
webSocketContext.SendSocketMessage(
|
|
SentMessagesCommands.AllUsersUpdateUserRole,
|
|
{
|
|
UserId: targetUserId,
|
|
RoleId: selectedRoleId,
|
|
}
|
|
);
|
|
};
|
|
|
|
const onUserDeletionConfirm = (userId) => {
|
|
webSocketContext.SendSocketMessage(
|
|
SentMessagesCommands.AllUsersDeleteUser,
|
|
{
|
|
UserId: userId,
|
|
}
|
|
);
|
|
};
|
|
|
|
const onUserDeactivationConfirm = (userId, deactivate) => {
|
|
webSocketContext.SendSocketMessage(
|
|
SentMessagesCommands.AllUsersUserDeactivation,
|
|
{
|
|
UserId: userId,
|
|
Deactivation: deactivate,
|
|
}
|
|
);
|
|
};
|
|
|
|
useEffect(() => {
|
|
const usersRequest = () =>
|
|
myFetch("/users", "GET").then((data) => {
|
|
usersContext.setRoleId(data.RoleId);
|
|
usersContext.setUsers(data.Users);
|
|
usersContext.setRoles(data.Roles);
|
|
});
|
|
|
|
usersRequest();
|
|
|
|
const handleUsersRequest = () => usersRequest();
|
|
|
|
document.addEventListener(wsConnectionCustomEventName, handleUsersRequest);
|
|
|
|
return () =>
|
|
document.removeEventListener(
|
|
wsConnectionCustomEventName,
|
|
handleUsersRequest
|
|
);
|
|
}, []);
|
|
|
|
return (
|
|
<>
|
|
{notificationContextHolder}
|
|
|
|
<div
|
|
style={{
|
|
display: "flex",
|
|
justifyContent: "space-between",
|
|
}}
|
|
>
|
|
<Typography.Title level={4}>
|
|
{t("allUsers.header.allUsers")} ({activatedUsers.length})
|
|
</Typography.Title>
|
|
|
|
{hasPermission(
|
|
appContext.userPermissions,
|
|
Constants.PERMISSIONS.ALL_USERS.CREATE_NEW_USER
|
|
) && (
|
|
<Button
|
|
icon={<UserAddOutlined />}
|
|
onClick={() => setIsCreateUserModalOpen(true)}
|
|
>
|
|
{t("allUsers.button.createNewUser")}
|
|
</Button>
|
|
)}
|
|
</div>
|
|
|
|
<Table
|
|
scroll={{ x: "max-content" }}
|
|
columns={getTableContent()}
|
|
dataSource={getTableItems(activatedUsers)}
|
|
/>
|
|
|
|
{hasPermission(
|
|
appContext.userPermissions,
|
|
Constants.PERMISSIONS.ALL_USERS.ACTION.USER_DEACTIVATION
|
|
) &&
|
|
deactivatedUsers.length > 0 && (
|
|
<>
|
|
<Typography.Title level={4}>
|
|
{t("allUsers.header.deactivatedUsers")} ({deactivatedUsers.length}
|
|
)
|
|
</Typography.Title>
|
|
<Table
|
|
scroll={{ x: "max-content" }}
|
|
columns={getTableContent()}
|
|
dataSource={getTableItems(deactivatedUsers)}
|
|
/>
|
|
</>
|
|
)}
|
|
|
|
<CreateUserModal
|
|
isModalOpen={isCreateUserModalOpen}
|
|
setIsModalOpen={setIsCreateUserModalOpen}
|
|
/>
|
|
</>
|
|
);
|
|
}
|