From 75ef43dffbd09f0c525913308385abb39954126d Mon Sep 17 00:00:00 2001 From: jeffvli Date: Wed, 4 Jan 2023 15:54:25 -0800 Subject: [PATCH] Add initial nd smart playlist ui --- src/renderer/api/navidrome.types.ts | 37 + .../components/query-builder/index.tsx | 90 +-- .../query-builder/query-builder-option.tsx | 38 +- .../components/playlist-query-builder.tsx | 632 +++++++++--------- .../playlist-detail-song-list-route.tsx | 105 ++- src/renderer/features/playlists/utils.ts | 109 +++ 6 files changed, 604 insertions(+), 407 deletions(-) create mode 100644 src/renderer/features/playlists/utils.ts diff --git a/src/renderer/api/navidrome.types.ts b/src/renderer/api/navidrome.types.ts index 91cdeca6..f7635534 100644 --- a/src/renderer/api/navidrome.types.ts +++ b/src/renderer/api/navidrome.types.ts @@ -339,3 +339,40 @@ export type NDPlaylistSongList = { startIndex: number; totalRecordCount: number; }; + +export const NDSongQueryFields = [ + { label: 'Title', value: 'title' }, + { label: 'Album', value: 'album' }, + { label: 'Artist', value: 'artist' }, + { label: 'Album artist', value: 'albumartist' }, + { label: 'Has cover art', value: 'hascoverart' }, + { label: 'Track number', value: 'tracknumber' }, + { label: 'Disc number', value: 'discnumber' }, + { label: 'Year', value: 'year' }, + { label: 'Size', value: 'size' }, + { label: 'Is compilation', value: 'compilation' }, + { label: 'Date added', value: 'dateadded' }, + { label: 'Date modified', value: 'datemodified' }, + { label: 'Disc subtitle', value: 'discsubtitle' }, + { label: 'Comment', value: 'comment' }, + { label: 'Lyrics', value: 'lyrics' }, + { label: 'Sort title', value: 'sorttitle' }, + { label: 'Sort album', value: 'sortalbum' }, + { label: 'Sort artist', value: 'sortartist' }, + { label: 'Sort album artist', value: 'sortalbumartist' }, + { label: 'Album type', value: 'albumtype' }, + { label: 'Album comment', value: 'albumcomment' }, + { label: 'Catalog number', value: 'catalognumber' }, + { label: 'File path', value: 'filepath' }, + { label: 'File type', value: 'filetype' }, + { label: 'Duration', value: 'duration' }, + { label: 'Bitrate', value: 'bitrate' }, + { label: 'BPM', value: 'bpm' }, + { label: 'Channels', value: 'channels' }, + { label: 'Genre', value: 'genre' }, + { label: 'Is favorite', value: 'loved' }, + { label: 'Date favorited', value: 'dateloved' }, + { label: 'Last played', value: 'lastplayed' }, + { label: 'Play count', value: 'playcount' }, + { label: 'Rating', value: 'rating' }, +]; diff --git a/src/renderer/components/query-builder/index.tsx b/src/renderer/components/query-builder/index.tsx index 41d9febe..82b59567 100644 --- a/src/renderer/components/query-builder/index.tsx +++ b/src/renderer/components/query-builder/index.tsx @@ -1,25 +1,11 @@ import { Group, Stack } from '@mantine/core'; import { Select } from '/@/renderer/components/select'; -import { FilterGroupType } from '/@/renderer/types'; import { AnimatePresence, motion } from 'framer-motion'; import { RiAddLine, RiMore2Line } from 'react-icons/ri'; import { Button } from '/@/renderer/components/button'; import { DropdownMenu } from '/@/renderer/components/dropdown-menu'; import { QueryBuilderOption } from '/@/renderer/components/query-builder/query-builder-option'; - -export type AdvancedFilterGroup = { - children: AdvancedFilterGroup[]; - rules: AdvancedFilterRule[]; - type: FilterGroupType; - uniqueId: string; -}; - -export type AdvancedFilterRule = { - field?: string | null; - operator?: string | null; - uniqueId: string; - value?: string | number | Date | undefined | null | any; -}; +import { QueryBuilderGroup, QueryBuilderRule } from '/@/renderer/types'; const FILTER_GROUP_OPTIONS_DATA = [ { @@ -32,58 +18,16 @@ const FILTER_GROUP_OPTIONS_DATA = [ }, ]; -// const queryJson = [ -// { -// any: [{ is: { loved: true } }, { gt: { rating: 3 } }], -// }, -// { inTheRange: { year: [1981, 1990] } }, -// ]; - -// const parseQuery = (query: Record[]) => { -// // for (const ruleset in query) { -// // // console.log('key', key); -// // // console.log('query[key]', query[key]); -// // // console.log('Object.keys(query[key])', Object.keys(query[key])); -// // // console.log('Object.values(query[key])', Object.values(query[key])); -// // // console.log('Object.entries(query[key])', Object.entries(query[key])); - -// // const keys = Object.keys(query[ruleset]); -// // } - -// const res = flatMapDeep(query, flatten); -// console.log('res', res); - -// return res; -// }; - -// const OperatorSelect = ({ value, onChange }: any) => { -// const handleChange = (e: any) => { -// onChange(e); -// }; - -// return ( -//