diff --git a/package.json b/package.json index caa52ad..8ac132b 100755 --- a/package.json +++ b/package.json @@ -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", diff --git a/src/components/FastRunMenu.tsx b/src/components/FastRunMenu.tsx new file mode 100644 index 0000000..dfaed0c --- /dev/null +++ b/src/components/FastRunMenu.tsx @@ -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() + const [results, setResults] = useState([]) + const ref = useRef(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)} + + {label.slice(idx.from, idx.to)} + + {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 ? ( +
+ +
+ ) : <> +}) + +export default FastRunMenu diff --git a/src/components/LayoutPortal.tsx b/src/components/LayoutPortal.tsx index 909172e..c8c3f0b 100644 --- a/src/components/LayoutPortal.tsx +++ b/src/components/LayoutPortal.tsx @@ -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(() => { setWellsTreeOpen((prev) => !prev)}>{currentWell} )} - {breadcrumb} + {breadcrumb !== true && 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 diff --git a/src/components/MenuBreadcrumb.tsx b/src/components/MenuBreadcrumb.tsx index 05cbc74..5299039 100644 --- a/src/components/MenuBreadcrumb.tsx +++ b/src/components/MenuBreadcrumb.tsx @@ -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) => ( + + {itemRender ? itemRender(item) : ( + {item.title} + )} + + )) } - -export const MenuBreadcrumbItems = memo(({ 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) => ( - - {itemRender ? itemRender(item) : ( - {item.title} - )} - - ))} - - ) -}) diff --git a/src/components/Table/Columns/index.ts b/src/components/Table/Columns/index.ts index c97f091..b8cb6ef 100755 --- a/src/components/Table/Columns/index.ts +++ b/src/components/Table/Columns/index.ts @@ -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 = Record export type RenderMethod = (value: T, dataset?: DataType, index?: number) => ReactNode diff --git a/src/components/Table/index.tsx b/src/components/Table/index.tsx index c1b3558..fd5d017 100755 --- a/src/components/Table/index.tsx +++ b/src/components/Table/index.tsx @@ -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 = { skip?: number take?: number count?: number - items?: any[] | null + items?: T[] | null } -export const makePaginationObject = (сontainer: PaginationContainer, ...other: any) => ({ +export const makePaginationObject = (сontainer: PaginationContainer, other: M) => ({ ...other, pageSize: сontainer.take, total: сontainer.count ?? сontainer.items?.length ?? 0, diff --git a/src/components/d3/index.ts b/src/components/d3/index.ts index 4811ec3..31e788a 100644 --- a/src/components/d3/index.ts +++ b/src/components/d3/index.ts @@ -1,4 +1,2 @@ export * from './D3Chart' -export type { D3ChartProps } from './D3Chart' - export * from './types' diff --git a/src/components/icons/index.ts b/src/components/icons/index.ts index fe5c856..9b09b0b 100755 --- a/src/components/icons/index.ts +++ b/src/components/icons/index.ts @@ -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' diff --git a/src/components/views/index.ts b/src/components/views/index.ts index 44ac284..9b90057 100755 --- a/src/components/views/index.ts +++ b/src/components/views/index.ts @@ -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' diff --git a/src/components/widgets/index.ts b/src/components/widgets/index.ts index c73bcc7..fedfb24 100644 --- a/src/components/widgets/index.ts +++ b/src/components/widgets/index.ts @@ -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' diff --git a/src/index.tsx b/src/index.tsx index d09f3d5..5354f6e 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -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( ) - -// 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() diff --git a/src/pages/AdminPanel/ClusterController.jsx b/src/pages/AdminPanel/ClusterController.jsx index 7fdbd72..35c9b9b 100755 --- a/src/pages/AdminPanel/ClusterController.jsx +++ b/src/pages/AdminPanel/ClusterController.jsx @@ -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']) diff --git a/src/pages/AdminPanel/CompanyController.jsx b/src/pages/AdminPanel/CompanyController.jsx index e7a31d8..454b16c 100755 --- a/src/pages/AdminPanel/CompanyController.jsx +++ b/src/pages/AdminPanel/CompanyController.jsx @@ -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']) diff --git a/src/pages/AdminPanel/CompanyTypeController.jsx b/src/pages/AdminPanel/CompanyTypeController.jsx index eeab683..3debe2c 100755 --- a/src/pages/AdminPanel/CompanyTypeController.jsx +++ b/src/pages/AdminPanel/CompanyTypeController.jsx @@ -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']) diff --git a/src/pages/AdminPanel/DepositController.jsx b/src/pages/AdminPanel/DepositController.jsx index edf3b46..748490b 100755 --- a/src/pages/AdminPanel/DepositController.jsx +++ b/src/pages/AdminPanel/DepositController.jsx @@ -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']) diff --git a/src/pages/AdminPanel/PermissionController.jsx b/src/pages/AdminPanel/PermissionController.jsx index b4d1314..73db56a 100755 --- a/src/pages/AdminPanel/PermissionController.jsx +++ b/src/pages/AdminPanel/PermissionController.jsx @@ -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']) diff --git a/src/pages/AdminPanel/RoleController.jsx b/src/pages/AdminPanel/RoleController.jsx index d87a586..b995fde 100755 --- a/src/pages/AdminPanel/RoleController.jsx +++ b/src/pages/AdminPanel/RoleController.jsx @@ -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']) diff --git a/src/pages/AdminPanel/Telemetry/TelemetryMerger.jsx b/src/pages/AdminPanel/Telemetry/TelemetryMerger.jsx index acb69d7..e8add7a 100755 --- a/src/pages/AdminPanel/Telemetry/TelemetryMerger.jsx +++ b/src/pages/AdminPanel/Telemetry/TelemetryMerger.jsx @@ -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) diff --git a/src/pages/AdminPanel/Telemetry/TelemetryViewer.jsx b/src/pages/AdminPanel/Telemetry/TelemetryViewer.jsx index 1f040a4..f90ff30 100755 --- a/src/pages/AdminPanel/Telemetry/TelemetryViewer.jsx +++ b/src/pages/AdminPanel/Telemetry/TelemetryViewer.jsx @@ -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) diff --git a/src/pages/AdminPanel/Telemetry/index.jsx b/src/pages/AdminPanel/Telemetry/index.jsx index 706e74b..fe3b85d 100755 --- a/src/pages/AdminPanel/Telemetry/index.jsx +++ b/src/pages/AdminPanel/Telemetry/index.jsx @@ -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']) diff --git a/src/pages/AdminPanel/UserController/index.jsx b/src/pages/AdminPanel/UserController/index.jsx index 2581082..2f6b301 100755 --- a/src/pages/AdminPanel/UserController/index.jsx +++ b/src/pages/AdminPanel/UserController/index.jsx @@ -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']) diff --git a/src/pages/AdminPanel/VisitLog.jsx b/src/pages/AdminPanel/VisitLog.jsx index cdbeac5..e54c604 100755 --- a/src/pages/AdminPanel/VisitLog.jsx +++ b/src/pages/AdminPanel/VisitLog.jsx @@ -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']) diff --git a/src/pages/AdminPanel/WellController/index.jsx b/src/pages/AdminPanel/WellController/index.jsx index d7b06a2..6fe163e 100755 --- a/src/pages/AdminPanel/WellController/index.jsx +++ b/src/pages/AdminPanel/WellController/index.jsx @@ -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']) diff --git a/src/pages/AdminPanel/index.jsx b/src/pages/AdminPanel/index.jsx index f66f718..e4c11b8 100755 --- a/src/pages/AdminPanel/index.jsx +++ b/src/pages/AdminPanel/index.jsx @@ -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: , - title: 'Администраторская панель', - isAdmin: true, - breadcrumb: , -} - const AdminPanel = memo(() => { + const location = useLocation() const root = useRootPath() const rootPath = useMemo(() => `${root}/admin`, [root]) - useLayoutProps(layoutProps) + const setLayoutProps = useLayoutProps() + + useEffect(() => { + setLayoutProps({ + sider: , + title: 'Администраторская панель', + isAdmin: true, + breadcrumb: makeMenuBreadcrumbItems(menuItems, location.pathname, /^\/admin\//), + }) + }, [location.pathname]) return ( + } /> } /> @@ -58,4 +63,4 @@ const AdminPanel = memo(() => { ) }) -export default wrapPrivateComponent(AdminPanel, { requirements: ['RequestTracker.get'] }) +export default withPermissions(AdminPanel, ['RequestTracker.get']) diff --git a/src/pages/Cluster/ClusterWells.jsx b/src/pages/Cluster/ClusterWells.jsx index 7538ec4..a74c8bd 100755 --- a/src/pages/Cluster/ClusterWells.jsx +++ b/src/pages/Cluster/ClusterWells.jsx @@ -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) diff --git a/src/pages/Cluster/index.jsx b/src/pages/Cluster/index.jsx index 9c33768..1fab68f 100755 --- a/src/pages/Cluster/index.jsx +++ b/src/pages/Cluster/index.jsx @@ -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 ( - - - + <> + + + + + ) }) -export default wrapPrivateComponent(Cluster, { - requirements: ['OperationStat.get'], - title: 'Анализ скважин куста', - route: 'cluster/:idCluster/*', - key: 'cluster', -}) +export default withPermissions(Cluster, ['OperationStat.get']) diff --git a/src/pages/Deposit.jsx b/src/pages/Deposit.jsx index 893a03d..9779e78 100755 --- a/src/pages/Deposit.jsx +++ b/src/pages/Deposit.jsx @@ -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 ( - -
- - {depositsData.map(deposit => ( - - - {deposit.clusters.map(cluster => ( - -
{cluster.caption}
- - ))} -
- } trigger={['click']} title={deposit.caption}> -
- - - -
- - - ))} - - -
+ <> + + +
+ + {depositsData.map(deposit => ( + + + {deposit.clusters.map(cluster => ( + +
{cluster.caption}
+ + ))} +
+ } trigger={['click']} title={deposit.caption}> +
+ + + +
+ + + ))} + + +
+ ) }) -export default wrapPrivateComponent(Deposit, { - requirements: ['Cluster.get'], - title: 'Месторождение', - route: 'deposit/*', - key: 'deposit', -}) +export default withPermissions(Deposit, ['Cluster.get']) diff --git a/src/pages/FileDownload.jsx b/src/pages/FileDownload.jsx index aa0f566..217edfb 100644 --- a/src/pages/FileDownload.jsx +++ b/src/pages/FileDownload.jsx @@ -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, WellService } from '@api' const { Paragraph, Text } = Typography @@ -99,7 +99,4 @@ const FileDownload = memo(function FileDownload() { FileDownload.displayName = 'FileDownloadMemo' -export default wrapPrivateComponent(FileDownload, { - requirements: ['File.get'], - route: 'file_download/:idWell/:idFile/*', -}) +export default withPermissions(FileDownload, ['File.get']) diff --git a/src/pages/Well/Analytics/Statistics.jsx b/src/pages/Well/Analytics/Statistics.jsx index e25cb51..68d4244 100644 --- a/src/pages/Well/Analytics/Statistics.jsx +++ b/src/pages/Well/Analytics/Statistics.jsx @@ -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) diff --git a/src/pages/Well/Analytics/WellCompositeEditor/WellCompositeSections.jsx b/src/pages/Well/Analytics/WellCompositeEditor/WellCompositeSections.jsx index db9229a..426ed21 100644 --- a/src/pages/Well/Analytics/WellCompositeEditor/WellCompositeSections.jsx +++ b/src/pages/Well/Analytics/WellCompositeEditor/WellCompositeSections.jsx @@ -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']) diff --git a/src/pages/Well/Analytics/WellCompositeEditor/index.jsx b/src/pages/Well/Analytics/WellCompositeEditor/index.jsx index b2ab94b..b76fd84 100644 --- a/src/pages/Well/Analytics/WellCompositeEditor/index.jsx +++ b/src/pages/Well/Analytics/WellCompositeEditor/index.jsx @@ -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']) diff --git a/src/pages/Well/Analytics/index.jsx b/src/pages/Well/Analytics/index.jsx index f610484..6191d3d 100644 --- a/src/pages/Well/Analytics/index.jsx +++ b/src/pages/Well/Analytics/index.jsx @@ -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) diff --git a/src/pages/Well/Documents/index.jsx b/src/pages/Well/Documents/index.jsx index 1b4c293..06a53b8 100644 --- a/src/pages/Well/Documents/index.jsx +++ b/src/pages/Well/Documents/index.jsx @@ -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' ]) diff --git a/src/pages/Well/DrillingProgram/index.jsx b/src/pages/Well/DrillingProgram/index.jsx index fe1fda4..a0298df 100644 --- a/src/pages/Well/DrillingProgram/index.jsx +++ b/src/pages/Well/DrillingProgram/index.jsx @@ -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' ]) diff --git a/src/pages/Well/Measure/index.jsx b/src/pages/Well/Measure/index.jsx index e6b4590..93ca8d7 100644 --- a/src/pages/Well/Measure/index.jsx +++ b/src/pages/Well/Measure/index.jsx @@ -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' ]) diff --git a/src/pages/Well/Reports/DailyReport/index.jsx b/src/pages/Well/Reports/DailyReport/index.jsx index 15f7869..aa19d13 100644 --- a/src/pages/Well/Reports/DailyReport/index.jsx +++ b/src/pages/Well/Reports/DailyReport/index.jsx @@ -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']) diff --git a/src/pages/Well/Reports/DiagramReport/index.jsx b/src/pages/Well/Reports/DiagramReport/index.jsx index f96e569..e4d7795 100644 --- a/src/pages/Well/Reports/DiagramReport/index.jsx +++ b/src/pages/Well/Reports/DiagramReport/index.jsx @@ -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' ]) diff --git a/src/pages/Well/Reports/index.jsx b/src/pages/Well/Reports/index.jsx index a8f581d..6ba17aa 100644 --- a/src/pages/Well/Reports/index.jsx +++ b/src/pages/Well/Reports/index.jsx @@ -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) diff --git a/src/pages/Well/Telemetry/Archive/index.jsx b/src/pages/Well/Telemetry/Archive/index.jsx index 7a0d65e..b15afdf 100644 --- a/src/pages/Well/Telemetry/Archive/index.jsx +++ b/src/pages/Well/Telemetry/Archive/index.jsx @@ -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']) diff --git a/src/pages/Well/Telemetry/DashboardNNB/index.jsx b/src/pages/Well/Telemetry/DashboardNNB/index.jsx index 2d4606e..a37f60c 100644 --- a/src/pages/Well/Telemetry/DashboardNNB/index.jsx +++ b/src/pages/Well/Telemetry/DashboardNNB/index.jsx @@ -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', +]) diff --git a/src/pages/Well/Telemetry/Messages.jsx b/src/pages/Well/Telemetry/Messages.jsx index e029e49..653e122 100644 --- a/src/pages/Well/Telemetry/Messages.jsx +++ b/src/pages/Well/Telemetry/Messages.jsx @@ -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']) diff --git a/src/pages/Well/Telemetry/OperationTime/index.jsx b/src/pages/Well/Telemetry/OperationTime/index.jsx index 3b78fae..11f7597 100644 --- a/src/pages/Well/Telemetry/OperationTime/index.jsx +++ b/src/pages/Well/Telemetry/OperationTime/index.jsx @@ -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']) diff --git a/src/pages/Well/Telemetry/Operations/index.jsx b/src/pages/Well/Telemetry/Operations/index.jsx index fd34730..fc1129d 100644 --- a/src/pages/Well/Telemetry/Operations/index.jsx +++ b/src/pages/Well/Telemetry/Operations/index.jsx @@ -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']) diff --git a/src/pages/Well/Telemetry/TelemetryView/index.jsx b/src/pages/Well/Telemetry/TelemetryView/index.jsx index afa3859..7a2ca50 100644 --- a/src/pages/Well/Telemetry/TelemetryView/index.jsx +++ b/src/pages/Well/Telemetry/TelemetryView/index.jsx @@ -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', +]) diff --git a/src/pages/Well/Telemetry/index.jsx b/src/pages/Well/Telemetry/index.jsx index e893433..a917396 100644 --- a/src/pages/Well/Telemetry/index.jsx +++ b/src/pages/Well/Telemetry/index.jsx @@ -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: , - title: 'Телеметрия', - route: 'telemetry/*', - key: 'telemetry', -}) +export default withPermissions(Telemetry) diff --git a/src/pages/Well/WellCase/index.jsx b/src/pages/Well/WellCase/index.jsx index 250d3c3..3912da6 100644 --- a/src/pages/Well/WellCase/index.jsx +++ b/src/pages/Well/WellCase/index.jsx @@ -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']) diff --git a/src/pages/Well/WellOperations/OperationEditor/Fact.jsx b/src/pages/Well/WellOperations/OperationEditor/Fact.jsx index 3671de2..c56be47 100644 --- a/src/pages/Well/WellOperations/OperationEditor/Fact.jsx +++ b/src/pages/Well/WellOperations/OperationEditor/Fact.jsx @@ -1,14 +1,10 @@ -import { wrapPrivateComponent } from '@utils' +import { withPermissions } from '@utils' import WellOperationsEditor from './WellOperationsEditor' -export const WellOperationsEditorFact = wrapPrivateComponent( +export const WellOperationsEditorFact = withPermissions( () => , - { - requirements: [ 'WellOperation.get' ], - title: 'Факт', - route: 'fact', - } + [ 'WellOperation.get' ], ) export default WellOperationsEditorFact diff --git a/src/pages/Well/WellOperations/OperationEditor/Plan.jsx b/src/pages/Well/WellOperations/OperationEditor/Plan.jsx index 240a189..c115c31 100644 --- a/src/pages/Well/WellOperations/OperationEditor/Plan.jsx +++ b/src/pages/Well/WellOperations/OperationEditor/Plan.jsx @@ -1,14 +1,10 @@ -import { wrapPrivateComponent } from '@utils' +import { withPermissions } from '@utils' import WellOperationsEditor from './WellOperationsEditor' -export const WellOperationsEditorPlan = wrapPrivateComponent( +export const WellOperationsEditorPlan = withPermissions( () => , - { - requirements: [ 'WellOperation.get' ], - title: 'План', - route: 'plan', - } + [ 'WellOperation.get' ], ) export default WellOperationsEditorPlan diff --git a/src/pages/Well/WellOperations/Tvd/index.jsx b/src/pages/Well/WellOperations/Tvd/index.jsx index e41ba75..1082b00 100644 --- a/src/pages/Well/WellOperations/Tvd/index.jsx +++ b/src/pages/Well/WellOperations/Tvd/index.jsx @@ -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']) diff --git a/src/pages/Well/WellOperations/index.jsx b/src/pages/Well/WellOperations/index.jsx index 53d7dfb..396bac4 100644 --- a/src/pages/Well/WellOperations/index.jsx +++ b/src/pages/Well/WellOperations/index.jsx @@ -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( @@ -22,4 +15,4 @@ const WellOperations = memo(() => { ) }) -export default wrapPrivateComponent(WellOperations, properties) +export default withPermissions(WellOperations) diff --git a/src/pages/Well/index.jsx b/src/pages/Well/index.jsx index 4725aa9..398a0b8 100644 --- a/src/pages/Well/index.jsx +++ b/src/pages/Well/index.jsx @@ -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: , - breadcrumb: , + breadcrumb: makeMenuBreadcrumbItems(menuItems, location.pathname, /^\/well\/[0-9]+\//), topRightBlock: topRightBlock, - }), [well, setLayoutProps, topRightBlock]) + }), [well, location.pathname, setLayoutProps, topRightBlock]) useEffect(() => setTopRightBlock(undefined), [location]) return ( + } /> @@ -138,9 +140,4 @@ const Well = memo(() => { ) }) -export default wrapPrivateComponent(Well, { - requirements: [], - title: 'Скважина', - route: 'well/:idWell/*', - key: 'well', -}) +export default withPermissions(Well) diff --git a/src/pages/public/Login.jsx b/src/pages/public/Login.jsx index f261d05..d322a11 100644 --- a/src/pages/public/Login.jsx +++ b/src/pages/public/Login.jsx @@ -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) diff --git a/src/pages/public/Register.jsx b/src/pages/public/Register.jsx index 89ddc46..8154059 100644 --- a/src/pages/public/Register.jsx +++ b/src/pages/public/Register.jsx @@ -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) diff --git a/src/styles/fast_run_menu.less b/src/styles/fast_run_menu.less new file mode 100644 index 0000000..299d3b0 --- /dev/null +++ b/src/styles/fast_run_menu.less @@ -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; +} diff --git a/src/utils/functions/index.ts b/src/utils/functions/index.ts index 69fcf3c..547fb68 100644 --- a/src/utils/functions/index.ts +++ b/src/utils/functions/index.ts @@ -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' diff --git a/src/utils/functions/permissions.tsx b/src/utils/functions/permissions.tsx index 6375502..c29b525 100644 --- a/src/utils/functions/permissions.tsx +++ b/src/utils/functions/permissions.tsx @@ -87,17 +87,7 @@ export const publicPages: Readonly = [ '/register', ] -export type PrivateProps = { - key?: string - icon?: ReactNode - route?: string - title?: ReactNode - requirements?: string[] -} - -export type PrivateComponent

= NamedExoticComponent

& PrivateProps & { - getKey: () => string -} +export type PrivateComponent

= NamedExoticComponent

export const NoAccessComponent = memo(() => getUser().login ? ( // @@ -105,18 +95,13 @@ export const NoAccessComponent = memo(() => getUser().login ? ( )) -export const wrapPrivateComponent =

( +export const withPermissions =

( Component: NamedExoticComponent

| ((props: P) => ReactElement), - properties: PrivateProps = {}, + requirements: Permission[] = [], elseNode: JSX.Element = -): PrivateComponent

=> Object.assign( - memo

((props) => hasPermission(properties.requirements) ? : elseNode), - { - getKey() { return this.key ?? this.route ?? '' }, - requirements: [], - ...properties, - } -) +): PrivateComponent

=> Object.assign(memo

(function PrivateWrapper(props) { + return hasPermission(requirements) ? : elseNode +})) export const getTabname = () => { const params = useParams() diff --git a/src/utils/hooks/index.ts b/src/utils/hooks/index.ts index 60ccb57..d4f229e 100644 --- a/src/utils/hooks/index.ts +++ b/src/utils/hooks/index.ts @@ -1,8 +1,4 @@ export * from './cachedFetch' - export * from './functionalValue' -export type { FunctionalValue } from './functionalValue' - export * from './usePartialProps' - export * from './useUserSettings'