예제 #1
1
 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> &nbsp;' . Ht::entry("tag", $qreq->tag, ["size" => 15, "onfocus" => "autosub('tag',this)", "class" => "wantcrpfocus"]) . ' &nbsp;' . 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")) . "&nbsp;" . Ht::label("Gapless order") . "</div>" . "<div style='margin:2px 0'>Using: &nbsp;" . Ht::select("tagcr_method", PaperRank::methods(), $qreq->tagcr_method) . "</div>" . "<div style='margin:2px 0'>Source tag: &nbsp;~" . Ht::entry("tagcr_source", $qreq->tagcr_source, array("size" => 15)) . "</div></div>";
     }
     $actions[] = [500, "tag", "Tag", "<b>:</b> &nbsp;" . Ht::select("tagfn", $tagopt, $qreq->tagfn, $tagextra) . " &nbsp;", ["id" => "foldplacttags", "class" => "foldc fold99c", "content" => $t]];
 }
예제 #2
0
 function list_actions(Contact $user, $qreq, PaperList $pl, &$actions)
 {
     global $Conf;
     Ht::stash_script("plactions_dofold()", "plactions_dofold");
     $Conf->stash_hotcrp_pc($user);
     $actions[] = [700, "assign", "Assign", "<b>:</b> &nbsp;" . Ht::select("assignfn", array("auto" => "Automatic assignments", "zzz1" => null, "conflict" => "Conflict", "unconflict" => "No conflict", "zzz2" => null, "assign" . REVIEW_PRIMARY => "Primary review", "assign" . REVIEW_SECONDARY => "Secondary review", "assign" . REVIEW_PC => "Optional review", "assign0" => "Clear review", "zzz3" => null, "lead" => "Discussion lead", "shepherd" => "Shepherd"), $qreq->assignfn, ["class" => "wantcrpfocus", "onchange" => "plactions_dofold()"]) . '<span class="fx"> &nbsp;<span id="atab_assign_for">for</span> &nbsp;' . Ht::select("markpc", [], 0, ["id" => "markpc", "class" => "need-pcselector", "data-pcselector-selected" => $qreq->markpc]) . "</span> &nbsp;" . Ht::submit("fn", "Go", ["value" => "assign", "onclick" => "return plist_submit.call(this)"])];
 }
