Added frontend fixes for app creation and getting started UI

This commit is contained in:
frikky
2022-01-12 14:02:58 +01:00
parent 8e3ee76a46
commit b2dafd6f28
5 changed files with 292 additions and 91 deletions
+98 -1
View File
@@ -576,7 +576,7 @@ const Framework = (props) => {
const foundelement = cy.getElementById(discoveryData.id) const foundelement = cy.getElementById(discoveryData.id)
if (foundelement !== undefined && foundelement !== null) { if (foundelement !== undefined && foundelement !== null) {
console.log("element: ", foundelement) //console.log("element: ", foundelement)
foundelement.data("large_image", newSelectedApp.image_url) foundelement.data("large_image", newSelectedApp.image_url)
foundelement.data("text_margin_y", "60px") foundelement.data("text_margin_y", "60px")
foundelement.data("margin_x", "0px") foundelement.data("margin_x", "0px")
@@ -1105,7 +1105,88 @@ const Framework = (props) => {
changeUsecase(selectedOption, usecaseType) changeUsecase(selectedOption, usecaseType)
} }
const UsecaseHandler = (props) => {
const { data, index, diff } = props
const svgSize = 20
var svgIcon = <svg width="17" height="17" viewBox="0 0 17 17" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M1 4H15.2772" stroke="#AFAFAF" stroke-linecap="round"/>
<path d="M13 1L16 4" stroke="#AFAFAF" stroke-linecap="round"/>
<path d="M12.7856 7L15.9999 4" stroke="#AFAFAF" stroke-linecap="round"/>
<path d="M16 13L1.72276 13" stroke="#AFAFAF" stroke-linecap="round"/>
<path d="M4.21436 16L1.00007 13" stroke="#AFAFAF" stroke-linecap="round"/>
<path d="M4.21436 10L1.00007 13" stroke="#AFAFAF" stroke-linecap="round"/>
</svg>
if (data.direction === "right") {
svgIcon = <svg width="16" height="8" viewBox="0 0 16 8" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M0.847656 4.16553H14.1479" stroke="#AFAFAF" stroke-linecap="round"/>
<path d="M11.8268 1.37085L14.8211 4.16556" stroke="#AFAFAF" stroke-linecap="round"/>
<path d="M11.8268 6.96024L14.8211 4.16553" stroke="#AFAFAF" stroke-linecap="round"/>
</svg>
} else if (data.direction === "left") {
svgIcon = <svg width="16" height="8" viewBox="0 0 16 8" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M14.5031 4.16577L1.20278 4.16577" stroke="#AFAFAF" stroke-linecap="round"/>
<path d="M3.52393 6.96045L0.529589 4.16573" stroke="#AFAFAF" stroke-linecap="round"/>
<path d="M3.52393 1.37106L0.529589 4.16577" stroke="#AFAFAF" stroke-linecap="round"/>
</svg>
}
//<img alt={"usecase_directional_arrow_"+index} style={{height: 30, width: 30}} src={parsedDirectionImage} />
return (
<Paper style={{width: 250, maxHeight: 400, overflow: "hidden", zIndex: 12500, padding: 15, backgroundColor: theme.palette.surfaceColor, border: "1px solid rgba(255,255,255,0.2)", position: "absolute", top: diff, right: 50, }}>
<Typography style={{textAlign: "center"}}>
Usecase {index+1}
</Typography>
<div style={{display: "flex", width: 200, margin: "auto", marginTop: 15, }}>
<div style={{backgroundColor: theme.palette.inputColor, height: 75, width: 75, borderRadius: theme.palette.borderRadius, border: "1px solid rgba(255,255,255,0.7)", marginRight: 15,}}>
</div>
<div style={{backgroundColor: theme.palette.inputColor, maxHeight: 30, maxWidth: 30, height: 30, width: 30, borderRadius: theme.palette.borderRadius, border: "1px solid rgba(255,255,255,0.7)", marginTop: 22, padding: "10px 0px 0px 9px",}}>
{svgIcon}
</div>
<div style={{backgroundColor: theme.palette.inputColor, height: 75, width: 75, borderRadius: theme.palette.borderRadius, border: "1px solid rgba(255,255,255,0.7)", marginLeft: 15,}}>
</div>
</div>
</Paper>
)
}
const selectedUsecases = [
{
"name": "Sync from ticket system 1 to 2 and back to 1",
"description": "Do cool shit weeeee - this just ensure they are syncing",
"image1": "cases",
"image2": "cases",
"direction": "both",
"automated": [
{
"source": "BOTTOM_LEFT",
"target": "COMMS",
"description": "Email received",
"human": false,
},
]
},
{
"name": "Send alerts when a ticket is created",
"description": "Do cool shit weeeee - this just ensure they are syncing",
"image1": "cases",
"image2": "comms",
"direction": "right",
"automated": [
{
"source": "BOTTOM_LEFT",
"target": "COMMS",
"description": "Email received",
"human": false,
},
]
}
]
//autounselectify={true} //autounselectify={true}
var usecasediff = -100
return ( return (
<div style={{margin: "auto", backgroundColor: theme.palette.surfaceColor, position: "relative", }}> <div style={{margin: "auto", backgroundColor: theme.palette.surfaceColor, position: "relative", }}>
{showOptions === false ? null : {showOptions === false ? null :
@@ -1121,6 +1202,19 @@ const Framework = (props) => {
})} })}
</div> </div>
} }
{
Object.getOwnPropertyNames(discoveryData).length > 0 ?
<div>
{selectedUsecases.map((data, index) => {
usecasediff += 175
return (
<UsecaseHandler data={data} index={index} key={index} diff={usecasediff} />
)
})}
</div>
: null}
{ {
Object.getOwnPropertyNames(discoveryData).length > 0 ? Object.getOwnPropertyNames(discoveryData).length > 0 ?
<Paper style={{width: 250, maxHeight: 400, overflow: "hidden", zIndex: 12500, padding: 25, paddingRight: 35, backgroundColor: theme.palette.surfaceColor, border: "1px solid rgba(255,255,255,0.2)", position: "absolute", top: 50, left: 50, }}> <Paper style={{width: 250, maxHeight: 400, overflow: "hidden", zIndex: 12500, padding: 25, paddingRight: 35, backgroundColor: theme.palette.surfaceColor, border: "1px solid rgba(255,255,255,0.2)", position: "absolute", top: 50, left: 50, }}>
@@ -1132,6 +1226,9 @@ const Framework = (props) => {
<IconButton <IconButton
style={{ zIndex: 12501, position: "absolute", top: 10, right: 10}} style={{ zIndex: 12501, position: "absolute", top: 10, right: 10}}
onClick={(e) => { onClick={(e) => {
//cy.elements().unselectify();
cy.elements().unselect()
e.preventDefault(); e.preventDefault();
setDiscoveryData({}) setDiscoveryData({})
setDefaultSearch("") setDefaultSearch("")
+36 -14
View File
@@ -3586,7 +3586,7 @@ const Admin = (props) => {
<h2 style={{ display: "inline" }}>App Authentication</h2> <h2 style={{ display: "inline" }}>App Authentication</h2>
<span style={{ marginLeft: 25 }}> <span style={{ marginLeft: 25 }}>
Control the authentication options for individual apps.{" "} Control the authentication options for individual apps.{" "}
<b>Actions can be destructive!</b> PS: Actions performed here can be destructive!
</span> </span>
&nbsp; &nbsp;
<a <a
@@ -3594,7 +3594,7 @@ const Admin = (props) => {
href="https://shuffler.io/docs/organizations#app_authentication" href="https://shuffler.io/docs/organizations#app_authentication"
style={{ textDecoration: "none", color: "#f85a3e" }} style={{ textDecoration: "none", color: "#f85a3e" }}
> >
Learn more Learn more about authentication
</a> </a>
</div> </div>
<Divider <Divider
@@ -3618,21 +3618,27 @@ const Admin = (props) => {
primary="App Name" primary="App Name"
style={{ minWidth: 175, maxWidth: 175, marginLeft: 10 }} style={{ minWidth: 175, maxWidth: 175, marginLeft: 10 }}
/> />
<ListItemText {/*<ListItemText
primary="Ready" primary="Ready"
style={{ minWidth: 100, maxWidth: 100 }} style={{ minWidth: 100, maxWidth: 100 }}
/> />*/}
<ListItemText <ListItemText
primary="Workflows" primary="Workflows"
style={{ minWidth: 110, maxWidth: 110, overflow: "hidden" }} style={{ minWidth: 100, maxWidth: 100, overflow: "hidden" }}
/> />
{/*
<ListItemText <ListItemText
primary="Actions" primary="App Usage"
style={{ minWidth: 110, maxWidth: 110, overflow: "hidden" }} style={{ minWidth: 100, maxWidth: 100, overflow: "hidden" }}
/> />
*/}
<ListItemText <ListItemText
primary="Fields" primary="Fields"
style={{ minWidth: 200, maxWidth: 200, overflow: "hidden" }} style={{ minWidth: 125, maxWidth: 125, overflow: "hidden" }}
/>
<ListItemText
primary="Last Edited"
style={{ minWidth: 225, maxWidth: 225, overflow: "hidden" }}
/> />
<ListItemText primary="Actions" /> <ListItemText primary="Actions" />
</ListItem> </ListItem>
@@ -3644,13 +3650,15 @@ const Admin = (props) => {
bgColor = "#1f2023"; bgColor = "#1f2023";
} }
console.log("Auth data: ", data)
return ( return (
<ListItem key={index} style={{ backgroundColor: bgColor }}> <ListItem key={index} style={{ backgroundColor: bgColor }}>
<ListItemText <ListItemText
primary=<img primary=<img
alt="" alt=""
src={data.app.large_image} src={data.app.large_image}
style={{ maxWidth: 50 }} style={{ maxWidth: 50, borderRadius: theme.palette.borderRadius, }}
/> />
style={{ minWidth: 75, maxWidth: 75 }} style={{ minWidth: 75, maxWidth: 75 }}
/> />
@@ -3666,28 +3674,34 @@ const Admin = (props) => {
primary={data.app.name} primary={data.app.name}
style={{ minWidth: 175, maxWidth: 175, marginLeft: 10 }} style={{ minWidth: 175, maxWidth: 175, marginLeft: 10 }}
/> />
{/*
<ListItemText <ListItemText
primary={data.defined === false ? "No" : "Yes"} primary={data.defined === false ? "No" : "Yes"}
style={{ minWidth: 100, maxWidth: 100, marginLeft: 10 }} style={{ minWidth: 100, maxWidth: 100, }}
/> />
*/}
<ListItemText <ListItemText
primary={ primary={
data.workflow_count === null ? 0 : data.workflow_count data.workflow_count === null ? 0 : data.workflow_count
} }
style={{ style={{
minWidth: 110, minWidth: 100,
maxWidth: 110, maxWidth: 100,
textAlign: "center",
overflow: "hidden", overflow: "hidden",
}} }}
/> />
{/*
<ListItemText <ListItemText
primary={data.node_count} primary={data.node_count}
style={{ style={{
minWidth: 110, minWidth: 110,
maxWidth: 110, maxWidth: 110,
textAlign: "center",
overflow: "hidden", overflow: "hidden",
}} }}
/> />
*/}
<ListItemText <ListItemText
primary={ primary={
data.fields === null || data.fields === undefined data.fields === null || data.fields === undefined
@@ -3699,11 +3713,19 @@ const Admin = (props) => {
.join(", ") .join(", ")
} }
style={{ style={{
minWidth: 200, minWidth: 125,
maxWidth: 200, maxWidth: 125,
overflow: "hidden", overflow: "hidden",
}} }}
/> />
<ListItemText
style={{
maxWidth: 225,
minWidth: 225,
overflow: "hidden",
}}
primary={new Date(data.edited * 1000).toISOString()}
/>
<ListItemText> <ListItemText>
<IconButton <IconButton
onClick={() => { onClick={() => {
+2
View File
@@ -3340,6 +3340,8 @@ const AngularWorkflow = (defaultprops) => {
typeof window === "undefined" || window.location === undefined typeof window === "undefined" || window.location === undefined
? "" ? ""
: window.location.search; : window.location.search;
// FIXME: Don't check specific one here
const tmpExec = new URLSearchParams(cursearch).get("execution_highlight"); const tmpExec = new URLSearchParams(cursearch).get("execution_highlight");
if ( if (
tmpExec !== undefined && tmpExec !== undefined &&
+102 -66
View File
@@ -1426,6 +1426,10 @@ const AppCreator = (defaultprops) => {
setParameterName(value.name); setParameterName(value.name);
setAuthenticationRequired(true); setAuthenticationRequired(true);
if (value.description !== undefined && value.description !== null && value.description.length > 0) {
setRefreshUrl(value.description)
}
} else if (value.scheme === "basic") { } else if (value.scheme === "basic") {
setAuthenticationOption("Basic auth"); setAuthenticationOption("Basic auth");
setAuthenticationRequired(true); setAuthenticationRequired(true);
@@ -1702,6 +1706,13 @@ const AppCreator = (defaultprops) => {
//break //break
} }
if (queryitem.name.toLowerCase() == "file_id") {
item.queries[querykey].name = "fileid"
continue;
//skipped = true
//break
}
if ( if (
queryitem.name.toLowerCase() == "url" || queryitem.name.toLowerCase() == "url" ||
queryitem.name.toLowerCase() == "body" || queryitem.name.toLowerCase() == "body" ||
@@ -1733,7 +1744,8 @@ const AppCreator = (defaultprops) => {
console.log( console.log(
item.name + " error: uses a bad query - not adding: ", item.name + " error: uses a bad query - not adding: ",
queryitem.name queryitem.name
); )
continue; continue;
} }
@@ -1996,7 +2008,8 @@ const AppCreator = (defaultprops) => {
type: "apiKey", type: "apiKey",
in: parameterLocation.toLowerCase(), in: parameterLocation.toLowerCase(),
name: newparamName, name: newparamName,
}; description: refreshUrl,
}
} else if (authenticationOption === "Bearer auth") { } else if (authenticationOption === "Bearer auth") {
data.components.securitySchemes["BearerAuth"] = { data.components.securitySchemes["BearerAuth"] = {
type: "http", type: "http",
@@ -2240,7 +2253,7 @@ const AppCreator = (defaultprops) => {
<Button <Button
color="primary" color="primary"
style={{ maxWidth: 50, marginLeft: 15 }} style={{ maxWidth: 50, marginLeft: 15 }}
variant="contained" variant="outlined"
onClick={() => { onClick={() => {
console.log("ADD NEW!"); console.log("ADD NEW!");
extraAuth.push(defaultAuth); extraAuth.push(defaultAuth);
@@ -2631,71 +2644,94 @@ const AppCreator = (defaultprops) => {
<div style={{ color: "white", marginTop: 20 }}> <div style={{ color: "white", marginTop: 20 }}>
<Typography variant="body1">API key authentication</Typography> <Typography variant="body1">API key authentication</Typography>
<Typography variant="body2" color="textSecondary"> <Typography variant="body2" color="textSecondary">
Add the name of the field used for authentication, e.g. "X-APIKEY" Add the name of the field used for authentication, e.g. "X-APIKEY". Should NOT be your actual API-key.
</Typography> </Typography>
<TextField <div style={{display: "flex", marginTop: 10, }}>
required <div style={{flex: 4,}}>
style={{ flex: "1", backgroundColor: inputColor }} Key
fullWidth={true} <TextField
placeholder="Field Name (not token)" required
type="name" style={{ marginTop: 0, backgroundColor: inputColor }}
id="standard-required" fullWidth={true}
margin="normal" placeholder="Field Name (key, NOT your actual API-key)"
variant="outlined" type="name"
value={parameterName} id="standard-required"
helperText={ margin="normal"
<span style={{ color: "white", marginBottom: "2px" }}> variant="outlined"
Can't be empty. Can't contain any of the following characters: value={parameterName}
!#$%&'^"+-._~|]+$ helperText={
</span> <span style={{ color: "white", marginBottom: "2px" }}>
} Can't be empty or contain any of the following: !#$%&'^"+-._~|]+$
onChange={(e) => { </span>
setParameterName(e.target.value); }
}} onChange={(e) => {
InputProps={{ setParameterName(e.target.value);
classes: { }}
notchedOutline: classes.notchedOutline, InputProps={{
}, classes: {
style: { notchedOutline: classes.notchedOutline,
color: "white", },
}, style: {
}} color: "white",
/> },
Field type }}
<Select />
fullWidth </div>
onChange={(e) => { <div style={{marginLeft: 5, flex: 1,}}>
setParameterLocation(e.target.value); Field type
}} <Select
value={parameterLocation} fullWidth
style={{ onChange={(e) => {
borderRadius: 5, setParameterLocation(e.target.value);
backgroundColor: inputColor, }}
paddingLeft: "10px", value={parameterLocation}
color: "white", style={{
height: "50px", borderRadius: 5,
}} backgroundColor: inputColor,
inputProps={{ paddingLeft: 10,
name: "age", color: "white",
id: "outlined-age-simple", height: 57,
}} }}
> inputProps={{
{apikeySelection.map((data, index) => { name: "age",
if (data === undefined) { id: "outlined-age-simple",
return null; }}
} >
{apikeySelection.map((data, index) => {
if (data === undefined) {
return null;
}
return ( return (
<MenuItem <MenuItem
key={index} key={index}
style={{ backgroundColor: inputColor, color: "white" }} style={{ backgroundColor: inputColor, color: "white" }}
value={data} value={data}
> >
{data} {data}
</MenuItem> </MenuItem>
); );
})} })}
</Select> </Select>
</div>
<div style={{marginLeft: 5, flex: 1,}}>
Value prefix
<TextField
style={{ marginTop: 0, flex: "1", backgroundColor: inputColor }}
fullWidth={true}
placeholder="Token, SSWS..."
type="name"
id="standard-notrequired"
margin="normal"
variant="outlined"
value={refreshUrl}
onChange={(e) => {
// Just reusing this state
setRefreshUrl(e.target.value);
}}
/>
</div>
</div>
</div> </div>
) : null; ) : null;
+54 -10
View File
@@ -1,6 +1,7 @@
import React, { useRef, useState, useEffect, useLayoutEffect } from "react"; import React, { useRef, useState, useEffect, useLayoutEffect } from "react";
import { Typography, CircularProgress } from "@material-ui/core"; import { Typography, CircularProgress } from "@material-ui/core";
import theme from '../theme';
const SetAuthentication = (props) => { const SetAuthentication = (props) => {
const { globalUrl, isLoggedIn, isLoaded, userdata } = props; const { globalUrl, isLoggedIn, isLoaded, userdata } = props;
@@ -127,22 +128,57 @@ const SetAuthentication = (props) => {
body: JSON.stringify(appAuthData), body: JSON.stringify(appAuthData),
}) })
.then((response) => { .then((response) => {
const cursearch = typeof window === "undefined" || window.location === undefined ? "" : window.location.search;
const tmpView = new URLSearchParams(cursearch).get("state");
if (
tmpView !== undefined &&
tmpView !== null &&
tmpView.length > 0
) {
console.log("State to find app name from: ", tmpView)
}
if (response.status !== 200) { if (response.status !== 200) {
console.log("Status not 200 for oauth2 authentication"); console.log("Status not 200 for oauth2 authentication");
setFailed(true); setFailed(true);
} } else {
setFinished(true);
setTimeout(() => {
window.close();
}, 2500);
}
return response.json(); return response.json();
}) })
.then((responseJson) => { .then((responseJson) => {
//setUserSettings(responseJson) //setUserSettings(responseJson)
console.log("Resp: ", responseJson); console.log("Resp: ", responseJson);
setFinished(true);
setResponse(responseJson.reason);
setTimeout(() => { if (responseJson.reason !== undefined) {
window.close(); setResponse(responseJson.reason);
}, 1000); setFinished(true);
} else {
const cursearch = typeof window === "undefined" || window.location === undefined ? "" : window.location.search;
var tmpView = new URLSearchParams(cursearch).get("error_description");
if (
tmpView !== undefined &&
tmpView !== null &&
tmpView.length > 0
) {
setResponse(tmpView)
} else {
tmpView = new URLSearchParams(cursearch).get("error");
if (
tmpView !== undefined &&
tmpView !== null &&
tmpView.length > 0
) {
setResponse(tmpView)
}
}
}
}) })
.catch((error) => { .catch((error) => {
console.log(error); console.log(error);
@@ -150,15 +186,23 @@ const SetAuthentication = (props) => {
} }
return ( return (
<div style={{ width: 1000, margin: "auto", itemAlign: "center" }}> <div style={{ maringTop: 50, padding: 50, border: "1px solid rgba(255,255,255,0.6)", borderRadius: theme.palette.borderRadius, width: 500, margin: "auto", itemAlign: "center", textAlign: "center",}}>
<Typography
variant="h4"
style={{ marginLeft: "auto", marginRight: "auto", marginTop: 50}}
>
Oauth2 setup
</Typography>
<Typography <Typography
variant="h6" variant="h6"
style={{ marginLeft: "auto", marginRight: "auto", marginTop: 200 }} style={{ marginLeft: "auto", marginRight: "auto", marginTop: 50}}
> >
{!finished ? ( {!finished ? (
<CircularProgress /> failed ?
null :
<CircularProgress />
) : ( ) : (
"DONE WITH AUTH - this will close soon!!" "Done - this window should close within 3 seconds."
)} )}
<div /> <div />
{failed ? "Failed setup. Error: " : ""} {response} {failed ? "Failed setup. Error: " : ""} {response}