Build a Dashboard with GraphicWalker
GraphicWalker is a powerful data visualization tool that enables you to create dashboards using a simple drag-and-drop interface. With GraphicWalker, you can build interactive visualizations, charts, and maps without needing to write any code.
In this tutorial, we will demonstrate how to build a dashboard using GraphicWalker and react-grid-layout.
You can design a dashboard through the drag-and-drop interface and save the layout to the server, allowing other users to view the dashboard.
Template Project
The template project includes an example dashboard builder with several widgets.
Quick Start
This project uses IndexedDB to store the dashboard layout. To run the project locally, follow these steps:
yarn install
yarn dev
The frontend will run on port 5173. You can visit http://localhost:5173/ (opens in a new tab) to see the dashboard builder in action.
Using Server Datasets
This project uses IndexedDB to simulate a server that provides datasets and stores the dashboard layout.
To switch requests to your server, edit the code in src/service/index.ts
.
Example code of intergration
src/service/index.ts
import { IDashboard, IDataset } from '@/interface';
import { IComputationFunction } from '@kanaries/graphic-walker';
const BASE_URL = 'http://localhost:3000';
export async function listDataset(
offset: number,
limit: number,
): Promise<IDataset[]> {
const resp = await fetch(
`${BASE_URL}/datasets?start=${offset}&limit=${limit}`,
);
if (resp.ok) {
const { data } = await resp.json();
return data;
}
throw new Error('Failed to fetch datasets');
}
export async function addDataset(
dataset: Omit<IDataset, 'id'>,
): Promise<IDataset> {
const resp = await fetch(`${BASE_URL}/datasets`, {
method: 'POST',
body: JSON.stringify(dataset),
headers: {
'Content-Type': 'application/json',
},
});
if (resp.ok) {
const { data } = await resp.json();
return data;
}
throw new Error('Failed to add dataset');
}
export async function updateDataset(dataset: IDataset): Promise<IDataset> {
const resp = await fetch(`${BASE_URL}/datasets/${dataset.id}`, {
method: 'PUT',
body: JSON.stringify(dataset),
headers: {
'Content-Type': 'application/json',
},
});
if (resp.ok) {
const { data } = await resp.json();
return data;
}
throw new Error('Failed to update dataset');
}
export async function deleteDataset(id: number): Promise<void> {
const resp = await fetch(`${BASE_URL}/datasets/${id}`, {
method: 'DELETE',
});
if (!resp.ok) {
throw new Error('Failed to delete dataset');
}
}
export async function getDataset(id: number): Promise<IDataset> {
const resp = await fetch(`${BASE_URL}/datasets/${id}`);
if (resp.ok) {
const { data } = await resp.json();
return data;
}
throw new Error('Failed to fetch dataset');
}
export function getDatasetQueryService(id: number): IComputationFunction {
return async (payload) => {
const resp = await fetch(`${BASE_URL}/datasets/${id}/query`, {
method: 'POST',
body: JSON.stringify(payload),
headers: {
'Content-Type': 'application/json',
},
});
if (resp.ok) {
const { data } = await resp.json();
return data;
}
throw new Error('Failed to fetch datasets');
};
}
export async function getDashboard(id: number): Promise<IDashboard> {
const resp = await fetch(`${BASE_URL}/dashboards/${id}`);
if (resp.ok) {
const { data } = await resp.json();
return data;
}
throw new Error('Failed to fetch dashboard');
}
export async function addDashboard(
dashboard: Omit<IDashboard, 'id'>,
): Promise<IDashboard> {
const resp = await fetch(`${BASE_URL}/dashboards`, {
method: 'POST',
body: JSON.stringify(dashboard),
headers: {
'Content-Type': 'application/json',
},
});
if (resp.ok) {
const { data } = await resp.json();
return data;
}
throw new Error('Failed to add dashboard');
}
export async function updateDashboard(dashboard: IDashboard) {
const resp = await fetch(`${BASE_URL}/dashboards/${dashboard.id}`, {
method: 'PUT',
body: JSON.stringify(dashboard),
headers: {
'Content-Type': 'application/json',
},
});
if (!resp.ok) {
throw new Error('Failed to update dashboard');
}
}
export async function listDashboard(
offset: number,
limit: number,
): Promise<IDashboard[]> {
const resp = await fetch(
`${BASE_URL}/dashboards?start=${offset}&limit=${limit}`,
);
if (resp.ok) {
const { data } = await resp.json();
return data;
}
throw new Error('Failed to fetch dashboards');
}
export async function deleteDashboard(id: number): Promise<void> {
const resp = await fetch(`${BASE_URL}/dashboards/${id}`, {
method: 'DELETE',
});
if (!resp.ok) {
throw new Error('Failed to delete dashboard');
}
}