// Before showing any page, check + save credentials
app.use(function(req, res, next) {
req.loggedIn = false;
+ res.locals.user = { name: "" };
if (!req.cookies.token)
return next();
UserModel.getOne("sessionToken", req.cookies.token, function(err, user) {
--- /dev/null
+// Logic to login, or create / update a user (and also logout)
+Vue.component('my-upsert-user', {
+ props: ["initUser"], //to find the game in storage (assumption: it exists)
+ data: function() {
+ return {
+ user: initUser, //initialized with prop value
+ stage: (!initUser.email ? "Login" : "Update"),
+ infoMsg: "",
+ };
+ },
+ template: `
+ <div>
+ <input id="modalUser" class="modal" type="checkbox"/>
+ <div role="dialog">
+ <div class="card">
+ <label class="modal-close" for="modalUser">
+ <h3>{{ stage }}</h3>
+ <form id="userForm" @submit.prevent="submit">
+ <fieldset>
+ <label for="useremail">Email</label>
+ <input id="useremail" type="email" v-model="user.email"/>
+ <fieldset>
+ <label for="username">Name</label>
+ <input id="username" type="text" v-model="user.name"/>
+ </fieldset>
+ <fieldset>
+ <label for="notifyNew">Notify new moves & games</label>
+ <input id="notifyNew" type="checkbox" v-model="user.notify"/>
+ <button id="submit" @click.prevent="submit">
+ <span>{{ submitMessage }}</span>
+ <i class="material-icons">send</i>
+ <p v-if="stage!='Update'">
+ <button @click.prevent="toggleStage()">
+ <span>{{ stage=="Login" ? "Register" : "Login" }}</span>
+ </button>
+ <button>Logout</button>
+ </p>
+ <div id="dialog" :style="{display: displayInfo}">{{ infoMsg }}</div>
+ </div>
+ </div>
+ `,
+ computed: {
+ submitMessage: function() {
+ switch (this.stage)
+ {
+ case "Login":
+ return "Go";
+ case "Register":
+ return "Send";
+ case "Update":
+ return "Apply";
+ }
+ },
+ displayInfo: function() {
+ return (this.infoMsg.length > 0 ? "block" : "none");
+ },
+ },
+ methods: {
+ toggleStage: function() {
+ this.stage = (this.stage == "Login" ? "Register" : "Login");
+ },
+ ajaxUrl: function() {
+ switch (this.stage)
+ {
+ case "Login":
+ return "/sendtoken";
+ case "Register":
+ return "/register";
+ case "Update":
+ return "/update";
+ }
+ },
+ ajaxMethod: function() {
+ switch (this.stage)
+ {
+ case "Login":
+ return "GET";
+ case "Register":
+ return "POST";
+ case "Update":
+ return "PUT";
+ }
+ },
+ infoMessage: function() {
+ switch (this.stage)
+ {
+ case "Login":
+ return "Connection token sent. Check your emails!";
+ case "Register":
+ return "Registration complete! Please check your emails.";
+ case "Update":
+ return "Modifications applied!";
+ }
+ },
+ submit: function() {
+ // TODO: re-activate simple measures like this: (using time of click on modal)
+// const exitTime = new Date();
+// if (this.stage=="Register" && exitTime.getTime() - enterTime.getTime() < 5000)
+// return;
+ if (!this.user.name.match(/[a-z0-9_]+/i))
+ return alert("User name: only alphanumerics and underscore");
+ this.infoMsg = "Processing... Please wait";
+ ajax(this.ajaxUrl(), this.ajaxMethod(),
+ this.stage == "Login" ? "PUT" : "POST", this.user,
+ res => {
+ this.infoMsg = this.infoMessage();
+ if (this.stage != "Update")
+ {
+ this.user["email"] = "";
+ this.user["name"] = "";
+ }
+ setTimeout(() => {
+ this.infoMsg = "";
+ document.getElementById("modalUser").checked = false;
+ }, 2000);
+ }
+ );
+ },
+ }
+});
// Javascript for index page: mostly counters updating
new Vue({
- el: "#indexPage",
+ el: "#VueElement",
data: {
counts: {},
curPrefix: "",
{
let data_str = "";
Object.keys(data).forEach(k => {
- data_str += k + "=" + data[k] + "&";
+ data_str += k + "=" + encodeURIComponent(data[k]) + "&";
});
return data_str.slice(0, -1); //remove last "&"
}
new Vue({
- el: "#variantPage",
+ el: "#VueElement",
data: {
display: "room", //default: main hall
gameid: "undefined", //...yet
--- /dev/null
+button#submit
+ display: inline-flex
+ //i
+ line-height: 36px
+ span
+ margin-right: 7px
+
+#dialog
+ clear: both
padding: 0
box-sizing: border-box
p
- display: inline-block
+ display: flex
padding: 3px
border: 1px solid black;
margin: 25px 15px 5px 7px
margin-top: 10px
font-size: 1em
-#settingsMenu, #introductionMenu
+#introductionMenu, #userMenu
float: right
@media screen and (max-width: 767px)
.info-container
p
margin-right: 5px
+#flagMenu
+ float: right
+ margin-right: 10px
+ @media screen and (max-width: 767px)
+ margin-right: 5px
+ img
+ display: inline-block
+ height: 30px
+ padding-top: 27px
+ @media screen and (max-width: 767px)
+ padding-top: 8px
+
// TODO: box-shadow or box-sizing ? https://stackoverflow.com/a/13517809
.variant
box-sizing: border-box
+@import users
+
html, *
font-family: "Open Sans", Arial, sans-serif
--back-color: #f2f2f2
return result;
}
+// TODO: empêcher multi-log du même user (envoyer le user ID + secret en même temps que name et...)
+// --> si secret ne matche pas celui trouvé en DB, stop
+
module.exports = function(wss) {
db.serialize(function() {
db.all("SELECT * FROM Variants", (err,variants) => {
link(rel="stylesheet", href="/stylesheets/index.css")
block content
- .container#indexPage
+ .container
case lang
when "en"
include welcome/en
.info-container
p vchess.club
img(src="/images/index/wildebeest.svg")
- #settingsMenu.clickable(
- onClick="document.getElementById('modalSettings').checked=true")
+ #flagMenu.clickable(
+ onClick="document.getElementById('modalLang').checked=true")
+ img(src="/images/flags/" + lang + ".svg")
+ #userMenu.clickable(
+ onClick="document.getElementById('modalUser').checked=true")
.info-container
- p Settings
+ if !user.email
+ p
+ span Login
+ i.material-icons person
+ else
+ p
+ span Update
+ i.material-icons person
#introductionMenu.clickable(
onClick="document.getElementById('modalWelcome').checked=true")
.info-container
include translations/es
when "fr"
include translations/fr
- if !user
- include login_register
- else
- include logout_update
include contactForm
- include settings
- main
+ include modalLang
+ main#VueElement
+ my-upsert-user(:user="user" :stage="stage")
block content
footer.col-sm-12.col-md-10.col-md-offset-1.col-lg-8.col-lg-offset-2.text-center
div
script(src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js")
else
script(src="https://cdn.jsdelivr.net/npm/vue")
+ script(src="/javascripts/components/upsertUser.js")
script.
const translations = !{JSON.stringify(translations)};
const user = !{JSON.stringify(user)};
+++ /dev/null
-extends layout
-
-block css
- link(rel="stylesheet", href="/stylesheets/login.css")
-
-block content
- .mui-container
- .row
- .mui-col.xs-12.mui-col-sm-8.mui-col-sm-offset-2.mui-col-md-6.mui-col-md-offset-3.mui-col-lg-4.mui-col-lg-offset-4.mui--z1.white.pad-updown.pad-sides
- form#loginForm(@submit.prevent="submit")
- .mui-textfield.mui-textfield--float-label
- input#email(type="email" ref="userEmail" v-model="user.email")
- label#labEmail(for="email") Email
- .mui-textfield.mui-textfield--float-label(v-show="stage == 'Register'")
- input#name(type="text" v-model="user.name")
- label#labName(for="name") Name
- .mui--pull-left.space-bottom.space-top
- button#submit.mui-btn.mui-btn--primary(@click.prevent="submit")
- span {{ stage=="Login" ? "Go" : "Send" }}
- i.material-icons.right send
- .mui--pull-right.space-bottom.space-top
- p
- button.mui-btn.mui-btn--accent(@click.prevent="toggleStage()")
- span {{ stage=="Login" ? "Register" : "Login" }}
- #dialog.mui--hide.space-top
-
-block javascripts
- script(src="//cdnjs.cloudflare.com/ajax/libs/vue/2.5.2/vue.min.js")
- script(src="/javascripts/utils/dialog.js")
- script(src="/javascripts/utils/validation.js")
- script(src="/javascripts/login.js")
+++ /dev/null
-extends layout
-
-block css
- link(rel="stylesheet", href="/stylesheets/settings.css")
-
-block content
- .mui-container-fluid
- .mui-row
- .mui-col-xs-12.mui-col-sm-10.mui-col-sm-offset-1.mui-col-md-8.mui-col-md-offset-2.mui-col-lg-6.mui-col-lg-offset-3.mui--z1.white.pad-updown.pad-sides
- form#settingsForm(@submit.prevent="submit")
- .mui-textfield.mui-textfield--float-label
- input#email(type="email" ref="userEmail" v-model="user.email")
- label#labEmail.active(for="email") Email
- .mui-textfield.mui-textfield--float-label
- input#name(type="text" v-model="user.name")
- label#labName.active(for="name") Name
- p
- span Theme
- button(v-for="theme in themes" class="theme-btn mui-btn grey"
- :class="themeClass(theme)" @click.prevent="toggleTheme(theme)")
- | {{ theme }}
- .mui-radio
- input#notify(type="checkbox" v-model="user.notify")
- label(for="notify") Notify new moves & games
- button#submit.mui-btn.mui-btn--primary(@click.prevent="submit")
- span Apply
- i.material-icons.right send
- #dialog.mui--hide.space-top
-
-block javascripts
- script(src="//cdnjs.cloudflare.com/ajax/libs/vue/2.5.2/vue.min.js")
- script(src="/javascripts/utils/dialog.js")
- script(src="/javascripts/utils/validation.js")
- script.
- var user = !{JSON.stringify(user)};
- script(src="/javascripts/settings.js")
--- /dev/null
+input#modalLang.modal(type="checkbox")
+div(role="dialog")
+ #language.card
+ label.modal-close(for="modalLang")
+ form
+ fieldset
+ label(for="langSelect")= translations["Language"]
+ select#langSelect
+ each language,langCode in langName
+ option(value=langCode selected=(lang==langCode))
+ =language
.card.smallpad(onChange="blabla(event)")
label.modal-close(for="modalSettings")
h3#settingsTitle.section= translations["Preferences"]
- fieldset
- label(for="langSelect")= translations["Language"]
- // image avec drapeau + select language ici
- select#langSelect
- each language,langCode in langName
- option(value=langCode selected=(lang==langCode))
- =language
- fieldset
- label(for="nameSetter")
- =translations["My name is..."]
- input#nameSetter(type="text" value=this.myname)
- // theme sombre / clair
// taille echiquier : TODO
fieldset
label(for="setHints")= translations["Show hints?"]
link(rel="stylesheet" href="/stylesheets/variant.css")
block content
- .container#variantPage
+ include settings
+ .container
.row
.col-sm-12.col-md-10.col-md-offset-1.col-lg-8.col-lg-offset-2
label.drawer-toggle(for="drawer-control")
#settings.clickable(
onClick="document.getElementById('modalSettings').checked=true")
i.material-icons settings
+ #userMenu.clickable(
+ onClick="document.getElementById('modalUser').checked=true")
+ .info-container
+ i.material-icons person
+ if !user.email
+ p Login
+ else
+ p Update
.row
my-room(v-show="display=='room'")
my-game-list(v-show="display=='gameList'")