относительные пути заменены на алиасы

This commit is contained in:
Александр Сироткин 2022-01-24 17:32:45 +05:00
parent e6264ba638
commit 8043c5c5e2
50 changed files with 445 additions and 388 deletions

View File

@ -1,4 +1,5 @@
const CracoLessPlugin = require('craco-less'); const CracoLessPlugin = require('craco-less')
const CracoAlias = require('craco-alias')
module.exports = { module.exports = {
plugins: [ plugins: [
@ -12,6 +13,13 @@ module.exports = {
}, },
}, },
}, },
}, }, {
plugin: CracoAlias,
options: {
source: 'tsconfig',
baseUrl: './src',
tsConfigPath: './tsconfig.paths.json'
}
}
], ],
}; }

14
package-lock.json generated
View File

@ -31,6 +31,7 @@
"devDependencies": { "devDependencies": {
"@types/react": "^17.0.3", "@types/react": "^17.0.3",
"@types/react-router-dom": "^5.3.2", "@types/react-router-dom": "^5.3.2",
"craco-alias": "^3.0.1",
"openapi-typescript": "^3.4.1", "openapi-typescript": "^3.4.1",
"openapi-typescript-codegen": "^0.9.3" "openapi-typescript-codegen": "^0.9.3"
} }
@ -6035,6 +6036,12 @@
"node": ">=10" "node": ">=10"
} }
}, },
"node_modules/craco-alias": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/craco-alias/-/craco-alias-3.0.1.tgz",
"integrity": "sha512-N+Qaf/Gr/f3o5ZH2TQjMu5NhR9PnT1ZYsfejpNvZPpB0ujdrhsSr4Ct6GVjnV5ostCVquhTKJpIVBKyL9qDQYA==",
"dev": true
},
"node_modules/craco-less": { "node_modules/craco-less": {
"version": "1.17.1", "version": "1.17.1",
"resolved": "https://registry.npmjs.org/craco-less/-/craco-less-1.17.1.tgz", "resolved": "https://registry.npmjs.org/craco-less/-/craco-less-1.17.1.tgz",
@ -27532,6 +27539,12 @@
"yaml": "^1.10.0" "yaml": "^1.10.0"
} }
}, },
"craco-alias": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/craco-alias/-/craco-alias-3.0.1.tgz",
"integrity": "sha512-N+Qaf/Gr/f3o5ZH2TQjMu5NhR9PnT1ZYsfejpNvZPpB0ujdrhsSr4Ct6GVjnV5ostCVquhTKJpIVBKyL9qDQYA==",
"dev": true
},
"craco-less": { "craco-less": {
"version": "1.17.1", "version": "1.17.1",
"resolved": "https://registry.npmjs.org/craco-less/-/craco-less-1.17.1.tgz", "resolved": "https://registry.npmjs.org/craco-less/-/craco-less-1.17.1.tgz",
@ -39581,6 +39594,7 @@
}, },
"ssri": { "ssri": {
"version": "6.0.1", "version": "6.0.1",
"integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==",
"requires": { "requires": {
"figgy-pudding": "^3.5.1" "figgy-pudding": "^3.5.1"
} }

View File

@ -27,8 +27,8 @@
"start": "craco start", "start": "craco start",
"build": "craco build", "build": "craco build",
"test": "craco test", "test": "craco test",
"update_openapi":"npx openapi -i http://127.0.0.1:5000/swagger/v1/swagger.json -o src/services/api", "update_openapi": "npx openapi -i http://127.0.0.1:5000/swagger/v1/swagger.json -o src/services/api",
"update_openapi_server":"npx openapi -i http://192.168.1.70:5000/swagger/v1/swagger.json -o src/services/api", "update_openapi_server": "npx openapi -i http://192.168.1.70:5000/swagger/v1/swagger.json -o src/services/api",
"react_start": "react-scripts start", "react_start": "react-scripts start",
"react_build": "react-scripts build", "react_build": "react-scripts build",
"react_test": "react-scripts test", "react_test": "react-scripts test",
@ -55,6 +55,8 @@
}, },
"devDependencies": { "devDependencies": {
"@types/react": "^17.0.3", "@types/react": "^17.0.3",
"@types/react-router-dom": "^5.3.2",
"craco-alias": "^3.0.1",
"openapi-typescript": "^3.4.1", "openapi-typescript": "^3.4.1",
"openapi-typescript-codegen": "^0.9.3" "openapi-typescript-codegen": "^0.9.3"
} }

View File

