Added statistics to both backend and frontend + cloud sync
This commit is contained in:
@@ -1692,15 +1692,24 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user
|
||||
const userId = user.id;
|
||||
const data = { user_id: userId };
|
||||
|
||||
fetch(globalUrl + "/api/v1/generateapikey", {
|
||||
console.log(user, userdata)
|
||||
|
||||
var fetchdata = {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Accept: "application/json",
|
||||
},
|
||||
body: JSON.stringify(data),
|
||||
credentials: "include",
|
||||
})
|
||||
}
|
||||
|
||||
if (userId === userdata.id) {
|
||||
fetchdata.method = "GET"
|
||||
} else {
|
||||
fetchdata.body = JSON.stringify(data)
|
||||
}
|
||||
|
||||
fetch(globalUrl + "/api/v1/generateapikey", fetchdata)
|
||||
.then((response) => {
|
||||
if (response.status !== 200) {
|
||||
console.log("Status not 200 for WORKFLOW EXECUTION :O!");
|
||||
@@ -1889,8 +1898,11 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user
|
||||
open={selectedUserModalOpen}
|
||||
onClose={() => {
|
||||
setSelectedUserModalOpen(false);
|
||||
setImage2FA("");
|
||||
setSecret2FA("");
|
||||
|
||||
setImage2FA("");
|
||||
setValue2FA("");
|
||||
setSecret2FA("");
|
||||
setShow2faSetup(false);
|
||||
}}
|
||||
PaperProps={{
|
||||
style: {
|
||||
@@ -2156,7 +2168,7 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user
|
||||
<Card
|
||||
style={{
|
||||
margin: 4,
|
||||
backgroundColor: theme.palette.inputColor,
|
||||
backgroundColor: theme.palette.surfaceColor,
|
||||
color: "white",
|
||||
minHeight: expanded ? 250 : "inherit",
|
||||
maxHeight: expanded ? 250 : "inherit",
|
||||
@@ -2515,9 +2527,8 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user
|
||||
</span>
|
||||
/>
|
||||
<Tab
|
||||
disabled={!isCloud}
|
||||
label=<span>
|
||||
Billing
|
||||
Billing (Beta)
|
||||
</span>
|
||||
/>
|
||||
<Tab
|
||||
@@ -3246,10 +3257,8 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user
|
||||
selectedOrganization.child_orgs !== null &&
|
||||
selectedOrganization.child_orgs.length > 0
|
||||
) {
|
||||
console.log("In here?");
|
||||
var active = [];
|
||||
for (var key in userdata.orgs) {
|
||||
console.log("ORG: ", userdata.orgs[key]);
|
||||
const found =
|
||||
selectedOrganization.child_orgs.find(
|
||||
(item) => item.id === userdata.orgs[key].id
|
||||
@@ -3299,7 +3308,6 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user
|
||||
) : null;
|
||||
|
||||
const run2FASetup = (data) => {
|
||||
console.log("2fa: ", data, show2faSetup);
|
||||
if (!show2faSetup) {
|
||||
get2faCode(data.id);
|
||||
} else {
|
||||
|
||||
@@ -580,15 +580,39 @@ const AngularWorkflow = (defaultprops) => {
|
||||
const cytoscapeWidth = isMobile ? bodyWidth - leftBarSize : bodyWidth - leftBarSize - 25
|
||||
|
||||
const [elements, setElements] = useState([]);
|
||||
const [loopRunning, setLoopRunning] = useState(false)
|
||||
|
||||
const stop = () => {
|
||||
setLoopRunning(false)
|
||||
}
|
||||
|
||||
const start = () => {
|
||||
setLoopRunning(true)
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
console.log("In useeffect for loopRunning: ", loopRunning)
|
||||
if (loopRunning) {
|
||||
const intervalId = setInterval(() => {
|
||||
if (!loopRunning) {
|
||||
clearInterval(intervalId);
|
||||
}
|
||||
|
||||
fetchUpdates()
|
||||
}, 3000)
|
||||
|
||||
return () => clearInterval(intervalId);
|
||||
}
|
||||
}, [loopRunning])
|
||||
|
||||
// No point going as fast, as the nodes aren't realtime anymore, but bulk updated.
|
||||
// Set it from 2500 to 6000 to reduce overall load
|
||||
const { start, stop } = useInterval({
|
||||
duration: 3000,
|
||||
startImmediate: false,
|
||||
callback: () => {
|
||||
fetchUpdates();
|
||||
},
|
||||
});
|
||||
//const { start, stop } = useInterval({
|
||||
// duration: 3000,
|
||||
// startImmediate: false,
|
||||
// callback: () => {
|
||||
// fetchUpdates();
|
||||
// },
|
||||
//});
|
||||
|
||||
const getAppDocs = (appname, location, version) => {
|
||||
fetch(`${globalUrl}/api/v1/docs/${appname}?location=${location}&version=${version}`, {
|
||||
@@ -924,7 +948,7 @@ const AngularWorkflow = (defaultprops) => {
|
||||
};
|
||||
|
||||
const getWorkflowExecution = (id, execution_id) => {
|
||||
fetch(`${globalUrl}/api/v1/workflows/${id}/executions`, {
|
||||
fetch(`${globalUrl}/api/v2/workflows/${id}/executions`, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
@@ -940,11 +964,10 @@ const AngularWorkflow = (defaultprops) => {
|
||||
return response.json();
|
||||
})
|
||||
.then((responseJson) => {
|
||||
if (responseJson !== undefined && responseJson !== null && responseJson.length > 0) {
|
||||
// FIXME: Sort this by time
|
||||
if (responseJson !== undefined && responseJson !== null && responseJson.executions !== undefined && responseJson.executions !== null && responseJson.executions.length > 0) {
|
||||
|
||||
// - means it's opposite
|
||||
const newkeys = sortByKey(responseJson, "-started_at");
|
||||
const newkeys = sortByKey(responseJson.executions, "-started_at");
|
||||
setWorkflowExecutions(newkeys);
|
||||
|
||||
const cursearch = typeof window === "undefined" || window.location === undefined ? "" : window.location.search;
|
||||
@@ -1021,6 +1044,7 @@ const AngularWorkflow = (defaultprops) => {
|
||||
},
|
||||
body: JSON.stringify(executionRequest),
|
||||
credentials: "include",
|
||||
cors: "no-cors",
|
||||
})
|
||||
.then((response) => {
|
||||
if (response.status !== 200) {
|
||||
@@ -1279,7 +1303,7 @@ const AngularWorkflow = (defaultprops) => {
|
||||
};
|
||||
|
||||
const sendStreamRequest = (body) => {
|
||||
console.log("Stream not activated yet.")
|
||||
//console.log("Stream not activated yet.")
|
||||
return
|
||||
|
||||
// Session may be important here huh
|
||||
@@ -15302,6 +15326,10 @@ const AngularWorkflow = (defaultprops) => {
|
||||
overflow: "hidden",
|
||||
}}
|
||||
onMouseOver={() => {
|
||||
if (cy == undefined || cy == null) {
|
||||
return
|
||||
}
|
||||
|
||||
var currentnode = cy.getElementById(data.action.id);
|
||||
if (currentnode !== undefined && currentnode !== null && currentnode.length !== 0) {
|
||||
currentnode.addClass("shuffle-hover-highlight");
|
||||
@@ -15314,6 +15342,10 @@ const AngularWorkflow = (defaultprops) => {
|
||||
//)
|
||||
}}
|
||||
onMouseOut={() => {
|
||||
if (cy == undefined || cy == null) {
|
||||
return
|
||||
}
|
||||
|
||||
var currentnode = cy.getElementById(data.action.id);
|
||||
if (currentnode.length !== 0) {
|
||||
currentnode.removeClass("shuffle-hover-highlight");
|
||||
|
||||
@@ -1354,7 +1354,8 @@ const Apps = (props) => {
|
||||
border: hover ? "1px solid #f85a3e" : "1px solid rgba(255,255,255,0.3)",
|
||||
cursor: hover ? "pointer" : "default",
|
||||
textAlign: "center",
|
||||
height: 125,
|
||||
minHeight: 150,
|
||||
maxHeight: 150,
|
||||
}}
|
||||
>
|
||||
{icon}
|
||||
|
||||
+181
-121
@@ -6,6 +6,7 @@ import { makeStyles, } from "@mui/styles";
|
||||
import classNames from "classnames";
|
||||
import theme from '../theme.jsx';
|
||||
import { useNavigate, Link, useParams } from "react-router-dom";
|
||||
import WorkflowTemplatePopup from "../components/WorkflowTemplatePopup.jsx";
|
||||
|
||||
// react plugin used to create charts
|
||||
//import { Line, Bar } from "react-chartjs-2";
|
||||
@@ -90,7 +91,7 @@ const useStyles = makeStyles({
|
||||
},
|
||||
});
|
||||
|
||||
const UsecaseListComponent = ({keys, isCloud, globalUrl, frameworkData, isLoggedIn, workflows, setWorkflows}) => {
|
||||
const UsecaseListComponent = ({userdata, keys, isCloud, globalUrl, frameworkData, isLoggedIn, workflows, setWorkflows}) => {
|
||||
const [expandedIndex, setExpandedIndex] = useState(-1);
|
||||
const [expandedItem, setExpandedItem] = useState(-1);
|
||||
const [inputUsecase, setInputUsecase] = useState({});
|
||||
@@ -103,17 +104,69 @@ const UsecaseListComponent = ({keys, isCloud, globalUrl, frameworkData, isLogged
|
||||
|
||||
const [selectedWorkflows, setSelectedWorkflows] = useState([])
|
||||
const [firstLoad, setFirstLoad] = useState(true)
|
||||
const [apps, setApps] = useState([])
|
||||
|
||||
const classes = useStyles();
|
||||
const classes = useStyles();
|
||||
let navigate = useNavigate();
|
||||
|
||||
const [mitreTags, setMitreTags] = useState([]);
|
||||
|
||||
const loadApps = () => {
|
||||
fetch(`${globalUrl}/api/v1/apps`, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Accept: "application/json",
|
||||
},
|
||||
credentials: "include",
|
||||
})
|
||||
.then((response) => {
|
||||
return response.json();
|
||||
})
|
||||
.then((responseJson) => {
|
||||
if (responseJson === null) {
|
||||
console.log("null-response from server")
|
||||
const pretend_apps = [{
|
||||
"name": "TBD",
|
||||
"app_name": "TBD",
|
||||
"app_version": "TBD",
|
||||
"description": "TBD",
|
||||
"version": "TBD",
|
||||
"large_image": "",
|
||||
}]
|
||||
|
||||
setApps(pretend_apps)
|
||||
return
|
||||
}
|
||||
|
||||
if (responseJson.success === false) {
|
||||
console.log("error loading apps: ", responseJson)
|
||||
return
|
||||
}
|
||||
|
||||
setApps(responseJson);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log("App loading error: " + error.toString());
|
||||
})
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
loadApps()
|
||||
}, [])
|
||||
|
||||
if (keys === undefined || keys === null || keys.length === 0) {
|
||||
return null
|
||||
}
|
||||
|
||||
const getUsecase = (name, index, subindex) => {
|
||||
fetch(`${globalUrl}/api/v1/workflows/usecases/${escape(name.replaceAll(" ", "_"))}`, {
|
||||
const parseUsecase = (parsedUsecase, subcase) => {
|
||||
console.log("parseUsecase: ", parsedUsecase, subcase)
|
||||
}
|
||||
|
||||
const getUsecase = (subcase, index, subindex) => {
|
||||
console.log(subcase)
|
||||
|
||||
fetch(`${globalUrl}/api/v1/workflows/usecases/${escape(subcase.name.replaceAll(" ", "_"))}`, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
@@ -129,14 +182,26 @@ const UsecaseListComponent = ({keys, isCloud, globalUrl, frameworkData, isLogged
|
||||
return response.json();
|
||||
})
|
||||
.then((responseJson) => {
|
||||
var parsedUsecase = responseJson
|
||||
if (responseJson.success === false) {
|
||||
setInputUsecase({
|
||||
"name": name,
|
||||
})
|
||||
parsedUsecase = subcase
|
||||
|
||||
//img1={inputUsecase.srcimg}
|
||||
//srcapp={inputUsecase.srcapp}
|
||||
//img2={inputUsecase.dstimg}
|
||||
//dstapp={inputUsecase.dstapp}
|
||||
//title={inputUsecase.name}
|
||||
parsedUsecase = parseUsecase(parsedUsecase, subcase)
|
||||
} else {
|
||||
setInputUsecase(responseJson)
|
||||
parsedUsecase = responseJson
|
||||
|
||||
parsedUsecase = parseUsecase(parsedUsecase, responseJson)
|
||||
}
|
||||
|
||||
// Look for the type of app and fill in img1, srcapp...
|
||||
|
||||
|
||||
setInputUsecase(parsedUsecase)
|
||||
setExpandedIndex(index)
|
||||
setExpandedItem(subindex)
|
||||
|
||||
@@ -289,6 +354,7 @@ const UsecaseListComponent = ({keys, isCloud, globalUrl, frameworkData, isLogged
|
||||
if (selectedItem && subcase.matches.length > 0 && selectedWorkflows.length === 0 && firstLoad === true) {
|
||||
setFirstLoad(false)
|
||||
setSelectedWorkflows(subcase.matches)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -316,10 +382,8 @@ const UsecaseListComponent = ({keys, isCloud, globalUrl, frameworkData, isLogged
|
||||
}
|
||||
}
|
||||
|
||||
//const backgroundColor = selectedItem ? "inherit" : finished ? "inherit" : usecase.color
|
||||
const finished = subcase.matches.length > 0
|
||||
const backgroundColor = theme.palette.surfaceColor
|
||||
//"inherit"
|
||||
const itemBorder = `${selectedItem ? "3px" : expandedItem >= 0 ? "0px" : "1px"} solid ${usecase.color}`
|
||||
|
||||
const fixedName = subcase.name.toLowerCase().replace("_", " ")
|
||||
@@ -330,14 +394,14 @@ const UsecaseListComponent = ({keys, isCloud, globalUrl, frameworkData, isLogged
|
||||
//setSelectedWorkflows([])
|
||||
if (selectedItem) {
|
||||
} else {
|
||||
getUsecase(subcase.name, index, subindex)
|
||||
getUsecase(subcase, index, subindex)
|
||||
navigate(`/usecases?selected_object=${fixedName}`)
|
||||
|
||||
//const newitem = removeParam("selected_object", cursearch);
|
||||
//navigate(curpath + newitem)
|
||||
}
|
||||
}}>
|
||||
<Paper style={{padding: 25, minHeight: 75, cursor: !selectedItem ? "pointer" : "default", border: itemBorder, backgroundColor: backgroundColor,}} onClick={() => {
|
||||
<Paper style={{padding: 25, minHeight: isCloud ? 75 : 122, cursor: !selectedItem ? "pointer" : "default", border: itemBorder, backgroundColor: backgroundColor,}} onClick={() => {
|
||||
}}>
|
||||
{!selectedItem ?
|
||||
<div style={{textAlign: "left", position: "relative",}}>
|
||||
@@ -649,12 +713,12 @@ const UsecaseListComponent = ({keys, isCloud, globalUrl, frameworkData, isLogged
|
||||
: null}
|
||||
|
||||
{workflows !== undefined && workflows !== null && workflows.length > 0 ?
|
||||
<Autocomplete
|
||||
multiple
|
||||
<Autocomplete
|
||||
multiple
|
||||
id="workflow_matching"
|
||||
options={workflows}
|
||||
autoHighlight
|
||||
value={selectedWorkflows}
|
||||
value={selectedWorkflows}
|
||||
classes={{ inputRoot: classes.inputRoot }}
|
||||
ListboxProps={{
|
||||
style: {
|
||||
@@ -662,7 +726,7 @@ const UsecaseListComponent = ({keys, isCloud, globalUrl, frameworkData, isLogged
|
||||
color: "white",
|
||||
},
|
||||
}}
|
||||
getOptionSelected={(option, value) => option.id === value.id}
|
||||
getOptionSelected={(option, value) => option.id === value.id}
|
||||
getOptionLabel={(option) => {
|
||||
|
||||
if (
|
||||
@@ -685,120 +749,120 @@ const UsecaseListComponent = ({keys, isCloud, globalUrl, frameworkData, isLogged
|
||||
borderRadius: theme.palette.borderRadius,
|
||||
}}
|
||||
onChange={(event, newValue) => {
|
||||
console.log("CLICK: ", newValue)
|
||||
//handleWorkflowSelectionUpdate({ target: { value: newValue} })
|
||||
//setSelectedWorkflows=
|
||||
//var newvalue = []
|
||||
//for (var key in newValue) {
|
||||
// if (newValue[key].id !== undefined) {
|
||||
// newvalue.push(newValue[key].id)
|
||||
// }
|
||||
//}
|
||||
console.log("CLICK: ", newValue)
|
||||
//handleWorkflowSelectionUpdate({ target: { value: newValue} })
|
||||
//setSelectedWorkflows=
|
||||
//var newvalue = []
|
||||
//for (var key in newValue) {
|
||||
// if (newValue[key].id !== undefined) {
|
||||
// newvalue.push(newValue[key].id)
|
||||
// }
|
||||
//}
|
||||
|
||||
// Doing this way as you may want to remove some too
|
||||
for (var key in workflows) {
|
||||
if (!newValue.find(data => data.id === workflows[key].id)) {
|
||||
// Check if it has the one in it
|
||||
if (workflows[key]["usecase_ids"] !== undefined && workflows[key]["usecase_ids"] !== null && workflows[key]["usecase_ids"].includes(subcase.name)) {
|
||||
const filtered = workflows[key]["usecase_ids"].filter(data => data !== subcase.name)
|
||||
if (filtered !== undefined && filtered !== null) {
|
||||
//console.log("Removing: ", workflows[key].name, workflows[key])
|
||||
workflows[key]["usecase_ids"] = filtered
|
||||
|
||||
setWorkflow(workflows[key])
|
||||
}
|
||||
}
|
||||
// Doing this way as you may want to remove some too
|
||||
for (var key in workflows) {
|
||||
if (!newValue.find(data => data.id === workflows[key].id)) {
|
||||
// Check if it has the one in it
|
||||
if (workflows[key]["usecase_ids"] !== undefined && workflows[key]["usecase_ids"] !== null && workflows[key]["usecase_ids"].includes(subcase.name)) {
|
||||
const filtered = workflows[key]["usecase_ids"].filter(data => data !== subcase.name)
|
||||
if (filtered !== undefined && filtered !== null) {
|
||||
//console.log("Removing: ", workflows[key].name, workflows[key])
|
||||
workflows[key]["usecase_ids"] = filtered
|
||||
|
||||
setWorkflow(workflows[key])
|
||||
}
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if (workflows[key]["usecase_ids"] === undefined || workflows[key]["usecase_ids"] === null) {
|
||||
workflows[key]["usecase_ids"] = [subcase.name]
|
||||
console.log("Setting: ", workflows[key].name)
|
||||
setWorkflow(workflows[key])
|
||||
if (workflows[key]["usecase_ids"] === undefined || workflows[key]["usecase_ids"] === null) {
|
||||
workflows[key]["usecase_ids"] = [subcase.name]
|
||||
console.log("Setting: ", workflows[key].name)
|
||||
setWorkflow(workflows[key])
|
||||
|
||||
} else if (!workflows[key]["usecase_ids"].includes(subcase.name)) {
|
||||
workflows[key]["usecase_ids"].push(subcase.name)
|
||||
console.log("Adding: ", workflows[key].name)
|
||||
setWorkflow(workflows[key])
|
||||
} else if (!workflows[key]["usecase_ids"].includes(subcase.name)) {
|
||||
workflows[key]["usecase_ids"].push(subcase.name)
|
||||
console.log("Adding: ", workflows[key].name)
|
||||
setWorkflow(workflows[key])
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setWorkflows(workflows)
|
||||
console.log("New: ", newValue)
|
||||
setSelectedWorkflows(newValue)
|
||||
setWorkflows(workflows)
|
||||
console.log("New: ", newValue)
|
||||
setSelectedWorkflows(newValue)
|
||||
//setUpdate(Math.random())
|
||||
}}
|
||||
renderOption={(props, option) => {
|
||||
//console.log("In options?: ", props, option)
|
||||
renderOption={(props, data, state) => {
|
||||
var newname = data.name
|
||||
if (newname === undefined || newname === null) {
|
||||
newname = "placeholder"
|
||||
}
|
||||
|
||||
var newname = props.name
|
||||
if (newname === undefined || newname === null) {
|
||||
newname = "placeholder"
|
||||
}
|
||||
|
||||
if (newname.length > 2) {
|
||||
newname = newname.charAt(0).toUpperCase() + newname.substring(1)
|
||||
}
|
||||
return (
|
||||
<li {...props}>
|
||||
<Tooltip arrow placement="left" title={
|
||||
<span style={{}}>
|
||||
{props.image !== undefined && props.image !== null && props.image.length > 0 ?
|
||||
<img src={props.image} alt={newname} style={{backgroundColor: theme.palette.surfaceColor, maxHeight: 200, minHeigth: 200, borderRadius: theme.palette.borderRadius, }} />
|
||||
: null}
|
||||
<Typography>
|
||||
Choose {newname}
|
||||
</Typography>
|
||||
</span>
|
||||
} placement="bottom">
|
||||
<span>
|
||||
<Checkbox
|
||||
icon={<CheckBoxOutlineBlankIcon fontSize="small" />}
|
||||
checkedIcon={<CheckBoxIcon fontSize="small" />}
|
||||
style={{ marginRight: 8 }}
|
||||
checked={option.selected}
|
||||
/>
|
||||
{newname}
|
||||
</span>
|
||||
</Tooltip>
|
||||
</li>
|
||||
)
|
||||
}}
|
||||
if (newname.length > 2) {
|
||||
newname = newname.charAt(0).toUpperCase() + newname.substring(1)
|
||||
}
|
||||
return (
|
||||
<li {...props}>
|
||||
<Tooltip arrow placement="left" title={
|
||||
<span style={{}}>
|
||||
{data.image !== undefined && data.image !== null && data.image.length > 0 ?
|
||||
<img src={data.image} alt={newname} style={{backgroundColor: theme.palette.surfaceColor, maxHeight: 200, minHeigth: 200, borderRadius: theme.palette.borderRadius, }} />
|
||||
: null}
|
||||
<Typography>
|
||||
Choose {newname}
|
||||
</Typography>
|
||||
</span>
|
||||
} placement="bottom">
|
||||
<span>
|
||||
<Checkbox
|
||||
icon={<CheckBoxOutlineBlankIcon fontSize="small" />}
|
||||
checkedIcon={<CheckBoxIcon fontSize="small" />}
|
||||
style={{ marginRight: 8 }}
|
||||
checked={selectedWorkflows.find(wf => wf.id === data.id) !== undefined}
|
||||
/>
|
||||
{newname}
|
||||
</span>
|
||||
</Tooltip>
|
||||
</li>
|
||||
)
|
||||
}}
|
||||
renderInput={(params) => {
|
||||
return (
|
||||
<TextField
|
||||
style={{
|
||||
backgroundColor: theme.palette.inputColor,
|
||||
borderRadius: theme.palette.borderRadius,
|
||||
}}
|
||||
{...params}
|
||||
label="Find your workflows"
|
||||
variant="outlined"
|
||||
<TextField
|
||||
style={{
|
||||
backgroundColor: theme.palette.inputColor,
|
||||
borderRadius: theme.palette.borderRadius,
|
||||
}}
|
||||
{...params}
|
||||
label="Find your workflows"
|
||||
variant="outlined"
|
||||
/>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
: null}
|
||||
: null}
|
||||
<span style={{top: 30, position: "relative",}}>
|
||||
<Typography variant="body1" style={{marginTop: 0,}} onClick={() => {}}>
|
||||
Try it out
|
||||
</Typography>
|
||||
<WorkflowTemplatePopup
|
||||
userdata={userdata}
|
||||
|
||||
globalUrl={globalUrl}
|
||||
img1={inputUsecase.srcimg}
|
||||
srcapp={inputUsecase.srcapp}
|
||||
img2={inputUsecase.dstimg}
|
||||
dstapp={inputUsecase.dstapp}
|
||||
title={inputUsecase.name}
|
||||
description={inputUsecase.description}
|
||||
|
||||
apps={apps}
|
||||
/>
|
||||
</span>
|
||||
{/*
|
||||
|
||||
{/*subcase.matches.length > 0 ?
|
||||
<Grid container style={{maxWidth: 325, marginTop: 10, }}>
|
||||
{subcase.matches.map((workflow, workflowindex) => {
|
||||
return (
|
||||
<Grid key={workflowindex} item index={workflowindex} xs={12}>
|
||||
<WorkflowPaper key={workflowindex} data={workflow} />
|
||||
</Grid>
|
||||
)
|
||||
})}
|
||||
</Grid>
|
||||
:
|
||||
<div>
|
||||
<Typography variant="body1" color="textSecondary">
|
||||
No workflow selected yet.
|
||||
</Typography>
|
||||
</div>
|
||||
*/}
|
||||
|
||||
{subcase.extra_buttons !== undefined && subcase.extra_buttons !== null && subcase.extra_buttons.length > 0 ?
|
||||
<div style={{marginTop: 25, }}>
|
||||
@@ -852,15 +916,9 @@ const UsecaseListComponent = ({keys, isCloud, globalUrl, frameworkData, isLogged
|
||||
<Typography variant="body1" style={{marginTop: 15, cursor: "pointer",}} onClick={() => {}}>
|
||||
See other Public Workflows for {} <OpenInNewIcon style={{marginTop: 5, marginLeft: 15, }}/>
|
||||
</Typography>
|
||||
{/*
|
||||
<div>
|
||||
<Typography variant="body1" color="textSecondary">
|
||||
No workflows yet.
|
||||
</Typography>
|
||||
</div>
|
||||
*/}
|
||||
</a>
|
||||
</div>
|
||||
*/}
|
||||
</div>
|
||||
}
|
||||
<div style={{
|
||||
@@ -868,6 +926,8 @@ const UsecaseListComponent = ({keys, isCloud, globalUrl, frameworkData, isLogged
|
||||
width: 350,
|
||||
borderRadius: theme.palette.borderRadius,
|
||||
border: "1px solid rgba(255,255,255,0.3)",
|
||||
padding: 5,
|
||||
backgroundColor: theme.palette.backgroundColor,
|
||||
}}>
|
||||
<AppFramework
|
||||
inputUsecase={inputUsecase}
|
||||
|
||||
@@ -305,7 +305,6 @@ const LoginDialog = (props) => {
|
||||
paddingBottom: "30px",
|
||||
paddingTop: "30px",
|
||||
position: "relative",
|
||||
backgroundColor: theme.palette.inputColor,
|
||||
textAlign: "left",
|
||||
marginTop: 15,
|
||||
}}
|
||||
@@ -331,17 +330,25 @@ const LoginDialog = (props) => {
|
||||
variant="body2"
|
||||
style={{ marginBottom: 20, color: "white" }}
|
||||
>
|
||||
<b>1.</b> Make sure shuffle-database folder has correct access:{" "}
|
||||
<b>1.</b> Make sure shuffle-database folder has correct access, and that you have a minimum of <b>2Gb of RAM available</b>:{" "}
|
||||
<br />
|
||||
<br />
|
||||
sudo chown 1000:1000 -R shuffle-database
|
||||
</Typography>
|
||||
|
||||
<Typography
|
||||
variant="body2"
|
||||
style={{ marginBottom: 20, color: "white" }}
|
||||
>
|
||||
<b>2</b>. Restart docker-compose:
|
||||
<b>2.</b> Disable memory swap on the host
|
||||
<br />
|
||||
<br />
|
||||
sudo swapoff -a
|
||||
</Typography>
|
||||
<Typography
|
||||
variant="body2"
|
||||
style={{ marginBottom: 20, color: "white" }}
|
||||
>
|
||||
<b>3</b>. Restart docker-compose:
|
||||
<br />
|
||||
<br />
|
||||
sudo docker-compose restart
|
||||
@@ -513,7 +520,7 @@ const LoginDialog = (props) => {
|
||||
//id="sso_button"
|
||||
const ssoBtn = document.getElementById("sso_button");
|
||||
if (ssoBtn !== undefined && ssoBtn !== null) {
|
||||
console.log("SSO BTN: ", ssoBtn)
|
||||
//console.log("SSO BTN: ", ssoBtn)
|
||||
const cursearch = typeof window === "undefined" || window.location === undefined ? "" : window.location.search;
|
||||
var tmpView = new URLSearchParams(cursearch).get("autologin");
|
||||
if (tmpView !== undefined && tmpView !== null) {
|
||||
@@ -527,7 +534,7 @@ const LoginDialog = (props) => {
|
||||
}, 200);
|
||||
}, [ssoUrl])
|
||||
|
||||
return <div>{loadedCheck}</div>;
|
||||
return <div style={{paddingBottom: 150, }}>{loadedCheck}</div>;
|
||||
};
|
||||
|
||||
export default LoginDialog;
|
||||
|
||||
@@ -26,7 +26,7 @@ const SetAuthentication = (props) => {
|
||||
//const alert = useAlert();
|
||||
|
||||
const parseIncomingOpenapiData = (data) => {
|
||||
if (data.app === undefined || data.app === null) {
|
||||
if (data.app === undefined || data.app === null) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -43,11 +43,11 @@ const SetAuthentication = (props) => {
|
||||
parsedapp.name = parsedapp.name.replaceAll("_", " ");
|
||||
setApp(parsedapp);
|
||||
|
||||
document.title = parsedapp.name + " App Auth";
|
||||
document.title = parsedapp.name + " App Auth";
|
||||
|
||||
}
|
||||
|
||||
console.log("App: ", app)
|
||||
console.log("App: ", app)
|
||||
|
||||
const getApp = (appid) => {
|
||||
if (serverside === true) {
|
||||
@@ -64,21 +64,21 @@ const SetAuthentication = (props) => {
|
||||
})
|
||||
.then((response) => {
|
||||
if (response.status !== 200) {
|
||||
if (isCloud) {
|
||||
ReactGA.event({
|
||||
category: "appauth",
|
||||
action: `app_not_found`,
|
||||
label: appid,
|
||||
});
|
||||
}
|
||||
if (isCloud) {
|
||||
ReactGA.event({
|
||||
category: "appauth",
|
||||
action: `app_not_found`,
|
||||
label: appid,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
if (isCloud) {
|
||||
ReactGA.event({
|
||||
category: "appauth",
|
||||
action: `app_found`,
|
||||
label: appid,
|
||||
});
|
||||
}
|
||||
if (isCloud) {
|
||||
ReactGA.event({
|
||||
category: "appauth",
|
||||
action: `app_found`,
|
||||
label: appid,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return response.json();
|
||||
|
||||
@@ -23,6 +23,7 @@ import {
|
||||
} from '@mui/material';
|
||||
import theme from '../theme.jsx';
|
||||
import { useNavigate, Link } from "react-router-dom";
|
||||
import ArrowBackIosIcon from '@mui/icons-material/ArrowBackIos';
|
||||
import Drift from "react-driftjs";
|
||||
|
||||
const Welcome = (props) => {
|
||||
@@ -301,44 +302,47 @@ const Welcome = (props) => {
|
||||
flex: 1,
|
||||
padding: 0,
|
||||
textAlign: "center",
|
||||
maxWidth: 300,
|
||||
minWidth: 300,
|
||||
maxWidth: 275,
|
||||
minWidth: 275,
|
||||
backgroundColor: theme.palette.surfaceColor,
|
||||
color: "white",
|
||||
borderRadius: theme.palette.borderRadius,
|
||||
}
|
||||
|
||||
const actionObject = {
|
||||
padding: "35px",
|
||||
maxHeight: 300,
|
||||
minHeight: 300,
|
||||
padding: "25px",
|
||||
maxHeight: 280,
|
||||
minHeight: 280,
|
||||
borderRadius: theme.palette.borderRadius,
|
||||
}
|
||||
|
||||
const imageStyle = {
|
||||
width: 150,
|
||||
width: 70,
|
||||
// height: 150,
|
||||
// margin: "auto",
|
||||
// marginTop: 10,
|
||||
borderRadius: 75,
|
||||
marginBottom: 18,
|
||||
// borderRadius: 75,
|
||||
objectFit: "scale-down",
|
||||
}
|
||||
const buttonStyle = {
|
||||
borderRadius: 8,
|
||||
borderRadius: 200,
|
||||
height: 51,
|
||||
width: 464,
|
||||
fontSize: 16,
|
||||
background: "linear-gradient(89.83deg, #FF8444 0.13%, #F2643B 99.84%)",
|
||||
// background: "linear-gradient(89.83deg, #FF8444 0.13%, #F2643B 99.84%)",
|
||||
background: "linear-gradient(90deg, #F86744 0%, #F34475 100%)",
|
||||
padding: "16px 24px",
|
||||
top: 75,
|
||||
top: 105,
|
||||
margin: "auto",
|
||||
itemAlign: "center",
|
||||
marginLeft: "65px",
|
||||
}
|
||||
|
||||
const defaultImage = "/images/experienced.png"
|
||||
const experienced_image = userdata !== undefined && userdata !== null && userdata.active_org !== undefined && userdata.active_org.image !== undefined && userdata.active_org.image !== null && userdata.active_org.image !== "" ? userdata.active_org.image : defaultImage
|
||||
return (
|
||||
<div style={{width: 1000, margin: "auto", paddingBottom: 150, minHeight: 1500, marginTop: 50, }}>
|
||||
<div style={{ margin: "auto", paddingBottom: 150, minHeight: 1500, marginTop: 50, }}>
|
||||
{/*
|
||||
<div style={{position: "fixed", bottom: 110, right: 110, display: "flex", }}>
|
||||
<img src="/images/Arrow.png" style={{width: 250, height: "100%",}} />
|
||||
@@ -346,7 +350,7 @@ const Welcome = (props) => {
|
||||
*/}
|
||||
{showWelcome === true ?
|
||||
<div>
|
||||
<div style={{minWidth: 500, maxWidth: 500, margin: "auto", marginTop: isCloud ? "auto" : 20, }}>
|
||||
{/* <div style={{minWidth: 500, maxWidth: 500, margin: "auto", marginTop: isCloud ? "auto" : 20, }}>
|
||||
<Stepper
|
||||
activeStep={activeStep}
|
||||
color="primary"
|
||||
@@ -379,8 +383,8 @@ const Welcome = (props) => {
|
||||
)
|
||||
})}
|
||||
</Stepper>
|
||||
</div>
|
||||
<Grid container spacing={2} style={{ padding: 0, maxWidth: 1000, minWidth: 1000, margin: "auto", }}>
|
||||
</div> */}
|
||||
<Grid container spacing={1} style={{ padding: 0, maxWidth: 500, minWidth: 500, marginRight : "auto" , marginLeft: "auto" }}>
|
||||
<Grid item xs={window.location.href.includes("tab=2") ? 6 : 12}>
|
||||
<div>
|
||||
{/*
|
||||
@@ -414,7 +418,7 @@ const Welcome = (props) => {
|
||||
/>
|
||||
</div>
|
||||
</Grid>
|
||||
{frameworkData === undefined || window.location.href.includes("tab=1") || window.location.href.includes("tab=3") ? null :
|
||||
{/* {frameworkData === undefined || window.location.href.includes("tab=1") || window.location.href.includes("tab=3") ? null :
|
||||
<div style={{marginTop: 25, }}>
|
||||
<Typography variant="h6" style={{textAlign: "center", marginBottom: 25, }}>
|
||||
App Framework
|
||||
@@ -439,32 +443,35 @@ const Welcome = (props) => {
|
||||
/>
|
||||
</Fade>
|
||||
</div>
|
||||
}
|
||||
} */}
|
||||
</Grid>
|
||||
</div>
|
||||
:
|
||||
<Fade in={true}>
|
||||
<div style={{maxWidth: 700, margin: "auto", marginTop: 50, }}>
|
||||
{/*
|
||||
<div style={{display:"flex"}}>
|
||||
<ArrowBackIosIcon style={{color: "#9E9E9E",}} onClick={() => {
|
||||
navigate("/login")
|
||||
<div style={{maxWidth: 590, margin: "auto", marginTop: 50, }}>
|
||||
|
||||
{/* <div style={{display:"flex"}}>
|
||||
<ArrowBackIosIcon style={{color: "#9E9E9E", width: "16px",}} onClick={() => {
|
||||
navigate("/workflows")
|
||||
}}/>
|
||||
<Typography variant="body1" style={{color: "#9E9E9E",textAlign: "center", marginBottom: 50, paddingRight: "366px"}} onClick={() => {
|
||||
navigate("/login")
|
||||
<Typography variant="h8" style={{color: "#9E9E9E",textAlign: "center", marginBottom: 20, paddingRight: "366px"}} onClick={() => {
|
||||
navigate("/workflows")
|
||||
}}>
|
||||
Back
|
||||
</Typography>
|
||||
</div>
|
||||
*/}
|
||||
<Typography variant="h4" style={{color: "#F1F1F1", textAlign: "center", marginTop: 50, }}>
|
||||
</div> */}
|
||||
|
||||
<Typography variant="h4" style={{color: "#F1F1F1", marginTop: 50, fontSize: 32}}>
|
||||
Help us get to know you
|
||||
</Typography>
|
||||
<Typography variant="body1" style={{color: "#9E9E9E", textAlign: "center", marginBottom: 50,}}>
|
||||
We will use this information to personalize your automation
|
||||
<Typography variant="body1" style={{color: "#9E9E9E", marginTop: 12 ,marginBottom: 50, fontSize: 16}}>
|
||||
Let us help you create a smoother journey.
|
||||
</Typography>
|
||||
{/* <Typography variant="body1" style={{color: "#9E9E9E", marginTop: 12 ,marginBottom: 50, fontSize: 16}}>
|
||||
We will use this information to personalize your automation
|
||||
</Typography> */}
|
||||
<div style={{display: "flex", marginTop: 70, width: 700, margin: "auto",}}>
|
||||
<div style={{border: "1px solid #806BFF", borderRadius: theme.palette.borderRadius, }}>
|
||||
<div style={{border: "2px solid #806BFF", borderRadius: theme.palette.borderRadius, }}>
|
||||
<Card style={paperObject} onClick={() => {
|
||||
if (isCloud) {
|
||||
ReactGA.event({
|
||||
@@ -506,7 +513,7 @@ const Welcome = (props) => {
|
||||
navigate("/workflows?message=Skipped intro")
|
||||
}}>
|
||||
<CardActionArea style={actionObject}>
|
||||
<img src={experienced_image} style={{padding: experienced_image === defaultImage ? 38 : 10, objectFit: "scale-down", minHeight: experienced_image === defaultImage ? 40 : 70, maxHeight: experienced_image === defaultImage ? 40 : 70, bordeRadius: theme.palette.borderRadius, }} />
|
||||
<img src={experienced_image} style={{padding: experienced_image === defaultImage ? 2 : 10, objectFit: "scale-down", minHeight: experienced_image === defaultImage ? 40 : 70, maxHeight: experienced_image === defaultImage ? 40 : 70, bordeRadius: theme.palette.borderRadius, marginBottom: experienced_image === defaultImage ? 24 : 2 }} />
|
||||
<Typography variant="h4" style={{color: "#F1F1F1"}}>
|
||||
Experienced
|
||||
</Typography>
|
||||
@@ -517,17 +524,22 @@ const Welcome = (props) => {
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
{/*
|
||||
<div style={{display: "flex", flexDirection: "row", }}>
|
||||
|
||||
<div style={{ flexDirection: "row", }}>
|
||||
<Button variant="contained" type="submit" fullWidth style={buttonStyle} onClick={() => {
|
||||
navigate("/workflows?message=Skipped intro continue")
|
||||
ReactGA.event({
|
||||
category: "welcome",
|
||||
action: "click_welcome_continue",
|
||||
label: "",
|
||||
})
|
||||
}}>
|
||||
Continue
|
||||
</Button>
|
||||
</div>
|
||||
*/}
|
||||
|
||||
|
||||
<div style={{margin: "auto", borderRadius: theme.palette.borderRadius, marginTop: 50, width: 200, overflow: "wrap", padding: 25, cursor: "pointer", }} onClick={() => {
|
||||
|
||||
{/* <div style={{margin: "auto", borderRadius: theme.palette.borderRadius, marginTop: 50, width: 200, overflow: "wrap", padding: 25, cursor: "pointer", }} onClick={() => {
|
||||
if (window.drift !== undefined) {
|
||||
window.drift.api.startInteraction({ interactionId: 340045 })
|
||||
} else {
|
||||
@@ -537,7 +549,7 @@ const Welcome = (props) => {
|
||||
<Typography variant="body1" style={{margin: "auto", textAlign: "center"}}>
|
||||
Want a demo instead?
|
||||
</Typography>
|
||||
</div>
|
||||
</div> */}
|
||||
</div>
|
||||
</Fade>
|
||||
}
|
||||
|
||||
+127
-137
@@ -11,13 +11,13 @@ import { isMobile } from "react-device-detect"
|
||||
|
||||
import {
|
||||
Badge,
|
||||
Divider,
|
||||
Divider,
|
||||
Avatar,
|
||||
Drawer,
|
||||
Grid,
|
||||
InputLabel,
|
||||
Select,
|
||||
ListSubheader,
|
||||
InputLabel,
|
||||
Select,
|
||||
ListSubheader,
|
||||
Paper,
|
||||
Tooltip,
|
||||
Button,
|
||||
@@ -533,7 +533,6 @@ const Workflows = (props) => {
|
||||
document.title = "Shuffle - Workflows";
|
||||
let navigate = useNavigate();
|
||||
|
||||
//const alert = useAlert();
|
||||
const classes = useStyles(theme);
|
||||
const imgSize = 60;
|
||||
|
||||
@@ -590,6 +589,9 @@ const Workflows = (props) => {
|
||||
const [drawerOpen, setDrawerOpen] = React.useState(false)
|
||||
const [videoViewOpen, setVideoViewOpen] = React.useState(false)
|
||||
const [gettingStartedItems, setGettingStartedItems] = React.useState([])
|
||||
const [selectedWorkflowIndexes, setSelectedWorkflowIndexes] = React.useState([])
|
||||
|
||||
const [apps, setApps] = React.useState([]);
|
||||
|
||||
const drawerWidth = drawerOpen ? 325 : 0
|
||||
|
||||
@@ -725,6 +727,30 @@ const Workflows = (props) => {
|
||||
}
|
||||
};
|
||||
|
||||
const getApps = () => {
|
||||
fetch(`${globalUrl}/api/v1/apps`, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Accept: "application/json",
|
||||
},
|
||||
credentials: "include",
|
||||
})
|
||||
.then((response) => {
|
||||
if (response.status !== 200) {
|
||||
console.log("Status not 200 for apps :O!");
|
||||
}
|
||||
|
||||
return response.json();
|
||||
})
|
||||
.then((responseJson) => {
|
||||
setApps(responseJson);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log("App loading error: "+error.toString());
|
||||
});
|
||||
}
|
||||
|
||||
const addFilter = (data) => {
|
||||
if (data === null || data === undefined) {
|
||||
console.log("No filter data")
|
||||
@@ -891,13 +917,15 @@ const Workflows = (props) => {
|
||||
backgroundColor: theme.palette.surfaceColor,
|
||||
color: "white",
|
||||
minWidth: 500,
|
||||
padding: 50,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<DialogTitle>
|
||||
<div style={{ textAlign: "center", color: "rgba(255,255,255,0.9)" }}>
|
||||
Are you sure you want to delete this workflow? <div />
|
||||
Other workflows relying on this one may stop working
|
||||
Are you sure you want to delete {selectedWorkflowId.length > 0 ? filteredWorkflows.find((w) => w.id === selectedWorkflowId).name : `${selectedWorkflowIndexes.length} workflow${selectedWorkflowIndexes.length === 1 ? '' : 's'}`}? <div />
|
||||
|
||||
Other workflows relying on {selectedWorkflowIndexes.length > 0 ? "them" : "it"} one will stop working
|
||||
</div>
|
||||
</DialogTitle>
|
||||
<DialogContent
|
||||
@@ -912,7 +940,21 @@ const Workflows = (props) => {
|
||||
setTimeout(() => {
|
||||
getAvailableWorkflows();
|
||||
}, 1000);
|
||||
}
|
||||
} else if (selectedWorkflowIndexes.length > 0) {
|
||||
// Do backwards so it doesn't change
|
||||
for (var i = selectedWorkflowIndexes.length - 1; i >= 0; i--) {
|
||||
const workflow = filteredWorkflows[selectedWorkflowIndexes[i]-1]
|
||||
if (workflow !== undefined && workflow !== null && workflow.id !== undefined && workflow.id !== null) {
|
||||
deleteWorkflow(workflow.id);
|
||||
}
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
getAvailableWorkflows();
|
||||
}, 1000);
|
||||
|
||||
setSelectedWorkflowIndexes([]);
|
||||
}
|
||||
setDeleteModalOpen(false);
|
||||
}}
|
||||
color="primary"
|
||||
@@ -1115,9 +1157,9 @@ const Workflows = (props) => {
|
||||
|
||||
// Ensures the zooming happens only once per load
|
||||
setTimeout(() => {
|
||||
fetchUsecases(newarray)
|
||||
setFirstLoad(false)
|
||||
}, 100)
|
||||
fetchUsecases(newarray)
|
||||
setFirstLoad(false)
|
||||
}, 100)
|
||||
|
||||
} else {
|
||||
if (isLoggedIn) {
|
||||
@@ -1223,8 +1265,9 @@ const Workflows = (props) => {
|
||||
setView(tmpView);
|
||||
}
|
||||
|
||||
getApps()
|
||||
getAvailableWorkflows();
|
||||
getFramework()
|
||||
getFramework()
|
||||
}
|
||||
}, [])
|
||||
|
||||
@@ -1280,6 +1323,7 @@ const Workflows = (props) => {
|
||||
color: "white",
|
||||
margin: "10px",
|
||||
backgroundColor: theme.palette.surfaceColor,
|
||||
position: "relative",
|
||||
};
|
||||
|
||||
const workflowActionStyle = {
|
||||
@@ -1708,21 +1752,22 @@ const Workflows = (props) => {
|
||||
<MenuItem
|
||||
style={{ backgroundColor: theme.palette.inputColor, color: "white" }}
|
||||
onClick={(event) => {
|
||||
event.stopPropagation()
|
||||
ReactDOM.unstable_batchedUpdates(() => {
|
||||
setModalOpen(true);
|
||||
setEditingWorkflow(JSON.parse(JSON.stringify(data)));
|
||||
setNewWorkflowName(data.name);
|
||||
setNewWorkflowDescription(data.description);
|
||||
setDefaultReturnValue(data.default_return_value);
|
||||
if (data.tags !== undefined && data.tags !== null) {
|
||||
setNewWorkflowTags(JSON.parse(JSON.stringify(data.tags)));
|
||||
}
|
||||
event.stopPropagation()
|
||||
ReactDOM.unstable_batchedUpdates(() => {
|
||||
setIsEditing(true)
|
||||
setModalOpen(true);
|
||||
setEditingWorkflow(JSON.parse(JSON.stringify(data)));
|
||||
setNewWorkflowName(data.name);
|
||||
setNewWorkflowDescription(data.description);
|
||||
setDefaultReturnValue(data.default_return_value);
|
||||
if (data.tags !== undefined && data.tags !== null) {
|
||||
setNewWorkflowTags(JSON.parse(JSON.stringify(data.tags)));
|
||||
}
|
||||
|
||||
if (data.usecase_ids !== undefined && data.usecase_ids !== null && data.usecase_ids.length > 0) {
|
||||
setSelectedUsecases(data.usecase_ids)
|
||||
}
|
||||
})
|
||||
if (data.usecase_ids !== undefined && data.usecase_ids !== null && data.usecase_ids.length > 0) {
|
||||
setSelectedUsecases(data.usecase_ids)
|
||||
}
|
||||
})
|
||||
}}
|
||||
key={"change"}
|
||||
>
|
||||
@@ -2654,6 +2699,7 @@ const Workflows = (props) => {
|
||||
renderCell: (params) => {},
|
||||
},
|
||||
];
|
||||
|
||||
let rows = [];
|
||||
rows = filteredWorkflows.map((data, index) => {
|
||||
let obj = {
|
||||
@@ -2671,17 +2717,55 @@ const Workflows = (props) => {
|
||||
className={classes.datagrid}
|
||||
rows={rows}
|
||||
columns={columns}
|
||||
pageSize={20}
|
||||
pageSize={25}
|
||||
checkboxSelection
|
||||
autoHeight
|
||||
density="standard"
|
||||
onSelectionModelChange={(newSelection) => {
|
||||
//setSelectedWorkflows(newSelection.selectionModel);
|
||||
console.log(newSelection)
|
||||
|
||||
setSelectedWorkflowIndexes(newSelection)
|
||||
}}
|
||||
selectionModel={selectedWorkflowIndexes}
|
||||
components={{
|
||||
Toolbar: GridToolbar,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
return <div style={gridContainer}>{workflowData}</div>;
|
||||
return (
|
||||
<div style={gridContainer}>
|
||||
<Tooltip title={`New Workflow`} placement="bottom">
|
||||
<IconButton
|
||||
style={{position: "absolute", top: 10, right: 50, zIndex: 1000}}
|
||||
onClick={() => {
|
||||
setModalOpen(true)
|
||||
setIsEditing(false)
|
||||
}}
|
||||
>
|
||||
<AddCircleIcon style={{}} />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
{filteredWorkflows.length === 0 ? null :
|
||||
<IconButton
|
||||
style={{position: "absolute", top: 10, right: 10, zIndex: 1000}}
|
||||
disabled={selectedWorkflowIndexes.length === 0}
|
||||
onClick={() => {
|
||||
setDeleteModalOpen(true)
|
||||
}}
|
||||
>
|
||||
<Tooltip
|
||||
title={`Delete ${selectedWorkflowIndexes.length} workflows`}
|
||||
placement="top"
|
||||
>
|
||||
<DeleteIcon />
|
||||
</Tooltip>
|
||||
</IconButton>
|
||||
}
|
||||
{workflowData}
|
||||
</div>
|
||||
)
|
||||
};
|
||||
|
||||
var total_count = 0
|
||||
@@ -3152,70 +3236,20 @@ const Workflows = (props) => {
|
||||
|
||||
const WorkflowView = () => {
|
||||
if (workflows.length === 0) {
|
||||
// Not going there yet
|
||||
//if ((userdata.tutorials !== undefined && userdata.tutorials !== null && !userdata.tutorials.includes("getting-started")) || userdata.tutorials === null) {
|
||||
// return <Navigate to="/getting-started" replace />;
|
||||
//}
|
||||
//return (
|
||||
// <div style={emptyWorkflowStyle}>
|
||||
// <Paper style={boxStyle}>
|
||||
// <div>
|
||||
// <h2>Welcome to Shuffle</h2>
|
||||
// </div>
|
||||
// <div>
|
||||
// <p>
|
||||
// <b>Shuffle</b> is a flexible, easy to use, automation platform
|
||||
// allowing users to integrate their services and devices freely.
|
||||
// It's made to significantly reduce the amount of manual labor,
|
||||
// and is focused on security applications.{" "}
|
||||
// <a
|
||||
// href="/docs/about"
|
||||
// style={{ textDecoration: "none", color: "#f85a3e" }}
|
||||
// >
|
||||
// Click here to learn more.
|
||||
// </a>
|
||||
// </p>
|
||||
// </div>
|
||||
// <div>
|
||||
// If you want to jump straight into it, click here to create your
|
||||
// first workflow:
|
||||
// </div>
|
||||
// <div style={{ display: "flex" }}>
|
||||
// <Button
|
||||
// id="second-step"
|
||||
// color="primary"
|
||||
// style={{ marginTop: "20px" }}
|
||||
// variant="outlined"
|
||||
// onClick={() => setModalOpen(true)}
|
||||
// >
|
||||
// New workflow
|
||||
// </Button>
|
||||
// <span style={{ paddingTop: 20, display: "flex" }}>
|
||||
// <Typography
|
||||
// style={{ marginTop: 5, marginLeft: 30, marginRight: 15 }}
|
||||
// >
|
||||
// ..OR
|
||||
// </Typography>
|
||||
// {workflowButtons}
|
||||
// </span>
|
||||
// </div>
|
||||
// </Paper>
|
||||
// </div>
|
||||
//)
|
||||
}
|
||||
|
||||
var workflowDelay = -150
|
||||
var appDelay = -75
|
||||
var workflowDelay = -150
|
||||
var appDelay = -75
|
||||
|
||||
const foundPriority = userdata === undefined || userdata === null ? null : userdata.priorities.find(prio => prio.type === "usecase" && prio.active === true)
|
||||
const foundPriority = userdata === undefined || userdata === null ? null : userdata.priorities.find(prio => prio.type === "usecase" && prio.active === true)
|
||||
return (
|
||||
<div style={viewStyle}>
|
||||
<div style={workflowViewStyle}>
|
||||
<div style={{ display: "flex", marginTop: 25, }}>
|
||||
<div style={{ flex: 1 }}>
|
||||
<Typography variant="h1" style={{fontSize: 30}}>
|
||||
Workflows
|
||||
</Typography>
|
||||
<Typography variant="h1" style={{fontSize: 30}}>
|
||||
Workflows
|
||||
</Typography>
|
||||
</div>
|
||||
{/*
|
||||
<div style={{ flex: 1 }}>
|
||||
@@ -3243,6 +3277,7 @@ const Workflows = (props) => {
|
||||
minWidth: 275,
|
||||
},
|
||||
}}
|
||||
rows={1}
|
||||
placeholder="Filter Workflows"
|
||||
color="primary"
|
||||
fullWidth
|
||||
@@ -3268,53 +3303,6 @@ const Workflows = (props) => {
|
||||
{workflowButtons}
|
||||
</div>
|
||||
</div>
|
||||
{/*
|
||||
<div style={flexContainerStyle}>
|
||||
<div style={{...flexBoxStyle, ...activeWorkflowStyle}}>
|
||||
<div style={flexContentStyle}>
|
||||
<div><img src={mobileImage} style={iconStyle} /></div>
|
||||
<div style={ blockRightStyle }>
|
||||
<div style={counterStyle}>{workflows.length}</div>
|
||||
<div style={fontSize_16}>ACTIVE WORKFLOWS</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style={{...flexBoxStyle, ...availableWorkflowStyle}}>
|
||||
<div style={flexContentStyle}>
|
||||
<div><img src={bookImage} style={iconStyle} /></div>
|
||||
<div style={ blockRightStyle }>
|
||||
<div style={counterStyle}>{workflows.length}</div>
|
||||
<div style={fontSize_16}>AVAILABE WORKFLOWS</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style={{...flexBoxStyle, ...notificationStyle}}>
|
||||
<div style={flexContentStyle}>
|
||||
<div><img src={bagImage} style={iconStyle} /></div>
|
||||
<div style={ blockRightStyle }>
|
||||
<div style={counterStyle}>{workflows.length}</div>
|
||||
<div style={fontSize_16}>NOTIFICATIONS</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
*/}
|
||||
|
||||
{/*
|
||||
chipRenderer={({ value, isFocused, isDisabled, handleClick, handleRequestDelete }, key) => {
|
||||
console.log("VALUE: ", value)
|
||||
|
||||
return (
|
||||
<Chip
|
||||
key={key}
|
||||
style={chipStyle}
|
||||
|
||||
>
|
||||
{value}
|
||||
</Chip>
|
||||
)
|
||||
}}
|
||||
*/}
|
||||
|
||||
<div style={{width: "100%", minHeight: isMobile ? 0 : 51, maxHeight: isMobile ? 0 : 51, marginTop: 10, }}>
|
||||
{!isMobile && usecases !== null && usecases !== undefined && usecases.length > 0 ?
|
||||
@@ -3772,12 +3760,12 @@ const Workflows = (props) => {
|
||||
}
|
||||
|
||||
const gettingStartedDrawer =
|
||||
<Drawer
|
||||
anchor={"right"}
|
||||
open={drawerOpen}
|
||||
variant="persistent"
|
||||
keepMounted={true}
|
||||
PaperProps={{
|
||||
<Drawer
|
||||
anchor={"right"}
|
||||
open={drawerOpen}
|
||||
variant="persistent"
|
||||
keepMounted={true}
|
||||
PaperProps={{
|
||||
style: {
|
||||
resize: "both",
|
||||
overflow: "auto",
|
||||
@@ -3928,6 +3916,7 @@ const Workflows = (props) => {
|
||||
{modalOpen === true ?
|
||||
<EditWorkflow
|
||||
globalUrl={globalUrl}
|
||||
userdata={userdata}
|
||||
workflow={editingWorkflow}
|
||||
setWorkflow={setEditingWorkflow}
|
||||
modalOpen={modalOpen}
|
||||
@@ -3938,6 +3927,7 @@ const Workflows = (props) => {
|
||||
isEditing={isEditing}
|
||||
|
||||
workflows={workflows}
|
||||
apps={apps}
|
||||
setWorkflows={setWorkflows}
|
||||
/>
|
||||
: null}
|
||||
|
||||
Reference in New Issue
Block a user