예제 #3
0
파일: pset.php 프로젝트: kohler/peteramati
function echo_grade_cdf()
{
    global $Conf, $Info, $Pset, $User, $Me;
    $sepx = $User->extension && $Pset->separate_extension_grades;
    $xmark = $sepx ? "extension " : "";
    echo '<div id="gradecdf61" style="float:right;position:relative">', '<table class="gradecdf61table"><tbody><tr>', '<td class="yaxislabelcontainer"></td>', '<td class="plot"><div style="width:300px;height:200px"></div></td>', '</tr><tr><td></td><td class="xaxislabelcontainer"></td></tr>', '</tbody></table>', '<table class="gradecdf61summary', $sepx ? " extension" : " all", '"><tbody>', '<tr class="gradecdf61mean"><td class="cap">', $xmark, ' mean</td><td class="val"></td></tr>', '<tr class="gradecdf61median"><td class="cap">', $xmark, ' median</td><td class="val"></td></tr>', '<tr class="gradecdf61stddev"><td class="cap">', $xmark, ' stddev</td><td class="val"></td></tr>', '</tbody></table>', '</div>';
    Ht::stash_script("gradecdf61(" . json_encode($Info->hoturl("pset", ["gradecdf" => 1])) . ")");
}
예제 #4
0
<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">&nbsp;Mute</span>';
//echo '<span class="hidden fhx_ib">&nbsp;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()")), "&nbsp;", 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>
<tr><td class="lcaption nw">Conflicts only</td>
예제 #5
0
    $Sv->report();
}
$Conf->header("Settings &nbsp;&#x2215;&nbsp; <strong>" . SettingGroup::$all[$Group]->description . "</strong>", "settings", actionBar());
$Conf->echoScript("");
// clear out other script references
echo $Conf->make_script_file("scripts/settings.js"), "\n";
echo Ht::form(hoturl_post("settings", "group={$Group}"), array("id" => "settingsform"));
echo '<div class="leftmenu_menucontainer"><div class="leftmenu_list">';
foreach (SettingGroup::all() as $g) {
    if ($g->name === $Group) {
        echo '<div class="leftmenu_item_on">', $g->description, '</div>';
    } else {
        echo '<div class="leftmenu_item">', '<a href="', hoturl("settings", "group={$g->name}"), '">', $g->description, '</a></div>';
    }
}
echo "</div></div>\n", '<div class="leftmenu_content_container"><div class="leftmenu_content">', '<div class="leftmenu_body">';
Ht::stash_script("jQuery(\".leftmenu_item\").click(divclick)");
function doActionArea($top)
{
    echo "<div class='aa'>", Ht::submit("update", "Save changes", array("class" => "bb")), " &nbsp;", Ht::submit("cancel", "Cancel"), "</div>";
}
echo "<div class='aahc'>";
doActionArea(true);
echo "<div>";
$Sv->interesting_groups[$Group] = true;
SettingGroup::$all[$Group]->render($Sv);
echo "</div>";
doActionArea(false);
echo "</div></div></div></div></form>\n";
$Conf->footerScript("hiliter_children('#settingsform');jQuery('textarea').autogrow()");
$Conf->footer();
예제 #6
0
파일: mail.php 프로젝트: kohler/peteramati
if (!isset($_REQUEST["template"]) || !isset($tmpl[$_REQUEST["template"]])) {
    $_REQUEST["template"] = "genericmailtool";
}
echo Ht::select("template", $tmpl, $_REQUEST["template"], array("onchange" => "highlightUpdate(\"loadtmpl\")")), " &nbsp;", Ht::submit("loadtmpl", "Load", array("id" => "loadtmpl")), " &nbsp;\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)")), "&nbsp;</td><td>", Ht::label("Choose individual papers", "plimit");
echo "<span class='fx8'>:</span><br /><div class='fx8'>";
$q = defval($_REQUEST, "q", "(All)");
echo "Search&nbsp; ", Ht::entry("q", @$_REQUEST["q"], array("id" => "q", "hottemptext" => "(All)", "class" => "hotcrp_searchbox", "size" => 36, "title" => "Enter paper numbers or search terms")), " &nbsp;in &nbsp;", 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";
        }
    }
}
// ** SUBJECT
echo "  <tr><td class='mhnp'>Subject:</td><td class='mhdp'>", "<tt>[", htmlspecialchars($Opt["shortName"]), "]&nbsp;</tt><input type='text' class='textlite-tt' name='subject' value=\"", htmlspecialchars($_REQUEST["subject"]), "\" size='64' /></td></tr>\n\n <tr><td></td><td class='mhb'>\n  <textarea class='tt' rows='20' name='emailBody' cols='80'>", htmlspecialchars($_REQUEST["emailBody"]), "</textarea>\n </td></tr>\n</table></div>\n\n";
if ($Me->privChair) {
    $result = $Conf->qe("select * from MailLog order by mailId desc limit 18");
    if (edb_nrows($result)) {
예제 #7
0
 public static function color_classes($tags, $color_type_bit = 1)
 {
     if (is_array($tags)) {
         $tags = join(" ", $tags);
     }
     if (!$tags || $tags === " ") {
         return "";
     }
     if (!preg_match_all(self::color_regex(), $tags, $m)) {
         return false;
     }
     $dt = self::defined_tags();
     $classes = array();
     foreach ($m[1] as $tag) {
         if (($t = $dt->check($tag)) && $t->colors) {
             foreach ($t->colors as $k) {
                 $classes[] = $k . "tag";
             }
         } else {
             $classes[] = self::canonical_color($tag) . "tag";
         }
     }
     if ($color_type_bit > 1) {
         $classes = array_filter($classes, "TagInfo::classes_have_colors");
     }
     if (count($classes) > 1) {
         sort($classes);
         $classes = array_unique($classes);
     }
     $key = join(" ", $classes);
     // This seems out of place---it's redundant if we're going to
     // generate JSON, for example---but it is convenient.
     if (count($classes) > 1) {
         $m = (int) get(self::$multicolor_map, $key);
         if (!($m & $color_type_bit)) {
             if ($color_type_bit == 1) {
                 Ht::stash_script("make_pattern_fill(" . json_encode($key) . ")");
             }
             self::$multicolor_map[$key] = $m | $color_type_bit;
         }
     }
     return $key;
 }
예제 #8
0
                $capmgr->delete($capdata);
                $Conf->save_session("password_reset", (object) array("time" => $Now, "email" => $Acct->email, "password" => $_POST["password"]));
                go(hoturl("index"));
            }
        }
    }
    $password_class = " error";
}
$Conf->header("Reset password", "resetpassword", null);
if (!isset($_POST["autopassword"]) || trim($_POST["autopassword"]) != $_POST["autopassword"] || strlen($_POST["autopassword"]) < 16 || !preg_match("/\\A[-0-9A-Za-z@_+=]*\\z/", $_POST["autopassword"])) {
    $_POST["autopassword"] = Contact::random_password();
}
echo "<div class='homegrp'>\nWelcome to the ", htmlspecialchars($Conf->full_name()), " submissions site.";
if (opt("conferenceSite")) {
    echo " For general information about ", htmlspecialchars($Conf->short_name), ", see <a href=\"", htmlspecialchars(opt("conferenceSite")), "\">the conference site</a>.";
}
echo "</div>\n<hr class='home' />\n<div class='homegrp' id='homereset'>\n", Ht::form(hoturl_post("resetpassword")), '<div class="f-contain">', Ht::hidden("resetcap", $resetcap), Ht::hidden("autopassword", $_POST["autopassword"]), "<p>Use this form to reset your password. You may want to use the random password we’ve chosen.</p>";
echo '<table style="margin-bottom:2em">', '<tr><td class="lcaption">Your email</td><td>', htmlspecialchars($Acct->email), '</td></tr>
<tr><td class="lcaption">Suggested password</td><td>', htmlspecialchars($_POST["autopassword"]), '</td></tr></table>';
echo '<div class="f-i">
  <div class="f-c', $password_class, '">New password</div>
  <div class="f-e">', Ht::password("password", "", array("id" => "login_d", "tabindex" => 1, "size" => 36)), '</div>
</div>
<div class="f-i">
  <div class="f-c', $password_class, '">New password (again)</div>
  <div class="f-e">', Ht::password("password2", "", array("tabindex" => 1, "size" => 36)), '</div>
