site has login box and displays list of games
authorGeoffrey Allott <geoffrey@allott.email>
Sat, 6 Feb 2021 00:32:04 +0000 (00:32 +0000)
committerGeoffrey Allott <geoffrey@allott.email>
Sat, 6 Feb 2021 00:32:04 +0000 (00:32 +0000)
site/index.html
site/main.js
site/modules/auth.js [new file with mode: 0644]
site/modules/socket.js [new file with mode: 0644]
site/style.css [new file with mode: 0644]

index da7e8f79fcc87410e9f4f93ba21fa2812dad8c40..5dee3ab6aa64da1975c239659c69f2c4061733c9 100644 (file)
@@ -2,9 +2,48 @@
 <html>
     <head>
         <meta charset="utf-8" />
-        <script src="main.js"></script>
+        <link rel="stylesheet" href="./style.css" />
+        <script type="module" src="main.js"></script>
     </head>
     <body>
-        <h1>Pokerwave</h1>
+        <div id="login-background">
+            <div id="login">
+                <label id="username-label" for="username">username</label>
+                <input id="username-input" />
+                <label id="password-label" for="password">password</label>
+                <input id="password-input" type="password" />
+                <button id="login-button">Sign In</button>
+                <p id="login-error"></p>
+            </div>
+        </div>
+        <div id="game-tile-background">
+            <!--<div class="game-list">
+                <div class="game-summary">
+                    <div class="game-id">#2</div>
+                    <div class="game-title">Poker chat</div>
+                    <div class="stub"></div>
+                    <div class="game-format">Chatroom</div>
+                    <ul class="game-settings">
+                        <li>max_players: 4</li>
+                    </ul>
+                </div>
+                <div class="game-summary">
+                    <div class="game-id">#1</div>
+                    <div class="game-title">General discussion</div>
+                    <div class="game-format">Chatroom</div>
+                    <ul class="game-settings">
+                        <li>max_players: 8</li>
+                    </ul>
+                </div>
+                <div class="game-summary">
+                    <div class="game-id">#0</div>
+                    <div class="game-title">Test chatroom</div>
+                    <div class="game-format">Chatroom</div>
+                    <ul class="game-settings">
+                        <li>max_players: 2</li>
+                    </ul>
+                </div>
+            </div>-->
+        </div>
     </body>
 </html>
index a99a9ffc2bbfc5f57487094bf09c6458fc70b983..662230a04052cc309a17e6ccbabf81906adff9be 100644 (file)
@@ -1,35 +1,38 @@
-"use strict";
+import { Auth } from "./modules/auth.js";
+import { Socket } from "./modules/socket.js";
 
-var socket;
+var sockets = [];
 
