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.
146 lines
4.5 KiB
146 lines
4.5 KiB
import React, { useEffect } from 'react'; |
|
import { createMuiTheme, Box, LinearProgress } from '@material-ui/core'; |
|
import { QueryElem, toApiQuery } from '../../lib/query/Query'; |
|
import QueryBuilder from '../querybuilder/QueryBuilder'; |
|
import * as serverApi from '../../api'; |
|
import SongTable from '../tables/ResultsTable'; |
|
import { songGetters } from '../../lib/songGetters'; |
|
import { getArtists, getSongTitles, getAlbums, getTags } from '../../lib/query/Getters'; |
|
import { grey } from '@material-ui/core/colors'; |
|
import { WindowState } from './Windows'; |
|
var _ = require('lodash'); |
|
|
|
const darkTheme = createMuiTheme({ |
|
palette: { |
|
type: 'dark', |
|
primary: { |
|
main: grey[100], |
|
} |
|
}, |
|
}); |
|
|
|
export interface ResultsForQuery { |
|
for: QueryElem, |
|
results: any[], |
|
}; |
|
|
|
export interface QueryWindowState extends WindowState { |
|
editingQuery: boolean, |
|
query: QueryElem | null, |
|
resultsForQuery: ResultsForQuery | null, |
|
} |
|
|
|
export enum QueryWindowStateActions { |
|
SetQuery = "setQuery", |
|
SetEditingQuery = "setEditingQuery", |
|
SetResultsForQuery = "setResultsForQuery", |
|
} |
|
|
|
export function QueryWindowReducer(state: QueryWindowState, action: any) { |
|
switch (action.type) { |
|
case QueryWindowStateActions.SetQuery: |
|
return { ...state, query: action.value } |
|
case QueryWindowStateActions.SetEditingQuery: |
|
return { ...state, editingQuery: action.value } |
|
case QueryWindowStateActions.SetResultsForQuery: |
|
return { ...state, resultsForQuery: action.value } |
|
default: |
|
throw new Error("Unimplemented QueryWindow state update.") |
|
} |
|
} |
|
|
|
export interface IProps { |
|
state: QueryWindowState, |
|
dispatch: (action: any) => void, |
|
mainDispatch: (action: any) => void, |
|
} |
|
|
|
export default function QueryWindow(props: IProps) { |
|
let query = props.state.query; |
|
let editing = props.state.editingQuery; |
|
let resultsFor = props.state.resultsForQuery; |
|
let setQuery = (q: QueryElem | null) => { |
|
props.dispatch({ type: QueryWindowStateActions.SetQuery, value: q }); |
|
} |
|
let setEditingQuery = (e: boolean) => { |
|
props.dispatch({ type: QueryWindowStateActions.SetEditingQuery, value: e }); |
|
} |
|
let setResultsForQuery = (r: ResultsForQuery | null) => { |
|
props.dispatch({ type: QueryWindowStateActions.SetResultsForQuery, value: r }); |
|
} |
|
|
|
const loading = query && (!resultsFor || !_.isEqual(resultsFor.for, query)); |
|
const showResults = (query && resultsFor && query == resultsFor.for) ? resultsFor.results : []; |
|
|
|
const doQuery = async (_query: QueryElem) => { |
|
var q: serverApi.QueryRequest = { |
|
query: toApiQuery(_query), |
|
offsetsLimits: { |
|
songOffset: 0, |
|
songLimit: 100, |
|
}, |
|
ordering: { |
|
orderBy: { |
|
type: serverApi.OrderByType.Name, |
|
}, |
|
ascending: true, |
|
}, |
|
}; |
|
|
|
const requestOpts = { |
|
method: 'POST', |
|
headers: { 'Content-Type': 'application/json' }, |
|
body: JSON.stringify(q), |
|
}; |
|
|
|
return (async () => { |
|
const response = await fetch((process.env.REACT_APP_BACKEND || "") + serverApi.QueryEndpoint, requestOpts) |
|
let json: any = await response.json(); |
|
if (_.isEqual(query, _query)) { |
|
setResultsForQuery({ |
|
for: _query, |
|
results: json.songs, |
|
}) |
|
} |
|
})(); |
|
} |
|
|
|
useEffect(() => { |
|
if (query) { |
|
doQuery(query); |
|
} else { |
|
setResultsForQuery(null); |
|
} |
|
}, [query]); |
|
|
|
return <Box width="100%" justifyContent="center" display="flex" flexWrap="wrap"> |
|
<Box |
|
m={1} |
|
width="80%" |
|
> |
|
<QueryBuilder |
|
query={query} |
|
onChangeQuery={setQuery} |
|
editing={editing} |
|
onChangeEditing={setEditingQuery} |
|
requestFunctions={{ |
|
getArtists: getArtists, |
|
getSongTitles: getSongTitles, |
|
getAlbums: getAlbums, |
|
getTags: getTags, |
|
}} |
|
/> |
|
</Box> |
|
<Box |
|
m={1} |
|
width="80%" |
|
> |
|
<SongTable |
|
songs={showResults} |
|
songGetters={songGetters} |
|
mainDispatch={props.mainDispatch} |
|
/> |
|
{loading && <LinearProgress />} |
|
</Box> |
|
</Box> |
|
} |