3 input#modalNewprob.modal(type="checkbox" @change="infoMsg=''")
4 div#newprobDiv(role="dialog" data-checkbox="modalNewprob")
5 .card(@keyup.enter="sendProblem()")
6 label#closeNewprob.modal-close(for="modalNewprob")
8 label(for="selectVariant") {{ st.tr["Variant"] }}
10 v-model="curproblem.vid"
11 @change="changeVariant(curproblem)"
14 v-for="v in [emptyVar].concat(st.variants)"
16 :selected="curproblem.vid==v.id"
23 v-model="curproblem.fen"
24 @input="trySetDiagram(curproblem)"
26 #diagram(v-html="curproblem.diag")
29 :placeholder="st.tr['Instructions']"
30 v-model="curproblem.instruction"
32 p(v-html="parseHtml(curproblem.instruction)")
35 :placeholder="st.tr['Solution']"
36 v-model="curproblem.solution"
38 p(v-html="parseHtml(curproblem.solution)")
39 button(@click="sendProblem()") {{ st.tr["Send"] }}
40 #dialog.text-center {{ st.tr[infoMsg] }}
42 .col-sm-12.col-md-10.col-md-offset-2
44 span.vname {{ curproblem.vname }}
45 span.uname ({{ curproblem.uname }})
46 button.marginleft(@click="backToList()") {{ st.tr["Back to list"] }}
48 v-if="st.user.id == curproblem.uid"
49 @click="editProblem(curproblem)"
53 v-if="st.user.id == curproblem.uid"
54 @click="deleteProblem(curproblem)"
56 | {{ st.tr["Delete"] }}
58 v-html="parseHtml(curproblem.instruction)"
59 @click="curproblem.showSolution=!curproblem.showSolution"
61 | {{ st.tr["Show solution"] }}
63 v-show="curproblem.showSolution"
64 v-html="parseHtml(curproblem.solution)"
67 .col-sm-12.col-md-10.col-md-offset-1.col-lg-8.col-lg-offset-2
69 button#newProblem(onClick="doClick('modalNewprob')")
70 | {{ st.tr["New problem"] }}
71 label(for="checkboxMine") {{ st.tr["My problems"] }}
76 label(for="selectVariant") {{ st.tr["Variant"] }}
77 select#selectVariant(v-model="selectedVar")
79 v-for="v in [emptyVar].concat(st.variants)"
85 th {{ st.tr["Variant"] }}
86 th {{ st.tr["Instructions"] }}
87 th {{ st.tr["Number"] }}
89 v-for="p in sortedProblems"
90 v-show="displayProblem(p)"
91 @click="setHrefPid(p)"
94 td {{ firstChars(p.instruction) }}
96 BaseGame(v-if="showOne" :game="game" :vr="vr")
100 import { store } from "@/store";
101 import { ajax } from "@/utils/ajax";
102 import { checkProblem } from "@/data/problemCheck";
103 import { getDiagram } from "@/utils/printDiagram";
104 import { processModalClick } from "@/utils/modalClick";
105 import { ArrayFun } from "@/utils/array";
106 import BaseGame from "@/components/BaseGame.vue";
119 // Problem currently showed, or edited:
121 id: 0, //used in case of edit
129 loadedVar: 0, //corresponding to loaded V
130 selectedVar: 0, //to filter problems based on variant
135 vr: null, //"variant rules" object initialized from FEN
137 players:[{name:"Problem"},{name:"Problem"}],
142 created: function() {
143 ajax("/problems", "GET", (res) => {
144 this.problems = res.problems;
145 if (this.st.variants.length > 0)
146 this.problems.forEach(p => this.setVname(p));
147 // Retrieve all problems' authors' names
149 this.problems.forEach(p => {
150 if (p.uid != this.st.user.id)
151 names[p.uid] = ""; //unknwon for now
153 p.uname = this.st.user.name;
155 const showOneIfPid = () => {
156 const pid = this.$route.query["id"];
158 this.showProblem(this.problems.find(p => p.id == pid));
160 if (Object.keys(names).length > 0)
164 { ids: Object.keys(names).join(",") },
166 res2.users.forEach(u => {names[u.id] = u.name});
167 this.problems.forEach(p => p.uname = names[p.uid]);
176 mounted: function() {
177 document.getElementById("newprobDiv").addEventListener("click", processModalClick);
180 // st.variants changes only once, at loading from [] to [...]
181 "st.variants": function(variantArray) {
182 // Set problems vname (either all are set or none)
183 if (this.problems.length > 0 && this.problems[0].vname == "")
184 this.problems.forEach(p => this.setVname(p));
186 "$route": function(to, from) {
187 const pid = to.query["id"];
189 this.showProblem(this.problems.find(p => p.id == pid));
195 sortedProblems: function() {
197 return this.problems.sort( (p1,p2) => p2.added - p1.added);
201 setVname: function(prob) {
202 prob.vname = this.st.variants.find(v => v.id == prob.vid).name;
204 firstChars: function(text) {
205 let preparedText = text
206 // Replace line jumps and <br> by spaces
207 .replace(/\n/g, " " )
208 .replace(/<br\/?>/g, " " )
209 .replace(/<[^>]+>/g, "") //remove remaining HTML tags
210 .replace(/[ ]+/g, " ") //remove series of spaces by only one
212 const maxLength = 32; //arbitrary...
213 if (preparedText.length > maxLength)
214 return preparedText.substr(0,32) + "...";
217 copyProblem: function(p1, p2) {
221 setHrefPid: function(p) {
222 // Change href => $route changes, watcher notices, call showProblem
223 const curHref = document.location.href;
224 document.location.href = curHref.split("?")[0] + "?id=" + p.id;
226 backToList: function() {
227 // Change href => $route change, watcher notices, reset showOne to false
228 document.location.href = document.location.href.split("?")[0];
230 resetCurProb: function() {
231 this.curproblem.id = 0;
232 this.curproblem.uid = 0;
233 this.curproblem.vid = "";
234 this.curproblem.vname = "";
235 this.curproblem.fen = "";
236 this.curproblem.diag = "";
237 this.curproblem.instruction = "";
238 this.curproblem.solution = "";
239 this.curproblem.showSolution = false;
241 parseHtml: function(txt) {
242 return !txt.match(/<[/a-zA-Z]+>/)
243 ? txt.replace(/\n/g, "<br/>") //no HTML tag
246 changeVariant: function(prob) {
251 // Set FEN if possible (might not be correct yet)
252 if (V.IsGoodFen(prob.fen))
253 this.setDiagram(prob);
257 loadVariant: async function(vid, cb) {
258 // Condition: vid is a valid variant ID
260 const variant = this.st.variants.find(v => v.id == vid);
261 const vModule = await import("@/variants/" + variant.name + ".js");
262 window.V = vModule.VariantRules;
263 this.loadedVar = vid;
266 trySetDiagram: function(prob) {
267 // Problem edit: FEN could be wrong or incomplete,
268 // variant could not be ready, or not defined
269 if (prob.vid > 0 && this.loadedVar == prob.vid && V.IsGoodFen(prob.fen))
270 this.setDiagram(prob);
272 setDiagram: function(prob) {
273 // Condition: prob.fen is correct and global V is ready
274 const parsedFen = V.ParseFen(prob.fen);
276 position: parsedFen.position,
277 orientation: parsedFen.turn,
279 prob.diag = getDiagram(args);
281 displayProblem: function(p) {
282 return ((this.selectedVar == 0 || p.vid == this.selectedVar) &&
283 ((this.onlyMines && p.uid == this.st.user.id)
284 || (!this.onlyMines && p.uid != this.st.user.id)));
286 showProblem: function(p) {
290 // The FEN is already checked at this stage:
291 this.vr = new V(p.fen);
292 this.game.vname = p.vname;
293 this.game.mycolor = this.vr.turn; //diagram orientation
294 this.game.fen = p.fen;
295 this.$set(this.game, "fenStart", p.fen);
296 this.copyProblem(p, this.curproblem);
301 sendProblem: function() {
302 const error = checkProblem(this.curproblem);
305 const edit = this.curproblem.id > 0;
306 this.infoMsg = "Processing... Please wait";
309 edit ? "PUT" : "POST",
310 {prob: this.curproblem},
314 let editedP = this.problems.find(p => p.id == this.curproblem.id);
315 this.copyProblem(this.curproblem, editedP);
319 let newProblem = Object.assign({}, this.curproblem);
320 newProblem.id = ret.id;
321 newProblem.uid = this.st.user.id;
322 newProblem.uname = this.st.user.name;
323 this.problems = this.problems.concat(newProblem);
330 editProblem: function(prob) {
332 this.setDiagram(prob); //possible because V is loaded at this stage
333 this.copyProblem(prob, this.curproblem);
334 doClick('modalNewprob');
336 deleteProblem: function(prob) {
337 if (confirm(this.st.tr["Are you sure?"]))
339 ajax("/problems", "DELETE", {id:prob.id}, () => {
340 ArrayFun.remove(this.problems, p => p.id == prob.id);
349 <style lang="sass" scoped>
350 [type="checkbox"].modal+div .card
370 padding-left: var(--universal-margin)
372 padding-left: var(--universal-margin)
379 @media screen and (max-width: 767px)