More header, notifications & debugger fixes
This commit is contained in:
@@ -294,49 +294,26 @@ const Header = (props) => {
|
|||||||
borderBottom: "1px solid rgba(255,255,255,0.4)",
|
borderBottom: "1px solid rgba(255,255,255,0.4)",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{/*<Typography variant="h6">
|
{data.reference_url !== undefined && data.reference_url !== null && data.reference_url.length > 0 ?
|
||||||
{new Date(data.updated_at).toISOString()}
|
<Link to={data.reference_url} style={{color: "#f86a3e", textDecoration: "none",}}>
|
||||||
</Typography >*/}
|
<Typography variant="body1">
|
||||||
{data.reference_url !== undefined &&
|
{data.title} ({data.amount})
|
||||||
data.reference_url !== null &&
|
</Typography >
|
||||||
data.reference_url.length > 0 ? (
|
|
||||||
<Link
|
|
||||||
to={data.reference_url}
|
|
||||||
style={{ color: "#f86a3e", textDecoration: "none" }}
|
|
||||||
>
|
|
||||||
<Typography variant="body1">{data.title}</Typography>
|
|
||||||
</Link>
|
</Link>
|
||||||
) : (
|
:
|
||||||
<Typography variant="body1" color="textSecondary">
|
<Typography variant="body1" color="textSecondary">
|
||||||
{data.title}
|
{data.title}
|
||||||
</Typography >
|
</Typography >
|
||||||
)}
|
}
|
||||||
|
|
||||||
{data.image !== undefined &&
|
{data.image !== undefined && data.image !== null && data.image.length > 0 ?
|
||||||
data.image !== null &&
|
<img alt={data.title} src={data.image} style={{height: 100, width: 100, }} />
|
||||||
data.image.length > 0 ? (
|
:
|
||||||
<img
|
null
|
||||||
alt={data.title}
|
}
|
||||||
src={data.image}
|
<Typography variant="body2" style={{marginTop: 10, maxHeight: 200, overflowX: "hidden", overflowY: "auto", }}>
|
||||||
style={{ height: 100, width: 100 }}
|
{data.description}
|
||||||
/>
|
</Typography >
|
||||||
) : null}
|
|
||||||
<Typography variant="body2">{data.description}</Typography>
|
|
||||||
{/*data.tags !== undefined && data.tags !== null && data.tags.length > 0 ?
|
|
||||||
data.tags.map((tag, index) => {
|
|
||||||
return (
|
|
||||||
<Chip
|
|
||||||
key={index}
|
|
||||||
style={chipStyle}
|
|
||||||
label={tag}
|
|
||||||
onClick={() => {
|
|
||||||
}}
|
|
||||||
variant="outlined"
|
|
||||||
color="primary"
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
: null */}
|
|
||||||
<div style={{ display: "flex" }}>
|
<div style={{ display: "flex" }}>
|
||||||
{data.read === false ? (
|
{data.read === false ? (
|
||||||
<Button
|
<Button
|
||||||
@@ -429,8 +406,9 @@ const Header = (props) => {
|
|||||||
) : null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
<Typography variant="body2">
|
<Typography variant="body2">
|
||||||
Notifications are made by Shuffle to help you discover issues or
|
Notifications generated made by Shuffle to help you discover issues or
|
||||||
improvements.
|
improvements. <a href="/docs/organizations#notifications" target="_blank" rel="noopener noreferrer" style={{color: "#f86a3e", textDecoration: "none", }}>
|
||||||
|
Learn more</a>
|
||||||
</Typography>
|
</Typography>
|
||||||
</Paper>
|
</Paper>
|
||||||
{notifications.map((data, index) => {
|
{notifications.map((data, index) => {
|
||||||
|
|||||||
@@ -170,6 +170,7 @@ const ParsedAction = (props) => {
|
|||||||
|
|
||||||
setEditorData,
|
setEditorData,
|
||||||
setcodedata,
|
setcodedata,
|
||||||
|
setAiQueryModalOpen,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
@@ -2913,14 +2914,17 @@ const ParsedAction = (props) => {
|
|||||||
}}
|
}}
|
||||||
disabled={autoCompleting}
|
disabled={autoCompleting}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
// aiSubmit(aiMsg, undefined, undefined, newSelectedAction)
|
//if (setAiQueryModalOpen !== undefined) {
|
||||||
|
// setAiQueryModalOpen(true)
|
||||||
|
//} else {
|
||||||
aiSubmit("Fill based on previous values", undefined, undefined, selectedAction)
|
aiSubmit("Fill based on previous values", undefined, undefined, selectedAction)
|
||||||
|
//}
|
||||||
setAutocompleting(true)
|
setAutocompleting(true)
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Tooltip
|
<Tooltip
|
||||||
color="primary"
|
color="primary"
|
||||||
title={"Autocompletes fields. Uses NAME of the action and previous values' results."}
|
title={"Autocomplete fields. Will show a popup so that you can query how you would like to fill it in"}
|
||||||
placement="top"
|
placement="top"
|
||||||
>
|
>
|
||||||
{autoCompleting ?
|
{autoCompleting ?
|
||||||
|
|||||||
@@ -46,11 +46,6 @@ const RuntimeDebugger = (props) => {
|
|||||||
|
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
|
|
||||||
//const [workflowId, setWorkflowId] = useState("");
|
|
||||||
//const [status, setStatus] = useState("FINISHED");
|
|
||||||
//const [endTime, setEndTime] = useState(dayjs().subtract(0, 'day'))
|
|
||||||
//const [startTime, setStartTime] = useState(dayjs().subtract(30, 'day'))
|
|
||||||
|
|
||||||
const [workflowId, setWorkflowId] = useState("")
|
const [workflowId, setWorkflowId] = useState("")
|
||||||
const [status, setStatus] = useState("")
|
const [status, setStatus] = useState("")
|
||||||
const [endTime, setEndTime] = useState("")
|
const [endTime, setEndTime] = useState("")
|
||||||
@@ -75,7 +70,7 @@ const RuntimeDebugger = (props) => {
|
|||||||
|
|
||||||
const submitSearch = (workflowId, status, startTime, endTime, cursor, limit) => {
|
const submitSearch = (workflowId, status, startTime, endTime, cursor, limit) => {
|
||||||
|
|
||||||
setResultRows([])
|
//setResultRows([])
|
||||||
setSearchLoading(true)
|
setSearchLoading(true)
|
||||||
const fetchData = {
|
const fetchData = {
|
||||||
workflow_id: workflowId,
|
workflow_id: workflowId,
|
||||||
@@ -107,22 +102,29 @@ const RuntimeDebugger = (props) => {
|
|||||||
//data.runs[key].endTimestamp = data.runs[key].ended_at.toISOString().slice(0, 19).replace('T', ' ')
|
//data.runs[key].endTimestamp = data.runs[key].ended_at.toISOString().slice(0, 19).replace('T', ' ')
|
||||||
const startTimestamp = new Date(data.runs[key].started_at*1000)
|
const startTimestamp = new Date(data.runs[key].started_at*1000)
|
||||||
data.runs[key].startTimestamp = startTimestamp.toISOString().slice(0, 19).replace('T', ' ')
|
data.runs[key].startTimestamp = startTimestamp.toISOString().slice(0, 19).replace('T', ' ')
|
||||||
|
|
||||||
const endTimestamp = new Date(data.runs[key].completed_at*1000)
|
const endTimestamp = new Date(data.runs[key].completed_at*1000)
|
||||||
data.runs[key].endTimestamp = endTimestamp.toISOString().slice(0, 19).replace('T', ' ')
|
data.runs[key].endTimestamp = endTimestamp.toISOString().slice(0, 19).replace('T', ' ')
|
||||||
|
if (data.runs[key].completed_at === 0 || data.runs[key].completed_at === null) {
|
||||||
|
data.runs[key].endTimestamp = ""
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Add 20 empty rows to the end of the resultRows array
|
// Add 20 empty rows to the end of the resultRows array
|
||||||
// This is to make sure that the scrollbar is always visible
|
// This is to make sure that the scrollbar is always visible
|
||||||
setResultRows(data.runs)
|
setResultRows(data.runs)
|
||||||
|
} else {
|
||||||
|
toast("No results found. Keeping old runs")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
console.error("Search error: ", data.reason)
|
toast("Failed to search for runs. Please try again.")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
setSearchLoading(false)
|
setSearchLoading(false)
|
||||||
console.error("Error:", error);
|
console.error("Error:", error);
|
||||||
|
toast("Failed to search for runs. Please try again (2)")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -315,13 +317,46 @@ const RuntimeDebugger = (props) => {
|
|||||||
)
|
)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{ field: 'startTimestamp', headerName: 'Start time (UTC)', width: 160, },
|
{ field: 'startTimestamp', headerName: 'Start time (UTC)', width: 160,
|
||||||
|
renderCell: (params) => {
|
||||||
|
const hasError = params.row.completed_at-params.row.started_at > 300
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Tooltip title={hasError ? "More than 5 minutes from start to finish" : ""} placement="top">
|
||||||
|
<span style={{cursor: "pointer", backgroundColor: !hasError ? "inherit" : "rgba(244,0,0,0.4)",}} onClick={() => {
|
||||||
|
console.log("Zoom in on end timestamp is this one: ", params.row.endTimestamp)
|
||||||
|
//setEndTimestamp(params.row.endTimestamp)
|
||||||
|
|
||||||
|
// Make a new Date() from params.row.startTimestamp and set it in the endTime
|
||||||
|
const newEndTime = new Date(params.row.startTimestamp)
|
||||||
|
if (newEndTime !== null && newEndTime !== undefined && newEndTime !== "" && newEndTime !== "Invalid Date") {
|
||||||
|
// Translate newEndTime to UTC no matter what timezone we are in. Based it on local()
|
||||||
|
// Plus 1 minute to make sure it comes in
|
||||||
|
setEndTime(dayjs(newEndTime.setMinutes(newEndTime.getMinutes()+1)))
|
||||||
|
|
||||||
|
// Use dayjs to translate it into something useful
|
||||||
|
|
||||||
|
// Remove 5 minutes from it and set startTime
|
||||||
|
//newEndTime.setMinutes(newEndTime.getMinutes()-5)
|
||||||
|
//setStartTime(dayjs(newEndTime))
|
||||||
|
}
|
||||||
|
}}>
|
||||||
|
{params.row.startTimestamp}
|
||||||
|
</span>
|
||||||
|
</Tooltip>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
{ field: 'endTimestamp', headerName: 'End time (UTC)', width: 160, },
|
{ field: 'endTimestamp', headerName: 'End time (UTC)', width: 160, },
|
||||||
{
|
{
|
||||||
field: 'id',
|
field: 'id',
|
||||||
headerName: 'Explore',
|
headerName: 'Explore',
|
||||||
width: 65,
|
width: 65,
|
||||||
renderCell: (params) => (
|
renderCell: (params) => {
|
||||||
|
const parsedResult = params.row.result === null || params.row.result === undefined || params.row.result === "" ? null : params.row.result
|
||||||
|
const hasError = parsedResult !== null && parsedResult !== undefined && parsedResult !== "" ? parsedResult.includes("{%") && parsedResult.includes("%}") : false
|
||||||
|
|
||||||
|
return (
|
||||||
<Tooltip arrow placement="right" title={
|
<Tooltip arrow placement="right" title={
|
||||||
<Typography variant="body2" style={{whiteSpace: "pre-line", }}>
|
<Typography variant="body2" style={{whiteSpace: "pre-line", }}>
|
||||||
{params.row.result !== null && params.row.result !== undefined && params.row.result !== "" ?
|
{params.row.result !== null && params.row.result !== undefined && params.row.result !== "" ?
|
||||||
@@ -331,11 +366,14 @@ const RuntimeDebugger = (props) => {
|
|||||||
}
|
}
|
||||||
</Typography>
|
</Typography>
|
||||||
}>
|
}>
|
||||||
|
<span style={{backgroundColor: !hasError ? "inherit" : "rgba(244,0,0,0.6)", }}>
|
||||||
<Link href={`/workflows/${params.row.workflow.id}?execution_id=${params.row.id}`} target="_blank" rel="noopener noreferrer">
|
<Link href={`/workflows/${params.row.workflow.id}?execution_id=${params.row.id}`} target="_blank" rel="noopener noreferrer">
|
||||||
<OpenInNewIcon fontSize="small" />
|
<OpenInNewIcon fontSize="small" />
|
||||||
</Link>
|
</Link>
|
||||||
|
</span>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
),
|
)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -522,6 +560,7 @@ const RuntimeDebugger = (props) => {
|
|||||||
minWidth: 240,
|
minWidth: 240,
|
||||||
maxWidth: 240,
|
maxWidth: 240,
|
||||||
}}
|
}}
|
||||||
|
ampm={false}
|
||||||
label="Search from"
|
label="Search from"
|
||||||
format="YYYY-MM-DD HH:mm:ss"
|
format="YYYY-MM-DD HH:mm:ss"
|
||||||
value={startTime}
|
value={startTime}
|
||||||
@@ -535,6 +574,7 @@ const RuntimeDebugger = (props) => {
|
|||||||
minWidth: 240,
|
minWidth: 240,
|
||||||
maxWidth: 240,
|
maxWidth: 240,
|
||||||
}}
|
}}
|
||||||
|
ampm={false}
|
||||||
label="Search until"
|
label="Search until"
|
||||||
format="YYYY-MM-DD HH:mm:ss"
|
format="YYYY-MM-DD HH:mm:ss"
|
||||||
value={endTime}
|
value={endTime}
|
||||||
|
|||||||
@@ -550,7 +550,6 @@ const CodeEditor = (props) => {
|
|||||||
var code_lines = localcodedata.split('\n')
|
var code_lines = localcodedata.split('\n')
|
||||||
for (var i = 0; i < code_lines.length; i++){
|
for (var i = 0; i < code_lines.length; i++){
|
||||||
var current_code_line = code_lines[i]
|
var current_code_line = code_lines[i]
|
||||||
console.log("Codeline: ", current_code_line)
|
|
||||||
|
|
||||||
var variable_occurence = current_code_line.match(/[\\]{0,1}[$]{1}([a-zA-Z0-9_-]+\.?){1}([a-zA-Z0-9#_-]+\.?){0,}/g)
|
var variable_occurence = current_code_line.match(/[\\]{0,1}[$]{1}([a-zA-Z0-9_-]+\.?){1}([a-zA-Z0-9#_-]+\.?){0,}/g)
|
||||||
|
|
||||||
@@ -612,8 +611,6 @@ const CodeEditor = (props) => {
|
|||||||
const fixedVariable = fixVariable(variable_occurence[occ])
|
const fixedVariable = fixVariable(variable_occurence[occ])
|
||||||
var correctVariable = availableVariables.includes(fixedVariable)
|
var correctVariable = availableVariables.includes(fixedVariable)
|
||||||
if(!correctVariable) {
|
if(!correctVariable) {
|
||||||
console.log("Line: ", i, "ch: ", dollar_occurence[occ])
|
|
||||||
|
|
||||||
value.markText({line:i, ch:dollar_occurence[occ]}, {line:i, ch:dollar_occurence_len[occ]+dollar_occurence[occ]}, {"css": "background-color: rgb(248, 106, 62, 0.9); padding-top: 2px; padding-bottom: 2px; color: white"})
|
value.markText({line:i, ch:dollar_occurence[occ]}, {line:i, ch:dollar_occurence_len[occ]+dollar_occurence[occ]}, {"css": "background-color: rgb(248, 106, 62, 0.9); padding-top: 2px; padding-bottom: 2px; color: white"})
|
||||||
} else {
|
} else {
|
||||||
value.markText({line:i, ch:dollar_occurence[occ]}, {line:i, ch:dollar_occurence_len[occ]+dollar_occurence[occ]}, {"css": "background-color: #8b8e26; padding-top: 2px; padding-bottom: 2px; color: white"})
|
value.markText({line:i, ch:dollar_occurence[occ]}, {line:i, ch:dollar_occurence_len[occ]+dollar_occurence[occ]}, {"css": "background-color: #8b8e26; padding-top: 2px; padding-bottom: 2px; color: white"})
|
||||||
@@ -664,6 +661,23 @@ const CodeEditor = (props) => {
|
|||||||
setlocalcodedata(updatedCode)
|
setlocalcodedata(updatedCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const fixStringInput = (new_input) => {
|
||||||
|
// Newline fixes
|
||||||
|
new_input = new_input.replace(/\r\n/g, "\\n")
|
||||||
|
new_input = new_input.replace(/\n/g, "\\n")
|
||||||
|
|
||||||
|
// Quote fixes
|
||||||
|
new_input = new_input.replace(/\\"/g, '"')
|
||||||
|
new_input = new_input.replace(/"/g, '\\"')
|
||||||
|
|
||||||
|
new_input = new_input.replace(/\\'/g, "'")
|
||||||
|
new_input = new_input.replace(/'/g, "\\'")
|
||||||
|
|
||||||
|
|
||||||
|
return new_input
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const expectedOutput = (input) => {
|
const expectedOutput = (input) => {
|
||||||
|
|
||||||
//const found = input.match(/[$]{1}([a-zA-Z0-9_-]+\.?){1}([a-zA-Z0-9#_-]+\.?){0,}/g)
|
//const found = input.match(/[$]{1}([a-zA-Z0-9_-]+\.?){1}([a-zA-Z0-9#_-]+\.?){0,}/g)
|
||||||
@@ -687,20 +701,26 @@ const CodeEditor = (props) => {
|
|||||||
|
|
||||||
valuefound = true
|
valuefound = true
|
||||||
|
|
||||||
|
console.log("Here. Checking if we got an example?")
|
||||||
try {
|
try {
|
||||||
if (typeof actionlist[j].example === "object") {
|
if (typeof actionlist[j].example === "object") {
|
||||||
|
|
||||||
input = input.replace(found[i], JSON.stringify(actionlist[j].example), -1);
|
input = input.replace(found[i], JSON.stringify(actionlist[j].example), -1);
|
||||||
|
|
||||||
} else if (actionlist[j].example.trim().startsWith("{") || actionlist[j].example.trim().startsWith("[")) {
|
} else if (actionlist[j].example.trim().startsWith("{") || actionlist[j].example.trim().startsWith("[")) {
|
||||||
input = input.replace(found[i], JSON.stringify(actionlist[j].example), -1);
|
input = input.replace(found[i], JSON.stringify(actionlist[j].example), -1);
|
||||||
} else {
|
} else {
|
||||||
input = input.replace(found[i], actionlist[j].example, -1)
|
console.log("This?")
|
||||||
|
|
||||||
|
const newExample = fixStringInput(actionlist[j].example)
|
||||||
|
input = input.replace(found[i], newExample, -1)
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
input = input.replace(found[i], actionlist[j].example, -1)
|
input = input.replace(found[i], actionlist[j].example, -1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//if (!valuefound) {
|
//if (!valuefound) {
|
||||||
// console.log("Couldn't find value "+fixedVariable)
|
// console.log("Couldn't find value "+fixedVariable)
|
||||||
//}
|
//}
|
||||||
@@ -736,7 +756,10 @@ const CodeEditor = (props) => {
|
|||||||
new_input = JSON.stringify(new_input)
|
new_input = JSON.stringify(new_input)
|
||||||
} else {
|
} else {
|
||||||
if (typeof new_input === "string") {
|
if (typeof new_input === "string") {
|
||||||
new_input = new_input
|
// Check if it contains any newlines, and replace them with raw newlines
|
||||||
|
new_input = fixStringInput(new_input)
|
||||||
|
|
||||||
|
// Replace quotes with nothing
|
||||||
} else {
|
} else {
|
||||||
console.log("NO TYPE? ", typeof new_input)
|
console.log("NO TYPE? ", typeof new_input)
|
||||||
try {
|
try {
|
||||||
@@ -747,7 +770,6 @@ const CodeEditor = (props) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//console.log("FOUND2: ", fixedVariable, actionlist[j].example)
|
|
||||||
input = input.replace(fixedVariable, new_input, -1)
|
input = input.replace(fixedVariable, new_input, -1)
|
||||||
input = input.replace(found[i], new_input, -1)
|
input = input.replace(found[i], new_input, -1)
|
||||||
|
|
||||||
@@ -1430,7 +1452,6 @@ const CodeEditor = (props) => {
|
|||||||
highlight_variables(value)
|
highlight_variables(value)
|
||||||
}}
|
}}
|
||||||
onChange={(value, viewUpdate) => {
|
onChange={(value, viewUpdate) => {
|
||||||
console.log("Value: ", value, viewUpdate)
|
|
||||||
setlocalcodedata(value)
|
setlocalcodedata(value)
|
||||||
expectedOutput(value)
|
expectedOutput(value)
|
||||||
|
|
||||||
|
|||||||
@@ -4,11 +4,10 @@ const data = [
|
|||||||
css: {
|
css: {
|
||||||
label: "data(label)",
|
label: "data(label)",
|
||||||
"text-valign": "center",
|
"text-valign": "center",
|
||||||
"font-family":
|
"font-family": "Segoe UI, Tahoma, Geneva, Verdana, sans-serif, sans-serif",
|
||||||
"Segoe UI, Tahoma, Geneva, Verdana, sans-serif, sans-serif",
|
|
||||||
"font-weight": "lighter",
|
"font-weight": "lighter",
|
||||||
"margin-right": "10px",
|
|
||||||
"font-size": "18px",
|
"font-size": "18px",
|
||||||
|
"margin-right": "10px",
|
||||||
width: "80px",
|
width: "80px",
|
||||||
height: "80px",
|
height: "80px",
|
||||||
color: "white",
|
color: "white",
|
||||||
|
|||||||
@@ -112,6 +112,7 @@ import {
|
|||||||
AutoFixHigh as AutoFixHighIcon,
|
AutoFixHigh as AutoFixHighIcon,
|
||||||
Polyline as PolylineIcon,
|
Polyline as PolylineIcon,
|
||||||
QueryStats as QueryStatsIcon,
|
QueryStats as QueryStatsIcon,
|
||||||
|
AutoAwesome as AutoAwesomeIcon,
|
||||||
} from "@mui/icons-material";
|
} from "@mui/icons-material";
|
||||||
|
|
||||||
|
|
||||||
@@ -438,6 +439,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
|
|
||||||
const [appAuthentication, setAppAuthentication] = React.useState(undefined);
|
const [appAuthentication, setAppAuthentication] = React.useState(undefined);
|
||||||
const [variablesModalOpen, setVariablesModalOpen] = React.useState(false);
|
const [variablesModalOpen, setVariablesModalOpen] = React.useState(false);
|
||||||
|
const [aiQueryModalOpen, setAiQueryModalOpen] = React.useState(false)
|
||||||
const [executionVariablesModalOpen, setExecutionVariablesModalOpen] =
|
const [executionVariablesModalOpen, setExecutionVariablesModalOpen] =
|
||||||
React.useState(false);
|
React.useState(false);
|
||||||
const [authenticationModalOpen, setAuthenticationModalOpen] = React.useState(false);
|
const [authenticationModalOpen, setAuthenticationModalOpen] = React.useState(false);
|
||||||
@@ -592,17 +594,22 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
const [elements, setElements] = useState([]);
|
const [elements, setElements] = useState([]);
|
||||||
const [loopRunning, setLoopRunning] = useState(false)
|
const [loopRunning, setLoopRunning] = useState(false)
|
||||||
|
|
||||||
|
var loopRunning2 = loopRunning
|
||||||
const stop = () => {
|
const stop = () => {
|
||||||
setLoopRunning(false)
|
setLoopRunning(false)
|
||||||
|
loopRunning2 = false
|
||||||
}
|
}
|
||||||
|
|
||||||
const start = () => {
|
const start = () => {
|
||||||
setLoopRunning(true)
|
setLoopRunning(true)
|
||||||
|
loopRunning2 = true
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
//console.log("In useeffect for loopRunning: ", loopRunning)
|
// Current variable + future state controlled
|
||||||
if (loopRunning) {
|
// This is so that the loop can stop itself as well
|
||||||
|
console.log("In useeffect for loopRunning: ", loopRunning, loopRunning2)
|
||||||
|
if (loopRunning && loopRunning2) {
|
||||||
const intervalId = setInterval(() => {
|
const intervalId = setInterval(() => {
|
||||||
if (!loopRunning) {
|
if (!loopRunning) {
|
||||||
clearInterval(intervalId);
|
clearInterval(intervalId);
|
||||||
@@ -983,19 +990,21 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
return response.json();
|
return response.json();
|
||||||
})
|
})
|
||||||
.then((responseJson) => {
|
.then((responseJson) => {
|
||||||
if (responseJson !== undefined && responseJson !== null && responseJson.executions !== undefined && responseJson.executions !== null && responseJson.executions.length > 0) {
|
console.log("GOT A RESPONSE??")
|
||||||
|
if (responseJson !== undefined && responseJson !== null && responseJson.executions !== undefined && responseJson.executions !== null) {
|
||||||
|
|
||||||
// - means it's opposite
|
// - means it's opposite
|
||||||
const newkeys = sortByKey(responseJson.executions, "-started_at");
|
const newkeys = sortByKey(responseJson.executions, "-started_at");
|
||||||
setWorkflowExecutions(newkeys);
|
setWorkflowExecutions(newkeys);
|
||||||
|
|
||||||
const cursearch = typeof window === "undefined" || window.location === undefined ? "" : window.location.search;
|
const cursearch = typeof window === "undefined" || window.location === undefined ? "" : window.location.search;
|
||||||
|
|
||||||
var tmpView = new URLSearchParams(cursearch).get("execution_id");
|
var tmpView = new URLSearchParams(cursearch).get("execution_id");
|
||||||
if (execution_id !== undefined && execution_id !== null && execution_id.length > 0 && (tmpView === undefined || tmpView === null || tmpView.length === 0)) {
|
if (execution_id !== undefined && execution_id !== null && execution_id.length > 0 && (tmpView === undefined || tmpView === null || tmpView.length === 0)) {
|
||||||
tmpView = execution_id;
|
tmpView = execution_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log("EXECUTION ID: ", tmpView)
|
||||||
|
|
||||||
// Compare with currently selected item
|
// Compare with currently selected item
|
||||||
if (tmpView !== undefined && tmpView !== null && tmpView.length > 0) {
|
if (tmpView !== undefined && tmpView !== null && tmpView.length > 0) {
|
||||||
// Don't clean up if it's already open
|
// Don't clean up if it's already open
|
||||||
@@ -1045,6 +1054,20 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
stop()
|
stop()
|
||||||
}, 5000);
|
}, 5000);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const cursearch = typeof window === "undefined" || window.location === undefined ? "" : window.location.search;
|
||||||
|
var tmpView = new URLSearchParams(cursearch).get("execution_id");
|
||||||
|
console.log("Alertnative execution id check: ", tmpView)
|
||||||
|
|
||||||
|
if (tmpView === undefined || tmpView === null || tmpView.length === 0) {
|
||||||
|
const execution_id = tmpView;
|
||||||
|
setExecutionModalView(1);
|
||||||
|
setExecutionRequest({
|
||||||
|
execution_id: execution_id,
|
||||||
|
});
|
||||||
|
|
||||||
|
start()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -1067,8 +1090,14 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
})
|
})
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
if (response.status !== 200) {
|
if (response.status !== 200) {
|
||||||
console.log("Status not 200 for stream results :O!");
|
|
||||||
stop();
|
stop();
|
||||||
|
setExecutionModalView(0);
|
||||||
|
toast("Failed loading the workflow run")
|
||||||
|
console.log("Status not 200 for stream results :O!");
|
||||||
|
|
||||||
|
//const cursearch = typeof window === "undefined" || window.location === undefined ? "" : window.location.search;
|
||||||
|
//const newitem = removeParam("execution_id", cursearch);
|
||||||
|
//navigate(curpath + newitem)
|
||||||
}
|
}
|
||||||
|
|
||||||
return response.json();
|
return response.json();
|
||||||
@@ -1248,6 +1277,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
// Style is in defaultCytoscapeStyle.js
|
// Style is in defaultCytoscapeStyle.js
|
||||||
const handleUpdateResults = (responseJson, executionRequest) => {
|
const handleUpdateResults = (responseJson, executionRequest) => {
|
||||||
if (responseJson === undefined || responseJson === null || responseJson.success === false) {
|
if (responseJson === undefined || responseJson === null || responseJson.success === false) {
|
||||||
|
stop()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
//console.log(responseJson)
|
//console.log(responseJson)
|
||||||
@@ -1263,7 +1293,8 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
//console.log("Updating data!")
|
//console.log("Updating data!")
|
||||||
setExecutionData(responseJson)
|
setExecutionData(responseJson)
|
||||||
} else {
|
} else {
|
||||||
if (responseJson.status === "ABORTED" || responseJson.status === "STOPPED" || responseJson.status === "FAILURE" || responseJson.status === "WAITING") {
|
if (responseJson.status === "ABORTED" || responseJson.status === "STOPPED" || responseJson.status === "FAILURE" || responseJson.status === "WAITING" || responseJson.status === "FINISHED") {
|
||||||
|
console.log("DONE!")
|
||||||
stop()
|
stop()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1321,6 +1352,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var streamDisabled2 = false
|
||||||
const sendStreamRequest = (body) => {
|
const sendStreamRequest = (body) => {
|
||||||
//console.log("Stream not activated yet.")
|
//console.log("Stream not activated yet.")
|
||||||
if (!isCloud) {
|
if (!isCloud) {
|
||||||
@@ -1356,6 +1388,9 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
.then((response) => {
|
.then((response) => {
|
||||||
setSavingState(0);
|
setSavingState(0);
|
||||||
if (response.status !== 200) {
|
if (response.status !== 200) {
|
||||||
|
|
||||||
|
setStreamDisabled(true)
|
||||||
|
streamDisabled2 = true
|
||||||
//console.log("Status not 200 for stream :O!");
|
//console.log("Status not 200 for stream :O!");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1367,6 +1402,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
console.log("Stream send error: ", error.toString())
|
console.log("Stream send error: ", error.toString())
|
||||||
setStreamDisabled(true)
|
setStreamDisabled(true)
|
||||||
|
streamDisabled2 = true
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2537,6 +2573,17 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
try {
|
try {
|
||||||
var chunkJson = JSON.parse(chunk)
|
var chunkJson = JSON.parse(chunk)
|
||||||
|
|
||||||
|
if (chunkJson.success === false) {
|
||||||
|
console.log("Chunk failed: ", chunkJson)
|
||||||
|
|
||||||
|
if (!streamDisabled) {
|
||||||
|
setStreamDisabled(true)
|
||||||
|
streamDisabled2 = true
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (chunkJson.item !== undefined && chunkJson.item !== null && chunkJson.item !== "") {
|
if (chunkJson.item !== undefined && chunkJson.item !== null && chunkJson.item !== "") {
|
||||||
if (chunkJson.item === "node") {
|
if (chunkJson.item === "node") {
|
||||||
if (chunkJson.type === "move") {
|
if (chunkJson.type === "move") {
|
||||||
@@ -2561,6 +2608,13 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log("Chunk JSON error: ", e)
|
console.log("Chunk JSON error: ", e)
|
||||||
|
|
||||||
|
if (!streamDisabled) {
|
||||||
|
setStreamDisabled(true)
|
||||||
|
streamDisabled2 = true
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
//data.push(chunk)
|
//data.push(chunk)
|
||||||
@@ -2619,7 +2673,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
const streamUrl = "https://stream.shuffler.io"
|
const streamUrl = "https://stream.shuffler.io"
|
||||||
const url = `${streamUrl}/api/v1/workflows/${workflowId}/stream`
|
const url = `${streamUrl}/api/v1/workflows/${workflowId}/stream`
|
||||||
while (true) {
|
while (true) {
|
||||||
if (streamDisabled) {
|
if (streamDisabled === true || streamDisabled2 === true) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3021,7 +3075,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
sendStreamRequest({
|
sendStreamRequest({
|
||||||
"item": "node",
|
"item": "node",
|
||||||
"type": "unselect",
|
"type": "unselect",
|
||||||
"userid": userdata.id,
|
"id": workflow.id,
|
||||||
})
|
})
|
||||||
//}, 150)
|
//}, 150)
|
||||||
};
|
};
|
||||||
@@ -4071,7 +4125,6 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
"item": "node",
|
"item": "node",
|
||||||
"type": "select",
|
"type": "select",
|
||||||
"id": data.id,
|
"id": data.id,
|
||||||
"userid": userdata.id,
|
|
||||||
"location": {
|
"location": {
|
||||||
"x": event.target.position("x"),
|
"x": event.target.position("x"),
|
||||||
"y": event.target.position("y"),
|
"y": event.target.position("y"),
|
||||||
@@ -5985,10 +6038,10 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
const xParsed = destinationnodePosition.x - sourcenodePosition.x
|
const xParsed = destinationnodePosition.x - sourcenodePosition.x
|
||||||
const yParsed = destinationnodePosition.y - sourcenodePosition.y
|
const yParsed = destinationnodePosition.y - sourcenodePosition.y
|
||||||
|
|
||||||
const z = Math.sqrt(xParsed * xParsed + yParsed * yParsed);
|
const z = Math.sqrt(xParsed * xParsed + yParsed * yParsed)
|
||||||
const costheta = xParsed / z;
|
const costheta = xParsed / z
|
||||||
const alpha = 0.25;
|
const alpha = 0.3
|
||||||
var controlPointDistance = [-alpha * yParsed * costheta, alpha * yParsed * costheta];
|
var controlPointDistance = [-alpha * yParsed * costheta, alpha * yParsed * costheta]
|
||||||
var controlPointWeight = [alpha, 1 - alpha]
|
var controlPointWeight = [alpha, 1 - alpha]
|
||||||
|
|
||||||
//'control-point-weight': ['0.33', '0.66'],
|
//'control-point-weight': ['0.33', '0.66'],
|
||||||
@@ -6151,8 +6204,18 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
const foundtriggers = inputworkflow.triggers.map((trigger) => {
|
const foundtriggers = inputworkflow.triggers.map((trigger) => {
|
||||||
const node = {};
|
const node = {};
|
||||||
node.position = trigger.position;
|
node.position = trigger.position;
|
||||||
node.data = trigger;
|
|
||||||
|
|
||||||
|
if (trigger.large_image === undefined || trigger.large_image === null || trigger.large_image.length === 0) {
|
||||||
|
|
||||||
|
// Search triggers array for it where the name is matching and set image
|
||||||
|
var foundTrigger = triggers.find((t) => t.name === trigger.name)
|
||||||
|
if (foundTrigger !== undefined && foundTrigger !== null) {
|
||||||
|
console.log("Autofilled missing trigger image")
|
||||||
|
trigger.large_image = foundTrigger.large_image
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
node.data = trigger;
|
||||||
node.data._id = trigger["id"];
|
node.data._id = trigger["id"];
|
||||||
node.data.id = trigger["id"];
|
node.data.id = trigger["id"];
|
||||||
node.data.type = "TRIGGER";
|
node.data.type = "TRIGGER";
|
||||||
@@ -6394,13 +6457,13 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
sendStreamRequest({
|
sendStreamRequest({
|
||||||
"item": "workflow",
|
"item": "workflow",
|
||||||
"type": "enter",
|
"type": "enter",
|
||||||
"userid": userdata.id,
|
"id": workflow.id,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const fetchRecommendations = (inputWorkflow) => {
|
const fetchRecommendations = (inputWorkflow) => {
|
||||||
//console.log("Disabled recommendations")
|
console.log("Disabled recommendations as they were too inaccurate")
|
||||||
//return
|
return
|
||||||
|
|
||||||
const parsedWorkflow = JSON.parse(JSON.stringify(inputWorkflow))
|
const parsedWorkflow = JSON.parse(JSON.stringify(inputWorkflow))
|
||||||
|
|
||||||
@@ -6500,6 +6563,11 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
return response.json();
|
return response.json();
|
||||||
})
|
})
|
||||||
.then((responseJson) => {
|
.then((responseJson) => {
|
||||||
|
if (responseJson === null) {
|
||||||
|
console.log("No revisions found")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if (responseJson.success === false) {
|
if (responseJson.success === false) {
|
||||||
console.log("Error getting workflow revisions: ", responseJson)
|
console.log("Error getting workflow revisions: ", responseJson)
|
||||||
return
|
return
|
||||||
@@ -6553,13 +6621,16 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// App length necessary cus of cy initialization
|
// App length necessary cus of cy initialization
|
||||||
if (elements.length === 0 && workflow.actions !== undefined && !graphSetup && Object.getOwnPropertyNames(workflow).length > 0 && workflowRecommendations !== undefined) {
|
// Not using recommendations, so skipping this for now
|
||||||
|
//if (elements.length === 0 && workflow.actions !== undefined && !graphSetup && Object.getOwnPropertyNames(workflow).length > 0 && workflowRecommendations !== undefined) {
|
||||||
|
if (elements.length === 0 && workflow.actions !== undefined && !graphSetup && Object.getOwnPropertyNames(workflow).length > 0) {
|
||||||
setGraphSetup(true);
|
setGraphSetup(true);
|
||||||
setupGraph(workflow);
|
setupGraph(workflow);
|
||||||
console.log("In graph setup")
|
console.log("In graph setup")
|
||||||
|
|
||||||
// 2nd load - configures cytoscape
|
// 2nd load - configures cytoscape
|
||||||
} else if (!established && cy !== undefined && ((apps !== null && apps !== undefined && apps.length > 0) || workflow.public === true) && Object.getOwnPropertyNames(workflow).length > 0 && appAuthentication !== undefined && workflowRecommendations !== undefined) {
|
//} else if (!established && cy !== undefined && ((apps !== null && apps !== undefined && apps.length > 0) || workflow.public === true) && Object.getOwnPropertyNames(workflow).length > 0 && appAuthentication !== undefined && workflowRecommendations !== undefined) {
|
||||||
|
} else if (!established && cy !== undefined && ((apps !== null && apps !== undefined && apps.length > 0) || workflow.public === true) && Object.getOwnPropertyNames(workflow).length > 0 && appAuthentication !== undefined) {
|
||||||
console.log("In POST graph setup!")
|
console.log("In POST graph setup!")
|
||||||
|
|
||||||
|
|
||||||
@@ -9086,6 +9157,33 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
backgroundColor: theme.palette.inputColor,
|
backgroundColor: theme.palette.inputColor,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const aiQueryModal =
|
||||||
|
<Dialog
|
||||||
|
PaperComponent={PaperComponent}
|
||||||
|
disableEnforceFocus={true}
|
||||||
|
hideBackdrop={true}
|
||||||
|
disableBackdropClick={true}
|
||||||
|
style={{ pointerEvents: "none" }}
|
||||||
|
PaperComponent={PaperComponent}
|
||||||
|
aria-labelledby="draggable-dialog-title"
|
||||||
|
open={aiQueryModalOpen}
|
||||||
|
PaperProps={{
|
||||||
|
style: {
|
||||||
|
pointerEvents: "auto",
|
||||||
|
color: "white",
|
||||||
|
minWidth: isMobile ? "90%" : 800,
|
||||||
|
border: theme.palette.defaultBorder,
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
onClose={() => {
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<DialogTitle id="draggable-dialog-title" style={{ cursor: "move", }}>
|
||||||
|
<span style={{ color: "white" }}>Condition</span>
|
||||||
|
</DialogTitle>
|
||||||
|
</Dialog>
|
||||||
|
|
||||||
|
|
||||||
const conditionsModal = (
|
const conditionsModal = (
|
||||||
<Dialog
|
<Dialog
|
||||||
PaperComponent={PaperComponent}
|
PaperComponent={PaperComponent}
|
||||||
@@ -11745,7 +11843,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
}}
|
}}
|
||||||
onChange={(event, newValue) => {
|
onChange={(event, newValue) => {
|
||||||
// Workaround with event lol
|
// Workaround with event lol
|
||||||
console.log(event, newValue)
|
console.log("CHANGE: ", event, newValue)
|
||||||
if (newValue !== undefined && newValue !== null) {
|
if (newValue !== undefined && newValue !== null) {
|
||||||
var parsedvalue = JSON.parse(JSON.stringify(newValue))
|
var parsedvalue = JSON.parse(JSON.stringify(newValue))
|
||||||
parsedvalue.actions = []
|
parsedvalue.actions = []
|
||||||
@@ -11772,6 +11870,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
>
|
>
|
||||||
<MenuItem
|
<MenuItem
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
console.log("CLICK: ", app)
|
||||||
const newValue = app
|
const newValue = app
|
||||||
|
|
||||||
if (newValue !== undefined && newValue !== null) {
|
if (newValue !== undefined && newValue !== null) {
|
||||||
@@ -13856,6 +13955,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
expansionModalOpen={codeEditorModalOpen}
|
expansionModalOpen={codeEditorModalOpen}
|
||||||
setExpansionModalOpen={setCodeEditorModalOpen}
|
setExpansionModalOpen={setCodeEditorModalOpen}
|
||||||
setEditorData={setEditorData}
|
setEditorData={setEditorData}
|
||||||
|
setAiQueryModalOpen={setAiQueryModalOpen}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
} else if (Object.getOwnPropertyNames(selectedComment).length > 0) {
|
} else if (Object.getOwnPropertyNames(selectedComment).length > 0) {
|
||||||
@@ -14403,6 +14503,13 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
style={{ width: size, height: size }}
|
style={{ width: size, height: size }}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
} else if (execution.execution_source === "ShuffleGPT") {
|
||||||
|
return (
|
||||||
|
<AutoAwesomeIcon
|
||||||
|
color="secondary"
|
||||||
|
style={{paddingTop: 8, paddingLeft: 4, height: 25, width: 25, }}
|
||||||
|
/>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
@@ -15484,6 +15591,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
width: 30,
|
width: 30,
|
||||||
}}
|
}}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
if (cy !== undefined) {
|
||||||
const oldstartnode = cy.getElementById(data.action.id);
|
const oldstartnode = cy.getElementById(data.action.id);
|
||||||
//console.log("FOUND NODe: ", oldstartnode)
|
//console.log("FOUND NODe: ", oldstartnode)
|
||||||
if (oldstartnode !== undefined && oldstartnode !== null) {
|
if (oldstartnode !== undefined && oldstartnode !== null) {
|
||||||
@@ -15497,6 +15605,9 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
//data.action.label = ""
|
//data.action.label = ""
|
||||||
setSelectedResult(data);
|
setSelectedResult(data);
|
||||||
setCodeModalOpen(true);
|
setCodeModalOpen(true);
|
||||||
|
} else {
|
||||||
|
toast("Please wait until the workflow is loaded and try again")
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Tooltip
|
<Tooltip
|
||||||
@@ -17797,6 +17908,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
{newView}
|
{newView}
|
||||||
<VariablesModal variableInfo={variableInfo} setVariableInfo={setVariableInfo} />
|
<VariablesModal variableInfo={variableInfo} setVariableInfo={setVariableInfo} />
|
||||||
<ExecutionVariableModal variableInfo={variableInfo} setVariableInfo={setVariableInfo} />
|
<ExecutionVariableModal variableInfo={variableInfo} setVariableInfo={setVariableInfo} />
|
||||||
|
{aiQueryModal}
|
||||||
{conditionsModal}
|
{conditionsModal}
|
||||||
{authenticationModal}
|
{authenticationModal}
|
||||||
{codePopoutModal}
|
{codePopoutModal}
|
||||||
|
|||||||
Reference in New Issue
Block a user