#133: Added first part of example and body parser
This commit is contained in:
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user