Hi!
I am a Software Engineering student and a beginner developer. For now, I am actively experimenting with data visualization and learning new tools for it.
In this article, I want to share a small but useful project that demonstrates how to create a one-page data analytics app.
So, speaking shortly, here I’ll show a way of building a complete web project using:
- Flexmonster Pivot Table
- Highcharts
- React
Flexmonster
Previously, I’ve had some experience working with Flexmonster, so I was already familiar with it. Also, I was impressed by how fast it can work with a large amount of data, and has an intuitively understandable UI where reports can be easily done.
Highcharts
For chart visualization, we’ll use Highcharts because they suggest a lot of types of charts and are so easy to combine with Flexmonster.
React
Maybe the easiest one to explain: I’ve just been using React in some projects and really enjoyed working with it. Also, it is quite a popular framework, which makes development faster and keeps code clean and understandable.
Then it was time to choose the dataset. For me, this process was quite long. I wanted to find something interesting and well-known. So, one random day, while listening to music, it hit me — why not use a Spotify dataset? Everyone knows it, it’s full of data, and who doesn’t want to see info about how high on the charts their favourite musician is?
As you may already understand, I will use the Spotify Top 200 Dataset from Kaggle to demonstrate how users can upload and analyze their own CSV data.
This article is presented in a tutorial format, making it easy to apply to your own projects. I genuinely hope it’s helpful.
Step 1: Integrating Flexmonster Pivot
I hope your React projects are already prepared, because now it’s time to integrate it ith Flexmonster!
In the beginning, you need to install Flexmonster CLI from npm:
npm install -g flexmonster-cli
To get Flexmonster, you should open your React project and run the following command:
flexmonster add js-flexmonster
After that, the flexmonster npm package will be downloaded to your node_modules/ .
Also, you can get Flexmonster not only from the CLI, but also from CDN, npm, ZIP package, and WebJars. To get more information about it, you can read about integrating Flexmonster here.
As I’m using React in this project, I need to add a React Wrapper for Flexmonster, which can be done by using this command:
npm install react-flexmonster
Step 2: Importing all necessary modules
Now that we have Flexmonster installed and ready, let’s build the main interface of our application using React.
We need to import all necessary modules at the top of App.js file:
import React, { useRef, useState, useEffect } from "react";
import { Pivot } from "react-flexmonster";
import "flexmonster/flexmonster.css";
import "./App.css";
The pivot component from react-flexmonster is what renders the interactive pivot table. We also import Flexmonster’s CSS files to apply the default styling, and optionally, you can import your own custom styles with App.css.
Step 3: Creating the Report Object
Inside our App.jsx file, we create a report object that describes the data source, field mapping, layout, and visual options for the pivot table.
const report = {
dataSource: {
filename: "/spotify-top-200-dataset.csv",
mapping: {
artist_name: { type: "string" },
track_name: { type: "string" },
streams: { type: "number" },
},
},
It’s important to mention the filename – path to the file (CSV file, in my case), it is spotify-top-200-dataset.csv.
Step 4: Configuring the Pivot Table Slice
Then we need to write the slice section, which defines how the data is grouped and summarized.
I was thinking what info is the best to display and decided to choose the artist, tracks, and number of streams.
So, to display it all, we need:
- to include artists and track names in the rows;
- to show the total number of streams as measures;
- to apply sorting in descending order based on the stream count.
-
slice: { rows: [ { uniqueName: "artist_name" }, { uniqueName: "track_name" } ], measures: [ { uniqueName: "streams", aggregation: "sum" } ], sorting: { column: { type: "desc", tuple: [], measure: "streams", }, }, },
Step 5: Setting Up the Component
Now, we define the pivot grid component and add it to the page:
return (
<div id="app-container">
<header>
<h1>Spotify Insights</h1>
</header>
<main>
<Pivot
key="original"
ref={pivotRef}
toolbar={true}
beforetoolbarcreated={customizeToolbar}
report={report}
licenseFilePath="https://cdn.flexmonster.com/jsfiddle.charts.key"
width="100%"
height="400px"
/>
<div id="highcharts-container"></div>
</main>
</div>
);
Here we define our pivot table, enabling the toolbar to be shown when we render the page. There is also an option to hide the toolbar, just don’t write the line toolbar={true}.
Now, I suggest you make our project more interactive by customizing the toolbar. Being more precise, adding a new tab. One of the biggest advantages of pivot tables is that you can see all your data from different angles. In my case, I didn’t want to change “Tracks View” anymore, so this tab will help us, because we will create a completely new view which will demonstrate even more possibilities of pivot tables.
For this, we need to create a function customizeToolbar:
function customizeToolbar(toolbar) {
const tabs = toolbar.getTabs();
toolbar.getTabs = function () {
tabs.unshift({
id: "fm-tab-newtab",
title: showOriginalPivot ? "Albums" : "Tracks",
handler: newTabHandler,
icon: this.icons.options,
});
return tabs;
};
}
In this code, we:
- Get all already existing tabs using getTabs()
- Add a new tab that will switch between two views (in our case, it will be two pivot tables)
Step 7: Creating a Second Pivot Table
For the second view, we will create a pivot table with albums. We should do the same steps as we did before but just a little bit change the data. For example, in report object we will display the year of release date, album name, artist name, and number of streams:
const genresReport = {
dataSource: {
filename: "/spotify-top-200-dataset.csv",
mapping: {
artist_name: { type: "string" },
streams: { type: "number" },
album_name: { type: "string" },
release_date: { type: "date" }
},
},
slice: {
rows: [
{ uniqueName: "release_date.Year" },
{ uniqueName: "album_name" }
],
columns: [
{
uniqueName: "artist_name",
filter: {
measure: "streams",
type: "top",
quantity: 20
},
sort: "desc"
}
],
measures: [
{ uniqueName: "streams", aggregation: "sum" }
],
sorting: {
column: {
type: "desc",
tuple: [],
measure: "streams"
}
}
}
};
Step 8: Install Highcharts and Bind Flexmonster to It
To install Highcharts, write the following command in the terminal:
npm install highcharts
Then, import Highcharts into your project:
import Highcharts from "highcharts";
import "flexmonster/lib/flexmonster.highcharts.js";
More about the integration of Flexmonster with Highcharts can be found here.
Inside your App.jsx, use useRef and useEffect to connect the pivot table with Highcharts:
const pivotRef = useRef(null);
useEffect(() => {
const handleReportComplete = (): void => {
const pivot = pivotRef.current?.flexmonster;
if (pivot) {
pivot.highcharts.getData(
{
type: "column",
},
(data: GetDataValueObject): void => {
Highcharts.chart("highcharts-container", data);
}
);
}
};
const pivot = pivotRef.current?.flexmonster;
if (pivot) {
pivot.on("reportcomplete", handleReportComplete);
}
}, []);
Here, pivotRef lets us get access to the pivot table instance so we can work with its built-in functions.
We use the “reportcomplete” event to run our code once the pivot table has finished loading.
Step 9: Displaying the Chart
Once data is passed to Highcharts via pivot.highcharts.getData(…), the chart will automatically appear in the container with the specified chart type. You can use any chart type supported by Highcharts, for example line, pie, or bar, by changing the type passed to getData.
I сhose to use a column chart for this project. It’s a familiar and visually intuitive way to display data. You can enable it in your code by specifying:
pivot.highcharts.getData({ type: "column" }, (data) => {
Make sure you have a <div> with a proper id for the Highcharts component:
<div id="highcharts-container"></div>
When the Flexmonster pivot table finishes loading, reportcomplete event is triggered. Then, we extract data using Flexmonster’s Highcharts integration and render it.
Step 10: Customizing your web app
And here is my favorite part of every project – styling and customizing!
I tried to make these grids as similar to Spotify’s original design as possible: font, black background, and green color.
So, how to implement it all? Let’s separately talk about Flexmonster pivot table and Highcharts visualizations.
Step 10.1: Customizing Flexmonster
Flexmonster has built-in themes, and all possible options are available in this demo.
However, as we want to do it in Spotify style, as much as possible, we’ll need to create a custom theme.
Firstly, you need to run these commands in your terminal to get theme-builder:
git clone https://github.com/flexmonster/custom-theme-builder
cd custom-theme-builder
In the custom-theme-builder/ folder, we should find and open the flexmonster.less file. There you can apply any styles you want.
After it, we need to compile .less file into .css, which can be easily done with the following command:
lessc flexmonster.less flexmonster.css
Then, add flexmonster.css file to your project src folder.
In index.html add this line:
<link rel="stylesheet" href="/flexmonster.css" />
And also don’t forget to import flexmonster.css file to your project in App.jsx:
import "flexmonster/flexmonster.css";
import "../flexmonster.css"
When you complete all these steps, you can already see a customized pivot table in your own style!
Step 10.2: Customizing Highcharts
Unfortunately, not all the CSS code can be applied to Highcharts, so to reduce the number of bugs and difficulties, I decided to do the styling directly in App.jsx.
Here is the code with already implemented styling of Highcharts:
const handleReportComplete = () => {
pivot.highcharts.getData({ type: "column" }, (data) => {
Highcharts.chart("highcharts-container", {
...data,
chart: {
...data.chart,
backgroundColor: "transparent",
style: {
fontFamily:
"'Poppins', 'Circular Spotify Text', 'Helvetica Neue', Helvetica, Arial, sans-serif",
},
},
title: {
text: "Spotify Top 200 Streams",
style: {
color: "#1DB954",
fontWeight: "900",
fontSize: "26px",
textShadow: "0 0 8px #1DB954",
},
},
xAxis: {
...data.xAxis,
labels: {
style: { color: "#E3E3E3", fontSize: "13px" },
},
lineColor: "#1DB954",
tickColor: "#1DB954",
},
yAxis: {
...data.yAxis,
labels: {
style: { color: "#E3E3E3", fontSize: "13px" },
},
gridLineColor: "rgba(29, 185, 84, 0.3)",
title: {
text: "Streams",
style: { color: "#1DB954", fontWeight: "700" },
},
},
legend: {
enabled: false,
},
plotOptions: {
column: {
color: "#1DB954",
borderRadius: 6,
shadow: {
color: "rgba(29, 185, 84, 0.8)",
offsetX: 0,
offsetY: 0,
opacity: 0.9,
width: 12,
},
},
},
tooltip: {
backgroundColor: "#1DB954",
style: { color: "#121212", fontWeight: "700" },
borderRadius: 8,
borderWidth: 0,
shadow: true,
animation: true,
},
series: data.series,
});
});
};
Feel free to change it to the way that works best for you!
Finally, we have our project completely done, and I hope that you are also happy with the result!
If you want to get the whole code, you can check this dashboard on my GitHub.
And there is our result:
Also, I’d love to hear your feedback and any thoughts about this webpage.
Thanks for reading, and good luck with coding!