Fixed a bunch of minor issues with notification workflows and the like

This commit is contained in:
Frikky
2023-09-22 01:01:20 +02:00
parent fc9bc33b30
commit ec36639fa7
7 changed files with 227 additions and 46 deletions
+8 -9
View File
@@ -22,8 +22,7 @@ import dateutil
import threading
import concurrent.futures
from io import StringIO as StringBuffer
from io import BytesIO
from io import StringIO as StringBuffer, BytesIO
from liquid import Liquid, defaults
runtime = os.getenv("SHUFFLE_SWARM_CONFIG", "")
@@ -1296,7 +1295,7 @@ class AppBase:
def delete_cache(self, key):
org_id = self.full_execution["workflow"]["execution_org"]["id"]
url = "%s/api/v1/orgs/%s/delete_cache" % (self.url, org_id, key)
url = "%s/api/v1/orgs/%s/delete_cache" % (self.url, org_id)
data = {
"workflow_id": self.full_execution["workflow"]["id"],
@@ -1309,11 +1308,11 @@ class AppBase:
response = requests.post(url, json=data, verify=False)
try:
allvalues = response.json()
return allvalues
return json.dumps(allvalues)
except Exception as e:
self.logger.info("[ERROR} Failed to parse response from delete_cache: %s" % e)
#return response.json()
return {"success": False, "reason": f"Failed to delete cache for key {key}"}
return json.dumps({"success": False, "reason": f"Failed to delete cache for key '{key}'"})
def set_cache(self, key, value):
org_id = self.full_execution["workflow"]["execution_org"]["id"]
@@ -2301,13 +2300,13 @@ class AppBase:
#if len(template) > 100:
# self.logger.info("[DEBUG] Running liquid with data of length %d" % len(template))
#self.logger.info(f"[DEBUG] Data: {template}")
run = Liquid(template, mode="wild", from_file=False, filters=shuffle_filters.filters)
# Can't handle self yet (?)
all_globals = globals()
all_globals["self"] = self
all_globals["self"] = self
run = Liquid(template, mode="wild", from_file=False, filters=shuffle_filters.filters, globals=all_globals)
ret = run.render(**all_globals)
# Add locals that are missing to globals
ret = run.render()
return ret
except jinja2.exceptions.TemplateNotFound as e:
self.logger.info(f"[ERROR] Liquid Template error: {e}")
+1 -1
View File
@@ -1,7 +1,7 @@
urllib3==1.26.5
requests==2.25.1
MarkupSafe==2.0.1
liquidpy==0.7.6
liquidpy==0.8.1
flask[async]==2.0.2
waitress==2.1.0
#flask==1.1.2
+15
View File
@@ -39,6 +39,9 @@ import AlertTemplate from "./components/AlertTemplate";
import { useAlert, positions, Provider } from "react-alert";
import { isMobile } from "react-device-detect";
import { ToastContainer, toast } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';
import Drift from "react-driftjs";
// Production - backend proxy forwarding in nginx
@@ -561,6 +564,18 @@ const App = (message, props) => {
{includedData}
</Provider>
</BrowserRouter>
<ToastContainer
position="bottom-center"
autoClose={5000}
hideProgressBar={false}
newestOnTop={false}
closeOnClick
rtl={false}
pauseOnFocusLoss
draggable
pauseOnHover
theme="dark"
/>
</CookiesProvider>
</ThemeProvider>
);
-1
View File
@@ -38,7 +38,6 @@ const OrgHeader = (props) => {
handleEditOrg,
} = props;
//const alert = useAlert();
const classes = useStyles();
var upload = "";
+201 -33
View File
@@ -1,8 +1,8 @@
import React, { useEffect } from "react";
import { makeStyles } from "@mui/styles";
import { useAlert } from "react-alert";
import theme from '../theme.jsx';
import { toast } from "react-toastify"
import {
FormControl,
@@ -24,6 +24,7 @@ import {
Tab,
Grid,
IconButton,
Autocomplete,
} from "@mui/material";
import {
@@ -48,7 +49,6 @@ const OrgHeaderexpanded = (props) => {
adminTab,
} = props;
const alert = useAlert();
const classes = useStyles();
const defaultBranch = "master";
@@ -155,6 +155,47 @@ const OrgHeaderexpanded = (props) => {
: selectedOrganization.sso_config.openid_token
)
const [workflows, setWorkflows] = React.useState([])
const [workflow, setWorkflow] = React.useState({})
const getAvailableWorkflows = (trigger_index) => {
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) {
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);
})
}
useEffect(() => {
getAvailableWorkflows()
}, [])
const handleEditOrg = (
name,
description,
@@ -188,17 +229,29 @@ const OrgHeaderexpanded = (props) => {
.then((response) =>
response.json().then((responseJson) => {
if (responseJson["success"] === false) {
alert.error("Failed updating org: ", responseJson.reason);
toast("Failed updating org: ", responseJson.reason);
} else {
alert.success("Successfully edited org!");
toast("Successfully edited org!");
}
})
)
.catch((error) => {
alert.error("Err: " + error.toString());
toast("Err: " + error.toString());
});
};
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
}
setWorkflow(e.target.value)
setNotificationWorkflow(e.target.value.id)
toast("Updated notification workflow. Don't forget to save!")
}
const orgSaveButton = (
<Tooltip title="Save any unsaved data" placement="bottom">
<div>
@@ -247,34 +300,149 @@ const OrgHeaderexpanded = (props) => {
<Grid container spacing={3} style={{ textAlign: "left" }}>
<Grid item xs={12} style={{}}>
<span>
<Typography>Notification Workflow ID</Typography>
<TextField
required
style={{
flex: "1",
marginTop: "5px",
marginRight: "15px",
backgroundColor: theme.palette.inputColor,
}}
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);
}}
InputProps={{
classes: {
notchedOutline: classes.notchedOutline,
},
style: {
color: "white",
},
}}
/>
<Typography>Notification Workflow</Typography>
{/*
<Typography variant="body2" color="textSecondary">
Add a Workflow that receives notifications from Shuffle when an error occurs in one of your workflows
</Typography>
*/}
<div style={{display: "flex", flexDirection: "row", alignItems: "center"}}>
{workflows !== undefined && workflows !== null && workflows.length > 0 ?
<Autocomplete
id="notification_workflow_search"
autoHighlight
freeSolo
//autoSelect
value={workflow}
classes={{ inputRoot: classes.inputRoot }}
ListboxProps={{
style: {
backgroundColor: theme.palette.inputColor,
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: theme.palette.inputColor,
height: 50,
borderRadius: theme.palette.borderRadius,
}}
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="left" 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
style={{
backgroundColor: theme.palette.inputColor,
color: data.id === workflow.id ? "red" : "white",
}}
value={data}
onClick={(e) => {
var parsedinput = { target: { value: data } }
handleWorkflowSelectionUpdate(parsedinput)
}}
>
{data.name}
</MenuItem>
</Tooltip>
)
}}
renderInput={(params) => {
return (
<TextField
style={{
backgroundColor: theme.palette.inputColor,
borderRadius: theme.palette.borderRadius,
}}
{...params}
label="Find a notification workflow"
variant="outlined"
/>
);
}}
/>
:
<TextField
required
style={{
flex: "1",
marginTop: "5px",
marginRight: "15px",
backgroundColor: theme.palette.inputColor,
}}
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);
}}
InputProps={{
classes: {
notchedOutline: classes.notchedOutline,
},
style: {
color: "white",
},
}}
/>
}
<div style={{minWidth: 150, maxWidth: 150, marginTop: 5, marginLeft: 10, }}>
{orgSaveButton}
</div>
</div>
</span>
</Grid>
<Grid item xs={12} style={{}}>
+1 -1
View File
@@ -1131,7 +1131,7 @@ const ParsedAction = (props) => {
borderRadius: theme.palette.borderRadius,
}}
onChange={(event, newValue) => {
console.log("SELECT: ", event, newValue)
console.log("SELECT: ", event, newValue)
// Workaround with event lol
//if (newValue !== undefined && newValue !== null) {
// setNewSelectedAction({ target: { value: newValue.name } });
+1 -1
View File
@@ -2718,7 +2718,7 @@ const Apps = (props) => {
</DialogTitle>
<DialogContent style={{ color: "rgba(255,255,255,0.65)" }}>
<Typography variant="body1">
Paste in a URL, and we will make it into an app for you. This may take multiple minutes based on the size of the documentation. {isCloud ? "" : "Uses to Shuffle Cloud (https://shuffler.io) for processing."}
Paste in a URL, and we will make it into an app for you. This may take multiple minutes based on the size of the documentation. <b>{isCloud ? "" : "Uses Shuffle Cloud (https://shuffler.io) for processing (for now)."}</b>
</Typography>
<TextField
style={{ backgroundColor: inputColor }}