diff --git a/db/models/event.js b/db/models/event.js index b1069e0..6966542 100644 --- a/db/models/event.js +++ b/db/models/event.js @@ -7,7 +7,7 @@ const pubsub = require(path.join(__dirname, "../../lib/event/pubsub.js")); const winston = require("winston"); const eventSchema = new Schema({ - type: { type: String, required: true }, + eventType: { type: String, required: true }, description: { type: String }, meta: { type: Schema.Types.Mixed }, public: { type: Boolean, default: false }, @@ -15,7 +15,7 @@ const eventSchema = new Schema({ }); eventSchema.index({ createdAt: -1 }); -eventSchema.index({ type: 1 }); +eventSchema.index({ eventType: 1 }); eventSchema.post("save", event => { pubsub.emit("newEvent", event); @@ -24,7 +24,7 @@ eventSchema.post("save", event => { eventSchema.statics.joiner = function (user) { winston.info("Gather Joiner", JSON.stringify(user)); this.create({ - type: "gather:joiner", + eventType: "gather:joiner", description: `${user.username} joined the gather`, public: true }); @@ -33,10 +33,69 @@ eventSchema.statics.joiner = function (user) { eventSchema.statics.leaver = function (user) { winston.info("Gather Leaver", JSON.stringify(user)); this.create({ - type: "gather:leaver", + eventType: "gather:leaver", description: `${user.username} left the gather`, public: true }); }; +eventSchema.statics.playerSelected = function (user, data, gather) { + winston.info("Selection Data", JSON.stringify(user), JSON.stringify(data)); + const gatherer = gather.getGatherer({id: data.player}); + const description = `${user.username} selected ${gatherer.user.username} into ${gatherer.team} team`; + this.create({ + eventType: "gather:select", + description: description, + public: true + }); +}; + +eventSchema.statics.leaderVote = function (user, data, gather) { + winston.info("Vote Data", JSON.stringify(user), JSON.stringify(data)); + const gatherer = gather.getGatherer({ id: data.leader.candidate }); + this.create({ + eventType: "gather:vote:leader", + description: `${user.username} voted for ${gatherer.user.username}`, + public: true + }); +}; + +eventSchema.statics.adminRegather = function (user) { + this.create({ + eventType: "gather:reset", + description: `${user.username} reset the gather`, + public: true + }); +}; + +eventSchema.statics.mapVote = function (user, data, gather, maps) { + const gatherer = gather.getGatherer(user); + if (gatherer.mapVote.some(mapId => mapId === data.map.id)) { + let map = maps.reduce((prev, curr) => { + if (curr.id === data.map.id) return curr; + return prev; + }); + this.create({ + eventType: "gather:vote:map", + description: `${user.username} voted for map ${map.name}`, + public: true + }); + } +}; + +eventSchema.statics.serverVote = function (user, data, gather, servers) { + const gatherer = gather.getGatherer(user); + if (gatherer.serverVote.some(serverId => serverId === data.server.id)) { + let server = servers.reduce((prev, curr) => { + if (curr.id === data.server.id) return curr; + return prev; + }); + this.create({ + eventType: "gather:vote:server", + description: `${user.username} voted for server ${server.name || server.description}`, + public: true + }); + } +}; + module.exports = mongoose.model('Event', eventSchema); diff --git a/lib/gather/controller.js b/lib/gather/controller.js index 6102338..3b41e50 100644 --- a/lib/gather/controller.js +++ b/lib/gather/controller.js @@ -149,9 +149,7 @@ module.exports = function (namespace) { gather.confirmSelection(socket._user); } - winston.info("Selection Data", - JSON.stringify(socket._user), - JSON.stringify(data)); + Event.playerSelected(socket._user, data, gather); refreshGather(); }); @@ -164,24 +162,23 @@ module.exports = function (namespace) { let gather = Gather.current; if (data.leader) { gather.selectLeader(socket._user, data.leader.candidate); + Event.leaderVote(socket._user, data, gather); } if (data.map) { gather.toggleMapVote(socket._user, data.map.id); + Event.mapVote(socket._user, data, gather, Map.list); } if (data.server) { - gather.toggleServerVote(socket._user, data.server.id); + gather.toggleServerVote(socket._user, data.server.id); + Event.serverVote(socket._user, data, gather, Server.list); } if (typeof data.regather === 'boolean' && gather.can("regather")) { gather.regather(socket._user, data.regather); } - winston.info("Vote Data", - JSON.stringify(socket._user), - JSON.stringify(data)); - refreshGather(); }); @@ -189,6 +186,7 @@ module.exports = function (namespace) { if (socket._user.isGatherAdmin()) { Gather.reset(); refreshGather(); + Event.adminRegather(socket._user); } }); diff --git a/lib/gather/gather.js b/lib/gather/gather.js index b0ddf5c..2b87889 100644 --- a/lib/gather/gather.js +++ b/lib/gather/gather.js @@ -11,8 +11,8 @@ * */ -var Gatherer = require("./gatherer"); -var StateMachine = require("javascript-state-machine"); +const Gatherer = require("./gatherer"); +const StateMachine = require("javascript-state-machine"); function Gather (options) { if (!(this instanceof Gather)) { diff --git a/lib/react/event.jsx b/lib/react/event.jsx index 3205ff1..fa06ff3 100644 --- a/lib/react/event.jsx +++ b/lib/react/event.jsx @@ -11,28 +11,16 @@ const Events = React.createClass({ let events; if (this.props.events.length) { events = this.props.events.map(event => { - return ( - - {this.getTime(event.createdAt)} - {event.description} - - ); - }); + return `${this.getTime(event.createdAt)} ${event.description}`; + }).join("\n"); } else { events = Listening for new events... } return ( -
-
- Recent Events -
- - - {events} - -
-
+
+				{events}
+			
); } }); diff --git a/lib/react/main.jsx b/lib/react/main.jsx index 026cee3..7237492 100644 --- a/lib/react/main.jsx +++ b/lib/react/main.jsx @@ -3,14 +3,20 @@ var App = React.createClass({ getInitialState() { let updateTitle = true; + let showEventsPanel = true; - if (storageAvailable('localStorage') && - localStorage.getItem("updateTitle") !== null) { - updateTitle = JSON.parse(localStorage.getItem("updateTitle")); + if (storageAvailable('localStorage')) { + if (localStorage.getItem("updateTitle") !== null) { + updateTitle = JSON.parse(localStorage.getItem("updateTitle")); + } + if (localStorage.getItem("showEventsPanel") !== null) { + showEventsPanel = JSON.parse(localStorage.getItem("showEventsPanel")); + } } return { updateTitle: updateTitle, + showEventsPanel: showEventsPanel, events: [] }; }, @@ -40,11 +46,17 @@ var App = React.createClass({ document.title = "NSL Gathers"; }, + toggleEventsPanel(event) { + let newState = event.target.checked; + this.setState({ showEventsPanel: newState }); + if (storageAvailable('localStorage')) { + localStorage.setItem("showEventsPanel", newState) + } + }, + toggleUpdateTitle(event) { let newState = event.target.checked; - this.setState({ - updateTitle: newState - }); + this.setState({ updateTitle: newState }); if (storageAvailable('localStorage')) { localStorage.setItem("updateTitle", newState) } @@ -85,7 +97,6 @@ var App = React.createClass({ }); socket.on('event:append', data => { - console.log(data) let events = self.state.events; events.unshift(data); self.setState({ @@ -138,6 +149,11 @@ var App = React.createClass({ }, render() { + let eventsPanel; + if (this.state.showEventsPanel) { + eventsPanel = ; + } + return
+
+ {eventsPanel}
diff --git a/lib/react/settings.jsx b/lib/react/settings.jsx index d0d0153..870b5bb 100644 --- a/lib/react/settings.jsx +++ b/lib/react/settings.jsx @@ -3,32 +3,41 @@ var SettingsPanel = React.createClass({ render() { return ( -
-
-
-
- -

Settings

-
-
-
- +
+
+
+
+ +

Settings

+
+
+
+ +
+
+
+
+ +
+
+
+
-
-
-
-
- ); - } - }); \ No newline at end of file + ); + } +}); diff --git a/public/css/app.css b/public/css/app.css index 452cf34..d7ae44e 100644 --- a/public/css/app.css +++ b/public/css/app.css @@ -202,3 +202,14 @@ html, body { .music-select { padding: 0 15px; } + +/* Events */ + +.events-panel { + max-height: 150px; + background-color: #002b36; + border: 1px solid transparent; + color: #839496; + border-color: #428bca; + border-radius: 4px; +} \ No newline at end of file diff --git a/spec/event.js b/spec/event.js index 3ecf78f..285ca9b 100644 --- a/spec/event.js +++ b/spec/event.js @@ -2,6 +2,11 @@ const helper = require("./helpers/index.js"); const Event = helper.Event; +const Gather = helper.Gather; +const Map = helper.Map; +const maps = Map.list; +const Server = helper.Server; +const servers = Server.list; const assert = require("chai").assert; const async = require("async"); const pubsub = helper.eventPubSub; @@ -15,10 +20,153 @@ describe("Event Model", () => { helper.clearDb(done); }); + describe("Event Methods", () => { + let user; + beforeEach(() => { + user = helper.createUser(); + }); + + describe(".joiner", () => { + it ("logs a joiner", done => { + pubsub.once("newEvent", event => { + assert.equal(event.eventType, "gather:joiner"); + assert.isTrue(event.public); + done(); + }); + Event.joiner(user); + }); + }); + + describe(".leaver", () => { + it ("logs a leaver", done => { + pubsub.once("newEvent", event => { + assert.equal(event.eventType, "gather:leaver"); + assert.isTrue(event.public); + done(); + }); + Event.leaver(user); + }); + }); + + describe(".adminRegather", () => { + it ("logs an admin reset of the gather", done => { + pubsub.once("newEvent", event => { + assert.equal(event.eventType, "gather:reset"); + assert.isTrue(event.public); + done(); + }); + Event.adminRegather(user); + }); + }); + + describe(".playerSelected", () => { + let gather, gatherers, marineLeader, alienLeader; + beforeEach(() => { + gatherers = []; + for (var i = 0; i < 12; i++) { + gatherers.push(helper.createUser()); + } + gather = Gather(); + helper.populateGatherAndVotes(gather, gatherers); + marineLeader = gather.marineLeader(); + alienLeader = gather.alienLeader(); + }); + it ("logs a playerSelected event", done => { + pubsub.once("newEvent", event => { + assert.equal(event.eventType, "gather:select"); + assert.isTrue(event.public); + assert.include(event.description, gather.gatherers[2].user.username); + assert.include(event.description, marineLeader.user.username); + done(); + }); + gather.moveToMarine(gather.gatherers[2], marineLeader); + Event.playerSelected(marineLeader.user, {player: gather.gatherers[2].user.id}, gather); + }); + }); + + describe(".leaderVote", () => { + let gather, gatherers; + beforeEach(() => { + gatherers = []; + gather = Gather(); + for (var i = 0; i < 12; i++) { + gatherers.push(helper.createUser()); + gather.addGatherer(gatherers[i]); + } + }); + it ("logs a leader vote event", done => { + const voter = gather.gatherers[0]; + const candidate = gather.gatherers[1]; + pubsub.once("newEvent", event => { + assert.equal(event.eventType, "gather:vote:leader"); + assert.isTrue(event.public); + assert.include(event.description, voter.user.username); + assert.include(event.description, candidate.user.username); + done(); + }); + Event.leaderVote(voter.user, { + leader: { + candidate: candidate.user.id + } + }, gather); + }); + }); + + describe(".mapVote", () => { + let gather, gatherer, map; + beforeEach(() => { + gather = Gather(); + gather.addGatherer(user); + gatherer = gather.gatherers[0]; + map = maps[0]; + gatherer.toggleMapVote(map.id); + }); + it ("logs a map vote event if map already voted", done => { + pubsub.once("newEvent", event => { + assert.equal(event.eventType, "gather:vote:map"); + assert.isTrue(event.public); + assert.include(event.description, user.username); + assert.include(event.description, map.name); + done(); + }); + Event.mapVote(user, { + map: { + id: map.id + } + }, gather, maps); + }); + }); + + describe(".serverVote", () => { + let gather, gatherer, server; + beforeEach(() => { + gather = Gather(); + gather.addGatherer(user); + gatherer = gather.gatherers[0]; + server = servers[0]; + gatherer.toggleServerVote(server.id); + }); + it ("logs a server vote event if server already voted", done => { + pubsub.once("newEvent", event => { + assert.equal(event.eventType, "gather:vote:server"); + assert.isTrue(event.public); + assert.include(event.description, user.username); + assert.include(event.description, server.description); + done(); + }); + Event.serverVote(user, { + server: { + id: server.id + } + }, gather, servers); + }); + }); + }); + describe(".create", () => { it ("creates a new event", done => { - const event = { - type: "event", + let event = { + eventType: "event", description: "An event occurred", meta: { foo: "bar" @@ -26,7 +174,7 @@ describe("Event Model", () => { }; Event.create(event, (error, result) => { if (error) return done(error); - assert.equal(result.type, event.type); + assert.equal(result.eventType, event.eventType); assert.equal(result.description, event.description); assert.equal(result.description, event.description); assert.isDefined(result.createdAt); @@ -34,8 +182,8 @@ describe("Event Model", () => { }); }); it ("emits an event when an event is created", done => { - const event = { - type: "event", + let event = { + eventType: "event", description: "An event occurred", meta: { foo: "bar" @@ -45,7 +193,7 @@ describe("Event Model", () => { if (error) return done(error); }); pubsub.once("newEvent", newEvent => { - assert.equal(newEvent.type, event.type); + assert.equal(newEvent.eventType, event.eventType); assert.equal(newEvent.description, event.description); assert.equal(newEvent.description, event.description); assert.isDefined(newEvent.createdAt); diff --git a/spec/gather.js b/spec/gather.js index 63879ef..b86a94d 100644 --- a/spec/gather.js +++ b/spec/gather.js @@ -12,8 +12,9 @@ describe("Gather Model:", function () { beforeEach(function () { user = helper.createUser(); gatherers = []; - for (var i = 0; i < 12; i++) - gatherers.push(helper.createUser()); + for (var i = 0; i < 12; i++) { + gatherers.push(helper.createUser()); + } gather = Gather(); }); diff --git a/spec/helpers/index.js b/spec/helpers/index.js index 42d0a3e..d3a4026 100644 --- a/spec/helpers/index.js +++ b/spec/helpers/index.js @@ -1,32 +1,38 @@ "use strict"; -var fs = require("fs"); -var path = require("path"); -var extend = require("extend"); +const fs = require("fs"); +const path = require("path"); +const extend = require("extend"); + +const winston = require("winston"); +winston.remove(winston.transports.Console); var helpers = {} +const Map = helpers.Map = require(path.join(__dirname, "../../lib/gather/map.js")); +const Server = helpers.Server = require(path.join(__dirname, "../../lib/gather/server.js")); + helpers.server = require(path.join(__dirname, "../../index.js")); helpers.app = helpers.server.app; // Models -var User = helpers.User = require(path.join(__dirname, "../../lib/user/user")); -var Gather = helpers.Gather = require(path.join(__dirname, "../../lib/gather/gather")); -var Gatherer = helpers.Gatherer = require(path.join(__dirname, "../../lib/gather/gatherer")); +const User = helpers.User = require(path.join(__dirname, "../../lib/user/user")); +const Gather = helpers.Gather = require(path.join(__dirname, "../../lib/gather/gather")); +const Gatherer = helpers.Gatherer = require(path.join(__dirname, "../../lib/gather/gatherer")); // ENSL Client -var EnslClient = helpers.EnslClient = require(path.join(__dirname, "../../lib/ensl/client")); -var HiveClient = helpers.HiveClient = require(path.join(__dirname, "../../lib/hive/client")); +const EnslClient = helpers.EnslClient = require(path.join(__dirname, "../../lib/ensl/client")); +const HiveClient = helpers.HiveClient = require(path.join(__dirname, "../../lib/hive/client")); // Mongo & Associated Models -var db = require(path.join(__dirname, "../../db/index")); -var mongoose = require("mongoose"); -var Message = helpers.Message = mongoose.model("Message"); -var Session = helpers.Session = mongoose.model("Session"); -var Profile = helpers.Profile = mongoose.model("Profile"); -var Event = helpers.Event = mongoose.model("Event"); -var ArchivedGather = helpers.ArchivedGather = mongoose.model("ArchivedGather"); +const db = require(path.join(__dirname, "../../db/index")); +const mongoose = require("mongoose"); +const Message = helpers.Message = mongoose.model("Message"); +const Session = helpers.Session = mongoose.model("Session"); +const Profile = helpers.Profile = mongoose.model("Profile"); +const Event = helpers.Event = mongoose.model("Event"); +const ArchivedGather = helpers.ArchivedGather = mongoose.model("ArchivedGather"); // Pubsub const eventPubSub = helpers.eventPubSub = require(path.join(__dirname, "../../lib/event/pubsub.js"));