Extract login pages to own files
Fix api Remove login window
This commit is contained in:
parent
fe429ea7d5
commit
213bb1c179
@ -6,13 +6,25 @@ const apiPath = "/schafkopf"
|
|||||||
|
|
||||||
var useEnglishTexts = false
|
var useEnglishTexts = false
|
||||||
|
|
||||||
|
const headerKeyPassword = "password";
|
||||||
|
const headerKeyToken = "token";
|
||||||
|
const headerKeyName = "name";
|
||||||
|
const headerKeyMail = "email";
|
||||||
|
|
||||||
function webSocketPath() {
|
function webSocketPath() {
|
||||||
const prefix = (window.location.protocol === "https:") ? "wss://" : "ws://"
|
const prefix = (window.location.protocol === "https:") ? "wss://" : "ws://"
|
||||||
return prefix + window.location.host + apiPath + "/session/start"
|
return prefix + window.location.host + apiPath + "/session/start"
|
||||||
}
|
}
|
||||||
|
|
||||||
async function performRegisterPlayerRequest(name, password) {
|
async function performRegisterPlayerRequest(name, password, email) {
|
||||||
return fetch(apiPath + "/player/register/" + name, { method: 'POST', body: password })
|
return fetch(apiPath + "/player/register", {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
[headerKeyName]: name,
|
||||||
|
[headerKeyPassword]: password,
|
||||||
|
[headerKeyMail]: email
|
||||||
|
}
|
||||||
|
})
|
||||||
.then(convertServerResponse)
|
.then(convertServerResponse)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,6 +56,22 @@ async function performGetCurrentTableRequest(token) {
|
|||||||
.then(convertJsonResponse)
|
.then(convertJsonResponse)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function performRecoveryEmailRequest(name) {
|
||||||
|
return fetch(apiPath + "/player/password/reset", {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { [headerKeyName] : name },
|
||||||
|
})
|
||||||
|
.then(convertServerResponse)
|
||||||
|
}
|
||||||
|
|
||||||
|
async function performResetPasswordRequest(token, password) {
|
||||||
|
return fetch(apiPath + "/player/reset", {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { [headerKeyPassword] : password, [headerKeyToken] : token }
|
||||||
|
})
|
||||||
|
.then(convertServerResponse)
|
||||||
|
}
|
||||||
|
|
||||||
async function performCreateTableRequest(token, name, visibility) {
|
async function performCreateTableRequest(token, name, visibility) {
|
||||||
const vis = visibility ? "public" : "private";
|
const vis = visibility ? "public" : "private";
|
||||||
return fetch(apiPath + "/table/create/" + vis + "/" + name, { method: 'POST', body: token })
|
return fetch(apiPath + "/table/create/" + vis + "/" + name, { method: 'POST', body: token })
|
||||||
@ -160,4 +188,4 @@ function convertStateToString(state) {
|
|||||||
default:
|
default:
|
||||||
return state
|
return state
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,14 +4,11 @@
|
|||||||
|
|
||||||
var playerName = ""
|
var playerName = ""
|
||||||
var debugSessionToken = null
|
var debugSessionToken = null
|
||||||
const debugMode = false // Does not load session token, to allow multiple players per browser
|
|
||||||
|
|
||||||
|
|
||||||
const offlineText = "Offline"
|
const offlineText = "Offline"
|
||||||
const missingPlayerText = "Leer"
|
const missingPlayerText = "Leer"
|
||||||
|
|
||||||
const elementIdUserName = "user-name"
|
|
||||||
const elementIdUserPssword = "user-pwd"
|
|
||||||
const elementIdPlayerCards = "player-cards"
|
const elementIdPlayerCards = "player-cards"
|
||||||
const elementIdLoginWindow = "login-window"
|
const elementIdLoginWindow = "login-window"
|
||||||
const elementIdTopBar = "top-bar"
|
const elementIdTopBar = "top-bar"
|
||||||
@ -28,22 +25,6 @@ const elementIdActionBar = "action-bar"
|
|||||||
const elementIdAvailableGamesList = "available-games-list"
|
const elementIdAvailableGamesList = "available-games-list"
|
||||||
const elementIdGameSummary = "game-summary"
|
const elementIdGameSummary = "game-summary"
|
||||||
|
|
||||||
const localStorageTokenId = "token"
|
|
||||||
|
|
||||||
function showDebugLogins() {
|
|
||||||
document.getElementById("login-window-inner").innerHTML +=
|
|
||||||
"<button class=\"login-buttons standard-button\" onclick=\"loginDebugUser('a')\">Player A</button>" +
|
|
||||||
"<button class=\"login-buttons standard-button\" onclick=\"loginDebugUser('b')\">Player B</button>" +
|
|
||||||
"<button class=\"login-buttons standard-button\" onclick=\"loginDebugUser('c')\">Player C</button>" +
|
|
||||||
"<button class=\"login-buttons standard-button\" onclick=\"loginDebugUser('d')\">Player D</button>"
|
|
||||||
}
|
|
||||||
|
|
||||||
function loginDebugUser(name) {
|
|
||||||
document.getElementById(elementIdUserName).value = name
|
|
||||||
document.getElementById(elementIdUserPssword).value = name
|
|
||||||
loginUser()
|
|
||||||
}
|
|
||||||
|
|
||||||
function setDisplayStyle(id, style) {
|
function setDisplayStyle(id, style) {
|
||||||
document.getElementById(id).style.display = style
|
document.getElementById(id).style.display = style
|
||||||
}
|
}
|
||||||
@ -102,41 +83,6 @@ function setPlayerName(name) {
|
|||||||
playerName = name
|
playerName = name
|
||||||
}
|
}
|
||||||
|
|
||||||
function getLoginName() {
|
|
||||||
return document.getElementById(elementIdUserName).value
|
|
||||||
}
|
|
||||||
|
|
||||||
function clearLoginName() {
|
|
||||||
document.getElementById(elementIdUserName).value = ""
|
|
||||||
}
|
|
||||||
|
|
||||||
function getLoginPassword() {
|
|
||||||
return document.getElementById(elementIdUserPssword).value
|
|
||||||
}
|
|
||||||
|
|
||||||
function clearLoginPassword() {
|
|
||||||
document.getElementById(elementIdUserPssword).value = ""
|
|
||||||
}
|
|
||||||
|
|
||||||
function getSessionToken() {
|
|
||||||
if (debugMode) {
|
|
||||||
return debugSessionToken
|
|
||||||
}
|
|
||||||
return localStorage.getItem(localStorageTokenId)
|
|
||||||
}
|
|
||||||
|
|
||||||
function setSessionToken(token) {
|
|
||||||
if (debugMode) {
|
|
||||||
debugSessionToken = token
|
|
||||||
return
|
|
||||||
}
|
|
||||||
localStorage.setItem(localStorageTokenId, token)
|
|
||||||
}
|
|
||||||
|
|
||||||
function deleteSessionToken() {
|
|
||||||
localStorage.removeItem(localStorageTokenId)
|
|
||||||
}
|
|
||||||
|
|
||||||
function setLoginError(text) {
|
function setLoginError(text) {
|
||||||
document.getElementById(elementIdLoginError).innerHTML = text
|
document.getElementById(elementIdLoginError).innerHTML = text
|
||||||
}
|
}
|
||||||
@ -388,8 +334,8 @@ function textForAction(action) {
|
|||||||
return "Herz Solo"
|
return "Herz Solo"
|
||||||
case "solo-schelln":
|
case "solo-schelln":
|
||||||
return "Schelln Solo"
|
return "Schelln Solo"
|
||||||
}
|
}
|
||||||
return action
|
return action
|
||||||
}
|
}
|
||||||
|
|
||||||
function performAction(action) {
|
function performAction(action) {
|
||||||
@ -411,4 +357,4 @@ function showAvailableGames(games) {
|
|||||||
html += "<div class=\"standard-button available-game\">" + content + "</div>"
|
html += "<div class=\"standard-button available-game\">" + content + "</div>"
|
||||||
}
|
}
|
||||||
document.getElementById(elementIdAvailableGamesList).innerHTML = html
|
document.getElementById(elementIdAvailableGamesList).innerHTML = html
|
||||||
}
|
}
|
||||||
|
@ -119,19 +119,20 @@ function deletePlayerAccount() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function loadExistingSession() {
|
function loadExistingSession() {
|
||||||
if (debugMode) {
|
const token = loadSessionToken()
|
||||||
showDebugLogins()
|
|
||||||
}
|
|
||||||
const token = getSessionToken()
|
|
||||||
if (token == null) {
|
if (token == null) {
|
||||||
showBlankLogin()
|
window.location.href = "login.html";
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
resumeSessionRequest(token)
|
resumeSessionRequest(token)
|
||||||
.then(function(name) {
|
.then(function(name) {
|
||||||
setPlayerName(name)
|
setPlayerName(name)
|
||||||
loadCurrentTable(token)
|
loadCurrentTable(token)
|
||||||
}).catch(showLoginWithError)
|
}).catch(function(error) {
|
||||||
|
console.log("Failed to resume session");
|
||||||
|
console.log(error);
|
||||||
|
window.location.href = "login.html";
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadCurrentTable(token) {
|
function loadCurrentTable(token) {
|
||||||
@ -265,4 +266,4 @@ function playCard(card) {
|
|||||||
.catch(function(error) {
|
.catch(function(error) {
|
||||||
console.log(error)
|
console.log(error)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
69
Public/login.css
Normal file
69
Public/login.css
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
|
||||||
|
#sheephead-logo {
|
||||||
|
color: rgb(0, 255, 0);
|
||||||
|
font-family: monospace, monospace;
|
||||||
|
white-space: pre;
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#login-window input {
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 6px;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#login-window {
|
||||||
|
background-color: var(--standard-background);
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
display: table;
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
#login-window-vertical-center {
|
||||||
|
display: table-cell;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
#login-window-inner {
|
||||||
|
background-color: var(--element-background);
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
width: 300px;
|
||||||
|
border-radius: 10px;
|
||||||
|
border-style: solid;
|
||||||
|
border-width: thin;
|
||||||
|
border-color: var(--element-border);
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-buttons {
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#login-error {
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
label a {
|
||||||
|
color: var(--button-color);
|
||||||
|
margin-left: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#user-hint {
|
||||||
|
padding-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#field-note {
|
||||||
|
padding-left: 5px;
|
||||||
|
color: gray;
|
||||||
|
}
|
70
Public/login.html
Normal file
70
Public/login.html
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset='utf-8'>
|
||||||
|
<title>Schafkopf</title>
|
||||||
|
<meta name='viewport' content='width=device-width, initial-scale=1'/>
|
||||||
|
<link rel='stylesheet' type='text/css' media='screen' href='style.css'/>
|
||||||
|
<link rel='stylesheet' type='text/css' media='screen' href='login.css'/>
|
||||||
|
<script src='api.js'></script>
|
||||||
|
<script src='storage.js'></script>
|
||||||
|
<script src='login.js'></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="login-window">
|
||||||
|
<div id="login-window-vertical-center">
|
||||||
|
<div id="login-window-inner">
|
||||||
|
<div id="sheephead-logo">\_______/<br>\ - - /<br>\ | /<br>\_/<br><br>Sheephead</div>
|
||||||
|
<label for="usrname">Username<a href="register.html">Create account</a></label>
|
||||||
|
<input type="text" id="user-name" name="usrname" required/>
|
||||||
|
|
||||||
|
<label for="psw">Password<a href="reset.html">Reset password</a></label>
|
||||||
|
<input type="password" id="user-pwd" name="psw" required/>
|
||||||
|
|
||||||
|
<button class="login-buttons standard-button" onclick="loginUser()">Log in</button>
|
||||||
|
<div id="user-hint"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
function loginUser() {
|
||||||
|
const username = getLoginName();
|
||||||
|
const password = getLoginPassword();
|
||||||
|
if (username == "") {
|
||||||
|
setTextHint("Please enter your user name");
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (password == "") {
|
||||||
|
setTextHint("Please enter a password");
|
||||||
|
return
|
||||||
|
}
|
||||||
|
performLoginPlayerRequest(username, password)
|
||||||
|
.then(function(token) {
|
||||||
|
storePlayerNameAndToken(username, token)
|
||||||
|
window.location.href = "schafkopf.html";
|
||||||
|
}).catch(function(error) {
|
||||||
|
console.log("Failed to log in")
|
||||||
|
console.log(error)
|
||||||
|
// TODO: Create better error message for user
|
||||||
|
setTextHint(error);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function showDebugLogins() {
|
||||||
|
document.getElementById("login-window-inner").innerHTML +=
|
||||||
|
"<button class=\"login-buttons standard-button\" onclick=\"loginDebugUser('a')\">Player A</button>" +
|
||||||
|
"<button class=\"login-buttons standard-button\" onclick=\"loginDebugUser('b')\">Player B</button>" +
|
||||||
|
"<button class=\"login-buttons standard-button\" onclick=\"loginDebugUser('c')\">Player C</button>" +
|
||||||
|
"<button class=\"login-buttons standard-button\" onclick=\"loginDebugUser('d')\">Player D</button>"
|
||||||
|
}
|
||||||
|
|
||||||
|
function loginDebugUser(name) {
|
||||||
|
setLoginName(name)
|
||||||
|
setLoginPassword(name)
|
||||||
|
loginUser()
|
||||||
|
}
|
||||||
|
|
||||||
|
loadExistingSession()
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
64
Public/login.js
Normal file
64
Public/login.js
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
// Site-specific elements
|
||||||
|
const elementIdUserName = "user-name";
|
||||||
|
const elementIdUserPassword = "user-pwd";
|
||||||
|
const elementIdUserEmail = "user-email";
|
||||||
|
const elementIdUserHint = "user-hint";
|
||||||
|
|
||||||
|
function getLoginName() {
|
||||||
|
return document.getElementById(elementIdUserName).value;
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearLoginName() {
|
||||||
|
document.getElementById(elementIdUserName).value = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
function setLoginName(name) {
|
||||||
|
document.getElementById(elementIdUserName).value = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getLoginPassword() {
|
||||||
|
return document.getElementById(elementIdUserPassword).value;
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearLoginPassword() {
|
||||||
|
document.getElementById(elementIdUserPassword).value = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
function setLoginPassword(password) {
|
||||||
|
document.getElementById(elementIdUserPassword).value = password;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getLoginEmail() {
|
||||||
|
return document.getElementById(elementIdUserEmail).value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set a text to indicate an action, warning or other message below the registration field;
|
||||||
|
*/
|
||||||
|
function setTextHint(text) {
|
||||||
|
document.getElementById(elementIdUserHint).innerHTML = text;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Attempt to reopen an existing session, either from the login or register page.
|
||||||
|
*
|
||||||
|
* It could be argued that this shouldn't be attempted for the registration page,
|
||||||
|
* but, a user may accidentally go to the registration page through the browser history,
|
||||||
|
* and then it will be convenient to be redirected to the game.
|
||||||
|
*/
|
||||||
|
function loadExistingSession() {
|
||||||
|
const token = loadSessionToken();
|
||||||
|
if (token == null) {
|
||||||
|
console.log("No session token to load")
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
resumeSessionRequest(token)
|
||||||
|
.then(function(name) {
|
||||||
|
storePlayerNameAndToken(name, token);
|
||||||
|
window.location.href = "list.html";
|
||||||
|
}).catch(function(error) {
|
||||||
|
// We don't expect a session to resume if the registration page is shown,
|
||||||
|
// and if the token is expired on the login page we just fail quietly.
|
||||||
|
console.log(error);
|
||||||
|
})
|
||||||
|
}
|
56
Public/recovery.html
Normal file
56
Public/recovery.html
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset='utf-8'/>
|
||||||
|
<title>Schafkopf</title>
|
||||||
|
<meta name='viewport' content='width=device-width, initial-scale=1'/>
|
||||||
|
<link rel='stylesheet' type='text/css' href='style.css'/>
|
||||||
|
<link rel='stylesheet' type='text/css' href='login.css'/>
|
||||||
|
<script src='api.js'></script>
|
||||||
|
<script src='login.js'></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="login-window">
|
||||||
|
<div id="login-window-vertical-center">
|
||||||
|
<div id="login-window-inner">
|
||||||
|
<div id="sheephead-logo">\_______/<br>\ - - /<br>\ | /<br>\_/<br><br>Sheephead</div>
|
||||||
|
<label for="psw">New Password</label>
|
||||||
|
<input type="password" id="user-pwd" name="psw" required>
|
||||||
|
|
||||||
|
<button class="login-buttons standard-button" onclick="resetPassword()">Set new password</button>
|
||||||
|
<div id="user-hint"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
|
||||||
|
function resetPassword() {
|
||||||
|
const password = getLoginPassword()
|
||||||
|
|
||||||
|
if (password == "") {
|
||||||
|
setTextHint("Please enter a password")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const queryString = window.location.search;
|
||||||
|
const urlParams = new URLSearchParams(queryString);
|
||||||
|
if (!urlParams.has('token')) {
|
||||||
|
setTextHint("Please open a valid recovery link")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const token = urlParams.get('token');
|
||||||
|
if (token == "") {
|
||||||
|
setTextHint("Please open a valid recovery link")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
performResetPasswordRequest(token, password)
|
||||||
|
.then(function(value) {
|
||||||
|
window.location.href = "login.html"
|
||||||
|
})
|
||||||
|
.catch(setTextHint)
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
75
Public/register.html
Normal file
75
Public/register.html
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset='utf-8'>
|
||||||
|
<title>Schafkopf</title>
|
||||||
|
<meta name='viewport' content='width=device-width, initial-scale=1'/>
|
||||||
|
<link rel='stylesheet' type='text/css' media='screen' href='style.css'/>
|
||||||
|
<link rel='stylesheet' type='text/css' href='login.css'/>
|
||||||
|
<script src='api.js'></script>
|
||||||
|
<script src='storage.js'></script>
|
||||||
|
<script src='login.js'></script>
|
||||||
|
</head>
|
||||||
|
<body id="login-window">
|
||||||
|
<div id="login-window-vertical-center">
|
||||||
|
<div id="login-window-inner">
|
||||||
|
<div id="sheephead-logo">\_______/<br>\ - - /<br>\ | /<br>\_/<br><br>Sheephead</div>
|
||||||
|
<label for="usrname">Username<span id="field-note">Required</span><a href="login.html">Log in instead</a></label>
|
||||||
|
<input type="text" id="user-name" name="usrname" required autofocus/>
|
||||||
|
|
||||||
|
<label for="psw">Password<span id="field-note">Required</span></label>
|
||||||
|
<input type="password" id="user-pwd" name="psw" required/>
|
||||||
|
|
||||||
|
<label for="email">Email<span id="field-note">Optional, for password reset</span></label>
|
||||||
|
<input type="email" id="user-email" name="email"/>
|
||||||
|
|
||||||
|
<button class="login-buttons standard-button" onclick="registerUser()">Create account</button>
|
||||||
|
<div id="user-hint"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
|
||||||
|
// Email address validation regex
|
||||||
|
const mailformat = /^([A-Za-z0-9_\-\.])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4})$/;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Register a new account.
|
||||||
|
*
|
||||||
|
* The function extracts the fields from the form, and attempts to create the account.
|
||||||
|
* Invalid emails are checked using basic validation.
|
||||||
|
*
|
||||||
|
* In case the registration fails, then we show an error to the user.
|
||||||
|
*/
|
||||||
|
function registerUser() {
|
||||||
|
const username = getLoginName();
|
||||||
|
if (username == "") {
|
||||||
|
setTextHint("Please enter your user name");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const password = getLoginPassword();
|
||||||
|
if (password == "") {
|
||||||
|
setTextHint("Please enter a password");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const email = getLoginEmail();
|
||||||
|
if (email != "" && !email.match(mailformat)) {
|
||||||
|
setTextHint("Invalid email address");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
performRegisterPlayerRequest(username, password, email)
|
||||||
|
.then(function(token) {
|
||||||
|
storePlayerNameAndToken(username, token);
|
||||||
|
window.location.href = "list.html";
|
||||||
|
}).catch(function(error) {
|
||||||
|
// TODO: Show better error messages to user
|
||||||
|
console.log("Registration failed.");
|
||||||
|
console.log(error);
|
||||||
|
setTextHint(error);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
loadExistingSession();
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
42
Public/reset.html
Normal file
42
Public/reset.html
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset='utf-8'/>
|
||||||
|
<title>Schafkopf</title>
|
||||||
|
<meta name='viewport' content='width=device-width, initial-scale=1'/>
|
||||||
|
<link rel='stylesheet' type='text/css' href='style.css'/>
|
||||||
|
<link rel='stylesheet' type='text/css' href='login.css'/>
|
||||||
|
<script src='api.js'></script>
|
||||||
|
<script src='login.js'></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="login-window">
|
||||||
|
<div id="login-window-vertical-center">
|
||||||
|
<div id="login-window-inner">
|
||||||
|
<div id="sheephead-logo">\_______/<br>\ - - /<br>\ | /<br>\_/<br><br>Sheephead</div>
|
||||||
|
<label for="usrname">Username</span><a href="login.html">Log in instead</a></label>
|
||||||
|
<input type="text" id="user-name" name="usrname" required/>
|
||||||
|
|
||||||
|
<button class="login-buttons standard-button" onclick="resetPassword()">Send recovery email</button>
|
||||||
|
<div id="user-hint"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
function resetPassword() {
|
||||||
|
const name = getLoginName()
|
||||||
|
|
||||||
|
if (name == "") {
|
||||||
|
setTextHint("Please enter a name")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
performRecoveryEmailRequest(name)
|
||||||
|
.then(function(value) {
|
||||||
|
setTextHint("The email has been sent")
|
||||||
|
})
|
||||||
|
.catch(setTextHint)
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -7,6 +7,7 @@
|
|||||||
<link rel='stylesheet' type='text/css' media='screen' href='style.css'>
|
<link rel='stylesheet' type='text/css' media='screen' href='style.css'>
|
||||||
<script src='elements.js?v=1'></script>
|
<script src='elements.js?v=1'></script>
|
||||||
<script src='api.js'></script>
|
<script src='api.js'></script>
|
||||||
|
<script src='storage.js'></script>
|
||||||
<script src='game.js'></script>
|
<script src='game.js'></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
@ -72,25 +73,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="login-window">
|
|
||||||
<div id="login-window-vertical-center">
|
|
||||||
<div id="login-window-inner">
|
|
||||||
<div id="sheephead-logo">\_______/<br> \ - - / <br> \ | / <br> \_/ <br><br>Sheephead</div>
|
|
||||||
<label for="usrname">Username</label>
|
|
||||||
<input type="text" id="user-name" name="usrname" required>
|
|
||||||
|
|
||||||
<label for="psw">Password</label>
|
|
||||||
<input type="password" id="user-pwd" name="psw" required>
|
|
||||||
|
|
||||||
<button class="login-buttons standard-button" onclick="registerUser()">Register</button>
|
|
||||||
<button class="login-buttons standard-button" onclick="loginUser()">Log in</button>
|
|
||||||
<div id="login-error"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<script>
|
<script>
|
||||||
loadExistingSession()
|
loadExistingSession()
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
38
Public/storage.js
Normal file
38
Public/storage.js
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
// Local storage element identifiers
|
||||||
|
const localStorageTokenId = "token";
|
||||||
|
const localStoragePlayerName = "name";
|
||||||
|
|
||||||
|
// Can prevent loading of session token, to allow multiple players per browser
|
||||||
|
const debugMode = false
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Store the player name and session token in local storage.
|
||||||
|
* Parameter name: The user name of the player
|
||||||
|
* Parameter token: The session token for the player session
|
||||||
|
*/
|
||||||
|
function storePlayerNameAndToken(name, token) {
|
||||||
|
localStorage.setItem(localStoragePlayerName, name);
|
||||||
|
localStorage.setItem(localStorageTokenId, token);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the last session token from local storage.
|
||||||
|
*/
|
||||||
|
function loadSessionToken() {
|
||||||
|
if (debugMode) {
|
||||||
|
return debugSessionToken
|
||||||
|
}
|
||||||
|
return localStorage.getItem(localStorageTokenId)
|
||||||
|
}
|
||||||
|
|
||||||
|
function storeSessionToken(token) {
|
||||||
|
if (debugMode) {
|
||||||
|
debugSessionToken = token
|
||||||
|
return
|
||||||
|
}
|
||||||
|
localStorage.setItem(localStorageTokenId, token)
|
||||||
|
}
|
||||||
|
|
||||||
|
function deleteSessionToken() {
|
||||||
|
localStorage.removeItem(localStorageTokenId)
|
||||||
|
}
|
@ -37,12 +37,6 @@ input {
|
|||||||
background-color: var(--standard-background);
|
background-color: var(--standard-background);
|
||||||
}
|
}
|
||||||
|
|
||||||
#login-window input {
|
|
||||||
width: 100%;
|
|
||||||
margin-top: 6px;
|
|
||||||
margin-bottom: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
html * {
|
html * {
|
||||||
font-family:-apple-system, BlinkMacSystemFont, "SF Hello", "Helvetica Neue", Helvetica, Arial, Verdana, sans-serif;
|
font-family:-apple-system, BlinkMacSystemFont, "SF Hello", "Helvetica Neue", Helvetica, Arial, Verdana, sans-serif;
|
||||||
color: var(--text-color);
|
color: var(--text-color);
|
||||||
@ -60,49 +54,6 @@ body {
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
}
|
}
|
||||||
|
|
||||||
#login-window {
|
|
||||||
background-color: var(--standard-background);
|
|
||||||
height: 100%;
|
|
||||||
width: 100%;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
display: table;
|
|
||||||
position: absolute;
|
|
||||||
}
|
|
||||||
|
|
||||||
#login-window-vertical-center {
|
|
||||||
display: table-cell;
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
|
|
||||||
#login-window-inner {
|
|
||||||
background-color: var(--element-background);
|
|
||||||
margin-left: auto;
|
|
||||||
margin-right: auto;
|
|
||||||
width: 300px;
|
|
||||||
border-radius: 10px;
|
|
||||||
border-style: solid;
|
|
||||||
border-width: thin;
|
|
||||||
border-color: var(--element-border);
|
|
||||||
padding: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#sheephead-logo {
|
|
||||||
color: rgb(0, 255, 0);
|
|
||||||
font-family: monospace, monospace;
|
|
||||||
white-space: pre;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.login-buttons {
|
|
||||||
width: 100%;
|
|
||||||
margin-top: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#login-error {
|
|
||||||
margin-top: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#top-bar {
|
#top-bar {
|
||||||
height: 50px;
|
height: 50px;
|
||||||
background-color: var(--element-background);
|
background-color: var(--element-background);
|
||||||
@ -580,4 +531,4 @@ body {
|
|||||||
#player-card8 {
|
#player-card8 {
|
||||||
grid-column: 8;
|
grid-column: 8;
|
||||||
z-index: 8;
|
z-index: 8;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user