Draft or user bio support (ready in Hall, TODO in Game)
authorBenjamin Auder <benjamin.auder@somewhere>
Fri, 1 May 2020 18:31:02 +0000 (20:31 +0200)
committerBenjamin Auder <benjamin.auder@somewhere>
Fri, 1 May 2020 18:31:02 +0000 (20:31 +0200)
TODO
client/src/components/UserBio.vue [new file with mode: 0644]
client/src/store.js
client/src/translations/en.js
client/src/translations/es.js
client/src/translations/fr.js
client/src/variants/Rampage.js [new file with mode: 0644]
client/src/views/Hall.vue
server/db/create.sql
server/models/User.js
server/routes/users.js

diff --git a/TODO b/TODO
index cd69599..c2981ce 100644 (file)
--- a/TODO
+++ b/TODO
@@ -7,10 +7,10 @@ https://www.chessvariants.com/winning.dir/kinglet.html
 you need to win all the pawns to win the game
 kings are not royal
 
 you need to win all the pawns to win the game
 kings are not royal
 
-https://www.chessvariants.com/diffmove.dir/balaklava.html
-
 Rampage Chess: Any Unit May move to any empty square that is guarded. A King cannot make a special move to get out of check.
 
 Rampage Chess: Any Unit May move to any empty square that is guarded. A King cannot make a special move to get out of check.
 
+https://www.chessvariants.com/rules/pacifist-chess (1 et 2, utilisant somme values ou nb pièces)
+
 Swap chess: Friendly pieces may swap places
 
 https://www.chessvariants.com/crossover.dir/koopachess.html
 Swap chess: Friendly pieces may swap places
 
 https://www.chessvariants.com/crossover.dir/koopachess.html
diff --git a/client/src/components/UserBio.vue b/client/src/components/UserBio.vue
new file mode 100644 (file)
index 0000000..c954f3d
--- /dev/null
@@ -0,0 +1,90 @@
+<template lang="pug">
+div
+  input#modalBio.modal(type="checkbox")
+  div#bioDiv(
+    role="dialog"
+    data-checkbox="modalBio"
+  )
+    .card
+      div(v-if="st.user.id == id")
+        h3.section(@click="modeEdit = !modeEdit") Click to edit
+        textarea(
+          v-if="userBio !== undefined"
+          v-show="modeEdit"
+          v-model="userBio"
+        )
+        button#submitBtn(@click="sendBio()") Submit
+      div(
+        v-if="userBio !== undefined"
+        v-html="userBio"
+        @click="modeEdit = !modeEdit"
+      )
+      #dialog.text-center {{ st.tr[infoMsg] }}
+  span.clickable(@click="showBio()") {{ name }}
+</template>
+
+<script>
+import { store } from "@/store";
+import { ajax } from "@/utils/ajax";
+import { processModalClick } from "@/utils/modalClick.js";
+export default {
+  name: "my-user-bio",
+  props: ["id", "name"],
+  data: function() {
+    return {
+      st: store.state,
+      userBio: undefined,
+      infoMsg: "",
+      modeEdit: false
+    };
+  },
+  mounted: function() {
+    document.getElementById("bioDiv")
+      .addEventListener("click", processModalClick);
+  },
+  methods: {
+    showBio: function() {
+      this.infoMsg = "";
+      document.getElementById("modalBio").checked = true;
+      if (this.userBio === undefined) {
+        ajax(
+          "/userbio",
+          "GET",
+          {
+            data: { id: this.id },
+            success: (res) => {
+              this.userBio = res.bio;
+            }
+          }
+        );
+      }
+    },
+    sendBio: function() {
+      ajax(
+        "/userbio",
+        "PUT",
+        {
+          data: { bio: this.userBio },
+          success: () => {
+            this.infoMsg = this.st.tr["Modifications applied!"];
+          }
+        }
+      );
+    }
+  }
+};
+</script>
+
+<style lang="sass" scoped>
+[type="checkbox"].modal+div .card
+  max-width: 768px
+  max-height: 100%
+
+#submitBtn
+  width: 50%
+  margin: 0 auto
+
+#dialog
+  padding: 5px
+  color: blue
+</style>
index 33d0312..fa363a3 100644 (file)
@@ -46,7 +46,6 @@ export const store = {
       name: localStorage.getItem("myname") || "", //"" for "anonymous"
       email: "", //unknown yet
       notify: false, //email notifications
       name: localStorage.getItem("myname") || "", //"" for "anonymous"
       email: "", //unknown yet
       notify: false, //email notifications
-      newsRead: localStorage.getItem("newsRead") || 0,
       sid: mysid
     };
     // Slow verification through the server:
       sid: mysid
     };
     // Slow verification through the server:
