Merge branch 'dev' into fix/file-download-page-fix

# Conflicts:
#	src/pages/FileDownload.jsx
This commit is contained in:
ts_salikhov 2022-10-31 11:30:03 +04:00
commit a4db41fdd4
57 changed files with 404 additions and 503 deletions

View File

@ -12,8 +12,7 @@
"react-dom": "^18.1.0",
"react-router-dom": "^6.3.0",
"rxjs": "^7.5.5",
"usehooks-ts": "^2.6.0",
"web-vitals": "^2.1.4"
"usehooks-ts": "^2.6.0"
},
"scripts": {
"test": "jest",

View File

@ -0,0 +1,165 @@
import { memo, ReactNode, useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { useLocation, useNavigate } from 'react-router-dom'
import { BaseSelectRef } from 'rc-select'
import { AutoComplete } from 'antd'
import { join } from 'path'
import { useWell } from '@asb/context'
import { makeItem, PrivateWellMenuItem } from './PrivateWellMenu'
import { hasPermission, isURLAvailable } from '@utils'
import { menuItems as adminMenuItems } from '@pages/AdminPanel/AdminNavigationMenu'
import { menuItems as wellMenuItems } from '@pages/Well/NavigationMenu'
import '@styles/fast_run_menu.less'
const transliterationTable = {
'q': 'й', 'w': 'ц', 'e': 'у', 'r': 'к', 't': 'е', 'y': 'н', 'u': 'г', 'i': 'ш', 'o': 'щ', 'p': 'з', '[': 'х', ']': 'ъ', '{': 'х', '}': 'ъ',
'a': 'ф', 's': 'ы', 'd': 'в', 'f': 'а', 'g': 'п', 'h': 'р', 'j': 'о', 'k': 'л', 'l': 'д', ';': 'ж', "'": 'э', ':': 'ж', '"': 'э',
'z': 'я', 'x': 'ч', 'c': 'с', 'v': 'м', 'b': 'и', 'n': 'т', 'm': 'ь', ',': 'б', '.': 'ю', '<': 'б', '>': 'ю',
}
type OptionType = {
value: string
label: ReactNode
}
const transliterateToRu = (text: string) => Object.entries(transliterationTable).reduce((out, [en, ru]) => out.replaceAll(en, ru), text.toLowerCase())
const transliterateToEn = (text: string) => Object.entries(transliterationTable).reduce((out, [en, ru]) => out.replaceAll(ru, en), text.toLowerCase())
const applyVars = (route: string, vars?: object): string => !vars ? route :
Object.entries(vars).reduce((out, [key, value]) => out.replaceAll(`{${key}}`, value), route)
const makeOptions = (items: PrivateWellMenuItem[], vars?: object): OptionType[] => {
const out: OptionType[] = []
items.forEach((item) => {
if (!hasPermission(item.permissions)) return
out.push({
label: item.title,
value: applyVars(item.route, vars),
})
if (item.children) {
const childrenOptions = makeOptions(item.children).map((child) => ({
label: `${item.title} > ${child.label}`,
value: applyVars(join(item.route, String(child.value)), vars),
}))
out.push(...childrenOptions)
}
})
return out
}
const makeFindInString = (text: string) => {
const searchText = text.toLowerCase()
const toRu = transliterateToRu(searchText)
const toEn = transliterateToEn(searchText)
return (sourceText: string) => {
const text = sourceText.toLowerCase()
let idx = text.indexOf(searchText)
if (idx < 0 && (idx = text.indexOf(toRu)) < 0 && (idx = text.indexOf(toEn)) < 0) return false
return { from: idx, to: idx + searchText.length }
}
}
export const FastRunMenu = memo(() => {
const [isOpen, setIsOpen] = useState(false)
const [value, setValue] = useState<string | null>()
const [results, setResults] = useState<OptionType[]>([])
const ref = useRef<BaseSelectRef | null>(null)
const [well] = useWell()
const navigate = useNavigate()
const location = useLocation()
const options = useMemo(() => {
const menus = [
makeItem('Месторождения', '/deposit', []),
]
if (isURLAvailable('/admin'))
menus.push(makeItem('Панель администратора', '/admin', [], undefined, adminMenuItems as PrivateWellMenuItem[]))
if (well.id)
menus.push(
makeItem(`Куст (${well.cluster})`, `/cluster/${well.idCluster}`, []),
makeItem(`Скважина (${well.caption})`, '/well/{idWell}', [], undefined, wellMenuItems),
)
return makeOptions(menus, { idWell: well.id })
}, [well])
const onClose = useCallback(() => {
setIsOpen(false)
setValue(null)
}, [])
const onTextChanged = useCallback((value: any) => {
navigate(value, { state: { from: location.pathname } })
onClose()
}, [onClose])
const onSearch = useCallback((text: string) => {
if (text.trim() === '') {
setResults(options)
return
}
const findInString = makeFindInString(text)
const results = options.map((option) => {
const label = String(option.label)
const idx = findInString(label.toLowerCase())
if (!idx) return findInString(option.value.toLowerCase()) ? option : false
return {
...option,
label: <>
{label.slice(0, idx.from)}
<span className={'fast-run-menu-text-found'}>
{label.slice(idx.from, idx.to)}
</span>
{label.slice(idx.to)}
</>
}
}).filter(Boolean) as OptionType[]
setResults(results)
}, [options])
useEffect(() => {
const listener = (event: KeyboardEvent) => {
if (event.altKey && event.code === 'KeyA')
setIsOpen((prev) => !prev)
}
document.addEventListener('keyup', listener)
return () => document.removeEventListener('keyup', listener)
}, [ref.current])
useEffect(() => {
if (!isOpen) return
ref.current?.focus()
ref.current?.scrollTo(0)
}, [isOpen])
useEffect(() => onSearch(''), [onSearch])
return isOpen ? (
<div className={'fast-run-menu'}>
<AutoComplete
ref={ref}
autoFocus
style={{ width: '100%' }}
options={results}
onBlur={onClose}
onChange={setValue}
onSearch={onSearch}
placeholder={'Введите название страницы...'}
onSelect={onTextChanged}
value={value}
/>
</div>
) : <></>
})
export default FastRunMenu

View File

@ -12,7 +12,7 @@ import {
import { LayoutPropsContext } from '@asb/context'
import { UserMenu, UserMenuProps } from '@components/UserMenu'
import { WellTreeSelector, WellTreeSelectorProps } from '@components/selectors/WellTreeSelector'
import { isURLAvailable, wrapPrivateComponent } from '@utils'
import { isURLAvailable, withPermissions } from '@utils'
import SuspenseFallback from './SuspenseFallback'
@ -114,7 +114,7 @@ const _LayoutPortal = memo(() => {
<a style={{ userSelect: 'none' }} onClick={() => setWellsTreeOpen((prev) => !prev)}>{currentWell}</a>
</Breadcrumb.Item>
)}
{breadcrumb}
{breadcrumb !== true && breadcrumb}
</Breadcrumb>
)}
{topRightBlock}
@ -131,6 +131,6 @@ const _LayoutPortal = memo(() => {
)
})
export const LayoutPortal = wrapPrivateComponent(_LayoutPortal, { requirements: ['Deposit.get'] })
export const LayoutPortal = withPermissions(_LayoutPortal, ['Deposit.get'])
export default LayoutPortal

