From e57c4de4148d43e7635e09adcde4e56585aea303 Mon Sep 17 00:00:00 2001 From: Benjamin Auder <benjamin.auder@somewhere> Date: Sun, 8 Mar 2020 11:59:11 +0100 Subject: [PATCH] Replaced AJAX by fetch: not everything tested yet, but seems fine --- client/src/components/ContactForm.vue | 21 ++-- client/src/components/GameList.vue | 10 +- client/src/components/UpsertUser.vue | 33 +++--- client/src/parameters.js.dist | 3 - client/src/store.js | 14 ++- client/src/utils/ajax.js | 78 ++++++------- client/src/views/Auth.vue | 21 ++-- client/src/views/Game.vue | 42 ++++--- client/src/views/Hall.vue | 161 ++++++++++++++++---------- client/src/views/Logout.vue | 19 +-- client/src/views/MyGames.vue | 37 +++--- client/src/views/News.vue | 96 +++++++++------ client/src/views/Problems.vue | 112 +++++++++++------- client/src/views/Rules.vue | 22 ++-- server/app.js | 20 +++- server/routes/all.js | 5 - server/routes/problems.js | 2 +- server/routes/users.js | 2 +- server/routes/variants.js | 2 +- server/while_update/favicon.ico | 1 + server/while_update/index.html | 27 +++++ 21 files changed, 440 insertions(+), 288 deletions(-) create mode 100644 server/while_update/favicon.ico create mode 100644 server/while_update/index.html diff --git a/client/src/components/ContactForm.vue b/client/src/components/ContactForm.vue index f9c5c60b..50270e69 100644 --- a/client/src/components/ContactForm.vue +++ b/client/src/components/ContactForm.vue @@ -23,7 +23,7 @@ div </template> <script> -import { ajax } from "../utils/ajax"; +import { ajax } from "@/utils/ajax"; import { store } from "@/store"; import { checkNameEmail } from "@/data/userCheck"; export default { @@ -66,14 +66,17 @@ export default { "/messages", "POST", { - email: email.value, - subject: subject.value, - content: content.value - }, - () => { - this.infoMsg = "Email sent!"; - subject.value = ""; - content.value = ""; + nocredentials: true, + data: { + email: email.value, + subject: subject.value, + content: content.value + }, + success: () => { + this.infoMsg = "Email sent!"; + subject.value = ""; + content.value = ""; + } } ); } diff --git a/client/src/components/GameList.vue b/client/src/components/GameList.vue index 098efd06..451d1bac 100644 --- a/client/src/components/GameList.vue +++ b/client/src/components/GameList.vue @@ -168,10 +168,12 @@ export default { "/games", "PUT", { - gid: game.id, - newObj: { removeFlag: true } - }, - afterDelete + data: { + gid: game.id, + newObj: { removeFlag: true } + }, + success: afterDelete + } ); } } diff --git a/client/src/components/UpsertUser.vue b/client/src/components/UpsertUser.vue index 2be637c6..ca322e0c 100644 --- a/client/src/components/UpsertUser.vue +++ b/client/src/components/UpsertUser.vue @@ -165,21 +165,26 @@ export default { ajax( this.ajaxUrl(), this.ajaxMethod(), - this.stage == "Login" - ? { nameOrEmail: this.nameOrEmail } - : this.user, - () => { - this.infoMsg = this.infoMessage(); - if (this.stage != "Update") this.nameOrEmail = ""; - else { - this.st.user.name = this.user.name; - this.st.user.email = this.user.email; - this.st.user.notify = this.user.notify; + { + credentials: true, + data: ( + this.stage == "Login" + ? { nameOrEmail: this.nameOrEmail } + : this.user + ), + success: () => { + this.infoMsg = this.infoMessage(); + if (this.stage != "Update") this.nameOrEmail = ""; + else { + this.st.user.name = this.user.name; + this.st.user.email = this.user.email; + this.st.user.notify = this.user.notify; + } + }, + error: (err) => { + this.infoMsg = ""; + alert(err); } - }, - err => { - this.infoMsg = ""; - alert(err); } ); }, diff --git a/client/src/parameters.js.dist b/client/src/parameters.js.dist index e96535b0..2e47407e 100644 --- a/client/src/parameters.js.dist +++ b/client/src/parameters.js.dist @@ -6,9 +6,6 @@ const Parameters = // URL of the server (leave blank for 1-server case) serverUrl: "http://localhost:3000", - // true if the server is at a different address - cors: true, - // "include" if the server is at a different address credentials: "same-origin" }; diff --git a/client/src/store.js b/client/src/store.js index c98657ef..668f999d 100644 --- a/client/src/store.js +++ b/client/src/store.js @@ -13,12 +13,23 @@ export const store = { }, socketCloseListener: null, initialize() { + const headers = { + "Content-Type": "application/json;charset=UTF-8", + "X-Requested-With": "XMLHttpRequest" + }; fetch( params.serverUrl + "/variants", - {method: "GET"}, + { + method: "GET", + headers: headers + } ) .then(res => res.json()) .then(json => { + if (!Array.isArray(json.variantArray)) { + alert("Variants loading failed: reload the page"); + return; + } this.state.variants = json.variantArray.sort( (v1,v2) => v1.name.localeCompare(v2.name)); }); @@ -42,6 +53,7 @@ export const store = { params.serverUrl + "/whoami", { method: "GET", + headers: headers, credentials: params.credentials } ) diff --git a/client/src/utils/ajax.js b/client/src/utils/ajax.js index 4573dd85..e43e9094 100644 --- a/client/src/utils/ajax.js +++ b/client/src/utils/ajax.js @@ -1,9 +1,6 @@ import params from "../parameters"; //for server URL import { store } from "../store"; //for translations -// TODO: replace by fetch API ? -// https://www.sitepoint.com/xmlhttprequest-vs-the-fetch-api-whats-best-for-ajax-in-2019/ - // From JSON (encoded string values!) to "arg1=...&arg2=..." function toQueryString(data) { let data_str = ""; @@ -13,49 +10,44 @@ function toQueryString(data) { return data_str.slice(0, -1); //remove last "&" } -// data, error: optional -export function ajax(url, method, data, success, error) { - let xhr = new XMLHttpRequest(); - if (data === undefined || typeof data === "function") { - //no data - error = success; - success = data; - data = {}; - } - if (!success) success = () => {}; //by default, do nothing - if (!error) - error = errmsg => { +// TODO: use this syntax https://stackoverflow.com/a/29823632 ? +// data, success, error: optional +export function ajax(url, method, options) { + const data = options.data || {}; + // By default, do nothing on success and print errors: + if (!options.success) + options.success = () => {}; + if (!options.error) { + options.error = (errmsg) => { alert(store.state.tr[errmsg] || errmsg); }; - xhr.onreadystatechange = function() { - if (this.readyState == 4 && this.status == 200) { - let res_json = ""; - try { - res_json = JSON.parse(xhr.responseText); - } catch (e) { - // Plain text (e.g. for rules retrieval) (TODO: no more plain text in current version) - success(xhr.responseText); - } - if (res_json) { - if (!res_json.errmsg && !res_json.errno) success(res_json); - else { - if (res_json.errmsg) error(res_json.errmsg); - else error(res_json.code + ". errno = " + res_json.errno); - } - } - } - }; - - if (["GET", "DELETE"].includes(method) && !!data) { + } + if (["GET", "DELETE"].includes(method) && !!data) // Append query params to URL url += "/?" + toQueryString(data); + const headers = { + "Content-Type": "application/json;charset=UTF-8", + "X-Requested-With": "XMLHttpRequest" + }; + let fetchOptions = { + method: method, + headers: headers, + }; + if (["POST", "PUT"].includes(method)) + fetchOptions["body"] = JSON.stringify(data); + if ( + !!options.credentials || + (method != "GET" && !options.nocredentials) + ) { + fetchOptions["credentials"] = params.credentials; } - xhr.open(method, params.serverUrl + url, true); - xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest"); - // Next line to allow cross-domain cookies in dev mode - if (params.cors) xhr.withCredentials = true; - if (["POST", "PUT"].includes(method)) { - xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8"); - xhr.send(JSON.stringify(data)); - } else xhr.send(); + fetch(params.serverUrl + url, fetchOptions) + .then(res => res.json()) + .then(json => { + if (!json.errmsg && !json.errno) options.success(json); + else { + if (!!json.errmsg) options.error(json.errmsg); + else options.error(json.code + ". errno = " + json.errno); + } + }); } diff --git a/client/src/views/Auth.vue b/client/src/views/Auth.vue index 0c5afe9c..b28ac1ef 100644 --- a/client/src/views/Auth.vue +++ b/client/src/views/Auth.vue @@ -21,15 +21,18 @@ export default { ajax( "/authenticate", "GET", - { token: this.$route.params["token"] }, - res => { - this.authOk = true; - this.st.user.id = res.id; - this.st.user.name = res.name; - this.st.user.email = res.email; - this.st.user.notify = res.notify; - localStorage["myname"] = res.name; - localStorage["myid"] = res.id; + { + credentials: true, + data: { token: this.$route.params["token"] }, + success: (res) => { + this.authOk = true; + this.st.user.id = res.id; + this.st.user.name = res.name; + this.st.user.email = res.email; + this.st.user.notify = res.notify; + localStorage["myname"] = res.name; + localStorage["myid"] = res.id; + } } ); } diff --git a/client/src/views/Game.vue b/client/src/views/Game.vue index 4ebc8f4c..7f1bd407 100644 --- a/client/src/views/Game.vue +++ b/client/src/views/Game.vue @@ -331,8 +331,13 @@ export default { clearChat: function() { // Nothing more to do if game is live (chats not recorded) if (this.game.type == "corr") { - if (!!this.game.mycolor) - ajax("/chats", "DELETE", {gid: this.game.id}); + if (!!this.game.mycolor) { + ajax( + "/chats", + "DELETE", + { data: { gid: this.game.id } } + ); + } this.$set(this.game, "chats", []); } }, @@ -639,11 +644,13 @@ export default { "/games", "PUT", { - gid: this.gameRef.id, - newObj: obj - }, - () => { - if (!!callback) callback(); + data: { + gid: this.gameRef.id, + newObj: obj + }, + success: () => { + if (!!callback) callback(); + } } ); }, @@ -865,13 +872,20 @@ export default { const gid = this.gameRef.id; if (Number.isInteger(gid) || !isNaN(parseInt(gid))) { // corr games identifiers are integers - ajax("/games", "GET", { gid: gid }, res => { - let g = res.game; - g.moves.forEach(m => { - m.squares = JSON.parse(m.squares); - }); - afterRetrieval(g); - }); + ajax( + "/games", + "GET", + { + data: { gid: gid }, + success: (res) => { + let g = res.game; + g.moves.forEach(m => { + m.squares = JSON.parse(m.squares); + }); + afterRetrieval(g); + } + } + ); } else // Local game diff --git a/client/src/views/Hall.vue b/client/src/views/Hall.vue index 009a1abe..5e7a10d4 100644 --- a/client/src/views/Hall.vue +++ b/client/src/views/Hall.vue @@ -238,61 +238,72 @@ export default { ajax( "/games", "GET", - { uid: this.st.user.id, excluded: true }, - response => { - this.games = this.games.concat( - response.games.map(g => { - const type = this.classifyObject(g); - const vname = this.getVname(g.vid); - return Object.assign({}, g, { type: type, vname: vname }); - }) - ); + { + data: { uid: this.st.user.id, excluded: true }, + success: (response) => { + this.games = this.games.concat( + response.games.map(g => { + const type = this.classifyObject(g); + const vname = this.getVname(g.vid); + return Object.assign({}, g, { type: type, vname: vname }); + }) + ); + } } ); // Also ask for corr challenges (open + sent by/to me) - ajax("/challenges", "GET", { uid: this.st.user.id }, response => { - // Gather all senders names, and then retrieve full identity: - // (TODO [perf]: some might be online...) - let names = {}; - response.challenges.forEach(c => { - if (c.uid != this.st.user.id) names[c.uid] = ""; - else if (!!c.target && c.target != this.st.user.id) - names[c.target] = ""; - }); - const addChallenges = () => { - names[this.st.user.id] = this.st.user.name; //in case of - this.challenges = this.challenges.concat( - response.challenges.map(c => { - const from = { name: names[c.uid], id: c.uid }; //or just name - const type = this.classifyObject(c); - const vname = this.getVname(c.vid); - return Object.assign( - {}, + ajax( + "/challenges", + "GET", + { + data: { uid: this.st.user.id }, + success: (response) => { + // Gather all senders names, and then retrieve full identity: + // (TODO [perf]: some might be online...) + let names = {}; + response.challenges.forEach(c => { + if (c.uid != this.st.user.id) names[c.uid] = ""; + else if (!!c.target && c.target != this.st.user.id) + names[c.target] = ""; + }); + const addChallenges = () => { + names[this.st.user.id] = this.st.user.name; //in case of + this.challenges = this.challenges.concat( + response.challenges.map(c => { + const from = { name: names[c.uid], id: c.uid }; //or just name + const type = this.classifyObject(c); + const vname = this.getVname(c.vid); + return Object.assign( + {}, + { + type: type, + vname: vname, + from: from, + to: c.target ? names[c.target] : "" + }, + c + ); + }) + ); + }; + if (Object.keys(names).length > 0) { + ajax( + "/users", + "GET", { - type: type, - vname: vname, - from: from, - to: c.target ? names[c.target] : "" - }, - c + data: { ids: Object.keys(names).join(",") }, + success: (response2) => { + response2.users.forEach(u => { + names[u.id] = u.name; + }); + addChallenges(); + } + } ); - }) - ); - }; - if (Object.keys(names).length > 0) { - ajax( - "/users", - "GET", - { ids: Object.keys(names).join(",") }, - response2 => { - response2.users.forEach(u => { - names[u.id] = u.name; - }); - addChallenges(); - } - ); - } else addChallenges(); - }); + } else addChallenges(); + } + } + ); const connectAndPoll = () => { this.send("connect"); this.send("pollclientsandgamers"); @@ -751,7 +762,11 @@ export default { // Delete current challenge (will be replaced now) this.send("deletechallenge", { data: this.challenges[cIdx].id }); if (ctype == "corr") { - ajax("/challenges", "DELETE", { id: this.challenges[cIdx].id }); + ajax( + "/challenges", + "DELETE", + { data: { id: this.challenges[cIdx].id } } + ); } this.challenges.splice(cIdx, 1); } @@ -788,9 +803,16 @@ export default { finishAddChallenge(null); } else { // Correspondance game: send challenge to server - ajax("/challenges", "POST", { chall: chall }, response => { - finishAddChallenge(response.cid); - }); + ajax( + "/challenges", + "POST", + { + data: { chall: chall }, + success: (response) => { + finishAddChallenge(response.cid); + } + } + ); } }, // Callback function after a diagram was showed to accept @@ -813,8 +835,13 @@ export default { const oppsid = this.getOppsid(c); if (!!oppsid) this.send("refusechallenge", { data: c.id, target: oppsid }); - if (c.type == "corr") - ajax("/challenges", "DELETE", { id: c.id }); + if (c.type == "corr") { + ajax( + "/challenges", + "DELETE", + { data: { id: c.id } } + ); + } } this.send("deletechallenge", { data: c.id }); }, @@ -853,8 +880,13 @@ export default { } else { // My challenge - if (c.type == "corr") - ajax("/challenges", "DELETE", { id: c.id }); + if (c.type == "corr") { + ajax( + "/challenges", + "DELETE", + { data: { id: c.id } } + ); + } this.send("deletechallenge", { data: c.id }); } // In all cases, the challenge is consumed: @@ -889,11 +921,14 @@ export default { ajax( "/games", "POST", - { gameInfo: gameInfo, cid: c.id }, //cid useful to delete challenge - response => { - gameInfo.id = response.gameId; - notifyNewgame(); - this.$router.push("/game/" + response.gameId); + { + // cid is useful to delete the challenge: + data: { gameInfo: gameInfo, cid: c.id }, + success: (response) => { + gameInfo.id = response.gameId; + notifyNewgame(); + this.$router.push("/game/" + response.gameId); + } } ); } diff --git a/client/src/views/Logout.vue b/client/src/views/Logout.vue index 0db08a93..919e4929 100644 --- a/client/src/views/Logout.vue +++ b/client/src/views/Logout.vue @@ -21,14 +21,17 @@ export default { ajax( "/logout", "GET", - () => { - this.logoutOk = true; - this.st.user.id = 0; - this.st.user.name = ""; - this.st.user.email = ""; - this.st.user.notify = false; - localStorage.removeItem("myid"); - localStorage.removeItem("myname"); + { + credentials: true, + success: () => { + this.logoutOk = true; + this.st.user.id = 0; + this.st.user.name = ""; + this.st.user.email = ""; + this.st.user.notify = false; + localStorage.removeItem("myid"); + localStorage.removeItem("myname"); + } } ); } diff --git a/client/src/views/MyGames.vue b/client/src/views/MyGames.vue index 2701e9ef..5148c3cf 100644 --- a/client/src/views/MyGames.vue +++ b/client/src/views/MyGames.vue @@ -53,18 +53,21 @@ export default { ajax( "/games", "GET", - { uid: this.st.user.id }, - res => { - let serverGames = res.games.filter(g => { - const mySide = - g.players[0].uid == this.st.user.id - ? "White" - : "Black"; - return !g["deletedBy" + mySide]; - }); - serverGames.forEach(g => g.type = "corr"); - this.corrGames = serverGames; - }); + { + data: { uid: this.st.user.id }, + success: (res) => { + let serverGames = res.games.filter(g => { + const mySide = + g.players[0].uid == this.st.user.id + ? "White" + : "Black"; + return !g["deletedBy" + mySide]; + }); + serverGames.forEach(g => g.type = "corr"); + this.corrGames = serverGames; + } + } + ); } // Initialize connection this.connexionString = @@ -157,10 +160,12 @@ export default { "/games", "PUT", { - gid: game.id, - newObj: { - score: "?", - scoreMsg: getScoreMessage("?") + data: { + gid: game.id, + newObj: { + score: "?", + scoreMsg: getScoreMessage("?") + } } } ); diff --git a/client/src/views/News.vue b/client/src/views/News.vue index f9e8adcd..1aebbd34 100644 --- a/client/src/views/News.vue +++ b/client/src/views/News.vue @@ -56,11 +56,18 @@ export default { }; }, created: function() { - ajax("/news", "GET", { cursor: this.cursor }, res => { - this.newsList = res.newsList.sort((n1, n2) => n2.added - n1.added); - const L = res.newsList.length; - if (L > 0) this.cursor = this.newsList[0].id; - }); + ajax( + "/news", + "GET", + { + data: { cursor: this.cursor }, + success: (res) => { + this.newsList = res.newsList.sort((n1, n2) => n2.added - n1.added); + const L = res.newsList.length; + if (L > 0) this.cursor = this.newsList[0].id; + } + } + ); }, mounted: function() { document @@ -99,23 +106,30 @@ export default { sendNews: function() { const edit = this.curnews.id > 0; this.infoMsg = "Processing... Please wait"; - ajax("/news", edit ? "PUT" : "POST", { news: this.curnews }, res => { - if (edit) { - let n = this.newsList.find(n => n.id == this.curnews.id); - if (n) n.content = this.curnews.content; - } else { - const newNews = { - content: this.curnews.content, - added: Date.now(), - uid: this.st.user.id, - id: res.id - }; - this.newsList = [newNews].concat(this.newsList); + ajax( + "/news", + edit ? "PUT" : "POST", + { + data: { news: this.curnews }, + success: (res) => { + if (edit) { + let n = this.newsList.find(n => n.id == this.curnews.id); + if (n) n.content = this.curnews.content; + } else { + const newNews = { + content: this.curnews.content, + added: Date.now(), + uid: this.st.user.id, + id: res.id + }; + this.newsList = [newNews].concat(this.newsList); + } + document.getElementById("modalNews").checked = false; + this.infoMsg = ""; + this.resetCurnews(); + } } - document.getElementById("modalNews").checked = false; - this.infoMsg = ""; - this.resetCurnews(); - }); + ); }, editNews: function(n) { this.curnews.content = n.content; @@ -126,22 +140,36 @@ export default { deleteNews: function(n) { if (confirm(this.st.tr["Are you sure?"])) { this.infoMsg = "Processing... Please wait"; - ajax("/news", "DELETE", { id: n.id }, () => { - const nIdx = this.newsList.findIndex(nw => nw.id == n.id); - this.newsList.splice(nIdx, 1); - this.infoMsg = ""; - document.getElementById("modalNews").checked = false; - }); + ajax( + "/news", + "DELETE", + { + data: { id: n.id }, + success: () => { + const nIdx = this.newsList.findIndex(nw => nw.id == n.id); + this.newsList.splice(nIdx, 1); + this.infoMsg = ""; + document.getElementById("modalNews").checked = false; + } + } + ); } }, loadMore: function() { - ajax("/news", "GET", { cursor: this.cursor }, res => { - if (res.newsList.length > 0) { - this.newsList = this.newsList.concat(res.newsList); - const L = res.newsList.length; - if (L > 0) this.cursor = res.newsList[L - 1].id; - } else this.hasMore = false; - }); + ajax( + "/news", + "GET", + { + data: { cursor: this.cursor }, + success: (res) => { + if (res.newsList.length > 0) { + this.newsList = this.newsList.concat(res.newsList); + const L = res.newsList.length; + if (L > 0) this.cursor = res.newsList[L - 1].id; + } else this.hasMore = false; + } + } + ); } } }; diff --git a/client/src/views/Problems.vue b/client/src/views/Problems.vue index a1c3e83c..ef05e121 100644 --- a/client/src/views/Problems.vue +++ b/client/src/views/Problems.vue @@ -145,34 +145,47 @@ export default { }; }, created: function() { - ajax("/problems", "GET", res => { - // Show newest problem first: - this.problems = res.problems.sort((p1, p2) => p2.added - p1.added); - if (this.st.variants.length > 0) - this.problems.forEach(p => this.setVname(p)); - // Retrieve all problems' authors' names - let names = {}; - this.problems.forEach(p => { - if (p.uid != this.st.user.id) names[p.uid] = ""; - else p.uname = this.st.user.name; - }); - const showOneIfPid = () => { - const pid = this.$route.query["id"]; - if (pid) this.showProblem(this.problems.find(p => p.id == pid)); - }; - if (Object.keys(names).length > 0) { - ajax("/users", "GET", { ids: Object.keys(names).join(",") }, res2 => { - res2.users.forEach(u => { - names[u.id] = u.name; - }); + ajax( + "/problems", + "GET", + { + success: (res) => { + // Show newest problem first: + this.problems = res.problems.sort((p1, p2) => p2.added - p1.added); + if (this.st.variants.length > 0) + this.problems.forEach(p => this.setVname(p)); + // Retrieve all problems' authors' names + let names = {}; this.problems.forEach(p => { - if (!p.uname) - p.uname = names[p.uid]; + if (p.uid != this.st.user.id) names[p.uid] = ""; + else p.uname = this.st.user.name; }); - showOneIfPid(); - }); - } else showOneIfPid(); - }); + const showOneIfPid = () => { + const pid = this.$route.query["id"]; + if (pid) this.showProblem(this.problems.find(p => p.id == pid)); + }; + if (Object.keys(names).length > 0) { + ajax( + "/users", + "GET", + { + data: { ids: Object.keys(names).join(",") }, + success: (res2) => { + res2.users.forEach(u => { + names[u.id] = u.name; + }); + this.problems.forEach(p => { + if (!p.uname) + p.uname = names[p.uid]; + }); + showOneIfPid(); + } + } + ); + } else showOneIfPid(); + } + } + ); }, mounted: function() { document @@ -322,22 +335,24 @@ export default { ajax( "/problems", edit ? "PUT" : "POST", - { prob: this.curproblem }, - ret => { - if (edit) { - let editedP = this.problems.find(p => p.id == this.curproblem.id); - this.copyProblem(this.curproblem, editedP); - this.showProblem(editedP); + { + data: { prob: this.curproblem }, + success: (ret) => { + if (edit) { + let editedP = this.problems.find(p => p.id == this.curproblem.id); + this.copyProblem(this.curproblem, editedP); + this.showProblem(editedP); + } + else { + let newProblem = Object.assign({}, this.curproblem); + newProblem.id = ret.id; + newProblem.uid = this.st.user.id; + newProblem.uname = this.st.user.name; + this.problems = [newProblem].concat(this.problems); + } + document.getElementById("modalNewprob").checked = false; + this.infoMsg = ""; } - else { - let newProblem = Object.assign({}, this.curproblem); - newProblem.id = ret.id; - newProblem.uid = this.st.user.id; - newProblem.uname = this.st.user.name; - this.problems = [newProblem].concat(this.problems); - } - document.getElementById("modalNewprob").checked = false; - this.infoMsg = ""; } ); }, @@ -349,10 +364,17 @@ export default { }, deleteProblem: function(prob) { if (confirm(this.st.tr["Are you sure?"])) { - ajax("/problems", "DELETE", { id: prob.id }, () => { - ArrayFun.remove(this.problems, p => p.id == prob.id); - this.backToList(); - }); + ajax( + "/problems", + "DELETE", + { + data: { id: prob.id }, + success: () => { + ArrayFun.remove(this.problems, p => p.id == prob.id); + this.backToList(); + } + } + ); } } } diff --git a/client/src/views/Rules.vue b/client/src/views/Rules.vue index 1851609f..7830d26a 100644 --- a/client/src/views/Rules.vue +++ b/client/src/views/Rules.vue @@ -78,17 +78,17 @@ export default { if (!this.gameInfo.vname) return ""; //variant not set yet // (AJAX) Request to get rules content (plain text, HTML) return ( - require("raw-loader!@/translations/rules/" + - this.gameInfo.vname + - "/" + - this.st.lang + - ".pug") - // Next two lines fix a weird issue after last update (2019-11) - .replace(/\\n/g, " ") - .replace(/\\"/g, '"') - .replace('module.exports = "', "") - .replace(/"$/, "") - .replace(/(fen:)([^:]*):/g, this.replaceByDiag) + require( + "raw-loader!@/translations/rules/" + + this.gameInfo.vname + "/" + + this.st.lang + ".pug" + ) + // Next two lines fix a weird issue after last update (2019-11) + .replace(/\\n/g, " ") + .replace(/\\"/g, '"') + .replace('module.exports = "', "") + .replace(/"$/, "") + .replace(/(fen:)([^:]*):/g, this.replaceByDiag) ); } }, diff --git a/server/app.js b/server/app.js index eced7d33..d029c956 100644 --- a/server/app.js +++ b/server/app.js @@ -28,7 +28,10 @@ else app.use(express.json()); app.use(express.urlencoded({ extended: false })); app.use(cookieParser()); -app.use(express.static(path.join(__dirname, 'static'))); //client "prod" files +// Client "prod" files: +app.use(express.static(path.join(__dirname, 'static'))); +// Update in progress: +app.use(express.static(path.join(__dirname, 'while_update'))); // In development stage the client side has its own server if (params.cors.enable) @@ -36,9 +39,14 @@ if (params.cors.enable) app.use(function(req, res, next) { res.header("Access-Control-Allow-Origin", params.cors.allowedOrigin); res.header("Access-Control-Allow-Credentials", true); //for cookies - res.header("Access-Control-Allow-Headers", - "Origin, X-Requested-With, Content-Type, Accept"); - res.header("Access-Control-Allow-Methods", "GET, POST, OPTIONS, PUT, DELETE"); + res.header( + "Access-Control-Allow-Headers", + "Origin, X-Requested-With, Content-Type, Accept" + ); + res.header( + "Access-Control-Allow-Methods", + "GET, POST, OPTIONS, PUT, DELETE" + ); next(); }); } @@ -47,12 +55,12 @@ if (params.cors.enable) const routes = require(path.join(__dirname, "routes", "all")); app.use('/', routes); -// catch 404 and forward to error handler +// Catch 404 and forward to error handler app.use(function(req, res, next) { next(createError(404)); }); -// error handler +// Error handler app.use(function(err, req, res, next) { res.status(err.status || 500); if (app.get('env') === 'development') diff --git a/server/routes/all.js b/server/routes/all.js index b58638e4..0c02129f 100644 --- a/server/routes/all.js +++ b/server/routes/all.js @@ -1,11 +1,6 @@ let router = require("express").Router(); const access = require("../utils/access"); -// To avoid a weird preflight AJAX request error in dev mode... -router.get("/", access.ajax, (req,res) => { - res.json({}); -}); - router.use("/", require("./challenges")); router.use("/", require("./games")); router.use("/", require("./messages")); diff --git a/server/routes/problems.js b/server/routes/problems.js index 64c173a1..732ea710 100644 --- a/server/routes/problems.js +++ b/server/routes/problems.js @@ -22,7 +22,7 @@ router.post("/problems", access.logged, access.ajax, (req,res) => { res.json({}); }); -router.get("/problems", (req,res) => { +router.get("/problems", access.ajax, (req,res) => { const probId = req.query["pid"]; if (probId && probId.match(/^[0-9]+$/)) { diff --git a/server/routes/users.js b/server/routes/users.js index 11966754..2b38c37f 100644 --- a/server/routes/users.js +++ b/server/routes/users.js @@ -34,7 +34,7 @@ router.post('/register', access.unlogged, access.ajax, (req,res) => { }); // NOTE: this method is safe because the sessionToken must be guessed -router.get("/whoami", (req,res) => { +router.get("/whoami", access.ajax, (req,res) => { const callback = (user) => { res.json({ name: user.name, diff --git a/server/routes/variants.js b/server/routes/variants.js index 57d4a30b..3f7417e3 100644 --- a/server/routes/variants.js +++ b/server/routes/variants.js @@ -4,7 +4,7 @@ let router = require("express").Router(); const VariantModel = require("../models/Variant"); const access = require("../utils/access"); -router.get('/variants', function(req, res) { +router.get('/variants', access.ajax, function(req, res) { VariantModel.getAll((err,variants) => { res.json(err || {variantArray:variants}); }); diff --git a/server/while_update/favicon.ico b/server/while_update/favicon.ico new file mode 100644 index 00000000..7b26be14 --- /dev/null +++ b/server/while_update/favicon.ico @@ -0,0 +1 @@ +#$# git-fat 79e7b6b353fa77bdb2ab20fcb86055db27175b91 9662 diff --git a/server/while_update/index.html b/server/while_update/index.html new file mode 100644 index 00000000..bee7392a --- /dev/null +++ b/server/while_update/index.html @@ -0,0 +1,27 @@ +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>vchess - club</title> + <meta http-equiv="X-UA-Compatible" content="IE=edge"> + <meta name="viewport" content="width=device-width,initial-scale=1.0"> + <style> + #container { + position: absolute; + width: 100%; + top: 30%; + } + p { + text-align: center; + font-weight: bold; + font-size: 2rem; + } + </style> + </head> + <body> + <div id="container"> + <p>Website update in progress!</p> + <p>It won't be long. Don't worry :)</p> + </div> + </body> +</html> -- 2.44.0