diff --git a/models/album.js b/models/album.js
index 0411a57..1fd23c3 100644
--- a/models/album.js
+++ b/models/album.js
@@ -1,2 +1,16 @@
var mongoose = require("mongoose");
var Schema = mongoose.Schema;
+
+var Song = require('./song');
+
+var AlbumSchema = new Schema({
+ artistName: String,
+ name: String,
+ releaseDate: String,
+ genres: [ String ],
+ songs: [Song.schema]
+});
+
+var Album = mongoose.model('Album', AlbumSchema);
+
+module.exports = Album;
diff --git a/models/index.js b/models/index.js
index 6c10401..0366699 100644
--- a/models/index.js
+++ b/models/index.js
@@ -1,2 +1,7 @@
var mongoose = require("mongoose");
-mongoose.connect("mongodb://localhost/tunely");
+mongoose.connect("mongodb://localhost/tunely_test");
+var Album = require('./album');
+var Song = require('./song');
+
+module.exports.Album = Album;
+module.exports.Song = Song;
diff --git a/models/song.js b/models/song.js
new file mode 100644
index 0000000..e6c12a0
--- /dev/null
+++ b/models/song.js
@@ -0,0 +1,11 @@
+var mongoose = require("mongoose");
+var Schema = mongoose.Schema;
+
+var SongSchema = new Schema({
+ name: String,
+ trackNumber: Number
+});
+
+var Song = mongoose.model('Song', SongSchema);
+
+module.exports = Song;
diff --git a/package.json b/package.json
index 0d3e4f8..415838f 100644
--- a/package.json
+++ b/package.json
@@ -4,7 +4,8 @@
"description": "An app for tracking your music collection",
"main": "server.js",
"scripts": {
- "test": "echo \"Error: no test specified\" && exit 1"
+ "test": "echo \"Error: no test specified\" && exit 1",
+ "start": "nodemon server.js"
},
"repository": {
"type": "git",
@@ -17,6 +18,8 @@
},
"homepage": "https://github.com/tgaff/tunely#readme",
"dependencies": {
- "express": "^4.13.3"
+ "body-parser": "^1.14.1",
+ "express": "^4.13.3",
+ "mongoose": "^4.2.9"
}
}
diff --git a/public/css/styles.css b/public/css/styles.css
index 6d4b961..0978ccf 100644
--- a/public/css/styles.css
+++ b/public/css/styles.css
@@ -13,4 +13,3 @@
vertical-align: baseline;
margin-right: 12px;
}
-
diff --git a/public/js/app.js b/public/js/app.js
index 164eb55..cd5a7ee 100644
--- a/public/js/app.js
+++ b/public/js/app.js
@@ -6,52 +6,140 @@
*/
-/* hard-coded data! */
-var sampleAlbums = [];
-sampleAlbums.push({
- artistName: 'Ladyhawke',
- name: 'Ladyhawke',
- releaseDate: '2008, November 18',
- genres: [ 'new wave', 'indie rock', 'synth pop' ]
- });
-sampleAlbums.push({
- artistName: 'The Knife',
- name: 'Silent Shout',
- releaseDate: '2006, February 17',
- genres: [ 'synth pop', 'electronica', 'experimental' ]
- });
-sampleAlbums.push({
- artistName: 'Juno Reactor',
- name: 'Shango',
- releaseDate: '2000, October 9',
- genres: [ 'electronic', 'goa trance', 'tribal house' ]
- });
-sampleAlbums.push({
- artistName: 'Philip Wesley',
- name: 'Dark Night of the Soul',
- releaseDate: '2008, September 12',
- genres: [ 'piano' ]
- });
-/* end of hard-coded data */
+$(document).ready(function() {
+ console.log('app.js loaded!');
+ $.get('/api/albums').success(function (albums) {
+ albums.forEach(function(album) {
+ renderAlbum(album);
+ });
+ });
+ $('#album-form form').on('submit', function(e) {
+ e.preventDefault();
+ var formData = $(this).serialize();
+ console.log('formData', formData);
+ $.post('/api/albums', formData, function(album) {
+ console.log('album after POST', album);
+ renderAlbum(album); //render the server's response
+ });
+ $(this).trigger("reset");
+ });
-$(document).ready(function() {
- console.log('app.js loaded!');
+
+ $('#albums').on('click', '.add-song', function(e) {
+ var id= $(this).parents('.album').data('album-id');
+ console.log('id',id);
+ $('#songModal').data('album-id', id);
+ $('#songModal').modal();
+ });
+
+ $('#saveSong').on('click', handleNewSongSubmit);
+
+ $('#albums').on('click', '.edit-album', handleEditAlbumClick);
+
+ $('#albums').on('click', '.put-album', handleSaveChangesClick);
+
+ $('#albums').on('click', '.delete-album', handleDeleteAlbumClick);
+
+ $('#editSongsModal').on('click', '.delete-song', handleDeleteSongClick);
+
+ $('#editSongsModal').on('submit', 'form', handleUpdateSong);
});
+function handleDeleteAlbumClick(e) {
+ var albumId = $(this).parents('.album').data('album-id');
+ console.log('someone wants to delete album id=' + albumId );
+ $.ajax({
+ method: 'DELETE',
+ url: ('/api/albums/' + albumId),
+ success: function() {
+ console.log("He's dead Jim");
+ $('[data-album-id='+ albumId + ']').remove();
+ }
+ });
+}
+
+// handles the modal fields and POSTing the form to the server
+function handleNewSongSubmit(e) {
+ var albumId = $('#songModal').data('album-id');
+ var songName = $('#songName').val();
+ var trackNumber = $('#trackNumber').val();
+
+ var formData = {
+ name: songName,
+ trackNumber: trackNumber
+ };
+
+ var postUrl = '/api/albums/' + albumId + '/songs';
+ console.log('posting to ', postUrl, ' with data ', formData);
+
+ $.post(postUrl, formData)
+ .success(function(song) {
+ console.log('song', song);
+
+ // re-get full album and render on page
+ $.get('/api/albums/' + albumId).success(function(album) {
+ //remove old entry
+ $('[data-album-id='+ albumId + ']').remove();
+ // render a replacement
+ renderAlbum(album);
+ });
+
+ //clear form
+ $('#songName').val('');
+ $('#trackNumber').val('');
+ $('#songModal').modal('hide');
+
+ });
+}
+function buildSongsHtml(songs) {
+ var songText = " – ";
+ songs.forEach(function(song) {
+ songText = songText + "(" + song.trackNumber + ") " + song.name + " – ";
+ });
+ var songsHtml =
+ "
" +
+ " " +
+ " " + songText + "" +
+ " ";
+ return songsHtml;
+}
+
+function generateEditSongsModalHtml(songs, albumId) {
+ var html = '';
+ songs.forEach(function(song) {
+ html += '';
+ });
+
+ return html;
+}
+
// this function takes a single album and renders it to the page
function renderAlbum(album) {
console.log('rendering album:', album);
var albumHtml =
" " +
- " " +
+ "
" +
"
" +
"
" +
"
" +
@@ -64,16 +152,20 @@ function renderAlbum(album) {
"
" +
" - " +
" " +
- " " + "HARDCODED ALBUM NAME" + "" +
+ " " + album.name + "" +
"
" +
" - " +
" " +
- " " + "HARDCODED ARTIST NAME" + "" +
+ " " + album.artistName + "" +
"
" +
" - " +
" " +
- " " + "HARDCODED RELEASE DATE" + "" +
+ " " + album.releaseDate + "" +
"
" +
+
+ buildSongsHtml(album.songs) +
+
+
"
" +
"
" +
"
" +
@@ -82,11 +174,13 @@ function renderAlbum(album) {
"
" + // end of panel-body
" " +
"
" +
"
" +
" ";
- // render to the page with jQuery
-}
+ $('#albums').prepend(albumHtml);
+ }
diff --git a/seed.js b/seed.js
index 1943f8f..ad5570f 100644
--- a/seed.js
+++ b/seed.js
@@ -3,13 +3,66 @@
var db = require("./models");
-var albumsList =[
- // put data here!
-];
+var albumList =[];
+albumList.push({
+ artistName: 'Nine Inch Nails',
+ name: 'The Downward Spiral',
+ releaseDate: '1994, March 8',
+ genres: [ 'industrial', 'industrial metal' ]
+ });
+albumList.push({
+ artistName: 'Metallica',
+ name: 'Metallica',
+ releaseDate: '1991, August 12',
+ genres: [ 'heavy metal' ]
+ });
+albumList.push({
+ artistName: 'The Prodigy',
+ name: 'Music for the Jilted Generation',
+ releaseDate: '1994, July 4',
+ genres: [ 'electronica', 'breakbeat hardcore', 'rave', 'jungle' ]
+ });
+albumList.push({
+ artistName: 'Johnny Cash',
+ name: 'Unchained',
+ releaseDate: '1996, November 5',
+ genres: [ 'country', 'rock' ]
+ });
+
+var sampleSongs = [];
+
+sampleSongs.push({ name: 'Swamped',
+ trackNumber: 1
+});
+sampleSongs.push({ name: "Heaven's a Lie",
+ trackNumber: 2
+});
+sampleSongs.push({ name: 'Daylight Dancer',
+ trackNumber: 3
+});
+sampleSongs.push({ name: 'Humane',
+ trackNumber: 4
+});
+sampleSongs.push({ name: 'Self Deception',
+ trackNumber: 5
+});
+sampleSongs.push({ name: 'Aeon',
+ trackNumber: 6
+});
+sampleSongs.push({ name: 'Tight Rope',
+ trackNumber: 7
+});
+
+
+// populate each albums song list
+albumList.forEach(function(album) {
+ album.songs = sampleSongs;
+});
+
db.Album.remove({}, function(err, albums){
- db.Album.create(albumsList, function(err, albums){
+ db.Album.create(albumList, function(err, albums){
if (err) { return console.log('ERROR', err); }
console.log("all albums:", albums);
console.log("created", albums.length, "albums");
diff --git a/server.js b/server.js
index 5da137b..792655f 100644
--- a/server.js
+++ b/server.js
@@ -4,46 +4,18 @@
var express = require('express');
// generate a new express app and call it 'app'
var app = express();
+var mongoose = require('mongoose');
+var bodyParser = require('body-parser');
// serve static files from public folder
app.use(express.static(__dirname + '/public'));
+app.use(bodyParser.urlencoded({ extended: true }));
/************
* DATABASE *
************/
-/* hard-coded data */
-var albums = [];
-albums.push({
- _id: 132,
- artistName: 'Nine Inch Nails',
- name: 'The Downward Spiral',
- releaseDate: '1994, March 8',
- genres: [ 'industrial', 'industrial metal' ]
- });
-albums.push({
- _id: 133,
- artistName: 'Metallica',
- name: 'Metallica',
- releaseDate: '1991, August 12',
- genres: [ 'heavy metal' ]
- });
-albums.push({
- _id: 134,
- artistName: 'The Prodigy',
- name: 'Music for the Jilted Generation',
- releaseDate: '1994, July 4',
- genres: [ 'electronica', 'breakbeat hardcore', 'rave', 'jungle' ]
- });
-albums.push({
- _id: 135,
- artistName: 'Johnny Cash',
- name: 'Unchained',
- releaseDate: '1996, November 5',
- genres: [ 'country', 'rock' ]
- });
-
-
+var db = require('./models');
/**********
* ROUTES *
@@ -73,6 +45,79 @@ app.get('/api', function api_index (req, res){
});
});
+app.get('/api/albums', function albumsIndex(req, res) {
+ db.Album.find({}, function(err, albums) {
+ res.json(albums);
+ });
+});
+
+app.post('/api/albums', function albumCreate(req, res) {
+ console.log('body', req.body);
+
+ // split at comma and remove and trailing space
+ var genres = req.body.genres.split(',').map(function(item) { return item.trim(); } );
+ req.body.genres = genres;
+
+ db.Album.create(req.body, function(err, album) {
+ if (err) { console.log('error', err); }
+ console.log(album);
+ res.json(album);
+ });
+
+});
+
+
+app.get('/api/albums/:id', function albumShow(req, res) {
+ console.log('requested album id=', req.params.id);
+ db.Album.findOne({_id: req.params.id}, function(err, album) {
+ res.json(album);
+ });
+});
+
+
+app.post('/api/albums/:albumId/songs', function songsCreate(req, res) {
+ console.log('body', req.body);
+ db.Album.findOne({_id: req.params.albumId}, function(err, album) {
+ if (err) { console.log('error', err); }
+
+ var song = new db.Song(req.body);
+ album.songs.push(song);
+ album.save(function(err, savedAlbum) {
+ if (err) { console.log('error', err); }
+ console.log('album with new song saved:', savedAlbum);
+ res.json(song);
+ });
+ });
+});
+
+app.delete('/api/albums/:id', function deleteAlbum(req, res) {
+ console.log('deleting id: ', req.params.id);
+ db.Album.remove({_id: req.params.id}, function(err) {
+ if (err) { return console.log(err); }
+ console.log("removal of id=" + req.params.id + " successful.");
+ res.status(200).send(); // everything is a-OK
+ });
+});
+
+app.put('/api/albums/:albumId/songs/:id', function(req, res) {
+ var albumId = req.params.albumId;
+ var songId = req.params.id;
+ db.Album.findOne({_id: albumId}, function (err, foundAlbum) {
+ // find song embedded in album
+ var foundSong = foundAlbum.songs.id(songId);
+ foundSong.name = req.body.name;
+ foundSong.trackNumber = req.body.trackNumber;
+
+ // save changes
+ foundAlbum.save(function(err, saved) {
+ if(err) { console.log('error', err); }
+ res.json(saved);
+ });
+ });
+});
+
+
+
/**********
* SERVER *
**********/
diff --git a/tunely.bmpr b/tunely.bmpr
new file mode 100644
index 0000000..a774469
Binary files /dev/null and b/tunely.bmpr differ
diff --git a/views/index.html b/views/index.html
index 5cb6501..ef82ff2 100644
--- a/views/index.html
+++ b/views/index.html
@@ -25,66 +25,84 @@ Welcome to tunely
-