contrib/opportunity: store local participant's name in a cookie
[nit.git] / contrib / opportunity / src / templates / meetup.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License
14
15 # Shows a meetup and allows to modify its participants
16 module meetup is i18n
17
18 import opportunity_model
19 import boilerplate
20 import welcome
21 import template
22
23 # Shows a meetup and allows to modify its participants
24 class OpportunityMeetupPage
25 super OpportunityPage
26
27 # Meetup the page is supposed to show
28 var meetup: nullable Meetup = null
29 # Answer mode for the meetup
30 var mode = 0
31
32 init from_id(id: String) do
33 var db = new OpportunityDB.open("opportunity")
34 meetup = db.find_meetup_by_id(id)
35 db.close
36 if meetup != null then mode = meetup.answer_mode
37 init
38 end
39
40 init do
41 header.page_js = "mode = {mode};\n"
42 header.page_js += """
43 function update_scores(){
44 var anss = $('.answer');
45 var count = {};
46 var scores = {};
47 var answers = [];
48 var maxscore = 0;
49 for(i=0; i < anss.length; i++){
50 var incscore = 0;
51 var inccount = 0;
52 var idparts = anss[i].id.split("_");
53 var ansid = idparts[1];
54 var html = anss[i].innerHTML;
55 if(html === "<center>✔</center>"){
56 inccount = 1;
57 incscore = 2;
58 }else if(html === "<center>❓</center>"){
59 incscore = 1;
60 }
61 var intansid = parseInt(ansid)
62 if(answers.indexOf(intansid) == -1){
63 answers.push(intansid);
64 }
65 if(ansid in count){
66 count[ansid] += inccount;
67 }else{
68 count[ansid] = inccount;
69 }
70 if(ansid in scores){
71 scores[ansid] += incscore;
72 }else{
73 scores[ansid] = incscore;
74 }
75 if(scores[ansid] > maxscore){
76 maxscore = scores[ansid];
77 }
78 }
79 for(i=0; i < answers.length; i++){
80 var ansid = answers[i].toString();
81 var el = $('#total'+ansid)[0];
82 var ins = "<center>"+count[ansid];
83 if(scores[ansid] >= maxscore){
84 ins += "<br/><span style=\\"color:blue\\">★</span>";
85 }
86 ins += "</center>";
87 el.innerHTML = ins;
88 }
89 }
90 function change_answer(ele, id){
91 // modify only the currently selected entry
92 if (in_modification_id != id) return;
93
94 var e = document.getElementById(ele.id);
95 var i = e.innerHTML;
96 var ans = true;"""
97 if mode == 0 then
98 header.page_js += """
99 if(i === "<center>✔</center>"){
100 ans = 0;
101 e.innerHTML = "<center>✘</center>"
102 e.style.color = "red";
103 }else{
104 ans = 1;
105 e.innerHTML = "<center>✔</center>";
106 e.style.color = "green";
107 }"""
108
109 else
110 header.page_js += """
111 if(i === "<center>✔</center>"){
112 ans = 1;
113 e.innerHTML = "<center>❓</center>"
114 e.style.color = "#B8860B";
115 }else if(i === "<center>❓</center>"){
116 ans = 0;
117 e.innerHTML = "<center>✘</center>"
118 e.style.color = "red";
119 }else{
120 ans = 2;
121 e.innerHTML = "<center>✔</center>";
122 e.style.color = "green";
123 }"""
124 end
125 header.page_js += """
126 var a = ele.id.split('_')
127 var pid = a[1]
128 var aid = a[2]
129 update_scores();
130 $.ajax({
131 type: "POST",
132 url: "./rest/answer",
133 data: {
134 answer_id: aid,
135 pers_id: pid,
136 answer: ans
137 }
138 });
139 }
140 function change_temp_answer(ele){
141 var e = document.getElementById(ele.id);
142 var i = e.innerHTML;"""
143 if mode == 0 then
144 header.page_js += """
145 if(i === "<center>✔</center>"){
146 e.innerHTML = "<center>✘</center>"
147 e.style.color = "red";
148 }else{
149 e.innerHTML = "<center>✔</center>";
150 e.style.color = "green";
151 }
152 """
153 else
154 header.page_js += """
155 if(i === "<center>✔</center>"){
156 e.innerHTML = "<center>❓</center>";
157 e.style.color = "#B8860B";
158 }else if(i === "<center>❓</center>"){
159 e.innerHTML = "<center>✘</center>"
160 e.style.color = "red";
161 }else{
162 e.innerHTML = "<center>✔</center>";
163 e.style.color = "green";
164 }
165 """
166 end
167 header.page_js += """
168 update_scores();
169 }
170 function add_part(ele){
171 var e = document.getElementById(ele.id);
172 var pname = document.getElementById("new_name").value;
173 var arr = e.id.split("_");
174 var mid = arr[1];
175 var ans = $('#' + ele.id).parent().parent().parent().children(".answer");
176 ansmap = {};
177 for(i=0;i<ans.length;i++){
178 var curr = ans.eq(i)
179 """
180 if mode == 0 then
181 header.page_js += """
182 if(curr[0].innerHTML === "<center>✔</center>"){
183 ansmap[curr.attr('id')] = 1
184 }else{
185 ansmap[curr.attr('id')] = 0
186 }"""
187 else
188 header.page_js += """
189 if(curr[0].innerHTML === "<center>✔</center>"){
190 ansmap[curr.attr('id')] = 2
191 }else if(curr[0].innerHTML === "<center>❓</center>"){
192 ansmap[curr.attr('id')] = 1
193 }else{
194 ansmap[curr.attr('id')] = 0
195 }"""
196 end
197 header.page_js += """
198 }
199 $.ajax({
200 type: "POST",
201 url: "./rest/meetup/new_pers",
202 data: {
203 meetup_id: mid,
204 persname: pname,
205 answers: $.param(ansmap)
206 }
207 })
208 .done(function(data){
209 location.reload();
210 })
211 .fail(function(data){
212 //TODO: Notify of failure
213 });
214
215 // Remember the participant's name client-side
216 set_cookie("opportunity_participant_name", pname);
217 }
218
219 function remove_people(ele){
220 var arr = ele.id.split("_")
221 var pid = arr[1]
222 $('#' + ele.id).parent().parent().parent().remove();
223 update_scores();
224 $.ajax({
225 type: "POST",
226 url: "./rest/people",
227 data: {
228 method: "DELETE",
229 p_id: pid
230 }
231 });
232 }
233
234 // ID of line currently open for modification
235 var in_modification_id = null;
236 function modify_people(ele, id){
237 if (in_modification_id != null) {
238 // reset to normal values
239 $('#modify_'+in_modification_id).text("{{{"Modify or delete"}}}");
240 $('#modify_'+in_modification_id).attr("class", "btn btn-xs btn-warning");
241 $('#line_'+in_modification_id).css("background-color", "");
242 $('#delete_'+in_modification_id).css("display", "none");
243 }
244 if (in_modification_id != id) {
245 // activate modifiable mode
246 $('#modify_'+id).text("{{{"Done"}}}");
247 $('#modify_'+id).attr("class", "btn btn-xs btn-success");
248 $('#line_'+id).css("background-color", "LightYellow");
249 $('#delete_'+id).show();
250
251 in_modification_id = id;
252 } else {
253 in_modification_id = null;
254 }
255 }
256
257 function get_cookie(cookie_name) {
258 var name = cookie_name + "=";
259 var ca = document.cookie.split(';');
260 for(var i = 0; i < ca.length; i ++) {
261 var c = ca[i];
262 while (c.charAt(0) == ' ') c = c.substring(1);
263 if (c.indexOf(name) == 0) return c.substring(name.length, c.length);
264 }
265 return "";
266 }
267
268 function set_cookie(cookie_name, value) {
269 var date = new Date();
270 date.setTime(date.getTime() + (365*24*60*60*1000));
271 var expires = "expires="+date.toUTCString();
272 document.cookie = cookie_name + "=" + value + "; " + expires;
273 }
274
275 // Retrieve the last client-side participant's name
276 window.onload = function () {
277 var name_field = document.getElementById("new_name");
278 name_field.value = get_cookie("opportunity_participant_name");
279 }
280 """
281 end
282
283 redef fun rendering do
284 if meetup == null then
285 add((new OpportunityHomePage).write_to_string)
286 return
287 end
288 add header
289 var db = new OpportunityDB.open("opportunity")
290 add meetup.to_html(db)
291 db.close
292 add footer
293 end
294 end
295
296 redef class Meetup
297 # Build the HTML for `self`
298 fun to_html(db: OpportunityDB): Writable do
299 var t = new Template
300 t.add """
301 <div class="container">
302 <div class="page-header">
303 <center><h1>{{{name}}}</h1></center>
304 """
305 if not date.is_empty then t.add """
306 <center><h4>{{{"When:"}}} {{{date}}}</h4></center>"""
307
308 if not place.is_empty then t.add """
309 <center><h4>{{{"Where:"}}} {{{place}}}</h4></center>"""
310
311 t.add """
312 </div>
313 <table class="table">
314 """
315 t.add "<th>{"Participant name"}</th>"
316 for i in answers(db) do
317 t.add "<th class=\"text-center\">"
318 t.add i.to_s
319 t.add "</th>"
320 end
321 t.add "<th></th>"
322 t.add "</tr>"
323 for i in participants(db) do
324 i.load_answers(db, self)
325 t.add "<tr id=\"line_{i.id}\">"
326 t.add "<td>"
327 t.add i.to_s
328 t.add "</td>"
329 for j, k in i.answers do
330 var color
331 if answer_mode == 0 then
332 if k == 1 then
333 color = "green"
334 else
335 color = "red"
336 end
337 else
338 if k == 2 then
339 color = "green"
340 else if k == 1 then
341 color = "#B8860B"
342 else
343 color = "red"
344 end
345 end
346 t.add """<td class="answer" onclick="change_answer(this, {{{i.id}}})" id="answer_{{{j.id}}}_{{{i.id}}}" style="color:{{{color}}}">"""
347 t.add "<center>"
348 if answer_mode == 0 then
349 if k == 1 then
350 t.add "✔"
351 else
352 t.add "✘"
353 end
354 else
355 if k == 2 then
356 t.add "✔"
357 else if k == 1 then
358 t.add "❓"
359 else
360 t.add "✘"
361 end
362 end
363 t.add "</center></td>"
364 end
365 t.add """<td class="opportunity-action"><center><button class="btn btn-xs btn-warning" type="button" onclick="modify_people(this, {{{i.id}}})" id="modify_{{{i.id}}}">{{{"Modify or delete"}}}</button>&nbsp;"""
366 t.add """<button class="btn btn-xs btn-danger" type="button" onclick="remove_people(this)" id="delete_{{{i.id}}}" style="display: none;">{{{"Delete"}}}</button></center></td>"""
367 t.add "</tr>"
368 end
369 t.add """
370 <tr id="newrow" style="background-color: LightYellow">
371 <td><input id="new_name" type="text" placeholder="{{{"Your name"}}}" class="input-large"></td>
372 """
373 for i in answers(db) do
374 t.add "<td class=\"answer\" id=\"newans_{i.id}\" onclick=\"change_temp_answer(this)\" style=\"color:red;\"><center>✘</center></td>"
375 end
376 t.add """
377 <td><center><span id="add_{{{id}}}" onclick="add_part(this)" style="color:green;" class="action"><button class="btn btn-xs btn-success" type="button">{{{"Done"}}}</button></span></center></td>"""
378 t.add "</tr>"
379 # Compute score for each answer
380 var scores = new HashMap[Int, Int]
381 var maxsc = 0
382 for i in answers(db) do
383 scores[i.id] = i.score(db)
384 if scores[i.id] > maxsc then maxsc = scores[i.id]
385 end
386 t.add """
387 <tr id="total">
388 <th>Total ({{{participants(db).length}}})</th>
389 """
390 for i in answers(db) do
391 t.add """<th id="total{{{i.id}}}"><center>{{{i.count(db)}}}"""
392 if scores.has_key(i.id) and scores[i.id] >= maxsc then
393 t.add """<br/><span style="color:blue">★</span>"""
394 end
395 t.add "</center></th>"
396 end
397 t.add "</th>"
398 t.add """
399 <th></th>
400 </tr>"""
401 t.add "</table>"
402 t.add "</div>"
403 return t
404 end
405 end