Отображение списков тегов обновлено

This commit is contained in:
goodmice 2022-12-27 19:04:02 +05:00
parent cbbe992966
commit 1e31f2f2c1
No known key found for this signature in database
GPG Key ID: EA4AA16454AC96C8
6 changed files with 56 additions and 32 deletions

View File

@ -1,7 +1,8 @@
import { memo, ReactNode, useCallback, useEffect, useState } from 'react' import { memo, ReactNode, useCallback, useEffect, useState } from 'react'
import { DefaultOptionType, SelectValue } from 'antd/lib/select' import { DefaultOptionType, SelectValue } from 'antd/lib/select'
import { Select, SelectProps, Tag } from 'antd' import { Select, SelectProps } from 'antd'
import TagList from '@components/TagList'
import type { OmitExtends } from '@utils/types' import type { OmitExtends } from '@utils/types'
import { ColumnProps, DataType, makeColumn } from '.' import { ColumnProps, DataType, makeColumn } from '.'
@ -67,7 +68,9 @@ export const makeTagColumn = <T extends DataType>(
return makeColumn(title, dataIndex, { return makeColumn(title, dataIndex, {
editable: true, editable: true,
...other, ...other,
render: (item: T[] | undefined, dataset, index) => item?.map((elm: T) => <Tag key={elm[label_key]} color={'blue'}>{other?.render?.(elm, dataset, index) ?? elm[label_key]}</Tag>) ?? '-', render: (item: T[] | undefined, dataset, index) => (
<TagList items={item} render={(elm) => other?.render?.(elm, dataset, index) ?? elm[label_key]} />
),
input: <InputComponent {...tagOther} options={options} />, input: <InputComponent {...tagOther} options={options} />,
}) })
} }

View File

@ -0,0 +1,25 @@
import { memo, ReactNode } from 'react'
import { Tag } from 'antd'
import '@styles/components/tag_list.less'
export type TagListProps<T> = {
items?: T[] | null
render: (item: T) => ReactNode
}
const _TagList = <T,>({ items, render }: TagListProps<T>) => {
if (!items || items.length <= 0) return <>-</>
return (
<div className={'dd-tag-list'}>
{items.map((item, i) => (
<Tag key={`${i}`}>{render(item)}</Tag>
))}
</div>
)
}
export const TagList = memo(_TagList) as typeof _TagList
export default TagList

View File

