Tons of priority management fixes - both frontend & backend

This commit is contained in:
frikky
2023-06-23 01:08:11 +02:00
parent c9076e7124
commit e319f0e9b1
21 changed files with 482 additions and 15870 deletions
+1
View File
@@ -503,6 +503,7 @@ const App = (message, props) => {
path="/workflows"
element={
<Workflows
checkLogin={checkLogin}
cookies={cookies}
removeCookie={removeCookie}
isLoaded={isLoaded}
+1 -1
View File
@@ -362,7 +362,7 @@ const AppGrid = props => {
: null
}
<span style={{position: "absolute", display: "flex", textAlign: "right", float: "right", right: 0, bottom: 120, }}>
<span style={{position: "absolute", display: "flex", textAlign: "right", float: "right", right: 0, bottom: isMobile?"":120, }}>
<Typography variant="body2" color="textSecondary" style={{}}>
Search by
</Typography>
+2 -1
View File
@@ -39,8 +39,9 @@ const AppSearchPopout = (props) => {
return null
}
// <Paper style={{width: 275, maxHeight: 400, zIndex: 100000, padding: 25, paddingRight: 35, backgroundColor: theme.palette.surfaceColor, border: "1px solid rgba(255,255,255,0.2)", position: "absolute", top: -15, left: 50, }}>
return (
<Paper style={{width: 275, maxHeight: 400, zIndex: 12500, padding: 25, paddingRight: 35, backgroundColor: theme.palette.surfaceColor, border: "1px solid rgba(255,255,255,0.2)", position: "absolute", top: -15, left: 50, overflow: "hidden", }}>
<Paper style={{minWidth: 275, width: 275, minHeight: 400, maxHeight: 400, zIndex: 100000, padding: 25, paddingRight: 35, backgroundColor: theme.palette.surfaceColor, border: "1px solid rgba(255,255,255,0.2)", position: "absolute", top: -15, left: 50, }}>
{paperTitle !== undefined && paperTitle.length > 0 ?
<span>
<Typography variant="h6" style={{textAlign: "center"}}>
@@ -79,6 +79,17 @@ const ConfigureWorkflow = (props) => {
},
});
// ONLY when component is being unloaded, run stop() function
// This is to prevent the interval from running when the component is not being used
/*
useEffect(() => {
return () => {
stop()
}
}, [])
*/
// Where is this from?
if (workflow === undefined || workflow === null) {
return null;
+1 -4
View File
@@ -2729,10 +2729,7 @@ const ParsedAction = (props) => {
// Look for the ID
const found = false;
for (let [key,keyval] in Object.entries(workflowExecutions)) {
if (
workflowExecutions[key].results === undefined ||
workflowExecutions[key].results === null
) {
if (workflowExecutions[key].results === undefined || workflowExecutions[key].results === null) {
continue;
}
+5 -5
View File
@@ -15,7 +15,7 @@ import Priority from "../components/Priority.jsx";
import { useAlert } from "react-alert";
const Priorities = (props) => {
const { globalUrl, userdata, serverside, billingInfo, stripeKey, selectedOrganization, handleGetOrg, checkLogin, } = props;
const { globalUrl, userdata, serverside, billingInfo, stripeKey, checkLogin, } = props;
const [showDismissed, setShowDismissed] = React.useState(false);
const [showRead, setShowRead] = React.useState(false);
@@ -25,9 +25,9 @@ const Priorities = (props) => {
return (
<div style={{maxWidth: 1000, }}>
<h2 style={{ display: "inline" }}>Priorities</h2>
<h2 style={{ display: "inline" }}>Suggestions</h2>
<span style={{ marginLeft: 25 }}>
Priorities identified by Shuffle to help you discover ways to protect yourself.&nbsp;
Suggestions are tasks identified by Shuffle to help you discover ways to protect your and customers' company. These range from simple configurations in Shuffle to Usecases you may have missed.&nbsp;
<a
target="_blank"
rel="noopener noreferrer"
@@ -46,7 +46,7 @@ const Priorities = (props) => {
/>&nbsp; Show dismissed
{userdata.priorities === null || userdata.priorities === undefined || userdata.priorities.length === 0 ?
<Typography variant="h4">
No Priorities found
No Suggestions found
</Typography>
:
userdata.priorities.map((priority, index) => {
@@ -67,7 +67,7 @@ const Priorities = (props) => {
<Divider style={{marginTop: 50, marginBottom: 50, }} />
<h2 style={{ display: "inline" }}>Notifications</h2>
<span style={{ marginLeft: 25 }}>
Notifications help you find potential problems with your workflows and apps
Notifications help you find potential problems with your workflows and apps.&nbsp;
<a
target="_blank"
rel="noopener noreferrer"
+45 -7
View File
@@ -11,6 +11,11 @@ import {
Card,
} from "@material-ui/core";
// import magic wand icon from material ui icons
import {
AutoFixHigh as AutoFixHighIcon,
ArrowForward as ArrowForwardIcon,
} from '@mui/icons-material';
import { useAlert } from "react-alert";
const Priority = (props) => {
@@ -60,18 +65,51 @@ const Priority = (props) => {
});
}
return (
<div style={{border: priority.active === false ? "1px solid #000000" : priority.severity === 1 ? "1px solid #f85a3e" : "1px solid rgba(255,255,255,0.3)", borderRadius: theme.palette.borderRadius, marginTop: 10, marginBottom: 10, padding: 15, textAlign: "center", height: 70, textAlign: "left", backgroundColor: theme.palette.surfaceColor, display: "flex", }}>
<div style={{flex: 2, overflow: "hidden",}}>
<Typography variant="body1" >
{priority.name}
</Typography>
<Typography variant="body2" color="textSecondary">
{priority.description}
</Typography>
<span style={{display: "flex", }}>
{priority.type === "usecase" || priority.type == "apps" ? <AutoFixHighIcon style={{height: 19, width: 19, marginLeft: 3, marginRight: 10, }}/> : null}
<Typography variant="body1" >
{priority.name}
</Typography>
</span>
{priority.type === "usecase" && priority.description.includes("&") ?
<span style={{display: "flex", marginTop: 10, }}>
<img src={priority.description.split("&")[1]} alt={priority.name} style={{height: 30, width: 30, marginRight: 5, borderRadius: theme.palette.borderRadius, marginRight: 10, }} />
<Typography variant="body2" color="textSecondary" style={{marginTop: 3, }}>
{priority.description.split("&")[0]}
</Typography>
{priority.description.split("&").length > 3 ?
<span style={{display: "flex", }}>
<ArrowForwardIcon style={{marginLeft: 15, marginRight: 15, }}/>
<img src={priority.description.split("&")[3]} alt={priority.name+"2"} style={{height: 30, width: 30, borderRadius: theme.palette.borderRadius, marginRight: 10, }} />
<Typography variant="body2" color="textSecondary" style={{marginTop: 3}}>
{priority.description.split("&")[2]}
</Typography>
</span>
: null}
</span>
:
<Typography variant="body2" color="textSecondary">
{priority.description}
</Typography>
}
</div>
<div style={{flex: 1, display: "flex", marginLeft: 30, }}>
<Button style={{height: 50, borderRadius: 25, marginTop: 8, width: 200, marginRight: 10, color: priority.active === false ? "white" : "black", backgroundColor: priority.active === false ? theme.palette.inputColor : "white", }} variant="contained" color="secondary" onClick={() => {navigate(priority.url)}}>
<Button style={{height: 50, borderRadius: 25, marginTop: 8, width: 175, marginRight: 10, color: priority.active === false ? "white" : "black", backgroundColor: priority.active === false ? theme.palette.inputColor : "white", }} variant="contained" color="secondary" onClick={() => {
/*
ReactGA.event({
category: "",
action: `partner_${partner.name}_click`,
label: "",
})
*/
navigate(priority.url)
}}>
explore
</Button>
{priority.active === true ?
-44
View File
@@ -693,52 +693,8 @@ const WelcomeForm = (props) => {
<Typography variant="body1" style={{marginTop: 15, marginBottom: 0, maxWidth: 500, margin: "auto", marginBottom: 15, }} color="textSecondary">
These are some of our Workflow templates, used to start new Workflows. Use the right and left buttons to find <a href="/usecases" target="_blank" rel="norefferer" style={{color: "#f86a3e", textDecoration: "none", }}>new Usecases</a>, and click the orange button to build it.
</Typography>
{/*<Divider />*/}
{/*
<div style={{width: 475, margin: "auto",}}>
{usecaseButtons.map((usecase, index) => {
return (
<Chip
key={usecase.name}
style={{
backgroundColor: defaultSearch === usecase.name ? usecase.color : theme.palette.surfaceColor,
marginRight: 10,
paddingLeft: 5,
paddingRight: 5,
height: 28,
cursor: "pointer",
border: `1px solid ${usecase.color}`,
color: "white",
borderRadius: theme.palette.borderRadius,
}}
label={`${index+1}. ${usecase.name}`}
onClick={() => {
console.log("Clicked: ", usecase.name)
if (defaultSearch === usecase.name) {
//setSelectedUsecaseCategory("")
} else {
handleSetSearch(usecase.name, usecase.usecase)
}
//addFilter(usecase.name.slice(3,usecase.name.length))
}}
variant="outlined"
color="primary"
/>
)
})}
</div>
*/}
<div style={{marginTop: 0, }}>
{/*
<UsecaseSearch
globalUrl={globalUrl}
defaultSearch={defaultSearch}
appFramework={appFramework}
apps={apps}
/>
*/}
<div className="thumbs" style={{display: "flex"}}>
<Tooltip title={"Previous usecase"}>
<IconButton
+214 -33
View File
@@ -177,7 +177,7 @@ const Admin = (props) => {
const [secret2FA, setSecret2FA] = React.useState("");
const [show2faSetup, setShow2faSetup] = useState(false);
const [adminTab, setAdminTab] = React.useState(1);
const [adminTab, setAdminTab] = React.useState(2);
const [showApiKey, setShowApiKey] = useState(false);
const [billingInfo, setBillingInfo] = React.useState({});
const [selectedStatus, setSelectedStatus] = React.useState([]);
@@ -189,8 +189,6 @@ const Admin = (props) => {
}
}, [isDropzone]);
const isCloud = window.location.host === "localhost:3002" || window.location.host === "shuffler.io";
const get2faCode = (userId) => {
@@ -299,6 +297,165 @@ const Admin = (props) => {
)
}
// Basically just a simple way to get a generated email
// This also may help understand how to communicate with users
// both inside and outside Shuffle
// This could also be generated on the backend
const mailsendingButton = (org) => {
if (org === undefined || org === null) {
return ""
}
if (users.length === 0) {
return ""
}
// 1 mail based on users that have only apps
// Another based on those doing workflows
// Another based on those trying usecases(?) or templates
//
// Start based on edr, siem & ticketing
// Talk about enrichment?
// Check suggested usecases
// Check suggested workflows
var your_apps = "- Connecting "
var subject_add = 0
var subject = "Want to automate "
if (org.security_framework !== undefined && org.security_framework !== null) {
if (org.security_framework.cases.name !== undefined && org.security_framework.cases.name !== null && org.security_framework.cases.name !== "") {
your_apps += org.security_framework.cases.name.replace("_", " ", -1) + ", "
if (subject_add < 2) {
if (subject_add === 1) {
subject += " & "
}
subject_add += 1
subject += org.security_framework.cases.name.replace("_", " ", -1)
}
}
if (org.security_framework.siem.name !== undefined && org.security_framework.siem.name !== null && org.security_framework.siem.name !== "") {
your_apps += org.security_framework.siem.name.replace("_", " ", -1) + ", "
if (subject_add < 2) {
if (subject_add === 1) {
subject += " & "
}
subject_add += 1
subject += org.security_framework.siem.name.replace("_", " ", -1)
}
}
if (org.security_framework.communication.name !== undefined && org.security_framework.communication.name !== null && org.security_framework.communication.name !== "") {
your_apps += org.security_framework.communication.name.replace("_", " ", -1) + ", "
if (subject_add < 2) {
if (subject_add === 1) {
subject += " & "
}
subject_add += 1
subject += org.security_framework.communication.name.replace("_", " ", -1)
}
}
if (org.security_framework.edr.name !== undefined && org.security_framework.edr.name !== null && org.security_framework.edr.name !== "") {
your_apps += org.security_framework.edr.name.replace("_", " ", -1) + ", "
if (subject_add < 2) {
if (subject_add === 1) {
subject += " & "
}
subject_add += 1
subject += org.security_framework.edr.name.replace("_", " ", -1)
}
}
if (org.security_framework.intel.name !== undefined && org.security_framework.intel.name !== null && org.security_framework.intel.name !== "") {
your_apps += org.security_framework.intel.name.replace("_", " ", -1) + ", "
if (subject_add < 2) {
if (subject_add === 1) {
subject += " & "
}
subject_add += 1
subject += org.security_framework.intel.name.replace("_", " ", -1)
}
}
// Remove comma
subject += "?"
your_apps = your_apps.substring(0, your_apps.length - 2)
}
// Add usecases they may not have tried (from recommendations): org.priorities where item type is usecase
var usecases = "- Building usecases like "
const active_usecase = org.priorities.filter((item) => item.type === "usecase" && item.active === true)
if (active_usecase.length > 0) {
for (var i = 0; i < active_usecase.length; i++) {
if (active_usecase[i].name.includes("Suggested Usecase: ")) {
usecases += active_usecase[i].name.replace("Suggested Usecase: ", "", -1) + ", "
} else {
usecases += active_usecase[i].name + ", "
}
}
usecases = usecases.substring(0, usecases.length - 2)
}
if (your_apps.length <= 15) {
your_apps = ""
}
if (usecases.length <= 30) {
usecases = ""
}
var workflow_amount = "a few"
var admins = ""
// Loop users
for (var i = 0; i < users.length; i++) {
if (users[i].role === "admin") {
admins += users[i].username + ","
}
}
// Remove last comma
admins = admins.substring(0, admins.length - 1)
if (your_apps.length > 5) {
your_apps += "%0D%0A"
}
if (usecases.length > 5) {
usecases += "%0D%0A"
}
// Get drift username from userdata.username before @ in email
const username = userdata.username.substring(0, userdata.username.indexOf("@"))
var body = `Hey,%0D%0AI saw you trying to use Shuffle, and thought we may be able to help. Right now, it looks like you have ${workflow_amount} workflows made, but I'm not sure if you're getting the most out of Shuffle.%0D%0A%0D%0AIf you're interested, I'd love to set up a quick call to see if we can help you get more out of Shuffle. %0D%0A%0D%0A
Some of the things we can help with:%0D%0A
${your_apps}
- Properly authenticating and custom building apps%0D%0A
${usecases}
- Creating special usecases%0D%0A%0D%0A
Let me know if you're interested, or set up a call here: https://drift.me/${username}`
return `mailto:${admins}?subject=${subject}&body=${body}`
}
const deleteAuthentication = (data) => {
alert.info("Deleting auth " + data.label);
@@ -367,6 +524,13 @@ const Admin = (props) => {
});
};
if (userdata.support === true && selectedOrganization.id !== "" && selectedOrganization.id !== undefined && selectedOrganization.id !== null && selectedOrganization.id !== userdata.active_org.id) {
alert.info("Refreshing window to fix org support access")
window.location.reload()
return null
}
const handleVerify2FA = (userId, code) => {
const data = {
code: code,
@@ -799,6 +963,10 @@ const Admin = (props) => {
if (responseJson.lead_info !== undefined && responseJson.lead_info !== null) {
var leads = []
if (responseJson.lead_info.contacted) {
leads.push("contacted")
}
if (responseJson.lead_info.customer) {
leads.push("customer")
}
@@ -1181,11 +1349,6 @@ const Admin = (props) => {
var localData = "";
// useEffect(() => {
// console.log('confirm', fileContent);
// }, [fileContent])
const getSchedules = () => {
fetch(globalUrl + "/api/v1/workflows/schedules", {
@@ -1322,6 +1485,10 @@ const Admin = (props) => {
});
};
useEffect(() => {
getUsers()
}, []);
const getSettings = () => {
fetch(globalUrl + "/api/v1/getsettings", {
method: "GET",
@@ -2189,27 +2356,45 @@ const Admin = (props) => {
*/}
{userdata.support === true ?
<FormControl sx={{ m: 1, width: 300, }} style={{top: -10, right: 50, position: "absolute" }}>
<InputLabel id="">Status</InputLabel>
<Select
style={{minWidth: 150, maxWidth: 150, }}
labelId="multiselect-status"
id="multiselect-status"
multiple
value={selectedStatus}
onChange={handleStatusChange}
input={<OutlinedInput label="Status" />}
renderValue={(selected) => selected.join(', ')}
MenuProps={MenuProps}
>
{["lead", "pov", "demo done", "customer", "student", ].map((name) => (
<MenuItem key={name} value={name}>
<Checkbox checked={selectedStatus.indexOf(name) > -1} />
<ListItemText primary={name} />
</MenuItem>
))}
</Select>
</FormControl>
<span style={{display: "flex", top: -10, right: 50, position: "absolute"}}>
<a href={mailsendingButton(selectedOrganization)} target="_blank" rel="noopener noreferrer" style={{textDecoration: "none"}} disabled={selectedStatus.length !== 0}>
<Button
variant="outlined"
color="primary"
disabled={selectedStatus.length !== 0}
style={{ minWidth: 80, maxWidth: 80, height: "100%", }}
onClick={() => {
console.log("Should send mail to admins of org with context")
handleStatusChange({target: {value: ["contacted"]}})
// open a mailto with subject "hello" and sender "frikky@shuffler.io"
}}
>
Sales mail
</Button>
</a>
<FormControl sx={{ m: 1, width: 300, }} style={{}}>
<InputLabel id="">Status</InputLabel>
<Select
style={{minWidth: 150, maxWidth: 150, }}
labelId="multiselect-status"
id="multiselect-status"
multiple
value={selectedStatus}
onChange={handleStatusChange}
input={<OutlinedInput label="Status" />}
renderValue={(selected) => selected.join(', ')}
MenuProps={MenuProps}
>
{["contacted", "lead", "pov", "demo done", "customer", "student", ].map((name) => (
<MenuItem key={name} value={name}>
<Checkbox checked={selectedStatus.indexOf(name) > -1} />
<ListItemText primary={name} />
</MenuItem>
))}
</Select>
</FormControl>
</span>
: null}
<Tooltip
@@ -2588,10 +2773,6 @@ const Admin = (props) => {
userdata={userdata}
adminTab={adminTab}
globalUrl={globalUrl}
handleGetOrg={handleGetOrg}
selectedOrganization={selectedOrganization}
selectedOrganization={selectedOrganization}
setSelectedOrganization={setSelectedOrganization}
checkLogin={checkLogin}
/>
: adminTab === 3 ?
+8 -7
View File
@@ -11484,7 +11484,7 @@ const AngularWorkflow = (defaultprops) => {
>
<div style={{ flex: "1" }}>
<h3 style={{ marginBottom: "5px" }}>
{selectedTrigger.app_name}: {selectedTrigger.status}
{selectedTrigger.app_name}
</h3>
<a
rel="noopener noreferrer"
@@ -11526,7 +11526,7 @@ const AngularWorkflow = (defaultprops) => {
onChange={selectedTriggerChange}
/>
<div style={{ marginTop: "20px" }}>
{/*<div style={{ marginTop: "20px" }}>
Environment:
<TextField
style={{
@@ -11549,6 +11549,7 @@ const AngularWorkflow = (defaultprops) => {
value={selectedTrigger.environment}
/>
</div>
*/}
<Divider
style={{
marginTop: "20px",
@@ -13697,7 +13698,7 @@ const AngularWorkflow = (defaultprops) => {
>
<h2 style={{ color: "rgba(255,255,255,0.5)" }}>
<DirectionsRunIcon style={{ marginRight: 10 }} />
All Executions
All Workflow Runs
</h2>
</Breadcrumbs>
<Button
@@ -13710,7 +13711,7 @@ const AngularWorkflow = (defaultprops) => {
color="primary"
>
<CachedIcon style={{ marginRight: 10 }} />
Refresh executions
Refresh Runs
</Button>
<Divider
style={{
@@ -13956,7 +13957,7 @@ const AngularWorkflow = (defaultprops) => {
style={{ color: "rgba(255,255,255,0.5)", cursor: "pointer" }}
onClick={() => { }}
>
See other Executions
See more runs
</h2>
</span>
</Breadcrumbs>
@@ -14781,7 +14782,7 @@ const AngularWorkflow = (defaultprops) => {
{curapp === null ? null : (
<img
alt={selectedResult.action.app_name}
src={selectedResult === undefined ? theme.palette.defaultImage : selectedResult.action.app_name === "shuffle-subflow" ? triggers[4].large_image : selectedResult.action.app_name === "User Input" ? triggers[5].large_image : selectedResult.action.large_image !== undefined && selectedResult.action.large_image !== null && selectedResult.action.large_image !== "" ? selectedResult.action.large_image : curapp.large_image}
src={selectedResult === undefined ? theme.palette.defaultImage : selectedResult.action.app_name === "shuffle-subflow" ? triggers[4].large_image : selectedResult.action.app_name === "User Input" ? triggers[5].large_image : selectedResult.action !== undefined && selectedResult.action.large_image !== undefined && selectedResult.action.large_image !== null && selectedResult.action.large_image !== "" ? selectedResult.action.large_image : curapp !== undefined ? curapp.large_image : theme.palette.defaultImage}
style={{
marginRight: 20,
width: imgsize,
@@ -15509,7 +15510,7 @@ const AngularWorkflow = (defaultprops) => {
<div>
<DialogTitle id="draggable-dialog-title" style={{ cursor: "move", }}>
<div style={{ color: "white" }}>
Authentication for {selectedApp.name}
Authentication for {selectedApp.name.replace("_", " ", -1)}
</div>
</DialogTitle>
<DialogContent>
File diff suppressed because one or more lines are too long
+2
View File
@@ -127,6 +127,8 @@ const Search = (props) => {
textColor="secondary"
onChange={setConfig}
aria-label="disabled tabs example"
variant="scrollable"
scrollButtons="auto"
>
<Tab
label=<span>
+1 -1
View File
@@ -334,7 +334,7 @@ const Welcome = (props) => {
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, }}>
<div style={{width: 1000, 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%",}} />
+33 -9
View File
@@ -9,6 +9,7 @@ import { Navigate } from "react-router-dom";
import SecurityFramework from '../components/SecurityFramework.jsx';
import EditWorkflow from "../components/EditWorkflow.jsx"
import { ShepherdTour, ShepherdTourContext } from 'react-shepherd'
import Priority from "../components/Priority.jsx";
import { isMobile } from "react-device-detect"
@@ -524,7 +525,7 @@ export const validateJson = (showResult) => {
};
const Workflows = (props) => {
const { globalUrl, isLoggedIn, isLoaded, userdata } = props;
const { globalUrl, isLoggedIn, isLoaded, userdata, checkLogin } = props;
document.title = "Shuffle - Workflows";
let navigate = useNavigate();
@@ -585,6 +586,7 @@ const Workflows = (props) => {
const [drawerOpen, setDrawerOpen] = React.useState(false)
const [videoViewOpen, setVideoViewOpen] = React.useState(false)
const [gettingStartedItems, setGettingStartedItems] = React.useState([])
const drawerWidth = drawerOpen ? 325 : 0
const sidebarKey = "getting_started_sidebar"
@@ -618,7 +620,6 @@ const Workflows = (props) => {
setDrawerOpen(true)
} else {
if (sidebar === "open") {
console.log("OPEN the thingy!")
setDrawerOpen(true)
} else {
setDrawerOpen(false)
@@ -1126,6 +1127,11 @@ const Workflows = (props) => {
var newcategories = []
for (var key in categorydata) {
var category = categorydata[key]
// Check if category is bool
if (typeof category === "boolean") {
continue
}
category.matches = []
for (var subcategorykey in category.list) {
@@ -1216,8 +1222,8 @@ const Workflows = (props) => {
color: "#ffffff",
width: "100%",
display: "flex",
minWidth: isMobile ? "100%" : drawerWidth > 0 ? 824 : 1024,
maxWidth: isMobile ? "100%" : drawerWidth > 0 ? 824 : 1024,
minWidth: isMobile ? "100%" : 1024,
maxWidth: isMobile ? "100%" : 1024,
margin: drawerWidth === 0 ? "auto" : `auto ${drawerWidth+100} auto auto`,
paddingBottom: 200,
};
@@ -1583,7 +1589,8 @@ const Workflows = (props) => {
const innerColor = "rgba(255,255,255,0.3)";
const setupPaperStyle = {
minHeight: paperAppStyle.minHeight,
width: paperAppStyle.width,
maxWidth: "100%",
minWidth: paperAppStyle.width,
color: innerColor,
padding: paperAppStyle.padding,
borderRadius: paperAppStyle.borderRadius,
@@ -1612,7 +1619,7 @@ const Workflows = (props) => {
}}
>
<Tooltip title={`New Workflow`} placement="bottom">
<span style={{ textAlign: "center", width: 300, margin: "auto" }}>
<span style={{ textAlign: "center", minWidth: 300, margin: "auto" }}>
<AddCircleIcon style={{ height: 65, width: 65 }} />
</span>
</Tooltip>
@@ -3197,7 +3204,7 @@ const Workflows = (props) => {
var workflowDelay = -150
var appDelay = -75
const foundPriority = userdata === undefined || userdata === null ? null : userdata.priorities.find(prio => prio.type === "usecase" && prio.active === true)
return (
<div style={viewStyle}>
<div style={workflowViewStyle}>
@@ -3470,9 +3477,17 @@ const Workflows = (props) => {
</div>
: null}
<div style={{marginTop: 15, }}>
{foundPriority != null && workflows.length < 6 ?
<Priority
globalUrl={globalUrl}
priority={foundPriority}
checkLogin={checkLogin}
/>
: null}
<div style={{marginTop: 15, marginBottom: 50, }}>
{view === "grid" ? (
<Grid container spacing={4} style={paperAppContainer}>
<Grid container spacing={filteredWorkflows.length === 0 ? 12 : filteredWorkflows.length === 1 ? 6 : 4} style={paperAppContainer}>
<Zoom in={true} style={{ transitionDelay: `${workflowDelay}ms` }}>
<NewWorkflowPaper />
</Zoom>
@@ -3507,6 +3522,15 @@ const Workflows = (props) => {
)}
</div>
{foundPriority != null && filteredWorkflows.length > 6 ?
<Priority
style={{marginTop: 15, }}
globalUrl={globalUrl}
priority={foundPriority}
checkLogin={checkLogin}
/>
: null}
<div style={{ marginBottom: 100 }} />
</div>
</div>