Charts
Analytics Dashboard
View Source
Mixed chart types with real-time data updates and interactive legends.
Analytics Dashboard
Website traffic and user engagement metrics
Last 30 days
Page Views
1.2M+18.2%Unique Visitors
342K+12.4%Bounce Rate
42.3%-5.1%Avg. Session
4m 32s+8.7%Conversions
8,432+22.1%Traffic Overview
Daily visitors over the past month
Traffic Sources
Distribution by channel
User Engagement
Actions per session by page type
Device Breakdown
Traffic by device type
Explore More Demos
Oorian Core
Task Manager
Interactive task manager demonstrating pure Oorian features: forms, tables, e...
Oorian Core
Browser APIs
Access browser features from Java: Geolocation, Clipboard, Storage, Notificat...
Maps
Weather Forecast
Real-time weather app with current conditions, 10-day forecast, hourly temper...
AnalyticsDashboardDemo.java
✕
/***********************************************************************************
* Copyright (c) 2025 Corvus Engineering
* All Rights Reserved
***********************************************************************************/
package com.oorian.website.demos;
import com.oorian.OorianWorkerThread;
import com.oorian.apexcharts.AxChart;
import com.oorian.apexcharts.AxSeries;
import com.oorian.css.*;
import com.oorian.html.elements.*;
import java.util.Random;
/****************************************************************************************************************
* Analytics Dashboard demo component.
* Showcases a web analytics dashboard with multiple ApexCharts visualizations.
* Features real-time data updates using OorianWorkerThread.
****************************************************************************************************************/
public class AnalyticsDashboardDemo extends Div
{
private AxChart trafficChart;
private AxChart sourcesChart;
private AxChart engagementChart;
private AxChart deviceChart;
private final Random random = new Random();
// Base values for simulating data changes
private int[] organicData = {12500, 14200, 13800, 16500};
private int[] directData = {8200, 9100, 8800, 10200};
private int[] referralData = {4500, 5200, 4900, 5800};
private int[] sourcesData = {72, 58, 45, 38};
private double[] clicksData = {4.2, 6.8, 3.5, 8.1, 5.2};
private double[] scrollsData = {2.8, 4.5, 5.2, 3.2, 2.1};
private int[] deviceData = {52, 38, 10};
public AnalyticsDashboardDemo()
{
createDashboard();
}
@Override
protected void initialize()
{
super.initialize();
startLiveUpdates();
}
private void startLiveUpdates()
{
OorianWorkerThread.create(() ->
{
try
{
while (true)
{
// Sleep for 3 seconds between updates
Thread.sleep(3000);
// Generate small random variations in the data
updateTrafficData();
updateSourcesData();
updateEngagementData();
updateDeviceData();
// Push updates to the client
sendUpdate();
}
}
catch (InterruptedException e)
{
// Thread interrupted, stop updates
Thread.currentThread().interrupt();
}
});
}
private void updateTrafficData()
{
// Apply small random variations to traffic data (±5%)
for (int i = 0; i < organicData.length; i++)
{
organicData[i] = varyValue(organicData[i], 0.05);
directData[i] = varyValue(directData[i], 0.05);
referralData[i] = varyValue(referralData[i], 0.05);
}
trafficChart.updateSeries(
new AxSeries("Organic").setData(organicData[0], organicData[1], organicData[2], organicData[3]),
new AxSeries("Direct").setData(directData[0], directData[1], directData[2], directData[3]),
new AxSeries("Referral").setData(referralData[0], referralData[1], referralData[2], referralData[3])
);
}
private void updateSourcesData()
{
// Vary sources data, keeping values between 20-90
for (int i = 0; i < sourcesData.length; i++)
{
sourcesData[i] = Math.max(20, Math.min(90, varyValue(sourcesData[i], 0.03)));
}
sourcesChart.updatePieData(sourcesData[0], sourcesData[1], sourcesData[2], sourcesData[3]);
}
private void updateEngagementData()
{
// Apply small random variations to engagement data (±8%)
for (int i = 0; i < clicksData.length; i++)
{
clicksData[i] = Math.max(1.0, varyValueDouble(clicksData[i], 0.08));
scrollsData[i] = Math.max(1.0, varyValueDouble(scrollsData[i], 0.08));
}
engagementChart.updateSeries(
new AxSeries("Clicks").setData(clicksData[0], clicksData[1], clicksData[2], clicksData[3], clicksData[4]),
new AxSeries("Scrolls").setData(scrollsData[0], scrollsData[1], scrollsData[2], scrollsData[3], scrollsData[4])
);
}
private void updateDeviceData()
{
// Vary device data slightly, keeping total around 100%
int desktopChange = random.nextInt(5) - 2;
int mobileChange = random.nextInt(3) - 1;
deviceData[0] = Math.max(40, Math.min(65, deviceData[0] + desktopChange));
deviceData[1] = Math.max(25, Math.min(50, deviceData[1] + mobileChange));
deviceData[2] = 100 - deviceData[0] - deviceData[1];
deviceChart.updatePieData(deviceData[0], deviceData[1], deviceData[2]);
}
private int varyValue(int value, double maxVariation)
{
double variation = (random.nextDouble() * 2 - 1) * maxVariation;
return (int) (value * (1 + variation));
}
private double varyValueDouble(double value, double maxVariation)
{
double variation = (random.nextDouble() * 2 - 1) * maxVariation;
return Math.round((value * (1 + variation)) * 10.0) / 10.0;
}
private void createDashboard()
{
// Main container
setPadding("40px");
setBackgroundColor("#0f172a");
Div container = new Div();
container.setMaxWidth("1400px");
container.setMargin("0 auto");
// Dashboard header
container.addElement(createDashboardHeader());
// Metrics cards row
container.addElement(createMetricsRow());
// Main charts area
container.addElement(createMainChartsArea());
// Bottom row
container.addElement(createBottomRow());
addElement(container);
}
private Div createDashboardHeader()
{
Div header = new Div();
header.setDisplay(Display.FLEX);
header.setJustifyContent(JustifyContent.SPACE_BETWEEN);
header.setAlignItems(AlignItems.CENTER);
header.setMarginBottom("32px");
Div titleSection = new Div();
H2 title = new H2();
title.setText("Analytics Dashboard");
title.setColor("#f8fafc");
title.setFontSize("26px");
title.setFontWeight("700");
title.setMarginTop("0");
title.setMarginBottom("4px");
titleSection.addElement(title);
P subtitle = new P();
subtitle.setText("Website traffic and user engagement metrics");
subtitle.setColor("#94a3b8");
subtitle.setFontSize("14px");
subtitle.setMargin("0");
titleSection.addElement(subtitle);
header.addElement(titleSection);
// Time range selector (decorative)
Div timeRange = new Div();
timeRange.setBackgroundColor("#1e293b");
timeRange.setPadding("8px 16px");
timeRange.setBorderRadius("8px");
timeRange.setColor("#94a3b8");
timeRange.setFontSize("13px");
timeRange.setText("Last 30 days");
header.addElement(timeRange);
return header;
}
private Div createMetricsRow()
{
Div row = new Div();
row.setDisplay(Display.GRID);
row.addStyleAttribute("grid-template-columns", "repeat(auto-fit, minmax(200px, 1fr))");
row.addStyleAttribute("gap", "16px");
row.setMarginBottom("24px");
row.addElement(createMetricCard("Page Views", "1.2M", "+18.2%", true));
row.addElement(createMetricCard("Unique Visitors", "342K", "+12.4%", true));
row.addElement(createMetricCard("Bounce Rate", "42.3%", "-5.1%", true));
row.addElement(createMetricCard("Avg. Session", "4m 32s", "+8.7%", true));
row.addElement(createMetricCard("Conversions", "8,432", "+22.1%", true));
return row;
}
private Div createMetricCard(String label, String value, String change, boolean positive)
{
Div card = new Div();
card.setBackgroundColor("#1e293b");
card.setBorderRadius("12px");
card.setPadding("20px");
P labelEl = new P();
labelEl.setText(label);
labelEl.setColor("#94a3b8");
labelEl.setFontSize("12px");
labelEl.setFontWeight("500");
labelEl.setMarginTop("0");
labelEl.setMarginBottom("8px");
labelEl.addStyleAttribute("text-transform", "uppercase");
labelEl.addStyleAttribute("letter-spacing", "0.05em");
card.addElement(labelEl);
Span valueEl = new Span();
valueEl.setText(value);
valueEl.setColor("#f8fafc");
valueEl.setFontSize("24px");
valueEl.setFontWeight("700");
valueEl.setDisplay(Display.BLOCK);
valueEl.setMarginBottom("4px");
card.addElement(valueEl);
Span changeEl = new Span();
changeEl.setText(change);
changeEl.setColor(positive ? "#10b981" : "#ef4444");
changeEl.setFontSize("13px");
changeEl.setFontWeight("500");
card.addElement(changeEl);
return card;
}
private Div createMainChartsArea()
{
Div area = new Div();
area.setDisplay(Display.GRID);
area.addStyleAttribute("grid-template-columns", "2fr 1fr");
area.addStyleAttribute("gap", "24px");
area.setMarginBottom("24px");
// Traffic trend chart (area chart)
area.addElement(createTrafficTrendCard());
// Traffic sources (radial bar)
area.addElement(createTrafficSourcesCard());
return area;
}
private Div createTrafficTrendCard()
{
Div card = createChartCard("Traffic Overview", "Daily visitors over the past month");
trafficChart = new AxChart(AxChart.TYPE_AREA)
.setChartHeight(320)
.setCategories("Week 1", "Week 2", "Week 3", "Week 4")
.addSeries(new AxSeries("Organic")
.setData(organicData[0], organicData[1], organicData[2], organicData[3]))
.addSeries(new AxSeries("Direct")
.setData(directData[0], directData[1], directData[2], directData[3]))
.addSeries(new AxSeries("Referral")
.setData(referralData[0], referralData[1], referralData[2], referralData[3]))
.setColors("#00e396", "#008ffb", "#feb019")
.setCurve(AxChart.CURVE_SMOOTH)
.setStacked(true)
.setLegendPosition(AxChart.LEGEND_TOP)
.setToolbar(false)
.setGrid(true)
.setForegroundColor("#94a3b8");
card.addElement(trafficChart);
return card;
}
private Div createTrafficSourcesCard()
{
Div card = createChartCard("Traffic Sources", "Distribution by channel");
sourcesChart = new AxChart(AxChart.TYPE_RADIAL_BAR)
.setChartHeight(320)
.setPieData(
new String[]{"Organic", "Direct", "Social", "Referral"},
new Number[]{sourcesData[0], sourcesData[1], sourcesData[2], sourcesData[3]})
.setColors("#00e396", "#008ffb", "#feb019", "#ff4560")
.setLegendPosition(AxChart.LEGEND_BOTTOM)
.setForegroundColor("#94a3b8");
card.addElement(sourcesChart);
return card;
}
private Div createBottomRow()
{
Div row = new Div();
row.setDisplay(Display.GRID);
row.addStyleAttribute("grid-template-columns", "1fr 1fr");
row.addStyleAttribute("gap", "24px");
// User engagement (bar chart)
row.addElement(createEngagementCard());
// Device breakdown (donut)
row.addElement(createDeviceBreakdownCard());
return row;
}
private Div createEngagementCard()
{
Div card = createChartCard("User Engagement", "Actions per session by page type");
engagementChart = new AxChart(AxChart.TYPE_BAR)
.setChartHeight(280)
.setCategories("Home", "Products", "Blog", "Checkout", "Account")
.addSeries(new AxSeries("Clicks")
.setData(clicksData[0], clicksData[1], clicksData[2], clicksData[3], clicksData[4]))
.addSeries(new AxSeries("Scrolls")
.setData(scrollsData[0], scrollsData[1], scrollsData[2], scrollsData[3], scrollsData[4]))
.setColors("#008ffb", "#00e396")
.setLegendPosition(AxChart.LEGEND_TOP)
.setToolbar(false)
.setDataLabels(false)
.setForegroundColor("#94a3b8");
card.addElement(engagementChart);
return card;
}
private Div createDeviceBreakdownCard()
{
Div card = createChartCard("Device Breakdown", "Traffic by device type");
deviceChart = new AxChart(AxChart.TYPE_DONUT)
.setChartHeight(280)
.setPieData(
new String[]{"Desktop", "Mobile", "Tablet"},
new Number[]{deviceData[0], deviceData[1], deviceData[2]})
.setColors("#008ffb", "#00e396", "#feb019")
.setLegendPosition(AxChart.LEGEND_BOTTOM)
.setForegroundColor("#94a3b8");
card.addElement(deviceChart);
return card;
}
private Div createChartCard(String title, String subtitle)
{
Div card = new Div();
card.setBackgroundColor("#1e293b");
card.setBorderRadius("12px");
card.setPadding("24px");
H4 titleEl = new H4();
titleEl.setText(title);
titleEl.setColor("#f8fafc");
titleEl.setFontSize("15px");
titleEl.setFontWeight("600");
titleEl.setMarginTop("0");
titleEl.setMarginBottom("4px");
card.addElement(titleEl);
P subtitleEl = new P();
subtitleEl.setText(subtitle);
subtitleEl.setColor("#64748b");
subtitleEl.setFontSize("12px");
subtitleEl.setMarginTop("0");
subtitleEl.setMarginBottom("16px");
card.addElement(subtitleEl);
return card;
}
}