2022-12-19 15:59:14 -08:00
|
|
|
import type { Ref } from 'react';
|
|
|
|
|
import { forwardRef, useRef } from 'react';
|
|
|
|
|
import type {
|
|
|
|
|
ICellRendererParams,
|
|
|
|
|
ValueGetterParams,
|
|
|
|
|
IHeaderParams,
|
|
|
|
|
ValueFormatterParams,
|
|
|
|
|
ColDef,
|
|
|
|
|
} from '@ag-grid-community/core';
|
|
|
|
|
import type { AgGridReactProps } 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 { useMergedRef } from '@mantine/hooks';
|
|
|
|
|
import formatDuration from 'format-duration';
|
|
|
|
|
import { generatePath } from 'react-router';
|
|
|
|
|
import styled from 'styled-components';
|
|
|
|
|
import { AlbumArtistCell } from '/@/renderer/components/virtual-table/cells/album-artist-cell';
|
|
|
|
|
import { ArtistCell } from '/@/renderer/components/virtual-table/cells/artist-cell';
|
|
|
|
|
import { CombinedTitleCell } from '/@/renderer/components/virtual-table/cells/combined-title-cell';
|
|
|
|
|
import { GenericCell } from '/@/renderer/components/virtual-table/cells/generic-cell';
|
|
|
|
|
import { GenreCell } from '/@/renderer/components/virtual-table/cells/genre-cell';
|
|
|
|
|
import { GenericTableHeader } from '/@/renderer/components/virtual-table/headers/generic-table-header';
|
|
|
|
|
import { AppRoute } from '/@/renderer/router/routes';
|
|
|
|
|
import { PersistedTableColumn } from '/@/renderer/store/settings.store';
|
|
|
|
|
import { TableColumn } from '/@/renderer/types';
|
|
|
|
|
|
|
|
|
|
export * from './table-config-dropdown';
|
2022-12-26 01:45:36 -08:00
|
|
|
export * from './table-pagination';
|
2022-12-19 15:59:14 -08:00
|
|
|
|
|
|
|
|
const TableWrapper = styled.div`
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
width: 100%;
|
|
|
|
|
height: 100%;
|
|
|
|
|
`;
|
|
|
|
|
|
|
|
|
|
const tableColumns: { [key: string]: ColDef } = {
|
|
|
|
|
album: {
|
|
|
|
|
cellRenderer: (params: ICellRendererParams) =>
|
|
|
|
|
GenericCell(params, { isLink: true, position: 'left' }),
|
|
|
|
|
colId: TableColumn.ALBUM,
|
|
|
|
|
headerName: 'Album',
|
2022-12-20 04:25:51 -08:00
|
|
|
valueGetter: (params: ValueGetterParams) =>
|
|
|
|
|
params.data
|
|
|
|
|
? {
|
|
|
|
|
link: generatePath(AppRoute.LIBRARY_ALBUMS_DETAIL, {
|
|
|
|
|
albumId: params.data?.albumId || '',
|
|
|
|
|
}),
|
|
|
|
|
value: params.data?.album,
|
|
|
|
|
}
|
|
|
|
|
: undefined,
|
2022-12-19 15:59:14 -08:00
|
|
|
},
|
|
|
|
|
albumArtist: {
|
|
|
|
|
cellRenderer: AlbumArtistCell,
|
|
|
|
|
colId: TableColumn.ALBUM_ARTIST,
|
|
|
|
|
headerName: 'Album Artist',
|
2022-12-20 04:25:51 -08:00
|
|
|
valueGetter: (params: ValueGetterParams) =>
|
|
|
|
|
params.data ? params.data.albumArtists : undefined,
|
2022-12-19 15:59:14 -08:00
|
|
|
},
|
|
|
|
|
artist: {
|
|
|
|
|
cellRenderer: ArtistCell,
|
|
|
|
|
colId: TableColumn.ARTIST,
|
|
|
|
|
headerName: 'Artist',
|
2022-12-20 04:25:51 -08:00
|
|
|
valueGetter: (params: ValueGetterParams) => (params.data ? params.data.artists : undefined),
|
2022-12-19 15:59:14 -08:00
|
|
|
},
|
|
|
|
|
bitRate: {
|
|
|
|
|
cellRenderer: (params: ICellRendererParams) => GenericCell(params, { position: 'left' }),
|
|
|
|
|
colId: TableColumn.BIT_RATE,
|
|
|
|
|
field: 'bitRate',
|
|
|
|
|
headerComponent: (params: IHeaderParams) => GenericTableHeader(params, { position: 'left' }),
|
|
|
|
|
valueFormatter: (params: ValueFormatterParams) => `${params.value} kbps`,
|
2022-12-20 04:25:51 -08:00
|
|
|
valueGetter: (params: ValueGetterParams) => (params.data ? params.data.bitRate : undefined),
|
2022-12-19 15:59:14 -08:00
|
|
|
},
|
2022-12-27 13:13:12 -08:00
|
|
|
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),
|
|
|
|
|
},
|
2022-12-19 15:59:14 -08:00
|
|
|
dateAdded: {
|
|
|
|
|
cellRenderer: (params: ICellRendererParams) => GenericCell(params, { position: 'left' }),
|
|
|
|
|
colId: TableColumn.DATE_ADDED,
|
|
|
|
|
field: 'createdAt',
|
|
|
|
|
headerComponent: (params: IHeaderParams) => GenericTableHeader(params, { position: 'left' }),
|
|
|
|
|
headerName: 'Date Added',
|
|
|
|
|
valueFormatter: (params: ValueFormatterParams) => params.value?.split('T')[0],
|
2022-12-20 04:25:51 -08:00
|
|
|
valueGetter: (params: ValueGetterParams) => (params.data ? params.data.createdAt : undefined),
|
2022-12-19 15:59:14 -08:00
|
|
|
},
|
|
|
|
|
discNumber: {
|
|
|
|
|
cellRenderer: (params: ICellRendererParams) => GenericCell(params, { position: 'center' }),
|
|
|
|
|
colId: TableColumn.DISC_NUMBER,
|
|
|
|
|
field: 'discNumber',
|
|
|
|
|
headerComponent: (params: IHeaderParams) => GenericTableHeader(params, { position: 'center' }),
|
|
|
|
|
headerName: 'Disc',
|
|
|
|
|
initialWidth: 75,
|
|
|
|
|
suppressSizeToFit: true,
|
2022-12-20 04:25:51 -08:00
|
|
|
valueGetter: (params: ValueGetterParams) => (params.data ? params.data.discNumber : undefined),
|
2022-12-19 15:59:14 -08:00
|
|
|
},
|
|
|
|
|
duration: {
|
|
|
|
|
cellRenderer: (params: ICellRendererParams) => GenericCell(params, { position: 'center' }),
|
|
|
|
|
colId: TableColumn.DURATION,
|
|
|
|
|
field: 'duration',
|
|
|
|
|
headerComponent: (params: IHeaderParams) =>
|
|
|
|
|
GenericTableHeader(params, { position: 'center', preset: 'duration' }),
|
|
|
|
|
initialWidth: 100,
|
|
|
|
|
valueFormatter: (params: ValueFormatterParams) => formatDuration(params.value * 1000),
|
2022-12-20 04:25:51 -08:00
|
|
|
valueGetter: (params: ValueGetterParams) => (params.data ? params.data.duration : undefined),
|
2022-12-19 15:59:14 -08:00
|
|
|
},
|
|
|
|
|
genre: {
|
|
|
|
|
cellRenderer: GenreCell,
|
|
|
|
|
colId: TableColumn.GENRE,
|
|
|
|
|
headerName: 'Genre',
|
2022-12-20 04:25:51 -08:00
|
|
|
valueGetter: (params: ValueGetterParams) => (params.data ? params.data.genres : undefined),
|
2022-12-19 15:59:14 -08:00
|
|
|
},
|
2022-12-27 13:13:12 -08:00
|
|
|
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),
|
|
|
|
|
},
|
2022-12-19 15:59:14 -08:00
|
|
|
releaseDate: {
|
|
|
|
|
cellRenderer: (params: ICellRendererParams) => GenericCell(params, { position: 'center' }),
|
|
|
|
|
colId: TableColumn.RELEASE_DATE,
|
|
|
|
|
field: 'releaseDate',
|
|
|
|
|
headerComponent: (params: IHeaderParams) => GenericTableHeader(params, { position: 'center' }),
|
|
|
|
|
headerName: 'Release Date',
|
|
|
|
|
valueFormatter: (params: ValueFormatterParams) => params.value?.split('T')[0],
|
2022-12-20 04:25:51 -08:00
|
|
|
valueGetter: (params: ValueGetterParams) => (params.data ? params.data.releaseDate : undefined),
|
2022-12-19 15:59:14 -08:00
|
|
|
},
|
|
|
|
|
releaseYear: {
|
|
|
|
|
cellRenderer: (params: ICellRendererParams) => GenericCell(params, { position: 'center' }),
|
|
|
|
|
colId: TableColumn.YEAR,
|
|
|
|
|
field: 'releaseYear',
|
|
|
|
|
headerComponent: (params: IHeaderParams) => GenericTableHeader(params, { position: 'center' }),
|
|
|
|
|
headerName: 'Year',
|
2022-12-20 04:25:51 -08:00
|
|
|
valueGetter: (params: ValueGetterParams) => (params.data ? params.data.releaseYear : undefined),
|
2022-12-19 15:59:14 -08:00
|
|
|
},
|
|
|
|
|
rowIndex: {
|
|
|
|
|
cellRenderer: (params: ICellRendererParams) => GenericCell(params, { position: 'left' }),
|
|
|
|
|
colId: TableColumn.ROW_INDEX,
|
|
|
|
|
headerComponent: (params: IHeaderParams) =>
|
|
|
|
|
GenericTableHeader(params, { position: 'left', preset: 'rowIndex' }),
|
|
|
|
|
initialWidth: 50,
|
|
|
|
|
suppressSizeToFit: true,
|
|
|
|
|
valueGetter: (params) => {
|
|
|
|
|
return (params.node?.rowIndex || 0) + 1;
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
title: {
|
|
|
|
|
cellRenderer: (params: ICellRendererParams) =>
|
|
|
|
|
GenericCell(params, { position: 'left', primary: true }),
|
|
|
|
|
colId: TableColumn.TITLE,
|
|
|
|
|
field: 'name',
|
|
|
|
|
headerName: 'Title',
|
2022-12-20 04:25:51 -08:00
|
|
|
valueGetter: (params: ValueGetterParams) => (params.data ? params.data.name : undefined),
|
2022-12-19 15:59:14 -08:00
|
|
|
},
|
|
|
|
|
titleCombined: {
|
|
|
|
|
cellRenderer: CombinedTitleCell,
|
|
|
|
|
colId: TableColumn.TITLE_COMBINED,
|
|
|
|
|
headerName: 'Title',
|
|
|
|
|
initialWidth: 500,
|
2022-12-20 04:25:51 -08:00
|
|
|
valueGetter: (params: ValueGetterParams) =>
|
|
|
|
|
params.data
|
|
|
|
|
? {
|
|
|
|
|
albumArtists: params.data?.albumArtists,
|
|
|
|
|
artists: params.data?.artists,
|
|
|
|
|
imageUrl: params.data?.imageUrl,
|
|
|
|
|
name: params.data?.name,
|
|
|
|
|
rowHeight: params.node?.rowHeight,
|
|
|
|
|
type: params.data?.type,
|
|
|
|
|
}
|
|
|
|
|
: undefined,
|
2022-12-19 15:59:14 -08:00
|
|
|
},
|
|
|
|
|
trackNumber: {
|
|
|
|
|
cellRenderer: (params: ICellRendererParams) => GenericCell(params, { position: 'center' }),
|
|
|
|
|
colId: TableColumn.TRACK_NUMBER,
|
|
|
|
|
field: 'trackNumber',
|
|
|
|
|
headerComponent: (params: IHeaderParams) => GenericTableHeader(params, { position: 'center' }),
|
|
|
|
|
headerName: 'Track',
|
|
|
|
|
initialWidth: 75,
|
|
|
|
|
suppressSizeToFit: true,
|
2022-12-20 04:25:51 -08:00
|
|
|
valueGetter: (params: ValueGetterParams) => (params.data ? params.data.trackNumber : undefined),
|
2022-12-19 15:59:14 -08:00
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export const getColumnDef = (column: TableColumn) => {
|
|
|
|
|
return tableColumns[column as keyof typeof tableColumns];
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export const getColumnDefs = (columns: PersistedTableColumn[]) => {
|
2022-12-28 00:41:34 -08:00
|
|
|
const columnDefs: ColDef[] = [];
|
2022-12-19 15:59:14 -08:00
|
|
|
for (const column of columns) {
|
2022-12-28 00:41:34 -08:00
|
|
|
const presetColumn = tableColumns[column.column as keyof typeof tableColumns];
|
|
|
|
|
if (presetColumn) {
|
|
|
|
|
columnDefs.push({
|
|
|
|
|
...presetColumn,
|
|
|
|
|
width: column.width,
|
|
|
|
|
});
|
|
|
|
|
}
|
2022-12-19 15:59:14 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return columnDefs;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export const VirtualTable = forwardRef(
|
|
|
|
|
({ ...rest }: AgGridReactProps, ref: Ref<AgGridReactType | null>) => {
|
|
|
|
|
const tableRef = useRef<AgGridReactType | null>(null);
|
|
|
|
|
|
|
|
|
|
const mergedRef = useMergedRef(ref, tableRef);
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<TableWrapper className="ag-theme-alpine-dark">
|
|
|
|
|
<AgGridReact
|
|
|
|
|
ref={mergedRef}
|
|
|
|
|
suppressMoveWhenRowDragging
|
|
|
|
|
suppressScrollOnNewData
|
|
|
|
|
rowBuffer={30}
|
|
|
|
|
{...rest}
|
|
|
|
|
/>
|
|
|
|
|
</TableWrapper>
|
|
|
|
|
);
|
|
|
|
|
},
|
|
|
|
|
);
|