From: Benjamin Auder Date: Sat, 12 Jan 2019 14:21:00 +0000 (+0100) Subject: Some advances. TODO: test board.js, and then game.js, and then implement room.js X-Git-Url: https://git.auder.net/js/css/doc/html/index.html?a=commitdiff_plain;h=fd08ab2c5b8931bb8c95cf7e9f2f95122647f991;p=vchess.git Some advances. TODO: test board.js, and then game.js, and then implement room.js --- diff --git a/TODO b/TODO index a4a9d5b9..7ea4813d 100644 --- a/TODO +++ b/TODO @@ -1,3 +1,8 @@ +Sur index, introduction menu remplacé par "mes parties", montrant parties (corr) en cours toutes variantes confondues +Dans variant page, "mes parties" peut toujours contenir corr + importées (deux onglets) +En fin de partie (observée ou non), bouton "import game" en + de "download game" ==> directement dans indexedDB +--> sursis de 7 jours pour les parties par correspondance, qui sont encore chargées depuis le serveur + mat en 2 échiqueté : brnkr3/pppp1p1p/4ps2/8/2P2P2/P1qP4/2c1s1PP/R1K5 (Bb3+ Kb1 Ba2#) diff --git a/config/parameters.js.dist b/config/parameters.js.dist index bb3cbe29..6f274dd3 100644 --- a/config/parameters.js.dist +++ b/config/parameters.js.dist @@ -1,4 +1,4 @@ -const Parameters = +module.exports = { // For mail sending. NOTE: *no trailing slash* siteURL: "http://localhost:3000", @@ -7,12 +7,12 @@ const Parameters = env: process.env.NODE_ENV || 'development', // Lifespan of a (login) cookie - cookieExpire: 183*24*3600*1000, //6 months in milliseconds + cookieExpire: 183*24*60*60*1000, //6 months in milliseconds // Characters in a login token, and period of validity (in milliseconds) token: { length: 16, - expire: 1000*60*30, //30 minutes in milliseconds + expire: 30*60*1000, //30 minutes in milliseconds }, // Email settings @@ -26,5 +26,3 @@ const Parameters = contact: "some_contact_email", }, }; - -module.exports = Parameters; diff --git a/db/create.sql b/db/create.sql index e94b84a3..5f463bfc 100644 --- a/db/create.sql +++ b/db/create.sql @@ -59,11 +59,11 @@ create table Games ( -- Store informations about players in a corr game create table Players ( + gid integer, uid integer, color character, - gid integer, - foreign key (uid) references Users(id), - foreign key (gid) references Games(id) + foreign key (gid) references Games(id), + foreign key (uid) references Users(id) ); create table Moves ( diff --git a/models/Game.js b/models/Game.js index 2e57309f..d279514f 100644 --- a/models/Game.js +++ b/models/Game.js @@ -1 +1 @@ -//TODO: at least this model (maybe MoveModel ?!) +//TODO: diff --git a/models/Problem.js b/models/Problem.js index 6184eafc..78586761 100644 --- a/models/Problem.js +++ b/models/Problem.js @@ -65,7 +65,7 @@ exports.fetchN = function(vname, uid, type, directionStr, lastDt, MaxNbProblems, "WHERE vid = (SELECT id FROM Variants WHERE name = '" + vname + "') " + " AND added " + directionStr + " " + lastDt + " " + typeLine + " " + "ORDER BY added " + (directionStr=="<" ? "DESC " : "") + - "LIMIT " + MaxNbProblems, + "LIMIT " + MaxNbProblems; db.all(query, callback); }); } diff --git a/public/javascripts/components/game.js b/public/javascripts/components/game.js index 39c12c0e..ca791257 100644 --- a/public/javascripts/components/game.js +++ b/public/javascripts/components/game.js @@ -4,7 +4,7 @@ // Game logic on a variant page: 3 modes, analyze, computer or human Vue.component('my-game', { // gameId: to find the game in storage (assumption: it exists) - props: ["gameId","mode","allowChat","allowMovelist"], + props: ["gameId","fen","mode","allowChat","allowMovelist"], data: function() { return { // if oppid == "computer" then mode = "computer" (otherwise human) @@ -24,6 +24,11 @@ Vue.component('my-game', { vr: null, //VariantRules object, describing the game state + rules }; }, + watch: { + fen: function(newFen) { + this.vr = new VariantRules(newFen); + }, + }, computed: { showChat: function() { return this.allowChat && this.mode=='human' && this.score != '*'; diff --git a/public/javascripts/components/problems.js b/public/javascripts/components/problems.js index 9a14c709..53077049 100644 --- a/public/javascripts/components/problems.js +++ b/public/javascripts/components/problems.js @@ -38,7 +38,7 @@ Vue.component('my-problems', { {{ curProb.instructions }}

