Superset series 4/6 — Modifying plugins

Teclead Ventures
6 min readMay 17, 2023

--

Teclead Ventures
We enable our enterprise clients to reach the mass market and digitalize internal and external businees processes. https://teclead-ventures.de/en

We are hiring!

Introduction

Modifying an existing plugin can be a great way to add new functionality to Superset, tweak the behavior of an existing feature, or fix a bug. Instead of creating a plugin from scratch it can often be more suitable to build upon already implemented plugins.

Open up an Editor of your choice and start editing the cloned repository. You can find all plugins in the directory: /superset-frontend/plugins

We will start by choosing a Plugin which we want to modify. In this guide we are choosing the heatmap Plugin which you can find in the /superset-frontend/plugins/legacy-plugin-chart-heatmap directory. Feel free to choose any other Plugin or any other dataset.

If you want to modify a plugin but keep the original one, then it might be useful to copy the desired plugin first. In the third guide of our superset documentation we discuss how to copy plugins.

Version

In this Guide we are using Superset version 2.1.0

You can use the same version by checking out in the corresponding branch

git checkout 2.1.0

Preparation

  • Make sure to stop any other superset non-related PostgreSQL instances
  • Node 16.9.1
  • Python 3.6 or newer

Then run the following commands in /superset-frontend directory:

cd superset-frontend
npm i
npm run build
cd ..
superset load examples
superset db upgrade
superset init
superset run -p 8088 --with-threads --reload --debugger

Result Repository

This Superset documentation series will guide you through each step of customizing Superset. If you’d like to use the results directly, you can clone our Git repository, which includes all changes made during the course of this guide:

(OPTIONAL)
git clone https://github.com/Teclead-Ventures/superset

Default Plugin Preview

💡It can take a bit for the datasets to fetch , if you can not see them try closing the page and reopen it

To preview our heatmap Plugin we can create a new chart by clicking the plus button in the top right corner and selecting ‘Chart’.

Then a dataset has to be chosen, in our example we choose the video_game_sales, as well as the heatmap Chart type:

Now we can set our query in the control panel on the left hand side to create a default heatmap chart.

(Here we set X-Axis : Year, Y-Axis: Genre , Metric : Count)

For this demonstration we will implement a feature which allows us to set our own Color Scheme by picking a color. We will edit the Controlpanel.tsx and change the data flow. In part 2 of our superset series we explain those two topics.

The result will look like this :

As you can see instead of choosing a linear color scheme, we are able to choose a color from an added color picker.

  1. In /legacy-plugin-chart-heatmapcopy/src/controlPanel.tsx we are adding the following color picker option:
controlSetRows: [
['linear_color_scheme'],
// Copy and Paste the following Array
[
{
name: 'primary_color_picker',
config: {
type: 'ColorPickerControl',
label: t('Primary Color'),
description: t(
'Use this to define a static color for all circles',
),
default: { r: 70, g: 80, b: 120, a: 1 },
renderTrigger: true,
},
},
],
//
...
]

When rebuilding superset the new option should appear in the controlpanel :

2. Now we adjust the /legacy-plugin-chart-heatmapcopy/src/transformProps.js props so that our color value is passed to the plugin correctly. Add primaryColorPicker :

Note that you should use the same name as the one you defined in the controlPanel.tsx file, but in camelCase instead of snake_case. So in our example we used primary_color_picker in controlpanel and primaryColorPicker in transformprops

export default function transformProps(chartProps) {
const { width, height, formData, queriesData } = chartProps;
const {
bottomMargin,
canvasImageRendering,
allColumnsX,
allColumnsY,
linearColorScheme,
primaryColorPicker, // ADDED
leftMargin,
metric,
normalized,
showLegend,
showPerc,
showValues,
sortXAxis,
sortYAxis,
xscaleInterval,
yscaleInterval,
yAxisBounds,
yAxisFormat,
} = formData;
return {
width,
height,
data: queriesData[0].data,
bottomMargin,
canvasImageRendering,
colorScheme: linearColorScheme,
primaryColorPicker, // ADDED
columnX: allColumnsX,
columnY: allColumnsY,
leftMargin,
metric,
normalized,
numberFormat: yAxisFormat,
showLegend,
showPercentage: showPerc,
showValues,
sortXAxis,
sortYAxis,
xScaleInterval: parseInt(xscaleInterval, 10),
yScaleInterval: parseInt(yscaleInterval, 10),
yAxisBounds,
};
}

3. Next in the /legacy-plugin-chart-heatmapcopy/src/Heatmap.js add primaryColorPicker :

