From 7d3530481643e777ad580ea9566f5368bcfb6e70 Mon Sep 17 00:00:00 2001 From: Varun Choudhary <68095256+Varun-Choudhary@users.noreply.github.com> Date: Fri, 7 Jul 2023 14:22:10 +0530 Subject: [PATCH] console: improve flow between rest and graphiql page This PR adds a button on the REST page `Create REST` which will open the rest form. Also, to select the query we have a link which will route the user to `GraphiQL` page with the `REST` button on the Nav bar highlighted. Demo - https://github.com/hasura/graphql-engine-mono/assets/68095256/3fab4ef2-fe21-4be6-b52d-bf8f937888aa PR-URL: https://github.com/hasura/graphql-engine-mono/pull/9797 GitOrigin-RevId: 848ccff74ec1489df945821f583270714ba4e770 --- .../ApiExplorer/GraphiQLWrapper/GraphiQL.css | 8 +++ .../GraphiQLWrapper/GraphiQLToolbarButton.tsx | 38 ++++++++++++++ .../GraphiQLWrapper/GraphiQLWrapper.js | 8 ++- .../Rest/Form/RestEndpointForm.tsx | 5 +- .../Services/ApiExplorer/Rest/Landing.tsx | 52 ++++++++++++------- .../Services/ApiExplorer/Rest/List.tsx | 15 ++++-- 6 files changed, 99 insertions(+), 27 deletions(-) create mode 100644 frontend/libs/console/legacy-ce/src/lib/components/Services/ApiExplorer/GraphiQLWrapper/GraphiQLToolbarButton.tsx diff --git a/frontend/libs/console/legacy-ce/src/lib/components/Services/ApiExplorer/GraphiQLWrapper/GraphiQL.css b/frontend/libs/console/legacy-ce/src/lib/components/Services/ApiExplorer/GraphiQLWrapper/GraphiQL.css index cde96ad1bbe..9a7549a51c9 100644 --- a/frontend/libs/console/legacy-ce/src/lib/components/Services/ApiExplorer/GraphiQLWrapper/GraphiQL.css +++ b/frontend/libs/console/legacy-ce/src/lib/components/Services/ApiExplorer/GraphiQLWrapper/GraphiQL.css @@ -285,6 +285,14 @@ color: #b00; } +.graphiql-container .toolbar-button.primary { + background: #f9c548; + border: 1px solid #d5ae52; + box-shadow: none; + color: #475569; + font-weight: 500; +} + .graphiql-container .toolbar-button-group { margin: 0 5px; white-space: nowrap; diff --git a/frontend/libs/console/legacy-ce/src/lib/components/Services/ApiExplorer/GraphiQLWrapper/GraphiQLToolbarButton.tsx b/frontend/libs/console/legacy-ce/src/lib/components/Services/ApiExplorer/GraphiQLWrapper/GraphiQLToolbarButton.tsx new file mode 100644 index 00000000000..f7b75abb954 --- /dev/null +++ b/frontend/libs/console/legacy-ce/src/lib/components/Services/ApiExplorer/GraphiQLWrapper/GraphiQLToolbarButton.tsx @@ -0,0 +1,38 @@ +import React from 'react'; + +export type GraphiQLToolbarButtonProps = { + label: string; + primary: boolean; +} & React.ComponentProps<'button'>; + +export const GraphiQLToolbarButton = React.forwardRef< + HTMLButtonElement, + GraphiQLToolbarButtonProps +>((props, forwardedRef) => { + const [errorMessage, setErrorMessage] = React.useState(null); + const handleClick = ( + event: React.MouseEvent + ) => { + try { + if (props.onClick) props.onClick(event); + setErrorMessage(null); + } catch (error: any) { + setErrorMessage(error.message); + } + }; + + return ( + + ); +}); diff --git a/frontend/libs/console/legacy-ce/src/lib/components/Services/ApiExplorer/GraphiQLWrapper/GraphiQLWrapper.js b/frontend/libs/console/legacy-ce/src/lib/components/Services/ApiExplorer/GraphiQLWrapper/GraphiQLWrapper.js index 24340ad5b77..ff35d90dfec 100644 --- a/frontend/libs/console/legacy-ce/src/lib/components/Services/ApiExplorer/GraphiQLWrapper/GraphiQLWrapper.js +++ b/frontend/libs/console/legacy-ce/src/lib/components/Services/ApiExplorer/GraphiQLWrapper/GraphiQLWrapper.js @@ -1,6 +1,7 @@ /* eslint-disable jsx-a11y/anchor-is-valid */ import React, { Component } from 'react'; import GraphiQL from 'graphiql'; +import queryString from 'query-string'; import { connect } from 'react-redux'; import { FaCheckCircle, FaExclamationTriangle } from 'react-icons/fa'; import PropTypes from 'prop-types'; @@ -49,6 +50,7 @@ import { ResponseTimeWarning, RESPONSE_TIME_CACHE_WARNING, } from './ResponseTimeWarning'; +import { GraphiQLToolbarButton } from './GraphiQLToolbarButton'; class GraphiQLWrapper extends Component { constructor(props) { @@ -293,6 +295,9 @@ class GraphiQLWrapper extends Component { const renderGraphiql = graphiqlProps => { const voyagerUrl = graphqlNetworkData.consoleUrl + '/voyager-view'; + const queryParams = queryString.parseUrl(window.location.href); + const highlightRestButton = queryParams.query.mode === 'rest'; + let analyzerProps = {}; if (graphiqlContext) { analyzerProps = graphiqlContext.state; @@ -345,6 +350,7 @@ class GraphiQLWrapper extends Component { { label: 'REST', title: 'REST Endpoints', + primary: highlightRestButton, onClick: () => { trackGraphiQlToolbarButtonClick('REST'); routeToREST(); @@ -361,7 +367,7 @@ class GraphiQLWrapper extends Component { return buttons .filter(b => !b.hide) .map(b => { - return ; + return ; }); }; diff --git a/frontend/libs/console/legacy-ce/src/lib/components/Services/ApiExplorer/Rest/Form/RestEndpointForm.tsx b/frontend/libs/console/legacy-ce/src/lib/components/Services/ApiExplorer/Rest/Form/RestEndpointForm.tsx index bd69b8a0cee..94bb2714b66 100644 --- a/frontend/libs/console/legacy-ce/src/lib/components/Services/ApiExplorer/Rest/Form/RestEndpointForm.tsx +++ b/frontend/libs/console/legacy-ce/src/lib/components/Services/ApiExplorer/Rest/Form/RestEndpointForm.tsx @@ -15,6 +15,7 @@ import globals from '../../../../../Globals'; import { FaArrowRight, FaMagic } from 'react-icons/fa'; import { IndicatorCard } from '../../../../../new-components/IndicatorCard'; import clsx from 'clsx'; +import { Link } from 'react-router'; const editorOptions = { minLines: 10, @@ -131,10 +132,10 @@ export const RestEndpointForm: React.FC = ({ editorOptions={editorOptions} /> diff --git a/frontend/libs/console/legacy-ce/src/lib/components/Services/ApiExplorer/Rest/Landing.tsx b/frontend/libs/console/legacy-ce/src/lib/components/Services/ApiExplorer/Rest/Landing.tsx index 62275c88794..968feb76196 100644 --- a/frontend/libs/console/legacy-ce/src/lib/components/Services/ApiExplorer/Rest/Landing.tsx +++ b/frontend/libs/console/legacy-ce/src/lib/components/Services/ApiExplorer/Rest/Landing.tsx @@ -1,32 +1,44 @@ import React from 'react'; -import { Link } from 'react-router'; import TopicDescription from '../../Common/Landing/TopicDescription'; import LandingImage from './LandingImage'; +import { Button } from '../../../../new-components/Button'; +import _push from '../../Data/push'; +import { useAppDispatch } from '../../../../storeHooks'; const landingDescription = `REST endpoints allow for the creation of a REST interface to your saved GraphQL queries and mutations. Endpoints are accessible from /api/rest/* and inherit the authorization and permission structure from your associated GraphQL nodes. To create a new endpoint simply test your query in GraphiQL then click the REST button on GraphiQL to configure a URL.`; -const Landing = () => ( -
-
-

