added multiple contexts

main
alex 2023-08-27 00:14:33 +02:00
parent c125751f17
commit ba5d3e9d20
16 changed files with 470 additions and 163 deletions

View File

@ -2,11 +2,52 @@ import { useState } from "react";
import "antd/dist/reset.css";
import "./App.css";
import Login from "./Pages/Login";
import { Layout, message, notification } from "antd";
import { UseUserSession, WebSocketProvider } from "./utils";
import { Layout, notification } from "antd";
import { UseUserSession } from "./utils";
import DashboardLayout from "./Components/DashboardLayout";
import WebSocketProvider from "./Contexts/WebSocketContext";
import SideBarProvider from "./Contexts/SideBarContext";
import { AppProvider } from "./Contexts/AppContext";
export default function App() {
const { userSession, setUserSession } = UseUserSession();
const [isWebSocketReady, setIsWebSocketReady] = useState(true);
if (!userSession) {
return <Login />;
}
console.info(
"\n %c Admin Dashboard %c v0.1.0 %c \n",
"background-color: #555;color: #fff;padding: 3px 2px 3px 3px;border-radius: 3px 0 0 3px;font-family: DejaVu Sans,Verdana,Geneva,sans-serif;text-shadow: 0 1px 0 rgba(1, 1, 1, 0.3)",
"background-color: #bc81e0;background-image: linear-gradient(90deg, #e67e22, #9b59b6);color: #fff;padding: 3px 3px 3px 2px;border-radius: 0 3px 3px 0;font-family: DejaVu Sans,Verdana,Geneva,sans-serif;text-shadow: 0 1px 0 rgba(1, 1, 1, 0.3)",
"background-color: transparent"
);
return (
<Layout style={{ minHeight: "100vh" }}>
<AppProvider>
<SideBarProvider>
<WebSocketProvider
userSession={userSession}
setUserSession={setUserSession}
isWebSocketReady={isWebSocketReady}
setIsWebSocketReady={setIsWebSocketReady}
>
<ReconnectingView isWebSocketReady={isWebSocketReady} />
<DashboardLayout
userSession={userSession}
setUserSession={setUserSession}
/>
</WebSocketProvider>
</SideBarProvider>
</AppProvider>
</Layout>
);
}
/*export default function App() {
const [notificationApi, notificationContextHolder] =
notification.useNotification();
const { userSession, setUserSession } = UseUserSession();
@ -26,6 +67,7 @@ export default function App() {
return (
<Layout style={{ minHeight: "100vh" }}>
{notificationContextHolder}
<WebSocketProvider
userSession={userSession}
setUserSession={setUserSession}
@ -42,9 +84,9 @@ export default function App() {
</WebSocketProvider>
</Layout>
);
}
} */
const ReconnectingView = ({ webSocketIsReady }) => {
const ReconnectingView = ({ isWebSocketReady }) => {
return (
<div
style={{
@ -54,7 +96,7 @@ const ReconnectingView = ({ webSocketIsReady }) => {
right: 0,
bottom: 0,
backgroundColor: "rgba(0, 0, 0, 0.8)",
display: webSocketIsReady ? "none" : "block",
display: isWebSocketReady ? "none" : "block",
justifyContent: "center",
alignItems: "center",
zIndex: 9999,

View File

@ -11,11 +11,12 @@ import Scanners from "../../Pages/Scanners";
import AdminAreaRoles from "../../Pages/AdminArea/Roles";
import AdminAreaLogs from "../../Pages/AdminArea/Logs";
import AllUsers from "../../Pages/AllUsers";
import { useContext } from "react";
import GroupTasks from "../../Pages/GroupTasks/Overview";
import GroupTasksHistory from "../../Pages/GroupTasks/History";
import PageNotFound from "../../Pages/PageNotFound";
import EquipmentDocumentationOverview from "../../Pages/EquipmentDocumentation";
import { UserProfileProvider } from "../../Contexts/UserProfileContext";
import { UsersProvider } from "../../Contexts/UsersContext";
export default function AppRoutes() {
// const webSocketContext = useContext(WebSocketContext);
@ -79,9 +80,23 @@ export default function AppRoutes() {
<Route path="/scanners" element={<Scanners />} />
<Route path="/users" element={<AllUsers />} />
<Route
path="/users"
element={
<UsersProvider>
<AllUsers />
</UsersProvider>
}
/>
<Route path="/user-profile" element={<UserProfile />} />
<Route
path="/user-profile"
element={
<UserProfileProvider>
<UserProfile />
</UserProfileProvider>
}
/>
<Route path="/admin-area/roles" element={<AdminAreaRoles />} />

View File

@ -58,3 +58,16 @@ export function MyAvatar({
return <MyAvat />;
}
export function MyUserAvatar({ avatar, size = "default" }) {
if (avatar === "") {
return <Avatar icon={<UserOutlined />} />;
}
return (
<Avatar
src={Constants.STATIC_CONTENT_ADDRESS + "avatars/" + avatar}
size={size}
/>
);
}

View File

@ -1,7 +1,6 @@
import { EditOutlined } from "@ant-design/icons";
import { Input, Typography } from "antd";
import { useState } from "react";
import { Constants } from "../../utils";
export default function MyTypography({ value, setValue, maxLength }) {
const [editing, setEditing] = useState(false);

View File

@ -14,15 +14,11 @@ import Sider from "antd/es/layout/Sider";
import { useContext, useEffect, useState } from "react";
import { useLocation, useNavigate } from "react-router-dom";
import PropTypes from "prop-types";
import {
Constants,
WebSocketContext,
getUserId,
hasOnePermission,
hasPermission,
} from "../../utils";
import { Constants, hasOnePermission, hasPermission } from "../../utils";
import { useTranslation } from "react-i18next";
import { MyAvatar } from "../MyAvatar";
import { MyUserAvatar } from "../MyAvatar";
import { useSideBarContext } from "../../Contexts/SideBarContext";
import { useAppContext } from "../../Contexts/AppContext";
export default function SideMenu({
userSession,
@ -30,9 +26,10 @@ export default function SideMenu({
isSideMenuCollapsed,
setIsSideMenuCollapsed,
}) {
const appContext = useAppContext();
const sidebarContext = useSideBarContext();
const location = useLocation();
const [selectedKeys, setSelectedKeys] = useState("/");
const webSocketContext = useContext(WebSocketContext);
const { t } = useTranslation();
useEffect(() => setSelectedKeys(location.pathname), [location.pathname]);
@ -40,13 +37,17 @@ export default function SideMenu({
const navigate = useNavigate();
const getCurrentUsedScannerName = () => {
const scannerName = webSocketContext.Scanners.find(
/*const scannerName = webSocketContext.Scanners.find(
(scanner) => scanner.UsedByUserId === getUserId()
)?.Name;
return scannerName === undefined
? t("sideMenu.adminArea.noScannerSelected")
: scannerName;
: scannerName; */
// TODO: handle scanner name
return Constants.LOADING;
};
const getFirstMenuItems = () => {
@ -57,19 +58,19 @@ export default function SideMenu({
key: "/",
},
];
/*
if (
hasPermission(
webSocketContext.User.Permissions,
appContext.userPermissions,
Constants.PERMISSIONS.EQUIPMENT_DOCUMENTATION.VIEW
)
) { */
items.push({
label: t("sideMenu.equipmentDocumentation"),
icon: <BookOutlined />,
key: "/equipment-documentation",
});
//}
) {
items.push({
label: t("sideMenu.equipmentDocumentation"),
icon: <BookOutlined />,
key: "/equipment-documentation",
});
}
let groupTasks = {
label: t("sideMenu.groupTasks.menuCategory"),
@ -85,7 +86,7 @@ export default function SideMenu({
if (
hasPermission(
webSocketContext.User.Permissions,
appContext.userPermissions,
Constants.PERMISSIONS.GROUP_TASKS.HISTORY
)
) {
@ -104,7 +105,7 @@ export default function SideMenu({
if (
hasOnePermission(
webSocketContext.User.Permissions,
appContext.userPermissions,
Constants.PERMISSIONS.ADMIN_AREA.ROLES.CREATE_NEW_ROLE,
Constants.PERMISSIONS.ADMIN_AREA.ROLES.UPDATE_ROLE,
Constants.PERMISSIONS.ADMIN_AREA.ROLES.DELETE_ROLE,
@ -121,7 +122,7 @@ export default function SideMenu({
if (
hasOnePermission(
webSocketContext.User.Permissions,
appContext.userPermissions,
Constants.PERMISSIONS.ADMIN_AREA.ROLES.CREATE_NEW_ROLE,
Constants.PERMISSIONS.ADMIN_AREA.ROLES.UPDATE_ROLE,
Constants.PERMISSIONS.ADMIN_AREA.ROLES.DELETE_ROLE,
@ -137,7 +138,7 @@ export default function SideMenu({
if (
hasPermission(
webSocketContext.User.Permissions,
appContext.userPermissions,
Constants.PERMISSIONS.ADMIN_AREA.LOGS
)
) {
@ -155,11 +156,13 @@ export default function SideMenu({
};
const getSecondMenuItems = () => {
console.log("getSecondMenuItems", sidebarContext.connectionBadgeStatus);
let items = [];
if (
hasPermission(
webSocketContext.User.Permissions,
appContext.userPermissions,
Constants.PERMISSIONS.SCANNER.USE_SCANNERS
)
) {
@ -174,9 +177,9 @@ export default function SideMenu({
{
icon: (
<Badge
status={webSocketContext.ConnectionBadgeStatus}
text={`${webSocketContext.ConnectedWebSocketUsersCount} ${
webSocketContext.ConnectedWebSocketUsersCount === 1
status={sidebarContext.connectionBadgeStatus}
text={`${sidebarContext.connectedUsers} ${
sidebarContext.connectedUsers === 1
? t("sideMenu.usersCount.single")
: t("sideMenu.usersCount.multiple")
}`}
@ -185,13 +188,8 @@ export default function SideMenu({
key: "/users",
},
{
label: ` ${webSocketContext.User.Username}`,
icon: (
<MyAvatar
allUsers={webSocketContext.AllUsers}
userId={webSocketContext.User.Id}
/>
),
label: ` ${appContext.username}`,
icon: <MyUserAvatar avatar={appContext.avatar} />,
key: "/user-profile",
},
{
@ -216,6 +214,11 @@ export default function SideMenu({
return items;
};
console.log(
"sidebarContext.connectionBadgeStatus",
sidebarContext.connectionBadgeStatus
);
return (
<Sider
theme="light"

View File

@ -0,0 +1,37 @@
import { createContext, useContext, useState } from "react";
import { Constants } from "../utils";
const preview = {
username: "",
avatar: "",
userPermissions: [],
availableGroupTasks: [],
};
const AppContext = createContext(preview);
export const useAppContext = () => useContext(AppContext);
export function AppProvider({ children }) {
const [username, setUsername] = useState(Constants.LOADING);
const [avatar, setAvatar] = useState("");
const [userPermissions, setUserPermissions] = useState([]);
const [availableGroupTasks, setAvailableGroupTasks] = useState([]);
return (
<AppContext.Provider
value={{
username,
setUsername,
avatar,
setAvatar,
userPermissions,
setUserPermissions,
availableGroupTasks,
setAvailableGroupTasks,
}}
>
{children}
</AppContext.Provider>
);
}

View File

@ -0,0 +1,32 @@
import { createContext, useContext, useState } from "react";
const preview = {
connectionBadgeStatus: "",
connectedUsers: 0,
selectedScanner: "",
};
const SideBarContext = createContext(preview);
export const useSideBarContext = () => useContext(SideBarContext);
export default function SideBarProvider({ children }) {
const [connectionBadgeStatus, setConnectionBadgeStatus] = useState("error");
const [connectedUsers, setConnectedUsers] = useState(0);
const [selectedScanner, setSelectedScanner] = useState("");
return (
<SideBarContext.Provider
value={{
connectionBadgeStatus,
setConnectionBadgeStatus,
connectedUsers,
setConnectedUsers,
selectedScanner,
setSelectedScanner,
}}
>
{children}
</SideBarContext.Provider>
);
}

View File

@ -0,0 +1,26 @@
import { createContext, useContext, useState } from "react";
import { Constants } from "../utils";
// only for tab completion
const preview = {
id: Constants.LOADING,
avatar: "",
username: Constants.LOADING,
email: Constants.LOADING,
sessions: [],
apiKeys: [],
};
const UserProfileContext = createContext({ userProfile: preview });
export const useUserProfileContext = () => useContext(UserProfileContext);
export function UserProfileProvider({ children }) {
const [userProfile, setUserProfile] = useState(preview);
return (
<UserProfileContext.Provider value={{ userProfile, setUserProfile }}>
{children}
</UserProfileContext.Provider>
);
}

View File

@ -0,0 +1,32 @@
import { createContext, useContext, useState } from "react";
const preview = {
roleId: "",
users: [],
roles: [],
};
const UsersContext = createContext(preview);
export const useUsersContext = () => useContext(UsersContext);
export function UsersProvider({ children }) {
const [roleId, setRoleId] = useState("");
const [users, setUsers] = useState([]);
const [roles, setRoles] = useState([]);
return (
<UsersContext.Provider
value={{
roleId,
setRoleId,
users,
setUsers,
roles,
setRoles,
}}
>
{children}
</UsersContext.Provider>
);
}

View File

@ -0,0 +1,100 @@
import { createContext, useContext, useEffect, useRef, useState } from "react";
import { Constants, ReceivedMessagesCommands, myFetch } from "../utils";
import { useSideBarContext } from "./SideBarContext";
import { useAppContext } from "./AppContext";
import { message } from "antd";
const WebSocketContext = createContext(null);
export const useWebSocketContext = () => useContext(WebSocketContext);
export default function WebSocketProvider({
children,
userSession,
setUserSession,
isWebSocketReady,
setIsWebSocketReady,
}) {
const ws = useRef(null);
const appContext = useAppContext();
const sideBarContext = useSideBarContext();
const connect = () => {
ws.current = new WebSocket(`${Constants.WS_ADDRESS}?auth=${userSession}`);
ws.current.onopen = () => {
console.log("connected");
sideBarContext.setConnectionBadgeStatus("success");
setIsWebSocketReady(true);
myFetch("/user/", "GET").then((data) => {
console.log("user info", data);
appContext.setUsername(data.Username);
appContext.setAvatar(data.Avatar);
appContext.setUserPermissions(data.Permissions);
appContext.setAvailableGroupTasks(data.AvailableGroupTasks);
});
};
ws.current.onmessage = (event) => {
const data = JSON.parse(event.data);
console.log("received message", data);
const cmd = data.Cmd;
const body = data.Body;
switch (cmd) {
case ReceivedMessagesCommands.UpdateConnectedUsers:
sideBarContext.setConnectedUsers(body.WebSocketUsersCount);
break;
}
};
ws.current.onclose = (event) => {
setIsWebSocketReady(false);
sideBarContext.setConnectionBadgeStatus("error");
console.warn("closed", event);
// custom code defined by the backend server
if (event.code === 4001 || event.code === 4002) {
//Unauthorized || SessionClosed
setUserSession();
window.location.href = "/";
return;
}
if (event.reason.code === 1005) return;
console.warn("reconnecting...");
setTimeout(() => connect(), 1000);
};
};
const SendSocketMessage = (cmd, body) => {
if (isWebSocketReady) {
ws.current.send(JSON.stringify({ Cmd: cmd, Body: body }));
} else {
/*notificationApi["error"]({
message: `Websocket is not ready`,
description: `Please check your internet connection`,
}); */
message.error(`Websocket is not ready`);
}
};
useEffect(() => {
connect();
return () => ws.current.close();
}, []);
return (
<WebSocketContext.Provider value={{ SendSocketMessage: SendSocketMessage }}>
{children}
</WebSocketContext.Provider>
);
}

View File

@ -0,0 +1 @@
export function handleWebSocketMessage(message) {}

View File

@ -12,20 +12,25 @@ import {
Constants,
FormatDatetime,
SentMessagesCommands,
WebSocketContext,
getConnectionStatusItem,
hasOnePermission,
hasPermission,
myFetch,
} from "../../utils";
import { useContext, useState } from "react";
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";
export default function AllUsers() {
const webSocketContext = useContext(WebSocketContext);
const webSocketContext = useWebSocketContext();
const appContext = useAppContext();
const usersContext = useUsersContext();
const { t } = useTranslation();
const [selectedRoleId, setSelectedRoleId] = useState("");
const [notificationApi, notificationContextHolder] =
@ -63,7 +68,7 @@ export default function AllUsers() {
if (
hasOnePermission(
webSocketContext.User.Permissions,
appContext.userPermissions,
Constants.PERMISSIONS.ALL_USERS.ACTION.CHANGE_ROLE,
Constants.PERMISSIONS.ALL_USERS.ACTION.DELETE_USER,
Constants.PERMISSIONS.ALL_USERS.ACTION.DEACTIVATE_USER
@ -75,17 +80,16 @@ export default function AllUsers() {
render: (_, record) => (
<Space size="middle">
{hasPermission(
webSocketContext.User.Permissions,
appContext.userPermissions,
Constants.PERMISSIONS.ALL_USERS.ACTION.CHANGE_ROLE
) &&
(webSocketContext.AllRoles.find(
(role) => role.Id === webSocketContext.User.RoleId
(usersContext.roles.find(
(role) => role.Id === usersContext.roleId
).SortingOrder <
webSocketContext.AllRoles.find(
(role) => role.Id === record._roleId
).SortingOrder ||
webSocketContext.AllRoles.find(
(role) => role.Id === webSocketContext.User.RoleId
usersContext.roles.find((role) => role.Id === record._roleId)
.SortingOrder ||
usersContext.roles.find(
(role) => role.Id === usersContext.roleId
).Master) && (
<Popconfirm
title={t(
@ -99,29 +103,28 @@ export default function AllUsers() {
okButtonProps={{
disabled:
selectedRoleId ===
webSocketContext.AllUsers.find(
(user) => user.Id === record.key
).RoleId,
usersContext.users.find((user) => user.Id === record.key)
.RoleId,
}}
description={
<Select
style={{ width: 250 }}
getPopupContainer={(node) => node.parentNode}
defaultValue={
webSocketContext.AllUsers.find(
usersContext.users.find(
(user) => user.Id === record.key
).RoleId
}
value={selectedRoleId}
onChange={(e) => setSelectedRoleId(e)}
>
{webSocketContext.AllRoles.map((role) => {
{usersContext.roles.map((role) => {
if (
webSocketContext.AllRoles.find(
(role) => role.Id === webSocketContext.User.RoleId
usersContext.roles.find(
(role) => role.Id === usersContext.roleId
).Master ||
webSocketContext.AllRoles.find(
(role) => role.Id === webSocketContext.User.RoleId
usersContext.roles.find(
(role) => role.Id === usersContext.roleId
).SortingOrder < role.SortingOrder
) {
return (
@ -140,7 +143,7 @@ export default function AllUsers() {
to="#"
onClick={() => {
setSelectedRoleId(
webSocketContext.AllUsers.find(
usersContext.users.find(
(user) => user.Id === record.key
).RoleId
);
@ -152,17 +155,16 @@ export default function AllUsers() {
)}
{hasPermission(
webSocketContext.User.Permissions,
appContext.userPermissions,
Constants.PERMISSIONS.ALL_USERS.ACTION.DELETE_USER
) &&
(webSocketContext.AllRoles.find(
(role) => role.Id === webSocketContext.User.RoleId
(usersContext.roles.find(
(role) => role.Id === usersContext.roleId
).SortingOrder <
webSocketContext.AllRoles.find(
(role) => role.Id === record._roleId
).SortingOrder ||
webSocketContext.AllRoles.find(
(role) => role.Id === webSocketContext.User.RoleId
usersContext.roles.find((role) => role.Id === record._roleId)
.SortingOrder ||
usersContext.roles.find(
(role) => role.Id === usersContext.roleId
).Master) && (
<Popconfirm
placement="top"
@ -175,20 +177,19 @@ export default function AllUsers() {
</Popconfirm>
)}
{!webSocketContext.AllUsers.find((user) => user.Id === record.key)
{!usersContext.users.find((user) => user.Id === record.key)
.Deactivated
? hasPermission(
webSocketContext.User.Permissions,
appContext.userPermissions,
Constants.PERMISSIONS.ALL_USERS.ACTION.USER_DEACTIVATION
) &&
(webSocketContext.AllRoles.find(
(role) => role.Id === webSocketContext.User.RoleId
(usersContext.roles.find(
(role) => role.Id === usersContext.roleId
).SortingOrder <
webSocketContext.AllRoles.find(
(role) => role.Id === record._roleId
).SortingOrder ||
webSocketContext.AllRoles.find(
(role) => role.Id === webSocketContext.User.RoleId
usersContext.roles.find((role) => role.Id === record._roleId)
.SortingOrder ||
usersContext.roles.find(
(role) => role.Id === usersContext.roleId
).Master) && (
<Popconfirm
placement="top"
@ -209,17 +210,16 @@ export default function AllUsers() {
</Popconfirm>
)
: hasPermission(
webSocketContext.User.Permissions,
appContext.userPermissions,
Constants.PERMISSIONS.ALL_USERS.ACTION.USER_DEACTIVATION
) &&
(webSocketContext.AllRoles.find(
(role) => role.Id === webSocketContext.User.RoleId
(usersContext.roles.find(
(role) => role.Id === usersContext.roleId
).SortingOrder <
webSocketContext.AllRoles.find(
(role) => role.Id === record._roleId
).SortingOrder ||
webSocketContext.AllRoles.find(
(role) => role.Id === webSocketContext.User.RoleId
usersContext.roles.find((role) => role.Id === record._roleId)
.SortingOrder ||
usersContext.roles.find(
(role) => role.Id === usersContext.roleId
).Master) && (
<Popconfirm
placement="top"
@ -247,10 +247,10 @@ export default function AllUsers() {
return items;
};
const activatedUsers = webSocketContext.AllUsers.filter(
const activatedUsers = usersContext.users.filter(
(user) => user.Deactivated === false
);
const deactivatedUsers = webSocketContext.AllUsers.filter(
const deactivatedUsers = usersContext.users.filter(
(user) => user.Deactivated === true
);
@ -259,8 +259,8 @@ export default function AllUsers() {
users.sort(
(a, b) =>
webSocketContext.AllRoles.find((r) => r.Id === a.RoleId).SortingOrder -
webSocketContext.AllRoles.find((r) => r.Id === b.RoleId).SortingOrder
usersContext.roles.find((r) => r.Id === a.RoleId).SortingOrder -
usersContext.roles.find((r) => r.Id === b.RoleId).SortingOrder
);
users.forEach((user) => {
@ -277,7 +277,7 @@ export default function AllUsers() {
</>
</Popover>
),
role: webSocketContext.AllRoles.find((role) => role.Id === user.RoleId)
role: usersContext.roles.find((role) => role.Id === user.RoleId)
.DisplayName,
_roleId: user.RoleId, // used as reference for user deletion
connectionStatus: getConnectionStatusItem(user.ConnectionStatus),
@ -290,7 +290,7 @@ export default function AllUsers() {
};
const onRoleChangeConfirm = (targetUserId) => {
const existsRole = webSocketContext.AllRoles.find(
const existsRole = usersContext.roles.find(
(role) => role.Id === selectedRoleId
);
@ -330,6 +330,16 @@ export default function AllUsers() {
);
};
useEffect(() => {
myFetch("/users", "GET").then((data) => {
console.log("users", data);
usersContext.setRoleId(data.RoleId);
usersContext.setUsers(data.Users);
usersContext.setRoles(data.Roles);
});
}, []);
return (
<>
{notificationContextHolder}
@ -344,7 +354,7 @@ export default function AllUsers() {
{t("allUsers.header.allUsers")} ({activatedUsers.length})
</Typography.Title>
{hasPermission(
webSocketContext.User.Permissions,
appContext.userPermissions,
Constants.PERMISSIONS.ALL_USERS.CREATE_NEW_USER
) && (
<Button
@ -363,7 +373,7 @@ export default function AllUsers() {
/>
{hasPermission(
webSocketContext.User.Permissions,
appContext.userPermissions,
Constants.PERMISSIONS.ALL_USERS.ACTION.USER_DEACTIVATION
) &&
deactivatedUsers.length > 0 && (

View File

@ -1,15 +1,5 @@
import {
Button,
Card,
Col,
Popover,
Result,
Row,
Spin,
Typography,
} from "antd";
import { Card, Col, Popover, Result, Row, Spin, Typography } from "antd";
import { useContext, useEffect, useState } from "react";
import { useNavigate } from "react-router-dom";
import CreateEquipmentDocumentationModal from "./CreateEquipmentDocumentationModal";
import {
AppStyle,
@ -287,7 +277,7 @@ function DocumentationTypeIcon({ type }) {
case 2:
return <BookOutlined style={{ fontSize: 24 }} />;
default:
console.log("DocumentationTypeIcon type not found:", type);
console.error("DocumentationTypeIcon type not found:", type);
return null;
}
}

View File

@ -3,7 +3,6 @@ import {
ArrowUpOutlined,
CameraOutlined,
DeleteOutlined,
EditOutlined,
EllipsisOutlined,
FullscreenOutlined,
PlusOutlined,
@ -86,8 +85,6 @@ export default function EquipmentDocumentationOverview() {
<>
<QrScanner
onDecode={(result) => {
console.log(result);
if (!isScannedQrCodeValid(result)) {
messageApi.error(
t(
@ -100,7 +97,7 @@ export default function EquipmentDocumentationOverview() {
setScannerResult(JSON.parse(result).stockitem.toString());
setIsScannerActive(false);
}}
onError={(error) => console.log(error?.message)}
onError={(error) => console.error(error?.message)}
/>
<Button
block

View File

@ -14,13 +14,12 @@ import {
Upload,
notification,
} from "antd";
import { useContext, useState } from "react";
import { useEffect, useState } from "react";
import {
Constants,
EncodeStringToBase64,
FormatDatetime,
SentMessagesCommands,
WebSocketContext,
getConnectionStatusItem,
getUserSessionFromLocalStorage,
hasPermission,
@ -36,14 +35,19 @@ import {
FileTextOutlined,
KeyOutlined,
} from "@ant-design/icons";
import { MyAvatar } from "../../Components/MyAvatar";
import { MyUserAvatar } from "../../Components/MyAvatar";
import { useUserProfileContext } from "../../Contexts/UserProfileContext";
import { useWebSocketContext } from "../../Contexts/WebSocketContext";
export default function UserProfile() {
const webSocketContext = useContext(WebSocketContext);
const webSocketContext = useWebSocketContext();
const { userProfile, setUserProfile } = useUserProfileContext();
const [notificationApi, notificationContextHolder] =
notification.useNotification();
const { t, i18n } = useTranslation();
const [username, setUsername] = useState(Constants.LOADING);
const [email, setEmail] = useState(Constants.LOADING);
const [oldPassword, setOldPassword] = useState("");
const [newPassword, setNewPassword] = useState("");
const [repeatedNewPassword, setRepeatedNewPassword] = useState("");
@ -178,7 +182,7 @@ export default function UserProfile() {
const getApiKeyTableItems = () => {
let items = [];
webSocketContext.User.ApiKeys.forEach((apiKey) => {
userProfile.apiKeys.forEach((apiKey) => {
items.push({
key: apiKey.Id,
name: apiKey.Name,
@ -195,11 +199,11 @@ export default function UserProfile() {
const getSessionTableItems = () => {
let items = [];
webSocketContext.User.Sessions.sort(
userProfile.sessions.sort(
(a, b) => b.ConnectionStatus - a.ConnectionStatus
);
webSocketContext.User.Sessions.forEach((session) => {
userProfile.sessions.forEach((session) => {
items.push({
key: session.IdForDeletion,
userAgent: session.UserAgent,
@ -228,17 +232,15 @@ export default function UserProfile() {
const isButtonDisabled = () => {
if (
!isEmailValid(webSocketContext.UserProfileStateEmail) ||
webSocketContext.UserProfileStateUsername.length <
Constants.GLOBALS.MIN_USERNAME_LENGTH
!isEmailValid(email) ||
userProfile.username.length < Constants.GLOBALS.MIN_USERNAME_LENGTH
) {
return true;
}
if (
webSocketContext.UserProfileStateUsername !==
webSocketContext.User.Username ||
webSocketContext.UserProfileStateEmail !== webSocketContext.User.Email ||
username !== userProfile.username ||
email !== userProfile.email ||
(oldPassword !== "" &&
newPassword !== "" &&
newPassword === repeatedNewPassword)
@ -252,17 +254,12 @@ export default function UserProfile() {
const handleOnSubmit = () => {
const changes = {};
if (
webSocketContext.User.Username !==
webSocketContext.UserProfileStateUsername
) {
changes.username = webSocketContext.UserProfileStateUsername;
if (userProfile.username !== username) {
changes.username = username;
}
if (
webSocketContext.User.Email !== webSocketContext.UserProfileStateEmail
) {
changes.email = webSocketContext.UserProfileStateEmail;
if (userProfile.email !== email) {
changes.email = email;
}
if (
@ -288,6 +285,22 @@ export default function UserProfile() {
setNewApikeyName("");
};
useEffect(() => {
myFetch("/user/profile", "GET").then((data) => {
setUserProfile({
id: data.Id,
avatar: data.Avatar,
username: data.Username,
email: data.Email,
sessions: data.Sessions,
apiKeys: data.ApiKeys,
});
setUsername(data.Username);
setEmail(data.Email);
});
}, []);
return (
<>
{notificationContextHolder}
@ -310,11 +323,7 @@ export default function UserProfile() {
"X-Authorization": getUserSessionFromLocalStorage(),
}}
>
<MyAvatar
avatarWidth={200}
allUsers={webSocketContext.AllUsers}
userId={webSocketContext.User.Id}
/>
<MyUserAvatar avatar={userProfile.avatar} size={256} />
</Upload>
</Col>
@ -343,14 +352,13 @@ export default function UserProfile() {
label={t("userProfile.form.username")}
hasFeedback
validateStatus={
webSocketContext.UserProfileStateUsername.length <
Constants.GLOBALS.MIN_USERNAME_LENGTH && "error"
username < Constants.GLOBALS.MIN_USERNAME_LENGTH && "error"
}
>
<Input
value={webSocketContext.UserProfileStateUsername}
value={userProfile.username}
onChange={(e) =>
webSocketContext.setUserProfileStateUsername(e.target.value)
setUserProfile({ ...userProfile, Username: e.target.value })
}
minLength={Constants.GLOBALS.MIN_USERNAME_LENGTH}
maxLength={Constants.GLOBALS.MAX_USERNAME_LENGTH}
@ -359,15 +367,13 @@ export default function UserProfile() {
<Form.Item
label={t("userProfile.form.email")}
hasFeedback
validateStatus={
!isEmailValid(webSocketContext.UserProfileStateEmail) && "error"
}
validateStatus={!isEmailValid(userProfile.email) && "error"}
>
<Input
type="email"
value={webSocketContext.UserProfileStateEmail}
value={userProfile.email}
onChange={(e) =>
webSocketContext.setUserProfileStateEmail(e.target.value)
setUserProfile({ ...userProfile, Email: e.target.value })
}
/>
</Form.Item>
@ -431,8 +437,7 @@ export default function UserProfile() {
<br />
<Typography.Title level={4}>
{t("userProfile.header.yourSessions")} (
{webSocketContext.User.Sessions.length})
{t("userProfile.header.yourSessions")} ({userProfile.sessions.length})
</Typography.Title>
<Table
@ -442,7 +447,7 @@ export default function UserProfile() {
/>
{hasPermission(
webSocketContext.User.Permissions,
userProfile.Permissions,
Constants.PERMISSIONS.USER_PROFILE.API_KEYS
) && (
<>
@ -455,7 +460,7 @@ export default function UserProfile() {
>
<Typography.Title level={4}>
{t("userProfile.header.yourApiKeys")} (
{webSocketContext.User.ApiKeys.length}){" "}
{userProfile.apiKeys.length}){" "}
<Tooltip title={t("userProfile.icon.viewApiDoc")}>
<Link
target="_blank"

View File

@ -130,6 +130,7 @@ export const Constants = {
INFO: 0,
ERROR: 1,
},
LOADING: "loading...",
};
export const AppStyle = {
@ -224,7 +225,7 @@ let webSocketContextPreview = {
export const WebSocketContext = createContext(webSocketContextPreview);
// commands received from the backend server
const ReceivedMessagesCommands = {
export const ReceivedMessagesCommands = {
InitUserSocketConnection: 1,
UpdateConnectedUsers: 2,
NewGroupTaskStarted: 3,
@ -1272,27 +1273,31 @@ export function CapitalizeFirstLetter(string) {
}
export function hasPermission(userPermissions, permission) {
return userPermissions.includes(permission);
return true;
//return userPermissions.includes(permission);
}
export function hasXYPermission(userPermissions, permission, xyValue) {
return userPermissions.includes(
return true;
/*return userPermissions.includes(
permission.replace("XY", xyValue.toLowerCase())
);
); */
}
export function hasOnePermission(userPermissions, ...permissions) {
for (const permission of permissions) {
return true;
/*for (const permission of permissions) {
if (userPermissions.includes(permission)) {
return true;
}
}
return false;
return false; */
}
export function hasOneXYPermission(userPermissions, xyValue, ...permissions) {
for (const permission of permissions) {
return true;
/* for (const permission of permissions) {
if (
userPermissions.includes(permission.replace("XY", xyValue.toLowerCase()))
) {
@ -1300,7 +1305,7 @@ export function hasOneXYPermission(userPermissions, xyValue, ...permissions) {
}
}
return false;
return false; */
}
export function EncodeStringToBase64(value) {