</div>
<div class="f-i" style="margin-top:2em">', Ht::submit("go", "Reset password", array("tabindex" => 1)), "</div>\n</div></form>\n<hr class='home' /></div>\n";
Ht::stash_script("crpfocus(\"login\", null, 2)");
echo '<hr class="c" />', "\n";
$Conf->footer();
예제 #9
0
 private function _analyze_folds($rstate, $fieldDef)
 {
     global $Conf;
     $classes = $jsmap = $jscol = array();
     $has_sel = false;
     $ord = 0;
     foreach ($fieldDef as $fdef) {
         $j = ["name" => $fdef->name, "title" => $this->_field_title($fdef, $ord)];
         if ($fdef->className != "pl_" . $fdef->name) {
             $j["className"] = $fdef->className;
         }
         if ($fdef->view == Column::VIEW_COLUMN) {
             $j["column"] = true;
             ++$ord;
         }
         if ($fdef->is_folded && $fdef->has_content) {
             $j["loadable"] = true;
         }
         if ($fdef->is_folded && $fdef->name !== "authors") {
             $j["missing"] = true;
         }
         if ($fdef->foldable) {
             $j["foldnum"] = $fdef->foldable;
         }
         $fdef->annotate_field_js($this, $j);
         $jscol[] = $j;
         if ($fdef->foldable && $fdef->name !== "authors") {
             $classes[] = "fold{$fdef->foldable}" . ($fdef->is_folded ? "c" : "o");
             $jsmap[] = "\"{$fdef->name}\":{$fdef->foldable}";
         }
         if (isset($fdef->is_selector)) {
             $has_sel = true;
         }
     }
     // authorship requires special handling
     if ($rstate->has_openau || $rstate->has_anonau) {
         $classes[] = "fold1" . ($this->is_folded("au") ? "c" : "o");
         $jsmap[] = "\"au\":1,\"aufull\":4";
     }
     if ($rstate->has_anonau) {
         $classes[] = "fold2" . ($this->is_folded("anonau") ? "c" : "o");
         $jsmap[] = "\"anonau\":2";
     }
     // total folding, row number folding
     if ($rstate->row_folded) {
         $classes[] = "fold3c";
     }
     if ($has_sel) {
         $jsmap[] = "\"rownum\":6";
         $classes[] = "fold6" . ($this->is_folded("rownum") ? "c" : "o");
     }
     if ($this->contact->privChair) {
         $jsmap[] = "\"force\":5";
         $classes[] = "fold5" . ($this->qreq->forceShow ? "o" : "c");
     }
     if ($this->viewmap->table_id) {
         if (!empty($jsmap)) {
             Ht::stash_script("foldmap.pl={" . join(",", $jsmap) . "};");
         }
         $args = array();
         if ($this->search->q) {
             $args["q"] = $this->search->q;
         }
         if ($this->search->qt) {
             $args["qt"] = $this->search->qt;
         }
         $args["t"] = $this->search->limitName;
         $args["pap"] = join(" ", $rstate->ids);
         Ht::stash_script("plinfo.needload(" . json_encode($args) . ");" . "plinfo.set_fields(" . json_encode($jscol) . ");");
     }
     return $classes;
 }
예제 #10
0
 public function stash_hotcrp_pc(Contact $user)
 {
     if (!Ht::mark_stash("hotcrp_pc")) {
         return;
     }
     $sortbylast = opt("sortByLastName");
     $hpcj = $list = [];
     foreach (pcMembers() as $pcm) {
         $hpcj[$pcm->contactId] = $j = (object) ["name" => $user->name_html_for($pcm), "email" => $pcm->email];
         if ($color_classes = $user->reviewer_color_classes_for($pcm)) {
             $j->color_classes = $color_classes;
         }
         if ($sortbylast && $pcm->lastName) {
             $r = Text::analyze_name($pcm);
             if (strlen($r->lastName) !== strlen($r->name)) {
                 $j->lastpos = strlen(htmlspecialchars($r->firstName)) + 1;
             }
             if ($r->nameAmbiguous && $r->name && $r->email) {
                 $j->emailpos = strlen(htmlspecialchars($r->name)) + 1;
             }
         }
         $list[] = $pcm->contactId;
     }
     $hpcj["__order__"] = $list;
     if ($sortbylast) {
         $hpcj["__sort__"] = "last";
     }
     Ht::stash_script("hotcrp_pc=" . json_encode($hpcj) . ";");
 }
