Merge branch 'launch' into launch

This commit is contained in:
Frikky
2022-07-14 13:28:36 +02:00
committed by GitHub
11 changed files with 473 additions and 273 deletions
+21 -3
View File
@@ -117,6 +117,22 @@ def as_object(a):
def ast(a): def ast(a):
return ast.literal_eval(str(a)) return ast.literal_eval(str(a))
@shuffle_filters.register
def escape_string(a):
a = str(a)
return a.replace("\\\'", "\'", -1).replace("\\\"", "\"", -1).replace("'", "\\\'", -1).replace("\"", "\\\"", -1)
@shuffle_filters.register
def json_escape(a):
a = str(a)
return a.replace("\\\'", "\'", -1).replace("\\\"", "\"", -1).replace("'", "\\\\\'", -1).replace("\"", "\\\\\"", -1)
# By default using json escape to add all backslashes
@shuffle_filters.register
def escape(a):
a = str(a)
return json_escape(a)
#print(standard_filter_manager.filters) #print(standard_filter_manager.filters)
#print(shuffle_filters.filters) #print(shuffle_filters.filters)
#print(Liquid("{{ '10' | plus: 1}}", filters=shuffle_filters.filters).render()) #print(Liquid("{{ '10' | plus: 1}}", filters=shuffle_filters.filters).render())
@@ -2025,7 +2041,6 @@ class AppBase:
errors = False errors = False
error_msg = "" error_msg = ""
try: try:
#self.logger.info("In liquid")
if len(template) > 10000000: if len(template) > 10000000:
self.logger.info("[DEBUG] Skipping liquid - size too big (%d)" % len(template)) self.logger.info("[DEBUG] Skipping liquid - size too big (%d)" % len(template))
return template return template
@@ -2094,6 +2109,9 @@ class AppBase:
error = True error = True
error_msg = e error_msg = e
if "fmt" in error_msg and "liquid_date" in error_msg:
return template
self.logger.info("Done in liquid") self.logger.info("Done in liquid")
if error == True: if error == True:
self.action_result["status"] = "FAILURE" self.action_result["status"] = "FAILURE"
@@ -2102,6 +2120,7 @@ class AppBase:
"reason": f"Failed to parse LiquidPy: {error_msg}", "reason": f"Failed to parse LiquidPy: {error_msg}",
"input": template, "input": template,
} }
try: try:
self.action_result["result"] = json.dumps(data) self.action_result["result"] = json.dumps(data)
except Exception as e: except Exception as e:
@@ -2240,7 +2259,6 @@ class AppBase:
#self.logger.info("STATIC PARSED: %s" % actualitem) #self.logger.info("STATIC PARSED: %s" % actualitem)
#self.logger.info("[INFO] Done with regex matching") #self.logger.info("[INFO] Done with regex matching")
if len(actualitem) > 0: if len(actualitem) > 0:
#self.logger.info("[DEBUG] Matches: ", actualitem)
for replace in actualitem: for replace in actualitem:
try: try:
to_be_replaced = replace[0] to_be_replaced = replace[0]
@@ -2798,7 +2816,7 @@ class AppBase:
})) }))
if parameter["name"] == "body": if parameter["name"] == "body":
self.logger.info("[INFO] Should debug field with liquid and other checks as it's BODY: %s" % value) self.logger.info(f"[INFO] Should debug field with liquid and other checks as it's BODY: {value}")
# Custom format for ${name[0,1,2,...]}$ # Custom format for ${name[0,1,2,...]}$
#submatch = "([${]{2}([0-9a-zA-Z_-]+)(\[.*\])[}$]{2})" #submatch = "([${]{2}([0-9a-zA-Z_-]+)(\[.*\])[}$]{2})"
+1 -1
View File
@@ -2,7 +2,7 @@
### DEFAULT ### DEFAULT
NAME=shuffle-app_sdk NAME=shuffle-app_sdk
VERSION=1.0.4 VERSION=1.0.5
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 -t ghcr.io/frikky/$NAME:nightly 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 -t ghcr.io/frikky/$NAME:nightly
+1 -1
View File
@@ -1,7 +1,7 @@
urllib3==1.26.5 urllib3==1.26.5
requests==2.25.1 requests==2.25.1
MarkupSafe==2.0.1 MarkupSafe==2.0.1
liquidpy==0.7.3 liquidpy==0.7.5
flask[async]==2.0.2 flask[async]==2.0.2
waitress==2.1.0 waitress==2.1.0
#flask==1.1.2 #flask==1.1.2
+1
View File
@@ -559,6 +559,7 @@ func runWorkflowExecutionTransaction(ctx context.Context, attempts int64, workfl
} }
//log.Printf("BASE LENGTH: %d", len(workflowExecution.Results)) //log.Printf("BASE LENGTH: %d", len(workflowExecution.Results))
workflowExecution, dbSave, err := shuffle.ParsedExecutionResult(ctx, *workflowExecution, actionResult, false, 0) workflowExecution, dbSave, err := shuffle.ParsedExecutionResult(ctx, *workflowExecution, actionResult, false, 0)
if err != nil { if err != nil {
b, suberr := json.Marshal(actionResult) b, suberr := json.Marshal(actionResult)
+6 -11
View File
@@ -1599,18 +1599,13 @@ const Framework = (props) => {
</div> </div>
<div style={{marginTop: 10}}> <div style={{marginTop: 10}}>
{selectionOpen ? {selectionOpen ?
isCloud && defaultSearch !== undefined && defaultSearch.length > 0 ? <WorkflowSearch
<WorkflowSearch defaultSearch={defaultSearch}
defaultSearch={defaultSearch} newSelectedApp={newSelectedApp}
newSelectedApp={newSelectedApp} setNewSelectedApp={setNewSelectedApp}
setNewSelectedApp={setNewSelectedApp} />
/>
:
<div>
Coming soon. <a style={{ textDecoration: "none", color: "#f85a3e" }} href="https://shuffler.io/register" target="_blank">Register for Shuffle cloud</a> to try an early version now.
</div>
: null} : null}
</div> </div>
</Paper> </Paper>
: null : null
} }
+88 -73
View File
@@ -5,6 +5,7 @@ import { useTheme } from '@material-ui/core/styles';
import {Link} from 'react-router-dom'; import {Link} from 'react-router-dom';
import { Search as SearchIcon, CloudQueue as CloudQueueIcon, Code as CodeIcon } from '@material-ui/icons'; import { Search as SearchIcon, CloudQueue as CloudQueueIcon, Code as CodeIcon } from '@material-ui/icons';
import aa from 'search-insights'
import algoliasearch from 'algoliasearch/lite'; import algoliasearch from 'algoliasearch/lite';
import { InstantSearch, Configure, connectSearchBox, connectHits } from 'react-instantsearch-dom'; import { InstantSearch, Configure, connectSearchBox, connectHits } from 'react-instantsearch-dom';
@@ -13,13 +14,20 @@ import {
Grid, Grid,
Paper, Paper,
TextField, TextField,
Avatar,
ButtonBase, ButtonBase,
InputAdornment, InputAdornment,
Typography, Typography,
Button, Button,
Tooltip Tooltip,
List,
ListItem,
ListItemAvatar,
ListItemText,
} from '@material-ui/core'; } from '@material-ui/core';
import {Close as CloseIcon, Folder as FolderIcon, Polymer as PolymerIcon, LibraryBooks as LibraryBooksIcon} from '@material-ui/icons'
const searchClient = algoliasearch("JNSS5CFDZZ", "db08e40265e2941b9a7d8f644b6e5240") const searchClient = algoliasearch("JNSS5CFDZZ", "db08e40265e2941b9a7d8f644b6e5240")
const DocsGrid = props => { const DocsGrid = props => {
const { maxRows, showName, showSuggestion, isMobile, globalUrl, parsedXs } = props const { maxRows, showName, showSuggestion, isMobile, globalUrl, parsedXs } = props
@@ -139,92 +147,99 @@ const DocsGrid = props => {
//} //}
return ( return (
<Grid container spacing={2}> <List>
{hits.map((data, index) => { {hits.map((data, index) => {
workflowDelay += 50 workflowDelay += 50
const paperStyle = { const innerlistitemStyle = {
backgroundColor: index === mouseHoverIndex ? "rgba(255,255,255,0.8)" : theme.palette.inputColor, width: "100%",
color: index === mouseHoverIndex ? theme.palette.inputColor : "rgba(255,255,255,0.8)", overflowX: "hidden",
border: `1px solid ${innerColor}`, overflowY: "hidden",
padding: 15, borderBottom: "1px solid rgba(255,255,255,0.4)",
backgroundColor: mouseHoverIndex === index ? "#1f2023" : "inherit",
cursor: "pointer", cursor: "pointer",
position: "relative", marginLeft: 5,
minHeight: 116, marginRight: 5,
} maxHeight: 75,
minHeight: 75,
if (counted === 12/xs*rowHandler) { maxWidth: 420,
return null minWidth: "100%",
} }
//if (counted === 12/xs*rowHandler) {
// return null
//}
console.log("DATA: ", data)
counted += 1 counted += 1
var parsedname = "" var name = data.name === undefined ?
for (var key = 0; key < data.name.length; key++) { data.filename.charAt(0).toUpperCase() + data.filename.slice(1).replaceAll("_", " ") + " - " + data.title :
var character = data.name.charAt(key) (data.name.charAt(0).toUpperCase()+data.name.slice(1)).replaceAll("_", " ")
if (character === character.toUpperCase()) {
//console.log(data.name[key], data.name[key+1])
if (data.name.charAt(key+1) !== undefined && data.name.charAt(key+1) === data.name.charAt(key+1).toUpperCase()) {
} else {
parsedname += " "
}
}
parsedname += character if (name.length > 100) {
name = name.slice(0, 100)+"..."
} }
parsedname = (parsedname.charAt(0).toUpperCase()+parsedname.substring(1)).replaceAll("_", " ") const secondaryText = data.data !== undefined ? data.data.slice(0, 100)+"..." : ""
const baseImage = <PolymerIcon />
const avatar = data.image_url === undefined ?
baseImage
:
<Avatar
src={data.image_url}
variant="rounded"
/>
var parsedUrl = data.urlpath !== undefined ? data.urlpath : ""
parsedUrl += `?queryID=${data.__queryID}`
return ( return (
<Zoom key={index} in={true} style={{ transitionDelay: `${workflowDelay}ms` }}> <Zoom key={index} in={true} style={{ transitionDelay: `${workflowDelay}ms` }}>
<Grid item xs={xs} key={index}> <Link key={data.objectID} to={parsedUrl} style={{textDecoration: "none", color: "white",}} onClick={(event) => {
<Link to={`/docs/${data.objectID}?queryID=${data.__queryID}`} style={{textDecoration: "none", color: "#f85a3e"}}> aa('init', {
<Paper elevation={0} style={paperStyle} onMouseOver={() => { appId: searchClient.appId,
setMouseHoverIndex(index) apiKey: searchClient.transporter.queryParameters["x-algolia-api-key"]
/* })
ReactGA.event({
category: "app_grid_view", const timestamp = new Date().getTime()
action: `search_bar_click`, aa('sendEvents', [
label: "", {
}) eventType: 'click',
*/ eventName: 'Product Clicked Appgrid',
}} onMouseOut={() => { index: 'documentation',
setMouseHoverIndex(-1) objectIDs: [data.objectID],
}} onClick={() => { timestamp: timestamp,
ReactGA.event({ queryID: data.__queryID,
category: "docs_grid_view", positions: [data.__position],
action: `docs_${parsedname}_${data.id}_click`, }
label: "", ])
})
}}> console.log("CLICK")
<ButtonBase style={{padding: 5, borderRadius: 3, minHeight: 100, minWidth: 100,}}> }}>
<img alt={data.name} src={data.image_url} style={{width: "100%", maxWidth: 100, minWidth: 100, minHeight: 100, maxHeight: 100, display: "block", margin: "0 auto"}} /> <ListItem key={data.objectID} style={innerlistitemStyle} onMouseOver={() => {
</ButtonBase> setMouseHoverIndex(index)
<div/> }}>
{index === mouseHoverIndex || showName === true ? <ListItemAvatar>
parsedname {avatar}
: </ListItemAvatar>
null <ListItemText
} primary={name}
{data.generated ? secondary={secondaryText}
<Tooltip title={"Created with App editor"} style={{marginTop: "28px", width: "100%"}} aria-label={data.name}> />
{data.invalid ? {/*
<CloudQueueIcon style={{position: "absolute", top: 1, left: 3, height: 16, width: 16, color: theme.palette.primary.main }}/> <ListItemSecondaryAction>
: <IconButton edge="end" aria-label="delete">
<CloudQueueIcon style={{position: "absolute", top: 1, left: 3, height: 16, width: 16, color: "rgba(255,255,255,0.95)",}}/> <DeleteIcon />
} </IconButton>
</Tooltip> </ListItemSecondaryAction>
: */}
<Tooltip title={"Created with python (custom app)"} style={{marginTop: "28px", width: "100%"}} aria-label={data.name}> </ListItem>
<CodeIcon style={{position: "absolute", top: 1, left: 3, height: 16, width: 16, color: "rgba(255,255,255,0.95)",}}/> </Link>
</Tooltip>
}
</Paper>
</Link>
</Grid>
</Zoom> </Zoom>
) )
})} })}
</Grid> </List>
) )
} }
+143 -1
View File
@@ -1295,6 +1295,19 @@ const ParsedAction = (props) => {
if (data.name === "url" && data.value !== undefined && data.value !== null && data.value.length === 0) { if (data.name === "url" && data.value !== undefined && data.value !== null && data.value.length === 0) {
data.value = data.example; data.value = data.example;
} }
if (data.value.length === 0) {
if (data.name.toLowerCase() === "headers") {
data.value = data.example
}
}
/*
if (data.name !== "queries" && data.name !== "key" && data.name !== "value" ) {
data.value = data.example
}
}
*/
} }
if (data.name.startsWith("${") && data.name.endsWith("}")) { if (data.name.startsWith("${") && data.name.endsWith("}")) {
@@ -2666,6 +2679,117 @@ 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?
//
// Should make it a function lol
if (workflow.branches !== undefined && workflow.branches !== null) {
for (var key in workflow.branches) {
for (var subkey in workflow.branches[key].conditions) {
const condition = workflow.branches[key].conditions[subkey]
const sourceparam = condition.source
const destinationparam = condition.destination
// Should have a smarter way of discovering node names
// Finding index(es) and replacing at the location
if (sourceparam.value.includes("$")) {
try {
var cnt = -1
var previous = 0
while (true) {
cnt += 1
// Need to make sure e.g. changing the first here doesn't change the 2nd
// $change_me
// $change_me_2
const foundindex = sourceparam.value.toLowerCase().indexOf(parsedBaseLabel, previous)
if (foundindex === previous && foundindex !== 0) {
break
}
if (foundindex >= 0) {
previous = foundindex+newname.length
// Need to add diff of length to word
// Check location:
// If it's a-zA-Z_ then don't replace
if (sourceparam.value.length > foundindex+parsedBaseLabel.length) {
const regex = /[a-zA-Z0-9_]/g;
const match = sourceparam.value[foundindex+parsedBaseLabel.length].match(regex);
if (match !== null) {
continue
}
}
console.log("Old found: ", workflow.branches[key].conditions[subkey].source.value)
const extralength = newname.length-parsedBaseLabel.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)
} else {
break
}
// Break no matter what after 5 replaces. May need to increase
if (cnt >= 5) {
break
}
}
} catch (e) {
console.log("Failed value replacement based on index: ", e)
}
}
if (destinationparam.value.includes("$")) {
try {
var cnt = -1
var previous = 0
while (true) {
cnt += 1
// Need to make sure e.g. changing the first here doesn't change the 2nd
// $change_me
// $change_me_2
const foundindex = destinationparam.value.toLowerCase().indexOf(parsedBaseLabel, previous)
if (foundindex === previous && foundindex !== 0) {
break
}
if (foundindex >= 0) {
previous = foundindex+newname.length
// Need to add diff of length to word
// Check location:
// If it's a-zA-Z_ then don't replace
if (destinationparam.value.length > foundindex+parsedBaseLabel.length) {
const regex = /[a-zA-Z0-9_]/g;
const match = destinationparam.value[foundindex+parsedBaseLabel.length].match(regex);
if (match !== null) {
continue
}
}
console.log("Old found: ", workflow.branches[key].conditions[subkey].destination.value)
const extralength = newname.length-parsedBaseLabel.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)
} else {
break
}
// Break no matter what after 5 replaces. May need to increase
if (cnt >= 5) {
break
}
}
} catch (e) {
console.log("Failed value replacement based on index: ", e)
}
}
}
}
}
for (var key in workflow.actions) { for (var key in workflow.actions) {
if (workflow.actions[key].id === selectedAction.id) { if (workflow.actions[key].id === selectedAction.id) {
@@ -2681,6 +2805,7 @@ const ParsedAction = (props) => {
// Should have a smarter way of discovering node names // Should have a smarter way of discovering node names
// Do regex? // Do regex?
// Finding index(es) and replacing at the location // Finding index(es) and replacing at the location
//
try { try {
var cnt = -1 var cnt = -1
@@ -3157,13 +3282,30 @@ const ParsedAction = (props) => {
for (var line in descSplit) { for (var line in descSplit) {
if (descSplit[line].includes("http") && descSplit[line].includes("://")) { if (descSplit[line].includes("http") && descSplit[line].includes("://")) {
const urlsplit = descSplit[line].split("/") const urlsplit = descSplit[line].split("/")
extraUrl = "/"+urlsplit.slice(3, urlsplit.length-1).join("/") try {
extraUrl = "/"+urlsplit.slice(3, urlsplit.length).join("/")
} catch (e) {
console.log("Failed - running with -1")
extraUrl = "/"+urlsplit.slice(3, urlsplit.length-1).join("/")
}
console.log("NO BASEURL TOO!! Why missing last one in certain scenarios (sevco)?", extraUrl, urlsplit, descSplit[line])
break break
} }
} }
if (extraUrl.length > 0) { if (extraUrl.length > 0) {
if (extraUrl.includes(" ")) {
extraUrl = extraUrl.split(" ")[0]
}
if (extraUrl.includes("#")) {
extraUrl = extraUrl.split("#")[0]
}
extraDescription = `${method} ${extraUrl}` extraDescription = `${method} ${extraUrl}`
} else {
console.log("No url found. Check again :)")
} }
} }
@@ -42,6 +42,7 @@ import data from '../frameworkStyle.jsx';
const liquidFilters = [ const liquidFilters = [
{"name": "Size", "value": "size", "example": ""}, {"name": "Size", "value": "size", "example": ""},
{"name": "Date", "value": `date: "%Y%M%d"`, "example": `{{ "now" | date: "%s" }}`}, {"name": "Date", "value": `date: "%Y%M%d"`, "example": `{{ "now" | date: "%s" }}`},
{"name": "Escape String", "value": `{{ \"\"\"'string with weird'" quotes\"\"\" | escape_string }}`, "example": ``},
] ]
const mathFilters = [ const mathFilters = [
@@ -51,7 +52,7 @@ const mathFilters = [
const pythonFilters = [ const pythonFilters = [
{"name": "Hello World", "value": `{% python %}\nprint("hello world")\n{% endpython %}`, "example": ``}, {"name": "Hello World", "value": `{% python %}\nprint("hello world")\n{% endpython %}`, "example": ``},
{"name": "Handle JSON", "value": `{% python %}\nimport json\njsondata = json.loads("""$nodename""")\n{% endpython %}`, "example": ``}, {"name": "Handle JSON", "value": `{% python %}\nimport json\njsondata = json.loads(r"""$nodename""")\n{% endpython %}`, "example": ``},
] ]
const CodeEditor = (props) => { const CodeEditor = (props) => {
@@ -354,7 +355,7 @@ const CodeEditor = (props) => {
return return
} }
if (!item.value.includes("{%")) { if (!item.value.includes("{%") && !item.value.includes("{{")) {
setlocalcodedata(localcodedata+" | "+item.value+" }}") setlocalcodedata(localcodedata+" | "+item.value+" }}")
} else { } else {
setlocalcodedata(localcodedata+item.value) setlocalcodedata(localcodedata+item.value)
@@ -610,7 +611,7 @@ const CodeEditor = (props) => {
}} }}
/> />
</span> </span>
{editorPopupOpen ? {/*editorPopupOpen ?
<Paper <Paper
style={{ style={{
margin: 10, margin: 10,
@@ -645,13 +646,12 @@ const CodeEditor = (props) => {
}} }}
> >
{data.substring(0, 25)} {data.substring(0, 25)}
{/* {Object.keys(data.example).forEach(key => key)} */}
</button> </button>
</div> </div>
) )
})} })}
</Paper> </Paper>
: null} : null*/}
<div <div
style={{ style={{
+119 -109
View File
@@ -1120,6 +1120,9 @@ const AngularWorkflow = (defaultprops) => {
} }
curworkflowTrigger.position = cyelements[key].position(); curworkflowTrigger.position = cyelements[key].position();
if (curworkflowTrigger.canConnect === false) {
continue
}
newTriggers.push(curworkflowTrigger); newTriggers.push(curworkflowTrigger);
} else if (type === "COMMENT") { } else if (type === "COMMENT") {
@@ -7055,8 +7058,10 @@ const AngularWorkflow = (defaultprops) => {
} }
var currentedge = cy.getElementById(selectedEdge.id); var currentedge = cy.getElementById(selectedEdge.id);
if (currentedge !== undefined && currentedge !== null) { if (currentedge !== undefined && currentedge !== null && label !== undefined) {
currentedge.data().label = label; currentedge.data("label", label)
//.label = label;
//oldstartnode[0].data("isStartNode", false);
} }
setSelectedEdge(selectedEdge); setSelectedEdge(selectedEdge);
@@ -11431,114 +11436,114 @@ const AngularWorkflow = (defaultprops) => {
<HandleLeftView /> <HandleLeftView />
</div> </div>
) : ( ) : (
<div <div
style={{ style={{
minWidth: leftBarSize, minWidth: leftBarSize,
maxWidth: leftBarSize, maxWidth: leftBarSize,
borderRight: "1px solid rgb(91, 96, 100)", borderRight: "1px solid rgb(91, 96, 100)",
}} }}
> >
<div <div
style={{ cursor: "pointer", height: 20, marginTop: 10, marginLeft: 10 }} style={{ cursor: "pointer", height: 20, marginTop: 10, marginLeft: 10 }}
onClick={() => { onClick={() => {
setLeftViewOpen(true); setLeftViewOpen(true);
setLeftBarSize(350); setLeftBarSize(350);
}} }}
> >
<Tooltip color="primary" title="Maximize" placement="top"> <Tooltip color="primary" title="Maximize" placement="top">
<KeyboardArrowRightIcon /> <KeyboardArrowRightIcon />
</Tooltip> </Tooltip>
</div>
</div>
);
const executionPaperStyle = {
minWidth: "95%",
maxWidth: "95%",
marginTop: "5px",
color: "white",
marginBottom: 10,
padding: 5,
backgroundColor: surfaceColor,
cursor: "pointer",
display: "flex",
minHeight: 40,
maxHeight: 40,
};
const parsedExecutionArgument = () => {
var showResult = executionData.execution_argument.trim();
const validate = validateJson(showResult);
if (validate.valid) {
if (typeof validate.result === "string") {
try {
validate.result = JSON.parse(validate.result);
} catch (e) {
console.log("Error: ", e);
validate.valid = false;
}
}
return (
<div style={{display: "flex"}}>
<IconButton
style={{
marginTop: "auto",
marginBottom: "auto",
height: 30,
paddingLeft: 0,
width: 30,
}}
onClick={() => {
setSelectedResult({
"action": {
"label": "Execution Argument",
"name": "Execution Argument",
"large_image": theme.palette.defaultImage,
"image": theme.palette.defaultImage,
},
"result": validate.valid ? JSON.stringify(validate.result) : validate.result,
"status": "SUCCESS"
})
setCodeModalOpen(true);
}}
>
<Tooltip
color="primary"
title="Expand result window"
placement="top"
style={{ zIndex: 10011 }}
>
<ArrowLeftIcon style={{ color: "white" }} />
</Tooltip>
</IconButton>
<ReactJson
src={validate.result}
theme={theme.palette.jsonTheme}
style={theme.palette.reactJsonStyle}
collapsed={true}
enableClipboard={(copy) => {
handleReactJsonClipboard(copy);
}}
displayDataTypes={false}
onSelect={(select) => {
HandleJsonCopy(validate.result, select, "exec");
}}
name={"Execution Argument"}
/>
</div> </div>
) </div>
} );
return ( const executionPaperStyle = {
<div> minWidth: "95%",
<h3>Execution Argument</h3> maxWidth: "95%",
<div style={{ maxHeight: 200, overflowY: "auto" }}> marginTop: "5px",
{executionData.execution_argument} color: "white",
</div> marginBottom: 10,
</div> padding: 5,
); backgroundColor: surfaceColor,
cursor: "pointer",
display: "flex",
minHeight: 40,
maxHeight: 40,
};
const parsedExecutionArgument = () => {
var showResult = executionData.execution_argument.trim();
const validate = validateJson(showResult);
if (validate.valid) {
if (typeof validate.result === "string") {
try {
validate.result = JSON.parse(validate.result);
} catch (e) {
console.log("Error: ", e);
validate.valid = false;
}
}
return (
<div style={{display: "flex"}}>
<IconButton
style={{
marginTop: "auto",
marginBottom: "auto",
height: 30,
paddingLeft: 0,
width: 30,
}}
onClick={() => {
setSelectedResult({
"action": {
"label": "Execution Argument",
"name": "Execution Argument",
"large_image": theme.palette.defaultImage,
"image": theme.palette.defaultImage,
},
"result": validate.valid ? JSON.stringify(validate.result) : validate.result,
"status": "SUCCESS"
})
setCodeModalOpen(true);
}}
>
<Tooltip
color="primary"
title="Expand result window"
placement="top"
style={{ zIndex: 10011 }}
>
<ArrowLeftIcon style={{ color: "white" }} />
</Tooltip>
</IconButton>
<ReactJson
src={validate.result}
theme={theme.palette.jsonTheme}
style={theme.palette.reactJsonStyle}
collapsed={true}
enableClipboard={(copy) => {
handleReactJsonClipboard(copy);
}}
displayDataTypes={false}
onSelect={(select) => {
HandleJsonCopy(validate.result, select, "exec");
}}
name={"Execution Argument"}
/>
</div>
)
}
return (
<div>
<h3>Execution Argument</h3>
<div style={{ maxHeight: 200, overflowY: "auto" }}>
{executionData.execution_argument}
</div>
</div>
);
}; };
const getExecutionSourceImage = (execution) => { const getExecutionSourceImage = (execution) => {
@@ -12173,7 +12178,12 @@ const parsedExecutionArgument = () => {
executionData.execution_argument, executionData.execution_argument,
executionData.start, executionData.start,
lastSaved lastSaved
); )
if (executionText === undefined || executionText === null || executionText.length === 0) {
setExecutionText(executionData.execution_argument)
}
setExecutionModalOpen(false); setExecutionModalOpen(false);
}} }}
> >
+70 -60
View File
@@ -1814,6 +1814,10 @@ const AppCreator = (defaultprops) => {
for (var querykey in item.queries) { for (var querykey in item.queries) {
const queryitem = item.queries[querykey]; const queryitem = item.queries[querykey];
if (queryitem === undefined || queryitem === null || queryitem.name === undefined || queryitem.name === null) {
continue
}
// A fix for duplicate items // A fix for duplicate items
if (querynames.includes(queryitem.name.toLowerCase())) { if (querynames.includes(queryitem.name.toLowerCase())) {
continue continue
@@ -1967,70 +1971,76 @@ const AppCreator = (defaultprops) => {
} }
} }
if ( const methodname = item.method.toLowerCase()
item.body !== undefined && if (methodname === "post" || methodname === "put" || methodname === "patch") {
item.body !== null && if (
item.body.length > 0 item.body !== undefined &&
) { item.body !== null &&
const required = false; item.body.length > 0
newitem = { ) {
in: "body", console.log("GOT BODY: ", item.url, item.method)
name: "body", //var pathjoin = item.url+"_"+item.method.toLowerCase()
multiline: true,
description: "Generated by shuffler.io OpenAPI",
required: required,
example: item.body,
schema: {
type: "string",
},
};
// FIXME - add application/json if JSON example? const required = false;
data.paths[item.url][item.method.toLowerCase()]["requestBody"] = { newitem = {
description: "Generated by Shuffler.io", in: "body",
required: required, name: "body",
content: { multiline: true,
example: { description: "Generated by shuffler.io OpenAPI",
example: item.body, required: required,
}, example: item.body,
}, schema: {
}; type: "string",
},
};
data.paths[item.url][item.method.toLowerCase()].parameters.push( // FIXME - add application/json if JSON example?
newitem data.paths[item.url][item.method.toLowerCase()]["requestBody"] = {
); description: "Generated by Shuffler.io",
} else if (actionBodyRequest.includes(item.method.toUpperCase())) { required: required,
// Appending an empty field content: {
const required = false; example: {
newitem = { example: item.body,
in: "body", },
name: "body", },
multiline: true, };
description: "Generated by shuffler.io OpenAPI",
required: required,
example: "",
schema: {
type: "string",
},
};
// FIXME - add application/json if JSON example? data.paths[item.url][item.method.toLowerCase()].parameters.push(
data.paths[item.url][item.method.toLowerCase()]["requestBody"] = { newitem
description: "Generated by Shuffler.io", );
required: required, } else if (actionBodyRequest.includes(item.method.toUpperCase())) {
content: { // Appending an empty field
example: { const required = false;
example: "", newitem = {
}, in: "body",
}, name: "body",
}; multiline: true,
description: "Generated by shuffler.io OpenAPI",
required: required,
example: "",
schema: {
type: "string",
},
};
data.paths[item.url][item.method.toLowerCase()].parameters.push( // FIXME - add application/json if JSON example?
newitem data.paths[item.url][item.method.toLowerCase()]["requestBody"] = {
); description: "Generated by Shuffler.io",
} else { required: required,
//console.log("Nothing to append?") content: {
} example: {
example: "",
},
},
};
data.paths[item.url][item.method.toLowerCase()].parameters.push(
newitem
);
} else {
//console.log("Nothing to append?")
}
}
// https://swagger.io/docs/specification/describing-request-body/file-upload/ // https://swagger.io/docs/specification/describing-request-body/file-upload/
if ( if (
+18 -9
View File
@@ -8,7 +8,6 @@ import SecurityFramework from '../components/SecurityFramework.jsx';
import { ShepherdTour, ShepherdTourContext } from 'react-shepherd' import { ShepherdTour, ShepherdTourContext } from 'react-shepherd'
import { isMobile } from "react-device-detect" import { isMobile } from "react-device-detect"
import { import {
Badge, Badge,
Avatar, Avatar,
@@ -88,6 +87,7 @@ import { useAlert } from "react-alert";
import ChipInput from "material-ui-chip-input"; import ChipInput from "material-ui-chip-input";
import { v4 as uuidv4 } from "uuid"; import { v4 as uuidv4 } from "uuid";
const inputColor = "#383B40"; const inputColor = "#383B40";
const surfaceColor = "#27292D"; const surfaceColor = "#27292D";
const svgSize = 24; const svgSize = 24;
@@ -133,8 +133,8 @@ export const GetIconInfo = (action) => {
const iconList = [ const iconList = [
{ key: "cache_add", values: ["set_cache"] }, { key: "cache_add", values: ["set_cache"] },
{ key: "cache_get", values: ["get_cache"] }, { key: "cache_get", values: ["get_cache"] },
{ key: "filter", values: ["filter", "route", "router"] }, { key: "filter", values: ["filter"] },
{ key: "merge", values: ["join", "merge"] }, { key: "merge", values: ["join", "merge", "route", "router"] },
{ {
key: "search", key: "search",
values: ["search", "find", "locate", "index", "analyze", "anal", "match", "check cache", "check", "verify", "validate"], values: ["search", "find", "locate", "index", "analyze", "anal", "match", "check cache", "check", "verify", "validate"],
@@ -412,6 +412,7 @@ export const validateJson = (showResult) => {
jsonvalid = false jsonvalid = false
} }
} catch (e) { } catch (e) {
console.log("Bug1: ", e)
showResult = showResult.split("'").join('"'); showResult = showResult.split("'").join('"');
try { try {
@@ -419,14 +420,17 @@ export const validateJson = (showResult) => {
jsonvalid = false; jsonvalid = false;
} }
} catch (e) { } catch (e) {
console.log("Bug2: ", e)
jsonvalid = false; jsonvalid = false;
} }
} }
var result = showResult; var result = showResult;
try { try {
result = jsonvalid ? JSON.parse(showResult) : showResult; result = jsonvalid ? JSON.parse(showResult, {"storeAsString": true}) : showResult;
} catch (e) { } catch (e) {
console.log("Bug3: ", e)
////console.log("Failed parsing JSON even though its valid: ", e) ////console.log("Failed parsing JSON even though its valid: ", e)
jsonvalid = false; jsonvalid = false;
} }
@@ -444,6 +448,7 @@ export const validateJson = (showResult) => {
result = JSON.parse(newstr) result = JSON.parse(newstr)
jsonvalid = true jsonvalid = true
} catch (e) { } catch (e) {
console.log("Bug4: ", e)
//console.log("Failed parsing JSON even though its valid (2): ", e) //console.log("Failed parsing JSON even though its valid (2): ", e)
jsonvalid = false jsonvalid = false
@@ -477,7 +482,6 @@ export const validateJson = (showResult) => {
} }
} }
//console.log("VALID: ", jsonvalid, result, typeof result)
return { return {
valid: jsonvalid, valid: jsonvalid,
result: result, result: result,
@@ -1116,10 +1120,15 @@ const Workflows = (props) => {
justifyContent: "space-between", justifyContent: "space-between",
}; };
const exportAllWorkflows = () => { const exportAllWorkflows = (allWorkflows) => {
for (var key in workflows) { for (var i = 0; i < allWorkflows.length; i++) {
exportWorkflow(workflows[key], false); setTimeout(() => {
console.log(workflows[i].name)
exportWorkflow(workflows[i], false)
}, i * 200);
} }
alert.info(`exporting and keeping original for all ${workflows.length} workflows`);
}; };
const deduplicateIds = (data) => { const deduplicateIds = (data) => {
@@ -2811,7 +2820,7 @@ const Workflows = (props) => {
style={{}} style={{}}
variant="text" variant="text"
onClick={() => { onClick={() => {
exportAllWorkflows(); exportAllWorkflows(workflows);
}} }}
> >
<GetAppIcon /> <GetAppIcon />