Skip to content
Home » Integrating Interactive Visual Data: Apache Superset with React.js & Nest.js

Integrating Interactive Visual Data: Apache Superset with React.js & Nest.js

Superset Dashboard

A Step-by-Step Guide with Examples

Apache Superset is a modern data exploration and visualization platform that enables users to analyze and visualize data interactively and intuitively. While many compare Apache Superset to tools like Tableau and Power BI, it offers a significant advantage: it’s completely free and highly customizable. So, let’s explore how to integrate Apache Superset with React.js and Nest.js in your application to visualize a Superset dashboard.

Why Integrate Superset with React?

  • Interactive Dashboards: Superset provides rich, interactive data visualizations, while React enables you to build dynamic, single-page applications.
  • Reusability: You can reuse Superset visualizations across different sections of your React application.
  • Customization: You can customize the appearance and functionality of Superset visualizations within your app using React.
Step 1. Setting Up Superset

To get started, ensure that Apache Superset is running locally or on a server.

Creating Charts and Dashboards: After logging in, you will see the “SQL” option in the top navigation. Click on SQL Lab to write and execute queries that generate your charts and dashboards.

Ensure Your Dataset is Ready: Connect to an existing data source or create a new dataset by running a query in SQL Lab. Once you prepare your dataset, use it to design your dashboards.

Accessing Dashboards via API: After you complete your dashboards, interact with them through Superset’s API, which makes it easy to embed them in your application.

Step 2. Get Dashboard ID

Below are the steps to enable the embedded option and get the dashboard ID.

  • Open the Dashboard: Access your desired dashboard in Apache Superset.
  • Access the Embed Option: Click the three dots in the top-right corner of the dashboard view.
  • Select Embed Dashboard: Choose “Embed Dashboard” from the dropdown menu.
  • Enable Embedding: In the pop-up window, click “Enable Embedding.”
  • Retrieve the Dashboard ID: After enabling embedding, you will see the Dashboard ID displayed in the pop-up window (e.g., 23e4f43s-d3n4-6y7hdvbd3x-). This ID is crucial for embedding the dashboard into your React.js frontend.

Step 3. Fetching Superset Dashboard via API

Superset provides an API that lets you interact with charts, dashboards, and datasets. So, let’s write an API to retrieve the guest token. Additionally, if you need to add any filters to the dashboard, pass them as parameters.

const [supersetGuestToken, setSupersetGuestToken] = useState(null);

const params = {
    client_id
}
axios.post('/api/v1/report/superset-embedd', params).then((resp) => {
    const response = resp?.data?.data;
    if (!response?.guestToken) {
        return;
    }
    setSupersetGuestToken(response?.guestToken);
}).catch(ex => {
    console.error(ex);
});

This handles fetching a Superset guest token for embedding a Superset dashboard in the frontend.

Step 4. Handling Authentication and getting the guest token

To properly embed a Superset dashboard on our React frontend, we must first authenticate with Superset and obtain an access token. We can then use this access token to issue a guest token, which provides access to the dashboard.

1: Create a POST API to Get the Guest Token
In our Nest.js backend, we will create a POST API endpoint to retrieve the guest token:

@Post('superset-embedd')
getSupersetGuestToken(@Body() body: any): Promise<any> {
    return this.reportService.getSupersetEmbed(body);
}

The getSupersetGuestToken method accepts arguments from the request body and calls the getSupersetEmbed method of the service, which handles the entire process of acquiring the guest token.

2: Authenticating with Superset
Before making the guest token request, we must authenticate with Superset to fetch the access token. The supersetAuth function handles this process:

import got from 'got';
import { CookieJar } from 'tough-cookie';

