import React, { memo, useContext, useEffect, useState } from 'react'; import theme from "../theme.jsx"; import { FormControl, Card, Tooltip, Typography, Switch, Divider, TextField, Button, Grid, List, ListItem, ListItemText, ListItemAvatar, Avatar, Dialog, DialogTitle, DialogActions, DialogContent, Skeleton, } from "@mui/material"; import { Edit as EditIcon, Polyline as PolylineIcon, CheckCircle as CheckCircleIcon, Close as CloseIcon, Apps as AppsIcon, Business as BusinessIcon, Flag, } from "@mui/icons-material"; import { toast } from 'react-toastify'; const TenantsTab = memo((props) => { const { globalUrl, isCloud, userdata, selectedOrganization, setSelectedOrganization, checkLogin } = props; const imageStyle = { width: 50, height: 50 }; // const [selectedOrganization, setSelectedOrganization] = React.useState({}); const [subOrgs, setSubOrgs] = useState([]); const [cloudSyncApikey, setCloudSyncApikey] = React.useState(""); const [orgName, setOrgName] = React.useState(""); const [orgSyncResponse, setOrgSyncResponse] = React.useState(""); const [loading, setLoading] = React.useState(false); // const [loginInfo, setLoginInfo] = React.useState(""); const [cloudSyncModalOpen, setCloudSyncModalOpen] = React.useState(false); const [modalOpen, setModalOpen] = React.useState(false); const [parentOrg, setParentOrg] = React.useState(null); const [parentOrgFlag, setParentOrgFlag] = React.useState(null); const [loadOrgs, setLoadOrgs] = React.useState(true); const [, forceUpdate] = React.useState(); const itemColor = "black"; useEffect(() => { if(parentOrg !== null && parentOrgFlag === null) { let regiontag = "UK"; let regionCode = "gb"; if (parentOrg?.region_url?.length > 0) { const regionsplit = parentOrg?.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"; regionCode = "us"; } else if (regiontag === "frankfurt") { regiontag = "EU-2"; regionCode = "eu"; } else if (regiontag === "ca") { regiontag = "CA"; regionCode = "ca"; } } setParentOrgFlag(regionCode); } } }, [parentOrg]); var syncList = [ { primary: "Workflows", secondary: "", active: true, icon: , }, { primary: "Apps", secondary: "", active: true, icon: , }, { primary: "Organization", secondary: "", active: true, icon: , }, ]; useEffect(() => { if (userdata.orgs !== undefined && userdata.orgs !== null && userdata.orgs.length > 0) { handleGetSubOrgs(userdata.active_org.id); } else console.log("error in user data") }, [userdata]); const handleGetSubOrgs = (orgId) => { if (orgId.length === 0) { toast("Organization ID not defined. Please contact us on https://shuffler.io if this persists logout."); return; } fetch(`${globalUrl}/api/v1/orgs/${orgId}/suborgs`, { method: "GET", credentials: "include", headers: { "Content-Type": "application/json", }, }) .then((response) => { if (!response.ok) { throw new Error('Failed to fetch sub organizations'); } return response.json(); }) .then((responseJson) => { if (responseJson.success === false) { setLoadOrgs(false) //toast("Failed getting your org. If this persists, please contact support."); } else { const { subOrgs, parentOrg } = responseJson; setLoadOrgs(false) setSubOrgs(subOrgs); setParentOrg(parentOrg); let regiontag = "UK"; let regionCode = "gb"; if (parentOrg?.region_url?.length > 0) { const regionsplit = parentOrg?.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"; regionCode = "us"; } else if (regiontag === "frankfurt") { regiontag = "EU-2"; regionCode = "eu"; } else if (regiontag === "ca") { regiontag = "CA"; regionCode = "ca"; } } setParentOrgFlag(regionCode); } } }) .catch((error) => { console.log("Error getting sub orgs: ", error); //toast("Error getting sub organizations"); setLoadOrgs(false) }); }; const GridItem = (props) => { const [expanded, setExpanded] = React.useState(false); const [showEdit, setShowEdit] = React.useState(false); const [newValue, setNewValue] = React.useState(-100); const primary = props.data.primary; const secondary = props.data.secondary; const primaryIcon = props.data.icon; const secondaryIcon = props.data.active ? ( ) : ( ); const submitFeatureEdit = (sync_features) => { if (!userdata.support) { console.log( "User does not have support access and can't edit features", ); return; } sync_features.editing = true; const data = { org_id: selectedOrganization.id, sync_features: sync_features, }; const url = globalUrl + `/api/v1/orgs/${selectedOrganization.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); } else { toast("Successfully edited org!"); } }), ) .catch((error) => { toast("Err: " + error.toString()); }); }; const enableFeature = () => { console.log("Enabling " + primary); console.log(selectedOrganization.sync_features); // Check if primary is in sync_features var tmpprimary = primary.replaceAll(" ", "_"); if (!(tmpprimary in selectedOrganization.sync_features)) { console.log("Primary not in sync_features: " + tmpprimary); return; } if (props.data.active) { selectedOrganization.sync_features[tmpprimary].active = false; } else { selectedOrganization.sync_features[tmpprimary].active = true; } // setSelectedOrganization(selectedOrganization); forceUpdate(Math.random()); submitFeatureEdit(selectedOrganization.sync_features); }; const submitEdit = (e) => { e.preventDefault(); e.stopPropagation(); // Check if primary is in sync_features var tmpprimary = primary.replaceAll(" ", "_"); if (!(tmpprimary in selectedOrganization.sync_features)) { console.log("Primary not in sync_features: " + tmpprimary); return; } // Make it into a number var tmp = parseInt(newValue); if (isNaN(tmp)) { console.log("Not a number: " + newValue); return; } selectedOrganization.sync_features[tmpprimary].limit = tmp; // setSelectedOrganization(selectedOrganization); forceUpdate(Math.random()); submitFeatureEdit(selectedOrganization.sync_features); }; return ( { setExpanded(!expanded); }} > {primaryIcon} {isCloud && userdata.support === true ? ( { e.preventDefault(); e.stopPropagation(); if (showEdit) { setShowEdit(false); return; } console.log("Edit"); setShowEdit(true); }} /> ) : null} { if (!isCloud || userdata.support !== true) { return; } e.preventDefault(); e.stopPropagation(); enableFeature(); }} > {secondaryIcon} {expanded ? (
Usage:  {props.data.limit === 0 ? ( "Unlimited" ) : ( {props.data.usage} /{" "} {props.data.limit === "" ? "Unlimited" : props.data.limit} )} {/* Data sharing: {props.data.data_collection} */} Description: {secondary}
) : null} {showEdit ? ( { console.log("Submit"); submitEdit(e); }} > { setNewValue(event.target.value); }} /> ) : null}
); }; const enableCloudSync = (apikey, organization, disableSync) => { setOrgSyncResponse(""); const data = { apikey: apikey, organization: organization, disable: disableSync, }; const url = globalUrl + "/api/v1/cloud/setup"; 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) => { setLoading(false); if (response.status === 200) { console.log("Cloud sync success?"); } else { console.log("Cloud sync fail?"); } return response.json(); //setTimeout(() => { //}, 1000) }) .then((responseJson) => { console.log("RESP: ", responseJson); if ( responseJson.success === false && responseJson.reason !== undefined ) { setOrgSyncResponse(responseJson.reason); toast("Failed to handle sync: " + responseJson.reason); } else if (!responseJson.success) { toast("Failed to handle sync."); } else { // getOrgs(); if (disableSync) { toast("Successfully disabled sync!"); setOrgSyncResponse("Successfully disabled syncronization"); } else { toast("Cloud Syncronization successfully set up!"); setOrgSyncResponse( "Successfully started syncronization. Cloud features you now have access to can be seen below.", ); } selectedOrganization.cloud_sync = !selectedOrganization.cloud_sync; // setSelectedOrganization(selectedOrganization); setCloudSyncApikey(""); // handleGetOrg(userdata.active_org.id); } }) .catch((error) => { setLoading(false); toast("Err: " + error.toString()); }); }; const createSubOrg = (currentOrgId, name) => { const data = { name: name, org_id: currentOrgId }; console.log(data); const url = globalUrl + `/api/v1/orgs/${currentOrgId}/create_sub_org`; 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) { if (responseJson.reason !== undefined) { toast.error(responseJson.reason, { autoClose: 5000, }) } else { toast("Failed creating suborg. Please try again"); } } else { toast("Successfully created suborg. Reloading in 3 seconds!"); // setSelectedUserModalOpen(false); setTimeout(() => { window.location.reload(); }, 2500); } setOrgName(""); setModalOpen(false); }), ) .catch((error) => { toast("Err: " + error.toString()); }); }; const handleClickChangeOrg = (orgId) => { // Don't really care about the logout //name: org.name, //orgId = "asd" 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.setItem("apps", []) } 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); //globalUrl = responseJson.region_url } checkLogin() setTimeout(() => { window.location.reload(); }, 3000); toast("Successfully changed active organization - refreshing!"); } else { toast("Failed changing org: " + responseJson.reason); } }) .catch((error) => { console.log("error changing: ", error); //removeCookie("session_token", {path: "/"}) }); }; const modalView = ( { setModalOpen(false); }} PaperProps={{ sx: { borderRadius: theme?.palette?.DialogStyle?.borderRadius, border: theme?.palette?.DialogStyle?.border, minWidth: "800px", minHeight: "320px", fontFamily: theme?.typography?.fontFamily, backgroundColor: theme?.palette?.DialogStyle?.backgroundColor, zIndex: 1000, '& .MuiDialogContent-root': { backgroundColor: theme?.palette?.DialogStyle?.backgroundColor, }, '& .MuiDialogTitle-root': { backgroundColor: theme?.palette?.DialogStyle?.backgroundColor, }, '& .MuiDialogActions-root': { backgroundColor: theme?.palette?.DialogStyle?.backgroundColor, }, }, }} > Add Sub-Organization
Name { setOrgName(event.target.value); }} />
{/* {loginInfo} */}
); const cloudSyncModal = ( { setCloudSyncModalOpen(false); }} PaperProps={{ sx: { borderRadius: theme?.palette?.DialogStyle?.borderRadius, border: theme?.palette?.DialogStyle?.border, minWidth: "800px", minHeight: "320px", fontFamily: theme?.typography?.fontFamily, backgroundColor: theme?.palette?.DialogStyle?.backgroundColor, zIndex: 1000, '& .MuiDialogContent-root': { backgroundColor: theme?.palette?.DialogStyle?.backgroundColor, }, '& .MuiDialogTitle-root': { backgroundColor: theme?.palette?.DialogStyle?.backgroundColor, }, '& .MuiDialogActions-root': { backgroundColor: theme?.palette?.DialogStyle?.backgroundColor, }, }, }} > Enable cloud features What does{" "} cloud sync {" "} do?
{ setCloudSyncApikey(event.target.value); }} />
{orgSyncResponse.length > 0 ? ( Error: {orgSyncResponse} ) : null} {syncList.map((data, index) => { return ; })} * New triggers (userinput, hotmail realtime)
* Execute in the cloud rather than onprem
* Apps can be built in the cloud
* Easily share apps and workflows
* Access to powerful cloud search
); const textColor = "#9E9E9E !important"; return (
{modalView} {cloudSyncModal}

Tenants

Create, manage and change to sub-organizations (tenants)! {" "} {isCloud ? "You can only make a sub organization if you are a customer of shuffle or running a POC of the platform. Please contact support@shuffler.io to try it out." : ''} Learn more

Your Parent Organization

{/* */}
{isCloud && ( )} {loadOrgs ? ( [...Array(3)].map((_, rowIndex) => ( {[ { width: 100, minWidth: 100, maxWidth: 100 }, { width: 250, minWidth: 50, maxWidth: 250 }, { width: 400, minWidth: 400, maxWidth: 400 }, { width: "28%", minWidth: "28%" }, { width: 400, minWidth: 400, maxWidth: 400 }, ].map((style, colIndex) => ( ))} )) ) : parentOrg?.id?.length > 0 ? ( } style={{ width: 100, minWidth: 100, maxWidth: 100, display: "table-cell", padding: "8px 8px 8px 20px", textAlign: "center", }} /> {isCloud && ( {parentOrgFlag}
} style={{ display: "table-cell", padding: 8, verticalAlign: "middle" }} /> )} } style={{ display: "table-cell", verticalAlign: "middle" }} /> ): ( {Array(5).fill().map((_, index) => ( ))} )}
{subOrgs.length > 0 && (

Sub Organizations of the Current Organization ({subOrgs.length})

{/* */}
{isCloud && ( )} {subOrgs.map((data, index) => { let regiontag = "UK"; let regionCode = "gb"; if (data.region_url?.length > 0) { const regionsplit = data.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"; regionCode = "us"; } else if (regiontag === "frankfurt") { regiontag = "EU-2"; regionCode = "eu"; } else if (regiontag === "ca") { regiontag = "CA"; regionCode = "ca"; } } } return ( } style={{ width: 100, minWidth: 100, maxWidth: 100, display: "table-cell", padding: "8px 8px 8px 20px", textAlign: "center", }} /> {isCloud && ( {regiontag}
} style={{ display: "table-cell", padding: 8, verticalAlign: "middle" }} /> )} } style={{ display: "table-cell", verticalAlign: "middle" }} /> )})}
)}

All Tenants

{/* */}
{isCloud && ( )} {userdata?.orgs?.length <= 0 ? ( [...Array(6)].map((_, rowIndex) => ( {Array(7) .fill() .map((_, colIndex) => ( ))} )) ) : ( userdata?.orgs?.length > 0 && userdata.orgs.map((data, index) => { let regiontag = "UK"; let regionCode = "gb"; if (data.region_url?.length > 0) { const regionsplit = data.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"; regionCode = "us"; } else if (regiontag === "frankfurt") { regiontag = "EU-2"; regionCode = "eu"; } else if (regiontag === "ca") { regiontag = "CA"; regionCode = "ca"; } } } return ( } style={{ width: 100, minWidth: 100, maxWidth: 100, display: "table-cell", padding: "8px 8px 8px 20px", textAlign: "center", }} /> {isCloud ? ( {regiontag}
} style={{ display: "table-cell", padding: 8, verticalAlign: "middle", }} > ) : null} { handleClickChangeOrg(data?.id); }} > Change Active Org } style={{ display: "table-cell", padding: 8, verticalAlign: "middle", }} > ); }) )}
); }); export default TenantsTab;