Some fixes, problems logic now functional
authorBenjamin Auder <benjamin.auder@somewhere>
Tue, 18 Dec 2018 15:50:43 +0000 (16:50 +0100)
committerBenjamin Auder <benjamin.auder@somewhere>
Tue, 18 Dec 2018 15:50:43 +0000 (16:50 +0100)
TODO
package-lock.json
public/javascripts/components/game.js
public/javascripts/components/problemSummary.js
public/javascripts/components/problems.js
public/stylesheets/variant.sass
routes/all.js
views/index.pug

diff --git a/TODO b/TODO
index 3684a84..4b311b0 100644 (file)
--- a/TODO
+++ b/TODO
@@ -1,4 +1,2 @@
-Set problems style (maybe will fix strange flashing bug?)
 global lang cookie, + display (remember in each variant what is shown...)
 translations (how ? switch on index page only, then find ideas...)
-Improve style for various screen sizes
index 783e409..cf4aad0 100644 (file)
         "code-point-at": {
           "version": "1.1.0",
           "bundled": true,
-          "dev": true
+          "dev": true,
+          "optional": true
         },
         "concat-map": {
           "version": "0.0.1",
         "console-control-strings": {
           "version": "1.1.0",
           "bundled": true,
-          "dev": true
+          "dev": true,
+          "optional": true
         },
         "core-util-is": {
           "version": "1.0.2",
         "inherits": {
           "version": "2.0.3",
           "bundled": true,
-          "dev": true
+          "dev": true,
+          "optional": true
         },
         "ini": {
           "version": "1.3.5",
           "version": "1.0.0",
           "bundled": true,
           "dev": true,
+          "optional": true,
           "requires": {
             "number-is-nan": "^1.0.0"
           }
         "number-is-nan": {
           "version": "1.0.1",
           "bundled": true,
-          "dev": true
+          "dev": true,
+          "optional": true
         },
         "object-assign": {
           "version": "4.1.1",
           "version": "1.0.2",
           "bundled": true,
           "dev": true,
+          "optional": true,
           "requires": {
             "code-point-at": "^1.0.0",
             "is-fullwidth-code-point": "^1.0.0",
       },
       "dependencies": {
         "readable-stream": {
-          "version": "3.0.6",
-          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.0.6.tgz",
-          "integrity": "sha512-9E1oLoOWfhSXHGv6QlwXJim7uNzd9EVlWK+21tCU9Ju/kR0/p2AZYPz4qSchgO8PlLIH4FpZYfzwS+rEksZjIg==",
+          "version": "3.1.0",
+          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.1.0.tgz",
+          "integrity": "sha512-vpydAvIJvPODZNagCPuHG87O9JNPtvFEtjHHRVwNVsVVRBqemvPJkc2SYbxJsiZXawJdtZNmkmnsPuE3IgsG0A==",
           "requires": {
             "inherits": "^2.0.3",
             "string_decoder": "^1.1.1",
       "dev": true
     },
     "postcss": {
-      "version": "7.0.6",
-      "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.6.tgz",
-      "integrity": "sha512-Nq/rNjnHFcKgCDDZYO0lNsl6YWe6U7tTy+ESN+PnLxebL8uBtYX59HZqvrj7YLK5UCyll2hqDsJOo3ndzEW8Ug==",
+      "version": "7.0.7",
+      "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.7.tgz",
+      "integrity": "sha512-HThWSJEPkupqew2fnuQMEI2YcTj/8gMV3n80cMdJsKxfIh5tHf7nM5JigNX6LxVMqo6zkgQNAI88hyFvBk41Pg==",
       "requires": {
         "chalk": "^2.4.1",
         "source-map": "^0.6.1",
       "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
     },
     "sanitize-html": {
-      "version": "1.19.3",
-      "resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-1.19.3.tgz",
-      "integrity": "sha512-QpIjbF1rhUSQj9V7Wey/gv4DPqOso8KTebaI4rC97p0WCLnTpmhf7BJZUhS83MTtqRvUo8MuXH316CW2Nzd48w==",
+      "version": "1.20.0",
+      "resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-1.20.0.tgz",
+      "integrity": "sha512-BpxXkBoAG+uKCHjoXFmox6kCSYpnulABoGcZ/R3QyY9ndXbIM5S94eOr1IqnzTG8TnbmXaxWoDDzKC5eJv7fEQ==",
       "requires": {
         "chalk": "^2.4.1",
         "htmlparser2": "^3.10.0",
index 16e1fdb..186c027 100644 (file)
@@ -326,7 +326,7 @@ Vue.component('my-game', {
                                        ]
                                );
                        }
-                       if (this.mode == "friend")
+                       if (["friend","problem"].includes(this.mode))
                        {
                                actionArray = actionArray.concat(
                                [
@@ -778,7 +778,7 @@ Vue.component('my-game', {
                                                        h('h3',
                                                                {
                                                                        domProps: { innerHTML: "Show solution" },
-                                                                       on: { click: "toggleShowSolution" }
+                                                                       on: { click: this.toggleShowSolution },
                                                                }
                                                        ),
                                                        h('p',
@@ -969,9 +969,10 @@ Vue.component('my-game', {
        methods: {
                toggleShowSolution: function() {
                        let problemSolution = document.getElementById("problem-solution");
-                       problemSolution.style.display = problemSolution.style.display == "none"
-                               ? "block"
-                               : "none";
+                       problemSolution.style.display =
+                               !problemSolution.style.display || problemSolution.style.display == "none"
+                                       ? "block"
+                                       : "none";
                },
                download: function() {
                        let content = document.getElementById("pgn-game").innerHTML;
@@ -1142,7 +1143,7 @@ Vue.component('my-game', {
                                this.fenStart = localStorage.getItem(prefix+"fenStart");
                        }
                        else
-                               this.fenStart = fen;
+                               this.fenStart = V.ParseFen(fen).position; //this is enough
                        if (mode=="human")
                        {
                                // Opponent found!
@@ -1168,6 +1169,8 @@ Vue.component('my-game', {
                },
                playComputerMove: function() {
                        const timeStart = Date.now();
+                       // TODO: next call asynchronous (avoid freezing interface while computer "think").
+                       // This would also allow to remove some artificial setTimeouts
                        const compMove = this.vr.getComputerMove();
                        // (first move) HACK: avoid selecting elements before they appear on page:
                        const delay = Math.max(250-(Date.now()-timeStart), 0);
@@ -1375,7 +1378,18 @@ Vue.component('my-game', {
                undoInGame: function() {
                        const lm = this.vr.lastMove;
                        if (!!lm)
+                       {
                                this.vr.undo(lm);
+                               const lmBefore = this.vr.lastMove;
+                               if (!!lmBefore)
+                               {
+                                       this.vr.undo(lmBefore);
+                                       this.incheck = this.vr.getCheckSquares(lmBefore);
+                                       this.vr.play(lmBefore, "ingame");
+                               }
+                               else
+                                       this.incheck = [];
+                       }
                },
        },
 })
index c0b409d..e7e1db7 100644 (file)
@@ -1,20 +1,25 @@
-// Show a problem summary on variant page
+// Show a problem summary on variant page or new problem preview
 Vue.component('my-problem-summary', {
-       props: ['prob'],
+       props: ['prob','preview'],
        template: `
-               <div class="problem col-sm-12" @click="showProblem()">
-                       <div class="diagram" v-html="getDiagram(prob.fen)"></div>
-                       <div class="problem-instructions" v-html="prob.instructions.substr(0,32)"></div>
-                       <div class="problem-time">{{ timestamp2date(prob.added) }}</div>
+               <div class="problem row" @click="showProblem()">
+                       <div class="col-sm-12 col-md-6 col-lg-3 diagram"
+                               v-html="getDiagram(prob.fen)">
+                       </div>
+                       <div class="col-sm-12 col-md-6 col-lg-9">
+                               <p v-html="prob.instructions"></p>
+                               <p v-if="preview" v-html="prob.solution"></p>
+                               <p v-else class="problem-time">{{ timestamp2date(prob.added) }}</p>
+                       </div>
                </div>
        `,
        methods: {
                getDiagram: function(fen) {
-                       const fenParts = fen.split(" ");
+                       const fenParsed = V.ParseFen(fen);
                        return getDiagram({
-                               position: fenParts[0],
+                               position: fenParsed.position,
+                               turn: fenParsed.turn,
                                // No need for flags here
-                               turn: fenParts[2],
                        });
                },
                timestamp2date(ts) {
index 3bd13f6..9117ebf 100644 (file)
@@ -16,7 +16,8 @@ Vue.component('my-problems', {
                        <button @click="fetchProblems('forward')">Next</button>
                        <button @click="showNewproblemModal">New</button>
                        <my-problem-summary v-on:show-problem="bubbleUp(p)"
-                               v-for="(p,idx) in sortedProblems" v-bind:prob="p" v-bind:key="idx">
+                               v-for="(p,idx) in sortedProblems"
+                               v-bind:prob="p" v-bind:preview="false" v-bind:key="idx">
                        </my-problem-summary>
                        <input type="checkbox" id="modal-newproblem" class="modal">
                        <div role="dialog" aria-labelledby="newProblemTxt">
@@ -32,18 +33,22 @@ Vue.component('my-problems', {
                                                        <p class="emphasis">Safe HTML tags allowed</p>
                                                        <label for="newpbInstructions">Instructions</label>
                                                        <textarea id="newpbInstructions" v-model="newProblem.instructions"
-                                                               placeholder="Explain the problem here"/>
+                                                               placeholder="Explain the problem here"></textarea>
                                                        <label for="newpbSolution">Solution</label>
                                                        <textarea id="newpbSolution" v-model="newProblem.solution"
-                                                               placeholder="How to solve the problem?"/>
+                                                               placeholder="How to solve the problem?"></textarea>
                                                        <button class="center-btn">Preview</button>
                                                </fieldset>
                                        </form>
                                </div>
                                <div v-show="newProblem.stage=='preview'" class="card newproblem-preview">
-                                       // TODO: we don't want exactly the same display (-date +solution)
-                                       <my-problem-summary v-bind:prob="newProblem"></my-problem-summary>
-                                       <button @click="sendNewProblem()" class="center-btn">Send</button>
+                                       <label for="modal-newproblem" class="modal-close"></label>
+                                       <my-problem-summary v-bind:prob="newProblem" v-bind:preview="true">
+                                       </my-problem-summary>
+                                       <div class="col-sm-12 col-md-6 col-lg-3 col-lg-offset-3 topspace">
+                                               <button @click="sendNewProblem()">Send</button>
+                                               <button @click="newProblem.stage='nothing'">Cancel</button>
+                                       </div>
                                </div>
                        </div>
                </div>
@@ -99,6 +104,8 @@ Vue.component('my-problems', {
                                instructions: this.newProblem.instructions,
                                solution: this.newProblem.solution,
                        }, response => {
+                               this.newProblem.added = Date.now();
+                               this.problems.push(JSON.parse(JSON.stringify(this.newProblem)));
                                document.getElementById("modal-newproblem").checked = false;
                                this.newProblem.stage = "nothing";
                        });
index 6472e3d..856f22b 100644 (file)
@@ -246,7 +246,7 @@ ul:not(.browser-default) > li
   margin-left: 0
   margin-right: 0
 
-.newproblem input, .newproblem textarea
+.newproblem-form input, .newproblem-form textarea
   width: 100%
 
 .emphasis
@@ -270,3 +270,13 @@ ul:not(.browser-default) > li
 
 #problem-solution
   display: none
+
+.topspace
+  margin-top: 15px
+
+.problem
+  cursor: pointer
+  margin-bottom: 15px
+
+#solution-div h3
+  cursor: pointer
index b1e0fda..b966532 100644 (file)
@@ -69,7 +69,7 @@ router.post("/problems/:variant([a-zA-Z0-9]+)", (req,res) => {
        const timestamp = Date.now();
        // Sanitize them
        const fen = req.body["fen"];
-       if (!fen.match(/^[a-zA-Z0-9 /]*$/))
+       if (!fen.match(/^[a-zA-Z0-9, /-]*$/))
                return res.json({errmsg: "Bad characters in FEN string"});
        const instructions = sanitizeHtml(req.body["instructions"]);
        const solution = sanitizeHtml(req.body["solution"]);
index 9ef1967..62690a3 100644 (file)
@@ -21,7 +21,7 @@ block content
                                                p.section.
                                                        All games start with a random assymetric position. #[br]
                                                        Games are untimed, and played anonymously. #[br]
-                                                       No chat, to rather focus on the moves :)
+                                                       No chat while playing, to focus on the moves :)
                                                h3.red.section Bug report
                                                p.section
                                                        | If you find a bug in a game, please follow this procedure: #[br]