diff --git a/src/App.tsx b/src/App.tsx index 0ac3eb0..0d84e96 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,18 +1,16 @@ import { BrowserRouter as Router, Navigate, Route, Routes } from 'react-router-dom' import { lazy, memo, Suspense } from 'react' -import locale from 'antd/lib/locale/ru_RU' -import { ConfigProvider } from 'antd' import { RootPathContext } from '@asb/context' -import { UserOutlet } from '@components/outlets' -import LayoutPortal from '@components/LayoutPortal' import SuspenseFallback from '@components/SuspenseFallback' -import { getUser, NoAccessComponent } from '@utils' -import { OpenAPI } from '@api' +import { NoAccessComponent } from '@utils' -import '@styles/include/antd_theme.less' import '@styles/App.less' +const UserOutlet = lazy(() => import('@components/outlets/UserOutlet')) +const DepositsOutlet = lazy(() => import('@components/outlets/DepositsOutlet')) +const LayoutPortal = lazy(() => import('@components/LayoutPortal')) + const Login = lazy(() => import('@pages/public/Login')) const Register = lazy(() => import('@pages/public/Register')) const FileDownload = lazy(() => import('@pages/FileDownload')) @@ -22,28 +20,23 @@ const Deposit = lazy(() => import('@pages/Deposit')) const Cluster = lazy(() => import('@pages/Cluster')) const Well = lazy(() => import('@pages/Well')) -// OpenAPI.BASE = 'http://localhost:3000' -// TODO: Удалить взятие из 'token' в следующем релизе, вставлено для совместимости -OpenAPI.TOKEN = async () => getUser().token || localStorage.getItem('token') || '' -OpenAPI.HEADERS = { 'Content-Type': 'application/json' } - export const App = memo(() => ( - - - }> - - - } /> - } /> + + }> + + + } /> + } /> - {/* Public pages */} - } /> - } /> + {/* Public pages */} + } /> + } /> - {/* User pages */} - }> - } /> + {/* User pages */} + }> + } /> + }> }> {/* Admin pages */} } /> @@ -54,11 +47,11 @@ export const App = memo(() => ( } /> - - - - - + + + + + )) export default App diff --git a/src/components/Grid.tsx b/src/components/Grid.tsx index 81783ab..ff38f20 100755 --- a/src/components/Grid.tsx +++ b/src/components/Grid.tsx @@ -22,7 +22,7 @@ export const Grid = memo(({ children, style, ...other }) => ( )) -export const GridItem = memo(({ children, row, col, rowSpan, colSpan, style, ...other }) => { +export const GridItem = memo(({ children, row, col, rowSpan, colSpan, style, className, ...other }) => { const localRow = +row const localCol = +col const localColSpan = colSpan ? colSpan - 1 : 0 @@ -32,12 +32,11 @@ export const GridItem = memo(({ children, row, col, rowSpan, colS gridColumnEnd: localCol + localColSpan, gridRowStart: localRow, gridRowEnd: localRow + localRowSpan, - padding: '4px', ...style, } return ( -
+
{children}
) diff --git a/src/components/LoaderPortal.tsx b/src/components/LoaderPortal.tsx index 04d9999..770c37a 100755 --- a/src/components/LoaderPortal.tsx +++ b/src/components/LoaderPortal.tsx @@ -6,11 +6,12 @@ type LoaderPortalProps = HTMLAttributes & { show?: boolean, fade?: boolean, spinnerProps?: HTMLAttributes, + fillContent?: boolean } -export const LoaderPortal: React.FC = ({ className = '', show, fade = true, children, spinnerProps, ...other }) => ( +export const LoaderPortal: React.FC = ({ className = '', show, fade = true, children, spinnerProps, fillContent, ...other }) => (
-
{children}
+
{children}
{show && fade &&
} {show &&
}
diff --git a/src/components/Table/EditableTable.jsx b/src/components/Table/EditableTable.jsx index a94955e..a471789 100755 --- a/src/components/Table/EditableTable.jsx +++ b/src/components/Table/EditableTable.jsx @@ -221,9 +221,7 @@ export const EditableTable = memo(({ const mergedColumns = useMemo(() => [...columns.map(handleColumn), operationColumn], [columns, handleColumn, operationColumn]) - useEffect(() => { - setData(tryAddKeys(dataSource)) - }, [dataSource]) + useEffect(() => setData(tryAddKeys(dataSource)), [dataSource]) return (
diff --git a/src/components/d3/monitoring/D3MonitoringCharts.tsx b/src/components/d3/monitoring/D3MonitoringCharts.tsx index dbc2a54..bfeb30b 100644 --- a/src/components/d3/monitoring/D3MonitoringCharts.tsx +++ b/src/components/d3/monitoring/D3MonitoringCharts.tsx @@ -193,6 +193,7 @@ const _D3MonitoringCharts = >({ methods, className = '', + style, ...other }: D3MonitoringChartsProps) => { const [datasets, setDatasets, resetDatasets] = useUserSettings(chartName, datasetGroups) @@ -351,10 +352,10 @@ const _D3MonitoringCharts = >({ x: getByAccessor(dataset.xAxis?.accessor), } ) - + if (newChart.type === 'line') newChart.optimization = false - + // Если у графика нет группы создаём её if (newChart().empty()) group().append('g') @@ -496,12 +497,12 @@ const _D3MonitoringCharts = >({ default: break } - + if (chart.point) renderPoint(xAxis, yAxis, chart, chartData, true) if (dash) chart().attr('stroke-dasharray', dash) - + chart.afterDraw?.(chart) }) }) @@ -513,6 +514,7 @@ const _D3MonitoringCharts = >({ style={{ width: givenWidth, height: givenHeight, + ...style, }} >
{ + const [deposits, setDeposits] = useState([]) + const [isLoading, setIsLoading] = useState(false) + + useEffect(() => { + invokeWebApiWrapperAsync( + async () => { + const deposits = await DepositService.getDeposits() + setDeposits(arrayOrDefault(deposits)) + }, + setIsLoading, + `Не удалось загрузить список кустов`, + { actionName: 'Получить список кустов' } + ) + }, []) + + return ( + + + + + + ) +}) + +export default DepositsOutlet diff --git a/src/components/outlets/index.ts b/src/components/outlets/index.ts index 77c9a70..3542fbb 100644 --- a/src/components/outlets/index.ts +++ b/src/components/outlets/index.ts @@ -1 +1,2 @@ +export * from './DepositsOutlet' export * from './UserOutlet' diff --git a/src/components/selectors/WellSelector.jsx b/src/components/selectors/WellSelector.jsx index ba448be..da7d95c 100755 --- a/src/components/selectors/WellSelector.jsx +++ b/src/components/selectors/WellSelector.jsx @@ -1,12 +1,11 @@ import { Tag, TreeSelect } from 'antd' import { memo, useEffect, useState } from 'react' +import { useDeposits } from '@asb/context' import { invokeWebApiWrapperAsync } from '@components/factory' import { hasPermission } from '@utils' -import { DepositService } from '@api' -export const getTreeData = async () => { - const deposits = await DepositService.getDeposits() +export const getTreeData = async (deposits) => { const wellsTree = deposits.map((deposit, dIdx) => ({ title: deposit.caption, key: `0-${dIdx}`, @@ -40,10 +39,12 @@ export const WellSelector = memo(({ value, onChange, treeData, treeLabels, ...ot const [wellsTree, setWellsTree] = useState([]) const [wellLabels, setWellLabels] = useState([]) + const deposits = useDeposits() + useEffect(() => { invokeWebApiWrapperAsync( async () => { - const wellsTree = treeData ?? await getTreeData() + const wellsTree = treeData ?? await getTreeData(deposits) const labels = treeLabels ?? getTreeLabels(wellsTree) setWellsTree(wellsTree) setWellLabels(labels) @@ -52,7 +53,7 @@ export const WellSelector = memo(({ value, onChange, treeData, treeLabels, ...ot 'Не удалось загрузить список скважин', { actionName: 'Получение списка скважин' } ) - }, [treeData, treeLabels]) + }, [deposits, treeData, treeLabels]) return ( deposits.map(deposit =>({ + title: deposit.caption, + key: `/deposit/${deposit.id}`, + value: `/deposit/${deposit.id}`, + icon: , + children: deposit.clusters?.map(cluster => { + const wells = cluster.wells ? cluster.wells.slice() : [] + wells.sort(sortWellsByActive) + + return { + title: cluster.caption, + key: `/cluster/${cluster.id}`, + value: `/cluster/${cluster.id}`, + icon: , + children: wells.map(well => ({ + title: well.caption, + key: `/well/${well.id}`, + value: `/well/${well.id}`, + icon: + })), + } + }), +})) + export const WellTreeSelector = memo(({ expand, current, onChange, onClose, open, ...other }) => { - const [wellsTree, setWellsTree] = useState([]) - const [showLoader, setShowLoader] = useState(false) const [expanded, setExpanded] = useState([]) const [selected, setSelected] = useState([]) const navigate = useNavigate() const location = useLocation() + const deposits = useDeposits() - useEffect(() => { - if (current) setSelected([current]) - }, [current]) - - useEffect(() => { - setExpanded((prev) => expand ? getExpandKeys(wellsTree, expand) : prev) - }, [wellsTree, expand]) - - useEffect(() => { - invokeWebApiWrapperAsync( - async () => { - const deposits: Array = await DepositService.getDeposits() - const wellsTree: TreeDataNode[] = deposits.map(deposit =>({ - title: deposit.caption, - key: `/deposit/${deposit.id}`, - value: `/deposit/${deposit.id}`, - icon: , - children: deposit.clusters?.map(cluster => { - const wells = cluster.wells ? cluster.wells.slice() : [] - wells.sort(sortWellsByActive) - - return { - title: cluster.caption, - key: `/cluster/${cluster.id}`, - value: `/cluster/${cluster.id}`, - icon: , - children: wells.map(well => ({ - title: well.caption, - key: `/well/${well.id}`, - value: `/well/${well.id}`, - icon: - })), - } - }), - })) - setWellsTree(wellsTree) - }, - setShowLoader, - `Не удалось загрузить список скважин`, - { actionName: 'Получить список скважин' } - ) - }, []) + const wellsTree = useMemo(() => makeWellsTreeData(deposits), [deposits]) const onValueChange = useCallback((value?: string): void => { const key = getKeyByUrl(value)[0] @@ -169,21 +151,27 @@ export const WellTreeSelector = memo(({ expand, current, navigate(newPath, { state: { from: location.pathname }}) }, [navigate, location]) - useEffect(() => onValueChange(location.pathname), [onValueChange, location]) + useEffect(() => { + if (current) setSelected([current]) + }, [current]) + + useEffect(() => { + setExpanded((prev) => expand ? getExpandKeys(wellsTree, expand) : prev) + }, [wellsTree, expand]) + + useEffect(() => onValueChange(location.pathname), [onValueChange, location.pathname]) return ( - - - + ) }) diff --git a/src/context.ts b/src/context.ts index bd186a5..d719031 100644 --- a/src/context.ts +++ b/src/context.ts @@ -1,7 +1,7 @@ import { createContext, useContext, useEffect } from 'react' import { LayoutPortalProps } from '@components/LayoutPortal' -import { UserTokenDto, WellDto } from '@api' +import { DepositDto, UserTokenDto, WellDto } from '@api' /** Контекст текущей скважины */ export const WellContext = createContext<[WellDto, (well: WellDto) => void]>([{}, () => {}]) @@ -13,6 +13,8 @@ export const UserContext = createContext({}) export const LayoutPropsContext = createContext<(props: LayoutPortalProps) => void>(() => {}) /** Контекст для блока справа от крошек на страницах скважин и админки */ export const TopRightBlockContext = createContext<(block: JSX.Element) => void>(() => {}) +/** Контекст со списком месторождений */ +export const DepositsContext = createContext([]) /** * Получить текущую скважину @@ -29,19 +31,31 @@ export const useWell = () => useContext(WellContext) export const useRootPath = () => useContext(RootPathContext) /** - * Получить текущего пользователя - * - * @returns Текущий пользователь, либо `null` - */ + * Получить текущего пользователя + * + * @returns Текущий пользователь, либо `null` + */ export const useUser = () => useContext(UserContext) +/** + * Получить список скважин + * + * @returns Список скважин + */ +export const useDeposits = () => useContext(DepositsContext) + +/** + * Получить метод задания элементов справа от крошек + * + * @returns Метод задания элементов справа от крошек + */ export const useTopRightBlock = () => useContext(TopRightBlockContext) /** - * Получить метод задания параметров заголовка и меню - * - * @returns Получить метод задания параметров заголовка и меню - */ + * Получить метод задания параметров заголовка и меню + * + * @returns Получить метод задания параметров заголовка и меню + */ export const useLayoutProps = (props?: LayoutPortalProps) => { const setLayoutProps = useContext(LayoutPropsContext) diff --git a/src/index.tsx b/src/index.tsx index 5354f6e..12aaff2 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,15 +1,28 @@ -import React from 'react' +import locale from 'antd/lib/locale/ru_RU' +import { ConfigProvider } from 'antd' import { createRoot } from 'react-dom/client' +import React from 'react' + +import { getUser } from '@utils' +import { OpenAPI } from '@api' import App from './App' +import '@styles/include/antd_theme.less' import '@styles/index.css' +// OpenAPI.BASE = 'http://localhost:3000' +// TODO: Удалить взятие из 'token' в следующем релизе, вставлено для совместимости +OpenAPI.TOKEN = async () => getUser().token || localStorage.getItem('token') || '' +OpenAPI.HEADERS = { 'Content-Type': 'application/json' } + const container = document.getElementById('root') ?? document.body const root = createRoot(container) root.render( - + + + ) diff --git a/src/pages/Cluster/ClusterWells.jsx b/src/pages/Cluster/ClusterWells.jsx index a74c8bd..a84e9cb 100755 --- a/src/pages/Cluster/ClusterWells.jsx +++ b/src/pages/Cluster/ClusterWells.jsx @@ -7,11 +7,11 @@ import { makeTextColumn, makeGroupColumn, makeColumn, - makeDateSorter, makeNumericColumnPlanFact, Table, makeNumericRender, makeNumericColumn, + makeDateColumn, } from '@components/Table' import LoaderPortal from '@components/LoaderPortal' import PointerIcon from '@components/icons/PointerIcon' @@ -39,7 +39,6 @@ const filtersWellsType = [] const DAY_IN_MS = 86_400_000 const ONLINE_DEADTIME = 600_000 -const getDate = (str) => isRawDate(str) ? new Date(str).toLocaleString() : '-' const numericRender = makeNumericRender(1) const ClusterWells = memo(({ statsWells }) => { @@ -131,8 +130,8 @@ const ClusterWells = memo(({ statsWells }) => { ), makeTextColumn('Тип скв.', 'wellType', filtersWellsType, null, (text) => text ?? '-'), makeGroupColumn('Фактические сроки', [ - makeColumn('начало', 'factStart', { sorter: makeDateSorter('factStart'), render: getDate }), - makeColumn('окончание', 'factEnd', { sorter: makeDateSorter('factEnd'), render: getDate }), + makeDateColumn('начало', 'factStart'), + makeDateColumn('окончание', 'factEnd'), ]), makeNumericColumnPlanFact('Продолжительность, сут', 'period', filtersMinMax, makeFilterMinMaxFunction, numericRender), makeNumericColumnPlanFact('МСП, м/ч', 'rateOfPenetration', filtersMinMax, makeFilterMinMaxFunction, numericRender), diff --git a/src/pages/Deposit.jsx b/src/pages/Deposit.jsx index 9779e78..f0eb9c3 100755 --- a/src/pages/Deposit.jsx +++ b/src/pages/Deposit.jsx @@ -1,120 +1,106 @@ -import { useState, useEffect, memo, useMemo } from 'react' +import { useEffect, memo, useMemo, useCallback } from 'react' import { Link, useLocation } from 'react-router-dom' import { Map, Overlay } from 'pigeon-maps' import { Popover, Badge } from 'antd' -import { useLayoutProps } from '@asb/context' +import { useDeposits, useLayoutProps } from '@asb/context' import { PointerIcon } from '@components/icons' -import LoaderPortal from '@components/LoaderPortal' import { FastRunMenu } from '@components/FastRunMenu' -import { invokeWebApiWrapperAsync } from '@components/factory' -import { arrayOrDefault, limitValue, withPermissions } from '@utils' -import { DepositService } from '@api' +import { limitValue, withPermissions } from '@utils' import '@styles/index.css' -const defaultViewParams = { center: [60.81226, 70.0562], zoom: 5 } - const zoomLimit = limitValue(5, 15) const calcViewParams = (clusters) => { - if ((clusters?.length ?? 0) <= 0) - return defaultViewParams + if ((clusters?.length ?? 0) <= 0) + return { center: [60.81226, 70.0562], zoom: 5 } - const center = clusters.reduce((sum, cluster) => { - sum[0] += (cluster.latitude / clusters.length) - sum[1] += (cluster.longitude / clusters.length) - return sum - }, [0, 0]) + const center = clusters.reduce((sum, cluster) => { + sum[0] += cluster.latitude + sum[1] += cluster.longitude + return sum + }, [0, 0]).map((elm) => elm / clusters.length) - const maxDeg = clusters.reduce((max, cluster) => { - const dLatitude = Math.abs(center[0] - cluster.latitude) - const dLongitude = Math.abs(center[1] - cluster.longitude) - const d = dLatitude > dLongitude ? dLatitude : dLongitude - return d > max ? d : max - }, 0) + const maxDeg = clusters.reduce((max, cluster) => { + const dLatitude = Math.abs(center[0] - cluster.latitude) + const dLongitude = Math.abs(center[1] - cluster.longitude) + return Math.max(Math.max(dLatitude, dLongitude), max) + }, 0) - // zoom max = 20 (too close) - // zoom min = 1 (mega far) - // 4 - full Russia (161.6 deg) - // 13.5 - Khanty-Mansiysk - const zoom = zoomLimit(5 + 5 / (maxDeg + 0.5)) + // zoom max = 20 (too close) + // zoom min = 1 (mega far) + // 4 - full Russia (161.6 deg) + // 13.5 - Khanty-Mansiysk + const zoom = zoomLimit(5 + 5 / (maxDeg + 0.5)) - return { center, zoom } + return { center, zoom } } const Deposit = memo(() => { - const [depositsData, setDepositsData] = useState([]) - const [showLoader, setShowLoader] = useState(false) - const [viewParams, setViewParams] = useState(defaultViewParams) + const deposits = useDeposits() + const setLayoutProps = useLayoutProps() + const location = useLocation() - const setLayoutProps = useLayoutProps() - - const location = useLocation() - - const selectorProps = useMemo(() => { - const hasId = location.pathname.length > '/deposit/'.length - - return { - expand: hasId ? [location.pathname] : true, - current: hasId ? location.pathname : undefined, - } - }, [location.pathname]) - - useEffect(() => setLayoutProps({ - sheet: false, - showSelector: true, - selectorProps, - title: 'Месторождение', - }), [setLayoutProps, selectorProps]) - - useEffect(() => { - invokeWebApiWrapperAsync( - async () => { - const deposits = await DepositService.getDeposits() - setDepositsData(arrayOrDefault(deposits)) - setViewParams(calcViewParams(deposits)) - }, - setShowLoader, - `Не удалось загрузить список кустов`, - { actionName: 'Получить список кустов' } - ) - }, []) - - return ( - <> - - -
- - {depositsData.map(deposit => ( - - - {deposit.clusters.map(cluster => ( - -
{cluster.caption}
- - ))} -
- } trigger={['click']} title={deposit.caption}> -
- - - -
- - + const makeDepositLinks = useCallback((clusters) => ( +
+ {clusters.map(cluster => ( + +
{cluster.caption}
+ ))} -
-
- - ) + ), [location.pathname]) + + const viewParams = useMemo(() => calcViewParams(deposits), [deposits]) + + useEffect(() => { + const hasId = location.pathname.length > '/deposit/'.length + + const selectorProps = { + expand: hasId ? [location.pathname] : true, + current: hasId ? location.pathname : undefined, + } + + setLayoutProps({ + sheet: false, + showSelector: true, + selectorProps, + title: 'Месторождение', + }) + }, [setLayoutProps, location.pathname]) + + return ( + <> + +
+ + {deposits.map(deposit => { + const anchor = [deposit.latitude, deposit.longitude] + const links = makeDepositLinks(deposit.clusters) + + return ( + + +
+ + + +
+
+
+ ) + })} +
+
+ + ) }) export default withPermissions(Deposit, ['Cluster.get']) diff --git a/src/pages/Well/Telemetry/Archive/index.jsx b/src/pages/Well/Telemetry/Archive/index.jsx index ce3d94a..8c8c493 100644 --- a/src/pages/Well/Telemetry/Archive/index.jsx +++ b/src/pages/Well/Telemetry/Archive/index.jsx @@ -15,7 +15,7 @@ import { formatDate, range, withPermissions } from '@utils' import { TelemetryDataSaubService } from '@api' import { normalizeData } from '../TelemetryView' -import cursorRender from '../TelemetryView/cursorRender' +import { cursorRender } from '../TelemetryView/cursorRender' import { makeChartGroups, yAxis } from '../TelemetryView/dataset' const DATA_COUNT = 2048 // Колличество точек на подгрузку графика @@ -223,7 +223,7 @@ const Archive = memo(() => { const chartData = useMemo(() => cutData(dataSaub, domain.min, domain.max), [dataSaub, domain]) return ( - +
Начальная дата:  @@ -259,6 +259,7 @@ const Archive = memo(() => { render: cursorRender, } }} + style={{ flexGrow: 1 }} height={'76vh'} onWheel={onGraphWheel} /> diff --git a/src/pages/Well/Telemetry/Messages.jsx b/src/pages/Well/Telemetry/Messages.jsx index 653e122..4af1a31 100644 --- a/src/pages/Well/Telemetry/Messages.jsx +++ b/src/pages/Well/Telemetry/Messages.jsx @@ -28,7 +28,7 @@ const categoryDictionary = { // Конфигурация таблицы export const makeMessageColumns = (idWell) => [ - makeDateColumn('Дата', 'date', undefined, undefined, { width: '10rem' }), + makeDateColumn('Дата', 'date', undefined, undefined, { width: '120px' }), makeNumericColumn('Глубина, м', 'wellDepth', null, null, (depth, item) => ( [ ellipsis: true, }), makeColumn('Сообщение', 'message', { onFilter: (value, record) => record.name.indexOf(value) === 0 }), - makeTextColumn('Пользователь', 'user', null, null, null, { width: '10rem' }), + makeTextColumn('Пользователь', 'user', null, null, null, { width: '120px' }), ] const filterOptions = [ diff --git a/src/pages/Well/Telemetry/TelemetryView/index.jsx b/src/pages/Well/Telemetry/TelemetryView/index.jsx index 1c5c4f9..76b0bcf 100644 --- a/src/pages/Well/Telemetry/TelemetryView/index.jsx +++ b/src/pages/Well/Telemetry/TelemetryView/index.jsx @@ -24,15 +24,15 @@ import WirelineRunOut from './WirelineRunOut' import { CustomColumn } from './CustomColumn' import { ModeDisplay } from './ModeDisplay' import { UserOfWell } from './UserOfWells' -import cursorRender from './cursorRender' import { Setpoints } from './Setpoints' +import { cursorRender } from './cursorRender' import MomentStabPicEnabled from '@images/DempherOn.png' import MomentStabPicDisabled from '@images/DempherOff.png' import SpinPicEnabled from '@images/SpinEnabled.png' import SpinPicDisabled from '@images/SpinDisabled.png' -import '@styles/monitoring.less' +import '@styles/telemetry_view.less' import '@styles/message.less' const { Option } = Select @@ -64,6 +64,7 @@ const makeSubjectSubsription = (subject$, handler) => { } const TelemetryView = memo(() => { + const [currentWellId, setCurrentWellId] = useState(null) const [dataSaub, setDataSaub] = useState([]) const [dataSpin, setDataSpin] = useState([]) const [chartInterval, setChartInterval] = useState(defaultPeriod) @@ -78,12 +79,12 @@ const TelemetryView = memo(() => { const saubSubject$ = useMemo(() => new BehaviorSubject(), []) const spinSubject$ = useMemo(() => new BehaviorSubject(), []) - const handleDataSaub = useCallback((data) => { - if (!data) return - - const dataSaub = normalizeData(data) + const handleDataSaub = useCallback((data, replace = false) => { setDataSaub((prev) => { - const out = [...prev, ...dataSaub] + if (!data) + return replace ? [] : prev + const dataSaub = normalizeData(data) + const out = replace ? [...dataSaub] : [...prev, ...dataSaub] out.sort(dateSorter) return out }) @@ -115,6 +116,8 @@ const TelemetryView = memo(() => { useEffect(() => makeSubjectSubsription(spinSubject$, handleDataSpin), [spinSubject$, handleDataSpin]) useEffect(() => { + if (currentWellId == well.id) return + setCurrentWellId(well.id) invokeWebApiWrapperAsync( async () => { const flowChart = await DrillFlowChartService.getByIdWell(well.id) @@ -128,7 +131,7 @@ const TelemetryView = memo(() => { `Не удалось получить данные`, { actionName: 'Получение данных по скважине', well } ) - }, [well, chartInterval, handleDataSpin, handleDataSaub]) + }, [well, chartInterval, currentWellId, handleDataSaub]) useEffect(() => { const unsubscribe = Subscribe( @@ -163,7 +166,7 @@ const TelemetryView = memo(() => { return ( - +
diff --git a/src/pages/Well/WellOperations/DrillProcessFlow.jsx b/src/pages/Well/WellOperations/DrillProcessFlow.jsx index 86dcb09..354b32b 100644 --- a/src/pages/Well/WellOperations/DrillProcessFlow.jsx +++ b/src/pages/Well/WellOperations/DrillProcessFlow.jsx @@ -10,7 +10,7 @@ import { arrayOrDefault } from '@utils' const columns = [ makeNumericStartEnd('Глубина, м', 'depth'), makeNumericMinMax('Нагрузка, т', 'axialLoad'), - makeNumericMinMax('Давление, атм', 'pressure'), + makeNumericMinMax('Перепад давления, атм', 'pressure'), makeNumericMinMax('Момент на ВСП, кН·м', 'rotorTorque'), makeNumericMinMax('Обороты на ВСП, об/мин', 'rotorSpeed'), makeNumericMinMax('Расход, л/с', 'flow') diff --git a/src/pages/Well/WellOperations/WellDrillParams.jsx b/src/pages/Well/WellOperations/WellDrillParams.jsx index 0ae6097..57b1ba8 100644 --- a/src/pages/Well/WellOperations/WellDrillParams.jsx +++ b/src/pages/Well/WellOperations/WellDrillParams.jsx @@ -26,7 +26,7 @@ export const getColumns = async (idWell) => { sorter: makeNumericSorter('idWellSectionType'), }), makeNumericAvgRange('Нагрузка, т', 'axialLoad', 1), - makeNumericAvgRange('Давление, атм', 'pressure', 1), + makeNumericAvgRange('Перепад давления, атм', 'pressure', 1), makeNumericAvgRange('Момент на ВСП, кН·м', 'rotorTorque', 1), makeNumericAvgRange('Обороты на ВСП, об/мин', 'rotorSpeed', 1), makeNumericAvgRange('Расход, л/с', 'flow', 1), diff --git a/src/styles/include/antd_theme.less b/src/styles/include/antd_theme.less index 68e0e3f..c9acd72 100644 --- a/src/styles/include/antd_theme.less +++ b/src/styles/include/antd_theme.less @@ -7,8 +7,5 @@ // Переменные для темы тут: // https://github.com/ant-design/ant-design/blob/master/components/style/themes/default.less -//@primary-color: rgba(124, 124, 124, 0.3); -@primary-color: rgb(195, 40,40); -//@primary-color:rgb(65, 63, 61); -//@layout-header-background: rgb(195, 40,40); -@layout-header-background: rgb(65, 63, 61); +@primary-color: #C32828; // rgb(195, 40, 40) +@layout-header-background:#413F3D; // rgb(65, 63, 61) diff --git a/src/styles/index.css b/src/styles/index.css index 53d4e5d..217ba16 100755 --- a/src/styles/index.css +++ b/src/styles/index.css @@ -135,7 +135,7 @@ code { -moz-user-select: none; /* Old versions of Firefox */ -ms-user-select: none; /* Internet Explorer/Edge */ user-select: none; /* Non-prefixed version, currently - supported by Chrome, Edge, Opera and Firefox */ + supported by Chrome, Edge, Opera and Firefox */ } .download-link { @@ -153,4 +153,17 @@ code { .color-pale-green { background-color: #98fb98; -} \ No newline at end of file +} + +.asb-grid-item { + padding: 4px; +} + +.pointer { + cursor: pointer; +} + +.deposit-page { + height: 100vh; + overflow: hidden; +} diff --git a/src/styles/layout.less b/src/styles/layout.less index 4d5861f..225dd03 100644 --- a/src/styles/layout.less +++ b/src/styles/layout.less @@ -19,6 +19,10 @@ } .page-layout { + --sheet-padding: 15px; + + @sheet-padding: var(--sheet-padding); + height: 100vh; & .menu-sider { @@ -62,7 +66,7 @@ background-color: transparent; cursor: pointer; overflow: hidden; - + &:hover { color: white; } @@ -88,8 +92,9 @@ display: flex; justify-content: space-between; align-items: center; - gap: 15px; - padding: 0 15px 15px 15px; + gap: @sheet-padding; + padding: @sheet-padding; + padding-top: 0; & .ant-breadcrumb-link, .ant-breadcrumb-separator { .no-select; @@ -99,7 +104,7 @@ } & .sheet{ - padding: 15px; + padding: @sheet-padding; // min-height: calc(@layout-min-height - 30px); // 280px; overflow: visible; // margin: 15px; @@ -126,3 +131,15 @@ .site-layout-background { background: #fff; } + +@media only screen and (max-width: 1280px) { + .page-layout { + --sheet-padding: 10px; + } +} + +@media only screen and (max-width: 1024px) { + .page-layout { + --sheet-padding: 5px; + } +} diff --git a/src/styles/loader.css b/src/styles/loader.css index 23ab350..33a233a 100755 --- a/src/styles/loader.css +++ b/src/styles/loader.css @@ -39,11 +39,18 @@ } .loader-content{ + display: flex; + flex-direction: column; grid-column-start: 1; grid-column-end: span 3; grid-row-start: 1; } +.loader-content.loader-content-fill { + height: 100%; + width: 100%; +} + .loader-overlay{ grid-column-start: 1; grid-column-end: span 3; diff --git a/src/styles/monitoring.less b/src/styles/monitoring.less deleted file mode 100644 index 9a3cb0e..0000000 --- a/src/styles/monitoring.less +++ /dev/null @@ -1,17 +0,0 @@ -.page-top { - display: flex; - flex-wrap: wrap; - margin: -5px; - - & > * { - margin: 5px; - } - - & > .icons { - display: flex; - - & > * { - margin-left: 15px; - } - } -} diff --git a/src/styles/telemetry_view.less b/src/styles/telemetry_view.less new file mode 100644 index 0000000..cdbb3c6 --- /dev/null +++ b/src/styles/telemetry_view.less @@ -0,0 +1,66 @@ +.telemetry-view-page { + --page-gap: 10px; + + @page-gap: var(--page-gap); + + .flex-container { + display: flex; + align-items: stretch; + justify-content: space-between; + gap: @page-gap; + } + + width: 100%; + height: 100%; + flex-direction: column; + .flex-container; + + & .page-top { + .flex-container; + flex-wrap: wrap; + justify-content: flex-start; + + & .icons { + display: flex; + + & > * { + margin-left: 15px; + } + } + } + + & .page-main { + flex-grow: 1; + .flex-container; + + & .page-left { + .flex-container; + justify-content: flex-start; + flex-direction: column; + + & .modes, & .current-values { + .flex-container; + flex-direction: column; + gap: 0; + } + } + + & .page-right { + flex-grow: 1; + .flex-container; + flex-direction: column; + } + } +} + +@media only screen and (max-width: 1280px) { + .telemetry-view-page { + --page-gap: 7.5px; + } +} + +@media only screen and (max-width: 1024px) { + .telemetry-view-page { + --page-gap: 5px; + } +} diff --git a/src/styles/well_composite.less b/src/styles/well_composite.less index ea64fc8..4d000cc 100644 --- a/src/styles/well_composite.less +++ b/src/styles/well_composite.less @@ -4,7 +4,7 @@ right: 0; top: 0; height: 100%; - background-color: red; + background-color: #FFF2F0; } & .avg-value {