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

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

View File

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

View File

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

View File

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

View File

@ -2,7 +2,7 @@ import { useState, useEffect, memo, useMemo } from 'react'
import { Navigate, Route, Routes } from 'react-router-dom'
import { Col, Layout, Row } from 'antd'
import { useIdWell, useRootPath } from '@asb/context'
import { useWell, useRootPath } from '@asb/context'
import { PrivateMenu } from '@components/Private'
import LoaderPortal from '@components/LoaderPortal'
import WellSelector from '@components/selectors/WellSelector'
@ -23,7 +23,7 @@ const properties = {
}
const WellCompositeEditor = memo(() => {
const idWell = useIdWell()
const [well] = useWell()
const root = useRootPath()
const rootPath = useMemo(() => `${root}/${properties.key}`, [root])
@ -37,17 +37,17 @@ const WellCompositeEditor = memo(() => {
invokeWebApiWrapperAsync(
async () => {
try {
setSelectedSections(arrayOrDefault(await WellCompositeService.get(idWell)))
setSelectedSections(arrayOrDefault(await WellCompositeService.get(well.id)))
} catch(e) {
setSelectedSections([])
throw e
}
},
setShowLoader,
'Не удалось загрузить список скважин',
`Не удалось получить данные по скважине "${well.caption}"`,
'Получение списка скважин'
)
}, [idWell])
}, [well])
useEffect(() => {
const wellIds = selectedSections.map((value) => value.idWellSrc)
@ -71,11 +71,7 @@ const WellCompositeEditor = memo(() => {
<LoaderPortal show={showLoader}>
<Row align={'middle'} justify={'space-between'} wrap={false} style={{ backgroundColor: 'white' }}>
<Col span={18}>
<WellSelector
idWell={idWell}
onChange={setSelectedIdWells}
value={selectedIdWells}
/>
<WellSelector onChange={setSelectedIdWells} value={selectedIdWells} />
</Col>
<Col span={6}>
<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 ClusterWells = memo(({ statsWells }) => {
const [selectedWellId, setSelectedWellId] = useState(0)
const [selectedWell, setSelectedWell] = useState(null)
const [isTVDModalVisible, setIsTVDModalVisible] = useState(false)
const [isOpsModalVisible, setIsOpsModalVisible] = useState(false)
const [isCompaniesModalVisible, setIsCompaniesModalVisible] = useState(false)
@ -54,20 +54,20 @@ const ClusterWells = memo(({ statsWells }) => {
const location = useLocation()
useEffect(() => {
if (!isOpsModalVisible || selectedWellId <= 0) {
if (!isOpsModalVisible || !selectedWell) {
setWellOperations([])
return
}
invokeWebApiWrapperAsync(
async () => {
const operations = await getOperations(selectedWellId)
const operations = await getOperations(selectedWell.id)
setWellOperations(operations.operations)
},
setShowLoader,
`Не удалось загрузить операции по скважине "${selectedWellId}"`,
`Не удалось загрузить операции по скважине "${selectedWell.caption}"`,
'Получение операций по скважине'
)
}, [selectedWellId, isOpsModalVisible])
}, [selectedWell, isOpsModalVisible])
useEffect(() => {
let data = statsWells?.map((well) => {
@ -139,7 +139,7 @@ const ClusterWells = memo(({ statsWells }) => {
makeNumericColumn('НПВ, ч', 'notProductiveTimeFact', filtersMinMax, makeFilterMinMaxFunction, numericRender),
makeColumn('TVD', 'tvd', { align: 'center', render: (_, value) => (
<Button onClick={() => {
setSelectedWellId(value?.id)
setSelectedWell(value)
setIsTVDModalVisible(true)
}}>
<LineChartOutlined />
@ -147,7 +147,7 @@ const ClusterWells = memo(({ statsWells }) => {
) }),
makeColumn('Операции', 'operations', { align: 'center', render: (_, value) => (
<Button onClick={() => {
setSelectedWellId(value?.id)
setSelectedWell(value)
setIsOpsModalVisible(true)
}}>
<ProfileOutlined />
@ -183,7 +183,7 @@ const ClusterWells = memo(({ statsWells }) => {
width={1500}
footer={null}
>
<Tvd style={{ minHeight: '600px' }} idWell={selectedWellId} />
<Tvd style={{ minHeight: '600px' }} well={selectedWell} />
</Modal>
<Modal

View File

@ -1,7 +1,7 @@
import { useState, useEffect, useMemo, useCallback } from 'react'
import { DatePicker, Input } from 'antd'
import { useIdWell } from '@asb/context'
import { useWell } from '@asb/context'
import DownloadLink from '@components/DownloadLink'
import LoaderPortal from '@components/LoaderPortal'
import { UploadForm } from '@components/UploadForm'
@ -31,7 +31,7 @@ const columns = [
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 [filterDataRange, setFilterDataRange] = useState([])
const [filterCompanyName, setFilterCompanyName] = useState([])
@ -40,10 +40,10 @@ export const DocumentsTemplate = ({ idCategory, idWell: wellId, mimeTypes, heade
const [files, setFiles] = useState([])
const [showLoader, setShowLoader] = useState(false)
const idwellContext = useIdWell()
const idWell = useMemo(() => wellId ?? idwellContext, [wellId, idwellContext])
const [wellContext] = useWell()
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 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(
async () => {
const paginatedFiles = await FileService.getFilesInfo(
idWell,
well.id,
idCategory,
filterCompanyName,
filterFileName,
@ -78,10 +78,10 @@ export const DocumentsTemplate = ({ idCategory, idWell: wellId, mimeTypes, heade
setPagination(newPagination)
},
setShowLoader,
`Не удалось загрузить файлы по скважине "${idWell}"`,
`Не удалось загрузить файлы по скважине "${well.caption}"`,
'Загрузка файла по скважине'
)
}, [filterCompanyName, filterDataRange, filterFileName, idCategory, idWell, page])
}, [filterCompanyName, filterDataRange, filterFileName, idCategory, well, page])
useEffect(() => {
update()
@ -92,9 +92,9 @@ export const DocumentsTemplate = ({ idCategory, idWell: wellId, mimeTypes, heade
}, [files, onChange])
const handleFileDelete = useMemo(() => hasPermission(`File.edit${idCategory}`) && (async (file) => {
await FileService.delete(idWell, file.id)
await FileService.delete(well.id, file.id)
update()
}), [idWell, idCategory, update])
}), [well, idCategory, update])
return (
<LoaderPortal show={showLoader}>

View File

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

View File

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

View File

@ -1,7 +1,7 @@
import { useCallback, useEffect, useState } from 'react'
import { Button, DatePicker, Input, Modal } from 'antd'
import { useIdWell } from '@asb/context'
import { useWell } from '@asb/context'
import { CompanyView } from '@components/views'
import DownloadLink from '@components/DownloadLink'
import LoaderPortal from '@components/LoaderPortal'
@ -65,7 +65,7 @@ export const CategoryHistory = ({ idCategory, visible, onClose }) => {
const [isLoading, setIsLoading] = useState(false)
const [companyName, setCompanyName] = useState('')
const idWell = useIdWell()
const [well] = useWell()
useEffect(() => {
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 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)
setData(arrayOrDefault(paginatedHistory?.items))
},
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) => {
setPage(page)

View File

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

View File

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

View File

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

View File

@ -2,7 +2,7 @@ import { useState, useEffect, memo } from 'react'
import { TableOutlined } from '@ant-design/icons'
import { Button } from 'antd'
import { useIdWell } from '@asb/context'
import { useWell } from '@asb/context'
import LoaderPortal from '@components/LoaderPortal'
import { invokeWebApiWrapperAsync } from '@components/factory'
import { wrapPrivateComponent } from '@utils'
@ -49,13 +49,13 @@ const Measure = memo(() => {
const [data, setData] = useState(defaultData)
const [tableIdx, setTableIdx] = useState(-1)
const idWell = useIdWell()
const [well] = useWell()
useEffect(() => {
invokeWebApiWrapperAsync(
async () => {
if (!isMeasuresUpdating) return
const measures = await MeasureService.getHisory(idWell)
const measures = await MeasureService.getHisory(well.id)
setIsMeasuresUpdating(false)
setData(prevData => {
@ -69,10 +69,10 @@ const Measure = memo(() => {
})
},
setShowLoader,
`Не удалось загрузить последние данные по скважине ${idWell}`,
`Не удалось загрузить последние данные по скважине ${well.caption}`,
'Получение последних данных телеметрий'
)
}, [idWell, isMeasuresUpdating])
}, [well, isMeasuresUpdating])
return (
<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 moment from 'moment'
import { useIdWell } from '@asb/context'
import { useWell } from '@asb/context'
import LoaderPortal from '@components/LoaderPortal'
import { invokeWebApiWrapperAsync } from '@components/factory'
import { makeColumn, makeGroupColumn } from '@components/Table'
@ -248,7 +248,7 @@ const table2Summary = () => (
const makeItem = (name, label) => ({ name, label })
const renderDescriptions = (items) => items.map(({ name, label }) => (
<Descriptions.Item label={label}>
<Descriptions.Item key={`${name}`} label={label}>
<Item name={name}>
<Input style={{ width: '100%' }} />
</Item>
@ -289,7 +289,7 @@ export const ReportEditor = memo(({ visible, data, onDone, onCancel, checkIsDate
const [isInvalid, setIsInvalid] = useState(false)
const [isLoading, setIsLoading] = useState(false)
const idWell = useIdWell()
const [well] = useWell()
const setFields = useCallback((data) =>
form.setFieldsValue(data ? {
@ -315,20 +315,20 @@ export const ReportEditor = memo(({ visible, data, onDone, onCancel, checkIsDate
const onFormFinish = useCallback((formData) => invokeWebApiWrapperAsync(
async () => {
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)
else await DailyReportService.add(idWell, payload)
if (data) await DailyReportService.update(well.id, data.head.reportDate, payload)
else await DailyReportService.add(well.id, payload)
onDone?.(formData)
form.resetFields()
},
setIsLoading,
'Не удалось сохранить суточный рапорт',
`Не удалось сохранить суточный рапорт для скважины "${well.caption}"`,
'Сохранение суточного рапорта'
), [data, onDone, idWell, form])
), [data, onDone, well, form])
const onDateChange = useCallback((date) => invokeWebApiWrapperAsync(
async () => {
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)))
throw new Error('Рапорт на данную дату уже существует')
setFields(newData)
@ -336,7 +336,7 @@ export const ReportEditor = memo(({ visible, data, onDone, onCancel, checkIsDate
setIsLoading,
(e) => `Не удалось загрузить автозаполняемые данные для нового рапорта: ${e}`,
'Получение автозаполняемых данных суточного рапорта'
), [idWell, data, setFields, checkIsDateBusy])
), [well, data, setFields, checkIsDateBusy])
return (
<Modal

View File

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

View File

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

View File

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

View File

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

View File

@ -3,7 +3,7 @@ import { useNavigate } from 'react-router-dom'
import { CloseOutlined } from '@ant-design/icons'
import { Button, Menu, Popconfirm } from 'antd'
import { useIdWell, useRootPath } from '@asb/context'
import { useWell, useRootPath } from '@asb/context'
import LoaderPortal from '@components/LoaderPortal'
import { invokeWebApiWrapperAsync } from '@components/factory'
import { BaseWidget, WidgetSettingsWindow } from '@components/widgets'
@ -112,7 +112,7 @@ const DashboardNNB = memo(({ enableEditing = false }) => {
const [selectedSettings, setSelectedSettings] = useState(null)
const [values, setValues] = useState({})
const idWell = useIdWell()
const [well] = useWell()
const root = useRootPath()
const rootPath = useMemo(() => `${root}/dashboard_nnb`, [root])
const navigate = useNavigate()
@ -151,18 +151,18 @@ const DashboardNNB = memo(({ enableEditing = false }) => {
useEffect(() => {
invokeWebApiWrapperAsync(
async () => {
handleData(await WitsRecord1Service.getLastData(idWell), '1')
handleData(await WitsRecord7Service.getLastData(idWell), '7')
handleData(await WitsRecord8Service.getLastData(idWell), '8')
handleData(await WitsRecord50Service.getLastData(idWell), '50')
handleData(await WitsRecord60Service.getLastData(idWell), '60')
handleData(await WitsRecord61Service.getLastData(idWell), '61')
handleData(await WitsRecord1Service.getLastData(well.id), '1')
handleData(await WitsRecord7Service.getLastData(well.id), '7')
handleData(await WitsRecord8Service.getLastData(well.id), '8')
handleData(await WitsRecord50Service.getLastData(well.id), '50')
handleData(await WitsRecord60Service.getLastData(well.id), '60')
handleData(await WitsRecord61Service.getLastData(well.id), '61')
},
setIsLoading,
'Не удалось загрузить последние данные',
`Не удалось загрузить последние данные по скважине ${well.caption}`,
'Получение данных WITS',
)
return Subscribe('hubs/telemetry', `well_${idWell}_wits`,
return Subscribe('hubs/telemetry', `well_${well.id}_wits`,
{ methodName: 'ReceiveWitsRecord1', handler: (data) => handleData(data, '1') },
{ methodName: 'ReceiveWitsRecord7', handler: (data) => handleData(data, '7') },
{ methodName: 'ReceiveWitsRecord8', handler: (data) => handleData(data, '8') },
@ -170,7 +170,7 @@ const DashboardNNB = memo(({ enableEditing = false }) => {
{ methodName: 'ReceiveWitsRecord60', handler: (data) => handleData(data, '60') },
{ methodName: 'ReceiveWitsRecord61', handler: (data) => handleData(data, '61') },
)
}, [idWell, handleData])
}, [well, handleData])
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 moment from 'moment'
import { useIdWell } from '@asb/context'
import { useWell } from '@asb/context'
import LoaderPortal from '@components/LoaderPortal'
import { invokeWebApiWrapperAsync } from '@components/factory'
import { makeColumn, makeDateColumn, makeNumericColumn, makeNumericSorter, makeTextColumn, Table } from '@components/Table'
@ -69,18 +69,18 @@ const Messages = memo(() => {
const [searchString, setSearchString] = useState('')
const [showLoader, setShowLoader] = useState(false)
const idWell = useIdWell()
const [well] = useWell()
const onChangeSearchString = useCallback((message) => setSearchString(message.length > 2 ? message : ''), [])
const columns = useMemo(() => makeMessageColumns(idWell), [idWell])
const columns = useMemo(() => makeMessageColumns(well.id), [well])
useEffect(() => {
invokeWebApiWrapperAsync(
async () => {
const [begin, end] = range?.length > 1 ? [range[0].toISOString(), range[1].toISOString()] : [null, null]
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
setMessages(paginatedMessages.items.map(m => ({
@ -95,10 +95,10 @@ const Messages = memo(() => {
})
},
setShowLoader,
`Не удалось загрузить сообщения по скважине "${idWell}"`,
`Не удалось загрузить сообщения по скважине "${well.caption}"`,
'Полученик списка сообщений'
)
}, [idWell, page, categories, range, searchString])
}, [well, page, categories, range, searchString])
return (
<>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -5,13 +5,15 @@ import {
DeploymentUnitOutlined,
} from '@ant-design/icons'
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 { IdWellContext, RootPathContext, useRootPath } from '@asb/context'
import { WellContext, RootPathContext, useRootPath } from '@asb/context'
import { LayoutPortal } from '@components/Layout'
import { PrivateMenu } from '@components/Private'
import { invokeWebApiWrapperAsync } from '@components/factory'
import { NoAccessComponent, wrapPrivateComponent } from '@utils'
import { WellService } from '@api'
import Measure from './Measure'
import Reports from './Reports'
@ -27,9 +29,33 @@ const { Content } = Layout
const Well = memo(() => {
const { idWell } = useParams()
const [well, setWell] = useState({ id: idWell })
const root = useRootPath()
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 (
<LayoutPortal>
<RootPathContext.Provider value={rootPath}>
@ -43,7 +69,7 @@ const Well = memo(() => {
<PrivateMenu.Link content={DrillingProgram} icon={<FolderOutlined />} />
</PrivateMenu>
<IdWellContext.Provider value={idWell}>
<WellContext.Provider value={[well, updateWell]}>
<Layout>
<Content className={'site-layout-background'}>
<Routes>
@ -60,7 +86,7 @@ const Well = memo(() => {
</Routes>
</Content>
</Layout>
</IdWellContext.Provider>
</WellContext.Provider>
</RootPathContext.Provider>
</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 { invokeWebApiWrapperAsync } from '@components/factory'
import { EditableTable, makeNumericMinMax, makeNumericStartEnd } from '@components/Table'
@ -21,21 +21,21 @@ export const DrillProcessFlow = memo(() => {
const [flows, setFlows] = useState([])
const [showLoader, setShowLoader] = useState(false)
const idWell = useIdWell()
const [well] = useWell()
const updateFlows = () => invokeWebApiWrapperAsync(
const updateFlows = useCallback(() => invokeWebApiWrapperAsync(
async () => {
const flows = await DrillFlowChartService.getByIdWell(idWell)
const flows = await DrillFlowChartService.getByIdWell(well.id)
setFlows(arrayOrDefault(flows))
},
setShowLoader,
'Не удалось загрузить режимно-технологическую карту скважины',
`Не удалось загрузить режимно-технологическую карту скважины "${well.caption}"`,
'Получение режимно-технологической карты скважины'
)
), [well])
useEffect(() => {
updateFlows()
}, [idWell])
}, [well])
const tableHandlers = useMemo(() => {
const handlerProps = {
@ -45,14 +45,14 @@ export const DrillProcessFlow = memo(() => {
permission: 'DrillFlowChart.edit',
}
const recordParser = (record) => ({ idWell, ...record })
const recordParser = (record) => ({ idWell: well.id, ...record })
return {
add: { ...handlerProps, action: 'insert', actionName: 'Добавление месторождения', recordParser },
edit: { ...handlerProps, action: 'update', actionName: 'Редактирование месторождения', recordParser },
delete: { ...handlerProps, action: 'delete', actionName: 'Удаление месторождения', permission: 'DrillFlowChart.delete' },
}
}, [updateFlows, idWell])
}, [updateFlows, well.di])
return (
<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 { FileOutlined, ImportOutlined, ExportOutlined } from '@ant-design/icons'
import { useIdWell } from '@asb/context'
import { useWell } from '@asb/context'
import { download } from '@components/factory'
import { hasPermission } from '@utils'
@ -10,19 +10,19 @@ import { ImportOperations } from './ImportOperations'
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 idWellContext = useIdWell()
const idWell = useMemo(() => wellId ?? idWellContext, [idWellContext])
const [wellContext] = useWell()
const well = useMemo(() => givenWell ?? wellContext, [givenWell, wellContext])
const downloadTemplate = async () => await download(`/api/well/${idWell}/wellOperations/template`)
const downloadExport = async () => await download(`/api/well/${idWell}/wellOperations/export`)
const downloadTemplate = useCallback(async () => await download(`/api/well/${well.id}/wellOperations/template`), [well.id])
const downloadExport = useCallback(async () => await download(`/api/well/${well.id}/wellOperations/export`), [well.id])
const onDone = () => {
const onDone = useCallback(() => {
setIsImportModalVisible(false)
onImported?.()
}
}, [onImported])
return (
<div>
@ -52,7 +52,7 @@ export const ImportExportBar = memo(({ idWell: wellId, onImported, disabled }) =
onCancel={() => setIsImportModalVisible(false)}
footer={null}
>
<ImportOperations idWell={idWell} onDone={onDone} />
<ImportOperations well={well} onDone={onDone} />
</Modal>
</div>
)

View File

@ -1,35 +1,38 @@
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 { UploadForm } from '@components/UploadForm'
const errorTextStyle = { color: 'red', fontWeight: 'bold' }
const uploadFormStyle = { marginTop: '24px' }
export const ImportOperations = memo(({ idWell, onDone }) =>{
export const ImportOperations = memo(({ well: givenWell, onDone }) => {
const [deleteBeforeImport, setDeleteBeforeImport] = useState(false)
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('')
onDone?.()
}
}, [onDone])
const onUploadError = (error) => {
if(error instanceof ErrorFetch && error.status === 400)
const onUploadError = useCallback((error) => {
if (error instanceof ErrorFetch && error.status === 400)
setErrorText(`Не удалось импортировать.\n ${error?.message}`)
else
setErrorText(`Не удалось импортировать.`)
}
else setErrorText(`Не удалось импортировать.`)
}, [])
return (
<div>
<p>Загрузить файл excel с операциями на сервер</p>
<span>Очистить список операций перед импортом&nbsp;</span>
<Switch onChange={setDeleteBeforeImport} checked={deleteBeforeImport}/>
<Switch onChange={setDeleteBeforeImport} checked={deleteBeforeImport} />
<UploadForm
url={url}
style={uploadFormStyle}

View File

@ -4,14 +4,14 @@ import { Button } from 'antd'
import { download, invokeWebApiWrapperAsync } from '@components/factory'
export const NetGraphExport = memo(({ idWell, ...other }) => {
export const NetGraphExport = memo(({ well, ...other }) => {
const [isFileExporting, setIsFileExporting] = useState(false)
const onExport = useCallback(() => invokeWebApiWrapperAsync(
async () => await download(`/api/well/${idWell}/wellOperations/scheduleReport`),
async () => await download(`/api/well/${well.id}/wellOperations/scheduleReport`),
setIsFileExporting,
'Не удалось загрузить файл'
), [idWell])
), [well.id])
return (
<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 { useIdWell } from '@asb/context'
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 [idCluster, setIdCluster] = useState()
const idWell = useIdWell()
useEffect(() => {
invokeWebApiWrapperAsync(
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}`),
const onExport = useCallback((isWell) => invokeWebApiWrapperAsync(
async () => await download(`/api/DetectedOperation/export?${isWell ? 'idWell' : 'idCluster'}=${isWell ? well.id : well.idCluster}`),
setIsFileExporting,
'Не удалось загрузить файл'
), [idWell, idCluster])
), [well])
return (
<Input.Group compact>

View File

@ -4,7 +4,6 @@ import { Empty } from 'antd'
import moment from 'moment'
import * as d3 from 'd3'
import { useIdWell } from '@asb/context'
import LoaderPortal from '@components/LoaderPortal'
import { invokeWebApiWrapperAsync } from '@components/factory'
import { DetectedOperationService } from '@api'
@ -44,6 +43,7 @@ const splitByDate = (startTime, endTime) => {
}
export const TLChart = memo(({
well,
backgroundColor = '#0000',
barHeight = 15,
offset = defaultOffset,
@ -59,8 +59,6 @@ export const TLChart = memo(({
const [rootRef, { width, height }] = useElementSize()
const idWell = useIdWell()
const dates = useMemo(() => {
if (!data || data.length <= 0) return [0, 0]
return [
@ -82,7 +80,7 @@ export const TLChart = memo(({
useEffect(() => {
invokeWebApiWrapperAsync(
async () => {
const { operations } = await DetectedOperationService.get(idWell)
const { operations } = await DetectedOperationService.get(well.id)
setData(operations.map((raw) => {
const startTime = moment(raw.dateStart)
const endTime = moment(raw.dateEnd)
@ -94,9 +92,9 @@ export const TLChart = memo(({
}).flat())
},
setIsLoading,
'Не удалось загрузить список операций'
`Не удалось загрузить список операций по скважине "${well.caption}"`
)
}, [idWell])
}, [well])
useEffect(() => { // Рисуем ось 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 * as d3 from 'd3'
import { useIdWell } from '@asb/context'
import { makeColumn, makeNumericColumn, makeTextColumn, Table } from '@components/Table'
import LoaderPortal from '@components/LoaderPortal'
import { invokeWebApiWrapperAsync } from '@components/factory'
@ -24,7 +23,7 @@ const tableColumns = [
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 [svgRef, setSvgRef] = useState()
const [stats, setStats] = useState([])
@ -32,8 +31,6 @@ export const TLPie = memo(() => {
const [rootRef, { width, height }] = useElementSize()
const idWell = useIdWell()
const pie = useMemo(() => d3.pie().value((d) => d.minutesTotal), [])
const getColor = useMemo(() => makeGetColor(stats?.map((row) => row.idCategory).filter(unique)), [stats])
@ -83,13 +80,13 @@ export const TLPie = memo(() => {
useEffect(() => {
invokeWebApiWrapperAsync(
async () => {
const stats = await DetectedOperationService.getStat(idWell)
const stats = await DetectedOperationService.getStat(well.id)
setStats(stats)
},
setIsLoading,
'Не удалось загрузить статистику автоопределённых операций'
`Не удалось загрузить статистику автоопределённых операций по скважине "${well.caption}"`
)
}, [idWell])
}, [well])
useEffect(() => {
if (!data) return

View File

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

View File

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

View File

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

View File

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