added multiple contexts
parent
c125751f17
commit
ba5d3e9d20
52
src/App.js
52
src/App.js
|
@ -2,11 +2,52 @@ import { useState } from "react";
|
||||||
import "antd/dist/reset.css";
|
import "antd/dist/reset.css";
|
||||||
import "./App.css";
|
import "./App.css";
|
||||||
import Login from "./Pages/Login";
|
import Login from "./Pages/Login";
|
||||||
import { Layout, message, notification } from "antd";
|
import { Layout, notification } from "antd";
|
||||||
import { UseUserSession, WebSocketProvider } from "./utils";
|
import { UseUserSession } from "./utils";
|
||||||
import DashboardLayout from "./Components/DashboardLayout";
|
import DashboardLayout from "./Components/DashboardLayout";
|
||||||
|
import WebSocketProvider from "./Contexts/WebSocketContext";
|
||||||
|
import SideBarProvider from "./Contexts/SideBarContext";
|
||||||
|
import { AppProvider } from "./Contexts/AppContext";
|
||||||
|
|
||||||
export default function App() {
|
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] =
|
const [notificationApi, notificationContextHolder] =
|
||||||
notification.useNotification();
|
notification.useNotification();
|
||||||
const { userSession, setUserSession } = UseUserSession();
|
const { userSession, setUserSession } = UseUserSession();
|
||||||
|
@ -26,6 +67,7 @@ export default function App() {
|
||||||
return (
|
return (
|
||||||
<Layout style={{ minHeight: "100vh" }}>
|
<Layout style={{ minHeight: "100vh" }}>
|
||||||
{notificationContextHolder}
|
{notificationContextHolder}
|
||||||
|
|
||||||
<WebSocketProvider
|
<WebSocketProvider
|
||||||
userSession={userSession}
|
userSession={userSession}
|
||||||
setUserSession={setUserSession}
|
setUserSession={setUserSession}
|
||||||
|
@ -42,9 +84,9 @@ export default function App() {
|
||||||
</WebSocketProvider>
|
</WebSocketProvider>
|
||||||
</Layout>
|
</Layout>
|
||||||
);
|
);
|
||||||
}
|
} */
|
||||||
|
|
||||||
const ReconnectingView = ({ webSocketIsReady }) => {
|
const ReconnectingView = ({ isWebSocketReady }) => {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
|
@ -54,7 +96,7 @@ const ReconnectingView = ({ webSocketIsReady }) => {
|
||||||
right: 0,
|
right: 0,
|
||||||
bottom: 0,
|
bottom: 0,
|
||||||
backgroundColor: "rgba(0, 0, 0, 0.8)",
|
backgroundColor: "rgba(0, 0, 0, 0.8)",
|
||||||
display: webSocketIsReady ? "none" : "block",
|
display: isWebSocketReady ? "none" : "block",
|
||||||
justifyContent: "center",
|
justifyContent: "center",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
zIndex: 9999,
|
zIndex: 9999,
|
||||||
|
|
|
@ -11,11 +11,12 @@ import Scanners from "../../Pages/Scanners";
|
||||||
import AdminAreaRoles from "../../Pages/AdminArea/Roles";
|
import AdminAreaRoles from "../../Pages/AdminArea/Roles";
|
||||||
import AdminAreaLogs from "../../Pages/AdminArea/Logs";
|
import AdminAreaLogs from "../../Pages/AdminArea/Logs";
|
||||||
import AllUsers from "../../Pages/AllUsers";
|
import AllUsers from "../../Pages/AllUsers";
|
||||||
import { useContext } from "react";
|
|
||||||
import GroupTasks from "../../Pages/GroupTasks/Overview";
|
import GroupTasks from "../../Pages/GroupTasks/Overview";
|
||||||
import GroupTasksHistory from "../../Pages/GroupTasks/History";
|
import GroupTasksHistory from "../../Pages/GroupTasks/History";
|
||||||
import PageNotFound from "../../Pages/PageNotFound";
|
import PageNotFound from "../../Pages/PageNotFound";
|
||||||
import EquipmentDocumentationOverview from "../../Pages/EquipmentDocumentation";
|
import EquipmentDocumentationOverview from "../../Pages/EquipmentDocumentation";
|
||||||
|
import { UserProfileProvider } from "../../Contexts/UserProfileContext";
|
||||||
|
import { UsersProvider } from "../../Contexts/UsersContext";
|
||||||
|
|
||||||
export default function AppRoutes() {
|
export default function AppRoutes() {
|
||||||
// const webSocketContext = useContext(WebSocketContext);
|
// const webSocketContext = useContext(WebSocketContext);
|
||||||
|
@ -79,9 +80,23 @@ export default function AppRoutes() {
|
||||||
|
|
||||||
<Route path="/scanners" element={<Scanners />} />
|
<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 />} />
|
<Route path="/admin-area/roles" element={<AdminAreaRoles />} />
|
||||||
|
|
||||||
|
|
|
@ -58,3 +58,16 @@ export function MyAvatar({
|
||||||
|
|
||||||
return <MyAvat />;
|
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}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import { EditOutlined } from "@ant-design/icons";
|
import { EditOutlined } from "@ant-design/icons";
|
||||||
import { Input, Typography } from "antd";
|
import { Input, Typography } from "antd";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { Constants } from "../../utils";
|
|
||||||
|
|
||||||
export default function MyTypography({ value, setValue, maxLength }) {
|
export default function MyTypography({ value, setValue, maxLength }) {
|
||||||
const [editing, setEditing] = useState(false);
|
const [editing, setEditing] = useState(false);
|
||||||
|
|
|
@ -14,15 +14,11 @@ import Sider from "antd/es/layout/Sider";
|
||||||
import { useContext, useEffect, useState } from "react";
|
import { useContext, useEffect, useState } from "react";
|
||||||
import { useLocation, useNavigate } from "react-router-dom";
|
import { useLocation, useNavigate } from "react-router-dom";
|
||||||
import PropTypes from "prop-types";
|
import PropTypes from "prop-types";
|
||||||
import {
|
import { Constants, hasOnePermission, hasPermission } from "../../utils";
|
||||||
Constants,
|
|
||||||
WebSocketContext,
|
|
||||||
getUserId,
|
|
||||||
hasOnePermission,
|
|
||||||
hasPermission,
|
|
||||||
} from "../../utils";
|
|
||||||
import { useTranslation } from "react-i18next";
|
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({
|
export default function SideMenu({
|
||||||
userSession,
|
userSession,
|
||||||
|
@ -30,9 +26,10 @@ export default function SideMenu({
|
||||||
isSideMenuCollapsed,
|
isSideMenuCollapsed,
|
||||||
setIsSideMenuCollapsed,
|
setIsSideMenuCollapsed,
|
||||||
}) {
|
}) {
|
||||||
|
const appContext = useAppContext();
|
||||||
|
const sidebarContext = useSideBarContext();
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const [selectedKeys, setSelectedKeys] = useState("/");
|
const [selectedKeys, setSelectedKeys] = useState("/");
|
||||||
const webSocketContext = useContext(WebSocketContext);
|
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
useEffect(() => setSelectedKeys(location.pathname), [location.pathname]);
|
useEffect(() => setSelectedKeys(location.pathname), [location.pathname]);
|
||||||
|
@ -40,13 +37,17 @@ export default function SideMenu({
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
const getCurrentUsedScannerName = () => {
|
const getCurrentUsedScannerName = () => {
|
||||||
const scannerName = webSocketContext.Scanners.find(
|
/*const scannerName = webSocketContext.Scanners.find(
|
||||||
(scanner) => scanner.UsedByUserId === getUserId()
|
(scanner) => scanner.UsedByUserId === getUserId()
|
||||||
)?.Name;
|
)?.Name;
|
||||||
|
|
||||||
return scannerName === undefined
|
return scannerName === undefined
|
||||||
? t("sideMenu.adminArea.noScannerSelected")
|
? t("sideMenu.adminArea.noScannerSelected")
|
||||||
: scannerName;
|
: scannerName; */
|
||||||
|
|
||||||
|
// TODO: handle scanner name
|
||||||
|
|
||||||
|
return Constants.LOADING;
|
||||||
};
|
};
|
||||||
|
|
||||||
const getFirstMenuItems = () => {
|
const getFirstMenuItems = () => {
|
||||||
|
@ -57,19 +58,19 @@ export default function SideMenu({
|
||||||
key: "/",
|
key: "/",
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
/*
|
|
||||||
if (
|
if (
|
||||||
hasPermission(
|
hasPermission(
|
||||||
webSocketContext.User.Permissions,
|
appContext.userPermissions,
|
||||||
Constants.PERMISSIONS.EQUIPMENT_DOCUMENTATION.VIEW
|
Constants.PERMISSIONS.EQUIPMENT_DOCUMENTATION.VIEW
|
||||||
)
|
)
|
||||||
) { */
|
) {
|
||||||
items.push({
|
items.push({
|
||||||
label: t("sideMenu.equipmentDocumentation"),
|
label: t("sideMenu.equipmentDocumentation"),
|
||||||
icon: <BookOutlined />,
|
icon: <BookOutlined />,
|
||||||
key: "/equipment-documentation",
|
key: "/equipment-documentation",
|
||||||
});
|
});
|
||||||
//}
|
}
|
||||||
|
|
||||||
let groupTasks = {
|
let groupTasks = {
|
||||||
label: t("sideMenu.groupTasks.menuCategory"),
|
label: t("sideMenu.groupTasks.menuCategory"),
|
||||||
|
@ -85,7 +86,7 @@ export default function SideMenu({
|
||||||
|
|
||||||
if (
|
if (
|
||||||
hasPermission(
|
hasPermission(
|
||||||
webSocketContext.User.Permissions,
|
appContext.userPermissions,
|
||||||
Constants.PERMISSIONS.GROUP_TASKS.HISTORY
|
Constants.PERMISSIONS.GROUP_TASKS.HISTORY
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
|
@ -104,7 +105,7 @@ export default function SideMenu({
|
||||||
|
|
||||||
if (
|
if (
|
||||||
hasOnePermission(
|
hasOnePermission(
|
||||||
webSocketContext.User.Permissions,
|
appContext.userPermissions,
|
||||||
Constants.PERMISSIONS.ADMIN_AREA.ROLES.CREATE_NEW_ROLE,
|
Constants.PERMISSIONS.ADMIN_AREA.ROLES.CREATE_NEW_ROLE,
|
||||||
Constants.PERMISSIONS.ADMIN_AREA.ROLES.UPDATE_ROLE,
|
Constants.PERMISSIONS.ADMIN_AREA.ROLES.UPDATE_ROLE,
|
||||||
Constants.PERMISSIONS.ADMIN_AREA.ROLES.DELETE_ROLE,
|
Constants.PERMISSIONS.ADMIN_AREA.ROLES.DELETE_ROLE,
|
||||||
|
@ -121,7 +122,7 @@ export default function SideMenu({
|
||||||
|
|
||||||
if (
|
if (
|
||||||
hasOnePermission(
|
hasOnePermission(
|
||||||
webSocketContext.User.Permissions,
|
appContext.userPermissions,
|
||||||
Constants.PERMISSIONS.ADMIN_AREA.ROLES.CREATE_NEW_ROLE,
|
Constants.PERMISSIONS.ADMIN_AREA.ROLES.CREATE_NEW_ROLE,
|
||||||
Constants.PERMISSIONS.ADMIN_AREA.ROLES.UPDATE_ROLE,
|
Constants.PERMISSIONS.ADMIN_AREA.ROLES.UPDATE_ROLE,
|
||||||
Constants.PERMISSIONS.ADMIN_AREA.ROLES.DELETE_ROLE,
|
Constants.PERMISSIONS.ADMIN_AREA.ROLES.DELETE_ROLE,
|
||||||
|
@ -137,7 +138,7 @@ export default function SideMenu({
|
||||||
|
|
||||||
if (
|
if (
|
||||||
hasPermission(
|
hasPermission(
|
||||||
webSocketContext.User.Permissions,
|
appContext.userPermissions,
|
||||||
Constants.PERMISSIONS.ADMIN_AREA.LOGS
|
Constants.PERMISSIONS.ADMIN_AREA.LOGS
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
|
@ -155,11 +156,13 @@ export default function SideMenu({
|
||||||
};
|
};
|
||||||
|
|
||||||
const getSecondMenuItems = () => {
|
const getSecondMenuItems = () => {
|
||||||
|
console.log("getSecondMenuItems", sidebarContext.connectionBadgeStatus);
|
||||||
|
|
||||||
let items = [];
|
let items = [];
|
||||||
|
|
||||||
if (
|
if (
|
||||||
hasPermission(
|
hasPermission(
|
||||||
webSocketContext.User.Permissions,
|
appContext.userPermissions,
|
||||||
Constants.PERMISSIONS.SCANNER.USE_SCANNERS
|
Constants.PERMISSIONS.SCANNER.USE_SCANNERS
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
|
@ -174,9 +177,9 @@ export default function SideMenu({
|
||||||
{
|
{
|
||||||
icon: (
|
icon: (
|
||||||
<Badge
|
<Badge
|
||||||
status={webSocketContext.ConnectionBadgeStatus}
|
status={sidebarContext.connectionBadgeStatus}
|
||||||
text={`${webSocketContext.ConnectedWebSocketUsersCount} ${
|
text={`${sidebarContext.connectedUsers} ${
|
||||||
webSocketContext.ConnectedWebSocketUsersCount === 1
|
sidebarContext.connectedUsers === 1
|
||||||
? t("sideMenu.usersCount.single")
|
? t("sideMenu.usersCount.single")
|
||||||
: t("sideMenu.usersCount.multiple")
|
: t("sideMenu.usersCount.multiple")
|
||||||
}`}
|
}`}
|
||||||
|
@ -185,13 +188,8 @@ export default function SideMenu({
|
||||||
key: "/users",
|
key: "/users",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: ` ${webSocketContext.User.Username}`,
|
label: ` ${appContext.username}`,
|
||||||
icon: (
|
icon: <MyUserAvatar avatar={appContext.avatar} />,
|
||||||
<MyAvatar
|
|
||||||
allUsers={webSocketContext.AllUsers}
|
|
||||||
userId={webSocketContext.User.Id}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
key: "/user-profile",
|
key: "/user-profile",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -216,6 +214,11 @@ export default function SideMenu({
|
||||||
return items;
|
return items;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
"sidebarContext.connectionBadgeStatus",
|
||||||
|
sidebarContext.connectionBadgeStatus
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Sider
|
<Sider
|
||||||
theme="light"
|
theme="light"
|
||||||
|
|
|
@ -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>
|
||||||
|
);
|
||||||
|
}
|
|
@ -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>
|
||||||
|
);
|
||||||
|
}
|
|
@ -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>
|
||||||
|
);
|
||||||
|
}
|
|
@ -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>
|
||||||
|
);
|
||||||
|
}
|
|
@ -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>
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
export function handleWebSocketMessage(message) {}
|
|
@ -12,20 +12,25 @@ import {
|
||||||
Constants,
|
Constants,
|
||||||
FormatDatetime,
|
FormatDatetime,
|
||||||
SentMessagesCommands,
|
SentMessagesCommands,
|
||||||
WebSocketContext,
|
|
||||||
getConnectionStatusItem,
|
getConnectionStatusItem,
|
||||||
hasOnePermission,
|
hasOnePermission,
|
||||||
hasPermission,
|
hasPermission,
|
||||||
|
myFetch,
|
||||||
} from "../../utils";
|
} from "../../utils";
|
||||||
import { useContext, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
import { UserAddOutlined } from "@ant-design/icons";
|
import { UserAddOutlined } from "@ant-design/icons";
|
||||||
import CreateUserModal from "./CreateUserModal";
|
import CreateUserModal from "./CreateUserModal";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { MyAvatar } from "../../Components/MyAvatar";
|
import { MyAvatar } from "../../Components/MyAvatar";
|
||||||
|
import { useUsersContext } from "../../Contexts/UsersContext";
|
||||||
|
import { useAppContext } from "../../Contexts/AppContext";
|
||||||
|
import { useWebSocketContext } from "../../Contexts/WebSocketContext";
|
||||||
|
|
||||||
export default function AllUsers() {
|
export default function AllUsers() {
|
||||||
const webSocketContext = useContext(WebSocketContext);
|
const webSocketContext = useWebSocketContext();
|
||||||
|
const appContext = useAppContext();
|
||||||
|
const usersContext = useUsersContext();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [selectedRoleId, setSelectedRoleId] = useState("");
|
const [selectedRoleId, setSelectedRoleId] = useState("");
|
||||||
const [notificationApi, notificationContextHolder] =
|
const [notificationApi, notificationContextHolder] =
|
||||||
|
@ -63,7 +68,7 @@ export default function AllUsers() {
|
||||||
|
|
||||||
if (
|
if (
|
||||||
hasOnePermission(
|
hasOnePermission(
|
||||||
webSocketContext.User.Permissions,
|
appContext.userPermissions,
|
||||||
Constants.PERMISSIONS.ALL_USERS.ACTION.CHANGE_ROLE,
|
Constants.PERMISSIONS.ALL_USERS.ACTION.CHANGE_ROLE,
|
||||||
Constants.PERMISSIONS.ALL_USERS.ACTION.DELETE_USER,
|
Constants.PERMISSIONS.ALL_USERS.ACTION.DELETE_USER,
|
||||||
Constants.PERMISSIONS.ALL_USERS.ACTION.DEACTIVATE_USER
|
Constants.PERMISSIONS.ALL_USERS.ACTION.DEACTIVATE_USER
|
||||||
|
@ -75,17 +80,16 @@ export default function AllUsers() {
|
||||||
render: (_, record) => (
|
render: (_, record) => (
|
||||||
<Space size="middle">
|
<Space size="middle">
|
||||||
{hasPermission(
|
{hasPermission(
|
||||||
webSocketContext.User.Permissions,
|
appContext.userPermissions,
|
||||||
Constants.PERMISSIONS.ALL_USERS.ACTION.CHANGE_ROLE
|
Constants.PERMISSIONS.ALL_USERS.ACTION.CHANGE_ROLE
|
||||||
) &&
|
) &&
|
||||||
(webSocketContext.AllRoles.find(
|
(usersContext.roles.find(
|
||||||
(role) => role.Id === webSocketContext.User.RoleId
|
(role) => role.Id === usersContext.roleId
|
||||||
).SortingOrder <
|
).SortingOrder <
|
||||||
webSocketContext.AllRoles.find(
|
usersContext.roles.find((role) => role.Id === record._roleId)
|
||||||
(role) => role.Id === record._roleId
|
.SortingOrder ||
|
||||||
).SortingOrder ||
|
usersContext.roles.find(
|
||||||
webSocketContext.AllRoles.find(
|
(role) => role.Id === usersContext.roleId
|
||||||
(role) => role.Id === webSocketContext.User.RoleId
|
|
||||||
).Master) && (
|
).Master) && (
|
||||||
<Popconfirm
|
<Popconfirm
|
||||||
title={t(
|
title={t(
|
||||||
|
@ -99,29 +103,28 @@ export default function AllUsers() {
|
||||||
okButtonProps={{
|
okButtonProps={{
|
||||||
disabled:
|
disabled:
|
||||||
selectedRoleId ===
|
selectedRoleId ===
|
||||||
webSocketContext.AllUsers.find(
|
usersContext.users.find((user) => user.Id === record.key)
|
||||||
(user) => user.Id === record.key
|
.RoleId,
|
||||||
).RoleId,
|
|
||||||
}}
|
}}
|
||||||
description={
|
description={
|
||||||
<Select
|
<Select
|
||||||
style={{ width: 250 }}
|
style={{ width: 250 }}
|
||||||
getPopupContainer={(node) => node.parentNode}
|
getPopupContainer={(node) => node.parentNode}
|
||||||
defaultValue={
|
defaultValue={
|
||||||
webSocketContext.AllUsers.find(
|
usersContext.users.find(
|
||||||
(user) => user.Id === record.key
|
(user) => user.Id === record.key
|
||||||
).RoleId
|
).RoleId
|
||||||
}
|
}
|
||||||
value={selectedRoleId}
|
value={selectedRoleId}
|
||||||
onChange={(e) => setSelectedRoleId(e)}
|
onChange={(e) => setSelectedRoleId(e)}
|
||||||
>
|
>
|
||||||
{webSocketContext.AllRoles.map((role) => {
|
{usersContext.roles.map((role) => {
|
||||||
if (
|
if (
|
||||||
webSocketContext.AllRoles.find(
|
usersContext.roles.find(
|
||||||
(role) => role.Id === webSocketContext.User.RoleId
|
(role) => role.Id === usersContext.roleId
|
||||||
).Master ||
|
).Master ||
|
||||||
webSocketContext.AllRoles.find(
|
usersContext.roles.find(
|
||||||
(role) => role.Id === webSocketContext.User.RoleId
|
(role) => role.Id === usersContext.roleId
|
||||||
).SortingOrder < role.SortingOrder
|
).SortingOrder < role.SortingOrder
|
||||||
) {
|
) {
|
||||||
return (
|
return (
|
||||||
|
@ -140,7 +143,7 @@ export default function AllUsers() {
|
||||||
to="#"
|
to="#"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setSelectedRoleId(
|
setSelectedRoleId(
|
||||||
webSocketContext.AllUsers.find(
|
usersContext.users.find(
|
||||||
(user) => user.Id === record.key
|
(user) => user.Id === record.key
|
||||||
).RoleId
|
).RoleId
|
||||||
);
|
);
|
||||||
|
@ -152,17 +155,16 @@ export default function AllUsers() {
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{hasPermission(
|
{hasPermission(
|
||||||
webSocketContext.User.Permissions,
|
appContext.userPermissions,
|
||||||
Constants.PERMISSIONS.ALL_USERS.ACTION.DELETE_USER
|
Constants.PERMISSIONS.ALL_USERS.ACTION.DELETE_USER
|
||||||
) &&
|
) &&
|
||||||
(webSocketContext.AllRoles.find(
|
(usersContext.roles.find(
|
||||||
(role) => role.Id === webSocketContext.User.RoleId
|
(role) => role.Id === usersContext.roleId
|
||||||
).SortingOrder <
|
).SortingOrder <
|
||||||
webSocketContext.AllRoles.find(
|
usersContext.roles.find((role) => role.Id === record._roleId)
|
||||||
(role) => role.Id === record._roleId
|
.SortingOrder ||
|
||||||
).SortingOrder ||
|
usersContext.roles.find(
|
||||||
webSocketContext.AllRoles.find(
|
(role) => role.Id === usersContext.roleId
|
||||||
(role) => role.Id === webSocketContext.User.RoleId
|
|
||||||
).Master) && (
|
).Master) && (
|
||||||
<Popconfirm
|
<Popconfirm
|
||||||
placement="top"
|
placement="top"
|
||||||
|
@ -175,20 +177,19 @@ export default function AllUsers() {
|
||||||
</Popconfirm>
|
</Popconfirm>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{!webSocketContext.AllUsers.find((user) => user.Id === record.key)
|
{!usersContext.users.find((user) => user.Id === record.key)
|
||||||
.Deactivated
|
.Deactivated
|
||||||
? hasPermission(
|
? hasPermission(
|
||||||
webSocketContext.User.Permissions,
|
appContext.userPermissions,
|
||||||
Constants.PERMISSIONS.ALL_USERS.ACTION.USER_DEACTIVATION
|
Constants.PERMISSIONS.ALL_USERS.ACTION.USER_DEACTIVATION
|
||||||
) &&
|
) &&
|
||||||
(webSocketContext.AllRoles.find(
|
(usersContext.roles.find(
|
||||||
(role) => role.Id === webSocketContext.User.RoleId
|
(role) => role.Id === usersContext.roleId
|
||||||
).SortingOrder <
|
).SortingOrder <
|
||||||
webSocketContext.AllRoles.find(
|
usersContext.roles.find((role) => role.Id === record._roleId)
|
||||||
(role) => role.Id === record._roleId
|
.SortingOrder ||
|
||||||
).SortingOrder ||
|
usersContext.roles.find(
|
||||||
webSocketContext.AllRoles.find(
|
(role) => role.Id === usersContext.roleId
|
||||||
(role) => role.Id === webSocketContext.User.RoleId
|
|
||||||
).Master) && (
|
).Master) && (
|
||||||
<Popconfirm
|
<Popconfirm
|
||||||
placement="top"
|
placement="top"
|
||||||
|
@ -209,17 +210,16 @@ export default function AllUsers() {
|
||||||
</Popconfirm>
|
</Popconfirm>
|
||||||
)
|
)
|
||||||
: hasPermission(
|
: hasPermission(
|
||||||
webSocketContext.User.Permissions,
|
appContext.userPermissions,
|
||||||
Constants.PERMISSIONS.ALL_USERS.ACTION.USER_DEACTIVATION
|
Constants.PERMISSIONS.ALL_USERS.ACTION.USER_DEACTIVATION
|
||||||
) &&
|
) &&
|
||||||
(webSocketContext.AllRoles.find(
|
(usersContext.roles.find(
|
||||||
(role) => role.Id === webSocketContext.User.RoleId
|
(role) => role.Id === usersContext.roleId
|
||||||
).SortingOrder <
|
).SortingOrder <
|
||||||
webSocketContext.AllRoles.find(
|
usersContext.roles.find((role) => role.Id === record._roleId)
|
||||||
(role) => role.Id === record._roleId
|
.SortingOrder ||
|
||||||
).SortingOrder ||
|
usersContext.roles.find(
|
||||||
webSocketContext.AllRoles.find(
|
(role) => role.Id === usersContext.roleId
|
||||||
(role) => role.Id === webSocketContext.User.RoleId
|
|
||||||
).Master) && (
|
).Master) && (
|
||||||
<Popconfirm
|
<Popconfirm
|
||||||
placement="top"
|
placement="top"
|
||||||
|
@ -247,10 +247,10 @@ export default function AllUsers() {
|
||||||
return items;
|
return items;
|
||||||
};
|
};
|
||||||
|
|
||||||
const activatedUsers = webSocketContext.AllUsers.filter(
|
const activatedUsers = usersContext.users.filter(
|
||||||
(user) => user.Deactivated === false
|
(user) => user.Deactivated === false
|
||||||
);
|
);
|
||||||
const deactivatedUsers = webSocketContext.AllUsers.filter(
|
const deactivatedUsers = usersContext.users.filter(
|
||||||
(user) => user.Deactivated === true
|
(user) => user.Deactivated === true
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -259,8 +259,8 @@ export default function AllUsers() {
|
||||||
|
|
||||||
users.sort(
|
users.sort(
|
||||||
(a, b) =>
|
(a, b) =>
|
||||||
webSocketContext.AllRoles.find((r) => r.Id === a.RoleId).SortingOrder -
|
usersContext.roles.find((r) => r.Id === a.RoleId).SortingOrder -
|
||||||
webSocketContext.AllRoles.find((r) => r.Id === b.RoleId).SortingOrder
|
usersContext.roles.find((r) => r.Id === b.RoleId).SortingOrder
|
||||||
);
|
);
|
||||||
|
|
||||||
users.forEach((user) => {
|
users.forEach((user) => {
|
||||||
|
@ -277,7 +277,7 @@ export default function AllUsers() {
|
||||||
</>
|
</>
|
||||||
</Popover>
|
</Popover>
|
||||||
),
|
),
|
||||||
role: webSocketContext.AllRoles.find((role) => role.Id === user.RoleId)
|
role: usersContext.roles.find((role) => role.Id === user.RoleId)
|
||||||
.DisplayName,
|
.DisplayName,
|
||||||
_roleId: user.RoleId, // used as reference for user deletion
|
_roleId: user.RoleId, // used as reference for user deletion
|
||||||
connectionStatus: getConnectionStatusItem(user.ConnectionStatus),
|
connectionStatus: getConnectionStatusItem(user.ConnectionStatus),
|
||||||
|
@ -290,7 +290,7 @@ export default function AllUsers() {
|
||||||
};
|
};
|
||||||
|
|
||||||
const onRoleChangeConfirm = (targetUserId) => {
|
const onRoleChangeConfirm = (targetUserId) => {
|
||||||
const existsRole = webSocketContext.AllRoles.find(
|
const existsRole = usersContext.roles.find(
|
||||||
(role) => role.Id === selectedRoleId
|
(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 (
|
return (
|
||||||
<>
|
<>
|
||||||
{notificationContextHolder}
|
{notificationContextHolder}
|
||||||
|
@ -344,7 +354,7 @@ export default function AllUsers() {
|
||||||
{t("allUsers.header.allUsers")} ({activatedUsers.length})
|
{t("allUsers.header.allUsers")} ({activatedUsers.length})
|
||||||
</Typography.Title>
|
</Typography.Title>
|
||||||
{hasPermission(
|
{hasPermission(
|
||||||
webSocketContext.User.Permissions,
|
appContext.userPermissions,
|
||||||
Constants.PERMISSIONS.ALL_USERS.CREATE_NEW_USER
|
Constants.PERMISSIONS.ALL_USERS.CREATE_NEW_USER
|
||||||
) && (
|
) && (
|
||||||
<Button
|
<Button
|
||||||
|
@ -363,7 +373,7 @@ export default function AllUsers() {
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{hasPermission(
|
{hasPermission(
|
||||||
webSocketContext.User.Permissions,
|
appContext.userPermissions,
|
||||||
Constants.PERMISSIONS.ALL_USERS.ACTION.USER_DEACTIVATION
|
Constants.PERMISSIONS.ALL_USERS.ACTION.USER_DEACTIVATION
|
||||||
) &&
|
) &&
|
||||||
deactivatedUsers.length > 0 && (
|
deactivatedUsers.length > 0 && (
|
||||||
|
|
|
@ -1,15 +1,5 @@
|
||||||
import {
|
import { Card, Col, Popover, Result, Row, Spin, Typography } from "antd";
|
||||||
Button,
|
|
||||||
Card,
|
|
||||||
Col,
|
|
||||||
Popover,
|
|
||||||
Result,
|
|
||||||
Row,
|
|
||||||
Spin,
|
|
||||||
Typography,
|
|
||||||
} from "antd";
|
|
||||||
import { useContext, useEffect, useState } from "react";
|
import { useContext, useEffect, useState } from "react";
|
||||||
import { useNavigate } from "react-router-dom";
|
|
||||||
import CreateEquipmentDocumentationModal from "./CreateEquipmentDocumentationModal";
|
import CreateEquipmentDocumentationModal from "./CreateEquipmentDocumentationModal";
|
||||||
import {
|
import {
|
||||||
AppStyle,
|
AppStyle,
|
||||||
|
@ -287,7 +277,7 @@ function DocumentationTypeIcon({ type }) {
|
||||||
case 2:
|
case 2:
|
||||||
return <BookOutlined style={{ fontSize: 24 }} />;
|
return <BookOutlined style={{ fontSize: 24 }} />;
|
||||||
default:
|
default:
|
||||||
console.log("DocumentationTypeIcon type not found:", type);
|
console.error("DocumentationTypeIcon type not found:", type);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,6 @@ import {
|
||||||
ArrowUpOutlined,
|
ArrowUpOutlined,
|
||||||
CameraOutlined,
|
CameraOutlined,
|
||||||
DeleteOutlined,
|
DeleteOutlined,
|
||||||
EditOutlined,
|
|
||||||
EllipsisOutlined,
|
EllipsisOutlined,
|
||||||
FullscreenOutlined,
|
FullscreenOutlined,
|
||||||
PlusOutlined,
|
PlusOutlined,
|
||||||
|
@ -86,8 +85,6 @@ export default function EquipmentDocumentationOverview() {
|
||||||
<>
|
<>
|
||||||
<QrScanner
|
<QrScanner
|
||||||
onDecode={(result) => {
|
onDecode={(result) => {
|
||||||
console.log(result);
|
|
||||||
|
|
||||||
if (!isScannedQrCodeValid(result)) {
|
if (!isScannedQrCodeValid(result)) {
|
||||||
messageApi.error(
|
messageApi.error(
|
||||||
t(
|
t(
|
||||||
|
@ -100,7 +97,7 @@ export default function EquipmentDocumentationOverview() {
|
||||||
setScannerResult(JSON.parse(result).stockitem.toString());
|
setScannerResult(JSON.parse(result).stockitem.toString());
|
||||||
setIsScannerActive(false);
|
setIsScannerActive(false);
|
||||||
}}
|
}}
|
||||||
onError={(error) => console.log(error?.message)}
|
onError={(error) => console.error(error?.message)}
|
||||||
/>
|
/>
|
||||||
<Button
|
<Button
|
||||||
block
|
block
|
||||||
|
|
|
@ -14,13 +14,12 @@ import {
|
||||||
Upload,
|
Upload,
|
||||||
notification,
|
notification,
|
||||||
} from "antd";
|
} from "antd";
|
||||||
import { useContext, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import {
|
import {
|
||||||
Constants,
|
Constants,
|
||||||
EncodeStringToBase64,
|
EncodeStringToBase64,
|
||||||
FormatDatetime,
|
FormatDatetime,
|
||||||
SentMessagesCommands,
|
SentMessagesCommands,
|
||||||
WebSocketContext,
|
|
||||||
getConnectionStatusItem,
|
getConnectionStatusItem,
|
||||||
getUserSessionFromLocalStorage,
|
getUserSessionFromLocalStorage,
|
||||||
hasPermission,
|
hasPermission,
|
||||||
|
@ -36,14 +35,19 @@ import {
|
||||||
FileTextOutlined,
|
FileTextOutlined,
|
||||||
KeyOutlined,
|
KeyOutlined,
|
||||||
} from "@ant-design/icons";
|
} 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() {
|
export default function UserProfile() {
|
||||||
const webSocketContext = useContext(WebSocketContext);
|
const webSocketContext = useWebSocketContext();
|
||||||
|
const { userProfile, setUserProfile } = useUserProfileContext();
|
||||||
const [notificationApi, notificationContextHolder] =
|
const [notificationApi, notificationContextHolder] =
|
||||||
notification.useNotification();
|
notification.useNotification();
|
||||||
const { t, i18n } = useTranslation();
|
const { t, i18n } = useTranslation();
|
||||||
|
|
||||||
|
const [username, setUsername] = useState(Constants.LOADING);
|
||||||
|
const [email, setEmail] = useState(Constants.LOADING);
|
||||||
const [oldPassword, setOldPassword] = useState("");
|
const [oldPassword, setOldPassword] = useState("");
|
||||||
const [newPassword, setNewPassword] = useState("");
|
const [newPassword, setNewPassword] = useState("");
|
||||||
const [repeatedNewPassword, setRepeatedNewPassword] = useState("");
|
const [repeatedNewPassword, setRepeatedNewPassword] = useState("");
|
||||||
|
@ -178,7 +182,7 @@ export default function UserProfile() {
|
||||||
const getApiKeyTableItems = () => {
|
const getApiKeyTableItems = () => {
|
||||||
let items = [];
|
let items = [];
|
||||||
|
|
||||||
webSocketContext.User.ApiKeys.forEach((apiKey) => {
|
userProfile.apiKeys.forEach((apiKey) => {
|
||||||
items.push({
|
items.push({
|
||||||
key: apiKey.Id,
|
key: apiKey.Id,
|
||||||
name: apiKey.Name,
|
name: apiKey.Name,
|
||||||
|
@ -195,11 +199,11 @@ export default function UserProfile() {
|
||||||
const getSessionTableItems = () => {
|
const getSessionTableItems = () => {
|
||||||
let items = [];
|
let items = [];
|
||||||
|
|
||||||
webSocketContext.User.Sessions.sort(
|
userProfile.sessions.sort(
|
||||||
(a, b) => b.ConnectionStatus - a.ConnectionStatus
|
(a, b) => b.ConnectionStatus - a.ConnectionStatus
|
||||||
);
|
);
|
||||||
|
|
||||||
webSocketContext.User.Sessions.forEach((session) => {
|
userProfile.sessions.forEach((session) => {
|
||||||
items.push({
|
items.push({
|
||||||
key: session.IdForDeletion,
|
key: session.IdForDeletion,
|
||||||
userAgent: session.UserAgent,
|
userAgent: session.UserAgent,
|
||||||
|
@ -228,17 +232,15 @@ export default function UserProfile() {
|
||||||
|
|
||||||
const isButtonDisabled = () => {
|
const isButtonDisabled = () => {
|
||||||
if (
|
if (
|
||||||
!isEmailValid(webSocketContext.UserProfileStateEmail) ||
|
!isEmailValid(email) ||
|
||||||
webSocketContext.UserProfileStateUsername.length <
|
userProfile.username.length < Constants.GLOBALS.MIN_USERNAME_LENGTH
|
||||||
Constants.GLOBALS.MIN_USERNAME_LENGTH
|
|
||||||
) {
|
) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
webSocketContext.UserProfileStateUsername !==
|
username !== userProfile.username ||
|
||||||
webSocketContext.User.Username ||
|
email !== userProfile.email ||
|
||||||
webSocketContext.UserProfileStateEmail !== webSocketContext.User.Email ||
|
|
||||||
(oldPassword !== "" &&
|
(oldPassword !== "" &&
|
||||||
newPassword !== "" &&
|
newPassword !== "" &&
|
||||||
newPassword === repeatedNewPassword)
|
newPassword === repeatedNewPassword)
|
||||||
|
@ -252,17 +254,12 @@ export default function UserProfile() {
|
||||||
const handleOnSubmit = () => {
|
const handleOnSubmit = () => {
|
||||||
const changes = {};
|
const changes = {};
|
||||||
|
|
||||||
if (
|
if (userProfile.username !== username) {
|
||||||
webSocketContext.User.Username !==
|
changes.username = username;
|
||||||
webSocketContext.UserProfileStateUsername
|
|
||||||
) {
|
|
||||||
changes.username = webSocketContext.UserProfileStateUsername;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (userProfile.email !== email) {
|
||||||
webSocketContext.User.Email !== webSocketContext.UserProfileStateEmail
|
changes.email = email;
|
||||||
) {
|
|
||||||
changes.email = webSocketContext.UserProfileStateEmail;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
|
@ -288,6 +285,22 @@ export default function UserProfile() {
|
||||||
setNewApikeyName("");
|
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 (
|
return (
|
||||||
<>
|
<>
|
||||||
{notificationContextHolder}
|
{notificationContextHolder}
|
||||||
|
@ -310,11 +323,7 @@ export default function UserProfile() {
|
||||||
"X-Authorization": getUserSessionFromLocalStorage(),
|
"X-Authorization": getUserSessionFromLocalStorage(),
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<MyAvatar
|
<MyUserAvatar avatar={userProfile.avatar} size={256} />
|
||||||
avatarWidth={200}
|
|
||||||
allUsers={webSocketContext.AllUsers}
|
|
||||||
userId={webSocketContext.User.Id}
|
|
||||||
/>
|
|
||||||
</Upload>
|
</Upload>
|
||||||
</Col>
|
</Col>
|
||||||
|
|
||||||
|
@ -343,14 +352,13 @@ export default function UserProfile() {
|
||||||
label={t("userProfile.form.username")}
|
label={t("userProfile.form.username")}
|
||||||
hasFeedback
|
hasFeedback
|
||||||
validateStatus={
|
validateStatus={
|
||||||
webSocketContext.UserProfileStateUsername.length <
|
username < Constants.GLOBALS.MIN_USERNAME_LENGTH && "error"
|
||||||
Constants.GLOBALS.MIN_USERNAME_LENGTH && "error"
|
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<Input
|
<Input
|
||||||
value={webSocketContext.UserProfileStateUsername}
|
value={userProfile.username}
|
||||||
onChange={(e) =>
|
onChange={(e) =>
|
||||||
webSocketContext.setUserProfileStateUsername(e.target.value)
|
setUserProfile({ ...userProfile, Username: e.target.value })
|
||||||
}
|
}
|
||||||
minLength={Constants.GLOBALS.MIN_USERNAME_LENGTH}
|
minLength={Constants.GLOBALS.MIN_USERNAME_LENGTH}
|
||||||
maxLength={Constants.GLOBALS.MAX_USERNAME_LENGTH}
|
maxLength={Constants.GLOBALS.MAX_USERNAME_LENGTH}
|
||||||
|
@ -359,15 +367,13 @@ export default function UserProfile() {
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("userProfile.form.email")}
|
label={t("userProfile.form.email")}
|
||||||
hasFeedback
|
hasFeedback
|
||||||
validateStatus={
|
validateStatus={!isEmailValid(userProfile.email) && "error"}
|
||||||
!isEmailValid(webSocketContext.UserProfileStateEmail) && "error"
|
|
||||||
}
|
|
||||||
>
|
>
|
||||||
<Input
|
<Input
|
||||||
type="email"
|
type="email"
|
||||||
value={webSocketContext.UserProfileStateEmail}
|
value={userProfile.email}
|
||||||
onChange={(e) =>
|
onChange={(e) =>
|
||||||
webSocketContext.setUserProfileStateEmail(e.target.value)
|
setUserProfile({ ...userProfile, Email: e.target.value })
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
@ -431,8 +437,7 @@ export default function UserProfile() {
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
<Typography.Title level={4}>
|
<Typography.Title level={4}>
|
||||||
{t("userProfile.header.yourSessions")} (
|
{t("userProfile.header.yourSessions")} ({userProfile.sessions.length})
|
||||||
{webSocketContext.User.Sessions.length})
|
|
||||||
</Typography.Title>
|
</Typography.Title>
|
||||||
|
|
||||||
<Table
|
<Table
|
||||||
|
@ -442,7 +447,7 @@ export default function UserProfile() {
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{hasPermission(
|
{hasPermission(
|
||||||
webSocketContext.User.Permissions,
|
userProfile.Permissions,
|
||||||
Constants.PERMISSIONS.USER_PROFILE.API_KEYS
|
Constants.PERMISSIONS.USER_PROFILE.API_KEYS
|
||||||
) && (
|
) && (
|
||||||
<>
|
<>
|
||||||
|
@ -455,7 +460,7 @@ export default function UserProfile() {
|
||||||
>
|
>
|
||||||
<Typography.Title level={4}>
|
<Typography.Title level={4}>
|
||||||
{t("userProfile.header.yourApiKeys")} (
|
{t("userProfile.header.yourApiKeys")} (
|
||||||
{webSocketContext.User.ApiKeys.length}){" "}
|
{userProfile.apiKeys.length}){" "}
|
||||||
<Tooltip title={t("userProfile.icon.viewApiDoc")}>
|
<Tooltip title={t("userProfile.icon.viewApiDoc")}>
|
||||||
<Link
|
<Link
|
||||||
target="_blank"
|
target="_blank"
|
||||||
|
|
21
src/utils.js
21
src/utils.js
|
@ -130,6 +130,7 @@ export const Constants = {
|
||||||
INFO: 0,
|
INFO: 0,
|
||||||
ERROR: 1,
|
ERROR: 1,
|
||||||
},
|
},
|
||||||
|
LOADING: "loading...",
|
||||||
};
|
};
|
||||||
|
|
||||||
export const AppStyle = {
|
export const AppStyle = {
|
||||||
|
@ -224,7 +225,7 @@ let webSocketContextPreview = {
|
||||||
export const WebSocketContext = createContext(webSocketContextPreview);
|
export const WebSocketContext = createContext(webSocketContextPreview);
|
||||||
|
|
||||||
// commands received from the backend server
|
// commands received from the backend server
|
||||||
const ReceivedMessagesCommands = {
|
export const ReceivedMessagesCommands = {
|
||||||
InitUserSocketConnection: 1,
|
InitUserSocketConnection: 1,
|
||||||
UpdateConnectedUsers: 2,
|
UpdateConnectedUsers: 2,
|
||||||
NewGroupTaskStarted: 3,
|
NewGroupTaskStarted: 3,
|
||||||
|
@ -1272,27 +1273,31 @@ export function CapitalizeFirstLetter(string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function hasPermission(userPermissions, permission) {
|
export function hasPermission(userPermissions, permission) {
|
||||||
return userPermissions.includes(permission);
|
return true;
|
||||||
|
//return userPermissions.includes(permission);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function hasXYPermission(userPermissions, permission, xyValue) {
|
export function hasXYPermission(userPermissions, permission, xyValue) {
|
||||||
return userPermissions.includes(
|
return true;
|
||||||
|
/*return userPermissions.includes(
|
||||||
permission.replace("XY", xyValue.toLowerCase())
|
permission.replace("XY", xyValue.toLowerCase())
|
||||||
);
|
); */
|
||||||
}
|
}
|
||||||
|
|
||||||
export function hasOnePermission(userPermissions, ...permissions) {
|
export function hasOnePermission(userPermissions, ...permissions) {
|
||||||
for (const permission of permissions) {
|
return true;
|
||||||
|
/*for (const permission of permissions) {
|
||||||
if (userPermissions.includes(permission)) {
|
if (userPermissions.includes(permission)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false; */
|
||||||
}
|
}
|
||||||
|
|
||||||
export function hasOneXYPermission(userPermissions, xyValue, ...permissions) {
|
export function hasOneXYPermission(userPermissions, xyValue, ...permissions) {
|
||||||
for (const permission of permissions) {
|
return true;
|
||||||
|
/* for (const permission of permissions) {
|
||||||
if (
|
if (
|
||||||
userPermissions.includes(permission.replace("XY", xyValue.toLowerCase()))
|
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) {
|
export function EncodeStringToBase64(value) {
|
||||||
|
|
Loading…
Reference in New Issue