1
0

Routing works between webpack and app, game loading works, new game creation works

Signed-off-by: James Ketrenos <james.p.ketrenos@intel.com>
This commit is contained in:
James Ketrenos 2020-04-22 09:57:28 -07:00
parent 15b2c67fa6
commit 41e7ef9aa0
11 changed files with 85 additions and 28 deletions

View File

@ -5,6 +5,7 @@
name="viewport"
content="minimum-scale=1, initial-scale=1, width=device-width"
/>
<script>'<base href="BASEPATH">';</script>
<link rel="icon" href="../assets/favicon-32.png" sizes="32x32">
<link rel="icon" href="../assets/favicon-57.png" sizes="57x57">
<link rel="icon" href="../assets/favicon-76.png" sizes="76x76">

View File

@ -10,19 +10,14 @@ const express = require("express"),
config = require("config"),
session = require('express-session'),
hb = require("handlebars"),
SQLiteStore = require('connect-sqlite3')(session);
SQLiteStore = require('connect-sqlite3')(session),
basePath = require("./basepath");
require("./console-line.js"); /* Monkey-patch console.log with line numbers */
const frontendPath = config.get("frontendPath").replace(/\/$/, "") + "/",
serverConfig = config.get("server");
let basePath = config.get("basePath");
basePath = "/" + basePath.replace(/^\/+/, "").replace(/\/+$/, "") + "/";
if (basePath == "//") {
basePath = "/";
}
console.log("Hosting server from: " + basePath);
let userDB, gameDB;
@ -231,6 +226,8 @@ app.use(basePath, function(req, res, next) {
/* Allow loading of the app w/out being logged in */
app.use(basePath, index);
/* /games loads the default index */
app.use(basePath + "games", index);
/* Allow access to the 'users' API w/out being logged in */
const users = require("./routes/users");

9
server/basepath.js Executable file
View File

@ -0,0 +1,9 @@
const config = require("config");
let basePath = config.get("basePath");
basePath = "/" + basePath.replace(/^\/+/, "").replace(/\/+$/, "") + "/";
if (basePath == "//") {
basePath = "/";
}
module.exports = basePath;

2
server/console-line.js Normal file → Executable file
View File

@ -15,7 +15,7 @@ if (process.env.LOG_LINE) {
}
let err = getErrorObject(),
caller_line = err.stack.split("\n")[4],
caller_line = err.stack.split("\n")[3],
args = [caller_line.replace(cwdRe, "$1 -")];
/* arguments.unshift() doesn't exist... */

0
server/mail.js Normal file → Executable file
View File

View File

@ -100,7 +100,7 @@ for (let i = 0; i < 5; i++) {
const games = {};
router.get("/:id", (req, res/*, next*/) => {
console.log("GET /" + req.params.id);
console.log("GET games/" + req.params.id);
if (req.params.id in games) {
return res.status(200).send(games[req.params.id]);
} else {
@ -110,7 +110,7 @@ router.get("/:id", (req, res/*, next*/) => {
});
router.post("/", (req, res/*, next*/) => {
console.log("POST /");
console.log("POST games/");
const game = {
startTime: Date.now(),
tiles: [],
@ -150,6 +150,7 @@ router.post("/", (req, res/*, next*/) => {
games[game.id] = game;
console.log(`New game created: ${game.id}`);
return res.status(200).send(game);
});

View File

@ -3,7 +3,8 @@
const express = require("express"),
fs = require("fs"),
url = require("url"),
config = require("config");
config = require("config"),
basePath = require("../basepath");
const router = express.Router();
@ -31,24 +32,24 @@ const extensionMatch = new RegExp("^.*?(" + extensions.join("|") + ")$", "i");
* dynamic client side route and *then* return index.html.
*/
router.get("/*", function(req, res, next) {
const parts = url.parse(req.url),
basePath = req.app.get("basePath");
const parts = url.parse(req.url);
/* If req.user isn't set yet (authentication hasn't happened) then
* only allow / to be loaded--everything else chains to the next
* handler */
if (!req.user && req.url != "/") {
if (!req.user &&
req.url != "/" &&
req.url.indexOf("/games") != 0) {
return next();
}
if (req.url == "/" || !extensionMatch.exec(parts.pathname)) {
if (req.url == "/" || req.url.indexOf("/games") == 0 || !extensionMatch.exec(parts.pathname)) {
console.log("Returning index for " + req.url);
/* Replace <script>'<base href="/BASEPATH/">';</script> in index.html with
/* Replace <script>'<base href="BASEPATH">';</script> in index.html with
* the basePath */
const frontendPath = config.get("frontendPath").replace(/\/$/, "") + "/",
index = fs.readFileSync(frontendPath + "/index.html", "utf8");
index = fs.readFileSync(frontendPath + "index.html", "utf8");
res.send(index.replace(
/<script>'<base href="BASEPATH">';<\/script>/,
"<base href='" + basePath + "'>"));

View File

@ -11,13 +11,20 @@ import AppBar from '@material-ui/core/AppBar';
import Box from '@material-ui/core/Box';
import Toolbar from '@material-ui/core/Toolbar';
import { makeStyles } from '@material-ui/core/styles';
import { Router, Route } from "react-router-dom";
//import 'typeface-roboto';
import history from "./history.js";
import Board from "./Board.js";
import "./App.css";
function App() {
let base = document.querySelector("base") ? document.querySelector("base").href : "";
if (base) {
base = new URL(base).pathname;
}
console.log(`Base: ${base}`);
return (
<React.Fragment>
<AppBar position="fixed">
@ -25,7 +32,10 @@ function App() {
<Button color="inherit">Login</Button>
</Toolbar>
</AppBar>
<Board/>
<Router history={history}>
<Route exact path={base + 'games/:id?'} component={Board}/>
<Route exact path={base} component={Board}/>
</Router>
</React.Fragment>
);
}

View File

@ -1,5 +1,6 @@
import React, { useState, useEffect } from "react";
import "./Board.css";
import history from "./history.js";
const hexagonRatio = 1.1547005,
tileHeight = 0.16,
@ -195,8 +196,20 @@ class Board extends React.Component {
this.mouse = { x: 0, y: 0 };
this.radius = 0.317;
window.fetch("api/v1/games", {
method: 'POST',
const params = {}
if (props.match.params.id) {
console.log(`Loading game: ${props.match.params.id}`);
params.url = `api/v1/games/${props.match.params.id}`;
params.method = "GET"
} else {
console.log("Requesting new game.");
params.url = "api/v1/games";
params.method = "POST";
}
window.fetch(params.url, {
method: params.method,
cache: 'no-cache',
credentials: 'same-origin',
headers: {
@ -204,9 +217,17 @@ class Board extends React.Component {
},
// body: JSON.stringify(data) // body data type must match "Content-Type" header
}).then((res) => {
if (res.status > 400) {
throw `Unable to load game ${props.match.params.id}`;
}
return res.json();
}).then((game) => {
console.log(JSON.stringify(game, null, 2));
console.log (`Game ${game.id} loaded.`);
if (!props.match.params.id) {
history.push(`games/${game.id}`);
}
this.game = game;
this.pips = Pips(this);
this.tiles = Tiles(this);
@ -225,6 +246,7 @@ class Board extends React.Component {
});
}).catch((error) => {
console.error(error);
alert(error);
});
}
@ -395,7 +417,7 @@ class Board extends React.Component {
}
drawFrame() {
if (!this.canvas) {
if (!this.canvas || !this.table) {
return;
}

11
src/history.js Executable file
View File

@ -0,0 +1,11 @@
import { createBrowserHistory } from 'history';
// Run our app under the /base URL.
const history = createBrowserHistory(),
push = history.push;
history.push = (path) => {
const base = new URL(document.querySelector("base") ? document.querySelector("base").href : "");
push(base.pathname + path);
};
export default history;

15
webpack.dev.js Normal file → Executable file
View File

@ -9,18 +9,23 @@ const proxy = {
// "/photos/api/*": "http://localhost:8123/",
}
console.log(`Using base: ${base}`);
proxy[`${base}/`] = {
target: "http://localhost:8911",
bypass: function(req, res, proxyOptions) {
console.log(req.url);
if (req.url.match(new RegExp(base.replace(/\//g, "\\/") + "\/identities[/?]?"))) {
return 'index.html';
} else {
return null;
console.log(`Proxy test: ${req.url}`);
if ((req.url.indexOf(`${base}/assets`) == 0) ||
(req.url.indexOf(`${base}/dist`) == 0)) {
return req.url.replace(base, "");
}
console.log(`Proxying to backend server: ${req.url}`);
return null;
}
};
/* https://webpack.js.org/configuration/dev-server/ */
module.exports = merge(common, {
mode: "development",
devServer: {