diff --git a/client/src/modules/front_end_components/HTMLFragments.js b/client/src/modules/front_end_components/HTMLFragments.js index bceb814..cbd7242 100644 --- a/client/src/modules/front_end_components/HTMLFragments.js +++ b/client/src/modules/front_end_components/HTMLFragments.js @@ -20,7 +20,7 @@ export const HTMLFragments = {
- +
@@ -75,7 +75,7 @@ export const HTMLFragments = {
- +
@@ -114,7 +114,7 @@ export const HTMLFragments = {
- +
@@ -157,9 +157,11 @@ export const HTMLFragments = {
- +
- +
@@ -201,7 +203,7 @@ export const HTMLFragments = {
- +
@@ -285,7 +287,7 @@ export const HTMLFragments = { `

🏁 The moderator has ended the game. Roles are revealed.

- + diff --git a/client/src/modules/game_state/states/InProgress.js b/client/src/modules/game_state/states/InProgress.js index 8d8fccd..ed4f3aa 100644 --- a/client/src/modules/game_state/states/InProgress.js +++ b/client/src/modules/game_state/states/InProgress.js @@ -71,12 +71,12 @@ export class InProgress { }; if (spectatorCount) { - spectatorCount?.addEventListener('click', spectatorHandler); - spectatorCount?.addEventListener('keyup', spectatorHandler); SharedStateUtil.setNumberOfSpectators( this.stateBucket.currentGameState.people.filter(p => p.userType === globals.USER_TYPES.SPECTATOR).length, spectatorCount ); + spectatorCount?.addEventListener('click', spectatorHandler); + spectatorCount?.addEventListener('keyup', spectatorHandler); } } diff --git a/client/src/modules/game_state/states/Lobby.js b/client/src/modules/game_state/states/Lobby.js index 28eef6f..9f39ba5 100644 --- a/client/src/modules/game_state/states/Lobby.js +++ b/client/src/modules/game_state/states/Lobby.js @@ -59,9 +59,15 @@ export class Lobby { const playerCount = this.container.querySelector('#game-player-count'); playerCount.innerText = this.stateBucket.currentGameState.gameSize + ' Players'; - this.container.querySelector('#spectator-count').addEventListener('click', () => { - Confirmation(SharedStateUtil.buildSpectatorList(this.stateBucket.currentGameState.people), null, true); - }); + const spectatorHandler = (e) => { + if (e.type === 'click' || e.code === 'Enter') { + Confirmation(SharedStateUtil.buildSpectatorList(this.stateBucket.currentGameState.people + .filter(p => p.userType === globals.USER_TYPES.SPECTATOR)), null, true); + } + }; + + this.container.querySelector('#spectator-count').addEventListener('click', spectatorHandler); + this.container.querySelector('#spectator-count').addEventListener('keyup', spectatorHandler); SharedStateUtil.setNumberOfSpectators( this.stateBucket.currentGameState.people.filter(p => p.userType === globals.USER_TYPES.SPECTATOR).length, diff --git a/client/src/modules/timer/GameTimerManager.js b/client/src/modules/timer/GameTimerManager.js index 5b839ea..ebcf212 100644 --- a/client/src/modules/timer/GameTimerManager.js +++ b/client/src/modules/timer/GameTimerManager.js @@ -152,6 +152,7 @@ export class GameTimerManager { const playBtn = document.createElement('img'); playBtn.setAttribute('src', '../images/play-button.svg'); + playBtn.setAttribute('alt', 'play button'); playBtn.setAttribute('tabindex', '0'); playBtn.addEventListener('click', this.playListener); playBtn.addEventListener('keyup', this.playListener); diff --git a/client/src/styles/GLOBAL.css b/client/src/styles/GLOBAL.css index 458e03e..ea1e72c 100644 --- a/client/src/styles/GLOBAL.css +++ b/client/src/styles/GLOBAL.css @@ -287,7 +287,7 @@ button { #game-parameters { font-family: signika-negative, sans-serif; color: #d7d7d7; - font-size: 25px; + font-size: 20px; margin: 0.5em; } @@ -591,7 +591,7 @@ input { } .evil, .compact-card.evil .card-role { - color: #dd2929 !important; + color: #e51a1a !important; font-weight: bold; } diff --git a/client/src/views/404.html b/client/src/views/404.html index 15a7822..4b0ce98 100644 --- a/client/src/views/404.html +++ b/client/src/views/404.html @@ -27,6 +27,6 @@

The game or other resource that you are looking for could not be found, or you don't have permission to access it. Old games are periodically cleared.

- + diff --git a/client/src/views/create.html b/client/src/views/create.html index 08b6a84..4229d82 100644 --- a/client/src/views/create.html +++ b/client/src/views/create.html @@ -23,6 +23,6 @@
- + diff --git a/client/src/views/game.html b/client/src/views/game.html index 1dd3246..be5a021 100644 --- a/client/src/views/game.html +++ b/client/src/views/game.html @@ -20,8 +20,8 @@ - - + + diff --git a/client/src/views/home.html b/client/src/views/home.html index 61fad29..df9865b 100644 --- a/client/src/views/home.html +++ b/client/src/views/home.html @@ -59,6 +59,6 @@ email
- + diff --git a/client/src/views/how-to-use.html b/client/src/views/how-to-use.html index 464f313..8627acb 100644 --- a/client/src/views/how-to-use.html +++ b/client/src/views/how-to-use.html @@ -143,6 +143,6 @@

- + diff --git a/client/src/views/join.html b/client/src/views/join.html index 7557730..33e6844 100644 --- a/client/src/views/join.html +++ b/client/src/views/join.html @@ -51,7 +51,7 @@ - + diff --git a/client/webpack/webpack-dev.config.js b/client/webpack/webpack-dev.config.js index 975d9a3..5442f3d 100644 --- a/client/webpack/webpack-dev.config.js +++ b/client/webpack/webpack-dev.config.js @@ -1,4 +1,5 @@ const path = require('path'); +const CompressionPlugin = require("compression-webpack-plugin"); module.exports = { entry: { @@ -11,8 +12,11 @@ module.exports = { }, output: { path: path.resolve(__dirname, '../dist'), - filename: "[name]-bundle.js" + filename: "[name]-bundle.js", }, + plugins: [new CompressionPlugin({ + exclude: [/.map$/, /521-bundle.js$/] + })], mode: "development", node: false, devtool: 'source-map', diff --git a/client/webpack/webpack-prod.config.js b/client/webpack/webpack-prod.config.js index d264f98..b7fc72e 100644 --- a/client/webpack/webpack-prod.config.js +++ b/client/webpack/webpack-prod.config.js @@ -1,4 +1,5 @@ const path = require('path'); +const CompressionPlugin = require("compression-webpack-plugin"); 'use strict'; module.exports = { @@ -14,6 +15,7 @@ module.exports = { path: path.resolve(__dirname, '../dist'), filename: "[name]-bundle.js" }, + plugins: [new CompressionPlugin({ deleteOriginalAssets: true, exclude: [/521-bundle.js$/]})], mode: "production", node: false, module: { diff --git a/package-lock.json b/package-lock.json index 11b4958..b8ee5b7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,7 @@ "dependencies": { "babel-loader": "^8.2.3", "body-parser": "^1.20.1", + "compression-webpack-plugin": "^10.0.0", "cors": "^2.8.5", "express": "^4.18.2", "express-force-https": "^1.0.0", @@ -2209,6 +2210,42 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ajv-formats/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, "node_modules/ajv-keywords": { "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", @@ -2703,6 +2740,74 @@ "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=" }, + "node_modules/compression-webpack-plugin": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/compression-webpack-plugin/-/compression-webpack-plugin-10.0.0.tgz", + "integrity": "sha512-wLXLIBwpul/ALcm7Aj+69X0pYT3BYt6DdPn3qrgBIh9YejV9Bju9ShhlAsjujLyWMo6SAweFIWaUoFmXZNuNrg==", + "dependencies": { + "schema-utils": "^4.0.0", + "serialize-javascript": "^6.0.0" + }, + "engines": { + "node": ">= 14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + } + }, + "node_modules/compression-webpack-plugin/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/compression-webpack-plugin/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/compression-webpack-plugin/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, + "node_modules/compression-webpack-plugin/node_modules/schema-utils": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", + "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.8.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.0.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -5983,7 +6088,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -8876,6 +8980,32 @@ "uri-js": "^4.2.2" } }, + "ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "requires": { + "ajv": "^8.0.0" + }, + "dependencies": { + "ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + } + } + }, "ajv-keywords": { "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", @@ -9239,6 +9369,52 @@ "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=" }, + "compression-webpack-plugin": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/compression-webpack-plugin/-/compression-webpack-plugin-10.0.0.tgz", + "integrity": "sha512-wLXLIBwpul/ALcm7Aj+69X0pYT3BYt6DdPn3qrgBIh9YejV9Bju9ShhlAsjujLyWMo6SAweFIWaUoFmXZNuNrg==", + "requires": { + "schema-utils": "^4.0.0", + "serialize-javascript": "^6.0.0" + }, + "dependencies": { + "ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "requires": { + "fast-deep-equal": "^3.1.3" + } + }, + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, + "schema-utils": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", + "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", + "requires": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.8.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.0.0" + } + } + } + }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -11655,8 +11831,7 @@ "require-from-string": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==" }, "requires-port": { "version": "1.0.0", diff --git a/package.json b/package.json index 9bd3e28..11c62b6 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,7 @@ "dependencies": { "babel-loader": "^8.2.3", "body-parser": "^1.20.1", + "compression-webpack-plugin": "^10.0.0", "cors": "^2.8.5", "express": "^4.18.2", "express-force-https": "^1.0.0", diff --git a/server/modules/ServerBootstrapper.js b/server/modules/ServerBootstrapper.js index 1fa5dec..723238b 100644 --- a/server/modules/ServerBootstrapper.js +++ b/server/modules/ServerBootstrapper.js @@ -139,6 +139,13 @@ const ServerBootstrapper = { const router = require('../routes/router'); app.use('', router); + app.use('/dist', (req, res, next) => { + if (req.url !== '/521-bundle.js') { + res.set('Content-Encoding', 'gzip'); + } + next(); + }); + app.use('/dist', express.static(path.join(__dirname, '../../client/dist'))); // set up routing for static content that isn't being bundled.