|
|
|
@ -16,17 +16,14 @@ import { querySongs } from '../../../lib/backend/queries'; |
|
|
|
|
import { useParams } from 'react-router'; |
|
|
|
|
|
|
|
|
|
export type SongMetadata = serverApi.SongDetails; |
|
|
|
|
export type SongMetadataChanges = serverApi.ModifySongRequest; |
|
|
|
|
|
|
|
|
|
export interface SongWindowState extends WindowState { |
|
|
|
|
id: number, |
|
|
|
|
metadata: SongMetadata | null, |
|
|
|
|
pendingChanges: SongMetadataChanges | null, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
export enum SongWindowStateActions { |
|
|
|
|
SetMetadata = "SetMetadata", |
|
|
|
|
SetPendingChanges = "SetPendingChanges", |
|
|
|
|
Reload = "Reload", |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -34,8 +31,6 @@ export function SongWindowReducer(state: SongWindowState, action: any) { |
|
|
|
|
switch (action.type) { |
|
|
|
|
case SongWindowStateActions.SetMetadata: |
|
|
|
|
return { ...state, metadata: action.value } |
|
|
|
|
case SongWindowStateActions.SetPendingChanges: |
|
|
|
|
return { ...state, pendingChanges: action.value } |
|
|
|
|
case SongWindowStateActions.Reload: |
|
|
|
|
return { ...state, metadata: null, pendingChanges: null } |
|
|
|
|
default: |
|
|
|
@ -60,7 +55,6 @@ export default function SongWindow(props: {}) { |
|
|
|
|
const [state, dispatch] = useReducer(SongWindowReducer, { |
|
|
|
|
id: id, |
|
|
|
|
metadata: null, |
|
|
|
|
pendingChanges: null, |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
return <SongWindowControlled state={state} dispatch={dispatch} /> |
|
|
|
@ -70,7 +64,7 @@ export function SongWindowControlled(props: { |
|
|
|
|
state: SongWindowState, |
|
|
|
|
dispatch: (action: any) => void, |
|
|
|
|
}) { |
|
|
|
|
let { pendingChanges, metadata, id: songId } = props.state; |
|
|
|
|
let { metadata, id: songId } = props.state; |
|
|
|
|
let { dispatch } = props; |
|
|
|
|
|
|
|
|
|
useEffect(() => { |
|
|
|
@ -83,23 +77,7 @@ export function SongWindowControlled(props: { |
|
|
|
|
}) |
|
|
|
|
}, [songId, dispatch]); |
|
|
|
|
|
|
|
|
|
const [editingTitle, setEditingTitle] = useState<string | null>(null); |
|
|
|
|
const title = <Typography variant="h4"><EditableText |
|
|
|
|
defaultValue={metadata?.title || "(Unknown title)"} |
|
|
|
|
changedValue={pendingChanges?.title || null} |
|
|
|
|
editingValue={editingTitle} |
|
|
|
|
editingLabel="Title" |
|
|
|
|
onChangeEditingValue={(v: string | null) => setEditingTitle(v)} |
|
|
|
|
onChangeChangedValue={(v: string | null) => { |
|
|
|
|
let newVal: any = { ...pendingChanges }; |
|
|
|
|
if (v) { newVal.title = v } |
|
|
|
|
else { delete newVal.title } |
|
|
|
|
props.dispatch({ |
|
|
|
|
type: SongWindowStateActions.SetPendingChanges, |
|
|
|
|
value: newVal, |
|
|
|
|
}) |
|
|
|
|
}} |
|
|
|
|
/></Typography> |
|
|
|
|
const title = <Typography variant="h4">{metadata?.title || "(Unknown title)"}</Typography> |
|
|
|
|
|
|
|
|
|
const artists = metadata?.artists && metadata?.artists.map((artist: ArtistMetadata) => { |
|
|
|
|
return <Typography> |
|
|
|
@ -126,22 +104,6 @@ export function SongWindowControlled(props: { |
|
|
|
|
</a> |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
const [applying, setApplying] = useState(false); |
|
|
|
|
const maybeSubmitButton = pendingChanges && Object.keys(pendingChanges).length > 0 && |
|
|
|
|
<Box> |
|
|
|
|
<SubmitChangesButton onClick={() => { |
|
|
|
|
setApplying(true); |
|
|
|
|
saveSongChanges(props.state.id, pendingChanges || {}) |
|
|
|
|
.then(() => { |
|
|
|
|
setApplying(false); |
|
|
|
|
props.dispatch({ |
|
|
|
|
type: SongWindowStateActions.Reload |
|
|
|
|
}) |
|
|
|
|
}) |
|
|
|
|
}} /> |
|
|
|
|
{applying && <CircularProgress />} |
|
|
|
|
</Box> |
|
|
|
|
|
|
|
|
|
return <Box width="100%" justifyContent="center" display="flex" flexWrap="wrap"> |
|
|
|
|
<Box |
|
|
|
|
m={1} |
|
|
|
@ -181,11 +143,5 @@ export function SongWindowControlled(props: { |
|
|
|
|
</Box> |
|
|
|
|
</Box>} |
|
|
|
|
</Box> |
|
|
|
|
<Box |
|
|
|
|
m={1} |
|
|
|
|
width="80%" |
|
|
|
|
> |
|
|
|
|
{maybeSubmitButton} |
|
|
|
|
</Box> |
|
|
|
|
</Box> |
|
|
|
|
} |