예제 #11
0
 function show($prow, $rrows, $rrow, &$options)
 {
     global $Conf, $Opt, $Me, $useRequest;
     if (!$options) {
         $options = array();
     }
     $editmode = defval($options, "edit", false);
     $reviewOrdinal = unparseReviewOrdinal($rrow);
     self::check_review_author_seen($prow, $rrow, $Me);
     if (!$editmode) {
         $rj = $this->unparse_review_json($prow, $rrow, $Me);
         if (get($options, "editmessage")) {
             $rj->message_html = $options["editmessage"];
         }
         $Conf->echoScript("review_form.add_review(" . json_encode($rj) . ");\n");
         return;
     }
     // From here on, edit mode.
     $forceShow = $Me->is_admin_force() ? "&amp;forceShow=1" : "";
     $reviewLinkArgs = "p={$prow->paperId}" . ($rrow ? "&amp;r={$reviewOrdinal}" : "") . "&amp;m=re" . $forceShow;
     $reviewPostLink = hoturl_post("review", $reviewLinkArgs);
     $reviewDownloadLink = hoturl("review", $reviewLinkArgs . "&amp;downloadForm=1" . $forceShow);
     echo Ht::form($reviewPostLink, array("class" => "revcard")), '<div class="aahc">', Ht::hidden_default_submit("default", "");
     if ($rrow) {
         echo Ht::hidden("version", defval($rrow, "reviewEditVersion", 0) + 1);
     }
     echo '<div class="revcard" id="r', $reviewOrdinal, '"><div class="revcard_head">';
     // Links
     if ($rrow) {
         echo '<div class="floatright"><a href="' . hoturl("review", "r={$reviewOrdinal}&amp;text=1" . $forceShow) . '" class="xx">', Ht::img("txt.png", "[Text]", "b"), "&nbsp;<u>Plain text</u></a>", "</div>";
     }
     echo "<h3>";
     if ($rrow) {
         echo '<a href="', hoturl("review", "r={$reviewOrdinal}" . $forceShow), '" class="q">Edit Review';
         if ($rrow->reviewSubmitted) {
             echo "&nbsp;#", $reviewOrdinal;
         }
         echo "</a>";
     } else {
         echo "Write Review";
     }
     echo "</h3>\n";
     $open = $sep = " <span class='revinfo'>";
     $xsep = " <span class='barsep'>·</span> ";
     $showtoken = $rrow && $Me->review_token_cid($prow, $rrow);
     $type = "";
     if ($rrow && $Me->can_view_review_round($prow, $rrow, null)) {
         $type = review_type_icon($rrow->reviewType);
         if ($rrow->reviewRound > 0 && $Me->can_view_review_round($prow, $rrow, null)) {
             $type .= "&nbsp;<span class=\"revround\" title=\"Review round\">" . htmlspecialchars($Conf->round_name($rrow->reviewRound, true)) . "</span>";
         }
     }
     if ($rrow && $Me->can_view_review_identity($prow, $rrow, null) && (!$showtoken || !Contact::is_anonymous_email($rrow->email))) {
         echo $sep, $rrow->reviewBlind ? "[" : "", Text::user_html($rrow), $rrow->reviewBlind ? "]" : "", " &nbsp;", $type;
         $sep = $xsep;
     } else {
         if ($type) {
             echo $sep, $type;
             $sep = $xsep;
         }
     }
     if ($showtoken) {
         echo $sep, "Review token ", encode_token((int) $rrow->reviewToken);
         $sep = $xsep;
     }
     if ($rrow && $rrow->reviewModified > 0 && $Me->can_view_review_time($prow, $rrow)) {
         echo $sep, "Updated ", $Conf->printableTime($rrow->reviewModified);
         $sep = $xsep;
     }
     if ($sep != $open) {
         echo "</span>\n";
     }
     if (defval($options, "editmessage")) {
         echo "<div class='hint'>", defval($options, "editmessage"), "</div>\n";
     }
     // download?
     echo '<hr class="c" />';
     echo "<table class='revoff'><tr>\n      <td><strong>Offline reviewing</strong> &nbsp;</td>\n      <td>Upload form: &nbsp; <input type='file' name='uploadedFile' accept='text/plain' size='30' />\n      &nbsp; ", Ht::submit("uploadForm", "Go"), "</td>\n    </tr><tr>\n      <td></td>\n      <td><a href='{$reviewDownloadLink}'>Download form</a>\n      <span class='barsep'>·</span>\n      <span class='hint'><strong>Tip:</strong> Use <a href='", hoturl("search"), "'>Search</a> or <a href='", hoturl("offline"), "'>Offline reviewing</a> to download or upload many forms at once.</span></td>\n    </tr></table></div>\n";
     // ready?
     $ready = $useRequest ? defval($_REQUEST, "ready") : !($rrow && $rrow->reviewModified && !$rrow->reviewSubmitted);
     // review card
     echo '<div class="revcard_body">';
     // administrator?
     $admin = $Me->allow_administer($prow);
     if ($rrow && !$Me->is_my_review($rrow) && $admin) {
         echo Ht::xmsg("info", "This isn’t your review, but as an administrator you can still make changes.");
     }
     // delegate?
     if ($rrow && !$rrow->reviewSubmitted && $rrow->contactId == $Me->contactId && $rrow->reviewType == REVIEW_SECONDARY) {
         $ndelegated = 0;
         foreach ($rrows as $rr) {
             if ($rr->reviewType == REVIEW_EXTERNAL && $rr->requestedBy == $rrow->contactId) {
                 $ndelegated++;
             }
         }
         if ($ndelegated == 0) {
             $t = "As a secondary reviewer, you can <a href=\"" . hoturl("assign", "p={$rrow->paperId}") . "\">delegate this review to an external reviewer</a>, but if your external reviewer declines to review the paper, you should complete this review yourself.";
         } else {
             if ($rrow->reviewNeedsSubmit == 0) {
                 $t = "A delegated external reviewer has submitted their review, but you can still complete your own if you’d like.";
             } else {
                 $t = "Your delegated external reviewer has not yet submitted a review.  If they do not, you should complete this review yourself.";
             }
         }
         echo Ht::xmsg("info", $t);
     }
     // top save changes
     if ($Me->timeReview($prow, $rrow) || $admin) {
         $buttons = $this->_review_buttons($prow, $rrow, "top", $reviewPostLink);
         echo Ht::actions($buttons, array("class" => "aab", "style" => "margin-top:0"));
     }
     // blind?
     if ($Conf->review_blindness() == Conf::BLIND_OPTIONAL) {
         echo '<div class="revet"><span class="revfn">', Ht::checkbox_h("blind", 1, $useRequest ? defval($_REQUEST, 'blind') : !$rrow || $rrow->reviewBlind), "&nbsp;", Ht::label("Anonymous review"), "</span><hr class=\"c\" /></div>\n", '<div class="revhint">', htmlspecialchars(Conf::$gShortName), " allows either anonymous or open review.  Check this box to submit your review anonymously (the authors won’t know who wrote the review).</div>\n", '<div class="g"></div>', "\n";
     }
     // form body
     $this->webFormRows($Me, $prow, $rrow, $useRequest);
     // review actions
     if ($Me->timeReview($prow, $rrow) || $admin) {
         $buttons = $this->_review_buttons($prow, $rrow, "bottom", $reviewPostLink);
         echo Ht::actions($buttons, array("class" => "aab", "style" => "margin-bottom:0"));
         if ($rrow && $rrow->reviewSubmitted && !$admin) {
             echo '<div class="hint">Only administrators can remove or unsubmit the review at this point.</div>';
         }
     }
     echo "</div></div></div></form>\n\n";
     Ht::stash_script('hiliter_children("form.revcard")', "form_revcard");
 }
