ConceptPortal-public/rsconcept/frontend/src/features/library/components/editor-library-item.tsx

156 lines
5.3 KiB
TypeScript
Raw Normal View History

import { Suspense } from 'react';
2024-05-27 20:42:34 +03:00
import { useIntl } from 'react-intl';
import { urls, useConceptNavigation } from '@/app';
2025-02-26 00:16:41 +03:00
import { useLabelUser, useRoleStore, UserRole } from '@/features/users';
import { InfoUsers, SelectUser } from '@/features/users/components';
2025-02-12 21:36:25 +03:00
2025-03-12 12:04:50 +03:00
import { Tooltip } from '@/components/container';
import { MiniButton } from '@/components/control';
import { useDropdown } from '@/components/dropdown';
2024-09-15 21:19:17 +03:00
import {
IconDateCreate,
IconDateUpdate,
IconEditor,
IconFolderEdit,
IconFolderOpened,
IconOwner
2025-03-12 12:04:50 +03:00
} from '@/components/icons';
import { Loader } from '@/components/loader';
import { ValueIcon } from '@/components/view';
import { useDialogsStore } from '@/stores/dialogs';
import { useModificationStore } from '@/stores/modification';
2024-05-27 20:42:34 +03:00
import { prefixes } from '@/utils/constants';
import { promptText } from '@/utils/labels';
2024-05-27 20:42:34 +03:00
import { type ILibraryItemData } from '../backend/types';
2025-03-12 11:55:43 +03:00
import { useMutatingLibrary } from '../backend/use-mutating-library';
import { useSetLocation } from '../backend/use-set-location';
import { useSetOwner } from '../backend/use-set-owner';
import { useLibrarySearchStore } from '../stores/library-search';
interface EditorLibraryItemProps {
2025-02-12 15:13:37 +03:00
schema: ILibraryItemData;
isAttachedToOSS: boolean;
}
export function EditorLibraryItem({ schema, isAttachedToOSS }: EditorLibraryItemProps) {
const getUserLabel = useLabelUser();
2025-01-15 23:03:35 +03:00
const role = useRoleStore(state => state.role);
2024-05-27 20:42:34 +03:00
const intl = useIntl();
2024-09-15 21:19:17 +03:00
const router = useConceptNavigation();
const setGlobalLocation = useLibrarySearchStore(state => state.setLocation);
const isProcessing = useMutatingLibrary();
const { isModified } = useModificationStore();
const { setOwner } = useSetOwner();
const { setLocation } = useSetLocation();
const showEditEditors = useDialogsStore(state => state.showEditEditors);
const showEditLocation = useDialogsStore(state => state.showChangeLocation);
2024-05-27 20:42:34 +03:00
const ownerSelector = useDropdown();
2025-02-12 13:07:55 +03:00
const onSelectUser = function (newValue: number) {
ownerSelector.hide();
if (newValue === schema.owner) {
return;
}
if (!window.confirm(promptText.ownerChange)) {
return;
}
void setOwner({ itemID: schema.id, owner: newValue });
};
2024-05-27 20:42:34 +03:00
2025-02-22 14:04:01 +03:00
function handleOpenLibrary(event: React.MouseEvent<Element>) {
setGlobalLocation(schema.location);
router.push({ path: urls.library, newTab: event.ctrlKey || event.metaKey });
}
function handleEditLocation() {
showEditLocation({
initial: schema.location,
onChangeLocation: newLocation => void setLocation({ itemID: schema.id, location: newLocation })
});
}
function handleEditEditors() {
showEditEditors({
itemID: schema.id,
initialEditors: schema.editors
});
}
2024-09-15 21:19:17 +03:00
2024-05-27 20:42:34 +03:00
return (
<div className='flex flex-col'>
2025-03-09 21:59:21 +03:00
<div className='relative flex justify-stretch sm:mb-1 max-w-120 gap-3'>
2024-09-15 21:19:17 +03:00
<MiniButton
2025-03-20 11:33:42 +03:00
title='Открыть в библиотеке'
2024-09-15 21:19:17 +03:00
noHover
noPadding
icon={<IconFolderOpened size='1.25rem' className='icon-primary' />}
onClick={handleOpenLibrary}
/>
<ValueIcon
className='text-ellipsis grow'
2024-09-15 21:19:17 +03:00
icon={<IconFolderEdit size='1.25rem' className='icon-primary' />}
value={schema.location}
title={isAttachedToOSS ? 'Путь наследуется от ОСС' : 'Путь'}
onClick={handleEditLocation}
disabled={isModified || isProcessing || isAttachedToOSS || role < UserRole.OWNER}
2024-09-15 21:19:17 +03:00
/>
</div>
2025-03-07 20:38:40 +03:00
<div className='relative'>
{ownerSelector.isOpen ? (
2025-03-09 21:59:21 +03:00
<div className='absolute -top-2 right-0'>
<SelectUser className='w-100 text-sm' value={schema.owner} onChange={onSelectUser} />
2025-03-07 20:38:40 +03:00
</div>
) : null}
<ValueIcon
className='sm:mb-1'
icon={<IconOwner size='1.25rem' className='icon-primary' />}
value={getUserLabel(schema.owner)}
title={isAttachedToOSS ? 'Владелец наследуется от ОСС' : 'Владелец'}
onClick={ownerSelector.toggle}
disabled={isModified || isProcessing || isAttachedToOSS || role < UserRole.OWNER}
/>
</div>
2024-05-27 20:42:34 +03:00
2024-08-21 21:36:29 +03:00
<div className='sm:mb-1 flex justify-between items-center'>
2024-08-23 12:35:48 +03:00
<ValueIcon
2024-08-21 21:36:29 +03:00
id='editor_stats'
dense
icon={<IconEditor size='1.25rem' className='icon-primary' />}
value={schema.editors.length}
onClick={handleEditEditors}
disabled={isModified || isProcessing || role < UserRole.OWNER}
2024-08-21 21:36:29 +03:00
/>
2025-03-07 20:38:40 +03:00
<Tooltip anchorSelect='#editor_stats'>
<Suspense fallback={<Loader scale={2} />}>
<InfoUsers items={schema.editors} prefix={prefixes.user_editors} header='Редакторы' />
</Suspense>
2024-08-21 21:36:29 +03:00
</Tooltip>
2024-08-23 12:35:48 +03:00
<ValueIcon
2025-03-20 14:42:01 +03:00
title='Дата обновления'
2024-08-21 21:36:29 +03:00
dense
icon={<IconDateUpdate size='1.25rem' className='text-ok-600' />}
value={new Date(schema.time_update).toLocaleString(intl.locale)}
2024-08-21 21:36:29 +03:00
/>
2024-08-23 12:35:48 +03:00
<ValueIcon
2025-03-20 14:42:01 +03:00
title='Дата создания'
2024-08-21 21:36:29 +03:00
dense
icon={<IconDateCreate size='1.25rem' className='text-ok-600' />}
value={new Date(schema.time_create).toLocaleString(intl.locale, {
2024-08-21 21:36:29 +03:00
year: '2-digit',
month: '2-digit',
day: '2-digit'
})}
/>
</div>
2024-05-27 20:42:34 +03:00
</div>
);
}