diff --git a/client/src/components/MainWindow.tsx b/client/src/components/MainWindow.tsx
index 970cef6..d3b73f1 100644
--- a/client/src/components/MainWindow.tsx
+++ b/client/src/components/MainWindow.tsx
@@ -1,5 +1,5 @@
-import React, { useReducer, useState, Reducer } from 'react';
-import { ThemeProvider, CssBaseline, createMuiTheme, withWidth } from '@material-ui/core';
+import React, { useReducer, Reducer } 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';
@@ -48,7 +48,6 @@ export function MainWindowReducer(state: MainWindowState, action: any) {
activeTab: state.activeTab >= (newSize - 1) ? (newSize - 1) : state.activeTab,
}
case MainWindowStateActions.AddTab:
- console.log("Add tab: ", action)
return {
...state,
tabStates: [...state.tabStates, action.tabState],
@@ -65,17 +64,33 @@ export function MainWindowReducer(state: MainWindowState, action: any) {
})
}
default:
- throw new Error("Unimplemented QueryWindow state update.")
+ throw new Error("Unimplemented MainWindow state update.")
}
}
export default function MainWindow(props: any) {
const [state, dispatch] = useReducer(MainWindowReducer, {
tabStates: [
- newWindowState[WindowType.Query]()
+ newWindowState[WindowType.Query](),
+ newWindowState[WindowType.Song](),
+ newWindowState[WindowType.Album](),
+ newWindowState[WindowType.Artist](),
+ newWindowState[WindowType.Tag](),
+ ],
+ tabReducers: [
+ newWindowReducer[WindowType.Query],
+ newWindowReducer[WindowType.Song],
+ newWindowReducer[WindowType.Album],
+ newWindowReducer[WindowType.Artist],
+ newWindowReducer[WindowType.Tag],
+ ],
+ tabTypes: [
+ WindowType.Query,
+ WindowType.Song,
+ WindowType.Album,
+ WindowType.Artist,
+ WindowType.Tag,
],
- tabReducers: [newWindowReducer[WindowType.Query]],
- tabTypes: [WindowType.Query],
activeTab: 0
})
diff --git a/client/src/components/appbar/AppBar.tsx b/client/src/components/appbar/AppBar.tsx
index b7308aa..820b479 100644
--- a/client/src/components/appbar/AppBar.tsx
+++ b/client/src/components/appbar/AppBar.tsx
@@ -1,4 +1,4 @@
-import React, { useState } from 'react';
+import React from 'react';
import { AppBar as MuiAppBar, Box, Tab as MuiTab, Tabs, IconButton } from '@material-ui/core';
import CloseIcon from '@material-ui/icons/Close';
import AddIcon from '@material-ui/icons/Add';
@@ -61,7 +61,12 @@ export default function AppBar(props: IProps) {
- props.setSelectedTab(v)}>
+ props.setSelectedTab(v)}
+ variant="scrollable"
+ scrollButtons="auto"
+ >
{props.tabLabels.map((l: string, idx: number) => void,
+ onChangeChangedValue: (v: string | null) => void,
+}
+
+export default function EditableText(props: IProps) {
+ let editingValue = props.editingValue;
+ let defaultValue = props.defaultValue;
+ let changedValue = props.changedValue;
+ let onChangeEditingValue = props.onChangeEditingValue;
+ let onChangeChangedValue = props.onChangeChangedValue;
+ let editing = editingValue !== null;
+ let editingLabel = props.editingLabel;
+
+ const theme = useTheme();
+
+ const [hovering, setHovering] = useState(false);
+
+ const editButton =
+ onChangeEditingValue(changedValue || defaultValue)}
+ >
+
+
+
+
+ const discardChangesButton =
+ {
+ onChangeChangedValue(null);
+ onChangeEditingValue(null);
+ }}
+ >
+
+
+
+
+ if (editing) {
+ return
+ onChangeEditingValue(e.target.value)}
+ />
+ {
+ onChangeChangedValue(editingValue === defaultValue ? null : editingValue);
+ onChangeEditingValue(null);
+ }}
+ >
+
+ } else if (changedValue) {
+ return setHovering(true)}
+ onMouseLeave={() => setHovering(false)}
+ display="flex"
+ alignItems="center"
+ >
+ {defaultValue}→
+ {changedValue}
+ {editButton}
+ {discardChangesButton}
+
+ }
+
+ return setHovering(true)}
+ onMouseLeave={() => setHovering(false)}
+ display="flex"
+ alignItems="center"
+ >{defaultValue}{editButton};
+}
\ No newline at end of file
diff --git a/client/src/components/common/StoreLinkIcon.tsx b/client/src/components/common/StoreLinkIcon.tsx
new file mode 100644
index 0000000..7359ab0
--- /dev/null
+++ b/client/src/components/common/StoreLinkIcon.tsx
@@ -0,0 +1,28 @@
+import React from 'react';
+import { ReactComponent as GPMIcon } from '../../assets/googleplaymusic_icon.svg';
+
+export enum ExternalStore {
+ GooglePlayMusic = "GPM",
+}
+
+export interface IProps {
+ whichStore: ExternalStore,
+}
+
+export function whichStore(url: string) {
+ if(url.includes('play.google.com')) {
+ return ExternalStore.GooglePlayMusic;
+ }
+ return undefined;
+}
+
+export default function StoreLinkIcon(props: any) {
+ const { whichStore, ...restProps } = props;
+
+ switch(whichStore) {
+ case ExternalStore.GooglePlayMusic:
+ return ;
+ default:
+ throw new Error("Unknown external store: " + whichStore)
+ }
+}
\ No newline at end of file
diff --git a/client/src/components/common/SubmitChangesButton.tsx b/client/src/components/common/SubmitChangesButton.tsx
new file mode 100644
index 0000000..51ad1c5
--- /dev/null
+++ b/client/src/components/common/SubmitChangesButton.tsx
@@ -0,0 +1,13 @@
+import React from 'react';
+import { Box, Button } from '@material-ui/core';
+
+export default function SubmitChangesButton(props: any) {
+ return
+
+
+}
\ No newline at end of file
diff --git a/client/src/components/tables/ResultsTable.tsx b/client/src/components/tables/ResultsTable.tsx
index 154bdaa..cce223f 100644
--- a/client/src/components/tables/ResultsTable.tsx
+++ b/client/src/components/tables/ResultsTable.tsx
@@ -7,6 +7,7 @@ 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';
export interface SongGetters {
getTitle: (song: any) => string,
@@ -25,13 +26,18 @@ export interface IProps {
mainDispatch: (action: any) => void,
}
-export function SongTable(props: IProps) {
- const useTableStyles = makeStyles({
+export default function SongTable(props: IProps) {
+ const classes = makeStyles({
+ button: {
+ textTransform: "none",
+ fontWeight: 400,
+ paddingLeft: '0',
+ textAlign: 'left',
+ },
table: {
minWidth: 650,
},
- });
- const classes = useTableStyles();
+ })();
return (
@@ -66,6 +72,8 @@ export function SongTable(props: IProps) {
tabLabel: <>{mainArtistName}>,
artistId: mainArtistId,
metadata: null,
+ songGetters: songGetters,
+ songsByArtist: null,
},
tabReducer: newWindowReducer[WindowType.Artist],
tabType: WindowType.Artist,
@@ -79,6 +87,8 @@ export function SongTable(props: IProps) {
tabLabel: <>{mainAlbumName}>,
albumId: mainAlbumId,
metadata: null,
+ songGetters: songGetters,
+ songsOnAlbum: null,
},
tabReducer: newWindowReducer[WindowType.Album],
tabType: WindowType.Album,
@@ -105,6 +115,8 @@ export function SongTable(props: IProps) {
tabLabel: <>{name}>,
tagId: id,
metadata: null,
+ songGetters: songGetters,
+ songsWithTag: null,
},
tabReducer: newWindowReducer[WindowType.Tag],
tabType: WindowType.Tag,
@@ -118,20 +130,12 @@ export function SongTable(props: IProps) {
return
onClickTag(tagIds[i][tagIds[i].length-1], fullTag)}
+ onClick={() => onClickTag(tagIds[i][tagIds[i].length - 1], fullTag)}
/>
});
const TextCell = (props: any) => {
- const classes = makeStyles({
- button: {
- textTransform: "none",
- fontWeight: 400,
- paddingLeft: '0',
- textAlign: 'left',
- }
- })();
return