forked from ddrilling/asb_cloud_front
График-пончик
This commit is contained in:
parent
2381eb9029
commit
17cbe374ad
@ -40,7 +40,7 @@ export function AnalysisDepthToInterval() {
|
|||||||
AnalyticsService.getWellDepthToInterval(id, chartInterval)
|
AnalyticsService.getWellDepthToInterval(id, chartInterval)
|
||||||
.then(handleReceiveDepthToIntervalData)
|
.then(handleReceiveDepthToIntervalData)
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
notify(`Не удалось получить данные для Анализа Глубина-День по скважине "${id}"`,
|
notify(`Не удалось получить данные для Анализа скорость проходки-интервал "${id}"`,
|
||||||
'warning')
|
'warning')
|
||||||
console.log(error)
|
console.log(error)
|
||||||
})
|
})
|
||||||
|
60
src/components/AnalysisOperationTime.jsx
Normal file
60
src/components/AnalysisOperationTime.jsx
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
import { useParams } from "react-router-dom"
|
||||||
|
import { DatePicker, ConfigProvider } from 'antd';
|
||||||
|
import notify from "../components/notify"
|
||||||
|
import { useState, useEffect } from 'react'
|
||||||
|
import { AnalyticsService } from '../services/api'
|
||||||
|
import { ChartOperationTime } from './charts/ChartOperationTime'
|
||||||
|
import locale from "antd/lib/locale/ru_RU";
|
||||||
|
|
||||||
|
const { RangePicker } = DatePicker
|
||||||
|
|
||||||
|
const lines = [{ labelAccessorName: "processName", pieceAccessorName: "duration" }]
|
||||||
|
|
||||||
|
export function AnalysisOperationTime() {
|
||||||
|
let { id } = useParams()
|
||||||
|
const [operationTimeData, setOperationTimeData] = useState([])
|
||||||
|
const [loader, setLoader] = useState(false)
|
||||||
|
const [range, setRange] = useState([])
|
||||||
|
|
||||||
|
let begin = null
|
||||||
|
let end = null
|
||||||
|
|
||||||
|
const onChangeRange = (range) => {
|
||||||
|
setRange(range)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleReceiveOperationTimeData = (data) => {
|
||||||
|
setOperationTimeData(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setLoader(true)
|
||||||
|
if (range?.length > 1) {
|
||||||
|
begin = range[0].toISOString()
|
||||||
|
end = range[1].toISOString()
|
||||||
|
}
|
||||||
|
AnalyticsService.getOperationsSummary(id, begin, end)
|
||||||
|
.then(handleReceiveOperationTimeData)
|
||||||
|
.catch(error => {
|
||||||
|
notify(`Не удалось получить данные для Анализа Операция-Время по скважине "${id}" за период с ${begin} по ${end}`,
|
||||||
|
'warning')
|
||||||
|
console.log(error)
|
||||||
|
})
|
||||||
|
.finally(setLoader(false))
|
||||||
|
}, [id, range])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<ConfigProvider locale={locale}>
|
||||||
|
<RangePicker
|
||||||
|
showTime
|
||||||
|
onChange={onChangeRange}
|
||||||
|
/>
|
||||||
|
</ConfigProvider>
|
||||||
|
<ChartOperationTime
|
||||||
|
data={operationTimeData}
|
||||||
|
lines={lines}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
@ -220,8 +220,5 @@ export const ChartDepthToIntervalBase: React.FC<ChartTimeBaseProps> = ({ options
|
|||||||
chart.update()
|
chart.update()
|
||||||
}, [chart, dataParams, options])
|
}, [chart, dataParams, options])
|
||||||
|
|
||||||
return (<canvas style={{
|
return (<canvas ref={chartRef} />)
|
||||||
width: "100px",
|
|
||||||
height: "100px"
|
|
||||||
}} ref={chartRef} />)
|
|
||||||
}
|
}
|
67
src/components/charts/ChartOperationTime.jsx
Normal file
67
src/components/charts/ChartOperationTime.jsx
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
import { useEffect, useState } from 'react'
|
||||||
|
import { ChartOpertationTimeBase } from './ChartOperationTimeBase'
|
||||||
|
import moment from 'moment'
|
||||||
|
|
||||||
|
export const CreateLabels = (lineConfig) => {
|
||||||
|
let labels = []
|
||||||
|
return labels
|
||||||
|
}
|
||||||
|
|
||||||
|
export const CreateData = (lineConfig) => {
|
||||||
|
let datasets = {
|
||||||
|
label: lineConfig.label,
|
||||||
|
data: [],
|
||||||
|
backgroundColor: [
|
||||||
|
'#f00', '#ff0', '#f0f', '#0ff', '#00f', '#0f0'
|
||||||
|
],
|
||||||
|
}
|
||||||
|
return datasets
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ChartOperationTime = ({ lines, data, rangeDate }) => {
|
||||||
|
const [opertationTimeDataParams, setOpertationTimeDataParams] = useState({ data: { labels: [], datasets: [] } })
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if ((!lines)
|
||||||
|
|| (!data))
|
||||||
|
return
|
||||||
|
|
||||||
|
let newLabels = lines.map(lineCfg => {
|
||||||
|
let labels = CreateLabels(lineCfg)
|
||||||
|
if (data.length !== 0)
|
||||||
|
labels = data.map(dataItem => {
|
||||||
|
return dataItem[lineCfg.labelAccessorName]
|
||||||
|
})
|
||||||
|
return labels
|
||||||
|
})
|
||||||
|
|
||||||
|
let newDatasets = lines.map(lineCfg => {
|
||||||
|
let datasets = CreateData(lineCfg)
|
||||||
|
if (data.length !== 0)
|
||||||
|
datasets.data = data.map(dataItem => {
|
||||||
|
return dataItem[lineCfg.pieceAccessorName]
|
||||||
|
})
|
||||||
|
return datasets
|
||||||
|
})
|
||||||
|
|
||||||
|
let interval = rangeDate ? (rangeDate[1] - rangeDate[0]) / 1000 : null
|
||||||
|
let startDate = rangeDate ? rangeDate[0] : moment()
|
||||||
|
let newParams = {
|
||||||
|
xInterval: interval,
|
||||||
|
xStart: startDate,
|
||||||
|
data: {
|
||||||
|
labels: newLabels,
|
||||||
|
datasets: newDatasets
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setOpertationTimeDataParams(newParams)
|
||||||
|
|
||||||
|
console.log(newParams)
|
||||||
|
|
||||||
|
}, [data, lines, rangeDate])
|
||||||
|
|
||||||
|
return (<>
|
||||||
|
<ChartOpertationTimeBase dataParams={opertationTimeDataParams} />
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
177
src/components/charts/ChartOperationTimeBase.tsx
Normal file
177
src/components/charts/ChartOperationTimeBase.tsx
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
import { useEffect, useRef, useState } from 'react'
|
||||||
|
import {
|
||||||
|
Chart,
|
||||||
|
ArcElement,
|
||||||
|
TimeScale,
|
||||||
|
Legend,
|
||||||
|
PointElement,
|
||||||
|
ChartData,
|
||||||
|
ChartTypeRegistry,
|
||||||
|
ChartOptions,
|
||||||
|
DoughnutController,
|
||||||
|
} from 'chart.js'
|
||||||
|
import 'chartjs-adapter-moment'
|
||||||
|
import ChartDataLabels from 'chartjs-plugin-datalabels'
|
||||||
|
|
||||||
|
Chart.register(TimeScale, DoughnutController, PointElement, ArcElement, Legend, ChartDataLabels)
|
||||||
|
|
||||||
|
const defaultOptions = {
|
||||||
|
responsive: true,
|
||||||
|
title: {
|
||||||
|
display: true,
|
||||||
|
position: "top",
|
||||||
|
text: "Doughnut Chart",
|
||||||
|
fontSize: 18,
|
||||||
|
fontColor: "#111"
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
display: true,
|
||||||
|
position: "bottom",
|
||||||
|
labels: {
|
||||||
|
fontColor: "#333",
|
||||||
|
fontSize: 16
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ChartTimeData = ChartData<keyof ChartTypeRegistry, {
|
||||||
|
x: String;
|
||||||
|
label: number;
|
||||||
|
y: number;
|
||||||
|
}[], unknown>
|
||||||
|
|
||||||
|
export type ChartTimeDataParams = {
|
||||||
|
data: ChartTimeData,
|
||||||
|
xStart?: Date,
|
||||||
|
xInterval?: number,
|
||||||
|
displayLabels?: Boolean,
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ChartTimeBaseProps = {
|
||||||
|
dataParams: ChartTimeDataParams,
|
||||||
|
// TODO: Create good type for options
|
||||||
|
options?: ChartOptions<keyof ChartTypeRegistry> | any,
|
||||||
|
}
|
||||||
|
|
||||||
|
export type TimeParams = {
|
||||||
|
unit: String
|
||||||
|
stepSize: number
|
||||||
|
}
|
||||||
|
|
||||||
|
const linesPerInterval = 32
|
||||||
|
|
||||||
|
export const timeUnitByInterval = (intervalSec: number): String => {
|
||||||
|
if (intervalSec <= 60)
|
||||||
|
return 'millisecond'
|
||||||
|
|
||||||
|
if (intervalSec <= 32 * 60)
|
||||||
|
return 'second'
|
||||||
|
|
||||||
|
if (intervalSec <= 32 * 60 * 60)
|
||||||
|
return 'minute'
|
||||||
|
|
||||||
|
if (intervalSec <= 32 * 12 * 60 * 60)
|
||||||
|
return 'hour'
|
||||||
|
|
||||||
|
if (intervalSec <= 32 * 24 * 60 * 60)
|
||||||
|
return 'day'
|
||||||
|
|
||||||
|
if (intervalSec <= 32 * 7 * 24 * 60 * 60)
|
||||||
|
return 'week'
|
||||||
|
|
||||||
|
if (intervalSec <= 32 * 30.4375 * 24 * 60 * 60)
|
||||||
|
return 'month'
|
||||||
|
|
||||||
|
if (intervalSec <= 32 * 121.75 * 24 * 60 * 60)
|
||||||
|
return 'quarter'
|
||||||
|
else
|
||||||
|
return 'year'
|
||||||
|
}
|
||||||
|
|
||||||
|
export const timeParamsByInterval = (intervalSec: number): TimeParams => {
|
||||||
|
let stepSize = intervalSec
|
||||||
|
let unit = timeUnitByInterval(intervalSec)
|
||||||
|
|
||||||
|
switch (unit) {
|
||||||
|
case "millisecond":
|
||||||
|
stepSize *= 1000
|
||||||
|
break;
|
||||||
|
case "second":
|
||||||
|
//stepSize *= 1
|
||||||
|
break;
|
||||||
|
case "minute":
|
||||||
|
stepSize /= 60
|
||||||
|
break;
|
||||||
|
case "hour":
|
||||||
|
stepSize /= 60 * 60
|
||||||
|
break;
|
||||||
|
case "day":
|
||||||
|
stepSize /= 24 * 60 * 60
|
||||||
|
break;
|
||||||
|
case "week":
|
||||||
|
stepSize /= 7 * 24 * 60 * 60
|
||||||
|
break;
|
||||||
|
case "month":
|
||||||
|
stepSize /= 30 * 24 * 60 * 60
|
||||||
|
break;
|
||||||
|
case "quarter":
|
||||||
|
stepSize /= 91 * 24 * 60 * 60
|
||||||
|
break;
|
||||||
|
case "year":
|
||||||
|
stepSize /= 365.25 * 24 * 60 * 60
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
stepSize = Math.round(stepSize / linesPerInterval)
|
||||||
|
stepSize = stepSize > 0 ? stepSize : 1;
|
||||||
|
return { unit, stepSize }
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ChartOpertationTimeBase: React.FC<ChartTimeBaseProps> = ({ options, dataParams }) => {
|
||||||
|
const chartRef = useRef<HTMLCanvasElement>(null)
|
||||||
|
const [chart, setChart] = useState<any>()
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if ((chartRef.current) && (!chart)) {
|
||||||
|
let thisOptions = {}
|
||||||
|
Object.assign(thisOptions, defaultOptions, options)
|
||||||
|
|
||||||
|
let newChart = new Chart(chartRef.current, {
|
||||||
|
type: 'doughnut',
|
||||||
|
plugins: [ChartDataLabels],
|
||||||
|
options: thisOptions,
|
||||||
|
data: dataParams.data
|
||||||
|
})
|
||||||
|
setChart(newChart)
|
||||||
|
|
||||||
|
return () => chart?.destroy()
|
||||||
|
}
|
||||||
|
}, [chart, options, dataParams])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!chart)
|
||||||
|
return
|
||||||
|
|
||||||
|
chart.data = dataParams.data
|
||||||
|
chart.options.aspectRatio = options?.aspectRatio
|
||||||
|
if (dataParams.xStart) {
|
||||||
|
let interval = Number(dataParams.xInterval ?? 600)
|
||||||
|
let start = new Date(dataParams.xStart)
|
||||||
|
let end = new Date(dataParams.xStart)
|
||||||
|
end.setSeconds(end.getSeconds() + interval)
|
||||||
|
let { unit, stepSize } = timeParamsByInterval(interval)
|
||||||
|
|
||||||
|
if (chart.options.scales?.x) {
|
||||||
|
chart.options.scales.x.max = end.getTime()
|
||||||
|
chart.options.scales.x.min = start.getTime()
|
||||||
|
chart.options.scales.x.ticks.display = dataParams.displayLabels ?? true
|
||||||
|
chart.options.scales.x.time.unit = unit
|
||||||
|
chart.options.scales.x.time.stepSize = stepSize
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
chart.update()
|
||||||
|
}, [chart, dataParams, options])
|
||||||
|
|
||||||
|
return (<canvas ref={chartRef} />)
|
||||||
|
}
|
@ -1,13 +1,30 @@
|
|||||||
import { AnalysisDepthToDay } from '../components/AnalysisDepthToDay'
|
import { AnalysisDepthToDay } from '../components/AnalysisDepthToDay'
|
||||||
import { AnalysisDepthToInterval } from '../components/AnalysisDepthToInterval'
|
import { AnalysisDepthToInterval } from '../components/AnalysisDepthToInterval'
|
||||||
|
import { AnalysisOperationTime } from '../components/AnalysisOperationTime'
|
||||||
|
import { Row, Col } from 'antd'
|
||||||
|
|
||||||
export default function Analysis() {
|
export default function Analysis() {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<AnalysisDepthToDay />
|
<Row>
|
||||||
<div style={{ marginTop: '100px' }}> </div>
|
<Col span={10}>
|
||||||
<AnalysisDepthToInterval />
|
<AnalysisDepthToDay />
|
||||||
|
</Col>
|
||||||
|
<Col span={2}></Col>
|
||||||
|
<Col span={10}>
|
||||||
|
<AnalysisDepthToInterval />
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<Col span={10}>
|
||||||
|
<AnalysisOperationTime />
|
||||||
|
</Col>
|
||||||
|
<Col span={2}></Col>
|
||||||
|
<Col span={10}>
|
||||||
|
<AnalysisDepthToDay />
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user