const propTypes = {
data: PropTypes.shape({
records: PropTypes.arrayOf(
PropTypes.shape({
x: PropTypes.string,
y: PropTypes.string,
v: PropTypes.number,
perc: PropTypes.number,
rank: PropTypes.number,
}),
),
extents: PropTypes.arrayOf(PropTypes.number),
}),
width: PropTypes.number,
height: PropTypes.number,
bottomMargin: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),

primaryColorPicker: PropTypes.object, // Added

columnX: PropTypes.oneOfType([PropTypes.object, PropTypes.string]),
columnY: PropTypes.oneOfType([PropTypes.object, PropTypes.string]),
leftMargin: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
metric: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
normalized: PropTypes.bool,
numberFormat: PropTypes.string,
showLegend: PropTypes.bool,
showPercentage: PropTypes.bool,
showValues: PropTypes.bool,
sortXAxis: PropTypes.string,
sortYAxis: PropTypes.string,
xScaleInterval: PropTypes.number,
yScaleInterval: PropTypes.number,
yAxisBounds: PropTypes.arrayOf(PropTypes.number),
};

4. Do the same for props :

function Heatmap(element, props) {
const {
data,
width,
height,
bottomMargin,
canvasImageRendering,
primaryColorPicker, // added
columnX,
columnY,
leftMargin,
metric,
normalized,
numberFormat,
showLegend,
showPercentage,
showValues,
sortXAxis,
sortYAxis,
xScaleInterval,
yScaleInterval,
yAxisBounds,
} = props

5. Now we adjust the colorScale Variable inside the Heatmap.js

// Find this Variable
const colorScale = getSequentialSchemeRegistry()
.get(colorScheme)
.createLinearScale([minBound, maxBound]);

For this step create a function which takes the RGB Object from the primaryColorPicker and returns a colorScale array. This can be implemented like this :

function rgbToHex(r, g, b) {
return `#${[r, g, b].map(x => x.toString(16).padStart(2, '0')).join('')}`;
}
function generateColorScale(primaryColorPicker) {
const { r, g, b } = primaryColorPicker;
const stepSize = (255 - Math.max(r, g, b)) / 10;
const tempcolorScale = [];
for (let i = 0; i < 10; i += 1) {
const newR = Math.min(255, r + i * stepSize);
const newG = Math.min(255, g + i * stepSize);
const newB = Math.min(255, b + i * stepSize);
tempcolorScale.push(
rgbToHex(Math.round(newR), Math.round(newG), Math.round(newB)),
);
}
return tempcolorScale.reverse();
}

Using those methods we can modify the colorScale variable :

// Add this
const beforeScaleAdded = getSequentialSchemeRegistry().get(colorScheme);
beforeScaleAdded.colors = generateColorScale(primaryColorPicker);
// Adjust colorScale to this :
const colorScale = beforeScaleAdded .createLinearScale([minBound, maxBound]);

Rebuild Superset by running :

cd superset-frontend
npm i
npm run build
cd ..
superset db upgrade
superset init
superset run -p 8088 --with-threads --reload --debugger

And that is it! Sometimes checking the NORMALIZED Checkbox gives better resuts. The heatmap plugin should then look like this :

Wrapping up this guide shows you how props are passed inside superset plugins and how to set different settings which affect the data visualization. In your very own use case this knowledge will help you to customize and add features to default plugins.

In the next part of our superset series we will show you how to add plugins from scratch which we will then use in the guide after to visualize maps using the Openlayers library.

Superset Setup Part 1 : https://medium.com/@teclead-ventures/superset-series-1-6-setting-up-superset-a750481c228e

Superset Controlpanel Part 2 : https://medium.com/@teclead-ventures/superset-series-2-6-control-panel-31a84afae465

Cloning Superset Plugins Part 3: https://medium.com/@teclead-ventures/superset-series-3-6-cloning-plugins-3336a8a979a0

Adding Superset Plugins Part 5 : https://medium.com/@teclead-ventures/superset-series-5-6-adding-plugins-4677c6a1ff5b

Visualizing Maps using Openlayers in Superset Part 6 : https://teclead-ventures.medium.com/superset-series-6-6-openlayers-map-visualization-e72e2976cfa0

Author : Daniel Jin Wodke

Editors: Ruben Karlsson, Matthias Daiber, Cherif Khlass, Lukas Zöllner, John Einicke

--

--

Teclead Ventures
Teclead Ventures

Written by Teclead Ventures

We enable our enterprise clients and our venture startups to reach the mass market and digitalize internal and external business processes.

No responses yet