From 3e2b503ad2ef28f5b42b7f55ce8e4b9a0c7789e8 Mon Sep 17 00:00:00 2001 From: AlecM33 Date: Tue, 28 Dec 2021 15:16:28 -0500 Subject: [PATCH] nodemon, fix small issues --- client/robots.txt | 2 + client/src/modules/GameCreationStepManager.js | 1 + client/src/modules/Templates.js | 2 +- client/src/scripts/game.js | 1 + client/src/styles/GLOBAL.css | 11 +- client/src/styles/create.css | 17 ++- client/src/styles/game.css | 13 +- client/src/styles/home.css | 7 +- client/src/styles/modal.css | 2 +- client/src/views/create.html | 2 +- manifest.json | 1 - package.json | 10 +- server/main.js | 125 +++--------------- server/modules/ServerBootstrapper.js | 106 +++++++++++++++ 14 files changed, 173 insertions(+), 127 deletions(-) create mode 100644 client/robots.txt create mode 100644 server/modules/ServerBootstrapper.js diff --git a/client/robots.txt b/client/robots.txt new file mode 100644 index 0000000..d346249 --- /dev/null +++ b/client/robots.txt @@ -0,0 +1,2 @@ +User-agent: * +Disallow: /api/ diff --git a/client/src/modules/GameCreationStepManager.js b/client/src/modules/GameCreationStepManager.js index 1679ae5..2dd9b54 100644 --- a/client/src/modules/GameCreationStepManager.js +++ b/client/src/modules/GameCreationStepManager.js @@ -319,6 +319,7 @@ function showButtons(back, forward, forwardHandler, backHandler, builtGame=null) backButton.innerText = "\u2bc7 Back"; backButton.addEventListener('click', backHandler); backButton.setAttribute("id", "step-back-button"); + backButton.classList.add('cancel'); document.getElementById("tracker-container").prepend(backButton); } diff --git a/client/src/modules/Templates.js b/client/src/modules/Templates.js index 7ef70cb..c1179a5 100644 --- a/client/src/modules/Templates.js +++ b/client/src/modules/Templates.js @@ -116,7 +116,7 @@ export const templates = { "

Transfer Mod Powers 👑

" + "" + "" + "" + "" + diff --git a/client/src/scripts/game.js b/client/src/scripts/game.js index ef6086f..5e77c73 100644 --- a/client/src/scripts/game.js +++ b/client/src/scripts/game.js @@ -141,6 +141,7 @@ function processGameState (currentGameState, userId, socket, gameStateRenderer, } break; case globals.STATUS.ENDED: + document.querySelector("#end-game-prompt")?.remove(); let container = document.getElementById("game-state-container") container.innerHTML = templates.END_OF_GAME_VIEW; container.classList.add('vertical-flex'); diff --git a/client/src/styles/GLOBAL.css b/client/src/styles/GLOBAL.css index 0efac8e..7afcd54 100644 --- a/client/src/styles/GLOBAL.css +++ b/client/src/styles/GLOBAL.css @@ -23,7 +23,8 @@ th, thead, tr, tt, u, ul, var { html { font-family: 'signika-negative', sans-serif !important; - background-color: #121314 !important; + background-color: #0f0f10; + height: 100%; } body { @@ -48,7 +49,7 @@ body { h1 { font-family: 'diavlo', sans-serif; - color: #ab2626; + color: #b1afcd; filter: drop-shadow(2px 2px 4px black); margin: 0.5em 0; } @@ -154,6 +155,11 @@ button:active, input[type=submit]:active { border: 2px solid #21ba45; } +.cancel:hover { + background-color: #623232 !important; + border: 2px solid #8a1c1c; +} + .container { padding: 5px; border-radius: 3px; @@ -206,6 +212,7 @@ input { padding: 5px 0; width: 100%; background-color: #333243; + border-bottom: 2px solid #57566a } #navbar img { diff --git a/client/src/styles/create.css b/client/src/styles/create.css index 137881e..83626d3 100644 --- a/client/src/styles/create.css +++ b/client/src/styles/create.css @@ -85,9 +85,10 @@ #deck-container, #custom-roles-container { margin: 1em 0; - background-color: #1f1f1f; + background-color: #191920; padding: 10px; border-radius: 3px; + border: 2px solid #333243; } #step-3 { @@ -101,7 +102,7 @@ } option { - background-color: #1f1f1f; + background-color: #191920; cursor: pointer; } @@ -148,7 +149,7 @@ select { } #game-form > div { - background-color: #1f1f1f; + background-color: #191920; display: flex; flex-direction: column; padding: 10px; @@ -164,7 +165,8 @@ select { #game-time { display: flex; flex-wrap: wrap; - background-color: #1f1f1f; + background-color: #191920; + border: 2px solid #333243; border-radius: 3px; } @@ -290,13 +292,13 @@ input[type="number"] { } #step-1 div { - background-color: black; + background-color: #191920; color: whitesmoke; padding: 1em; max-width: 20em; margin: 0.5em; cursor: pointer; - border: 2px solid transparent; + border: 2px solid #333243; border-radius: 3px; box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.6); } @@ -315,7 +317,8 @@ input[type="number"] { } .review-option { - background-color: #1f1f1f; + background-color: #191920; + border: 2px solid #333243; color: whitesmoke; padding: 10px; font-size: 18px; diff --git a/client/src/styles/game.css b/client/src/styles/game.css index c92930d..5577605 100644 --- a/client/src/styles/game.css +++ b/client/src/styles/game.css @@ -178,6 +178,7 @@ h1 { #role-info-modal #modal-button-container { margin-top: 1em; + justify-content: center; } #game-role-info-container .role-info-name { @@ -186,7 +187,7 @@ h1 { font-size: 20px; font-family: signika-negative, sans-serif; margin: 0.5em 0; - background-color: #15191c; + background-color: black; } #role-info-modal h2 { @@ -541,7 +542,15 @@ label[for='moderator'] { } .reveal-role-button { - background-color: #3f5256; + background-color: #586a6e; +} + +.reveal-role-button:hover, #mod-transfer-button:hover { + background-color: #4e5664; +} + +.kill-player-button:hover { + background-color: #b35c5c; } .reveal-role-button img { diff --git a/client/src/styles/home.css b/client/src/styles/home.css index ddf547d..a2b3e5f 100644 --- a/client/src/styles/home.css +++ b/client/src/styles/home.css @@ -1,5 +1,6 @@ html { - height: 100%; + background: rgb(0,0,0); + background: linear-gradient(180deg, rgba(0,0,0,1) 0%, rgb(17 18 18) 35%, rgba(27,31,31,1) 100%); } body { @@ -18,7 +19,7 @@ form { margin: 1em 0; padding: 10px; border-radius: 3px; - background-color: #1f1f1f; + background-color: black; justify-content: center; align-items: center; } @@ -70,7 +71,7 @@ form > div { #join-container > label { font-size: 35px; font-family: 'diavlo', sans-serif; - color: #ab2626; + color: #b1afcd; filter: drop-shadow(2px 2px 4px black); } diff --git a/client/src/styles/modal.css b/client/src/styles/modal.css index 28f7bd3..20b41e8 100644 --- a/client/src/styles/modal.css +++ b/client/src/styles/modal.css @@ -7,7 +7,7 @@ top: 50%; left: 50%; transform: translate(-50%, -50%); - background-color: #23282b; + background-color: #191920; align-items: center; justify-content: center; max-width: 25em; diff --git a/client/src/views/create.html b/client/src/views/create.html index 5f70e52..0db4447 100644 --- a/client/src/views/create.html +++ b/client/src/views/create.html @@ -42,7 +42,7 @@ diff --git a/manifest.json b/manifest.json index 13566cd..0e32c7b 100644 --- a/manifest.json +++ b/manifest.json @@ -18,6 +18,5 @@ "start_url": "/?source=pwa", "display": "fullscreen", "display_override": ["fullscreen", "standalone", "minimal-ui"], - "description": "A utility to deal Werewolf cards and run games in any setting, on any device." } diff --git a/package.json b/package.json index 76b9fad..c37d3f7 100644 --- a/package.json +++ b/package.json @@ -7,8 +7,8 @@ "bundle": "webpack --config client/webpack/webpack-prod.config.js", "prestart": "npm run bundle", "build:dev": "webpack --watch --config client/webpack/webpack-dev.config.js --mode=development", - "start:dev": "NODE_ENV=development node server/main.js", - "start:dev:windows": "SET NODE_ENV=development && node server/main.js", + "start:dev": "NODE_ENV=development nodemon server/main.js", + "start:dev:windows": "SET NODE_ENV=development && nodemon server/main.js", "start": "NODE_ENV=production node server/main.js -- loglevel=warn port=8080", "start:windows": "SET NODE_ENV=production && node server/main.js -- loglevel=warn port=8080", "test": "jasmine && node browsertest.js openBrowser socket", @@ -26,6 +26,7 @@ "@babel/preset-env": "^7.16.5", "acorn": "^8.6.0", "babel-loader": "^8.2.3", + "body-parser": "^1.19.1", "cors": "^2.8.5", "express": "^4.17.1", "express-force-https": "^1.0.0", @@ -38,5 +39,8 @@ "webpack-cli": "^4.9.1", "webpack-remove-debug": "^0.1.0" }, - "devDependencies": {} + "devDependencies": {}, + "nodemonConfig": { + "ignore": ["client/*", "node_modules/*"] + } } diff --git a/server/main.js b/server/main.js index fedfe26..4d4a4ab 100644 --- a/server/main.js +++ b/server/main.js @@ -1,114 +1,33 @@ const express = require('express'); -const http = require('http'); -const https = require('https'); const path = require('path'); -const fs = require('fs'); const app = express(); -const cors = require('cors') const bodyParser = require('body-parser'); const GameManager = require('./modules/GameManager.js'); const globals = require('./config/globals'); -// const QueueManager = require('./modules/managers/QueueManager'); +const ServerBootstrapper = require('./modules/ServerBootstrapper'); -app.use(bodyParser.json()); // to support JSON-encoded bodies -app.use(bodyParser.urlencoded({ // to support URL-encoded bodies +app.use(bodyParser.json()); +app.use(bodyParser.urlencoded({ extended: true })); -let main, environment; +const args = ServerBootstrapper.processCLIArgs(); -let args = Array.from(process.argv.map((arg) => arg.trim().toLowerCase())); +const logger = require('./modules/Logger')(args.logLevel); +logger.log('LOG LEVEL IS: ' + args.logLevel); -const localServer = args.includes('local'); -const useHttps = args.includes('https'); -const port = process.env.PORT || args - .filter((arg) => { - return /port=\d+/.test(arg); - }) - .map((arg) => { - return /port=(\d+)/.exec(arg)[1]; - })[0] || 5000; -const logLevel = process.env.LOG_LEVEL || args - .filter((arg) => { - return /loglevel=[a-zA-Z]+/.test(arg); - }) - .map((arg) => { - return /loglevel=([a-zA-Z]+)/.exec(arg)[1]; - })[0] || globals.LOG_LEVEL.INFO; +const main = ServerBootstrapper.createServerWithCorrectHTTPProtocol(app, args.useHttps, args.port, logger) -const logger = require('./modules/Logger')(logLevel); +app.set('port', args.port); -logger.log('LOG LEVEL IS: ' + logLevel) - -if (localServer) { - environment = globals.ENVIRONMENT.LOCAL; - logger.log('starting main in LOCAL mode.'); - if (useHttps && fs.existsSync(path.join(__dirname, '../client/certs/localhost-key.pem')) && fs.existsSync(path.join(__dirname, '../client/certs/localhost.pem'))) { - const key = fs.readFileSync(path.join(__dirname, '../client/certs/localhost-key.pem'), 'utf-8'); - const cert = fs.readFileSync(path.join(__dirname, '../client/certs/localhost.pem'), 'utf-8'); - logger.log('local certs detected. Using HTTPS.'); - main = https.createServer({ key, cert }, app); - logger.log(`navigate to https://localhost:${port}`); - } else { - logger.log('https not specified or no local certs detected. Using HTTP.'); - main = http.createServer(app); - logger.log(`navigate to http://localhost:${port}`); - } -} else { - environment = globals.ENVIRONMENT.PRODUCTION; - logger.warn('starting main in PRODUCTION mode. This should not be used for local development.'); - main = http.createServer(app); - const secure = require('express-force-https'); - app.use(secure); -} - -app.set('port', port); - -let io; - -if (process.env.NODE_ENV.trim() === 'development') { - const corsOptions = { - origin: "http://localhost:" + port, - optionsSuccessStatus: 200, - methods: ["GET", "POST"] - } - app.use(cors(corsOptions)); - io = require("socket.io")(main, { - cors: { - origin: "http://localhost:" + port, - methods: ["GET", "POST"], - allowedHeaders: ["Content-Type", "X-Requested-With", "Accept"], - credentials: false - } - }); -} else { - const corsOptions = { - origin: ["https://playwerewolf.uk.r.appspot.com"], - methods: ["GET", "POST"], - allowedHeaders: ["Content-Type", "X-Requested-With", "Accept"], - optionsSuccessStatus: 200, - } - app.use(cors(corsOptions)); - io = require("socket.io")(main, { - cors: { - origin: ["https://playwerewolf.uk.r.appspot.com", "wss://playwerewolf.uk.r.appspot.com"], - methods: ["GET", "POST"], - allowedHeaders: ["Content-Type", "X-Requested-With", "Accept"], - credentials: false - }, - transports: ["polling"] - }); -} - -const inGame = io.of('/in-game'); +const inGameSocketServer = ServerBootstrapper.createSocketServer(main, app, args.port); +inGameSocketServer.on('connection', function (socket) { + gameManager.addGameSocketHandlers(inGameSocketServer, socket); +}); /* Instantiate the singleton game manager */ -//const gameManager = new GameManager(logger, environment).getInstance(); -const gameManager = new GameManager(logger, globals.ENVIRONMENT.LOCAL).getInstance(); // temporary - -/* Instantiate the singleton queue manager */ -//const queueManager = new QueueManager(matchmaking, logger).getInstance(); +const gameManager = new GameManager(logger, globals.ENVIRONMENT.LOCAL).getInstance(); // temporarily use local environment configuration for game manager /* api endpoints */ const games = require('./api/GamesAPI'); @@ -126,26 +45,20 @@ app.use('/favicon.ico', (req, res) => { const router = require('./routes/router'); app.use('', router); -if (process.env.NODE_ENV.trim() === 'development') { - app.use('/dist', express.static(path.join(__dirname, '../client/dist'))); -} else if (process.env.NODE_ENV.trim() === 'production') { - app.use('/dist', express.static(path.join(__dirname, '../client/dist'))); -} +app.use('/dist', express.static(path.join(__dirname, '../client/dist'))); // set up routing for static content that isn't being bundled. app.use('/images', express.static(path.join(__dirname, '../client/src/images'))); app.use('/styles', express.static(path.join(__dirname, '../client/src/styles'))); app.use('/webfonts', express.static(path.join(__dirname, '../client/src/webfonts'))); - +app.use('/robots.txt', (req, res) => { + res.sendFile(path.join(__dirname, '../client/robots.txt')); +}); app.use(function (req, res) { res.sendFile(path.join(__dirname, '../client/src/views/404.html')); }); -inGame.on('connection', function (socket) { - gameManager.addGameSocketHandlers(inGame, socket); -}); - -main.listen(port, function () { - logger.log(`Starting server on port ${port}` ); +main.listen(args.port, function () { + logger.log(`Starting server on port ${args.port}` ); }); diff --git a/server/modules/ServerBootstrapper.js b/server/modules/ServerBootstrapper.js new file mode 100644 index 0000000..345fe3b --- /dev/null +++ b/server/modules/ServerBootstrapper.js @@ -0,0 +1,106 @@ +const LOG_LEVEL = require('../config/globals').LOG_LEVEL; +const http = require('http'); +const https = require('https'); +const path = require('path'); +const fs = require('fs'); +const cors = require('cors') + +const ServerBootstrapper = { + processCLIArgs: () => { + try { + let args = Array.from(process.argv.map((arg) => arg.trim().toLowerCase())); + const useHttps = args.includes('https'); + const port = process.env.PORT || args + .filter((arg) => { + return /port=\d+/.test(arg); + }) + .map((arg) => { + return /port=(\d+)/.exec(arg)[1]; + })[0] || 5000; + const logLevel = process.env.LOG_LEVEL || args + .filter((arg) => { + return /loglevel=[a-zA-Z]+/.test(arg); + }) + .map((arg) => { + return /loglevel=([a-zA-Z]+)/.exec(arg)[1]; + })[0] || LOG_LEVEL.INFO; + + return { + useHttps: useHttps, + port: port, + logLevel: logLevel + }; + } catch (e) { + throw new Error("Your server run command is malformed. Consult the codebase wiki for proper usage. Error: " + e); + } + }, + + createServerWithCorrectHTTPProtocol: (app, useHttps, port, logger) => { + let main; + if (process.env.NODE_ENV.trim() === 'development') { + logger.log('starting main in DEVELOPMENT mode.'); + if ( + useHttps + && fs.existsSync(path.join(__dirname, '../../client/certs/localhost-key.pem')) + && fs.existsSync(path.join(__dirname, '../../client/certs/localhost.pem')) + ) { + const key = fs.readFileSync(path.join(__dirname, '../../client/certs/localhost-key.pem'), 'utf-8'); + const cert = fs.readFileSync(path.join(__dirname, '../../client/certs/localhost.pem'), 'utf-8'); + logger.log('local certs detected. Using HTTPS.'); + main = https.createServer({ key, cert }, app); + logger.log(`navigate to https://localhost:${port}`); + } else { + logger.log('https not specified or no local certs detected. Certs should reside in /client/certs. Using HTTP.'); + main = http.createServer(app); + logger.log(`navigate to http://localhost:${port}`); + } + } else { + logger.warn('starting main in PRODUCTION mode. This should not be used for local development.'); + main = http.createServer(app); + app.use(require('express-force-https')); + } + + return main; + }, + + createSocketServer: (main, app, port) => { + let io; + if (process.env.NODE_ENV.trim() === 'development') { + const corsOptions = { + origin: "http://localhost:" + port, + optionsSuccessStatus: 200, + methods: ["GET", "POST"] + } + app.use(cors(corsOptions)); + io = require("socket.io")(main, { + cors: { + origin: "http://localhost:" + port, + methods: ["GET", "POST"], + allowedHeaders: ["Content-Type", "X-Requested-With", "Accept"], + credentials: false + } + }); + } else { + const corsOptions = { + origin: ["https://playwerewolf.uk.r.appspot.com"], + methods: ["GET", "POST"], + allowedHeaders: ["Content-Type", "X-Requested-With", "Accept"], + optionsSuccessStatus: 200, + } + app.use(cors(corsOptions)); + io = require("socket.io")(main, { + cors: { + origin: ["https://playwerewolf.uk.r.appspot.com", "wss://playwerewolf.uk.r.appspot.com"], + methods: ["GET", "POST"], + allowedHeaders: ["Content-Type", "X-Requested-With", "Accept"], + credentials: false + }, + transports: ["polling"] + }); + } + + return io.of('/in-game'); + } +} + +module.exports = ServerBootstrapper;