2024-06-07 20:17:03 +03:00
|
|
|
|
'use client';
|
|
|
|
|
|
2024-06-19 22:09:31 +03:00
|
|
|
|
import clsx from 'clsx';
|
2024-12-13 21:30:49 +03:00
|
|
|
|
import { useLayoutEffect, useState } from 'react';
|
2024-06-07 20:17:03 +03:00
|
|
|
|
import { useIntl } from 'react-intl';
|
|
|
|
|
|
2025-02-10 01:32:16 +03:00
|
|
|
|
import { urls, useConceptNavigation } from '@/app';
|
|
|
|
|
import { FlexColumn } from '@/components/Container';
|
|
|
|
|
import { MiniButton, TextURL } from '@/components/Control';
|
|
|
|
|
import DataTable, { createColumnHelper, IConditionalStyle, VisibilityState } from '@/components/DataTable';
|
2024-06-20 11:50:26 +03:00
|
|
|
|
import { IconFolderTree } from '@/components/Icons';
|
2024-06-07 20:17:03 +03:00
|
|
|
|
import { CProps } from '@/components/props';
|
2025-02-10 01:32:16 +03:00
|
|
|
|
import { useLabelUser } from '@/features/users/backend/useLabelUser';
|
2024-06-07 20:17:03 +03:00
|
|
|
|
import useWindowSize from '@/hooks/useWindowSize';
|
2025-01-14 21:57:32 +03:00
|
|
|
|
import { useFitHeight } from '@/stores/appLayout';
|
2025-01-15 16:06:18 +03:00
|
|
|
|
import { usePreferencesStore } from '@/stores/preferences';
|
2025-02-11 21:07:06 +03:00
|
|
|
|
import { APP_COLORS } from '@/styling/colors';
|
2024-06-07 20:17:03 +03:00
|
|
|
|
|
2025-02-10 01:32:16 +03:00
|
|
|
|
import BadgeLocation from '../../components/BadgeLocation';
|
|
|
|
|
import { ILibraryItem, LibraryItemType } from '../../models/library';
|
|
|
|
|
import { useLibrarySearchStore } from '../../stores/librarySearch';
|
|
|
|
|
|
2024-06-26 19:47:05 +03:00
|
|
|
|
interface TableLibraryItemsProps {
|
2024-06-07 20:17:03 +03:00
|
|
|
|
items: ILibraryItem[];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const columnHelper = createColumnHelper<ILibraryItem>();
|
|
|
|
|
|
2025-01-15 16:06:18 +03:00
|
|
|
|
function TableLibraryItems({ items }: TableLibraryItemsProps) {
|
2024-06-07 20:17:03 +03:00
|
|
|
|
const router = useConceptNavigation();
|
|
|
|
|
const intl = useIntl();
|
2025-01-21 12:00:09 +03:00
|
|
|
|
const getUserLabel = useLabelUser();
|
2025-01-15 16:06:18 +03:00
|
|
|
|
|
|
|
|
|
const folderMode = useLibrarySearchStore(state => state.folderMode);
|
|
|
|
|
const toggleFolderMode = useLibrarySearchStore(state => state.toggleFolderMode);
|
|
|
|
|
const resetFilter = useLibrarySearchStore(state => state.resetFilter);
|
|
|
|
|
|
|
|
|
|
const itemsPerPage = usePreferencesStore(state => state.libraryPagination);
|
|
|
|
|
const setItemsPerPage = usePreferencesStore(state => state.setLibraryPagination);
|
2024-06-07 20:17:03 +03:00
|
|
|
|
|
|
|
|
|
function handleOpenItem(item: ILibraryItem, event: CProps.EventMouse) {
|
2024-12-16 23:51:31 +03:00
|
|
|
|
const selection = window.getSelection();
|
|
|
|
|
if (!!selection && selection.toString().length > 0) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2024-06-07 20:17:03 +03:00
|
|
|
|
if (item.item_type === LibraryItemType.RSFORM) {
|
|
|
|
|
router.push(urls.schema(item.id), event.ctrlKey || event.metaKey);
|
|
|
|
|
} else if (item.item_type === LibraryItemType.OSS) {
|
|
|
|
|
router.push(urls.oss(item.id), event.ctrlKey || event.metaKey);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const windowSize = useWindowSize();
|
|
|
|
|
|
|
|
|
|
const [columnVisibility, setColumnVisibility] = useState<VisibilityState>({});
|
|
|
|
|
|
|
|
|
|
useLayoutEffect(() => {
|
|
|
|
|
setColumnVisibility({
|
|
|
|
|
owner: !windowSize.isSmall
|
|
|
|
|
});
|
|
|
|
|
}, [windowSize]);
|
|
|
|
|
|
2024-12-13 21:30:49 +03:00
|
|
|
|
function handleToggleFolder(event: CProps.EventMouse) {
|
|
|
|
|
event.preventDefault();
|
|
|
|
|
event.stopPropagation();
|
|
|
|
|
toggleFolderMode();
|
|
|
|
|
}
|
2024-06-19 22:09:31 +03:00
|
|
|
|
|
2024-12-13 21:30:49 +03:00
|
|
|
|
const columns = [
|
|
|
|
|
...(folderMode
|
|
|
|
|
? []
|
|
|
|
|
: [
|
|
|
|
|
columnHelper.accessor('location', {
|
|
|
|
|
id: 'location',
|
|
|
|
|
header: () => (
|
|
|
|
|
<MiniButton
|
|
|
|
|
noPadding
|
|
|
|
|
noHover
|
|
|
|
|
className='pl-2 max-h-[1rem] translate-y-[-0.125rem]'
|
|
|
|
|
onClick={handleToggleFolder}
|
|
|
|
|
titleHtml='Переключение в режим Проводник'
|
|
|
|
|
icon={<IconFolderTree size='1.25rem' className='clr-text-controls' />}
|
|
|
|
|
/>
|
|
|
|
|
),
|
|
|
|
|
size: 50,
|
|
|
|
|
minSize: 50,
|
|
|
|
|
maxSize: 50,
|
|
|
|
|
enableSorting: true,
|
|
|
|
|
cell: props => <BadgeLocation location={props.getValue()} />,
|
|
|
|
|
sortingFn: 'text'
|
|
|
|
|
})
|
|
|
|
|
]),
|
|
|
|
|
columnHelper.accessor('alias', {
|
|
|
|
|
id: 'alias',
|
|
|
|
|
header: 'Шифр',
|
|
|
|
|
size: 150,
|
|
|
|
|
minSize: 80,
|
|
|
|
|
maxSize: 150,
|
|
|
|
|
enableSorting: true,
|
|
|
|
|
cell: props => <div className='min-w-[5rem]'>{props.getValue()}</div>,
|
|
|
|
|
sortingFn: 'text'
|
|
|
|
|
}),
|
|
|
|
|
columnHelper.accessor('title', {
|
|
|
|
|
id: 'title',
|
|
|
|
|
header: 'Название',
|
|
|
|
|
size: 1200,
|
|
|
|
|
minSize: 200,
|
|
|
|
|
maxSize: 1200,
|
|
|
|
|
enableSorting: true,
|
|
|
|
|
sortingFn: 'text'
|
|
|
|
|
}),
|
|
|
|
|
columnHelper.accessor(item => item.owner ?? 0, {
|
|
|
|
|
id: 'owner',
|
|
|
|
|
header: 'Владелец',
|
|
|
|
|
size: 400,
|
|
|
|
|
minSize: 100,
|
|
|
|
|
maxSize: 400,
|
|
|
|
|
cell: props => getUserLabel(props.getValue()),
|
|
|
|
|
enableSorting: true,
|
|
|
|
|
sortingFn: 'text'
|
|
|
|
|
}),
|
|
|
|
|
columnHelper.accessor('time_update', {
|
|
|
|
|
id: 'time_update',
|
|
|
|
|
header: windowSize.isSmall ? 'Дата' : 'Обновлена',
|
|
|
|
|
cell: props => (
|
|
|
|
|
<div className='whitespace-nowrap'>
|
|
|
|
|
{new Date(props.getValue()).toLocaleString(intl.locale, {
|
|
|
|
|
year: '2-digit',
|
|
|
|
|
month: '2-digit',
|
|
|
|
|
day: '2-digit',
|
|
|
|
|
...(!windowSize.isSmall && {
|
|
|
|
|
hour: '2-digit',
|
|
|
|
|
minute: '2-digit'
|
2024-06-19 22:09:31 +03:00
|
|
|
|
})
|
2024-12-13 21:30:49 +03:00
|
|
|
|
})}
|
|
|
|
|
</div>
|
|
|
|
|
),
|
|
|
|
|
enableSorting: true,
|
|
|
|
|
sortingFn: 'datetime',
|
|
|
|
|
sortDescFirst: true
|
|
|
|
|
})
|
|
|
|
|
];
|
2024-06-07 20:17:03 +03:00
|
|
|
|
|
2025-01-14 21:57:32 +03:00
|
|
|
|
const tableHeight = useFitHeight('2.2rem');
|
2024-06-07 20:17:03 +03:00
|
|
|
|
|
2024-12-13 21:30:49 +03:00
|
|
|
|
const conditionalRowStyles: IConditionalStyle<ILibraryItem>[] = [
|
|
|
|
|
{
|
|
|
|
|
when: (item: ILibraryItem) => item.item_type === LibraryItemType.OSS,
|
|
|
|
|
style: {
|
2024-12-16 23:51:31 +03:00
|
|
|
|
color: APP_COLORS.fgGreen
|
2024-06-07 20:17:03 +03:00
|
|
|
|
}
|
2024-12-13 21:30:49 +03:00
|
|
|
|
}
|
|
|
|
|
];
|
2024-06-07 20:17:03 +03:00
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<DataTable
|
|
|
|
|
id='library_data'
|
|
|
|
|
columns={columns}
|
|
|
|
|
data={items}
|
|
|
|
|
headPosition='0'
|
2024-12-04 20:07:01 +03:00
|
|
|
|
className={clsx('text-xs sm:text-sm cc-scroll-y h-fit border-b', { 'border-l': folderMode })}
|
2024-06-07 20:17:03 +03:00
|
|
|
|
style={{ maxHeight: tableHeight }}
|
|
|
|
|
noDataComponent={
|
2024-06-21 19:16:41 +03:00
|
|
|
|
<FlexColumn className='dense p-3 items-center min-h-[6rem]'>
|
2024-06-07 20:17:03 +03:00
|
|
|
|
<p>Список схем пуст</p>
|
|
|
|
|
<p className='flex gap-6'>
|
|
|
|
|
<TextURL text='Создать схему' href='/library/create' />
|
2025-01-15 16:06:18 +03:00
|
|
|
|
<TextURL text='Очистить фильтр' onClick={resetFilter} />
|
2024-06-07 20:17:03 +03:00
|
|
|
|
</p>
|
|
|
|
|
</FlexColumn>
|
|
|
|
|
}
|
|
|
|
|
columnVisibility={columnVisibility}
|
|
|
|
|
onRowClicked={handleOpenItem}
|
|
|
|
|
enableSorting
|
|
|
|
|
initialSorting={{
|
|
|
|
|
id: 'time_update',
|
|
|
|
|
desc: true
|
|
|
|
|
}}
|
|
|
|
|
enablePagination
|
|
|
|
|
paginationPerPage={itemsPerPage}
|
|
|
|
|
onChangePaginationOption={setItemsPerPage}
|
|
|
|
|
paginationOptions={[10, 20, 30, 50, 100]}
|
|
|
|
|
conditionalRowStyles={conditionalRowStyles}
|
|
|
|
|
/>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-26 19:47:05 +03:00
|
|
|
|
export default TableLibraryItems;
|