예제 #12
0
 static function echo_repo_last_commit_group($info, $commitgroup)
 {
     global $Me, $Conf;
     list($user, $repo) = array($info->user, $info->repo);
     if ($info->pset->gitless) {
         return;
     }
     if ($repo && !$info->user_can_view_repo_contents) {
         $value = "(unconfirmed repository)";
     } else {
         if ($repo && $repo->snaphash) {
             $value = substr($repo->snaphash, 0, 7) . " " . htmlspecialchars($repo->snapcommitline);
         } else {
             if ($repo) {
                 $value = "(checking)";
             } else {
                 $value = "(no repo yet)";
             }
         }
     }
     $notes = array();
     if ($repo && $repo->snapat && $info->can_view_repo_contents) {
         $n = "committed " . ago($repo->snapcommitat) . ", fetched " . ago($repo->snapat) . ", last checked " . ago($repo->snapcheckat);
         if ($Me->privChair) {
             $n .= " <small style=\"padding-left:1em;font-size:70%\">group " . $repo->cacheid . ", repo" . $repo->repoid . "</small>";
         }
         $notes[] = $n;
     }
     if ($repo && !$info->user_can_view_repo_contents) {
         if ($user->is_anonymous) {
             $notes[] = array(true, "ERROR: The user hasn’t confirmed that they can view this repository.");
         } else {
             $uname = Text::analyze_name($user);
             if ($uname->name && $uname->email) {
                 $uname = "{$uname->name} <{$uname->email}>";
             } else {
                 if ($uname->email) {
                     $uname = "Your Name <{$uname->email}>";
                 } else {
                     if ($uname->name) {
                         $uname = "{$uname->name} <*****@*****.**>";
                     } else {
                         $uname = "Your Name <*****@*****.**>";
                     }
                 }
             }
             $notes[] = array(true, "ERROR: We haven’t confirmed that you can view this repository.<br>\n    We only let you view repositories that you’ve committed to.<br>\n    Fix this error by making a commit from your email address, " . htmlspecialchars($user->email) . ", and pushing that commit to the repository.<br>\n    For example, try these commands: <pre>git commit --allow-empty --author=" . htmlspecialchars(escapeshellarg($uname)) . " \\\n        -m \"Confirm repository\" &amp;&amp; git push</pre>");
         }
         $commitgroup = true;
     }
     if ($commitgroup) {
         echo "<div class=\"commitcontainer61\" data-pa-pset=\"", htmlspecialchars($info->pset->urlkey);
         if ($repo && $repo->snaphash && $info->can_view_repo_contents) {
             echo "\" data-pa-commit=\"", $repo->snaphash;
         }
         echo "\">";
         Ht::stash_script("checklatest61()", "checklatest61");
     }
     self::echo_group("last commit", $value, $notes);
     if ($commitgroup) {
         echo "</div>";
     }
 }
예제 #13
0
 function header($title, $id = "", $actionBar = null, $showTitle = true)
 {
     global $ConfSitePATH, $Me, $Now;
     if ($this->headerPrinted) {
         return;
     }
     // <head>
     if ($title === "Home") {
         $title = "";
     }
     $this->header_head($title);
     // <body>
     echo "<body", $id ? " id=\"{$id}\"" : "", " onload=\"hotcrp_load()\">\n";
     // initial load (JS's timezone offsets are negative of PHP's)
     Ht::stash_script("hotcrp_load.time(" . -date("Z", $Now) / 60 . "," . ($this->opt("time24hour") ? 1 : 0) . ")");
     echo "<div id='prebody'>\n";
     echo "<div id='header'>\n<div id='header_left_conf'><h1>";
     if ($title && $showTitle && ($title == "Home" || $title == "Sign in")) {
         echo "<a name='' class='qq' href='", hoturl("index"), "' title='Home'>", htmlspecialchars($this->short_name), "</a>";
     } else {
         echo "<a name='' class='uu' href='", hoturl("index"), "' title='Home'>", htmlspecialchars($this->short_name), "</a></h1></div><div id='header_left_page'><h1>", $title;
     }
     echo "</h1></div><div id='header_right'>";
     if ($Me && !$Me->is_empty()) {
         // profile link
         $profile_parts = [];
         if ($Me->has_email() && !$Me->disabled) {
             $profile_parts[] = '<strong>' . htmlspecialchars($Me->email) . '</strong>';
             /*echo '<a class="q" href="', hoturl("profile"), '"><strong>',
               htmlspecialchars($Me->email),
               '</strong></a> &nbsp; <a href="', hoturl("profile"), '">Profile</a>',
               $xsep;*/
         }
         // "act as" link
         if (($actas = get($_SESSION, "last_actas")) && get($_SESSION, "trueuser") && ($Me->privChair || Contact::$trueuser_privChair === $Me)) {
             // Link becomes true user if not currently chair.
             if (!$Me->privChair || strcasecmp($Me->email, $actas) == 0) {
                 $actas = $_SESSION["trueuser"]->email;
             }
             if (strcasecmp($Me->email, $actas) != 0) {
                 $profile_parts[] = "<a href=\"" . self_href(["actas" => $actas]) . "\">" . ($Me->privChair ? htmlspecialchars($actas) : "Admin") . "&nbsp;" . Ht::img("viewas.png", "Act as " . htmlspecialchars($actas)) . "</a>";
             }
         }
         // help, sign out
         $x = $id == "search" ? "t={$id}" : ($id == "settings" ? "t=chair" : "");
         if (!$Me->has_email() && !isset($this->opt["httpAuthLogin"])) {
             $profile_parts[] = '<a href="' . hoturl("index", "signin=1") . '">Sign&nbsp;in</a>';
         }
         if (!$Me->is_empty() || isset($this->opt["httpAuthLogin"])) {
             $profile_parts[] = '<a href="' . hoturl_post("index", "signout=1") . '">Sign&nbsp;out</a>';
         }
         if (!empty($profile_parts)) {
             echo join(' <span class="barsep">·</span> ', $profile_parts);
         }
     }
     echo '<div id="maindeadline" style="display:none"></div></div>', "\n";
     echo "  <hr class=\"c\" />\n";
     echo $actionBar;
     echo "</div>\n<div id=\"initialmsgs\">\n";
     if ($x = $this->opt("maintenance")) {
         echo "<div class=\"merror\"><strong>The site is down for maintenance.</strong> ", is_string($x) ? $x : "Please check back later.", "</div>";
     }
     $this->save_messages = false;
     if (($msgs = $this->session("msgs")) && count($msgs)) {
         $this->save_session("msgs", null);
         foreach ($msgs as $m) {
             $this->msg($m[0], $m[1]);
         }
         echo "<div id=\"initialmsgspacer\"></div>";
     }
     echo "</div>\n";
     $this->headerPrinted = true;
     echo "</div>\n<div class='body'>\n";
 }
