Query window uses a reducer.

pull/20/head
Sander Vocke 5 years ago
parent f3850eff97
commit 16654795d2
  1. 4
      client/public/manifest.json
  2. 15
      client/src/components/MainWindow.tsx
  3. 16
      client/src/components/querybuilder/QueryBuilder.tsx
  4. 60
      client/src/components/windows/QueryWindow.tsx

@ -1,6 +1,6 @@
{
"short_name": "React App",
"name": "Create React App Sample",
"short_name": "MuDBase",
"name": "MuDBase: self-hosted music management",
"icons": [
{
"src": "favicon.ico",

@ -1,8 +1,8 @@
import React from 'react';
import React, { useReducer } from 'react';
import { ThemeProvider, CssBaseline, createMuiTheme } from '@material-ui/core';
import { grey } from '@material-ui/core/colors';
import AppBar from './appbar/AppBar';
import QueryWindow from './windows/QueryWindow';
import QueryWindow, { QueryWindowReducer } from './windows/QueryWindow';
var _ = require('lodash');
const darkTheme = createMuiTheme({
@ -15,9 +15,18 @@ const darkTheme = createMuiTheme({
});
export default function MainWindow(props: any) {
const [state, dispatch] = useReducer(QueryWindowReducer, {
query: null,
resultsForQuery: null,
editingQuery: false,
});
return <ThemeProvider theme={darkTheme}>
<CssBaseline />
<AppBar />
<QueryWindow />
<QueryWindow
state={state}
dispatch={dispatch}
/>
</ThemeProvider>
}

@ -1,4 +1,4 @@
import React, { useState } from 'react';
import React from 'react';
import { Box } from '@material-ui/core';
import QBQueryButton from './QBEditButton';
import { QBQueryElem } from './QBQueryElem';
@ -20,20 +20,20 @@ export interface Requests {
export interface IProps {
query: QueryElem | null,
editing: boolean,
onChangeEditing: (e: boolean) => void,
onChangeQuery: (q: QueryElem | null) => void,
requestFunctions: Requests,
}
export default function QueryBuilder(props: IProps) {
const [editing, setEditing] = useState<boolean>(false);
const simpleQuery = simplify(props.query);
const showQuery = editing ?
const showQuery = props.editing ?
addPlaceholders(simpleQuery, null) : simpleQuery;
const onReplace = (q: any) => {
const newQ = removePlaceholders(q);
setEditing(false);
props.onChangeEditing(false);
props.onChangeQuery(newQ);
}
@ -41,15 +41,15 @@ export default function QueryBuilder(props: IProps) {
<Box display="flex" alignItems="center">
<Box m={2}>
<QBQueryButton
onClick={() => setEditing(!editing)}
editing={editing}
onClick={() => props.onChangeEditing(!props.editing)}
editing={props.editing}
/>
</Box>
<Box m={2}>
{showQuery && <QBQueryElem
elem={showQuery}
onReplace={onReplace}
editingQuery={editing}
editingQuery={props.editing}
requestFunctions={props.requestFunctions}
/>}
</Box>

@ -18,14 +18,54 @@ const darkTheme = createMuiTheme({
},
});
export default function QueryWindow(props: any) {
interface ResultsFor {
for: QueryElem,
results: any[],
};
export interface ResultsForQuery {
for: QueryElem,
results: any[],
};
const [query, setQuery] = useState<QueryElem | null>(null);
const [resultsFor, setResultsFor] = useState<ResultsFor | null>(null);
export interface QueryWindowState {
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
}
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 : [];
@ -71,7 +111,7 @@ export default function QueryWindow(props: any) {
const response = await fetch((process.env.REACT_APP_BACKEND || "") + serverApi.QueryEndpoint, requestOpts)
let json: any = await response.json();
if (_.isEqual(query, _query)) {
setResultsFor({
setResultsForQuery({
for: _query,
results: json.songs,
})
@ -83,7 +123,7 @@ export default function QueryWindow(props: any) {
if (query) {
doQuery(query);
} else {
setResultsFor(null);
setResultsForQuery(null);
}
}, [query]);
@ -95,6 +135,8 @@ export default function QueryWindow(props: any) {
<QueryBuilder
query={query}
onChangeQuery={setQuery}
editing={editing}
onChangeEditing={setEditingQuery}
requestFunctions={{
getArtists: getArtists,
getSongTitles: getSongTitles,

Loading…
Cancel
Save