refactor: polish UI and improve popover interactions (#2016)

This commit is contained in:
SeDemal
2024-04-20 18:41:54 +02:00
committed by GitHub
parent 2b92c98975
commit fdbb8d8b35
2 changed files with 51 additions and 11 deletions

View File

@@ -30,9 +30,16 @@
"label": "Display filtered torrents list ratio", "label": "Display filtered torrents list ratio",
"info": "If disabled, only the global ratio will be display. The global ratio will still use the labels if set" "info": "If disabled, only the global ratio will be display. The global ratio will still use the labels if set"
}, },
"columnOrdering":{
"label": "Enable reordering the columns"
},
"rowSorting":{
"label": "Enable sorting the rows"
},
"columns": { "columns": {
"label": "Select columns to display", "label": "Select columns to display",
"data": { "data": {
"date": "Date Added",
"down": "Down", "down": "Down",
"up": "Up", "up": "Up",
"eta": "ETA", "eta": "ETA",

View File

@@ -17,7 +17,7 @@ import duration from 'dayjs/plugin/duration';
import relativeTime from 'dayjs/plugin/relativeTime'; import relativeTime from 'dayjs/plugin/relativeTime';
import { type MRT_ColumnDef, MRT_TableContainer, useMantineReactTable } from 'mantine-react-table'; import { type MRT_ColumnDef, MRT_TableContainer, useMantineReactTable } from 'mantine-react-table';
import { useTranslation } from 'next-i18next'; import { useTranslation } from 'next-i18next';
import { useMemo } from 'react'; import { useMemo, useState } from 'react';
import { MIN_WIDTH_MOBILE } from '~/constants/constants'; import { MIN_WIDTH_MOBILE } from '~/constants/constants';
import { calculateETA } from '~/tools/client/calculateEta'; import { calculateETA } from '~/tools/client/calculateEta';
import { humanFileSize } from '~/tools/humanFileSize'; import { humanFileSize } from '~/tools/humanFileSize';
@@ -69,10 +69,24 @@ const definition = defineWidget({
defaultValue: true, defaultValue: true,
info: true, info: true,
}, },
columnOrdering: {
type: 'switch',
defaultValue: true,
},
rowSorting: {
type: 'switch',
defaultValue: true,
},
columns: { columns: {
type: 'multi-select', type: 'multi-select',
defaultValue: ['up', 'down', 'eta', 'progress'], defaultValue: ['up', 'down', 'eta', 'progress'],
data: [{ value: 'up' }, { value: 'down' }, { value: 'eta' }, { value: 'progress' }], data: [
{ value: 'up' },
{ value: 'down' },
{ value: 'eta' },
{ value: 'progress' },
{ value: 'date' },
],
}, },
nameColumnSize: { nameColumnSize: {
type: 'slider', type: 'slider',
@@ -127,12 +141,20 @@ function TorrentTile({ widget }: TorrentTileProps) {
const ratioGlobal = getTorrentsRatio(widget, torrents, false); const ratioGlobal = getTorrentsRatio(widget, torrents, false);
const ratioWithFilter = getTorrentsRatio(widget, torrents, true); const ratioWithFilter = getTorrentsRatio(widget, torrents, true);
const [opened, setOpened] = useState<number>(-1);
const columns = useMemo<MRT_ColumnDef<TorrentTotalDownload['torrents'][0]>[]>( const columns = useMemo<MRT_ColumnDef<TorrentTotalDownload['torrents'][0]>[]>(
() => [ () => [
{ {
id: 'dateAdded', id: 'dateAdded',
accessorFn: (row) => new Date(row.dateAdded), accessorFn: (row) => new Date(row.dateAdded),
header: 'dateAdded', Cell: ({ cell }) => (
<Stack spacing={0}>
<Text>{dayjs(cell.getValue() as Date).format('YYYY/MM/DD')}</Text>
<Text>{dayjs(cell.getValue() as Date).format('HH:mm')}</Text>
</Stack>
),
header: t('card.table.header.dateAdded'),
maxSize: 1, maxSize: 1,
}, },
{ {
@@ -147,6 +169,8 @@ function TorrentTile({ widget }: TorrentTileProps) {
transitionProps={{ transitionProps={{
transition: 'pop', transition: 'pop',
}} }}
opened={opened === row.index}
onChange={(o) => setOpened(() => (o ? row.index : -1))}
> >
<Popover.Target> <Popover.Target>
<Text maw={'30vw'} size="xs" lineClamp={1}> <Text maw={'30vw'} size="xs" lineClamp={1}>
@@ -193,7 +217,7 @@ function TorrentTile({ widget }: TorrentTileProps) {
header: t('card.table.header.progress'), header: t('card.table.header.progress'),
maxSize: 1, maxSize: 1,
Cell: ({ cell, row }) => ( Cell: ({ cell, row }) => (
<Flex> <Flex direction="column" w="100%">
<Text className={useStyles().classes.noTextBreak}> <Text className={useStyles().classes.noTextBreak}>
{(Number(cell.getValue()) * 100).toPrecision(3)}% {(Number(cell.getValue()) * 100).toPrecision(3)}%
</Text> </Text>
@@ -207,15 +231,14 @@ function TorrentTile({ widget }: TorrentTileProps) {
: 'blue' : 'blue'
} }
value={Number(cell.getValue()) * 100} value={Number(cell.getValue()) * 100}
size="lg" size="md"
/> />
,
</Flex> </Flex>
), ),
sortDescFirst: true, sortDescFirst: true,
}, },
], ],
[] [opened]
); );
const torrentsTable = useMantineReactTable({ const torrentsTable = useMantineReactTable({
@@ -228,9 +251,19 @@ function TorrentTile({ widget }: TorrentTileProps) {
enableColumnFilters: false, enableColumnFilters: false,
enableRowVirtualization: true, enableRowVirtualization: true,
rowVirtualizerProps: { overscan: 20 }, rowVirtualizerProps: { overscan: 20 },
mantineTableContainerProps: { sx: { scrollbarWidth: 'none' } }, mantineTableContainerProps: { sx: { scrollbarWidth: 'none', flex: '1', borderRadius: '0.5rem' } },
enableColumnOrdering: true, mantineTableBodyCellProps: { style: { background: 'transparent' } },
enableSorting: true, mantineTableHeadCellProps: {
style: { borderTopLeftRadius: '0.5rem', borderTopRightRadius: '0.5rem' },
},
mantineTableHeadRowProps: {
style: { borderTopLeftRadius: '0.5rem', borderTopRightRadius: '0.5rem' },
},
mantineTableBodyRowProps: ({ row }) => ({
onClick: () => setOpened((o) => (o === row.index ? -1 : row.index)),
}),
enableColumnOrdering: widget.properties.columnOrdering,
enableSorting: widget.properties.rowSorting,
initialState: { initialState: {
showColumnFilters: false, showColumnFilters: false,
showGlobalFilter: false, showGlobalFilter: false,
@@ -250,7 +283,7 @@ function TorrentTile({ widget }: TorrentTileProps) {
density: 'xs', density: 'xs',
columnVisibility: { columnVisibility: {
isCompleted: false, isCompleted: false,
dateAdded: false, dateAdded: widget.properties.columns.includes('date') && width > MIN_WIDTH_MOBILE,
uploadSpeed: widget.properties.columns.includes('up') && width > MIN_WIDTH_MOBILE, uploadSpeed: widget.properties.columns.includes('up') && width > MIN_WIDTH_MOBILE,
downloadSpeed: widget.properties.columns.includes('down') && width > MIN_WIDTH_MOBILE, downloadSpeed: widget.properties.columns.includes('down') && width > MIN_WIDTH_MOBILE,
eta: widget.properties.columns.includes('eta') && width > MIN_WIDTH_MOBILE, eta: widget.properties.columns.includes('eta') && width > MIN_WIDTH_MOBILE,