diff --git a/concept/Smbo/EquipmentDetails.jsx b/concept/Smbo/EquipmentDetails.jsx index 5178236..24b18a7 100755 --- a/concept/Smbo/EquipmentDetails.jsx +++ b/concept/Smbo/EquipmentDetails.jsx @@ -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(

{timer.label}: {timer.value} {timer.unit}

diff --git a/src/components/Private/PrivateMenu.tsx b/src/components/Private/PrivateMenu.tsx index 1a06311..6894518 100644 --- a/src/components/Private/PrivateMenu.tsx +++ b/src/components/Private/PrivateMenu.tsx @@ -1,9 +1,10 @@ import { join } from 'path' import { Menu, MenuItemProps, MenuProps } from 'antd' -import { Children, cloneElement, memo, ReactElement } from 'react' +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 } @@ -23,19 +24,22 @@ export const PrivateMenuLink = memo(({ tabName = '', path ) }) -const PrivateMenuMain = memo(({ root = '', children, ...other }) => { - const items = Children.toArray(children).map((child) => { +const PrivateMenuMain = memo(({ 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(root, key) + const path = join(rootPath, key) if (visible || isURLAvailable(path)) return cloneElement(element, { key, path, tabName: key }) } return null - }) + }), [children, rootPath]) return }) diff --git a/src/components/Private/PrivateSwitch.tsx b/src/components/Private/PrivateSwitch.tsx new file mode 100644 index 0000000..57911ed --- /dev/null +++ b/src/components/Private/PrivateSwitch.tsx @@ -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) => ReactNode + elseRedirect?: string | string[] +} + +const getDefaultRedirectPath = () => getUserId() ? '/access_denied' : '/login' + +export const defaultRedirect = (location?: Location) => ( + +) + +export const PrivateSwitch = memo(({ 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 ( + 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 ( + + {items} + + + + + ) +}) + +export default PrivateSwitch diff --git a/src/components/Private/index.ts b/src/components/Private/index.ts index 61de54c..b9cd980 100755 --- a/src/components/Private/index.ts +++ b/src/components/Private/index.ts @@ -3,9 +3,11 @@ 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' // 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' diff --git a/src/pages/AdminPanel/Telemetry/index.jsx b/src/pages/AdminPanel/Telemetry/index.jsx index 7ad8b46..9a145e0 100755 --- a/src/pages/AdminPanel/Telemetry/index.jsx +++ b/src/pages/AdminPanel/Telemetry/index.jsx @@ -1,41 +1,41 @@ import { Layout } from 'antd' -import { lazy, memo, Suspense } from 'react' -import { Switch, useParams } from 'react-router-dom' +import { lazy, memo, Suspense, useContext, useMemo } from 'react' +import { useParams } from 'react-router-dom' -import { PrivateRoute, PrivateDefaultRoute, PrivateMenu } 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() - return ( - - - - - + const root = useContext(RootPathContext) + const rootPath = useMemo(() => `${root}/telemetry`, [root]) + return ( + - - }> - - - - - - - + + + + + + + + }> + + + + + + + - + ) }) diff --git a/src/pages/AdminPanel/UserController/index.jsx b/src/pages/AdminPanel/UserController/index.jsx index 2152cd4..c090d73 100755 --- a/src/pages/AdminPanel/UserController/index.jsx +++ b/src/pages/AdminPanel/UserController/index.jsx @@ -188,7 +188,7 @@ export const UserController = memo(() => { allowClear placeholder={'Введите текст для поиска (по всем полям за исключением ролей)...'} onChange={onSearchTextChange} - style={{ marginBottom: '15px' }} + style={{ margin: '15px 0' }} loading={isSearching} /> 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() - return ( - - - - - - - - - - - - - + const root = useContext(RootPathContext) + const rootPath = useMemo(() => `${root}/admin`, [root]) + return ( + - - }> - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + }> + + + + + + + + + + + + + + + - + ) }) diff --git a/src/pages/Analytics/Statistics.jsx b/src/pages/Analytics/Statistics.jsx index c0ad71d..fabd3c1 100755 --- a/src/pages/Analytics/Statistics.jsx +++ b/src/pages/Analytics/Statistics.jsx @@ -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" не стало исключением diff --git a/src/pages/Analytics/WellCompositeEditor/NewParamsTable.jsx b/src/pages/Analytics/WellCompositeEditor/NewParamsTable.jsx index 6998087..c353e4d 100755 --- a/src/pages/Analytics/WellCompositeEditor/NewParamsTable.jsx +++ b/src/pages/Analytics/WellCompositeEditor/NewParamsTable.jsx @@ -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]) diff --git a/src/pages/Analytics/WellCompositeEditor/WellCompositeSections.jsx b/src/pages/Analytics/WellCompositeEditor/WellCompositeSections.jsx index 7e1505a..38aa452 100755 --- a/src/pages/Analytics/WellCompositeEditor/WellCompositeSections.jsx +++ b/src/pages/Analytics/WellCompositeEditor/WellCompositeSections.jsx @@ -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} /> - - - + { +export const WellCompositeEditor = memo(({ rootPath }) => { const { tab } = useParams() + const idWell = useContext(IdWellContext) const [statsWells, setStatsWells] = useState([]) const [showLoader, setShowLoader] = useState(false) @@ -68,27 +67,18 @@ export const WellCompositeEditor = memo(({ idWell, rootPath }) => { - - + + - - - - - - - - - + + + + diff --git a/src/pages/Analytics/index.jsx b/src/pages/Analytics/index.jsx index bbe5243..1a38c6a 100755 --- a/src/pages/Analytics/index.jsx +++ b/src/pages/Analytics/index.jsx @@ -1,36 +1,35 @@ -import { memo, useMemo } from 'react' +import { memo, useContext, useMemo } from 'react' +import { useParams } from 'react-router-dom' import { Layout } from 'antd' -import { Switch, useParams } from 'react-router-dom' -import { PrivateDefaultRoute, PrivateMenu, 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 ( - - - - - + - - - - - - - - - - - + + + + + + + + + + + + - + ) }) diff --git a/src/pages/Documents/DocumentsTemplate.jsx b/src/pages/Documents/DocumentsTemplate.jsx index f786551..dc98a2e 100755 --- a/src/pages/Documents/DocumentsTemplate.jsx +++ b/src/pages/Documents/DocumentsTemplate.jsx @@ -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) => }) ] -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]) diff --git a/src/pages/Documents/index.jsx b/src/pages/Documents/index.jsx index e429b20..3c79213 100755 --- a/src/pages/Documents/index.jsx +++ b/src/pages/Documents/index.jsx @@ -1,12 +1,12 @@ -import { join } from 'path' -import { memo, useMemo } from 'react' -import { Layout } 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, PrivateMenu, PrivateRoute } from '@components/Private' +import { PrivateMenu, PrivateSwitch } from '@components/Private' import DocumentsTemplate from './DocumentsTemplate' +import { RootPathContext } from '@pages/Main' const { Content } = Layout @@ -23,13 +23,14 @@ 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 ( - <> - + + {documentCategories.map(category => ( { - + cat.key)}> {documentCategories.map(category => ( - - - + ))} - join(root, cat.key))}/> - + - + ) }) diff --git a/src/pages/DrillingProgram/CategoryAdder.jsx b/src/pages/DrillingProgram/CategoryAdder.jsx index dd45dad..66534e7 100755 --- a/src/pages/DrillingProgram/CategoryAdder.jsx +++ b/src/pages/DrillingProgram/CategoryAdder.jsx @@ -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) => ({ diff --git a/src/pages/DrillingProgram/CategoryEditor.jsx b/src/pages/DrillingProgram/CategoryEditor.jsx index 5a01b67..4bedc5e 100755 --- a/src/pages/DrillingProgram/CategoryEditor.jsx +++ b/src/pages/DrillingProgram/CategoryEditor.jsx @@ -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 && [ diff --git a/src/pages/DrillingProgram/CategoryHistory.jsx b/src/pages/DrillingProgram/CategoryHistory.jsx index 1df55ad..b9f1424 100755 --- a/src/pages/DrillingProgram/CategoryHistory.jsx +++ b/src/pages/DrillingProgram/CategoryHistory.jsx @@ -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 diff --git a/src/pages/DrillingProgram/CategoryRender.jsx b/src/pages/DrillingProgram/CategoryRender.jsx index d3a168e..92f6e27 100755 --- a/src/pages/DrillingProgram/CategoryRender.jsx +++ b/src/pages/DrillingProgram/CategoryRender.jsx @@ -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 }) => ( )) -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]) diff --git a/src/pages/DrillingProgram/index.jsx b/src/pages/DrillingProgram/index.jsx index 303d240..1b08c73 100755 --- a/src/pages/DrillingProgram/index.jsx +++ b/src/pages/DrillingProgram/index.jsx @@ -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 }) => {

