summaryrefslogtreecommitdiff
path: root/WebInterface
diff options
context:
space:
mode:
authorTrueKuehli <rctcoaster2000@hotmail.de>2018-10-01 14:15:05 +0200
committerTrueKuehli <rctcoaster2000@hotmail.de>2018-10-01 14:15:05 +0200
commit237e4d43229847bb69aadcfa6e6aca517128913b (patch)
treef36f0a1a1eec574c975d5a33fb6975b13bb457ba /WebInterface
parent4013f66c732841beaa55733af2b5b9a5efa25572 (diff)
Documented the code better and made some minor fixes
Diffstat (limited to 'WebInterface')
-rw-r--r--WebInterface/NodeJSServer/src/index.js6
-rw-r--r--WebInterface/NodeJSServer/src/modules/hash.js5
-rw-r--r--WebInterface/NodeJSServer/src/modules/server-client.js82
-rw-r--r--WebInterface/NodeJSServer/src/modules/ui/backdrop.js19
-rw-r--r--WebInterface/NodeJSServer/src/modules/ui/login-modal.js27
-rw-r--r--WebInterface/NodeJSServer/src/modules/ui/modal.js21
-rw-r--r--WebInterface/NodeJSServer/src/modules/ui/notification-banner.js42
-rw-r--r--WebInterface/NodeJSServer/src/modules/ui/server-listing.js14
8 files changed, 165 insertions, 51 deletions
diff --git a/WebInterface/NodeJSServer/src/index.js b/WebInterface/NodeJSServer/src/index.js
index a37ae5f..3ca0e39 100644
--- a/WebInterface/NodeJSServer/src/index.js
+++ b/WebInterface/NodeJSServer/src/index.js
@@ -1,7 +1,7 @@
import Backdrop from './modules/ui/backdrop.js';
import BannerController from './modules/ui/notification-banner.js';
-import ServerClient from './modules/server-client.js'
-import LoginModal from './modules/ui/login-modal.js'; // TODO: JUST FOR DEBUGGING
+import ServerClient from './modules/server-client.js';
+import LoginModal from './modules/ui/login-modal.js'; // TODO: JUST DEBUG
let backdrop = new Backdrop('menu', 'front-layer', 'show-menu');
backdrop.register();
@@ -16,4 +16,4 @@ document.getElementById('refresh-button')
new LoginModal('The Crew', client);
-window.client = client; //TODO: REMOVE, JUST FOR DEBUGGING
+window.client = client; // TODO: REMOVE, JUST FOR DEBUGGING
diff --git a/WebInterface/NodeJSServer/src/modules/hash.js b/WebInterface/NodeJSServer/src/modules/hash.js
index 826c8ee..3abcc21 100644
--- a/WebInterface/NodeJSServer/src/modules/hash.js
+++ b/WebInterface/NodeJSServer/src/modules/hash.js
@@ -1,3 +1,6 @@
+/**
+ * Creates Base64 String with SHA-256 Hash of given string
+ */
String.prototype.getHash = async function() {
let data = new ArrayBuffer(this.length * 2);
let bufferView = new Uint16Array(data);
@@ -14,4 +17,4 @@ String.prototype.getHash = async function() {
}
return btoa(base64String);
-}
+};
diff --git a/WebInterface/NodeJSServer/src/modules/server-client.js b/WebInterface/NodeJSServer/src/modules/server-client.js
index 0a257ba..ea37e1e 100644
--- a/WebInterface/NodeJSServer/src/modules/server-client.js
+++ b/WebInterface/NodeJSServer/src/modules/server-client.js
@@ -1,10 +1,20 @@
import * as signalR from '@aspnet/signalr';
import ServerListing from './ui/server-listing.js';
+/**
+ * Class for communication to server
+ */
export default class ServerClient {
+ /**
+ * Creates new connection
+ * @param {string} url URL of server running signalR
+ * @param {string} serverListingId HTML ID of server-listing element,
+ * to populate with available games
+ * @param {boolean} [debug=false] Enable debug output?
+ */
constructor(url, serverListingId, debug = false) {
const connectionBuilder = new signalR.HubConnectionBuilder()
- .withUrl(url)
+ .withUrl(url);
if (debug) {
connectionBuilder.configureLogging(signalR.LogLevel.Debug);
@@ -14,20 +24,25 @@ export default class ServerClient {
this.connection = connectionBuilder.build();
this.connection.start()
- .then(() => this.loadServers())
- .catch(() => err => console.error(err.toString()));
+ .then(() => this.loadServers()) // Load games list, once connected
+ .catch((err) => console.error(err.toString()));
+ // Initialize refreshing (blocks new refreshes if true)
this.refreshing = false;
this.serverListing = new ServerListing(serverListingId);
- this.messageHandling(); //TODO: REMOVE, JUST FOR DEBUGGING
+ this.messageHandling();
}
+ /**
+ * Requests list of avalable games on the server
+ */
loadServers() {
- if (this.refreshing) return;
+ if (this.refreshing) return; // If already refreshing, no new request
+
this.connection.on('ListGroups', (groups) => {
- console.log(groups)
+ // Populate server listing
this.serverListing.flushElements();
this.serverListing.addElements(groups);
this.connection.off('ListGroups');
@@ -36,39 +51,54 @@ export default class ServerClient {
});
this.connection.invoke('GetGroups')
- .catch(err => {
+ .catch((err) => {
this.refreshing = false;
- console.error(err.toString())
+ console.error(err.toString());
});
this.refreshing = true;
}
- createServer(){
+ /**
+ * Sends a game creating request to the server
+ * @param {string} name Name of the new game
+ * @param {string} password Password
+ */
+ createServer(name, password) {
// TODO: Create
}
- sendLogin(group, password, username){
+ /**
+ * Sends a login request
+ * @param {string} group Group name to join
+ * @param {string} password Password to send as SHA-256 Base64 String
+ * @param {string} username Display name to use
+ * @param {ServerClient~loginCallback} callback Callback function to use
+ */
+ sendLogin(group, password, username, callback) {
+ this.connection.on('LoginResponse', (result) => {
+ callback(result);
+ this.connection.off('LoginResponse');
+ });
this.connection.invoke('Login', group, username, password);
}
- messageHandling(){
+ /**
+ * Registers message handling
+ */
+ messageHandling() {
this.connection.on('ReceiveMessage', (user, message) => {
- let msg = message.replace(/&/g, "&amp;")
- .replace(/</g, "&lt;")
- .replace(/>/g, "&gt;");
- let encodedMsg = user + " sagt: " + msg;
- console.log(encodedMsg); //TODO: REMOVE, JUST FOR DEBUGGING
+ let msg = message.replace(/&/g, '&amp;')
+ .replace(/</g, '&lt;')
+ .replace(/>/g, '&gt;');
+ let encodedMsg = user + ' sagt: ' + msg;
+ console.log(encodedMsg); // TODO: REMOVE, JUST FOR DEBUGGING
});
}
}
-
-
-// connection.on('ReceiveMessage', (user, message) => {
-// let msg = message.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
-// let encodedMsg = user + " says " + msg;
-// let li = document.createElement("div");
-// li.classList.add('server');
-// li.textContent = encodedMsg;
-// document.getElementById('server-list').appendChild(li);
-// });
+/**
+ * Callback to call with response to login request
+ * @callback ServerClient~loginCallback
+ * @param {number} result 0: Success, 1: PasswordError, 2:UsernameTaken
+ * , 3:Unknown Error
+ */
diff --git a/WebInterface/NodeJSServer/src/modules/ui/backdrop.js b/WebInterface/NodeJSServer/src/modules/ui/backdrop.js
index 243bbb3..1a24bd2 100644
--- a/WebInterface/NodeJSServer/src/modules/ui/backdrop.js
+++ b/WebInterface/NodeJSServer/src/modules/ui/backdrop.js
@@ -1,18 +1,32 @@
// Showing / Hiding the backdrop menu
+/**
+ * Class for adding functionality to backdrop elements
+ */
export default class Backdrop {
+ /**
+ * Registers all important elements in the backdrop
+ * @param {string} backdropMenu ID of Backdrop Menu
+ * @param {string} frontLayer ID of Front Layer
+ * @param {string} menuButton ID of Show / Hide Menu Button
+ */
constructor(backdropMenu, frontLayer, menuButton) {
this.backdrop = document.getElementById(backdropMenu);
this.frontLayer = document.getElementById(frontLayer);
this.menuButton = document.getElementById(menuButton);
}
-
+ /**
+ * Registers all neccessary events
+ */
register() {
this.registerButtonEvent();
this.registerFrontLayerEvent();
}
+ /**
+ * Registers showing / hiding through menu button
+ */
registerButtonEvent() {
this.menuButton.addEventListener('click', () => {
// Hide / Unhide Backdrop Menu
@@ -31,6 +45,9 @@ export default class Backdrop {
});
}
+ /**
+ * Registers hiding, when clicking on the front layer
+ */
registerFrontLayerEvent() {
// Hide menu when interacting with front layer
this.frontLayer.addEventListener('click', () => {
diff --git a/WebInterface/NodeJSServer/src/modules/ui/login-modal.js b/WebInterface/NodeJSServer/src/modules/ui/login-modal.js
index cb1f2ac..4c7b872 100644
--- a/WebInterface/NodeJSServer/src/modules/ui/login-modal.js
+++ b/WebInterface/NodeJSServer/src/modules/ui/login-modal.js
@@ -1,7 +1,17 @@
import Modal from './modal.js';
import '../hash.js';
+/**
+ * Class to implement a login modal from the parent modal class
+ */
export default class LoginModal extends Modal {
+ /**
+ * Creates necessary elements for login modal
+ * @param {string} serverName Name of the server, used for login and displayed
+ * in title
+ * @param {ServerClient} serverClient Server client object used to send the
+ * login
+ */
constructor(serverName, serverClient) {
super(serverName);
this.serverName = serverName;
@@ -15,7 +25,7 @@ export default class LoginModal extends Modal {
let passwordInput = document.createElement('input');
passwordLabel.setAttribute('for', 'password-input');
passwordLabel.textContent = 'Passwort:';
- passwordLabel.title = 'Das Passwort des Spiels'
+ passwordLabel.title = 'Das Passwort des Spiels';
passwordInput.id = 'password-input';
passwordInput.type = 'password';
passwordInput.placeholder = 'Passwort';
@@ -24,7 +34,7 @@ export default class LoginModal extends Modal {
let nameInput = document.createElement('input');
nameLabel.setAttribute('for', 'name-input');
nameLabel.textContent = 'Benutzername:';
- nameLabel.title = 'Dein Anzeigename'
+ nameLabel.title = 'Dein Anzeigename';
nameInput.id = 'name-input';
nameInput.type = 'text';
nameInput.autocomplete = 'on';
@@ -53,15 +63,22 @@ export default class LoginModal extends Modal {
this.registerLoginBtn();
}
+ /**
+ * Registers event to send login, on button press
+ */
registerLoginBtn() {
- this.loginButton.addEventListener('click', () => {
- console.log('button pressed')
+ let eventListener = () => {
+ this.loginButton.removeEventListener('click', eventListener);
let userName = this.nameInput.value;
this.passwordInput.value.getHash()
.then((result) => {
this.serverClient.sendLogin(this.serverName, result, userName);
+
+ // TODO: Wait for response, if error keep window intact,
+ // and reenable event listener
this.close();
});
- });
+ };
+ this.loginButton.addEventListener('click', eventListener);
}
}
diff --git a/WebInterface/NodeJSServer/src/modules/ui/modal.js b/WebInterface/NodeJSServer/src/modules/ui/modal.js
index 55e38bd..10a1be5 100644
--- a/WebInterface/NodeJSServer/src/modules/ui/modal.js
+++ b/WebInterface/NodeJSServer/src/modules/ui/modal.js
@@ -1,4 +1,12 @@
+/**
+ * Parent class to create Modals on the screen
+ * Contains no content, as that is implemented by child classes
+ */
export default class Modal {
+ /**
+ * Creates a new modal with a title and empty content
+ * @param {string} titleString Title to show at the top of the modal
+ */
constructor(titleString) {
let modalBackground = document.createElement('div');
let modal = document.createElement('div');
@@ -8,7 +16,7 @@ export default class Modal {
modalBackground.className = 'modal-container';
modal.className = 'modal';
title.className = 'modal-title';
- body.className = 'modal-body'
+ body.className = 'modal-body';
title.textContent = titleString;
@@ -25,6 +33,10 @@ export default class Modal {
this.registerEvents();
}
+ /**
+ * Register event to close if clicked outside of modal
+ * Clicking on the modal itself should not close it though
+ */
registerEvents() {
this.modal.addEventListener('click', (e) => {
e.stopPropagation();
@@ -35,6 +47,9 @@ export default class Modal {
});
}
+ /**
+ * Fades modal out and removes it from the flow of the document
+ */
close() {
this.bg.classList.add('hidden');
this.bg.addEventListener('transitionend', () => {
@@ -42,6 +57,10 @@ export default class Modal {
});
}
+ /**
+ * Puts text in the body
+ * @param {string} text Text to put into the body
+ */
setBodyText(text) {
this.body.textContent = text;
}
diff --git a/WebInterface/NodeJSServer/src/modules/ui/notification-banner.js b/WebInterface/NodeJSServer/src/modules/ui/notification-banner.js
index d14845e..395db94 100644
--- a/WebInterface/NodeJSServer/src/modules/ui/notification-banner.js
+++ b/WebInterface/NodeJSServer/src/modules/ui/notification-banner.js
@@ -1,4 +1,13 @@
+/**
+ * Class for controlling the Notification banner
+ */
export default class BannerController {
+ /**
+ * Creates references to objects and hides notification banner
+ * @param {string} bannerId ID of Notification Banner
+ * @param {string} textP ID of Notification Banner text field
+ * @param {string} dismissBtn ID of dismiss button
+ */
constructor(bannerId, textP, dismissBtn) {
this.banner = document.getElementById(bannerId);
this.bannerText = document.getElementById(textP);
@@ -9,12 +18,20 @@ export default class BannerController {
this.banner.classList.add('hidden');
}
+ /**
+ * Registers dismissing via the dismiss button
+ */
register() {
this.dismissBtn.addEventListener('click', () => {
this.dismissCurrent();
});
}
+ /**
+ * Pushes a new message to the notification banner and shows it
+ * @param {string} name Name to register notification (referenced in hide)
+ * @param {string} text Notification text
+ */
show(name, text) {
let bannerItem = {name, text, 'html': false};
this.bannerMsgs.push(bannerItem);
@@ -22,6 +39,10 @@ export default class BannerController {
this.update();
}
+ /**
+ * Removes notification from banner
+ * @param {string} name Name, that the notification was registered under
+ */
hide(name) {
if (!name) {
this.bannerMsgs = [];
@@ -37,11 +58,18 @@ export default class BannerController {
}
}
+ /**
+ * Dismisses the currently shown message
+ */
dismissCurrent() {
this.hide(this.current);
}
+ /**
+ * Updates the notification banner with the most recent message
+ */
update() {
+ // TODO: Show if multiple messages are there
if (this.bannerMsgs.length === 0) {
this.banner.classList.add('hidden');
return;
@@ -58,18 +86,4 @@ export default class BannerController {
this.current = name;
}
-
- showPersistence() {
- let text = `Storage persistence is disabled, so in-browser storage of created Wikis might not work.\n` +
- `Click <a href="#" onclick="
- event.preventDefault();
- navigator.storage.persist().then((persistent) => {
- if (persistent) notificationManager.show('storageSuccess', 'Storage persistence successfully turned on.');
- else notificationManager.show('storageFail', 'Storage persistence has been rejected.');
- });
- ">here</a> to enable storage persistence.`;
- let bannerItem = {'name': 'persistence', text, 'html': true};
- this.bannerMsgs.push(bannerItem);
- this.update();
- }
}
diff --git a/WebInterface/NodeJSServer/src/modules/ui/server-listing.js b/WebInterface/NodeJSServer/src/modules/ui/server-listing.js
index 2c501fd..0069ac6 100644
--- a/WebInterface/NodeJSServer/src/modules/ui/server-listing.js
+++ b/WebInterface/NodeJSServer/src/modules/ui/server-listing.js
@@ -1,12 +1,26 @@
+/**
+ * Class for handling the server list
+ */
export default class ServerListing {
+ /**
+ * Creates reference to container
+ * @param {string} serverListId ID of the server list div
+ */
constructor(serverListId) {
this.serverListing = document.getElementById(serverListId);
}
+ /**
+ * Removes all elements currently in the server listing
+ */
flushElements() {
this.serverListing.innerHTML = '';
}
+ /**
+ * Populates servers from a given array of games
+ * @param {array} array Array of available games
+ */
addElements(array) {
for (let server of array) {
const name = server['name'];