Bladeren bron

fixed room creation bug

Akira Laine 9 jaren geleden
bovenliggende
commit
1c852d2031

+ 761 - 4
app/client/scripts/events.js

@@ -182,7 +182,7 @@ Template.admin.events({
         Session.set("playlistToEdit", id);
     },
     "click #croom_create": function() {
-        Meteor.call("createRoom", $("#croom_display").val(), $("#croom_tag").val(), $("#croom_private").prop("checked"), function (err, res) {
+        Meteor.call("createRoom", $("#croom_display").val(), $("#croom_tag").val(), $("#croom_private").prop("checked"), $("#croom_desc").val(), function (err, res) {
             if (err) {
                 alert("Error " + err.error + ": " + err.reason);
             } else {
@@ -906,10 +906,767 @@ Template.register.events({
     }
 });
 
-/*Template.room.events({
+Template.news.events({
+    "click #createArticleButton": function() {
+        var title = $("#title").val();
+        var content = $("#content").val();
+        var anonymous = $("#anonymous").is(":checked");
+        Meteor.call("createArticle", {title: title, content: content, anonymous: anonymous}, function(err, res) {
+            if (err) {
+                var $toastContent = $('<span><strong>Article not created.</strong> ' + err.reason + '</span>');
+                Materialize.toast($toastContent, 8000);
+            } else {
+                $('#createArticle').closeModal()
+                $("#title").val("").change();
+                $("#content").val("").change();
+                $("#anonymous").prop("checked", false).change();
+            }
+        });
+    }
+});
 
-});*/
+Template.room.events({
+    "click #youtube-playlist-button": function () {
+        if (!Session.get("importingPlaylist")) {
+            var playlist_link = $("#youtube-playlist-input").val();
+            var playlist_id = gup("list", playlist_link);
+            var ytImportQueue = [];
+            var totalVideos = 0;
+            var videosInvalid = 0;
+            var videosInQueue = 0;
+            var videosInPlaylist = 0;
+            var ranOnce = false;
 
+            Session.set("importingPlaylist", true);
+            $("#youtube-playlist-button").attr("disabled", "");
+            $("#youtube-playlist-button").addClass("disabled");
+            $("#youtube-playlist-input").attr("disabled", "");
+            $("#youtube-playlist-input").addClass("disabled");
+            $("#playlist-import-queue").empty();
+            $("#playlist-import-queue").hide();
+            $("#add-youtube-playlist").addClass("hidden-2");
+            $("#import-progress").attr("aria-valuenow", 0);
+            $("#import-progress").css({width: "0%"});
+            $("#import-progress").text("0%");
+
+            function makeAPICall(playlist_id, nextPageToken) {
+                if (nextPageToken !== undefined) {
+                    nextPageToken = "&pageToken=" + nextPageToken;
+                } else {
+                    nextPageToken = "";
+                }
+                $.ajax({
+                    type: "GET",
+                    url: "https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&maxResults=50&playlistId=" + playlist_id + nextPageToken + "&key=AIzaSyAgBdacEWrHCHVPPM4k-AFM7uXg-Q__YXY",
+                    applicationType: "application/json",
+                    contentType: "json",
+                    success: function (data) {
+                        if (!ranOnce) {
+                            ranOnce = true;
+                            totalVideos = data.pageInfo.totalResults;
+                        }
+                        var nextToken = data.nextPageToken;
+                        for (var i in data.items) {
+                            var item = data.items[i];
+                            if (item.snippet.thumbnails !== undefined) {
+                                var genre = Session.get("type");
+                                if (Playlists.find({
+                                        type: genre,
+                                        "songs.id": item.snippet.resourceId.videoId
+                                    }, {songs: {$elemMatch: {id: item.snippet.resourceId.videoId}}}).count() !== 0) {
+                                    videosInPlaylist++;
+                                } else if (Queues.find({
+                                        type: genre,
+                                        "songs.id": item.snippet.resourceId.videoId
+                                    }, {songs: {$elemMatch: {id: item.snippet.resourceId.videoId}}}).count() !== 0) {
+                                    videosInQueue++;
+                                } else {
+                                    $("#playlist-import-queue").append(
+                                        "<div class='youtube-import-queue-item'>" +
+                                        "<img src='" + item.snippet.thumbnails.medium.url + "' class='song-result-thumbnail'/>" +
+                                        "<div>" +
+                                        "<span class='song-result-title'>" + item.snippet.title + "</span>" +
+                                        "<span class='song-result-channel'>" + item.snippet.channelTitle + "</span>" +
+                                        "</div>" +
+                                        "<i class='fa fa-times remove-import-song'></i>" +
+                                        "</div>"
+                                    );
+                                    var percentage = ytImportQueue.length / (totalVideos - videosInvalid) * 100;
+                                    $("#import-progress").attr("aria-valuenow", percentage.toFixed(2));
+                                    $("#import-progress").css({width: percentage + "%"});
+                                    $("#import-progress").text(percentage.toFixed(1) + "%");
+                                    ytImportQueue.push({
+                                        title: item.snippet.title,
+                                        id: item.snippet.resourceId.videoId
+                                    });
+                                }
+                            } else {
+                                videosInvalid++;
+                            }
+                        }
+                        if (nextToken !== undefined) {
+                            makeAPICall(playlist_id, nextToken);
+                        } else {
+                            $("#playlist-import-queue > div > i").click(function () {
+                                var title = $(this).parent().find("div > .song-result-title").text();
+                                for (var i in ytImportQueue) {
+                                    if (ytImportQueue[i].title === title) {
+                                        ytImportQueue.splice(i, 1);
+                                    }
+                                }
+                                $(this).parent().remove();
+                                Session.set("YTImportQueue", ytImportQueue);
+                            });
+                            Session.set("importingPlaylist", false);
+                            $("#import-progress").attr("aria-valuenow", 100);
+                            $("#import-progress").css({width: "100%"});
+                            $("#import-progress").text("100%");
+                            $("#youtube-playlist-button").removeAttr("disabled");
+                            $("#youtube-playlist-button").removeClass("disabled");
+                            $("#youtube-playlist-input").removeAttr("disabled");
+                            $("#youtube-playlist-input").removeClass("disabled");
+                            $("#playlist-import-queue").show();
+                            $("#add-youtube-playlist").removeClass("hidden-2");
+                            Session.set("YTImportQueue", ytImportQueue);
+                        }
+                    }
+                })
+            }
+
+            makeAPICall(playlist_id);
+        }
+    },
+    "click #add-youtube-playlist": function () {
+        var YTImportQueue = Session.get("YTImportQueue");
+        $("#youtube-playlist-button").attr("disabled", "");
+        $("#youtube-playlist-button").addClass("disabled");
+        $("#youtube-playlist-input").attr("disabled", "");
+        $("#youtube-playlist-input").addClass("disabled");
+        $("#import-progress").attr("aria-valuenow", 0);
+        $("#import-progress").css({width: "0%"});
+        $("#import-progress").text("0%");
+        var failed = 0;
+        var success = 0;
+        var processed = 0;
+        var total = YTImportQueue.length;
+        YTImportQueue.forEach(function (song) {
+            var songData = {type: "YouTube", id: song.id, title: song.title, artist: "", img: ""};
+            Meteor.call("addSongToQueue", songData, function (err, res) {
+                if (err) {
+                    console.log(err);
+                    failed++;
+                } else {
+                    success++;
+                }
+                processed++;
+                var percentage = processed / total * 100;
+                $("#import-progress").attr("aria-valuenow", percentage.toFixed(2));
+                $("#import-progress").css({width: percentage + "%"});
+                $("#import-progress").text(percentage.toFixed(1) + "%");
+            });
+        });
+    },
+    "click #chat-tab": function () {
+        $("#chat-tab").removeClass("unread-messages");
+    },
+    "click #global-chat-tab": function () {
+        $("#global-chat-tab").removeClass("unread-messages");
+    },
+    "click #sync": function () {
+        if (Session.get("currentSong") !== undefined) {
+            var room = Rooms.findOne({type: Session.get("type")});
+            if (room !== undefined) {
+                var timeIn = Date.now() - Session.get("currentSong").started - room.timePaused;
+                var skipDuration = Number(Session.get("currentSong").skipDuration) | 0;
+                if (YTPlayer !== undefined) {
+                    YTPlayer.seekTo(skipDuration + timeIn / 1000);
+                }
+            }
+        }
+    },
+    "click #lock": function () {
+        Meteor.call("lockRoom", Session.get("type"));
+    },
+    "click #unlock": function () {
+        Meteor.call("unlockRoom", Session.get("type"));
+    },
+    "click #chat-tab": function (e) {
+        Meteor.setTimeout(function () {
+            $("#chat-ul").scrollTop(100000);
+        }, 1);
+    },
+    "click #global-chat-tab": function (e) {
+        Meteor.setTimeout(function () {
+            $("#global-chat-ul").scrollTop(100000);
+        }, 1);
+    },
+    "click #submit": function () {
+        sendMessage();
+        Meteor.setTimeout(function () {
+            $("#chat-ul").scrollTop(100000);
+        }, 1000)
+    },
+    "click #global-submit": function () {
+        sendMessageGlobal();
+        Meteor.setTimeout(function () {
+            $("#global-chat-ul").scrollTop(100000);
+        }, 1000)
+    },
+    "keyup #chat-input": function (e) {
+        if (e.type === "keyup" && e.which === 13) {
+            e.preventDefault();
+            if (!$('#chat-input').data('dropdownshown')) {
+                sendMessage();
+                Meteor.setTimeout(function () {
+                    $("#chat-ul").scrollTop(100000);
+                }, 1000)
+            }
+        }
+    },
+    "keyup #global-chat-input": function (e) {
+        if (e.type === "keyup" && e.which === 13) {
+            e.preventDefault();
+            if (!$('#global-chat-input').data('dropdownshown')) {
+                sendMessageGlobal();
+                Meteor.setTimeout(function () {
+                    $("#global-chat-ul").scrollTop(100000);
+                }, 1000)
+            }
+        }
+    },
+    "click #like": function (e) {
+        $("#like").blur();
+        Meteor.call("likeSong", Session.get("currentSong").mid);
+    },
+    "click #dislike": function (e) {
+        $("#dislike").blur();
+        Meteor.call("dislikeSong", Session.get("currentSong").mid);
+    },
+    "click #vote-skip": function () {
+        Meteor.call("voteSkip", type, function (err, res) {
+            $("#vote-skip").attr("disabled", true);
+        });
+    },
+    "click #report-prev": function (e) {
+        if (Session.get("previousSong") !== undefined) {
+            Session.set("reportPrevious", true);
+            $("#report-prev").prop("disabled", true);
+            $("#report-curr").prop("disabled", false);
+        }
+    },
+    "click #report-curr": function (e) {
+        Session.set("reportPrevious", false);
+        $("#report-prev").prop("disabled", false);
+        $("#report-curr").prop("disabled", true);
+    },
+    "click #report-modal": function () {
+        Session.set("currentSongR", Session.get("currentSong"));
+        Session.set("previousSongR", Session.get("previousSong"));
+    },
+    "click #add-song-button": function (e) {
+        e.preventDefault();
+        parts = location.href.split('/');
+        var roomType = parts.pop();
+        var genre = roomType.toLowerCase();
+        var type = $("#type").val();
+        id = $("#id").val();
+        var title = $("#title").val();
+        var artist = $("#artist").val();
+        var img = $("#img").val();
+        var songData = {type: type, id: id, title: title, artist: artist, img: img};
+        if (Playlists.find({
+                type: genre,
+                "songs.id": songData.id
+            }, {songs: {$elemMatch: {id: songData.id}}}).count() !== 0) {
+            $("<div class='alert alert-danger alert-dismissible' role='alert' style='margin-bottom: 0'><button type='button' class='close' data-dismiss='alert' aria-label='Close'><span aria-hidden='true'><i class='fa fa-times'></i></span></button><strong>Song not added.</strong> This song is already in the playlist.</div>").prependTo($(".landing")).delay(7000).fadeOut(1000, function () {
+                $(this).remove();
+            });
+        } else if (Queues.find({
+                type: genre,
+                "songs.id": songData.id
+            }, {songs: {$elemMatch: {id: songData.id}}}).count() !== 0) {
+            $("<div class='alert alert-danger alert-dismissible' role='alert' style='margin-bottom: 0'><button type='button' class='close' data-dismiss='alert' aria-label='Close'><span aria-hidden='true'><i class='fa fa-times'></i></span></button><strong>Song not added.</strong> This song has already been requested.</div>").prependTo($(".landing")).delay(7000).fadeOut(1000, function () {
+                $(this).remove();
+            });
+        } else {
+            Meteor.call("addSongToQueue", songData, function (err, res) {
+                console.log(err, res);
+                if (err) {
+                    $("<div class='alert alert-danger alert-dismissible' role='alert' style='margin-bottom: 0'><button type='button' class='close' data-dismiss='alert' aria-label='Close'><span aria-hidden='true'><i class='fa fa-times'></i></span></button><strong>Song not added.</strong> Something went wrong.</div>").prependTo($(".landing")).delay(7000).fadeOut(1000, function () {
+                        $(this).remove();
+                    });
+                } else {
+                    $("<div class='alert alert-success alert-dismissible' role='alert' style='margin-bottom: 0'><button type='button' class='close' data-dismiss='alert' aria-label='Close'><span aria-hidden='true'><i class='fa fa-times'></i></span></button><strong>Song added.</strong> Your song has been added to the queue.</div>").prependTo($(".landing")).delay(7000).fadeOut(1000, function () {
+                        $(this).remove();
+                    });
+                }
+            });
+        }
+        $("#close-modal-a").click();
+    },
+    "click #toggle-video": function (e) {
+        e.preventDefault();
+        if (Session.get("mediaHidden")) {
+            $("#media-container").removeClass("hidden");
+            $("#toggle-video").text("Hide video");
+            Session.set("mediaHidden", false);
+        } else {
+            $("#media-container").addClass("hidden");
+            $("#toggle-video").text("Show video");
+            Session.set("mediaHidden", true);
+        }
+    },
+    "click #return": function (e) {
+        $("#add-info").hide();
+        $("#search-info").show();
+    },
+    "click #search-song": function () {
+        var songs = [];
+        $("#song-results").empty();
+        $.ajax({
+            type: "GET",
+            url: "https://www.googleapis.com/youtube/v3/search?part=snippet&q=" + $("#song-input").val() + "&key=AIzaSyAgBdacEWrHCHVPPM4k-AFM7uXg-Q__YXY",
+            applicationType: "application/json",
+            contentType: "json",
+            success: function (data) {
+                for (var i in data.items) {
+                    var item = data.items[i];
+                    $("#song-results").append(
+                        "<div>" +
+                        "<img src='" + item.snippet.thumbnails.medium.url + "' class='song-result-thumbnail'/>" +
+                        "<div>" +
+                        "<span class='song-result-title'>" + item.snippet.title + "</span>" +
+                        "<span class='song-result-channel'>" + item.snippet.channelTitle + "</span>" +
+                        "</div>" +
+                        "</div>"
+                    );
+                    songs.push({title: item.snippet.title, id: item.id.videoId});
+                }
+                $("#song-results > div").click(function () {
+                    $("#search-info").hide();
+                    $("#add-info").show();
+                    var title = $(this).find("div > .song-result-title").text();
+                    for (var i in songs) {
+                        if (songs[i].title === title) {
+                            var songObj = {
+                                id: songs[i].id,
+                                title: songs[i].title,
+                                type: "youtube"
+                            };
+                            $("#title").val(songObj.title);
+                            $("#artist").val("");
+                            $("#id").val(songObj.id);
+                            getSpotifyInfo(songObj.title.replace(/\[.*\]/g, ""), function (data) {
+                                if (data.tracks.items.length > 0) {
+                                    $("#title").val(data.tracks.items[0].name);
+                                    var artists = [];
+                                    $("#img").val(data.tracks.items[0].album.images[2].url);
+                                    data.tracks.items[0].artists.forEach(function (artist) {
+                                        artists.push(artist.name);
+                                    });
+                                    $("#artist").val(artists.join(", "));
+                                }
+                            });
+                        }
+                    }
+                })
+            }
+        })
+    },
+    "click #volume-icon": function () {
+        var volume = 0;
+        var slider = $("#volume-slider").slider();
+        $("#volume-icon").removeClass("fa-volume-down").addClass("fa-volume-off")
+        if (YTPlayer !== undefined) {
+            YTPlayer.setVolume(volume);
+            localStorage.setItem("volume", volume);
+            $("#volume-slider").slider("setValue", volume);
+        }
+    },
+    "click #play": function () {
+        Meteor.call("resumeRoom", type);
+    },
+    "click #pause": function () {
+        Meteor.call("pauseRoom", type);
+    },
+    "click #skip": function () {
+        Meteor.call("skipSong", type);
+    },
+    "click #shuffle": function () {
+        Meteor.call("shufflePlaylist", type);
+    },
+    "change input": function (e) {
+        if (e.target && e.target.id) {
+            var partsOfId = e.target.id.split("-");
+            partsOfId[1] = partsOfId[1].charAt(0).toUpperCase() + partsOfId[1].slice(1);
+            var camelCase = partsOfId.join("");
+            Session.set(camelCase, e.target.checked);
+        }
+    },
+    "click #report-song-button": function () {
+        var room = Session.get("type");
+        var reportData = {};
+        reportData.song = Session.get("currentSong").mid;
+        reportData.type = [];
+        reportData.reason = [];
+
+        $(".report-layer-1 > .checkbox input:checked").each(function () {
+            reportData.type.push(this.id);
+            if (this.id == "report-other") {
+                var otherText = $(".other-textarea").val();
+            }
+        });
+
+        $(".report-layer-2 input:checked").each(function () {
+            reportData.reason.push(this.id);
+        });
+
+        console.log(reportData);
+        Meteor.call("submitReport", room, reportData, Session.get("id"), function () {
+            $("#close-modal-r").click();
+        });
+    },
+    "change #si_or_pl": function () {
+        if ($("#select_playlist").is(':selected')) {
+            $("#search-info").hide();
+            $("#playlist-import").show();
+        }
+        if ($("#select_single").is(':selected')) {
+            $("#search-info").show();
+            $("#playlist-import").hide();
+        }
+    },
+    "click #close-modal-a": function () {
+        $("#select_single").attr("selected", true);
+        $("#search-info").show();
+        $("#playlist-import").hide();
+    }
+});
+
+Template.room.helpers({
+    singleVideo: function() {
+        return true;
+    },
+    chat: function() {
+        Meteor.setTimeout(function() {
+            var elem = document.getElementById('chat');
+            if (elem !== undefined && elem !== null) {
+                elem.scrollTop = elem.scrollHeight;
+            }
+        }, 100);
+        return Chat.find({type: Session.get("type")}, {sort: {time: -1}, limit: 50 }).fetch().reverse();
+    },
+    globalChat: function() {
+        Meteor.setTimeout(function() {
+            var elem = document.getElementById('global-chat');
+            if (elem !== undefined && elem !== null) {
+                elem.scrollTop = elem.scrollHeight;
+            }
+        }, 100);
+        return Chat.find({type: "global"}, {sort: {time: -1}, limit: 50 }).fetch().reverse();
+    },
+    likes: function() {
+        var playlist = Playlists.findOne({type: Session.get("type")});
+        var likes = 0;
+        playlist.songs.forEach(function(song) {
+            if (Session.get("currentSong") && song.mid === Session.get("currentSong").mid) {
+                likes = song.likes;
+                return;
+            }
+        });
+        return likes;
+    },
+    dislikes: function() {
+        var playlist = Playlists.findOne({type: Session.get("type")});
+        var dislikes = 0;
+        playlist.songs.forEach(function(song) {
+            if (Session.get("currentSong") && song.mid === Session.get("currentSong").mid) {
+                dislikes = song.dislikes;
+                return;
+            }
+        });
+        return dislikes;
+    },
+    liked: function() {
+        if (Meteor.userId()) {
+            var currentSong = Session.get("currentSong");
+            if (currentSong && Meteor.user().profile.liked.indexOf(currentSong.mid) !== -1) {
+                return "active";
+            } else {
+                return "";
+            }
+        } else {
+            "";
+        }
+    },
+    disliked: function() {
+        if (Meteor.userId()) {
+            var currentSong = Session.get("currentSong");
+            if (currentSong && Meteor.user().profile.disliked.indexOf(currentSong.mid) !== -1) {
+                return "active";
+            } else {
+                return "";
+            }
+        } else {
+            "";
+        }
+    },
+    type: function() {
+        var parts = location.href.split('/');
+        var id = parts.pop().toLowerCase();
+        return Rooms.findOne({type: id}).display;
+    },
+    users: function() {
+        var parts = location.href.split('/');
+        var id = parts.pop().toLowerCase();
+        return Rooms.findOne({type: id}).users;
+    },
+    title: function(){
+        return Session.get("title");
+    },
+    artist: function(){
+        return Session.get("artist");
+    },
+    loaded: function() {
+        return Session.get("loaded");
+    },
+    paused: function() {
+        return Session.get("state") === "paused";
+    },
+    private: function() {
+        return Rooms.findOne({type: Session.get("type")}).private === true;
+    },
+    report: function() {
+        return Session.get("reportObj");
+    },
+    reportSong: function() {
+        return Session.get("reportSong");
+    },
+    reportTitle: function() {
+        return Session.get("reportTitle");
+    },
+    reportAuthor: function() {
+        return Session.get("reportAuthor");
+    },
+    reportDuration: function() {
+        return Session.get("reportDuration");
+    },
+    reportAudio: function() {
+        return Session.get("reportAudio");
+    },
+    reportAlbumart: function() {
+        return Session.get("reportAlbumart");
+    },
+    reportOther: function() {
+        return Session.get("reportOther");
+    },
+    currentSong: function() {
+        return Session.get("currentSong");
+    },
+    previousSong: function() {
+        return Session.get("previousSong");
+    },
+    currentSongR: function() {
+        return Session.get("currentSongR");
+    },
+    previousSongR: function() {
+        return Session.get("previousSongR");
+    },
+    reportingSong: function() {
+        if (Session.get("reportPrevious")) {
+            return Session.get("previousSongR");
+        } else {
+            return Session.get("currentSongR");
+        }
+    },
+    votes: function(){
+        return Rooms.findOne({type: Session.get("type")}).votes;
+    }
+});
+Template.room.onCreated(function () {
+    Chat.after.find(function(userId, selector) {
+        if (selector.type === "global") {
+            if (!$("#global-chat-tab").hasClass("active")) {
+                $("#global-chat-tab").addClass("unread-messages");
+            }
+        } else if(selector.type === Session.get("type")) {
+            if (!$("#chat-tab").hasClass("active")) {
+                $("#chat-tab").addClass("unread-messages");
+            }
+        }
+    });
+    Session.set("reportSong", false);
+    Session.set("reportTitle", false);
+    Session.set("reportAuthor", false);
+    Session.set("reportDuration", false);
+    Session.set("reportAudio", false);
+    Session.set("reportAlbumart", false);
+    Session.set("reportOther", false);
+    /*if (resizeSeekerbarInterval !== undefined) {
+        Meteor.clearInterval(resizeSeekerbarInterval);
+        resizeSeekerbarInterval = undefined;
+    }*/
+    YTPlayer = undefined;
+    Session.set("videoHidden", false);
+    var tag = document.createElement("script");
+    tag.src = "https://www.youtube.com/iframe_api";
+    var firstScriptTag = document.getElementsByTagName('script')[0];
+    firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
+
+    Session.set("singleVideo", true);
+
+    var currentSong = undefined;
+    var currentSongR = undefined;
+
+    function getTimeElapsed() {
+        if (currentSong !== undefined) {
+            var room = Rooms.findOne({type: type});
+            if (room !== undefined) {
+                return Date.now() - currentSong.started - room.timePaused;
+            }
+        }
+        return 0;
+    }
+
+    function getSongInfo(songData){
+        Session.set("title", songData.title);
+        Session.set("artist", songData.artist);
+        Session.set("id", songData.id);
+        $("#song-img").attr("src", songData.img);
+        Session.set("duration", parseInt(songData.duration));
+        var d = moment.duration(parseInt(songData.duration), 'seconds');
+        $("#time-total").text(d.minutes() + ":" + ("0" + d.seconds()).slice(-2));
+        Session.set("timeFormat", d.minutes() + ":" + ("0" + d.seconds()).slice(-2));
+    }
+
+    function resizeSeekerbar() {
+        if (Session.get("state") === "playing") {
+            $("#seeker-bar").width(((getTimeElapsed() / 1000) / Session.get("duration") * 100) + "%");
+        }
+    }
+
+    function startSong() {
+        $("#time-elapsed").text("0:00");
+        $("#vote-skip").attr("disabled", false);
+        if (currentSong !== undefined) {
+            if (YTPlayer !== undefined && YTPlayer.stopVideo !== undefined) YTPlayer.stopVideo();
+
+            var volume = localStorage.getItem("volume") || 20;
+
+            if ($("#player").length !== 1) {
+                $("#media-container").append('<div id="player" class="embed-responsive-item"></div>');
+            }
+            $("#player").show();
+            function loadVideo() {
+                if (!Session.get("YTLoaded")) {
+                    Session.set("loadVideoTimeout", Meteor.setTimeout(function () {
+                        loadVideo();
+                    }, 500));
+                } else {
+                    if (YTPlayer === undefined) {
+                        YTPlayer = new YT.Player("player", {
+                            height: 540,
+                            width: 960,
+                            videoId: currentSong.id,
+                            playerVars: {controls: 0, iv_load_policy: 3, rel: 0, showinfo: 0},
+                            events: {
+                                'onReady': function (event) {
+                                    if (currentSong.skipDuration === undefined) {
+                                        currentSong.skipDuration = 0;
+                                    }
+                                    event.target.seekTo(Number(currentSong.skipDuration) + getTimeElapsed() / 1000);
+                                    event.target.playVideo();
+                                    event.target.setVolume(volume);
+                                    resizeSeekerbar();
+                                },
+                                'onStateChange': function (event) {
+                                    if (Session.get("YTLoaded")) {
+                                        if (event.data == YT.PlayerState.PAUSED && Session.get("state") === "playing") {
+                                            event.target.seekTo(Number(currentSong.skipDuration) + getTimeElapsed() / 1000);
+                                            event.target.playVideo();
+                                        }
+                                        if (event.data == YT.PlayerState.PLAYING && Session.get("state") === "paused") {
+                                            event.target.seekTo(Number(currentSong.skipDuration) + getTimeElapsed() / 1000);
+                                            event.target.pauseVideo();
+                                        }
+                                    }
+                                }
+                            }
+                        });
+                    } else {
+                        YTPlayer.loadVideoById(currentSong.id);
+                        if (currentSong.skipDuration === undefined) {
+                            currentSong.skipDuration = 0;
+                        }
+                        YTPlayer.seekTo(Number(currentSong.skipDuration) + getTimeElapsed() / 1000);
+                    }
+                    Session.set("pauseVideo", false);
+                    getSongInfo(currentSong);
+                }
+            }
+            loadVideo();
+        }
+    }
+
+    Session.set("loaded", false);
+    Meteor.subscribe("rooms", function() {
+        var parts = location.href.split('/');
+        var id = parts.pop();
+        var type = id.toLowerCase();
+        Session.set("type", type);
+        if (Rooms.find({type: type}).count() !== 1) {
+            window.location = "/";
+        } else {
+            StationSubscription = Meteor.subscribe(type);
+            Session.set("loaded", true);
+            minterval = Meteor.setInterval(function () {
+                var room = Rooms.findOne({type: type});
+                if (room !== undefined) {
+                    if (room.state === "paused" || Session.get("pauseVideo")) {
+                        Session.set("state", "paused");
+                        // TODO Fix issue where sometimes nothing loads with the YT is not defined error. The error points to around this.
+                        if (YTPlayer !== undefined && YTPlayer.getPlayerState !== undefined && YTPlayer.getPlayerState() === 1) {
+                            YTPlayer.pauseVideo();
+                        }
+                    } else {
+                        Session.set("state", "playing");
+                        if (YTPlayer !== undefined && YTPlayer.getPlayerState !== undefined && YTPlayer.getPlayerState() !== 1) {
+                            YTPlayer.playVideo();
+                        }
+                    }
+                }
+
+                if (room.currentSong.song !== undefined && (currentSongR === undefined || room.currentSong.started !== currentSongR.started)) {
+                    Session.set("previousSong", currentSong);
+                    currentSongR = room.currentSong;
+
+                    currentSong = room.currentSong.song;
+                    currentSong.started = room.currentSong.started;
+                    Session.set("currentSong", currentSong);
+                    Meteor.clearTimeout(Session.get("loadVideoTimeout"));
+                    startSong();
+                }
+
+                if (currentSong !== undefined) {
+                    if (room !== undefined) {
+                        var duration = (Date.now() - currentSong.started - room.timePaused) / 1000;
+                        var song_duration = currentSong.duration;
+                            if (song_duration <= duration) {
+                                Session.set("pauseVideo", true);
+                            }
+                        var d = moment.duration(duration, 'seconds');
+                        if (Session.get("state") === "playing") {
+                            $("#time-elapsed").text(d.minutes() + ":" + ("0" + d.seconds()).slice(-2));
+                        }
+                    }
+                }
+            }, 100);
+            resizeSeekerbarInterval = Meteor.setInterval(function () {
+                resizeSeekerbar();
+            }, 500);
+        }
+    });
+});
 // Settings Template
 Template.settings.events({
     "click #save-settings": function() {
@@ -948,4 +1705,4 @@ Template.settings.events({
     }
 });
 
-var previewEndSongTimeout = undefined;
+var previewEndSongTimeout = undefined;

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

@@ -128,20 +128,6 @@ Router.route("/admin/alerts", {
     }
 });
 
-Router.route("/admin/news", {
-    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")) {
-            this.render("mnews");
-        } else {
-            this.redirect("/");
-        }
-    }
-});
-
 Router.route("/u/:user", function() {
     this.render("profile");
 });

+ 0 - 4
app/client/stylesheets/app.css

@@ -9,10 +9,6 @@ main {
     flex: 1 0 auto;
 }
 
-main h3{
-    margin-left: 10px;
-}
-
 main h4.thin{
     margin-left: 10px;
 }

+ 8 - 5
app/client/templates/admin.html

@@ -53,7 +53,6 @@
                 </div>
                 <div class="row">
                     <a class="btn col l12 s12 m12 waves-effect waves-light" href="/admin/queues">Manage Queues</a> <!-- TODO Make this redirect to the queues -->
-                    <a class="btn col l12 s12 m12 waves-effect waves-light" href="/admin/news">Manage News</a>
                 </div>
             </div>
         </div>
@@ -64,14 +63,18 @@
                     <h4>Add Room</h4>
                     <div class="input-field">
                         <input type="text" class="croom" id="croom_display" name="croom" required/>
-                        <label for="croom_display" class="white-text">Room Display Name</label>
+                        <label for="croom_display" class="black-text">Room Display Name</label>
                     </div>
                     <div class="input-field">
                         <input type="text" class="croom" id="croom_tag" name="croom" required/>
-                        <label for="croom_tag" class="white-text">Room Tag</label>
+                        <label for="croom_tag" class="black-text">Room Tag</label>
+                    </div>
+                    <div class="input-field">
+                        <input type="text" class="croom" id="croom_desc" name="croom" required/>
+                        <label for="croom_desc" class="black-text">Room Description</label>
                     </div>
                     <input type="checkbox" name="croom_private" id="croom_private"/>
-                    <label for="croom_private" class="white-text">Make Room Private?</label>
+                    <label for="croom_private" class="black-text">Make Room Private?</label>
                     <div class="section">
                         <button class="btn btn-warning btn-block waves-effect waves-light" id="croom_create">Create</button>
                     </div>
@@ -122,7 +125,7 @@
                     <a id="submit_desc" class="waves-effect waves-light btn">Submit</a>
                 </div>
                 <div class="modal-footer">
-                    <button id="close-modal" type="button" class="btn btn-default waves-effect waves-light" data-dismiss="modal">Close</button>
+                    <a href="#!" class=" modal-action modal-close waves-effect waves-light btn-flat">Close</a>
                 </div>
             </div>
         </div>

+ 1 - 1
app/client/templates/faq.html

@@ -1,5 +1,4 @@
 <template name="faq">
-    {{> alerts}}
     {{> header}}
     <div class="text-center">
         <h3>FAQ
@@ -37,4 +36,5 @@
         <p class="flow-text">Yes! Just type /commands or /help in chat and it will show you all of the available
             chat commands.</p>
     </div>
+    {{> footer}}
 </template>

+ 3 - 1
app/client/templates/feedback.html

@@ -1,9 +1,11 @@
 <template name="feedback">
     {{> header}}
     <main>
-        <h3 class="black-text thin text-center">Feedback</h3>
+        <div class="center-align">
+        <h3 class="black-text thin">Feedback</h3>
         <a class="waves-effect waves-light btn modal-trigger feedback-btn" href="#modal1">Send New Feedback</a>
         <a id="editModal" class="modal-trigger" href="#editFeedback" style="display:none"></a>
+        </div>
 
         <div class="row">
             {{#each feedback}}

+ 6 - 0
app/client/templates/header.html

@@ -26,6 +26,9 @@
                 <a href="/" class="brand-logo light">Musare</a>
                 <a href="#" data-activates="mobile-navi" class="button-collapse"><i class="material-icons">menu</i></a>
                 <ul class="right hide-on-med-and-down scroll-fix">
+                  {{#if isModerator}}
+                    <li><a  class="orange-text" href="/admin"><b>Admin</b></a></li>
+                  {{/if}}
                     <li><a href="/news">News</a></li>
                     <li><a class="dropdown-button" href="#!" data-activates="contributeDrop">Contribute<i
                             class="material-icons right">arrow_drop_down</i></a></li>
@@ -41,6 +44,9 @@
                 </ul>
                 <ul class="side-nav" id="mobile-navi" style="width: 240px;">
                     <ul class="collapsible" data-collapsible="accordion">
+                      {{#if isModerator}}
+                        <li><a href="/admin">Admin</a></li>
+                      {{/if}}
                         <li>
                             <a href="/news">News</a>
                         </li>

+ 0 - 42
app/client/templates/mnews.html

@@ -1,42 +0,0 @@
-<template name="mnews">
-    <div class="landing">
-        {{> header}}
-        <div class="row">
-            <div class="about col-md-8 col-md-offset-2">
-                <h1 class="center-align">Add A New Article:</h1>
-                <div class="row">
-                    <form class="col s12">
-                        <div class="row">
-                            <div class="input-field col s6">
-                                <input id="input_text" type="text" length="10">
-                                <label for="input_text">Article Title:</label>
-                            </div>
-                        </div>
-                        <div class="row">
-                            <div class="input-field col s12">
-                                <textarea id="textarea1" class="materialize-textarea" length="120"></textarea>
-                                <label for="textarea1">Article Content:</label>
-                            </div>
-                        </div>
-                        <div class="switch">
-                          <p>Post As "Musare Admin"</p>
-                            <label>
-                                No
-                                <input type="checkbox">
-                                <span class="lever"></span>
-                                Yes
-                            </label>
-                        </div>
-                        <div class="row">
-                            <div class="input-field col s12">
-                                <a class="btn-floating btn-large waves-effect waves-light right red"><i class="material-icons">add</i></a>
-                            </div>
-                        </div>
-                    </form>
-                </div>
-                <hr />
-                <h1 class="center-align">Article List:</h1>
-            </div>
-        </div>
-    </div>
-</template>

+ 40 - 0
app/client/templates/news.html

@@ -18,5 +18,45 @@
                 </div>
             {{/each}}
     </main>
+    <div class="fixed-action-btn" style="bottom: 45px; right: 24px;">
+        <a class="btn-floating btn-large red modal-trigger" href="#createArticle"><i class="large material-icons">add</i></a>
+    </div>
+    <div id="createArticle" class="modal">
+        <div class="modal-content musare white-text">
+            <h4 class="center-align">Create Article</h4>
+            <div class="row">
+                <div class="input-field col l8 m8 s12 offset-l2 offset-m2">
+                    <label for="title" class="white-text">Title</label>
+                    <input class="validate" name="title" id="title" type="text"/>
+                </div>
+                <div class="input-field col l8 m8 s12 offset-l2 offset-m2">
+                    <textarea class="materialize-textarea validate" name="content" id="content" type="text"></textarea>
+                    <label for="content" class="white-text">Content</label>
+                </div>
+                <div class="col l8 m8 s12 offset-l2 offset-m2">
+                    <div class="switch">
+                        <label class="white-text">
+                            Post as myself
+                            <input id="anonymous" type="checkbox">
+                            <span class="lever"></span>
+                            Post anonymous
+                        </label>
+                    </div>
+                </div>
+            </div>
+            <div class="row">
+                <button type="button" id="createArticleButton" class="btn btn-large col l6 m6 s10 offset-l3 offset-m3 offset-s1 waves-effect waves-light">Create Article</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>
+    <script>
+        $(document).ready(function(){
+            // the "href" attribute of .modal-trigger must specify the modal ID that wants to be triggered
+            $('.modal-trigger').leanModal();
+        });
+    </script>
     {{> footer}}
 </template>

+ 1 - 1
app/client/templates/profile.html

@@ -3,7 +3,7 @@
     {{> header}}
     {{#if loaded}}
         <!--{{> avatar userId=profileUserId shape="circle" class="profile-img" initials=initials}}-->
-        <h1 id="profile-name" class="black-text thin">{{username}}</h1>
+        <h1 id="profile-name" class="center-align black-text thin">{{username}}</h1>
         <div class="row">
             <div class="col s12 m6 l4">
                 <div class="card blue-grey darken-1 profile-card">

+ 44 - 31
app/client/templates/room.html

@@ -1,40 +1,53 @@
 <template name="room">
     {{> alerts}}
     {{#if loaded}}
-      <header>
-        <nav>
-          <div class="nav-wrapper teal accent-4">
-            <ul class="left hide-on-med-and-down">
-              <li><a href="/"><i class="material-icons">home</i></a></li>
-              <li><a href="#add_song_modal"><i class="material-icons">playlist_add</i></a></li>
-              <li><a href="#bug_report_modal"><i class="material-icons">bug_report</i></a></li>
-              <li><a href="#vote_to_skip" id="skip_vote"><i class="material-icons">skip_next</i></a></li>
-            </ul>
-            <ul class="right hide-on-med-and-down">
-              <li><a href="#"><i class="material-icons">queue_music</i></a></li>
-              <li><a href="#"><i class="material-icons">chat</i></a></li>
-            </ul>
-          </div>
-        </nav>
-      </header>
+        <header>
+            <nav>
+                <div class="nav-wrapper teal accent-4">
+                    <ul class="left hide-on-med-and-down">
+                        <li><a href="/"><i class="material-icons">home</i></a></li>
+                        <li><a href="#add_song_modal"><i class="material-icons">playlist_add</i></a></li>
+                        <li><a href="#bug_report_modal"><i class="material-icons">bug_report</i></a></li>
+                        <li><a href="#vote_to_skip" id="skip_vote"><i class="material-icons">skip_next</i></a></li>
+                    </ul>
+                    <span class="brand-logo center">{{type}}</span>
+                    <ul class="right hide-on-med-and-down">
+                        <li><a href="#"><i class="material-icons">queue_music</i></a></li>
+                        <li><a href="#"><i class="material-icons">chat</i></a></li>
+                    </ul>
+                </div>
+            </nav>
+        </header>
 
-      <main>
-        <div class="container">
-          <div class="row">
-            <div class="col s12 m10 l8 offset-l2 offset-m1" id="media-container">
-              <div class="video-container">
-                <div id="player"></div>
-              </div>
-              <div class="media-info-container">
+        <main>
+            <div class="container">
                 <div class="row">
-                  <div class="s4">
-                    Hello
-                  </div>
+                    <div class="col s12 m10 l8 offset-l2 offset-m1" id="media-container">
+                        <div class="video-container">
+                            <div id="player"></div>
+                        </div>
+                    </div>
+                    <div class="col s12 m10 l8 offset-l2 offset-m1">
+                        <div class="row">
+                            <div class="col s12 m12 l8">
+                                <h3>{{{title}}} - {{{artist}}}</h3>
+                                <h4 id="time-display"><span id="time-elapsed"></span> / <span id="time-total"></span></h4>
+                                <div class="row">
+                                    <form action="#" class="col s4 m4 l4">
+                                        <p class="range-field" style="margin-top: 0">
+                                            <input type="range" id="volume_slider" min="0" max="100" />
+                                        </p>
+                                    </form>
+                                </div>
+                                <div class="seeker-bar-container white" id="preview-progress">
+                                    <div class="seeker-bar teal" style="width: 0%"></div>
+                                </div>
+                            </div>
+                            <img alt="Not loading" class="song-img col s12 m12 l4" onError="this.src='http://static.boredpanda.com/blog/wp-content/uploads/2014/04/amazing-fox-photos-182.jpg'" id="song-img"/>
+                        </div>
+                    </div>
                 </div>
-              </div>
             </div>
-          </div>
-        </div>
-      </main>
+        </main>
     {{/if}}
 </template>

+ 3 - 2
app/server/server.js

@@ -943,18 +943,19 @@ Meteor.methods({
     createArticle: function(data) {
         if (!isBanned() && isModerator()) {
             var userId = Meteor.userId();
-            var requiredProperties = ["title", "content", "author"];
+            var requiredProperties = ["title", "content", "anonymous"];
             if (data !== undefined && Object.keys(data).length === requiredProperties.length) {
                 for (var property in requiredProperties) {
                     if (data[requiredProperties[property]] === undefined) {
                         throw new Meteor.Error(403, "Invalid data.");
                     }
                 }
-                if (data.author === true) {
+                if (data.anonymous === false) {
                     data.author = Meteor.user().profile.username
                 } else {
                     data.author = "A Musare Admin";
                 }
+                delete data.anonymous;
                 data.time =  new Date();
                 News.insert(data, function(err, res) {
                     if (err) {