From 2b0d4c44a6a785ee8e52baf2c16634455297c177 Mon Sep 17 00:00:00 2001 From: jeffvli Date: Tue, 27 Dec 2022 13:13:12 -0800 Subject: [PATCH] Update table component --- .../virtual-table/cells/album-artist-cell.tsx | 1 - .../virtual-table/cells/artist-cell.tsx | 1 - .../cells/combined-title-cell.tsx | 1 + .../virtual-table/cells/generic-cell.tsx | 14 +- .../virtual-table/cells/genre-cell.tsx | 1 - .../components/virtual-table/index.tsx | 41 ++++ .../virtual-table/table-config-dropdown.tsx | 18 +- .../virtual-table/table-pagination.tsx | 180 +++++++++++------- src/renderer/types.ts | 20 +- 9 files changed, 189 insertions(+), 88 deletions(-) diff --git a/src/renderer/components/virtual-table/cells/album-artist-cell.tsx b/src/renderer/components/virtual-table/cells/album-artist-cell.tsx index 0885a104..5ba3a8fa 100644 --- a/src/renderer/components/virtual-table/cells/album-artist-cell.tsx +++ b/src/renderer/components/virtual-table/cells/album-artist-cell.tsx @@ -31,7 +31,6 @@ export const AlbumArtistCell = ({ value, data }: ICellRendererParams) => { {index > 0 && ( { {index > 0 && ( ` display: grid; diff --git a/src/renderer/components/virtual-table/cells/generic-cell.tsx b/src/renderer/components/virtual-table/cells/generic-cell.tsx index dd948b43..46ba07d6 100644 --- a/src/renderer/components/virtual-table/cells/generic-cell.tsx +++ b/src/renderer/components/virtual-table/cells/generic-cell.tsx @@ -1,12 +1,20 @@ import type { ICellRendererParams } from '@ag-grid-community/core'; +import { motion, Variants } from 'framer-motion'; import { Link } from 'react-router-dom'; import styled from 'styled-components'; import { Skeleton } from '/@/renderer/components/skeleton'; import { Text } from '/@/renderer/components/text'; -export const CellContainer = styled.div<{ - position?: 'left' | 'center' | 'right'; -}>` +export const CELL_VARIANTS: Variants = { + animate: { + opacity: 1, + }, + initial: { + opacity: 0, + }, +}; + +export const CellContainer = styled(motion.div)<{ position?: 'left' | 'center' | 'right' }>` display: flex; align-items: center; justify-content: ${(props) => diff --git a/src/renderer/components/virtual-table/cells/genre-cell.tsx b/src/renderer/components/virtual-table/cells/genre-cell.tsx index 5047456a..7d2a5150 100644 --- a/src/renderer/components/virtual-table/cells/genre-cell.tsx +++ b/src/renderer/components/virtual-table/cells/genre-cell.tsx @@ -17,7 +17,6 @@ export const GenreCell = ({ value, data }: ICellRendererParams) => { {index > 0 && ( `${params.value} kbps`, valueGetter: (params: ValueGetterParams) => (params.data ? params.data.bitRate : undefined), }, + bpm: { + cellRenderer: (params: ICellRendererParams) => GenericCell(params, { position: 'center' }), + colId: TableColumn.BPM, + headerComponent: (params: IHeaderParams) => GenericTableHeader(params, { position: 'center' }), + headerName: 'BPM', + valueGetter: (params: ValueGetterParams) => (params.data ? params.data.bpm : undefined), + }, + channels: { + cellRenderer: (params: ICellRendererParams) => GenericCell(params, { position: 'center' }), + colId: TableColumn.CHANNELS, + field: 'channels', + headerComponent: (params: IHeaderParams) => GenericTableHeader(params, { position: 'center' }), + valueGetter: (params: ValueGetterParams) => (params.data ? params.data.channels : undefined), + }, + comment: { + cellRenderer: GenericCell, + colId: TableColumn.COMMENT, + headerName: 'Note', + valueGetter: (params: ValueGetterParams) => (params.data ? params.data.comment : undefined), + }, dateAdded: { cellRenderer: (params: ICellRendererParams) => GenericCell(params, { position: 'left' }), colId: TableColumn.DATE_ADDED, @@ -106,6 +126,27 @@ const tableColumns: { [key: string]: ColDef } = { headerName: 'Genre', valueGetter: (params: ValueGetterParams) => (params.data ? params.data.genres : undefined), }, + lastPlayedAt: { + cellRenderer: GenericCell, + colId: TableColumn.LAST_PLAYED, + headerName: 'Last Played', + valueGetter: (params: ValueGetterParams) => + params.data ? params.data.lastPlayedAt : undefined, + }, + path: { + cellRenderer: GenericCell, + colId: TableColumn.PATH, + headerName: 'Path', + valueGetter: (params: ValueGetterParams) => (params.data ? params.data.path : undefined), + }, + playCount: { + cellRenderer: (params: ICellRendererParams) => GenericCell(params, { position: 'center' }), + colId: TableColumn.PLAY_COUNT, + field: 'playCount', + headerComponent: (params: IHeaderParams) => GenericTableHeader(params, { position: 'center' }), + headerName: 'Plays', + valueGetter: (params: ValueGetterParams) => (params.data ? params.data.playCount : undefined), + }, releaseDate: { cellRenderer: (params: ICellRendererParams) => GenericCell(params, { position: 'center' }), colId: TableColumn.RELEASE_DATE, diff --git a/src/renderer/components/virtual-table/table-config-dropdown.tsx b/src/renderer/components/virtual-table/table-config-dropdown.tsx index 0ea2cab4..61e4ce83 100644 --- a/src/renderer/components/virtual-table/table-config-dropdown.tsx +++ b/src/renderer/components/virtual-table/table-config-dropdown.tsx @@ -7,7 +7,7 @@ import { Text } from '/@/renderer/components/text'; import { useSettingsStoreActions, useSettingsStore } from '/@/renderer/store/settings.store'; import { TableColumn, TableType } from '/@/renderer/types'; -export const tableColumns = [ +export const SONG_TABLE_COLUMNS = [ { label: 'Row Index', value: TableColumn.ROW_INDEX }, { label: 'Title', value: TableColumn.TITLE }, { label: 'Title (Combined)', value: TableColumn.TITLE_COMBINED }, @@ -21,13 +21,17 @@ export const tableColumns = [ { label: 'Disc Number', value: TableColumn.DISC_NUMBER }, { label: 'Track Number', value: TableColumn.TRACK_NUMBER }, { label: 'Bitrate', value: TableColumn.BIT_RATE }, - // { label: 'Size', value: TableColumn.SIZE }, - // { label: 'Skip', value: TableColumn.SKIP }, - // { label: 'Path', value: TableColumn.PATH }, - // { label: 'Play Count', value: TableColumn.PLAY_COUNT }, + { label: 'Last Played', value: TableColumn.LAST_PLAYED }, + { label: 'Note', value: TableColumn.COMMENT }, + { label: 'Channels', value: TableColumn.CHANNELS }, + { label: 'BPM', value: TableColumn.BPM }, + { label: 'Date Added', value: TableColumn.DATE_ADDED }, + { label: 'Path', value: TableColumn.PATH }, + { label: 'Plays', value: TableColumn.PLAY_COUNT }, // { label: 'Favorite', value: TableColumn.FAVORITE }, // { label: 'Rating', value: TableColumn.RATING }, - { label: 'Date Added', value: TableColumn.DATE_ADDED }, + // { label: 'Size', value: TableColumn.SIZE }, + // { label: 'Skip', value: TableColumn.SKIP }, ]; interface TableConfigDropdownProps { @@ -130,7 +134,7 @@ export const TableConfigDropdown = ({ type }: TableConfigDropdownProps) => { Table Columns column.column)} dropdownPosition="top" width={300} diff --git a/src/renderer/components/virtual-table/table-pagination.tsx b/src/renderer/components/virtual-table/table-pagination.tsx index 5023c526..0a12fda1 100644 --- a/src/renderer/components/virtual-table/table-pagination.tsx +++ b/src/renderer/components/virtual-table/table-pagination.tsx @@ -1,104 +1,144 @@ +import type { AgGridReact as AgGridReactType } from '@ag-grid-community/react/lib/agGridReact'; import { Group } from '@mantine/core'; import { useForm } from '@mantine/form'; import { useDisclosure } from '@mantine/hooks'; +import { MutableRefObject } from 'react'; import { RiHashtag } from 'react-icons/ri'; import { Button } from '/@/renderer/components/button'; +import { MotionFlex } from '../motion'; import { NumberInput } from '/@/renderer/components/input'; import { Pagination } from '/@/renderer/components/pagination'; import { Popover } from '/@/renderer/components/popover'; +import { Text } from '/@/renderer/components/text'; import { useContainerQuery } from '/@/renderer/hooks'; +import { TablePagination as TablePaginationType } from '/@/renderer/types'; interface TablePaginationProps { - containerQuery: ReturnType; - pagination: { - currentPage: number; - itemsPerPage: number; - totalPages: number; - }; - tableRef: any; + pagination: TablePaginationType; + setPagination: (pagination: Partial) => void; + tableRef: MutableRefObject; } -export const TablePagination = ({ tableRef, containerQuery, pagination }: TablePaginationProps) => { +export const TablePagination = ({ tableRef, pagination, setPagination }: TablePaginationProps) => { const [isGoToPageOpen, handlers] = useDisclosure(false); + const containerQuery = useContainerQuery(); - const form = useForm({ + const goToForm = useForm({ initialValues: { pageNumber: undefined, }, }); const handlePagination = (index: number) => { - tableRef.current?.api.paginationGoToPage(index - 1); + const newPage = index - 1; + tableRef.current?.api.paginationGoToPage(newPage); + setPagination({ currentPage: newPage }); }; - const handleGoSubmit = form.onSubmit((values) => { + const handleGoSubmit = goToForm.onSubmit((values) => { handlers.close(); if (!values.pageNumber || values.pageNumber < 1 || values.pageNumber > pagination.totalPages) { return; } - tableRef.current?.api.paginationGoToPage(values.pageNumber - 1); + const newPage = values.pageNumber - 1; + tableRef.current?.api.paginationGoToPage(newPage); + setPagination({ currentPage: newPage }); }); - return ( - - handlers.close()} - > - - - - -
- - - - -
-
-
+ const currentPageStartIndex = pagination.currentPage * pagination.itemsPerPage + 1; + const currentPageStopIndex = (pagination.currentPage + 1) * pagination.itemsPerPage; - + + {containerQuery.isMd ? ( + <> + Showing {currentPageStartIndex} - {currentPageStopIndex} of{' '} + {pagination.totalItems} items + + ) : containerQuery.isSm ? ( + <> + {currentPageStartIndex} - {currentPageStopIndex} of{' '} + {pagination.totalItems} items + + ) : ( + <> + {currentPageStartIndex} - {currentPageStopIndex} of{' '} + {pagination.totalItems} + + )} + + - + spacing="sm" + > + handlers.close()} + > + + + + +
+ + + + +
+
+
+ +
+ ); }; diff --git a/src/renderer/types.ts b/src/renderer/types.ts index 0c1e164a..928c5980 100644 --- a/src/renderer/types.ts +++ b/src/renderer/types.ts @@ -1,6 +1,13 @@ import { Album, AlbumArtist, Artist } from '/@/renderer/api/types'; import { AppRoute } from '/@/renderer/router/routes'; +export type TablePagination = { + currentPage: number; + itemsPerPage: number; + totalItems: number; + totalPages: number; +}; + export type RouteSlug = { idProperty: string; slugProperty: string; @@ -128,18 +135,21 @@ export enum TableColumn { ALBUM_ARTIST = 'albumArtist', ARTIST = 'artist', BIT_RATE = 'bitRate', + BPM = 'bpm', + CHANNELS = 'channels', + COMMENT = 'comment', DATE_ADDED = 'dateAdded', DISC_NUMBER = 'discNumber', DURATION = 'duration', - // FAVORITE = 'favorite', + FAVORITE = 'favorite', GENRE = 'genre', - // PATH = 'path', - // PLAY_COUNT = 'playCount', - // RATING = 'rating', + LAST_PLAYED = 'lastPlayedAt', + PATH = 'path', + PLAY_COUNT = 'playCount', + RATING = 'rating', RELEASE_DATE = 'releaseDate', ROW_INDEX = 'rowIndex', // SKIP = 'skip', - // SIZE = 'size', TITLE = 'title', TITLE_COMBINED = 'titleCombined', TRACK_NUMBER = 'trackNumber',