View File

@ -1,10 +1,9 @@
import { Breadcrumb, BreadcrumbItemProps } from 'antd'
import { Link, useLocation } from 'react-router-dom'
import { memo, useMemo } from 'react'
import { Link } from 'react-router-dom'
import { join } from 'path'
import { PrivateWellMenuItem } from '@components/PrivateWellMenu'
import { FunctionalValue, useFunctionalValue } from '@utils'
import { FunctionalValue, getFunctionalValue, } from '@utils'
export const makeBreadcrumbItems = (items: PrivateWellMenuItem[], pathParts: string[], root: string = '/') => {
const out = []
@ -22,35 +21,26 @@ export const makeBreadcrumbItems = (items: PrivateWellMenuItem[], pathParts: str
return out
}
export type MenuBreadcrumbItemsProps = {
menuItems: PrivateWellMenuItem[]
pathRoot?: RegExp
itemsProps?: FunctionalValue<(item: PrivateWellMenuItem) => BreadcrumbItemProps>
itemRender?: (item: PrivateWellMenuItem) => JSX.Element
export const makeMenuBreadcrumbItems = (
menuItems: PrivateWellMenuItem[],
path: string,
pathRoot: RegExp = /^\//,
itemsProps?: FunctionalValue<(item: PrivateWellMenuItem) => BreadcrumbItemProps>,
itemRender?: (item: PrivateWellMenuItem) => JSX.Element,
) => {
const getItemProps = getFunctionalValue(itemsProps)
const rootPart = pathRoot.exec(path)
if (!rootPart || rootPart.length <= 0) return []
const root = rootPart[0]
const parts = path.trim().slice(root.length).split('/')
const items = makeBreadcrumbItems(menuItems, parts, root)
return items.map((item) => (
<Breadcrumb.Item key={item.route} {...getItemProps(item)}>
{itemRender ? itemRender(item) : (
<Link to={item.route}>{item.title}</Link>
)}
</Breadcrumb.Item>
))
}
export const MenuBreadcrumbItems = memo<MenuBreadcrumbItemsProps>(({ menuItems, pathRoot = /^\//, itemsProps, itemRender }) => {
const location = useLocation()
const getItemProps = useFunctionalValue(itemsProps)
const items = useMemo(() => {
const path = location.pathname
const rootPart = pathRoot.exec(path)
if (!rootPart || rootPart.length <= 0) return []
const root = rootPart[0]
const parts = path.trim().slice(root.length).split('/')
return makeBreadcrumbItems(menuItems, parts, root)
}, [location, menuItems, pathRoot])
return (
<>
{items.map((item) => (
<Breadcrumb.Item key={item.route} {...getItemProps(item)}>
{itemRender ? itemRender(item) : (
<Link to={item.route}>{item.title}</Link>
)}
</Breadcrumb.Item>
))}
</>
)
})

View File

@ -2,29 +2,14 @@ import { ReactNode } from 'react'
import { Rule } from 'antd/lib/form'
import { ColumnProps } from 'antd/lib/table'
export { makeDateColumn } from './date'
export { makeTimeColumn } from './time'
export {
RegExpIsFloat,
makeNumericRender,
makeNumericColumn,
makeNumericColumnOptions,
makeNumericColumnPlanFact,
makeNumericStartEnd,
makeNumericMinMax,
} from './numeric'
export { makeColumnsPlanFact } from './plan_fact'
export { makeSelectColumn } from './select'
export { makeTagColumn, makeTagInput } from './tag'
export { makeFilterTextMatch, makeTextColumn } from './text'
export {
timezoneOptions,
TimezoneSelect,
makeTimezoneColumn,
makeTimezoneRenderer
} from './timezone'
export type { TagInputProps } from './tag'
export * from './date'
export * from './time'
export * from './numeric'
export * from './plan_fact'
export * from './select'
export * from './tag'
export * from './text'
export * from './timezone'
export type DataType<T = any> = Record<string, T>
export type RenderMethod<T = any> = (value: T, dataset?: DataType<T>, index?: number) => ReactNode

View File

@ -1,58 +1,24 @@
export { makeDateSorter, makeNumericSorter, makeStringSorter, makeTimeSorter } from './sorters'
export { EditableTable, makeTableAction } from './EditableTable'
export { DatePickerWrapper } from './DatePickerWrapper'
export { TimePickerWrapper } from './TimePickerWrapper'
export { DateRangeWrapper } from './DateRangeWrapper'
export { Table } from './Table'
export {
RegExpIsFloat,
timezoneOptions,
TimezoneSelect,
makeDateColumn,
makeTimeColumn,
makeGroupColumn,
makeColumn,
makeColumnsPlanFact,
makeFilterTextMatch,
makeNumericRender,
makeNumericColumn,
makeNumericColumnOptions,
makeNumericColumnPlanFact,
makeNumericStartEnd,
makeNumericMinMax,
makeSelectColumn,
makeTagColumn,
makeTagInput,
makeTextColumn,
makeTimezoneColumn,
makeTimezoneRenderer,
} from './Columns'
export type {
DataType,
RenderMethod,
SorterMethod,
TagInputProps,
columnPropsOther,
} from './Columns'
export type { DateRangeWrapperProps } from './DateRangeWrapper'
export type { DatePickerWrapperProps } from './DatePickerWrapper'
export type { TimePickerWrapperProps } from './TimePickerWrapper'
export type { BaseTableColumn, TableColumns, TableContainer } from './Table'
export * from './sorters'
export * from './EditableTable'
export * from './DatePickerWrapper'
export * from './TimePickerWrapper'
export * from './DateRangeWrapper'
export * from './Table'
export * from './Columns'
export const defaultPagination = {
defaultPageSize: 14,
showSizeChanger: true,
}
type PaginationContainer = {
export type PaginationContainer<T> = {
skip?: number
take?: number
count?: number
items?: any[] | null
items?: T[] | null
}
export const makePaginationObject = (сontainer: PaginationContainer, ...other: any) => ({
export const makePaginationObject = <T, M extends object>(сontainer: PaginationContainer<T>, other: M) => ({
...other,
pageSize: сontainer.take,
total: сontainer.count ?? сontainer.items?.length ?? 0,

View File

@ -1,4 +1,2 @@
export * from './D3Chart'
export type { D3ChartProps } from './D3Chart'
export * from './types'

View File

@ -1,6 +1,3 @@
export type { PointerIconColors, PointerIconProps } from './PointerIcon'
export type { WellIconColors, WellIconProps, WellIconState } from './WellIcon'
export { PointerIcon } from './PointerIcon'
export { WellIcon } from './WellIcon'
export { Loader } from './Loader'
export * from './PointerIcon'
export * from './WellIcon'
export * from './Loader'

View File

@ -1,14 +1,7 @@
export type { PermissionViewProps } from './PermissionView'
export type { TelemetryViewProps } from './TelemetryView'
export type { CompanyViewProps } from './CompanyView'
export type { RoleViewProps } from './RoleView'
export type { UserViewProps } from './UserView'
export type { WirelineViewProps } from './WirelineView'
export { PermissionView } from './PermissionView'
export { TelemetryView, getTelemetryLabel } from './TelemetryView'
export { CompanyView } from './CompanyView'
export { RoleView } from './RoleView'
export { UserView } from './UserView'
export { WirelineView } from './WirelineView'
export * from './PermissionView'
export * from './TelemetryView'
export * from './CompanyView'
export * from './RoleView'
export * from './UserView'
export * from './WirelineView'
export * from './WellView'

View File

@ -1,5 +1,2 @@
export { WidgetSettingsWindow } from './WidgetSettingsWindow'
export { BaseWidget } from './BaseWidget'
export type { WidgetSettingsWindowProps } from './WidgetSettingsWindow'
export type { WidgetSettings, BaseWidgetProps } from './BaseWidget'
export * from './WidgetSettingsWindow'
export * from './BaseWidget'

View File

@ -1,7 +1,6 @@
import React from 'react'
import { createRoot } from 'react-dom/client'
import reportWebVitals from './reportWebVitals'
import App from './App'
import '@styles/index.css'
@ -14,8 +13,3 @@ root.render(
<App />
</React.StrictMode>
)
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals()

View File

@ -11,7 +11,7 @@ import {
} from '@components/Table'
import { invokeWebApiWrapperAsync } from '@components/factory'
import { AdminClusterService, AdminDepositService } from '@api'
import { arrayOrDefault, coordsFormat, wrapPrivateComponent } from '@utils'
import { arrayOrDefault, coordsFormat, withPermissions } from '@utils'
import { min1 } from '@utils/validationRules'
const ClusterController = memo(() => {
@ -112,8 +112,4 @@ const ClusterController = memo(() => {
)
})
export default wrapPrivateComponent(ClusterController, {
requirements: ['AdminDeposit.get', 'AdminCluster.get'],
title: 'Кусты',
route: 'cluster',
})
export default withPermissions(ClusterController, ['AdminDeposit.get', 'AdminCluster.get'])

View File

@ -10,7 +10,7 @@ import {
} from '@components/Table'
import { invokeWebApiWrapperAsync } from '@components/factory'
import { AdminCompanyService, AdminCompanyTypeService } from '@api'
import { arrayOrDefault, wrapPrivateComponent } from '@utils'
import { arrayOrDefault, withPermissions } from '@utils'
import { min1 } from '@utils/validationRules'
const CompanyController = memo(() => {
@ -103,8 +103,4 @@ const CompanyController = memo(() => {
)
})
export default wrapPrivateComponent(CompanyController, {
requirements: ['AdminCompany.get', 'AdminCompanyType.get'],
title: 'Компании',
route: 'company',
})
export default withPermissions(CompanyController, ['AdminCompany.get', 'AdminCompanyType.get'])

View File

@ -3,7 +3,7 @@ import { Input } from 'antd'
import { EditableTable, makeColumn, makeStringSorter, defaultPagination } from '@components/Table'
import { invokeWebApiWrapperAsync } from '@components/factory'
import { arrayOrDefault, wrapPrivateComponent } from '@utils'
import { arrayOrDefault, withPermissions } from '@utils'
import { min1 } from '@utils/validationRules'
import { AdminCompanyTypeService } from '@api'
@ -81,8 +81,4 @@ const CompanyTypeController = memo(() => {
)
})
export default wrapPrivateComponent(CompanyTypeController, {
requirements: ['AdminCompanyType.get'],
title: 'Типы компаний',
route: 'company_type',
})
export default withPermissions(CompanyTypeController, ['AdminCompanyType.get'])

View File

@ -3,7 +3,7 @@ import { Input } from 'antd'
import { invokeWebApiWrapperAsync } from '@components/factory'
import { EditableTable, makeColumn, defaultPagination, makeTimezoneColumn } from '@components/Table'
import { arrayOrDefault, coordsFormat, wrapPrivateComponent } from '@utils'
import { arrayOrDefault, coordsFormat, withPermissions } from '@utils'
import { min1 } from '@utils/validationRules'
import { AdminDepositService } from '@api'
@ -81,8 +81,4 @@ const DepositController = memo(() => {
)
})
export default wrapPrivateComponent(DepositController, {
requirements: ['AdminDeposit.get'],
title: 'Месторождения',
route: 'deposit',
})
export default withPermissions(DepositController, ['AdminDeposit.get'])

View File

@ -3,7 +3,7 @@ import { Input } from 'antd'
import { EditableTable, makeColumn, makeStringSorter } from '@components/Table'
import { invokeWebApiWrapperAsync } from '@components/factory'
import { arrayOrDefault, wrapPrivateComponent } from '@utils'
import { arrayOrDefault, withPermissions } from '@utils'
import { min1 } from '@utils/validationRules'
import { AdminPermissionService } from '@api'
@ -88,8 +88,4 @@ const PermissionController = memo(() => {
)
})
export default wrapPrivateComponent(PermissionController, {
requirements: ['AdminPermission.get'],
title: 'Разрешения',
route: 'permission',
})
export default withPermissions(PermissionController, ['AdminPermission.get'])

View File

@ -5,7 +5,7 @@ import { PermissionView, RoleView } from '@components/views'
import { invokeWebApiWrapperAsync } from '@components/factory'
import { EditableTable, makeTagColumn, makeTextColumn } from '@components/Table'
import { AdminPermissionService, AdminUserRoleService } from '@api'
import { arrayOrDefault, wrapPrivateComponent } from '@utils'
import { arrayOrDefault, withPermissions } from '@utils'
import { min1 } from '@utils/validationRules'
const RoleController = memo(() => {
@ -95,8 +95,4 @@ const RoleController = memo(() => {
)
})
export default wrapPrivateComponent(RoleController, {
requirements: ['AdminPermission.get', 'AdminUserRole.get'],
title: 'Роли',
route: 'role',
})
export default withPermissions(RoleController, ['AdminPermission.get', 'AdminUserRole.get'])

View File

@ -8,7 +8,7 @@ import LoaderPortal from '@components/LoaderPortal'
import { lables } from '@components/views/TelemetryView'
import { invokeWebApiWrapperAsync } from '@components/factory'
import TelemetrySelect from '@components/selectors/TelemetrySelect'
import { arrayOrDefault, wrapPrivateComponent } from '@utils'
import { arrayOrDefault, withPermissions } from '@utils'
import { AdminTelemetryService } from '@api'
const { Item } = Descriptions
@ -134,9 +134,4 @@ const TelemetryMerger = memo(() => {
)
})
export default wrapPrivateComponent(TelemetryMerger, {
requirements: [],
title: 'Объединение',
route: 'merger',
key: 'merger',
})
export default withPermissions(TelemetryMerger)

View File

@ -14,7 +14,7 @@ import {
} from '@components/Table'
import Poprompt from '@components/selectors/Poprompt'
import { invokeWebApiWrapperAsync } from '@components/factory'
import { arrayOrDefault, wrapPrivateComponent } from '@utils'
import { arrayOrDefault, withPermissions } from '@utils'
import { AdminTelemetryService } from '@api'
const TelemetryController = memo(() => {
@ -121,9 +121,4 @@ const TelemetryController = memo(() => {
)
})
export default wrapPrivateComponent(TelemetryController, {
requirements: [],
title: 'Просмотр',
route: 'viewer',
key: 'viewer',
})
export default withPermissions(TelemetryController)

View File

@ -2,7 +2,7 @@ import { memo, useMemo } from 'react'
import { Outlet } from 'react-router-dom'
import { RootPathContext, useRootPath } from '@asb/context'
import { wrapPrivateComponent } from '@utils'
import { withPermissions } from '@utils'
const Telemetry = memo(() => {
const root = useRootPath()
@ -15,9 +15,4 @@ const Telemetry = memo(() => {
)
})
export default wrapPrivateComponent(Telemetry, {
requirements: ['AdminTelemetry.get'],
title: 'Телеметрия',
key: 'telemetry',
route: 'telemetry/*',
})
export default withPermissions(Telemetry, ['AdminTelemetry.get'])

View File

@ -17,7 +17,7 @@ import { invokeWebApiWrapperAsync } from '@components/factory'
import { AdminCompanyService, AdminUserRoleService, AdminUserService } from '@api'
import { createLoginRules, nameRules, phoneRules, emailRules } from '@utils/validationRules'
import { makeTextOnFilter, makeTextFilters, makeArrayOnFilter } from '@utils/filters'
import { arrayOrDefault, wrapPrivateComponent } from '@utils'
import { arrayOrDefault, withPermissions } from '@utils'
import RoleTag from './RoleTag'
@ -227,8 +227,4 @@ const UserController = memo(() => {
)
})
export default wrapPrivateComponent(UserController, {
requirements: ['AdminUser.get', 'AdminCompany.get', 'AdminUserRole.get'],
title: 'Пользователи',
route: 'user',
})
export default withPermissions(UserController, ['AdminUser.get', 'AdminCompany.get', 'AdminUserRole.get'])

View File

@ -3,7 +3,7 @@ import { Input } from 'antd'
import { invokeWebApiWrapperAsync } from '@components/factory'
import { defaultPagination, makeColumn, makeDateSorter, makeStringSorter, Table } from '@components/Table'
import { arrayOrDefault, formatDate, wrapPrivateComponent } from '@utils'
import { arrayOrDefault, formatDate, withPermissions } from '@utils'
import { RequestTrackerService } from '@api'
const logRecordCount = 1000
@ -65,8 +65,4 @@ const VisitLog = memo(() => {
)
})
export default wrapPrivateComponent(VisitLog, {
requirements: ['RequestTracker.get'],
title: 'Журнал посещений',
route: 'visit_log',
})
export default withPermissions(VisitLog, ['RequestTracker.get'])

View File

@ -21,7 +21,7 @@ import {
import { invokeWebApiWrapperAsync } from '@components/factory'
import { TelemetryView, CompanyView } from '@components/views'
import TelemetrySelect from '@components/selectors/TelemetrySelect'
import { arrayOrDefault, coordsFormat, wrapPrivateComponent } from '@utils'
import { arrayOrDefault, coordsFormat, withPermissions } from '@utils'
const wellTypes = [
{ value: 1, label: 'Наклонно-направленная' },
@ -160,8 +160,4 @@ const WellController = memo(() => {
)
})
export default wrapPrivateComponent(WellController, {
requirements: ['AdminCluster.get', 'AdminCompany.get', 'AdminTelemetry.get', 'AdminWell.get'],
title: 'Скважины',
route: 'well',
})
export default withPermissions(WellController, ['AdminCluster.get', 'AdminCompany.get', 'AdminTelemetry.get', 'AdminWell.get'])

View File

@ -1,9 +1,10 @@
import { Navigate, Route, Routes } from 'react-router-dom'
import { lazy, memo, useMemo } from 'react'
import { Navigate, Route, Routes, useLocation } from 'react-router-dom'
import { lazy, memo, useEffect, useMemo } from 'react'
import { RootPathContext, useLayoutProps, useRootPath } from '@asb/context'
import { MenuBreadcrumbItems } from '@components/MenuBreadcrumb'
import { NoAccessComponent, wrapPrivateComponent } from '@utils'
import { FastRunMenu } from '@components/FastRunMenu'
import { makeMenuBreadcrumbItems } from '@components/MenuBreadcrumb'
import { NoAccessComponent, withPermissions } from '@utils'
import { AdminNavigationMenu, menuItems } from './AdminNavigationMenu'
@ -20,21 +21,25 @@ const TelemetryViewer = lazy(() => import('./Telemetry/TelemetryViewer'))
const TelemetryMerger = lazy(() => import('./Telemetry/TelemetryMerger'))
const VisitLog = lazy(() => import('./VisitLog'))
const layoutProps = {
sider: <AdminNavigationMenu />,
title: 'Администраторская панель',
isAdmin: true,
breadcrumb: <MenuBreadcrumbItems menuItems={menuItems} pathRoot={/^\/admin\//} />,
}
const AdminPanel = memo(() => {
const location = useLocation()
const root = useRootPath()
const rootPath = useMemo(() => `${root}/admin`, [root])
useLayoutProps(layoutProps)
const setLayoutProps = useLayoutProps()
useEffect(() => {
setLayoutProps({
sider: <AdminNavigationMenu />,
title: 'Администраторская панель',
isAdmin: true,
breadcrumb: makeMenuBreadcrumbItems(menuItems, location.pathname, /^\/admin\//),
})
}, [location.pathname])
return (
<RootPathContext.Provider value={rootPath}>
<FastRunMenu />
<Routes>
<Route index element={<Navigate to={'visit_log'} replace />} />
<Route path={'*'} element={<NoAccessComponent />} />
@ -58,4 +63,4 @@ const AdminPanel = memo(() => {
)
})
export default wrapPrivateComponent(AdminPanel, { requirements: ['RequestTracker.get'] })
export default withPermissions(AdminPanel, ['RequestTracker.get'])

View File

@ -22,7 +22,7 @@ import {
calcAndUpdateStatsBySections,
isRawDate,
makeFilterMinMaxFunction,
wrapPrivateComponent
withPermissions
} from '@utils'
const Tvd = lazy(() => import('@pages/Well/WellOperations/Tvd'))
@ -219,8 +219,4 @@ const ClusterWells = memo(({ statsWells }) => {
)
})
export default wrapPrivateComponent(ClusterWells, {
requirements: [],
title: 'Статистика по скважинам',
route: 'wells',
})
export default withPermissions(ClusterWells)

View File

@ -3,8 +3,9 @@ import { useParams } from 'react-router-dom'
import { useLayoutProps } from '@asb/context'
import LoaderPortal from '@components/LoaderPortal'
import { FastRunMenu } from '@components/FastRunMenu'
import { invokeWebApiWrapperAsync } from '@components/factory'
import { arrayOrDefault, wrapPrivateComponent } from '@utils'
import { arrayOrDefault, withPermissions } from '@utils'
import { OperationStatService } from '@api'
import ClusterWells from './ClusterWells'
@ -34,15 +35,13 @@ const Cluster = memo(() => {
}, [idCluster])
return (
<LoaderPortal show={showLoader}>
<ClusterWells statsWells={data} />
</LoaderPortal>
<>
<FastRunMenu />
<LoaderPortal show={showLoader}>
<ClusterWells statsWells={data} />
</LoaderPortal>
</>
)
})
export default wrapPrivateComponent(Cluster, {
requirements: ['OperationStat.get'],
title: 'Анализ скважин куста',
route: 'cluster/:idCluster/*',
key: 'cluster',
})
export default withPermissions(Cluster, ['OperationStat.get'])

View File

@ -1,13 +1,14 @@
import { Map, Overlay } from 'pigeon-maps'
import { useState, useEffect, memo, useMemo } from 'react'
import { Link, useLocation } from 'react-router-dom'
import { Map, Overlay } from 'pigeon-maps'
import { Popover, Badge } from 'antd'
import { useLayoutProps } from '@asb/context'
import { PointerIcon } from '@components/icons'
import LoaderPortal from '@components/LoaderPortal'
import { FastRunMenu } from '@components/FastRunMenu'
import { invokeWebApiWrapperAsync } from '@components/factory'
import { arrayOrDefault, limitValue, wrapPrivateComponent } from '@utils'
import { arrayOrDefault, limitValue, withPermissions } from '@utils'
import { DepositService } from '@api'
import '@styles/index.css'
@ -81,41 +82,39 @@ const Deposit = memo(() => {
}, [])
return (
<LoaderPortal show={showLoader}>
<div className={'h-100vh'} style={{ overflow: 'hidden' }}>
<Map {...viewParams}>
{depositsData.map(deposit => (
<Overlay
width={32}
anchor={[deposit.latitude, deposit.longitude]}
key={`${deposit.latitude} ${deposit.longitude}`}
>
<Popover content={
<div>
{deposit.clusters.map(cluster => (
<Link key={cluster.id} to={{ pathname: `/cluster/${cluster.id}`, state: { from: location.pathname }}}>
<div>{cluster.caption}</div>
</Link>
))}
</div>
} trigger={['click']} title={deposit.caption}>
<div style={{cursor: 'pointer'}}>
<Badge count={deposit.clusters.length}>
<PointerIcon state={'active'} width={48} height={59} />
</Badge>
</div>
</Popover>
</Overlay>
))}
</Map>
</div>
</LoaderPortal>
<>
<FastRunMenu />
<LoaderPortal show={showLoader}>
<div className={'h-100vh'} style={{ overflow: 'hidden' }}>
<Map {...viewParams}>
{depositsData.map(deposit => (
<Overlay
width={32}
anchor={[deposit.latitude, deposit.longitude]}
key={`${deposit.latitude} ${deposit.longitude}`}
>
<Popover content={
<div>
{deposit.clusters.map(cluster => (
<Link key={cluster.id} to={{ pathname: `/cluster/${cluster.id}`, state: { from: location.pathname }}}>
<div>{cluster.caption}</div>
</Link>
))}
</div>
} trigger={['click']} title={deposit.caption}>
<div style={{cursor: 'pointer'}}>
<Badge count={deposit.clusters.length}>
<PointerIcon state={'active'} width={48} height={59} />
</Badge>
</div>
</Popover>
</Overlay>
))}
</Map>
</div>
</LoaderPortal>
</>
)
})
export default wrapPrivateComponent(Deposit, {
requirements: ['Cluster.get'],
title: 'Месторождение',
route: 'deposit/*',
key: 'deposit',
})
export default withPermissions(Deposit, ['Cluster.get'])

View File

@ -4,7 +4,7 @@ import { InfoCircleFilled, CloseCircleOutlined } from '@ant-design/icons'
import { Button, Result, Typography } from 'antd'
import { downloadFile, invokeWebApiWrapperAsync } from '@components/factory'
import { wrapPrivateComponent } from '@utils'
import { withPermissions } from '@utils'
import { FileService } from '@api'
const { Paragraph, Text } = Typography
@ -92,7 +92,4 @@ const FileDownload = memo(function FileDownload() {
FileDownload.displayName = 'FileDownloadMemo'
export default wrapPrivateComponent(FileDownload, {
requirements: ['File.get'],
route: 'file_download/:idFile/*',
})
export default withPermissions(FileDownload, ['File.get'])

View File

@ -7,7 +7,7 @@ import { invokeWebApiWrapperAsync } from '@components/factory'
import { WellSelector } from '@components/selectors/WellSelector'
import { makeGroupColumn, makeNumericColumn, makeNumericRender, makeTextColumn, Table } from '@components/Table'
import { OperationStatService, WellOperationService } from '@api'
import { arrayOrDefault, wrapPrivateComponent } from '@utils'
import { arrayOrDefault, withPermissions } from '@utils'
import '@styles/index.css'
import '@styles/statistics.less'
@ -242,8 +242,4 @@ const Statistics = memo(() => {
)
})
export default wrapPrivateComponent(Statistics, {
requirements: [],
title: 'Оценка по ЦБ',
route: 'statistics',
})
export default withPermissions(Statistics)

View File

@ -10,7 +10,7 @@ import { makeTextColumn, makeNumericColumnPlanFact, makeNumericColumn } from '@c
import { WellCompositeService } from '@api'
import {
hasPermission,
wrapPrivateComponent,
withPermissions,
calcAndUpdateStatsBySections,
makeFilterMinMaxFunction,
getOperations
@ -267,8 +267,4 @@ const WellCompositeSections = memo(({ statsWells, selectedSections }) => {
)
})
export default wrapPrivateComponent(WellCompositeSections, {
requirements: ['WellComposite.get'],
title: 'Статистика по секциям',
route: 'sections',
})
export default withPermissions(WellCompositeSections, ['WellComposite.get'])

View File

@ -7,7 +7,7 @@ import LoaderPortal from '@components/LoaderPortal'
import SuspenseFallback from '@components/SuspenseFallback'
import WellSelector from '@components/selectors/WellSelector'
import { invokeWebApiWrapperAsync } from '@components/factory'
import { arrayOrDefault, NoAccessComponent, wrapPrivateComponent } from '@utils'
import { arrayOrDefault, NoAccessComponent, withPermissions } from '@utils'
import { OperationStatService, WellCompositeService } from '@api'
import WellCompositeSections from './WellCompositeSections'
@ -76,4 +76,4 @@ const WellCompositeEditor = memo(() => {
)
})
export default wrapPrivateComponent(WellCompositeEditor, { requirements: ['OperationStat.get', 'WellComposite.get'] })
export default withPermissions(WellCompositeEditor, ['OperationStat.get', 'WellComposite.get'])

View File

@ -2,7 +2,7 @@ import { memo, useMemo } from 'react'
import { Outlet } from 'react-router-dom'
import { RootPathContext, useRootPath } from '@asb/context'
import { wrapPrivateComponent } from '@utils'
import { withPermissions } from '@utils'
const Analytics = memo(() => {
const root = useRootPath()
@ -15,9 +15,4 @@ const Analytics = memo(() => {
)
})
export default wrapPrivateComponent(Analytics, {
requirements: [],
title: 'Аналитика',
route: 'analytics/*',
key: 'analytics',
})
export default withPermissions(Analytics)

View File

@ -2,7 +2,7 @@ import { Navigate, Route, Routes } from 'react-router-dom'
import { memo, useMemo } from 'react'
import { RootPathContext, useRootPath } from '@asb/context'
import { wrapPrivateComponent, NoAccessComponent, hasPermission } from '@utils'
import { withPermissions, NoAccessComponent, hasPermission } from '@utils'
import DocumentsTemplate from './DocumentsTemplate'
@ -48,9 +48,4 @@ const MenuDocuments = memo(() => {
)
})
export default wrapPrivateComponent(MenuDocuments, {
requirements: [ 'Deposit.get', 'File.get' ],
title: 'Документы',
route: 'document/*',
key: 'document',
})
export default withPermissions(MenuDocuments, [ 'Deposit.get', 'File.get' ])

View File

@ -13,7 +13,7 @@ import { memo, useCallback, useEffect, useMemo, useState } from 'react'
import { useWell } from '@asb/context'
import LoaderPortal from '@components/LoaderPortal'
import { downloadFile, formatBytes, invokeWebApiWrapperAsync } from '@components/factory'
import { arrayOrDefault, formatDate, wrapPrivateComponent } from '@utils'
import { arrayOrDefault, formatDate, withPermissions } from '@utils'
import { DrillingProgramService } from '@api'
import CategoryAdder from './CategoryAdder'
@ -185,8 +185,4 @@ const DrillingProgram = memo(() => {
)
})
export default wrapPrivateComponent(DrillingProgram, {
requirements: [ 'DrillingProgram.get' ],
title: 'Программа бурения',
route: 'drillingProgram',
})
export default withPermissions(DrillingProgram, [ 'DrillingProgram.get' ])

View File

@ -5,7 +5,7 @@ import { Button } from 'antd'
import { useWell } from '@asb/context'
import LoaderPortal from '@components/LoaderPortal'
import { invokeWebApiWrapperAsync } from '@components/factory'
import { wrapPrivateComponent } from '@utils'
import { withPermissions } from '@utils'
import { MeasureService } from '@api'
import { MeasureTable } from './MeasureTable'
@ -93,8 +93,4 @@ const Measure = memo(() => {
)
})
export default wrapPrivateComponent(Measure, {
requirements: [ 'Measure.get' ],
title: 'Измерения',
route: 'measure',
})
export default withPermissions(Measure, [ 'Measure.get' ])

View File

@ -7,7 +7,7 @@ import { useWell } from '@asb/context'
import LoaderPortal from '@components/LoaderPortal'
import { DateRangeWrapper, Table, makeDateColumn, makeColumn } from '@components/Table'
import { download, invokeWebApiWrapperAsync, notify } from '@components/factory'
import { arrayOrDefault, wrapPrivateComponent } from '@utils'
import { arrayOrDefault, withPermissions } from '@utils'
import { DailyReportService } from '@api'
import ReportEditor from './ReportEditor'
@ -123,10 +123,4 @@ const DailyReport = memo(() => {
)
})
export default wrapPrivateComponent(DailyReport, {
requirements: [
// 'DailyReport.get',
],
title: 'Суточный рапорт',
route: 'daily_report',
})
export default withPermissions(DailyReport) //, ['DailyReport.get'])

View File

@ -7,7 +7,7 @@ import { useWell } from '@asb/context'
import { DateRangeWrapper } from 'components/Table'
import { LoaderPortal } from '@components/LoaderPortal'
import { invokeWebApiWrapperAsync } from '@components/factory'
import { formatDate, wrapPrivateComponent } from '@utils'
import { formatDate, withPermissions } from '@utils'
import { Subscribe } from '@services/signalr'
import { ReportService } from '@api'
@ -175,8 +175,4 @@ const DiagramReport = memo(() => {
)
})
export default wrapPrivateComponent(DiagramReport, {
requirements: [ 'Report.get' ],
title: 'Диаграмма',
route: 'diagram_report',
})
export default withPermissions(DiagramReport, [ 'Report.get' ])

View File

@ -2,7 +2,7 @@ import { Outlet } from 'react-router-dom'
import { memo, useMemo } from 'react'
import { RootPathContext, useRootPath } from '@asb/context'
import { wrapPrivateComponent } from '@utils'
import { withPermissions } from '@utils'
const Reports = memo(() => {
const root = useRootPath()
@ -15,9 +15,4 @@ const Reports = memo(() => {
)
})
export default wrapPrivateComponent(Reports, {
requirements: [],
title: 'Рапорта',
route: 'reports/*',
key: 'reports',
})
export default withPermissions(Reports)

View File

@ -11,7 +11,7 @@ import LoaderPortal from '@components/LoaderPortal'
import { invokeWebApiWrapperAsync } from '@components/factory'
import { DatePickerWrapper, makeDateSorter } from '@components/Table'
import { PeriodPicker, defaultPeriod } from '@components/selectors/PeriodPicker'
import { formatDate, range, wrapPrivateComponent } from '@utils'
import { formatDate, range, withPermissions } from '@utils'
import { TelemetryDataSaubService } from '@api'
import { makeChartGroups, normalizeData, yAxis } from '../TelemetryView'
@ -265,8 +265,4 @@ const Archive = memo(() => {
)
})
export default wrapPrivateComponent(Archive, {
requirements: ['TelemetryDataSaub.get'],
title: 'Архив',
route: 'archive',
})
export default withPermissions(Archive, ['TelemetryDataSaub.get'])

View File

@ -7,7 +7,7 @@ import { useWell, useRootPath } from '@asb/context'
import LoaderPortal from '@components/LoaderPortal'
import { invokeWebApiWrapperAsync } from '@components/factory'
import { BaseWidget, WidgetSettingsWindow } from '@components/widgets'
import { arrayOrDefault, wrapPrivateComponent, getJSON, setJSON, getTabname } from '@utils'
import { arrayOrDefault, withPermissions, getJSON, setJSON, getTabname } from '@utils'
import Subscribe from '@services/signalr'
import {
WitsInfoService,
@ -260,17 +260,12 @@ const DashboardNNB = memo(({ enableEditing = false }) => {
)
})
export default wrapPrivateComponent(DashboardNNB, {
requirements: [
// 'WitsInfo',
// 'WitsRecord1',
// 'WitsRecord7',
// 'WitsRecord8',
// 'WitsRecord50',
// 'WitsRecord60',
// 'WitsRecord61',
],
title: 'ННБ',
route: 'dashboard_nnb/*',
key: 'dashboard_nnb',
})
export default withPermissions(DashboardNNB, [
// 'WitsInfo',
// 'WitsRecord1',
// 'WitsRecord7',
// 'WitsRecord8',
// 'WitsRecord50',
// 'WitsRecord60',
// 'WitsRecord61',
])

View File

@ -8,7 +8,7 @@ import { useWell } from '@asb/context'
import LoaderPortal from '@components/LoaderPortal'
import { invokeWebApiWrapperAsync } from '@components/factory'
import { makeColumn, makeDateColumn, makeNumericColumn, makeNumericSorter, makeTextColumn, Table } from '@components/Table'
import { wrapPrivateComponent } from '@utils'
import { withPermissions } from '@utils'
import { MessageService } from '@api'
import '@styles/filter.less'
@ -147,8 +147,4 @@ const Messages = memo(() => {
)
})
export default wrapPrivateComponent(Messages, {
requirements: ['Message.get'],
title: 'Сообщения',
route: 'messages',
})
export default withPermissions(Messages, ['Message.get'])

View File

@ -7,7 +7,7 @@ import LoaderPortal from '@components/LoaderPortal'
import { invokeWebApiWrapperAsync } from '@components/factory'
import D3HorizontalPercentChart from '@components/d3/D3HorizontalPercentChart'
import { DateRangeWrapper, makeColumn, makeNumericColumn, makeNumericRender, makeTextColumn, Table } from '@components/Table'
import { arrayOrDefault, range, wrapPrivateComponent } from '@utils'
import { arrayOrDefault, range, withPermissions } from '@utils'
import { SubsystemOperationTimeService } from '@api'
import '@styles/filter.less'
@ -121,9 +121,4 @@ export const OperationTime = memo(() => {
)
})
export default wrapPrivateComponent(OperationTime, {
requirements: [], // SubsystemOperationTime.get
title: 'Наработка',
route: 'operation_time',
key: 'operation_time',
})
export default withPermissions(OperationTime) //, ['SubsystemOperationTime.get'])

View File

@ -7,7 +7,7 @@ import LoaderPortal from '@components/LoaderPortal'
import { DateRangeWrapper } from '@components/Table'
import { invokeWebApiWrapperAsync } from '@components/factory'
import { unique } from '@utils/filters'
import { getPermissions, arrayOrDefault, range, wrapPrivateComponent, pretify } from '@utils'
import { getPermissions, arrayOrDefault, range, withPermissions, pretify } from '@utils'
import { DetectedOperationService, DrillerService, TelemetryDataSaubService } from '@api'
import DrillerList from './DrillerList'
@ -161,4 +161,4 @@ const Operations = memo(() => {
)
})
export default wrapPrivateComponent(Operations, { requirements: ['DetectedOperation.get', 'TelemetryDataSaub.get'] })
export default withPermissions(Operations, ['DetectedOperation.get', 'TelemetryDataSaub.get'])

