Add smart playlist builder to create playlist form
This commit is contained in:
parent
e5f478218e
commit
e063ee0c29
2 changed files with 70 additions and 11 deletions
|
@ -1,8 +1,14 @@
|
||||||
import { Group, Stack } from '@mantine/core';
|
import { Group, Stack } from '@mantine/core';
|
||||||
import { useForm } from '@mantine/form';
|
import { useForm } from '@mantine/form';
|
||||||
import { CreatePlaylistBody, ServerType } from '/@/renderer/api/types';
|
import { useRef, useState } from 'react';
|
||||||
import { Button, Switch, TextInput, toast } from '/@/renderer/components';
|
import { CreatePlaylistBody, ServerType, SongListSort } from '/@/renderer/api/types';
|
||||||
|
import { Button, Switch, Text, TextInput, toast } from '/@/renderer/components';
|
||||||
|
import {
|
||||||
|
PlaylistQueryBuilder,
|
||||||
|
PlaylistQueryBuilderRef,
|
||||||
|
} from '/@/renderer/features/playlists/components/playlist-query-builder';
|
||||||
import { useCreatePlaylist } from '/@/renderer/features/playlists/mutations/create-playlist-mutation';
|
import { useCreatePlaylist } from '/@/renderer/features/playlists/mutations/create-playlist-mutation';
|
||||||
|
import { convertQueryGroupToNDQuery } from '/@/renderer/features/playlists/utils';
|
||||||
import { useCurrentServer } from '/@/renderer/store';
|
import { useCurrentServer } from '/@/renderer/store';
|
||||||
|
|
||||||
interface CreatePlaylistFormProps {
|
interface CreatePlaylistFormProps {
|
||||||
|
@ -12,6 +18,7 @@ interface CreatePlaylistFormProps {
|
||||||
export const CreatePlaylistForm = ({ onCancel }: CreatePlaylistFormProps) => {
|
export const CreatePlaylistForm = ({ onCancel }: CreatePlaylistFormProps) => {
|
||||||
const mutation = useCreatePlaylist();
|
const mutation = useCreatePlaylist();
|
||||||
const server = useCurrentServer();
|
const server = useCurrentServer();
|
||||||
|
const queryBuilderRef = useRef<PlaylistQueryBuilderRef>(null);
|
||||||
|
|
||||||
const form = useForm<CreatePlaylistBody>({
|
const form = useForm<CreatePlaylistBody>({
|
||||||
initialValues: {
|
initialValues: {
|
||||||
|
@ -23,10 +30,34 @@ export const CreatePlaylistForm = ({ onCancel }: CreatePlaylistFormProps) => {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
const [isSmartPlaylist, setIsSmartPlaylist] = useState(false);
|
||||||
|
|
||||||
const handleSubmit = form.onSubmit((values) => {
|
const handleSubmit = form.onSubmit((values) => {
|
||||||
|
if (isSmartPlaylist) {
|
||||||
|
values.ndParams = {
|
||||||
|
...values.ndParams,
|
||||||
|
rules: queryBuilderRef.current?.getFilters(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const smartPlaylist = queryBuilderRef.current?.getFilters();
|
||||||
|
|
||||||
mutation.mutate(
|
mutation.mutate(
|
||||||
{ body: values },
|
{
|
||||||
|
body: {
|
||||||
|
...values,
|
||||||
|
ndParams: {
|
||||||
|
...values.ndParams,
|
||||||
|
rules:
|
||||||
|
isSmartPlaylist && smartPlaylist?.filters
|
||||||
|
? {
|
||||||
|
...convertQueryGroupToNDQuery(smartPlaylist.filters),
|
||||||
|
...smartPlaylist.extraFilters,
|
||||||
|
}
|
||||||
|
: undefined,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
onError: (err) => {
|
onError: (err) => {
|
||||||
toast.error({ message: err.message, title: 'Error creating playlist' });
|
toast.error({ message: err.message, title: 'Error creating playlist' });
|
||||||
|
@ -55,12 +86,34 @@ export const CreatePlaylistForm = ({ onCancel }: CreatePlaylistFormProps) => {
|
||||||
label="Description"
|
label="Description"
|
||||||
{...form.getInputProps('comment')}
|
{...form.getInputProps('comment')}
|
||||||
/>
|
/>
|
||||||
{isPublicDisplayed && (
|
<Group>
|
||||||
<Switch
|
{isPublicDisplayed && (
|
||||||
label="Is Public?"
|
<Switch
|
||||||
{...form.getInputProps('ndParams.public')}
|
label="Is public?"
|
||||||
/>
|
{...form.getInputProps('ndParams.public')}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{server?.type === ServerType.NAVIDROME && (
|
||||||
|
<Switch
|
||||||
|
label="Is smart playlist?"
|
||||||
|
onChange={(e) => setIsSmartPlaylist(e.currentTarget.checked)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Group>
|
||||||
|
{server?.type === ServerType.NAVIDROME && isSmartPlaylist && (
|
||||||
|
<Stack pt="1rem">
|
||||||
|
<Text>Query Editor</Text>
|
||||||
|
<PlaylistQueryBuilder
|
||||||
|
ref={queryBuilderRef}
|
||||||
|
isSaving={false}
|
||||||
|
limit={undefined}
|
||||||
|
query={undefined}
|
||||||
|
sortBy={SongListSort.ALBUM}
|
||||||
|
sortOrder="asc"
|
||||||
|
/>
|
||||||
|
</Stack>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<Group position="right">
|
<Group position="right">
|
||||||
<Button
|
<Button
|
||||||
variant="subtle"
|
variant="subtle"
|
||||||
|
|
|
@ -34,10 +34,15 @@ import {
|
||||||
SidebarItem,
|
SidebarItem,
|
||||||
} from '/@/renderer/features/sidebar/components/sidebar-item';
|
} from '/@/renderer/features/sidebar/components/sidebar-item';
|
||||||
import { AppRoute } from '/@/renderer/router/routes';
|
import { AppRoute } from '/@/renderer/router/routes';
|
||||||
import { useSidebarStore, useAppStoreActions, useCurrentSong } from '/@/renderer/store';
|
import {
|
||||||
|
useSidebarStore,
|
||||||
|
useAppStoreActions,
|
||||||
|
useCurrentSong,
|
||||||
|
useCurrentServer,
|
||||||
|
} from '/@/renderer/store';
|
||||||
import { fadeIn } from '/@/renderer/styles';
|
import { fadeIn } from '/@/renderer/styles';
|
||||||
import { CreatePlaylistForm, usePlaylistList } from '/@/renderer/features/playlists';
|
import { CreatePlaylistForm, usePlaylistList } from '/@/renderer/features/playlists';
|
||||||
import { LibraryItem, PlaylistListSort, SortOrder } from '/@/renderer/api/types';
|
import { LibraryItem, PlaylistListSort, ServerType, SortOrder } from '/@/renderer/api/types';
|
||||||
import { usePlayQueueAdd } from '/@/renderer/features/player';
|
import { usePlayQueueAdd } from '/@/renderer/features/player';
|
||||||
import { usePlayButtonBehavior } from '/@/renderer/store/settings.store';
|
import { usePlayButtonBehavior } from '/@/renderer/store/settings.store';
|
||||||
|
|
||||||
|
@ -80,6 +85,7 @@ export const Sidebar = () => {
|
||||||
const sidebar = useSidebarStore();
|
const sidebar = useSidebarStore();
|
||||||
const { setSidebar } = useAppStoreActions();
|
const { setSidebar } = useAppStoreActions();
|
||||||
const imageUrl = useCurrentSong()?.imageUrl;
|
const imageUrl = useCurrentSong()?.imageUrl;
|
||||||
|
const server = useCurrentServer();
|
||||||
|
|
||||||
const upsizedImageUrl = imageUrl
|
const upsizedImageUrl = imageUrl
|
||||||
?.replace(/size=\d+/, 'size=300')
|
?.replace(/size=\d+/, 'size=300')
|
||||||
|
@ -112,7 +118,7 @@ export const Sidebar = () => {
|
||||||
|
|
||||||
openModal({
|
openModal({
|
||||||
children: <CreatePlaylistForm onCancel={() => closeAllModals()} />,
|
children: <CreatePlaylistForm onCancel={() => closeAllModals()} />,
|
||||||
size: 'sm',
|
size: server?.type === ServerType?.NAVIDROME ? 'lg' : 'sm',
|
||||||
title: 'Create Playlist',
|
title: 'Create Playlist',
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
Reference in a new issue