Updated OpenAPI app creation process
This commit is contained in:
+170
-22
@@ -4,12 +4,14 @@ import (
|
|||||||
"archive/zip"
|
"archive/zip"
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"cloud.google.com/go/storage"
|
"cloud.google.com/go/storage"
|
||||||
@@ -365,6 +367,20 @@ func generateYaml(swagger *openapi3.Swagger, newmd5 string) (WorkflowApp, []stri
|
|||||||
// Setting up security schemes
|
// Setting up security schemes
|
||||||
extraParameters := []WorkflowAppActionParameter{}
|
extraParameters := []WorkflowAppActionParameter{}
|
||||||
|
|
||||||
|
if val, ok := swagger.Info.ExtensionProps.Extensions["x-logo"]; ok {
|
||||||
|
j, err := json.Marshal(&val)
|
||||||
|
if err == nil {
|
||||||
|
if j[0] == 0x22 && j[len(j)-1] == 0x22 {
|
||||||
|
j = j[1 : len(j)-1]
|
||||||
|
}
|
||||||
|
|
||||||
|
//log.Printf("%s", j)
|
||||||
|
api.SmallImage = string(j)
|
||||||
|
api.LargeImage = string(j)
|
||||||
|
log.Printf("Set images!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
securitySchemes := swagger.Components.SecuritySchemes
|
securitySchemes := swagger.Components.SecuritySchemes
|
||||||
if securitySchemes != nil {
|
if securitySchemes != nil {
|
||||||
//log.Printf("%#v", securitySchemes)
|
//log.Printf("%#v", securitySchemes)
|
||||||
@@ -719,6 +735,24 @@ func handleConnect(swagger *openapi3.Swagger, api WorkflowApp, extraParameters [
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: Example & Multiline
|
||||||
|
if param.Value.Example != nil {
|
||||||
|
curParam.Example = param.Value.Example.(string)
|
||||||
|
|
||||||
|
if param.Value.Name == "body" {
|
||||||
|
curParam.Value = param.Value.Example.(string)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if val, ok := param.Value.ExtensionProps.Extensions["multiline"]; ok {
|
||||||
|
j, err := json.Marshal(&val)
|
||||||
|
if err == nil {
|
||||||
|
b, err := strconv.ParseBool(string(j))
|
||||||
|
if err == nil {
|
||||||
|
curParam.Multiline = b
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if param.Value.Required {
|
if param.Value.Required {
|
||||||
action.Parameters = append(action.Parameters, curParam)
|
action.Parameters = append(action.Parameters, curParam)
|
||||||
} else {
|
} else {
|
||||||
@@ -809,6 +843,24 @@ func handleGet(swagger *openapi3.Swagger, api WorkflowApp, extraParameters []Wor
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: Example & Multiline
|
||||||
|
if param.Value.Example != nil {
|
||||||
|
curParam.Example = param.Value.Example.(string)
|
||||||
|
|
||||||
|
if param.Value.Name == "body" {
|
||||||
|
curParam.Value = param.Value.Example.(string)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if val, ok := param.Value.ExtensionProps.Extensions["multiline"]; ok {
|
||||||
|
j, err := json.Marshal(&val)
|
||||||
|
if err == nil {
|
||||||
|
b, err := strconv.ParseBool(string(j))
|
||||||
|
if err == nil {
|
||||||
|
curParam.Multiline = b
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if param.Value.Required {
|
if param.Value.Required {
|
||||||
action.Parameters = append(action.Parameters, curParam)
|
action.Parameters = append(action.Parameters, curParam)
|
||||||
} else {
|
} else {
|
||||||
@@ -894,6 +946,24 @@ func handleHead(swagger *openapi3.Swagger, api WorkflowApp, extraParameters []Wo
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: Example & Multiline
|
||||||
|
if param.Value.Example != nil {
|
||||||
|
curParam.Example = param.Value.Example.(string)
|
||||||
|
|
||||||
|
if param.Value.Name == "body" {
|
||||||
|
curParam.Value = param.Value.Example.(string)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if val, ok := param.Value.ExtensionProps.Extensions["multiline"]; ok {
|
||||||
|
j, err := json.Marshal(&val)
|
||||||
|
if err == nil {
|
||||||
|
b, err := strconv.ParseBool(string(j))
|
||||||
|
if err == nil {
|
||||||
|
curParam.Multiline = b
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if param.Value.Required {
|
if param.Value.Required {
|
||||||
action.Parameters = append(action.Parameters, curParam)
|
action.Parameters = append(action.Parameters, curParam)
|
||||||
} else {
|
} else {
|
||||||
@@ -979,6 +1049,24 @@ func handleDelete(swagger *openapi3.Swagger, api WorkflowApp, extraParameters []
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: Example & Multiline
|
||||||
|
if param.Value.Example != nil {
|
||||||
|
curParam.Example = param.Value.Example.(string)
|
||||||
|
|
||||||
|
if param.Value.Name == "body" {
|
||||||
|
curParam.Value = param.Value.Example.(string)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if val, ok := param.Value.ExtensionProps.Extensions["multiline"]; ok {
|
||||||
|
j, err := json.Marshal(&val)
|
||||||
|
if err == nil {
|
||||||
|
b, err := strconv.ParseBool(string(j))
|
||||||
|
if err == nil {
|
||||||
|
curParam.Multiline = b
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if param.Value.Required {
|
if param.Value.Required {
|
||||||
action.Parameters = append(action.Parameters, curParam)
|
action.Parameters = append(action.Parameters, curParam)
|
||||||
} else {
|
} else {
|
||||||
@@ -1049,23 +1137,27 @@ func handlePost(swagger *openapi3.Swagger, api WorkflowApp, extraParameters []Wo
|
|||||||
firstQuery = true
|
firstQuery = true
|
||||||
optionalQueries := []string{}
|
optionalQueries := []string{}
|
||||||
parameters := []string{}
|
parameters := []string{}
|
||||||
optionalParameters := []WorkflowAppActionParameter{
|
optionalParameters := []WorkflowAppActionParameter{}
|
||||||
WorkflowAppActionParameter{
|
/*
|
||||||
Name: "body",
|
WorkflowAppActionParameter{
|
||||||
Description: "The body to use",
|
Name: "body",
|
||||||
Multiline: true,
|
Description: "The body to use",
|
||||||
Required: false,
|
Multiline: true,
|
||||||
Example: `{"username": "test"}`,
|
Required: false,
|
||||||
Schema: SchemaDefinition{
|
Example: `{"username": "test"}`,
|
||||||
Type: "string",
|
Schema: SchemaDefinition{
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
}
|
||||||
}
|
*/
|
||||||
if len(path.Post.Parameters) > 0 {
|
if len(path.Post.Parameters) > 0 {
|
||||||
for _, param := range path.Post.Parameters {
|
for _, param := range path.Post.Parameters {
|
||||||
if param.Value.Schema == nil {
|
if param.Value.Schema == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Printf("PARAM: %#v", param.Value)
|
||||||
curParam := WorkflowAppActionParameter{
|
curParam := WorkflowAppActionParameter{
|
||||||
Name: param.Value.Name,
|
Name: param.Value.Name,
|
||||||
Description: param.Value.Description,
|
Description: param.Value.Description,
|
||||||
@@ -1076,6 +1168,24 @@ func handlePost(swagger *openapi3.Swagger, api WorkflowApp, extraParameters []Wo
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: Example & Multiline
|
||||||
|
if param.Value.Example != nil {
|
||||||
|
curParam.Example = param.Value.Example.(string)
|
||||||
|
|
||||||
|
if param.Value.Name == "body" {
|
||||||
|
curParam.Value = param.Value.Example.(string)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if val, ok := param.Value.ExtensionProps.Extensions["multiline"]; ok {
|
||||||
|
j, err := json.Marshal(&val)
|
||||||
|
if err == nil {
|
||||||
|
b, err := strconv.ParseBool(string(j))
|
||||||
|
if err == nil {
|
||||||
|
curParam.Multiline = b
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if param.Value.Required {
|
if param.Value.Required {
|
||||||
action.Parameters = append(action.Parameters, curParam)
|
action.Parameters = append(action.Parameters, curParam)
|
||||||
} else {
|
} else {
|
||||||
@@ -1172,6 +1282,24 @@ func handlePatch(swagger *openapi3.Swagger, api WorkflowApp, extraParameters []W
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: Example & Multiline
|
||||||
|
if param.Value.Example != nil {
|
||||||
|
curParam.Example = param.Value.Example.(string)
|
||||||
|
|
||||||
|
if param.Value.Name == "body" {
|
||||||
|
curParam.Value = param.Value.Example.(string)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if val, ok := param.Value.ExtensionProps.Extensions["multiline"]; ok {
|
||||||
|
j, err := json.Marshal(&val)
|
||||||
|
if err == nil {
|
||||||
|
b, err := strconv.ParseBool(string(j))
|
||||||
|
if err == nil {
|
||||||
|
curParam.Multiline = b
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if param.Value.Required {
|
if param.Value.Required {
|
||||||
action.Parameters = append(action.Parameters, curParam)
|
action.Parameters = append(action.Parameters, curParam)
|
||||||
} else {
|
} else {
|
||||||
@@ -1241,18 +1369,20 @@ func handlePut(swagger *openapi3.Swagger, api WorkflowApp, extraParameters []Wor
|
|||||||
firstQuery = true
|
firstQuery = true
|
||||||
optionalQueries := []string{}
|
optionalQueries := []string{}
|
||||||
parameters := []string{}
|
parameters := []string{}
|
||||||
optionalParameters := []WorkflowAppActionParameter{
|
optionalParameters := []WorkflowAppActionParameter{}
|
||||||
WorkflowAppActionParameter{
|
/*
|
||||||
Name: "body",
|
WorkflowAppActionParameter{
|
||||||
Description: "The body to use",
|
Name: "body",
|
||||||
Multiline: true,
|
Description: "The body to use",
|
||||||
Required: false,
|
Multiline: true,
|
||||||
Example: `{"username": "test"}`,
|
Required: false,
|
||||||
Schema: SchemaDefinition{
|
Example: `{"username": "test"}`,
|
||||||
Type: "string",
|
Schema: SchemaDefinition{
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
}
|
||||||
}
|
*/
|
||||||
if len(path.Put.Parameters) > 0 {
|
if len(path.Put.Parameters) > 0 {
|
||||||
for _, param := range path.Put.Parameters {
|
for _, param := range path.Put.Parameters {
|
||||||
if param.Value.Schema == nil {
|
if param.Value.Schema == nil {
|
||||||
@@ -1268,6 +1398,24 @@ func handlePut(swagger *openapi3.Swagger, api WorkflowApp, extraParameters []Wor
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: Example & Multiline
|
||||||
|
if param.Value.Example != nil {
|
||||||
|
curParam.Example = param.Value.Example.(string)
|
||||||
|
|
||||||
|
if param.Value.Name == "body" {
|
||||||
|
curParam.Value = param.Value.Example.(string)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if val, ok := param.Value.ExtensionProps.Extensions["multiline"]; ok {
|
||||||
|
j, err := json.Marshal(&val)
|
||||||
|
if err == nil {
|
||||||
|
b, err := strconv.ParseBool(string(j))
|
||||||
|
if err == nil {
|
||||||
|
curParam.Multiline = b
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if param.Value.Required {
|
if param.Value.Required {
|
||||||
action.Parameters = append(action.Parameters, curParam)
|
action.Parameters = append(action.Parameters, curParam)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -5543,10 +5543,6 @@ func verifySwagger(resp http.ResponseWriter, request *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
api.Owner = user.Id
|
api.Owner = user.Id
|
||||||
if len(test.Image) > 0 {
|
|
||||||
api.SmallImage = test.Image
|
|
||||||
api.LargeImage = test.Image
|
|
||||||
}
|
|
||||||
|
|
||||||
err = dumpApi(basePath, api)
|
err = dumpApi(basePath, api)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -5569,7 +5565,7 @@ func verifySwagger(resp http.ResponseWriter, request *http.Request) {
|
|||||||
|
|
||||||
identifier = strings.Replace(identifier, " ", "-", -1)
|
identifier = strings.Replace(identifier, " ", "-", -1)
|
||||||
identifier = strings.Replace(identifier, "_", "-", -1)
|
identifier = strings.Replace(identifier, "_", "-", -1)
|
||||||
log.Printf("Successfully uploaded %s to bucket. Proceeding to cloud function", identifier)
|
log.Printf("Successfully parsed %s. Proceeding to docker container", identifier)
|
||||||
|
|
||||||
// Now that the baseline is setup, we need to make it into a cloud function
|
// Now that the baseline is setup, we need to make it into a cloud function
|
||||||
// 1. Upload the API to datastore for use
|
// 1. Upload the API to datastore for use
|
||||||
|
|||||||
@@ -2744,6 +2744,7 @@ func getWorkflowAppConfig(resp http.ResponseWriter, request *http.Request) {
|
|||||||
resp.Write([]byte(`{"success": false}`))
|
resp.Write([]byte(`{"success": false}`))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
log.Printf("API: %#v", parsedApi)
|
||||||
|
|
||||||
//log.Printf("Parsed API: %#v", parsedApi)
|
//log.Printf("Parsed API: %#v", parsedApi)
|
||||||
if len(parsedApi.ID) > 0 {
|
if len(parsedApi.ID) > 0 {
|
||||||
|
|||||||
@@ -51,6 +51,7 @@
|
|||||||
"react-router-dom": "^4.3.1",
|
"react-router-dom": "^4.3.1",
|
||||||
"react-scripts": "^2.1.8",
|
"react-scripts": "^2.1.8",
|
||||||
"reactstrap": "^7.1.0",
|
"reactstrap": "^7.1.0",
|
||||||
|
"shellwords": "^0.1.1",
|
||||||
"simplebar": "^4.2.3",
|
"simplebar": "^4.2.3",
|
||||||
"styled-components": "^4.4.0",
|
"styled-components": "^4.4.0",
|
||||||
"websocket": "^1.0.30",
|
"websocket": "^1.0.30",
|
||||||
|
|||||||
+340
-62
@@ -2,6 +2,7 @@ import React, {useState, useEffect} from 'react';
|
|||||||
import { makeStyles } from '@material-ui/styles';
|
import { makeStyles } from '@material-ui/styles';
|
||||||
import {BrowserView, MobileView} from "react-device-detect";
|
import {BrowserView, MobileView} from "react-device-detect";
|
||||||
|
|
||||||
|
import {Link} from 'react-router-dom';
|
||||||
import Paper from '@material-ui/core/Paper';
|
import Paper from '@material-ui/core/Paper';
|
||||||
import Button from '@material-ui/core/Button';
|
import Button from '@material-ui/core/Button';
|
||||||
import Divider from '@material-ui/core/Divider';
|
import Divider from '@material-ui/core/Divider';
|
||||||
@@ -18,6 +19,7 @@ import CheckCircleIcon from '@material-ui/icons/CheckCircle';
|
|||||||
|
|
||||||
import ErrorOutline from '@material-ui/icons/ErrorOutline';
|
import ErrorOutline from '@material-ui/icons/ErrorOutline';
|
||||||
import { useAlert } from "react-alert";
|
import { useAlert } from "react-alert";
|
||||||
|
import words from "shellwords"
|
||||||
|
|
||||||
const surfaceColor = "#27292D"
|
const surfaceColor = "#27292D"
|
||||||
const inputColor = "#383B40"
|
const inputColor = "#383B40"
|
||||||
@@ -55,7 +57,118 @@ const useStyles = makeStyles({
|
|||||||
notchedOutline: {
|
notchedOutline: {
|
||||||
borderColor: "#f85a3e !important"
|
borderColor: "#f85a3e !important"
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
|
|
||||||
|
|
||||||
|
function rewrite(args) {
|
||||||
|
return args.reduce(function(args, a){
|
||||||
|
if (0 == a.indexOf('-X')) {
|
||||||
|
args.push('-X')
|
||||||
|
args.push(a.slice(2))
|
||||||
|
} else {
|
||||||
|
args.push(a)
|
||||||
|
}
|
||||||
|
|
||||||
|
return args
|
||||||
|
}, [])
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseField(s) {
|
||||||
|
return s.split(/: (.+)/)
|
||||||
|
}
|
||||||
|
|
||||||
|
function isURL(s) {
|
||||||
|
return /^https?:\/\//.test(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
const parseCurl = (s) => {
|
||||||
|
//console.log("CURL: ", s)
|
||||||
|
|
||||||
|
if (0 != s.indexOf('curl ')) {
|
||||||
|
console.log("Not curl start")
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
var args = rewrite(words.split(s))
|
||||||
|
var out = { method: 'GET', header: {} }
|
||||||
|
var state = ''
|
||||||
|
|
||||||
|
args.forEach(function(arg){
|
||||||
|
switch (true) {
|
||||||
|
case isURL(arg):
|
||||||
|
out.url = arg
|
||||||
|
break;
|
||||||
|
|
||||||
|
case arg == '-A' || arg == '--user-agent':
|
||||||
|
state = 'user-agent'
|
||||||
|
break;
|
||||||
|
|
||||||
|
case arg == '-H' || arg == '--header':
|
||||||
|
state = 'header'
|
||||||
|
break;
|
||||||
|
|
||||||
|
case arg == '-d' || arg == '--data' || arg == '--data-ascii':
|
||||||
|
state = 'data'
|
||||||
|
break;
|
||||||
|
|
||||||
|
case arg == '-u' || arg == '--user':
|
||||||
|
state = 'user'
|
||||||
|
break;
|
||||||
|
|
||||||
|
case arg == '-I' || arg == '--head':
|
||||||
|
out.method = 'HEAD'
|
||||||
|
break;
|
||||||
|
|
||||||
|
case arg == '-X' || arg == '--request':
|
||||||
|
state = 'method'
|
||||||
|
break;
|
||||||
|
|
||||||
|
case arg == '-b' || arg =='--cookie':
|
||||||
|
state = 'cookie'
|
||||||
|
break;
|
||||||
|
|
||||||
|
case arg == '--compressed':
|
||||||
|
out.header['Accept-Encoding'] = out.header['Accept-Encoding'] || 'deflate, gzip'
|
||||||
|
break;
|
||||||
|
|
||||||
|
case !!arg:
|
||||||
|
switch (state) {
|
||||||
|
case 'header':
|
||||||
|
var field = parseField(arg)
|
||||||
|
out.header[field[0]] = field[1]
|
||||||
|
state = ''
|
||||||
|
break;
|
||||||
|
case 'user-agent':
|
||||||
|
out.header['User-Agent'] = arg
|
||||||
|
state = ''
|
||||||
|
break;
|
||||||
|
case 'data':
|
||||||
|
if (out.method == 'GET' || out.method == 'HEAD') out.method = 'POST'
|
||||||
|
out.header['Content-Type'] = out.header['Content-Type'] || 'application/x-www-form-urlencoded'
|
||||||
|
out.body = out.body
|
||||||
|
? out.body + '&' + arg
|
||||||
|
: arg
|
||||||
|
state = ''
|
||||||
|
break;
|
||||||
|
case 'user':
|
||||||
|
out.header['Authorization'] = 'Basic ' + btoa(arg)
|
||||||
|
state = ''
|
||||||
|
break;
|
||||||
|
case 'method':
|
||||||
|
out.method = arg
|
||||||
|
state = ''
|
||||||
|
break;
|
||||||
|
case 'cookie':
|
||||||
|
out.header['Set-Cookie'] = arg
|
||||||
|
state = ''
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
// Should be different if logged in :|
|
// Should be different if logged in :|
|
||||||
const AppCreator = (props) => {
|
const AppCreator = (props) => {
|
||||||
@@ -144,13 +257,13 @@ const AppCreator = (props) => {
|
|||||||
|
|
||||||
const handleEditApp = () => {
|
const handleEditApp = () => {
|
||||||
fetch(globalUrl+"/api/v1/apps/"+props.match.params.appid+"/config", {
|
fetch(globalUrl+"/api/v1/apps/"+props.match.params.appid+"/config", {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
'Accept': 'application/json',
|
'Accept': 'application/json',
|
||||||
},
|
},
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
})
|
})
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
if (response.status !== 200) {
|
if (response.status !== 200) {
|
||||||
window.location.pathname = "/apps"
|
window.location.pathname = "/apps"
|
||||||
@@ -164,9 +277,7 @@ const AppCreator = (props) => {
|
|||||||
alert.error("Failed to get the app")
|
alert.error("Failed to get the app")
|
||||||
} else {
|
} else {
|
||||||
const data = JSON.parse(responseJson.body)
|
const data = JSON.parse(responseJson.body)
|
||||||
console.log("LOADED IMAGE: ", data.image)
|
parseIncomingOpenapiData(data)
|
||||||
setFileBase64(data.image)
|
|
||||||
parseOpenapiData(data)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
@@ -184,13 +295,13 @@ const AppCreator = (props) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fetch(globalUrl+"/api/v1/get_openapi/"+urlParams.get("id"), {
|
fetch(globalUrl+"/api/v1/get_openapi/"+urlParams.get("id"), {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
'Accept': 'application/json',
|
'Accept': 'application/json',
|
||||||
},
|
},
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
})
|
})
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
if (response.status !== 200) {
|
if (response.status !== 200) {
|
||||||
throw new Error("NOT 200 :O")
|
throw new Error("NOT 200 :O")
|
||||||
@@ -199,12 +310,12 @@ const AppCreator = (props) => {
|
|||||||
return response.json()
|
return response.json()
|
||||||
})
|
})
|
||||||
.then((responseJson) => {
|
.then((responseJson) => {
|
||||||
setIsAppLoaded(true)
|
setIsAppLoaded(true)
|
||||||
if (!responseJson.success) {
|
if (!responseJson.success) {
|
||||||
alert.error("Failed to verify")
|
alert.error("Failed to verify")
|
||||||
} else {
|
} else {
|
||||||
const data = JSON.parse(responseJson.body)
|
const data = JSON.parse(responseJson.body)
|
||||||
parseOpenapiData(data)
|
parseIncomingOpenapiData(data)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
@@ -227,14 +338,20 @@ 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
|
||||||
const parseOpenapiData = (data) => {
|
// This is the data FROM the database, not what's being saved
|
||||||
|
const parseIncomingOpenapiData = (data) => {
|
||||||
setBasedata(data)
|
setBasedata(data)
|
||||||
|
|
||||||
|
|
||||||
setName(data.info.title)
|
setName(data.info.title)
|
||||||
setDescription(data.info.description)
|
setDescription(data.info.description)
|
||||||
document.title = "Apps - "+data.info.title
|
document.title = "Apps - "+data.info.title
|
||||||
|
|
||||||
|
console.log(data.info["x-logo"])
|
||||||
|
if (data.info !== null && data.info !== undefined && data.info["x-logo"] !== undefined) {
|
||||||
|
setFileBase64(data.info["x-logo"])
|
||||||
|
console.log("IMG: ", data.inf0["x-logo"])
|
||||||
|
}
|
||||||
|
|
||||||
if (data.info.contact != undefined) {
|
if (data.info.contact != undefined) {
|
||||||
setContact(data.info.contact)
|
setContact(data.info.contact)
|
||||||
}
|
}
|
||||||
@@ -243,7 +360,7 @@ const AppCreator = (props) => {
|
|||||||
setBaseUrl(data.servers[0].url)
|
setBaseUrl(data.servers[0].url)
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(data)
|
|
||||||
|
|
||||||
// This is annoying (:
|
// This is annoying (:
|
||||||
var securitySchemes = data.components.securityDefinitions
|
var securitySchemes = data.components.securityDefinitions
|
||||||
@@ -295,9 +412,6 @@ const AppCreator = (props) => {
|
|||||||
"errors": [],
|
"errors": [],
|
||||||
}
|
}
|
||||||
|
|
||||||
//console.log(`${path}: ${method}`);
|
|
||||||
//console.log(methodvalue)
|
|
||||||
|
|
||||||
for (var key in methodvalue.parameters) {
|
for (var key in methodvalue.parameters) {
|
||||||
const parameter = methodvalue.parameters[key]
|
const parameter = methodvalue.parameters[key]
|
||||||
if (parameter.in === "query") {
|
if (parameter.in === "query") {
|
||||||
@@ -323,12 +437,12 @@ const AppCreator = (props) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(newActions)
|
|
||||||
setActions(newActions)
|
setActions(newActions)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Saving the app that's been configured.
|
||||||
const submitApp = () => {
|
const submitApp = () => {
|
||||||
alert.info("Uploading private app " + name)
|
alert.info("Uploading and building app " + name)
|
||||||
setErrorCode("")
|
setErrorCode("")
|
||||||
|
|
||||||
// Format the information
|
// Format the information
|
||||||
@@ -336,6 +450,7 @@ const AppCreator = (props) => {
|
|||||||
const host = splitBase[2]
|
const host = splitBase[2]
|
||||||
const schemes = [splitBase[0]]
|
const schemes = [splitBase[0]]
|
||||||
const basePath = "/"+(splitBase.slice(3, )).join("/")
|
const basePath = "/"+(splitBase.slice(3, )).join("/")
|
||||||
|
console.log("IMAGE: ", fileBase64)
|
||||||
|
|
||||||
const data = {
|
const data = {
|
||||||
"swagger": "3.0",
|
"swagger": "3.0",
|
||||||
@@ -343,6 +458,7 @@ const AppCreator = (props) => {
|
|||||||
"title": name,
|
"title": name,
|
||||||
"description": description,
|
"description": description,
|
||||||
"version": "1.0",
|
"version": "1.0",
|
||||||
|
"x-logo": fileBase64,
|
||||||
},
|
},
|
||||||
"servers": [{"url": baseUrl}],
|
"servers": [{"url": baseUrl}],
|
||||||
"host": host,
|
"host": host,
|
||||||
@@ -353,7 +469,6 @@ const AppCreator = (props) => {
|
|||||||
"components": {
|
"components": {
|
||||||
"securitySchemes": {},
|
"securitySchemes": {},
|
||||||
},
|
},
|
||||||
"image": fileBase64,
|
|
||||||
"id": props.match.params.appid,
|
"id": props.match.params.appid,
|
||||||
"securityDefinitions": {},
|
"securityDefinitions": {},
|
||||||
}
|
}
|
||||||
@@ -368,7 +483,7 @@ const AppCreator = (props) => {
|
|||||||
data.info["contact"] = contact
|
data.info["contact"] = contact
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("LOADED IMAGE: ", data.image)
|
//console.log("LOADED IMAGE: ", data.image)
|
||||||
|
|
||||||
for (var key in actions) {
|
for (var key in actions) {
|
||||||
const item = actions[key]
|
const item = actions[key]
|
||||||
@@ -440,6 +555,23 @@ const AppCreator = (props) => {
|
|||||||
//console.log(queryitem)
|
//console.log(queryitem)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (item.body.length > 0) {
|
||||||
|
console.log("HANDLE BODY!")
|
||||||
|
newitem = {
|
||||||
|
"in": "body",
|
||||||
|
"name": "body",
|
||||||
|
"multiline": true,
|
||||||
|
"description": "Generated by shuffler.io OpenAPI",
|
||||||
|
"required": false,
|
||||||
|
"example": item.body,
|
||||||
|
"schema": {
|
||||||
|
"type": "string",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
data.paths[item.url][item.method.toLowerCase()].parameters.push(newitem)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (authenticationOption === "API key") {
|
if (authenticationOption === "API key") {
|
||||||
@@ -462,7 +594,7 @@ const AppCreator = (props) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fetch(globalUrl+"/api/v1/verify_openapi", {
|
fetch(globalUrl+"/api/v1/verify_openapi", {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
'Accept': 'application/json',
|
'Accept': 'application/json',
|
||||||
@@ -495,9 +627,9 @@ const AppCreator = (props) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const bearerAuth = authenticationOption === "Bearer auth" ?
|
const bearerAuth = authenticationOption === "Bearer auth" ?
|
||||||
<div>
|
<div style={{color: "white"}}>
|
||||||
<h4>
|
<h4>
|
||||||
<a href="https://swagger.io/docs/specification/authentication/bearer-authentication/" style={{textDecoriation: "none", color: "#f85a3e"}}>
|
<a target="_blank" href="https://swagger.io/docs/specification/authentication/bearer-authentication/" style={{textDecoriation: "none", color: "#f85a3e"}}>
|
||||||
Bearer auth
|
Bearer auth
|
||||||
</a>
|
</a>
|
||||||
</h4>
|
</h4>
|
||||||
@@ -508,9 +640,9 @@ const AppCreator = (props) => {
|
|||||||
|
|
||||||
// Basicauth
|
// Basicauth
|
||||||
const basicAuth = authenticationOption === "Basic auth" ?
|
const basicAuth = authenticationOption === "Basic auth" ?
|
||||||
<div>
|
<div style={{color: "white"}}>
|
||||||
<h4>
|
<h4>
|
||||||
<a href="https://swagger.io/docs/specification/authentication/basic-authentication/" style={{textDecoriation: "none", color: "#f85a3e"}}>
|
<a target="_blank" href="https://swagger.io/docs/specification/authentication/basic-authentication/" style={{textDecoriation: "none", color: "#f85a3e"}}>
|
||||||
Basic authentication
|
Basic authentication
|
||||||
</a>
|
</a>
|
||||||
</h4>
|
</h4>
|
||||||
@@ -596,9 +728,9 @@ const AppCreator = (props) => {
|
|||||||
setActions(actions)
|
setActions(actions)
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("Option: ", authenticationOption)
|
//console.log("Option: ", authenticationOption)
|
||||||
console.log("Location: ", parameterLocation)
|
//console.log("Location: ", parameterLocation)
|
||||||
console.log("Name: ", parameterName)
|
//console.log("Name: ", parameterName)
|
||||||
const apiKey = authenticationOption === "API key" ?
|
const apiKey = authenticationOption === "API key" ?
|
||||||
<div style={{color: "white"}}>
|
<div style={{color: "white"}}>
|
||||||
<h4>API key</h4>
|
<h4>API key</h4>
|
||||||
@@ -818,13 +950,30 @@ const AppCreator = (props) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const UrlPathParameters = () => {
|
const UrlPathParameters = () => {
|
||||||
|
var paths = []
|
||||||
|
var queries = []
|
||||||
|
|
||||||
if (urlPath.includes("{") && urlPath.includes("}")) {
|
if (urlPath.includes("{") && urlPath.includes("}")) {
|
||||||
var values = []
|
|
||||||
var tmpWord = ""
|
var tmpWord = ""
|
||||||
var record = false
|
var record = false
|
||||||
|
|
||||||
|
var query = false
|
||||||
for (var key in urlPath) {
|
for (var key in urlPath) {
|
||||||
|
if (urlPath[key] === "?") {
|
||||||
|
query = true
|
||||||
|
}
|
||||||
|
|
||||||
if (urlPath[key] === "}") {
|
if (urlPath[key] === "}") {
|
||||||
values.push(tmpWord)
|
if (tmpWord === parameterName) {
|
||||||
|
tmpWord = ""
|
||||||
|
record = false
|
||||||
|
continue
|
||||||
|
} else if (query) {
|
||||||
|
queries.push(tmpWord)
|
||||||
|
} else {
|
||||||
|
paths.push(tmpWord)
|
||||||
|
}
|
||||||
|
|
||||||
tmpWord = ""
|
tmpWord = ""
|
||||||
record = false
|
record = false
|
||||||
}
|
}
|
||||||
@@ -833,24 +982,75 @@ const AppCreator = (props) => {
|
|||||||
tmpWord += urlPath[key]
|
tmpWord += urlPath[key]
|
||||||
}
|
}
|
||||||
|
|
||||||
if (urlPath[key] === "{" && urlPath[key-1] === "/") {
|
//if (urlPath[key] === "{" && urlPath[key-1] === "/") {
|
||||||
|
if (urlPath[key] === "{") {
|
||||||
record = true
|
record = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!currentAction.paths === values) {
|
|
||||||
currentAction.paths = values
|
|
||||||
setCurrentAction(currentAction)
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
Required parameters: {values.join(", ")}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null
|
if (urlPath.includes("<") && urlPath.includes(">")) {
|
||||||
|
var tmpWord = ""
|
||||||
|
var record = false
|
||||||
|
|
||||||
|
var query = false
|
||||||
|
for (var key in urlPath) {
|
||||||
|
if (urlPath[key] === "?") {
|
||||||
|
query = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (urlPath[key] === ">") {
|
||||||
|
if (tmpWord === parameterName) {
|
||||||
|
tmpWord = ""
|
||||||
|
record = false
|
||||||
|
continue
|
||||||
|
} else if (query) {
|
||||||
|
queries.push(tmpWord)
|
||||||
|
} else {
|
||||||
|
paths.push(tmpWord)
|
||||||
|
}
|
||||||
|
|
||||||
|
tmpWord = ""
|
||||||
|
record = false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (record) {
|
||||||
|
tmpWord += urlPath[key]
|
||||||
|
}
|
||||||
|
|
||||||
|
//if (urlPath[key] === "{" && urlPath[key-1] === "/") {
|
||||||
|
if (urlPath[key] === "<") {
|
||||||
|
record = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentAction.paths !== paths) {
|
||||||
|
setActionField("paths", paths)
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("QUERIES: ", queries)
|
||||||
|
var tmpQueries = []
|
||||||
|
|
||||||
|
// No overlapping of names
|
||||||
|
for (var key in queries) {
|
||||||
|
const tmpquery = queries[key]
|
||||||
|
const found = tmpQueries.find(query => query.name === tmpquery)
|
||||||
|
if (found === undefined) {
|
||||||
|
tmpQueries.push({"name": queries[key], required: true})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: Frontend isn't updating..
|
||||||
|
if (JSON.stringify(tmpQueries) !== JSON.stringify(urlPathQueries)) {
|
||||||
|
setUrlPathQueries(tmpQueries)
|
||||||
|
}
|
||||||
|
|
||||||
|
return paths.length > 0 ?
|
||||||
|
<div>
|
||||||
|
Required parameters: {paths.join(", ")}
|
||||||
|
</div>
|
||||||
|
: null
|
||||||
}
|
}
|
||||||
|
|
||||||
const newActionModal =
|
const newActionModal =
|
||||||
@@ -878,7 +1078,7 @@ const AppCreator = (props) => {
|
|||||||
<FormControl style={{backgroundColor: surfaceColor, color: "white",}}>
|
<FormControl style={{backgroundColor: surfaceColor, color: "white",}}>
|
||||||
<DialogTitle><div style={{color: "white"}}>New action</div></DialogTitle>
|
<DialogTitle><div style={{color: "white"}}>New action</div></DialogTitle>
|
||||||
<DialogContent>
|
<DialogContent>
|
||||||
<a href="/docs/apps#actions" style={{textDecoration: "none", color: "#f85a3e"}}>Learn more about app creation</a>
|
<Link target="_blank" to="/docs/apps#actions" style={{textDecoration: "none", color: "#f85a3e"}}>Learn more about actions</Link>
|
||||||
<div style={{marginTop: "15px"}}/>
|
<div style={{marginTop: "15px"}}/>
|
||||||
Name
|
Name
|
||||||
<TextField
|
<TextField
|
||||||
@@ -891,7 +1091,14 @@ const AppCreator = (props) => {
|
|||||||
margin="normal"
|
margin="normal"
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
defaultValue={currentAction["name"]}
|
defaultValue={currentAction["name"]}
|
||||||
onChange={e => setActionField("name", e.target.value)}
|
onChange={e => {
|
||||||
|
// Fix basic issues in frontend. Python functions run a-zA-Z0-9_
|
||||||
|
const regex = /[A-Z-a-z0-9 _]/g;
|
||||||
|
const found = e.target.value.match(regex);
|
||||||
|
if (found !== null) {
|
||||||
|
setActionField("name", found.join(""))
|
||||||
|
}
|
||||||
|
}}
|
||||||
key={currentAction}
|
key={currentAction}
|
||||||
InputProps={{
|
InputProps={{
|
||||||
classes: {
|
classes: {
|
||||||
@@ -951,7 +1158,7 @@ const AppCreator = (props) => {
|
|||||||
))}
|
))}
|
||||||
</Select>
|
</Select>
|
||||||
<div style={{marginTop: "15px"}} />
|
<div style={{marginTop: "15px"}} />
|
||||||
URL path
|
URL path / Curl statement
|
||||||
<TextField
|
<TextField
|
||||||
required
|
required
|
||||||
style={{flex: "1", marginRight: "15px", marginTop: "5px", backgroundColor: inputColor}}
|
style={{flex: "1", marginRight: "15px", marginTop: "5px", backgroundColor: inputColor}}
|
||||||
@@ -966,7 +1173,7 @@ const AppCreator = (props) => {
|
|||||||
setUrlPath(e.target.value)
|
setUrlPath(e.target.value)
|
||||||
console.log(e.target.value)
|
console.log(e.target.value)
|
||||||
}}
|
}}
|
||||||
helperText={<div style={{color:"white", marginBottom: "2px",}}>The path to use. Must start with /. Add {"{variable}"} to have path variables</div>}
|
helperText={<div style={{color:"white", marginBottom: "2px",}}>The path to use. Must start with /. Use {"{variablename}"} to have path variables</div>}
|
||||||
InputProps={{
|
InputProps={{
|
||||||
classes: {
|
classes: {
|
||||||
notchedOutline: classes.notchedOutline,
|
notchedOutline: classes.notchedOutline,
|
||||||
@@ -976,6 +1183,55 @@ const AppCreator = (props) => {
|
|||||||
color: "white",
|
color: "white",
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
|
onBlur={event => {
|
||||||
|
var parsedurl = event.target.value
|
||||||
|
if (parsedurl.startsWith("curl")) {
|
||||||
|
const request = parseCurl(event.target.value)
|
||||||
|
console.log(request)
|
||||||
|
if (request.method.toUpperCase() !== currentAction.Method) {
|
||||||
|
setCurrentActionMethod(request.method.toUpperCase())
|
||||||
|
setActionField("method", request.method.toUpperCase())
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request.header !== undefined && request.header !== null) {
|
||||||
|
var headers = ""
|
||||||
|
for (let [key, value] of Object.entries(request.header)) {
|
||||||
|
headers += key+"="+value+"\n"
|
||||||
|
}
|
||||||
|
|
||||||
|
setActionField("headers", headers)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request.body !== undefined && request.body !== null) {
|
||||||
|
setActionField("body", request.body)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse URL
|
||||||
|
parsedurl = request.url
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parsedurl.startsWith("http") || parsedurl.startsWith("ftp")) {
|
||||||
|
if (parsedurl !== undefined && parsedurl.includes(parameterName)) {
|
||||||
|
// Remove <> etc.
|
||||||
|
//
|
||||||
|
|
||||||
|
console.log("IT HAS THE PARAM NAME!")
|
||||||
|
const newurl = new URL(encodeURI(parsedurl))
|
||||||
|
newurl.searchParams.delete(parameterName)
|
||||||
|
parsedurl = decodeURI(newurl.href)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the base URL itself
|
||||||
|
if (parsedurl !== undefined && baseUrl !== undefined && baseUrl.length > 0 && parsedurl.includes(baseUrl)) {
|
||||||
|
parsedurl = parsedurl.replace(baseUrl, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check URL query && headers
|
||||||
|
setActionField("url", parsedurl)
|
||||||
|
setUrlPath(parsedurl)
|
||||||
|
}
|
||||||
|
//console.log("URL: ", request.url)
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
<UrlPathParameters />
|
<UrlPathParameters />
|
||||||
{loopQueries}
|
{loopQueries}
|
||||||
@@ -1029,7 +1285,7 @@ const AppCreator = (props) => {
|
|||||||
<div style={{color: "white"}}>
|
<div style={{color: "white"}}>
|
||||||
<h2>Actions</h2>
|
<h2>Actions</h2>
|
||||||
Actions are the tasks performed by an app. Read more about actions and apps
|
Actions are the tasks performed by an app. Read more about actions and apps
|
||||||
<a href="/docs/apps#actions" style={{textDecoration: "none", color: "#f85a3e"}}> here</a>.
|
<Link target="_blank" to="/docs/apps#actions" style={{textDecoration: "none", color: "#f85a3e"}}> here</Link>.
|
||||||
<div>
|
<div>
|
||||||
{loopActions}
|
{loopActions}
|
||||||
<Button color="primary" style={{marginTop: "20px", borderRadius: "0px"}} variant="outlined" onClick={() => {
|
<Button color="primary" style={{marginTop: "20px", borderRadius: "0px"}} variant="outlined" onClick={() => {
|
||||||
@@ -1054,7 +1310,7 @@ const AppCreator = (props) => {
|
|||||||
<div style={{color: "white"}}>
|
<div style={{color: "white"}}>
|
||||||
<h2>Test</h2>
|
<h2>Test</h2>
|
||||||
Test an action to see whether it performs in an expected way.
|
Test an action to see whether it performs in an expected way.
|
||||||
<a href="/docs/apps#testing" style={{textDecoration: "none", color: "#f85a3e"}}> Click here to learn more about testing</a>.
|
<Link target="_blank" to="/docs/apps#testing" style={{textDecoration: "none", color: "#f85a3e"}}> TBD: Click here to learn more about testing</Link>.
|
||||||
<div>
|
<div>
|
||||||
Test :)
|
Test :)
|
||||||
</div>
|
</div>
|
||||||
@@ -1071,14 +1327,23 @@ const AppCreator = (props) => {
|
|||||||
if (file !== "") {
|
if (file !== "") {
|
||||||
const img = document.getElementById('logo')
|
const img = document.getElementById('logo')
|
||||||
var canvas = document.createElement('canvas')
|
var canvas = document.createElement('canvas')
|
||||||
|
canvas.width = 174
|
||||||
|
canvas.height = 174
|
||||||
var ctx = canvas.getContext('2d')
|
var ctx = canvas.getContext('2d')
|
||||||
|
|
||||||
img.onload = function() {
|
img.onload = function() {
|
||||||
// img, x, y, width, height
|
// img, x, y, width, height
|
||||||
ctx.drawImage(img, 0, 0)
|
//ctx.drawImage(img, 174, 174)
|
||||||
|
console.log("IMG natural: ", img.naturalWidth, img.naturalHeight)
|
||||||
|
//ctx.drawImage(img, 0, 0, 174, 174)
|
||||||
|
ctx.drawImage(img,
|
||||||
|
0, 0, img.width, img.height,
|
||||||
|
0, 0, canvas.width, canvas.height
|
||||||
|
)
|
||||||
|
|
||||||
const canvasUrl = canvas.toDataURL()
|
const canvasUrl = canvas.toDataURL()
|
||||||
console.log(canvasUrl)
|
|
||||||
if (canvasUrl !== fileBase64) {
|
if (canvasUrl !== fileBase64) {
|
||||||
|
console.log("SET URL TO: ", canvasUrl)
|
||||||
setFileBase64(canvasUrl)
|
setFileBase64(canvasUrl)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1096,14 +1361,14 @@ const AppCreator = (props) => {
|
|||||||
// <img src={file} id="logo" style={{width: "100%", height: "100%"}} />
|
// <img src={file} id="logo" style={{width: "100%", height: "100%"}} />
|
||||||
|
|
||||||
const imageData = file.length > 0 ? file : fileBase64
|
const imageData = file.length > 0 ? file : fileBase64
|
||||||
const imageInfo = <img src={imageData} alt="Click to upload an image" id="logo" style={{width: 174, height: 174}} />
|
const imageInfo = <img src={imageData} alt="Click to upload an image" id="logo" style={{}} />
|
||||||
|
|
||||||
// Random names for type & autoComplete. Didn't research :^)
|
// Random names for type & autoComplete. Didn't research :^)
|
||||||
const landingpageDataBrowser =
|
const landingpageDataBrowser =
|
||||||
<div style={{paddingBottom: 100, color: "white",}}>
|
<div style={{paddingBottom: 100, color: "white",}}>
|
||||||
<Paper style={boxStyle}>
|
<Paper style={boxStyle}>
|
||||||
<h2 style={{marginBottom: "10px", color: "white"}}>General information</h2>
|
<h2 style={{marginBottom: "10px", color: "white"}}>General information</h2>
|
||||||
<a href="/docs/apps#create" style={{textDecoration: "none", color: "#f85a3e"}}>Click here to learn more about app creation</a>
|
<Link target="_blank" to="/docs/apps#create_openapi_app" style={{textDecoration: "none", color: "#f85a3e"}}>Click here to learn more about app creation</Link>
|
||||||
<div style={{color: "white", flex: "1", display: "flex", flexDirection: "row"}}>
|
<div style={{color: "white", flex: "1", display: "flex", flexDirection: "row"}}>
|
||||||
<Tooltip title="Click to edit the app's image" placement="bottom">
|
<Tooltip title="Click to edit the app's image" placement="bottom">
|
||||||
<div style={{flex: "1", margin: 10, border: "1px solid #f85a3e", cursor: "pointer", backgroundColor: inputColor, maxWidth: 174, maxHeight: 174}} onClick={() => {upload.click()}}>
|
<div style={{flex: "1", margin: 10, border: "1px solid #f85a3e", cursor: "pointer", backgroundColor: inputColor, maxWidth: 174, maxHeight: 174}} onClick={() => {upload.click()}}>
|
||||||
@@ -1120,11 +1385,11 @@ const AppCreator = (props) => {
|
|||||||
fullWidth={true}
|
fullWidth={true}
|
||||||
placeholder="Name"
|
placeholder="Name"
|
||||||
type="name"
|
type="name"
|
||||||
id="standard-required"
|
id="standard-required"
|
||||||
margin="normal"
|
margin="normal"
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
value={name}
|
value={name}
|
||||||
onChange={e => setName(e.target.value)}
|
onChange={e => setName(e.target.value)}
|
||||||
color="primary"
|
color="primary"
|
||||||
InputProps={{
|
InputProps={{
|
||||||
style:{
|
style:{
|
||||||
@@ -1187,6 +1452,19 @@ const AppCreator = (props) => {
|
|||||||
helperText={<div style={{color:"white", marginBottom: "2px",}}>Must start with http(s):// and CANT end with /. </div>}
|
helperText={<div style={{color:"white", marginBottom: "2px",}}>Must start with http(s):// and CANT end with /. </div>}
|
||||||
placeholder="https://api.example.com"
|
placeholder="https://api.example.com"
|
||||||
onChange={e => setBaseUrl(e.target.value)}
|
onChange={e => setBaseUrl(e.target.value)}
|
||||||
|
onBlur={(event) => {
|
||||||
|
var tmpstring = event.target.value.trim()
|
||||||
|
if (tmpstring.endsWith("/")) {
|
||||||
|
tmpstring = tmpstring.slice(0, -1)
|
||||||
|
}
|
||||||
|
if (tmpstring.length > 4 && !tmpstring.startsWith("http") && !tmpstring.startsWith("ftp")) {
|
||||||
|
alert.error("URL must start with http(s)://")
|
||||||
|
}
|
||||||
|
|
||||||
|
//if (authenticationOption === "No authentication" &&
|
||||||
|
|
||||||
|
setBaseUrl(tmpstring)
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
<FormControl style={{marginTop: "15px",}} variant="outlined">
|
<FormControl style={{marginTop: "15px",}} variant="outlined">
|
||||||
<h5 style={{marginBottom: "10px", color: "white",}}>Authentication</h5>
|
<h5 style={{marginBottom: "10px", color: "white",}}>Authentication</h5>
|
||||||
@@ -1196,7 +1474,7 @@ const AppCreator = (props) => {
|
|||||||
setAuthenticationOption(e.target.value)
|
setAuthenticationOption(e.target.value)
|
||||||
}}
|
}}
|
||||||
value={authenticationOption}
|
value={authenticationOption}
|
||||||
style={{backgroundColor: inputColor, paddingLeft: "10px", color: "white", height: "50px"}}
|
style={{backgroundColor: inputColor, color: "white", height: "50px"}}
|
||||||
>
|
>
|
||||||
{authenticationOptions.map(data => (
|
{authenticationOptions.map(data => (
|
||||||
<MenuItem style={{backgroundColor: inputColor, color: "white"}} value={data}>
|
<MenuItem style={{backgroundColor: inputColor, color: "white"}} value={data}>
|
||||||
|
|||||||
+42
-31
@@ -117,10 +117,12 @@ const Apps = (props) => {
|
|||||||
setFilteredApps(responseJson)
|
setFilteredApps(responseJson)
|
||||||
if (responseJson.length > 0) {
|
if (responseJson.length > 0) {
|
||||||
setSelectedApp(responseJson[0])
|
setSelectedApp(responseJson[0])
|
||||||
if (responseJson[0].actions.length > 0) {
|
if (responseJson[0].actions !== null && responseJson[0].actions.length > 0) {
|
||||||
setSelectedAction(responseJson[0].actions[0])
|
setSelectedAction(responseJson[0].actions[0])
|
||||||
|
} else {
|
||||||
|
setSelectedAction({})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
alert.error(error.toString())
|
alert.error(error.toString())
|
||||||
@@ -188,6 +190,7 @@ const Apps = (props) => {
|
|||||||
boxColor = "green"
|
boxColor = "green"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log("IMG: ", data.large_image)
|
||||||
var imageline = data.large_image.length === 0 ?
|
var imageline = data.large_image.length === 0 ?
|
||||||
<img alt={data.title} style={{width: 100, height: 100}} />
|
<img alt={data.title} style={{width: 100, height: 100}} />
|
||||||
:
|
:
|
||||||
@@ -222,9 +225,11 @@ const Apps = (props) => {
|
|||||||
<Paper square style={paperAppStyle} onClick={() => {
|
<Paper square style={paperAppStyle} onClick={() => {
|
||||||
if (selectedApp.id !== data.id) {
|
if (selectedApp.id !== data.id) {
|
||||||
setSelectedApp(data)
|
setSelectedApp(data)
|
||||||
if (data.actions.length > 0) {
|
if (data.actions !== undefined && data.actions !== null && data.actions.length > 0) {
|
||||||
console.log(data.actions[0])
|
console.log(data.actions[0])
|
||||||
setSelectedAction(data.actions[0])
|
setSelectedAction(data.actions[0])
|
||||||
|
} else {
|
||||||
|
setSelectedAction({})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}}>
|
}}>
|
||||||
@@ -352,36 +357,42 @@ const Apps = (props) => {
|
|||||||
|
|
||||||
<div style={{marginTop: 15, marginBottom: 15}}>
|
<div style={{marginTop: 15, marginBottom: 15}}>
|
||||||
<b>Actions</b>
|
<b>Actions</b>
|
||||||
<Select
|
{selectedApp.actions !== null && selectedApp.actions.length > 0 ?
|
||||||
fullWidth
|
<Select
|
||||||
value={selectedAction}
|
fullWidth
|
||||||
onChange={(event) => {
|
value={selectedAction}
|
||||||
setSelectedAction(event.target.value)
|
onChange={(event) => {
|
||||||
}}
|
setSelectedAction(event.target.value)
|
||||||
style={{backgroundColor: inputColor, color: "white", height: "50px"}}
|
}}
|
||||||
SelectDisplayProps={{
|
style={{backgroundColor: inputColor, color: "white", height: "50px"}}
|
||||||
style: {
|
SelectDisplayProps={{
|
||||||
marginLeft: 10,
|
style: {
|
||||||
}
|
marginLeft: 10,
|
||||||
}}
|
}
|
||||||
>
|
}}
|
||||||
{selectedApp.actions.map(data => {
|
>
|
||||||
var newActionname = data.label !== undefined && data.label.length > 0 ? data.label : data.name
|
{selectedApp.actions.map(data => {
|
||||||
|
var newActionname = data.label !== undefined && data.label.length > 0 ? data.label : data.name
|
||||||
|
|
||||||
// ROFL FIXME - loop
|
// ROFL FIXME - loop
|
||||||
newActionname = newActionname.replace("_", " ")
|
newActionname = newActionname.replace("_", " ")
|
||||||
newActionname = newActionname.replace("_", " ")
|
newActionname = newActionname.replace("_", " ")
|
||||||
newActionname = newActionname.replace("_", " ")
|
newActionname = newActionname.replace("_", " ")
|
||||||
newActionname = newActionname.replace("_", " ")
|
newActionname = newActionname.replace("_", " ")
|
||||||
newActionname = newActionname.charAt(0).toUpperCase()+newActionname.substring(1)
|
newActionname = newActionname.charAt(0).toUpperCase()+newActionname.substring(1)
|
||||||
return (
|
return (
|
||||||
<MenuItem style={{backgroundColor: inputColor, color: "white"}} value={data}>
|
<MenuItem style={{backgroundColor: inputColor, color: "white"}} value={data}>
|
||||||
{newActionname}
|
{newActionname}
|
||||||
|
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
</Select>
|
</Select>
|
||||||
|
:
|
||||||
|
<div style={{marginTop: 10}}>
|
||||||
|
There are no actions defined for this app.
|
||||||
|
</div>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{selectedAction.parameters !== undefined && selectedAction.parameters !== null ?
|
{selectedAction.parameters !== undefined && selectedAction.parameters !== null ?
|
||||||
|
|||||||
Reference in New Issue
Block a user