mirror of
https://github.com/IRBorisov/ConceptPortal.git
synced 2025-06-26 13:00:39 +03:00
M: Improve LibraryItem editor
This commit is contained in:
parent
9b87120b1e
commit
6a1a4b8543
|
@ -49,6 +49,8 @@ export { BiChevronLeft as IconPageLeft } from 'react-icons/bi';
|
||||||
export { BiChevronRight as IconPageRight } from 'react-icons/bi';
|
export { BiChevronRight as IconPageRight } from 'react-icons/bi';
|
||||||
export { BiFirstPage as IconPageFirst } from 'react-icons/bi';
|
export { BiFirstPage as IconPageFirst } from 'react-icons/bi';
|
||||||
export { BiLastPage as IconPageLast } from 'react-icons/bi';
|
export { BiLastPage as IconPageLast } from 'react-icons/bi';
|
||||||
|
export { TbCalendarPlus as IconDateCreate } from 'react-icons/tb';
|
||||||
|
export { TbCalendarRepeat as IconDateUpdate } from 'react-icons/tb';
|
||||||
|
|
||||||
// ==== User status =======
|
// ==== User status =======
|
||||||
export { LuUserCircle2 as IconUser } from 'react-icons/lu';
|
export { LuUserCircle2 as IconUser } from 'react-icons/lu';
|
||||||
|
|
|
@ -18,6 +18,7 @@ function InfoUsers({ items, className, prefix, ...restProps }: InfoUsersProps) {
|
||||||
{items.map((user, index) => (
|
{items.map((user, index) => (
|
||||||
<div key={`${prefix}${index}`}>{getUserLabel(user)}</div>
|
<div key={`${prefix}${index}`}>{getUserLabel(user)}</div>
|
||||||
))}
|
))}
|
||||||
|
{items.length === 0 ? <div className='text-center'>Пользователи не выбраны</div> : null}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
48
rsconcept/frontend/src/components/ui/IconValue.tsx
Normal file
48
rsconcept/frontend/src/components/ui/IconValue.tsx
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
import clsx from 'clsx';
|
||||||
|
|
||||||
|
import { CProps } from '../props';
|
||||||
|
import MiniButton from './MiniButton';
|
||||||
|
|
||||||
|
interface IconValueProps extends CProps.Styling, CProps.Titled {
|
||||||
|
id?: string;
|
||||||
|
icon: React.ReactNode;
|
||||||
|
value: string | number;
|
||||||
|
onClick?: (event: CProps.EventMouse) => void;
|
||||||
|
dense?: boolean;
|
||||||
|
disabled?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
function IconValue({
|
||||||
|
id,
|
||||||
|
dense,
|
||||||
|
value,
|
||||||
|
icon,
|
||||||
|
disabled = true,
|
||||||
|
title,
|
||||||
|
titleHtml,
|
||||||
|
hideTitle,
|
||||||
|
className,
|
||||||
|
onClick,
|
||||||
|
...restProps
|
||||||
|
}: IconValueProps) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={clsx('flex items-center', { 'justify-between gap-6 text-right': !dense, 'gap-2': dense }, className)}
|
||||||
|
{...restProps}
|
||||||
|
>
|
||||||
|
<MiniButton
|
||||||
|
noHover
|
||||||
|
noPadding
|
||||||
|
title={title}
|
||||||
|
titleHtml={titleHtml}
|
||||||
|
hideTitle={hideTitle}
|
||||||
|
icon={icon}
|
||||||
|
disabled={disabled}
|
||||||
|
onClick={onClick}
|
||||||
|
/>
|
||||||
|
<span id={id}>{value}</span>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default IconValue;
|
|
@ -1,11 +1,10 @@
|
||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
import { useIntl } from 'react-intl';
|
import { useIntl } from 'react-intl';
|
||||||
|
|
||||||
import { IconEdit } from '@/components/Icons';
|
import { IconDateCreate, IconDateUpdate, IconEditor, IconFolder, IconOwner } from '@/components/Icons';
|
||||||
import InfoUsers from '@/components/info/InfoUsers';
|
import InfoUsers from '@/components/info/InfoUsers';
|
||||||
import SelectUser from '@/components/select/SelectUser';
|
import SelectUser from '@/components/select/SelectUser';
|
||||||
import LabeledValue from '@/components/ui/LabeledValue';
|
import IconValue from '@/components/ui/IconValue';
|
||||||
import MiniButton from '@/components/ui/MiniButton';
|
|
||||||
import Overlay from '@/components/ui/Overlay';
|
import Overlay from '@/components/ui/Overlay';
|
||||||
import Tooltip from '@/components/ui/Tooltip';
|
import Tooltip from '@/components/ui/Tooltip';
|
||||||
import { useAccessMode } from '@/context/AccessModeContext';
|
import { useAccessMode } from '@/context/AccessModeContext';
|
||||||
|
@ -42,79 +41,76 @@ function EditorLibraryItem({ item, isModified, controller }: EditorLibraryItemPr
|
||||||
[controller, item?.owner, ownerSelector]
|
[controller, item?.owner, ownerSelector]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (!item) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='flex flex-col'>
|
<div className='flex flex-col'>
|
||||||
{accessLevel >= UserLevel.OWNER ? (
|
<IconValue
|
||||||
<Overlay position='top-[-0.5rem] left-[2.3rem] cc-icons'>
|
className='sm:mb-1 text-ellipsis max-w-[30rem]'
|
||||||
<MiniButton
|
icon={<IconFolder size='1.25rem' className='icon-primary' />}
|
||||||
title={controller.isAttachedToOSS ? 'Путь наследуется от ОСС' : 'Изменить путь'}
|
value={item.location}
|
||||||
noHover
|
title={controller.isAttachedToOSS ? 'Путь наследуется от ОСС' : 'Путь'}
|
||||||
onClick={() => controller.promptLocation()}
|
onClick={controller.promptLocation}
|
||||||
icon={<IconEdit size='1rem' className='mt-1 icon-primary' />}
|
disabled={isModified || controller.isProcessing || controller.isAttachedToOSS || accessLevel < UserLevel.OWNER}
|
||||||
disabled={isModified || controller.isProcessing || controller.isAttachedToOSS}
|
|
||||||
/>
|
|
||||||
</Overlay>
|
|
||||||
) : null}
|
|
||||||
<LabeledValue
|
|
||||||
className='max-w-[30rem] sm:mb-1 text-ellipsis' //
|
|
||||||
label='Путь'
|
|
||||||
text={item?.location ?? ''}
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{accessLevel >= UserLevel.OWNER ? (
|
{ownerSelector.isOpen ? (
|
||||||
<Overlay position='top-[-0.5rem] left-[5.5rem] cc-icons'>
|
<Overlay position='top-[-0.5rem] left-[2.5rem] cc-icons'>
|
||||||
<div className='flex items-start'>
|
|
||||||
<MiniButton
|
|
||||||
title={controller.isAttachedToOSS ? 'Владелец наследуется от ОСС' : 'Изменить владельца'}
|
|
||||||
noHover
|
|
||||||
onClick={() => ownerSelector.toggle()}
|
|
||||||
icon={<IconEdit size='1rem' className='mt-1 icon-primary' />}
|
|
||||||
disabled={isModified || controller.isProcessing || controller.isAttachedToOSS}
|
|
||||||
/>
|
|
||||||
{ownerSelector.isOpen ? (
|
{ownerSelector.isOpen ? (
|
||||||
<SelectUser
|
<SelectUser
|
||||||
className='w-[21rem] sm:w-[23rem] text-sm'
|
className='w-[26.5rem] sm:w-[27.5rem] text-sm'
|
||||||
items={users}
|
items={users}
|
||||||
value={item?.owner ?? undefined}
|
value={item.owner ?? undefined}
|
||||||
onSelectValue={onSelectUser}
|
onSelectValue={onSelectUser}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
</div>
|
|
||||||
</Overlay>
|
</Overlay>
|
||||||
) : null}
|
) : null}
|
||||||
<LabeledValue
|
<IconValue
|
||||||
className='sm:mb-1' //
|
className='sm:mb-1'
|
||||||
label='Владелец'
|
icon={<IconOwner size='1.25rem' className='icon-primary' />}
|
||||||
text={getUserLabel(item?.owner ?? null)}
|
value={getUserLabel(item.owner)}
|
||||||
|
title={controller.isAttachedToOSS ? 'Владелец наследуется от ОСС' : 'Владелец'}
|
||||||
|
onClick={ownerSelector.toggle}
|
||||||
|
disabled={isModified || controller.isProcessing || controller.isAttachedToOSS || accessLevel < UserLevel.OWNER}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{accessLevel >= UserLevel.OWNER ? (
|
<div className='sm:mb-1 flex justify-between items-center'>
|
||||||
<Overlay position='top-[-0.5rem] left-[5.5rem]' className='cc-icons'>
|
<IconValue
|
||||||
<MiniButton
|
id='editor_stats'
|
||||||
title='Изменить редакторов'
|
dense
|
||||||
noHover
|
icon={<IconEditor size='1.25rem' className='icon-primary' />}
|
||||||
onClick={() => controller.promptEditors()}
|
value={item.editors.length}
|
||||||
icon={<IconEdit size='1rem' className='mt-1 icon-primary' />}
|
title='Редакторы'
|
||||||
disabled={isModified || controller.isProcessing}
|
onClick={controller.promptEditors}
|
||||||
/>
|
disabled={isModified || controller.isProcessing || accessLevel < UserLevel.OWNER}
|
||||||
</Overlay>
|
|
||||||
) : null}
|
|
||||||
<LabeledValue
|
|
||||||
id='editor_stats' //
|
|
||||||
className='sm:mb-1'
|
|
||||||
label='Редакторы'
|
|
||||||
text={item?.editors.length ?? 0}
|
|
||||||
/>
|
/>
|
||||||
<Tooltip anchorSelect='#editor_stats' layer='z-modalTooltip'>
|
<Tooltip anchorSelect='#editor_stats' layer='z-modalTooltip'>
|
||||||
<InfoUsers items={item?.editors ?? []} prefix={prefixes.user_editors} />
|
<InfoUsers items={item?.editors ?? []} prefix={prefixes.user_editors} />
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
|
||||||
<LabeledValue
|
<IconValue
|
||||||
className='sm:mb-1'
|
dense
|
||||||
label='Дата обновления'
|
disabled
|
||||||
text={item ? new Date(item?.time_update).toLocaleString(intl.locale) : ''}
|
icon={<IconDateUpdate size='1.25rem' className='clr-text-green' />}
|
||||||
|
value={new Date(item.time_update).toLocaleString(intl.locale)}
|
||||||
|
title='Дата обновления'
|
||||||
/>
|
/>
|
||||||
<LabeledValue label='Дата создания' text={item ? new Date(item?.time_create).toLocaleString(intl.locale) : ''} />
|
|
||||||
|
<IconValue
|
||||||
|
dense
|
||||||
|
disabled
|
||||||
|
icon={<IconDateCreate size='1.25rem' className='clr-text-green' />}
|
||||||
|
value={new Date(item.time_create).toLocaleString(intl.locale, {
|
||||||
|
year: '2-digit',
|
||||||
|
month: '2-digit',
|
||||||
|
day: '2-digit'
|
||||||
|
})}
|
||||||
|
title='Дата создания'
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user