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

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 = {
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": {
"@types/react": "^17.0.3",
"@types/react-router-dom": "^5.3.2",
"craco-alias": "^3.0.1",
"openapi-typescript": "^3.4.1",
"openapi-typescript-codegen": "^0.9.3"
}
@ -6035,6 +6036,12 @@
"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": {
"version": "1.17.1",
"resolved": "https://registry.npmjs.org/craco-less/-/craco-less-1.17.1.tgz",
@ -27532,6 +27539,12 @@
"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": {
"version": "1.17.1",
"resolved": "https://registry.npmjs.org/craco-less/-/craco-less-1.17.1.tgz",
@ -39581,6 +39594,7 @@
},
"ssri": {
"version": "6.0.1",
"integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==",
"requires": {
"figgy-pudding": "^3.5.1"
}

View File

@ -27,8 +27,8 @@
"start": "craco start",
"build": "craco build",
"test": "craco test",
"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": "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",
"react_start": "react-scripts start",
"react_build": "react-scripts build",
"react_test": "react-scripts test",
@ -55,6 +55,8 @@
},
"devDependencies": {
"@types/react": "^17.0.3",
"@types/react-router-dom": "^5.3.2",
"craco-alias": "^3.0.1",
"openapi-typescript": "^3.4.1",
"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 { headerHeight } from '../utils'
import { UserMenu } from './UserMenu'
import logo from '../images/logo_32.png'
import { Link } from 'react-router-dom'
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
isAdmin?: boolean
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.Header className={'header'} {...other}>
<Link to={'/'} style={{ height: headerHeight }}>
@ -22,6 +24,6 @@ export const PageHeader: React.FC<PageHeaderProps> = ({ title = 'Монитор
<UserMenu isAdmin={isAdmin} />
</Layout.Header>
</Layout>
)
))
export default PageHeader

View File

@ -3,16 +3,16 @@ import { DefaultValueType } from 'rc-tree-select/lib/interface'
import { useState, useEffect, ReactNode } from 'react'
import { useHistory, useRouteMatch } from 'react-router-dom'
import { isRawDate } from '../utils'
import { isRawDate } from '@utils'
import LoaderPortal from './LoaderPortal'
import { WellIcon, WellIconState } from './icons'
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 ClusterIcon } from '../images/ClusterIcon.svg'
import { ReactComponent as DepositIcon } from '@images/DepositIcon.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 checkIsWellOnline = (lastTelemetryDate: unknown): boolean =>

View File

