Browse Source

Added manage page for stations and removed stations admin page.

KrisVos130 9 năm trước cách đây
mục cha
commit
1a1f9622ad

+ 229 - 202
app/client/scripts/events.js

@@ -455,6 +455,9 @@ Template.queues.events({
         Meteor.call("removeSongFromQueue", genre, this.mid);
     },
     "click #play": function() {
+        var duration = Session.get("song").duration;
+        var d = moment.duration(parseInt(duration), 'seconds');
+        $("#time-total").text(d.minutes() + ":" + ("0" + d.seconds()).slice(-2));
         $("#previewPlayerContainer").removeClass("hide-preview");
         var song = Session.get("song");
         var id = song.id;
@@ -475,9 +478,6 @@ Template.queues.events({
                             event.target.seekTo(Number(song.skipDuration));
                             event.target.playVideo();
                             event.target.setVolume(volume);
-                            var duration = Session.get("song").duration;
-                            var d = moment.duration(parseInt(duration), 'seconds');
-                            $("#time-total").text(d.minutes() + ":" + ("0" + d.seconds()).slice(-2));
                         },
                         'onStateChange': function(event){
                             if (event.data == YT.PlayerState.PAUSED) {
@@ -638,6 +638,231 @@ Template.queues.events({
     }
 });
 
+Template.manageStation.events({
+    /* TODO Add undo delete button */
+    "input #id": function() {
+        $("#previewPlayerContainer").addClass("hide-preview");
+    },
+    "input #img": function() {
+        var url = $("#img").val();
+        Session.set("image_url", url);
+    },
+    "click .preview-button": function(e){
+        Session.set("song", this);
+        $("#previewModal").openModal();
+    },
+    "click #previewImageButton": function() {
+        $("#preview-image").attr("src", Session.get("song").img);
+    },
+    "click .edit-song-button": function(e){
+        Session.set("song", this);
+        Session.set("genre", $(e.target).data("genre"));
+        $("#mid").val(this.mid).change();
+        $("#artist").val(this.artist).change();
+        $("#title").val(this.title).change();
+        $("#img").val(this.img).change();
+        $("#id").val(this.id).change();
+        $("#likes").val(this.likes).change();
+        $("#dislikes").val(this.dislikes).change();
+        $("#duration").val(this.duration).change();
+        $("#skip-duration").val(this.skipDuration).change();
+        $("#previewPlayerContainer").addClass("hide-preview");
+        Session.set("image_url", this.img);
+        Session.set("editing", true);
+        $("#editModal").openModal({
+            complete : function() {
+                Session.set("editing", false);
+                if (YTPlayer !== undefined && YTPlayer.stopVideo !== undefined) {
+                    YTPlayer.stopVideo();
+                }
+            }
+        });
+    },
+    "click .remove-song-button": function(e){
+        var genre = $(e.target).data("genre") || $(e.target).parent().data("genre");
+        Meteor.call("removeSongFromPlaylist", genre, this.mid);
+    },
+    "click #play": function() {
+        var duration = Session.get("song").duration;
+        var d = moment.duration(parseInt(duration), 'seconds');
+        $("#time-total").text(d.minutes() + ":" + ("0" + d.seconds()).slice(-2));
+        $("#previewPlayerContainer").removeClass("hide-preview");
+        var song = Session.get("song");
+        var id = song.id;
+        var volume = localStorage.getItem("volume") || 20;
+        if (song.duration !== 0) {
+            $("#play").attr("disabled", true);
+            $("#stop").attr("disabled", false);
+            $("#pause").attr("disabled", false);
+            $("#forward").attr("disabled", false);
+            if (YTPlayer === undefined) {
+                YTPlayer = new YT.Player("previewPlayer", {
+                    height: 540,
+                    width: 568,
+                    videoId: id,
+                    playerVars: {autoplay: 1, controls: 0, iv_load_policy: 3, showinfo: 0, fs: 0},
+                    events: {
+                        'onReady': function(event) {
+                            event.target.seekTo(Number(song.skipDuration));
+                            event.target.playVideo();
+                            event.target.setVolume(volume);
+                        },
+                        'onStateChange': function(event){
+                            if (event.data == YT.PlayerState.PAUSED) {
+                                if (seekerBarInterval !== undefined) {
+                                    Meteor.clearInterval(seekerBarInterval);
+                                    seekerBarInterval = undefined;
+                                }
+                            }
+                            if (event.data == YT.PlayerState.UNSTARTED) {
+                                if (seekerBarInterval !== undefined) {
+                                    Meteor.clearInterval(seekerBarInterval);
+                                    seekerBarInterval = undefined;
+                                }
+                                $(".seeker-bar").css({width: "0"});
+                                $("#time-elapsed").text("0:00");
+                                $("#previewPlayerContainer").addClass("hide-preview");
+                            }
+                            if (event.data == YT.PlayerState.PLAYING) {
+                                seekerBarInterval = Meteor.setInterval(function() {
+                                    var duration = Session.get("song").duration;
+                                    var timeElapsed = YTPlayer.getCurrentTime();
+                                    var skipDuration = Session.get("song").skipDuration;
+
+                                    if (duration <= (timeElapsed - skipDuration)) {
+                                        YTPlayer.stopVideo();
+                                        $("#play").attr("disabled", false);
+                                        $("#stop").attr("disabled", true);
+                                        $("#pause").attr("disabled", true);
+                                        $("#forward").attr("disabled", true);
+                                        $("#previewPlayerContainer").addClass("hide-preview");
+                                        $(".seeker-bar").css({width: "0"});
+                                        $("#time-elapsed").text("0:00");
+                                        Meteor.clearInterval(seekerBarInterval);
+                                    } else {
+                                        var percentComplete = (timeElapsed - skipDuration) / duration * 100;
+                                        $(".seeker-bar").css({width: percentComplete + "%"});
+                                        var d = moment.duration(timeElapsed - skipDuration, 'seconds');
+                                        $("#time-elapsed").text(d.minutes() + ":" + ("0" + d.seconds()).slice(-2));
+                                    }
+                                }, 100);
+                                $("#play").attr("disabled", true);
+                                $("#stop").attr("disabled", false);
+                                $("#pause").attr("disabled", false);
+                                $("#forward").attr("disabled", false);
+                            } else {
+                                $("#play").attr("disabled", false);
+                                $("#stop").attr("disabled", true);
+                                $("#pause").attr("disabled", true);
+                                $("#forward").attr("disabled", true);
+                            }
+                        }
+                    }
+                });
+            } else {
+                if (YTPlayer.getPlayerState() === 2) {
+                    YTPlayer.playVideo();
+                } else {
+                    console.log(id, song.skipDuration, song.duration);
+                    YTPlayer.loadVideoById(id);
+                    YTPlayer.seekTo(Number(song.skipDuration));
+                }
+            }
+            $("#previewPlayerContainer").removeClass("hide-preview");
+        }
+    },
+    "click #stop": function() {
+        $("#play").attr("disabled", false);
+        $("#stop").attr("disabled", true);
+        $("#pause").attr("disabled", true);
+        $("#forward").attr("disabled", true);
+        if (previewEndSongTimeout !== undefined) {
+            Meteor.clearTimeout(previewEndSongTimeout);
+        }
+        if (YTPlayer !== undefined && YTPlayer.stopVideo !== undefined) {
+            YTPlayer.stopVideo();
+        }
+    },
+    "click #pause": function() {
+        $("#play").attr("disabled", false);
+        $("#stop").attr("disabled", false);
+        $("#pause").attr("disabled", true);
+        $("#forward").attr("disabled", true);
+        if (previewEndSongTimeout !== undefined) {
+            Meteor.clearTimeout(previewEndSongTimeout);
+        }
+        if (YTPlayer !== undefined && YTPlayer.pauseVideo !== undefined) {
+            YTPlayer.pauseVideo();
+        }
+    },
+    "click #forward": function() {
+        var error = false;
+        if (YTPlayer !== undefined) {
+            var duration = Number(Session.get("song").duration) | 0;
+            var skipDuration = Number(Session.get("song").skipDuration) | 0;
+            if (YTPlayer.getDuration() < duration + skipDuration) {
+                var $toastContent = $('<span><strong>Error.</strong> The song duration is longer than the length of the video.</span>');
+                Materialize.toast($toastContent, 8000);
+                error = true;
+            } else {
+                YTPlayer.seekTo(skipDuration + duration - 10);
+            }
+        }
+        if (!error) {
+            if (previewEndSongTimeout !== undefined) {
+                Meteor.clearTimeout(previewEndSongTimeout);
+            }
+            previewEndSongTimeout = Meteor.setTimeout(function() {
+                if (YTPlayer !== undefined) {
+                    YTPlayer.stopVideo();
+                }
+                $("#play").attr("disabled", false);
+                $("#stop").attr("disabled", true);
+                $("#pause").attr("disabled", true);
+                $("#forward").attr("disabled", true);
+                $("#previewPlayerContainer").addClass("hide-preview");
+            }, 10000);
+        }
+    },
+    "click #get-spotify-info": function() {
+        var search = $("#title").val();
+        var artistName = $("#artist").val();
+        getSpotifyInfo(search, function(data) {
+            for(var i in data){
+                for(var j in data[i].items){
+                    if(search.indexOf(data[i].items[j].name) !== -1 && artistName.indexOf(data[i].items[j].artists[0].name) !== -1){
+                        $("#img").val(data[i].items[j].album.images[2].url).change();
+                        $("#duration").val(data[i].items[j].duration_ms / 1000).change();
+                        return;
+                    }
+                }
+            }
+        }, artistName);
+    },
+    "click #save-song-button": function() {
+        var newSong = {};
+        newSong.mid = $("#mid").val();
+        newSong.id = $("#id").val();
+        newSong.likes = Number($("#likes").val());
+        newSong.dislikes = Number($("#dislikes").val());
+        newSong.title = $("#title").val();
+        newSong.artist = $("#artist").val();
+        newSong.img = $("#img").val();
+        newSong.duration = Number($("#duration").val());
+        newSong.skipDuration = $("#skip-duration").val();
+        newSong.requestedBy = Session.get("song").requestedBy;
+        Meteor.call("updatePlaylistSong", Session.get("genre"), Session.get("song"), newSong, function(err, res) {
+            console.log(err, res);
+            if (err) {
+                var $toastContent = $('<span><strong>Song not saved.</strong> ' + err.reason + '</span>');
+                Materialize.toast($toastContent, 8000);
+            } else {
+                Session.set("song", newSong);
+            }
+        });
+    }
+});
+
 Template.register.events({
     "submit form": function(e){
         e.preventDefault();
@@ -1454,202 +1679,4 @@ Template.settings.events({
     }
 });
 
-var previewEndSongTimeout = undefined;
-
-Template.stations.events({
-    "click .preview-button": function(e){
-        Session.set("song", this);
-    },
-    "click #previewImageButton": function() {
-        $("#preview-image").attr("src", Session.get("song").img);
-    },
-    "click .edit-queue-button": function(e){
-        Session.set("song", this);
-        Session.set("genre", $(e.target).data("genre"));
-        Session.set("type", "queue");
-        $("#mid").val(this.mid).change();
-        $("#artist").val(this.artist).change();
-        $("#title").val(this.title).change();
-        $("#img").val(this.img).change();
-        $("#id").val(this.id).change();
-        $("#likes").val(this.likes).change();
-        $("#dislikes").val(this.dislikes).change();
-        $("#duration").val(this.duration).change();
-        $("#skip-duration").val(this.skipDuration).change();
-    },
-    "click .edit-playlist-button": function(e){
-        Session.set("song", this);
-        Session.set("genre", $(e.target).data("genre"));
-        Session.set("type", "playlist");
-        $("#mid").val(this.mid);
-        $("#artist").val(this.artist);
-        $("#title").val(this.title);
-        $("#img").val(this.img);
-        $("#id").val(this.id);
-        $("#likes").val(this.likes);
-        $("#dislikes").val(this.dislikes);
-        $("#duration").val(this.duration);
-        $("#skip-duration").val(this.skipDuration);
-    },
-    "click .add-song-button": function(e){
-        var genre = $(e.target).data("genre") || $(e.target).parent().data("genre");
-        Meteor.call("addSongToPlaylist", genre, this);
-    },
-    "click .deny-song-button": function(e){
-        var genre = $(e.target).data("genre") || $(e.target).parent().data("genre");
-        Meteor.call("removeSongFromQueue", genre, this.mid);
-    },
-    "click .remove-song-button": function(e){
-        var genre = $(e.target).data("genre") || $(e.target).parent().data("genre");
-        Meteor.call("removeSongFromPlaylist", genre, this.mid);
-    },
-    "click #moveSong": function(e){
-        var genre = $(e.target).data("genre") || $(e.target).parent().data("genre");
-        if (genre !== Session.get(genre)) {
-            Meteor.call("addSongToPlaylist", genre, Session.get("song"));
-            Meteor.call("removeSongFromPlaylist", Session.get("genre"), Session.get("song").mid);
-        }else {
-            console.log("Something Went Wrong?!");
-            return false;
-        }
-
-    },
-    "click #copySong": function(e){
-        var genre = $(e.target).data("genre") || $(e.target).parent().data("genre");
-        Meteor.call("addSongToPlaylist", genre, Session.get("song"));
-    },
-    "click .copyMove-button": function(e){
-        Session.set("song", this);
-        Session.set("genre", $(e.target).data("genre"));
-    },
-    "click #play": function() {
-        $("#play").attr("disabled", true);
-        $("#stop").attr("disabled", false);
-        var song = Session.get("song");
-        var id = song.id;
-        var volume = localStorage.getItem("volume") || 20;
-
-        if (YTPlayer === undefined) {
-            YTPlayer = new YT.Player("previewPlayer", {
-                height: 540,
-                width: 568,
-                videoId: id,
-                playerVars: {controls: 0, iv_load_policy: 3, showinfo: 0},
-                events: {
-                    'onReady': function(event) {
-                        event.target.seekTo(Number(song.skipDuration));
-                        event.target.playVideo();
-                        event.target.setVolume(volume);
-                    },
-                    'onStateChange': function(event){
-                        if (event.data == YT.PlayerState.PAUSED) {
-                            event.target.playVideo();
-                        }
-                        if (event.data == YT.PlayerState.PLAYING) {
-                            $("#play").attr("disabled", true);
-                            $("#stop").attr("disabled", false);
-                        } else {
-                            $("#play").attr("disabled", false);
-                            $("#stop").attr("disabled", true);
-                        }
-                    }
-                }
-            });
-        } else {
-            YTPlayer.loadVideoById(id);
-            YTPlayer.seekTo(Number(song.skipDuration));
-        }
-        $("#previewPlayer").show();
-
-        if (previewEndSongTimeout !== undefined) {
-            Meteor.clearTimeout(previewEndSongTimeout);
-        }
-        previewEndSongTimeout = Meteor.setTimeout(function() {
-            if (YTPlayer !== undefined) {
-                YTPlayer.stopVideo();
-            }
-            $("#play").attr("disabled", false);
-            $("#stop").attr("disabled", true);
-            $("#previewPlayer").hide();
-        }, song.duration * 1000);
-    },
-    "click #stop": function() {
-        $("#play").attr("disabled", false);
-        $("#stop").attr("disabled", true);
-        $("#pause").attr("disabled", true);
-        if (previewEndSongTimeout !== undefined) {
-            Meteor.clearTimeout(previewEndSongTimeout);
-        }
-        if (YTPlayer !== undefined && YTPlayer.stopVideo !== undefined) {
-            YTPlayer.stopVideo();
-        }
-    },
-    "click #forward": function() {
-        var error = false;
-        if (YTPlayer !== undefined) {
-            var duration = Number(Session.get("song").duration) | 0;
-            var skipDuration = Number(Session.get("song").skipDuration) | 0;
-            if (YTPlayer.getDuration() < duration + skipDuration) {
-                alert("The duration of the YouTube video is smaller than the duration.");
-                error = true;
-            } else {
-                YTPlayer.seekTo(skipDuration + duration - 10);
-            }
-        }
-        if (!error) {
-            if (previewEndSongTimeout !== undefined) {
-                Meteor.clearTimeout(previewEndSongTimeout);
-            }
-            previewEndSongTimeout = Meteor.setTimeout(function() {
-                if (YTPlayer !== undefined) {
-                    YTPlayer.stopVideo();
-                }
-                $("#play").attr("disabled", false);
-                $("#stop").attr("disabled", true);
-                $("#previewPlayer").hide();
-            }, 10000);
-        }
-    },
-    "click #get-spotify-info": function() {
-        var search = $("#title").val();
-        var artistName = $("#artist").val();
-        getSpotifyInfo(search, function(data) {
-            for(var i in data){
-                for(var j in data[i].items){
-                    if(search.indexOf(data[i].items[j].name) !== -1 && artistName.indexOf(data[i].items[j].artists[0].name) !== -1){
-                        $("#img").val(data[i].items[j].album.images[2].url);
-                        $("#duration").val(data[i].items[j].duration_ms / 1000);
-                        return;
-                    }
-                }
-            }
-        }, artistName);
-    },
-    "click #save-song-button": function() {
-        var newSong = {};
-        newSong.id = $("#id").val();
-        newSong.likes = Number($("#likes").val());
-        newSong.dislikes = Number($("#dislikes").val());
-        newSong.title = $("#title").val();
-        newSong.artist = $("#artist").val();
-        newSong.img = $("#img").val();
-        newSong.duration = Number($("#duration").val());
-        newSong.skipDuration = $("#skip-duration").val();
-        if(newSong.skipDuration === undefined){
-            newSong.skipDuration = 0;
-        };
-        if (Session.get("type") === "playlist") {
-            Meteor.call("updatePlaylistSong", Session.get("genre"), Session.get("song"), newSong, function() {
-                $('#editModal').modal('hide');
-            });
-        } else {
-            Meteor.call("updateQueueSong", Session.get("genre"), Session.get("song"), newSong, function() {
-                $('#editModal').modal('hide');
-            });
-        }
-    },
-    "click .delete-room": function(){
-        var typeDel = $(this)[0].type;
-        Meteor.call("deleteRoom", typeDel);
-    }
-});
+var previewEndSongTimeout = undefined;

+ 23 - 18
app/client/scripts/helpers.js

@@ -213,6 +213,28 @@ Template.queues.helpers({
     }
 });
 
+Template.manageStation.helpers({
+    songs: function () {
+        var parts = location.href.split('/');
+        parts.pop();
+        var id = parts.pop();
+        var type = id.toLowerCase();
+
+        var playlist = Playlists.findOne({type: type});
+        return playlist.songs;
+    },
+    song_image: function() {
+        return Session.get("image_url");
+    },
+    genre: function() {
+        var parts = location.href.split('/');
+        parts.pop();
+        var id = parts.pop();
+        var type = id.toLowerCase();
+        return type;
+    }
+});
+
 Template.room.helpers({
     singleVideo: function () {
         return true;
@@ -362,21 +384,4 @@ Template.settings.helpers({
             return "";
         }
     }
-});
-
-Template.stations.helpers({
-    playlist: function () {
-        var query = {type: Session.get("playlistToEdit").toLowerCase()};
-        var playlists = Playlists.find(query).fetch();
-        return playlists;
-    },
-    whichStation: function () {
-        return Session.get("playlistToEdit");
-    },
-    reports: function () {
-        var query = {room: Session.get("playlistToEdit").toLowerCase()};
-        var reports = Reports.find(query).fetch();
-        console.log(reports);
-        return reports;
-    }
-});
+});

+ 17 - 9
app/client/scripts/onCreated.js

@@ -87,6 +87,22 @@ Template.queues.onCreated(function() {
     });
 });
 
+Template.manageStation.onCreated(function() {
+    var tag = document.createElement("script");
+    tag.src = "https://www.youtube.com/iframe_api";
+    var firstScriptTag = document.getElementsByTagName('script')[0];
+    firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
+    YTPlayer = undefined;
+    $(document).keydown(function(evt){
+        if (evt.keyCode==83 && (evt.ctrlKey)){
+            evt.preventDefault();
+            if (Session.get("editing") === true) {
+                $("#save-song-button").click();
+            }
+        }
+    });
+});
+
 Template.register.onCreated(function() {
     Accounts.onLoginFailure(function() {
         var errAlert = $('<div style="margin-bottom: 0" class="alert alert-danger" role="alert"><strong>Oh Snap!</strong> Something went wrong when trying to register with GitHub. Maybe an account with that username already exists?</div>');
@@ -308,12 +324,4 @@ Template.settings.onCreated(function() {
         }
         initSettings();
     });
-});
-
-Template.stations.onCreated(function() {
-    var tag = document.createElement("script");
-    tag.src = "https://www.youtube.com/iframe_api";
-    var firstScriptTag = document.getElementsByTagName('script')[0];
-    firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
-    YTPlayer = undefined;
-});
+});

+ 25 - 35
app/client/scripts/onRendered.js

@@ -25,6 +25,31 @@ Template.queues.onRendered(function() {
     });
 });
 
