Synced 2.0 updates
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
import React, { useEffect, useState } from 'react';
|
import React, { useCallback, useEffect, useState } from 'react';
|
||||||
import { useNavigate } from 'react-router';
|
import { useNavigate } from 'react-router';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@@ -23,14 +23,14 @@ import ForkRightIcon from '@mui/icons-material/ForkRight';
|
|||||||
import OpenInNewIcon from '@mui/icons-material/OpenInNew';
|
import OpenInNewIcon from '@mui/icons-material/OpenInNew';
|
||||||
import LaunchIcon from '@mui/icons-material/Launch';
|
import LaunchIcon from '@mui/icons-material/Launch';
|
||||||
import CheckCircleIcon from '@mui/icons-material/CheckCircle';
|
import CheckCircleIcon from '@mui/icons-material/CheckCircle';
|
||||||
import { CloudDownloadOutlined } from '@mui/icons-material';
|
import { CloudDownloadOutlined, Delete } from '@mui/icons-material';
|
||||||
import { findSpecificApp } from '../components/AppFramework.jsx';
|
import { findSpecificApp } from '../components/AppFramework.jsx';
|
||||||
import theme from "../theme.jsx";
|
import theme from "../theme.jsx";
|
||||||
import YAML from 'yaml';
|
import YAML from 'yaml';
|
||||||
import { toast } from 'react-toastify';
|
import { toast } from 'react-toastify';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
const AppModal = ({ open, onClose, app, globalUrl }) => {
|
const AppModal = ({ open, onClose, app, globalUrl, getApps }) => {
|
||||||
|
|
||||||
const [frameworkData, setFrameworkData] = useState({})
|
const [frameworkData, setFrameworkData] = useState({})
|
||||||
const [userdata, setUserdata] = useState({})
|
const [userdata, setUserdata] = useState({})
|
||||||
@@ -41,6 +41,8 @@ const AppModal = ({ open, onClose, app, globalUrl }) => {
|
|||||||
const [latestUsecase, setLatestUsecase] = useState([])
|
const [latestUsecase, setLatestUsecase] = useState([])
|
||||||
const [foundAppUsecase, setFoundAppUsecase] = useState({})
|
const [foundAppUsecase, setFoundAppUsecase] = useState({})
|
||||||
const [usecaseLoading, setUsecaseLoading] = useState(false)
|
const [usecaseLoading, setUsecaseLoading] = useState(false)
|
||||||
|
const [deleteModalOpen, setDeleteModalOpen] = useState(false)
|
||||||
|
const [sharingConfiguration, setSharingConfiguration] = React.useState("you");
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const parseUsecase = (subcase) => {
|
const parseUsecase = (subcase) => {
|
||||||
const srcdata = findSpecificApp(frameworkData, subcase.type)
|
const srcdata = findSpecificApp(frameworkData, subcase.type)
|
||||||
@@ -294,8 +296,101 @@ const AppModal = ({ open, onClose, app, globalUrl }) => {
|
|||||||
setUsecaseLoading(true)
|
setUsecaseLoading(true)
|
||||||
getAvailableWorkflows()
|
getAvailableWorkflows()
|
||||||
getFramework()
|
getFramework()
|
||||||
|
handleUpdateSharingConfiguration()
|
||||||
}, [app])
|
}, [app])
|
||||||
|
|
||||||
|
const handleUpdateSharingConfiguration = useCallback(() => {
|
||||||
|
if (app?.sharing === true) {
|
||||||
|
setSharingConfiguration("public")
|
||||||
|
}else {
|
||||||
|
setSharingConfiguration("you")
|
||||||
|
}
|
||||||
|
|
||||||
|
}, [app?.id])
|
||||||
|
|
||||||
|
const deleteApp = (appId) => {
|
||||||
|
toast("Attempting to delete app");
|
||||||
|
fetch(globalUrl + "/api/v1/apps/" + appId, {
|
||||||
|
method: "DELETE",
|
||||||
|
headers: {
|
||||||
|
Accept: "application/json",
|
||||||
|
},
|
||||||
|
credentials: "include",
|
||||||
|
})
|
||||||
|
.then((response) => {
|
||||||
|
if (response.status === 200) {
|
||||||
|
toast("Successfully deleted app");
|
||||||
|
setTimeout(() => {
|
||||||
|
//delete apps from local storage
|
||||||
|
localStorage.removeItem("apps");
|
||||||
|
getApps();
|
||||||
|
}, 1000);
|
||||||
|
} else {
|
||||||
|
toast("Failed deleting app. Does it still exist?");
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
toast(error.toString());
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const deleteModal = deleteModalOpen ? (
|
||||||
|
<Dialog
|
||||||
|
open={deleteModalOpen}
|
||||||
|
onClose={() => {
|
||||||
|
setDeleteModalOpen(false);
|
||||||
|
}}
|
||||||
|
PaperProps={{
|
||||||
|
sx: {
|
||||||
|
borderRadius: theme?.palette?.DialogStyle?.borderRadius,
|
||||||
|
border: theme?.palette?.DialogStyle?.border,
|
||||||
|
fontFamily: theme?.typography?.fontFamily,
|
||||||
|
backgroundColor: theme?.palette?.DialogStyle?.backgroundColor,
|
||||||
|
zIndex: 1000,
|
||||||
|
minWidth: "500px",
|
||||||
|
overflow: "hidden",
|
||||||
|
'& .MuiDialogContent-root': {
|
||||||
|
backgroundColor: theme?.palette?.DialogStyle?.backgroundColor,
|
||||||
|
},
|
||||||
|
'& .MuiDialogTitle-root': {
|
||||||
|
backgroundColor: theme?.palette?.DialogStyle?.backgroundColor,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<DialogTitle>
|
||||||
|
<div style={{ textAlign: "center", color: "rgba(255,255,255,0.9)" }}>
|
||||||
|
Are you sure? <div />
|
||||||
|
Some workflows may stop working.
|
||||||
|
</div>
|
||||||
|
</DialogTitle>
|
||||||
|
<DialogContent
|
||||||
|
style={{ color: "rgba(255,255,255,0.65)", textAlign: "center" }}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
style={{}}
|
||||||
|
onClick={() => {
|
||||||
|
deleteApp(app.id);
|
||||||
|
setDeleteModalOpen(false);
|
||||||
|
}}
|
||||||
|
color="primary"
|
||||||
|
>
|
||||||
|
Yes
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
variant="outlined"
|
||||||
|
style={{marginLeft: 5}}
|
||||||
|
onClick={() => {
|
||||||
|
setDeleteModalOpen(false);
|
||||||
|
}}
|
||||||
|
color="primary"
|
||||||
|
>
|
||||||
|
No
|
||||||
|
</Button>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
) : null;
|
||||||
|
|
||||||
|
|
||||||
const downloadApp = (inputdata) => {
|
const downloadApp = (inputdata) => {
|
||||||
const id = inputdata.id;
|
const id = inputdata.id;
|
||||||
@@ -425,6 +520,7 @@ const AppModal = ({ open, onClose, app, globalUrl }) => {
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
{deleteModal}
|
||||||
<DialogTitle
|
<DialogTitle
|
||||||
sx={{
|
sx={{
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
@@ -457,7 +553,7 @@ const AppModal = ({ open, onClose, app, globalUrl }) => {
|
|||||||
<div style={{ display: "flex", flexDirection: "row", gap: 10, fontFamily: theme?.typography?.fontFamily }}>
|
<div style={{ display: "flex", flexDirection: "row", gap: 10, fontFamily: theme?.typography?.fontFamily }}>
|
||||||
<img
|
<img
|
||||||
alt={app?.name}
|
alt={app?.name}
|
||||||
src={app?.large_image || app?.image_url}
|
src={app?.large_image || app?.image_url || "/images/no_image.png"}
|
||||||
style={{
|
style={{
|
||||||
borderRadius: 4,
|
borderRadius: 4,
|
||||||
maxWidth: 100,
|
maxWidth: 100,
|
||||||
@@ -536,6 +632,35 @@ const AppModal = ({ open, onClose, app, globalUrl }) => {
|
|||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
) : null}
|
) : null}
|
||||||
|
{(userdata?.id === app?.owner)? (
|
||||||
|
<Tooltip title={"Delete app (confirm box will show)"}>
|
||||||
|
<Button
|
||||||
|
variant="outlined"
|
||||||
|
component="label"
|
||||||
|
color="primary"
|
||||||
|
sx={{
|
||||||
|
bgcolor: '#494949',
|
||||||
|
'&:hover': { bgcolor: '#494949', border: 'none' },
|
||||||
|
textTransform: 'none',
|
||||||
|
borderRadius: 1,
|
||||||
|
minWidth: '45px',
|
||||||
|
width: '45px',
|
||||||
|
height: '40px',
|
||||||
|
padding: 2,
|
||||||
|
color: "#fff",
|
||||||
|
fontFamily: theme?.typography?.fontFamily,
|
||||||
|
border: 'none'
|
||||||
|
}}
|
||||||
|
onClick={() => {
|
||||||
|
setDeleteModalOpen(true);
|
||||||
|
}}
|
||||||
|
disabled={(sharingConfiguration === undefined || sharingConfiguration === null || sharingConfiguration === "public") }
|
||||||
|
>
|
||||||
|
<Delete />
|
||||||
|
</Button>
|
||||||
|
</Tooltip>
|
||||||
|
): null}
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
variant="contained"
|
variant="contained"
|
||||||
sx={{
|
sx={{
|
||||||
|
|||||||
@@ -50,6 +50,9 @@ const Appsearch = props => {
|
|||||||
return (
|
return (
|
||||||
<form noValidate action="" role="search">
|
<form noValidate action="" role="search">
|
||||||
<TextField
|
<TextField
|
||||||
|
autoFocus
|
||||||
|
autoComplete="off"
|
||||||
|
autocomplete="off"
|
||||||
fullWidth
|
fullWidth
|
||||||
style={{backgroundColor: "#2F2F2F", borderRadius: borderRadius, width: "100%",}}
|
style={{backgroundColor: "#2F2F2F", borderRadius: borderRadius, width: "100%",}}
|
||||||
InputProps={{
|
InputProps={{
|
||||||
|
|||||||
@@ -390,6 +390,10 @@ const CacheView = memo((props) => {
|
|||||||
variant="contained"
|
variant="contained"
|
||||||
style={{ borderRadius: "2px", backgroundColor: "#ff8544",color: "#1a1a1a", textTransform:"none" }}
|
style={{ borderRadius: "2px", backgroundColor: "#ff8544",color: "#1a1a1a", textTransform:"none" }}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
if (value === "") {
|
||||||
|
toast("Key or Value can not be empty");
|
||||||
|
return;
|
||||||
|
}
|
||||||
{editCache ? editOrgCache(orgId) : addOrgCache(orgId)}
|
{editCache ? editOrgCache(orgId) : addOrgCache(orgId)}
|
||||||
setKey("")
|
setKey("")
|
||||||
setValue("")
|
setValue("")
|
||||||
@@ -503,7 +507,7 @@ const CacheView = memo((props) => {
|
|||||||
>
|
>
|
||||||
<DialogTitle>
|
<DialogTitle>
|
||||||
<div style={{ color: "rgba(255,255,255,0.9)" }}>
|
<div style={{ color: "rgba(255,255,255,0.9)" }}>
|
||||||
Select sub-org to distribute files
|
Select sub-org to distribute Datastore key
|
||||||
</div>
|
</div>
|
||||||
</DialogTitle>
|
</DialogTitle>
|
||||||
<DialogContent style={{ color: "rgba(255,255,255,0.65)" }}>
|
<DialogContent style={{ color: "rgba(255,255,255,0.65)" }}>
|
||||||
@@ -714,7 +718,9 @@ const CacheView = memo((props) => {
|
|||||||
display: "table-cell",
|
display: "table-cell",
|
||||||
overflow: "hidden",
|
overflow: "hidden",
|
||||||
verticalAlign: "middle",
|
verticalAlign: "middle",
|
||||||
padding: "8px 8px 8px 15px"
|
padding: "8px 8px 8px 15px",
|
||||||
|
maxWidth: 200,
|
||||||
|
overflowX: "auto",
|
||||||
}}
|
}}
|
||||||
primary={data.key}
|
primary={data.key}
|
||||||
/>
|
/>
|
||||||
@@ -872,6 +878,8 @@ const CacheView = memo((props) => {
|
|||||||
style={{display: "table-cell", textAlign: 'center', verticalAlign: 'middle', }}
|
style={{display: "table-cell", textAlign: 'center', verticalAlign: 'middle', }}
|
||||||
/>
|
/>
|
||||||
:
|
:
|
||||||
|
<ListItemText
|
||||||
|
primary={
|
||||||
<Tooltip
|
<Tooltip
|
||||||
title="Distributed to sub-organizations. This means the sub organizations can use this datastore key, but can not modify it."
|
title="Distributed to sub-organizations. This means the sub organizations can use this datastore key, but can not modify it."
|
||||||
placement="top"
|
placement="top"
|
||||||
@@ -879,7 +887,7 @@ const CacheView = memo((props) => {
|
|||||||
<Checkbox
|
<Checkbox
|
||||||
disabled={ userdata?.active_org?.role !== "admin" || (selectedOrganization.creator_org !== undefined && selectedOrganization.creator_org !== null && selectedOrganization.creator_org !== "" )? true : false}
|
disabled={ userdata?.active_org?.role !== "admin" || (selectedOrganization.creator_org !== undefined && selectedOrganization.creator_org !== null && selectedOrganization.creator_org !== "" )? true : false}
|
||||||
checked={isDistributed}
|
checked={isDistributed}
|
||||||
style={{ }}
|
style={{ margin: "auto" }}
|
||||||
color="secondary"
|
color="secondary"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setShowDistributionPopup(true)
|
setShowDistributionPopup(true)
|
||||||
@@ -893,6 +901,9 @@ const CacheView = memo((props) => {
|
|||||||
/>
|
/>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
}
|
}
|
||||||
|
style={{display: "table-cell", textAlign: 'center', verticalAlign: 'middle', }}
|
||||||
|
/>
|
||||||
|
}
|
||||||
</ListItem>
|
</ListItem>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
|||||||
@@ -799,12 +799,16 @@ const ConfigureWorkflow = (props) => {
|
|||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
border: filled ? `1px solid ${theme.palette.green}` : "1px solid rgba(255,255,255,0.3)", borderRadius: theme.palette?.borderRadius, width: "100%", padding: 12, cursor: "pointer",
|
border: filled ? `1px solid ${theme.palette.green}` : "1px solid rgba(255,255,255,0.3)", borderRadius: theme.palette?.borderRadius, width: "100%", padding: 12, cursor: filled ? "default" : "pointer",
|
||||||
}}
|
}}
|
||||||
id="app-config"
|
id="app-config"
|
||||||
>
|
>
|
||||||
<div style={{display: "flex", }}
|
<div style={{display: "flex", }}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
if (filled) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
setOpened(!opened);
|
setOpened(!opened);
|
||||||
|
|
||||||
// Scroll to it
|
// Scroll to it
|
||||||
@@ -865,6 +869,7 @@ const ConfigureWorkflow = (props) => {
|
|||||||
isLoggedIn={true}
|
isLoggedIn={true}
|
||||||
getAppAuthentication={undefined}
|
getAppAuthentication={undefined}
|
||||||
|
|
||||||
|
workflow={workflow}
|
||||||
setFinalized={setFinalized}
|
setFinalized={setFinalized}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -1377,7 +1382,7 @@ const ConfigureWorkflow = (props) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div style={{margin: setConfigureWorkflowModalOpen !== undefined ? "0px 50px 0px 50px" : "35px 0px 0px 0px", maxHeight: 475, }}>
|
<div style={{margin: setConfigureWorkflowModalOpen !== undefined ? "0px 50px 0px 50px" : "25px 0px 0px 0px", maxHeight: 475, }}>
|
||||||
|
|
||||||
|
|
||||||
{setConfigureWorkflowModalOpen !== undefined ?
|
{setConfigureWorkflowModalOpen !== undefined ?
|
||||||
@@ -1387,7 +1392,7 @@ const ConfigureWorkflow = (props) => {
|
|||||||
: null
|
: null
|
||||||
}
|
}
|
||||||
|
|
||||||
<div style={{marginTop: 10, }} />
|
<div style={{marginTop: setConfigureWorkflowModalOpen !== undefined ? 10 : 0, }} />
|
||||||
|
|
||||||
{/*
|
{/*
|
||||||
<WorkflowValidationTimeline
|
<WorkflowValidationTimeline
|
||||||
@@ -1404,7 +1409,7 @@ const ConfigureWorkflow = (props) => {
|
|||||||
{requiredActions.length > 0 ? (
|
{requiredActions.length > 0 ? (
|
||||||
<span>
|
<span>
|
||||||
<Typography variant="body2" color="textSecondary">
|
<Typography variant="body2" color="textSecondary">
|
||||||
Please configure the following steps to help us complete your workflow. This can also be done later.
|
To complete the workflow setup, please configure the following steps.
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|
||||||
{setConfigureWorkflowModalOpen !== undefined ?
|
{setConfigureWorkflowModalOpen !== undefined ?
|
||||||
@@ -1434,6 +1439,13 @@ const ConfigureWorkflow = (props) => {
|
|||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
</List>
|
</List>
|
||||||
|
|
||||||
|
{/*
|
||||||
|
<Typography variant="body2" color="textSecondary">
|
||||||
|
Once done, you may continue to the workflow.
|
||||||
|
</Typography>
|
||||||
|
*/}
|
||||||
|
|
||||||
</span>
|
</span>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
|
|||||||
@@ -71,7 +71,8 @@ const EditWorkflow = (props) => {
|
|||||||
const [_, setUpdate] = React.useState(""); // Used for rendering, don't remove
|
const [_, setUpdate] = React.useState(""); // Used for rendering, don't remove
|
||||||
|
|
||||||
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 [showMoreClicked, setShowMoreClicked] = React.useState(true);
|
||||||
|
|
||||||
const [innerWorkflow, setInnerWorkflow] = React.useState(workflow)
|
const [innerWorkflow, setInnerWorkflow] = React.useState(workflow)
|
||||||
|
|
||||||
@@ -244,7 +245,6 @@ const EditWorkflow = (props) => {
|
|||||||
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>
|
||||||
|
|
||||||
{/*
|
|
||||||
<div style={{marginTop: 10, marginBottom: 10, marginRight: 50, }}>
|
<div style={{marginTop: 10, marginBottom: 10, marginRight: 50, }}>
|
||||||
<WorkflowValidationTimeline
|
<WorkflowValidationTimeline
|
||||||
|
|
||||||
@@ -252,7 +252,6 @@ const EditWorkflow = (props) => {
|
|||||||
workflow={workflow}
|
workflow={workflow}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
*/}
|
|
||||||
|
|
||||||
{showUpload === true ?
|
{showUpload === true ?
|
||||||
<div style={{ float: "right" }}>
|
<div style={{ float: "right" }}>
|
||||||
@@ -290,7 +289,7 @@ const EditWorkflow = (props) => {
|
|||||||
bottom: 0,
|
bottom: 0,
|
||||||
zIndex: 1002,
|
zIndex: 1002,
|
||||||
backgroundColor: theme.palette.backgroundColor,
|
backgroundColor: theme.palette.backgroundColor,
|
||||||
height: 50,
|
height: 75,
|
||||||
paddingTop: 20,
|
paddingTop: 20,
|
||||||
paddingLeft: 75,
|
paddingLeft: 75,
|
||||||
}}>
|
}}>
|
||||||
@@ -327,12 +326,17 @@ const EditWorkflow = (props) => {
|
|||||||
|
|
||||||
innerWorkflow.name = name
|
innerWorkflow.name = name
|
||||||
innerWorkflow.description = description
|
innerWorkflow.description = description
|
||||||
|
|
||||||
if (newWorkflowTags.length > 0) {
|
if (newWorkflowTags.length > 0) {
|
||||||
innerWorkflow.tags = newWorkflowTags
|
innerWorkflow.tags = newWorkflowTags
|
||||||
|
} else {
|
||||||
|
innerWorkflow.tags = []
|
||||||
}
|
}
|
||||||
|
|
||||||
if (selectedUsecases.length > 0) {
|
if (selectedUsecases.length > 0) {
|
||||||
innerWorkflow.usecase_ids = selectedUsecases
|
innerWorkflow.usecase_ids = selectedUsecases
|
||||||
|
} else {
|
||||||
|
innerWorkflow.usecase_ids = []
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dueDate > 0) {
|
if (dueDate > 0) {
|
||||||
@@ -361,7 +365,6 @@ const EditWorkflow = (props) => {
|
|||||||
setWorkflow({})
|
setWorkflow({})
|
||||||
} else {
|
} else {
|
||||||
setWorkflow(innerWorkflow)
|
setWorkflow(innerWorkflow)
|
||||||
console.log("editing workflow: ", innerWorkflow)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setSubmitLoading(true)
|
setSubmitLoading(true)
|
||||||
@@ -505,7 +508,7 @@ const EditWorkflow = (props) => {
|
|||||||
color: "white",
|
color: "white",
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
multiLine
|
multiline
|
||||||
rows={3}
|
rows={3}
|
||||||
color="primary"
|
color="primary"
|
||||||
defaultValue={innerWorkflow.description}
|
defaultValue={innerWorkflow.description}
|
||||||
@@ -537,81 +540,10 @@ const EditWorkflow = (props) => {
|
|||||||
|
|
||||||
</RadioGroup>
|
</RadioGroup>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<LocalizationProvider dateAdapter={AdapterDayjs}>
|
|
||||||
<DatePicker
|
|
||||||
sx={{
|
|
||||||
marginTop: 3,
|
|
||||||
marginLeft: 3,
|
|
||||||
}}
|
|
||||||
value={dueDate}
|
|
||||||
label="Due Date"
|
|
||||||
format="YYYY-MM-DD"
|
|
||||||
onChange={(newValue) => {
|
|
||||||
setDueDate(newValue)
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</LocalizationProvider>
|
|
||||||
</div>
|
</div>
|
||||||
<div />
|
<div />
|
||||||
|
|
||||||
<FormControl style={{ marginTop: 15, }}>
|
|
||||||
<FormLabel id="demo-row-radio-buttons-group-label">Type</FormLabel>
|
|
||||||
<RadioGroup
|
|
||||||
row
|
|
||||||
aria-labelledby="demo-row-radio-buttons-group-label"
|
|
||||||
name="row-radio-buttons-group"
|
|
||||||
defaultValue={innerWorkflow.workflow_type}
|
|
||||||
onChange={(e) => {
|
|
||||||
console.log("Data: ", e.target.value)
|
|
||||||
|
|
||||||
innerWorkflow.workflow_type = e.target.value
|
|
||||||
setInnerWorkflow(innerWorkflow)
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<FormControlLabel value="trigger" control={<Radio />} label="Trigger" />
|
|
||||||
<FormControlLabel value="subflow" control={<Radio />} label="Subflow" />
|
|
||||||
<FormControlLabel value="standalone" control={<Radio />} label="Standalone" />
|
|
||||||
|
|
||||||
</RadioGroup>
|
|
||||||
</FormControl>
|
|
||||||
|
|
||||||
|
|
||||||
<TextField
|
|
||||||
onBlur={(event) => {
|
|
||||||
innerWorkflow.blogpost = event.target.value
|
|
||||||
setInnerWorkflow(innerWorkflow)
|
|
||||||
}}
|
|
||||||
InputProps={{
|
|
||||||
style: {
|
|
||||||
color: "white",
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
color="primary"
|
|
||||||
defaultValue={innerWorkflow.blogpost}
|
|
||||||
placeholder="A blogpost or other reference for how this work workflow was built, and what it's for."
|
|
||||||
rows="1"
|
|
||||||
label="blogpost"
|
|
||||||
margin="dense"
|
|
||||||
fullWidth
|
|
||||||
/>
|
|
||||||
<TextField
|
|
||||||
onBlur={(event) => {
|
|
||||||
innerWorkflow.video = event.target.value
|
|
||||||
setInnerWorkflow(innerWorkflow)
|
|
||||||
}}
|
|
||||||
InputProps={{
|
|
||||||
style: {
|
|
||||||
color: "white",
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
color="primary"
|
|
||||||
defaultValue={innerWorkflow.video}
|
|
||||||
placeholder="A youtube or loom link to the video"
|
|
||||||
rows="1"
|
|
||||||
label="Video"
|
|
||||||
margin="dense"
|
|
||||||
fullWidth
|
|
||||||
/>
|
|
||||||
|
|
||||||
<TextField
|
<TextField
|
||||||
onBlur={(event) => {
|
onBlur={(event) => {
|
||||||
@@ -1166,6 +1098,87 @@ const EditWorkflow = (props) => {
|
|||||||
</div>
|
</div>
|
||||||
</> : null*/}
|
</> : null*/}
|
||||||
|
|
||||||
|
<Typography variant="h4" style={{ marginTop: 100, }}>
|
||||||
|
Publishing
|
||||||
|
</Typography>
|
||||||
|
<Typography variant="body1" color="textSecondary" style={{ marginTop: 10, }}>
|
||||||
|
Publishing is related to making the workflow itself public. When publishing a workflow, all the details (except sensitive info) become available to everyone. The details below will help a user understand this better. When a workflow is published, you keep the original, and a copy enters the workflow search, and is associated with your <a href="/creators" style={{ textDecoration: "none", color: "#f86a3e" }} target="_blank">creator account</a>, if you have one. You can always unpublish the workflow after. To publish it, click the three dots next to the workflow.
|
||||||
|
</Typography>
|
||||||
|
|
||||||
|
<LocalizationProvider style={{marginLeft: 0, }} dateAdapter={AdapterDayjs}>
|
||||||
|
<DatePicker
|
||||||
|
sx={{
|
||||||
|
marginTop: 3,
|
||||||
|
marginLeft: 3,
|
||||||
|
}}
|
||||||
|
value={dueDate}
|
||||||
|
label="Due Date"
|
||||||
|
format="YYYY-MM-DD"
|
||||||
|
onChange={(newValue) => {
|
||||||
|
setDueDate(newValue)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</LocalizationProvider>
|
||||||
|
|
||||||
|
<FormControl style={{ marginTop: 15, }}>
|
||||||
|
<FormLabel id="demo-row-radio-buttons-group-label">Type</FormLabel>
|
||||||
|
<RadioGroup
|
||||||
|
row
|
||||||
|
aria-labelledby="demo-row-radio-buttons-group-label"
|
||||||
|
name="row-radio-buttons-group"
|
||||||
|
defaultValue={innerWorkflow.workflow_type}
|
||||||
|
onChange={(e) => {
|
||||||
|
console.log("Data: ", e.target.value)
|
||||||
|
|
||||||
|
innerWorkflow.workflow_type = e.target.value
|
||||||
|
setInnerWorkflow(innerWorkflow)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<FormControlLabel value="trigger" control={<Radio />} label="Trigger" />
|
||||||
|
<FormControlLabel value="subflow" control={<Radio />} label="Subflow" />
|
||||||
|
<FormControlLabel value="standalone" control={<Radio />} label="Standalone" />
|
||||||
|
|
||||||
|
</RadioGroup>
|
||||||
|
</FormControl>
|
||||||
|
|
||||||
|
|
||||||
|
<TextField
|
||||||
|
onBlur={(event) => {
|
||||||
|
innerWorkflow.blogpost = event.target.value
|
||||||
|
setInnerWorkflow(innerWorkflow)
|
||||||
|
}}
|
||||||
|
InputProps={{
|
||||||
|
style: {
|
||||||
|
color: "white",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
color="primary"
|
||||||
|
defaultValue={innerWorkflow.blogpost}
|
||||||
|
placeholder="A blogpost or other reference for how this work workflow was built, and what it's for."
|
||||||
|
rows="1"
|
||||||
|
label="blogpost"
|
||||||
|
margin="dense"
|
||||||
|
fullWidth
|
||||||
|
/>
|
||||||
|
<TextField
|
||||||
|
onBlur={(event) => {
|
||||||
|
innerWorkflow.video = event.target.value
|
||||||
|
setInnerWorkflow(innerWorkflow)
|
||||||
|
}}
|
||||||
|
InputProps={{
|
||||||
|
style: {
|
||||||
|
color: "white",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
color="primary"
|
||||||
|
defaultValue={innerWorkflow.video}
|
||||||
|
placeholder="A youtube or loom link to the video"
|
||||||
|
rows="1"
|
||||||
|
label="Video"
|
||||||
|
margin="dense"
|
||||||
|
fullWidth
|
||||||
|
/>
|
||||||
|
|
||||||
<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: 10, textAlign: "center", textTransform: "none", }}
|
style={{ margin: "auto", marginTop: 50, marginBottom: 10, textAlign: "center", textTransform: "none", }}
|
||||||
|
|||||||
@@ -644,6 +644,7 @@ const FixWorkflowValidationErrors = (props) => {
|
|||||||
console.log("Workflow validation: ", workflow.validation)
|
console.log("Workflow validation: ", workflow.validation)
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
|
{/*
|
||||||
{workflow.errors !== undefined && workflow.errors !== null ?
|
{workflow.errors !== undefined && workflow.errors !== null ?
|
||||||
<div>
|
<div>
|
||||||
General errors: {workflow.errors.length}
|
General errors: {workflow.errors.length}
|
||||||
@@ -656,11 +657,8 @@ const FixWorkflowValidationErrors = (props) => {
|
|||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
: null}
|
: null}
|
||||||
|
|
||||||
<Divider style={{marginTop: 15, marginBottom: 15, }}/>
|
<Divider style={{marginTop: 15, marginBottom: 15, }}/>
|
||||||
|
workflow.validation.errors !== undefined && workflow.validation.errors !== null ?
|
||||||
|
|
||||||
{workflow.validation.errors !== undefined && workflow.validation.errors !== null ?
|
|
||||||
<div>
|
<div>
|
||||||
Validation errors: {workflow.validation.errors.length}
|
Validation errors: {workflow.validation.errors.length}
|
||||||
{workflow.validation.errors.map((error, index) => {
|
{workflow.validation.errors.map((error, index) => {
|
||||||
@@ -675,10 +673,12 @@ const FixWorkflowValidationErrors = (props) => {
|
|||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
: null}
|
: null*/}
|
||||||
|
|
||||||
|
{/*
|
||||||
<Divider style={{marginTop: 15, marginBottom: 15, }} />
|
<Divider style={{marginTop: 15, marginBottom: 15, }} />
|
||||||
Apps loaded: {apps.length}
|
Apps loaded: {apps.length}
|
||||||
|
*/}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -7,7 +7,9 @@ import {
|
|||||||
Add as AddIcon,
|
Add as AddIcon,
|
||||||
BorderColor,
|
BorderColor,
|
||||||
Close as CloseIcon,
|
Close as CloseIcon,
|
||||||
ConstructionOutlined,
|
ConstructionOutlined as ConstructionOutlinedIcon,
|
||||||
|
Toc as TocIcon,
|
||||||
|
Settings as SettingsIcon
|
||||||
} from "@mui/icons-material";
|
} from "@mui/icons-material";
|
||||||
import SearchBox from "./SearchData.jsx";
|
import SearchBox from "./SearchData.jsx";
|
||||||
import {
|
import {
|
||||||
@@ -29,9 +31,6 @@ import {
|
|||||||
Collapse,
|
Collapse,
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
import theme from "../theme.jsx";
|
import theme from "../theme.jsx";
|
||||||
import {
|
|
||||||
Settings as SettingsIcon
|
|
||||||
} from "@mui/icons-material";
|
|
||||||
import RecentWorkflow from "../components/RecentWorkflow.jsx";
|
import RecentWorkflow from "../components/RecentWorkflow.jsx";
|
||||||
|
|
||||||
import { useNavigate } from "react-router";
|
import { useNavigate } from "react-router";
|
||||||
@@ -143,8 +142,6 @@ useEffect(() => {
|
|||||||
>
|
>
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
maxHeight: 250,
|
|
||||||
overflowY: "auto",
|
|
||||||
scrollbarWidth: "thin",
|
scrollbarWidth: "thin",
|
||||||
scrollbarColor: "#494949 transparent",
|
scrollbarColor: "#494949 transparent",
|
||||||
"& .MuiAutocomplete-listbox": {
|
"& .MuiAutocomplete-listbox": {
|
||||||
@@ -238,7 +235,7 @@ useEffect(() => {
|
|||||||
setOpenautomateTab(true);
|
setOpenautomateTab(true);
|
||||||
setOpenSecurityTab(false);
|
setOpenSecurityTab(false);
|
||||||
setCurrentOpenTab("workflows");
|
setCurrentOpenTab("workflows");
|
||||||
} else if ((lastTabOpenByUser === "apps" && currentPath.includes("/search")) || currentPath.includes("/search")) {
|
} else if ((lastTabOpenByUser === "apps" && currentPath.includes("/apps")) || currentPath.includes("/apps")) {
|
||||||
setOpenautomateTab(true);
|
setOpenautomateTab(true);
|
||||||
setOpenSecurityTab(false);
|
setOpenSecurityTab(false);
|
||||||
setCurrentOpenTab("apps");
|
setCurrentOpenTab("apps");
|
||||||
@@ -500,16 +497,6 @@ useEffect(() => {
|
|||||||
})
|
})
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
</Link>
|
</Link>
|
||||||
<Link to="/workflows" style={hrefStyle}>
|
|
||||||
<MenuItem
|
|
||||||
onClick={(event) => {
|
|
||||||
handleClose();
|
|
||||||
}}
|
|
||||||
style={{fontSize: 18}}
|
|
||||||
>
|
|
||||||
<LightbulbIcon style={{ marginRight: 5 }} /> Use Cases
|
|
||||||
</MenuItem>
|
|
||||||
</Link>
|
|
||||||
|
|
||||||
<Divider style={{ marginTop: 10, marginBottom: 10, }} />
|
<Divider style={{ marginTop: 10, marginBottom: 10, }} />
|
||||||
|
|
||||||
@@ -537,7 +524,7 @@ useEffect(() => {
|
|||||||
<Divider style={{ marginBottom: 10, }} />
|
<Divider style={{ marginBottom: 10, }} />
|
||||||
|
|
||||||
<Typography color="textSecondary" align="center" style={{ marginTop: 5, marginBottom: 5, fontSize: 18 }}>
|
<Typography color="textSecondary" align="center" style={{ marginTop: 5, marginBottom: 5, fontSize: 18 }}>
|
||||||
Version: 2.0.0-rc3
|
Version: 2.0.0-rc4
|
||||||
</Typography>
|
</Typography>
|
||||||
</Menu>
|
</Menu>
|
||||||
</span>
|
</span>
|
||||||
@@ -704,16 +691,48 @@ useEffect(() => {
|
|||||||
|
|
||||||
const CheckOrgStates = useCallback(() => {
|
const CheckOrgStates = useCallback(() => {
|
||||||
setOrgOptions(
|
setOrgOptions(
|
||||||
userdata?.orgs?.map((org) => ({
|
userdata?.orgs?.map((org) => {
|
||||||
|
let skipOrg = false;
|
||||||
|
|
||||||
|
if (
|
||||||
|
org.creator_org !== undefined &&
|
||||||
|
org.creator_org !== null &&
|
||||||
|
org.creator_org.length > 0
|
||||||
|
) {
|
||||||
|
// Finds the parent org
|
||||||
|
for (let key in userdata.child_orgs) {
|
||||||
|
if (userdata.child_orgs[key].id === org.creator_org) {
|
||||||
|
skipOrg = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (skipOrg) {
|
||||||
|
return null; // Skip this org
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
id: org.id,
|
id: org.id,
|
||||||
name: org.name,
|
name: org.name,
|
||||||
image: org.image,
|
image: org.image,
|
||||||
region_url: getRegionTag(org.region_url),
|
region_url: getRegionTag(org.region_url),
|
||||||
})) || []
|
margin_left:
|
||||||
|
org.creator_org !== undefined &&
|
||||||
|
org.creator_org !== null &&
|
||||||
|
org.creator_org.length > 0
|
||||||
|
? org.id === userdata.active_org.id
|
||||||
|
? 0
|
||||||
|
: 20
|
||||||
|
: 0,
|
||||||
|
};
|
||||||
|
}) || []
|
||||||
);
|
);
|
||||||
|
|
||||||
setActiveOrgName(userdata?.active_org?.name || "Select Organization");
|
setActiveOrgName(userdata?.active_org?.name || "Select Organization");
|
||||||
setSelectedOrg(userdata?.active_org?.name || "Select Organization");
|
setSelectedOrg(userdata?.active_org?.name || "Select Organization");
|
||||||
},[orgOptions, activeOrgName, selectedOrg]);
|
}, [userdata]);
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (typeof userdata?.id === "string" && userdata?.id?.length > 0) {
|
if (typeof userdata?.id === "string" && userdata?.id?.length > 0) {
|
||||||
@@ -870,7 +889,7 @@ useEffect(() => {
|
|||||||
</Button>
|
</Button>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
<Box sx={{ display: "flex", flexDirection: "column", width:"100%", height: "100%", overflowY: "auto", overflowX: "hidden",transition: 'display 0.3s ease',paddingTop: 0.5 }} onMouseOver={()=>{!leftSideBarOpenByClick && setExpandLeftNav(true);}} onMouseLeave={()=>{!leftSideBarOpenByClick && setExpandLeftNav(false);setOpenAutocomplete(false);}}>
|
<Box sx={{ display: "flex", flexDirection: "column", width:"100%", height: "100%", overflowY: "auto", overflowX: "hidden",transition: 'display 0.3s ease',paddingTop: 0.5 }} onMouseOver={()=>{!leftSideBarOpenByClick && setExpandLeftNav(true)}} onMouseLeave={()=>{!leftSideBarOpenByClick && setExpandLeftNav(false);setOpenAutocomplete(false)}}>
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
@@ -1144,7 +1163,7 @@ useEffect(() => {
|
|||||||
color: currentOpenTab === "apps" && currentPath.includes("/apps") ? "#FFFFFF" : "#C8C8C8",
|
color: currentOpenTab === "apps" && currentPath.includes("/apps") ? "#FFFFFF" : "#C8C8C8",
|
||||||
justifyContent: "flex-start",
|
justifyContent: "flex-start",
|
||||||
textTransform: "none",
|
textTransform: "none",
|
||||||
backgroundColor: currentOpenTab === "apps" && expandLeftNav && currentPath.includes("/apps2") ? "#2f2f2f": "transparent",
|
backgroundColor: currentOpenTab === "apps" && expandLeftNav && currentPath.includes("/apps") ? "#2f2f2f": "transparent",
|
||||||
marginLeft: 16,
|
marginLeft: 16,
|
||||||
fontSize: 18
|
fontSize: 18
|
||||||
}}
|
}}
|
||||||
@@ -1152,7 +1171,7 @@ useEffect(() => {
|
|||||||
event.currentTarget.style.backgroundColor = "#2f2f2f";
|
event.currentTarget.style.backgroundColor = "#2f2f2f";
|
||||||
}}
|
}}
|
||||||
onMouseOut={(event)=>{
|
onMouseOut={(event)=>{
|
||||||
event.currentTarget.style.backgroundColor = currentOpenTab === "apps" && expandLeftNav && currentPath.includes("/search") ? "#2f2f2f": "transparent";
|
event.currentTarget.style.backgroundColor = currentOpenTab === "apps" && expandLeftNav && currentPath.includes("/apps") ? "#2f2f2f": "transparent";
|
||||||
}}
|
}}
|
||||||
disableRipple={expandLeftNav ? false : true}
|
disableRipple={expandLeftNav ? false : true}
|
||||||
>
|
>
|
||||||
@@ -1205,7 +1224,7 @@ useEffect(() => {
|
|||||||
: "transparent";
|
: "transparent";
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<ShieldOutlinedIcon
|
<TocIcon
|
||||||
style={{
|
style={{
|
||||||
width: 18,
|
width: 18,
|
||||||
height: 18,
|
height: 18,
|
||||||
@@ -1223,7 +1242,7 @@ useEffect(() => {
|
|||||||
: "#C8C8C8"
|
: "#C8C8C8"
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Discover
|
Content
|
||||||
</span>
|
</span>
|
||||||
</Button>
|
</Button>
|
||||||
</Link>
|
</Link>
|
||||||
@@ -1262,7 +1281,7 @@ useEffect(() => {
|
|||||||
<Collapse in={openSecurityTab} timeout="auto" unmountOnExit>
|
<Collapse in={openSecurityTab} timeout="auto" unmountOnExit>
|
||||||
<Box
|
<Box
|
||||||
style={{
|
style={{
|
||||||
maxHeight: openSecurityTab && expandLeftNav ? 100 : 0,
|
maxHeight: openSecurityTab && expandLeftNav ? 135 : 0,
|
||||||
overflow: "hidden",
|
overflow: "hidden",
|
||||||
transition: "max-height 0.3s ease, opacity 0.3s ease",
|
transition: "max-height 0.3s ease, opacity 0.3s ease",
|
||||||
display: "flex",
|
display: "flex",
|
||||||
@@ -1276,19 +1295,18 @@ useEffect(() => {
|
|||||||
to={"/forms"}
|
to={"/forms"}
|
||||||
style={{
|
style={{
|
||||||
...hrefStyle,
|
...hrefStyle,
|
||||||
pointerEvents: userdata?.support ? "auto" : "none",
|
pointerEvents: "auto",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Button
|
<Button
|
||||||
onClick={(event) => {
|
onClick={(event) => {
|
||||||
if (!userdata?.support) return;
|
|
||||||
setCurrentOpenTab("detection");
|
setCurrentOpenTab("detection");
|
||||||
localStorage.setItem("lastTabOpenByUser", "detection");
|
localStorage.setItem("lastTabOpenByUser", "detection");
|
||||||
}}
|
}}
|
||||||
sx={{
|
sx={{
|
||||||
width: "100%",
|
width: "100%",
|
||||||
height: 35,
|
height: 35,
|
||||||
color: userdata?.support ? "#C8C8C8" : "#6F6F6F",
|
color: "#C8C8C8",
|
||||||
justifyContent: "flex-start",
|
justifyContent: "flex-start",
|
||||||
textTransform: "none",
|
textTransform: "none",
|
||||||
backgroundColor:
|
backgroundColor:
|
||||||
@@ -1296,11 +1314,10 @@ useEffect(() => {
|
|||||||
? "#2f2f2f"
|
? "#2f2f2f"
|
||||||
: "transparent",
|
: "transparent",
|
||||||
"&:hover": {
|
"&:hover": {
|
||||||
backgroundColor: userdata?.support ? "#2f2f2f" : "transparent",
|
backgroundColor: "#2f2f2f",
|
||||||
},
|
},
|
||||||
cursor: userdata?.support ? "pointer" : "not-allowed",
|
cursor: "pointer",
|
||||||
}}
|
}}
|
||||||
disabled={userdata?.support === false}
|
|
||||||
>
|
>
|
||||||
<span style={{ position: "relative", left: !expandLeftNav ? 10 : 0, marginRight: 10, fontSize: 18 }}>
|
<span style={{ position: "relative", left: !expandLeftNav ? 10 : 0, marginRight: 10, fontSize: 18 }}>
|
||||||
•
|
•
|
||||||
@@ -1312,11 +1329,9 @@ useEffect(() => {
|
|||||||
transition: "opacity 0.3s ease",
|
transition: "opacity 0.3s ease",
|
||||||
fontSize: 18,
|
fontSize: 18,
|
||||||
color:
|
color:
|
||||||
userdata?.support && currentOpenTab === "detection" && currentPath.includes("/detection")
|
currentOpenTab === "detection" && currentPath.includes("/detection")
|
||||||
? "#F1F1F1"
|
? "#F1F1F1"
|
||||||
: userdata?.support
|
: "#C8C8C8"
|
||||||
? "#C8C8C8"
|
|
||||||
: "#6F6F6F",
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Forms
|
Forms
|
||||||
@@ -1329,19 +1344,18 @@ useEffect(() => {
|
|||||||
to={"/admin?tab=datastore"}
|
to={"/admin?tab=datastore"}
|
||||||
style={{
|
style={{
|
||||||
...hrefStyle,
|
...hrefStyle,
|
||||||
pointerEvents: userdata?.support ? "auto" : "none",
|
pointerEvents: "auto",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Button
|
<Button
|
||||||
onClick={(event) => {
|
onClick={(event) => {
|
||||||
if (!userdata?.support) return;
|
|
||||||
setCurrentOpenTab("response");
|
setCurrentOpenTab("response");
|
||||||
localStorage.setItem("lastTabOpenByUser", "response");
|
localStorage.setItem("lastTabOpenByUser", "response");
|
||||||
}}
|
}}
|
||||||
sx={{
|
sx={{
|
||||||
width: "100%",
|
width: "100%",
|
||||||
height: 35,
|
height: 35,
|
||||||
color: userdata?.support ? "#C8C8C8" : "#6F6F6F",
|
color: "#C8C8C8",
|
||||||
justifyContent: "flex-start",
|
justifyContent: "flex-start",
|
||||||
textTransform: "none",
|
textTransform: "none",
|
||||||
backgroundColor:
|
backgroundColor:
|
||||||
@@ -1349,9 +1363,9 @@ useEffect(() => {
|
|||||||
? "#2f2f2f"
|
? "#2f2f2f"
|
||||||
: "transparent",
|
: "transparent",
|
||||||
"&:hover": {
|
"&:hover": {
|
||||||
backgroundColor: userdata?.support ? "#2f2f2f" : "transparent",
|
backgroundColor: "#2f2f2f",
|
||||||
},
|
},
|
||||||
cursor: userdata?.support ? "pointer" : "not-allowed",
|
cursor: "pointer",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<span style={{ position: "relative", left: !expandLeftNav ? 10 : 0, marginRight: 10, fontSize: 18 }}>
|
<span style={{ position: "relative", left: !expandLeftNav ? 10 : 0, marginRight: 10, fontSize: 18 }}>
|
||||||
@@ -1364,11 +1378,9 @@ useEffect(() => {
|
|||||||
transition: "opacity 0.3s ease",
|
transition: "opacity 0.3s ease",
|
||||||
fontSize: 18,
|
fontSize: 18,
|
||||||
color:
|
color:
|
||||||
userdata?.support && currentOpenTab === "response" && currentPath.includes("/response")
|
currentOpenTab === "response" && currentPath.includes("/response")
|
||||||
? "#F1F1F1"
|
? "#F1F1F1"
|
||||||
: userdata?.support
|
: "#C8C8C8"
|
||||||
? "#C8C8C8"
|
|
||||||
: "#6F6F6F",
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Datastore
|
Datastore
|
||||||
@@ -1376,24 +1388,24 @@ useEffect(() => {
|
|||||||
</Button>
|
</Button>
|
||||||
</Link>
|
</Link>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<span style={{ display: "inline-block", width: "100%" }}>
|
<span style={{ display: "inline-block", width: "100%" }}>
|
||||||
<Link
|
<Link
|
||||||
to={"/admin?tab=files"}
|
to={"/admin?tab=files"}
|
||||||
style={{
|
style={{
|
||||||
...hrefStyle,
|
...hrefStyle,
|
||||||
pointerEvents: userdata?.support ? "auto" : "none",
|
pointerEvents: "auto",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Button
|
<Button
|
||||||
onClick={(event) => {
|
onClick={(event) => {
|
||||||
if (!userdata?.support) return;
|
|
||||||
setCurrentOpenTab("response");
|
setCurrentOpenTab("response");
|
||||||
localStorage.setItem("lastTabOpenByUser", "response");
|
localStorage.setItem("lastTabOpenByUser", "response");
|
||||||
}}
|
}}
|
||||||
sx={{
|
sx={{
|
||||||
width: "100%",
|
width: "100%",
|
||||||
height: 35,
|
height: 35,
|
||||||
color: userdata?.support ? "#C8C8C8" : "#6F6F6F",
|
color: "#C8C8C8",
|
||||||
justifyContent: "flex-start",
|
justifyContent: "flex-start",
|
||||||
textTransform: "none",
|
textTransform: "none",
|
||||||
backgroundColor:
|
backgroundColor:
|
||||||
@@ -1401,9 +1413,9 @@ useEffect(() => {
|
|||||||
? "#2f2f2f"
|
? "#2f2f2f"
|
||||||
: "transparent",
|
: "transparent",
|
||||||
"&:hover": {
|
"&:hover": {
|
||||||
backgroundColor: userdata?.support ? "#2f2f2f" : "transparent",
|
backgroundColor: "#2f2f2f",
|
||||||
},
|
},
|
||||||
cursor: userdata?.support ? "pointer" : "not-allowed",
|
cursor: "pointer",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<span style={{ position: "relative", left: !expandLeftNav ? 10 : 0, marginRight: 10, fontSize: 18 }}>
|
<span style={{ position: "relative", left: !expandLeftNav ? 10 : 0, marginRight: 10, fontSize: 18 }}>
|
||||||
@@ -1416,11 +1428,9 @@ useEffect(() => {
|
|||||||
transition: "opacity 0.3s ease",
|
transition: "opacity 0.3s ease",
|
||||||
fontSize: 18,
|
fontSize: 18,
|
||||||
color:
|
color:
|
||||||
userdata?.support && currentOpenTab === "response" && currentPath.includes("/response")
|
currentOpenTab === "response" && currentPath.includes("/response")
|
||||||
? "#F1F1F1"
|
? "#F1F1F1"
|
||||||
: userdata?.support
|
: "#C8C8C8"
|
||||||
? "#C8C8C8"
|
|
||||||
: "#6F6F6F",
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Files
|
Files
|
||||||
@@ -1428,8 +1438,59 @@ useEffect(() => {
|
|||||||
</Button>
|
</Button>
|
||||||
</Link>
|
</Link>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
|
<span style={{ display: "inline-block", width: "100%" }}>
|
||||||
|
<Link
|
||||||
|
to={"/admin?tab=locations"}
|
||||||
|
style={{
|
||||||
|
...hrefStyle,
|
||||||
|
pointerEvents: "auto",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
onClick={(event) => {
|
||||||
|
setCurrentOpenTab("response");
|
||||||
|
localStorage.setItem("lastTabOpenByUser", "response");
|
||||||
|
}}
|
||||||
|
sx={{
|
||||||
|
width: "100%",
|
||||||
|
height: 35,
|
||||||
|
color: "#C8C8C8",
|
||||||
|
justifyContent: "flex-start",
|
||||||
|
textTransform: "none",
|
||||||
|
backgroundColor:
|
||||||
|
currentOpenTab === "response" && currentPath.includes("/response")
|
||||||
|
? "#2f2f2f"
|
||||||
|
: "transparent",
|
||||||
|
"&:hover": {
|
||||||
|
backgroundColor: "#2f2f2f",
|
||||||
|
},
|
||||||
|
cursor: "pointer",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span style={{ position: "relative", left: !expandLeftNav ? 10 : 0, marginRight: 10, fontSize: 18 }}>
|
||||||
|
•
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
style={{
|
||||||
|
display: expandLeftNav ? "inline" : "none",
|
||||||
|
opacity: expandLeftNav ? 1 : 0,
|
||||||
|
transition: "opacity 0.3s ease",
|
||||||
|
fontSize: 18,
|
||||||
|
color:
|
||||||
|
currentOpenTab === "response" && currentPath.includes("/response")
|
||||||
|
? "#F1F1F1"
|
||||||
|
: "#C8C8C8"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Shuffle Agent
|
||||||
|
</span>
|
||||||
|
</Button>
|
||||||
|
</Link>
|
||||||
|
</span>
|
||||||
</Box>
|
</Box>
|
||||||
</Collapse>
|
</Collapse>
|
||||||
|
|
||||||
<Link to="/docs" style={hrefStyle}>
|
<Link to="/docs" style={hrefStyle}>
|
||||||
<Button
|
<Button
|
||||||
onClick={(event) => {
|
onClick={(event) => {
|
||||||
@@ -1464,6 +1525,38 @@ useEffect(() => {
|
|||||||
</span>
|
</span>
|
||||||
</Button>
|
</Button>
|
||||||
</Link>
|
</Link>
|
||||||
|
|
||||||
|
|
||||||
|
<Link to="/admin?admin_tab=billingstats" style={hrefStyle}>
|
||||||
|
<Button
|
||||||
|
onClick={(event) => {
|
||||||
|
setCurrentOpenTab("admin");
|
||||||
|
localStorage.setItem("lastTabOpenByUser", "admin");
|
||||||
|
}}
|
||||||
|
style={{
|
||||||
|
...ButtonStyle,
|
||||||
|
marginTop: 8,
|
||||||
|
marginTop: 8,
|
||||||
|
backgroundColor: currentOpenTab === "docs" && currentPath.includes("/admin") ? "#2f2f2f": "transparent",
|
||||||
|
}}
|
||||||
|
onMouseOver={(event)=>{
|
||||||
|
event.currentTarget.style.backgroundColor = "#2f2f2f";
|
||||||
|
}}
|
||||||
|
onMouseOut={(event)=>{
|
||||||
|
event.currentTarget.style.backgroundColor = currentOpenTab === "docs" && currentPath.includes("/admin") ? "#2f2f2f": "transparent";
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<BusinessIcon style={{ width: 16, height: 16, marginRight: expandLeftNav ? 10 : 0, color: "rgba(255,255,255,0.5)", }} />
|
||||||
|
<span
|
||||||
|
style={{
|
||||||
|
display: expandLeftNav ? "inline" : "none",
|
||||||
|
color: currentOpenTab === "admin" && currentPath.includes("/admin") ? "#F1F1F1" : "#C8C8C8",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Admin
|
||||||
|
</span>
|
||||||
|
</Button>
|
||||||
|
</Link>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
{recentworkflows?.length > 0 ?
|
{recentworkflows?.length > 0 ?
|
||||||
@@ -1549,6 +1642,7 @@ useEffect(() => {
|
|||||||
padding: option.id === "add_suborg" ? "0" : "12px 16px",
|
padding: option.id === "add_suborg" ? "0" : "12px 16px",
|
||||||
marginTop: index !== 0 ? 8 : 0,
|
marginTop: index !== 0 ? 8 : 0,
|
||||||
borderRadius: 6,
|
borderRadius: 6,
|
||||||
|
marginLeft: option.margin_left ? option.margin_left : 0,
|
||||||
}}
|
}}
|
||||||
onMouseOver={(e) => {
|
onMouseOver={(e) => {
|
||||||
e.currentTarget.style.backgroundColor = "#444444";
|
e.currentTarget.style.backgroundColor = "#444444";
|
||||||
@@ -1618,12 +1712,15 @@ useEffect(() => {
|
|||||||
setAutocompleteValue(newInputValue);
|
setAutocompleteValue(newInputValue);
|
||||||
}}
|
}}
|
||||||
filterOptions={(options, params) => {
|
filterOptions={(options, params) => {
|
||||||
|
const normalize = (str) => str.toLowerCase().replace(/[\s-]+/g, "");
|
||||||
|
const input = normalize(params.inputValue);
|
||||||
|
|
||||||
return options.filter((option) =>
|
return options.filter((option) =>
|
||||||
option.name
|
normalize(option.name).includes(input) ||
|
||||||
.toLowerCase()
|
normalize(option.region_url).includes(input)
|
||||||
.includes(params.inputValue.toLowerCase())
|
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
|
|
||||||
value={userOrgs}
|
value={userOrgs}
|
||||||
renderInput={(params) => (
|
renderInput={(params) => (
|
||||||
<Box
|
<Box
|
||||||
|
|||||||
@@ -431,7 +431,7 @@ const AuthenticationOauth2 = (props) => {
|
|||||||
|
|
||||||
const authentication_url = authenticationType.token_uri;
|
const authentication_url = authenticationType.token_uri;
|
||||||
const redirectUri = `${window.location.protocol}//${window.location.host}/set_authentication`;
|
const redirectUri = `${window.location.protocol}//${window.location.host}/set_authentication`;
|
||||||
const workflowId = workflow !== undefined ? workflow.id : "";
|
const workflowId = workflow !== undefined ? workflow.id : ""
|
||||||
var state = `workflow_id%3D${workflowId}%26reference_action_id%3d${selectedAction.app_id}%26app_name%3d${selectedAction.app_name}%26app_id%3d${selectedAction.app_id}%26app_version%3d${selectedAction.app_version}%26authentication_url%3d${authentication_url}%26scope%3d${resources}%26client_id%3d${client_id}%26client_secret%3d${client_secret}`;
|
var state = `workflow_id%3D${workflowId}%26reference_action_id%3d${selectedAction.app_id}%26app_name%3d${selectedAction.app_name}%26app_id%3d${selectedAction.app_id}%26app_version%3d${selectedAction.app_version}%26authentication_url%3d${authentication_url}%26scope%3d${resources}%26client_id%3d${client_id}%26client_secret%3d${client_secret}`;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -200,6 +200,7 @@ const ParsedAction = (props) => {
|
|||||||
const [menuPosition, setMenuPosition] = useState(null);
|
const [menuPosition, setMenuPosition] = useState(null);
|
||||||
const [uiBox, setUiBox] = useState(null);
|
const [uiBox, setUiBox] = useState(null);
|
||||||
const isIntegration = selectedAction.app_id === "integration"
|
const isIntegration = selectedAction.app_id === "integration"
|
||||||
|
const [distributeAuthToSuborgs, setDistributeAuthToSuborgs] = useState(selectedAction?.selectedAuthentication?.suborg_distributed || false)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (setLastSaved !== undefined) {
|
if (setLastSaved !== undefined) {
|
||||||
@@ -420,7 +421,7 @@ const ParsedAction = (props) => {
|
|||||||
);
|
);
|
||||||
if (foundAction !== null && foundAction !== undefined) {
|
if (foundAction !== null && foundAction !== undefined) {
|
||||||
var foundparams = [];
|
var foundparams = [];
|
||||||
for (let [paramkey,paramkeyval] in Object.entries(foundAction.parameters)) {
|
for (let [paramkey, paramkeyval] in Object.entries(foundAction.parameters)) {
|
||||||
const param = foundAction.parameters[paramkey];
|
const param = foundAction.parameters[paramkey];
|
||||||
|
|
||||||
const foundParam = selectedAction.parameters.find(
|
const foundParam = selectedAction.parameters.find(
|
||||||
@@ -454,7 +455,50 @@ const ParsedAction = (props) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const changeDistribution = (data) => {
|
||||||
|
editAuthenticationConfig(data.id, "suborg_distribute")
|
||||||
|
}
|
||||||
|
|
||||||
|
const editAuthenticationConfig = (id, parentAction) => {
|
||||||
|
const data = {
|
||||||
|
id: id,
|
||||||
|
action: parentAction !== undefined && parentAction !== null ? parentAction : "assign_everywhere",
|
||||||
|
}
|
||||||
|
|
||||||
|
const url = globalUrl + "/api/v1/apps/authentication/" + id + "/config";
|
||||||
|
|
||||||
|
fetch(url, {
|
||||||
|
mode: "cors",
|
||||||
|
method: "POST",
|
||||||
|
body: JSON.stringify(data),
|
||||||
|
credentials: "include",
|
||||||
|
crossDomain: true,
|
||||||
|
withCredentials: true,
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json; charset=utf-8",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.then((response) =>
|
||||||
|
response.json().then((responseJson) => {
|
||||||
|
if (responseJson["success"] === false) {
|
||||||
|
toast("Failed overwriting appauth");
|
||||||
|
} else {
|
||||||
|
if (distributeAuthToSuborgs) {
|
||||||
|
toast.success("Successfully updated auth");
|
||||||
|
} else {
|
||||||
|
toast.success("Successfully distributed auth to suborgs");
|
||||||
|
}
|
||||||
|
setTimeout(() => {
|
||||||
|
getAppAuthentication();
|
||||||
|
setDistributeAuthToSuborgs(!distributeAuthToSuborgs)
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.catch((error) => {
|
||||||
|
toast("Err: " + error.toString());
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const defineStartnode = () => {
|
const defineStartnode = () => {
|
||||||
if (cy === undefined) {
|
if (cy === undefined) {
|
||||||
@@ -522,7 +566,7 @@ const ParsedAction = (props) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(selectedAction.label !== prevActionName){
|
if (selectedAction.label !== prevActionName) {
|
||||||
setPrevActionName(selectedAction.label)
|
setPrevActionName(selectedAction.label)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -542,7 +586,7 @@ const ParsedAction = (props) => {
|
|||||||
if (!selectedVariableParameter && workflow.workflow_variables?.length > 0) {
|
if (!selectedVariableParameter && workflow.workflow_variables?.length > 0) {
|
||||||
setSelectedVariableParameter(workflow.workflow_variables[0].name);
|
setSelectedVariableParameter(workflow.workflow_variables[0].name);
|
||||||
}
|
}
|
||||||
},[selectedAction,selectedApp,setNewSelectedAction,workflow, workflowExecutions, getParents])
|
}, [selectedAction, selectedApp, setNewSelectedAction, workflow, workflowExecutions, getParents])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const newActionList = [];
|
const newActionList = [];
|
||||||
@@ -697,17 +741,17 @@ const ParsedAction = (props) => {
|
|||||||
let paramvalue = param.value === undefined || param.value === null ? "" : param.value;
|
let paramvalue = param.value === undefined || param.value === null ? "" : param.value;
|
||||||
let errorVars = [];
|
let errorVars = [];
|
||||||
|
|
||||||
if(paramvalue.includes("$")){
|
if (paramvalue.includes("$")) {
|
||||||
let actions = workflow.actions?.map((action) => {
|
let actions = workflow.actions?.map((action) => {
|
||||||
return "$"+action.label?.toLowerCase();
|
return "$" + action.label?.toLowerCase();
|
||||||
})
|
})
|
||||||
|
|
||||||
if(newActionList?.length > 0){
|
if (newActionList?.length > 0) {
|
||||||
let appParentActions = parentActionList?.map(action => "$" + action.name.toLowerCase());
|
let appParentActions = parentActionList?.map(action => "$" + action.name.toLowerCase());
|
||||||
let notPresentAction = actions?.filter((action) => !appParentActions?.includes(action))
|
let notPresentAction = actions?.filter((action) => !appParentActions?.includes(action))
|
||||||
notPresentAction?.forEach((action) => {
|
notPresentAction?.forEach((action) => {
|
||||||
action = action.replace(" ", "_");
|
action = action.replace(" ", "_");
|
||||||
if(paramvalue.includes(action)){
|
if (paramvalue.includes(action)) {
|
||||||
errorVars.push(action);
|
errorVars.push(action);
|
||||||
// paramvalue = paramvalue.replace(action, "")
|
// paramvalue = paramvalue.replace(action, "")
|
||||||
// paramvalue = paramvalue.replace(/^\s*[\r\n]/gm, "");
|
// paramvalue = paramvalue.replace(/^\s*[\r\n]/gm, "");
|
||||||
@@ -717,30 +761,30 @@ const ParsedAction = (props) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let message = "";
|
let message = "";
|
||||||
if(errorVars.length > 0){
|
if (errorVars.length > 0) {
|
||||||
if(errorVars.length === 1){
|
if (errorVars.length === 1) {
|
||||||
message = errorVars[0] + " is not accessible in this action.";
|
message = errorVars[0] + " is not accessible in this action.";
|
||||||
}else{
|
} else {
|
||||||
message = errorVars.join(", ") + " are not accessible in this action.";
|
message = errorVars.join(", ") + " are not accessible in this action.";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (param?.configuration) {
|
if (param?.configuration && param?.name !== "url") {
|
||||||
let regex = /(^|[^\\])\$/;
|
let regex = /(^|[^\\])\$/;
|
||||||
if (regex.test(paramvalue)) {
|
if (regex.test(paramvalue)) {
|
||||||
if(message.length > 0){
|
if (message.length > 0) {
|
||||||
message += "\nUse \"\\$\" instead of \"$\" if you want to escape $ (1)";
|
message += "\nUse \"\\$\" instead of \"$\" if you want to escape $ (1)";
|
||||||
}else{
|
} else {
|
||||||
message = "Use \"\\$\" instead of \"$\" if you want to escape $ (2)";
|
message = "Use \"\\$\" instead of \"$\" if you want to escape $ (2)";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return {...param, value: paramvalue, error: message}
|
return { ...param, value: paramvalue, error: message }
|
||||||
});
|
});
|
||||||
|
|
||||||
setSelectedActionParameters(newParameters);
|
setSelectedActionParameters(newParameters);
|
||||||
setActionlist(newActionList);
|
setActionlist(newActionList);
|
||||||
}, [workflow.execution_variables, paramUpdate, workflow.workflow_variables, workflowExecutions, workflow, selectedAction, listCache, getParents,setNewSelectedAction]);
|
}, [workflow.execution_variables, paramUpdate, workflow.workflow_variables, workflowExecutions, workflow, selectedAction, listCache, getParents, setNewSelectedAction]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
selectedNameChange(appActionName)
|
selectedNameChange(appActionName)
|
||||||
@@ -748,9 +792,9 @@ const ParsedAction = (props) => {
|
|||||||
if (actionDelayChange !== undefined) {
|
if (actionDelayChange !== undefined) {
|
||||||
actionDelayChange(delay)
|
actionDelayChange(delay)
|
||||||
}
|
}
|
||||||
},[appActionName,delay])
|
}, [appActionName, delay])
|
||||||
|
|
||||||
const handleParamChange = (event, count,data) => {
|
const handleParamChange = (event, count, data) => {
|
||||||
const newParams = [...selectedActionParameters];
|
const newParams = [...selectedActionParameters];
|
||||||
newParams.map((param) => {
|
newParams.map((param) => {
|
||||||
if (param.name === data.name) {
|
if (param.name === data.name) {
|
||||||
@@ -770,7 +814,7 @@ const ParsedAction = (props) => {
|
|||||||
|
|
||||||
if (found !== null && found !== undefined) {
|
if (found !== null && found !== undefined) {
|
||||||
var new_occurences = []
|
var new_occurences = []
|
||||||
for (let [key,keyval] in Object.entries(found)) {
|
for (let [key, keyval] in Object.entries(found)) {
|
||||||
if (found[key][0] !== "\\") {
|
if (found[key][0] !== "\\") {
|
||||||
new_occurences.push(found[key])
|
new_occurences.push(found[key])
|
||||||
}
|
}
|
||||||
@@ -784,7 +828,7 @@ const ParsedAction = (props) => {
|
|||||||
// When the found array is empty.
|
// When the found array is empty.
|
||||||
for (let i = 0; i < found.length; i++) {
|
for (let i = 0; i < found.length; i++) {
|
||||||
const variableSplit = found[i].split(".#")
|
const variableSplit = found[i].split(".#")
|
||||||
if ((variableSplit.length-1) > 1) {
|
if ((variableSplit.length - 1) > 1) {
|
||||||
//console.log("Larger than 1: ", variableSplit)
|
//console.log("Larger than 1: ", variableSplit)
|
||||||
if (looperText.length === 0) {
|
if (looperText.length === 0) {
|
||||||
looperText += "PS: Double looping (.#.#) may cause problems."
|
looperText += "PS: Double looping (.#.#) may cause problems."
|
||||||
@@ -795,7 +839,7 @@ const ParsedAction = (props) => {
|
|||||||
for (let j = 0; j < actionlist.length; j++) {
|
for (let j = 0; j < actionlist.length; j++) {
|
||||||
//console.log("ACTION: ", found[i], actionlist[j])
|
//console.log("ACTION: ", found[i], actionlist[j])
|
||||||
//console.log("ACTION :", found[i].split(".")[0].slice(1,).toLowerCase(), actionlist[j].autocomplete.toLowerCase())
|
//console.log("ACTION :", found[i].split(".")[0].slice(1,).toLowerCase(), actionlist[j].autocomplete.toLowerCase())
|
||||||
if(found[i].split(".")[0].slice(1,).toLowerCase() == actionlist[j].autocomplete.toLowerCase()){
|
if (found[i].split(".")[0].slice(1,).toLowerCase() == actionlist[j].autocomplete.toLowerCase()) {
|
||||||
//console.log("Found: ", found[i])
|
//console.log("Found: ", found[i])
|
||||||
// Validate path?
|
// Validate path?
|
||||||
|
|
||||||
@@ -805,9 +849,9 @@ const ParsedAction = (props) => {
|
|||||||
|
|
||||||
if (!foundSlice) {
|
if (!foundSlice) {
|
||||||
if (!helperText.includes("Invalid variables")) {
|
if (!helperText.includes("Invalid variables")) {
|
||||||
helperText+= "Invalid variables: "
|
helperText += "Invalid variables: "
|
||||||
}
|
}
|
||||||
helperText+= found[i] + ", "
|
helperText += found[i] + ", "
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -929,7 +973,7 @@ const ParsedAction = (props) => {
|
|||||||
|
|
||||||
var curstring = "";
|
var curstring = "";
|
||||||
var record = false;
|
var record = false;
|
||||||
for (let [key,keyval] in Object.entries(selectedActionParameters[count].value)) {
|
for (let [key, keyval] in Object.entries(selectedActionParameters[count].value)) {
|
||||||
const item = selectedActionParameters[count].value[key];
|
const item = selectedActionParameters[count].value[key];
|
||||||
if (record) {
|
if (record) {
|
||||||
curstring += item;
|
curstring += item;
|
||||||
@@ -1090,7 +1134,7 @@ const ParsedAction = (props) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.target.value[event.target.value.length-1] === "$") {
|
if (event.target.value[event.target.value.length - 1] === "$") {
|
||||||
if (!showDropdown) {
|
if (!showDropdown) {
|
||||||
setShowAutocomplete(false)
|
setShowAutocomplete(false)
|
||||||
setShowDropdown(true)
|
setShowDropdown(true)
|
||||||
@@ -1104,7 +1148,7 @@ const ParsedAction = (props) => {
|
|||||||
|
|
||||||
|
|
||||||
// bad detection mechanism probably
|
// bad detection mechanism probably
|
||||||
if (event.target.value[event.target.value.length-1] === "." && actionlist.length > 0) {
|
if (event.target.value[event.target.value.length - 1] === "." && actionlist.length > 0) {
|
||||||
console.log("GET THE LAST ARGUMENT FOR NODE!")
|
console.log("GET THE LAST ARGUMENT FOR NODE!")
|
||||||
// THIS IS AN EXAMPLE OF SHOWING IT
|
// THIS IS AN EXAMPLE OF SHOWING IT
|
||||||
/*
|
/*
|
||||||
@@ -1125,7 +1169,7 @@ const ParsedAction = (props) => {
|
|||||||
|
|
||||||
var curstring = ""
|
var curstring = ""
|
||||||
var record = false
|
var record = false
|
||||||
for (let [key,keyval] in Object.entries(selectedActionParameters[count].value)) {
|
for (let [key, keyval] in Object.entries(selectedActionParameters[count].value)) {
|
||||||
const item = selectedActionParameters[count].value[key]
|
const item = selectedActionParameters[count].value[key]
|
||||||
if (record) {
|
if (record) {
|
||||||
curstring += item
|
curstring += item
|
||||||
@@ -1315,7 +1359,7 @@ const ParsedAction = (props) => {
|
|||||||
if (selectedAction.name === "set_cache_value") {
|
if (selectedAction.name === "set_cache_value") {
|
||||||
var actionKey = ""
|
var actionKey = ""
|
||||||
var actionValue = ""
|
var actionValue = ""
|
||||||
for (let [key,keyval] in Object.entries(selectedActionParameters)) {
|
for (let [key, keyval] in Object.entries(selectedActionParameters)) {
|
||||||
const param = selectedActionParameters[key]
|
const param = selectedActionParameters[key]
|
||||||
if (param.name === "key") {
|
if (param.name === "key") {
|
||||||
actionKey = param.value
|
actionKey = param.value
|
||||||
@@ -1331,7 +1375,7 @@ const ParsedAction = (props) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!actionKey.includes(".#") && actionValue.includes(".#")) {
|
if (!actionKey.includes(".#") && actionValue.includes(".#")) {
|
||||||
return <span>When the key ({actionKey}) is static, but the value is a list ({actionValue}), it will overwrite the list. You may be looking for the <span onClick={() => {}} style={{cursor: "pointer", color: "#FF8544", }}>Check Cache Contains</span> action instead.</span>
|
return <span>When the key ({actionKey}) is static, but the value is a list ({actionValue}), it will overwrite the list. You may be looking for the <span onClick={() => { }} style={{ cursor: "pointer", color: "#FF8544", }}>Check Cache Contains</span> action instead.</span>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1349,8 +1393,8 @@ const ParsedAction = (props) => {
|
|||||||
selectedAction.errors = ["Suggestion: " + suggestionText]
|
selectedAction.errors = ["Suggestion: " + suggestionText]
|
||||||
}
|
}
|
||||||
|
|
||||||
return <Paper style={{padding: 10, backgroundColor: theme.palette.surfaceColor, border: "1px solid red",}}>
|
return <Paper style={{ padding: 10, backgroundColor: theme.palette.surfaceColor, border: "1px solid red", }}>
|
||||||
<Typography variant="body" style={{color: "white", }}>
|
<Typography variant="body" style={{ color: "white", }}>
|
||||||
<b>Tip:</b> {suggestionText}
|
<b>Tip:</b> {suggestionText}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Paper>
|
</Paper>
|
||||||
@@ -1433,7 +1477,7 @@ const ParsedAction = (props) => {
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div style={{ display: "flex", marginBottom: 0,}}>
|
<div style={{ display: "flex", marginBottom: 0, }}>
|
||||||
<span
|
<span
|
||||||
style={{
|
style={{
|
||||||
marginRight: 10,
|
marginRight: 10,
|
||||||
@@ -1443,10 +1487,10 @@ const ParsedAction = (props) => {
|
|||||||
>
|
>
|
||||||
{useIcon}
|
{useIcon}
|
||||||
</span>
|
</span>
|
||||||
<span style={{marginBottom: 0, marginTop: 3, }}>{newActionname}</span>
|
<span style={{ marginBottom: 0, marginTop: 3, }}>{newActionname}</span>
|
||||||
</div>
|
</div>
|
||||||
{extraDescription.length > 0 ?
|
{extraDescription.length > 0 ?
|
||||||
<Typography variant="body2" color="textSecondary" style={{marginTop: 0, overflow: "hidden", whiteSpace: "nowrap", display: "block",}}>
|
<Typography variant="body2" color="textSecondary" style={{ marginTop: 0, overflow: "hidden", whiteSpace: "nowrap", display: "block", }}>
|
||||||
{extraDescription}
|
{extraDescription}
|
||||||
</Typography>
|
</Typography>
|
||||||
: null}
|
: null}
|
||||||
@@ -1498,7 +1542,12 @@ const ParsedAction = (props) => {
|
|||||||
if (newAppname === undefined || newAppname === null) {
|
if (newAppname === undefined || newAppname === null) {
|
||||||
newAppname = ""
|
newAppname = ""
|
||||||
} else {
|
} else {
|
||||||
newAppname = newAppname.replaceAll("_", " ")
|
try {
|
||||||
|
newAppname = newAppname?.replaceAll("_", " ")
|
||||||
|
} catch (e) {
|
||||||
|
console.log("Error in replace newappname: ", e)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var optionalFound = false
|
var optionalFound = false
|
||||||
@@ -1514,7 +1563,7 @@ const ParsedAction = (props) => {
|
|||||||
//window.open("/apps/${selectedAction.app_id}", "_blank")
|
//window.open("/apps/${selectedAction.app_id}", "_blank")
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Tooltip title={"App: "+selectedAction.app_name} placement="top">
|
<Tooltip title={"App: " + selectedAction.app_name} placement="top">
|
||||||
<img src={selectedAppIcon} style={{
|
<img src={selectedAppIcon} style={{
|
||||||
width: 30,
|
width: 30,
|
||||||
height: 30,
|
height: 30,
|
||||||
@@ -1525,11 +1574,11 @@ const ParsedAction = (props) => {
|
|||||||
}} />
|
}} />
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
|
||||||
<h3 style={{ }}>
|
<h3 style={{}}>
|
||||||
{newAppname}
|
{newAppname}
|
||||||
</h3>
|
</h3>
|
||||||
</div>
|
</div>
|
||||||
<div style={{display: "flex", marginTop: 0, }}>
|
<div style={{ display: "flex", marginTop: 0, }}>
|
||||||
<IconButton
|
<IconButton
|
||||||
style={{
|
style={{
|
||||||
marginTop: "auto",
|
marginTop: "auto",
|
||||||
@@ -1542,7 +1591,7 @@ const ParsedAction = (props) => {
|
|||||||
if (workflowExecutions.length > 0) {
|
if (workflowExecutions.length > 0) {
|
||||||
// Look for the ID
|
// Look for the ID
|
||||||
var found = false;
|
var found = false;
|
||||||
for (let [key,keyval] in Object.entries(workflowExecutions)) {
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -1636,7 +1685,7 @@ const ParsedAction = (props) => {
|
|||||||
placement="top"
|
placement="top"
|
||||||
>
|
>
|
||||||
{autoCompleting ?
|
{autoCompleting ?
|
||||||
<CircularProgress style={{height: 20, width: 20, }} />
|
<CircularProgress style={{ height: 20, width: 20, }} />
|
||||||
:
|
:
|
||||||
<AutoFixHighIcon style={{ color: "rgba(255,255,255,0.7)", height: 24, }} />
|
<AutoFixHighIcon style={{ color: "rgba(255,255,255,0.7)", height: 24, }} />
|
||||||
}
|
}
|
||||||
@@ -1670,7 +1719,7 @@ const ParsedAction = (props) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
toast.success("Changed version of all nodes to "+event.target.value)
|
toast.success("Changed version of all nodes to " + event.target.value)
|
||||||
}}
|
}}
|
||||||
style={{
|
style={{
|
||||||
marginTop: 10,
|
marginTop: 10,
|
||||||
@@ -1704,9 +1753,9 @@ const ParsedAction = (props) => {
|
|||||||
) : null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div style={{display: "flex"}}>
|
<div style={{ display: "flex" }}>
|
||||||
<div style={{flex: 5}}>
|
<div style={{ flex: 5 }}>
|
||||||
<Typography style={{color: "rgba(255,255,255,0.7)"}}>Name</Typography>
|
<Typography style={{ color: "rgba(255,255,255,0.7)" }}>Name</Typography>
|
||||||
<TextField
|
<TextField
|
||||||
style={theme.palette.textFieldStyle}
|
style={theme.palette.textFieldStyle}
|
||||||
InputProps={{
|
InputProps={{
|
||||||
@@ -1725,8 +1774,8 @@ const ParsedAction = (props) => {
|
|||||||
onBlur={(e) => {
|
onBlur={(e) => {
|
||||||
// Copy the name value
|
// Copy the name value
|
||||||
const name = e.target.value
|
const name = e.target.value
|
||||||
const parsedBaseLabel = "$"+prevActionName.toLowerCase().replaceAll(" ", "_")
|
const parsedBaseLabel = "$" + prevActionName.toLowerCase().replaceAll(" ", "_")
|
||||||
const newname = "$"+name.toLowerCase().replaceAll(" ", "_")
|
const newname = "$" + name.toLowerCase().replaceAll(" ", "_")
|
||||||
|
|
||||||
// Check if it's the same as the current name in use
|
// Check if it's the same as the current name in use
|
||||||
//if (name === selectedAction.label) {
|
//if (name === selectedAction.label) {
|
||||||
@@ -1737,9 +1786,9 @@ const ParsedAction = (props) => {
|
|||||||
// Change in actions, triggers & conditions
|
// Change in actions, triggers & conditions
|
||||||
// Highlight the changes somehow with a glow?
|
// Highlight the changes somehow with a glow?
|
||||||
if (workflow.branches !== undefined && workflow.branches !== null) {
|
if (workflow.branches !== undefined && workflow.branches !== null) {
|
||||||
for (let [key,keyval] in Object.entries(workflow.branches)) {
|
for (let [key, keyval] in Object.entries(workflow.branches)) {
|
||||||
if (workflow.branches[key].conditions !== undefined && workflow.branches[key].conditions !== null) {
|
if (workflow.branches[key].conditions !== undefined && workflow.branches[key].conditions !== null) {
|
||||||
for (let [subkey,subkeyval] in Object.entries(workflow.branches[key].conditions)) {
|
for (let [subkey, subkeyval] in Object.entries(workflow.branches[key].conditions)) {
|
||||||
const condition = workflow.branches[key].conditions[subkey]
|
const condition = workflow.branches[key].conditions[subkey]
|
||||||
const sourceparam = condition.source
|
const sourceparam = condition.source
|
||||||
const destinationparam = condition.destination
|
const destinationparam = condition.destination
|
||||||
@@ -1762,22 +1811,22 @@ const ParsedAction = (props) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (foundindex >= 0) {
|
if (foundindex >= 0) {
|
||||||
previous = foundindex+newname.length
|
previous = foundindex + newname.length
|
||||||
// Need to add diff of length to word
|
// Need to add diff of length to word
|
||||||
|
|
||||||
// Check location:
|
// Check location:
|
||||||
// If it's a-zA-Z_ then don't replace
|
// If it's a-zA-Z_ then don't replace
|
||||||
if (sourceparam.value.length > foundindex+parsedBaseLabel.length) {
|
if (sourceparam.value.length > foundindex + parsedBaseLabel.length) {
|
||||||
const regex = /[a-zA-Z0-9_]/g;
|
const regex = /[a-zA-Z0-9_]/g;
|
||||||
const match = sourceparam.value[foundindex+parsedBaseLabel.length].match(regex);
|
const match = sourceparam.value[foundindex + parsedBaseLabel.length].match(regex);
|
||||||
if (match !== null) {
|
if (match !== null) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("Old found: ", workflow.branches[key].conditions[subkey].source.value)
|
console.log("Old found: ", workflow.branches[key].conditions[subkey].source.value)
|
||||||
const extralength = newname.length-parsedBaseLabel.length
|
const extralength = newname.length - parsedBaseLabel.length
|
||||||
sourceparam.value = sourceparam.value.substring(0, foundindex) + newname + sourceparam.value.substring(foundindex-extralength+newname.length, sourceparam.value.length)
|
sourceparam.value = sourceparam.value.substring(0, foundindex) + newname + sourceparam.value.substring(foundindex - extralength + newname.length, sourceparam.value.length)
|
||||||
|
|
||||||
console.log("New: ", workflow.branches[key].conditions[subkey].source.value)
|
console.log("New: ", workflow.branches[key].conditions[subkey].source.value)
|
||||||
} else {
|
} else {
|
||||||
@@ -1811,22 +1860,22 @@ const ParsedAction = (props) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (foundindex >= 0) {
|
if (foundindex >= 0) {
|
||||||
previous = foundindex+newname.length
|
previous = foundindex + newname.length
|
||||||
// Need to add diff of length to word
|
// Need to add diff of length to word
|
||||||
|
|
||||||
// Check location:
|
// Check location:
|
||||||
// If it's a-zA-Z_ then don't replace
|
// If it's a-zA-Z_ then don't replace
|
||||||
if (destinationparam.value.length > foundindex+parsedBaseLabel.length) {
|
if (destinationparam.value.length > foundindex + parsedBaseLabel.length) {
|
||||||
const regex = /[a-zA-Z0-9_]/g;
|
const regex = /[a-zA-Z0-9_]/g;
|
||||||
const match = destinationparam.value[foundindex+parsedBaseLabel.length].match(regex);
|
const match = destinationparam.value[foundindex + parsedBaseLabel.length].match(regex);
|
||||||
if (match !== null) {
|
if (match !== null) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("Old found: ", workflow.branches[key].conditions[subkey].destination.value)
|
console.log("Old found: ", workflow.branches[key].conditions[subkey].destination.value)
|
||||||
const extralength = newname.length-parsedBaseLabel.length
|
const extralength = newname.length - parsedBaseLabel.length
|
||||||
destinationparam.value = destinationparam.value.substring(0, foundindex) + newname + destinationparam.value.substring(foundindex-extralength+newname.length, destinationparam.value.length)
|
destinationparam.value = destinationparam.value.substring(0, foundindex) + newname + destinationparam.value.substring(foundindex - extralength + newname.length, destinationparam.value.length)
|
||||||
|
|
||||||
console.log("New: ", workflow.branches[key].conditions[subkey].destination.value)
|
console.log("New: ", workflow.branches[key].conditions[subkey].destination.value)
|
||||||
} else {
|
} else {
|
||||||
@@ -1848,7 +1897,7 @@ const ParsedAction = (props) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let [key,keyval] in Object.entries(workflow.actions)) {
|
for (let [key, keyval] in Object.entries(workflow.actions)) {
|
||||||
if (workflow.actions[key].id === selectedAction.id) {
|
if (workflow.actions[key].id === selectedAction.id) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -1883,21 +1932,21 @@ const ParsedAction = (props) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (foundindex >= 0) {
|
if (foundindex >= 0) {
|
||||||
previous = foundindex+newname.length
|
previous = foundindex + newname.length
|
||||||
// Need to add diff of length to word
|
// Need to add diff of length to word
|
||||||
|
|
||||||
// Check location:
|
// Check location:
|
||||||
// If it's a-zA-Z_ then don't replace
|
// If it's a-zA-Z_ then don't replace
|
||||||
if (param.value.length > foundindex+parsedBaseLabel.length) {
|
if (param.value.length > foundindex + parsedBaseLabel.length) {
|
||||||
const regex = /[a-zA-Z0-9_]/g;
|
const regex = /[a-zA-Z0-9_]/g;
|
||||||
const match = param.value[foundindex+parsedBaseLabel.length].match(regex);
|
const match = param.value[foundindex + parsedBaseLabel.length].match(regex);
|
||||||
if (match !== null) {
|
if (match !== null) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const extralength = newname.length-parsedBaseLabel.length
|
const extralength = newname.length - parsedBaseLabel.length
|
||||||
param.value = param.value.substring(0, foundindex) + newname + param.value.substring(foundindex-extralength+newname.length, param.value.length)
|
param.value = param.value.substring(0, foundindex) + newname + param.value.substring(foundindex - extralength + newname.length, param.value.length)
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
break
|
break
|
||||||
@@ -1922,14 +1971,14 @@ const ParsedAction = (props) => {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{/*!isCloud ? null :*/}
|
{/*!isCloud ? null :*/}
|
||||||
<div style={{flex: 1, marginLeft: 5,}}>
|
<div style={{ flex: 1, marginLeft: 5, }}>
|
||||||
<Tooltip
|
<Tooltip
|
||||||
color="primary"
|
color="primary"
|
||||||
title={"Delay before action executes (in seconds)"}
|
title={"Delay before action executes (in seconds)"}
|
||||||
placement="top"
|
placement="top"
|
||||||
>
|
>
|
||||||
<span>
|
<span>
|
||||||
<Typography style={{color: "rgba(255,255,255,0.7)"}}>Delay</Typography>
|
<Typography style={{ color: "rgba(255,255,255,0.7)" }}>Delay</Typography>
|
||||||
<TextField
|
<TextField
|
||||||
InputProps={{
|
InputProps={{
|
||||||
style: theme.palette.innerTextfieldStyle,
|
style: theme.palette.innerTextfieldStyle,
|
||||||
@@ -1987,8 +2036,31 @@ const ParsedAction = (props) => {
|
|||||||
{selectedAction.authentication !== undefined &&
|
{selectedAction.authentication !== undefined &&
|
||||||
selectedAction.authentication !== null &&
|
selectedAction.authentication !== null &&
|
||||||
selectedAction.authentication.length > 0 ? (
|
selectedAction.authentication.length > 0 ? (
|
||||||
<div style={{ marginTop: 15 }}>
|
|
||||||
<Typography style={{color: "rgba(255,255,255,0.7)"}}>Authentication</Typography>
|
<div style={{ marginTop: 15, position: "relative", }}>
|
||||||
|
<Typography style={{ color: "rgba(255,255,255,0.7)" }}>Authentication</Typography>
|
||||||
|
<Tooltip
|
||||||
|
title={
|
||||||
|
workflow?.suborg_distribution?.length > 0 && Object.getOwnPropertyNames(selectedAction?.selectedAuthentication).length !== 0 ? (
|
||||||
|
<React.Fragment>
|
||||||
|
<div style={{padding: 10, backgroundColor: theme.palette.inputColor, borderRadius: theme.palette.borderRadius, border: "1px solid rgba(255,255,255,0)"}}>
|
||||||
|
<FormControlLabel
|
||||||
|
control={
|
||||||
|
<Checkbox
|
||||||
|
checked={distributeAuthToSuborgs}
|
||||||
|
onChange={(event) => {
|
||||||
|
changeDistribution(selectedAction?.selectedAuthentication)
|
||||||
|
}}
|
||||||
|
name="distributeAuth"
|
||||||
|
color="primary"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
label="Distribute auth to suborgs"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</React.Fragment>
|
||||||
|
) : null
|
||||||
|
} placement="left">
|
||||||
<div style={{ display: "flex" }}>
|
<div style={{ display: "flex" }}>
|
||||||
<Select
|
<Select
|
||||||
MenuProps={{
|
MenuProps={{
|
||||||
@@ -2008,11 +2080,12 @@ const ParsedAction = (props) => {
|
|||||||
}}
|
}}
|
||||||
fullWidth
|
fullWidth
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
|
|
||||||
if (e.target.value === "No selection") {
|
if (e.target.value === "No selection") {
|
||||||
selectedAction.selectedAuthentication = {};
|
selectedAction.selectedAuthentication = {};
|
||||||
selectedAction.authentication_id = "";
|
selectedAction.authentication_id = "";
|
||||||
|
|
||||||
for (let [key,keyval] in Object.entries(selectedAction.parameters)) {
|
for (let [key, keyval] in Object.entries(selectedAction.parameters)) {
|
||||||
if (selectedAction.parameters[key].configuration === false) {
|
if (selectedAction.parameters[key].configuration === false) {
|
||||||
//console.log("FIELDSKIP: ", selectedAction.parameters[key].name)
|
//console.log("FIELDSKIP: ", selectedAction.parameters[key].name)
|
||||||
continue
|
continue
|
||||||
@@ -2033,6 +2106,7 @@ const ParsedAction = (props) => {
|
|||||||
selectedAction.parameters[key].value = ""
|
selectedAction.parameters[key].value = ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setSelectedAction(selectedAction)
|
setSelectedAction(selectedAction)
|
||||||
setUpdate(Math.random())
|
setUpdate(Math.random())
|
||||||
|
|
||||||
@@ -2047,7 +2121,7 @@ const ParsedAction = (props) => {
|
|||||||
selectedAction.selectedAuthentication = {};
|
selectedAction.selectedAuthentication = {};
|
||||||
selectedAction.authentication_id = "authgroups"
|
selectedAction.authentication_id = "authgroups"
|
||||||
|
|
||||||
for (let [key,keyval] in Object.entries(selectedAction.parameters)) {
|
for (let [key, keyval] in Object.entries(selectedAction.parameters)) {
|
||||||
//console.log(selectedAction.parameters[key])
|
//console.log(selectedAction.parameters[key])
|
||||||
if (selectedAction.parameters[key].configuration) {
|
if (selectedAction.parameters[key].configuration) {
|
||||||
|
|
||||||
@@ -2064,6 +2138,9 @@ const ParsedAction = (props) => {
|
|||||||
} else {
|
} else {
|
||||||
selectedAction.selectedAuthentication = e.target.value;
|
selectedAction.selectedAuthentication = e.target.value;
|
||||||
selectedAction.authentication_id = e.target.value.id;
|
selectedAction.authentication_id = e.target.value.id;
|
||||||
|
|
||||||
|
setDistributeAuthToSuborgs(e.target.value?.suborg_distributed || false)
|
||||||
|
|
||||||
setSelectedAction(selectedAction)
|
setSelectedAction(selectedAction)
|
||||||
setUpdate(Math.random())
|
setUpdate(Math.random())
|
||||||
}
|
}
|
||||||
@@ -2105,16 +2182,16 @@ const ParsedAction = (props) => {
|
|||||||
{data?.validation?.valid === true ?
|
{data?.validation?.valid === true ?
|
||||||
<Tooltip title="Authentication has been validated" placement="top">
|
<Tooltip title="Authentication has been validated" placement="top">
|
||||||
<Chip
|
<Chip
|
||||||
style={{marginLeft: 0, padding: 0, marginRight: 10, cursor: "pointer", borderColor: green, maxHeight: 25, }}
|
style={{ marginLeft: 0, padding: 0, marginRight: 10, cursor: "pointer", borderColor: green, maxHeight: 25, }}
|
||||||
label={"Valid"}
|
label={"Valid"}
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
color="secondary"
|
color="secondary"
|
||||||
/>
|
/>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
: null }
|
: null}
|
||||||
{data?.last_modified === true ?
|
{data?.last_modified === true ?
|
||||||
<Chip
|
<Chip
|
||||||
style={{marginLeft: 0, padding: 0, marginRight: 10, cursor: "pointer", maxHeight: 25, }}
|
style={{ marginLeft: 0, padding: 0, marginRight: 10, cursor: "pointer", maxHeight: 25, }}
|
||||||
label={"Latest"}
|
label={"Latest"}
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
color="secondary"
|
color="secondary"
|
||||||
@@ -2133,7 +2210,7 @@ const ParsedAction = (props) => {
|
|||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
|
||||||
<Divider style={{marginTop: 10, marginBottom: 10, }}/>
|
<Divider style={{ marginTop: 10, marginBottom: 10, }} />
|
||||||
|
|
||||||
<MenuItem
|
<MenuItem
|
||||||
style={{
|
style={{
|
||||||
@@ -2165,12 +2242,13 @@ const ParsedAction = (props) => {
|
|||||||
</IconButton>
|
</IconButton>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</div>
|
</div>
|
||||||
|
</Tooltip>
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
{selectedAction.authentication_id === "authgroups" && (authGroups === undefined || authGroups === null || authGroups.length === 0) ?
|
{selectedAction.authentication_id === "authgroups" && (authGroups === undefined || authGroups === null || authGroups.length === 0) ?
|
||||||
<a href="/admin?tab=app_auth" target="_blank" style={{textDecoration: "none", color: "#FF8544",}}>
|
<a href="/admin?tab=app_auth" target="_blank" style={{ textDecoration: "none", color: "#FF8544", }}>
|
||||||
<Typography variant="body2" style={{marginTop: 5,}}>
|
<Typography variant="body2" style={{ marginTop: 5, }}>
|
||||||
Create your first Authentication group
|
Create your first Authentication group
|
||||||
</Typography>
|
</Typography>
|
||||||
</a>
|
</a>
|
||||||
@@ -2364,7 +2442,7 @@ const ParsedAction = (props) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<li key={params.key}>
|
<li key={params.key}>
|
||||||
<Typography variant="body1" style={{textAlign: "center", marginLeft: 10, marginTop: 25, marginBottom: 10, }}>{params.group}</Typography>
|
<Typography variant="body1" style={{ textAlign: "center", marginLeft: 10, marginTop: 25, marginBottom: 10, }}>{params.group}</Typography>
|
||||||
<Typography variant="body2">{params.children}</Typography>
|
<Typography variant="body2">{params.children}</Typography>
|
||||||
</li>
|
</li>
|
||||||
)
|
)
|
||||||
@@ -2383,7 +2461,7 @@ const ParsedAction = (props) => {
|
|||||||
return options
|
return options
|
||||||
}}
|
}}
|
||||||
getOptionLabel={(option) => {
|
getOptionLabel={(option) => {
|
||||||
if (option === undefined || option === null || option.name === undefined || option.name === null ) {
|
if (option === undefined || option === null || option.name === undefined || option.name === null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2429,7 +2507,7 @@ const ParsedAction = (props) => {
|
|||||||
if (option.description === undefined || option.description === null) {
|
if (option.description === undefined || option.description === null) {
|
||||||
newActiondescription = "Description: No description defined for this action"
|
newActiondescription = "Description: No description defined for this action"
|
||||||
} else {
|
} else {
|
||||||
newActiondescription = "Description: "+newActiondescription
|
newActiondescription = "Description: " + newActiondescription
|
||||||
}
|
}
|
||||||
|
|
||||||
const iconInfo = GetIconInfo({ name: option.name });
|
const iconInfo = GetIconInfo({ name: option.name });
|
||||||
@@ -2467,7 +2545,7 @@ const ParsedAction = (props) => {
|
|||||||
const descSplit = option.description.split("\n")
|
const descSplit = option.description.split("\n")
|
||||||
// Last line of descSplit
|
// Last line of descSplit
|
||||||
if (descSplit.length > 0) {
|
if (descSplit.length > 0) {
|
||||||
extraUrl = descSplit[descSplit.length-1]
|
extraUrl = descSplit[descSplit.length - 1]
|
||||||
}
|
}
|
||||||
|
|
||||||
if (extraUrl.length > 0) {
|
if (extraUrl.length > 0) {
|
||||||
@@ -2569,7 +2647,7 @@ const ParsedAction = (props) => {
|
|||||||
<div style={{ marginTop: hideExtraTypes ? 10 : 30 }}>
|
<div style={{ marginTop: hideExtraTypes ? 10 : 30 }}>
|
||||||
{isIntegration ?
|
{isIntegration ?
|
||||||
apps !== undefined && apps !== null && apps.length > 0 ?
|
apps !== undefined && apps !== null && apps.length > 0 ?
|
||||||
<div style={{display: "flex", maxWidth: 335, overflowX: "auto", overflowY: "hidden",}}>
|
<div style={{ display: "flex", maxWidth: 335, overflowX: "auto", overflowY: "hidden", }}>
|
||||||
<div onClick={() => {
|
<div onClick={() => {
|
||||||
|
|
||||||
selectedAction.example = "noapp"
|
selectedAction.example = "noapp"
|
||||||
@@ -2605,7 +2683,7 @@ const ParsedAction = (props) => {
|
|||||||
|
|
||||||
}}>
|
}}>
|
||||||
<Tooltip title={"Unselect which App to use"} placement="top">
|
<Tooltip title={"Unselect which App to use"} placement="top">
|
||||||
<div style={{textAlign: "center", }}>
|
<div style={{ textAlign: "center", }}>
|
||||||
<img
|
<img
|
||||||
src={wrapperapp.large_image}
|
src={wrapperapp.large_image}
|
||||||
style={{
|
style={{
|
||||||
@@ -2704,7 +2782,7 @@ const ParsedAction = (props) => {
|
|||||||
title={"Click to learn more about this action"}
|
title={"Click to learn more about this action"}
|
||||||
placement="top"
|
placement="top"
|
||||||
>
|
>
|
||||||
<div style={{marginTop: 50, }} />
|
<div style={{ marginTop: 50, }} />
|
||||||
{/*
|
{/*
|
||||||
<Button
|
<Button
|
||||||
variant="text"
|
variant="text"
|
||||||
@@ -2812,11 +2890,11 @@ const ParsedAction = (props) => {
|
|||||||
renderInput={(params) => {
|
renderInput={(params) => {
|
||||||
if (params.inputProps !== undefined && params.inputProps !== null && params.inputProps.value !== undefined && params.inputProps.value !== null) {
|
if (params.inputProps !== undefined && params.inputProps !== null && params.inputProps.value !== undefined && params.inputProps.value !== null) {
|
||||||
const prefixes = ["Post", "Put", "Patch"]
|
const prefixes = ["Post", "Put", "Patch"]
|
||||||
for (let [key,keyval] in Object.entries(prefixes)) {
|
for (let [key, keyval] in Object.entries(prefixes)) {
|
||||||
if (params.inputProps.value.startsWith(prefixes[key])) {
|
if (params.inputProps.value.startsWith(prefixes[key])) {
|
||||||
params.inputProps.value = params.inputProps.value.replace(prefixes[key]+" ", "", -1)
|
params.inputProps.value = params.inputProps.value.replace(prefixes[key] + " ", "", -1)
|
||||||
if (params.inputProps.value.length > 1) {
|
if (params.inputProps.value.length > 1) {
|
||||||
params.inputProps.value = params.inputProps.value.charAt(0).toUpperCase()+params.inputProps.value.substring(1)
|
params.inputProps.value = params.inputProps.value.charAt(0).toUpperCase() + params.inputProps.value.substring(1)
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -3316,7 +3394,7 @@ const ParsedAction = (props) => {
|
|||||||
<CloseIcon fontSize="small" />
|
<CloseIcon fontSize="small" />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</Box>
|
</Box>
|
||||||
<Divider sx={{ backgroundColor: theme.palette.surfaceColor, marginTop: "5px", marginBottom : "10px", height: "3px" }}/>
|
<Divider sx={{ backgroundColor: theme.palette.surfaceColor, marginTop: "5px", marginBottom: "10px", height: "3px" }} />
|
||||||
<Box display="flex" flexDirection="column">
|
<Box display="flex" flexDirection="column">
|
||||||
<Typography variant="body2" mb={0.5}>
|
<Typography variant="body2" mb={0.5}>
|
||||||
<strong>Required:</strong> {data.required === true || data.configuration === true ? "True" : "False"}
|
<strong>Required:</strong> {data.required === true || data.configuration === true ? "True" : "False"}
|
||||||
@@ -3343,7 +3421,7 @@ const ParsedAction = (props) => {
|
|||||||
localStorage.setItem("disabled_ui_box", "true")
|
localStorage.setItem("disabled_ui_box", "true")
|
||||||
setUiBox("closed")
|
setUiBox("closed")
|
||||||
}}>
|
}}>
|
||||||
<Typography style={{marginTop: 10, color: "#FF8544", cursor: "pointer",}} variant="body2">
|
<Typography style={{ marginTop: 10, color: "#FF8544", cursor: "pointer", }} variant="body2">
|
||||||
Don't show again
|
Don't show again
|
||||||
</Typography>
|
</Typography>
|
||||||
</div>
|
</div>
|
||||||
@@ -3441,7 +3519,7 @@ const ParsedAction = (props) => {
|
|||||||
error={
|
error={
|
||||||
data?.error?.length > 0 ? true : false
|
data?.error?.length > 0 ? true : false
|
||||||
}
|
}
|
||||||
helperText={data?.error?.length > 0 ? errorHelperText(data?.name,data?.value,data?.error) : returnHelperText(data.name, data.value)}
|
helperText={data?.error?.length > 0 ? errorHelperText(data?.name, data?.value, data?.error) : returnHelperText(data.name, data.value)}
|
||||||
//options={{
|
//options={{
|
||||||
// theme: 'gruvbox-dark',
|
// theme: 'gruvbox-dark',
|
||||||
// keyMap: 'sublime',
|
// keyMap: 'sublime',
|
||||||
@@ -3497,7 +3575,7 @@ const ParsedAction = (props) => {
|
|||||||
|
|
||||||
var foundnewline = false
|
var foundnewline = false
|
||||||
var allValues = []
|
var allValues = []
|
||||||
for (let [key,keyval] in Object.entries(splitdata)) {
|
for (let [key, keyval] in Object.entries(splitdata)) {
|
||||||
const line = splitdata[key]
|
const line = splitdata[key]
|
||||||
if (line === "") {
|
if (line === "") {
|
||||||
foundnewline = true
|
foundnewline = true
|
||||||
@@ -3513,7 +3591,7 @@ const ParsedAction = (props) => {
|
|||||||
splitvalue = "="
|
splitvalue = "="
|
||||||
}
|
}
|
||||||
|
|
||||||
if (splitvalue.length === 0){
|
if (splitvalue.length === 0) {
|
||||||
allValues.push({
|
allValues.push({
|
||||||
key: line,
|
key: line,
|
||||||
value: "",
|
value: "",
|
||||||
@@ -3554,10 +3632,10 @@ const ParsedAction = (props) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<span key={index}>
|
<span key={index}>
|
||||||
<div style={{display: "flex"}}>
|
<div style={{ display: "flex" }}>
|
||||||
<TextField
|
<TextField
|
||||||
placeholder="Key"
|
placeholder="Key"
|
||||||
style={{flex: 5}}
|
style={{ flex: 5 }}
|
||||||
defaultValue={inputdata.key}
|
defaultValue={inputdata.key}
|
||||||
onBlur={(e) => {
|
onBlur={(e) => {
|
||||||
console.log("Change from oldkey to new: ", oldkey, e.target.value)
|
console.log("Change from oldkey to new: ", oldkey, e.target.value)
|
||||||
@@ -3567,7 +3645,7 @@ const ParsedAction = (props) => {
|
|||||||
const tmpsplit = selectedActionParameters[count].value.split("\n")
|
const tmpsplit = selectedActionParameters[count].value.split("\n")
|
||||||
var valsplit = []
|
var valsplit = []
|
||||||
var add_empty = false
|
var add_empty = false
|
||||||
for (let [key,keyval] in Object.entries(tmpsplit)) {
|
for (let [key, keyval] in Object.entries(tmpsplit)) {
|
||||||
if (tmpsplit[key] === "") {
|
if (tmpsplit[key] === "") {
|
||||||
add_empty = true
|
add_empty = true
|
||||||
continue
|
continue
|
||||||
@@ -3582,7 +3660,7 @@ const ParsedAction = (props) => {
|
|||||||
console.log("Split: ", valsplit)
|
console.log("Split: ", valsplit)
|
||||||
|
|
||||||
var newarr = []
|
var newarr = []
|
||||||
for (let [key,keyval] in Object.entries(valsplit)) {
|
for (let [key, keyval] in Object.entries(valsplit)) {
|
||||||
var line = valsplit[key]
|
var line = valsplit[key]
|
||||||
|
|
||||||
if (key == index) {
|
if (key == index) {
|
||||||
@@ -3612,7 +3690,7 @@ const ParsedAction = (props) => {
|
|||||||
/>
|
/>
|
||||||
<TextField
|
<TextField
|
||||||
placeholder="Value"
|
placeholder="Value"
|
||||||
style={{flex: 6}}
|
style={{ flex: 6 }}
|
||||||
defaultValue={inputdata.value}
|
defaultValue={inputdata.value}
|
||||||
onBlur={(e) => {
|
onBlur={(e) => {
|
||||||
console.log("Change from oldval to new: ", oldval, e.target.value)
|
console.log("Change from oldval to new: ", oldval, e.target.value)
|
||||||
@@ -3622,7 +3700,7 @@ const ParsedAction = (props) => {
|
|||||||
var tmpsplit = selectedActionParameters[count].value.split("\n")
|
var tmpsplit = selectedActionParameters[count].value.split("\n")
|
||||||
var valsplit = []
|
var valsplit = []
|
||||||
var add_empty = false
|
var add_empty = false
|
||||||
for (let [key,keyval] in Object.entries(tmpsplit)) {
|
for (let [key, keyval] in Object.entries(tmpsplit)) {
|
||||||
if (tmpsplit[key] === "") {
|
if (tmpsplit[key] === "") {
|
||||||
add_empty = true
|
add_empty = true
|
||||||
continue
|
continue
|
||||||
@@ -3637,7 +3715,7 @@ const ParsedAction = (props) => {
|
|||||||
console.log("Split: ", valsplit)
|
console.log("Split: ", valsplit)
|
||||||
|
|
||||||
var newarr = []
|
var newarr = []
|
||||||
for (let [key,keyval] in Object.entries(valsplit)) {
|
for (let [key, keyval] in Object.entries(valsplit)) {
|
||||||
var line = valsplit[key]
|
var line = valsplit[key]
|
||||||
|
|
||||||
if (key == index) {
|
if (key == index) {
|
||||||
@@ -3750,7 +3828,7 @@ const ParsedAction = (props) => {
|
|||||||
onChange={(event) => {
|
onChange={(event) => {
|
||||||
changeActionParameter(event, count, data);
|
changeActionParameter(event, count, data);
|
||||||
}}
|
}}
|
||||||
onBlur={(event) => {}}
|
onBlur={(event) => { }}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
} else if (
|
} else if (
|
||||||
@@ -3856,7 +3934,7 @@ const ParsedAction = (props) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleItemClick = (values) => {
|
const handleItemClick = (values) => {
|
||||||
if (values === undefined ||values === null ||values.length === 0) {
|
if (values === undefined || values === null || values.length === 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3866,7 +3944,7 @@ const ParsedAction = (props) => {
|
|||||||
: "$" + values[0].autocomplete;
|
: "$" + values[0].autocomplete;
|
||||||
|
|
||||||
toComplete = toComplete.toLowerCase().replaceAll(" ", "_");
|
toComplete = toComplete.toLowerCase().replaceAll(" ", "_");
|
||||||
for (let [key,keyval] in Object.entries(values)) {
|
for (let [key, keyval] in Object.entries(values)) {
|
||||||
if (key == 0 || values[key].autocomplete.length === 0) {
|
if (key == 0 || values[key].autocomplete.length === 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -3921,7 +3999,7 @@ const ParsedAction = (props) => {
|
|||||||
|
|
||||||
console.log("In nestedclick!!")
|
console.log("In nestedclick!!")
|
||||||
var newValue = selectedActionParameters[count].value + toComplete
|
var newValue = selectedActionParameters[count].value + toComplete
|
||||||
changeActionParameter({target: {value: newValue}}, count, data, true)
|
changeActionParameter({ target: { value: newValue } }, count, data, true)
|
||||||
//selectedActionParameters[count].value += toComplete;
|
//selectedActionParameters[count].value += toComplete;
|
||||||
//selectedAction.parameters[count].value = selectedActionParameters[count].value;
|
//selectedAction.parameters[count].value = selectedActionParameters[count].value;
|
||||||
//setSelectedAction(selectedAction);
|
//setSelectedAction(selectedAction);
|
||||||
@@ -3978,7 +4056,7 @@ const ParsedAction = (props) => {
|
|||||||
workflow.triggers !== null &&
|
workflow.triggers !== null &&
|
||||||
workflow.triggers.length > 0
|
workflow.triggers.length > 0
|
||||||
) {
|
) {
|
||||||
for (let [key,keyval] in Object.entries(workflow.triggers)) {
|
for (let [key, keyval] in Object.entries(workflow.triggers)) {
|
||||||
const item = workflow.triggers[key];
|
const item = workflow.triggers[key];
|
||||||
|
|
||||||
if (cy !== undefined) {
|
if (cy !== undefined) {
|
||||||
@@ -4083,7 +4161,7 @@ const ParsedAction = (props) => {
|
|||||||
handleItemClick([innerdata]);
|
handleItemClick([innerdata]);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Paper style={{minHeight: 500, maxHeight: 500, minWidth: 275, maxWidth: 275, position: "fixed", top: menuPosition1.top-200, left: menuPosition1.left-450, padding: "10px 0px 10px 10px", overflow: "hidden", overflowY: "auto", border: "1px solid rgba(255,255,255,0.3)",}}>
|
<Paper style={{ minHeight: 500, maxHeight: 500, minWidth: 275, maxWidth: 275, position: "fixed", top: menuPosition1.top - 200, left: menuPosition1.left - 450, padding: "10px 0px 10px 10px", overflow: "hidden", overflowY: "auto", border: "1px solid rgba(255,255,255,0.3)", }}>
|
||||||
<MenuItem
|
<MenuItem
|
||||||
key={innerdata.name}
|
key={innerdata.name}
|
||||||
style={{
|
style={{
|
||||||
@@ -4102,7 +4180,7 @@ const ParsedAction = (props) => {
|
|||||||
handleItemClick([innerdata]);
|
handleItemClick([innerdata]);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Typography variant="h6" style={{paddingBottom: 5}}>
|
<Typography variant="h6" style={{ paddingBottom: 5 }}>
|
||||||
{innerdata.name}
|
{innerdata.name}
|
||||||
</Typography>
|
</Typography>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
@@ -4111,20 +4189,20 @@ const ParsedAction = (props) => {
|
|||||||
//<VpnKeyIcon style={iconStyle} />
|
//<VpnKeyIcon style={iconStyle} />
|
||||||
const icon =
|
const icon =
|
||||||
pathdata.type === "value" ? (
|
pathdata.type === "value" ? (
|
||||||
<span style={{marginLeft: 9, }} />
|
<span style={{ marginLeft: 9, }} />
|
||||||
) : pathdata.type === "list" ? (
|
) : pathdata.type === "list" ? (
|
||||||
<FormatListNumberedIcon style={{marginLeft: 9, marginRight: 10, }} />
|
<FormatListNumberedIcon style={{ marginLeft: 9, marginRight: 10, }} />
|
||||||
) : (
|
) : (
|
||||||
<CircleIcon style={{marginLeft: 9, marginRight: 10, color: coverColor}}/>
|
<CircleIcon style={{ marginLeft: 9, marginRight: 10, color: coverColor }} />
|
||||||
);
|
);
|
||||||
//<ExpandMoreIcon style={iconStyle} />
|
//<ExpandMoreIcon style={iconStyle} />
|
||||||
|
|
||||||
const indentation_count = (pathdata.name.match(/\./g) || []).length+1
|
const indentation_count = (pathdata.name.match(/\./g) || []).length + 1
|
||||||
const baseIndent = <div style={{marginLeft: 20, height: 30, width: 1, backgroundColor: coverColor,}} />
|
const baseIndent = <div style={{ marginLeft: 20, height: 30, width: 1, backgroundColor: coverColor, }} />
|
||||||
//const boxPadding = pathdata.type === "object" ? "10px 0px 0px 0px" : 0
|
//const boxPadding = pathdata.type === "object" ? "10px 0px 0px 0px" : 0
|
||||||
const boxPadding = 0
|
const boxPadding = 0
|
||||||
const namesplit = pathdata.name.split(".")
|
const namesplit = pathdata.name.split(".")
|
||||||
const newname = namesplit[namesplit.length-1]
|
const newname = namesplit[namesplit.length - 1]
|
||||||
return (
|
return (
|
||||||
<MenuItem
|
<MenuItem
|
||||||
key={pathdata.name}
|
key={pathdata.name}
|
||||||
@@ -4154,7 +4232,7 @@ const ParsedAction = (props) => {
|
|||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
{icon} {newname}
|
{icon} {newname}
|
||||||
{pathdata.type === "list" ? <SquareFootIcon style={{marginleft: 10, }} onClick={(e) => {
|
{pathdata.type === "list" ? <SquareFootIcon style={{ marginleft: 10, }} onClick={(e) => {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
|
|
||||||
@@ -4163,7 +4241,7 @@ const ParsedAction = (props) => {
|
|||||||
// Removing .list from autocomplete
|
// Removing .list from autocomplete
|
||||||
var newname = pathdata.name
|
var newname = pathdata.name
|
||||||
if (newname.length > 5) {
|
if (newname.length > 5) {
|
||||||
newname = newname.slice(0, newname.length-5)
|
newname = newname.slice(0, newname.length - 5)
|
||||||
}
|
}
|
||||||
|
|
||||||
//selectedActionParameters[count].value += `{{ $${innerdata.name}.${newname} | size }}`
|
//selectedActionParameters[count].value += `{{ $${innerdata.name}.${newname} | size }}`
|
||||||
@@ -4222,17 +4300,32 @@ const ParsedAction = (props) => {
|
|||||||
data.variant = "STATIC_VALUE"
|
data.variant = "STATIC_VALUE"
|
||||||
}
|
}
|
||||||
|
|
||||||
const isFirstOptional = optionalFound === false && data.configuration === false && data.required === false ? true : false
|
var isFirstOptional = optionalFound === false && data.configuration === false && data.required === false ? true : false
|
||||||
if (optionalFound === false && data.configuration === false && data.required === false) {
|
if (optionalFound === false && data.configuration === false && data.required === false) {
|
||||||
optionalFound = true
|
optionalFound = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isFirstOptional) {
|
||||||
|
// Check if any required fields are found
|
||||||
|
var foundRequired = false
|
||||||
|
for (var key in selectedActionParameters) {
|
||||||
|
if (selectedActionParameters[key]?.required === true) {
|
||||||
|
foundRequired = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!foundRequired) {
|
||||||
|
isFirstOptional = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div key={data.name} style={{marginTop: isFirstOptional ? 55 : 5, }}>
|
<div key={data.name} style={{ marginTop: isFirstOptional ? 55 : 5, }}>
|
||||||
{isFirstOptional ? <Divider style={{backgroundColor: "rgba(255,255,255,0.1)", marginBottom: 20, }} /> : null}
|
{isFirstOptional ? <Divider style={{ backgroundColor: "rgba(255,255,255,0.1)", marginBottom: 20, }} /> : null}
|
||||||
{showButtonField === true ? hideBodyButtonValue : null}
|
{showButtonField === true ? hideBodyButtonValue : null}
|
||||||
<div
|
<div
|
||||||
style={{ marginTop: 20, marginBottom: 0, display: "flex" }}
|
style={{ marginTop: 18, marginBottom: 0, display: "flex" }}
|
||||||
>
|
>
|
||||||
{data.configuration === true ? (
|
{data.configuration === true ? (
|
||||||
<Tooltip
|
<Tooltip
|
||||||
@@ -4263,9 +4356,9 @@ const ParsedAction = (props) => {
|
|||||||
>
|
>
|
||||||
<PriorityHighIcon
|
<PriorityHighIcon
|
||||||
style={{
|
style={{
|
||||||
color: "rgba(255,255,255,0.5)" ,
|
color: "rgba(255,255,255,0.5)",
|
||||||
marginRight: 0,
|
marginRight: 0,
|
||||||
}}/>
|
}} />
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
|
||||||
:
|
:
|
||||||
@@ -4275,9 +4368,9 @@ const ParsedAction = (props) => {
|
|||||||
placement="top"
|
placement="top"
|
||||||
>
|
>
|
||||||
<AutoFixHighIcon style={{
|
<AutoFixHighIcon style={{
|
||||||
color: "rgba(255,255,255,0.7)" ,
|
color: "rgba(255,255,255,0.7)",
|
||||||
marginRight: 10,
|
marginRight: 10,
|
||||||
}}/>
|
}} />
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
:
|
:
|
||||||
null}
|
null}
|
||||||
@@ -4288,11 +4381,11 @@ const ParsedAction = (props) => {
|
|||||||
title={"Explore your keys in Datastore"}
|
title={"Explore your keys in Datastore"}
|
||||||
placement="top"
|
placement="top"
|
||||||
>
|
>
|
||||||
<a href="/admin?tab=datastore" target="_blank" style={{textDecoration: "none"}}>
|
<a href="/admin?tab=datastore" target="_blank" style={{ textDecoration: "none" }}>
|
||||||
<StorageIcon style={{
|
<StorageIcon style={{
|
||||||
color: "#FF8544",
|
color: "#FF8544",
|
||||||
marginRight: 10,
|
marginRight: 10,
|
||||||
}}/>
|
}} />
|
||||||
</a>
|
</a>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
: null}
|
: null}
|
||||||
@@ -4305,7 +4398,7 @@ const ParsedAction = (props) => {
|
|||||||
color: "#C5C5C5",
|
color: "#C5C5C5",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{tmpitem} <span style={{color: theme.palette.main}}>{selectedActionParameters[count].required || selectedActionParameters[count].configuration ? "*" : ""}</span>
|
{tmpitem} <span style={{ color: theme.palette.main }}>{selectedActionParameters[count].required || selectedActionParameters[count].configuration ? "*" : ""}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Tooltip title="Expand editor window" placement="top">
|
<Tooltip title="Expand editor window" placement="top">
|
||||||
@@ -4400,7 +4493,7 @@ const ParsedAction = (props) => {
|
|||||||
console.log("SELECT ONCHANGE DONE")
|
console.log("SELECT ONCHANGE DONE")
|
||||||
|
|
||||||
if (selectedActionParameters[count].value[selectedActionParameters[count].value.length - 1] === ".") {
|
if (selectedActionParameters[count].value[selectedActionParameters[count].value.length - 1] === ".") {
|
||||||
e.target.value.autocomplete = e.target.value.autocomplete.slice(1,e.target.value.autocomplete.length);
|
e.target.value.autocomplete = e.target.value.autocomplete.slice(1, e.target.value.autocomplete.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
selectedActionParameters[count].value += e.target.value.autocomplete;
|
selectedActionParameters[count].value += e.target.value.autocomplete;
|
||||||
@@ -4433,7 +4526,7 @@ const ParsedAction = (props) => {
|
|||||||
color: "white",
|
color: "white",
|
||||||
}}
|
}}
|
||||||
value={data}
|
value={data}
|
||||||
onMouseOver={() => {}}
|
onMouseOver={() => { }}
|
||||||
>
|
>
|
||||||
<Tooltip
|
<Tooltip
|
||||||
color="primary"
|
color="primary"
|
||||||
|
|||||||
@@ -13,8 +13,11 @@ import {
|
|||||||
Card,
|
Card,
|
||||||
Chip,
|
Chip,
|
||||||
Switch,
|
Switch,
|
||||||
Skeleton,
|
Autocomplete,
|
||||||
|
TextField,
|
||||||
|
MenuItem,
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
|
import { makeStyles } from "@mui/styles";
|
||||||
import { Context } from "../context/ContextApi.jsx";
|
import { Context } from "../context/ContextApi.jsx";
|
||||||
|
|
||||||
import { useNavigate, Link } from "react-router-dom";
|
import { useNavigate, Link } from "react-router-dom";
|
||||||
@@ -22,8 +25,15 @@ import Priority from "../components/Priority.jsx";
|
|||||||
import { constrainMatrix } from "reaviz";
|
import { constrainMatrix } from "reaviz";
|
||||||
//import { useAlert
|
//import { useAlert
|
||||||
|
|
||||||
|
|
||||||
|
const useStyles = makeStyles({
|
||||||
|
notchedOutline: {
|
||||||
|
borderColor: "#f85a3e !important",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
const Priorities = memo((props) => {
|
const Priorities = memo((props) => {
|
||||||
const { globalUrl, userdata,clickedFromOrgTab, serverside, billingInfo, stripeKey, checkLogin, setAdminTab, setCurTab, notifications, setNotifications, } = props;
|
const { globalUrl, userdata,clickedFromOrgTab,selectedOrganization, handleEditOrg, serverside, billingInfo, stripeKey, checkLogin, setAdminTab, setCurTab, notifications, setNotifications, } = props;
|
||||||
|
|
||||||
const [showDismissed, setShowDismissed] = React.useState(false);
|
const [showDismissed, setShowDismissed] = React.useState(false);
|
||||||
const [showRead, setShowRead] = React.useState(false);
|
const [showRead, setShowRead] = React.useState(false);
|
||||||
@@ -32,7 +42,21 @@ const Priorities = memo((props) => {
|
|||||||
const [selectedExecutionId, setSelectedExecutionId] = React.useState("NO HIGHLIGHT");
|
const [selectedExecutionId, setSelectedExecutionId] = React.useState("NO HIGHLIGHT");
|
||||||
const [highlightKMS, setHighlightKMS] = React.useState(false)
|
const [highlightKMS, setHighlightKMS] = React.useState(false)
|
||||||
|
|
||||||
|
const [workflows, setWorkflows] = React.useState([])
|
||||||
|
const [openNotification, setOpenNotification] = React.useState(false);
|
||||||
|
const [workflow, setWorkflow] = React.useState({})
|
||||||
|
const [notificationWorkflow, setNotificationWorkflow] = React.useState(
|
||||||
|
selectedOrganization.defaults === undefined
|
||||||
|
? ""
|
||||||
|
: selectedOrganization.defaults.notification_workflow === undefined ||
|
||||||
|
selectedOrganization.defaults.notification_workflow.length === 0
|
||||||
|
? ""
|
||||||
|
: selectedOrganization.defaults.notification_workflow
|
||||||
|
);
|
||||||
|
|
||||||
let navigate = useNavigate();
|
let navigate = useNavigate();
|
||||||
|
const classes = useStyles();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
getFramework()
|
getFramework()
|
||||||
|
|
||||||
@@ -60,6 +84,20 @@ const Priorities = memo((props) => {
|
|||||||
}
|
}
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (selectedOrganization === undefined || selectedOrganization === null || selectedOrganization?.id === undefined || selectedOrganization?.id === null || selectedOrganization?.id.length === 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if(workflows?.length === 0) {
|
||||||
|
getAvailableWorkflows()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (notificationWorkflow !== selectedOrganization?.defaults?.notification_workflow) {
|
||||||
|
setNotificationWorkflow(selectedOrganization?.defaults?.notification_workflow)
|
||||||
|
}
|
||||||
|
}, [selectedOrganization])
|
||||||
|
|
||||||
if (userdata === undefined || userdata === null) {
|
if (userdata === undefined || userdata === null) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -220,11 +258,287 @@ const Priorities = memo((props) => {
|
|||||||
const imagesize = 22
|
const imagesize = 22
|
||||||
const boxColor = "#86c142"
|
const boxColor = "#86c142"
|
||||||
|
|
||||||
|
|
||||||
|
const getAvailableWorkflows = () => {
|
||||||
|
fetch(globalUrl + "/api/v1/workflows", {
|
||||||
|
method: "GET",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
Accept: "application/json",
|
||||||
|
},
|
||||||
|
credentials: "include",
|
||||||
|
})
|
||||||
|
.then((response) => {
|
||||||
|
if (response.status !== 200) {
|
||||||
|
console.log("Status not 200 for workflows :O!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return response.json();
|
||||||
|
})
|
||||||
|
.then((responseJson) => {
|
||||||
|
if (responseJson !== undefined) {
|
||||||
|
|
||||||
|
// Add parent notification workflow if it's a child org
|
||||||
|
// selectedOrganization,
|
||||||
|
if (selectedOrganization.creator_org !== undefined && selectedOrganization.creator_org !== null && selectedOrganization.creator_org.length > 0) {
|
||||||
|
|
||||||
|
// Add to start of the list
|
||||||
|
responseJson.unshift({
|
||||||
|
"name": "Parent-Org's Notification Workflow",
|
||||||
|
"id": "parent",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
setWorkflows(responseJson)
|
||||||
|
|
||||||
|
if (selectedOrganization.defaults !== undefined && selectedOrganization.defaults.notification_workflow !== undefined) {
|
||||||
|
|
||||||
|
const workflow = responseJson.find((workflow) => workflow.id === selectedOrganization.defaults.notification_workflow)
|
||||||
|
if (workflow !== undefined && workflow !== null) {
|
||||||
|
setWorkflow(workflow)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.log("Error getting workflows: " + error);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleWorkflowSelectionUpdate = (e, isUserinput) => {
|
||||||
|
if (e.target.value === undefined || e.target.value === null || e.target.value.id === undefined) {
|
||||||
|
console.log("Returning as there's no id")
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
setOpenNotification(false)
|
||||||
|
setWorkflow(e.target.value)
|
||||||
|
setNotificationWorkflow(e.target.value.id)
|
||||||
|
handleEditOrg(
|
||||||
|
selectedOrganization?.name,
|
||||||
|
selectedOrganization.description,
|
||||||
|
selectedOrganization.id,
|
||||||
|
selectedOrganization.image,
|
||||||
|
{
|
||||||
|
app_download_repo: selectedOrganization?.defaults?.app_download_repo,
|
||||||
|
app_download_branch: selectedOrganization?.defaults?.app_download_branch,
|
||||||
|
workflow_download_repo: selectedOrganization?.defaults?.workflow_download_repo,
|
||||||
|
workflow_download_branch: selectedOrganization?.defaults?.workflow_download_branch,
|
||||||
|
notification_workflow: e.target.value.id,
|
||||||
|
documentation_reference: selectedOrganization?.defaults?.documentation_reference,
|
||||||
|
workflow_upload_repo: selectedOrganization?.defaults?.workflow_upload_repo,
|
||||||
|
workflow_upload_branch: selectedOrganization?.defaults?.workflow_upload_branch,
|
||||||
|
workflow_upload_username: selectedOrganization?.defaults?.workflow_upload_username,
|
||||||
|
workflow_upload_token: selectedOrganization?.defaults?.workflow_upload_token,
|
||||||
|
newsletter: selectedOrganization?.defaults?.newsletter,
|
||||||
|
weekly_recommendations: selectedOrganization?.defaults?.weekly_recommendations,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
sso_entrypoint: selectedOrganization?.sso_config?.sso_entrypoint,
|
||||||
|
sso_certificate: selectedOrganization?.sso_config?.sso_certificate,
|
||||||
|
client_id: selectedOrganization?.sso_config?.client_id,
|
||||||
|
client_secret: selectedOrganization?.sso_config?.client_secret,
|
||||||
|
openid_authorization: selectedOrganization?.sso_config?.openid_authorization,
|
||||||
|
openid_token: selectedOrganization?.sso_config?.openid_token,
|
||||||
|
SSORequired: selectedOrganization?.sso_config?.SSORequired,
|
||||||
|
auto_provision: selectedOrganization?.sso_config?.auto_provision,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{width: "100%", height: "100%", boxSizing: 'border-box', transition: 'width 0.3s ease', padding: clickedFromOrgTab ? "27px 10px 19px 27px":null, height: clickedFromOrgTab ? "auto":null, minHeight: 843, backgroundColor: clickedFromOrgTab ? '#212121':null, borderRadius: clickedFromOrgTab ? '16px':null, }}>
|
<div style={{width: "100%", height: "100%", boxSizing: 'border-box', transition: 'width 0.3s ease', padding: clickedFromOrgTab ? "27px 10px 19px 27px":null, height: clickedFromOrgTab ? "auto":null, minHeight: 843, backgroundColor: clickedFromOrgTab ? '#212121':null, borderRadius: clickedFromOrgTab ? '16px':null, }}>
|
||||||
<div style={{ maxHeight: 1700, overflowY: "auto", width: '100%', scrollbarColor: '#494949 transparent', scrollbarWidth: 'thin'}}>
|
<div style={{ maxHeight: 1700, overflowY: "auto", width: '100%', scrollbarColor: '#494949 transparent', scrollbarWidth: 'thin'}}>
|
||||||
<div style={{maxWidth: "calc(100% - 20px)"}}>
|
<div style={{maxWidth: "calc(100% - 20px)"}}>
|
||||||
<Typography style={{ fontSize: 24, fontWeight: 'bold', display: clickedFromOrgTab?null:"inline", marginBottom: clickedFromOrgTab? 8:null, color: clickedFromOrgTab?"#ffffff":null }}>Notifications ({
|
<Typography variant="h5" style={{ color: "rgba(241, 241, 241, 1)", fontSize: 24, fontWeight: 600, textAlign: "left" }}>
|
||||||
|
Notification Workflow
|
||||||
|
</Typography>
|
||||||
|
<Typography style={{ color: "rgba(158, 158, 158, 1)", fontSize: 16, fontWeight: 400, marginTop: 5, }}>
|
||||||
|
The notification workflow triggers when an error occurs in one of your workflows. Each individual one will only start a workflow once every 2 minutes. <b>You can point child org notifications into the parent org notification by choosing it in the list.</b>
|
||||||
|
</Typography>
|
||||||
|
<div style={{ display: "flex", flexDirection: "row", alignItems: "center", }}>
|
||||||
|
|
||||||
|
{workflows !== undefined && workflows !== null && workflows.length > 0 ?
|
||||||
|
<Autocomplete
|
||||||
|
id="notification_workflow_search"
|
||||||
|
autoHighlight
|
||||||
|
open={openNotification}
|
||||||
|
onOpen={() => {
|
||||||
|
setOpenNotification(true);
|
||||||
|
}}
|
||||||
|
onClose={() => {
|
||||||
|
setOpenNotification(false);
|
||||||
|
}}
|
||||||
|
freeSolo
|
||||||
|
//autoSelect
|
||||||
|
value={workflows?.find(w => w.id === notificationWorkflow) || null}
|
||||||
|
classes={{ inputRoot: classes.inputRoot }}
|
||||||
|
ListboxProps={{
|
||||||
|
style: {
|
||||||
|
backgroundColor: "#212121",
|
||||||
|
color: "white",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
getOptionLabel={(option) => {
|
||||||
|
if (
|
||||||
|
option === undefined ||
|
||||||
|
option === null ||
|
||||||
|
option.name === undefined ||
|
||||||
|
option.name === null
|
||||||
|
) {
|
||||||
|
return "No Workflow Selected";
|
||||||
|
}
|
||||||
|
|
||||||
|
const newname = (
|
||||||
|
option.name.charAt(0).toUpperCase() + option.name.substring(1)
|
||||||
|
).replaceAll("_", " ");
|
||||||
|
return newname;
|
||||||
|
}}
|
||||||
|
options={workflows}
|
||||||
|
fullWidth
|
||||||
|
style={{
|
||||||
|
backgroundColor: "#212121",
|
||||||
|
borderRadius: theme.palette?.borderRadius,
|
||||||
|
height: 35,
|
||||||
|
marginBottom: 40,
|
||||||
|
}}
|
||||||
|
onChange={(event, newValue) => {
|
||||||
|
console.log("Found value: ", newValue)
|
||||||
|
|
||||||
|
var parsedinput = { target: { value: newValue } }
|
||||||
|
|
||||||
|
// For variables
|
||||||
|
if (typeof newValue === 'string' && newValue.startsWith("$")) {
|
||||||
|
parsedinput = {
|
||||||
|
target: {
|
||||||
|
value: {
|
||||||
|
"name": newValue,
|
||||||
|
"id": newValue,
|
||||||
|
"actions": [],
|
||||||
|
"triggers": [],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handleWorkflowSelectionUpdate(parsedinput)
|
||||||
|
}}
|
||||||
|
renderOption={(props, data, state) => {
|
||||||
|
if (data.id === workflow.id) {
|
||||||
|
data = workflow;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Tooltip arrow placement="right" title={
|
||||||
|
<span style={{}}>
|
||||||
|
{data.image !== undefined && data.image !== null && data.image.length > 0 ?
|
||||||
|
<img src={data.image} alt={data.name} style={{ backgroundColor: theme.palette.surfaceColor, maxHeight: 200, minHeigth: 200, borderRadius: theme.palette?.borderRadius, }} />
|
||||||
|
: null}
|
||||||
|
<Typography>
|
||||||
|
Choose {data.name}
|
||||||
|
</Typography>
|
||||||
|
</span>
|
||||||
|
} placement="bottom">
|
||||||
|
<MenuItem
|
||||||
|
{...props}
|
||||||
|
style={{
|
||||||
|
// backgroundColor: theme.palette.inputColor,
|
||||||
|
color: data.id === workflow.id ? "red" : "white",
|
||||||
|
borderBottom: data.id === "parent" ? "2px solid rgba(255,255,255,0.5)" : null
|
||||||
|
}}
|
||||||
|
value={data}
|
||||||
|
onClick={(e) => {
|
||||||
|
props.onMouseDown?.(null);
|
||||||
|
var parsedinput = { target: { value: data } }
|
||||||
|
handleWorkflowSelectionUpdate(parsedinput)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{data.name}
|
||||||
|
</MenuItem>
|
||||||
|
</Tooltip>
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
renderInput={(params) => {
|
||||||
|
return (
|
||||||
|
<TextField
|
||||||
|
{...params}
|
||||||
|
style={{
|
||||||
|
backgroundColor: "rgba(33, 33, 33, 1)",
|
||||||
|
borderRadius: 4,
|
||||||
|
height: 35,
|
||||||
|
fontSize: 16,
|
||||||
|
marginTop: "16px"
|
||||||
|
}}
|
||||||
|
InputProps={{
|
||||||
|
...params.InputProps,
|
||||||
|
style: {
|
||||||
|
height: 35,
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
padding: "0px 8px",
|
||||||
|
fontSize: 16,
|
||||||
|
borderRadius: 4,
|
||||||
|
},
|
||||||
|
inputProps: {
|
||||||
|
...params.inputProps,
|
||||||
|
style: {
|
||||||
|
height: "100%",
|
||||||
|
boxSizing: "border-box",
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
// label="Find a notification workflow"
|
||||||
|
variant="outlined"
|
||||||
|
placeholder="Select a notification workflow"
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
:
|
||||||
|
<TextField
|
||||||
|
required
|
||||||
|
InputProps={{
|
||||||
|
style: {
|
||||||
|
height: 35,
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
padding: "0px 8px",
|
||||||
|
fontSize: 16,
|
||||||
|
borderRadius: 4,
|
||||||
|
},
|
||||||
|
inputProps: {
|
||||||
|
style: {
|
||||||
|
height: "100%",
|
||||||
|
boxSizing: "border-box",
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
style={{
|
||||||
|
backgroundColor: "rgba(33, 33, 33, 1)",
|
||||||
|
borderRadius: 4,
|
||||||
|
height: 35,
|
||||||
|
fontSize: 16,
|
||||||
|
marginBottom: 30
|
||||||
|
}}
|
||||||
|
fullWidth={true}
|
||||||
|
type="name"
|
||||||
|
id="outlined-with-placeholder"
|
||||||
|
margin="normal"
|
||||||
|
variant="outlined"
|
||||||
|
placeholder="ID of the workflow to receive notifications"
|
||||||
|
value={notificationWorkflow}
|
||||||
|
onChange={(e) => {
|
||||||
|
setNotificationWorkflow(e.target.value);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
{/* <div style={{ minWidth: 150, maxWidth: 150, marginTop: 5, marginLeft: 10, }}>
|
||||||
|
{orgSaveButton}
|
||||||
|
</div> */}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Typography style={{marginTop: 50, fontSize: 24, fontWeight: 'bold', display: clickedFromOrgTab?null:"inline", marginBottom: clickedFromOrgTab? 8:null, color: clickedFromOrgTab?"#ffffff":null }}>Notifications ({
|
||||||
notifications?.filter((notification) => showRead === true || notification.read === false).length
|
notifications?.filter((notification) => showRead === true || notification.read === false).length
|
||||||
})</Typography>
|
})</Typography>
|
||||||
|
|
||||||
@@ -261,10 +575,12 @@ const Priorities = memo((props) => {
|
|||||||
</Button>
|
</Button>
|
||||||
) : null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<NotificationComponent notifications={notifications} showRead={showRead} selectedExecutionId={selectedExecutionId} selectedWorkflow={selectedWorkflow} highlightKMS={highlightKMS} userdata={userdata} imagesize={imagesize} boxColor={boxColor} clickedFromOrgTab={clickedFromOrgTab} notificationWidth={notificationWidth} dismissNotification={dismissNotification}/>
|
<NotificationComponent notifications={notifications} showRead={showRead} selectedExecutionId={selectedExecutionId} selectedWorkflow={selectedWorkflow} highlightKMS={highlightKMS} userdata={userdata} imagesize={imagesize} boxColor={boxColor} clickedFromOrgTab={clickedFromOrgTab} notificationWidth={notificationWidth} dismissNotification={dismissNotification}/>
|
||||||
|
|
||||||
{clickedFromOrgTab? null : <Divider style={{marginTop: 50, marginBottom: 50, }} />}
|
{clickedFromOrgTab? null : <Divider style={{marginTop: 50, marginBottom: 50, }} />}
|
||||||
<h2 style={{ display: clickedFromOrgTab ? null:"inline", marginBottom: clickedFromOrgTab ? 8:null, marginTop: clickedFromOrgTab ? 30 :null, color: clickedFromOrgTab ? "#ffffff" : null }}>Suggestions</h2>
|
|
||||||
|
<h2 style={{ display: clickedFromOrgTab ? null:"inline", marginBottom: clickedFromOrgTab ? 8:null, marginTop: clickedFromOrgTab ? 60 : null, color: clickedFromOrgTab ? "#ffffff" : null }}>Suggestions</h2>
|
||||||
<span style={{ fontSize: 16, color: clickedFromOrgTab ?"#9E9E9E":null,marginLeft: clickedFromOrgTab ?null:25, }}>
|
<span style={{ fontSize: 16, color: clickedFromOrgTab ?"#9E9E9E":null,marginLeft: clickedFromOrgTab ?null:25, }}>
|
||||||
Suggestions are tasks identified by Shuffle to help you discover ways to protect your and customers' company. <br/>These range from simple configurations in Shuffle to Usecases you may have missed.
|
Suggestions are tasks identified by Shuffle to help you discover ways to protect your and customers' company. <br/>These range from simple configurations in Shuffle to Usecases you may have missed.
|
||||||
<a
|
<a
|
||||||
|
|||||||
@@ -90,8 +90,8 @@ const pythonFilters = [
|
|||||||
{ "name": "Use files", "value": `# Create a sample file\nfiles = [{\n \"name\": \"test.txt\",\n \"data\": \"Testdata\"\n}]\nret = self.set_files(files)\n\n# Get the content of the file from Shuffle storage\n# Originally a byte string in the \"data\" key\nfile_content = (self.get_file(ret[0])[\"data\"]).decode()\nprint(file_content)`, "example": `` },
|
{ "name": "Use files", "value": `# Create a sample file\nfiles = [{\n \"name\": \"test.txt\",\n \"data\": \"Testdata\"\n}]\nret = self.set_files(files)\n\n# Get the content of the file from Shuffle storage\n# Originally a byte string in the \"data\" key\nfile_content = (self.get_file(ret[0])[\"data\"]).decode()\nprint(file_content)`, "example": `` },
|
||||||
|
|
||||||
{ "name": "Use datastore", "value": `key = \"testkey\"\nvalue = \"The value of the testkey\"\n\nself.set_cache(key, value)\n\n# Print the details of the key after it's been updated\n# To get the value, use self.get_cache(key)[\"value\"]\nprint(self.get_cache(key))`, "example": `` },
|
{ "name": "Use datastore", "value": `key = \"testkey\"\nvalue = \"The value of the testkey\"\n\nself.set_cache(key, value)\n\n# Print the details of the key after it's been updated\n# To get the value, use self.get_cache(key)[\"value\"]\nprint(self.get_cache(key))`, "example": `` },
|
||||||
{ "name": "Run an App Action", "value": `response = self.run_app(app_id="app", action="action_name", auth="authentication_id", params={})\nprint(response)`, "example": ``, "disabled": true, },
|
{ "name": "Run an App Action", "value": `response = shuffle.run_app(app_id="app", action="action_name", auth="authentication_id", params={})\nprint(response)`, "example": ``, "disabled": true, },
|
||||||
{ "name": "Run a Singul AI Action", "value": `response = self.create_ticket(app="jira/iris/ticketingsystem", fields={"title": "Test ticket!"})\nprint(response)`, "example": ``, "disabled": true, },
|
{ "name": "Run a Singul AI Action", "value": `response = singul.create_ticket(app="jira/iris/ticketingsystem", fields={"title": "Test ticket!"})\nprint(response)`, "example": ``, "disabled": true, },
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -1416,7 +1416,7 @@ const CodeEditor = (props) => {
|
|||||||
return (
|
return (
|
||||||
<MenuItem key={index} onClick={() => {
|
<MenuItem key={index} onClick={() => {
|
||||||
if (item.disabled) {
|
if (item.disabled) {
|
||||||
toast.error("This feature may not work in your environment yet, and is awaiting updates to the Shuffle python execution environment.", { autoClose: 10000 })
|
toast.error("This feature may not work in your environment until you update your Shuffle Tools app.", { autoClose: 10000 })
|
||||||
}
|
}
|
||||||
|
|
||||||
if (selectedAction.name !== "execute_python") {
|
if (selectedAction.name !== "execute_python") {
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import {
|
|||||||
Close as CloseIcon,
|
Close as CloseIcon,
|
||||||
East as EastIcon,
|
East as EastIcon,
|
||||||
Interests as InterestsIcon,
|
Interests as InterestsIcon,
|
||||||
|
OpenInNew as OpenInNewIcon,
|
||||||
} from '@mui/icons-material';
|
} from '@mui/icons-material';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@@ -35,7 +36,8 @@ import {
|
|||||||
grey,
|
grey,
|
||||||
} from "../views/AngularWorkflow.jsx"
|
} from "../views/AngularWorkflow.jsx"
|
||||||
|
|
||||||
import WorkflowTemplatePopup2 from "./WorkflowTemplatePopup.jsx";
|
//import WorkflowTemplatePopup2 from "./WorkflowTemplatePopup2.jsx";
|
||||||
|
import WorkflowTemplatePopup2 from "./WorkflowTemplatePopup2.jsx";
|
||||||
import ConfigureWorkflow from "../components/ConfigureWorkflow.jsx";
|
import ConfigureWorkflow from "../components/ConfigureWorkflow.jsx";
|
||||||
import WorkflowValidationTimeline from "../components/WorkflowValidationTimeline.jsx";
|
import WorkflowValidationTimeline from "../components/WorkflowValidationTimeline.jsx";
|
||||||
import FixWorkflowValidationErrors from "../components/FixWorkflowValidationErrors.jsx";
|
import FixWorkflowValidationErrors from "../components/FixWorkflowValidationErrors.jsx";
|
||||||
@@ -47,9 +49,11 @@ const WorkflowTemplatePopup = (props) => {
|
|||||||
isModalOpenDefault,
|
isModalOpenDefault,
|
||||||
setIsClicked,
|
setIsClicked,
|
||||||
inputWorkflowId,
|
inputWorkflowId,
|
||||||
|
inputWorkflow,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const [isActive, setIsActive] = useState(workflowBuilt === true);
|
const [isActive, setIsActive] = useState(workflowBuilt === true || (workflowBuilt !== undefined && workflowBuilt !== null && workflowBuilt?.length > 0) || (inputWorkflow !== undefined && inputWorkflow !== null && inputWorkflow.id !== undefined && inputWorkflow.id !== null && inputWorkflow.id !== "") ? true : false)
|
||||||
|
|
||||||
const [isHovered, setIsHovered] = useState(false);
|
const [isHovered, setIsHovered] = useState(false);
|
||||||
const [modalOpen, setModalOpen] = useState(isModalOpenDefault === true ? true : false)
|
const [modalOpen, setModalOpen] = useState(isModalOpenDefault === true ? true : false)
|
||||||
const [errorMessage, setErrorMessage] = useState("");
|
const [errorMessage, setErrorMessage] = useState("");
|
||||||
@@ -65,7 +69,7 @@ const WorkflowTemplatePopup = (props) => {
|
|||||||
const [showTryitOut, setShowTryitout] = React.useState(showTryit === true ? true : false)
|
const [showTryitOut, setShowTryitout] = React.useState(showTryit === true ? true : false)
|
||||||
|
|
||||||
const [loadingWorkflow, setLoadingWorkflow] = React.useState(false)
|
const [loadingWorkflow, setLoadingWorkflow] = React.useState(false)
|
||||||
const [workflow, setWorkflow] = useState({});
|
const [workflow, setWorkflow] = useState(inputWorkflow !== undefined && inputWorkflow !== null && inputWorkflow.id !== undefined && inputWorkflow.id !== null && inputWorkflow.id !== "" ? inputWorkflow : {})
|
||||||
const [_, setUpdate] = useState(0)
|
const [_, setUpdate] = useState(0)
|
||||||
|
|
||||||
const fetchWorkflow = (id) => {
|
const fetchWorkflow = (id) => {
|
||||||
@@ -455,7 +459,7 @@ const WorkflowTemplatePopup = (props) => {
|
|||||||
//console.log("Error in workflow template: ", responseJson.error);
|
//console.log("Error in workflow template: ", responseJson.error);
|
||||||
setRequestSent(false)
|
setRequestSent(false)
|
||||||
|
|
||||||
const defaultMessage = "Error: Failed to generate workflow the workflow - the Shuffle team has been notified. Contact support@shuffler.io if you want manual help building this usecase until the AI system is handled."
|
const defaultMessage = "Error: Failed to generate workflow the workflow - the Shuffle team has been notified. Contact support@shuffler.io if you want manual help building this usecase."
|
||||||
if (responseJson.reason !== undefined && responseJson.reason !== null && responseJson.reason !== "") {
|
if (responseJson.reason !== undefined && responseJson.reason !== null && responseJson.reason !== "") {
|
||||||
setErrorMessage(defaultMessage + "\n\n" + responseJson.reason)
|
setErrorMessage(defaultMessage + "\n\n" + responseJson.reason)
|
||||||
} else {
|
} else {
|
||||||
@@ -535,8 +539,8 @@ const WorkflowTemplatePopup = (props) => {
|
|||||||
style: {
|
style: {
|
||||||
backgroundColor: "black",
|
backgroundColor: "black",
|
||||||
color: "white",
|
color: "white",
|
||||||
minWidth: isHomePage ? null : isMobile ? 300 : 850,
|
minWidth: isHomePage ? null : isMobile ? 300 : 750,
|
||||||
maxWidth: isHomePage ? null : isMobile ? 300 : 850,
|
maxWidth: isHomePage ? null : isMobile ? 300 : 750,
|
||||||
paddingTop: isMobile ? null : 75,
|
paddingTop: isMobile ? null : 75,
|
||||||
itemAlign: "center",
|
itemAlign: "center",
|
||||||
},
|
},
|
||||||
@@ -564,7 +568,7 @@ const WorkflowTemplatePopup = (props) => {
|
|||||||
{title === undefined || title === null || title === "" ? null :
|
{title === undefined || title === null || title === "" ? null :
|
||||||
<span>
|
<span>
|
||||||
<Typography variant="body2" color="textSecondary" style={{marginTop: 25, }}>
|
<Typography variant="body2" color="textSecondary" style={{marginTop: 25, }}>
|
||||||
Selected Workflow:
|
Selected Usecase:
|
||||||
</Typography>
|
</Typography>
|
||||||
<div style={{marginBottom: 0, }} id="workflow-template">
|
<div style={{marginBottom: 0, }} id="workflow-template">
|
||||||
<WorkflowTemplatePopup2
|
<WorkflowTemplatePopup2
|
||||||
@@ -575,9 +579,10 @@ const WorkflowTemplatePopup = (props) => {
|
|||||||
dstapp={dstapp}
|
dstapp={dstapp}
|
||||||
title={title}
|
title={title}
|
||||||
description={description}
|
description={description}
|
||||||
visualOnly={true}
|
|
||||||
|
|
||||||
|
visualOnly={true}
|
||||||
workflowBuilt={workflowBuilt}
|
workflowBuilt={workflowBuilt}
|
||||||
|
inputWorkflow={workflow}
|
||||||
shownColor={shownColor}
|
shownColor={shownColor}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
@@ -585,7 +590,7 @@ const WorkflowTemplatePopup = (props) => {
|
|||||||
</span>
|
</span>
|
||||||
}
|
}
|
||||||
|
|
||||||
<div style={{marginTop: 15, }}>
|
<div style={{marginTop: 0, }}>
|
||||||
{/* Fix the timeline when errors are fixed.. how? */}
|
{/* Fix the timeline when errors are fixed.. how? */}
|
||||||
<WorkflowValidationTimeline
|
<WorkflowValidationTimeline
|
||||||
workflow={workflow}
|
workflow={workflow}
|
||||||
@@ -601,21 +606,23 @@ const WorkflowTemplatePopup = (props) => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{workflowLoading === true ?
|
{workflowLoading === true ?
|
||||||
<div style={{marginTop: 75, textAlign: "center", }}>
|
<div style={{marginTop: 60, textAlign: "center", }}>
|
||||||
<Typography variant="h4"> Generating the Workflow...
|
<Typography variant="h4"> Generating Workflows...
|
||||||
</Typography>
|
</Typography>
|
||||||
<CircularProgress style={{marginLeft: 0, marginTop: 25, }}/>
|
<CircularProgress style={{marginLeft: 0, marginTop: 25, }}/>
|
||||||
</div>
|
</div>
|
||||||
:
|
:
|
||||||
<div>
|
<div>
|
||||||
{usecaseDetails === undefined ? null :
|
{usecaseDetails === undefined || usecaseDetails === null || workflow.id !== undefined ? null :
|
||||||
<Typography variant="h6" style={{marginTop: 75, }}>
|
<Typography variant="body1" style={{marginTop: 60, }} color="textSecondary">
|
||||||
{usecaseDetails?.description}
|
{usecaseDetails?.description}
|
||||||
</Typography>
|
</Typography>
|
||||||
}
|
}
|
||||||
|
{errorMessage !== "" ?
|
||||||
<Typography variant="h6" style={{marginTop: 75, }}>
|
<Typography variant="h6" style={{marginTop: 75, }}>
|
||||||
{errorMessage !== "" ? errorMessage : ""}
|
{errorMessage !== "" ? errorMessage : ""}
|
||||||
</Typography>
|
</Typography>
|
||||||
|
: null}
|
||||||
{showLoginButton ?
|
{showLoginButton ?
|
||||||
<Link to="/register?message=Please login to create workflows&view=usecases"
|
<Link to="/register?message=Please login to create workflows&view=usecases"
|
||||||
style={{
|
style={{
|
||||||
@@ -643,6 +650,7 @@ const WorkflowTemplatePopup = (props) => {
|
|||||||
variant="outlined"
|
variant="outlined"
|
||||||
style={{
|
style={{
|
||||||
textTransform: "none",
|
textTransform: "none",
|
||||||
|
marginTop: 15,
|
||||||
}}
|
}}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
//setWorkflowLoading(true)
|
//setWorkflowLoading(true)
|
||||||
@@ -730,11 +738,11 @@ const WorkflowTemplatePopup = (props) => {
|
|||||||
|
|
||||||
const parsedDescription = description !== undefined && description !== null ? description.replaceAll("_", " ") : ""
|
const parsedDescription = description !== undefined && description !== null ? description.replaceAll("_", " ") : ""
|
||||||
|
|
||||||
const boxHeight = 104
|
const boxHeight = visualOnly ? 75 : 104
|
||||||
const highlightColor = shownColor !== undefined && shownColor !== null && shownColor !== "" ? shownColor : "#f85a3e"
|
const highlightColor = shownColor !== undefined && shownColor !== null && shownColor !== "" ? shownColor : "#f85a3e"
|
||||||
|
|
||||||
var hasInterest = false
|
var hasInterest = false
|
||||||
if (userdata.interests !== undefined && userdata.interests !== null && userdata.interests.length > 0) {
|
if (userdata?.interests !== undefined && userdata?.interests !== null && userdata?.interests?.length > 0) {
|
||||||
const comparisonTitle = title === undefined || title === null ? "" : title.trim().toLowerCase().replaceAll(" ", "_")
|
const comparisonTitle = title === undefined || title === null ? "" : title.trim().toLowerCase().replaceAll(" ", "_")
|
||||||
for (var interestkey in userdata.interests) {
|
for (var interestkey in userdata.interests) {
|
||||||
if (userdata.interests[interestkey].name === undefined || userdata.interests[interestkey].name === null || userdata.interests[interestkey].name === "") {
|
if (userdata.interests[interestkey].name === undefined || userdata.interests[interestkey].name === null || userdata.interests[interestkey].name === "") {
|
||||||
@@ -742,12 +750,12 @@ const WorkflowTemplatePopup = (props) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (modalOpen) {
|
if (modalOpen) {
|
||||||
console.log("COMPARE: ", userdata.interests[interestkey].name.trim().toLowerCase().replaceAll(" ", "_"), comparisonTitle)
|
//console.log("COMPARE: ", userdata.interests[interestkey].name.trim().toLowerCase().replaceAll(" ", "_"), comparisonTitle)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (userdata.interests[interestkey].name.trim().toLowerCase().replaceAll(" ", "_") === comparisonTitle) {
|
if (userdata.interests[interestkey].name.trim().toLowerCase().replaceAll(" ", "_") === comparisonTitle) {
|
||||||
if (modalOpen) {
|
if (modalOpen) {
|
||||||
console.log("FOUND: ", comparisonTitle)
|
//console.log("FOUND: ", comparisonTitle)
|
||||||
}
|
}
|
||||||
|
|
||||||
hasInterest = true
|
hasInterest = true
|
||||||
@@ -791,7 +799,16 @@ const WorkflowTemplatePopup = (props) => {
|
|||||||
}}
|
}}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (visualOnly === true) {
|
if (visualOnly === true) {
|
||||||
console.log("Not showing more than visuals.")
|
console.log("Not showing more than visuals. Workflow built: ", workflowBuilt, workflow)
|
||||||
|
|
||||||
|
if (workflowBuilt !== undefined && workflowBuilt !== null && workflowBuilt?.length > 0) {
|
||||||
|
window.open("/workflows/" + workflowBuilt, "_blank")
|
||||||
|
} else if (workflow.id !== undefined && workflow.id !== null && workflow.id !== "") {
|
||||||
|
window.open("/workflows/" + workflow.id, "_blank")
|
||||||
|
} else {
|
||||||
|
toast("Click 'Try this usecase' to generate workflows for this usecase.")
|
||||||
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -822,7 +839,7 @@ const WorkflowTemplatePopup = (props) => {
|
|||||||
: null}
|
: null}
|
||||||
|
|
||||||
<div style={{ display: "flex", itemAlign: "left", textAlign: "left", }}>
|
<div style={{ display: "flex", itemAlign: "left", textAlign: "left", }}>
|
||||||
<div style={{display: "flex", flex: 1, marginLeft: 25, marginTop: showTryitOut && !isActive ? 14 : 30, }}>
|
<div style={{display: "flex", flex: 1, marginLeft: 25, marginTop: visualOnly ? 18 : showTryitOut && !isActive ? 14 : 30, }}>
|
||||||
<div style={{zIndex: 51}}>
|
<div style={{zIndex: 51}}>
|
||||||
{img1 !== undefined && img1 !== "" && srcapp !== undefined && srcapp !== "" ?
|
{img1 !== undefined && img1 !== "" && srcapp !== undefined && srcapp !== "" ?
|
||||||
<Tooltip title={srcapp.replaceAll(":default", "").replaceAll("_", " ").replaceAll(" API", "")} placement="top">
|
<Tooltip title={srcapp.replaceAll(":default", "").replaceAll("_", " ").replaceAll(" API", "")} placement="top">
|
||||||
@@ -849,7 +866,7 @@ const WorkflowTemplatePopup = (props) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div style={{ marginLeft: 20, overflow: "hidden", maxHeight: 30, marginTop: showTryitOut && !isActive ? 8 : 23, }}>
|
<div style={{ marginLeft: 20, overflow: "hidden", maxHeight: 30, marginTop: visualOnly ? 12 : showTryitOut && !isActive ? 8 : 23, }}>
|
||||||
<Typography variant="body1" style={{ marginTop: parsedDescription.length === 0 ? 10 : 0, fontSize: isMobile ? 13 : 16, fontWeight: isHomePage ? 600 : null, textTransform: 'capitalize', color: isHomePage ? "var(--White-text, #F1F1F1)" : "rgba(241, 241, 241, 1)"}} >
|
<Typography variant="body1" style={{ marginTop: parsedDescription.length === 0 ? 10 : 0, fontSize: isMobile ? 13 : 16, fontWeight: isHomePage ? 600 : null, textTransform: 'capitalize', color: isHomePage ? "var(--White-text, #F1F1F1)" : "rgba(241, 241, 241, 1)"}} >
|
||||||
<b>{parsedTitle}</b>
|
<b>{parsedTitle}</b>
|
||||||
</Typography>
|
</Typography>
|
||||||
@@ -858,13 +875,19 @@ const WorkflowTemplatePopup = (props) => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
|
|
||||||
{isActive === true && errorMessage === "" ?
|
{isActive === true && errorMessage === "" ?
|
||||||
|
visualOnly === true ?
|
||||||
|
<Tooltip title="Open the workflow in a new tab" placement="top">
|
||||||
|
<OpenInNewIcon color="primary" sx={{ borderRadius: 4 }} style={{ position: "absolute", top: 22, right: 20, }} />
|
||||||
|
</Tooltip>
|
||||||
|
:
|
||||||
<Tooltip title="You already have workflows that are based on this usecase" placement="top">
|
<Tooltip title="You already have workflows that are based on this usecase" placement="top">
|
||||||
<CheckIcon color="primary" sx={{ borderRadius: 4 }} style={{ position: "absolute", color: theme.palette.green, top: 10, right: 10, }} />
|
<CheckIcon color="primary" sx={{ borderRadius: 4 }} style={{ position: "absolute", color: theme.palette.green, top: 10, right: 10, }} />
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
: ""}
|
: ""}
|
||||||
|
|
||||||
{!isActive && hasInterest === true ?
|
{!isActive && hasInterest === true && !visualOnly ?
|
||||||
<Tooltip title="Your team has shown interest in this usecase previously." placement="top">
|
<Tooltip title="Your team has shown interest in this usecase previously." placement="top">
|
||||||
<InterestsIcon color="primary" sx={{ borderRadius: 4 }} style={{ position: "absolute", color: "rgba(254, 204, 0, 0.5)", top: 10, right: 10, }} />
|
<InterestsIcon color="primary" sx={{ borderRadius: 4 }} style={{ position: "absolute", color: "rgba(254, 204, 0, 0.5)", top: 10, right: 10, }} />
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
@@ -872,7 +895,7 @@ const WorkflowTemplatePopup = (props) => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
{showTryitOut && !isActive ?
|
{showTryitOut && !isActive && !visualOnly ?
|
||||||
<Fade in={showTryitOut} timeout={300}>
|
<Fade in={showTryitOut} timeout={300}>
|
||||||
<Button
|
<Button
|
||||||
variant="text"
|
variant="text"
|
||||||
|
|||||||
@@ -287,7 +287,7 @@ const WorkflowValidationTimeline = (props) => {
|
|||||||
var scheduleNotStarted = false
|
var scheduleNotStarted = false
|
||||||
|
|
||||||
if (workflow.validation !== undefined && workflow.validation !== null && workflow.validation.validation_ran === false) {
|
if (workflow.validation !== undefined && workflow.validation !== null && workflow.validation.validation_ran === false) {
|
||||||
console.log("Validation didn't run. Why?")
|
console.log("Validation didn't run or get set for workflow. Why?")
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -367,10 +367,13 @@ const WorkflowValidationTimeline = (props) => {
|
|||||||
action.result = foundResult
|
action.result = foundResult
|
||||||
|
|
||||||
action.status = foundResult.status
|
action.status = foundResult.status
|
||||||
|
} else {
|
||||||
|
action.status = "SUCCESS"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const lastitem = index === relevantactions.length - 1
|
const lastitem = index === relevantactions.length - 1
|
||||||
|
|
||||||
if (!lastitem) {
|
if (!lastitem) {
|
||||||
if (action.app_name === "Shuffle Tools") {
|
if (action.app_name === "Shuffle Tools") {
|
||||||
if (action.status === "SUCCESS") {
|
if (action.status === "SUCCESS") {
|
||||||
@@ -386,9 +389,10 @@ const WorkflowValidationTimeline = (props) => {
|
|||||||
nodecolor = grey
|
nodecolor = grey
|
||||||
branchcolor = grey
|
branchcolor = grey
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
nodecolor = green
|
||||||
|
branchcolor = green
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} else if (action.status === "SKIPPED") {
|
} else if (action.status === "SKIPPED") {
|
||||||
branchcolor = grey
|
branchcolor = grey
|
||||||
} else {
|
} else {
|
||||||
@@ -489,7 +493,7 @@ const WorkflowValidationTimeline = (props) => {
|
|||||||
|
|
||||||
if (!showMiddle && relevantactions.length > 2 && index > 0 && index === relevantactions.length - 2) {
|
if (!showMiddle && relevantactions.length > 2 && index > 0 && index === relevantactions.length - 2) {
|
||||||
if (founderror.length > 0) {
|
if (founderror.length > 0) {
|
||||||
middleError += founderror+"\n"
|
middleError += action.label+": "+founderror+"\n\n"
|
||||||
|
|
||||||
middleBranchColor = branchcolor
|
middleBranchColor = branchcolor
|
||||||
}
|
}
|
||||||
@@ -497,11 +501,18 @@ const WorkflowValidationTimeline = (props) => {
|
|||||||
if (index === relevantactions.length-2 && relevantactions.length > 2) {
|
if (index === relevantactions.length-2 && relevantactions.length > 2) {
|
||||||
|
|
||||||
const selectedIcon = middleError.length > 0 ?
|
const selectedIcon = middleError.length > 0 ?
|
||||||
<Tooltip title={
|
<Tooltip
|
||||||
|
title={
|
||||||
<Typography variant="body1" style={{margin: 5, whiteSpace: "pre-line", }}>
|
<Typography variant="body1" style={{margin: 5, whiteSpace: "pre-line", }}>
|
||||||
{middleError}
|
{middleError}
|
||||||
</Typography>
|
</Typography>
|
||||||
}>
|
}
|
||||||
|
inputProps={{
|
||||||
|
paperProps: {
|
||||||
|
backgroundColor: "red",
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
<IconButton style={{width: 30, height: 30, backgroundColor: "rgba(255,255,255,0.0)", borderRadius: 30, marginTop: 2, }}>
|
<IconButton style={{width: 30, height: 30, backgroundColor: "rgba(255,255,255,0.0)", borderRadius: 30, marginTop: 2, }}>
|
||||||
<ErrorOutlineIcon style={{color: "red", }} />
|
<ErrorOutlineIcon style={{color: "red", }} />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
@@ -517,7 +528,7 @@ const WorkflowValidationTimeline = (props) => {
|
|||||||
// Returns for anything non-middle
|
// Returns for anything non-middle
|
||||||
if (relevantactions.length > 2 && index >= 1 && index < relevantactions.length - 2) {
|
if (relevantactions.length > 2 && index >= 1 && index < relevantactions.length - 2) {
|
||||||
if (founderror.length > 0) {
|
if (founderror.length > 0) {
|
||||||
middleError += founderror+"\n"
|
middleError += action.label+": "+founderror+"\n\n"
|
||||||
}
|
}
|
||||||
|
|
||||||
return null
|
return null
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -5435,6 +5435,7 @@ const AppCreator = (defaultprops) => {
|
|||||||
minWidth: 174,
|
minWidth: 174,
|
||||||
minHeight: 174,
|
minHeight: 174,
|
||||||
objectFit: "contain",
|
objectFit: "contain",
|
||||||
|
borderRadius: theme.palette?.borderRadius,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
@@ -5450,6 +5451,7 @@ const AppCreator = (defaultprops) => {
|
|||||||
margin: "auto",
|
margin: "auto",
|
||||||
marginTop: 30,
|
marginTop: 30,
|
||||||
marginLeft: 40,
|
marginLeft: 40,
|
||||||
|
borderRadius: theme.palette?.borderRadius,
|
||||||
}}
|
}}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
upload.click();
|
upload.click();
|
||||||
@@ -5832,6 +5834,7 @@ const AppCreator = (defaultprops) => {
|
|||||||
//setOpenApiModal(true)
|
//setOpenApiModal(true)
|
||||||
toast.info("Action merging & fork management coming soon")
|
toast.info("Action merging & fork management coming soon")
|
||||||
}}
|
}}
|
||||||
|
disabled={true}
|
||||||
style={{marginLeft: 10, }}
|
style={{marginLeft: 10, }}
|
||||||
>
|
>
|
||||||
<CallMergeIcon
|
<CallMergeIcon
|
||||||
@@ -5846,7 +5849,7 @@ const AppCreator = (defaultprops) => {
|
|||||||
href="https://shuffler.io/docs/app_creation#app-creator-instructions"
|
href="https://shuffler.io/docs/app_creation#app-creator-instructions"
|
||||||
style={{ textDecoration: "none", color: "#f85a3e" }}
|
style={{ textDecoration: "none", color: "#f85a3e" }}
|
||||||
>
|
>
|
||||||
Click here to learn more about app creation
|
Click to learn more about app creation
|
||||||
</a>
|
</a>
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
@@ -5940,7 +5943,6 @@ const AppCreator = (defaultprops) => {
|
|||||||
<TextField
|
<TextField
|
||||||
required
|
required
|
||||||
style={{
|
style={{
|
||||||
paddingTop: 5,
|
|
||||||
marginTop: 5,
|
marginTop: 5,
|
||||||
marginRight: 15,
|
marginRight: 15,
|
||||||
backgroundColor: inputColor,
|
backgroundColor: inputColor,
|
||||||
|
|||||||
@@ -1258,7 +1258,6 @@ const Apps = (props) => {
|
|||||||
style={{
|
style={{
|
||||||
width: 150,
|
width: 150,
|
||||||
backgroundColor: theme.palette.surfaceColor,
|
backgroundColor: theme.palette.surfaceColor,
|
||||||
backgroundColor: inputColor,
|
|
||||||
color: "white",
|
color: "white",
|
||||||
height: 35,
|
height: 35,
|
||||||
marginleft: 10,
|
marginleft: 10,
|
||||||
|
|||||||
@@ -1853,6 +1853,7 @@ const Apps2 = (props) => {
|
|||||||
app={selectedApp}
|
app={selectedApp}
|
||||||
userdata={userdata}
|
userdata={userdata}
|
||||||
globalUrl={globalUrl}
|
globalUrl={globalUrl}
|
||||||
|
getApps={getApps}
|
||||||
/>
|
/>
|
||||||
<AppCreationModal
|
<AppCreationModal
|
||||||
open={createAppModalOpen}
|
open={createAppModalOpen}
|
||||||
|
|||||||
@@ -1642,7 +1642,7 @@ const RunWorkflow = (defaultprops) => {
|
|||||||
maxHeight: 500,
|
maxHeight: 500,
|
||||||
position: "absolute",
|
position: "absolute",
|
||||||
left: 150,
|
left: 150,
|
||||||
top: 0,
|
top: 75,
|
||||||
border: "1px solid rgba(255,255,255,0.3)",
|
border: "1px solid rgba(255,255,255,0.3)",
|
||||||
borderRadius: theme.palette?.borderRadius,
|
borderRadius: theme.palette?.borderRadius,
|
||||||
|
|
||||||
|
|||||||
@@ -621,7 +621,7 @@ const UsecaseListComponent = (props) => {
|
|||||||
parsedUsecase.dstapp = newsubcase.dstapp
|
parsedUsecase.dstapp = newsubcase.dstapp
|
||||||
|
|
||||||
|
|
||||||
var workflowBuilt = false
|
var workflowBuilt = ""
|
||||||
const newname = subcase.name.toLowerCase().replaceAll(" ", "_")
|
const newname = subcase.name.toLowerCase().replaceAll(" ", "_")
|
||||||
for (var workflowkey in workflows) {
|
for (var workflowkey in workflows) {
|
||||||
const workflow = workflows[workflowkey]
|
const workflow = workflows[workflowkey]
|
||||||
@@ -635,7 +635,7 @@ const UsecaseListComponent = (props) => {
|
|||||||
|
|
||||||
//console.log("WORKFLOW: ", newname, newusecases)
|
//console.log("WORKFLOW: ", newname, newusecases)
|
||||||
if (newusecases.includes(newname)) {
|
if (newusecases.includes(newname)) {
|
||||||
workflowBuilt = true
|
workflowBuilt = workflow.id
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -676,6 +676,7 @@ const UsecaseListComponent = (props) => {
|
|||||||
showTryit={false}
|
showTryit={false}
|
||||||
shownColor={""}
|
shownColor={""}
|
||||||
workflowBuilt={workflowBuilt}
|
workflowBuilt={workflowBuilt}
|
||||||
|
inputWorkflowId={workflowBuilt}
|
||||||
usecaseDetails={usecaseDetails}
|
usecaseDetails={usecaseDetails}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|||||||
@@ -92,6 +92,7 @@ import {
|
|||||||
ArrowRight as ArrowRightIcon,
|
ArrowRight as ArrowRightIcon,
|
||||||
Visibility as VisibilityIcon,
|
Visibility as VisibilityIcon,
|
||||||
EditNote as EditNoteIcon,
|
EditNote as EditNoteIcon,
|
||||||
|
ErrorOutline as ErrorOutlineIcon,
|
||||||
} from "@mui/icons-material";
|
} from "@mui/icons-material";
|
||||||
|
|
||||||
// Additional Components
|
// Additional Components
|
||||||
@@ -108,6 +109,8 @@ import { InstantSearch, Configure, connectHits, connectSearchBox, connectRefinem
|
|||||||
import { debounce } from "lodash";
|
import { debounce } from "lodash";
|
||||||
import { removeQuery } from "../components/ScrollToTop.jsx";
|
import { removeQuery } from "../components/ScrollToTop.jsx";
|
||||||
|
|
||||||
|
import {green, yellow, red, grey } from "../views/AngularWorkflow.jsx"
|
||||||
|
|
||||||
|
|
||||||
const searchClient = algoliasearch("JNSS5CFDZZ", "db08e40265e2941b9a7d8f644b6e5240");
|
const searchClient = algoliasearch("JNSS5CFDZZ", "db08e40265e2941b9a7d8f644b6e5240");
|
||||||
|
|
||||||
@@ -1114,12 +1117,9 @@ const Workflows2 = (props) => {
|
|||||||
<Button
|
<Button
|
||||||
style={{}}
|
style={{}}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
console.log("Editing: ", editingWorkflow);
|
|
||||||
if (selectedWorkflowId) {
|
if (selectedWorkflowId) {
|
||||||
deleteWorkflow(selectedWorkflowId)
|
deleteWorkflow(selectedWorkflowId)
|
||||||
setTimeout(() => {
|
|
||||||
getAvailableWorkflows();
|
|
||||||
}, 1000);
|
|
||||||
} else if (selectedWorkflowIndexes.length > 0) {
|
} else if (selectedWorkflowIndexes.length > 0) {
|
||||||
// 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.")
|
||||||
@@ -1132,11 +1132,11 @@ const Workflows2 = (props) => {
|
|||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
getAvailableWorkflows()
|
getAvailableWorkflows()
|
||||||
}, 1000);
|
}, 5000)
|
||||||
|
|
||||||
setSelectedWorkflowIndexes([]);
|
setSelectedWorkflowIndexes([]);
|
||||||
}
|
}
|
||||||
setDeleteModalOpen(false);
|
|
||||||
|
setDeleteModalOpen(false)
|
||||||
}}
|
}}
|
||||||
color="primary"
|
color="primary"
|
||||||
>
|
>
|
||||||
@@ -2807,6 +2807,7 @@ const Workflows2 = (props) => {
|
|||||||
{workflowMenuButtons}
|
{workflowMenuButtons}
|
||||||
</div>
|
</div>
|
||||||
) : 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 !== "") && type !== "public" ?
|
{(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 !== "") && type !== "public" ?
|
||||||
<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, }}>
|
||||||
@@ -2821,10 +2822,33 @@ const Workflows2 = (props) => {
|
|||||||
>
|
>
|
||||||
<EditNoteIcon />
|
<EditNoteIcon />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
{workflowMenuButtons}
|
|
||||||
</div>
|
</div>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
: null}
|
: null}
|
||||||
|
|
||||||
|
{(data?.validation?.validation_ran === true && data?.validation?.valid === false && data?.validation?.errors?.length > 0 ) ?
|
||||||
|
<Tooltip title={`Explore more than ${data?.validation?.errors?.length} errors. When the last execution finishes without errors AND notifications stop occuring, this icon disappears.`} placement="top">
|
||||||
|
<div style={{ position: "absolute", top: 45, right: 8, }}>
|
||||||
|
<IconButton
|
||||||
|
aria-label="more"
|
||||||
|
aria-controls="long-menu"
|
||||||
|
aria-haspopup="true"
|
||||||
|
onClick={() => {
|
||||||
|
window.open(`/admin?admin_tab=notifications&workflow_id=${data.id}`, "_blank")
|
||||||
|
}}
|
||||||
|
style={{
|
||||||
|
padding: "0px",
|
||||||
|
color: "#979797",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ErrorOutlineIcon style={{
|
||||||
|
marginRight: 2,
|
||||||
|
}} />
|
||||||
|
</IconButton>
|
||||||
|
</div>
|
||||||
|
</Tooltip>
|
||||||
|
|
||||||
|
: null}
|
||||||
</Grid>
|
</Grid>
|
||||||
</Paper>
|
</Paper>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user