Bug Fixes and field toggle

- fixed overlay bugs
- added feedback to startRound button
- switched to socket.io for field toggle
- added compression and minify
pull/23/head
Trivernis 6 years ago
parent 38420bd0dd
commit 6dc331c392

@ -9,10 +9,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added ### Added
- socket.io for real time communication - socket.io for real time communication
- compression and minify
## Changed ## Changed
- frontend to use socket.io instead of graphql for refreshing - frontend to use socket.io instead of graphql for refreshing
- use of socket.io for toggeling binogo fields
### Removed ### Removed

@ -4,6 +4,9 @@ const createError = require('http-errors'),
cookieParser = require('cookie-parser'), cookieParser = require('cookie-parser'),
logger = require('morgan'), logger = require('morgan'),
compileSass = require('express-compile-sass'), compileSass = require('express-compile-sass'),
minify = require('express-minify'),
compression = require('compression'),
uglifyEs = require('uglify-es'),
session = require('express-session'), session = require('express-session'),
pgSession = require('connect-pg-simple')(session), pgSession = require('connect-pg-simple')(session),
fsx = require('fs-extra'), fsx = require('fs-extra'),
@ -48,6 +51,10 @@ async function init() {
app.set('view engine', 'pug'); app.set('view engine', 'pug');
app.set('trust proxy', 1); app.set('trust proxy', 1);
app.use(compression());
app.use(minify({
uglifyJsModule: uglifyEs
}));
app.use(logger('dev')); app.use(logger('dev'));
app.use(express.json()); app.use(express.json());
app.use(express.urlencoded({extended: false})); app.use(express.urlencoded({extended: false}));

84
package-lock.json generated

@ -800,6 +800,11 @@
"delayed-stream": "~1.0.0" "delayed-stream": "~1.0.0"
} }
}, },
"commander": {
"version": "2.20.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz",
"integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ=="
},
"component-bind": { "component-bind": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz",
@ -815,6 +820,38 @@
"resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz", "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz",
"integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=" "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM="
}, },
"compressible": {
"version": "2.0.17",
"resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.17.tgz",
"integrity": "sha512-BGHeLCK1GV7j1bSmQQAi26X+GgWcTjLr/0tzSvMCl3LH1w1IJ4PFSPoV5316b30cneTziC+B1a+3OjoSUcQYmw==",
"requires": {
"mime-db": ">= 1.40.0 < 2"
}
},
"compression": {
"version": "1.7.4",
"resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz",
"integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==",
"requires": {
"accepts": "~1.3.5",
"bytes": "3.0.0",
"compressible": "~2.0.16",
"debug": "2.6.9",
"on-headers": "~1.0.2",
"safe-buffer": "5.1.2",
"vary": "~1.1.2"
},
"dependencies": {
"debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"requires": {
"ms": "2.0.0"
}
}
}
},
"concat-map": { "concat-map": {
"version": "0.0.1", "version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
@ -1744,6 +1781,32 @@
} }
} }
}, },
"express-minify": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/express-minify/-/express-minify-1.0.0.tgz",
"integrity": "sha512-04/iYxB79jGeNZBBkbAW7L7FMG4Wtu78F1SayXIKiJD6MfqYnOI3DD8no7QOntgedYCdYUpj+Skg8QWR/2WnMQ==",
"requires": {
"clean-css": "^4.1.7",
"on-headers": "^1.0.1",
"uglify-js": "^3.0.28"
},
"dependencies": {
"source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
},
"uglify-js": {
"version": "3.5.14",
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.5.14.tgz",
"integrity": "sha512-dgyjIw8KFK6AyVl5vm2tEqPewv5TKGEiiVFLI1LbF+oHua/Njd8tZk3lIbF1AWU1rNdEg7scaceADb4zqCcWXg==",
"requires": {
"commander": "~2.20.0",
"source-map": "~0.6.1"
}
}
}
},
"express-session": { "express-session": {
"version": "1.16.1", "version": "1.16.1",
"resolved": "https://registry.npmjs.org/express-session/-/express-session-1.16.1.tgz", "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.16.1.tgz",
@ -5787,6 +5850,27 @@
"resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz",
"integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==" "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA=="
}, },
"uglify-es": {
"version": "3.3.9",
"resolved": "https://registry.npmjs.org/uglify-es/-/uglify-es-3.3.9.tgz",
"integrity": "sha512-r+MU0rfv4L/0eeW3xZrd16t4NZfK8Ld4SWVglYBb7ez5uXFWHuVRs6xCTrf1yirs9a4j4Y27nn7SRfO6v67XsQ==",
"requires": {
"commander": "~2.13.0",
"source-map": "~0.6.1"
},
"dependencies": {
"commander": {
"version": "2.13.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.13.0.tgz",
"integrity": "sha512-MVuS359B+YzaWqjCL/c+22gfryv+mCBPHAv3zyVI2GN8EY6IRP8VwtasXn8jyyhvvq84R4ImN1OKRtcbIasjYA=="
},
"source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
}
}
},
"uglify-js": { "uglify-js": {
"version": "2.8.29", "version": "2.8.29",
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz",

@ -6,12 +6,14 @@
"start": "node ./bin/www" "start": "node ./bin/www"
}, },
"dependencies": { "dependencies": {
"compression": "^1.7.4",
"connect-pg-simple": "5.0.0", "connect-pg-simple": "5.0.0",
"cookie-parser": "1.4.4", "cookie-parser": "1.4.4",
"debug": "4.1.1", "debug": "4.1.1",
"express": "4.17.0", "express": "4.17.0",
"express-compile-sass": "latest", "express-compile-sass": "latest",
"express-graphql": "0.8.0", "express-graphql": "0.8.0",
"express-minify": "^1.0.0",
"express-session": "latest", "express-session": "latest",
"fs-extra": "8.0.1", "fs-extra": "8.0.1",
"graphql": "14.3.0", "graphql": "14.3.0",
@ -26,7 +28,8 @@
"node-sass": "4.12.0", "node-sass": "4.12.0",
"pg": "7.11.0", "pg": "7.11.0",
"pug": "2.0.3", "pug": "2.0.3",
"socket.io": "^2.2.0" "socket.io": "^2.2.0",
"uglify-es": "^3.3.9"
}, },
"devDependencies": { "devDependencies": {
"eslint": "^5.16.0", "eslint": "^5.16.0",

@ -378,9 +378,11 @@ async function sendChatMessage() {
* @returns {Promise<boolean>} * @returns {Promise<boolean>}
*/ */
async function startRound() { async function startRound() {
let roundStart = document.querySelector('#button-round-start');
let textinput = document.querySelector('#input-bingo-words'); let textinput = document.querySelector('#input-bingo-words');
let words = getLobbyWords(); let words = getLobbyWords();
if (words.length > 0) { if (words.length > 0) {
roundStart.setAttribute('class', 'pending');
let gridSize = document.querySelector('#input-grid-size').value || 3; let gridSize = document.querySelector('#input-grid-size').value || 3;
let resultWords = await BingoGraphqlHelper.setLobbySettings(words, gridSize); let resultWords = await BingoGraphqlHelper.setLobbySettings(words, gridSize);
if (resultWords) { if (resultWords) {
@ -402,6 +404,7 @@ async function startRound() {
console.error(response); console.error(response);
showError('Error when starting round.'); showError('Error when starting round.');
} }
roundStart.setAttribute('class', '');
} }
} else { } else {
throw new Error('No words provided.'); throw new Error('No words provided.');
@ -429,32 +432,8 @@ async function submitFieldToggle(wordPanel) {
let column = Number(wordPanel.getAttribute('b-column')); let column = Number(wordPanel.getAttribute('b-column'));
let wordClass = wordPanel.getAttribute('class'); let wordClass = wordPanel.getAttribute('class');
wordPanel.setAttribute('class', wordClass + ' pending'); wordPanel.setAttribute('class', wordClass + ' pending');
let response = await postGraphqlQuery(`
mutation($lobbyId:ID!, $row:Int!, $column:Int!){
bingo {
mutateLobby(id:$lobbyId) {
toggleGridField(location:{row:$row, column:$column}) {
submitted
grid {
bingo
}
}
}
}
}`, {lobbyId: getLobbyParam(), row: row, column: column});
wordPanel.setAttribute('class', wordClass);
if (response.status === 200) { socket.emit('fieldToggle', {row: row, column: column});
wordPanel.setAttribute('b-sub', response.data.bingo.mutateLobby.toggleGridField.submitted);
if (response.data.bingo.mutateLobby.toggleGridField.grid.bingo)
document.querySelector('#container-bingo-button').setAttribute('class', '');
else
document.querySelector('#container-bingo-button').setAttribute('class', 'hidden');
} else {
console.error(response);
showError('Error when submitting field toggle');
}
} }
/** /**
@ -483,7 +462,7 @@ async function setRoundFinished() {
/** /**
* Submits bingo * Submits bingo
* @returns {Promise<void>} * @returns {Promise<boolean>}
*/ */
async function submitBingo() { async function submitBingo() {
let response = await postGraphqlQuery(` let response = await postGraphqlQuery(`
@ -504,8 +483,7 @@ async function submitBingo() {
}`, {lobbyId: getLobbyParam()}); }`, {lobbyId: getLobbyParam()});
if (response.status === 200 && response.data.bingo.mutateLobby.submitBingo) { if (response.status === 200 && response.data.bingo.mutateLobby.submitBingo) {
let round = response.data.bingo.mutateLobby.submitBingo; return true;
displayWinner(round);
} else { } else {
console.error(response); console.error(response);
showError('Failed to submit bingo'); showError('Failed to submit bingo');
@ -514,10 +492,10 @@ async function submitBingo() {
/** /**
* Displays the winner of the game in a popup. * Displays the winner of the game in a popup.
* @param roundInfo {Object} - the round object as returned by graphql * @param winner {Object} - the round object as returned by graphql
*/ */
function displayWinner(roundInfo) { function displayWinner(winner) {
let name = roundInfo.winner.username; let name = winner.username;
let winnerDiv = document.createElement('div'); let winnerDiv = document.createElement('div');
let greyoverDiv = document.createElement('div'); let greyoverDiv = document.createElement('div');
winnerDiv.setAttribute('class', 'popup'); winnerDiv.setAttribute('class', 'popup');
@ -585,7 +563,7 @@ function addChatMessage(messageObject, player) {
<span class="chatMessageContent ${messageObject.type}">${messageObject.htmlContent}</span>`; <span class="chatMessageContent ${messageObject.type}">${messageObject.htmlContent}</span>`;
if (messageObject.author && messageObject.author.id !== player) if (messageObject.type === 'USER' && messageObject.author && messageObject.author.id !== player)
spawnNotification(messageObject.content, messageObject.author.username); spawnNotification(messageObject.content, messageObject.author.username);
let chatContent = document.querySelector('#chat-content'); let chatContent = document.querySelector('#chat-content');
@ -678,16 +656,16 @@ function initSocketEvents(data) {
}); });
socket.on('message', (msg) => { socket.on('message', (msg) => {
console.log(msg);
addChatMessage(msg, playerId); addChatMessage(msg, playerId);
}); });
socket.on('statusChange', (status) => { socket.on('statusChange', (status, winner) => {
console.log(`Status changed to ${status}`); if (status === 'FINISHED') {
if (status === 'FINISHED') if (document.querySelector('#container-bingo-round'))
BingoGraphqlHelper.loadWinnerInfo(); displayWinner(winner);
else } else {
window.location.reload(); window.location.reload();
}
}); });
socket.on('playerJoin', (playerObject) => { socket.on('playerJoin', (playerObject) => {
@ -699,7 +677,6 @@ function initSocketEvents(data) {
}); });
socket.on('usernameChange', (playerObject) => { socket.on('usernameChange', (playerObject) => {
console.log(playerObject);
document.querySelector(`.playerEntryContainer[b-pid='${playerObject.id}'] .playerNameSpan`).innerText = playerObject.username; document.querySelector(`.playerEntryContainer[b-pid='${playerObject.id}'] .playerNameSpan`).innerText = playerObject.username;
}); });
@ -710,6 +687,16 @@ function initSocketEvents(data) {
showError('Failed to load new lobby words.'); showError('Failed to load new lobby words.');
} }
}); });
socket.on('fieldChange', (field) => {
let wordPanel = document.querySelector(`.bingoWordPanel[b-row='${field.row}'][b-column='${field.column}']`);
wordPanel.setAttribute('b-sub', field.submitted);
wordPanel.setAttribute('class', 'bingoWordPanel');
if (field.bingo)
document.querySelector('#container-bingo-button').setAttribute('class', '');
else
document.querySelector('#container-bingo-button').setAttribute('class', 'hidden');
});
} }
/** /**
@ -747,6 +734,8 @@ window.onload = async () => {
showError(err.message); showError(err.message);
} }
} }
let chatContent = document.querySelector('#chat-content');
chatContent.scrollTop = chatContent.scrollHeight;
}; };
let socket = null; let socket = null;

@ -891,7 +891,7 @@ class RoundWrapper {
let updateResult = await bdm.setRoundWinner(this.id, winnerId); let updateResult = await bdm.setRoundWinner(this.id, winnerId);
if (updateResult) if (updateResult)
await this.setFinished(); await this.setFinished();
(await this.lobby()).socket.emit('statusChange', 'FINISHED'); (await this.lobby()).socket.emit('statusChange', 'FINISHED', await resolvePlayer(new PlayerWrapper(winnerId)));
return true; return true;
} }
} }
@ -1456,6 +1456,20 @@ async function resolvePlayer(playerWrapper, lobbyId) {
}; };
} }
/**
* Resolves a fieldWrapper object
* @param fieldWrapper
* @returns {Promise<{submitted: (Object.submitted|*), column: *, bingo: boolean, row: (Object.grid_row|number|*)}>}
*/
async function resolveGridField(fieldWrapper) {
return {
row: fieldWrapper.row,
column: fieldWrapper.column,
submitted: fieldWrapper.submitted,
bingo: await fieldWrapper.grid.bingo()
};
}
/** /**
* Returns resolved message data. * Returns resolved message data.
* @param lobbyId * @param lobbyId
@ -1493,6 +1507,12 @@ function createSocketIfNotExist(io, lobbyId) {
console.log(err); console.log(err);
} }
}); });
socket.on('fieldToggle', async (context, location) => {
let {row, column} = location;
let result = await (await (new PlayerWrapper(context.playerId)).grid({lobbyId: lobbyId}))
.toggleField(row, column);
socket.emit('fieldChange', await resolveGridField(result));
});
}); });
} }
} }

Loading…
Cancel
Save