我一直在努力获取这个数据集并能够跨多个组件显示。截至目前,我有 6 个不同的组件在 React 应用程序中从 Chart.js 生成折线图。我正在尝试从 QuickBase RESTful API 完成 API 调用以调用 2 个不同的表并从每个表中获取字段列表,因此,我的结构中有 2 个文件,其中包含对每个表的这 2 个不同的 api 调用。我希望我能够成功完成这些 api 调用,并能够根据需要实际呈现数据,以便能够在所有这些图表上使用。有没有人可以帮助我解决这个问题?已经坚持了一段时间了......这是我到目前为止的 API 调用。
import React, { Component } from 'react'
let headers = {
'QB-Realm-Hostname': 'XXXXXXXXXX.quickbase.com',
'User-Agent': 'FileService_Integration_V2.1',
'Authorization': 'QB-USER-TOKEN XXXX_XXXX_XXXXXXXXXXXXXX',
'Content-Type': 'application/json'
};
class JobsTableApi extends Component {
state = {
data: [],
}
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],"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 => {
if (response.ok) {
return response.json().then(res => {
this.setState({
data: [],
})
});
}
return response.json().then(resBody => Promise.reject({status: response.status, ...resBody}));
}).catch(err => console.log(err))
}
render() {
const { data } = this.state;
if (data === null) return 'Loading...';
return (
<div>
{data.jobname}
</div>
);
}
}
export default JobsTableApi;
所以最终我试图选择“选择”部分中提到的所有字段,以便能够根据需要分配给折线图。我在这里做错了什么,我无法渲染任何东西?我们的想法是我们的 quickbase 用于项目管理,因此页面上的 1 个折线图将是“总计”,而其他折线图将属于该作业中包含的部门,它们都是相关的,并且数据都在 quickbase 中,并且在我的控制台中,但我无法弄清楚如何让这一切正确呈现,因此我可以创建折线图并根据作业名称循环结果。
现在我也不确定如何调用每个字段名称,因为 json 像这样过来: data: 0, 3, 18
0 = 该工作的所有信息,3 = 将是具有工作名称的实际字段,18 = 部门名称......等等。
我的想法是让所有这些折线图显示在一个页面上,显示工作的总数,以及每个部门的总数,然后设置一个计时器,使用滑块库或类似的东西循环浏览所有工作。
所以到目前为止,我正试图弄清楚如何编写代码以能够选择特定字段并在折线图组件中使用它们。
任何帮助,将不胜感激!
谢谢!
更新 我现在可以根据 App.js 中循环作业名称和 ID 的初始 api 调用来选择所需的每个 ID。因此,无论当前显示什么 ID,它都将作为 props 发送并在 QuickBase API 调用中使用,该调用将确定从 QuickBase 返回的内容。
应用程序.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 XXXXXXXX",
"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 XXXXXXX",
"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;