Update table component
This commit is contained in:
parent
d1c038ea6f
commit
2b0d4c44a6
9 changed files with 189 additions and 88 deletions
|
@ -31,7 +31,6 @@ export const AlbumArtistCell = ({ value, data }: ICellRendererParams) => {
|
||||||
<React.Fragment key={`row-${item.id}-${data.uniqueId}`}>
|
<React.Fragment key={`row-${item.id}-${data.uniqueId}`}>
|
||||||
{index > 0 && (
|
{index > 0 && (
|
||||||
<Text
|
<Text
|
||||||
$link
|
|
||||||
$secondary
|
$secondary
|
||||||
size="sm"
|
size="sm"
|
||||||
style={{ display: 'inline-block' }}
|
style={{ display: 'inline-block' }}
|
||||||
|
|
|
@ -31,7 +31,6 @@ export const ArtistCell = ({ value, data }: ICellRendererParams) => {
|
||||||
<React.Fragment key={`row-${item.id}-${data.uniqueId}`}>
|
<React.Fragment key={`row-${item.id}-${data.uniqueId}`}>
|
||||||
{index > 0 && (
|
{index > 0 && (
|
||||||
<Text
|
<Text
|
||||||
$link
|
|
||||||
$secondary
|
$secondary
|
||||||
size="sm"
|
size="sm"
|
||||||
style={{ display: 'inline-block' }}
|
style={{ display: 'inline-block' }}
|
||||||
|
|
|
@ -11,6 +11,7 @@ import { Text } from '/@/renderer/components/text';
|
||||||
import { AppRoute } from '/@/renderer/router/routes';
|
import { AppRoute } from '/@/renderer/router/routes';
|
||||||
import { ServerType } from '/@/renderer/types';
|
import { ServerType } from '/@/renderer/types';
|
||||||
import { Skeleton } from '/@/renderer/components/skeleton';
|
import { Skeleton } from '/@/renderer/components/skeleton';
|
||||||
|
import { CELL_VARIANTS } from '/@/renderer/components/virtual-table/cells/generic-cell';
|
||||||
|
|
||||||
const CellContainer = styled(motion.div)<{ height: number }>`
|
const CellContainer = styled(motion.div)<{ height: number }>`
|
||||||
display: grid;
|
display: grid;
|
||||||
|
|
|
@ -1,12 +1,20 @@
|
||||||
import type { ICellRendererParams } from '@ag-grid-community/core';
|
import type { ICellRendererParams } from '@ag-grid-community/core';
|
||||||
|
import { motion, Variants } from 'framer-motion';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import { Skeleton } from '/@/renderer/components/skeleton';
|
import { Skeleton } from '/@/renderer/components/skeleton';
|
||||||
import { Text } from '/@/renderer/components/text';
|
import { Text } from '/@/renderer/components/text';
|
||||||
|
|
||||||
export const CellContainer = styled.div<{
|
export const CELL_VARIANTS: Variants = {
|
||||||
position?: 'left' | 'center' | 'right';
|
animate: {
|
||||||
}>`
|
opacity: 1,
|
||||||
|
},
|
||||||
|
initial: {
|
||||||
|
opacity: 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const CellContainer = styled(motion.div)<{ position?: 'left' | 'center' | 'right' }>`
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: ${(props) =>
|
justify-content: ${(props) =>
|
||||||
|
|
|
@ -17,7 +17,6 @@ export const GenreCell = ({ value, data }: ICellRendererParams) => {
|
||||||
<React.Fragment key={`row-${item.id}-${data.uniqueId}`}>
|
<React.Fragment key={`row-${item.id}-${data.uniqueId}`}>
|
||||||
{index > 0 && (
|
{index > 0 && (
|
||||||
<Text
|
<Text
|
||||||
$link
|
|
||||||
$secondary
|
$secondary
|
||||||
size="sm"
|
size="sm"
|
||||||
style={{ display: 'inline-block' }}
|
style={{ display: 'inline-block' }}
|
||||||
|
|
|
@ -71,6 +71,26 @@ const tableColumns: { [key: string]: ColDef } = {
|
||||||
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),
|
||||||
},
|
},
|
||||||
|
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: {
|
dateAdded: {
|
||||||
cellRenderer: (params: ICellRendererParams) => GenericCell(params, { position: 'left' }),
|
cellRenderer: (params: ICellRendererParams) => GenericCell(params, { position: 'left' }),
|
||||||
colId: TableColumn.DATE_ADDED,
|
colId: TableColumn.DATE_ADDED,
|
||||||
|
@ -106,6 +126,27 @@ const tableColumns: { [key: string]: ColDef } = {
|
||||||
headerName: 'Genre',
|
headerName: 'Genre',
|
||||||
valueGetter: (params: ValueGetterParams) => (params.data ? params.data.genres : undefined),
|
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: {
|
releaseDate: {
|
||||||
cellRenderer: (params: ICellRendererParams) => GenericCell(params, { position: 'center' }),
|
cellRenderer: (params: ICellRendererParams) => GenericCell(params, { position: 'center' }),
|
||||||
colId: TableColumn.RELEASE_DATE,
|
colId: TableColumn.RELEASE_DATE,
|
||||||
|
|
|
@ -7,7 +7,7 @@ import { Text } from '/@/renderer/components/text';
|
||||||
import { useSettingsStoreActions, useSettingsStore } from '/@/renderer/store/settings.store';
|
import { useSettingsStoreActions, useSettingsStore } from '/@/renderer/store/settings.store';
|
||||||
import { TableColumn, TableType } from '/@/renderer/types';
|
import { TableColumn, TableType } from '/@/renderer/types';
|
||||||
|
|
||||||
export const tableColumns = [
|
export const SONG_TABLE_COLUMNS = [
|
||||||
{ label: 'Row Index', value: TableColumn.ROW_INDEX },
|
{ label: 'Row Index', value: TableColumn.ROW_INDEX },
|
||||||
{ label: 'Title', value: TableColumn.TITLE },
|
{ label: 'Title', value: TableColumn.TITLE },
|
||||||
{ label: 'Title (Combined)', value: TableColumn.TITLE_COMBINED },
|
{ label: 'Title (Combined)', value: TableColumn.TITLE_COMBINED },
|
||||||
|
@ -21,13 +21,17 @@ export const tableColumns = [
|
||||||
{ label: 'Disc Number', value: TableColumn.DISC_NUMBER },
|
{ label: 'Disc Number', value: TableColumn.DISC_NUMBER },
|
||||||
{ label: 'Track Number', value: TableColumn.TRACK_NUMBER },
|
{ label: 'Track Number', value: TableColumn.TRACK_NUMBER },
|
||||||
{ label: 'Bitrate', value: TableColumn.BIT_RATE },
|
{ label: 'Bitrate', value: TableColumn.BIT_RATE },
|
||||||
// { label: 'Size', value: TableColumn.SIZE },
|
{ label: 'Last Played', value: TableColumn.LAST_PLAYED },
|
||||||
// { label: 'Skip', value: TableColumn.SKIP },
|
{ label: 'Note', value: TableColumn.COMMENT },
|
||||||
// { label: 'Path', value: TableColumn.PATH },
|
{ label: 'Channels', value: TableColumn.CHANNELS },
|
||||||
// { label: 'Play Count', value: TableColumn.PLAY_COUNT },
|
{ 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: 'Favorite', value: TableColumn.FAVORITE },
|
||||||
// { label: 'Rating', value: TableColumn.RATING },
|
// { label: 'Rating', value: TableColumn.RATING },
|
||||||
{ label: 'Date Added', value: TableColumn.DATE_ADDED },
|
// { label: 'Size', value: TableColumn.SIZE },
|
||||||
|
// { label: 'Skip', value: TableColumn.SKIP },
|
||||||
];
|
];
|
||||||
|
|
||||||
interface TableConfigDropdownProps {
|
interface TableConfigDropdownProps {
|
||||||
|
@ -130,7 +134,7 @@ export const TableConfigDropdown = ({ type }: TableConfigDropdownProps) => {
|
||||||
<Text>Table Columns</Text>
|
<Text>Table Columns</Text>
|
||||||
<MultiSelect
|
<MultiSelect
|
||||||
clearable
|
clearable
|
||||||
data={tableColumns}
|
data={SONG_TABLE_COLUMNS}
|
||||||
defaultValue={tableConfig[type]?.columns.map((column) => column.column)}
|
defaultValue={tableConfig[type]?.columns.map((column) => column.column)}
|
||||||
dropdownPosition="top"
|
dropdownPosition="top"
|
||||||
width={300}
|
width={300}
|
||||||
|
|
|
@ -1,104 +1,144 @@
|
||||||
|
import type { AgGridReact as AgGridReactType } from '@ag-grid-community/react/lib/agGridReact';
|
||||||
import { Group } from '@mantine/core';
|
import { Group } from '@mantine/core';
|
||||||
import { useForm } from '@mantine/form';
|
import { useForm } from '@mantine/form';
|
||||||
import { useDisclosure } from '@mantine/hooks';
|
import { useDisclosure } from '@mantine/hooks';
|
||||||
|
import { MutableRefObject } from 'react';
|
||||||
import { RiHashtag } from 'react-icons/ri';
|
import { RiHashtag } from 'react-icons/ri';
|
||||||
import { Button } from '/@/renderer/components/button';
|
import { Button } from '/@/renderer/components/button';
|
||||||
|
import { MotionFlex } from '../motion';
|
||||||
import { NumberInput } from '/@/renderer/components/input';
|
import { NumberInput } from '/@/renderer/components/input';
|
||||||
import { Pagination } from '/@/renderer/components/pagination';
|
import { Pagination } from '/@/renderer/components/pagination';
|
||||||
import { Popover } from '/@/renderer/components/popover';
|
import { Popover } from '/@/renderer/components/popover';
|
||||||
|
import { Text } from '/@/renderer/components/text';
|
||||||
import { useContainerQuery } from '/@/renderer/hooks';
|
import { useContainerQuery } from '/@/renderer/hooks';
|
||||||
|
import { TablePagination as TablePaginationType } from '/@/renderer/types';
|
||||||
|
|
||||||
interface TablePaginationProps {
|
interface TablePaginationProps {
|
||||||
containerQuery: ReturnType<typeof useContainerQuery>;
|
pagination: TablePaginationType;
|
||||||
pagination: {
|
setPagination: (pagination: Partial<TablePaginationType>) => void;
|
||||||
currentPage: number;
|
tableRef: MutableRefObject<AgGridReactType | null>;
|
||||||
itemsPerPage: number;
|
|
||||||
totalPages: number;
|
|
||||||
};
|
|
||||||
tableRef: any;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const TablePagination = ({ tableRef, containerQuery, pagination }: TablePaginationProps) => {
|
export const TablePagination = ({ tableRef, pagination, setPagination }: TablePaginationProps) => {
|
||||||
const [isGoToPageOpen, handlers] = useDisclosure(false);
|
const [isGoToPageOpen, handlers] = useDisclosure(false);
|
||||||
|
const containerQuery = useContainerQuery();
|
||||||
|
|
||||||
const form = useForm({
|
const goToForm = useForm({
|
||||||
initialValues: {
|
initialValues: {
|
||||||
pageNumber: undefined,
|
pageNumber: undefined,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const handlePagination = (index: number) => {
|
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();
|
handlers.close();
|
||||||
if (!values.pageNumber || values.pageNumber < 1 || values.pageNumber > pagination.totalPages) {
|
if (!values.pageNumber || values.pageNumber < 1 || values.pageNumber > pagination.totalPages) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
tableRef.current?.api.paginationGoToPage(values.pageNumber - 1);
|
const newPage = values.pageNumber - 1;
|
||||||
|
tableRef.current?.api.paginationGoToPage(newPage);
|
||||||
|
setPagination({ currentPage: newPage });
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
const currentPageStartIndex = pagination.currentPage * pagination.itemsPerPage + 1;
|
||||||
<Group
|
const currentPageStopIndex = (pagination.currentPage + 1) * pagination.itemsPerPage;
|
||||||
ref={containerQuery.ref}
|
|
||||||
noWrap
|
|
||||||
spacing="sm"
|
|
||||||
>
|
|
||||||
<Popover
|
|
||||||
trapFocus
|
|
||||||
opened={isGoToPageOpen}
|
|
||||||
position="bottom-start"
|
|
||||||
transition="fade"
|
|
||||||
onClose={() => handlers.close()}
|
|
||||||
>
|
|
||||||
<Popover.Target>
|
|
||||||
<Button
|
|
||||||
compact
|
|
||||||
radius="sm"
|
|
||||||
size="lg"
|
|
||||||
sx={{ height: '32px', padding: 0, width: '32px' }}
|
|
||||||
tooltip={{ label: 'Go to page' }}
|
|
||||||
variant="default"
|
|
||||||
onClick={() => handlers.toggle()}
|
|
||||||
>
|
|
||||||
<RiHashtag size={15} />
|
|
||||||
</Button>
|
|
||||||
</Popover.Target>
|
|
||||||
<Popover.Dropdown>
|
|
||||||
<form onSubmit={handleGoSubmit}>
|
|
||||||
<Group>
|
|
||||||
<NumberInput
|
|
||||||
{...form.getInputProps('pageNumber')}
|
|
||||||
hideControls={false}
|
|
||||||
max={pagination.totalPages}
|
|
||||||
min={1}
|
|
||||||
width={70}
|
|
||||||
/>
|
|
||||||
<Button
|
|
||||||
type="submit"
|
|
||||||
variant="filled"
|
|
||||||
>
|
|
||||||
Go
|
|
||||||
</Button>
|
|
||||||
</Group>
|
|
||||||
</form>
|
|
||||||
</Popover.Dropdown>
|
|
||||||
</Popover>
|
|
||||||
|
|
||||||
<Pagination
|
return (
|
||||||
|
<MotionFlex
|
||||||
|
ref={containerQuery.ref}
|
||||||
|
layout
|
||||||
|
align="center"
|
||||||
|
animate={{ y: 0 }}
|
||||||
|
exit={{ y: 50 }}
|
||||||
|
initial={{ y: 50 }}
|
||||||
|
justify="space-between"
|
||||||
|
p="1rem"
|
||||||
|
sx={{ borderTop: '1px solid var(--generic-border-color)' }}
|
||||||
|
>
|
||||||
|
<Text
|
||||||
|
$secondary
|
||||||
|
size="md"
|
||||||
|
>
|
||||||
|
{containerQuery.isMd ? (
|
||||||
|
<>
|
||||||
|
Showing <b>{currentPageStartIndex}</b> - <b>{currentPageStopIndex}</b> of{' '}
|
||||||
|
<b>{pagination.totalItems}</b> items
|
||||||
|
</>
|
||||||
|
) : containerQuery.isSm ? (
|
||||||
|
<>
|
||||||
|
<b>{currentPageStartIndex}</b> - <b>{currentPageStopIndex}</b> of{' '}
|
||||||
|
<b>{pagination.totalItems}</b> items
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<b>{currentPageStartIndex}</b> - <b>{currentPageStopIndex}</b> of{' '}
|
||||||
|
<b>{pagination.totalItems}</b>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</Text>
|
||||||
|
<Group
|
||||||
|
ref={containerQuery.ref}
|
||||||
noWrap
|
noWrap
|
||||||
$hideDividers={!containerQuery.isMd}
|
spacing="sm"
|
||||||
boundaries={1}
|
>
|
||||||
page={pagination.currentPage + 1}
|
<Popover
|
||||||
radius="sm"
|
trapFocus
|
||||||
// siblings={containerQuery.isSm ? 1 : 0}
|
opened={isGoToPageOpen}
|
||||||
siblings={1}
|
position="bottom-start"
|
||||||
total={pagination.totalPages - 1}
|
transition="fade"
|
||||||
withControls={containerQuery.isSm}
|
onClose={() => handlers.close()}
|
||||||
onChange={handlePagination}
|
>
|
||||||
/>
|
<Popover.Target>
|
||||||
</Group>
|
<Button
|
||||||
|
compact
|
||||||
|
radius="sm"
|
||||||
|
size="lg"
|
||||||
|
sx={{ height: '32px', padding: 0, width: '32px' }}
|
||||||
|
tooltip={{ label: 'Go to page' }}
|
||||||
|
variant="default"
|
||||||
|
onClick={() => handlers.toggle()}
|
||||||
|
>
|
||||||
|
<RiHashtag size={15} />
|
||||||
|
</Button>
|
||||||
|
</Popover.Target>
|
||||||
|
<Popover.Dropdown>
|
||||||
|
<form onSubmit={handleGoSubmit}>
|
||||||
|
<Group>
|
||||||
|
<NumberInput
|
||||||
|
{...goToForm.getInputProps('pageNumber')}
|
||||||
|
hideControls={false}
|
||||||
|
max={pagination.totalPages}
|
||||||
|
min={1}
|
||||||
|
width={70}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
type="submit"
|
||||||
|
variant="filled"
|
||||||
|
>
|
||||||
|
Go
|
||||||
|
</Button>
|
||||||
|
</Group>
|
||||||
|
</form>
|
||||||
|
</Popover.Dropdown>
|
||||||
|
</Popover>
|
||||||
|
<Pagination
|
||||||
|
noWrap
|
||||||
|
$hideDividers={!containerQuery.isMd}
|
||||||
|
boundaries={1}
|
||||||
|
page={pagination.currentPage + 1}
|
||||||
|
radius="sm"
|
||||||
|
siblings={1}
|
||||||
|
total={pagination.totalPages - 1}
|
||||||
|
withControls={containerQuery.isSm}
|
||||||
|
onChange={handlePagination}
|
||||||
|
/>
|
||||||
|
</Group>
|
||||||
|
</MotionFlex>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,6 +1,13 @@
|
||||||
import { Album, AlbumArtist, Artist } from '/@/renderer/api/types';
|
import { Album, AlbumArtist, Artist } from '/@/renderer/api/types';
|
||||||
import { AppRoute } from '/@/renderer/router/routes';
|
import { AppRoute } from '/@/renderer/router/routes';
|
||||||
|
|
||||||
|
export type TablePagination = {
|
||||||
|
currentPage: number;
|
||||||
|
itemsPerPage: number;
|
||||||
|
totalItems: number;
|
||||||
|
totalPages: number;
|
||||||
|
};
|
||||||
|
|
||||||
export type RouteSlug = {
|
export type RouteSlug = {
|
||||||
idProperty: string;
|
idProperty: string;
|
||||||
slugProperty: string;
|
slugProperty: string;
|
||||||
|
@ -128,18 +135,21 @@ export enum TableColumn {
|
||||||
ALBUM_ARTIST = 'albumArtist',
|
ALBUM_ARTIST = 'albumArtist',
|
||||||
ARTIST = 'artist',
|
ARTIST = 'artist',
|
||||||
BIT_RATE = 'bitRate',
|
BIT_RATE = 'bitRate',
|
||||||
|
BPM = 'bpm',
|
||||||
|
CHANNELS = 'channels',
|
||||||
|
COMMENT = 'comment',
|
||||||
DATE_ADDED = 'dateAdded',
|
DATE_ADDED = 'dateAdded',
|
||||||
DISC_NUMBER = 'discNumber',
|
DISC_NUMBER = 'discNumber',
|
||||||
DURATION = 'duration',
|
DURATION = 'duration',
|
||||||
// FAVORITE = 'favorite',
|
FAVORITE = 'favorite',
|
||||||
GENRE = 'genre',
|
GENRE = 'genre',
|
||||||
// PATH = 'path',
|
LAST_PLAYED = 'lastPlayedAt',
|
||||||
// PLAY_COUNT = 'playCount',
|
PATH = 'path',
|
||||||
// RATING = 'rating',
|
PLAY_COUNT = 'playCount',
|
||||||
|
RATING = 'rating',
|
||||||
RELEASE_DATE = 'releaseDate',
|
RELEASE_DATE = 'releaseDate',
|
||||||
ROW_INDEX = 'rowIndex',
|
ROW_INDEX = 'rowIndex',
|
||||||
// SKIP = 'skip',
|
// SKIP = 'skip',
|
||||||
// SIZE = 'size',
|
|
||||||
TITLE = 'title',
|
TITLE = 'title',
|
||||||
TITLE_COMBINED = 'titleCombined',
|
TITLE_COMBINED = 'titleCombined',
|
||||||
TRACK_NUMBER = 'trackNumber',
|
TRACK_NUMBER = 'trackNumber',
|
||||||
|
|
Reference in a new issue