Commit | Line | Data |
---|---|---|
4ecf423b | 1 | Vue.component('my-problems', { |
da06a6eb BA |
2 | data: function () { |
3 | return { | |
45109880 BA |
4 | problems: problemArray, //initial value |
5 | newProblem: { | |
77fa6d1f | 6 | fen: "", |
45109880 BA |
7 | instructions: "", |
8 | solution: "", | |
9 | stage: "nothing", //or "preview" after new problem is filled | |
10 | }, | |
da06a6eb BA |
11 | }; |
12 | }, | |
4ecf423b | 13 | template: ` |
a5d56686 BA |
14 | <div class="col-sm-12 col-md-10 col-md-offset-1 col-lg-8 col-lg-offset-2"> |
15 | <div id="problemControls" class="button-group"> | |
247356cd | 16 | <button :aria-label='translate("Load previous problems")' class="tooltip" |
a5d56686 BA |
17 | @click="fetchProblems('backward')"> |
18 | <i class="material-icons">skip_previous</i> | |
19 | </button> | |
247356cd | 20 | <button :aria-label='translate("Add a problem")' class="tooltip" |
a5d56686 | 21 | @click="showNewproblemModal"> |
247356cd | 22 | {{ translate("New") }} |
a5d56686 | 23 | </button> |
247356cd | 24 | <button :aria-label='translate("Load next problems")' class="tooltip" |
a5d56686 BA |
25 | @click="fetchProblems('forward')"> |
26 | <i class="material-icons">skip_next</i> | |
27 | </button> | |
28 | </div> | |
c794dbb8 | 29 | <my-problem-summary v-on:show-problem="bubbleUp(p)" |
b5fb8e69 BA |
30 | v-for="(p,idx) in sortedProblems" |
31 | v-bind:prob="p" v-bind:preview="false" v-bind:key="idx"> | |
da06a6eb BA |
32 | </my-problem-summary> |
33 | <input type="checkbox" id="modal-newproblem" class="modal"> | |
34 | <div role="dialog" aria-labelledby="newProblemTxt"> | |
45109880 | 35 | <div v-show="newProblem.stage=='nothing'" class="card newproblem-form"> |
da06a6eb | 36 | <label for="modal-newproblem" class="modal-close"></label> |
247356cd | 37 | <h3 id="newProblemTxt">{{ translate("Add a problem") }}</h3> |
45109880 | 38 | <form @submit.prevent="previewNewProblem"> |
da06a6eb | 39 | <fieldset> |
247356cd | 40 | <label for="newpbFen">FEN</label> |
77fa6d1f | 41 | <input id="newpbFen" type="text" v-model="newProblem.fen" |
247356cd | 42 | :placeholder='translate("Full FEN string")'/> |
da06a6eb BA |
43 | </fieldset> |
44 | <fieldset> | |
247356cd BA |
45 | <p class="emphasis">{{ translate("Safe HTML tags allowed") }}</p> |
46 | <label for="newpbInstructions">{{ translate("Instructions") }}</label> | |
45109880 | 47 | <textarea id="newpbInstructions" v-model="newProblem.instructions" |
d289b043 | 48 | :placeholder='translate("Describe the problem goal")'></textarea> |
247356cd | 49 | <label for="newpbSolution">{{ translate("Solution") }}</label> |
45109880 | 50 | <textarea id="newpbSolution" v-model="newProblem.solution" |
d289b043 | 51 | :placeholder='translate("How to solve the problem?")'></textarea> |
247356cd | 52 | <button class="center-btn">{{ translate("Preview") }}</button> |
da06a6eb | 53 | </fieldset> |
da06a6eb BA |
54 | </form> |
55 | </div> | |
45109880 | 56 | <div v-show="newProblem.stage=='preview'" class="card newproblem-preview"> |
b5fb8e69 BA |
57 | <label for="modal-newproblem" class="modal-close"></label> |
58 | <my-problem-summary v-bind:prob="newProblem" v-bind:preview="true"> | |
59 | </my-problem-summary> | |
a5d56686 | 60 | <div class="button-group"> |
247356cd BA |
61 | <button @click="newProblem.stage='nothing'">{{ translate("Cancel") }}</button> |
62 | <button @click="sendNewProblem()">{{ translate("Send") }}</button> | |
b5fb8e69 | 63 | </div> |
45109880 | 64 | </div> |
da06a6eb | 65 | </div> |
4ecf423b BA |
66 | </div> |
67 | `, | |
da06a6eb BA |
68 | computed: { |
69 | sortedProblems: function() { | |
70 | // Newest problem first | |
7931e479 | 71 | return this.problems.sort((p1,p2) => { return p2.added - p1.added; }); |
da06a6eb | 72 | }, |
da06a6eb BA |
73 | }, |
74 | methods: { | |
247356cd BA |
75 | translate: function(text) { |
76 | return translations[text]; | |
77 | }, | |
c794dbb8 BA |
78 | // Propagate "show problem" event to parent component (my-variant) |
79 | bubbleUp: function(problem) { | |
80 | this.$emit('show-problem', JSON.stringify(problem)); | |
81 | }, | |
da06a6eb | 82 | fetchProblems: function(direction) { |
7931e479 BA |
83 | if (this.problems.length == 0) |
84 | return; //what could we do?! | |
85 | // Search for newest date (or oldest) | |
86 | let last_dt = this.problems[0].added; | |
87 | for (let i=0; i<this.problems.length; i++) | |
88 | { | |
89 | if ((direction == "forward" && this.problems[i].added > last_dt) || | |
90 | (direction == "backward" && this.problems[i].added < last_dt)) | |
91 | { | |
92 | last_dt = this.problems[i].added; | |
93 | } | |
94 | } | |
95 | ajax("/problems/" + variant, "GET", { | |
96 | direction: direction, | |
97 | last_dt: last_dt, | |
98 | }, response => { | |
99 | if (response.problems.length > 0) | |
100 | this.problems = response.problems; | |
101 | }); | |
da06a6eb BA |
102 | }, |
103 | showNewproblemModal: function() { | |
104 | document.getElementById("modal-newproblem").checked = true; | |
105 | }, | |
45109880 BA |
106 | previewNewProblem: function() { |
107 | if (!V.IsGoodFen(this.newProblem.fen)) | |
7931e479 | 108 | return alert("Bad FEN string"); |
a5d56686 BA |
109 | if (this.newProblem.instructions.length == 0) |
110 | return alert("Empty instructions"); | |
111 | if (this.newProblem.solution.length == 0) | |
112 | return alert("Empty solution"); | |
45109880 BA |
113 | this.newProblem.stage = "preview"; |
114 | }, | |
115 | sendNewProblem: function() { | |
116 | // Send it to the server and close modal | |
7931e479 | 117 | ajax("/problems/" + variant, "POST", { |
45109880 BA |
118 | fen: this.newProblem.fen, |
119 | instructions: this.newProblem.instructions, | |
120 | solution: this.newProblem.solution, | |
7931e479 | 121 | }, response => { |
b5fb8e69 BA |
122 | this.newProblem.added = Date.now(); |
123 | this.problems.push(JSON.parse(JSON.stringify(this.newProblem))); | |
7931e479 | 124 | document.getElementById("modal-newproblem").checked = false; |
45109880 | 125 | this.newProblem.stage = "nothing"; |
7931e479 | 126 | }); |
da06a6eb BA |
127 | }, |
128 | }, | |
4ecf423b | 129 | }) |