Improve default table column/header defaults

This commit is contained in:
jeffvli 2023-01-05 20:33:12 -08:00
parent bcfb9dbec3
commit 3070586104
5 changed files with 97 additions and 41 deletions

View file

@ -3,6 +3,7 @@ import type { IHeaderParams } from '@ag-grid-community/core';
import { AiOutlineNumber } from 'react-icons/ai'; import { AiOutlineNumber } from 'react-icons/ai';
import { FiClock } from 'react-icons/fi'; import { FiClock } from 'react-icons/fi';
import styled from 'styled-components'; import styled from 'styled-components';
import { _Text } from '/@/renderer/components/text';
type Presets = 'duration' | 'rowIndex'; type Presets = 'duration' | 'rowIndex';
@ -12,7 +13,7 @@ type Options = {
preset?: Presets; preset?: Presets;
}; };
const HeaderWrapper = styled.div<{ position: 'left' | 'center' | 'right' }>` const HeaderWrapper = styled.div<{ position: Options['position'] }>`
display: flex; display: flex;
justify-content: ${(props) => justify-content: ${(props) =>
props.position === 'right' props.position === 'right'
@ -25,6 +26,19 @@ const HeaderWrapper = styled.div<{ position: 'left' | 'center' | 'right' }>`
text-transform: uppercase; text-transform: uppercase;
`; `;
const TextHeaderWrapper = styled(_Text)<{ position: Options['position'] }>`
width: 100%;
color: var(--ag-header-foreground-color);
font-weight: 500;
text-align: ${(props) =>
props.position === 'right'
? 'flex-end'
: props.position === 'center'
? 'center'
: 'flex-start'};
text-transform: uppercase;
`;
const headerPresets = { duration: <FiClock size={15} />, rowIndex: <AiOutlineNumber size={15} /> }; const headerPresets = { duration: <FiClock size={15} />, rowIndex: <AiOutlineNumber size={15} /> };
export const GenericTableHeader = ( export const GenericTableHeader = (
@ -32,10 +46,18 @@ export const GenericTableHeader = (
{ preset, children, position }: Options, { preset, children, position }: Options,
) => { ) => {
if (preset) { if (preset) {
return <HeaderWrapper position={position || 'left'}>{headerPresets[preset]}</HeaderWrapper>; return <HeaderWrapper position={position}>{headerPresets[preset]}</HeaderWrapper>;
} }
return <HeaderWrapper position={position || 'left'}>{children || displayName}</HeaderWrapper>; return (
<TextHeaderWrapper
fw="500"
overflow="hidden"
position={position}
>
{children || displayName}
</TextHeaderWrapper>
);
}; };
GenericTableHeader.defaultProps = { GenericTableHeader.defaultProps = {

View file

@ -11,6 +11,8 @@ import type { AgGridReactProps } from '@ag-grid-community/react';
import { AgGridReact } from '@ag-grid-community/react'; import { AgGridReact } from '@ag-grid-community/react';
import type { AgGridReact as AgGridReactType } from '@ag-grid-community/react/lib/agGridReact'; import type { AgGridReact as AgGridReactType } from '@ag-grid-community/react/lib/agGridReact';
import { useMergedRef } from '@mantine/hooks'; import { useMergedRef } from '@mantine/hooks';
import dayjs from 'dayjs';
import relativeTime from 'dayjs/plugin/relativeTime';
import formatDuration from 'format-duration'; import formatDuration from 'format-duration';
import { generatePath } from 'react-router'; import { generatePath } from 'react-router';
import styled from 'styled-components'; import styled from 'styled-components';
@ -34,6 +36,8 @@ const TableWrapper = styled.div`
height: 100%; height: 100%;
`; `;
dayjs.extend(relativeTime);
const tableColumns: { [key: string]: ColDef } = { const tableColumns: { [key: string]: ColDef } = {
album: { album: {
cellRenderer: (params: ICellRendererParams) => cellRenderer: (params: ICellRendererParams) =>
@ -49,6 +53,7 @@ const tableColumns: { [key: string]: ColDef } = {
value: params.data?.album, value: params.data?.album,
} }
: undefined, : undefined,
width: 200,
}, },
albumArtist: { albumArtist: {
cellRenderer: AlbumArtistCell, cellRenderer: AlbumArtistCell,
@ -56,6 +61,7 @@ const tableColumns: { [key: string]: ColDef } = {
headerName: 'Album Artist', headerName: 'Album Artist',
valueGetter: (params: ValueGetterParams) => valueGetter: (params: ValueGetterParams) =>
params.data ? params.data.albumArtists : undefined, params.data ? params.data.albumArtists : undefined,
width: 150,
}, },
albumCount: { albumCount: {
cellRenderer: (params: ICellRendererParams) => GenericCell(params, { position: 'center' }), cellRenderer: (params: ICellRendererParams) => GenericCell(params, { position: 'center' }),
@ -63,36 +69,42 @@ const tableColumns: { [key: string]: ColDef } = {
field: 'albumCount', field: 'albumCount',
headerComponent: (params: IHeaderParams) => GenericTableHeader(params, { position: 'center' }), headerComponent: (params: IHeaderParams) => GenericTableHeader(params, { position: 'center' }),
headerName: 'Albums', headerName: 'Albums',
suppressSizeToFit: true,
valueGetter: (params: ValueGetterParams) => (params.data ? params.data.albumCount : undefined), valueGetter: (params: ValueGetterParams) => (params.data ? params.data.albumCount : undefined),
width: 80,
}, },
artist: { artist: {
cellRenderer: ArtistCell, cellRenderer: ArtistCell,
colId: TableColumn.ARTIST, colId: TableColumn.ARTIST,
headerName: 'Artist', headerName: 'Artist',
valueGetter: (params: ValueGetterParams) => (params.data ? params.data.artists : undefined), valueGetter: (params: ValueGetterParams) => (params.data ? params.data.artists : undefined),
width: 150,
}, },
biography: { biography: {
cellRenderer: (params: ICellRendererParams) => GenericCell(params, { position: 'left' }), cellRenderer: (params: ICellRendererParams) => GenericCell(params, { position: 'left' }),
colId: TableColumn.BIOGRAPHY, colId: TableColumn.BIOGRAPHY,
field: 'biography', field: 'biography',
headerComponent: (params: IHeaderParams) => GenericTableHeader(params, { position: 'left' }),
headerName: 'Biography', headerName: 'Biography',
valueGetter: (params: ValueGetterParams) => (params.data ? params.data.biography : undefined), valueGetter: (params: ValueGetterParams) => (params.data ? params.data.biography : ''),
width: 200,
}, },
bitRate: { bitRate: {
cellRenderer: (params: ICellRendererParams) => GenericCell(params, { position: 'left' }), cellRenderer: (params: ICellRendererParams) => GenericCell(params, { position: 'left' }),
colId: TableColumn.BIT_RATE, colId: TableColumn.BIT_RATE,
field: 'bitRate', field: 'bitRate',
headerComponent: (params: IHeaderParams) => GenericTableHeader(params, { position: 'left' }), suppressSizeToFit: true,
valueFormatter: (params: ValueFormatterParams) => `${params.value} kbps`, valueFormatter: (params: ValueFormatterParams) => `${params.value} kbps`,
valueGetter: (params: ValueGetterParams) => (params.data ? params.data.bitRate : undefined), valueGetter: (params: ValueGetterParams) => (params.data ? params.data.bitRate : undefined),
width: 90,
}, },
bpm: { bpm: {
cellRenderer: (params: ICellRendererParams) => GenericCell(params, { position: 'center' }), cellRenderer: (params: ICellRendererParams) => GenericCell(params, { position: 'center' }),
colId: TableColumn.BPM, colId: TableColumn.BPM,
headerComponent: (params: IHeaderParams) => GenericTableHeader(params, { position: 'center' }), headerComponent: (params: IHeaderParams) => GenericTableHeader(params, { position: 'center' }),
headerName: 'BPM', headerName: 'BPM',
suppressSizeToFit: true,
valueGetter: (params: ValueGetterParams) => (params.data ? params.data.bpm : undefined), valueGetter: (params: ValueGetterParams) => (params.data ? params.data.bpm : undefined),
width: 60,
}, },
channels: { channels: {
cellRenderer: (params: ICellRendererParams) => GenericCell(params, { position: 'center' }), cellRenderer: (params: ICellRendererParams) => GenericCell(params, { position: 'center' }),
@ -100,60 +112,70 @@ const tableColumns: { [key: string]: ColDef } = {
field: 'channels', field: 'channels',
headerComponent: (params: IHeaderParams) => GenericTableHeader(params, { position: 'center' }), headerComponent: (params: IHeaderParams) => GenericTableHeader(params, { position: 'center' }),
valueGetter: (params: ValueGetterParams) => (params.data ? params.data.channels : undefined), valueGetter: (params: ValueGetterParams) => (params.data ? params.data.channels : undefined),
width: 100,
}, },
comment: { comment: {
cellRenderer: GenericCell, cellRenderer: GenericCell,
colId: TableColumn.COMMENT, colId: TableColumn.COMMENT,
headerName: 'Note', headerName: 'Note',
valueGetter: (params: ValueGetterParams) => (params.data ? params.data.comment : undefined), valueGetter: (params: ValueGetterParams) => (params.data ? params.data.comment : undefined),
width: 150,
}, },
dateAdded: { dateAdded: {
cellRenderer: (params: ICellRendererParams) => GenericCell(params, { position: 'left' }), cellRenderer: (params: ICellRendererParams) => GenericCell(params, { position: 'left' }),
colId: TableColumn.DATE_ADDED, colId: TableColumn.DATE_ADDED,
field: 'createdAt', field: 'createdAt',
headerComponent: (params: IHeaderParams) => GenericTableHeader(params, { position: 'left' }),
headerName: 'Date Added', headerName: 'Date Added',
valueFormatter: (params: ValueFormatterParams) => params.value?.split('T')[0], suppressSizeToFit: true,
valueFormatter: (params: ValueFormatterParams) =>
params.value ? dayjs(params.value).format('MMM D, YYYY') : '',
valueGetter: (params: ValueGetterParams) => (params.data ? params.data.createdAt : undefined), valueGetter: (params: ValueGetterParams) => (params.data ? params.data.createdAt : undefined),
width: 110,
}, },
discNumber: { discNumber: {
cellRenderer: (params: ICellRendererParams) => GenericCell(params, { position: 'center' }), cellRenderer: (params: ICellRendererParams) => GenericCell(params, { position: 'right' }),
colId: TableColumn.DISC_NUMBER, colId: TableColumn.DISC_NUMBER,
field: 'discNumber', field: 'discNumber',
headerComponent: (params: IHeaderParams) => GenericTableHeader(params, { position: 'center' }), headerComponent: (params: IHeaderParams) => GenericTableHeader(params, { position: 'right' }),
headerName: 'Disc', headerName: 'Disc',
initialWidth: 75,
suppressSizeToFit: true, suppressSizeToFit: true,
valueGetter: (params: ValueGetterParams) => (params.data ? params.data.discNumber : undefined), valueGetter: (params: ValueGetterParams) => (params.data ? params.data.discNumber : undefined),
width: 60,
}, },
duration: { duration: {
cellRenderer: (params: ICellRendererParams) => GenericCell(params, { position: 'center' }), cellRenderer: (params: ICellRendererParams) => GenericCell(params, { position: 'right' }),
colId: TableColumn.DURATION, colId: TableColumn.DURATION,
field: 'duration', field: 'duration',
headerComponent: (params: IHeaderParams) => headerComponent: (params: IHeaderParams) =>
GenericTableHeader(params, { position: 'center', preset: 'duration' }), GenericTableHeader(params, { position: 'right', preset: 'duration' }),
initialWidth: 100, suppressSizeToFit: true,
valueFormatter: (params: ValueFormatterParams) => formatDuration(params.value * 1000), valueFormatter: (params: ValueFormatterParams) => formatDuration(params.value * 1000),
valueGetter: (params: ValueGetterParams) => (params.data ? params.data.duration : undefined), valueGetter: (params: ValueGetterParams) => (params.data ? params.data.duration : undefined),
width: 60,
}, },
genre: { genre: {
cellRenderer: GenreCell, cellRenderer: GenreCell,
colId: TableColumn.GENRE, colId: TableColumn.GENRE,
headerName: 'Genre', headerName: 'Genre',
valueGetter: (params: ValueGetterParams) => (params.data ? params.data.genres : undefined), valueGetter: (params: ValueGetterParams) => (params.data ? params.data.genres : undefined),
width: 100,
}, },
lastPlayedAt: { lastPlayedAt: {
cellRenderer: GenericCell, cellRenderer: GenericCell,
colId: TableColumn.LAST_PLAYED, colId: TableColumn.LAST_PLAYED,
headerName: 'Last Played', headerName: 'Last Played',
valueFormatter: (params: ValueFormatterParams) =>
params.value ? dayjs(params.value).fromNow() : '',
valueGetter: (params: ValueGetterParams) => valueGetter: (params: ValueGetterParams) =>
params.data ? params.data.lastPlayedAt : undefined, params.data ? params.data.lastPlayedAt : undefined,
width: 130,
}, },
path: { path: {
cellRenderer: GenericCell, cellRenderer: GenericCell,
colId: TableColumn.PATH, colId: TableColumn.PATH,
headerName: 'Path', headerName: 'Path',
valueGetter: (params: ValueGetterParams) => (params.data ? params.data.path : undefined), valueGetter: (params: ValueGetterParams) => (params.data ? params.data.path : undefined),
width: 200,
}, },
playCount: { playCount: {
cellRenderer: (params: ICellRendererParams) => GenericCell(params, { position: 'center' }), cellRenderer: (params: ICellRendererParams) => GenericCell(params, { position: 'center' }),
@ -161,16 +183,20 @@ const tableColumns: { [key: string]: ColDef } = {
field: 'playCount', field: 'playCount',
headerComponent: (params: IHeaderParams) => GenericTableHeader(params, { position: 'center' }), headerComponent: (params: IHeaderParams) => GenericTableHeader(params, { position: 'center' }),
headerName: 'Plays', headerName: 'Plays',
suppressSizeToFit: true,
valueGetter: (params: ValueGetterParams) => (params.data ? params.data.playCount : undefined), valueGetter: (params: ValueGetterParams) => (params.data ? params.data.playCount : undefined),
width: 90,
}, },
releaseDate: { releaseDate: {
cellRenderer: (params: ICellRendererParams) => GenericCell(params, { position: 'center' }), cellRenderer: (params: ICellRendererParams) => GenericCell(params, { position: 'left' }),
colId: TableColumn.RELEASE_DATE, colId: TableColumn.RELEASE_DATE,
field: 'releaseDate', field: 'releaseDate',
headerComponent: (params: IHeaderParams) => GenericTableHeader(params, { position: 'center' }),
headerName: 'Release Date', headerName: 'Release Date',
valueFormatter: (params: ValueFormatterParams) => params.value?.split('T')[0], suppressSizeToFit: true,
valueFormatter: (params: ValueFormatterParams) =>
params.value ? dayjs(params.value).format('MMM D, YYYY') : '',
valueGetter: (params: ValueGetterParams) => (params.data ? params.data.releaseDate : undefined), valueGetter: (params: ValueGetterParams) => (params.data ? params.data.releaseDate : undefined),
width: 130,
}, },
releaseYear: { releaseYear: {
cellRenderer: (params: ICellRendererParams) => GenericCell(params, { position: 'center' }), cellRenderer: (params: ICellRendererParams) => GenericCell(params, { position: 'center' }),
@ -178,26 +204,29 @@ const tableColumns: { [key: string]: ColDef } = {
field: 'releaseYear', field: 'releaseYear',
headerComponent: (params: IHeaderParams) => GenericTableHeader(params, { position: 'center' }), headerComponent: (params: IHeaderParams) => GenericTableHeader(params, { position: 'center' }),
headerName: 'Year', headerName: 'Year',
suppressSizeToFit: true,
valueGetter: (params: ValueGetterParams) => (params.data ? params.data.releaseYear : undefined), valueGetter: (params: ValueGetterParams) => (params.data ? params.data.releaseYear : undefined),
width: 60,
}, },
rowIndex: { rowIndex: {
cellRenderer: (params: ICellRendererParams) => GenericCell(params, { position: 'left' }), cellRenderer: (params: ICellRendererParams) => GenericCell(params, { position: 'right' }),
colId: TableColumn.ROW_INDEX, colId: TableColumn.ROW_INDEX,
headerComponent: (params: IHeaderParams) => headerComponent: (params: IHeaderParams) =>
GenericTableHeader(params, { position: 'left', preset: 'rowIndex' }), GenericTableHeader(params, { position: 'right', preset: 'rowIndex' }),
initialWidth: 50,
suppressSizeToFit: true, suppressSizeToFit: true,
valueGetter: (params) => { valueGetter: (params) => {
return (params.node?.rowIndex || 0) + 1; return (params.node?.rowIndex || 0) + 1;
}, },
width: 65,
}, },
songCount: { songCount: {
cellRenderer: (params: ICellRendererParams) => GenericCell(params, { position: 'center' }), cellRenderer: (params: ICellRendererParams) => GenericCell(params, { position: 'center' }),
colId: TableColumn.SONG_COUNT, colId: TableColumn.SONG_COUNT,
field: 'songCount', field: 'songCount',
headerComponent: (params: IHeaderParams) => GenericTableHeader(params, { position: 'center' }),
headerName: 'Songs', headerName: 'Songs',
suppressSizeToFit: true,
valueGetter: (params: ValueGetterParams) => (params.data ? params.data.songCount : undefined), valueGetter: (params: ValueGetterParams) => (params.data ? params.data.songCount : undefined),
width: 80,
}, },
title: { title: {
cellRenderer: (params: ICellRendererParams) => cellRenderer: (params: ICellRendererParams) =>
@ -206,6 +235,7 @@ const tableColumns: { [key: string]: ColDef } = {
field: 'name', field: 'name',
headerName: 'Title', headerName: 'Title',
valueGetter: (params: ValueGetterParams) => (params.data ? params.data.name : undefined), valueGetter: (params: ValueGetterParams) => (params.data ? params.data.name : undefined),
width: 250,
}, },
titleCombined: { titleCombined: {
cellRenderer: CombinedTitleCell, cellRenderer: CombinedTitleCell,
@ -224,16 +254,17 @@ const tableColumns: { [key: string]: ColDef } = {
type: params.data?.type, type: params.data?.type,
} }
: undefined, : undefined,
width: 250,
}, },
trackNumber: { trackNumber: {
cellRenderer: (params: ICellRendererParams) => GenericCell(params, { position: 'center' }), cellRenderer: (params: ICellRendererParams) => GenericCell(params, { position: 'right' }),
colId: TableColumn.TRACK_NUMBER, colId: TableColumn.TRACK_NUMBER,
field: 'trackNumber', field: 'trackNumber',
headerComponent: (params: IHeaderParams) => GenericTableHeader(params, { position: 'center' }), headerComponent: (params: IHeaderParams) => GenericTableHeader(params, { position: 'right' }),
headerName: 'Track', headerName: 'Track',
initialWidth: 75,
suppressSizeToFit: true, suppressSizeToFit: true,
valueGetter: (params: ValueGetterParams) => (params.data ? params.data.trackNumber : undefined), valueGetter: (params: ValueGetterParams) => (params.data ? params.data.trackNumber : undefined),
width: 80,
}, },
}; };

View file

@ -42,13 +42,6 @@ const ContentContainer = styled.div`
.ag-header-container { .ag-header-container {
z-index: 1000; z-index: 1000;
} }
.ag-header-cell-resize {
top: 25%;
width: 7px;
height: 50%;
background-color: rgb(70, 70, 70, 20%);
}
`; `;
interface AlbumDetailContentProps { interface AlbumDetailContentProps {

View file

@ -28,13 +28,6 @@ const ContentContainer = styled.div`
.ag-header-container { .ag-header-container {
z-index: 1000; z-index: 1000;
} }
.ag-header-cell-resize {
top: 25%;
width: 7px;
height: 50%;
background-color: rgb(70, 70, 70, 20%);
}
`; `;
interface PlaylistDetailContentProps { interface PlaylistDetailContentProps {

View file

@ -116,10 +116,27 @@
--ag-selected-row-background-color: rgba(100, 100, 100, 0.4); --ag-selected-row-background-color: rgba(100, 100, 100, 0.4);
} }
.ag-header {
border-bottom: 1px solid rgb(50, 50, 50, 0.5);
margin-bottom: 1rem;
}
.ag-header-cell-comp-wrapper {
margin: 0.5rem 0.5rem;
}
.ag-header-cell,
.ag-header-group-cell {
padding-left: 0.5rem;
padding-right: 0.5rem;
}
.ag-header-cell-resize { .ag-header-cell-resize {
background-color: rgb(70, 70, 70, 0.4); background-color: transparent;
height: 50%; }
top: 25%;
.ag-header:hover .ag-header-cell-resize {
border-left: 2px rgb(70, 70, 70, 1) solid;
width: 7px; width: 7px;
} }