Merge branch 'setheal-import-openapi-as-file' into launch
This commit is contained in:
@@ -0,0 +1,84 @@
|
|||||||
|
import React, { useRef, useState } from 'react';
|
||||||
|
import { useEffect } from 'react';
|
||||||
|
import BackupIcon from '@material-ui/icons/Backup';
|
||||||
|
|
||||||
|
const dragOverStyle = {
|
||||||
|
backgroundColor: 'rgba(0,0,0,0.8)',
|
||||||
|
border: '5px dashed white',
|
||||||
|
borderRadius: '8px',
|
||||||
|
width: '100%',
|
||||||
|
height: '100%',
|
||||||
|
position: 'absolute',
|
||||||
|
overflow: 'hidden',
|
||||||
|
zIndex: 100,
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center'
|
||||||
|
};
|
||||||
|
|
||||||
|
const Dropzone = ({ children, style, onDrop }) => {
|
||||||
|
const dropzoneRef = useRef(null);
|
||||||
|
const [dragging, setDragging] = useState(false);
|
||||||
|
|
||||||
|
let dragCounter = 0;
|
||||||
|
|
||||||
|
const handleDragOver = (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDragEnter = (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
dragCounter++;
|
||||||
|
if (e.dataTransfer.items && e.dataTransfer.items.length > 0)
|
||||||
|
setDragging(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDragLeave = (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
dragCounter--;
|
||||||
|
if (dragCounter === 0) setDragging(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDrop = (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
setDragging(false);
|
||||||
|
if (e.dataTransfer.files && e.dataTransfer.files.length > 0) {
|
||||||
|
onDrop(e);
|
||||||
|
e.dataTransfer.clearData();
|
||||||
|
dragCounter = 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!dropzoneRef.current) return;
|
||||||
|
|
||||||
|
dropzoneRef.current.addEventListener('dragover', handleDragOver);
|
||||||
|
dropzoneRef.current.addEventListener('dragenter', handleDragEnter);
|
||||||
|
dropzoneRef.current.addEventListener('dragleave', handleDragLeave);
|
||||||
|
dropzoneRef.current.addEventListener('drop', handleDrop);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
dropzoneRef.current.removeEventListener('dragover', handleDragOver);
|
||||||
|
dropzoneRef.current.removeEventListener('dragenter', handleDragEnter);
|
||||||
|
dropzoneRef.current.removeEventListener('dragleave', handleDragLeave);
|
||||||
|
dropzoneRef.current.removeEventListener('drop', handleDrop);
|
||||||
|
};
|
||||||
|
}, [dropzoneRef]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div ref={dropzoneRef} style={{ position: 'relative', ...style }}>
|
||||||
|
{dragging && (
|
||||||
|
<div style={dragOverStyle}>
|
||||||
|
<BackupIcon fontSize="large" />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Dropzone;
|
||||||
+55
-28
@@ -1,4 +1,4 @@
|
|||||||
import React, { useEffect} from 'react';
|
import React, { useEffect } from 'react';
|
||||||
|
|
||||||
import { useInterval } from 'react-powerhooks';
|
import { useInterval } from 'react-powerhooks';
|
||||||
|
|
||||||
@@ -37,6 +37,7 @@ import DialogActions from '@material-ui/core/DialogActions';
|
|||||||
import DialogContent from '@material-ui/core/DialogContent';
|
import DialogContent from '@material-ui/core/DialogContent';
|
||||||
import CircularProgress from '@material-ui/core/CircularProgress';
|
import CircularProgress from '@material-ui/core/CircularProgress';
|
||||||
|
|
||||||
|
import Dropzone from '../components/Dropzone';
|
||||||
|
|
||||||
const surfaceColor = "#27292D"
|
const surfaceColor = "#27292D"
|
||||||
const inputColor = "#383B40"
|
const inputColor = "#383B40"
|
||||||
@@ -134,6 +135,9 @@ const Apps = (props) => {
|
|||||||
const [cursearch, setCursearch] = React.useState("")
|
const [cursearch, setCursearch] = React.useState("")
|
||||||
const [sharingConfiguration, setSharingConfiguration] = React.useState("you")
|
const [sharingConfiguration, setSharingConfiguration] = React.useState("you")
|
||||||
|
|
||||||
|
const [isDropzone, setIsDropzone] = React.useState(false);
|
||||||
|
const upload = React.useRef(null);
|
||||||
|
|
||||||
const { start, stop } = useInterval({
|
const { start, stop } = useInterval({
|
||||||
duration: 5000,
|
duration: 5000,
|
||||||
startImmediate: false,
|
startImmediate: false,
|
||||||
@@ -177,7 +181,6 @@ const Apps = (props) => {
|
|||||||
color: "#ffffff",
|
color: "#ffffff",
|
||||||
width: "100%",
|
width: "100%",
|
||||||
display: "flex",
|
display: "flex",
|
||||||
margin: 20,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const paperAppStyle = {
|
const paperAppStyle = {
|
||||||
@@ -790,8 +793,38 @@ const Apps = (props) => {
|
|||||||
//}
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const uploadFile = (e) => {
|
||||||
|
const isDropzone = e.dataTransfer?.files.length > 0;
|
||||||
|
const files = isDropzone ? e.dataTransfer.files : e.target.files;
|
||||||
|
|
||||||
|
const reader = new FileReader();
|
||||||
|
|
||||||
|
reader.addEventListener('load', (e) => {
|
||||||
|
const content = e.target.result;
|
||||||
|
setOpenApiData(content);
|
||||||
|
setIsDropzone(isDropzone);
|
||||||
|
setOpenApiModal(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
reader.readAsText(files[0]);
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (openApiData.length > 0) {
|
||||||
|
setOpenApiError('');
|
||||||
|
validateOpenApi(openApiData);
|
||||||
|
}
|
||||||
|
}, [openApiData]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (appValidation && isDropzone) {
|
||||||
|
redirectOpenApi();
|
||||||
|
setIsDropzone(false);
|
||||||
|
}
|
||||||
|
}, [appValidation, isDropzone]);
|
||||||
|
|
||||||
const appView = isLoggedIn ?
|
const appView = isLoggedIn ?
|
||||||
<div style={{maxWidth: window.innerWidth > 1366 ? 1366 : 1200, margin: "auto",}}>
|
<Dropzone style={{maxWidth: window.innerWidth > 1366 ? 1366 : 1200, margin: "auto", padding: 20 }} onDrop={uploadFile}>
|
||||||
<div style={appViewStyle}>
|
<div style={appViewStyle}>
|
||||||
<div style={{flex: 1}}>
|
<div style={{flex: 1}}>
|
||||||
<Breadcrumbs aria-label="breadcrumb" separator="›" style={{color: "white",}}>
|
<Breadcrumbs aria-label="breadcrumb" separator="›" style={{color: "white",}}>
|
||||||
@@ -903,7 +936,7 @@ const Apps = (props) => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</Dropzone>
|
||||||
:
|
:
|
||||||
null
|
null
|
||||||
|
|
||||||
@@ -1174,7 +1207,7 @@ const Apps = (props) => {
|
|||||||
})
|
})
|
||||||
.then((responseJson) => {
|
.then((responseJson) => {
|
||||||
if (responseJson.success) {
|
if (responseJson.success) {
|
||||||
setAppValidation(responseJson.id)
|
setAppValidation(responseJson.id);
|
||||||
} else {
|
} else {
|
||||||
if (responseJson.reason !== undefined) {
|
if (responseJson.reason !== undefined) {
|
||||||
setOpenApiError(responseJson.reason)
|
setOpenApiError(responseJson.reason)
|
||||||
@@ -1327,7 +1360,7 @@ const Apps = (props) => {
|
|||||||
</Dialog>
|
</Dialog>
|
||||||
: null
|
: null
|
||||||
|
|
||||||
const errorText = openApiError.length > 0 ? <div>Error: {openApiError}</div> : null
|
const errorText = openApiError.length > 0 ? <div style={{marginTop: 10}}>Error: {openApiError}</div> : null
|
||||||
const modalView = openApiModal ?
|
const modalView = openApiModal ?
|
||||||
<Dialog
|
<Dialog
|
||||||
open={openApiModal}
|
open={openApiModal}
|
||||||
@@ -1376,28 +1409,22 @@ const Apps = (props) => {
|
|||||||
<div />
|
<div />
|
||||||
https://raw.githubusercontent.com/OAI/OpenAPI-Specification/master/examples/v2.0/json/uber.json
|
https://raw.githubusercontent.com/OAI/OpenAPI-Specification/master/examples/v2.0/json/uber.json
|
||||||
*/}
|
*/}
|
||||||
Or paste the YAML or JSON specification
|
<p>Or upload a YAML or JSON specification</p>
|
||||||
<TextField
|
<input
|
||||||
style={{backgroundColor: inputColor}}
|
hidden
|
||||||
variant="outlined"
|
type="file"
|
||||||
multiline
|
ref={upload}
|
||||||
rows={6}
|
accept="application/JSON, text/yaml, text/x-yaml, application/x-yaml, application/vnd.yaml"
|
||||||
margin="normal"
|
multiple={false}
|
||||||
InputProps={{
|
onChange={uploadFile}
|
||||||
style:{
|
/>
|
||||||
color: "white",
|
<Button
|
||||||
fontSize: "1em",
|
variant="contained"
|
||||||
},
|
color="primary"
|
||||||
endAdornment: <Button style={{marginLeft: 10, borderRadius: "0px", marginTop: "0px"}} variant="contained" disabled={openApiData.length === 0 || appValidation.length > 0} color="primary" onClick={() => {
|
onClick={() => upload.current.click()}
|
||||||
setOpenApiError("")
|
>
|
||||||
validateOpenApi(openApiData)
|
Upload
|
||||||
}}>Validate OpenAPI</Button>
|
</Button>
|
||||||
}}
|
|
||||||
onChange={e => setOpenApiData(e.target.value)}
|
|
||||||
helperText={<span style={{color:"white", marginBottom: "2px",}}>Must point to a version 2 or 3 specification.</span>}
|
|
||||||
placeholder="OpenAPI text"
|
|
||||||
fullWidth
|
|
||||||
/>
|
|
||||||
{errorText}
|
{errorText}
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
<DialogActions>
|
<DialogActions>
|
||||||
|
|||||||
Reference in New Issue
Block a user