Изменён контекст скважины, теперь передаются все данные по скважине

This commit is contained in:
goodmice 2022-08-16 10:58:22 +05:00
parent aaf0f7b523
commit f25d351349
42 changed files with 381 additions and 390 deletions

View File

@ -36,7 +36,7 @@ export const getTreeLabels = (treeData) => {
return labels return labels
} }
export const WellSelector = memo(({ idWell, value, onChange, treeData, treeLabels, ...other }) => { export const WellSelector = memo(({ value, onChange, treeData, treeLabels, ...other }) => {
const [wellsTree, setWellsTree] = useState([]) const [wellsTree, setWellsTree] = useState([])
const [wellLabels, setWellLabels] = useState([]) const [wellLabels, setWellLabels] = useState([])
@ -52,7 +52,7 @@ export const WellSelector = memo(({ idWell, value, onChange, treeData, treeLabel
'Не удалось загрузить список скважин', 'Не удалось загрузить список скважин',
'Получение списка скважин' 'Получение списка скважин'
) )
}, [idWell, treeData, treeLabels]) }, [treeData, treeLabels])
return ( return (
<TreeSelect <TreeSelect

View File

@ -1,17 +1,18 @@
import { createContext, useContext } from 'react' import { createContext, useContext } from 'react'
import { WellDto } from '@api'
/** Контекст текущего ID скважины */ /** Контекст текущей скважины */
export const IdWellContext = createContext<number | null>(null) export const WellContext = createContext<[WellDto, (well: WellDto) => void]>([{}, () => {}])
/** Контекст текущего корневого пути */ /** Контекст текущего корневого пути */
export const RootPathContext = createContext<string>('') export const RootPathContext = createContext<string>('')
/** /**
* Получает текущий ID скважины * Получение текущей скважины
* *
* @returns Текущий ID скважины, либо `null` * @returns Текущая скважина, либо `null`
*/ */
export const useIdWell = () => useContext(IdWellContext) export const useWell = () => useContext(WellContext)
/** /**
* Получает текущий корневой путь * Получает текущий корневой путь

View File

@ -1,7 +1,7 @@
import { Table as RawTable, Typography } from 'antd' import { Table as RawTable, Typography } from 'antd'
import { Fragment, memo, useCallback, useEffect, useState } from 'react' import { Fragment, memo, useCallback, useEffect, useState } from 'react'
import { useIdWell } from '@asb/context' import { useWell } from '@asb/context'
import LoaderPortal from '@components/LoaderPortal' import LoaderPortal from '@components/LoaderPortal'
import { invokeWebApiWrapperAsync } from '@components/factory' import { invokeWebApiWrapperAsync } from '@components/factory'
import { WellSelector } from '@components/selectors/WellSelector' import { WellSelector } from '@components/selectors/WellSelector'
@ -76,7 +76,7 @@ const Statistics = memo(() => {
const [cmpData, setCmpData] = useState([]) const [cmpData, setCmpData] = useState([])
const [avgRow, setAvgRow] = useState({}) const [avgRow, setAvgRow] = useState({})
const idWell = useIdWell() const [well] = useWell()
const cmpSpeedRender = useCallback((key) => (section) => { const cmpSpeedRender = useCallback((key) => (section) => {
let spanClass = '' let spanClass = ''
@ -99,14 +99,14 @@ const Statistics = memo(() => {
useEffect(() => { useEffect(() => {
invokeWebApiWrapperAsync( invokeWebApiWrapperAsync(
async () => { async () => {
const types = await WellOperationService.getSectionTypes(idWell) const types = await WellOperationService.getSectionTypes(well.id)
setSectionTypes(Object.entries(types)) setSectionTypes(Object.entries(types))
}, },
setIsPageLoading, setIsPageLoading,
`Не удалось получить типы секции`, `Не удалось получить типы секции для скважины "${well.caption}"`,
`Получение списка возможных секций`, `Получение списка возможных секций`,
) )
}, [idWell]) }, [well])
useEffect(() => { useEffect(() => {
invokeWebApiWrapperAsync( invokeWebApiWrapperAsync(
@ -197,7 +197,6 @@ const Statistics = memo(() => {
<div className={'well-selector'}> <div className={'well-selector'}>
<span className={'well-selector-label'}>Выберите скважины для расчёта средних значений:</span> <span className={'well-selector-label'}>Выберите скважины для расчёта средних значений:</span>
<WellSelector <WellSelector
idWell={idWell}
value={avgWells} value={avgWells}
style={{ flex: 100 }} style={{ flex: 100 }}
onChange={setAvgWells} onChange={setAvgWells}
@ -219,7 +218,6 @@ const Statistics = memo(() => {
<div className={'well-selector'}> <div className={'well-selector'}>
<span className={'well-selector-label'}>Выберите скважины сравнения:</span> <span className={'well-selector-label'}>Выберите скважины сравнения:</span>
<WellSelector <WellSelector
idWell={idWell}
value={cmpWells} value={cmpWells}
style={{ flex: 100 }} style={{ flex: 100 }}
onChange={setCmpWells} onChange={setCmpWells}

View File

@ -1,7 +1,7 @@
import { memo, useCallback, useEffect, useState } from 'react' import { memo, useCallback, useEffect, useState } from 'react'
import { Button, Modal, Popconfirm } from 'antd' import { Button, Modal, Popconfirm } from 'antd'
import { useIdWell } from '@asb/context' import { useWell } from '@asb/context'
import { Table } from '@components/Table' import { Table } from '@components/Table'
import LoaderPortal from '@components/LoaderPortal' import LoaderPortal from '@components/LoaderPortal'
import { invokeWebApiWrapperAsync } from '@components/factory' import { invokeWebApiWrapperAsync } from '@components/factory'
@ -15,32 +15,32 @@ export const NewParamsTable = memo(({ selectedWellsKeys }) => {
const [showParamsLoader, setShowParamsLoader] = useState(false) const [showParamsLoader, setShowParamsLoader] = useState(false)
const [isParamsModalVisible, setIsParamsModalVisible] = useState(false) const [isParamsModalVisible, setIsParamsModalVisible] = useState(false)
const idWell = useIdWell() const [well] = useWell()
useEffect(() => { useEffect(() => {
invokeWebApiWrapperAsync(async () => setParamsColumns(await getColumns(idWell))) invokeWebApiWrapperAsync(async () => setParamsColumns(await getColumns(well.id)))
}, [idWell]) }, [well])
const onParamButtonClick = useCallback(() => invokeWebApiWrapperAsync( const onParamButtonClick = useCallback(() => invokeWebApiWrapperAsync(
async () => { async () => {
setIsParamsModalVisible(true) setIsParamsModalVisible(true)
const params = await DrillParamsService.getCompositeAll(idWell) const params = await DrillParamsService.getCompositeAll(well.id)
setParams(params) setParams(params)
}, },
setShowParamsLoader, setShowParamsLoader,
`Не удалось загрузить список режимов для скважины "${idWell}"`, `Не удалось загрузить список режимов для скважины "${well.caption}"`,
'Получение списка режимов скважины' 'Получение списка режимов скважины'
), [idWell]) ), [well])
const onParamsAddClick = useCallback(() => invokeWebApiWrapperAsync( const onParamsAddClick = useCallback(() => invokeWebApiWrapperAsync(
async () => { async () => {
await DrillParamsService.save(idWell, params) await DrillParamsService.save(well.id, params)
setIsParamsModalVisible(false) setIsParamsModalVisible(false)
}, },
setShowParamsLoader, setShowParamsLoader,
`Не удалось добавить режимы в список скважины "${idWell}"`, `Не удалось добавить режимы в список скважины "${well.caption}"`,
'Добавление режима скважины' 'Добавление режима скважины'
), [idWell, params]) ), [well, params])
return ( return (
<> <>

View File

@ -3,8 +3,7 @@ import { useState, useEffect, memo, useMemo } from 'react'
import { LineChartOutlined, ProfileOutlined, TeamOutlined } from '@ant-design/icons' import { LineChartOutlined, ProfileOutlined, TeamOutlined } from '@ant-design/icons'
import { Table, Tag, Button, Badge, Divider, Modal, Row, Col } from 'antd' import { Table, Tag, Button, Badge, Divider, Modal, Row, Col } from 'antd'
import { useIdWell } from '@asb/context' import { useWell } from '@asb/context'
import { CompanyView } from '@components/views'
import LoaderPortal from '@components/LoaderPortal' import LoaderPortal from '@components/LoaderPortal'
import { invokeWebApiWrapperAsync } from '@components/factory' import { invokeWebApiWrapperAsync } from '@components/factory'
import { makeTextColumn, makeNumericColumnPlanFact, makeNumericColumn } from '@components/Table' import { makeTextColumn, makeNumericColumnPlanFact, makeNumericColumn } from '@components/Table'
@ -37,13 +36,13 @@ const WellCompositeSections = memo(({ statsWells, selectedSections }) => {
const [wellOperations, setWellOperations] = useState([]) const [wellOperations, setWellOperations] = useState([])
const [companies, setCompanies] = useState([]) const [companies, setCompanies] = useState([])
const [selectedWellsKeys, setSelectedWellsKeys] = useState([]) const [selectedWellsKeys, setSelectedWellsKeys] = useState([])
const [selectedWellId, setSelectedWellId] = useState(0) const [selectedWell, setSelectedWell] = useState(null)
const [showLoader, setShowLoader] = useState(false) const [showLoader, setShowLoader] = useState(false)
const [isTVDModalVisible, setIsTVDModalVisible] = useState(false) const [isTVDModalVisible, setIsTVDModalVisible] = useState(false)
const [isOpsModalVisible, setIsOpsModalVisible] = useState(false) const [isOpsModalVisible, setIsOpsModalVisible] = useState(false)
const [isCompaniesModalVisible, setIsCompaniesModalVisible] = useState(false) const [isCompaniesModalVisible, setIsCompaniesModalVisible] = useState(false)
const idWell = useIdWell() const [well] = useWell()
const location = useLocation() const location = useLocation()
@ -104,16 +103,16 @@ const WellCompositeSections = memo(({ statsWells, selectedSections }) => {
}, [statsWells]) }, [statsWells])
useEffect(() => { useEffect(() => {
if (isOpsModalVisible || selectedWellId <= 0) return if (isOpsModalVisible || !selectedWell) return
invokeWebApiWrapperAsync( invokeWebApiWrapperAsync(
async () => { async () => {
const { operations } = await getOperations(selectedWellId) const { operations } = await getOperations(selectedWell.id)
setWellOperations(operations) setWellOperations(operations)
}, },
setShowLoader, setShowLoader,
`Не удалось загрузить операции по скважине "${selectedWellId}"`, `Не удалось загрузить операции по скважине "${selectedWell.caption}"`,
) )
}, [selectedWellId, isOpsModalVisible]) }, [selectedWell, isOpsModalVisible])
useEffect(() => { useEffect(() => {
const selected = rows.filter((row) => selectedSections.some(section => ( const selected = rows.filter((row) => selectedSections.some(section => (
@ -128,17 +127,17 @@ const WellCompositeSections = memo(({ statsWells, selectedSections }) => {
selectedRowKeys: selectedWellsKeys, selectedRowKeys: selectedWellsKeys,
onChange: (keys, items) => invokeWebApiWrapperAsync( onChange: (keys, items) => invokeWebApiWrapperAsync(
async () => { async () => {
const selectedSections = items.map((row) => ({idWell, idWellSrc: row.id, idWellSectionType: row.sectionId})) const selectedSections = items.map((row) => ({ idWell: well.id, idWellSrc: row.id, idWellSectionType: row.sectionId}))
await WellCompositeService.save(idWell, selectedSections) await WellCompositeService.save(well.id, selectedSections)
setSelectedWells(items) setSelectedWells(items)
setSelectedWellsKeys(keys) setSelectedWellsKeys(keys)
}, },
setShowLoader, setShowLoader,
`Не удалось сохранить изменения выбранных секций для композитной скважины "${idWell}"`, `Не удалось сохранить изменения выбранных секций для композитной скважины "${well.caption}"`,
'Изменение выбранных секций скважины' 'Изменение выбранных секций скважины'
) )
}, [idWell, selectedWellsKeys]) }, [well, selectedWellsKeys])
const columns = useMemo(() => [ const columns = useMemo(() => [
makeTextColumn('скв №', 'caption', null, null, makeTextColumn('скв №', 'caption', null, null,
@ -157,7 +156,7 @@ const WellCompositeSections = memo(({ statsWells, selectedSections }) => {
title: 'TVD', title: 'TVD',
render: (value) => ( render: (value) => (
<Button onClick={() => { <Button onClick={() => {
setSelectedWellId(value.id) setSelectedWell(value)
setIsTVDModalVisible(true) setIsTVDModalVisible(true)
}}> }}>
<LineChartOutlined /> <LineChartOutlined />
@ -169,7 +168,7 @@ const WellCompositeSections = memo(({ statsWells, selectedSections }) => {
title: 'Операции', title: 'Операции',
render: (value) => ( render: (value) => (
<Button onClick={()=> { <Button onClick={()=> {
setSelectedWellId(value.id) setSelectedWell(value)
setIsOpsModalVisible(true) setIsOpsModalVisible(true)
}}> }}>
<ProfileOutlined /> <ProfileOutlined />
@ -227,7 +226,7 @@ const WellCompositeSections = memo(({ statsWells, selectedSections }) => {
width={1500} width={1500}
footer={null} footer={null}
> >
<Tvd idWell={selectedWellId} style={{ height: '80vh' }} /> <Tvd well={selectedWell} style={{ height: '80vh' }} />
</Modal> </Modal>
<Modal <Modal

View File

@ -2,7 +2,7 @@ import { useState, useEffect, memo, useMemo } from 'react'
import { Navigate, Route, Routes } from 'react-router-dom' import { Navigate, Route, Routes } from 'react-router-dom'
import { Col, Layout, Row } from 'antd' import { Col, Layout, Row } from 'antd'
import { useIdWell, useRootPath } from '@asb/context' import { useWell, useRootPath } from '@asb/context'
import { PrivateMenu } from '@components/Private' import { PrivateMenu } from '@components/Private'
import LoaderPortal from '@components/LoaderPortal' import LoaderPortal from '@components/LoaderPortal'
import WellSelector from '@components/selectors/WellSelector' import WellSelector from '@components/selectors/WellSelector'
@ -23,7 +23,7 @@ const properties = {
} }
const WellCompositeEditor = memo(() => { const WellCompositeEditor = memo(() => {
const idWell = useIdWell() const [well] = useWell()
const root = useRootPath() const root = useRootPath()
const rootPath = useMemo(() => `${root}/${properties.key}`, [root]) const rootPath = useMemo(() => `${root}/${properties.key}`, [root])
@ -37,17 +37,17 @@ const WellCompositeEditor = memo(() => {
invokeWebApiWrapperAsync( invokeWebApiWrapperAsync(
async () => { async () => {
try { try {
setSelectedSections(arrayOrDefault(await WellCompositeService.get(idWell))) setSelectedSections(arrayOrDefault(await WellCompositeService.get(well.id)))
} catch(e) { } catch(e) {
setSelectedSections([]) setSelectedSections([])
throw e throw e
} }
}, },
setShowLoader, setShowLoader,
'Не удалось загрузить список скважин', `Не удалось получить данные по скважине "${well.caption}"`,
'Получение списка скважин' 'Получение списка скважин'
) )
}, [idWell]) }, [well])
useEffect(() => { useEffect(() => {
const wellIds = selectedSections.map((value) => value.idWellSrc) const wellIds = selectedSections.map((value) => value.idWellSrc)
@ -71,11 +71,7 @@ const WellCompositeEditor = memo(() => {
<LoaderPortal show={showLoader}> <LoaderPortal show={showLoader}>
<Row align={'middle'} justify={'space-between'} wrap={false} style={{ backgroundColor: 'white' }}> <Row align={'middle'} justify={'space-between'} wrap={false} style={{ backgroundColor: 'white' }}>
<Col span={18}> <Col span={18}>
<WellSelector <WellSelector onChange={setSelectedIdWells} value={selectedIdWells} />
idWell={idWell}
onChange={setSelectedIdWells}
value={selectedIdWells}
/>
</Col> </Col>
<Col span={6}> <Col span={6}>
<PrivateMenu root={rootPath} className={'well_menu'}> <PrivateMenu root={rootPath} className={'well_menu'}>

View File

@ -42,7 +42,7 @@ const getDate = (str) => isRawDate(str) ? new Date(str).toLocaleString() : '-'
const numericRender = makeNumericRender(1) const numericRender = makeNumericRender(1)
const ClusterWells = memo(({ statsWells }) => { const ClusterWells = memo(({ statsWells }) => {
const [selectedWellId, setSelectedWellId] = useState(0) const [selectedWell, setSelectedWell] = useState(null)
const [isTVDModalVisible, setIsTVDModalVisible] = useState(false) const [isTVDModalVisible, setIsTVDModalVisible] = useState(false)
const [isOpsModalVisible, setIsOpsModalVisible] = useState(false) const [isOpsModalVisible, setIsOpsModalVisible] = useState(false)
const [isCompaniesModalVisible, setIsCompaniesModalVisible] = useState(false) const [isCompaniesModalVisible, setIsCompaniesModalVisible] = useState(false)
@ -54,20 +54,20 @@ const ClusterWells = memo(({ statsWells }) => {
const location = useLocation() const location = useLocation()
useEffect(() => { useEffect(() => {
if (!isOpsModalVisible || selectedWellId <= 0) { if (!isOpsModalVisible || !selectedWell) {
setWellOperations([]) setWellOperations([])
return return
} }
invokeWebApiWrapperAsync( invokeWebApiWrapperAsync(
async () => { async () => {
const operations = await getOperations(selectedWellId) const operations = await getOperations(selectedWell.id)
setWellOperations(operations.operations) setWellOperations(operations.operations)
}, },
setShowLoader, setShowLoader,
`Не удалось загрузить операции по скважине "${selectedWellId}"`, `Не удалось загрузить операции по скважине "${selectedWell.caption}"`,
'Получение операций по скважине' 'Получение операций по скважине'
) )
}, [selectedWellId, isOpsModalVisible]) }, [selectedWell, isOpsModalVisible])
useEffect(() => { useEffect(() => {
let data = statsWells?.map((well) => { let data = statsWells?.map((well) => {
@ -139,7 +139,7 @@ const ClusterWells = memo(({ statsWells }) => {
makeNumericColumn('НПВ, ч', 'notProductiveTimeFact', filtersMinMax, makeFilterMinMaxFunction, numericRender), makeNumericColumn('НПВ, ч', 'notProductiveTimeFact', filtersMinMax, makeFilterMinMaxFunction, numericRender),
makeColumn('TVD', 'tvd', { align: 'center', render: (_, value) => ( makeColumn('TVD', 'tvd', { align: 'center', render: (_, value) => (
<Button onClick={() => { <Button onClick={() => {
setSelectedWellId(value?.id) setSelectedWell(value)
setIsTVDModalVisible(true) setIsTVDModalVisible(true)
}}> }}>
<LineChartOutlined /> <LineChartOutlined />
@ -147,7 +147,7 @@ const ClusterWells = memo(({ statsWells }) => {
) }), ) }),
makeColumn('Операции', 'operations', { align: 'center', render: (_, value) => ( makeColumn('Операции', 'operations', { align: 'center', render: (_, value) => (
<Button onClick={() => { <Button onClick={() => {
setSelectedWellId(value?.id) setSelectedWell(value)
setIsOpsModalVisible(true) setIsOpsModalVisible(true)
}}> }}>
<ProfileOutlined /> <ProfileOutlined />
@ -183,7 +183,7 @@ const ClusterWells = memo(({ statsWells }) => {
width={1500} width={1500}
footer={null} footer={null}
> >
<Tvd style={{ minHeight: '600px' }} idWell={selectedWellId} /> <Tvd style={{ minHeight: '600px' }} well={selectedWell} />
</Modal> </Modal>
<Modal <Modal

View File

@ -1,7 +1,7 @@
import { useState, useEffect, useMemo, useCallback } from 'react' import { useState, useEffect, useMemo, useCallback } from 'react'
import { DatePicker, Input } from 'antd' import { DatePicker, Input } from 'antd'
import { useIdWell } from '@asb/context' import { useWell } from '@asb/context'
import DownloadLink from '@components/DownloadLink' import DownloadLink from '@components/DownloadLink'
import LoaderPortal from '@components/LoaderPortal' import LoaderPortal from '@components/LoaderPortal'
import { UploadForm } from '@components/UploadForm' import { UploadForm } from '@components/UploadForm'
@ -31,7 +31,7 @@ const columns = [
makeColumn('Компания', 'company', { render: (_, record) => <CompanyView company={record?.author?.company}/> }) makeColumn('Компания', 'company', { render: (_, record) => <CompanyView company={record?.author?.company}/> })
] ]
export const DocumentsTemplate = ({ idCategory, idWell: wellId, mimeTypes, headerChild, customColumns, beforeTable, onChange, tableName }) => { export const DocumentsTemplate = ({ idCategory, well: givenWell, mimeTypes, headerChild, customColumns, beforeTable, onChange, tableName }) => {
const [page, setPage] = useState(1) const [page, setPage] = useState(1)
const [filterDataRange, setFilterDataRange] = useState([]) const [filterDataRange, setFilterDataRange] = useState([])
const [filterCompanyName, setFilterCompanyName] = useState([]) const [filterCompanyName, setFilterCompanyName] = useState([])
@ -40,10 +40,10 @@ export const DocumentsTemplate = ({ idCategory, idWell: wellId, mimeTypes, heade
const [files, setFiles] = useState([]) const [files, setFiles] = useState([])
const [showLoader, setShowLoader] = useState(false) const [showLoader, setShowLoader] = useState(false)
const idwellContext = useIdWell() const [wellContext] = useWell()
const idWell = useMemo(() => wellId ?? idwellContext, [wellId, idwellContext]) const well = useMemo(() => givenWell ?? wellContext, [givenWell, wellContext])
const uploadUrl = useMemo(() => `/api/well/${idWell}/files/?idCategory=${idCategory}`, [idWell, idCategory]) const uploadUrl = useMemo(() => `/api/well/${well.id}/files/?idCategory=${idCategory}`, [well, idCategory])
const mergedColumns = useMemo(() => [...columns, ...(customColumns ?? [])], [customColumns]) const mergedColumns = useMemo(() => [...columns, ...(customColumns ?? [])], [customColumns])
const companies = useMemo(() => files.map(file => file?.author?.company?.caption).filter(Boolean).filter(unique), [files]) const companies = useMemo(() => files.map(file => file?.author?.company?.caption).filter(Boolean).filter(unique), [files])
@ -60,7 +60,7 @@ export const DocumentsTemplate = ({ idCategory, idWell: wellId, mimeTypes, heade
invokeWebApiWrapperAsync( invokeWebApiWrapperAsync(
async () => { async () => {
const paginatedFiles = await FileService.getFilesInfo( const paginatedFiles = await FileService.getFilesInfo(
idWell, well.id,
idCategory, idCategory,
filterCompanyName, filterCompanyName,
filterFileName, filterFileName,
@ -78,10 +78,10 @@ export const DocumentsTemplate = ({ idCategory, idWell: wellId, mimeTypes, heade
setPagination(newPagination) setPagination(newPagination)
}, },
setShowLoader, setShowLoader,
`Не удалось загрузить файлы по скважине "${idWell}"`, `Не удалось загрузить файлы по скважине "${well.caption}"`,
'Загрузка файла по скважине' 'Загрузка файла по скважине'
) )
}, [filterCompanyName, filterDataRange, filterFileName, idCategory, idWell, page]) }, [filterCompanyName, filterDataRange, filterFileName, idCategory, well, page])
useEffect(() => { useEffect(() => {
update() update()
@ -92,9 +92,9 @@ export const DocumentsTemplate = ({ idCategory, idWell: wellId, mimeTypes, heade
}, [files, onChange]) }, [files, onChange])
const handleFileDelete = useMemo(() => hasPermission(`File.edit${idCategory}`) && (async (file) => { const handleFileDelete = useMemo(() => hasPermission(`File.edit${idCategory}`) && (async (file) => {
await FileService.delete(idWell, file.id) await FileService.delete(well.id, file.id)
update() update()
}), [idWell, idCategory, update]) }), [well, idCategory, update])
return ( return (
<LoaderPortal show={showLoader}> <LoaderPortal show={showLoader}>

View File

@ -2,7 +2,7 @@ import { Form, Select } from 'antd'
import { FileAddOutlined } from '@ant-design/icons' import { FileAddOutlined } from '@ant-design/icons'
import { memo, useCallback, useEffect, useState } from 'react' import { memo, useCallback, useEffect, useState } from 'react'
import { useIdWell } from '@asb/context' import { useWell } from '@asb/context'
import Poprompt from '@components/selectors/Poprompt' import Poprompt from '@components/selectors/Poprompt'
import { invokeWebApiWrapperAsync } from '@components/factory' import { invokeWebApiWrapperAsync } from '@components/factory'
import { DrillingProgramService } from '@api' import { DrillingProgramService } from '@api'
@ -21,7 +21,7 @@ export const CategoryAdder = memo(({ categories, onUpdate, className, ...other }
const [showLoader, setShowLoader] = useState(false) const [showLoader, setShowLoader] = useState(false)
const [showCatLoader, setShowCatLoader] = useState(false) const [showCatLoader, setShowCatLoader] = useState(false)
const idWell = useIdWell() const [well] = useWell()
useEffect(() => { useEffect(() => {
invokeWebApiWrapperAsync( invokeWebApiWrapperAsync(
@ -39,14 +39,14 @@ export const CategoryAdder = memo(({ categories, onUpdate, className, ...other }
const onFinish = useCallback(({ categories }) => invokeWebApiWrapperAsync( const onFinish = useCallback(({ categories }) => invokeWebApiWrapperAsync(
async () => { async () => {
if (!categories) return if (!categories) return
await DrillingProgramService.addParts(idWell, categories) await DrillingProgramService.addParts(well.id, categories)
setValue([]) setValue([])
onUpdate?.() onUpdate?.()
}, },
setShowLoader, setShowLoader,
`Не удалось добавить новые категорий программы бурения`, `Не удалось добавить новые категорий программы бурения для скважины "${well.caption}"`,
`Добавление категорий программы бурения` `Добавление категорий программы бурения`
), [onUpdate, idWell]) ), [onUpdate, well])
return ( return (
<Poprompt <Poprompt

View File

@ -2,7 +2,7 @@ import { Input, Modal, Radio } from 'antd'
import { memo, useCallback, useEffect, useMemo, useState } from 'react' import { memo, useCallback, useEffect, useMemo, useState } from 'react'
import { BehaviorSubject, debounceTime, distinctUntilChanged, filter, map } from 'rxjs' import { BehaviorSubject, debounceTime, distinctUntilChanged, filter, map } from 'rxjs'
import { useIdWell } from '@asb/context' import { useWell } from '@asb/context'
import { UserView } from '@components/views' import { UserView } from '@components/views'
import LoaderPortal from '@components/LoaderPortal' import LoaderPortal from '@components/LoaderPortal'
import { invokeWebApiWrapperAsync } from '@components/factory' import { invokeWebApiWrapperAsync } from '@components/factory'
@ -30,7 +30,7 @@ export const CategoryEditor = memo(({ visible, category, onClosed }) => {
const [subject, setSubject] = useState(null) const [subject, setSubject] = useState(null)
const [needUpdate, setNeedUpdate] = useState(false) const [needUpdate, setNeedUpdate] = useState(false)
const idWell = useIdWell() const [well] = useWell()
useEffect(() => { useEffect(() => {
if (visible) if (visible)
@ -79,13 +79,13 @@ export const CategoryEditor = memo(({ visible, category, onClosed }) => {
useEffect(() => { useEffect(() => {
invokeWebApiWrapperAsync( invokeWebApiWrapperAsync(
async () => { async () => {
const allUsers = arrayOrDefault(await DrillingProgramService.getAvailableUsers(idWell)) const allUsers = arrayOrDefault(await DrillingProgramService.getAvailableUsers(well.id))
setAllUsers(allUsers) setAllUsers(allUsers)
}, },
setShowLoader, setShowLoader,
`Не удалось загрузить список доступных пользователей скважины "${idWell}"` `Не удалось загрузить список доступных пользователей скважины "${well.caption}"`
) )
}, [idWell]) }, [well])
const calcUsers = useCallback(() => { const calcUsers = useCallback(() => {
if (!visible) return if (!visible) return
@ -110,9 +110,9 @@ export const CategoryEditor = memo(({ visible, category, onClosed }) => {
if (userIdx <= -1) return if (userIdx <= -1) return
if (status === 0) { if (status === 0) {
await DrillingProgramService.removeUser(idWell, user.id, category.idFileCategory, users[userIdx].status) await DrillingProgramService.removeUser(well.id, user.id, category.idFileCategory, users[userIdx].status)
} else { } else {
await DrillingProgramService.addUser(idWell, user.id, category.idFileCategory, status) await DrillingProgramService.addUser(well.id, user.id, category.idFileCategory, status)
} }
setUsers((prevUsers) => { setUsers((prevUsers) => {
prevUsers[userIdx].status = status prevUsers[userIdx].status = status
@ -124,9 +124,10 @@ export const CategoryEditor = memo(({ visible, category, onClosed }) => {
<> <>
Не удалось изменить статус пользователя Не удалось изменить статус пользователя
<UserView user={user} /> <UserView user={user} />
для скважины "{well.caption}"
</>, </>,
`Изменение статуса пользователя` `Изменение статуса пользователя`
), [users, idWell, category.idFileCategory]) ), [users, well, category.idFileCategory])
const userColumns = useMemo(() => [ const userColumns = useMemo(() => [
makeColumn('Пользователь', 'user', { makeColumn('Пользователь', 'user', {

View File

@ -1,7 +1,7 @@
import { useCallback, useEffect, useState } from 'react' import { useCallback, useEffect, useState } from 'react'
import { Button, DatePicker, Input, Modal } from 'antd' import { Button, DatePicker, Input, Modal } from 'antd'
import { useIdWell } from '@asb/context' import { useWell } from '@asb/context'
import { CompanyView } from '@components/views' import { CompanyView } from '@components/views'
import DownloadLink from '@components/DownloadLink' import DownloadLink from '@components/DownloadLink'
import LoaderPortal from '@components/LoaderPortal' import LoaderPortal from '@components/LoaderPortal'
@ -65,7 +65,7 @@ export const CategoryHistory = ({ idCategory, visible, onClose }) => {
const [isLoading, setIsLoading] = useState(false) const [isLoading, setIsLoading] = useState(false)
const [companyName, setCompanyName] = useState('') const [companyName, setCompanyName] = useState('')
const idWell = useIdWell() const [well] = useWell()
useEffect(() => { useEffect(() => {
invokeWebApiWrapperAsync( invokeWebApiWrapperAsync(
@ -74,14 +74,14 @@ export const CategoryHistory = ({ idCategory, visible, onClose }) => {
const [begin, end] = range?.length > 1 ? [range[0].toISOString(), range[1].toISOString()] : [null, null] const [begin, end] = range?.length > 1 ? [range[0].toISOString(), range[1].toISOString()] : [null, null]
const skip = (page - 1) * pageSize const skip = (page - 1) * pageSize
const paginatedHistory = await FileService.getFilesInfo(idWell, idCategory, companyName, fileName, begin, end, skip, pageSize) const paginatedHistory = await FileService.getFilesInfo(well.caption, idCategory, companyName, fileName, begin, end, skip, pageSize)
setTotal(paginatedHistory?.count ?? 0) setTotal(paginatedHistory?.count ?? 0)
setData(arrayOrDefault(paginatedHistory?.items)) setData(arrayOrDefault(paginatedHistory?.items))
}, },
setIsLoading, setIsLoading,
`Не удалось загрузить историю категорий "${idCategory}" скважины "${idWell}"` `Не удалось загрузить историю категорий "${idCategory}" скважины "${well.caption}"`
) )
}, [idWell, idCategory, visible, range, companyName, fileName, page, pageSize]) }, [well, idCategory, visible, range, companyName, fileName, page, pageSize])
const onPaginationChange = useCallback((page, pageSize) => { const onPaginationChange = useCallback((page, pageSize) => {
setPage(page) setPage(page)

View File

@ -6,7 +6,7 @@ import {
TableOutlined, TableOutlined,
} from '@ant-design/icons' } from '@ant-design/icons'
import { useIdWell } from '@asb/context' import { useWell } from '@asb/context'
import { UserView } from '@components/views' import { UserView } from '@components/views'
import UploadForm from '@components/UploadForm' import UploadForm from '@components/UploadForm'
import DownloadLink from '@components/DownloadLink' import DownloadLink from '@components/DownloadLink'
@ -45,9 +45,9 @@ export const CategoryRender = memo(({ partData, onUpdate, onEdit, onHistory, set
file // Информация о файле file // Информация о файле
} = partData ?? {} } = partData ?? {}
const idWell = useIdWell() const [well] = useWell()
const uploadUrl = useMemo(() => `/api/well/${idWell}/drillingProgram/part/${idFileCategory}`, [idWell, idFileCategory]) const uploadUrl = useMemo(() => `/api/well/${well.id}/drillingProgram/part/${idFileCategory}`, [well, idFileCategory])
const approvedMarks = useMemo(() => file?.fileMarks?.filter((mark) => mark.idMarkType === 1), [file]) const approvedMarks = useMemo(() => file?.fileMarks?.filter((mark) => mark.idMarkType === 1), [file])
const rejectMarks = useMemo(() => file?.fileMarks?.filter((mark) => mark.idMarkType === 0), [file]) const rejectMarks = useMemo(() => file?.fileMarks?.filter((mark) => mark.idMarkType === 0), [file])
@ -57,7 +57,7 @@ export const CategoryRender = memo(({ partData, onUpdate, onEdit, onHistory, set
const onApprove = useCallback((approve = true) => (values) => invokeWebApiWrapperAsync( const onApprove = useCallback((approve = true) => (values) => invokeWebApiWrapperAsync(
async () => { async () => {
if (!file?.id || !permissionToApprove) return if (!file?.id || !permissionToApprove) return
await DrillingProgramService.addOrReplaceFileMark(idWell, { await DrillingProgramService.addOrReplaceFileMark(well.id, {
idFile: file.id, idFile: file.id,
idMarkType: approve ? 1 : 0, idMarkType: approve ? 1 : 0,
comment: values.comment comment: values.comment
@ -65,19 +65,19 @@ export const CategoryRender = memo(({ partData, onUpdate, onEdit, onHistory, set
await onUpdate?.() await onUpdate?.()
}, },
setIsLoading, setIsLoading,
`Не удалось ${approve ? 'согласовать' : 'отклонить'} документ для скважины "${idWell}"!`, `Не удалось ${approve ? 'согласовать' : 'отклонить'} документ для скважины "${well.caption}"!`,
`${approve ? 'Согласование' : 'Отклонение'} документа "${title}" скважины "${idWell}"` `${approve ? 'Согласование' : 'Отклонение'} документа "${title}" скважины "${well.caption}"`
), [idWell, setIsLoading, file, permissionToApprove, title, onUpdate]) ), [well, setIsLoading, file, permissionToApprove, title, onUpdate])
const onRemoveClick = useCallback(() => invokeWebApiWrapperAsync( const onRemoveClick = useCallback(() => invokeWebApiWrapperAsync(
async () => { async () => {
await DrillingProgramService.removeParts(idWell, [idFileCategory]) await DrillingProgramService.removeParts(well.id, [idFileCategory])
onUpdate?.() onUpdate?.()
}, },
setIsDeleting, setIsDeleting,
`Не удалось удалить категорию "${title}" для скважины "${idWell}"`, `Не удалось удалить категорию "${title}" для скважины "${well.caption}"`,
`Удаление категории "${title}" скважины "${idWell}"` `Удаление категории "${title}" скважины "${well.caption}"`
), [idWell, idFileCategory, onUpdate, title]) ), [well, idFileCategory, onUpdate, title])
const onUploadComplete = useCallback(() => { const onUploadComplete = useCallback(() => {
onUpdate?.(idFileCategory) onUpdate?.(idFileCategory)

View File

@ -10,7 +10,7 @@ import {
} from '@ant-design/icons' } from '@ant-design/icons'
import { memo, useCallback, useEffect, useMemo, useState } from 'react' import { memo, useCallback, useEffect, useMemo, useState } from 'react'
import { useIdWell } from '@asb/context' import { useWell } from '@asb/context'
import LoaderPortal from '@components/LoaderPortal' import LoaderPortal from '@components/LoaderPortal'
import { downloadFile, formatBytes, invokeWebApiWrapperAsync } from '@components/factory' import { downloadFile, formatBytes, invokeWebApiWrapperAsync } from '@components/factory'
import { arrayOrDefault, formatDate, wrapPrivateComponent } from '@utils' import { arrayOrDefault, formatDate, wrapPrivateComponent } from '@utils'
@ -49,7 +49,7 @@ const DrillingProgram = memo(() => {
const [categories, setCategories] = useState([]) const [categories, setCategories] = useState([])
const [data, setData] = useState({}) const [data, setData] = useState({})
const idWell = useIdWell() const [well] = useWell()
const { const {
idState, idState,
@ -65,8 +65,8 @@ const DrillingProgram = memo(() => {
const updateData = useCallback(async () => await invokeWebApiWrapperAsync( const updateData = useCallback(async () => await invokeWebApiWrapperAsync(
async () => { async () => {
const data = await DrillingProgramService.getState(idWell) const data = await DrillingProgramService.getState(well.id)
const categories = arrayOrDefault(await DrillingProgramService.getCategories(idWell)) const categories = arrayOrDefault(await DrillingProgramService.getCategories(well.id))
setData(data) setData(data)
setCategories(categories.filter(cat => { setCategories(categories.filter(cat => {
if (cat?.id && (cat.name || cat.shortName)) if (cat?.id && (cat.name || cat.shortName))
@ -76,8 +76,8 @@ const DrillingProgram = memo(() => {
})) }))
}, },
setShowLoader, setShowLoader,
`Не удалось загрузить название скважины "${idWell}"` `Не удалось загрузить название скважины "${well.caption}"`
), [idWell]) ), [well])
useEffect(() => { useEffect(() => {
updateData() updateData()
@ -101,12 +101,12 @@ const DrillingProgram = memo(() => {
const clearError = useCallback(() => invokeWebApiWrapperAsync( const clearError = useCallback(() => invokeWebApiWrapperAsync(
async () => { async () => {
await DrillingProgramService.clearError(idWell) await DrillingProgramService.clearError(well.id)
await updateData() await updateData()
}, },
setShowLoader, setShowLoader,
`Не удалось сбросить ошибку формирования программы бурения для скважины ${idWell}` `Не удалось сбросить ошибку формирования программы бурения для скважины ${well.caption}`
), [idWell]) ), [well])
return ( return (
<LoaderPortal show={showLoader}> <LoaderPortal show={showLoader}>

View File

@ -9,7 +9,7 @@ import {
DeleteOutlined DeleteOutlined
} from '@ant-design/icons' } from '@ant-design/icons'
import { useIdWell } from '@asb/context' import { useWell } from '@asb/context'
import LoaderPortal from '@components/LoaderPortal' import LoaderPortal from '@components/LoaderPortal'
import { invokeWebApiWrapperAsync } from '@components/factory' import { invokeWebApiWrapperAsync } from '@components/factory'
import { hasPermission, formatDate } from '@utils' import { hasPermission, formatDate } from '@utils'
@ -32,7 +32,7 @@ export const MeasureTable = memo(({ group, updateMeasuresFunc, additionalButtons
const [isTableEditing, setIsTableEditing] = useState(false) const [isTableEditing, setIsTableEditing] = useState(false)
const [editingActionName, setEditingActionName] = useState('') const [editingActionName, setEditingActionName] = useState('')
const idWell = useIdWell() const [well] = useWell()
const [measuresForm] = Form.useForm() const [measuresForm] = Form.useForm()
@ -54,15 +54,16 @@ export const MeasureTable = memo(({ group, updateMeasuresFunc, additionalButtons
setEditingColumns(switchableColumns) setEditingColumns(switchableColumns)
}, [isTableEditing, group.columns, editingActionName, displayedValues?.data, measuresForm]) }, [isTableEditing, group.columns, editingActionName, displayedValues?.data, measuresForm])
const markMeasuresAsDeleted = async () => await invokeWebApiWrapperAsync( const markMeasuresAsDeleted = useCallback(async () => await invokeWebApiWrapperAsync(
async () => { async () => {
await MeasureService.markAsDelete(idWell, displayedValues.id) await MeasureService.markAsDelete(well.id, displayedValues.id)
updateMeasuresFunc() updateMeasuresFunc()
}, },
setShowLoader, setShowLoader,
`Не удалось удалить запись ${displayedValues.id} для скважины "${idWell}"`, `Не удалось удалить запись ${displayedValues.id} для скважины "${well.caption}"`,
'Удаление записи для скважины' 'Удаление записи для скважины'
) ), [well, displayedValues, updateMeasuresFunc])
const editingDisabled = useMemo(() => disabled || !!displayedValues?.isDefaultData, [displayedValues?.isDefaultData]) const editingDisabled = useMemo(() => disabled || !!displayedValues?.isDefaultData, [displayedValues?.isDefaultData])
const deleteDisabled = useMemo(() => !hasPermission('Measure.delete') || !!displayedValues?.isDefaultData, [displayedValues?.isDefaultData]) const deleteDisabled = useMemo(() => !hasPermission('Measure.delete') || !!displayedValues?.isDefaultData, [displayedValues?.isDefaultData])
@ -76,27 +77,27 @@ export const MeasureTable = memo(({ group, updateMeasuresFunc, additionalButtons
measuresForm.validateFields() measuresForm.validateFields()
const measureParams = { const measureParams = {
idWell: idWell, idWell: well.id,
idCategory: group.idCategory, idCategory: group.idCategory,
timestamp: new Date().toISOString(), timestamp: new Date().toISOString(),
data: formData data: formData
} }
if(editingActionName === 'add') { if(editingActionName === 'add') {
await MeasureService.insert(idWell, measureParams) await MeasureService.insert(well.id, measureParams)
} else if (editingActionName === 'edit') { } else if (editingActionName === 'edit') {
measureParams.id = displayedValues.id measureParams.id = displayedValues.id
measureParams.timestamp = displayedValues.timestamp measureParams.timestamp = displayedValues.timestamp
await MeasureService.update(idWell, measureParams) await MeasureService.update(well.id, measureParams)
} }
setIsTableEditing(false) setIsTableEditing(false)
updateMeasuresFunc() updateMeasuresFunc()
}, },
setShowLoader, setShowLoader,
`Не удалось добавить/изменить запись для скаважины "${idWell}"`, `Не удалось добавить/изменить запись для скаважины "${well.caption}"`,
'Добавление/изменение записи по скважине' 'Добавление/изменение записи по скважине'
), [displayedValues?.id, displayedValues?.timestamp, editingActionName, group.idCategory, idWell, measuresForm, updateMeasuresFunc]) ), [displayedValues, editingActionName, group.idCategory, well, measuresForm, updateMeasuresFunc])
return ( return (
<> <>

View File

@ -2,7 +2,7 @@ import { useState, useEffect, memo } from 'react'
import { TableOutlined } from '@ant-design/icons' import { TableOutlined } from '@ant-design/icons'
import { Button } from 'antd' import { Button } from 'antd'
import { useIdWell } from '@asb/context' import { useWell } from '@asb/context'
import LoaderPortal from '@components/LoaderPortal' import LoaderPortal from '@components/LoaderPortal'
import { invokeWebApiWrapperAsync } from '@components/factory' import { invokeWebApiWrapperAsync } from '@components/factory'
import { wrapPrivateComponent } from '@utils' import { wrapPrivateComponent } from '@utils'
@ -49,13 +49,13 @@ const Measure = memo(() => {
const [data, setData] = useState(defaultData) const [data, setData] = useState(defaultData)
const [tableIdx, setTableIdx] = useState(-1) const [tableIdx, setTableIdx] = useState(-1)
const idWell = useIdWell() const [well] = useWell()
useEffect(() => { useEffect(() => {
invokeWebApiWrapperAsync( invokeWebApiWrapperAsync(
async () => { async () => {
if (!isMeasuresUpdating) return if (!isMeasuresUpdating) return
const measures = await MeasureService.getHisory(idWell) const measures = await MeasureService.getHisory(well.id)
setIsMeasuresUpdating(false) setIsMeasuresUpdating(false)
setData(prevData => { setData(prevData => {
@ -69,10 +69,10 @@ const Measure = memo(() => {
}) })
}, },
setShowLoader, setShowLoader,
`Не удалось загрузить последние данные по скважине ${idWell}`, `Не удалось загрузить последние данные по скважине ${well.caption}`,
'Получение последних данных телеметрий' 'Получение последних данных телеметрий'
) )
}, [idWell, isMeasuresUpdating]) }, [well, isMeasuresUpdating])
return ( return (
<LoaderPortal show={showLoader}> <LoaderPortal show={showLoader}>

View File

@ -2,7 +2,7 @@ import { DatePicker, Descriptions, Form, Input, InputNumber, Modal, Table, Tabs
import { memo, useCallback, useEffect, useState } from 'react' import { memo, useCallback, useEffect, useState } from 'react'
import moment from 'moment' import moment from 'moment'
import { useIdWell } from '@asb/context' import { useWell } from '@asb/context'
import LoaderPortal from '@components/LoaderPortal' import LoaderPortal from '@components/LoaderPortal'
import { invokeWebApiWrapperAsync } from '@components/factory' import { invokeWebApiWrapperAsync } from '@components/factory'
import { makeColumn, makeGroupColumn } from '@components/Table' import { makeColumn, makeGroupColumn } from '@components/Table'
@ -248,7 +248,7 @@ const table2Summary = () => (
const makeItem = (name, label) => ({ name, label }) const makeItem = (name, label) => ({ name, label })
const renderDescriptions = (items) => items.map(({ name, label }) => ( const renderDescriptions = (items) => items.map(({ name, label }) => (
<Descriptions.Item label={label}> <Descriptions.Item key={`${name}`} label={label}>
<Item name={name}> <Item name={name}>
<Input style={{ width: '100%' }} /> <Input style={{ width: '100%' }} />
</Item> </Item>
@ -289,7 +289,7 @@ export const ReportEditor = memo(({ visible, data, onDone, onCancel, checkIsDate
const [isInvalid, setIsInvalid] = useState(false) const [isInvalid, setIsInvalid] = useState(false)
const [isLoading, setIsLoading] = useState(false) const [isLoading, setIsLoading] = useState(false)
const idWell = useIdWell() const [well] = useWell()
const setFields = useCallback((data) => const setFields = useCallback((data) =>
form.setFieldsValue(data ? { form.setFieldsValue(data ? {
@ -315,20 +315,20 @@ export const ReportEditor = memo(({ visible, data, onDone, onCancel, checkIsDate
const onFormFinish = useCallback((formData) => invokeWebApiWrapperAsync( const onFormFinish = useCallback((formData) => invokeWebApiWrapperAsync(
async () => { async () => {
const payload = Object.fromEntries(names.map(([head, names]) => [head, Object.fromEntries(names.map((name) => [name, formData[name]]))])) const payload = Object.fromEntries(names.map(([head, names]) => [head, Object.fromEntries(names.map((name) => [name, formData[name]]))]))
if (data) await DailyReportService.update(idWell, data.head.reportDate, payload) if (data) await DailyReportService.update(well.id, data.head.reportDate, payload)
else await DailyReportService.add(idWell, payload) else await DailyReportService.add(well.id, payload)
onDone?.(formData) onDone?.(formData)
form.resetFields() form.resetFields()
}, },
setIsLoading, setIsLoading,
'Не удалось сохранить суточный рапорт', `Не удалось сохранить суточный рапорт для скважины "${well.caption}"`,
'Сохранение суточного рапорта' 'Сохранение суточного рапорта'
), [data, onDone, idWell, form]) ), [data, onDone, well, form])
const onDateChange = useCallback((date) => invokeWebApiWrapperAsync( const onDateChange = useCallback((date) => invokeWebApiWrapperAsync(
async () => { async () => {
if (data) return if (data) return
const newData = await DailyReportService.getOrGenerate(idWell, date.format('YYYY-MM-DD') + 'Z') const newData = await DailyReportService.getOrGenerate(well.id, date.format('YYYY-MM-DD') + 'Z')
if (checkIsDateBusy(moment(newData.reportDate))) if (checkIsDateBusy(moment(newData.reportDate)))
throw new Error('Рапорт на данную дату уже существует') throw new Error('Рапорт на данную дату уже существует')
setFields(newData) setFields(newData)
@ -336,7 +336,7 @@ export const ReportEditor = memo(({ visible, data, onDone, onCancel, checkIsDate
setIsLoading, setIsLoading,
(e) => `Не удалось загрузить автозаполняемые данные для нового рапорта: ${e}`, (e) => `Не удалось загрузить автозаполняемые данные для нового рапорта: ${e}`,
'Получение автозаполняемых данных суточного рапорта' 'Получение автозаполняемых данных суточного рапорта'
), [idWell, data, setFields, checkIsDateBusy]) ), [well, data, setFields, checkIsDateBusy])
return ( return (
<Modal <Modal

View File

@ -3,7 +3,7 @@ import { FileExcelOutlined, EditOutlined, PlusOutlined } from '@ant-design/icons
import { Button } from 'antd' import { Button } from 'antd'
import moment from 'moment' import moment from 'moment'
import { useIdWell } from '@asb/context' import { useWell } from '@asb/context'
import LoaderPortal from '@components/LoaderPortal' import LoaderPortal from '@components/LoaderPortal'
import { DateRangeWrapper, Table, makeDateColumn, makeColumn } from '@components/Table' import { DateRangeWrapper, Table, makeDateColumn, makeColumn } from '@components/Table'
import { download, invokeWebApiWrapperAsync } from '@components/factory' import { download, invokeWebApiWrapperAsync } from '@components/factory'
@ -19,17 +19,17 @@ const DailyReport = memo(() => {
const [selectedReport, setSelectedReport] = useState(null) const [selectedReport, setSelectedReport] = useState(null)
const [isEditorVisible, setIsEditorVisible] = useState(false) const [isEditorVisible, setIsEditorVisible] = useState(false)
const idWell = useIdWell() const [well] = useWell()
const updateTable = useCallback(() => invokeWebApiWrapperAsync( const updateTable = useCallback(() => invokeWebApiWrapperAsync(
async () => { async () => {
const data = arrayOrDefault(await DailyReportService.getList(idWell)) const data = arrayOrDefault(await DailyReportService.getList(well.id))
setData(data.map((row) => ({ ...row, reportDate: row.head.reportDate }))) setData(data.map((row, i) => ({ ...row, reportDate: row.head.reportDate })))
}, },
setIsLoading, setIsLoading,
'Не удалось загрузить список суточных рапортов', `Не удалось загрузить список суточных рапортов для скважины "${well.caption}"`,
'Получение списка суточных рапортов', 'Получение списка суточных рапортов',
), [idWell]) ), [well])
useEffect(() => { useEffect(() => {
updateTable() updateTable()
@ -44,7 +44,7 @@ const DailyReport = memo(() => {
<Button <Button
type={'link'} type={'link'}
icon={<FileExcelOutlined />} icon={<FileExcelOutlined />}
onClick={async () => await download(`/api/well/${idWell}/DailyReport/${report.reportDate}/excel`)} onClick={async () => await download(`/api/well/${well.id}/DailyReport/${report.reportDate}/excel`)}
children={'Скачать XLSX'} children={'Скачать XLSX'}
/> />
<Button <Button
@ -58,7 +58,7 @@ const DailyReport = memo(() => {
/> />
</> </>
)}), )}),
], [idWell]) ], [well])
const filteredData = useMemo(() => { const filteredData = useMemo(() => {
if (!searchDate) return data if (!searchDate) return data

View File

@ -2,7 +2,7 @@ import { Button, Tooltip } from 'antd'
import { useState, useEffect, memo } from 'react' import { useState, useEffect, memo } from 'react'
import { FilePdfOutlined, FileTextOutlined } from '@ant-design/icons' import { FilePdfOutlined, FileTextOutlined } from '@ant-design/icons'
import { useIdWell } from '@asb/context' import { useWell } from '@asb/context'
import LoaderPortal from '@components/LoaderPortal' import LoaderPortal from '@components/LoaderPortal'
import { Table, makeDateSorter, makeNumericSorter } from '@components/Table' import { Table, makeDateSorter, makeNumericSorter } from '@components/Table'
import { invokeWebApiWrapperAsync, downloadFile } from '@components/factory' import { invokeWebApiWrapperAsync, downloadFile } from '@components/factory'
@ -60,20 +60,20 @@ export const Reports = memo(() => {
const [reports, setReports] = useState([]) const [reports, setReports] = useState([])
const [showLoader, setShowLoader] = useState(false) const [showLoader, setShowLoader] = useState(false)
const idWell = useIdWell() const [well] = useWell()
useEffect(() => { useEffect(() => {
invokeWebApiWrapperAsync( invokeWebApiWrapperAsync(
async () => { async () => {
const reportsResponse = await ReportService.getAllReportsNamesByWell(idWell) const reportsResponse = await ReportService.getAllReportsNamesByWell(well.id)
const reports = reportsResponse.map(r => ({ ...r, key: r.id ?? r.name ?? r.date })) const reports = reportsResponse.map(r => ({ ...r, key: r.id ?? r.name ?? r.date }))
setReports(reports) setReports(reports)
}, },
setShowLoader, setShowLoader,
`Не удалось загрузить список рапортов по скважине "${idWell}"`, `Не удалось загрузить список рапортов по скважине "${well.caption}"`,
'Получение списка рапортов' 'Получение списка рапортов'
) )
}, [idWell]) }, [well])
return ( return (
<LoaderPortal show={showLoader}> <LoaderPortal show={showLoader}>

View File

@ -3,11 +3,11 @@ import moment from 'moment'
import { useState, useEffect, memo, useCallback } from 'react' import { useState, useEffect, memo, useCallback } from 'react'
import { Radio, Button, Select, notification } from 'antd' import { Radio, Button, Select, notification } from 'antd'
import { useIdWell } from '@asb/context' import { useWell } from '@asb/context'
import { DateRangeWrapper } from 'components/Table' import { DateRangeWrapper } from 'components/Table'
import { LoaderPortal } from '@components/LoaderPortal' import { LoaderPortal } from '@components/LoaderPortal'
import { invokeWebApiWrapperAsync } from '@components/factory' import { invokeWebApiWrapperAsync } from '@components/factory'
import { wrapPrivateComponent } from '@utils' import { formatDate, wrapPrivateComponent } from '@utils'
import { Subscribe } from '@services/signalr' import { Subscribe } from '@services/signalr'
import { ReportService } from '@api' import { ReportService } from '@api'
@ -27,8 +27,6 @@ const timePeriodNames = [
{ label: '1 неделя', value: 604800 }, { label: '1 неделя', value: 604800 },
] ]
const dateTimeFormat = 'DD.MM.YYYY hh:mm:ss'
const reportFormats = [ const reportFormats = [
{ value: 0, label: 'PDF' }, { value: 0, label: 'PDF' },
{ value: 1, label: 'LAS' }, { value: 1, label: 'LAS' },
@ -45,12 +43,12 @@ const DiagramReport = memo(() => {
const [pagesCount, setPagesCount] = useState(0) const [pagesCount, setPagesCount] = useState(0)
const [showLoader, setShowLoader] = useState(false) const [showLoader, setShowLoader] = useState(false)
const idWell = useIdWell() const [well] = useWell()
const handleReportCreation = useCallback(async () => await invokeWebApiWrapperAsync( const handleReportCreation = useCallback(async () => await invokeWebApiWrapperAsync(
async () => { async () => {
const taskId = await ReportService.createReport( const taskId = await ReportService.createReport(
idWell, well.id,
step, step,
format, format,
filterDateRange[0].toISOString(), filterDateRange[0].toISOString(),
@ -79,11 +77,11 @@ const DiagramReport = memo(() => {
}) })
}, },
setShowLoader, setShowLoader,
`Не удалось создать отчет по скважине (${idWell}) c `Не удалось создать отчет по скважине "${well.caption}" c
${filterDateRange[0].format(dateTimeFormat)} по ${formatDate(filterDateRange[0])} по
${filterDateRange[1].format(dateTimeFormat)}`, ${formatDate(filterDateRange[1])}`,
'Создание отчёта по скважине' 'Создание отчёта по скважине'
), [filterDateRange, format, idWell, step]) ), [filterDateRange, format, well, step])
const disabledDate = useCallback((current) => const disabledDate = useCallback((current) =>
!current.isBetween(aviableDateRange[0], aviableDateRange[1], 'seconds', '[]') !current.isBetween(aviableDateRange[0], aviableDateRange[1], 'seconds', '[]')
@ -92,7 +90,7 @@ const DiagramReport = memo(() => {
useEffect(() => { useEffect(() => {
invokeWebApiWrapperAsync( invokeWebApiWrapperAsync(
async () => { async () => {
const datesRangeResponse = await ReportService.getReportsDateRange(idWell) const datesRangeResponse = await ReportService.getReportsDateRange(well.id)
if (!datesRangeResponse?.from || !datesRangeResponse.to) if (!datesRangeResponse?.from || !datesRangeResponse.to)
throw new Error('Формат ответа неверный!') throw new Error('Формат ответа неверный!')
@ -110,17 +108,17 @@ const DiagramReport = memo(() => {
]) ])
}, },
setShowLoader, setShowLoader,
`Не удалось получить диапозон дат рапортов для скважины "${idWell}"`, `Не удалось получить диапозон дат рапортов для скважины "${well.caption}"`,
'Получение диапозона дат рапортов' 'Получение диапозона дат рапортов'
) )
}, [idWell]) }, [well])
useEffect(() => { useEffect(() => {
invokeWebApiWrapperAsync( invokeWebApiWrapperAsync(
async () => { async () => {
if (filterDateRange?.length !== 2) return if (filterDateRange?.length !== 2) return
const pagesCount = await ReportService.getReportSize( const pagesCount = await ReportService.getReportSize(
idWell, well.id,
step, step,
format, format,
filterDateRange[0].toISOString(), filterDateRange[0].toISOString(),
@ -130,11 +128,11 @@ const DiagramReport = memo(() => {
}, },
setShowLoader, setShowLoader,
`Не удалось получить предварительные параметры отчета c `Не удалось получить предварительные параметры отчета c
${filterDateRange[0].format(dateTimeFormat)} по ${formatDate(filterDateRange[0])} по
${filterDateRange[1].format(dateTimeFormat)}`, ${formatDate(filterDateRange[1])}`,
'Получение размера рапортов' 'Получение размера рапортов'
) )
}, [filterDateRange, step, format, idWell]) }, [filterDateRange, step, format, well])
return ( return (
<div> <div>

View File

@ -3,7 +3,7 @@ import { useState, useEffect, memo, useCallback, useMemo } from 'react'
import { useSearchParams } from 'react-router-dom' import { useSearchParams } from 'react-router-dom'
import { Select } from 'antd' import { Select } from 'antd'
import { useIdWell } from '@asb/context' import { useWell } from '@asb/context'
import { Flex } from '@components/Grid' import { Flex } from '@components/Grid'
import { D3MonitoringCharts } from '@components/d3/monitoring' import { D3MonitoringCharts } from '@components/d3/monitoring'
import { CopyUrlButton } from '@components/CopyUrl' import { CopyUrlButton } from '@components/CopyUrl'
@ -109,7 +109,7 @@ const Archive = memo(() => {
const [showLoader, setShowLoader] = useState(false) const [showLoader, setShowLoader] = useState(false)
const [loaded, setLoaded] = useState(null) const [loaded, setLoaded] = useState(null)
const idWell = useIdWell() const [well] = useWell()
const [search, setSearchParams] = useSearchParams() const [search, setSearchParams] = useSearchParams()
const getInitialRange = useCallback(() => parseInt(search.get('range') ?? defaultPeriod) * 1000, [search]) const getInitialRange = useCallback(() => parseInt(search.get('range') ?? defaultPeriod) * 1000, [search])
@ -167,7 +167,7 @@ const Archive = memo(() => {
useEffect(() => { useEffect(() => {
invokeWebApiWrapperAsync( invokeWebApiWrapperAsync(
async () => { async () => {
let dates = await TelemetryDataSaubService.getDataDatesRange(idWell) let dates = await TelemetryDataSaubService.getDataDatesRange(well.id)
dates = { dates = {
from: new Date(dates?.from ?? 0), from: new Date(dates?.from ?? 0),
to: new Date(dates?.to ?? 0) to: new Date(dates?.to ?? 0)
@ -175,10 +175,10 @@ const Archive = memo(() => {
setDateLimit(dates) setDateLimit(dates)
}, },
setShowLoader, setShowLoader,
`Не удалось загрузить диапозон телеметрии для скважины "${idWell}"`, `Не удалось загрузить диапозон телеметрии для скважины "${well.caption}"`,
'Загрузка диапозона телеметрии' 'Загрузка диапозона телеметрии'
) )
}, []) }, [well])
useEffect(() => { useEffect(() => {
setStartDate((prev) => new Date(Math.max(dateLimit.from, Math.min(+prev, +dateLimit.to - chartInterval)))) setStartDate((prev) => new Date(Math.max(dateLimit.from, Math.min(+prev, +dateLimit.to - chartInterval))))
@ -190,7 +190,7 @@ const Archive = memo(() => {
if (loadingInterval <= 0) return if (loadingInterval <= 0) return
invokeWebApiWrapperAsync( invokeWebApiWrapperAsync(
async () => { async () => {
const data = await TelemetryDataSaubService.getData(idWell, loadingStartDate.toISOString(), loadingInterval, DATA_COUNT) const data = await TelemetryDataSaubService.getData(well.id, loadingStartDate.toISOString(), loadingInterval, DATA_COUNT)
const loadedStartDate = new Date(Math.max(+newLoaded.start, +startDate - chartInterval * ADDITIVE_PAGES)) const loadedStartDate = new Date(Math.max(+newLoaded.start, +startDate - chartInterval * ADDITIVE_PAGES))
const loadedEndDate = new Date(Math.min(+newLoaded.end, +startDate + chartInterval * (ADDITIVE_PAGES + 1))) const loadedEndDate = new Date(Math.min(+newLoaded.end, +startDate + chartInterval * (ADDITIVE_PAGES + 1)))
@ -207,10 +207,10 @@ const Archive = memo(() => {
}, },
setShowLoader, setShowLoader,
`Не удалось загрузить данные по скважине "${idWell}" c ${startDate.toISOString()} по ${new Date(+startDate + chartInterval).toISOString()}`, `Не удалось загрузить данные по скважине "${well.caption}" c ${formatDate(startDate)} по ${formatDate(+startDate + chartInterval)}`,
'Загрузка телеметрий в диапозоне' 'Загрузка телеметрий в диапозоне'
) )
}, [idWell, chartInterval, loaded, startDate]) }, [well, chartInterval, loaded, startDate])
const onRangeChange = useCallback((value) => { const onRangeChange = useCallback((value) => {
setChartInterval(value * 1000) setChartInterval(value * 1000)

View File

@ -3,7 +3,7 @@ import { useNavigate } from 'react-router-dom'
import { CloseOutlined } from '@ant-design/icons' import { CloseOutlined } from '@ant-design/icons'
import { Button, Menu, Popconfirm } from 'antd' import { Button, Menu, Popconfirm } from 'antd'
import { useIdWell, useRootPath } from '@asb/context' import { useWell, useRootPath } from '@asb/context'
import LoaderPortal from '@components/LoaderPortal' import LoaderPortal from '@components/LoaderPortal'
import { invokeWebApiWrapperAsync } from '@components/factory' import { invokeWebApiWrapperAsync } from '@components/factory'
import { BaseWidget, WidgetSettingsWindow } from '@components/widgets' import { BaseWidget, WidgetSettingsWindow } from '@components/widgets'
@ -112,7 +112,7 @@ const DashboardNNB = memo(({ enableEditing = false }) => {
const [selectedSettings, setSelectedSettings] = useState(null) const [selectedSettings, setSelectedSettings] = useState(null)
const [values, setValues] = useState({}) const [values, setValues] = useState({})
const idWell = useIdWell() const [well] = useWell()
const root = useRootPath() const root = useRootPath()
const rootPath = useMemo(() => `${root}/dashboard_nnb`, [root]) const rootPath = useMemo(() => `${root}/dashboard_nnb`, [root])
const navigate = useNavigate() const navigate = useNavigate()
@ -151,18 +151,18 @@ const DashboardNNB = memo(({ enableEditing = false }) => {
useEffect(() => { useEffect(() => {
invokeWebApiWrapperAsync( invokeWebApiWrapperAsync(
async () => { async () => {
handleData(await WitsRecord1Service.getLastData(idWell), '1') handleData(await WitsRecord1Service.getLastData(well.id), '1')
handleData(await WitsRecord7Service.getLastData(idWell), '7') handleData(await WitsRecord7Service.getLastData(well.id), '7')
handleData(await WitsRecord8Service.getLastData(idWell), '8') handleData(await WitsRecord8Service.getLastData(well.id), '8')
handleData(await WitsRecord50Service.getLastData(idWell), '50') handleData(await WitsRecord50Service.getLastData(well.id), '50')
handleData(await WitsRecord60Service.getLastData(idWell), '60') handleData(await WitsRecord60Service.getLastData(well.id), '60')
handleData(await WitsRecord61Service.getLastData(idWell), '61') handleData(await WitsRecord61Service.getLastData(well.id), '61')
}, },
setIsLoading, setIsLoading,
'Не удалось загрузить последние данные', `Не удалось загрузить последние данные по скважине ${well.caption}`,
'Получение данных WITS', 'Получение данных WITS',
) )
return Subscribe('hubs/telemetry', `well_${idWell}_wits`, return Subscribe('hubs/telemetry', `well_${well.id}_wits`,
{ methodName: 'ReceiveWitsRecord1', handler: (data) => handleData(data, '1') }, { methodName: 'ReceiveWitsRecord1', handler: (data) => handleData(data, '1') },
{ methodName: 'ReceiveWitsRecord7', handler: (data) => handleData(data, '7') }, { methodName: 'ReceiveWitsRecord7', handler: (data) => handleData(data, '7') },
{ methodName: 'ReceiveWitsRecord8', handler: (data) => handleData(data, '8') }, { methodName: 'ReceiveWitsRecord8', handler: (data) => handleData(data, '8') },
@ -170,7 +170,7 @@ const DashboardNNB = memo(({ enableEditing = false }) => {
{ methodName: 'ReceiveWitsRecord60', handler: (data) => handleData(data, '60') }, { methodName: 'ReceiveWitsRecord60', handler: (data) => handleData(data, '60') },
{ methodName: 'ReceiveWitsRecord61', handler: (data) => handleData(data, '61') }, { methodName: 'ReceiveWitsRecord61', handler: (data) => handleData(data, '61') },
) )
}, [idWell, handleData]) }, [well, handleData])
const addGroup = useCallback((values) => dispatchGroups({ type: 'add_group', value: { name: values.groupName } }), []) const addGroup = useCallback((values) => dispatchGroups({ type: 'add_group', value: { name: values.groupName } }), [])

View File

@ -4,7 +4,7 @@ import { LinkOutlined } from '@ant-design/icons'
import { Link } from 'react-router-dom' import { Link } from 'react-router-dom'
import moment from 'moment' import moment from 'moment'
import { useIdWell } from '@asb/context' import { useWell } from '@asb/context'
import LoaderPortal from '@components/LoaderPortal' import LoaderPortal from '@components/LoaderPortal'
import { invokeWebApiWrapperAsync } from '@components/factory' import { invokeWebApiWrapperAsync } from '@components/factory'
import { makeColumn, makeDateColumn, makeNumericColumn, makeNumericSorter, makeTextColumn, Table } from '@components/Table' import { makeColumn, makeDateColumn, makeNumericColumn, makeNumericSorter, makeTextColumn, Table } from '@components/Table'
@ -69,18 +69,18 @@ const Messages = memo(() => {
const [searchString, setSearchString] = useState('') const [searchString, setSearchString] = useState('')
const [showLoader, setShowLoader] = useState(false) const [showLoader, setShowLoader] = useState(false)
const idWell = useIdWell() const [well] = useWell()
const onChangeSearchString = useCallback((message) => setSearchString(message.length > 2 ? message : ''), []) const onChangeSearchString = useCallback((message) => setSearchString(message.length > 2 ? message : ''), [])
const columns = useMemo(() => makeMessageColumns(idWell), [idWell]) const columns = useMemo(() => makeMessageColumns(well.id), [well])
useEffect(() => { useEffect(() => {
invokeWebApiWrapperAsync( invokeWebApiWrapperAsync(
async () => { async () => {
const [begin, end] = range?.length > 1 ? [range[0].toISOString(), range[1].toISOString()] : [null, null] const [begin, end] = range?.length > 1 ? [range[0].toISOString(), range[1].toISOString()] : [null, null]
const skip = (page - 1) * pageSize const skip = (page - 1) * pageSize
const paginatedMessages = await MessageService.getMessages(idWell, skip, pageSize, categories, begin, end, searchString) const paginatedMessages = await MessageService.getMessages(well.id, skip, pageSize, categories, begin, end, searchString)
if (!paginatedMessages) return if (!paginatedMessages) return
setMessages(paginatedMessages.items.map(m => ({ setMessages(paginatedMessages.items.map(m => ({
@ -95,10 +95,10 @@ const Messages = memo(() => {
}) })
}, },
setShowLoader, setShowLoader,
`Не удалось загрузить сообщения по скважине "${idWell}"`, `Не удалось загрузить сообщения по скважине "${well.caption}"`,
'Полученик списка сообщений' 'Полученик списка сообщений'
) )
}, [idWell, page, categories, range, searchString]) }, [well, page, categories, range, searchString])
return ( return (
<> <>

View File

@ -1,7 +1,7 @@
import { memo, useCallback, useEffect, useMemo, useState } from 'react' import { memo, useCallback, useEffect, useMemo, useState } from 'react'
import { Button, Modal } from 'antd' import { Button, Modal } from 'antd'
import { useIdWell } from '@asb/context' import { useWell } from '@asb/context'
import { import {
makeTimeColumn, makeTimeColumn,
makeGroupColumn, makeGroupColumn,
@ -25,17 +25,17 @@ export const DrillerSchedule = memo(({ drillers, loading, onChange }) => {
const [showLoader, setShowLoader] = useState(false) const [showLoader, setShowLoader] = useState(false)
const [schedule, setSchedule] = useState([]) const [schedule, setSchedule] = useState([])
const idWell = useIdWell() const [well] = useWell()
const updateSchedule = useCallback(async () => invokeWebApiWrapperAsync( const updateSchedule = useCallback(async () => invokeWebApiWrapperAsync(
async () => { async () => {
const schedule = arrayOrDefault(await ScheduleService.getByIdWell(idWell)) const schedule = arrayOrDefault(await ScheduleService.getByIdWell(well.id))
setSchedule(schedule) setSchedule(schedule)
}, },
setShowLoader, setShowLoader,
'Не удалось загрузить расписания', `Не удалось загрузить расписания по скважине "${well.caption}"`,
'Получение списка расписаний', 'Получение списка расписаний',
), [idWell]) ), [well])
const onModalOpen = useCallback(() => { const onModalOpen = useCallback(() => {
setScheduleModalVisible(true) setScheduleModalVisible(true)
@ -45,7 +45,7 @@ export const DrillerSchedule = memo(({ drillers, loading, onChange }) => {
setScheduleModalVisible(false) setScheduleModalVisible(false)
}, []) }, [])
const recordParser = useCallback((record) => ({ ...record, idWell }), [idWell]) const recordParser = useCallback((record) => ({ ...record, idWell: well.id }), [well])
const isLoading = useMemo(() => loading || showLoader, [loading, showLoader]) const isLoading = useMemo(() => loading || showLoader, [loading, showLoader])

View File

@ -1,7 +1,7 @@
import { memo, useCallback, useEffect, useMemo, useState } from 'react' import { memo, useCallback, useEffect, useMemo, useState } from 'react'
import { Button, Modal } from 'antd' import { Button, Modal } from 'antd'
import { useIdWell } from '@asb/context' import { useWell } from '@asb/context'
import { invokeWebApiWrapperAsync } from '@components/factory' import { invokeWebApiWrapperAsync } from '@components/factory'
import { EditableTable, makeGroupColumn, makeNumericColumn, makeNumericRender, makeSelectColumn } from '@components/Table' import { EditableTable, makeGroupColumn, makeNumericColumn, makeNumericRender, makeSelectColumn } from '@components/Table'
import { DetectedOperationService, OperationValueService } from '@api' import { DetectedOperationService, OperationValueService } from '@api'
@ -21,22 +21,22 @@ export const TargetEditor = memo(({ loading, onChange }) => {
const [showLoader, setShowLoader] = useState(false) const [showLoader, setShowLoader] = useState(false)
const [targetColumns, setTargetColumns] = useState([]) const [targetColumns, setTargetColumns] = useState([])
const idWell = useIdWell() const [well] = useWell()
const updateTable = useCallback(async () => invokeWebApiWrapperAsync( const updateTable = useCallback(async () => invokeWebApiWrapperAsync(
async () => { async () => {
const targets = arrayOrDefault(await OperationValueService.getByIdWell(idWell)) const targets = arrayOrDefault(await OperationValueService.getByIdWell(well.id))
setTargets(targets) setTargets(targets)
}, },
setShowLoader, setShowLoader,
'Не удалось загрузить цели', `Не удалось загрузить цели для скважины "${well.caption}"`,
'Получение списка целей', 'Получение списка целей',
), [idWell]) ), [well])
const onModalOpen = useCallback(() => setShowModal(true), []) const onModalOpen = useCallback(() => setShowModal(true), [])
const onModalCancel = useCallback(() => setShowModal(false), []) const onModalCancel = useCallback(() => setShowModal(false), [])
const recordParser = useCallback((record) => ({ ...record, idWell }), [idWell]) const recordParser = useCallback((record) => ({ ...record, idWell: well.id }), [well.id])
const onTargetChange = useCallback(() => { const onTargetChange = useCallback(() => {
updateTable() updateTable()
@ -81,10 +81,10 @@ export const TargetEditor = memo(({ loading, onChange }) => {
]) ])
}, },
setShowLoader, setShowLoader,
`Не удалось получить список категорий целей`, `Не удалось получить список категорий целей для скважины "${well.caption}"`,
'Получение списка категорий целей' 'Получение списка категорий целей'
) )
}, [idWell]) }, [well])
useEffect(() => { useEffect(() => {
updateTable() updateTable()

View File

@ -2,7 +2,7 @@ import { memo, useCallback, useEffect, useMemo, useState } from 'react'
import { Empty, InputNumber, Select } from 'antd' import { Empty, InputNumber, Select } from 'antd'
import moment from 'moment' import moment from 'moment'
import { useIdWell } from '@asb/context' import { useWell } from '@asb/context'
import LoaderPortal from '@components/LoaderPortal' import LoaderPortal from '@components/LoaderPortal'
import { DateRangeWrapper } from '@components/Table' import { DateRangeWrapper } from '@components/Table'
import { invokeWebApiWrapperAsync } from '@components/factory' import { invokeWebApiWrapperAsync } from '@components/factory'
@ -28,7 +28,7 @@ const Operations = memo(() => {
const [selectedCategory, setSelectedCategory] = useState(14) const [selectedCategory, setSelectedCategory] = useState(14)
const [categories, setCategories] = useState() const [categories, setCategories] = useState()
const idWell = useIdWell() const [well] = useWell()
const permissions = useMemo(() => getPermissions('Driller.get', 'DetectedOperation.get', 'OperationValue.get'), []) const permissions = useMemo(() => getPermissions('Driller.get', 'DetectedOperation.get', 'OperationValue.get'), [])
@ -53,13 +53,13 @@ const Operations = memo(() => {
const updateData = useCallback(async () => invokeWebApiWrapperAsync( const updateData = useCallback(async () => invokeWebApiWrapperAsync(
async () => { async () => {
if (!dates) return if (!dates) return
const data = await DetectedOperationService.get(idWell, selectedCategory, dates[0].toISOString(), dates[1].toISOString()) const data = await DetectedOperationService.get(well.id, selectedCategory, dates[0].toISOString(), dates[1].toISOString())
setData(data) setData(data)
}, },
setIsLoading, setIsLoading,
'Не удалось загрузить список определённых операций', `Не удалось загрузить список определённых операций по скважине "${well.caption}"`,
'Получение списка определённых операций', 'Получение списка определённых операций',
), [idWell, dates, selectedCategory]) ), [well, dates, selectedCategory])
useEffect(() => { useEffect(() => {
if (permissions.driller.get) if (permissions.driller.get)
@ -84,7 +84,7 @@ const Operations = memo(() => {
useEffect(() => { useEffect(() => {
invokeWebApiWrapperAsync( invokeWebApiWrapperAsync(
async () => { async () => {
const dates = await TelemetryDataSaubService.getDataDatesRange(idWell) const dates = await TelemetryDataSaubService.getDataDatesRange(well.id)
if (dates) { if (dates) {
const dt = [moment(dates.from), moment(dates.to)] const dt = [moment(dates.from), moment(dates.to)]
setDateRange(dt) setDateRange(dt)
@ -92,10 +92,10 @@ const Operations = memo(() => {
} }
}, },
setIsLoading, setIsLoading,
'Не удалось загрузить диапазон доступных дат', `Не удалось загрузить диапазон доступных дат для скважины "${well.caption}"`,
'Получение дапазона доступних дат', 'Получение дапазона доступних дат',
) )
}, [idWell]) }, [well])
useEffect(() => { useEffect(() => {
updateData() updateData()

View File

@ -1,7 +1,7 @@
import { Table } from 'antd' import { Table } from 'antd'
import { useState, useEffect, useCallback, memo, useMemo } from 'react' import { useState, useEffect, useCallback, memo, useMemo } from 'react'
import { useIdWell } from '@asb/context' import { useWell } from '@asb/context'
import LoaderPortal from '@components/LoaderPortal' import LoaderPortal from '@components/LoaderPortal'
import { invokeWebApiWrapperAsync } from '@components/factory' import { invokeWebApiWrapperAsync } from '@components/factory'
import { Subscribe } from '@services/signalr' import { Subscribe } from '@services/signalr'
@ -11,34 +11,35 @@ import { makeMessageColumns } from '../Messages'
import '@styles/message.css' import '@styles/message.css'
export const ActiveMessagesOnline = memo(() => { export const ActiveMessagesOnline = memo(({ well: givenWell }) => {
const [messages, setMessages] = useState([]) const [messages, setMessages] = useState([])
const [loader, setLoader] = useState(false) const [loader, setLoader] = useState(false)
const idWell = useIdWell() const [wellContext] = useWell()
const well = useMemo(() => givenWell ?? wellContext, [givenWell, wellContext])
const handleReceiveMessages = useCallback((messages) => { const handleReceiveMessages = useCallback((messages) => {
if (messages) if (messages)
setMessages(messages.items.splice(0, 4)) setMessages(messages.items.splice(0, 4))
}, []) }, [])
const columns = useMemo(() => makeMessageColumns(idWell), [idWell]) const columns = useMemo(() => makeMessageColumns(well.id), [well.id])
useEffect(() => { useEffect(() => {
invokeWebApiWrapperAsync( invokeWebApiWrapperAsync(
async () => { async () => {
const messages = await MessageService.getMessages(idWell, 0, 4) const messages = await MessageService.getMessages(well.id, 0, 4)
handleReceiveMessages(messages) handleReceiveMessages(messages)
}, },
setLoader, setLoader,
`Не удалось загрузить сообщения по скважине "${idWell}"`, `Не удалось загрузить сообщения по скважине "${well.caption}"`,
'Получение списка сообщений' 'Получение списка сообщений'
) )
return Subscribe('hubs/telemetry',`well_${idWell}`, { return Subscribe('hubs/telemetry',`well_${well.id}`, {
methodName: 'ReceiveMessages', methodName: 'ReceiveMessages',
handler: handleReceiveMessages, handler: handleReceiveMessages,
}) })
}, [idWell, handleReceiveMessages]) }, [well, handleReceiveMessages])
return ( return (
<LoaderPortal show={loader}> <LoaderPortal show={loader}>

View File

@ -1,7 +1,7 @@
import { memo, useCallback, useMemo, useState } from 'react' import { memo, useCallback, useMemo, useState } from 'react'
import { Select, Modal, Input, InputNumber } from 'antd' import { Select, Modal, Input, InputNumber } from 'antd'
import { useIdWell } from '@asb/context' import { useWell } from '@asb/context'
import { Grid, GridItem } from '@components/Grid' import { Grid, GridItem } from '@components/Grid'
import LoaderPortal from '@components/LoaderPortal' import LoaderPortal from '@components/LoaderPortal'
import { invokeWebApiWrapperAsync } from '@components/factory' import { invokeWebApiWrapperAsync } from '@components/factory'
@ -16,7 +16,7 @@ export const SetpointSender = memo(({ onClose, visible, setpointNames }) => {
const [setpoints, setSetpoints] = useState([]) const [setpoints, setSetpoints] = useState([])
const [isLoading, setIsLoading] = useState(false) const [isLoading, setIsLoading] = useState(false)
const idWell = useIdWell() const [well] = useWell()
const addingColumns = useMemo(() => [ const addingColumns = useMemo(() => [
{ {
@ -68,13 +68,13 @@ export const SetpointSender = memo(({ onClose, visible, setpointNames }) => {
setpoints: setpointsObject, setpoints: setpointsObject,
comment: comment comment: comment
} }
await SetpointsService.insert(idWell, request) await SetpointsService.insert(well.id, request)
await onClose(true) await onClose(true)
}, },
setIsLoading, setIsLoading,
`Не удалось отправить уставки по скважине "${idWell}"`, `Не удалось отправить уставки по скважине "${well.caption}"`,
`Рекомендация новыой уставки` `Рекомендация новыой уставки`
), [idWell, setpoints, comment, expirePeriod, onClose]) ), [well, setpoints, comment, expirePeriod, onClose])
return ( return (
<Modal <Modal

View File

@ -1,7 +1,7 @@
import { Button, Modal } from 'antd' import { Button, Modal } from 'antd'
import { useState, useEffect, memo, useCallback, useMemo } from 'react' import { useState, useEffect, memo, useCallback, useMemo } from 'react'
import { useIdWell } from '@asb/context' import { useWell } from '@asb/context'
import { Table } from '@components/Table' import { Table } from '@components/Table'
import { UserView } from '@components/views' import { UserView } from '@components/views'
import LoaderPortal from '@components/LoaderPortal' import LoaderPortal from '@components/LoaderPortal'
@ -21,12 +21,12 @@ export const Setpoints = memo(({ ...other }) => {
const [selected, setSelected] = useState(null) const [selected, setSelected] = useState(null)
const [setpointNames, setSetpointNames] = useState([]) const [setpointNames, setSetpointNames] = useState([])
const idWell = useIdWell() const [well] = useWell()
useEffect(() => { useEffect(() => {
invokeWebApiWrapperAsync( invokeWebApiWrapperAsync(
async () => { async () => {
const names = await SetpointsService.getSetpointsNamesByIdWell(idWell) const names = await SetpointsService.getSetpointsNamesByIdWell(well.id)
if (!names) throw Error('Setpoints not found') if (!names) throw Error('Setpoints not found')
setSetpointNames(names.map(spn => ({ setSetpointNames(names.map(spn => ({
label: spn.displayName, label: spn.displayName,
@ -35,10 +35,10 @@ export const Setpoints = memo(({ ...other }) => {
}))) })))
}, },
setIsLoading, setIsLoading,
`Не удалось загрузить список имён уставок по скважине "${idWell}"`, `Не удалось загрузить список имён уставок по скважине "${well.caption}"`,
'Получение списка имён уставок' 'Получение списка имён уставок'
) )
}, [idWell]) }, [well])
const showMore = useCallback((id) => { const showMore = useCallback((id) => {
const selected = setpoints.find((sp) => sp.id === id) const selected = setpoints.find((sp) => sp.id === id)
@ -56,13 +56,13 @@ export const Setpoints = memo(({ ...other }) => {
const updateTable = useCallback(async () => await invokeWebApiWrapperAsync( const updateTable = useCallback(async () => await invokeWebApiWrapperAsync(
async () => { async () => {
const setpoints = await SetpointsService.getByIdWell(idWell) const setpoints = await SetpointsService.getByIdWell(well.id)
setSetpoints(setpoints) setSetpoints(setpoints)
}, },
setIsLoading, setIsLoading,
`Не удалось загрузить список для скважины "${idWell}"`, `Не удалось загрузить список для скважины "${well.caption}"`,
'Получение списка скважин' 'Получение списка рекомендаций'
), [idWell]) ), [well])
const onOpenClick = useCallback(async () => { const onOpenClick = useCallback(async () => {
await updateTable() await updateTable()
@ -85,7 +85,7 @@ export const Setpoints = memo(({ ...other }) => {
<> <>
<span style={{ marginRight: '15px' }}>Рекомендованные уставки</span> <span style={{ marginRight: '15px' }}>Рекомендованные уставки</span>
<Button onClick={() => setIsSenderVisible(true)} disabled={!hasPermission('Setpoints.edit')}> <Button onClick={() => setIsSenderVisible(true)} disabled={!hasPermission('Setpoints.edit')}>
Рекомендовать Создать рекомендацию
</Button> </Button>
</> </>
)} )}

View File

@ -1,6 +1,6 @@
import { memo, useCallback, useEffect, useState } from 'react' import { memo, useCallback, useEffect, useState } from 'react'
import { useIdWell } from '@asb/context' import { useWell } from '@asb/context'
import { WirelineView } from '@components/views' import { WirelineView } from '@components/views'
import { invokeWebApiWrapperAsync } from '@components/factory' import { invokeWebApiWrapperAsync } from '@components/factory'
import { TelemetryWirelineRunOutService } from '@api' import { TelemetryWirelineRunOutService } from '@api'
@ -10,16 +10,16 @@ export const WirelineRunOut = memo(() => {
const [twro, setTwro] = useState({}) const [twro, setTwro] = useState({})
const [isLoading, setIsLoading] = useState(false) const [isLoading, setIsLoading] = useState(false)
const idWell = useIdWell() const [well] = useWell()
const update = useCallback(() => invokeWebApiWrapperAsync( const update = useCallback(() => invokeWebApiWrapperAsync(
async () => { async () => {
const twro = await TelemetryWirelineRunOutService.getData(idWell) const twro = await TelemetryWirelineRunOutService.getData(well.id)
setTwro(twro) setTwro(twro)
}, },
setIsLoading, setIsLoading,
'Не удалось получить данные по талевому канату' `Не удалось получить данные по талевому канату скважины "${well.caption}"`
), [idWell]) ), [well])
const onTooltipVisibleChanged = useCallback((visible) => { const onTooltipVisibleChanged = useCallback((visible) => {
if (visible) update() if (visible) update()

View File

@ -2,7 +2,7 @@ import { useState, useEffect, useCallback, memo, useMemo } from 'react'
import { BehaviorSubject, buffer, throttleTime } from 'rxjs' import { BehaviorSubject, buffer, throttleTime } from 'rxjs'
import { Button, Select } from 'antd' import { Button, Select } from 'antd'
import { useIdWell } from '@asb/context' import { useWell } from '@asb/context'
import { makeDateSorter } from '@components/Table' import { makeDateSorter } from '@components/Table'
import { D3MonitoringCharts } from '@components/d3/monitoring' import { D3MonitoringCharts } from '@components/d3/monitoring'
import LoaderPortal from '@components/LoaderPortal' import LoaderPortal from '@components/LoaderPortal'
@ -15,8 +15,7 @@ import {
DrillFlowChartService, DrillFlowChartService,
OperationStatService, OperationStatService,
TelemetryDataSaubService, TelemetryDataSaubService,
TelemetryDataSpinService, TelemetryDataSpinService
WellService
} from '@api' } from '@api'
import ActiveMessagesOnline from './ActiveMessagesOnline' import ActiveMessagesOnline from './ActiveMessagesOnline'
@ -143,14 +142,13 @@ const TelemetryView = memo(() => {
const [dataSaub, setDataSaub] = useState([]) const [dataSaub, setDataSaub] = useState([])
const [dataSpin, setDataSpin] = useState([]) const [dataSpin, setDataSpin] = useState([])
const [chartInterval, setChartInterval] = useState(defaultPeriod) const [chartInterval, setChartInterval] = useState(defaultPeriod)
const [wellData, setWellData] = useState({ idState: 0 })
const [showLoader, setShowLoader] = useState(false) const [showLoader, setShowLoader] = useState(false)
const [flowChartData, setFlowChartData] = useState([]) const [flowChartData, setFlowChartData] = useState([])
const [rop, setRop] = useState(null) const [rop, setRop] = useState(null)
const [domain, setDomain] = useState({}) const [domain, setDomain] = useState({})
const [chartMethods, setChartMethods] = useState() const [chartMethods, setChartMethods] = useState()
const idWell = useIdWell() const [well, updateWell] = useWell()
const saubSubject$ = useMemo(() => new BehaviorSubject(), []) const saubSubject$ = useMemo(() => new BehaviorSubject(), [])
const spinSubject$ = useMemo(() => new BehaviorSubject(), []) const spinSubject$ = useMemo(() => new BehaviorSubject(), [])
@ -187,53 +185,42 @@ const TelemetryView = memo(() => {
useEffect(() => { useEffect(() => {
invokeWebApiWrapperAsync( invokeWebApiWrapperAsync(
async () => { async () => {
const flowChart = await DrillFlowChartService.getByIdWell(idWell) const flowChart = await DrillFlowChartService.getByIdWell(well.id)
const dataSaub = await TelemetryDataSaubService.getData(idWell, null, chartInterval) const dataSaub = await TelemetryDataSaubService.getData(well.id, null, chartInterval)
const dataSpin = await TelemetryDataSpinService.getData(idWell, null, chartInterval) const dataSpin = await TelemetryDataSpinService.getData(well.id, null, chartInterval)
setFlowChartData(flowChart ?? []) setFlowChartData(flowChart ?? [])
handleDataSaub(dataSaub) handleDataSaub(dataSaub)
handleDataSpin(dataSpin) handleDataSpin(dataSpin)
}, },
null, null,
`Не удалось получить данные по скважине "${idWell}"`, `Не удалось получить данные по скважине "${well.caption}"`,
'Получение данных по скважине' 'Получение данных по скважине'
) )
}, [idWell, chartInterval, handleDataSpin, handleDataSaub]) }, [well, chartInterval, handleDataSpin, handleDataSaub])
useEffect(() => { useEffect(() => {
const unsubscribe = Subscribe( const unsubscribe = Subscribe(
'hubs/telemetry', `well_${idWell}`, 'hubs/telemetry', `well_${well.id}`,
{ methodName: 'ReceiveDataSaub', handler: (data) => saubSubject$.next(data) }, { methodName: 'ReceiveDataSaub', handler: (data) => saubSubject$.next(data) },
{ methodName: 'ReceiveDataSpin', handler: (data) => spinSubject$.next(data) } { methodName: 'ReceiveDataSpin', handler: (data) => spinSubject$.next(data) }
) )
return () => unsubscribe() return () => unsubscribe()
}, [idWell, saubSubject$, spinSubject$]) }, [well.id, saubSubject$, spinSubject$])
useEffect(() => { useEffect(() => {
invokeWebApiWrapperAsync( invokeWebApiWrapperAsync(
async () => { async () => {
const well = await WellService.get(idWell) const rop = await OperationStatService.getClusterRopStatByIdWell(well.id)
const rop = await OperationStatService.getClusterRopStatByIdWell(idWell)
setRop(rop) setRop(rop)
setWellData(well ?? {})
}, },
setShowLoader, setShowLoader,
`Не удалось загрузить данные по скважине "${idWell}"`, `Не удалось загрузить данные по скважине "${well.caption}"`,
'Получение данных по скважине' 'Получение данных по скважине'
) )
}, [idWell]) }, [well])
const onStatusChanged = useCallback((value) => invokeWebApiWrapperAsync( const onStatusChanged = useCallback((value) => updateWell({ idState: value }), [well])
async () => {
const well = { idWell, ...wellData, idState: value }
await WellService.updateWell(well)
setWellData(well)
},
setShowLoader,
`Не удалось задать состояние скважины "${idWell}"`,
'Задание состояния скважины'
), [idWell, wellData])
useEffect(() => { useEffect(() => {
if (dataSaub.length <= 0) return if (dataSaub.length <= 0) return
@ -275,7 +262,7 @@ const TelemetryView = memo(() => {
<Button onClick={() => chartMethods?.setSettingsVisible(true)}>Настроить графики</Button> <Button onClick={() => chartMethods?.setSettingsVisible(true)}>Настроить графики</Button>
<div style={{ marginLeft: '1rem' }}> <div style={{ marginLeft: '1rem' }}>
Статус:&nbsp; Статус:&nbsp;
<Select value={wellData.idState ?? 0} onChange={onStatusChanged} disabled={!hasPermission('Well.edit')}> <Select value={well.idState ?? 0} onChange={onStatusChanged} disabled={!hasPermission('Well.edit')}>
<Option value={0} disabled hidden>Неизвестно</Option> <Option value={0} disabled hidden>Неизвестно</Option>
<Option value={1}>В работе</Option> <Option value={1}>В работе</Option>
<Option value={2}>Завершено</Option> <Option value={2}>Завершено</Option>
@ -316,7 +303,7 @@ const TelemetryView = memo(() => {
/> />
</GridItem> </GridItem>
<GridItem col={'2'} row={'3'} colSpan={'7'}> <GridItem col={'2'} row={'3'} colSpan={'7'}>
<ActiveMessagesOnline idWell={idWell} /> <ActiveMessagesOnline well={well} />
</GridItem> </GridItem>
</Grid> </Grid>
</LoaderPortal> </LoaderPortal>

View File

@ -5,13 +5,15 @@ import {
DeploymentUnitOutlined, DeploymentUnitOutlined,
} from '@ant-design/icons' } from '@ant-design/icons'
import { Layout } from 'antd' import { Layout } from 'antd'
import { memo, useMemo } from 'react' import { memo, useCallback, useEffect, useMemo, useState } from 'react'
import { Navigate, Route, Routes, useParams } from 'react-router-dom' import { Navigate, Route, Routes, useParams } from 'react-router-dom'
import { IdWellContext, RootPathContext, useRootPath } from '@asb/context' import { WellContext, RootPathContext, useRootPath } from '@asb/context'
import { LayoutPortal } from '@components/Layout' import { LayoutPortal } from '@components/Layout'
import { PrivateMenu } from '@components/Private' import { PrivateMenu } from '@components/Private'
import { invokeWebApiWrapperAsync } from '@components/factory'
import { NoAccessComponent, wrapPrivateComponent } from '@utils' import { NoAccessComponent, wrapPrivateComponent } from '@utils'
import { WellService } from '@api'
import Measure from './Measure' import Measure from './Measure'
import Reports from './Reports' import Reports from './Reports'
@ -27,9 +29,33 @@ const { Content } = Layout
const Well = memo(() => { const Well = memo(() => {
const { idWell } = useParams() const { idWell } = useParams()
const [well, setWell] = useState({ id: idWell })
const root = useRootPath() const root = useRootPath()
const rootPath = useMemo(() => `${root}/well/${idWell}`, [root, idWell]) const rootPath = useMemo(() => `${root}/well/${idWell}`, [root, idWell])
useEffect(() => {
invokeWebApiWrapperAsync(
async () => {
const well = await WellService.get(idWell)
setWell(well ?? { id: idWell })
},
undefined,
'Не удалось получить данные по скважине'
)
}, [idWell])
const updateWell = useCallback((data) => invokeWebApiWrapperAsync(
async () => {
const newWell = { ...well, ...data }
await WellService.updateWell(newWell)
setWell(newWell)
},
undefined,
`Не удалось изменить данные скважины "${well.caption}"`
), [well])
return ( return (
<LayoutPortal> <LayoutPortal>
<RootPathContext.Provider value={rootPath}> <RootPathContext.Provider value={rootPath}>
@ -43,7 +69,7 @@ const Well = memo(() => {
<PrivateMenu.Link content={DrillingProgram} icon={<FolderOutlined />} /> <PrivateMenu.Link content={DrillingProgram} icon={<FolderOutlined />} />
</PrivateMenu> </PrivateMenu>
<IdWellContext.Provider value={idWell}> <WellContext.Provider value={[well, updateWell]}>
<Layout> <Layout>
<Content className={'site-layout-background'}> <Content className={'site-layout-background'}>
<Routes> <Routes>
@ -60,7 +86,7 @@ const Well = memo(() => {
</Routes> </Routes>
</Content> </Content>
</Layout> </Layout>
</IdWellContext.Provider> </WellContext.Provider>
</RootPathContext.Provider> </RootPathContext.Provider>
</LayoutPortal> </LayoutPortal>
) )

View File

@ -1,6 +1,6 @@
import { useState, useEffect, memo, useMemo } from 'react' import { useState, useEffect, memo, useMemo, useCallback } from 'react'
import { useIdWell } from '@asb/context' import { useWell } from '@asb/context'
import LoaderPortal from '@components/LoaderPortal' import LoaderPortal from '@components/LoaderPortal'
import { invokeWebApiWrapperAsync } from '@components/factory' import { invokeWebApiWrapperAsync } from '@components/factory'
import { EditableTable, makeNumericMinMax, makeNumericStartEnd } from '@components/Table' import { EditableTable, makeNumericMinMax, makeNumericStartEnd } from '@components/Table'
@ -21,21 +21,21 @@ export const DrillProcessFlow = memo(() => {
const [flows, setFlows] = useState([]) const [flows, setFlows] = useState([])
const [showLoader, setShowLoader] = useState(false) const [showLoader, setShowLoader] = useState(false)
const idWell = useIdWell() const [well] = useWell()
const updateFlows = () => invokeWebApiWrapperAsync( const updateFlows = useCallback(() => invokeWebApiWrapperAsync(
async () => { async () => {
const flows = await DrillFlowChartService.getByIdWell(idWell) const flows = await DrillFlowChartService.getByIdWell(well.id)
setFlows(arrayOrDefault(flows)) setFlows(arrayOrDefault(flows))
}, },
setShowLoader, setShowLoader,
'Не удалось загрузить режимно-технологическую карту скважины', `Не удалось загрузить режимно-технологическую карту скважины "${well.caption}"`,
'Получение режимно-технологической карты скважины' 'Получение режимно-технологической карты скважины'
) ), [well])
useEffect(() => { useEffect(() => {
updateFlows() updateFlows()
}, [idWell]) }, [well])
const tableHandlers = useMemo(() => { const tableHandlers = useMemo(() => {
const handlerProps = { const handlerProps = {
@ -45,14 +45,14 @@ export const DrillProcessFlow = memo(() => {
permission: 'DrillFlowChart.edit', permission: 'DrillFlowChart.edit',
} }
const recordParser = (record) => ({ idWell, ...record }) const recordParser = (record) => ({ idWell: well.id, ...record })
return { return {
add: { ...handlerProps, action: 'insert', actionName: 'Добавление месторождения', recordParser }, add: { ...handlerProps, action: 'insert', actionName: 'Добавление месторождения', recordParser },
edit: { ...handlerProps, action: 'update', actionName: 'Редактирование месторождения', recordParser }, edit: { ...handlerProps, action: 'update', actionName: 'Редактирование месторождения', recordParser },
delete: { ...handlerProps, action: 'delete', actionName: 'Удаление месторождения', permission: 'DrillFlowChart.delete' }, delete: { ...handlerProps, action: 'delete', actionName: 'Удаление месторождения', permission: 'DrillFlowChart.delete' },
} }
}, [updateFlows, idWell]) }, [updateFlows, well.di])
return ( return (
<LoaderPortal show={showLoader}> <LoaderPortal show={showLoader}>

View File

@ -1,8 +1,8 @@
import { memo, useMemo, useState } from 'react' import { memo, useCallback, useMemo, useState } from 'react'
import { Button, Tooltip, Modal } from 'antd' import { Button, Tooltip, Modal } from 'antd'
import { FileOutlined, ImportOutlined, ExportOutlined } from '@ant-design/icons' import { FileOutlined, ImportOutlined, ExportOutlined } from '@ant-design/icons'
import { useIdWell } from '@asb/context' import { useWell } from '@asb/context'
import { download } from '@components/factory' import { download } from '@components/factory'
import { hasPermission } from '@utils' import { hasPermission } from '@utils'
@ -10,19 +10,19 @@ import { ImportOperations } from './ImportOperations'
const style = { margin: 4 } const style = { margin: 4 }
export const ImportExportBar = memo(({ idWell: wellId, onImported, disabled }) => { export const ImportExportBar = memo(({ well: givenWell, onImported, disabled }) => {
const [isImportModalVisible, setIsImportModalVisible] = useState(false) const [isImportModalVisible, setIsImportModalVisible] = useState(false)
const idWellContext = useIdWell() const [wellContext] = useWell()
const idWell = useMemo(() => wellId ?? idWellContext, [idWellContext]) const well = useMemo(() => givenWell ?? wellContext, [givenWell, wellContext])
const downloadTemplate = async () => await download(`/api/well/${idWell}/wellOperations/template`) const downloadTemplate = useCallback(async () => await download(`/api/well/${well.id}/wellOperations/template`), [well.id])
const downloadExport = async () => await download(`/api/well/${idWell}/wellOperations/export`) const downloadExport = useCallback(async () => await download(`/api/well/${well.id}/wellOperations/export`), [well.id])
const onDone = () => { const onDone = useCallback(() => {
setIsImportModalVisible(false) setIsImportModalVisible(false)
onImported?.() onImported?.()
} }, [onImported])
return ( return (
<div> <div>
@ -52,7 +52,7 @@ export const ImportExportBar = memo(({ idWell: wellId, onImported, disabled }) =
onCancel={() => setIsImportModalVisible(false)} onCancel={() => setIsImportModalVisible(false)}
footer={null} footer={null}
> >
<ImportOperations idWell={idWell} onDone={onDone} /> <ImportOperations well={well} onDone={onDone} />
</Modal> </Modal>
</div> </div>
) )

View File

@ -1,29 +1,32 @@
import { Switch } from 'antd' import { Switch } from 'antd'
import { memo, useState } from 'react' import { memo, useCallback, useMemo, useState } from 'react'
import { useWell } from '@asb/context'
import { ErrorFetch } from '@components/ErrorFetch' import { ErrorFetch } from '@components/ErrorFetch'
import { UploadForm } from '@components/UploadForm' import { UploadForm } from '@components/UploadForm'
const errorTextStyle = { color: 'red', fontWeight: 'bold' } const errorTextStyle = { color: 'red', fontWeight: 'bold' }
const uploadFormStyle = { marginTop: '24px' } const uploadFormStyle = { marginTop: '24px' }
export const ImportOperations = memo(({ idWell, onDone }) =>{ export const ImportOperations = memo(({ well: givenWell, onDone }) => {
const [deleteBeforeImport, setDeleteBeforeImport] = useState(false) const [deleteBeforeImport, setDeleteBeforeImport] = useState(false)
const [errorText, setErrorText] = useState('') const [errorText, setErrorText] = useState('')
const url = `/api/well/${idWell}/wellOperations/import${deleteBeforeImport ? '/1' : '/0'}` const [wellContext] = useWell()
const well = useMemo(() => givenWell ?? wellContext, [givenWell, wellContext])
const onUploadSuccess = () => { const url = useMemo(() => `/api/well/${well.id}/wellOperations/import${deleteBeforeImport ? '/1' : '/0'}`, [well])
const onUploadSuccess = useCallback(() => {
setErrorText('') setErrorText('')
onDone?.() onDone?.()
} }, [onDone])
const onUploadError = (error) => { const onUploadError = useCallback((error) => {
if (error instanceof ErrorFetch && error.status === 400) if (error instanceof ErrorFetch && error.status === 400)
setErrorText(`Не удалось импортировать.\n ${error?.message}`) setErrorText(`Не удалось импортировать.\n ${error?.message}`)
else else setErrorText(`Не удалось импортировать.`)
setErrorText(`Не удалось импортировать.`) }, [])
}
return ( return (
<div> <div>

View File

@ -4,14 +4,14 @@ import { Button } from 'antd'
import { download, invokeWebApiWrapperAsync } from '@components/factory' import { download, invokeWebApiWrapperAsync } from '@components/factory'
export const NetGraphExport = memo(({ idWell, ...other }) => { export const NetGraphExport = memo(({ well, ...other }) => {
const [isFileExporting, setIsFileExporting] = useState(false) const [isFileExporting, setIsFileExporting] = useState(false)
const onExport = useCallback(() => invokeWebApiWrapperAsync( const onExport = useCallback(() => invokeWebApiWrapperAsync(
async () => await download(`/api/well/${idWell}/wellOperations/scheduleReport`), async () => await download(`/api/well/${well.id}/wellOperations/scheduleReport`),
setIsFileExporting, setIsFileExporting,
'Не удалось загрузить файл' 'Не удалось загрузить файл'
), [idWell]) ), [well.id])
return ( return (
<div className={'tvd-input-group'}> <div className={'tvd-input-group'}>

View File

@ -1,31 +1,16 @@
import { memo, useCallback, useEffect, useState } from 'react' import { memo, useCallback, useState } from 'react'
import { Button, Input } from 'antd' import { Button, Input } from 'antd'
import { useIdWell } from '@asb/context'
import { download, invokeWebApiWrapperAsync } from '@components/factory' import { download, invokeWebApiWrapperAsync } from '@components/factory'
import { WellService } from '@api'
export const StatExport = memo(() => { export const StatExport = memo(({ well }) => {
const [isFileExporting, setIsFileExporting] = useState(false) const [isFileExporting, setIsFileExporting] = useState(false)
const [idCluster, setIdCluster] = useState()
const idWell = useIdWell()
useEffect(() => { const onExport = useCallback((isWell) => invokeWebApiWrapperAsync(
invokeWebApiWrapperAsync( async () => await download(`/api/DetectedOperation/export?${isWell ? 'idWell' : 'idCluster'}=${isWell ? well.id : well.idCluster}`),
async () => {
const { idCluster } = await WellService.get(idWell)
setIdCluster(idCluster)
},
setIsFileExporting,
'Не удалось загрузить ID куста'
)
}, [idWell])
const onExport = useCallback((well) => invokeWebApiWrapperAsync(
async () => await download(`/api/DetectedOperation/export?${well ? 'idWell' : 'idCluster'}=${well ? idWell : idCluster}`),
setIsFileExporting, setIsFileExporting,
'Не удалось загрузить файл' 'Не удалось загрузить файл'
), [idWell, idCluster]) ), [well])
return ( return (
<Input.Group compact> <Input.Group compact>

View File

@ -4,7 +4,6 @@ import { Empty } from 'antd'
import moment from 'moment' import moment from 'moment'
import * as d3 from 'd3' import * as d3 from 'd3'
import { useIdWell } from '@asb/context'
import LoaderPortal from '@components/LoaderPortal' import LoaderPortal from '@components/LoaderPortal'
import { invokeWebApiWrapperAsync } from '@components/factory' import { invokeWebApiWrapperAsync } from '@components/factory'
import { DetectedOperationService } from '@api' import { DetectedOperationService } from '@api'
@ -44,6 +43,7 @@ const splitByDate = (startTime, endTime) => {
} }
export const TLChart = memo(({ export const TLChart = memo(({
well,
backgroundColor = '#0000', backgroundColor = '#0000',
barHeight = 15, barHeight = 15,
offset = defaultOffset, offset = defaultOffset,
@ -59,8 +59,6 @@ export const TLChart = memo(({
const [rootRef, { width, height }] = useElementSize() const [rootRef, { width, height }] = useElementSize()
const idWell = useIdWell()
const dates = useMemo(() => { const dates = useMemo(() => {
if (!data || data.length <= 0) return [0, 0] if (!data || data.length <= 0) return [0, 0]
return [ return [
@ -82,7 +80,7 @@ export const TLChart = memo(({
useEffect(() => { useEffect(() => {
invokeWebApiWrapperAsync( invokeWebApiWrapperAsync(
async () => { async () => {
const { operations } = await DetectedOperationService.get(idWell) const { operations } = await DetectedOperationService.get(well.id)
setData(operations.map((raw) => { setData(operations.map((raw) => {
const startTime = moment(raw.dateStart) const startTime = moment(raw.dateStart)
const endTime = moment(raw.dateEnd) const endTime = moment(raw.dateEnd)
@ -94,9 +92,9 @@ export const TLChart = memo(({
}).flat()) }).flat())
}, },
setIsLoading, setIsLoading,
'Не удалось загрузить список операций' `Не удалось загрузить список операций по скважине "${well.caption}"`
) )
}, [idWell]) }, [well])
useEffect(() => { // Рисуем ось X useEffect(() => { // Рисуем ось X
const xAxisArea = d3.select(svgRef).select('.axis.x') const xAxisArea = d3.select(svgRef).select('.axis.x')

View File

@ -3,7 +3,6 @@ import { useElementSize } from 'usehooks-ts'
import { Empty } from 'antd' import { Empty } from 'antd'
import * as d3 from 'd3' import * as d3 from 'd3'
import { useIdWell } from '@asb/context'
import { makeColumn, makeNumericColumn, makeTextColumn, Table } from '@components/Table' import { makeColumn, makeNumericColumn, makeTextColumn, Table } from '@components/Table'
import LoaderPortal from '@components/LoaderPortal' import LoaderPortal from '@components/LoaderPortal'
import { invokeWebApiWrapperAsync } from '@components/factory' import { invokeWebApiWrapperAsync } from '@components/factory'
@ -24,7 +23,7 @@ const tableColumns = [
makeNumericColumn('Процент, %', 'percent', undefined, undefined, (d) => d ? d.toFixed(2) : '---', 100) makeNumericColumn('Процент, %', 'percent', undefined, undefined, (d) => d ? d.toFixed(2) : '---', 100)
] ]
export const TLPie = memo(() => { export const TLPie = memo(({ well }) => {
const [isLoading, setIsLoading] = useState(false) const [isLoading, setIsLoading] = useState(false)
const [svgRef, setSvgRef] = useState() const [svgRef, setSvgRef] = useState()
const [stats, setStats] = useState([]) const [stats, setStats] = useState([])
@ -32,8 +31,6 @@ export const TLPie = memo(() => {
const [rootRef, { width, height }] = useElementSize() const [rootRef, { width, height }] = useElementSize()
const idWell = useIdWell()
const pie = useMemo(() => d3.pie().value((d) => d.minutesTotal), []) const pie = useMemo(() => d3.pie().value((d) => d.minutesTotal), [])
const getColor = useMemo(() => makeGetColor(stats?.map((row) => row.idCategory).filter(unique)), [stats]) const getColor = useMemo(() => makeGetColor(stats?.map((row) => row.idCategory).filter(unique)), [stats])
@ -83,13 +80,13 @@ export const TLPie = memo(() => {
useEffect(() => { useEffect(() => {
invokeWebApiWrapperAsync( invokeWebApiWrapperAsync(
async () => { async () => {
const stats = await DetectedOperationService.getStat(idWell) const stats = await DetectedOperationService.getStat(well.id)
setStats(stats) setStats(stats)
}, },
setIsLoading, setIsLoading,
'Не удалось загрузить статистику автоопределённых операций' `Не удалось загрузить статистику автоопределённых операций по скважине "${well.caption}"`
) )
}, [idWell]) }, [well])
useEffect(() => { useEffect(() => {
if (!data) return if (!data) return

View File

@ -4,7 +4,7 @@ import { Switch, Segmented, Button } from 'antd'
import { Link } from 'react-router-dom' import { Link } from 'react-router-dom'
import * as d3 from 'd3' import * as d3 from 'd3'
import { useIdWell } from '@asb/context' import { useWell } from '@asb/context'
import { D3Chart } from '@components/d3' import { D3Chart } from '@components/d3'
import LoaderPortal from '@components/LoaderPortal' import LoaderPortal from '@components/LoaderPortal'
import { invokeWebApiWrapperAsync } from '@components/factory' import { invokeWebApiWrapperAsync } from '@components/factory'
@ -149,15 +149,15 @@ const makeDataset = (key, label, color, width, radius, dash) => ({
}, },
}) })
const Tvd = memo(({ idWell: wellId, title, ...other }) => { const Tvd = memo(({ well: givenWell, title, ...other }) => {
const [xLabel, setXLabel] = useState('day') const [xLabel, setXLabel] = useState('day')
const [operations, setOperations] = useState({}) const [operations, setOperations] = useState({})
const [isLoading, setIsLoading] = useState(false) const [isLoading, setIsLoading] = useState(false)
const [pointsEnabled, setPointsEnabled] = useState(true) const [pointsEnabled, setPointsEnabled] = useState(true)
const [selectedTab, setSelectedTab] = useState('Скрыть') const [selectedTab, setSelectedTab] = useState('Скрыть')
const idWellContext = useIdWell() const [wellContext] = useWell()
const idWell = useMemo(() => wellId ?? idWellContext, [wellId, idWellContext]) const well = useMemo(() => givenWell ?? wellContext, [givenWell, wellContext])
const chartData = useMemo(() => { const chartData = useMemo(() => {
const withoutNpt = [] const withoutNpt = []
@ -187,12 +187,12 @@ const Tvd = memo(({ idWell: wellId, title, ...other }) => {
useEffect(() => { useEffect(() => {
invokeWebApiWrapperAsync( invokeWebApiWrapperAsync(
async () => setOperations(await getOperations(idWell)), async () => setOperations(await getOperations(well.id)),
setIsLoading, setIsLoading,
`Не удалось загрузить операции по скважине "${idWell}"`, `Не удалось загрузить операции по скважине "${well.caption}"`,
'Получение списка опервций по скважине' 'Получение списка опервций по скважине'
) )
}, [idWell]) }, [well])
return ( return (
<div className={'container tvd-page'} {...other}> <div className={'container tvd-page'} {...other}>
@ -216,8 +216,8 @@ const Tvd = memo(({ idWell: wellId, title, ...other }) => {
</Item> </Item>
</div> </div>
<div className={'tvd-inputs'}> <div className={'tvd-inputs'}>
<StatExport /> <StatExport well={well} />
<NetGraphExport idWell={idWell} /> <NetGraphExport well={well} />
<Segmented <Segmented
options={['НПВ', 'ЕСО', 'Статистика', 'Скрыть']} options={['НПВ', 'ЕСО', 'Статистика', 'Скрыть']}
value={selectedTab} value={selectedTab}
@ -241,8 +241,8 @@ const Tvd = memo(({ idWell: wellId, title, ...other }) => {
/> />
</div> </div>
{selectedTab === 'НПВ' && <NptTable operations={operations?.fact} />} {selectedTab === 'НПВ' && <NptTable operations={operations?.fact} />}
{selectedTab === 'ЕСО' && <TLChart />} {selectedTab === 'ЕСО' && <TLChart well={well} />}
{selectedTab === 'Статистика' && <TLPie />} {selectedTab === 'Статистика' && <TLPie well={well} />}
</div> </div>
</LoaderPortal> </LoaderPortal>
</div> </div>

View File

@ -1,6 +1,6 @@
import { useState, useEffect, useCallback, memo, useMemo } from 'react' import { useState, useEffect, useCallback, memo, useMemo } from 'react'
import { useIdWell } from '@asb/context' import { useWell } from '@asb/context'
import { import {
EditableTable, EditableTable,
makeSelectColumn, makeSelectColumn,
@ -39,28 +39,28 @@ export const WellDrillParams = memo(() => {
const [showLoader, setShowLoader] = useState(false) const [showLoader, setShowLoader] = useState(false)
const [columns, setColumns] = useState([]) const [columns, setColumns] = useState([])
const idWell = useIdWell() const [well] = useWell()
const updateParams = useCallback(async () => await invokeWebApiWrapperAsync( const updateParams = useCallback(async () => await invokeWebApiWrapperAsync(
async () => { async () => {
const params = arrayOrDefault(await DrillParamsService.getAll(idWell)) const params = arrayOrDefault(await DrillParamsService.getAll(well.id))
// Typescript против использования числа в качестве типа значения select // Typescript против использования числа в качестве типа значения select
params.forEach((param) => param.idWellSectionType = `${param.idWellSectionType}`) params.forEach((param) => param.idWellSectionType = `${param.idWellSectionType}`)
setParams(params) setParams(params)
}, },
setShowLoader, setShowLoader,
'Не удалось загрузить список режимов бурения скважины', `Не удалось загрузить список режимов бурения скважины "${well.caption}"`,
'Получение списка режимов бурения скважины' 'Получение списка режимов бурения скважины'
), [idWell]) ), [well])
useEffect(() => { useEffect(() => {
(async () => { (async () => {
setColumns(await getColumns(idWell)) setColumns(await getColumns(well.id))
await updateParams() await updateParams()
})() })()
}, [idWell, updateParams]) }, [well.id, updateParams])
const recordParser = useCallback((record) => ({ ...record, idWell }), [idWell]) const recordParser = useCallback((record) => ({ ...record, idWell: well.id }), [well.id])
const tableHandlers = useMemo(() => { const tableHandlers = useMemo(() => {
const handlerProps = { const handlerProps = {
@ -68,7 +68,7 @@ export const WellDrillParams = memo(() => {
setLoader: setShowLoader, setLoader: setShowLoader,
onComplete: updateParams, onComplete: updateParams,
permission: 'DrillParams.edit', permission: 'DrillParams.edit',
idWell, idWell: well.id,
idRecord: true, idRecord: true,
} }
@ -77,7 +77,7 @@ export const WellDrillParams = memo(() => {
edit: { ...handlerProps, action: 'update', actionName: 'Редактирование режима бурения', recordParser }, edit: { ...handlerProps, action: 'update', actionName: 'Редактирование режима бурения', recordParser },
delete: { ...handlerProps, action: 'delete', actionName: 'Удаление режима бурения', permission: 'DrillParams.delete' }, delete: { ...handlerProps, action: 'delete', actionName: 'Удаление режима бурения', permission: 'DrillParams.delete' },
} }
}, [idWell, updateParams, recordParser]) }, [well.id, updateParams, recordParser])
return ( return (
<LoaderPortal show={showLoader}> <LoaderPortal show={showLoader}>

View File

@ -3,7 +3,7 @@ import { Input } from 'antd'
import { useLocation } from 'react-router-dom' import { useLocation } from 'react-router-dom'
import { useState, useEffect, memo, useMemo, useCallback } from 'react' import { useState, useEffect, memo, useMemo, useCallback } from 'react'
import { useIdWell } from '@asb/context' import { useWell } from '@asb/context'
import { import {
EditableTable, EditableTable,
makeColumn, makeColumn,
@ -57,7 +57,7 @@ const WellOperationsEditor = memo(({ idType, showNpt, ...other }) => {
const [operations, setOperations] = useState([]) const [operations, setOperations] = useState([])
const [showLoader, setShowLoader] = useState(false) const [showLoader, setShowLoader] = useState(false)
const idWell = useIdWell() const [well] = useWell()
const [categories, setCategories] = useState([]) const [categories, setCategories] = useState([])
const [sectionTypes, setSectionTypes] = useState([]) const [sectionTypes, setSectionTypes] = useState([])
@ -73,23 +73,23 @@ const WellOperationsEditor = memo(({ idType, showNpt, ...other }) => {
useEffect(() => { useEffect(() => {
invokeWebApiWrapperAsync( invokeWebApiWrapperAsync(
async () => { async () => {
const categories = arrayOrDefault(await WellOperationService.getCategories(idWell)) const categories = arrayOrDefault(await WellOperationService.getCategories(well.id))
setCategories(categories.map((item) => ({ value: item.id, label: item.name }))) setCategories(categories.map((item) => ({ value: item.id, label: item.name })))
const sectionTypes = Object.entries(await WellOperationService.getSectionTypes(idWell) ?? {}) const sectionTypes = Object.entries(await WellOperationService.getSectionTypes(well.id) ?? {})
setSectionTypes(sectionTypes.map(([id, label]) => ({ value: parseInt(id), label }))) setSectionTypes(sectionTypes.map(([id, label]) => ({ value: parseInt(id), label })))
}, },
setShowLoader, setShowLoader,
'Не удалось загрузить список операций по скважине', `Не удалось загрузить список операций по скважине "${well.caption}"`,
'Получение списка операций по скважине' 'Получение списка операций по скважине'
) )
}, [idWell]) }, [well])
const updateOperations = useCallback(() => invokeWebApiWrapperAsync( const updateOperations = useCallback(() => invokeWebApiWrapperAsync(
async () => { async () => {
const skip = ((pageNumAndPageSize.current - 1) * pageNumAndPageSize.pageSize) || 0 const skip = ((pageNumAndPageSize.current - 1) * pageNumAndPageSize.pageSize) || 0
const take = pageNumAndPageSize.pageSize const take = pageNumAndPageSize.pageSize
const paginatedOperations = await WellOperationService.getOperations(idWell, const paginatedOperations = await WellOperationService.getOperations(well.id,
idType, undefined, undefined, undefined, undefined, idType, undefined, undefined, undefined, undefined,
undefined, undefined, skip, take) undefined, undefined, skip, take)
const operations = paginatedOperations?.items ?? [] const operations = paginatedOperations?.items ?? []
@ -98,9 +98,9 @@ const WellOperationsEditor = memo(({ idType, showNpt, ...other }) => {
setPaginationTotal(total) setPaginationTotal(total)
}, },
setShowLoader, setShowLoader,
'Не удалось загрузить список операций по скважине', `Не удалось загрузить список операций по скважине ${well.caption}`,
'Получение списка операций по скважине' 'Получение списка операций по скважине'
), [idWell, idType, pageNumAndPageSize]) ), [well, idType, pageNumAndPageSize])
useEffect(() => { useEffect(() => {
updateOperations() updateOperations()
@ -125,7 +125,7 @@ const WellOperationsEditor = memo(({ idType, showNpt, ...other }) => {
onComplete: updateOperations, onComplete: updateOperations,
permission: 'WellOperation.edit', permission: 'WellOperation.edit',
idRecord: true, idRecord: true,
idWell, idWell: well.id,
} }
return { return {
@ -133,7 +133,7 @@ const WellOperationsEditor = memo(({ idType, showNpt, ...other }) => {
edit: { ...handlerProps, action: 'update', actionName: 'Редактирование операции по скважине', recordParser }, edit: { ...handlerProps, action: 'update', actionName: 'Редактирование операции по скважине', recordParser },
delete: { ...handlerProps, action: 'delete', actionName: 'Удаление операции по скважине', permission: 'WellOperation.delete' }, delete: { ...handlerProps, action: 'delete', actionName: 'Удаление операции по скважине', permission: 'WellOperation.delete' },
} }
}, [updateOperations, idWell, recordParser]) }, [updateOperations, well.id, recordParser])
return ( return (
<LoaderPortal show={showLoader}> <LoaderPortal show={showLoader}>

View File

@ -1,6 +1,6 @@
import { useState, useEffect, memo } from 'react' import { useState, useEffect, memo } from 'react'
import { useIdWell } from '@asb/context' import { useWell } from '@asb/context'
import LoaderPortal from '@components/LoaderPortal' import LoaderPortal from '@components/LoaderPortal'
import { invokeWebApiWrapperAsync } from '@components/factory' import { invokeWebApiWrapperAsync } from '@components/factory'
import { Table, makeColumn, makeColumnsPlanFact, makeNumericRender } from '@components/Table' import { Table, makeColumn, makeColumnsPlanFact, makeNumericRender } from '@components/Table'
@ -25,12 +25,12 @@ export const WellSectionsStat = memo(() => {
const [sections, setSections] = useState([]) const [sections, setSections] = useState([])
const [showLoader, setShowLoader] = useState(false) const [showLoader, setShowLoader] = useState(false)
const idWell = useIdWell() const [well] = useWell()
useEffect(() => { useEffect(() => {
invokeWebApiWrapperAsync( invokeWebApiWrapperAsync(
async () => { async () => {
const sectionsResponse = await OperationStatService.getStatWell(idWell) const sectionsResponse = await OperationStatService.getStatWell(well.id)
if(sectionsResponse?.sections){ if(sectionsResponse?.sections){
const sections = sectionsResponse.sections.map(s => ({ const sections = sectionsResponse.sections.map(s => ({
@ -57,10 +57,10 @@ export const WellSectionsStat = memo(() => {
} }
}, },
setShowLoader, setShowLoader,
`Не удалось получить статистику по секциям скважины "${idWell}"`, `Не удалось получить статистику по секциям скважины "${well.caption}"`,
'Получение статистики по секциям скважины' 'Получение статистики по секциям скважины'
) )
}, [idWell]) }, [well])
return ( return (
<LoaderPortal show={showLoader}> <LoaderPortal show={showLoader}>