diff --git a/frontend/package.json b/frontend/package.json index cb5cc964b..a7c3bc221 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -11,6 +11,7 @@ }, "dependencies": { "@graphiql/plugin-explorer": "^0.1.20", + "@graphiql/plugin-code-exporter": "^0.1.2", "@monaco-editor/react": "^4.1.3", "@near-lake/primitives": "0.1.0", "@next/font": "13.1.6", @@ -34,9 +35,8 @@ "typescript": "4.9.5", "graphiql": "^2.4.1", "react-bootstrap-icons": "^1.10.3", - "buffer": "^6.0.3" - }, - "devDependencies": { - "raw-loader": "^4.0.2" + "buffer": "^6.0.3", + "raw-loader": "^4.0.2", + "regenerator-runtime": "^0.13.11" } } diff --git a/frontend/src/components/Editor/ResizableLayoutEditor.jsx b/frontend/src/components/Editor/ResizableLayoutEditor.jsx index 550af5e10..90dfb75e7 100644 --- a/frontend/src/components/Editor/ResizableLayoutEditor.jsx +++ b/frontend/src/components/Editor/ResizableLayoutEditor.jsx @@ -59,7 +59,7 @@ const ResizableEditor = ({ // Render logic based on fileName const editorComponents = { - GraphiQL: () => , + GraphiQL: () => , "indexingLogic.js": () => diffView ? ( { return await response.json(); }; -export const GraphqlPlayground = () => { +const extractQueryName = query => { + const match = query.match(/^[^{(]+\s([^{\s(]+)/); + return match ? match[1] : null; +}; + +const extractTableName = query => { + const match = query.match(/query\s*\w*\s*{\s*([^({\s]+)/); + return match ? match[1].trim() : null; +}; + +const bosQuerySnippet = (accountId) => { + return { + name: `BOS Widget`, + language: `JavaScript`, + codeMirrorMode: `jsx`, + options: [], + generate: arg => { + const { operationDataList } = arg; + const { query } = operationDataList[0]; + const queryName = extractQueryName(query) + const tableName = extractTableName(query) + const formattedQuery = query.replace(/\n/g, `\n` + ` `.repeat(2)); + return ` +const QUERYAPI_ENDPOINT = \`${HASURA_ENDPOINT}\`; + +State.init({ +data: [] +}); + +const query = \`${formattedQuery}\` +function fetchGraphQL(operationsDoc, operationName, variables) { + return asyncFetch( + QUERYAPI_ENDPOINT, + { + method: "POST", + headers: { "x-hasura-role": \`${accountId?.replaceAll(".", "_")}\` }, + body: JSON.stringify({ + query: operationsDoc, + variables: variables, + operationName: operationName, + }), + } + ); + } + + fetchGraphQL(query, "${queryName}", {}).then((result) => { + if (result.status === 200) { + if (result.body.data) { + const data = result.body.data.${tableName}; + State.update({ data }) + console.log(data); + } + } + }); + +const renderData = (a) => { + return ( +
+ {JSON.stringify(a)} +
+ ); +}; + +const renderedData = state.data.map(renderData); +return ( + {renderedData} +);`; + } + } +}; + +export default () => { const { indexerDetails } = useContext(IndexerDetailsContext); + const snippets = [bosQuerySnippet(indexerDetails.accountId)]; const [query, setQuery] = useState(""); + const explorerPlugin = useExplorerPlugin({ query, onEdit: setQuery, }); + const exporterPlugin = useExporterPlugin({ + query, + snippets, + codeMirrorTheme: 'graphiql', + }); + return (
graphQLFetcher(params, indexerDetails.accountId)} query={query} onEditQuery={setQuery} plugins={[explorerPlugin]} defaultQuery="" storage={sessionStorage} - theme="dark" + plugins={[explorerPlugin, exporterPlugin]} />
); diff --git a/frontend/src/components/Playground/index.js b/frontend/src/components/Playground/index.js index 84abb703b..352a5cd30 100644 --- a/frontend/src/components/Playground/index.js +++ b/frontend/src/components/Playground/index.js @@ -1,3 +1,16 @@ -import { GraphqlPlayground } from "./graphiql"; +import dynamic from 'next/dynamic'; + +const DynamicGraphiQLWithExporter = dynamic( + () => import('./graphiql.jsx'), + { ssr: false } // This will load the component only on client side +); + +function GraphqlPlayground({ }) { + return ( +
+ +
+ ); +} export default GraphqlPlayground; diff --git a/frontend/src/pages/_app.tsx b/frontend/src/pages/_app.tsx index 29885ae68..eecf66fe2 100644 --- a/frontend/src/pages/_app.tsx +++ b/frontend/src/pages/_app.tsx @@ -7,6 +7,7 @@ import { NearSocialBridgeProvider, } from "near-social-bridge"; import { IndexerDetailsProvider } from '../contexts/IndexerDetailsContext'; +import 'regenerator-runtime/runtime'; overrideLocalStorage(); export default function App({ Component, pageProps }: AppProps) {