Synced over a lot of sidebar changes
This commit is contained in:
@@ -92,7 +92,7 @@ const RequestMethods = [
|
||||
},
|
||||
];
|
||||
|
||||
const ApiExplorer = memo(({ openapi, globalUrl, userdata, HandleApiExecution, selectedAppData, ConfigurationTab }) => {
|
||||
const ApiExplorer = memo(({ openapi, globalUrl, userdata, HandleApiExecution, selectedAppData, ConfigurationTab, isLoggedIn, isLoaded }) => {
|
||||
const [actions, setActions] = useState([]);
|
||||
const [info, setInfo] = useState({});
|
||||
const [serverurl, setServerUrl] = useState("");
|
||||
@@ -1265,12 +1265,12 @@ const ApiExplorer = memo(({ openapi, globalUrl, userdata, HandleApiExecution, se
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: 'row',
|
||||
height: userdata?.support ? "auto" : "calc(100vh - 80px)",
|
||||
height: (isLoggedIn && isLoaded) ? "auto" : "calc(100vh - 80px)",
|
||||
}}
|
||||
>
|
||||
<ActionsList info={info} openapi={openapi} userdata={userdata} actions={actions} filteredActions={filteredActions} setFilteredActions={setFilteredActions} selectedActionIndex={selectedActionIndex} setSelectedActionIndex={setSelectedActionIndex} setExampleBody={setExampleBody }/>
|
||||
<ActionsList info={info} openapi={openapi} isLoggedIn={isLoggedIn} isLoaded={isLoaded} userdata={userdata} actions={actions} filteredActions={filteredActions} setFilteredActions={setFilteredActions} selectedActionIndex={selectedActionIndex} setSelectedActionIndex={setSelectedActionIndex} setExampleBody={setExampleBody }/>
|
||||
|
||||
<ActionResponseAndRequest ConfigurationTab={ConfigurationTab} selectedAppData={selectedAppData} HandleApiExecution={HandleApiExecution} userdata={userdata} info={info} filteredActions={filteredActions} setFilteredActions={setFilteredActions} actions={actions} selectedActionIndex={selectedActionIndex} ExampleBody={ExampleBody} setExampleBody={setExampleBody} openapi={openapi} serverurl={serverurl} globalUrl={globalUrl} setSelectedActionIndex={setSelectedActionIndex}/>
|
||||
<ActionResponseAndRequest isLoaded={isLoaded} isLoggedIn={isLoggedIn} ConfigurationTab={ConfigurationTab} selectedAppData={selectedAppData} HandleApiExecution={HandleApiExecution} userdata={userdata} info={info} filteredActions={filteredActions} setFilteredActions={setFilteredActions} actions={actions} selectedActionIndex={selectedActionIndex} ExampleBody={ExampleBody} setExampleBody={setExampleBody} openapi={openapi} serverurl={serverurl} globalUrl={globalUrl} setSelectedActionIndex={setSelectedActionIndex}/>
|
||||
|
||||
</div>
|
||||
);
|
||||
@@ -1279,7 +1279,7 @@ const ApiExplorer = memo(({ openapi, globalUrl, userdata, HandleApiExecution, se
|
||||
export default ApiExplorer;
|
||||
|
||||
|
||||
const ActionResponseAndRequest = memo(({ConfigurationTab, selectedAppData,actions, info, HandleApiExecution, userdata, filteredActions, setFilteredActions, serverurl, globalUrl, setSelectedActionIndex, ExampleBody, setExampleBody, selectedActionIndex}) => {
|
||||
const ActionResponseAndRequest = memo(({ isLoggedIn, isLoaded, ConfigurationTab, selectedAppData,actions, info, HandleApiExecution, userdata, filteredActions, setFilteredActions, serverurl, globalUrl, setSelectedActionIndex, ExampleBody, setExampleBody, selectedActionIndex}) => {
|
||||
const [apiResponse, setApiResponse] = useState({});
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const loadAction = 10;
|
||||
@@ -1366,7 +1366,7 @@ const ActionResponseAndRequest = memo(({ConfigurationTab, selectedAppData,action
|
||||
))}
|
||||
</div>
|
||||
|
||||
<ActionResponse userdata={userdata} apiResponse={apiResponse} ExampleBody={ExampleBody}/>
|
||||
<ActionResponse isLoaded={isLoaded} isLoggedIn={isLoggedIn} apiResponse={apiResponse} ExampleBody={ExampleBody}/>
|
||||
</div>
|
||||
)})
|
||||
|
||||
@@ -1381,6 +1381,8 @@ const ActionsList = memo(({
|
||||
userdata,
|
||||
info,
|
||||
openapi,
|
||||
isLoggedIn,
|
||||
isLoaded
|
||||
}) => {
|
||||
|
||||
const [searchQuery, setSearchQuery] = useState("");
|
||||
@@ -1436,7 +1438,7 @@ const ActionsList = memo(({
|
||||
}
|
||||
};
|
||||
return (
|
||||
<div style={{ maxWidth: '350px', width: "25%", overflow: 'hidden', marginLeft: !userdata.support ? 5 : 0}}>
|
||||
<div style={{ maxWidth: '350px', width: "25%", overflow: 'hidden', marginLeft: !(isLoggedIn || isLoaded) ? 5 : 0}}>
|
||||
<div style={{ borderBottom: '1px solid #494949', paddingTop: 10, paddingBottom: 10}}>
|
||||
<div>
|
||||
{info?.title ? (
|
||||
@@ -1487,7 +1489,7 @@ const ActionsList = memo(({
|
||||
marginTop: 15,
|
||||
backgroundColor: "#1a1a1a",
|
||||
overflowY: "auto",
|
||||
height: userdata?.support ? "calc(100vh - 190px)" : "calc(100vh - 260px)",
|
||||
height: (isLoaded && isLoggedIn) ? "calc(100vh - 190px)" : "calc(100vh - 260px)",
|
||||
paddingRight: 5,
|
||||
}}
|
||||
>
|
||||
@@ -2776,7 +2778,7 @@ const Action = memo((
|
||||
);
|
||||
})
|
||||
|
||||
const ActionResponse = memo(({ apiResponse, ExampleBody, userdata }) => {
|
||||
const ActionResponse = memo(({ apiResponse, ExampleBody, isLoggedIn, isLoaded }) => {
|
||||
const [height, setHeight] = useState("14vh")
|
||||
const [responseTabIndex, setResponseTabIndex] = useState(0)
|
||||
const [oldResponse, setOldResponse] = useState(apiResponse)
|
||||
@@ -2897,7 +2899,7 @@ const ActionResponse = memo(({ apiResponse, ExampleBody, userdata }) => {
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<ApiResponseWrapper userdata={userdata}>
|
||||
<ApiResponseWrapper isLoggedIn={isLoggedIn} isLoaded={isLoaded}>
|
||||
<div
|
||||
style={{
|
||||
width: '100%',
|
||||
@@ -3016,12 +3018,12 @@ const ResponseTabWrapper = memo(({ apiResponse }) => {
|
||||
/>
|
||||
)})
|
||||
|
||||
const PaddingWrapper = memo(({ userdata, children }) => {
|
||||
const PaddingWrapper = memo(({ isLoggedIn, isLoaded, children }) => {
|
||||
const { leftSideBarOpenByClick, windowWidth } = useContext(Context);
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
width: userdata?.support
|
||||
width: (isLoggedIn && isLoaded)
|
||||
? leftSideBarOpenByClick
|
||||
? windowWidth >= 1920 ? "calc(100% - 630px)" : "calc(100% - 570px)"
|
||||
: windowWidth >= 1920 ? "calc(100vw - 460px)": "calc(100% - 410px)"
|
||||
@@ -3042,9 +3044,9 @@ const PaddingWrapper = memo(({ userdata, children }) => {
|
||||
);
|
||||
});
|
||||
|
||||
const ApiResponseWrapper = memo(({ children, userdata }) => {
|
||||
const ApiResponseWrapper = memo(({ children, isLoaded, isLoggedIn }) => {
|
||||
return (
|
||||
<PaddingWrapper userdata={userdata}>
|
||||
<PaddingWrapper isLoggedIn={isLoggedIn} isLoaded={isLoaded}>
|
||||
{children}
|
||||
</PaddingWrapper>
|
||||
);
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { useNavigate } from 'react-router';
|
||||
|
||||
import {
|
||||
Dialog,
|
||||
DialogTitle,
|
||||
@@ -21,17 +23,22 @@ import LaunchIcon from '@mui/icons-material/Launch';
|
||||
import CheckCircleIcon from '@mui/icons-material/CheckCircle';
|
||||
import { CloudDownloadOutlined } from '@mui/icons-material';
|
||||
import { findSpecificApp } from './AppFramework';
|
||||
import theme from "../theme";
|
||||
import YAML from 'yaml';
|
||||
import { toast } from 'react-toastify';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
const AppModal = ({ open, onClose, app, userdata, globalUrl }) => {
|
||||
const AppModal = ({ open, onClose, app, globalUrl }) => {
|
||||
|
||||
const [frameworkData, setFrameworkData] = useState({})
|
||||
const [userdata, setUserdata] = useState({})
|
||||
const [usecases, setUsecases] = useState([])
|
||||
const [workflows, setWorkflows] = useState([])
|
||||
const [prevSubcase, setPrevSubcase] = useState({})
|
||||
const [inputUsecase, setInputUsecase] = useState({})
|
||||
const [latestUsecase, setLatestUsecase] = useState([])
|
||||
const [foundAppUsecase, setFoundAppUsecase] = useState({})
|
||||
|
||||
const navigate = useNavigate();
|
||||
const parseUsecase = (subcase) => {
|
||||
const srcdata = findSpecificApp(frameworkData, subcase.type)
|
||||
const dstdata = findSpecificApp(frameworkData, subcase.last)
|
||||
@@ -48,6 +55,25 @@ const AppModal = ({ open, onClose, app, userdata, globalUrl }) => {
|
||||
return subcase
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
var baseurl = globalUrl;
|
||||
fetch(baseurl + "/api/v1/me", {
|
||||
credentials: "include",
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(responseJson => {
|
||||
if (responseJson.success) {
|
||||
setUserdata(responseJson)
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.log("Failed login check: ", error);
|
||||
});
|
||||
}, [app]);
|
||||
|
||||
|
||||
const getFramework = () => {
|
||||
fetch(globalUrl + "/api/v1/apps/frameworkConfiguration", {
|
||||
@@ -266,6 +292,89 @@ const AppModal = ({ open, onClose, app, userdata, globalUrl }) => {
|
||||
setFoundAppUsecase(foundSubcase);
|
||||
}, [latestUsecase])
|
||||
|
||||
const downloadApp = (inputdata) => {
|
||||
const id = inputdata.id;
|
||||
|
||||
toast("Downloading..");
|
||||
fetch(globalUrl + "/api/v1/apps/" + id + "/config", {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Accept: "application/json",
|
||||
},
|
||||
credentials: "include",
|
||||
})
|
||||
.then((response) => {
|
||||
if (response.status !== 200) {
|
||||
window.location.pathname = "/apps";
|
||||
}
|
||||
|
||||
return response.json();
|
||||
})
|
||||
.then((responseJson) => {
|
||||
if (!responseJson.success) {
|
||||
toast("Failed to download file");
|
||||
} else {
|
||||
console.log(responseJson);
|
||||
const basedata = atob(responseJson.openapi);
|
||||
console.log("BASE: ", basedata);
|
||||
var inputdata = JSON.parse(basedata);
|
||||
console.log("POST INPUT: ", inputdata);
|
||||
inputdata = JSON.parse(inputdata.body);
|
||||
|
||||
const newpaths = {};
|
||||
if (inputdata["paths"] !== undefined) {
|
||||
Object.keys(inputdata["paths"]).forEach(function (key) {
|
||||
newpaths[key.split("?")[0]] = inputdata.paths[key];
|
||||
});
|
||||
}
|
||||
|
||||
inputdata.paths = newpaths;
|
||||
console.log("INPUT: ", inputdata);
|
||||
var name = inputdata.info.title;
|
||||
name = name.replace(/ /g, "_", -1);
|
||||
name = name.toLowerCase();
|
||||
|
||||
delete inputdata.id;
|
||||
delete inputdata.editing;
|
||||
|
||||
const data = YAML.stringify(inputdata);
|
||||
var blob = new Blob([data], {
|
||||
type: "application/octet-stream",
|
||||
});
|
||||
|
||||
var url = URL.createObjectURL(blob);
|
||||
var link = document.createElement("a");
|
||||
link.setAttribute("href", url);
|
||||
link.setAttribute("download", `${name}.yaml`);
|
||||
var event = document.createEvent("MouseEvents");
|
||||
event.initMouseEvent(
|
||||
"click",
|
||||
true,
|
||||
true,
|
||||
window,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
0,
|
||||
null
|
||||
);
|
||||
link.dispatchEvent(event);
|
||||
//link.parentNode.removeChild(link)
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
toast(error.toString());
|
||||
});
|
||||
};
|
||||
|
||||
const isCloud =
|
||||
window.location.host === "localhost:3002" ||
|
||||
window.location.host === "shuffler.io" || window.location.host === "localhost:3000"
|
||||
@@ -280,7 +389,8 @@ const AppModal = ({ open, onClose, app, userdata, globalUrl }) => {
|
||||
newAppname = newAppname?.replaceAll("_", " ");
|
||||
}
|
||||
|
||||
var canEditApp = userdata.admin === "true" || userdata.id === app?.owner || app?.owner === "" || (userdata.admin === "true" && userdata.active_org.id === app?.reference_org) || !app?.generated
|
||||
var canEditApp = userdata.admin === "true" || userdata?.id === app?.owner || app?.owner === "" || (userdata.admin === "true" && userdata.active_org.id === app?.reference_org) || !app?.generated
|
||||
|
||||
|
||||
|
||||
return (
|
||||
@@ -294,7 +404,7 @@ const AppModal = ({ open, onClose, app, userdata, globalUrl }) => {
|
||||
borderRadius: 2,
|
||||
border: "1px solid #494949",
|
||||
minWidth: '440px',
|
||||
fontFamily: "Inter",
|
||||
fontFamily: theme?.typography?.fontFamily,
|
||||
backgroundColor: "#212121",
|
||||
'& .MuiDialogContent-root': {
|
||||
backgroundColor: "#212121",
|
||||
@@ -303,10 +413,10 @@ const AppModal = ({ open, onClose, app, userdata, globalUrl }) => {
|
||||
backgroundColor: "#212121",
|
||||
},
|
||||
'& .MuiTypography-root': {
|
||||
fontFamily: 'Inter, sans-serif',
|
||||
fontFamily: theme?.typography?.fontFamily,
|
||||
},
|
||||
'& .MuiButton-root': {
|
||||
fontFamily: 'Inter, sans-serif',
|
||||
fontFamily: theme?.typography?.fontFamily,
|
||||
},
|
||||
}
|
||||
}}
|
||||
@@ -320,7 +430,7 @@ const AppModal = ({ open, onClose, app, userdata, globalUrl }) => {
|
||||
pt: 2,
|
||||
pl: 3,
|
||||
pr: 2,
|
||||
fontFamily: "Inter"
|
||||
fontFamily: theme?.typography?.fontFamily
|
||||
}}
|
||||
>
|
||||
<Typography component="div" sx={{ fontWeight: 500, color: "#F1F1F1", fontSize: "22px" }}>
|
||||
@@ -340,7 +450,7 @@ const AppModal = ({ open, onClose, app, userdata, globalUrl }) => {
|
||||
<DialogContent sx={{ py: 3, px: 3 }}>
|
||||
<Box sx={{ display: 'flex', alignItems: 'space-between', justifyContent: 'space-between' }}>
|
||||
|
||||
<div style={{ display: "flex", flexDirection: "row", gap: 10, fontFamily: "Inter" }}>
|
||||
<div style={{ display: "flex", flexDirection: "row", gap: 10, fontFamily: theme?.typography?.fontFamily }}>
|
||||
<img
|
||||
alt={app?.name}
|
||||
src={app?.large_image || app?.image_url}
|
||||
@@ -364,11 +474,9 @@ const AppModal = ({ open, onClose, app, userdata, globalUrl }) => {
|
||||
</Typography>
|
||||
{
|
||||
isCloud && (
|
||||
<a
|
||||
rel="noopener noreferrer"
|
||||
href={"https://shuffler.io/apps/" + app?.id}
|
||||
<Link
|
||||
to={"/apps/" + (app?.id || app?.objectID)}
|
||||
style={{ textDecoration: "none", color: "#f85a3e", marginTop: "-2px" }}
|
||||
target="_blank"
|
||||
>
|
||||
<IconButton
|
||||
style={{
|
||||
@@ -378,7 +486,7 @@ const AppModal = ({ open, onClose, app, userdata, globalUrl }) => {
|
||||
>
|
||||
<OpenInNewIcon />
|
||||
</IconButton>
|
||||
</a>
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
@@ -391,23 +499,33 @@ const AppModal = ({ open, onClose, app, userdata, globalUrl }) => {
|
||||
</div>
|
||||
</div>
|
||||
<div style={{ display: "flex", flexDirection: "row", justifyContent: "center", alignItems: "center", gap: 10 }}>
|
||||
<Button
|
||||
variant="contained"
|
||||
sx={{
|
||||
bgcolor: '#494949',
|
||||
'&:hover': { bgcolor: '#494949' },
|
||||
textTransform: 'none',
|
||||
borderRadius: 1,
|
||||
minWidth: '45px',
|
||||
width: '45px',
|
||||
height: '40px',
|
||||
padding: 2,
|
||||
color: "#fff",
|
||||
fontFamily: "Inter"
|
||||
}}
|
||||
>
|
||||
<CloudDownloadOutlined />
|
||||
</Button>
|
||||
|
||||
{app?.activated &&
|
||||
app?.private_id !== undefined &&
|
||||
app?.private_id?.length > 0 &&
|
||||
app?.generated ? (
|
||||
<Button
|
||||
variant="contained"
|
||||
sx={{
|
||||
bgcolor: '#494949',
|
||||
'&:hover': { bgcolor: '#494949' },
|
||||
textTransform: 'none',
|
||||
borderRadius: 1,
|
||||
minWidth: '45px',
|
||||
width: '45px',
|
||||
height: '40px',
|
||||
padding: 2,
|
||||
color: "#fff",
|
||||
fontFamily: theme?.typography?.fontFamily
|
||||
}}
|
||||
onClick={(event) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
downloadApp(app);
|
||||
}}
|
||||
>
|
||||
<CloudDownloadOutlined />
|
||||
</Button>) : null}
|
||||
<Button
|
||||
variant="contained"
|
||||
sx={{
|
||||
@@ -419,9 +537,21 @@ const AppModal = ({ open, onClose, app, userdata, globalUrl }) => {
|
||||
px: 3,
|
||||
height: '40px',
|
||||
color: "#fff",
|
||||
fontFamily: "Inter"
|
||||
fontFamily: theme?.typography?.fontFamily
|
||||
}}
|
||||
startIcon={canEditApp ? <EditIcon /> :
|
||||
(app?.generated && app?.activated && userdata?.id !== app?.owner && isCloud ?
|
||||
<ForkRightIcon /> : null
|
||||
)}
|
||||
onClick={() => {
|
||||
if (canEditApp) {
|
||||
const editUrl = "/apps/edit/" + (app?.id || app?.objectID);
|
||||
navigate(editUrl)
|
||||
}else{
|
||||
const forkUrl = "/apps/new?id=" + (app?.id || app?.objectID);
|
||||
navigate(forkUrl)
|
||||
}
|
||||
}}
|
||||
startIcon={canEditApp ? <EditIcon /> : <ForkRightIcon />}
|
||||
>
|
||||
{canEditApp ? "Edit" : "Fork"}
|
||||
</Button>
|
||||
@@ -431,17 +561,17 @@ const AppModal = ({ open, onClose, app, userdata, globalUrl }) => {
|
||||
<div style={{
|
||||
display: "flex",
|
||||
justifyContent: "space-between",
|
||||
fontFamily: "Inter",
|
||||
fontFamily: theme?.typography?.fontFamily,
|
||||
padding: "26px 0px"
|
||||
}}>
|
||||
<div style={{
|
||||
textAlign: "start",
|
||||
flex: 1,
|
||||
}}>
|
||||
<Typography
|
||||
variant="h6"
|
||||
<Typography
|
||||
variant="h6"
|
||||
sx={{
|
||||
fontFamily: 'Inter, sans-serif',
|
||||
fontFamily: theme?.typography?.fontFamily,
|
||||
fontSize: '24px',
|
||||
fontWeight: 600,
|
||||
mb: 0.3,
|
||||
@@ -450,11 +580,11 @@ const AppModal = ({ open, onClose, app, userdata, globalUrl }) => {
|
||||
>
|
||||
20
|
||||
</Typography>
|
||||
<Typography
|
||||
variant="body2"
|
||||
sx={{
|
||||
<Typography
|
||||
variant="body2"
|
||||
sx={{
|
||||
color: 'rgba(255, 255, 255, 0.7)',
|
||||
fontFamily: 'Inter, sans-serif',
|
||||
fontFamily: theme?.typography?.fontFamily,
|
||||
fontSize: '14px'
|
||||
}}
|
||||
>
|
||||
@@ -468,12 +598,12 @@ const AppModal = ({ open, onClose, app, userdata, globalUrl }) => {
|
||||
paddingLeft: "10px",
|
||||
height: "100%",
|
||||
}}>
|
||||
<Typography variant="h6"
|
||||
sx={{
|
||||
fontWeight: 600,
|
||||
mb: 0.3,
|
||||
color: '#fff'
|
||||
}}>
|
||||
<Typography variant="h6"
|
||||
sx={{
|
||||
fontWeight: 600,
|
||||
mb: 0.3,
|
||||
color: '#fff'
|
||||
}}>
|
||||
{Array.isArray(app?.actions) ? app.actions.length : app?.actions}
|
||||
</Typography>
|
||||
<Typography variant="body2" sx={{ color: 'rgba(255, 255, 255, 0.7)' }}>
|
||||
@@ -486,7 +616,7 @@ const AppModal = ({ open, onClose, app, userdata, globalUrl }) => {
|
||||
paddingLeft: "10px",
|
||||
paddingTop: "5px"
|
||||
}}>
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: '4px', marginBottom: "5px", fontFamily: "Inter", fontSize: "14px", fontWeight: 600 }}>
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: '4px', marginBottom: "5px", fontFamily: theme?.typography?.fontFamily, fontSize: "14px", fontWeight: 600, color: 'white' }}>
|
||||
{
|
||||
app?.collection ? (
|
||||
<>
|
||||
@@ -494,13 +624,25 @@ const AppModal = ({ open, onClose, app, userdata, globalUrl }) => {
|
||||
<Typography variant="body1" sx={{
|
||||
fontWeight: 500,
|
||||
color: '#fff',
|
||||
marginTop: "1px"
|
||||
marginTop: "1px",
|
||||
fontFamily: theme?.typography?.fontFamily,
|
||||
fontSize: "16px"
|
||||
}}>
|
||||
app.collection
|
||||
|
||||
</Typography>
|
||||
</>
|
||||
) : "No collection yet"
|
||||
) : (
|
||||
<Typography sx={{
|
||||
fontSize: "16px",
|
||||
fontWeight: 500,
|
||||
marginTop: "1px",
|
||||
color: 'rgba(255, 255, 255, 0.7)',
|
||||
fontFamily: theme?.typography?.fontFamily
|
||||
}}>
|
||||
No collection yet
|
||||
</Typography>
|
||||
)
|
||||
}
|
||||
|
||||
</div>
|
||||
@@ -517,7 +659,7 @@ const AppModal = ({ open, onClose, app, userdata, globalUrl }) => {
|
||||
width: "100%"
|
||||
}}>
|
||||
<div style={{
|
||||
fontFamily: "Inter",
|
||||
fontFamily: theme?.typography?.fontFamily,
|
||||
fontSize: "16px",
|
||||
color: "#fff",
|
||||
marginBottom: "16px",
|
||||
@@ -544,7 +686,7 @@ const AppModal = ({ open, onClose, app, userdata, globalUrl }) => {
|
||||
{
|
||||
foundAppUsecase === undefined ? (
|
||||
<Avatar sx={{ width: 32, height: 32, bgcolor: 'background.paper', border: 1, borderColor: 'divider' }}>
|
||||
<Search sx={{ color: 'text.primary', zIndex: 10, fontSize: 18}} />
|
||||
<Search sx={{ color: 'text.primary', zIndex: 10, fontSize: 18 }} />
|
||||
</Avatar>
|
||||
) : (
|
||||
<Avatar
|
||||
@@ -560,10 +702,10 @@ const AppModal = ({ open, onClose, app, userdata, globalUrl }) => {
|
||||
/>
|
||||
)
|
||||
}
|
||||
{
|
||||
{
|
||||
foundAppUsecase === undefined ? (
|
||||
<Avatar sx={{ width: 32, height: 32, bgcolor: 'background.paper', border: 1, borderColor: 'divider' }}>
|
||||
<AddIcon sx={{ color: 'text.primary', zIndex: 10, fontSize: 18}} />
|
||||
<AddIcon sx={{ color: 'text.primary', zIndex: 10, fontSize: 18 }} />
|
||||
</Avatar>
|
||||
) : (
|
||||
<Avatar
|
||||
@@ -586,7 +728,7 @@ const AppModal = ({ open, onClose, app, userdata, globalUrl }) => {
|
||||
</Box>
|
||||
</div>
|
||||
|
||||
<div style={{ display: "flex", justifyContent: "center", fontFamily: "Inter" }}>
|
||||
<div style={{ display: "flex", justifyContent: "center", fontFamily: theme?.typography?.fontFamily }}>
|
||||
<Button
|
||||
variant="contained"
|
||||
sx={{
|
||||
@@ -599,11 +741,14 @@ const AppModal = ({ open, onClose, app, userdata, globalUrl }) => {
|
||||
fontSize: "14px",
|
||||
letterSpacing: "0.5px",
|
||||
color: "black",
|
||||
fontFamily: "Inter",
|
||||
fontFamily: theme?.typography?.fontFamily,
|
||||
minWidth: '200px'
|
||||
}}
|
||||
onClick={() => {
|
||||
navigate("/usecases2")
|
||||
}}
|
||||
>
|
||||
Create a Usecase
|
||||
Find a Usecase
|
||||
</Button>
|
||||
</div>
|
||||
</DialogContent>
|
||||
@@ -611,4 +756,4 @@ const AppModal = ({ open, onClose, app, userdata, globalUrl }) => {
|
||||
);
|
||||
};
|
||||
|
||||
export default AppModal;
|
||||
export default AppModal;
|
||||
|
||||
@@ -465,7 +465,7 @@ const AppSelection = props => {
|
||||
style={{
|
||||
fontSize: 16,
|
||||
color: "rgba(158, 158, 158, 1)",
|
||||
fontFamily: "Inter",
|
||||
fontFamily: theme?.typography?.fontFamily,
|
||||
}}
|
||||
>
|
||||
Your organization has no apps yet, select your starting apps here
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import React, { useState, useEffect, useContext, memo, useMemo } from "react";
|
||||
import ReactGA from 'react-ga4';
|
||||
|
||||
import theme from "../theme.jsx";
|
||||
@@ -41,7 +41,8 @@ import {
|
||||
Delete,
|
||||
RestaurantRounded,
|
||||
Cloud,
|
||||
CheckCircle
|
||||
CheckCircle,
|
||||
Padding,
|
||||
} from "@mui/icons-material";
|
||||
|
||||
//import { useAlert
|
||||
@@ -49,8 +50,9 @@ import { typecost, typecost_single, } from "../views/HandlePaymentNew.jsx";
|
||||
import BillingStats from "./BillingStats.jsx";
|
||||
import { handlePayasyougo } from "../views/HandlePaymentNew.jsx"
|
||||
import DeleteIcon from '@mui/icons-material/Delete';
|
||||
import { Context } from "../context/ContextApi.jsx";
|
||||
|
||||
const Billing = (props) => {
|
||||
const Billing = memo((props) => {
|
||||
const { globalUrl, userdata, serverside, billingInfo, stripeKey, selectedOrganization, handleGetOrg, clickedFromOrgTab } = props;
|
||||
//const alert = useAlert();
|
||||
let navigate = useNavigate();
|
||||
@@ -72,7 +74,7 @@ const Billing = (props) => {
|
||||
const [alertThresholds, setAlertThresholds] = useState(selectedOrganization.Billing !== undefined && selectedOrganization.Billing.AlertThreshold !== undefined && selectedOrganization.Billing.AlertThreshold !== null ? selectedOrganization.Billing.AlertThreshold : [{ percentage: '', count: '', Email_send: false }]);
|
||||
const [currentIndex, setCurrentIndex] = useState(0);
|
||||
const [deleteAlertVerification, setDeleteAlertVerification] = useState(false);
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
if (userdata.app_execution_limit !== undefined && userdata.app_execution_usage !== undefined) {
|
||||
const percentage = (userdata.app_execution_usage / userdata.app_execution_limit) * 100;
|
||||
@@ -81,18 +83,12 @@ const Billing = (props) => {
|
||||
}
|
||||
}, [userdata]);
|
||||
|
||||
const [BillingEmail, setBillingEmail] = useState(selectedOrganization?.Billing?.Email);
|
||||
|
||||
const [BillingEmail, setBillingEmail] = useState(selectedOrganization.Billing !== undefined && selectedOrganization.Billing.Email !== undefined && selectedOrganization.Billing.Email != null && selectedOrganization.Billing.Email.length > 0 ? selectedOrganization.Billing.Email : selectedOrganization.org);
|
||||
|
||||
useState(() => {
|
||||
// Set the billing email
|
||||
setBillingEmail(
|
||||
selectedOrganization.Billing !== undefined &&
|
||||
selectedOrganization.Billing.Email !== undefined &&
|
||||
selectedOrganization.Billing.Email.length > 0
|
||||
? selectedOrganization.Billing.Email
|
||||
: selectedOrganization.org
|
||||
);
|
||||
useEffect(() => {
|
||||
if (BillingEmail !== selectedOrganization?.Billing?.Email) {
|
||||
setBillingEmail(selectedOrganization?.Billing?.Email);
|
||||
}
|
||||
|
||||
// Set and sort the alert thresholds
|
||||
const alertThresholds = selectedOrganization.Billing !== undefined &&
|
||||
@@ -126,7 +122,6 @@ const Billing = (props) => {
|
||||
];
|
||||
|
||||
const handleGetDeals = (orgId) => {
|
||||
console.log("Get deals!");
|
||||
|
||||
if (orgId.length === 0) {
|
||||
toast(
|
||||
@@ -178,7 +173,7 @@ const Billing = (props) => {
|
||||
width: 340,
|
||||
height: 480,
|
||||
// width: "100%",
|
||||
backgroundColor: theme.palette.platformColor,
|
||||
backgroundColor: theme.palette.backgroundColor,
|
||||
borderRadius: theme.palette?.borderRadius * 2,
|
||||
border: "1px solid rgba(255,255,255,0.3)",
|
||||
marginRight: 10,
|
||||
@@ -384,7 +379,7 @@ const Billing = (props) => {
|
||||
}
|
||||
|
||||
if (hovered) {
|
||||
newPaperstyle.backgroundColor = theme.palette.surfaceColor
|
||||
newPaperstyle.backgroundColor = "#2b2b2b"
|
||||
}
|
||||
|
||||
const handleClickOpen = () => {
|
||||
@@ -412,7 +407,6 @@ const Billing = (props) => {
|
||||
const HandleChangeBillingEmail = (orgId) => {
|
||||
const email = newBillingEmail;
|
||||
const emailPattern = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}$/;
|
||||
console.log("Pattern matches: ", emailPattern.test(email));
|
||||
if (!emailPattern.test(email)) {
|
||||
toast("Please enter a valid email address");
|
||||
return;
|
||||
@@ -445,7 +439,6 @@ const Billing = (props) => {
|
||||
}
|
||||
return response.json();
|
||||
}).then((responseJson) => {
|
||||
console.log("Got org:", responseJson);
|
||||
if (responseJson.success === true) {
|
||||
toast.success("Successfully updated billing email");
|
||||
setBillingEmail(newBillingEmail);
|
||||
@@ -460,7 +453,7 @@ const Billing = (props) => {
|
||||
}
|
||||
|
||||
return (
|
||||
<Paper
|
||||
<div
|
||||
style={newPaperstyle}
|
||||
onMouseEnter={() => setHovered(true)}
|
||||
onMouseLeave={() => setHovered(false)}
|
||||
@@ -726,7 +719,7 @@ const Billing = (props) => {
|
||||
</Typography>
|
||||
<div style={{ display: 'flex', flexDirection: 'row' }}>
|
||||
<Typography variant="body2" style={{ marginTop: !userdata.has_card_available ? 5 : 0 }}>
|
||||
Billing email: {BillingEmail}
|
||||
{BillingEmail?.length > 0 ? `Billing email: ${BillingEmail}` : null}
|
||||
</Typography>
|
||||
{userdata.has_card_available === true && (
|
||||
<Button
|
||||
@@ -817,11 +810,11 @@ const Billing = (props) => {
|
||||
color="primary"
|
||||
style={{
|
||||
marginTop: !userdata.has_card_available ? 20 : 10,
|
||||
borderRadius: 25,
|
||||
borderRadius: 8,
|
||||
height: 40,
|
||||
fontSize: 16,
|
||||
color: "white",
|
||||
backgroundColor: userdata.has_card_available ? null : "#f86743",
|
||||
color: userdata.has_card_available ? "#ff8544" : "#1a1a1a",
|
||||
backgroundColor: userdata.has_card_available ? null : "#ff8544",
|
||||
// backgroundImage: userdata.has_card_available ? null : "linear-gradient(to right, #f86a3e, #f34079)",
|
||||
textTransform: "none",
|
||||
|
||||
@@ -850,11 +843,11 @@ const Billing = (props) => {
|
||||
color="primary"
|
||||
style={{
|
||||
marginTop: 10,
|
||||
borderRadius: 25,
|
||||
borderRadius: 8,
|
||||
height: 40,
|
||||
fontSize: 16,
|
||||
color: "white",
|
||||
backgroundColor: "#f86743",
|
||||
color: "#1a1a1a",
|
||||
backgroundColor: "#ff8544",
|
||||
textTransform: 'none'
|
||||
}}
|
||||
onClick={() => {
|
||||
@@ -873,7 +866,6 @@ const Billing = (props) => {
|
||||
: null}
|
||||
{showSupport ?
|
||||
<Button variant="outlined" color="primary" style={{ marginTop: 20, marginBottom: 10, }} onClick={() => {
|
||||
console.log("Support click")
|
||||
if (window.drift !== undefined) {
|
||||
//window.drift.api.startInteraction({ interactionId: 340045 })
|
||||
window.drift.api.startInteraction({ interactionId: 340043 })
|
||||
@@ -884,7 +876,7 @@ const Billing = (props) => {
|
||||
Get Support
|
||||
</Button>
|
||||
: null}
|
||||
</Paper>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
const ConsultationManagement = (props) => {
|
||||
@@ -1035,12 +1027,12 @@ const Billing = (props) => {
|
||||
})
|
||||
|
||||
return (
|
||||
<Paper style={{
|
||||
<div style={{
|
||||
padding: 20,
|
||||
// maxWidth: 400,
|
||||
width: 340,
|
||||
height: 480,
|
||||
backgroundColor: hovered ? "#232427" : theme.palette.platformColor,
|
||||
backgroundColor: hovered ? "#2b2b2b" : theme.palette.backgroundColor,
|
||||
borderRadius: theme.palette?.borderRadius * 2,
|
||||
border: "1px solid rgba(255,255,255,0.3)",
|
||||
marginRight: 10,
|
||||
@@ -1131,11 +1123,11 @@ const Billing = (props) => {
|
||||
color="primary"
|
||||
style={{
|
||||
marginTop: userdata.support ? 0 : 10,
|
||||
borderRadius: 25,
|
||||
borderRadius: 8,
|
||||
height: 40,
|
||||
fontSize: 16,
|
||||
color: "white",
|
||||
backgroundColor: "#f86743",
|
||||
color: "#1A1A1A",
|
||||
backgroundColor: "#FF8544",
|
||||
textTransform: 'none',
|
||||
}}
|
||||
onClick={() => {
|
||||
@@ -1150,7 +1142,7 @@ const Billing = (props) => {
|
||||
>
|
||||
Buy
|
||||
</Button>
|
||||
<Dialog open={clickOnBuy} onClose={() => { setClickOnBuy(false) }}>
|
||||
<Dialog open={clickOnBuy} onClose={() => { setClickOnBuy(false) }} PaperProps={{style: {backgroundColor: "rgb(26, 26, 26)"}}}>
|
||||
<Typography variant="body1" style={{ marginTop: 10, textAlign: 'center', padding: 20, fontSize: 18 }}>
|
||||
You will be taken to Stripe to book professional service hours. You can adjust the number of hours on the left side of the Stripe page.
|
||||
</Typography>
|
||||
@@ -1158,7 +1150,7 @@ const Billing = (props) => {
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
style={{ display: 'block', marginLeft: 'auto', marginRight: 'auto', padding: '12px 24px', textTransform: 'none', fontSize: 16 }}
|
||||
style={{ display: 'block', marginLeft: 'auto', marginRight: 'auto', padding: '12px 24px', textTransform: 'none', fontSize: 16, color: "#1a1a1a", backgroundColor: "#ff8544" }}
|
||||
onClick={() => {
|
||||
if (Cloud) {
|
||||
ReactGA.event({
|
||||
@@ -1186,10 +1178,10 @@ const Billing = (props) => {
|
||||
color="primary"
|
||||
style={{
|
||||
marginTop: userdata.support ? 5 : 10,
|
||||
borderRadius: 25,
|
||||
borderRadius: 8,
|
||||
height: 40,
|
||||
fontSize: 16,
|
||||
color: "white",
|
||||
color: "#ff8544",
|
||||
textTransform: 'none',
|
||||
cursor: getProfessionalServices ? 'pointer' : 'not-allowed',
|
||||
opacity: getProfessionalServices ? 1 : 0.6,
|
||||
@@ -1259,7 +1251,7 @@ const Billing = (props) => {
|
||||
</Button>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
</Paper >
|
||||
</div >
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1308,13 +1300,13 @@ const Billing = (props) => {
|
||||
}
|
||||
|
||||
return (
|
||||
<Paper
|
||||
<div
|
||||
style={{
|
||||
padding: 20,
|
||||
height: 480,
|
||||
// maxWidth: 400,
|
||||
width: 340,
|
||||
backgroundColor: hovered ? "#232427" : theme.palette.platformColor,
|
||||
backgroundColor: hovered ? "#2b2b2b" : theme.palette.backgroundColor,
|
||||
borderRadius: theme.palette?.borderRadius * 2,
|
||||
border: "1px solid rgba(255,255,255,0.3)",
|
||||
marginRight: 10,
|
||||
@@ -1370,11 +1362,12 @@ const Billing = (props) => {
|
||||
color="primary"
|
||||
style={{
|
||||
marginTop: 10,
|
||||
borderRadius: 25,
|
||||
borderRadius: 8,
|
||||
height: 40,
|
||||
fontSize: 16,
|
||||
color: "white",
|
||||
textTransform: 'none'
|
||||
color: "#1A1A1A",
|
||||
textTransform: 'none',
|
||||
backgroundColor: "#FF8544"
|
||||
}}
|
||||
onClick={() => {
|
||||
if (Cloud) {
|
||||
@@ -1397,10 +1390,12 @@ const Billing = (props) => {
|
||||
color="primary"
|
||||
style={{
|
||||
marginTop: 10,
|
||||
borderRadius: 25,
|
||||
borderRadius: 8,
|
||||
height: 40,
|
||||
fontSize: 16,
|
||||
textTransform: 'none'
|
||||
textTransform: 'none',
|
||||
color: "#FF8544",
|
||||
backgroundColor: "#1a1a1a",
|
||||
}}
|
||||
onClick={() => {
|
||||
if (Cloud) {
|
||||
@@ -1425,6 +1420,7 @@ const Billing = (props) => {
|
||||
style: {
|
||||
width: 500,
|
||||
margin: 0,
|
||||
backgroundColor: "rgb(26, 26, 26)",
|
||||
}
|
||||
}}
|
||||
>
|
||||
@@ -1464,7 +1460,7 @@ const Billing = (props) => {
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
style={{ marginTop: '24px', display: 'block', marginLeft: 'auto', marginRight: 'auto', padding: '12px 24px', textTransform: 'none' }}
|
||||
style={{ marginTop: '24px', display: 'block', marginLeft: 'auto', marginRight: 'auto', padding: '12px 24px', textTransform: 'none', color: "#1a1a1a", backgroundColor: "#ff8544" }}
|
||||
onClick={handlePrivateTraining}
|
||||
>
|
||||
Submit Request
|
||||
@@ -1472,7 +1468,7 @@ const Billing = (props) => {
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
</div>
|
||||
</Paper>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1892,13 +1888,15 @@ const Billing = (props) => {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const isChildOrg = userdata.active_org.creator_org !== "" && userdata.active_org.creator_org !== undefined && userdata.active_org.creator_org !== null
|
||||
const isChildOrg = userdata?.active_org?.creator_org !== "" && userdata?.active_org?.creator_org !== undefined && userdata?.active_org?.creator_org !== null
|
||||
|
||||
return (
|
||||
<div style={{ width: clickedFromOrgTab ? 1030 : "auto", padding: 27, backgroundColor: '#212121', borderRadius: '16px', }}>
|
||||
{addDealModal}
|
||||
<Wrapper clickedFromOrgTab={clickedFromOrgTab}>
|
||||
<div style={{ height: "100%", width: "100%"}}>
|
||||
<div style={{ width: "100%",}}>
|
||||
{addDealModal}
|
||||
{clickedFromOrgTab ?
|
||||
<h2 style={{ marginBottom: 8, marginTop: 0, color: "#ffffff" }}>Billing & Licensing</h2> :
|
||||
<Typography style={{fontSize: 24, fontWeight: "bold", marginBottom: 8, marginTop: 0, color: "#ffffff" }}>Billing & Licensing</Typography> :
|
||||
<Typography variant="h4" style={{ marginTop: 20, marginBottom: 10 }}>
|
||||
Billing & Licensing
|
||||
</Typography>}
|
||||
@@ -1942,11 +1940,11 @@ const Billing = (props) => {
|
||||
|
||||
{isChildOrg ?
|
||||
<Typography variant="h6" style={{ marginBottom: 50, }}>
|
||||
Billing is handled by your parent organisation. Reach out to support@shuffler.io if you have questions about this.
|
||||
Licensing is handled by your parent organisation. Reach out to support@shuffler.io if you have questions about this.
|
||||
</Typography>
|
||||
: null}
|
||||
|
||||
<div style={{ display: "flex", width: 1180, overflowX: 'auto', overflowY: 'hidden', scrollbarWidth: 'thin', scrollbarColor: '#494949 #2f2f2f', height: 580 }} >
|
||||
<div style={{ display: "flex", width: clickedFromOrgTab ? 1030 : "auto", overflowX: 'auto', overflowY: 'hidden', scrollbarWidth: 'thin', scrollbarColor: '#494949 #2f2f2f', height: isChildOrg ? 0 : 580 }} >
|
||||
{isCloud && billingInfo.subscription !== undefined && billingInfo.subscription !== null ? isChildOrg ? null :
|
||||
<SubscriptionObject
|
||||
index={0}
|
||||
@@ -2258,10 +2256,10 @@ const Billing = (props) => {
|
||||
) : null*/}
|
||||
{!isChildOrg && isCloud && (
|
||||
<div style={{ display: 'flex', flexDirection: 'column', marginTop: 10 }}>
|
||||
<Typography style={{ marginBottom: 5 }} variant="h4">
|
||||
<Typography style={{ marginBottom: 5, fontSize: 24, fontWeight: "bold" }}>
|
||||
Professional Services
|
||||
</Typography>
|
||||
<Typography color="textSecondary">
|
||||
<Typography color="textSecondary" style={{fontSize: 16,}}>
|
||||
We offer priority support through consultations and training to help you make the most of our product. If you have any questions, please reach out to us at support@shuffler.io.
|
||||
</Typography>
|
||||
<div style={{ display: 'flex', flexDirection: 'row', marginTop: 5 }}>
|
||||
@@ -2280,15 +2278,14 @@ const Billing = (props) => {
|
||||
)}
|
||||
<div style={{ marginTop: isCloud && 40, marginLeft: 10 }}>
|
||||
<Typography
|
||||
style={{ marginBottom: 5 }}
|
||||
variant="h4"
|
||||
style={{ marginBottom: 5, fontSize: 24, fontWeight: "bold" }}
|
||||
>
|
||||
Manage Billing
|
||||
</Typography>
|
||||
<Typography variant="body1" color="textSecondary" style={{ marginTop: 0, marginBottom: 10 }}>
|
||||
<Typography color="textSecondary" style={{ marginTop: 10, marginBottom: 10, fontSize: 16, }}>
|
||||
Manage your billing and licensing information below. When you reach the certain thresholds of your subscription limit, you will be notified by email.
|
||||
</Typography>
|
||||
<Typography variant="body1">Current Usage:</Typography>
|
||||
<Typography style={{fontSize: 18, marginTop: 10}}>Current Usage:</Typography>
|
||||
<LinearProgress
|
||||
variant="determinate"
|
||||
value={currentAppRunsInPercentage}
|
||||
@@ -2300,15 +2297,15 @@ const Billing = (props) => {
|
||||
marginBottom: 10,
|
||||
}}
|
||||
/>
|
||||
<Typography variant="body1" color="textSecondary">
|
||||
<Typography style={{marginTop: 10, fontSize: 16,}} color="textSecondary">
|
||||
You have used <strong>{currentAppRunsInPercentage}%</strong> of total app execution limit or <strong>{userdata.app_execution_usage}</strong> app runs out of <strong>{userdata.app_execution_limit}</strong> app runs.
|
||||
</Typography>
|
||||
|
||||
<div>
|
||||
<Typography variant="body1" style={{ marginTop: 20 }}>
|
||||
<Typography style={{ marginTop: 20, fontSize: 18 }}>
|
||||
Set email alert thresholds for app runs
|
||||
</Typography>
|
||||
<Typography variant="body1" color="textSecondary" style={{ marginTop: 10 }}>
|
||||
<Typography color="textSecondary" style={{ marginTop: 10, fontSize: 16 }}>
|
||||
You will be notified by email when you reach the
|
||||
{currentIndex !== -1
|
||||
? " " + getSafeValue(alertThresholds[currentIndex].percentage) + '%' + " "
|
||||
@@ -2320,8 +2317,8 @@ const Billing = (props) => {
|
||||
: " " + 0 + " "}
|
||||
app runs.
|
||||
</Typography>
|
||||
<Typography variant="body1" color="textSecondary" style={{ marginTop: 10 }}>
|
||||
Please note: Once your app runs reach the set alert threshold, all admins in the organization will receive an email notification.
|
||||
<Typography color="textSecondary" style={{ fontSize: 16 }}>
|
||||
<span style={{fontWeight: 'bold'}}>Please note</span>: Once your app runs reach the set alert threshold, all admins in the organization will receive an email notification.
|
||||
</Typography>
|
||||
<div style={{ marginTop: 15 }}>
|
||||
{alertThresholds.map((threshold, index) => (
|
||||
@@ -2329,7 +2326,7 @@ const Billing = (props) => {
|
||||
<TextField
|
||||
style={{
|
||||
marginTop: 10,
|
||||
backgroundColor: theme.palette.inputColor,
|
||||
backgroundColor: "#212121",
|
||||
width: 250,
|
||||
}}
|
||||
InputProps={{
|
||||
@@ -2354,7 +2351,7 @@ const Billing = (props) => {
|
||||
<TextField
|
||||
style={{
|
||||
marginTop: 10,
|
||||
backgroundColor: theme.palette.inputColor,
|
||||
backgroundColor: "#212121",
|
||||
width: 250,
|
||||
marginLeft: 15,
|
||||
}}
|
||||
@@ -2421,11 +2418,11 @@ const Billing = (props) => {
|
||||
Save
|
||||
</Button>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div style={{ marginTop: 40, display: 'flex', flexDirection: 'column' }}>
|
||||
<Typography
|
||||
style={{ marginTop: 10, marginLeft: 10, marginBottom: 5 }}
|
||||
variant="h4"
|
||||
style={{ marginTop: 10, marginLeft: 10, marginBottom: 5, fontSize: 24, fontWeight: "bold" }}
|
||||
>
|
||||
Utilization & Stats
|
||||
</Typography>
|
||||
@@ -2436,9 +2433,41 @@ const Billing = (props) => {
|
||||
globalUrl={globalUrl}
|
||||
selectedOrganization={selectedOrganization}
|
||||
userdata={userdata}
|
||||
/>
|
||||
</div>
|
||||
/>
|
||||
</div>
|
||||
</Wrapper>
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
export default Billing;
|
||||
export default memo(Billing);
|
||||
|
||||
const PaddingWrapper = memo(({ clickedFromOrgTab, children }) => {
|
||||
|
||||
const wrapperStyle = useMemo(() => ({
|
||||
width: clickedFromOrgTab
|
||||
? "100%"
|
||||
: "auto",
|
||||
padding: "27px 10px 19px 27px",
|
||||
backgroundColor: '#212121',
|
||||
borderRadius: '16px',
|
||||
height: '100%',
|
||||
boxSizing: 'border-box',
|
||||
borderLeft: '1px solid #494949',
|
||||
overflow: 'hidden',
|
||||
maxHeight: "1700px", overflowY: "auto",scrollbarColor: '#494949 transparent', scrollbarWidth: 'thin'
|
||||
}), [clickedFromOrgTab]);
|
||||
|
||||
return (
|
||||
<div style={wrapperStyle}>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
const Wrapper = memo(({ children, clickedFromOrgTab }) => {
|
||||
return (
|
||||
<PaddingWrapper clickedFromOrgTab={clickedFromOrgTab}>
|
||||
{children}
|
||||
</PaddingWrapper>
|
||||
);
|
||||
});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import React, { useState, useEffect, useContext, memo, useMemo } from 'react';
|
||||
|
||||
import theme from '../theme.jsx';
|
||||
import classNames from "classnames";
|
||||
@@ -37,6 +37,7 @@ import {
|
||||
} from 'reaviz';
|
||||
|
||||
import { typecost, typecost_single, } from "../views/HandlePaymentNew.jsx";
|
||||
import { Context } from '../context/ContextApi.jsx';
|
||||
|
||||
const LineChartWrapper = ({keys, inputname, height, width}) => {
|
||||
const [hovered, setHovered] = useState("");
|
||||
@@ -82,8 +83,8 @@ const AppStats = (defaultprops) => {
|
||||
const [workflows, setWorkflows] = useState(inputWorkflows === undefined ? [] : inputWorkflows)
|
||||
const [resultRows, setResultRows] = useState([])
|
||||
const [resultLoading, setResultLoading] = useState(true)
|
||||
|
||||
const includedExecutions = selectedOrganization.sync_features.app_executions !== undefined ? selectedOrganization.sync_features.app_executions.limit : 0
|
||||
|
||||
const includedExecutions = selectedOrganization?.sync_features?.app_executions !== undefined ? selectedOrganization?.sync_features?.app_executions?.limit : 0
|
||||
|
||||
useEffect(() => {
|
||||
if (workflows === undefined || workflows === null || workflows.length === 0) {
|
||||
@@ -92,7 +93,6 @@ const AppStats = (defaultprops) => {
|
||||
}, [])
|
||||
|
||||
|
||||
|
||||
const getWorkflowStats = async (workflow, startTime, endTime) => {
|
||||
if (!userdata.support) {
|
||||
return workflow
|
||||
@@ -162,8 +162,6 @@ const AppStats = (defaultprops) => {
|
||||
|
||||
const loadWorkflowStats = (foundWorkflows, startTime, endTime) => {
|
||||
if (!userdata.support) {
|
||||
console.log("Not support")
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -488,8 +486,13 @@ const AppStats = (defaultprops) => {
|
||||
setApprunCosts(appcostRuns)
|
||||
}
|
||||
|
||||
const getStats = () => {
|
||||
fetch(`${globalUrl}/api/v1/orgs/${selectedOrganization.id}/stats`, {
|
||||
const getStats = (orgid) => {
|
||||
|
||||
if (orgid === undefined || orgid === null) {
|
||||
return
|
||||
}
|
||||
|
||||
fetch(`${globalUrl}/api/v1/orgs/${orgid}/stats`, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
@@ -519,8 +522,10 @@ const AppStats = (defaultprops) => {
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
getStats()
|
||||
}, [])
|
||||
if(selectedOrganization?.id?.length > 0) {
|
||||
getStats(selectedOrganization.id)
|
||||
}
|
||||
}, [selectedOrganization])
|
||||
|
||||
const paperStyle = {
|
||||
textAlign: "center",
|
||||
@@ -639,7 +644,7 @@ const AppStats = (defaultprops) => {
|
||||
|
||||
const data = (
|
||||
<div className="content" style={{width: "100%", margin: "auto", }}>
|
||||
<Typography variant="body1" style={{margin: "auto", marginLeft: 10, marginBottom: 20, }} color="textSecondary">
|
||||
<Typography style={{margin: "auto", marginLeft: 10, marginBottom: 20, fontSize: 16}} color="textSecondary">
|
||||
All shown statistics are gathered from <a
|
||||
href={`${globalUrl}/api/v1/orgs/${selectedOrganization.id}/stats`}
|
||||
target="_blank"
|
||||
@@ -722,6 +727,40 @@ const AppStats = (defaultprops) => {
|
||||
</div>
|
||||
: null}
|
||||
|
||||
{clickedFromOrgTab? (
|
||||
<LocalizationProvider dateAdapter={AdapterDayjs} style={{ flex: 1 }}>
|
||||
<div style={{ display: "flex", flexDirection: "column", gap: "10px" }}>
|
||||
<div style={{ flex: 1, maxWidth: "200px", }}>
|
||||
<DateTimePicker
|
||||
sx={{
|
||||
marginTop: 1,
|
||||
marginLeft: 1,
|
||||
}}
|
||||
ampm={false}
|
||||
label="Search from"
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
value={startTime}
|
||||
onChange={handleStartTimeChange}
|
||||
renderInput={(params) => <TextField {...params} />}
|
||||
/>
|
||||
</div>
|
||||
<div style={{ flex: 1, maxWidth: "200px",}}>
|
||||
<DateTimePicker
|
||||
sx={{
|
||||
marginTop: 1,
|
||||
marginLeft: 1,
|
||||
}}
|
||||
ampm={false}
|
||||
label="Search until"
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
value={endTime}
|
||||
onChange={handleEndTimeChange}
|
||||
renderInput={(params) => <TextField {...params} />}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</LocalizationProvider>
|
||||
):(
|
||||
<LocalizationProvider dateAdapter={AdapterDayjs} style={{flex: 1, }}>
|
||||
<div style={{display: "flex", flexDirection: "column", }}>
|
||||
<DateTimePicker
|
||||
@@ -754,6 +793,8 @@ const AppStats = (defaultprops) => {
|
||||
/>
|
||||
</div>
|
||||
</LocalizationProvider>
|
||||
)}
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import React, { useState, useEffect, useContext } from "react";
|
||||
import ReactGA from 'react-ga4';
|
||||
import theme from "../theme.jsx";
|
||||
import { ToastContainer, toast } from "react-toastify"
|
||||
@@ -21,6 +21,7 @@ import {
|
||||
red,
|
||||
green,
|
||||
} from "../views/AngularWorkflow.jsx"
|
||||
import { Context } from "../context/ContextApi.jsx";
|
||||
|
||||
//import { useAlert
|
||||
|
||||
@@ -30,7 +31,8 @@ const Branding = (props) => {
|
||||
const [publishingInfo, setPublishingInfo] = useState("");
|
||||
const [publishRequirements, setPublishRequirements] = useState([])
|
||||
|
||||
|
||||
const { leftSideBarOpenByClick } = useContext(Context)
|
||||
|
||||
const handleEditOrg = (joinStatus) => {
|
||||
const data = {
|
||||
"org_id": selectedOrganization.id,
|
||||
@@ -115,48 +117,73 @@ const Branding = (props) => {
|
||||
const leadinfo = selectedOrganization.lead_info === undefined || selectedOrganization.lead_info === null || selectedOrganization.lead_info === "" ? "" : JSON.stringify(selectedOrganization.lead_info)
|
||||
const isPartner = leadinfo.includes("partner")
|
||||
|
||||
console.log("LEADINFO: ", leadinfo)
|
||||
|
||||
console.log("SELECTEDORGANIZATION: ", selectedOrganization)
|
||||
|
||||
return (
|
||||
<div style={{ width: clickedFromOrgTab? 1030: "auto", padding: 27, height: "auto", backgroundColor: '#212121', borderRadius: '16px', }}>
|
||||
<h2 style={{marginTop: clickedFromOrgTab ?0:null,}}>
|
||||
<div style={{ width: clickedFromOrgTab? "100%": "auto", height: "100%", minHeight: 1100, boxSizing: 'border-box', transition: "width 0.3s ease", padding: "27px 10px 19px 27px", height: "auto", backgroundColor: '#212121', borderRadius: '16px', }}>
|
||||
<div style={{height: 843, overflowY: "auto",}}>
|
||||
<div style={{width: "100%", overflowX: 'hidden', }}>
|
||||
<Typography style={{fontSize: 24, fontWeight: "bold", marginTop: clickedFromOrgTab ?0:null,}}>
|
||||
Partner Status & Branding
|
||||
</h2>
|
||||
<Typography variant="body1" color="textSecondary" style={{ marginTop: 20, marginBottom: 10 }}>
|
||||
</Typography>
|
||||
<Typography variant="body1" color="textSecondary" style={{ marginTop: 10, marginBottom: 10, fontSize: 16 }}>
|
||||
You can customize your organization's branding by uploading a logo, changing the color scheme and a lot more.
|
||||
</Typography>
|
||||
|
||||
<Typography variant="body1" color="textSecondary" style={{ marginTop: 20, marginBottom: 10 }}>
|
||||
<Typography variant="body1" color="textSecondary" style={{display: 'flex', marginTop: 20, marginBottom: 10 }}>
|
||||
{isPublished ? <CheckCircleIcon style={{color: red, }} /> : <CheckCircleIcon style={{color: green, }} />}
|
||||
<span style={{marginLeft: 10, color: isPublished ? red : green, }}>{isPublished ? "Not Published" : "Published"}</span>
|
||||
<span style={{marginLeft: 10, color: isPublished ? red : green, fontSize: 16 }}>{isPublished ? "Not Published" : "Published"}</span>
|
||||
</Typography>
|
||||
|
||||
<a href="https://shuffler.io/partners" target="_blank" style={{ textDecoration: "none", }}>
|
||||
<Typography variant="body1" color="textSecondary" style={{ marginTop: 20, marginBottom: 10 }}>
|
||||
<Typography variant="body1" color="textSecondary" style={{display: 'flex', marginTop: 20, marginBottom: 10 }}>
|
||||
{!isPartner ? <CheckCircleIcon style={{color: red, }} /> : <CheckCircleIcon style={{color: green, }} />}
|
||||
<Tooltip title="Official Partner Program (manual verification)" placement="top" arrow>
|
||||
<span style={{marginLeft: 10, color: !isPartner ? red : green, }}>{!isPartner? "Not Officially Partnered" : "Officially Partnered"}</span>
|
||||
<span style={{marginLeft: 10, color: !isPartner ? red : green, fontSize: 16}}>{!isPartner? "Not Officially Partnered" : "Officially Partnered"}</span>
|
||||
</Tooltip>
|
||||
</Typography>
|
||||
</a>
|
||||
|
||||
<a href={`/partners/${selectedOrganization.creator_id}/edit`} target="_blank">
|
||||
<Button disabled={isPublished} variant="contained" style={{ marginTop: 20, marginBottom: 10, }} onClick={() => {
|
||||
}}>
|
||||
Modify Public Partner Details
|
||||
</Button>
|
||||
</a>
|
||||
{!isPublished ? (
|
||||
<a
|
||||
href={`/partners/${selectedOrganization.creator_id}/edit`}
|
||||
target="_blank"
|
||||
style={{ textDecoration: "none" }} // Optional: remove underline
|
||||
>
|
||||
<Button
|
||||
variant="contained"
|
||||
style={{
|
||||
marginTop: 20,
|
||||
marginBottom: 10,
|
||||
textTransform: 'none',
|
||||
fontSize: 16
|
||||
}}
|
||||
>
|
||||
Modify Public Partner Details
|
||||
</Button>
|
||||
</a>
|
||||
) : (
|
||||
<Button
|
||||
disabled
|
||||
variant="contained"
|
||||
style={{
|
||||
marginTop: 20,
|
||||
marginBottom: 10,
|
||||
textTransform: 'none',
|
||||
fontSize: 16
|
||||
}}
|
||||
>
|
||||
Modify Public Partner Details
|
||||
</Button>
|
||||
)}
|
||||
|
||||
<Divider style={{marginTop: 50, marginBottom: 50, }} />
|
||||
<h2>
|
||||
<Typography style={{fontSize: 24, fontWeight: "bold"}}>
|
||||
Partner Program
|
||||
</h2>
|
||||
<div style={{ display: "flex", width: 900, }}>
|
||||
</Typography>
|
||||
<div style={{ display: "flex", width: 900, marginTop: 10}}>
|
||||
<div>
|
||||
<span>
|
||||
<Typography variant="body1" color="textSecondary">
|
||||
<Typography variant="body1" color="textSecondary" style={{fontSize: 16}}>
|
||||
By changing publishing settings, you agree to our <a href="/docs/terms_of_service" target="_blank" style={{ textDecoration: "none", color: "#f86a3e"}}>Terms of Service</a>, and acknowledge that your organization's non-sensitive data will be added as a <a target="_blank" style={{ textDecoration: "none", color: "#f86a3e"}} href="https://shuffler.io/creators">creator account</a>. None of your existing workflows, apps, or other stored data will be published. Any admin in your organization can manage the creator configuration. Becoming a creator organization IS reversible.<div/>Support: <a href="mailto:support@shuffler.io"target="_blank" style={{ textDecoration: "none", color: "#f86a3e"}}>support@shuffler.io</a>
|
||||
</Typography>
|
||||
{selectedOrganization.creator_id == "" ?
|
||||
@@ -167,9 +194,8 @@ const Branding = (props) => {
|
||||
null
|
||||
}
|
||||
|
||||
|
||||
<Button
|
||||
style={{ height: 40, marginTop: 10, width: 300, }}
|
||||
style={{ height: 40, marginTop: 10, width: 300, textTransform: 'none', fontSize: 18, backgroundColor: "#ff8544", color: "#1a1a1a" }}
|
||||
variant={selectedOrganization.creator_id == "" ? "contained" : "outlined"}
|
||||
color={selectedOrganization.creator_id == "" ? "primary" : "secondary"}
|
||||
disabled={!isOrganizationReady()}
|
||||
@@ -195,6 +221,8 @@ const Branding = (props) => {
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import React, { useState, useEffect, useContext, memo } from "react";
|
||||
import theme from "../theme.jsx";
|
||||
import { toast } from 'react-toastify';
|
||||
import ReactJson from "react-json-view-ssr";
|
||||
@@ -19,6 +19,7 @@ import {
|
||||
Dialog,
|
||||
DialogTitle,
|
||||
DialogActions,
|
||||
Skeleton,
|
||||
} from "@mui/material";
|
||||
|
||||
import {
|
||||
@@ -47,6 +48,7 @@ import {
|
||||
VisibilityOff as VisibilityOffIcon,
|
||||
} from "@mui/icons-material";
|
||||
import { validateJson, } from "../views/Workflows.jsx";
|
||||
import { Context } from "../context/ContextApi.jsx";
|
||||
|
||||
const scrollStyle1 = {
|
||||
height: 100,
|
||||
@@ -65,7 +67,7 @@ const scrollStyle2 = {
|
||||
}
|
||||
|
||||
|
||||
const CacheView = (props) => {
|
||||
const CacheView = memo((props) => {
|
||||
const { globalUrl, userdata, serverside, orgId, isSelectedDataStore } = props;
|
||||
const [orgCache, setOrgCache] = React.useState("");
|
||||
const [listCache, setListCache] = React.useState([]);
|
||||
@@ -78,11 +80,13 @@ const CacheView = (props) => {
|
||||
const [cacheCursor, setCacheCursor] = React.useState("");
|
||||
const [dataValue, setDataValue] = React.useState({});
|
||||
const [editCache, setEditCache] = React.useState(false);
|
||||
const [cachedLoaded, setCachedLoaded] = React.useState(false);
|
||||
const [show, setShow] = useState({});
|
||||
|
||||
useEffect(() => {
|
||||
listOrgCache(orgId);
|
||||
}, []);
|
||||
if(orgId?.length >0){
|
||||
listOrgCache(orgId);
|
||||
}
|
||||
}, [orgId]);
|
||||
|
||||
const listOrgCache = (orgId) => {
|
||||
fetch(globalUrl + `/api/v1/orgs/${orgId}/list_cache`, {
|
||||
@@ -104,6 +108,7 @@ const CacheView = (props) => {
|
||||
.then((responseJson) => {
|
||||
if (responseJson.success === true) {
|
||||
setListCache(responseJson.keys);
|
||||
setCachedLoaded(true);
|
||||
}
|
||||
|
||||
if (responseJson.cursor !== undefined && responseJson.cursor !== null && responseJson.cursor !== "") {
|
||||
@@ -232,6 +237,34 @@ const CacheView = (props) => {
|
||||
}
|
||||
}
|
||||
|
||||
const handleReactJsonClipboard = (copy) => {
|
||||
const elementName = "copy_element_shuffle";
|
||||
let copyText = document.getElementById(elementName);
|
||||
|
||||
if (copyText) {
|
||||
if (copy.namespace && copy.name && copy.src) {
|
||||
copy = copy.src;
|
||||
}
|
||||
|
||||
const clipboard = navigator.clipboard;
|
||||
if (!clipboard) {
|
||||
toast("Can only copy over HTTPS (port 3443)");
|
||||
return;
|
||||
}
|
||||
|
||||
let stringified = JSON.stringify(copy);
|
||||
if (stringified.startsWith('"') && stringified.endsWith('"')) {
|
||||
stringified = stringified.slice(1, -1);
|
||||
}
|
||||
|
||||
navigator.clipboard.writeText(stringified);
|
||||
toast("Copied value to clipboard, NOT json path.");
|
||||
} else {
|
||||
console.log("Failed to copy from " + elementName + ": ", copyText);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const modalView = (
|
||||
// console.log("key:", dataValue.key),
|
||||
//console.log("value:",dataValue.value),
|
||||
@@ -241,11 +274,23 @@ const CacheView = (props) => {
|
||||
setModalOpen(false);
|
||||
}}
|
||||
PaperProps={{
|
||||
style: {
|
||||
backgroundColor: theme.palette.surfaceColor,
|
||||
color: "white",
|
||||
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,
|
||||
},
|
||||
},
|
||||
}}
|
||||
>
|
||||
@@ -254,7 +299,7 @@ const CacheView = (props) => {
|
||||
{ editCache ? "Edit Cache" : "Add Cache" }
|
||||
</span>
|
||||
</DialogTitle>
|
||||
<div style={{ paddingLeft: "30px", paddingRight: '30px' }}>
|
||||
<div style={{ paddingLeft: "30px", paddingRight: '30px', backgroundColor: "#212121", }}>
|
||||
Key
|
||||
<TextField
|
||||
color="primary"
|
||||
@@ -278,7 +323,7 @@ const CacheView = (props) => {
|
||||
onChange={(e) => setKey(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div style={{ paddingLeft: 30, paddingRight: 30 }}>
|
||||
<div style={{ paddingLeft: 30, paddingRight: 30, backgroundColor: "#212121" }}>
|
||||
<div style={{display: "flex", }}>
|
||||
<Typography style={{marginTop: 25, marginBottom: 0, flex: 20, }}>
|
||||
Value - ({isValidJson.valid === true ? "Valid" : "Invalid"} JSON)
|
||||
@@ -320,7 +365,7 @@ const CacheView = (props) => {
|
||||
</div>
|
||||
<DialogActions style={{ paddingLeft: "30px", paddingRight: '30px' }}>
|
||||
<Button
|
||||
style={{ borderRadius: "0px" }}
|
||||
style={{ borderRadius: "2px", fontSize: 16, color: "#ff8544", textTransform:"none" }}
|
||||
onClick={() => {
|
||||
setModalOpen(false)
|
||||
setValue("")
|
||||
@@ -332,7 +377,7 @@ const CacheView = (props) => {
|
||||
</Button>
|
||||
<Button
|
||||
variant="contained"
|
||||
style={{ borderRadius: "0px" }}
|
||||
style={{ borderRadius: "2px", backgroundColor: "#ff8544",color: "#1a1a1a", textTransform:"none" }}
|
||||
onClick={() => {
|
||||
{editCache ? editOrgCache(orgId) : addOrgCache(orgId)}
|
||||
|
||||
@@ -348,10 +393,11 @@ const CacheView = (props) => {
|
||||
);
|
||||
|
||||
return (
|
||||
|
||||
<div style={{paddingBottom: isSelectedDataStore?null:250, width: isSelectedDataStore?1030:null, padding:isSelectedDataStore?27:null, height: isSelectedDataStore?"auto":null, color: isSelectedDataStore?'#ffffff':null, backgroundColor: isSelectedDataStore?'#212121':null, borderRadius: isSelectedDataStore?'16px':null, }}>
|
||||
<div style={{paddingBottom: isSelectedDataStore?null:250, minHeight: 1000, boxSizing: "border-box", width: isSelectedDataStore? "100%" :null, transition: "width 0.3s ease", padding:isSelectedDataStore?"27px 10px 27px 27px":null, height: isSelectedDataStore?"100%":null, color: isSelectedDataStore?'#ffffff':null, backgroundColor: isSelectedDataStore?'#212121':null, borderTopRightRadius: isSelectedDataStore?'8px':null, borderBottomRightRadius: isSelectedDataStore?'8px':null, borderLeft: "1px solid #494949" }}>
|
||||
{modalView}
|
||||
<div style={{ marginTop: isSelectedDataStore?null:20, marginBottom: 20 }}>
|
||||
<div style={{height: "100%", maxHeight: 1700, overflowY: "auto", scrollbarColor: '#494949 transparent', scrollbarWidth: 'thin'}}>
|
||||
<div style={{ height: "100%", width: "calc(100% - 20px)", scrollbarColor: '#494949 transparent', scrollbarWidth: 'thin' }}>
|
||||
<div style={{ marginTop: isSelectedDataStore?null:20, marginBottom: 20 }}>
|
||||
<h2 style={{ display: isSelectedDataStore?null: "inline" }}>Shuffle Datastore</h2>
|
||||
<span style={{ marginLeft: isSelectedDataStore?null:25, color:isSelectedDataStore?"#9E9E9E":null}}>
|
||||
Datastore is a permanent key-value database for storing data that can be used cross-workflow. <br/>You can store anything from lists of IPs to complex configurations.
|
||||
@@ -366,7 +412,7 @@ const CacheView = (props) => {
|
||||
</span>
|
||||
</div>
|
||||
<Button
|
||||
style={{backgroundColor: isSelectedDataStore?'rgba(255, 132, 68, 0.2)':null, boxShadow: isSelectedDataStore ? "none":null,textTransform: isSelectedDataStore ? 'capitalize':null, color:isSelectedDataStore?"#FF8444":null, borderRadius:isSelectedDataStore?200:null, width:isSelectedDataStore?162:null, height:isSelectedDataStore?40:null}}
|
||||
style={{backgroundColor: isSelectedDataStore? "#ff8544":null, fontSize: 16, boxShadow: isSelectedDataStore ? "none":null,textTransform: isSelectedDataStore ? 'capitalize':null, color:isSelectedDataStore?"#1a1a1a":null, borderRadius:isSelectedDataStore?8:null, width:isSelectedDataStore?162:null, height:isSelectedDataStore?40:null}}
|
||||
variant="contained"
|
||||
color="primary"
|
||||
onClick={() =>{
|
||||
@@ -379,7 +425,7 @@ const CacheView = (props) => {
|
||||
Add Cache
|
||||
</Button>
|
||||
<Button
|
||||
style={{ marginLeft: 5, marginRight: 15, backgroundColor: isSelectedDataStore?"#2F2F2F":null, boxShadow: isSelectedDataStore ? "none":null,textTransform: isSelectedDataStore ? 'capitalize':null,borderRadius:isSelectedDataStore?200:null, width:isSelectedDataStore?81:null, height:isSelectedDataStore?40:null, }}
|
||||
style={{ marginLeft: 5, marginRight: 15, backgroundColor: isSelectedDataStore?"#2F2F2F":null, boxShadow: isSelectedDataStore ? "none":null,textTransform: isSelectedDataStore ? 'capitalize':null,borderRadius:isSelectedDataStore?8:null, width:isSelectedDataStore?81:null, height:isSelectedDataStore?40:null, }}
|
||||
variant="contained"
|
||||
color="primary"
|
||||
onClick={() => listOrgCache(orgId)}
|
||||
@@ -392,28 +438,79 @@ const CacheView = (props) => {
|
||||
marginBottom: 20,
|
||||
}}
|
||||
/>}
|
||||
<List style={{borderRadius: isSelectedDataStore?8:null, border:isSelectedDataStore?"1px solid #494949":null, marginTop:isSelectedDataStore?24:null}}>
|
||||
<ListItem style={{width: isSelectedDataStore?"100%":null, borderBottom:isSelectedDataStore?"1px solid #494949":null}}>
|
||||
<ListItemText
|
||||
primary="Key"
|
||||
style={{ minWidth: isSelectedDataStore?200:250, maxWidth: isSelectedDataStore?200:250, }}
|
||||
/>
|
||||
<ListItemText
|
||||
primary="Value"
|
||||
style={{ minWidth: isSelectedDataStore?300:400, maxWidth: isSelectedDataStore?300:400, overflowX: "auto", overflowY: "hidden", }}
|
||||
/>
|
||||
<ListItemText
|
||||
primary="Actions"
|
||||
style={{ minWidth: 150, maxWidth: 150, marginLeft: isSelectedDataStore?80:null,}}
|
||||
/>
|
||||
<ListItemText
|
||||
style={{textAlign:isSelectedDataStore?"center":null}}
|
||||
primary="Updated"
|
||||
/>
|
||||
<div
|
||||
style={{
|
||||
borderRadius: 8,
|
||||
marginTop: 24,
|
||||
border: "1px solid #494949",
|
||||
width: "100%",
|
||||
overflowX: "auto",
|
||||
paddingBottom: 0,
|
||||
}}
|
||||
>
|
||||
<List
|
||||
style={{
|
||||
borderRadius: 8,
|
||||
paddingBottom: 0,
|
||||
tableLayout: "auto",
|
||||
display: "table",
|
||||
width: '100%',
|
||||
minWidth: 800,
|
||||
overflowX: "auto",
|
||||
}}>
|
||||
<ListItem style={{width: isSelectedDataStore?"100%":null, borderBottom:isSelectedDataStore?"1px solid #494949":null, display: "table-row"}}>
|
||||
{["Key", "Value", "Actions", "Updated"].map((header, index) => (
|
||||
<ListItemText
|
||||
key={index}
|
||||
primary={header}
|
||||
style={{
|
||||
display: "table-cell",
|
||||
padding: "0px 8px 8px 8px",
|
||||
whiteSpace: "nowrap",
|
||||
overflow: "hidden",
|
||||
textOverflow: "ellipsis",
|
||||
borderBottom: "1px solid #494949"
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</ListItem>
|
||||
{listCache === undefined || listCache === null
|
||||
? null
|
||||
: listCache.map((data, index) => {
|
||||
{cachedLoaded === false
|
||||
? [...Array(6)].map((_, rowIndex) => (
|
||||
<ListItem
|
||||
key={rowIndex}
|
||||
style={{
|
||||
display: "table-row",
|
||||
backgroundColor: "#212121",
|
||||
}}
|
||||
>
|
||||
{Array(4)
|
||||
.fill()
|
||||
.map((_, colIndex) => (
|
||||
<ListItemText
|
||||
key={colIndex}
|
||||
style={{
|
||||
display: "table-cell",
|
||||
padding: "8px",
|
||||
}}
|
||||
>
|
||||
<Skeleton
|
||||
variant="text"
|
||||
animation="wave"
|
||||
sx={{
|
||||
backgroundColor: "#1a1a1a",
|
||||
height: "20px",
|
||||
borderRadius: "4px",
|
||||
}}
|
||||
/>
|
||||
</ListItemText>
|
||||
))}
|
||||
</ListItem>
|
||||
))
|
||||
: listCache?.length === 0 ? (
|
||||
<Typography style={{ textAlign: "center", marginTop: 20, marginBottom: 20, minWidth: 1000, }}>
|
||||
No Keys Found
|
||||
</Typography>
|
||||
): listCache?.map((data, index) => {
|
||||
var bgColor = isSelectedDataStore? "#212121":"#27292d";
|
||||
if (index % 2 === 0) {
|
||||
bgColor = isSelectedDataStore? "#1A1A1A":"#1f2023";
|
||||
@@ -421,49 +518,61 @@ const CacheView = (props) => {
|
||||
|
||||
const validate = validateJson(data.value);
|
||||
return (
|
||||
<ListItem key={index} style={{ backgroundColor: bgColor, maxHeight: 300, overflow: "auto", }}>
|
||||
<ListItem key={index} style={{display:'table-row', backgroundColor: bgColor, maxHeight: 300, overflow: "auto", borderBottomLeftRadius: listCache?.length - 1 === index ? 8 : 0, borderBottomRightRadius: listCache?.length - 1 === index ? 8 : 0}}>
|
||||
<ListItemText
|
||||
style={{
|
||||
maxWidth: 200,
|
||||
minWidth: 200,
|
||||
display: "table-cell",
|
||||
overflow: "hidden",
|
||||
padding: 8,
|
||||
verticalAlign: "middle",
|
||||
}}
|
||||
primary={data.key}
|
||||
/>
|
||||
<ListItemText
|
||||
style={{
|
||||
minWidth: 300,
|
||||
maxWidth: 300,
|
||||
// height:200,
|
||||
overflowX: "hidden",
|
||||
display: "table-cell",
|
||||
overflowY: "auto",
|
||||
overflowX: "auto",
|
||||
border: "1px solid rgba(255,255,255,0.7)",
|
||||
borderRadius: 6,
|
||||
backgroundColor: "#151515",
|
||||
maxHeight: 300,
|
||||
verticalAlign: "middle",
|
||||
}}
|
||||
primary={validate.valid ?
|
||||
<ReactJson
|
||||
src={validate.result}
|
||||
theme={theme.palette.jsonTheme}
|
||||
style={theme.palette.reactJsonStyle}
|
||||
collapsed={true}
|
||||
enableClipboard={(copy) => {
|
||||
//handleReactJsonClipboard(copy);
|
||||
}}
|
||||
displayDataTypes={false}
|
||||
onSelect={(select) => {
|
||||
//HandleJsonCopy(showResult, select, data.action.label);
|
||||
//console.log("SELECTED!: ", select);
|
||||
}}
|
||||
name={"value"}
|
||||
/>
|
||||
primary={validate.valid ?
|
||||
<ReactJson
|
||||
src={validate.result}
|
||||
theme={theme.palette.jsonTheme}
|
||||
style={{
|
||||
padding: 5,
|
||||
maxHeight: 300,
|
||||
overflowY: "auto",
|
||||
}}
|
||||
collapsed={true}
|
||||
enableClipboard={(copy) => {
|
||||
// handleReactJsonClipboard(copy);
|
||||
}}
|
||||
collapseStringsAfterLength={theme.palette.jsonCollapseStringsAfterLength}
|
||||
iconStyle={theme.palette.jsonIconStyle}
|
||||
displayDataTypes={false}
|
||||
onSelect={(select) => {
|
||||
// HandleJsonCopy(showResult, select, data.action.label);
|
||||
console.log("SELECTED!: ", select);
|
||||
}}
|
||||
name={"value"}
|
||||
/>
|
||||
:
|
||||
data.value
|
||||
}
|
||||
/>
|
||||
<ListItemText
|
||||
style={{
|
||||
maxWidth: 200,
|
||||
minWidth: 200,
|
||||
marginLeft: 50,
|
||||
display: "table-cell",
|
||||
verticalAlign: "middle",
|
||||
padding: 8
|
||||
}}
|
||||
primary=<span style={{ display: "inline" }}>
|
||||
primary={(
|
||||
<span style={{ display: "inline" }}>
|
||||
<Tooltip
|
||||
title="Edit item"
|
||||
style={{}}
|
||||
@@ -482,9 +591,7 @@ const CacheView = (props) => {
|
||||
setModalOpen(true)
|
||||
}}
|
||||
>
|
||||
<EditIcon
|
||||
style={{ color: "white" }}
|
||||
/>
|
||||
<img src="/icons/editIcon.svg" alt="edit" />
|
||||
</IconButton>
|
||||
</span>
|
||||
</Tooltip>
|
||||
@@ -508,7 +615,6 @@ const CacheView = (props) => {
|
||||
</Tooltip>
|
||||
<Tooltip
|
||||
title={"Delete item"}
|
||||
style={{ marginLeft: 25, }}
|
||||
aria-label={"Delete"}
|
||||
>
|
||||
<span>
|
||||
@@ -519,18 +625,18 @@ const CacheView = (props) => {
|
||||
//deleteFile(orgId);
|
||||
}}
|
||||
>
|
||||
<DeleteIcon
|
||||
style={{ color: "white" }}
|
||||
/>
|
||||
<img src="/icons/deleteIcon.svg" alt="delete" />
|
||||
</IconButton>
|
||||
</span>
|
||||
</Tooltip>
|
||||
</span>
|
||||
)}
|
||||
/>
|
||||
<ListItemText
|
||||
style={{
|
||||
maxWidth: 225,
|
||||
minWidth: 225,
|
||||
display: "table-cell",
|
||||
verticalAlign: "middle",
|
||||
padding: 8
|
||||
}}
|
||||
primary={new Date(data.edited * 1000).toISOString()}
|
||||
/>
|
||||
@@ -538,8 +644,11 @@ const CacheView = (props) => {
|
||||
);
|
||||
})}
|
||||
</List>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
);
|
||||
}
|
||||
export default CacheView;
|
||||
});
|
||||
|
||||
export default memo(CacheView);
|
||||
|
||||
@@ -1149,7 +1149,7 @@ const EditWorkflow = (props) => {
|
||||
</div>
|
||||
: null}
|
||||
|
||||
{/*!isEditing ? <>
|
||||
{!isEditing ? <>
|
||||
<div style={{ marginTop: 20, }}>
|
||||
<FormControlLabel
|
||||
control={<Checkbox />}
|
||||
@@ -1164,7 +1164,7 @@ const EditWorkflow = (props) => {
|
||||
/>
|
||||
|
||||
</div>
|
||||
</> : null*/}
|
||||
</> : null}
|
||||
|
||||
<Tooltip color="primary" title={"Add more details"} placement="top">
|
||||
<Button
|
||||
|
||||
+398
-330
@@ -1,4 +1,4 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import React, { useState, useEffect, useContext, memo } from "react";
|
||||
import { toast } from 'react-toastify';
|
||||
|
||||
import {
|
||||
@@ -21,6 +21,7 @@ import {
|
||||
DialogContent,
|
||||
DialogActions,
|
||||
Typography,
|
||||
Skeleton,
|
||||
} from "@mui/material";
|
||||
|
||||
import {
|
||||
@@ -39,11 +40,13 @@ import {
|
||||
import Dropzone from "../components/Dropzone.jsx";
|
||||
import ShuffleCodeEditor from "../components/ShuffleCodeEditor1.jsx";
|
||||
import theme from "../theme.jsx";
|
||||
import { Context } from "../context/ContextApi.jsx";
|
||||
|
||||
const Files = (props) => {
|
||||
const Files = memo((props) => {
|
||||
const { globalUrl, userdata, serverside, selectedOrganization, isCloud,isSelectedFiles } = props;
|
||||
|
||||
const [files, setFiles] = React.useState([]);
|
||||
const [showLoader, setShowLoader] = useState(true)
|
||||
const [selectedCategory, setSelectedCategory] = React.useState("default");
|
||||
const [openFileId, setOpenFileId] = React.useState(false);
|
||||
const [fileCategories, setFileCategories] = React.useState([]);
|
||||
@@ -58,16 +61,13 @@ const Files = (props) => {
|
||||
const [downloadBranch, setDownloadBranch] = React.useState("main");
|
||||
const [downloadFolder, setDownloadFolder] = React.useState("translation_standards");
|
||||
const [contentLoading, setContentLoading] = React.useState(false)
|
||||
|
||||
//const alert = useAlert();
|
||||
const allowedFileTypes = ["txt", "py", "yaml", "yml","json", "html", "js", "csv", "log", "eml", "msg", "md", "xml", "sh", "bat", "ps1", "psm1", "psd1", "ps1xml", "pssc", "psc1", "response"]
|
||||
var upload = "";
|
||||
|
||||
const handleKeyDown = (event) => {
|
||||
if (event.key === 'Enter') {
|
||||
|
||||
console.log('do validate')
|
||||
console.log("new namespace name->",event.target.value);
|
||||
|
||||
fileCategories.push(event.target.value);
|
||||
setSelectedCategory(event.target.value);
|
||||
setRenderTextBox(false);
|
||||
@@ -136,6 +136,7 @@ const Files = (props) => {
|
||||
.then((responseJson) => {
|
||||
if (responseJson.files !== undefined && responseJson.files !== null) {
|
||||
setFiles(responseJson.files);
|
||||
setShowLoader(false)
|
||||
} else if (responseJson.list !== undefined && responseJson.list !== null) {
|
||||
// Set the "namespace" field in all items
|
||||
if (namespace !== undefined && namespace !== null) {
|
||||
@@ -147,8 +148,10 @@ const Files = (props) => {
|
||||
}
|
||||
|
||||
setFiles(responseJson.list);
|
||||
setShowLoader(false)
|
||||
} else {
|
||||
setFiles([]);
|
||||
setShowLoader(false)
|
||||
}
|
||||
|
||||
if (namespace === undefined || namespace === null || namespace === "default") {
|
||||
@@ -244,15 +247,27 @@ const Files = (props) => {
|
||||
const fileDownloadModal = loadFileModalOpen ?
|
||||
<Dialog
|
||||
open={loadFileModalOpen}
|
||||
onClose={() => {}}
|
||||
PaperProps={{
|
||||
style: {
|
||||
backgroundColor: theme.palette.surfaceColor,
|
||||
color: "white",
|
||||
minWidth: "800px",
|
||||
minHeight: "320px",
|
||||
},
|
||||
}}
|
||||
sx: {
|
||||
borderRadius: theme?.palette?.DialogStyle?.borderRadius,
|
||||
border: theme?.palette?.DialogStyle?.border,
|
||||
fontFamily: theme?.typography?.fontFamily,
|
||||
backgroundColor: theme?.palette?.DialogStyle?.backgroundColor,
|
||||
zIndex: 1000,
|
||||
minWidth: "800px",
|
||||
minHeight: "320px",
|
||||
overflow: "hidden",
|
||||
'& .MuiDialogContent-root': {
|
||||
backgroundColor: theme?.palette?.DialogStyle?.backgroundColor,
|
||||
},
|
||||
'& .MuiDialogTitle-root': {
|
||||
backgroundColor: theme?.palette?.DialogStyle?.backgroundColor,
|
||||
},
|
||||
'& .MuiDialogActions-root': {
|
||||
backgroundColor: theme?.palette?.DialogStyle?.backgroundColor,
|
||||
},
|
||||
}
|
||||
}}
|
||||
>
|
||||
<DialogTitle>
|
||||
<div style={{ color: "rgba(255,255,255,0.9)" }}>
|
||||
@@ -364,7 +379,7 @@ const Files = (props) => {
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button
|
||||
style={{ borderRadius: "0px" }}
|
||||
style={{ borderRadius: "2px", textTransform: 'none', fontSize:16, color: "#ff8544" }}
|
||||
onClick={() => setLoadFileModalOpen(false)}
|
||||
color="primary"
|
||||
>
|
||||
@@ -372,7 +387,7 @@ const Files = (props) => {
|
||||
</Button>
|
||||
<Button
|
||||
variant="contained"
|
||||
style={{ borderRadius: "0px" }}
|
||||
style={{ borderRadius: "2px", textTransform: 'none', fontSize:16, color: "#1a1a1a", backgroundColor: "#ff8544" }}
|
||||
disabled={downloadUrl.length === 0 || !downloadUrl.includes("http")}
|
||||
onClick={() => {
|
||||
handleGithubValidation();
|
||||
@@ -637,24 +652,18 @@ const Files = (props) => {
|
||||
return (
|
||||
<Dropzone
|
||||
style={{
|
||||
maxWidth: window.innerWidth > 1366 ? 1366 : 1200,
|
||||
margin: "auto",
|
||||
padding: isSelectedFiles ? null : 20,
|
||||
width: '100%',
|
||||
height: "100%",
|
||||
}}
|
||||
onDrop={uploadFile}
|
||||
>
|
||||
<div style={{position: "relative", width: isSelectedFiles? 1030: null, padding:isSelectedFiles?27:null, height: isSelectedFiles?"auto":null, color: isSelectedFiles?'#ffffff':null, backgroundColor: isSelectedFiles?'#212121':null, borderRadius: isSelectedFiles?'16px':null,}}>
|
||||
<div style={{width: "100%", minHeight: 1100, boxSizing: 'border-box', padding: "27px 10px 19px 27px", height:"100%", backgroundColor: '#212121',borderTopRightRadius: '8px', borderBottomRightRadius: 8, borderLeft: "1px solid #494949", }}>
|
||||
|
||||
<Tooltip color="primary" title={"Import files to Shuffle from Git"} placement="top">
|
||||
<IconButton
|
||||
color="secondary"
|
||||
style={{position: "absolute", right: 0, top: isSelectedFiles?null:0, left: isSelectedFiles? 990:null }}
|
||||
variant="text"
|
||||
onClick={() => setLoadFileModalOpen(true)}
|
||||
>
|
||||
<CloudDownloadIcon />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
<div style={{height: "100%", maxHeight: 1700,overflowY: 'auto', scrollbarColor: '#494949 transparent', scrollbarWidth: 'thin'}}>
|
||||
<div style={{ height: "100%", width: "calc(100% - 20px)", scrollbarColor: '#494949 transparent', scrollbarWidth: 'thin' }}>
|
||||
<DownloadFileIcon setLoadFileModalOpen={setLoadFileModalOpen} isSelectedFiles={isSelectedFiles} />
|
||||
|
||||
{fileDownloadModal}
|
||||
|
||||
@@ -681,9 +690,9 @@ const Files = (props) => {
|
||||
onClick={() => {
|
||||
upload.click();
|
||||
}}
|
||||
style={{backgroundColor: isSelectedFiles?'rgba(255, 132, 68, 0.2)':null, color:isSelectedFiles?"#FF8444":null, borderRadius:isSelectedFiles?200:null, width:isSelectedFiles?162:null, height:isSelectedFiles?40:null, boxShadow: isSelectedFiles?'none':null,}}
|
||||
style={{backgroundColor: isSelectedFiles?'#ff8544':null, color:isSelectedFiles?"#212121":null, textTransform: 'none',fontSize: 16, borderRadius:isSelectedFiles?8:null, width:isSelectedFiles?143:null, height:isSelectedFiles?35:null, boxShadow: isSelectedFiles?'none':null,}}
|
||||
>
|
||||
<PublishIcon /> Upload files
|
||||
Upload files
|
||||
</Button>
|
||||
{/* <FileCategoryInput
|
||||
isSet={renderTextBox} /> */}
|
||||
@@ -702,7 +711,7 @@ const Files = (props) => {
|
||||
}}
|
||||
/>
|
||||
<Button
|
||||
style={{ marginLeft: 5, marginRight: 15, backgroundColor:isSelectedFiles?"#2F2F2F":null,borderRadius:isSelectedFiles?200:null, width:isSelectedFiles?81:null, height:isSelectedFiles?40:null, boxShadow: isSelectedFiles?'none':null, }}
|
||||
style={{ marginLeft: 16, marginRight: 15, backgroundColor:isSelectedFiles?"#2F2F2F":null,borderRadius:isSelectedFiles?8:null, width:isSelectedFiles?81:null, height:isSelectedFiles?35:null, boxShadow: isSelectedFiles?'none':null, }}
|
||||
variant="contained"
|
||||
color="primary"
|
||||
onClick={() => getFiles(selectedCategory)}
|
||||
@@ -710,21 +719,23 @@ const Files = (props) => {
|
||||
<CachedIcon />
|
||||
</Button>
|
||||
|
||||
|
||||
{/* <div style={{height: 35, width: 1, color: "#494949"}}></div> */}
|
||||
|
||||
{fileCategories !== undefined &&
|
||||
fileCategories !== null &&
|
||||
fileCategories.length > 1 ? (
|
||||
<FormControl style={{ minWidth: 150, maxWidth: 150 }}>
|
||||
<InputLabel id="input-namespace-label">File Category</InputLabel>
|
||||
<Select
|
||||
labelId="input-namespace-select-label"
|
||||
id="input-namespace-select-id"
|
||||
style={{
|
||||
color: "white",
|
||||
minWidth: 150,
|
||||
maxWidth: 150,
|
||||
minWidth: 122,
|
||||
maxWidth: 122,
|
||||
height: 35,
|
||||
float: "right",
|
||||
position: 'relative',
|
||||
top: 8
|
||||
}}
|
||||
value={selectedCategory}
|
||||
onChange={(event) => {
|
||||
@@ -759,7 +770,7 @@ const Files = (props) => {
|
||||
</Select>
|
||||
</FormControl>
|
||||
) : null}
|
||||
<div style={{display: "inline-flex", position:"relative"}}>
|
||||
<div style={{display: "inline-flex", position:"relative", top: 8}}>
|
||||
{renderTextBox ?
|
||||
|
||||
<Tooltip title={"Close"} style={{}} aria-label={""}>
|
||||
@@ -777,13 +788,14 @@ const Files = (props) => {
|
||||
:
|
||||
<Tooltip title={"Add new file category"} style={{}} aria-label={""}>
|
||||
<Button
|
||||
style={{ marginLeft: 5, marginRight: 15 }}
|
||||
style={{ marginLeft: 5, marginRight: 15, width: 169, height: 35, backgroundColor: "#494949", textTransform: 'none', fontSize: 16, color: "#f1f1f1" }}
|
||||
color="primary"
|
||||
onClick={() => {
|
||||
setRenderTextBox(true);
|
||||
}}
|
||||
>
|
||||
<AddIcon/>
|
||||
File Category
|
||||
</Button>
|
||||
</Tooltip>
|
||||
}
|
||||
@@ -824,323 +836,379 @@ const Files = (props) => {
|
||||
backgroundColor: theme.palette.inputColor,
|
||||
}}
|
||||
/>}
|
||||
|
||||
<List style={{borderRadius: isSelectedFiles?8:null, border:isSelectedFiles?"1px solid #494949":null, marginTop:isSelectedFiles?24:null}}>
|
||||
<ListItem style={{width:isSelectedFiles?"100%":null, borderBottom:isSelectedFiles?"1px solid #494949":null}}>
|
||||
{/*
|
||||
<ListItemText
|
||||
primary="Updated"
|
||||
style={{ maxWidth: 185, minWidth: 185 }}
|
||||
/>
|
||||
*/}
|
||||
<ListItemText
|
||||
primary="Name"
|
||||
style={{
|
||||
maxWidth: 250,
|
||||
minWidth: 250,
|
||||
overflow: "hidden",
|
||||
marginLeft: 10,
|
||||
<div
|
||||
style={{
|
||||
borderRadius: 8,
|
||||
marginTop: 24,
|
||||
border: "1px solid #494949",
|
||||
width: "100%",
|
||||
overflowX: "auto",
|
||||
paddingBottom: 0,
|
||||
}}
|
||||
>
|
||||
<List
|
||||
style={{
|
||||
width: '100%',
|
||||
tableLayout: "auto",
|
||||
display: "table",
|
||||
minWidth: 800,
|
||||
overflowX: "auto"
|
||||
}}
|
||||
>
|
||||
<ListItem style={{width:isSelectedFiles?"100%":null, borderBottom:isSelectedFiles?"1px solid #494949":null, display: 'table-row'}}>
|
||||
{["Name", "Workflow", "Md5", "Status", "Filesize", "Actions"].map((header, index) => (
|
||||
<ListItemText
|
||||
key={index}
|
||||
primary={header}
|
||||
style={{
|
||||
display: "table-cell",
|
||||
padding: "0px 8px 8px 8px",
|
||||
whiteSpace: "nowrap",
|
||||
textOverflow: "ellipsis",
|
||||
borderBottom: "1px solid #494949",
|
||||
verticalAlign: "middle"
|
||||
}}
|
||||
primaryTypographyProps={{
|
||||
style: {
|
||||
paddingLeft: index === 3 ? 80 : 10,
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<ListItemText
|
||||
primary="Workflow"
|
||||
style={{ maxWidth: 100, minWidth: 100, overflow: "hidden" }}
|
||||
/>
|
||||
<ListItemText
|
||||
primary="Md5"
|
||||
style={{ minWidth: 300, maxWidth: 300, overflow: "hidden" }}
|
||||
/>
|
||||
<ListItemText
|
||||
primary="Status"
|
||||
style={{ minWidth: 75, maxWidth: 75, marginLeft: 10 }}
|
||||
/>
|
||||
<ListItemText
|
||||
primary="Filesize"
|
||||
style={{ minWidth: 125, maxWidth: 125 }}
|
||||
/>
|
||||
<ListItemText primary="Actions" />
|
||||
/>
|
||||
))}
|
||||
</ListItem>
|
||||
{files === undefined || files === null || files.length === 0 ? null :
|
||||
files.map((file, index) => {
|
||||
if (file.namespace === "") {
|
||||
file.namespace = "default";
|
||||
}
|
||||
|
||||
if (file.namespace !== selectedCategory) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var bgColor = isSelectedFiles ? "#212121":"#27292d";
|
||||
if (index % 2 === 0) {
|
||||
bgColor = isSelectedFiles ? "#1A1A1A":"#1f2023";
|
||||
}
|
||||
|
||||
const filenamesplit = file.filename.split(".")
|
||||
const iseditable = file.filesize < 2000000 && file.status === "active" && allowedFileTypes.includes(filenamesplit[filenamesplit.length-1])
|
||||
|
||||
return (
|
||||
<ListItem
|
||||
key={index}
|
||||
style={{
|
||||
backgroundColor: bgColor,
|
||||
maxHeight: 100,
|
||||
overflow: "hidden",
|
||||
}}
|
||||
>
|
||||
{/*
|
||||
<ListItemText
|
||||
{showLoader ?
|
||||
[...Array(6)].map((_, rowIndex) => (
|
||||
<ListItem
|
||||
key={rowIndex}
|
||||
style={{
|
||||
display: "table-row",
|
||||
backgroundColor: "#212121",
|
||||
}}
|
||||
>
|
||||
{Array(6)
|
||||
.fill()
|
||||
.map((_, colIndex) => (
|
||||
<ListItemText
|
||||
key={colIndex}
|
||||
style={{
|
||||
display: "table-cell",
|
||||
padding: "8px",
|
||||
}}
|
||||
>
|
||||
<Skeleton
|
||||
variant="text"
|
||||
animation="wave"
|
||||
sx={{
|
||||
backgroundColor: "#1a1a1a",
|
||||
height: "20px",
|
||||
borderRadius: "4px",
|
||||
}}
|
||||
/>
|
||||
</ListItemText>
|
||||
))}
|
||||
</ListItem>
|
||||
)):
|
||||
files.length === 0 ? (
|
||||
<div style={{textAlign: "center"}}>
|
||||
<Typography style={{padding: 25, fontSize: 18, textAlign: 'center'}}>
|
||||
No files found
|
||||
</Typography>
|
||||
</div>
|
||||
):(
|
||||
files?.map((file, index) => {
|
||||
if (file.namespace === "") {
|
||||
file.namespace = "default";
|
||||
}
|
||||
|
||||
if (file.namespace !== selectedCategory) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var bgColor = isSelectedFiles ? "#212121":"#27292d";
|
||||
if (index % 2 === 0) {
|
||||
bgColor = isSelectedFiles ? "#1A1A1A":"#1f2023";
|
||||
}
|
||||
|
||||
const filenamesplit = file.filename.split(".")
|
||||
const iseditable = file.filesize < 2000000 && file.status === "active" && allowedFileTypes.includes(filenamesplit[filenamesplit.length-1])
|
||||
return (
|
||||
<ListItem
|
||||
key={index}
|
||||
style={{
|
||||
maxWidth: isSelectedFiles ? 170:225,
|
||||
minWidth: isSelectedFiles ? 170:225,
|
||||
display: 'table-row',
|
||||
backgroundColor: bgColor,
|
||||
maxHeight: 100,
|
||||
overflow: "hidden",
|
||||
borderBottomLeftRadius: files?.length - 1 === index ? 8 : 0,
|
||||
borderBottomRightRadius: files?.length - 1 === index ? 8 : 0,
|
||||
}}
|
||||
primary={new Date(file.updated_at * 1000).toISOString()}
|
||||
/>
|
||||
*/}
|
||||
<ListItemText
|
||||
style={{
|
||||
maxWidth: 250,
|
||||
minWidth: 250,
|
||||
overflow: "hidden",
|
||||
marginLeft: 10,
|
||||
}}
|
||||
primary={file.filename}
|
||||
/>
|
||||
<ListItemText
|
||||
primary={
|
||||
file.workflow_id === "global" || file.workflow_id === "" || file.workflow_id === null || file.workflow_id === undefined ?
|
||||
<IconButton
|
||||
disabled={file.workflow_id === "global"}
|
||||
>
|
||||
<OpenInNewIcon
|
||||
style={{
|
||||
color:
|
||||
file.workflow_id !== "global"
|
||||
? "white"
|
||||
: "grey",
|
||||
}}
|
||||
/>
|
||||
</IconButton>
|
||||
: (
|
||||
>
|
||||
{/*
|
||||
<ListItemText
|
||||
style={{
|
||||
maxWidth: isSelectedFiles ? 170:225,
|
||||
minWidth: isSelectedFiles ? 170:225,
|
||||
overflow: "hidden",
|
||||
}}
|
||||
primary={new Date(file.updated_at * 1000).toISOString()}
|
||||
/>
|
||||
*/}
|
||||
<ListItemText
|
||||
primaryTypographyProps={{
|
||||
style: {
|
||||
display: 'table-cell',
|
||||
maxWidth: "170px",
|
||||
whiteSpace: 'nowrap',
|
||||
textOverflow: 'ellipsis',
|
||||
overflow: 'hidden',
|
||||
padding: 8
|
||||
},
|
||||
}}
|
||||
|
||||
primary={file.filename}
|
||||
/>
|
||||
<ListItemText
|
||||
primary={
|
||||
file.workflow_id === "global" || file.workflow_id === "" || file.workflow_id === null || file.workflow_id === undefined ?
|
||||
<IconButton
|
||||
disabled={file.workflow_id === "global"}
|
||||
style={{marginLeft: 10}}
|
||||
>
|
||||
<OpenInNewIcon
|
||||
style={{
|
||||
color:
|
||||
file.workflow_id !== "global"
|
||||
? "#FF8444"
|
||||
: "grey",
|
||||
}}
|
||||
/>
|
||||
</IconButton>
|
||||
: (
|
||||
<Tooltip
|
||||
title={"Go to workflow"}
|
||||
style={{}}
|
||||
aria-label={"Download"}
|
||||
>
|
||||
<span>
|
||||
<a
|
||||
rel="noopener noreferrer"
|
||||
style={{
|
||||
textDecoration: "none",
|
||||
color: "#f85a3e",
|
||||
}}
|
||||
href={`/workflows/${file.workflow_id}`}
|
||||
target="_blank"
|
||||
>
|
||||
<IconButton
|
||||
disabled={file.workflow_id === "global"}
|
||||
style={{marginLeft: 10}}
|
||||
>
|
||||
<OpenInNewIcon
|
||||
style={{
|
||||
color:
|
||||
file.workflow_id !== "global"
|
||||
? "#FF8444"
|
||||
: "grey",
|
||||
}}
|
||||
/>
|
||||
</IconButton>
|
||||
</a>
|
||||
</span>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
style={{
|
||||
display: 'table-cell',
|
||||
overflow: "hidden",
|
||||
}}
|
||||
/>
|
||||
<ListItemText
|
||||
primary={(
|
||||
<Tooltip title={file.md5_sum}>
|
||||
{file.md5_sum}
|
||||
</Tooltip>
|
||||
)}
|
||||
primaryTypographyProps={{
|
||||
style:{
|
||||
display: 'table-cell',
|
||||
marginLeft:isSelectedFiles? 15:null,
|
||||
overflow: "hidden",
|
||||
whiteSpace: 'nowrap',
|
||||
textOverflow: 'ellipsis',
|
||||
maxWidth: 200,
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<ListItemText
|
||||
primary={file.status}
|
||||
style={{
|
||||
display: 'table-cell',
|
||||
overflow: "hidden",
|
||||
textAlign:isSelectedFiles?"left":null,
|
||||
color: file.status === "active" ? "#2BC07E" : "#FD4C62"
|
||||
}}
|
||||
/>
|
||||
<ListItemText
|
||||
primary={file.filesize}
|
||||
style={{
|
||||
display: 'table-cell',
|
||||
overflow: "hidden",
|
||||
textAlign:'center'
|
||||
}}
|
||||
/>
|
||||
<ListItemText
|
||||
primary=<span style={{ display:"inline"}}>
|
||||
<Tooltip
|
||||
title={"Go to workflow"}
|
||||
title={`Edit File (${allowedFileTypes.join(", ")}). Max size 2MB`}
|
||||
style={{}}
|
||||
aria-label={"Edit"}
|
||||
>
|
||||
<span>
|
||||
<IconButton
|
||||
disabled={!iseditable}
|
||||
style = {{padding: "6px", }}
|
||||
onClick={() => {
|
||||
setOpenEditor(true)
|
||||
setOpenFileId(file.id)
|
||||
readFileData(file)
|
||||
}}
|
||||
>
|
||||
<img src="/icons/editIcon.svg" alt="edit icon"
|
||||
style={{color: iseditable ? "white" : "grey",}}
|
||||
/>
|
||||
</IconButton>
|
||||
</span>
|
||||
</Tooltip>
|
||||
{/*
|
||||
<Tooltip
|
||||
title={"Public URL"}
|
||||
style={{}}
|
||||
>
|
||||
<span>
|
||||
<IconButton
|
||||
style = {{padding: "6px"}}
|
||||
disabled={file.status !== "active"}
|
||||
onClick={() => {
|
||||
// Open the file, without downloading it
|
||||
window.open(`${globalUrl}/api/v1/files/${file.id}/content?type=text&authorization=${file.public_authorization}`, "_blank noreferrer noopener")
|
||||
}}
|
||||
>
|
||||
<LinkIcon
|
||||
style={{
|
||||
color:
|
||||
file.status === "active"
|
||||
? "white"
|
||||
: "grey",
|
||||
}}
|
||||
/>
|
||||
</IconButton>
|
||||
</span>
|
||||
</Tooltip>
|
||||
*/}
|
||||
<Tooltip
|
||||
title={"Download file"}
|
||||
style={{}}
|
||||
aria-label={"Download"}
|
||||
>
|
||||
<span>
|
||||
<a
|
||||
rel="noopener noreferrer"
|
||||
style={{
|
||||
textDecoration: "none",
|
||||
color: "#f85a3e",
|
||||
<IconButton
|
||||
style = {{padding: "6px"}}
|
||||
disabled={file.status !== "active"}
|
||||
onClick={() => {
|
||||
downloadFile(file);
|
||||
}}
|
||||
href={`/workflows/${file.workflow_id}`}
|
||||
target="_blank"
|
||||
>
|
||||
<IconButton
|
||||
disabled={file.workflow_id === "global"}
|
||||
>
|
||||
<OpenInNewIcon
|
||||
style={{
|
||||
color:
|
||||
file.workflow_id !== "global"
|
||||
? "white"
|
||||
: "grey",
|
||||
}}
|
||||
/>
|
||||
</IconButton>
|
||||
</a>
|
||||
<img src="/icons/downloadIcon.svg" alt="download icon"
|
||||
style={{
|
||||
color:
|
||||
file.status === "active"
|
||||
? "white"
|
||||
: "grey",
|
||||
}}
|
||||
/>
|
||||
</IconButton>
|
||||
</span>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
style={{
|
||||
minWidth: 100,
|
||||
maxWidth: 100,
|
||||
overflow: "hidden",
|
||||
textAlign: isSelectedFiles?"center":null
|
||||
}}
|
||||
/>
|
||||
<ListItemText
|
||||
primary={file.md5_sum}
|
||||
style={{
|
||||
minWidth: 300,
|
||||
maxWidth: 300,
|
||||
marginLeft:isSelectedFiles? 15:null,
|
||||
overflow: isSelectedFiles?"auto":"hidden",
|
||||
}}
|
||||
/>
|
||||
<ListItemText
|
||||
primary={file.status}
|
||||
style={{
|
||||
minWidth: 75,
|
||||
maxWidth: 75,
|
||||
overflow: "hidden",
|
||||
textAlign:isSelectedFiles?"center":null,
|
||||
marginLeft: 10,
|
||||
}}
|
||||
/>
|
||||
<ListItemText
|
||||
primary={file.filesize}
|
||||
style={{
|
||||
minWidth: isSelectedFiles?80:125,
|
||||
maxWidth: isSelectedFiles?80:125,
|
||||
marginLeft: isSelectedFiles?15:null,
|
||||
overflow: "hidden",
|
||||
}}
|
||||
/>
|
||||
<ListItemText
|
||||
primary=<span style={{ display:"inline"}}>
|
||||
<Tooltip
|
||||
title={`Edit File (${allowedFileTypes.join(", ")}). Max size 2MB`}
|
||||
style={{}}
|
||||
aria-label={"Edit"}
|
||||
>
|
||||
<span>
|
||||
<IconButton
|
||||
disabled={!iseditable}
|
||||
style = {{padding: "6px"}}
|
||||
onClick={() => {
|
||||
setOpenEditor(true)
|
||||
setOpenFileId(file.id)
|
||||
readFileData(file)
|
||||
}}
|
||||
>
|
||||
<EditIcon
|
||||
style={{color: iseditable ? "white" : "grey",}}
|
||||
/>
|
||||
</IconButton>
|
||||
</span>
|
||||
</Tooltip>
|
||||
{/*
|
||||
<Tooltip
|
||||
title={"Public URL"}
|
||||
style={{}}
|
||||
>
|
||||
<span>
|
||||
<IconButton
|
||||
style = {{padding: "6px"}}
|
||||
disabled={file.status !== "active"}
|
||||
onClick={() => {
|
||||
// Open the file, without downloading it
|
||||
window.open(`${globalUrl}/api/v1/files/${file.id}/content?type=text&authorization=${file.public_authorization}`, "_blank noreferrer noopener")
|
||||
}}
|
||||
>
|
||||
<LinkIcon
|
||||
style={{
|
||||
color:
|
||||
file.status === "active"
|
||||
? "white"
|
||||
: "grey",
|
||||
}}
|
||||
/>
|
||||
</IconButton>
|
||||
</span>
|
||||
</Tooltip>
|
||||
*/}
|
||||
<Tooltip
|
||||
title={"Download file"}
|
||||
style={{}}
|
||||
aria-label={"Download"}
|
||||
>
|
||||
<span>
|
||||
<IconButton
|
||||
style = {{padding: "6px"}}
|
||||
disabled={file.status !== "active"}
|
||||
onClick={() => {
|
||||
downloadFile(file);
|
||||
}}
|
||||
>
|
||||
<CloudDownloadIcon
|
||||
style={{
|
||||
color:
|
||||
file.status === "active"
|
||||
? "white"
|
||||
: "grey",
|
||||
}}
|
||||
/>
|
||||
</IconButton>
|
||||
</span>
|
||||
</Tooltip>
|
||||
<Tooltip
|
||||
title={"Copy file ID"}
|
||||
style={{}}
|
||||
aria-label={"copy"}
|
||||
>
|
||||
<IconButton
|
||||
style = {{padding: "6px"}}
|
||||
onClick={() => {
|
||||
const elementName = "copy_element_shuffle";
|
||||
var copyText =
|
||||
document.getElementById(elementName);
|
||||
if (
|
||||
copyText !== null &&
|
||||
copyText !== undefined
|
||||
) {
|
||||
const clipboard = navigator.clipboard;
|
||||
if (clipboard === undefined) {
|
||||
toast(
|
||||
"Can only copy over HTTPS (port 3443)"
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
navigator.clipboard.writeText(file.id);
|
||||
copyText.select();
|
||||
copyText.setSelectionRange(
|
||||
0,
|
||||
99999
|
||||
); /* For mobile devices */
|
||||
|
||||
/* Copy the text inside the text field */
|
||||
document.execCommand("copy");
|
||||
|
||||
toast(file.id + " copied to clipboard");
|
||||
}
|
||||
}}
|
||||
<Tooltip
|
||||
title={"Copy file ID"}
|
||||
style={{}}
|
||||
aria-label={"copy"}
|
||||
>
|
||||
<FileCopyIcon style={{ color: "white" }} />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
<Tooltip
|
||||
title={"Delete file"}
|
||||
style={{marginLeft: isSelectedFiles?5:15, }}
|
||||
aria-label={"Delete"}
|
||||
>
|
||||
<span>
|
||||
<IconButton
|
||||
disabled={file.status !== "active"}
|
||||
style = {{padding: "6px"}}
|
||||
onClick={() => {
|
||||
deleteFile(file)
|
||||
console.log("file is : ", file)
|
||||
navigator.clipboard.writeText(file.id);
|
||||
document.execCommand("copy");
|
||||
|
||||
toast(file.id + " copied to clipboard");
|
||||
}}
|
||||
>
|
||||
<DeleteIcon
|
||||
style={{
|
||||
color:
|
||||
file.status === "active"
|
||||
? "white"
|
||||
: "grey",
|
||||
}}
|
||||
/>
|
||||
<img src="/icons/copyIcon.svg" alt="copy icon" style={{ color: "white" }} />
|
||||
</IconButton>
|
||||
</span>
|
||||
</Tooltip>
|
||||
</span>
|
||||
style={{
|
||||
minWidth: 250,
|
||||
maxWidth: 250,
|
||||
// overflow: "hidden",
|
||||
}}
|
||||
/>
|
||||
</ListItem>
|
||||
);
|
||||
})
|
||||
</Tooltip>
|
||||
<Tooltip
|
||||
title={"Delete file"}
|
||||
style={{marginLeft: isSelectedFiles?5:15, }}
|
||||
aria-label={"Delete"}
|
||||
>
|
||||
<span>
|
||||
<IconButton
|
||||
disabled={file.status !== "active"}
|
||||
style = {{padding: "6px"}}
|
||||
onClick={() => {
|
||||
deleteFile(file)
|
||||
}}
|
||||
>
|
||||
<img src="/icons/deleteIcon.svg" alt="delete icon"
|
||||
style={{
|
||||
color:
|
||||
file.status === "active"
|
||||
? "white"
|
||||
: "grey",
|
||||
}}
|
||||
/>
|
||||
</IconButton>
|
||||
</span>
|
||||
</Tooltip>
|
||||
</span>
|
||||
style={{
|
||||
display: 'table-cell',
|
||||
textAlign:'center'
|
||||
// overflow: "hidden",
|
||||
}}
|
||||
/>
|
||||
</ListItem>
|
||||
);
|
||||
})
|
||||
)
|
||||
}
|
||||
</List>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Dropzone>
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
export default Files;
|
||||
export default memo(Files);
|
||||
|
||||
|
||||
const DownloadFileIcon = memo(({ setLoadFileModalOpen, isSelectedFiles, }) => {
|
||||
|
||||
const { leftSideBarOpenByClick } = useContext(Context)
|
||||
|
||||
return(
|
||||
<Tooltip color="primary" title={"Import files to Shuffle from Git"} placement="top">
|
||||
<IconButton
|
||||
color="secondary"
|
||||
style={{position: "absolute", right: 0, top: isSelectedFiles?null:0, left: isSelectedFiles? leftSideBarOpenByClick ? "90%": "85%":null, transition: "left 0.3s ease" }}
|
||||
variant="text"
|
||||
onClick={() => setLoadFileModalOpen(true)}
|
||||
>
|
||||
<CloudDownloadIcon />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
)
|
||||
})
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
Add as AddIcon,
|
||||
BorderColor,
|
||||
Close as CloseIcon,
|
||||
ConstructionOutlined,
|
||||
} from "@mui/icons-material";
|
||||
import SearchBox from "./SearchData.jsx";
|
||||
import {
|
||||
@@ -85,7 +86,21 @@ const LeftSideBar = ({ userdata, serverside, globalUrl, notifications, }) => {
|
||||
return orgOptions.find((option) => option.name === selectedOrg);
|
||||
}, [selectedOrg, orgOptions]);
|
||||
|
||||
//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]);
|
||||
|
||||
const CustomPopper = (props) => {
|
||||
return (
|
||||
@@ -141,7 +156,7 @@ const LeftSideBar = ({ userdata, serverside, globalUrl, notifications, }) => {
|
||||
>
|
||||
{props.children}
|
||||
</Box>
|
||||
<Link to="/admin2" style={hrefStyle}>
|
||||
<Link to="/admin?tab=tenants" style={hrefStyle}>
|
||||
<Box
|
||||
sx={{
|
||||
width: "100%",
|
||||
@@ -446,7 +461,7 @@ const LeftSideBar = ({ userdata, serverside, globalUrl, notifications, }) => {
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Link to="/admin2" style={hrefStyle}>
|
||||
<Link to="/admin" style={hrefStyle}>
|
||||
<MenuItem
|
||||
onClick={(event) => {
|
||||
handleClose();
|
||||
@@ -466,7 +481,7 @@ const LeftSideBar = ({ userdata, serverside, globalUrl, notifications, }) => {
|
||||
</Link>
|
||||
|
||||
<Divider style={{ marginTop: 10, marginBottom: 10, }} />
|
||||
<Link to="/admin2?admin_tab=priorities" style={hrefStyle}>
|
||||
<Link to="/admin?admin_tab=notifications" style={hrefStyle}>
|
||||
<MenuItem
|
||||
onClick={(event) => {
|
||||
handleClose();
|
||||
@@ -478,7 +493,7 @@ const LeftSideBar = ({ userdata, serverside, globalUrl, notifications, }) => {
|
||||
})
|
||||
</MenuItem>
|
||||
</Link>
|
||||
<Link to="/usecases2" style={hrefStyle}>
|
||||
<Link to="/usecases" style={hrefStyle}>
|
||||
<MenuItem
|
||||
onClick={(event) => {
|
||||
handleClose();
|
||||
@@ -641,7 +656,7 @@ const LeftSideBar = ({ userdata, serverside, globalUrl, notifications, }) => {
|
||||
};
|
||||
|
||||
const getRegionTag = (region_url) => {
|
||||
let regiontag = "eu";
|
||||
let regiontag = "UK";
|
||||
if (
|
||||
region_url !== undefined &&
|
||||
region_url !== null &&
|
||||
@@ -653,15 +668,25 @@ const LeftSideBar = ({ userdata, serverside, globalUrl, notifications, }) => {
|
||||
regiontag = namesplit[namesplit.length - 1];
|
||||
|
||||
if (regiontag === "california") {
|
||||
regiontag = "us";
|
||||
regiontag = "US";
|
||||
} else if (regiontag === "frankfurt") {
|
||||
regiontag = "fr";
|
||||
regiontag = "EU";
|
||||
} 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) => ({
|
||||
@@ -723,6 +748,20 @@ const LeftSideBar = ({ userdata, serverside, globalUrl, notifications, }) => {
|
||||
</Dialog>
|
||||
);
|
||||
|
||||
const getRegionFlag = (region_url) => {
|
||||
var region = "gb";
|
||||
const regionMapping = {
|
||||
"US": "us",
|
||||
"EU": "eu",
|
||||
"CA": "ca",
|
||||
"UK": "gb"
|
||||
};
|
||||
|
||||
region = regionMapping[region_url] || "gb";
|
||||
|
||||
return `https://flagcdn.com/48x36/${region}.png`;
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
@@ -736,7 +775,8 @@ const LeftSideBar = ({ userdata, serverside, globalUrl, notifications, }) => {
|
||||
boxShadow: "0px 4px 12px rgba(0, 0, 0, 0.2)" ,
|
||||
resize: 'both',
|
||||
|
||||
height: "calc(100vh - 32px)",
|
||||
zoom: 0.8,
|
||||
height: "calc((100vh - 32px)*1.2)",
|
||||
}}
|
||||
>
|
||||
{modalView}
|
||||
@@ -759,7 +799,7 @@ const LeftSideBar = ({ userdata, serverside, globalUrl, notifications, }) => {
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
// alignItems: "center",
|
||||
justifyContent: "center",
|
||||
position: "relative",
|
||||
right: !expandLeftNav && 8,
|
||||
@@ -814,46 +854,62 @@ const LeftSideBar = ({ userdata, serverside, globalUrl, notifications, }) => {
|
||||
{expandLeftNav ? (
|
||||
<Fade in={expandLeftNav} timeout={500}>
|
||||
<TextField
|
||||
id="sidebar-search"
|
||||
placeholder= "Search"
|
||||
sx={{
|
||||
width: "100%",
|
||||
maxWidth: 228,
|
||||
"& .MuiInputBase-root": {
|
||||
height: 35,
|
||||
padding: 0,
|
||||
},
|
||||
"& .MuiOutlinedInput-root": {
|
||||
cursor: "pointer",
|
||||
width: 228,
|
||||
"& fieldset": {
|
||||
borderColor: "#494949",
|
||||
},
|
||||
"&:hover fieldset": {
|
||||
borderColor: "#ffffff",
|
||||
display: "block"
|
||||
},
|
||||
"&.Mui-focused fieldset": {
|
||||
borderColor: "#A9A9A9",
|
||||
},
|
||||
},
|
||||
"& input": {
|
||||
padding: "8px 14px",
|
||||
fontSize: "14px",
|
||||
color: "#C8C8C8",
|
||||
},
|
||||
backgroundColor: "transparent",
|
||||
}}
|
||||
variant="outlined"
|
||||
InputProps={{
|
||||
startAdornment: (
|
||||
<SearchIcon style={{ color: "#CDCDCD", width: 24, height: 24, marginLeft: 16}} />
|
||||
),
|
||||
disableUnderline: true,
|
||||
}}
|
||||
onClick={()=>{setSearchBarModalOpen(true)}}
|
||||
onChange={()=> {setSearchBarModalOpen(true)}}
|
||||
/>
|
||||
id="sidebar-search"
|
||||
placeholder="Search"
|
||||
sx={{
|
||||
width: "100%",
|
||||
maxWidth: 228,
|
||||
"& .MuiInputBase-root": {
|
||||
height: 35,
|
||||
padding: 0,
|
||||
},
|
||||
"& .MuiOutlinedInput-root": {
|
||||
cursor: "pointer",
|
||||
width: 228,
|
||||
"& fieldset": {
|
||||
borderColor: "#494949",
|
||||
},
|
||||
"&:hover fieldset": {
|
||||
borderColor: "#ffffff",
|
||||
display: "block",
|
||||
},
|
||||
"&.Mui-focused fieldset": {
|
||||
borderColor: "#A9A9A9",
|
||||
},
|
||||
},
|
||||
"& input": {
|
||||
padding: "8px 14px",
|
||||
fontSize: "14px",
|
||||
color: "#C8C8C8",
|
||||
},
|
||||
backgroundColor: "transparent",
|
||||
}}
|
||||
variant="outlined"
|
||||
InputProps={{
|
||||
startAdornment: (
|
||||
<SearchIcon style={{ color: "#CDCDCD", width: 24, height: 24, marginLeft: 16 }} />
|
||||
),
|
||||
endAdornment: (
|
||||
<span
|
||||
style={{
|
||||
color: "#C8C8C8",
|
||||
fontSize: "12px",
|
||||
marginRight: 16,
|
||||
whiteSpace: "nowrap",
|
||||
}}
|
||||
>
|
||||
<kbd>Ctrl</kbd>/<kbd>Cmd</kbd>+<kbd>K</kbd>
|
||||
</span>
|
||||
),
|
||||
disableUnderline: true,
|
||||
}}
|
||||
onClick={() => {
|
||||
setSearchBarModalOpen(true);
|
||||
}}
|
||||
onChange={() => {
|
||||
setSearchBarModalOpen(true);
|
||||
}}
|
||||
/>
|
||||
</Fade>
|
||||
):(
|
||||
<>
|
||||
@@ -891,10 +947,16 @@ const LeftSideBar = ({ userdata, serverside, globalUrl, notifications, }) => {
|
||||
setCurrentOpenTab("automate");
|
||||
localStorage.setItem("lastTabOpenByUser", "automate");
|
||||
}}
|
||||
sx={{
|
||||
variant="text"
|
||||
style={{
|
||||
...ButtonStyle,
|
||||
backgroundColor: ((currentOpenTab === "automate" && currentPath.includes("/dashboards/automate"))|| (!expandLeftNav && (currentPath === "/workflows" || currentPath === "/usecases2" || currentPath.includes("/search"))))? "#2f2f2f": "transparent",
|
||||
"&:hover": { backgroundColor: "#2f2f2f" },
|
||||
}}
|
||||
onMouseOver={(event)=>{
|
||||
event.currentTarget.style.backgroundColor = "#2f2f2f";
|
||||
}}
|
||||
onMouseOut={(event)=>{
|
||||
event.currentTarget.style.backgroundColor = ((currentOpenTab === "automate" && currentPath.includes("/dashboards/automate"))|| (!expandLeftNav && (currentPath === "/workflows" || currentPath === "/usecases2" || currentPath.includes("/search"))))? "#2f2f2f": "transparent";
|
||||
}}
|
||||
>
|
||||
<img
|
||||
@@ -920,8 +982,15 @@ const LeftSideBar = ({ userdata, serverside, globalUrl, notifications, }) => {
|
||||
setOpenautomateTab((prev) => !prev);
|
||||
setOpenSecurityTab(false);
|
||||
}}
|
||||
sx={{
|
||||
marginLeft: 0.625,
|
||||
style={{
|
||||
color: "#FFFFFF",
|
||||
marginLeft: 0.625,
|
||||
}}
|
||||
onMouseOver={(event)=>{
|
||||
event.currentTarget.style.backgroundColor = "#2f2f2f";
|
||||
}}
|
||||
onMouseOut={(event)=>{
|
||||
event.currentTarget.style.backgroundColor = "transparent";
|
||||
}}
|
||||
>
|
||||
{openautomatetab ? (
|
||||
@@ -952,23 +1021,28 @@ const LeftSideBar = ({ userdata, serverside, globalUrl, notifications, }) => {
|
||||
flexDirection: "column",
|
||||
paddingLeft: 16,
|
||||
gap: 4,
|
||||
marginTop: expandLeftNav ? 16 : 0,
|
||||
}}
|
||||
>
|
||||
<Link to="/usecases2" style={hrefStyle}>
|
||||
<Link to="/usecases" style={hrefStyle}>
|
||||
<Button
|
||||
onClick={(event) => {
|
||||
setCurrentOpenTab("usecases");
|
||||
localStorage.setItem("lastTabOpenByUser", "usecases");
|
||||
}}
|
||||
sx={{
|
||||
style={{
|
||||
width: "100%",
|
||||
height: 35,
|
||||
color: "#C8C8C8",
|
||||
justifyContent: "flex-start",
|
||||
textTransform: "none",
|
||||
backgroundColor: currentOpenTab === "usecases" && expandLeftNav && currentPath.includes("/usecases2")? "#2f2f2f": "transparent",
|
||||
"&:hover": { backgroundColor: "#2f2f2f" },
|
||||
backgroundColor: currentOpenTab === "usecases" && expandLeftNav && currentPath.includes("/usecases")? "#2f2f2f": "transparent",
|
||||
marginLeft: 16
|
||||
}}
|
||||
onMouseOver={(event)=>{
|
||||
event.currentTarget.style.backgroundColor = "#2f2f2f";
|
||||
}}
|
||||
onMouseOut={(event)=>{
|
||||
event.currentTarget.style.backgroundColor = currentOpenTab === "usecases" && expandLeftNav && currentPath.includes("/usecases")? "#2f2f2f": "transparent";
|
||||
}}
|
||||
disableRipple={expandLeftNav ? false : true}
|
||||
>
|
||||
@@ -985,22 +1059,28 @@ const LeftSideBar = ({ userdata, serverside, globalUrl, notifications, }) => {
|
||||
</span>
|
||||
</Button>
|
||||
</Link>
|
||||
<Link to="/workflows2" style={hrefStyle}>
|
||||
<Link to="/workflows" style={hrefStyle}>
|
||||
<Button
|
||||
onClick={(event) => {
|
||||
setCurrentOpenTab("workflows");
|
||||
localStorage.setItem("lastTabOpenByUser", "workflows");
|
||||
}}
|
||||
sx={{
|
||||
style={{
|
||||
width: "100%",
|
||||
height: 35,
|
||||
color: "#C8C8C8",
|
||||
justifyContent: "flex-start",
|
||||
textTransform: "none",
|
||||
backgroundColor: currentOpenTab === "workflows" && currentPath === "/workflows" && expandLeftNav? "#2f2f2f": "transparent",
|
||||
"&:hover": { backgroundColor: "#2f2f2f" },
|
||||
marginLeft: 16
|
||||
}}
|
||||
disableRipple={expandLeftNav ? false : true}
|
||||
onMouseOver={(event)=>{
|
||||
event.currentTarget.style.backgroundColor = "#2f2f2f";
|
||||
}}
|
||||
onMouseOut={(event)=>{
|
||||
event.currentTarget.style.backgroundColor = currentOpenTab === "workflows" && currentPath === "/workflows" && expandLeftNav? "#2f2f2f": "transparent";
|
||||
}}
|
||||
>
|
||||
<span style={{display: expandLeftNav ? "inline" : "none", opacity: expandLeftNav ? 1 : 0, transition: "opacity 0.3s ease", position: 'relative', left: !expandLeftNav ? 10: 0, marginRight: 10, fontSize: 16 }}>•</span>{" "}
|
||||
<span
|
||||
@@ -1015,20 +1095,26 @@ const LeftSideBar = ({ userdata, serverside, globalUrl, notifications, }) => {
|
||||
</span>
|
||||
</Button>
|
||||
</Link>
|
||||
<Link to="/apps2" style={hrefStyle}>
|
||||
<Link to="/apps" style={hrefStyle}>
|
||||
<Button
|
||||
onClick={(event) => {
|
||||
setCurrentOpenTab("apps");
|
||||
localStorage.setItem("lastTabOpenByUser", "apps");
|
||||
}}
|
||||
sx={{
|
||||
style={{
|
||||
width: "100%",
|
||||
height: 35,
|
||||
color: "#C8C8C8",
|
||||
justifyContent: "flex-start",
|
||||
textTransform: "none",
|
||||
backgroundColor: currentOpenTab === "apps" && expandLeftNav && currentPath.includes("/search") ? "#2f2f2f": "transparent",
|
||||
"&:hover": { backgroundColor: "#2f2f2f" },
|
||||
backgroundColor: currentOpenTab === "apps" && expandLeftNav && currentPath.includes("/apps2") ? "#2f2f2f": "transparent",
|
||||
marginLeft: 16
|
||||
}}
|
||||
onMouseOver={(event)=>{
|
||||
event.currentTarget.style.backgroundColor = "#2f2f2f";
|
||||
}}
|
||||
onMouseOut={(event)=>{
|
||||
event.currentTarget.style.backgroundColor = currentOpenTab === "apps" && expandLeftNav && currentPath.includes("/search") ? "#2f2f2f": "transparent";
|
||||
}}
|
||||
disableRipple={expandLeftNav ? false : true}
|
||||
>
|
||||
@@ -1038,7 +1124,7 @@ const LeftSideBar = ({ userdata, serverside, globalUrl, notifications, }) => {
|
||||
display: expandLeftNav ? "inline" : "none",
|
||||
opacity: expandLeftNav ? 1 : 0,
|
||||
transition: "opacity 0.3s ease",
|
||||
color: currentOpenTab === "apps" && currentPath.includes("/search") ? "#F1F1F1" : "#C8C8C8",
|
||||
color: currentOpenTab === "apps" && currentPath.includes("/apps2") ? "#F1F1F1" : "#C8C8C8",
|
||||
}}
|
||||
>
|
||||
Apps
|
||||
@@ -1051,7 +1137,7 @@ const LeftSideBar = ({ userdata, serverside, globalUrl, notifications, }) => {
|
||||
sx={{
|
||||
display: "flex",
|
||||
flexDirection: "row",
|
||||
marginTop: 2.5,
|
||||
marginTop: 1
|
||||
}}
|
||||
>
|
||||
<span style={{ display: "inline-block", width: "100%" }}>
|
||||
@@ -1072,7 +1158,7 @@ const LeftSideBar = ({ userdata, serverside, globalUrl, notifications, }) => {
|
||||
setCurrentOpenTab("security");
|
||||
localStorage.setItem("lastTabOpenByUser", "security");
|
||||
}}
|
||||
sx={{
|
||||
style={{
|
||||
...ButtonStyle,
|
||||
backgroundColor:
|
||||
((currentOpenTab === "security" && currentPath.includes("/security")) ||
|
||||
@@ -1080,11 +1166,19 @@ const LeftSideBar = ({ userdata, serverside, globalUrl, notifications, }) => {
|
||||
(currentPath.includes("detections") || currentPath.includes("response"))))
|
||||
? "#2f2f2f"
|
||||
: "transparent",
|
||||
"&:hover": {
|
||||
backgroundColor: userdata?.support ? "#2f2f2f" : "transparent",
|
||||
},
|
||||
cursor: userdata?.support ? "pointer" : "not-allowed",
|
||||
}}
|
||||
onMouseOver={(event)=>{
|
||||
event.currentTarget.style.backgroundColor = "#2f2f2f";
|
||||
}}
|
||||
onMouseOut={(event)=>{
|
||||
event.currentTarget.style.backgroundColor = ((currentOpenTab === "security" && currentPath.includes("/security")) ||
|
||||
(!expandLeftNav &&
|
||||
(currentPath.includes("detections") || currentPath.includes("response"))))
|
||||
? "#2f2f2f"
|
||||
: "transparent";
|
||||
}}
|
||||
disabled={!userdata?.support}
|
||||
>
|
||||
<ShieldOutlinedIcon
|
||||
style={{
|
||||
@@ -1105,19 +1199,25 @@ const LeftSideBar = ({ userdata, serverside, globalUrl, notifications, }) => {
|
||||
: "#6F6F6F",
|
||||
}}
|
||||
>
|
||||
Security
|
||||
Content
|
||||
</span>
|
||||
</Button>
|
||||
</Link>
|
||||
</span>
|
||||
<IconButton
|
||||
disabled={true}
|
||||
onClick={() => {
|
||||
setOpenSecurityTab((prev) => !prev);
|
||||
setOpenautomateTab(false);
|
||||
}}
|
||||
sx={{
|
||||
style={{
|
||||
marginLeft: 0.625,
|
||||
color: "#FFFFFF",
|
||||
}}
|
||||
onMouseOver={(event)=>{
|
||||
event.currentTarget.style.backgroundColor = "#2f2f2f";
|
||||
}}
|
||||
onMouseOut={(event)=>{
|
||||
event.currentTarget.style.backgroundColor = "transparent";
|
||||
}}
|
||||
>
|
||||
{openSecurityTab ? (
|
||||
@@ -1144,14 +1244,12 @@ const LeftSideBar = ({ userdata, serverside, globalUrl, notifications, }) => {
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
paddingLeft: 16,
|
||||
gap: 4,
|
||||
marginTop: expandLeftNav ? 16 : 0,
|
||||
}}
|
||||
disableRipple={expandLeftNav ? false : true}
|
||||
>
|
||||
<span style={{ display: "inline-block", width: "100%" }}>
|
||||
<Link
|
||||
to={userdata?.support ? "/detections" : "#"}
|
||||
to={"/forms"}
|
||||
style={{
|
||||
...hrefStyle,
|
||||
pointerEvents: userdata?.support ? "auto" : "none",
|
||||
@@ -1196,14 +1294,14 @@ const LeftSideBar = ({ userdata, serverside, globalUrl, notifications, }) => {
|
||||
: "#6F6F6F",
|
||||
}}
|
||||
>
|
||||
Detection
|
||||
Forms
|
||||
</span>
|
||||
</Button>
|
||||
</Link>
|
||||
</span>
|
||||
<span style={{ display: "inline-block", width: "100%" }}>
|
||||
<span style={{ display: "inline-block", width: "100%" }}>
|
||||
<Link
|
||||
to={userdata?.support ? "/response" : "#"}
|
||||
to={"/admin?tab=datastore"}
|
||||
style={{
|
||||
...hrefStyle,
|
||||
pointerEvents: userdata?.support ? "auto" : "none",
|
||||
@@ -1230,7 +1328,6 @@ const LeftSideBar = ({ userdata, serverside, globalUrl, notifications, }) => {
|
||||
},
|
||||
cursor: userdata?.support ? "pointer" : "not-allowed",
|
||||
}}
|
||||
disabled={!userdata?.support}
|
||||
>
|
||||
<span style={{ position: "relative", left: !expandLeftNav ? 10 : 0, marginRight: 10, fontSize: 16 }}>
|
||||
•
|
||||
@@ -1248,26 +1345,81 @@ const LeftSideBar = ({ userdata, serverside, globalUrl, notifications, }) => {
|
||||
: "#6F6F6F",
|
||||
}}
|
||||
>
|
||||
Response
|
||||
Datastore
|
||||
</span>
|
||||
</Button>
|
||||
</Link>
|
||||
</span>
|
||||
<span style={{ display: "inline-block", width: "100%" }}>
|
||||
<Link
|
||||
to={"/admin?tab=files"}
|
||||
style={{
|
||||
...hrefStyle,
|
||||
pointerEvents: userdata?.support ? "auto" : "none",
|
||||
}}
|
||||
>
|
||||
<Button
|
||||
onClick={(event) => {
|
||||
if (!userdata?.support) return;
|
||||
setCurrentOpenTab("response");
|
||||
localStorage.setItem("lastTabOpenByUser", "response");
|
||||
}}
|
||||
sx={{
|
||||
width: "100%",
|
||||
height: 35,
|
||||
color: userdata?.support ? "#C8C8C8" : "#6F6F6F",
|
||||
justifyContent: "flex-start",
|
||||
textTransform: "none",
|
||||
backgroundColor:
|
||||
currentOpenTab === "response" && currentPath.includes("/response")
|
||||
? "#2f2f2f"
|
||||
: "transparent",
|
||||
"&:hover": {
|
||||
backgroundColor: userdata?.support ? "#2f2f2f" : "transparent",
|
||||
},
|
||||
cursor: userdata?.support ? "pointer" : "not-allowed",
|
||||
}}
|
||||
>
|
||||
<span style={{ position: "relative", left: !expandLeftNav ? 10 : 0, marginRight: 10, fontSize: 16 }}>
|
||||
•
|
||||
</span>
|
||||
<span
|
||||
style={{
|
||||
display: expandLeftNav ? "inline" : "none",
|
||||
opacity: expandLeftNav ? 1 : 0,
|
||||
transition: "opacity 0.3s ease",
|
||||
color:
|
||||
userdata?.support && currentOpenTab === "response" && currentPath.includes("/response")
|
||||
? "#F1F1F1"
|
||||
: userdata?.support
|
||||
? "#C8C8C8"
|
||||
: "#6F6F6F",
|
||||
}}
|
||||
>
|
||||
Files
|
||||
</span>
|
||||
</Button>
|
||||
</Link>
|
||||
</span>
|
||||
</Box>
|
||||
</Collapse>
|
||||
|
||||
|
||||
<Link to="/docs" style={hrefStyle}>
|
||||
<Button
|
||||
onClick={(event) => {
|
||||
setCurrentOpenTab("docs");
|
||||
localStorage.setItem("lastTabOpenByUser", "docs");
|
||||
}}
|
||||
sx={{
|
||||
style={{
|
||||
...ButtonStyle,
|
||||
marginTop: 2,
|
||||
marginTop: 8,
|
||||
marginTop: 8,
|
||||
backgroundColor: currentOpenTab === "docs" && currentPath.includes("/docs") ? "#2f2f2f": "transparent",
|
||||
"&:hover": { backgroundColor: "#2f2f2f" },
|
||||
}}
|
||||
onMouseOver={(event)=>{
|
||||
event.currentTarget.style.backgroundColor = "#2f2f2f";
|
||||
}}
|
||||
onMouseOut={(event)=>{
|
||||
event.currentTarget.style.backgroundColor = currentOpenTab === "docs" && currentPath.includes("/docs") ? "#2f2f2f": "transparent";
|
||||
}}
|
||||
>
|
||||
<img
|
||||
@@ -1385,15 +1537,20 @@ const LeftSideBar = ({ userdata, serverside, globalUrl, notifications, }) => {
|
||||
>
|
||||
{
|
||||
isCloud ? (
|
||||
<span
|
||||
<span
|
||||
style={{
|
||||
color: "#bbb",
|
||||
fontSize: "16px",
|
||||
marginRight: 12,
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
}}
|
||||
>
|
||||
<img src={getRegionFlag(option.region_url)} alt={option.region_url} style={{ width: 24, height: 24, marginRight: 12, borderRadius: "50%" }} />
|
||||
{option.region_url}
|
||||
</span>) : null
|
||||
</span>
|
||||
) : null
|
||||
}
|
||||
<img
|
||||
src={option.image ? option.image : "/images/no_image.png"}
|
||||
|
||||
@@ -127,7 +127,7 @@ const MFASetup = ({ isLoaded, globalUrl, setCookie }) => {
|
||||
};
|
||||
|
||||
return (
|
||||
<div style={{ margin: "50px auto", width: "500px" }}>
|
||||
<div style={{ paddingTop: 50, margin: "0px auto", width: "500px" }}>
|
||||
<Paper elevation={3} style={{ padding: "30px", backgroundColor: "#212121" }}>
|
||||
<Typography variant="h5" style={{ color: "white", marginBottom: 10, textAlign: "center" }}>
|
||||
Multi-Factor Authentication Setup
|
||||
|
||||
@@ -110,8 +110,30 @@ const OrgHeader = (props) => {
|
||||
orgDescription,
|
||||
selectedOrganization.id,
|
||||
selectedOrganization.image,
|
||||
{},
|
||||
{},
|
||||
{
|
||||
app_download_repo: selectedOrganization?.defaults?.app_download_repo,
|
||||
app_download_branch: selectedOrganization?.defaults?.app_download_branch,
|
||||
workflow_download_repo: selectedOrganization?.defaults?.workflow_download_repo,
|
||||
workflow_download_branch: selectedOrganization?.defaults?.workflow_download_branch,
|
||||
notification_workflow: selectedOrganization?.defaults?.notification_workflow,
|
||||
documentation_reference: selectedOrganization?.defaults?.documentation_reference,
|
||||
workflow_upload_repo: selectedOrganization?.defaults?.workflow_upload_repo,
|
||||
workflow_upload_branch: selectedOrganization?.defaults?.workflow_upload_branch,
|
||||
workflow_upload_username: selectedOrganization?.defaults?.workflow_upload_username,
|
||||
workflow_upload_token: selectedOrganization?.defaults?.workflow_upload_token,
|
||||
newsletter: selectedOrganization?.defaults?.newsletter,
|
||||
weekly_recommendations: selectedOrganization?.defaults?.weekly_recommendations,
|
||||
},
|
||||
{
|
||||
sso_entrypoint: selectedOrganization?.sso_config?.sso_entrypoint,
|
||||
sso_certificate: selectedOrganization?.sso_config?.sso_certificate,
|
||||
client_id: selectedOrganization?.sso_config?.client_id,
|
||||
client_secret: selectedOrganization?.sso_config?.client_secret,
|
||||
openid_authorization: selectedOrganization?.sso_config?.openid_authorization,
|
||||
openid_token: selectedOrganization?.sso_config?.openid_token,
|
||||
SSORequired: selectedOrganization?.sso_config?.SSORequired,
|
||||
auto_provision: selectedOrganization?.sso_config?.auto_provision,
|
||||
},
|
||||
[],
|
||||
)
|
||||
}
|
||||
|
||||
@@ -227,7 +227,7 @@ const OrgHeaderexpanded = (props) => {
|
||||
defaults,
|
||||
sso_config
|
||||
) => {
|
||||
|
||||
console.log("defatult in handleEditOrg", defaults)
|
||||
const data = {
|
||||
name: name,
|
||||
description: description,
|
||||
@@ -309,6 +309,7 @@ const OrgHeaderexpanded = (props) => {
|
||||
openid_authorization: openidAuthorization,
|
||||
openid_token: openidToken,
|
||||
SSORequired: SSORequired,
|
||||
auto_provision: selectedOrganization?.sso_config?.auto_provision,
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -485,6 +486,7 @@ const OrgHeaderexpanded = (props) => {
|
||||
value={data}
|
||||
onClick={(e) => {
|
||||
var parsedinput = { target: { value: data } }
|
||||
console.log("Parsed input: ", parsedinput)
|
||||
handleWorkflowSelectionUpdate(parsedinput)
|
||||
}}
|
||||
>
|
||||
@@ -753,7 +755,7 @@ const OrgHeaderexpanded = (props) => {
|
||||
{SSORequired ? "Required" : "Optional"}
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
{/* <div
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
@@ -800,7 +802,7 @@ const OrgHeaderexpanded = (props) => {
|
||||
</Button>
|
||||
</span>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div> */}
|
||||
<div></div>
|
||||
<Grid item xs={12} style={{}}>
|
||||
<Typography variant="h6" style={{ textAlign: "center" }}>
|
||||
|
||||
@@ -53,6 +53,7 @@ import {
|
||||
|
||||
import {
|
||||
HelpOutline as HelpOutlineIcon,
|
||||
OpenInFull as OpenInFullIcon,
|
||||
Description as DescriptionIcon,
|
||||
GetApp as GetAppIcon,
|
||||
Search as SearchIcon,
|
||||
@@ -2090,7 +2091,7 @@ const ParsedAction = (props) => {
|
||||
{data?.validation?.valid === true ?
|
||||
<Tooltip title="Authentication has been validated" placement="top">
|
||||
<Chip
|
||||
style={{marginLeft: 0, padding: 0, marginRight: 10, cursor: "pointer", borderColor: green, }}
|
||||
style={{marginLeft: 0, padding: 0, marginRight: 10, cursor: "pointer", borderColor: green, maxHeight: 25, }}
|
||||
label={"Valid"}
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
@@ -2099,7 +2100,7 @@ const ParsedAction = (props) => {
|
||||
: null }
|
||||
{data?.last_modified === true ?
|
||||
<Chip
|
||||
style={{marginLeft: 0, padding: 0, marginRight: 10, cursor: "pointer",}}
|
||||
style={{marginLeft: 0, padding: 0, marginRight: 10, cursor: "pointer", maxHeight: 25, }}
|
||||
label={"Latest"}
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
@@ -2139,7 +2140,7 @@ const ParsedAction = (props) => {
|
||||
>
|
||||
<IconButton
|
||||
color="primary"
|
||||
variant="outlined"
|
||||
variant="outlined"
|
||||
style={{}}
|
||||
onClick={() => {
|
||||
setAuthenticationModalOpen(true);
|
||||
@@ -3452,36 +3453,10 @@ const ParsedAction = (props) => {
|
||||
disableUnderline: true,
|
||||
endAdornment: hideExtraTypes ? null : (
|
||||
<InputAdornment position="end">
|
||||
<ButtonGroup orientation={multiline ? "vertical" : "horizontal"}>
|
||||
<Tooltip title="Expand window" placement="top">
|
||||
<AspectRatioIcon
|
||||
style={{ cursor: "pointer", margin: multiline ? 5 : 0 ,}}
|
||||
onClick={(event) => {
|
||||
event.preventDefault()
|
||||
setFieldCount(count)
|
||||
setExpansionModalOpen(true)
|
||||
setActiveDialog("codeeditor")
|
||||
//setcodedata(data.value)
|
||||
var parsedvalue = data.value
|
||||
if (parsedvalue === undefined || parsedvalue === null) {
|
||||
parsedvalue = ""
|
||||
}
|
||||
|
||||
setEditorData({
|
||||
"name": data.name,
|
||||
"value": parsedvalue,
|
||||
"field_number": count,
|
||||
"actionlist": actionlist,
|
||||
"field_id": clickedFieldId,
|
||||
|
||||
"example": selectedActionParameters[count].example,
|
||||
})
|
||||
}}
|
||||
/>
|
||||
</Tooltip>
|
||||
<ButtonGroup color="secondary" orientation={multiline ? "vertical" : "horizontal"}>
|
||||
<Tooltip title="Autocomplete text" placement="bottom">
|
||||
<AddCircleOutlineIcon
|
||||
style={{ cursor: "pointer", margin: multiline ? 5 : 0, }}
|
||||
style={{ color: "rgba(255,255,255,0.7)", cursor: "pointer", margin: multiline ? 5 : 0, }}
|
||||
onClick={(event) => {
|
||||
event.preventDefault()
|
||||
|
||||
@@ -4355,6 +4330,34 @@ const ParsedAction = (props) => {
|
||||
{tmpitem} <span style={{color: theme.palette.main}}>{selectedActionParameters[count].required || selectedActionParameters[count].configuration ? "*" : ""}</span>
|
||||
</div>
|
||||
|
||||
<Tooltip title="Expand editor window" placement="top">
|
||||
|
||||
<OpenInFullIcon
|
||||
style={{ color: "rgba(255,255,255,0.7)", cursor: "pointer", margin: multiline ? 5 : 0, height: 20, width: 20, }}
|
||||
onClick={(event) => {
|
||||
event.preventDefault()
|
||||
setFieldCount(count)
|
||||
setExpansionModalOpen(true)
|
||||
setActiveDialog("codeeditor")
|
||||
//setcodedata(data.value)
|
||||
var parsedvalue = data.value
|
||||
if (parsedvalue === undefined || parsedvalue === null) {
|
||||
parsedvalue = ""
|
||||
}
|
||||
|
||||
setEditorData({
|
||||
"name": data.name,
|
||||
"value": parsedvalue,
|
||||
"field_number": count,
|
||||
"actionlist": actionlist,
|
||||
"field_id": clickedFieldId,
|
||||
|
||||
"example": selectedActionParameters[count].example,
|
||||
})
|
||||
}}
|
||||
/>
|
||||
</Tooltip>
|
||||
|
||||
</div>
|
||||
{datafield}
|
||||
{/*shufflecode*/}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import React, { useState, useEffect, useContext, memo } from "react";
|
||||
|
||||
import { toast } from "react-toastify";
|
||||
import theme from "../theme.jsx";
|
||||
@@ -13,22 +13,25 @@ import {
|
||||
Card,
|
||||
Chip,
|
||||
Switch,
|
||||
Skeleton,
|
||||
} from "@mui/material";
|
||||
import { Context } from "../context/ContextApi.jsx";
|
||||
|
||||
import { useNavigate, Link } from "react-router-dom";
|
||||
import Priority from "../components/Priority.jsx";
|
||||
import { constrainMatrix } from "reaviz";
|
||||
//import { useAlert
|
||||
|
||||
const Priorities = (props) => {
|
||||
const Priorities = memo((props) => {
|
||||
const { globalUrl, userdata,clickedFromOrgTab, serverside, billingInfo, stripeKey, checkLogin, setAdminTab, setCurTab, notifications, setNotifications, } = props;
|
||||
|
||||
const [showDismissed, setShowDismissed] = React.useState(false);
|
||||
const [showRead, setShowRead] = React.useState(false);
|
||||
const [appFramework, setAppFramework] = React.useState({});
|
||||
|
||||
const [selectedWorkflow, setSelectedWorkflow] = React.useState("NO HIGHLIGHT");
|
||||
const [selectedExecutionId, setSelectedExecutionId] = React.useState("NO HIGHLIGHT");
|
||||
const [highlightKMS, setHighlightKMS] = React.useState(false)
|
||||
|
||||
|
||||
let navigate = useNavigate();
|
||||
useEffect(() => {
|
||||
getFramework()
|
||||
@@ -216,188 +219,16 @@ const Priorities = (props) => {
|
||||
const notificationWidth = "100%"
|
||||
const imagesize = 22
|
||||
const boxColor = "#86c142"
|
||||
const NotificationItem = (props) => {
|
||||
const {data} = props
|
||||
|
||||
var image = "";
|
||||
var orgName = "";
|
||||
var orgId = "";
|
||||
|
||||
|
||||
var highlighted = selectedExecutionId === "" && selectedWorkflow === "" ? false : data.reference_url === undefined || data.reference_url === null || data.reference_url.length === 0 ? false : data.reference_url.includes(selectedExecutionId) || data.reference_url.includes(selectedWorkflow)
|
||||
|
||||
if (!highlighted && highlightKMS) {
|
||||
if (data.title !== undefined && data.title !== null && data.title.toLowerCase().includes("kms")) {
|
||||
highlighted = true
|
||||
} else if (data.description !== undefined && data.description !== null && data.description.toLowerCase().includes("kms")) {
|
||||
highlighted = true
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (userdata.orgs !== undefined) {
|
||||
const foundOrg = userdata.orgs.find((org) => org.id === data["org_id"]);
|
||||
if (foundOrg !== undefined && foundOrg !== null) {
|
||||
//position: "absolute", bottom: 5, right: -5,
|
||||
const imageStyle = {
|
||||
width: imagesize,
|
||||
height: imagesize,
|
||||
pointerEvents: "none",
|
||||
marginLeft:
|
||||
data.creator_org !== undefined && data.creator_org.length > 0
|
||||
? 20
|
||||
: 0,
|
||||
borderRadius: 10,
|
||||
border:
|
||||
foundOrg.id === userdata.active_org.id
|
||||
? `3px solid ${boxColor}`
|
||||
: null,
|
||||
cursor: "pointer",
|
||||
marginRight: 10,
|
||||
};
|
||||
|
||||
image =
|
||||
foundOrg.image === "" ? (
|
||||
<img
|
||||
alt={foundOrg.name}
|
||||
src={theme.palette.defaultImage}
|
||||
style={imageStyle}
|
||||
/>
|
||||
) : (
|
||||
<img
|
||||
alt={foundOrg.name}
|
||||
src={foundOrg.image}
|
||||
style={imageStyle}
|
||||
onClick={() => {}}
|
||||
/>
|
||||
);
|
||||
|
||||
orgName = foundOrg.name;
|
||||
orgId = foundOrg.id;
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Paper
|
||||
style={{
|
||||
backgroundColor: theme.palette.platformColor,
|
||||
width: clickedFromOrgTab ? null :notificationWidth,
|
||||
padding: 30,
|
||||
borderBottom: "1px solid rgba(255,255,255,0.4)",
|
||||
marginBottom: 20,
|
||||
border: highlighted ? "2px solid #f85a3e" : null,
|
||||
borderRadius: theme.palette?.borderRadius,
|
||||
}}
|
||||
>
|
||||
<div style={{display: "flex", }}>
|
||||
{data.amount === 1 && data.read === false ?
|
||||
<Chip
|
||||
label={"First seen"}
|
||||
variant="contained"
|
||||
color="primary"
|
||||
style={{marginRight: 15, height: 25, }}
|
||||
/>
|
||||
: null}
|
||||
{data.ignored === true ?
|
||||
<Chip
|
||||
label={"Disabled"}
|
||||
variant="outlined"
|
||||
color="primary"
|
||||
style={{marginRight: 15, height: 25, }}
|
||||
/>
|
||||
: null}
|
||||
{data.read === false ?
|
||||
<Chip
|
||||
label={"Unread"}
|
||||
variant="outlined"
|
||||
color="primary"
|
||||
style={{marginRight: 15, height: 25, }}
|
||||
/>
|
||||
:
|
||||
<Chip
|
||||
label={"Read"}
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
style={{marginRight: 15, height: 25, }}
|
||||
/>
|
||||
}
|
||||
<Typography variant="body1" color="textPrimary">
|
||||
{data.title}
|
||||
</Typography >
|
||||
</div>
|
||||
|
||||
{data.image !== undefined && data.image !== null && data.image.length > 0 ?
|
||||
<img alt={data.title} src={data.image} style={{height: 100, width: 100, }} />
|
||||
:
|
||||
null
|
||||
}
|
||||
<Typography variant="body2" color="textSecondary" style={{marginTop: 10, maxHeight: 200, overflowX: "hidden", overflowY: "auto", }}>
|
||||
{data.description}
|
||||
</Typography >
|
||||
<div style={{ display: "flex" }}>
|
||||
<ButtonGroup>
|
||||
<Button
|
||||
color="secondary"
|
||||
variant="outlined"
|
||||
style={{ marginTop: 15 }}
|
||||
disabled={data.reference_url === undefined || data.reference_url === null || data.reference_url.length === 0}
|
||||
onClick={() => {
|
||||
window.open(data.reference_url, "_blank")
|
||||
}}
|
||||
>
|
||||
Explore
|
||||
</Button>
|
||||
{data.read === false ? (
|
||||
<Button
|
||||
color="secondary"
|
||||
variant="outlined"
|
||||
style={{ marginTop: 15 }}
|
||||
onClick={() => {
|
||||
dismissNotification(data.id);
|
||||
}}
|
||||
>
|
||||
Dismiss
|
||||
</Button>
|
||||
) : null}
|
||||
<Tooltip title="Disabling a notification makes it so similar notifications to this one will NOT be re-opened. It will NOT forward notifications to your notification workflow, but WILL still keep counting." placement="top">
|
||||
<Button
|
||||
color="secondary"
|
||||
variant={data.ignored === true ? "contained" : "outlined"}
|
||||
style={{ marginTop: 15, }}
|
||||
onClick={() => {
|
||||
if (data.ignored === true) {
|
||||
dismissNotification(data.id, false)
|
||||
} else {
|
||||
dismissNotification(data.id, true)
|
||||
}
|
||||
}}
|
||||
>
|
||||
{data.ignored === true ? "Re-enable" : "Disable"}
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</ButtonGroup>
|
||||
|
||||
<Typography variant="body2" color="textSecondary" style={{marginLeft: 20, marginTop: 20, }}>
|
||||
<b>First seen</b>: {new Date(data.created_at * 1000).toISOString().slice(0, 19)}
|
||||
</Typography >
|
||||
<Typography variant="body2" color="textSecondary" style={{marginLeft: 20, marginTop: 20, }}>
|
||||
<b>Last seen</b>: {new Date(data.updated_at * 1000).toISOString().slice(0, 19)}
|
||||
</Typography >
|
||||
<Typography variant="body2" color="textSecondary" style={{marginLeft: 20, marginTop: 20, }}>
|
||||
<b>Times seen</b>: {data.amount}
|
||||
</Typography >
|
||||
</div>
|
||||
</Paper>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div style={{width: clickedFromOrgTab ? 1030:1000, padding: clickedFromOrgTab ? 27:null, height: clickedFromOrgTab ? "auto":null, backgroundColor: clickedFromOrgTab ? '#212121':null, borderRadius: clickedFromOrgTab ? '16px':null, }}>
|
||||
<h2 style={{ display: clickedFromOrgTab?null:"inline", marginBottom: clickedFromOrgTab? 8:null, marginTop: clickedFromOrgTab?40:null, color: clickedFromOrgTab?"#ffffff":null }}>Notifications ({
|
||||
<div style={{width: "100%", height: "100%", boxSizing: 'border-box', transition: 'width 0.3s ease', padding: clickedFromOrgTab ? "27px 10px 19px 27px":null, height: clickedFromOrgTab ? "auto":null, minHeight: 843, backgroundColor: clickedFromOrgTab ? '#212121':null, borderRadius: clickedFromOrgTab ? '16px':null, }}>
|
||||
<div style={{ maxHeight: 1700, overflowY: "auto", width: '100%', scrollbarColor: '#494949 transparent', scrollbarWidth: 'thin'}}>
|
||||
<div style={{maxWidth: "calc(100% - 20px)"}}>
|
||||
<Typography style={{ fontSize: 24, fontWeight: 'bold', display: clickedFromOrgTab?null:"inline", marginBottom: clickedFromOrgTab? 8:null, color: clickedFromOrgTab?"#ffffff":null }}>Notifications ({
|
||||
notifications?.filter((notification) => showRead === true || notification.read === false).length
|
||||
})</h2>
|
||||
})</Typography>
|
||||
|
||||
<span style={{ marginLeft: clickedFromOrgTab?null:25, color: clickedFromOrgTab?"#9E9E9E":null, }}>
|
||||
<span style={{ fontSize: 16, marginLeft: clickedFromOrgTab?null:25, color: clickedFromOrgTab?"#9E9E9E":null, }}>
|
||||
Notifications help you find potential problems with your workflows and apps.
|
||||
<a
|
||||
target="_blank"
|
||||
@@ -430,24 +261,11 @@ const Priorities = (props) => {
|
||||
</Button>
|
||||
) : null}
|
||||
</div>
|
||||
{notifications === null || notifications === undefined || notifications.length === 0 ? null :
|
||||
<div>
|
||||
{notifications.map((notification, index) => {
|
||||
if (showRead === false && notification.read === true) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<NotificationItem data={notification} key={index} />
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
}
|
||||
<NotificationComponent notifications={notifications} showRead={showRead} selectedExecutionId={selectedExecutionId} selectedWorkflow={selectedWorkflow} highlightKMS={highlightKMS} userdata={userdata} imagesize={imagesize} boxColor={boxColor} clickedFromOrgTab={clickedFromOrgTab} notificationWidth={notificationWidth} dismissNotification={dismissNotification}/>
|
||||
|
||||
{clickedFromOrgTab? null : <Divider style={{marginTop: 50, marginBottom: 50, }} />}
|
||||
|
||||
<h2 style={{ display: clickedFromOrgTab ? null:"inline", marginBottom: clickedFromOrgTab ? 8:null, marginTop: clickedFromOrgTab ?0:null, color: clickedFromOrgTab ? "#ffffff" : null }}>Suggestions</h2>
|
||||
<span style={{ color: clickedFromOrgTab ?"#9E9E9E":null,marginLeft: clickedFromOrgTab ?null:25 }}>
|
||||
<h2 style={{ display: clickedFromOrgTab ? null:"inline", marginBottom: clickedFromOrgTab ? 8:null, marginTop: clickedFromOrgTab ? 30 :null, color: clickedFromOrgTab ? "#ffffff" : null }}>Suggestions</h2>
|
||||
<span style={{ fontSize: 16, color: clickedFromOrgTab ?"#9E9E9E":null,marginLeft: clickedFromOrgTab ?null:25 }}>
|
||||
Suggestions are tasks identified by Shuffle to help you discover ways to protect your and customers' company. <br/>These range from simple configurations in Shuffle to Usecases you may have missed.
|
||||
<a
|
||||
target="_blank"
|
||||
@@ -489,9 +307,232 @@ const Priorities = (props) => {
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
export default Priorities;
|
||||
|
||||
|
||||
const NotificationItem = memo((props) => {
|
||||
const {data, selectedExecutionId, selectedWorkflow, highlightKMS, userdata, imagesize, boxColor, clickedFromOrgTab, notificationWidth, dismissNotification} = props
|
||||
|
||||
var image = "";
|
||||
var orgName = "";
|
||||
var orgId = "";
|
||||
|
||||
|
||||
var highlighted = selectedExecutionId === "" && selectedWorkflow === "" ? false : data.reference_url === undefined || data.reference_url === null || data.reference_url.length === 0 ? false : data.reference_url.includes(selectedExecutionId) || data.reference_url.includes(selectedWorkflow)
|
||||
|
||||
if (!highlighted && highlightKMS) {
|
||||
if (data.title !== undefined && data.title !== null && data.title.toLowerCase().includes("kms")) {
|
||||
highlighted = true
|
||||
} else if (data.description !== undefined && data.description !== null && data.description.toLowerCase().includes("kms")) {
|
||||
highlighted = true
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (userdata.orgs !== undefined) {
|
||||
const foundOrg = userdata.orgs.find((org) => org.id === data["org_id"]);
|
||||
if (foundOrg !== undefined && foundOrg !== null) {
|
||||
//position: "absolute", bottom: 5, right: -5,
|
||||
const imageStyle = {
|
||||
width: imagesize,
|
||||
height: imagesize,
|
||||
pointerEvents: "none",
|
||||
marginLeft:
|
||||
data.creator_org !== undefined && data.creator_org.length > 0
|
||||
? 20
|
||||
: 0,
|
||||
borderRadius: 10,
|
||||
border:
|
||||
foundOrg.id === userdata.active_org.id
|
||||
? `3px solid ${boxColor}`
|
||||
: null,
|
||||
cursor: "pointer",
|
||||
marginRight: 10,
|
||||
};
|
||||
|
||||
image =
|
||||
foundOrg.image === "" ? (
|
||||
<img
|
||||
alt={foundOrg.name}
|
||||
src={theme.palette.defaultImage}
|
||||
style={imageStyle}
|
||||
/>
|
||||
) : (
|
||||
<img
|
||||
alt={foundOrg.name}
|
||||
src={foundOrg.image}
|
||||
style={imageStyle}
|
||||
onClick={() => {}}
|
||||
/>
|
||||
);
|
||||
|
||||
orgName = foundOrg.name;
|
||||
orgId = foundOrg.id;
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Paper
|
||||
style={{
|
||||
backgroundColor: theme.palette.inputColor.backgroundColor,
|
||||
width: clickedFromOrgTab ? null :notificationWidth,
|
||||
padding: 30,
|
||||
borderBottom: "1px solid rgba(255,255,255,0.4)",
|
||||
marginBottom: 20,
|
||||
border: highlighted ? "2px solid #f85a3e" : null,
|
||||
borderRadius: theme.palette?.borderRadius,
|
||||
}}
|
||||
>
|
||||
<div style={{display: "flex", }}>
|
||||
{data.amount === 1 && data.read === false ?
|
||||
<Chip
|
||||
label={"First seen"}
|
||||
variant="contained"
|
||||
color="primary"
|
||||
style={{marginRight: 15, height: 25, }}
|
||||
/>
|
||||
: null}
|
||||
{data.ignored === true ?
|
||||
<Chip
|
||||
label={"Disabled"}
|
||||
variant="outlined"
|
||||
color="primary"
|
||||
style={{marginRight: 15, height: 25, }}
|
||||
/>
|
||||
: null}
|
||||
{data.read === false ?
|
||||
<Chip
|
||||
label={"Unread"}
|
||||
variant="outlined"
|
||||
color="primary"
|
||||
style={{marginRight: 15, height: 25, }}
|
||||
/>
|
||||
:
|
||||
<Chip
|
||||
label={"Read"}
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
style={{marginRight: 15, height: 25, }}
|
||||
/>
|
||||
}
|
||||
<Typography variant="body1" color="textPrimary" style={{ wordWrap: "break-word", overflow: "hidden", textOverflow: "ellipsis" }}>
|
||||
{data.title}
|
||||
</Typography >
|
||||
</div>
|
||||
|
||||
{data.image !== undefined && data.image !== null && data.image.length > 0 ?
|
||||
<img alt={data.title} src={data.image} style={{height: 100, width: 100, }} />
|
||||
:
|
||||
null
|
||||
}
|
||||
<Typography variant="body2" color="textSecondary" style={{ marginTop: 10, maxHeight: 200, overflowX: "hidden", overflowY: "auto", wordWrap: "break-word" }}>
|
||||
{data.description}
|
||||
</Typography >
|
||||
<div style={{ display: "flex" }}>
|
||||
<ButtonGroup>
|
||||
<Button
|
||||
color="secondary"
|
||||
variant="outlined"
|
||||
style={{ marginTop: 15 }}
|
||||
disabled={data.reference_url === undefined || data.reference_url === null || data.reference_url.length === 0}
|
||||
onClick={() => {
|
||||
window.open(data.reference_url, "_blank")
|
||||
}}
|
||||
>
|
||||
Explore
|
||||
</Button>
|
||||
{data.read === false ? (
|
||||
<Button
|
||||
color="secondary"
|
||||
variant="outlined"
|
||||
style={{ marginTop: 15 }}
|
||||
onClick={() => {
|
||||
dismissNotification(data.id);
|
||||
}}
|
||||
>
|
||||
Dismiss
|
||||
</Button>
|
||||
) : null}
|
||||
<Tooltip title="Disabling a notification makes it so similar notifications to this one will NOT be re-opened. It will NOT forward notifications to your notification workflow, but WILL still keep counting." placement="top">
|
||||
<Button
|
||||
color="secondary"
|
||||
variant={data.ignored === true ? "contained" : "outlined"}
|
||||
style={{ marginTop: 15, }}
|
||||
onClick={() => {
|
||||
if (data.ignored === true) {
|
||||
dismissNotification(data.id, false)
|
||||
} else {
|
||||
dismissNotification(data.id, true)
|
||||
}
|
||||
}}
|
||||
>
|
||||
{data.ignored === true ? "Re-enable" : "Disable"}
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</ButtonGroup>
|
||||
|
||||
<Typography variant="body2" color="textSecondary" style={{ marginLeft: 20, marginTop: 20, wordWrap: "break-word", overflow: "hidden", textOverflow: "ellipsis" }}>
|
||||
<b>First seen</b>: {new Date(data.created_at * 1000).toISOString().slice(0, 19)}
|
||||
</Typography >
|
||||
|
||||
<Typography variant="body2" color="textSecondary" style={{ marginLeft: 20, marginTop: 20, wordWrap: "break-word", overflow: "hidden", textOverflow: "ellipsis" }}>
|
||||
<b>Last seen</b>: {new Date(data.updated_at * 1000).toISOString().slice(0, 19)}
|
||||
</Typography >
|
||||
|
||||
<Typography variant="body2" color="textSecondary" style={{ marginLeft: 20, marginTop: 20, wordWrap: "break-word", overflow: "hidden", textOverflow: "ellipsis" }}>
|
||||
<b>Times seen</b>: {data.amount}
|
||||
</Typography >
|
||||
</div>
|
||||
</Paper>
|
||||
);
|
||||
})
|
||||
|
||||
|
||||
const NotificationComponent = memo(({notifications, showRead, selectedExecutionId, selectedWorkflow, highlightKMS, userdata, imagesize, boxColor, clickedFromOrgTab, notificationWidth, dismissNotification}) => {
|
||||
|
||||
return(
|
||||
<div>
|
||||
{notifications === null || notifications === undefined || notifications?.length === 0 ? (
|
||||
null
|
||||
) :
|
||||
<div>
|
||||
{notifications?.map((notification, index) => {
|
||||
if (showRead === false && notification.read === true) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<NotificationItem data={notification} key={index} selectedExecutionId={selectedExecutionId} selectedWorkflow={selectedWorkflow} highlightKMS={highlightKMS} userdata={userdata} imagesize={imagesize} boxColor={boxColor} clickedFromOrgTab={clickedFromOrgTab} notificationWidth={notificationWidth} dismissNotification={dismissNotification} />
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
)
|
||||
})
|
||||
|
||||
// const PaddingWrapper = memo(({children, clickedFromOrgTab}) => {
|
||||
|
||||
// const { leftSideBarOpenByClick } = useContext(Context)
|
||||
|
||||
// return(
|
||||
// <div style={{width: leftSideBarOpenByClick ? 950 : 1030,transition: 'width 0.3s ease', padding: clickedFromOrgTab ? "27px 10px 19px 27px":null, height: clickedFromOrgTab ? "auto":null, minHeight: 843, backgroundColor: clickedFromOrgTab ? '#212121':null, borderRadius: clickedFromOrgTab ? '16px':null, }}>
|
||||
// {children}
|
||||
// </div>
|
||||
// )
|
||||
// })
|
||||
|
||||
// const Wrapper = memo(({children, clickedFromOrgTab}) => {
|
||||
|
||||
// return(
|
||||
// <PaddingWrapper clickedFromOrgTab={clickedFromOrgTab}>
|
||||
// {children}
|
||||
// </PaddingWrapper>
|
||||
// )
|
||||
// })
|
||||
|
||||
@@ -1084,6 +1084,8 @@ const CodeEditor = (props) => {
|
||||
maxHeight: isMobile ? "100%" : 700,
|
||||
border: theme.palette.defaultBorder,
|
||||
padding: isMobile ? "25px 10px 25px 10px" : 25,
|
||||
zoom: 0.8,
|
||||
backgroundColor: "black",
|
||||
},
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -382,7 +382,7 @@ const data = [
|
||||
css: {
|
||||
"background-color": "#f85a3e",
|
||||
"border-color": "#f85a3e",
|
||||
"border-width": "12px",
|
||||
"border-width": "7px",
|
||||
"transition-property": "border-width",
|
||||
"transition-duration": "0.25s",
|
||||
label: "data(label)",
|
||||
|
||||
@@ -50,6 +50,12 @@ const theme = createTheme(adaptV4Theme({
|
||||
borderRadius: 5,
|
||||
height: 40,
|
||||
},
|
||||
DialogStyle: {
|
||||
backgroundColor: "#212121",
|
||||
borderRadius: 2,
|
||||
boxShadow: "0px 0px 10px 0px rgba(0,0,0,0.75)",
|
||||
border: "1px solid #494949",
|
||||
},
|
||||
innerTextfieldStyle: {
|
||||
height: 40,
|
||||
fontSize: 16,
|
||||
|
||||
+109
-14
@@ -4,13 +4,13 @@ import { toast } from "react-toastify";
|
||||
|
||||
const Admin2 = (props) => {
|
||||
// Destructure props if needed
|
||||
const { userdata, globalUrl, isCloud, serverside, checkLogin, notifications, setNotifications, stripeKey } = props;
|
||||
const { userdata, globalUrl, serverside, checkLogin, notifications, setNotifications, stripeKey, isLoaded, isLoggedIn} = props;
|
||||
const [selectedTab, setSelectedTab] = useState('editdetails');
|
||||
const [selectedStatus, setSelectedStatus] = React.useState([]);
|
||||
const [selectedOrganization, setSelectedOrganization] = useState({});
|
||||
const [organizationFeatures, setOrganizationFeatures] = useState({});
|
||||
const [orgRequest, setOrgRequest] = React.useState(true);
|
||||
|
||||
const isCloud = window.location.host === "localhost:3002" || window.location.host === "shuffler.io";
|
||||
const handleGetOrg = (orgId) => {
|
||||
if (
|
||||
serverside !== true &&
|
||||
@@ -51,8 +51,11 @@ const Admin2 = (props) => {
|
||||
.then((responseJson) => {
|
||||
if (responseJson["success"] === false) {
|
||||
toast(
|
||||
"Failed getting your org. If this persists, please contact support.",
|
||||
"Failed getting your org. If this persists, please contact support. Redirecting to workflows...",
|
||||
);
|
||||
setTimeout(() => {
|
||||
window.location.href = "/workflows";
|
||||
}, 3000);
|
||||
} else {
|
||||
if (
|
||||
responseJson.sync_features === undefined ||
|
||||
@@ -151,6 +154,77 @@ const Admin2 = (props) => {
|
||||
});
|
||||
};
|
||||
|
||||
const urlSearchParams = new URLSearchParams(window.location.search);
|
||||
const params = Object.fromEntries(urlSearchParams.entries());
|
||||
const foundOrgID = params["org_id"]
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
if(foundOrgID !== null && foundOrgID !== undefined && userdata?.support && foundOrgID?.length > 0) {
|
||||
handleClickChangeOrg(foundOrgID)
|
||||
}
|
||||
}, [foundOrgID]);
|
||||
|
||||
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.removeItem("apps")
|
||||
localStorage.removeItem("workflows")
|
||||
localStorage.removeItem("userinfo")
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
window.location.reload()
|
||||
}, 3000);
|
||||
toast("Successfully changed active organization - refreshing!");
|
||||
} else {
|
||||
if (responseJson.reason !== undefined && responseJson.reason !== null) {
|
||||
if (!responseJson.reason.includes("already")) {
|
||||
toast("Failed changing org: " + responseJson.reason);
|
||||
}
|
||||
} else {
|
||||
toast("Failed changing org")
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log("error changing: ", error);
|
||||
//removeCookie("session_token", {path: "/"})
|
||||
});
|
||||
};
|
||||
|
||||
const handleEditOrg = (
|
||||
name,
|
||||
description,
|
||||
@@ -159,6 +233,7 @@ const Admin2 = (props) => {
|
||||
defaults,
|
||||
sso_config,
|
||||
lead_info,
|
||||
{ mfa_required } = {}
|
||||
) => {
|
||||
const data = {
|
||||
name: name,
|
||||
@@ -168,6 +243,7 @@ const Admin2 = (props) => {
|
||||
defaults: defaults,
|
||||
sso_config: sso_config,
|
||||
lead_info: lead_info,
|
||||
mfa_required: mfa_required !== undefined ? mfa_required : selectedOrganization?.mfa_required,
|
||||
};
|
||||
|
||||
const url = globalUrl + `/api/v1/orgs/${selectedOrganization.id}`;
|
||||
@@ -202,21 +278,40 @@ const Admin2 = (props) => {
|
||||
});
|
||||
};
|
||||
|
||||
// useEffect(() => {
|
||||
// handleGetOrg();
|
||||
// }, []);
|
||||
|
||||
const handleStatusChange = (event) => {
|
||||
const { value } = event.target;
|
||||
setSelectedStatus(value);
|
||||
|
||||
handleEditOrg(
|
||||
"",
|
||||
"",
|
||||
selectedOrganization?.name,
|
||||
selectedOrganization?.description,
|
||||
selectedOrganization.id,
|
||||
"",
|
||||
{},
|
||||
{},
|
||||
selectedOrganization?.image,
|
||||
{
|
||||
app_download_repo: selectedOrganization?.defaults?.app_download_repo,
|
||||
app_download_branch: selectedOrganization?.defaults?.app_download_branch,
|
||||
workflow_download_repo: selectedOrganization?.defaults?.workflow_download_repo,
|
||||
workflow_download_branch: selectedOrganization?.defaults?.workflow_download_branch,
|
||||
notification_workflow: selectedOrganization?.defaults?.notification_workflow,
|
||||
documentation_reference: selectedOrganization?.defaults?.documentation_reference,
|
||||
workflow_upload_repo: selectedOrganization?.defaults?.workflow_upload_repo,
|
||||
workflow_upload_branch: selectedOrganization?.defaults?.workflow_upload_branch,
|
||||
workflow_upload_username: selectedOrganization?.defaults?.workflow_upload_username,
|
||||
workflow_upload_token: selectedOrganization?.defaults?.workflow_upload_token,
|
||||
newsletter: !selectedOrganization?.defaults?.newsletter,
|
||||
weekly_recommendations: selectedOrganization?.defaults?.weekly_recommendations,
|
||||
},
|
||||
{
|
||||
sso_entrypoint: selectedOrganization?.sso_config?.sso_entrypoint,
|
||||
sso_certificate: selectedOrganization?.sso_config?.sso_certificate,
|
||||
client_id: selectedOrganization?.sso_config?.client_id,
|
||||
client_secret: selectedOrganization?.sso_config?.client_secret,
|
||||
openid_authorization: selectedOrganization?.sso_config?.openid_authorization,
|
||||
openid_token: selectedOrganization?.sso_config?.openid_token,
|
||||
SSORequired: selectedOrganization?.sso_config?.SSORequired,
|
||||
auto_provision: selectedOrganization?.sso_config?.auto_provision,
|
||||
},
|
||||
value.length === 0 ? ["none"] : value,
|
||||
);
|
||||
};
|
||||
@@ -228,14 +323,14 @@ const Admin2 = (props) => {
|
||||
orgRequest
|
||||
) {
|
||||
const orgId = userdata.active_org.id
|
||||
console.log("orgID", orgId)
|
||||
|
||||
setOrgRequest(false);
|
||||
handleGetOrg(orgId);
|
||||
}
|
||||
|
||||
return (
|
||||
<div style={{ display: 'flex', justifyContent: 'center', paddingTop: 30 }}>
|
||||
<AdminNavBar userdata={userdata} selectedStatus={selectedStatus} setSelectedStatus={setSelectedStatus} selectedTab={selectedTab} orgId={selectedOrganization.id} handleStatusChange={handleStatusChange} handleEditOrg={handleEditOrg} handleGetOrg={handleGetOrg} setSelectedOrganization={setSelectedOrganization} selectedOrganization={selectedOrganization} setNotifications={setNotifications} stripeKey={stripeKey} notifications={notifications} checkLogin={checkLogin} globalUrl={globalUrl} isCloud={isCloud} serverside={serverside} />
|
||||
<div style={{ display: 'flex', justifyContent: 'center', paddingTop: 29, zoom: 0.8, }}>
|
||||
<AdminNavBar userdata={userdata} isLoaded={isLoaded} selectedStatus={selectedStatus} setSelectedStatus={setSelectedStatus} selectedTab={selectedTab} orgId={selectedOrganization.id} handleStatusChange={handleStatusChange} handleEditOrg={handleEditOrg} handleGetOrg={handleGetOrg} setSelectedOrganization={setSelectedOrganization} selectedOrganization={selectedOrganization} setNotifications={setNotifications} stripeKey={stripeKey} notifications={notifications} checkLogin={checkLogin} globalUrl={globalUrl} isCloud={isCloud} serverside={serverside} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -422,7 +422,7 @@ const AngularWorkflow = (defaultprops) => {
|
||||
const [subworkflow, setSubworkflow] = React.useState({});
|
||||
const [subworkflowStartnode, setSubworkflowStartnode] = React.useState("");
|
||||
const [leftViewOpen, setLeftViewOpen] = React.useState(isMobile ? false : true);
|
||||
const [leftBarSize, setLeftBarSize] = React.useState(isMobile ? 0 : 255)
|
||||
const [leftBarSize, setLeftBarSize] = React.useState(isMobile ? 0 : 235)
|
||||
const [creatorProfile, setCreatorProfile] = React.useState({});
|
||||
const [usecases, setUsecases] = React.useState([]);
|
||||
const [files, setFiles] = React.useState({
|
||||
@@ -3813,7 +3813,7 @@ const releaseToConnectLabel = "Release to Connect"
|
||||
});
|
||||
}
|
||||
|
||||
cy.fit(null, 100);
|
||||
cy.fit(null, 400);
|
||||
cy.on("add", "node", (e) => onNodeAdded(e));
|
||||
cy.on("add", "edge", (e) => onEdgeAdded(e));
|
||||
} else {
|
||||
@@ -4052,7 +4052,7 @@ const releaseToConnectLabel = "Release to Connect"
|
||||
.then(() => {
|
||||
console.log("DONE: ", workflow_id);
|
||||
getWorkflow(workflow_id.value, nodedata);
|
||||
cy.fit(null, 50);
|
||||
cy.fit(null, 300);
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -4180,7 +4180,7 @@ const releaseToConnectLabel = "Release to Connect"
|
||||
|
||||
if (nodedata.app_name === "Webhook" || nodedata.app_name === "Schedule" || nodedata.app_name === "Gmail" || nodedata.app_name === "Office365") {
|
||||
if (!found) {
|
||||
console.log("Find amount of executions for the specific nodetype: ", nodedata.app_name, "Executions: ", workflowExecutions)
|
||||
//console.log("Find amount of executions for the specific nodetype: ", nodedata.app_name, "Executions: ", workflowExecutions)
|
||||
// Find how many executions it has
|
||||
var executions = 0
|
||||
const matchingExecutions = workflowExecutions.filter((execution => execution.execution_source === nodedata.app_name.toLowerCase()))
|
||||
@@ -6121,7 +6121,7 @@ const releaseToConnectLabel = "Release to Connect"
|
||||
event.target.remove()
|
||||
|
||||
//console.log("Found branch already!")
|
||||
toast.error("Triggers can have exactly one target node")
|
||||
toast.error("Triggers can point to exactly one start node")
|
||||
return
|
||||
|
||||
|
||||
@@ -7782,7 +7782,7 @@ const releaseToConnectLabel = "Release to Connect"
|
||||
const item = typeIds[idkey]
|
||||
if (item.data.id === nodedata.id) {
|
||||
//console.log("items: ", item.data.id, nodedata.id)
|
||||
parsedStyle["border-width"] = "12px"
|
||||
parsedStyle["border-width"] = "7px"
|
||||
break
|
||||
}
|
||||
}
|
||||
@@ -8391,7 +8391,7 @@ const releaseToConnectLabel = "Release to Connect"
|
||||
// Reset view for cytoscape
|
||||
if (cy !== undefined && cy !== null) {
|
||||
cy.add(insertedNodes);
|
||||
cy.fit(null, 200);
|
||||
cy.fit(null, 400);
|
||||
} else {
|
||||
setElements(insertedNodes);
|
||||
}
|
||||
@@ -8772,7 +8772,7 @@ const releaseToConnectLabel = "Release to Connect"
|
||||
}
|
||||
// preview: true,
|
||||
|
||||
cy.fit(null, 200);
|
||||
cy.fit(null, 400)
|
||||
|
||||
cy.on("boxselect", "node", (e) => {
|
||||
if (e.target.data("isButton") || e.target.data("isDescriptor") || e.target.data("isSuggestion")) {
|
||||
@@ -9380,7 +9380,9 @@ const releaseToConnectLabel = "Release to Connect"
|
||||
onChange={handleSetTab}
|
||||
aria-label="Left sidebar tab"
|
||||
orientation={isMobile ? "vertical" : "horizontal"}
|
||||
style={{}}
|
||||
style={{
|
||||
display: "flex",
|
||||
}}
|
||||
>
|
||||
<Tab
|
||||
value={0}
|
||||
@@ -9421,7 +9423,7 @@ const releaseToConnectLabel = "Release to Connect"
|
||||
<Grid item>
|
||||
<FavoriteBorderIcon style={iconStyle} />
|
||||
</Grid>
|
||||
{isMobile ? null : <Grid item>Variables</Grid>}
|
||||
{isMobile ? null : <Grid item>Vars</Grid>}
|
||||
</Grid>
|
||||
}
|
||||
style={tabStyle}
|
||||
@@ -9776,11 +9778,13 @@ const releaseToConnectLabel = "Release to Connect"
|
||||
const barHeight = bodyHeight - appBarSize - 50;
|
||||
const appScrollStyle = {
|
||||
overflow: "scroll",
|
||||
maxHeight: isMobile ? bodyHeight - appBarSize * 4 : barHeight-300,
|
||||
minHeight: isMobile ? bodyHeight - appBarSize * 4 : barHeight-300,
|
||||
maxHeight: isMobile ? bodyHeight - appBarSize * 4 : barHeight-70,
|
||||
minHeight: isMobile ? bodyHeight - appBarSize * 4 : barHeight-70,
|
||||
marginTop: 1,
|
||||
overflowY: "auto",
|
||||
overflowX: "hidden",
|
||||
|
||||
zoom: 0.9,
|
||||
}
|
||||
|
||||
const handleAppDrag = (e, app) => {
|
||||
@@ -10568,12 +10572,12 @@ const releaseToConnectLabel = "Release to Connect"
|
||||
var viewedApps = []
|
||||
return (
|
||||
<div style={appViewStyle}>
|
||||
<div style={{ flex: "1" }}>
|
||||
<div style={{ flex: "1", zoom: 0.9, }}>
|
||||
<TextField
|
||||
style={{
|
||||
backgroundColor: theme.palette.inputColor,
|
||||
borderRadius: theme.palette?.borderRadius,
|
||||
marginTop: 5,
|
||||
marginTop: 10,
|
||||
marginRight: 10,
|
||||
height: 40,
|
||||
}}
|
||||
@@ -11193,14 +11197,12 @@ const releaseToConnectLabel = "Release to Connect"
|
||||
overflowAnchor: "none",
|
||||
};
|
||||
|
||||
const minSize = 370
|
||||
const minSize = 370
|
||||
var rightsidebarStyle = {
|
||||
position: "fixed",
|
||||
top: appBarSize - 35,
|
||||
right: 25,
|
||||
height: "90vh",
|
||||
width: isMobile ? "100%" : minSize,
|
||||
minWidth: minSize,
|
||||
maxWidth: 600,
|
||||
maxHeight: "100vh",
|
||||
border: "1px solid rgb(91, 96, 100)",
|
||||
@@ -11210,6 +11212,9 @@ const releaseToConnectLabel = "Release to Connect"
|
||||
overflow: "auto",
|
||||
|
||||
overflowAnchor: "none",
|
||||
minWidth: minSize,
|
||||
width: isMobile ? "100%" : minSize,
|
||||
zoom: 0.9,
|
||||
};
|
||||
|
||||
const setTriggerFolderWrapperMulti = (event) => {
|
||||
@@ -16153,13 +16158,15 @@ const releaseToConnectLabel = "Release to Connect"
|
||||
position: "absolute",
|
||||
|
||||
top: isMobile ? 30 : 25,
|
||||
left: isMobile ? 20 : leftSideBarOpenByClick ? leftBarSize + 275 : leftBarSize+100,
|
||||
left: isMobile ? 20 : leftSideBarOpenByClick ? leftBarSize + 275 : leftBarSize+135,
|
||||
|
||||
transition: "left 0.3s ease",
|
||||
maxWidth: 500,
|
||||
zoom: 0.9,
|
||||
}
|
||||
|
||||
const TopCytoscapeBar = (props) => {
|
||||
const [hovered, setHovered] = useState(false)
|
||||
|
||||
if (workflow.public === true) {
|
||||
return null
|
||||
}
|
||||
@@ -16174,12 +16181,30 @@ const releaseToConnectLabel = "Release to Connect"
|
||||
<div style={topBarStyle}>
|
||||
<div style={{
|
||||
margin: "0px 10px 0px 35px",
|
||||
maxWidth: 500,
|
||||
}}>
|
||||
<Typography variant="h6" style={{
|
||||
margin: 0,
|
||||
}}>
|
||||
{workflow.name}
|
||||
cursor: "pointer",
|
||||
display: "flex",
|
||||
borderRadius: theme.palette.borderRadius,
|
||||
border: hovered ? "1px solid rgba(255,255,255,0.3)" : "1px solid transparent",
|
||||
paddingRight: 10,
|
||||
paddingLeft: 10,
|
||||
position: "relative",
|
||||
}}
|
||||
onMouseEnter={() => {
|
||||
setHovered(true)
|
||||
}}
|
||||
onMouseLeave={() => {
|
||||
setHovered(false)
|
||||
}}
|
||||
onClick={() => {
|
||||
setEditWorkflowModalOpen(true)
|
||||
setLastSaved(false)
|
||||
}}
|
||||
>
|
||||
<EditIcon style={{position: "absolute", top: 7, height: 20, width: 20, }} />
|
||||
<span style={{marginLeft: 30, }}>{workflow.name}</span>
|
||||
</Typography>
|
||||
{workflowAsCode && (
|
||||
<Tooltip title="Switch to Code View">
|
||||
@@ -16204,7 +16229,7 @@ const releaseToConnectLabel = "Release to Connect"
|
||||
|
||||
{!distributedFromParent ?
|
||||
isCorrectOrg ? null :
|
||||
<Typography variant="body1">
|
||||
<Typography variant="body2">
|
||||
<b>Warning</b>: Change <span
|
||||
style={{color: "#FF8544", cursor: "pointer", pointerEvents: "auto", }}
|
||||
onClick={() => {
|
||||
@@ -16275,7 +16300,7 @@ const releaseToConnectLabel = "Release to Connect"
|
||||
>Active Organization</span> to edit this Workflow.
|
||||
</Typography>
|
||||
:
|
||||
<Typography variant="body1">
|
||||
<Typography variant="body2" color="textSecondary">
|
||||
Warning: This workflow is controlled by your parent org and may not be editable.
|
||||
</Typography>
|
||||
}
|
||||
@@ -16285,7 +16310,7 @@ const releaseToConnectLabel = "Release to Connect"
|
||||
|
||||
<InputLabel
|
||||
id="suborg-changer"
|
||||
style={{ color: "white" }}
|
||||
style={{ color: "rgba(255,255,255,0.7)", }}
|
||||
>
|
||||
Select an Org
|
||||
</InputLabel>
|
||||
@@ -16294,10 +16319,15 @@ const releaseToConnectLabel = "Release to Connect"
|
||||
pointerEvents: "auto",
|
||||
backgroundColor: theme.palette.inputColor,
|
||||
color: "white",
|
||||
height: 50,
|
||||
maxWidth: 250,
|
||||
minWidth: 250,
|
||||
borderRadius: theme.palette?.borderRadius,
|
||||
height: 40,
|
||||
}}
|
||||
InputProps={{
|
||||
style: {
|
||||
height: 40,
|
||||
}
|
||||
}}
|
||||
labelId="suborg-changer"
|
||||
value={workflow.org_id}
|
||||
@@ -16470,47 +16500,16 @@ const releaseToConnectLabel = "Release to Connect"
|
||||
</Select>
|
||||
</FormControl>
|
||||
}
|
||||
|
||||
</div>
|
||||
<div style={{display: "flex", marginLeft: 10, maxWidth: 250, pointerEvents: "auto", }}>
|
||||
{parentWorkflows.slice(0,5).map((wf, index) => {
|
||||
return (
|
||||
<a href={`/workflows/${wf.id}`} target="_blank" rel="noopener noreferrer" key={index}>
|
||||
<Tooltip arrow placement="left" title={
|
||||
<span style={{}}>
|
||||
{wf.image !== undefined && wf.image !== null && wf.image.length > 0 ?
|
||||
<img
|
||||
src={wf.image}
|
||||
alt={wf.name}
|
||||
style={{ backgroundColor: theme.palette.surfaceColor, maxHeight: 200, minHeigth: 200, borderRadius: theme.palette?.borderRadius, }}
|
||||
|
||||
/>
|
||||
: null}
|
||||
<Typography>
|
||||
Parent workflow: '{wf.name}'
|
||||
</Typography>
|
||||
</span>
|
||||
|
||||
} placement="bottom">
|
||||
<span onClick={() => {
|
||||
console.log("Click: ", wf)
|
||||
}}>
|
||||
<img src={theme.palette.defaultImage} style={{height: 25, width: 25, cursor: "pointer", border: 15, marginRight: 5, marginTop: 5, filter: "grayscale(90%)", }} />
|
||||
</span>
|
||||
</Tooltip>
|
||||
</a>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{showEnvironment === true && environments.length > 1 && selectedActionEnvironment !== undefined && selectedActionEnvironment !== null && selectedActionEnvironment.Name !== undefined && selectedActionEnvironment.Name !== null ?
|
||||
<FormControl fullWidth style={{marginTop: 15, marginleft: 10, pointerEvents: "auto", maxWidth: 250, }}>
|
||||
<FormControl fullWidth style={{marginTop: 15, pointerEvents: "auto", maxWidth: 250, }}>
|
||||
|
||||
<InputLabel
|
||||
id="execution_location"
|
||||
style={{ color: "white" }}
|
||||
style={{ color: "rgba(255,255,255,0.7)", marginLeft: 40, }}
|
||||
>
|
||||
Execution Location
|
||||
Location
|
||||
</InputLabel>
|
||||
<Select
|
||||
labelId="execution_location"
|
||||
@@ -16523,6 +16522,11 @@ const releaseToConnectLabel = "Release to Connect"
|
||||
style: {
|
||||
},
|
||||
}}
|
||||
InputProps={{
|
||||
style: {
|
||||
height: 40,
|
||||
}
|
||||
}}
|
||||
onChange={(e) => {
|
||||
setLastSaved(false)
|
||||
const env = environments.find((a) => a.Name === e.target.value);
|
||||
@@ -16539,13 +16543,14 @@ const releaseToConnectLabel = "Release to Connect"
|
||||
}}
|
||||
style={{
|
||||
pointerEvents: "auto",
|
||||
backgroundColor: theme.palette.inputColor,
|
||||
color: "white",
|
||||
height: 50,
|
||||
maxWidth: 250,
|
||||
minWidth: 250,
|
||||
borderRadius: theme.palette?.borderRadius,
|
||||
marginLeft: 10,
|
||||
marginLeft: 35,
|
||||
|
||||
backgroundColor: theme.palette.inputColor,
|
||||
height: 40,
|
||||
}}
|
||||
>
|
||||
{environments.map((data, index) => {
|
||||
@@ -16603,6 +16608,43 @@ const releaseToConnectLabel = "Release to Connect"
|
||||
</FormControl>
|
||||
: null}
|
||||
|
||||
|
||||
{parentWorkflows === undefined || parentWorkflows === null || parentWorkflows.length === 0 ? null :
|
||||
<div style={{display: "flex", marginLeft: 40, maxWidth: 250, pointerEvents: "auto", marginTop: 5, }}>
|
||||
<Typography variant="body2" color="textSecondary" style={{marginRight: 5, marginTop: 5, }}>
|
||||
<b>Parent Workflows:</b>
|
||||
</Typography>
|
||||
{parentWorkflows.slice(0,5).map((wf, index) => {
|
||||
return (
|
||||
<a href={`/workflows/${wf.id}`} target="_blank" rel="noopener noreferrer" key={index}>
|
||||
<Tooltip arrow placement="left" title={
|
||||
<span style={{}}>
|
||||
{wf.image !== undefined && wf.image !== null && wf.image.length > 0 ?
|
||||
<img
|
||||
src={wf.image}
|
||||
alt={wf.name}
|
||||
style={{ backgroundColor: theme.palette.surfaceColor, maxHeight: 200, minHeigth: 200, borderRadius: theme.palette?.borderRadius, }}
|
||||
|
||||
/>
|
||||
: null}
|
||||
<Typography>
|
||||
Parent workflow: '{wf.name}'
|
||||
</Typography>
|
||||
</span>
|
||||
|
||||
} placement="bottom">
|
||||
<span onClick={() => {
|
||||
console.log("Click: ", wf)
|
||||
}}>
|
||||
<img src={theme.palette.defaultImage} style={{height: 25, width: 25, cursor: "pointer", border: 15, marginRight: 5, marginTop: 5, filter: "grayscale(90%)", }} />
|
||||
</span>
|
||||
</Tooltip>
|
||||
</a>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
}
|
||||
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -17210,7 +17252,7 @@ const releaseToConnectLabel = "Release to Connect"
|
||||
<Tooltip color="primary" title="Stop execution" placement="top">
|
||||
<span>
|
||||
<Button
|
||||
style={{ height: boxSize, width: boxSize }}
|
||||
style={{ height: boxSize, width: boxSize+5 }}
|
||||
color="secondary"
|
||||
variant="contained"
|
||||
onClick={() => {
|
||||
@@ -17228,7 +17270,7 @@ const releaseToConnectLabel = "Release to Connect"
|
||||
workflow.public
|
||||
|| executionRequestStarted
|
||||
}
|
||||
style={{ height: boxSize, width: boxSize, backgroundColor: green, }}
|
||||
style={{ height: boxSize, width: boxSize+5, backgroundColor: green, }}
|
||||
color="primary"
|
||||
variant="contained"
|
||||
onClick={() => {
|
||||
@@ -17265,7 +17307,7 @@ const releaseToConnectLabel = "Release to Connect"
|
||||
{executionButton}
|
||||
<Tooltip
|
||||
color="secondary"
|
||||
title={`Show previous runs (${workflowExecutions.length}) (Ctrl + ')`}
|
||||
title={`Show previous workflow runs (${workflowExecutions.length}) (Ctrl + ')`}
|
||||
placement="top-start"
|
||||
>
|
||||
<Button
|
||||
@@ -17492,6 +17534,8 @@ const releaseToConnectLabel = "Release to Connect"
|
||||
workflow.configuration.exit_on_error !== undefined ? (
|
||||
<WorkflowMenu />
|
||||
) : null}
|
||||
|
||||
{/*
|
||||
<Tooltip
|
||||
color="secondary"
|
||||
title="Edit workflow details"
|
||||
@@ -17514,6 +17558,7 @@ const releaseToConnectLabel = "Release to Connect"
|
||||
</Button>
|
||||
</span>
|
||||
</Tooltip>
|
||||
*/}
|
||||
|
||||
<Tooltip
|
||||
color="secondary"
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
|
||||
import React, { memo, useCallback } from "react";
|
||||
import { useState, useEffect, useContext, Suspense } from "react";
|
||||
import { useNavigate, Link, useLocation } from "react-router-dom";
|
||||
@@ -57,7 +58,7 @@ const ApiExplorer = React.lazy(() => import("../components/ApiExplorer.jsx"));
|
||||
|
||||
|
||||
const ApiExplorerWrapper = (props) => {
|
||||
const { globalUrl, serverside, userdata, isLoggedIn} = props;
|
||||
const { globalUrl, serverside, userdata, isLoggedIn, isLoaded} = props;
|
||||
const isCloud = window.location.host === "localhost:3002" || window.location.host === "shuffler.io"
|
||||
const location = useLocation();
|
||||
const navigate = useNavigate();
|
||||
@@ -1754,7 +1755,7 @@ const ApiExplorerWrapper = (props) => {
|
||||
)});
|
||||
|
||||
return (
|
||||
<Wrapper userdata={userdata}>
|
||||
<Wrapper isLoggedIn={isLoggedIn} isLoaded={isLoaded}>
|
||||
<Suspense fallback={skeletonLoader}>
|
||||
{authenticationModal}
|
||||
<ApiExplorer
|
||||
@@ -1765,6 +1766,8 @@ const ApiExplorerWrapper = (props) => {
|
||||
HandleApiExecution={HandleApiExecution}
|
||||
selectedAppData={selectedAppData}
|
||||
ConfigurationTab={ConfigurationTab}
|
||||
isLoggedIn={isLoggedIn}
|
||||
isLoaded={isLoaded}
|
||||
/>
|
||||
</Suspense>
|
||||
</Wrapper>
|
||||
@@ -1774,13 +1777,13 @@ const ApiExplorerWrapper = (props) => {
|
||||
export default ApiExplorerWrapper;
|
||||
|
||||
|
||||
const Wrapper = ({children, userdata})=>{
|
||||
const Wrapper = ({children, isLoaded,isLoggedIn})=>{
|
||||
|
||||
const { leftSideBarOpenByClick } = useContext(Context);
|
||||
|
||||
return(
|
||||
|
||||
<div className="api-explorer-wrapper" style={{ paddingLeft: userdata?.support ? leftSideBarOpenByClick ? 280 : 100 : 0, transition: 'padding-left 0.3s ease' }}>
|
||||
<div className="api-explorer-wrapper" style={{ paddingLeft: (isLoggedIn && isLoaded) ? leftSideBarOpenByClick ? 280 : 100 : 0, transition: 'padding-left 0.3s ease' }}>
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -3239,15 +3239,13 @@ const AppsWrapper = memo(({ appView, modalView, userdata, publishModal, generate
|
||||
));
|
||||
|
||||
|
||||
const SidebarAdjustWrapper = memo(({ userdata, children }) => {
|
||||
const SidebarAdjustWrapper = memo(({ children }) => {
|
||||
|
||||
const {leftSideBarOpenByClick } = useContext(Context)
|
||||
const marginLeft = userdata?.support
|
||||
? leftSideBarOpenByClick ? 250 : 80
|
||||
: 0;
|
||||
|
||||
|
||||
return (
|
||||
<div style={{ marginLeft, transition: 'margin-left 0.3s ease' }}>
|
||||
<div style={{ marginLeft: leftSideBarOpenByClick ? 250 : 80, transition: 'margin-left 0.3s ease' }}>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
|
||||
+477
-311
File diff suppressed because it is too large
Load Diff
@@ -274,7 +274,8 @@ const CodeWorkflow = (defaultprops) => {
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
height: '100vh', // Set to full viewport height
|
||||
backgroundColor: '#252526'
|
||||
backgroundColor: '#252526',
|
||||
marginLeft: '100px',
|
||||
}}>
|
||||
{/* IDE-like toolbar */}
|
||||
<Toolbar
|
||||
|
||||
@@ -337,11 +337,23 @@ const Dashboard = (props) => {
|
||||
const [, setUpdate] = useState(0);
|
||||
|
||||
let navigate = useNavigate();
|
||||
const isCloud =
|
||||
window.location.host === "localhost:3002" ||
|
||||
window.location.host === "shuffler.io";
|
||||
const isCloud = window.location.host === "localhost:3002" || window.location.host === "shuffler.io";
|
||||
|
||||
const path = window.location.pathname
|
||||
if (path !== undefined && path !== null) {
|
||||
if (path.includes("/automate")) {
|
||||
navigate("/usecases")
|
||||
}
|
||||
|
||||
if (path.includes("/security")) {
|
||||
navigate("/forms")
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
// Look for the path. If it is automation, go to usecases
|
||||
// Handles redirect
|
||||
|
||||
const widgetnames = ["app_executions_cloud"]
|
||||
for (let widgetkey in widgetnames) {
|
||||
const widgetName = widgetnames[widgetkey]
|
||||
@@ -859,7 +871,7 @@ const Dashboard = (props) => {
|
||||
);
|
||||
|
||||
const dataWrapper = (
|
||||
<div style={{ maxWidth: 1366, margin: "auto" }}>{data}</div>
|
||||
<div style={{ maxWidth: 1366, margin: "auto", paddingTop: 10, }}>{data}</div>
|
||||
);
|
||||
|
||||
return dataWrapper;
|
||||
|
||||
@@ -251,7 +251,7 @@ export const CodeHandler = (props) => {
|
||||
}
|
||||
|
||||
const Docs = (defaultprops) => {
|
||||
const { globalUrl, selectedDoc, serverside, serverMobile, userdata } = defaultprops;
|
||||
const { globalUrl, selectedDoc, serverside, serverMobile, isLoggedIn, isLoaded } = defaultprops;
|
||||
let navigate = useNavigate();
|
||||
// Quickfix for react router 5 -> 6
|
||||
const params = useParams();
|
||||
@@ -1266,7 +1266,7 @@ const Docs = (defaultprops) => {
|
||||
|
||||
// Padding and zIndex etc set because of footer in cloud.
|
||||
const loadedCheck = (
|
||||
<DocsWrapper userdata={userdata}>
|
||||
<DocsWrapper isLoggedIn={isLoggedIn} isLoaded={isLoaded}>
|
||||
<DocsContent postDataBrowser={postDataBrowser} postDataMobile={postDataMobile}/>
|
||||
</DocsWrapper>
|
||||
);
|
||||
@@ -1285,18 +1285,18 @@ const DocsContent = memo(({postDataBrowser, postDataMobile}) => {
|
||||
</div>
|
||||
)})
|
||||
|
||||
const DocsWrapper = memo(({userdata, children })=>{
|
||||
const DocsWrapper = memo(({isLoggedIn, isLoaded, children })=>{
|
||||
|
||||
const { leftSideBarOpenByClick, windowWidth } = useContext(Context);
|
||||
|
||||
return (
|
||||
<div style={{
|
||||
minHeight: 1000, zIndex: 1,
|
||||
maxWidth: Math.min(leftSideBarOpenByClick ? windowWidth - 300 : windowWidth - 200, 1920),
|
||||
minWidth: isMobile ? null : leftSideBarOpenByClick ? 800 : 900, margin: "auto",
|
||||
position: leftSideBarOpenByClick ? "relative" : "static",
|
||||
left: leftSideBarOpenByClick ? 120 : !leftSideBarOpenByClick ? 80 : 0,
|
||||
marginLeft: windowWidth < 1920 ? leftSideBarOpenByClick ? 160 : !leftSideBarOpenByClick ? 80 : 0 : "auto", width: "100%",
|
||||
maxWidth: Math.min(!(isLoggedIn && isLoaded) ? 1920 : leftSideBarOpenByClick ? windowWidth - 300 : windowWidth - 200, 1920),
|
||||
minWidth: isMobile ? null : (isLoggedIn && isLoaded) ? leftSideBarOpenByClick ? 800 : 900 : null, margin: "auto",
|
||||
position: (isLoggedIn && isLoaded) && leftSideBarOpenByClick ? "relative" : "static",
|
||||
left: (isLoggedIn && isLoaded) && leftSideBarOpenByClick ? 120 : (isLoggedIn && isLoaded) && !leftSideBarOpenByClick ? 80 : 0,
|
||||
marginLeft: windowWidth < 1920 ? leftSideBarOpenByClick && (isLoggedIn && isLoaded) ? 160 : (isLoggedIn && isLoaded) && !leftSideBarOpenByClick ? 80 : 0 : "auto", width: "100%",
|
||||
transition: "left 0.3s ease-in-out, min-width 0.3s ease-in-out, max-width 0.3s ease-in-out, position 0.3s ease-in-out, margin 0.3s ease-in-out, margin-left 0.3s ease"
|
||||
}}>
|
||||
{children}
|
||||
|
||||
@@ -108,7 +108,6 @@ const RunWorkflow = (defaultprops) => {
|
||||
const boxStyle = {
|
||||
color: "white",
|
||||
padding: "25px 50px 50px 50px",
|
||||
backgroundColor: theme.palette.surfaceColor,
|
||||
borderRadius: 25,
|
||||
minHeight: 500,
|
||||
}
|
||||
@@ -1116,7 +1115,7 @@ const RunWorkflow = (defaultprops) => {
|
||||
|
||||
const ExplorerUi = () => {
|
||||
return (
|
||||
<div style={{paddingTop: 50, marginTop: 50, width: 250, itemAlign: "center", textAlign: "center", margin: "auto", }}>
|
||||
<div style={{paddingTop: 50, marginTop: 50, width: 350, itemAlign: "center", textAlign: "center", margin: "auto", }}>
|
||||
|
||||
{forms !== undefined && forms !== null && forms.length > 0 ?
|
||||
<div>
|
||||
@@ -1126,9 +1125,14 @@ const RunWorkflow = (defaultprops) => {
|
||||
<FormList />
|
||||
</div>
|
||||
:
|
||||
<Typography variant="h6" style={{marginTop: 100, marginBottom: 20, }}>
|
||||
No Form Found
|
||||
</Typography>
|
||||
<div>
|
||||
<Typography variant="h4" style={{marginTop: 125, marginBottom: 25, }}>
|
||||
No Forms Found
|
||||
</Typography>
|
||||
<Typography variant="body1" color="textSecondary">
|
||||
<b>Every</b> Workflow is a form, and can be accessed by going to /forms/{`{workflow_id}`}. You can control the form by editing the workflow details in the "Forms" section.
|
||||
</Typography>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
)
|
||||
@@ -1474,7 +1478,7 @@ const RunWorkflow = (defaultprops) => {
|
||||
|
||||
{workflowQuestion !== "" ? null :
|
||||
<Typography variant="body2" color="textSecondary" align="center" style={{marginTop: 10, }} >
|
||||
Forms are in late Beta. Form submission data includes your Organization's unique ID while logged in, or a unique identifier for your browser otherwise. Your input will be automatically sanitized.
|
||||
Form submission data includes your Organization's unique ID while logged in, or a unique identifier for your browser otherwise. Your input will be automatically sanitized.
|
||||
</Typography>
|
||||
}
|
||||
</div>
|
||||
@@ -1482,7 +1486,7 @@ const RunWorkflow = (defaultprops) => {
|
||||
|
||||
// const isCorrectOrg = userdata.active_org.id === undefined || userdata.active_org.id === null || workflow.org_id === null || workflow.org_id === undefined || workflow.org_id.length === 0 || userdata.active_org.id === workflow.org_id
|
||||
const loadedCheck = isLoaded ?
|
||||
<div style={{marginTop: 30, }}>
|
||||
<div style={{paddingTop: 60, }}>
|
||||
{editWorkflowModalOpen === true ?
|
||||
<EditWorkflow
|
||||
saveWorkflow={saveWorkflow}
|
||||
@@ -1570,6 +1574,7 @@ const RunWorkflow = (defaultprops) => {
|
||||
<div style={{position: "fixed", top: 10, right: 20, }}>
|
||||
|
||||
<Button
|
||||
disabled={workflow.id === undefined || workflow.id === null}
|
||||
variant={"outlined"}
|
||||
color={"secondary"}
|
||||
style={{marginRight: 10, }}
|
||||
@@ -1582,6 +1587,7 @@ const RunWorkflow = (defaultprops) => {
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
disabled={workflow.id === undefined || workflow.id === null}
|
||||
variant={workflow.sharing === "form" ? "outlined" : "contained"}
|
||||
color={"secondary"}
|
||||
style={{marginRight: 10, }}
|
||||
@@ -1603,6 +1609,7 @@ const RunWorkflow = (defaultprops) => {
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
disabled={workflow.id === undefined || workflow.id === null}
|
||||
variant={"contained"}
|
||||
color={"primary"}
|
||||
style={{}}
|
||||
|
||||
@@ -91,7 +91,7 @@ const Search = (props) => {
|
||||
userdata={userdata}
|
||||
/>, [curTab]);
|
||||
|
||||
const MemoizedDiscordChat = useMemo(() => <DiscordChat isMobile={isMobile} />)
|
||||
const MemoizedDiscordChat = useMemo(() => <DiscordChat isMobile={isMobile} />, [curTab])
|
||||
|
||||
const useStyles = makeStyles({
|
||||
hideIndicator: {
|
||||
|
||||
@@ -1220,7 +1220,7 @@ const Usecases2 = (props) => {
|
||||
) : null
|
||||
|
||||
const data =
|
||||
<div className="content" style={{width: isMobile ? "100%": leftSideBarOpenByClick ? 1200: 1000, margin: "auto", paddingBottom: 200, textAlign: "center", paddingLeft: leftSideBarOpenByClick ? 200 : 0, transition: "padding-left 0.3s ease, width 0.3s ease"}}>
|
||||
<div className="content" style={{width: isMobile ? "100%": leftSideBarOpenByClick ? 1000: 1200, margin: "auto", paddingBottom: 200, textAlign: "center", paddingLeft: leftSideBarOpenByClick ? 200 : 0, transition: "padding-left 0.3s ease, width 0.3s ease"}}>
|
||||
|
||||
<UsecaseListComponent
|
||||
userdata={userdata}
|
||||
@@ -1241,7 +1241,7 @@ const Usecases2 = (props) => {
|
||||
|
||||
const dataWrapper =
|
||||
<Fade in={true} timeout={1250}>
|
||||
<div style={{ maxWidth: 1366, margin: "auto", }}>
|
||||
<div style={{ maxWidth: 1366, margin: "auto", zoom: 0.8, }}>
|
||||
{data}
|
||||
</div>
|
||||
</Fade>
|
||||
|
||||
+486
-488
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user