ensl_gathers/public/js/app.js
Chris Blanchard be3eb07795 Stuff
2015-07-29 15:54:45 +01:00

895 lines
25 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use strict";
var VoteButton = React.createClass({displayName: "VoteButton",
cancelVote: function (e) {
socket.emit("gather:vote", {
leader: {
candidate: null
}
});
},
vote: function (e) {
e.preventDefault();
socket.emit("gather:vote", {
leader: {
candidate: parseInt(e.target.value, 10)
}
});
},
render: function () {
if (this.props.currentGatherer === null) {
return false;
}
if (this.props.currentGatherer.leaderVote === this.props.candidate.id) {
return (
React.createElement("button", {
onClick: this.cancelVote,
className: "btn btn-xs btn-success"}, "Voted"
)
);
} else {
return (
React.createElement("button", {
onClick: this.vote,
className: "btn btn-xs btn-default",
value: this.props.candidate.id}, "Vote"
)
);
}
}
});
var SelectPlayerButton = React.createClass({displayName: "SelectPlayerButton",
selectPlayer: function (e) {
e.preventDefault();
socket.emit("gather:select", {
player: parseInt(e.target.value, 10)
})
},
render: function () {
if (this.props.gatherer.leader) {
return (React.createElement("button", {
className: "btn btn-xs btn-default",
"data-disabled": "true"}, "Leader"));
} else {
return (React.createElement("button", {
onClick: this.selectPlayer,
value: this.props.gatherer.id,
className: "btn btn-xs btn-primary"}, " Select"
)
);
}
}
});
var GatherTeams = React.createClass({displayName: "GatherTeams",
alienGatherers: function () {
return this.props.gather.gatherers.filter(function (gatherer) {
return gatherer.team === "alien";
}).sort(function (gatherer) {
return (gatherer.leader) ? 1 : -1;
});
},
marineGatherers: function () {
return this.props.gather.gatherers.filter(function (gatherer) {
return gatherer.team === "marine";
}).sort(function (gatherer) {
return (gatherer.leader) ? 1 : -1;
});
},
render: function () {
var extractGatherer = function (gatherer) {
var image;
if (gatherer.leader) {
image = (React.createElement("img", {src: "/images/commander.png",
alt: "Commander",
height: "20",
width: "20"}));
}
return (
React.createElement("tr", {key: gatherer.id},
React.createElement("td", {className: "col-md-1"}, image),
React.createElement("td", {className: "col-md-11"}, gatherer.user.username)
)
);
}
var marines = this.marineGatherers().map(extractGatherer);
var aliens = this.alienGatherers().map(extractGatherer);
return (
React.createElement("div", {className: "panel-body"},
React.createElement("div", {className: "row"},
React.createElement("div", {className: "col-md-6"},
React.createElement("div", {className: "panel panel-default"},
React.createElement("div", {className: "panel-heading"},
"Aliens"
),
React.createElement("table", {className: "table"},
React.createElement("tbody", null,
aliens
)
)
)
),
React.createElement("div", {className: "col-md-6"},
React.createElement("div", {className: "panel panel-default"},
React.createElement("div", {className: "panel-heading"},
"Marines"
),
React.createElement("table", {className: "table"},
React.createElement("tbody", null,
marines
)
)
)
)
)
)
);
}
})
var GatherProgress = React.createClass({displayName: "GatherProgress",
stateDescription: function () {
switch(this.props.gather.state) {
case "gathering":
return "Waiting for more gatherers.";
case "election":
return "Currently voting for team leaders.";
case "selection":
return "Waiting for leaders to picking teams.";
case "done":
return "Gather completed.";
default:
return "Initialising gather.";
}
},
gatheringProgress: function () {
var num = this.props.gather.gatherers.length;
var den = 12;
var remaining = den - num;
var message = (remaining === 1) ? "Waiting for last player" : "Waiting for " + remaining + " more players";
return {
num: num,
den: den,
message: message
};
},
electionProgress: function () {
var num = this.props.gather.gatherers.reduce(function (acc, gatherer) {
if (gatherer.leaderVote) acc++;
return acc;
}, 0);
var den = 12;
return {
num: num,
den: den,
message: den - num + " more votes required"
};
},
selectionProgress: function () {
var num = this.props.gather.gatherers.reduce(function (acc, gatherer) {
if (gatherer.team !== "lobby") acc++;
return acc;
}, 0);
var den = 12;
return {
num: num,
den: den,
message: num + " out of " + den + " players assigned"
};
},
render: function () {
var progress;
var gatherState = this.props.gather.state;
if (gatherState === 'gathering' && this.props.gather.gatherers.length) {
progress = this.gatheringProgress();
} else if (gatherState === 'election') {
progress = this.electionProgress();
} else if (gatherState === 'selection') {
progress = this.selectionProgress();
}
if (progress) {
var style = {
width: Math.round((progress.num / progress.den * 100)) + "%"
};
return (
React.createElement("div", {className: "panel-body no-bottom"},
React.createElement("p", null, React.createElement("strong", null, this.stateDescription()), " ", progress.message),
React.createElement("div", {className: "progress"},
React.createElement("div", {className: "progress-bar progress-bar-striped active",
"data-role": "progressbar",
"data-aria-valuenow": progress.num,
"data-aria-valuemin": "0",
"data-aria-valuemax": progress.den,
style: style}
)
)
)
);
} else {
return false;
}
}
});
var GatherActions = React.createClass({displayName: "GatherActions",
joinGather: function (e) {
e.preventDefault();
socket.emit("gather:join");
},
leaveGather: function (e) {
e.preventDefault();
socket.emit("gather:leave");
},
confirmTeam: function (e) {
e.preventDefault();
socket.emit("gather:select:confirm");
},
inviteToGather: function (e) {
e.preventDefault();
alert("Boop!");
},
render: function () {
var joinButton;
if (this.props.currentGatherer) {
joinButton = (React.createElement("li", null, React.createElement("button", {
onClick: this.leaveGather,
className: "btn btn-danger"}, "Leave Gather")));
} else if (this.props.gather.state === 'gathering') {
joinButton = (
React.createElement("button", {
onClick: this.joinGather,
className: "btn btn-success"}, "Join Gather")
);
}
var confirmTeam;
if (this.props.currentGatherer &&
this.props.currentGatherer.leader &&
this.props.gather.state === 'selection' &&
this.props.gather.gatherers.every(function (gatherer) {
return gatherer.team !== 'lobby';
}) ) {
if (this.props.currentGatherer.confirm) {
confirmTeam = (
React.createElement("li", null,
React.createElement("button", {
className: "btn btn-default",
"data-disabled": "true"
},
"Confirmed"
)
)
);
} else {
confirmTeam = (
React.createElement("li", null,
React.createElement("button", {
className: "btn btn-success",
onClick: this.confirmTeam
},
"Confirm Team"
)
)
);
}
}
var inviteButton;
if (this.props.gather.state === 'gathering') {
inviteButton = (React.createElement("li", null, React.createElement("button", {
onClick: this.inviteToGather,
className: "btn btn-primary"}, "Invite to Gather")));
}
return (
React.createElement("div", {className: "panel-footer text-right"},
React.createElement("ul", {className: "list-inline no-bottom"},
confirmTeam,
inviteButton,
joinButton
)
)
);
}
});
var ServerVoting = React.createClass({displayName: "ServerVoting",
handleServerVote: function (e) {
e.preventDefault();
socket.emit("gather:vote", {
server: {
id: parseInt(e.target.value, 10)
}
});
},
votesForServer: function (server) {
return this.props.gather.gatherers.reduce(function (acc, gatherer) {
if (server.id === gatherer.serverVote) acc++;
return acc;
}, 0);
},
render: function () {
var self = this;
var servers = self.props.servers.map(function (server) {
var voteButton;
if (self.props.currentGatherer.serverVote === server.id) {
voteButton = (React.createElement("button", {
"data-disabled": "true",
className: "btn btn-xs btn-success"},
"Voted"))
} else {
voteButton = (React.createElement("button", {
onClick: self.handleServerVote,
value: server.id,
className: "btn btn-xs btn-primary"},
"Vote"));
}
return (
React.createElement("tr", null,
React.createElement("td", {className: "col-md-6"}, server.name),
React.createElement("td", {className: "col-md-3"}, self.votesForServer(server), " Votes"),
React.createElement("td", {className: "col-md-3 text-right"},
voteButton
)
)
);
});
return (
React.createElement("div", {className: "panel panel-default"},
React.createElement("div", {className: "panel-heading"},
"Server Voting"
),
React.createElement("table", {id: "serverVoteTable", className: "table table-condensed table-hover voting-table"},
servers
)
)
);
}
})
var MapVoting = React.createClass({displayName: "MapVoting",
handleMapVote: function (e) {
e.preventDefault();
socket.emit("gather:vote", {
map: {
id: parseInt(e.target.value, 10)
}
});
},
votesForMap: function (map) {
return this.props.gather.gatherers.reduce(function (acc, gatherer) {
if (map.id === gatherer.mapVote) acc++;
return acc;
}, 0);
},
render: function () {
var self = this;
var maps = self.props.maps.map(function (map) {
var voteButton;
if (self.props.currentGatherer.mapVote === map.id) {
voteButton = (React.createElement("button", {
"data-disabled": "true",
className: "btn btn-xs btn-success"},
"Voted"))
} else {
voteButton = (React.createElement("button", {
onClick: self.handleMapVote,
value: map.id,
className: "btn btn-xs btn-primary"},
"Vote"));
}
return (
React.createElement("tr", null,
React.createElement("td", {className: "col-md-6"}, map.name),
React.createElement("td", {className: "col-md-3"}, self.votesForMap(map), " Votes"),
React.createElement("td", {className: "col-md-3 text-right"},
voteButton
)
)
);
});
return (
React.createElement("div", {className: "panel panel-default"},
React.createElement("div", {className: "panel-heading"},
"Map Voting"
),
React.createElement("table", {className: "table table-condensed table-hover voting-table"},
maps
)
)
);
}
})
var Gather = React.createClass({displayName: "Gather",
getDefaultProps: function () {
return {
gather: {
gatherers: []
}
}
},
componentDidMount: function () {
var self = this;
socket.on("gather:refresh", function (data) {
self.setProps(data);
});
},
render: function () {
if (this.props.gather.state === 'done') {
return (React.createElement(CompletedGather, React.__spread({}, this.props)));
}
var voting;
if (this.props.currentGatherer) {
voting = (
React.createElement("div", {className: "panel-body"},
React.createElement("div", {className: "row"},
React.createElement("div", {className: "col-md-6"},
React.createElement(MapVoting, React.__spread({}, this.props))
),
React.createElement("div", {className: "col-md-6"},
React.createElement(ServerVoting, React.__spread({}, this.props))
)
)
)
);
}
var gatherTeams;
if (this.props.gather.state === 'selection') {
gatherTeams = React.createElement(GatherTeams, {gather: this.props.gather})
}
return (
React.createElement("div", {className: "panel panel-default"},
React.createElement("div", {className: "panel-heading"},
React.createElement("strong", null, "NS2 Gather "),
React.createElement("span", {className: "badge add-left"}, this.props.gather.gatherers.length)
),
React.createElement(GatherProgress, {gather: this.props.gather}),
React.createElement(Gatherers, {gather: this.props.gather, currentGatherer: this.props.currentGatherer}),
gatherTeams,
voting,
React.createElement(GatherActions, React.__spread({}, this.props))
)
);
}
});
var Gatherers = React.createClass({displayName: "Gatherers",
joinGather: function (e) {
e.preventDefault();
socket.emit("gather:join");
},
render: function () {
var self = this;
var gatherers = this.props.gather.gatherers.map(function (gatherer) {
// Switch this to online status
var online= (React.createElement("div", {className: "dot online"}));
var division = (React.createElement("span", {className: "label label-primary"}, gatherer.user.ability.division));
var action;
if (self.props.gather.state === 'gathering') {
action = (
gatherer.user.ability.lifeforms.map(function (lifeform) {
return (React.createElement("span", {className: "label label-default"}, lifeform));
})
);
}
if (self.props.gather.state === "election") {
var votes = self.props.gather.gatherers.reduce(function (acc, voter) {
if (voter.leaderVote === gatherer.id) acc++;
return acc;
}, 0)
action = (
React.createElement("span", null,
React.createElement("small", null, votes + " votes", "  "),
React.createElement(VoteButton, {currentGatherer: self.props.currentGatherer, candidate: gatherer})
)
);
}
if (self.props.gather.state === 'selection') {
action = (
React.createElement("span", null,
React.createElement(SelectPlayerButton, {gatherer: gatherer})
)
);
}
return (
React.createElement("tr", {key: gatherer.user.id},
React.createElement("td", {className: "col-md-6"}, online, " ", gatherer.user.username),
React.createElement("td", {className: "col-md-3"}, division, " "),
React.createElement("td", {className: "col-md-3 text-right"}, action, " ")
)
);
})
if (this.props.gather.gatherers.length) {
return (
React.createElement("div", {className: "panel-body"},
React.createElement("div", {className: "panel panel-default"},
React.createElement("table", {className: "table roster-table"},
React.createElement("tbody", null,
gatherers
)
)
)
)
);
} else {
return (
React.createElement("div", {className: "panel-body text-center join-hero"},
React.createElement("button", {
onClick: this.joinGather,
className: "btn btn-success btn-lg"}, "Start a Gather")
)
);
}
}
});
var CompletedGather = React.createClass({displayName: "CompletedGather",
votedMaps: function () {
},
votedServer: function () {
},
render: function () {
return (
React.createElement("div", {className: "panel panel-default"},
React.createElement("div", {className: "panel-heading"},
React.createElement("strong", null, "Gather Completed")
),
React.createElement("div", {className: "panel-body"},
React.createElement("h3", null, "Join Up:"),
React.createElement("p", null, "Map Voted: To be completed"),
React.createElement("p", null, "Server Voted: To be completed")
),
React.createElement(GatherTeams, {gather: this.props.gather})
)
);
}
});
"use strict";
var socket;
function initialiseVisibilityMonitoring (socket) {
var hidden, visibilityChange;
if (typeof document.hidden !== "undefined") { // Opera 12.10 and Firefox 18 and later support
hidden = "hidden";
visibilityChange = "visibilitychange";
} else if (typeof document.mozHidden !== "undefined") {
hidden = "mozHidden";
visibilityChange = "mozvisibilitychange";
} else if (typeof document.msHidden !== "undefined") {
hidden = "msHidden";
visibilityChange = "msvisibilitychange";
} else if (typeof document.webkitHidden !== "undefined") {
hidden = "webkitHidden";
visibilityChange = "webkitvisibilitychange";
}
document.addEventListener(visibilityChange, function () {
if (document[hidden]) {
socket.emit("users:away");
} else {
socket.emit("users:online");
}
}, false);
}
function initialiseComponents () {
var socketUrl = window.location.protocol + "//" + window.location.host;
socket = io(socketUrl)
.on("connect", function () {
console.log("Connected");
})
.on("reconnect", function () {
console.log("Reconnected");
})
.on("disconnect", function () {
console.log("Disconnected")
});
initialiseVisibilityMonitoring(socket);
// Render Page
React.render(React.createElement(UserMenu, null), document.getElementById('side-menu'));
React.render(React.createElement(Chatroom, null), document.getElementById('chatroom'));
React.render(React.createElement(Gather, null), document.getElementById('gathers'));
React.render(React.createElement(CurrentUser, null), document.getElementById('currentuser'));
React.render(React.createElement(AdminPanel, null), document.getElementById('admin-menu'));
};
"use strict";
var Chatroom = React.createClass({displayName: "Chatroom",
getDefaultProps: function () {
return {
history: []
};
},
componentDidMount: function () {
var self = this;
var TIMER_INTERVAL = 60000; // Every minute
socket.on("message:new", function (data) {
var history = self.props.history;
history.push(data);
self.setProps({
history: history
});
self.scrollToBottom();
});
// Message History Retrieved
socket.on("message:refresh", function (data) {
self.setProps({
history: data.chatHistory
});
self.scrollToBottom();
});
socket.emit("message:refresh", {});
self.timer = setInterval(function () {
if (self.refs.messages) self.refs.messages.refreshTime();
}, TIMER_INTERVAL);
},
componentDidUnmount: function () {
clearInterval(this.timer);
},
sendMessage: function (message) {
socket.emit("newMessage", {message: message});
},
scrollToBottom: function () {
var node = React.findDOMNode(this.refs.messageContainer);
node.scrollTop = node.scrollHeight;
},
render: function () {
var messages = this.props.history.map(function (message) {
return (
React.createElement(ChatMessage, {
avatar: message.author.avatar,
username: message.author.username,
content: message.content,
ref: "messages",
createdAt: message.createdAt})
);
});
return (
React.createElement("div", {className: "panel panel-default"},
React.createElement("div", {className: "panel-heading"}, "Gather Chat"),
React.createElement("div", {className: "panel-body"},
React.createElement("ul", {className: "chat", id: "chatmessages", ref: "messageContainer"},
messages
)
),
React.createElement("div", {className: "panel-footer"},
React.createElement(MessageBar, null)
)
)
);
}
});
var ChatMessage = React.createClass({displayName: "ChatMessage",
getInitialState: function () {
return {
timeAgo: $.timeago(this.props.createdAt)
}
},
refreshTime: function () {
var self = this;
self.setState({
timeAgo: $.timeago(self.props.createdAt)
});
},
render: function () {
return (
React.createElement("li", {className: "left clearfix"},
React.createElement("span", {className: "chat-img pull-left"},
React.createElement("img", {
src: this.props.avatar,
alt: "User Avatar",
height: "40",
width: "40",
className: "img-circle"})
),
React.createElement("div", {className: "chat-body clearfix"},
React.createElement("div", {className: "header"},
React.createElement("strong", {className: "primary-font"}, this.props.username),
React.createElement("small", {className: "pull-right text-muted"},
React.createElement("i", {className: "fa fa-clock-o fa-fw"}), " ", this.state.timeAgo
)
),
React.createElement("p", null, this.props.content)
)
)
);
}
});
var MessageBar = React.createClass({displayName: "MessageBar",
sendMessage: function (content) {
socket.emit("message:new", {
content: content
});
},
handleSubmit: function (e) {
e.preventDefault();
var content = React.findDOMNode(this.refs.content).value.trim();
if (!content) return;
React.findDOMNode(this.refs.content).value = '';
this.sendMessage(content);
return;
},
render: function () {
return (
React.createElement("form", {onSubmit: this.handleSubmit},
React.createElement("div", {className: "input-group"},
React.createElement("input", {
id: "btn-input",
type: "text",
className: "form-control",
ref: "content",
placeholder: "Be polite please..."}),
React.createElement("span", {className: "input-group-btn"},
React.createElement("input", {
type: "submit",
className: "btn btn-primary",
id: "btn-chat",
value: "Send"})
)
)
)
);
}
});
"use strict";
var UserCounter = React.createClass({displayName: "UserCounter",
render: function () {
return (
React.createElement("li", null,
React.createElement("a", {href: "#"},
React.createElement("i", {className: "fa fa-users fa-fw"}), " Online",
React.createElement("span", {className: "badge add-left"}, " ", this.props.count, " ")
)
)
);
}
});
var UserLogin = React.createClass({displayName: "UserLogin",
authorizeId: function (id) {
id = parseInt(id, 10);
socket.emit("users:authorize", {
id: id
});
setTimeout(function () {
socket.emit("gather:refresh");
}, 5000);
},
handleSubmit: function (e) {
e.preventDefault();
var id = React.findDOMNode(this.refs.authorize_id).value.trim();
if (!id) return;
React.findDOMNode(this.refs.authorize_id).value = '';
this.authorizeId(id);
return;
},
render: function () {
return (
React.createElement("form", {onSubmit: this.handleSubmit},
React.createElement("div", {className: "input-group signin"},
React.createElement("input", {
id: "btn-input",
type: "text",
className: "form-control",
ref: "authorize_id",
placeholder: "Choose an ID..."}),
React.createElement("span", {className: "input-group-btn"},
React.createElement("input", {
type: "submit",
className: "btn btn-primary",
id: "btn-chat",
value: "Login"})
)
),
React.createElement("div", {className: "signin"},
React.createElement("p", {className: "text-center"}, React.createElement("small", null, "Just a temporary measure until genuine authentication is implemented"))
)
)
);
}
})
var UserMenu = React.createClass({displayName: "UserMenu",
getDefaultProps: function () {
return {
count: 0,
users: []
};
},
componentDidMount: function () {
socket.on('users:update', this.updateUsers);
},
updateUsers: function (data) {
this.setProps({
count: data.count,
users: data.users
});
},
render: function () {
var users = this.props.users.map(function (user) {
return (
React.createElement("li", {key: user.id}, React.createElement("a", {href: "#"}, user.username))
);
});
return (
React.createElement("ul", {className: "nav", id: "side-menu"},
React.createElement(UserCounter, React.__spread({}, this.props)),
users,
React.createElement("li", null, React.createElement("br", null), React.createElement(UserLogin, null), React.createElement("br", null))
)
);
}
});
var AdminPanel = React.createClass({displayName: "AdminPanel",
handleGatherReset: function () {
socket.emit("gather:reset");
},
render: function () {
return (
React.createElement("ul", {className: "nav", id: "admin-menu"},
React.createElement("li", null,
React.createElement("div", {className: "admin-panel"},
React.createElement("h5", null, "Admin"),
React.createElement("button", {
className: "btn btn-danger",
onClick: this.handleGatherReset},
"Reset Gather"),
React.createElement("p", {className: "text-center"}, React.createElement("small", null, "Only responds for admins on staging.ensl.org"))
)
)
)
)
}
});
var CurrentUser = React.createClass({displayName: "CurrentUser",
componentDidMount: function () {
var self = this;
socket.on("users:update", function (data) {
self.setProps({
user: data.currentUser
});
});
socket.emit("users:refresh", {});
},
render: function () {
if (this.props.user) {
return (
React.createElement("a", {href: "#"}, this.props.user.username, "  ", React.createElement("img", {src: this.props.user.avatar,
alt: "User Avatar",
height: "20",
width: "20"}))
);
} else {
return false;
}
}
});