|
|
|
@ -2,11 +2,12 @@ import React, { useEffect, useState } from 'react';
|
|
|
|
|
import { observer } from 'mobx-react'; |
|
|
|
|
import { useStores } from '../hooks/useStores'; |
|
|
|
|
// prettier-ignore
|
|
|
|
|
import { Button, ButtonGroup, Collapse, ControlGroup, H1, H3, H4, HTMLTable, Icon, Intent, Tab, Tabs, Tag, Tooltip } from '@blueprintjs/core'; |
|
|
|
|
import { Button, Switch, Collapse, ControlGroup, H1, H3, H4, HTMLTable, Icon, Intent, Tab, Tabs, Tag, Tooltip, TextArea } from '@blueprintjs/core'; |
|
|
|
|
import { Link, useParams } from 'react-router-dom'; |
|
|
|
|
import { ControlledEditor as Editor } from '@monaco-editor/react'; |
|
|
|
|
import { toJS } from 'mobx'; |
|
|
|
|
import Box from './_common/Box'; |
|
|
|
|
import ReactJson from 'react-json-view'; |
|
|
|
|
|
|
|
|
|
const ApiReference = observer(props => { |
|
|
|
|
const { rootStore } = useStores(); |
|
|
|
@ -20,6 +21,8 @@ const ApiReference = observer(props => {
|
|
|
|
|
let [currentApi, setCurrentApi] = useState(null); |
|
|
|
|
let [currentTime, setCurrentTime] = useState(0); |
|
|
|
|
let [working, setWorking] = useState(false); |
|
|
|
|
let [treeReq, setTreeReq] = useState(true); |
|
|
|
|
let [treeRes, setTreeRes] = useState(true); |
|
|
|
|
|
|
|
|
|
useEffect(() => { |
|
|
|
|
getAPIs(() => { |
|
|
|
@ -69,6 +72,41 @@ const ApiReference = observer(props => {
|
|
|
|
|
marginBottom: 4, |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
function getFancyPrivitiveType(str) { |
|
|
|
|
if (str === 'Boolean') return 'bool'; |
|
|
|
|
if (str === 'Int32') return 'int'; |
|
|
|
|
if (str === 'String') return 'string'; |
|
|
|
|
return str; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function getFancyType(str) { |
|
|
|
|
if (str === '') return '""'; |
|
|
|
|
|
|
|
|
|
if (str === 'System.Boolean') return 'bool'; |
|
|
|
|
if (str === 'System.Int32') return 'int'; |
|
|
|
|
if (str === 'System.String') return 'string'; |
|
|
|
|
|
|
|
|
|
if (str.includes('List`1')) { |
|
|
|
|
let matches = str.match(/\[(.*?)\]/); |
|
|
|
|
|
|
|
|
|
if (matches) { |
|
|
|
|
let string = matches[1]; |
|
|
|
|
let ret = string.split('.'); |
|
|
|
|
return `List<${getFancyPrivitiveType(ret.pop())}>`; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (!str.includes('`')) { |
|
|
|
|
let matches = str.match(/(?<=\.)[^.]*$/); |
|
|
|
|
|
|
|
|
|
if (matches) { |
|
|
|
|
return matches[0]; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return str; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const infoPanel = ( |
|
|
|
|
<> |
|
|
|
|
{!!apiSearch && !!apis && !!currentApi && !!currentApi.Request && ( |
|
|
|
@ -96,9 +134,19 @@ const ApiReference = observer(props => {
|
|
|
|
|
{currentApi.Request.Fields.map(r => { |
|
|
|
|
return ( |
|
|
|
|
<tr> |
|
|
|
|
<td>{r.Name}</td> |
|
|
|
|
<td>{r.Type}</td> |
|
|
|
|
<td>{r.DefaultValue}</td> |
|
|
|
|
<td style={{ minWidth: '350px' }}> |
|
|
|
|
<code>{r.Name}</code> |
|
|
|
|
</td> |
|
|
|
|
<td style={{ minWidth: '100px' }}> |
|
|
|
|
<Tooltip content={r.Type}> |
|
|
|
|
<Tag minimal>{getFancyType(r.Type)}</Tag> |
|
|
|
|
</Tooltip> |
|
|
|
|
</td> |
|
|
|
|
<td style={{ minWidth: '100px' }}> |
|
|
|
|
<Tooltip content={r.DefaultValue}> |
|
|
|
|
<Tag minimal>{getFancyType(r.DefaultValue)}</Tag> |
|
|
|
|
</Tooltip> |
|
|
|
|
</td> |
|
|
|
|
</tr> |
|
|
|
|
); |
|
|
|
|
})} |
|
|
|
@ -128,9 +176,19 @@ const ApiReference = observer(props => {
|
|
|
|
|
{currentApi.Response.Fields.map(r => { |
|
|
|
|
return ( |
|
|
|
|
<tr> |
|
|
|
|
<td>{r.Name}</td> |
|
|
|
|
<td>{r.Type}</td> |
|
|
|
|
<td>{r.DefaultValue}</td> |
|
|
|
|
<td style={{ minWidth: '350px' }}> |
|
|
|
|
<code>{r.Name}</code> |
|
|
|
|
</td> |
|
|
|
|
<td style={{ minWidth: '100px' }}> |
|
|
|
|
<Tooltip content={r.Type}> |
|
|
|
|
<Tag minimal>{getFancyType(r.Type)}</Tag> |
|
|
|
|
</Tooltip> |
|
|
|
|
</td> |
|
|
|
|
<td style={{ minWidth: '100px' }}> |
|
|
|
|
<Tooltip content={r.DefaultValue}> |
|
|
|
|
<Tag minimal>{getFancyType(r.DefaultValue)}</Tag> |
|
|
|
|
</Tooltip> |
|
|
|
|
</td> |
|
|
|
|
</tr> |
|
|
|
|
); |
|
|
|
|
})} |
|
|
|
@ -142,45 +200,94 @@ const ApiReference = observer(props => {
|
|
|
|
|
</> |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
function tryParse(json) { |
|
|
|
|
try { |
|
|
|
|
return JSON.parse(json); |
|
|
|
|
} catch { |
|
|
|
|
return ''; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const editorTheme = darkTheme ? 'codeschool' : 'rjv-default'; |
|
|
|
|
|
|
|
|
|
const testPanel = ( |
|
|
|
|
<> |
|
|
|
|
<div style={{ display: 'flex' }}> |
|
|
|
|
<div style={{ border: '1px solid #BFCCD6' }}> |
|
|
|
|
<Editor |
|
|
|
|
width="300px" |
|
|
|
|
height="300px" |
|
|
|
|
language="javascript" |
|
|
|
|
value={currentRequest} |
|
|
|
|
onChange={(e, v) => { |
|
|
|
|
setCurrentRequest(v); |
|
|
|
|
console.log('onChange'); |
|
|
|
|
}} |
|
|
|
|
theme={darkTheme ? 'dark' : 'light'} |
|
|
|
|
options={{ |
|
|
|
|
codeLens: false, |
|
|
|
|
}} |
|
|
|
|
/> |
|
|
|
|
<div style={{ minWidth: '50%', width: '50%', marginRight: '.2rem' }}> |
|
|
|
|
<Switch checked={treeReq} label="Tree view" onChange={() => setTreeReq(!treeReq)} /> |
|
|
|
|
{!treeReq && ( |
|
|
|
|
<TextArea |
|
|
|
|
style={{ height: '500px' }} |
|
|
|
|
fill={true} |
|
|
|
|
value={currentRequest} |
|
|
|
|
onChange={e => { |
|
|
|
|
setCurrentRequest(e.target.value); |
|
|
|
|
}} |
|
|
|
|
/> |
|
|
|
|
)} |
|
|
|
|
{treeReq && !!currentRequest && ( |
|
|
|
|
<ReactJson |
|
|
|
|
theme={editorTheme} |
|
|
|
|
src={tryParse(currentRequest)} |
|
|
|
|
onEdit={e => { |
|
|
|
|
setCurrentRequest(JSON.stringify(e.updated_src)); |
|
|
|
|
}} |
|
|
|
|
displayDataTypes={false} |
|
|
|
|
displayObjectSize={false} |
|
|
|
|
onAdd={() => { |
|
|
|
|
return true; |
|
|
|
|
}} |
|
|
|
|
style={{ |
|
|
|
|
border: `1px solid ${darkTheme ? '#262626' : '#BFCCD6'}`, |
|
|
|
|
borderRadius: '3px 0 0 3px', |
|
|
|
|
height: '500px', |
|
|
|
|
maxHeight: '500px', |
|
|
|
|
overflow: 'auto', |
|
|
|
|
padding: '10px', |
|
|
|
|
}} |
|
|
|
|
/> |
|
|
|
|
)} |
|
|
|
|
</div> |
|
|
|
|
<div> |
|
|
|
|
<Editor |
|
|
|
|
width="300px" |
|
|
|
|
height="300px" |
|
|
|
|
language="javascript" |
|
|
|
|
value={testResult} |
|
|
|
|
theme={darkTheme ? 'dark' : 'light'} |
|
|
|
|
/> |
|
|
|
|
<div style={{ minWidth: '50%' }}> |
|
|
|
|
<Switch checked={treeRes} label="Tree view" onChange={() => setTreeRes(!treeRes)} /> |
|
|
|
|
{!treeRes && <TextArea fill={true} style={{ height: '500px' }} value={testResult} />} |
|
|
|
|
{treeRes && !!testResult && ( |
|
|
|
|
<ReactJson |
|
|
|
|
theme={editorTheme} |
|
|
|
|
src={tryParse(testResult)} |
|
|
|
|
displayDataTypes={false} |
|
|
|
|
displayObjectSize={false} |
|
|
|
|
style={{ |
|
|
|
|
height: '500px', |
|
|
|
|
border: `1px solid ${darkTheme ? '#262626' : '#BFCCD6'}`, |
|
|
|
|
borderRadius: '0 3px 3px 0', |
|
|
|
|
maxHeight: '500px', |
|
|
|
|
overflow: 'auto', |
|
|
|
|
padding: '10px', |
|
|
|
|
}} |
|
|
|
|
/> |
|
|
|
|
)} |
|
|
|
|
</div> |
|
|
|
|
</div> |
|
|
|
|
<Box> |
|
|
|
|
<ControlGroup fill={true} vertical={false}> |
|
|
|
|
<Button icon="reset">Reset</Button> |
|
|
|
|
<Button loading={working} icon="send-message" intent={Intent.PRIMARY} onClick={handleTest}> |
|
|
|
|
Go |
|
|
|
|
</Button> |
|
|
|
|
<div style={{ display: 'flex', justifyContent: 'space-between' }}> |
|
|
|
|
<div> |
|
|
|
|
<ControlGroup vertical={false}> |
|
|
|
|
<Button icon="reset">Reset</Button> |
|
|
|
|
<Button loading={working} icon="send-message" intent={Intent.PRIMARY} onClick={handleTest}> |
|
|
|
|
Go |
|
|
|
|
</Button> |
|
|
|
|
</ControlGroup> |
|
|
|
|
</div> |
|
|
|
|
<div className="bp3-running-text .modifier"> |
|
|
|
|
{!!currentTime && <p>{`Took ${currentTime} ms`}</p>} |
|
|
|
|
{!!currentTime && ( |
|
|
|
|
<p> |
|
|
|
|
<Icon style={{ marginRight: '.2rem' }} icon={'time'} /> |
|
|
|
|
{`${currentTime} ms`} |
|
|
|
|
</p> |
|
|
|
|
)} |
|
|
|
|
</div> |
|
|
|
|
</ControlGroup> |
|
|
|
|
</div> |
|
|
|
|
</Box> |
|
|
|
|
</> |
|
|
|
|
); |
|
|
|
@ -250,7 +357,7 @@ const ApiReference = observer(props => {
|
|
|
|
|
); |
|
|
|
|
})} |
|
|
|
|
</div> |
|
|
|
|
<div> |
|
|
|
|
<div style={{ width: '100%' }}> |
|
|
|
|
{!!apiSearch && !!apis && !!currentApi && ( |
|
|
|
|
<> |
|
|
|
|
<H3 style={{ display: 'inline-block', marginRight: '.5em' }}> |
|
|
|
|