skip to Main Content

I’m trying to embed an Apache 1.5 dashboard in a WordPress site. So far I’ve succeeded in doing the following:

  • Upgrade to Apache Superset 1.5 and enable the embedded dashboard functionality
  • Configure dashboard to be embedded
  • Implemented backend code to obtain JWT token

What I’m struggling with now is to implement the "@superset-ui/embedded-sdk" functionality in my WordPress site (using TwentyTwentyOne standard template). I’m trying to follow the instructions listed here: https://fossies.org/dox/apache-superset-1.5.0-source/md_superset_embedded_sdk_README.html

The CDN approach looks the easiest, but I’m getting the error ReferenceError: Buffer is not defined. And if I add the following code:

<script src="https://unpkg.com/buffer"></script>

Then I get the error ReferenceError: require is not defined. I’m not sure how I can resolve this error. Is the CDN approach a dead end, or is there a way I can make this work?

With the "Using npm" approach I’m struggling even more. I’m able to install the npm packages on bitnami linux, but then I don’t know how to make use of them in the site. I wasn’t able to make it work to add ‘@superset-ui/embedded-sdk’ using wp_enqueue_script(). Also I tried the following code in wordpress:

<script type="module">
import {embedDashboard} from 'http://[MY_IP_ADDRESS]/wp-content/themes/twentytwentyone/node_modules/@superset-ui/embedded-sdk/lib/index.js';
</script>

However then I get the following error:

Uncaught SyntaxError: The requested module ‘http://[MY_IP_ADDRESS]/wp-content/themes/twentytwentyone/node_modules/@superset-ui/embedded-sdk/lib/index.js’ does not provide an export named ’embedDashboard’

I don’t quite understand this error as embedDashboard does appear to be defined in the js file. I also tried using the embedded-sdk/bundle/index.js file with the same result.

I’ve spent many hours on this and I’m not sure what approach I should take. Can anyone point me in the right direction? Or even better: have a solution to a similar problem with sample code I can look at? If I need to provide more details on what I’ve tried or what errors I’m seeing let me know.

2

Answers


  1. Hello, I hope this example of using ‘superset embedded-sdk’ will help you:

    <!DOCTYPE html>
    <head>
        ...
        <script src="https://unpkg.com/@superset-ui/embedded-sdk"></script>
    </head>
    <body>
        <p id="dashboard" width="700" height="700"></p>
            <script>
                async function getToken() {
                    const res = await fetch('http://localhost:3000/token');
                    const data = await res.json()
                    console.log(data['value']);
                    return data['value'];
                }
        
                supersetEmbeddedSdk.embedDashboard({
                    id: "7b5ee110-435b-4ad1-a257-97ea340bf82d",
                    supersetDomain: "http://localhost:8088",
                    mountPoint: document.getElementById("dashboard"),
                    fetchGuestToken: () => getToken(),
                    dashboardUiConfig: {
                        hideTitle: true,
                        filters: {
                            expanded: true
                        }
                    }
                });
            </script>
    </body>
    </html>
    
    Login or Signup to reply.
  2. This is how I did it.
    I wrote my backend in Flask.
    My Superset Version is 2.0

    backend.py

    from flask import Flask, render_template, jsonify 
    import requests 
    import json 
    import os
    
    app = Flask(__name__)
    
    @app.route('/') 
    def hello():
        return render_template('index.html')
    
    @app.route("/guest-token", methods=["GET"])
    def guest_token():
        url = "http://<IP>:<PORT>/api/v1/security/login" 
        payload = json.dumps({ "password": "<>", "provider": "db", "refresh": "true", "username": "<>" })
        headers = { 'Content-Type': 'application/json', 'Accept': 'application/json' }
    
        responsel = requests.request("POST", url, headers=headers, data=payload) 
        print(responsel.text)
        superset_access_token = json.loads(responsel.text)['access_token']
        payload = json.dumps ({ 
            "user": {
                "username": "kashew",
                "first name":"Kashish", 
                "lastname":"Bakshi"
            },
            
            "resources": [{
                "type": "dashboard",
                "id": "8f96cc84-7e9e-4f5c-ba92-3a1f0825fe3d"
            }],
            "rls": []
        })
                   
        bearer_token = "Bearer " + superset_access_token
        print(bearer_token)
        response2 = requests.post(
             "http://<IP>:<PORT>/api/v1/security/guest_token", 
             data = payload,
             headers = { "Authorization": bearer_token, 'Accept': 'application/json', 'Content-Type': 'application/json' }) 
        print(response2.json())
        return jsonify(response2.json()['token'])
    
    if __name__ == "__main__":
        app.run(debug=True)
    

    Explanation:
    The Major part of understanding is the Guest_Token Function.

    Here two POST Requests are at play.

    1. The first Request gets the access token from Superset.
    2. The Second request uses the Access Token we got as Bearer and is a POST Call to get the Guest_Token from Superset.

    Payload for Guest_Token:

    { 
            "user": {
                "username": "kashew",
                "first name":"Kashish", 
                "lastname":"Bakshi"
            },
            
            "resources": [{
                "type": "dashboard",
                "id": "8f96cc84-7e9e-4f5c-ba92-3a1f0825fe3d"
            }],
            "rls": []
        }
    

    Explanation:
    The Payload is a JSON with 3 Key-Value Pair.

    • user (Here, I created a Dummy User{ This can be replaced with your App Auth Logic})
    • resources (Refer this)
    • rls (I kept it empty but more can be found here)

    I ran my backend on Localhost:5000.

    For Frontend, I created a directory "templates" and put my index.html file inside it.

    index.html

    <html>
      <head>
        <script src="https://unpkg.com/@superset-ui/embedded-sdk"></script>
        <style>
          iframe {
            width: 100%;
            height: 50%;
            border: none;
    
            pretext {
              margin-right: 10%;
              margin-left: 10%;
              font-family: Tahoma;
        </style>
      </head>
      <body>
        <div class="pretext">
          <h2> Covid Statistics </h2>
          <p> Dive into Covid data
          <p id="dashboard-container"></p>
          <script>
            async function fetchGuestTokenFromBackend() {
                let response = await fetch('http://127.0.0.1:5000/guest-token');
                let data = await response.json()
                return data 
            }
    
                const myDashboard = supersetEmbeddedSdk.embedDashboard({
                  id: "8f96cc84-7e9e-4f5c-ba92-3a1f0825fe3d",
                  supersetDomain: "http://<IP>:<PORT>",
                  mountPoint: document.getElementById("dashboard-container"),
                  fetchGuestToken: () => fetchGuestTokenFromBackend(),
                  dashboardUiConfig: {
                    hideTitle: true,
                    hideChartControls: true
                  },
                });
          </script>
        </div>
      </body>
    </html>

    Explanation:
    It calls my guest-token method which returns a Guest-Token to my frontend. The Frontend then makes a request to Superset Embed Dashboard URL with the guest-token which in turn embeds and renders the chart in an Iframe on my website.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search