1 # This file is part of NIT ( http://www.nitlanguage.org ).
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
7 # http://www.apache.org/licenses/LICENSE-2.0
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
15 # Shows a meetup and allows to modify its participants
18 import opportunity_model
23 # Shows a meetup and allows to modify its participants
24 class OpportunityMeetupPage
27 # Meetup the page is supposed to show
28 var meetup
: nullable Meetup = null
29 # Answer mode for the meetup
32 init from_id
(id
: String) do
33 var db
= new OpportunityDB.open
("opportunity")
34 meetup
= db
.find_meetup_by_id
(id
)
36 if meetup
!= null then mode
= meetup
.answer_mode
41 header
.page_js
= "mode = {mode};\n"
43 function update_scores(){
44 var anss = $('.answer');
52 var pizzas_person = {};
53 var pizzas_total = 0.0;
55 // Iterate over each participant x possible answers
56 for(i=0; i < anss.length; i++){
59 var idparts = anss[i].id.split("_");
60 var ansid = idparts[1];
61 var html = anss[i].innerHTML;
62 if(html === "<center>✔</center>"){
65 }else if(html === "<center>❓</center>"){
68 var intansid = parseInt(ansid)
69 if(answers.indexOf(intansid) == -1){
70 answers.push(intansid);
73 count[ansid] += inccount;
75 count[ansid] = inccount;
78 scores[ansid] += incscore;
80 scores[ansid] = incscore;
82 if(scores[ansid] > maxscore){
83 maxscore = scores[ansid];
86 if (ansid in pizzas_person) {
88 // Pizza ratio of previous participant
89 for (a in pizzas_person) {
90 var value = pizzas_person[a];
91 if (value != 0.0 && pizzas_total != 0)
92 value /= pizzas_total;
100 // Reset for a new person
105 pizzas_total += incscore;
106 pizzas_person[ansid] = incscore;
109 // Pizza ratio of the last participant
110 for (a in pizzas_person) {
111 var value = pizzas_person[a];
112 if (value != 0.0 && pizzas_total != 0)
113 value /= pizzas_total;
121 var pizza_unit = document.getElementById("pizza_unit").value;
123 pizza_unit = parseFloat(pizza_unit);
127 for(i=0; i < answers.length; i++){
128 var ansid = answers[i].toString();
129 var el = $('#total'+ansid)[0];
130 var ins = "<center>"+count[ansid];
131 if(scores[ansid] >= maxscore){
132 ins += "<br/><span style=\\"color:blue\\">★</span>";
138 var val = pizzas[ansid] * pizza_unit;
140 el = $('#pizzas'+ansid)[0];
141 ins = "<center>"+val.toFixed(1);
142 ins += "<br><span style=\\"color:orange\\">∇</span>";
147 var pizza_unit = $("#pizza_unit").val();
148 set_cookie("opportunity_pizza_unit", pizza_unit);
150 function change_answer(ele, id){
151 // modify only the currently selected entry
152 if (in_modification_id != id) return;
154 var e = document.getElementById(ele.id);
158 header
.page_js
+= """
159 if(i === "<center>✔</center>"){
161 e.innerHTML = "<center>✘</center>"
162 e.style.color = "red";
165 e.innerHTML = "<center>✔</center>";
166 e.style.color = "green";
170 header
.page_js
+= """
171 if(i === "<center>✔</center>"){
173 e.innerHTML = "<center>❓</center>"
174 e.style.color = "#B8860B";
175 }else if(i === "<center>❓</center>"){
177 e.innerHTML = "<center>✘</center>"
178 e.style.color = "red";
181 e.innerHTML = "<center>✔</center>";
182 e.style.color = "green";
185 header
.page_js
+= """
186 var a = ele.id.split('_')
192 url: "./rest/answer",
200 function change_temp_answer(ele){
201 var e = document.getElementById(ele.id);
202 var i = e.innerHTML;"""
204 header
.page_js
+= """
205 if(i === "<center>✔</center>"){
206 e.innerHTML = "<center>✘</center>"
207 e.style.color = "red";
209 e.innerHTML = "<center>✔</center>";
210 e.style.color = "green";
214 header
.page_js
+= """
215 if(i === "<center>✔</center>"){
216 e.innerHTML = "<center>❓</center>";
217 e.style.color = "#B8860B";
218 }else if(i === "<center>❓</center>"){
219 e.innerHTML = "<center>✘</center>"
220 e.style.color = "red";
222 e.innerHTML = "<center>✔</center>";
223 e.style.color = "green";
227 header
.page_js
+= """
230 function add_part(ele){
231 var e = document.getElementById(ele.id);
232 var pname = document.getElementById("new_name").value;
233 var arr = e.id.split("_");
235 var ans = $('#' + ele.id).parent().parent().parent().children(".answer");
237 for(i=0;i<ans.length;i++){
241 header
.page_js
+= """
242 if(curr[0].innerHTML === "<center>✔</center>"){
243 ansmap[curr.attr('id')] = 1
245 ansmap[curr.attr('id')] = 0
248 header
.page_js
+= """
249 if(curr[0].innerHTML === "<center>✔</center>"){
250 ansmap[curr.attr('id')] = 2
251 }else if(curr[0].innerHTML === "<center>❓</center>"){
252 ansmap[curr.attr('id')] = 1
254 ansmap[curr.attr('id')] = 0
257 header
.page_js
+= """
261 url: "./rest/meetup/new_pers",
265 answers: $.param(ansmap)
268 .done(function(data){
271 .fail(function(data){
272 //TODO: Notify of failure
275 // Remember the participant's name client-side
276 set_cookie("opportunity_participant_name", pname);
279 function remove_people(ele){
280 var arr = ele.id.split("_")
282 $('#' + ele.id).parent().parent().parent().remove();
286 url: "./rest/people",
294 // ID of line currently open for modification
295 var in_modification_id = null;
296 function modify_people(ele, id){
297 if (in_modification_id != null) {
298 // reset to normal values
299 $('#modify_'+in_modification_id).text("{{{"Modify or delete"}}}");
300 $('#modify_'+in_modification_id).attr("class", "btn btn-xs btn-warning");
301 $('#line_'+in_modification_id).css("background-color", "");
302 $('#delete_'+in_modification_id).css("display", "none");
304 if (in_modification_id != id) {
305 // activate modifiable mode
306 $('#modify_'+id).text("{{{"Done"}}}");
307 $('#modify_'+id).attr("class", "btn btn-xs btn-success");
308 $('#line_'+id).css("background-color", "LightYellow");
309 $('#delete_'+id).show();
311 in_modification_id = id;
313 in_modification_id = null;
317 function get_cookie(cookie_name) {
318 var name = cookie_name + "=";
319 var ca = document.cookie.split(';');
320 for(var i = 0; i < ca.length; i ++) {
322 while (c.charAt(0) == ' ') c = c.substring(1);
323 if (c.indexOf(name) == 0) return c.substring(name.length, c.length);
328 function set_cookie(cookie_name, value) {
329 var date = new Date();
330 date.setTime(date.getTime() + (365*24*60*60*1000));
331 var expires = "expires="+date.toUTCString();
332 document.cookie = cookie_name + "=" + value + "; " + expires;
335 // Retrieve the last client-side participant's name
336 window.onload = function () {
337 $("#new_name").val(get_cookie("opportunity_participant_name"));
338 $("#new_name").focus();
340 $("#pizza_unit").val(get_cookie("opportunity_pizza_unit"));
347 redef fun rendering
do
348 if meetup
== null then
349 add
((new OpportunityHomePage).write_to_string
)
353 var db
= new OpportunityDB.open
("opportunity")
354 add meetup
.to_html
(db
)
361 # Build the HTML for `self`
362 fun to_html
(db
: OpportunityDB): Writable do
365 <div class="container">
366 <div class="page-header">
367 <center><h1>{{{name}}}</h1></center>
369 if not date
.is_empty
then t
.add
"""
370 <center><h4>{{{"When:"}}} {{{date}}}</h4></center>"""
372 if not place
.is_empty
then t
.add
"""
373 <center><h4>{{{"Where:"}}} {{{place}}}</h4></center>"""
377 <table class="table">
379 t
.add
"<th>{"Participant name"}</th>"
380 for i
in answers
(db
) do
381 t
.add
"<th class=\"text-center\
">"
387 for i
in participants
(db
) do
388 i
.load_answers
(db
, self)
389 t
.add
"<tr id=\"line_
{i.id}\
">"
393 for j
, k
in i
.answers
do
395 if answer_mode
== 0 then
410 t
.add
"""<td class="answer" onclick="change_answer(this, {{{i.id}}})" id="answer_{{{j.id}}}_{{{i.id}}}" style="color:{{{color}}}">"""
412 if answer_mode
== 0 then
427 t
.add
"</center></td>"
429 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> """
430 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>"""
434 <tr id="newrow" style="background-color: LightYellow">
435 <td><input id="new_name" type="text" placeholder="{{{"Your name"}}}" class="input-large"></td>
437 for i
in answers
(db
) do
438 t
.add
"<td class=\"answer\
" id=\"newans_
{i.id}\
" onclick=\"change_temp_answer
(this
)\
" style=\"color
:red
;\
"><center>✘</center></td>"
441 <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>"""
443 # Compute score for each answer
444 var scores
= new HashMap[Int, Int]
446 for i
in answers
(db
) do
447 scores
[i
.id
] = i
.score
(db
)
448 if scores
[i
.id
] > maxsc
then maxsc
= scores
[i
.id
]
452 <th>Total ({{{participants(db).length}}})</th>
454 for i
in answers
(db
) do t
.add
"""
455 <th id="total{{{i.id}}}"><center></center></th>
461 {{{"%1 ratio × %2".format("<span style='color:orange'>∇</span>", "<input id='pizza_unit' type='number' placeholder='1' text='1' class='inputsm' style='width: 8ex !important;' onchange='update_scores()' onkeypress='update_scores()' onpaste='update_scores()' oninput='update_scores()'>")}}}
464 for i
in answers
(db
) do t
.add
"""
465 <th id="pizzas{{{i.id}}}"></center></th>