Fixed action parser view for multiple locations

This commit is contained in:
frikky
2021-04-06 22:00:24 +02:00
parent 8112bd16c5
commit 6bdd84bdd9
4 changed files with 485 additions and 498 deletions
+254 -282
View File
@@ -1,18 +1,65 @@
import React, {useState, useEffect, useLayoutEffect} from 'react'; import React, {useState, useEffect, useLayoutEffect} from 'react';
import { useTheme } from '@material-ui/core/styles';
import { GetParsedPaths } from "../views/Apps.jsx"; import { GetParsedPaths } from "../views/Apps.jsx";
import { sortByKey } from "../views/AngularWorkflow.jsx";
import { useTheme } from '@material-ui/core/styles';
import NestedMenuItem from "material-ui-nested-menu-item"; import NestedMenuItem from "material-ui-nested-menu-item";
import {TextField, Drawer, Button, Paper, Grid, Tabs, InputAdornment, Tab, ButtonBase, Tooltip, Select, MenuItem, Divider, Dialog, Modal, DialogActions, DialogTitle, InputLabel, DialogContent, FormControl, IconButton, Menu, Input, FormGroup, FormControlLabel, Typography, Checkbox, Breadcrumbs, CircularProgress, Switch, Fade} from '@material-ui/core'; import {TextField, Drawer, Button, Paper, Grid, Tabs, InputAdornment, Tab, ButtonBase, Tooltip, Select, MenuItem, Divider, Dialog, Modal, DialogActions, DialogTitle, InputLabel, DialogContent, FormControl, IconButton, Menu, Input, FormGroup, FormControlLabel, Typography, Checkbox, Breadcrumbs, CircularProgress, Switch, Fade} from '@material-ui/core';
import {GetApp as GetAppIcon, Search as SearchIcon, ArrowUpward as ArrowUpwardIcon, Visibility as VisibilityIcon, Done as DoneIcon, Close as CloseIcon, Error as ErrorIcon, FindReplace as FindreplaceIcon, ArrowLeft as ArrowLeftIcon, Cached as CachedIcon, DirectionsRun as DirectionsRunIcon, Add as AddIcon, Polymer as PolymerIcon, FormatListNumbered as FormatListNumberedIcon, Create as CreateIcon, PlayArrow as PlayArrowIcon, AspectRatio as AspectRatioIcon, MoreVert as MoreVertIcon, Apps as AppsIcon, Schedule as ScheduleIcon, FavoriteBorder as FavoriteBorderIcon, Pause as PauseIcon, Delete as DeleteIcon, AddCircleOutline as AddCircleOutlineIcon, Save as SaveIcon, KeyboardArrowLeft as KeyboardArrowLeftIcon, KeyboardArrowRight as KeyboardArrowRightIcon, ArrowBack as ArrowBackIcon, Settings as SettingsIcon, LockOpen as LockOpenIcon, ExpandMore as ExpandMoreIcon, VpnKey as VpnKeyIcon} from '@material-ui/icons'; import {GetApp as GetAppIcon, Search as SearchIcon, ArrowUpward as ArrowUpwardIcon, Visibility as VisibilityIcon, Done as DoneIcon, Close as CloseIcon, Error as ErrorIcon, FindReplace as FindreplaceIcon, ArrowLeft as ArrowLeftIcon, Cached as CachedIcon, DirectionsRun as DirectionsRunIcon, Add as AddIcon, Polymer as PolymerIcon, FormatListNumbered as FormatListNumberedIcon, Create as CreateIcon, PlayArrow as PlayArrowIcon, AspectRatio as AspectRatioIcon, MoreVert as MoreVertIcon, Apps as AppsIcon, Schedule as ScheduleIcon, FavoriteBorder as FavoriteBorderIcon, Pause as PauseIcon, Delete as DeleteIcon, AddCircleOutline as AddCircleOutlineIcon, Save as SaveIcon, KeyboardArrowLeft as KeyboardArrowLeftIcon, KeyboardArrowRight as KeyboardArrowRightIcon, ArrowBack as ArrowBackIcon, Settings as SettingsIcon, LockOpen as LockOpenIcon, ExpandMore as ExpandMoreIcon, VpnKey as VpnKeyIcon} from '@material-ui/icons';
const ParsedAction = (props) => { const ParsedAction = (props) => {
const {workflow, setWorkflow, setAction, setSelectedAction, setUpdate, appActionArguments, selectedApp, workflowExecutions, setSelectedResult, selectedAction, getParents, setSelectedApp, setSelectedTrigger, setSelectedEdge, setCurrentView, cy, setAuthenticationModalOpen,setVariablesModalOpen, setLastSaved, setCodeModalOpen, selectedNameChange, rightsidebarStyle, showEnvironment, selectedActionEnvironment, environments, setNewSelectedAction, sortByKey, appApiViewStyle, globalUrl, setSelectedActionEnvironment, requiresAuthentication } = props const {workflow, setWorkflow, setAction, setSelectedAction, setUpdate, appActionArguments, selectedApp, workflowExecutions, setSelectedResult, selectedAction, setSelectedApp, setSelectedTrigger, setSelectedEdge, setCurrentView, cy, setAuthenticationModalOpen,setVariablesModalOpen, setCodeModalOpen, selectedNameChange, rightsidebarStyle, showEnvironment, selectedActionEnvironment, environments, setNewSelectedAction, appApiViewStyle, globalUrl, setSelectedActionEnvironment, requiresAuthentication, hideExtraTypes } = props
const theme = useTheme(); const theme = useTheme();
const getParents = (action) => {
if (cy === undefined) {
return []
}
var allkeys = [action.id]
var handled = []
var results = []
while(true) {
for (var key in allkeys) {
var currentnode = cy.getElementById(allkeys[key])
if (handled.includes(currentnode.data().id)) {
continue
} else {
// Get the name / label here too?
handled.push(currentnode.data().id)
results.push(currentnode.data())
}
if (currentnode.length === 0) {
continue
}
const incomingEdges = currentnode.incomers('edge')
if (incomingEdges.length === 0) {
continue
}
for (var i = 0; i < incomingEdges.length; i++) {
var tmp = incomingEdges[i]
if (!allkeys.includes(tmp.data().source)) {
allkeys.push(tmp.data().source)
}
}
}
if (results.length === allkeys.length) {
break
}
}
// Remove self
results = results.filter(data => data.id !== action.id)
results = results.filter(data => data.type !== "TRIGGER")
results.push({"label": "Execution Argument", "type": "INTERNAL"})
return results
}
const getApp = (appId, setApp) => { const getApp = (appId, setApp) => {
fetch(globalUrl+"/api/v1/apps/"+appId+"/config?openapi=false", { fetch(globalUrl+"/api/v1/apps/"+appId+"/config?openapi=false", {
@@ -71,6 +118,10 @@ const ParsedAction = (props) => {
} }
const defineStartnode = () => { const defineStartnode = () => {
if (cy === undefined) {
return
}
var oldstartnode = cy.getElementById(workflow.start) var oldstartnode = cy.getElementById(workflow.start)
if (oldstartnode.length > 0) { if (oldstartnode.length > 0) {
oldstartnode[0].data("isStartNode", false) oldstartnode[0].data("isStartNode", false)
@@ -405,9 +456,12 @@ const ParsedAction = (props) => {
// This is a stupid workaround to make it refresh rofl // This is a stupid workaround to make it refresh rofl
setSelectedAction({}) setSelectedAction({})
setSelectedTrigger({})
setSelectedApp({}) if (setSelectedTrigger !== undefined) {
setSelectedEdge({}) setSelectedTrigger({})
setSelectedApp({})
setSelectedEdge({})
}
// FIXME - check if startnode // FIXME - check if startnode
// Set value // Set value
@@ -419,7 +473,7 @@ const ParsedAction = (props) => {
// FIXME: Issue #40 - selectedActionParameters not reset // FIXME: Issue #40 - selectedActionParameters not reset
if (Object.getOwnPropertyNames(selectedAction).length > 0 && selectedActionParameters.length > 0) { if (Object.getOwnPropertyNames(selectedAction).length > 0 && selectedActionParameters.length > 0) {
return ( return (
<div style={{marginTop: "30px"}}> <div style={{marginTop: hideExtraTypes ? 10 : 30}}>
<b>Parameters</b> <b>Parameters</b>
{selectedActionParameters.map((data, count) => { {selectedActionParameters.map((data, count) => {
if (data.variant === "") { if (data.variant === "") {
@@ -539,19 +593,21 @@ const ParsedAction = (props) => {
fontSize: "1em", fontSize: "1em",
}, },
endAdornment: ( endAdornment: (
<InputAdornment position="end"> hideExtraTypes ? null :
<Tooltip title="Autocomplete text" placement="top"> <InputAdornment position="end">
<AddCircleOutlineIcon style={{cursor: "pointer"}} onClick={(event) => { <Tooltip title="Autocomplete text" placement="top">
setMenuPosition({ <AddCircleOutlineIcon style={{cursor: "pointer"}} onClick={(event) => {
top: event.pageY+10, setMenuPosition({
left: event.pageX+10, top: event.pageY+10,
}) left: event.pageX+10,
setShowDropdownNumber(count) })
setShowDropdown(true) setShowDropdownNumber(count)
setShowAutocomplete(true) setShowDropdown(true)
}}/> setShowAutocomplete(true)
</Tooltip> }}/>
</InputAdornment> </Tooltip>
</InputAdornment>
) )
}} }}
fullWidth fullWidth
@@ -559,7 +615,7 @@ const ParsedAction = (props) => {
rows={rows} rows={rows}
color="primary" color="primary"
defaultValue={data.value} defaultValue={data.value}
type={placeholder.includes("***") ? "password" : "text"} type={placeholder.includes("***") || (data.configuration && (data.name.toLowerCase().includes("api") || data.name.toLowerCase().includes("key") || data.name.toLowerCase().includes("pass"))) ? "password" : "text"}
placeholder={placeholder} placeholder={placeholder}
onChange={(event) => { onChange={(event) => {
changeActionParameter(event, count, data) changeActionParameter(event, count, data)
@@ -602,19 +658,20 @@ const ParsedAction = (props) => {
fontSize: "1em", fontSize: "1em",
}, },
endAdornment: ( endAdornment: (
<InputAdornment position="end"> hideExtraTypes ? null :
<Tooltip title="Autocomplete text" placement="top"> <InputAdornment position="end">
<AddCircleOutlineIcon style={{cursor: "pointer"}} onClick={(event) => { <Tooltip title="Autocomplete text" placement="top">
setMenuPosition({ <AddCircleOutlineIcon style={{cursor: "pointer"}} onClick={(event) => {
top: event.pageY+10, setMenuPosition({
left: event.pageX+10, top: event.pageY+10,
}) left: event.pageX+10,
setShowDropdownNumber(count) })
setShowDropdown(true) setShowDropdownNumber(count)
setShowAutocomplete(true) setShowDropdown(true)
}}/> setShowAutocomplete(true)
</Tooltip> }}/>
</InputAdornment> </Tooltip>
</InputAdornment>
) )
}} }}
fullWidth fullWidth
@@ -684,106 +741,6 @@ const ParsedAction = (props) => {
} else if (data.variant === "STATIC_VALUE") { } else if (data.variant === "STATIC_VALUE") {
staticcolor = "#f85a3e" staticcolor = "#f85a3e"
} else if (data.variant === "ACTION_RESULT") {
// Gets the parents of the current node
var parents = getParents(selectedAction)
actioncolor = "#f85a3e"
// set the datafield
//var datafieldvalue = "Error: No parents. Action not eligible"
//if (parents.length > 0) {
// datafieldvalue = parents[0].label
//}
const fixedActionText = selectedActionParameters[count].value
datafield =
<div>
<Select
SelectDisplayProps={{
style: {
marginLeft: 10,
}
}}
value={selectedActionParameters[count].action_field}
fullWidth
onChange={(e) => {
changeActionParameterActionResult(e.target.value, count)
}}
style={{backgroundColor: theme.palette.surfaceColor, color: "white", height: "50px"}}
>
{parents.map(data => (
<MenuItem key={data.label} style={{backgroundColor: theme.palette.inputColor, color: "white"}} value={data.label}>
{data.label}
</MenuItem>
))}
</Select>
<TextField
style={{backgroundColor: theme.palette.inputColor, borderRadius: theme.palette.borderRadius,}}
InputProps={{
style:{
color: "white",
marginLeft: "5px",
maxWidth: "95%",
height: 50,
fontSize: "1em",
},
}}
fullWidth
color="primary"
defaultValue={data.value}
helperText={<div style={{marginLeft: "5px", color:"white", marginBottom: "2px",}}>Example: $.body will get "data" from {'{"body": "data"}'}</div>}
placeholder="Action variable ($.)"
onChange={(event) => {
changeActionParameter(event, count, data)
}}
/>
</div>
} else if (data.variant === "WORKFLOW_VARIABLE") {
varcolor = "#f85a3e"
if ((workflow.workflow_variables === null || workflow.workflow_variables === undefined || workflow.workflow_variables.length === 0) && (workflow.execution_variables === null || workflow.execution_variables === undefined || workflow.execution_variables.length === 0)) {
setCurrentView(2)
datafield =
<div>
<div>
Looks like you don't have any variables yet.
</div>
<div style={{width: "100%", margin: "auto"}}>
<Button style={{margin: "auto", marginTop: "10px"}} color="primary" variant="outlined" onClick={() => {
setVariablesModalOpen(true)
setLastSaved(false)
}}>New workflow variable</Button>
</div>
</div>
} else {
// FIXME - this is a shitty solution that needs re-renders all the time
datafield =
<Select
SelectDisplayProps={{
style: {
marginLeft: 10,
}
}}
fullWidth
value={selectedAction.parameters[count].action_field}
onChange={(e) => {
console.log(e.target.value)
changeActionParameterVariable(e.target.value, count)
}}
style={{backgroundColor: theme.palette.inputColor, color: "white", height: "50px"}}
>
{workflow.workflow_variables !== undefined && workflow.workflow_variables !== null ? workflow.workflow_variables.map(data => (
<MenuItem style={{backgroundColor: theme.palette.inputColor, color: "white"}} value={data.name}>
{data.name}
</MenuItem>
)) : null}
<Divider />
{workflow.execution_variables !== undefined && workflow.execution_variables !== null ? workflow.execution_variables.map(data => (
<MenuItem style={{backgroundColor: theme.palette.inputColor, color: "white"}} value={data.name}>
{data.name}
</MenuItem>
)) : null}
</Select>
}
} }
// Shows nested list of nodes > their JSON lists // Shows nested list of nodes > their JSON lists
@@ -894,26 +851,29 @@ const ParsedAction = (props) => {
for (var key in workflow.triggers) { for (var key in workflow.triggers) {
const item = workflow.triggers[key] const item = workflow.triggers[key]
var node = cy.getElementById(item.id) if (cy !== undefined) {
if (node.length > 0) { var node = cy.getElementById(item.id)
if (inside) { if (node.length > 0) {
node.addClass('shuffle-hover-highlight') if (inside) {
} else { node.addClass('shuffle-hover-highlight')
node.removeClass('shuffle-hover-highlight') } else {
node.removeClass('shuffle-hover-highlight')
}
} }
} }
} }
} }
} }
const handleActionHover = (inside, actionId) => { const handleActionHover = (inside, actionId) => {
var node = cy.getElementById(actionId) if (cy !== undefined) {
if (node.length > 0) { var node = cy.getElementById(actionId)
if (inside) { if (node.length > 0) {
node.addClass('shuffle-hover-highlight') if (inside) {
} else { node.addClass('shuffle-hover-highlight')
node.removeClass('shuffle-hover-highlight') } else {
node.removeClass('shuffle-hover-highlight')
}
} }
} }
} }
@@ -1009,8 +969,6 @@ const ParsedAction = (props) => {
return ( return (
<div key={data.name}> <div key={data.name}>
<div style={{marginTop: 20, marginBottom: 0, display: "flex"}}> <div style={{marginTop: 20, marginBottom: 0, display: "flex"}}>
{data.configuration === true ? {data.configuration === true ?
<Tooltip color="primary" title={`Authenticate ${selectedApp.name}`} placement="top"> <Tooltip color="primary" title={`Authenticate ${selectedApp.name}`} placement="top">
<LockOpenIcon style={{cursor: "pointer", width: 24, height: 24, marginRight: 10, }} onClick={() => { <LockOpenIcon style={{cursor: "pointer", width: 24, height: 24, marginRight: 10, }} onClick={() => {
@@ -1056,7 +1014,7 @@ const ParsedAction = (props) => {
</Tooltip> </Tooltip>
</div> </div>
*/} */}
{selectedActionParameters[count].options !== undefined && selectedActionParameters[count].options !== null && selectedActionParameters[count].options.length > 0 && selectedActionParameters[count].required === true && selectedActionParameters[count].unique_toggled !== undefined ? null : {(selectedActionParameters[count].options !== undefined && selectedActionParameters[count].options !== null && selectedActionParameters[count].options.length > 0 && selectedActionParameters[count].required === true && selectedActionParameters[count].unique_toggled !== undefined) || hideExtraTypes ? null :
<div style={{display: "flex"}}> <div style={{display: "flex"}}>
<Tooltip color="primary" title="Value must be unique" placement="top"> <Tooltip color="primary" title="Value must be unique" placement="top">
<div style={{cursor: "pointer", color: staticcolor}} onClick={(e) => {}}> <div style={{cursor: "pointer", color: staticcolor}} onClick={(e) => {}}>
@@ -1150,99 +1108,106 @@ const ParsedAction = (props) => {
} }
return ( return (
<div style={appApiViewStyle}> <div style={appApiViewStyle}>
<div style={{display: "flex", minHeight: 40, marginBottom: 30}}> {hideExtraTypes === true ? null :
<div style={{flex: 1}}> <span>
<h3 style={{marginBottom: 5}}>{selectedAction.app_name.replaceAll("_", " ")}</h3> <div style={{display: "flex", minHeight: 40, marginBottom: 30}}>
<div style={{display: "flex",}}> <div style={{flex: 1}}>
<IconButton style={{marginTop: "auto", marginBottom: "auto", height: 30, paddingLeft: 0, paddingRight: 0}} onClick={() => { <h3 style={{marginBottom: 5}}>{selectedAction.app_name.replaceAll("_", " ")}</h3>
console.log("FIND EXAMPLE RESULTS FOR ", selectedAction) <div style={{display: "flex",}}>
if (workflowExecutions.length > 0) { <IconButton style={{marginTop: "auto", marginBottom: "auto", height: 30, paddingLeft: 0, paddingRight: 0}} onClick={() => {
// Look for the ID console.log("FIND EXAMPLE RESULTS FOR ", selectedAction)
const found = false if (workflowExecutions.length > 0) {
for (var key in workflowExecutions) { // Look for the ID
if (workflowExecutions[key].results === undefined || workflowExecutions[key].results === null) { const found = false
continue for (var key in workflowExecutions) {
} if (workflowExecutions[key].results === undefined || workflowExecutions[key].results === null) {
continue
}
var foundResult = workflowExecutions[key].results.find(result => result.action.id === selectedAction.id) var foundResult = workflowExecutions[key].results.find(result => result.action.id === selectedAction.id)
if (foundResult === undefined || foundResult === null) { if (foundResult === undefined || foundResult === null) {
continue continue
} }
setSelectedResult(foundResult) setSelectedResult(foundResult)
setCodeModalOpen(true)
break if (setCodeModalOpen !== undefined) {
setCodeModalOpen(true)
}
break
}
} }
} }}>
}}> <Tooltip color="primary" title="See previous results for this action" placement="top">
<Tooltip color="primary" title="See previous results for this action" placement="top"> <ArrowLeftIcon style={{color: "white"}}/>
<ArrowLeftIcon style={{color: "white"}}/> </Tooltip>
</IconButton>
<span style={{}}>
<Typography style={{marginTop: 5, marginLeft: 10,}}><a rel="norefferer" href="https://shuffler.io/docs/workflows#nodes" target="_blank" style={{textDecoration: "none", color: "#f85a3e"}}>What are actions?</a></Typography>
{selectedAction.errors !== undefined && selectedAction.errors !== null && selectedAction.errors.length > 0 ?
<div>
Errors: {selectedAction.errors.join("\n")}
</div>
: null
}
</span>
</div>
</div>
<div style={{display: "flex", flexDirection: "column",}}>
{selectedAction.id === workflow.start ? null :
<Tooltip color="primary" title={"Make this node the start action"} placement="top">
<Button style={{zIndex: 5000, marginTop: 10,}} color="primary" variant="outlined" onClick={(e) => {
defineStartnode(e)
}}>
<KeyboardArrowRightIcon />
</Button>
</Tooltip> </Tooltip>
</IconButton> }
<span style={{}}> {selectedApp.versions !== null && selectedApp.versions !== undefined && selectedApp.versions.length > 1 ?
<Typography style={{marginTop: 5, marginLeft: 10,}}><a rel="norefferer" href="https://shuffler.io/docs/workflows#nodes" target="_blank" style={{textDecoration: "none", color: "#f85a3e"}}>What are actions?</a></Typography> <Select
{selectedAction.errors !== null && selectedAction.errors.length > 0 ? defaultValue={selectedAction.app_version}
<div> onChange={(event) => {
Errors: {selectedAction.errors.join("\n")} const newversion = selectedApp.versions.find(tmpApp => tmpApp.version == event.target.value)
</div> if (newversion !== undefined && newversion !== null) {
: null getApp(newversion.id, true)
} }
</span> }}
style={{marginTop: 10, backgroundColor: theme.palette.surfaceColor, backgroundColor: theme.palette.inputColor, color: "white", height: 35, marginleft: 10,}}
SelectDisplayProps={{
style: {
marginLeft: 10,
}
}}
>
{selectedApp.versions.map((data, index) => {
return (
<MenuItem key={index} style={{backgroundColor: theme.palette.inputColor, color: "white"}} value={data.version}>
{data.version}
</MenuItem>
)
})}
</Select>
: null }
</div> </div>
</div> </div>
<div style={{display: "flex", flexDirection: "column",}}> <Divider style={{marginBottom: "10px", marginTop: "10px", height: "1px", width: "100%", backgroundColor: "rgb(91, 96, 100)"}}/>
{selectedAction.id === workflow.start ? null : <Typography>
<Tooltip color="primary" title={"Make this node the start action"} placement="top"> Name
<Button style={{zIndex: 5000, marginTop: 10,}} color="primary" variant="outlined" onClick={(e) => { </Typography>
defineStartnode(e) <TextField
}}> style={theme.palette.textFieldStyle}
<KeyboardArrowRightIcon /> InputProps={{
</Button> style: theme.palette.innerTextfieldStyle,
</Tooltip> }}
} fullWidth
{selectedApp.versions !== null && selectedApp.versions !== undefined && selectedApp.versions.length > 0 ? color="primary"
<Select placeholder={selectedAction.label}
defaultValue={selectedAction.app_version} onChange={selectedNameChange}
onChange={(event) => { />
const newversion = selectedApp.versions.find(tmpApp => tmpApp.version == event.target.value) </span>
if (newversion !== undefined && newversion !== null) { }
getApp(newversion.id, true) {selectedApp.name !== undefined && selectedAction.authentication !== null && selectedAction.authentication !== undefined && selectedAction.authentication.length === 0 && requiresAuthentication ?
}
}}
style={{marginTop: 10, backgroundColor: theme.palette.theme.palette.surfaceColor, backgroundColor: theme.palette.inputColor, color: "white", height: 35, marginleft: 10,}}
SelectDisplayProps={{
style: {
marginLeft: 10,
}
}}
>
{selectedApp.versions.map((data, index) => {
return (
<MenuItem key={index} style={{backgroundColor: theme.palette.inputColor, color: "white"}} value={data.version}>
{data.version}
</MenuItem>
)
})}
</Select>
: null }
</div>
</div>
<Divider style={{marginBottom: "10px", marginTop: "10px", height: "1px", width: "100%", backgroundColor: "rgb(91, 96, 100)"}}/>
<Typography>
Name
</Typography>
<TextField
style={theme.palette.textFieldStyle}
InputProps={{
style: theme.palette.innerTextfieldStyle,
}}
fullWidth
color="primary"
placeholder={selectedAction.label}
onChange={selectedNameChange}
/>
{selectedApp.name !== undefined && selectedAction.authentication !== undefined && selectedAction.authentication.length === 0 && requiresAuthentication ?
<div style={{marginTop: 15}}> <div style={{marginTop: 15}}>
<Tooltip color="primary" title={"Add authentication option"} placement="top"> <Tooltip color="primary" title={"Add authentication option"} placement="top">
<span> <span>
@@ -1255,8 +1220,8 @@ const ParsedAction = (props) => {
</Tooltip> </Tooltip>
</div> </div>
: null} : null}
{selectedAction.authentication !== undefined && selectedAction.authentication.length > 0 ? {selectedAction.authentication !== undefined && selectedAction.authentication !== null && selectedAction.authentication.length > 0 ?
<div style={{marginTop: 20, overflow: "hidden",}}> <div style={{marginTop: 15, }}>
Authentication Authentication
<div style={{display: "flex"}}> <div style={{display: "flex"}}>
<Select <Select
@@ -1277,11 +1242,14 @@ const ParsedAction = (props) => {
}} }}
style={{backgroundColor: theme.palette.inputColor, color: "white", height: 50, maxWidth: rightsidebarStyle.maxWidth-80,}} style={{backgroundColor: theme.palette.inputColor, color: "white", height: 50, maxWidth: rightsidebarStyle.maxWidth-80,}}
> >
{selectedAction.authentication.map(data => ( {selectedAction.authentication.map(data => {
<MenuItem key={data.id} style={{backgroundColor: theme.palette.inputColor, color: "white"}} value={data}> console.log("DATA: ", data)
{data.label} - ({data.app.app_version}) return(
</MenuItem> <MenuItem key={data.id} style={{backgroundColor: theme.palette.inputColor, color: "white"}} value={data}>
))} {data.label} - ({data.app.app_version})
</MenuItem>
)
})}
</Select> </Select>
{/* {/*
@@ -1302,7 +1270,7 @@ const ParsedAction = (props) => {
</div> </div>
</div> </div>
: null} : null}
{showEnvironment ? {showEnvironment !== undefined && showEnvironment ?
<div style={{marginTop: "20px"}}> <div style={{marginTop: "20px"}}>
<Typography> <Typography>
Environment Environment
@@ -1375,46 +1343,50 @@ const ParsedAction = (props) => {
: null} : null}
<Divider style={{marginTop: "20px", height: "1px", width: "100%", backgroundColor: "rgb(91, 96, 100)"}}/> <Divider style={{marginTop: "20px", height: "1px", width: "100%", backgroundColor: "rgb(91, 96, 100)"}}/>
<div style={{flex: "6", marginTop: "20px"}}> <div style={{flex: "6", marginTop: "20px"}}>
<div style={{marginBottom: 5}}> {hideExtraTypes ? null :
<b>Actions</b> <div style={{marginBottom: 5}}>
</div> <b>Actions</b>
<Select </div>
value={selectedAction.name} }
fullWidth {setNewSelectedAction !== undefined ?
onChange={setNewSelectedAction} <Select
style={{backgroundColor: theme.palette.inputColor, color: "white", height: 50, borderRadius: theme.palette.borderRadius,}} value={selectedAction.name}
SelectDisplayProps={{ fullWidth
style: { onChange={setNewSelectedAction}
marginLeft: 10, style={{backgroundColor: theme.palette.inputColor, color: "white", height: 50, borderRadius: theme.palette.borderRadius,}}
maxHeight: 200, SelectDisplayProps={{
borderRadius: theme.palette.borderRadius, style: {
} marginLeft: 10,
}} maxHeight: 200,
> borderRadius: theme.palette.borderRadius,
{sortByKey(selectedApp.actions, "label").map(data => { }
var newActionname = data.name }}
if (data.label !== undefined && data.label !== null && data.label.length > 0) { >
newActionname = data.label {sortByKey(selectedApp.actions, "label").map(data => {
} var newActionname = data.name
// ROFL FIXME - loop if (data.label !== undefined && data.label !== null && data.label.length > 0) {
newActionname = newActionname.replaceAll("_", " ") newActionname = data.label
newActionname = newActionname.replaceAll("_", " ") }
newActionname = newActionname.replaceAll("_", " ") // ROFL FIXME - loop
newActionname = newActionname.replaceAll("_", " ") newActionname = newActionname.replaceAll("_", " ")
newActionname = newActionname.charAt(0).toUpperCase()+newActionname.substring(1) newActionname = newActionname.replaceAll("_", " ")
return ( newActionname = newActionname.replaceAll("_", " ")
<MenuItem key={data.name} style={{maxWidth: 400, overflowX: "hidden", backgroundColor: theme.palette.inputColor, color: "white"}} value={data.name}> newActionname = newActionname.replaceAll("_", " ")
{newActionname} newActionname = newActionname.charAt(0).toUpperCase()+newActionname.substring(1)
return (
<MenuItem key={data.name} style={{maxWidth: 400, overflowX: "hidden", backgroundColor: theme.palette.inputColor, color: "white"}} value={data.name}>
{newActionname}
</MenuItem> </MenuItem>
) )
})} })}
</Select> </Select>
{selectedAction.description !== undefined && selectedAction.description.length > 0 ? : null}
{selectedAction.description !== undefined && selectedAction.description.length > 0 && hideExtraTypes !== true ?
<div style={{marginTop: 10, marginBottom: 10, maxHeight: 60, overflow: "hidden"}}> <div style={{marginTop: 10, marginBottom: 10, maxHeight: 60, overflow: "hidden"}}>
{selectedAction.description} {selectedAction.description}
</div> : null} </div> : null}
<div style={{marginTop: "10px", borderColor: "white", borderWidth: "2px", marginBottom: 200}}> <div style={{marginTop: "10px", borderColor: "white", borderWidth: "2px", marginBottom: 50,}}>
<AppActionArguments key={selectedAction.id} selectedAction={selectedAction} /> <AppActionArguments key={selectedAction.id} selectedAction={selectedAction} />
</div> </div>
</div> </div>
+22 -20
View File
@@ -5,8 +5,8 @@ import { useTheme } from '@material-ui/core/styles';
import uuid from "uuid"; import uuid from "uuid";
import {Link} from 'react-router-dom'; import {Link} from 'react-router-dom';
import { Prompt } from 'react-router' import { Prompt } from 'react-router'
import ReactJson from 'react-json-view'
import { useBeforeunload } from 'react-beforeunload'; import { useBeforeunload } from 'react-beforeunload';
import ReactJson from 'react-json-view'
import NestedMenuItem from "material-ui-nested-menu-item"; import NestedMenuItem from "material-ui-nested-menu-item";
import {TextField, Drawer, Button, Paper, Grid, Tabs, InputAdornment, Tab, ButtonBase, Tooltip, Select, MenuItem, Divider, Dialog, Modal, DialogActions, DialogTitle, InputLabel, DialogContent, FormControl, IconButton, Menu, Input, FormGroup, FormControlLabel, Typography, Checkbox, Breadcrumbs, CircularProgress, Switch, Fade} from '@material-ui/core'; import {TextField, Drawer, Button, Paper, Grid, Tabs, InputAdornment, Tab, ButtonBase, Tooltip, Select, MenuItem, Divider, Dialog, Modal, DialogActions, DialogTitle, InputLabel, DialogContent, FormControl, IconButton, Menu, Input, FormGroup, FormControlLabel, Typography, Checkbox, Breadcrumbs, CircularProgress, Switch, Fade} from '@material-ui/core';
@@ -52,6 +52,25 @@ function useWindowSize() {
return size; return size;
} }
export function sortByKey(array, key) {
if (array === undefined) {
return []
}
if (key.startsWith("-") && key.length > 2) {
key = key.slice(1, key.length)
return array.sort(function(a, b) {
var x = a[key]; var y = b[key]
return ((x < y) ? -1 : ((x > y) ? 1 : 0))
}).reverse()
}
return array.sort(function(a, b) {
var x = a[key]; var y = b[key]
return ((x < y) ? -1 : ((x > y) ? 1 : 0))
})
}
function removeParam(key, sourceURL) { function removeParam(key, sourceURL) {
if (sourceURL === undefined) { if (sourceURL === undefined) {
return return
@@ -2678,13 +2697,14 @@ const AngularWorkflow = (props) => {
*/ */
console.log("ENVS: ", environments) console.log("ENVS: ", environments)
const parsedEnvironments = environments === null || environments === [] ? "cloud" : environments[defaultEnvironmentIndex] === undefined ? "cloud" : environments[defaultEnvironmentIndex].Name
const newAppData = { const newAppData = {
app_name: app.name, app_name: app.name,
app_version: app.app_version, app_version: app.app_version,
app_id: app.id, app_id: app.id,
sharing: app.sharing, sharing: app.sharing,
private_id: app.private_id, private_id: app.private_id,
environment: environments === null || environments === [] ? "cloud" : environments[defaultEnvironmentIndex].Name, environment: parsedEnvironments,
errors: [], errors: [],
id_: newNodeId, id_: newNodeId,
_id_: newNodeId, _id_: newNodeId,
@@ -3126,24 +3146,7 @@ const AngularWorkflow = (props) => {
function sortByKey(array, key) {
if (array === undefined) {
return []
}
if (key.startsWith("-") && key.length > 2) {
key = key.slice(1, key.length)
return array.sort(function(a, b) {
var x = a[key]; var y = b[key]
return ((x < y) ? -1 : ((x > y) ? 1 : 0))
}).reverse()
}
return array.sort(function(a, b) {
var x = a[key]; var y = b[key]
return ((x < y) ? -1 : ((x > y) ? 1 : 0))
})
}
const rightsidebarStyle = { const rightsidebarStyle = {
position: "fixed", position: "fixed",
@@ -3170,7 +3173,6 @@ const AngularWorkflow = (props) => {
selectedApp={selectedApp} selectedApp={selectedApp}
workflowExecutions={workflowExecutions} workflowExecutions={workflowExecutions}
setSelectedResult={setSelectedResult} setSelectedResult={setSelectedResult}
getParents={getParents}
setSelectedApp={setSelectedApp} setSelectedApp={setSelectedApp}
setSelectedTrigger={setSelectedTrigger} setSelectedTrigger={setSelectedTrigger}
setSelectedEdge={setSelectedEdge} setSelectedEdge={setSelectedEdge}
+194 -189
View File
@@ -301,12 +301,12 @@ const AppCreator = (props) => {
return response.json() return response.json()
}) })
.then((responseJson) => { .then((responseJson) => {
if (!responseJson.success) { if (responseJson.success === false) {
alert.error("Failed to get the app") alert.error("Failed to get the app")
setIsAppLoaded(true) setIsAppLoaded(true)
window.location.pathname = "/search"
} else { } else {
const data = JSON.parse(responseJson.body) parseIncomingOpenapiData(responseJson)
parseIncomingOpenapiData(data)
} }
}) })
.catch(error => { .catch(error => {
@@ -346,27 +346,8 @@ const AppCreator = (props) => {
if (!responseJson.success) { if (!responseJson.success) {
alert.error("Failed to verify") alert.error("Failed to verify")
} else{ } else{
var jsonvalid = false parseIncomingOpenapiData(responseJson)
var tmpvalue = ""
try {
tmpvalue = JSON.parse(responseJson.body)
jsonvalid = true
} catch (e) {
console.log("Error JSON: ", e)
}
if (!jsonvalid) {
try {
tmpvalue = YAML.parse(responseJson.body, )
jsonvalid = true
} catch(e) {
console.log("Error YAML: ", e)
}
}
if (jsonvalid) {
parseIncomingOpenapiData(tmpvalue)
}
} }
}) })
.catch(error => { .catch(error => {
@@ -427,9 +408,33 @@ const AppCreator = (props) => {
// Sets the data up as it should be at later points // Sets the data up as it should be at later points
// This is the data FROM the database, not what's being saved // This is the data FROM the database, not what's being saved
const parseIncomingOpenapiData = (data) => { const parseIncomingOpenapiData = (data) => {
//console.log("DATA: ", data.info) const parsedapp = data.openapi === undefined ? data : JSON.parse(atob(data.openapi))
setBasedata(data) data = parsedapp.body === undefined ? parsedapp : parsedapp.body
var jsonvalid = false
var tmpvalue = ""
try {
data = JSON.parse(data)
jsonvalid = true
} catch (e) {
console.log("Error JSON: ", e)
}
if (!jsonvalid) {
try {
data = YAML.parse(data)
jsonvalid = true
} catch(e) {
console.log("Error YAML: ", e)
}
}
if (!jsonvalid) {
alert.info("OpenAPI data is invalid.")
return
}
setBasedata(data)
if (data.info !== null && data.info !== undefined) { if (data.info !== null && data.info !== undefined) {
setName(data.info.title) setName(data.info.title)
setDescription(data.info.description) setDescription(data.info.description)
@@ -490,210 +495,211 @@ const AppCreator = (props) => {
"PUT", "PUT",
] ]
// FIXME - headers?
var newActions = [] var newActions = []
var wordlist = {} var wordlist = {}
for (let [path, pathvalue] of Object.entries(data.paths)) { if (data.paths !== null && data.paths !== undefined) {
for (let [method, methodvalue] of Object.entries(pathvalue)) { for (let [path, pathvalue] of Object.entries(data.paths)) {
if (methodvalue === null) { for (let [method, methodvalue] of Object.entries(pathvalue)) {
alert.info("Skipped method (null)"+method) if (methodvalue === null) {
continue alert.info("Skipped method (null)"+method)
} continue
}
if (!allowedfunctions.includes(method.toUpperCase())) { if (!allowedfunctions.includes(method.toUpperCase())) {
console.log("Invalid method: ", method, "data: ", methodvalue) console.log("Invalid method: ", method, "data: ", methodvalue)
alert.info("Skipped method (not allowed): "+method) alert.info("Skipped method (not allowed): "+method)
continue continue
} }
var tmpname = methodvalue.summary var tmpname = methodvalue.summary
if (methodvalue.operationId !== undefined && methodvalue.operationId !== null && methodvalue.operationId.length > 0 && (tmpname === undefined || tmpname.length === 0)) { if (methodvalue.operationId !== undefined && methodvalue.operationId !== null && methodvalue.operationId.length > 0 && (tmpname === undefined || tmpname.length === 0)) {
tmpname = methodvalue.operationId tmpname = methodvalue.operationId
} }
var newaction = { var newaction = {
"name": tmpname, "name": tmpname,
"description": methodvalue.description, "description": methodvalue.description,
"url": path, "url": path,
"file_field": "", "file_field": "",
"method": method.toUpperCase(), "method": method.toUpperCase(),
"headers": "", "headers": "",
"queries": [], "queries": [],
"paths": [], "paths": [],
"body": "", "body": "",
"errors": [], "errors": [],
"example_response": "", "example_response": "",
} }
if (methodvalue["requestBody"] !== undefined) { if (methodvalue["requestBody"] !== undefined) {
//console.log("Handle requestbody: ", methodvalue["requestBody"]) //console.log("Handle requestbody: ", methodvalue["requestBody"])
if (methodvalue["requestBody"]["content"] !== undefined) { if (methodvalue["requestBody"]["content"] !== undefined) {
if (methodvalue["requestBody"]["content"]["application/json"] !== undefined) { if (methodvalue["requestBody"]["content"]["application/json"] !== undefined) {
if (methodvalue["requestBody"]["content"]["application/json"]["schema"] !== undefined && methodvalue["requestBody"]["content"]["application/json"]["schema"] !== null) { if (methodvalue["requestBody"]["content"]["application/json"]["schema"] !== undefined && methodvalue["requestBody"]["content"]["application/json"]["schema"] !== null) {
if (methodvalue["requestBody"]["content"]["application/json"]["schema"]["properties"] !== undefined) { if (methodvalue["requestBody"]["content"]["application/json"]["schema"]["properties"] !== undefined) {
var tmpobject = {} var tmpobject = {}
for (let [prop, propvalue] of Object.entries(methodvalue["requestBody"]["content"]["application/json"]["schema"]["properties"])) { for (let [prop, propvalue] of Object.entries(methodvalue["requestBody"]["content"]["application/json"]["schema"]["properties"])) {
tmpobject[prop] = `\$\{${prop}\}` tmpobject[prop] = `\$\{${prop}\}`
}
for (var subkey in methodvalue["requestBody"]["content"]["application/json"]["schema"]["required"]) {
const tmpitem = methodvalue["requestBody"]["content"]["application/json"]["schema"]["required"][subkey]
tmpobject[tmpitem] = `\$\{${tmpitem}\}`
}
newaction["body"] = JSON.stringify(tmpobject, null, 2)
} }
for (var subkey in methodvalue["requestBody"]["content"]["application/json"]["schema"]["required"]) {
const tmpitem = methodvalue["requestBody"]["content"]["application/json"]["schema"]["required"][subkey]
tmpobject[tmpitem] = `\$\{${tmpitem}\}`
}
newaction["body"] = JSON.stringify(tmpobject, null, 2)
} }
} } else if (methodvalue["requestBody"]["content"]["application/xml"] !== undefined) {
} else if (methodvalue["requestBody"]["content"]["application/xml"] !== undefined) { console.log("METHOD XML: ", methodvalue)
console.log("METHOD XML: ", methodvalue) if (methodvalue["requestBody"]["content"]["application/xml"]["schema"] !== undefined && methodvalue["requestBody"]["content"]["application/xml"]["schema"] !== null) {
if (methodvalue["requestBody"]["content"]["application/xml"]["schema"] !== undefined && methodvalue["requestBody"]["content"]["application/xml"]["schema"] !== null) { if (methodvalue["requestBody"]["content"]["application/xml"]["schema"]["properties"] !== undefined) {
if (methodvalue["requestBody"]["content"]["application/xml"]["schema"]["properties"] !== undefined) { var tmpobject = {}
var tmpobject = {} for (let [prop, propvalue] of Object.entries(methodvalue["requestBody"]["content"]["application/xml"]["schema"]["properties"])) {
for (let [prop, propvalue] of Object.entries(methodvalue["requestBody"]["content"]["application/xml"]["schema"]["properties"])) { tmpobject[prop] = `\$\{${prop}\}`
tmpobject[prop] = `\$\{${prop}\}` }
for (var subkey in methodvalue["requestBody"]["content"]["application/xml"]["schema"]["required"]) {
const tmpitem = methodvalue["requestBody"]["content"]["application/xml"]["schema"]["required"][subkey]
tmpobject[tmpitem] = `\$\{${tmpitem}\}`
}
//console.log("OBJ XML: ", tmpobject)
//newaction["body"] = XML.stringify(tmpobject, null, 2)
} }
}
for (var subkey in methodvalue["requestBody"]["content"]["application/xml"]["schema"]["required"]) { } else {
const tmpitem = methodvalue["requestBody"]["content"]["application/xml"]["schema"]["required"][subkey] if (methodvalue["requestBody"]["content"]["example"] !== undefined) {
tmpobject[tmpitem] = `\$\{${tmpitem}\}` if (methodvalue["requestBody"]["content"]["example"]["example"] !== undefined) {
newaction["body"] = methodvalue["requestBody"]["content"]["example"]["example"]
//JSON.stringify(tmpobject, null, 2)
} }
//console.log("OBJ XML: ", tmpobject)
//newaction["body"] = XML.stringify(tmpobject, null, 2)
} }
}
} else {
if (methodvalue["requestBody"]["content"]["example"] !== undefined) {
if (methodvalue["requestBody"]["content"]["example"]["example"] !== undefined) {
newaction["body"] = methodvalue["requestBody"]["content"]["example"]["example"]
//JSON.stringify(tmpobject, null, 2)
}
}
//console.log(methodvalue["requestBody"]["content"]) //console.log(methodvalue["requestBody"]["content"])
if (methodvalue["requestBody"]["content"]["multipart/form-data"] !== undefined) { if (methodvalue["requestBody"]["content"]["multipart/form-data"] !== undefined) {
if (methodvalue["requestBody"]["content"]["multipart/form-data"]["schema"] !== undefined && methodvalue["requestBody"]["content"]["multipart/form-data"]["schema"] !== null) { if (methodvalue["requestBody"]["content"]["multipart/form-data"]["schema"] !== undefined && methodvalue["requestBody"]["content"]["multipart/form-data"]["schema"] !== null) {
if (methodvalue["requestBody"]["content"]["multipart/form-data"]["schema"]["type"] === "object") { if (methodvalue["requestBody"]["content"]["multipart/form-data"]["schema"]["type"] === "object") {
const fieldname = methodvalue["requestBody"]["content"]["multipart/form-data"]["schema"]["properties"]["fieldname"] const fieldname = methodvalue["requestBody"]["content"]["multipart/form-data"]["schema"]["properties"]["fieldname"]
if (fieldname !== undefined) { if (fieldname !== undefined) {
console.log("FIELDNAME: ", fieldname) console.log("FIELDNAME: ", fieldname)
newaction.file_field = fieldname["value"] newaction.file_field = fieldname["value"]
}
} }
} }
} }
} }
} }
} }
}
// HAHAHA wtf is this. // HAHAHA wtf is this.
if (methodvalue.responses !== undefined && methodvalue.responses !== null) { if (methodvalue.responses !== undefined && methodvalue.responses !== null) {
if (methodvalue.responses.default !== undefined) { if (methodvalue.responses.default !== undefined) {
if (methodvalue.responses.default.content !== undefined) { if (methodvalue.responses.default.content !== undefined) {
if (methodvalue.responses.default.content["text/plain"] !== 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"] !== undefined) {
if (methodvalue.responses.default.content["text/plain"]["schema"]["example"] !== undefined) { if (methodvalue.responses.default.content["text/plain"]["schema"]["example"] !== undefined) {
newaction.example_response = methodvalue.responses.default.content["text/plain"]["schema"]["example"] newaction.example_response = methodvalue.responses.default.content["text/plain"]["schema"]["example"]
}
} }
} }
} }
} }
} }
}
for (var key in methodvalue.parameters) { for (var key in methodvalue.parameters) {
const parameter = handleGetRef(methodvalue.parameters[key], data) const parameter = handleGetRef(methodvalue.parameters[key], data)
if (parameter.in === "query") { if (parameter.in === "query") {
var tmpaction = { var tmpaction = {
"description": parameter.description, "description": parameter.description,
"name": parameter.name, "name": parameter.name,
"required": parameter.required, "required": parameter.required,
"in": "query", "in": "query",
}
if (parameter.required === undefined) {
tmpaction.required = false
}
newaction.queries.push(tmpaction)
} else if (parameter.in === "path") {
// FIXME - parse this to the URL too
newaction.paths.push(parameter.name)
// FIXME: This doesn't follow OpenAPI3 exactly.
// https://swagger.io/docs/specification/describing-request-body/
// https://swagger.io/docs/specification/describing-parameters/
// Need to split the data.
} else if (parameter.in === "body") {
// FIXME: Add tracking for components
// E.G: https://raw.githubusercontent.com/owentl/Shuffle/master/gosecure.yaml
if (parameter.example !== undefined) {
newaction.body = parameter.example
}
} else if (parameter.in === "header") {
newaction.headers += `${parameter.name}=${parameter.example}\n`
} else {
console.log("WARNING: don't know how to handle this param: ", parameter)
} }
if (parameter.required === undefined) {
tmpaction.required = false
}
newaction.queries.push(tmpaction)
} else if (parameter.in === "path") {
// FIXME - parse this to the URL too
newaction.paths.push(parameter.name)
// FIXME: This doesn't follow OpenAPI3 exactly.
// https://swagger.io/docs/specification/describing-request-body/
// https://swagger.io/docs/specification/describing-parameters/
// Need to split the data.
} else if (parameter.in === "body") {
// FIXME: Add tracking for components
// E.G: https://raw.githubusercontent.com/owentl/Shuffle/master/gosecure.yaml
if (parameter.example !== undefined) {
newaction.body = parameter.example
}
} else if (parameter.in === "header") {
newaction.headers += `${parameter.name}=${parameter.example}\n`
} else {
console.log("WARNING: don't know how to handle this param: ", parameter)
} }
}
if (newaction.name === "" || newaction.name === undefined) { if (newaction.name === "" || newaction.name === undefined) {
// Find a unique part of the string // Find a unique part of the string
// FIXME: Looks for length between /, find the one where they differ // FIXME: Looks for length between /, find the one where they differ
// Should find others with the same START to their path // Should find others with the same START to their path
// Make a list of reserved names? Aka things that show up only once // Make a list of reserved names? Aka things that show up only once
if (Object.getOwnPropertyNames(wordlist).length === 0) { if (Object.getOwnPropertyNames(wordlist).length === 0) {
for (let [newpath, pathvalue] of Object.entries(data.paths)) { for (let [newpath, pathvalue] of Object.entries(data.paths)) {
const newpathsplit = newpath.split("/") const newpathsplit = newpath.split("/")
for(var key in newpathsplit) { for(var key in newpathsplit) {
const pathitem = newpathsplit[key].toLowerCase() const pathitem = newpathsplit[key].toLowerCase()
if (wordlist[pathitem] === undefined) { if (wordlist[pathitem] === undefined) {
wordlist[pathitem] = 1 wordlist[pathitem] = 1
} else { } else {
wordlist[pathitem] += 1 wordlist[pathitem] += 1
}
} }
} }
} }
}
//console.log("WORDLIST: ", wordlist) //console.log("WORDLIST: ", wordlist)
// Remove underscores and make it normal with upper case etc // Remove underscores and make it normal with upper case etc
const urlsplit = path.split("/") const urlsplit = path.split("/")
if (urlsplit.length > 0) { if (urlsplit.length > 0) {
var curname = "" var curname = ""
for(var key in urlsplit) { for(var key in urlsplit) {
var subpath = urlsplit[key] var subpath = urlsplit[key]
if (wordlist[subpath] > 2 || subpath.length < 1) { if (wordlist[subpath] > 2 || subpath.length < 1) {
continue continue
}
curname = subpath
break
} }
curname = subpath // FIXME: If name exists,
break // FIXME: Check if first part of parsedname is verb, otherwise use method
} const parsedname = curname.split("_").join(" ").split("-").join(" ").split("{").join(" ").split("}").join(" ").trim()
if (parsedname.length === 0) {
// FIXME: If name exists,
// FIXME: Check if first part of parsedname is verb, otherwise use method
const parsedname = curname.split("_").join(" ").split("-").join(" ").split("{").join(" ").split("}").join(" ").trim()
if (parsedname.length === 0) {
newaction.errors.push("Missing name")
} else {
const newname = method.charAt(0).toUpperCase() + method.slice(1) + " " + parsedname
const searchactions = newActions.find(data => data.name === newname)
console.log("SEARCH: ", searchactions)
if (searchactions !== undefined) {
newaction.errors.push("Missing name") newaction.errors.push("Missing name")
} else { } else {
newaction.name = newname const newname = method.charAt(0).toUpperCase() + method.slice(1) + " " + parsedname
const searchactions = newActions.find(data => data.name === newname)
console.log("SEARCH: ", searchactions)
if (searchactions !== undefined) {
newaction.errors.push("Missing name")
} else {
newaction.name = newname
}
} }
}
} else { } else {
newaction.errors.push("Missing name") newaction.errors.push("Missing name")
}
} }
newActions.push(newaction)
} }
newActions.push(newaction)
} }
if (data.servers !== undefined && data.servers.length > 0) { if (data.servers !== undefined && data.servers.length > 0) {
@@ -721,8 +727,7 @@ const AppCreator = (props) => {
} }
} }
console.log("INVALID9: ", data)
// FIXME: Have multiple authentication options?
if (securitySchemes !== undefined) { if (securitySchemes !== undefined) {
for (const [key, value] of Object.entries(securitySchemes)) { for (const [key, value] of Object.entries(securitySchemes)) {
if (value.scheme === "bearer") { if (value.scheme === "bearer") {
+12 -4
View File
@@ -280,11 +280,19 @@ const Apps = (props) => {
if (!responseJson.success) { if (!responseJson.success) {
alert.error("Failed to download file") alert.error("Failed to download file")
} else { } else {
const inputdata = YAML.parse(responseJson.body) console.log(responseJson)
const basedata = atob(responseJson.openapi)
console.log("BASE: ", basedata)
var inputdata = JSON.parse(basedata)
console.log("POST INPUT: ", inputdata)
inputdata = JSON.parse(inputdata.body)
const newpaths = {} const newpaths = {}
Object.keys(inputdata["paths"]).forEach(function(key) { if (inputdata["paths"] !== undefined) {
newpaths[key.split("?")[0]] = inputdata.paths[key] Object.keys(inputdata["paths"]).forEach(function(key) {
}) newpaths[key.split("?")[0]] = inputdata.paths[key]
})
}
inputdata.paths = newpaths inputdata.paths = newpaths
console.log("INPUT: ", inputdata) console.log("INPUT: ", inputdata)