API Data to be displayed in Line Charts (react-chartjs-2) - javascript

I'm trying to figure out how to accurately use and display this API values in a line chart.
API Call with Line Chart:
import React, { Component } from 'react'
import { Line } from 'react-chartjs-2'
let headers = {
'QB-Realm-Hostname': 'XXXXXXXXXX.quickbase.com',
'User-Agent': 'FileService_Integration_V2.1',
'Authorization': 'QB-USER-TOKEN XXXX_XXX_XXXXXXX',
'Content-Type': 'application/json'
};
class TotalLineChart extends Component {
constructor(props) {
super(props);
this.state = {
data: null
};
}
componentDidMount() {
this.fetchData();
}
fetchData = () => {
let body = {"from":"bpz99ram7","select":[3,6,80,81,82,83,86,84,88,89,90,91,92,93,94,95,96,97,98,99,101,103,104,105,106,107,109,111,113,115,120,123,224,225,226,227,228,229,230,231,477,479,480,481],"where": "{40.CT. 'In Progress'}","sortBy":[{"fieldId":6,"order":"ASC"}],"groupBy":[{"fieldId":40,"grouping":"equal-values"}],"options":{"skip":0,"top":0,"compareWithAppLocalTime":false}}
fetch('https://api.quickbase.com/v1/records/query', {
method: 'POST',
headers: headers,
body: JSON.stringify(body)
}).then(response => response.json())
.then( data => this.setState({ data })
);
}
render() {
const data = {
labels: ['50', '100', '150', '200', '250', '300'],
datasets: [
{
label: 'TOTAL',
data: [
{x: this.state.data["6"].value, y: this.state.data["3"].value },
],
fill: false,
borderColor: '#00498D'
},
],
};
const options = {
scales: {
yAxes: [
{
ticks: {
beginAtZero: true,
},
},
],
},
};
return (
<div>
<Line data={data} options={options} />
</div>
)
}
}
export default TotalLineChart;
Example of API working rendering data:
import React, { Component } from 'react'
let headers = {
'QB-Realm-Hostname': 'XXXXXXXXXXXXXX.quickbase.com',
'User-Agent': 'FileService_Integration_V2.1',
'Authorization': 'QB-USER-TOKEN XXXXX_XXXX_XXXXXXXXXXXXXX',
'Content-Type': 'application/json'
};
class JobsTableApi extends Component {
constructor(props) {
super(props);
this.state = {
data: null,
};
}
componentDidMount() {
this.fetchData();
}
fetchData = () => {
let body = {"from":"bpz99ram7","select":[3,6,80,81,82,83,86,84,88,89,90,91,92,93,94,95,96,97,98,99,101,103,104,105,106,107,109,111,113,115,120,123,224,225,226,227,228,229,230,231,477,479,480,481],"where": "{40.CT. 'In Progress'}","sortBy":[{"fieldId":6,"order":"ASC"}],"groupBy":[{"fieldId":40,"grouping":"equal-values"}],"options":{"skip":0,"top":0,"compareWithAppLocalTime":false}}
fetch('https://api.quickbase.com/v1/records/query', {
method: 'POST',
headers: headers,
body: JSON.stringify(body)
}).then(response => response.json())
.then( data => this.setState({ data })
);
}
render() {
const { data } = this.state;
if (data === null) return 'Loading Job Data... ';
return (
<div>
{Object.keys(data["data"]).map(item => (
<div key = {item}>
{data["data"][item][6].value}
</div>
))}
</div>
)
}
}
export default JobsTableApi;
My Idea is that I have multiple line charts and all the data from the API, I'm attempting to display this data on line charts and have them change when the Title changes automatically so it just Cycles through the whole job show the Title and job info.
Any Ideas on what I'm doing wrong?
Struggling on this, I don't know how to get each ID in the API body to be able to be used in the line chart...
API Response Sample:
{
"data": [
{
"3": {
"value": 177
},
"6": {
"value": "2220 Three Kings "
},
"40": {
"value": "In Progress"
},
"80": {
"value": 41406.07
},
"81": {
"value": 42076.44499999999
},
"82": {
"value": 1384.888156072408
},
UPDATE
This is what I'm trying to figure out how to do... but obviously doesn't work and can't figure out the assigning the ids to fields to actually display in the line chart.
import React, { useState, useEffect } from "react";
import { Line } from "react-chartjs-2";
const TotalLineChart = () => {
const [chartData, setChartData] = useState({});
// const [designHours, setdesignHours] = useState([]);
// const [designAmount, setdesignAmount] = useState([]);
// const [subRoughHours, setSubRoughHours] = useState([]);
// const [subRoughAmount, setSubRoughAmount] = useState([]);
// const [roughHours, setRoughHours] = useState([]);
// const [roughAmount, setRoughAmount] = useState([]);
// const [finishHours, setFinishHours] = useState([]);
// const [finishAmount, setFinishAmount] = useState([]);
// const [closeHours, setCloseHours] = useState([]);
// const [closeAmount, setCloseAmount] = useState([]);
// const [actualHours, setActualHours] = useState([]);
// const [actualAmount, setActualAmount] = useState([]);
const chart = () => {
let designHours = [];
let designAmount = [];
let subRoughHours = [];
let subRoughAmount = [];
let roughHours = [];
let roughAmount = [];
let finishHours = [];
let finishAmount = [];
let closeHours = [];
let closeAmount = [];
let actualHours = [];
let actualAmount = [];
let headers = {
'QB-Realm-Hostname': 'XXXXXXXXXX.quickbase.com',
'User-Agent': 'FileService_Integration_V2.1',
'Authorization': 'QB-USER-TOKEN XXX_XXXX_XXXXXXXXXXX',
'Content-Type': 'application/json'
};
let body = {"from":"bpz99ram7","select":[3,6,80,81,82,83,86,84,88,89,90,91,92,93,94,95,96,97,98,99,101,103,104,105,106,107,109,111,113,115,120,123,224,225,226,227,228,229,230,231,477,479,480,481],"where": "{40.CT. 'In Progress'}","sortBy":[{"fieldId":6,"order":"ASC"}],"groupBy":[{"fieldId":40,"grouping":"equal-values"}],"options":{"skip":0,"top":0,"compareWithAppLocalTime":false}}
fetch('https://api.quickbase.com/v1/records/query', {
method: 'POST',
headers: headers,
body: JSON.stringify(body)
}).then(response => response.json())
.then(res => {
console.log(res);
for (const dataObj of res.data.data) {
designHours.push(parseInt(dataObj.value, 88));
designAmount.push(parseInt(dataObj.value, 91));
subRoughHours.push(parseInt(dataObj.value, 92));
subRoughAmount.push(parseInt(dataObj.value, 95));
roughHours.push(parseInt(dataObj.value, 96));
roughAmount.push(parseInt(dataObj.value, 98));
finishHours.push(parseInt(dataObj.value, 104));
finishAmount.push(parseInt(dataObj.value, 107));
closeHours.push(parseInt(dataObj.value, 477));
closeAmount.push(parseInt(dataObj.value, 480));
actualHours.push(parseInt(dataObj.value, 479));
actualAmount.push(parseInt(dataObj.value, 224));
}
setChartData({
type: 'scatter',
data: {
datasets: [
{
data: [
{x: designHours, y: designAmount },
{x: subRoughHours, y: subRoughAmount },
{x: roughHours, y: roughAmount },
{x: finishHours, y: finishAmount },
{x: closeHours, y: closeAmount }
],
backgroundColor: ["rgba(75, 192, 192, 0.6)"],
borderWidth: 4
}
]
}
});
})
.catch(err => {
console.log(err);
});
console.log(designHours, designAmount, subRoughHours, subRoughAmount, finishHours, finishAmount, closeHours, closeAmount, actualHours, actualAmount);
};
useEffect(() => {
chart();
}, []);
return (
<div className="App">
<div>
<Line
data={chartData}
options={{
responsive: true,
title: { text: "", display: true },
scales: {
yAxes: [
{
ticks: {
autoSkip: true,
maxTicksLimit: 10,
beginAtZero: true
},
gridLines: {
display: true
}
}
],
xAxes: [
{
gridLines: {
display: true
}
}
]
}
}}
/>
</div>
</div>
);
};
export default TotalLineChart;
That way I can select each field I need and display it in the line chart...
Any suggestions or ideas?

Related

project become whole blank during import graph. Linegraph problem in Reactjs

//* This is Linegraph.js file /
import React, { useEffect, useState } from 'react'
import { Line } from 'react-chartjs-2'
import numeral from 'numeral'
const options = {
legend: {
display: false,
},
elements: {
point: {
radius: 0,
},
},
maintainAspectRatio: false,
tooltips: {
mode: "index",
intersect: false,
callbacks: {
label: function (tooltipItem, data) {
return numeral(tooltipItem.value).format("+0,0");
},
},
},
scales: {
xAxes: [
{
type: "time",
time: {
format: "MM/DD/YY",
tooltipFormat: "ll",
},
},
],
yAxes: [
{
gridLines: {
display: false,
},
ticks: {
callback: function (value, index, values) {
return numeral(value).format("0a");
},
},
},
],
},
};
const LineGraph = ({ casesType="cases" }) => {
const [data, setData] = useState({})
const buildChartData = (data, caseType) => {
const chartData = []
let lastPoint;
for(let date in data.cases){
if(lastPoint) {
const newPoint = {
x: date,
y: data[caseType][date] - lastPoint
}
chartData.push(newPoint)
}
lastPoint = data[caseType][date]
}
return chartData
}
useEffect(() => {
const fetchData = async () => {
fetch('https://disease.sh/v3/covid-19/historical/all?lastdays=120')
.then(response => response.json())
.then(data => {
console.log(data)
const chartData = buildChartData(data, casesType)
setData(chartData)
})
}
fetchData()
}, [casesType])
return (
<div>
{data?.length > 0 && (
<Line
options={options}
data={{
datasets: [{
backgroundColor: "rgba(204, 16, 52, 0.5)",
borderColor: "#CC1034",
data: data
}]
}}
/>
)}
</div>
)
}
export default LineGraph

React Chart.js Match API data to what Title is displaying, then update chart on data/Title change

I have an Title.js that is pulling a title from an API call, from there I am sending it over to TitleCycle.js to Cycle through each job coming from the API call, in this file, I also have the record ID data[index]['3'].value which I have displaying under the Job Title for reference (see image) this number relates all records to the job name and also cycles. I've updated my code to show that now I'm looping through whatever api data is in the API call, from here I don't know how to call {jobId} from TitleCycle.js in the body of my api call to only get what records are matching the record id when that title changes. Then updates on change with the Title.
Right now, I'm able to put a number in and get the line chart to update accurately with that data. However, instead of having a number I want to pull that from the TitleCycle.js to display whatever Title's Record ID is currently displaying, so it cycles with it.
Line Chart.js
import React, { useState, useEffect } from "react";
import { Scatter } from "react-chartjs-2";
import jobId from '../TitleCycle';
// import Title from '../header/Title';
const TotalLineChart = () => {
const [chartData, setChartData] = useState({});
const chart = () => {
let designHours = [];
let designAmount = [];
let subRoughHours = [];
let subRoughAmount = [];
let roughHours = [];
let roughAmount = [];
let finishHours = [];
let finishAmount = [];
let closeHours = [];
let closeAmount = [];
let actualHours = [];
let actualAmount = [];
let headers = {
"QB-Realm-Hostname": "XXXXXXXXXX.quickbase.com",
"User-Agent": "FileService_Integration_V2.1",
"Authorization": "QB-USER-TOKEN XXXXXXXXXXXXXX",
"Content-Type": "application/json"
};
let body = {
from: "bpz99ram7",
select: [
3,
6,
80,
81,
82,
83,
86,
84,
88,
89,
90,
91,
92,
93,
94,
95,
96,
97,
98,
99,
101,
103,
104,
105,
106,
107,
109,
111,
113,
115,
120,
123,
224,
225,
226,
227,
228,
229,
230,
231,
477,
479,
480,
481
],
where: "{3.EX. '290'}", // this is where i'm attempting to place {jobId}, right now it is set to 290 manually, thats where the data is coming from in the images below. ONLY EFFECTING TOP LINE CHART!
sortBy: [{ fieldId: 6, order: "ASC" }],
groupBy: [{ fieldId: 40, grouping: "equal-values" }],
options: { skip: 0, compareWithAppLocalTime: false }
};
fetch("https://api.quickbase.com/v1/records/query", {
method: "POST",
headers: headers,
body: JSON.stringify(body)
})
.then((response) => response.json())
.then((res) => {
console.log(res);
console.log({jobId})
Object.keys(res.data).map(jobId => {
const designHours = parseInt(res.data[jobId]['88'].value, 10);
const designAmount = parseInt(res.data[jobId]['91'].value, 10);
const subRoughHours = parseInt(res.data[jobId]['92'].value, 10);
const subRoughAmount = parseInt(res.data[jobId]['95'].value, 10);
const roughHours = parseInt(res.data[jobId]['96'].value, 10);
const roughAmount = parseInt(res.data[jobId]['98'].value, 10);
const finishHours = parseInt(res.data[jobId]['104'].value, 10);
const finishAmount = parseInt(res.data[jobId]['107'].value, 10);
const closeHours = parseInt(res.data[jobId]['477'].value, 10);
const closeAmount = parseInt(res.data[jobId]['480'].value, 10);
const actualHours = parseInt(res.data[jobId]['479'].value, 10);
const actualAmount = parseInt(res.data[jobId]['224'].value, 10);
setChartData({
type: 'scatter',
datasets: [
{
label: 'TOTAL',
data: [
{ x: designHours, y: designAmount },
{ x: subRoughHours, y: subRoughAmount },
{ x: roughHours, y: roughAmount },
{ x: finishHours, y: finishAmount },
{ x: closeHours, y: closeAmount }
],
borderWidth: 2,
borderColor: '#4183c4',
backgroundColor: '#4183c4',
tension: 0.8,
spanGaps: true,
lineTension: 0.5,
showLine: true,
fill: false,
showTooltip: false,
pointBorderWidth: 1
},
{
label: 'ACTUALS',
data: [{ x: actualHours, y: actualAmount }],
fill: false,
borderColor: '#e34747',
backgroundColor: '#e34747',
borderWidth: 5,
showTooltip: false
}
],
options: {
showAllTooltips: true,
enabled: true,
maintainAspectRatio: false,
legend: {
display: true
}
}
});
})
})
.catch((err) => {
console.log(err);
});
console.log(
designHours,
designAmount,
subRoughHours,
subRoughAmount,
roughHours,
roughAmount,
finishHours,
finishAmount,
closeHours,
closeAmount,
actualHours,
actualAmount
);
};
useEffect(() => {
chart();
}, []);
return (
<div className="App">
<div>
<Scatter
data={chartData}
options={{
responsive: true,
title: { text: "Total Project", display: true },
scales: {
yAxes: [
{
scaleLabel: {
display: true,
labelString: 'Dollar Amounts'
},
ticks: {
autoSkip: true,
maxTicksLimit: 10,
beginAtZero: true
},
gridLines: {
display: true
}
}
],
xAxes: [
{
scaleLabel: {
display: true,
labelString: 'Hours'
},
gridLines: {
display: true
}
}
],
},
}}
/>
</div>
</div>
);
};
export default TotalLineChart;
Note the comment above to show where I'm trying to place {jobId} from TitleCycle.js ONLY EFFECTING TOP LINE CHART
*Attempted to change API body to: where: "{3.EX. '{jobId}'}",
TitleCycle.js
import React from "react";
function TitleCycle({ data }) {
const [index, setIndex] = React.useState(0);
const jobId = data[index]['3'].value;
// Set Timer and Interval based on Index
React.useEffect(() => {
const timerId = setInterval(
() => setIndex((i) => (i + 1) % data.length),
5000 // 5 seconds.
);
return () => clearInterval(timerId);
}, [data]);
console.log(data[index]['3'].value)
return data.length ? (
<div className="TitleCycle">
<h3>{data[index]["6"].value}</h3>
{jobId}
</div>
) : null;
}
export default TitleCycle;
Title.js
import { Component, React } from "react";
import TitleCycle from '../TitleCycle';
//import TotalLineChart from '../charts/TotalLineChart'
let headers = {
"QB-Realm-Hostname": "XXXXXXXX.quickbase.com",
"User-Agent": "FileService_Integration_V2.1",
"Authorization": "QB-USER-TOKEN XXXXXXXXXXXXXX",
"Content-Type": "application/json"
};
class Title extends Component {
state = {
data: null,
};
componentDidMount() {
this.fetchData();
}
fetchData = () => {
let body = {"from":"bpz99ram7","select":[3,6,40],"where": "{40.CT. 'In Progress'}","sortBy":[{"fieldId":6,"order":"ASC"}],"groupBy":[{"fieldId":40,"grouping":"equal-values"}],"options":{"skip":0,"top":0,"compareWithAppLocalTime":false}};
fetch("https://api.quickbase.com/v1/records/query", {
method: "POST",
headers: headers,
body: JSON.stringify(body)
})
.then((response) => response.json())
.then(({data}) => this.setState({ data }));
};
render() {
const { data } = this.state;
if (data === null) return "Loading...";
return (
<div className="Title">
<TitleCycle data={data} />
</div>
);
}
}
export default Title;
Note this is only sending the Job Name over to TitleCycle.js as {data}
Above you can see a job name, with the record ID below, which Cycles with the job on a set duration
Above you can see how it changed and updated the record ID, So now I just want that field of {jobId} to be able to be set in my LineChart.js file so that the data being pulled is whatever data is displaying
ONLY THE TOP LINE CHART IS BEING EFFECTED RIGHT NOW, this is where I'm attempting this first before changing the others to match.
Hope this helps!
App.js
import './App.css'
// import Title from './components/header/Title'
import TotalLineChart from './components/charts/TotalLineChart'
import RadiantLineChart from './components/charts/RadiantLineChart'
import PlumbingLineChart from './components/charts/PlumbingLineChart'
import SnowmeltLineChart from './components/charts/SnowmeltLineChart'
import HVACLineChart from './components/charts/HVACLineChart'
import GasPipeLineChart from './components/charts/GasPipeLineChart'
import FixturesLineChart from './components/charts/FixturesLineChart'
// import JobsTableApi from './components/JobsTableApi'
import ClassBudgetsTableApi from './components/ClassBudgetsTableApi'
// import TitleCycle from './components/TitleCycle'
import Title from './components/header/Title'
// import Logo from './components/Logo';
// import CurrentTitleInfo from './components/CurrentTitleInfo'
function App() {
return (
<div>
{/* <div className="flexbox-container">
<div className="Logo">
{/* </div> */}
{/* <Logo /> */}
<div className="App">
<Title />
</div>
{/* </div> */}
<div className="TopChart">
<TotalLineChart />
</div>
<div className="FirstRowContainer">
<RadiantLineChart />
<PlumbingLineChart />
<FixturesLineChart />
</div>
<div className="SecondRowContainer">
<SnowmeltLineChart />
<HVACLineChart />
<GasPipeLineChart />
</div>
{/* <JobsTableApi /> */}
<ClassBudgetsTableApi />
</div>
);
}
export default App;
Update
App.js
import React, { useEffect, useState } from "react";
import './App.css'
import Title from './components/header/Title'
import TotalLineChart from './components/charts/TotalLineChart'
import RadiantLineChart from './components/charts/RadiantLineChart'
import PlumbingLineChart from './components/charts/PlumbingLineChart'
import SnowmeltLineChart from './components/charts/SnowmeltLineChart'
import HVACLineChart from './components/charts/HVACLineChart'
import GasPipeLineChart from './components/charts/GasPipeLineChart'
import FixturesLineChart from './components/charts/FixturesLineChart'
// import TitleCycle from './components/TitleCycle'
// import Logo from './components/Logo';
let headers = {
"QB-Realm-Hostname": "XXXXXXXX.quickbase.com",
"User-Agent": "FileService_Integration_V2.1",
"Authorization": "QB-USER-TOKEN XXXXXXXXX",
"Content-Type": "application/json"
};
function App() {
const [index, setIndex] = useState(0);
const [allData, setAllData] = useState([]);
// Fetch all data, all jobs
useEffect(() => {
function fetchData() {
let body = {
from: "bpz99ram7",
select: [3, 6, 40],
where: "{40.CT. 'In Progress'}",
sortBy: [{ fieldId: 6, order: "ASC" }],
groupBy: [{ fieldId: 40, grouping: "equal-values" }],
options: { skip: 0, top: 0, compareWithAppLocalTime: false },
};
fetch("https://api.quickbase.com/v1/records/query", {
method: "POST",
headers: headers,
body: JSON.stringify(body),
})
.then((response) => response.json())
.then(({ data }) => setAllData(data));
}
fetchData();
}, []);
// Cycle through the jobIds and indexes
useEffect(() => {
const timerId = setInterval(
() => setIndex((i) => (i + 1) % allData.length),
5000 // 5 seconds.
);
return () => clearInterval(timerId);
}, [allData]);
// Calculate info based on index
const jobId = allData[index]["3"].value;
const title = allData[index]["6"].value;
return (
<div>
{/* <div className="flexbox-container">
<div className="Logo">
{/* <Logo /> */}
{/* </div> */}
<div className="App">
<Title title = {title}/>
</div>
<div className="TopChart">
<TotalLineChart jobId = {jobId}/>
</div>
<div className="FirstRowContainer">
<RadiantLineChart jobId = {jobId}/>
<PlumbingLineChart jobId = {jobId}/>
<FixturesLineChart jobId = {jobId}/>
</div>
<div className="SecondRowContainer">
<SnowmeltLineChart jobId = {jobId}/>
<HVACLineChart jobId = {jobId}/>
<GasPipeLineChart jobId = {jobId}/>
</div>
</div>
);
}
export default App;
TypeError: Cannot read property '3' of undefined
{
"data": [
{
"3": {
"value": 316
},
"6": {
"value": "1545 Indian Hills"
},
"40": {
"value": "In Progress"
}
},
{
"3": {
"value": 291
},
"6": {
"value": "1547 Tomahawk"
},
"40": {
"value": "In Progress"
}
},
It seems like you need to sync the jobId state between the TitleCycle component and the LineChart component, so that both has access to this variable, and can render stuff in sync (Title changes and LineChart changes also).
In that case, you need jobId as a somewhat global variable. I think of this solution.
This seems to be the current hierachy
App
|-- LineChart
|-- Title
|-- TitleCycle
Therefore, put the jobId in the common ancestor and prop drills it down. In this case, instead of generating jobId and index from TitleCycle and having to lift the state back up and around into LineChart, you shall cycle the indexes right inside App.js. Something like this:
// App.js
function App() {
const [allData, setAllData] = useState([]);
const [index, setIndex] = useState(0);
// Fetch all data, all jobs
useEffect(() => {
function fetchData() {
let body = {
from: "bpz99ram7",
select: [3, 6, 40],
where: "{40.CT. 'In Progress'}",
sortBy: [{ fieldId: 6, order: "ASC" }],
groupBy: [{ fieldId: 40, grouping: "equal-values" }],
options: { skip: 0, top: 0, compareWithAppLocalTime: false },
};
fetch("https://api.quickbase.com/v1/records/query", {
method: "POST",
headers: headers,
body: JSON.stringify(body),
})
.then((response) => response.json())
.then(({ data }) => setAllData(data));
}
fetchData();
}, []);
// Cycle through the jobIds and indexes
useEffect(() => {
const timerId = setInterval(
() => setIndex((i) => (i + 1) % allData.length),
5000 // 5 seconds.
);
return () => clearInterval(timerId);
}, [allData]);
// Calculate info based on index
const jobId = allData[index]?.["3"]?.value || "290"; // Default "290"
const title = allData[index]?.["6"]?.value || "Default title";
// Renders the components with the necessary data
return (
<div>
<Title title={title} />
<LineChart1 jobId={jobId} />
<LineChart2 jobId={jobId} />
</div>
);
}
// LineChart.js
function TotalLineChart(props) {
// Got the jobId from props
const { jobId } = props;
// Now make the request with this jobId
}

Can't change the time of the xAxes in the Chart.js

So I have ChartData Component. I am taking the data from an API, the data is being displayed through Chart. I have determine Format Logic, which it's the main thing is to determine the time of the data, I have 3 buttons, the thing that I am struggling to achieve is when let's say I wanna see the data of 7days when I press the button. I can see data is changing in the yAxes but I can't see time being changed on thexAxes, it's still set to hours, it should display the days.
ChartData
import React, { useRef, useEffect, useState } from "react";
import 'chartjs-adapter-moment';
import annotationPlugin from 'chartjs-plugin-annotation';
import { Chart, registerables } from 'chart.js';
Chart.register(...registerables);
Chart.register(annotationPlugin);
const determineTimeFormat = (
timeFormat: string,
day: any,
week: any,
year: any
) => {
switch (timeFormat) {
case "24h":
return day;
case "7d":
return week;
case "1y":
return year;
default:
return day;
}
};
interface Props {
data: any
}
const ChartData: React.FC<Props> = ({ data }) => {
const chartCanvasRef = useRef<HTMLCanvasElement | null>(null);
const { day, week, year, detail } = data;
const [timeFormat, setTimeFormat] = useState("24h");
const [isRebuildingCanvas, setIsRebuildingCanvas] = useState(false);
useEffect(() => {
setIsRebuildingCanvas(true);
}, [timeFormat]);
useEffect(() => {
if (isRebuildingCanvas) {
setIsRebuildingCanvas(false);
}
}, [isRebuildingCanvas]);
useEffect(() => {
if (chartCanvasRef && chartCanvasRef.current && detail) {
const chartCanvas = chartCanvasRef.current
if (isRebuildingCanvas || !chartCanvas) {
return;
}
const chartInstance = new Chart(chartCanvasRef.current, {
type: "line",
data: {
datasets: [
{
label: `${detail.name} price`,
data: determineTimeFormat(timeFormat, day, week, year),
backgroundColor: "rgba(134,159,152, 1)",
borderColor: "rgba(174, 305, 194, 0.4",
},
],
},
Options
options: {
plugins: {
annotation: {
annotations: {
}
}
},
animations: {
tension: {
duration: 1000,
easing: 'linear',
from: 1,
to: 0,
loop: true
}
},
maintainAspectRatio: false,
responsive: true,
scales: {
x:
{
type: 'time',
},
},
}
});
return () => {
chartInstance.destroy();
}
}}, [day, isRebuildingCanvas,timeFormat, week, year, detail]);
Rest of the Component
return (
<div className='chart__container'>
{renderPrice()}
{isRebuildingCanvas ? undefined : (
<canvas ref={chartCanvasRef} width={250} height={250} id='myChart'></canvas>
)}
<button className='time__format' onClick={() => setTimeFormat("24h")}>24h</button>
<button className='time__format' onClick={() => setTimeFormat("7d")}>7d</button>
<button className='time__format' onClick={() => setTimeFormat("1y")}>1y</button>
</div>
);
};
export default ChartData;
I have created a similar working example without reactjs. This can be useful for you to understand. You can refer the fiddle as well. A limitation that am currently facing is if there is data more than 100 then am getting errors while updating the data, performed slicing of data upto 100 to make it working.
var coinData = {};
var fetchData = async() => {
api = "https://api.coingecko.com/api/v3";
id = "bitcoin";
var [day1, week1, year1, detail1] = await Promise.all([
fetch(api + `/coins/${id}/market_chart/?vs_currency=usd&days=1`).then(data => {
return data.json()
}),
fetch(api + `/coins/${id}/market_chart/?vs_currency=usd&days=7`).then(data => {
return data.json()
}),
fetch(api + `/coins/${id}/market_chart/?vs_currency=usd&days=365`).then(data => {
return data.json()
}),
fetch(api + `/coins/markets/?vs_currency=usd&ids=${id}`).then(data => {
return data.json()
})
]);
coinData = {
day: formatData(day1.prices).slice(0, 100),
week: formatData(week1.prices).slice(0, 100),
year: formatData(year1.prices).slice(0, 100),
detail: detail1[0]
}
}
const formatData = (data) => {
return data.map((el) => {
return {
t: el[0],
y: el[1].toFixed(2)
};
});
};
const determineTimeFormat = (timeFormat) => {
switch (timeFormat) {
case "24h":
return coinData.day;
case "7d":
return coinData.week;
case "1y":
return coinData.year;
default:
return coinData.day;
}
};
var chartInstance;
fetchData().then(() => {
/* console.log(coinData); */
var ctx = document.getElementById('chartJSContainer');
chartInstance = new Chart(ctx, {
type: "line",
labels: false,
data: {
datasets: [{
label: `${coinData.detail.name} price`,
data: determineTimeFormat('1d'),
parsing: {
yAxisKey: 'y',
xAxisKey: 't',
},
backgroundColor: "rgba(134,159,152, 1)",
borderColor: "rgba(174, 305, 194, 0.4)"
}],
},
options: {
scales: {
x: {
ticks: {
source: "data"
},
type: 'time',
time: {
unit: "day"
}
}
},
}
});
});
function setTimeFormat(format) {
Chart.instances[0].data.datasets[0].data = determineTimeFormat(format);
Chart.instances[0].update();
}
<script src="https://cdn.jsdelivr.net/npm/chart.js#3.3.1/dist/chart.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-moment#1.0.0/dist/chartjs-adapter-moment.min.js"></script>
<body>
<button className='time__format' onclick="setTimeFormat( '24h')">24h</button>
<button className='time__format' onclick="setTimeFormat( '7d')">7d</button>
<button className='time__format' onclick="setTimeFormat( '1y')">1y</button><br><br>
<canvas id="chartJSContainer" width="600" height="400"></canvas>
</body>

Display API data in line charts dynamically

I was having trouble getting parseInt(res.data[0]['97'].value to render accurate data from my API call. [0] being the index, and ['97'] being the ID from my API Response. I've updated my code to accept props of {jobId} from my App.js sending the ID to LineChart.js. This allows me to access this ID when it is in a Cycle along with the Title, so that I can say "whatever Title is displaying, get the ID and in LineCharts, match that ID to the data needed for the Line chart."
Old LineChart.js
import React, { useState, useEffect } from "react";
import { Scatter } from "react-chartjs-2";
const TotalLineChart = () => {
const [chartData, setChartData] = useState({});
// const [designHours, setDesignHours] = useState([]);
// const [designAmount, setDesignAmount] = useState([]);
// const [subRoughHours, setSubRoughHours] = useState([]);
// const [subRoughAmount, setSubRoughAmount] = useState([]);
// const [roughHours, setRoughHours] = useState([]);
// const [roughAmount, setRoughAmount] = useState([]);
// const [finishHours, setFinishHours] = useState([]);
// const [finishAmount, setFinishAmount] = useState([]);
// const [closeHours, setCloseHours] = useState([]);
// const [closeAmount, setCloseAmount] = useState([]);
// const [actualHours, setActualHours] = useState([]);
// const [actualAmount, setActualAmount] = useState([]);
const chart = () => {
let designHours = [];
let designAmount = [];
let subRoughHours = [];
let subRoughAmount = [];
let roughHours = [];
let roughAmount = [];
let finishHours = [];
let finishAmount = [];
let closeHours = [];
let closeAmount = [];
let actualHours = [];
let actualAmount = [];
let headers = {
'QB-Realm-Hostname': 'XXXXXXXXXX.quickbase.com',
'User-Agent': 'FileService_Integration_V2.1',
'Authorization': 'QB-USER-TOKEN XXXX_XXX_XXXXXXXXXX',
'Content-Type': 'application/json'
};
let body = {"from":"bpz99ram7","select":[3,6,80,81,82,83,86,84,88,89,90,91,92,93,94,95,96,97,98,99,101,103,104,105,106,107,109,111,113,115,120,123,224,225,226,227,228,229,230,231,477,479,480,481],"where": "{40.CT. 'In Progress'}","sortBy":[{"fieldId":6,"order":"ASC"}],"groupBy":[{"fieldId":40,"grouping":"equal-values"}],"options":{"skip":0,"top":0,"compareWithAppLocalTime":false}}
fetch('https://api.quickbase.com/v1/records/query', {
method: 'POST',
headers: headers,
body: JSON.stringify(body)
}).then(response => response.json())
.then(res => {
console.log(res);
const designHours = parseInt(res.data[0]['89'].value, 10);
const designAmount = parseInt(res.data[0]['91'].value, 10);
const subRoughHours = parseInt(res.data[0]['93'].value, 10);
const subRoughAmount = parseInt(res.data[0]['95'].value, 10);
const roughHours = parseInt(res.data[0]['97'].value, 10);
const roughAmount = parseInt(res.data[0]['99'].value, 10);
const finishHours = parseInt(res.data[0]['105'].value, 10);
const finishAmount = parseInt(res.data[0]['107'].value, 10);
const closeHours = parseInt(res.data[0]['477'].value, 10);
const closeAmount = parseInt(res.data[0]['480'].value, 10);
const actualHours = parseInt(res.data[0]['479'].value, 10);
const actualAmount = parseInt(res.data[0]['224'].value, 10);
}
setChartData({
type: 'scatter',
data: {
datasets: [
{
data: [
{x: designHours, y: designAmount },
{x: subRoughHours, y: subRoughAmount },
{x: roughHours, y: roughAmount },
{x: finishHours, y: finishAmount },
{x: closeHours, y: closeAmount }
],
backgroundColor: ["rgba(75, 192, 192, 0.6)"],
borderWidth: 4
}
]
}
});
})
.catch(err => {
console.log(err);
});
console.log(designHours, designAmount, subRoughHours, subRoughAmount, finishHours, finishAmount, closeHours, closeAmount, actualHours, actualAmount);
};
useEffect(() => {
chart();
}, []);
return (
<div className="App">
<div>
<Scatter
data={chartData}
options={{
responsive: true,
title: { text: "", display: true },
scales: {
yAxes: [
{
ticks: {
autoSkip: true,
maxTicksLimit: 20,
beginAtZero: true
},
gridLines: {
display: true
}
}
],
xAxes: [
{
gridLines: {
display: true
}
}
]
}
}}
/>
</div>
</div>
);
};
export default TotalLineChart;
Fixed/Updated LineChart.js
import React, { useState, useEffect } from "react";
import { Scatter } from "react-chartjs-2";
// import jobId from '../TitleCycle';
// import Title from '../header/Title';
const TotalLineChart = (props) => {
const {jobId} = props;
console.log(jobId)
const [chartData, setChartData] = useState({});
const chart = () => {
let designHours = [];
let designAmount = [];
let subRoughHours = [];
let subRoughAmount = [];
let roughHours = [];
let roughAmount = [];
let finishHours = [];
let finishAmount = [];
let closeHours = [];
let closeAmount = [];
let actualHours = [];
let actualAmount = [];
let headers = {
"QB-Realm-Hostname": "XXXXXXXXX.quickbase.com",
"User-Agent": "FileService_Integration_V2.1",
"Authorization": "QB-USER-TOKEN XXXXXXXXXXXX",
"Content-Type": "application/json"
};
const body = {
from: "bpz99ram7",
select: [
3,
6,
80,
81,
82,
83,
86,
84,
88,
89,
90,
91,
92,
93,
94,
95,
96,
97,
98,
99,
101,
103,
104,
105,
106,
107,
109,
111,
113,
115,
120,
123,
224,
225,
226,
227,
228,
229,
230,
231,
477,
479,
480,
481
],
where: `{3.EX. ${jobId}}`,
sortBy: [{ fieldId: 6, order: "ASC" }],
groupBy: [{ fieldId: 40, grouping: "equal-values" }],
options: { skip: 0, compareWithAppLocalTime: false }
};
fetch("https://api.quickbase.com/v1/records/query", {
method: "POST",
headers: headers,
body: JSON.stringify(body)
})
.then((response) => response.json())
.then((res) => {
// console.log(res);
Object.keys(res.data).map(jobId => {
const designHours = parseInt(res.data[jobId]['88'].value, 10);
const designAmount = parseInt(res.data[jobId]['91'].value, 10);
const subRoughHours = parseInt(res.data[jobId]['92'].value, 10);
const subRoughAmount = parseInt(res.data[jobId]['95'].value, 10);
const roughHours = parseInt(res.data[jobId]['96'].value, 10);
const roughAmount = parseInt(res.data[jobId]['98'].value, 10);
const finishHours = parseInt(res.data[jobId]['104'].value, 10);
const finishAmount = parseInt(res.data[jobId]['107'].value, 10);
const closeHours = parseInt(res.data[jobId]['477'].value, 10);
const closeAmount = parseInt(res.data[jobId]['480'].value, 10);
const actualHours = parseInt(res.data[jobId]['479'].value, 10);
const actualAmount = parseInt(res.data[jobId]['224'].value, 10);
setChartData({
type: 'scatter',
datasets: [
{
label: 'TOTAL',
data: [
{ x: designHours, y: designAmount },
{ x: subRoughHours, y: subRoughAmount },
{ x: roughHours, y: roughAmount },
{ x: finishHours, y: finishAmount },
{ x: closeHours, y: closeAmount }
],
borderWidth: 2,
borderColor: '#4183c4',
backgroundColor: '#4183c4',
tension: 0.8,
spanGaps: true,
lineTension: 0.5,
showLine: true,
fill: false,
showTooltip: false,
pointBorderWidth: 1
},
{
label: 'ACTUALS',
data: [{ x: actualHours, y: actualAmount }],
fill: false,
borderColor: '#e34747',
backgroundColor: '#e34747',
borderWidth: 3,
showTooltip: false
}
],
options: {
showAllTooltips: true,
enabled: true,
maintainAspectRatio: false,
legend: {
display: true
}
}
})
setChartData.addData(chart, label, data); {
chart.data.labels.push(label);
chart.data.datasets.forEach((dataset) => {
dataset.data.push(data);
});
chart.update();
}
setChartData.removeData(chart); {
chart.data.labels.pop();
chart.data.datasets.forEach((dataset) => {
dataset.data.pop();
});
chart.update();
}
})
})
.catch((err) => {
console.log(err);
});
console.log(
designHours,
designAmount,
subRoughHours,
subRoughAmount,
roughHours,
roughAmount,
finishHours,
finishAmount,
closeHours,
closeAmount,
actualHours,
actualAmount
);
};
useEffect(() => {
chart();
}, []);
return (
<div className="App">
<div>
<Scatter
data={chartData}
options={{
responsive: true,
title: { text: "Total Project", display: true },
scales: {
yAxes: [
{
scaleLabel: {
display: true,
labelString: 'Amount'
},
ticks: {
autoSkip: true,
maxTicksLimit: 10,
beginAtZero: true
},
gridLines: {
display: true
}
}
],
xAxes: [
{
scaleLabel: {
display: true,
labelString: 'Hours'
},
gridLines: {
display: true
}
}
],
},
}}
/>
</div>
</div>
);
};
export default TotalLineChart;
NOTE how I've added ${jobId} to the API Body, as well as replacing the manually inputted Index in the parseInt()
App.js
import React, { useEffect, useState } from "react";
import './App.css'
import Title from './components/header/Title'
import TotalLineChart from './components/charts/TotalLineChart'
import RadiantLineChart from './components/charts/RadiantLineChart'
import PlumbingLineChart from './components/charts/PlumbingLineChart'
import SnowmeltLineChart from './components/charts/SnowmeltLineChart'
import HVACLineChart from './components/charts/HVACLineChart'
import GasPipeLineChart from './components/charts/GasPipeLineChart'
import FixturesLineChart from './components/charts/FixturesLineChart'
// import TitleCycle from './components/TitleCycle'
// import Logo from './components/Logo';
let headers = {
"QB-Realm-Hostname": "XXXXXXXX.quickbase.com",
"User-Agent": "FileService_Integration_V2.1",
"Authorization": "QB-USER-TOKEN XXXXXXXX",
"Content-Type": "application/json"
};
function App() {
const [allData, setAllData] = useState([]);
const [index, setIndex] = useState(0);
// Fetch all data, all jobs
useEffect(() => {
function fetchData() {
let body = {
from: "bpz99ram7",
select: [3, 6, 40],
where: "{40.CT. 'In Progress'}",
sortBy: [{ fieldId: 6, order: "ASC" }],
groupBy: [{ fieldId: 40, grouping: "equal-values" }],
options: { skip: 0, top: 0, compareWithAppLocalTime: false },
};
fetch("https://api.quickbase.com/v1/records/query", {
method: "POST",
headers: headers,
body: JSON.stringify(body),
})
.then((response) => response.json())
.then(({ data }) => setAllData(data));
}
fetchData();
}, []);
// Cycle through the jobIds and indexes
useEffect(() => {
const timerId = setInterval(
() => setIndex((i) => (i + 1) % allData.length),
5000 // 5 seconds.
);
return () => clearInterval(timerId);
}, [allData]);
console.log(allData)
console.log(index)
// Calculate info based on index
const jobId = allData[index]?.['3']?.value || 291; // Default 291
const title = allData[index]?.['6']?.value || 'Default Title';
console.log(jobId)
return (
<div>
{/* <div className="flexbox-container">
<div className="Logo">
{/* <Logo /> */}
{/* </div> */}
<div className="App">
<Title title = {title}/>
</div>
<div className="TopChart">
<TotalLineChart jobId = {jobId}/>
</div>
<div className="FirstRowContainer">
<RadiantLineChart jobId = {jobId}/>
<PlumbingLineChart jobId = {jobId}/>
<FixturesLineChart jobId = {jobId}/>
</div>
<div className="SecondRowContainer">
<SnowmeltLineChart jobId = {jobId}/>
<HVACLineChart jobId = {jobId}/>
<GasPipeLineChart jobId = {jobId}/>
</div>
</div>
);
}
export default App;
App.js takes the field ID and cycles it along with the Title in a duration of 5 seconds each, then sends that data to LineChart.js to be used at the same time with corresponding data.
UPDATE: Able to display dynamically by using props with IDs needed, and using those in each api call to get specific data based on the Title Displaying:
App.js:
import React, { useEffect, useState } from "react";
import './App.css'
import Title from './components/header/Title'
import TotalLineChart from './components/charts/TotalLineChart'
import RadiantLineChart from './components/charts/RadiantLineChart'
import PlumbingLineChart from './components/charts/PlumbingLineChart'
import SnowmeltLineChart from './components/charts/SnowmeltLineChart'
import HVACLineChart from './components/charts/HVACLineChart'
import GasPipeLineChart from './components/charts/GasPipeLineChart'
import FixturesLineChart from './components/charts/FixturesLineChart'
// import TitleCycle from './components/TitleCycle'
// import Logo from './components/Logo';
let headers = {
"QB-Realm-Hostname": "XXXXXXXXX.quickbase.com",
"User-Agent": "FileService_Integration_V2.1",
"Authorization": "QB-USER-TOKEN XXXXXXXXX",
"Content-Type": "application/json",
"Retry-After": 120000
};
function App() {
const [allData, setAllData] = useState([]);
const [index, setIndex] = useState(0);
// Fetch all data, all jobs
useEffect(() => {
function fetchData() {
let body = {
from: "bpz99ram7",
select: [3, 6, 40],
where: "{40.CT. 'In Progress'}",
sortBy: [{ fieldId: 6, order: "ASC" }],
groupBy: [{ fieldId: 40, grouping: "equal-values" }],
options: { skip: 0, top: 0, compareWithAppLocalTime: false },
};
fetch("https://api.quickbase.com/v1/records/query", {
method: "POST",
headers: headers,
body: JSON.stringify(body),
})
.then((response) => response.json())
.then(({ data }) => setAllData(data));
}
fetchData();
}, []);
// Cycle through the jobIds and indexes
useEffect(() => {
const timerId = setInterval(
() => setIndex((i) => (i + 1) % allData.length),
5000 // 5 seconds.
);
return () => clearInterval(timerId);
}, [allData]);
// console.log(allData)
// console.log(index)
// Calculate info based on index
const jobId = allData[index]?.['3']?.value || '291'; // Default 291
const title = allData[index]?.['6']?.value || 'Default Title';
// console.log(jobId)
return (
<div>
{/* <div className="flexbox-container">
<div className="Logo">
{/* <Logo /> */}
{/* </div> */}
<div className="App">
<Title title = {title} />
</div>
<div className="TopChart">
<TotalLineChart jobId = {jobId} />
</div>
<div className="FirstRowContainer">
{/* <RadiantLineChart jobId = {jobId} /> */}
<PlumbingLineChart jobId = {jobId} />
<FixturesLineChart jobId = {jobId} />
</div>
<div className="SecondRowContainer">
<SnowmeltLineChart jobId = {jobId} />
<HVACLineChart jobId = {jobId} />
<GasPipeLineChart jobId = {jobId} />
</div>
</div>
);
}
export default App;
LineChart.js
import React, { useState, useEffect } from "react";
import { Scatter } from "react-chartjs-2";
// import jobId from '../TitleCycle';
// import Title from '../header/Title';
function TotalLineChart(props) {
const { jobId } = props;
// console.log(`${jobId}`)
const [chartData, setChartData] = useState({});
const chart = () => {
let designHours = [];
let designAmount = [];
let subRoughHours = [];
let subRoughAmount = [];
let roughHours = [];
let roughAmount = [];
let finishHours = [];
let finishAmount = [];
let closeHours = [];
let closeAmount = [];
let actualHours = [];
let actualAmount = [];
let headers = {
"QB-Realm-Hostname": "XXXXXXXX.quickbase.com",
"User-Agent": "FileService_Integration_V2.1",
"Authorization": "QB-USER-TOKEN XXXXXXXX",
"Content-Type": "application/json",
"x-ratelimit-reset": 10000,
"Retry-After": 30000
};
// useEffect(() => {
// function fetchData() {
const body = {
from: "bpz99ram7",
select: [
3,
88,
91,
92,
95,
96,
98,
104,
107,
224,
477,
479,
480,
],
where: `{3.EX. ${ jobId }}`,
sortBy: [{ fieldId: 6, order: "ASC" }],
groupBy: [{ fieldId: 40, grouping: "equal-values" }],
options: { skip: 0, compareWithAppLocalTime: false }
};
fetch("https://api.quickbase.com/v1/records/query", {
method: "POST",
headers: headers,
body: JSON.stringify(body)
})
// }
// fetchData();
// }, [])
.then((response) => response.json())
.then((res) => {
// console.log(res);
Object.keys(res.data).map(jobId => {
designHours = parseInt(res.data[jobId]['88'].value, 10);
designAmount = parseInt(res.data[jobId]['91'].value, 10);
subRoughHours = parseInt(res.data[jobId]['92'].value, 10);
subRoughAmount = parseInt(res.data[jobId]['95'].value, 10);
roughHours = parseInt(res.data[jobId]['96'].value, 10);
roughAmount = parseInt(res.data[jobId]['98'].value, 10);
finishHours = parseInt(res.data[jobId]['104'].value, 10);
finishAmount = parseInt(res.data[jobId]['107'].value, 10);
closeHours = parseInt(res.data[jobId]['477'].value, 10);
closeAmount = parseInt(res.data[jobId]['480'].value, 10);
actualHours = parseInt(res.data[jobId]['479'].value, 10);
actualAmount = parseInt(res.data[jobId]['224'].value, 10);
setChartData({
type: 'scatter',
redraw: true,
datasets: [
{
label: 'TOTAL',
data: [
{ x: designHours, y: designAmount },
{ x: subRoughHours, y: subRoughAmount },
{ x: roughHours, y: roughAmount },
{ x: finishHours, y: finishAmount },
{ x: closeHours, y: closeAmount }
],
borderWidth: 2,
borderColor: '#4183c4',
backgroundColor: '#4183c4',
tension: 0.8,
spanGaps: true,
lineTension: 0.5,
showLine: true,
fill: false,
showTooltip: false,
pointBorderWidth: 1
},
{
label: 'ACTUALS',
data: [{ x: actualHours, y: actualAmount }],
fill: false,
borderColor: '#e34747',
backgroundColor: '#e34747',
borderWidth: 3,
showTooltip: false
}
],
options: {
showAllTooltips: true,
enabled: true,
maintainAspectRatio: false,
legend: {
display: true
}
}
})
})
})
.catch((err) => {
console.log(err);
});
};
useEffect(() => {
chart();
}, []);
return (
<div className="App">
<div>
<Scatter
// ref={(reference) => this.chartReference = reference }
data={chartData}
options={{
title: { text: "Total Project", display: false },
scales: {
yAxes: [
{
scaleLabel: {
display: true,
labelString: '$ AMOUNT'
},
ticks: {
autoSkip: true,
maxTicksLimit: 10,
beginAtZero: true
},
gridLines: {
display: true
}
}
],
xAxes: [
{
scaleLabel: {
display: true,
labelString: 'HOURS'
},
gridLines: {
display: true
}
}
],
},
}}
/>
</div>
</div>
);
};
export default TotalLineChart;
You are specifying all kind of weird radixes for your parseInt method, I assume all of your values are just base 10, even if not with a quick test the radix argument only goes up till 36, so if you remove that it should work.
Also you are pushing the same value to a lot of different arrays, seems like you need to specify the value in the dataObject you want to push and not just value, otherwise 1 array would be enough.

How to use axios to fetch data from servlet and then crossfilter it and display via highcharts

I am trying to display charts through highcharts with data from my servlet, but somehow it's not able to display data properly from my servlet(like its showing in console but after that I think I'm missing few steps). I am totally new to react js and this web development stuff, please help, I think its something with axios,
import React from 'react';
import SearchPanel from '../components/SearchPanel'
import { Grid } from '#material-ui/core';
import Highcharts from 'highcharts';
import HighchartsReact from 'highcharts-react-official';
import crossfilter from 'crossfilter2';
import axios from 'axios';
import App1 from '../components/App1';
export default class AnalyticsSection extends React.Component {
state = {
dataResults: [],
data : [],
};
componentDidMount() {
axios.get('http://localhost:8080/Internship_Backend/customer')
.then(response => {
console.log(response);
this.setState({ dataResults : response.data });
})
.catch(error => {
console.log(error);
});
var dataset = crossfilter(this.state.dataResults);
var bcodedim = dataset.dimension(d => d.business_code);
var bcodegrp = bcodedim.group().reduceSum(d => d.actualOpenAmount);
function prepareDataForHighcharts(groups){
var categories =[];
var data = [];
var gdata = groups.top(4);
gdata.forEach(d => {
categories.push(d.key);
data.push(d.value);
});
return{
categories : categories,
data : data
}
}
var tempObject = prepareDataForHighcharts(bcodegrp);
var options = {
chart: {
renderTo : 'container',
type : 'bar',
backgroundColor:'#1b1f38',
minWidth: 275,
height: '222px',
},
// colors: ['#FFFFFFa5 '],
title : {
text : "Total Amount by Company Code",
style:{
color: '#FFFFFFa5'
}
},
xAxis : {
type : 'category',
categories : tempObject.categories,
title: {
text: null
},
overflow : 'auto'
},
yAxis : {
min: 0,
// overflow : 'scroll'
// tickInterval: 10000,
},
tooltip: {
valueSuffix: ' dollars'
},
series : [{
// name : 'Count',
data : tempObject.data,
// data: [125, 100,85, 74, ]
}],
legend : {
enabled : false,
},
credits: {
enabled : false,
},
exporting: {
enabled : false,
},
plotOptions: {
}
}
var chart = new Highcharts.chart(options);
}
render (){
return (
<Grid container >
<Grid item xs style={{
minWidth: 275,
height: '225px',
margin: '2px 2px 10px ',
backgroundColor: "rgb(93,175,240,0.5)",
marginTop:'-10px',
marginLeft : '12px',
marginRight : '-5px'
}} >
<div id = 'container' align='center' style = {{ marginTop : '2px' }}> </div>
</Grid>
<Grid item xs style = {{
minWidth: 275,
height: '225px',
margin: '2px 2px 10px ',
backgroundColor: "rgb(93,175,240,0.5)",
marginTop:'0px',
marginLeft : '12px',
marginRight : '-5px'
}} >
<SearchPanel/>
< div align='center'>
</div>
</Grid>
</Grid>
);
}
}
the data in my servlet is in json format
I would process data further in the then callback and then store results in state.
const url = (() => {
const data = [{"pk_id":1,"acct_doc_header_id":539592086,"company_id":60,"document_number":39439082,"document_number_norm":39439082,"business_code":"pier9","create_year":"","document_line_number":0,"doctype":"RI","customer_number":218994,"customer_number_norm":218994,"fk_customer_map_id":-1,"customer_name":"pied piper","division":"","documentCreateDate":"Jul 5, 2018","documentCreateDateNorm":"Jul 5, 2018","posting_id":"","invoice_id":39439082,"invoice_id_norm":39439082,"totalOpenAmount":0.0,"totalOpenAmountNorm":0.0,"cust_payment_terms":60,"business_area":"","ship_to":"","clearingDate":"Sep 5, 2018","clearingDateNorm":"Sep 5, 2018","reason_code":"","isOpen":0,"debit_credit_indicator":"","payment_method":"","invoiceAmountDocCurrency":3925.91,"document_id":539592086,"actualOpenAmount":3925.91,"paidAmount":3925.91,"dayspast_due":2,"invoice_age":62,"disputed_amount":0.0}]
const blob = new Blob([JSON.stringify(data)], {
type: 'application/json'
})
return URL.createObjectURL(blob);
})()
const options = ({data, categories}) => ({
chart: {
type : 'bar',
backgroundColor:'#1b1f38',
minWidth: 275,
height: '222px',
},
title : {
text : "Total Amount by Company Code",
style:{
color: '#FFFFFFa5'
}
},
xAxis : {
type : 'category',
categories,
title: {
text: null
},
overflow : 'auto'
},
yAxis : {
min: 0,
},
tooltip: {
valueSuffix: ' dollars'
},
series : [{
data
}],
legend : {
enabled : false,
},
credits: {
enabled : false,
},
exporting: {
enabled : false,
},
plotOptions: {}
})
const prepareDataForHighcharts = (groups) => {
const categories = [];
const data = [];
const gdata = groups.top(4);
for(const {key, value} of gdata) {
categories.push(key);
data.push(value);
}
return {
categories,
data
}
}
const ReactHighcharts = ReactHighcharts;
const { Component, useState, useEffect } = React;
class AnalyticsSection extends Component {
constructor(props) {
super(props);
this.state = {
isLoading: true,
dataResults: [],
config: {}
}
}
componentDidMount() {
this.mounted = true;
axios.get(url)
.then(response => {
const dataResults = response.data;
if(!this.mounted) {
return;
}
const dataset = crossfilter(dataResults);
const bcodedim = dataset
.dimension(({business_code}) => business_code);
const bcodegrp = bcodedim.group()
.reduceSum(({actualOpenAmount}) => actualOpenAmount);
const obj = prepareDataForHighcharts(bcodegrp);
const config = options(obj);
this.setState(state => ({
isLoading: false,
config
}));
})
.catch(error => {
console.log(error);
});
}
componentWillUnmount() {
this.mounted = false;
}
render() {
const { isLoading, config } = this.state;
return <div>
{isLoading ? <div>Loading</div> : <ReactHighcharts config = {config}></ReactHighcharts>}
</div>
}
}
ReactDOM.render(
<AnalyticsSection />,
document.getElementById('root')
);
<script src="https://unpkg.com/react/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/babel-standalone#6/babel.min.js"></script>
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://unpkg.com/react-highcharts#16.0.2/bundle/ReactHighcharts.js"></script>
<script src="https://unpkg.com/crossfilter2#latest/crossfilter.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.19.2/axios.js"></script>
<div id="root"></div>

Categories

Resources