-function socket_open() {
-    let proto = window.location.protocol === "https:" ? "wss:" : "ws:";
-    let uri = proto + "//" + window.location.host + "/api";
-    socket = new WebSocket(uri);
-    socket.onopen = socket_onopen;
-    socket.onmessage = socket_onmessage;
+function hide_login() {
+    document.getElementById("login-background").classList.add("hidden");
 }
 
-function socket_onopen() {
-    console.log("WebSocket connected");
-    socket_send({type: "Login", username: "geoff"});
-}
-
-function socket_send(object) {
-    console.log(">>", object);
-    socket.send(JSON.stringify(object));
+function show_login(error) {
+    if (error) {
+        document.getElementById("login-error").classList.remove("hidden");
+        document.getElementById("login-error").innerText = error;
+    } else {
+        document.getElementById("login-error").classList.add("hidden");
+        document.getElementById("login-error").innerText = "";
+    }
+    document.getElementById("login-background").classList.remove("hidden");
+    document.getElementById("login-button").onclick = login;
+    document.getElementById("password-input").onchange = login;
 }
 
-function socket_onmessage(msg) {
-    var message = JSON.parse(msg.data);
-    console.log("<<", message);
-    switch (message.type) {
-        case "LoginAuthChallenge":
-            socket_send({type: "LoginAuthResponse", signature: "hunter2"});
-            break;
+function login() {
+    var username = document.getElementById("username-input").value;
+    var password = document.getElementById("password-input").value;
+    delete document.getElementById("login-button").onclick;
+    delete document.getElementById("password-input").onchange;
+    var auth = new Auth(username, password);
+    for (var socket of sockets) {
+        socket.login(auth);
     }
 }
 
 window.onload = function() {
-    socket_open();
+    var container = document.getElementById("game-tile-background");
+    sockets.push(new Socket(container));
+    show_login();
 };
diff --git a/site/modules/auth.js b/site/modules/auth.js
new file mode 100644 (file)
index 0000000..0a6d7cb
--- /dev/null
@@ -0,0 +1,20 @@
+export class Auth {
+    constructor(username, password) {
+        this.username = username;
+        this.password = password;
+    }
+
+    login_message() {
+        return {
+            type: "Login",
+            username: this.username
+        };
+    }
+
+    challenge_response(challenge) {
+        return {
+            type: "LoginAuthResponse",
+            signature: this.password
+        };
+    }
+}
diff --git a/site/modules/socket.js b/site/modules/socket.js
new file mode 100644 (file)
index 0000000..342677f
--- /dev/null
@@ -0,0 +1,134 @@
+export class Socket {
+    constructor(container) {
+        this.container = container;
+        let proto = window.location.protocol === "https:" ? "wss:" : "ws:";
+        let uri = proto + "//" + window.location.host + "/api";
+        this.socket = new WebSocket(uri);
+        this.socket.onopen = this.onopen.bind(this);
+        this.socket.onmessage = this.onmessage.bind(this);
+        this.socket.onclose = this.onclose.bind(this);
+        this.state = "Connecting";
+    }
+
+    onopen() {
+        console.log("WebSocket connected");
+        this.state = "Connected";
+    }
+
+    send(object) {
+        console.log(">>", object);
+        this.socket.send(JSON.stringify(object));
+    }
+
+    login(auth) {
+        this.auth = auth;
+        this.send(auth.login_message());
+        this.state = "LoginSent";
+    }
+
+    onmessage(msg) {
+        var message = JSON.parse(msg.data);
+        console.log("<<", message);
+        switch (message.type) {
+            case "LoginAuthChallenge":
+                this.send(this.auth.challenge_response(message.challenge));
+                this.state = "LoginAuthResponseSent";
+                break;
+            case "LoginFailure":
+                this.auth = null;
+                this.show_login(message.reason);
+                this.state = "Connected";
+                break;
+            case "LoginSuccess":
+                this.hide_login();
+                this.send({type: "JoinLobby", filter: ""});
+                this.state = "JoinLobbySent";
+                break;
+            case "JoinLobbySuccess":
+                this.create_game_list();
+                this.games = message.games;
+                this.redraw_games();
+                this.state = "InLobby";
+                break;
+            case "AddGame":
+                this.add_game(message.game);
+                break;
+            case "LogoutSuccess":
+                this.auth = null;
+                this.show_login();
+                this.state = "Connected";
+                break;
+        }
+    }
+
+    hide_login() {
+        document.getElementById("login-background").classList.add("hidden");
+    }
+
+    show_login(error) {
+        if (error) {
+            document.getElementById("login-error").classList.remove("hidden");
+            document.getElementById("login-error").innerText = error;
+        } else {
+            document.getElementById("login-error").classList.add("hidden");
+            document.getElementById("login-error").innerText = "";
+        }
+        document.getElementById("login-background").classList.remove("hidden");
+        document.getElementById("login-button").onclick = login;
+        document.getElementById("password-input").onchange = login;
+    }
+
+    game_element(game) {
+        console.log("getting game element for ", game);
+        var game_element = document.createElement("div");
+        game_element.classList.add("game-summary");
+        var id = document.createElement("div");
+        id.innerText = "#" + game.id;
+        id.classList.add("game-id");
+        game_element.appendChild(id);
+        var title = document.createElement("div");
+        title.innerText = game.settings.format; // TODO
+        title.classList.add("game-title");
+        game_element.appendChild(title);
+        var format = document.createElement("div");
+        format.innerText = game.settings.format;
+        format.classList.add("game-format");
+        game_element.appendChild(format);
+        var settings = document.createElement("ul");
+        settings.classList.add("game-settings");
+        for (var setting of Object.keys(game.settings)) {
+            if (setting !== "id" && setting !== "title" && setting !== "format") {
+                var li = document.createElement("li");
+                li.innerText = setting + ": " + game.settings[setting];
+                settings.appendChild(li);
+            }
+        }
+        game_element.appendChild(settings);
+        return game_element;
+    }
+
+    add_game(game) {
+        this.games.push(game);
+        var game_element = this.game_element(game);
+        this.game_list.prepend(game_element);
+    }
+
+    create_game_list() {
+        this.container.textContent = "";
+        this.game_list = document.createElement("div");
+        this.game_list.classList.add("game-list");
+        this.container.append(this.game_list);
+    }
+
+    redraw_games() {
+        for (var game of this.games) {
+            var game_element = this.game_element(game);
+            this.game_list.prepend(game_element);
+        }
+    }
+
+    onclose() {
+        console.error("Websocket closed unexpectedly");
+        this.state = "Disconnected";
+    }
+}
diff --git a/site/style.css b/site/style.css
new file mode 100644 (file)
index 0000000..3d9d22a
--- /dev/null
@@ -0,0 +1,96 @@
+html, body {
+    width: 100%;
+    height: 100%;
+    margin: 0;
+}
+
+.hidden {
+    display: none !important;
+}
+
+#login-background {
+    background-color: rgba(0, 0, 100, 0.5);
+    width: 100%;
+    height: 100%;
+    position: fixed;
+    display: grid;
+    grid: 1fr 1fr 1fr / 1fr 1fr 1fr;
+}
+
+#login {
+    grid-column: 2 / 3;
+    grid-row: 2 / 3;
+    background-color: skyblue;
+    border-radius: 2vmax;
+    padding: 4vmax;
+    display: grid;
+    grid: 1fr;
+    font-size: 4vmax;
+}
+
+#login > label {
+    font-family: monospace;
+}
+
+#login > input {
+    font-size: inherit;
+    margin-bottom: 1vmax;
+}
+
+#login > button {
+    font-size: inherit;
+    margin-top: 2vmax;
+}
+
+#login > #login-error {
+    font-size: 2vmax;
+    color: red;
+    margin-bottom: 0;
+}
+
+#game-tile-background {
+    width: 100%;
+    height: 100%;
+    display: grid;
+    grid: 1fr / 1fr;
+}
+
+.game-list {
+    width: 100%;
+    display: grid;
+    grid-auto-rows: 30vw;
+}
+
+.game-summary {
+    border: 1px solid grey;
+    border-bottom: none;
+    font-family: sans;
+    font-size: 4vw;
+    display: grid;
+    grid: 'id title blank'
+          'format format format'
+          'settings settings settings'
+          'settings settings settings';
+}
+
+.game-id {
+    font-style: italic;
+    color: grey;
+    grid-area: id;
+}
+
+.game-title {
+    text-align: center;
+    font-weight: bold;
+    grid-area: title;
+}
+
+.game-format {
+    text-align: left;
+    margin-left: 5vw;
+    grid-area: format;
+}
+
+.game-settings {
+    grid-area: settings;
+}