diff --git a/frontend/src/components/LeftSideBar.jsx b/frontend/src/components/LeftSideBar.jsx
new file mode 100644
index 00000000..1d0de5d5
--- /dev/null
+++ b/frontend/src/components/LeftSideBar.jsx
@@ -0,0 +1,1546 @@
+import React, { useEffect, useRef, useState, useContext, useCallback, useMemo } from "react";
+import {
+ ExpandLess as ExpandLessIcon,
+ ExpandMore as ExpandMoreIcon,
+ GridView as GridViewIcon,
+ ShieldOutlined as ShieldOutlinedIcon,
+ Add as AddIcon,
+ BorderColor,
+ Close as CloseIcon,
+} from "@mui/icons-material";
+import SearchBox from "./SearchData.jsx";
+import {
+ Button,
+ Typography,
+ Autocomplete,
+ TextField,
+ Popper,
+ Avatar,
+ Menu,
+ IconButton,
+ MenuItem,
+ Divider,
+ Box,
+ Dialog,
+ DialogContent,
+ Fade,
+ Portal,
+ Collapse,
+} from "@mui/material";
+import theme from "../theme.jsx";
+import {
+ Settings as SettingsIcon
+} from "@mui/icons-material";
+import RecentWorkflow from "../components/RecentWorkflow.jsx";
+
+import { useNavigate } from "react-router";
+
+import { Link } from "react-router-dom";
+import {
+ Business as BusinessIcon,
+ Notifications as NotificationsIcon,
+ HelpOutline as HelpOutlineIcon,
+ MeetingRoom as MeetingRoomIcon,
+ Lightbulb as LightbulbIcon,
+ Search as SearchIcon
+} from "@mui/icons-material";
+
+import { toast } from "react-toastify";
+import { Context } from "../context/ContextApi.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, }) => {
+
+ const navigate = useNavigate();
+ const {setLeftSideBarOpenByClick, leftSideBarOpenByClick, setSearchBarModalOpen, searchBarModalOpen} = 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 currentPath = 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 userOrgs = React.useMemo(() => {
+ return orgOptions.find((option) => option.name === selectedOrg);
+ }, [selectedOrg, orgOptions]);
+
+
+
+ const CustomPopper = (props) => {
+ return (
+
+
+
+ {props.children}
+
+
+ {
+ setSelectedOrg(userdata?.active_org?.name);
+ setOpenAutocomplete(false)
+ }}
+ >
+ 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("/dashboards/automate")) || currentPath.includes("/dashboards/automate")) {
+ 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("/usecases2")) || currentPath.includes("/usecases2")) {
+ 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("/search")) || currentPath.includes("/search")) {
+ setOpenautomateTab(true);
+ setOpenSecurityTab(false);
+ setCurrentOpenTab("apps");
+ } else if ((lastTabOpenByUser === "detection" && currentPath.includes("/detections")) || currentPath.includes("/detections")) {
+ setOpenautomateTab(false);
+ setOpenSecurityTab(true);
+ setCurrentOpenTab("detection");
+ } else if ((lastTabOpenByUser === "response" && currentPath.includes("/response")) || currentPath.includes("/response")) {
+ setOpenautomateTab(false);
+ setOpenSecurityTab(true);
+ setCurrentOpenTab("response");
+ } 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);
+ setLeftSideBarOpenByClick(false);
+ } else {
+ setLeftSideBarOpenByClick(true);
+ 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 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();
+
+ // Redirect to home immediately
+ window.location.href = "/";
+ })
+ .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,
+ };
+
+ localStorage.setItem("globalUrl", "");
+ localStorage.setItem("getting_started_sidebar", "open");
+
+ 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 support@shuffler.io if this persists."
+ );
+ }
+ }
+ })
+ .catch((error) => {
+ console.log("error changing: ", error);
+ });
+};
+
+ const getRegionTag = (region_url) => {
+ 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 = "fr";
+ }
+ }
+ }
+ return regiontag;
+ };
+
+ const CheckOrgStates = useCallback(() => {
+ setOrgOptions(
+ userdata?.orgs?.map((org) => ({
+ id: org.id,
+ name: org.name,
+ image: org.image,
+ region_url: getRegionTag(org.region_url),
+ })) || []
+ );
+ setActiveOrgName(userdata?.active_org?.name || "Select Organization");
+ setSelectedOrg(userdata?.active_org?.name || "Select Organization");
+ },[orgOptions, activeOrgName, selectedOrg]);
+
+ 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" : "#C8C8C8",
+ textTransform: "none",
+ "& .MuiButton-root ": {
+ width: expandLeftNav ? "100%" : 30,
+ padding: 0,
+ },
+ };
+
+ const modalView = (
+
+ );
+
+ return (
+
+ {modalView}
+
+
+
+
+
+
+
+
+
{!leftSideBarOpenByClick && setExpandLeftNav(true);}} onMouseLeave={()=>{!leftSideBarOpenByClick && setExpandLeftNav(false);setOpenAutocomplete(false);}}>
+
+ {expandLeftNav ? (
+
+
+ ),
+ disableUnderline: true,
+ }}
+ onClick={()=>{setSearchBarModalOpen(true)}}
+ onChange={()=> {setSearchBarModalOpen(true)}}
+ />
+
+ ):(
+ <>
+
+
+
+ >)}
+
+
+
+
+
+
+
+
+ {
+ setOpenautomateTab((prev) => !prev);
+ setOpenSecurityTab(false);
+ }}
+ sx={{
+ marginLeft: 0.625,
+ }}
+ >
+ {openautomatetab ? (
+
+ ) : (
+
+ )}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {
+ setOpenSecurityTab((prev) => !prev);
+ setOpenautomateTab(false);
+ }}
+ sx={{
+ marginLeft: 0.625,
+ }}
+ >
+ {openSecurityTab ? (
+
+ ) : (
+
+ )}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Recent Workflows
+
+
+ {recentworkflows?.slice(0, 2).map((workflow, index) => {
+ return (
+
+ )
+ }) }
+
+
+
+
+
+ orgOptions, [orgOptions])}
+ getOptionLabel={(option) => option.name}
+ PopperComponent={CustomPopper}
+ open={openAutocomplete}
+ onOpen={() => setOpenAutocomplete(true)}
+ renderOption={(props, option, { selected, index }) => (
+ {
+ e.currentTarget.style.backgroundColor = "#444444";
+ }}
+ onMouseOut={(e) => {
+ e.currentTarget.style.backgroundColor = option.name === selectedOrg ? "#696969" : "transparent";
+ }}
+ onClick={(e) => {
+ if (option.id !== userdata?.active_org?.id) {
+ setSelectedOrg(option.name);
+ handleClickChangeOrg(option.id);
+ } else {
+ setSelectedOrg(userdata?.active_org?.name);
+ }
+ setOpenAutocomplete(false);
+ }}
+ >
+
+ {option.region_url}
+
+
+
+ {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) => {
+ return options.filter((option) =>
+ option.name
+ .toLowerCase()
+ .includes(params.inputValue.toLowerCase())
+ );
+ }}
+ value={userOrgs}
+ renderInput={(params) => (
+
+ {expandLeftNav ? (
+
+ ) : (
+
+
+ setOpenAutocomplete((prev) => !prev)}
+ style={{
+ cursor: "pointer",
+ fontSize: "24px",
+ opacity: expandLeftNav ? 0 : 1,
+ transition: "opacity 0.3s ease",
+ }}
+ />
+
+ )}
+
+ )}
+ />
+
+ {event.currentTarget.style.backgroundColor = "#2f2f2f";setHoverOnAvatar(true)}}
+ onMouseLeave ={(event)=>{event.currentTarget.style.backgroundColor = "transparent";setHoverOnAvatar(false)}}
+ >
+ {expandLeftNav ? (
+ <>
+
+ >
+ ) : (
+ <>
+
+ >
+ )}
+
+
+
+
+ );
+};
+
+export default LeftSideBar;