Sync from cloud for 2.1.0-rc1
This commit is contained in:
@@ -1463,7 +1463,7 @@ const ActionsList = memo(({
|
||||
<Tooltip title="Go to app" placement="right">
|
||||
<div style={{ display: "flex", alignItems: "center" }}>
|
||||
<img
|
||||
src={openapi?.info["x-logo"]}
|
||||
src={openapi?.info["x-logo"]?.length > 0 ? openapi?.info["x-logo"] : theme?.palette?.defaultImage}
|
||||
width={48}
|
||||
height={48}
|
||||
alt="app logo"
|
||||
|
||||
@@ -83,18 +83,17 @@ const AppAuthTab = memo((props) => {
|
||||
const [appAuthenticationGroupId, setAppAuthenticationGroupId] = React.useState("");
|
||||
const [appAuthenticationGroups, setAppAuthenticationGroups] = React.useState([]);
|
||||
const [appAuthenticationGroupName, setAppAuthenticationGroupName] = React.useState("");
|
||||
const [selectedSubOrg, setSelectedSubOrg] = useState([]);
|
||||
const [appAuthenticationGroupDescription, setAppAuthenticationGroupDescription] = React.useState("");
|
||||
const [appsForAppAuthGroup, setAppsForAppAuthGroup] = React.useState([]);
|
||||
const [searchQuery, setSearchQuery] = React.useState("");
|
||||
const [showAppModal, setShowAppModal] = useState(false)
|
||||
const [selectedAuthId, setSelectedAuthId] = useState("");
|
||||
const [showDistributionPopup, setShowDistributionPopup] = useState(false);
|
||||
const [showAuthenticationLoader, setShowAuthenticationLoader] = useState(true)
|
||||
const [showAppAuthGroupLoader, setShowAppAuthGroupLoader] = useState(true)
|
||||
const { themeMode, supportEmail, brandColor } = useContext(Context)
|
||||
const theme = getTheme(themeMode, brandColor)
|
||||
const changeDistribution = (data) => {
|
||||
//changeDistributed(data, !isDistributed)
|
||||
editAuthenticationConfig(data.id, "suborg_distribute")
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
getAppAuthentication();
|
||||
@@ -214,11 +213,39 @@ const AppAuthTab = memo((props) => {
|
||||
});
|
||||
};
|
||||
|
||||
const editAuthenticationConfig = (id, parentAction) => {
|
||||
const handleSelectSubOrg = (id, action) => {
|
||||
if (action === "all") {
|
||||
const childOrgs = userdata.orgs.filter(
|
||||
(data) => data.creator_org === userdata.active_org.id
|
||||
);
|
||||
setSelectedSubOrg((prev) => {
|
||||
if (prev.length === childOrgs.length) {
|
||||
// If all child orgs are already selected, clear the selection
|
||||
return [];
|
||||
} else {
|
||||
// Otherwise, select all child org IDs
|
||||
return childOrgs.map((data) => data.id);
|
||||
}
|
||||
});
|
||||
} else if (action === "none") {
|
||||
setSelectedSubOrg([]);
|
||||
} else {
|
||||
setSelectedSubOrg((prev) => {
|
||||
if (prev.includes(id)) {
|
||||
return prev.filter((data) => data !== id);
|
||||
} else {
|
||||
return [...prev, id];
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const editAuthenticationConfig = (id, parentAction, selectedSuborgs) => {
|
||||
const data = {
|
||||
id: id,
|
||||
action: parentAction !== undefined && parentAction !== null ? parentAction : "assign_everywhere",
|
||||
}
|
||||
selected_suborgs: selectedSuborgs !== undefined && selectedSuborgs !== null ? selectedSuborgs : [],
|
||||
}
|
||||
|
||||
const url = globalUrl + "/api/v1/apps/authentication/" + id + "/config";
|
||||
|
||||
@@ -240,6 +267,7 @@ const AppAuthTab = memo((props) => {
|
||||
} else {
|
||||
toast("Successfully updated auth!");
|
||||
setSelectedUserModalOpen(false);
|
||||
setShowDistributionPopup(false);
|
||||
setTimeout(() => {
|
||||
getAppAuthentication();
|
||||
}, 1000);
|
||||
@@ -251,6 +279,106 @@ const AppAuthTab = memo((props) => {
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
const changeDistribution = (id, selectedSubOrg) => {
|
||||
|
||||
editAuthenticationConfig(id, "suborg_distribute", [...new Set(selectedSubOrg)])
|
||||
}
|
||||
|
||||
|
||||
const cacheDistributionModal = showDistributionPopup ? (
|
||||
<Dialog
|
||||
open={showDistributionPopup}
|
||||
onClose={() => {setShowDistributionPopup(false);setSelectedAuthId("")}}
|
||||
PaperProps={{
|
||||
sx: {
|
||||
borderRadius: theme?.palette?.DialogStyle?.borderRadius,
|
||||
border: theme?.palette?.DialogStyle?.border,
|
||||
fontFamily: theme?.typography?.fontFamily,
|
||||
backgroundColor: theme?.palette?.DialogStyle?.backgroundColor,
|
||||
zIndex: 1000,
|
||||
minWidth: "600px",
|
||||
minHeight: "320px",
|
||||
overflow: "auto",
|
||||
'& .MuiDialogContent-root': {
|
||||
backgroundColor: theme?.palette?.DialogStyle?.backgroundColor,
|
||||
},
|
||||
'& .MuiDialogTitle-root': {
|
||||
backgroundColor: theme?.palette?.DialogStyle?.backgroundColor,
|
||||
},
|
||||
'& .MuiDialogActions-root': {
|
||||
backgroundColor: theme?.palette?.DialogStyle?.backgroundColor,
|
||||
},
|
||||
},
|
||||
}}
|
||||
>
|
||||
<DialogTitle>
|
||||
<Typography variant="h5" color="textPrimary">
|
||||
Select sub-org to distribute Datastore key
|
||||
</Typography>
|
||||
</DialogTitle>
|
||||
<DialogContent style={{ color: "rgba(255,255,255,0.65)" }}>
|
||||
<MenuItem value="none" onClick={()=> {handleSelectSubOrg(null, "none")}}>None</MenuItem>
|
||||
<MenuItem value="all" onClick={()=> {handleSelectSubOrg(null, "all")}}>All</MenuItem>
|
||||
{userdata.orgs.map((data, index) => {
|
||||
if (data.creator_org !== userdata.active_org.id) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const imagesize = 22;
|
||||
const imageStyle = {
|
||||
width: imagesize,
|
||||
height: imagesize,
|
||||
pointerEvents: "none",
|
||||
marginRight: 10,
|
||||
marginLeft: data.id === userdata.active_org.id ? 0 : 20,
|
||||
};
|
||||
|
||||
const image = data.image === "" ? (
|
||||
<img alt={data.name} src={theme.palette.defaultImage} style={imageStyle} />
|
||||
) : (
|
||||
<img alt={data.name} src={data.image} style={imageStyle} />
|
||||
);
|
||||
|
||||
return (
|
||||
<MenuItem
|
||||
key={index}
|
||||
value={data.id}
|
||||
onClick={() => handleSelectSubOrg(data.id)}
|
||||
style={{ display: "flex", alignItems: "center" }}
|
||||
>
|
||||
<Checkbox
|
||||
checked={selectedSubOrg.includes(data.id)}
|
||||
/>
|
||||
{image}
|
||||
<span style={{ marginLeft: 8 }}>{data.name}</span>
|
||||
</MenuItem>
|
||||
);
|
||||
})}
|
||||
|
||||
<div style={{ display: "flex", marginTop: 20 }}>
|
||||
<Button
|
||||
style={{ borderRadius: "2px", textTransform: 'none', fontSize:16, color: theme.palette.primary.main }}
|
||||
onClick={() => {setShowDistributionPopup(false); setSelectedAuthId("")}}
|
||||
color="primary"
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
variant="contained"
|
||||
style={{ borderRadius: "2px", textTransform: 'none', fontSize:16, marginLeft: 10 }}
|
||||
onClick={() => {
|
||||
changeDistribution(selectedAuthId, selectedSubOrg);
|
||||
}}
|
||||
color="primary"
|
||||
>
|
||||
Submit
|
||||
</Button>
|
||||
</div>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
) : null;
|
||||
|
||||
const editAuthenticationModal = selectedAuthenticationModalOpen ? (
|
||||
<Dialog
|
||||
open={selectedAuthenticationModalOpen}
|
||||
@@ -857,6 +985,7 @@ const AppAuthTab = memo((props) => {
|
||||
return (
|
||||
<div style={{width: "100%", minHeight: 1100, maxHeight: 1700, overflowY: "auto", scrollbarColor: theme.palette.scrollbarColorTransparent, scrollbarWidth: 'thin',boxSizing: 'border-box', padding: "27px 10px 19px 27px", height:"100%", backgroundColor: theme.palette.platformColor,borderTopRightRadius: '8px', borderBottomRightRadius: 8, borderLeft: theme.palette.defaultBorder, }}>
|
||||
{appModal}
|
||||
{cacheDistributionModal}
|
||||
<div style={{ height: "100%", width: "calc(100% - 20px)", scrollbarColor: theme.palette.scrollbarColorTransparent, scrollbarWidth: 'thin'}}>
|
||||
<div style={{ width: 'auto', display:'flex',}}>
|
||||
<div style={{display: 'flex', flexDirection: 'column'}}>
|
||||
@@ -1004,7 +1133,7 @@ const AppAuthTab = memo((props) => {
|
||||
];
|
||||
}
|
||||
|
||||
const isDistributed = data.suborg_distributed === true ? true : false;
|
||||
const isDistributed = data?.suborg_distribution?.length > 0 || data?.suborg_distributed ? true : false;
|
||||
var validIcon = <CheckCircleIcon style={{ color: "green" }} />
|
||||
if (data.validation !== null && data.validation !== undefined && data.validation.valid === false) {
|
||||
|
||||
@@ -1260,7 +1389,23 @@ const AppAuthTab = memo((props) => {
|
||||
style={{ }}
|
||||
color="secondary"
|
||||
onClick={() => {
|
||||
changeDistribution(data, !isDistributed)
|
||||
setShowDistributionPopup(true)
|
||||
if(data?.suborg_distribution?.length > 0){
|
||||
setSelectedSubOrg(data.suborg_distribution)
|
||||
}else{
|
||||
setSelectedSubOrg([])
|
||||
}
|
||||
setSelectedAuthId(data.id)
|
||||
if (data?.suborg_distributed) {
|
||||
const allSuborg = userdata?.orgs?.map((data, index) => {
|
||||
if (data.creator_org !== userdata.active_org.id) {
|
||||
return null;
|
||||
}
|
||||
return data.id;
|
||||
})
|
||||
setSelectedSubOrg(allSuborg.filter((data) => data !== null))
|
||||
}
|
||||
|
||||
}}
|
||||
/>
|
||||
</Tooltip>
|
||||
|
||||
@@ -33,7 +33,7 @@ const Branding = (props) => {
|
||||
//const alert = useAlert();
|
||||
const [publishingInfo, setPublishingInfo] = useState("");
|
||||
const [publishRequirements, setPublishRequirements] = useState([])
|
||||
const [currentSelectedTheme, setCurrentSelectedTheme] = useState("dark");
|
||||
const [currentSelectedTheme, setCurrentSelectedTheme] = useState(themeMode);
|
||||
const [integrationPartner, setIntegrationPartner] = useState(false);
|
||||
const [changingTheme, setChangingTheme] = useState(false);
|
||||
const theme = getTheme(themeMode, brandColor)
|
||||
@@ -190,6 +190,13 @@ const Branding = (props) => {
|
||||
})
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (userdata && userdata?.active_org && userdata?.active_org?.branding?.theme?.length > 0) {
|
||||
console.log("Setting current selected theme from userdata", userdata?.active_org?.branding?.theme);
|
||||
setCurrentSelectedTheme(userdata?.active_org?.branding?.theme);
|
||||
}
|
||||
},[userdata]);
|
||||
|
||||
// Should enable / disable org branding
|
||||
const handleChangePublishing = () => {
|
||||
console.log("Handle change publishing");
|
||||
@@ -247,10 +254,6 @@ const Branding = (props) => {
|
||||
setCurrentSelectedTheme(userdata?.active_org?.branding.theme);
|
||||
}
|
||||
|
||||
if (userdata.support) {
|
||||
setCurrentSelectedTheme(localStorage.getItem("theme") || "dark");
|
||||
}
|
||||
|
||||
if (
|
||||
selectedOrganization &&
|
||||
selectedOrganization?.branding?.brand_color &&
|
||||
|
||||
@@ -213,9 +213,16 @@ const CacheView = memo((props) => {
|
||||
const cache = {
|
||||
key: dataValue.key,
|
||||
value: value,
|
||||
category: selectedCategory,
|
||||
category: selectedCategory,
|
||||
}
|
||||
|
||||
if (listCache.length > 0) {
|
||||
const selectedCache = listCache.find((data) => data.key === dataValue.key);
|
||||
if (selectedCache?.suborg_distribution?.length > 0) {
|
||||
cache.suborg_distribution = selectedCache.suborg_distribution;
|
||||
}
|
||||
}
|
||||
|
||||
setCacheInput([cache]);
|
||||
|
||||
fetch(globalUrl + `/api/v1/orgs/${orgId}/set_cache`, {
|
||||
@@ -805,7 +812,7 @@ const CacheView = memo((props) => {
|
||||
}}
|
||||
>
|
||||
<AddIcon/>
|
||||
Category (beta)
|
||||
Category
|
||||
</Button>
|
||||
</Tooltip>
|
||||
}
|
||||
|
||||
@@ -212,13 +212,7 @@ const EditWorkflow = (props) => {
|
||||
//minWidth: isMobile ? "90%" : newWorkflow === true ? 1000 : 550,
|
||||
//maxWidth: isMobile ? "90%" : newWorkflow === true ? 1000 : 550,
|
||||
borderRadius: theme.palette.DialogStyle.borderRadius,
|
||||
backgroundColor: theme?.palette?.DialogStyle?.backgroundColor,
|
||||
'& .MuiDialogContent-root': {
|
||||
backgroundColor: theme?.palette?.DialogStyle?.backgroundColor,
|
||||
},
|
||||
'& .MuiDialogTitle-root': {
|
||||
backgroundColor: theme?.palette?.DialogStyle?.backgroundColor,
|
||||
},
|
||||
backgroundColor: themeMode === "dark" ? "black" : theme?.palette?.DialogStyle?.backgroundColor,
|
||||
},
|
||||
}}
|
||||
>
|
||||
@@ -299,10 +293,10 @@ const EditWorkflow = (props) => {
|
||||
right: 20,
|
||||
bottom: 0,
|
||||
zIndex: 1002,
|
||||
backgroundColor: theme.palette.DialogStyle.backgroundColor,
|
||||
height: 75,
|
||||
paddingTop: 20,
|
||||
paddingLeft: 30,
|
||||
backgroundColor: themeMode === "dark" ? "#262626" : theme.palette.DialogStyle.backgroundColor,
|
||||
}}>
|
||||
<Button
|
||||
variant="contained"
|
||||
@@ -1292,7 +1286,7 @@ const EditWorkflow = (props) => {
|
||||
|
||||
|
||||
{newWorkflow === true ?
|
||||
<span style={{ paddingTop: 30, backgroundColor: theme.palette.DialogStyle.backgroundColor }}>
|
||||
<span style={{ paddingTop: 30 }}>
|
||||
<Typography variant="h6" style={{ marginLeft: 30, paddingBottom: 0, }}>
|
||||
Relevant Workflows
|
||||
</Typography>
|
||||
|
||||
@@ -117,6 +117,14 @@ const LeftSideBar = ({ userdata, serverside, globalUrl, notifications, }) => {
|
||||
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 (
|
||||
@@ -436,11 +444,7 @@ const LeftSideBar = ({ userdata, serverside, globalUrl, notifications, }) => {
|
||||
response.json().then((responseJson) => {
|
||||
if (responseJson["success"] === false) {
|
||||
toast("Failed updating org: ", responseJson.reason);
|
||||
} else {
|
||||
handleThemeChange(newTheme)
|
||||
setCurrentSelectedTheme(newTheme);
|
||||
}
|
||||
|
||||
}
|
||||
})
|
||||
)
|
||||
.catch((error) => {
|
||||
@@ -586,6 +590,8 @@ const LeftSideBar = ({ userdata, serverside, globalUrl, notifications, }) => {
|
||||
if (newTheme === currentSelectedTheme) {
|
||||
return;
|
||||
}
|
||||
handleThemeChange(newTheme)
|
||||
setCurrentSelectedTheme(newTheme);
|
||||
if (userdata?.org_status?.includes("integration_partner")){
|
||||
handleChangeTheme(newTheme);
|
||||
} else {
|
||||
|
||||
@@ -3750,41 +3750,46 @@ const ParsedAction = (props) => {
|
||||
boxShadow={2}
|
||||
backgroundColor={theme.palette.textFieldStyle}
|
||||
display="flex"
|
||||
height={"100%"}
|
||||
flexDirection="column"
|
||||
>
|
||||
<Box display="flex" alignItems="center" justifyContent="space-between">
|
||||
<Typography variant="body1" style={{ flexGrow: 1 }}>
|
||||
<Typography sx={{fontSize: "16px"}} style={{ flexGrow: 1 }}>
|
||||
{tmpitem.charAt(0).toUpperCase() + tmpitem.slice(1)}
|
||||
</Typography>
|
||||
<IconButton size="small"
|
||||
{/* <IconButton size="small"
|
||||
onClick={() => {
|
||||
setUiBox("closed")
|
||||
}}
|
||||
>
|
||||
<CloseIcon fontSize="small" />
|
||||
</IconButton>
|
||||
</IconButton> */}
|
||||
</Box>
|
||||
<Divider sx={{ backgroundColor: theme.palette.surfaceColor, marginTop: "5px", marginBottom: "10px", height: "3px" }} />
|
||||
<Divider sx={{ backgroundColor: theme.palette.surfaceColor, marginTop: "5px", marginBottom: "10px", height: "1px" }} />
|
||||
<Box display="flex" flexDirection="column">
|
||||
<Typography variant="body2" mb={0.5}>
|
||||
<Typography sx={{fontSize: "14px"}} mb={0.5}>
|
||||
<strong>Required:</strong> {data.required === true || data.configuration === true ? "True" : "False"}
|
||||
</Typography>
|
||||
<Typography variant="body2" mb={0.5}>
|
||||
<strong>Description:</strong> {description}
|
||||
</Typography>
|
||||
<Typography variant="body2">
|
||||
{
|
||||
data.description !== undefined && data.description !== null && data.description.length > 0 ?
|
||||
<Typography sx={{fontSize: "14px"}} mb={0.5}>
|
||||
<strong>Description:</strong> {description}
|
||||
</Typography>
|
||||
: null
|
||||
}
|
||||
<Typography sx={{fontSize: "14px"}}>
|
||||
<strong>Ex. :</strong> {data?.example?.length > 0 ? data.example : "No example available"}
|
||||
</Typography>
|
||||
{
|
||||
data?.configuration === true ?
|
||||
(
|
||||
<Typography variant="body2" mt={0.5}>
|
||||
<Typography sx={{fontSize: "14px"}} mt={0.5}>
|
||||
<strong>Auth: </strong>Use "\$" instead of "$"
|
||||
</Typography>
|
||||
) : null
|
||||
}
|
||||
|
||||
<div onClick={(e) => {
|
||||
{/* <div onClick={(e) => {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
|
||||
@@ -3794,7 +3799,7 @@ const ParsedAction = (props) => {
|
||||
<Typography style={{ marginTop: 10, color: "#FF8544", cursor: "pointer", }} variant="body2">
|
||||
Don't show again
|
||||
</Typography>
|
||||
</div>
|
||||
</div> */}
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
@@ -4734,8 +4739,9 @@ const ParsedAction = (props) => {
|
||||
{isFirstOptional ? <Divider style={{ backgroundColor: "rgba(255,255,255,0.1)", marginBottom: 20, }} /> : null}
|
||||
{showButtonField === true ? hideBodyButtonValue : null}
|
||||
<div
|
||||
style={{ marginTop: 18, marginBottom: 0, display: "flex" }}
|
||||
style={{ marginTop: 18, marginBottom: "4px", display: "flex", width: "100%", justifyContent: "space-between", alignItems: "center"}}
|
||||
>
|
||||
<div style={{display: "flex", alignItems: "center", justifyContent: "flex-start"}}>
|
||||
{data.configuration === true ? (
|
||||
<Tooltip
|
||||
title={buttonTitle}
|
||||
@@ -4794,28 +4800,59 @@ const ParsedAction = (props) => {
|
||||
<StorageIcon style={{
|
||||
color: "#FF8544",
|
||||
marginRight: 10,
|
||||
marginBottom: "-5px",
|
||||
}} />
|
||||
</a>
|
||||
</Tooltip>
|
||||
: null}
|
||||
|
||||
<div
|
||||
style={{
|
||||
flex: "10",
|
||||
marginTop: "auto",
|
||||
marginBottom: "auto",
|
||||
color: theme.palette.textPrimary,
|
||||
<Tooltip
|
||||
title={tooltipDescription}
|
||||
placement="left"
|
||||
sx={{
|
||||
zIndex: 0,
|
||||
}}
|
||||
PopperProps={{
|
||||
sx: {
|
||||
'& .MuiTooltip-tooltip': {
|
||||
backgroundColor: 'transparent',
|
||||
boxShadow: 'none',
|
||||
},
|
||||
'& .MuiTooltip-arrow': {
|
||||
color: 'transparent',
|
||||
},
|
||||
},
|
||||
modifiers: [
|
||||
{
|
||||
name: 'offset',
|
||||
options: {
|
||||
offset: (data?.configuration || showCacheConfig || hasAutocomplete) ? [0, 31] : [0,0]
|
||||
},
|
||||
},
|
||||
],
|
||||
}}
|
||||
>
|
||||
{tmpitem} <span style={{ color: theme.palette.main }}>{selectedActionParameters[count].required || selectedActionParameters[count].configuration ? "*" : ""}</span>
|
||||
</div>
|
||||
<Typography
|
||||
sx={{
|
||||
marginTop: "auto",
|
||||
width: "fit-content",
|
||||
cursor: "pointer",
|
||||
color: theme.palette.textPrimary,
|
||||
fontFamily: theme.typography.fontFamily,
|
||||
"&:hover": {
|
||||
color: theme.palette.main,
|
||||
},
|
||||
}}
|
||||
>
|
||||
{tmpitem} <span style={{ color: theme.palette.main }}>{selectedActionParameters[count].required || selectedActionParameters[count].configuration ? "*" : ""}</span>
|
||||
</Typography>
|
||||
</Tooltip>
|
||||
|
||||
{parentParamValue !== undefined && parentParamValue !== null && parentParamValue !== "" && parentParamValue !== data.value ?
|
||||
<Tooltip title={`Parent value is different. Click to reset.`} placement="top" arrow>
|
||||
<RestoreIcon
|
||||
style={{
|
||||
marginRight: 10,
|
||||
marginBottom: 5,
|
||||
cursor: "pointer",
|
||||
color: theme.palette.distributionColor,
|
||||
}}
|
||||
@@ -4828,7 +4865,7 @@ const ParsedAction = (props) => {
|
||||
/>
|
||||
</Tooltip>
|
||||
: null}
|
||||
|
||||
</div>
|
||||
|
||||
{((data.options !== undefined && data.options !== null && data.options.length > 0) || (selectedActionParameters[count].options !== undefined && selectedActionParameters[count].options !== null && selectedActionParameters[count].options.length > 0)) ? null :
|
||||
<Tooltip title="Expand editor window" placement="top">
|
||||
|
||||
@@ -76,7 +76,6 @@ const UserManagmentTab = memo((props) => {
|
||||
const [ipSelected, setIpSelected] = React.useState("");
|
||||
const [userLogViewing, setUserLogViewing] = React.useState({});
|
||||
const { themeMode, supportEmail, brandColor } = useContext(Context);
|
||||
|
||||
const theme = getTheme(themeMode, brandColor);
|
||||
|
||||
|
||||
@@ -1359,7 +1358,7 @@ const UserManagmentTab = memo((props) => {
|
||||
}}
|
||||
>
|
||||
<ListItem style={{ width: "100%", padding: "10px 10px 10px 0px", verticalAlign: 'middle', borderBottom: theme.palette.defaultBorder, display: "table-row" }}>
|
||||
{["Region", "Username", /*"API Key",*/ "Role", /*"Active",*/ "Type", "MFA", ...(selectedOrganization?.child_orgs?.length > 0 ? ["Suborgs"]: []), "Actions", "Last Login"].map((header, index) => (
|
||||
{[...(isCloud ? ["Region"] : []), "Username", /*"API Key",*/ "Role", /*"Active",*/ "Type", "MFA", ...(selectedOrganization?.child_orgs?.length > 0 ? ["Suborgs"]: []), "Actions", "Last Login"].map((header, index) => (
|
||||
<ListItemText
|
||||
key={index}
|
||||
primary={header}
|
||||
@@ -1384,7 +1383,7 @@ const UserManagmentTab = memo((props) => {
|
||||
backgroundColor: theme.palette.platformColor,
|
||||
}}
|
||||
>
|
||||
{Array(9)
|
||||
{Array(isCloud ? 7 : 6)
|
||||
.fill()
|
||||
.map((_, colIndex) => (
|
||||
<ListItemText
|
||||
@@ -1485,14 +1484,15 @@ const UserManagmentTab = memo((props) => {
|
||||
return regionCode;
|
||||
};
|
||||
|
||||
const userRegion = data?.user_geo_info?.country?.iso_code?.length > 0 ? data?.user_geo_info?.country?.iso_code : data?.active_org?.region_url?.length > 0 ? getRegionFlag(data?.active_org?.region_url) : "eu";
|
||||
const userRegion = data?.user_geo_info?.country?.iso_code?.length > 0 ? data?.user_geo_info?.country?.iso_code : selectedOrganization?.region_url?.length > 0 ? getRegionFlag(selectedOrganization?.region_url) : "eu";
|
||||
|
||||
return (
|
||||
<ListItem key={index} style={{ backgroundColor: bgColor, display: 'table-row', borderBottomLeftRadius: users?.length - 1 === index ? 8 : 0, borderBottomRightRadius: users?.length - 1 === index ? 8 : 0 }}>
|
||||
<ListItemText
|
||||
{isCloud ? (
|
||||
<ListItemText
|
||||
primary={(<img src={`https://flagcdn.com/48x36/${userRegion.toLowerCase()}.png`} alt={data?.user_geo_info?.country?.iso_code} style={{ marginRight: 30, width: 25, height: 23, }} />)}
|
||||
style={{ display: 'table-cell', verticalAlign: 'middle', textAlign: 'center' }}
|
||||
/>
|
||||
/>) : null}
|
||||
<ListItemText
|
||||
primary={(
|
||||
<Tooltip title={data.username || 'No username available'}>
|
||||
|
||||
@@ -31,6 +31,13 @@ const SSOTab = ({selectedOrganization, userdata, isEditOrgTab, globalUrl, handle
|
||||
const [roleRequired, setRoleRequired] = React.useState(selectedOrganization?.sso_config?.role_required || false);
|
||||
const [showOpenIdCred, setShowOpenIdCred] = React.useState(false);
|
||||
const [showSamlCred, setShowSamlCred] = React.useState(false);
|
||||
const [skipSSOForAdmin, setSkipSSOForAdmin] = React.useState(
|
||||
selectedOrganization?.sso_config === undefined
|
||||
? false
|
||||
: selectedOrganization?.sso_config?.skip_sso_for_admins === undefined
|
||||
? false
|
||||
: selectedOrganization?.sso_config?.skip_sso_for_admins
|
||||
);
|
||||
const [ssoEntrypoint, setSsoEntrypoint] = React.useState(
|
||||
selectedOrganization.sso_config === undefined
|
||||
? ""
|
||||
@@ -127,6 +134,10 @@ const SSOTab = ({selectedOrganization, userdata, isEditOrgTab, globalUrl, handle
|
||||
setRoleRequired(selectedOrganization?.sso_config?.role_required)
|
||||
}
|
||||
|
||||
if (skipSSOForAdmin !== selectedOrganization?.sso_config?.skip_sso_for_admins) {
|
||||
setSkipSSOForAdmin(selectedOrganization?.sso_config?.skip_sso_for_admins)
|
||||
}
|
||||
|
||||
},[selectedOrganization])
|
||||
|
||||
const orgSaveButton = (
|
||||
@@ -170,9 +181,14 @@ const SSOTab = ({selectedOrganization, userdata, isEditOrgTab, globalUrl, handle
|
||||
SSORequired: SSORequired,
|
||||
auto_provision: autoPrivision,
|
||||
role_required: roleRequired,
|
||||
}
|
||||
skip_sso_for_admins: skipSSOForAdmin,
|
||||
},
|
||||
undefined,
|
||||
{},
|
||||
"sso_config"
|
||||
)
|
||||
}
|
||||
|
||||
>
|
||||
Save Changes
|
||||
{/* <SaveIcon /> */}
|
||||
@@ -206,12 +222,9 @@ const SSOTab = ({selectedOrganization, userdata, isEditOrgTab, globalUrl, handle
|
||||
openidAuthorization === "" &&
|
||||
openidToken === ""
|
||||
) {
|
||||
if (!autoPrivision) {
|
||||
toast.error(
|
||||
"Please fill in fields for either OpenID connect or SSO before continuing. "
|
||||
);
|
||||
return;
|
||||
}
|
||||
toast.error(
|
||||
"Please fill in fields for either OpenID connect or SSO before continuing. "
|
||||
);
|
||||
} else {
|
||||
setAutoProvision((prev)=> !prev);
|
||||
toast.info("Toggled Auto Provisioning. Remember to save.");
|
||||
@@ -232,6 +245,12 @@ const SSOTab = ({selectedOrganization, userdata, isEditOrgTab, globalUrl, handle
|
||||
toast.info("Toggled Role Required. Remember to save.");
|
||||
}
|
||||
}
|
||||
|
||||
const handlechangeSkipSSOForAdmin = (event) => {
|
||||
|
||||
setSkipSSOForAdmin((prev) => !prev);
|
||||
toast.info("Toggled Skip SSO for Admins. Remember to save.");
|
||||
};
|
||||
|
||||
const HandleTestSSO = () => {
|
||||
const url = `${globalUrl}/api/v1/orgs/${selectedOrganization?.id}/change`;
|
||||
@@ -385,6 +404,35 @@ const SSOTab = ({selectedOrganization, userdata, isEditOrgTab, globalUrl, handle
|
||||
</div>
|
||||
|
||||
</div>
|
||||
{userdata && userdata?.active_org?.creator_org?.length > 0 ? null :
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
width: "100%",
|
||||
justifyContent: 'flex-start',
|
||||
marginTop: 30
|
||||
}}
|
||||
>
|
||||
<Typography
|
||||
variant="body2"
|
||||
color="textSecondary"
|
||||
style={{ marginTop: 5, marginBottom: 5, color: "rgba(158, 158, 158, 1)", fontSize: 16, fontFamily: "var(--zds-typography-base,Inter,Helvetica,arial,sans-serif)", fontWeight: 400 }}
|
||||
>
|
||||
Skip SSO for Admins. When enabled, parent org admins will be able switch to the sub-organization without SSO.
|
||||
</Typography>
|
||||
<div>
|
||||
<Switch
|
||||
checked={skipSSOForAdmin}
|
||||
onChange={handlechangeSkipSSOForAdmin}
|
||||
sx={{marginBottom: 0.6, marginTop: 0.6}}
|
||||
name="onOffSwitch"
|
||||
color="primary"
|
||||
title="Disable auto-provisioning of users in SSO"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<div
|
||||
style={{
|
||||
|
||||
@@ -237,7 +237,8 @@ const Admin2 = (props) => {
|
||||
defaults,
|
||||
sso_config,
|
||||
lead_info,
|
||||
{ mfa_required } = {}
|
||||
{ mfa_required } = {},
|
||||
editing,
|
||||
) => {
|
||||
const data = {
|
||||
name: name,
|
||||
@@ -248,6 +249,7 @@ const Admin2 = (props) => {
|
||||
sso_config: sso_config,
|
||||
lead_info: lead_info,
|
||||
mfa_required: mfa_required !== undefined ? mfa_required : selectedOrganization?.mfa_required,
|
||||
editing: editing?.length > 0 ? editing : "",
|
||||
};
|
||||
|
||||
const url = globalUrl + `/api/v1/orgs/${selectedOrganization.id}`;
|
||||
|
||||
@@ -1973,7 +1973,7 @@ const AppCreator = (defaultprops) => {
|
||||
// Saving the app that's been configured.
|
||||
// Save SAVE app
|
||||
const submitApp = () => {
|
||||
toast("Uploading and building app " + name);
|
||||
toast.info("Uploading and building app " + name + ". This may take a minute or two.");
|
||||
setAppBuilding(true);
|
||||
setErrorCode("");
|
||||
|
||||
@@ -2600,15 +2600,23 @@ const AppCreator = (defaultprops) => {
|
||||
}
|
||||
|
||||
if (setExtraAuth.length > 0) {
|
||||
const invalidfieldnames = ["apikey", "username", "password", "username_basic", "password_basic", "url", "access_token"]
|
||||
for (let authkey in extraAuth) {
|
||||
const curauth = extraAuth[authkey];
|
||||
|
||||
if (curauth.name.length === 0 || curauth.name.toLowerCase() == "url") {
|
||||
toast("Can't add extra auth with empty name or Name URL");
|
||||
setAppBuilding(false);
|
||||
return;
|
||||
}
|
||||
|
||||
// Additional comparisonchecks
|
||||
if (authenticationOption !== "No authentication" && authenticationOption !== "") {
|
||||
if (invalidfieldnames.includes(curauth.name.toLowerCase())) {
|
||||
toast.warn("Skipping extra auth field: " + curauth.name + ". This is not valid.")
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
data.components.securitySchemes[curauth.name] = {
|
||||
type: "apiKey",
|
||||
in: curauth.type,
|
||||
@@ -2662,9 +2670,15 @@ const AppCreator = (defaultprops) => {
|
||||
if (responseJson.reason !== undefined) {
|
||||
setErrorCode(responseJson.reason);
|
||||
|
||||
toast.error("Failed to build: " + responseJson.reason, {
|
||||
autoClose: 10000
|
||||
})
|
||||
if (responseJson.details !== undefined && responseJson.details !== null) {
|
||||
toast.error("Failed to build - contact support@shuffler.io: " + responseJson.details, {
|
||||
autoClose: 60000
|
||||
})
|
||||
} else {
|
||||
toast.error("Failed to build: " + responseJson.reason, {
|
||||
autoClose: 10000
|
||||
})
|
||||
}
|
||||
}
|
||||
} else {
|
||||
toast.success("Successfully built openapi app! Added job to rebuild it in your hybrid runtime locations (Orborus).");
|
||||
@@ -2678,7 +2692,7 @@ const AppCreator = (defaultprops) => {
|
||||
.catch((error) => {
|
||||
setAppBuilding(false);
|
||||
setErrorCode(error.toString());
|
||||
toast(error.toString());
|
||||
toast.error(error.toString());
|
||||
});
|
||||
};
|
||||
|
||||
@@ -2810,10 +2824,21 @@ const AppCreator = (defaultprops) => {
|
||||
margin="normal"
|
||||
variant="outlined"
|
||||
defaultValue={extraAuth[index].name}
|
||||
helperText={
|
||||
<Typography variant="caption" style={{ color: theme.palette.error.main, marginTop: 10, marginBottom: 10, }}>
|
||||
{extraAuth[index]?.name?.toLowerCase() === "url"
|
||||
|| extraAuth[index]?.name?.toLowerCase() === "apikey"
|
||||
? `ERROR: Invalid key: ${extraAuth[index].name}. ` : ""}
|
||||
</Typography>
|
||||
}
|
||||
onChange={(e) => {
|
||||
extraAuth[index].name = e.target.value;
|
||||
setExtraAuth(extraAuth);
|
||||
}}
|
||||
onBlur={(e) => {
|
||||
// Forcerender
|
||||
setUpdate(Math.random());
|
||||
}}
|
||||
InputProps={{
|
||||
classes: {
|
||||
notchedOutline: classes.notchedOutline,
|
||||
@@ -5865,7 +5890,9 @@ const AppCreator = (defaultprops) => {
|
||||
</h2>
|
||||
</Link>
|
||||
<h2>
|
||||
{name}{" "}
|
||||
<Link to={props?.match?.params?.appid !== undefined && props?.match?.params?.appid !== null && props?.match?.params?.appid.length > 0 ? `/apps/${props?.match?.params?.appid}` : "/apps" } style={{ textDecoration: "none", color: theme.palette.text.primary }}>
|
||||
{name}{" "}
|
||||
</Link>
|
||||
{actions === null ||
|
||||
actions === undefined ||
|
||||
actions.length === 0 ? null : (
|
||||
|
||||
@@ -3121,12 +3121,12 @@ const buttonBackground = "linear-gradient(to right, #f86a3e, #f34079)";
|
||||
style={{ marginBottom: 0, marginLeft: 0, marginRight: 0, minWidth: 800, maxWidth: 800, margin: "auto", }}
|
||||
aria-label="disabled tabs example"
|
||||
>
|
||||
<Tab style={{marginLeft: 0, color: theme.palette.text.primary }} icon={<DescriptionIcon />} label="Docs" />
|
||||
<Tab icon={appType === 0 || appType === 2 ? <OpenInNewIcon /> : <AppsIcon />} label={appType === 0 || appType === 2 ? "Explore the API" : "Try it out"} />
|
||||
<Tab style={{marginLeft: 0, color: theme.palette.text.primary, textTransform: "none",}} icon={<DescriptionIcon />} label="Docs" />
|
||||
<Tab style={{color: theme.palette.text.primary, textTransform: "none", }} icon={appType === 0 || appType === 2 ? <OpenInNewIcon /> : <AppsIcon />} label={appType === 0 || appType === 2 ? "Try the API" : "Try it out"} />
|
||||
|
||||
<Tab icon={<ShowChartIcon />} style={{color: theme.palette.text.primary}} label="Stats" />
|
||||
<Tab icon={<PolylineIcon />} disabled style={{color: theme.palette.text.secondary}} label="Integrations" />
|
||||
<Tab icon={<PersonIcon />} disabled={userdata.support !== true} style={{color: userdata.support !== true ? theme.palette.text.secondary: theme.palette.text.primary}} label="Creator" value={4} />
|
||||
<Tab icon={<ShowChartIcon />} style={{color: theme.palette.text.primary, textTransform: "none", }} label="Stats & Downloads" />
|
||||
<Tab icon={<PolylineIcon />} style={{color: theme.palette.text.primary, textTransform: "none", }} disabled style={{color: theme.palette.text.secondary}} label="Integrations" />
|
||||
<Tab icon={<PersonIcon />} disabled={userdata.support !== true} style={{color: userdata.support !== true ? theme.palette.text.secondary: theme.palette.text.primary, textTransform: "none", }} label="Creator" value={4} />
|
||||
</Tabs>
|
||||
<div style={{ marginTop: 25 }}>
|
||||
{selectedTab === 1 && app.skipped_build == false ? (
|
||||
@@ -3135,8 +3135,8 @@ const buttonBackground = "linear-gradient(to right, #f86a3e, #f34079)";
|
||||
<SelectedActionView action={currentAction} />
|
||||
</div>
|
||||
<div style={{ marginLeft: 25, maxWidth: 350 }}>
|
||||
{currentAction.description !== undefined && currentAction.description !== null && currentAction.description !== "" ?
|
||||
<div
|
||||
{currentAction.description !== undefined && currentAction.description !== null && currentAction.description !== "" ?
|
||||
<div
|
||||
style={{
|
||||
maxHeight: 175,
|
||||
overflowX: "hidden",
|
||||
@@ -3253,11 +3253,11 @@ const buttonBackground = "linear-gradient(to right, #f86a3e, #f34079)";
|
||||
Use the App onprem (hybrid)
|
||||
</Typography>
|
||||
<Typography variant="body2" color="textSecondary" style={{marginTop: 5, }}>
|
||||
Due to using docker containers with privately uploaded containers, we had to use a custom registry. Use the command below to download the image to the server if it fails to run.
|
||||
Custom uses a custom Docker registry for private containers. Use the command below to download the app image to a server if it fails to do so automatically.
|
||||
|
||||
It will authenticate and authorize you, before redirecting to a Signed URL on https://storage.googleapis.com
|
||||
The downloadable image may not be ready until 5 minutes after the app was built.
|
||||
|
||||
<b> Now also works for ARM containers!</b>
|
||||
<b> Now also works for ARM containers (?arch=arm)!</b>
|
||||
</Typography>
|
||||
|
||||
<div
|
||||
@@ -4027,7 +4027,7 @@ const buttonBackground = "linear-gradient(to right, #f86a3e, #f34079)";
|
||||
</IconButton>
|
||||
) : null}
|
||||
|
||||
{selectedOrganization !== undefined && selectedOrganization !== null && selectedOrganization.id !== undefined && userdata.support === true ?
|
||||
{selectedOrganization !== undefined && selectedOrganization !== null && selectedOrganization.id !== undefined ?
|
||||
// Iconbutton for authentication with just an icon. Link to /apps/authentication?app_id=app.id
|
||||
<IconButton
|
||||
color="secondary"
|
||||
@@ -4165,7 +4165,7 @@ const buttonBackground = "linear-gradient(to right, #f86a3e, #f34079)";
|
||||
style={{ height: 40, marginTop: 5, marginLeft: 5, }}
|
||||
>
|
||||
<OpenInNewIcon style={{marginRight: 5, }}/>
|
||||
Explore API
|
||||
Try the API
|
||||
</Button>
|
||||
</a>
|
||||
<Select
|
||||
|
||||
@@ -191,6 +191,7 @@ const SetAuthentication = (props) => {
|
||||
appAuthentication={appAuthentication} />}
|
||||
</Typography>
|
||||
|
||||
{/*
|
||||
<Typography variant="h6" style={{ marginTop: 50, marginBottom: 20, }}>
|
||||
What can they do with this?
|
||||
</Typography>
|
||||
@@ -217,6 +218,7 @@ const SetAuthentication = (props) => {
|
||||
</div>
|
||||
</div>
|
||||
</Typography>
|
||||
*/}
|
||||
</div>
|
||||
<>
|
||||
<div style={{ height: 100, }}></div>
|
||||
|
||||
Reference in New Issue
Block a user