Fix routing.

pull/28/head
Sander Vocke 5 years ago
parent 679a00b77d
commit c249c7495d
  1. 48
      client/src/components/MainWindow.tsx
  2. 40
      client/src/components/appbar/AddTabMenu.tsx
  3. 86
      client/src/components/appbar/AppBar.tsx
  4. 14
      client/src/components/tables/ResultsTable.tsx
  5. 35
      client/src/components/windows/Windows.tsx
  6. 29
      client/src/components/windows/album/AlbumWindow.tsx
  7. 24
      client/src/components/windows/artist/ArtistWindow.tsx
  8. 20
      client/src/components/windows/manage_tags/ManageTagsWindow.tsx
  9. 23
      client/src/components/windows/query/QueryWindow.tsx
  10. 20
      client/src/components/windows/song/SongWindow.tsx
  11. 27
      client/src/components/windows/tag/TagWindow.tsx

@ -1,10 +1,9 @@
import React, { useReducer, Reducer } from 'react'; import React, { useReducer, Reducer, useContext } from 'react';
import { ThemeProvider, CssBaseline, createMuiTheme } from '@material-ui/core'; import { ThemeProvider, CssBaseline, createMuiTheme } from '@material-ui/core';
import { grey } from '@material-ui/core/colors'; import { grey } from '@material-ui/core/colors';
import AppBar from './appbar/AppBar'; import AppBar, { AppBarTab } from './appbar/AppBar';
import QueryWindow, { QueryWindowReducer } from './windows/query/QueryWindow'; import QueryWindow, { QueryWindowReducer } from './windows/query/QueryWindow';
import { NewTabProps } from './appbar/AddTabMenu'; import { newWindowState, newWindowReducer, WindowType } from './windows/Windows';
import { newWindowState, newWindowReducer, WindowType, Window } from './windows/Windows';
import ArtistWindow from './windows/artist/ArtistWindow'; import ArtistWindow from './windows/artist/ArtistWindow';
import AlbumWindow from './windows/album/AlbumWindow'; import AlbumWindow from './windows/album/AlbumWindow';
import TagWindow from './windows/tag/TagWindow'; import TagWindow from './windows/tag/TagWindow';
@ -22,54 +21,37 @@ const darkTheme = createMuiTheme({
}, },
}); });
function WindowContent(props: {
type: WindowType,
}) {
const { id } = useParams();
return <Window type={props.type} stateOverride={id ? { "id": id } : {}} />
}
export default function MainWindow(props: any) { export default function MainWindow(props: any) {
const [windowState, windowDispatch] = useReducer(
QueryWindowReducer,
{
editingQuery: false,
query: null,
resultsForQuery: null,
},
);
return <ThemeProvider theme={darkTheme}> return <ThemeProvider theme={darkTheme}>
<CssBaseline /> <CssBaseline />
<BrowserRouter> <BrowserRouter>
<AppBar
tabLabels={[]}
selectedTab={0}
setSelectedTab={(t: number) => { }}
onCloseTab={(t: number) => { }}
onAddTab={(w: NewTabProps) => { }}
/>
<Switch> <Switch>
<Route exact path="/"> <Route exact path="/">
<Redirect to={"/query"} /> <Redirect to={"/query"} />
</Route> </Route>
<Route path="/query"> <Route path="/query">
<WindowContent type={WindowType.Query} /> <AppBar selectedTab={AppBarTab.Query} />
<QueryWindow/>
</Route> </Route>
<Route path="/artist/:id"> <Route path="/artist/:id">
<WindowContent type={WindowType.Artist} /> <AppBar selectedTab={null} />
<ArtistWindow/>
</Route> </Route>
<Route path="/tag/:id"> <Route path="/tag/:id">
<WindowContent type={WindowType.Tag} /> <AppBar selectedTab={null} />
<TagWindow/>
</Route> </Route>
<Route path="/album/:id"> <Route path="/album/:id">
<WindowContent type={WindowType.Album} /> <AppBar selectedTab={null} />
<AlbumWindow/>
</Route> </Route>
<Route path="/song/:id"> <Route path="/song/:id">
<WindowContent type={WindowType.Song} /> <AppBar selectedTab={null} />
<SongWindow/>
</Route> </Route>
<Route path="/tags"> <Route path="/tags">
<WindowContent type={WindowType.ManageTags} /> <AppBar selectedTab={AppBarTab.Tags} />
<ManageTagsWindow/>
</Route> </Route>
</Switch> </Switch>
</BrowserRouter> </BrowserRouter>

@ -1,40 +0,0 @@
import React from 'react';
import { WindowType } from '../windows/Windows';
import { Menu, MenuItem } from '@material-ui/core';
export interface NewTabProps {
windowType: WindowType,
}
export interface IProps {
anchorEl: null | HTMLElement,
onClose: () => void,
onCreateTab: (q: NewTabProps) => void,
}
export default function AddTabMenu(props: IProps) {
return <Menu
anchorEl={props.anchorEl}
keepMounted
open={Boolean(props.anchorEl)}
onClose={props.onClose}
>
<MenuItem disabled={true}>New Tab</MenuItem>
<MenuItem
onClick={() => {
props.onClose();
props.onCreateTab({
windowType: WindowType.Query,
})
}}
>{WindowType.Query}</MenuItem>
<MenuItem
onClick={() => {
props.onClose();
props.onCreateTab({
windowType: WindowType.ManageTags,
})
}}
>Manage Tags</MenuItem>
</Menu>
}

@ -1,60 +1,31 @@
import React from 'react'; import React from 'react';
import { AppBar as MuiAppBar, Box, Tab as MuiTab, Tabs, IconButton } from '@material-ui/core'; import { AppBar as MuiAppBar, Box, Tab as MuiTab, Tabs, IconButton, Typography } from '@material-ui/core';
import CloseIcon from '@material-ui/icons/Close'; import CloseIcon from '@material-ui/icons/Close';
import AddIcon from '@material-ui/icons/Add'; import SearchIcon from '@material-ui/icons/Search';
import AddTabMenu, { NewTabProps } from './AddTabMenu'; import LocalOfferIcon from '@material-ui/icons/LocalOffer';
import { Link } from 'react-router-dom'; import { Link, useHistory } from 'react-router-dom';
import { WindowType } from '../windows/Windows';
export interface IProps {
tabLabels: string[], export enum AppBarTab {
selectedTab: number, Query = 0,
setSelectedTab: (n: number) => void, Tags,
onCloseTab: (idx: number) => void,
onAddTab: (w: NewTabProps) => void,
}
export interface TabProps {
onClose: () => void,
} }
export function Tab(props: any) { export const appBarTabProps: Record<any, any> = {
const { onClose, label, ...restProps } = props; [AppBarTab.Query]: {
label: <Box display="flex"><SearchIcon/><Typography variant="button">Query</Typography></Box>,
const labelElem = <Box path: "/query",
display="flex" },
alignItems="center" [AppBarTab.Tags]: {
justifyContent="center" label: <Box display="flex"><LocalOfferIcon/><Typography variant="button">Tags</Typography></Box>,
> path: "/tags",
{label} },
<Box ml={1}>
<IconButton
size="small"
color="inherit"
onClick={onClose}
>
<CloseIcon />
</IconButton>
</Box>
</Box>;
return <MuiTab
label={labelElem}
{...restProps}
/>
} }
export default function AppBar(props: IProps) { export default function AppBar(props: {
const [addMenuAnchorEl, setAddMenuAnchorEl] = React.useState<null | HTMLElement>(null); selectedTab: AppBarTab | null
}) {
const onOpenAddMenu = (event: any) => { const history = useHistory();
setAddMenuAnchorEl(event.currentTarget);
};
const onCloseAddMenu = () => {
setAddMenuAnchorEl(null);
};
const onAddTab = (w: NewTabProps) => {
props.onAddTab(w);
};
return <> return <>
<MuiAppBar position="static" style={{ background: 'grey' }}> <MuiAppBar position="static" style={{ background: 'grey' }}>
@ -66,23 +37,16 @@ export default function AppBar(props: IProps) {
</Link> </Link>
<Tabs <Tabs
value={props.selectedTab} value={props.selectedTab}
onChange={(e: any, v: number) => props.setSelectedTab(v)} onChange={(e: any, val: AppBarTab) => history.push(appBarTabProps[val].path)}
variant="scrollable" variant="scrollable"
scrollButtons="auto" scrollButtons="auto"
> >
{props.tabLabels.map((l: string, idx: number) => <Tab {Object.keys(appBarTabProps).map((tab: any, idx: number) => <MuiTab
label={l} label={appBarTabProps[tab].label}
value={idx} value={idx}
onClose={() => props.onCloseTab(idx)}
/>)} />)}
</Tabs> </Tabs>
<IconButton color="inherit" onClick={onOpenAddMenu}><AddIcon /></IconButton>
</Box> </Box>
</MuiAppBar> </MuiAppBar>
<AddTabMenu
anchorEl={addMenuAnchorEl}
onClose={onCloseAddMenu}
onCreateTab={onAddTab}
/>
</> </>
} }

@ -1,13 +1,7 @@
import React from 'react'; import React from 'react';
import { TableContainer, Table, TableHead, TableRow, TableCell, Paper, makeStyles, TableBody, Chip, Box, Button } from '@material-ui/core'; import { TableContainer, Table, TableHead, TableRow, TableCell, Paper, makeStyles, TableBody, Chip, Box, Button } from '@material-ui/core';
import stringifyList from '../../lib/stringifyList'; import stringifyList from '../../lib/stringifyList';
import { newWindowReducer, WindowType } from '../windows/Windows'; import { useHistory } from 'react-router';
import PersonIcon from '@material-ui/icons/Person';
import AlbumIcon from '@material-ui/icons/Album';
import AudiotrackIcon from '@material-ui/icons/Audiotrack';
import LocalOfferIcon from '@material-ui/icons/LocalOffer';
import { songGetters } from '../../lib/songGetters';
import { Redirect, useHistory } from 'react-router';
export interface SongGetters { export interface SongGetters {
getTitle: (song: any) => string, getTitle: (song: any) => string,
@ -20,12 +14,10 @@ export interface SongGetters {
getTagIds: (song: any) => number[][], // Each tag is represented as a series of ids. getTagIds: (song: any) => number[][], // Each tag is represented as a series of ids.
} }
export interface IProps { export default function SongTable(props: {
songs: any[], songs: any[],
songGetters: SongGetters, songGetters: SongGetters,
} }) {
export default function SongTable(props: IProps) {
const history = useHistory(); const history = useHistory();
const classes = makeStyles({ const classes = makeStyles({

@ -24,41 +24,6 @@ export enum WindowType {
export interface WindowState { } export interface WindowState { }
export function Window(props: {
type: WindowType,
stateOverride: any,
}) {
const [state, dispatch] = useReducer(
newWindowReducer[props.type],
newWindowState[props.type](),
);
const _state: any = {
...state,
...props.stateOverride
};
if (props.type === WindowType.Query) {
return <QueryWindow state={_state} dispatch={dispatch}/>
}
if (props.type === WindowType.Artist) {
return <ArtistWindow state={_state} dispatch={dispatch}/>
}
if (props.type === WindowType.Album) {
return <AlbumWindow state={_state} dispatch={dispatch}/>
}
if (props.type === WindowType.ManageTags) {
return <ManageTagsWindow state={_state} dispatch={dispatch}/>
}
if (props.type === WindowType.Song) {
return <SongWindow state={_state} dispatch={dispatch}/>
}
if (props.type === WindowType.Tag) {
return <TagWindow state={_state} dispatch={dispatch}/>
}
throw new Error("Unsupported window type")
}
export const newWindowReducer = { export const newWindowReducer = {
[WindowType.Query]: QueryWindowReducer, [WindowType.Query]: QueryWindowReducer,
[WindowType.Artist]: ArtistWindowReducer, [WindowType.Artist]: ArtistWindowReducer,

@ -1,4 +1,4 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState, useReducer } from 'react';
import { Box, Typography, IconButton, CircularProgress } from '@material-ui/core'; import { Box, Typography, IconButton, CircularProgress } from '@material-ui/core';
import AlbumIcon from '@material-ui/icons/Album'; import AlbumIcon from '@material-ui/icons/Album';
import * as serverApi from '../../../api'; import * as serverApi from '../../../api';
@ -10,6 +10,8 @@ import SongTable, { SongGetters } from '../../tables/ResultsTable';
import { saveAlbumChanges } from '../../../lib/saveChanges'; import { saveAlbumChanges } from '../../../lib/saveChanges';
import { QueryLeafBy, QueryLeafOp } from '../../../lib/query/Query'; import { QueryLeafBy, QueryLeafOp } from '../../../lib/query/Query';
import { queryAlbums, querySongs } from '../../../lib/backend/queries'; import { queryAlbums, querySongs } from '../../../lib/backend/queries';
import { songGetters } from '../../../lib/songGetters';
import { useParams } from 'react-router';
var _ = require('lodash'); var _ = require('lodash');
export type AlbumMetadata = serverApi.AlbumDetails; export type AlbumMetadata = serverApi.AlbumDetails;
@ -45,11 +47,6 @@ export function AlbumWindowReducer(state: AlbumWindowState, action: any) {
} }
} }
export interface IProps {
state: AlbumWindowState,
dispatch: (action: any) => void,
}
export async function getAlbumMetadata(id: number) { export async function getAlbumMetadata(id: number) {
return (await queryAlbums({ return (await queryAlbums({
query: { query: {
@ -62,7 +59,23 @@ export async function getAlbumMetadata(id: number) {
}))[0]; }))[0];
} }
export default function AlbumWindow(props: IProps) { export default function AlbumWindow(props: {}) {
const { id } = useParams();
const [state, dispatch] = useReducer(AlbumWindowReducer, {
id: id,
metadata: null,
pendingChanges: null,
songGetters: songGetters,
songsOnAlbum: null,
});
return <AlbumWindowControlled state={state} dispatch={dispatch} />
}
export function AlbumWindowControlled(props: {
state: AlbumWindowState,
dispatch: (action: any) => void,
}) {
let metadata = props.state.metadata; let metadata = props.state.metadata;
let pendingChanges = props.state.pendingChanges; let pendingChanges = props.state.pendingChanges;
@ -94,7 +107,7 @@ export default function AlbumWindow(props: IProps) {
props.dispatch({ props.dispatch({
type: AlbumWindowStateActions.SetSongs, type: AlbumWindowStateActions.SetSongs,
value: songs, value: songs,
}); });
})(); })();
}, [props.state.songsOnAlbum]); }, [props.state.songsOnAlbum]);

@ -1,4 +1,4 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState, useReducer } from 'react';
import { Box, Typography, IconButton, Button, CircularProgress } from '@material-ui/core'; import { Box, Typography, IconButton, Button, CircularProgress } from '@material-ui/core';
import PersonIcon from '@material-ui/icons/Person'; import PersonIcon from '@material-ui/icons/Person';
import * as serverApi from '../../../api'; import * as serverApi from '../../../api';
@ -10,6 +10,8 @@ import SongTable, { SongGetters } from '../../tables/ResultsTable';
import { saveArtistChanges } from '../../../lib/saveChanges'; import { saveArtistChanges } from '../../../lib/saveChanges';
import { QueryLeafBy, QueryLeafOp } from '../../../lib/query/Query'; import { QueryLeafBy, QueryLeafOp } from '../../../lib/query/Query';
import { queryArtists, querySongs } from '../../../lib/backend/queries'; import { queryArtists, querySongs } from '../../../lib/backend/queries';
import { songGetters } from '../../../lib/songGetters';
import { useParams } from 'react-router';
var _ = require('lodash'); var _ = require('lodash');
export type ArtistMetadata = serverApi.ArtistDetails; export type ArtistMetadata = serverApi.ArtistDetails;
@ -62,7 +64,23 @@ export async function getArtistMetadata(id: number) {
}))[0]; }))[0];
} }
export default function ArtistWindow(props: IProps) { export default function ArtistWindow(props: {}) {
const { id } = useParams();
const [state, dispatch] = useReducer(ArtistWindowReducer, {
id: id,
metadata: null,
pendingChanges: null,
songGetters: songGetters,
songsByArtist: null,
});
return <ArtistWindowControlled state={state} dispatch={dispatch} />
}
export function ArtistWindowControlled(props: {
state: ArtistWindowState,
dispatch: (action: any) => void,
}) {
let metadata = props.state.metadata; let metadata = props.state.metadata;
let pendingChanges = props.state.pendingChanges; let pendingChanges = props.state.pendingChanges;
@ -94,7 +112,7 @@ export default function ArtistWindow(props: IProps) {
props.dispatch({ props.dispatch({
type: ArtistWindowStateActions.SetSongs, type: ArtistWindowStateActions.SetSongs,
value: songs, value: songs,
}); });
})(); })();
}, [props.state.songsByArtist]); }, [props.state.songsByArtist]);

