Portal/rsconcept/frontend/src/features/library/components/EditorLibraryItem.tsx

172 lines
5.8 KiB
TypeScript
Raw Normal View History

2025-01-26 22:24:34 +03:00
import { Suspense } from 'react';
2024-06-07 20:17:03 +03:00
import { useIntl } from 'react-intl';
import { urls, useConceptNavigation } from '@/app';
2025-02-12 21:36:03 +03:00
import { InfoUsers, SelectUser, useLabelUser, useRoleStore, UserRole } from '@/features/users';
import { Overlay, Tooltip } from '@/components/Container';
import { MiniButton } from '@/components/Control';
import { useDropdown } from '@/components/Dropdown';
2024-09-15 21:18:32 +03:00
import {
IconDateCreate,
IconDateUpdate,
IconEditor,
IconFolderEdit,
IconFolderOpened,
IconOwner
} from '@/components/Icons';
import { Loader } from '@/components/Loader';
2024-09-15 21:18:32 +03:00
import { CProps } from '@/components/props';
import { ValueIcon } from '@/components/View';
2025-01-26 22:24:34 +03:00
import { useDialogsStore } from '@/stores/dialogs';
import { useModificationStore } from '@/stores/modification';
2024-06-07 20:17:03 +03:00
import { prefixes } from '@/utils/constants';
import { promptText } from '@/utils/labels';
2024-06-07 20:17:03 +03:00
2025-02-18 19:39:54 +03:00
import { ILibraryItemData } from '../backend/types';
import { useMutatingLibrary } from '../backend/useMutatingLibrary';
import { useSetLocation } from '../backend/useSetLocation';
import { useSetOwner } from '../backend/useSetOwner';
import { useLibrarySearchStore } from '../stores/librarySearch';
2025-02-12 15:12:59 +03:00
/**
* Represents common {@link ILibraryItem} editor controller.
*/
export interface ILibraryItemEditor {
schema: ILibraryItemData;
deleteSchema: () => void;
isMutable: boolean;
isAttachedToOSS: boolean;
}
2024-06-07 20:17:03 +03:00
interface EditorLibraryItemProps {
controller: ILibraryItemEditor;
}
export function EditorLibraryItem({ controller }: EditorLibraryItemProps) {
2025-01-21 12:00:09 +03:00
const getUserLabel = useLabelUser();
2025-01-15 23:03:23 +03:00
const role = useRoleStore(state => state.role);
2024-06-07 20:17:03 +03:00
const intl = useIntl();
2024-09-15 21:18:32 +03:00
const router = useConceptNavigation();
2025-01-26 22:24:34 +03:00
const setGlobalLocation = useLibrarySearchStore(state => state.setLocation);
const isProcessing = useMutatingLibrary();
2025-01-26 22:24:34 +03:00
const { isModified } = useModificationStore();
const { setOwner } = useSetOwner();
const { setLocation } = useSetLocation();
const showEditEditors = useDialogsStore(state => state.showEditEditors);
const showEditLocation = useDialogsStore(state => state.showChangeLocation);
2024-06-07 20:17:03 +03:00
const ownerSelector = useDropdown();
2025-02-12 13:07:26 +03:00
const onSelectUser = function (newValue: number) {
2025-01-26 22:24:34 +03:00
ownerSelector.hide();
if (newValue === controller.schema.owner) {
2025-01-26 22:24:34 +03:00
return;
}
if (!window.confirm(promptText.ownerChange)) {
2025-01-26 22:24:34 +03:00
return;
}
2025-02-11 20:56:11 +03:00
void setOwner({ itemID: controller.schema.id, owner: newValue });
2025-01-26 22:24:34 +03:00
};
2024-06-07 20:17:03 +03:00
2025-01-26 22:24:34 +03:00
function handleOpenLibrary(event: CProps.EventMouse) {
setGlobalLocation(controller.schema.location);
2025-01-26 22:24:34 +03:00
router.push(urls.library, event.ctrlKey || event.metaKey);
}
function handleEditLocation() {
showEditLocation({
initial: controller.schema.location,
2025-02-11 20:56:11 +03:00
onChangeLocation: newLocation => void setLocation({ itemID: controller.schema.id, location: newLocation })
2025-01-26 22:24:34 +03:00
});
}
function handleEditEditors() {
showEditEditors({
itemID: controller.schema.id,
2025-02-12 13:07:26 +03:00
initialEditors: controller.schema.editors
2025-01-26 22:24:34 +03:00
});
}
2024-09-15 21:18:32 +03:00
2024-06-07 20:17:03 +03:00
return (
<div className='flex flex-col'>
2024-09-15 21:18:32 +03:00
<div className='flex justify-stretch sm:mb-1 max-w-[30rem] gap-3'>
<MiniButton
noHover
noPadding
title='Открыть в библиотеке'
icon={<IconFolderOpened size='1.25rem' className='icon-primary' />}
onClick={handleOpenLibrary}
/>
<ValueIcon
className='text-ellipsis flex-grow'
icon={<IconFolderEdit size='1.25rem' className='icon-primary' />}
value={controller.schema.location}
2024-09-15 21:18:32 +03:00
title={controller.isAttachedToOSS ? 'Путь наследуется от ОСС' : 'Путь'}
2025-01-26 22:24:34 +03:00
onClick={handleEditLocation}
disabled={isModified || isProcessing || controller.isAttachedToOSS || role < UserRole.OWNER}
2024-09-15 21:18:32 +03:00
/>
</div>
2024-06-07 20:17:03 +03:00
2024-08-21 21:36:02 +03:00
{ownerSelector.isOpen ? (
2024-09-19 20:52:17 +03:00
<Overlay position='top-[-0.5rem] left-[4rem] cc-icons'>
2024-08-21 21:36:02 +03:00
{ownerSelector.isOpen ? (
<SelectUser
2024-09-19 20:52:17 +03:00
className='w-[25rem] sm:w-[26rem] text-sm'
value={controller.schema.owner}
onChange={onSelectUser}
2024-06-07 20:17:03 +03:00
/>
2024-08-21 21:36:02 +03:00
) : null}
2024-06-07 20:17:03 +03:00
</Overlay>
) : null}
2024-08-23 12:35:05 +03:00
<ValueIcon
2024-06-21 19:16:41 +03:00
className='sm:mb-1'
2024-08-21 21:36:02 +03:00
icon={<IconOwner size='1.25rem' className='icon-primary' />}
value={getUserLabel(controller.schema.owner)}
2024-08-21 21:36:02 +03:00
title={controller.isAttachedToOSS ? 'Владелец наследуется от ОСС' : 'Владелец'}
onClick={ownerSelector.toggle}
2025-01-26 22:24:34 +03:00
disabled={isModified || isProcessing || controller.isAttachedToOSS || role < UserRole.OWNER}
2024-06-21 19:16:41 +03:00
/>
2024-06-07 20:17:03 +03:00
2024-08-21 21:36:02 +03:00
<div className='sm:mb-1 flex justify-between items-center'>
2024-08-23 12:35:05 +03:00
<ValueIcon
2024-08-21 21:36:02 +03:00
id='editor_stats'
dense
icon={<IconEditor size='1.25rem' className='icon-primary' />}
value={controller.schema.editors.length}
2025-01-26 22:24:34 +03:00
onClick={handleEditEditors}
disabled={isModified || isProcessing || role < UserRole.OWNER}
2024-08-21 21:36:02 +03:00
/>
<Tooltip anchorSelect='#editor_stats' layer='z-modalTooltip'>
2025-01-21 12:00:09 +03:00
<Suspense fallback={<Loader scale={2} />}>
<InfoUsers items={controller.schema.editors} prefix={prefixes.user_editors} header='Редакторы' />
2025-01-21 12:00:09 +03:00
</Suspense>
2024-08-21 21:36:02 +03:00
</Tooltip>
2024-08-23 12:35:05 +03:00
<ValueIcon
2024-08-21 21:36:02 +03:00
dense
disabled
icon={<IconDateUpdate size='1.25rem' className='text-ok-600' />}
value={new Date(controller.schema.time_update).toLocaleString(intl.locale)}
2024-08-21 21:36:02 +03:00
title='Дата обновления'
/>
2024-08-23 12:35:05 +03:00
<ValueIcon
2024-08-21 21:36:02 +03:00
dense
disabled
icon={<IconDateCreate size='1.25rem' className='text-ok-600' />}
value={new Date(controller.schema.time_create).toLocaleString(intl.locale, {
2024-08-21 21:36:02 +03:00
year: '2-digit',
month: '2-digit',
day: '2-digit'
})}
title='Дата создания'
/>
</div>
2024-06-07 20:17:03 +03:00
</div>
);
}