+Template.manageStation.onRendered(function() {
+    $("#previewModal").on("hidden.bs.modal", function() {
+        if (previewEndSongTimeout !== undefined) {
+            Meteor.clearTimeout(previewEndSongTimeout);
+        }
+        $("#play").attr("disabled", false);
+        $("#stop").attr("disabled", true);
+        if (YTPlayer !== undefined) {
+            $("#previewPlayer").hide();
+            YTPlayer.seekTo(0);
+            YTPlayer.stopVideo();
+        }
+    });
+    $(document).ready(function() {
+        var volume = localStorage.getItem("volume") || 20;
+        $("#volume_slider").val(volume).on("input", function() {
+            volume = Number($("#volume_slider").val());
+            localStorage.setItem("volume", volume);
+            if (YTPlayer !== undefined) {
+                YTPlayer.setVolume(volume);
+            }
+        });
+    });
+});
+
 Template.room.onRendered(function() {
     if (rTimeInterval !== undefined) {
         Meteor.clearInterval(rTimeInterval)
@@ -63,39 +88,4 @@ Template.room.onRendered(function() {
         }
         makeSlider();
     });
-});
-
-Template.stations.onRendered(function() {
-    $("#previewModal").on("hidden.bs.modal", function() {
-        if (previewEndSongTimeout !== undefined) {
-            Meteor.clearTimeout(previewEndSongTimeout);
-        }
-        $("#play").attr("disabled", false);
-        $("#stop").attr("disabled", true);
-        if (YTPlayer !== undefined) {
-            $("#previewPlayer").hide();
-            YTPlayer.seekTo(0);
-            YTPlayer.stopVideo();
-        }
-    });
-    $(document).ready(function() {
-        function makeSlider(){
-            var slider = $("#volume-slider").slider();
-            var volume = localStorage.getItem("volume") || 20;
-            $("#volume-slider").slider("setValue", volume);
-            if (slider.length === 0) {
-                Meteor.setTimeout(function() {
-                    makeSlider();
-                }, 500);
-            } else {
-                slider.on("slide", function(val) {
-                    localStorage.setItem("volume", val.value);
-                    if (YTPlayer !== undefined) {
-                        YTPlayer.setVolume(val.value);
-                    }
-                });
-            }
-        }
-        makeSlider();
-    });
 });

