admin-dashboard-web/src/utils.js

1506 lines
45 KiB
JavaScript

import { Badge } from "antd";
import { useState } from "react";
import { Buffer } from "buffer";
import { v4 as uuidv4 } from "uuid";
/**
* constants
*/
const wssProtocol = window.location.protocol === "https:" ? "wss://" : "ws://";
let apiAddress = "";
let staticContentAddress = "";
let wsAddress = "";
let logApiAddress = "";
let roboticsApiAddress = "";
var roboticsSwaggerAddress = "";
var telegramBotManagerAddress = "";
var telegramBotManagerStaticContentAddress = "";
var crmLinkShareAddress = "";
if (window.location.hostname === "localhost" && window.location.port === "") {
// for docker container testing on localhost
apiAddress = "http://localhost/api/v1";
staticContentAddress = "http://localhost/api/";
wsAddress = "ws://localhost/ws";
logApiAddress = "http://localhost/lm/v1/log";
roboticsApiAddress = "http://localhost/rcm/v1";
roboticsSwaggerAddress = "http://localhost/rcm/swagger/index.html";
telegramBotManagerAddress = "http://localhost/tm/v1";
telegramBotManagerStaticContentAddress = "http://localhost/tm/";
crmLinkShareAddress = "http://localhost/crm/link/";
} else if (window.location.hostname === "localhost") {
// programming on localhost
apiAddress = "http://localhost:50050/v1";
staticContentAddress = "http://localhost:50050/";
wsAddress = "ws://localhost:50050/ws";
logApiAddress = "http://127.0.0.1:50110/v1/log";
roboticsApiAddress = "http://localhost:50055/v1";
roboticsSwaggerAddress = "http://localhost:50055/swagger/index.html";
telegramBotManagerAddress = "http://localhost:50056/v1";
telegramBotManagerStaticContentAddress = "http://localhost:50056/";
crmLinkShareAddress = "http://localhost:50050/v1/crm/link/";
/*} else if (window.location.hostname === "192.168.178.93") {
apiAddress = "http://192.168.178.93:50050/v1";
staticContentAddress = "http://192.168.178.93:50050/";
wsAddress = "ws://192.168.168.93:50050/ws"; */
} else {
// production
apiAddress = `${window.location.protocol}//${window.location.hostname}/api/v1`;
staticContentAddress = `${window.location.protocol}//${window.location.hostname}/api/`;
wsAddress = `${wssProtocol}${window.location.hostname}/ws`;
logApiAddress = `${window.location.protocol}//${window.location.hostname}/lm/v1/log`;
roboticsApiAddress = `${window.location.protocol}//${window.location.hostname}/rcm/v1`;
roboticsSwaggerAddress = `${window.location.protocol}//${window.location.hostname}/rcm/swagger/index.html`;
telegramBotManagerAddress = `${window.location.protocol}//${window.location.hostname}/tm/v1`;
telegramBotManagerStaticContentAddress = `${window.location.protocol}//${window.location.hostname}/tm/`;
crmLinkShareAddress = `${window.location.protocol}//${window.location.hostname}/api/v1/crm/link/`;
}
export const Constants = {
COLORS: {
PRIMARY: "#e67e22",
SECONDARY: "#9b59b6",
ICON_INFO: "#08c",
},
TEXT_EMPTY_PLACEHOLDER: "-/-",
/*API_ADDRESS: "http://localhost:50050/v1",
STATIC_CONTENT_ADDRESS: "http://localhost:50050/",
WS_ADDRESS: "ws://localhost:50050/ws", */
/*API_ADDRESS:
window.location.protocol + "//" + window.location.hostname + "/api/v1",
STATIC_CONTENT_ADDRESS:
window.location.protocol + "//" + window.location.hostname + "/api/",
WS_ADDRESS: `${wssProtocol}${window.location.hostname}/wsapi`,*/
API_ADDRESS: apiAddress,
STATIC_CONTENT_ADDRESS: staticContentAddress,
WS_ADDRESS: wsAddress,
LOG_API_ADDRESS: logApiAddress,
ROBOTICS_API_ADDRESS: roboticsApiAddress, // robot-control-manager
ROBOTICS_SWAGGER_ADDRESS: roboticsSwaggerAddress,
TELEGRAM_BOT_MANAGER_ADDRESS: telegramBotManagerAddress,
TELEGRAM_BOT_MANAGER_CONTENT_ADDRESS: telegramBotManagerStaticContentAddress,
CRM_LINK_SHARE_ADDRESS: crmLinkShareAddress,
ROUTE_PATHS: {
EQUIPMENT_DOCUMENTATION: "/equipment-documentation",
EQUIPMENT_DOCUMENTATION_VIEW: "/equipment-documentation/",
NO_GROUP_TASKS_AVAILABLE: "/group-tasks-no-available",
GROUP_TASKS: "/group-tasks/",
GROUP_TASKS_HISTORY: "/group-tasks-history",
USERS: "/users",
SCANNERS: "/scanners",
USER_PROFILE: "/user-profile",
ADMIN_AREA_ROLES: "/admin-area/roles",
ADMIN_AREA_LOGS: "/admin-area/logs",
ADMIN_AREA_MANAGE: "/admin-area/manage",
CONSOLES: "/consoles",
ROBOTICS_ROBOTS: "/robotics/robots",
CRM: "/crm/",
CRM_TEST: "/crm/test",
CUSTOMERFEEDBACK_VIEW: "/customer-feedback",
},
CRM_TYPE: {
TEST_CUSTOMERS: "test-customers",
CUSTOMERS: "customers",
DMC_PIPELINE: "dmc-pipeline",
SETTER_CLOSER: "setter-closer",
},
GROUP_TASKS_STATUS: {
FINISHED: 1,
RUNNING: 2,
CANCELED: 3,
FAILED: 4,
INPUT_REQUIRED: 5,
PAUSED: 6,
UNDO_ENDED: 7,
},
GLOBALS: {
MIN_USERNAME_LENGTH: 2,
MAX_USERNAME_LENGTH: 20,
MIN_PASSWORD_LENGTH: 6,
MAX_PASSWORD_LENGTH: 64,
MIN_ROLE_DISPLAY_NAME: 3,
MAX_ROLE_DISPLAY_NAME: 30,
MAX_ROLE_DESCRIPTION: 80,
MAX_EQUIPMENT_DOCUMENTATION_TITLE_LENGTH: 60,
MAX_EQUIPMENT_DOCUMENTATION_NOTE_LENGTH: 2000,
EQUIPMENT_DOCUMENTATIONS_PAGINATION_LIMIT: 3,
GROUP_TASKS_PAGINATION_LIMIT: 5,
NOTIFICATIONS_PAGINATION_LIMIT: 10,
MIN_LOG_MANAGER_DISPLAY_NAME_LENGTH: 2,
MAX_LOG_MANAGER_DISPLAY_NAME_LENGTH: 16,
MIN_LOG_MANAGER_ADDRESS_LENGTH: 3,
MAX_LOG_MANAGER_ADDRESS_LENGTH: 100,
MIN_ROBOTICS_ROBOT_NAME_LENGTH: 2,
MAX_ROBOTICS_ROBOT_NAME_LENGTH: 30,
MIN_USER_API_KEY_NAME_LENGTH: 2,
MAX_USER_API_KEY_NAME_LENGTH: 30,
ROBOTICS_ROBOTS_PAGINATION_LIMIT: 5,
ROBOTICS_UNAUTHORIZED_PAGINATION_LIMIT: 5,
TELEGRAM_VERIFY_CODE_EXPIRATION_TIME: 10 * 60 * 1000, // 10 minutes
},
MAX_AVATAR_SIZE: 5 * 1024 * 1024,
ACCEPTED_AVATAR_FILE_TYPES: [
"image/png",
"image/jpeg",
"image/jpg",
"image/gif",
],
ACCEPTED_EQUIPMENT_DOCUMENTATION_FILE_TYPES: [
"image/png",
"image/jpeg",
"image/jpg",
],
PERMISSIONS: {
EQUIPMENT_DOCUMENTATION: {
VIEW: "equipment_documentation.view",
CREATE: "equipment_documentation.create",
EDIT: "equipment_documentation.edit",
},
GROUP_TASKS: {
OVERVIEW: {
XYNewTask: "group_tasks.overview.XY.new_task",
XYReloadGroupConfig: "group_tasks.overview.XY.reload_group_config",
XYInstallPythonPackages:
"group_tasks.overview.XY.install_python_packages",
XYView: "group_tasks.overview.XY.view",
},
HISTORY: "group_tasks.history",
INSTALL_GLOBAL_PYTHON_PACKAGES:
"group_tasks.install_global_python_packages",
},
ALL_USERS: {
CREATE_NEW_USER: "all_users.create_new_user",
ACTION: {
CHANGE_ROLE: "all_users.action.change_role",
DELETE_USER: "all_users.action.delete_user",
USER_DEACTIVATION: "all_users.action.user_deactivation",
},
},
ADMIN_AREA: {
ROLES: {
CREATE_NEW_ROLE: "admin_area.roles.create_new_role",
UPDATE_ROLE: "admin_area.roles.update_role",
DELETE_ROLE: "admin_area.roles.delete_role",
MOVE_ROLE_UP_DOWN: "admin_area.roles.move_role_up_down",
},
LOGS: "admin_area.logs",
MANAGE: {
CHECK_WHICH_CATEGORIES_ARE_AVAILABLE:
"admin_area.manage.check_which_categories_are_available",
ADD_LOG_MANAGER_SERVER_CONNECTION:
"admin_area.manage.add_log_manager_server_connection",
REMOVE_LOG_MANAGER_SERVER_CONNECTION:
"admin_area.manage.remove_log_manager_server_connection",
},
},
USER_PROFILE: {
API_KEYS: "user_profile.api_keys",
},
CONSOLES: {
VIEW: "consoles.view",
},
ROBOTICS: {
ROBOTS: {
VIEW: "robotics.robots.view",
VIEW_ROBOTS_ADDRESSES: "robotics.robots.view_robots_addresses",
FREE_UP_JOB: "robotics.robots.free_up_job",
EDIT_ROBOT_NAME: "robotics.robots.edit_robot_name",
DISCONNECT_ROBOT: "robotics.robots.disconnect_robot",
ENABLE_PERMIT_JOIN: "robotics.robots.enable_permit_join",
AUTHORIZE_DENY_UNAUTHORIZED_ROBOTS:
"robotics.robots.authorize_deny_unauthorized_robots",
VIEW_SWAGGER_DOCUMENTATION:
"robotics.robots.view_swagger_documentation",
},
},
CRM: {
CUSTOMERS: {
VIEW: "crm.customers.view",
},
DMC_PIPELINE: {
VIEW: "crm.dmc_pipeline.view",
},
SETTER_CLOSER: {
VIEW: "crm.setter_closer.view",
},
},
CUSTOMERFEEDBACK: {
VIEW: "customerfeedback.view",
},
},
SYSTEM_LOG_TYPE: {
INFO: 0,
ERROR: 1,
},
LOADING: "loading...",
};
export const AppStyle = {
app: {
margin: 12,
borderRadius: 12,
primary: "#4096ff",
},
typography: {
text: {
marginBottom: 6,
},
},
grid: {
row: {
gutter: [16, 16],
},
},
};
export function GetUuid() {
return uuidv4();
}
/**
* user session
*/
export function UseUserSession() {
const getUserSession = () => {
return getUserSessionFromLocalStorage();
};
const [userSession, setUserSession] = useState(getUserSession());
const saveUserSession = (session) => {
setUserSession(session);
if (session === undefined) {
localStorage.removeItem("session");
} else {
setUserSessionToLocalStorage(session);
}
};
return {
setUserSession: saveUserSession,
userSession,
};
}
export function getUserSessionFromLocalStorage() {
return localStorage.getItem("session");
}
export function setUserSessionToLocalStorage(session) {
localStorage.setItem("session", session);
}
// needed for a user who uses multiple tabs in the browser
// with the same session id because otherwise the last browser
// tab would subscribe to the topic and the other tabs would
// not receive any messages
// used for topic subscribtion and grouptasks
export const BrowserTabSession = GetUuid();
export const wsConnectionCustomEventName = "wsConnection";
// used for sideMenu
export const BreakpointLgWidth = 992;
/**
* websocket
*/
//let l = "loading...";
/*
let webSocketContextPreview = {
User: {
Id: "",
Username: l,
Email: l,
Sessions: [],
Permissions: [],
RoleId: "",
ApiKeys: [],
},
AllUsers: [],
AllRoles: [],
ConnectionBadgeStatus: "error",
ConnectedWebSocketUsersCount: 0,
CategoryGroups: [],
GroupTasks: [],
GroupTasksSteps: [],
Scanners: [],
UserProfileStateUsername: l,
UserProfileStateEmail: l,
AdminAreaRolesPermissions: [],
}; */
//export const WebSocketContext = createContext(webSocketContextPreview);
/*
// commands received from the backend server
export const ReceivedMessagesCommands = {
InitUserSocketConnection: 1,
UpdateConnectedUsers: 2,
NewGroupTaskStarted: 3,
NewGroupTaskStep: 4,
UpdateGroupTaskStep: 5,
UpdateGroupTask: 6,
ReloadingGroupTasks: 7,
GroupTasksReloaded: 8,
UpdateUserSessions: 9,
UpdateAllUsersUserAvatar: 10,
NewScanner: 11,
DeleteScanner: 12,
UpdateScannerUsedByUserId: 13,
ScanResult: 14,
UpdateScannerLastUsed: 15,
TaskLocked: 16,
TaskUnlocked: 17,
UserProfileUpdated: 18,
AdminAreaNewRoleCreated: 19,
AdminAreaRoleUpdated: 20,
AdminAreaUpdateRoleSortingOrder: 21,
AdminAreaRoleDeleted: 22,
AllUsersUserRoleUpdated: 23,
RolePermissionsUpdated: 24,
ErrorNoPermissions: 25,
AllUsersNewUserCreated: 26,
AllUsersUserDeleted: 27,
AllUsersUserDeactivation: 28,
GroupTasksCategoryGroupChanges: 29,
NewUserApiKeyCreated: 30,
DeletedUserApiKey: 31,
NewApiKeyUsageCount: 32,
InstallingPythonPackages: 33,
InstallingPythonPackagesFailed: 34,
InstallingPythonPackagesFinished: 35,
InstallingGlobalPythonPackages: 36,
InstallingGlobalPythonPackagesFailed: 37,
InstallingGlobalPythonPackagesFinished: 38,
};
// commands sent to the backend server
export const SentMessagesCommands = {
StartGroupTasks: 1,
TaskFailedTryAgainRunTaskStep: 2,
TaskContinueTaskStep: 3,
ReloadGroupTasks: 4,
TaskLocking: 5,
UpdateUserProfile: 6,
AdminAreaCreateNewRole: 7,
AdminAreaUpdateRole: 8,
AdminAreaUpdateRoleSortingOrder: 9,
AdminAreaDeleteRole: 10,
AllUsersUpdateUserRole: 11,
AllUsersCreateNewUser: 12,
AllUsersDeleteUser: 13,
AllUsersUserDeactivation: 14,
ScannersUseScanners: 15,
ScannersDisconnectScanner: 16,
GroupTasksCheckingForCategoryGroupChanges: 17,
HandleUserActionTaskStep: 18,
CreateNewUserApiKey: 19,
DeleteUserApiKey: 20,
GroupTasksInstallPythonPackages: 21,
GroupTasksInstallGlobalPythonPackages: 22,
}; */
/*
export function WebSocketProvider({
children,
userSession,
setUserSession,
notificationApi,
isReady,
setIsReady,
}) {
//const [isReady, setIsReady] = useState(false);
const [connectionBadgeStatus, setConnectionBadgeStatus] = useState(
webSocketContextPreview.ConnectionBadgeStatus
);
const [connectedWebSocketUsersCount, setConnectedWebSocketUsersCount] =
useState(0);
const [user, setUser] = useState(webSocketContextPreview.User);
const [allUsers, setAllUsers] = useState(webSocketContextPreview.AllUsers);
const [allRoles, setAllRoles] = useState(webSocketContextPreview.AllRoles);
const [categoryGroups, setCategoryGroups] = useState(
webSocketContextPreview.CategoryGroups
);
// these are all group tasks that are then filtered and displayed in the respective tables for the category
const [groupTasks, setGroupTasks] = useState([]);
const [groupTasksSteps, setGroupTasksSteps] = useState([]);
const [scanners, setScanners] = useState([]);
const navigate = useNavigate();
const StartGroupTasksOpenModalRememberIdRef = useRef(null);
const [userProfileStateUsername, setUserProfileStateUsername] = useState(
webSocketContextPreview.UserProfileStateUsername
);
const [userProfileStateEmail, setUserProfileStateEmail] = useState(
webSocketContextPreview.UserProfileStateEmail
);
const [adminAreaRolesPermissions, setAdminAreaRolesPermissions] = useState(
webSocketContextPreview.AdminAreaRolesPermissions
);
const ws = useRef(null);
const connect = () => {
ws.current = new WebSocket(Constants.WS_ADDRESS + "?auth=" + userSession);
ws.current.onopen = () => {
console.log("connected");
setConnectionBadgeStatus("success");
setIsReady(true);
};
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.InitUserSocketConnection:
if (body.User.Permissions === null) {
body.User.Permissions = [];
}
setUser(body.User);
setUserProfileStateEmail(body.User.Email);
setUserProfileStateUsername(body.User.Username);
setAllUsers(body.AllUsers);
setAllRoles(body.AllRoles);
if (body.CategoryGroups === null) {
body.CategoryGroups = [];
}
setCategoryGroups(body.CategoryGroups);
setGroupTasks(body.GroupTasks);
setGroupTasksSteps(body.GroupTasksSteps);
if (body.Scanners !== null) setScanners(body.Scanners);
if (body.AdminArea.RolesPermissions !== null)
setAdminAreaRolesPermissions(body.AdminArea.RolesPermissions);
localStorage.setItem("userId", body.User.Id);
break;
case ReceivedMessagesCommands.UpdateConnectedUsers:
setConnectedWebSocketUsersCount(body.WebSocketUsersCount);
setAllUsers((arr) => {
const newArr = [...arr];
const arrIndex = arr.findIndex((arr1) => arr1.Id === body.UserId);
if (arrIndex !== -1) {
newArr[arrIndex].ConnectionStatus = body.ConnectionStatus;
newArr[arrIndex].LastOnline = body.LastOnline;
}
return newArr;
});
break;
case ReceivedMessagesCommands.NewGroupTaskStarted:
setGroupTasks((arr) => [...arr, body]);
if (
body.RememberId === StartGroupTasksOpenModalRememberIdRef.current
) {
navigate(`${Constants.ROUTE_PATHS.GROUP_TASKS}/${body.Id}`);
}
break;
case ReceivedMessagesCommands.NewGroupTaskStep:
setGroupTasksSteps((arr) => [...arr, body]);
scrollToNextStep(body.GroupTasksId, body.Step);
break;
case ReceivedMessagesCommands.UpdateGroupTaskStep:
setGroupTasksSteps((arr) => {
const newArr = [...arr];
newArr[arr.findIndex((arr1) => arr1.Id === body.Id)] = body;
return newArr;
});
scrollToNextStep(body.GroupTasksId, body.Step);
break;
case ReceivedMessagesCommands.UpdateGroupTask:
setGroupTasks((arr) => {
const newArr = [...arr];
newArr[arr.findIndex((arr1) => arr1.Id === body.Id)] = body;
return newArr;
});
break;
case ReceivedMessagesCommands.ReloadingGroupTasks:
notificationApi["warning"]({
message: `Group ${body} is reloading`,
duration: 2,
});
break;
case ReceivedMessagesCommands.GroupTasksReloaded:
if (body.RemovedCategory !== undefined) {
setCategoryGroups((arr) =>
arr.filter((arr1) => arr1.category !== body.RemovedCategory)
);
setUser((user) => {
const updatedUser = { ...user };
updatedUser.Permissions = updatedUser.Permissions.filter(
(arr) => !body.RemovedPermissions.includes(arr)
);
return updatedUser;
});
setAdminAreaRolesPermissions((arr) => {
const newArr = [...arr];
newArr.forEach((role, i) => {
if (role.Permissions !== null) {
newArr[i].Permissions = role.Permissions.filter(
(arr) => !body.RemovedPermissions.includes(arr)
);
}
});
return newArr;
});
notificationApi["info"]({
message: `Category ${body.RemovedCategory} was removed`,
duration: 2,
});
break;
}
setCategoryGroups((arr) => {
const newArr = [...arr];
newArr[
arr.findIndex((arr1) => arr1.category === body.Category)
].groups = body.CategoryGroups;
return newArr;
});
break;
case ReceivedMessagesCommands.UpdateUserSessions:
setUser((arr) => ({ ...arr, Sessions: body }));
break;
case ReceivedMessagesCommands.UpdateAllUsersUserAvatar:
setAllUsers((arr) => {
const newArr = [...arr];
newArr[arr.findIndex((arr1) => arr1.Id === body.UserId)].Avatar =
body.Avatar;
return newArr;
});
break;
case ReceivedMessagesCommands.NewScanner:
setScanners((arr) => [...arr, body]);
break;
case ReceivedMessagesCommands.DeleteScanner:
setScanners((arr) => arr.filter((arr) => arr.Id !== body.Id));
break;
case ReceivedMessagesCommands.UpdateScannerUsedByUserId:
setScanners((arr) => {
const newArr = [...arr];
newArr[
arr.findIndex((arr1) => arr1.Id === body.ScannerId)
].UsedByUserId = body.UsedByUserId;
return newArr;
});
break;
case ReceivedMessagesCommands.ScanResult:
const decodedScanResult = DecodedBase64ToString(body);
if (decodedScanResult === "" || decodedScanResult === null) {
notificationApi["error"]({
message: `Failed to decode scan result`,
description: "See in developer console",
});
console.error(
"Received scan result: ",
body,
"Decoded result: ",
decodedScanResult
);
break;
}
notificationApi["info"]({
message: `Scan Result`,
description: decodedScanResult,
});
new Audio(
`${Constants.STATIC_CONTENT_ADDRESS}sounds/scan_result.mp3`
).play();
break;
case ReceivedMessagesCommands.UpdateScannerLastUsed:
setScanners((arr) => {
const newArr = [...arr];
newArr[
arr.findIndex((arr1) => arr1.Id === body.ScannerId)
].LastUsed = body.LastUsed;
return newArr;
});
break;
case ReceivedMessagesCommands.TaskLocked:
if (
body.rememberId ===
GroupTasksStepsLockedAndUserUpdateInputValueRememberId
)
break;
setGroupTasksSteps((arr) => {
const newArr = [...arr];
newArr[
arr.findIndex(
(arr1) =>
arr1.GroupTasksId === body.groupTaskId &&
arr1.Step === body.step
)
].LockedByUserId = body.lockedByUserId;
return newArr;
});
// update input value
// html based DOM manipulation
const foundInput = document.getElementById(body.element);
if (foundInput) {
// this timeout is needed because the previous useState for the lockedByUserId takes some milliseconds to complete
setTimeout(() => setNativeValue(foundInput, body.value), 50);
}
// update group task step as html based DOM manipulation only works if user has no other modal open
setGroupTasksSteps((arr) => {
const newArr = [...arr];
const stepIndex = arr.findIndex(
(arr1) =>
arr1.GroupTasksId === body.groupTaskId &&
arr1.Step === body.step
);
if (stepIndex === -1) return newArr;
let inputs = [];
if (newArr[stepIndex].Inputs !== "") {
inputs = JSON.parse(newArr[stepIndex].Inputs);
}
let parameterFound = false;
for (let i = 0; i < inputs.length; i++) {
if (inputs[i].parameterName === body.parameterName) {
inputs[i].value = body.value;
parameterFound = true;
break;
}
}
if (!parameterFound) {
let obj = {};
obj["parameterName"] = body.parameterName;
obj["value"] = body.value;
inputs.push(obj);
}
newArr[stepIndex].Inputs = JSON.stringify(inputs);
return newArr;
});
break;
case ReceivedMessagesCommands.TaskUnlocked:
if (
body.rememberId ===
GroupTasksStepsLockedAndUserUpdateInputValueRememberId
)
break;
setGroupTasksSteps((arr) => {
const newArr = [...arr];
newArr[
arr.findIndex(
(arr1) =>
arr1.GroupTasksId === body.GroupTaskId &&
arr1.Step === body.Step
)
].LockedByUserId = "";
return newArr;
});
break;
case ReceivedMessagesCommands.UserProfileUpdated:
// feedback message for the user who has changed his profile
if (body.Result !== undefined) {
if (body.Result === 0) {
notificationApi["error"]({
message: `Profile couldn't be updated`,
description: "Username already in use",
});
} else if (body.Result === 1) {
notificationApi["error"]({
message: `Profile couldn't be updated`,
description: "Email already in use",
});
} else if (body.Result === 2) {
notificationApi["error"]({
message: `Profile couldn't be updated`,
description: "Provided password is incorrect",
});
}
}
if (body.Changes !== undefined) {
setUser((user) => {
const updatedUser = { ...user };
if (user.Id === body.UserId) {
if (body.Changes.Username !== undefined) {
updatedUser.Username = body.Changes.Username;
setUserProfileStateUsername(body.Changes.Username);
}
if (body.Changes.Email !== undefined) {
updatedUser.Email = body.Changes.Email;
setUserProfileStateEmail(body.Changes.Email);
}
}
return updatedUser;
});
if (body.Changes.Username !== undefined) {
setAllUsers((arr) => {
const newArr = [...arr];
newArr[
arr.findIndex((arr1) => arr1.Id === body.UserId)
].Username = body.Changes.Username;
return newArr;
});
}
}
break;
case ReceivedMessagesCommands.AdminAreaNewRoleCreated:
setAllRoles((arr) => [...arr, body]);
setAdminAreaRolesPermissions((arr) => [
...arr,
{ RoleId: body.Id, Permissions: [] },
]);
break;
case ReceivedMessagesCommands.AdminAreaRoleUpdated:
setAllRoles((arr) => {
const newArr = [...arr];
const arrIndex = arr.findIndex((arr1) => arr1.Id === body.RoleId);
if (body.Changes.DisplayName !== undefined) {
newArr[arrIndex].DisplayName = body.Changes.DisplayName;
}
if (body.Changes.Description !== undefined) {
newArr[arrIndex].Description = body.Changes.Description;
}
return newArr;
});
if (
body.Changes.AddedPermissions !== undefined ||
body.Changes.RemovedPermissions !== undefined
) {
setAdminAreaRolesPermissions((arr) => {
const newArr = [...arr];
const roleIndex = arr.findIndex(
(item) => item.RoleId === body.RoleId
);
if (body.Changes.AddedPermissions !== undefined) {
if (newArr[roleIndex].Permissions === null) {
newArr[roleIndex].Permissions = body.Changes.AddedPermissions;
} else {
newArr[roleIndex].Permissions = newArr[
roleIndex
].Permissions.concat(body.Changes.AddedPermissions);
}
}
if (body.Changes.RemovedPermissions !== undefined) {
newArr[roleIndex].Permissions = newArr[
roleIndex
].Permissions.filter(
(permission) =>
!body.Changes.RemovedPermissions.includes(permission)
);
}
return newArr;
});
}
if (body.Result !== undefined) {
if (body.Result.DisplayName !== undefined) {
if (body.Result.DisplayName === 1) {
notificationApi["error"]({
message: `Display name could be changed`,
description: `Display name already in use`,
});
}
}
}
break;
case ReceivedMessagesCommands.AdminAreaUpdateRoleSortingOrder:
setAllRoles((arr) => {
const newArr = [...arr];
const updatedRoleIndex = newArr.findIndex(
(role) => role.Id === body.RoleId
);
const currentSortingOrder = newArr[updatedRoleIndex].SortingOrder;
if (body.Direction === 0) {
newArr[updatedRoleIndex].SortingOrder =
newArr[updatedRoleIndex].SortingOrder - 1;
} else {
newArr[updatedRoleIndex].SortingOrder =
newArr[updatedRoleIndex].SortingOrder + 1;
}
const newSortingOrder = newArr[updatedRoleIndex].SortingOrder;
for (let i = 0; i < newArr.length; i++) {
if (newArr[i].Id !== newArr[updatedRoleIndex].Id) {
if (newArr[i].SortingOrder === newSortingOrder) {
newArr[i].SortingOrder = currentSortingOrder;
} else if (
newArr[i].SortingOrder < currentSortingOrder &&
newArr[i].SortingOrder >= newSortingOrder
) {
newArr[i].SortingOrder = newArr[i].SortingOrder + 1;
} else if (
newArr[i].SortingOrder > currentSortingOrder &&
newArr[i].SortingOrder <= newSortingOrder
) {
newArr[i].SortingOrder = newArr[i] - 1;
}
}
}
newArr.sort((a, b) => a.SortingOrder - b.SortingOrder);
return newArr;
});
break;
case ReceivedMessagesCommands.AdminAreaRoleDeleted:
setAllRoles((arr) => {
let newArr = [...arr];
const deletedRole = newArr.find((r) => r.Id === body.RoleId);
newArr = newArr.filter((role) => role.Id !== body.RoleId);
for (let i = 0; i < newArr.length; i++) {
if (newArr[i].SortingOrder > deletedRole.SortingOrder) {
newArr[i].SortingOrder = newArr[i].SortingOrder - 1;
}
}
return newArr;
});
setAdminAreaRolesPermissions((arr) => {
let newArr = [...arr];
newArr = newArr.filter(
(rolePermission) => rolePermission.RoleId !== body.RoleId
);
return newArr;
});
break;
case ReceivedMessagesCommands.AllUsersUserRoleUpdated:
setAllUsers((arr) => {
const newArr = [...arr];
newArr[newArr.findIndex((user) => user.Id === body.UserId)].RoleId =
body.RoleId;
return newArr;
});
if (body.Permissions !== undefined) {
setUser((user) => {
const updatedUser = { ...user };
if (body.Permissions === null) {
updatedUser.Permissions = [];
} else {
updatedUser.Permissions = body.Permissions;
}
return updatedUser;
});
}
break;
case ReceivedMessagesCommands.RolePermissionsUpdated:
if (
body.AddedPermissions !== undefined ||
body.RemovedPermissions !== undefined
) {
setUser((user) => {
const updatedUser = { ...user };
if (body.AddedPermissions !== undefined) {
updatedUser.Permissions = updatedUser.Permissions.concat(
body.AddedPermissions
);
}
if (body.RemovedPermissions !== undefined) {
updatedUser.Permissions = updatedUser.Permissions.filter(
(permission) => !body.RemovedPermissions.includes(permission)
);
}
return updatedUser;
});
}
break;
case ReceivedMessagesCommands.ErrorNoPermissions:
notificationApi["error"]({
message: `No permissions`,
description: `Please contact the administrator`,
});
break;
case ReceivedMessagesCommands.AllUsersNewUserCreated:
if (body.Result !== undefined) {
if (body.Result === 0) {
notificationApi["error"]({
message: `User could not be created`,
description: `Username already in use`,
});
}
if (body.Result === 1) {
notificationApi["error"]({
message: `User could not be created`,
description: `Email already in use`,
});
}
break;
}
setAllUsers((arr) => [
...arr,
{
Id: body.Id,
RoleId: body.RoleId,
Username: body.Username,
ConnectionStatus: body.ConnectionStatus,
Deactivated: body.Deactivated,
},
]);
break;
case ReceivedMessagesCommands.AllUsersUserDeleted:
setAllUsers((arr) => {
let newArr = [...arr];
newArr = newArr.filter((user) => user.Id !== body.UserId);
return newArr;
});
if (body.ScannerId !== "") {
setScanners((arr) => {
let newArr = [...arr];
newArr[
newArr.findIndex((scanner) => scanner.Id === body.ScannerId)
].UsedByUserId = "";
return newArr;
});
}
break;
case ReceivedMessagesCommands.AllUsersUserDeactivation:
setAllUsers((arr) => {
let newArr = [...arr];
newArr[
newArr.findIndex((user) => user.Id === body.UserId)
].Deactivated = body.Deactivated;
return newArr;
});
break;
case ReceivedMessagesCommands.GroupTasksCategoryGroupChanges:
if (
body["AddedPermissions"] !== undefined ||
body["RemovedPermissions"] !== undefined
) {
setUser((user) => {
const updatedUser = { ...user };
if (
body.AddedPermissions !== undefined &&
updatedUser.RoleId === body.MasterRoleId
) {
updatedUser.Permissions = updatedUser.Permissions.concat(
body.AddedPermissions
);
}
if (body.RemovedPermissions !== undefined) {
updatedUser.Permissions = updatedUser.Permissions.filter(
(permission) => !body.RemovedPermissions.includes(permission)
);
}
return updatedUser;
});
setAdminAreaRolesPermissions((arr) => {
let newArr = [...arr];
const roleIndex = arr.findIndex(
(item) => item.RoleId === body.MasterRoleId
);
if (roleIndex !== -1) {
if (body.AddedPermissions !== undefined) {
newArr[roleIndex].Permissions = newArr[
roleIndex
].Permissions.concat(body.AddedPermissions);
}
if (body.RemovedPermissions !== undefined) {
newArr[roleIndex].Permissions = newArr[
roleIndex
].Permissions.filter(
(permission) =>
!body.RemovedPermissions.includes(permission)
);
}
}
return newArr;
});
}
if (
body["AddedCategoryGroups"] !== undefined ||
body["RemovedCategoryGroups"] !== undefined
) {
setCategoryGroups((arr) => {
let newArr = [...arr];
if (body["RemovedCategoryGroups"] !== undefined) {
newArr = newArr.filter(
(c) => !body.RemovedCategoryGroups.includes(c.category)
);
}
if (body["AddedCategoryGroups"] !== undefined) {
newArr = newArr.concat(body.AddedCategoryGroups);
}
newArr = newArr.sort((a, b) => {
if (a.category < b.category) {
return -1; // a below b
} else if (a.category > b.category) {
return 1; // a above b
} else {
return 0; // keep the order
}
});
return newArr;
});
}
break;
case ReceivedMessagesCommands.NewUserApiKeyCreated:
setUser((user) => {
const updatedUser = { ...user };
updatedUser.ApiKeys.push(body);
return updatedUser;
});
break;
case ReceivedMessagesCommands.DeletedUserApiKey:
setUser((user) => {
const updatedUser = { ...user };
updatedUser.ApiKeys = updatedUser.ApiKeys.filter(
(apiKey) => apiKey.Id !== body
);
return updatedUser;
});
break;
case ReceivedMessagesCommands.NewApiKeyUsageCount:
setUser((user) => {
const updatedUser = { ...user };
const foundIndex = updatedUser.ApiKeys.findIndex(
(apiKey) => apiKey.Id === body.Id
);
if (foundIndex !== -1) {
updatedUser.ApiKeys[foundIndex].UsageCount = body.UsageCount;
updatedUser.ApiKeys[foundIndex].LastUsed = body.LastUsed;
}
return updatedUser;
});
break;
case ReceivedMessagesCommands.InstallingPythonPackages:
notificationApi["info"]({
message: `Installing python packages for ${body.GroupId} of ${body.Category}`,
description: `This may take a while`,
});
break;
case ReceivedMessagesCommands.InstallingPythonPackagesFailed:
notificationApi["error"]({
message: `Installing python packages for ${body.GroupId} of ${body.Category} failed`,
description: `Please check the logs`,
});
break;
case ReceivedMessagesCommands.InstallingPythonPackagesFinished:
notificationApi["success"]({
message: `Installing python packages for ${body.GroupId} of ${body.Category} finished`,
description: `You can now start the group task`,
});
break;
case ReceivedMessagesCommands.InstallingGlobalPythonPackages:
notificationApi["info"]({
message: `Installing global python packages`,
description: `This may take a while`,
});
break;
case ReceivedMessagesCommands.InstallingGlobalPythonPackagesFailed:
notificationApi["error"]({
message: `Installing global python packages failed`,
description: `Please check the logs`,
});
break;
case ReceivedMessagesCommands.InstallingGlobalPythonPackagesFinished:
notificationApi["success"]({
message: `Installing global python packages finished`,
description: `You can now continue with the work`,
});
break;
default:
console.error("unknown command", cmd);
break;
}
};
ws.current.onclose = (event) => {
setIsReady(false);
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);
};
};
useEffect(() => {
connect();
return () => ws.current.close();
}, []);
const SendSocketMessage = (cmd, body) => {
if (isReady) {
ws.current.send(JSON.stringify({ Cmd: cmd, Body: body }));
} else {
notificationApi["error"]({
message: `Websocket is not ready`,
description: `Please check your internet connection`,
});
}
};
return (
<WebSocketContext.Provider
value={{
ConnectionBadgeStatus: connectionBadgeStatus,
ConnectedWebSocketUsersCount: connectedWebSocketUsersCount,
CategoryGroups: categoryGroups,
GroupTasks: groupTasks,
User: user,
AllUsers: allUsers,
AllRoles: allRoles,
Scanners: scanners,
SendSocketMessage: SendSocketMessage,
GroupTasksSteps: groupTasksSteps,
setGroupTasksSteps: setGroupTasksSteps,
StartGroupTasksOpenModalRememberIdRef:
StartGroupTasksOpenModalRememberIdRef,
UserProfileStateUsername: userProfileStateUsername,
setUserProfileStateUsername: setUserProfileStateUsername,
UserProfileStateEmail: userProfileStateEmail,
setUserProfileStateEmail: setUserProfileStateEmail,
AdminAreaRolesPermissions: adminAreaRolesPermissions,
}}
>
{children}
</WebSocketContext.Provider>
);
} */
/*
function scrollToNextStep(groupTaskId, step) {
setTimeout(
() =>
document
.getElementById(`${groupTaskId}-scroll-${step - 1}`)
?.scrollIntoView({ behavior: "smooth" }),
200
);
} */
export function FormatDatetime(datetime) {
if (datetime === undefined || datetime === "0001-01-01T00:00:00Z") {
return Constants.TEXT_EMPTY_PLACEHOLDER;
}
const date = new Date(datetime);
const day = String(date.getDate()).padStart(2, "0");
const month = String(date.getMonth() + 1).padStart(2, "0");
const year = date.getFullYear();
const hours = String(date.getHours()).padStart(2, "0");
const minutes = String(date.getMinutes()).padStart(2, "0");
const seconds = String(date.getSeconds()).padStart(2, "0");
return `${day}.${month}.${year} ${hours}:${minutes}:${seconds}`;
}
export function GetDuration(startTime, endTime) {
if (endTime === "0001-01-01T00:00:00Z") {
return Constants.TEXT_EMPTY_PLACEHOLDER;
}
const diff = Math.abs(new Date(startTime) - new Date(endTime));
if (diff === 0) {
return "0ms";
}
const milliseconds = diff % 1000;
const seconds = Math.floor(diff / 1000);
const minutes = Math.floor(seconds / 60);
const hours = Math.floor(minutes / 60);
const days = Math.floor(hours / 24);
let result = "";
if (days > 0) {
result += days + "d ";
}
if (hours > 0) {
result += (hours % 24) + "h ";
}
if (minutes > 0) {
result += (minutes % 60) + "m ";
}
if (seconds > 0) {
result += (seconds % 60) + "s ";
}
if (milliseconds > 0) {
result += milliseconds + "ms";
}
return result.trim();
}
export function getConnectionStatusItem(connectionStatus) {
return connectionStatus === 0 ? (
<Badge status="error" text="Offline" />
) : (
<Badge status="success" text="Online" />
);
}
/*
export function getUserId() {
return localStorage.getItem("userId");
} */
const emailRegex =
/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
export function isEmailValid(email) {
return emailRegex.test(email);
}
export function CapitalizeFirstLetter(string) {
return string.charAt(0).toUpperCase() + string.slice(1);
}
export function hasPermission(userPermissions, permission) {
if (userPermissions === null) return false;
return userPermissions.includes(permission);
}
export function hasXYPermission(userPermissions, permission, xyValue) {
if (userPermissions === null) return false;
return userPermissions.includes(
permission.replace("XY", xyValue.toLowerCase())
);
}
export function hasOnePermission(userPermissions, ...permissions) {
if (userPermissions === null) return false;
for (const permission of permissions) {
if (userPermissions.includes(permission)) {
return true;
}
}
return false;
}
export function hasOneXYPermission(userPermissions, xyValue, ...permissions) {
for (const permission of permissions) {
if (
userPermissions.includes(permission.replace("XY", xyValue.toLowerCase()))
) {
return true;
}
}
return false;
}
export function EncodeStringToBase64(value) {
return Buffer.from(value).toString("base64");
}
export function DecodedBase64ToString(value) {
return Buffer.from(value, "base64").toString();
}
export const myFetchContentType = {
JSON: 0,
MULTIPART_FORM_DATA: 1,
};
export function myFetch(
url,
method,
body = null,
headers = {},
contentType = myFetchContentType.JSON,
fetchUrl = Constants.API_ADDRESS,
ignoreUnauthorized = false
) {
const getContentType = () => {
if (contentType === myFetchContentType.JSON) return "application/json";
return "multipart/form-data";
};
const getBody = () => {
if (!body) return null;
if (contentType === myFetchContentType.JSON) return JSON.stringify(body);
return body;
};
const requestOptions = {
method: method,
headers: {
"X-Authorization": getUserSessionFromLocalStorage(),
"Content-Type": getContentType(),
...headers,
},
body: getBody(),
};
if (fetchUrl === "") {
fetchUrl = Constants.API_ADDRESS;
}
return fetch(`${fetchUrl}${url}`, requestOptions)
.then((response) => {
// if status is not in range 200-299
if (!response.ok) {
if (!ignoreUnauthorized && response.status === 401) {
setUserSessionToLocalStorage("");
window.location.href = "/";
}
throw response.status;
}
// check if response is json
if (response.headers.get("content-type")?.includes("application/json")) {
return response.json();
}
return response.text();
})
.catch((error) => {
throw error;
});
}
export function showUnkownErrorNotification(notificationApi, t) {
notificationApi["error"]({
message: t("common.request.unknownError.title"),
description: t("common.request.unknownError.description"),
});
}
export function showInputsInvalidNotification(notificationApi, t) {
notificationApi["warning"]({
message: t("common.request.inputsInvalid.title"),
description: t("common.request.inputsInvalid.description"),
});
}