Minor UI fixes

This commit is contained in:
IRBorisov 2023-09-11 21:06:51 +03:00
parent 3e416564b5
commit a3e60b7d85
6 changed files with 65 additions and 52 deletions

View File

@ -190,7 +190,7 @@ export default function DataTable<TData extends RowData>({
</tfoot> </tfoot>
</table>} </table>}
{enablePagination && {!isEmpty && enablePagination &&
<PaginationTools <PaginationTools
table={tableImpl} table={tableImpl}
paginationOptions={paginationOptions} paginationOptions={paginationOptions}

View File

@ -1,10 +1,9 @@
import { useCallback, useLayoutEffect, useState } from 'react'; import { useCallback, useLayoutEffect } from 'react';
import { useLocation } from 'react-router-dom'; import { useLocation } from 'react-router-dom';
import { MagnifyingGlassIcon } from '../../components/Icons'; import { MagnifyingGlassIcon } from '../../components/Icons';
import { useAuth } from '../../context/AuthContext'; import { useAuth } from '../../context/AuthContext';
import { useConceptNavigation } from '../../context/NagivationContext'; import { useConceptNavigation } from '../../context/NagivationContext';
import useLocalStorage from '../../hooks/useLocalStorage';
import { ILibraryFilter } from '../../models/miscelanious'; import { ILibraryFilter } from '../../models/miscelanious';
import { LibraryFilterStrategy } from '../../models/miscelanious'; import { LibraryFilterStrategy } from '../../models/miscelanious';
import PickerStrategy from './PickerStrategy'; import PickerStrategy from './PickerStrategy';
@ -25,16 +24,17 @@ interface SearchPanelProps {
total: number total: number
filtered: number filtered: number
setFilter: React.Dispatch<React.SetStateAction<ILibraryFilter>> setFilter: React.Dispatch<React.SetStateAction<ILibraryFilter>>
query: string
setQuery: React.Dispatch<React.SetStateAction<string>>
strategy: LibraryFilterStrategy
setStrategy: React.Dispatch<React.SetStateAction<LibraryFilterStrategy>>
} }
function SearchPanel({ total, filtered, setFilter }: SearchPanelProps) { function SearchPanel({ total, filtered, query, setQuery, strategy, setStrategy, setFilter }: SearchPanelProps) {
const { navigateTo } = useConceptNavigation(); const { navigateTo } = useConceptNavigation();
const search = useLocation().search; const search = useLocation().search;
const { user } = useAuth(); const { user } = useAuth();
const [query, setQuery] = useState('');
const [strategy, setStrategy] = useLocalStorage<LibraryFilterStrategy>('search_strategy', LibraryFilterStrategy.MANUAL);
function handleChangeQuery(event: React.ChangeEvent<HTMLInputElement>) { function handleChangeQuery(event: React.ChangeEvent<HTMLInputElement>) {
const newQuery = event.target.value; const newQuery = event.target.value;
setQuery(newQuery); setQuery(newQuery);
@ -76,7 +76,7 @@ function SearchPanel({ total, filtered, setFilter }: SearchPanelProps) {
{filtered} из {total} {filtered} из {total}
</span> </span>
</div> </div>
<div className='flex items-center justify-center w-full pr-[10rem]'> <div className='flex items-center justify-center w-full ml-8'>
<PickerStrategy <PickerStrategy
value={strategy} value={strategy}
onChange={handleChangeStrategy} onChange={handleChangeStrategy}

View File

@ -15,12 +15,12 @@ import { prefixes } from '../../utils/constants';
interface ViewLibraryProps { interface ViewLibraryProps {
items: ILibraryItem[] items: ILibraryItem[]
cleanQuery: () => void resetQuery: () => void
} }
const columnHelper = createColumnHelper<ILibraryItem>(); const columnHelper = createColumnHelper<ILibraryItem>();
function ViewLibrary({ items, cleanQuery }: ViewLibraryProps) { function ViewLibrary({ items, resetQuery: cleanQuery }: ViewLibraryProps) {
const { navigateTo } = useConceptNavigation(); const { navigateTo } = useConceptNavigation();
const intl = useIntl(); const intl = useIntl();
const { user } = useAuth(); const { user } = useAuth();
@ -42,7 +42,7 @@ function ViewLibrary({ items, cleanQuery }: ViewLibraryProps) {
const item = props.row.original; const item = props.row.original;
return (<> return (<>
<div <div
className='flex items-center justify-start gap-1' className='flex items-center justify-start gap-1 min-w-[2.75rem]'
id={`${prefixes.library_list}${item.id}`} id={`${prefixes.library_list}${item.id}`}
> >
{user && user.subscriptions.includes(item.id) && <p title='Отслеживаемая'><EyeIcon size={3}/></p>} {user && user.subscriptions.includes(item.id) && <p title='Отслеживаемая'><EyeIcon size={3}/></p>}
@ -83,10 +83,10 @@ function ViewLibrary({ items, cleanQuery }: ViewLibraryProps) {
columnHelper.accessor('time_update', { columnHelper.accessor('time_update', {
id: 'time_update', id: 'time_update',
header: 'Обновлена', header: 'Обновлена',
size: 220, size: 150,
minSize: 220, minSize: 150,
maxSize: 220, maxSize: 150,
cell: props => new Date(props.cell.getValue()).toLocaleString(intl.locale), cell: props => <div className='text-sm min-w-[8.25rem]'>{new Date(props.cell.getValue()).toLocaleString(intl.locale)}</div>,
enableSorting: true, enableSorting: true,
sortingFn: 'datetime', sortingFn: 'datetime',
sortDescFirst: true sortDescFirst: true
@ -95,6 +95,7 @@ function ViewLibrary({ items, cleanQuery }: ViewLibraryProps) {
return ( return (
<div> <div>
{items.length > 0 &&
<div className='relative w-full'> <div className='relative w-full'>
<div className='absolute top-[-0.125rem] left-0 flex gap-1 ml-3 z-pop'> <div className='absolute top-[-0.125rem] left-0 flex gap-1 ml-3 z-pop'>
<div id='library-help' className='py-2'> <div id='library-help' className='py-2'>
@ -106,21 +107,18 @@ function ViewLibrary({ items, cleanQuery }: ViewLibraryProps) {
</div> </div>
</ConceptTooltip> </ConceptTooltip>
</div> </div>
</div> </div>}
<DataTable <DataTable
columns={columns} columns={columns}
data={items} data={items}
noDataComponent={ noDataComponent={
<div className='flex flex-col gap-4 justify-center p-2 text-center min-h-[10rem]'> <div className='flex flex-col gap-4 justify-center p-2 text-center min-h-[6rem]'>
<p><b>Список схем пуст</b></p> <p>Список схем пуст</p>
<p> <p className='flex justify-center gap-4'>
<TextURL text='Создать схему' href='/rsform-create'/> <TextURL text='Создать схему' href='/rsform-create'/>
<span> | </span>
<TextURL text='Все схемы' href='/library'/>
<span> | </span>
<span className='cursor-pointer hover:underline text-url' onClick={cleanQuery}> <span className='cursor-pointer hover:underline text-url' onClick={cleanQuery}>
<b>Очистить фильтр</b> Очистить фильтр
</span> </span>
</p> </p>
</div>} </div>}

View File

@ -1,11 +1,12 @@
import { useLayoutEffect, useState } from 'react'; import { useCallback, useLayoutEffect, useState } from 'react';
import BackendError from '../../components/BackendError' import BackendError from '../../components/BackendError'
import { ConceptLoader } from '../../components/Common/ConceptLoader' import { ConceptLoader } from '../../components/Common/ConceptLoader'
import { useLibrary } from '../../context/LibraryContext'; import { useLibrary } from '../../context/LibraryContext';
import { useConceptTheme } from '../../context/ThemeContext'; import { useConceptTheme } from '../../context/ThemeContext';
import useLocalStorage from '../../hooks/useLocalStorage';
import { ILibraryItem } from '../../models/library'; import { ILibraryItem } from '../../models/library';
import { ILibraryFilter } from '../../models/miscelanious'; import { ILibraryFilter, LibraryFilterStrategy } from '../../models/miscelanious';
import SearchPanel from './SearchPanel'; import SearchPanel from './SearchPanel';
import ViewLibrary from './ViewLibrary'; import ViewLibrary from './ViewLibrary';
@ -16,6 +17,9 @@ function LibraryPage() {
const [ filter, setFilter ] = useState<ILibraryFilter>({}); const [ filter, setFilter ] = useState<ILibraryFilter>({});
const [ items, setItems ] = useState<ILibraryItem[]>([]); const [ items, setItems ] = useState<ILibraryItem[]>([]);
const [query, setQuery] = useState('');
const [strategy, setStrategy] = useLocalStorage<LibraryFilterStrategy>('search_strategy', LibraryFilterStrategy.MANUAL);
useLayoutEffect( useLayoutEffect(
() => { () => {
setShowScroll(true); setShowScroll(true);
@ -27,6 +31,13 @@ function LibraryPage() {
setItems(library.filter(filter)); setItems(library.filter(filter));
}, [library, filter, filter.query]); }, [library, filter, filter.query]);
const resetQuery = useCallback(
() => {
setQuery('');
setStrategy(LibraryFilterStrategy.MANUAL);
setFilter({});
}, [setStrategy])
return ( return (
<div className='w-full'> <div className='w-full'>
{ library.loading && <ConceptLoader /> } { library.loading && <ConceptLoader /> }
@ -34,12 +45,16 @@ function LibraryPage() {
{ !library.loading && library.items && { !library.loading && library.items &&
<div className='flex flex-col w-full'> <div className='flex flex-col w-full'>
<SearchPanel <SearchPanel
query={query}
setQuery={setQuery}
strategy={strategy}
setStrategy={setStrategy}
total={library.items.length ?? 0} total={library.items.length ?? 0}
filtered={items.length} filtered={items.length}
setFilter={setFilter} setFilter={setFilter}
/> />
<ViewLibrary <ViewLibrary
cleanQuery={() => setFilter({})} resetQuery={resetQuery}
items={items} items={items}
/> />
</div> </div>

View File

@ -49,7 +49,7 @@ function UserTabs() {
</div> </div>
</div> </div>
{subscriptions.length > 0 && showSubs && {subscriptions.length > 0 && showSubs &&
<div className='flex flex-col w-full gap-2 pl-4'> <div className='flex flex-col w-full gap-6 pl-4'>
<h1>Отслеживаемые схемы</h1> <h1>Отслеживаемые схемы</h1>
<ViewSubscriptions items={subscriptions} /> <ViewSubscriptions items={subscriptions} />
</div>} </div>}

View File

@ -38,10 +38,10 @@ function ViewSubscriptions({items}: ViewSubscriptionsProps) {
columnHelper.accessor('time_update', { columnHelper.accessor('time_update', {
id: 'time_update', id: 'time_update',
header: 'Обновлена', header: 'Обновлена',
minSize: 200, minSize: 150,
size: 200, size: 150,
maxSize: 200, maxSize: 150,
cell: props => new Date(props.cell.getValue()).toLocaleString(intl.locale), cell: props => <div className='min-w-[8.25rem]'>{new Date(props.cell.getValue()).toLocaleString(intl.locale)}</div>,
enableSorting: true enableSorting: true
}) })
], [intl]); ], [intl]);