예제 #14
0
 function footerScript($script, $uniqueid = null)
 {
     Ht::stash_script($script, $uniqueid);
 }
예제 #15
0
파일: home.php 프로젝트: kohler/peteramati
    $result = Dbl::qe("select cn.*, rg.gradercid main_gradercid, rg.gradehash\n        from CommitNotes cn\n        left join RepositoryGrade rg on (rg.repoid=cn.repoid and rg.pset=cn.pset)\n        where hasactiveflags=1");
    if (edb_nrows($result)) {
        echo $sep;
        show_regrades($result);
        if ($Profile) {
            echo "<div>Δt ", sprintf("%.06f", microtime(true) - $t0), "</div>";
        }
        $sep = "<hr />\n";
    }
    $pctable = [];
    foreach (pcMembers() as $pc) {
        if ($pc->firstName && !$pc->firstNameAmbiguous) {
            $pctable[$pc->contactId] = $pc->firstName;
        } else {
            $pctable[$pc->contactId] = Text::name_text($pc);
        }
    }
    Ht::stash_script('peteramati_grader_map=' . json_encode($pctable) . ';');
    foreach (ContactView::pset_list($Me, true) as $pset) {
        echo $sep;
        show_pset_table($pset, $Me);
        $sep = "<hr />\n";
    }
    Ht::stash_script("\$('.s61check').click(click_s61check)");
    if ($LastPsetFix) {
        $Conf->log("Repository.lastpset links are bogus", $Me);
        Contact::update_all_repo_lastpset();
    }
}
echo "<div class='clear'></div>\n";
$Conf->footer();
예제 #16
0
 function echo_editable_html(PaperOptionValue $ov, $reqv, PaperTable $pt)
 {
     $reqv = !!($reqv === null ? $ov->value : $reqv);
     $pt->echo_editable_option_papt($this, Ht::checkbox_h("opt{$this->id}", 1, $reqv) . "&nbsp;" . Ht::label(htmlspecialchars($this->name)));
     echo "</div>\n\n";
     Ht::stash_script("jQuery('#opt{$this->id}_div').click(function(e){if(e.target==this)jQuery(this).find('input').click();})");
 }
예제 #17
0
function goPaperForm($baseUrl = null, $args = array())
{
    global $Conf, $Me, $CurrentList;
    if ($Me->is_empty()) {
        return "";
    }
    if ($baseUrl === null) {
        $baseUrl = $Me->isPC && $Conf->setting("rev_open") ? "review" : "paper";
    }
    $x = "<form class='gopaper' action='" . hoturl($baseUrl) . "' method='get' accept-charset='UTF-8'><div class='inform'>";
    $x .= "<input id='quicksearchq' class='textlite temptext' type='text' size='10' name='p' value='(All)' title='Enter paper numbers or search terms' />";
    Ht::stash_script("mktemptext('quicksearchq','(All)')");
    foreach ($args as $what => $val) {
        $x .= "<input type='hidden' name=\"" . htmlspecialchars($what) . "\" value=\"" . htmlspecialchars($val) . "\" />";
    }
    if (isset($CurrentList) && $CurrentList > 0) {
        $x .= "<input type='hidden' name='ls' value='{$CurrentList}' />";
    }
    $x .= "&nbsp; <input class='b' type='submit' value='Search' /></div></form>";
    return $x;
}
예제 #18
0
 function echo_file_diff($file, DiffInfo $dinfo, LinenotesOrder $lnorder, $open)
 {
     $fileid = html_id_encode($file);
     $tabid = "file61_" . $fileid;
     $linenotes = $lnorder->file($file);
     echo '<h3><a class="fold61" href="#" onclick="return fold61(', "'#{$tabid}'", ',this)"><span class="foldarrow">', $open ? "&#x25BC;" : "&#x25B6;", "</span>&nbsp;", htmlspecialchars($file), "</a>";
     if (!$dinfo->removed) {
         $rawfile = $file;
         if ($this->repo->truncated_psetdir($this->pset) && str_starts_with($rawfile, $this->pset->directory_slash)) {
             $rawfile = substr($rawfile, strlen($this->pset->directory_slash));
         }
         echo '<a style="display:inline-block;margin-left:2em;font-weight:normal" href="', $this->hoturl("raw", ["file" => $rawfile]), '">[Raw]</a>';
     }
     echo '</h3>';
     echo '<table id="', $tabid, '" class="code61 diff61 filediff61';
     if ($this->pc_view) {
         echo " live";
     }
     if (!$this->user_can_see_grades) {
         echo " hidegrade61";
     }
     if (!$open) {
         echo '" style="display:none';
     }
     echo '" data-pa-file="', htmlspecialchars($file), '" data-pa-fileid="', $fileid, "\"><tbody>\n";
     if ($this->pc_view) {
         Ht::stash_script("jQuery('#{$tabid}').mousedown(linenote61).mouseup(linenote61)");
     }
     foreach ($dinfo->diff as $l) {
         if ($l[0] == "@") {
             $x = array(" gx", "difflctx61", "", "", $l[3]);
         } else {
             if ($l[0] == " ") {
                 $x = array(" gc", "difflc61", $l[1], $l[2], $l[3]);
             } else {
                 if ($l[0] == "-") {
                     $x = array(" gd", "difflc61", $l[1], "", $l[3]);
                 } else {
                     $x = array(" gi", "difflc61", "", $l[2], $l[3]);
                 }
             }
         }
         $aln = $x[2] ? "a" . $x[2] : "";
         $bln = $x[3] ? "b" . $x[3] : "";
         $ak = $bk = "";
         if ($linenotes && $aln && isset($linenotes->{$aln})) {
             $ak = ' id="L' . $aln . '_' . $fileid . '"';
         }
         if ($bln) {
             $bk = ' id="L' . $bln . '_' . $fileid . '"';
         }
         if (!$x[2] && !$x[3]) {
             $x[2] = $x[3] = "...";
         }
         echo '<tr class="diffl61', $x[0], '">', '<td class="difflna61"', $ak, '>', $x[2], '</td>', '<td class="difflnb61"', $bk, '>', $x[3], '</td>', '<td class="', $x[1], '">', diff_line_code($x[4]), "</td></tr>\n";
         if ($linenotes && $bln && isset($linenotes->{$bln})) {
             $this->echo_linenote($file, $bln, $linenotes->{$bln}, $lnorder);
         }
         if ($linenotes && $aln && isset($linenotes->{$aln})) {
             $this->echo_linenote($file, $aln, $linenotes->{$aln}, $lnorder);
         }
     }
     echo "</tbody></table>\n";
 }
