Refactor defaultNumericColunmOptions to makeNumericColunmOptions(..)

This commit is contained in:
Фролов 2021-10-08 17:02:15 +05:00
parent fbc0c97b99
commit 26044734ad
8 changed files with 83 additions and 202 deletions

View File

@ -32,7 +32,7 @@
"react_test": "react-scripts test", "react_test": "react-scripts test",
"eject": "react-scripts eject" "eject": "react-scripts eject"
}, },
"proxy": "http://localhost:5000", "proxy": "http://192.168.1.58:5000",
"eslintConfig": { "eslintConfig": {
"extends": [ "extends": [
"react-app", "react-app",

View File

@ -1,4 +1,6 @@
import { ReactNode } from 'react' import { ReactNode } from 'react'
import { makeNumericSorter, makeStringSorter} from './sorters'
export { makeDateSorter, makeNumericSorter, makeStringSorter} from './sorters'
export { Table } from 'antd' export { Table } from 'antd'
export { EditableTable } from './EditableTable' export { EditableTable } from './EditableTable'
export { DatePickerWrapper } from './DatePickerWrapper' export { DatePickerWrapper } from './DatePickerWrapper'
@ -7,10 +9,28 @@ export { SelectFromDictionary } from './SelectFromDictionary'
export const RegExpIsFloat = /^[-+]?\d+\.?\d*$/ export const RegExpIsFloat = /^[-+]?\d+\.?\d*$/
export const formatDate='YYYY.MM.DD HH:mm' export const formatDate='YYYY.MM.DD HH:mm'
export const numericColumnOptions = { export const makeNumericRender = (fixed?:number) => (value: any, row: object): ReactNode => {
const placeholder = '-'
let val = placeholder
if((value !== null) ||
(value !== undefined) ||
Number.isNaN(value) ||
!Number.isFinite(value)){
val = !!fixed
? (+value).toFixed(fixed)
: (+value).toPrecision(5)
}
return (<div className='text-align-r-container'>
<span>{val}</span>
</div>)
}
export const makeNumericColumnOptions = (fixed?:number, sorterKey?:string ) => ({
editable: true, editable: true,
initialValue: 0, initialValue: 0,
width:100, width:100,
sorter: sorterKey? makeNumericSorter(sorterKey) : null,
formItemRules: [ formItemRules: [
{ {
required: true, required: true,
@ -18,7 +38,8 @@ export const numericColumnOptions = {
pattern: RegExpIsFloat, pattern: RegExpIsFloat,
}, },
], ],
}; render: makeNumericRender(fixed),
})
/* /*
other - объект с дополнительными свойствами колонки other - объект с дополнительными свойствами колонки
@ -78,41 +99,6 @@ export const makeColumnsPlanFact = (title:string | ReactNode, key:string|string[
export const makeFilterTextMatch = (key: string | number) => (filterValue: string | number, dataItem: any) => export const makeFilterTextMatch = (key: string | number) => (filterValue: string | number, dataItem: any) =>
dataItem[key] === filterValue dataItem[key] === filterValue
export const makeNumericSorter = (key: string) => (a: any, b: any) => a[key] - b[key]
export const makeStringSorter = (key: string) => (a: any, b: any) =>
{
if(a == null && b == null)
return 1
if(a == null)
return 1
if(b == null)
return -1
let aValue = a[key]
let bValue = b[key]
for (let i = 0; i < a.length; i++) {
if (isNaN(aValue.charCodeAt(i)) || (aValue.charCodeAt(i) > bValue.charCodeAt(i)))
return 1
if (aValue.charCodeAt(i) > bValue.charCodeAt(i))
return -1
}
return 0
}
export const makeDateSorter = (key: string) => (a: any, b: any) => {
const date = new Date(a[key])
if(Number.isNaN(date.getTime()))
throw new Error('Date column contains not date formatted string(s)')
return date.getTime() - new Date(b[key]).getTime()
}
export const makeGroupColumn = (title: string, children: object[]) => ({ export const makeGroupColumn = (title: string, children: object[]) => ({
title: title, title: title,
children: children, children: children,
@ -135,17 +121,6 @@ export const makeTextColumn = (
...other ...other
}) })
export const defaultNumericRender = (value: any, row: object) => {
const placeholder = '-'
if((value === null) ||
(value === undefined) ||
Number.isNaN(value) ||
!Number.isFinite(value))
return placeholder
return (+value).toPrecision(5)
}
export const makeNumericColumn = (title: string, dataIndex: string, export const makeNumericColumn = (title: string, dataIndex: string,
filters: object[], filterDelegate: (key: string | number) => any, filters: object[], filterDelegate: (key: string | number) => any,
renderDelegate: (_: any, row: object) => any, width: string) => ({ renderDelegate: (_: any, row: object) => any, width: string) => ({
@ -156,7 +131,7 @@ export const makeNumericColumn = (title: string, dataIndex: string,
onFilter: filterDelegate ? filterDelegate(dataIndex) : null, onFilter: filterDelegate ? filterDelegate(dataIndex) : null,
sorter: makeNumericSorter(dataIndex), sorter: makeNumericSorter(dataIndex),
width: width, width: width,
render: renderDelegate??defaultNumericRender, render: renderDelegate??makeNumericRender(),
align: 'right' align: 'right'
}) })

View File

@ -0,0 +1,33 @@
export const makeNumericSorter = (key: string) => (a: any, b: any) => a[key] - b[key];
export const makeStringSorter = (key: string) => (a: any, b: any) => {
if (a == null && b == null)
return 1;
if (a == null)
return 1;
if (b == null)
return -1;
let aValue = a[key];
let bValue = b[key];
for (let i = 0; i < a.length; i++) {
if (isNaN(aValue.charCodeAt(i)) || (aValue.charCodeAt(i) > bValue.charCodeAt(i)))
return 1;
if (aValue.charCodeAt(i) > bValue.charCodeAt(i))
return -1;
}
return 0;
};
export const makeDateSorter = (key: string) => (a: any, b: any) => {
const date = new Date(a[key]);
if (Number.isNaN(date.getTime()))
throw new Error('Date column contains not date formatted string(s)');
return date.getTime() - new Date(b[key]).getTime();
};

View File

@ -1,133 +0,0 @@
import {useEffect, useRef, useState} from 'react';
import {
Chart,
TimeScale,
LinearScale,
Legend,
LineController,
PointElement,
LineElement
} from 'chart.js'
import 'chartjs-adapter-moment';
import ChartDataLabels from 'chartjs-plugin-datalabels';
import zoomPlugin from 'chartjs-plugin-zoom';
Chart.register(TimeScale, LinearScale, LineController, LineElement, PointElement, Legend, ChartDataLabels, zoomPlugin);
const defaultOptions = {
responsive: true,
aspectRatio: 2.6,
interaction: {
intersect: false,
mode: 'index',
},
scales: {
x:{
display: true,
title: {
display: true
},
type: 'time',
time: {
unit: 'hour',
displayFormats: {
'hour': 'MM.DD'
}
},
grid:{
drawTicks: true,
},
ticks: {
stepSize:3,
major:{enabled:true,},
z: 1,
display : true,
textStrokeColor : "#fff",
textStrokeWidth : 2,
color:"#000",
}
},
y:{
type:'linear',
position:'top',
reverse:true,
display: true,
title: {
display: false,
text: ''
},
}
},
parsing: {
xAxisKey: 'date',
yAxisKey: 'depth'
},
elements:{
point:{
radius:1.7,
//backgroundColor:'#aaa',
//pointStyle:'triangle',
},
},
plugins:{
legend:{
display: true,
},
datalabels: {
display: false,
},
tooltip: {
enabled: true,
callbacks: {
label(tooltipItem) {
return tooltipItem.yLabel;
}
}
},
}
}
const makeDataset = (data, label, color, width=1.5, dash) => ({
label: label,
data: data,
backgroundColor: color,
borderColor: color,
borderWidth: width,
borderDash: dash,
})
export default function ChartDepthToDay({dataPlan, dataFact, dataForecast}) {
const chartRef = useRef(null)
const [chart, setChart] = useState()
useEffect(() => {
let data = {
datasets: [
makeDataset(dataFact, 'Факт', '#0A0'),
makeDataset(dataForecast, 'Прогноз', 'purple', 1, [7,3]),
makeDataset(dataPlan, 'План', '#C004', 4),
]
}
if((chartRef.current)&&(!chart)) {
let thisOptions = {}
Object.assign(thisOptions, defaultOptions)
let newChart = new Chart(chartRef.current, {
type: 'line',
plugins: [ChartDataLabels],
options: thisOptions,
data: data
})
setChart(newChart)
return () => chart?.destroy()
} else {
chart.data = data
chart.update()
}
}, [chart, dataPlan, dataFact, dataForecast])
return (<canvas ref={chartRef} />)
}

View File

@ -7,7 +7,7 @@ import {
makeNumericColumnPlanFact makeNumericColumnPlanFact
} from "../../components/Table"; } from "../../components/Table";
import { invokeWebApiWrapperAsync } from '../../components/factory'; import { invokeWebApiWrapperAsync } from '../../components/factory';
import ChartDepthToDay from '../../components/charts/ChartDepthToDay'; import ChartTvD from '../WellOperations/ChartTvD';
import WellOperationsTable from './WellOperationsTable' import WellOperationsTable from './WellOperationsTable'
import { import {
calcAndUpdateStatsBySections, calcAndUpdateStatsBySections,
@ -249,10 +249,10 @@ export default function ClusterSections({ clusterData }) {
width={1500} width={1500}
footer={null} footer={null}
> >
<ChartDepthToDay <ChartTvD
dataPlan={tvdDataPlan} dataPlan={tvdDataPlan}
dataFact={tvdDataFact} dataFact={tvdDataFact}
dataForecast={tvdDataForecast} /> dataPredict={tvdDataForecast} />
</Modal> </Modal>
<Modal <Modal

View File

@ -6,12 +6,11 @@ import {
makeTextColumn, makeTextColumn,
makeGroupColumn, makeGroupColumn,
makeColumn, makeColumn,
makeNumericColumnPlanFact, makeDateSorter,
makeDateSorter makeNumericColumnPlanFact} from "../../components/Table";
} from "../../components/Table";
import { calcAndUpdateStatsBySections, makeFilterMinMaxFunction } from "./functions"; import { calcAndUpdateStatsBySections, makeFilterMinMaxFunction } from "./functions";
import { invokeWebApiWrapperAsync } from '../../components/factory'; import { invokeWebApiWrapperAsync } from '../../components/factory';
import ChartDepthToDay from '../../components/charts/ChartDepthToDay'; import ChartTvD from '../WellOperations/ChartTvD';
import WellOperationsTable from './WellOperationsTable' import WellOperationsTable from './WellOperationsTable'
import { getOperations } from "./functions"; import { getOperations } from "./functions";
@ -206,10 +205,10 @@ useEffect(() => {
width={1500} width={1500}
footer={null} footer={null}
> >
<ChartDepthToDay <ChartTvD
dataPlan={tvdDataPlan} dataPlan={tvdDataPlan}
dataFact={tvdDataFact} dataFact={tvdDataFact}
dataForecast={tvdDataForecast} dataPredict={tvdDataForecast}
/> />
</Modal> </Modal>

View File

@ -6,17 +6,24 @@ const minPrefix = "isMin"
export const getOperations = async (idWell) => { export const getOperations = async (idWell) => {
const ops = await WellOperationStatService.getTvd(idWell); const ops = await WellOperationStatService.getTvd(idWell);
const planData = ops.map(el => { const convert = wellOperationDto =>
return {key: el.plan?.id, depth: el.plan?.wellDepth, date: el.plan?.startDate} ({
}).filter(el => el.key) key: wellOperationDto?.id,
depth: wellOperationDto?.depthStart,
date: wellOperationDto?.dateStart
})
const factData = ops.map(el => { const planData = ops
return {key: el.fact?.id, depth: el.fact?.wellDepth, date: el.fact?.startDate} .map(item => convert(item.plan))
}).filter(el => el.key) .filter(el => el.key)
const predictData = ops.map(el => { const factData = ops
return {key: el.predict?.id, depth: el.predict?.wellDepth, date: el.predict?.startDate} .map(item => convert(item.fact))
}).filter(el => el.key) .filter(el => el.key)
const predictData = ops
.map(item => convert(item.predict))
.filter(el => el.key)
return { operations: ops, plan: planData, fact: factData, predict: predictData } return { operations: ops, plan: planData, fact: factData, predict: predictData }
} }

View File

@ -1,5 +1,5 @@
import { useState, useEffect } from "react" import { useState, useEffect } from "react"
import { Table, makeDateSorter, makeNumericSorter, formatDate} from "../../components/Table" import { Table, formatDate, makeDateSorter, makeNumericSorter} from "../../components/Table"
import { Button, Tooltip } from "antd" import { Button, Tooltip } from "antd"
import { FilePdfOutlined, FileTextOutlined} from '@ant-design/icons' import { FilePdfOutlined, FileTextOutlined} from '@ant-design/icons'
import { ReportService } from "../../services/api" import { ReportService } from "../../services/api"