@ -1,4 +1,4 @@
import React, { useEffect, useState, ReactFragment } from 'react'; import React, { useEffect, useState, ReactFragment, useReducer } from 'react';
import { WindowState, newWindowReducer, WindowType } from '../Windows'; import { WindowState, newWindowReducer, WindowType } from '../Windows';
import { Box, Typography, Chip, IconButton, useTheme, Button } from '@material-ui/core'; import { Box, Typography, Chip, IconButton, useTheme, Button } from '@material-ui/core';
import LoyaltyIcon from '@material-ui/icons/Loyalty'; import LoyaltyIcon from '@material-ui/icons/Loyalty';
@ -127,7 +127,7 @@ export function SingleTag(props: {
const hasChildren = 'children' in tag && tag.children.length > 0; const hasChildren = 'children' in tag && tag.children.length > 0;
const [menuPos, setMenuPos] = React.useState<null | number[]>(null); const [menuPos, setMenuPos] = React.useState<null | number[]>(null);
const [expanded, setExpanded] = useState<boolean>(false); const [expanded, setExpanded] = useState<boolean>(true);
const theme = useTheme(); const theme = useTheme();
const history = useHistory(); const history = useHistory();
@ -340,7 +340,17 @@ function applyTagsChanges(tags: Record<string, any>, changes: TagChange[]) {
return retval; return retval;
} }
export default function ManageTagsWindow(props: { export default function ManageTagsWindow(props: {}) {
const [state, dispatch] = useReducer(ManageTagsWindowReducer, {
fetchedTags: null,
alert: null,
pendingChanges: [],
});
return <ManageTagsWindowControlled state={state} dispatch={dispatch} />
}
export function ManageTagsWindowControlled(props: {
state: ManageTagsWindowState, state: ManageTagsWindowState,
dispatch: (action: any) => void, dispatch: (action: any) => void,
}) { }) {
@ -368,9 +378,9 @@ export default function ManageTagsWindow(props: {
})(); })();
}, [props.state.fetchedTags]); }, [props.state.fetchedTags]);
const tagsWithChanges = annotateTagsWithChanges(props.state.fetchedTags || {}, props.state.pendingChanges) const tagsWithChanges = annotateTagsWithChanges(props.state.fetchedTags || {}, props.state.pendingChanges || [])
const changedTags = organiseTags( const changedTags = organiseTags(
applyTagsChanges(props.state.fetchedTags || {}, props.state.pendingChanges), applyTagsChanges(props.state.fetchedTags || {}, props.state.pendingChanges || []),
null); null);
const tags = organiseTags(tagsWithChanges, null); const tags = organiseTags(tagsWithChanges, null);

