From b9e5331d91905dc010208365aa92b91857049ae4 Mon Sep 17 00:00:00 2001 From: Ivan <8611739+IRBorisov@users.noreply.github.com> Date: Wed, 5 Mar 2025 00:57:03 +0300 Subject: [PATCH] R: Refactor table usage --- .../src/features/help/items/HelpRSLang.tsx | 3 +- .../pages/LibraryPage/TableLibraryItems.tsx | 131 +++--------------- .../pages/LibraryPage/ViewSideLocation.tsx | 4 +- .../pages/LibraryPage/useLibraryColumns.tsx | 104 ++++++++++++++ .../RSFormPage/EditorRSList/TableRSList.tsx | 18 +-- .../RSFormPage/EditorTermGraph/ViewHidden.tsx | 4 +- 6 files changed, 133 insertions(+), 131 deletions(-) create mode 100644 rsconcept/frontend/src/features/library/pages/LibraryPage/useLibraryColumns.tsx diff --git a/rsconcept/frontend/src/features/help/items/HelpRSLang.tsx b/rsconcept/frontend/src/features/help/items/HelpRSLang.tsx index 173a02e1..9be8400c 100644 --- a/rsconcept/frontend/src/features/help/items/HelpRSLang.tsx +++ b/rsconcept/frontend/src/features/help/items/HelpRSLang.tsx @@ -7,11 +7,12 @@ import { HelpTopic } from '../models/helpTopic'; export function HelpRSLang() { const windowSize = useWindowSize(); + const isSmall = windowSize.isSmall; const videoHeight = (() => { const viewH = windowSize.height ?? 0; const viewW = windowSize.width ?? 0; - const availableWidth = viewW - (windowSize.isSmall ? 35 : 310); + const availableWidth = viewW - (isSmall ? 35 : 310); return Math.min(1080, Math.max(viewH - 450, 300), Math.floor((availableWidth * 9) / 16)); })(); diff --git a/rsconcept/frontend/src/features/library/pages/LibraryPage/TableLibraryItems.tsx b/rsconcept/frontend/src/features/library/pages/LibraryPage/TableLibraryItems.tsx index fde5669b..9632377e 100644 --- a/rsconcept/frontend/src/features/library/pages/LibraryPage/TableLibraryItems.tsx +++ b/rsconcept/frontend/src/features/library/pages/LibraryPage/TableLibraryItems.tsx @@ -1,43 +1,48 @@ 'use client'; -import { useLayoutEffect, useState } from 'react'; -import { useIntl } from 'react-intl'; import clsx from 'clsx'; import { urls, useConceptNavigation } from '@/app'; -import { useLabelUser } from '@/features/users'; import { FlexColumn } from '@/components/Container'; -import { MiniButton, TextURL } from '@/components/Control'; -import { createColumnHelper, DataTable, type IConditionalStyle, type VisibilityState } from '@/components/DataTable'; -import { IconFolderTree } from '@/components/Icons'; +import { TextURL } from '@/components/Control'; +import { DataTable, type IConditionalStyle, type VisibilityState } from '@/components/DataTable'; import { useWindowSize } from '@/hooks/useWindowSize'; import { useFitHeight } from '@/stores/appLayout'; import { usePreferencesStore } from '@/stores/preferences'; import { APP_COLORS } from '@/styling/colors'; import { type ILibraryItem, LibraryItemType } from '../../backend/types'; -import { BadgeLocation } from '../../components/BadgeLocation'; import { useLibrarySearchStore } from '../../stores/librarySearch'; +import { useLibraryColumns } from './useLibraryColumns'; + interface TableLibraryItemsProps { items: ILibraryItem[]; } -const columnHelper = createColumnHelper(); - export function TableLibraryItems({ items }: TableLibraryItemsProps) { const router = useConceptNavigation(); - const intl = useIntl(); - const getUserLabel = useLabelUser(); + const { isSmall } = useWindowSize(); 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); + const columns = useLibraryColumns(); + const columnVisibility: VisibilityState = { owner: !isSmall }; + const conditionalRowStyles: IConditionalStyle[] = [ + { + when: (item: ILibraryItem) => item.item_type === LibraryItemType.OSS, + style: { + color: APP_COLORS.fgGreen + } + } + ]; + const tableHeight = useFitHeight('2.2rem'); + function handleOpenItem(item: ILibraryItem, event: React.MouseEvent) { const selection = window.getSelection(); if (!!selection && selection.toString().length > 0) { @@ -50,108 +55,6 @@ export function TableLibraryItems({ items }: TableLibraryItemsProps) { } } - const windowSize = useWindowSize(); - - const [columnVisibility, setColumnVisibility] = useState({}); - - useLayoutEffect(() => { - setColumnVisibility({ - owner: !windowSize.isSmall - }); - }, [windowSize]); - - function handleToggleFolder(event: React.MouseEvent) { - event.preventDefault(); - event.stopPropagation(); - toggleFolderMode(); - } - - const columns = [ - ...(folderMode - ? [] - : [ - columnHelper.accessor('location', { - id: 'location', - header: () => ( - } - /> - ), - size: 50, - minSize: 50, - maxSize: 50, - enableSorting: true, - cell: props => , - sortingFn: 'text' - }) - ]), - columnHelper.accessor('alias', { - id: 'alias', - header: 'Шифр', - size: 150, - minSize: 80, - maxSize: 150, - enableSorting: true, - cell: props =>
{props.getValue()}
, - 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 => ( -
- {new Date(props.getValue()).toLocaleString(intl.locale, { - year: '2-digit', - month: '2-digit', - day: '2-digit', - ...(!windowSize.isSmall && { - hour: '2-digit', - minute: '2-digit' - }) - })} -
- ), - enableSorting: true, - sortingFn: 'datetime', - sortDescFirst: true - }) - ]; - - const tableHeight = useFitHeight('2.2rem'); - - const conditionalRowStyles: IConditionalStyle[] = [ - { - when: (item: ILibraryItem) => item.item_type === LibraryItemType.OSS, - style: { - color: APP_COLORS.fgGreen - } - } - ]; - return ( state.location); const setLocation = useLibrarySearchStore(state => state.setLocation); @@ -68,7 +68,7 @@ export function ViewSideLocation({ isVisible, onRenameLocation }: ViewSideLocati transitionProperty: 'width, min-width, opacity', transitionDuration: `${PARAMETER.moveDuration}ms`, transitionTimingFunction: 'ease-out', - minWidth: isVisible ? (windowSize.isSmall ? '10rem' : '15rem') : '0', + minWidth: isVisible ? (isSmall ? '10rem' : '15rem') : '0', width: isVisible ? '100%' : '0', opacity: isVisible ? 1 : 0 }} diff --git a/rsconcept/frontend/src/features/library/pages/LibraryPage/useLibraryColumns.tsx b/rsconcept/frontend/src/features/library/pages/LibraryPage/useLibraryColumns.tsx new file mode 100644 index 00000000..2d1ff7cc --- /dev/null +++ b/rsconcept/frontend/src/features/library/pages/LibraryPage/useLibraryColumns.tsx @@ -0,0 +1,104 @@ +import { useIntl } from 'react-intl'; + +import { useLabelUser } from '@/features/users'; + +import { MiniButton } from '@/components/Control'; +import { createColumnHelper } from '@/components/DataTable'; +import { IconFolderTree } from '@/components/Icons'; +import { useWindowSize } from '@/hooks/useWindowSize'; + +import { type ILibraryItem } from '../../backend/types'; +import { BadgeLocation } from '../../components/BadgeLocation'; +import { useLibrarySearchStore } from '../../stores/librarySearch'; + +const columnHelper = createColumnHelper(); + +export function useLibraryColumns() { + const { isSmall } = useWindowSize(); + const intl = useIntl(); + + const getUserLabel = useLabelUser(); + const folderMode = useLibrarySearchStore(state => state.folderMode); + const toggleFolderMode = useLibrarySearchStore(state => state.toggleFolderMode); + + function handleToggleFolder(event: React.MouseEvent) { + event.preventDefault(); + event.stopPropagation(); + toggleFolderMode(); + } + + return [ + ...(folderMode + ? [] + : [ + columnHelper.accessor('location', { + id: 'location', + header: () => ( + } + /> + ), + size: 50, + minSize: 50, + maxSize: 50, + enableSorting: true, + cell: props => , + sortingFn: 'text' + }) + ]), + columnHelper.accessor('alias', { + id: 'alias', + header: 'Шифр', + size: 150, + minSize: 80, + maxSize: 150, + enableSorting: true, + cell: props =>
{props.getValue()}
, + 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: isSmall ? 'Дата' : 'Обновлена', + cell: props => ( +
+ {new Date(props.getValue()).toLocaleString(intl.locale, { + year: '2-digit', + month: '2-digit', + day: '2-digit', + ...(!isSmall && { + hour: '2-digit', + minute: '2-digit' + }) + })} +
+ ), + enableSorting: true, + sortingFn: 'datetime', + sortDescFirst: true + }) + ]; +} diff --git a/rsconcept/frontend/src/features/rsform/pages/RSFormPage/EditorRSList/TableRSList.tsx b/rsconcept/frontend/src/features/rsform/pages/RSFormPage/EditorRSList/TableRSList.tsx index a80e919f..a4072659 100644 --- a/rsconcept/frontend/src/features/rsform/pages/RSFormPage/EditorRSList/TableRSList.tsx +++ b/rsconcept/frontend/src/features/rsform/pages/RSFormPage/EditorRSList/TableRSList.tsx @@ -1,6 +1,5 @@ 'use client'; -import { useLayoutEffect, useState } from 'react'; import clsx from 'clsx'; import { TextURL } from '@/components/Control'; @@ -49,16 +48,6 @@ export function TableRSList({ }: TableRSListProps) { const windowSize = useWindowSize(); - const [columnVisibility, setColumnVisibility] = useState({}); - - useLayoutEffect(() => { - setColumnVisibility({ - type: (windowSize.width ?? 0) >= COLUMN_TYPE_HIDE_THRESHOLD, - convention: (windowSize.width ?? 0) >= COLUMN_CONVENTION_HIDE_THRESHOLD, - definition: (windowSize.width ?? 0) >= COLUMN_DEFINITION_HIDE_THRESHOLD - }); - }, [windowSize]); - function handleRowClicked(cst: IConstituenta, event: React.MouseEvent) { if (event.altKey) { event.preventDefault(); @@ -127,6 +116,12 @@ export function TableRSList({ }) ]; + const columnVisibility: VisibilityState = { + type: (windowSize.width ?? 0) >= COLUMN_TYPE_HIDE_THRESHOLD, + convention: (windowSize.width ?? 0) >= COLUMN_CONVENTION_HIDE_THRESHOLD, + definition: (windowSize.width ?? 0) >= COLUMN_DEFINITION_HIDE_THRESHOLD + }; + return ( state.coloring); const { navigateCst, setFocus, schema, selected, toggleSelect } = useRSEdit(); @@ -29,7 +29,7 @@ export function ViewHidden({ items }: ViewHiddenProps) { const isFolded = useTermGraphStore(state => state.foldHidden); const toggleFolded = useTermGraphStore(state => state.toggleFoldHidden); const setActiveCst = useCstTooltipStore(state => state.setActiveCst); - const hiddenHeight = useFitHeight(windowSize.isSmall ? '10.4rem + 2px' : '12.5rem + 2px'); + const hiddenHeight = useFitHeight(isSmall ? '10.4rem + 2px' : '12.5rem + 2px'); function handleClick(event: React.MouseEvent, cstID: number) { event.preventDefault();