feat: graphql docs explorer (#65)

This commit is contained in:
Anoop M D 2022-11-08 03:35:58 +05:30
parent dcdeb78995
commit 2393092248
4 changed files with 79 additions and 7 deletions

View File

@ -16,6 +16,7 @@
"@tabler/icons": "^1.46.0",
"@tippyjs/react": "^4.2.6",
"@usebruno/schema": "0.2.0",
"@usebruno/graphql-docs": "0.1.0",
"axios": "^0.26.0",
"classnames": "^2.3.1",
"codemirror": "^5.65.2",

View File

@ -1,4 +1,4 @@
import React from 'react';
import React, { useEffect } from 'react';
import find from 'lodash/find';
import get from 'lodash/get';
import classnames from 'classnames';
@ -13,7 +13,7 @@ import { sendRequest, saveRequest } from 'providers/ReduxStore/slices/collection
import useGraphqlSchema from './useGraphqlSchema';
import StyledWrapper from './StyledWrapper';
const GraphQLRequestPane = ({ item, collection, leftPaneWidth }) => {
const GraphQLRequestPane = ({ item, collection, leftPaneWidth, onSchemaLoad, toggleDocs, handleGqlClickReference }) => {
const dispatch = useDispatch();
const tabs = useSelector((state) => state.tabs.tabs);
const activeTabUid = useSelector((state) => state.tabs.activeTabUid);
@ -36,6 +36,12 @@ const GraphQLRequestPane = ({ item, collection, leftPaneWidth }) => {
}
};
useEffect(() => {
if(onSchemaLoad) {
onSchemaLoad(schema);
}
}, [schema]);
const onQueryChange = (value) => {
dispatch(
updateRequestGraphqlQuery({
@ -60,7 +66,16 @@ const GraphQLRequestPane = ({ item, collection, leftPaneWidth }) => {
const getTabPanel = (tab) => {
switch (tab) {
case 'query': {
return <QueryEditor theme={storedTheme} schema={schema} width={leftPaneWidth} onSave={onSave} value={query} onRun={onRun} onEdit={onQueryChange} />;
return <QueryEditor
theme={storedTheme}
schema={schema}
width={leftPaneWidth}
onSave={onSave}
value={query}
onRun={onRun}
onEdit={onQueryChange}
onClickReference={handleGqlClickReference}
/>;
}
case 'headers': {
return <RequestHeaders item={item} collection={collection} />;
@ -104,9 +119,12 @@ const GraphQLRequestPane = ({ item, collection, leftPaneWidth }) => {
{!isSchemaLoading && schema ? <IconRefresh size={18} strokeWidth={1.5}/> : null }
<span className='ml-1'>{schema ? 'Schema' : 'Load Schema'}</span>
</div>
{/* <div className='flex items-center cursor-pointer hover:underline ml-2'>
<div
className='flex items-center cursor-pointer hover:underline ml-2'
onClick={toggleDocs}
>
<IconBook size={18} strokeWidth={1.5} /><span className='ml-1'>Docs</span>
</div> */}
</div>
</div>
</div>
<section className="flex w-full mt-5">{getTabPanel(focusedTab.requestPaneTab)}</section>

View File

@ -25,6 +25,25 @@ const StyledWrapper = styled.div`
border-left: solid 1px ${(props) => props.theme.requestTabPanel.dragbar.activeBorder};
}
}
div.graphql-docs-explorer-container {
background: white;
outline: none;
box-shadow: rgb(0 0 0 / 15%) 0px 0px 8px;
position: absolute;
right: 0px;
z-index: 2000;
width: 350px;
height: 100%;
div.doc-explorer-title {
text-align: left;
}
div.doc-explorer-rhs {
display: flex;
}
}
`;
export default StyledWrapper;

View File

@ -1,4 +1,4 @@
import React, { useState, useEffect } from 'react';
import React, { useState, useEffect, useRef } from 'react';
import find from 'lodash/find';
import toast from 'react-hot-toast';
import { useSelector, useDispatch } from 'react-redux';
@ -12,6 +12,7 @@ import { sendRequest } from 'providers/ReduxStore/slices/collections/actions';
import RequestNotFound from './RequestNotFound';
import QueryUrl from 'components/RequestPane/QueryUrl';
import NetworkError from 'components/ResponsePane/NetworkError';
import { DocExplorer } from '@usebruno/graphql-docs';
import StyledWrapper from './StyledWrapper';
@ -35,6 +36,22 @@ const RequestTabPanel = () => {
const [rightPaneWidth, setRightPaneWidth] = useState(screenWidth - asideWidth - leftPaneWidth - DEFAULT_PADDING);
const [dragging, setDragging] = useState(false);
// Not a recommended pattern here to have the child component
// make a callback to set state, but treating this as an exception
const docExplorerRef = useRef(null);
const [schema, setSchema] = useState(null);
const [showGqlDocs, setShowGqlDocs] = useState(false);
const onSchemaLoad = (schema) => setSchema(schema);
const toggleDocs = () => setShowGqlDocs((showGqlDocs) => !showGqlDocs);
const handleGqlClickReference = (reference) => {
if(docExplorerRef.current) {
docExplorerRef.current.showDocForReference(reference);
}
if(!showGqlDocs) {
setShowGqlDocs(true);
}
};
useEffect(() => {
const leftPaneWidth = (screenWidth - asideWidth) / 2.2;
setLeftPaneWidth(leftPaneWidth);
@ -113,7 +130,7 @@ const RequestTabPanel = () => {
<div className="pt-4 pb-3 px-4">
<QueryUrl item={item} collection={collection} handleRun={handleRun} />
</div>
<section className="main flex flex-grow pb-4">
<section className="main flex flex-grow pb-4 relative">
<section className="request-pane">
<div className="px-4" style={{ width: `${Math.max(leftPaneWidth, MIN_LEFT_PANE_WIDTH)}px`, height: `calc(100% - ${DEFAULT_PADDING}px)` }}>
{item.type === 'graphql-request' ? (
@ -121,6 +138,9 @@ const RequestTabPanel = () => {
item={item}
collection={collection}
leftPaneWidth={leftPaneWidth}
onSchemaLoad={onSchemaLoad}
toggleDocs={toggleDocs}
handleGqlClickReference={handleGqlClickReference}
/>
) : null}
@ -136,6 +156,20 @@ const RequestTabPanel = () => {
<ResponsePane item={item} collection={collection} rightPaneWidth={rightPaneWidth} response={item.response} />
</section>
</section>
{item.type === 'graphql-request' ? (
<div className={`graphql-docs-explorer-container ${showGqlDocs ? '' : 'hidden'}`}>
<DocExplorer schema={schema} ref={(r) => docExplorerRef.current = r}>
<button
className='mr-2'
onClick={toggleDocs}
aria-label="Close Documentation Explorer"
>
{'\u2715'}
</button>
</DocExplorer>
</div>
): null}
</StyledWrapper>
);
};