You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
168 lines
5.5 KiB
168 lines
5.5 KiB
import React, { useRef, useState } from 'react';
|
|
import { useQuery, useQueryClient } from 'react-query';
|
|
import { useHistory } from 'react-router-dom';
|
|
import { Form, Input, Popover, Whisper } from 'rsuite';
|
|
import settings from 'electron-settings';
|
|
import useSearchQuery from '../../hooks/useSearchQuery';
|
|
import { createPlaylist, getPlaylists } from '../../api/api';
|
|
import ListViewType from '../viewtypes/ListViewType';
|
|
import PageLoader from '../loader/PageLoader';
|
|
import GenericPage from '../layout/GenericPage';
|
|
import GenericPageHeader from '../layout/GenericPageHeader';
|
|
import GridViewType from '../viewtypes/GridViewType';
|
|
import { StyledButton, StyledInputGroup } from '../shared/styled';
|
|
import { errorMessages, isFailedResponse } from '../../shared/utils';
|
|
import { notifyToast } from '../shared/toast';
|
|
import { AddPlaylistButton } from '../shared/ToolbarButtons';
|
|
|
|
const PlaylistList = () => {
|
|
const history = useHistory();
|
|
const queryClient = useQueryClient();
|
|
const playlistTriggerRef = useRef<any>();
|
|
const [sortBy] = useState('name');
|
|
const [newPlaylistName, setNewPlaylistName] = useState('');
|
|
const [viewType, setViewType] = useState(settings.getSync('playlistViewType') || 'list');
|
|
const { isLoading, isError, data: playlists, error }: any = useQuery(['playlists', sortBy], () =>
|
|
getPlaylists(sortBy)
|
|
);
|
|
const [searchQuery, setSearchQuery] = useState('');
|
|
const filteredData = useSearchQuery(searchQuery, playlists, ['name', 'comment']);
|
|
|
|
const handleCreatePlaylist = async (name: string) => {
|
|
try {
|
|
const res = await createPlaylist(name);
|
|
|
|
if (isFailedResponse(res)) {
|
|
notifyToast('error', errorMessages(res)[0]);
|
|
} else {
|
|
await queryClient.refetchQueries(['playlists'], {
|
|
active: true,
|
|
});
|
|
notifyToast('success', `Playlist "${name}" created!`);
|
|
}
|
|
} catch (err) {
|
|
notifyToast('error', err);
|
|
}
|
|
};
|
|
|
|
const handleRowClick = (_e: any, rowData: any) => {
|
|
history.push(`playlist/${rowData.id}`);
|
|
};
|
|
|
|
if (isLoading) {
|
|
return <PageLoader />;
|
|
}
|
|
|
|
if (isError) {
|
|
return <span>Error: {error.message}</span>;
|
|
}
|
|
|
|
return (
|
|
<GenericPage
|
|
hideDivider
|
|
header={
|
|
<GenericPageHeader
|
|
title="Playlists"
|
|
subtitle={
|
|
<Whisper
|
|
ref={playlistTriggerRef}
|
|
enterable
|
|
placement="auto"
|
|
trigger="click"
|
|
speaker={
|
|
<Popover>
|
|
<Form>
|
|
<StyledInputGroup>
|
|
<Input
|
|
placeholder="Enter name..."
|
|
value={newPlaylistName}
|
|
onChange={(e) => setNewPlaylistName(e)}
|
|
/>
|
|
</StyledInputGroup>
|
|
<br />
|
|
<StyledButton
|
|
size="sm"
|
|
type="submit"
|
|
block
|
|
loading={false}
|
|
appearance="primary"
|
|
onClick={() => {
|
|
handleCreatePlaylist(newPlaylistName);
|
|
playlistTriggerRef.current.close();
|
|
}}
|
|
>
|
|
Create
|
|
</StyledButton>
|
|
</Form>
|
|
</Popover>
|
|
}
|
|
>
|
|
<AddPlaylistButton
|
|
size="sm"
|
|
onClick={() =>
|
|
playlistTriggerRef.current.state.isOverlayShown
|
|
? playlistTriggerRef.current.close()
|
|
: playlistTriggerRef.current.open()
|
|
}
|
|
/>
|
|
</Whisper>
|
|
}
|
|
searchQuery={searchQuery}
|
|
handleSearch={(e: any) => setSearchQuery(e)}
|
|
clearSearchQuery={() => setSearchQuery('')}
|
|
showViewTypeButtons
|
|
viewTypeSetting="playlist"
|
|
showSearchBar
|
|
handleListClick={() => setViewType('list')}
|
|
handleGridClick={() => setViewType('grid')}
|
|
/>
|
|
}
|
|
>
|
|
{viewType === 'list' && (
|
|
<ListViewType
|
|
data={
|
|
searchQuery === ''
|
|
? playlists
|
|
: playlists.filter((playlist: any) => {
|
|
return (
|
|
playlist.name.toLowerCase().includes(searchQuery.toLowerCase()) ||
|
|
playlist.comment?.toLowerCase().includes(searchQuery.toLowerCase())
|
|
);
|
|
})
|
|
}
|
|
handleRowClick={handleRowClick}
|
|
tableColumns={settings.getSync('playlistListColumns')}
|
|
rowHeight={Number(settings.getSync('playlistListRowHeight'))}
|
|
fontSize={settings.getSync('playlistListFontSize')}
|
|
cacheImages={{
|
|
enabled: settings.getSync('cacheImages'),
|
|
cacheType: 'playlist',
|
|
cacheIdProperty: 'id',
|
|
}}
|
|
listType="playlist"
|
|
virtualized
|
|
/>
|
|
)}
|
|
{viewType === 'grid' && (
|
|
<GridViewType
|
|
data={searchQuery === '' ? playlists : filteredData}
|
|
cardTitle={{
|
|
prefix: 'playlist',
|
|
property: 'name',
|
|
urlProperty: 'id',
|
|
}}
|
|
cardSubtitle={{
|
|
prefix: 'playlist',
|
|
property: 'songCount',
|
|
unit: ' tracks',
|
|
}}
|
|
playClick={{ type: 'playlist', idProperty: 'id' }}
|
|
size={Number(settings.getSync('gridCardSize'))}
|
|
cacheType="playlist"
|
|
/>
|
|
)}
|
|
</GenericPage>
|
|
);
|
|
};
|
|
|
|
export default PlaylistList;
|
|
|