Clicking on artist in results now opens its tab.

pull/20/head
Sander Vocke 5 years ago
parent d4d4c67672
commit e02c99954a
  1. 3
      client/src/components/MainWindow.tsx
  2. 36
      client/src/components/tables/ResultsTable.tsx
  3. 15
      client/src/components/windows/ArtistWindow.tsx
  4. 11
      client/src/components/windows/QueryWindow.tsx

@ -47,6 +47,7 @@ export function MainWindowReducer(state: MainWindowState, action: any) {
activeTab: state.activeTab >= (newSize - 1) ? (newSize - 1) : state.activeTab, activeTab: state.activeTab >= (newSize - 1) ? (newSize - 1) : state.activeTab,
} }
case MainWindowStateActions.AddTab: case MainWindowStateActions.AddTab:
console.log("Add tab: ", action)
return { return {
...state, ...state,
tabStates: [...state.tabStates, action.tabState], tabStates: [...state.tabStates, action.tabState],
@ -98,11 +99,13 @@ export default function MainWindow(props: any) {
return <QueryWindow return <QueryWindow
state={tabState} state={tabState}
dispatch={tabDispatch} dispatch={tabDispatch}
mainDispatch={dispatch}
/> />
case WindowType.Artist: case WindowType.Artist:
return <ArtistWindow return <ArtistWindow
state={tabState} state={tabState}
dispatch={tabDispatch} dispatch={tabDispatch}
mainDispatch={dispatch}
/> />
default: default:
throw new Error("Unimplemented window type"); throw new Error("Unimplemented window type");

@ -1,17 +1,21 @@
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 { MainWindowStateActions } from '../MainWindow';
import { newWindowReducer, WindowType } from '../windows/Windows';
export interface SongGetters { export interface SongGetters {
getTitle: (song: any) => string, getTitle: (song: any) => string,
getArtist: (song: any) => string, getArtistNames: (song: any) => string[],
getAlbum: (song: any) => string, getArtistIds: (song: any) => number[],
getTags: (song: any) => string[][], // Each tag is represented as a series of strings. getAlbumNames: (song: any) => string[],
getTagNames: (song: any) => string[][], // Each tag is represented as a series of strings.
} }
export interface IProps { export interface IProps {
songs: any[], songs: any[],
songGetters: SongGetters, songGetters: SongGetters,
mainDispatch: (action: any) => void,
} }
export function SongTable(props: IProps) { export function SongTable(props: IProps) {
@ -36,9 +40,11 @@ export function SongTable(props: IProps) {
<TableBody> <TableBody>
{props.songs.map((song: any) => { {props.songs.map((song: any) => {
const title = props.songGetters.getTitle(song); const title = props.songGetters.getTitle(song);
const artist = props.songGetters.getArtist(song); // TODO / FIXME: display artists and albums separately!
const album = props.songGetters.getAlbum(song); const artist = stringifyList(props.songGetters.getArtistNames(song));
const tags = props.songGetters.getTags(song).map((tag: string[]) => { const mainArtistId = props.songGetters.getArtistIds(song)[0];
const album = stringifyList(props.songGetters.getAlbumNames(song));
const tags = props.songGetters.getTagNames(song).map((tag: string[]) => {
return <Box ml={0.5} mr={0.5}> return <Box ml={0.5} mr={0.5}>
<Chip size="small" label={stringifyList(tag, undefined, (idx: number, e: string) => { <Chip size="small" label={stringifyList(tag, undefined, (idx: number, e: string) => {
return (idx === 0) ? e : " / " + e; return (idx === 0) ? e : " / " + e;
@ -46,6 +52,20 @@ export function SongTable(props: IProps) {
</Box> </Box>
}); });
const onClickArtist = () => {
console.log("onClick!")
props.mainDispatch({
type: MainWindowStateActions.AddTab,
tabState: {
artistId: mainArtistId,
metadata: null,
},
tabLabel: "Artist " + mainArtistId,
tabReducer: newWindowReducer[WindowType.Artist],
tabType: WindowType.Artist,
})
}
const TextCell = (props: any) => { const TextCell = (props: any) => {
const classes = makeStyles({ const classes = makeStyles({
button: { button: {
@ -56,7 +76,7 @@ export function SongTable(props: IProps) {
} }
})(); })();
return <TableCell padding="none" {...props}> return <TableCell padding="none" {...props}>
<Button className={classes.button} fullWidth={true}> <Button className={classes.button} fullWidth={true} onClick={props._onClick}>
<Box <Box
width="100%" width="100%"
display="flex" display="flex"
@ -71,7 +91,7 @@ export function SongTable(props: IProps) {
return <TableRow key={title}> return <TableRow key={title}>
<TextCell align="left">{title}</TextCell> <TextCell align="left">{title}</TextCell>
<TextCell align="left">{artist}</TextCell> <TextCell align="left" _onClick={onClickArtist}>{artist}</TextCell>
<TextCell align="left">{album}</TextCell> <TextCell align="left">{album}</TextCell>
<TableCell padding="none" align="left" width="25%"> <TableCell padding="none" align="left" width="25%">
<Box display="flex" alignItems="center"> <Box display="flex" alignItems="center">

@ -1,5 +1,6 @@
import React, { useEffect } from 'react'; import React, { useEffect } from 'react';
import { Box } from '@material-ui/core'; import { Box, Typography } from '@material-ui/core';
import PersonIcon from '@material-ui/icons/Person';
import * as serverApi from '../../api'; import * as serverApi from '../../api';
export interface ArtistMetadata { export interface ArtistMetadata {
@ -26,7 +27,8 @@ export function ArtistWindowReducer(state: ArtistWindowState, action: any) {
export interface IProps { export interface IProps {
state: ArtistWindowState, state: ArtistWindowState,
dispatch: (action: any) => void dispatch: (action: any) => void,
mainDispatch: (action: any) => void,
} }
export async function getArtistMetadata(id: number) { export async function getArtistMetadata(id: number) {
@ -83,9 +85,16 @@ export default function ArtistWindow(props: IProps) {
return <Box width="100%" justifyContent="center" display="flex" flexWrap="wrap"> return <Box width="100%" justifyContent="center" display="flex" flexWrap="wrap">
<Box <Box
m={1} m={1}
mt={4}
width="80%" width="80%"
> >
{metadata && metadata.name} <PersonIcon style={{ fontSize: 80 }}/>
</Box>
<Box
m={1}
width="80%"
>
{metadata && <Typography variant="h4">{metadata.name}</Typography>}
</Box> </Box>
</Box> </Box>
} }

@ -50,7 +50,8 @@ export function QueryWindowReducer(state: QueryWindowState, action: any) {
export interface IProps { export interface IProps {
state: QueryWindowState, state: QueryWindowState,
dispatch: (action: any) => void dispatch: (action: any) => void,
mainDispatch: (action: any) => void,
} }
export default function QueryWindow(props: IProps) { export default function QueryWindow(props: IProps) {
@ -72,9 +73,10 @@ export default function QueryWindow(props: IProps) {
const songGetters = { const songGetters = {
getTitle: (song: any) => song.title, getTitle: (song: any) => song.title,
getArtist: (song: any) => stringifyList(song.artists, (a: any) => a.name), getArtistNames: (song: any) => song.artists.map((a: any) => a.name),
getAlbum: (song: any) => stringifyList(song.albums, (a: any) => a.name), getArtistIds: (song: any) => song.artists.map((a: any) => a.artistId),
getTags: (song: any) => { getAlbumNames: (song: any) => song.albums.map((a: any) => a.name),
getTagNames: (song: any) => {
// Recursively resolve the name. // Recursively resolve the name.
const resolveTag = (tag: any) => { const resolveTag = (tag: any) => {
var r = [tag.name]; var r = [tag.name];
@ -152,6 +154,7 @@ export default function QueryWindow(props: IProps) {
<SongTable <SongTable
songs={showResults} songs={showResults}
songGetters={songGetters} songGetters={songGetters}
mainDispatch={props.mainDispatch}
/> />
{loading && <LinearProgress />} {loading && <LinearProgress />}
</Box> </Box>

Loading…
Cancel
Save