From 5b3dc10e34bf5bf970494be6ee1fa0b67e2ca88c Mon Sep 17 00:00:00 2001
From: Benjamin Auder <benjamin.auder@somewhere>
Date: Fri, 28 Feb 2020 14:57:02 +0100
Subject: [PATCH] Better site presentation (especially for languages settings)

---
 client/public/images/settings.svg  |  7 +++
 client/src/App.vue                 | 43 ++++++-----------
 client/src/components/BaseGame.vue | 66 ++------------------------
 client/src/components/Language.vue | 46 ------------------
 client/src/components/MoveList.vue | 76 +++++++++++++++++++++++++++++-
 client/src/components/Settings.vue | 45 +++++++++++++++++-
 6 files changed, 141 insertions(+), 142 deletions(-)
 create mode 100644 client/public/images/settings.svg
 delete mode 100644 client/src/components/Language.vue

diff --git a/client/public/images/settings.svg b/client/public/images/settings.svg
new file mode 100644
index 00000000..d7839216
--- /dev/null
+++ b/client/public/images/settings.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Svg Vector Icons : http://www.onlinewebfonts.com/icon -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 1000 1000" enable-background="new 0 0 1000 1000" xml:space="preserve">
+<metadata> Svg Vector Icons : http://www.onlinewebfonts.com/icon </metadata>
+<g><path d="M987.5,633c1.4,8.4,1.1,18.6-1.1,30.5c-2.1,11.9-5.6,24-10.5,36.3C971,712,965,723,958,732.8c-7,9.8-14.7,16.8-23.1,21c-8.4,4.2-15.8,6.3-22.1,6.3c-6.3,0-13.3-1.4-21-4.2c-7-2.1-15.8-4-26.3-5.8c-10.5-1.8-21.2-2.1-32.1-1.1c-10.9,1.1-21.7,3.3-32.6,6.8c-10.9,3.5-20.1,9.5-27.9,17.9c-16.8,17.5-26.6,37.5-29.4,59.9c-2.8,22.4,0.4,43.8,9.5,64.1c7,14,6,28-3.2,42c-4.2,5.6-10.9,11.4-20,17.3c-9.1,6-19.1,11.4-30,16.3c-10.9,4.9-22.2,8.8-34.2,11.6c-11.9,2.8-22.4,4.2-31.5,4.2c-6.3,0-12.3-2.5-17.9-7.4c-5.6-4.9-9.5-10.2-11.6-15.8h-1.1c-7.7-21.7-20.8-40.5-39.4-56.2c-18.6-15.8-40.1-23.6-64.6-23.6c-23.8,0-45.4,7.9-64.6,23.6c-19.3,15.8-32.8,34.2-40.5,55.2c-3.5,8.4-8.8,14.5-15.8,18.4c-7,3.9-14.7,5.8-23.1,5.8c-9.8,0-20.8-1.8-33.1-5.3c-12.3-3.5-24.5-7.9-36.8-13.1c-12.3-5.3-23.3-11.4-33.1-18.4c-9.8-7-17.2-14-22.1-21c-3.5-4.9-5.4-10.7-5.8-17.3c-0.4-6.7,2.3-15.9,7.9-27.9c7.7-16.1,10.7-34.5,8.9-55.2c-1.8-20.7-10.7-39.8-26.8-57.3c-9.8-10.5-21.7-17.3-35.7-20.5c-14-3.1-27.3-4.4-39.9-3.7c-14.7,0.7-29.8,3.5-45.2,8.4c-9.8,2.8-19.6,2.1-29.4-2.1c-7.7-2.8-14.9-9.3-21.6-19.4c-6.7-10.2-12.6-21.4-17.9-33.6C20,690.6,16,678,13.2,665c-2.8-13-3.5-23.6-2.1-32.1c2.1-15.4,9.1-25.2,21-29.4c21-8.4,39.9-22.2,56.8-41.5c16.8-19.3,25.2-40.8,25.2-64.6c0-24.5-8.4-45.9-25.2-64.1C72,415,53.1,401.7,32.1,393.3c-6.3-2.1-11.6-7.2-15.8-15.2c-4.2-8.1-6.3-16.3-6.3-24.7c0-9.1,1.4-19.3,4.2-30.5c2.8-11.2,6.5-22.1,11-32.6c4.6-10.5,9.8-20.1,15.8-28.9c6-8.8,12.4-15.2,19.4-19.4c5.6-3.5,11-4.9,16.3-4.2c5.3,0.7,11,2.1,17.3,4.2c21,8.4,42.9,11,65.7,7.9c22.8-3.2,42.9-13.1,60.4-30c8.4-8.4,14.5-18.7,18.4-31c3.9-12.3,6.3-24.4,7.4-36.3c1-11.9,1-22.8,0-32.6c-1.1-9.8-1.9-16.8-2.6-21c-1.4-4.2-2.6-9.1-3.7-14.7c-1.1-5.6-0.5-10.5,1.6-14.7c4.2-9.8,11.7-18.4,22.6-25.8c10.9-7.4,22.6-13.5,35.2-18.4c12.6-4.9,24.9-8.6,36.8-11c11.9-2.5,21.4-3.7,28.4-3.7c9.1,0,16.3,3,21.5,8.9c5.3,6,8.9,12.1,11,18.4c7.7,18.9,20.3,35.6,37.8,49.9c17.5,14.4,38.2,21.5,62,21.5c24.5,0,46.2-6.8,65.2-20.5c18.9-13.7,32.2-31,39.9-52c2.8-5.6,7.2-11.4,13.1-17.3c6-6,12.1-8.9,18.4-8.9c9.8,0,20.5,1.4,32.1,4.2c11.6,2.8,22.9,6.7,34.2,11.6c11.2,4.9,21.5,11.2,31,18.9c9.5,7.7,17,16.1,22.6,25.2c3.5,5.6,4.6,11.7,3.2,18.4s-2.8,11.4-4.2,14.2c-9.1,20.3-11.9,41.7-8.4,64.1c3.5,22.4,13.7,42,30.5,58.9c16.8,16.8,37.5,26.1,62,27.8c24.5,1.8,47.3-2.3,68.3-12.1c5.6-3.5,12.4-4.9,20.5-4.2c8.1,0.7,14.9,3.9,20.5,9.5c10.5,9.8,19.8,24.7,27.9,44.7c8.1,20,13.5,40.1,16.3,60.4c1.4,11.9-0.5,21.2-5.8,27.9c-5.3,6.7-10.7,11-16.3,13.1c-21.7,7.7-40.3,21.2-55.7,40.5c-15.4,19.3-23.1,41.2-23.1,65.7c0,23.8,6.5,44.7,19.4,62.5c13,17.9,29.9,30.7,51,38.4c4.9,2.8,9.1,5.6,12.6,8.4C979.4,615.1,984.7,623.1,987.5,633L987.5,633z M498.7,727.6c31.5,0,61.3-6,89.3-17.9c28-11.9,52.4-28.4,73-49.4c20.7-21,37-45.4,48.9-73c11.9-27.7,17.9-57.3,17.9-88.8c0-31.5-6-61.1-17.9-88.8c-11.9-27.7-28.2-51.9-48.9-72.5c-20.7-20.7-45-37-73-48.9c-28-11.9-57.8-17.9-89.3-17.9c-31.5,0-61.1,6-88.8,17.9c-27.7,11.9-51.8,28.2-72.5,48.9c-20.7,20.7-37,44.9-48.9,72.5c-11.9,27.7-17.9,57.3-17.9,88.8c0,31.5,6,61.1,17.9,88.8c11.9,27.7,28.2,52,48.9,73c20.7,21,44.8,37.5,72.5,49.4C437.6,721.6,467.2,727.6,498.7,727.6L498.7,727.6z"/></g>
+</svg>
\ No newline at end of file
diff --git a/client/src/App.vue b/client/src/App.vue
index 9c724e76..b98618bf 100644
--- a/client/src/App.vue
+++ b/client/src/App.vue
@@ -1,6 +1,5 @@
 <template lang="pug">
 #app
