Browse Source

Allowed for the creation of News by Admins

theflametrooper 8 years ago
parent
commit
23babf8839

+ 1 - 1
backend/logic/actions/apis.js

@@ -44,7 +44,7 @@ module.exports = {
 	},
 
 	joinAdminRoom: hooks.adminRequired((session, page, cb) => {
-		if (page === 'queue' || page === 'songs' || page === 'stations' || page === 'reports') {
+		if (page === 'queue' || page === 'songs' || page === 'stations' || page === 'reports' || page === 'news') {
 			utils.socketJoinRoom(session.socketId, `admin.${page}`);
 		}
 		cb({});

+ 32 - 9
backend/logic/actions/news.js

@@ -1,6 +1,19 @@
 'use strict';
 
+const async = require('async');
+
 const db = require('../db');
+const cache = require('../cache');
+const utils = require('../utils');
+const hooks = require('./hooks');
+
+cache.sub('news.create', news => {
+	utils.socketsFromUser(news.createdBy, sockets => {
+		sockets.forEach(socket => {
+			socket.emit('event:admin.news.created', news);
+		});
+	});
+});
 
 module.exports = {
 
@@ -11,16 +24,26 @@ module.exports = {
 		});
 	},
 
+	create: hooks.adminRequired((session, data, cb, userId) => {
+		async.waterfall([
+
+			(next) => {
+				data.createdBy = userId;
+				data.createdAt = Date.now();
+				db.models.news.create(data, next);
+			}
+
+		], (err, news) => {
+			console.log(err);
+			if (err) return cb({ 'status': 'failure', 'message': 'Something went wrong' });
+			else {
+				cache.pub('news.create', news);
+				return cb({ 'status': 'success', 'message': 'Successfully created News' });
+			}
+		});
+	}),
+
 	newest: (session, cb) => {
-		// db.models.news.create({
-		// 	title: 'Beta',
-		// 	description: 'Remember to let us know in Discord if you notice anything odd!',
-		// 	upcoming: ['Private Playlists', 'Christmas Magic', 'Reports'],
-		// 	bugs: ['Mobile Responsiveness',	'Station Name Overflow'],
-		// 	improvements: ['No more Meteor Glitches!'],
-		// 	createdAt: Date.now(),
-		// 	createdBy: 'Jonathan (Musare Lead Developer)'
-		// });
 		db.models.news.findOne({}).sort({ createdAt: 'desc' }).exec((err, news) => {
 			if (err) throw err;
 			else cb({ status: 'success', data: news });

+ 1 - 1
backend/logic/actions/reports.js

@@ -131,7 +131,7 @@ module.exports = {
 			}
 
 		], (err, report) => {
-			if (err) return cb({ 'status': 'failure', 'message': 'Something went wrong'});
+			if (err) return cb({ 'status': 'failure', 'message': 'Something went wrong' });
 			else {
 				cache.pub('report.create', report);
 				return cb({ 'status': 'success', 'message': 'Successfully created report' });

+ 149 - 0
frontend/components/Admin/News.vue

@@ -0,0 +1,149 @@
+<template>
+	<div class='container'>
+		<div class='card is-fullwidth'>
+			<header class='card-header'>
+				<p class='card-header-title'>Create News</p>
+			</header>
+			<div class='card-content'>
+				<div class='content'>
+
+					<label class='label'>Title & Description</label>
+					<div class='control is-horizontal'>
+						<div class='control is-grouped'>
+							<p class='control is-expanded'>
+								<input class='input' type='text' placeholder='Title' v-model='news.title'>
+							</p>
+							<p class='control is-expanded'>
+								<input class='input' type='text' placeholder='Short description' v-model='news.description'>
+							</p>
+						</div>
+					</div>
+
+					<div class="columns">
+						<div class="column">
+							<label class='label'>Bugs</label>
+							<p class='control has-addons'>
+								<input class='input' id='new-bugs' type='text' placeholder='Bug' v-on:keyup.enter='addChange("bugs")'>
+								<a class='button is-info' href='#' @click='addChange("bugs")'>Add Bug</a>
+							</p>
+							<span class='tag is-info' v-for='(index, bug) in news.bugs' track-by='$index'>
+								{{ bug }}
+								<button class='delete is-info' @click='removeChange("bugs", index)'></button>
+							</span>
+						</div>
+						<div class="column">
+							<label class='label'>Features</label>
+							<p class='control has-addons'>
+								<input class='input' id='new-features' type='text' placeholder='Feature' v-on:keyup.enter='addChange("features")'>
+								<a class='button is-info' href='#' @click='addChange("features")'>Add Feature</a>
+							</p>
+							<span class='tag is-info' v-for='(index, feature) in news.features' track-by='$index'>
+								{{ feature }}
+								<button class='delete is-info' @click='removeChange("features", index)'></button>
+							</span>
+						</div>
+					</div>
+
+					<div class="columns">
+						<div class="column">
+							<label class='label'>Improvements</label>
+							<p class='control has-addons'>
+								<input class='input' id='new-improvements' type='text' placeholder='Improvement' v-on:keyup.enter='addChange("improvements")'>
+								<a class='button is-info' href='#' @click='addChange("improvements")'>Add Improvement</a>
+							</p>
+							<span class='tag is-info' v-for='(index, improvement) in news.improvements' track-by='$index'>
+								{{ improvement }}
+								<button class='delete is-info' @click='removeChange("improvements", index)'></button>
+							</span>
+						</div>
+						<div class="column">
+							<label class='label'>Upcoming</label>
+							<p class='control has-addons'>
+								<input class='input' id='new-upcoming' type='text' placeholder='Upcoming' v-on:keyup.enter='addChange("upcoming")'>
+								<a class='button is-info' href='#' @click='addChange("upcoming")'>Add Upcoming Change</a>
+							</p>
+							<span class='tag is-info' v-for='(index, upcoming) in news.upcoming' track-by='$index'>
+								{{ upcoming }}
+								<button class='delete is-info' @click='removeChange("upcoming", index)'></button>
+							</span>
+						</div>
+					</div>
+
+				</div>
+			</div>
+			<footer class='card-footer'>
+				<a class='card-footer-item' @click='createNews()' href='#'>Create</a>
+			</footer>
+		</div>
+	</div>
+</template>
+
+<script>
+	import { Toast } from 'vue-roaster';
+	import io from '../../io';
+
+	export default {
+		data() {
+			return {
+				news: {
+					title: '',
+					description: '',
+					bugs: [],
+					features: [],
+					improvements: [],
+					upcoming: []
+				}
+			}
+		},
+		methods: {
+			createNews: function () {
+				let _this = this;
+
+				let { news: { bugs, features, improvements, upcoming } } = this;
+
+				if (this.news.title === '') return Toast.methods.addToast('Field (Title) cannot be empty', 3000);
+				if (this.news.description === '') return Toast.methods.addToast('Field (Description) cannot be empty', 3000);
+				if (
+					bugs.length <= 0 && features.length <= 0 && 
+					improvements.length <= 0 && upcoming.length <= 0
+				) return Toast.methods.addToast('You must have at least one News Item', 3000);
+
+				_this.socket.emit('news.create', _this.news, result => {
+					Toast.methods.addToast(result.message, 4000);
+				});
+			},
+			addChange: function (type) {
+				let change = $(`#new-${type}`).val().toLowerCase().trim();
+
+				if (this.news[type].indexOf(change) !== -1) return Toast.methods.addToast(`Tag already exists`, 3000);
+
+				if (change) this.news[type].push(change);
+				else Toast.methods.addToast(`${type} cannot be empty`, 3000);
+			},
+			removeChange: function (type, index) {
+				this.news[type].splice(index, 1);
+			},
+			init: function () {
+				this.socket.emit('apis.joinAdminRoom', 'news', data => {});
+			}
+		},
+		ready: function () {
+			let _this = this;
+			io.getSocket((socket) => {
+				_this.socket = socket;
+				if (_this.socket.connected) _this.init();
+				io.onConnect(() => {
+					_this.init();
+				});
+			});
+		}
+	}
+</script>
+
+<style lang='scss' scoped>
+	.tag:not(:last-child) { margin-right: 5px; }
+
+	.is-info:focus { background-color: #0398db; }
+
+	.card-footer-item { color: #03A9F4; }
+</style>

+ 17 - 1
frontend/components/pages/Admin.vue

@@ -27,6 +27,12 @@
 						<span>&nbsp;Reports</span>
 					</a>
 				</li>
+				<li :class='{ "is-active": currentTab == "news" }' @click='showTab("news")'>
+					<a>
+						<i class="material-icons">chrome_reader_mode</i>
+						<span>&nbsp;News</span>
+					</a>
+				</li>
 			</ul>
 		</div>
 
@@ -34,6 +40,7 @@
 		<songs v-if='currentTab == "songs"'></songs>
 		<stations v-if='currentTab == "stations"'></stations>
 		<reports v-if='currentTab == "reports"'></reports>
+		<news v-if='currentTab == "news"'></news>
 	</div>
 </template>
 
@@ -45,9 +52,18 @@
 	import Songs from '../Admin/Songs.vue';
 	import Stations from '../Admin/Stations.vue';
 	import Reports from '../Admin/Reports.vue';
+	import News from '../Admin/News.vue';
 
 	export default {
-		components: { MainHeader, MainFooter, QueueSongs, Songs, Stations, Reports },
+		components: {
+			MainHeader,
+			MainFooter,
+			QueueSongs,
+			Songs,
+			Stations,
+			Reports,
+			News
+		},
 		data() {
 			return {
 				currentTab: 'queueSongs'

+ 3 - 0
frontend/components/pages/News.vue

@@ -67,6 +67,9 @@
 				_this.socket.emit('news.index', res => {
 					_this.news = res.data;
 				});
+				_this.socket.on('event:admin.news.created', news => {
+					_this.news.unshift(news);
+				});
 			});
 		}
 	}