Fixed response forwarding for OpenAPI apps with all details
This commit is contained in:
+52
-42
@@ -36,6 +36,16 @@ class AppBase:
|
|||||||
self.start_time = int(time.time())
|
self.start_time = int(time.time())
|
||||||
self.result_wrapper_count = 0
|
self.result_wrapper_count = 0
|
||||||
|
|
||||||
|
self.action_result = {
|
||||||
|
"action": self.action,
|
||||||
|
"authorization": self.authorization,
|
||||||
|
"execution_id": self.current_execution_id,
|
||||||
|
"result": f"",
|
||||||
|
"started_at": self.start_time,
|
||||||
|
"status": "",
|
||||||
|
"completed_at": int(time.time()),
|
||||||
|
}
|
||||||
|
|
||||||
if isinstance(self.action, str):
|
if isinstance(self.action, str):
|
||||||
try:
|
try:
|
||||||
self.action = json.loads(self.action)
|
self.action = json.loads(self.action)
|
||||||
@@ -489,7 +499,7 @@ class AppBase:
|
|||||||
#print(f"NEW PARAMS: {new_params}")
|
#print(f"NEW PARAMS: {new_params}")
|
||||||
if len(new_params) == 0:
|
if len(new_params) == 0:
|
||||||
print("[WARNING] SHOULD STOP MULTI-EXECUTION BECAUSE FIELDS AREN'T UNIQUE")
|
print("[WARNING] SHOULD STOP MULTI-EXECUTION BECAUSE FIELDS AREN'T UNIQUE")
|
||||||
action_result = {
|
self.action_result = {
|
||||||
"action": self.action,
|
"action": self.action,
|
||||||
"authorization": self.authorization,
|
"authorization": self.authorization,
|
||||||
"execution_id": self.current_execution_id,
|
"execution_id": self.current_execution_id,
|
||||||
@@ -499,7 +509,7 @@ class AppBase:
|
|||||||
"completed_at": int(time.time()),
|
"completed_at": int(time.time()),
|
||||||
}
|
}
|
||||||
|
|
||||||
self.send_result(action_result, {"Content-Type": "application/json", "Authorization": "Bearer %s" % self.authorization}, "/api/v1/streams")
|
self.send_result(self.action_result, {"Content-Type": "application/json", "Authorization": "Bearer %s" % self.authorization}, "/api/v1/streams")
|
||||||
exit()
|
exit()
|
||||||
#return
|
#return
|
||||||
else:
|
else:
|
||||||
@@ -834,7 +844,7 @@ class AppBase:
|
|||||||
# !!! Let this line stay - its used for some horrible codegeneration / stitching !!! #
|
# !!! Let this line stay - its used for some horrible codegeneration / stitching !!! #
|
||||||
#STARTCOPY
|
#STARTCOPY
|
||||||
stream_path = "/api/v1/streams"
|
stream_path = "/api/v1/streams"
|
||||||
action_result = {
|
self.action_result = {
|
||||||
"action": action,
|
"action": action,
|
||||||
"authorization": self.authorization,
|
"authorization": self.authorization,
|
||||||
"execution_id": self.current_execution_id,
|
"execution_id": self.current_execution_id,
|
||||||
@@ -861,20 +871,20 @@ class AppBase:
|
|||||||
|
|
||||||
if len(self.action) == 0:
|
if len(self.action) == 0:
|
||||||
print("ACTION env not defined")
|
print("ACTION env not defined")
|
||||||
action_result["result"] = "Error in setup ENV: ACTION not defined"
|
self.action_result["result"] = "Error in setup ENV: ACTION not defined"
|
||||||
self.send_result(action_result, headers, stream_path)
|
self.send_result(self.action_result, headers, stream_path)
|
||||||
return
|
return
|
||||||
|
|
||||||
if len(self.authorization) == 0:
|
if len(self.authorization) == 0:
|
||||||
print("AUTHORIZATION env not defined")
|
print("AUTHORIZATION env not defined")
|
||||||
action_result["result"] = "Error in setup ENV: AUTHORIZATION not defined"
|
self.action_result["result"] = "Error in setup ENV: AUTHORIZATION not defined"
|
||||||
self.send_result(action_result, headers, stream_path)
|
self.send_result(self.action_result, headers, stream_path)
|
||||||
return
|
return
|
||||||
|
|
||||||
if len(self.current_execution_id) == 0:
|
if len(self.current_execution_id) == 0:
|
||||||
print("EXECUTIONID env not defined")
|
print("EXECUTIONID env not defined")
|
||||||
action_result["result"] = "Error in setup ENV: EXECUTIONID not defined"
|
self.action_result["result"] = "Error in setup ENV: EXECUTIONID not defined"
|
||||||
self.send_result(action_result, headers, stream_path)
|
self.send_result(self.action_result, headers, stream_path)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
@@ -922,21 +932,21 @@ class AppBase:
|
|||||||
except json.decoder.JSONDecodeError:
|
except json.decoder.JSONDecodeError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
action_result["result"] = "Bad result from backend: %d" % ret.status_code
|
self.action_result["result"] = "Bad result from backend: %d" % ret.status_code
|
||||||
self.send_result(action_result, headers, stream_path)
|
self.send_result(self.action_result, headers, stream_path)
|
||||||
return
|
return
|
||||||
except requests.exceptions.ConnectionError as e:
|
except requests.exceptions.ConnectionError as e:
|
||||||
self.logger.info("Connectionerror: %s" % e)
|
self.logger.info("Connectionerror: %s" % e)
|
||||||
action_result["result"] = "Connection error during startup: %s" % e
|
self.action_result["result"] = "Connection error during startup: %s" % e
|
||||||
self.send_result(action_result, headers, stream_path)
|
self.send_result(self.action_result, headers, stream_path)
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
fullexecution = json.loads(self.full_execution)
|
fullexecution = json.loads(self.full_execution)
|
||||||
except json.decoder.JSONDecodeError as e:
|
except json.decoder.JSONDecodeError as e:
|
||||||
print("Json decode execution error: %s" % e)
|
print("Json decode execution error: %s" % e)
|
||||||
action_result["result"] = "Json error during startup: %s" % e
|
self.action_result["result"] = "Json error during startup: %s" % e
|
||||||
self.send_result(action_result, headers, stream_path)
|
self.send_result(self.action_result, headers, stream_path)
|
||||||
return
|
return
|
||||||
|
|
||||||
print("")
|
print("")
|
||||||
@@ -1993,10 +2003,10 @@ class AppBase:
|
|||||||
|
|
||||||
if not branchcheck:
|
if not branchcheck:
|
||||||
self.logger.info("Failed one or more branch conditions.")
|
self.logger.info("Failed one or more branch conditions.")
|
||||||
action_result["result"] = tmpresult
|
self.action_result["result"] = tmpresult
|
||||||
action_result["status"] = "SKIPPED"
|
self.action_result["status"] = "SKIPPED"
|
||||||
try:
|
try:
|
||||||
ret = requests.post("%s%s" % (self.base_url, stream_path), headers=headers, json=action_result)
|
ret = requests.post("%s%s" % (self.base_url, stream_path), headers=headers, json=self.action_result)
|
||||||
self.logger.info("Result: %d" % ret.status_code)
|
self.logger.info("Result: %d" % ret.status_code)
|
||||||
if ret.status_code != 200:
|
if ret.status_code != 200:
|
||||||
self.logger.info(ret.text)
|
self.logger.info(ret.text)
|
||||||
@@ -2021,8 +2031,8 @@ class AppBase:
|
|||||||
func = getattr(self, actionname, None)
|
func = getattr(self, actionname, None)
|
||||||
if func == None:
|
if func == None:
|
||||||
self.logger.debug(f"Failed executing {actionname} because func is None.")
|
self.logger.debug(f"Failed executing {actionname} because func is None.")
|
||||||
action_result["status"] = "FAILURE"
|
self.action_result["status"] = "FAILURE"
|
||||||
action_result["result"] = "Function %s doesn't exist." % actionname
|
self.action_result["result"] = "Function %s doesn't exist." % actionname
|
||||||
elif callable(func):
|
elif callable(func):
|
||||||
try:
|
try:
|
||||||
if len(action["parameters"]) < 1:
|
if len(action["parameters"]) < 1:
|
||||||
@@ -2385,9 +2395,9 @@ class AppBase:
|
|||||||
print("LENGTH OF ARR: %d" % len(resultarray))
|
print("LENGTH OF ARR: %d" % len(resultarray))
|
||||||
if len(resultarray) == 0:
|
if len(resultarray) == 0:
|
||||||
print("[WARNING] Returning empty array because the array length to be looped is 0 (0)")
|
print("[WARNING] Returning empty array because the array length to be looped is 0 (0)")
|
||||||
action_result["status"] = "SUCCESS"
|
self.action_result["status"] = "SUCCESS"
|
||||||
action_result["result"] = "[]"
|
self.action_result["result"] = "[]"
|
||||||
self.send_result(action_result, headers, stream_path)
|
self.send_result(self.action_result, headers, stream_path)
|
||||||
return
|
return
|
||||||
|
|
||||||
#print("RESULTARRAY: %s" % resultarray)
|
#print("RESULTARRAY: %s" % resultarray)
|
||||||
@@ -2531,10 +2541,10 @@ class AppBase:
|
|||||||
params = new_params[0]
|
params = new_params[0]
|
||||||
else:
|
else:
|
||||||
print("[WARNING] SHOULD STOP EXECUTION BECAUSE FIELDS AREN'T UNIQUE")
|
print("[WARNING] SHOULD STOP EXECUTION BECAUSE FIELDS AREN'T UNIQUE")
|
||||||
action_result["status"] = "SKIPPED"
|
self.action_result["status"] = "SKIPPED"
|
||||||
action_result["result"] = f"A non-unique value was found"
|
self.action_result["result"] = f"A non-unique value was found"
|
||||||
action_result["completed_at"] = int(time.time())
|
self.action_result["completed_at"] = int(time.time())
|
||||||
self.send_result(action_result, headers, stream_path)
|
self.send_result(self.action_result, headers, stream_path)
|
||||||
return
|
return
|
||||||
|
|
||||||
print("[INFO] Running normal execution (not loop)\n")
|
print("[INFO] Running normal execution (not loop)\n")
|
||||||
@@ -2764,46 +2774,46 @@ class AppBase:
|
|||||||
print("Normal result - no list?")
|
print("Normal result - no list?")
|
||||||
result = results
|
result = results
|
||||||
|
|
||||||
action_result["status"] = "SUCCESS"
|
self.action_result["status"] = "SUCCESS"
|
||||||
action_result["result"] = str(result)
|
self.action_result["result"] = str(result)
|
||||||
if action_result["result"] == "":
|
if self.action_result["result"] == "":
|
||||||
action_result["result"] = result
|
self.action_result["result"] = result
|
||||||
|
|
||||||
self.logger.debug(f"Executed {action['label']}-{action['id']}")#with result: {result}")
|
self.logger.debug(f"Executed {action['label']}-{action['id']}")#with result: {result}")
|
||||||
#self.logger.debug(f"Data: %s" % action_result)
|
#self.logger.debug(f"Data: %s" % action_result)
|
||||||
except TypeError as e:
|
except TypeError as e:
|
||||||
print("TypeError issue: %s" % e)
|
print("TypeError issue: %s" % e)
|
||||||
action_result["status"] = "FAILURE"
|
self.action_result["status"] = "FAILURE"
|
||||||
action_result["result"] = "TypeError: %s" % str(e)
|
self.action_result["result"] = "TypeError: %s" % str(e)
|
||||||
else:
|
else:
|
||||||
print("Function %s doesn't exist?" % action["name"])
|
print("Function %s doesn't exist?" % action["name"])
|
||||||
self.logger.error(f"App {self.__class__.__name__}.{action['name']} is not callable")
|
self.logger.error(f"App {self.__class__.__name__}.{action['name']} is not callable")
|
||||||
action_result["status"] = "FAILURE"
|
self.action_result["status"] = "FAILURE"
|
||||||
action_result["result"] = "Function %s is not callable." % actionname
|
self.action_result["result"] = "Function %s is not callable." % actionname
|
||||||
|
|
||||||
# https://ptb.discord.com/channels/747075026288902237/882017498550112286/882043773138382890
|
# https://ptb.discord.com/channels/747075026288902237/882017498550112286/882043773138382890
|
||||||
except (requests.exceptions.RequestException, TimeoutError) as e:
|
except (requests.exceptions.RequestException, TimeoutError) as e:
|
||||||
print(f"Failed to execute request: {e}")
|
print(f"Failed to execute request: {e}")
|
||||||
self.logger.exception(f"Failed to execute {e}-{action['id']}")
|
self.logger.exception(f"Failed to execute {e}-{action['id']}")
|
||||||
action_result["status"] = "SUCCESS"
|
self.action_result["status"] = "SUCCESS"
|
||||||
try:
|
try:
|
||||||
action_result["result"] = json.dumps({
|
self.action_result["result"] = json.dumps({
|
||||||
"success": False,
|
"success": False,
|
||||||
"reason": f"Request error - failing silently. Details: {e}"
|
"reason": f"Request error - failing silently. Details: {e}"
|
||||||
})
|
})
|
||||||
except json.decoder.JSONDecodeError as e:
|
except json.decoder.JSONDecodeError as e:
|
||||||
action_result["result"] = f"Request error: {e}"
|
self.action_result["result"] = f"Request error: {e}"
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Failed to execute: {e}")
|
print(f"Failed to execute: {e}")
|
||||||
self.logger.exception(f"Failed to execute {e}-{action['id']}")
|
self.logger.exception(f"Failed to execute {e}-{action['id']}")
|
||||||
action_result["status"] = "FAILURE"
|
self.action_result["status"] = "FAILURE"
|
||||||
action_result["result"] = f"General exception: {e}"
|
self.action_result["result"] = f"General exception: {e}"
|
||||||
|
|
||||||
action_result["completed_at"] = int(time.time())
|
self.action_result["completed_at"] = int(time.time())
|
||||||
|
|
||||||
# Send the result :)
|
# Send the result :)
|
||||||
self.send_result(action_result, headers, stream_path)
|
self.send_result(self.action_result, headers, stream_path)
|
||||||
return
|
return
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
### DEFAULT
|
### DEFAULT
|
||||||
NAME=shuffle-app_sdk
|
NAME=shuffle-app_sdk
|
||||||
VERSION=0.9.19
|
VERSION=0.9.20
|
||||||
|
|
||||||
docker rmi docker.pkg.github.com/frikky/shuffle/$NAME:$VERSION --force
|
docker rmi docker.pkg.github.com/frikky/shuffle/$NAME:$VERSION --force
|
||||||
docker build . -f Dockerfile -t frikky/shuffle:app_sdk -t frikky/$NAME:$VERSION -t docker.pkg.github.com/frikky/shuffle/$NAME:$VERSION -t ghcr.io/frikky/$NAME:$VERSION
|
docker build . -f Dockerfile -t frikky/shuffle:app_sdk -t frikky/$NAME:$VERSION -t docker.pkg.github.com/frikky/shuffle/$NAME:$VERSION -t ghcr.io/frikky/$NAME:$VERSION
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import { useTheme } from '@material-ui/core/styles';
|
|||||||
|
|
||||||
import YAML from 'yaml'
|
import YAML from 'yaml'
|
||||||
import {Link} from 'react-router-dom';
|
import {Link} from 'react-router-dom';
|
||||||
import ReactJson from 'react-json-view'
|
|
||||||
import { useAlert } from "react-alert";
|
import { useAlert } from "react-alert";
|
||||||
import Dropzone from '../components/Dropzone';
|
import Dropzone from '../components/Dropzone';
|
||||||
|
|
||||||
@@ -620,15 +619,6 @@ const Apps = (props) => {
|
|||||||
</MenuItem>
|
</MenuItem>
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
{/*
|
|
||||||
<ReactJson
|
|
||||||
src={JSON.parse(showResult)}
|
|
||||||
theme="solarized"
|
|
||||||
collapsed={false}
|
|
||||||
displayDataTypes={true}
|
|
||||||
name={"Example return value"}
|
|
||||||
/>
|
|
||||||
*/}
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import {BrowserView, MobileView} from "react-device-detect";
|
|||||||
import {Link} from 'react-router-dom';
|
import {Link} from 'react-router-dom';
|
||||||
|
|
||||||
import {Tooltip, Divider, Button, Menu, MenuItem, Typography, Paper, List} from '@material-ui/core';
|
import {Tooltip, Divider, Button, Menu, MenuItem, Typography, Paper, List} from '@material-ui/core';
|
||||||
import {Edit as EditIcon} from '@material-ui/icons';
|
import {Link as LinkIcon, Edit as EditIcon} from '@material-ui/icons';
|
||||||
|
|
||||||
const Body = {
|
const Body = {
|
||||||
maxWidth: '1000px',
|
maxWidth: '1000px',
|
||||||
@@ -28,6 +28,7 @@ const Docs = (props) => {
|
|||||||
const { globalUrl, selectedDoc, serverside, isMobile, } = props;
|
const { globalUrl, selectedDoc, serverside, isMobile, } = props;
|
||||||
|
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
const [mobile, setMobile] = useState(isMobile === true ? true : false);
|
||||||
const [data, setData] = useState("");
|
const [data, setData] = useState("");
|
||||||
const [firstrequest, setFirstrequest] = useState(true);
|
const [firstrequest, setFirstrequest] = useState(true);
|
||||||
const [list, setList] = useState([]);
|
const [list, setList] = useState([]);
|
||||||
@@ -107,16 +108,23 @@ const Docs = (props) => {
|
|||||||
|
|
||||||
if (firstrequest) {
|
if (firstrequest) {
|
||||||
setFirstrequest(false)
|
setFirstrequest(false)
|
||||||
|
if (!serverside) {
|
||||||
|
if (window.innerWidth < 768) {
|
||||||
|
setMobile(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (selectedDoc !== undefined) {
|
if (selectedDoc !== undefined) {
|
||||||
setData(selectedDoc.reason)
|
setData(selectedDoc.reason)
|
||||||
setList(selectedDoc.list)
|
setList(selectedDoc.list)
|
||||||
setListLoaded(true)
|
setListLoaded(true)
|
||||||
} else {
|
} else {
|
||||||
|
if (!serverside) {
|
||||||
fetchDocList()
|
fetchDocList()
|
||||||
fetchDocs(props.match.params.key)
|
fetchDocs(props.match.params.key)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Handles search-based changes that origin from outside this file
|
// Handles search-based changes that origin from outside this file
|
||||||
if (serverside !== true && window.location.href !== baseUrl) {
|
if (serverside !== true && window.location.href !== baseUrl) {
|
||||||
@@ -194,10 +202,10 @@ const Docs = (props) => {
|
|||||||
const markdownStyle = {
|
const markdownStyle = {
|
||||||
color: "rgba(255, 255, 255, 0.65)",
|
color: "rgba(255, 255, 255, 0.65)",
|
||||||
flex: "1",
|
flex: "1",
|
||||||
maxWidth: isMobile ? "100%" : 750,
|
maxWidth: mobile ? "100%" : 750,
|
||||||
overflow: "hidden",
|
overflow: "hidden",
|
||||||
paddingBottom: 200,
|
paddingBottom: 200,
|
||||||
marginLeft: isMobile ? 0 : 275,
|
marginLeft: mobile ? 0 : 275,
|
||||||
}
|
}
|
||||||
|
|
||||||
function OuterLink(props) {
|
function OuterLink(props) {
|
||||||
@@ -221,14 +229,16 @@ const Docs = (props) => {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function Heading(props) {
|
const Heading = (props) => {
|
||||||
const element = React.createElement(`h${props.level}`, {style: {marginTop: 50}}, props.children)
|
const element = React.createElement(`h${props.level}`, {style: {marginTop: 50}}, props.children)
|
||||||
|
const [hover, setHover] = useState(false)
|
||||||
|
|
||||||
var extraInfo = ""
|
var extraInfo = ""
|
||||||
if (props.level === 1) {
|
if (props.level === 1) {
|
||||||
extraInfo =
|
extraInfo =
|
||||||
<div style={{backgroundColor: theme.palette.inputColor, padding: 15, borderRadius: theme.palette.borderRadius, marginBottom: 30, display: "flex",}}>
|
<div style={{backgroundColor: theme.palette.inputColor, padding: 15, borderRadius: theme.palette.borderRadius, marginBottom: 30, display: "flex",}}>
|
||||||
<div style={{flex: 3, display: "flex", vAlign: "center",}}>
|
<div style={{flex: 3, display: "flex", vAlign: "center",}}>
|
||||||
|
{mobile ? null :
|
||||||
<Typography style={{display: "inline", marginTop: 6, }}>
|
<Typography style={{display: "inline", marginTop: 6, }}>
|
||||||
<a rel="norefferer" target="_blank" href={selectedMeta.link} target="_blank" style={{textDecoration: "none", color: "#f85a3e"}}>
|
<a rel="norefferer" target="_blank" href={selectedMeta.link} target="_blank" style={{textDecoration: "none", color: "#f85a3e"}}>
|
||||||
<Button style={{}} variant="outlined">
|
<Button style={{}} variant="outlined">
|
||||||
@@ -236,19 +246,22 @@ const Docs = (props) => {
|
|||||||
</Button>
|
</Button>
|
||||||
</a>
|
</a>
|
||||||
</Typography>
|
</Typography>
|
||||||
|
}
|
||||||
|
{mobile ? null :
|
||||||
<div style={{height: "100%", width: 1, backgroundColor: "white", marginLeft: 50, marginRight: 50, }} />
|
<div style={{height: "100%", width: 1, backgroundColor: "white", marginLeft: 50, marginRight: 50, }} />
|
||||||
<Typography style={{display: "inline", marginTop: 9, }}>
|
}
|
||||||
|
<Typography style={{display: "inline", marginTop: 11, }}>
|
||||||
{selectedMeta.read_time} minute{selectedMeta.read_time === 1 ? "" : "s"} to read
|
{selectedMeta.read_time} minute{selectedMeta.read_time === 1 ? "" : "s"} to read
|
||||||
</Typography>
|
</Typography>
|
||||||
</div>
|
</div>
|
||||||
<div style={{flex: 2}}>
|
<div style={{flex: 2}}>
|
||||||
{selectedMeta.contributors === undefined || selectedMeta.contributors === null ? "" :
|
{mobile || selectedMeta.contributors === undefined || selectedMeta.contributors === null ? "" :
|
||||||
<div style={{margin: 10, height: "100%", display: "inline",}}>
|
<div style={{margin: 10, height: "100%", display: "inline",}}>
|
||||||
{selectedMeta.contributors.slice(0,7).map((data, index) => {
|
{selectedMeta.contributors.slice(0,7).map((data, index) => {
|
||||||
return (
|
return (
|
||||||
<a rel="norefferer" target="_blank" href={data.url} target="_blank" style={{textDecoration: "none", color: "#f85a3e"}}>
|
<a rel="norefferer" target="_blank" href={data.url} target="_blank" style={{textDecoration: "none", color: "#f85a3e"}}>
|
||||||
<Tooltip title={data.url} placement="bottom">
|
<Tooltip title={data.url} placement="bottom">
|
||||||
<img alt={data.url} src={data.image} style={{height: 40, borderRadius: 40, }} />
|
<img alt={data.url} src={data.image} style={{marginTop: 5, marginRight: 10, height: 40, borderRadius: 40, }} />
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</a>
|
</a>
|
||||||
)
|
)
|
||||||
@@ -260,9 +273,20 @@ const Docs = (props) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Typography>
|
<Typography
|
||||||
|
onMouseOver={() => {
|
||||||
|
setHover(true)
|
||||||
|
}} >
|
||||||
{props.level !== 1 ? <Divider style={{width: "90%", marginTop: 40, backgroundColor: theme.palette.inputColor}} /> : null}
|
{props.level !== 1 ? <Divider style={{width: "90%", marginTop: 40, backgroundColor: theme.palette.inputColor}} /> : null}
|
||||||
{element}
|
{element}
|
||||||
|
{/*hover ? <LinkIcon onMouseOver={() => {setHover(true)}} style={{cursor: "pointer", display: "inline", }} onClick={() => {
|
||||||
|
window.location.href += "#hello"
|
||||||
|
console.log(window.location)
|
||||||
|
//window.history.pushState('page2', 'Title', '/page2.php');
|
||||||
|
//window.history.replaceState('page2', 'Title', '/page2.php');
|
||||||
|
}} />
|
||||||
|
: ""
|
||||||
|
*/}
|
||||||
{extraInfo}
|
{extraInfo}
|
||||||
</Typography>
|
</Typography>
|
||||||
)
|
)
|
||||||
@@ -345,6 +369,10 @@ const Docs = (props) => {
|
|||||||
>
|
>
|
||||||
{list.map((data, index) => {
|
{list.map((data, index) => {
|
||||||
const item = data.name
|
const item = data.name
|
||||||
|
if (item === undefined) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
const path = "/docs/"+item
|
const path = "/docs/"+item
|
||||||
const newname = item.charAt(0).toUpperCase()+item.substring(1).split("_").join(" ").split("-").join(" ")
|
const newname = item.charAt(0).toUpperCase()+item.substring(1).split("_").join(" ").split("-").join(" ")
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ import {DataGrid, GridToolbarContainer, GridDensitySelector, GridToolbar} from '
|
|||||||
|
|
||||||
//import JSONPretty from 'react-json-pretty';
|
//import JSONPretty from 'react-json-pretty';
|
||||||
//import JSONPrettyMon from 'react-json-pretty/dist/monikai'
|
//import JSONPrettyMon from 'react-json-pretty/dist/monikai'
|
||||||
import ReactJson from 'react-json-view'
|
|
||||||
import Dropzone from '../components/Dropzone';
|
import Dropzone from '../components/Dropzone';
|
||||||
|
|
||||||
import {Link} from 'react-router-dom';
|
import {Link} from 'react-router-dom';
|
||||||
@@ -1372,181 +1371,11 @@ const Workflows = (props) => {
|
|||||||
return string.split(search).join(replace);
|
return string.split(search).join(replace);
|
||||||
}
|
}
|
||||||
|
|
||||||
const resultsPaper = (data) => {
|
|
||||||
var boxWidth = "2px"
|
|
||||||
var boxColor = "orange"
|
|
||||||
if (data.status === "ABORTED" || data.status === "UNFINISHED" || data.status === "FAILURE"){
|
|
||||||
boxColor = "red"
|
|
||||||
} else if (data.status === "FINISHED" || data.status === "SUCCESS") {
|
|
||||||
boxColor = "green"
|
|
||||||
} else if (data.status === "SKIPPED" || data.status === "EXECUTING") {
|
|
||||||
boxColor = "yellow"
|
|
||||||
} else {
|
|
||||||
boxColor = "green"
|
|
||||||
}
|
|
||||||
|
|
||||||
var t = new Date(data.started_at*1000)
|
|
||||||
var showResult = data.result.trim()
|
|
||||||
const validate = validateJson(showResult)
|
|
||||||
|
|
||||||
if (validate.valid) {
|
|
||||||
showResult = <ReactJson
|
|
||||||
src={validate.result}
|
|
||||||
theme="solarized"
|
|
||||||
collapsed={collapseJson}
|
|
||||||
displayDataTypes={false}
|
|
||||||
name={"Results for "+data.action.label}
|
|
||||||
/>
|
|
||||||
} else {
|
|
||||||
// FIXME - have everything parsed as json, either just for frontend
|
|
||||||
// or in the backend?
|
|
||||||
/*
|
|
||||||
const newdata = {"result": data.result}
|
|
||||||
showResult = <ReactJson
|
|
||||||
src={JSON.parse(newdata)}
|
|
||||||
theme="solarized"
|
|
||||||
collapsed={collapseJson}
|
|
||||||
displayDataTypes={false}
|
|
||||||
name={"Results for "+data.action.name}
|
|
||||||
/>
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Paper key={data.execution_id} square style={resultPaperAppStyle} onClick={() => {}}>
|
|
||||||
<div style={{marginLeft: "10px", marginTop: "5px", marginBottom: "5px", marginRight: "5px", width: boxWidth, backgroundColor: boxColor}}>
|
|
||||||
</div>
|
|
||||||
<Grid container style={{margin: "10px 10px 10px 10px", flex: "1"}}>
|
|
||||||
<Grid style={{display: "flex", flexDirection: "column", width: "100%"}}>
|
|
||||||
<Grid item style={{flex: "1"}}>
|
|
||||||
<h4 style={{marginBottom: "0px", marginTop: "10px"}}><b>Name</b>: {data.action.label}</h4>
|
|
||||||
</Grid>
|
|
||||||
<Grid item style={{flex: "1", justifyContent: "center"}}>
|
|
||||||
App: {data.action.app_name}, Version: {data.action.app_version}
|
|
||||||
</Grid>
|
|
||||||
<Grid item style={{flex: "1", justifyContent: "center"}}>
|
|
||||||
Action: {data.action.name}, Environment: {data.action.environment}, Status: {data.status}
|
|
||||||
</Grid>
|
|
||||||
<div style={{display: "flex", flex: "1"}}>
|
|
||||||
<Grid item style={{flex: "10", justifyContent: "center"}}>
|
|
||||||
Started: {t.toISOString()}
|
|
||||||
</Grid>
|
|
||||||
</div>
|
|
||||||
<Divider style={{marginBottom: "10px", marginTop: "10px", height: "1px", width: "100%", backgroundColor: dividerColor}}/>
|
|
||||||
<div style={{display: "flex", flex: "1"}}>
|
|
||||||
<Grid item style={{flex: "10", justifyContent: "center"}}>
|
|
||||||
{showResult}
|
|
||||||
</Grid>
|
|
||||||
</div>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
</Paper>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const resultsHandler = Object.getOwnPropertyNames(selectedExecution).length > 0 && selectedExecution.results !== null ?
|
|
||||||
<div>
|
|
||||||
{selectedExecution.results.sort((a, b) => a.started_at - b.started_at).map((data, index) => {
|
|
||||||
return (
|
|
||||||
<div key={index}>
|
|
||||||
{resultsPaper(data)}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
:
|
|
||||||
<div>
|
|
||||||
No results yet
|
|
||||||
</div>
|
|
||||||
|
|
||||||
const resultsLength = Object.getOwnPropertyNames(selectedExecution).length > 0 && selectedExecution.results !== null ? selectedExecution.results.length : 0
|
const resultsLength = Object.getOwnPropertyNames(selectedExecution).length > 0 && selectedExecution.results !== null ? selectedExecution.results.length : 0
|
||||||
|
|
||||||
const ExecutionDetails = () => {
|
|
||||||
var starttime = new Date(selectedExecution.started_at*1000)
|
|
||||||
var endtime = new Date(selectedExecution.started_at*1000)
|
|
||||||
|
|
||||||
var parsedArgument = selectedExecution.execution_argument
|
|
||||||
if (selectedExecution.execution_argument !== undefined && selectedExecution.execution_argument.length > 0) {
|
|
||||||
parsedArgument = replaceAll(parsedArgument, " None", " \"None\"");
|
|
||||||
}
|
|
||||||
|
|
||||||
var arg = null
|
|
||||||
if (selectedExecution.execution_argument !== undefined && selectedExecution.execution_argument.length > 0) {
|
|
||||||
var showResult = selectedExecution.execution_argument.trim()
|
|
||||||
const validate = validateJson(showResult)
|
|
||||||
|
|
||||||
arg = validate.valid ?
|
|
||||||
<ReactJson
|
|
||||||
src={validate.result}
|
|
||||||
theme="solarized"
|
|
||||||
collapsed={true}
|
|
||||||
displayDataTypes={false}
|
|
||||||
name={"Execution argument / webhook"}
|
|
||||||
/>
|
|
||||||
: showResult
|
|
||||||
}
|
|
||||||
|
|
||||||
var lastresult = null
|
|
||||||
if (selectedExecution.result !== undefined && selectedExecution.result.length > 0) {
|
|
||||||
var showResult = selectedExecution.result.trim()
|
|
||||||
const validate = validateJson(showResult)
|
|
||||||
lastresult = validate.valid ?
|
|
||||||
<ReactJson
|
|
||||||
src={validate.result}
|
|
||||||
theme="solarized"
|
|
||||||
collapsed={true}
|
|
||||||
displayDataTypes={false}
|
|
||||||
name={"Last result from execution"}
|
|
||||||
/>
|
|
||||||
: showResult
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
<div>
|
|
||||||
ID: {selectedExecution.execution_id}
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<b>Last node:</b> {selectedExecution.workflow.actions.find(data => data.id === selectedExecution.last_node).actions[0].label}
|
|
||||||
</div>
|
|
||||||
*/
|
|
||||||
if (Object.getOwnPropertyNames(selectedExecution).length > 0 && selectedExecution.workflow.actions !== null) {
|
|
||||||
return (
|
|
||||||
<div style={{overflowX: "hidden"}}>
|
|
||||||
<div>
|
|
||||||
<b>Status:</b> {selectedExecution.status}
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<b>Started:</b> {starttime.toISOString()}
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<b>Finished:</b> {endtime.toISOString()}
|
|
||||||
</div>
|
|
||||||
{/*
|
|
||||||
<div>
|
|
||||||
<b>Last Result:</b> {lastresult}
|
|
||||||
</div>
|
|
||||||
*/}
|
|
||||||
<div style={{marginTop: 10}}>
|
|
||||||
{arg}
|
|
||||||
</div>
|
|
||||||
<Divider style={{marginBottom: "10px", marginTop: "10px", height: "1px", width: "100%", backgroundColor: dividerColor}}/>
|
|
||||||
{resultsHandler}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
executionLoading ?
|
|
||||||
<div style={{marginTop: 25, textAlign: "center"}}>
|
|
||||||
<CircularProgress />
|
|
||||||
</div>
|
|
||||||
:
|
|
||||||
<h4>
|
|
||||||
There are no executiondetails yet. Click "execute" to run your first one.
|
|
||||||
</h4>
|
|
||||||
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can create and set workflows
|
// Can create and set workflows
|
||||||
const setNewWorkflow = (name, description, tags, defaultReturnValue, editingWorkflow, redirect) => {
|
const setNewWorkflow = (name, description, tags, defaultReturnValue, editingWorkflow, redirect) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user