@ -1,4 +1,4 @@
import React, { useEffect } from 'react'; import React, { useEffect, useReducer } from 'react';
import { createMuiTheme, Box, LinearProgress } from '@material-ui/core'; import { createMuiTheme, Box, LinearProgress } from '@material-ui/core';
import { QueryElem, toApiQuery, QueryLeafBy, QueryLeafOp } from '../../../lib/query/Query'; import { QueryElem, toApiQuery, QueryLeafBy, QueryLeafOp } from '../../../lib/query/Query';
import QueryBuilder from '../../querybuilder/QueryBuilder'; import QueryBuilder from '../../querybuilder/QueryBuilder';
@ -47,7 +47,7 @@ async function getArtistNames(filter: string) {
limit: -1, limit: -1,
}); });
return [...(new Set([...(artists.map((a:any) => a.name))]))]; return [...(new Set([...(artists.map((a: any) => a.name))]))];
} }
async function getAlbumNames(filter: string) { async function getAlbumNames(filter: string) {
@ -61,7 +61,7 @@ async function getAlbumNames(filter: string) {
limit: -1, limit: -1,
}); });
return [...(new Set([...(albums.map((a:any) => a.name))]))]; return [...(new Set([...(albums.map((a: any) => a.name))]))];
} }
async function getSongTitles(filter: string) { async function getSongTitles(filter: string) {
@ -75,7 +75,7 @@ async function getSongTitles(filter: string) {
limit: -1, limit: -1,
}); });
return [...(new Set([...(songs.map((s:any) => s.title))]))]; return [...(new Set([...(songs.map((s: any) => s.title))]))];
} }
async function getTagItems() { async function getTagItems() {
@ -98,13 +98,20 @@ export function QueryWindowReducer(state: QueryWindowState, action: any) {
throw new Error("Unimplemented QueryWindow state update.") throw new Error("Unimplemented QueryWindow state update.")
} }
} }
export default function QueryWindow(props: {}) {
const [state, dispatch] = useReducer(QueryWindowReducer, {
editingQuery: false,
query: null,
resultsForQuery: null,
});
export interface IProps { return <QueryWindowControlled state={state} dispatch={dispatch} />
state: QueryWindowState,
dispatch: (action: any) => void,
} }
export default function QueryWindow(props: IProps) { export function QueryWindowControlled(props: {
state: QueryWindowState,
dispatch: (action: any) => void,
}) {
let query = props.state.query; let query = props.state.query;
let editing = props.state.editingQuery; let editing = props.state.editingQuery;
let resultsFor = props.state.resultsForQuery; let resultsFor = props.state.resultsForQuery;

@ -1,4 +1,4 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState, useReducer } from 'react';
import { Box, Typography, IconButton, Button, CircularProgress } from '@material-ui/core'; import { Box, Typography, IconButton, Button, CircularProgress } from '@material-ui/core';
import AudiotrackIcon from '@material-ui/icons/Audiotrack'; import AudiotrackIcon from '@material-ui/icons/Audiotrack';
import PersonIcon from '@material-ui/icons/Person'; import PersonIcon from '@material-ui/icons/Person';
@ -13,6 +13,8 @@ import SubmitChangesButton from '../../common/SubmitChangesButton';
import { saveSongChanges } from '../../../lib/saveChanges'; import { saveSongChanges } from '../../../lib/saveChanges';
import { QueryLeafBy, QueryLeafOp } from '../../../lib/query/Query'; import { QueryLeafBy, QueryLeafOp } from '../../../lib/query/Query';
import { querySongs } from '../../../lib/backend/queries'; import { querySongs } from '../../../lib/backend/queries';
import { songGetters } from '../../../lib/songGetters';
import { useParams } from 'react-router';
export type SongMetadata = serverApi.SongDetails; export type SongMetadata = serverApi.SongDetails;
export type SongMetadataChanges = serverApi.ModifySongRequest; export type SongMetadataChanges = serverApi.ModifySongRequest;
@ -59,7 +61,21 @@ export async function getSongMetadata(id: number) {
}))[0]; }))[0];
} }
export default function SongWindow(props: IProps) { export default function SongWindow(props: {}) {
const { id } = useParams();
const [state, dispatch] = useReducer(SongWindowReducer, {
id: id,
metadata: null,
pendingChanges: null,
});
return <SongWindowControlled state={state} dispatch={dispatch} />
}
export function SongWindowControlled(props: {
state: SongWindowState,
dispatch: (action: any) => void,
}) {
let metadata = props.state.metadata; let metadata = props.state.metadata;
let pendingChanges = props.state.pendingChanges; let pendingChanges = props.state.pendingChanges;

@ -1,4 +1,4 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState, useReducer } from 'react';
import { Box, Typography, IconButton, CircularProgress } from '@material-ui/core'; import { Box, Typography, IconButton, CircularProgress } from '@material-ui/core';
import LocalOfferIcon from '@material-ui/icons/LocalOffer'; import LocalOfferIcon from '@material-ui/icons/LocalOffer';
import * as serverApi from '../../../api'; import * as serverApi from '../../../api';
@ -10,6 +10,8 @@ import SongTable, { SongGetters } from '../../tables/ResultsTable';
import { saveTagChanges } from '../../../lib/saveChanges'; import { saveTagChanges } from '../../../lib/saveChanges';
import { queryTags, querySongs } from '../../../lib/backend/queries'; import { queryTags, querySongs } from '../../../lib/backend/queries';
import { QueryLeafBy, QueryLeafOp } from '../../../lib/query/Query'; import { QueryLeafBy, QueryLeafOp } from '../../../lib/query/Query';
import { songGetters } from '../../../lib/songGetters';
import { useParams } from 'react-router';
var _ = require('lodash'); var _ = require('lodash');
export interface FullTagMetadata extends serverApi.TagDetails { export interface FullTagMetadata extends serverApi.TagDetails {
@ -50,11 +52,6 @@ export function TagWindowReducer(state: TagWindowState, action: any) {
} }
} }
export interface IProps {
state: TagWindowState,
dispatch: (action: any) => void,
}
export async function getTagMetadata(id: number) { export async function getTagMetadata(id: number) {
var tag = (await queryTags({ var tag = (await queryTags({
query: { query: {
@ -79,7 +76,23 @@ export async function getTagMetadata(id: number) {
return tag; return tag;
} }
export default function TagWindow(props: IProps) { export default function TagWindow(props: {}) {
const { id } = useParams();
const [state, dispatch] = useReducer(TagWindowReducer,{
id: id,
metadata: null,
pendingChanges: null,
songGetters: songGetters,
songsWithTag: null,
});
return <TagWindowControlled state={state} dispatch={dispatch} />
}
export function TagWindowControlled(props: {
state: TagWindowState,
dispatch: (action: any) => void,
}) {
let metadata = props.state.metadata; let metadata = props.state.metadata;
let pendingChanges = props.state.pendingChanges; let pendingChanges = props.state.pendingChanges;

Loading…
Cancel
Save