async supersetAuth() {
    const loginUrl = ${config.get('superset.domain')}/api/v1/security/login
    const cookieJar = new CookieJar();
    const loginOptions: any = {
        method: 'POST',
        json: {
            "username": config.get('superset.username'),
            "provider": "db",
            "refresh": 1,
            "password": config.get('superset.password'),
        },
        cookieJar
    }
    const loginResponse = await got(loginUrl, loginOptions);
    const { access_token: accessToken } = JSON.parse(loginResponse.bod
    return {
        accessToken,
        loginUrl,
        cookieJar
    };
}

Config-Driven Credentials: Rather than hardcoding sensitive data like the Superset domain (e.g.:https://superset.test.co.in/), username, and password, we dynamically fetch these values from the config file using config.get(). This approach significantly improves security and flexibility.

Handling Cookies: To manage cookies during the authentication session, we utilize CookieJar from the tough-cookie library. This step is crucial for maintaining the session across multiple requests.

Access Token: After we send the login request to Superset’s API, we extract the accessToken from the response. This token is essential for making subsequent API requests.

3. Get the Guest token

Once authenticated, the getSupersetEmbed function fetches the guest token, which is needed to embed the Superset dashboard:

async getSupersetEmbed(data: any): Promise <any> {
    const { client_id } = data;

    const { accessToken, cookieJar, loginUrl } = await this.supersetAuth();
    if(!accessToken) {
        return {
            success: false,
            message: "Superset login failed!"
        }
    }

    const dashboardId = '23e4f43s-d3n4-6y7hdvbd3x-********';
    const supersetDomain = config.get('superset.domain');
    const rls = []
    const resource_list = [];

    resource_list.push({ "type": "dashboard", "id": dashboardId })
    if(client_id) {
        rls.push({ "clause": `client_id IN ('${client_id}')` });
    }

    const csrfTokenUrl = `${supersetDomain}/api/v1/security/csrf_token/`;
    const csrfResp = await got(csrfTokenUrl, {
        headers: {
            Authorization: `Bearer ${accessToken}`,
        },
        cookieJar
    });

    const { result: csrf } = JSON.parse(csrfResp.body)
    const headers = {
        "X-CSRFToken": csrf,
        "X-CSRF-Token": csrf,
        "Referer": loginUrl,
        "Authorization": "Bearer " + accessToken,
    }
    const postData = {
        "resources": resource_list,
        "rls": rls,
        "user": {
            "username": config.get('superset.username'),
            "first_name": config.get('superset.firstName'),
            "last_name": config.get('superset.lastName'),
        },
    }
    const guestTokenUrl = `${supersetDomain}/api/v1/security/guest_token/`
    const options: any = {
        method: 'POST',
        json: postData,
        headers,
        cookieJar,
    };

    try {
        const guestTokenData = await got(guestTokenUrl, options);
        const { token: guestToken } = JSON.parse(guestTokenData.body)
        return {
            success: true,
            data: {
                rls,
                resource_list,
                guestToken
            }
        }
    } catch(err) {
        console.error('err: ', err);
        return {
            success: false,
            message: `Failed to get the guest token!`
        }
    }
}

Client-Specific Filters (RLS): If a client_id is provided in the request, the system uses it to add a Row Level Security (RLS) filter, thereby limiting data visibility based on the client. This approach ensures that only data related to the specific client appears on the embedded dashboard.

CSRF Token: Next, the application requests a Superset CSRF token to ensure security for POST requests. The system then places the CSRF token in the headers.

Requesting the Guest Token: Finally, you can request the guest token by sending a request to /api/v1/security/guest_token/. This guest token will allow you to embed the dashboard into the frontend.

4. Load Superset Dashboard

We can now embed the Superset dashboard in our React application using the @superset-ui/embedded-sdk package. First, ensure you have installed the package. Then, follow the integration steps to seamlessly integrate the dashboard into your app.

import { embedDashboard } from "@superset-ui/embedded-sdk";

const dashboardRef = useRef(null);

useEffect(() => {
    embedSupersetDashboard();
}, [supersetGuestToken]);

const embedSupersetDashboard = async () => {
    if (!dashboardId) {
        return
    }
    await embedDashboard({
        id: dashboardId,  // ID of the dashboard to embed
        supersetDomain: 'https://superset.domain.com',  // Superset domain URL
        mountPoint: dashboardRef.current,  // The DOM element to embed the dashboard
        fetchGuestToken: () => supersetGuestToken,
        dashboardUiConfig: {
            hideTitle: true,  // Hide the dashboard title
            hideChartControls: true,  // Hide chart control options
            hideTab: true,  // Hide tab bar
            filters: {
                visible: false,  // Hide filter panel
                expanded: false,  // Keep filter panel collapsed
            }
        }
    });
}

return (
    <div id={`superset-db-${dashboardId}`}>
        <div ref={dashboardRef} 
            style={{ height: dashboardHeight }} 
            className="superset-db">
        </div>
    </div>
);

The embedDashboard function embeds the dashboard into the component while ensuring safety. Additionally, we customize the dashboard by hiding titles, controls, tabs, and filters to create a cleaner UI. Meanwhile, the fetchGuestToken function retrieves the guest token required for the dashboard.

By following these steps, you can effectively authenticate with Superset and seamlessly embed a fully interactive dashboard in your React app using the guest token.

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments