From fac3a93bd32993572a6fe2b3fd810df9c243994f Mon Sep 17 00:00:00 2001 From: masnn Date: Mon, 13 May 2019 20:42:23 +0800 Subject: [PATCH 01/21] String PID support --- vj4/handler/contest.py | 16 ++++++++-------- vj4/handler/homework.py | 16 ++++++++-------- vj4/handler/problem.py | 15 +++++++-------- vj4/locale/zh_CN.yaml | 3 ++- vj4/model/adaptor/problem.py | 4 ++++ vj4/ui/templates/components/problem.html | 2 +- vj4/ui/templates/problem_edit.html | 10 +++++----- vj4/util/validator.py | 11 +++++++++++ 8 files changed, 46 insertions(+), 31 deletions(-) diff --git a/vj4/handler/contest.py b/vj4/handler/contest.py index 311decb45..fbce6f011 100644 --- a/vj4/handler/contest.py +++ b/vj4/handler/contest.py @@ -24,7 +24,7 @@ from vj4.util import pagination -@app.route('/contest', 'contest_main') +@app.route('/c', 'contest_main') class ContestMainHandler(contest.ContestMixin, base.Handler): CONTESTS_PER_PAGE = 20 @@ -47,7 +47,7 @@ async def get(self, *, rule: int=0, page: int=1): tdocs=tdocs, tsdict=tsdict) -@app.route('/contest/{tid:\w{24}}', 'contest_detail') +@app.route('/c/{tid:\w{24}}', 'contest_detail') class ContestDetailHandler(contest.ContestMixin, base.OperationHandler): DISCUSSIONS_PER_PAGE = 15 @@ -105,7 +105,7 @@ async def post_attend(self, *, tid: objectid.ObjectId): self.json_or_redirect(self.url) -@app.route('/contest/{tid:\w{24}}/code', 'contest_code') +@app.route('/c/{tid:\w{24}}/code', 'contest_code') class ContestCodeHandler(base.OperationHandler): @base.limit_rate('contest_code', 3600, 60) @base.route_argument @@ -132,7 +132,7 @@ async def get(self, *, tid: objectid.ObjectId): file_name='{}.zip'.format(tdoc['title'])) -@app.route('/contest/{tid}/{pid:-?\d+|\w{24}}', 'contest_detail_problem') +@app.route('/c/{tid}/p/{pid:[a-zA-Z0-9]+}', 'contest_detail_problem') class ContestDetailProblemHandler(contest.ContestMixin, base.Handler): @base.route_argument @base.require_perm(builtin.PERM_VIEW_CONTEST) @@ -163,7 +163,7 @@ async def get(self, *, tid: objectid.ObjectId, pid: document.convert_doc_id): page_title=pdoc['title'], path_components=path_components) -@app.route('/contest/{tid}/{pid}/submit', 'contest_detail_problem_submit') +@app.route('/c/{tid}/p/{pid}/submit', 'contest_detail_problem_submit') class ContestDetailProblemSubmitHandler(contest.ContestMixin, base.Handler): @base.route_argument @base.require_perm(builtin.PERM_VIEW_CONTEST) @@ -233,7 +233,7 @@ async def post(self, *, tid: objectid.ObjectId, pid: document.convert_doc_id, self.json_or_redirect(self.reverse_url('record_detail', rid=rid)) -@app.route('/contest/{tid}/scoreboard', 'contest_scoreboard') +@app.route('/c/{tid}/scoreboard', 'contest_scoreboard') class ContestScoreboardHandler(contest.ContestMixin, base.Handler): @base.route_argument @base.require_perm(builtin.PERM_VIEW_CONTEST) @@ -251,7 +251,7 @@ async def get(self, *, tid: objectid.ObjectId): page_title=page_title, path_components=path_components) -@app.route('/contest/{tid}/scoreboard/download/{ext}', 'contest_scoreboard_download') +@app.route('/c/{tid}/scoreboard/download/{ext}', 'contest_scoreboard_download') class ContestScoreboardDownloadHandler(contest.ContestMixin, base.Handler): def _export_status_as_csv(self, rows): # \r\n for notepad compatibility @@ -321,7 +321,7 @@ async def post(self, *, title: str, content: str, rule: int, self.json_or_redirect(self.reverse_url('contest_detail', tid=tid)) -@app.route('/contest/{tid}/edit', 'contest_edit') +@app.route('/c/{tid}/edit', 'contest_edit') class ContestEditHandler(contest.ContestMixin, base.Handler): @base.route_argument @base.require_priv(builtin.PRIV_USER_PROFILE) diff --git a/vj4/handler/homework.py b/vj4/handler/homework.py index 46b485bd7..5fd828bac 100644 --- a/vj4/handler/homework.py +++ b/vj4/handler/homework.py @@ -51,7 +51,7 @@ def _format_penalty_rules_yaml(penalty_rules): return yaml_doc -@app.route('/homework', 'homework_main') +@app.route('/h', 'homework_main') class HomeworkMainHandler(contest.ContestMixin, base.Handler): @base.require_perm(builtin.PERM_VIEW_HOMEWORK) async def get(self): @@ -72,7 +72,7 @@ async def get(self): self.render('homework_main.html', tdocs=tdocs, calendar_tdocs=calendar_tdocs) -@app.route('/homework/{tid:\w{24}}', 'homework_detail') +@app.route('/h/{tid:\w{24}}', 'homework_detail') class HomeworkDetailHandler(contest.ContestMixin, base.OperationHandler): DISCUSSIONS_PER_PAGE = 15 @@ -130,7 +130,7 @@ async def post_attend(self, *, tid: objectid.ObjectId): self.json_or_redirect(self.url) -@app.route('/homework/{tid:\w{24}}/code', 'homework_code') +@app.route('/h/{tid:\w{24}}/code', 'homework_code') class HomeworkCodeHandler(base.OperationHandler): @base.limit_rate('homework_code', 3600, 60) @base.route_argument @@ -157,7 +157,7 @@ async def get(self, *, tid: objectid.ObjectId): file_name='{}.zip'.format(tdoc['title'])) -@app.route('/homework/{tid}/{pid:-?\d+|\w{24}}', 'homework_detail_problem') +@app.route('/h/{tid}/p/{pid:[a-zA-Z0-9]+}', 'homework_detail_problem') class HomeworkDetailProblemHandler(contest.ContestMixin, base.Handler): @base.route_argument @base.require_perm(builtin.PERM_VIEW_HOMEWORK) @@ -188,7 +188,7 @@ async def get(self, *, tid: objectid.ObjectId, pid: document.convert_doc_id): page_title=pdoc['title'], path_components=path_components) -@app.route('/homework/{tid}/{pid}/submit', 'homework_detail_problem_submit') +@app.route('/h/{tid}/p/{pid}/submit', 'homework_detail_problem_submit') class HomeworkDetailProblemSubmitHandler(contest.ContestMixin, base.Handler): @base.route_argument @base.require_perm(builtin.PERM_VIEW_HOMEWORK) @@ -257,7 +257,7 @@ async def post(self, *, tid: objectid.ObjectId, pid: document.convert_doc_id, self.json_or_redirect(self.reverse_url('record_detail', rid=rid)) -@app.route('/homework/{tid}/scoreboard', 'homework_scoreboard') +@app.route('/h/{tid}/scoreboard', 'homework_scoreboard') class HomeworkScoreboardHandler(contest.ContestMixin, base.Handler): @base.route_argument @base.require_perm(builtin.PERM_VIEW_HOMEWORK) @@ -275,7 +275,7 @@ async def get(self, *, tid: objectid.ObjectId): page_title=page_title, path_components=path_components) -@app.route('/homework/{tid}/scoreboard/download/{ext}', 'homework_scoreboard_download') +@app.route('/h/{tid}/scoreboard/download/{ext}', 'homework_scoreboard_download') class HomeworkScoreboardDownloadHandler(contest.ContestMixin, base.Handler): def _export_status_as_csv(self, rows): # \r\n for notepad compatibility @@ -357,7 +357,7 @@ async def post(self, *, title: str, content: str, self.json_or_redirect(self.reverse_url('homework_detail', tid=tid)) -@app.route('/homework/{tid}/edit', 'homework_edit') +@app.route('/h/{tid}/edit', 'homework_edit') class HomeworkEditHandler(contest.ContestMixin, base.Handler): @base.require_priv(builtin.PRIV_USER_PROFILE) @base.require_perm(builtin.PERM_EDIT_HOMEWORK) diff --git a/vj4/handler/problem.py b/vj4/handler/problem.py index e67030b8e..3a3d161aa 100644 --- a/vj4/handler/problem.py +++ b/vj4/handler/problem.py @@ -90,7 +90,7 @@ async def star_unstar(self, *, pid: document.convert_doc_id, star: bool): post_unstar = functools.partialmethod(star_unstar, star=False) -@app.route('/p/random', 'problem_random') +@app.route('/problem/random', 'problem_random') class ProblemRandomHandler(base.Handler): @base.require_perm(builtin.PERM_VIEW_PROBLEM) @base.route_argument @@ -185,7 +185,7 @@ async def get(self, *, category: str): self.json_or_redirect(self.referer_or_main) -@app.route('/p/{pid:-?\d+|\w{24}}', 'problem_detail') +@app.route('/p/{pid:[a-zA-Z0-9]+}', 'problem_detail') class ProblemDetailHandler(base.OperationHandler): async def _get_related_trainings(self, pid): if self.has_perm(builtin.PERM_VIEW_TRAINING): @@ -568,7 +568,7 @@ async def get(self, *, pid: document.convert_doc_id): secret=fdoc['metadata']['secret'])) -@app.route('/p/create', 'problem_create') +@app.route('/problem/create', 'problem_create') class ProblemCreateHandler(base.Handler): @base.require_priv(builtin.PRIV_USER_PROFILE) @base.require_perm(builtin.PERM_CREATE_PROBLEM) @@ -580,16 +580,15 @@ async def get(self): @base.post_argument @base.require_csrf_token @base.sanitize - async def post(self, *, title: str, content: str, hidden: bool=False, numeric_pid: bool=False): - pid = None - if numeric_pid: + async def post(self, *, title: str, content: str, hidden: bool=False, pid: str): + if not pid: pid = await domain.inc_pid_counter(self.domain_id) pid = await problem.add(self.domain_id, title, content, self.user['_id'], hidden=hidden, pid=pid) self.json_or_redirect(self.reverse_url('problem_settings', pid=pid)) -@app.route('/p/copy', 'problem_copy') +@app.route('/problem/copy', 'problem_copy') class ProblemCopyHandler(base.Handler): MAX_PROBLEMS_PER_REQUEST = 20 @@ -791,7 +790,7 @@ async def get(self, *, pid: document.convert_doc_id): page_title=pdoc['title'], path_components=path_components) -@app.route('/p/search', 'problem_search') +@app.route('/problem/search', 'problem_search') class ProblemSearchHandler(base.Handler): @base.get_argument @base.route_argument diff --git a/vj4/locale/zh_CN.yaml b/vj4/locale/zh_CN.yaml index e7db8935b..e78c8f813 100644 --- a/vj4/locale/zh_CN.yaml +++ b/vj4/locale/zh_CN.yaml @@ -773,7 +773,8 @@ display_name: 显示名 home_domain_account: 当前域的设置 'The value `{1}` of {0} already exists.': '{0} 的值 `{1}` 已经存在。' Display name {1} you want to set is used by others.: 您想要设置的显示名 {1} 已经被其他人使用了。 -Numeric PID: 数字题号 +Leave blank to use an allocated one.: 留空以自动获取题号 +PID: 题号 Only {0} problems can be copied in one request, got {1}.: 一次请求只能复制 {0} 个题目,但是您输入了 {1} 个。 Problem is successfully copied.: 题目复制完成。 problem_copy: 复制题目 diff --git a/vj4/model/adaptor/problem.py b/vj4/model/adaptor/problem.py index f37f37997..5450959ef 100644 --- a/vj4/model/adaptor/problem.py +++ b/vj4/model/adaptor/problem.py @@ -39,6 +39,10 @@ async def add(domain_id: str, title: str, content: str, owner_uid: int, category: list=[], tag: list=[], hidden: bool=False): validator.check_title(title) validator.check_content(content) + try: + pid = int(pid) + except ValueError: + validator.check_string_pid(pid) pid = await document.add(domain_id, content, owner_uid, document.TYPE_PROBLEM, pid, title=title, data=data, category=category, tag=tag, hidden=hidden, num_submit=0, num_accept=0) diff --git a/vj4/ui/templates/components/problem.html b/vj4/ui/templates/components/problem.html index c8bbbd526..48956c659 100644 --- a/vj4/ui/templates/components/problem.html +++ b/vj4/ui/templates/components/problem.html @@ -10,7 +10,7 @@ {%- endif %} > {%- endif %} - {% if pdoc['doc_id']|string|length < 10 %}P{{ pdoc['doc_id'] }} {% endif %}{{ pdoc['title'] }} + {% if pdoc['doc_id'] is number %}P {{ pdoc['doc_id'] }}{% elif pdoc['doc_id']|string|length < 10 %} {{ pdoc['doc_id'] }} {% endif %}{{ pdoc['title'] }} {%- if not invalid %} {%- endif %} diff --git a/vj4/ui/templates/problem_edit.html b/vj4/ui/templates/problem_edit.html index ad0e614cb..5efdb2be6 100644 --- a/vj4/ui/templates/problem_edit.html +++ b/vj4/ui/templates/problem_edit.html @@ -6,19 +6,19 @@
-
+
{% if page_name == 'problem_create' %} -
+
diff --git a/vj4/util/validator.py b/vj4/util/validator.py index c6b674548..c28f2bebf 100644 --- a/vj4/util/validator.py +++ b/vj4/util/validator.py @@ -12,6 +12,8 @@ ID_RE = re.compile(r'[^\\/\s\u3000]([^\\/\n\r]*[^\\/\s\u3000])?') ROLE_RE = re.compile(r'[_0-9A-Za-z]{1,256}') DOMAIN_INVITATION_CODE_RE = re.compile(r'[0-9A-Za-z]{1,64}') +PID_RE1 = re.compile(r'[a-zA-Z0-9]*[a-zA-Z]+[a-zA-Z0-9]*') +PID_RE2 = re.compile(r'[a-zA-Z0-9]{3,23}') def is_uid(s): @@ -23,6 +25,15 @@ def check_uid(s): raise error.ValidationError('uid') +def is_string_pid(s): + return bool(PID_RE1.fullmatch(s)) and bool(PID_RE2.fullmatch(s)) + + +def check_string_pid(s): + if not is_string_pid(s): + raise error.ValidationError('pid') + + def is_uname(s): return bool(UNAME_RE.fullmatch(s)) From 316f5ce36575965d462b2f060308d0b2cf193f79 Mon Sep 17 00:00:00 2001 From: masnn Date: Mon, 13 May 2019 20:56:14 +0800 Subject: [PATCH 02/21] fix spaces --- vj4/ui/templates/components/problem.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vj4/ui/templates/components/problem.html b/vj4/ui/templates/components/problem.html index 48956c659..b0cb3eeec 100644 --- a/vj4/ui/templates/components/problem.html +++ b/vj4/ui/templates/components/problem.html @@ -10,7 +10,7 @@ {%- endif %} > {%- endif %} - {% if pdoc['doc_id'] is number %}P {{ pdoc['doc_id'] }}{% elif pdoc['doc_id']|string|length < 10 %} {{ pdoc['doc_id'] }} {% endif %}{{ pdoc['title'] }} + {% if pdoc['doc_id'] is number %}P{{ pdoc['doc_id'] }} {% elif pdoc['doc_id']|string|length < 10 %} {{ pdoc['doc_id'] }} {% endif %}{{ pdoc['title'] }} {%- if not invalid %} {%- endif %} From a6c531a96f1a175e155869ac23368085d8efb00b Mon Sep 17 00:00:00 2001 From: masnn Date: Mon, 13 May 2019 22:32:46 +0800 Subject: [PATCH 03/21] String PID validator --- vj4/handler/problem.py | 4 ++-- vj4/ui/templates/components/problem.html | 2 +- vj4/util/validator.py | 5 ++--- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/vj4/handler/problem.py b/vj4/handler/problem.py index 3a3d161aa..c483839bd 100644 --- a/vj4/handler/problem.py +++ b/vj4/handler/problem.py @@ -580,8 +580,8 @@ async def get(self): @base.post_argument @base.require_csrf_token @base.sanitize - async def post(self, *, title: str, content: str, hidden: bool=False, pid: str): - if not pid: + async def post(self, *, title: str, content: str, hidden: bool=False, pid: str=''): + if pid=='': pid = await domain.inc_pid_counter(self.domain_id) pid = await problem.add(self.domain_id, title, content, self.user['_id'], hidden=hidden, pid=pid) diff --git a/vj4/ui/templates/components/problem.html b/vj4/ui/templates/components/problem.html index b0cb3eeec..af21e06f0 100644 --- a/vj4/ui/templates/components/problem.html +++ b/vj4/ui/templates/components/problem.html @@ -10,7 +10,7 @@ {%- endif %} > {%- endif %} - {% if pdoc['doc_id'] is number %}P{{ pdoc['doc_id'] }} {% elif pdoc['doc_id']|string|length < 10 %} {{ pdoc['doc_id'] }} {% endif %}{{ pdoc['title'] }} + {% if pdoc['doc_id'] is number %}P{{ pdoc['doc_id'] }} {% elif pdoc['doc_id']|string|length < 24 %}{{ pdoc['doc_id'] }} {% endif %}{{ pdoc['title'] }} {%- if not invalid %} {%- endif %} diff --git a/vj4/util/validator.py b/vj4/util/validator.py index c28f2bebf..1d2963237 100644 --- a/vj4/util/validator.py +++ b/vj4/util/validator.py @@ -12,8 +12,7 @@ ID_RE = re.compile(r'[^\\/\s\u3000]([^\\/\n\r]*[^\\/\s\u3000])?') ROLE_RE = re.compile(r'[_0-9A-Za-z]{1,256}') DOMAIN_INVITATION_CODE_RE = re.compile(r'[0-9A-Za-z]{1,64}') -PID_RE1 = re.compile(r'[a-zA-Z0-9]*[a-zA-Z]+[a-zA-Z0-9]*') -PID_RE2 = re.compile(r'[a-zA-Z0-9]{3,23}') +PID_RE = re.compile(r'[a-zA-Z0-9]{3,23}') def is_uid(s): @@ -26,7 +25,7 @@ def check_uid(s): def is_string_pid(s): - return bool(PID_RE1.fullmatch(s)) and bool(PID_RE2.fullmatch(s)) + return bool(PID_RE.fullmatch(s)) def check_string_pid(s): From 0515be614f619f83b457bc695a58297f21e6e77c Mon Sep 17 00:00:00 2001 From: masnn Date: Tue, 14 May 2019 00:53:17 +0800 Subject: [PATCH 04/21] Help-Wanted: @/vj4/model/document.py Func need: Get doc_id by pname --- vj4/handler/problem.py | 7 +++---- vj4/locale/zh_CN.yaml | 4 ++-- vj4/model/adaptor/problem.py | 9 +++------ vj4/ui/templates/components/problem.html | 2 +- vj4/ui/templates/problem_edit.html | 6 ++---- vj4/util/validator.py | 12 ++++++------ 6 files changed, 17 insertions(+), 23 deletions(-) diff --git a/vj4/handler/problem.py b/vj4/handler/problem.py index c483839bd..da8072333 100644 --- a/vj4/handler/problem.py +++ b/vj4/handler/problem.py @@ -580,11 +580,10 @@ async def get(self): @base.post_argument @base.require_csrf_token @base.sanitize - async def post(self, *, title: str, content: str, hidden: bool=False, pid: str=''): - if pid=='': - pid = await domain.inc_pid_counter(self.domain_id) + async def post(self, *, title: str, content: str, hidden: bool=False, pname: str=None): + pid = await domain.inc_pid_counter(self.domain_id) pid = await problem.add(self.domain_id, title, content, self.user['_id'], - hidden=hidden, pid=pid) + hidden=hidden, pid=pid, pname=pname) self.json_or_redirect(self.reverse_url('problem_settings', pid=pid)) diff --git a/vj4/locale/zh_CN.yaml b/vj4/locale/zh_CN.yaml index e78c8f813..3ec6fe210 100644 --- a/vj4/locale/zh_CN.yaml +++ b/vj4/locale/zh_CN.yaml @@ -773,8 +773,8 @@ display_name: 显示名 home_domain_account: 当前域的设置 'The value `{1}` of {0} already exists.': '{0} 的值 `{1}` 已经存在。' Display name {1} you want to set is used by others.: 您想要设置的显示名 {1} 已经被其他人使用了。 -Leave blank to use an allocated one.: 留空以自动获取题号 -PID: 题号 +Leave blank to use numeric pid.: 留空以使用数字题号 +PNAME: 题号 Only {0} problems can be copied in one request, got {1}.: 一次请求只能复制 {0} 个题目,但是您输入了 {1} 个。 Problem is successfully copied.: 题目复制完成。 problem_copy: 复制题目 diff --git a/vj4/model/adaptor/problem.py b/vj4/model/adaptor/problem.py index 5450959ef..114f0b1c0 100644 --- a/vj4/model/adaptor/problem.py +++ b/vj4/model/adaptor/problem.py @@ -34,17 +34,14 @@ def get_categories(): @argmethod.wrap -async def add(domain_id: str, title: str, content: str, owner_uid: int, +async def add(domain_id: str, title: str, content: str, owner_uid: int, pname: str=None, pid: document.convert_doc_id=None, data: objectid.ObjectId=None, category: list=[], tag: list=[], hidden: bool=False): validator.check_title(title) validator.check_content(content) - try: - pid = int(pid) - except ValueError: - validator.check_string_pid(pid) + validator.check_string_pname(pname) pid = await document.add(domain_id, content, owner_uid, document.TYPE_PROBLEM, - pid, title=title, data=data, category=category, tag=tag, + pid, pname=pname, title=title, data=data, category=category, tag=tag, hidden=hidden, num_submit=0, num_accept=0) await domain.inc_user(domain_id, owner_uid, num_problems=1) return pid diff --git a/vj4/ui/templates/components/problem.html b/vj4/ui/templates/components/problem.html index af21e06f0..c601527bf 100644 --- a/vj4/ui/templates/components/problem.html +++ b/vj4/ui/templates/components/problem.html @@ -10,7 +10,7 @@ {%- endif %} > {%- endif %} - {% if pdoc['doc_id'] is number %}P{{ pdoc['doc_id'] }} {% elif pdoc['doc_id']|string|length < 24 %}{{ pdoc['doc_id'] }} {% endif %}{{ pdoc['title'] }} + {% if pdoc['pname'] %}{{ pdoc['pname'] }} {% elif pdoc['doc_id']|string|length < 24 %}P{{ pdoc['doc_id'] }} {% endif %}{{ pdoc['title'] }} {%- if not invalid %} {%- endif %} diff --git a/vj4/ui/templates/problem_edit.html b/vj4/ui/templates/problem_edit.html index 5efdb2be6..8f859dc8f 100644 --- a/vj4/ui/templates/problem_edit.html +++ b/vj4/ui/templates/problem_edit.html @@ -12,13 +12,12 @@
- {% if page_name == 'problem_create' %}
@@ -30,7 +29,6 @@
- {% endif %}
From 6c2fd17b5dc59b1ee478ddf3e9637daebc80cd81 Mon Sep 17 00:00:00 2001 From: masnn Date: Wed, 15 May 2019 23:30:26 +0800 Subject: [PATCH 16/21] 0x0b --- vj4/ui/templates/components/problem.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/vj4/ui/templates/components/problem.html b/vj4/ui/templates/components/problem.html index ab471d3d4..36f4a28b5 100644 --- a/vj4/ui/templates/components/problem.html +++ b/vj4/ui/templates/components/problem.html @@ -2,11 +2,11 @@ {%- if not invalid %} Date: Thu, 16 May 2019 00:31:45 +0800 Subject: [PATCH 17/21] 0x0c --- vj4/model/document.py | 1 + 1 file changed, 1 insertion(+) diff --git a/vj4/model/document.py b/vj4/model/document.py index 3b5b83e63..db38c4429 100644 --- a/vj4/model/document.py +++ b/vj4/model/document.py @@ -3,6 +3,7 @@ from pymongo import ReturnDocument from vj4 import db +from vj4 import error from vj4.util import argmethod TYPE_PROBLEM = 10 From a18e83a10d85f3adbe4de55050c73c2ea1145dba Mon Sep 17 00:00:00 2001 From: masnn Date: Thu, 16 May 2019 02:47:58 +0000 Subject: [PATCH 18/21] 0x0d --- vj4/handler/problem.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/vj4/handler/problem.py b/vj4/handler/problem.py index 9fdc747fa..0af967a88 100644 --- a/vj4/handler/problem.py +++ b/vj4/handler/problem.py @@ -665,12 +665,12 @@ async def get(self, *, pid: document.convert_doc_id): @base.post_argument @base.require_csrf_token @base.sanitize - async def post(self, *, pid: document.convert_doc_id, title: str, content: str): + async def post(self, *, pid: document.convert_doc_id, title: str, content: str, pname: str=None): pdoc = await problem.get(self.domain_id, pid) if not self.own(pdoc, builtin.PERM_EDIT_PROBLEM_SELF): self.check_perm(builtin.PERM_EDIT_PROBLEM) - await problem.edit(self.domain_id, pdoc['doc_id'], title=title, content=content) - self.json_or_redirect(self.reverse_url('problem_detail', pid=pid)) + pdoc = await problem.edit(self.domain_id, pdoc['doc_id'], title=title, content=content, pname=pname) + self.json_or_redirect(self.reverse_url('problem_detail', pid=pdoc.get('pname', pdoc['doc_id']))) @app.route('/p/{pid}/settings', 'problem_settings') From c6cf31574425ef4639592c5d085608ccf90439db Mon Sep 17 00:00:00 2001 From: masnn Date: Fri, 24 May 2019 23:13:54 +0800 Subject: [PATCH 19/21] fix solution --- vj4/model/adaptor/problem.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/vj4/model/adaptor/problem.py b/vj4/model/adaptor/problem.py index 203316687..b397c3d81 100644 --- a/vj4/model/adaptor/problem.py +++ b/vj4/model/adaptor/problem.py @@ -92,13 +92,19 @@ async def get(domain_id: str, pid: document.convert_doc_id, uid: int = None): @argmethod.wrap -async def edit(domain_id: str, pid: document.convert_doc_id, **kwargs): +async def edit(domain_id: str, pid: document.convert_doc_id, pname: str=None, **kwargs): pid = await document.get_pid(domain_id, pid) if 'title' in kwargs: - validator.check_title(kwargs['title']) + validator.check_title(kwargs['title']) if 'content' in kwargs: - validator.check_content(kwargs['content']) - pdoc = await document.set(domain_id, document.TYPE_PROBLEM, pid, **kwargs) + validator.check_content(kwargs['content']) + if pname == "": + pname = None + if pname: + validator.check_string_pname(pname) + pid = await document.set(domain_id, document.TYPE_PROBLEM, pid, pname=pname, **kwargs) + else: + pdoc = await document.set(domain_id, document.TYPE_PROBLEM, pid, **kwargs) if not pdoc: raise error.DocumentNotFoundError(domain_id, document.TYPE_PROBLEM, pid) return pdoc @@ -205,8 +211,7 @@ async def set_solution(domain_id: str, psid: document.convert_doc_id, content: s return psdoc -async def get_multi_solution(domain_id: str, pid: document.convert_doc_id, fields=None): - pid = await document.get_pid(domain_id, pid) +def get_multi_solution(domain_id: str, pid: document.convert_doc_id, fields=None): return document.get_multi(domain_id=domain_id, doc_type=document.TYPE_PROBLEM_SOLUTION, parent_doc_type=document.TYPE_PROBLEM, From e3e2e6f8d710efd40688a34a830c4f381e782fbf Mon Sep 17 00:00:00 2001 From: masnn Date: Mon, 27 May 2019 09:35:20 +0800 Subject: [PATCH 20/21] bug fix --- vj4/model/adaptor/problem.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vj4/model/adaptor/problem.py b/vj4/model/adaptor/problem.py index b397c3d81..e055e4a1c 100644 --- a/vj4/model/adaptor/problem.py +++ b/vj4/model/adaptor/problem.py @@ -102,7 +102,7 @@ async def edit(domain_id: str, pid: document.convert_doc_id, pname: str=None, ** pname = None if pname: validator.check_string_pname(pname) - pid = await document.set(domain_id, document.TYPE_PROBLEM, pid, pname=pname, **kwargs) + pdoc = await document.set(domain_id, document.TYPE_PROBLEM, pid, pname=pname, **kwargs) else: pdoc = await document.set(domain_id, document.TYPE_PROBLEM, pid, **kwargs) if not pdoc: From 3132019df5e2441b438d3432a8d28c19add1c8da Mon Sep 17 00:00:00 2001 From: masnn Date: Wed, 29 May 2019 22:25:00 +0800 Subject: [PATCH 21/21] to lowercase --- vj4/locale/zh_CN.yaml | 2 +- vj4/ui/templates/problem_edit.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/vj4/locale/zh_CN.yaml b/vj4/locale/zh_CN.yaml index 3ec6fe210..454014898 100644 --- a/vj4/locale/zh_CN.yaml +++ b/vj4/locale/zh_CN.yaml @@ -774,7 +774,7 @@ home_domain_account: 当前域的设置 'The value `{1}` of {0} already exists.': '{0} 的值 `{1}` 已经存在。' Display name {1} you want to set is used by others.: 您想要设置的显示名 {1} 已经被其他人使用了。 Leave blank to use numeric pid.: 留空以使用数字题号 -PNAME: 题号 +pname: 题号 Only {0} problems can be copied in one request, got {1}.: 一次请求只能复制 {0} 个题目,但是您输入了 {1} 个。 Problem is successfully copied.: 题目复制完成。 problem_copy: 复制题目 diff --git a/vj4/ui/templates/problem_edit.html b/vj4/ui/templates/problem_edit.html index 1d6382187..20dcbca30 100644 --- a/vj4/ui/templates/problem_edit.html +++ b/vj4/ui/templates/problem_edit.html @@ -14,7 +14,7 @@