View File

@ -9,7 +9,7 @@ import LoaderPortal from '@components/LoaderPortal'
import { Grid, GridItem } from '@components/Grid'
import { invokeWebApiWrapperAsync } from '@components/factory'
import { PeriodPicker, defaultPeriod } from '@components/selectors/PeriodPicker'
import { formatDate, hasPermission, wrapPrivateComponent } from '@utils'
import { formatDate, hasPermission, withPermissions } from '@utils'
import { Subscribe } from '@services/signalr'
import {
DrillFlowChartService,
@ -312,14 +312,10 @@ const TelemetryView = memo(() => {
)
})
export default wrapPrivateComponent(TelemetryView, {
requirements: [
'DrillFlowChart.get',
'OperationStat.get',
'TelemetryDataSaub.get',
'TelemetryDataSpin.get',
'Well.get',
],
title: 'Мониторинг',
route: 'telemetry',
})
export default withPermissions(TelemetryView, [
'DrillFlowChart.get',
'OperationStat.get',
'TelemetryDataSaub.get',
'TelemetryDataSpin.get',
'Well.get',
])

View File

@ -1,9 +1,8 @@
import { FundViewOutlined } from '@ant-design/icons'
import { Outlet } from 'react-router-dom'
import { memo, useMemo } from 'react'
import { RootPathContext, useRootPath } from '@asb/context'
import { wrapPrivateComponent } from '@utils'
import { withPermissions } from '@utils'
import '@styles/index.css'
@ -18,10 +17,4 @@ const Telemetry = memo(() => {
)
})
export default wrapPrivateComponent(Telemetry, {
requirements: [],
icon: <FundViewOutlined />,
title: 'Телеметрия',
route: 'telemetry/*',
key: 'telemetry',
})
export default withPermissions(Telemetry)

