Custom swagger endpoint for docs (#3869)

* custom swagger endpoint
metadata graphql
remove /rest from endpoint

* fixed pseudo scheme creation

* move graphql playground creation to own file, added navbar to change baseurl and token

* add schema switcher, fix changing url not applied, add invalid overlay

* fix link color

* removed path on Graphql Playground, naming fixes subdoc

* - fixed overflow issue Rest docs

* history replace & goBack

* Small fix GraphQL playground broken

---------

Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
This commit is contained in:
brendanlaschke
2024-02-08 16:54:20 +01:00
committed by GitHub
parent 719da29795
commit c53b593ea6
13 changed files with 338 additions and 113 deletions

View File

@ -1,87 +0,0 @@
import React, { useEffect, useState } from 'react';
import BrowserOnly from '@docusaurus/BrowserOnly';
import { explorerPlugin } from '@graphiql/plugin-explorer';
import { Theme, useTheme } from '@graphiql/react';
import { createGraphiQLFetcher } from '@graphiql/toolkit';
import Layout from '@theme/Layout';
import { GraphiQL } from 'graphiql';
import Playground from '../components/playground';
import explorerCss from '!css-loader!@graphiql/plugin-explorer/dist/style.css';
import graphiqlCss from '!css-loader!graphiql/graphiql.css';
// Docusaurus does SSR for custom pages, but we need to load GraphiQL in the browser
const GraphQlComponent = ({ token }) => {
const explorer = explorerPlugin({
showAttribution: true,
});
const fetcher = createGraphiQLFetcher({
url: 'https://api.twenty.com/graphql',
});
// We load graphiql style using useEffect as it breaks remaining docs style
useEffect(() => {
const createAndAppendStyle = (css) => {
const styleElement = document.createElement('style');
styleElement.innerHTML = css.toString();
document.head.append(styleElement);
return styleElement;
};
const styleElement1 = createAndAppendStyle(graphiqlCss);
const styleElement2 = createAndAppendStyle(explorerCss);
return () => {
styleElement1.remove();
styleElement2.remove();
};
}, []);
return (
<div className="fullHeightPlayground">
<GraphiQL
plugins={[explorer]}
fetcher={fetcher}
defaultHeaders={JSON.stringify({ Authorization: `Bearer ${token}` })}
/>
</div>
);
};
const graphQL = () => {
const [token, setToken] = useState();
const { setTheme } = useTheme();
useEffect(() => {
window.localStorage.setItem(
'graphiql:theme',
window.localStorage.getItem('theme') || 'light',
);
const handleThemeChange = (ev) => {
if (ev.key === 'theme') {
setTheme(ev.newValue as Theme);
}
};
window.addEventListener('storage', handleThemeChange);
return () => window.removeEventListener('storage', handleThemeChange);
}, []);
const children = <GraphQlComponent token={token} />;
return (
<Layout
title="GraphQL Playground"
description="GraphQL Playground for Twenty"
>
<BrowserOnly>
{() => <Playground children={children} setToken={setToken} />}
</BrowserOnly>
</Layout>
);
};
export default graphQL;

View File

@ -0,0 +1,9 @@
import React from 'react';
import GraphQlPlayground from '../../components/graphql-playground';
const CoreGraphql = () => {
return <GraphQlPlayground subDoc={'core'} />;
};
export default CoreGraphql;

View File

@ -0,0 +1,9 @@
import React from 'react';
import GraphQlPlayground from '../../components/graphql-playground';
const CoreGraphql = () => {
return <GraphQlPlayground subDoc={'metadata'} />;
};
export default CoreGraphql;

View File

@ -1,13 +1,13 @@
import Layout from '@theme/Layout';
import BrowserOnly from '@docusaurus/BrowserOnly';
import React, { useEffect, useState } from 'react';
import BrowserOnly from '@docusaurus/BrowserOnly';
import { API } from '@stoplight/elements';
import Playground from '../components/playground';
import Layout from '@theme/Layout';
import Playground from '../../components/playground';
import spotlightTheme from '!css-loader!@stoplight/elements/styles.min.css';
const RestApiComponent = ({openApiJson}) => {
const RestApiComponent = ({ openApiJson }) => {
// We load spotlightTheme style using useEffect as it breaks remaining docs style
useEffect(() => {
const styleElement = document.createElement('style');
@ -18,31 +18,38 @@ const RestApiComponent = ({openApiJson}) => {
}, []);
return (
<API
apiDescriptionDocument={JSON.stringify(openApiJson)}
router="hash"
/>
)
}
<div
style={{
height: 'calc(100vh - var(--ifm-navbar-height) - 45px)',
overflow: 'auto',
}}
>
<API apiDescriptionDocument={JSON.stringify(openApiJson)} router="hash" />
</div>
);
};
const restApi = () => {
const [openApiJson, setOpenApiJson] = useState({})
const [openApiJson, setOpenApiJson] = useState({});
const children = <RestApiComponent openApiJson={openApiJson} />
const children = <RestApiComponent openApiJson={openApiJson} />;
return (
<Layout
title="REST API Playground"
description="REST API Playground for Twenty"
>
<BrowserOnly>{
() => <Playground
children={children}
setOpenApiJson={setOpenApiJson}
/>
}</BrowserOnly>
<BrowserOnly>
{() => (
<Playground
children={children}
setOpenApiJson={setOpenApiJson}
subDoc="core"
/>
)}
</BrowserOnly>
</Layout>
)
);
};
export default restApi;