Giter Club home page Giter Club logo

Comments (14)

KingDarBoja avatar KingDarBoja commented on June 10, 2024 2

@datavistics I hate doing stuff with React but was able to make it work with a custom template by looking at other repositories which tried to implement it (on JS ofc) like OneGraph/graphiql-explorer#29 (comment) .

My current result

image

What do you need (and I have done so far) on the graphiql_template:

GraphiQL Template on some py file
GRAPHIQL_VERSION = "1.0.3"
GRAPHIQL_TEMPLATE = """
<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8" />
    <title>{{graphiql_html_title}}</title>
    <meta name="robots" content="noindex" />
    <meta name="referrer" content="origin" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <style>
        body {
            margin: 0;
            overflow: hidden;
        }
        
        #graphiql {
            height: 100vh;
        }
        
        .graphiql-container {
            height: 100%;
            display: flex;
        }
        
        .graphiql-wrapper {
            width: calc(100% - 320px);
        }
    </style>
    <link href="//cdn.jsdelivr.net/npm/graphiql@{{graphiql_version}}/graphiql.css" rel="stylesheet" />
    <script src="//cdn.jsdelivr.net/npm/[email protected]/dist/polyfill.min.js"></script>
    <script src="//cdn.jsdelivr.net/npm/[email protected]/dist/unfetch.umd.js"></script>
    <script src="//cdn.jsdelivr.net/npm/[email protected]/umd/react.production.min.js"></script>
    <script src="//cdn.jsdelivr.net/npm/[email protected]/umd/react-dom.production.min.js"></script>
    <script src="//cdn.jsdelivr.net/npm/graphiql@{{graphiql_version}}/graphiql.min.js"></script>
    <script src="//cdn.jsdelivr.net/npm/[email protected]/graphiqlExplorer.min.js"></script>
    <script src="//cdn.jsdelivr.net/npm/[email protected]/browser/client.js"></script>
    <script src="//cdn.jsdelivr.net/npm/[email protected]/browser/client.js"></script>
</head>

<body>
    <div id="graphiql">Loading...</div>
    <script>
        // Collect the URL parameters
        var parameters = {};
        window.location.search.substr(1).split('&').forEach(function (entry) {
            var eq = entry.indexOf('=');
            if (eq >= 0) {
                parameters[decodeURIComponent(entry.slice(0, eq))] =
                    decodeURIComponent(entry.slice(eq + 1));
            }
        });
        // Produce a Location query string from a parameter object.
        function locationQuery(params) {
            return '?' + Object.keys(params).filter(function (key) {
                return Boolean(params[key]);
            }).map(function (key) {
                return encodeURIComponent(key) + '=' +
                    encodeURIComponent(params[key]);
            }).join('&');
        }
        // Derive a fetch URL from the current URL, sans the GraphQL parameters.
        var graphqlParamNames = {
            query: true,
            variables: true,
            operationName: true
        };
        var otherParams = {};
        for (var k in parameters) {
            if (parameters.hasOwnProperty(k) && graphqlParamNames[k] !== true) {
                otherParams[k] = parameters[k];
            }
        }
        // Configure the subscription client
        let subscriptionsFetcher = null;
        if ('{{subscription_url}}') {
            let subscriptionsClient = new SubscriptionsTransportWs.SubscriptionClient(
                '{{ subscription_url }}',
                { reconnect: true }
            );
            subscriptionsFetcher = GraphiQLSubscriptionsFetcher.graphQLFetcher(
                subscriptionsClient,
                graphQLFetcher
            );
        }
        var fetchURL = locationQuery(otherParams);
        // Defines a GraphQL fetcher using the fetch API.
        function graphQLFetcher(graphQLParams, opts) {
            return fetch(fetchURL, {
                method: 'post',
                headers: Object.assign(
                    {
                        'Accept': 'application/json',
                        'Content-Type': 'application/json'
                    },
                    opts && opts.headers,
                ),
                body: JSON.stringify(graphQLParams),
                credentials: 'include',
            }).then(function (response) {
                return response.json();
            });
        }
        // When the query and variables string is edited, update the URL bar so
        // that it can be easily shared.
        function onEditQuery(newQuery) {
            parameters.query = newQuery;
            updateURL();
        }
        function onEditVariables(newVariables) {
            parameters.variables = newVariables;
            updateURL();
        }
        function onEditHeaders(newHeaders) {
            parameters.headers = newHeaders;
            updateURL();
        }
        function onEditOperationName(newOperationName) {
            parameters.operationName = newOperationName;
            updateURL();
        }
        function updateURL() {
            history.replaceState(null, null, locationQuery(parameters));
        }
        
        // function handleToggleExplorer() {}
        // Render <GraphiQL /> into the body.
        function AppComponent() {
            var state = React.useState(undefined);
            var schema = state[0];
            var setSchema = state[1];
            var explorerIsOpen = true;
            window.setSchema = setSchema;
            
            function handleToggleExplorer() {
                this.explorerIsOpen = !this.explorerIsOpen;
            }
            
            const graphiql_explorer = React.createElement(GraphiQLExplorer.Explorer, {
                schema: schema,
                query: {{query|tojson}},
                onEdit: onEditQuery,
                // onRunOperation: {operationName =>
                //     this._graphiql.handleRunQuery(operationName)
                // }
                explorerIsOpen: explorerIsOpen,
                onToggleExplorer: handleToggleExplorer
                // getDefaultScalarArgValue: getDefaultScalarArgValue
                // makeDefaultArg: makeDefaultArg
            });
            const graphiql = React.createElement(GraphiQL, {
                fetcher: subscriptionsFetcher || graphQLFetcher,
                onEditQuery: onEditQuery,
                onEditVariables: onEditVariables,
                onEditHeaders: onEditHeaders,
                onEditOperationName: onEditOperationName,
                query: {{query|tojson}},
                response: {{result|tojson}},
                variables: {{variables|tojson}},
                headers: {{headers|tojson}},
                operationName: {{operation_name|tojson}},
                defaultQuery: {{default_query|tojson}},
                headerEditorEnabled: {{header_editor_enabled|tojson}},
                shouldPersistHeaders: {{should_persist_headers|tojson}},
                ref: function(ref) {
                    window._graphiql = ref;
                }
            });
            const graphiql_component = React.createElement(
                "div",
                { className: "graphiql-wrapper" },
                graphiql
            );
            
            return React.createElement(
                "div",
                { className: "graphiql-container" },
                graphiql_explorer,
                graphiql_component
            )
        }

        ReactDOM.render(
            React.createElement(AppComponent),
            document.getElementById('graphiql')
        );
        
        function trySetSchemaFromGraphiqlToGraphiqlExplorer() {
            setTimeout(function() {
                if (
                    window._graphiql &&
                    window._graphiql.state &&
                    window._graphiql.state.schema
                ) {
                    window.setSchema(window._graphiql.state.schema);
                } else {
                    trySetSchemaFromGraphiqlToGraphiqlExplorer();
                }
            }, 500);
        }
        trySetSchemaFromGraphiqlToGraphiqlExplorer();
    </script>
</body>

</html>
"""

