import React, { useEffect, useState } from 'react'; import { Box, Typography, IconButton, Button, CircularProgress } from '@material-ui/core'; import PersonIcon from '@material-ui/icons/Person'; import * as serverApi from '../../../api'; import { WindowState } from '../Windows'; import StoreLinkIcon, { whichStore } from '../../common/StoreLinkIcon'; import EditableText from '../../common/EditableText'; import SubmitChangesButton from '../../common/SubmitChangesButton'; import SongTable, { SongGetters } from '../../tables/ResultsTable'; import { saveArtistChanges } from '../../../lib/saveChanges'; import { QueryLeafBy, QueryLeafOp } from '../../../lib/query/Query'; import { queryArtists, querySongs } from '../../../lib/backend/queries'; var _ = require('lodash'); export type ArtistMetadata = serverApi.ArtistDetails; export type ArtistMetadataChanges = serverApi.ModifyArtistRequest; export interface ArtistWindowState extends WindowState { artistId: number, metadata: ArtistMetadata | null, pendingChanges: ArtistMetadataChanges | null, songsByArtist: any[] | null, songGetters: SongGetters, } export enum ArtistWindowStateActions { SetMetadata = "SetMetadata", SetPendingChanges = "SetPendingChanges", SetSongs = "SetSongs", Reload = "Reload", } export function ArtistWindowReducer(state: ArtistWindowState, action: any) { switch (action.type) { case ArtistWindowStateActions.SetMetadata: return { ...state, metadata: action.value } case ArtistWindowStateActions.SetPendingChanges: return { ...state, pendingChanges: action.value } case ArtistWindowStateActions.SetSongs: return { ...state, songsByArtist: action.value } case ArtistWindowStateActions.Reload: return { ...state, metadata: null, pendingChanges: null, songsByArtist: null } default: throw new Error("Unimplemented ArtistWindow state update.") } } export interface IProps { state: ArtistWindowState, dispatch: (action: any) => void, mainDispatch: (action: any) => void, } export async function getArtistMetadata(id: number) { return (await queryArtists({ query: { a: QueryLeafBy.ArtistId, b: id, leafOp: QueryLeafOp.Equals, }, offset: 0, limit: 1, }))[0]; } export default function ArtistWindow(props: IProps) { let metadata = props.state.metadata; let pendingChanges = props.state.pendingChanges; // Effect to get the artist's metadata. useEffect(() => { getArtistMetadata(props.state.artistId) .then((m: ArtistMetadata) => { props.dispatch({ type: ArtistWindowStateActions.SetMetadata, value: m }); }) }, [metadata?.name]); // Effect to get the artist's songs. useEffect(() => { if (props.state.songsByArtist) { return; } (async () => { const songs = await querySongs({ query: { a: QueryLeafBy.ArtistId, b: props.state.artistId, leafOp: QueryLeafOp.Equals, }, offset: 0, limit: -1, }); props.dispatch({ type: ArtistWindowStateActions.SetSongs, value: songs, }); })(); }, [props.state.songsByArtist]); const [editingName, setEditingName] = useState(null); const name = setEditingName(v)} onChangeChangedValue={(v: string | null) => { let newVal: any = { ...pendingChanges }; if (v) { newVal.name = v } else { delete newVal.name } props.dispatch({ type: ArtistWindowStateActions.SetPendingChanges, value: newVal, }) }} /> const storeLinks = metadata?.storeLinks && metadata?.storeLinks.map((link: string) => { const store = whichStore(link); return store && }); const [applying, setApplying] = useState(false); const maybeSubmitButton = pendingChanges && Object.keys(pendingChanges).length > 0 && { setApplying(true); saveArtistChanges(props.state.artistId, pendingChanges || {}) .then(() => { setApplying(false); props.dispatch({ type: ArtistWindowStateActions.Reload }) }) }} /> {applying && } return {metadata && {name} {storeLinks} } {maybeSubmitButton} Songs by this artist in your library: {props.state.songsByArtist && } {!props.state.songsByArtist && } }