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 [actions, setActions] = useState([]);
|
||||||
const [info, setInfo] = useState({});
|
const [info, setInfo] = useState({});
|
||||||
const [serverurl, setServerUrl] = useState("");
|
const [serverurl, setServerUrl] = useState("");
|
||||||
@@ -1265,12 +1265,12 @@ const ApiExplorer = memo(({ openapi, globalUrl, userdata, HandleApiExecution, se
|
|||||||
style={{
|
style={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
flexDirection: 'row',
|
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>
|
</div>
|
||||||
);
|
);
|
||||||
@@ -1279,7 +1279,7 @@ const ApiExplorer = memo(({ openapi, globalUrl, userdata, HandleApiExecution, se
|
|||||||
export default ApiExplorer;
|
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 [apiResponse, setApiResponse] = useState({});
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
const loadAction = 10;
|
const loadAction = 10;
|
||||||
@@ -1366,7 +1366,7 @@ const ActionResponseAndRequest = memo(({ConfigurationTab, selectedAppData,action
|
|||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ActionResponse userdata={userdata} apiResponse={apiResponse} ExampleBody={ExampleBody}/>
|
<ActionResponse isLoaded={isLoaded} isLoggedIn={isLoggedIn} apiResponse={apiResponse} ExampleBody={ExampleBody}/>
|
||||||
</div>
|
</div>
|
||||||
)})
|
)})
|
||||||
|
|
||||||
@@ -1381,6 +1381,8 @@ const ActionsList = memo(({
|
|||||||
userdata,
|
userdata,
|
||||||
info,
|
info,
|
||||||
openapi,
|
openapi,
|
||||||
|
isLoggedIn,
|
||||||
|
isLoaded
|
||||||
}) => {
|
}) => {
|
||||||
|
|
||||||
const [searchQuery, setSearchQuery] = useState("");
|
const [searchQuery, setSearchQuery] = useState("");
|
||||||
@@ -1436,7 +1438,7 @@ const ActionsList = memo(({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
return (
|
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 style={{ borderBottom: '1px solid #494949', paddingTop: 10, paddingBottom: 10}}>
|
||||||
<div>
|
<div>
|
||||||
{info?.title ? (
|
{info?.title ? (
|
||||||
@@ -1487,7 +1489,7 @@ const ActionsList = memo(({
|
|||||||
marginTop: 15,
|
marginTop: 15,
|
||||||
backgroundColor: "#1a1a1a",
|
backgroundColor: "#1a1a1a",
|
||||||
overflowY: "auto",
|
overflowY: "auto",
|
||||||
height: userdata?.support ? "calc(100vh - 190px)" : "calc(100vh - 260px)",
|
height: (isLoaded && isLoggedIn) ? "calc(100vh - 190px)" : "calc(100vh - 260px)",
|
||||||
paddingRight: 5,
|
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 [height, setHeight] = useState("14vh")
|
||||||
const [responseTabIndex, setResponseTabIndex] = useState(0)
|
const [responseTabIndex, setResponseTabIndex] = useState(0)
|
||||||
const [oldResponse, setOldResponse] = useState(apiResponse)
|
const [oldResponse, setOldResponse] = useState(apiResponse)
|
||||||
@@ -2897,7 +2899,7 @@ const ActionResponse = memo(({ apiResponse, ExampleBody, userdata }) => {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ApiResponseWrapper userdata={userdata}>
|
<ApiResponseWrapper isLoggedIn={isLoggedIn} isLoaded={isLoaded}>
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
width: '100%',
|
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);
|
const { leftSideBarOpenByClick, windowWidth } = useContext(Context);
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
width: userdata?.support
|
width: (isLoggedIn && isLoaded)
|
||||||
? leftSideBarOpenByClick
|
? leftSideBarOpenByClick
|
||||||
? windowWidth >= 1920 ? "calc(100% - 630px)" : "calc(100% - 570px)"
|
? windowWidth >= 1920 ? "calc(100% - 630px)" : "calc(100% - 570px)"
|
||||||
: windowWidth >= 1920 ? "calc(100vw - 460px)": "calc(100% - 410px)"
|
: 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 (
|
return (
|
||||||
<PaddingWrapper userdata={userdata}>
|
<PaddingWrapper isLoggedIn={isLoggedIn} isLoaded={isLoaded}>
|
||||||
{children}
|
{children}
|
||||||
</PaddingWrapper>
|
</PaddingWrapper>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
|
import { useNavigate } from 'react-router';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Dialog,
|
Dialog,
|
||||||
DialogTitle,
|
DialogTitle,
|
||||||
@@ -21,17 +23,22 @@ import LaunchIcon from '@mui/icons-material/Launch';
|
|||||||
import CheckCircleIcon from '@mui/icons-material/CheckCircle';
|
import CheckCircleIcon from '@mui/icons-material/CheckCircle';
|
||||||
import { CloudDownloadOutlined } from '@mui/icons-material';
|
import { CloudDownloadOutlined } from '@mui/icons-material';
|
||||||
import { findSpecificApp } from './AppFramework';
|
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 [frameworkData, setFrameworkData] = useState({})
|
||||||
|
const [userdata, setUserdata] = useState({})
|
||||||
const [usecases, setUsecases] = useState([])
|
const [usecases, setUsecases] = useState([])
|
||||||
const [workflows, setWorkflows] = useState([])
|
const [workflows, setWorkflows] = useState([])
|
||||||
const [prevSubcase, setPrevSubcase] = useState({})
|
const [prevSubcase, setPrevSubcase] = useState({})
|
||||||
const [inputUsecase, setInputUsecase] = useState({})
|
const [inputUsecase, setInputUsecase] = useState({})
|
||||||
const [latestUsecase, setLatestUsecase] = useState([])
|
const [latestUsecase, setLatestUsecase] = useState([])
|
||||||
const [foundAppUsecase, setFoundAppUsecase] = useState({})
|
const [foundAppUsecase, setFoundAppUsecase] = useState({})
|
||||||
|
const navigate = useNavigate();
|
||||||
const parseUsecase = (subcase) => {
|
const parseUsecase = (subcase) => {
|
||||||
const srcdata = findSpecificApp(frameworkData, subcase.type)
|
const srcdata = findSpecificApp(frameworkData, subcase.type)
|
||||||
const dstdata = findSpecificApp(frameworkData, subcase.last)
|
const dstdata = findSpecificApp(frameworkData, subcase.last)
|
||||||
@@ -48,6 +55,25 @@ const AppModal = ({ open, onClose, app, userdata, globalUrl }) => {
|
|||||||
return subcase
|
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 = () => {
|
const getFramework = () => {
|
||||||
fetch(globalUrl + "/api/v1/apps/frameworkConfiguration", {
|
fetch(globalUrl + "/api/v1/apps/frameworkConfiguration", {
|
||||||
@@ -266,6 +292,89 @@ const AppModal = ({ open, onClose, app, userdata, globalUrl }) => {
|
|||||||
setFoundAppUsecase(foundSubcase);
|
setFoundAppUsecase(foundSubcase);
|
||||||
}, [latestUsecase])
|
}, [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 =
|
const isCloud =
|
||||||
window.location.host === "localhost:3002" ||
|
window.location.host === "localhost:3002" ||
|
||||||
window.location.host === "shuffler.io" || window.location.host === "localhost:3000"
|
window.location.host === "shuffler.io" || window.location.host === "localhost:3000"
|
||||||
@@ -280,7 +389,8 @@ const AppModal = ({ open, onClose, app, userdata, globalUrl }) => {
|
|||||||
newAppname = newAppname?.replaceAll("_", " ");
|
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 (
|
return (
|
||||||
@@ -294,7 +404,7 @@ const AppModal = ({ open, onClose, app, userdata, globalUrl }) => {
|
|||||||
borderRadius: 2,
|
borderRadius: 2,
|
||||||
border: "1px solid #494949",
|
border: "1px solid #494949",
|
||||||
minWidth: '440px',
|
minWidth: '440px',
|
||||||
fontFamily: "Inter",
|
fontFamily: theme?.typography?.fontFamily,
|
||||||
backgroundColor: "#212121",
|
backgroundColor: "#212121",
|
||||||
'& .MuiDialogContent-root': {
|
'& .MuiDialogContent-root': {
|
||||||
backgroundColor: "#212121",
|
backgroundColor: "#212121",
|
||||||
@@ -303,10 +413,10 @@ const AppModal = ({ open, onClose, app, userdata, globalUrl }) => {
|
|||||||
backgroundColor: "#212121",
|
backgroundColor: "#212121",
|
||||||
},
|
},
|
||||||
'& .MuiTypography-root': {
|
'& .MuiTypography-root': {
|
||||||
fontFamily: 'Inter, sans-serif',
|
fontFamily: theme?.typography?.fontFamily,
|
||||||
},
|
},
|
||||||
'& .MuiButton-root': {
|
'& .MuiButton-root': {
|
||||||
fontFamily: 'Inter, sans-serif',
|
fontFamily: theme?.typography?.fontFamily,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
@@ -320,7 +430,7 @@ const AppModal = ({ open, onClose, app, userdata, globalUrl }) => {
|
|||||||
pt: 2,
|
pt: 2,
|
||||||
pl: 3,
|
pl: 3,
|
||||||
pr: 2,
|
pr: 2,
|
||||||
fontFamily: "Inter"
|
fontFamily: theme?.typography?.fontFamily
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Typography component="div" sx={{ fontWeight: 500, color: "#F1F1F1", fontSize: "22px" }}>
|
<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 }}>
|
<DialogContent sx={{ py: 3, px: 3 }}>
|
||||||
<Box sx={{ display: 'flex', alignItems: 'space-between', justifyContent: 'space-between' }}>
|
<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
|
<img
|
||||||
alt={app?.name}
|
alt={app?.name}
|
||||||
src={app?.large_image || app?.image_url}
|
src={app?.large_image || app?.image_url}
|
||||||
@@ -364,11 +474,9 @@ const AppModal = ({ open, onClose, app, userdata, globalUrl }) => {
|
|||||||
</Typography>
|
</Typography>
|
||||||
{
|
{
|
||||||
isCloud && (
|
isCloud && (
|
||||||
<a
|
<Link
|
||||||
rel="noopener noreferrer"
|
to={"/apps/" + (app?.id || app?.objectID)}
|
||||||
href={"https://shuffler.io/apps/" + app?.id}
|
|
||||||
style={{ textDecoration: "none", color: "#f85a3e", marginTop: "-2px" }}
|
style={{ textDecoration: "none", color: "#f85a3e", marginTop: "-2px" }}
|
||||||
target="_blank"
|
|
||||||
>
|
>
|
||||||
<IconButton
|
<IconButton
|
||||||
style={{
|
style={{
|
||||||
@@ -378,7 +486,7 @@ const AppModal = ({ open, onClose, app, userdata, globalUrl }) => {
|
|||||||
>
|
>
|
||||||
<OpenInNewIcon />
|
<OpenInNewIcon />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</a>
|
</Link>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
@@ -391,23 +499,33 @@ const AppModal = ({ open, onClose, app, userdata, globalUrl }) => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div style={{ display: "flex", flexDirection: "row", justifyContent: "center", alignItems: "center", gap: 10 }}>
|
<div style={{ display: "flex", flexDirection: "row", justifyContent: "center", alignItems: "center", gap: 10 }}>
|
||||||
<Button
|
|
||||||
variant="contained"
|
{app?.activated &&
|
||||||
sx={{
|
app?.private_id !== undefined &&
|
||||||
bgcolor: '#494949',
|
app?.private_id?.length > 0 &&
|
||||||
'&:hover': { bgcolor: '#494949' },
|
app?.generated ? (
|
||||||
textTransform: 'none',
|
<Button
|
||||||
borderRadius: 1,
|
variant="contained"
|
||||||
minWidth: '45px',
|
sx={{
|
||||||
width: '45px',
|
bgcolor: '#494949',
|
||||||
height: '40px',
|
'&:hover': { bgcolor: '#494949' },
|
||||||
padding: 2,
|
textTransform: 'none',
|
||||||
color: "#fff",
|
borderRadius: 1,
|
||||||
fontFamily: "Inter"
|
minWidth: '45px',
|
||||||
}}
|
width: '45px',
|
||||||
>
|
height: '40px',
|
||||||
<CloudDownloadOutlined />
|
padding: 2,
|
||||||
</Button>
|
color: "#fff",
|
||||||
|
fontFamily: theme?.typography?.fontFamily
|
||||||
|
}}
|
||||||
|
onClick={(event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
downloadApp(app);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<CloudDownloadOutlined />
|
||||||
|
</Button>) : null}
|
||||||
<Button
|
<Button
|
||||||
variant="contained"
|
variant="contained"
|
||||||
sx={{
|
sx={{
|
||||||
@@ -419,9 +537,21 @@ const AppModal = ({ open, onClose, app, userdata, globalUrl }) => {
|
|||||||
px: 3,
|
px: 3,
|
||||||
height: '40px',
|
height: '40px',
|
||||||
color: "#fff",
|
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"}
|
{canEditApp ? "Edit" : "Fork"}
|
||||||
</Button>
|
</Button>
|
||||||
@@ -431,17 +561,17 @@ const AppModal = ({ open, onClose, app, userdata, globalUrl }) => {
|
|||||||
<div style={{
|
<div style={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
justifyContent: "space-between",
|
justifyContent: "space-between",
|
||||||
fontFamily: "Inter",
|
fontFamily: theme?.typography?.fontFamily,
|
||||||
padding: "26px 0px"
|
padding: "26px 0px"
|
||||||
}}>
|
}}>
|
||||||
<div style={{
|
<div style={{
|
||||||
textAlign: "start",
|
textAlign: "start",
|
||||||
flex: 1,
|
flex: 1,
|
||||||
}}>
|
}}>
|
||||||
<Typography
|
<Typography
|
||||||
variant="h6"
|
variant="h6"
|
||||||
sx={{
|
sx={{
|
||||||
fontFamily: 'Inter, sans-serif',
|
fontFamily: theme?.typography?.fontFamily,
|
||||||
fontSize: '24px',
|
fontSize: '24px',
|
||||||
fontWeight: 600,
|
fontWeight: 600,
|
||||||
mb: 0.3,
|
mb: 0.3,
|
||||||
@@ -450,11 +580,11 @@ const AppModal = ({ open, onClose, app, userdata, globalUrl }) => {
|
|||||||
>
|
>
|
||||||
20
|
20
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography
|
<Typography
|
||||||
variant="body2"
|
variant="body2"
|
||||||
sx={{
|
sx={{
|
||||||
color: 'rgba(255, 255, 255, 0.7)',
|
color: 'rgba(255, 255, 255, 0.7)',
|
||||||
fontFamily: 'Inter, sans-serif',
|
fontFamily: theme?.typography?.fontFamily,
|
||||||
fontSize: '14px'
|
fontSize: '14px'
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@@ -468,12 +598,12 @@ const AppModal = ({ open, onClose, app, userdata, globalUrl }) => {
|
|||||||
paddingLeft: "10px",
|
paddingLeft: "10px",
|
||||||
height: "100%",
|
height: "100%",
|
||||||
}}>
|
}}>
|
||||||
<Typography variant="h6"
|
<Typography variant="h6"
|
||||||
sx={{
|
sx={{
|
||||||
fontWeight: 600,
|
fontWeight: 600,
|
||||||
mb: 0.3,
|
mb: 0.3,
|
||||||
color: '#fff'
|
color: '#fff'
|
||||||
}}>
|
}}>
|
||||||
{Array.isArray(app?.actions) ? app.actions.length : app?.actions}
|
{Array.isArray(app?.actions) ? app.actions.length : app?.actions}
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography variant="body2" sx={{ color: 'rgba(255, 255, 255, 0.7)' }}>
|
<Typography variant="body2" sx={{ color: 'rgba(255, 255, 255, 0.7)' }}>
|
||||||
@@ -486,7 +616,7 @@ const AppModal = ({ open, onClose, app, userdata, globalUrl }) => {
|
|||||||
paddingLeft: "10px",
|
paddingLeft: "10px",
|
||||||
paddingTop: "5px"
|
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 ? (
|
app?.collection ? (
|
||||||
<>
|
<>
|
||||||
@@ -494,13 +624,25 @@ const AppModal = ({ open, onClose, app, userdata, globalUrl }) => {
|
|||||||
<Typography variant="body1" sx={{
|
<Typography variant="body1" sx={{
|
||||||
fontWeight: 500,
|
fontWeight: 500,
|
||||||
color: '#fff',
|
color: '#fff',
|
||||||
marginTop: "1px"
|
marginTop: "1px",
|
||||||
|
fontFamily: theme?.typography?.fontFamily,
|
||||||
|
fontSize: "16px"
|
||||||
}}>
|
}}>
|
||||||
app.collection
|
app.collection
|
||||||
|
|
||||||
</Typography>
|
</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>
|
</div>
|
||||||
@@ -517,7 +659,7 @@ const AppModal = ({ open, onClose, app, userdata, globalUrl }) => {
|
|||||||
width: "100%"
|
width: "100%"
|
||||||
}}>
|
}}>
|
||||||
<div style={{
|
<div style={{
|
||||||
fontFamily: "Inter",
|
fontFamily: theme?.typography?.fontFamily,
|
||||||
fontSize: "16px",
|
fontSize: "16px",
|
||||||
color: "#fff",
|
color: "#fff",
|
||||||
marginBottom: "16px",
|
marginBottom: "16px",
|
||||||
@@ -544,7 +686,7 @@ const AppModal = ({ open, onClose, app, userdata, globalUrl }) => {
|
|||||||
{
|
{
|
||||||
foundAppUsecase === undefined ? (
|
foundAppUsecase === undefined ? (
|
||||||
<Avatar sx={{ width: 32, height: 32, bgcolor: 'background.paper', border: 1, borderColor: 'divider' }}>
|
<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>
|
||||||
) : (
|
) : (
|
||||||
<Avatar
|
<Avatar
|
||||||
@@ -560,10 +702,10 @@ const AppModal = ({ open, onClose, app, userdata, globalUrl }) => {
|
|||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
foundAppUsecase === undefined ? (
|
foundAppUsecase === undefined ? (
|
||||||
<Avatar sx={{ width: 32, height: 32, bgcolor: 'background.paper', border: 1, borderColor: 'divider' }}>
|
<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>
|
||||||
) : (
|
) : (
|
||||||
<Avatar
|
<Avatar
|
||||||
@@ -586,7 +728,7 @@ const AppModal = ({ open, onClose, app, userdata, globalUrl }) => {
|
|||||||
</Box>
|
</Box>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style={{ display: "flex", justifyContent: "center", fontFamily: "Inter" }}>
|
<div style={{ display: "flex", justifyContent: "center", fontFamily: theme?.typography?.fontFamily }}>
|
||||||
<Button
|
<Button
|
||||||
variant="contained"
|
variant="contained"
|
||||||
sx={{
|
sx={{
|
||||||
@@ -599,11 +741,14 @@ const AppModal = ({ open, onClose, app, userdata, globalUrl }) => {
|
|||||||
fontSize: "14px",
|
fontSize: "14px",
|
||||||
letterSpacing: "0.5px",
|
letterSpacing: "0.5px",
|
||||||
color: "black",
|
color: "black",
|
||||||
fontFamily: "Inter",
|
fontFamily: theme?.typography?.fontFamily,
|
||||||
minWidth: '200px'
|
minWidth: '200px'
|
||||||
}}
|
}}
|
||||||
|
onClick={() => {
|
||||||
|
navigate("/usecases2")
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
Create a Usecase
|
Find a Usecase
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</DialogContent>
|
</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={{
|
style={{
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
color: "rgba(158, 158, 158, 1)",
|
color: "rgba(158, 158, 158, 1)",
|
||||||
fontFamily: "Inter",
|
fontFamily: theme?.typography?.fontFamily,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Your organization has no apps yet, select your starting apps here
|
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 ReactGA from 'react-ga4';
|
||||||
|
|
||||||
import theme from "../theme.jsx";
|
import theme from "../theme.jsx";
|
||||||
@@ -41,7 +41,8 @@ import {
|
|||||||
Delete,
|
Delete,
|
||||||
RestaurantRounded,
|
RestaurantRounded,
|
||||||
Cloud,
|
Cloud,
|
||||||
CheckCircle
|
CheckCircle,
|
||||||
|
Padding,
|
||||||
} from "@mui/icons-material";
|
} from "@mui/icons-material";
|
||||||
|
|
||||||
//import { useAlert
|
//import { useAlert
|
||||||
@@ -49,8 +50,9 @@ import { typecost, typecost_single, } from "../views/HandlePaymentNew.jsx";
|
|||||||
import BillingStats from "./BillingStats.jsx";
|
import BillingStats from "./BillingStats.jsx";
|
||||||
import { handlePayasyougo } from "../views/HandlePaymentNew.jsx"
|
import { handlePayasyougo } from "../views/HandlePaymentNew.jsx"
|
||||||
import DeleteIcon from '@mui/icons-material/Delete';
|
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 { globalUrl, userdata, serverside, billingInfo, stripeKey, selectedOrganization, handleGetOrg, clickedFromOrgTab } = props;
|
||||||
//const alert = useAlert();
|
//const alert = useAlert();
|
||||||
let navigate = useNavigate();
|
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 [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 [currentIndex, setCurrentIndex] = useState(0);
|
||||||
const [deleteAlertVerification, setDeleteAlertVerification] = useState(false);
|
const [deleteAlertVerification, setDeleteAlertVerification] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (userdata.app_execution_limit !== undefined && userdata.app_execution_usage !== undefined) {
|
if (userdata.app_execution_limit !== undefined && userdata.app_execution_usage !== undefined) {
|
||||||
const percentage = (userdata.app_execution_usage / userdata.app_execution_limit) * 100;
|
const percentage = (userdata.app_execution_usage / userdata.app_execution_limit) * 100;
|
||||||
@@ -81,18 +83,12 @@ const Billing = (props) => {
|
|||||||
}
|
}
|
||||||
}, [userdata]);
|
}, [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);
|
useEffect(() => {
|
||||||
|
if (BillingEmail !== selectedOrganization?.Billing?.Email) {
|
||||||
useState(() => {
|
setBillingEmail(selectedOrganization?.Billing?.Email);
|
||||||
// Set the billing email
|
}
|
||||||
setBillingEmail(
|
|
||||||
selectedOrganization.Billing !== undefined &&
|
|
||||||
selectedOrganization.Billing.Email !== undefined &&
|
|
||||||
selectedOrganization.Billing.Email.length > 0
|
|
||||||
? selectedOrganization.Billing.Email
|
|
||||||
: selectedOrganization.org
|
|
||||||
);
|
|
||||||
|
|
||||||
// Set and sort the alert thresholds
|
// Set and sort the alert thresholds
|
||||||
const alertThresholds = selectedOrganization.Billing !== undefined &&
|
const alertThresholds = selectedOrganization.Billing !== undefined &&
|
||||||
@@ -126,7 +122,6 @@ const Billing = (props) => {
|
|||||||
];
|
];
|
||||||
|
|
||||||
const handleGetDeals = (orgId) => {
|
const handleGetDeals = (orgId) => {
|
||||||
console.log("Get deals!");
|
|
||||||
|
|
||||||
if (orgId.length === 0) {
|
if (orgId.length === 0) {
|
||||||
toast(
|
toast(
|
||||||
@@ -178,7 +173,7 @@ const Billing = (props) => {
|
|||||||
width: 340,
|
width: 340,
|
||||||
height: 480,
|
height: 480,
|
||||||
// width: "100%",
|
// width: "100%",
|
||||||
backgroundColor: theme.palette.platformColor,
|
backgroundColor: theme.palette.backgroundColor,
|
||||||
borderRadius: theme.palette?.borderRadius * 2,
|
borderRadius: theme.palette?.borderRadius * 2,
|
||||||
border: "1px solid rgba(255,255,255,0.3)",
|
border: "1px solid rgba(255,255,255,0.3)",
|
||||||
marginRight: 10,
|
marginRight: 10,
|
||||||
@@ -384,7 +379,7 @@ const Billing = (props) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (hovered) {
|
if (hovered) {
|
||||||
newPaperstyle.backgroundColor = theme.palette.surfaceColor
|
newPaperstyle.backgroundColor = "#2b2b2b"
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleClickOpen = () => {
|
const handleClickOpen = () => {
|
||||||
@@ -412,7 +407,6 @@ const Billing = (props) => {
|
|||||||
const HandleChangeBillingEmail = (orgId) => {
|
const HandleChangeBillingEmail = (orgId) => {
|
||||||
const email = newBillingEmail;
|
const email = newBillingEmail;
|
||||||
const emailPattern = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}$/;
|
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)) {
|
if (!emailPattern.test(email)) {
|
||||||
toast("Please enter a valid email address");
|
toast("Please enter a valid email address");
|
||||||
return;
|
return;
|
||||||
@@ -445,7 +439,6 @@ const Billing = (props) => {
|
|||||||
}
|
}
|
||||||
return response.json();
|
return response.json();
|
||||||
}).then((responseJson) => {
|
}).then((responseJson) => {
|
||||||
console.log("Got org:", responseJson);
|
|
||||||
if (responseJson.success === true) {
|
if (responseJson.success === true) {
|
||||||
toast.success("Successfully updated billing email");
|
toast.success("Successfully updated billing email");
|
||||||
setBillingEmail(newBillingEmail);
|
setBillingEmail(newBillingEmail);
|
||||||
@@ -460,7 +453,7 @@ const Billing = (props) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Paper
|
<div
|
||||||
style={newPaperstyle}
|
style={newPaperstyle}
|
||||||
onMouseEnter={() => setHovered(true)}
|
onMouseEnter={() => setHovered(true)}
|
||||||
onMouseLeave={() => setHovered(false)}
|
onMouseLeave={() => setHovered(false)}
|
||||||
@@ -726,7 +719,7 @@ const Billing = (props) => {
|
|||||||
</Typography>
|
</Typography>
|
||||||
<div style={{ display: 'flex', flexDirection: 'row' }}>
|
<div style={{ display: 'flex', flexDirection: 'row' }}>
|
||||||
<Typography variant="body2" style={{ marginTop: !userdata.has_card_available ? 5 : 0 }}>
|
<Typography variant="body2" style={{ marginTop: !userdata.has_card_available ? 5 : 0 }}>
|
||||||
Billing email: {BillingEmail}
|
{BillingEmail?.length > 0 ? `Billing email: ${BillingEmail}` : null}
|
||||||
</Typography>
|
</Typography>
|
||||||
{userdata.has_card_available === true && (
|
{userdata.has_card_available === true && (
|
||||||
<Button
|
<Button
|
||||||
@@ -817,11 +810,11 @@ const Billing = (props) => {
|
|||||||
color="primary"
|
color="primary"
|
||||||
style={{
|
style={{
|
||||||
marginTop: !userdata.has_card_available ? 20 : 10,
|
marginTop: !userdata.has_card_available ? 20 : 10,
|
||||||
borderRadius: 25,
|
borderRadius: 8,
|
||||||
height: 40,
|
height: 40,
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
color: "white",
|
color: userdata.has_card_available ? "#ff8544" : "#1a1a1a",
|
||||||
backgroundColor: userdata.has_card_available ? null : "#f86743",
|
backgroundColor: userdata.has_card_available ? null : "#ff8544",
|
||||||
// backgroundImage: userdata.has_card_available ? null : "linear-gradient(to right, #f86a3e, #f34079)",
|
// backgroundImage: userdata.has_card_available ? null : "linear-gradient(to right, #f86a3e, #f34079)",
|
||||||
textTransform: "none",
|
textTransform: "none",
|
||||||
|
|
||||||
@@ -850,11 +843,11 @@ const Billing = (props) => {
|
|||||||
color="primary"
|
color="primary"
|
||||||
style={{
|
style={{
|
||||||
marginTop: 10,
|
marginTop: 10,
|
||||||
borderRadius: 25,
|
borderRadius: 8,
|
||||||
height: 40,
|
height: 40,
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
color: "white",
|
color: "#1a1a1a",
|
||||||
backgroundColor: "#f86743",
|
backgroundColor: "#ff8544",
|
||||||
textTransform: 'none'
|
textTransform: 'none'
|
||||||
}}
|
}}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
@@ -873,7 +866,6 @@ const Billing = (props) => {
|
|||||||
: null}
|
: null}
|
||||||
{showSupport ?
|
{showSupport ?
|
||||||
<Button variant="outlined" color="primary" style={{ marginTop: 20, marginBottom: 10, }} onClick={() => {
|
<Button variant="outlined" color="primary" style={{ marginTop: 20, marginBottom: 10, }} onClick={() => {
|
||||||
console.log("Support click")
|
|
||||||
if (window.drift !== undefined) {
|
if (window.drift !== undefined) {
|
||||||
//window.drift.api.startInteraction({ interactionId: 340045 })
|
//window.drift.api.startInteraction({ interactionId: 340045 })
|
||||||
window.drift.api.startInteraction({ interactionId: 340043 })
|
window.drift.api.startInteraction({ interactionId: 340043 })
|
||||||
@@ -884,7 +876,7 @@ const Billing = (props) => {
|
|||||||
Get Support
|
Get Support
|
||||||
</Button>
|
</Button>
|
||||||
: null}
|
: null}
|
||||||
</Paper>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
const ConsultationManagement = (props) => {
|
const ConsultationManagement = (props) => {
|
||||||
@@ -1035,12 +1027,12 @@ const Billing = (props) => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Paper style={{
|
<div style={{
|
||||||
padding: 20,
|
padding: 20,
|
||||||
// maxWidth: 400,
|
// maxWidth: 400,
|
||||||
width: 340,
|
width: 340,
|
||||||
height: 480,
|
height: 480,
|
||||||
backgroundColor: hovered ? "#232427" : theme.palette.platformColor,
|
backgroundColor: hovered ? "#2b2b2b" : theme.palette.backgroundColor,
|
||||||
borderRadius: theme.palette?.borderRadius * 2,
|
borderRadius: theme.palette?.borderRadius * 2,
|
||||||
border: "1px solid rgba(255,255,255,0.3)",
|
border: "1px solid rgba(255,255,255,0.3)",
|
||||||
marginRight: 10,
|
marginRight: 10,
|
||||||
@@ -1131,11 +1123,11 @@ const Billing = (props) => {
|
|||||||
color="primary"
|
color="primary"
|
||||||
style={{
|
style={{
|
||||||
marginTop: userdata.support ? 0 : 10,
|
marginTop: userdata.support ? 0 : 10,
|
||||||
borderRadius: 25,
|
borderRadius: 8,
|
||||||
height: 40,
|
height: 40,
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
color: "white",
|
color: "#1A1A1A",
|
||||||
backgroundColor: "#f86743",
|
backgroundColor: "#FF8544",
|
||||||
textTransform: 'none',
|
textTransform: 'none',
|
||||||
}}
|
}}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
@@ -1150,7 +1142,7 @@ const Billing = (props) => {
|
|||||||
>
|
>
|
||||||
Buy
|
Buy
|
||||||
</Button>
|
</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 }}>
|
<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.
|
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>
|
</Typography>
|
||||||
@@ -1158,7 +1150,7 @@ const Billing = (props) => {
|
|||||||
<Button
|
<Button
|
||||||
variant="contained"
|
variant="contained"
|
||||||
color="primary"
|
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={() => {
|
onClick={() => {
|
||||||
if (Cloud) {
|
if (Cloud) {
|
||||||
ReactGA.event({
|
ReactGA.event({
|
||||||
@@ -1186,10 +1178,10 @@ const Billing = (props) => {
|
|||||||
color="primary"
|
color="primary"
|
||||||
style={{
|
style={{
|
||||||
marginTop: userdata.support ? 5 : 10,
|
marginTop: userdata.support ? 5 : 10,
|
||||||
borderRadius: 25,
|
borderRadius: 8,
|
||||||
height: 40,
|
height: 40,
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
color: "white",
|
color: "#ff8544",
|
||||||
textTransform: 'none',
|
textTransform: 'none',
|
||||||
cursor: getProfessionalServices ? 'pointer' : 'not-allowed',
|
cursor: getProfessionalServices ? 'pointer' : 'not-allowed',
|
||||||
opacity: getProfessionalServices ? 1 : 0.6,
|
opacity: getProfessionalServices ? 1 : 0.6,
|
||||||
@@ -1259,7 +1251,7 @@ const Billing = (props) => {
|
|||||||
</Button>
|
</Button>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
</Paper >
|
</div >
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1308,13 +1300,13 @@ const Billing = (props) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Paper
|
<div
|
||||||
style={{
|
style={{
|
||||||
padding: 20,
|
padding: 20,
|
||||||
height: 480,
|
height: 480,
|
||||||
// maxWidth: 400,
|
// maxWidth: 400,
|
||||||
width: 340,
|
width: 340,
|
||||||
backgroundColor: hovered ? "#232427" : theme.palette.platformColor,
|
backgroundColor: hovered ? "#2b2b2b" : theme.palette.backgroundColor,
|
||||||
borderRadius: theme.palette?.borderRadius * 2,
|
borderRadius: theme.palette?.borderRadius * 2,
|
||||||
border: "1px solid rgba(255,255,255,0.3)",
|
border: "1px solid rgba(255,255,255,0.3)",
|
||||||
marginRight: 10,
|
marginRight: 10,
|
||||||
@@ -1370,11 +1362,12 @@ const Billing = (props) => {
|
|||||||
color="primary"
|
color="primary"
|
||||||
style={{
|
style={{
|
||||||
marginTop: 10,
|
marginTop: 10,
|
||||||
borderRadius: 25,
|
borderRadius: 8,
|
||||||
height: 40,
|
height: 40,
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
color: "white",
|
color: "#1A1A1A",
|
||||||
textTransform: 'none'
|
textTransform: 'none',
|
||||||
|
backgroundColor: "#FF8544"
|
||||||
}}
|
}}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (Cloud) {
|
if (Cloud) {
|
||||||
@@ -1397,10 +1390,12 @@ const Billing = (props) => {
|
|||||||
color="primary"
|
color="primary"
|
||||||
style={{
|
style={{
|
||||||
marginTop: 10,
|
marginTop: 10,
|
||||||
borderRadius: 25,
|
borderRadius: 8,
|
||||||
height: 40,
|
height: 40,
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
textTransform: 'none'
|
textTransform: 'none',
|
||||||
|
color: "#FF8544",
|
||||||
|
backgroundColor: "#1a1a1a",
|
||||||
}}
|
}}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (Cloud) {
|
if (Cloud) {
|
||||||
@@ -1425,6 +1420,7 @@ const Billing = (props) => {
|
|||||||
style: {
|
style: {
|
||||||
width: 500,
|
width: 500,
|
||||||
margin: 0,
|
margin: 0,
|
||||||
|
backgroundColor: "rgb(26, 26, 26)",
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@@ -1464,7 +1460,7 @@ const Billing = (props) => {
|
|||||||
<Button
|
<Button
|
||||||
variant="contained"
|
variant="contained"
|
||||||
color="primary"
|
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}
|
onClick={handlePrivateTraining}
|
||||||
>
|
>
|
||||||
Submit Request
|
Submit Request
|
||||||
@@ -1472,7 +1468,7 @@ const Billing = (props) => {
|
|||||||
</DialogContent>
|
</DialogContent>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
</div>
|
</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 (
|
return (
|
||||||
<div style={{ width: clickedFromOrgTab ? 1030 : "auto", padding: 27, backgroundColor: '#212121', borderRadius: '16px', }}>
|
<Wrapper clickedFromOrgTab={clickedFromOrgTab}>
|
||||||
{addDealModal}
|
<div style={{ height: "100%", width: "100%"}}>
|
||||||
|
<div style={{ width: "100%",}}>
|
||||||
|
{addDealModal}
|
||||||
{clickedFromOrgTab ?
|
{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 }}>
|
<Typography variant="h4" style={{ marginTop: 20, marginBottom: 10 }}>
|
||||||
Billing & Licensing
|
Billing & Licensing
|
||||||
</Typography>}
|
</Typography>}
|
||||||
@@ -1942,11 +1940,11 @@ const Billing = (props) => {
|
|||||||
|
|
||||||
{isChildOrg ?
|
{isChildOrg ?
|
||||||
<Typography variant="h6" style={{ marginBottom: 50, }}>
|
<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>
|
</Typography>
|
||||||
: null}
|
: 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 :
|
{isCloud && billingInfo.subscription !== undefined && billingInfo.subscription !== null ? isChildOrg ? null :
|
||||||
<SubscriptionObject
|
<SubscriptionObject
|
||||||
index={0}
|
index={0}
|
||||||
@@ -2258,10 +2256,10 @@ const Billing = (props) => {
|
|||||||
) : null*/}
|
) : null*/}
|
||||||
{!isChildOrg && isCloud && (
|
{!isChildOrg && isCloud && (
|
||||||
<div style={{ display: 'flex', flexDirection: 'column', marginTop: 10 }}>
|
<div style={{ display: 'flex', flexDirection: 'column', marginTop: 10 }}>
|
||||||
<Typography style={{ marginBottom: 5 }} variant="h4">
|
<Typography style={{ marginBottom: 5, fontSize: 24, fontWeight: "bold" }}>
|
||||||
Professional Services
|
Professional Services
|
||||||
</Typography>
|
</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.
|
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>
|
</Typography>
|
||||||
<div style={{ display: 'flex', flexDirection: 'row', marginTop: 5 }}>
|
<div style={{ display: 'flex', flexDirection: 'row', marginTop: 5 }}>
|
||||||
@@ -2280,15 +2278,14 @@ const Billing = (props) => {
|
|||||||
)}
|
)}
|
||||||
<div style={{ marginTop: isCloud && 40, marginLeft: 10 }}>
|
<div style={{ marginTop: isCloud && 40, marginLeft: 10 }}>
|
||||||
<Typography
|
<Typography
|
||||||
style={{ marginBottom: 5 }}
|
style={{ marginBottom: 5, fontSize: 24, fontWeight: "bold" }}
|
||||||
variant="h4"
|
|
||||||
>
|
>
|
||||||
Manage Billing
|
Manage Billing
|
||||||
</Typography>
|
</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.
|
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>
|
||||||
<Typography variant="body1">Current Usage:</Typography>
|
<Typography style={{fontSize: 18, marginTop: 10}}>Current Usage:</Typography>
|
||||||
<LinearProgress
|
<LinearProgress
|
||||||
variant="determinate"
|
variant="determinate"
|
||||||
value={currentAppRunsInPercentage}
|
value={currentAppRunsInPercentage}
|
||||||
@@ -2300,15 +2297,15 @@ const Billing = (props) => {
|
|||||||
marginBottom: 10,
|
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.
|
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>
|
</Typography>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<Typography variant="body1" style={{ marginTop: 20 }}>
|
<Typography style={{ marginTop: 20, fontSize: 18 }}>
|
||||||
Set email alert thresholds for app runs
|
Set email alert thresholds for app runs
|
||||||
</Typography>
|
</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
|
You will be notified by email when you reach the
|
||||||
{currentIndex !== -1
|
{currentIndex !== -1
|
||||||
? " " + getSafeValue(alertThresholds[currentIndex].percentage) + '%' + " "
|
? " " + getSafeValue(alertThresholds[currentIndex].percentage) + '%' + " "
|
||||||
@@ -2320,8 +2317,8 @@ const Billing = (props) => {
|
|||||||
: " " + 0 + " "}
|
: " " + 0 + " "}
|
||||||
app runs.
|
app runs.
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography variant="body1" color="textSecondary" style={{ marginTop: 10 }}>
|
<Typography color="textSecondary" style={{ fontSize: 16 }}>
|
||||||
Please note: Once your app runs reach the set alert threshold, all admins in the organization will receive an email notification.
|
<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>
|
</Typography>
|
||||||
<div style={{ marginTop: 15 }}>
|
<div style={{ marginTop: 15 }}>
|
||||||
{alertThresholds.map((threshold, index) => (
|
{alertThresholds.map((threshold, index) => (
|
||||||
@@ -2329,7 +2326,7 @@ const Billing = (props) => {
|
|||||||
<TextField
|
<TextField
|
||||||
style={{
|
style={{
|
||||||
marginTop: 10,
|
marginTop: 10,
|
||||||
backgroundColor: theme.palette.inputColor,
|
backgroundColor: "#212121",
|
||||||
width: 250,
|
width: 250,
|
||||||
}}
|
}}
|
||||||
InputProps={{
|
InputProps={{
|
||||||
@@ -2354,7 +2351,7 @@ const Billing = (props) => {
|
|||||||
<TextField
|
<TextField
|
||||||
style={{
|
style={{
|
||||||
marginTop: 10,
|
marginTop: 10,
|
||||||
backgroundColor: theme.palette.inputColor,
|
backgroundColor: "#212121",
|
||||||
width: 250,
|
width: 250,
|
||||||
marginLeft: 15,
|
marginLeft: 15,
|
||||||
}}
|
}}
|
||||||
@@ -2421,11 +2418,11 @@ const Billing = (props) => {
|
|||||||
Save
|
Save
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div style={{ marginTop: 40, display: 'flex', flexDirection: 'column' }}>
|
<div style={{ marginTop: 40, display: 'flex', flexDirection: 'column' }}>
|
||||||
<Typography
|
<Typography
|
||||||
style={{ marginTop: 10, marginLeft: 10, marginBottom: 5 }}
|
style={{ marginTop: 10, marginLeft: 10, marginBottom: 5, fontSize: 24, fontWeight: "bold" }}
|
||||||
variant="h4"
|
|
||||||
>
|
>
|
||||||
Utilization & Stats
|
Utilization & Stats
|
||||||
</Typography>
|
</Typography>
|
||||||
@@ -2436,9 +2433,41 @@ const Billing = (props) => {
|
|||||||
globalUrl={globalUrl}
|
globalUrl={globalUrl}
|
||||||
selectedOrganization={selectedOrganization}
|
selectedOrganization={selectedOrganization}
|
||||||
userdata={userdata}
|
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 theme from '../theme.jsx';
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
@@ -37,6 +37,7 @@ import {
|
|||||||
} from 'reaviz';
|
} from 'reaviz';
|
||||||
|
|
||||||
import { typecost, typecost_single, } from "../views/HandlePaymentNew.jsx";
|
import { typecost, typecost_single, } from "../views/HandlePaymentNew.jsx";
|
||||||
|
import { Context } from '../context/ContextApi.jsx';
|
||||||
|
|
||||||
const LineChartWrapper = ({keys, inputname, height, width}) => {
|
const LineChartWrapper = ({keys, inputname, height, width}) => {
|
||||||
const [hovered, setHovered] = useState("");
|
const [hovered, setHovered] = useState("");
|
||||||
@@ -82,8 +83,8 @@ const AppStats = (defaultprops) => {
|
|||||||
const [workflows, setWorkflows] = useState(inputWorkflows === undefined ? [] : inputWorkflows)
|
const [workflows, setWorkflows] = useState(inputWorkflows === undefined ? [] : inputWorkflows)
|
||||||
const [resultRows, setResultRows] = useState([])
|
const [resultRows, setResultRows] = useState([])
|
||||||
const [resultLoading, setResultLoading] = useState(true)
|
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(() => {
|
useEffect(() => {
|
||||||
if (workflows === undefined || workflows === null || workflows.length === 0) {
|
if (workflows === undefined || workflows === null || workflows.length === 0) {
|
||||||
@@ -92,7 +93,6 @@ const AppStats = (defaultprops) => {
|
|||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const getWorkflowStats = async (workflow, startTime, endTime) => {
|
const getWorkflowStats = async (workflow, startTime, endTime) => {
|
||||||
if (!userdata.support) {
|
if (!userdata.support) {
|
||||||
return workflow
|
return workflow
|
||||||
@@ -162,8 +162,6 @@ const AppStats = (defaultprops) => {
|
|||||||
|
|
||||||
const loadWorkflowStats = (foundWorkflows, startTime, endTime) => {
|
const loadWorkflowStats = (foundWorkflows, startTime, endTime) => {
|
||||||
if (!userdata.support) {
|
if (!userdata.support) {
|
||||||
console.log("Not support")
|
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -488,8 +486,13 @@ const AppStats = (defaultprops) => {
|
|||||||
setApprunCosts(appcostRuns)
|
setApprunCosts(appcostRuns)
|
||||||
}
|
}
|
||||||
|
|
||||||
const getStats = () => {
|
const getStats = (orgid) => {
|
||||||
fetch(`${globalUrl}/api/v1/orgs/${selectedOrganization.id}/stats`, {
|
|
||||||
|
if (orgid === undefined || orgid === null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fetch(`${globalUrl}/api/v1/orgs/${orgid}/stats`, {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
@@ -519,8 +522,10 @@ const AppStats = (defaultprops) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
getStats()
|
if(selectedOrganization?.id?.length > 0) {
|
||||||
}, [])
|
getStats(selectedOrganization.id)
|
||||||
|
}
|
||||||
|
}, [selectedOrganization])
|
||||||
|
|
||||||
const paperStyle = {
|
const paperStyle = {
|
||||||
textAlign: "center",
|
textAlign: "center",
|
||||||
@@ -639,7 +644,7 @@ const AppStats = (defaultprops) => {
|
|||||||
|
|
||||||
const data = (
|
const data = (
|
||||||
<div className="content" style={{width: "100%", margin: "auto", }}>
|
<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
|
All shown statistics are gathered from <a
|
||||||
href={`${globalUrl}/api/v1/orgs/${selectedOrganization.id}/stats`}
|
href={`${globalUrl}/api/v1/orgs/${selectedOrganization.id}/stats`}
|
||||||
target="_blank"
|
target="_blank"
|
||||||
@@ -722,6 +727,40 @@ const AppStats = (defaultprops) => {
|
|||||||
</div>
|
</div>
|
||||||
: null}
|
: 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, }}>
|
<LocalizationProvider dateAdapter={AdapterDayjs} style={{flex: 1, }}>
|
||||||
<div style={{display: "flex", flexDirection: "column", }}>
|
<div style={{display: "flex", flexDirection: "column", }}>
|
||||||
<DateTimePicker
|
<DateTimePicker
|
||||||
@@ -754,6 +793,8 @@ const AppStats = (defaultprops) => {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</LocalizationProvider>
|
</LocalizationProvider>
|
||||||
|
)}
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect, useContext } from "react";
|
||||||
import ReactGA from 'react-ga4';
|
import ReactGA from 'react-ga4';
|
||||||
import theme from "../theme.jsx";
|
import theme from "../theme.jsx";
|
||||||
import { ToastContainer, toast } from "react-toastify"
|
import { ToastContainer, toast } from "react-toastify"
|
||||||
@@ -21,6 +21,7 @@ import {
|
|||||||
red,
|
red,
|
||||||
green,
|
green,
|
||||||
} from "../views/AngularWorkflow.jsx"
|
} from "../views/AngularWorkflow.jsx"
|
||||||
|
import { Context } from "../context/ContextApi.jsx";
|
||||||
|
|
||||||
//import { useAlert
|
//import { useAlert
|
||||||
|
|
||||||
@@ -30,7 +31,8 @@ const Branding = (props) => {
|
|||||||
const [publishingInfo, setPublishingInfo] = useState("");
|
const [publishingInfo, setPublishingInfo] = useState("");
|
||||||
const [publishRequirements, setPublishRequirements] = useState([])
|
const [publishRequirements, setPublishRequirements] = useState([])
|
||||||
|
|
||||||
|
const { leftSideBarOpenByClick } = useContext(Context)
|
||||||
|
|
||||||
const handleEditOrg = (joinStatus) => {
|
const handleEditOrg = (joinStatus) => {
|
||||||
const data = {
|
const data = {
|
||||||
"org_id": selectedOrganization.id,
|
"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 leadinfo = selectedOrganization.lead_info === undefined || selectedOrganization.lead_info === null || selectedOrganization.lead_info === "" ? "" : JSON.stringify(selectedOrganization.lead_info)
|
||||||
const isPartner = leadinfo.includes("partner")
|
const isPartner = leadinfo.includes("partner")
|
||||||
|
|
||||||
console.log("LEADINFO: ", leadinfo)
|
|
||||||
|
|
||||||
console.log("SELECTEDORGANIZATION: ", selectedOrganization)
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{ width: clickedFromOrgTab? 1030: "auto", padding: 27, height: "auto", backgroundColor: '#212121', borderRadius: '16px', }}>
|
<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', }}>
|
||||||
<h2 style={{marginTop: clickedFromOrgTab ?0:null,}}>
|
<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
|
Partner Status & Branding
|
||||||
</h2>
|
</Typography>
|
||||||
<Typography variant="body1" color="textSecondary" style={{ marginTop: 20, marginBottom: 10 }}>
|
<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.
|
You can customize your organization's branding by uploading a logo, changing the color scheme and a lot more.
|
||||||
</Typography>
|
</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, }} />}
|
{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>
|
</Typography>
|
||||||
|
|
||||||
<a href="https://shuffler.io/partners" target="_blank" style={{ textDecoration: "none", }}>
|
<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, }} />}
|
{!isPartner ? <CheckCircleIcon style={{color: red, }} /> : <CheckCircleIcon style={{color: green, }} />}
|
||||||
<Tooltip title="Official Partner Program (manual verification)" placement="top" arrow>
|
<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>
|
</Tooltip>
|
||||||
</Typography>
|
</Typography>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<a href={`/partners/${selectedOrganization.creator_id}/edit`} target="_blank">
|
{!isPublished ? (
|
||||||
<Button disabled={isPublished} variant="contained" style={{ marginTop: 20, marginBottom: 10, }} onClick={() => {
|
<a
|
||||||
}}>
|
href={`/partners/${selectedOrganization.creator_id}/edit`}
|
||||||
Modify Public Partner Details
|
target="_blank"
|
||||||
</Button>
|
style={{ textDecoration: "none" }} // Optional: remove underline
|
||||||
</a>
|
>
|
||||||
|
<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, }} />
|
<Divider style={{marginTop: 50, marginBottom: 50, }} />
|
||||||
<h2>
|
<Typography style={{fontSize: 24, fontWeight: "bold"}}>
|
||||||
Partner Program
|
Partner Program
|
||||||
</h2>
|
</Typography>
|
||||||
<div style={{ display: "flex", width: 900, }}>
|
<div style={{ display: "flex", width: 900, marginTop: 10}}>
|
||||||
<div>
|
<div>
|
||||||
<span>
|
<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>
|
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>
|
</Typography>
|
||||||
{selectedOrganization.creator_id == "" ?
|
{selectedOrganization.creator_id == "" ?
|
||||||
@@ -167,9 +194,8 @@ const Branding = (props) => {
|
|||||||
null
|
null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
<Button
|
<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"}
|
variant={selectedOrganization.creator_id == "" ? "contained" : "outlined"}
|
||||||
color={selectedOrganization.creator_id == "" ? "primary" : "secondary"}
|
color={selectedOrganization.creator_id == "" ? "primary" : "secondary"}
|
||||||
disabled={!isOrganizationReady()}
|
disabled={!isOrganizationReady()}
|
||||||
@@ -195,6 +221,8 @@ const Branding = (props) => {
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</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 theme from "../theme.jsx";
|
||||||
import { toast } from 'react-toastify';
|
import { toast } from 'react-toastify';
|
||||||
import ReactJson from "react-json-view-ssr";
|
import ReactJson from "react-json-view-ssr";
|
||||||
@@ -19,6 +19,7 @@ import {
|
|||||||
Dialog,
|
Dialog,
|
||||||
DialogTitle,
|
DialogTitle,
|
||||||
DialogActions,
|
DialogActions,
|
||||||
|
Skeleton,
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@@ -47,6 +48,7 @@ import {
|
|||||||
VisibilityOff as VisibilityOffIcon,
|
VisibilityOff as VisibilityOffIcon,
|
||||||
} from "@mui/icons-material";
|
} from "@mui/icons-material";
|
||||||
import { validateJson, } from "../views/Workflows.jsx";
|
import { validateJson, } from "../views/Workflows.jsx";
|
||||||
|
import { Context } from "../context/ContextApi.jsx";
|
||||||
|
|
||||||
const scrollStyle1 = {
|
const scrollStyle1 = {
|
||||||
height: 100,
|
height: 100,
|
||||||
@@ -65,7 +67,7 @@ const scrollStyle2 = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const CacheView = (props) => {
|
const CacheView = memo((props) => {
|
||||||
const { globalUrl, userdata, serverside, orgId, isSelectedDataStore } = props;
|
const { globalUrl, userdata, serverside, orgId, isSelectedDataStore } = props;
|
||||||
const [orgCache, setOrgCache] = React.useState("");
|
const [orgCache, setOrgCache] = React.useState("");
|
||||||
const [listCache, setListCache] = React.useState([]);
|
const [listCache, setListCache] = React.useState([]);
|
||||||
@@ -78,11 +80,13 @@ const CacheView = (props) => {
|
|||||||
const [cacheCursor, setCacheCursor] = React.useState("");
|
const [cacheCursor, setCacheCursor] = React.useState("");
|
||||||
const [dataValue, setDataValue] = React.useState({});
|
const [dataValue, setDataValue] = React.useState({});
|
||||||
const [editCache, setEditCache] = React.useState(false);
|
const [editCache, setEditCache] = React.useState(false);
|
||||||
|
const [cachedLoaded, setCachedLoaded] = React.useState(false);
|
||||||
const [show, setShow] = useState({});
|
const [show, setShow] = useState({});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
listOrgCache(orgId);
|
if(orgId?.length >0){
|
||||||
}, []);
|
listOrgCache(orgId);
|
||||||
|
}
|
||||||
|
}, [orgId]);
|
||||||
|
|
||||||
const listOrgCache = (orgId) => {
|
const listOrgCache = (orgId) => {
|
||||||
fetch(globalUrl + `/api/v1/orgs/${orgId}/list_cache`, {
|
fetch(globalUrl + `/api/v1/orgs/${orgId}/list_cache`, {
|
||||||
@@ -104,6 +108,7 @@ const CacheView = (props) => {
|
|||||||
.then((responseJson) => {
|
.then((responseJson) => {
|
||||||
if (responseJson.success === true) {
|
if (responseJson.success === true) {
|
||||||
setListCache(responseJson.keys);
|
setListCache(responseJson.keys);
|
||||||
|
setCachedLoaded(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (responseJson.cursor !== undefined && responseJson.cursor !== null && responseJson.cursor !== "") {
|
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 = (
|
const modalView = (
|
||||||
// console.log("key:", dataValue.key),
|
// console.log("key:", dataValue.key),
|
||||||
//console.log("value:",dataValue.value),
|
//console.log("value:",dataValue.value),
|
||||||
@@ -241,11 +274,23 @@ const CacheView = (props) => {
|
|||||||
setModalOpen(false);
|
setModalOpen(false);
|
||||||
}}
|
}}
|
||||||
PaperProps={{
|
PaperProps={{
|
||||||
style: {
|
sx: {
|
||||||
backgroundColor: theme.palette.surfaceColor,
|
borderRadius: theme?.palette?.DialogStyle?.borderRadius,
|
||||||
color: "white",
|
border: theme?.palette?.DialogStyle?.border,
|
||||||
minWidth: "800px",
|
minWidth: "800px",
|
||||||
minHeight: "320px",
|
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" }
|
{ editCache ? "Edit Cache" : "Add Cache" }
|
||||||
</span>
|
</span>
|
||||||
</DialogTitle>
|
</DialogTitle>
|
||||||
<div style={{ paddingLeft: "30px", paddingRight: '30px' }}>
|
<div style={{ paddingLeft: "30px", paddingRight: '30px', backgroundColor: "#212121", }}>
|
||||||
Key
|
Key
|
||||||
<TextField
|
<TextField
|
||||||
color="primary"
|
color="primary"
|
||||||
@@ -278,7 +323,7 @@ const CacheView = (props) => {
|
|||||||
onChange={(e) => setKey(e.target.value)}
|
onChange={(e) => setKey(e.target.value)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div style={{ paddingLeft: 30, paddingRight: 30 }}>
|
<div style={{ paddingLeft: 30, paddingRight: 30, backgroundColor: "#212121" }}>
|
||||||
<div style={{display: "flex", }}>
|
<div style={{display: "flex", }}>
|
||||||
<Typography style={{marginTop: 25, marginBottom: 0, flex: 20, }}>
|
<Typography style={{marginTop: 25, marginBottom: 0, flex: 20, }}>
|
||||||
Value - ({isValidJson.valid === true ? "Valid" : "Invalid"} JSON)
|
Value - ({isValidJson.valid === true ? "Valid" : "Invalid"} JSON)
|
||||||
@@ -320,7 +365,7 @@ const CacheView = (props) => {
|
|||||||
</div>
|
</div>
|
||||||
<DialogActions style={{ paddingLeft: "30px", paddingRight: '30px' }}>
|
<DialogActions style={{ paddingLeft: "30px", paddingRight: '30px' }}>
|
||||||
<Button
|
<Button
|
||||||
style={{ borderRadius: "0px" }}
|
style={{ borderRadius: "2px", fontSize: 16, color: "#ff8544", textTransform:"none" }}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setModalOpen(false)
|
setModalOpen(false)
|
||||||
setValue("")
|
setValue("")
|
||||||
@@ -332,7 +377,7 @@ const CacheView = (props) => {
|
|||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
variant="contained"
|
variant="contained"
|
||||||
style={{ borderRadius: "0px" }}
|
style={{ borderRadius: "2px", backgroundColor: "#ff8544",color: "#1a1a1a", textTransform:"none" }}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
{editCache ? editOrgCache(orgId) : addOrgCache(orgId)}
|
{editCache ? editOrgCache(orgId) : addOrgCache(orgId)}
|
||||||
|
|
||||||
@@ -348,10 +393,11 @@ const CacheView = (props) => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<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" }}>
|
||||||
<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, }}>
|
|
||||||
{modalView}
|
{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>
|
<h2 style={{ display: isSelectedDataStore?null: "inline" }}>Shuffle Datastore</h2>
|
||||||
<span style={{ marginLeft: isSelectedDataStore?null:25, color:isSelectedDataStore?"#9E9E9E":null}}>
|
<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.
|
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>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<Button
|
<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"
|
variant="contained"
|
||||||
color="primary"
|
color="primary"
|
||||||
onClick={() =>{
|
onClick={() =>{
|
||||||
@@ -379,7 +425,7 @@ const CacheView = (props) => {
|
|||||||
Add Cache
|
Add Cache
|
||||||
</Button>
|
</Button>
|
||||||
<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"
|
variant="contained"
|
||||||
color="primary"
|
color="primary"
|
||||||
onClick={() => listOrgCache(orgId)}
|
onClick={() => listOrgCache(orgId)}
|
||||||
@@ -392,28 +438,79 @@ const CacheView = (props) => {
|
|||||||
marginBottom: 20,
|
marginBottom: 20,
|
||||||
}}
|
}}
|
||||||
/>}
|
/>}
|
||||||
<List style={{borderRadius: isSelectedDataStore?8:null, border:isSelectedDataStore?"1px solid #494949":null, marginTop:isSelectedDataStore?24:null}}>
|
<div
|
||||||
<ListItem style={{width: isSelectedDataStore?"100%":null, borderBottom:isSelectedDataStore?"1px solid #494949":null}}>
|
style={{
|
||||||
<ListItemText
|
borderRadius: 8,
|
||||||
primary="Key"
|
marginTop: 24,
|
||||||
style={{ minWidth: isSelectedDataStore?200:250, maxWidth: isSelectedDataStore?200:250, }}
|
border: "1px solid #494949",
|
||||||
/>
|
width: "100%",
|
||||||
<ListItemText
|
overflowX: "auto",
|
||||||
primary="Value"
|
paddingBottom: 0,
|
||||||
style={{ minWidth: isSelectedDataStore?300:400, maxWidth: isSelectedDataStore?300:400, overflowX: "auto", overflowY: "hidden", }}
|
}}
|
||||||
/>
|
>
|
||||||
<ListItemText
|
<List
|
||||||
primary="Actions"
|
style={{
|
||||||
style={{ minWidth: 150, maxWidth: 150, marginLeft: isSelectedDataStore?80:null,}}
|
borderRadius: 8,
|
||||||
/>
|
paddingBottom: 0,
|
||||||
<ListItemText
|
tableLayout: "auto",
|
||||||
style={{textAlign:isSelectedDataStore?"center":null}}
|
display: "table",
|
||||||
primary="Updated"
|
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>
|
</ListItem>
|
||||||
{listCache === undefined || listCache === null
|
{cachedLoaded === false
|
||||||
? null
|
? [...Array(6)].map((_, rowIndex) => (
|
||||||
: listCache.map((data, index) => {
|
<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";
|
var bgColor = isSelectedDataStore? "#212121":"#27292d";
|
||||||
if (index % 2 === 0) {
|
if (index % 2 === 0) {
|
||||||
bgColor = isSelectedDataStore? "#1A1A1A":"#1f2023";
|
bgColor = isSelectedDataStore? "#1A1A1A":"#1f2023";
|
||||||
@@ -421,49 +518,61 @@ const CacheView = (props) => {
|
|||||||
|
|
||||||
const validate = validateJson(data.value);
|
const validate = validateJson(data.value);
|
||||||
return (
|
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
|
<ListItemText
|
||||||
style={{
|
style={{
|
||||||
maxWidth: 200,
|
display: "table-cell",
|
||||||
minWidth: 200,
|
|
||||||
overflow: "hidden",
|
overflow: "hidden",
|
||||||
|
padding: 8,
|
||||||
|
verticalAlign: "middle",
|
||||||
}}
|
}}
|
||||||
primary={data.key}
|
primary={data.key}
|
||||||
/>
|
/>
|
||||||
<ListItemText
|
<ListItemText
|
||||||
style={{
|
style={{
|
||||||
minWidth: 300,
|
display: "table-cell",
|
||||||
maxWidth: 300,
|
overflowY: "auto",
|
||||||
// height:200,
|
overflowX: "auto",
|
||||||
overflowX: "hidden",
|
border: "1px solid rgba(255,255,255,0.7)",
|
||||||
|
borderRadius: 6,
|
||||||
|
backgroundColor: "#151515",
|
||||||
|
maxHeight: 300,
|
||||||
|
verticalAlign: "middle",
|
||||||
}}
|
}}
|
||||||
primary={validate.valid ?
|
primary={validate.valid ?
|
||||||
<ReactJson
|
<ReactJson
|
||||||
src={validate.result}
|
src={validate.result}
|
||||||
theme={theme.palette.jsonTheme}
|
theme={theme.palette.jsonTheme}
|
||||||
style={theme.palette.reactJsonStyle}
|
style={{
|
||||||
collapsed={true}
|
padding: 5,
|
||||||
enableClipboard={(copy) => {
|
maxHeight: 300,
|
||||||
//handleReactJsonClipboard(copy);
|
overflowY: "auto",
|
||||||
}}
|
}}
|
||||||
displayDataTypes={false}
|
collapsed={true}
|
||||||
onSelect={(select) => {
|
enableClipboard={(copy) => {
|
||||||
//HandleJsonCopy(showResult, select, data.action.label);
|
// handleReactJsonClipboard(copy);
|
||||||
//console.log("SELECTED!: ", select);
|
}}
|
||||||
}}
|
collapseStringsAfterLength={theme.palette.jsonCollapseStringsAfterLength}
|
||||||
name={"value"}
|
iconStyle={theme.palette.jsonIconStyle}
|
||||||
/>
|
displayDataTypes={false}
|
||||||
|
onSelect={(select) => {
|
||||||
|
// HandleJsonCopy(showResult, select, data.action.label);
|
||||||
|
console.log("SELECTED!: ", select);
|
||||||
|
}}
|
||||||
|
name={"value"}
|
||||||
|
/>
|
||||||
:
|
:
|
||||||
data.value
|
data.value
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<ListItemText
|
<ListItemText
|
||||||
style={{
|
style={{
|
||||||
maxWidth: 200,
|
display: "table-cell",
|
||||||
minWidth: 200,
|
verticalAlign: "middle",
|
||||||
marginLeft: 50,
|
padding: 8
|
||||||
}}
|
}}
|
||||||
primary=<span style={{ display: "inline" }}>
|
primary={(
|
||||||
|
<span style={{ display: "inline" }}>
|
||||||
<Tooltip
|
<Tooltip
|
||||||
title="Edit item"
|
title="Edit item"
|
||||||
style={{}}
|
style={{}}
|
||||||
@@ -482,9 +591,7 @@ const CacheView = (props) => {
|
|||||||
setModalOpen(true)
|
setModalOpen(true)
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<EditIcon
|
<img src="/icons/editIcon.svg" alt="edit" />
|
||||||
style={{ color: "white" }}
|
|
||||||
/>
|
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</span>
|
</span>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
@@ -508,7 +615,6 @@ const CacheView = (props) => {
|
|||||||
</Tooltip>
|
</Tooltip>
|
||||||
<Tooltip
|
<Tooltip
|
||||||
title={"Delete item"}
|
title={"Delete item"}
|
||||||
style={{ marginLeft: 25, }}
|
|
||||||
aria-label={"Delete"}
|
aria-label={"Delete"}
|
||||||
>
|
>
|
||||||
<span>
|
<span>
|
||||||
@@ -519,18 +625,18 @@ const CacheView = (props) => {
|
|||||||
//deleteFile(orgId);
|
//deleteFile(orgId);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<DeleteIcon
|
<img src="/icons/deleteIcon.svg" alt="delete" />
|
||||||
style={{ color: "white" }}
|
|
||||||
/>
|
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</span>
|
</span>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</span>
|
</span>
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
<ListItemText
|
<ListItemText
|
||||||
style={{
|
style={{
|
||||||
maxWidth: 225,
|
display: "table-cell",
|
||||||
minWidth: 225,
|
verticalAlign: "middle",
|
||||||
|
padding: 8
|
||||||
}}
|
}}
|
||||||
primary={new Date(data.edited * 1000).toISOString()}
|
primary={new Date(data.edited * 1000).toISOString()}
|
||||||
/>
|
/>
|
||||||
@@ -538,8 +644,11 @@ const CacheView = (props) => {
|
|||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</List>
|
</List>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
);
|
);
|
||||||
}
|
});
|
||||||
export default CacheView;
|
|
||||||
|
export default memo(CacheView);
|
||||||
|
|||||||
@@ -1149,7 +1149,7 @@ const EditWorkflow = (props) => {
|
|||||||
</div>
|
</div>
|
||||||
: null}
|
: null}
|
||||||
|
|
||||||
{/*!isEditing ? <>
|
{!isEditing ? <>
|
||||||
<div style={{ marginTop: 20, }}>
|
<div style={{ marginTop: 20, }}>
|
||||||
<FormControlLabel
|
<FormControlLabel
|
||||||
control={<Checkbox />}
|
control={<Checkbox />}
|
||||||
@@ -1164,7 +1164,7 @@ const EditWorkflow = (props) => {
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</> : null*/}
|
</> : null}
|
||||||
|
|
||||||
<Tooltip color="primary" title={"Add more details"} placement="top">
|
<Tooltip color="primary" title={"Add more details"} placement="top">
|
||||||
<Button
|
<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 { toast } from 'react-toastify';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@@ -21,6 +21,7 @@ import {
|
|||||||
DialogContent,
|
DialogContent,
|
||||||
DialogActions,
|
DialogActions,
|
||||||
Typography,
|
Typography,
|
||||||
|
Skeleton,
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@@ -39,11 +40,13 @@ import {
|
|||||||
import Dropzone from "../components/Dropzone.jsx";
|
import Dropzone from "../components/Dropzone.jsx";
|
||||||
import ShuffleCodeEditor from "../components/ShuffleCodeEditor1.jsx";
|
import ShuffleCodeEditor from "../components/ShuffleCodeEditor1.jsx";
|
||||||
import theme from "../theme.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 { globalUrl, userdata, serverside, selectedOrganization, isCloud,isSelectedFiles } = props;
|
||||||
|
|
||||||
const [files, setFiles] = React.useState([]);
|
const [files, setFiles] = React.useState([]);
|
||||||
|
const [showLoader, setShowLoader] = useState(true)
|
||||||
const [selectedCategory, setSelectedCategory] = React.useState("default");
|
const [selectedCategory, setSelectedCategory] = React.useState("default");
|
||||||
const [openFileId, setOpenFileId] = React.useState(false);
|
const [openFileId, setOpenFileId] = React.useState(false);
|
||||||
const [fileCategories, setFileCategories] = React.useState([]);
|
const [fileCategories, setFileCategories] = React.useState([]);
|
||||||
@@ -58,16 +61,13 @@ const Files = (props) => {
|
|||||||
const [downloadBranch, setDownloadBranch] = React.useState("main");
|
const [downloadBranch, setDownloadBranch] = React.useState("main");
|
||||||
const [downloadFolder, setDownloadFolder] = React.useState("translation_standards");
|
const [downloadFolder, setDownloadFolder] = React.useState("translation_standards");
|
||||||
const [contentLoading, setContentLoading] = React.useState(false)
|
const [contentLoading, setContentLoading] = React.useState(false)
|
||||||
|
|
||||||
//const alert = useAlert();
|
//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"]
|
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 = "";
|
var upload = "";
|
||||||
|
|
||||||
const handleKeyDown = (event) => {
|
const handleKeyDown = (event) => {
|
||||||
if (event.key === 'Enter') {
|
if (event.key === 'Enter') {
|
||||||
|
|
||||||
console.log('do validate')
|
|
||||||
console.log("new namespace name->",event.target.value);
|
|
||||||
fileCategories.push(event.target.value);
|
fileCategories.push(event.target.value);
|
||||||
setSelectedCategory(event.target.value);
|
setSelectedCategory(event.target.value);
|
||||||
setRenderTextBox(false);
|
setRenderTextBox(false);
|
||||||
@@ -136,6 +136,7 @@ const Files = (props) => {
|
|||||||
.then((responseJson) => {
|
.then((responseJson) => {
|
||||||
if (responseJson.files !== undefined && responseJson.files !== null) {
|
if (responseJson.files !== undefined && responseJson.files !== null) {
|
||||||
setFiles(responseJson.files);
|
setFiles(responseJson.files);
|
||||||
|
setShowLoader(false)
|
||||||
} else if (responseJson.list !== undefined && responseJson.list !== null) {
|
} else if (responseJson.list !== undefined && responseJson.list !== null) {
|
||||||
// Set the "namespace" field in all items
|
// Set the "namespace" field in all items
|
||||||
if (namespace !== undefined && namespace !== null) {
|
if (namespace !== undefined && namespace !== null) {
|
||||||
@@ -147,8 +148,10 @@ const Files = (props) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setFiles(responseJson.list);
|
setFiles(responseJson.list);
|
||||||
|
setShowLoader(false)
|
||||||
} else {
|
} else {
|
||||||
setFiles([]);
|
setFiles([]);
|
||||||
|
setShowLoader(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (namespace === undefined || namespace === null || namespace === "default") {
|
if (namespace === undefined || namespace === null || namespace === "default") {
|
||||||
@@ -244,15 +247,27 @@ const Files = (props) => {
|
|||||||
const fileDownloadModal = loadFileModalOpen ?
|
const fileDownloadModal = loadFileModalOpen ?
|
||||||
<Dialog
|
<Dialog
|
||||||
open={loadFileModalOpen}
|
open={loadFileModalOpen}
|
||||||
onClose={() => {}}
|
|
||||||
PaperProps={{
|
PaperProps={{
|
||||||
style: {
|
sx: {
|
||||||
backgroundColor: theme.palette.surfaceColor,
|
borderRadius: theme?.palette?.DialogStyle?.borderRadius,
|
||||||
color: "white",
|
border: theme?.palette?.DialogStyle?.border,
|
||||||
minWidth: "800px",
|
fontFamily: theme?.typography?.fontFamily,
|
||||||
minHeight: "320px",
|
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>
|
<DialogTitle>
|
||||||
<div style={{ color: "rgba(255,255,255,0.9)" }}>
|
<div style={{ color: "rgba(255,255,255,0.9)" }}>
|
||||||
@@ -364,7 +379,7 @@ const Files = (props) => {
|
|||||||
</DialogContent>
|
</DialogContent>
|
||||||
<DialogActions>
|
<DialogActions>
|
||||||
<Button
|
<Button
|
||||||
style={{ borderRadius: "0px" }}
|
style={{ borderRadius: "2px", textTransform: 'none', fontSize:16, color: "#ff8544" }}
|
||||||
onClick={() => setLoadFileModalOpen(false)}
|
onClick={() => setLoadFileModalOpen(false)}
|
||||||
color="primary"
|
color="primary"
|
||||||
>
|
>
|
||||||
@@ -372,7 +387,7 @@ const Files = (props) => {
|
|||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
variant="contained"
|
variant="contained"
|
||||||
style={{ borderRadius: "0px" }}
|
style={{ borderRadius: "2px", textTransform: 'none', fontSize:16, color: "#1a1a1a", backgroundColor: "#ff8544" }}
|
||||||
disabled={downloadUrl.length === 0 || !downloadUrl.includes("http")}
|
disabled={downloadUrl.length === 0 || !downloadUrl.includes("http")}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
handleGithubValidation();
|
handleGithubValidation();
|
||||||
@@ -637,24 +652,18 @@ const Files = (props) => {
|
|||||||
return (
|
return (
|
||||||
<Dropzone
|
<Dropzone
|
||||||
style={{
|
style={{
|
||||||
maxWidth: window.innerWidth > 1366 ? 1366 : 1200,
|
|
||||||
margin: "auto",
|
margin: "auto",
|
||||||
padding: isSelectedFiles ? null : 20,
|
padding: isSelectedFiles ? null : 20,
|
||||||
|
width: '100%',
|
||||||
|
height: "100%",
|
||||||
}}
|
}}
|
||||||
onDrop={uploadFile}
|
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">
|
<div style={{height: "100%", maxHeight: 1700,overflowY: 'auto', scrollbarColor: '#494949 transparent', scrollbarWidth: 'thin'}}>
|
||||||
<IconButton
|
<div style={{ height: "100%", width: "calc(100% - 20px)", scrollbarColor: '#494949 transparent', scrollbarWidth: 'thin' }}>
|
||||||
color="secondary"
|
<DownloadFileIcon setLoadFileModalOpen={setLoadFileModalOpen} isSelectedFiles={isSelectedFiles} />
|
||||||
style={{position: "absolute", right: 0, top: isSelectedFiles?null:0, left: isSelectedFiles? 990:null }}
|
|
||||||
variant="text"
|
|
||||||
onClick={() => setLoadFileModalOpen(true)}
|
|
||||||
>
|
|
||||||
<CloudDownloadIcon />
|
|
||||||
</IconButton>
|
|
||||||
</Tooltip>
|
|
||||||
|
|
||||||
{fileDownloadModal}
|
{fileDownloadModal}
|
||||||
|
|
||||||
@@ -681,9 +690,9 @@ const Files = (props) => {
|
|||||||
onClick={() => {
|
onClick={() => {
|
||||||
upload.click();
|
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>
|
</Button>
|
||||||
{/* <FileCategoryInput
|
{/* <FileCategoryInput
|
||||||
isSet={renderTextBox} /> */}
|
isSet={renderTextBox} /> */}
|
||||||
@@ -702,7 +711,7 @@ const Files = (props) => {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Button
|
<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"
|
variant="contained"
|
||||||
color="primary"
|
color="primary"
|
||||||
onClick={() => getFiles(selectedCategory)}
|
onClick={() => getFiles(selectedCategory)}
|
||||||
@@ -710,21 +719,23 @@ const Files = (props) => {
|
|||||||
<CachedIcon />
|
<CachedIcon />
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
|
{/* <div style={{height: 35, width: 1, color: "#494949"}}></div> */}
|
||||||
|
|
||||||
{fileCategories !== undefined &&
|
{fileCategories !== undefined &&
|
||||||
fileCategories !== null &&
|
fileCategories !== null &&
|
||||||
fileCategories.length > 1 ? (
|
fileCategories.length > 1 ? (
|
||||||
<FormControl style={{ minWidth: 150, maxWidth: 150 }}>
|
<FormControl style={{ minWidth: 150, maxWidth: 150 }}>
|
||||||
<InputLabel id="input-namespace-label">File Category</InputLabel>
|
|
||||||
<Select
|
<Select
|
||||||
labelId="input-namespace-select-label"
|
labelId="input-namespace-select-label"
|
||||||
id="input-namespace-select-id"
|
id="input-namespace-select-id"
|
||||||
style={{
|
style={{
|
||||||
color: "white",
|
color: "white",
|
||||||
minWidth: 150,
|
minWidth: 122,
|
||||||
maxWidth: 150,
|
maxWidth: 122,
|
||||||
|
height: 35,
|
||||||
float: "right",
|
float: "right",
|
||||||
|
position: 'relative',
|
||||||
|
top: 8
|
||||||
}}
|
}}
|
||||||
value={selectedCategory}
|
value={selectedCategory}
|
||||||
onChange={(event) => {
|
onChange={(event) => {
|
||||||
@@ -759,7 +770,7 @@ const Files = (props) => {
|
|||||||
</Select>
|
</Select>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
) : null}
|
) : null}
|
||||||
<div style={{display: "inline-flex", position:"relative"}}>
|
<div style={{display: "inline-flex", position:"relative", top: 8}}>
|
||||||
{renderTextBox ?
|
{renderTextBox ?
|
||||||
|
|
||||||
<Tooltip title={"Close"} style={{}} aria-label={""}>
|
<Tooltip title={"Close"} style={{}} aria-label={""}>
|
||||||
@@ -777,13 +788,14 @@ const Files = (props) => {
|
|||||||
:
|
:
|
||||||
<Tooltip title={"Add new file category"} style={{}} aria-label={""}>
|
<Tooltip title={"Add new file category"} style={{}} aria-label={""}>
|
||||||
<Button
|
<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"
|
color="primary"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setRenderTextBox(true);
|
setRenderTextBox(true);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<AddIcon/>
|
<AddIcon/>
|
||||||
|
File Category
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
}
|
}
|
||||||
@@ -824,323 +836,379 @@ const Files = (props) => {
|
|||||||
backgroundColor: theme.palette.inputColor,
|
backgroundColor: theme.palette.inputColor,
|
||||||
}}
|
}}
|
||||||
/>}
|
/>}
|
||||||
|
<div
|
||||||
<List style={{borderRadius: isSelectedFiles?8:null, border:isSelectedFiles?"1px solid #494949":null, marginTop:isSelectedFiles?24:null}}>
|
style={{
|
||||||
<ListItem style={{width:isSelectedFiles?"100%":null, borderBottom:isSelectedFiles?"1px solid #494949":null}}>
|
borderRadius: 8,
|
||||||
{/*
|
marginTop: 24,
|
||||||
<ListItemText
|
border: "1px solid #494949",
|
||||||
primary="Updated"
|
width: "100%",
|
||||||
style={{ maxWidth: 185, minWidth: 185 }}
|
overflowX: "auto",
|
||||||
/>
|
paddingBottom: 0,
|
||||||
*/}
|
}}
|
||||||
<ListItemText
|
>
|
||||||
primary="Name"
|
<List
|
||||||
style={{
|
style={{
|
||||||
maxWidth: 250,
|
width: '100%',
|
||||||
minWidth: 250,
|
tableLayout: "auto",
|
||||||
overflow: "hidden",
|
display: "table",
|
||||||
marginLeft: 10,
|
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>
|
</ListItem>
|
||||||
{files === undefined || files === null || files.length === 0 ? null :
|
{showLoader ?
|
||||||
files.map((file, index) => {
|
[...Array(6)].map((_, rowIndex) => (
|
||||||
if (file.namespace === "") {
|
<ListItem
|
||||||
file.namespace = "default";
|
key={rowIndex}
|
||||||
}
|
style={{
|
||||||
|
display: "table-row",
|
||||||
if (file.namespace !== selectedCategory) {
|
backgroundColor: "#212121",
|
||||||
return null;
|
}}
|
||||||
}
|
>
|
||||||
|
{Array(6)
|
||||||
var bgColor = isSelectedFiles ? "#212121":"#27292d";
|
.fill()
|
||||||
if (index % 2 === 0) {
|
.map((_, colIndex) => (
|
||||||
bgColor = isSelectedFiles ? "#1A1A1A":"#1f2023";
|
<ListItemText
|
||||||
}
|
key={colIndex}
|
||||||
|
style={{
|
||||||
const filenamesplit = file.filename.split(".")
|
display: "table-cell",
|
||||||
const iseditable = file.filesize < 2000000 && file.status === "active" && allowedFileTypes.includes(filenamesplit[filenamesplit.length-1])
|
padding: "8px",
|
||||||
|
}}
|
||||||
return (
|
>
|
||||||
<ListItem
|
<Skeleton
|
||||||
key={index}
|
variant="text"
|
||||||
style={{
|
animation="wave"
|
||||||
backgroundColor: bgColor,
|
sx={{
|
||||||
maxHeight: 100,
|
backgroundColor: "#1a1a1a",
|
||||||
overflow: "hidden",
|
height: "20px",
|
||||||
}}
|
borderRadius: "4px",
|
||||||
>
|
}}
|
||||||
{/*
|
/>
|
||||||
<ListItemText
|
</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={{
|
style={{
|
||||||
maxWidth: isSelectedFiles ? 170:225,
|
display: 'table-row',
|
||||||
minWidth: isSelectedFiles ? 170:225,
|
backgroundColor: bgColor,
|
||||||
|
maxHeight: 100,
|
||||||
overflow: "hidden",
|
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
|
||||||
<ListItemText
|
style={{
|
||||||
style={{
|
maxWidth: isSelectedFiles ? 170:225,
|
||||||
maxWidth: 250,
|
minWidth: isSelectedFiles ? 170:225,
|
||||||
minWidth: 250,
|
overflow: "hidden",
|
||||||
overflow: "hidden",
|
}}
|
||||||
marginLeft: 10,
|
primary={new Date(file.updated_at * 1000).toISOString()}
|
||||||
}}
|
/>
|
||||||
primary={file.filename}
|
*/}
|
||||||
/>
|
<ListItemText
|
||||||
<ListItemText
|
primaryTypographyProps={{
|
||||||
primary={
|
style: {
|
||||||
file.workflow_id === "global" || file.workflow_id === "" || file.workflow_id === null || file.workflow_id === undefined ?
|
display: 'table-cell',
|
||||||
<IconButton
|
maxWidth: "170px",
|
||||||
disabled={file.workflow_id === "global"}
|
whiteSpace: 'nowrap',
|
||||||
>
|
textOverflow: 'ellipsis',
|
||||||
<OpenInNewIcon
|
overflow: 'hidden',
|
||||||
style={{
|
padding: 8
|
||||||
color:
|
},
|
||||||
file.workflow_id !== "global"
|
}}
|
||||||
? "white"
|
|
||||||
: "grey",
|
primary={file.filename}
|
||||||
}}
|
/>
|
||||||
/>
|
<ListItemText
|
||||||
</IconButton>
|
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
|
<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={{}}
|
style={{}}
|
||||||
aria-label={"Download"}
|
aria-label={"Download"}
|
||||||
>
|
>
|
||||||
<span>
|
<span>
|
||||||
<a
|
<IconButton
|
||||||
rel="noopener noreferrer"
|
style = {{padding: "6px"}}
|
||||||
style={{
|
disabled={file.status !== "active"}
|
||||||
textDecoration: "none",
|
onClick={() => {
|
||||||
color: "#f85a3e",
|
downloadFile(file);
|
||||||
}}
|
}}
|
||||||
href={`/workflows/${file.workflow_id}`}
|
|
||||||
target="_blank"
|
|
||||||
>
|
>
|
||||||
<IconButton
|
<img src="/icons/downloadIcon.svg" alt="download icon"
|
||||||
disabled={file.workflow_id === "global"}
|
style={{
|
||||||
>
|
color:
|
||||||
<OpenInNewIcon
|
file.status === "active"
|
||||||
style={{
|
? "white"
|
||||||
color:
|
: "grey",
|
||||||
file.workflow_id !== "global"
|
}}
|
||||||
? "white"
|
/>
|
||||||
: "grey",
|
</IconButton>
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</IconButton>
|
|
||||||
</a>
|
|
||||||
</span>
|
</span>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
)
|
<Tooltip
|
||||||
}
|
title={"Copy file ID"}
|
||||||
style={{
|
style={{}}
|
||||||
minWidth: 100,
|
aria-label={"copy"}
|
||||||
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");
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<FileCopyIcon style={{ color: "white" }} />
|
|
||||||
</IconButton>
|
|
||||||
</Tooltip>
|
|
||||||
<Tooltip
|
|
||||||
title={"Delete file"}
|
|
||||||
style={{marginLeft: isSelectedFiles?5:15, }}
|
|
||||||
aria-label={"Delete"}
|
|
||||||
>
|
|
||||||
<span>
|
|
||||||
<IconButton
|
<IconButton
|
||||||
disabled={file.status !== "active"}
|
|
||||||
style = {{padding: "6px"}}
|
style = {{padding: "6px"}}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
deleteFile(file)
|
console.log("file is : ", file)
|
||||||
|
navigator.clipboard.writeText(file.id);
|
||||||
|
document.execCommand("copy");
|
||||||
|
|
||||||
|
toast(file.id + " copied to clipboard");
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<DeleteIcon
|
<img src="/icons/copyIcon.svg" alt="copy icon" style={{ color: "white" }} />
|
||||||
style={{
|
|
||||||
color:
|
|
||||||
file.status === "active"
|
|
||||||
? "white"
|
|
||||||
: "grey",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</span>
|
</Tooltip>
|
||||||
</Tooltip>
|
<Tooltip
|
||||||
</span>
|
title={"Delete file"}
|
||||||
style={{
|
style={{marginLeft: isSelectedFiles?5:15, }}
|
||||||
minWidth: 250,
|
aria-label={"Delete"}
|
||||||
maxWidth: 250,
|
>
|
||||||
// overflow: "hidden",
|
<span>
|
||||||
}}
|
<IconButton
|
||||||
/>
|
disabled={file.status !== "active"}
|
||||||
</ListItem>
|
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>
|
</List>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Dropzone>
|
</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,
|
Add as AddIcon,
|
||||||
BorderColor,
|
BorderColor,
|
||||||
Close as CloseIcon,
|
Close as CloseIcon,
|
||||||
|
ConstructionOutlined,
|
||||||
} from "@mui/icons-material";
|
} from "@mui/icons-material";
|
||||||
import SearchBox from "./SearchData.jsx";
|
import SearchBox from "./SearchData.jsx";
|
||||||
import {
|
import {
|
||||||
@@ -85,7 +86,21 @@ const LeftSideBar = ({ userdata, serverside, globalUrl, notifications, }) => {
|
|||||||
return orgOptions.find((option) => option.name === selectedOrg);
|
return orgOptions.find((option) => option.name === selectedOrg);
|
||||||
}, [selectedOrg, orgOptions]);
|
}, [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) => {
|
const CustomPopper = (props) => {
|
||||||
return (
|
return (
|
||||||
@@ -141,7 +156,7 @@ const LeftSideBar = ({ userdata, serverside, globalUrl, notifications, }) => {
|
|||||||
>
|
>
|
||||||
{props.children}
|
{props.children}
|
||||||
</Box>
|
</Box>
|
||||||
<Link to="/admin2" style={hrefStyle}>
|
<Link to="/admin?tab=tenants" style={hrefStyle}>
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
width: "100%",
|
width: "100%",
|
||||||
@@ -446,7 +461,7 @@ const LeftSideBar = ({ userdata, serverside, globalUrl, notifications, }) => {
|
|||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Link to="/admin2" style={hrefStyle}>
|
<Link to="/admin" style={hrefStyle}>
|
||||||
<MenuItem
|
<MenuItem
|
||||||
onClick={(event) => {
|
onClick={(event) => {
|
||||||
handleClose();
|
handleClose();
|
||||||
@@ -466,7 +481,7 @@ const LeftSideBar = ({ userdata, serverside, globalUrl, notifications, }) => {
|
|||||||
</Link>
|
</Link>
|
||||||
|
|
||||||
<Divider style={{ marginTop: 10, marginBottom: 10, }} />
|
<Divider style={{ marginTop: 10, marginBottom: 10, }} />
|
||||||
<Link to="/admin2?admin_tab=priorities" style={hrefStyle}>
|
<Link to="/admin?admin_tab=notifications" style={hrefStyle}>
|
||||||
<MenuItem
|
<MenuItem
|
||||||
onClick={(event) => {
|
onClick={(event) => {
|
||||||
handleClose();
|
handleClose();
|
||||||
@@ -478,7 +493,7 @@ const LeftSideBar = ({ userdata, serverside, globalUrl, notifications, }) => {
|
|||||||
})
|
})
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
</Link>
|
</Link>
|
||||||
<Link to="/usecases2" style={hrefStyle}>
|
<Link to="/usecases" style={hrefStyle}>
|
||||||
<MenuItem
|
<MenuItem
|
||||||
onClick={(event) => {
|
onClick={(event) => {
|
||||||
handleClose();
|
handleClose();
|
||||||
@@ -641,7 +656,7 @@ const LeftSideBar = ({ userdata, serverside, globalUrl, notifications, }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const getRegionTag = (region_url) => {
|
const getRegionTag = (region_url) => {
|
||||||
let regiontag = "eu";
|
let regiontag = "UK";
|
||||||
if (
|
if (
|
||||||
region_url !== undefined &&
|
region_url !== undefined &&
|
||||||
region_url !== null &&
|
region_url !== null &&
|
||||||
@@ -653,15 +668,25 @@ const LeftSideBar = ({ userdata, serverside, globalUrl, notifications, }) => {
|
|||||||
regiontag = namesplit[namesplit.length - 1];
|
regiontag = namesplit[namesplit.length - 1];
|
||||||
|
|
||||||
if (regiontag === "california") {
|
if (regiontag === "california") {
|
||||||
regiontag = "us";
|
regiontag = "US";
|
||||||
} else if (regiontag === "frankfurt") {
|
} else if (regiontag === "frankfurt") {
|
||||||
regiontag = "fr";
|
regiontag = "EU";
|
||||||
|
} else if (regiontag === "ca"){
|
||||||
|
regiontag = "CA";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return regiontag;
|
return regiontag;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
|
||||||
|
if(activeOrgName !== userdata?.active_org?.name){
|
||||||
|
setActiveOrgName(userdata?.active_org?.name || "Select Organization");
|
||||||
|
}
|
||||||
|
}, [userdata]);
|
||||||
|
|
||||||
const CheckOrgStates = useCallback(() => {
|
const CheckOrgStates = useCallback(() => {
|
||||||
setOrgOptions(
|
setOrgOptions(
|
||||||
userdata?.orgs?.map((org) => ({
|
userdata?.orgs?.map((org) => ({
|
||||||
@@ -723,6 +748,20 @@ const LeftSideBar = ({ userdata, serverside, globalUrl, notifications, }) => {
|
|||||||
</Dialog>
|
</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 (
|
return (
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
@@ -736,7 +775,8 @@ const LeftSideBar = ({ userdata, serverside, globalUrl, notifications, }) => {
|
|||||||
boxShadow: "0px 4px 12px rgba(0, 0, 0, 0.2)" ,
|
boxShadow: "0px 4px 12px rgba(0, 0, 0, 0.2)" ,
|
||||||
resize: 'both',
|
resize: 'both',
|
||||||
|
|
||||||
height: "calc(100vh - 32px)",
|
zoom: 0.8,
|
||||||
|
height: "calc((100vh - 32px)*1.2)",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{modalView}
|
{modalView}
|
||||||
@@ -759,7 +799,7 @@ const LeftSideBar = ({ userdata, serverside, globalUrl, notifications, }) => {
|
|||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
alignItems: "center",
|
// alignItems: "center",
|
||||||
justifyContent: "center",
|
justifyContent: "center",
|
||||||
position: "relative",
|
position: "relative",
|
||||||
right: !expandLeftNav && 8,
|
right: !expandLeftNav && 8,
|
||||||
@@ -814,46 +854,62 @@ const LeftSideBar = ({ userdata, serverside, globalUrl, notifications, }) => {
|
|||||||
{expandLeftNav ? (
|
{expandLeftNav ? (
|
||||||
<Fade in={expandLeftNav} timeout={500}>
|
<Fade in={expandLeftNav} timeout={500}>
|
||||||
<TextField
|
<TextField
|
||||||
id="sidebar-search"
|
id="sidebar-search"
|
||||||
placeholder= "Search"
|
placeholder="Search"
|
||||||
sx={{
|
sx={{
|
||||||
width: "100%",
|
width: "100%",
|
||||||
maxWidth: 228,
|
maxWidth: 228,
|
||||||
"& .MuiInputBase-root": {
|
"& .MuiInputBase-root": {
|
||||||
height: 35,
|
height: 35,
|
||||||
padding: 0,
|
padding: 0,
|
||||||
},
|
},
|
||||||
"& .MuiOutlinedInput-root": {
|
"& .MuiOutlinedInput-root": {
|
||||||
cursor: "pointer",
|
cursor: "pointer",
|
||||||
width: 228,
|
width: 228,
|
||||||
"& fieldset": {
|
"& fieldset": {
|
||||||
borderColor: "#494949",
|
borderColor: "#494949",
|
||||||
},
|
},
|
||||||
"&:hover fieldset": {
|
"&:hover fieldset": {
|
||||||
borderColor: "#ffffff",
|
borderColor: "#ffffff",
|
||||||
display: "block"
|
display: "block",
|
||||||
},
|
},
|
||||||
"&.Mui-focused fieldset": {
|
"&.Mui-focused fieldset": {
|
||||||
borderColor: "#A9A9A9",
|
borderColor: "#A9A9A9",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"& input": {
|
"& input": {
|
||||||
padding: "8px 14px",
|
padding: "8px 14px",
|
||||||
fontSize: "14px",
|
fontSize: "14px",
|
||||||
color: "#C8C8C8",
|
color: "#C8C8C8",
|
||||||
},
|
},
|
||||||
backgroundColor: "transparent",
|
backgroundColor: "transparent",
|
||||||
}}
|
}}
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
InputProps={{
|
InputProps={{
|
||||||
startAdornment: (
|
startAdornment: (
|
||||||
<SearchIcon style={{ color: "#CDCDCD", width: 24, height: 24, marginLeft: 16}} />
|
<SearchIcon style={{ color: "#CDCDCD", width: 24, height: 24, marginLeft: 16 }} />
|
||||||
),
|
),
|
||||||
disableUnderline: true,
|
endAdornment: (
|
||||||
}}
|
<span
|
||||||
onClick={()=>{setSearchBarModalOpen(true)}}
|
style={{
|
||||||
onChange={()=> {setSearchBarModalOpen(true)}}
|
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>
|
</Fade>
|
||||||
):(
|
):(
|
||||||
<>
|
<>
|
||||||
@@ -891,10 +947,16 @@ const LeftSideBar = ({ userdata, serverside, globalUrl, notifications, }) => {
|
|||||||
setCurrentOpenTab("automate");
|
setCurrentOpenTab("automate");
|
||||||
localStorage.setItem("lastTabOpenByUser", "automate");
|
localStorage.setItem("lastTabOpenByUser", "automate");
|
||||||
}}
|
}}
|
||||||
sx={{
|
variant="text"
|
||||||
|
style={{
|
||||||
...ButtonStyle,
|
...ButtonStyle,
|
||||||
backgroundColor: ((currentOpenTab === "automate" && currentPath.includes("/dashboards/automate"))|| (!expandLeftNav && (currentPath === "/workflows" || currentPath === "/usecases2" || currentPath.includes("/search"))))? "#2f2f2f": "transparent",
|
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
|
<img
|
||||||
@@ -920,8 +982,15 @@ const LeftSideBar = ({ userdata, serverside, globalUrl, notifications, }) => {
|
|||||||
setOpenautomateTab((prev) => !prev);
|
setOpenautomateTab((prev) => !prev);
|
||||||
setOpenSecurityTab(false);
|
setOpenSecurityTab(false);
|
||||||
}}
|
}}
|
||||||
sx={{
|
style={{
|
||||||
marginLeft: 0.625,
|
color: "#FFFFFF",
|
||||||
|
marginLeft: 0.625,
|
||||||
|
}}
|
||||||
|
onMouseOver={(event)=>{
|
||||||
|
event.currentTarget.style.backgroundColor = "#2f2f2f";
|
||||||
|
}}
|
||||||
|
onMouseOut={(event)=>{
|
||||||
|
event.currentTarget.style.backgroundColor = "transparent";
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{openautomatetab ? (
|
{openautomatetab ? (
|
||||||
@@ -952,23 +1021,28 @@ const LeftSideBar = ({ userdata, serverside, globalUrl, notifications, }) => {
|
|||||||
flexDirection: "column",
|
flexDirection: "column",
|
||||||
paddingLeft: 16,
|
paddingLeft: 16,
|
||||||
gap: 4,
|
gap: 4,
|
||||||
marginTop: expandLeftNav ? 16 : 0,
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Link to="/usecases2" style={hrefStyle}>
|
<Link to="/usecases" style={hrefStyle}>
|
||||||
<Button
|
<Button
|
||||||
onClick={(event) => {
|
onClick={(event) => {
|
||||||
setCurrentOpenTab("usecases");
|
setCurrentOpenTab("usecases");
|
||||||
localStorage.setItem("lastTabOpenByUser", "usecases");
|
localStorage.setItem("lastTabOpenByUser", "usecases");
|
||||||
}}
|
}}
|
||||||
sx={{
|
style={{
|
||||||
width: "100%",
|
width: "100%",
|
||||||
height: 35,
|
height: 35,
|
||||||
color: "#C8C8C8",
|
color: "#C8C8C8",
|
||||||
justifyContent: "flex-start",
|
justifyContent: "flex-start",
|
||||||
textTransform: "none",
|
textTransform: "none",
|
||||||
backgroundColor: currentOpenTab === "usecases" && expandLeftNav && currentPath.includes("/usecases2")? "#2f2f2f": "transparent",
|
backgroundColor: currentOpenTab === "usecases" && expandLeftNav && currentPath.includes("/usecases")? "#2f2f2f": "transparent",
|
||||||
"&:hover": { backgroundColor: "#2f2f2f" },
|
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}
|
disableRipple={expandLeftNav ? false : true}
|
||||||
>
|
>
|
||||||
@@ -985,22 +1059,28 @@ const LeftSideBar = ({ userdata, serverside, globalUrl, notifications, }) => {
|
|||||||
</span>
|
</span>
|
||||||
</Button>
|
</Button>
|
||||||
</Link>
|
</Link>
|
||||||
<Link to="/workflows2" style={hrefStyle}>
|
<Link to="/workflows" style={hrefStyle}>
|
||||||
<Button
|
<Button
|
||||||
onClick={(event) => {
|
onClick={(event) => {
|
||||||
setCurrentOpenTab("workflows");
|
setCurrentOpenTab("workflows");
|
||||||
localStorage.setItem("lastTabOpenByUser", "workflows");
|
localStorage.setItem("lastTabOpenByUser", "workflows");
|
||||||
}}
|
}}
|
||||||
sx={{
|
style={{
|
||||||
width: "100%",
|
width: "100%",
|
||||||
height: 35,
|
height: 35,
|
||||||
color: "#C8C8C8",
|
color: "#C8C8C8",
|
||||||
justifyContent: "flex-start",
|
justifyContent: "flex-start",
|
||||||
textTransform: "none",
|
textTransform: "none",
|
||||||
backgroundColor: currentOpenTab === "workflows" && currentPath === "/workflows" && expandLeftNav? "#2f2f2f": "transparent",
|
backgroundColor: currentOpenTab === "workflows" && currentPath === "/workflows" && expandLeftNav? "#2f2f2f": "transparent",
|
||||||
"&:hover": { backgroundColor: "#2f2f2f" },
|
marginLeft: 16
|
||||||
}}
|
}}
|
||||||
disableRipple={expandLeftNav ? false : true}
|
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 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
|
<span
|
||||||
@@ -1015,20 +1095,26 @@ const LeftSideBar = ({ userdata, serverside, globalUrl, notifications, }) => {
|
|||||||
</span>
|
</span>
|
||||||
</Button>
|
</Button>
|
||||||
</Link>
|
</Link>
|
||||||
<Link to="/apps2" style={hrefStyle}>
|
<Link to="/apps" style={hrefStyle}>
|
||||||
<Button
|
<Button
|
||||||
onClick={(event) => {
|
onClick={(event) => {
|
||||||
setCurrentOpenTab("apps");
|
setCurrentOpenTab("apps");
|
||||||
localStorage.setItem("lastTabOpenByUser", "apps");
|
localStorage.setItem("lastTabOpenByUser", "apps");
|
||||||
}}
|
}}
|
||||||
sx={{
|
style={{
|
||||||
width: "100%",
|
width: "100%",
|
||||||
height: 35,
|
height: 35,
|
||||||
color: "#C8C8C8",
|
color: "#C8C8C8",
|
||||||
justifyContent: "flex-start",
|
justifyContent: "flex-start",
|
||||||
textTransform: "none",
|
textTransform: "none",
|
||||||
backgroundColor: currentOpenTab === "apps" && expandLeftNav && currentPath.includes("/search") ? "#2f2f2f": "transparent",
|
backgroundColor: currentOpenTab === "apps" && expandLeftNav && currentPath.includes("/apps2") ? "#2f2f2f": "transparent",
|
||||||
"&:hover": { backgroundColor: "#2f2f2f" },
|
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}
|
disableRipple={expandLeftNav ? false : true}
|
||||||
>
|
>
|
||||||
@@ -1038,7 +1124,7 @@ const LeftSideBar = ({ userdata, serverside, globalUrl, notifications, }) => {
|
|||||||
display: expandLeftNav ? "inline" : "none",
|
display: expandLeftNav ? "inline" : "none",
|
||||||
opacity: expandLeftNav ? 1 : 0,
|
opacity: expandLeftNav ? 1 : 0,
|
||||||
transition: "opacity 0.3s ease",
|
transition: "opacity 0.3s ease",
|
||||||
color: currentOpenTab === "apps" && currentPath.includes("/search") ? "#F1F1F1" : "#C8C8C8",
|
color: currentOpenTab === "apps" && currentPath.includes("/apps2") ? "#F1F1F1" : "#C8C8C8",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Apps
|
Apps
|
||||||
@@ -1051,7 +1137,7 @@ const LeftSideBar = ({ userdata, serverside, globalUrl, notifications, }) => {
|
|||||||
sx={{
|
sx={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
flexDirection: "row",
|
flexDirection: "row",
|
||||||
marginTop: 2.5,
|
marginTop: 1
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<span style={{ display: "inline-block", width: "100%" }}>
|
<span style={{ display: "inline-block", width: "100%" }}>
|
||||||
@@ -1072,7 +1158,7 @@ const LeftSideBar = ({ userdata, serverside, globalUrl, notifications, }) => {
|
|||||||
setCurrentOpenTab("security");
|
setCurrentOpenTab("security");
|
||||||
localStorage.setItem("lastTabOpenByUser", "security");
|
localStorage.setItem("lastTabOpenByUser", "security");
|
||||||
}}
|
}}
|
||||||
sx={{
|
style={{
|
||||||
...ButtonStyle,
|
...ButtonStyle,
|
||||||
backgroundColor:
|
backgroundColor:
|
||||||
((currentOpenTab === "security" && currentPath.includes("/security")) ||
|
((currentOpenTab === "security" && currentPath.includes("/security")) ||
|
||||||
@@ -1080,11 +1166,19 @@ const LeftSideBar = ({ userdata, serverside, globalUrl, notifications, }) => {
|
|||||||
(currentPath.includes("detections") || currentPath.includes("response"))))
|
(currentPath.includes("detections") || currentPath.includes("response"))))
|
||||||
? "#2f2f2f"
|
? "#2f2f2f"
|
||||||
: "transparent",
|
: "transparent",
|
||||||
"&:hover": {
|
|
||||||
backgroundColor: userdata?.support ? "#2f2f2f" : "transparent",
|
|
||||||
},
|
|
||||||
cursor: userdata?.support ? "pointer" : "not-allowed",
|
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
|
<ShieldOutlinedIcon
|
||||||
style={{
|
style={{
|
||||||
@@ -1105,19 +1199,25 @@ const LeftSideBar = ({ userdata, serverside, globalUrl, notifications, }) => {
|
|||||||
: "#6F6F6F",
|
: "#6F6F6F",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Security
|
Content
|
||||||
</span>
|
</span>
|
||||||
</Button>
|
</Button>
|
||||||
</Link>
|
</Link>
|
||||||
</span>
|
</span>
|
||||||
<IconButton
|
<IconButton
|
||||||
disabled={true}
|
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setOpenSecurityTab((prev) => !prev);
|
setOpenSecurityTab((prev) => !prev);
|
||||||
setOpenautomateTab(false);
|
setOpenautomateTab(false);
|
||||||
}}
|
}}
|
||||||
sx={{
|
style={{
|
||||||
marginLeft: 0.625,
|
marginLeft: 0.625,
|
||||||
|
color: "#FFFFFF",
|
||||||
|
}}
|
||||||
|
onMouseOver={(event)=>{
|
||||||
|
event.currentTarget.style.backgroundColor = "#2f2f2f";
|
||||||
|
}}
|
||||||
|
onMouseOut={(event)=>{
|
||||||
|
event.currentTarget.style.backgroundColor = "transparent";
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{openSecurityTab ? (
|
{openSecurityTab ? (
|
||||||
@@ -1144,14 +1244,12 @@ const LeftSideBar = ({ userdata, serverside, globalUrl, notifications, }) => {
|
|||||||
display: "flex",
|
display: "flex",
|
||||||
flexDirection: "column",
|
flexDirection: "column",
|
||||||
paddingLeft: 16,
|
paddingLeft: 16,
|
||||||
gap: 4,
|
|
||||||
marginTop: expandLeftNav ? 16 : 0,
|
|
||||||
}}
|
}}
|
||||||
disableRipple={expandLeftNav ? false : true}
|
disableRipple={expandLeftNav ? false : true}
|
||||||
>
|
>
|
||||||
<span style={{ display: "inline-block", width: "100%" }}>
|
<span style={{ display: "inline-block", width: "100%" }}>
|
||||||
<Link
|
<Link
|
||||||
to={userdata?.support ? "/detections" : "#"}
|
to={"/forms"}
|
||||||
style={{
|
style={{
|
||||||
...hrefStyle,
|
...hrefStyle,
|
||||||
pointerEvents: userdata?.support ? "auto" : "none",
|
pointerEvents: userdata?.support ? "auto" : "none",
|
||||||
@@ -1196,14 +1294,14 @@ const LeftSideBar = ({ userdata, serverside, globalUrl, notifications, }) => {
|
|||||||
: "#6F6F6F",
|
: "#6F6F6F",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Detection
|
Forms
|
||||||
</span>
|
</span>
|
||||||
</Button>
|
</Button>
|
||||||
</Link>
|
</Link>
|
||||||
</span>
|
</span>
|
||||||
<span style={{ display: "inline-block", width: "100%" }}>
|
<span style={{ display: "inline-block", width: "100%" }}>
|
||||||
<Link
|
<Link
|
||||||
to={userdata?.support ? "/response" : "#"}
|
to={"/admin?tab=datastore"}
|
||||||
style={{
|
style={{
|
||||||
...hrefStyle,
|
...hrefStyle,
|
||||||
pointerEvents: userdata?.support ? "auto" : "none",
|
pointerEvents: userdata?.support ? "auto" : "none",
|
||||||
@@ -1230,7 +1328,6 @@ const LeftSideBar = ({ userdata, serverside, globalUrl, notifications, }) => {
|
|||||||
},
|
},
|
||||||
cursor: userdata?.support ? "pointer" : "not-allowed",
|
cursor: userdata?.support ? "pointer" : "not-allowed",
|
||||||
}}
|
}}
|
||||||
disabled={!userdata?.support}
|
|
||||||
>
|
>
|
||||||
<span style={{ position: "relative", left: !expandLeftNav ? 10 : 0, marginRight: 10, fontSize: 16 }}>
|
<span style={{ position: "relative", left: !expandLeftNav ? 10 : 0, marginRight: 10, fontSize: 16 }}>
|
||||||
•
|
•
|
||||||
@@ -1248,26 +1345,81 @@ const LeftSideBar = ({ userdata, serverside, globalUrl, notifications, }) => {
|
|||||||
: "#6F6F6F",
|
: "#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>
|
</span>
|
||||||
</Button>
|
</Button>
|
||||||
</Link>
|
</Link>
|
||||||
</span>
|
</span>
|
||||||
</Box>
|
</Box>
|
||||||
</Collapse>
|
</Collapse>
|
||||||
|
|
||||||
|
|
||||||
<Link to="/docs" style={hrefStyle}>
|
<Link to="/docs" style={hrefStyle}>
|
||||||
<Button
|
<Button
|
||||||
onClick={(event) => {
|
onClick={(event) => {
|
||||||
setCurrentOpenTab("docs");
|
setCurrentOpenTab("docs");
|
||||||
localStorage.setItem("lastTabOpenByUser", "docs");
|
localStorage.setItem("lastTabOpenByUser", "docs");
|
||||||
}}
|
}}
|
||||||
sx={{
|
style={{
|
||||||
...ButtonStyle,
|
...ButtonStyle,
|
||||||
marginTop: 2,
|
marginTop: 8,
|
||||||
|
marginTop: 8,
|
||||||
backgroundColor: currentOpenTab === "docs" && currentPath.includes("/docs") ? "#2f2f2f": "transparent",
|
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
|
<img
|
||||||
@@ -1385,15 +1537,20 @@ const LeftSideBar = ({ userdata, serverside, globalUrl, notifications, }) => {
|
|||||||
>
|
>
|
||||||
{
|
{
|
||||||
isCloud ? (
|
isCloud ? (
|
||||||
<span
|
<span
|
||||||
style={{
|
style={{
|
||||||
color: "#bbb",
|
color: "#bbb",
|
||||||
fontSize: "16px",
|
fontSize: "16px",
|
||||||
marginRight: 12,
|
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}
|
{option.region_url}
|
||||||
</span>) : null
|
</span>
|
||||||
|
) : null
|
||||||
}
|
}
|
||||||
<img
|
<img
|
||||||
src={option.image ? option.image : "/images/no_image.png"}
|
src={option.image ? option.image : "/images/no_image.png"}
|
||||||
|
|||||||
@@ -127,7 +127,7 @@ const MFASetup = ({ isLoaded, globalUrl, setCookie }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
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" }}>
|
<Paper elevation={3} style={{ padding: "30px", backgroundColor: "#212121" }}>
|
||||||
<Typography variant="h5" style={{ color: "white", marginBottom: 10, textAlign: "center" }}>
|
<Typography variant="h5" style={{ color: "white", marginBottom: 10, textAlign: "center" }}>
|
||||||
Multi-Factor Authentication Setup
|
Multi-Factor Authentication Setup
|
||||||
|
|||||||
@@ -110,8 +110,30 @@ const OrgHeader = (props) => {
|
|||||||
orgDescription,
|
orgDescription,
|
||||||
selectedOrganization.id,
|
selectedOrganization.id,
|
||||||
selectedOrganization.image,
|
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,
|
defaults,
|
||||||
sso_config
|
sso_config
|
||||||
) => {
|
) => {
|
||||||
|
console.log("defatult in handleEditOrg", defaults)
|
||||||
const data = {
|
const data = {
|
||||||
name: name,
|
name: name,
|
||||||
description: description,
|
description: description,
|
||||||
@@ -309,6 +309,7 @@ const OrgHeaderexpanded = (props) => {
|
|||||||
openid_authorization: openidAuthorization,
|
openid_authorization: openidAuthorization,
|
||||||
openid_token: openidToken,
|
openid_token: openidToken,
|
||||||
SSORequired: SSORequired,
|
SSORequired: SSORequired,
|
||||||
|
auto_provision: selectedOrganization?.sso_config?.auto_provision,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -485,6 +486,7 @@ const OrgHeaderexpanded = (props) => {
|
|||||||
value={data}
|
value={data}
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
var parsedinput = { target: { value: data } }
|
var parsedinput = { target: { value: data } }
|
||||||
|
console.log("Parsed input: ", parsedinput)
|
||||||
handleWorkflowSelectionUpdate(parsedinput)
|
handleWorkflowSelectionUpdate(parsedinput)
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@@ -753,7 +755,7 @@ const OrgHeaderexpanded = (props) => {
|
|||||||
{SSORequired ? "Required" : "Optional"}
|
{SSORequired ? "Required" : "Optional"}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
{/* <div
|
||||||
style={{
|
style={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
flexDirection: "column",
|
flexDirection: "column",
|
||||||
@@ -800,7 +802,7 @@ const OrgHeaderexpanded = (props) => {
|
|||||||
</Button>
|
</Button>
|
||||||
</span>
|
</span>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</div>
|
</div> */}
|
||||||
<div></div>
|
<div></div>
|
||||||
<Grid item xs={12} style={{}}>
|
<Grid item xs={12} style={{}}>
|
||||||
<Typography variant="h6" style={{ textAlign: "center" }}>
|
<Typography variant="h6" style={{ textAlign: "center" }}>
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ import {
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
HelpOutline as HelpOutlineIcon,
|
HelpOutline as HelpOutlineIcon,
|
||||||
|
OpenInFull as OpenInFullIcon,
|
||||||
Description as DescriptionIcon,
|
Description as DescriptionIcon,
|
||||||
GetApp as GetAppIcon,
|
GetApp as GetAppIcon,
|
||||||
Search as SearchIcon,
|
Search as SearchIcon,
|
||||||
@@ -2090,7 +2091,7 @@ const ParsedAction = (props) => {
|
|||||||
{data?.validation?.valid === true ?
|
{data?.validation?.valid === true ?
|
||||||
<Tooltip title="Authentication has been validated" placement="top">
|
<Tooltip title="Authentication has been validated" placement="top">
|
||||||
<Chip
|
<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"}
|
label={"Valid"}
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
color="secondary"
|
color="secondary"
|
||||||
@@ -2099,7 +2100,7 @@ const ParsedAction = (props) => {
|
|||||||
: null }
|
: null }
|
||||||
{data?.last_modified === true ?
|
{data?.last_modified === true ?
|
||||||
<Chip
|
<Chip
|
||||||
style={{marginLeft: 0, padding: 0, marginRight: 10, cursor: "pointer",}}
|
style={{marginLeft: 0, padding: 0, marginRight: 10, cursor: "pointer", maxHeight: 25, }}
|
||||||
label={"Latest"}
|
label={"Latest"}
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
color="secondary"
|
color="secondary"
|
||||||
@@ -2139,7 +2140,7 @@ const ParsedAction = (props) => {
|
|||||||
>
|
>
|
||||||
<IconButton
|
<IconButton
|
||||||
color="primary"
|
color="primary"
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
style={{}}
|
style={{}}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setAuthenticationModalOpen(true);
|
setAuthenticationModalOpen(true);
|
||||||
@@ -3452,36 +3453,10 @@ const ParsedAction = (props) => {
|
|||||||
disableUnderline: true,
|
disableUnderline: true,
|
||||||
endAdornment: hideExtraTypes ? null : (
|
endAdornment: hideExtraTypes ? null : (
|
||||||
<InputAdornment position="end">
|
<InputAdornment position="end">
|
||||||
<ButtonGroup orientation={multiline ? "vertical" : "horizontal"}>
|
<ButtonGroup color="secondary" 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>
|
|
||||||
<Tooltip title="Autocomplete text" placement="bottom">
|
<Tooltip title="Autocomplete text" placement="bottom">
|
||||||
<AddCircleOutlineIcon
|
<AddCircleOutlineIcon
|
||||||
style={{ cursor: "pointer", margin: multiline ? 5 : 0, }}
|
style={{ color: "rgba(255,255,255,0.7)", cursor: "pointer", margin: multiline ? 5 : 0, }}
|
||||||
onClick={(event) => {
|
onClick={(event) => {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
|
|
||||||
@@ -4355,6 +4330,34 @@ const ParsedAction = (props) => {
|
|||||||
{tmpitem} <span style={{color: theme.palette.main}}>{selectedActionParameters[count].required || selectedActionParameters[count].configuration ? "*" : ""}</span>
|
{tmpitem} <span style={{color: theme.palette.main}}>{selectedActionParameters[count].required || selectedActionParameters[count].configuration ? "*" : ""}</span>
|
||||||
</div>
|
</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>
|
</div>
|
||||||
{datafield}
|
{datafield}
|
||||||
{/*shufflecode*/}
|
{/*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 { toast } from "react-toastify";
|
||||||
import theme from "../theme.jsx";
|
import theme from "../theme.jsx";
|
||||||
@@ -13,22 +13,25 @@ import {
|
|||||||
Card,
|
Card,
|
||||||
Chip,
|
Chip,
|
||||||
Switch,
|
Switch,
|
||||||
|
Skeleton,
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
|
import { Context } from "../context/ContextApi.jsx";
|
||||||
|
|
||||||
import { useNavigate, Link } from "react-router-dom";
|
import { useNavigate, Link } from "react-router-dom";
|
||||||
import Priority from "../components/Priority.jsx";
|
import Priority from "../components/Priority.jsx";
|
||||||
|
import { constrainMatrix } from "reaviz";
|
||||||
//import { useAlert
|
//import { useAlert
|
||||||
|
|
||||||
const Priorities = (props) => {
|
const Priorities = memo((props) => {
|
||||||
const { globalUrl, userdata,clickedFromOrgTab, serverside, billingInfo, stripeKey, checkLogin, setAdminTab, setCurTab, notifications, setNotifications, } = props;
|
const { globalUrl, userdata,clickedFromOrgTab, serverside, billingInfo, stripeKey, checkLogin, setAdminTab, setCurTab, notifications, setNotifications, } = props;
|
||||||
|
|
||||||
const [showDismissed, setShowDismissed] = React.useState(false);
|
const [showDismissed, setShowDismissed] = React.useState(false);
|
||||||
const [showRead, setShowRead] = React.useState(false);
|
const [showRead, setShowRead] = React.useState(false);
|
||||||
const [appFramework, setAppFramework] = React.useState({});
|
const [appFramework, setAppFramework] = React.useState({});
|
||||||
|
|
||||||
const [selectedWorkflow, setSelectedWorkflow] = React.useState("NO HIGHLIGHT");
|
const [selectedWorkflow, setSelectedWorkflow] = React.useState("NO HIGHLIGHT");
|
||||||
const [selectedExecutionId, setSelectedExecutionId] = React.useState("NO HIGHLIGHT");
|
const [selectedExecutionId, setSelectedExecutionId] = React.useState("NO HIGHLIGHT");
|
||||||
const [highlightKMS, setHighlightKMS] = React.useState(false)
|
const [highlightKMS, setHighlightKMS] = React.useState(false)
|
||||||
|
|
||||||
let navigate = useNavigate();
|
let navigate = useNavigate();
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
getFramework()
|
getFramework()
|
||||||
@@ -216,188 +219,16 @@ const Priorities = (props) => {
|
|||||||
const notificationWidth = "100%"
|
const notificationWidth = "100%"
|
||||||
const imagesize = 22
|
const imagesize = 22
|
||||||
const boxColor = "#86c142"
|
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 (
|
return (
|
||||||
<div style={{width: clickedFromOrgTab ? 1030:1000, padding: clickedFromOrgTab ? 27:null, height: clickedFromOrgTab ? "auto":null, backgroundColor: clickedFromOrgTab ? '#212121':null, borderRadius: clickedFromOrgTab ? '16px':null, }}>
|
<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, }}>
|
||||||
<h2 style={{ display: clickedFromOrgTab?null:"inline", marginBottom: clickedFromOrgTab? 8:null, marginTop: clickedFromOrgTab?40:null, color: clickedFromOrgTab?"#ffffff":null }}>Notifications ({
|
<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
|
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.
|
Notifications help you find potential problems with your workflows and apps.
|
||||||
<a
|
<a
|
||||||
target="_blank"
|
target="_blank"
|
||||||
@@ -430,24 +261,11 @@ const Priorities = (props) => {
|
|||||||
</Button>
|
</Button>
|
||||||
) : null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
{notifications === null || notifications === undefined || notifications.length === 0 ? null :
|
<NotificationComponent notifications={notifications} showRead={showRead} selectedExecutionId={selectedExecutionId} selectedWorkflow={selectedWorkflow} highlightKMS={highlightKMS} userdata={userdata} imagesize={imagesize} boxColor={boxColor} clickedFromOrgTab={clickedFromOrgTab} notificationWidth={notificationWidth} dismissNotification={dismissNotification}/>
|
||||||
<div>
|
|
||||||
{notifications.map((notification, index) => {
|
|
||||||
if (showRead === false && notification.read === true) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<NotificationItem data={notification} key={index} />
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
{clickedFromOrgTab? null : <Divider style={{marginTop: 50, marginBottom: 50, }} />}
|
{clickedFromOrgTab? null : <Divider style={{marginTop: 50, marginBottom: 50, }} />}
|
||||||
|
<h2 style={{ display: clickedFromOrgTab ? null:"inline", marginBottom: clickedFromOrgTab ? 8:null, marginTop: clickedFromOrgTab ? 30 :null, color: clickedFromOrgTab ? "#ffffff" : null }}>Suggestions</h2>
|
||||||
<h2 style={{ display: clickedFromOrgTab ? null:"inline", marginBottom: clickedFromOrgTab ? 8:null, marginTop: clickedFromOrgTab ?0:null, color: clickedFromOrgTab ? "#ffffff" : null }}>Suggestions</h2>
|
<span style={{ fontSize: 16, color: clickedFromOrgTab ?"#9E9E9E":null,marginLeft: clickedFromOrgTab ?null:25 }}>
|
||||||
<span style={{ 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.
|
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
|
<a
|
||||||
target="_blank"
|
target="_blank"
|
||||||
@@ -489,9 +307,232 @@ const Priorities = (props) => {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
})
|
||||||
|
|
||||||
export default Priorities;
|
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,
|
maxHeight: isMobile ? "100%" : 700,
|
||||||
border: theme.palette.defaultBorder,
|
border: theme.palette.defaultBorder,
|
||||||
padding: isMobile ? "25px 10px 25px 10px" : 25,
|
padding: isMobile ? "25px 10px 25px 10px" : 25,
|
||||||
|
zoom: 0.8,
|
||||||
|
backgroundColor: "black",
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -382,7 +382,7 @@ const data = [
|
|||||||
css: {
|
css: {
|
||||||
"background-color": "#f85a3e",
|
"background-color": "#f85a3e",
|
||||||
"border-color": "#f85a3e",
|
"border-color": "#f85a3e",
|
||||||
"border-width": "12px",
|
"border-width": "7px",
|
||||||
"transition-property": "border-width",
|
"transition-property": "border-width",
|
||||||
"transition-duration": "0.25s",
|
"transition-duration": "0.25s",
|
||||||
label: "data(label)",
|
label: "data(label)",
|
||||||
|
|||||||
@@ -50,6 +50,12 @@ const theme = createTheme(adaptV4Theme({
|
|||||||
borderRadius: 5,
|
borderRadius: 5,
|
||||||
height: 40,
|
height: 40,
|
||||||
},
|
},
|
||||||
|
DialogStyle: {
|
||||||
|
backgroundColor: "#212121",
|
||||||
|
borderRadius: 2,
|
||||||
|
boxShadow: "0px 0px 10px 0px rgba(0,0,0,0.75)",
|
||||||
|
border: "1px solid #494949",
|
||||||
|
},
|
||||||
innerTextfieldStyle: {
|
innerTextfieldStyle: {
|
||||||
height: 40,
|
height: 40,
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
|
|||||||
+109
-14
@@ -4,13 +4,13 @@ import { toast } from "react-toastify";
|
|||||||
|
|
||||||
const Admin2 = (props) => {
|
const Admin2 = (props) => {
|
||||||
// Destructure props if needed
|
// 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 [selectedTab, setSelectedTab] = useState('editdetails');
|
||||||
const [selectedStatus, setSelectedStatus] = React.useState([]);
|
const [selectedStatus, setSelectedStatus] = React.useState([]);
|
||||||
const [selectedOrganization, setSelectedOrganization] = useState({});
|
const [selectedOrganization, setSelectedOrganization] = useState({});
|
||||||
const [organizationFeatures, setOrganizationFeatures] = useState({});
|
const [organizationFeatures, setOrganizationFeatures] = useState({});
|
||||||
const [orgRequest, setOrgRequest] = React.useState(true);
|
const [orgRequest, setOrgRequest] = React.useState(true);
|
||||||
|
const isCloud = window.location.host === "localhost:3002" || window.location.host === "shuffler.io";
|
||||||
const handleGetOrg = (orgId) => {
|
const handleGetOrg = (orgId) => {
|
||||||
if (
|
if (
|
||||||
serverside !== true &&
|
serverside !== true &&
|
||||||
@@ -51,8 +51,11 @@ const Admin2 = (props) => {
|
|||||||
.then((responseJson) => {
|
.then((responseJson) => {
|
||||||
if (responseJson["success"] === false) {
|
if (responseJson["success"] === false) {
|
||||||
toast(
|
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 {
|
} else {
|
||||||
if (
|
if (
|
||||||
responseJson.sync_features === undefined ||
|
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 = (
|
const handleEditOrg = (
|
||||||
name,
|
name,
|
||||||
description,
|
description,
|
||||||
@@ -159,6 +233,7 @@ const Admin2 = (props) => {
|
|||||||
defaults,
|
defaults,
|
||||||
sso_config,
|
sso_config,
|
||||||
lead_info,
|
lead_info,
|
||||||
|
{ mfa_required } = {}
|
||||||
) => {
|
) => {
|
||||||
const data = {
|
const data = {
|
||||||
name: name,
|
name: name,
|
||||||
@@ -168,6 +243,7 @@ const Admin2 = (props) => {
|
|||||||
defaults: defaults,
|
defaults: defaults,
|
||||||
sso_config: sso_config,
|
sso_config: sso_config,
|
||||||
lead_info: lead_info,
|
lead_info: lead_info,
|
||||||
|
mfa_required: mfa_required !== undefined ? mfa_required : selectedOrganization?.mfa_required,
|
||||||
};
|
};
|
||||||
|
|
||||||
const url = globalUrl + `/api/v1/orgs/${selectedOrganization.id}`;
|
const url = globalUrl + `/api/v1/orgs/${selectedOrganization.id}`;
|
||||||
@@ -202,21 +278,40 @@ const Admin2 = (props) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// useEffect(() => {
|
|
||||||
// handleGetOrg();
|
|
||||||
// }, []);
|
|
||||||
|
|
||||||
const handleStatusChange = (event) => {
|
const handleStatusChange = (event) => {
|
||||||
const { value } = event.target;
|
const { value } = event.target;
|
||||||
setSelectedStatus(value);
|
setSelectedStatus(value);
|
||||||
|
|
||||||
handleEditOrg(
|
handleEditOrg(
|
||||||
"",
|
selectedOrganization?.name,
|
||||||
"",
|
selectedOrganization?.description,
|
||||||
selectedOrganization.id,
|
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,
|
value.length === 0 ? ["none"] : value,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -228,14 +323,14 @@ const Admin2 = (props) => {
|
|||||||
orgRequest
|
orgRequest
|
||||||
) {
|
) {
|
||||||
const orgId = userdata.active_org.id
|
const orgId = userdata.active_org.id
|
||||||
console.log("orgID", orgId)
|
|
||||||
setOrgRequest(false);
|
setOrgRequest(false);
|
||||||
handleGetOrg(orgId);
|
handleGetOrg(orgId);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{ display: 'flex', justifyContent: 'center', paddingTop: 30 }}>
|
<div style={{ display: 'flex', justifyContent: 'center', paddingTop: 29, zoom: 0.8, }}>
|
||||||
<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} />
|
<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>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -422,7 +422,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
const [subworkflow, setSubworkflow] = React.useState({});
|
const [subworkflow, setSubworkflow] = React.useState({});
|
||||||
const [subworkflowStartnode, setSubworkflowStartnode] = React.useState("");
|
const [subworkflowStartnode, setSubworkflowStartnode] = React.useState("");
|
||||||
const [leftViewOpen, setLeftViewOpen] = React.useState(isMobile ? false : true);
|
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 [creatorProfile, setCreatorProfile] = React.useState({});
|
||||||
const [usecases, setUsecases] = React.useState([]);
|
const [usecases, setUsecases] = React.useState([]);
|
||||||
const [files, setFiles] = 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", "node", (e) => onNodeAdded(e));
|
||||||
cy.on("add", "edge", (e) => onEdgeAdded(e));
|
cy.on("add", "edge", (e) => onEdgeAdded(e));
|
||||||
} else {
|
} else {
|
||||||
@@ -4052,7 +4052,7 @@ const releaseToConnectLabel = "Release to Connect"
|
|||||||
.then(() => {
|
.then(() => {
|
||||||
console.log("DONE: ", workflow_id);
|
console.log("DONE: ", workflow_id);
|
||||||
getWorkflow(workflow_id.value, nodedata);
|
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 (nodedata.app_name === "Webhook" || nodedata.app_name === "Schedule" || nodedata.app_name === "Gmail" || nodedata.app_name === "Office365") {
|
||||||
if (!found) {
|
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
|
// Find how many executions it has
|
||||||
var executions = 0
|
var executions = 0
|
||||||
const matchingExecutions = workflowExecutions.filter((execution => execution.execution_source === nodedata.app_name.toLowerCase()))
|
const matchingExecutions = workflowExecutions.filter((execution => execution.execution_source === nodedata.app_name.toLowerCase()))
|
||||||
@@ -6121,7 +6121,7 @@ const releaseToConnectLabel = "Release to Connect"
|
|||||||
event.target.remove()
|
event.target.remove()
|
||||||
|
|
||||||
//console.log("Found branch already!")
|
//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
|
return
|
||||||
|
|
||||||
|
|
||||||
@@ -7782,7 +7782,7 @@ const releaseToConnectLabel = "Release to Connect"
|
|||||||
const item = typeIds[idkey]
|
const item = typeIds[idkey]
|
||||||
if (item.data.id === nodedata.id) {
|
if (item.data.id === nodedata.id) {
|
||||||
//console.log("items: ", item.data.id, nodedata.id)
|
//console.log("items: ", item.data.id, nodedata.id)
|
||||||
parsedStyle["border-width"] = "12px"
|
parsedStyle["border-width"] = "7px"
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -8391,7 +8391,7 @@ const releaseToConnectLabel = "Release to Connect"
|
|||||||
// Reset view for cytoscape
|
// Reset view for cytoscape
|
||||||
if (cy !== undefined && cy !== null) {
|
if (cy !== undefined && cy !== null) {
|
||||||
cy.add(insertedNodes);
|
cy.add(insertedNodes);
|
||||||
cy.fit(null, 200);
|
cy.fit(null, 400);
|
||||||
} else {
|
} else {
|
||||||
setElements(insertedNodes);
|
setElements(insertedNodes);
|
||||||
}
|
}
|
||||||
@@ -8772,7 +8772,7 @@ const releaseToConnectLabel = "Release to Connect"
|
|||||||
}
|
}
|
||||||
// preview: true,
|
// preview: true,
|
||||||
|
|
||||||
cy.fit(null, 200);
|
cy.fit(null, 400)
|
||||||
|
|
||||||
cy.on("boxselect", "node", (e) => {
|
cy.on("boxselect", "node", (e) => {
|
||||||
if (e.target.data("isButton") || e.target.data("isDescriptor") || e.target.data("isSuggestion")) {
|
if (e.target.data("isButton") || e.target.data("isDescriptor") || e.target.data("isSuggestion")) {
|
||||||
@@ -9380,7 +9380,9 @@ const releaseToConnectLabel = "Release to Connect"
|
|||||||
onChange={handleSetTab}
|
onChange={handleSetTab}
|
||||||
aria-label="Left sidebar tab"
|
aria-label="Left sidebar tab"
|
||||||
orientation={isMobile ? "vertical" : "horizontal"}
|
orientation={isMobile ? "vertical" : "horizontal"}
|
||||||
style={{}}
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<Tab
|
<Tab
|
||||||
value={0}
|
value={0}
|
||||||
@@ -9421,7 +9423,7 @@ const releaseToConnectLabel = "Release to Connect"
|
|||||||
<Grid item>
|
<Grid item>
|
||||||
<FavoriteBorderIcon style={iconStyle} />
|
<FavoriteBorderIcon style={iconStyle} />
|
||||||
</Grid>
|
</Grid>
|
||||||
{isMobile ? null : <Grid item>Variables</Grid>}
|
{isMobile ? null : <Grid item>Vars</Grid>}
|
||||||
</Grid>
|
</Grid>
|
||||||
}
|
}
|
||||||
style={tabStyle}
|
style={tabStyle}
|
||||||
@@ -9776,11 +9778,13 @@ const releaseToConnectLabel = "Release to Connect"
|
|||||||
const barHeight = bodyHeight - appBarSize - 50;
|
const barHeight = bodyHeight - appBarSize - 50;
|
||||||
const appScrollStyle = {
|
const appScrollStyle = {
|
||||||
overflow: "scroll",
|
overflow: "scroll",
|
||||||
maxHeight: isMobile ? bodyHeight - appBarSize * 4 : barHeight-300,
|
maxHeight: isMobile ? bodyHeight - appBarSize * 4 : barHeight-70,
|
||||||
minHeight: isMobile ? bodyHeight - appBarSize * 4 : barHeight-300,
|
minHeight: isMobile ? bodyHeight - appBarSize * 4 : barHeight-70,
|
||||||
marginTop: 1,
|
marginTop: 1,
|
||||||
overflowY: "auto",
|
overflowY: "auto",
|
||||||
overflowX: "hidden",
|
overflowX: "hidden",
|
||||||
|
|
||||||
|
zoom: 0.9,
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleAppDrag = (e, app) => {
|
const handleAppDrag = (e, app) => {
|
||||||
@@ -10568,12 +10572,12 @@ const releaseToConnectLabel = "Release to Connect"
|
|||||||
var viewedApps = []
|
var viewedApps = []
|
||||||
return (
|
return (
|
||||||
<div style={appViewStyle}>
|
<div style={appViewStyle}>
|
||||||
<div style={{ flex: "1" }}>
|
<div style={{ flex: "1", zoom: 0.9, }}>
|
||||||
<TextField
|
<TextField
|
||||||
style={{
|
style={{
|
||||||
backgroundColor: theme.palette.inputColor,
|
backgroundColor: theme.palette.inputColor,
|
||||||
borderRadius: theme.palette?.borderRadius,
|
borderRadius: theme.palette?.borderRadius,
|
||||||
marginTop: 5,
|
marginTop: 10,
|
||||||
marginRight: 10,
|
marginRight: 10,
|
||||||
height: 40,
|
height: 40,
|
||||||
}}
|
}}
|
||||||
@@ -11193,14 +11197,12 @@ const releaseToConnectLabel = "Release to Connect"
|
|||||||
overflowAnchor: "none",
|
overflowAnchor: "none",
|
||||||
};
|
};
|
||||||
|
|
||||||
const minSize = 370
|
const minSize = 370
|
||||||
var rightsidebarStyle = {
|
var rightsidebarStyle = {
|
||||||
position: "fixed",
|
position: "fixed",
|
||||||
top: appBarSize - 35,
|
top: appBarSize - 35,
|
||||||
right: 25,
|
right: 25,
|
||||||
height: "90vh",
|
height: "90vh",
|
||||||
width: isMobile ? "100%" : minSize,
|
|
||||||
minWidth: minSize,
|
|
||||||
maxWidth: 600,
|
maxWidth: 600,
|
||||||
maxHeight: "100vh",
|
maxHeight: "100vh",
|
||||||
border: "1px solid rgb(91, 96, 100)",
|
border: "1px solid rgb(91, 96, 100)",
|
||||||
@@ -11210,6 +11212,9 @@ const releaseToConnectLabel = "Release to Connect"
|
|||||||
overflow: "auto",
|
overflow: "auto",
|
||||||
|
|
||||||
overflowAnchor: "none",
|
overflowAnchor: "none",
|
||||||
|
minWidth: minSize,
|
||||||
|
width: isMobile ? "100%" : minSize,
|
||||||
|
zoom: 0.9,
|
||||||
};
|
};
|
||||||
|
|
||||||
const setTriggerFolderWrapperMulti = (event) => {
|
const setTriggerFolderWrapperMulti = (event) => {
|
||||||
@@ -16153,13 +16158,15 @@ const releaseToConnectLabel = "Release to Connect"
|
|||||||
position: "absolute",
|
position: "absolute",
|
||||||
|
|
||||||
top: isMobile ? 30 : 25,
|
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",
|
transition: "left 0.3s ease",
|
||||||
maxWidth: 500,
|
zoom: 0.9,
|
||||||
}
|
}
|
||||||
|
|
||||||
const TopCytoscapeBar = (props) => {
|
const TopCytoscapeBar = (props) => {
|
||||||
|
const [hovered, setHovered] = useState(false)
|
||||||
|
|
||||||
if (workflow.public === true) {
|
if (workflow.public === true) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
@@ -16174,12 +16181,30 @@ const releaseToConnectLabel = "Release to Connect"
|
|||||||
<div style={topBarStyle}>
|
<div style={topBarStyle}>
|
||||||
<div style={{
|
<div style={{
|
||||||
margin: "0px 10px 0px 35px",
|
margin: "0px 10px 0px 35px",
|
||||||
maxWidth: 500,
|
|
||||||
}}>
|
}}>
|
||||||
<Typography variant="h6" style={{
|
<Typography variant="h6" style={{
|
||||||
margin: 0,
|
margin: 0,
|
||||||
}}>
|
cursor: "pointer",
|
||||||
{workflow.name}
|
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>
|
</Typography>
|
||||||
{workflowAsCode && (
|
{workflowAsCode && (
|
||||||
<Tooltip title="Switch to Code View">
|
<Tooltip title="Switch to Code View">
|
||||||
@@ -16204,7 +16229,7 @@ const releaseToConnectLabel = "Release to Connect"
|
|||||||
|
|
||||||
{!distributedFromParent ?
|
{!distributedFromParent ?
|
||||||
isCorrectOrg ? null :
|
isCorrectOrg ? null :
|
||||||
<Typography variant="body1">
|
<Typography variant="body2">
|
||||||
<b>Warning</b>: Change <span
|
<b>Warning</b>: Change <span
|
||||||
style={{color: "#FF8544", cursor: "pointer", pointerEvents: "auto", }}
|
style={{color: "#FF8544", cursor: "pointer", pointerEvents: "auto", }}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
@@ -16275,7 +16300,7 @@ const releaseToConnectLabel = "Release to Connect"
|
|||||||
>Active Organization</span> to edit this Workflow.
|
>Active Organization</span> to edit this Workflow.
|
||||||
</Typography>
|
</Typography>
|
||||||
:
|
:
|
||||||
<Typography variant="body1">
|
<Typography variant="body2" color="textSecondary">
|
||||||
Warning: This workflow is controlled by your parent org and may not be editable.
|
Warning: This workflow is controlled by your parent org and may not be editable.
|
||||||
</Typography>
|
</Typography>
|
||||||
}
|
}
|
||||||
@@ -16285,7 +16310,7 @@ const releaseToConnectLabel = "Release to Connect"
|
|||||||
|
|
||||||
<InputLabel
|
<InputLabel
|
||||||
id="suborg-changer"
|
id="suborg-changer"
|
||||||
style={{ color: "white" }}
|
style={{ color: "rgba(255,255,255,0.7)", }}
|
||||||
>
|
>
|
||||||
Select an Org
|
Select an Org
|
||||||
</InputLabel>
|
</InputLabel>
|
||||||
@@ -16294,10 +16319,15 @@ const releaseToConnectLabel = "Release to Connect"
|
|||||||
pointerEvents: "auto",
|
pointerEvents: "auto",
|
||||||
backgroundColor: theme.palette.inputColor,
|
backgroundColor: theme.palette.inputColor,
|
||||||
color: "white",
|
color: "white",
|
||||||
height: 50,
|
|
||||||
maxWidth: 250,
|
maxWidth: 250,
|
||||||
minWidth: 250,
|
minWidth: 250,
|
||||||
borderRadius: theme.palette?.borderRadius,
|
borderRadius: theme.palette?.borderRadius,
|
||||||
|
height: 40,
|
||||||
|
}}
|
||||||
|
InputProps={{
|
||||||
|
style: {
|
||||||
|
height: 40,
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
labelId="suborg-changer"
|
labelId="suborg-changer"
|
||||||
value={workflow.org_id}
|
value={workflow.org_id}
|
||||||
@@ -16470,47 +16500,16 @@ const releaseToConnectLabel = "Release to Connect"
|
|||||||
</Select>
|
</Select>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
}
|
}
|
||||||
|
</div>
|
||||||
</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>
|
|
||||||
|
|
||||||
{showEnvironment === true && environments.length > 1 && selectedActionEnvironment !== undefined && selectedActionEnvironment !== null && selectedActionEnvironment.Name !== undefined && selectedActionEnvironment.Name !== null ?
|
{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
|
<InputLabel
|
||||||
id="execution_location"
|
id="execution_location"
|
||||||
style={{ color: "white" }}
|
style={{ color: "rgba(255,255,255,0.7)", marginLeft: 40, }}
|
||||||
>
|
>
|
||||||
Execution Location
|
Location
|
||||||
</InputLabel>
|
</InputLabel>
|
||||||
<Select
|
<Select
|
||||||
labelId="execution_location"
|
labelId="execution_location"
|
||||||
@@ -16523,6 +16522,11 @@ const releaseToConnectLabel = "Release to Connect"
|
|||||||
style: {
|
style: {
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
|
InputProps={{
|
||||||
|
style: {
|
||||||
|
height: 40,
|
||||||
|
}
|
||||||
|
}}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
setLastSaved(false)
|
setLastSaved(false)
|
||||||
const env = environments.find((a) => a.Name === e.target.value);
|
const env = environments.find((a) => a.Name === e.target.value);
|
||||||
@@ -16539,13 +16543,14 @@ const releaseToConnectLabel = "Release to Connect"
|
|||||||
}}
|
}}
|
||||||
style={{
|
style={{
|
||||||
pointerEvents: "auto",
|
pointerEvents: "auto",
|
||||||
backgroundColor: theme.palette.inputColor,
|
|
||||||
color: "white",
|
color: "white",
|
||||||
height: 50,
|
|
||||||
maxWidth: 250,
|
maxWidth: 250,
|
||||||
minWidth: 250,
|
minWidth: 250,
|
||||||
borderRadius: theme.palette?.borderRadius,
|
borderRadius: theme.palette?.borderRadius,
|
||||||
marginLeft: 10,
|
marginLeft: 35,
|
||||||
|
|
||||||
|
backgroundColor: theme.palette.inputColor,
|
||||||
|
height: 40,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{environments.map((data, index) => {
|
{environments.map((data, index) => {
|
||||||
@@ -16603,6 +16608,43 @@ const releaseToConnectLabel = "Release to Connect"
|
|||||||
</FormControl>
|
</FormControl>
|
||||||
: null}
|
: 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>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -17210,7 +17252,7 @@ const releaseToConnectLabel = "Release to Connect"
|
|||||||
<Tooltip color="primary" title="Stop execution" placement="top">
|
<Tooltip color="primary" title="Stop execution" placement="top">
|
||||||
<span>
|
<span>
|
||||||
<Button
|
<Button
|
||||||
style={{ height: boxSize, width: boxSize }}
|
style={{ height: boxSize, width: boxSize+5 }}
|
||||||
color="secondary"
|
color="secondary"
|
||||||
variant="contained"
|
variant="contained"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
@@ -17228,7 +17270,7 @@ const releaseToConnectLabel = "Release to Connect"
|
|||||||
workflow.public
|
workflow.public
|
||||||
|| executionRequestStarted
|
|| executionRequestStarted
|
||||||
}
|
}
|
||||||
style={{ height: boxSize, width: boxSize, backgroundColor: green, }}
|
style={{ height: boxSize, width: boxSize+5, backgroundColor: green, }}
|
||||||
color="primary"
|
color="primary"
|
||||||
variant="contained"
|
variant="contained"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
@@ -17265,7 +17307,7 @@ const releaseToConnectLabel = "Release to Connect"
|
|||||||
{executionButton}
|
{executionButton}
|
||||||
<Tooltip
|
<Tooltip
|
||||||
color="secondary"
|
color="secondary"
|
||||||
title={`Show previous runs (${workflowExecutions.length}) (Ctrl + ')`}
|
title={`Show previous workflow runs (${workflowExecutions.length}) (Ctrl + ')`}
|
||||||
placement="top-start"
|
placement="top-start"
|
||||||
>
|
>
|
||||||
<Button
|
<Button
|
||||||
@@ -17492,6 +17534,8 @@ const releaseToConnectLabel = "Release to Connect"
|
|||||||
workflow.configuration.exit_on_error !== undefined ? (
|
workflow.configuration.exit_on_error !== undefined ? (
|
||||||
<WorkflowMenu />
|
<WorkflowMenu />
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
|
{/*
|
||||||
<Tooltip
|
<Tooltip
|
||||||
color="secondary"
|
color="secondary"
|
||||||
title="Edit workflow details"
|
title="Edit workflow details"
|
||||||
@@ -17514,6 +17558,7 @@ const releaseToConnectLabel = "Release to Connect"
|
|||||||
</Button>
|
</Button>
|
||||||
</span>
|
</span>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
*/}
|
||||||
|
|
||||||
<Tooltip
|
<Tooltip
|
||||||
color="secondary"
|
color="secondary"
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
|
||||||
import React, { memo, useCallback } from "react";
|
import React, { memo, useCallback } from "react";
|
||||||
import { useState, useEffect, useContext, Suspense } from "react";
|
import { useState, useEffect, useContext, Suspense } from "react";
|
||||||
import { useNavigate, Link, useLocation } from "react-router-dom";
|
import { useNavigate, Link, useLocation } from "react-router-dom";
|
||||||
@@ -57,7 +58,7 @@ const ApiExplorer = React.lazy(() => import("../components/ApiExplorer.jsx"));
|
|||||||
|
|
||||||
|
|
||||||
const ApiExplorerWrapper = (props) => {
|
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 isCloud = window.location.host === "localhost:3002" || window.location.host === "shuffler.io"
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
@@ -1754,7 +1755,7 @@ const ApiExplorerWrapper = (props) => {
|
|||||||
)});
|
)});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Wrapper userdata={userdata}>
|
<Wrapper isLoggedIn={isLoggedIn} isLoaded={isLoaded}>
|
||||||
<Suspense fallback={skeletonLoader}>
|
<Suspense fallback={skeletonLoader}>
|
||||||
{authenticationModal}
|
{authenticationModal}
|
||||||
<ApiExplorer
|
<ApiExplorer
|
||||||
@@ -1765,6 +1766,8 @@ const ApiExplorerWrapper = (props) => {
|
|||||||
HandleApiExecution={HandleApiExecution}
|
HandleApiExecution={HandleApiExecution}
|
||||||
selectedAppData={selectedAppData}
|
selectedAppData={selectedAppData}
|
||||||
ConfigurationTab={ConfigurationTab}
|
ConfigurationTab={ConfigurationTab}
|
||||||
|
isLoggedIn={isLoggedIn}
|
||||||
|
isLoaded={isLoaded}
|
||||||
/>
|
/>
|
||||||
</Suspense>
|
</Suspense>
|
||||||
</Wrapper>
|
</Wrapper>
|
||||||
@@ -1774,13 +1777,13 @@ const ApiExplorerWrapper = (props) => {
|
|||||||
export default ApiExplorerWrapper;
|
export default ApiExplorerWrapper;
|
||||||
|
|
||||||
|
|
||||||
const Wrapper = ({children, userdata})=>{
|
const Wrapper = ({children, isLoaded,isLoggedIn})=>{
|
||||||
|
|
||||||
const { leftSideBarOpenByClick } = useContext(Context);
|
const { leftSideBarOpenByClick } = useContext(Context);
|
||||||
|
|
||||||
return(
|
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}
|
{children}
|
||||||
</div>
|
</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 {leftSideBarOpenByClick } = useContext(Context)
|
||||||
const marginLeft = userdata?.support
|
|
||||||
? leftSideBarOpenByClick ? 250 : 80
|
|
||||||
: 0;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{ marginLeft, transition: 'margin-left 0.3s ease' }}>
|
<div style={{ marginLeft: leftSideBarOpenByClick ? 250 : 80, transition: 'margin-left 0.3s ease' }}>
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
+477
-311
File diff suppressed because it is too large
Load Diff
@@ -274,7 +274,8 @@ const CodeWorkflow = (defaultprops) => {
|
|||||||
display: 'flex',
|
display: 'flex',
|
||||||
flexDirection: 'column',
|
flexDirection: 'column',
|
||||||
height: '100vh', // Set to full viewport height
|
height: '100vh', // Set to full viewport height
|
||||||
backgroundColor: '#252526'
|
backgroundColor: '#252526',
|
||||||
|
marginLeft: '100px',
|
||||||
}}>
|
}}>
|
||||||
{/* IDE-like toolbar */}
|
{/* IDE-like toolbar */}
|
||||||
<Toolbar
|
<Toolbar
|
||||||
|
|||||||
@@ -337,11 +337,23 @@ const Dashboard = (props) => {
|
|||||||
const [, setUpdate] = useState(0);
|
const [, setUpdate] = useState(0);
|
||||||
|
|
||||||
let navigate = useNavigate();
|
let navigate = useNavigate();
|
||||||
const isCloud =
|
const isCloud = window.location.host === "localhost:3002" || window.location.host === "shuffler.io";
|
||||||
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(() => {
|
useEffect(() => {
|
||||||
|
// Look for the path. If it is automation, go to usecases
|
||||||
|
// Handles redirect
|
||||||
|
|
||||||
const widgetnames = ["app_executions_cloud"]
|
const widgetnames = ["app_executions_cloud"]
|
||||||
for (let widgetkey in widgetnames) {
|
for (let widgetkey in widgetnames) {
|
||||||
const widgetName = widgetnames[widgetkey]
|
const widgetName = widgetnames[widgetkey]
|
||||||
@@ -859,7 +871,7 @@ const Dashboard = (props) => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const dataWrapper = (
|
const dataWrapper = (
|
||||||
<div style={{ maxWidth: 1366, margin: "auto" }}>{data}</div>
|
<div style={{ maxWidth: 1366, margin: "auto", paddingTop: 10, }}>{data}</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
return dataWrapper;
|
return dataWrapper;
|
||||||
|
|||||||
@@ -251,7 +251,7 @@ export const CodeHandler = (props) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const Docs = (defaultprops) => {
|
const Docs = (defaultprops) => {
|
||||||
const { globalUrl, selectedDoc, serverside, serverMobile, userdata } = defaultprops;
|
const { globalUrl, selectedDoc, serverside, serverMobile, isLoggedIn, isLoaded } = defaultprops;
|
||||||
let navigate = useNavigate();
|
let navigate = useNavigate();
|
||||||
// Quickfix for react router 5 -> 6
|
// Quickfix for react router 5 -> 6
|
||||||
const params = useParams();
|
const params = useParams();
|
||||||
@@ -1266,7 +1266,7 @@ const Docs = (defaultprops) => {
|
|||||||
|
|
||||||
// Padding and zIndex etc set because of footer in cloud.
|
// Padding and zIndex etc set because of footer in cloud.
|
||||||
const loadedCheck = (
|
const loadedCheck = (
|
||||||
<DocsWrapper userdata={userdata}>
|
<DocsWrapper isLoggedIn={isLoggedIn} isLoaded={isLoaded}>
|
||||||
<DocsContent postDataBrowser={postDataBrowser} postDataMobile={postDataMobile}/>
|
<DocsContent postDataBrowser={postDataBrowser} postDataMobile={postDataMobile}/>
|
||||||
</DocsWrapper>
|
</DocsWrapper>
|
||||||
);
|
);
|
||||||
@@ -1285,18 +1285,18 @@ const DocsContent = memo(({postDataBrowser, postDataMobile}) => {
|
|||||||
</div>
|
</div>
|
||||||
)})
|
)})
|
||||||
|
|
||||||
const DocsWrapper = memo(({userdata, children })=>{
|
const DocsWrapper = memo(({isLoggedIn, isLoaded, children })=>{
|
||||||
|
|
||||||
const { leftSideBarOpenByClick, windowWidth } = useContext(Context);
|
const { leftSideBarOpenByClick, windowWidth } = useContext(Context);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{
|
<div style={{
|
||||||
minHeight: 1000, zIndex: 1,
|
minHeight: 1000, zIndex: 1,
|
||||||
maxWidth: Math.min(leftSideBarOpenByClick ? windowWidth - 300 : windowWidth - 200, 1920),
|
maxWidth: Math.min(!(isLoggedIn && isLoaded) ? 1920 : leftSideBarOpenByClick ? windowWidth - 300 : windowWidth - 200, 1920),
|
||||||
minWidth: isMobile ? null : leftSideBarOpenByClick ? 800 : 900, margin: "auto",
|
minWidth: isMobile ? null : (isLoggedIn && isLoaded) ? leftSideBarOpenByClick ? 800 : 900 : null, margin: "auto",
|
||||||
position: leftSideBarOpenByClick ? "relative" : "static",
|
position: (isLoggedIn && isLoaded) && leftSideBarOpenByClick ? "relative" : "static",
|
||||||
left: leftSideBarOpenByClick ? 120 : !leftSideBarOpenByClick ? 80 : 0,
|
left: (isLoggedIn && isLoaded) && leftSideBarOpenByClick ? 120 : (isLoggedIn && isLoaded) && !leftSideBarOpenByClick ? 80 : 0,
|
||||||
marginLeft: windowWidth < 1920 ? leftSideBarOpenByClick ? 160 : !leftSideBarOpenByClick ? 80 : 0 : "auto", width: "100%",
|
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"
|
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}
|
{children}
|
||||||
|
|||||||
@@ -108,7 +108,6 @@ const RunWorkflow = (defaultprops) => {
|
|||||||
const boxStyle = {
|
const boxStyle = {
|
||||||
color: "white",
|
color: "white",
|
||||||
padding: "25px 50px 50px 50px",
|
padding: "25px 50px 50px 50px",
|
||||||
backgroundColor: theme.palette.surfaceColor,
|
|
||||||
borderRadius: 25,
|
borderRadius: 25,
|
||||||
minHeight: 500,
|
minHeight: 500,
|
||||||
}
|
}
|
||||||
@@ -1116,7 +1115,7 @@ const RunWorkflow = (defaultprops) => {
|
|||||||
|
|
||||||
const ExplorerUi = () => {
|
const ExplorerUi = () => {
|
||||||
return (
|
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 ?
|
{forms !== undefined && forms !== null && forms.length > 0 ?
|
||||||
<div>
|
<div>
|
||||||
@@ -1126,9 +1125,14 @@ const RunWorkflow = (defaultprops) => {
|
|||||||
<FormList />
|
<FormList />
|
||||||
</div>
|
</div>
|
||||||
:
|
:
|
||||||
<Typography variant="h6" style={{marginTop: 100, marginBottom: 20, }}>
|
<div>
|
||||||
No Form Found
|
<Typography variant="h4" style={{marginTop: 125, marginBottom: 25, }}>
|
||||||
</Typography>
|
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>
|
</div>
|
||||||
)
|
)
|
||||||
@@ -1474,7 +1478,7 @@ const RunWorkflow = (defaultprops) => {
|
|||||||
|
|
||||||
{workflowQuestion !== "" ? null :
|
{workflowQuestion !== "" ? null :
|
||||||
<Typography variant="body2" color="textSecondary" align="center" style={{marginTop: 10, }} >
|
<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>
|
</Typography>
|
||||||
}
|
}
|
||||||
</div>
|
</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 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 ?
|
const loadedCheck = isLoaded ?
|
||||||
<div style={{marginTop: 30, }}>
|
<div style={{paddingTop: 60, }}>
|
||||||
{editWorkflowModalOpen === true ?
|
{editWorkflowModalOpen === true ?
|
||||||
<EditWorkflow
|
<EditWorkflow
|
||||||
saveWorkflow={saveWorkflow}
|
saveWorkflow={saveWorkflow}
|
||||||
@@ -1570,6 +1574,7 @@ const RunWorkflow = (defaultprops) => {
|
|||||||
<div style={{position: "fixed", top: 10, right: 20, }}>
|
<div style={{position: "fixed", top: 10, right: 20, }}>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
|
disabled={workflow.id === undefined || workflow.id === null}
|
||||||
variant={"outlined"}
|
variant={"outlined"}
|
||||||
color={"secondary"}
|
color={"secondary"}
|
||||||
style={{marginRight: 10, }}
|
style={{marginRight: 10, }}
|
||||||
@@ -1582,6 +1587,7 @@ const RunWorkflow = (defaultprops) => {
|
|||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
|
disabled={workflow.id === undefined || workflow.id === null}
|
||||||
variant={workflow.sharing === "form" ? "outlined" : "contained"}
|
variant={workflow.sharing === "form" ? "outlined" : "contained"}
|
||||||
color={"secondary"}
|
color={"secondary"}
|
||||||
style={{marginRight: 10, }}
|
style={{marginRight: 10, }}
|
||||||
@@ -1603,6 +1609,7 @@ const RunWorkflow = (defaultprops) => {
|
|||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
|
disabled={workflow.id === undefined || workflow.id === null}
|
||||||
variant={"contained"}
|
variant={"contained"}
|
||||||
color={"primary"}
|
color={"primary"}
|
||||||
style={{}}
|
style={{}}
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ const Search = (props) => {
|
|||||||
userdata={userdata}
|
userdata={userdata}
|
||||||
/>, [curTab]);
|
/>, [curTab]);
|
||||||
|
|
||||||
const MemoizedDiscordChat = useMemo(() => <DiscordChat isMobile={isMobile} />)
|
const MemoizedDiscordChat = useMemo(() => <DiscordChat isMobile={isMobile} />, [curTab])
|
||||||
|
|
||||||
const useStyles = makeStyles({
|
const useStyles = makeStyles({
|
||||||
hideIndicator: {
|
hideIndicator: {
|
||||||
|
|||||||
@@ -1220,7 +1220,7 @@ const Usecases2 = (props) => {
|
|||||||
) : null
|
) : null
|
||||||
|
|
||||||
const data =
|
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
|
<UsecaseListComponent
|
||||||
userdata={userdata}
|
userdata={userdata}
|
||||||
@@ -1241,7 +1241,7 @@ const Usecases2 = (props) => {
|
|||||||
|
|
||||||
const dataWrapper =
|
const dataWrapper =
|
||||||
<Fade in={true} timeout={1250}>
|
<Fade in={true} timeout={1250}>
|
||||||
<div style={{ maxWidth: 1366, margin: "auto", }}>
|
<div style={{ maxWidth: 1366, margin: "auto", zoom: 0.8, }}>
|
||||||
{data}
|
{data}
|
||||||
</div>
|
</div>
|
||||||
</Fade>
|
</Fade>
|
||||||
|
|||||||
+486
-488
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user