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.
 
 
 
 

198 lines
6.6 KiB

import React, { useState, useEffect } from 'react';
import { Query, toApiQuery, QueryOrdering, TypesIncluded, QueryKeys, OrderKey } from '../types/Query';
import FilterControl from './FilterControl';
import * as serverApi from '../api';
import BrowseWindow, { Item } from './BrowseWindow';
import { FormControl, FormLabel, FormGroup, FormControlLabel, Checkbox, Select, MenuItem } from '@material-ui/core';
const _ = require('lodash');
interface ItemTypeCheckboxesProps {
types: TypesIncluded,
onChange: (types: TypesIncluded) => void;
}
function ItemTypeCheckboxes(props: ItemTypeCheckboxesProps) {
const songChange = (v: any) => {
props.onChange({
[QueryKeys.Songs]: v.target.checked,
[QueryKeys.Artists]: props.types[QueryKeys.Artists],
[QueryKeys.Tags]: props.types[QueryKeys.Tags]
});
}
const artistChange = (v: any) => {
props.onChange({
[QueryKeys.Songs]: props.types[QueryKeys.Songs],
[QueryKeys.Artists]: v.target.checked,
[QueryKeys.Tags]: props.types[QueryKeys.Tags]
});
}
const tagChange = (v: any) => {
props.onChange({
[QueryKeys.Songs]: props.types[QueryKeys.Songs],
[QueryKeys.Artists]: props.types[QueryKeys.Artists],
[QueryKeys.Tags]: v.target.checked
});
}
return <FormControl component='fieldset'>
<FormLabel component='legend'>Result types</FormLabel>
<FormGroup>
<FormControlLabel
control={<Checkbox checked={props.types[QueryKeys.Songs]} onChange={songChange} name='Songs' />}
label="Songs"
/>
<FormControlLabel
control={<Checkbox checked={props.types[QueryKeys.Artists]} onChange={artistChange} name='Artists' />}
label="Artists"
/>
<FormControlLabel
control={<Checkbox checked={props.types[QueryKeys.Tags]} onChange={tagChange} name='Tags' />}
label="Tags"
/>
</FormGroup>
</FormControl>;
}
interface OrderingWidgetProps {
ordering: QueryOrdering,
onChange: (o: QueryOrdering) => void;
}
function OrderingWidget(props: OrderingWidgetProps) {
const onTypeChange = (e: any) => {
props.onChange({
[QueryKeys.OrderBy]: {
[QueryKeys.OrderKey]: e.target.value,
},
[QueryKeys.Ascending]: props.ordering[QueryKeys.Ascending],
});
}
const onAscendingChange = (e: any) => {
props.onChange({
[QueryKeys.OrderBy]: props.ordering[QueryKeys.OrderBy],
[QueryKeys.Ascending]: (e.target.value == 'asc'),
});
}
return <FormControl component='fieldset'>
<FormLabel component='legend'>Ordering</FormLabel>
<FormGroup>
<Select
onChange={onTypeChange}
value={props.ordering[QueryKeys.OrderBy][QueryKeys.OrderKey]}
>
<MenuItem value={OrderKey.Name}>Name</MenuItem>
</Select>
<Select
onChange={onAscendingChange}
value={props.ordering[QueryKeys.Ascending] ? 'asc' : 'desc'}
>
<MenuItem value={'asc'}>Ascending</MenuItem>
<MenuItem value={'desc'}>Descending</MenuItem>
</Select>
</FormGroup>
</FormControl>;
}
function toServerOrdering(o: QueryOrdering | undefined): serverApi.Ordering {
if (!o) {
return {
orderBy: {
type: serverApi.OrderByType.Name
},
ascending: true
};
}
const keys = {
[OrderKey.Name]: serverApi.OrderByType.Name,
};
return {
orderBy: {
type: keys[o[QueryKeys.OrderBy][QueryKeys.OrderKey]]
},
ascending: o[QueryKeys.Ascending],
}
}
export interface IProps {
query: Query | undefined,
typesIncluded: TypesIncluded | undefined,
resultOrder: QueryOrdering | undefined,
onQueryChange: (q: Query) => void,
onTypesChange: (t: TypesIncluded) => void,
onOrderChange: (o: QueryOrdering) => void,
}
export default function QueryBrowseWindow(props: IProps) {
const [songs, setSongs] = useState<serverApi.SongDetails[]>([]);
const [artists, setArtists] = useState<serverApi.ArtistDetails[]>([]);
//const [tags, setTags] = useState<serverApi.TagDetails[]>([]);
var items: Item[] = [];
props.typesIncluded && props.typesIncluded[QueryKeys.Songs] && items.push(...songs);
props.typesIncluded && props.typesIncluded[QueryKeys.Artists] && items.push(...artists);
useEffect(() => {
if (!props.query) { return; }
const q = _.cloneDeep(props.query);
const r = _.cloneDeep(props.resultOrder);
const t = _.cloneDeep(props.typesIncluded);
const request: serverApi.QueryRequest = {
query: toApiQuery(props.query),
offsetsLimits: {
songOffset: 0,
songLimit: 5, // TODO
artistOffset: 0,
artistLimit: 5,
tagOffset: 0,
tagLimit: 5,
},
ordering: toServerOrdering(props.resultOrder),
}
const requestOpts = {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(request)
};
fetch(serverApi.QueryEndpoint, requestOpts)
.then((response: any) => response.json())
.then((json: any) => {
const match = _.isEqual(q, props.query) && _.isEqual(r, props.resultOrder) && _.isEqual(t, props.typesIncluded);
'songs' in json && match && setSongs(json.songs);
'artists' in json && match && setArtists(json.artists);
});
}, [props.query]);
return <>
<FormControl component='fieldset'>
<FormLabel component='legend'>Query</FormLabel>
<FilterControl
query={props.query}
onChangeQuery={props.onQueryChange}
/>
</FormControl>
<ItemTypeCheckboxes
types={props.typesIncluded || {
[QueryKeys.Songs]: true,
[QueryKeys.Artists]: true,
[QueryKeys.Tags]: true,
}}
onChange={props.onTypesChange}
/>
<OrderingWidget
ordering={props.resultOrder || {
[QueryKeys.OrderBy]: {
[QueryKeys.OrderKey]: OrderKey.Name
},
[QueryKeys.Ascending]: true
}}
onChange={props.onOrderChange}
/>
<BrowseWindow items={items} />
</>
}