forked from ddrilling/asb_cloud_front
Добавлено View для роли
Добавлен столбец роли на страницу admin/user Проверка уникальности логина отключена до исправления Добавлена кнопка дублирования скважины
This commit is contained in:
parent
e084727c72
commit
f228b64a6f
@ -209,34 +209,42 @@ export const makeSelectColumn = <T extends unknown = string>(
|
||||
other?: columnPropsOther,
|
||||
selectOther?: SelectProps<SelectValue>
|
||||
) => makeColumn(title, dataIndex, {
|
||||
...other,
|
||||
input: <Select options={options} {...selectOther}/>,
|
||||
render: (value) => options?.find(option => option?.value === value)?.label ?? defaultValue ?? value ?? '--',
|
||||
...other
|
||||
render: (value) => {
|
||||
const item = options?.find(option => option?.value === value)
|
||||
return other?.render?.(item?.value) ?? item?.label ?? defaultValue ?? value ?? '--'
|
||||
}
|
||||
})
|
||||
|
||||
const makeTagInput = <T extends Record<string, any>>(id_key: string, value_key: string) => memo<{
|
||||
const makeTagInput = <T extends Record<string, any>>(value_key: string, label_key: string) => memo<{
|
||||
options: T[],
|
||||
value?: T[],
|
||||
onChange?: (values: T[]) => void
|
||||
}>(({ options, value, onChange }) => {
|
||||
const [selectOptions, setSelectOptions] = useState<OptionsType>([])
|
||||
const [selectedValue, setSelectedValue] = useState<SelectValue>([])
|
||||
|
||||
useEffect(() => {
|
||||
setSelectOptions(options.map((elm) => ({
|
||||
value: elm[id_key],
|
||||
label: elm[value_key]
|
||||
value: String(elm[value_key]),
|
||||
label: elm[label_key],
|
||||
})))
|
||||
}, [options])
|
||||
|
||||
useEffect(() => {
|
||||
setSelectedValue(value?.map((elm) => String(elm[value_key])) ?? [])
|
||||
}, [value])
|
||||
|
||||
const onSelectChange = (rawValues?: SelectValue) => {
|
||||
let values: string[] = []
|
||||
let values: any[] = []
|
||||
if (typeof rawValues === 'string')
|
||||
values = rawValues.split(',')
|
||||
else if (typeof rawValues === 'number')
|
||||
values = [`${rawValues}`]
|
||||
else if (Array.isArray(rawValues))
|
||||
values = rawValues
|
||||
|
||||
const objectValues: T[] = values.reduce((out: T[], id: string) => {
|
||||
const res = options.find((option) => `${option[id_key]}` === id)
|
||||
const objectValues: T[] = values.reduce((out: T[], value: string) => {
|
||||
const res = options.find((option) => String(option[value_key]) === String(value))
|
||||
if (res) out.push(res)
|
||||
return out
|
||||
}, [])
|
||||
@ -248,7 +256,7 @@ const makeTagInput = <T extends Record<string, any>>(id_key: string, value_key:
|
||||
<Select
|
||||
mode={'tags'}
|
||||
options={selectOptions}
|
||||
value={value?.join(',')}
|
||||
value={selectedValue}
|
||||
onChange={onSelectChange}
|
||||
/>
|
||||
)
|
||||
@ -266,7 +274,7 @@ export const makeTagColumn = <T extends Record<string, any>>(
|
||||
|
||||
return makeColumn(title, dataIndex, {
|
||||
...other,
|
||||
render: (item?: T[]) => item?.map((elm: T) => <Tag key={elm[label_key]} color='blue'>{elm[label_key]}</Tag>) ?? '-',
|
||||
render: (item?: T[]) => item?.map((elm: T) => <Tag key={elm[label_key]} color={'blue'}>{other?.render?.(elm) ?? elm[label_key]}</Tag>) ?? '-',
|
||||
input: <InputComponent options={options} />,
|
||||
})
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { memo } from 'react'
|
||||
import { Tooltip } from 'antd'
|
||||
import { BankOutlined } from '@ant-design/icons'
|
||||
|
||||
import { CompanyDto } from '../../services/api'
|
||||
import { Grid, GridItem } from '../Grid'
|
||||
|
||||
@ -11,7 +12,7 @@ export type CompanyViewProps = {
|
||||
export const CompanyView = memo<CompanyViewProps>(({ company }) => company ? (
|
||||
<Tooltip title={
|
||||
<Grid style={{ columnGap: '8px' }}>
|
||||
<GridItem row={1} col={1}>тип:</GridItem>
|
||||
<GridItem row={1} col={1}>Тип:</GridItem>
|
||||
<GridItem row={1} col={2}>{company?.companyTypeCaption}</GridItem>
|
||||
</Grid>
|
||||
}>
|
||||
|
42
src/components/Views/RoleView.tsx
Normal file
42
src/components/Views/RoleView.tsx
Normal file
@ -0,0 +1,42 @@
|
||||
import { memo } from 'react'
|
||||
import { Tag, Tooltip } from 'antd'
|
||||
|
||||
import { UserRoleDto } from '../../services/api'
|
||||
import { Grid, GridItem } from '../Grid'
|
||||
import PermissionView from './PermissionView'
|
||||
|
||||
export type RoleViewProps = {
|
||||
role?: UserRoleDto
|
||||
parentRole?: UserRoleDto
|
||||
}
|
||||
|
||||
export const RoleView = memo<RoleViewProps>(({ role, parentRole }) => role ? (
|
||||
<Tooltip
|
||||
overlayInnerStyle={{ width: '400px' }}
|
||||
title={
|
||||
<Grid>
|
||||
<GridItem row={1} col={1}>Название:</GridItem>
|
||||
<GridItem row={1} col={2}>{role.caption}</GridItem>
|
||||
|
||||
<GridItem row={2} col={1}>Роль-родитель:</GridItem>
|
||||
<GridItem row={2} col={2}>{parentRole?.caption ?? 'Отсутствует'}</GridItem>
|
||||
|
||||
<GridItem row={3} col={1}>Тип:</GridItem>
|
||||
<GridItem row={3} col={2}>{role.idType}</GridItem>
|
||||
|
||||
<GridItem row={4} col={1}>Разрешения:</GridItem>
|
||||
<GridItem row={5} col={1} colSpan={3}>
|
||||
{role.permissions?.map((permission, i) => (
|
||||
<Tag key={i} color={'blue'}>
|
||||
<PermissionView info={permission} />
|
||||
</Tag>
|
||||
)) ?? '-'}
|
||||
</GridItem>
|
||||
</Grid>
|
||||
}
|
||||
>
|
||||
{role.caption}
|
||||
</Tooltip>
|
||||
) : (
|
||||
<Tooltip title={'нет данных'}>-</Tooltip>
|
||||
))
|
@ -3,7 +3,7 @@ import { Tooltip } from 'antd'
|
||||
import { TelemetryDto, TelemetryInfoDto } from '../../services/api'
|
||||
import { Grid, GridItem } from '../Grid'
|
||||
|
||||
const lables: { [labelKey: string]: string } = {
|
||||
const lables: Record<string, string> = {
|
||||
timeZoneId: 'Временная зона',
|
||||
timeZoneOffsetTotalHours: 'Сдвиг временной зоны',
|
||||
drillingStartDate: 'Начало бурения',
|
||||
|
@ -3,6 +3,7 @@ import { Tooltip } from 'antd'
|
||||
import { UserOutlined } from '@ant-design/icons'
|
||||
import { UserDto } from '../../services/api'
|
||||
import { Grid, GridItem } from '../Grid'
|
||||
import { CompanyView } from './CompanyView'
|
||||
|
||||
export type UserViewProps = {
|
||||
user?: UserDto
|
||||
@ -21,7 +22,9 @@ export const UserView = memo<UserViewProps>(({ user }) => user ? (
|
||||
<GridItem row={3} col={2}>{user?.patronymic}</GridItem>
|
||||
|
||||
<GridItem row={4} col={1}>Компания:</GridItem>
|
||||
<GridItem row={4} col={2}>{user?.company?.caption}</GridItem>
|
||||
<GridItem row={4} col={2}>
|
||||
<CompanyView company={user?.company}/>
|
||||
</GridItem>
|
||||
</Grid>
|
||||
)}>
|
||||
<UserOutlined style={{ marginRight: 8 }}/>
|
||||
|
@ -1,11 +1,13 @@
|
||||
export type { CompanyViewProps } from './CompanyView'
|
||||
export type { MarkViewProps } from './MarkView'
|
||||
export type { PermissionViewProps } from './PermissionView'
|
||||
export type { TelemetryViewProps } from './TelemetryView'
|
||||
export type { CompanyViewProps } from './CompanyView'
|
||||
export type { MarkViewProps } from './MarkView'
|
||||
export type { RoleViewProps } from './RoleView'
|
||||
export type { UserViewProps } from './UserView'
|
||||
|
||||
export { CompanyView } from './CompanyView'
|
||||
export { MarkView } from './MarkView'
|
||||
export { PermissionView } from './PermissionView'
|
||||
export { TelemetryView, getTelemetryLabel } from './TelemetryView'
|
||||
export { CompanyView } from './CompanyView'
|
||||
export { MarkView } from './MarkView'
|
||||
export { RoleView } from './RoleView'
|
||||
export { UserView } from './UserView'
|
@ -1,41 +1,13 @@
|
||||
import { Select, Tag } from 'antd'
|
||||
import { memo, useEffect, useState } from 'react'
|
||||
|
||||
import LoaderPortal from '../../components/LoaderPortal'
|
||||
import { PermissionView } from '../../components/Views'
|
||||
import { invokeWebApiWrapperAsync } from '../../components/factory'
|
||||
import { EditableTable, makeActionHandler, makeColumn, makeSelectColumn } from '../../components/Table'
|
||||
import { EditableTable, makeActionHandler, makeColumn, makeSelectColumn, makeTagColumn } from '../../components/Table'
|
||||
import { AdminPermissionService, AdminUserRoleService } from '../../services/api'
|
||||
import { arrayOrDefault } from '../../utils'
|
||||
|
||||
const PermissionTag = memo(({ permissions, value, onChange }) => {
|
||||
const [options, setOptions] = useState([])
|
||||
|
||||
useEffect(() => {
|
||||
setOptions(permissions.map((elm) => ({ key: Date.now(), value: `${elm.id}`, label: elm.name })))
|
||||
}, [permissions])
|
||||
|
||||
console.log({ permissions, value })
|
||||
|
||||
const onSelectChange = (values) => {
|
||||
const arr = values.map((id) => permissions.find((elm) => `${elm.id}` === id))
|
||||
onChange?.(arr)
|
||||
}
|
||||
|
||||
const selectValue = value?.map((val) => `${val.id}`)
|
||||
|
||||
return (
|
||||
<Select
|
||||
showSearch
|
||||
mode={'tags'}
|
||||
options={options}
|
||||
value={selectValue}
|
||||
onChange={onSelectChange}
|
||||
/>
|
||||
)
|
||||
})
|
||||
|
||||
export const RoleController = () => {
|
||||
export const RoleController = memo(() => {
|
||||
const [permissions, setPermissions] = useState([])
|
||||
const [roles, setRoles] = useState([])
|
||||
const [showLoader, setShowLoader] = useState(false)
|
||||
@ -54,15 +26,10 @@ export const RoleController = () => {
|
||||
width: 200,
|
||||
editable: true
|
||||
}, { allowClear: true }),
|
||||
makeColumn('Права доступа', 'permissions', {
|
||||
makeTagColumn('Права доступа', 'permissions', permissions, 'id', 'name', {
|
||||
width: 200,
|
||||
editable: true,
|
||||
input: <PermissionTag permissions={permissions} />,
|
||||
render: (item) => item?.map((elm) => (
|
||||
<Tag key={elm.name} color={'blue'}>
|
||||
<PermissionView info={elm} />
|
||||
</Tag>
|
||||
)) ?? '-',
|
||||
render: (permission) => <PermissionView info={permission} />,
|
||||
}),
|
||||
])
|
||||
}, [roles, permissions])
|
||||
@ -101,6 +68,6 @@ export const RoleController = () => {
|
||||
/>
|
||||
</LoaderPortal>
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
export default RoleController
|
||||
|
@ -1,13 +1,47 @@
|
||||
import { useEffect, useState } from 'react'
|
||||
import { Button, Select, Tag } from 'antd'
|
||||
import { UserSwitchOutlined } from '@ant-design/icons'
|
||||
import { invokeWebApiWrapperAsync } from '../../components/factory'
|
||||
import { memo, useEffect, useState } from 'react'
|
||||
|
||||
import { RoleView } from '../../components/Views'
|
||||
import LoaderPortal from '../../components/LoaderPortal'
|
||||
import { EditableTable, makeColumn, makeSelectColumn, makeActionHandler, makeStringSorter, makeNumericSorter } from '../../components/Table'
|
||||
import { AdminCompanyService, AdminUserService } from '../../services/api'
|
||||
import { ChangePassword } from '../../components/ChangePassword'
|
||||
import { invokeWebApiWrapperAsync } from '../../components/factory'
|
||||
import {
|
||||
EditableTable,
|
||||
makeColumn,
|
||||
makeSelectColumn,
|
||||
makeActionHandler,
|
||||
makeStringSorter,
|
||||
makeNumericSorter
|
||||
} from '../../components/Table'
|
||||
import { AdminCompanyService, AdminUserRoleService, AdminUserService } from '../../services/api'
|
||||
import { createLoginRules, nameRules, phoneRules, emailRules } from '../../utils/validationRules'
|
||||
import { arrayOrDefault } from '../../utils'
|
||||
import { Button } from 'antd'
|
||||
import { ChangePassword } from '../../components/ChangePassword'
|
||||
|
||||
const RoleTag = memo(({ roles, value, onChange }) => {
|
||||
const [options, setOptions] = useState([])
|
||||
|
||||
useEffect(() => {
|
||||
setOptions(roles.map((elm) => ({
|
||||
key: Date.now(),
|
||||
value: `${elm.caption}`,
|
||||
label: elm.caption
|
||||
})))
|
||||
}, [roles])
|
||||
|
||||
console.log(value)
|
||||
|
||||
return (
|
||||
<Select
|
||||
allowClear
|
||||
showSearch
|
||||
mode={'tags'}
|
||||
options={options}
|
||||
value={value ?? []}
|
||||
onChange={onChange}
|
||||
/>
|
||||
)
|
||||
})
|
||||
|
||||
export default function UserController() {
|
||||
const [users, setUsers] = useState([])
|
||||
@ -35,25 +69,30 @@ export default function UserController() {
|
||||
|
||||
useEffect(() => invokeWebApiWrapperAsync(
|
||||
async () => {
|
||||
let companies = arrayOrDefault(await AdminCompanyService.getAll())
|
||||
companies = companies?.map((company) => ({ value: company.id, label: company.caption }))
|
||||
const roles = arrayOrDefault(await AdminUserRoleService.getAll())
|
||||
const companies = arrayOrDefault(await AdminCompanyService.getAll()).map((company) => ({
|
||||
value: company.id,
|
||||
label: company.caption
|
||||
}))
|
||||
|
||||
const users = arrayOrDefault(await AdminUserService.getAll())
|
||||
setUsers(users)
|
||||
|
||||
|
||||
setColumns([
|
||||
makeColumn('Логин', 'login', {
|
||||
editable: true,
|
||||
formItemRules: [
|
||||
{ required: true },
|
||||
...createLoginRules,
|
||||
() => ({
|
||||
validator(_, value) {
|
||||
if (!value || users.findIndex((user) => user.login === value) < 0)
|
||||
return Promise.resolve()
|
||||
return Promise.reject(new Error('Логин уже занят!'))
|
||||
}
|
||||
})
|
||||
// () => ({
|
||||
// validator(_, value) {
|
||||
// if (!value || users.findIndex((user) => user.login === value) < 0)
|
||||
// return Promise.resolve()
|
||||
// return Promise.reject(new Error('Логин уже занят!'))
|
||||
// }
|
||||
// })
|
||||
// TODO: Для проверки уникальности логина необходимо исключить из выборки логин выбранного пользователя
|
||||
],
|
||||
sorter: makeStringSorter('login'),
|
||||
}),
|
||||
@ -86,10 +125,19 @@ export default function UserController() {
|
||||
editable: true,
|
||||
sorter: makeStringSorter('position'),
|
||||
}),
|
||||
makeColumn('Роли', 'roleNames', {
|
||||
editable: true,
|
||||
input: <RoleTag roles={roles} />,
|
||||
render: (item) => item?.map((elm) => (
|
||||
<Tag key={elm} color={'blue'}>
|
||||
<RoleView role={roles.find((role) => role.caption === elm)} />
|
||||
</Tag>
|
||||
)) ?? '-'
|
||||
}),
|
||||
makeSelectColumn('Компания', 'idCompany', companies, '--', {
|
||||
editable: true,
|
||||
sorter: makeNumericSorter('idCompany'),
|
||||
}),
|
||||
})
|
||||
])
|
||||
},
|
||||
setShowLoader,
|
||||
@ -114,7 +162,7 @@ export default function UserController() {
|
||||
onRowAdd={makeActionHandler('insert', handlerProps)}
|
||||
onRowEdit={makeActionHandler('update', handlerProps)}
|
||||
onRowDelete={makeActionHandler('delete', handlerProps)}
|
||||
additionalButtons={additionalButtons}
|
||||
// additionalButtons={additionalButtons}
|
||||
buttonsWidth={120}
|
||||
pagination={{ defaultPageSize: 14 }}
|
||||
/>
|
||||
|
@ -1,9 +1,10 @@
|
||||
import { Select } from 'antd'
|
||||
import { Button, Select } from 'antd'
|
||||
import { ForkOutlined } from '@ant-design/icons'
|
||||
import { memo, useEffect, useState } from 'react'
|
||||
|
||||
import LoaderPortal from '../../components/LoaderPortal'
|
||||
import { invokeWebApiWrapperAsync } from '../../components/factory'
|
||||
import { TelemetryView, getTelemetryLabel } from '../../components/Views'
|
||||
import { TelemetryView, getTelemetryLabel, CompanyView } from '../../components/Views'
|
||||
import {
|
||||
EditableTable,
|
||||
makeColumn,
|
||||
@ -11,13 +12,13 @@ import {
|
||||
makeActionHandler,
|
||||
makeStringSorter,
|
||||
makeNumericSorter,
|
||||
makeTagColumn
|
||||
makeTagColumn,
|
||||
} from '../../components/Table'
|
||||
import {
|
||||
AdminClusterService,
|
||||
AdminCompanyService,
|
||||
AdminTelemetryService,
|
||||
AdminWellService
|
||||
AdminWellService,
|
||||
} from '../../services/api'
|
||||
import { arrayOrDefault } from '../../utils'
|
||||
|
||||
@ -58,12 +59,27 @@ export default function WellController() {
|
||||
`Не удалось загрузить список скважин`
|
||||
)
|
||||
|
||||
const duplicateWell = (well) => {
|
||||
// TODO: Метод дубликации скважины
|
||||
}
|
||||
|
||||
const addititonalButtons = (record, editingKey) => (
|
||||
<Button
|
||||
icon={<ForkOutlined />}
|
||||
title={'Дублировать скважину'}
|
||||
disabled={(editingKey ?? '') !== ''}
|
||||
onClick={() => duplicateWell(record)}
|
||||
/>
|
||||
)
|
||||
|
||||
useEffect(() => invokeWebApiWrapperAsync(
|
||||
async () => {
|
||||
const companies = arrayOrDefault(await AdminCompanyService.getAll())
|
||||
const telemetry = arrayOrDefault(await AdminTelemetryService.getAll())
|
||||
let clusters = arrayOrDefault(await AdminClusterService.getAll())
|
||||
clusters = clusters.map((cluster) => ({ value: cluster.id, label: cluster.caption }))
|
||||
const clusters = arrayOrDefault(await AdminClusterService.getAll()).map((cluster) => ({
|
||||
value: cluster.id,
|
||||
label: cluster.caption
|
||||
}))
|
||||
|
||||
setColumns([
|
||||
makeSelectColumn('Куст', 'idCluster', clusters, '--', {
|
||||
@ -90,7 +106,9 @@ export default function WellController() {
|
||||
input: <TelemetrySelect telemetry={telemetry}/>,
|
||||
}),
|
||||
makeTagColumn('Компании', 'companies', companies, 'id', 'caption', {
|
||||
width: 400
|
||||
width: 400,
|
||||
editable: true,
|
||||
render: (company) => <CompanyView company={company} />,
|
||||
}),
|
||||
])
|
||||
|
||||
@ -117,6 +135,8 @@ export default function WellController() {
|
||||
onRowAdd={makeActionHandler('insert', handlerProps)}
|
||||
onRowEdit={makeActionHandler('update', handlerProps)}
|
||||
onRowDelete={makeActionHandler('delete', handlerProps)}
|
||||
additionalButtons={addititonalButtons}
|
||||
buttonsWidth={95}
|
||||
/>
|
||||
</LoaderPortal>
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user