Программа бурения

{permissionToEdit && (
- +
)} @@ -143,7 +142,6 @@ export const DrillingProgram = memo(({ idWell }) => { {parts?.map?.((part, idx) => part && ( { {permissionToEdit && ( <> part.idFileCategory === selectedCategory) ?? {}} @@ -163,7 +160,6 @@ export const DrillingProgram = memo(({ idWell }) => { )} setHistoryVisible(false)} visible={historyVisible} diff --git a/src/pages/Main.jsx b/src/pages/Main.jsx index e090edf..183da19 100755 --- a/src/pages/Main.jsx +++ b/src/pages/Main.jsx @@ -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,33 +10,37 @@ import Deposit from './Deposit' import AdminPanel from './AdminPanel' import AccessDenied from './AccessDenied' +export const RootPathContext = createContext('') + export const Main = memo(() => ( - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + )) export default Main diff --git a/src/pages/Measure/MeasureTable.jsx b/src/pages/Measure/MeasureTable.jsx index 25e7fd5..32bd830 100755 --- a/src/pages/Measure/MeasureTable.jsx +++ b/src/pages/Measure/MeasureTable.jsx @@ -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]) diff --git a/src/pages/Measure/index.jsx b/src/pages/Measure/index.jsx index adf6b4c..af15e53 100755 --- a/src/pages/Measure/index.jsx +++ b/src/pages/Measure/index.jsx @@ -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) => ( setIsMeasuresUpdating(true)} additionalButtons={group.additionalButtons?.(group, idx, setTableIdx)} diff --git a/src/pages/Report/Reports.jsx b/src/pages/Report/Reports.jsx index cf44431..c5fb7ca 100755 --- a/src/pages/Report/Reports.jsx +++ b/src/pages/Report/Reports.jsx @@ -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 { ReportService } from '@api' @@ -7,6 +7,7 @@ import { formatDate, periodToString } from '@utils' import LoaderPortal from '@components/LoaderPortal' import { Table, makeDateSorter, makeNumericSorter } from '@components/Table' import { invokeWebApiWrapperAsync, downloadFile } from '@components/factory' +import { IdWellContext } from '@pages/Well' const imgPaths = { '.pdf': , @@ -55,10 +56,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) diff --git a/src/pages/Report/index.jsx b/src/pages/Report/index.jsx index 866ecdf..0c1f2e0 100755 --- a/src/pages/Report/index.jsx +++ b/src/pages/Report/index.jsx @@ -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 { ReportService } from '@api' @@ -11,6 +11,7 @@ import { DateRangeWrapper } from 'components/Table/DateRangeWrapper' import { Reports } from './Reports' import { ReportCreationNotify } from './ReportCreationNotify' +import { IdWellContext } from '../Well' const timePeriodNames = [ { label: '1 секунда', value: 1 }, @@ -32,7 +33,7 @@ const reportFormats = [ { value: 1, label: 'LAS' }, ] -export const Report = memo(({ idWell }) => { +export const Report = memo(() => { const [aviableDateRange, setAviableDateRange] = useState([moment(), moment()]) const [filterDateRange, setFilterDateRange] = useState([ moment().subtract(1, 'days').startOf('day'), @@ -43,6 +44,8 @@ export const Report = 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 Report = memo(({ idWell }) => { - + ) }) diff --git a/src/pages/Telemetry/Archive/index.jsx b/src/pages/Telemetry/Archive/index.jsx index 4c37e9f..1a45d4e 100755 --- a/src/pages/Telemetry/Archive/index.jsx +++ b/src/pages/Telemetry/Archive/index.jsx @@ -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) => { diff --git a/src/pages/Telemetry/DashboardNNB/index.jsx b/src/pages/Telemetry/DashboardNNB/index.jsx index eb5f8b8..cf16bcf 100644 --- a/src/pages/Telemetry/DashboardNNB/index.jsx +++ b/src/pages/Telemetry/DashboardNNB/index.jsx @@ -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 }) => { + ))}
diff --git a/src/pages/Telemetry/Messages.jsx b/src/pages/Telemetry/Messages.jsx index 2500ada..e97732b 100755 --- a/src/pages/Telemetry/Messages.jsx +++ b/src/pages/Telemetry/Messages.jsx @@ -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 => {depth.toFixed(2)} м. }), + 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 => {depth.toFixed(2)} м., - }, { - 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) => ) // Данные для таблицы -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( diff --git a/src/pages/Telemetry/TelemetryView/ActiveMessagesOnline.jsx b/src/pages/Telemetry/TelemetryView/ActiveMessagesOnline.jsx index b2fd566..f839c02 100755 --- a/src/pages/Telemetry/TelemetryView/ActiveMessagesOnline.jsx +++ b/src/pages/Telemetry/TelemetryView/ActiveMessagesOnline.jsx @@ -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)) diff --git a/src/pages/Telemetry/TelemetryView/Setpoints/SetpointSender.jsx b/src/pages/Telemetry/TelemetryView/Setpoints/SetpointSender.jsx index 12006ea..985dd96 100755 --- a/src/pages/Telemetry/TelemetryView/Setpoints/SetpointSender.jsx +++ b/src/pages/Telemetry/TelemetryView/Setpoints/SetpointSender.jsx @@ -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: 'Наименование уставки', diff --git a/src/pages/Telemetry/TelemetryView/Setpoints/index.jsx b/src/pages/Telemetry/TelemetryView/Setpoints/index.jsx index 2339ea2..bf54c98 100755 --- a/src/pages/Telemetry/TelemetryView/Setpoints/index.jsx +++ b/src/pages/Telemetry/TelemetryView/Setpoints/index.jsx @@ -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 }) => { { +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) diff --git a/src/pages/Telemetry/TelemetryView/index.jsx b/src/pages/Telemetry/TelemetryView/index.jsx index c11ae6f..aa0083a 100755 --- a/src/pages/Telemetry/TelemetryView/index.jsx +++ b/src/pages/Telemetry/TelemetryView/index.jsx @@ -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 }) { - +   - + {'TorqueMaster'} {'SpinMaster'}

