source: indico/indico/MaKaC/webinterface/tpls/ConfReviewingAssignContributions.tpl @ ac1609

burotelhello-world-walkthroughipv6v0.98-seriesv0.98.2v0.98.3v0.98b1v0.98b2v0.99v1.0v1.1
Last change on this file since ac1609 was ac1609, checked in by Jose Benito <jose.benito.gonzalez@…>, 3 years ago

[FIX] - different fixes in the PRM

  • there is the option to enable/disable the automatic e-mails when is added/removed a PRM.
  • Competences - depending on the reviewing mode not all of the reviewers are shown here. For example, if we have only the Layout Reviewing, will be shown only the Layout Reviewers and the PRM.
  • Team - there are now warning messages that the added/removed reviewers will receive an e-mails if the option is enabled from the Setup.
  • Assign Contributions - when we want to remove a Referee or Layout Reviewer from a contributions that don't have ones - there is an alert.
  • Judgements/Final? Judgements - depending on the reviewing mode are shown/not shown the Referee/Layout/Conten? Reviewers Judgements
  • layout fix - For Referee/Content/Layout? Reviewers - the field "Judgements"goes last, because this is the last this that they should do.
  • Display Manager - depending on the reviewing mode in the Display/My? Conference there are different link shown.
  • Property mode set to 100644