@@ -79,8 +78,6 @@ export const store = {
         localStorage.removeItem("myname");
       this.state.user.email = json.email;
       this.state.user.notify = json.notify;
         localStorage.removeItem("myname");
       this.state.user.email = json.email;
       this.state.user.notify = json.notify;
-      if (!!json.newsRead && json.newsRead > this.state.user.newsRead)
-        this.state.user.newsRead = json.newsRead;
     });
     // Settings initialized with values from localStorage
     const getItemDefaultTrue = (item) => {
     });
     // Settings initialized with values from localStorage
     const getItemDefaultTrue = (item) => {
index 91667a7..a72cf61 100644 (file)
@@ -154,7 +154,6 @@ export const translations = {
   "Who's there?": "Who's there?",
   With: "With",
   with: "with",
   "Who's there?": "Who's there?",
   With: "With",
   with: "with",
-  "Write news": "Write news",
   "Wrong time control": "Wrong time control",
   "Your message": "Your message",
 
   "Wrong time control": "Wrong time control",
   "Your message": "Your message",
 
index daf09ae..10e5422 100644 (file)
@@ -154,7 +154,6 @@ export const translations = {
   "Who's there?": "¿Quién está ahí?",
   With: "Con",
   with: "con",
   "Who's there?": "¿Quién está ahí?",
   With: "Con",
   with: "con",
-  "Write news": "Escribir una news",
   "Wrong time control": "Cadencia errónea",
   "Your message": "Tu mensaje",
 
   "Wrong time control": "Cadencia errónea",
   "Your message": "Tu mensaje",
 
index 6b57c32..c4de144 100644 (file)
@@ -154,7 +154,6 @@ export const translations = {
   "Who's there?": "Qui est là ?",
   With: "Avec",
   with: "avec",
   "Who's there?": "Qui est là ?",
   With: "Avec",
   with: "avec",
-  "Write news": "Écrire une news",
   "Wrong time control": "Cadence erronée",
   "Your message": "Votre message",
 
   "Wrong time control": "Cadence erronée",
   "Your message": "Votre message",
 
diff --git a/client/src/variants/Rampage.js b/client/src/variants/Rampage.js
new file mode 100644 (file)
index 0000000..31d4f35
--- /dev/null
@@ -0,0 +1,10 @@
+import { ChessRules } from "@/base_rules";
+
+// Plan : garder intact isAttacked,
+// ajouter "guarded" qui somme les attaques blanches et soustrait les attaques noires sur une case
+// (regarder toutes directions, OK)
+// --> boulot à faire sur chaque case vide, après chaque getPotentialMoves()
+// --> sauf si le roi est en échec (avant de jouer).
+
+export class RampageRules extends ChessRules {
+};
index 0e2c1c6..48af22e 100644 (file)
@@ -113,7 +113,7 @@ main
             v-for="sid in Object.keys(people)"
             v-if="!!people[sid].name"
           )
             v-for="sid in Object.keys(people)"
             v-if="!!people[sid].name"
           )
-            span {{ people[sid].name }}
+            UserBio(:id="people[sid].id" :name="people[sid].name")
             button.player-action(
               v-if="isGamer(sid)"
               @click="watchGame(sid)"
             button.player-action(
               v-if="isGamer(sid)"
               @click="watchGame(sid)"
@@ -212,6 +212,7 @@ import params from "@/parameters";
 import { getRandString, shuffle, randInt } from "@/utils/alea";
 import { getDiagram } from "@/utils/printDiagram";
 import Chat from "@/components/Chat.vue";
 import { getRandString, shuffle, randInt } from "@/utils/alea";
 import { getDiagram } from "@/utils/printDiagram";
 import Chat from "@/components/Chat.vue";
+import UserBio from "@/components/UserBio.vue";
 import GameList from "@/components/GameList.vue";
 import ChallengeList from "@/components/ChallengeList.vue";
 import { GameStorage } from "@/utils/gameStorage";
 import GameList from "@/components/GameList.vue";
 import ChallengeList from "@/components/ChallengeList.vue";
 import { GameStorage } from "@/utils/gameStorage";
@@ -220,6 +221,7 @@ export default {
   name: "my-hall",
   components: {
     Chat,
   name: "my-hall",
   components: {
     Chat,
+    UserBio,
     GameList,
     ChallengeList
   },
     GameList,
     ChallengeList
   },
index 84b72b9..15417b1 100644 (file)
@@ -16,7 +16,7 @@ create table Users (
   sessionToken varchar,
   created datetime,
   notify boolean,
   sessionToken varchar,
   created datetime,
   notify boolean,
-  newsRead datetime
+  bio text default ''
 );
 
 create table Problems (
 );
 
 create table Problems (
index edb3c06..8a97d57 100644 (file)
@@ -13,7 +13,7 @@ const sendEmail = require('../utils/mailer');
  *   sessionToken: token in cookies for authentication
  *   notify: boolean (send email notifications for corr games)
  *   created: datetime
  *   sessionToken: token in cookies for authentication
  *   notify: boolean (send email notifications for corr games)
  *   created: datetime
- *   newsRead: datetime
+ *   bio: text
  */
 
 const UserModel = {
  */
 
 const UserModel = {
@@ -58,6 +58,16 @@ const UserModel = {
     });
   },
 
     });
   },
 
+  getBio: function(id) {
+    db.serialize(function() {
+      const query =
+        "SELECT bio " +
+        "FROM Users " +
+        "WHERE id = " + id;
+      db.get(query, cb);
+    });
+  },
+
   /////////
   // MODIFY
 
   /////////
   // MODIFY
 
@@ -71,13 +81,13 @@ const UserModel = {
     });
   },
 
     });
   },
 