-  Language
   Settings
   ContactForm
   UpsertUser
@@ -9,7 +8,7 @@
       .col-sm-12.col-md-10.col-md-offset-1.col-lg-8.col-lg-offset-2
         // Menu (top of page):
         // Left: hall, variants, problems, mygames
-        // Right: usermenu, settings, flag
+        // Right: usermenu, settings
         nav
           label.drawer-toggle(for="drawerControl")
           input#drawerControl.drawer(type="checkbox")
@@ -27,13 +26,9 @@
             #rightMenu
               .clickable(onClick="window.doClick('modalUser')")
                 | {{ st.user.id > 0 ? (st.user.name || "@nonymous") : "Login" }}
-              .clickable(onClick="window.doClick('modalSettings')")
-                | {{ st.tr["Settings"] }}
-              .clickable#flagContainer(onClick="window.doClick('modalLang')")
-                img(
-                  v-if="!!st.lang"
-                  :src="flagImage"
-                )
+              #divSettings.clickable(onClick="window.doClick('modalSettings')")
+                span {{ st.tr["Settings"] }}
+                img(src="/images/settings.svg")
     router-view
   .row
     .col-sm-12.col-md-10.col-md-offset-1.col-lg-8.col-lg-offset-2
@@ -46,7 +41,6 @@
 
 <script>
 import ContactForm from "@/components/ContactForm.vue";