File size: 51.1 KB
Line 
1<% import MaKaC.webinterface.urlHandlers as urlHandlers %>
2<% from MaKaC.common.timezoneUtils import nowutc %>
3<% from MaKaC.conference import ContribStatusNone %>
4
5<% dueDateFormat = "%a %d %b %Y" %>
6<% color = '' %>
7<% if not ConfReview.hasReviewing(): %>
8<p style="padding-left: 25px;"><font color="gray"><%= _("Type of reviewing has not been chosen yet")%></font></p>
9<% end %>
10<% else: %>
11<% if len(Conference.getContributionListSortedById()) == 0: %>
12<p style="padding-left: 25px;"><font color="gray"><%= _("There are no contributions to assign.")%></font></p>
13<% end %>
14<%else:%>
15<div style="padding-top:10px; padding-bottom: 10px;padding-left: 10px"><em><%= _("Please, select one or more contributions to assign Reviewers")%></em></div>
16
17<div id="showHideFilteringHelp" style="padding-top: 10px;padding-left: 40px"><div id="showHideFiltering" style="display:inline"></div></div>
18<br/>
19<table id="filteringTable" class="Revtab" width="90%%" align="center">
20    <thead>
21        <tr style="text-align:center;">
22            <td nowrap class="titleCellFormat" style="border-right:5px solid #FFFFFF;border-left:5px solid #FFFFFF;border-bottom:1px solid #BBBBBB;">
23                <%= _("types")%>
24            </td>
25            <td nowrap class="titleCellFormat" style="border-right:5px solid #FFFFFF;border-left:5px solid #FFFFFF;border-bottom:1px solid #BBBBBB;">
26                <%= _("sessions")%>
27            </td>
28            <td nowrap class="titleCellFormat" style="border-right:5px solid #FFFFFF;border-left:5px solid #FFFFFF;border-bottom:1px solid #BBBBBB;">
29                <%= _("tracks")%>
30            </td>
31            <td nowrap class="titleCellFormat" style="border-right:5px solid #FFFFFF;border-left:5px solid #FFFFFF;border-bottom:1px solid #BBBBBB;">
32                <%= _("assign status")%>
33            </td>
34        </tr>
35    </thead>
36    <tbody>
37        <tr style="vertical-align:top">
38            <td>
39                <table cellpadding="0px" cellspacing="0px" border="0px">
40                    <tr>
41                        <td><img src="<%= Config.getInstance().getSystemIconURL("checkAll") %>" alt="Select all" title="Select all" onclick="selectAll('selTypes')" style="border:none;"><img src="<%= Config.getInstance().getSystemIconURL("uncheckAll") %>" alt="Deselect all" title="Deselect all" onclick="deselectAll('selTypes')" style="border:none;"></td>
42                    </tr>
43                    <tr>
44                        <td><input type="checkbox" id="typeShowNoValue" name="selTypes" value="not specified" checked/></td>
45                        <td> --<%= _("not specified")%>--</td>
46                    </tr>
47                    <% for type in self._conf.getContribTypeList(): %>
48                        <tr>
49                            <td><input type="checkbox" name="selTypes" value="<%=type.getId()%>" checked></td>
50                            <td><%= type.getName() %></td>
51                        </tr>
52                    <% end %>
53                </table>
54            </td>
55            <td>
56                <table cellpadding="0px" cellspacing="0px" border="0px">
57                    <tr>
58                        <td><img src="<%= Config.getInstance().getSystemIconURL("checkAll") %>" alt="Select all" title="Select all" onclick="selectAll('selSessions')" style="border:none;"><img src="<%= Config.getInstance().getSystemIconURL("uncheckAll") %>" alt="Deselect all" title="Deselect all" onclick="deselectAll('selSessions')" style="border:none;"></td>
59                    </tr>
60                    <tr>
61                        <td><input type="checkbox" id="sessionShowNoValue" name="selSessions" value="not specified" checked/></td>
62                        <td> --<%= _("not specified")%>--</td>
63                    </tr>
64                    <% for s in self._conf.getSessionListSorted(): %>
65                        <tr>
66                            <td><input type="checkbox" name="selSessions" value="<%=s.getId()%>" checked></td>
67                            <td><%= s.getTitle() %></td>
68                        </tr>
69                    <% end %>
70                </table>
71            </td>
72            <td>
73                <table cellpadding="0px" cellspacing="0px" border="0px">
74                    <tr>
75                        <td><img src="<%= Config.getInstance().getSystemIconURL("checkAll") %>" alt="Select all" title="Select all" onclick="selectAll('selTracks')" style="border:none;"><img src="<%= Config.getInstance().getSystemIconURL("uncheckAll") %>" alt="Deselect all" title="Deselect all" onclick="deselectAll('selTracks')" style="border:none;"></td>
76                    </tr>
77                    <tr>
78                        <td><input type="checkbox" id="trackShowNoValue" name="selTracks" value="not specified" checked/></td>
79                        <td> --<%= _("not specified")%>--</td>
80                    </tr>
81                    <% for t in Conference.getTrackList(): %>
82                        <tr>
83                            <td><input type="checkbox" name="selTracks" value="<%=t.getId()%>" checked></td>
84                            <td><%= t.getTitle() %></td>
85                        </tr>
86                    <% end %>
87                </table>
88            </td>
89            <td>
90                <ul style="list-style-type:none">
91                    <% if not IsOnlyReferee: %>
92                        <li><input type="checkbox" id="showWithReferee" checked/> <%= _("With Referee assigned")%></li>
93                    <% end %>
94                    <li><input type="checkbox" id="showWithEditor" checked/> <%= _("With Layout Reviewer assigned")%></li>
95                    <li><input type="checkbox" id="showWithReviewer" checked/> <%= _("With at least 1 Content Reviewer assigned")%></li>
96
97                </ul>
98            </td>
99        </tr>
100        <tr>
101            <td id="applyFilterHelp" colspan="4" style="border-top: 1px solid rgb(119, 119, 119); padding: 10px;text-align:center">
102                <input id="applyFilter" type="button" class="popUpButton" value="Apply filter"/>
103            </td>
104        </tr>
105    </tbody>
106</table>
107
108<table style="padding-left: 40px">
109    <% if not IsOnlyReferee and not (ConfReview.getChoice() == 3 or ConfReview.getChoice() == 1): %>
110    <tr>
111        <td><%= _("Referee")%>:</td>
112        <td id="assignRefereeHelp">
113            <input id="assignRefereeButton_top" type="button" class="popUpButton" value="Assign">
114            <input id="removeRefereeButton_top" type="button" class="popUpButton" value="Remove">
115        </td>
116    </tr>
117    <% end %>
118    <%if not (ConfReview.getChoice() == 2 or ConfReview.getChoice() == 1):%>
119    <tr>
120        <td><%= _("Layout Reviewer")%>:</td>
121        <td id="assignEditorHelp">
122            <input id="assignEditorButton_top" type="button" class="popUpButton" value="Assign">
123            <input id="removeEditorButton_top" type="button" class="popUpButton" value="Remove">
124        </td>
125    </tr>
126    <% end %>
127    <% if not (ConfReview.getChoice() == 3 or ConfReview.getChoice() == 1): %>
128    <tr>
129        <td><%= _("Content Reviewers")%>:</td>
130        <td id="assignReviewerHelp">
131            <input id="addReviewerButton_top" type="button" class="popUpButton" value="Assign">
132            <input id="removeReviewerButton_top" type="button" class="popUpButton" value="Remove">
133            <input id="removeAllReviewersButton_top" type="button" class="popUpButton" value="Remove All">
134        </td>
135    </tr>
136    <% end %>
137</table>
138<!--  and not (ConfReview.getChoice() == 3 or ConfReview.getChoice() == 1) -->
139
140<table style="padding-left:40px;">
141        <tr>
142            <td style="padding-bottom: 5px; padding-top: 5px">
143                <%= _("Select:") %>
144            </td>
145            <td nowrap class="titleCellFormat" style="padding-bottom: 20px;  padding-top: 20px; border-right:5px solid #FFFFFF;border-left:5px solid #FFFFFF">
146                 <span onclick="selectAll('selectedContributions')" align="left" style="cursor:pointer;padding-bottom:5px;color:#0B63A5;list-style-type:none;" onmouseover="this.style.color='#E25300'" onmouseout="this.style.color='#0B63A5'">
147                        <%= _("All")%>
148                 </span>,
149                 <span onclick="deselectAll('selectedContributions')" align="left" style="cursor:pointer;padding-bottom:5px;color:#0B63A5;list-style-type:none;" onmouseover="this.style.color='#E25300'" onmouseout="this.style.color='#0B63A5'">
150                        <%= _("None")%>
151                 </span>
152            </td>
153        </tr>
154</table>
155
156   <table class="Revtab" width="95%%" cellspacing="0" align="center" border="0" style="padding-left:20px; margin-bottom:1em">
157<!--
158    <tr>
159        <td nowrap class="groupTitle" colspan=4>Contributions to judge as Referee</td>
160    </tr>
161-->
162    <thead>
163        <tr>
164            <td></td>
165            <td nowrap class="titleCellFormat" style="border-right:5px solid #FFFFFF;border-left:5px solid #FFFFFF;">
166                <%= _("Id")%>
167            </td>
168            <td nowrap class="titleCellFormat" style="border-right:5px solid #FFFFFF;border-left:5px solid #FFFFFF;">
169                <%= _("Title")%>
170            </td>
171            <td nowrap class="titleCellFormat" style="border-right:5px solid #FFFFFF;border-left:5px solid #FFFFFF;">
172                <%= _("Type")%>
173            </td>
174            <td nowrap class="titleCellFormat" style="border-right:5px solid #FFFFFF;border-left:5px solid #FFFFFF;">
175                <%= _("Track")%>
176            </td>
177            <td nowrap class="titleCellFormat" style="border-right:5px solid #FFFFFF;border-left:5px solid #FFFFFF;">
178                <%= _("Session")%>
179            </td>
180            <!--
181            <td nowrap class="titleCellFormat" style="border-right:5px solid #FFFFFF;border-left:5px solid #FFFFFF;border-bottom: 1px solid #5294CC;">
182                State
183            </td>
184            -->
185            <td nowrap class="titleCellFormat" style="border-right:5px solid #FFFFFF;border-left:5px solid #FFFFFF;">
186                <%= _("Reviewing team")%>
187            </td>
188            <td nowrap class="titleCellFormat" style="border-right:5px solid #FFFFFF;border-left:5px solid #FFFFFF;">
189                <%= _("Deadline")%>
190            </td>
191        </tr>
192        <tr>
193            <td colspan="8" style="border-bottom: 1px solid grey"></td>
194        </tr>
195    </thead>
196   
197   <tbody id="tablebody">
198    <% for c in Conference.getContributionListSortedById(): %>
199        <% rm = c.getReviewManager() %>
200        <% if not isinstance(c.getStatus(), ContribStatusNone): %>
201         <tr valign="top">
202            <td></td>         
203            <td style="border-right:5px solid #FFFFFF;border-left:5px solid #FFFFFF;">
204                <%= c.getId() %>
205            </td>
206           
207            <td style="border-right:5px solid #FFFFFF;border-left:5px solid #FFFFFF;">
208                <a href="<%= urlHandlers.UHContributionModifReviewing.getURL(c) %>">
209                    <%= c.getTitle() %>
210                </a>
211            </td>
212           
213            <td style="border-right:5px solid #FFFFFF;border-left:5px solid #FFFFFF;">
214                <% if c.getType(): %>
215                    <%= c.getType().getName() %>
216                <% end %>
217            </td>
218           
219            <td style="border-right:5px solid #FFFFFF;border-left:5px solid #FFFFFF;">
220                <% if c.getTrack(): %>
221                    <%= c.getTrack().getTitle() %>
222                <% end %>
223            </td>
224           
225            <td style="border-right:5px solid #FFFFFF;border-left:5px solid #FFFFFF;">
226                <% if c.getSession(): %>
227                    <%= c.getSession().getTitle() %>
228                <% end %>
229            </td>
230           
231            <!--
232            <td style="border-right:5px solid #FFFFFF;border-left:5px solid #FFFFFF;">
233            <% if rm.getLastReview().getRefereeJudgement().isSubmitted(): %>
234                <span style="color:green;">
235                    Judged: <%= rm.getLastReview().getRefereeJudgement().getJudgement() %>
236                </span>
237            <% end %>
238            <% else: %>
239                <span style="color:red;">Not judged yet<br>
240                <%= "<br>".join(rm.getLastReview().getReviewingStatus()) %>
241                </span>
242            <% end %>
243            </td>
244            -->
245            <td>
246                <ul>
247                    <% if not (ConfReview.getChoice() == 3 or ConfReview.getChoice() == 1): %>
248                    <li>
249                        <em><%= _("Referee")%>:</em>
250                    </li>
251                    <% end %>
252                    <li>
253                        <em><%= _("Layout Reviewer")%>:</em>
254                    </li>
255                    <li>
256                        <em><%= _("Content Reviewers")%>:</em>
257                        <ul>
258                        <% for reviewer in rm.getReviewersList() :%>
259                            <li>a</li>
260                        <% end %>
261                        </ul>
262                    </li>
263                </ul>
264            </td>
265           
266            <td style="border-right:5px solid #FFFFFF; border-left:5px solid #FFFFFF;">
267                <% date = rm.getLastReview().getAdjustedRefereeDueDate() %>
268                <% if date is None: %>
269                    <%= _("Deadline not set.")%>
270                <% end %>
271                <% else: %>
272                    <%= date.strftime(dueDateFormat) %>                   
273                <% end %>
274            </td>           
275        </tr>
276        <% end %>
277    <% end %>
278    </tbody>
279</table>
280
281<table style="padding-left: 40px">
282    <% if not IsOnlyReferee and not (ConfReview.getChoice() == 3 or ConfReview.getChoice() == 1): %>
283    <tr>
284        <td><%= _("Referee")%>:</td>
285        <td id="assignRefereeHelp">
286            <input id="assignRefereeButton_bottom" type="button" class="popUpButton" value="Assign">
287            <input id="removeRefereeButton_bottom" type="button" class="popUpButton" value="Remove">
288        </td>
289    </tr>
290    <% end %>
291    <% if not (ConfReview.getChoice() == 2 or ConfReview.getChoice() == 1): %>
292    <tr>
293        <td><%= _("Layout Reviewer")%>:</td>
294        <td id="assignEditorHelp">
295            <input id="assignEditorButton_bottom" type="button" class="popUpButton" value="Assign">
296            <input id="removeEditorButton_bottom" type="button" class="popUpButton" value="Remove">
297        </td>
298    </tr>
299    <% end %>
300    <% if not (ConfReview.getChoice() == 3 or ConfReview.getChoice() == 1): %>
301    <tr>
302        <td><%= _("Content Reviewers")%>:</td>
303        <td id="assignReviewerHelp">
304            <input id="addReviewerButton_bottom" type="button" class="popUpButton" value="Assign">
305            <input id="removeReviewerButton_bottom" type="button" class="popUpButton" value="Remove">
306            <input id="removeAllReviewersButton_bottom" type="button" class="popUpButton" value="Remove All">
307        </td>
308    </tr>
309    <% end %>
310</table>
311
312<div id="userSelection_bottom" style="margin-top: 1em">
313    <span id="userSelectionMessage_bottom"></span>
314    <ul id="userList_bottom">
315    </ul>
316</div>
317
318
319
320
321<script type="text/javascript">
322
323var contributions = $L(); // watchlist of contribution objects, pickled from Indico Contribution objects
324var contributionsIndexes = []; //array that maps contribution ids to the index of the contribution in the 'contributions' watchlist
325var action = ''; // stores which button has been pressed, in order to know which list of users has to be retrieved
326
327/**
328 * Returns a contribution object given its id.
329 * The contribution object is obtained from the 'contributions' watchlist.
330 * @param {Object} id The id of the contribution.
331 */
332var getContribution = function (id) {
333    return contributions.item(contributionsIndexes[id]);
334}
335
336/**
337 * Selects all the checkboxes of a given name
338 */
339var selectAll = function (name) {
340    var checkBoxes = document.getElementsByName(name);
341    if ( checkBoxes ) { // true if there is at least 1 checkbox
342        if ( !checkBoxes.length) { // true if there is only 1 checkbox
343            checkBoxes.checked=true
344        } else { // there is more than 1 checkbox
345            for (i = 0; i < checkBoxes.length; i++) {
346                checkBoxes[i].checked=true
347            }
348        }
349    }
350}
351
352/**
353 * Deselects all the contributions by unticking their checkboxes
354 */
355var deselectAll = function(name) {
356    var checkBoxes = document.getElementsByName(name)
357    if ( checkBoxes ) { // true if there is at least 1 checkbox
358        if ( !checkBoxes.length) { // true if there is only 1 checkbox
359            checkBoxes.checked=false
360        } else { // there is more than 1 checkbox
361            for (i = 0; i < checkBoxes.length; i++) {
362                checkBoxes[i].checked=false
363            }
364        }
365    }
366}
367
368/**
369 * Builds the 'link' to show and hide the filtering options.
370 */
371var buildShowHideFiltering = function() {
372    var option = new Chooser({
373        showFiltering: command(function(){
374            $E('filteringTable').dom.style.display = '';
375            option.set('hideFiltering');
376        }, $T('Show Filtering Criteria')),
377        hideFiltering: command(function(){
378            $E('filteringTable').dom.style.display = 'none';
379            option.set('showFiltering');
380        }, $T('Hide Filtering Criteria'))
381    });
382    option.set('showFiltering');
383   
384    $E('showHideFiltering').set(Widget.link(option));
385}
386
387/**
388 * Builds a table row element from a contribution object, pickled from an Indico's Contribution object
389 * @param {Object} contribution
390 */
391var backgroundColorOver = function() {
392    IndicoUI.Widgets.Generic.tooltip(this.style.backgroundColor='#ECECEC');
393}
394
395var backgroundColorOut = function() {
396    IndicoUI.Widgets.Generic.tooltip(this.style.backgroundColor='transparent');
397}
398
399var contributionTemplate = function(contribution) {
400       
401    var row = Html.tr();
402    row.dom.onmouseover = backgroundColorOver;
403    row.dom.onmouseout = backgroundColorOut;
404    // Cell1: checkbox to select this contribution
405    var cell1 = Html.td({style:{"textAlign":"center", "width":"0px"}});
406    var id = ("cb" + contribution.id);
407    var name = ("selectedContributions");
408   
409    /*
410    //creating the checkbox IE way
411    if (document.all) {   
412    var checkbox = document.createElement('<input name='+name+'>');
413    checkbox.type = "checkbox";
414    checkbox.id = id ;
415    }
416    //the other browsers
417    else {
418        var checkbox = Html.checkbox({id: id, name:name});
419    }
420    cell1.set(checkbox);
421    //checkbox.dom.value = contribution.id; // has to be added after constructor because of IE
422    */
423    var checkbox = Html.input('checkbox', {id: id, name:name});
424    checkbox.dom.value = contribution.id;
425    cell1.set(checkbox);
426   
427    row.append(cell1);
428   
429    // Cell2: contribution id
430    var cell2 = Html.td({style:{"textAlign":"center", "width":"0px"}});
431    cell2.set(contribution.id)
432    row.append(cell2);
433
434    // Cell3: contribution title
435    var cell3 = Html.td();
436    // Sadly this hack is necessary to get the link since getURL() needs a Contribution object (from Indico, not the local one from Javascript)
437    // and contributions are loaded asynchronously...
438    linkString = "<%= urlHandlers.UHContributionModifReviewing.getURL() %>" + "?contribId=" + contribution.id + "&confId=<%= Conference.getId()%>"
439    var link = Html.a({href: linkString});
440    link.set(contribution.title);
441    cell3.set(link);
442    row.append(cell3);
443
444    // Cell4: contribution type
445    var cell4 = Html.td({style:{"marginLeft":"5px"}});
446    cell4.set(contribution.type)
447    row.append(cell4);
448   
449    // Cell5: contribution track
450    var cell5 = Html.td({style:{"marginLeft":"5px"}});
451    cell5.set(contribution.track ? contribution.track.title : "")
452    row.append(cell5);
453   
454    // Cell6: contribution session
455    var cell6 = Html.td({style:{"marginLeft":"5px"}});
456    cell6.set(contribution.session ? contribution.session.title : "")
457    row.append(cell6);
458
459    /*
460    // Cell7: contribution status
461    var cell7 = Html.td();
462   
463    if (contribution.reviewManager.lastReview.refereeJudgement.isSubmitted) {
464        var span = Html.span();
465        span.dom.style.color = 'green';
466        span.set("Judged" + contribution.reviewManager.lastReview.refereeJudgement.judgement);
467        cell7.set(span);
468       
469    } else {
470        var ul = Html.ul();
471        ul.dom.style.color = 'red';
472        ul.dom.style.listStyleType = 'none';
473        ul.dom.style.padding = 0;
474        ul.dom.style.marginLeft = '5px';
475       
476        var li = Html.li();
477        li.set("Not judged yet");
478        ul.append(li);
479       
480        statusList = contribution.reviewManager.lastReview.reviewingStatus;
481        for (j in statusList) {
482            var li = Html.li();
483            li.set(statusList[j])
484            ul.append(li)
485        }
486       
487        cell7.set(ul);
488    }
489
490    row.append(cell7);
491    */
492
493    // Cell8: reviewing team assigned to the contribution
494    var cell8 = Html.td();
495   
496    var ul = Html.ul();
497    ul.dom.style.listStyleType = 'none';
498    ul.dom.style.padding = 0;
499    ul.dom.style.marginLeft = '5px';
500   
501    <% if not (ConfReview.getChoice() == 3 or ConfReview.getChoice() == 1): %>
502    var li1 = Html.li();
503    var span1 = Html.span({}, $T('Referee: '))
504    var span2 = contribution.reviewManager.referee ?
505                    Html.span({id: ("creferee" + contribution.id), style:{"fontWeight":"bolder"}},  contribution.reviewManager.referee.name) :
506                    Html.span({id: ("creferee" + contribution.id)},$T('No referee'));
507    li1.set(Widget.block([span1,span2]));
508    ul.append(li1);
509    <% end %>
510   
511    <% if not (ConfReview.getChoice() == 2 or ConfReview.getChoice() == 1): %>
512    var li2 = Html.li();
513    var span1 = Html.span({}, $T('Layout reviewer: '))
514    var span2 = contribution.reviewManager.editor ?
515                    Html.span({id: ("ceditor" + contribution.id), style:{"fontWeight":"bolder"}},  contribution.reviewManager.editor.name) :
516                    Html.span({id: ("ceditor" + contribution.id)},$T('No layout reviewer'));
517    li2.set(Widget.block([span1,span2]));
518    ul.append(li2);
519    <% end %>
520   
521    <% if not (ConfReview.getChoice() == 3 or ConfReview.getChoice() == 1): %>
522    var li3 = Html.li();
523    var span = Html.span({id : ("creviewerstitle" + contribution.id)}, $T('Content reviewers: '));
524    li3.append(span);
525   
526   
527    var ulReviewers = Html.ul();
528    if (contribution.reviewManager.reviewersList.length > 0){
529        for (j in contribution.reviewManager.reviewersList) {
530            var li = Html.li({id: ("creviewer" + contribution.id + "_" + contribution.reviewManager.reviewersList[j].id), style:{"fontWeight":"bolder"}});
531            li.set(contribution.reviewManager.reviewersList[j].name);
532            ulReviewers.append(li);
533        }
534        li3.append(ulReviewers);
535    } else {
536        var span = Html.span({id: ("creviewer" + contribution.id)},$T('No content reviewers' ));
537        li3.append(span);
538    }
539    ul.append(li3);
540    <% end %>
541   
542    cell8.set(ul);
543    row.append(cell8);
544
545    // Cell9: due date of the contribution
546    var cell9 = Html.td();
547    cell9.set(contribution.reviewManager.lastReview.refereeDueDate)
548    row.append(cell9);
549   
550    return row;
551}
552
553
554/**
555 * Updates the display of the contribution row.
556 * @param {Object} id The id of the contribution.
557 */
558var updateContribution = function (id) {
559    index = contributionsIndexes[id];
560    var c = contributions.item(index);
561    contributions.removeAt(index);
562    contributions.insert(c, index);
563}
564
565
566/**
567 * Returns a list of checkbox values, for a given checkbox name
568 * ('name' attribute of an 'input' HTML element)
569 * The list only contains the checkboxes who are selected.
570 * The first checkbox ('--not specified--' one) is discarded.
571 * @param {Object} checkboxName
572 */
573var getCheckedBoxes = function(checkboxName) {
574   
575    var checkBoxes = document.getElementsByName(checkboxName);
576    var checkedIds = []
577    for (var i=0; i<checkBoxes.length; i++) {
578        var cb = checkBoxes[i];
579        if (cb.checked && cb.value != "not specified") {
580            checkedIds.push(cb.value)
581        }
582    }
583    return checkedIds;
584}
585
586
587/**
588 * Returns a list of contribution ids.
589 * Only the contributios whose checkbox has been selected are returned.
590 */
591var getCheckedContributions = function() {
592   
593    var checkBoxes = document.getElementsByName('selectedContributions');
594    var checkedContributions = []
595   
596    for (var i=0; i<checkBoxes.length; i++) {
597        var cb = checkBoxes[i];
598        if (cb.checked) {
599            checkedContributions.push(cb.id.slice(2))
600        }
601    }
602    return checkedContributions;
603}
604
605/**
606 * Turns the given user orange for some seconds to indicate that it has changed
607 * @param {Object} contributionId The id of the contribution where a user has been assigned
608 * @param {Object} role The role that has been assigned
609 * @param {Object} reviewerId In case of a reviewerm the reviewerId. Otherwise leave to null.
610 */
611var colorify = function(contributionId, role, reviewerId) {
612    id = "c" + role + contributionId;
613    if (reviewerId) {
614        id = id + "_" + reviewerId;
615    }
616    IndicoUI.Effect.highLight(id, 'orange', 2000);
617}
618
619/**
620 * Among a list of contributions (given as contribution ids),
621 * this function unchecks the checboxes of the contributions
622 * who don't ahve a refree yet.
623 * @param {array} contributions List of contribution ids
624 */
625var deselectWithoutReferee = function(contributions) {
626    for (i in contributions) {
627        contributionId = contributions[i];
628        contribution = getContribution(contributionId);
629        if (contribution.reviewManager.referee == null) {
630            $E('cb' + contributionId).dom.checked = false;
631        }
632    }
633}
634
635/**
636 * Among a list of contributions (given as contribution ids),
637 * this function unchecks the checboxes of the contributions
638 * who don't have a reviewer.
639 * @param {array} contributions List of contribution ids
640 */
641var deselectWithoutReviewer = function(contributions) {
642    for (i in contributions) {
643        contributionId = contributions[i];
644        contribution = getContribution(contributionId);
645        if (contribution.reviewManager.reviewersList.length == 0) {
646            $E('cb' + contributionId).dom.checked = false;
647        }
648    }
649}
650
651/**
652 * Checks that all contributions have a Referee.
653 * Returns true if all have a referee, false otherwise.
654 * If none have a referee, an alert message appear.
655 * If some have a referee and others don't, a dialog will appear offering
656 * the choice to only apply the assignment to contributions with referee.
657 * @param {Object} contributions
658 * @param {Object} order
659 * @param {Object} role
660 */
661var checkAllHaveReferee = function(contributions, order, role) {
662    var contributionsWithoutReferee = []
663    for (i in contributions) {
664        contributionId = contributions[i]
665        contribution = getContribution(contributionId)
666        if (contribution.reviewManager.referee == null) {
667            contributionsWithoutReferee.push(contributionId)
668        }
669    }
670    if (contributionsWithoutReferee.length == contributions.length) {
671        alert($T("None of the contributions you checked have a Referee.") +
672            $T("You can only add an editor or a reviewer if the contribution has a referee.")
673        );
674        return false;
675    }
676   
677    if (contributionsWithoutReferee.length > 0) {
678        title =$T('Contributions without referee');   
679           
680        var popup = new ExclusivePopup(title, function(){popup.close();});
681       
682        popup.draw = function(){
683       
684            var span1 = Html.span({}, $T("Some of the contributions you checked do not have a Referee."));
685            var span2 = Html.span({}, $T("You can only add an editor or a reviewer if the contribution has a referee."));
686            var span3 = Html.span({}, $T("Do you want to add that " + role + " only to the contributions with a referee?"));
687            var yesButton = Html.button('popUpButton', $T("Yes"));
688            yesButton.observeClick(function(){
689                deselectWithoutReferee(contributions);
690                fetchUsers(order, role);
691                popup.close();
692            });
693                       
694             var noButton = Html.button('popUpButton', $T("No"));
695            noButton.observeClick(function(){
696                popup.close();
697            });
698              var buttons = Widget.inline([yesButton, noButton])
699              var all = Widget.lines([span1, span2, span3, buttons])
700         return this.ExclusivePopup.prototype.draw.call(this, Html.div({style: {height: '130px', width: '420px'}},[all])); 
701                };
702             popup.open();
703         
704        return false;
705    }
706    return true;
707}
708
709/**
710 * When removing a reviewer from one or more contributions this function takes care for the alert messages.
711 * Returns true if there are no warnings, returns false otherwise.
712 * If are checked contributions with no reviewers assigned, an alert message appears.
713 * If some have a reviewers and others don't, a dialog will appear offering
714 * the choice to only apply the assignment to contributions with reviewer.
715 * @param {Object} contributions
716 * @param {Object} order
717 * @param {Object} role
718 */
719var removeReviewersAlerts = function(contributions, role) {
720    contributionsWithoutReviewers = []
721    for (i in contributions) {
722        contributionId = contributions[i]
723        contribution = getContribution(contributionId)
724        if (contribution.reviewManager.reviewersList.length == 0) {
725            contributionsWithoutReviewers.push(contributionId)
726        }
727    }
728    if (contributionsWithoutReviewers.length == contributions.length) {
729        alert($T("There is no assigned Content Reviewer to remove.")
730        );
731        return false;
732    }
733   
734    contributionsWithoutEditor = []
735    for (i in contributions) {
736        contributionId = contributions[i]
737        contribution = getContribution(contributionId)
738        if (contribution.reviewManager.editor = null) {
739            contributionsWithoutEditor.push(contributionId)
740        }
741    }
742   
743    if (contributionsWithoutEditor.length == contributions.length) {
744        alert($T("There is no assigned Layout Reviewer to remove.")
745        );
746        return false;
747    }
748   
749    if (contributionsWithoutReviewers.length > 0) {
750        title =$T('Contributions without reviewer');   
751           
752        var popup = new ExclusivePopup(title, function(){popup.close();});
753       
754        popup.draw = function(){
755       
756            var span1 = Html.span({}, $T("The Content Reviewers will be removed only from the contributions that have one."));
757            var okButton = Html.button('popUpButton', $T("OK"));
758            okButton.observeClick(function(){
759                deselectWithoutReviewer(contributions);
760                removeUser('allReviewers');
761                popup.close();
762            });
763           
764              var all = Widget.lines([span1, okButton])
765              okButton.dom.align = 'center';
766              return this.ExclusivePopup.prototype.draw.call(this, Html.div({style: {height: '100px', width: '250px'}},[all])); 
767                };
768             popup.open();
769         
770        return false;
771    }
772   
773    return true;   
774}
775
776var removeEditorAlerts = function(contributions, role) {
777   
778    contributionsWithoutEditor = []
779    for (i in contributions) {
780        contributionId = contributions[i]
781        contribution = getContribution(contributionId)
782        if (contribution.reviewManager.editor == null) {
783            contributionsWithoutEditor.push(contributionId)
784        }
785    }
786   
787    if (contributionsWithoutEditor.length == contributions.length) {
788        alert($T("There is no assigned Layout Reviewer to remove.")
789        );
790        return false;
791    }
792   
793    return true;
794   
795}
796
797var removeNoRefereeAlerts = function(contributions, role) {
798   
799    contributionsWithoutEditor = []
800    for (i in contributions) {
801        contributionId = contributions[i]
802        contribution = getContribution(contributionId)
803        if (contribution.reviewManager.referee == null) {
804            contributionsWithoutEditor.push(contributionId)
805        }
806    }
807   
808    if (contributionsWithoutEditor.length == contributions.length) {
809        alert($T("There is no assigned Referee to remove.")
810        );
811        return false;
812    }
813   
814    return true;
815   
816}
817
818/**
819 * When removing a refereee from one or more contributions this function checks
820 * if there are alredy assigned reviewers or editor, or both
821 * @param {array} contributions List of contribution ids
822 */
823var removeRefereeAlerts = function(contributions){
824    for (i in contributions) {
825        contributionId = contributions[i]
826        contribution = getContribution(contributionId)
827    }
828    if(contribution.reviewManager.reviewersList.length != 0 && contribution.reviewManager.editor != null) {
829            return false;
830        }
831    if(contribution.reviewManager.reviewersList.length != 0 && contribution.reviewManager.editor == null){
832           return false;
833        }
834    if(contribution.reviewManager.reviewersList.length == 0 && contribution.reviewManager.editor != null) {
835            return false;
836        }
837   
838    return true;
839}
840
841/**
842 * When removing a refereee from one or more contributions this function takes care for the alert messages.
843 * If are checked contributions with alredy assigned reviewers/editor
844 * alert message appears that a referee should be assigned
845 * @param {array} contributions List of contribution ids
846 */   
847var removeRefereeAlertsMessage = function(contributions){
848    for (i in contributions) {
849        contributionId = contributions[i]
850        contribution = getContribution(contributionId)
851    }
852    var warning = $T("You have to assign new referee.")
853    var message = $T("")
854    if(contribution.reviewManager.reviewersList.length != 0 && contribution.reviewManager.editor != null) {       
855            message = $T("Please note that layout and content have already been assigned for this/these contributions."+ warning)
856            return message;
857        }
858    if(contribution.reviewManager.reviewersList.length != 0 && contribution.reviewManager.editor == null){
859           message = $T("Please note that a content reviewer has already been assigned for this/these contributions."+ warning)
860           return message;
861        }
862    if(contribution.reviewManager.reviewersList.length == 0 && contribution.reviewManager.editor != null) {
863           message = $T("Please note that a layout reviewer has already been assigned for this/these contributions."+ warning)
864            return message;
865        }
866   
867    return message;
868}
869                       
870/**
871 * Function that is called when a user (referee, editor, reviewer) is clicked.
872 * Depending on what has been sotred in the variable 'action', the user will be
873 * added as a referee, added as an editor, removed as a reviewer, etc on the checked contributions.
874 * @param {Object} user The user that has been clicked.
875 */
876var userSelected = function(user){
877   
878    var checkedContributions = getCheckedContributions()
879
880    if (checkedContributions.length > 0) {
881       
882        var params = {conference: '<%= Conference.getId() %>',contributions: checkedContributions, user: user.id}
883       
884        switch(action) {
885        case 'assign_referee':
886            indicoRequest(
887                'reviewing.conference.assignReferee',
888                params,
889                function(result,error) {
890                    if (!error) {
891                        for (i in checkedContributions) {
892                            contributionId = checkedContributions[i];
893                            contribution = getContribution(contributionId);
894                            contribution.reviewManager.referee = user;
895                            updateContribution(contributionId);
896                            colorify(contributionId,'referee');
897                            $E('cb' + contributionId).dom.checked = true; //updateContribution will build a row with an unchecked checkbox
898                        }
899                    } else {
900                        IndicoUtil.errorReport(error);
901                    }
902                }
903            );
904            break;
905           
906        case 'assign_editor':
907            indicoRequest(
908                'reviewing.conference.assignEditor',
909                params,
910                function(result,error) {
911                    if (!error) {
912                        for (i in checkedContributions) {
913                            contributionId = checkedContributions[i]
914                            contribution = getContribution(contributionId)
915                            contribution.reviewManager.editor = user
916                            updateContribution(contributionId)
917                            colorify(contributionId,'editor');
918                            $E('cb' + contributionId).dom.checked = true; //updateContribution will build a row with an unchecked checkbox
919                        }
920                    } else {
921                        IndicoUtil.errorReport(error);
922                    }     
923                }
924            );
925            break;
926           
927        case 'add_reviewer':
928            indicoRequest(
929                'reviewing.conference.addReviewer',
930                params,
931                function(result,error) {
932                    if (!error) {
933                        for (i in checkedContributions) {
934                            contributionId = checkedContributions[i]
935                            contribution = getContribution(contributionId)
936                           
937                            var present = false;
938                            for (j in contribution.reviewManager.reviewersList) {
939                                if (contribution.reviewManager.reviewersList[j].id == user.id) {
940                                    present = true;
941                                    break;
942                                }
943                            }
944                            if (!present) {
945                                contribution.reviewManager.reviewersList.push(user)
946                            }
947
948                            updateContribution(contributionId);
949                            colorify(contributionId,'reviewer', user.id);
950                            $E('cb' + contributionId).dom.checked = true; //updateContribution will build a row with an unchecked checkbox
951                        }
952                    } else {
953                        IndicoUtil.errorReport(error);
954                    } 
955                }
956            );
957            break;
958           
959        case 'remove_reviewer':
960            indicoRequest(
961                'reviewing.conference.removeReviewer',
962                params,
963                function(result, error) {
964                    notinlist2 = [];
965                    if(!error) {
966                        for (i in checkedContributions) {
967                            contributionId = checkedContributions[i]
968                            contribution = getContribution(contributionId)
969                           
970                            notinlist = false;
971                            deleted = false;
972                            for (j in contribution.reviewManager.reviewersList) {
973                                if (contribution.reviewManager.reviewersList[j].id == user.id) {
974                                    contribution.reviewManager.reviewersList.splice(j,1);
975                                    updateContribution(contributionId);
976                                    colorify(contributionId,'reviewerstitle');
977                                    $E('cb' + contributionId).dom.checked = true; //updateContribution will build a row with an unchecked checkbox
978                                    deleted = true;
979                                } else {
980                                    notinlist = true;
981                                    notinlist2.push(contributionId)
982                                    $E('cb' + contributionId).dom.checked = false;
983                                   
984                                }
985                            }                   
986                        }
987                   } else {
988                        IndicoUtil.errorReport(error);
989                   }
990                }
991            );
992            break;
993           
994        default:
995            break;
996        }
997               
998    }
999}
1000
1001
1002
1003/**
1004 * Requests the list of contribution from the server,
1005 * given the filtering parameters.
1006 */
1007var fetchContributions = function() {
1008   
1009    contributions.clear();
1010    contributionsIndexes = []
1011    indicoRequest('event.contributions.list',
1012        {
1013            conference: '<%= Conference.getId() %>',
1014            typeShowNoValue : $E('typeShowNoValue').dom.checked,
1015            trackShowNoValue : $E('trackShowNoValue').dom.checked,
1016            sessionShowNoValue : $E('sessionShowNoValue').dom.checked,
1017            selTypes : getCheckedBoxes('selTypes'),
1018            selTracks : getCheckedBoxes('selTracks'),
1019            selSessions : getCheckedBoxes('selSessions'),
1020            <% if not IsOnlyReferee: %>
1021            showWithReferee: $E('showWithReferee').dom.checked,
1022            <% end %>
1023            showWithEditor: $E('showWithEditor').dom.checked,
1024            showWithReviewer: $E('showWithReviewer').dom.checked
1025        },
1026        function(result, error){
1027            if (!error) {
1028                for (i in result) {
1029                    c = result[i]
1030                    contributions.append(c);
1031                    contributionsIndexes[c.id] = i;
1032                }
1033            } else {
1034                IndicoUtil.errorReport(error);
1035            }
1036        }
1037    )
1038}
1039
1040/**
1041 * Retrieves a list of users from the server.
1042 * @param {string} order The action that will be taken on the users: 'assign', 'remove'.
1043 * @param {string} role The role of the users: 'referee', 'editor', 'reviewer'.
1044 */
1045var fetchUsers = function(order, role) {
1046   
1047    var checkedContributions = getCheckedContributions();
1048    if (checkedContributions.length == 0) {
1049        alert($T("Please select at least 1 contribution"));
1050        return;
1051    }
1052   
1053    if ((order == 'assign' && role == 'editor') || (order == 'add' && role == 'reviewer')) {
1054        <% if not (ConfReview.getChoice() == 3 or ConfReview.getChoice() == 1): %>
1055                if (!checkAllHaveReferee(checkedContributions, order, role)) {
1056                    return;
1057                }
1058            <% end %>
1059   }
1060   
1061   if (order == 'remove' && role == 'reviewer')  {
1062        if (!removeReviewersAlerts(checkedContributions, role)) {
1063            return;
1064        }
1065   }
1066   
1067   
1068    indicoRequest(
1069        'reviewing.conference.userCompetencesList',
1070        {conference: '<%= Conference.getId() %>', role: role},
1071        function(result,error) {
1072            if (!error) {
1073               
1074                action = order + '_' + role;
1075               
1076                var title = '';
1077                var new_assign = '';
1078                if (role == 'editor') {
1079                    title = $T('Click on a user name to ') + order + $T(' a layout reviewer:');
1080                }
1081                if (role == 'reviewer') {
1082                    title = $T('Click on a user name to ') + order + ' a ' + $T('content reviewer:');
1083                } else {
1084                    if (order == 'assign') {
1085                    title = $T('Click on a user name to ') + order + ' a ' + role + ':';
1086                    } if(order == 'new_assign' && !removeRefereeAlerts(checkedContributions)) {
1087                        action = 'assign_' + role;
1088                        title = $T('Click on a user name to assign new ') + role + ':';
1089                        new_assign = 'True';
1090                    }
1091                }
1092               
1093                var popup = new ExclusivePopup(title, function(){popup.close();});
1094               
1095                popup.draw = function(){
1096                        var users = $L();
1097                        var userTemplate = function(user) {
1098                            var li = Html.li();
1099                            var userName = Widget.link(command(function(){
1100                                userSelected(user);
1101                                var killProgress = IndicoUI.Dialogs.Util.progress()
1102                                popup.close();
1103                                killProgress();
1104                            }, user.name));
1105                       
1106                       
1107                        var userCompetences = Html.span({style:{marginLeft:'5px'}},
1108                            user.competences.length == 0 ? $T('(no competences defined)') : $T('(competences: ') + user.competences.join(', ') + ')'
1109                        );
1110                       
1111                        li.set(Widget.inline([userName, userCompetences]));
1112                        return li;
1113                    }   
1114                   
1115                        var userList = Html.ul();
1116                        bind.element(userList, users, userTemplate);
1117                       
1118                        for (i in result) {
1119                        users.append(result[i]);
1120                        }                       
1121                         
1122                        var cancelButton = Html.button({style:{marginLeft:pixels(5)}}, $T("Cancel"));
1123                          cancelButton.observeClick(function(){
1124                          popup.close();
1125                           });
1126                       
1127                       var span1 = Html.span({}, "");
1128                       var message = '';
1129                       if(new_assign) {
1130                            span1 = Html.span({}, removeRefereeAlertsMessage(checkedContributions));
1131                       }   
1132                       if(role == 'reviewer' && order == 'remove') {
1133                            if (checkedContributions.length == 1){
1134                                    message = $T("The Reviewer you choose will be removed only from the contribution that is assigned to him/her.")
1135                                } else {
1136                                    message = $T("The Reviewer you choose will be removed only from the contributions that are assigned to him/her.")
1137                                }
1138                            span1 = Html.span({}, message);
1139                       }   
1140                        return this.ExclusivePopup.prototype.draw.call(this, Widget.block([span1, userList, cancelButton])); 
1141                };
1142             popup.open();
1143             
1144            } else {
1145                IndicoUtil.errorReport(error);
1146            }
1147        }
1148    );
1149}
1150
1151/**
1152 * Removes the referee, the editor, or all the reviewers from the contributions that are selected.
1153 * @param {Object} role 'referee', 'editor', 'allReviewers'
1154 */
1155var removeUser = function(role) {
1156   
1157    var checkedContributions = getCheckedContributions();
1158    if (checkedContributions.length == 0) {
1159        alert($T("Please select at least 1 contribution"));
1160        return;
1161    }
1162   
1163    var params = {conference: '<%= Conference.getId() %>',contributions: checkedContributions}
1164   
1165    switch(role) {
1166    case 'referee':
1167        indicoRequest(
1168            'reviewing.conference.removeReferee',
1169            params,
1170            function(result,error) {
1171                if (!error) {
1172                    if (!removeNoRefereeAlerts(checkedContributions, role)) {
1173                                return;
1174                        }
1175                    for (i in checkedContributions) {
1176                        contributionId = checkedContributions[i];
1177                        contribution = getContribution(contributionId);
1178                        contribution.reviewManager.referee = null;
1179                        updateContribution(contributionId);
1180                        colorify(contributionId, 'referee')
1181                        $E('cb' + contributionId).dom.checked = true; //updateContribution will build a row with an unchecked checkbox
1182                                               
1183                    }
1184                    if(!removeRefereeAlerts(checkedContributions)){
1185                      fetchUsers('new_assign', 'referee')
1186                    }
1187                } else {
1188                    IndicoUtil.errorReport(error);
1189                }
1190            }
1191        );
1192        break;
1193    case 'editor':
1194        indicoRequest(
1195            'reviewing.conference.removeEditor',
1196            params,
1197            function(result,error) {
1198                if (!error) {
1199                    if (!removeEditorAlerts(checkedContributions, role)) {
1200                                return;
1201                        }
1202                    for (i in checkedContributions) {
1203                        contributionId = checkedContributions[i];
1204                        contribution = getContribution(contributionId);
1205                        contribution.reviewManager.editor = null;
1206                        updateContribution(contributionId);
1207                        colorify(contributionId, 'editor')
1208                        $E('cb' + contributionId).dom.checked = true; //updateContribution will build a row with an unchecked checkbox
1209                    }
1210                } else {
1211                    IndicoUtil.errorReport(error);
1212                }
1213            }
1214        );
1215        break;
1216    case 'allReviewers':
1217        indicoRequest(
1218            'reviewing.conference.removeAllReviewers',
1219            params,
1220            function(result,error) {
1221                if (!error) {
1222                    if (!removeReviewersAlerts(checkedContributions, role)) {
1223                                return;
1224                        }
1225                    for (i in checkedContributions) {
1226                        contributionId = checkedContributions[i];
1227                        contribution = getContribution(contributionId);
1228                        contribution.reviewManager.reviewersList = [];
1229                        updateContribution(contributionId);
1230                        colorify(contributionId, 'reviewer')
1231                        $E('cb' + contributionId).dom.checked = true; //updateContribution will build a row with an unchecked checkbox
1232                    }
1233                } else {
1234                    IndicoUtil.errorReport(error);
1235                }
1236            }
1237        );
1238    default:
1239        break;
1240    }
1241}
1242
1243// Code to be executed on page load
1244
1245buildShowHideFiltering();
1246$E('filteringTable').dom.style.display = 'none';
1247
1248bind.element($E("tablebody"), contributions, contributionTemplate);
1249
1250$E('applyFilter').observeClick(fetchContributions);
1251
1252<% if not IsOnlyReferee and not (ConfReview.getChoice() == 3 or ConfReview.getChoice() == 1): %>
1253$E('assignRefereeButton_top').observeClick(function(){ fetchUsers('assign', 'referee'); });
1254$E('assignRefereeButton_bottom').observeClick(function(){ fetchUsers('assign', 'referee'); });
1255$E('removeRefereeButton_top').observeClick(function(){ removeUser('referee') });
1256$E('removeRefereeButton_bottom').observeClick(function(){ removeUser('referee') });
1257<% end %>
1258
1259<% if not (ConfReview.getChoice() == 2 or ConfReview.getChoice() == 1): %>
1260$E('assignEditorButton_top').observeClick(function(){ fetchUsers('assign', 'editor'); });
1261$E('assignEditorButton_bottom').observeClick(function(){ fetchUsers('assign', 'editor'); });
1262$E('removeEditorButton_top').observeClick(function(){ removeUser('editor') });
1263$E('removeEditorButton_bottom').observeClick(function(){ removeUser('editor') });
1264<% end %>
1265
1266<% if not (ConfReview.getChoice() == 3 or ConfReview.getChoice() == 1): %>
1267$E('addReviewerButton_top').observeClick(function(){ fetchUsers('add', 'reviewer'); });
1268$E('addReviewerButton_bottom').observeClick(function(){ fetchUsers('add', 'reviewer'); });
1269$E('removeReviewerButton_top').observeClick(function(){ fetchUsers('remove', 'reviewer'); });
1270$E('removeReviewerButton_bottom').observeClick(function(){ fetchUsers('remove', 'reviewer'); });
1271$E('removeAllReviewersButton_top').observeClick(function(){ removeUser('allReviewers') });
1272$E('removeAllReviewersButton_bottom').observeClick(function(){ removeUser('allReviewers') });
1273<% end %>
1274
1275
1276fetchContributions();
1277   
1278</script>
1279<% end %>
1280<% end %>
Note: See TracBrowser for help on using the repository browser.