View File

@ -9,7 +9,7 @@ import LoaderPortal from '@components/LoaderPortal'
import { invokeWebApiWrapperAsync } from '@components/factory'
import { makeColumn, makeDateColumn, makeTextColumn, Table } from '@components/Table'
import { WellFinalDocumentsService } from '@api'
import { wrapPrivateComponent } from '@utils'
import { withPermissions } from '@utils'
import WellCaseEditor from './WellCaseEditor'
import { HistoryTable } from './HistoryTable'
@ -102,9 +102,4 @@ const WellCase = memo(() => {
)
})
export default wrapPrivateComponent(WellCase, {
title: 'Дело скважины',
route: 'well_case',
requirements: [],
// requirements: ['WellFinalDocuments.get'],
})
export default withPermissions(WellCase) //, ['WellFinalDocuments.get'])

View File

@ -1,14 +1,10 @@
import { wrapPrivateComponent } from '@utils'
import { withPermissions } from '@utils'
import WellOperationsEditor from './WellOperationsEditor'
export const WellOperationsEditorFact = wrapPrivateComponent(
export const WellOperationsEditorFact = withPermissions(
() => <WellOperationsEditor idType={1} tableName={'well_operations_fact'}/>,
{
requirements: [ 'WellOperation.get' ],
title: 'Факт',
route: 'fact',
}
[ 'WellOperation.get' ],
)
export default WellOperationsEditorFact

View File

@ -1,14 +1,10 @@
import { wrapPrivateComponent } from '@utils'
import { withPermissions } from '@utils'
import WellOperationsEditor from './WellOperationsEditor'
export const WellOperationsEditorPlan = wrapPrivateComponent(
export const WellOperationsEditorPlan = withPermissions(
() => <WellOperationsEditor idType={0} tableName={'well_operations_plan'}/>,
{
requirements: [ 'WellOperation.get' ],
title: 'План',
route: 'plan',
}
[ 'WellOperation.get' ],
)
export default WellOperationsEditorPlan

View File

@ -8,7 +8,7 @@ import { useTopRightBlock, useWell } from '@asb/context'
import { D3Chart } from '@components/d3'
import LoaderPortal from '@components/LoaderPortal'
import { invokeWebApiWrapperAsync } from '@components/factory'
import { formatDate, fractionalSum, wrapPrivateComponent, getOperations, pretify } from '@utils'
import { formatDate, fractionalSum, withPermissions, getOperations, pretify } from '@utils'
import TLPie from './TLPie'
import TLChart from './TLChart'
@ -294,8 +294,4 @@ const Tvd = memo(({ well: givenWell, title, ...other }) => {
)
})
export default wrapPrivateComponent(Tvd, {
requirements: ['OperationStat.get', 'DetectedOperation.get'],
title: 'TVD',
route: 'tvd',
})
export default withPermissions(Tvd, ['OperationStat.get', 'DetectedOperation.get'])

View File

@ -2,18 +2,11 @@ import { Outlet } from 'react-router-dom'
import { memo, useMemo } from 'react'
import { RootPathContext, useRootPath } from '@asb/context'
import { wrapPrivateComponent } from '@utils'
const properties = {
requirements: [],
title: 'Операции по скважине',
route: 'operations/*',
key: 'operations',
}
import { withPermissions } from '@utils'
const WellOperations = memo(() => {
const root = useRootPath()
const rootPath = useMemo(() => `${root}/${properties.key}`, [root])
const rootPath = useMemo(() => `${root}/operations`, [root])
return(
<RootPathContext.Provider value={rootPath}>
@ -22,4 +15,4 @@ const WellOperations = memo(() => {
)
})
export default wrapPrivateComponent(WellOperations, properties)
export default withPermissions(WellOperations)

View File

@ -2,9 +2,10 @@ import { lazy, memo, useCallback, useEffect, useMemo, useState } from 'react'
import { Navigate, Route, Routes, useLocation, useParams } from 'react-router-dom'
import { WellContext, RootPathContext, useRootPath, useLayoutProps, TopRightBlockContext } from '@asb/context'
import { FastRunMenu } from '@components/FastRunMenu'
import { invokeWebApiWrapperAsync } from '@components/factory'
import { MenuBreadcrumbItems } from '@components/MenuBreadcrumb'
import { NoAccessComponent, wrapPrivateComponent } from '@utils'
import { makeMenuBreadcrumbItems } from '@components/MenuBreadcrumb'
import { NoAccessComponent, withPermissions } from '@utils'
import { WellService } from '@api'
import { NavigationMenu, menuItems } from './NavigationMenu'
@ -77,15 +78,16 @@ const Well = memo(() => {
useEffect(() => setLayoutProps({
sider: <NavigationMenu idWell={well.id} />,
breadcrumb: <MenuBreadcrumbItems menuItems={menuItems} pathRoot={/^\/well\/[0-9]+\//} />,
breadcrumb: makeMenuBreadcrumbItems(menuItems, location.pathname, /^\/well\/[0-9]+\//),
topRightBlock: topRightBlock,
}), [well, setLayoutProps, topRightBlock])
}), [well, location.pathname, setLayoutProps, topRightBlock])
useEffect(() => setTopRightBlock(undefined), [location])
return (
<RootPathContext.Provider value={rootPath}>
<WellContext.Provider value={[well, updateWell]}>
<FastRunMenu />
<TopRightBlockContext.Provider value={setTopRightBlock}>
<Routes>
<Route index element={<Navigate to={'telemetry'} replace />} />
@ -138,9 +140,4 @@ const Well = memo(() => {
)
})
export default wrapPrivateComponent(Well, {
requirements: [],
title: 'Скважина',
route: 'well/:idWell/*',
key: 'well',
})
export default withPermissions(Well)

View File

@ -6,7 +6,7 @@ import { Card, Form, Input, Button } from 'antd'
import LoaderPortal from '@components/LoaderPortal'
import { invokeWebApiWrapperAsync } from '@components/factory'
import { loginRules, passwordRules } from '@utils/validationRules'
import { setUser, wrapPrivateComponent } from '@utils'
import { setUser, withPermissions } from '@utils'
import { AuthService } from '@api'
import '@styles/index.css'
@ -59,8 +59,4 @@ const Login = memo(() => {
)
})
export default wrapPrivateComponent(Login, {
requirements: [],
title: 'Вход в систему',
route: 'login',
})
export default withPermissions(Login)

View File

@ -20,7 +20,7 @@ import {
passwordRules,
phoneRules
} from '@utils/validationRules'
import { wrapPrivateComponent } from '@utils'
import { withPermissions } from '@utils'
import Logo from '@images/Logo'
@ -92,8 +92,4 @@ export const Register = memo(() => {
)
})
export default wrapPrivateComponent(Register, {
requirements: [],
title: 'Регистрация',
route: 'register',
})
export default withPermissions(Register)

View File

@ -0,0 +1,13 @@
.fast-run-menu {
position: absolute;
z-index: 1000;
top: 100px;
left: calc(25vw - 5px);
border: 5px solid #777;
border-radius: 5px;
width: 50vw;
}
.fast-run-menu-text-found {
background-color: yellow;
}

View File

@ -1,29 +1,12 @@
export * from './arrayOrDefault'
export * from './datetime'
export type { RawDate, TimezoneId, timeInS } from './datetime'
export * from './chart'
export * from './min_max_filter'
export type { KeyType } from './min_max_filter'
export * from './objects'
export * from './numbers'
export * from './permissions'
export type { Role, Permission, ServiceName, ServiceRequestType, PermissionRequest, PermissionRecord, PrivateProps } from './permissions'
export * from './saubOperations'
export type { SaubData } from './saubOperations'
export * from './storage'
export type { StorageNames, DataDashboardNNB } from './storage'
export * from './string'
export * from './svg'
export * from './table_settings'
export type { TableColumnSettings, TableSettings, TableSettingsStore } from './table_settings'

View File

@ -87,17 +87,7 @@ export const publicPages: Readonly<string[]> = [
'/register',
]
export type PrivateProps = {
key?: string
icon?: ReactNode
route?: string
title?: ReactNode
requirements?: string[]
}
export type PrivateComponent<P extends object> = NamedExoticComponent<P> & PrivateProps & {
getKey: () => string
}
export type PrivateComponent<P extends object> = NamedExoticComponent<P>
export const NoAccessComponent = memo(() => getUser().login ? (
<AccessDenied /> // <Navigate to={'/access_denied'} replace />
@ -105,18 +95,13 @@ export const NoAccessComponent = memo(() => getUser().login ? (
<Navigate to={'/login'} replace />
))
export const wrapPrivateComponent = <P extends object>(
export const withPermissions = <P extends object>(
Component: NamedExoticComponent<P> | ((props: P) => ReactElement),
properties: PrivateProps = {},
requirements: Permission[] = [],
elseNode: JSX.Element = <NoAccessComponent />
): PrivateComponent<P> => Object.assign(
memo<P>((props) => hasPermission(properties.requirements) ? <Component {...props} /> : elseNode),
{
getKey() { return this.key ?? this.route ?? '' },
requirements: [],
...properties,
}
)
): PrivateComponent<P> => Object.assign(memo<P>(function PrivateWrapper(props) {
return hasPermission(requirements) ? <Component {...props} /> : elseNode
}))
export const getTabname = () => {
const params = useParams()

View File

@ -1,8 +1,4 @@
export * from './cachedFetch'
export * from './functionalValue'
export type { FunctionalValue } from './functionalValue'
export * from './usePartialProps'
export * from './useUserSettings'