forked from ddrilling/asb_cloud_front
Merge branch 'dev' into feature/daily-report
This commit is contained in:
commit
b2d8b7729c
@ -1,8 +1,10 @@
|
||||
import {Row, Col} from 'antd'
|
||||
import Documents from '../Documents/DocumentsTemplate'
|
||||
import '../../styles/equipment_details.css'
|
||||
|
||||
export default function EquipmentDetails({id, equipmentTimers, equipmentSensors}) {
|
||||
import Documents from '../Documents/DocumentsTemplate'
|
||||
|
||||
import '@styles/equipment_details.css'
|
||||
|
||||
export default function EquipmentDetails({ id, equipmentTimers, equipmentSensors }) {
|
||||
let stateOfEquipmentDetails = equipmentTimers.map(timer => {
|
||||
return(
|
||||
<p key={timer.label}>{timer.label}: <span className="right-text"><b>{timer.value} {timer.unit}</b></span></p>
|
||||
|
49
src/components/Private/PrivateMenu.tsx
Normal file
49
src/components/Private/PrivateMenu.tsx
Normal file
@ -0,0 +1,49 @@
|
||||
import { join } from 'path'
|
||||
import { Menu, MenuItemProps, MenuProps } from 'antd'
|
||||
import { Children, cloneElement, memo, ReactElement, useContext, useMemo } from 'react'
|
||||
import { Link, useLocation } from 'react-router-dom'
|
||||
|
||||
import { isURLAvailable } from '@utils/permissions'
|
||||
import { RootPathContext } from '@pages/Main'
|
||||
|
||||
export type PrivateMenuProps = MenuProps & { root?: string }
|
||||
|
||||
export type PrivateMenuLinkProps = MenuItemProps & {
|
||||
tabName?: string
|
||||
path?: string
|
||||
title: string
|
||||
visible?: boolean
|
||||
}
|
||||
|
||||
export const PrivateMenuLink = memo<PrivateMenuLinkProps>(({ tabName = '', path = '', title, ...other }) => {
|
||||
const location = useLocation()
|
||||
return (
|
||||
<Menu.Item key={tabName} {...other}>
|
||||
<Link to={{ pathname: path, state: { from: location.pathname }}}>{title}</Link>
|
||||
</Menu.Item>
|
||||
)
|
||||
})
|
||||
|
||||
const PrivateMenuMain = memo<PrivateMenuProps>(({ root, children, ...other }) => {
|
||||
const rootContext = useContext(RootPathContext)
|
||||
const rootPath = useMemo(() => root ?? rootContext ?? '', [root, rootContext])
|
||||
|
||||
const items = useMemo(() => Children.toArray(children).map((child) => {
|
||||
const element = child as ReactElement
|
||||
let key = element.key?.toString()
|
||||
const visible: boolean | undefined = element.props.visible
|
||||
if (key && visible !== false) {
|
||||
key = key.slice(key.lastIndexOf('$') + 1) // Ключ автоматический преобразуется в "(.+)\$ключ"
|
||||
const path = join(rootPath, key)
|
||||
if (visible || isURLAvailable(path))
|
||||
return cloneElement(element, { key, path, tabName: key })
|
||||
}
|
||||
return null
|
||||
}), [children, rootPath])
|
||||
|
||||
return <Menu children={items} {...other} />
|
||||
})
|
||||
|
||||
export const PrivateMenu = Object.assign(PrivateMenuMain, { Link: PrivateMenuLink })
|
||||
|
||||
export default PrivateMenu
|
@ -1,22 +1,22 @@
|
||||
import { join } from 'path'
|
||||
import { Menu, MenuItemProps } from 'antd'
|
||||
import { memo, NamedExoticComponent } from 'react'
|
||||
import { Link, useLocation } from 'react-router-dom'
|
||||
|
||||
import { isURLAvailable } from '@utils/permissions'
|
||||
import { Link, useLocation } from 'react-router-dom'
|
||||
|
||||
export type PrivateMenuItemProps = MenuItemProps & {
|
||||
root: string
|
||||
path: string
|
||||
}
|
||||
|
||||
export type PrivateMenuLinkProps = MenuItemProps & {
|
||||
export type PrivateMenuItemLinkProps = MenuItemProps & {
|
||||
root?: string
|
||||
path: string
|
||||
title: string
|
||||
}
|
||||
|
||||
export const PrivateMenuItemLink = memo<PrivateMenuLinkProps>(({ root = '', path, title, ...other }) => {
|
||||
export const PrivateMenuItemLink = memo<PrivateMenuItemLinkProps>(({ root = '', path, title, ...other }) => {
|
||||
const location = useLocation()
|
||||
return (
|
||||
<PrivateMenuItem key={path} root={root} path={path} {...other}>
|
||||
@ -26,9 +26,9 @@ export const PrivateMenuItemLink = memo<PrivateMenuLinkProps>(({ root = '', path
|
||||
})
|
||||
|
||||
export const PrivateMenuItem: NamedExoticComponent<PrivateMenuItemProps> & {
|
||||
Link: NamedExoticComponent<PrivateMenuLinkProps>
|
||||
Link: NamedExoticComponent<PrivateMenuItemLinkProps>
|
||||
} = Object.assign(memo<PrivateMenuItemProps>(({ root, path, ...other }) =>
|
||||
isURLAvailable(join(root, path)) ? <Menu.Item key={path} {...other}/> : null
|
||||
<Menu.Item key={path} hidden={!isURLAvailable(join(root, path))} {...other} />
|
||||
), {
|
||||
Link: PrivateMenuItemLink
|
||||
})
|
||||
|
75
src/components/Private/PrivateSwitch.tsx
Normal file
75
src/components/Private/PrivateSwitch.tsx
Normal file
@ -0,0 +1,75 @@
|
||||
import { join } from 'path'
|
||||
import { Location } from 'history'
|
||||
import { Children, cloneElement, memo, ReactElement, ReactNode, useCallback, useContext, useMemo } from 'react'
|
||||
|
||||
import { Redirect, Route, Switch, SwitchProps, useLocation } from 'react-router-dom'
|
||||
import { isURLAvailable } from '@utils/permissions'
|
||||
import { getUserId } from '@utils/storage'
|
||||
|
||||
import { RootPathContext } from '@pages/Main'
|
||||
|
||||
export type PrivateSwitchProps = SwitchProps & {
|
||||
root?: string
|
||||
redirect?: (location?: Location<unknown>) => ReactNode
|
||||
elseRedirect?: string | string[]
|
||||
}
|
||||
|
||||
const getDefaultRedirectPath = () => getUserId() ? '/access_denied' : '/login'
|
||||
|
||||
export const defaultRedirect = (location?: Location<unknown>) => (
|
||||
<Redirect to={{ pathname: getDefaultRedirectPath(), state: { from: location?.pathname } }} />
|
||||
)
|
||||
|
||||
export const PrivateSwitch = memo<PrivateSwitchProps>(({ root, elseRedirect, redirect = defaultRedirect, children }) => {
|
||||
const rootContext = useContext(RootPathContext)
|
||||
const rootPath = useMemo(() => root ?? rootContext ?? '', [root, rootContext])
|
||||
|
||||
const location = useLocation()
|
||||
|
||||
const toAbsolute = useCallback((path: string) => path.startsWith('/') ? path : join(rootPath, path), [rootPath])
|
||||
|
||||
const items = useMemo(() => Children.toArray(children).map((child) => {
|
||||
const element = child as ReactElement
|
||||
let key = element.key?.toString()
|
||||
if (!key) return null
|
||||
key = key.slice(key.lastIndexOf('$') + 1).replaceAll('=2', ':')
|
||||
// Ключ автоматический преобразуется в "(.+)\$ключ"
|
||||
// Все ":" в ключе заменяются на "=2"
|
||||
// TODO: улучшить метод нормализации ключа
|
||||
const path = toAbsolute(key)
|
||||
return (
|
||||
<Route
|
||||
key={key}
|
||||
path={path}
|
||||
render={({ location }) => isURLAvailable(path) ? cloneElement(element) : redirect(location)}
|
||||
/>
|
||||
)
|
||||
}), [children, redirect, toAbsolute])
|
||||
|
||||
const defaultRoute = useMemo(() => {
|
||||
if (!elseRedirect) {
|
||||
const path = items.map((elm) => elm?.props.path).find((path) => path && isURLAvailable(path))
|
||||
if (path) return path
|
||||
} else if (Array.isArray(elseRedirect)) {
|
||||
const path = elseRedirect.find((path) => {
|
||||
if (!path) return false
|
||||
return isURLAvailable(toAbsolute(path))
|
||||
})
|
||||
if (path) return toAbsolute(path)
|
||||
} else if(elseRedirect && isURLAvailable(toAbsolute(elseRedirect))) {
|
||||
return toAbsolute(elseRedirect)
|
||||
}
|
||||
return getDefaultRedirectPath()
|
||||
}, [items, elseRedirect, toAbsolute])
|
||||
|
||||
return (
|
||||
<Switch>
|
||||
{items}
|
||||
<Route path={'/'}>
|
||||
<Redirect to={{ pathname: defaultRoute, state: { from: location.pathname } }} />
|
||||
</Route>
|
||||
</Switch>
|
||||
)
|
||||
})
|
||||
|
||||
export default PrivateSwitch
|
@ -1,9 +1,13 @@
|
||||
export { PrivateRoute, defaultRedirect } from './PrivateRoute'
|
||||
export { PrivateContent } from './PrivateContent'
|
||||
export { PrivateMenuItem, PrivateMenuItemLink } from './PrivateMenuItem'
|
||||
export { PrivateContent } from './PrivateContent' // TODO: Remove
|
||||
export { PrivateMenuItem, PrivateMenuItemLink } from './PrivateMenuItem' // TODO: Remove
|
||||
export { PrivateDefaultRoute } from './PrivateDefaultRoute'
|
||||
export { PrivateMenu, PrivateMenuLink } from './PrivateMenu'
|
||||
export { PrivateSwitch } from './PrivateSwitch'
|
||||
|
||||
export type { PrivateRouteProps } from './PrivateRoute'
|
||||
export type { PrivateContentProps } from './PrivateContent'
|
||||
export type { PrivateMenuItemProps, PrivateMenuLinkProps } from './PrivateMenuItem'
|
||||
export type { PrivateContentProps } from './PrivateContent' // TODO: Remove
|
||||
export type { PrivateMenuItemProps, PrivateMenuItemLinkProps } from './PrivateMenuItem' // TODO: Remove
|
||||
export type { PrivateDefaultRouteProps } from './PrivateDefaultRoute'
|
||||
export type { PrivateMenuProps, PrivateMenuLinkProps } from './PrivateMenu'
|
||||
export type { PrivateSwitchProps } from './PrivateSwitch'
|
||||
|
@ -1,41 +1,41 @@
|
||||
import { Layout, Menu } from 'antd'
|
||||
import { lazy, memo, Suspense } from 'react'
|
||||
import { Switch, useParams } from 'react-router-dom'
|
||||
import { Layout } from 'antd'
|
||||
import { lazy, memo, Suspense, useContext, useMemo } from 'react'
|
||||
import { useParams } from 'react-router-dom'
|
||||
|
||||
import { PrivateMenuItem, PrivateRoute, PrivateDefaultRoute } from '@components/Private'
|
||||
import { PrivateMenu, PrivateSwitch } from '@components/Private'
|
||||
|
||||
import { SuspenseFallback } from '@pages/SuspenseFallback'
|
||||
import { RootPathContext } from '@pages/Main'
|
||||
|
||||
const TelemetryViewer = lazy(() => import('./TelemetryViewer'))
|
||||
const TelemetryMerger = lazy(() => import('./TelemetryMerger'))
|
||||
|
||||
const rootPath = '/admin/telemetry'
|
||||
|
||||
export const Telemetry = memo(() => {
|
||||
const { tab } = useParams()
|
||||
|
||||
const root = useContext(RootPathContext)
|
||||
const rootPath = useMemo(() => `${root}/telemetry`, [root])
|
||||
|
||||
return (
|
||||
<RootPathContext.Provider value={rootPath}>
|
||||
<Layout>
|
||||
<Menu mode={'horizontal'} selectable={true} selectedKeys={[tab]}>
|
||||
<PrivateMenuItem.Link root={rootPath} key={'viewer'} path={'viewer'} title={'Просмотр'} />
|
||||
<PrivateMenuItem.Link root={rootPath} key={'merger'} path={'merger'} title={'Объединение'} />
|
||||
</Menu>
|
||||
<PrivateMenu mode={'horizontal'} selectable={true} selectedKeys={[tab]}>
|
||||
<PrivateMenu.Link key={'viewer'} title={'Просмотр'} />
|
||||
<PrivateMenu.Link key={'merger'} title={'Объединение'} />
|
||||
</PrivateMenu>
|
||||
|
||||
<Layout>
|
||||
<Layout.Content className={'site-layout-background'}>
|
||||
<Suspense fallback={<SuspenseFallback />}>
|
||||
<Switch>
|
||||
<PrivateRoute path={`${rootPath}/viewer`} component={TelemetryViewer} />
|
||||
<PrivateRoute path={`${rootPath}/merger`} component={TelemetryMerger} />
|
||||
<PrivateDefaultRoute urls={[
|
||||
`${rootPath}/viewer`,
|
||||
`${rootPath}/merger`,
|
||||
]}/>
|
||||
</Switch>
|
||||
<PrivateSwitch elseRedirect={['viewer', 'merger']}>
|
||||
<TelemetryViewer key={'viewer'} />
|
||||
<TelemetryMerger key={'merger'} />
|
||||
</PrivateSwitch>
|
||||
</Suspense>
|
||||
</Layout.Content>
|
||||
</Layout>
|
||||
</Layout>
|
||||
</RootPathContext.Provider>
|
||||
)
|
||||
})
|
||||
|
||||
|
@ -188,7 +188,7 @@ export const UserController = memo(() => {
|
||||
allowClear
|
||||
placeholder={'Введите текст для поиска (по всем полям за исключением ролей)...'}
|
||||
onChange={onSearchTextChange}
|
||||
style={{ marginBottom: '15px' }}
|
||||
style={{ margin: '15px 0' }}
|
||||
loading={isSearching}
|
||||
/>
|
||||
<EditableTable
|
||||
|
@ -1,9 +1,10 @@
|
||||
import { Layout, Menu } from 'antd'
|
||||
import { lazy, memo, Suspense } from 'react'
|
||||
import { Switch, useParams } from 'react-router-dom'
|
||||
import { Layout } from 'antd'
|
||||
import { lazy, memo, Suspense, useContext, useMemo } from 'react'
|
||||
import { useParams } from 'react-router-dom'
|
||||
|
||||
import { PrivateMenuItem, PrivateRoute, PrivateDefaultRoute } from '@components/Private'
|
||||
import { PrivateMenu, PrivateSwitch } from '@components/Private'
|
||||
|
||||
import { RootPathContext } from '@pages/Main'
|
||||
import { SuspenseFallback } from '@pages/SuspenseFallback'
|
||||
|
||||
const ClusterController = lazy(() => import( './ClusterController'))
|
||||
@ -17,57 +18,48 @@ const PermissionController = lazy(() => import( './PermissionController'))
|
||||
const TelemetrySection = lazy(() => import( './Telemetry'))
|
||||
const VisitLog = lazy(() => import( './VisitLog'))
|
||||
|
||||
const rootPath = '/admin'
|
||||
|
||||
export const AdminPanel = memo(() => {
|
||||
const { tab } = useParams()
|
||||
|
||||
const root = useContext(RootPathContext)
|
||||
const rootPath = useMemo(() => `${root}/admin`, [root])
|
||||
|
||||
return (
|
||||
<RootPathContext.Provider value={rootPath}>
|
||||
<Layout>
|
||||
<Menu mode={'horizontal'} selectable={true} selectedKeys={[tab]}>
|
||||
<PrivateMenuItem.Link root={rootPath} key={'deposit' } path={'deposit' } title={'Месторождения' } />
|
||||
<PrivateMenuItem.Link root={rootPath} key={'cluster' } path={'cluster' } title={'Кусты' } />
|
||||
<PrivateMenuItem.Link root={rootPath} key={'well' } path={'well' } title={'Скважины' } />
|
||||
<PrivateMenuItem.Link root={rootPath} key={'user' } path={'user' } title={'Пользователи' } />
|
||||
<PrivateMenuItem.Link root={rootPath} key={'company' } path={'company' } title={'Компании' } />
|
||||
<PrivateMenuItem.Link root={rootPath} key={'company_type'} path={'company_type'} title={'Типы компаний' } />
|
||||
<PrivateMenuItem.Link root={rootPath} key={'role' } path={'role' } title={'Роли' } />
|
||||
<PrivateMenuItem.Link root={rootPath} key={'permission' } path={'permission' } title={'Разрешения' } />
|
||||
<PrivateMenuItem.Link root={rootPath} key={'telemetry' } path={'telemetry' } title={'Телеметрия' } />
|
||||
<PrivateMenuItem.Link root={rootPath} key={'visit_log' } path={'visit_log' } title={'Журнал посещений'} />
|
||||
</Menu>
|
||||
<PrivateMenu mode={'horizontal'} selectable={true} selectedKeys={[tab]}>
|
||||
<PrivateMenu.Link key={'deposit' } title={'Месторождения' } />
|
||||
<PrivateMenu.Link key={'cluster' } title={'Кусты' } />
|
||||
<PrivateMenu.Link key={'well' } title={'Скважины' } />
|
||||
<PrivateMenu.Link key={'user' } title={'Пользователи' } />
|
||||
<PrivateMenu.Link key={'company' } title={'Компании' } />
|
||||
<PrivateMenu.Link key={'company_type'} title={'Типы компаний' } />
|
||||
<PrivateMenu.Link key={'role' } title={'Роли' } />
|
||||
<PrivateMenu.Link key={'permission' } title={'Разрешения' } />
|
||||
<PrivateMenu.Link key={'telemetry' } title={'Телеметрия' } />
|
||||
<PrivateMenu.Link key={'visit_log' } title={'Журнал посещений'} />
|
||||
</PrivateMenu>
|
||||
|
||||
<Layout>
|
||||
<Layout.Content className={'site-layout-background'}>
|
||||
<Suspense fallback={<SuspenseFallback />}>
|
||||
<Switch>
|
||||
<PrivateRoute path={`${rootPath}/deposit` } component={ DepositController} />
|
||||
<PrivateRoute path={`${rootPath}/cluster` } component={ ClusterController} />
|
||||
<PrivateRoute path={`${rootPath}/well` } component={ WellController} />
|
||||
<PrivateRoute path={`${rootPath}/user` } component={ UserController} />
|
||||
<PrivateRoute path={`${rootPath}/company` } component={ CompanyController} />
|
||||
<PrivateRoute path={`${rootPath}/company_type` } component={CompanyTypeController} />
|
||||
<PrivateRoute path={`${rootPath}/role` } component={ RoleController} />
|
||||
<PrivateRoute path={`${rootPath}/permission` } component={ PermissionController} />
|
||||
<PrivateRoute path={`${rootPath}/telemetry/:tab?`} component={TelemetrySection} />
|
||||
<PrivateRoute path={`${rootPath}/visit_log` } component={VisitLog} />
|
||||
<PrivateDefaultRoute urls={[
|
||||
`${rootPath}/deposit`,
|
||||
`${rootPath}/cluster`,
|
||||
`${rootPath}/well`,
|
||||
`${rootPath}/user`,
|
||||
`${rootPath}/company`,
|
||||
`${rootPath}/company_type`,
|
||||
`${rootPath}/role`,
|
||||
`${rootPath}/permission`,
|
||||
`${rootPath}/telemetry`,
|
||||
`${rootPath}/visit_log`,
|
||||
]}/>
|
||||
</Switch>
|
||||
<PrivateSwitch elseRedirect={['deposit', 'cluster', 'well', 'user', 'company', 'company_type', 'role', 'permission', 'telemetry', 'visit_log']}>
|
||||
<DepositController key={'deposit'} />
|
||||
<ClusterController key={'cluster'} />
|
||||
<WellController key={'well'} />
|
||||
<UserController key={'user'} />
|
||||
<CompanyController key={'company'} />
|
||||
<CompanyTypeController key={'company_type'} />
|
||||
<RoleController key={'role'} />
|
||||
<PermissionController key={'permission'} />
|
||||
<TelemetrySection key={'telemetry/:tab?'} />
|
||||
<VisitLog key={'visit_log'} />
|
||||
</PrivateSwitch>
|
||||
</Suspense>
|
||||
</Layout.Content>
|
||||
</Layout>
|
||||
</Layout>
|
||||
</RootPathContext.Provider>
|
||||
)
|
||||
})
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Table as RawTable, Typography } from 'antd'
|
||||
import { Fragment, memo, useCallback, useEffect, useState } from 'react'
|
||||
import { Fragment, memo, useCallback, useContext, useEffect, useState } from 'react'
|
||||
|
||||
import LoaderPortal from '@components/LoaderPortal'
|
||||
import { invokeWebApiWrapperAsync } from '@components/factory'
|
||||
@ -8,6 +8,8 @@ import { makeGroupColumn, makeNumericColumn, makeNumericRender, makeTextColumn,
|
||||
import { OperationStatService, WellOperationService } from '@api'
|
||||
import { arrayOrDefault } from '@utils'
|
||||
|
||||
import { IdWellContext } from '../Well'
|
||||
|
||||
import '@styles/index.css'
|
||||
import '@styles/statistics.less'
|
||||
|
||||
@ -62,7 +64,7 @@ const getWellData = async (wellsList) => {
|
||||
return wellData
|
||||
}
|
||||
|
||||
export const Statistics = memo(({ idWell }) => {
|
||||
export const Statistics = memo(() => {
|
||||
const [sectionTypes, setSectionTypes] = useState([])
|
||||
const [avgColumns, setAvgColumns] = useState(defaultColumns)
|
||||
const [cmpColumns, setCmpColumns] = useState(defaultColumns)
|
||||
@ -75,6 +77,8 @@ export const Statistics = memo(({ idWell }) => {
|
||||
const [cmpData, setCmpData] = useState([])
|
||||
const [avgRow, setAvgRow] = useState({})
|
||||
|
||||
const idWell = useContext(IdWellContext)
|
||||
|
||||
const cmpSpeedRender = useCallback((key) => (section) => {
|
||||
let spanClass = ''
|
||||
// Дополнительная проверка на "null" необходима, чтобы значение "0" не стало исключением
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { memo, useCallback, useEffect, useState } from 'react'
|
||||
import { memo, useCallback, useContext, useEffect, useState } from 'react'
|
||||
import { Button, Modal, Popconfirm } from 'antd'
|
||||
|
||||
import { Table } from '@components/Table'
|
||||
@ -6,14 +6,17 @@ import LoaderPortal from '@components/LoaderPortal'
|
||||
import { invokeWebApiWrapperAsync } from '@components/factory'
|
||||
import { DrillParamsService } from '@api'
|
||||
|
||||
import { IdWellContext } from '@pages/Well'
|
||||
import { getColumns } from '@pages/WellOperations/WellDrillParams'
|
||||
|
||||
export const NewParamsTable = memo(({ idWell, selectedWellsKeys }) => {
|
||||
export const NewParamsTable = memo(({ selectedWellsKeys }) => {
|
||||
const [params, setParams] = useState([])
|
||||
const [paramsColumns, setParamsColumns] = useState([])
|
||||
const [showParamsLoader, setShowParamsLoader] = useState(false)
|
||||
const [isParamsModalVisible, setIsParamsModalVisible] = useState(false)
|
||||
|
||||
const idWell = useContext(IdWellContext)
|
||||
|
||||
useEffect(() => invokeWebApiWrapperAsync(
|
||||
async () => setParamsColumns(await getColumns(idWell))
|
||||
), [idWell])
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Link, useLocation } from 'react-router-dom'
|
||||
import { useState, useEffect, memo, useMemo } from 'react'
|
||||
import { useState, useEffect, memo, useMemo, useContext } from 'react'
|
||||
import { LineChartOutlined, ProfileOutlined } from '@ant-design/icons'
|
||||
import { Table, Tag, Button, Badge, Divider, Modal, Row, Col } from 'antd'
|
||||
|
||||
@ -15,6 +15,7 @@ import {
|
||||
getOperations
|
||||
} from '@utils/functions'
|
||||
|
||||
import { IdWellContext } from '@pages/Well'
|
||||
import { Tvd } from '@pages/WellOperations/Tvd'
|
||||
import WellOperationsTable from '@pages/Cluster/WellOperationsTable'
|
||||
import NewParamsTable from './NewParamsTable'
|
||||
@ -29,7 +30,7 @@ const sortBySectionId = (a, b) => a.sectionId - b.sectionId
|
||||
const filtersSectionsType = []
|
||||
const DAY_IN_MS = 1000 * 60 * 60 * 24
|
||||
|
||||
export const WellCompositeSections = memo(({ idWell, statsWells, selectedSections }) => {
|
||||
export const WellCompositeSections = memo(({ statsWells, selectedSections }) => {
|
||||
const [selectedWells, setSelectedWells] = useState([])
|
||||
const [wellOperations, setWellOperations] = useState([])
|
||||
const [selectedWellsKeys, setSelectedWellsKeys] = useState([])
|
||||
@ -38,6 +39,8 @@ export const WellCompositeSections = memo(({ idWell, statsWells, selectedSection
|
||||
const [isTVDModalVisible, setIsTVDModalVisible] = useState(false)
|
||||
const [isOpsModalVisible, setIsOpsModalVisible] = useState(false)
|
||||
|
||||
const idWell = useContext(IdWellContext)
|
||||
|
||||
const location = useLocation()
|
||||
|
||||
const rows = useMemo(() => {
|
||||
@ -208,9 +211,7 @@ export const WellCompositeSections = memo(({ idWell, statsWells, selectedSection
|
||||
pagination={false}
|
||||
/>
|
||||
<Row justify={'end'} style={{ margin: '1rem 0' }}>
|
||||
<Col>
|
||||
<NewParamsTable idWell={idWell} selectedWellsKeys={selectedWellsKeys} />
|
||||
</Col>
|
||||
<Col><NewParamsTable selectedWellsKeys={selectedWellsKeys} /></Col>
|
||||
</Row>
|
||||
|
||||
<Modal
|
||||
|
@ -1,24 +1,23 @@
|
||||
import { useState, useEffect, memo } from 'react'
|
||||
import { Switch, useParams } from 'react-router-dom'
|
||||
import { Col, Layout, Menu, Row } from 'antd'
|
||||
import { useState, useEffect, memo, useContext } from 'react'
|
||||
import { useParams } from 'react-router-dom'
|
||||
import { Col, Layout, Row } from 'antd'
|
||||
|
||||
import {
|
||||
OperationStatService,
|
||||
WellCompositeService,
|
||||
} from '@api'
|
||||
import { arrayOrDefault } from '@utils'
|
||||
import LoaderPortal from '@components/LoaderPortal'
|
||||
import WellSelector from '@components/selectors/WellSelector'
|
||||
import { invokeWebApiWrapperAsync } from '@components/factory'
|
||||
import { PrivateDefaultRoute, PrivateMenuItemLink, PrivateRoute } from '@components/Private'
|
||||
import { PrivateMenu, PrivateSwitch } from '@components/Private'
|
||||
import { OperationStatService, WellCompositeService } from '@api'
|
||||
|
||||
import { IdWellContext } from '@pages/Well'
|
||||
import ClusterWells from '@pages/Cluster/ClusterWells'
|
||||
import { WellCompositeSections } from './WellCompositeSections'
|
||||
|
||||
const { Content } = Layout
|
||||
|
||||
export const WellCompositeEditor = memo(({ idWell, rootPath }) => {
|
||||
export const WellCompositeEditor = memo(({ rootPath }) => {
|
||||
const { tab } = useParams()
|
||||
const idWell = useContext(IdWellContext)
|
||||
|
||||
const [statsWells, setStatsWells] = useState([])
|
||||
const [showLoader, setShowLoader] = useState(false)
|
||||
@ -67,28 +66,19 @@ export const WellCompositeEditor = memo(({ idWell, rootPath }) => {
|
||||
/>
|
||||
</Col>
|
||||
<Col span={6}>
|
||||
<Menu mode={'horizontal'} selectable={true} className={'well_menu'} selectedKeys={[tab]}>
|
||||
<PrivateMenuItemLink root={rootPath} key={'wells'} path={'wells'} title={'Статистика по скважинам'} />
|
||||
<PrivateMenuItemLink root={rootPath} key={'sections'} path={'sections'} title={'Статистика по секциям'} />
|
||||
</Menu>
|
||||
<PrivateMenu root={rootPath} mode={'horizontal'} selectable={true} className={'well_menu'} selectedKeys={[tab]}>
|
||||
<PrivateMenu.Link key={'wells'} title={'Статистика по скважинам'} />
|
||||
<PrivateMenu.Link key={'sections'} title={'Статистика по секциям'} />
|
||||
</PrivateMenu>
|
||||
</Col>
|
||||
</Row>
|
||||
<Layout>
|
||||
<Content className={'site-layout-background'}>
|
||||
<LoaderPortal show={showTabLoader}>
|
||||
<Switch>
|
||||
<PrivateRoute path={`${rootPath}/wells`}>
|
||||
<ClusterWells statsWells={statsWells}/>
|
||||
</PrivateRoute>
|
||||
<PrivateRoute path={`${rootPath}/sections`}>
|
||||
<WellCompositeSections
|
||||
idWell={idWell}
|
||||
statsWells={statsWells}
|
||||
selectedSections={selectedSections}
|
||||
/>
|
||||
</PrivateRoute>
|
||||
<PrivateDefaultRoute urls={[`${rootPath}/wells`, `${rootPath}/sections`]}/>
|
||||
</Switch>
|
||||
<PrivateSwitch root={rootPath} elseRedirect={['wells', 'sections']}>
|
||||
<ClusterWells key={'wells'} statsWells={statsWells} />
|
||||
<WellCompositeSections key={'sections'} statsWells={statsWells} selectedSections={selectedSections} />
|
||||
</PrivateSwitch>
|
||||
</LoaderPortal>
|
||||
</Content>
|
||||
</Layout>
|
||||
|
@ -1,36 +1,35 @@
|
||||
import { memo, useMemo } from 'react'
|
||||
import { Layout, Menu } from 'antd'
|
||||
import { Switch, useParams } from 'react-router-dom'
|
||||
import { memo, useContext, useMemo } from 'react'
|
||||
import { useParams } from 'react-router-dom'
|
||||
import { Layout } from 'antd'
|
||||
|
||||
import { PrivateDefaultRoute, PrivateMenuItemLink, PrivateRoute } from '@components/Private'
|
||||
import { PrivateMenu, PrivateSwitch } from '@components/Private'
|
||||
|
||||
import WellCompositeEditor from './WellCompositeEditor'
|
||||
import Statistics from './Statistics'
|
||||
import WellCompositeEditor from './WellCompositeEditor'
|
||||
import { RootPathContext } from '@pages/Main'
|
||||
|
||||
export const Analytics = memo(({ idWell }) => {
|
||||
export const Analytics = memo(() => {
|
||||
const { tab } = useParams()
|
||||
const rootPath = useMemo(() => `/well/${idWell}/analytics`, [idWell])
|
||||
const root = useContext(RootPathContext)
|
||||
const rootPath = useMemo(() => `${root}/analytics`, [root])
|
||||
|
||||
return (
|
||||
<RootPathContext.Provider value={rootPath}>
|
||||
<Layout>
|
||||
<Menu mode={'horizontal'} selectable={true} className={'well_menu'} selectedKeys={[tab]}>
|
||||
<PrivateMenuItemLink root={rootPath} key={'composite'} path={'composite'} title={'Композитная скважина'} />
|
||||
<PrivateMenuItemLink root={rootPath} key={'statistics'} path={'statistics'} title={'Оценка по ЦБ'} />
|
||||
</Menu>
|
||||
<PrivateMenu mode={'horizontal'} selectable={true} className={'well_menu'} selectedKeys={[tab]}>
|
||||
<PrivateMenu.Link key={'composite'} title={'Композитная скважина'} />
|
||||
<PrivateMenu.Link key={'statistics'} title={'Оценка по ЦБ'} />
|
||||
</PrivateMenu>
|
||||
<Layout>
|
||||
<Layout.Content>
|
||||
<Switch>
|
||||
<PrivateRoute path={`${rootPath}/composite/:tab?`}>
|
||||
<WellCompositeEditor idWell={idWell} rootPath={`${rootPath}/composite`} />
|
||||
</PrivateRoute>
|
||||
<PrivateRoute path={`${rootPath}/statistics`}>
|
||||
<Statistics idWell={idWell} />
|
||||
</PrivateRoute>
|
||||
<PrivateDefaultRoute urls={[`${rootPath}/composite`]}/>
|
||||
</Switch>
|
||||
<PrivateSwitch elseRedirect={'composite'}>
|
||||
<WellCompositeEditor key={'composite/:tab?'} rootPath={`${rootPath}/composite`} />
|
||||
<Statistics key={'statistics'} />
|
||||
</PrivateSwitch>
|
||||
</Layout.Content>
|
||||
</Layout>
|
||||
</Layout>
|
||||
</RootPathContext.Provider>
|
||||
)
|
||||
})
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { useState, useEffect, useMemo, useCallback } from 'react'
|
||||
import { useState, useEffect, useMemo, useCallback, useContext } from 'react'
|
||||
import { DatePicker, Button, Input } from 'antd'
|
||||
|
||||
import { FileService } from '@api'
|
||||
@ -9,6 +9,8 @@ import { EditableTable, makeColumn, makeDateColumn, makeNumericColumn, makePagin
|
||||
import { invokeWebApiWrapperAsync, downloadFile, formatBytes } from '@components/factory'
|
||||
import { hasPermission } from '@utils/permissions'
|
||||
|
||||
import { IdWellContext } from '@pages/Well'
|
||||
|
||||
const pageSize = 12
|
||||
const { RangePicker } = DatePicker
|
||||
const { Search } = Input
|
||||
@ -30,7 +32,7 @@ const columns = [
|
||||
makeColumn('Компания', 'company', { render: (_, record) => <CompanyView company={record?.author?.company}/> })
|
||||
]
|
||||
|
||||
export const DocumentsTemplate = ({ idCategory, idWell, accept, headerChild, customColumns, beforeTable, onChange, tableName }) => {
|
||||
export const DocumentsTemplate = ({ idCategory, idWell: wellId, accept, headerChild, customColumns, beforeTable, onChange, tableName }) => {
|
||||
const [page, setPage] = useState(1)
|
||||
const [filterDataRange, setFilterDataRange] = useState([])
|
||||
const [filterCompanyName, setFilterCompanyName] = useState([])
|
||||
@ -39,6 +41,9 @@ export const DocumentsTemplate = ({ idCategory, idWell, accept, headerChild, cus
|
||||
const [files, setFiles] = useState([])
|
||||
const [showLoader, setShowLoader] = useState(false)
|
||||
|
||||
const idwellContext = useContext(IdWellContext)
|
||||
const idWell = useMemo(() => wellId ?? idwellContext, [wellId])
|
||||
|
||||
const uploadUrl = useMemo(() => `/api/well/${idWell}/files/?idCategory=${idCategory}`, [idWell, idCategory])
|
||||
|
||||
const mergedColumns = useMemo(() => [...columns, ...(customColumns ?? [])], [customColumns])
|
||||
|
@ -1,12 +1,12 @@
|
||||
import { join } from 'path'
|
||||
import { memo, useMemo } from 'react'
|
||||
import { Layout, Menu } from 'antd'
|
||||
import { useParams } from 'react-router-dom'
|
||||
import { memo, useContext, useMemo } from 'react'
|
||||
import { FolderOutlined } from '@ant-design/icons'
|
||||
import { Switch, useParams } from 'react-router-dom'
|
||||
import { Layout } from 'antd'
|
||||
|
||||
import { PrivateDefaultRoute, PrivateMenuItemLink, PrivateRoute } from '@components/Private'
|
||||
import { PrivateMenu, PrivateSwitch } from '@components/Private'
|
||||
|
||||
import DocumentsTemplate from './DocumentsTemplate'
|
||||
import { RootPathContext } from '@pages/Main'
|
||||
|
||||
const { Content } = Layout
|
||||
|
||||
@ -23,37 +23,37 @@ export const documentCategories = [
|
||||
{ id: 9, key: 'closingService', title: 'Сервис по заканчиванию скважины' },
|
||||
]
|
||||
|
||||
export const MenuDocuments = memo(({ idWell }) => {
|
||||
export const MenuDocuments = memo(() => {
|
||||
const { category } = useParams()
|
||||
const root = useMemo(() => `/well/${idWell}/document`, [idWell])
|
||||
const root = useContext(RootPathContext)
|
||||
const rootPath = useMemo(() => `${root}/document`, [root])
|
||||
|
||||
return (
|
||||
<>
|
||||
<Menu mode={'horizontal'} selectable={true} className={'well_menu'} selectedKeys={[category]}>
|
||||
<RootPathContext.Provider value={rootPath}>
|
||||
<PrivateMenu mode={'horizontal'} selectable={true} className={'well_menu'} selectedKeys={[category]}>
|
||||
{documentCategories.map(category => (
|
||||
<PrivateMenuItemLink
|
||||
root={root}
|
||||
<PrivateMenu.Link
|
||||
key={`${category.key}`}
|
||||
path={`${category.key}`}
|
||||
className={'ant-menu-item'}
|
||||
icon={<FolderOutlined/>}
|
||||
title={category.title}
|
||||
/>
|
||||
))}
|
||||
</Menu>
|
||||
</PrivateMenu>
|
||||
<Layout>
|
||||
<Content className={'site-layout-background'}>
|
||||
<Switch>
|
||||
<PrivateSwitch elseRedirect={documentCategories.map((cat) => cat.key)}>
|
||||
{documentCategories.map(category => (
|
||||
<PrivateRoute path={join(root, category.key)} key={`${category.key}`}>
|
||||
<DocumentsTemplate idCategory={category.id} idWell={idWell} tableName={`documents_${category.key}`} />
|
||||
</PrivateRoute>
|
||||
<DocumentsTemplate
|
||||
key={category.key}
|
||||
idCategory={category.id}
|
||||
tableName={`documents_${category.key}`}
|
||||
/>
|
||||
))}
|
||||
<PrivateDefaultRoute urls={documentCategories.map((cat) => join(root, cat.key))}/>
|
||||
</Switch>
|
||||
</PrivateSwitch>
|
||||
</Content>
|
||||
</Layout>
|
||||
</>
|
||||
</RootPathContext.Provider>
|
||||
)
|
||||
})
|
||||
|
||||
|
@ -1,11 +1,13 @@
|
||||
import { Form, Select } from 'antd'
|
||||
import { FileAddOutlined } from '@ant-design/icons'
|
||||
import { memo, useCallback, useEffect, useState } from 'react'
|
||||
import { memo, useCallback, useContext, useEffect, useState } from 'react'
|
||||
|
||||
import Poprompt from '@components/selectors/Poprompt'
|
||||
import { invokeWebApiWrapperAsync } from '@components/factory'
|
||||
import { DrillingProgramService } from '@api'
|
||||
|
||||
import { IdWellContext } from '@pages/Well'
|
||||
|
||||
import '@styles/drilling_program.less'
|
||||
|
||||
const catSelectorRules = [{
|
||||
@ -13,12 +15,14 @@ const catSelectorRules = [{
|
||||
message: 'Пожалуйста, выберите категории'
|
||||
}]
|
||||
|
||||
export const CategoryAdder = memo(({ categories, idWell, onUpdate, className, ...other }) => {
|
||||
export const CategoryAdder = memo(({ categories, onUpdate, className, ...other }) => {
|
||||
const [options, setOptions] = useState([])
|
||||
const [value, setValue] = useState([])
|
||||
const [showLoader, setShowLoader] = useState(false)
|
||||
const [showCatLoader, setShowCatLoader] = useState(false)
|
||||
|
||||
const idWell = useContext(IdWellContext)
|
||||
|
||||
useEffect(() => invokeWebApiWrapperAsync(
|
||||
async () => {
|
||||
setOptions(categories.map((category) => ({
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Input, Modal, Radio } from 'antd'
|
||||
import { memo, useCallback, useEffect, useMemo, useState } from 'react'
|
||||
import { memo, useCallback, useContext, useEffect, useMemo, useState } from 'react'
|
||||
import { BehaviorSubject, debounceTime, distinctUntilChanged, filter, map } from 'rxjs'
|
||||
|
||||
import { UserView } from '@components/views'
|
||||
@ -9,6 +9,8 @@ import { makeColumn, makeNumericSorter, Table } from '@components/Table'
|
||||
import { DrillingProgramService } from '@api'
|
||||
import { arrayOrDefault } from '@utils'
|
||||
|
||||
import { IdWellContext } from '@pages/Well'
|
||||
|
||||
const userRules = [
|
||||
{ label: 'Нет', value: 0 },
|
||||
{ label: 'Публикатор', value: 1 },
|
||||
@ -17,7 +19,7 @@ const userRules = [
|
||||
|
||||
const SEARCH_TIMEOUT = 400
|
||||
|
||||
export const CategoryEditor = memo(({ idWell, visible, category, onClosed }) => {
|
||||
export const CategoryEditor = memo(({ visible, category, onClosed }) => {
|
||||
const [title, setTitle] = useState()
|
||||
const [users, setUsers] = useState([])
|
||||
const [allUsers, setAllUsers] = useState([])
|
||||
@ -27,6 +29,8 @@ export const CategoryEditor = memo(({ idWell, visible, category, onClosed }) =>
|
||||
const [searchValue, setSearchValue] = useState('')
|
||||
const [subject, setSubject] = useState(null)
|
||||
|
||||
const idWell = useContext(IdWellContext)
|
||||
|
||||
useEffect(() => invokeWebApiWrapperAsync(
|
||||
async () => {
|
||||
const filteredUsers = users.filter(({ user }) => user && [
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
import { useCallback, useContext, useEffect, useState } from 'react'
|
||||
import { Button, DatePicker, Input, Modal } from 'antd'
|
||||
|
||||
import { CompanyView } from '@components/views'
|
||||
@ -10,6 +10,7 @@ import { arrayOrDefault, formatDate } from '@utils'
|
||||
import { FileService } from '@api'
|
||||
|
||||
import MarksCard from './MarksCard'
|
||||
import { IdWellContext } from '@pages/Well'
|
||||
|
||||
import '@styles/drilling_program.less'
|
||||
|
||||
@ -54,7 +55,7 @@ export const historyColumns = [
|
||||
})
|
||||
]
|
||||
|
||||
export const CategoryHistory = ({ idWell, idCategory, visible, onClose }) => {
|
||||
export const CategoryHistory = ({ idCategory, visible, onClose }) => {
|
||||
const [data, setData] = useState([])
|
||||
const [page, setPage] = useState(1)
|
||||
const [total, setTotal] = useState(0)
|
||||
@ -64,6 +65,8 @@ export const CategoryHistory = ({ idWell, idCategory, visible, onClose }) => {
|
||||
const [isLoading, setIsLoading] = useState(false)
|
||||
const [companyName, setCompanyName] = useState('')
|
||||
|
||||
const idWell = useContext(IdWellContext)
|
||||
|
||||
useEffect(() => invokeWebApiWrapperAsync(
|
||||
async () => {
|
||||
if (!visible) return
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { memo, useCallback, useMemo, useState } from 'react'
|
||||
import { memo, useCallback, useContext, useMemo, useState } from 'react'
|
||||
import { Button, Input, Popconfirm, Form } from 'antd'
|
||||
import {
|
||||
DeleteOutlined,
|
||||
@ -16,6 +16,7 @@ import { DrillingProgramService } from '@api'
|
||||
import { formatDate } from '@utils'
|
||||
|
||||
import MarksCard from './MarksCard'
|
||||
import { IdWellContext } from '@pages/Well'
|
||||
|
||||
import '@styles/drilling_program.less'
|
||||
|
||||
@ -34,7 +35,7 @@ const CommentPrompt = memo(({ isRequired = true, ...props }) => (
|
||||
</Poprompt>
|
||||
))
|
||||
|
||||
export const CategoryRender = memo(({ idWell, partData, onUpdate, onEdit, onHistory, setIsLoading, ...other }) => {
|
||||
export const CategoryRender = memo(({ partData, onUpdate, onEdit, onHistory, setIsLoading, ...other }) => {
|
||||
const {
|
||||
idFileCategory,
|
||||
name: title, // Название категории
|
||||
@ -44,6 +45,8 @@ export const CategoryRender = memo(({ idWell, partData, onUpdate, onEdit, onHist
|
||||
file // Информация о файле
|
||||
} = partData ?? {}
|
||||
|
||||
const idWell = useContext(IdWellContext)
|
||||
|
||||
const uploadUrl = useMemo(() => `/api/well/${idWell}/drillingProgram/part/${idFileCategory}`, [idWell, idFileCategory])
|
||||
const approvedMarks = useMemo(() => file?.fileMarks?.filter((mark) => mark.idMarkType === 1), [file])
|
||||
const rejectMarks = useMemo(() => file?.fileMarks?.filter((mark) => mark.idMarkType === 0), [file])
|
||||
|
@ -8,7 +8,7 @@ import {
|
||||
ReloadOutlined,
|
||||
WarningOutlined,
|
||||
} from '@ant-design/icons'
|
||||
import { memo, useCallback, useEffect, useMemo, useState } from 'react'
|
||||
import { memo, useCallback, useContext, useEffect, useMemo, useState } from 'react'
|
||||
|
||||
import LoaderPortal from '@components/LoaderPortal'
|
||||
import { downloadFile, formatBytes, invokeWebApiWrapperAsync } from '@components/factory'
|
||||
@ -19,6 +19,7 @@ import CategoryAdder from './CategoryAdder'
|
||||
import CategoryRender from './CategoryRender'
|
||||
import CategoryEditor from './CategoryEditor'
|
||||
import CategoryHistory from './CategoryHistory'
|
||||
import { IdWellContext } from '@pages/Well'
|
||||
|
||||
import '@styles/drilling_program.less'
|
||||
|
||||
@ -38,7 +39,7 @@ const stateString = {
|
||||
[idStateUnknown]: { icon: WarningOutlined, text: 'Неизвестно' },
|
||||
}
|
||||
|
||||
export const DrillingProgram = memo(({ idWell }) => {
|
||||
export const DrillingProgram = memo(() => {
|
||||
const [selectedCategory, setSelectedCategory] = useState()
|
||||
const [historyVisible, setHistoryVisible] = useState(false)
|
||||
const [editorVisible, setEditorVisible] = useState(false)
|
||||
@ -46,6 +47,8 @@ export const DrillingProgram = memo(({ idWell }) => {
|
||||
const [categories, setCategories] = useState([])
|
||||
const [data, setData] = useState({})
|
||||
|
||||
const idWell = useContext(IdWellContext)
|
||||
|
||||
const {
|
||||
idState,
|
||||
permissionToEdit,
|
||||
@ -99,11 +102,7 @@ export const DrillingProgram = memo(({ idWell }) => {
|
||||
<h3>Программа бурения</h3>
|
||||
{permissionToEdit && (
|
||||
<div>
|
||||
<CategoryAdder
|
||||
idWell={idWell}
|
||||
categories={categories}
|
||||
onUpdate={updateData}
|
||||
/>
|
||||
<CategoryAdder categories={categories} onUpdate={updateData} />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
@ -143,7 +142,6 @@ export const DrillingProgram = memo(({ idWell }) => {
|
||||
{parts?.map?.((part, idx) => part && (
|
||||
<CategoryRender
|
||||
key={`${idx}`}
|
||||
idWell={idWell}
|
||||
partData={part}
|
||||
onEdit={permissionToEdit && onCategoryEdit}
|
||||
onUpdate={updateData}
|
||||
@ -154,7 +152,6 @@ export const DrillingProgram = memo(({ idWell }) => {
|
||||
{permissionToEdit && (
|
||||
<>
|
||||
<CategoryEditor
|
||||
idWell={idWell}
|
||||
visible={editorVisible}
|
||||
onClosed={onEditorClosed}
|
||||
category={parts?.find((part) => part.idFileCategory === selectedCategory) ?? {}}
|
||||
@ -163,7 +160,6 @@ export const DrillingProgram = memo(({ idWell }) => {
|
||||
)}
|
||||
|
||||
<CategoryHistory
|
||||
idWell={idWell}
|
||||
idCategory={selectedCategory}
|
||||
onClose={() => setHistoryVisible(false)}
|
||||
visible={historyVisible}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { memo } from 'react'
|
||||
import { createContext, memo } from 'react'
|
||||
import { Route, Switch } from 'react-router-dom'
|
||||
|
||||
import { AdminLayoutPortal, LayoutPortal } from '@components/Layout'
|
||||
@ -10,7 +10,10 @@ import Deposit from './Deposit'
|
||||
import AdminPanel from './AdminPanel'
|
||||
import AccessDenied from './AccessDenied'
|
||||
|
||||
export const RootPathContext = createContext('')
|
||||
|
||||
export const Main = memo(() => (
|
||||
<RootPathContext.Provider value={''}>
|
||||
<Switch>
|
||||
<PrivateRoute path={'/admin/:tab?'}>
|
||||
<AdminLayoutPortal title={'Администраторская панель'}>
|
||||
@ -37,6 +40,7 @@ export const Main = memo(() => (
|
||||
</Route>
|
||||
<PrivateDefaultRoute urls={['/deposit']} />
|
||||
</Switch>
|
||||
</RootPathContext.Provider>
|
||||
))
|
||||
|
||||
export default Main
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { useState, useEffect, memo, useMemo, useCallback } from 'react'
|
||||
import { useState, useEffect, memo, useMemo, useCallback, useContext } from 'react'
|
||||
import { Button, Form, Input, Popconfirm, Timeline } from 'antd'
|
||||
import {
|
||||
CheckSquareOutlined,
|
||||
@ -16,6 +16,7 @@ import { formatDate } from '@utils'
|
||||
import { MeasureService } from '@api'
|
||||
|
||||
import { View } from './View'
|
||||
import { IdWellContext } from '@pages/Well'
|
||||
|
||||
import '@styles/index.css'
|
||||
import '@styles/measure.css'
|
||||
@ -25,13 +26,15 @@ const createEditingColumns = (cols, renderDelegate) =>
|
||||
|
||||
const disabled = !hasPermission('Measure.edit')
|
||||
|
||||
export const MeasureTable = memo(({ idWell, group, updateMeasuresFunc, additionalButtons }) => {
|
||||
export const MeasureTable = memo(({ group, updateMeasuresFunc, additionalButtons }) => {
|
||||
const [showLoader, setShowLoader] = useState(false)
|
||||
const [displayedValues, setDisplayedValues] = useState({})
|
||||
const [editingColumns, setEditingColumns] = useState(group.columns)
|
||||
const [isTableEditing, setIsTableEditing] = useState(false)
|
||||
const [editingActionName, setEditingActionName] = useState('')
|
||||
|
||||
const idWell = useContext(IdWellContext)
|
||||
|
||||
const [measuresForm] = Form.useForm()
|
||||
|
||||
const data = useMemo(() => group?.values?.length > 0 ? group.values : [group?.defaultValue], [group?.defaultValue, group?.values])
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Button } from 'antd'
|
||||
import { useState, useEffect, memo } from 'react'
|
||||
import { useState, useEffect, memo, useContext } from 'react'
|
||||
import { TableOutlined } from '@ant-design/icons'
|
||||
|
||||
import { MeasureService } from '@api'
|
||||
@ -11,6 +11,7 @@ import { InclinometryTable } from './InclinometryTable'
|
||||
import { columnsNnb, nnbDefaultData } from './nnbData'
|
||||
import { columnsMudDiagram, mudDiagramDefaultData } from './mudDiagramData'
|
||||
import { columnsDrillingFluid, drillingFluidDefaultData } from './drillingFluidData'
|
||||
import { IdWellContext } from '@pages/Well'
|
||||
|
||||
const defaultData = [
|
||||
{
|
||||
@ -41,12 +42,14 @@ const defaultData = [
|
||||
}
|
||||
]
|
||||
|
||||
export const Measure = memo(({ idWell }) => {
|
||||
export const Measure = memo(() => {
|
||||
const [showLoader, setShowLoader] = useState(false)
|
||||
const [isMeasuresUpdating, setIsMeasuresUpdating] = useState(true)
|
||||
const [data, setData] = useState(defaultData)
|
||||
const [tableIdx, setTableIdx] = useState(-1)
|
||||
|
||||
const idWell = useContext(IdWellContext)
|
||||
|
||||
useEffect(() => invokeWebApiWrapperAsync(
|
||||
async () => {
|
||||
if (!isMeasuresUpdating) return
|
||||
@ -73,7 +76,6 @@ export const Measure = memo(({ idWell }) => {
|
||||
{data.map((group, idx) => (
|
||||
<MeasureTable
|
||||
key={idx}
|
||||
idWell={idWell}
|
||||
group={group}
|
||||
updateMeasuresFunc={() => setIsMeasuresUpdating(true)}
|
||||
additionalButtons={group.additionalButtons?.(group, idx, setTableIdx)}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Button, Tooltip } from 'antd'
|
||||
import { useState, useEffect, memo } from 'react'
|
||||
import { useState, useEffect, memo, useContext } from 'react'
|
||||
import { FilePdfOutlined, FileTextOutlined } from '@ant-design/icons'
|
||||
|
||||
import LoaderPortal from '@components/LoaderPortal'
|
||||
@ -8,6 +8,8 @@ import { invokeWebApiWrapperAsync, downloadFile } from '@components/factory'
|
||||
import { formatDate, periodToString } from '@utils'
|
||||
import { ReportService } from '@api'
|
||||
|
||||
import { IdWellContext } from '@pages/Well'
|
||||
|
||||
const imgPaths = {
|
||||
'.pdf': <FilePdfOutlined/>,
|
||||
'.las': <FileTextOutlined/>,
|
||||
@ -55,10 +57,12 @@ const columns = [
|
||||
},
|
||||
]
|
||||
|
||||
export const Reports = memo(({ idWell }) => {
|
||||
export const Reports = memo(() => {
|
||||
const [reports, setReports] = useState([])
|
||||
const [showLoader, setShowLoader] = useState(false)
|
||||
|
||||
const idWell = useContext(IdWellContext)
|
||||
|
||||
useEffect(() => invokeWebApiWrapperAsync(
|
||||
async () => {
|
||||
const reportsResponse = await ReportService.getAllReportsNamesByWell(idWell)
|
||||
|
@ -1,6 +1,6 @@
|
||||
import 'moment/locale/ru'
|
||||
import moment from 'moment'
|
||||
import { useState, useEffect, memo, useCallback } from 'react'
|
||||
import { useState, useEffect, memo, useCallback, useContext } from 'react'
|
||||
import { Radio, Button, Select, notification } from 'antd'
|
||||
|
||||
import { LoaderPortal } from '@components/LoaderPortal'
|
||||
@ -11,6 +11,7 @@ import { ReportService } from '@api'
|
||||
|
||||
import { Reports } from './Reports'
|
||||
import { ReportCreationNotify } from './ReportCreationNotify'
|
||||
import { IdWellContext } from '@pages/Well'
|
||||
|
||||
const timePeriodNames = [
|
||||
{ label: '1 секунда', value: 1 },
|
||||
@ -32,7 +33,7 @@ const reportFormats = [
|
||||
{ value: 1, label: 'LAS' },
|
||||
]
|
||||
|
||||
export const DiagramReport = memo(({ idWell }) => {
|
||||
export const DiagramReport = memo(() => {
|
||||
const [aviableDateRange, setAviableDateRange] = useState([moment(), moment()])
|
||||
const [filterDateRange, setFilterDateRange] = useState([
|
||||
moment().subtract(1, 'days').startOf('day'),
|
||||
@ -43,6 +44,8 @@ export const DiagramReport = memo(({ idWell }) => {
|
||||
const [pagesCount, setPagesCount] = useState(0)
|
||||
const [showLoader, setShowLoader] = useState(false)
|
||||
|
||||
const idWell = useContext(IdWellContext)
|
||||
|
||||
const handleReportCreation = useCallback(async () => await invokeWebApiWrapperAsync(
|
||||
async () => {
|
||||
const taskId = await ReportService.createReport(
|
||||
@ -166,7 +169,7 @@ export const DiagramReport = memo(({ idWell }) => {
|
||||
</div>
|
||||
</div>
|
||||
</LoaderPortal>
|
||||
<Reports idWell={idWell} />
|
||||
<Reports />
|
||||
</div>
|
||||
)
|
||||
})
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* eslint-disable react-hooks/exhaustive-deps */
|
||||
import { useState, useEffect, memo, useCallback } from 'react'
|
||||
import { useState, useEffect, memo, useCallback, useContext } from 'react'
|
||||
|
||||
import { Flex } from '@components/Grid'
|
||||
import LoaderPortal from '@components/LoaderPortal'
|
||||
@ -8,6 +8,7 @@ import { DatePickerWrapper, makeDateSorter } from '@components/Table'
|
||||
import { PeriodPicker, defaultPeriod } from '@components/selectors/PeriodPicker'
|
||||
import { TelemetryDataSaubService } from '@api'
|
||||
|
||||
import { IdWellContext } from '@pages/Well'
|
||||
import { normalizeData } from '../TelemetryView'
|
||||
import { ArchiveDisplay, cutData } from './ArchiveDisplay'
|
||||
|
||||
@ -61,7 +62,7 @@ const range = (start, end) => {
|
||||
return result
|
||||
}
|
||||
|
||||
export const Archive = memo(({ idWell }) => {
|
||||
export const Archive = memo(() => {
|
||||
const [dataSaub, setDataSaub] = useState([])
|
||||
const [dateLimit, setDateLimit] = useState({ from: 0, to: new Date() })
|
||||
const [chartInterval, setChartInterval] = useState(parseInt(defaultPeriod) * 1000)
|
||||
@ -69,6 +70,8 @@ export const Archive = memo(({ idWell }) => {
|
||||
const [showLoader, setShowLoader] = useState(false)
|
||||
const [loaded, setLoaded] = useState(null)
|
||||
|
||||
const idWell = useContext(IdWellContext)
|
||||
|
||||
const onGraphWheel = useCallback((e) => {
|
||||
if (loaded && dateLimit.from && dateLimit.to) {
|
||||
setStartDate((prevStartDate) => {
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { memo, useCallback, useEffect, useMemo, useReducer, useState } from 'react'
|
||||
import { memo, useCallback, useContext, useEffect, useMemo, useReducer, useState } from 'react'
|
||||
import { useHistory, useParams } from 'react-router-dom'
|
||||
import { CloseOutlined } from '@ant-design/icons'
|
||||
import { Button, Menu, Popconfirm } from 'antd'
|
||||
@ -19,10 +19,12 @@ import {
|
||||
WitsRecord61Service,
|
||||
} from '@api'
|
||||
|
||||
import { IdWellContext } from '@pages/Well'
|
||||
import { RootPathContext } from '@pages/Main'
|
||||
import AddGroupWindow from './AddGroupWindow'
|
||||
import AddWidgetWindow, { makeWidgetFromWits } from './AddWidgetWindow'
|
||||
|
||||
import '@styles/dashboard_nnb.less'
|
||||
import AddGroupWindow from './AddGroupWindow'
|
||||
|
||||
const getWitsInfo = async () => {
|
||||
// TODO: Добавить expire с принудительным обновлением
|
||||
@ -105,19 +107,21 @@ const groupsReducer = (groups, action) => {
|
||||
return newGroups
|
||||
}
|
||||
|
||||
export const DashboardNNB = memo(({ idWell }) => {
|
||||
export const DashboardNNB = memo(() => {
|
||||
const [groups, dispatchGroups] = useReducer(groupsReducer, [])
|
||||
const [witsInfo, setWitsInfo] = useState([])
|
||||
const [isLoading, setIsLoading] = useState(false)
|
||||
const [selectedSettings, setSelectedSettings] = useState(null)
|
||||
const [values, setValues] = useState({})
|
||||
|
||||
const root = useMemo(() => `/well/${idWell}/telemetry/dashboard_nnb`, [idWell])
|
||||
const idWell = useContext(IdWellContext)
|
||||
const root = useContext(RootPathContext)
|
||||
const rootPath = useMemo(() => `${root}/dashboard_nnb`, [root])
|
||||
const history = useHistory()
|
||||
const { tab: selectedGroup } = useParams()
|
||||
|
||||
if (!selectedGroup && groups?.length > 0)
|
||||
history.push(`${root}/${groups[0].id}`)
|
||||
history.push(`${rootPath}/${groups[0].id}`)
|
||||
|
||||
|
||||
const group = useMemo(() => ({
|
||||
@ -172,8 +176,8 @@ export const DashboardNNB = memo(({ idWell }) => {
|
||||
|
||||
const removeGroup = useCallback((id) => {
|
||||
dispatchGroups({ type: 'remove_group', groupId: `${id}` })
|
||||
if (id === selectedGroup) history.push(`${root}`)
|
||||
}, [root, history, selectedGroup])
|
||||
if (id === selectedGroup) history.push(`${rootPath}`)
|
||||
}, [rootPath, history, selectedGroup])
|
||||
|
||||
const addWidget = useCallback((settings) => dispatchGroups({
|
||||
type: 'add_widget',
|
||||
@ -226,7 +230,7 @@ export const DashboardNNB = memo(({ idWell }) => {
|
||||
<Button type={'link'} icon={<CloseOutlined />} />
|
||||
</Popconfirm>
|
||||
)}
|
||||
<Button type={'text'} style={{ paddingLeft: 0 }} onClick={() => history.push(`${root}/${id}`)}>{name}</Button>
|
||||
<Button type={'text'} style={{ paddingLeft: 0 }} onClick={() => history.push(`${rootPath}/${id}`)}>{name}</Button>
|
||||
</Menu.Item>
|
||||
))}
|
||||
</Menu>
|
||||
|
@ -1,10 +1,12 @@
|
||||
import moment from 'moment'
|
||||
import { useState, useEffect, memo, useCallback } from 'react'
|
||||
import { useState, useEffect, memo, useCallback, useContext } from 'react'
|
||||
import { Table, Select, DatePicker, Input } from 'antd'
|
||||
|
||||
import { MessageService } from '@api'
|
||||
import LoaderPortal from '@components/LoaderPortal'
|
||||
import { invokeWebApiWrapperAsync } from '@components/factory'
|
||||
import { makeColumn, makeDateColumn, makeNumericSorter } from '@components/Table'
|
||||
import { MessageService } from '@api'
|
||||
|
||||
import { IdWellContext } from '../Well'
|
||||
|
||||
import '@styles/message.css'
|
||||
|
||||
@ -22,41 +24,18 @@ const categoryDictionary = {
|
||||
|
||||
// Конфигурация таблицы
|
||||
export const columns = [
|
||||
{
|
||||
makeDateColumn('Дата', 'date', undefined, undefined, { width: '10rem' }),
|
||||
makeColumn('Глубина', 'wellDepth', { width: '10rem', render: depth => <span>{depth.toFixed(2)} м.</span> }),
|
||||
makeColumn('Категория', 'categoryId', {
|
||||
width: '10rem',
|
||||
title: 'Дата',
|
||||
key: 'date',
|
||||
dataIndex: 'date',
|
||||
render: item => moment(item).format('DD MMM YYYY, HH:mm:ss'),
|
||||
sorter: (a, b) => new Date(b.date) - new Date(a.date),
|
||||
sortDirections: ['descend', 'ascend'],
|
||||
}, {
|
||||
width: '10rem',
|
||||
title: 'Глубина',
|
||||
key: 'wellDepth',
|
||||
dataIndex: 'wellDepth',
|
||||
render: depth => <span>{depth.toFixed(2)} м.</span>,
|
||||
}, {
|
||||
width: '10rem',
|
||||
title: 'Категория',
|
||||
key: 'categoryId',
|
||||
dataIndex: 'categoryId',
|
||||
render: (_, item) => categoryDictionary[item.categoryId].title,
|
||||
style: (_, item) => categoryDictionary[item.categoryId]?.style,
|
||||
sorter: (a, b) => a.categoryId - b.categoryId,
|
||||
sorter: makeNumericSorter('categoryId'),
|
||||
sortDirections: ['descend', 'ascend'],
|
||||
ellipsis: true,
|
||||
}, {
|
||||
title: 'Сообщение',
|
||||
key: 'message',
|
||||
dataIndex: 'message',
|
||||
onFilter: (value, record) => record.name.indexOf(value) === 0,
|
||||
}, {
|
||||
width: '10rem',
|
||||
title: 'Пользователь',
|
||||
key: 'user',
|
||||
dataIndex: 'user',
|
||||
},
|
||||
}),
|
||||
makeColumn('Сообщение', 'message', { onFilter: (value, record) => record.name.indexOf(value) === 0 }),
|
||||
makeColumn('Пользователь', 'user', { width: '10rem' }),
|
||||
]
|
||||
|
||||
const filterOptions = [
|
||||
@ -68,7 +47,7 @@ const filterOptions = [
|
||||
const children = filterOptions.map((line) => <Option key={line.value}>{line.label}</Option>)
|
||||
|
||||
// Данные для таблицы
|
||||
export const Messages = memo(({ idWell }) => {
|
||||
export const Messages = memo(() => {
|
||||
const [messages, setMessages] = useState([])
|
||||
const [pagination, setPagination] = useState(null)
|
||||
const [page, setPage] = useState(1)
|
||||
@ -77,6 +56,8 @@ export const Messages = memo(({ idWell }) => {
|
||||
const [searchString, setSearchString] = useState('')
|
||||
const [showLoader, setShowLoader] = useState(false)
|
||||
|
||||
const idWell = useContext(IdWellContext)
|
||||
|
||||
const onChangeSearchString = useCallback((message) => setSearchString(message.length > 2 ? message : ''), [])
|
||||
|
||||
useEffect(() => invokeWebApiWrapperAsync(
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Table } from 'antd'
|
||||
import { useState, useEffect, useCallback, memo } from 'react'
|
||||
import { useState, useEffect, useCallback, memo, useContext } from 'react'
|
||||
|
||||
import LoaderPortal from '@components/LoaderPortal'
|
||||
import { invokeWebApiWrapperAsync } from '@components/factory'
|
||||
@ -7,13 +7,16 @@ import { Subscribe } from '@services/signalr'
|
||||
import { MessageService } from '@api'
|
||||
|
||||
import { columns } from '../Messages'
|
||||
import { IdWellContext } from '@pages/Well'
|
||||
|
||||
import '@styles/message.css'
|
||||
|
||||
export const ActiveMessagesOnline = memo(({ idWell }) => {
|
||||
export const ActiveMessagesOnline = memo(() => {
|
||||
const [messages, setMessages] = useState([])
|
||||
const [loader, setLoader] = useState(false)
|
||||
|
||||
const idWell = useContext(IdWellContext)
|
||||
|
||||
const handleReceiveMessages = useCallback((messages) => {
|
||||
if (messages)
|
||||
setMessages(messages.items.splice(0, 4))
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { memo, useCallback, useMemo, useState } from 'react'
|
||||
import { memo, useCallback, useContext, useMemo, useState } from 'react'
|
||||
import { Select, Modal, Input, InputNumber } from 'antd'
|
||||
|
||||
import { SetpointsService } from '@api'
|
||||
@ -8,12 +8,16 @@ import { invokeWebApiWrapperAsync } from '@components/factory'
|
||||
import { makeNumericRender, EditableTable } from '@components/Table'
|
||||
import { PeriodPicker, defaultPeriod } from '@components/selectors/PeriodPicker'
|
||||
|
||||
export const SetpointSender = memo(({ idWell, onClose, visible, setpointNames }) => {
|
||||
import { IdWellContext } from '@pages/Well'
|
||||
|
||||
export const SetpointSender = memo(({ onClose, visible, setpointNames }) => {
|
||||
const [expirePeriod, setExpirePeriod] = useState(defaultPeriod)
|
||||
const [comment, setComment] = useState('')
|
||||
const [setpoints, setSetpoints] = useState([])
|
||||
const [isLoading, setIsLoading] = useState(false)
|
||||
|
||||
const idWell = useContext(IdWellContext)
|
||||
|
||||
const addingColumns = useMemo(() => [
|
||||
{
|
||||
title: 'Наименование уставки',
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Button, Modal } from 'antd'
|
||||
import { useState, useEffect, memo, useCallback, useMemo } from 'react'
|
||||
import { useState, useEffect, memo, useCallback, useMemo, useContext } from 'react'
|
||||
|
||||
import { Table } from '@components/Table'
|
||||
import { UserView } from '@components/views'
|
||||
@ -10,10 +10,11 @@ import { makeStringCutter } from '@utils/string'
|
||||
import { formatDate } from '@utils'
|
||||
import { SetpointsService } from '@api'
|
||||
|
||||
import { IdWellContext } from '@pages/Well'
|
||||
import SetpointSender from './SetpointSender'
|
||||
import { SetpointViewer, getSetpointStatus } from './SetpointViewer'
|
||||
|
||||
export const Setpoints = memo(({ idWell, ...other }) => {
|
||||
export const Setpoints = memo(({ ...other }) => {
|
||||
const [isModalVisible, setIsModalVisible] = useState(false)
|
||||
const [isSenderVisible, setIsSenderVisible] = useState(false)
|
||||
const [isViewerVisible, setIsViewerVisible] = useState(false)
|
||||
@ -22,6 +23,8 @@ export const Setpoints = memo(({ idWell, ...other }) => {
|
||||
const [selected, setSelected] = useState(null)
|
||||
const [setpointNames, setSetpointNames] = useState([])
|
||||
|
||||
const idWell = useContext(IdWellContext)
|
||||
|
||||
useEffect(() => invokeWebApiWrapperAsync(
|
||||
async () => {
|
||||
const names = await SetpointsService.getSetpointsNamesByIdWell(idWell)
|
||||
@ -102,7 +105,6 @@ export const Setpoints = memo(({ idWell, ...other }) => {
|
||||
</LoaderPortal>
|
||||
</Modal>
|
||||
<SetpointSender
|
||||
idWell={idWell}
|
||||
setpointNames={setpointNames}
|
||||
visible={isSenderVisible}
|
||||
onClose={onSenderClose}
|
||||
|
@ -1,13 +1,17 @@
|
||||
import { memo, useCallback, useEffect, useState } from 'react'
|
||||
import { memo, useCallback, useContext, useEffect, useState } from 'react'
|
||||
|
||||
import { TelemetryWirelineRunOutService } from '@api'
|
||||
import { invokeWebApiWrapperAsync } from '@components/factory'
|
||||
import { WirelineView } from '@components/views'
|
||||
|
||||
export const WirelineRunOut = memo(({ idWell }) => {
|
||||
import { IdWellContext } from '@pages/Well'
|
||||
|
||||
export const WirelineRunOut = memo(() => {
|
||||
const [twro, setTwro] = useState({})
|
||||
const [isLoading, setIsLoading] = useState(false)
|
||||
|
||||
const idWell = useContext(IdWellContext)
|
||||
|
||||
const update = useCallback(() => invokeWebApiWrapperAsync(
|
||||
async () => {
|
||||
const twro = await TelemetryWirelineRunOutService.getData(idWell)
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Select } from 'antd'
|
||||
import { useState, useEffect, useCallback } from 'react'
|
||||
import { useState, useEffect, useCallback, useContext } from 'react'
|
||||
|
||||
import {
|
||||
DrillFlowChartService,
|
||||
@ -22,6 +22,8 @@ import ActiveMessagesOnline from './ActiveMessagesOnline'
|
||||
import { ModeDisplay } from './ModeDisplay'
|
||||
import { UserOfWell } from './UserOfWells'
|
||||
import { Setpoints } from './Setpoints'
|
||||
import WirelineRunOut from './WirelineRunOut'
|
||||
import { IdWellContext } from '@pages/Well'
|
||||
|
||||
import MomentStabPicEnabled from '@images/DempherOn.png'
|
||||
import MomentStabPicDisabled from '@images/DempherOff.png'
|
||||
@ -29,7 +31,6 @@ import SpinPicEnabled from '@images/SpinEnabled.png'
|
||||
import SpinPicDisabled from '@images/SpinDisabled.png'
|
||||
|
||||
import '@styles/message.css'
|
||||
import WirelineRunOut from './WirelineRunOut'
|
||||
|
||||
const { Option } = Select
|
||||
|
||||
@ -303,7 +304,7 @@ export const normalizeData = (data) => data?.map(item => ({
|
||||
blockSpeed: Math.abs(item.blockSpeed)
|
||||
})) ?? []
|
||||
|
||||
export default function TelemetryView({ idWell }) {
|
||||
export default function TelemetryView() {
|
||||
const [dataSaub, setDataSaub] = useState([])
|
||||
const [dataSpin, setDataSpin] = useState([])
|
||||
const [chartInterval, setChartInterval] = useState(defaultPeriod)
|
||||
@ -312,6 +313,8 @@ export default function TelemetryView({ idWell }) {
|
||||
const [flowChartData, setFlowChartData] = useState([])
|
||||
const [rop, setRop] = useState(null)
|
||||
|
||||
const idWell = useContext(IdWellContext)
|
||||
|
||||
const handleDataSaub = useCallback((data) => {
|
||||
if (data) {
|
||||
const dataSaub = normalizeData(data)
|
||||
@ -392,9 +395,9 @@ export default function TelemetryView({ idWell }) {
|
||||
<Option value={2}>Завершено</Option>
|
||||
</Select>
|
||||
</div>
|
||||
<Setpoints idWell={idWell} style={{ marginLeft: '1rem' }} />
|
||||
<Setpoints style={{ marginLeft: '1rem' }} />
|
||||
<span style={{ flexGrow: 20 }}> </span>
|
||||
<WirelineRunOut idWell={idWell} />
|
||||
<WirelineRunOut />
|
||||
<img src={isTorqueStabEnabled(dataSpin) ? MomentStabPicEnabled : MomentStabPicDisabled} style={{ marginRight: '15px' }} alt={'TorqueMaster'} />
|
||||
<img src={isSpinEnabled(dataSpin) ? SpinPicEnabled : SpinPicDisabled} style={{ marginRight: '15px' }} alt={'SpinMaster'} />
|
||||
<h2 style={{ marginBottom: 0, marginRight: '15px', fontWeight: 'bold', color: isMseEnabled(dataSaub) ? 'green' : 'lightgrey' }}>MSE</h2>
|
||||
|
@ -1,57 +1,47 @@
|
||||
import { Switch, useParams } from 'react-router-dom'
|
||||
import { memo, useMemo } from 'react'
|
||||
import { Layout, Menu } from 'antd'
|
||||
import { useParams } from 'react-router-dom'
|
||||
import { memo, useContext, useMemo } from 'react'
|
||||
import { Layout } from 'antd'
|
||||
import { AlertOutlined, FundViewOutlined, DatabaseOutlined } from '@ant-design/icons'
|
||||
|
||||
import { PrivateRoute, PrivateDefaultRoute, PrivateMenuItem } from '@components/Private'
|
||||
import { PrivateSwitch, PrivateMenu } from '@components/Private'
|
||||
|
||||
import Archive from './Archive'
|
||||
import Messages from './Messages'
|
||||
import DashboardNNB from './DashboardNNB'
|
||||
import TelemetryView from './TelemetryView'
|
||||
import { RootPathContext } from '@pages/Main'
|
||||
|
||||
import '@styles/index.css'
|
||||
|
||||
const { Content } = Layout
|
||||
|
||||
export const Telemetry = memo(({ idWell }) => {
|
||||
export const Telemetry = memo(() => {
|
||||
const { tab } = useParams()
|
||||
const rootPath = useMemo(() => `/well/${idWell}/telemetry`, [idWell])
|
||||
const root = useContext(RootPathContext)
|
||||
const rootPath = useMemo(() => `${root}/telemetry`, [root])
|
||||
|
||||
return (
|
||||
<RootPathContext.Provider value={rootPath}>
|
||||
<Layout>
|
||||
<Menu mode={'horizontal'} selectable={true} selectedKeys={[tab]} className={'well_menu'}>
|
||||
<PrivateMenuItem.Link root={rootPath} key={'monitoring'} path={'monitoring'} icon={<FundViewOutlined />} title={'Мониторинг'}/>
|
||||
<PrivateMenuItem.Link root={rootPath} key={'messages'} path={'messages'} icon={<AlertOutlined/>} title={'Сообщения'} />
|
||||
<PrivateMenuItem.Link root={rootPath} key={'archive'} path={'archive'} icon={<DatabaseOutlined />} title={'Архив'} />
|
||||
<PrivateMenuItem.Link root={rootPath} key={'dashboard_nnb'} path={'dashboard_nnb'} title={'ННБ'} />
|
||||
</Menu>
|
||||
<PrivateMenu mode={'horizontal'} selectable={true} selectedKeys={[tab]} className={'well_menu'}>
|
||||
<PrivateMenu.Link key={'monitoring'} icon={<FundViewOutlined />} title={'Мониторинг'}/>
|
||||
<PrivateMenu.Link key={'messages'} icon={<AlertOutlined/>} title={'Сообщения'} />
|
||||
<PrivateMenu.Link key={'archive'} icon={<DatabaseOutlined />} title={'Архив'} />
|
||||
<PrivateMenu.Link key={'dashboard_nnb'} title={'ННБ'} />
|
||||
</PrivateMenu>
|
||||
|
||||
<Layout>
|
||||
<Content className={'site-layout-background'}>
|
||||
<Switch>
|
||||
<PrivateRoute path={`${rootPath}/monitoring`}>
|
||||
<TelemetryView idWell={idWell} />
|
||||
</PrivateRoute>
|
||||
<PrivateRoute path={`${rootPath}/messages`}>
|
||||
<Messages idWell={idWell} />
|
||||
</PrivateRoute>
|
||||
<PrivateRoute path={`${rootPath}/archive`}>
|
||||
<Archive idWell={idWell} />
|
||||
</PrivateRoute>
|
||||
<PrivateRoute path={`${rootPath}/dashboard_nnb/:tab?`}>
|
||||
<DashboardNNB idWell={idWell} />
|
||||
</PrivateRoute>
|
||||
<PrivateDefaultRoute urls={[
|
||||
`${rootPath}/monitoring`,
|
||||
`${rootPath}/messages`,
|
||||
`${rootPath}/archive`,
|
||||
`${rootPath}/dashboard_nnb`,
|
||||
]}/>
|
||||
</Switch>
|
||||
<PrivateSwitch elseRedirect={['monitoring', 'messages', 'archive', 'dashboard_nnb']}>
|
||||
<TelemetryView key={'monitoring'} />
|
||||
<Messages key={'messages'} />
|
||||
<Archive key={'archive'} />
|
||||
<DashboardNNB key={'dashboard_nnb/:tab?'} />
|
||||
</PrivateSwitch>
|
||||
</Content>
|
||||
</Layout>
|
||||
</Layout>
|
||||
</RootPathContext.Provider>
|
||||
)
|
||||
})
|
||||
|
||||
|
@ -1,15 +1,19 @@
|
||||
import { useState, useEffect, memo } from 'react'
|
||||
import { useState, useEffect, memo, useContext } from 'react'
|
||||
|
||||
import { TelemetryAnalyticsService } from '@api'
|
||||
import LoaderPortal from '@components/LoaderPortal'
|
||||
import { invokeWebApiWrapperAsync } from '@components/factory'
|
||||
import { ChartTelemetryDepthToDay } from '@components/charts/ChartTelemetryDepthToDay'
|
||||
|
||||
export const TelemetryAnalysisDepthToDay = memo(({ idWell }) => {
|
||||
import { IdWellContext } from '@pages/Well'
|
||||
|
||||
export const TelemetryAnalysisDepthToDay = memo(() => {
|
||||
const [depthData, setDepthData] = useState([])
|
||||
const [bitPositionData, setBitPositionData] = useState([])
|
||||
const [loader, setLoader] = useState(false)
|
||||
|
||||
const idWell = useContext(IdWellContext)
|
||||
|
||||
useEffect(() => invokeWebApiWrapperAsync(
|
||||
async () => {
|
||||
const depthToDayData = await TelemetryAnalyticsService.getWellDepthToDay(idWell)
|
||||
|
@ -1,11 +1,13 @@
|
||||
import { Select } from 'antd'
|
||||
import { useState, useEffect, memo } from 'react'
|
||||
import { useState, useEffect, memo, useContext } from 'react'
|
||||
|
||||
import { arrayOrDefault } from '@utils'
|
||||
import { TelemetryAnalyticsService } from '@api'
|
||||
import LoaderPortal from '@components/LoaderPortal'
|
||||
import { invokeWebApiWrapperAsync } from '@components/factory'
|
||||
import { ChartTelemetryDepthToInterval } from '@components/charts/ChartTelemetryDepthToInterval'
|
||||
import { TelemetryAnalyticsService } from '@api'
|
||||
import { arrayOrDefault } from '@utils'
|
||||
|
||||
import { IdWellContext } from '@pages/Well'
|
||||
|
||||
const timePeriodCollection = [
|
||||
{ value: '3600', label: '1 час' },
|
||||
@ -14,11 +16,13 @@ const timePeriodCollection = [
|
||||
{ value: '86400', label: '24 часа' }
|
||||
]
|
||||
|
||||
export const TelemetryAnalysisDepthToInterval = memo(({ idWell }) => {
|
||||
export const TelemetryAnalysisDepthToInterval = memo(() => {
|
||||
const [depthToIntervalData, setDepthToIntervalData] = useState([])
|
||||
const [chartInterval, setChartInterval] = useState(86400)
|
||||
const [loader, setLoader] = useState(false)
|
||||
|
||||
const idWell = useContext(IdWellContext)
|
||||
|
||||
useEffect(() => invokeWebApiWrapperAsync(
|
||||
async () => {
|
||||
const depthToIntervalData = await TelemetryAnalyticsService.getWellDepthToInterval(idWell, chartInterval)
|
||||
|
@ -1,20 +1,24 @@
|
||||
import moment from 'moment'
|
||||
import { Form, DatePicker } from 'antd'
|
||||
import { useState, useEffect, memo } from 'react'
|
||||
import { useState, useEffect, memo, useContext } from 'react'
|
||||
|
||||
import { TelemetryAnalyticsService } from '@api'
|
||||
import LoaderPortal from '@components/LoaderPortal'
|
||||
import { invokeWebApiWrapperAsync } from '@components/factory'
|
||||
import { ChartTelemetryOperationsSummary } from '@components/charts/ChartTelemetryOperationsSummary'
|
||||
|
||||
import { IdWellContext } from '@pages/Well'
|
||||
|
||||
const { RangePicker } = DatePicker
|
||||
|
||||
export const TelemetryAnalysisOperationsSummary = memo(({ idWell }) => {
|
||||
export const TelemetryAnalysisOperationsSummary = memo(() => {
|
||||
const [avilableDatesRange, setAviableDatesRange] = useState([moment(),moment()])
|
||||
const [filterDateRange, setFilterDateRange] = useState([moment().subtract(1, 'days'),moment()])
|
||||
const [operationsData, setOperationsData] = useState([])
|
||||
const [loader, setLoader] = useState(false)
|
||||
|
||||
const idWell = useContext(IdWellContext)
|
||||
|
||||
const disabledDate = (current) => current < avilableDatesRange[0] || current > avilableDatesRange[1]
|
||||
|
||||
useEffect(() => invokeWebApiWrapperAsync(
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { memo } from 'react'
|
||||
|
||||
export const TelemetryAnalysisOperationsToInterval = memo(({ idWell }) => (<>{idWell} 123</>))
|
||||
export const TelemetryAnalysisOperationsToInterval = memo(() => (<>123</>))
|
||||
|
||||
export default TelemetryAnalysisOperationsToInterval
|
||||
|
@ -1,56 +1,43 @@
|
||||
import { memo } from 'react'
|
||||
import { Layout, Menu } from 'antd'
|
||||
import { useParams } from 'react-router-dom'
|
||||
import { memo, useContext, useMemo } from 'react'
|
||||
import { FolderOutlined } from '@ant-design/icons'
|
||||
import { Switch, useParams } from 'react-router-dom'
|
||||
import { Layout } from 'antd'
|
||||
|
||||
import { PrivateDefaultRoute, PrivateRoute } from '@components/Private'
|
||||
import { PrivateMenuItemLink } from '@components/Private/PrivateMenuItem'
|
||||
import { PrivateMenu, PrivateSwitch } from '@components/Private'
|
||||
|
||||
import TelemetryAnalysisDepthToDay from './TelemetryAnalysisDepthToDay'
|
||||
import TelemetryAnalysisDepthToInterval from './TelemetryAnalysisDepthToInterval'
|
||||
import TelemetryAnalysisOperationsSummary from './TelemetryAnalysisOperationsSummary'
|
||||
import TelemetryAnalysisOperationsToInterval from './TelemetryAnalysisOperationsToInterval'
|
||||
import { RootPathContext } from '@pages/Main'
|
||||
|
||||
const { Content } = Layout
|
||||
|
||||
export const TelemetryAnalysis = memo(({ idWell }) => {
|
||||
export const TelemetryAnalysis = memo(() => {
|
||||
const { tab } = useParams()
|
||||
const rootPath = `/well/${idWell}/telemetryAnalysis`
|
||||
const root = useContext(RootPathContext)
|
||||
const rootPath = useMemo(() => `${root}/telemetryAnalysis`, [root])
|
||||
|
||||
return (
|
||||
<>
|
||||
<Menu mode={'horizontal'} selectable={true} className={'well_menu'} selectedKeys={[tab]}>
|
||||
<PrivateMenuItemLink root={rootPath} icon={<FolderOutlined />} key={'depthToDay'} path={'depthToDay'} title={'Глубина-день'} />
|
||||
<PrivateMenuItemLink root={rootPath} icon={<FolderOutlined />} key={'depthToInterval'} path={'depthToInterval'} title={'Глубина-интервал'} />
|
||||
<PrivateMenuItemLink root={rootPath} icon={<FolderOutlined />} key={'operationsSummary'} path={'operationsSummary'} title={'Все операции'} />
|
||||
<PrivateMenuItemLink root={rootPath} icon={<FolderOutlined />} key={'operationsToInterval'} path={'operationsToInterval'} title={'Операции-интервал'} />
|
||||
</Menu>
|
||||
<RootPathContext.Provider value={rootPath}>
|
||||
<PrivateMenu mode={'horizontal'} selectable={true} className={'well_menu'} selectedKeys={[tab]}>
|
||||
<PrivateMenu.Link icon={<FolderOutlined />} key={'depthToDay'} title={'Глубина-день'} />
|
||||
<PrivateMenu.Link icon={<FolderOutlined />} key={'depthToInterval'} title={'Глубина-интервал'} />
|
||||
<PrivateMenu.Link icon={<FolderOutlined />} key={'operationsSummary'} title={'Все операции'} />
|
||||
<PrivateMenu.Link icon={<FolderOutlined />} key={'operationsToInterval'} title={'Операции-интервал'} />
|
||||
</PrivateMenu>
|
||||
|
||||
<Layout>
|
||||
<Content className={'site-layout-background'}>
|
||||
<Switch>
|
||||
<PrivateRoute path={`${rootPath}/depthToDay`}>
|
||||
<TelemetryAnalysisDepthToDay idWell={idWell}/>
|
||||
</PrivateRoute>
|
||||
<PrivateRoute path={`${rootPath}/depthToInterval`}>
|
||||
<TelemetryAnalysisDepthToInterval idWell={idWell}/>
|
||||
</PrivateRoute>
|
||||
<PrivateRoute path={`${rootPath}/operationsSummary`}>
|
||||
<TelemetryAnalysisOperationsSummary idWell={idWell}/>
|
||||
</PrivateRoute>
|
||||
<PrivateRoute path={`${rootPath}/operationsToInterval`}>
|
||||
<TelemetryAnalysisOperationsToInterval idWell={idWell}/>
|
||||
</PrivateRoute>
|
||||
<PrivateDefaultRoute urls={[
|
||||
`${rootPath}/depthToDay`,
|
||||
`${rootPath}/depthToInterval`,
|
||||
`${rootPath}/operationsSummary`,
|
||||
`${rootPath}/operationsToInterval`,
|
||||
]}/>
|
||||
</Switch>
|
||||
<PrivateSwitch elseRedirect={['depthToDay', 'depthToInterval', 'operationsSummary', 'operationsToInterval']}>
|
||||
<TelemetryAnalysisDepthToDay key={'depthToDay'} />
|
||||
<TelemetryAnalysisDepthToInterval key={'depthToInterval'} />
|
||||
<TelemetryAnalysisOperationsSummary key={'operationsSummary'} />
|
||||
<TelemetryAnalysisOperationsToInterval key={'operationsToInterval'} />
|
||||
</PrivateSwitch>
|
||||
</Content>
|
||||
</Layout>
|
||||
</>
|
||||
</RootPathContext.Provider>
|
||||
)
|
||||
})
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { memo, useMemo } from 'react'
|
||||
import { createContext, memo, useContext, useMemo } from 'react'
|
||||
import {
|
||||
FolderOutlined,
|
||||
FundViewOutlined,
|
||||
@ -6,10 +6,10 @@ import {
|
||||
ExperimentOutlined,
|
||||
DeploymentUnitOutlined,
|
||||
} from '@ant-design/icons'
|
||||
import { Layout, Menu } from 'antd'
|
||||
import { Switch, useParams } from 'react-router-dom'
|
||||
import { Layout } from 'antd'
|
||||
import { useParams } from 'react-router-dom'
|
||||
|
||||
import { PrivateRoute, PrivateDefaultRoute, PrivateMenuItem } from '@components/Private'
|
||||
import { PrivateMenu, PrivateSwitch } from '@components/Private'
|
||||
|
||||
import Measure from './Measure'
|
||||
import Reports from './Reports'
|
||||
@ -19,69 +19,51 @@ import Telemetry from './Telemetry'
|
||||
import WellOperations from './WellOperations'
|
||||
import DrillingProgram from './DrillingProgram'
|
||||
import TelemetryAnalysis from './TelemetryAnalysis'
|
||||
import { RootPathContext } from './Main'
|
||||
|
||||
import '@styles/index.css'
|
||||
|
||||
const { Content } = Layout
|
||||
|
||||
export const IdWellContext = createContext(null)
|
||||
|
||||
export const Well = memo(() => {
|
||||
const { idWell, tab } = useParams()
|
||||
const rootPath = useMemo(() => `/well/${idWell}`, [idWell])
|
||||
const root = useContext(RootPathContext)
|
||||
const rootPath = useMemo(() => `${root}/well/${idWell}`, [root, idWell])
|
||||
|
||||
return (
|
||||
<RootPathContext.Provider value={rootPath}>
|
||||
<Layout>
|
||||
<Menu mode={'horizontal'} selectable={true} selectedKeys={[tab]} className={'well_menu'}>
|
||||
<PrivateMenuItem.Link root={rootPath} key={'telemetry'} path={'telemetry'} icon={<FundViewOutlined />} title={'Телеметрия'}/>
|
||||
<PrivateMenuItem.Link root={rootPath} key={'reports'} path={'reports'} icon={<FilePdfOutlined />} title={'Рапорта'} />
|
||||
<PrivateMenuItem.Link root={rootPath} key={'analytics'} path={'analytics'} icon={<DeploymentUnitOutlined />} title={'Аналитика'} />
|
||||
<PrivateMenuItem.Link root={rootPath} key={'operations'} path={'operations'} icon={<FolderOutlined />} title={'Операции по скважине'} />
|
||||
{/* <PrivateMenuItem.Link root={rootPath} key={'telemetryAnalysis'} path={'telemetryAnalysis'} icon={<FundProjectionScreenOutlined />} title={'Операции по телеметрии'} /> */}
|
||||
<PrivateMenuItem.Link root={rootPath} key={'document'} path={'document'} icon={<FolderOutlined />} title={'Документы'} />
|
||||
<PrivateMenuItem.Link root={rootPath} key={'measure'} path={'measure'} icon={<ExperimentOutlined />} title={'Измерения'} />
|
||||
<PrivateMenuItem.Link root={rootPath} key={'drillingProgram'} path={'drillingProgram'} icon={<FolderOutlined />} title={'Программа бурения'} />
|
||||
</Menu>
|
||||
<PrivateMenu mode={'horizontal'} selectable={true} selectedKeys={[tab]} className={'well_menu'}>
|
||||
<PrivateMenu.Link key={'telemetry'} icon={<FundViewOutlined />} title={'Телеметрия'}/>
|
||||
<PrivateMenu.Link key={'reports'} icon={<FilePdfOutlined />} title={'Рапорта'} />
|
||||
<PrivateMenu.Link key={'analytics'} icon={<DeploymentUnitOutlined />} title={'Аналитика'} />
|
||||
<PrivateMenu.Link key={'operations'} icon={<FolderOutlined />} title={'Операции по скважине'} />
|
||||
{/* <PrivateMenu.Link key={'telemetryAnalysis'} icon={<FundProjectionScreenOutlined />} title={'Операции по телеметрии'} /> */}
|
||||
<PrivateMenu.Link key={'document'} icon={<FolderOutlined />} title={'Документы'} />
|
||||
<PrivateMenu.Link key={'measure'} icon={<ExperimentOutlined />} title={'Измерения'} />
|
||||
<PrivateMenu.Link key={'drillingProgram'} icon={<FolderOutlined />} title={'Программа бурения'} />
|
||||
</PrivateMenu>
|
||||
|
||||
<IdWellContext.Provider value={idWell}>
|
||||
<Layout>
|
||||
<Content className={'site-layout-background'}>
|
||||
<Switch>
|
||||
<PrivateRoute path={`${rootPath}/telemetry/:tab?`}>
|
||||
<Telemetry idWell={idWell} />
|
||||
</PrivateRoute>
|
||||
<PrivateRoute path={`${rootPath}/reports/:tab?`}>
|
||||
<Reports idWell={idWell} />
|
||||
</PrivateRoute>
|
||||
<PrivateRoute path={`${rootPath}/analytics/:tab?`}>
|
||||
<Analytics idWell={idWell} rootPath={`${rootPath}/analytics`}/>
|
||||
</PrivateRoute>
|
||||
<PrivateRoute path={`${rootPath}/operations/:tab?`}>
|
||||
<WellOperations idWell={idWell} />
|
||||
</PrivateRoute>
|
||||
<PrivateRoute path={`${rootPath}/telemetryAnalysis/:tab?`}>
|
||||
<TelemetryAnalysis idWell={idWell} />
|
||||
</PrivateRoute>
|
||||
<PrivateRoute path={`${rootPath}/document/:category?`}>
|
||||
<Documents idWell={idWell} />
|
||||
</PrivateRoute>
|
||||
<PrivateRoute path={`${rootPath}/measure`}>
|
||||
<Measure idWell={idWell}/>
|
||||
</PrivateRoute>
|
||||
<PrivateRoute path={`${rootPath}/drillingProgram`}>
|
||||
<DrillingProgram idWell={idWell}/>
|
||||
</PrivateRoute>
|
||||
<PrivateDefaultRoute urls={[
|
||||
`${rootPath}/telemetry`,
|
||||
`${rootPath}/report`,
|
||||
`${rootPath}/analytics`,
|
||||
`${rootPath}/operations`,
|
||||
`${rootPath}/telemetryAnalysis`,
|
||||
`${rootPath}/document`,
|
||||
`${rootPath}/measure`,
|
||||
`${rootPath}/drillingProgram`,
|
||||
]}/>
|
||||
</Switch>
|
||||
<PrivateSwitch elseRedirect={['telemetry', 'reports', 'analytics', 'operations', 'telemetryAnalysis', 'document', 'measure', 'drillingProgram']}>
|
||||
<Telemetry key={'telemetry/:tab?'} />
|
||||
<Reports key={'reports/:tab?'} />
|
||||
<Analytics key={'analytics/:tab?'} />
|
||||
<WellOperations key={'operations/:tab?'} />
|
||||
<TelemetryAnalysis key={'telemetryAnalysis/:tab?'} />
|
||||
<Documents key={'document/:category?'} />
|
||||
<Measure key={'measure'} />
|
||||
<DrillingProgram key={'drillingProgram'} />
|
||||
</PrivateSwitch>
|
||||
</Content>
|
||||
</Layout>
|
||||
</IdWellContext.Provider>
|
||||
</Layout>
|
||||
</RootPathContext.Provider>
|
||||
)
|
||||
})
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { useState, useEffect, memo } from 'react'
|
||||
import { useState, useEffect, memo, useContext } from 'react'
|
||||
|
||||
import {
|
||||
EditableTable,
|
||||
@ -11,6 +11,8 @@ import { invokeWebApiWrapperAsync } from '@components/factory'
|
||||
import { hasPermission } from '@utils/permissions'
|
||||
import { arrayOrDefault } from '@utils'
|
||||
|
||||
import { IdWellContext } from '../Well'
|
||||
|
||||
const columns = [
|
||||
makeNumericStartEnd('Глубина, м', 'depth'),
|
||||
makeNumericMinMax('Нагрузка, т', 'axialLoad'),
|
||||
@ -20,10 +22,12 @@ const columns = [
|
||||
makeNumericMinMax('Расход, л/с', 'flow')
|
||||
]
|
||||
|
||||
export const DrillProcessFlow = memo(({ idWell }) => {
|
||||
export const DrillProcessFlow = memo(() => {
|
||||
const [flows, setFlows] = useState([])
|
||||
const [showLoader, setShowLoader] = useState(false)
|
||||
|
||||
const idWell = useContext(IdWellContext)
|
||||
|
||||
const updateFlows = () => invokeWebApiWrapperAsync(
|
||||
async () => {
|
||||
const flows = await DrillFlowChartService.get(idWell)
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { useHistory } from 'react-router-dom'
|
||||
import { memo, useState, useRef, useEffect, useCallback } from 'react'
|
||||
import { memo, useState, useRef, useEffect, useCallback, useContext, useMemo } from 'react'
|
||||
import { DoubleLeftOutlined, DoubleRightOutlined } from '@ant-design/icons'
|
||||
import { Switch, Button } from 'antd'
|
||||
|
||||
@ -24,6 +24,7 @@ import { getOperations } from '@utils/functions'
|
||||
import NptTable from './NptTable'
|
||||
import NetGraphExport from './NetGraphExport'
|
||||
import AdditionalTables from './AdditionalTables'
|
||||
import { IdWellContext } from '@pages/Well'
|
||||
|
||||
import '@styles/index.css'
|
||||
import '@styles/tvd.less'
|
||||
@ -114,13 +115,16 @@ const makeDataset = (data, label, color, borderWidth = 1.5, borderDash) => ({
|
||||
borderDash,
|
||||
})
|
||||
|
||||
export const Tvd = memo(({ idWell, title, ...other }) => {
|
||||
export const Tvd = memo(({ idWell: wellId, title, ...other }) => {
|
||||
const [chart, setChart] = useState()
|
||||
const [xLabel, setXLabel] = useState('day')
|
||||
const [operations, setOperations] = useState({})
|
||||
const [tableVisible, setTableVisible] = useState(false)
|
||||
const [isLoading, setIsLoading] = useState(false)
|
||||
|
||||
const idWellContext = useContext(IdWellContext)
|
||||
const idWell = useMemo(() => wellId ?? idWellContext, [wellId, idWellContext])
|
||||
|
||||
const chartRef = useRef(null)
|
||||
const history = useHistory()
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { useState, useEffect, useCallback, memo, useMemo } from 'react'
|
||||
import { useState, useEffect, useCallback, memo, useMemo, useContext } from 'react'
|
||||
|
||||
import {
|
||||
EditableTable,
|
||||
@ -13,6 +13,8 @@ import { DrillParamsService, WellOperationService } from '@api'
|
||||
import { hasPermission } from '@utils/permissions'
|
||||
import { arrayOrDefault } from '@utils'
|
||||
|
||||
import { IdWellContext } from '../Well'
|
||||
|
||||
export const getColumns = async (idWell) => {
|
||||
let sectionTypes = await WellOperationService.getSectionTypes(idWell)
|
||||
sectionTypes = Object.entries(sectionTypes).map(([id, value]) => ({
|
||||
@ -34,11 +36,13 @@ export const getColumns = async (idWell) => {
|
||||
]
|
||||
}
|
||||
|
||||
export const WellDrillParams = memo(({ idWell }) => {
|
||||
export const WellDrillParams = memo(() => {
|
||||
const [params, setParams] = useState([])
|
||||
const [showLoader, setShowLoader] = useState(false)
|
||||
const [columns, setColumns] = useState([])
|
||||
|
||||
const idWell = useContext(IdWellContext)
|
||||
|
||||
const updateParams = useCallback(async () => await invokeWebApiWrapperAsync(
|
||||
async () => {
|
||||
const params = arrayOrDefault(await DrillParamsService.getAll(idWell))
|
||||
|
@ -1,7 +1,7 @@
|
||||
import moment from 'moment'
|
||||
import { Input } from 'antd'
|
||||
import { useLocation } from 'react-router-dom'
|
||||
import { useState, useEffect, memo, useMemo, useCallback } from 'react'
|
||||
import { useState, useEffect, memo, useMemo, useCallback, useContext } from 'react'
|
||||
|
||||
import {
|
||||
EditableTable,
|
||||
@ -21,6 +21,8 @@ import { hasPermission } from '@utils/permissions'
|
||||
import { arrayOrDefault } from '@utils'
|
||||
import { WellOperationService } from '@api'
|
||||
|
||||
import { IdWellContext } from '../Well'
|
||||
|
||||
const { TextArea } = Input
|
||||
|
||||
const basePageSize = 160
|
||||
@ -52,12 +54,14 @@ const generateColumns = (showNpt = false, categories = [], sectionTypes = []) =>
|
||||
makeTextColumn('Комментарий', 'comment', null, null, null, { editable: true, input: <TextArea/> }),
|
||||
].filter(Boolean)
|
||||
|
||||
export const WellOperationsEditor = memo(({ idWell, idType, showNpt, ...other }) => {
|
||||
export const WellOperationsEditor = memo(({ idType, showNpt, ...other }) => {
|
||||
const [pageNumAndPageSize, setPageNumAndPageSize] = useState({ current: 1, pageSize: basePageSize })
|
||||
const [paginationTotal, setPaginationTotal] = useState(0)
|
||||
const [operations, setOperations] = useState([])
|
||||
const [showLoader, setShowLoader] = useState(false)
|
||||
|
||||
const idWell = useContext(IdWellContext)
|
||||
|
||||
const [categories, setCategories] = useState([])
|
||||
const [sectionTypes, setSectionTypes] = useState([])
|
||||
|
||||
|
@ -1,10 +1,12 @@
|
||||
import { useState, useEffect, memo } from 'react'
|
||||
import { useState, useEffect, memo, useContext } from 'react'
|
||||
|
||||
import LoaderPortal from '@components/LoaderPortal'
|
||||
import { invokeWebApiWrapperAsync } from '@components/factory'
|
||||
import { Table, makeColumn, makeColumnsPlanFact, makeNumericRender } from '@components/Table'
|
||||
import { OperationStatService } from '@api'
|
||||
import { calcDuration } from '@utils/datetime'
|
||||
import { OperationStatService } from '@api'
|
||||
|
||||
import { IdWellContext } from '../Well'
|
||||
|
||||
const numericRender = makeNumericRender(2)
|
||||
|
||||
@ -19,10 +21,12 @@ const columns = [
|
||||
makeColumnsPlanFact('Спуск ОК, м/ч' ,'casingDownSpeed', { render: numericRender }),
|
||||
]
|
||||
|
||||
export const WellSectionsStat = memo(({ idWell }) => {
|
||||
export const WellSectionsStat = memo(() => {
|
||||
const [sections, setSections] = useState([])
|
||||
const [showLoader, setShowLoader] = useState(false)
|
||||
|
||||
const idWell = useContext(IdWellContext)
|
||||
|
||||
useEffect(() => invokeWebApiWrapperAsync(
|
||||
async () => {
|
||||
const sectionsResponse = await OperationStatService.getStatWell(idWell)
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { memo, useCallback } from 'react'
|
||||
import { Layout, Menu } from 'antd'
|
||||
import { Switch, useParams, useHistory, useLocation } from 'react-router-dom'
|
||||
import { useParams, useHistory, useLocation } from 'react-router-dom'
|
||||
import { memo, useCallback, useContext, useMemo } from 'react'
|
||||
import { Layout } from 'antd'
|
||||
import {
|
||||
BarChartOutlined,
|
||||
BuildOutlined,
|
||||
@ -9,7 +9,7 @@ import {
|
||||
TableOutlined,
|
||||
} from '@ant-design/icons'
|
||||
|
||||
import { PrivateDefaultRoute, PrivateRoute, PrivateMenuItemLink } from '@components/Private'
|
||||
import { PrivateMenu, PrivateSwitch } from '@components/Private'
|
||||
|
||||
import { Tvd } from './Tvd'
|
||||
import { ImportExportBar } from './ImportExportBar'
|
||||
@ -17,68 +17,53 @@ import { WellDrillParams } from './WellDrillParams'
|
||||
import { DrillProcessFlow } from './DrillProcessFlow'
|
||||
import { WellSectionsStat } from './WellSectionsStat'
|
||||
import { WellOperationsEditor } from './WellOperationsEditor'
|
||||
import { Flex } from '@asb/components/Grid'
|
||||
import { Flex } from '@components/Grid'
|
||||
|
||||
import { RootPathContext } from '@pages/Main'
|
||||
import { IdWellContext } from '@pages/Well'
|
||||
|
||||
const { Content } = Layout
|
||||
|
||||
export const WellOperations = memo(({ idWell }) => {
|
||||
export const WellOperations = memo(() => {
|
||||
const { tab } = useParams()
|
||||
const history = useHistory()
|
||||
const location = useLocation()
|
||||
const rootPath = `/well/${idWell}/operations`
|
||||
const root = useContext(RootPathContext)
|
||||
const idWell = useContext(IdWellContext)
|
||||
const rootPath = useMemo(() => `${root}/operations`, [root])
|
||||
|
||||
const onImported = useCallback(() =>
|
||||
history.push({ pathname: `${rootPath}`, state: { from: location.pathname }})
|
||||
, [history, location, rootPath])
|
||||
|
||||
const isIEBarDisabled = !['plan', 'fact'].includes(tab)
|
||||
const isIEBarDisabled = useMemo(() => !['plan', 'fact'].includes(tab), [tab])
|
||||
|
||||
return(
|
||||
<>
|
||||
<RootPathContext.Provider value={rootPath}>
|
||||
<Flex style={{ width: '100%' }}>
|
||||
<Menu mode={'horizontal'} selectable={true} className={'well_menu'} selectedKeys={[tab]} style={{ flex: 1 }}>
|
||||
<PrivateMenuItemLink root={rootPath} icon={<LineChartOutlined />} key={'tvd'} path={'tvd'} title={'TVD'} />
|
||||
<PrivateMenuItemLink root={rootPath} icon={<BuildOutlined />} key={'sections'} path={'sections'} title={'Секции'} />
|
||||
<PrivateMenuItemLink root={rootPath} icon={<TableOutlined />} key={'plan'} path={'plan'} title={'План'} />
|
||||
<PrivateMenuItemLink root={rootPath} icon={<TableOutlined />} key={'fact'} path={'fact'} title={'Факт'} />
|
||||
<PrivateMenuItemLink root={rootPath} icon={<BarChartOutlined />} key={'drillProcessFlow'} path={'drillProcessFlow'} title={'РТК'} />
|
||||
<PrivateMenuItemLink root={rootPath} icon={<ControlOutlined />} key={'params'} path={'params'} title={'Режимы'} />
|
||||
</Menu>
|
||||
<PrivateMenu mode={'horizontal'} selectable={true} className={'well_menu'} selectedKeys={[tab]} style={{ flex: 1 }}>
|
||||
<PrivateMenu.Link icon={<LineChartOutlined />} key={'tvd'} title={'TVD'} />
|
||||
<PrivateMenu.Link icon={<BuildOutlined />} key={'sections'} title={'Секции'} />
|
||||
<PrivateMenu.Link icon={<TableOutlined />} key={'plan'} title={'План'} />
|
||||
<PrivateMenu.Link icon={<TableOutlined />} key={'fact'} title={'Факт'} />
|
||||
<PrivateMenu.Link icon={<BarChartOutlined />} key={'drillProcessFlow'} title={'РТК'} />
|
||||
<PrivateMenu.Link icon={<ControlOutlined />} key={'params'} title={'Режимы'} />
|
||||
</PrivateMenu>
|
||||
<ImportExportBar idWell={idWell} disabled={isIEBarDisabled} onImported={onImported}/>
|
||||
</Flex>
|
||||
<Layout>
|
||||
<Content className={'site-layout-background'}>
|
||||
<Switch>
|
||||
<PrivateRoute path={`${rootPath}/tvd`}>
|
||||
<Tvd idWell={idWell}/>
|
||||
</PrivateRoute>
|
||||
<PrivateRoute path={`${rootPath}/sections`}>
|
||||
<WellSectionsStat idWell={idWell}/>
|
||||
</PrivateRoute>
|
||||
<PrivateRoute path={`${rootPath}/plan`}>
|
||||
<WellOperationsEditor idWell={idWell} idType={0} tableName={'well_operations_plan'}/>
|
||||
</PrivateRoute>
|
||||
<PrivateRoute path={`${rootPath}/fact`}>
|
||||
<WellOperationsEditor idWell={idWell} idType={1} showNpt tableName={'well_operations_fact'}/>
|
||||
</PrivateRoute>
|
||||
<PrivateRoute path={`${rootPath}/drillProcessFlow`}>
|
||||
<DrillProcessFlow idWell={idWell} />
|
||||
</PrivateRoute>
|
||||
<PrivateRoute path={`${rootPath}/params`}>
|
||||
<WellDrillParams idWell={idWell}/>
|
||||
</PrivateRoute>
|
||||
<PrivateDefaultRoute urls={[
|
||||
`${rootPath}/plan`,
|
||||
`${rootPath}/fact`,
|
||||
`${rootPath}/tvd`,
|
||||
`${rootPath}/sections`,
|
||||
`${rootPath}/drillProcessFlow`,
|
||||
`${rootPath}/params`
|
||||
]}/>
|
||||
</Switch>
|
||||
<PrivateSwitch elseRedirect={['plan', 'fact', 'tvd', 'sections', 'drillProcessFlow', 'params']}>
|
||||
<Tvd key={'tvd'} />
|
||||
<WellSectionsStat key={'sections'} />
|
||||
<WellOperationsEditor key={'plan'} idType={0} tableName={'well_operations_plan'}/>
|
||||
<WellOperationsEditor key={'fact'} idType={1} showNpt tableName={'well_operations_fact'}/>
|
||||
<DrillProcessFlow key={'drillProcessFlow'} />
|
||||
<WellDrillParams key={'params'} />
|
||||
</PrivateSwitch>
|
||||
</Content>
|
||||
</Layout>
|
||||
</>
|
||||
</RootPathContext.Provider>
|
||||
)
|
||||
})
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user