MSE

diff --git a/src/pages/Telemetry/index.jsx b/src/pages/Telemetry/index.jsx index 77026e1..85189ba 100755 --- a/src/pages/Telemetry/index.jsx +++ b/src/pages/Telemetry/index.jsx @@ -1,58 +1,47 @@ -import { Switch, useParams } from 'react-router-dom' -import { memo, useMemo } from 'react' +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 PrivateMenu from '@components/Private/PrivateMenu' -import { PrivateRoute, PrivateDefaultRoute } 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 ( - - - } title={'Мониторинг'}/> - } title={'Сообщения'} /> - } title={'Архив'} /> - - - + - - - - - - - - - - - - - - - - - + + } title={'Мониторинг'}/> + } title={'Сообщения'} /> + } title={'Архив'} /> + + + + + + + + + + + + + - + ) }) diff --git a/src/pages/TelemetryAnalysis/TelemetryAnalysisDepthToDay.jsx b/src/pages/TelemetryAnalysis/TelemetryAnalysisDepthToDay.jsx index 904b966..f679a67 100755 --- a/src/pages/TelemetryAnalysis/TelemetryAnalysisDepthToDay.jsx +++ b/src/pages/TelemetryAnalysis/TelemetryAnalysisDepthToDay.jsx @@ -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) diff --git a/src/pages/TelemetryAnalysis/TelemetryAnalysisDepthToInterval.jsx b/src/pages/TelemetryAnalysis/TelemetryAnalysisDepthToInterval.jsx index 989165f..c5cb90e 100755 --- a/src/pages/TelemetryAnalysis/TelemetryAnalysisDepthToInterval.jsx +++ b/src/pages/TelemetryAnalysis/TelemetryAnalysisDepthToInterval.jsx @@ -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) diff --git a/src/pages/TelemetryAnalysis/TelemetryAnalysisOperationsSummary.jsx b/src/pages/TelemetryAnalysis/TelemetryAnalysisOperationsSummary.jsx index 9337c78..37e35b5 100755 --- a/src/pages/TelemetryAnalysis/TelemetryAnalysisOperationsSummary.jsx +++ b/src/pages/TelemetryAnalysis/TelemetryAnalysisOperationsSummary.jsx @@ -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( diff --git a/src/pages/TelemetryAnalysis/TelemetryAnalysisOperationsToInterval.jsx b/src/pages/TelemetryAnalysis/TelemetryAnalysisOperationsToInterval.jsx index e37da57..460ccd1 100755 --- a/src/pages/TelemetryAnalysis/TelemetryAnalysisOperationsToInterval.jsx +++ b/src/pages/TelemetryAnalysis/TelemetryAnalysisOperationsToInterval.jsx @@ -1,5 +1,5 @@ import { memo } from 'react' -export const TelemetryAnalysisOperationsToInterval = memo(({ idWell }) => (<>{idWell} 123)) +export const TelemetryAnalysisOperationsToInterval = memo(() => (<>123)) export default TelemetryAnalysisOperationsToInterval diff --git a/src/pages/TelemetryAnalysis/index.jsx b/src/pages/TelemetryAnalysis/index.jsx index 1cd423c..54bae03 100755 --- a/src/pages/TelemetryAnalysis/index.jsx +++ b/src/pages/TelemetryAnalysis/index.jsx @@ -1,24 +1,26 @@ -import { memo } from 'react' -import { Layout } 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, PrivateMenu, PrivateRoute } from '@components/Private' +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 ( - <> - + + } key={'depthToDay'} title={'Глубина-день'} /> } key={'depthToInterval'} title={'Глубина-интервал'} /> } key={'operationsSummary'} title={'Все операции'} /> @@ -27,29 +29,15 @@ export const TelemetryAnalysis = memo(({ idWell }) => { - - - - - - - - - - - - - - - + + + + + + - + ) }) diff --git a/src/pages/Well.jsx b/src/pages/Well.jsx index 41bae5e..f3aa58c 100755 --- a/src/pages/Well.jsx +++ b/src/pages/Well.jsx @@ -1,4 +1,4 @@ -import { memo, useMemo } from 'react' +import { createContext, memo, useContext, useMemo } from 'react' import { FolderOutlined, FundViewOutlined, @@ -7,9 +7,9 @@ import { DeploymentUnitOutlined, } from '@ant-design/icons' import { Layout } from 'antd' -import { Switch, useParams } from 'react-router-dom' +import { useParams } from 'react-router-dom' -import { PrivateRoute, PrivateDefaultRoute, PrivateMenu } from '@components/Private' +import { PrivateMenu, PrivateSwitch } from '@components/Private' import Report from './Report' import Measure from './Measure' @@ -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 ( - - - } title={'Телеметрия'}/> - } title={'Рапорт'} /> - } title={'Аналитика'} /> - } title={'Операции по скважине'} /> - {/* } title={'Операции по телеметрии'} /> */} - } title={'Документы'} /> - } title={'Измерения'} /> - } title={'Программа бурения'} /> - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + } title={'Телеметрия'}/> + } title={'Рапорт'} /> + } title={'Аналитика'} /> + } title={'Операции по скважине'} /> + {/* } title={'Операции по телеметрии'} /> */} + } title={'Документы'} /> + } title={'Измерения'} /> + } title={'Программа бурения'} /> + + + + + + + + + + + + + + + + + + - + ) }) diff --git a/src/pages/WellOperations/DrillProcessFlow.jsx b/src/pages/WellOperations/DrillProcessFlow.jsx index 878d410..b451c25 100755 --- a/src/pages/WellOperations/DrillProcessFlow.jsx +++ b/src/pages/WellOperations/DrillProcessFlow.jsx @@ -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) diff --git a/src/pages/WellOperations/Tvd/index.jsx b/src/pages/WellOperations/Tvd/index.jsx index c35a2d3..6f61e78 100755 --- a/src/pages/WellOperations/Tvd/index.jsx +++ b/src/pages/WellOperations/Tvd/index.jsx @@ -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' @@ -27,6 +27,7 @@ import AdditionalTables from './AdditionalTables' import '@styles/index.css' import '@styles/tvd.less' +import { IdWellContext } from '@asb/pages/Well' Chart.register( TimeScale, @@ -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() diff --git a/src/pages/WellOperations/WellDrillParams.jsx b/src/pages/WellOperations/WellDrillParams.jsx index b113209..79b7e63 100755 --- a/src/pages/WellOperations/WellDrillParams.jsx +++ b/src/pages/WellOperations/WellDrillParams.jsx @@ -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)) diff --git a/src/pages/WellOperations/WellOperationsEditor.jsx b/src/pages/WellOperations/WellOperationsEditor.jsx index 033a6f0..6c50d0f 100755 --- a/src/pages/WellOperations/WellOperationsEditor.jsx +++ b/src/pages/WellOperations/WellOperationsEditor.jsx @@ -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: