diff --git a/client/package.json b/client/package.json index 19e3121..bc0f19a 100644 --- a/client/package.json +++ b/client/package.json @@ -4,6 +4,7 @@ "private": true, "dependencies": { "@material-ui/core": "^4.11.0", + "@material-ui/lab": "^4.0.0-alpha.56", "@testing-library/jest-dom": "^4.2.4", "@testing-library/react": "^9.3.2", "@testing-library/user-event": "^7.1.2", diff --git a/client/src/App.tsx b/client/src/App.tsx index 8b1dc43..2ec6189 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -21,8 +21,8 @@ function App() { name: "" }); - const fetchSongs = () => { - fetch(serverApi.ListSongsEndpoint) + const updateSongs = () => { + return fetch(serverApi.ListSongsEndpoint) .then((response: any) => response.json()) .then((result: serverApi.ListSongsResponse) => { setSongs(result.map((item: serverApi.ListSongsResponseItem) => { @@ -35,18 +35,29 @@ function App() { } const fetchArtists = () => { - fetch(serverApi.ListArtistsEndpoint) - .then((response: any) => response.json()) - .then((result: serverApi.ListArtistsResponse) => { - setArtists(result.map((item: serverApi.ListArtistsResponseItem) => { - return { - name: item.name, - }; - })); + return fetch(serverApi.ListArtistsEndpoint) + .then((response: any) => response.json()) + .then((result: serverApi.ListArtistsResponse) => { + return result.map((item: serverApi.ListArtistsResponseItem) => { + return { + name: item.name, + id: item.id, + }; }); + }); + } + + const updateArtists = () => { + return fetchArtists() + .then((artists: any[]) => { + setArtists(artists); + }); } const createSong = (p:SongProperties) => { + if(!p.artistId) { + throw "Undefined artist ID for song to be created."; + } const request:serverApi.CreateSongRequest = { title: p.title, artistId: p.artistId, @@ -56,7 +67,7 @@ function App() { headers: {'Content-Type': 'application/json'}, body: JSON.stringify(request) }; - fetch(serverApi.CreateSongEndpoint, requestOpts) + return fetch(serverApi.CreateSongEndpoint, requestOpts) } const createArtist = (p:ArtistProperties) => { @@ -68,7 +79,7 @@ function App() { headers: {'Content-Type': 'application/json'}, body: JSON.stringify(request) }; - fetch(serverApi.CreateArtistEndpoint, requestOpts) + return fetch(serverApi.CreateArtistEndpoint, requestOpts) } const openCreateSongDialog = () => { @@ -80,9 +91,9 @@ function App() { } const onSubmitCreateSongDialog = () => { - createSong(songDialogProperties); - fetchSongs(); - setEditSongDialogOpen(false); + createSong(songDialogProperties) + .then(updateSongs) + .then(() => { setEditSongDialogOpen(false); }) } const openCreateArtistDialog = () => { @@ -93,13 +104,13 @@ function App() { } const onSubmitCreateArtistDialog = () => { - createArtist(artistDialogProperties); - fetchArtists(); - setEditArtistDialogOpen(false); + createArtist(artistDialogProperties) + .then(updateArtists) + .then(() => { setEditArtistDialogOpen(false); }) } - useEffect(fetchSongs, []); - useEffect(fetchArtists, []); + useEffect(() => { updateSongs(); }, []); + useEffect(() => { updateArtists(); }, []); return (
@@ -119,6 +130,7 @@ function App() { onChangeSongProperties={(props:SongProperties) => setSongDialogProperties(props)} songProperties={songDialogProperties} onSubmit={onSubmitCreateSongDialog} + artists={artists} /> {}; export function checkListArtistsRequest(req:any): boolean { diff --git a/client/src/components/ArtistTable.tsx b/client/src/components/ArtistTable.tsx index dbcfcc7..ceef43e 100644 --- a/client/src/components/ArtistTable.tsx +++ b/client/src/components/ArtistTable.tsx @@ -2,7 +2,8 @@ import React from 'react'; import MaterialTable from 'material-table'; export interface Entry { - name: String + name: String, + id: Number, } export interface IProps { diff --git a/client/src/components/EditSongDialog.tsx b/client/src/components/EditSongDialog.tsx index 598987d..151bf2c 100644 --- a/client/src/components/EditSongDialog.tsx +++ b/client/src/components/EditSongDialog.tsx @@ -1,11 +1,17 @@ -import React from 'react'; +import React, { useState, useEffect } from 'react'; import { Dialog, Grid, Typography, TextField, Button } from '@material-ui/core'; +import { Autocomplete } from '@material-ui/lab'; var cloneDeep = require('lodash/cloneDeep'); export interface SongProperties { title: String, - artistId: Number, + artistId: Number | undefined, +} + +export interface ArtistProperties { + name: String, + id: Number, } export interface IProps { @@ -14,6 +20,7 @@ export interface IProps { onChangeSongProperties?: (props: SongProperties) => void, songProperties: SongProperties, onSubmit?: () => void, + artists: ArtistProperties[], } export default function EditSongDialog(props: IProps) { @@ -24,10 +31,10 @@ export default function EditSongDialog(props: IProps) { props.onChangeSongProperties(p); } }; - const onArtistChange = (artist: Number) => { + const onArtistChange = (artist: Number | undefined) => { if (props.onChangeSongProperties) { const p = cloneDeep(props.songProperties); - p.artistHash = artist; + p.artistId = artist; props.onChangeSongProperties(p); } }; @@ -49,11 +56,24 @@ export default function EditSongDialog(props: IProps) { /> - onArtistChange(parseInt(i.target.value))} - fullWidth + option.name as string} + onChange={(event, newValue) => { + console.log("Change: ", newValue) + if(newValue) { + onArtistChange(newValue.id); + } else { + onArtistChange(undefined); + } + }} + renderInput={ + (params) => + + } /> diff --git a/client/yarn.lock b/client/yarn.lock index ee55a4c..0ed8022 100644 --- a/client/yarn.lock +++ b/client/yarn.lock @@ -1321,6 +1321,17 @@ react-is "^16.8.0" react-transition-group "^4.4.0" +"@material-ui/lab@^4.0.0-alpha.56": + version "4.0.0-alpha.56" + resolved "https://registry.yarnpkg.com/@material-ui/lab/-/lab-4.0.0-alpha.56.tgz#ff63080949b55b40625e056bbda05e130d216d34" + integrity sha512-xPlkK+z/6y/24ka4gVJgwPfoCF4RCh8dXb1BNE7MtF9bXEBLN/lBxNTK8VAa0qm3V2oinA6xtUIdcRh0aeRtVw== + dependencies: + "@babel/runtime" "^7.4.4" + "@material-ui/utils" "^4.10.2" + clsx "^1.0.4" + prop-types "^15.7.2" + react-is "^16.8.0" + "@material-ui/pickers@^3.2.2": version "3.2.10" resolved "https://registry.yarnpkg.com/@material-ui/pickers/-/pickers-3.2.10.tgz#19df024895876eb0ec7cd239bbaea595f703f0ae" diff --git a/server/package.json b/server/package.json index e5d114e..63c3495 100644 --- a/server/package.json +++ b/server/package.json @@ -2,8 +2,7 @@ "name": "mudbase-server", "version": "1.0.0", "scripts": { - "start": "ts-node server.ts", - "start:watch": "nodemon", + "start": "nodemon server.ts", "build": "tsc" }, "dependencies": { diff --git a/server/server.ts b/server/server.ts index 5222ab0..9a3ad4d 100644 --- a/server/server.ts +++ b/server/server.ts @@ -20,8 +20,8 @@ app.post(api.CreateSongEndpoint, (req: any, res: any) => { const reqObject: api.CreateSongRequest = req.body; console.log("Request create song: ", reqObject); // TODO: remove // First check that the artist exists. - models.Song.findAll({ - where: { artistId: reqObject.artistId } + models.Artist.findAll({ + where: { id: reqObject.artistId } }) .then((artist: any[]) => { if (artist.length != 1) { @@ -32,7 +32,7 @@ app.post(api.CreateSongEndpoint, (req: any, res: any) => { } const song = models.Song.create({ title: reqObject.title, - artistId: reqObject.artistId + ArtistId: reqObject.artistId }); const responseObject: api.CreateSongResponse = { id: song.id @@ -51,12 +51,13 @@ app.get(api.ListSongsEndpoint, (req: any, res: any) => { include: [models.Artist] }) .then((songs: any[]) => { + console.log(songs); const response: api.ListSongsResponse = songs.map((song: any) => { return { title: song.title, id: song.id, - artistName: "", // TODO: fetch artist details - artistId: song.artistId, + artistName: song.Artist.name, + artistId: song.ArtistId, }; }); res.send(response);