REST Endpoints

+const Landing = () => { + const dispatch = useAppDispatch(); + return ( +
+
+

REST Endpoints

+ +
+
+ Create Rest endpoints on the top of existing GraphQL queries and + mutations{' '} +
+
+ } + imgAlt="REST endpoints" + description={landingDescription} + learnMoreHref="https://hasura.io/docs/latest/graphql/core/api-reference/restified.html" + /> +
-
- Create endpoints from GraphQL queries using{' '} - GraphiQL. -
-
- } - imgAlt="REST endpoints" - description={landingDescription} - learnMoreHref="https://hasura.io/docs/latest/graphql/core/api-reference/restified.html" - /> -
-
-); + ); +}; export default Landing; diff --git a/frontend/libs/console/legacy-ce/src/lib/components/Services/ApiExplorer/Rest/List.tsx b/frontend/libs/console/legacy-ce/src/lib/components/Services/ApiExplorer/Rest/List.tsx index b3a5f55c3bd..dfe3f980430 100644 --- a/frontend/libs/console/legacy-ce/src/lib/components/Services/ApiExplorer/Rest/List.tsx +++ b/frontend/libs/console/legacy-ce/src/lib/components/Services/ApiExplorer/Rest/List.tsx @@ -61,11 +61,18 @@ const ListComponent: React.FC = ({
-

REST Endpoints

+

REST Endpoints

+
-
- Create endpoints from GraphQL queries using{' '} - GraphiQL. +
+ Create Rest endpoints on the top of existing GraphQL queries + andmutations{' '}
REST endpoints allow for the creation of a REST interface to your saved GraphQL queries and mutations. Endpoints are generated from