mirror of
https://github.com/renbaoshuo/S2OJ.git
synced 2024-11-08 14:48:41 +00:00
refactor(contest/self_reviews): allow admins edit participants' self_reviews
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
58ba28d9b9
commit
946ea8283f
@ -236,97 +236,85 @@ if ($cur_tab == 'dashboard') {
|
||||
$reply_question = null;
|
||||
}
|
||||
} elseif ($cur_tab == 'self_reviews') {
|
||||
if (UOJContest::cur()->userHasMarkedParticipated(Auth::user())) {
|
||||
$self_reviews_update_form = new UOJForm('self_review_update');
|
||||
$self_reviews_update_form->config['ctrl_enter_submit'] = true;
|
||||
|
||||
$contest_problems = DB::selectAll([
|
||||
"select problem_id",
|
||||
"from", "contests_problems",
|
||||
"where", ["contest_id" => $contest['id']],
|
||||
"order by level, problem_id"
|
||||
]);
|
||||
for ($i = 0; $i < count($contest_problems); $i++) {
|
||||
$contest_problems[$i]['problem'] = UOJContestProblem::query($contest_problems[$i]['problem_id']);
|
||||
$self_reviews_update_form = new UOJForm('self_reviews_update');
|
||||
$self_reviews_update_form->config['ctrl_enter_submit'] = true;
|
||||
$self_reviews_update_form->addHidden('self_reviews_update__username', '', function ($username, &$vdata) {
|
||||
if (!validateUsername($username)) {
|
||||
return '无效用户名';
|
||||
}
|
||||
|
||||
for ($i = 0; $i < count($contest_problems); $i++) {
|
||||
$content = DB::selectSingle([
|
||||
"select content",
|
||||
"from", "contests_reviews",
|
||||
"where", [
|
||||
"contest_id" => $contest['id'],
|
||||
"problem_id" => $contest_problems[$i]['problem_id'],
|
||||
"poster" => Auth::id(),
|
||||
],
|
||||
]);
|
||||
$self_reviews_update_form->addTextArea('self_review_update__problem_' . $contest_problems[$i]['problem']->getLetter(), [
|
||||
'div_class' => 'mb-3',
|
||||
'label' => '<b>' . $contest_problems[$i]['problem']->getLetter() . '</b>: ' . $contest_problems[$i]['problem']->info['title'],
|
||||
'default_value' => $content,
|
||||
'validator_php' => function ($content) {
|
||||
if (strlen($content) > 200) {
|
||||
return '总结不能超过200字';
|
||||
}
|
||||
|
||||
return '';
|
||||
},
|
||||
]);
|
||||
if ($username != Auth::id() && !UOJContest::cur()->userCanManage(Auth::user())) {
|
||||
return '权限不足';
|
||||
}
|
||||
|
||||
$content = DB::selectSingle([
|
||||
"select content",
|
||||
"from", "contests_reviews",
|
||||
"where", [
|
||||
"contest_id" => $contest['id'],
|
||||
"problem_id" => -1,
|
||||
"poster" => Auth::id(),
|
||||
],
|
||||
]);
|
||||
$self_reviews_update_form->addTextArea('self_review_update__overall', [
|
||||
'label' => '比赛总结',
|
||||
'default_value' => $content,
|
||||
return '';
|
||||
}, null);
|
||||
|
||||
$contest_problems = array_map(fn ($row) => UOJContestProblem::query($row['problem_id']), DB::selectAll([
|
||||
"select problem_id",
|
||||
"from", "contests_problems",
|
||||
"where", ["contest_id" => $contest['id']],
|
||||
"order by level, problem_id"
|
||||
]));
|
||||
|
||||
foreach ($contest_problems as $cp) {
|
||||
$self_reviews_update_form->addTextArea('self_reviews_update__problem_' . $cp->getLetter(), [
|
||||
'div_class' => 'mb-3',
|
||||
'label' => $cp->getTitle(['with' => 'letter']),
|
||||
'default_value' => '',
|
||||
'validator_php' => function ($content) {
|
||||
if (strlen($content) > 200) {
|
||||
return '总结不能超过200字';
|
||||
return '长度超过限制';
|
||||
}
|
||||
|
||||
return '';
|
||||
},
|
||||
]);
|
||||
|
||||
$self_reviews_update_form->handle = function () use ($contest, $contest_problems) {
|
||||
for ($i = 0; $i < count($contest_problems); $i++) {
|
||||
if (isset($_POST['self_review_update__problem_' . $contest_problems[$i]['problem']->getLetter()])) {
|
||||
DB::query([
|
||||
"replace into contests_reviews",
|
||||
"(contest_id, problem_id, poster, content)",
|
||||
"values", DB::tuple([
|
||||
$contest['id'],
|
||||
$contest_problems[$i]['problem_id'],
|
||||
Auth::id(),
|
||||
$_POST['self_review_update__problem_' . $contest_problems[$i]['problem']->getLetter()],
|
||||
]),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($_POST['self_review_update__overall'])) {
|
||||
DB::query([
|
||||
"replace into contests_reviews",
|
||||
"(contest_id, problem_id, poster, content)",
|
||||
"values", DB::tuple([
|
||||
$contest['id'],
|
||||
-1,
|
||||
Auth::id(),
|
||||
$_POST['self_review_update__overall'],
|
||||
]),
|
||||
]);
|
||||
}
|
||||
};
|
||||
|
||||
$self_reviews_update_form->runAtServer();
|
||||
}
|
||||
|
||||
$self_reviews_update_form->addTextArea('self_reviews_update__overall', [
|
||||
'label' => '比赛总结',
|
||||
'validator_php' => function ($content) {
|
||||
if (strlen($content) > 300) {
|
||||
return '长度超过限制';
|
||||
}
|
||||
|
||||
return '';
|
||||
},
|
||||
]);
|
||||
|
||||
$self_reviews_update_form->handle = function (&$vdata) use ($contest_problems) {
|
||||
foreach ($contest_problems as $cp) {
|
||||
DB::update([
|
||||
"replace into contests_reviews",
|
||||
DB::bracketed_fields([
|
||||
"contest_id",
|
||||
"problem_id",
|
||||
"poster",
|
||||
"content"
|
||||
]),
|
||||
"values", DB::tuple([
|
||||
UOJContest::info('id'),
|
||||
$cp->info['id'],
|
||||
$_POST['self_reviews_update__username'],
|
||||
$_POST['self_reviews_update__problem_' . $cp->getLetter()],
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
DB::update([
|
||||
"replace into contests_reviews",
|
||||
"(contest_id, problem_id, poster, content)",
|
||||
"values", DB::tuple([
|
||||
UOJContest::info('id'),
|
||||
-1,
|
||||
$_POST['self_reviews_update__username'],
|
||||
$_POST['self_reviews_update__overall'],
|
||||
]),
|
||||
]);
|
||||
};
|
||||
|
||||
$self_reviews_update_form->runAtServer();
|
||||
}
|
||||
|
||||
function echoDashboard() {
|
||||
@ -469,9 +457,12 @@ function echoStandings($is_after_contest_query = false) {
|
||||
}
|
||||
|
||||
function echoSelfReviews() {
|
||||
global $contest;
|
||||
global $contest, $self_reviews_update_form;
|
||||
|
||||
uojIncludeView('contest-reviews', ['contest' => $contest] + UOJContest::cur()->queryResult());
|
||||
uojIncludeView('contest-reviews', [
|
||||
'contest' => $contest,
|
||||
'self_reviews_update_form' => $self_reviews_update_form,
|
||||
] + UOJContest::cur()->queryResult());
|
||||
}
|
||||
?>
|
||||
<?php echoUOJPageHeader($tabs_info[$cur_tab]['name'] . ' - ' . UOJContest::info('name') . ' - ' . UOJLocale::get('contests::contest')) ?>
|
||||
@ -538,17 +529,7 @@ function echoSelfReviews() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php if ($cur_tab == 'standings' || $cur_tab == 'after_contest_standings') : ?>
|
||||
<?php elseif ($cur_tab == 'self_reviews') : ?>
|
||||
<?php if (isset($self_reviews_update_form)) : ?>
|
||||
<hr />
|
||||
|
||||
<div class="col-md-6">
|
||||
<h4>修改我的赛后总结</h4>
|
||||
<div class="small">赛后总结支持 Markdown 语法。</div>
|
||||
<?php $self_reviews_update_form->printHTML(); ?>
|
||||
</div>
|
||||
<?php endif ?>
|
||||
<?php if ($cur_tab == 'standings' || $cur_tab == 'after_contest_standings' || $cur_tab == 'self_reviews') : ?>
|
||||
<?php else : ?>
|
||||
<div class="d-md-none">
|
||||
<hr />
|
||||
|
@ -5,7 +5,9 @@ $parsedown = HTML::parsedown(['username_with_color' => true]);
|
||||
$purifier = HTML::purifier_inline();
|
||||
|
||||
foreach ($contest_data['people'] as $person) {
|
||||
$reviews[$person[0]] = [];
|
||||
$reviews[$person[0]] = [
|
||||
'_can_edit' => Auth::id() == $person[0] || UOJContest::cur()->userCanManage(Auth::user()),
|
||||
];
|
||||
|
||||
foreach ($contest_data['problems'] as $problem) {
|
||||
$content = DB::selectSingle([
|
||||
@ -18,7 +20,8 @@ foreach ($contest_data['people'] as $person) {
|
||||
],
|
||||
]);
|
||||
|
||||
$reviews[$person[0]][$problem] = $purifier->purify($parsedown->line($content));
|
||||
$reviews[$person[0]][$problem]['raw'] = $content;
|
||||
$reviews[$person[0]][$problem]['html'] = $purifier->purify($parsedown->line($content));
|
||||
}
|
||||
|
||||
$content = DB::selectSingle([
|
||||
@ -31,19 +34,34 @@ foreach ($contest_data['people'] as $person) {
|
||||
],
|
||||
]);
|
||||
|
||||
$reviews[$person[0]]['all'] = $purifier->purify($parsedown->line($content));
|
||||
$reviews[$person[0]]['_all']['raw'] = $content;
|
||||
$reviews[$person[0]]['_all']['html'] = $purifier->purify($parsedown->line($content));
|
||||
}
|
||||
?>
|
||||
|
||||
<div id="standings"></div>
|
||||
|
||||
<div class="modal fade" id="UpdateSelfReviewsModal" tabindex="-1" aria-labelledby="UpdateSelfReviewsModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h1 class="modal-title fs-5" id="UpdateSelfReviewsModalLabel">更新赛后总结</h1>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<?php $self_reviews_update_form->printHTML(); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
var contest_id = <?= $contest['id'] ?>;
|
||||
var standings = <?= json_encode($standings) ?>;
|
||||
var score = <?= json_encode($score) ?>;
|
||||
var problems = <?= json_encode($contest_data['problems']) ?>;
|
||||
var reviews = <?= json_encode($reviews) ?>;
|
||||
var standings_config = <?= json_encode(isset($standings_config) ? $standings_config : ['_config' => true]) ?>;
|
||||
var reviews = <?= json_encode($reviews, JSON_FORCE_OBJECT) ?>;
|
||||
var standings_config = <?= json_encode(isset($standings_config) ? $standings_config : [], JSON_FORCE_OBJECT) ?>;
|
||||
|
||||
$(document).ready(function() {
|
||||
$("#standings").long_table(
|
||||
@ -59,33 +77,75 @@ foreach ($contest_data['people'] as $person) {
|
||||
'<th style="width:16em">赛后总结</th>' +
|
||||
'</tr>',
|
||||
function(row) {
|
||||
var col_tr = '<tr>';
|
||||
col_tr += '<td>' + row[3] + '</td>';
|
||||
col_tr += '<td>' + getUserLink(row[2][0], row[2][1]) + '</td>';
|
||||
col_tr += '<td>' + '<span class="uoj-score" data-max="' + problems.length * 100 + '" style="color:' + getColOfScore(row[0] / problems.length) + '">' + row[0] + '</span>' + '</td>';
|
||||
if (reviews[row[2][0]]['_can_edit']) {
|
||||
var button_update_review = $('<button class="btn btn-sm btn-outline-secondary ms-2" />').append('<i class="bi bi-pencil"></i>');
|
||||
|
||||
button_update_review.click(function() {
|
||||
$('#UpdateSelfReviewsModalLabel').text('更新 ' + row[2][0] + ' 的赛后总结');
|
||||
$('#input-self_reviews_update__username').val(row[2][0]);
|
||||
|
||||
$.map(problems, function(col, idx) {
|
||||
$('#input-self_reviews_update__problem_' + String.fromCharCode('A'.charCodeAt(0) + idx)).val(reviews[row[2][0]][col]['raw'] || '');
|
||||
});
|
||||
|
||||
$('#input-self_reviews_update__overall').val(reviews[row[2][0]]['_all']['raw'] || '');
|
||||
$('#UpdateSelfReviewsModal').modal('show');
|
||||
});
|
||||
} else {
|
||||
var button_update_review = '';
|
||||
}
|
||||
|
||||
var res = $('<tr />')
|
||||
.append($('<td />').append(row[3]))
|
||||
.append($('<td />').append(getUserLink(row[2][0], row[2][1])).append(button_update_review))
|
||||
.append($('<td />').append($('<span class="uoj-score" />').attr('data-max', problems.length * 100).css('color', getColOfScore(row[0] / problems.length)).append(row[0])));
|
||||
|
||||
for (var i = 0; i < problems.length; i++) {
|
||||
col_tr += '<td class="align-text-top">';
|
||||
var td = $('<td class="align-text-top" />');
|
||||
|
||||
col = score[row[2][0]][i];
|
||||
|
||||
if (col != undefined) {
|
||||
col_tr += '<div>';
|
||||
td.append($('<div />').append($('<a class="uoj-score" />').attr('href', '/submission/' + col[2]).attr('data-max', 100).css('color', getColOfScore(col[0])).append(col[0])));
|
||||
|
||||
if (col[2]) col_tr += '<a href="/submission/' + col[2] + '" class="uoj-score" style="color:' + getColOfScore(col[0]) + '">' + col[0] + '</a>';
|
||||
else col_tr += '<span class="uoj-score" style="color:' + getColOfScore(col[0]) + '">' + col[0] + '</span>';
|
||||
|
||||
col_tr += '</div>';
|
||||
if (col[2]) {
|
||||
td.append(
|
||||
$('<div />').append(
|
||||
$('<a class="uoj-score" />')
|
||||
.attr('href', '/submission/' + col[2])
|
||||
.attr('data-max', 100)
|
||||
.css('color', getColOfScore(col[0]))
|
||||
.append(col[0])
|
||||
)
|
||||
);
|
||||
} else {
|
||||
td.append(
|
||||
$('<div />').append(
|
||||
$('<span class="uoj-score" />')
|
||||
.data('max', 100)
|
||||
.css('color', getColOfScore(col[0]))
|
||||
.append(col[0])
|
||||
)
|
||||
);
|
||||
}
|
||||
} else {
|
||||
col_tr += '<div> </div>';
|
||||
td.append($('<div />').append(' '));
|
||||
}
|
||||
|
||||
if (reviews[row[2][0]][problems[i]]) {
|
||||
col_tr += '<div class="mt-2 pt-2 border-top">' + reviews[row[2][0]][problems[i]] + '</div>';
|
||||
td.append($('<div class="mt-2 pt-2 border-top" />').append(reviews[row[2][0]][problems[i]]['html']));
|
||||
}
|
||||
|
||||
col_tr += '</td>';
|
||||
res.append(td);
|
||||
}
|
||||
col_tr += '<td>' + reviews[row[2][0]]['all'] + '</td>';
|
||||
col_tr += '</tr>';
|
||||
return col_tr;
|
||||
|
||||
if (reviews[row[2][0]]['_all']) {
|
||||
res.append($('<td />').append(reviews[row[2][0]]['_all']['html']));
|
||||
} else {
|
||||
res.append($('<td />').append(' '));
|
||||
}
|
||||
|
||||
return res.uoj_highlight();
|
||||
}, {
|
||||
div_classes: standings_config.div_classes ? standings_config.div_classes : ['table-responsive', 'card', 'my-3'],
|
||||
table_classes: standings_config.table_classes ? standings_config.table_classes : ['table', 'table-bordered', 'text-center', 'align-middle', 'uoj-table', 'uoj-standings-table', 'mb-0'],
|
||||
|
Loading…
Reference in New Issue
Block a user