import React, { useEffect, useRef, useState, useContext, useCallback, useMemo, memo } from "react";
import {
ExpandLess as ExpandLessIcon,
ExpandMore as ExpandMoreIcon,
Toc as TocIcon,
Settings as SettingsIcon,
Business as BusinessIcon,
HelpOutline as HelpOutlineIcon,
MeetingRoom as MeetingRoomIcon,
Search as SearchIcon,
Add as AddIcon
} from "@mui/icons-material";
import LightModeIcon from '@mui/icons-material/LightMode';
import DarkModeIcon from '@mui/icons-material/DarkMode';
import MonitorIcon from '@mui/icons-material/Monitor';
import SearchBox from "./SearchData.jsx";
import {
Button,
Typography,
Autocomplete,
TextField,
Popper,
Avatar,
Menu,
IconButton,
MenuItem,
Divider,
Box,
Dialog,
DialogContent,
Fade,
Portal,
Collapse,
Tooltip,
ToggleButtonGroup,
ToggleButton,
} from "@mui/material";
import RecentWorkflow from "../components/RecentWorkflow.jsx";
import { useNavigate } from "react-router";
import { getTheme } from "../theme.jsx";
import { Link } from "react-router-dom";
import { toast } from "react-toastify";
import { Context } from "../context/ContextApi.jsx";
import Licensed from "./Licensed.jsx";
const ShuffleLogo = "/images/Shuffle_logo.png";
const detectionIcon = "/icons/detection.svg";
const documentationIcon = "/icons/documentation.svg";
const ExpandMoreAndLessIcon = "/icons/expandMoreIcon.svg";
const LeftSideBar = ({ userdata, serverside, globalUrl, notifications, SHUFFLE_VERSION }) => {
const navigate = useNavigate();
const {setLeftSideBarOpenByClick, leftSideBarOpenByClick, updateOrg, setUpdateOrg, setSearchBarModalOpen, searchBarModalOpen, logoutUrl, themeMode, handleThemeChange, isDocSearchModalOpen, setIsDocSearchModalOpen, supportEmail} = useContext(Context);
const [expandLeftNav, setExpandLeftNav] = useState(false);
const [activeOrgName, setActiveOrgName] = useState(
userdata?.active_org?.name || "Select Organziation"
);
const [openAutocomplete, setOpenAutocomplete] = useState(false);
const [autocompleteValue, setAutocompleteValue] = useState("");
const [openautomatetab, setOpenautomateTab] = useState(false);
const [openSecurityTab, setOpenSecurityTab] = useState(false);
const [selectedOrg, setSelectedOrg] = useState(activeOrgName);
const [anchorElAvatar, setAnchorElAvatar] = React.useState(null);
const [anchorEl, setAnchorEl] = React.useState(null);
const [recentworkflows, setRecentworkflows] = useState(null);
const [usersWorkFlows, setUsersWorkFlows] = useState([]);
const [currentOpenTab, setCurrentOpenTab] = useState("");
const params = new URLSearchParams(window.location.search);
const [currentSelectedTheme, setCurrentSelectedTheme] = useState(themeMode);
const tab = params.get("tab");
const currentPath = tab ? `${window.location.pathname}?tab=${tab}` : window.location.pathname;
const [hoverOnAvatar, setHoverOnAvatar] = useState(false);
const [orgOptions, setOrgOptions] = useState(
userdata?.orgs?.map((org) => ({
id: org.id,
name: org.name,
image: org.image,
region_url: org.region_url,
})) || []
);
const [activeOrgData, setActiveOrgData] = useState(null);
const [isProdStatusOn, setIsProdStatusOn] = useState(false);
const userOrgs = React.useMemo(() => {
return orgOptions.find((option) => option.name === selectedOrg);
}, [selectedOrg, orgOptions]);
const theme = getTheme(themeMode);
const darkText = "#0F1419"
const lightText = "#CDCDCD"
const lightHoverColor = "#D6D6D6"
const darkHoverColor = "#2F2F2F"
//With this code it is opening search bar on google chrome search bar as well which is not required
useEffect(() => {
const handleKeyDown = (event) => {
if ((event.ctrlKey || event.metaKey) && event.key === "k") {
event.preventDefault();
setSearchBarModalOpen((prev)=> !prev);
}
};
window.addEventListener("keydown", handleKeyDown);
return () => {
window.removeEventListener("keydown", handleKeyDown);
};
}, [setSearchBarModalOpen]);
useEffect(() => {
if (userdata && userdata?.active_org?.branding?.theme?.length > 0) {
setCurrentSelectedTheme(userdata?.active_org?.branding?.theme);
}else if (userdata && userdata?.theme?.length > 0) {
setCurrentSelectedTheme(userdata?.theme);
}
}, [userdata]);
const CustomPopper = (props) => {
return (
{props.children}
{
setSelectedOrg(userdata?.active_org?.name);
setOpenAutocomplete(false)
}}
>
} sx={{
textTransform: 'none',
}}>
Add suborg
);
};
const iconRef = useRef(null);
const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
const parsedAvatar =
userdata?.avatar !== undefined &&
userdata?.avatar !== null &&
userdata?.avatar.length > 0
? userdata?.avatar
: "";
const autocompleteRef = useRef(null);
const hoverOutColor = "#e8eaf6";
const handleClose = () => {
setAnchorEl(null);
setAnchorElAvatar(null);
};
const hrefStyle = {
color: hoverOutColor,
textDecoration: "none",
textTransform: "none",
fontStyle: "normal",
width: "100%",
fontSize: "16px",
};
const isCloud =
serverside === true || typeof window === "undefined"
? true
: window.location.host === "localhost:3002" ||
window.location.host === "shuffler.io" ||
window.location.host === "localhost:5002";
const UpdateTabStatus = useCallback(() => {
const lastTabOpenByUser = localStorage.getItem("lastTabOpenByUser");
if ((lastTabOpenByUser === "automate" && currentPath.includes("/new-dashboard")) || currentPath.includes("/new-dashboard")) {
setOpenautomateTab(true);
setCurrentOpenTab("automate");
setOpenSecurityTab(false);
} else if ((lastTabOpenByUser === "security" && currentPath.includes("/dashboards/security")) || currentPath.includes("/dashboards/security")) {
setOpenautomateTab(false);
setOpenSecurityTab(true);
setCurrentOpenTab("security");
} else if ((lastTabOpenByUser === "usecases" && currentPath.includes("/usecases")) || currentPath.includes("/usecases")) {
setOpenautomateTab(true);
setOpenSecurityTab(false);
setCurrentOpenTab("usecases");
} else if ((lastTabOpenByUser === "workflows" && currentPath === "/workflows") || currentPath === "/workflows") {
setOpenautomateTab(true);
setOpenSecurityTab(false);
setCurrentOpenTab("workflows");
} else if ((lastTabOpenByUser === "apps" && currentPath.includes("/apps")) || currentPath.includes("/apps")) {
setOpenautomateTab(true);
setOpenSecurityTab(false);
setCurrentOpenTab("apps");
} else if ((lastTabOpenByUser === "forms" && currentPath.includes("/forms")) || currentPath.includes("/forms")) {
setOpenautomateTab(false);
setOpenSecurityTab(true);
setCurrentOpenTab("forms");
} else if ((lastTabOpenByUser === "datastore" && currentPath.includes("/admin?tab=datastore")) || currentPath.includes("/admin?tab=datastore")) {
setOpenautomateTab(false);
setOpenSecurityTab(true);
setCurrentOpenTab("datastore");
} else if ((lastTabOpenByUser === "files" && currentPath.includes("/admin?tab=files")) || currentPath.includes("/admin?tab=files")) {
setOpenautomateTab(false);
setOpenSecurityTab(true);
setCurrentOpenTab("files");
}
else if ((lastTabOpenByUser === "locations" && currentPath.includes("/admin?tab=locations")) || currentPath.includes("/admin?tab=locations")) {
setOpenautomateTab(false);
setOpenSecurityTab(true);
setCurrentOpenTab("locations");
} else if ((lastTabOpenByUser === "docs" || currentPath.includes("/docs")) || currentPath.includes("/docs")) {
setOpenautomateTab(false);
setOpenSecurityTab(false);
setCurrentOpenTab("docs");
} else {
setOpenautomateTab(true);
setOpenSecurityTab(false);
setCurrentOpenTab("");
}
},[currentPath]);
useEffect(() => {
UpdateTabStatus()
const expandLeftNav1 = localStorage.getItem("expandLeftNav")
if (expandLeftNav1 === "false") {
setLeftSideBarOpenByClick(false)
} else {
const currentLocation = window?.location?.pathname
if (currentLocation?.includes('/workflows/')) {
} else {
setLeftSideBarOpenByClick(true)
setExpandLeftNav(true)
}
}
}, [])
const getAvailableWorkflows = useCallback((amount) => {
var url = `${globalUrl}/api/v1/workflows`
if (amount !== undefined && amount !== null) {
url += `?top=${amount}`
}
fetch(url, {
method: "GET",
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
credentials: "include",
})
.then((response) => {
if (response.status !== 200) {
toast("Failed getting workflows. Are you logged in?");
return
}
return response.json();
})
.then((responseJson) => {
if (responseJson !== undefined) {
var newarray = []
for (var wfkey in responseJson) {
const wf = responseJson[wfkey]
if (wf.public === true || wf.hidden === true) {
continue
}
newarray.push(wf)
}
var actionnamelist = [];
var parsedactionlist = [];
for (var key in newarray) {
for (var actionkey in newarray[key].actions) {
const action = newarray[key].actions[actionkey];
if (actionnamelist.includes(action.app_name)) {
continue;
}
actionnamelist.push(action.app_name);
parsedactionlist.push(action);
}
}
if (newarray.length > 0) {
try {
localStorage.setItem("workflows", JSON.stringify(newarray))
} catch (e) {
console.log("Failed to set workflows in localstorage: ", e)
}
}
setTimeout(() => {
setUsersWorkFlows(newarray);
if (newarray.length === 0) {
setUsersWorkFlows([]);
}
}, 250)
}
})
.catch((error) => {
toast(error.toString());
});
}, [usersWorkFlows]);
useEffect(() => {
const fetchData = async () => {
if (recentworkflows === null || recentworkflows === undefined || recentworkflows?.length === 0) {
await delay(2000);
}
const storagewf = localStorage.getItem("workflows");
const storageWorkflows = JSON.parse(storagewf);
if (storageWorkflows) {
setUsersWorkFlows(storageWorkflows);
} else {
getAvailableWorkflows();
}
};
fetchData();
}, []);
useEffect(() => {
if (usersWorkFlows) {
const recentWorkflow = HandleGetUsersRecentWorkflows(usersWorkFlows);
setRecentworkflows(recentWorkflow);
}
}, [usersWorkFlows]);
const handleChangeTheme = (newTheme) => {
const data = {
"org_id": userdata?.active_org?.id,
};
data["branding"] = {
"theme": newTheme,
"enable_chat": userdata?.active_org?.branding?.enable_chat || false,
"home_url": userdata.active_org?.branding?.home_url || "",
"brand_color": userdata?.active_org?.branding?.brand_color || theme.palette.primary.main,
"brand_name": userdata?.active_org?.branding?.brand_name || "",
"logout_url": userdata?.active_org?.branding?.logout_url || "",
"support_email": userdata?.active_org?.branding?.support_email || "",
}
data["editing_branding"] = true;
const url = globalUrl + `/api/v1/orgs/${userdata?.active_org?.id}`;
fetch(url, {
mode: "cors",
method: "POST",
body: JSON.stringify(data),
credentials: "include",
crossDomain: true,
withCredentials: true,
headers: {
"Content-Type": "application/json; charset=utf-8",
},
})
.then((response) =>
response.json().then((responseJson) => {
if (responseJson["success"] === false) {
toast("Failed updating org: ", responseJson.reason);
}
})
)
.catch((error) => {
console.log("Error changing theme: ", error);
});
};
const handleUpdateTheme = (newTheme) => {
handleThemeChange(newTheme);
setCurrentSelectedTheme(newTheme)
const data = {
"user_id": userdata?.id,
"theme": newTheme,
}
const url = globalUrl + `/api/v1/users/updateuser`;
fetch(url, {
mode: "cors",
method: "PUT",
body: JSON.stringify(data),
credentials: "include",
crossDomain: true,
withCredentials: true,
headers: {
"Content-Type": "application/json; charset=utf-8",
},
}).then((response) =>
response.json().then((responseJson) => {
if (responseJson["success"] === false) {
toast("Failed saving your theme: ", responseJson.reason);
}
})
).catch((error) => {
console.log("Error saving your theme: ", error);
});
};
const removeCookie = (name, path = "/") => {
document.cookie = `${name}=; path=${path}; expires=Thu, 01 Jan 1970 00:00:00 GMT;`;
};
const handleClickLogout = () => {
// Logout API call
fetch(`${globalUrl}/api/v1/logout`, {
credentials: "include",
method: "POST",
headers: {
"Content-Type": "application/json",
},
})
.then((response) => {
if (response.status !== 200) {
toast.error("Failed to logout. Please try again.");
return;
}
// Remove cookies
removeCookie("session_token", { path: "/" });
removeCookie("__session", { path: "/" });
// Clear localStorage
localStorage.clear();
if(userdata?.org_status?.includes("integration_partner") && logoutUrl?.length > 0){
window.location.href = logoutUrl
} else {
window.location.pathname = "/";
}
})
.catch((error) => {
console.error("Logout error:", error);
});
};
const avatarMenu = (
{
setAnchorElAvatar(event.currentTarget);
}}
disableRipple
disableElevation
>
);
const getWorkflowAppgroup = (data) => {
if (!data.actions) {
return [];
}
let appsFound = [];
Object.keys(data.actions).forEach((key) => {
const parsedAction = data.actions[key];
if (!parsedAction.large_image) {
return;
}
if (
appsFound.findIndex((app) => app.app_name === parsedAction.app_name) < 0
) {
appsFound.push(parsedAction);
}
});
return appsFound;
};
const HandleGetUsersRecentWorkflows = useCallback(() => {
if (!usersWorkFlows) {
return [];
}
let groupedWorkflows = [];
usersWorkFlows.forEach((workflow) => {
const apps = getWorkflowAppgroup(workflow);
if (apps.length > 0) {
groupedWorkflows.push({
name: workflow.name,
id: workflow.id,
apps: apps,
});
}
});
return groupedWorkflows;
},[usersWorkFlows]);
const handleClickChangeOrg = (orgId) => {
toast.info("Changing active organization - please wait!");
const data = {
org_id: orgId,
};
if (userdata?.active_org?.id === orgId) {
return
}
localStorage.setItem("globalUrl", "");
localStorage.setItem("getting_started_sidebar", "open");
localStorage.removeItem("workflows");
localStorage.removeItem("apps");
localStorage.removeItem("dashboard_onboarding_complete")
localStorage.removeItem("dashboard_onboarding_completed")
fetch(`${globalUrl}/api/v1/orgs/${orgId}/change`, {
mode: "cors",
credentials: "include",
crossDomain: true,
method: "POST",
body: JSON.stringify(data),
withCredentials: true,
headers: {
"Content-Type": "application/json; charset=utf-8",
},
})
.then(function (response) {
if (response.status !== 200) {
console.log("Error in response");
} else {
localStorage.removeItem("apps");
localStorage.removeItem("workflows");
localStorage.removeItem("userinfo");
localStorage.removeItem("lastTabOpenByUser");
}
return response.json();
})
.then(function (responseJson) {
if (responseJson.success === true) {
if (
responseJson?.region_url !== undefined &&
responseJson?.region_url !== null &&
responseJson?.region_url.length > 0
) {
localStorage.setItem("globalUrl", responseJson.region_url);
}
if (responseJson["reason"] === "SSO_REDIRECT") {
setTimeout(() => {
toast.info(
"Redirecting to SSO login page as SSO is required for this organization."
);
window.location.href = responseJson["url"];
return;
}, 2000);
} else {
setTimeout(() => {
window.location.reload();
}, 2000);
}
toast.success("Successfully changed active organization - refreshing!");
} else {
if (
responseJson.reason !== undefined &&
responseJson.reason !== null &&
responseJson.reason.length > 0
) {
toast(responseJson.reason);
} else {
toast(
`Failed changing org. Try again or contact ${supportEmail} if this persists.`
);
}
}
})
.catch((error) => {
console.log("error changing: ", error);
});
};
const getRegionTag = (region_url) => {
let regiontag = "UK";
//let regiontag = "EU";
if (
region_url !== undefined &&
region_url !== null &&
region_url.length > 0
) {
const regionsplit = region_url.split(".");
if (regionsplit.length > 2 && !regionsplit[0].includes("shuffler")) {
const namesplit = regionsplit[0].split("/");
regiontag = namesplit[namesplit.length - 1];
if (regiontag === "california") {
regiontag = "US";
} else if (regiontag === "frankfurt") {
regiontag = "EU-2";
} else if (regiontag === "ca"){
regiontag = "CA";
}
}
}
return regiontag;
};
useEffect(() => {
if(activeOrgName !== userdata?.active_org?.name){
setActiveOrgName(userdata?.active_org?.name || "Select Organization");
}
}, [userdata]);
const CheckOrgStates = useCallback(() => {
setOrgOptions(
userdata?.orgs?.map((org) => {
let skipOrg = false;
if (
org.creator_org !== undefined &&
org.creator_org !== null &&
org.creator_org.length > 0
) {
// Finds the parent org
for (let key in userdata.child_orgs) {
if (userdata.child_orgs[key].id === org.creator_org) {
skipOrg = true;
break;
}
}
if (skipOrg) {
return null; // Skip this org
}
}
return {
id: org.id,
name: org.name,
image: org.image,
region_url: getRegionTag(org.region_url),
margin_left:
org.creator_org !== undefined &&
org.creator_org !== null &&
org.creator_org.length > 0 ? 20 : 0,
};
}) || []
);
setActiveOrgName(userdata?.active_org?.name || "Select Organization");
setSelectedOrg(userdata?.active_org?.name || "Select Organization");
}, [userdata]);
useEffect(() => {
if (typeof userdata?.id === "string" && userdata?.id?.length > 0) {
CheckOrgStates();
setAutocompleteValue(userdata?.active_org?.name || "");
}
}, []);
const ButtonStyle = {
width: expandLeftNav ? "100%" : 30,
justifyContent: expandLeftNav ? "flex-start" : "center",
height: 35,
color: openautomatetab ? "#F1F1F1" : themeMode === "dark" ? lightText : darkText,
textTransform: "none",
"& .MuiButton-root ": {
width: expandLeftNav ? "100%" : 30,
padding: 0,
},
fontSize: 18
};
const getRegionFlag = (region_url) => {
var region = "UK";
const regionMapping = {
"US": "us",
"EU": "eu",
"CA": "ca",
"UK": "gb",
"au": "au",
};
region = regionMapping[region_url] || "eu";
return `https://flagcdn.com/48x36/${region}.png`;
};
useEffect(() => {
if (window?.location?.pathname?.includes("/workflows/")) {
setExpandLeftNav(false);
}
}, [window?.location?.pathname]);
const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
const showPartnerLogo = userdata?.org_status?.includes("integration_partner") && userdata?.active_org?.image !== undefined && userdata?.active_org?.image !== null && userdata?.active_org?.image.length > 0
useEffect(() => {
const orgId = userdata?.active_org?.id;
if (!orgId) {
return;
}
let fetched = false;
fetch(`${globalUrl}/api/v1/orgs/${orgId}`, {
method: "GET",
credentials: "include",
headers: { "Content-Type": "application/json" },
})
.then((response) => (response.ok ? response.json() : null))
.then((org) => {
if (!fetched && org) {
setActiveOrgData(org);
setUpdateOrg(false);
if (!isCloud) {
if (org?.cloud_sync && org?.subscriptions[0]?.name?.toLowerCase().includes("enterprise") && org?.subscriptions[0]?.active) {
setIsProdStatusOn(true);
} else if (org?.subscriptions[0]?.name?.toLowerCase().includes("enterprise") && org?.subscriptions[0]?.active) {
setIsProdStatusOn(true);
} else {
setIsProdStatusOn(false);
}
}
}
})
.catch(() => {});
return () => {
fetched = true;
};
}, [userdata?.active_org?.id, globalUrl, updateOrg]);
return (
{searchBarModalOpen && !isDocSearchModalOpen ?
: null}
{
if(window?.location?.pathname?.includes("/workflows/")) {
setExpandLeftNav(true)
}
}}
onMouseLeave={()=>{
if(window?.location?.pathname?.includes("/workflows/")) {
setExpandLeftNav(false)
}
}}
>
{
!isCloud && expandLeftNav && (
{isProdStatusOn ? "Enterprise" : "Open Source"}
)
}
{(!leftSideBarOpenByClick || window?.location?.pathname?.includes("/workflows/")) && setExpandLeftNav(true)}} onMouseLeave={()=>{(!leftSideBarOpenByClick || window?.location?.pathname?.includes("/workflows/")) && setExpandLeftNav(false);setOpenAutocomplete(false)}}>
{expandLeftNav ? (
),
endAdornment: (
Ctrl+K
),
disableUnderline: true,
}}
onClick={() => {
setSearchBarModalOpen(true);
setIsDocSearchModalOpen(false);
}}
onChange={() => {
setSearchBarModalOpen(true);
setIsDocSearchModalOpen(false);
}}
/>
):(
<>
>)}
{
setOpenautomateTab((prev) => !prev);
setOpenSecurityTab(false);
}}
style={{
color: themeMode === "dark" ? lightText : darkText,
marginLeft: 0.625,
}}
onMouseOver={(event)=>{
event.currentTarget.style.backgroundColor = themeMode === "dark" ? darkHoverColor : lightHoverColor;
}}
onMouseOut={(event)=>{
event.currentTarget.style.backgroundColor = "transparent";
}}
>
{openautomatetab ? (
) : (
)}
{
setOpenSecurityTab((prev) => !prev);
setOpenautomateTab(false);
}}
style={{
marginLeft: 0.625,
color: themeMode === "dark" ? lightText : darkText,
}}
onMouseOver={(event)=>{
event.currentTarget.style.backgroundColor = themeMode === "dark" ? darkHoverColor : lightHoverColor;
}}
onMouseOut={(event)=>{
event.currentTarget.style.backgroundColor = "transparent";
}}
>
{openSecurityTab ? (
) : (
)}
{userdata && (userdata?.support || userdata?.active_org?.role === "admin") ? (
<>
>): null}
{recentworkflows?.length > 0 ?
Recent Workflows
{recentworkflows?.slice(0, 2).map((workflow, index) => {
return (
)
}) }
: null }
<>
{userdata?.licensed !== true && !userdata?.org_status?.includes("integration_partner") && !isProdStatusOn && (
)}
{!isCloud && (activeOrgData?.old_org || isProdStatusOn) && (
)}
>
orgOptions, [orgOptions])}
getOptionLabel={(option) => option.name}
PopperComponent={CustomPopper}
open={openAutocomplete}
onOpen={() => setOpenAutocomplete(true)}
renderOption={(props, option, { selected, index }) => (
{
e.currentTarget.style.backgroundColor = theme.palette.hoverColor;
}}
onMouseOut={(e) => {
e.currentTarget.style.backgroundColor = option.name === selectedOrg ? theme.palette.hoverColor : "transparent";
}}
onClick={(e) => {
if (option.id !== userdata?.active_org?.id) {
setSelectedOrg(option.name);
handleClickChangeOrg(option.id);
} else {
setSelectedOrg(userdata?.active_org?.name);
}
setOpenAutocomplete(false);
}}
>
{
isCloud ? (
{option.region_url}
) : null
}
{option.name}
)}
onChange={(event, newValue) => {
if (newValue) {
if (userdata?.active_org?.id !== newValue.id) {
setSelectedOrg(newValue.name);
handleClickChangeOrg(newValue.id);
} else {
setSelectedOrg(userdata?.active_org?.name);
}
setOpenAutocomplete(false);
}
}}
onInputChange={(event, newInputValue) => {
setAutocompleteValue(newInputValue);
}}
filterOptions={(options, params) => {
const normalize = (str) => str.toLowerCase().replace(/[\s-]+/g, "");
const input = normalize(params.inputValue);
return options.filter((option) =>
normalize(option.name).includes(input) ||
normalize(option.region_url).includes(input)
);
}}
value={userOrgs}
renderInput={(params) => (
{expandLeftNav ? (
) : (
setOpenAutocomplete((prev) => !prev)}
style={{
cursor: "pointer",
fontSize: "24px",
opacity: expandLeftNav ? 0 : 1,
transition: "opacity 0.3s ease",
color: themeMode === "dark" ? lightText : darkText,
}}
/>
)}
)}
/>
{
event.currentTarget.style.backgroundColor = themeMode === "dark" ? darkHoverColor : lightHoverColor;
setHoverOnAvatar(true);
}}
onMouseLeave={(event) => {
event.currentTarget.style.backgroundColor = "transparent";
setHoverOnAvatar(false);
}}
>
{expandLeftNav ? (
<>
{avatarMenu}
>
) : (
)}
);
};
export default LeftSideBar;
const ModalView = memo(({searchBarModalOpen, setSearchBarModalOpen, globalUrl, serverside, userdata, isDocSearchModalOpen}) => {
const {themeMode} = useContext(Context);
const theme = getTheme(themeMode);
return (
(
)
)
});