예제 #19
0
파일: run.php 프로젝트: kohler/peteramati
        } else {
            if ($Runner->disabled) {
                quit("Command disabled");
            } else {
                quit("Can’t run command right now");
            }
        }
    }
}
// magic multi-runner
if ($Me->isPC && get($_GET, "runmany") && check_post()) {
    $Conf->header(htmlspecialchars($Pset->title . " " . $Runner->title), "home");
    echo '<h2 id="runmany61_who"></h2>', Ht::form(hoturl_post("run")), '<div class="f-contain">', Ht::hidden("u", ""), Ht::hidden("pset", $Pset->urlkey), Ht::hidden("run", $Runner->name, ["id" => "runmany61", "data-pa-runclass" => $Runner->runclass_argument()]), '</div></form>';
    echo '<div id="run61out_' . $Runner->runclass . '">', '<div class="run61" id="run61_' . $Runner->runclass . '">', '<div class="run61in"><pre class="run61pre"></pre></div>', '</div>', '</div>';
    echo '<div id="runmany61_users">', htmlspecialchars($_GET["runmany"]), '</div>';
    Ht::stash_script('runmany61()');
    echo '<div class="clear"></div>', "\n";
    $Conf->footer();
    exit;
}
// repo
$Info = user_pset_info();
$Repo = $Info->repo;
$RecentCommits = $Info->recent_commits();
// can we run this?
if (!$Repo) {
    quit("No repository to run");
} else {
    if (!$Info->commit()) {
        quit("No commit to run");
    } else {
예제 #20
0
파일: diff.php 프로젝트: kohler/peteramati
$lnorder = new LinenotesOrder($all_linenotes, $Info->can_see_grades);
$lnorder->set_diff($diff);
// print line notes
$notelinks = array();
foreach ($lnorder->seq() as $fl) {
    $f = str_starts_with($fl[0], $Pset->directory_slash) ? substr($fl[0], strlen($Pset->directory_slash)) : $fl[0];
    $notelinks[] = '<a href="#L' . $fl[1] . '_' . html_id_encode($fl[0]) . '" onclick="return gotoline61(this)" class="noteref61' . (!$fl[2] && !$Info->user_can_see_grades ? " hiddennote61" : "") . '">' . htmlspecialchars($f) . ':' . substr($fl[1], 1) . '</a>';
}
if (count($notelinks)) {
    ContactView::echo_group("notes", join(", ", $notelinks));
}
// check for any linenotes
$has_any_linenotes = false;
foreach ($diff as $file => $dinfo) {
    if ($lnorder->file($file)) {
        $has_any_linenotes = true;
        break;
    }
}
// line notes
foreach ($diff as $file => $dinfo) {
    $linenotes = $lnorder->file($file);
    $open = $linenotes || !$dinfo->boring || !$hasha_mine && !$hashb_mine;
    $Info->echo_file_diff($file, $dinfo, $lnorder, $open);
}
Ht::stash_script('jQuery(".diffnoteentry61").autogrow();jQuery(window).on("beforeunload",beforeunload61)');
echo "<table id=\"diff61linenotetemplate\" style=\"display:none\"><tbody>";
$Info->echo_linenote_entry_prototype();
echo "</tbody></table>";
echo "<div class='clear'></div>\n";
$Conf->footer();
예제 #21
0
 function render($sv)
 {
     global $Conf;
     $sv->echo_checkbox("rev_open", "<b>Open site for reviewing</b>");
     $sv->echo_checkbox("cmt_always", "Allow comments even if reviewing is closed");
     echo "<div class='g'></div>\n";
     $sv->echo_checkbox('pcrev_any', "PC members can review <strong>any</strong> submitted paper");
     echo "<div class='g'></div>\n";
     echo "<strong>Review anonymity:</strong> Are reviewer names hidden from authors?<br />\n";
     $sv->echo_radio_table("rev_blind", array(Conf::BLIND_ALWAYS => "Yes—reviews are anonymous", Conf::BLIND_NEVER => "No—reviewer names are visible to authors", Conf::BLIND_OPTIONAL => "Depends—reviewers decide whether to expose their names"));
     echo "<div class='g'></div>\n";
     $sv->echo_checkbox('rev_notifychair', 'Notify PC chairs of newly submitted reviews by email');
     // Deadlines
     echo "<h3 id=\"rounds\" class=\"settings g\">Deadlines &amp; rounds</h3>\n";
     echo '<p class="hint">Reviews are due by the deadline, but <em>cannot be modified</em> after the hard deadline. Most conferences don’t use hard deadlines for reviews.<br />', $sv->type_hint("date") ?: "", '</p>';
     $rounds = $Conf->round_list();
     if ($sv->use_req()) {
         for ($i = 1; isset($sv->req["roundname_{$i}"]); ++$i) {
             $rounds[$i] = get($sv->req, "deleteround_{$i}") ? ";" : trim(get_s($sv->req, "roundname_{$i}"));
         }
     }
     // prepare round selector
     $round_value = trim($sv->curv("rev_roundtag"));
     $current_round_value = $Conf->setting_data("rev_roundtag", "");
     if (preg_match('/\\A(?:|\\(none\\)|\\(no name\\)|default|unnamed|#0)\\z/i', $round_value)) {
         $round_value = "#0";
     } else {
         if (($round_number = $Conf->round_number($round_value, false)) || ($round_number = $Conf->round_number($current_round_value, false))) {
             $round_value = "#" . $round_number;
         } else {
             $round_value = $selector[$current_round_value] = $current_round_value;
         }
     }
     $round_map = edb_map(Dbl::ql("select reviewRound, count(*) from PaperReview group by reviewRound"));
     $print_round0 = true;
     if ($round_value !== "#0" && $round_value !== "" && $current_round_value !== "" && (!$sv->use_req() || isset($sv->req["roundname_0"])) && !$Conf->round0_defined()) {
         $print_round0 = false;
     }
     $selector = array();
     if ($print_round0) {
         $selector["#0"] = "unnamed";
     }
     for ($i = 1; $i < count($rounds); ++$i) {
         if ($rounds[$i] !== ";") {
             $selector["#{$i}"] = (object) array("label" => $rounds[$i], "id" => "rev_roundtag_{$i}");
         }
     }
     echo '<div id="round_container"', count($selector) == 1 ? ' style="display:none"' : '', '>', '<table id="rev_roundtag_table"><tr><td class="lxcaption">', $sv->label("rev_roundtag", "Current round"), '</td><td>', Ht::select("rev_roundtag", $selector, $round_value, $sv->sjs("rev_roundtag")), '</td></tr></table>', '<div class="hint">This round is used for new assignments.</div><div class="g"></div></div>';
     echo '<div id="roundtable">';
     $num_printed = 0;
     for ($i = 0; $i < count($rounds); ++$i) {
         if ($i ? $rounds[$i] !== ";" : $print_round0) {
             $this->echo_round($sv, $i, $i ? $rounds[$i] : "", +get($round_map, $i), count($selector) !== 1);
             ++$num_printed;
         }
     }
     echo '</div><div id="newround" style="display:none">';
     $this->echo_round($sv, '$', "", "", true);
     echo '</div><div class="g"></div>';
     echo Ht::js_button("Add round", "review_round_settings.add();hiliter(this)"), ' &nbsp; <span class="hint"><a href="', hoturl("help", "t=revround"), '">What is this?</a></span>', Ht::hidden("oldroundcount", count($Conf->round_list())), Ht::hidden("has_rev_roundtag", 1);
     for ($i = 1; $i < count($rounds); ++$i) {
         if ($rounds[$i] === ";") {
             echo Ht::hidden("roundname_{$i}", "", array("id" => "roundname_{$i}")), Ht::hidden("deleteround_{$i}", 1);
         }
     }
     Ht::stash_script("review_round_settings.init()");
     // External reviews
     echo "<h3 class=\"settings g\">External reviews</h3>\n";
     echo "<div class='g'></div>";
     $sv->echo_checkbox("extrev_chairreq", "PC chair must approve proposed external reviewers");
     $sv->echo_checkbox("pcrev_editdelegate", "PC members can edit external reviews they requested");
     echo "<div class='g'></div>\n";
     $t = expandMailTemplate("requestreview", false);
     echo "<table id='foldmailbody_requestreview' class='", $t == expandMailTemplate("requestreview", true) ? "foldc" : "foldo", "'><tr><td>", foldbutton("mailbody_requestreview"), "</td>", "<td><a href='#' onclick='return fold(\"mailbody_requestreview\")' class='q'><strong>Mail template for external review requests</strong></a>", " <span class='fx'>(<a href='", hoturl("mail"), "'>keywords</a> allowed; set to empty for default)<br /></span>\n<textarea class='tt fx' name='mailbody_requestreview' cols='80' rows='20'>", htmlspecialchars($t["body"]), "</textarea>", "</td></tr></table>\n";
     // Review visibility
     echo "<h3 class=\"settings g\">Visibility</h3>\n";
     echo "Can PC members <strong>see all reviews</strong> except for conflicts?<br />\n";
     $sv->echo_radio_table("pc_seeallrev", array(Conf::PCSEEREV_YES => "Yes", Conf::PCSEEREV_UNLESSINCOMPLETE => "Yes, unless they haven’t completed an assigned review for the same paper", Conf::PCSEEREV_UNLESSANYINCOMPLETE => "Yes, after completing all their assigned reviews", Conf::PCSEEREV_IFCOMPLETE => "Only after completing a review for the same paper"));
     echo "<div class='g'></div>\n";
     echo "Can PC members see <strong>reviewer names</strong> except for conflicts?<br />\n";
     $sv->echo_radio_table("pc_seeblindrev", array(0 => "Yes", 1 => "Only after completing a review for the same paper<br /><span class='hint'>This setting also hides reviewer-only comments from PC members who have not completed a review for the same paper.</span>"));
     echo "<div class='g'></div>";
     echo "Can external reviewers see the other reviews for their assigned papers, once they’ve submitted their own?<br />\n";
     $sv->echo_radio_table("extrev_view", array(2 => "Yes", 1 => "Yes, but they can’t see who wrote blind reviews", 0 => "No"));
     // Review ratings
     echo "<h3 class=\"settings g\">Review ratings</h3>\n";
     echo "Should HotCRP collect ratings of reviews? &nbsp; <a class='hint' href='", hoturl("help", "t=revrate"), "'>(Learn more)</a><br />\n";
     $sv->echo_radio_table("rev_ratings", array(REV_RATINGS_PC => "Yes, PC members can rate reviews", REV_RATINGS_PC_EXTERNAL => "Yes, PC members and external reviewers can rate reviews", REV_RATINGS_NONE => "No"));
 }