forked from ddrilling/asb_cloud_front
Layout вынесен в отдельную директорию, добавлена админка, добавлена фабрика для колонок с Select
This commit is contained in:
parent
2c585ab227
commit
7a3d26e846
21
src/components/Layout/AdminLayoutPortal.tsx
Normal file
21
src/components/Layout/AdminLayoutPortal.tsx
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import { Button, Layout } from 'antd'
|
||||||
|
import { Link } from 'react-router-dom'
|
||||||
|
import PageHeader from '../PageHeader'
|
||||||
|
|
||||||
|
type LayoutPortalProps = {
|
||||||
|
title?: string
|
||||||
|
[props: string]: any
|
||||||
|
}
|
||||||
|
|
||||||
|
export const AdminLayoutPortal: React.FC<LayoutPortalProps> = ({title, ...props}) => (
|
||||||
|
<Layout.Content>
|
||||||
|
<PageHeader title={title}>
|
||||||
|
<Button size={'large'}>
|
||||||
|
<Link to={'/'}>Вернуться на основной сайт</Link>
|
||||||
|
</Button>
|
||||||
|
</PageHeader>
|
||||||
|
<Layout>
|
||||||
|
<Layout.Content className={'site-layout-background sheet'} {...props}/>
|
||||||
|
</Layout>
|
||||||
|
</Layout.Content>
|
||||||
|
)
|
22
src/components/Layout/LayoutPortal.tsx
Normal file
22
src/components/Layout/LayoutPortal.tsx
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import { Layout } from 'antd'
|
||||||
|
import PageHeader from '../PageHeader'
|
||||||
|
import WellTreeSelector from '../WellTreeSelector'
|
||||||
|
|
||||||
|
type LayoutPortalProps = {
|
||||||
|
title?: string
|
||||||
|
noSheet?: boolean
|
||||||
|
[props: string]: any
|
||||||
|
}
|
||||||
|
|
||||||
|
export const LayoutPortal: React.FC<LayoutPortalProps> = ({title, noSheet, ...props}) => (
|
||||||
|
<Layout.Content>
|
||||||
|
<PageHeader title={title}>
|
||||||
|
<WellTreeSelector />
|
||||||
|
</PageHeader>
|
||||||
|
<Layout>
|
||||||
|
{noSheet ? props.children : (
|
||||||
|
<Layout.Content className={'site-layout-background sheet'} {...props}/>
|
||||||
|
)}
|
||||||
|
</Layout>
|
||||||
|
</Layout.Content>
|
||||||
|
)
|
2
src/components/Layout/index.ts
Normal file
2
src/components/Layout/index.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export { AdminLayoutPortal } from './AdminLayoutPortal'
|
||||||
|
export { LayoutPortal } from './LayoutPortal'
|
@ -1,13 +0,0 @@
|
|||||||
import {Layout} from 'antd'
|
|
||||||
import PageHeader from './PageHeader'
|
|
||||||
|
|
||||||
export const LayoutPortal = ({title, noSheet, ...props}) => (
|
|
||||||
<Layout.Content>
|
|
||||||
<PageHeader title={title}/>
|
|
||||||
<Layout>
|
|
||||||
{noSheet ? props.children : (
|
|
||||||
<Layout.Content className={'site-layout-background sheet'} {...props}/>
|
|
||||||
)}
|
|
||||||
</Layout>
|
|
||||||
</Layout.Content>
|
|
||||||
)
|
|
@ -1,35 +1,24 @@
|
|||||||
import { Layout, Button } from 'antd'
|
|
||||||
import { UserOutlined } from '@ant-design/icons'
|
|
||||||
import logo from '../images/logo_32.png'
|
|
||||||
import { Link } from 'react-router-dom'
|
import { Link } from 'react-router-dom'
|
||||||
import WellTreeSelector from './WellTreeSelector'
|
import { Layout } from 'antd'
|
||||||
import { headerHeight } from '../utils'
|
import { headerHeight } from '../utils'
|
||||||
|
import { UserMenu } from './UserMenu'
|
||||||
|
import logo from '../images/logo_32.png'
|
||||||
|
|
||||||
const { Header } = Layout
|
type PageHeaderProps = {
|
||||||
|
children?: React.ReactNode
|
||||||
const logoStyle = { height: headerHeight }
|
title?: string
|
||||||
|
|
||||||
const handleLogout = () => {
|
|
||||||
localStorage.removeItem('login')
|
|
||||||
localStorage.removeItem('token')
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type PageHeaderProps = { title?: string }
|
export const PageHeader: React.FC<PageHeaderProps> = ({ children, title = 'Мониторинг' }) => (
|
||||||
|
|
||||||
export const PageHeader = ({ title = 'Мониторинг' }: PageHeaderProps) => (
|
|
||||||
<Layout>
|
<Layout>
|
||||||
<Header className={'header'}>
|
<Layout.Header className={'header'}>
|
||||||
<Link to={'/'} style={logoStyle}>
|
<Link to={'/'} style={{ height: headerHeight }}>
|
||||||
<img src={logo} alt={'АСБ'} className={'logo'}/>
|
<img src={logo} alt={'АСБ'} className={'logo'}/>
|
||||||
</Link>
|
</Link>
|
||||||
<WellTreeSelector />
|
{children}
|
||||||
<h1 className={'title'}>{title}</h1>
|
<h1 className={'title'}>{title}</h1>
|
||||||
<Link to={'/login'} onClick={handleLogout}>
|
<UserMenu />
|
||||||
<Button icon={<UserOutlined/>}>
|
</Layout.Header>
|
||||||
({localStorage['login']}) Выход
|
|
||||||
</Button>
|
|
||||||
</Link>
|
|
||||||
</Header>
|
|
||||||
</Layout>
|
</Layout>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { ReactNode } from 'react'
|
import { ReactNode } from 'react'
|
||||||
import { Table as RawTable } from 'antd'
|
import { Select, Table as RawTable } from 'antd'
|
||||||
|
import { OptionsType } from 'rc-select/lib/interface'
|
||||||
import { tryAddKeys } from './EditableTable'
|
import { tryAddKeys } from './EditableTable'
|
||||||
import { makeNumericSorter, makeStringSorter} from './sorters'
|
import { makeNumericSorter, makeStringSorter} from './sorters'
|
||||||
export { makeDateSorter, makeNumericSorter, makeStringSorter} from './sorters'
|
export { makeDateSorter, makeNumericSorter, makeStringSorter} from './sorters'
|
||||||
@ -25,7 +26,7 @@ export const makeNumericRender = (fixed?: number) => (value: any, row: object):
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const makeNumericColumnOptions = (fixed?:number, sorterKey?:string ) => ({
|
export const makeNumericColumnOptions = (fixed?: number, sorterKey?: string ) => ({
|
||||||
editable: true,
|
editable: true,
|
||||||
initialValue: 0,
|
initialValue: 0,
|
||||||
width:100,
|
width:100,
|
||||||
@ -57,30 +58,36 @@ interface columnPropsOther {
|
|||||||
formItemRules?: any[]
|
formItemRules?: any[]
|
||||||
// дефолтное значение при добавлении новой строки
|
// дефолтное значение при добавлении новой строки
|
||||||
initialValue?: string|number
|
initialValue?: string|number
|
||||||
|
|
||||||
|
render?: (...attributes: any) => any
|
||||||
}
|
}
|
||||||
|
|
||||||
export const makeColumn = (title:string | ReactNode, key:string, other?:columnPropsOther) => ({
|
export const makeColumn = (title: string | ReactNode, key: string, other?: columnPropsOther) => ({
|
||||||
title: title,
|
title: title,
|
||||||
key: key,
|
key: key,
|
||||||
dataIndex: key,
|
dataIndex: key,
|
||||||
...other,
|
...other,
|
||||||
})
|
})
|
||||||
|
|
||||||
export const makeColumnsPlanFact = (title:string | ReactNode, key:string|string[], columsOther?:any|any[], gruopOther?:any) =>
|
export const makeColumnsPlanFact = (
|
||||||
{
|
title:string | ReactNode,
|
||||||
|
key:string | string[],
|
||||||
|
columsOther?: any | any[],
|
||||||
|
gruopOther?: any
|
||||||
|
) => {
|
||||||
let keyPlanLocal = key
|
let keyPlanLocal = key
|
||||||
let keyFactLocal = key
|
let keyFactLocal = key
|
||||||
|
|
||||||
if(key instanceof Array){
|
if (key instanceof Array) {
|
||||||
keyPlanLocal = key[0]
|
keyPlanLocal = key[0]
|
||||||
keyFactLocal = key[1]
|
keyFactLocal = key[1]
|
||||||
}else{
|
} else {
|
||||||
keyPlanLocal = key + 'Plan'
|
keyPlanLocal = key + 'Plan'
|
||||||
keyFactLocal = key + 'Fact'
|
keyFactLocal = key + 'Fact'
|
||||||
}
|
}
|
||||||
|
|
||||||
let columsOtherLoacl :any[2]
|
let columsOtherLoacl : any[2]
|
||||||
if(columsOther instanceof Array)
|
if (columsOther instanceof Array)
|
||||||
columsOtherLoacl = [columsOther[0], columsOther[1]]
|
columsOtherLoacl = [columsOther[0], columsOther[1]]
|
||||||
else
|
else
|
||||||
columsOtherLoacl = [columsOther, columsOther]
|
columsOtherLoacl = [columsOther, columsOther]
|
||||||
@ -109,7 +116,8 @@ export const makeTextColumn = (
|
|||||||
filters: object[],
|
filters: object[],
|
||||||
sorter?: (key: string) => any,
|
sorter?: (key: string) => any,
|
||||||
render?: any,
|
render?: any,
|
||||||
other?: any) => ({
|
other?: any
|
||||||
|
) => ({
|
||||||
title: title,
|
title: title,
|
||||||
dataIndex: dataIndex,
|
dataIndex: dataIndex,
|
||||||
key: dataIndex,
|
key: dataIndex,
|
||||||
@ -120,9 +128,15 @@ export const makeTextColumn = (
|
|||||||
...other
|
...other
|
||||||
})
|
})
|
||||||
|
|
||||||
export const makeNumericColumn = (title: string, dataIndex: string,
|
export const makeNumericColumn = (
|
||||||
filters: object[], filterDelegate: (key: string | number) => any,
|
title: string,
|
||||||
renderDelegate: (_: any, row: object) => any, width: string, other?: columnPropsOther) => ({
|
dataIndex: string,
|
||||||
|
filters: object[],
|
||||||
|
filterDelegate: (key: string | number) => any,
|
||||||
|
renderDelegate: (_: any, row: object) => any,
|
||||||
|
width: string,
|
||||||
|
other?: columnPropsOther
|
||||||
|
) => ({
|
||||||
title: title,
|
title: title,
|
||||||
dataIndex: dataIndex,
|
dataIndex: dataIndex,
|
||||||
key: dataIndex,
|
key: dataIndex,
|
||||||
@ -135,12 +149,17 @@ export const makeNumericColumn = (title: string, dataIndex: string,
|
|||||||
...other
|
...other
|
||||||
})
|
})
|
||||||
|
|
||||||
export const makeNumericColumnPlanFact = (title: string, dataIndex: string, filters: object[],
|
export const makeNumericColumnPlanFact = (
|
||||||
filterDelegate: (key: string | number) => any, renderDelegate: (_: any, row: object) => any, width: string) =>
|
title: string,
|
||||||
makeGroupColumn( title, [
|
dataIndex: string,
|
||||||
|
filters: object[],
|
||||||
|
filterDelegate: (key: string | number) => any,
|
||||||
|
renderDelegate: (_: any, row: object) => any,
|
||||||
|
width: string
|
||||||
|
) => makeGroupColumn(title, [
|
||||||
makeNumericColumn('п', dataIndex + 'Plan', filters, filterDelegate, renderDelegate, width),
|
makeNumericColumn('п', dataIndex + 'Plan', filters, filterDelegate, renderDelegate, width),
|
||||||
makeNumericColumn('ф', dataIndex + 'Fact', filters, filterDelegate, renderDelegate, width),
|
makeNumericColumn('ф', dataIndex + 'Fact', filters, filterDelegate, renderDelegate, width),
|
||||||
])
|
])
|
||||||
|
|
||||||
export const makeNumericStartEnd = (
|
export const makeNumericStartEnd = (
|
||||||
title: string,
|
title: string,
|
||||||
@ -150,7 +169,7 @@ export const makeNumericStartEnd = (
|
|||||||
filterDelegate: (key: string | number) => any,
|
filterDelegate: (key: string | number) => any,
|
||||||
renderDelegate: (_: any, row: object) => any,
|
renderDelegate: (_: any, row: object) => any,
|
||||||
width: string,
|
width: string,
|
||||||
) => makeGroupColumn( title, [
|
) => makeGroupColumn(title, [
|
||||||
makeNumericColumn('старт', dataIndex + 'Start', filters, filterDelegate, renderDelegate, width, makeNumericColumnOptions(fixed, dataIndex + 'Start')),
|
makeNumericColumn('старт', dataIndex + 'Start', filters, filterDelegate, renderDelegate, width, makeNumericColumnOptions(fixed, dataIndex + 'Start')),
|
||||||
makeNumericColumn('конец', dataIndex + 'End', filters, filterDelegate, renderDelegate, width, makeNumericColumnOptions(fixed, dataIndex + 'End'))
|
makeNumericColumn('конец', dataIndex + 'End', filters, filterDelegate, renderDelegate, width, makeNumericColumnOptions(fixed, dataIndex + 'End'))
|
||||||
])
|
])
|
||||||
@ -176,34 +195,43 @@ export const makeNumericAvgRange = (
|
|||||||
filterDelegate: (key: string | number) => any,
|
filterDelegate: (key: string | number) => any,
|
||||||
renderDelegate: (_: any, row: object) => any,
|
renderDelegate: (_: any, row: object) => any,
|
||||||
width: string
|
width: string
|
||||||
) => makeGroupColumn( title, [
|
) => makeGroupColumn(title, [
|
||||||
makeNumericColumn('мин', dataIndex + 'Min', filters, filterDelegate, renderDelegate, width, makeNumericColumnOptions(fixed, dataIndex + 'Min')),
|
makeNumericColumn('мин', dataIndex + 'Min', filters, filterDelegate, renderDelegate, width, makeNumericColumnOptions(fixed, dataIndex + 'Min')),
|
||||||
makeNumericColumn('сред', dataIndex + 'Avg', filters, filterDelegate, renderDelegate, width, makeNumericColumnOptions(fixed, dataIndex + 'Avg')),
|
makeNumericColumn('сред', dataIndex + 'Avg', filters, filterDelegate, renderDelegate, width, makeNumericColumnOptions(fixed, dataIndex + 'Avg')),
|
||||||
makeNumericColumn('макс', dataIndex + 'Max', filters, filterDelegate, renderDelegate, width, makeNumericColumnOptions(fixed, dataIndex + 'Max'))
|
makeNumericColumn('макс', dataIndex + 'Max', filters, filterDelegate, renderDelegate, width, makeNumericColumnOptions(fixed, dataIndex + 'Max'))
|
||||||
])
|
])
|
||||||
|
|
||||||
|
export const makeSelectColumn = <T extends unknown = string>(
|
||||||
|
title: string,
|
||||||
|
dataIndex: string,
|
||||||
|
options: OptionsType,
|
||||||
|
defaultValue?: T,
|
||||||
|
other?: columnPropsOther
|
||||||
|
) => makeColumn(title, dataIndex, {
|
||||||
|
input: <Select options={options}/>,
|
||||||
|
render: (key) => options.find(option => option?.key === key)?.label ?? defaultValue ?? '--',
|
||||||
|
...other
|
||||||
|
})
|
||||||
|
|
||||||
type PaginationContainer = {
|
type PaginationContainer = {
|
||||||
skip?: number;
|
skip?: number
|
||||||
take?: number;
|
take?: number
|
||||||
count?: number;
|
count?: number
|
||||||
items?: any[] | null;
|
items?: any[] | null
|
||||||
}
|
}
|
||||||
|
|
||||||
export const makePaginationObject = (paginationContainer:PaginationContainer, ...other:any) => {
|
export const makePaginationObject = (сontainer: PaginationContainer, ...other: any) => ({
|
||||||
let page = 1 + Math.floor((paginationContainer.skip??0) /(paginationContainer.take??1));
|
|
||||||
return {
|
|
||||||
...other,
|
...other,
|
||||||
pageSize: paginationContainer.take,
|
pageSize: сontainer.take,
|
||||||
total: paginationContainer.count ?? paginationContainer.items?.length ?? 0,
|
total: сontainer.count ?? сontainer.items?.length ?? 0,
|
||||||
current: page,
|
current: 1 + Math.floor((сontainer.skip ?? 0) / (сontainer.take ?? 1))
|
||||||
}
|
})
|
||||||
}
|
|
||||||
|
|
||||||
interface TableContainer {
|
interface TableContainer {
|
||||||
dataSource: any[];
|
dataSource: any[]
|
||||||
children?: any;
|
children?: any
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Table = ({dataSource, children, ...other}: TableContainer) => {
|
export const Table = ({dataSource, children, ...other}: TableContainer) => (
|
||||||
return <RawTable dataSource={tryAddKeys(dataSource)} {...other}>{children}</RawTable>
|
<RawTable dataSource={tryAddKeys(dataSource)} {...other}>{children}</RawTable>
|
||||||
}
|
)
|
||||||
|
88
src/components/UserMenu.tsx
Normal file
88
src/components/UserMenu.tsx
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
import { MouseEventHandler, useState } from 'react'
|
||||||
|
import { Link, useHistory } from 'react-router-dom'
|
||||||
|
import { Button, Dropdown, Menu, Modal, Form, Input, FormProps } from 'antd'
|
||||||
|
import { useForm } from 'antd/lib/form/Form'
|
||||||
|
import { UserOutlined } from '@ant-design/icons'
|
||||||
|
import { AuthService } from '../services/api'
|
||||||
|
import { passwordRules } from '../utils/validationRules'
|
||||||
|
import { invokeWebApiWrapperAsync } from './factory'
|
||||||
|
import { PrivateMenuItem } from './Private'
|
||||||
|
import LoaderPortal from './LoaderPortal'
|
||||||
|
|
||||||
|
const handleLogout = () => {
|
||||||
|
localStorage.removeItem('login')
|
||||||
|
localStorage.removeItem('token')
|
||||||
|
}
|
||||||
|
|
||||||
|
const formLayout: FormProps = { labelCol: { span: 11 }, wrapperCol: { span: 16 } }
|
||||||
|
|
||||||
|
export const UserMenu: React.FC = () => {
|
||||||
|
const [form] = useForm()
|
||||||
|
const [isModalVisible, setIsModalVisible] = useState<boolean>(false)
|
||||||
|
const [showLoader, setShowLoader] = useState<boolean>(false)
|
||||||
|
const [password, setPassword] = useState<string>('')
|
||||||
|
|
||||||
|
const history = useHistory()
|
||||||
|
|
||||||
|
const changePassword = () => invokeWebApiWrapperAsync(
|
||||||
|
async() => {
|
||||||
|
await AuthService.changePassword(localStorage['userId'], `"${password}"`)
|
||||||
|
history.push('/login')
|
||||||
|
},
|
||||||
|
setShowLoader,
|
||||||
|
`Не удалось сменить пароль пользователя ${localStorage['login']}`
|
||||||
|
)
|
||||||
|
|
||||||
|
const onFormCancel = () => {
|
||||||
|
form.resetFields()
|
||||||
|
setIsModalVisible(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
const onChangePasswordClick: MouseEventHandler = (e) => {
|
||||||
|
setIsModalVisible(true)
|
||||||
|
e.preventDefault()
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Dropdown
|
||||||
|
placement={'bottomRight'}
|
||||||
|
overlay={(
|
||||||
|
<Menu style={{ textAlign: 'right' }}>
|
||||||
|
<PrivateMenuItem roles={['admin']}>
|
||||||
|
<Link to={'/admin'} onClick={() => {}}>Панель администратора</Link>
|
||||||
|
</PrivateMenuItem>
|
||||||
|
<Menu.Item>
|
||||||
|
<Link to={'/'} onClick={onChangePasswordClick}>Сменить пароль</Link>
|
||||||
|
</Menu.Item>
|
||||||
|
<Menu.Item>
|
||||||
|
<Link to={'/login'} onClick={handleLogout}>Выход</Link>
|
||||||
|
</Menu.Item>
|
||||||
|
</Menu>
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<Button icon={<UserOutlined/>}>{localStorage['login']}</Button>
|
||||||
|
</Dropdown>
|
||||||
|
<Modal
|
||||||
|
title={'Сменить пароль'}
|
||||||
|
centered
|
||||||
|
visible={isModalVisible}
|
||||||
|
onCancel={onFormCancel}
|
||||||
|
onOk={() => form.submit()}
|
||||||
|
>
|
||||||
|
<LoaderPortal show={showLoader}>
|
||||||
|
<Form
|
||||||
|
{...formLayout}
|
||||||
|
form={form}
|
||||||
|
name={'change-password'}
|
||||||
|
onFinish={changePassword}
|
||||||
|
>
|
||||||
|
<Form.Item label={'Новый пароль'} name={'new-password'} rules={passwordRules}>
|
||||||
|
<Input.Password onChange={(e) => setPassword(e.target.value)} value={password} />
|
||||||
|
</Form.Item>
|
||||||
|
</Form>
|
||||||
|
</LoaderPortal>
|
||||||
|
</Modal>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
89
src/pages/AdminPanel/ClusterController.jsx
Normal file
89
src/pages/AdminPanel/ClusterController.jsx
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
import { useEffect, useState } from 'react'
|
||||||
|
import { useHistory, useParams } from 'react-router'
|
||||||
|
import { invokeWebApiWrapperAsync } from '../../components/factory'
|
||||||
|
import LoaderPortal from '../../components/LoaderPortal'
|
||||||
|
import { EditableTable, makeColumn, makeNumericColumn, makeSelectColumn } from '../../components/Table'
|
||||||
|
import { AdminClusterService, DepositService } from '../../services/api'
|
||||||
|
|
||||||
|
export const ClusterController = () => {
|
||||||
|
const { page } = useParams()
|
||||||
|
const history = useHistory()
|
||||||
|
|
||||||
|
const [deposits, setDeposits] = useState([])
|
||||||
|
const [clusters, setClusters] = useState([])
|
||||||
|
const [pagination, setPagination] = useState({ current: page ?? 1, pageSize: 20 })
|
||||||
|
const [pagintaionTotal, setPagintaionTotal] = useState(0)
|
||||||
|
const [showLoader, setShowLoader] = useState(false)
|
||||||
|
|
||||||
|
const clusterColumns = [
|
||||||
|
makeSelectColumn('Месторождение', 'idDeposit', deposits, '--', { width: 200, editable: true }),
|
||||||
|
makeColumn('Название', 'caption', { width: 200, editable: true }),
|
||||||
|
makeColumn('Описание', 'description', { width: 500, editable: true }),
|
||||||
|
makeNumericColumn('Широта', 'latitude', null, null, null, 150, { editable: true }),
|
||||||
|
makeNumericColumn('Долгота', 'longitude', null, null, null, 150, { editable: true })
|
||||||
|
]
|
||||||
|
|
||||||
|
const updateTable = () => invokeWebApiWrapperAsync(
|
||||||
|
async () => {
|
||||||
|
history.push(`/admin/cluster/${pagination.current}`)
|
||||||
|
const skip = ((pagination.current - 1) * pagination.pageSize) || 0
|
||||||
|
const clusters = await AdminClusterService.getPage(skip, pagination.pageSize)
|
||||||
|
if (!clusters?.items)
|
||||||
|
throw Error(`Не удалось загрузить список кустов`)
|
||||||
|
setClusters(clusters.items)
|
||||||
|
setPagintaionTotal(clusters.count ?? clusters.items.length ?? 0)
|
||||||
|
},
|
||||||
|
setShowLoader,
|
||||||
|
`Не удалось загрузить список кустов`
|
||||||
|
)
|
||||||
|
|
||||||
|
useEffect(() => invokeWebApiWrapperAsync(
|
||||||
|
async () => {
|
||||||
|
let deposits = await DepositService.getDeposits()
|
||||||
|
deposits = deposits?.map((deposit) => ({ key: deposit.id, label: deposit.caption }))
|
||||||
|
setDeposits(deposits ?? [])
|
||||||
|
},
|
||||||
|
setShowLoader,
|
||||||
|
`Не удалось загрузить список месторождений`
|
||||||
|
), [])
|
||||||
|
|
||||||
|
useEffect(updateTable, [pagination, history])
|
||||||
|
|
||||||
|
const onAdd = async (cluster) => {
|
||||||
|
await AdminClusterService.insert(cluster)
|
||||||
|
updateTable()
|
||||||
|
}
|
||||||
|
|
||||||
|
const onEdit = async (cluster) => {
|
||||||
|
if (!cluster.id) return
|
||||||
|
await AdminClusterService.put(cluster.id, cluster)
|
||||||
|
updateTable()
|
||||||
|
}
|
||||||
|
|
||||||
|
const onDelete = async (cluster) => {
|
||||||
|
if (!cluster.id) return
|
||||||
|
await AdminClusterService.delete(cluster.id)
|
||||||
|
updateTable()
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<LoaderPortal show={showLoader}>
|
||||||
|
<EditableTable
|
||||||
|
size={'small'}
|
||||||
|
bordered
|
||||||
|
columns={clusterColumns}
|
||||||
|
dataSource={clusters}
|
||||||
|
onRowAdd={onAdd}
|
||||||
|
onRowEdit={onEdit}
|
||||||
|
onRowDelete={onDelete}
|
||||||
|
pagination={{
|
||||||
|
current: pagination.current,
|
||||||
|
pageSize: pagination.pageSize,
|
||||||
|
total: pagintaionTotal,
|
||||||
|
showSizeChanger: false,
|
||||||
|
onChange: (current, pageSize) => setPagination({ current, pageSize })
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</LoaderPortal>
|
||||||
|
)
|
||||||
|
}
|
75
src/pages/AdminPanel/CompanyController.jsx
Normal file
75
src/pages/AdminPanel/CompanyController.jsx
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
import { useEffect, useState } from 'react'
|
||||||
|
import { useHistory, useParams } from 'react-router'
|
||||||
|
import { invokeWebApiWrapperAsync } from '../../components/factory'
|
||||||
|
import LoaderPortal from '../../components/LoaderPortal'
|
||||||
|
import { EditableTable, makeColumn } from '../../components/Table'
|
||||||
|
import { AdminCompanyService } from '../../services/api'
|
||||||
|
|
||||||
|
const companyColumns = [
|
||||||
|
makeColumn('Название', 'caption', { width: 200, editable: true }),
|
||||||
|
makeColumn('Тип компании', 'companyTypeCaption', { width: 200, editable: true })
|
||||||
|
]
|
||||||
|
|
||||||
|
export const CompanyController = () => {
|
||||||
|
const { page } = useParams()
|
||||||
|
const history = useHistory()
|
||||||
|
|
||||||
|
const [companies, setCompanies] = useState([])
|
||||||
|
const [pagination, setPagination] = useState({current: page ?? 1, pageSize: 20})
|
||||||
|
const [pagintaionTotal, setPagintaionTotal] = useState(0)
|
||||||
|
const [showLoader, setShowLoader] = useState(false)
|
||||||
|
|
||||||
|
const updateTable = () => invokeWebApiWrapperAsync(
|
||||||
|
async() => {
|
||||||
|
history.push(`/admin/company/${pagination.current}`)
|
||||||
|
const skip = ((pagination.current - 1) * pagination.pageSize) || 0
|
||||||
|
const companies = await AdminCompanyService.getPage(skip, pagination.pageSize)
|
||||||
|
if (!companies?.items)
|
||||||
|
throw Error(`Не удалось загрузить список кустов`)
|
||||||
|
setCompanies(companies.items)
|
||||||
|
setPagintaionTotal(companies.count ?? companies.items.length ?? 0)
|
||||||
|
},
|
||||||
|
setShowLoader,
|
||||||
|
`Не удалось загрузить список кустов`
|
||||||
|
)
|
||||||
|
|
||||||
|
useEffect(updateTable, [pagination, history])
|
||||||
|
|
||||||
|
const onAdd = async (company) => {
|
||||||
|
await AdminCompanyService.insert(company)
|
||||||
|
updateTable()
|
||||||
|
}
|
||||||
|
|
||||||
|
const onEdit= async (company) => {
|
||||||
|
if(!company.id) return
|
||||||
|
await AdminCompanyService.put(company.id, company)
|
||||||
|
updateTable()
|
||||||
|
}
|
||||||
|
|
||||||
|
const onDelete= async (company) => {
|
||||||
|
if(!company.id) return
|
||||||
|
await AdminCompanyService.delete(company.id)
|
||||||
|
updateTable()
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<LoaderPortal show={showLoader}>
|
||||||
|
<EditableTable
|
||||||
|
size={'small'}
|
||||||
|
bordered
|
||||||
|
columns={companyColumns}
|
||||||
|
dataSource={companies}
|
||||||
|
onRowAdd={onAdd}
|
||||||
|
onRowEdit={onEdit}
|
||||||
|
onRowDelete={onDelete}
|
||||||
|
pagination={{
|
||||||
|
current: pagination.current,
|
||||||
|
pageSize: pagination.pageSize,
|
||||||
|
total: pagintaionTotal,
|
||||||
|
showSizeChanger: false,
|
||||||
|
onChange: (current, pageSize) => setPagination({ current, pageSize })
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</LoaderPortal>
|
||||||
|
)
|
||||||
|
}
|
77
src/pages/AdminPanel/DepositController.jsx
Normal file
77
src/pages/AdminPanel/DepositController.jsx
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
import { useEffect, useState } from 'react'
|
||||||
|
import { useHistory, useParams } from 'react-router'
|
||||||
|
import { invokeWebApiWrapperAsync } from '../../components/factory'
|
||||||
|
import LoaderPortal from '../../components/LoaderPortal'
|
||||||
|
import { EditableTable, makeColumn, makeNumericColumn } from '../../components/Table'
|
||||||
|
import { AdminDepositService } from '../../services/api'
|
||||||
|
|
||||||
|
const depositColumns = [
|
||||||
|
makeColumn('Название', 'caption', { width: 200, editable: true }),
|
||||||
|
makeColumn('Описание', 'description', { width: 500, editable: true }),
|
||||||
|
makeNumericColumn('Широта', 'latitude', null, null, null, 150, { editable: true }),
|
||||||
|
makeNumericColumn('Долгота', 'longitude', null, null, null, 150, { editable: true })
|
||||||
|
]
|
||||||
|
|
||||||
|
export const DepositController = () => {
|
||||||
|
const { page } = useParams()
|
||||||
|
const history = useHistory()
|
||||||
|
|
||||||
|
const [deposits, setDeposits] = useState([])
|
||||||
|
const [pagination, setPagination] = useState({current: page ?? 1, pageSize: 20})
|
||||||
|
const [pagintaionTotal, setPagintaionTotal] = useState(0)
|
||||||
|
const [showLoader, setShowLoader] = useState(false)
|
||||||
|
|
||||||
|
const updateTable = () => invokeWebApiWrapperAsync(
|
||||||
|
async() => {
|
||||||
|
history.push(`/admin/deposit/${pagination.current}`)
|
||||||
|
const skip = ((pagination.current - 1) * pagination.pageSize) || 0
|
||||||
|
const deposits = await AdminDepositService.getPage(skip, pagination.pageSize)
|
||||||
|
if (!deposits?.items)
|
||||||
|
throw Error(`Не удалось загрузить список месторождении`)
|
||||||
|
setDeposits(deposits.items)
|
||||||
|
setPagintaionTotal(deposits.count ?? deposits.items.length ?? 0)
|
||||||
|
},
|
||||||
|
setShowLoader,
|
||||||
|
`Не удалось загрузить список месторождении`
|
||||||
|
)
|
||||||
|
|
||||||
|
useEffect(updateTable, [pagination, history])
|
||||||
|
|
||||||
|
const onAdd = async (deposit) => {
|
||||||
|
await AdminDepositService.insert(deposit)
|
||||||
|
updateTable()
|
||||||
|
}
|
||||||
|
|
||||||
|
const onEdit= async (deposit) => {
|
||||||
|
if(!deposit.id) return
|
||||||
|
await AdminDepositService.put(deposit.id, deposit)
|
||||||
|
updateTable()
|
||||||
|
}
|
||||||
|
|
||||||
|
const onDelete= async (deposit) => {
|
||||||
|
if(!deposit.id) return
|
||||||
|
await AdminDepositService.delete(deposit.id)
|
||||||
|
updateTable()
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<LoaderPortal show={showLoader}>
|
||||||
|
<EditableTable
|
||||||
|
size={'small'}
|
||||||
|
bordered
|
||||||
|
columns={depositColumns}
|
||||||
|
dataSource={deposits}
|
||||||
|
onRowAdd={onAdd}
|
||||||
|
onRowEdit={onEdit}
|
||||||
|
onRowDelete={onDelete}
|
||||||
|
pagination={{
|
||||||
|
current: pagination.current,
|
||||||
|
pageSize: pagination.pageSize,
|
||||||
|
total: pagintaionTotal,
|
||||||
|
showSizeChanger: false,
|
||||||
|
onChange: (current, pageSize) => setPagination({ current, pageSize })
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</LoaderPortal>
|
||||||
|
)
|
||||||
|
}
|
104
src/pages/AdminPanel/UserController.jsx
Normal file
104
src/pages/AdminPanel/UserController.jsx
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
import { useEffect, useState } from 'react'
|
||||||
|
import { useHistory, useParams } from 'react-router'
|
||||||
|
import { invokeWebApiWrapperAsync } from '../../components/factory'
|
||||||
|
import LoaderPortal from '../../components/LoaderPortal'
|
||||||
|
import { EditableTable, makeColumn, makeSelectColumn } from '../../components/Table'
|
||||||
|
import { AdminCompanyService, AdminUserService } from '../../services/api'
|
||||||
|
import { loginRules, nameRules, phoneRules, emailRules } from '../../utils/validationRules'
|
||||||
|
|
||||||
|
const maxCompaniesCount = 1500
|
||||||
|
|
||||||
|
export const UserController = () => {
|
||||||
|
const { page } = useParams()
|
||||||
|
const history = useHistory()
|
||||||
|
|
||||||
|
const [companies, setCompanies] = useState([])
|
||||||
|
const [users, setUsers] = useState([])
|
||||||
|
const [pagination, setPagination] = useState({current: page ?? 1, pageSize: 20})
|
||||||
|
const [pagintaionTotal, setPagintaionTotal] = useState(0)
|
||||||
|
const [showLoader, setShowLoader] = useState(false)
|
||||||
|
|
||||||
|
const userColumns = [
|
||||||
|
makeColumn('Логин', 'login', {
|
||||||
|
editable: true,
|
||||||
|
formItemRules: [{ required: true }, ...loginRules]
|
||||||
|
}),
|
||||||
|
makeColumn('Фамилия', 'surname', {
|
||||||
|
editable: true,
|
||||||
|
formItemRules: [{ required: true }, ...nameRules]
|
||||||
|
}),
|
||||||
|
makeColumn('Имя', 'name', { editable: true, formItemRules: nameRules }),
|
||||||
|
makeColumn('Отчество', 'patronymic', { editable: true, formItemRules: nameRules }),
|
||||||
|
makeColumn('E-mail', 'email', {
|
||||||
|
editable: true,
|
||||||
|
formItemRules: [{ required: true }, ...emailRules]
|
||||||
|
}),
|
||||||
|
makeColumn('Номер телефона', 'phone', { editable: true, formItemRules: phoneRules }),
|
||||||
|
makeColumn('Должность', 'position', { editable: true }),
|
||||||
|
makeSelectColumn('Компания', 'idCompany', companies, '--', { editable: true })
|
||||||
|
]
|
||||||
|
|
||||||
|
const updateTable = () => invokeWebApiWrapperAsync(
|
||||||
|
async() => {
|
||||||
|
history.push(`/admin/user/${pagination.current}`)
|
||||||
|
const skip = ((pagination.current - 1) * pagination.pageSize) || 0
|
||||||
|
const users = await AdminUserService.getPage(skip, pagination.pageSize)
|
||||||
|
if (!users?.items)
|
||||||
|
throw Error(`Не удалось загрузить список пользователей`)
|
||||||
|
setUsers(users.items)
|
||||||
|
setPagintaionTotal(users.count ?? users.items.length ?? 0)
|
||||||
|
},
|
||||||
|
setShowLoader,
|
||||||
|
`Не удалось загрузить список пользователей`
|
||||||
|
)
|
||||||
|
|
||||||
|
useEffect(() => invokeWebApiWrapperAsync(
|
||||||
|
async () => {
|
||||||
|
let companies = await AdminCompanyService.getPage(0, maxCompaniesCount)
|
||||||
|
companies = companies?.map((company) => ({ key: company.id, label: company.caption }))
|
||||||
|
setCompanies(companies?.items ?? [])
|
||||||
|
},
|
||||||
|
setShowLoader,
|
||||||
|
`Не удалось загрузить список компаний`
|
||||||
|
), [])
|
||||||
|
|
||||||
|
useEffect(updateTable, [pagination, history])
|
||||||
|
|
||||||
|
const onAdd = async (user) => {
|
||||||
|
await AdminUserService.insert(user)
|
||||||
|
updateTable()
|
||||||
|
}
|
||||||
|
|
||||||
|
const onEdit = async (user) => {
|
||||||
|
if(!user.id) return
|
||||||
|
await AdminUserService.put(user.id, user)
|
||||||
|
updateTable()
|
||||||
|
}
|
||||||
|
|
||||||
|
const onDelete = async (user) => {
|
||||||
|
if(!user.id) return
|
||||||
|
await AdminUserService.delete(user.id)
|
||||||
|
updateTable()
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<LoaderPortal show={showLoader}>
|
||||||
|
<EditableTable
|
||||||
|
size={'small'}
|
||||||
|
bordered
|
||||||
|
columns={userColumns}
|
||||||
|
dataSource={users}
|
||||||
|
onRowAdd={onAdd}
|
||||||
|
onRowEdit={onEdit}
|
||||||
|
onRowDelete={onDelete}
|
||||||
|
pagination={{
|
||||||
|
current: pagination.current,
|
||||||
|
pageSize: pagination.pageSize,
|
||||||
|
total: pagintaionTotal,
|
||||||
|
showSizeChanger: false,
|
||||||
|
onChange: (current, pageSize) => setPagination({ current, pageSize })
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</LoaderPortal>
|
||||||
|
)
|
||||||
|
}
|
89
src/pages/AdminPanel/WellController.jsx
Normal file
89
src/pages/AdminPanel/WellController.jsx
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
import { useEffect, useState } from 'react'
|
||||||
|
import { useHistory, useParams } from 'react-router'
|
||||||
|
import { invokeWebApiWrapperAsync } from '../../components/factory'
|
||||||
|
import LoaderPortal from '../../components/LoaderPortal'
|
||||||
|
import { EditableTable, makeColumn, makeNumericColumn, makeSelectColumn } from '../../components/Table'
|
||||||
|
import { AdminWellService, ClusterService } from '../../services/api'
|
||||||
|
|
||||||
|
export const WellController = () => {
|
||||||
|
const { page } = useParams()
|
||||||
|
const history = useHistory()
|
||||||
|
|
||||||
|
const [clusters, setClusters] = useState([])
|
||||||
|
const [wells, setWells] = useState([])
|
||||||
|
const [pagination, setPagination] = useState({ current: page ?? 1, pageSize: 20 })
|
||||||
|
const [pagintaionTotal, setPagintaionTotal] = useState(0)
|
||||||
|
const [showLoader, setShowLoader] = useState(false)
|
||||||
|
|
||||||
|
const wellColumns = [
|
||||||
|
makeSelectColumn('Куст', 'idCluster', clusters, '--', { width: 200 , editable: true }),
|
||||||
|
makeColumn('Название', 'caption', { width: 200, editable: true }),
|
||||||
|
makeColumn('Описание', 'description', { width: 500, editable: true }),
|
||||||
|
makeNumericColumn('Широта', 'latitude', null, null, null, 150, { editable: true }),
|
||||||
|
makeNumericColumn('Долгота', 'longitude', null, null, null, 150, { editable: true })
|
||||||
|
]
|
||||||
|
|
||||||
|
const updateTable = () => invokeWebApiWrapperAsync(
|
||||||
|
async () => {
|
||||||
|
history.push(`/admin/well/${pagination.current}`)
|
||||||
|
const skip = ((pagination.current - 1) * pagination.pageSize) || 0
|
||||||
|
const wells = await AdminWellService.getPage(skip, pagination.pageSize)
|
||||||
|
if (!wells?.items)
|
||||||
|
throw Error(`Не удалось загрузить список скважин`)
|
||||||
|
setWells(wells.items)
|
||||||
|
setPagintaionTotal(wells.count ?? wells.items.length ?? 0)
|
||||||
|
},
|
||||||
|
setShowLoader,
|
||||||
|
`Не удалось загрузить список скважин`
|
||||||
|
)
|
||||||
|
|
||||||
|
useEffect(() => invokeWebApiWrapperAsync(
|
||||||
|
async () => {
|
||||||
|
let clusters = await ClusterService.getClusters()
|
||||||
|
clusters = clusters?.map((cluster) => ({ key: cluster.id, label: cluster.caption }))
|
||||||
|
setClusters(clusters ?? [])
|
||||||
|
},
|
||||||
|
setShowLoader,
|
||||||
|
`Не удалось загрузить список кустов`
|
||||||
|
), [])
|
||||||
|
|
||||||
|
useEffect(updateTable, [pagination, history])
|
||||||
|
|
||||||
|
const onAdd = async (well) => {
|
||||||
|
await AdminWellService.insert(well)
|
||||||
|
updateTable()
|
||||||
|
}
|
||||||
|
|
||||||
|
const onEdit = async (well) => {
|
||||||
|
if (!well.id) return
|
||||||
|
await AdminWellService.put(well.id, well)
|
||||||
|
updateTable()
|
||||||
|
}
|
||||||
|
|
||||||
|
const onDelete = async (well) => {
|
||||||
|
if (!well.id) return
|
||||||
|
await AdminWellService.delete(well.id)
|
||||||
|
updateTable()
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<LoaderPortal show={showLoader}>
|
||||||
|
<EditableTable
|
||||||
|
size={'small'}
|
||||||
|
bordered
|
||||||
|
columns={wellColumns}
|
||||||
|
dataSource={wells}
|
||||||
|
onRowAdd={onAdd}
|
||||||
|
onRowEdit={onEdit}
|
||||||
|
onRowDelete={onDelete}
|
||||||
|
pagination={{
|
||||||
|
current: pagination.current,
|
||||||
|
pageSize: pagination.pageSize,
|
||||||
|
total: pagintaionTotal,
|
||||||
|
showSizeChanger: false,
|
||||||
|
onChange: (current, pageSize) => setPagination({ current, pageSize })
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</LoaderPortal>
|
||||||
|
)
|
||||||
|
}
|
66
src/pages/AdminPanel/index.jsx
Normal file
66
src/pages/AdminPanel/index.jsx
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
import { Layout, Menu } from 'antd'
|
||||||
|
import { Switch, Link, useParams, Redirect, Route } from 'react-router-dom'
|
||||||
|
import { PrivateMenuItem, PrivateRoute } from '../../components/Private'
|
||||||
|
import { ClusterController } from './ClusterController'
|
||||||
|
import { CompanyController } from './CompanyController'
|
||||||
|
import { DepositController } from './DepositController'
|
||||||
|
import { UserController } from './UserController'
|
||||||
|
import { WellController } from './WellController'
|
||||||
|
|
||||||
|
export const AdminPanel = () => {
|
||||||
|
const { tab } = useParams()
|
||||||
|
const rootPath = '/admin'
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Layout>
|
||||||
|
<Menu
|
||||||
|
mode={'horizontal'}
|
||||||
|
selectable={true}
|
||||||
|
selectedKeys={[tab]}
|
||||||
|
>
|
||||||
|
<PrivateMenuItem roles={['deposit_admin']} key={'deposit'}>
|
||||||
|
<Link to={`${rootPath}/deposit`}>Управление месторождениями</Link>
|
||||||
|
</PrivateMenuItem>
|
||||||
|
<PrivateMenuItem roles={['cluster_admin']} key={'cluster'}>
|
||||||
|
<Link to={`${rootPath}/cluster`}>Управление кустами</Link>
|
||||||
|
</PrivateMenuItem>
|
||||||
|
<PrivateMenuItem roles={['well_admin']} key={'well'}>
|
||||||
|
<Link to={`${rootPath}/well`}>Управление скважинами</Link>
|
||||||
|
</PrivateMenuItem>
|
||||||
|
<PrivateMenuItem roles={['user_admin']} key={'user'}>
|
||||||
|
<Link to={`${rootPath}/user`}>Управление пользователями</Link>
|
||||||
|
</PrivateMenuItem>
|
||||||
|
<PrivateMenuItem roles={['company_admin']} key={'company'}>
|
||||||
|
<Link to={`${rootPath}/company`}>Управление компаниями</Link>
|
||||||
|
</PrivateMenuItem>
|
||||||
|
</Menu>
|
||||||
|
|
||||||
|
<Layout>
|
||||||
|
<Layout.Content className={'site-layout-background'}>
|
||||||
|
<Switch>
|
||||||
|
<PrivateRoute roles={['deposit_admin']} path={`${rootPath}/deposit/:page?`}>
|
||||||
|
<DepositController />
|
||||||
|
</PrivateRoute>
|
||||||
|
<PrivateRoute roles={['cluster_admin']} path={`${rootPath}/cluster/:page?`}>
|
||||||
|
<ClusterController />
|
||||||
|
</PrivateRoute>
|
||||||
|
<PrivateRoute roles={['well_admin']} path={`${rootPath}/well/:page?`}>
|
||||||
|
<WellController />
|
||||||
|
</PrivateRoute>
|
||||||
|
<PrivateRoute roles={['user_admin']} path={`${rootPath}/user/:page?`}>
|
||||||
|
<UserController />
|
||||||
|
</PrivateRoute>
|
||||||
|
<PrivateRoute roles={['company_admin']} path={`${rootPath}/company/:page?`}>
|
||||||
|
<CompanyController />
|
||||||
|
</PrivateRoute>
|
||||||
|
<Route path={'/'}>
|
||||||
|
<Redirect to={`${rootPath}/deposit`}/>
|
||||||
|
</Route>
|
||||||
|
</Switch>
|
||||||
|
</Layout.Content>
|
||||||
|
</Layout>
|
||||||
|
</Layout>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default AdminPanel
|
@ -1,30 +1,37 @@
|
|||||||
import { Redirect, Route, Switch } from "react-router-dom";
|
import { Redirect, Route, Switch } from 'react-router-dom'
|
||||||
import Deposit from "./Deposit";
|
import { PrivateRoute } from '../components/Private'
|
||||||
import Cluster from "./Cluster";
|
import { AdminLayoutPortal, LayoutPortal } from '../components/Layout'
|
||||||
import Well from "./Well";
|
import Deposit from './Deposit'
|
||||||
import {LayoutPortal} from "../components/LayoutPortal";
|
import Cluster from './Cluster'
|
||||||
|
import Well from './Well'
|
||||||
|
import AdminPanel from './AdminPanel'
|
||||||
|
|
||||||
export default function Main() {
|
export const Main = () => (
|
||||||
return (
|
|
||||||
<Switch>
|
<Switch>
|
||||||
<Route path="/deposit">
|
<PrivateRoute path={'/admin/:tab?'} roles={['admin']}>
|
||||||
|
<AdminLayoutPortal title={'Администраторская панель'}>
|
||||||
|
<AdminPanel />
|
||||||
|
</AdminLayoutPortal>
|
||||||
|
</PrivateRoute>
|
||||||
|
<Route path={'/deposit'}>
|
||||||
<LayoutPortal noSheet title='Месторождение'>
|
<LayoutPortal noSheet title='Месторождение'>
|
||||||
<Deposit />
|
<Deposit />
|
||||||
</LayoutPortal>
|
</LayoutPortal>
|
||||||
</Route>
|
</Route>
|
||||||
<Route path="/cluster/:idClaster/:tab?">
|
<Route path={'/cluster/:idClaster/:tab?'}>
|
||||||
<LayoutPortal title="Анализ скважин куста">
|
<LayoutPortal title={'Анализ скважин куста'}>
|
||||||
<Cluster />
|
<Cluster />
|
||||||
</LayoutPortal>
|
</LayoutPortal>
|
||||||
</Route>
|
</Route>
|
||||||
<Route path="/well/:idWell/:tab?">
|
<Route path={'/well/:idWell/:tab?'}>
|
||||||
<LayoutPortal>
|
<LayoutPortal>
|
||||||
<Well />
|
<Well />
|
||||||
</LayoutPortal>
|
</LayoutPortal>
|
||||||
</Route>
|
</Route>
|
||||||
<Route path="/">
|
<Route path={'/'}>
|
||||||
<Redirect to={{ pathname: `/deposit` }} />
|
<Redirect to={{ pathname: `/deposit` }} />
|
||||||
</Route>
|
</Route>
|
||||||
</Switch>
|
</Switch>
|
||||||
);
|
)
|
||||||
}
|
|
||||||
|
export default Main
|
||||||
|
Loading…
Reference in New Issue
Block a user