mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-20 01:38:19 +08:00
core: admin can remove contestant before contest start (#1196)
This commit is contained in:
1 parent
52f811cf98
commit
f29971a30d
11 files changed
+50
-3
No files matched your search
@@ -685,6 +685,7 @@ The user is too lazy to leave something here...: 설명이 없습니다... (´
|
|||||||
There are no contests...: 대회 없음
|
There are no contests...: 대회 없음
|
||||||
There is no homework so far ╰(*°▽°*)╯: 과제 없음 ╰(*°▽°*)╯
|
There is no homework so far ╰(*°▽°*)╯: 과제 없음 ╰(*°▽°*)╯
|
||||||
This contest is not live.: 대회가 실시간이 아닙니다.
|
This contest is not live.: 대회가 실시간이 아닙니다.
|
||||||
|
This contest has already started.: 대회가 이미 시작되었습니다.
|
||||||
This email was sent by {0} automatically, and please do not reply directly.: '{0}으로 이메일을 보냈습니다.'
|
This email was sent by {0} automatically, and please do not reply directly.: '{0}으로 이메일을 보냈습니다.'
|
||||||
This homework is not open and you cannot view problems.: 과제를 열지 않았기에 문제를 볼 수 없습니다.
|
This homework is not open and you cannot view problems.: 과제를 열지 않았기에 문제를 볼 수 없습니다.
|
||||||
This homework is not open.: 과제가 아직 닫혀 있습니다.
|
This homework is not open.: 과제가 아직 닫혀 있습니다.
|
||||||
|
|||||||
@@ -811,6 +811,7 @@ theme: 主题
|
|||||||
There are no contests...: 没有比赛…
|
There are no contests...: 没有比赛…
|
||||||
There is no homework so far ╰(*°▽°*)╯: 目前还没有作业 ╰(*°▽°*)╯
|
There is no homework so far ╰(*°▽°*)╯: 目前还没有作业 ╰(*°▽°*)╯
|
||||||
This contest is not live.: 比赛没有开始。
|
This contest is not live.: 比赛没有开始。
|
||||||
|
This contest has already started.: 比赛已开始。
|
||||||
This email was sent by {0} automatically, and please do not reply directly.: 这封邮件由 {0} 自动发送,请勿直接回复。
|
This email was sent by {0} automatically, and please do not reply directly.: 这封邮件由 {0} 自动发送,请勿直接回复。
|
||||||
This homework is not open and you cannot view problems.: 该作业还未到开放时间,您无法查看作业题目。
|
This homework is not open and you cannot view problems.: 该作业还未到开放时间,您无法查看作业题目。
|
||||||
This homework is not open.: 该作业还未开放递交。
|
This homework is not open.: 该作业还未开放递交。
|
||||||
|
|||||||
@@ -808,6 +808,7 @@ theme: 主題
|
|||||||
There are no contests...: 沒有比賽…
|
There are no contests...: 沒有比賽…
|
||||||
There is no homework so far ╰(*°▽°*)╯: 目前沒有功課 ╰(*°▽°*)╯
|
There is no homework so far ╰(*°▽°*)╯: 目前沒有功課 ╰(*°▽°*)╯
|
||||||
This contest is not live.: 比賽沒有開始。
|
This contest is not live.: 比賽沒有開始。
|
||||||
|
This contest has already started.: 比賽已開始。
|
||||||
This email was sent by {0} automatically, and please do not reply directly.: 這封郵件由 {0} 自動傳送,請勿直接回復。
|
This email was sent by {0} automatically, and please do not reply directly.: 這封郵件由 {0} 自動傳送,請勿直接回復。
|
||||||
This homework is not open and you cannot view problems.: 功課尚未開放,不能檢視題目。
|
This homework is not open and you cannot view problems.: 功課尚未開放,不能檢視題目。
|
||||||
This homework is not open.: 功課尚未開放遞交。
|
This homework is not open.: 功課尚未開放遞交。
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ export const ContestNotAttendedError = Err('ContestNotAttendedError', ForbiddenE
|
|||||||
export const RequireProError = Err('RequireProError', ForbiddenError, 'RequireProError');
|
export const RequireProError = Err('RequireProError', ForbiddenError, 'RequireProError');
|
||||||
export const ContestAlreadyAttendedError = Err('ContestAlreadyAttendedError', ForbiddenError, "You've already attended this contest.");
|
export const ContestAlreadyAttendedError = Err('ContestAlreadyAttendedError', ForbiddenError, "You've already attended this contest.");
|
||||||
export const ContestNotLiveError = Err('ContestNotLiveError', ForbiddenError, 'This contest is not live.');
|
export const ContestNotLiveError = Err('ContestNotLiveError', ForbiddenError, 'This contest is not live.');
|
||||||
|
export const ContestAlreadyStartedError = Err('ContestAlreadyStartedError', ForbiddenError, 'This contest has already started.');
|
||||||
export const ContestNotEndedError = Err('ContestNotEndedError', ForbiddenError, 'This contest is not ended.');
|
export const ContestNotEndedError = Err('ContestNotEndedError', ForbiddenError, 'This contest is not ended.');
|
||||||
export const ContestScoreboardHiddenError = Err('ContestScoreboardHiddenError', ForbiddenError, 'Contest scoreboard is not visible.');
|
export const ContestScoreboardHiddenError = Err('ContestScoreboardHiddenError', ForbiddenError, 'Contest scoreboard is not visible.');
|
||||||
export const TrainingAlreadyEnrollError = Err('TrainingAlreadyEnrollError', ForbiddenError, "You've already enrolled this training.");
|
export const TrainingAlreadyEnrollError = Err('TrainingAlreadyEnrollError', ForbiddenError, "You've already enrolled this training.");
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ import {
|
|||||||
} from '@hydrooj/utils/lib/utils';
|
} from '@hydrooj/utils/lib/utils';
|
||||||
import { Context, Service } from '../context';
|
import { Context, Service } from '../context';
|
||||||
import {
|
import {
|
||||||
BadRequestError, ContestNotAttendedError, ContestNotEndedError, ContestNotFoundError, ContestNotLiveError,
|
BadRequestError, ContestAlreadyStartedError, ContestNotAttendedError, ContestNotEndedError, ContestNotFoundError,
|
||||||
ContestScoreboardHiddenError, FileLimitExceededError, FileUploadError,
|
ContestNotLiveError, ContestScoreboardHiddenError, FileLimitExceededError, FileUploadError,
|
||||||
InvalidTokenError, MethodNotAllowedError, NotAssignedError, NotFoundError, PermissionError, ValidationError,
|
InvalidTokenError, MethodNotAllowedError, NotAssignedError, NotFoundError, PermissionError, ValidationError,
|
||||||
} from '../error';
|
} from '../error';
|
||||||
import { ContestStatusDoc, FileInfo, ScoreboardConfig, Tdoc } from '../interface';
|
import { ContestStatusDoc, FileInfo, ScoreboardConfig, Tdoc } from '../interface';
|
||||||
@@ -761,6 +761,16 @@ export class ContestUserHandler extends ContestManagementBaseHandler {
|
|||||||
await contest.setStatus(domainId, tid, uid, null, { endAt: '' });
|
await contest.setStatus(domainId, tid, uid, null, { endAt: '' });
|
||||||
this.back();
|
this.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@param('tid', Types.ObjectId)
|
||||||
|
@param('uid', Types.Int)
|
||||||
|
async postRemoveUser(domainId: string, tid: ObjectId, uid: number) {
|
||||||
|
if (!contest.isNotStarted(this.tdoc)) throw new ContestAlreadyStartedError();
|
||||||
|
const tsdoc = await contest.getStatus(domainId, tid, uid);
|
||||||
|
if (!tsdoc?.attend) throw new ContestNotAttendedError(uid);
|
||||||
|
await contest.cancelAttend(domainId, tid, uid);
|
||||||
|
this.back();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ContestBalloonHandler extends ContestManagementBaseHandler {
|
export class ContestBalloonHandler extends ContestManagementBaseHandler {
|
||||||
|
|||||||
@@ -939,6 +939,12 @@ export async function attend(domainId: string, tid: ObjectId, uid: number, paylo
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function cancelAttend(domainId: string, tid: ObjectId, uid: number) {
|
||||||
|
await document.deleteMultiStatus(domainId, document.TYPE_CONTEST, { docId: tid, uid });
|
||||||
|
await document.inc(domainId, document.TYPE_CONTEST, tid, 'attend', -1);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
export function getMultiStatus(domainId: string, query: any) {
|
export function getMultiStatus(domainId: string, query: any) {
|
||||||
return document.getMultiStatus(domainId, document.TYPE_CONTEST, query);
|
return document.getMultiStatus(domainId, document.TYPE_CONTEST, query);
|
||||||
}
|
}
|
||||||
@@ -1148,6 +1154,7 @@ global.Hydro.model.contest = {
|
|||||||
getListStatus,
|
getListStatus,
|
||||||
getMultiStatus,
|
getMultiStatus,
|
||||||
attend,
|
attend,
|
||||||
|
cancelAttend,
|
||||||
edit,
|
edit,
|
||||||
del,
|
del,
|
||||||
get,
|
get,
|
||||||
|
|||||||
@@ -59,6 +59,9 @@ Active Sessions: 활성 세션
|
|||||||
Add module: 앱 모듈
|
Add module: 앱 모듈
|
||||||
Add new data: 데이터 추가
|
Add new data: 데이터 추가
|
||||||
Add User: 사용자 추가
|
Add User: 사용자 추가
|
||||||
|
Cancel Registration: 참가 취소
|
||||||
|
Registration cancelled.: 참가가 취소되었습니다.
|
||||||
|
Are you sure to cancel the registration of this user?: 이 사용자의 참가를 취소하시겠습니까?
|
||||||
Add: 추가
|
Add: 추가
|
||||||
All {0} Contests: 전체 {0} 대회
|
All {0} Contests: 전체 {0} 대회
|
||||||
All Contests: 전체 대회
|
All Contests: 전체 대회
|
||||||
@@ -690,6 +693,7 @@ Their account will not be deleted and they will be with the guest role until the
|
|||||||
There are no contests...: 대회 없음
|
There are no contests...: 대회 없음
|
||||||
There is no homework so far ╰(*°▽°*)╯: 과제 없음 ╰(*°▽°*)╯
|
There is no homework so far ╰(*°▽°*)╯: 과제 없음 ╰(*°▽°*)╯
|
||||||
This contest is not live.: 대회가 실시간이 아닙니다.
|
This contest is not live.: 대회가 실시간이 아닙니다.
|
||||||
|
This contest has already started.: 대회가 이미 시작되었습니다.
|
||||||
This email was sent by {0} automatically, and please do not reply directly.: '{0}으로 이메일을 보냈습니다.'
|
This email was sent by {0} automatically, and please do not reply directly.: '{0}으로 이메일을 보냈습니다.'
|
||||||
This homework is not open and you cannot view problems.: 과제를 열지 않았기에 문제를 볼 수 없습니다.
|
This homework is not open and you cannot view problems.: 과제를 열지 않았기에 문제를 볼 수 없습니다.
|
||||||
This homework is not open.: 과제가 아직 닫혀 있습니다.
|
This homework is not open.: 과제가 아직 닫혀 있습니다.
|
||||||
|
|||||||
@@ -87,6 +87,9 @@ Add prefix/suffix: 添加前缀/后缀
|
|||||||
Add suffix: 添加后缀
|
Add suffix: 添加后缀
|
||||||
Add testcase: 添加测试点
|
Add testcase: 添加测试点
|
||||||
Add User: 添加用户
|
Add User: 添加用户
|
||||||
|
Cancel Registration: 取消报名
|
||||||
|
Registration cancelled.: 报名已取消。
|
||||||
|
Are you sure to cancel the registration of this user?: 确定要取消该用户的报名吗?
|
||||||
Add: 添加
|
Add: 添加
|
||||||
Additional Files: 附加文件
|
Additional Files: 附加文件
|
||||||
additional_file: 附加文件
|
additional_file: 附加文件
|
||||||
@@ -966,6 +969,7 @@ There are no contests...: 没有比赛…
|
|||||||
There are no files currently.: 目前还没有文件。
|
There are no files currently.: 目前还没有文件。
|
||||||
There is no homework so far ╰(*°▽°*)╯: 目前还没有作业 ╰(*°▽°*)╯
|
There is no homework so far ╰(*°▽°*)╯: 目前还没有作业 ╰(*°▽°*)╯
|
||||||
This contest is not live.: 比赛没有开始。
|
This contest is not live.: 比赛没有开始。
|
||||||
|
This contest has already started.: 比赛已开始。
|
||||||
This email was sent by {0} automatically, and please do not reply directly.: 这封邮件由 {0} 自动发送,请勿直接回复。
|
This email was sent by {0} automatically, and please do not reply directly.: 这封邮件由 {0} 自动发送,请勿直接回复。
|
||||||
This homework is not open and you cannot view problems.: 该作业还未到开放时间,您无法查看作业题目。
|
This homework is not open and you cannot view problems.: 该作业还未到开放时间,您无法查看作业题目。
|
||||||
This homework is not open.: 该作业还未开放递交。
|
This homework is not open.: 该作业还未开放递交。
|
||||||
|
|||||||
@@ -87,6 +87,9 @@ Add prefix/suffix: 新增字首/字尾
|
|||||||
Add suffix: 新增字尾
|
Add suffix: 新增字尾
|
||||||
Add testcase: 新增測試點
|
Add testcase: 新增測試點
|
||||||
Add User: 新增使用者
|
Add User: 新增使用者
|
||||||
|
Cancel Registration: 取消報名
|
||||||
|
Registration cancelled.: 報名已取消。
|
||||||
|
Are you sure to cancel the registration of this user?: 確定要取消該使用者的報名嗎?
|
||||||
Add: 新增
|
Add: 新增
|
||||||
Additional Files: 附加檔案
|
Additional Files: 附加檔案
|
||||||
additional_file: 附加檔案
|
additional_file: 附加檔案
|
||||||
@@ -962,6 +965,7 @@ There are no contests...: 沒有比賽…
|
|||||||
There are no files currently.: 目前還沒有檔案。
|
There are no files currently.: 目前還沒有檔案。
|
||||||
There is no homework so far ╰(*°▽°*)╯: 目前沒有功課 ╰(*°▽°*)╯
|
There is no homework so far ╰(*°▽°*)╯: 目前沒有功課 ╰(*°▽°*)╯
|
||||||
This contest is not live.: 比賽沒有開始。
|
This contest is not live.: 比賽沒有開始。
|
||||||
|
This contest has already started.: 比賽已開始。
|
||||||
This email was sent by {0} automatically, and please do not reply directly.: 這封郵件由 {0} 自動傳送,請勿直接回復。
|
This email was sent by {0} automatically, and please do not reply directly.: 這封郵件由 {0} 自動傳送,請勿直接回復。
|
||||||
This homework is not open and you cannot view problems.: 功課尚未開放,不能檢視題目。
|
This homework is not open and you cannot view problems.: 功課尚未開放,不能檢視題目。
|
||||||
This homework is not open.: 功課尚未開放遞交。
|
This homework is not open.: 功課尚未開放遞交。
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import $ from 'jquery';
|
import $ from 'jquery';
|
||||||
import UserSelectAutoComplete from 'vj/components/autocomplete/UserSelectAutoComplete';
|
import UserSelectAutoComplete from 'vj/components/autocomplete/UserSelectAutoComplete';
|
||||||
import { ActionDialog } from 'vj/components/dialog';
|
import { ActionDialog, confirm } from 'vj/components/dialog';
|
||||||
import Notification from 'vj/components/notification';
|
import Notification from 'vj/components/notification';
|
||||||
import { NamedPage } from 'vj/misc/Page';
|
import { NamedPage } from 'vj/misc/Page';
|
||||||
import {
|
import {
|
||||||
@@ -93,9 +93,20 @@ const page = new NamedPage('contest_user', () => {
|
|||||||
}, i18n('Contest resumed.'));
|
}, i18n('Contest resumed.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function handleCancelRegistration(ev) {
|
||||||
|
const uid = $(ev.target).data('uid');
|
||||||
|
const yes = await confirm(i18n('Are you sure to cancel the registration of this user?'));
|
||||||
|
if (!yes) return;
|
||||||
|
await handlePostRequest({
|
||||||
|
operation: 'remove_user',
|
||||||
|
uid,
|
||||||
|
}, i18n('Registration cancelled.'));
|
||||||
|
}
|
||||||
|
|
||||||
$('[name="add_user"]').on('click', () => handleClickAddUser());
|
$('[name="add_user"]').on('click', () => handleClickAddUser());
|
||||||
$(document).on('click', '[name="edit_rank"]', handleEditRank);
|
$(document).on('click', '[name="edit_rank"]', handleEditRank);
|
||||||
$(document).on('click', '[name="resume_contest"]', handleResume);
|
$(document).on('click', '[name="resume_contest"]', handleResume);
|
||||||
|
$(document).on('click', '[name="cancel_registration"]', handleCancelRegistration);
|
||||||
});
|
});
|
||||||
|
|
||||||
export default page;
|
export default page;
|
||||||
@@ -13,6 +13,9 @@
|
|||||||
{% if tsdoc.endAt and tsdoc.endAt < tdoc.endAt and tdoc.endAt.getTime() > Date.now() and (not tdoc.duration or not tsdoc.startAt or tsdoc.startAt.getTime() + tdoc.duration * 3600000 > Date.now()) %}
|
{% if tsdoc.endAt and tsdoc.endAt < tdoc.endAt and tdoc.endAt.getTime() > Date.now() and (not tdoc.duration or not tsdoc.startAt or tsdoc.startAt.getTime() + tdoc.duration * 3600000 > Date.now()) %}
|
||||||
| <a name="resume_contest" data-uid="{{ tsdoc.uid }}">{{ _('Resume') }}</a>
|
| <a name="resume_contest" data-uid="{{ tsdoc.uid }}">{{ _('Resume') }}</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% if tdoc.beginAt.getTime() > Date.now() %}
|
||||||
|
| <a name="cancel_registration" data-uid="{{ tsdoc.uid }}">{{ _('Cancel Registration') }}</a>
|
||||||
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{%- endfor -%}
|
{%- endfor -%}
|
||||||
|
|||||||
Reference in new issue
Block a user