@ -1,9 +1,10 @@
import { memo } from 'react' import { memo } from 'react'
import { Tag, Tooltip } from 'antd' import { Tooltip } from 'antd'
import { UserRoleDto } from '@api' import { UserRoleDto } from '@api'
import { Grid, GridItem } from '@components/Grid' import { Grid, GridItem } from '@components/Grid'
import PermissionView from './PermissionView' import PermissionView from './PermissionView'
import TagList from '../TagList'
export type RoleViewProps = { export type RoleViewProps = {
role?: UserRoleDto role?: UserRoleDto
@ -26,12 +27,8 @@ export const RoleView = memo<RoleViewProps>(({ role }) => {
<GridItem row={2} col={1}>Включённые роли:</GridItem> <GridItem row={2} col={1}>Включённые роли:</GridItem>
{hasIncludedRoles ? ( {hasIncludedRoles ? (
<GridItem row={3} col={1} colSpan={3}> <GridItem row={3} col={1} colSpan={3} style={{ display: 'flex', flexWrap: 'wrap', gap: 5 }}>
{role.roles?.map((role, i) => ( <TagList items={role.roles} render={(role) => <RoleView role={role} />} />
<Tag key={i} color={'blue'}>
<RoleView role={role} />
</Tag>
))}
</GridItem> </GridItem>
) : ( ) : (
<GridItem row={2} col={2}>Отсутствуют</GridItem> <GridItem row={2} col={2}>Отсутствуют</GridItem>
@ -42,12 +39,8 @@ export const RoleView = memo<RoleViewProps>(({ role }) => {
<GridItem row={4 + hasIncludedRoles} col={1}>Разрешения:</GridItem> <GridItem row={4 + hasIncludedRoles} col={1}>Разрешения:</GridItem>
{hasPermissions ? ( {hasPermissions ? (
<GridItem row={5 + hasIncludedRoles} col={1} colSpan={3}> <GridItem row={5 + hasIncludedRoles} col={1} colSpan={3} style={{ display: 'flex', flexWrap: 'wrap', gap: 5 }}>
{role.permissions?.map((permission, i) => ( <TagList items={role.permissions} render={(permission) => <PermissionView info={permission} />} />
<Tag key={i} color={'blue'}>
<PermissionView info={permission} />
</Tag>
))}
</GridItem> </GridItem>
) : ( ) : (
<GridItem row={4 + hasIncludedRoles} col={2}>Отсутствуют</GridItem> <GridItem row={4 + hasIncludedRoles} col={2}>Отсутствуют</GridItem>

View File

@ -18,15 +18,13 @@ export const TelemetryInfo = memo(({ info, danger, ...other }) => (
bordered bordered
column={1} column={1}
size={'small'} size={'small'}
style={{ background: 'white' }}
className={'telemetry_merger_info'}
{...other} {...other}
> >
{Object.keys({ ...lables, ...info }).map(key => ( {Object.keys({ ...lables, ...info }).map(key => (
<Item <Item
key={key} key={key}
label={lables[key] ?? key} label={lables[key] ?? key}
style={{ color: danger === true || danger?.includes(key) ? 'red' : 'black' }} style={{ color: danger === true || danger?.includes(key) ? 'red' : '#ddd' }}
>{info?.[key] ?? '-'}</Item> >{info?.[key] ?? '-'}</Item>
))} ))}
</Descriptions> </Descriptions>

View File

@ -1,4 +1,4 @@
import { Button, Input, Tag } from 'antd' import { Button, Input } from 'antd'
import { UserSwitchOutlined } from '@ant-design/icons' import { UserSwitchOutlined } from '@ant-design/icons'
import { memo, useCallback, useEffect, useMemo, useState } from 'react' import { memo, useCallback, useEffect, useMemo, useState } from 'react'
import { BehaviorSubject, debounceTime, distinctUntilChanged, filter, map } from 'rxjs' import { BehaviorSubject, debounceTime, distinctUntilChanged, filter, map } from 'rxjs'
@ -20,6 +20,7 @@ import { makeTextOnFilter, makeTextFilters, makeArrayOnFilter } from '@utils/fil
import { arrayOrDefault, withPermissions } from '@utils' import { arrayOrDefault, withPermissions } from '@utils'
import RoleTag from './RoleTag' import RoleTag from './RoleTag'
import TagList from '@components/TagList'
const SEARCH_TIMEOUT = 400 const SEARCH_TIMEOUT = 400
@ -107,25 +108,20 @@ const UserController = memo(() => {
const filters = makeTextFilters(users, ['surname', 'name', 'patronymic', 'email']) const filters = makeTextFilters(users, ['surname', 'name', 'patronymic', 'email'])
const roleFilters = [{ text: 'Без роли', value: null }, ...roles.map((role) => ({ text: role.caption, value: role.caption }))] const roleFilters = [{ text: 'Без роли', value: null }, ...roles.map((role) => ({ text: role.caption, value: role.caption }))]
const rolesRender = (item) => item?.map((elm) => ( const rolesRender = (item) => (
<Tag key={elm} color={'blue'}> <TagList
items={item}
render={(elm) => (
<RoleView role={roles.find((role) => role.caption === elm)} /> <RoleView role={roles.find((role) => role.caption === elm)} />
</Tag> )}
)) ?? '-' />
)
setColumns([ setColumns([
makeTextColumn('Логин', 'login', null, null, null, { makeTextColumn('Логин', 'login', null, null, null, {
formItemRules: [ formItemRules: [
{ required: true }, { required: true },
...createLoginRules, ...createLoginRules,
// () => ({
// validator(_, value) {
// if (!value || users.findIndex((user) => user.login === value) < 0)
// return Promise.resolve()
// return Promise.reject(new Error('Логин уже занят!'))
// }
// })
// TODO: Для проверки уникальности логина необходимо исключить из выборки логин выбранного пользователя
], ],
}), }),
makeTextColumn('Фамилия', 'surname', filters.surname, null, null, { makeTextColumn('Фамилия', 'surname', filters.surname, null, null, {

View File

@ -0,0 +1,9 @@
.dd-tag-list {
display: flex;
flex-wrap: wrap;
gap: 5px;
& > .ant-tag {
margin-right: 0;
}
}