function list_actions(Contact $user, $qreq, PaperList $pl, &$actions) { if (!$user->isPC || Navigation::page() === "reviewprefs") { return; } // tagtype cell $tagopt = array("a" => "Add", "d" => "Remove", "s" => "Define", "xxxa" => null, "ao" => "Add to order", "aos" => "Add to gapless order", "so" => "Define order", "sos" => "Define gapless order", "sor" => "Define random order"); $tagextra = array("id" => "placttagtype"); if ($user->privChair) { $tagopt["xxxb"] = null; $tagopt["da"] = "Clear twiddle"; $tagopt["cr"] = "Calculate rank"; $tagextra["onchange"] = "plactions_dofold()"; Ht::stash_script("plactions_dofold()", "plactions_dofold"); } // tag name cell $t = ""; if ($user->privChair) { $t .= '<span class="fx99"><a class="q" href="#" onclick="return fold(\'placttags\')">' . expander(null, 0) . "</a></span>"; } $t .= 'tag<span class="fn99">(s)</span> ' . Ht::entry("tag", $qreq->tag, ["size" => 15, "onfocus" => "autosub('tag',this)", "class" => "wantcrpfocus"]) . ' ' . Ht::submit("fn", "Go", ["value" => "tag", "onclick" => "return plist_submit.call(this)"]); if ($user->privChair) { $t .= "<div class='fx'><div style='margin:2px 0'>" . Ht::checkbox("tagcr_gapless", 1, $qreq->tagcr_gapless, array("style" => "margin-left:0")) . " " . Ht::label("Gapless order") . "</div>" . "<div style='margin:2px 0'>Using: " . Ht::select("tagcr_method", PaperRank::methods(), $qreq->tagcr_method) . "</div>" . "<div style='margin:2px 0'>Source tag: ~" . Ht::entry("tagcr_source", $qreq->tagcr_source, array("size" => 15)) . "</div></div>"; } $actions[] = [500, "tag", "Tag", "<b>:</b> " . Ht::select("tagfn", $tagopt, $qreq->tagfn, $tagextra) . " ", ["id" => "foldplacttags", "class" => "foldc fold99c", "content" => $t]]; }
echo " (<a class='q' href=\"" . hoturl("search", "q=pri:" . urlencode($pc->email)) . "\">{$numPrimary} primary</a>)"; } } echo "</div><hr class=\"c\" /></div></div>\n"; } echo "</div>\n", "<div class='aa' style='margin-bottom:0'>", Ht::submit("update", "Save assignments", array("class" => "bb")), " ", Ht::submit("cancel", "Cancel"), " <span id='assresult' style='padding-left:1em'></span></div>\n\n", '</div></form>'; } echo "</div></div>\n"; // add external reviewers echo Ht::form($loginUrl), '<div class="aahc revcard"><div class="revcard_head">', "<h3>Request an external review</h3>\n", "<div class='hint'>External reviewers get access to their assigned papers, including "; if (setting("extrev_view") >= 2) { echo "the other reviewers' identities and "; } echo "any eventual decision. Before requesting an external review,\n you should generally check personally whether they are interested."; if ($Me->allow_administer($prow)) { echo "\nTo create a review with no associated reviewer, leave Name and Email blank."; } echo '</div></div><div class="revcard_body">'; echo "<div class='f-i'><div class='f-ix'>\n <div class='f-c'>Name</div>\n <div class='f-e'><input type='text' name='name' value=\"", htmlspecialchars(defval($_REQUEST, "name", "")), "\" size='32' tabindex='1' /></div>\n</div><div class='f-ix'>\n <div class='f-c", isset($Error["email"]) ? " error" : "", "'>Email</div>\n <div class='f-e'><input type='text' name='email' value=\"", htmlspecialchars(defval($_REQUEST, "email", "")), "\" size='28' tabindex='1' /></div>\n</div><hr class=\"c\" /></div>\n\n"; // reason area $null_mailer = new HotCRPMailer(); $reqbody = $null_mailer->expand_template("requestreview", false); if (strpos($reqbody["body"], "%REASON%") !== false) { echo "<div class='f-i'>\n <div class='f-c'>Note to reviewer <span class='f-cx'>(optional)</span></div>\n <div class='f-e'>", Ht::textarea("reason", @$_REQUEST["reason"], array("class" => "papertext", "rows" => 2, "cols" => 60, "tabindex" => 1, "spellcheck" => "true")), "</div><hr class=\"c\" /></div>\n\n"; } echo "<div class='f-i'>\n", Ht::submit("add", "Request review", array("tabindex" => 2)), "</div>\n\n"; if ($Me->can_administer($prow)) { echo "<div class='f-i'>\n ", Ht::checkbox("override"), " ", Ht::label("Override deadlines and any previous refusal"), "\n</div>\n"; } echo "</div></div></form>\n"; $Conf->footer();
} asort($tmpl); foreach ($tmpl as $k => &$v) { $v = $mailTemplates[$k]["mailtool_name"]; } if (!isset($_REQUEST["template"]) || !isset($tmpl[$_REQUEST["template"]])) { $_REQUEST["template"] = "genericmailtool"; } echo Ht::select("template", $tmpl, $_REQUEST["template"], array("onchange" => "highlightUpdate(\"loadtmpl\")")), " ", Ht::submit("loadtmpl", "Load", array("id" => "loadtmpl")), " \n <span class='hint'>Templates are mail texts tailored for common conference tasks.</span>\n</div>\n\n<div class='mail' style='float:left;margin:4px 1em 12px 0'><table>\n"; // ** TO echo '<tr><td class="mhnp nw">To:</td><td class="mhdd">', $recip->selectors(), "<div class='g'></div>\n"; // paper selection echo '<div id="foldpsel" class="fold8c fold9o fold10c">'; echo '<table class="fx9"><tr>'; if ($Me->privChair) { echo '<td class="nw">', Ht::checkbox("plimit", 1, isset($_REQUEST["plimit"]), ["id" => "plimit", "onchange" => "fold('psel', !this.checked, 8)"]), " </td><td>", Ht::label("Choose papers", "plimit"), "<span class='fx8'>: "; } else { echo '<td class="nw">Papers: </td><td>', Ht::hidden("plimit", 1), '<span>'; } echo Ht::entry("q", @$_REQUEST["q"], array("id" => "q", "placeholder" => "(All)", "class" => "hotcrp_searchbox", "size" => 36)), " in "; if (count($tOpt) == 1) { echo htmlspecialchars($tOpt[$_REQUEST["t"]]); } else { echo " ", Ht::select("t", $tOpt, $_REQUEST["t"], array("id" => "t")); } echo " ", Ht::submit("psearch", "Search"); echo "</span>"; if (isset($_REQUEST["plimit"]) && !isset($_REQUEST["monreq"]) && (isset($_REQUEST["loadtmpl"]) || isset($_REQUEST["psearch"]))) { $plist = new PaperList(new PaperSearch($Me, ["t" => $_REQUEST["t"], "q" => $_REQUEST["q"]])); $ptext = $plist->table_html("reviewers", ["noheader" => true, "nofooter" => true]); echo "<div class='fx8'>";
function show_regrades($result) { global $Conf, $Me, $Now, $LastPsetFix; $rows = $uids = []; while ($row = edb_orow($result)) { $row->notes = json_decode($row->notes); $latest = ""; $uid = 0; foreach (get($row->notes, "flags", []) as $t => $v) { if (!get($v, "resolved") && $t > $latest) { $latest = $t; $uid = get($v, "uid"); } } if ($latest) { $rows[] = [$latest, $uid, $row]; $uids[$uid] = true; } } Dbl::free($result); if (empty($rows)) { return; } usort($rows, function ($a, $b) { return strcmp($a[0], $b[0]); }); $contacts = []; $result = $Conf->qe("select * from ContactInfo where contactId?a", array_keys($uids)); while ($c = Contact::fetch($result, $Conf)) { $contacts[$c->contactId] = $c; } Dbl::free($result); echo '<div id="_regrades">'; echo "<h3>flagged commits</h3>"; echo '<table class="s61"><tbody>'; $trn = 0; $checkbox = false; $sprefix = ""; $reqsort = req("sort"); $reqanonymize = req("anonymize"); $pcmembers = pcMembers(); foreach ($rows as $rowx) { $uid = $rowx[1]; $row = $rowx[2]; $u = $contacts[$uid]; ++$trn; echo '<tr class="k', $trn % 2, '">'; if ($checkbox) { echo '<td class="s61checkbox">', Ht::checkbox("s61_" . urlencode($Me->user_idpart($u)), 1, array("class" => "s61check")), '</td>'; } echo '<td class="s61rownumber">', $trn, '.</td>'; $pset = $Conf->pset_by_id($row->pset); echo '<td class="s61pset">', htmlspecialchars($pset->title), '</td>'; echo '<td class="s61username">', '<a href="', hoturl("pset", ["pset" => $pset->urlkey, "u" => $Me->user_linkpart($u), "commit" => $row->hash, "sort" => $reqsort]), '">', htmlspecialchars($Me->user_linkpart($u)), '</a></td>', '<td class="s61hash"><a href="', hoturl("pset", array("pset" => $pset->urlkey, "u" => $Me->user_linkpart($u), "commit" => $row->hash, "sort" => $reqsort)), '">', substr($row->hash, 0, 7), '</a></td>'; if (get($row->notes, "gradercid") || $row->main_gradercid) { $gcid = get($row->notes, "gradercid") ?: $row->main_gradercid; if (isset($pcmembers[$gcid])) { echo "<td>" . htmlspecialchars($pcmembers[$gcid]->firstName) . "</td>"; } else { echo "<td>???</td>"; } } else { echo "<td></td>"; } echo "<td>"; if ($row->hash === $row->gradehash) { echo "✱"; } if ($row->haslinenotes) { echo "♪"; } echo "</td>"; $total = ""; if ($row->notes) { $garr = render_grades($pset, $row->notes, null); if ($garr->totalindex !== null) { $total = $garr->all[$garr->totalindex]; } } echo '<td class="r">' . $total . '</td>'; echo '</tr>'; } echo "</tbody></table></div>\n"; }
echo '<td><button type="button" class="foldc" style="padding-bottom:5px" onclick="trackertable_mute(this)"> <svg id="soundicon" class="fn" width="1.5em" height="1.5em" viewBox="0 0 75 75" style="position:relative;bottom:-3px"> <polygon points="39.389,13.769 22.235,28.606 6,28.606 6,47.699 21.989,47.699 39.389,62.75 39.389,13.769" style="stroke:#111111;stroke-width:5;stroke-linejoin:round;fill:#111111;" /> <path d="M 48.128,49.03 C 50.057,45.934 51.19,42.291 51.19,38.377 C 51.19,34.399 50.026,30.703 48.043,27.577" style="fill:none;stroke:#111111;stroke-width:5;stroke-linecap:round"/> <path d="M 55.082,20.537 C 58.777,25.523 60.966,31.694 60.966,38.377 C 60.966,44.998 58.815,51.115 55.178,56.076" style="fill:none;stroke:#111111;stroke-width:5;stroke-linecap:round"/> <path d="M 61.71,62.611 C 66.977,55.945 70.128,47.531 70.128,38.378 C 70.128,29.161 66.936,20.696 61.609,14.01" style="fill:none;stroke:#111111;stroke-width:5;stroke-linecap:round"/> </svg><svg id="muteicon" class="fx" width="1.5em" height="1.5em" viewBox="0 0 75 75" style="position:relative;bottom:-3px"> <polygon points="39.389,13.769 22.235,28.606 6,28.606 6,47.699 21.989,47.699 39.389,62.75 39.389,13.769" style="stroke:#111111;stroke-width:5;stroke-linejoin:round;fill:#111111;" /> <path d="M 48.651772,50.269646 69.395223,25.971024" style="fill:none;stroke:#111111;stroke-width:5;stroke-linecap:round"/> <path d="M 69.395223,50.269646 48.651772,25.971024" style="fill:none;stroke:#111111;stroke-width:5;stroke-linecap:round" /> </svg></button></td>'; //echo '<span class="hidden fhn_ib"> Mute</span>'; //echo '<span class="hidden fhx_ib"> Unmute</span></button></td>'; // show-papers if ($Me->has_database_account()) { echo '<td style="padding-left:2em">', Ht::checkbox("buzzer_showpapers", 1, $show_papers, array("id" => "buzzer_showpapers", "onclick" => "trackertable_showpapers()")), " ", Ht::label("Show papers"), '</td>'; Ht::stash_script("trackertable_showpapers()"); } // kiosk mode if ($Me->privChair) { echo '<td style="padding-left:2em">', Ht::js_button("Kiosk mode", "popup(this,'kiosk',0,true)"), '</td>'; $Conf->footerHtml('<div id="popup_kiosk" class="popupc"> <p>Kiosk mode is a discussion status page with no other site privileges. It’s safe to leave a browser in kiosk mode open in the hallway.</p> <p><b>Kiosk mode will sign you out of the site.</b> Do not use kiosk mode on your main browser. Instead, sign in to another browser and navigate to this page. Or use these URLs:</p> <p><table><tr><td class="lcaption nw">With papers</td> <td>' . hoturl_absolute("buzzer", array("__PATH__" => $kiosk_keys[1])) . '</td></tr>
public function echo_checkbox_row($name, $text, $onchange = null) { $x = $this->curv($name); echo '<tr><td class="nw">', Ht::hidden("has_{$name}", 1), Ht::checkbox($name, 1, $x !== null && $x > 0, $this->sjs($name, array("onchange" => $onchange, "id" => "cb{$name}"))), " </td><td>", $this->label($name, $text, true), "</td></tr>\n"; }
$tmpl[$k] = defval($v, "mailtool_priority", 100); } } asort($tmpl); foreach ($tmpl as $k => &$v) { $v = $mailTemplates[$k]["mailtool_name"]; } if (!isset($_REQUEST["template"]) || !isset($tmpl[$_REQUEST["template"]])) { $_REQUEST["template"] = "genericmailtool"; } echo Ht::select("template", $tmpl, $_REQUEST["template"], array("onchange" => "highlightUpdate(\"loadtmpl\")")), " ", Ht::submit("loadtmpl", "Load", array("id" => "loadtmpl")), " \n <span class='hint'>Templates are mail texts tailored for common conference tasks.</span>\n</div>\n\n<div class='mail' style='float:left;margin:4px 1em 12px 0'><table>\n"; // ** TO echo '<tr><td class="mhnp">To:</td><td class="mhdd">', $recip->selectors(), "<div class='g'></div>\n"; // paper selection echo '<div id="foldpsel" class="fold8c fold9o fold10c">'; echo '<table class="fx9"><tr><td>', Ht::checkbox("plimit", 1, isset($_REQUEST["plimit"]), array("id" => "plimit", "onchange" => "fold('psel', !this.checked, 8)")), " </td><td>", Ht::label("Choose individual papers", "plimit"); echo "<span class='fx8'>:</span><br /><div class='fx8'>"; $q = defval($_REQUEST, "q", "(All)"); echo "Search ", Ht::entry("q", @$_REQUEST["q"], array("id" => "q", "hottemptext" => "(All)", "class" => "hotcrp_searchbox", "size" => 36, "title" => "Enter paper numbers or search terms")), " in ", Ht::select("t", $tOpt, $_REQUEST["t"], array("id" => "t")), "</div></td></tr></table>\n"; echo '<div class="fx9 g"></div></div>'; Ht::stash_script("fold(\"psel\",!\$\$(\"plimit\").checked,8);" . "setmailpsel(\$\$(\"recipients\"))"); echo "</td></tr>\n"; Ht::stash_script("mktemptext('q','(All)')"); // ** CC, REPLY-TO if ($Me->privChair) { foreach (Mailer::$email_fields as $lcfield => $field) { if ($lcfield !== "to" && $lcfield !== "bcc") { $xfield = $lcfield == "reply-to" ? "replyto" : $lcfield; $ec = isset($Error[$xfield]) ? " error" : ""; echo " <tr><td class='mhnp{$ec}'>{$field}:</td><td class='mhdp{$ec}'>", "<input type='text' class='textlite-tt' name='{$xfield}' value=\"", htmlspecialchars($_REQUEST[$xfield]), "\" size='64' />", $xfield == "replyto" ? "<div class='g'></div>" : "", "</td></tr>\n\n"; }
function echo_linenote_entry_prototype() { echo '<tr class="diffl61 gw iscomment61"', ' data-pa-savednote="">', '<td colspan="2" class="difflnoteborder61"></td>', '<td class="difflnote61"><div class="diffnoteholder61" style="display:none">', Ht::form($this->hoturl_post("pset", array("savelinenote" => 1)), array("onsubmit" => "return savelinenote61(this)")), '<div class="f-contain">', Ht::hidden("file", ""), Ht::hidden("line", ""), Ht::hidden("iscomment", "", array("class" => "iscomment")), '<textarea class="diffnoteentry61" name="note"></textarea>', '<div class="aab aabr difflnoteaa61">', '<div class="aabut">', Ht::submit("Save comment"), '</div><div class="aabut">'; if ($this->user_can_see_grades) { echo Ht::hidden("iscomment", 1); } else { echo Ht::checkbox("iscomment", 1), ' ', Ht::label("Show immediately"); } echo '</div></div></div></form></div></td></tr>'; }
$paperList = new PaperList($search, ["sort" => true, "list" => true, "reviewer" => $pcm[$reviewer]], make_qreq()); $paperList->display .= " topics "; if ($qreq->kind != "c") { $paperList->display .= "reviewers "; } if (isset($showau)) { $search->overrideMatchPreg = true; $search->matchPreg = array(); if ($showau) { $search->matchPreg["authorInformation"] = make_match_preg($showau); } if ($showco) { $search->matchPreg["collaborators"] = make_match_preg($showco); } } $a = isset($qreq->sort) ? "&sort=" . urlencode($qreq->sort) : ""; echo "<div class='aahc'><form class='assignpc' method='post' action=\"", hoturl_post("manualassign", "reviewer={$reviewer}&kind={$qreq->kind}{$a}"), "\" enctype='multipart/form-data' accept-charset='UTF-8'><div>\n", Ht::hidden("t", $qreq->t), Ht::hidden("q", $qreq->q), Ht::hidden("papx", join(" ", $search->paperList())), "<div class=\"aa\">", Ht::submit("update", "Save assignments", array("class" => "bb")); if ($qreq->kind != "c") { $rev_rounds = $Conf->round_selector_options(); if (count($rev_rounds) > 1) { echo '<span style="padding-left:2em">Review round: ', Ht::select("rev_roundtag", $rev_rounds, $qreq->rev_roundtag ?: "unnamed", array("id" => "assrevroundtag")), '</span>'; } else { if (!@$rev_rounds["unnamed"]) { echo '<span style="padding-left:2em">Review round: ', $Conf->current_round_name(), '</span>'; } } } echo "<span style='padding-left:2em'>", Ht::checkbox(false, false, true, array("id" => "assrevimmediate")), " ", Ht::label("Automatically save assignments", "assrevimmediate"), "</span></div>\n", $paperList->table_html($qreq->kind == "c" ? "conflict" : "reviewAssignment", array("class" => "pltable_full", "table_id" => "foldpl", "header_links" => true, "nofooter" => true, "fold" => array("allrevtopicpref" => true))), "<div class='aa'>", Ht::submit("update", "Save assignments", array("class" => "bb")), "</div></div></form></div>\n"; } echo '<hr class="c" />'; $Conf->footer();
if (isset($_REQUEST["saveassignment"]) && check_post() && isset($_POST["file"]) && get($_POST, "assignment_size_estimate") >= 1000) { complete_assignment("keep_browser_alive"); finish_browser_alive(); } echo Ht::form_div(hoturl_post("bulkassign", "upload=1"), array("divstyle" => "margin-top:1em")); // Upload echo '<div class="f-contain"><div class="f-i"><div class="f-e">', Ht::textarea("bulkentry", req_s("bulkentry"), ["rows" => 1, "cols" => 80, "placeholder" => "Enter assignments"]), '</div></div></div>'; echo '<div class="g"><strong>OR</strong> ', '<input type="file" name="bulk" accept="text/plain,text/csv" size="30" /></div>'; echo '<div id="foldoptions" class="lg foldc fold2o">', 'By default, assign ', Ht::select("default_action", array("primary" => "primary reviews", "secondary" => "secondary reviews", "pcreview" => "optional PC reviews", "review" => "external reviews", "conflict" => "PC conflicts", "lead" => "discussion leads", "shepherd" => "shepherds", "tag" => "add tags", "settag" => "replace tags", "preference" => "reviewer preferences"), defval($_REQUEST, "default_action", "primary"), array("id" => "tsel", "onchange" => "fold(\"options\",this.value!=\"review\");fold(\"options\",!/^(?:primary|secondary|(?:pc)?review)\$/.test(this.value),2)")); $rev_rounds = $Conf->round_selector_options(); if (count($rev_rounds) > 1) { echo '<span class="fx2"> in round ', Ht::select("rev_roundtag", $rev_rounds, $_REQUEST["rev_roundtag"] ?: "unnamed"), '</span>'; } else { if (!get($rev_rounds, "unnamed")) { echo '<span class="fx2"> in round ', $Conf->current_round_name(), '</span>'; } } echo '<div class="g"></div>', "\n"; $requestreview_template = $null_mailer->expand_template("requestreview"); echo Ht::hidden("requestreview_subject", $requestreview_template["subject"]); if (isset($_REQUEST["requestreview_body"])) { $t = $_REQUEST["requestreview_body"]; } else { $t = $requestreview_template["body"]; } echo "<table class='fx'><tr><td>", Ht::checkbox("requestreview_notify", 1, true), " </td><td>", Ht::label("Send email to external reviewers:"), "</td></tr>\n<tr><td></td><td>", Ht::textarea("requestreview_body", $t, array("class" => "tt", "cols" => 80, "rows" => 20, "spellcheck" => "true")), "</td></tr></table>\n"; echo '<div class="g"></div><div class="aa">', Ht::submit("Prepare assignments"), " <span class='hint'>You’ll be able to check the assignment before it is saved.</span></div>\n"; echo '<div style="margin-top:1.5em"><a href="', hoturl_post("search", "t=manager&q=&get=pcassignments&p=all"), '">Download current PC assignments</a></div>'; echo "</div></form>\n\n<hr style='margin-top:1em' />\n\n<div class='helppagetext'>\n<h3>Instructions</h3>\n\n<p>Upload a comma-separated value file to prepare an assignment of reviews,\nconflicts, leads, shepherds, and tags. HotCRP calculates the minimal changes\nbetween the current state and the requested assignment; you’ll confirm those\nchanges before they are committed.</p>\n\n<p>A simple example:</p>\n\n<pre class='entryexample'>paper,assignment,email\n1,primary,man@alice.org\n2,secondary,slugger@manny.com\n1,primary,slugger@manny.com</pre>\n\n<p>This assigns PC members man@alice.org and slugger@manny.com as primary\nreviewers for paper #1, and slugger@manny.com as a secondary\nreviewer for paper #2. Errors will be reported if those users aren’t PC\nmembers, or if they have conflicts with their assigned papers.</p>\n\n<p>A more complex example:</p>\n\n<pre class='entryexample'>paper,assignment,email,round\nall,clearreview,all,R2\n1,primary,man@alice.org,R2\n10,primary,slugger@manny.com,R2\n#manny OR #ramirez,primary,slugger@manny.com,R2</pre>\n\n<p>The first assignment line clears all review assignments in\nround R2. (Review assignments in other rounds are left alone.) The next\nlines assign man@alice.org as a primary reviewer for paper #1, and slugger@manny.com\nas a primary reviewer for paper #10. The last line assigns slugger@manny.com\nas a primary reviewer for all papers tagged #manny or #ramirez.</p>\n\n<p>Assignment types are:</p>\n\n<dl class=\"spaced\">\n<dt><code>review</code></dt>\n\n<dd>Assign a review. The <code>email</code> and/or <code>name</code> columns\nlocate the user. (<code>first</code> and <code>last</code> columns may be used\nin place of <code>name</code>.) The <code>reviewtype</code> column sets the\nreview type; it can be <code>primary</code>, <code>secondary</code>,\n<code>pcreview</code> (optional PC review), or <code>external</code>, or\n<code>clear</code> to unassign the review. The optional\n<code>round</code> column sets the review round.\n\n<p>Only PC members can be assigned primary, secondary, and optional PC\nreviews. Accounts will be created for new external reviewers as necessary. The\n<code>clear</code> action doesn’t delete reviews that have already been\nentered.</p>\n\n<p>Assignments can create new reviews or change existing reviews. Use\n“<code>any</code>” or “old:new” syntax in the <code>round</code> and/or\n<code>reviewtype</code> columns to restrict assignments to existing reviews.\nFor example, to create a new assignment or modify an existing review:</p>\n\n<pre class=\"entryexample\">paper,assignment,email,reviewtype,round\n1,review,drew@harvard.edu,primary,R2</pre>\n\n<p>To modify an existing review’s round (“<code>any</code>” restricts the\nassignment to existing reviews):</p>\n\n<pre class=\"entryexample\">paper,assignment,email,reviewtype,round\n1,review,drew@harvard.edu,any,R2</pre>\n\n<p>To change an existing review from round R1 to round R2:</p>\n\n<pre class=\"entryexample\">paper,assignment,email,reviewtype,round\n1,review,drew@harvard.edu,any,R1:R2</pre>\n\n<p>To change all round-R1 primary reviews to round R2:</p>\n\n<pre class=\"entryexample\">paper,assignment,email,reviewtype,round\nall,review,all,primary,R1:R2</pre>\n\n</dd>\n\n<dt><code>primary</code>, <code>secondary</code>, <code>pcreview</code>,\n<code>external</code>, <code>clearreview</code></dt>\n<dd>Like <code>review</code>, assign a primary, secondary, optional PC, or\nexternal review, or clear existing reviews.</dd>\n\n<dt><code>unsubmitreview</code></dt>\n<dd>Unsubmit a submitted review. The <code>email</code>, <code>name</code>,\n<code>reviewtype</code>, and <code>round</code> columns locate the review.</dd>\n\n<dt><code>lead</code></dt>\n<dd>Set the discussion lead. The <code>email</code>, <code>name</code>,\nand/or <code>user</code> columns locate the PC user. To clear the discussion lead,\nuse email <code>none</code> or assignment type <code>clearlead</code>.</dd>\n\n<dt><code>shepherd</code></dt>\n<dd>Set the shepherd. The <code>email</code>, <code>name</code>,\nand/or <code>user</code> columns locate the PC user. To clear the shepherd,\nuse email <code>none</code> or assignment type <code>clearshepherd</code>.</dd>\n\n<dt><code>conflict</code></dt>\n<dd>Mark a PC conflict. The <code>email</code>, <code>name</code>,\nand/or <code>user</code> columns locate the PC user. To clear a conflict,\nuse assignment type <code>clearconflict</code>.</dd>\n\n<dt><code>tag</code></dt>\n<dd>Add a tag. The <code>tag</code> column names the tag and the optional\n<code>value</code> column sets the tag value.\nTo clear a tag, use assignment type <code>cleartag</code> or value <code>none</code>.</dd>\n\n<dt><code>preference</code></dt>\n<dd>Set reviewer preference and expertise. The <code>preference</code> column\ngives the preference value.</dd>\n</dl>\n\n</div>\n"; $Conf->footerScript('$("#tsel").trigger("change");$("textarea").autogrow()'); $Conf->footer();
function show_pset_table($pset) { global $Conf, $Me, $Now, $Opt, $Profile, $LastPsetFix; echo '<div id="', $pset->urlkey, '">'; echo "<h3>", htmlspecialchars($pset->title), "</h3>"; if ($Me->privChair) { show_pset_actions($pset); } if ($pset->disabled) { return; } $t0 = $Profile ? microtime(true) : 0; // load students if (@$Opt["restrictRepoView"]) { $view = "l2.link repoviewable"; $viewjoin = "left join ContactLink l2 on (l2.cid=c.contactId and l2.type=" . LINK_REPOVIEW . " and l2.link=l.link)\n"; } else { $view = "4 repoviewable"; $viewjoin = ""; } $result = Dbl::qe("select c.contactId, c.firstName, c.lastName, c.email,\n\tc.huid, c.seascode_username, c.anon_username, c.extension, c.disabled, c.dropped, c.roles, c.contactTags,\n\tpl.link pcid, group_concat(rpl.link) rpcid,\n\tr.repoid, r.cacheid, r.heads, r.url, r.open, r.working, r.lastpset, r.snapcheckat, {$view},\n\trg.gradehash, rg.gradercid, rg.placeholder, rg.placeholder_at\n\tfrom ContactInfo c\n\tleft join ContactLink l on (l.cid=c.contactId and l.type=" . LINK_REPO . " and l.pset={$pset->id})\n\t{$viewjoin}\n\tleft join Repository r on (r.repoid=l.link)\n\tleft join ContactLink pl on (pl.cid=c.contactId and pl.type=" . LINK_PARTNER . " and pl.pset={$pset->id})\n\tleft join ContactLink rpl on (rpl.cid=c.contactId and rpl.type=" . LINK_BACKPARTNER . " and rpl.pset={$pset->id})\n\tleft join RepositoryGrade rg on (rg.repoid=r.repoid and rg.pset={$pset->id})\n\twhere (c.roles&" . Contact::ROLE_PCLIKE . ")=0\n\tand (rg.repoid is not null or not c.dropped)\n\tgroup by c.contactId"); $t1 = $Profile ? microtime(true) : 0; $students = array(); while ($result && ($s = $result->fetch_object("Contact"))) { $s->is_anonymous = $pset->anonymous; Contact::set_sorter($s, @$_REQUEST["sort"]); $students[$s->contactId] = $s; // maybe lastpset links are out of order if ($s->lastpset < $pset) { $LastPsetFix = true; } } uasort($students, "Contact::compare"); $checkbox = $Me->privChair || !$pset->gitless && $pset->runners; $rows = array(); $max_ncol = 0; $incomplete = array(); $pcmembers = pcMembers(); foreach ($students as $s) { if (!isset($s->printed)) { $row = (object) array("student" => $s); $row->text = render_pset_row($pset, $students, $s, $row, $pcmembers); if ($s->pcid && isset($students[$s->pcid])) { $row->ptext = render_pset_row($pset, $students, $students[$s->pcid], $row, $pcmembers); } $rows[$row->sortprefix . $s->sorter] = $row; $max_ncol = max($max_ncol, $row->ncol); if (@$s->incomplete) { $u = $Me->user_linkpart($s); $incomplete[] = '<a href="' . hoturl("pset", array("pset" => $pset->urlkey, "u" => $u, "sort" => @$_REQUEST["sort"])) . '">' . htmlspecialchars($u) . '</a>'; } } } ksort($rows, SORT_NATURAL | SORT_FLAG_CASE); if (count($incomplete)) { echo '<div id="incomplete_pset', $pset->id, '" style="display:none" class="merror">', '<strong>', htmlspecialchars($pset->title), '</strong>: ', 'Your grading is incomplete. Missing grades: ', join(", ", $incomplete), '</div>', '<script>jQuery("#incomplete_pset', $pset->id, '").remove().show().appendTo("#incomplete_notices")</script>'; } if ($checkbox) { echo Ht::form_div(hoturl_post("index", array("pset" => $pset->urlkey, "save" => 1))); } echo '<table class="s61"><tbody>'; $trn = 0; $sprefix = ""; foreach ($rows as $row) { ++$trn; if ($row->sortprefix !== $sprefix && $row->sortprefix[0] == "~") { echo "\n", '<tr><td colspan="' . ($max_ncol + ($checkbox ? 2 : 1)) . '"><hr></td></tr>', "\n"; } $sprefix = $row->sortprefix; echo '<tr class="k', $trn % 2, '">'; if ($checkbox) { echo '<td class="s61rownumber">', Ht::checkbox("s61_" . $Me->user_idpart($row->student), 1, array("class" => "s61check")), '</td>'; } echo '<td class="s61rownumber">', $trn, '.</td>', $row->text, "</tr>\n"; if (@$row->ptext) { echo '<tr class="k', $trn % 2, ' s61partner">'; if ($checkbox) { echo '<td></td>'; } echo '<td></td>', $row->ptext, "</tr>\n"; } } echo "</tbody></table>\n"; if ($Me->privChair && !$pset->gitless_grades) { echo "<div class='g'></div>"; $sel = array("none" => "N/A"); foreach (pcMembers() as $pcm) { $sel[$pcm->email] = Text::name_html($pcm); } $sel["__random__"] = "Random"; echo '<span class="nowrap" style="padding-right:2em">', Ht::select("grader", $sel, "none"), Ht::submit("setgrader", "Set grader"), '</span>'; } if (!$pset->gitless) { $sel = array(); foreach ($pset->runners as $r) { if ($Me->can_run($pset, $r)) { $sel[$r->name] = htmlspecialchars($r->title); } } if (count($sel)) { echo '<span class="nowrap" style="padding-right:2em">', Ht::select("runner", $sel), Ht::submit("runmany", "Run all"), '</span>'; } } if ($checkbox) { echo "</div></form>\n"; } if ($Profile) { $t2 = microtime(true); echo sprintf("<div>Δt %.06f DB, %.06f total</div>", $t1 - $t0, $t2 - $t0); } echo "</div>\n"; }
} echo "<table><tr><td><strong>Show:</strong> </td>\n <td class='pad'>"; $Conf->footerScript('foldmap.ul={"aff":2,"tags":3,"topics":1};'); foreach (array("aff" => "Affiliations", "collab" => "Collaborators", "tags" => "Tags", "topics" => "Topics") as $fold => $text) { if (@$pl->have_folds[$fold] !== null) { echo Ht::checkbox("show{$fold}", 1, $pl->have_folds[$fold], array("onchange" => "fold('ul',!this.checked,'{$fold}')")), " ", Ht::label($text), "<br />\n"; } } echo "</td>"; if (isset($pl->scoreMax)) { echo "<td class='pad'>"; $revViewScore = $Me->aggregated_view_score_bound(); foreach (ReviewForm::all_fields() as $f) { if ($f->view_score > $revViewScore && $f->has_options) { $checked = strpos(displayOptionsSet("uldisplay"), $f->id) !== false; echo Ht::checkbox("show{$f->id}", 1, $checked), " ", Ht::label($f->name_html), "<br />"; } } echo "</td>"; } echo "<td>", Ht::submit("redisplay", "Redisplay"), "</td></tr>\n"; if (isset($pl->scoreMax)) { $ss = array(); foreach (array("A", "V", "D") as $k) { /* ghetto array_intersect_key */ if (isset(ListSorter::$score_sorts[$k])) { $ss[$k] = ListSorter::$score_sorts[$k]; } } echo "<tr><td colspan='3'><div class='g'></div><b>Sort scores by:</b> ", Ht::select("scoresort", $ss, $Conf->session("scoresort", "A")), "</td></tr>"; }
echo '<div class="pc_ctable">', join("", $summary), "</div>\n", "</td></tr></table>\n"; // Bad pairs function bpSelector($i, $which) { static $badPairSelector, $Qreq; if (!$badPairSelector) { $badPairSelector = pc_members_selector_options("(PC member)"); } return Ht::select("bp{$which}{$i}", $badPairSelector, $Qreq["bp{$which}{$i}"] ?: "0", ["onchange" => "badpairs_click()"]); } echo "<div class='g'></div><div class='relative'><table id=\"bptable\"><tbody>\n"; for ($i = 1; $i == 1 || isset($Qreq["bpa{$i}"]); ++$i) { $selector_text = bpSelector($i, "a") . " and " . bpSelector($i, "b"); echo ' <tr><td class="rentry nw">'; if ($i == 1) { echo Ht::checkbox("badpairs", 1, isset($Qreq["badpairs"]), array("id" => "badpairs")), " ", Ht::label("Don’t assign", "badpairs"), " "; } else { echo "or "; } echo '</td><td class="lentry">', $selector_text; if ($i == 1) { echo ' to the same paper (<a href="#" onclick="return badpairs_change(true)">More</a> · <a href="#" onclick="return badpairs_change(false)">Fewer</a>)'; } echo "</td></tr>\n"; } echo "</tbody></table></div>\n"; // Load balancing echo "<h3>Load balancing</h3>"; doRadio('balance', 'new', "Spread new assignments equally among selected PC members"); echo "<br />"; doRadio('balance', 'all', "Spread assignments so that selected PC members have roughly equal overall load");
function render($sv) { global $Conf, $Opt; echo "Can <b>authors see reviews and author-visible comments</b> for their papers?<br />"; if ($Conf->setting("resp_active")) { $no_text = "No, unless responses are open"; } else { $no_text = "No"; } if (!$Conf->setting("au_seerev", 0) && $Conf->timeAuthorViewReviews()) { $no_text .= '<div class="hint">Authors are currently able to see reviews since responses are open.</div>'; } $opts = array(Conf::AUSEEREV_NO => $no_text, Conf::AUSEEREV_YES => "Yes"); if ($sv->newv("au_seerev") == Conf::AUSEEREV_UNLESSINCOMPLETE && !get($Opt, "allow_auseerev_unlessincomplete")) { $Conf->save_setting("opt.allow_auseerev_unlessincomplete", 1); } if (get($Opt, "allow_auseerev_unlessincomplete")) { $opts[Conf::AUSEEREV_UNLESSINCOMPLETE] = "Yes, after completing any assigned reviews for other papers"; } $opts[Conf::AUSEEREV_TAGS] = "Yes, for papers with any of these tags: " . $sv->render_entry("tag_au_seerev", ["onfocus" => "\$('#au_seerev_" . Conf::AUSEEREV_TAGS . "').click()"]); $sv->echo_radio_table("au_seerev", $opts); echo Ht::hidden("has_tag_au_seerev", 1); // Authors' response echo '<div class="g"></div><table id="foldauresp" class="fold2o">'; $sv->echo_checkbox_row('resp_active', "<b>Collect authors’ responses to the reviews<span class='fx2'>:</span></b>", "void fold('auresp',!this.checked,2)"); echo '<tr class="fx2"><td></td><td><div id="auresparea">', Ht::hidden("has_resp_rounds", 1); // Response rounds if ($sv->use_req()) { $rrounds = array(1); for ($i = 1; isset($sv->req["resp_roundname_{$i}"]); ++$i) { $rrounds[$i] = $sv->req["resp_roundname_{$i}"]; } } else { $rrounds = $Conf->resp_round_list(); } $rrounds["n"] = ""; foreach ($rrounds as $i => $rname) { $isuf = $i ? "_{$i}" : ""; $rname_si = $sv->si("resp_roundname{$isuf}"); if (!$i) { $rname = $rname == "1" ? "none" : $rname; $rname_si->placeholder = "none"; } $sv->set_oldv("resp_roundname{$isuf}", $rname); echo '<div id="response', $isuf; if ($i) { echo '" style="padding-top:1em'; } if ($i === "n") { echo ';display:none'; } echo '"><table class="secondary-settings"><tbody>'; $sv->echo_entry_row("resp_roundname{$isuf}", "Response name"); if ($sv->curv("resp_open{$isuf}") === 1 && ($x = $sv->curv("resp_done{$isuf}"))) { $Conf->settings["resp_open{$isuf}"] = $x - 7 * 86400; } $sv->echo_entry_row("resp_open{$isuf}", "Start time"); $sv->echo_entry_row("resp_done{$isuf}", "Hard deadline"); $sv->echo_entry_row("resp_grace{$isuf}", "Grace period"); $sv->echo_entry_row("resp_words{$isuf}", "Word limit", $i ? null : "This is a soft limit: authors may submit longer responses. 0 means no limit."); echo '</tbody></table><div style="padding-top:4px">'; $sv->echo_message_minor("msg.resp_instrux{$isuf}", "Instructions"); echo '</div></div>', "\n"; } echo '</div><div style="padding-top:1em">', '<button type="button" onclick="settings_add_resp_round()">Add response round</button>', '</div></td></tr></table>'; $Conf->footerScript("fold('auresp',!\$\$('cbresp_active').checked,2)"); echo "<div class='g'></div>\n<hr class='hr' />\n", "Who can see paper <b>decisions</b> (accept/reject)?<br />\n"; $sv->echo_radio_table("seedec", array(Conf::SEEDEC_ADMIN => "Only administrators", Conf::SEEDEC_NCREV => "Reviewers and non-conflicted PC members", Conf::SEEDEC_REV => "Reviewers and <em>all</em> PC members", Conf::SEEDEC_ALL => "<b>Authors</b>, reviewers, and all PC members (and reviewers can see accepted papers’ author lists)")); echo "<div class='g'></div>\n"; echo "<table>\n"; $decs = $Conf->decision_map(); krsort($decs); // count papers per decision $decs_pcount = array(); $result = $Conf->qe("select outcome, count(*) from Paper where timeSubmitted>0 group by outcome"); while ($row = edb_row($result)) { $decs_pcount[$row[0]] = $row[1]; } // real decisions $n_real_decs = 0; foreach ($decs as $k => $v) { $n_real_decs += $k ? 1 : 0; } $caption = "<td class='lcaption' rowspan='{$n_real_decs}'>Current decision types</td>"; foreach ($decs as $k => $v) { if ($k) { if ($sv->use_req()) { $v = defval($sv->req, "dec{$k}", $v); } echo "<tr>", $caption, '<td class="lentry nw">', Ht::entry("dec{$k}", $v, array("size" => 35)), " ", $k > 0 ? "Accept class" : "Reject class", "</td>"; if (isset($decs_pcount[$k]) && $decs_pcount[$k]) { echo '<td class="lentry nw">', plural($decs_pcount[$k], "paper"), "</td>"; } echo "</tr>\n"; $caption = ""; } } // new decision $v = ""; $vclass = 1; if ($sv->use_req()) { $v = defval($sv->req, "decn", $v); $vclass = defval($sv->req, "dtypn", $vclass); } echo '<tr><td class="lcaption">', $sv->label("decn", "New decision type"), '<br /></td>', '<td class="lentry nw">', Ht::hidden("has_decisions", 1), Ht::entry("decn", $v, array("id" => "decn", "size" => 35)), ' ', Ht::select("dtypn", array(1 => "Accept class", -1 => "Reject class"), $vclass), "<br /><small>Examples: “Accepted as short paper”, “Early reject”</small>", "</td></tr>"; if ($sv->has_error("decn")) { echo '<tr><td></td><td class="lentry nw">', Ht::checkbox("decn_confirm", 1, false), ' <span class="error">', Ht::label("Confirm"), "</span></td></tr>"; } echo "</table>\n"; // Final versions echo "<h3 class=\"settings g\">Final versions</h3>\n"; echo '<table id="foldfinal" class="fold2o">'; $sv->echo_checkbox_row('final_open', '<b>Collect final versions of accepted papers<span class="fx">:</span></b>', "void fold('final',!this.checked,2)"); echo '<tr class="fx2"><td></td><td><table class="secondary-settings"><tbody>'; $sv->echo_entry_row("final_soft", "Deadline"); $sv->echo_entry_row("final_done", "Hard deadline"); $sv->echo_entry_row("final_grace", "Grace period"); echo "</tbody></table><div class='g'></div>"; $sv->echo_message_minor("msg.finalsubmit", "Instructions"); echo "<div class='g'></div>", "<small>To collect <em>multiple</em> final versions, such as one in 9pt and one in 11pt, add “Alternate final version” options via <a href='", hoturl("settings", "group=opt"), "'>Settings > Submission options</a>.</small>", "</td></tr></table>\n\n"; $Conf->footerScript("fold('final',!\$\$('cbfinal_open').checked)"); }
$revopt[htmlspecialchars($reviewer_contact->email)] = Text::name_html($Me) . " (not on PC)"; } echo Ht::select("reviewer", $revopt, htmlspecialchars($reviewer_contact->email), array("onchange" => "\$\$(\"redisplayform\").submit()")), "<div class='g'></div></td></tr>\n"; } echo "<tr><td class='lxcaption'><strong>Search:</strong></td><td class='lentry'><input type='text' size='32' name='q' value=\"", htmlspecialchars(defval($_REQUEST, "q", "")), "\" /><span class='sep'></span></td>", "<td>", Ht::submit("redisplay", "Redisplay"), "</td>", "</tr>\n"; $show_data = array(); if (!$Conf->subBlindAlways() && ($Conf->subBlindNever() || $pl->any->openau)) { $show_data[] = '<span class="sep">' . Ht::checkbox("showau", 1, strpos($pldisplay, " au ") !== false, array("disabled" => !$Conf->subBlindNever() && !$pl->any->openau, "onchange" => "plinfo('au',this)", "id" => "showau")) . " " . Ht::label("Authors") . '</span>'; } if (!$Conf->subBlindNever() && $Me->privChair) { $show_data[] = '<span class="sep' . (!$Conf->subBlindAlways() ? " fx10" : "") . '">' . Ht::checkbox("showanonau", 1, strpos($pldisplay, " anonau ") !== false, array("disabled" => !$pl->any->anonau, "onchange" => (!$Conf->subBlindAlways() ? "" : "plinfo('au',this);") . "plinfo('anonau',this)", "id" => !$Conf->subBlindAlways() ? "showanonau" : "showau")) . " " . Ht::label(!$Conf->subBlindAlways() ? "Anonymous authors" : "Authors") . '</span>'; } if (!$Conf->subBlindAlways() || $Me->privChair) { $show_data[] = '<span class="sep fx10">' . Ht::checkbox("showaufull", 1, strpos($pldisplay, " aufull ") !== false, array("onchange" => "plinfo('aufull',this)", "id" => "showaufull")) . " " . Ht::label("Full author info") . "</span>"; $Conf->footerScript("plinfo.extra=function(type,dofold){var x=(type=='au'?!dofold:(\$\$('showau')||{}).checked);fold('redisplayform',!x,10)};"); } if ($pl->any->abstract) { $show_data[] = '<span class="sep">' . Ht::checkbox("showabstract", 1, strpos($pldisplay, " abstract ") !== false, array("onchange" => "plinfo('abstract',this)")) . " " . Ht::label("Abstracts") . '</span>'; } if ($pl->any->topics) { $show_data[] = '<span class="sep">' . Ht::checkbox("showtopics", 1, strpos($pldisplay, " topics ") !== false, array("onchange" => "plinfo('topics',this)")) . " " . Ht::label("Topics") . '</span>'; } if (count($show_data) && $pl->count) { echo '<tr><td class="lxcaption"><strong>Show:</strong> ', '</td><td colspan="2" class="lentry">', join('', $show_data), '</td></tr>'; } echo "</table></div></form>"; // </div></div> echo "</td></tr></table>\n"; // main form echo Ht::form_div(hoturl_post("reviewprefs", "reviewer={$reviewer}" . (defval($_REQUEST, "q") ? "&q=" . urlencode($_REQUEST["q"]) : "")), array("class" => "assignpc", "onsubmit" => "return plist_onsubmit.call(this)", "id" => "sel")), Ht::hidden("defaultact", "", array("id" => "defaultact")), Ht::hidden_default_submit("default", 1), "<div class='pltable_full_ctr'>\n", '<noscript><div style="text-align:center">', Ht::submit("update", "Save changes"), '</div></noscript>', $pl_text, "</div></div></form>\n"; $Conf->footer();
if ($pastDeadline && $Me->privChair) { echo "<br />", Ht::checkbox("override"), " ", Ht::label("Override deadlines"); } echo "<br /><span class='hint'><strong>Tip:</strong> You may upload a file containing several forms.</span>"; echo "</div></form></td>\n"; } echo "</tr>\n"; // Ranks if ($Conf->setting("tag_rank") && $Me->is_reviewer()) { $ranktag = $Conf->setting_data("tag_rank"); echo "<tr><td><div class='g'></div></td></tr>\n", "<tr><td><h3>Download ranking file</h3>\n<div>"; echo "<a href=\"", hoturl("search", "get=rank&tag=%7E{$ranktag}&q=&t=r&p=all"), "\">Your reviews</a>"; if ($Me->isPC) { echo "<br />\n<a href=\"", hoturl("search", "get=rank&tag=%7E{$ranktag}&q=&t=s&p=all"), "\">All submitted papers</a>"; } echo "</div></td>\n"; $disabled = $pastDeadline && !$Me->privChair ? " disabled='disabled'" : ""; echo "<td><h3>Upload ranking file</h3>\n", Ht::form_div(hoturl_post("offline", "setrank=1&tag=%7E{$ranktag}")), Ht::hidden("upload", 1), "<input type='file' name='file' accept='text/plain' size='30' {$disabled}/> ", Ht::submit("Go", array("disabled" => !!$disabled)); if ($pastDeadline && $Me->privChair) { echo "<br />", Ht::checkbox("override"), " ", Ht::label("Override deadlines"); } echo "<br /><span class='hint'><strong>Tip:</strong> Use “<a href='", hoturl("search", "q=" . urlencode("editsort:#~{$ranktag}")), "'>editsort:#~{$ranktag}</a>” to drag and drop your ranking.</span>"; echo "<br /><span class='hint'><strong>Tip:</strong> “<a href='", hoturl("search", "q=order:%7E{$ranktag}"), "'>order:~{$ranktag}</a>” searches by your ranking.</span>"; echo "</div></form></td>\n"; echo "</tr>\n"; } echo "</table>\n"; if ($text = $rf->webGuidanceRows($Me->permissive_view_score_bound())) { echo "<div class='g'></div>\n\n<table class='review'>\n<thead><tr class='id'><td></td><td class='entry'><h3>Review form information</h3></td></tr></thead>\n<tbody>", $text, "<tr class='last'>\n <td class='caption'></td>\n <td class='entry'></td>\n</tr></tbody></table>\n"; } $Conf->footer();