Merge pull request #1342 from satti-hari-krishna-reddy/subOrg

added a way to get sub orgs of the current org
This commit is contained in:
Frikky
2024-03-15 14:39:57 +01:00
committed by GitHub
2 changed files with 350 additions and 12 deletions
+2 -1
View File
@@ -4929,7 +4929,8 @@ func initHandlers() {
r.HandleFunc("/api/v1/orgs/{orgId}/change", shuffle.HandleChangeUserOrg).Methods("POST", "OPTIONS") // Swaps to the org
r.HandleFunc("/api/v1/orgs/{orgId}", shuffle.HandleDeleteOrg).Methods("DELETE", "OPTIONS")
r.HandleFunc("/api/v1/orgs/{orgId}/suborgs", shuffle.HandleGetSubOrgs).Methods("GET", "OPTIONS")
// This is a new API that validates if a key has been seen before.
// Not sure what the best course of action is for it.
r.HandleFunc("/api/v1/environments/{key}/stop", shuffle.HandleStopExecutions).Methods("GET", "POST", "OPTIONS")
+348 -11
View File
@@ -160,6 +160,8 @@ const Admin = (props) => {
const [loginInfo, setLoginInfo] = React.useState("");
const [curTab, setCurTab] = React.useState(0);
const [users, setUsers] = React.useState([]);
const [subOrgs, setSubOrgs] = useState([]);
const [parentOrg, setParentOrg] = React.useState(null);
const [organizations, setOrganizations] = React.useState([]);
const [orgSyncResponse, setOrgSyncResponse] = React.useState("");
const [userSettings, setUserSettings] = React.useState({});
@@ -202,6 +204,14 @@ const Admin = (props) => {
}
}, [isDropzone]);
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 isCloud = window.location.host === "localhost:3002" || window.location.host === "shuffler.io";
const get2faCode = (userId) => {
@@ -1101,6 +1111,92 @@ If you're interested, please let me know a time that works for you, or set up a
});
};
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) {
toast("Failed getting your org. If this persists, please contact support.");
} else {
const { subOrgs, parentOrg } = responseJson;
setSubOrgs(subOrgs);
setParentOrg(parentOrg);
}
})
.catch((error) => {
console.log("Error getting sub orgs: ", error);
toast("Error getting sub organizations");
});
};
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")
}
return response.json();
}).then(function(responseJson) {
if (responseJson.success === true) {
if (responseJson.region_url !== undefined && responseJson.region_url !== null && responseJson.region_url.length > 0) {
console.log("Region Change: ", responseJson.region_url)
localStorage.setItem("globalUrl", responseJson.region_url)
//globalUrl = responseJson.region_url
}
setTimeout(() => {
window.location.reload()
}, 2000)
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 inviteUser = (data) => {
//console.log("INPUT: ", data);
setLoginInfo("");
@@ -4662,6 +4758,13 @@ If you're interested, please let me know a time that works for you, or set up a
</div>
) : null;
const imagesize = 40;
const imageStyle = {
width: imagesize,
height: imagesize,
pointerEvents: "none",
};
const organizationsTab =
curTab === 7 ? (
<div>
@@ -4682,13 +4785,253 @@ If you're interested, please let me know a time that works for you, or set up a
>
Add suborganization
</Button>
<Divider
{parentOrg ? (
<span>
<Divider
style={{
marginTop: 20,
marginBottom: 20,
backgroundColor: theme.palette.inputColor,
}}
/>
<div
style={{
textAlign: "center",
width: "100%",
padding: "10px",
marginTop: 20,
}}
>
<h3
style={{
marginTop: 20,
marginBottom: 20,
backgroundColor: theme.palette.inputColor,
margin: 0,
fontSize: "1.2rem",
fontWeight: "bold",
letterSpacing: "1px",
}}
/>
>
{" "}
Your Parent Organization
</h3>
</div>
<Divider
style={{
marginTop: 20,
marginBottom: 20,
backgroundColor: theme.palette.inputColor,
}}
/>
{(() => {
const image =
parentOrg.image === "" ? (
<img
alt={parentOrg.name}
src={theme.palette.defaultImage}
style={imageStyle}
/>
) : (
<img
alt={parentOrg.name}
src={parentOrg.image}
style={imageStyle}
/>
);
const bgColor = "#27292d";
return (
<List>
<ListItem>
<ListItemText
primary="Logo"
style={{ minWidth: 100, maxWidth: 100 }}
/>
<ListItemText
primary="Name"
style={{ minWidth: 250, maxWidth: 250 }}
/>
<ListItemText
primary="Your role"
style={{ minWidth: 150, maxWidth: 150 }}
/>
<ListItemText
primary="id"
style={{ minWidth: 400, maxWidth: 400 }}
/>
</ListItem>
<ListItem style={{ backgroundColor: bgColor }}>
<ListItemText
primary={image}
style={{ minWidth: 100, maxWidth: 100 }}
/>
<ListItemText
primary={parentOrg.name}
style={{ minWidth: 250, maxWidth: 250 }}
/>
<ListItemText
primary={parentOrg.role}
style={{ minWidth: 150, maxWidth: 150 }}
/>
<ListItemText
primary={parentOrg.id}
style={{ minWidth: 400, maxWidth: 400 }}
/>
<Button
variant="contained"
color="primary"
onClick={() => {
handleClickChangeOrg(parentOrg.id);
}}
>
Switch To Parent
</Button>
</ListItem>
</List>
);
})()}
</span>
) : null
}
{subOrgs.length > 0 ? (
<span>
<Divider
style={{
marginTop: 20,
marginBottom: 20,
backgroundColor: theme.palette.inputColor,
}}
/>
<div
style={{
textAlign: "center",
width: "100%",
padding: "10px",
marginTop: 20,
}}
>
<h3
style={{
margin: 0,
fontSize: "1.2rem",
fontWeight: "bold",
letterSpacing: "1px",
}}
>
Sub Organizations of the Current Organization
</h3>
</div>
<Divider
style={{
marginTop: 20,
marginBottom: 20,
backgroundColor: theme.palette.inputColor,
}}
/>
<List>
<ListItem>
<ListItemText
primary="Logo"
style={{ minWidth: 100, maxWidth: 100 }}
/>
<ListItemText
primary="Name"
style={{ minWidth: 250, maxWidth: 250 }}
/>
<ListItemText
primary="Your role"
style={{ minWidth: 150, maxWidth: 150 }}
/>
<ListItemText primary="id" style={{ minWidth: 400, maxWidth: 400 }} />
</ListItem>
<span>
{subOrgs.map((data, index) => {
const image =
data.image === "" ? (
<img
alt={data.name}
src={theme.palette.defaultImage}
style={imageStyle}
/>
) : (
<img alt={data.name} src={data.image} style={imageStyle} />
);
var bgColor = "#27292d";
if (index % 2 === 0) {
bgColor = "#1f2023";
}
return (
<ListItem key={index} style={{ backgroundColor: bgColor }}>
<ListItemText
primary={image}
style={{ minWidth: 100, maxWidth: 100 }}
/>
<ListItemText
primary={data.name}
style={{ minWidth: 250, maxWidth: 250 }}
/>
<ListItemText
primary={data.role}
style={{ minWidth: 150, maxWidth: 150 }}
/>
<ListItemText
primary={data.id}
style={{ minWidth: 400, maxWidth: 400 }}
/>
<Button
variant="contained"
color="primary"
onClick={() => {
handleClickChangeOrg(data.id);
}}
>
Change Active Org
</Button>
</ListItem>
);
})}
</span>
</List>
</span>
) : null
}
<Divider
style={{
marginTop: 20,
marginBottom: 20,
backgroundColor: theme.palette.inputColor,
}}
/>
<div style={{ textAlign: "center", width: "100%", padding: "10px", marginTop: 20 }}>
<h3
style={{
margin: 0,
fontSize: "1.2rem",
fontWeight: "bold",
letterSpacing: "1px",
}}
>
All Tenants
</h3>
</div>
<Divider
style={{
marginTop: 20,
marginBottom: 20,
backgroundColor: theme.palette.inputColor,
}}
/>
<List>
<ListItem>
<ListItemText
@@ -4728,12 +5071,6 @@ If you're interested, please let me know a time that works for you, or set up a
? "True"
: "False";
const imagesize = 40;
const imageStyle = {
width: imagesize,
height: imagesize,
pointerEvents: "none",
};
const image =
data.image === "" ? (
<img