-  setNewsRead: function(id) {
+  setBio: function(id, bio) {
     db.serialize(function() {
       const query =
         "UPDATE Users " +
     db.serialize(function() {
       const query =
         "UPDATE Users " +
-        "SET newsRead = " + Date.now() + " " +
+        "SET bio = ? " +
         "WHERE id = " + id;
         "WHERE id = " + id;
-      db.run(query);
+      db.run(query, bio);
     });
   },
 
     });
   },
 
index 7898ac8..a9adc16 100644 (file)
@@ -4,6 +4,22 @@ const sendEmail = require('../utils/mailer');
 const genToken = require("../utils/tokenGenerator");
 const access = require("../utils/access");
 const params = require("../config/parameters");
 const genToken = require("../utils/tokenGenerator");
 const access = require("../utils/access");
 const params = require("../config/parameters");
+const sanitizeHtml = require('sanitize-html');
+
+router.get("/userbio", access.ajax, (req,res) => {
+  const uid = req.query["id"];
+  if (!!(uid.toString().match(/^[0-9]+$/))) {
+    UserModel.getBio(uid, (err, bio) => {
+      res.json(bio);
+    });
+  }
+});
+
+router.put('/userbio', access.logged, access.ajax, (req,res) => {
+  const bio = sanitizeHtml(req.body.bio);
+  UserModel.setBio(req.userId, bio);
+  res.json({});
+});
 
 router.post('/register', access.unlogged, access.ajax, (req,res) => {
   const name = req.body.name;
 
 router.post('/register', access.unlogged, access.ajax, (req,res) => {
   const name = req.body.name;
@@ -36,16 +52,14 @@ router.get("/whoami", access.ajax, (req,res) => {
       name: user.name,
       email: user.email,
       id: user.id,
       name: user.name,
       email: user.email,
       id: user.id,
-      notify: user.notify,
-      newsRead: user.newsRead
+      notify: user.notify
     });
   };
   const anonymous = {
     name: "",
     email: "",
     id: 0,
     });
   };
   const anonymous = {
     name: "",
     email: "",
     id: 0,
-    notify: false,
-    newsRead: 0
+    notify: false
   };
   if (!req.cookies.token) callback(anonymous);
   else if (req.cookies.token.match(/^[a-z0-9]+$/)) {
   };
   if (!req.cookies.token) callback(anonymous);
   else if (req.cookies.token.match(/^[a-z0-9]+$/)) {
@@ -60,8 +74,8 @@ router.get("/users", access.ajax, (req,res) => {
   const ids = req.query["ids"];
   // NOTE: slightly too permissive RegExp
   if (ids.match(/^([0-9]+,?)+$/)) {
   const ids = req.query["ids"];
   // NOTE: slightly too permissive RegExp
   if (ids.match(/^([0-9]+,?)+$/)) {
-    UserModel.getByIds(ids, (err,users) => {
-      res.json({users:users});
+    UserModel.getByIds(ids, (err, users) => {
+      res.json({ users:users });
     });
   }
 });
     });
   }
 });
@@ -81,12 +95,6 @@ router.put('/update', access.logged, access.ajax, (req,res) => {
   }
 });
 
   }
 });
 
-// Special route to update newsRead timestamp:
-router.put('/newsread', access.logged, access.ajax, (req,res) => {
-  UserModel.setNewsRead(req.userId);
-  res.json({});
-});
-
 // Authentication-related methods:
 
 // to: object user (to who we send an email)
 // Authentication-related methods:
 
 // to: object user (to who we send an email)