@ -1,17 +1,19 @@
import { Link } from 'react-router-dom' import { memo } from 'react'
import { Layout } from 'antd' import { Layout } from 'antd'
import { headerHeight } from '../utils' import { Link } from 'react-router-dom'
import { UserMenu } from './UserMenu'
import logo from '../images/logo_32.png'
type PageHeaderProps = { import logo from '@images/logo_32.png'
import { headerHeight } from '@utils'
import { UserMenu } from './UserMenu'
import { BasicProps } from 'antd/lib/layout/layout'
export type PageHeaderProps = BasicProps & {
title?: string title?: string
isAdmin?: boolean isAdmin?: boolean
children?: React.ReactNode children?: React.ReactNode
[other: string]: any
} }
export const PageHeader: React.FC<PageHeaderProps> = ({ title = 'Мониторинг', isAdmin, children, ...other }) => ( export const PageHeader: React.FC<PageHeaderProps> = memo(({ title = 'Мониторинг', isAdmin, children, ...other }) => (
<Layout> <Layout>
<Layout.Header className={'header'} {...other}> <Layout.Header className={'header'} {...other}>
<Link to={'/'} style={{ height: headerHeight }}> <Link to={'/'} style={{ height: headerHeight }}>
@ -22,6 +24,6 @@ export const PageHeader: React.FC<PageHeaderProps> = ({ title = 'Монитор
<UserMenu isAdmin={isAdmin} /> <UserMenu isAdmin={isAdmin} />
</Layout.Header> </Layout.Header>
</Layout> </Layout>
) ))
export default PageHeader export default PageHeader

View File

@ -3,16 +3,16 @@ import { DefaultValueType } from 'rc-tree-select/lib/interface'
import { useState, useEffect, ReactNode } from 'react' import { useState, useEffect, ReactNode } from 'react'
import { useHistory, useRouteMatch } from 'react-router-dom' import { useHistory, useRouteMatch } from 'react-router-dom'
import { isRawDate } from '../utils' import { isRawDate } from '@utils'
import LoaderPortal from './LoaderPortal' import LoaderPortal from './LoaderPortal'
import { WellIcon, WellIconState } from './icons' import { WellIcon, WellIconState } from './icons'
import { invokeWebApiWrapperAsync } from './factory' import { invokeWebApiWrapperAsync } from './factory'
import { DepositService, DepositDto } from '../services/api' import { DepositService, DepositDto } from '@api'
import { ReactComponent as DepositIcon } from '../images/DepositIcon.svg' import { ReactComponent as DepositIcon } from '@images/DepositIcon.svg'
import { ReactComponent as ClusterIcon } from '../images/ClusterIcon.svg' import { ReactComponent as ClusterIcon } from '@images/ClusterIcon.svg'
import '../styles/wellTreeSelect.css' import '@styles/wellTreeSelect.css'
export const getWellState = (idState?: number): WellIconState => idState === 1 ? 'active' : 'unknown' export const getWellState = (idState?: number): WellIconState => idState === 1 ? 'active' : 'unknown'
export const checkIsWellOnline = (lastTelemetryDate: unknown): boolean => export const checkIsWellOnline = (lastTelemetryDate: unknown): boolean =>

View File

@ -1,7 +1,8 @@
import { notification } from 'antd' import { notification } from 'antd'
import { Dispatch, SetStateAction } from 'react' import { Dispatch, ReactNode, SetStateAction } from 'react'
import { FileInfoDto } from '../services/api'
import { getUserToken } from '../utils/storage' import { FileInfoDto } from '@api'
import { getUserToken } from '@utils/storage'
const notificationTypeDictionary = new Map([ const notificationTypeDictionary = new Map([
['error' , { notifyInstance: notification.error , caption: 'Ошибка' }], ['error' , { notifyInstance: notification.error , caption: 'Ошибка' }],
@ -15,7 +16,7 @@ const notificationTypeDictionary = new Map([
* @param body string или ReactNode * @param body string или ReactNode
* @param notifyType для параметра типа. Допустимые значение 'error', 'warning', 'info' * @param notifyType для параметра типа. Допустимые значение 'error', 'warning', 'info'
*/ */
export const notify = (body: string | any, notifyType: string = 'info', other?: any) => { export const notify = (body: ReactNode, notifyType: string = 'info', other?: any) => {
if (!body) return if (!body) return
const instance = notificationTypeDictionary.get(notifyType) ?? const instance = notificationTypeDictionary.get(notifyType) ??

View File

@ -2,8 +2,8 @@ import { memo } from 'react'
import { Tooltip } from 'antd' import { Tooltip } from 'antd'
import { BankOutlined } from '@ant-design/icons' import { BankOutlined } from '@ant-design/icons'
import { CompanyDto } from '../../services/api' import { CompanyDto } from '@api'
import { Grid, GridItem } from '../Grid' import { Grid, GridItem } from '@components/Grid'
export type CompanyViewProps = { export type CompanyViewProps = {
company?: CompanyDto company?: CompanyDto

View File

@ -1,7 +1,7 @@
import { Tooltip, Tag, Typography, Popconfirm, Button } from 'antd' import { Tooltip, Tag, Typography, Popconfirm, Button } from 'antd'
import { memo } from 'react' import { memo } from 'react'
import { FileMarkDto } from '../../services/api' import { FileMarkDto } from '@api'
import { UserView } from './UserView' import { UserView } from './UserView'
const markTypes: { [id: number]: {color: string, text: string} } = { const markTypes: { [id: number]: {color: string, text: string} } = {

View File

@ -1,8 +1,8 @@
import { Tooltip } from 'antd' import { Tooltip } from 'antd'
import { memo } from 'react' import { memo } from 'react'
import { PermissionDto } from '../../services/api' import { PermissionDto } from '@api'
import { Grid, GridItem } from '../Grid' import { Grid, GridItem } from '@components/Grid'
export type PermissionViewProps = { export type PermissionViewProps = {
info?: PermissionDto info?: PermissionDto

View File

@ -1,8 +1,8 @@
import { memo } from 'react' import { memo } from 'react'
import { Tag, Tooltip } from 'antd' import { Tag, Tooltip } from 'antd'
import { UserRoleDto } from '../../services/api' import { UserRoleDto } from '@api'
import { Grid, GridItem } from '../Grid' import { Grid, GridItem } from '@components/Grid'
import PermissionView from './PermissionView' import PermissionView from './PermissionView'
export type RoleViewProps = { export type RoleViewProps = {

View File

@ -1,8 +1,8 @@
import { Fragment, memo } from 'react' import { Fragment, memo } from 'react'
import { Tooltip } from 'antd' import { Tooltip } from 'antd'
import { TelemetryDto, TelemetryInfoDto } from '../../services/api' import { TelemetryDto, TelemetryInfoDto } from '@api'
import { Grid, GridItem } from '../Grid' import { Grid, GridItem } from '@components/Grid'
const lables: Record<string, string> = { const lables: Record<string, string> = {
timeZoneId: 'Временная зона', timeZoneId: 'Временная зона',

View File

@ -2,8 +2,8 @@ import { memo } from 'react'
import { Tooltip } from 'antd' import { Tooltip } from 'antd'
import { UserOutlined } from '@ant-design/icons' import { UserOutlined } from '@ant-design/icons'
import { UserDto } from '../../services/api' import { UserDto } from '@api'
import { Grid, GridItem } from '../Grid' import { Grid, GridItem } from '@components/Grid'
import { CompanyView } from './CompanyView' import { CompanyView } from './CompanyView'
export type UserViewProps = { export type UserViewProps = {

View File

@ -1,7 +1,5 @@
import { useEffect, useState } from 'react' import { useEffect, useState } from 'react'
import LoaderPortal from '../../components/LoaderPortal'
import { invokeWebApiWrapperAsync } from '../../components/factory'
import { import {
defaultPagination, defaultPagination,
makeDateSorter, makeDateSorter,
@ -9,9 +7,11 @@ import {
makeNumericRender, makeNumericRender,
makeTextColumn, makeTextColumn,
Table Table
} from '../../components/Table' } from '@components/Table'
import { AdminTelemetryService } from '../../services/api' import LoaderPortal from '@components/LoaderPortal'
import { arrayOrDefault } from '../../utils' import { invokeWebApiWrapperAsync } from '@components/factory'
import { AdminTelemetryService } from '@api'
import { arrayOrDefault } from '@utils'
const columns = [ const columns = [
makeNumericColumn('ID', 'id', null, null, makeNumericRender(0)), makeNumericColumn('ID', 'id', null, null, makeNumericRender(0)),

View File

@ -1,10 +1,10 @@
import { memo, useEffect, useState } from 'react' import { memo, useEffect, useState } from 'react'
import { invokeWebApiWrapperAsync } from '../../components/factory' import LoaderPortal from '@components/LoaderPortal'
import LoaderPortal from '../../components/LoaderPortal' import { invokeWebApiWrapperAsync } from '@components/factory'
import { defaultPagination, makeColumn, makeDateSorter, makeStringSorter, Table } from '../../components/Table' import { defaultPagination, makeColumn, makeDateSorter, makeStringSorter, Table } from '@components/Table'
import { RequerstTrackerService } from '../../services/api' import { RequerstTrackerService } from '@api'
import { arrayOrDefault, formatDate } from '../../utils' import { arrayOrDefault, formatDate } from '@utils'
const logRecordCount = 1000 const logRecordCount = 1000

View File

@ -1,7 +1,7 @@
import { memo } from 'react' import { memo } from 'react'
import { Select } from 'antd' import { Select } from 'antd'
import { getTelemetryLabel } from '../../../components/views' import { getTelemetryLabel } from '@components/views'
export const TelemetrySelect = memo(({ telemetry, value, onChange }) => { export const TelemetrySelect = memo(({ telemetry, value, onChange }) => {
const onSelectChange = (id) => { const onSelectChange = (id) => {

View File

@ -1,6 +1,7 @@
import { useEffect, useState } from 'react' import { useEffect, useState } from 'react'
import { Grid, GridItem } from '../../components/Grid'
import { Column } from '../../components/charts/Column' import { Grid, GridItem } from '@components/Grid'
import { Column } from '@components/charts/Column'
export const ArchiveColumn = ({ lineGroup, data, interval, style, headerHeight, yStart }) => { export const ArchiveColumn = ({ lineGroup, data, interval, style, headerHeight, yStart }) => {
const [lineGroupWithoutShapes, setLineGroupWithoutShapes] = useState([]) const [lineGroupWithoutShapes, setLineGroupWithoutShapes] = useState([])
@ -33,3 +34,5 @@ export const ArchiveColumn = ({ lineGroup, data, interval, style, headerHeight,
</div> </div>
) )
} }
export default ArchiveColumn

View File

@ -1,7 +1,9 @@
import { useEffect, useState } from 'react' import { useEffect, useState } from 'react'
import { Grid, GridItem } from '../../components/Grid'
import { Grid, GridItem } from '@components/Grid'
import { paramsGroups } from '@pages/TelemetryView'
import { ArchiveColumn } from './ArchiveColumn' import { ArchiveColumn } from './ArchiveColumn'
import { paramsGroups } from '../TelemetryView'
const interpolationSearch = (data, begin, end, accessor) => { const interpolationSearch = (data, begin, end, accessor) => {
const fy = (i) => new Date(data[i]?.[accessor] ?? 0) const fy = (i) => new Date(data[i]?.[accessor] ?? 0)
@ -64,3 +66,5 @@ export const ArchiveDisplay = ({data, startDate, interval, onWheel}) => {
</Grid> </Grid>
) )
} }
export default ArchiveDisplay

View File

@ -10,13 +10,14 @@ import {
makeDateSorter, makeDateSorter,
makeNumericColumnPlanFact, makeNumericColumnPlanFact,
Table, Table,
} from '../../components/Table' makeNumericRender,
import { invokeWebApiWrapperAsync } from '../../components/factory' } from '@components/Table'
import LoaderPortal from '../../components/LoaderPortal' import { CompanyView } from '@components/views'
import PointerIcon from '../../components/icons/PointerIcon' import LoaderPortal from '@components/LoaderPortal'
import { CompanyView } from '../../components/views' import PointerIcon from '@components/icons/PointerIcon'
import { invokeWebApiWrapperAsync } from '@components/factory'
import { Tvd } from '../WellOperations/Tvd' import { Tvd } from '@pages/WellOperations/Tvd'
import { import {
getOperations, getOperations,
calcAndUpdateStatsBySections, calcAndUpdateStatsBySections,
@ -33,8 +34,7 @@ const filtersWellsType = []
const DAY_IN_MS = 86_400_000 const DAY_IN_MS = 86_400_000
const ONLINE_DEADTIME = 600_000 const ONLINE_DEADTIME = 600_000
export default function ClusterWells({statsWells}) { export const ClusterWells = ({ statsWells }) => {
const [selectedWellId, setSelectedWellId] = useState(0) const [selectedWellId, setSelectedWellId] = useState(0)
const [isTVDModalVisible, setIsTVDModalVisible] = useState(false) const [isTVDModalVisible, setIsTVDModalVisible] = useState(false)
const [isOpsModalVisible, setIsOpsModalVisible] = useState(false) const [isOpsModalVisible, setIsOpsModalVisible] = useState(false)
@ -128,10 +128,10 @@ export default function ClusterWells({statsWells}) {
makeColumn('начало', 'factStart', { sorter: makeDateSorter('factStart'), render: getDate }), makeColumn('начало', 'factStart', { sorter: makeDateSorter('factStart'), render: getDate }),
makeColumn('окончание', 'factEnd', { sorter: makeDateSorter('factEnd'), render: getDate }), makeColumn('окончание', 'factEnd', { sorter: makeDateSorter('factEnd'), render: getDate }),
]), ]),
makeNumericColumnPlanFact('Продолжительность, сут', 'period', filtersMinMax, makeFilterMinMaxFunction), makeNumericColumnPlanFact('Продолжительность, сут', 'period', filtersMinMax, makeFilterMinMaxFunction, makeNumericRender(1)),
makeNumericColumnPlanFact('МСП, м/ч', 'rateOfPenetration', filtersMinMax, makeFilterMinMaxFunction), makeNumericColumnPlanFact('МСП, м/ч', 'rateOfPenetration', filtersMinMax, makeFilterMinMaxFunction, makeNumericRender(1)),
makeNumericColumnPlanFact('Рейсовая скорость, м/ч', 'routeSpeed', filtersMinMax, makeFilterMinMaxFunction), makeNumericColumnPlanFact('Рейсовая скорость, м/ч', 'routeSpeed', filtersMinMax, makeFilterMinMaxFunction, makeNumericRender(1)),
makeNumericColumnPlanFact('НПВ, сут', 'notProductiveTime', filtersMinMax, makeFilterMinMaxFunction), makeNumericColumnPlanFact('НПВ, сут', 'notProductiveTime', filtersMinMax, makeFilterMinMaxFunction, makeNumericRender(1)),
{ {
title: 'TVD', title: 'TVD',
key: 'tvd', key: 'tvd',
@ -199,3 +199,5 @@ export default function ClusterWells({statsWells}) {
</> </>
) )
} }
export default ClusterWells

View File

@ -1,23 +1,20 @@
import { Table } from 'antd'; import { Table } from 'antd'
import {
makeTextColumn, import { makeTextColumn, makeNumericColumnPlanFact } from '@components/Table'
makeNumericColumnPlanFact
} from '../../components/Table'
import { getPrecision } from './functions' import { getPrecision } from './functions'
export default function WellOperationsTable({wellOperations}) { export const WellOperationsTable = ({ wellOperations }) => {
const columns = [ const columns = [
makeTextColumn('Конструкция секции','sectionType'), makeTextColumn('Конструкция секции','sectionType'),
makeTextColumn('Операция','operationName'), makeTextColumn('Операция','operationName'),
makeNumericColumnPlanFact('Глубина забоя', 'depth', null, null, getPrecision), makeNumericColumnPlanFact('Глубина забоя', 'depth', null, null, getPrecision),
makeNumericColumnPlanFact('Часы', 'durationHours', null, null, getPrecision), makeNumericColumnPlanFact('Часы', 'durationHours', null, null, getPrecision),
makeNumericColumnPlanFact('Комментарий', 'comment', null, null, (text) => text ?? '-') makeNumericColumnPlanFact('Комментарий', 'comment', null, null, (text) => text ?? '-')
]; ]
const operations = wellOperations?.map(el => { const operations = wellOperations?.map(el => ({
return {
key: el.plan?.id ?? el.fact.id, key: el.plan?.id ?? el.fact.id,
sectionType: el.plan?.wellSectionTypeName ?? el.fact?.wellSectionTypeName, sectionType: el.plan?.wellSectionTypeName ?? el.fact?.wellSectionTypeName,
operationName: `${el.plan?.categoryName ?? el.fact?.categoryName ?? ''} ${' '} operationName: `${el.plan?.categoryName ?? el.fact?.categoryName ?? ''} ${' '}
@ -28,17 +25,18 @@ export default function WellOperationsTable({wellOperations}) {
durationHoursFact: el.fact?.durationHours, durationHoursFact: el.fact?.durationHours,
commentPlan: el.plan?.comment ?? '-', commentPlan: el.plan?.comment ?? '-',
commentFact: el.fact?.comment ?? '-' commentFact: el.fact?.comment ?? '-'
} }))
})
return( return(
<Table <Table
bordered
size={'small'}
columns={columns} columns={columns}
dataSource={operations} dataSource={operations}
size={'small'}
bordered
pagination={{ defaultPageSize: 10 }}
rowKey={(record) => record.key} rowKey={(record) => record.key}
pagination={{ defaultPageSize: 10 }}
/> />
) )
} }
export default WellOperationsTable

View File

@ -1,4 +1,4 @@
import { OperationStatService } from '../../services/api' import { OperationStatService } from '@api'
const maxPrefix = 'isMax' const maxPrefix = 'isMax'
const minPrefix = 'isMin' const minPrefix = 'isMin'

View File

@ -1,24 +1,26 @@
import { useParams } from 'react-router-dom'
import { useState, useEffect } from 'react' import { useState, useEffect } from 'react'
import ClusterWells from './ClusterWells' import { useParams } from 'react-router-dom'
import LoaderPortal from '../../components/LoaderPortal'
import { invokeWebApiWrapperAsync } from '../../components/factory'
import { OperationStatService } from '../../services/api'
import { arrayOrDefault } from '@utils'
import { OperationStatService } from '@api'
import LoaderPortal from '@components/LoaderPortal'
import { invokeWebApiWrapperAsync } from '@components/factory'
import ClusterWells from './ClusterWells'
export const Cluster = () => { export const Cluster = () => {
const { idClaster } = useParams() const { idCluster } = useParams()
const [data, setData] = useState([]) const [data, setData] = useState([])
const [showLoader, setShowLoader] = useState(false) const [showLoader, setShowLoader] = useState(false)
useEffect(() => invokeWebApiWrapperAsync( useEffect(() => invokeWebApiWrapperAsync(
async () => { async () => {
const clusterData = await OperationStatService.getStatCluster(idClaster) const clusterData = await OperationStatService.getStatCluster(idCluster)
setData(clusterData?.statsWells ?? []) setData(arrayOrDefault(clusterData?.statsWells))
}, },
setShowLoader, setShowLoader,
`Не удалось загрузить данные по кусту "${idClaster}"` `Не удалось загрузить данные по кусту "${idCluster}"`
), [idClaster]) ), [idCluster])
return ( return (
<LoaderPortal show={showLoader}> <LoaderPortal show={showLoader}>

View File

@ -2,10 +2,10 @@ import { Map, Overlay } from 'pigeon-maps'
import { Link } from 'react-router-dom' import { Link } from 'react-router-dom'
import { useState, useEffect, memo } from 'react' import { useState, useEffect, memo } from 'react'
import { PointerIcon } from '../components/icons' import { ClusterService } from '@api'
import LoaderPortal from '../components/LoaderPortal' import { PointerIcon } from '@components/icons'
import { ClusterService } from '../services/api' import LoaderPortal from '@components/LoaderPortal'
import { invokeWebApiWrapperAsync } from '../components/factory' import { invokeWebApiWrapperAsync } from '@components/factory'
const defaultViewParams = { center: [60.81226, 70.0562], zoom: 5 } const defaultViewParams = { center: [60.81226, 70.0562], zoom: 5 }

View File

@ -1,12 +1,13 @@
import moment from 'moment' import moment from 'moment'
import { useState, useEffect } from 'react' import { useState, useEffect } from 'react'
import { DatePicker, Button, Input } from 'antd' import { DatePicker, Button, Input } from 'antd'
import { FileService } from '../../services/api'
import { invokeWebApiWrapperAsync, downloadFile, formatBytes } from '../../components/factory' import { FileService } from '@api'
import { EditableTable, makePaginationObject } from '../../components/Table' import LoaderPortal from '@components/LoaderPortal'
import { UploadForm } from '../../components/UploadForm' import { UploadForm } from '@components/UploadForm'
import LoaderPortal from '../../components/LoaderPortal' import { CompanyView, UserView } from '@components/views'
import { CompanyView, UserView } from '../../components/views' import { EditableTable, makePaginationObject } from '@components/Table'
import { invokeWebApiWrapperAsync, downloadFile, formatBytes } from '@components/factory'
const pageSize = 12 const pageSize = 12
const { RangePicker } = DatePicker const { RangePicker } = DatePicker
@ -44,7 +45,7 @@ const columns = [
} }
] ]
export default function DocumentsTemplate({ idCategory, idWell, accept, headerChild, customColumns, beforeTable, onChange}) { export const DocumentsTemplate = ({ idCategory, idWell, accept, headerChild, customColumns, beforeTable, onChange}) => {
const [page, setPage] = useState(1) const [page, setPage] = useState(1)
const [filterDataRange, setFilterDataRange] = useState([]) const [filterDataRange, setFilterDataRange] = useState([])
const [filterCompanyName, setFilterCompanyName] = useState([]) const [filterCompanyName, setFilterCompanyName] = useState([])
@ -172,3 +173,5 @@ export default function DocumentsTemplate({ idCategory, idWell, accept, headerCh
</LoaderPortal> </LoaderPortal>
) )
} }
export default DocumentsTemplate

View File

@ -3,18 +3,18 @@ import { UserOutlined, LockOutlined } from '@ant-design/icons'
import { useState } from 'react' import { useState } from 'react'
import { Link, useHistory } from 'react-router-dom' import { Link, useHistory } from 'react-router-dom'
import { AuthService } from '../services/api/' import { AuthService } from '@api'
import LoaderPortal from '../components/LoaderPortal' import LoaderPortal from '@components/LoaderPortal'
import { invokeWebApiWrapperAsync } from '../components/factory' import { invokeWebApiWrapperAsync } from '@components/factory'
import { loginRules, passwordRules } from '../utils/validationRules' import { loginRules, passwordRules } from '@utils/validationRules'
import { setUser } from '../utils/storage' import { setUser } from '@utils/storage'
import '../styles/index.css' import '@styles/index.css'
import logo from '../images/logo_32.png' import logo from '@images/logo_32.png'
const logoIcon = <img src={logo} alt={'АСБ'} className={'logo'} width={130}/> const logoIcon = <img src={logo} alt={'АСБ'} className={'logo'} width={130} />
export default function Login() { export const Login = () => {
const history = useHistory() const history = useHistory()
const [showLoader, setShowLoader] = useState(false) const [showLoader, setShowLoader] = useState(false)
@ -52,3 +52,5 @@ export default function Login() {
</LoaderPortal> </LoaderPortal>
) )
} }
export default Login

View File

@ -1,8 +1,8 @@
import { Modal } from 'antd' import { Modal } from 'antd'
import { memo, useEffect, useState } from 'react' import { memo, useEffect, useState } from 'react'
import { Table } from '../../components/Table' import { Table } from '@components/Table'
import { formatDate } from '../../utils' import { formatDate } from '@utils'
import { v } from './columnsCommon' import { v } from './columnsCommon'
@ -52,3 +52,5 @@ export const InclinometryTable = memo(({ group, visible, onClose }) => {
</Modal> </Modal>
) )
}) })
export default InclinometryTable

View File

@ -1,10 +1,10 @@
import { memo, Fragment } from 'react' import { memo, Fragment } from 'react'
import { Empty, Form } from 'antd' import { Empty, Form } from 'antd'
import { Grid, GridItem } from '../../components/Grid' import { Grid, GridItem } from '@components/Grid'
import '../../styles/index.css' import '@styles/index.css'
import '../../styles/measure.css' import '@styles/measure.css'
const colsCount = 3 const colsCount = 3

View File

@ -1,8 +1,8 @@
import { Input } from 'antd' import { Input } from 'antd'
import { RegExpIsFloat } from '../../components/Table' import { RegExpIsFloat } from '@components/Table'
import '../../styles/measure.css' import '@styles/measure.css'
export const v = (text) => ( export const v = (text) => (
<div className={'v-div'}> <div className={'v-div'}>

View File

@ -1,4 +1,4 @@
import { makeColumn } from '../../components/Table' import { makeColumn } from '@components/Table'
import { numericColumnOptions, textColumnOptions } from './columnsCommon' import { numericColumnOptions, textColumnOptions } from './columnsCommon'

View File

@ -2,9 +2,9 @@ import { Button } from 'antd'
import { useState, useEffect } from 'react' import { useState, useEffect } from 'react'
import { TableOutlined } from '@ant-design/icons' import { TableOutlined } from '@ant-design/icons'
import { MeasureService } from '../../services/api' import { MeasureService } from '@api'
import LoaderPortal from '../../components/LoaderPortal' import LoaderPortal from '@components/LoaderPortal'
import { invokeWebApiWrapperAsync } from '../../components/factory' import { invokeWebApiWrapperAsync } from '@components/factory'
import { MeasureTable } from './MeasureTable' import { MeasureTable } from './MeasureTable'
import { InclinometryTable } from './InclinometryTable' import { InclinometryTable } from './InclinometryTable'

View File

@ -1,4 +1,5 @@
import { makeColumn } from '../../components/Table' import { makeColumn } from '@components/Table'
import { numericColumnOptions, textColumnOptions } from './columnsCommon' import { numericColumnOptions, textColumnOptions } from './columnsCommon'
export const columnsMudDiagram = [ export const columnsMudDiagram = [

View File

@ -1,4 +1,4 @@
import { makeColumn } from '../../components/Table' import { makeColumn } from '@components/Table'
import { numericColumnOptions, textColumnOptions } from './columnsCommon' import { numericColumnOptions, textColumnOptions } from './columnsCommon'
export const columnsNnb = [ export const columnsNnb = [

View File

@ -1,11 +1,12 @@
import { Table, Select, DatePicker, Input } from 'antd'
import { useState, useEffect } from 'react'
import moment from 'moment' import moment from 'moment'
import { useState, useEffect, memo } from 'react'
import { Table, Select, DatePicker, Input } from 'antd'
import { MessageService } from '../services/api' import { MessageService } from '@api'
import LoaderPortal from '../components/LoaderPortal' import { invokeWebApiWrapperAsync } from '@components/factory'
import { notify } from '../components/factory' import LoaderPortal from '@components/LoaderPortal'
import '../styles/message.css'
import '@styles/message.css'
const { Option } = Select const { Option } = Select
const pageSize = 26 const pageSize = 26
@ -14,9 +15,9 @@ const { Search } = Input
// Словарь категорий для строк таблицы // Словарь категорий для строк таблицы
const categoryDictionary = { const categoryDictionary = {
1: {title: 'Важное'}, 1: { title: 'Важное' },
2: {title: 'Предупреждение'}, 2: { title: 'Предупреждение' },
3: {title: 'Информация'}, 3: { title: 'Информация' },
} }
// Конфигурация таблицы // Конфигурация таблицы
@ -59,13 +60,13 @@ export const columns = [
] ]
const filterOptions = [ const filterOptions = [
{label: 'Важное', value: 1}, { value: 1, label: 'Важное' },
{label: 'Предупреждение', value: 2}, { value: 2, label: 'Предупреждение' },
{label: 'Информация', value: 3}, { value: 3, label: 'Информация' },
] ]
// Данные для таблицы // Данные для таблицы
export default function Messages({idWell}) { export const Messages = memo(({ idWell }) => {
const [messages, setMessages] = useState([]) const [messages, setMessages] = useState([])
const [pagination, setPagination] = useState(null) const [pagination, setPagination] = useState(null)
const [page, setPage] = useState(1) const [page, setPage] = useState(1)
@ -76,27 +77,14 @@ export default function Messages({idWell}) {
const children = filterOptions.map((line) => <Option key={line.value}>{line.label}</Option>) const children = filterOptions.map((line) => <Option key={line.value}>{line.label}</Option>)
const onChangeRange = (range) => setRange(range)
const onChangeSearchString = (message) => setSearchString(message.length > 2 ? message : '') const onChangeSearchString = (message) => setSearchString(message.length > 2 ? message : '')
useEffect(() => { useEffect(() => invokeWebApiWrapperAsync(
const GetMessages = async () => { async () => {
setShowLoader(true)
try {
const [begin, end] = range?.length > 1 ? [range[0].toISOString(), range[1].toISOString()] : [null, null] const [begin, end] = range?.length > 1 ? [range[0].toISOString(), range[1].toISOString()] : [null, null]
let paginatedMessages = await MessageService.getMessages(idWell, const skip = (page - 1) * pageSize
(page - 1) * pageSize, const paginatedMessages = await MessageService.getMessages(idWell, skip, pageSize, categories, begin, end, searchString)
pageSize, if (!paginatedMessages) return
categories,
begin,
end,
searchString)
if (paginatedMessages === null){
notify(`Данных по скважине "${idWell}" нет`, 'warning')
setShowLoader(false)
return
}
setMessages(paginatedMessages.items.map(m => ({ setMessages(paginatedMessages.items.map(m => ({
key: m.id, key: m.id,
@ -108,15 +96,10 @@ export default function Messages({idWell}) {
total: paginatedMessages.count, total: paginatedMessages.count,
current: Math.floor(paginatedMessages.skip / pageSize), current: Math.floor(paginatedMessages.skip / pageSize),
}) })
},
} catch (ex) { setShowLoader,
console.log(ex) `Не удалось загрузить сообщения по скважине "${idWell}"`
notify(`Не удалось загрузить сообщения по скважине "${idWell}"`, 'error') ), [idWell, page, categories, range, searchString])
}
setShowLoader(false)
}
GetMessages()
}, [idWell, page, categories, range, searchString])
return ( return (
<> <>
@ -131,10 +114,7 @@ export default function Messages({idWell}) {
onChange={setCategories}> onChange={setCategories}>
{children} {children}
</Select> </Select>
<RangePicker <RangePicker showTime onChange={(range) => setRange(range)} />
showTime
onChange={onChangeRange}
/>
<Search <Search
className={'filter-selector'} className={'filter-selector'}
placeholder={'Фильтр сообщений по тексту'} placeholder={'Фильтр сообщений по тексту'}
@ -159,4 +139,6 @@ export default function Messages({idWell}) {
</LoaderPortal> </LoaderPortal>
</> </>
) )
} })
export default Messages

View File

@ -1,15 +1,16 @@
import { memo, useState } from 'react' import { memo, useState } from 'react'
import { Link, useHistory } from 'react-router-dom' import { Link, useHistory } from 'react-router-dom'
import { Card, Form, Input, Select, Button } from 'antd' import { Card, Form, Input, Button } from 'antd'
import { import {
UserOutlined, UserOutlined,
LockOutlined, LockOutlined,
EyeInvisibleOutlined, EyeInvisibleOutlined,
EyeTwoTone EyeTwoTone
} from '@ant-design/icons' } from '@ant-design/icons'
import { AuthService } from '../services/api/'
import LoaderPortal from '../components/LoaderPortal' import { AuthService } from '@api'
import { invokeWebApiWrapperAsync } from '../components/factory' import LoaderPortal from '@components/LoaderPortal'
import { invokeWebApiWrapperAsync } from '@components/factory'
import { import {
createLoginRules, createLoginRules,
createPasswordRules, createPasswordRules,
@ -18,15 +19,9 @@ import {
nameRules, nameRules,
passwordRules, passwordRules,
phoneRules phoneRules
} from '../utils/validationRules' } from '@utils/validationRules'
import logo from '../images/logo_32.png'
const companies = [ import logo from '@images/logo_32.png'
{ label: 'ООО «Газпромнефть-Хантос» ', value: 1 },
{ label: 'АО «НафтаГаз»', value: 2 },
{ label: 'ООО «Нафтагаз Бурение»', value: 3 },
{ label: 'ООО «Газпромнефть-ННГ»', value: 4 }
]
const surnameRules = [...nameRules, { required: true, message: 'Пожалуйста, введите фамилию!' }] const surnameRules = [...nameRules, { required: true, message: 'Пожалуйста, введите фамилию!' }]
const regEmailRules = [{ required: true, message: 'Пожалуйста, введите email!' }, ...emailRules] const regEmailRules = [{ required: true, message: 'Пожалуйста, введите email!' }, ...emailRules]
@ -80,9 +75,6 @@ export const Register = memo(() => {
{createInput('patronymic', 'Отчество', nameRules)} {createInput('patronymic', 'Отчество', nameRules)}
{createInput('email', 'Email', regEmailRules)} {createInput('email', 'Email', regEmailRules)}
{createInput('phone', 'Номер телефона', phoneRules)} {createInput('phone', 'Номер телефона', phoneRules)}
<Form.Item name={'idCompany'} initialValue={companies[0].value}>
<Select placeholder={'Выберите компанию'} className={'m-0'} options={companies} />
</Form.Item>
{createInput('position', 'Должность')} {createInput('position', 'Должность')}
<Form.Item> <Form.Item>
<div className={'register-button'}> <div className={'register-button'}>

View File

@ -1,5 +1,6 @@
import { Progress, Button } from 'antd' import { Progress, Button } from 'antd'
import { downloadFile } from '../../components/factory'
import { downloadFile } from '@components/factory'
export const ReportCreationNotify = ({ progressData }) => ( export const ReportCreationNotify = ({ progressData }) => (
<> <>

View File

@ -2,11 +2,11 @@ import { Button, Tooltip } from 'antd'
import { useState, useEffect } from 'react' import { useState, useEffect } from 'react'
import { FilePdfOutlined, FileTextOutlined } from '@ant-design/icons' import { FilePdfOutlined, FileTextOutlined } from '@ant-design/icons'
import { ReportService } from '../../services/api' import { ReportService } from '@api'
import { formatDate, periodToString } from '../../utils' import { formatDate, periodToString } from '@utils'
import LoaderPortal from '../../components/LoaderPortal' import LoaderPortal from '@components/LoaderPortal'
import { Table, makeDateSorter, makeNumericSorter } from '../../components/Table' import { Table, makeDateSorter, makeNumericSorter } from '@components/Table'
import { invokeWebApiWrapperAsync, downloadFile } from '../../components/factory' import { invokeWebApiWrapperAsync, downloadFile } from '@components/factory'
const imgPaths = { const imgPaths = {
'.pdf': <FilePdfOutlined/>, '.pdf': <FilePdfOutlined/>,
@ -81,3 +81,5 @@ export const Reports = ({ idWell }) => {
</LoaderPortal> </LoaderPortal>
) )
} }
export default Reports

View File

@ -1,10 +1,11 @@
import { ChartTelemetryDepthToDay } from '../../components/charts/ChartTelemetryDepthToDay' import { useState, useEffect, memo } from 'react'
import { useState, useEffect } from 'react'
import { invokeWebApiWrapperAsync } from '../../components/factory'
import { TelemetryAnalyticsService } from "../../services/api"
import LoaderPortal from '../../components/LoaderPortal'
export default function TelemetryAnalysisDepthToDay({idWell}) { 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 }) => {
const [depthData, setDepthData] = useState([]) const [depthData, setDepthData] = useState([])
const [bitPositionData, setBitPositionData] = useState([]) const [bitPositionData, setBitPositionData] = useState([])
const [loader, setLoader] = useState(false) const [loader, setLoader] = useState(false)
@ -37,4 +38,6 @@ export default function TelemetryAnalysisDepthToDay({idWell}) {
</div> </div>
</LoaderPortal> </LoaderPortal>
) )
} })
export default TelemetryAnalysisDepthToDay

View File

@ -1,11 +1,11 @@
import { useState, useEffect } from 'react'
import { TelemetryAnalyticsService } from '../../services/api'
import { invokeWebApiWrapperAsync } from '../../components/factory'
import { ChartTelemetryDepthToInterval } from '../../components/charts/ChartTelemetryDepthToInterval'
import { Select } from 'antd' import { Select } from 'antd'
import LoaderPortal from '../../components/LoaderPortal' import { useState, useEffect, memo } from 'react'
const { Option } = Select import { arrayOrDefault } from '@utils'
import { TelemetryAnalyticsService } from '@api'
import LoaderPortal from '@components/LoaderPortal'
import { invokeWebApiWrapperAsync } from '@components/factory'
import { ChartTelemetryDepthToInterval } from '@components/charts/ChartTelemetryDepthToInterval'
const timePeriodCollection = [ const timePeriodCollection = [
{ value: '3600', label: '1 час' }, { value: '3600', label: '1 час' },
@ -14,41 +14,35 @@ const timePeriodCollection = [
{ value: '86400', label: '24 часа' } { value: '86400', label: '24 часа' }
] ]
export default function TelemetryAnalysisDepthToInterval({idWell}) { export const TelemetryAnalysisDepthToInterval = memo(({ idWell }) => {
const [depthToIntervalData, setDepthToIntervalData] = useState([]) const [depthToIntervalData, setDepthToIntervalData] = useState([])
const [loader, setLoader] = useState(false)
const [chartInterval, setChartInterval] = useState(86400) const [chartInterval, setChartInterval] = useState(86400)
const [loader, setLoader] = useState(false)
const children = timePeriodCollection.map((line) => useEffect(() => invokeWebApiWrapperAsync(
<Option key={line.value}>{line.label}</Option>)
useEffect(() => {
setLoader(true)
invokeWebApiWrapperAsync(
async () => { async () => {
const depthToIntervalData = await const depthToIntervalData = await TelemetryAnalyticsService.getWellDepthToInterval(idWell, chartInterval)
TelemetryAnalyticsService.getWellDepthToInterval(idWell, chartInterval) ?? [] setDepthToIntervalData(arrayOrDefault(depthToIntervalData))
setDepthToIntervalData(depthToIntervalData)
}, },
setLoader, setLoader,
`Не удалось получить данные для анализа скорость проходки-интервал "${idWell}"`) `Не удалось получить данные для анализа скорость проходки-интервал "${idWell}"`
}, [idWell, chartInterval]) ), [idWell, chartInterval])
return ( return (
<LoaderPortal show={loader}> <LoaderPortal show={loader}>
<div className='mt-20px'> <div className={'mt-20px'}>
<Select <Select
defaultValue="86400" options={timePeriodCollection}
onChange={setChartInterval} onChange={setChartInterval}
className='ml-30px' defaultValue={'86400'}
> className={'ml-30px'}
{children} />
</Select>
<ChartTelemetryDepthToInterval <ChartTelemetryDepthToInterval
depthToIntervalData={depthToIntervalData} depthToIntervalData={depthToIntervalData}
/> />
</div> </div>
</LoaderPortal> </LoaderPortal>
) )
} })
export default TelemetryAnalysisDepthToInterval

View File

@ -1,30 +1,32 @@
import { ChartTelemetryOperationsSummary } from '../../components/charts/ChartTelemetryOperationsSummary' import moment from 'moment'
import { useState, useEffect } from 'react' import { Form, DatePicker } from 'antd'
import moment from "moment" import { useState, useEffect, memo } from 'react'
import { invokeWebApiWrapperAsync } from '../../components/factory'
import { TelemetryAnalyticsService } from '../../services/api' import { TelemetryAnalyticsService } from '@api'
import { Form, DatePicker } from "antd" import LoaderPortal from '@components/LoaderPortal'
import LoaderPortal from '../../components/LoaderPortal' import { invokeWebApiWrapperAsync } from '@components/factory'
import { ChartTelemetryOperationsSummary } from '@components/charts/ChartTelemetryOperationsSummary'
const { RangePicker } = DatePicker const { RangePicker } = DatePicker
export default function TelemetryAnalysisOperationsSummary({idWell}){ export const TelemetryAnalysisOperationsSummary = memo(({ idWell }) => {
const [avilableDatesRange, setAviableDatesRange] = useState([moment(),moment()]) const [avilableDatesRange, setAviableDatesRange] = useState([moment(),moment()])
const [filterDateRange, setFilterDateRange] = useState([moment().subtract(1, "days"),moment()]) const [filterDateRange, setFilterDateRange] = useState([moment().subtract(1, 'days'),moment()])
const [operationsData, setOperationsData] = useState([]) const [operationsData, setOperationsData] = useState([])
const [loader, setLoader] = useState(false) const [loader, setLoader] = useState(false)
const disabledDate = (current) => const disabledDate = (current) => current < avilableDatesRange[0] || current > avilableDatesRange[1]
current < avilableDatesRange[0] || current > avilableDatesRange[1]
useEffect(() => invokeWebApiWrapperAsync(async() => { useEffect(() => invokeWebApiWrapperAsync(
async() => {
const datesRange = await TelemetryAnalyticsService.getOperationsDateRange(idWell) const datesRange = await TelemetryAnalyticsService.getOperationsDateRange(idWell)
setAviableDatesRange(datesRange) setAviableDatesRange(datesRange)
}), [idWell]) },
setLoader,
`Не удалось загрузить диапозон дат для скважины "${idWell}"`
), [idWell])
useEffect(() => { useEffect(() => invokeWebApiWrapperAsync(
setLoader(true)
invokeWebApiWrapperAsync(
async () => { async () => {
const operationsSummaryData = await TelemetryAnalyticsService.getOperationsSummary(idWell, const operationsSummaryData = await TelemetryAnalyticsService.getOperationsSummary(idWell,
filterDateRange[0].toISOString(), filterDateRange[1].toISOString()) filterDateRange[0].toISOString(), filterDateRange[1].toISOString())
@ -32,39 +34,33 @@ export default function TelemetryAnalysisOperationsSummary({idWell}){
setOperationsData(operationsSummaryData) setOperationsData(operationsSummaryData)
}, },
setLoader, setLoader,
`Не удалось получить данные для анализа операций по скважине "${idWell}"`) `Не удалось получить данные для анализа операций по скважине "${idWell}"`
}, [idWell, filterDateRange]) ), [idWell, filterDateRange])
return ( return (
<LoaderPortal show={loader}> <LoaderPortal show={loader}>
<div className="w-100 mt-20px"> <div className={'w-100 mt-20px'}>
<Form <Form layout={'vertical'} name={'operationsForm'} initialValues={{ remember: true }}>
layout="vertical" <div className={'d-flex'}>
name="operationsForm"
initialValues={{ remember: true }}
>
<div className={"d-flex"}>
<Form.Item <Form.Item
label="Диапазон дат графика:" name={'period'}
name="period" className={'ml-30px'}
initialValue={filterDateRange} initialValue={filterDateRange}
className='ml-30px' label={'Диапазон дат графика:'}
> >
<RangePicker <RangePicker
disabledDate={disabledDate}
allowClear={false}
onCalendarChange={(dates) => {
setFilterDateRange(dates)
}}
showTime showTime
allowClear={false}
disabledDate={disabledDate}
onCalendarChange={(dates) => setFilterDateRange(dates)}
/> />
</Form.Item> </Form.Item>
</div> </div>
</Form> </Form>
</div> </div>
<ChartTelemetryOperationsSummary <ChartTelemetryOperationsSummary operationsData={operationsData}/>
operationsData={operationsData}
/>
</LoaderPortal> </LoaderPortal>
) )
} })
export default TelemetryAnalysisOperationsSummary

View File

@ -1,23 +1,23 @@
import {useState, useEffect} from 'react' import { Table } from 'antd'
import {Table} from 'antd' import { useState, useEffect } from 'react'
import LoaderPortal from '../../components/LoaderPortal' import LoaderPortal from '@components/LoaderPortal'
import {invokeWebApiWrapperAsync} from '../../components/factory' import { invokeWebApiWrapperAsync } from '@components/factory'
import {columns} from '../Messages' import { Subscribe } from '@services/signalr'
import { MessageService } from '@api'
import {Subscribe} from '../../services/signalr' import { columns } from '@pages/Messages'
import {MessageService} from '../../services/api'
import '../../styles/message.css'
export default function ActiveMessagesOnline({idWell}) { import '@styles/message.css'
export const ActiveMessagesOnline = ({ idWell }) => {
const [messages, setMessages] = useState([]) const [messages, setMessages] = useState([])
const [loader, setLoader] = useState(false) const [loader, setLoader] = useState(false)
const handleReceiveMessages = (messages) => { const handleReceiveMessages = (messages) => {
if (messages) { if (messages)
setMessages(messages.items.splice(0, 4)) setMessages(messages.items.splice(0, 4))
} }
}
useEffect(() => { useEffect(() => {
invokeWebApiWrapperAsync( invokeWebApiWrapperAsync(
@ -31,7 +31,8 @@ export default function ActiveMessagesOnline({idWell}) {
return Subscribe('hubs/telemetry','ReceiveMessages', `well_${idWell}`, handleReceiveMessages) return Subscribe('hubs/telemetry','ReceiveMessages', `well_${idWell}`, handleReceiveMessages)
}, [idWell]) }, [idWell])
return (<LoaderPortal show={loader}> return (
<LoaderPortal show={loader}>
<Table <Table
showHeader={false} showHeader={false}
columns={columns} columns={columns}
@ -42,5 +43,8 @@ export default function ActiveMessagesOnline({idWell}) {
pagination={false} pagination={false}
rowKey={(record) => record.id} rowKey={(record) => record.id}
/> />
</LoaderPortal>) </LoaderPortal>
)
} }
export default ActiveMessagesOnline

View File

@ -1,6 +1,7 @@
import {ValueDisplay} from '../../components/Display' import { Popover } from 'antd'
import {ControlOutlined} from '@ant-design/icons' import { ControlOutlined } from '@ant-design/icons'
import {Popover} from 'antd'
import { ValueDisplay } from '@components/Display'
export const ChartTimeOnlineFooter = ({ data, lineGroup }) => { export const ChartTimeOnlineFooter = ({ data, lineGroup }) => {
const getFooterData = (name) => { const getFooterData = (name) => {
@ -8,7 +9,7 @@ export const ChartTimeOnlineFooter = ({ data, lineGroup }) => {
return (<ValueDisplay value={data?.[dataIdx]}/>) return (<ValueDisplay value={data?.[dataIdx]}/>)
} }
let spValues = getFooterData('SP') const spValues = getFooterData('SP')
const idleValues = getFooterData('IDLE') const idleValues = getFooterData('IDLE')
const popContent = lineGroup?.filter(line => line.footer === true).map(line => ( const popContent = lineGroup?.filter(line => line.footer === true).map(line => (

View File

@ -1,36 +1,42 @@
import {Display} from '../../components/Display' import { memo } from 'react'
import { Display } from '@components/Display'
import RigMnemo from './RigMnemo' import RigMnemo from './RigMnemo'
const params = [ const params = [
{label:'Рот., об/мин', accessorName:'rotorSpeed', isArrowVisible:true}, { label: 'Рот., об/мин', accessorName: 'rotorSpeed', isArrowVisible: true },
{label:'Долото, м', accessorName:'bitDepth', isArrowVisible:true, format:2}, { label: 'Долото, м', accessorName: 'bitDepth', isArrowVisible: true, format: 2 },
{label:'Забой, м', accessorName:'wellDepth', isArrowVisible:true, format:2}, { label: 'Забой, м', accessorName: 'wellDepth', isArrowVisible: true, format: 2 },
{label:'Расход, м³/ч', accessorName:'flow', isArrowVisible:true}, { label: 'Расход, м³/ч', accessorName: 'flow', isArrowVisible: true },
{label:'Расход х.х., м³/ч', accessorName:'flowIdle', isArrowVisible:true}, { label: 'Расход х.х., м³/ч', accessorName: 'flowIdle', isArrowVisible: true },
{label: 'Время', accessorName: 'date', format:'HH:mm:ss'}, { label: 'Время', accessorName: 'date', format: 'HH:mm:ss' },
] ]
export const CustomColumn = ({data}) => { export const CustomColumn = memo(({ data }) => {
const dataLast = data[data.length -1] const dataLast = data[data.length - 1]
params.forEach(param => param.value = dataLast?.[param.accessorName] ?? '-')
if(dataLast) return (
params.forEach(param => param.value = dataLast[param.accessorName]) <>
else {params.map(param => (
params.forEach(param => param.value = '-' ) <Display
className={'border_small display_flex_container'}
return (<>
{params.map(param => <Display className='border_small display_flex_container'
key={param.label} key={param.label}
label={param.label} label={param.label}
value={param.value} value={param.value}
suffix={param.units} suffix={param.units}
isArrowVisible = {param.isArrowVisible}
format = {param.format} format = {param.format}
/>)} isArrowVisible = {param.isArrowVisible}
<RigMnemo
blockPosition={dataLast?.blockPosition??Number.NaN}
bitPosition={dataLast?.bitDepth??Number.NaN}
wellDepth={dataLast?.wellDepth??Number.NaN}
/> />
</>) ))}
} <RigMnemo
wellDepth={dataLast?.wellDepth ?? Number.NaN}
bitPosition={dataLast?.bitDepth ?? Number.NaN}
blockPosition={dataLast?.blockPosition ?? Number.NaN}
/>
</>
)
})
export default CustomColumn

View File

@ -1,22 +1,24 @@
import { Display } from '../../components/Display' import { memo } from 'react'
import { Display } from '@components/Display'
const modeNames = { const modeNames = {
0: "Ручной", 0: 'Ручной',
1: "Бурение в роторе", 1: 'Бурение в роторе',
2: "Проработка", 2: 'Проработка',
3: "Бурение в слайде", 3: 'Бурение в слайде',
4: "Спуск СПО", 4: 'Спуск СПО',
5: "Подъем СПО", 5: 'Подъем СПО',
6: "Подъем с проработкой", 6: 'Подъем с проработкой',
10: "БЛОКИРОВКА", 10: 'БЛОКИРОВКА',
} }
export const ModeDisplay = ({data})=>{ export const ModeDisplay = memo(({ data }) => (
const dataLast = data[data.length - 1] <Display
className={'border_small display_flex_container user_card'}
return <Display className='border_small display_flex_container user_card' label={'Режим:'}
label='Режим:' value={data?.[data?.length - 1]?.mode}
value={dataLast?.mode} enumeration={modeNames}
enumeration={modeNames}/> />
} ))

View File

@ -1,8 +1,10 @@
import { Grid, GridItem } from '../../components/Grid'
import { Column, GetOrCreateDatasetByLineConfig } from '../../components/charts/Column'
import { ChartTimeOnlineFooter } from './ChartTimeOnlineFooter'
import { useEffect, useState } from 'react' import { useEffect, useState } from 'react'
import { makeDateSorter } from '../../components/Table'
import { Grid, GridItem } from '@components/Grid'
import { makeDateSorter } from '@components/Table'
import { Column, GetOrCreateDatasetByLineConfig } from '@components/charts/Column'
import { ChartTimeOnlineFooter } from './ChartTimeOnlineFooter'
const GetLimitShape = (flowChartData, points, accessor) => { const GetLimitShape = (flowChartData, points, accessor) => {
const min = [], max = [] const min = [], max = []
@ -118,3 +120,5 @@ export const MonitoringColumn = ({ lineGroup, data, flowChartData, interval, sho
</div> </div>
) )
} }
export default MonitoringColumn

View File

@ -1,11 +1,12 @@
import { useState } from 'react' import { useState } from 'react'
import { Select, Modal, Input, InputNumber } from 'antd' import { Select, Modal, Input, InputNumber } from 'antd'
import { SetpointsService } from '../../services/api'
import LoaderPortal from '../../components/LoaderPortal' import { SetpointsService } from '@api'
import { invokeWebApiWrapperAsync } from '../../components/factory' import LoaderPortal from '@components/LoaderPortal'
import { makeNumericRender, EditableTable } from '../../components/Table' import { invokeWebApiWrapperAsync } from '@components/factory'
import { PeriodPicker, defaultPeriod } from '../../components/PeriodPicker' import { makeNumericRender, EditableTable } from '@components/Table'
import { Grid, GridItem } from '../../components/Grid' import { PeriodPicker, defaultPeriod } from '@components/PeriodPicker'
import { Grid, GridItem } from '@components/Grid'
export const SetpointSender = ({ idWell, onClose, visible, setpointNames }) => { export const SetpointSender = ({ idWell, onClose, visible, setpointNames }) => {
const [expirePeriod, setExpirePeriod] = useState(defaultPeriod) const [expirePeriod, setExpirePeriod] = useState(defaultPeriod)

View File

@ -1,10 +1,10 @@
import { memo } from 'react' import { memo } from 'react'
import { Modal, Input } from 'antd' import { Modal, Input } from 'antd'
import { Table } from '../../components/Table' import { Table } from '@components/Table'
import { UserView } from '../../components/views' import { UserView } from '@components/views'
import { Grid, GridItem } from '../../components/Grid' import { Grid, GridItem } from '@components/Grid'
import { formatDate, periodToString } from '../../utils' import { formatDate, periodToString } from '@utils'
export const setpointStatus = { export const setpointStatus = {
0: 'Неизвестно', 0: 'Неизвестно',

View File

@ -1,9 +1,11 @@
import { Display } from '../../components/Display' import { Display } from '@components/Display'
export const UserOfWell = ({ data }) => { export const UserOfWell = ({ data }) => (
const dataLast = data[data.length - 1] <Display
className={'border_small display_flex_container user_card'}
label={'Пользователь'}
value={data[data.length - 1]?.user}
/>
)
return <Display className='border_small display_flex_container user_card' export default UserOfWell
label='Пользователь'
value={dataLast?.user}/>
}

View File

@ -13,9 +13,9 @@ import 'chartjs-adapter-moment'
import zoomPlugin from 'chartjs-plugin-zoom' import zoomPlugin from 'chartjs-plugin-zoom'
import ChartDataLabels from 'chartjs-plugin-datalabels' import ChartDataLabels from 'chartjs-plugin-datalabels'
import { invokeWebApiWrapperAsync } from '../../components/factory' import { invokeWebApiWrapperAsync } from '@components/factory'
import { getOperations } from '../Cluster/functions' import { getOperations } from '@pages/Cluster/functions'
import LoaderPortal from '../../components/LoaderPortal' import LoaderPortal from '@components/LoaderPortal'
Chart.register(TimeScale, LinearScale, LineController, LineElement, PointElement, Legend, ChartDataLabels, zoomPlugin) Chart.register(TimeScale, LinearScale, LineController, LineElement, PointElement, Legend, ChartDataLabels, zoomPlugin)

View File

@ -1,4 +1,4 @@
import { OpenAPI, UserTokenDto } from '../services/api' import { OpenAPI, UserTokenDto } from '@api'
import { Role, Permission } from './permissions' import { Role, Permission } from './permissions'
export enum StorageNames { export enum StorageNames {

View File

@ -18,7 +18,11 @@
"resolveJsonModule": true, "resolveJsonModule": true,
"isolatedModules": true, "isolatedModules": true,
"noEmit": true, "noEmit": true,
"jsx": "react-jsx" "jsx": "react-jsx",
"baseUrl": "src"
}, },
"include": ["src"] "include": [
"src"
],
"extends": "./tsconfig.paths.json"
} }

19
tsconfig.paths.json Normal file
View File

@ -0,0 +1,19 @@
{
"compilerOptions": {
"baseUrl": "./src",
"paths": {
"@asb/*": ["./*"],
"@api": ["./services/api"],
"@api/*": ["./services/api/*"],
"@components": ["./components"],
"@components/*": ["./components/*"],
"@services": ["./services"],
"@services/*": ["./services/*"],
"@images/*": ["./images/*"],
"@pages/*": ["./pages/*"],
"@utils": ["./utils"],
"@utils/*": ["./utils/*"],
"@styles/*": ["./styles/*"]
}
}
}