Added more events

This commit is contained in:
Chris Blanchard 2016-01-02 21:32:26 +00:00
parent 7c45f9cf17
commit c37b70721c
10 changed files with 326 additions and 88 deletions

View file

@ -7,7 +7,7 @@ const pubsub = require(path.join(__dirname, "../../lib/event/pubsub.js"));
const winston = require("winston"); const winston = require("winston");
const eventSchema = new Schema({ const eventSchema = new Schema({
type: { type: String, required: true }, eventType: { type: String, required: true },
description: { type: String }, description: { type: String },
meta: { type: Schema.Types.Mixed }, meta: { type: Schema.Types.Mixed },
public: { type: Boolean, default: false }, public: { type: Boolean, default: false },
@ -15,7 +15,7 @@ const eventSchema = new Schema({
}); });
eventSchema.index({ createdAt: -1 }); eventSchema.index({ createdAt: -1 });
eventSchema.index({ type: 1 }); eventSchema.index({ eventType: 1 });
eventSchema.post("save", event => { eventSchema.post("save", event => {
pubsub.emit("newEvent", event); pubsub.emit("newEvent", event);
@ -24,7 +24,7 @@ eventSchema.post("save", event => {
eventSchema.statics.joiner = function (user) { eventSchema.statics.joiner = function (user) {
winston.info("Gather Joiner", JSON.stringify(user)); winston.info("Gather Joiner", JSON.stringify(user));
this.create({ this.create({
type: "gather:joiner", eventType: "gather:joiner",
description: `${user.username} joined the gather`, description: `${user.username} joined the gather`,
public: true public: true
}); });
@ -33,10 +33,69 @@ eventSchema.statics.joiner = function (user) {
eventSchema.statics.leaver = function (user) { eventSchema.statics.leaver = function (user) {
winston.info("Gather Leaver", JSON.stringify(user)); winston.info("Gather Leaver", JSON.stringify(user));
this.create({ this.create({
type: "gather:leaver", eventType: "gather:leaver",
description: `${user.username} left the gather`, description: `${user.username} left the gather`,
public: true 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); module.exports = mongoose.model('Event', eventSchema);

View file

@ -149,9 +149,7 @@ module.exports = function (namespace) {
gather.confirmSelection(socket._user); gather.confirmSelection(socket._user);
} }
winston.info("Selection Data", Event.playerSelected(socket._user, data, gather);
JSON.stringify(socket._user),
JSON.stringify(data));
refreshGather(); refreshGather();
}); });
@ -164,24 +162,23 @@ module.exports = function (namespace) {
let gather = Gather.current; let gather = Gather.current;
if (data.leader) { if (data.leader) {
gather.selectLeader(socket._user, data.leader.candidate); gather.selectLeader(socket._user, data.leader.candidate);
Event.leaderVote(socket._user, data, gather);
} }
if (data.map) { if (data.map) {
gather.toggleMapVote(socket._user, data.map.id); gather.toggleMapVote(socket._user, data.map.id);
Event.mapVote(socket._user, data, gather, Map.list);
} }
if (data.server) { 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")) { if (typeof data.regather === 'boolean' && gather.can("regather")) {
gather.regather(socket._user, data.regather); gather.regather(socket._user, data.regather);
} }
winston.info("Vote Data",
JSON.stringify(socket._user),
JSON.stringify(data));
refreshGather(); refreshGather();
}); });
@ -189,6 +186,7 @@ module.exports = function (namespace) {
if (socket._user.isGatherAdmin()) { if (socket._user.isGatherAdmin()) {
Gather.reset(); Gather.reset();
refreshGather(); refreshGather();
Event.adminRegather(socket._user);
} }
}); });

View file

@ -11,8 +11,8 @@
* *
*/ */
var Gatherer = require("./gatherer"); const Gatherer = require("./gatherer");
var StateMachine = require("javascript-state-machine"); const StateMachine = require("javascript-state-machine");
function Gather (options) { function Gather (options) {
if (!(this instanceof Gather)) { if (!(this instanceof Gather)) {

View file

@ -11,28 +11,16 @@ const Events = React.createClass({
let events; let events;
if (this.props.events.length) { if (this.props.events.length) {
events = this.props.events.map(event => { events = this.props.events.map(event => {
return ( return `${this.getTime(event.createdAt)} ${event.description}`;
<tr key={event._id}> }).join("\n");
<td className="col-xs-2">{this.getTime(event.createdAt)}</td>
<td className="col-xs-10">{event.description}</td>
</tr>
);
});
} else { } else {
events = <tr><td>Listening for new events...</td></tr> events = <tr><td>Listening for new events...</td></tr>
} }
return ( return (
<div className="panel panel-primary"> <pre className="events-panel">
<div className="panel-heading">
Recent Events
</div>
<table className="table table-condensed">
<tbody>
{events} {events}
</tbody> </pre>
</table>
</div>
); );
} }
}); });

View file

@ -3,14 +3,20 @@
var App = React.createClass({ var App = React.createClass({
getInitialState() { getInitialState() {
let updateTitle = true; let updateTitle = true;
let showEventsPanel = true;
if (storageAvailable('localStorage') && if (storageAvailable('localStorage')) {
localStorage.getItem("updateTitle") !== null) { if (localStorage.getItem("updateTitle") !== null) {
updateTitle = JSON.parse(localStorage.getItem("updateTitle")); updateTitle = JSON.parse(localStorage.getItem("updateTitle"));
} }
if (localStorage.getItem("showEventsPanel") !== null) {
showEventsPanel = JSON.parse(localStorage.getItem("showEventsPanel"));
}
}
return { return {
updateTitle: updateTitle, updateTitle: updateTitle,
showEventsPanel: showEventsPanel,
events: [] events: []
}; };
}, },
@ -40,11 +46,17 @@ var App = React.createClass({
document.title = "NSL Gathers"; document.title = "NSL Gathers";
}, },
toggleEventsPanel(event) {
let newState = event.target.checked;
this.setState({ showEventsPanel: newState });
if (storageAvailable('localStorage')) {
localStorage.setItem("showEventsPanel", newState)
}
},
toggleUpdateTitle(event) { toggleUpdateTitle(event) {
let newState = event.target.checked; let newState = event.target.checked;
this.setState({ this.setState({ updateTitle: newState });
updateTitle: newState
});
if (storageAvailable('localStorage')) { if (storageAvailable('localStorage')) {
localStorage.setItem("updateTitle", newState) localStorage.setItem("updateTitle", newState)
} }
@ -85,7 +97,6 @@ var App = React.createClass({
}); });
socket.on('event:append', data => { socket.on('event:append', data => {
console.log(data)
let events = self.state.events; let events = self.state.events;
events.unshift(data); events.unshift(data);
self.setState({ self.setState({
@ -138,6 +149,11 @@ var App = React.createClass({
}, },
render() { render() {
let eventsPanel;
if (this.state.showEventsPanel) {
eventsPanel = <Events events={this.state.events} />;
}
return <div id="wrapper"> return <div id="wrapper">
<nav className="navbar navbar-default navbar-static-top" <nav className="navbar navbar-default navbar-static-top"
role="navigation" role="navigation"
@ -184,6 +200,8 @@ var App = React.createClass({
</nav> </nav>
<AdminPanel /> <AdminPanel />
<SettingsPanel <SettingsPanel
toggleEventsPanel={this.toggleEventsPanel}
showEventsPanel={this.state.showEventsPanel}
toggleUpdateTitle={this.toggleUpdateTitle} toggleUpdateTitle={this.toggleUpdateTitle}
updateTitle={this.state.updateTitle} /> updateTitle={this.state.updateTitle} />
<TeamSpeakModal /> <TeamSpeakModal />
@ -200,8 +218,6 @@ var App = React.createClass({
<Chatroom <Chatroom
messages={this.props.messages} messages={this.props.messages}
user={this.props.user} /> user={this.props.user} />
<Events
events={this.state.events} />
</div> </div>
<div className="col-md-6" id="gathers"> <div className="col-md-6" id="gathers">
<Gather <Gather
@ -216,6 +232,8 @@ var App = React.createClass({
<ArchivedGathers archive={this.props.archive} <ArchivedGathers archive={this.props.archive}
maps={this.props.maps} maps={this.props.maps}
servers={this.props.servers} /> servers={this.props.servers} />
<hr />
{eventsPanel}
</div> </div>
</div> </div>
</div> </div>

View file

@ -13,7 +13,7 @@ var SettingsPanel = React.createClass({
</button> </button>
<h4 className="modal-title">Settings</h4> <h4 className="modal-title">Settings</h4>
</div> </div>
<div className="modal-body" id="admin-menu"> <div className="modal-body">
<div className="checkbox"> <div className="checkbox">
<label className="checkbox-inline"> <label className="checkbox-inline">
<input type="checkbox" <input type="checkbox"
@ -21,6 +21,15 @@ var SettingsPanel = React.createClass({
checked={this.props.updateTitle}/> Update Gather Status in Title (Cabooble Mode) - May require refresh checked={this.props.updateTitle}/> Update Gather Status in Title (Cabooble Mode) - May require refresh
</label> </label>
</div> </div>
</div>
<div className="modal-body">
<div className="checkbox">
<label className="checkbox-inline">
<input type="checkbox"
onChange={this.props.toggleEventsPanel}
checked={this.props.showEventsPanel}/> Show events panel
</label>
</div>
</div> </div>
<div className="modal-footer"> <div className="modal-footer">
<button type="button" className="btn btn-default" <button type="button" className="btn btn-default"
@ -31,4 +40,4 @@ var SettingsPanel = React.createClass({
</div> </div>
); );
} }
}); });

View file

@ -202,3 +202,14 @@ html, body {
.music-select { .music-select {
padding: 0 15px; padding: 0 15px;
} }
/* Events */
.events-panel {
max-height: 150px;
background-color: #002b36;
border: 1px solid transparent;
color: #839496;
border-color: #428bca;
border-radius: 4px;
}

View file

@ -2,6 +2,11 @@
const helper = require("./helpers/index.js"); const helper = require("./helpers/index.js");
const Event = helper.Event; 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 assert = require("chai").assert;
const async = require("async"); const async = require("async");
const pubsub = helper.eventPubSub; const pubsub = helper.eventPubSub;
@ -15,10 +20,153 @@ describe("Event Model", () => {
helper.clearDb(done); 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", () => { describe(".create", () => {
it ("creates a new event", done => { it ("creates a new event", done => {
const event = { let event = {
type: "event", eventType: "event",
description: "An event occurred", description: "An event occurred",
meta: { meta: {
foo: "bar" foo: "bar"
@ -26,7 +174,7 @@ describe("Event Model", () => {
}; };
Event.create(event, (error, result) => { Event.create(event, (error, result) => {
if (error) return done(error); 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.equal(result.description, event.description); assert.equal(result.description, event.description);
assert.isDefined(result.createdAt); assert.isDefined(result.createdAt);
@ -34,8 +182,8 @@ describe("Event Model", () => {
}); });
}); });
it ("emits an event when an event is created", done => { it ("emits an event when an event is created", done => {
const event = { let event = {
type: "event", eventType: "event",
description: "An event occurred", description: "An event occurred",
meta: { meta: {
foo: "bar" foo: "bar"
@ -45,7 +193,7 @@ describe("Event Model", () => {
if (error) return done(error); if (error) return done(error);
}); });
pubsub.once("newEvent", newEvent => { 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.equal(newEvent.description, event.description); assert.equal(newEvent.description, event.description);
assert.isDefined(newEvent.createdAt); assert.isDefined(newEvent.createdAt);

View file

@ -12,8 +12,9 @@ describe("Gather Model:", function () {
beforeEach(function () { beforeEach(function () {
user = helper.createUser(); user = helper.createUser();
gatherers = []; gatherers = [];
for (var i = 0; i < 12; i++) for (var i = 0; i < 12; i++) {
gatherers.push(helper.createUser()); gatherers.push(helper.createUser());
}
gather = Gather(); gather = Gather();
}); });

View file

@ -1,32 +1,38 @@
"use strict"; "use strict";
var fs = require("fs"); const fs = require("fs");
var path = require("path"); const path = require("path");
var extend = require("extend"); const extend = require("extend");
const winston = require("winston");
winston.remove(winston.transports.Console);
var helpers = {} 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.server = require(path.join(__dirname, "../../index.js"));
helpers.app = helpers.server.app; helpers.app = helpers.server.app;
// Models // Models
var User = helpers.User = require(path.join(__dirname, "../../lib/user/user")); const User = helpers.User = require(path.join(__dirname, "../../lib/user/user"));
var Gather = helpers.Gather = require(path.join(__dirname, "../../lib/gather/gather")); const Gather = helpers.Gather = require(path.join(__dirname, "../../lib/gather/gather"));
var Gatherer = helpers.Gatherer = require(path.join(__dirname, "../../lib/gather/gatherer")); const Gatherer = helpers.Gatherer = require(path.join(__dirname, "../../lib/gather/gatherer"));
// ENSL Client // ENSL Client
var EnslClient = helpers.EnslClient = require(path.join(__dirname, "../../lib/ensl/client")); const EnslClient = helpers.EnslClient = require(path.join(__dirname, "../../lib/ensl/client"));
var HiveClient = helpers.HiveClient = require(path.join(__dirname, "../../lib/hive/client")); const HiveClient = helpers.HiveClient = require(path.join(__dirname, "../../lib/hive/client"));
// Mongo & Associated Models // Mongo & Associated Models
var db = require(path.join(__dirname, "../../db/index")); const db = require(path.join(__dirname, "../../db/index"));
var mongoose = require("mongoose"); const mongoose = require("mongoose");
var Message = helpers.Message = mongoose.model("Message"); const Message = helpers.Message = mongoose.model("Message");
var Session = helpers.Session = mongoose.model("Session"); const Session = helpers.Session = mongoose.model("Session");
var Profile = helpers.Profile = mongoose.model("Profile"); const Profile = helpers.Profile = mongoose.model("Profile");
var Event = helpers.Event = mongoose.model("Event"); const Event = helpers.Event = mongoose.model("Event");
var ArchivedGather = helpers.ArchivedGather = mongoose.model("ArchivedGather"); const ArchivedGather = helpers.ArchivedGather = mongoose.model("ArchivedGather");
// Pubsub // Pubsub
const eventPubSub = helpers.eventPubSub = require(path.join(__dirname, "../../lib/event/pubsub.js")); const eventPubSub = helpers.eventPubSub = require(path.join(__dirname, "../../lib/event/pubsub.js"));