#133: Added first part of example and body parser

This commit is contained in:
frikky
2020-12-07 16:05:30 +01:00
parent b13c3f3765
commit 6ae79cc87d
2 changed files with 215 additions and 17 deletions
+72 -4
View File
@@ -845,7 +845,7 @@ const AngularWorkflow = (props) => {
return response.json()
})
.then((responseJson) => {
.then((responseJson) => {
// FIXME - handle versions on left bar
//handleAppVersioning(responseJson)
//var tmpapps = []
@@ -2872,8 +2872,64 @@ const AngularWorkflow = (props) => {
placeholder = data.example
}
var disabled = false
var rows = "5"
var openApiHelperText = "This is an OpenAPI specific field"
if (selectedApp.generated && selectedApp.activated && data.name === "body") {
const regex = /\${(\w+)}/g
const found = placeholder.match(regex)
console.log("THERE MAY BE THINGS INSIDE THE BODY, NO: ", found)
if (found === null) {
//setExtraBodyFields([])
} else {
rows = "1"
disabled = true
openApiHelperText = "OpenAPI spec: fill the following fields."
console.log("SHOULD ADD TO selectedActionParameters!: ", found, selectedActionParameters)
var changed = false
for (var specKey in found) {
const tmpitem = found[specKey]
var skip = false
for (var innerkey in selectedActionParameters) {
if (selectedActionParameters[innerkey].name === tmpitem) {
skip = true
break
}
}
if (skip) {
console.log("SKIPPING ", tmpitem)
continue
}
changed = true
selectedActionParameters.push({
action_field: "",
configuration: false,
description: "Generated by OpenAPI body example",
example: "",
id: "",
multiline: false,
name: tmpitem,
options: null,
required: false,
schema: {type: "string"},
skip_multicheck: false,
tags: null,
value: "",
variant: "STATIC_VALUE",
})
}
if (changed) {
setSelectedActionParameters(selectedActionParameters)
}
}
}
var datafield =
<TextField
disabled={disabled}
style={{backgroundColor: inputColor, borderRadius: borderRadius,}}
InputProps={{
style:{
@@ -2901,7 +2957,7 @@ const AngularWorkflow = (props) => {
}}
fullWidth
multiline={multiline}
rows="5"
rows={rows}
color="primary"
defaultValue={data.value}
type={placeholder.includes("***") ? "password" : "text"}
@@ -2909,6 +2965,13 @@ const AngularWorkflow = (props) => {
onChange={(event) => {
changeActionParameter(event, count)
}}
helperText={selectedApp.generated && selectedApp.activated && data.name === "body" ?
<span style={{color:"white", marginBottom: 5,}}>
{openApiHelperText}
</span>
:
null
}
onBlur={(event) => {
// Super basic check
//if (event.target.value.startsWith("{")) {
@@ -3303,7 +3366,7 @@ const AngularWorkflow = (props) => {
<div style={{width: 17, height: 17, borderRadius: 17 / 2, backgroundColor: itemColor, marginRight: 10}}/>
}
<div style={{flex: "10"}}>
<b>{data.name} </b>
<b>{data.name.charAt(0).toUpperCase()+data.name.substring(1)} </b>
</div>
{selectedActionParameters[count].options !== undefined && selectedActionParameters[count].options !== null && selectedActionParameters[count].options.length > 0 ? null :
@@ -3685,7 +3748,7 @@ const AngularWorkflow = (props) => {
{selectedAction.description}
</div> : null}
<div style={{marginTop: "10px", borderColor: "white", borderWidth: "2px", marginBottom: 200}}>
<AppActionArguments key={selectedAction.id} selectedAction={selectedAction} />
<AppActionArguments key={selectedAction.id} selectedAction={selectedAction} />
</div>
<div style={{}}>
@@ -6253,6 +6316,11 @@ const AngularWorkflow = (props) => {
getAppAuthentication()
setUpdate(authenticationOption.id)
/*
{selectedAction.authentication.map(data => (
<MenuItem key={data.id} style={{backgroundColor: inputColor, color: "white"}} value={data}>
*/
}
return (
+143 -13
View File
@@ -4,6 +4,7 @@ import {BrowserView, MobileView} from "react-device-detect";
import {Link} from 'react-router-dom';
import Paper from '@material-ui/core/Paper';
import Typography from '@material-ui/core/Typography';
import FormControlLabel from '@material-ui/core/FormControlLabel';
import Button from '@material-ui/core/Button';
import Divider from '@material-ui/core/Divider';
@@ -218,6 +219,7 @@ const AppCreator = (props) => {
const [actions, setActions] = useState([])
const [errorCode, setErrorCode] = useState("")
const [appBuilding, setAppBuilding] = useState(false)
const [extraBodyFields, setExtraBodyFields] = useState([])
//const [actions, setActions] = useState([{
// "name": "Get workflows",
@@ -253,6 +255,7 @@ const AppCreator = (props) => {
"queries": [],
"body": "",
"errors": [],
"example_response": "",
"method": actionNonBodyRequest[0],
});
@@ -262,7 +265,7 @@ const AppCreator = (props) => {
if (firstrequest) {
setFirstrequest(false)
if (window.location.pathname.includes("apps/edit")) {
setIsEditing(true)
setIsEditing(true)
handleEditApp()
} else {
checkQuery()
@@ -433,6 +436,22 @@ const AppCreator = (props) => {
"paths": [],
"body": "",
"errors": [],
"example_response": "",
}
// HAHAHA wtf is this.
if (methodvalue.responses !== undefined) {
if (methodvalue.responses.default !== undefined) {
if (methodvalue.responses.default.content !== undefined) {
if (methodvalue.responses.default.content["text/plain"] !== undefined) {
if (methodvalue.responses.default.content["text/plain"]["schema"] !== undefined) {
if (methodvalue.responses.default.content["text/plain"]["schema"]["example"] !== undefined) {
newaction.example_response = methodvalue.responses.default.content["text/plain"]["schema"]["example"]
}
}
}
}
}
}
for (var key in methodvalue.parameters) {
@@ -469,6 +488,7 @@ const AppCreator = (props) => {
}
}
if (newaction.name === "" || newaction.name === undefined) {
// Find a unique part of the string
// FIXME: Looks for length between /, find the one where they differ
@@ -668,7 +688,14 @@ const AppCreator = (props) => {
"responses": {
"default": {
"description": "default",
"schema": {}
"content": {
"text/plain": {
"schema": {
"type": "string",
"example": "",
},
},
},
}
},
"summary": item.name,
@@ -679,6 +706,35 @@ const AppCreator = (props) => {
//console.log("ACTION: ", item)
if (item.example_response !== undefined && item.example_response.length > 0) {
// FIXME: Shallow copy of the string
var showResult = Object.assign("", item.example_response).trim()
showResult = showResult.split(" None").join(" \"None\"")
showResult = showResult.split("\'").join("\"")
showResult = showResult.split(" False").join(" false")
showResult = showResult.split(" True").join(" true")
var jsonvalid = true
try {
const tmp = String(JSON.parse(showResult))
if (!showResult.includes("{") && !showResult.includes("[")) {
jsonvalid = false
}
} catch (e) {
jsonvalid = false
}
data.paths[item.url][item.method.toLowerCase()].responses["default"]["content"]["text/plain"].schema.type = "string"
if (jsonvalid) {
// FIXME: Add a JSON parser here - don't run it as a string.
data.paths[item.url][item.method.toLowerCase()].responses["default"]["content"]["text/plain"].schema.example = showResult
} else {
data.paths[item.url][item.method.toLowerCase()].responses["default"]["content"]["text/plain"].schema.example = item.example_response
}
}
if (item.queries.length > 0) {
for (var querykey in item.queries) {
const queryitem = item.queries[querykey]
@@ -761,7 +817,7 @@ const AppCreator = (props) => {
"type": "string",
},
}
// FIXME - add application/json if JSON example?
data.paths[item.url][item.method.toLowerCase()]["requestBody"] = {
"description": "Generated by Shuffler.io",
@@ -773,6 +829,18 @@ const AppCreator = (props) => {
},
}
/*
data.paths[item.url][item.method.toLowerCase()]["requestBody"] = {
"description": "Generated by Shuffler.io",
"required": required,
"content": {
"example": {
"example": item.body,
},
},
}
*/
data.paths[item.url][item.method.toLowerCase()].parameters.push(newitem)
}
@@ -782,7 +850,6 @@ const AppCreator = (props) => {
const headersSplit = item.headers.split("\n")
for (var key in headersSplit) {
const header = headersSplit[key]
console.log("HEADER: ", header)
var key = ""
var value = ""
if (header.length > 0 && header.includes("= ")) {
@@ -1137,12 +1204,15 @@ const AppCreator = (props) => {
setUrlPathQueries(data.queries)
setUrlPath(data.url)
setActionsModalOpen(true)
if (data["body"] !== undefined && data["body"] !== null && data["body"].length > 0) {
findBodyParams(data["body"])
}
}}>
<div style={{display: "flex"}}>
<Chip
style={{backgroundColor: bgColor, color: "white", borderRadius: 5, minWidth: 80, marginRight: 10, marginTop: 2, cursor: "pointer", fontSize: 14,}}
label={data.method}
variant="contained"
/>
<span style={{fontSize: 16, marginTop: "auto", marginBottom: "auto",}}>
{url} - {data.name}
@@ -1177,24 +1247,52 @@ const AppCreator = (props) => {
const setActionField = (field, value) => {
currentAction[field] = value
setCurrentAction(currentAction)
//setUrlPathQueries(currentAction.queries)
}
const findBodyParams = (body) => {
const regex = /\${(\w+)}/g
const found = body.match(regex)
console.log("FOUND: ", found)
if (found === null) {
setExtraBodyFields([])
} else {
setExtraBodyFields(found)
}
}
const bodyInfo = actionBodyRequest.includes(currentActionMethod) ?
<div>
Body - used as example in action argument
<div style={{marginTop: 10}}>
<b>Request Body</b>: {extraBodyFields.length > 0 ?
<Typography style={{display: "inline-block"}}>
Variables: {extraBodyFields.join(", ")}
</Typography>
:
<Typography style={{display: "inline-block"}}>
{`Add variables with \$\{ variable_name }`}
</Typography>
}
<TextField
required
style={{flex: "1", marginRight: "15px", backgroundColor: inputColor}}
fullWidth={true}
placeholder={'{\n\t"username": "testing@test.com"\n\t"name": "test testington"\n}'}
placeholder={'{\n\t"username": "${username}",\n\t"apikey": "${apikey}",\n\t"search": "1.2.3.5"}'}
margin="normal"
variant="outlined"
multiline
rows="5"
defaultValue={currentAction["body"]}
onChange={e => setActionField("body", e.target.value)}
onChange={e => {
setActionField("body", e.target.value)
findBodyParams(e.target.value)
}}
key={currentAction}
helperText={
<span style={{color:"white", marginBottom: "2px",}}>
Shows an example body to the user. ${} creates variables.
</span>
}
InputProps={{
classes: {
notchedOutline: classes.notchedOutline,
@@ -1205,9 +1303,40 @@ const AppCreator = (props) => {
}}
/>
<div>
</div>
</div>
: null
const exampleResponse =
<div style={{}}>
<b>Example success response</b>
<TextField
required
style={{flex: "1", marginRight: "15px", backgroundColor: inputColor}}
fullWidth={true}
placeholder={'{\n\t"email": "testing@test.com",\n\t"firstname": "testing"\n}'}
margin="normal"
variant="outlined"
multiline
rows="2"
defaultValue={currentAction["example_response"]}
onChange={e => setActionField("example_response", e.target.value)}
helperText={<span style={{color:"white", marginBottom: "2px",}}>
Helps with autocompletion and understanding of the endpoint
</span>}
key={currentAction}
InputProps={{
classes: {
notchedOutline: classes.notchedOutline,
},
style:{
color: "white",
},
}}
/>
</div>
const addActionToView = (errors) => {
currentAction.errors = errors
currentAction.queries = urlPathQueries
@@ -1361,7 +1490,6 @@ const AppCreator = (props) => {
open={actionsModalOpen}
fullWidth
onClose={() => {
console.log("CLOSED?")
setUrlPath("")
setCurrentAction({
"name": "",
@@ -1564,7 +1692,7 @@ const AppCreator = (props) => {
addPathQuery()
}}>New query</Button>
<div/>
Headers - static for the action
<b>Headers</b>: static for the action
<TextField
required
style={{flex: "1", marginRight: "15px", marginTop: "5px", backgroundColor: inputColor}}
@@ -1575,7 +1703,7 @@ const AppCreator = (props) => {
id="standard-required"
defaultValue={currentAction["headers"]}
multiline
rows="5"
rows="2"
onChange={e => setActionField("headers", e.target.value)}
helperText={<span style={{color:"white", marginBottom: "2px",}}>Headers that are part of the request. Default: EMPTY</span>}
InputProps={{
@@ -1588,6 +1716,8 @@ const AppCreator = (props) => {
}}
/>
{bodyInfo}
<Divider style={{backgroundColor: "rgba(255,255,255,0.5)", marginTop: 15, marginBottom: 15}} />
{exampleResponse}
</DialogContent>
<DialogActions>
<Button style={{borderRadius: "0px"}} onClick={() => {
@@ -1597,7 +1727,7 @@ const AppCreator = (props) => {
<Button color="primary" variant="outlined" style={{borderRadius: "0px"}} onClick={() => {
console.log(urlPathQueries)
console.log(urlPath)
// value={urlPath}
console.log(currentAction)
const errors = getActionErrors()
addActionToView(errors)
setActionsModalOpen(false)