Then just pass to GraphQLView class at graphiql_template field like below.

from flask import Flask
from graphql_server.flask import GraphQLView

from graphiql_explorer import GRAPHIQL_TEMPLATE, GRAPHIQL_VERSION
from schema import schema

app = Flask(__name__)

app.add_url_rule('/graphql', view_func=GraphQLView.as_view(
    'graphql',
    schema=schema,
    graphiql=True,
    graphiql_template=GRAPHIQL_TEMPLATE,
    graphiql_version=GRAPHIQL_VERSION,
))

if __name__ == '__main__':
    app.run()

NOTE: I am using graphql-server beta version so please follow these setup to know how to install flask integration with this or use flask-graphql beta v3.

Also, some stuff doesn't work at all like clicking on the explorer nodes as I haven't added the rest of options listed at https://github.com/OneGraph/graphiql-explorer-example/blob/master/src/App.js#L171 example but this initial setup should be the way to go.

from flask-graphql.

KingDarBoja avatar KingDarBoja commented on June 10, 2024 1

Ah, that thing is easy to implement, guess I could add that extension to the graphiql template on https://github.com/graphql-python/graphql-server as all server integration code lives there since v3.

from flask-graphql.

datavistics avatar datavistics commented on June 10, 2024 1

Thanks for responding, and if you wrote it over the weekend that would be hugely helpful.

I tried for longer than I care to admit, but Im just at a loss between the js + react -> html -> jinja. I didnt see how to pass the schema, or some of the other parameters required.

from flask-graphql.

KingDarBoja avatar KingDarBoja commented on June 10, 2024

Do something like as:

view_func = GraphQLView.as_view("graphql", schema=Schema(query=some_api_schema.Query), graphiql=True)
app.add_url_rule("/graphql", view_func=view_func)

Notice the graphiql=True argument being passed,

from flask-graphql.

datavistics avatar datavistics commented on June 10, 2024

@KingDarBoja , I think they mean like this: https://stackoverflow.com/questions/59791068/how-do-i-add-the-explorer-to-graphiql-using-flask-graphql

Using graphiql-explorer.

Do you have an example template that would work? Ive been trying to follow the stack overflow ticket, but Im not a react expert.

from flask-graphql.

datavistics avatar datavistics commented on June 10, 2024

@KingDarBoja , any ideas for a quick fix, ie a template string? I tried myself like the ticket mentioned but had no luck.

from flask-graphql.

KingDarBoja avatar KingDarBoja commented on June 10, 2024

@datavistics Best idea should be providing a working example, which make use of the graphiql_template option as described at https://github.com/graphql-python/graphql-server/blob/master/docs/flask.md . I could write it but would be at the weekend as I'm currently busy these days.

from flask-graphql.

KingDarBoja avatar KingDarBoja commented on June 10, 2024

Speaking of that, I found strawberry-graphql/strawberry#293 which seems to point out some issues regarding graphql-explorer 🤔 I will take a closer look at it later.

from flask-graphql.

datavistics avatar datavistics commented on June 10, 2024

@KingDarBoja thanks a ton, but unfortunately I couldnt get it to work. Im using graphene-elastic which depends on graphene < 3.

from flask-graphql.

datavistics avatar datavistics commented on June 10, 2024

@KingDarBoja Is there a way to use this for graphene 2.1.8 and Flask-GraphQL 2.0.1 ?

from flask-graphql.

KingDarBoja avatar KingDarBoja commented on June 10, 2024

@KingDarBoja Is there a way to use this for graphene 2.1.8 and Flask-GraphQL 2.0.1 ?

Flask-GraphQL 2 supports passing custom graphiql templates as well.

from flask-graphql.

Ambro17 avatar Ambro17 commented on June 10, 2024

@KingDarBoja Is your working graphiql version with explorer published on github? I can't get it to work and a working example from where to start would be a lifesaver

from flask-graphql.

samhaaf avatar samhaaf commented on June 10, 2024

@KingDarBoja Thanks for this!

Would love to see it get fully developed. I.e. clicking on the nodes fills the query; node selections get updated when query is updated; node fields can be selected.

from flask-graphql.

ScottChapman avatar ScottChapman commented on June 10, 2024

Has anyone had any luck using graphiql v2?

from flask-graphql.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.