Removed null check for cluster table data from parse functions to render

This commit is contained in:
KharchenkoVV 2021-08-31 16:41:13 +05:00
parent af76dad0b2
commit a21e528f55
4 changed files with 303 additions and 172 deletions

View File

@ -119,7 +119,8 @@ export const makeTextColumn = (title: string, dataIndex: string,
})
export const makeNumericColumn = (title: string, dataIndex: string,
filters: object[], filterDelegate: (key: string | number) => any, width: string) => ({
filters: object[], filterDelegate: (key: string | number) => any,
renderDelegate: (_: any, row: object) => any, width: string) => ({
title: title,
dataIndex: dataIndex,
key: dataIndex,
@ -127,13 +128,15 @@ export const makeNumericColumn = (title: string, dataIndex: string,
onFilter: filterDelegate ? filterDelegate(dataIndex) : null,
sorter: makeNumericSorter(dataIndex),
width: width,
render: renderDelegate,
align: 'right'
})
export const makeNumericColumnPlanFact = (title: string, dataIndex: string, filters: object[], filterDelegate: (key: string | number) => any, width: string) =>
export const makeNumericColumnPlanFact = (title: string, dataIndex: string, filters: object[],
filterDelegate: (key: string | number) => any, renderDelegate: (_: any, row: object) => any, width: string) =>
makeGroupColumn( title, [
makeNumericColumn('п', dataIndex + 'Plan', filters, filterDelegate, width),
makeNumericColumn('ф', dataIndex + 'Fact', filters, filterDelegate, width),
makeNumericColumn('п', dataIndex + 'Plan', filters, filterDelegate, renderDelegate, width),
makeNumericColumn('ф', dataIndex + 'Fact', filters, filterDelegate, renderDelegate, width),
])
type PaginationContainer = {

View File

@ -6,6 +6,10 @@ import {
makeTextColumn,
makeNumericColumnPlanFact
} from "../../components/Table";
import { invokeWebApiWrapperAsync } from '../../components/factory';
import { WellOperationStatService } from '../../services/api';
import ChartDepthToDay from '../../components/charts/ChartDepthToDay';
import WellOperationsTable from './WellOperationsTable'
import { calcAndUpdateStatsBySections, makeFilterMinMaxFunction } from "./functions";
@ -22,111 +26,19 @@ const filtersMinMax = [
const filtersSectionsType = [];
const ModalWindowButton = ({
buttonIcon,
buttonText,
modalTitle,
modalContent,
}) => {
const [isModalVisible, setIsModalVisible] = useState(false);
let content =
typeof modalContent === "string" ? (
<img src={modalContent} alt="" style={{ width: "100%" }} />
) : (
modalContent
);
return (
<>
<Button
type="secondary"
onClick={() => setIsModalVisible(true)}
icon={buttonIcon}
>
{buttonText}
</Button>
<Modal
title={modalTitle}
centered
visible={isModalVisible}
onOk={() => setIsModalVisible(false)}
onCancel={() => setIsModalVisible(false)}
width={1400}
>
{content}
</Modal>
</>
);
};
const columns = [
makeTextColumn("скв №", "caption", null, null, (_, item) => (
<Link to={`/well/${item.id}`}>{item.caption}</Link>
)),
makeTextColumn("Секция", "sectionType", filtersSectionsType),
makeNumericColumnPlanFact("Глубина", "sectionWellDepth", filtersMinMax, makeFilterMinMaxFunction),
makeNumericColumnPlanFact(
"Продолжительность",
"sectionBuildDays",
filtersMinMax,
makeFilterMinMaxFunction
), //Цикл строительства
makeNumericColumnPlanFact("МСП", "sectionRateOfPenetration", filtersMinMax, makeFilterMinMaxFunction),
makeNumericColumnPlanFact(
"Рейсовая скорость",
"sectionRouteSpeed",
filtersMinMax,
makeFilterMinMaxFunction
),
makeNumericColumnPlanFact("Спуск КНБК", "sectionBhaDownSpeed", filtersMinMax, makeFilterMinMaxFunction), //Скорость спуска КНБК
makeNumericColumnPlanFact("Подъем КНБК", "sectionBhaUpSpeed", filtersMinMax, makeFilterMinMaxFunction), //Скорость подъема КНБК
makeNumericColumnPlanFact(
"Скорость спуска ОК",
"sectionCasingDownSpeed",
filtersMinMax,
makeFilterMinMaxFunction
),
makeNumericColumnPlanFact(
"НПВ, сут",
"nonProductiveTime",
filtersMinMax,
makeFilterMinMaxFunction,
"70px"
),
{
title: "TVD",
render: (_, record) => (
<ModalWindowButton
buttonIcon={<LineChartOutlined />}
modalTitle={`График по скв.:${record.caption}`}
/>
),
//modalContent = {resources['Chart' + record.caption]}/>,
},
{
title: "Операции",
render: (_, record) => (
<ModalWindowButton
buttonIcon={<ProfileOutlined />}
modalTitle={`Операции по скв.:${record.caption}`}
/>
),
//modalContent = {resources['Table' + record.caption]},
},
{
title: "Подрядчики",
dataIndex: "companies",
render: (item) =>
item?.map((company) => <Tag color="blue">{company.caption}</Tag>),
},
];
export default function ClusterSections({ clusterData }) {
let { id } = useParams();
const [wellsStat, setWellsStat] = useState([]);
const [selectedWells, setSelectedWells] = useState([]);
const [selectedWellsKeys, setSelectedWellsKeys] = useState([]);
const [selectedWellId, setSelectedWellId] = useState([]);
const [isTVDModalVisible, setIsTVDModalVisible] = useState(false)
const [isOpsModalVisible, setIsOpsModalVisible] = useState(false)
const [tvdDataPlan, setTvdDataPlan] = useState([]);
const [tvdDataFact, setTvdDataFact] = useState([]);
const [tvdDataForecast, setTvdDataForecast] = useState([]);
const [wellOperations, setWellOperations] = useState([]);
calcAndUpdateStatsBySections(wellsStat ?? [], [
"sectionWellDepthPlan",
@ -147,6 +59,38 @@ export default function ClusterSections({ clusterData }) {
"nonProductiveTimeFact",
]);
useEffect(() => {
if (selectedWellId > 0) {
invokeWebApiWrapperAsync(
async () => {
const operations = await WellOperationStatService.getTvd(selectedWellId);
setWellOperations(operations)
const tvdPlanData = operations.map(el => {
return {key: el.plan?.id, depth: el.plan?.wellDepth, date: el.plan?.startDate}
}).filter(el => el.key)
setTvdDataPlan(tvdPlanData)
const tvdFactData = operations.map(el => {
return {key: el.fact?.id, depth: el.fact?.wellDepth, date: el.fact?.startDate}
}).filter(el => el.key)
setTvdDataFact(tvdFactData)
const tvdPredictData = operations.map(el => {
return {key: el.predict?.id, depth: el.predict?.wellDepth, date: el.predict?.startDate}
}).filter(el => el.key)
setTvdDataForecast(tvdPredictData)
},
null,
`Не удалось загрузить операции по скважине "${selectedWellId}"`,
);
}
}, [selectedWellId]);
useEffect(() => {
let rows = [];
@ -162,23 +106,23 @@ export default function ClusterSections({ clusterData }) {
sectionBuildDaysPlan: (
(new Date(section.plan?.end) - new Date(section.plan?.start)) /
(1000 * 60 * 60 * 24)
).toFixed(2),
),
sectionBuildDaysFact: (
(new Date(section.fact?.end) - new Date(section.fact?.start)) /
(1000 * 60 * 60 * 24)
).toFixed(2),
sectionRateOfPenetrationPlan: section.plan?.rop.toFixed(2),
sectionRateOfPenetrationFact: section.fact?.rop.toFixed(2),
sectionRouteSpeedPlan: section.plan?.routeSpeed.toFixed(2),
sectionRouteSpeedFact: section.fact?.routeSpeed.toFixed(2),
sectionBhaDownSpeedPlan: section.plan?.bhaDownSpeed.toFixed(2),
sectionBhaDownSpeedFact: section.fact?.bhaDownSpeed.toFixed(2),
sectionBhaUpSpeedPlan: section.plan?.bhaUpSpeed.toFixed(2),
sectionBhaUpSpeedFact: section.fact?.bhaUpSpeed.toFixed(2),
sectionCasingDownSpeedPlan: section.plan?.casingDownSpeed.toFixed(2),
sectionCasingDownSpeedFact: section.fact?.casingDownSpeed.toFixed(2),
nonProductiveTimePlan: section.plan?.nonProductiveHours.toFixed(2),
nonProductiveTimeFact: section.fact?.nonProductiveHours.toFixed(2),
),
sectionRateOfPenetrationPlan: section.plan?.rop,
sectionRateOfPenetrationFact: section.fact?.rop,
sectionRouteSpeedPlan: section.plan?.routeSpeed,
sectionRouteSpeedFact: section.fact?.routeSpeed,
sectionBhaDownSpeedPlan: section.plan?.bhaDownSpeed,
sectionBhaDownSpeedFact: section.fact?.bhaDownSpeed,
sectionBhaUpSpeedPlan: section.plan?.bhaUpSpeed,
sectionBhaUpSpeedFact: section.fact?.bhaUpSpeed,
sectionCasingDownSpeedPlan: section.plan?.casingDownSpeed,
sectionCasingDownSpeedFact: section.fact?.casingDownSpeed,
nonProductiveTimePlan: section.plan?.nonProductiveHours,
nonProductiveTimeFact: section.fact?.nonProductiveHours,
companies: well.companies,
};
@ -195,6 +139,110 @@ export default function ClusterSections({ clusterData }) {
setWellsStat(rows);
}, [id, clusterData]);
const columns = [
makeTextColumn("скв №", "caption", null, null,
(_, item) => <Link to={`/well/${item.id}`}>{item.caption ?? '-'}</Link>
),
makeTextColumn("Секция", "sectionType", filtersSectionsType, null,
(_, item) => _ ?? '-'
),
makeNumericColumnPlanFact(
"Глубина",
"sectionWellDepth",
filtersMinMax,
makeFilterMinMaxFunction,
(number) => (!Number.isNaN(number) && number !== undefined)
? number.toFixed(2)
: '-',
),
makeNumericColumnPlanFact(
"Продолжительность",
"sectionBuildDays",
filtersMinMax,
makeFilterMinMaxFunction,
(number) => (!Number.isNaN(number) && number !== undefined)
? number.toFixed(2)
: '-',
),
makeNumericColumnPlanFact(
"МСП",
"sectionRateOfPenetration",
filtersMinMax,
makeFilterMinMaxFunction,
(number) => (!Number.isNaN(number) && number !== undefined)
? number.toFixed(2)
: '-',
),
makeNumericColumnPlanFact(
"Рейсовая скорость",
"sectionRouteSpeed",
filtersMinMax,
makeFilterMinMaxFunction,
(number) => (!Number.isNaN(number) && number !== undefined)
? number.toFixed(2)
: '-',
),
makeNumericColumnPlanFact(
"Спуск КНБК",
"sectionBhaDownSpeed",
filtersMinMax,
makeFilterMinMaxFunction,
(number) => (!Number.isNaN(number) && number !== undefined)
? number.toFixed(2)
: '-',
),
makeNumericColumnPlanFact(
"Подъем КНБК",
"sectionBhaUpSpeed",
filtersMinMax,
makeFilterMinMaxFunction,
(number) => (!Number.isNaN(number) && number !== undefined)
? number.toFixed(2)
: '-',
),
makeNumericColumnPlanFact(
"Скорость спуска ОК",
"sectionCasingDownSpeed",
filtersMinMax,
makeFilterMinMaxFunction,
(number) => (!Number.isNaN(number) && number !== undefined)
? number.toFixed(2)
: '-',
),
makeNumericColumnPlanFact(
"НПВ, сут",
"nonProductiveTime",
filtersMinMax,
makeFilterMinMaxFunction,
(number) => (!Number.isNaN(number) && number !== undefined)
? number.toFixed(2)
: '-',
"70px"
),
{
title: "TVD",
render: (value) => <Button onClick={()=> {
setSelectedWellId(value.id)
setIsTVDModalVisible(true)
}}><LineChartOutlined /></Button>,
align: 'center'
},
{
title: "Операции",
render: (value) => <Button onClick={()=> {
setSelectedWellId(value.id)
setIsOpsModalVisible(true)
}}><ProfileOutlined /></Button>,
align: 'center'
},
{
title: "Подрядчики",
dataIndex: "companies",
render: (item) =>
item?.map((company) => <Tag color="blue">{company.caption}</Tag>),
},
];
const rowSelection = {
selectedRowKeys: selectedWellsKeys,
onChange: (keys, items) => {
@ -229,6 +277,33 @@ export default function ClusterSections({ clusterData }) {
scroll={{ x: true }}
pagination={false}
/>
<Modal
title='TVD'
centered
visible={isTVDModalVisible}
onCancel={() => setIsTVDModalVisible(false)}
width={1500}
footer={null}
>
<ChartDepthToDay
dataPlan={tvdDataPlan}
dataFact={tvdDataFact}
dataForecast={tvdDataForecast} />
</Modal>
<Modal
title='Операции'
centered
visible={isOpsModalVisible}
onCancel={() => setIsOpsModalVisible(false)}
width={1500}
footer={null}
>
<WellOperationsTable
wellOperations={wellOperations}
/>
</Modal>
</>
);
}

View File

@ -2,6 +2,7 @@ import { useParams } from "react-router-dom";
import { Link } from "react-router-dom";
import { useState, useEffect } from "react";
import { Table, Tag, Button, Modal } from "antd";
import { LineChartOutlined, ProfileOutlined } from "@ant-design/icons";
import {
makeTextColumn,
makeGroupColumn,
@ -25,16 +26,7 @@ const filtersMinMax = [
},
];
const filtersWellsType = [
{
text: "Наклонно-направленная",
value: "Наклонно-направленная",
},
{
text: "Горизонтальная",
value: "Горизонтальная",
},
];
const filtersWellsType = [];
export default function ClusterWells({ clusterData }) {
let { id } = useParams();
@ -47,6 +39,18 @@ export default function ClusterWells({ clusterData }) {
const [tvdDataForecast, setTvdDataForecast] = useState([]);
const [wellOperations, setWellOperations] = useState([]);
calcAndUpdateStatsBySections(wellsStat ?? [], [
"factStart",
"factEnd",
"periodPlan",
"periodFact",
"rateOfPenetrationPlan",
"rateOfPenetrationFact",
"routeSpeedPlan",
"routeSpeedFact",
"notProductiveTime",
]);
useEffect(() => {
if (selectedWellId > 0) {
invokeWebApiWrapperAsync(
@ -79,41 +83,36 @@ export default function ClusterWells({ clusterData }) {
}
}, [selectedWellId]);
calcAndUpdateStatsBySections(wellsStat ?? [], [
"factStart",
"factEnd",
"periodPlan",
"periodFact",
"rateOfPenetrationPlan",
"rateOfPenetrationFact",
"routeSpeedPlan",
"routeSpeedFact",
"notProductiveTime",
]);
useEffect(() => {
let tableData = clusterData.statsWells?.map((well) => {
if (!filtersWellsType.some((el) => el.text === well.wellType))
filtersWellsType.push({
text: well.wellType,
value: well.wellType,
});
return {
key: well.id,
id: well.id,
caption: well.caption,
wellType: well.wellType,
factStart: new Date(well.total.fact.start).toLocaleString(),
factEnd: new Date(well.total.fact.end).toLocaleString(),
factStart: well.total?.fact?.start,
factEnd: well.total?.fact?.end,
periodPlan: (
(new Date(well.total.plan.end) - new Date(well.total.plan.start)) /
(new Date(well.total?.plan?.end) - new Date(well.total?.plan?.start)) /
(1000 * 60 * 60 * 24)
).toFixed(2),
),
periodFact: (
(new Date(well.total.fact.end) - new Date(well.total.fact.start)) /
(new Date(well.total?.fact?.end) - new Date(well.total?.fact?.start)) /
(1000 * 60 * 60 * 24)
).toFixed(2),
rateOfPenetrationPlan: well.total.plan.rop.toFixed(2),
rateOfPenetrationFact: well.total.fact.rop.toFixed(2),
routeSpeedPlan: well.total.plan.routeSpeed.toFixed(2),
routeSpeedFact: well.total.fact.routeSpeed.toFixed(2),
notProductiveTimePlan: well.total.plan.nonProductiveHours.toFixed(2),
notProductiveTimeFact: well.total.fact.nonProductiveHours.toFixed(2),
),
rateOfPenetrationPlan: well.total?.plan?.rop,
rateOfPenetrationFact: well.total?.fact?.rop,
routeSpeedPlan: well.total?.plan?.routeSpeed,
routeSpeedFact: well.total?.fact?.routeSpeed,
notProductiveTimePlan: well.total?.plan?.nonProductiveHours,
notProductiveTimeFact: well.total?.fact?.nonProductiveHours,
companies: well.companies,
};
});
@ -122,31 +121,63 @@ export default function ClusterWells({ clusterData }) {
}, [id, clusterData]);
const columns = [
makeTextColumn("скв №", "caption", null, null, (_, item) => (
<Link to={`/well/${item.id}`}>{item.caption}</Link>
makeTextColumn("скв №", "caption", null, null,
(_, item) => (<Link to={`/well/${item.id}`}>{item.caption ?? '-'}</Link>
)),
makeTextColumn("Тип скв.", "wellType", filtersWellsType),
makeTextColumn("Тип скв.", "wellType", filtersWellsType, null,
(text) => text ?? '-'
),
makeGroupColumn("Фактические сроки", [
makeNumericColumn("начало", "factStart"),
makeNumericColumn("окончание", "factEnd"),
makeNumericColumn("начало", "factStart", null, null, (dateString) => !Number.isNaN(new Date(dateString).getTime()) ? new Date(dateString).toLocaleString() : '-'),
makeNumericColumn("окончание", "factEnd", null, null, (dateString) => !Number.isNaN(new Date(dateString).getTime()) ? new Date(dateString).toLocaleString() : '-'),
]),
makeNumericColumnPlanFact("Продолжительность", "period", filtersMinMax, makeFilterMinMaxFunction),
makeNumericColumnPlanFact("МСП", "rateOfPenetration", filtersMinMax, makeFilterMinMaxFunction),
makeNumericColumnPlanFact("Рейсовая скорость", "routeSpeed", filtersMinMax, makeFilterMinMaxFunction),
makeNumericColumnPlanFact("НПВ, сут", "notProductiveTime", filtersMinMax, makeFilterMinMaxFunction),
makeNumericColumnPlanFact(
"Продолжительность",
"period",
filtersMinMax,
makeFilterMinMaxFunction,
(number) => (!Number.isNaN(number) && number !== undefined)
? number.toFixed(2)
: '-'),
makeNumericColumnPlanFact(
"МСП",
"rateOfPenetration",
filtersMinMax,
makeFilterMinMaxFunction,
(number) => (!Number.isNaN(number) && number !== undefined)
? number.toFixed(2)
: '-'),
makeNumericColumnPlanFact(
"Рейсовая скорость",
"routeSpeed",
filtersMinMax,
makeFilterMinMaxFunction,
(number) => (!Number.isNaN(number) && number !== undefined)
? number.toFixed(2)
: '-'),
makeNumericColumnPlanFact(
"НПВ, сут",
"notProductiveTime",
filtersMinMax,
makeFilterMinMaxFunction,
(number) => (!Number.isNaN(number) && number !== undefined)
? number.toFixed(2)
: '-'),
{
title: "График глубина-день",
title: "TVD",
render: (value) => <Button onClick={()=> {
setSelectedWellId(value.id)
setIsTVDModalVisible(true)
}}>Открыть</Button>,
}}><LineChartOutlined /></Button>,
align: 'center'
},
{
title: "Таблица по операциям",
title: "Операции",
render: (value) => <Button onClick={()=> {
setSelectedWellId(value.id)
setIsOpsModalVisible(true)
}}>Открыть</Button>,
}}><ProfileOutlined /></Button>,
align: 'center'
},
{
title: "Подрядчики",

View File

@ -10,21 +10,43 @@ export default function WellOperationsTable({wellOperations}) {
const columns = [
makeTextColumn("Конструкция секции","sectionType"),
makeTextColumn("Операция","operationName"),
makeNumericColumnPlanFact("Глубина забоя", "depth"),
makeNumericColumnPlanFact("Часы", "durationHours"),
makeNumericColumnPlanFact("Комментарий", "comment")
makeNumericColumnPlanFact(
"Глубина забоя",
"depth",
null,
null,
(number) => (!Number.isNaN(number) && number !== undefined)
? number.toFixed(2)
: '-'
),
makeNumericColumnPlanFact(
"Часы",
"durationHours",
null,
null,
(number) => (!Number.isNaN(number) && number !== undefined)
? number.toFixed(2)
: '-'
),
makeNumericColumnPlanFact(
"Комментарий",
"comment",
null,
null,
(text) => text ?? '-'
)
];
const operations = wellOperations.map(el => {
return {
key: el.plan?.id ?? el.fact.id,
sectionType: el.plan?.wellSectionTypeName ?? el.fact?.wellSectionTypeName,
operationName: `${el.plan?.categoryName ?? el.fact?.categoryName} ${' '}
operationName: `${el.plan?.categoryName ?? el.fact?.categoryName ?? ''} ${' '}
${el.plan?.categoryInfo ?? el.fact?.categoryInfo ?? ''}`,
depthPlan: el.plan?.wellDepth?.toFixed(0) ?? '-',
depthFact: el.fact?.wellDepth?.toFixed(0) ?? '-',
durationHoursPlan: el.plan?.durationHours?.toFixed(2) ?? '-',
durationHoursFact: el.fact?.durationHours?.toFixed(2) ?? '-',
depthPlan: el.plan?.wellDepth,
depthFact: el.fact?.wellDepth,
durationHoursPlan: el.plan?.durationHours,
durationHoursFact: el.fact?.durationHours,
commentPlan: el.plan?.comment ?? '-',
commentFact: el.fact?.comment ?? '-'
}