@ -1,7 +1,8 @@
import { notification } from 'antd'
import { Dispatch, SetStateAction } from 'react'
import { FileInfoDto } from '../services/api'
import { getUserToken } from '../utils/storage'
import { Dispatch, ReactNode, SetStateAction } from 'react'
import { FileInfoDto } from '@api'
import { getUserToken } from '@utils/storage'
const notificationTypeDictionary = new Map([
['error' , { notifyInstance: notification.error , caption: 'Ошибка' }],
@ -15,7 +16,7 @@ const notificationTypeDictionary = new Map([
* @param body string или ReactNode
* @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
const instance = notificationTypeDictionary.get(notifyType) ??

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,6 +1,7 @@
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 }) => {
const [lineGroupWithoutShapes, setLineGroupWithoutShapes] = useState([])
@ -33,3 +34,5 @@ export const ArchiveColumn = ({ lineGroup, data, interval, style, headerHeight,
</div>
)
}
export default ArchiveColumn

View File

@ -1,7 +1,9 @@
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 { paramsGroups } from '../TelemetryView'
const interpolationSearch = (data, begin, end, accessor) => {
const fy = (i) => new Date(data[i]?.[accessor] ?? 0)
@ -64,3 +66,5 @@ export const ArchiveDisplay = ({data, startDate, interval, onWheel}) => {
</Grid>
)
}
export default ArchiveDisplay

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -3,18 +3,18 @@ import { UserOutlined, LockOutlined } from '@ant-design/icons'
import { useState } from 'react'
import { Link, useHistory } from 'react-router-dom'
import { AuthService } from '../services/api/'
import LoaderPortal from '../components/LoaderPortal'
import { invokeWebApiWrapperAsync } from '../components/factory'
import { loginRules, passwordRules } from '../utils/validationRules'
import { setUser } from '../utils/storage'
import { AuthService } from '@api'
import LoaderPortal from '@components/LoaderPortal'
import { invokeWebApiWrapperAsync } from '@components/factory'
import { loginRules, passwordRules } from '@utils/validationRules'
import { setUser } from '@utils/storage'
import '../styles/index.css'
import logo from '../images/logo_32.png'
import '@styles/index.css'
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 [showLoader, setShowLoader] = useState(false)
@ -52,3 +52,5 @@ export default function Login() {
</LoaderPortal>
)
}
export default Login

View File

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

View File

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

View File

@ -1,8 +1,8 @@
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) => (
<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'

View File

@ -2,9 +2,9 @@ import { Button } from 'antd'
import { useState, useEffect } from 'react'
import { TableOutlined } from '@ant-design/icons'
import { MeasureService } from '../../services/api'
import LoaderPortal from '../../components/LoaderPortal'
import { invokeWebApiWrapperAsync } from '../../components/factory'
import { MeasureService } from '@api'
import LoaderPortal from '@components/LoaderPortal'
import { invokeWebApiWrapperAsync } from '@components/factory'
import { MeasureTable } from './MeasureTable'
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'
export const columnsMudDiagram = [

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,22 +1,22 @@
import {useState, useEffect} from 'react'
import {Table} from 'antd'
import { Table } from 'antd'
import { useState, useEffect } from 'react'
import LoaderPortal from '../../components/LoaderPortal'
import {invokeWebApiWrapperAsync} from '../../components/factory'
import {columns} from '../Messages'
import LoaderPortal from '@components/LoaderPortal'
import { invokeWebApiWrapperAsync } from '@components/factory'
import { Subscribe } from '@services/signalr'
import { MessageService } from '@api'
import {Subscribe} from '../../services/signalr'
import {MessageService} from '../../services/api'
import '../../styles/message.css'
import { columns } from '@pages/Messages'
export default function ActiveMessagesOnline({idWell}) {
import '@styles/message.css'
export const ActiveMessagesOnline = ({ idWell }) => {
const [messages, setMessages] = useState([])
const [loader, setLoader] = useState(false)
const handleReceiveMessages = (messages) => {
if (messages) {
if (messages)
setMessages(messages.items.splice(0, 4))
}
}
useEffect(() => {
@ -31,16 +31,20 @@ export default function ActiveMessagesOnline({idWell}) {
return Subscribe('hubs/telemetry','ReceiveMessages', `well_${idWell}`, handleReceiveMessages)
}, [idWell])
return (<LoaderPortal show={loader}>
<Table
showHeader={false}
columns={columns}
dataSource={messages}
rowClassName={(record) => `event_message_${record.categoryId} event_message`}
className={'message_table'}
size={'small'}
pagination={false}
rowKey={(record) => record.id}
/>
</LoaderPortal>)
return (
<LoaderPortal show={loader}>
<Table
showHeader={false}
columns={columns}
dataSource={messages}
rowClassName={(record) => `event_message_${record.categoryId} event_message`}
className={'message_table'}
size={'small'}
pagination={false}
rowKey={(record) => record.id}
/>
</LoaderPortal>
)
}
export default ActiveMessagesOnline

View File

@ -1,6 +1,7 @@
import {ValueDisplay} from '../../components/Display'
import {ControlOutlined} from '@ant-design/icons'
import {Popover} from 'antd'
import { Popover } from 'antd'
import { ControlOutlined } from '@ant-design/icons'
import { ValueDisplay } from '@components/Display'
export const ChartTimeOnlineFooter = ({ data, lineGroup }) => {
const getFooterData = (name) => {
@ -8,7 +9,7 @@ export const ChartTimeOnlineFooter = ({ data, lineGroup }) => {
return (<ValueDisplay value={data?.[dataIdx]}/>)
}
let spValues = getFooterData('SP')
const spValues = getFooterData('SP')
const idleValues = getFooterData('IDLE')
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'
const params = [
{label:'Рот., об/мин', accessorName:'rotorSpeed', isArrowVisible:true},
{label:'Долото, м', accessorName:'bitDepth', isArrowVisible:true, format:2},
{label:'Забой, м', accessorName:'wellDepth', isArrowVisible:true, format:2},
{label:'Расход, м³/ч', accessorName:'flow', isArrowVisible:true},
{label:'Расход х.х., м³/ч', accessorName:'flowIdle', isArrowVisible:true},
{label: 'Время', accessorName: 'date', format:'HH:mm:ss'},
{ label: 'Рот., об/мин', accessorName: 'rotorSpeed', isArrowVisible: true },
{ label: 'Долото, м', accessorName: 'bitDepth', isArrowVisible: true, format: 2 },
{ label: 'Забой, м', accessorName: 'wellDepth', isArrowVisible: true, format: 2 },
{ label: 'Расход, м³/ч', accessorName: 'flow', isArrowVisible: true },
{ label: 'Расход х.х., м³/ч', accessorName: 'flowIdle', isArrowVisible: true },
{ label: 'Время', accessorName: 'date', format: 'HH:mm:ss' },
]
export const CustomColumn = ({data}) => {
const dataLast = data[data.length -1]
export const CustomColumn = memo(({ data }) => {
const dataLast = data[data.length - 1]
params.forEach(param => param.value = dataLast?.[param.accessorName] ?? '-')
if(dataLast)
params.forEach(param => param.value = dataLast[param.accessorName])
else
params.forEach(param => param.value = '-' )
return (<>
{params.map(param => <Display className='border_small display_flex_container'
key={param.label}
label={param.label}
value={param.value}
suffix={param.units}
isArrowVisible = {param.isArrowVisible}
format = {param.format}
/>)}
<RigMnemo
blockPosition={dataLast?.blockPosition??Number.NaN}
bitPosition={dataLast?.bitDepth??Number.NaN}
wellDepth={dataLast?.wellDepth??Number.NaN}
return (
<>
{params.map(param => (
<Display
className={'border_small display_flex_container'}
key={param.label}
label={param.label}
value={param.value}
suffix={param.units}
format = {param.format}
isArrowVisible = {param.isArrowVisible}
/>
</>)
}
))}
<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 = {
0: "Ручной",
1: "Бурение в роторе",
2: "Проработка",
3: "Бурение в слайде",
4: "Спуск СПО",
5: "Подъем СПО",
6: "Подъем с проработкой",
0: 'Ручной',
1: 'Бурение в роторе',
2: 'Проработка',
3: 'Бурение в слайде',
4: 'Спуск СПО',
5: 'Подъем СПО',
6: 'Подъем с проработкой',
10: "БЛОКИРОВКА",
10: 'БЛОКИРОВКА',
}
export const ModeDisplay = ({data})=>{
const dataLast = data[data.length - 1]
return <Display className='border_small display_flex_container user_card'
label='Режим:'
value={dataLast?.mode}
enumeration={modeNames}/>
}
export const ModeDisplay = memo(({ data }) => (
<Display
className={'border_small display_flex_container user_card'}
label={'Режим:'}
value={data?.[data?.length - 1]?.mode}
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 { 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 min = [], max = []
@ -118,3 +120,5 @@ export const MonitoringColumn = ({ lineGroup, data, flowChartData, interval, sho
</div>
)
}
export default MonitoringColumn

View File

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

View File

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

View File

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

View File

@ -13,9 +13,9 @@ import 'chartjs-adapter-moment'
import zoomPlugin from 'chartjs-plugin-zoom'
import ChartDataLabels from 'chartjs-plugin-datalabels'
import { invokeWebApiWrapperAsync } from '../../components/factory'
import { getOperations } from '../Cluster/functions'
import LoaderPortal from '../../components/LoaderPortal'
import { invokeWebApiWrapperAsync } from '@components/factory'
import { getOperations } from '@pages/Cluster/functions'
import LoaderPortal from '@components/LoaderPortal'
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'
export enum StorageNames {

View File

@ -18,7 +18,11 @@
"resolveJsonModule": true,
"isolatedModules": 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/*"]
}
}
}