mirror of
https://github.com/Redocly/redoc.git
synced 2025-09-24 04:56:39 +03:00
SG API docs
This commit is contained in:
parent
5a9e6a5633
commit
4b8a2da368
|
@ -1,53 +1,167 @@
|
|||
import * as React from 'react';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { render } from 'react-dom';
|
||||
import { AppContainer } from 'react-hot-loader';
|
||||
// import DevTools from 'mobx-react-devtools';
|
||||
|
||||
import { Redoc, RedocProps } from '../../src/components/Redoc/Redoc';
|
||||
import styled from 'styled-components';
|
||||
import { Loading } from '../../src';
|
||||
import { Redoc } from '../../src/components/Redoc/Redoc';
|
||||
import { AppStore } from '../../src/services/AppStore';
|
||||
import { RedocRawOptions } from '../../src/services/RedocNormalizedOptions';
|
||||
import { loadAndBundleSpec } from '../../src/utils/loadAndBundleSpec';
|
||||
|
||||
const renderRoot = (props: RedocProps) =>
|
||||
const API_SOURCES = [
|
||||
{ name: 'Supergrid', url: '../swagger/sg/swagger.json' },
|
||||
{ name: 'What If', url: '../swagger/t5/swagger.json' },
|
||||
];
|
||||
|
||||
const RedocPlayground = () => {
|
||||
const [store, setStore] = useState<AppStore | null>(null);
|
||||
const [selectedApi, setSelectedApi] = useState(0);
|
||||
const [showDownloadButton, setShowDownloadButton] = useState(true);
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
const redocOptions = {
|
||||
hideDownloadButton: window.location.protocol === 'file:',
|
||||
theme: {
|
||||
colors: {
|
||||
primary: {
|
||||
main: '#37B5FF',
|
||||
},
|
||||
},
|
||||
typography: {
|
||||
fontWeightRegular: '400',
|
||||
fontWeightBold: '700',
|
||||
fontWeightLight: '300',
|
||||
fontFamily: '\'Open Sans\', sans-serif',
|
||||
headings: {
|
||||
fontFamily: '\'Open Sans\', sans-serif',
|
||||
},
|
||||
},
|
||||
menu: {
|
||||
backgroundColor: '#fff',
|
||||
},
|
||||
logo: {
|
||||
maxWidth: '150px',
|
||||
maxHeight: '60px',
|
||||
gutter: '10px 20px',
|
||||
},
|
||||
rightPanel: {
|
||||
textColor: '#000',
|
||||
headerTextColor: '#697386',
|
||||
backgroundColor: '#fff',
|
||||
tabPanelBackgroundColor: '#f5f5f5',
|
||||
},
|
||||
codeSample: {
|
||||
endpointBackgroundColor: '#59618d',
|
||||
},
|
||||
schema: {
|
||||
defaultDetailsWidth: '100%',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const loadApi = async (apiIndex: number) => {
|
||||
try {
|
||||
setLoading(true);
|
||||
if (store) { store.dispose(); }
|
||||
|
||||
const specUrl = API_SOURCES[apiIndex].url;
|
||||
const spec = await loadAndBundleSpec(specUrl);
|
||||
const newStore = new AppStore(spec, specUrl, redocOptions);
|
||||
setStore(newStore);
|
||||
} catch (error) {
|
||||
console.error('Error loading API:', error);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (window.location.protocol === 'file:') {
|
||||
setShowDownloadButton(false);
|
||||
}
|
||||
loadApi(selectedApi);
|
||||
}, []);
|
||||
|
||||
const handleApiChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
|
||||
const newIndex = parseInt(e.target.value, 10);
|
||||
setSelectedApi(newIndex);
|
||||
loadApi(newIndex);
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Header>
|
||||
{showDownloadButton && (
|
||||
<DownloadButton
|
||||
target="_blank"
|
||||
href="../Export/ExportApiDoc"
|
||||
className="download-button"
|
||||
>
|
||||
Download HTML Version
|
||||
</DownloadButton>
|
||||
)}
|
||||
<span style={{ marginLeft: '14px' }}>
|
||||
<label htmlFor="ApiSources">Tempus Api: </label>
|
||||
<select id="ApiSources" value={selectedApi} onChange={handleApiChange}>
|
||||
{API_SOURCES.map((api, index) => (
|
||||
<option key={index} value={index}>{api.name}</option>
|
||||
))}
|
||||
</select>
|
||||
</span>
|
||||
</Header>
|
||||
|
||||
<div id="redoc">
|
||||
{loading && (
|
||||
<Loading color={redocOptions.theme.colors.primary.main} />
|
||||
)}
|
||||
{!loading && store && <Redoc store={store} />}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const Header = styled.div`
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
z-index: 200;
|
||||
text-align: right;
|
||||
height: 30px;
|
||||
padding: 19px;
|
||||
font-family: 'Open Sans', sans-serif;
|
||||
font-weight: 400;
|
||||
line-height: 1.5em;
|
||||
font-size: 14px;
|
||||
`;
|
||||
|
||||
const DownloadButton = styled.a`
|
||||
border: 1px solid rgb(55, 181, 255);
|
||||
color: rgb(55, 181, 255);
|
||||
font-weight: normal;
|
||||
margin-left: 0.5em;
|
||||
padding: 4px 8px;
|
||||
display: inline-block;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
box-sizing: border-box;
|
||||
-webkit-tap-highlight-color: rgba(255, 255, 255, 0);
|
||||
`;
|
||||
|
||||
// Рендеринг
|
||||
const renderRoot = () => {
|
||||
render(
|
||||
<AppContainer>
|
||||
<Redoc {...props} />
|
||||
<RedocPlayground />
|
||||
</AppContainer>,
|
||||
document.getElementById('example'),
|
||||
);
|
||||
};
|
||||
|
||||
const big = window.location.search.indexOf('big') > -1;
|
||||
const swagger = window.location.search.indexOf('swagger') > -1;
|
||||
|
||||
const userUrl = window.location.search.match(/url=(.*)$/);
|
||||
|
||||
const specUrl =
|
||||
(userUrl && userUrl[1]) || (swagger ? 'swagger.yaml' : big ? 'big-openapi.json' : 'openapi.yaml');
|
||||
|
||||
let store;
|
||||
const options: RedocRawOptions = { nativeScrollbars: false };
|
||||
|
||||
async function init() {
|
||||
const spec = await loadAndBundleSpec(specUrl);
|
||||
store = new AppStore(spec, specUrl, options);
|
||||
renderRoot({ store });
|
||||
}
|
||||
|
||||
init();
|
||||
renderRoot();
|
||||
|
||||
// Hot Module Replacement
|
||||
if (module.hot) {
|
||||
const reload = (reloadStore = false) => async () => {
|
||||
if (reloadStore) {
|
||||
// create a new Store
|
||||
store.dispose();
|
||||
|
||||
const state = await store.toJS();
|
||||
store = AppStore.fromJS(state);
|
||||
}
|
||||
|
||||
renderRoot({ store });
|
||||
};
|
||||
|
||||
module.hot.accept(['../../src/components/Redoc/Redoc'], reload());
|
||||
module.hot.accept(['../../src/services/AppStore'], reload(true));
|
||||
module.hot.accept(() => {
|
||||
renderRoot();
|
||||
});
|
||||
}
|
||||
|
|
|
@ -4,22 +4,29 @@
|
|||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>ReDoc</title>
|
||||
<title>Supergrid API Reference</title>
|
||||
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400,600,700&display=swap" rel="stylesheet">
|
||||
<link rel="shortcut icon" href="assets/favicon.ico" type="image/x-icon">
|
||||
<link rel="icon" href="../assets/plugins/redoc/assets/favicon.ico" type="image/x-icon" />
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
redoc {
|
||||
display: block;
|
||||
#example {
|
||||
width: 100%;
|
||||
}
|
||||
.tab-success .react-tabs__tab--selected {
|
||||
color: rgb(0, 170, 19);
|
||||
background-color: rgba(0, 170, 19, 0.1);
|
||||
border-color: transparent;
|
||||
}
|
||||
</style>
|
||||
<link href="https://fonts.googleapis.com/css?family=Montserrat:300,400,700|Roboto:300,400,700" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<redoc id="example"></redoc>
|
||||
<div id="example"></div>
|
||||
</body>
|
||||
|
||||
</html>
|
18690
demo/swagger/sg/swagger.json
Normal file
18690
demo/swagger/sg/swagger.json
Normal file
File diff suppressed because one or more lines are too long
2528
demo/swagger/t5/swagger.json
Normal file
2528
demo/swagger/t5/swagger.json
Normal file
File diff suppressed because it is too large
Load Diff
|
@ -98,7 +98,7 @@
|
|||
"html-webpack-plugin": "^3.1.0",
|
||||
"jest": "^24.8.0",
|
||||
"license-checker": "^25.0.1",
|
||||
"lodash": "^4.17.15",
|
||||
"lodash": "^4.17.21",
|
||||
"mobx": "^4.3.1",
|
||||
"prettier": "^1.18.2",
|
||||
"prettier-eslint": "^9.0.0",
|
||||
|
|
|
@ -74,7 +74,7 @@ export const PrismDiv = styled.div`
|
|||
.token.char,
|
||||
.token.builtin,
|
||||
.token.inserted {
|
||||
color: #a0fbaa;
|
||||
color: #000000;
|
||||
& + a,
|
||||
& + a:visited {
|
||||
color: #4ed2ba;
|
||||
|
|
|
@ -35,19 +35,21 @@ export const H3 = styled.h2`
|
|||
`;
|
||||
|
||||
export const RightPanelHeader = styled.h3`
|
||||
color: ${({ theme }) => theme.rightPanel.textColor};
|
||||
color: #697386;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
|
||||
${extensionsHook('RightPanelHeader')};
|
||||
`;
|
||||
|
||||
export const UnderlinedHeader = styled.h5`
|
||||
border-bottom: 1px solid rgba(38, 50, 56, 0.3);
|
||||
margin: 1em 0 1em 0;
|
||||
color: rgba(38, 50, 56, 0.5);
|
||||
font-weight: normal;
|
||||
color: rgb(0, 0, 0);
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
font-size: 0.929em;
|
||||
line-height: 20px;
|
||||
display: inline-block;
|
||||
margin: 0;
|
||||
|
||||
${extensionsHook('UnderlinedHeader')};
|
||||
`;
|
||||
|
|
|
@ -39,7 +39,7 @@ export const Section = styled.div.attrs(props => ({
|
|||
width: 100%;
|
||||
display: block;
|
||||
content: '';
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.2);
|
||||
border-bottom: 1px solid rgb(243, 243, 243);
|
||||
}
|
||||
`) ||
|
||||
''}
|
||||
|
|
|
@ -5,7 +5,7 @@ import styled from '../styled-components';
|
|||
|
||||
export { Tab, TabList, TabPanel } from 'react-tabs';
|
||||
|
||||
export const Tabs = styled(ReactTabs)`
|
||||
export const RequestSamplesTabs = styled(ReactTabs)`
|
||||
> ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
|
@ -13,31 +13,30 @@ export const Tabs = styled(ReactTabs)`
|
|||
margin: 0 -5px;
|
||||
|
||||
> li {
|
||||
padding: 5px 10px;
|
||||
color: rgb(0, 0, 0);
|
||||
background: rgb(255, 255, 255);
|
||||
padding: 2px 5px;
|
||||
display: inline-block;
|
||||
|
||||
background-color: ${({ theme }) => theme.codeSample.backgroundColor};
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.5);
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
outline: none;
|
||||
color: ${({ theme }) => darken(theme.colors.tonalOffset, theme.rightPanel.textColor)};
|
||||
margin: 0
|
||||
${({ theme }) => `${theme.spacing.unit}px ${theme.spacing.unit}px ${theme.spacing.unit}px`};
|
||||
border: 1px solid ${({ theme }) => darken(0.05, theme.codeSample.backgroundColor)};
|
||||
border: 1px solid rgb(245, 245, 245);
|
||||
border-radius: 5px;
|
||||
min-width: 60px;
|
||||
min-width: 50px;
|
||||
font-size: 0.9em;
|
||||
font-weight: bold;
|
||||
|
||||
&.react-tabs__tab--selected {
|
||||
color: ${props => props.theme.colors.text.primary};
|
||||
background: ${({ theme }) => theme.rightPanel.textColor};
|
||||
color: rgb(55, 181, 255);
|
||||
border-color: rgb(55, 181, 255);
|
||||
background: rgb(255, 255, 255);
|
||||
}
|
||||
|
||||
&:only-child {
|
||||
flex: none;
|
||||
min-width: 100px;
|
||||
}
|
||||
|
||||
&.tab-success {
|
||||
|
@ -58,7 +57,77 @@ export const Tabs = styled(ReactTabs)`
|
|||
}
|
||||
}
|
||||
> .react-tabs__tab-panel {
|
||||
background: ${({ theme }) => theme.codeSample.backgroundColor};
|
||||
border: 1px solid rgb(242, 242, 242);
|
||||
background: rgb(245, 245, 245);
|
||||
border-radius: 4px;
|
||||
& > div,
|
||||
& > pre {
|
||||
padding: ${props => props.theme.spacing.unit * 4}px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
& > div > pre {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export const Tabs = styled(ReactTabs)`
|
||||
> ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
margin: 0 -5px;
|
||||
|
||||
> li {
|
||||
padding: 2px 5px;
|
||||
display: inline-block;
|
||||
|
||||
background-color: ${({ theme }) => theme.codeSample.backgroundColor};
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.5);
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
outline: none;
|
||||
color: ${({ theme }) => darken(theme.colors.tonalOffset, theme.rightPanel.textColor)};
|
||||
margin: 0
|
||||
${({ theme }) => `${theme.spacing.unit}px ${theme.spacing.unit}px ${theme.spacing.unit}px`};
|
||||
border: 1px solid ${({ theme }) => darken(0.05, theme.codeSample.backgroundColor)};
|
||||
border-radius: 5px;
|
||||
min-width: 50px;
|
||||
font-size: 0.9em;
|
||||
font-weight: bold;
|
||||
|
||||
&.react-tabs__tab--selected {
|
||||
color: rgb(0, 170, 19);
|
||||
background-color: rgba(0, 170, 19, 0.1);
|
||||
border-color: transparent;
|
||||
}
|
||||
|
||||
&:only-child {
|
||||
flex: none;
|
||||
}
|
||||
|
||||
&.tab-success {
|
||||
color: ${props => props.theme.colors.responses.success.color};
|
||||
}
|
||||
|
||||
&.tab-redirect {
|
||||
color: ${props => props.theme.colors.responses.redirect.color};
|
||||
}
|
||||
|
||||
&.tab-info {
|
||||
color: ${props => props.theme.colors.responses.info.color};
|
||||
}
|
||||
|
||||
&.tab-error {
|
||||
color: ${props => props.theme.colors.responses.error.color};
|
||||
}
|
||||
}
|
||||
}
|
||||
> .react-tabs__tab-panel {
|
||||
border: 1px solid rgb(242, 242, 242);
|
||||
background: rgb(245, 245, 245);
|
||||
border-radius: 4px;
|
||||
& > div,
|
||||
& > pre {
|
||||
padding: ${props => props.theme.spacing.unit * 4}px;
|
||||
|
|
|
@ -16,15 +16,20 @@ export const ServerRelativeURL = styled.span`
|
|||
|
||||
export const EndpointInfo = styled.div<{ expanded?: boolean; inverted?: boolean }>`
|
||||
padding: 10px 30px 10px ${props => (props.inverted ? '10px' : '20px')};
|
||||
border-radius: ${props => (props.inverted ? '0' : '4px 4px 0 0')};
|
||||
background-color: ${props =>
|
||||
props.inverted ? 'transparent' : props.theme.codeSample.backgroundColor};
|
||||
border-radius: 4px;
|
||||
background-color: ${props => props.theme.codeSample.endpointBackgroundColor || props.theme.codeSample.backgroundColor};
|
||||
display: flex;
|
||||
white-space: nowrap;
|
||||
align-items: center;
|
||||
border: ${props => (props.inverted ? '0' : '1px solid transparent')};
|
||||
border-bottom: ${props => (props.inverted ? '1px solid #ccc' : '0')};
|
||||
transition: border-color 0.25s ease;
|
||||
font-family: Courier, monospace;
|
||||
color: rgb(255, 255, 255);
|
||||
font-weight: 600;
|
||||
flex: 1 1 0;
|
||||
overflow-x: hidden;
|
||||
text-overflow: ellipsis;
|
||||
|
||||
${props =>
|
||||
(props.expanded && !props.inverted && `border-color: ${props.theme.colors.border.dark};`) || ''}
|
||||
|
@ -45,6 +50,7 @@ export const HttpVerb = styled.span.attrs((props: { type: string }) => ({
|
|||
text-transform: uppercase;
|
||||
font-family: ${props => props.theme.typography.headings.fontFamily};
|
||||
margin: 0;
|
||||
border-radius: 4px;
|
||||
`;
|
||||
|
||||
export const ServersOverlay = styled.div<{ expanded: boolean }>`
|
||||
|
|
|
@ -78,5 +78,4 @@ export class MediaTypeSamples extends React.Component<PayloadSamplesProps, Media
|
|||
}
|
||||
|
||||
const SamplesWrapper = styled.div`
|
||||
margin-top: 15px;
|
||||
`;
|
||||
|
|
|
@ -25,7 +25,8 @@ export const DropdownLabel = styled.span`
|
|||
`;
|
||||
|
||||
export const DropdownWrapper = styled.div`
|
||||
position: relative;
|
||||
visibility: hidden;
|
||||
margin-bottom: -60px;
|
||||
`;
|
||||
|
||||
export const InvertedSimpleDropdown = styled(StyledDropdown)`
|
||||
|
|
|
@ -4,7 +4,7 @@ import { OperationModel, RedocNormalizedOptions } from '../../services';
|
|||
import { PayloadSamples } from '../PayloadSamples/PayloadSamples';
|
||||
import { SourceCodeWithCopy } from '../SourceCode/SourceCode';
|
||||
|
||||
import { RightPanelHeader, Tab, TabList, TabPanel, Tabs } from '../../common-elements';
|
||||
import { RequestSamplesTabs, RightPanelHeader, Tab, TabList, TabPanel } from '../../common-elements';
|
||||
import { OptionsContext } from '../OptionsProvider';
|
||||
|
||||
export interface RequestSamplesProps {
|
||||
|
@ -33,7 +33,7 @@ export class RequestSamples extends React.Component<RequestSamplesProps> {
|
|||
<div>
|
||||
<RightPanelHeader> Request samples </RightPanelHeader>
|
||||
|
||||
<Tabs defaultIndex={0}>
|
||||
<RequestSamplesTabs defaultIndex={0}>
|
||||
<TabList hidden={hideTabList}>
|
||||
{hasBodySample && <Tab key="payload"> Payload </Tab>}
|
||||
{samples.map(sample => (
|
||||
|
@ -54,7 +54,7 @@ export class RequestSamples extends React.Component<RequestSamplesProps> {
|
|||
<SourceCodeWithCopy lang={sample.lang} source={sample.source} />
|
||||
</TabPanel>
|
||||
))}
|
||||
</Tabs>
|
||||
</RequestSamplesTabs>
|
||||
</div>
|
||||
)) ||
|
||||
null
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
import * as React from 'react';
|
||||
|
||||
import { darken } from 'polished';
|
||||
import styled from '../../styled-components';
|
||||
import { MenuItemLabel } from '../SideMenu/styled.elements';
|
||||
|
||||
export const SearchWrap = styled.div`
|
||||
padding: 5px 0;
|
||||
margin: 0 20px;
|
||||
border-radius: 4px;
|
||||
border: 1px solid rgb(243, 243, 243);
|
||||
`;
|
||||
|
||||
export const SearchInput = styled.input.attrs(() => ({
|
||||
|
@ -17,7 +19,6 @@ export const SearchInput = styled.input.attrs(() => ({
|
|||
padding: 5px ${props => props.theme.spacing.unit * 2}px 5px
|
||||
${props => props.theme.spacing.unit * 4}px;
|
||||
border: 0;
|
||||
border-bottom: 1px solid ${({ theme }) => darken(0.1, theme.menu.backgroundColor)};
|
||||
font-family: ${({ theme }) => theme.typography.fontFamily};
|
||||
font-weight: bold;
|
||||
font-size: 13px;
|
||||
|
@ -41,7 +42,7 @@ export const SearchIcon = styled((props: { className?: string }) => (
|
|||
className: 'search-icon',
|
||||
})`
|
||||
position: absolute;
|
||||
left: ${props => props.theme.spacing.unit * 4}px;
|
||||
left: 30px;
|
||||
height: 1.8em;
|
||||
width: 0.9em;
|
||||
|
||||
|
|
|
@ -319,6 +319,7 @@ export interface ResolvedThemeInterface {
|
|||
};
|
||||
codeSample: {
|
||||
backgroundColor: string;
|
||||
endpointBackgroundColor: string;
|
||||
};
|
||||
|
||||
extensionsHook?: (name: string, props: any) => string;
|
||||
|
|
Loading…
Reference in New Issue
Block a user