-import Language from "@/components/Language.vue";
 import Settings from "@/components/Settings.vue";
 import UpsertUser from "@/components/UpsertUser.vue";
 import { store } from "./store.js";
@@ -54,7 +48,6 @@ import { processModalClick } from "./utils/modalClick.js";
 export default {
   components: {
     ContactForm,
-    Language,
     Settings,
     UpsertUser
   },
@@ -63,11 +56,6 @@ export default {
       st: store.state
     };
   },
-  computed: {
-    flagImage: function() {
-      return `/images/flags/${this.st.lang}.svg`;
-    }
-  },
   mounted: function() {
     let dialogs = document.querySelectorAll("div[role='dialog']");
     dialogs.forEach(d => {
@@ -145,6 +133,16 @@ table
   th, td
     padding: 5px
 
+#divSettings
+  padding: 0 10px 0 0
+  height: 100%
+  & > span
+    vertical-align: middle
+  & > img
+    padding: 0
+    height: 24px
+    vertical-align: middle
+
 @media screen and (max-width: 767px)
   table
     tr > th, td
@@ -177,12 +175,6 @@ nav
         justify-content: flex-end
         & > div
           display: inline-block
-          &#flagContainer
-            display: inline-flex
-          & > img
-            padding: 0
-            width: 36px
-            height: 27px
     @media screen and (max-width: 767px)
       & > #leftMenu
         margin-top: 42px
@@ -194,13 +186,6 @@ nav
       & > #rightMenu
         padding-top: 5px
         border-top: 1px solid darkgrey
-        & > div
-          &#flagContainer
-            display: inline-flex
-          & > img
-            padding: 0
-            width: 36px
-            height: 27px
 
 @media screen and (max-width: 767px)
   nav
diff --git a/client/src/components/BaseGame.vue b/client/src/components/BaseGame.vue
index 1253c063..3820dc1b 100644
--- a/client/src/components/BaseGame.vue
+++ b/client/src/components/BaseGame.vue
@@ -8,21 +8,6 @@ div#baseGame
     .card.text-center
       label.modal-close(for="modalEog")
       h3.section {{ endgameMessage }}
-  input#modalAdjust.modal(type="checkbox")
-  div#adjuster(
-    role="dialog"
-    data-checkbox="modalAdjust"
-  )
-    .card.text-center
-      label.modal-close(for="modalAdjust")
-      label(for="boardSize") {{ st.tr["Board size"] }}
-      input#boardSize.slider(
-        type="range"
-        min="0"
-        max="100"
-        value="50"
-        @input="adjustBoard()"
-      )
   #gameContainer
     #boardContainer
       Board(
@@ -47,7 +32,6 @@ div#baseGame
         #downloadDiv(v-if="allowDownloadPGN")
           a#download(href="#")
           button(@click="download()") {{ st.tr["Download"] }} PGN
-        button(onClick="window.doClick('modalAdjust')") &#10530;
         button(
           v-if="canAnalyze"
           @click="analyzePosition()"
@@ -158,55 +142,14 @@ export default {
       baseGameDiv.addEventListener("keydown", this.handleKeys);
       baseGameDiv.addEventListener("wheel", this.handleScroll);
     }
-    [
-      document.getElementById("eogDiv"),
-      document.getElementById("adjuster")
-    ].forEach(elt => elt.addEventListener("click", processModalClick));
-    // Take full width on small screens:
-    let boardSize = parseInt(localStorage.getItem("boardSize"));
-    if (!boardSize) {
-      boardSize =
-        window.innerWidth >= 768
-          ? 0.75 * Math.min(window.innerWidth, window.innerHeight)
-          : window.innerWidth;
-    }
-    const movesWidth = window.innerWidth >= 768 ? 280 : 0;
-    document.getElementById("boardContainer").style.width = boardSize + "px";
-    let gameContainer = document.getElementById("gameContainer");
-    gameContainer.style.width = boardSize + movesWidth + "px";
-    document.getElementById("boardSize").value =
-      (boardSize * 100) / (window.innerWidth - movesWidth);
-    // timeout to avoid calling too many time the adjust method
-    let timeoutLaunched = false;
-    window.addEventListener("resize", () => {
-      if (!timeoutLaunched) {
-        timeoutLaunched = true;
-        setTimeout(() => {
-          this.adjustBoard();
-          timeoutLaunched = false;
-        }, 500);
-      }
-    });
+    document.getElementById("eogDiv").addEventListener(
+      "click",
+      processModalClick);
   },
   methods: {
     focusBg: function() {
       document.getElementById("baseGame").focus();
     },
-    adjustBoard: function() {
-      const boardContainer = document.getElementById("boardContainer");
-      if (!boardContainer) return; //no board on page
-      const k = document.getElementById("boardSize").value;
-      const movesWidth = window.innerWidth >= 768 ? 280 : 0;
-      const minBoardWidth = 240; //TODO: these 240 and 280 are arbitrary...
-      // Value of 0 is board min size; 100 is window.width [- movesWidth]
-      const boardSize =
-        minBoardWidth +
-        (k * (window.innerWidth - (movesWidth + minBoardWidth))) / 100;
-      localStorage.setItem("boardSize", boardSize);
-      boardContainer.style.width = boardSize + "px";
-      document.getElementById("gameContainer").style.width =
-        boardSize + movesWidth + "px";
-    },
     handleKeys: function(e) {
       if ([32, 37, 38, 39, 40].includes(e.keyCode)) e.preventDefault();
       switch (e.keyCode) {
@@ -530,9 +473,6 @@ export default {
 [type="checkbox"]#modalEog+div .card
   min-height: 45px
 
-[type="checkbox"]#modalAdjust+div .card
-  padding: 5px
-
 #baseGame
   width: 100%
   &:focus
diff --git a/client/src/components/Language.vue b/client/src/components/Language.vue
deleted file mode 100644
index f49a592e..00000000
--- a/client/src/components/Language.vue
+++ /dev/null
@@ -1,46 +0,0 @@
-<template lang="pug">
-div
-  -
-    var langName = {
-      "en": "English",
-      "es": "Español",
-      "fr": "Français",
-    };
-  input#modalLang.modal(type="checkbox")
-  div(
-    role="dialog"
-    data-checkbox="modalLang"
-  )
-    .card
-      label.modal-close(for="modalLang")
-      fieldset(@change="setLanguage($event)")
-        label(for="langSelect") {{ st.tr["Language"] }}
-        select#langSelect
-          each language,langCode in langName
-            option(value=langCode)
-              =language
-</template>
-
-<script>
-import { store } from "@/store";
-export default {
-  name: "my-language",
-  data: function() {
-    return {
-      st: store.state
-    };
-  },
-  mounted: function() {
-    // NOTE: better style would be in pug directly, but how?
-    document.querySelectorAll("#langSelect > option").forEach(opt => {
-      if (opt.value == this.st.lang) opt.selected = true;
-    });
-  },
-  methods: {
-    setLanguage: function(e) {
-      localStorage["lang"] = e.target.value;
-      store.setLanguage(e.target.value);
-    }
-  }
-};
-</script>
diff --git a/client/src/components/MoveList.vue b/client/src/components/MoveList.vue
index 920d5240..6ff93d8d 100644
--- a/client/src/components/MoveList.vue
+++ b/client/src/components/MoveList.vue
@@ -1,5 +1,23 @@
 <template lang="pug">
 div
+  input#modalAdjust.modal(type="checkbox")
+  div#adjuster(
+    role="dialog"
+    data-checkbox="modalAdjust"
+  )
+    .card.text-center
+      label.modal-close(for="modalAdjust")
+      label(for="boardSize") {{ st.tr["Board size"] }}
+      input#boardSize.slider(
+        type="range"
+        min="0"
+        max="100"
+        value="50"
+        @input="adjustBoard()"
+      )
+  div#boardSizeBtnContainer
+    button#boardSizeBtn(onClick="window.doClick('modalAdjust')")
+      | {{ st.tr["Board size"] }}
   #scoreInfo(v-if="score!='*'")
     p {{ score }}
     p {{ st.tr[message] }}
@@ -17,13 +35,12 @@ div
         @click="() => gotoMove(moveIdx+1)"
       )
         | {{ notation(moves[moveIdx+1]) }}
-      // Else: just add an empty cell
-      //.td(v-else)
 </template>
 
 <script>
 import { store } from "@/store";
 import { getFullNotation } from "@/utils/notation";
+import { processModalClick } from "@/utils/modalClick";
 export default {
   name: "my-move-list",
   props: ["moves", "show", "cursor", "score", "message", "firstNum"],
@@ -32,6 +49,36 @@ export default {
       st: store.state
     };
   },
+  mounted: function() {
+    document.getElementById("adjuster").addEventListener(
+      "click",
+      processModalClick);
+    // Take full width on small screens:
+    let boardSize = parseInt(localStorage.getItem("boardSize"));
+    if (!boardSize) {
+      boardSize =
+        window.innerWidth >= 768
+          ? 0.75 * Math.min(window.innerWidth, window.innerHeight)
+          : window.innerWidth;
+    }
+    const movesWidth = window.innerWidth >= 768 ? 280 : 0;
+    document.getElementById("boardContainer").style.width = boardSize + "px";
+    let gameContainer = document.getElementById("gameContainer");
+    gameContainer.style.width = boardSize + movesWidth + "px";
+    document.getElementById("boardSize").value =
+      (boardSize * 100) / (window.innerWidth - movesWidth);
+    // timeout to avoid calling too many time the adjust method
+    let timeoutLaunched = false;
+    window.addEventListener("resize", () => {
+      if (!timeoutLaunched) {
+        timeoutLaunched = true;
+        setTimeout(() => {
+          this.adjustBoard();
+          timeoutLaunched = false;
+        }, 500);
+      }
+    });
+  },
   watch: {
     cursor: function(newCursor) {
       if (window.innerWidth <= 767) return; //scrolling would hide chessboard
@@ -58,6 +105,21 @@ export default {
     },
     gotoMove: function(index) {
       this.$emit("goto-move", index);
+    },
+    adjustBoard: function() {
+      const boardContainer = document.getElementById("boardContainer");
+      if (!boardContainer) return; //no board on page
+      const k = document.getElementById("boardSize").value;
+      const movesWidth = window.innerWidth >= 768 ? 280 : 0;
+      const minBoardWidth = 240; //TODO: these 240 and 280 are arbitrary...
+      // Value of 0 is board min size; 100 is window.width [- movesWidth]
+      const boardSize =
+        minBoardWidth +
+        (k * (window.innerWidth - (movesWidth + minBoardWidth))) / 100;
+      localStorage.setItem("boardSize", boardSize);
+      boardContainer.style.width = boardSize + "px";
+      document.getElementById("gameContainer").style.width =
+        boardSize + movesWidth + "px";
     }
   }
 };
@@ -89,4 +151,14 @@ export default {
 
 .td.highlight-lm
   background-color: plum
+
+#boardSizeBtnContainer
+  width: 100%
+  text-align: center
+
+button#boardSizeBtn
+  margin: 0
+
+[type="checkbox"]#modalAdjust+div .card
+  padding: 5px
 </style>
diff --git a/client/src/components/Settings.vue b/client/src/components/Settings.vue
index 117133d1..a6c3e658 100644
--- a/client/src/components/Settings.vue
+++ b/client/src/components/Settings.vue
@@ -5,9 +5,27 @@ div
     role="dialog"
     data-checkbox="modalSettings"
   )
-    .card(@change="updateSettings($event)")
+    .card
       label.modal-close(for="modalSettings")
-      form
+      -
+        var langName = {
+          "en": "English",
+          "es": "Español",
+          "fr": "Français",
+        };
+      fieldset(@change="setLanguage($event)")
+        label(for="langSelect")
+          | {{ st.tr["Language"] }}
+        select#langSelect
+          each language,langCode in langName
+            option(value=langCode)
+              =language
+        #flagContainer
+          img(
+            v-if="!!st.lang"
+            :src="flagImage"
+          )
+      div(@change="updateSettings($event)")
         fieldset
           label(for="setHints") {{ st.tr["Show possible moves?"] }}
           input#setHints(
@@ -44,7 +62,22 @@ export default {
       st: store.state
     };
   },
+  mounted: function() {
+    // NOTE: better style would be in pug directly, but how?
+    document.querySelectorAll("#langSelect > option").forEach(opt => {
+      if (opt.value == this.st.lang) opt.selected = true;
+    });
+  },
+  computed: {
+    flagImage: function() {
+      return `/images/flags/${this.st.lang}.svg`;
+    }
+  },
   methods: {
+    setLanguage: function(e) {
+      localStorage["lang"] = e.target.value;
+      store.setLanguage(e.target.value);
+    },
     updateSettings: function(event) {
       const propName = event.target.id
         .substr(3)
@@ -63,4 +96,12 @@ export default {
 [type="checkbox"].modal+div .card
   max-width: 767px
   max-height: 100%
+#flagContainer
+  display: inline-block
+  height: 100%
+  & > img
+    vertical-align: middle
+    padding: 0 0 0 10px
+    width: 36px
+    height: 27px
 </style>
-- 
2.44.0