diff --git a/package.json b/package.json index 3fefe17..13399cb 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,7 @@ "react_test": "react-scripts test", "eject": "react-scripts eject" }, - "proxy": "http://localhost:5000", + "proxy": "http://192.168.1.58:5000", "eslintConfig": { "extends": [ "react-app", diff --git a/src/components/Table/index.ts b/src/components/Table/index.tsx similarity index 79% rename from src/components/Table/index.ts rename to src/components/Table/index.tsx index d06ed94..d936ab5 100644 --- a/src/components/Table/index.ts +++ b/src/components/Table/index.tsx @@ -1,4 +1,6 @@ import { ReactNode } from 'react' +import { makeNumericSorter, makeStringSorter} from './sorters' +export { makeDateSorter, makeNumericSorter, makeStringSorter} from './sorters' export { Table } from 'antd' export { EditableTable } from './EditableTable' export { DatePickerWrapper } from './DatePickerWrapper' @@ -7,10 +9,28 @@ export { SelectFromDictionary } from './SelectFromDictionary' export const RegExpIsFloat = /^[-+]?\d+\.?\d*$/ 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 (
+ {val} +
) +} + +export const makeNumericColumnOptions = (fixed?:number, sorterKey?:string ) => ({ editable: true, initialValue: 0, width:100, + sorter: sorterKey? makeNumericSorter(sorterKey) : null, formItemRules: [ { required: true, @@ -18,7 +38,8 @@ export const numericColumnOptions = { pattern: RegExpIsFloat, }, ], -}; + render: makeNumericRender(fixed), +}) /* 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) => 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[]) => ({ title: title, children: children, @@ -135,17 +121,6 @@ export const makeTextColumn = ( ...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, filters: object[], filterDelegate: (key: string | number) => any, renderDelegate: (_: any, row: object) => any, width: string) => ({ @@ -156,7 +131,7 @@ export const makeNumericColumn = (title: string, dataIndex: string, onFilter: filterDelegate ? filterDelegate(dataIndex) : null, sorter: makeNumericSorter(dataIndex), width: width, - render: renderDelegate??defaultNumericRender, + render: renderDelegate??makeNumericRender(), align: 'right' }) diff --git a/src/components/Table/sorters.ts b/src/components/Table/sorters.ts new file mode 100644 index 0000000..71732cb --- /dev/null +++ b/src/components/Table/sorters.ts @@ -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(); +}; diff --git a/src/components/charts/ChartDepthToDay.jsx b/src/components/charts/ChartDepthToDay.jsx deleted file mode 100644 index dcd7cde..0000000 --- a/src/components/charts/ChartDepthToDay.jsx +++ /dev/null @@ -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 () -} \ No newline at end of file diff --git a/src/pages/Cluster/ClusterSections.jsx b/src/pages/Cluster/ClusterSections.jsx index b87ecd6..f3b862b 100644 --- a/src/pages/Cluster/ClusterSections.jsx +++ b/src/pages/Cluster/ClusterSections.jsx @@ -7,7 +7,7 @@ import { makeNumericColumnPlanFact } from "../../components/Table"; import { invokeWebApiWrapperAsync } from '../../components/factory'; -import ChartDepthToDay from '../../components/charts/ChartDepthToDay'; +import ChartTvD from '../WellOperations/ChartTvD'; import WellOperationsTable from './WellOperationsTable' import { calcAndUpdateStatsBySections, @@ -249,10 +249,10 @@ export default function ClusterSections({ clusterData }) { width={1500} footer={null} > - + dataPredict={tvdDataForecast} /> { width={1500} footer={null} > - diff --git a/src/pages/Cluster/functions.jsx b/src/pages/Cluster/functions.jsx index 557e867..a50358b 100644 --- a/src/pages/Cluster/functions.jsx +++ b/src/pages/Cluster/functions.jsx @@ -6,17 +6,24 @@ const minPrefix = "isMin" export const getOperations = async (idWell) => { const ops = await WellOperationStatService.getTvd(idWell); - const planData = ops.map(el => { - return {key: el.plan?.id, depth: el.plan?.wellDepth, date: el.plan?.startDate} - }).filter(el => el.key) + const convert = wellOperationDto => + ({ + key: wellOperationDto?.id, + depth: wellOperationDto?.depthStart, + date: wellOperationDto?.dateStart + }) - const factData = ops.map(el => { - return {key: el.fact?.id, depth: el.fact?.wellDepth, date: el.fact?.startDate} - }).filter(el => el.key) + const planData = ops + .map(item => convert(item.plan)) + .filter(el => el.key) - const predictData = ops.map(el => { - return {key: el.predict?.id, depth: el.predict?.wellDepth, date: el.predict?.startDate} - }).filter(el => el.key) + const factData = ops + .map(item => convert(item.fact)) + .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 } } diff --git a/src/pages/Report/Reports.jsx b/src/pages/Report/Reports.jsx index 064be92..322171e 100644 --- a/src/pages/Report/Reports.jsx +++ b/src/pages/Report/Reports.jsx @@ -1,5 +1,5 @@ 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 { FilePdfOutlined, FileTextOutlined} from '@ant-design/icons' import { ReportService } from "../../services/api"