diff --git a/server/handlers/io.js b/server/handlers/io.js
index 5432031d..e42efc82 100644
--- a/server/handlers/io.js
+++ b/server/handlers/io.js
@@ -190,6 +190,17 @@ module.exports = function() {
Suggestions.description(msg, coll, guid, offline, socket);
});
+ socket.on('suggest_rules', function(msg){
+ if(msg.hasOwnProperty("channel") && msg.channel.indexOf("?") > -1){
+ var _list = msg.channel.substring(0, msg.channel.indexOf("?"));
+ msg.channel = _list;
+ }
+ if(msg.hasOwnProperty("channel")) {
+ msg.channel = Functions.encodeChannelName(msg.channel);
+ }
+ Suggestions.rules(msg, coll, guid, offline, socket);
+ });
+
socket.on("namechange", function(msg) {
if(msg.hasOwnProperty("channel") && msg.channel.indexOf("?") > -1){
var _list = msg.channel.substring(0, msg.channel.indexOf("?"));
diff --git a/server/handlers/suggestions.js b/server/handlers/suggestions.js
index b4ec133b..180165f3 100644
--- a/server/handlers/suggestions.js
+++ b/server/handlers/suggestions.js
@@ -120,5 +120,64 @@ function description(msg, coll, guid, offline, socket) {
}
}
+
+function rules(msg, coll, guid, offline, socket) {
+ if(msg.rules && msg.channel && msg.rules.length < 250){
+ if(typeof(msg.channel) != "string" || typeof(msg.rules) != "string") {
+ var result = {
+ channel: {
+ expected: "string",
+ got: msg.hasOwnProperty("channel") ? typeof(msg.channel) : undefined,
+ },
+ pass: {
+ expected: "string",
+ got: msg.hasOwnProperty("pass") ? typeof(msg.pass) : undefined,
+ },
+ rules: {
+ expected: "string",
+ got: msg.hasOwnProperty("rules") ? typeof(msg.rules) : undefined,
+ },
+ adminpass: {
+ expected: "string",
+ got: msg.hasOwnProperty("adminpass") ? typeof(msg.adminpass) : undefined,
+ },
+ };
+ socket.emit("update_required", result);
+ return;
+ }
+ //coll = coll.replace(/ /g,'');
+ Functions.getSessionAdminUser(Functions.getSession(socket), coll, function(userpass, adminpass, gotten) {
+ if(userpass != "" || msg.pass == undefined) {
+ msg.pass = userpass;
+ } else if(msg.hasOwnProperty("pass")) {
+ msg.pass = crypto.createHash('sha256').update(Functions.decrypt_string(msg.pass)).digest("base64");
+ }
+ if(adminpass != "" || msg.adminpass == undefined) {
+ msg.adminpass = Functions.hash_pass(adminpass);
+ } else {
+ msg.adminpass = Functions.hash_pass(Functions.hash_pass(Functions.decrypt_string(msg.adminpass), true));
+ }
+ var channel = msg.channel.toLowerCase();
+ var hash = msg.adminpass;
+ db.collection(channel + "_settings").find({id: "config"}, function(err, docs){
+ if(docs.length > 0 && (docs[0].userpass == undefined || docs[0].userpass == "" || (msg.hasOwnProperty('pass') && docs[0].userpass == msg.pass))) {
+ if(docs !== null && docs.length !== 0 && docs[0].adminpass !== "" && docs[0].adminpass == hash){
+ db.collection("suggested_rules").update({channel: channel}, {$set:{rules: msg.rules}}, {upsert:true}, function(err, docs){
+ Notifications.requested_change("rules", msg.rules, channel);
+ socket.emit("toast", "suggested_rules");
+ });
+ }
+ } else {
+ socket.emit("auth_required");
+ }
+ });
+ });
+ } else {
+ socket.emit("toast", "rules_denied");
+ }
+}
+
+
module.exports.thumbnail = thumbnail;
module.exports.description = description;
+module.exports.rules = rules;
diff --git a/server/public/assets/admin/authenticated/js/main.js b/server/public/assets/admin/authenticated/js/main.js
index 8b0f8efb..9cf37bfe 100644
--- a/server/public/assets/admin/authenticated/js/main.js
+++ b/server/public/assets/admin/authenticated/js/main.js
@@ -12,7 +12,14 @@ function toast(text, length, classes) {
}
window.addEventListener("DOMContentLoaded", function() {
- M.Tabs.init(document.querySelector("ul.tabs"));
+ M.Tabs.init(document.querySelector(".tabs_admin"), {
+ onShow: function() {
+ if(this.index == 2) {
+ M.Tabs.getInstance(document.querySelector(".tabs_admin_info")).updateTabIndicator();
+ }
+ }
+ });
+ M.Tabs.init(document.querySelector(".tabs_admin_info"));
api_token_list = document.querySelector("#api_token_list").cloneNode(true);
document.querySelector("#api_token_list").remove();
loaded();
@@ -207,6 +214,7 @@ addListener("click", ".approve_thumbnails", function(event) {
that.parentElement.remove();
var length = parseInt(document.querySelector(".thumbnails-badge").innerText);
length = length - 1;
+ increaseInfo(-1);
document.querySelector(".thumbnails-badge").innerText = length;
if(length <= 0){
addClass(".thumbnails-badge", "hide");
@@ -244,6 +252,7 @@ addListener("click", ".deny_thumbnails", function(event) {
that.parentElement.remove();
var length = parseInt(document.querySelector(".thumbnails-badge").innerText);
length = length - 1;
+ increaseInfo(-1);
document.querySelector(".thumbnails-badge").innerText = length;
if(length <= 0){
addClass(".thumbnails-badge", "hide");
@@ -279,6 +288,7 @@ addListener("click", ".approve_descriptions", function(event) {
that.parentElement.remove();
var length = parseInt(document.querySelector(".descriptions-badge").innerText);
length = length - 1;
+ increaseInfo(-1);
document.querySelector(".descriptions-badge").innerText = length;
if(length <= 0){
addClass(".descriptions-badge", "hide");
@@ -314,6 +324,7 @@ addListener("click", ".deny_descriptions", function(event) {
that.parentElement.remove();
var length = parseInt(document.querySelector(".descriptions-badge").innerText);
length = length - 1;
+ increaseInfo(-1);
document.querySelector(".descriptions-badge").innerText = length;
if(length <= 0){
addClass(".descriptions-badge", "hide");
@@ -326,6 +337,78 @@ addListener("click", ".deny_descriptions", function(event) {
});
});
+addListener("click", ".approve_rules", function(event) {
+ this.preventDefault();
+ var that = event;
+ var channel = that.getAttribute("data-channel");
+ if(!channel) {
+ toast("Something went wrong...", 2000, "red lighten");
+ return;
+ }
+
+ ajax({
+ type: "POST",
+ url: "/api/approve_rules",
+ data: {
+ channel: channel
+ },
+ headers: {
+ "Content-Type": "application/json"
+ },
+ success: function(response){
+ if(response){
+ that.parentElement.remove();
+ var length = parseInt(document.querySelector(".rules-badge").innerText);
+ length = length - 1;
+ increaseInfo(-1);
+ document.querySelector(".rules-badge").innerText = length;
+ if(length <= 0){
+ addClass(".rules-badge", "hide");
+ }
+ toast("Approved rules!", 2000, "green lighten");
+ } else {
+ toast("Something went wrong...", 2000, "red lighten");
+ }
+ }
+ });
+});
+
+addListener("click", ".deny_rules", function(event) {
+ this.preventDefault();
+ var that = event;
+ var channel = that.getAttribute("data-channel");
+ if(!channel) {
+ toast("Something went wrong...", 2000, "red lighten");
+ return;
+ }
+
+ ajax({
+ type: "POST",
+ url: "/api/deny_rules",
+ data: {
+ channel: channel
+ },
+ headers: {
+ "Content-Type": "application/json"
+ },
+ success: function(response){
+ if(response){
+ that.parentElement.remove();
+ var length = parseInt(document.querySelector(".rules-badge").innerText);
+ length = length - 1;
+ increaseInfo(-1);
+ document.querySelector(".rules-badge").innerText = length;
+ if(length <= 0){
+ addClass(".rules-badge", "hide");
+ }
+ toast("Denied description!", 2000, "green lighten");
+ } else {
+ toast("Something went wrong...", 2000, "red lighten");
+ }
+ }
+ });
+});
+
addListener("click", "#remove_description_button", function(event) {
this.preventDefault();
var that = event;
@@ -353,6 +436,34 @@ addListener("click", "#remove_description_button", function(event) {
});
});
+
+addListener("click", "#remove_rules_button", function(event) {
+ this.preventDefault();
+ var that = event;
+ var channel = document.querySelector("#remove_rules").value;
+ if(!channel) {
+ toast("Something went wrong...", 2000, "red lighten");
+ return;
+ }
+ ajax({
+ type: "POST",
+ url: "/api/remove_rules",
+ data: {
+ channel: channel
+ },
+ headers: {
+ "Content-Type": "application/json"
+ },
+ success: function(response){
+ if(response){
+ toast("Removed rules!", 2000, "green lighten");
+ } else {
+ toast("Something went wrong...", 2000, "red lighten");
+ }
+ }
+ });
+});
+
addListener("click", "#remove_thumbnail_button", function(event) {
this.preventDefault();
var that = event;
@@ -558,12 +669,30 @@ function add_to_tab(dest, resp){
for(var x = 0; x < resp.length; x++){
if(dest == "thumbnails"){
document.querySelector("#" + dest + "_cont").insertAdjacentHTML("beforeend", "
");
- } else {
+ } else if(dest == "descriptions"){
document.querySelector("#" + dest + "_cont").insertAdjacentHTML("beforeend", "");
+ } else {
+ resp[x].rules = resp[x].rules.replace(/\n/g, " /n\\ ");
+ document.querySelector("#" + dest + "_cont").insertAdjacentHTML("beforeend", "");
}
}
}
+function increaseInfo(num) {
+ removeClass(".info-badge", "hide");
+ try {
+ var currentNumber = parseInt(document.querySelector(".info-badge").innerText);
+ if(isNaN(currentNumber)) currentNumber = 0;
+ document.querySelector(".info-badge").innerText = currentNumber + num;
+ currentNumber += num;
+ if(currentNumber <= 0) {
+ addClass(".info-badge", "hide");
+ }
+ } catch(e) {
+ document.querySelector(".info-badge").innerText = 1;
+ }
+}
+
function loaded() {
ajax({
type: "GET",
@@ -625,6 +754,7 @@ function loaded() {
document.querySelector("#frontpage_pinned").innerHTML = output_pinned;
document.querySelector("#remove_thumbnail").innerHTML = document.querySelector("#frontpage_pinned").cloneNode(true).innerHTML;
document.querySelector("#remove_description").innerHTML = document.querySelector("#frontpage_pinned").cloneNode(true).innerHTML;
+ document.querySelector("#remove_rules").innerHTML = document.querySelector("#frontpage_pinned").cloneNode(true).innerHTML;
document.querySelector("#delete_list_name").innerHTML = document.querySelector("#frontpage_pinned").cloneNode(true).innerHTML;
document.querySelector("#delete_userpass_name").innerHTML = document.querySelector("#frontpage_pinned").cloneNode(true).innerHTML;
document.querySelector("#delete_channel_name").innerHTML = document.querySelector("#frontpage_pinned").cloneNode(true).innerHTML;
@@ -665,6 +795,7 @@ function loaded() {
if(response.length > 0){
removeClass(".thumbnails-badge", "hide");
document.querySelector(".thumbnails-badge").innerText = response.length;
+ increaseInfo(response.length);
}
add_to_tab("thumbnails", response);
}
@@ -680,10 +811,27 @@ function loaded() {
if(response.length > 0){
removeClass(".descriptions-badge", "hide");
document.querySelector(".descriptions-badge").innerText = response.length;
+ increaseInfo(response.length);
}
add_to_tab("descriptions", response);
}
});
+
+ ajax({
+ type: "GET",
+ url: "/api/rules",
+ headers: {
+ "Content-Type": "application/json"
+ },
+ success: function(response){
+ if(response.length > 0){
+ removeClass(".rules-badge", "hide");
+ document.querySelector(".rules-badge").innerText = response.length;
+ increaseInfo(response.length);
+ }
+ add_to_tab("rules", response);
+ }
+ });
}
function predicate() {
diff --git a/server/public/assets/css/style.css b/server/public/assets/css/style.css
index e1668f5d..c7f3e5f2 100755
--- a/server/public/assets/css/style.css
+++ b/server/public/assets/css/style.css
@@ -25,6 +25,10 @@ a {
outline: 0 !important;
}
+.initial-line-height {
+ line-height: initial;
+}
+
.error-code-container {
background: lightgrey;
border: 1px solid darkgrey;
@@ -1362,8 +1366,11 @@ margin:-1px;
.suggest-songs:nth-child(odd) {background: rgba(204,204,204,0.40)}
.suggest-songs:nth-child(even) {background: #FFF}
-.suggest-songs {
+.info_change_button_container, .suggest-songs {
padding-top:20px;
+}
+.suggest-songs {
+
border-bottom:1px solid black;
}
diff --git a/server/public/assets/js/admin.js b/server/public/assets/js/admin.js
index 67078217..8bc4d00e 100755
--- a/server/public/assets/js/admin.js
+++ b/server/public/assets/js/admin.js
@@ -8,7 +8,7 @@ var Admin = {
Admin.logged_in = msg;
if(!msg) return;
w_p = false;
-
+ M.Modal.init(document.getElementById("channel_info"));
if(Admin.logged_in) {
Helper.css("#thumbnail_form", "display", "inline-block");
Helper.css("#description_form", "display", "inline-block");
@@ -179,15 +179,34 @@ var Admin = {
Helper.addClass(".change_user_pass", "hide");
//Crypt.remove_userpass(chan.toLowerCase());
}
+ var updated = false;
if(conf_array.thumbnail != undefined && conf_array.thumbnail != "") {
document.getElementById("thumbnail_image").innerHTML = " ";
+ document.getElementById("thumbnail_input").value = conf_array.thumbnail;
+ updated = true;
}
if(conf_array.description != undefined && conf_array.description != "") {
document.getElementById("description_area").innerHTML = conf_array.description;
+ document.getElementById("description_input").value = conf_array.description;
+ updated = true;
}
+ if(conf_array.rules != undefined && conf_array.rules != "") {
+ var existingRules = document.querySelector(".rules-container");
+ if(existingRules) existingRules.remove();
+ var rules = conf_array.rules.split("\n");
+ var elementToAdd = "Rules ";
+ for(var i = 0; i < rules.length; i++) {
+ elementToAdd += "
" + rules[i] + "
";
+ }
+ elementToAdd += "
";
+ document.querySelector(".channel_info_container").insertAdjacentHTML("afterend", elementToAdd);
+ document.getElementById("rules_input").value = conf_array.rules;
+ updated = true;
+ }
+ if(updated) M.updateTextFields();
},
submitAdmin: function(form, userpass_changed) {
diff --git a/server/public/assets/js/functions.js b/server/public/assets/js/functions.js
index 6a2fc0a8..3c72fc5e 100644
--- a/server/public/assets/js/functions.js
+++ b/server/public/assets/js/functions.js
@@ -21,6 +21,21 @@ function removeAllListeners() {
socket.removeEventListener(id);
}
+function sendDescription() {
+ emit("suggest_description", {channel: chan, description: document.getElementById("description_input").value});
+ document.getElementById("description_input").value = "";
+}
+
+function sendThumbnail() {
+ emit("suggest_thumbnail", {channel: chan, thumbnail: document.getElementById("thumbnail_input").value});
+ document.getElementById("thumbnail_input").value = "";
+}
+
+function sendRules() {
+ emit("suggest_rules", {channel: chan, rules: document.getElementById("rules_input").value});
+ document.getElementById("rules_input").value = "";
+}
+
function resizeFunction() {
if(chan && !Helper.mobilecheck()){
if(document.querySelector("#wrapper") == null) return;
@@ -1072,6 +1087,12 @@ function toast(msg, _class) {
case "other_list_pass":
msg = "The other list has a pass, can't import the songs..";
break;
+ case "suggested_rules":
+ msg = "Your rules have been suggested";
+ break;
+ case "rules_denied":
+ msg = "Your rules will be denied";
+ break;
case "nolist":
msg = "There is no list with that name";
break;
diff --git a/server/public/assets/js/listeners.js b/server/public/assets/js/listeners.js
index 55822b22..8c22b356 100755
--- a/server/public/assets/js/listeners.js
+++ b/server/public/assets/js/listeners.js
@@ -433,6 +433,11 @@ function addDynamicListeners() {
}
});
+ addListener("click", ".info_change_button", function(event) {
+ this.preventDefault();
+ M.Modal.getInstance(document.querySelector("#channel_info")).open();
+ });
+
addListener("click", "#hide-playlist", function(event) {
this.preventDefault();
fullVideo(!hiddenPlaylist);
@@ -506,16 +511,34 @@ function addDynamicListeners() {
}
});
- addListener("submit", "#thumbnail_form", function(event){
+ addListener("click", ".description_input_send", function(event) {
this.preventDefault();
- emit("suggest_thumbnail", {channel: chan, thumbnail: document.getElementById("chan_thumbnail").value});
- document.getElementById("chan_thumbnail").value = "";
+ sendDescription();
});
- addListener("submit", "#description_form", function(event){
+ addListener("click", ".rules_input_send", function(event) {
this.preventDefault();
- emit("suggest_description", {channel: chan, description: document.getElementById("chan_description").value});
- document.getElementById("chan_description").value = "";
+ sendRules();
+ });
+
+ addListener("click", ".thumbnail_input_send", function(event) {
+ this.preventDefault();
+ sendThumbnail();
+ });
+
+ addListener("submit", "#thumbnail_input_form", function(event){
+ this.preventDefault();
+ sendThumbnail();
+ });
+
+ addListener("submit", "#description_input_form", function(event){
+ this.preventDefault();
+ sendDescription();
+ });
+
+ addListener("submit", "#rules_input_form", function(event){
+ this.preventDefault();
+ sendRules();
});
addListener("click", "#playpause-overlay", function(){
@@ -1639,8 +1662,9 @@ function addDynamicListeners() {
document.querySelector("#text-chat-input") != document.activeElement &&
document.querySelector("#password") != document.activeElement &&
document.querySelector("#user-pass-input") != document.activeElement &&
- document.querySelector("#chan_thumbnail") != document.activeElement &&
- document.querySelector("#chan_description") != document.activeElement &&
+ document.querySelector("#thumbnail_input") != document.activeElement &&
+ document.querySelector("#rules_input") != document.activeElement &&
+ document.querySelector("#description_input") != document.activeElement &&
document.querySelector("#contact-form-from") != document.activeElement &&
document.querySelector("#contact-form-message") != document.activeElement &&
document.querySelector("#remote_channel") != document.activeElement &&
diff --git a/server/public/layouts/admin/authenticated.handlebars b/server/public/layouts/admin/authenticated.handlebars
index c550b78a..4f95686a 100644
--- a/server/public/layouts/admin/authenticated.handlebars
+++ b/server/public/layouts/admin/authenticated.handlebars
@@ -11,194 +11,219 @@
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
check
-
close
+
+
+
+
+
+
+
+ Channels
+
+ Remove Thumbnail
+
+
+
+
+
+
+
+
+
+
+ Channels
+
+ Remove Description
+
+
+
+
+
+
+
+
+
+
+ Channels
+
+ Remove Rules
+
+
+
+
+
+
+
-
check
-
X
-
-
-
-
-
-
- Channels
-
- Remove Thumbnail
-
-
-
-
-
-
-
-
-
-
- Channels
-
- Remove Description
-
-
-
-
-
-
-
-
-
-
diff --git a/server/public/layouts/admin/main.handlebars b/server/public/layouts/admin/main.handlebars
index 6200a950..93fb0559 100644
--- a/server/public/layouts/admin/main.handlebars
+++ b/server/public/layouts/admin/main.handlebars
@@ -48,11 +48,11 @@
margin-right: 2px;
}
- .tabs_admin{
+ .tabs_admin, .tabs_margin{
margin-bottom:20px;
}
- .tabs_admin .indicator{
+ .tabs_admin .indicator, .tabs_admin_info .indicator{
width: initial !important;
background: black !important;
}
diff --git a/server/public/partials/channel/modal.handlebars b/server/public/partials/channel/modal.handlebars
index 2ac59855..95e53c82 100644
--- a/server/public/partials/channel/modal.handlebars
+++ b/server/public/partials/channel/modal.handlebars
@@ -53,6 +53,43 @@
Close
+
+
+
Channel Info
+
Here you can add a thumbnail for the channel, description or rules. The description and thumbnail will be visible from the frontpage, and the sidebar, but the rules will only be visible from the sidebar when in the channel.
+
Remember, all thumbnails, descriptions and rules has to be approved by a site-administrator before it will be visible to visitors.
+
+
+
+
+
+
Locked Channel
diff --git a/server/public/partials/channel/panel.handlebars b/server/public/partials/channel/panel.handlebars
index 516dea84..ce2d0467 100755
--- a/server/public/partials/channel/panel.handlebars
+++ b/server/public/partials/channel/panel.handlebars
@@ -8,22 +8,8 @@
-
diff --git a/server/routing/admin/api.js b/server/routing/admin/api.js
index 419a2029..09c3b170 100644
--- a/server/routing/admin/api.js
+++ b/server/routing/admin/api.js
@@ -43,6 +43,16 @@ router.route('/api/descriptions').get(function(req, res){
}
});
+router.route('/api/rules').get(function(req, res){
+ if(req.isAuthenticated()){
+ db.collection("suggested_rules").find(function(err, docs){
+ res.json(docs);
+ });
+ } else {
+ res.send(false);
+ }
+});
+
router.route('/api/approve_thumbnail').post(function(req, res){
if(req.isAuthenticated()){
var channel = req.body.channel;
@@ -72,6 +82,45 @@ router.route('/api/deny_thumbnail').post(function(req, res){
}
});
+
+router.route('/api/approve_rules').post(function(req, res){
+ if(req.isAuthenticated()){
+ var channel = req.body.channel;
+ db.collection("suggested_rules").find({channel: channel}, function(err, docs){
+ var rules = docs[0].rules;
+ db.collection(channel + "_settings").update({views:{$exists:true}}, {$set:{rules: rules}}, {upsert: true}, function(err, docs){
+ db.collection("suggested_rules").remove({channel: channel}, function(err, docs){
+ res.send(true);
+ });
+ });
+ });
+ } else {
+ res.send(false);
+ }
+});
+
+router.route('/api/deny_rules').post(function(req, res){
+ if(req.isAuthenticated()){
+ var channel = req.body.channel;
+ db.collection("suggested_rules").remove({channel: channel},function(err, docs){
+ res.send(true);
+ });
+ } else {
+ res.send(false);
+ }
+});
+
+router.route('/api/remove_rules').post(function(req, res){
+ if(req.isAuthenticated()){
+ var channel = req.body.channel;
+ db.collection(channel + "_settings").update({views:{$exists:true}}, {$set:{rules: ""}}, function(err, docs){
+ res.send(true);
+ });
+ } else {
+ res.send(false);
+ }
+});
+
router.route('/api/approve_description').post(function(req, res){
if(req.isAuthenticated()){
var channel = req.body.channel;