mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-09-20 06:58:39 +03:00
parent
b9918e0eac
commit
a78f17b79c
@ -476,6 +476,7 @@ See [upgrade docs](https://hasura.io/docs/1.0/graphql/manual/migrations/upgrade-
|
||||
- console: fix parsing of wrapped types in SDL (close #4099) (#4167)
|
||||
- console: misc actions fixes (#4059)
|
||||
- console: action relationship page improvements (fix #4062, #4130) (#4133)
|
||||
- console: add code exporter to graphiql (close #4531) #4652
|
||||
- cli: fix init command to generate correct config (fix #4036) (#4038)
|
||||
- cli: fix parse error returned on console api (close #4126) (#4152)
|
||||
- cli: fix typo in cli example for squash (fix #4047) (#4049)
|
||||
|
1638
console/package-lock.json
generated
1638
console/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -55,6 +55,7 @@
|
||||
"apollo-link-ws": "1.0.20",
|
||||
"brace": "0.11.1",
|
||||
"graphiql": "1.0.0-alpha.0",
|
||||
"graphiql-code-exporter": "2.0.8",
|
||||
"graphiql-explorer": "0.6.2",
|
||||
"graphql": "14.5.8",
|
||||
"graphql-voyager": "1.0.0-rc.29",
|
||||
|
@ -6,6 +6,11 @@ import PropTypes from 'prop-types';
|
||||
import GraphiQLErrorBoundary from './GraphiQLErrorBoundary';
|
||||
import OneGraphExplorer from '../OneGraphExplorer/OneGraphExplorer';
|
||||
import AnalyzeButton from '../Analyzer/AnalyzeButton';
|
||||
import CodeExporter from 'graphiql-code-exporter';
|
||||
import {
|
||||
getPersistedCodeExporterOpen,
|
||||
persistCodeExporterOpen,
|
||||
} from '../OneGraphExplorer/utils';
|
||||
|
||||
import {
|
||||
clearCodeMirrorHints,
|
||||
@ -28,9 +33,11 @@ import {
|
||||
setDerivedActionParentOperation,
|
||||
} from '../../Actions/Add/reducer';
|
||||
import { getGraphQLEndpoint } from '../utils';
|
||||
import snippets from './snippets';
|
||||
|
||||
import 'graphiql/graphiql.css';
|
||||
import './GraphiQL.css';
|
||||
import 'graphiql-code-exporter/CodeExporter.css';
|
||||
|
||||
class GraphiQLWrapper extends Component {
|
||||
constructor(props) {
|
||||
@ -40,6 +47,7 @@ class GraphiQLWrapper extends Component {
|
||||
noSchema: false,
|
||||
onBoardingEnabled: false,
|
||||
copyButtonText: 'Copy',
|
||||
codeExporterOpen: false,
|
||||
};
|
||||
}
|
||||
|
||||
@ -47,10 +55,23 @@ class GraphiQLWrapper extends Component {
|
||||
setQueryVariableSectionHeight();
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
const codeExporterOpen = getPersistedCodeExporterOpen();
|
||||
this.setState({ codeExporterOpen });
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
clearCodeMirrorHints();
|
||||
}
|
||||
|
||||
_handleToggleCodeExporter = () => {
|
||||
const nextState = !this.state.codeExporterOpen;
|
||||
|
||||
persistCodeExporterOpen(nextState);
|
||||
|
||||
this.setState({ codeExporterOpen: nextState });
|
||||
};
|
||||
|
||||
render() {
|
||||
const styles = require('../../../Common/Common.scss');
|
||||
|
||||
@ -62,6 +83,7 @@ class GraphiQLWrapper extends Component {
|
||||
mode,
|
||||
loading,
|
||||
} = this.props;
|
||||
const { codeExporterOpen } = this.state;
|
||||
const graphqlNetworkData = this.props.data;
|
||||
const graphQLFetcher = graphQLParams => {
|
||||
if (headerFocus) {
|
||||
@ -173,6 +195,11 @@ class GraphiQLWrapper extends Component {
|
||||
title: 'Toggle Explorer',
|
||||
onClick: graphiqlProps.toggleExplorer,
|
||||
},
|
||||
{
|
||||
label: 'Code Exporter',
|
||||
title: 'Toggle Code Exporter',
|
||||
onClick: this._handleToggleCodeExporter,
|
||||
},
|
||||
{
|
||||
label: 'Voyager',
|
||||
title: 'GraphQL Voyager',
|
||||
@ -193,24 +220,34 @@ class GraphiQLWrapper extends Component {
|
||||
};
|
||||
|
||||
return (
|
||||
<GraphiQL
|
||||
{...graphiqlProps}
|
||||
ref={c => {
|
||||
graphiqlContext = c;
|
||||
}}
|
||||
fetcher={graphQLFetcher}
|
||||
voyagerUrl={voyagerUrl}
|
||||
>
|
||||
<GraphiQL.Logo>GraphiQL</GraphiQL.Logo>
|
||||
<GraphiQL.Toolbar>
|
||||
{getGraphiqlButtons()}
|
||||
<AnalyzeButton
|
||||
operations={graphiqlContext && graphiqlContext.state.operations}
|
||||
analyzeFetcher={analyzeFetcherInstance}
|
||||
{...analyzerProps}
|
||||
<>
|
||||
<GraphiQL
|
||||
{...graphiqlProps}
|
||||
ref={c => {
|
||||
graphiqlContext = c;
|
||||
}}
|
||||
fetcher={graphQLFetcher}
|
||||
voyagerUrl={voyagerUrl}
|
||||
>
|
||||
<GraphiQL.Logo>GraphiQL</GraphiQL.Logo>
|
||||
<GraphiQL.Toolbar>
|
||||
{getGraphiqlButtons()}
|
||||
<AnalyzeButton
|
||||
operations={graphiqlContext && graphiqlContext.state.operations}
|
||||
analyzeFetcher={analyzeFetcherInstance}
|
||||
{...analyzerProps}
|
||||
/>
|
||||
</GraphiQL.Toolbar>
|
||||
</GraphiQL>
|
||||
{codeExporterOpen ? (
|
||||
<CodeExporter
|
||||
hideCodeExporter={this._handleToggleCodeExporter}
|
||||
snippets={snippets}
|
||||
query={graphiqlProps.query}
|
||||
codeMirrorTheme="default"
|
||||
/>
|
||||
</GraphiQL.Toolbar>
|
||||
</GraphiQL>
|
||||
) : null}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -0,0 +1,109 @@
|
||||
import snippets from 'graphiql-code-exporter/lib/snippets';
|
||||
import { OperationTypeNode, OperationDefinitionNode } from 'graphql';
|
||||
|
||||
export type Options = Array<{ id: string; label: string; initial: boolean }>;
|
||||
|
||||
export type OptionValues = { [id: string]: boolean };
|
||||
|
||||
export type OperationData = {
|
||||
query: string;
|
||||
name: string;
|
||||
displayName: string;
|
||||
type: OperationTypeNode;
|
||||
variableName: string;
|
||||
variables: object;
|
||||
operationDefinition: OperationDefinitionNode;
|
||||
};
|
||||
|
||||
export type GenerateOptions = {
|
||||
serverUrl: string;
|
||||
headers: { [name: string]: string };
|
||||
context: object;
|
||||
operationDataList: Array<OperationData>;
|
||||
options: OptionValues;
|
||||
};
|
||||
|
||||
export type CodesandboxFile = {
|
||||
content: string;
|
||||
};
|
||||
|
||||
export type CodesandboxFiles = {
|
||||
[filename: string]: CodesandboxFile;
|
||||
};
|
||||
|
||||
export type Snippet = {
|
||||
options: Options;
|
||||
language: string;
|
||||
codeMirrorMode: string;
|
||||
name: string;
|
||||
generate: (options: GenerateOptions) => string;
|
||||
generateCodesandboxFiles?: (options: GenerateOptions) => CodesandboxFiles;
|
||||
};
|
||||
|
||||
const getQuery = (query: string) => {
|
||||
return ` `.repeat(2) + query.replace(/\n/g, `\n${` `.repeat(2)}`);
|
||||
};
|
||||
|
||||
const getVariables = (operationData: OperationData): string => {
|
||||
const params = (
|
||||
operationData?.operationDefinition?.variableDefinitions || []
|
||||
).map(def => def?.variable?.name?.value);
|
||||
const variablesBody = params.map(param => `"${param}": ${param}`).join(', ');
|
||||
const variables = `{${variablesBody}}`;
|
||||
return variables;
|
||||
};
|
||||
|
||||
const typeScriptSnippet: Snippet = {
|
||||
name: `fetch`,
|
||||
language: `TypeScript`,
|
||||
codeMirrorMode: `jsx`,
|
||||
options: [],
|
||||
generate: ({ operationDataList }) => {
|
||||
const queryDef = operationDataList[0];
|
||||
|
||||
return `
|
||||
/*
|
||||
This is an example snippet - you should consider tailoring it
|
||||
to your service.
|
||||
|
||||
Note: we only handle the first operation here
|
||||
*/
|
||||
|
||||
function fetchGraphQL(
|
||||
operationsDoc: string,
|
||||
operationName: string,
|
||||
variables: Record<string, any>
|
||||
) {
|
||||
return fetch('undefined', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
query: operationsDoc,
|
||||
variables,
|
||||
operationName,
|
||||
}),
|
||||
}).then(result => result.json());
|
||||
}
|
||||
|
||||
const operation = \`
|
||||
${getQuery(queryDef.query)}
|
||||
\`;
|
||||
|
||||
function fetch${queryDef.name}() {
|
||||
return fetchGraphQL(operations, ${queryDef.name}, ${getVariables(queryDef)})
|
||||
}
|
||||
|
||||
fetch${queryDef.name}()
|
||||
.then(({ data, errors }) => {
|
||||
if (errors) {
|
||||
console.error(errors);
|
||||
}
|
||||
console.log(data);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error(error);
|
||||
});
|
||||
`;
|
||||
},
|
||||
};
|
||||
|
||||
export default [...snippets, typeScriptSnippet];
|
@ -32,3 +32,22 @@ export const getExplorerIsOpen = () => {
|
||||
export const setExplorerIsOpen = isOpen => {
|
||||
window.localStorage.setItem('graphiql:explorerOpen', isOpen);
|
||||
};
|
||||
|
||||
export const persistCodeExporterOpen = isOpen => {
|
||||
window.localStorage.setItem(
|
||||
'graphiql:codeExporterOpen',
|
||||
JSON.stringify(isOpen)
|
||||
);
|
||||
};
|
||||
|
||||
export const getPersistedCodeExporterOpen = () => {
|
||||
const isOpen = window.localStorage.getItem('graphiql:codeExporterOpen');
|
||||
|
||||
if (!isOpen) return false;
|
||||
|
||||
try {
|
||||
return JSON.parse(isOpen);
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
3
console/src/declaration.d.ts
vendored
3
console/src/declaration.d.ts
vendored
@ -12,3 +12,6 @@ declare namespace React {
|
||||
css?: import('styled-components').CSSProp;
|
||||
}
|
||||
}
|
||||
|
||||
declare module 'graphiql-code-exporter/lib/snippets';
|
||||
declare module 'graphiql-code-exporter';
|
||||
|
Loading…
Reference in New Issue
Block a user