M: Improve LibraryItem editor

This commit is contained in:
Ivan 2024-08-21 21:36:02 +03:00
parent 96db927c71
commit 87bdf9f2e6
4 changed files with 113 additions and 66 deletions

View File

@ -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';

View File

@ -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>
); );
} }

View 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;

View File

@ -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'> {ownerSelector.isOpen ? (
<MiniButton <SelectUser
title={controller.isAttachedToOSS ? 'Владелец наследуется от ОСС' : 'Изменить владельца'} className='w-[26.5rem] sm:w-[27.5rem] text-sm'
noHover items={users}
onClick={() => ownerSelector.toggle()} value={item.owner ?? undefined}
icon={<IconEdit size='1rem' className='mt-1 icon-primary' />} onSelectValue={onSelectUser}
disabled={isModified || controller.isProcessing || controller.isAttachedToOSS}
/> />
{ownerSelector.isOpen ? ( ) : null}
<SelectUser
className='w-[21rem] sm:w-[23rem] text-sm'
items={users}
value={item?.owner ?? undefined}
onSelectValue={onSelectUser}
/>
) : 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} <Tooltip anchorSelect='#editor_stats' layer='z-modalTooltip'>
<LabeledValue <InfoUsers items={item?.editors ?? []} prefix={prefixes.user_editors} />
id='editor_stats' // </Tooltip>
className='sm:mb-1'
label='Редакторы'
text={item?.editors.length ?? 0}
/>
<Tooltip anchorSelect='#editor_stats' layer='z-modalTooltip'>
<InfoUsers items={item?.editors ?? []} prefix={prefixes.user_editors} />
</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)}
<LabeledValue label='Дата создания' text={item ? new Date(item?.time_create).toLocaleString(intl.locale) : ''} /> title='Дата обновления'
/>
<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>
); );
} }