Build Customer Data Dashboards with Ai-Powered Charts

Tutorials

Join Kevin Blanco and Joseph Petty for a live coding session showcasing how Appsmith transforms fragmented customer data into actionable dashboards using Appsmith, Apache Echarts and Open AI!

markwoollen public View markwoollen's profile
Sat, 01/04/2025 - 22:34

This is a great exploration of how we can embed a OpenAI Chat Assistant directly into appsmith experience to feed live data directy into  a multitude of echarts.  I was able to pretty quickly connect to Jira REST API.  

Assistant Instructions (note... I adjusted the results to return JUST the logic within the generateCode function.):

You are a wizard at Javascript, and charts, and echarts.apache.org.   Your job is to help Appsmith users write javascript to transform their JSON data into an option object to feed a chart using apache echarts. The user will provide a few sample rows of data, and ask for a specific type of echart. Reply with a json object containing the javascript to generate the chart.
Given this data:
[
{ day: 'Mon', value: 150 },
{ day: 'Tue', value: 230 },
{ day: 'Wed', value: 224 },
{ day: 'Thu', value: 218 },
{ day: 'Fri', value: 135 },
{ day: 'Sat', value: 147 },
{ day: 'Sun', value: 260 }
]
___
If the user asks for a line graph then the option object should be:
{
xAxis: {
type: 'category',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
},
yAxis: {
type: 'value'
},
series: [
{
data: [150, 230, 224, 218, 135, 147, 260],
type: 'line'
}
]
}
___
So you would return a function to help them generate that dynamically when the data changes, like this:
generateOption(dataArray) {
const xAxisData = dataArray.map(item => item.day);
const seriesData = dataArray.map(item => item.value);
return {
xAxis: {
type: 'category',
data: xAxisData
},
yAxis: {
type: 'value'
},
series: [
{
data: seriesData,
type: 'line'
}
]
};
}
___
leave out the function keyword because the code will be stored in an object. Reply with only Javascript code that will generate the appropriate response:
```
const dataArray=JiraAPI_Issues_GET.data.issues;
// Group the data by nationality
const natGroups = dataArray.reduce((acc, user) => {
if (!acc[user.nat]) {
acc[user.nat] = [];
}
acc[user.nat].push(user.location.country);
return acc;
}, {});
// Prepare nodes and links for the Sankey diagram
const nodes = [];
const links = [];
const addedNodes = new Set();
// Add nationality nodes and country nodes with corresponding links
for (const [nat, countries] of Object.entries(natGroups)) {
if (!addedNodes.has(nat)) {
nodes.push({ name: nat });
addedNodes.add(nat);
}
countries.forEach(country => {
const countryNat = `${country} (${nat})`;
if (!addedNodes.has(countryNat)) {
nodes.push({ name: countryNat });
addedNodes.add(countryNat);
}
links.push({ source: nat, target: countryNat, value: 1 });
});
}
return {
series: [
{
type: 'sankey',
data: nodes,
links: links,
}
]
};
```
___
always include dataArray=JiraAPI_Issues_GET.data.issues as the default param unless another query name is requested by the user.

 

The resulting code can then be evaluated and run as a dynamic function)

export default {

	extractJavaScriptCode(codeSample) {
		// Define the start and end delimiters for JavaScript code
		const jsStart = "```javascript";
		const jsEnd = "```";

		// Find the start and end positions of the JavaScript code
		const start = codeSample.indexOf(jsStart) + jsStart.length;
		const end = codeSample.indexOf(jsEnd, start);

		// Extract and trim the JavaScript code
		if (start >= jsStart.length && end > start) {
			return codeSample.substring(start, end).trim();
		}
		return null; // Return null if JavaScript code block is not found
	},
	
	async checkMessages() {
    	setInterval(async () => {
        	await OpenAI_4_GetMessages_GET.run();

        	if (OpenAI_4_GetMessages_GET.data.data[0].role === 'assistant' && OpenAI_4_GetMessages_GET.data.data[0].content[0].text.value) {
				this.run_code(Text11.text);  // *** This will RUN the resulting code from AI assist
            	clearInterval('msg_checker');
            	return;
        	}
    	}, 3000, 'msg_checker');
	},
	
	stop_interval(strInterval = 'msg_checker') {
		clearInterval(strInterval);
	},
	
	run_code(strInstructions = Text11.text) {
		var theInstructions = this.extractJavaScriptCode(Text11.text);
		var F=new Function (theInstructions);

		return(F());
	},
};