Workflow fixes

This commit is contained in:
Frikky
2024-11-30 15:02:45 +01:00
parent 8d57bd15a7
commit cc5fc5fde2
5 changed files with 2519 additions and 2381 deletions
+77 -57
View File
@@ -72,6 +72,7 @@ const EditWorkflow = (props) => {
const [submitLoading, setSubmitLoading] = React.useState(false); const [submitLoading, setSubmitLoading] = React.useState(false);
const [showMoreClicked, setShowMoreClicked] = React.useState(expanded === true ? true : false); const [showMoreClicked, setShowMoreClicked] = React.useState(expanded === true ? true : false);
const [innerWorkflow, setInnerWorkflow] = React.useState(workflow) const [innerWorkflow, setInnerWorkflow] = React.useState(workflow)
const [newWorkflowTags, setNewWorkflowTags] = React.useState(workflow.tags !== undefined && workflow.tags !== null ? JSON.parse(JSON.stringify(workflow.tags)) : []) const [newWorkflowTags, setNewWorkflowTags] = React.useState(workflow.tags !== undefined && workflow.tags !== null ? JSON.parse(JSON.stringify(workflow.tags)) : [])
@@ -80,7 +81,8 @@ const EditWorkflow = (props) => {
const [selectedUsecases, setSelectedUsecases] = React.useState(workflow.usecase_ids !== undefined && workflow.usecase_ids !== null ? JSON.parse(JSON.stringify(workflow.usecase_ids)) : []); const [selectedUsecases, setSelectedUsecases] = React.useState(workflow.usecase_ids !== undefined && workflow.usecase_ids !== null ? JSON.parse(JSON.stringify(workflow.usecase_ids)) : []);
const [foundWorkflowId, setFoundWorkflowId] = React.useState("") const [foundWorkflowId, setFoundWorkflowId] = React.useState("")
const [name, setName] = React.useState(workflow.name !== undefined ? workflow.name : "") const [name, setName] = React.useState(workflow.name !== undefined ? workflow.name : "")
const [dueDate, setDueDate] = React.useState(workflow.due_date !== undefined && workflow.due_date !== null && workflow.due_date !== 0 ? dayjs(workflow.due_date*1000) : dayjs().subtract(1, 'day')) const [workflowAsCode, setWorkflowAsCode] = React.useState(false)
const [dueDate, setDueDate] = React.useState(workflow.due_date !== undefined && workflow.due_date !== null && workflow.due_date !== 0 ? dayjs(workflow.due_date * 1000) : dayjs().subtract(1, 'day'))
const [inputQuestions, setInputQuestions] = React.useState(workflow.input_questions !== undefined && workflow.input_questions !== null ? JSON.parse(JSON.stringify(workflow.input_questions)) : []) const [inputQuestions, setInputQuestions] = React.useState(workflow.input_questions !== undefined && workflow.input_questions !== null ? JSON.parse(JSON.stringify(workflow.input_questions)) : [])
const [inputMarkdown, setInputMarkdown] = React.useState(workflow?.form_control?.input_markdown !== undefined && workflow?.form_control?.input_markdown !== null ? workflow?.form_control?.input_markdown : "") const [inputMarkdown, setInputMarkdown] = React.useState(workflow?.form_control?.input_markdown !== undefined && workflow?.form_control?.input_markdown !== null ? workflow?.form_control?.input_markdown : "")
@@ -206,11 +208,11 @@ const EditWorkflow = (props) => {
}, },
}} }}
> >
<DialogTitle style={{padding: 30, paddingBottom: 0, zIndex: 1000,}}> <DialogTitle style={{ padding: 30, paddingBottom: 0, zIndex: 1000, }}>
<div style={{display: "flex"}}> <div style={{ display: "flex" }}>
<div style={{flex: 1, color: "rgba(255,255,255,0.9)" }}> <div style={{ flex: 1, color: "rgba(255,255,255,0.9)" }}>
<div style={{display: "flex"}}> <div style={{ display: "flex" }}>
<Typography variant="h4" style={{flex: 9, }}> <Typography variant="h4" style={{ flex: 9, }}>
{newWorkflow ? "New" : "Editing"} workflow {newWorkflow ? "New" : "Editing"} workflow
</Typography> </Typography>
@@ -236,7 +238,7 @@ const EditWorkflow = (props) => {
} }
</div> </div>
<Typography variant="body2" color="textSecondary" style={{marginTop: 20, maxWidth: 440,}}> <Typography variant="body2" color="textSecondary" style={{ marginTop: 20, maxWidth: 440, }}>
Workflows can be built from scratch, or from templates. <a href="/usecases2" rel="noopener noreferrer" target="_blank" style={{ textDecoration: "none", color: "#f86a3e" }}>Usecases</a> can help you discover next steps, and you can <a href="/search?tab=workflows" rel="noopener noreferrer" target="_blank" style={{ textDecoration: "none", color: "#f86a3e" }}>search</a> for them directly. <a href="/docs/workflows" rel="noopener noreferrer" target="_blank" style={{ textDecoration: "none", color: "#f86a3e" }}>Learn more</a> Workflows can be built from scratch, or from templates. <a href="/usecases2" rel="noopener noreferrer" target="_blank" style={{ textDecoration: "none", color: "#f86a3e" }}>Usecases</a> can help you discover next steps, and you can <a href="/search?tab=workflows" rel="noopener noreferrer" target="_blank" style={{ textDecoration: "none", color: "#f86a3e" }}>search</a> for them directly. <a href="/docs/workflows" rel="noopener noreferrer" target="_blank" style={{ textDecoration: "none", color: "#f86a3e" }}>Learn more</a>
</Typography> </Typography>
@@ -278,7 +280,7 @@ const EditWorkflow = (props) => {
</div> </div>
</DialogTitle> </DialogTitle>
<FormControl> <FormControl>
<div style={{borderTop: "1px solid rgba(255,255,255,0.5)", width: 600, position: "fixed", right: 20, bottom: 0, zIndex: 1002, backgroundColor: "rgba(53,53,53,1)", height: 75, paddingTop: 20, paddingLeft: 75, }}> <div style={{ borderTop: "1px solid rgba(255,255,255,0.5)", width: 600, position: "fixed", right: 20, bottom: 0, zIndex: 1002, backgroundColor: "rgba(53,53,53,1)", height: 75, paddingTop: 20, paddingLeft: 75, }}>
{/* {/*
<Button <Button
style={{}} style={{}}
@@ -336,7 +338,7 @@ const EditWorkflow = (props) => {
} }
if (dueDate > 0) { if (dueDate > 0) {
innerWorkflow.due_date = new Date(`${dueDate["$y"]}-${dueDate["$M"]+1}-${dueDate["$D"]}`).getTime()/1000 innerWorkflow.due_date = new Date(`${dueDate["$y"]}-${dueDate["$M"] + 1}-${dueDate["$D"]}`).getTime() / 1000
} }
if (saveWorkflow !== undefined) { if (saveWorkflow !== undefined) {
@@ -356,6 +358,7 @@ const EditWorkflow = (props) => {
innerWorkflow.usecase_ids, innerWorkflow.usecase_ids,
innerWorkflow.blogpost, innerWorkflow.blogpost,
innerWorkflow.status, innerWorkflow.status,
workflowAsCode
) )
setWorkflow({}) setWorkflow({})
} else { } else {
@@ -376,8 +379,8 @@ const EditWorkflow = (props) => {
</Button> </Button>
</div> </div>
<DialogContent style={{paddingTop: 10, display: "flex", minHeight: 300, zIndex: 1001, paddingBottom: 200, }}> <DialogContent style={{ paddingTop: 10, display: "flex", minHeight: 300, zIndex: 1001, paddingBottom: 200, }}>
<div style={{minWidth: newWorkflow ? 500 : 550, maxWidth: newWorkflow ? 450 : 500, }}> <div style={{ minWidth: newWorkflow ? 500 : 550, maxWidth: newWorkflow ? 450 : 500, }}>
<TextField <TextField
onChange={(event) => { onChange={(event) => {
setName(event.target.value) setName(event.target.value)
@@ -396,9 +399,10 @@ const EditWorkflow = (props) => {
autoFocus autoFocus
fullWidth fullWidth
/> />
<div style={{display: "flex", marginTop: 10, }}>
<div style={{ display: "flex", marginTop: 10, }}>
{usecases !== null && usecases !== undefined && usecases.length > 0 ? {usecases !== null && usecases !== undefined && usecases.length > 0 ?
<FormControl style={{flex: 1, marginRight: 5,}}> <FormControl style={{ flex: 1, marginRight: 5, }}>
<InputLabel htmlFor="grouped-select-usecase">Usecases</InputLabel> <InputLabel htmlFor="grouped-select-usecase">Usecases</InputLabel>
<Select <Select
defaultValue="" defaultValue=""
@@ -419,7 +423,7 @@ const EditWorkflow = (props) => {
return ( return (
<span key={index}> <span key={index}>
<ListSubheader <ListSubheader
style={{color: usecase.color}} style={{ color: usecase.color }}
> >
{usecase.name} {usecase.name}
</ListSubheader> </ListSubheader>
@@ -440,7 +444,7 @@ const EditWorkflow = (props) => {
setUpdate(Math.random()); setUpdate(Math.random());
setSelectedUsecases(selectedUsecases) setSelectedUsecases(selectedUsecases)
}}> }}>
<Checkbox style={{color: selectedUsecases.includes(subcase.name) ? usecase.color : theme.palette.inputColor}} checked={selectedUsecases.includes(subcase.name)} /> <Checkbox style={{ color: selectedUsecases.includes(subcase.name) ? usecase.color : theme.palette.inputColor }} checked={selectedUsecases.includes(subcase.name)} />
<ListItemText primary={subcase.name} /> <ListItemText primary={subcase.name} />
</MenuItem> </MenuItem>
) )
@@ -452,7 +456,7 @@ const EditWorkflow = (props) => {
</FormControl> </FormControl>
: null} : null}
<MuiChipsInput <MuiChipsInput
style={{ flex: 1, maxHeight: 120, overflow: "auto",}} style={{ flex: 1, maxHeight: 120, overflow: "auto", }}
InputProps={{ InputProps={{
style: { style: {
color: "white", color: "white",
@@ -493,7 +497,7 @@ const EditWorkflow = (props) => {
</div> </div>
{showMoreClicked === true ? {showMoreClicked === true ?
<div style={{marginTop: 50, }}> <div style={{ marginTop: 50, }}>
<TextField <TextField
onBlur={(event) => { onBlur={(event) => {
setDescription(event.target.value) setDescription(event.target.value)
@@ -514,8 +518,8 @@ const EditWorkflow = (props) => {
fullWidth fullWidth
/> />
<div style={{display: "flex"}}> <div style={{ display: "flex" }}>
<FormControl style={{marginTop: 15, }}> <FormControl style={{ marginTop: 15, }}>
<FormLabel id="demo-row-radio-buttons-group-label">Status</FormLabel> <FormLabel id="demo-row-radio-buttons-group-label">Status</FormLabel>
<RadioGroup <RadioGroup
row row
@@ -552,7 +556,7 @@ const EditWorkflow = (props) => {
</div> </div>
<div /> <div />
<FormControl style={{marginTop: 15, }}> <FormControl style={{ marginTop: 15, }}>
<FormLabel id="demo-row-radio-buttons-group-label">Type</FormLabel> <FormLabel id="demo-row-radio-buttons-group-label">Type</FormLabel>
<RadioGroup <RadioGroup
row row
@@ -631,25 +635,25 @@ const EditWorkflow = (props) => {
fullWidth fullWidth
/> />
<Divider style={{marginTop: 20, marginBottom: 20, }} /> <Divider style={{ marginTop: 20, marginBottom: 20, }} />
<Typography variant="h4" style={{marginTop: 50, }}> <Typography variant="h4" style={{ marginTop: 50, }}>
MSSP controls MSSP controls
</Typography> </Typography>
<Typography variant="body1" style={{marginTop: 50, }}> <Typography variant="body1" style={{ marginTop: 50, }}>
MSSP Suborg Distribution (<b>beta</b> - contact support@shuffler.io for more info) MSSP Suborg Distribution (<b>beta</b> - contact support@shuffler.io for more info)
</Typography> </Typography>
{userdata !== undefined && userdata !== null && userdata.orgs !== undefined && userdata.orgs !== null && userdata.orgs.length > 0 ? {userdata !== undefined && userdata !== null && userdata.orgs !== undefined && userdata.orgs !== null && userdata.orgs.length > 0 ?
userdata.orgs.filter(org => org.creator_org === userdata.active_org.id).length === 0 ? userdata.orgs.filter(org => org.creator_org === userdata.active_org.id).length === 0 ?
userdata.active_org.creator_org === undefined || userdata.active_org.creator_org === null || userdata.active_org.creator_org === "" ? userdata.active_org.creator_org === undefined || userdata.active_org.creator_org === null || userdata.active_org.creator_org === "" ?
<Typography variant="body2" style={{marginTop: 10, color: "rgba(255,255,255,0.7)"}}> <Typography variant="body2" style={{ marginTop: 10, color: "rgba(255,255,255,0.7)" }}>
Your organization does not have any suborgs yet OR your user may not have access to available suborgs. Please <a href="/admin?tab=suborgs" style={{textDecoration: "none", color: "#f86a3e"}} target="_blank">make one</a> or get access to suborgs by another admin, then try again. Your organization does not have any suborgs yet OR your user may not have access to available suborgs. Please <a href="/admin?tab=suborgs" style={{ textDecoration: "none", color: "#f86a3e" }} target="_blank">make one</a> or get access to suborgs by another admin, then try again.
</Typography> </Typography>
: :
<Typography variant="body2" style={{marginTop: 10, color: "rgba(255,255,255,0.7)"}}> <Typography variant="body2" style={{ marginTop: 10, color: "rgba(255,255,255,0.7)" }}>
{innerWorkflow.parentorg_workflow !== undefined && innerWorkflow.parentorg_workflow !== null && innerWorkflow.parentorg_workflow.length > 0 ? <span>This workflow is distributed from <a href={`/workflows/${innerWorkflow.parentorg_workflow}`} style={{textDecoration: "none", color: "#f86a3e"}} target="_blank">your parent workflow</a> (you may not have access).</span> : null} {innerWorkflow.parentorg_workflow !== undefined && innerWorkflow.parentorg_workflow !== null && innerWorkflow.parentorg_workflow.length > 0 ? <span>This workflow is distributed from <a href={`/workflows/${innerWorkflow.parentorg_workflow}`} style={{ textDecoration: "none", color: "#f86a3e" }} target="_blank">your parent workflow</a> (you may not have access).</span> : null}
<br /> <br />
<br /> <br />
You can only distribute to suborgs from a parent org. You can only distribute to suborgs from a parent org.
@@ -657,7 +661,7 @@ const EditWorkflow = (props) => {
: :
<Select <Select
multiple multiple
style={{marginTop: 10, }} style={{ marginTop: 10, }}
value={innerWorkflow.suborg_distribution === undefined || innerWorkflow.suborg_distribution === null ? ["none"] : innerWorkflow.suborg_distribution} value={innerWorkflow.suborg_distribution === undefined || innerWorkflow.suborg_distribution === null ? ["none"] : innerWorkflow.suborg_distribution}
onChange={(e) => { onChange={(e) => {
var newvalue = e.target.value var newvalue = e.target.value
@@ -736,8 +740,8 @@ const EditWorkflow = (props) => {
})} })}
</Select> </Select>
: :
<Link to={"/admin?tab=suborgs"} style={{textDecoration: "none", color: "#f86a3e"}} target="_blank"> <Link to={"/admin?tab=suborgs"} style={{ textDecoration: "none", color: "#f86a3e" }} target="_blank">
<Typography variant="body2" style={{marginTop: 10, }}> <Typography variant="body2" style={{ marginTop: 10, }}>
Create a sub-org to distribute workflows to suborgs. Create a sub-org to distribute workflows to suborgs.
</Typography> </Typography>
</Link> </Link>
@@ -747,11 +751,11 @@ const EditWorkflow = (props) => {
<Typography variant="body1" style={{marginTop: 100, }}> <Typography variant="body1" style={{ marginTop: 100, }}>
Git Backup Repository Git Backup Repository
</Typography> </Typography>
<Typography variant="body2" style={{ textAlign: "left", marginTop: 5, }} color="textSecondary"> <Typography variant="body2" style={{ textAlign: "left", marginTop: 5, }} color="textSecondary">
Decide where this workflow is backed up in a Git repository. Will create logs and notifications if upload fails. <b>The repository and branch must already have been initialized</b>. Files will show up in the root folder in the format 'orgid/workflow status/workflow id.json' without images. Overrides your <a href="/admin?admin_tab=organization" style={{textDecoration: "none", color: "#f86a3e"}} target="_blank">default backup repository</a>. <a href="/docs/configuration#environment-variables" style={{textDecoration: "none", color: "#f86a3e"}} target="_blank">Credentials are encrypted.</a> Creates <a href="/admin?admin_tab=priorities" style={{textDecoration: "none", color: "#f86a3e"}} target="_blank">notifications</a> if it fails. Decide where this workflow is backed up in a Git repository. Will create logs and notifications if upload fails. <b>The repository and branch must already have been initialized</b>. Files will show up in the root folder in the format 'orgid/workflow status/workflow id.json' without images. Overrides your <a href="/admin?admin_tab=organization" style={{ textDecoration: "none", color: "#f86a3e" }} target="_blank">default backup repository</a>. <a href="/docs/configuration#environment-variables" style={{ textDecoration: "none", color: "#f86a3e" }} target="_blank">Credentials are encrypted.</a> Creates <a href="/admin?admin_tab=priorities" style={{ textDecoration: "none", color: "#f86a3e" }} target="_blank">notifications</a> if it fails.
</Typography> </Typography>
<Grid container style={{ marginTop: 10, }} spacing={2}> <Grid container style={{ marginTop: 10, }} spacing={2}>
<Grid item xs={6} style={{}}> <Grid item xs={6} style={{}}>
@@ -823,7 +827,7 @@ const EditWorkflow = (props) => {
</span> </span>
</Grid> </Grid>
</Grid> </Grid>
<Grid container style={{ }} spacing={2}> <Grid container style={{}} spacing={2}>
<Grid item xs={6} style={{}}> <Grid item xs={6} style={{}}>
<span> <span>
<Typography>Username</Typography> <Typography>Username</Typography>
@@ -893,23 +897,23 @@ const EditWorkflow = (props) => {
</Grid> </Grid>
</Grid> </Grid>
<Divider style={{marginTop: 20, marginBottom: 20, }} /> <Divider style={{ marginTop: 20, marginBottom: 20, }} />
<div id="form_fill" style={{position: "relative", }}> <div id="form_fill" style={{ position: "relative", }}>
<Typography variant="h4" style={{marginTop: 100, }}> <Typography variant="h4" style={{ marginTop: 100, }}>
Form Control Form Control
</Typography> </Typography>
<Typography variant="body1" color="textSecondary" style={{marginTop: 10, }}> <Typography variant="body1" color="textSecondary" style={{ marginTop: 10, }}>
Form Control is used to control how the Form for the workflow is shown to users. You can add input fields, markdown, and more. This is the first step in the workflow, and is required for all workflows. Form Control is used to control how the Form for the workflow is shown to users. You can add input fields, markdown, and more. This is the first step in the workflow, and is required for all workflows.
</Typography> </Typography>
<Typography variant="h6" style={{marginTop: 50, }}> <Typography variant="h6" style={{ marginTop: 50, }}>
Input fields Input fields
</Typography> </Typography>
<Tooltip title="Go to Public Form page"> <Tooltip title="Go to Public Form page">
<IconButton style={{position: "absolute", top: 0, right: 10, }}> <IconButton style={{ position: "absolute", top: 0, right: 10, }}>
<a <a
rel="noopener noreferrer" rel="noopener noreferrer"
href={`/forms/${workflow.id}`} href={`/forms/${workflow.id}`}
@@ -927,7 +931,7 @@ const EditWorkflow = (props) => {
</div> </div>
<Typography variant="body2" color="textSecondary" style={{marginBottom: 20, }}> <Typography variant="body2" color="textSecondary" style={{ marginBottom: 20, }}>
Input fields are fields that will be used during the startup of the workflow. These will be formatted in JSON and is most commonly used from the <a href={`/forms/${workflow.id}`} rel="noopener noreferrer" target="_blank" style={{ textDecoration: "none", color: "#f86a3e" }}>Form page</a> for this workflow. If chosen in the User Input node, these will be required fields. Use Semi-Colon ";" to create dropdown options. The first key will be the name shown, and subsequent keys will be the available values. Input fields are fields that will be used during the startup of the workflow. These will be formatted in JSON and is most commonly used from the <a href={`/forms/${workflow.id}`} rel="noopener noreferrer" target="_blank" style={{ textDecoration: "none", color: "#f86a3e" }}>Form page</a> for this workflow. If chosen in the User Input node, these will be required fields. Use Semi-Colon ";" to create dropdown options. The first key will be the name shown, and subsequent keys will be the available values.
</Typography> </Typography>
@@ -941,7 +945,7 @@ const EditWorkflow = (props) => {
} }
return ( return (
<div style={{display: "flex", }}> <div style={{ display: "flex", }}>
<TextField <TextField
disabled={data.deleted === true} disabled={data.deleted === true}
style={{ style={{
@@ -1037,10 +1041,10 @@ const EditWorkflow = (props) => {
</Button> </Button>
<div id="input_markdown"> <div id="input_markdown">
<Typography variant="h6" style={{marginTop: 50, }}> <Typography variant="h6" style={{ marginTop: 50, }}>
Input Markdown Input Markdown
</Typography> </Typography>
<Typography variant="body2" color="textSecondary" style={{marginBottom: 20, }}> <Typography variant="body2" color="textSecondary" style={{ marginBottom: 20, }}>
Markdown will be shown on the <a href={`/forms/${workflow.id}`} rel="noopener noreferrer" target="_blank" style={{ textDecoration: "none", color: "#f86a3e" }}>Form page</a>. The first image added will be used in your Form Toolbox list. Output for a Workflow is shown in Markdown, and is controlled by the LAST action that runs. Supports HTML. Markdown will be shown on the <a href={`/forms/${workflow.id}`} rel="noopener noreferrer" target="_blank" style={{ textDecoration: "none", color: "#f86a3e" }}>Form page</a>. The first image added will be used in your Form Toolbox list. Output for a Workflow is shown in Markdown, and is controlled by the LAST action that runs. Supports HTML.
</Typography> </Typography>
<TextField <TextField
@@ -1070,10 +1074,10 @@ const EditWorkflow = (props) => {
</div> </div>
<div id="form_size"> <div id="form_size">
<Typography variant="h6" style={{marginTop: 50, }}> <Typography variant="h6" style={{ marginTop: 50, }}>
Form Size Form Size
</Typography> </Typography>
<Typography variant="body2" color="textSecondary" style={{marginBottom: 20, }}> <Typography variant="body2" color="textSecondary" style={{ marginBottom: 20, }}>
Control the width of the form. It will grow vertically as needed. Control the width of the form. It will grow vertically as needed.
</Typography> </Typography>
<Slider <Slider
@@ -1091,22 +1095,22 @@ const EditWorkflow = (props) => {
</div> </div>
<div id="output_control"> <div id="output_control">
<Typography variant="h6" style={{marginTop: 50, }}> <Typography variant="h6" style={{ marginTop: 50, }}>
Output Control ({selectedYieldActions.length === 0 ? "No Returns" : selectedYieldActions.length === 1 ? "Returning 1 node" : `Returning ${selectedYieldActions.length} nodes`}) Output Control ({selectedYieldActions.length === 0 ? "No Returns" : selectedYieldActions.length === 1 ? "Returning 1 node" : `Returning ${selectedYieldActions.length} nodes`})
</Typography> </Typography>
<Typography variant="body2" color="textSecondary" style={{marginBottom: 20, }}> <Typography variant="body2" color="textSecondary" style={{ marginBottom: 20, }}>
When running this workflow, the output will be shown as a Markdown object by default, with JSON objects being rendered. By adding nodes below, they will be shown while the workflow is running as soon as they get a result. Failing/Skipped nodes are not shown. This makes it possible to track progress for more complex usecases. When running this workflow, the output will be shown as a Markdown object by default, with JSON objects being rendered. By adding nodes below, they will be shown while the workflow is running as soon as they get a result. Failing/Skipped nodes are not shown. This makes it possible to track progress for more complex usecases.
</Typography> </Typography>
<FormControl style={{marginTop: 15, }}> <FormControl style={{ marginTop: 15, }}>
<Select <Select
defaultValue="" defaultValue=""
id="output-yield-control" id="output-yield-control"
label="Yielding nodes" label="Yielding nodes"
multiple multiple
fullWidth fullWidth
style={{width: 500, }} style={{ width: 500, }}
value={selectedYieldActions === [] ? ["none"] : selectedYieldActions} value={selectedYieldActions === [] ? ["none"] : selectedYieldActions}
renderValue={(selected) => selected.join(', ')} renderValue={(selected) => selected.join(', ')}
onChange={(event) => { onChange={(event) => {
@@ -1135,7 +1139,7 @@ const EditWorkflow = (props) => {
value={action.id} value={action.id}
> >
<Tooltip title={action.app_name} key={actionIndex}> <Tooltip title={action.app_name} key={actionIndex}>
<img src={action.large_image !== undefined && action.large_image !== null && action.large_image.length > 0 ? action.large_image : theme.palette.defaultImage} style={{width: 20, height: 20, marginRight: 10, }} /> <img src={action.large_image !== undefined && action.large_image !== null && action.large_image.length > 0 ? action.large_image : theme.palette.defaultImage} style={{ width: 20, height: 20, marginRight: 10, }} />
</Tooltip> </Tooltip>
{action.label} {action.label}
</MenuItem> </MenuItem>
@@ -1147,11 +1151,26 @@ const EditWorkflow = (props) => {
</div> </div>
: null} : null}
{/*!isEditing ? <>
<div style={{ marginTop: 20, }}>
<FormControlLabel
control={<Checkbox />}
label="Create workflow as code"
style={{ marginTop: '12px' }}
onChange={(e) => {
setWorkflowAsCode(e.target.checked)
workflow.workflow_as_code = e.target.checked
setWorkflow(workflow)
setInnerWorkflow(workflow)
}}
/>
</div>
</> : null*/}
<Tooltip color="primary" title={"Add more details"} placement="top"> <Tooltip color="primary" title={"Add more details"} placement="top">
<Button <Button
style={{ margin: "auto", marginTop: 50, marginBottom: 100, textAlign: "center", textTransform: "none", }} style={{ margin: "auto", marginTop: 50, marginBottom: 10, textAlign: "center", textTransform: "none", }}
variant="outlined" variant="outlined"
disabled={newWorkflow === true} disabled={newWorkflow === true}
color="secondary" color="secondary"
@@ -1159,24 +1178,25 @@ const EditWorkflow = (props) => {
setShowMoreClicked(!showMoreClicked); setShowMoreClicked(!showMoreClicked);
}} }}
> >
{showMoreClicked ? <ExpandLessIcon style={{marginRight: 10, }}/> : <ExpandMoreIcon style={{marginRight: 10, }}/>} {showMoreClicked ? <ExpandLessIcon style={{ marginRight: 10, }} /> : <ExpandMoreIcon style={{ marginRight: 10, }} />}
{showMoreClicked ? "Less Options": "More Options"} {showMoreClicked ? "Less Options" : "More Options"}
</Button> </Button>
</Tooltip> </Tooltip>
</div> </div>
</DialogContent> </DialogContent>
{newWorkflow === true ? {newWorkflow === true ?
<span style={{marginTop: 30, }}> <span style={{ marginTop: 30, }}>
<Typography variant="h6" style={{marginLeft: 30, paddingBottom: 0, }}> <Typography variant="h6" style={{ marginLeft: 30, paddingBottom: 0, }}>
Relevant Workflows Relevant Workflows
</Typography> </Typography>
{priority === null || priority === undefined ? null : {priority === null || priority === undefined ? null :
<div style={{marginLeft: 30, }}> <div style={{ marginLeft: 30, }}>
<WorkflowTemplatePopup <WorkflowTemplatePopup
userdata={userdata} userdata={userdata}
globalUrl={globalUrl} globalUrl={globalUrl}
@@ -1214,7 +1234,7 @@ const EditWorkflow = (props) => {
</div> </div>
: null*/} : null*/}
</FormControl> </FormControl>
</Drawer> </Drawer >
) )
} }
+52 -2
View File
@@ -114,6 +114,7 @@ const CodeEditor = (props) => {
editorData, editorData,
setAiQueryModalOpen, setAiQueryModalOpen,
fullScreenMode
} = props } = props
const [localcodedata, setlocalcodedata] = React.useState(codedata === undefined || codedata === null || codedata.length === 0 ? "" : codedata); const [localcodedata, setlocalcodedata] = React.useState(codedata === undefined || codedata === null || codedata.length === 0 ? "" : codedata);
@@ -999,6 +1000,55 @@ const CodeEditor = (props) => {
} }
} }
if (fullScreenMode) {
return (
<AceEditor
mode="python"
theme="gruvbox"
value={localcodedata}
onChange={(value, editor) => {
// setlocalcodedata(value)
// expectedOutput(value)
// highlight_variables(value,editor)
setlocalcodedata(value)
setcodedata(value)
}}
name="python-editor"
fontSize={14}
width="100%"
height="100%"
showPrintMargin={false}
showGutter={true}
markers={markers}
highlightActiveLine={false}
enableBasicAutocompletion={true}
completers={[customCompleter]}
style={{
wordBreak: "break-word",
marginTop: 0,
paddingBottom: 10,
overflowY: "auto",
whiteSpace: "pre-wrap",
wordWrap: "break-word",
backgroundColor: "rgba(40,40,40,1)",
zIndex: activeDialog === "codeeditor" ? 1200 : 1100,
}}
setOptions={{
enableBasicAutocompletion: true,
enableLiveAutocompletion: true,
enableSnippets: true,
showLineNumbers: true,
tabSize: 4,
fontFamily: "'JetBrains Mono', Consolas, monospace",
useSoftTabs: true
}}
/>
)
}
return ( return (
<Dialog <Dialog
aria-labelledby="draggable-dialog-title" aria-labelledby="draggable-dialog-title"
@@ -1130,7 +1180,7 @@ const CodeEditor = (props) => {
*/} */}
{ isFileEditor ? null : { isFileEditor ? null :
<div style={{display: "flex", maxHeight: 40, }}> <div style={{display: "flex", maxHeight: 40, }}>
{selectedAction.name === "execute_python" ? {selectedAction?.name === "execute_python" ?
<Typography variant="body1" style={{marginTop: 5, }}> <Typography variant="body1" style={{marginTop: 5, }}>
Run Python Code Run Python Code
</Typography> </Typography>
@@ -1300,7 +1350,7 @@ const CodeEditor = (props) => {
maxHeight: 650, maxHeight: 650,
}} }}
> >
{actionlist.map((innerdata) => { {actionlist?.map((innerdata) => {
const icon = const icon =
innerdata.type === "action" ? ( innerdata.type === "action" ? (
<AppsIcon style={{ marginRight: 10 }} /> <AppsIcon style={{ marginRight: 10 }} />
+80 -22
View File
@@ -1,5 +1,5 @@
/* eslint-disable react/no-multi-comp */ /* eslint-disable react/no-multi-comp */
import React, { useState, useEffect, useLayoutEffect, memo, useMemo, useRef } from "react"; import React, { useState, useEffect, useLayoutEffect, memo, useMemo, useRef, useContext } from "react";
import ReactDOM from "react-dom" import ReactDOM from "react-dom"
import theme from "../theme.jsx"; import theme from "../theme.jsx";
@@ -72,6 +72,8 @@ import {
ButtonGroup, ButtonGroup,
} from "@mui/material"; } from "@mui/material";
import CodeIcon from '@mui/icons-material/Code';
import { import {
Folder as FolderIcon, Folder as FolderIcon,
VerifiedUser as VerifiedUserIcon, VerifiedUser as VerifiedUserIcon,
@@ -151,6 +153,8 @@ import PaperComponent from "../components/PaperComponent.jsx"
import ExtraApps from "../components/ExtraApps.jsx" import ExtraApps from "../components/ExtraApps.jsx"
import EditWorkflow from "../components/EditWorkflow.jsx" import EditWorkflow from "../components/EditWorkflow.jsx"
import { act } from "react"; import { act } from "react";
import { Context } from "../context/ContextApi.jsx";
import transitions from "@material-ui/core/styles/transitions.js";
// import AppStats from "../components/AppStats.jsx"; // import AppStats from "../components/AppStats.jsx";
const noImage = "/public/no_image.png"; const noImage = "/public/no_image.png";
@@ -396,6 +400,9 @@ const AngularWorkflow = (defaultprops) => {
props.match = {} props.match = {}
props.match.params = params props.match.params = params
const { leftSideBarOpenByClick, windowWidth } = useContext(Context)
const [workflowAsCode, setWorkflowAsCode] = useState(false);
var to_be_copied = ""; var to_be_copied = "";
const [firstrequest, setFirstrequest] = React.useState(true); const [firstrequest, setFirstrequest] = React.useState(true);
const [cystyle] = useState(cytoscapestyle); const [cystyle] = useState(cytoscapestyle);
@@ -801,6 +808,15 @@ const releaseToConnectLabel = "Release to Connect"
}) })
} }
useEffect(() => {
console.log("Loaded workflow: ", workflow)
if (workflow.actions?.length == 1) {
if (workflow.actions[0].app_id == "3e320a20966d33c9b7e6790b2705f0bf") {
setWorkflowAsCode(true);
}
}
}, [workflow]);
// Event for making sure app is correct // Event for making sure app is correct
useEffect(() => { useEffect(() => {
if (selectedApp === undefined || selectedApp === null && selectedApp.app_name === undefined) { if (selectedApp === undefined || selectedApp === null && selectedApp.app_name === undefined) {
@@ -3227,6 +3243,10 @@ const releaseToConnectLabel = "Release to Connect"
cy.add(nodeData) cy.add(nodeData)
if (workflowAsCode) {
setWorkflowAsCode(false)
}
// Wait 100ms then add a style for it // Wait 100ms then add a style for it
setTimeout(() => { setTimeout(() => {
const node = cy.getElementById(chunkJson.id) const node = cy.getElementById(chunkJson.id)
@@ -6318,6 +6338,10 @@ const releaseToConnectLabel = "Release to Connect"
} }
} }
if (nodedata.app_id == "3e320a20966d33c9b7e6790b2705f0bf") {
setWorkflowAsCode(true);
}
if (nodedata.decorator !== true && nodedata.attachedTo === undefined) { if (nodedata.decorator !== true && nodedata.attachedTo === undefined) {
var newdata = JSON.parse(JSON.stringify(nodedata)) var newdata = JSON.parse(JSON.stringify(nodedata))
newdata.large_image = "" newdata.large_image = ""
@@ -9002,7 +9026,7 @@ const releaseToConnectLabel = "Release to Connect"
}); });
}; };
const parsedHeight = isMobile ? bodyHeight - appBarSize * 4 : bodyHeight - appBarSize - 50 const parsedHeight = isMobile ? bodyHeight - appBarSize * 4 : userdata?.support ? bodyHeight - 80 : bodyHeight - appBarSize - 50
const appViewStyle = { const appViewStyle = {
marginLeft: 5, marginLeft: 5,
marginRight: 5, marginRight: 5,
@@ -9342,6 +9366,7 @@ const releaseToConnectLabel = "Release to Connect"
minHeight: parsedHeight, minHeight: parsedHeight,
maxHeight: parsedHeight, maxHeight: parsedHeight,
overflow: "hidden", overflow: "hidden",
paddingTop: userdata?.support ? 10 : 0,
}} }}
> >
{thisview} {thisview}
@@ -11016,11 +11041,14 @@ const releaseToConnectLabel = "Release to Connect"
iterations += 1; iterations += 1;
} }
// Remove on the end as we don't want to remove everything // Remove on the end as we don't want to remove everything
results = results.filter((data) => data.id !== action.id) results = results.filter((data) => data.id !== action.id)
results = results.filter((data) => data.type === "ACTION" || data.app_name === "Shuffle Workflow" || data.app_name === "User Input") results = results.filter((data) => data.type === "ACTION" || data.app_name === "Shuffle Workflow" || data.app_name === "User Input")
results.push({ label: "Execution Argument", type: "INTERNAL" }) results.push({ label: "Execution Argument", type: "INTERNAL" })
console.log(results)
return results return results
} }
@@ -11050,9 +11078,9 @@ const releaseToConnectLabel = "Release to Connect"
const minSize = 370 const minSize = 370
var rightsidebarStyle = { var rightsidebarStyle = {
position: "fixed", position: "fixed",
top: appBarSize + 25, top: userdata?.support ? appBarSize - 35 : appBarSize + 25,
right: 25, right: 25,
height: "80vh", height: userdata?.support ? "90vh": "80vh",
width: isMobile ? "100%" : minSize, width: isMobile ? "100%" : minSize,
minWidth: minSize, minWidth: minSize,
maxWidth: 600, maxWidth: 600,
@@ -15961,24 +15989,33 @@ const releaseToConnectLabel = "Release to Connect"
const cytoscapeViewWidths = isMobile ? 50 : 950; const cytoscapeViewWidths = isMobile ? 50 : 950;
const bottomBarStyle = { const bottomBarStyle = {
position: "fixed", position: "fixed",
right: isMobile ? 20 : 20, transition: "all 0.3s ease",
bottom: isMobile ? undefined : 0, minWidth: userdata?.support && windowWidth < 1600 && leftSideBarOpenByClick ? 800 : cytoscapeViewWidths,
top: isMobile ? appBarSize + 55 : undefined, maxWidth: userdata?.support && windowWidth < 1600 && leftSideBarOpenByClick ? 800 : cytoscapeViewWidths,
left: isMobile ? undefined : leftBarSize,
minWidth: cytoscapeViewWidths,
maxWidth: cytoscapeViewWidths,
marginLeft: 20, marginLeft: 20,
marginBottom: 20, marginBottom: 30,
zIndex: 10, zIndex: 10,
}; transform: isMobile
? `translateX(20px)`
: `translateX(${userdata?.support
? leftSideBarOpenByClick ? 340 : 330
: leftBarSize}px)`,
top: isMobile ? appBarSize + 55 : undefined,
bottom: isMobile ? undefined : 0,
};
const topBarStyle = { const topBarStyle = {
position: "fixed", position: "fixed",
right: 0, top: isMobile ? 30 : userdata?.support ? appBarSize - 20 : appBarSize + 20,
left: isMobile ? 20 : leftBarSize + 20,
top: isMobile ? 30 : appBarSize + 20,
pointerEvents: "none", pointerEvents: "none",
} transition: "transform 0.3s ease",
transform: isMobile
? `translateX(20px)`
: userdata?.support
? `translateX(${leftSideBarOpenByClick ? 340 : 330}px)`
: `translateX(${leftBarSize + 20}px)`,
};
@@ -16028,6 +16065,26 @@ const releaseToConnectLabel = "Release to Connect"
pointerEvents: "none", pointerEvents: "none",
}}>{workflow.name}</h2> }}>{workflow.name}</h2>
</Breadcrumbs> </Breadcrumbs>
{workflowAsCode && (
<Tooltip title="Switch to Code View">
<Button
startIcon={<CodeIcon />}
variant="outlined"
color="secondary"
onClick={() => {
window.location.href = `/workflows/${workflow.id}/code`
}}
style={{
marginTop: 10,
marginLeft: 5,
height: 40,
pointerEvents: "auto",
}}
>
Build this workflow as code
</Button>
</Tooltip>
)}
{!distributedFromParent ? {!distributedFromParent ?
isCorrectOrg ? null : isCorrectOrg ? null :
@@ -16706,11 +16763,12 @@ const releaseToConnectLabel = "Release to Connect"
style={{ style={{
border: "1px solid rgba(255,255,255,0.1)", border: "1px solid rgba(255,255,255,0.1)",
position: "absolute", position: "absolute",
bottom: 130, bottom: 140,
left: leftBarSize+20, left: userdata?.support ? leftSideBarOpenByClick ? 620 : 435 : leftBarSize + 20,
color: "white", color: "white",
padding: 10, padding: 10,
borderRadius: theme.palette?.borderRadius, borderRadius: theme.palette?.borderRadius,
transition: "left 0.3s ease, top 0.3s ease",
}} }}
> >
@@ -20293,7 +20351,7 @@ const releaseToConnectLabel = "Release to Connect"
); );
const newView = ( const newView = (
<div style={{ color: "white" }}> <div style={{ color: "white", marginLeft: userdata?.support ? leftSideBarOpenByClick ? 280 : 100 : 0, transition: "margin-left 0.3s ease", }}>
<div <div
style={{ display: "flex", borderTop: "1px solid rgba(91, 96, 100, 1)" }} style={{ display: "flex", borderTop: "1px solid rgba(91, 96, 100, 1)" }}
> >
@@ -20330,7 +20388,7 @@ const releaseToConnectLabel = "Release to Connect"
wheelSensitivity={0.25} wheelSensitivity={0.25}
style={{ style={{
width: cytoscapeWidth, width: cytoscapeWidth,
height: bodyHeight - appBarSize - 5, height: userdata?.support ? bodyHeight - 20 : bodyHeight - appBarSize - 5,
backgroundColor: theme.palette.surfaceColor, backgroundColor: theme.palette.surfaceColor,
}} }}
stylesheet={cystyle} stylesheet={cystyle}
@@ -22225,7 +22283,7 @@ const releaseToConnectLabel = "Release to Connect"
const loadedCheck = const loadedCheck =
isLoaded && workflowDone ? ( isLoaded && workflowDone ? (
<div> <div style={{overflow:'hidden'}}>
{newView} {newView}
<VariablesModal variableInfo={variableInfo} setVariableInfo={setVariableInfo} /> <VariablesModal variableInfo={variableInfo} setVariableInfo={setVariableInfo} />
<ExecutionVariableModal variableInfo={variableInfo} setVariableInfo={setVariableInfo} /> <ExecutionVariableModal variableInfo={variableInfo} setVariableInfo={setVariableInfo} />
@@ -22359,7 +22417,7 @@ const releaseToConnectLabel = "Release to Connect"
/> />
</div> </div>
) : ( ) : (
<div style={{width: 200, margin: "auto", marginTop: 300, textAlign: "center", }}> <div style={{width: 200, margin: "auto", paddingTop: 300, textAlign: "center", }}>
<CircularProgress style={{}} /> <CircularProgress style={{}} />
<Typography variant="body2" color="textSecondary" style={{marginTop: 10, }}> <Typography variant="body2" color="textSecondary" style={{marginTop: 10, }}>
Loading Workflow & Apps... Loading Workflow & Apps...
+1 -1
View File
@@ -302,7 +302,7 @@ const SetAuthentication = (props) => {
} }
return ( return (
<div style={{ padding: 50, border: failed === true ? `1px solid ${red}` : "1px solid rgba(255,255,255,0.6)", borderRadius: theme.palette?.borderRadius, width: 500, margin: "auto", marginTop: 50, itemAlign: "center", textAlign: "center",}}> <div style={{ padding: 50, border: failed === true ? `1px solid ${red}` : "1px solid rgba(255,255,255,0.6)", borderRadius: theme.palette?.borderRadius, width: 500, margin: "auto", paddingTop: 50, itemAlign: "center", textAlign: "center",}}>
<Typography <Typography
variant="h4" variant="h4"
style={{ marginLeft: "auto", marginRight: "auto", marginTop: 50}} style={{ marginLeft: "auto", marginRight: "auto", marginTop: 50}}
+83 -73
View File
@@ -105,13 +105,11 @@ const useStyles = makeStyles(() => {
display: "none", display: "none",
}, },
"& .MuiDataGrid-colCell, .MuiDataGrid-cell": { "& .MuiDataGrid-colCell, .MuiDataGrid-cell": {
borderRight: `1px solid ${ borderRight: `1px solid ${theme?.palette?.type === "light" ? "white" : "#303030"
theme?.palette?.type === "light" ? "white" : "#303030"
}`, }`,
}, },
"& .MuiDataGrid-columnsContainer, .MuiDataGrid-cell": { "& .MuiDataGrid-columnsContainer, .MuiDataGrid-cell": {
borderBottom: `1px solid ${ borderBottom: `1px solid ${theme?.palette?.type === "light" ? "#f0f0f0" : "#303030"
theme?.palette?.type === "light" ? "#f0f0f0" : "#303030"
}`, }`,
}, },
"& .MuiDataGrid-cell": { "& .MuiDataGrid-cell": {
@@ -157,7 +155,7 @@ export const GetIconInfo = (action) => {
"preview", "preview",
], ],
}, },
{ key: "add", values: ["add", "accept", ] }, { key: "add", values: ["add", "accept",] },
{ key: "delete", values: ["delete", "remove", "clear", "clean", "dismiss",] }, { key: "delete", values: ["delete", "remove", "clear", "clean", "dismiss",] },
{ {
key: "send", key: "send",
@@ -175,7 +173,7 @@ export const GetIconInfo = (action) => {
}, },
{ {
key: "repeat", key: "repeat",
values: ["repeat", "retry", "pause", "skip", "copy", "replicat", "demo", ], values: ["repeat", "retry", "pause", "skip", "copy", "replicat", "demo",],
}, },
{ key: "execute", values: ["execute", "run", "play", "raise"] }, { key: "execute", values: ["execute", "run", "play", "raise"] },
{ key: "extract", values: ["extract", "unpack", "decompress", "open"] }, { key: "extract", values: ["extract", "unpack", "decompress", "open"] },
@@ -209,7 +207,7 @@ export const GetIconInfo = (action) => {
var selectedKey = "" var selectedKey = ""
if (action.app_name == "Integration Framework") { if (action.app_name == "Integration Framework") {
selectedKey = "magic" selectedKey = "magic"
}else if (action.name === undefined || action.name === null) { } else if (action.name === undefined || action.name === null) {
} else { } else {
const actionname = action.name.toLowerCase() const actionname = action.name.toLowerCase()
for (var key in iconList) { for (var key in iconList) {
@@ -498,7 +496,7 @@ export const validateJson = (showResult) => {
var result = showResult; var result = showResult;
try { try {
result = jsonvalid ? JSON.parse(showResult, {"storeAsString": true}) : showResult; result = jsonvalid ? JSON.parse(showResult, { "storeAsString": true }) : showResult;
} catch (e) { } catch (e) {
////console.log("Failed parsing JSON even though its valid: ", e) ////console.log("Failed parsing JSON even though its valid: ", e)
jsonvalid = false; jsonvalid = false;
@@ -665,7 +663,7 @@ const Workflows = (props) => {
const [view, setView] = React.useState("grid"); const [view, setView] = React.useState("grid");
const [filters, setFilters] = React.useState([]); const [filters, setFilters] = React.useState([]);
const [submitLoading, setSubmitLoading] = React.useState(false); const [submitLoading, setSubmitLoading] = React.useState(false);
const [actionImageList, setActionImageList] = React.useState([{"large_image": ""}]) const [actionImageList, setActionImageList] = React.useState([{ "large_image": "" }])
const [firstLoad, setFirstLoad] = React.useState(true); const [firstLoad, setFirstLoad] = React.useState(true);
const [showMoreClicked, setShowMoreClicked] = React.useState(false); const [showMoreClicked, setShowMoreClicked] = React.useState(false);
@@ -841,7 +839,7 @@ const Workflows = (props) => {
setApps(responseJson); setApps(responseJson);
}) })
.catch((error) => { .catch((error) => {
console.log("App loading error: "+error.toString()); console.log("App loading error: " + error.toString());
}); });
} }
@@ -1038,7 +1036,7 @@ const Workflows = (props) => {
// Do backwards so it doesn't change // Do backwards so it doesn't change
toast("Starting deletion of workflows. This might take a while.") toast("Starting deletion of workflows. This might take a while.")
for (var i = selectedWorkflowIndexes.length - 1; i >= 0; i--) { for (var i = selectedWorkflowIndexes.length - 1; i >= 0; i--) {
const workflow = filteredWorkflows[selectedWorkflowIndexes[i]-1] const workflow = filteredWorkflows[selectedWorkflowIndexes[i] - 1]
if (workflow !== undefined && workflow !== null && workflow.id !== undefined && workflow.id !== null) { if (workflow !== undefined && workflow !== null && workflow.id !== undefined && workflow.id !== null) {
deleteWorkflow(workflow.id, true) deleteWorkflow(workflow.id, true)
} }
@@ -1432,7 +1430,7 @@ const Workflows = (props) => {
display: "flex", display: "flex",
minWidth: isMobile ? "100%" : 1024, minWidth: isMobile ? "100%" : 1024,
maxWidth: isMobile ? "100%" : 1024, maxWidth: isMobile ? "100%" : 1024,
margin: drawerWidth === 0 ? "auto" : `auto ${drawerWidth+100} auto auto`, margin: drawerWidth === 0 ? "auto" : `auto ${drawerWidth + 100} auto auto`,
paddingBottom: 200, paddingBottom: 200,
}; };
@@ -2021,7 +2019,7 @@ const Workflows = (props) => {
continue continue
} }
if (appsFound.findIndex(data => data.app_name === parsedAction.app_name) < 0){ if (appsFound.findIndex(data => data.app_name === parsedAction.app_name) < 0) {
appsFound.push(parsedAction) appsFound.push(parsedAction)
} }
} }
@@ -2216,7 +2214,7 @@ const Workflows = (props) => {
alt={foundOrg.name} alt={foundOrg.name}
src={foundOrg.image} src={foundOrg.image}
style={imageStyle} style={imageStyle}
onClick={() => {}} onClick={() => { }}
/> />
); );
@@ -2258,7 +2256,7 @@ const Workflows = (props) => {
} }
return ( return (
<div style={{width: "100%", minWidth: 320, position: "relative", border: highlightIds.includes(data.id) ? "2px solid #f85a3e" : isDistributed || hasSuborgs ? "1px solid #40E0D0" : "inherit", borderRadius: theme.palette?.borderRadius, }}> <div style={{ width: "100%", minWidth: 320, position: "relative", border: highlightIds.includes(data.id) ? "2px solid #f85a3e" : isDistributed || hasSuborgs ? "1px solid #40E0D0" : "inherit", borderRadius: theme.palette?.borderRadius, }}>
<Paper square style={paperAppStyle}> <Paper square style={paperAppStyle}>
{selectedCategory !== "" ? {selectedCategory !== "" ?
<Tooltip title={`Usecase Category: ${selectedCategory}`} placement="bottom"> <Tooltip title={`Usecase Category: ${selectedCategory}`} placement="bottom">
@@ -2304,9 +2302,9 @@ const Workflows = (props) => {
*/ */
}} }}
title={ title={
<div style={{width: "100%", minWidth: 250, maxWidth: 310, }}> <div style={{ width: "100%", minWidth: 250, maxWidth: 310, }}>
{data.image !== undefined && data.image !== null && data.image.length > 0 ? {data.image !== undefined && data.image !== null && data.image.length > 0 ?
<img src={data.image} alt={data.name} style={{backgroundColor: theme.palette.surfaceColor, maxWidth: 300, minWidth: 250, borderRadius: theme.palette?.borderRadius, }} /> <img src={data.image} alt={data.name} style={{ backgroundColor: theme.palette.surfaceColor, maxWidth: 300, minWidth: 250, borderRadius: theme.palette?.borderRadius, }} />
: null} : null}
<Typography> <Typography>
Edit '{data.name}' Edit '{data.name}'
@@ -2332,7 +2330,7 @@ const Workflows = (props) => {
}} }}
> >
<Link <Link
to={"/workflows/" + data.id} to={data.workflow_as_code ? `/workflows/${data.id}/code` : `/workflows/${data.id}`}
style={{ textDecoration: "none", color: "inherit" }} style={{ textDecoration: "none", color: "inherit" }}
> >
{parsedName} {parsedName}
@@ -2342,8 +2340,8 @@ const Workflows = (props) => {
</Grid> </Grid>
<Grid item style={workflowActionStyle}> <Grid item style={workflowActionStyle}>
{appGroup.length > 0 ? {appGroup.length > 0 ?
<div style={{display: "flex", marginTop: 8, }}> <div style={{ display: "flex", marginTop: 8, }}>
<AvatarGroup max={4} style={{marginLeft: 5, maxHeight: 24,}}> <AvatarGroup max={4} style={{ marginLeft: 5, maxHeight: 24, }}>
{appGroup.map((data, index) => { {appGroup.map((data, index) => {
return ( return (
<div <div
@@ -2359,7 +2357,7 @@ const Workflows = (props) => {
}} }}
> >
<Tooltip color="primary" title={data.app_name} placement="bottom"> <Tooltip color="primary" title={data.app_name} placement="bottom">
<Avatar alt={data.app_name} src={data.large_image} style={{width: 24, height: 24}}/> <Avatar alt={data.app_name} src={data.large_image} style={{ width: 24, height: 24 }} />
</Tooltip> </Tooltip>
</div> </div>
) )
@@ -2509,7 +2507,7 @@ const Workflows = (props) => {
: null} : null}
</Grid> </Grid>
{data.actions !== undefined && data.actions !== null ? ( {data.actions !== undefined && data.actions !== null ? (
<div style={{position: "absolute", top: 10, right: 10, }}> <div style={{ position: "absolute", top: 10, right: 10, }}>
<IconButton <IconButton
aria-label="more" aria-label="more"
aria-controls="long-menu" aria-controls="long-menu"
@@ -2524,7 +2522,7 @@ const Workflows = (props) => {
) : null} ) : null}
{(data.sharing !== undefined && data.sharing !== null && data.sharing === "form") || (data?.form_control?.input_markdown !== undefined && data?.form_control?.input_markdown !== null && data?.form_control?.input_markdown !== "") ? {(data.sharing !== undefined && data.sharing !== null && data.sharing === "form") || (data?.form_control?.input_markdown !== undefined && data?.form_control?.input_markdown !== null && data?.form_control?.input_markdown !== "") ?
<Tooltip title="Edit Form" placement="top"> <Tooltip title="Edit Form" placement="top">
<div style={{position: "absolute", top: 45, right: 8, }}> <div style={{ position: "absolute", top: 45, right: 8, }}>
<IconButton <IconButton
aria-label="more" aria-label="more"
aria-controls="long-menu" aria-controls="long-menu"
@@ -2557,6 +2555,7 @@ const Workflows = (props) => {
currentUsecases, currentUsecases,
inputblogpost, inputblogpost,
inputstatus, inputstatus,
workflow_as_code,
) => { ) => {
var method = "POST"; var method = "POST";
@@ -2578,6 +2577,10 @@ const Workflows = (props) => {
// FIXME: Loop triggers and turn them off? // FIXME: Loop triggers and turn them off?
} }
if (workflow_as_code !== undefined && workflow_as_code !== null && workflow_as_code !== "") {
workflowdata["workflow_as_code"] = workflow_as_code
}
workflowdata["name"] = name; workflowdata["name"] = name;
workflowdata["description"] = description; workflowdata["description"] = description;
if (tags !== undefined) { if (tags !== undefined) {
@@ -2587,6 +2590,7 @@ const Workflows = (props) => {
workflowdata["blogpost"] = inputblogpost workflowdata["blogpost"] = inputblogpost
workflowdata["status"] = inputstatus workflowdata["status"] = inputstatus
if (defaultReturnValue !== undefined) { if (defaultReturnValue !== undefined) {
workflowdata["default_return_value"] = defaultReturnValue; workflowdata["default_return_value"] = defaultReturnValue;
} }
@@ -2629,7 +2633,11 @@ const Workflows = (props) => {
if (redirect) { if (redirect) {
//window.location.pathname = "/workflows/" + responseJson["id"]; //window.location.pathname = "/workflows/" + responseJson["id"];
navigate("/workflows/" + responseJson["id"])
// navigate("/workflows/" + responseJson["id"])
navigate(`/workflows/${responseJson["id"]}` + (workflow_as_code ? "/code" : ""))
// {data.workflow_as_code ? `/workflows/${data.id}/code` : `/workflows/${data.id}`}
//setModalOpen(false); //setModalOpen(false);
} else if (!redirect) { } else if (!redirect) {
// Update :) // Update :)
@@ -2872,8 +2880,8 @@ const Workflows = (props) => {
<Grid item> <Grid item>
<div style={{ display: "flex" }}> <div style={{ display: "flex" }}>
{appGroup.length > 0 ? {appGroup.length > 0 ?
<div style={{display: "flex", marginTop: 3, }}> <div style={{ display: "flex", marginTop: 3, }}>
<AvatarGroup max={4} style={{marginLeft: 5, maxHeight: 24,}}> <AvatarGroup max={4} style={{ marginLeft: 5, maxHeight: 24, }}>
{appGroup.map((data, index) => { {appGroup.map((data, index) => {
return ( return (
<div <div
@@ -2889,7 +2897,7 @@ const Workflows = (props) => {
}} }}
> >
<Tooltip color="primary" title={data.app_name} placement="bottom"> <Tooltip color="primary" title={data.app_name} placement="bottom">
<Avatar alt={data.app_name} src={data.large_image} style={{width: 24, height: 24}}/> <Avatar alt={data.app_name} src={data.large_image} style={{ width: 24, height: 24 }} />
</Tooltip> </Tooltip>
</div> </div>
) )
@@ -3064,7 +3072,7 @@ const Workflows = (props) => {
width: 100, width: 100,
sortable: false, sortable: false,
disableClickEventBubbling: true, disableClickEventBubbling: true,
renderCell: (params) => {}, renderCell: (params) => { },
}, },
]; ];
@@ -3103,7 +3111,7 @@ const Workflows = (props) => {
<div style={gridContainer}> <div style={gridContainer}>
<Tooltip title={`New Workflow`} placement="bottom"> <Tooltip title={`New Workflow`} placement="bottom">
<IconButton <IconButton
style={{position: "absolute", top: 10, right: 50, zIndex: 1000}} style={{ position: "absolute", top: 10, right: 50, zIndex: 1000 }}
onClick={() => { onClick={() => {
setModalOpen(true) setModalOpen(true)
setIsEditing(false) setIsEditing(false)
@@ -3114,7 +3122,7 @@ const Workflows = (props) => {
</Tooltip> </Tooltip>
{filteredWorkflows.length === 0 ? null : {filteredWorkflows.length === 0 ? null :
<IconButton <IconButton
style={{position: "absolute", top: 10, right: 10, zIndex: 1000}} style={{ position: "absolute", top: 10, right: 10, zIndex: 1000 }}
disabled={selectedWorkflowIndexes.length === 0} disabled={selectedWorkflowIndexes.length === 0}
onClick={() => { onClick={() => {
setDeleteModalOpen(true) setDeleteModalOpen(true)
@@ -3197,9 +3205,9 @@ const Workflows = (props) => {
margin="dense" margin="dense"
fullWidth fullWidth
/> />
<div style={{display: "flex", marginTop: 10, }}> <div style={{ display: "flex", marginTop: 10, }}>
<MuiChipsInput <MuiChipsInput
style={{ flex: 1}} style={{ flex: 1 }}
InputProps={{ InputProps={{
style: { style: {
color: "white", color: "white",
@@ -3219,7 +3227,7 @@ const Workflows = (props) => {
}} }}
/> />
{usecases !== null && usecases !== undefined && usecases.length > 0 ? {usecases !== null && usecases !== undefined && usecases.length > 0 ?
<FormControl style={{flex: 1, marginLeft: 5, }}> <FormControl style={{ flex: 1, marginLeft: 5, }}>
<InputLabel htmlFor="grouped-select-usecase">Usecases</InputLabel> <InputLabel htmlFor="grouped-select-usecase">Usecases</InputLabel>
<Select <Select
defaultValue="" defaultValue=""
@@ -3262,7 +3270,7 @@ const Workflows = (props) => {
setUpdate(Math.random()); setUpdate(Math.random());
setSelectedUsecases(selectedUsecases) setSelectedUsecases(selectedUsecases)
}}> }}>
<Checkbox style={{color: selectedUsecases.includes(subcase.name) ? usecase.color : theme.palette.inputColor}} checked={selectedUsecases.includes(subcase.name)} /> <Checkbox style={{ color: selectedUsecases.includes(subcase.name) ? usecase.color : theme.palette.inputColor }} checked={selectedUsecases.includes(subcase.name)} />
<ListItemText primary={subcase.name} /> <ListItemText primary={subcase.name} />
</MenuItem> </MenuItem>
) )
@@ -3276,7 +3284,7 @@ const Workflows = (props) => {
</div> </div>
{showMoreClicked ? {showMoreClicked ?
<span style={{marginTop: 25, }}> <span style={{ marginTop: 25, }}>
<TextField <TextField
onBlur={(event) => { onBlur={(event) => {
if (event.target.value.toLowerCase() === "test") { if (event.target.value.toLowerCase() === "test") {
@@ -3330,7 +3338,7 @@ const Workflows = (props) => {
: null} : null}
<Tooltip color="primary" title={"Add more details"} placement="top"> <Tooltip color="primary" title={"Add more details"} placement="top">
<IconButton <IconButton
style={{ color: "white", margin: "auto", marginTop: 10, textAlign: "center", width: 50,}} style={{ color: "white", margin: "auto", marginTop: 10, textAlign: "center", width: 50, }}
onClick={() => { onClick={() => {
setShowMoreClicked(!showMoreClicked); setShowMoreClicked(!showMoreClicked);
}} }}
@@ -3624,7 +3632,7 @@ const Workflows = (props) => {
<div style={workflowViewStyle}> <div style={workflowViewStyle}>
<div style={{ display: "flex", marginTop: 25, }}> <div style={{ display: "flex", marginTop: 25, }}>
<div style={{ flex: 1 }}> <div style={{ flex: 1 }}>
<Typography variant="h1" style={{fontSize: 30}}> <Typography variant="h1" style={{ fontSize: 30 }}>
Workflows Workflows
</Typography> </Typography>
</div> </div>
@@ -3681,7 +3689,7 @@ const Workflows = (props) => {
</div> </div>
</div> </div>
<div style={{width: "100%", minHeight: isMobile ? 0 : hasWorkflows ? 0 : 51, maxHeight: isMobile ? 0 : 51, marginTop: 10, }}> <div style={{ width: "100%", minHeight: isMobile ? 0 : hasWorkflows ? 0 : 51, maxHeight: isMobile ? 0 : 51, marginTop: 10, }}>
{!isMobile && !hasWorkflows && usecases !== null && usecases !== undefined && usecases.length > 0 ? {!isMobile && !hasWorkflows && usecases !== null && usecases !== undefined && usecases.length > 0 ?
<div style={{ display: "flex", }}> <div style={{ display: "flex", }}>
{usecases.map((usecase, index) => { {usecases.map((usecase, index) => {
@@ -3689,7 +3697,7 @@ const Workflows = (props) => {
return null return null
} }
const percentDone = usecase.matches.length > 0 ? parseInt(usecase.matches.length/usecase.list.length*100) : 0 const percentDone = usecase.matches.length > 0 ? parseInt(usecase.matches.length / usecase.list.length * 100) : 0
if (percentDone === 0) { if (percentDone === 0) {
usecase = findMatches(usecase, workflows) usecase = findMatches(usecase, workflows)
} }
@@ -3702,7 +3710,7 @@ const Workflows = (props) => {
backgroundImage: `linear-gradient(to right, ${usecase.color}, ${usecase.color} ${percentDone}%, transparent ${percentDone}%, transparent 100%)`, backgroundImage: `linear-gradient(to right, ${usecase.color}, ${usecase.color} ${percentDone}%, transparent ${percentDone}%, transparent 100%)`,
backgroundColor: filters.includes(usecase.name.toLowerCase()) ? null : theme.palette.surfaceColor, backgroundColor: filters.includes(usecase.name.toLowerCase()) ? null : theme.palette.surfaceColor,
borderRadius: theme.palette?.borderRadius, borderRadius: theme.palette?.borderRadius,
marginRight: index === usecases.length-1 ? 0 : 10, marginRight: index === usecases.length - 1 ? 0 : 10,
cursor: "pointer", cursor: "pointer",
border: `2px solid ${usecase.color}`, border: `2px solid ${usecase.color}`,
overflow: "hidden", overflow: "hidden",
@@ -3719,10 +3727,10 @@ const Workflows = (props) => {
}} }}
> >
<span style={{ textDecoration: "none", display: "flex", }}> <span style={{ textDecoration: "none", display: "flex", }}>
<Typography variant="body1" color="textPrimary" style={{flex: 4, }}> <Typography variant="body1" color="textPrimary" style={{ flex: 4, }}>
{usecase.name} {usecase.name}
</Typography> </Typography>
<Typography variant="body2" color="textSecondary" style={{flex: 1, marginTop: 0,}}> <Typography variant="body2" color="textSecondary" style={{ flex: 1, marginTop: 0, }}>
{usecase.matches.length}/{usecase.list.length} {usecase.matches.length}/{usecase.list.length}
</Typography> </Typography>
</span> </span>
@@ -3805,8 +3813,8 @@ const Workflows = (props) => {
> >
<img <img
style={{ style={{
height: isCloud ? imgSize : imgSize+4, height: isCloud ? imgSize : imgSize + 4,
width: isCloud ? imgSize : imgSize+4, width: isCloud ? imgSize : imgSize + 4,
position: "absolute", position: "absolute",
top: -2, top: -2,
left: -2, left: -2,
@@ -3842,24 +3850,26 @@ const Workflows = (props) => {
) : null} ) : null}
{userdata.priorities !== undefined && userdata.priorities !== null && userdata.priorities.length > 0 && userdata.priorities[0].name.includes("CPU") && userdata.priorities[0].active === true ? {userdata.priorities !== undefined && userdata.priorities !== null && userdata.priorities.length > 0 && userdata.priorities[0].name.includes("CPU") && userdata.priorities[0].active === true ?
<div style={{border: "1px solid rgba(255,255,255,0.1)" , borderRadius: theme.palette?.borderRadius, marginTop: 10, <div style={{
marginBottom: 10, padding: 15, textAlign: "center" , height: 70, textAlign: "left" , backgroundColor: border: "1px solid rgba(255,255,255,0.1)", borderRadius: theme.palette?.borderRadius, marginTop: 10,
theme.palette.surfaceColor, display: "flex" , maxHeight: "105px", minHeight: "110px"}} marginBottom: 10, padding: 15, textAlign: "center", height: 70, textAlign: "left", backgroundColor:
theme.palette.surfaceColor, display: "flex", maxHeight: "105px", minHeight: "110px"
}}
> >
<div style={{flex: 2, overflow: "hidden",}}> <div style={{ flex: 2, overflow: "hidden", }}>
<Typography variant="body1" > <Typography variant="body1" >
{userdata.priorities[0].name} {userdata.priorities[0].name}
</Typography> </Typography>
<div style={{flex: "2 1 0%", overflow: "hidden"}}> <div style={{ flex: "2 1 0%", overflow: "hidden" }}>
<span style={{display: "flex", marginTop: "10px"}}> <span style={{ display: "flex", marginTop: "10px" }}>
<Typography variant="body2" color="textSecondary" style={{marginTop: "3px"}}> <Typography variant="body2" color="textSecondary" style={{ marginTop: "3px" }}>
{userdata.priorities[0].description} {userdata.priorities[0].description}
</Typography> </Typography>
</span> </span>
</div> </div>
</div> </div>
<div style={{flex: 1, display: "flex", marginLeft: 30, }}> <div style={{ flex: 1, display: "flex", marginLeft: 30, }}>
<Button style={{height: 50, borderRadius: 25, marginTop: 8, width: 175, backgroundColor: "rgba(255,255,255,0.8)"}} variant="contained" color="secondary" onClick={() => {navigate(userdata.priorities[0].url)}}> <Button style={{ height: 50, borderRadius: 25, marginTop: 8, width: 175, backgroundColor: "rgba(255,255,255,0.8)" }} variant="contained" color="secondary" onClick={() => { navigate(userdata.priorities[0].url) }}>
explore explore
</Button> </Button>
{/* {/*
@@ -3922,7 +3932,7 @@ const Workflows = (props) => {
{foundPriority != null && filteredWorkflows.length > 6 ? {foundPriority != null && filteredWorkflows.length > 6 ?
<Priority <Priority
style={{marginTop: 15, }} style={{ marginTop: 15, }}
globalUrl={globalUrl} globalUrl={globalUrl}
priority={foundPriority} priority={foundPriority}
checkLogin={checkLogin} checkLogin={checkLogin}
@@ -3994,7 +4004,7 @@ const Workflows = (props) => {
const workflowDownloadModalOpen = loadWorkflowsModalOpen ? ( const workflowDownloadModalOpen = loadWorkflowsModalOpen ? (
<Dialog <Dialog
open={loadWorkflowsModalOpen} open={loadWorkflowsModalOpen}
onClose={() => {}} onClose={() => { }}
PaperProps={{ PaperProps={{
style: { style: {
backgroundColor: theme.palette.surfaceColor, backgroundColor: theme.palette.surfaceColor,
@@ -4125,25 +4135,25 @@ const Workflows = (props) => {
//const [percentDone, setPercentDone] = React.useState(0) //const [percentDone, setPercentDone] = React.useState(0)
const percentDone = gettingStartedItems.filter((item) => item.done).length / gettingStartedItems.length * 100 const percentDone = gettingStartedItems.filter((item) => item.done).length / gettingStartedItems.length * 100
const GettingStartedItem = ({item, index}) => { const GettingStartedItem = ({ item, index }) => {
const [clicked, setClicked] = React.useState(false) const [clicked, setClicked] = React.useState(false)
const doneIcon = item.done ? <CheckCircleIcon style={{color: "#4caf50", marginRight: 10, }} /> : <RadioButtonUncheckedIcon disabled style={{color: "#bdbdbd", marginRight: 10, }} /> const doneIcon = item.done ? <CheckCircleIcon style={{ color: "#4caf50", marginRight: 10, }} /> : <RadioButtonUncheckedIcon disabled style={{ color: "#bdbdbd", marginRight: 10, }} />
return ( return (
<div <div
style={{cursor: "pointer", padding: 20, borderBottom: "1px solid rgba(255,255,255,0.3", backgroundColor: !clicked ? "#1f2023" : theme.palette.inputColor, }} style={{ cursor: "pointer", padding: 20, borderBottom: "1px solid rgba(255,255,255,0.3", backgroundColor: !clicked ? "#1f2023" : theme.palette.inputColor, }}
onClick={() => setClicked(true)} onClick={() => setClicked(true)}
> >
<Typography variant="body2" style={{display: "flex", textDecoration: item.done ? "line-through" : "none", }}> <Typography variant="body2" style={{ display: "flex", textDecoration: item.done ? "line-through" : "none", }}>
{doneIcon} {index + 1}. {item.name} {doneIcon} {index + 1}. {item.name}
</Typography> </Typography>
{clicked ? {clicked ?
<span> <span>
<Typography variant="body2" style={{marginLeft: 30, }}> <Typography variant="body2" style={{ marginLeft: 30, }}>
{item.description} {item.description}
</Typography> </Typography>
<Link to={item.link} style={{color: "inherit", textDecoration: "none", }}> <Link to={item.link} style={{ color: "inherit", textDecoration: "none", }}>
<Button variant={item.done ? "outlined" : "contained"} color="primary" style={{marginLeft: 30, marginTop: 5, }}> <Button variant={item.done ? "outlined" : "contained"} color="primary" style={{ marginLeft: 30, marginTop: 5, }}>
Configure Configure
</Button> </Button>
</Link> </Link>
@@ -4176,8 +4186,8 @@ const Workflows = (props) => {
}, },
}} }}
> >
<div style={{backgroundColor: "#f86a3e", display: "flex", }}> <div style={{ backgroundColor: "#f86a3e", display: "flex", }}>
<Typography variant="h6" style={{flex: 5, marginTop: 20, marginLeft: 20, marginBottom: 20, }}> <Typography variant="h6" style={{ flex: 5, marginTop: 20, marginLeft: 20, marginBottom: 20, }}>
Getting Started Getting Started
</Typography> </Typography>
<Tooltip <Tooltip
@@ -4193,28 +4203,28 @@ const Workflows = (props) => {
localStorage.setItem(sidebarKey, "closed"); localStorage.setItem(sidebarKey, "closed");
}} }}
> >
<ArrowRightIcon style={{color: "white"}} /> <ArrowRightIcon style={{ color: "white" }} />
</IconButton> </IconButton>
</Tooltip> </Tooltip>
</div> </div>
<div style={{padding: 20, }}> <div style={{ padding: 20, }}>
<Typography variant="body2"> <Typography variant="body2">
Setup progress: <b>{isNaN(percentDone) ? 0 : percentDone}%</b> Setup progress: <b>{isNaN(percentDone) ? 0 : percentDone}%</b>
</Typography> </Typography>
<LinearProgress color="primary" variant="determinate" value={percentDone} style={{marginTop: 5, height: 7, borderRadius: theme.palette?.borderRadius, }} /> <LinearProgress color="primary" variant="determinate" value={percentDone} style={{ marginTop: 5, height: 7, borderRadius: theme.palette?.borderRadius, }} />
<Typography variant="body2" style={{marginTop: 20, }}> <Typography variant="body2" style={{ marginTop: 20, }}>
Follow these steps to get you up and running! Follow these steps to get you up and running!
</Typography> </Typography>
<Divider style={{marginTop: 20, }} /> <Divider style={{ marginTop: 20, }} />
<Typography variant="body2" style={{color: "#f86a3e", marginTop: 20, cursor: "pointer", }} onClick={() => { <Typography variant="body2" style={{ color: "#f86a3e", marginTop: 20, cursor: "pointer", }} onClick={() => {
setVideoViewOpen(true) setVideoViewOpen(true)
}}> }}>
<b>Watch 2-min introduction video</b> <b>Watch 2-min introduction video</b>
</Typography> </Typography>
</div> </div>
<div style={{borderTop: "1px solid rgba(255,255,255,0.3)", }}> <div style={{ borderTop: "1px solid rgba(255,255,255,0.3)", }}>
{gettingStartedItems.map((item, index) => { {gettingStartedItems.map((item, index) => {
return ( return (
<GettingStartedItem key={index} item={item} index={index} /> <GettingStartedItem key={index} item={item} index={index} />
@@ -4262,7 +4272,7 @@ const Workflows = (props) => {
<iframe <iframe
width="560" width="560"
height="315" height="315"
style={{margin: "0px auto 0px auto", width: 560, height: 315,}} style={{ margin: "0px auto 0px auto", width: 560, height: 315, }}
src="https://www.youtube-nocookie.com/embed/rO7k9q3OgC0" src="https://www.youtube-nocookie.com/embed/rO7k9q3OgC0"
title="Introduction video" title="Introduction video"
frameborder="0" frameborder="0"
@@ -4280,7 +4290,7 @@ const Workflows = (props) => {
<TourButton /> <TourButton />
</ShepherdTour> </ShepherdTour>
*/} */}
<DropzoneWrapper onDrop={uploadFile} WorkflowView={WorkflowView}/> <DropzoneWrapper onDrop={uploadFile} WorkflowView={WorkflowView} />
{/*modalView*/} {/*modalView*/}
{deleteModal} {deleteModal}
{exportVerifyModal} {exportVerifyModal}