+ 15 - 14
app/client/scripts/routes.js

@@ -100,20 +100,6 @@ Router.route("/admin", {
     }
 });
 
-Router.route("/admin/stations", {
-    waitOn: function() {
-        return [Meteor.subscribe("isModerator", Meteor.userId()), Meteor.subscribe("isAdmin", Meteor.userId())];
-    },
-    action: function() {
-        var user = Meteor.users.findOne({});
-        if (user !== undefined && user.profile !== undefined && (user.profile.rank === "admin" || user.profile.rank === "moderator")) {
-            this.render("stations");
-        } else {
-            this.redirect("/");
-        }
-    }
-});
-
 Router.route("/admin/queues", {
     waitOn: function() {
         return [Meteor.subscribe("isModerator", Meteor.userId()), Meteor.subscribe("isAdmin", Meteor.userId())];
@@ -174,3 +160,18 @@ Router.route("/:type", {
         }
     }
 });
+
+Router.route("/:type/manage", {
+    waitOn: function() {
+        return [Meteor.subscribe("isModerator", Meteor.userId()), Meteor.subscribe("isAdmin", Meteor.userId())];
+    },
+    action: function() {
+        var user = Meteor.users.findOne({});
+        var room = Rooms.findOne({type: this.params.type});
+        if (room !== undefined && user !== undefined && user.profile !== undefined && (user.profile.rank === "admin" || user.profile.rank === "moderator")) {
+            this.render("manageStation");
+        } else {
+            this.redirect("/");
+        }
+    }
+});

+ 141 - 0
app/client/templates/manageStation.html

@@ -0,0 +1,141 @@
+<template name="manageStation">
+    {{> alerts}}
+    <div class="landing">
+        {{> header}}
+        <div class="row">
+            <div class="col m8 s8 l8 offset-l2 offset-m1 offset-s2 admin-playlist-panel card-panel teal accent-3">
+                <div class="card-content white-text">
+                    <h3 class="text-center">{{display}} playlist</h3>
+                    <table class="bordered">
+                        <thead>
+                        <tr>
+                            <th>Title</th>
+                            <th>Artist(s)</th>
+                            <th>Id</th>
+                            <th>Mid</th>
+                            <th>Likes</th>
+                            <th>Dislikes</th>
+                            <th class="table-right-th">Edit</th>
+                            <th class="table-right-th">Remove</th>
+                        </tr>
+                        </thead>
+                        <tbody>
+                        {{#each songs}}
+                            <tr>
+                                <th align="left" scope="row">{{title}}</th>
+                                <td align="left">{{artist}}</td>
+                                <td align="left">{{id}}</td>
+                                <td align="left">{{mid}}</td>
+                                <td align="left">{{likes}}</td>
+                                <td align="left">{{dislikes}}</td>
+                                <td class="table-right-td">
+                                    <button class="btn edit-song-button" data-genre="{{genre}}"
+                                            data-toggle="modal" data-target="#editModal">Edit
+                                    </button>
+                                </td>
+                                <td class="table-right-td">
+                                    <button class="btn red remove-song-button" data-genre="{{genre}}"><i
+                                            class="material-icons">remove_circle</i></button>
+                                </td>
+                            </tr>
+                        {{/each}}
+                        </tbody>
+                    </table>
+                </div>
+            </div>
+        </div>
+    </div>
+    <div id="editModal" class="modal modal-fixed-footer">
+        <div class="modal-content musare white-text">
+            <div class="row">
+                <h4 class="center-align">Video Preview</h4>
+                <div class="video-container" id="previewPlayerContainer">
+                    <div width="960" height="540" id="previewPlayer"></div>
+                </div>
+                <div class="seeker-bar-container col l10 m10 s10 white" id="preview-progress">
+                    <div class="seeker-bar teal" style="width: 0%"></div>
+                </div>
+            <span class="col l2 m2 s2 center" id="preview-time">
+                <span id="time-elapsed">0:00</span> / <span id="time-total">0:00</span>
+            </span>
+                <button id="play" title="Play video" class="btn green col m1 s1 l1 offset-l3 offset-m3 offset-s3">
+                    <i class="material-icons">play_arrow</i>
+                </button>
+                <button id="stop" title="Stop video" class="btn red col m1 s1 l1" disabled>
+                    <i class="material-icons">stop</i>
+                </button>
+                <button id="pause" title="Pause video" class="btn orange col m1 s1 l1" disabled>
+                    <i class="material-icons">pause</i>
+                </button>
+                <button id="forward" title="Go to the last 10 seconds of the video" class="btn blue col m1 s1 l1" disabled>
+                    <i class="material-icons">fast_forward</i>
+                </button>
+                <form class="col m2 s2 l2" action="#">
+                    <p class="range-field" style="margin-top: 0">
+                        <input type="range" id="volume_slider" min="0" max="100" />
+                    </p>
+                </form>
+            </div>
+            <div class="row">
+                <h4 class="center-align">Image Preview</h4>
+                <img id="song-preview" onerror="this.src='http://static.boredpanda.com/blog/wp-content/uploads/2014/04/amazing-fox-photos-182.jpg'" class="center-block" src="{{song_image}}"/>
+            </div>
+            <div class="row">
+                <h4 class="center-align">Edit Info</h4>
+                <div class="input-field col l8 m8 s12 offset-l2 offset-m2">
+                    <i class="material-icons prefix">vpn_key</i>
+                    <label for="mid" class="white-text">Song MID</label>
+                    <input class="validate" name="mid" id="mid" type="text" pattern=".{6}"/>
+                </div>
+                <div class="input-field col l8 m8 s12 offset-l2 offset-m2">
+                    <i class="material-icons prefix">vpn_key</i>
+                    <label for="mid" class="white-text">Song ID</label>
+                    <input class="validate" name="id" id="id" type="text" pattern=".{11}"/>
+                </div>
+                <div class="input-field col l8 m8 s12 offset-l2 offset-m2">
+                    <i class="material-icons prefix">person</i>
+                    <label for="id" class="white-text">Song Artist</label>
+                    <input class="validate" name="artist" id="artist" aria-required="true" type="text"/>
+                </div>
+                <div class="input-field col l8 m8 s12 offset-l2 offset-m2">
+                    <i class="material-icons prefix">subject</i>
+                    <label for="title" class="white-text">Song Title</label>
+                    <input class="validate required" name="title" id="title" type="text"/>
+                </div>
+                <div class="input-field col l8 m8 s12 offset-l2 offset-m2">
+                    <i class="material-icons prefix">timelapse</i>
+                    <label for="title" class="white-text">Song Duration</label>
+                    <input class="validate" name="duration" id="duration" type="number" step="any" min="0"/>
+                </div>
+                <div class="input-field col l8 m8 s12 offset-l2 offset-m2">
+                    <i class="material-icons prefix">timer_off</i>
+                    <label for="skip-duration" class="white-text">Skip Duration</label>
+                    <input class="validate" id="skip-duration" type="number" step="any" min="0"/>
+                </div>
+                <div class="input-field col l8 m8 s12 offset-l2 offset-m2">
+                    <i class="material-icons prefix">thumb_up</i>
+                    <label for="likes" class="white-text">Likes</label>
+                    <input disabled id="likes" type="number"/>
+                </div>
+                <div class="input-field col l8 m8 s12 offset-l2 offset-m2">
+                    <i class="material-icons prefix">thumb_down</i>
+                    <label for="dislikes" class="white-text">Dislikes</label>
+                    <input disabled id="dislikes" type="number"/>
+                </div>
+                <div class="input-field col l8 m8 s12 offset-l2 offset-m2">
+                    <i class="material-icons prefix">image</i>
+                    <label for="img" class="white-text">Song Image</label>
+                    <input class="validate" name="img" id="img" type="url"/>
+                </div>
+            </div>
+            <div class="row">
+                <button type="button" id="get-spotify-info" class="btn btn-large col l6 m6 s10 offset-l3 offset-m3 offset-s1 waves-effect waves-light">Get Spotify Data</button>
+                <button type="button" id="save-song-button" class="btn btn-large col l6 m6 s10 offset-l3 offset-m3 offset-s1 waves-effect waves-light">Save Changes</button>
+            </div>
+
+        </div>
+        <div class="modal-footer musare white-text">
+            <a href="#!" class="modal-action modal-close waves-effect waves-light btn-flat white">X</a>
+        </div>
+    </div>
+</template>

+ 0 - 156
app/client/templates/stations.html

@@ -1,156 +0,0 @@
-<template name="stations">
-    {{> alerts}}
-    <div class="landing">
-        {{> header}}
-            <h1 class="col-md-8 col-md-offset-2 admin-header">Playlist for {{whichStation}}</h1>
-                {{#each playlist}}
-                    <div class="col-md-8 col-md-offset-2 admin-playlist-panel">
-                        <div class="panel panel-primary">
-                            <div class="panel-heading">
-                                <h3 class="panel-title">Delete</h3> <i class="fa fa-times delete-room" name="Delete room"></i>
-                            </div>
-                            <div class="panel-body admin-panel-body">
-                                <table class="table table-striped">
-                                    <thead>
-                                    <tr>
-                                        <th>Mid</th>
-                                        <th>Title</th>
-                                        <th>Artist(s)</th>
-                                        <th>Type</th>
-                                        <th>Id</th>
-                                        <th>Likes</th>
-                                        <th>Dislikes</th>
-                                        <th>Img</th>
-                                        <th>Preview</th>
-                                        <th>Edit</th>
-                                        <th colspan="10">Remove</th>
-                                    </tr>
-                                    </thead>
-                                    <tbody>
-                                    {{#each songs}}
-                                    <tr>
-                                        <th scope="row">{{mid}}</th>
-                                        <th>{{title}}</th>
-                                        <td>{{artist}}</td>
-                                        <td>{{type}}</td>
-                                        <td>{{id}}</td>
-                                        <td>{{likes}}</td>
-                                        <td>{{dislikes}}</td>
-                                        <td class="column-small"><button class="btn btn-primary preview-button" id="previewImageButton" data-toggle="modal" data-target="#previewImageModal">Preview Image</button></td>
-                                        <td class="column-small"><button class="btn btn-primary preview-button" data-toggle="modal" data-target="#previewModal">Preview</button></td>
-                                        <td class="column-small"><button class="btn btn-primary edit-playlist-button" data-genre="{{../type}}" data-toggle="modal" data-target="#editModal">Edit</button></td>
-                                        <td class="column-small"><button class="btn btn-danger remove-song-button" data-genre="{{../type}}"><i class="fa fa-ban"></i></button></td>
-                                    </tr>
-                                    {{/each}}
-                                    </tbody>
-                                </table>
-                            </div>
-                        </div>
-                    </div>
-                {{/each}}
-            <div class="row" style="margin-top: 20px; height: 100%;">
-                <div class="col-md-8 col-md-offset-2 admin-container">
-                    <div>
-                        <h1>Reports</h1>
-                    </div>
-                        <p>{{display}}</p>
-                        <table class="table table-striped">
-                        <thead>
-                            <tr>
-                            <th>Song mid</th>
-                            <th>Report Type</th>
-                            <th>Report Reason</th>
-                            <th>Comments</th>
-                            </tr>
-                        </thead>
-                        {{#each reports}}
-                            {{#each report}}
-                                <tr>
-                                    <td>{{song}}</td>
-                                    <td>{{type}}</td>
-                                    <td>{{reason}}</td>
-                                    <td>{{other}}</td>
-                                </tr>
-                            {{/each}}
-                        {{/each}}
-                      </table>
-                </div>
-            </div>
-            <div id="previewModal" class="modal fade" role="dialog">
-                <div class="modal-dialog">
-                    <!-- Modal content-->
-                    <div class="modal-content">
-                        <div class="modal-header">
-                            <button type="button" class="close" data-dismiss="modal">&times;</button>
-                            <h4 class="modal-title">Preview</h4>
-                        </div>
-                        <div class="modal-body">
-                            <div width="960" height="540" id="previewPlayer"></div>
-                            <button id="play" title="Play video" class="btn btn-success"><i class="fa fa-play"></i></button>
-                            <button id="stop" title="Stop video" class="btn btn-danger" disabled><i class="fa fa-stop"></i></button>
-                            <button id="forward" title="Go to the last 10 seconds of the video" class="btn btn-primary"><i class="fa fa-fast-forward"></i></button>
-                            <div id="volume-container-admin">
-                                <input type="text" id="volume-slider" class="span2" value="" data-slider-min="0" data-slider-max="100" data-slider-step="1" data-slider-value="50" data-slider-orientation="horizontal" data-slider-selection="after" data-slider-tooltip="hide">
-                            </div>
-                        </div>
-                        <div class="modal-footer">
-                            <button id="close-modal" type="button" class="btn btn-default" data-dismiss="modal">Close</button>
-                        </div>
-                    </div>
-                </div>
-            </div>
-                <div id="previewImageModal" class="modal fade" role="dialog">
-                    <div class="modal-dialog">
-                        <!-- Modal content-->
-                        <div class="modal-content">
-                            <div class="modal-header">
-                                <button type="button" class="close" data-dismiss="modal">&times;</button>
-                                <h4 class="modal-title">Preview Image</h4>
-                            </div>
-                            <div class="modal-body">
-                                <img alt="Not loading" id="preview-image" height="210px" width="210px" src=""/>
-                            </div>
-                            <div class="modal-footer">
-                                <button id="close-modal" type="button" class="btn btn-default" data-dismiss="modal">Close</button>
-                            </div>
-                        </div>
-                    </div>
-                </div>
-            <div id="editModal" class="modal fade" role="dialog">
-                <div class="modal-dialog">
-                    <!-- Modal content-->
-                    <div class="modal-content">
-                        <div class="modal-header">
-                            <button type="button" class="close" data-dismiss="modal">&times;</button>
-                            <h4 class="modal-title">Edit</h4>
-                        </div>
-                        <div class="modal-body">
-                            <label for="mid" class="song-input-label">Song MID</label>
-                            <input class="song-input" name="mid" id="mid" type="text" />
-                            <label for="id" class="song-input-label">Song ID</label>
-                            <input class="song-input" name="id" id="id" type="text" />
-                            <label for="id" class="song-input-label">Song Artist</label>
-                            <input class="song-input" name="artist" id="artist" type="text" />
-                            <label for="title" class="song-input-label">Song Title</label>
-                            <input class="song-input" name="title" id="title" type="text" />
-                            <label for="title" class="song-input-label">Song Duration</label>
-                            <input class="song-input" name="duration" id="duration" type="number" />
-                            <label for="skip-duration" class="song-input-label">Skip Duration</label>
-                            <input class="song-input" id="skip-duration" type="number" />
-                            <label for="likes" class="song-input-label">Likes</label>
-                            <input class="song-input" id="likes" type="number"/>
-                            <label for="dislikes" class="song-input-label">Dislikes</label>
-                            <input class="song-input" id="dislikes" type="number"/>
-                            <label for="img" class="song-input-label">Song Image</label>
-                            <input class="song-input" name="img" id="img" type="text" />
-                            <button type="button" id="get-spotify-info" class="button">Get Spotify Data</button>
-                            <button type="button" id="save-song-button" class="button">Save Changes</button>
-                        </div>
-                        <div class="modal-footer">
-                            <button id="close-modal" type="button" class="btn btn-default" data-dismiss="modal">Close</button>
-                        </div>
-                    </div>
-                </div>
-            </div>
-        </div>
-</template>

+ 11 - 1
app/server/server.js

@@ -1000,7 +1000,17 @@ Meteor.methods({
     updatePlaylistSong: function (genre, oldSong, newSong) {
         if (isModerator() && !isBanned()) {
             newSong.mid = oldSong.mid;
-            Playlists.update({type: genre, "songs": oldSong}, {$set: {"songs.$": newSong}});
+            newSong.approvedBy = Meteor.userId();
+            console.log(genre);
+            console.log(oldSong);
+            Playlists.update({type: genre, "songs": oldSong}, {$set: {"songs.$": newSong}}, function(err) {
+                console.log(err);
+                if (err) {
+                    throw err.sanitizedError;
+                } else {
+                    return true;
+                }
+            });
             return true;
         } else {
             throw new Meteor.Error(403, "Invalid permissions.");