- //TODO: use my-game in analyze mode ? +

diff --git a/public/javascripts/index.js b/public/javascripts/index.js index 3d35c456..bc4cd9e1 100644 --- a/public/javascripts/index.js +++ b/public/javascripts/index.js @@ -5,10 +5,10 @@ new Vue({ counts: {}, curPrefix: "", conn: null, + display: "variants", }, computed: { sortedCounts: function () { - // TODO: priorité aux parties corr où c'est à nous de jouer ! const capitalizedPrefix = this.curPrefix.replace(/^\w/, c => c.toUpperCase()); const variantsCounts = variantArray .filter( v => { @@ -50,7 +50,7 @@ new Vue({ this.conn.onmessage = socketMessageListener; this.conn.onclose = socketCloseListener; - // TODO: + // TODO: AJAX call get corr games (all variants) // si dernier lastMove sur serveur n'est pas le mien et nextColor == moi, alors background orange // ==> background orange si à moi de jouer par corr (sur main index) // (helper: static fonction "GetNextCol()" dans base_rules.js) diff --git a/public/javascripts/layout.js b/public/javascripts/layout.js index 6d26b921..8cb79e0d 100644 --- a/public/javascripts/layout.js +++ b/public/javascripts/layout.js @@ -2,3 +2,4 @@ //à l'arrivée sur le site : set peerID (un identifiant unique en tout cas...) si pas trouvé // //TODO: si une partie en cours dans storage, rediriger vers cette partie +//(à condition que l'URL n'y corresponde pas déjà !) diff --git a/public/stylesheets/index.sass b/public/stylesheets/index.sass index d25ecb49..5f76e00b 100644 --- a/public/stylesheets/index.sass +++ b/public/stylesheets/index.sass @@ -40,13 +40,6 @@ margin-top: 10px font-size: 1em -#introductionMenu, #userMenu - float: right - @media screen and (max-width: 767px) - .info-container - p - margin-right: 5px - #flagMenu float: right margin-right: 10px diff --git a/public/stylesheets/layout.sass b/public/stylesheets/layout.sass index eae4542a..161995db 100644 --- a/public/stylesheets/layout.sass +++ b/public/stylesheets/layout.sass @@ -35,6 +35,13 @@ body border-left: 1px solid var(--button-group-border-color) border-top: 0 +.right-menu + float: right + @media screen and (max-width: 767px) + .info-container + p + margin-right: 5px + #settings, #contactForm max-width: 767px @media screen and (max-width: 767px) diff --git a/reflexions b/reflexions new file mode 100644 index 00000000..61c9932a --- /dev/null +++ b/reflexions @@ -0,0 +1,5 @@ +tell opponent that I got the move, for him to start timer (and lose...) +board2, board3, board4 +VariantRules2, 3 et 4 aussi +fetch challenges and corr games from server at startup (room) +but forbid anonymous to start corr games or accept challenges diff --git a/routes/playing.js b/routes/playing.js index 37592c9d..7af0a1bc 100644 --- a/routes/playing.js +++ b/routes/playing.js @@ -90,12 +90,8 @@ router.get("/gamesbyplayer", access.logged, access.ajax, (req,res) => { }); }); -// Load a rules page -router.get("/rules/:variant([a-zA-Z0-9]+)", access.ajax, (req,res) => { - res.render("rules/" + req.params["variant"]); -}); - // TODO: if newmove fail, takeback in GUI // TODO: check move structure +// TODO: for corr games, move should contain an optional "message" field ("corr chat" !) router.post("/moves", access.logged, access.ajax, (req,res) => { let gid = ObjectId(req.body.gid); let fen = req.body.fen; @@ -111,16 +107,4 @@ router.post("/moves", access.logged, access.ajax, (req,res) => { }); }); -//TODO: if new chat fails, do not show chat message locally -router.post("/chats", access.logged, access.ajax, (req,res) => { - let gid = ObjectId(req.body.gid); - let uid = ObjectId(req.body.uid); - let msg = req.body.msg; //TODO: sanitize HTML (strip all tags...) - GameModel.addChat(gid, uid, msg, (err,game) => { - access.checkRequest(res, err, game, "Cannot find game", () => { - res.json({}); - }); - }); -}); - module.exports = router; diff --git a/utils/access.js b/utils/access.js index 1c82cb67..49d204c3 100644 --- a/utils/access.js +++ b/utils/access.js @@ -1,41 +1,36 @@ -var Access = {}; - -// Prevent access to "users pages" -Access.logged = function(req, res, next) +module.exports = { - if (req.userId == 0) - return res.redirect("/"); - next(); -}; + // Prevent access to "users pages" + logged: function(req, res, next) { + if (req.userId == 0) + return res.redirect("/"); + next(); + }, -// Prevent access to "anonymous pages" -Access.unlogged = function(req, res, next) -{ - if (req.userId > 0) - return res.redirect("/"); - next(); -}; + // Prevent access to "anonymous pages" + unlogged: function(req, res, next) { + if (req.userId > 0) + return res.redirect("/"); + next(); + }, -// Prevent direct access to AJAX results -Access.ajax = function(req, res, next) -{ - if (!req.xhr) - return res.json({errmsg: "Unauthorized access"}); - next(); -} + // Prevent direct access to AJAX results + ajax: function(req, res, next) { + if (!req.xhr) + return res.json({errmsg: "Unauthorized access"}); + next(); + }, -// Check for errors before callback (continue page loading). TODO: better name. -Access.checkRequest = function(res, err, out, msg, cb) -{ - if (!!err) - return res.json({errmsg: err.errmsg || err.toString()}); - if (!out - || (Array.isArray(out) && out.length == 0) - || (typeof out === "object" && Object.keys(out).length == 0)) - { - return res.json({errmsg: msg}); - } - cb(); + // Check for errors before callback (continue page loading). TODO: better name. + checkRequest: function(res, err, out, msg, cb) { + if (!!err) + return res.json({errmsg: err.errmsg || err.toString()}); + if (!out + || (Array.isArray(out) && out.length == 0) + || (typeof out === "object" && Object.keys(out).length == 0)) + { + return res.json({errmsg: msg}); + } + cb(); + }, } - -module.exports = Access; diff --git a/utils/tokenGenerator.js b/utils/tokenGenerator.js index 5578c2ec..1bc172cd 100644 --- a/utils/tokenGenerator.js +++ b/utils/tokenGenerator.js @@ -1,17 +1,14 @@ -var TokenGen = {}; - -TokenGen.rand = function() +module.exports = { - return Math.random().toString(36).substr(2); // remove `0.` -}; + rand: function() { + return Math.random().toString(36).substr(2); // remove `0.` + }, -TokenGen.generate = function(tlen) -{ - var res = ""; - var nbRands = Math.ceil(tlen/10); //10 = min length of a rand() string - for (var i = 0; i < nbRands; i++) - res += TokenGen.rand(); - return res.substr(0, tlen); + generate: function(tlen) { + var res = ""; + var nbRands = Math.ceil(tlen/10); //10 = min length of a rand() string + for (var i = 0; i < nbRands; i++) + res += TokenGen.rand(); + return res.substr(0, tlen); + }, } - -module.exports = TokenGen; diff --git a/views/index.pug b/views/index.pug index 6b13a4e9..823b67c5 100644 --- a/views/index.pug +++ b/views/index.pug @@ -14,7 +14,7 @@ block content include welcome/fr .row #header.col-sm-12.col-md-10.col-md-offset-1.col-lg-8.col-lg-offset-2 - #mainTitle + #mainTitle.clickable(onClick="doClick('modalWelcome')") img(src="/images/index/unicorn.svg") .info-container p vchess.club @@ -22,16 +22,21 @@ block content #flagMenu.clickable(onClick="doClick('modalLang')") img(src="/images/flags/" + lang + ".svg") include userMenu - #introductionMenu.clickable(onClick="doClick('modalWelcome')") + #mygamesMenu.clickable.right-menu(v-show="display=='variants'" @click="display='games'") .info-container - p Introduction - .row + p My games + #variantsMenu.clickable.right-menu(v-show="display=='games'" @click="display='variants'") + .info-container + p Variants + .row(v-show="display=='variants'") .col-sm-12.col-md-10.col-md-offset-1.col-lg-8.col-lg-offset-2 label(for="prefixFilter") Type first letters... input#prefixFilter(v-model="curPrefix") - .row my-variant-summary(v-for="(v,idx) in sortedCounts" v-bind:vobj="v" v-bind:index="idx" v-bind:key="v.name") + .row(v-show="display=='games'") + .col-sm-12.col-md-10.col-md-offset-1.col-lg-8.col-lg-offset-2 + p TODO: load from server, show timeControl + players + link "play" block javascripts script. diff --git a/views/userMenu.pug b/views/userMenu.pug index f590a2ee..5a0b0743 100644 --- a/views/userMenu.pug +++ b/views/userMenu.pug @@ -1,4 +1,4 @@ -#userMenu.clickable(onClick="doClick('modalUser')") +#userMenu.clickable.right-menu(onClick="doClick('modalUser')") .info-container if !user.email p