From f2f124e462410025433fd0b5cfa80bf69a2dfd8b Mon Sep 17 00:00:00 2001 From: sxw Date: Sat, 5 Dec 2015 13:22:21 +0800 Subject: [PATCH 01/27] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=8A=A0=E5=B0=8F?= =?UTF-8?q?=E7=BB=84=E8=AF=B7=E6=B1=82=E7=9A=84=E9=97=AE=E9=A2=98=EF=BC=8C?= =?UTF-8?q?=E6=8A=8Agroup=3D[]=E6=94=B9=E6=88=90group=5F=5Fin=3D[],?= =?UTF-8?q?=E5=90=A6=E5=88=99=E6=97=A0=E6=B3=95=E8=BF=94=E5=9B=9E=E6=AD=A3?= =?UTF-8?q?=E7=A1=AE=E7=9A=84=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- group/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/group/views.py b/group/views.py index a4a31236..23e59ad3 100644 --- a/group/views.py +++ b/group/views.py @@ -217,7 +217,7 @@ class JoinGroupRequestAdminAPIView(APIView, GroupAPIViewBase): --- response_serializer: JoinGroupRequestSerializer """ - requests = JoinGroupRequest.objects.filter(group=Group.objects.filter(admin=request.user, visible=True), + requests = JoinGroupRequest.objects.filter(group__in=Group.objects.filter(admin=request.user, visible=True), status=False) return paginate(request, requests, JoinGroupRequestSerializer) From c2597a6647eee6401d5e49851881c78396f5bd91 Mon Sep 17 00:00:00 2001 From: sxw Date: Sat, 5 Dec 2015 13:26:09 +0800 Subject: [PATCH 02/27] =?UTF-8?q?=E5=AE=8C=E6=88=90=E5=90=8E=E5=8F=B0?= =?UTF-8?q?=E5=B0=8F=E7=BB=84=E7=AE=A1=E7=90=86=E7=9B=B8=E5=85=B3=E5=86=85?= =?UTF-8?q?=E5=AE=B9=EF=BC=8C=E6=B7=BB=E5=8A=A0=E6=96=B0=E5=BB=BA=E5=B0=8F?= =?UTF-8?q?=E7=BB=84UI=EF=BC=8C=E6=B7=BB=E5=8A=A0=E5=88=B0=E5=B0=8F?= =?UTF-8?q?=E7=BB=84=E8=AF=A6=E7=BB=86=E7=9A=84=E8=BF=9E=E6=8E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- static/src/js/app/admin/admin.js | 9 +---- static/src/js/app/admin/group/group.js | 35 +++++++++++++++++--- static/src/js/app/admin/group/groupDetail.js | 1 + static/src/js/app/oj/group/group.js | 3 +- template/src/admin/group/group.html | 29 ++++++++++++++++ template/src/admin/group/group_detail.html | 4 +-- 6 files changed, 66 insertions(+), 15 deletions(-) diff --git a/static/src/js/app/admin/admin.js b/static/src/js/app/admin/admin.js index 72c8fd6b..2c527de7 100644 --- a/static/src/js/app/admin/admin.js +++ b/static/src/js/app/admin/admin.js @@ -103,14 +103,7 @@ require(["jquery", "avalon", "csrfToken", "bsAlert", "bootstrap"], function ($, } }); - vm.$watch("showGroupDetailPage", function (groupId) { - vm.groupId = groupId; - vm.template_url = "template/group/group_detail.html"; - }); - - vm.$watch("showGroupListPage", function () { - vm.template_url = "template/group/group.html"; - }); + avalon.scan(); diff --git a/static/src/js/app/admin/group/group.js b/static/src/js/app/admin/group/group.js index 425e4bbf..f97e809c 100644 --- a/static/src/js/app/admin/group/group.js +++ b/static/src/js/app/admin/group/group.js @@ -1,7 +1,30 @@ -require(["jquery", "avalon", "csrfToken", "bsAlert"], function ($, avalon, csrfTokenHeader, bsAlert) { +require(["jquery", "avalon", "csrfToken", "bsAlert", "validator"], function ($, avalon, csrfTokenHeader, bsAlert) { avalon.ready(function () { - //avalon.vmodels.group = null; + $('#add-group-form').validator().on('submit', function (e) { + if (!e.isDefaultPrevented()) { + var name = vm.name; + var description = vm.description; + var join_group_setting = vm.group_type; + $.ajax({ + beforeSend: csrfTokenHeader, + url: "/api/admin/group/", + method: "post", + data: {name: name, description: description, join_group_setting: join_group_setting}, + dataType: "json", + success: function (data) { + if (!data.code) { + getPageData(1); + bsAlert("添加成功"); + } + else { + bsAlert(data.data); + } + } + }); + return false; + } + }) if (avalon.vmodels.group) { var vm = avalon.vmodels.group; } @@ -16,7 +39,9 @@ require(["jquery", "avalon", "csrfToken", "bsAlert"], function ($, avalon, csrfT page: 1, // 当前页数 totalPage: 1, // 总页数 keyword: "", - + name: "", + description: "", + group_type: 0, getNext: function () { if (!vm.nextPage) return; @@ -42,8 +67,10 @@ require(["jquery", "avalon", "csrfToken", "bsAlert"], function ($, avalon, csrfT getGroupSettingString: function (setting) { return {0: "允许任何人加入", 1: "提交请求后管理员审核", 2: "不允许任何人加入"}[setting] }, + showGroupDetailPage: function (groupId) { - vm.$fire("up!showGroupDetailPage", groupId); + avalon.vmodels.admin.groupId = groupId; + avalon.vmodels.admin.template_url = "template/group/group_detail.html"; } }); } diff --git a/static/src/js/app/admin/group/groupDetail.js b/static/src/js/app/admin/group/groupDetail.js index de4a0ff5..7b7e3f38 100644 --- a/static/src/js/app/admin/group/groupDetail.js +++ b/static/src/js/app/admin/group/groupDetail.js @@ -53,6 +53,7 @@ require(["jquery", "avalon", "csrfToken", "bsAlert", "validator"], function ($, }) }, showGroupListPage: function () { + avalon.vmodels.admin.template_url = "template/group/group.html"; vm.$fire("up!showGroupListPage"); } }); diff --git a/static/src/js/app/oj/group/group.js b/static/src/js/app/oj/group/group.js index d9371427..66bb7335 100644 --- a/static/src/js/app/oj/group/group.js +++ b/static/src/js/app/oj/group/group.js @@ -3,9 +3,10 @@ require(["jquery", "csrfToken", "bsAlert"], function ($, csrfTokenHeader, bsAler var message; if ($("#applyMessage").length) { message = $("#applyMessage").val(); - if (!message) + if (!message) { bsAlert("提交失败,请填写申请信息!"); return false; + } } var groupId = window.location.pathname.split("/")[2]; diff --git a/template/src/admin/group/group.html b/template/src/admin/group/group.html index 84614c9b..3dcb7eaa 100644 --- a/template/src/admin/group/group.html +++ b/template/src/admin/group/group.html @@ -38,6 +38,35 @@ +

创建小组

+
+
+
+ +
+
+
+
+
+ +
+
+
+ +
+
+ + 允许任何人加入 + 提交请求后管理员审核 + 不允许任何人加入 + +
+ +
+
\ No newline at end of file diff --git a/template/src/admin/group/group_detail.html b/template/src/admin/group/group_detail.html index b75f0efa..a6e0a3b0 100644 --- a/template/src/admin/group/group_detail.html +++ b/template/src/admin/group/group_detail.html @@ -5,7 +5,7 @@ aria-hidden="true">← 返回 -

小组成员管理

+

小组成员管理

@@ -31,7 +31,7 @@ -

修改小组信息

+

修改小组信息

From 42a289d656f30be0de725f27536d4155c8824a23 Mon Sep 17 00:00:00 2001 From: sxw Date: Sat, 5 Dec 2015 13:26:51 +0800 Subject: [PATCH 03/27] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=A8=A1=E6=9D=BF?= =?UTF-8?q?=E4=B8=80=E7=82=B9=E6=98=BE=E7=A4=BA=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- template/src/oj/group/group.html | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/template/src/oj/group/group.html b/template/src/oj/group/group.html index c860fdf8..3d9fa23c 100644 --- a/template/src/oj/group/group.html +++ b/template/src/oj/group/group.html @@ -35,11 +35,7 @@
{% endif %}
- +
From ddb609ae6bd8c53d7d90194bb3ada567d586db72 Mon Sep 17 00:00:00 2001 From: sxw Date: Sat, 5 Dec 2015 15:46:54 +0800 Subject: [PATCH 04/27] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=AF=B9=E6=9C=89?= =?UTF-8?q?=E5=AF=86=E7=A0=81=E7=9A=84=E5=B0=8F=E7=BB=84=E8=B5=9B=E7=9A=84?= =?UTF-8?q?=E5=AF=86=E7=A0=81=E9=AA=8C=E8=AF=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contest/decorators.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contest/decorators.py b/contest/decorators.py index 01297f67..63884119 100644 --- a/contest/decorators.py +++ b/contest/decorators.py @@ -9,7 +9,7 @@ from django.core.urlresolvers import reverse from utils.shortcuts import error_response, error_page from account.models import SUPER_ADMIN -from .models import (Contest, PASSWORD_PROTECTED_CONTEST, PUBLIC_CONTEST, GROUP_CONTEST, +from .models import (Contest, PASSWORD_PROTECTED_CONTEST, PASSWORD_PROTECTED_GROUP_CONTEST, PUBLIC_CONTEST, GROUP_CONTEST, CONTEST_ENDED, CONTEST_NOT_START, CONTEST_UNDERWAY) @@ -66,7 +66,7 @@ def check_user_contest_permission(func): return error_page(request, u"比赛不存在") # 有密码的公开赛 - if contest.contest_type == PASSWORD_PROTECTED_CONTEST: + if contest.contest_type == PASSWORD_PROTECTED_CONTEST or contest.contest_type == PASSWORD_PROTECTED_GROUP_CONTEST: # 没有输入过密码 if contest.id not in request.session.get("contests", []): if request.is_ajax(): From e6af2734adfd387f5ef6c5eacc0c7c2e600b0edc Mon Sep 17 00:00:00 2001 From: sxw Date: Sat, 5 Dec 2015 15:47:25 +0800 Subject: [PATCH 05/27] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=96=B0=E7=9A=84?= =?UTF-8?q?=E6=AF=94=E8=B5=9B=E7=B1=BB=E5=9E=8B=E2=80=94=E2=80=94=E2=80=94?= =?UTF-8?q?=E2=80=94=E6=9C=89=E5=AF=86=E7=A0=81=E7=9A=84=E5=B0=8F=E7=BB=84?= =?UTF-8?q?=E8=B5=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contest/models.py | 1 + 1 file changed, 1 insertion(+) diff --git a/contest/models.py b/contest/models.py index 2213f43e..51f5ea50 100644 --- a/contest/models.py +++ b/contest/models.py @@ -13,6 +13,7 @@ from judge.judger.result import result GROUP_CONTEST = 0 PUBLIC_CONTEST = 1 PASSWORD_PROTECTED_CONTEST = 2 +PASSWORD_PROTECTED_GROUP_CONTEST = 3 CONTEST_NOT_START = 1 CONTEST_ENDED = -1 From f7f2a327ea21e99dd1a55f5f4cd272da4200b687 Mon Sep 17 00:00:00 2001 From: sxw Date: Sat, 5 Dec 2015 15:48:02 +0800 Subject: [PATCH 06/27] =?UTF-8?q?=E5=AF=B9=E6=96=B0=E7=9A=84=E6=AF=94?= =?UTF-8?q?=E8=B5=9B=E7=B1=BB=E5=9E=8B=EF=BC=8C=E6=9C=89=E5=AF=86=E7=A0=81?= =?UTF-8?q?=E7=9A=84=E5=B0=8F=E7=BB=84=E8=B5=9B=E7=9A=84=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contest/views.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/contest/views.py b/contest/views.py index 87378db5..be6630e5 100644 --- a/contest/views.py +++ b/contest/views.py @@ -23,7 +23,7 @@ from submission.models import Submission from problem.models import Problem from .models import (Contest, ContestProblem, CONTEST_ENDED, CONTEST_NOT_START, CONTEST_UNDERWAY, ContestRank) -from .models import GROUP_CONTEST, PUBLIC_CONTEST, PASSWORD_PROTECTED_CONTEST +from .models import GROUP_CONTEST, PUBLIC_CONTEST, PASSWORD_PROTECTED_CONTEST, PASSWORD_PROTECTED_GROUP_CONTEST from .decorators import check_user_contest_permission from .serializers import (CreateContestSerializer, ContestSerializer, EditContestSerializer, CreateContestProblemSerializer, ContestProblemSerializer, @@ -50,11 +50,11 @@ class ContestAdminAPIView(APIView): if request.user.admin_type != SUPER_ADMIN: return error_response(u"只有超级管理员才可创建公开赛") - if data["contest_type"] == PASSWORD_PROTECTED_CONTEST: + if data["contest_type"] in [PASSWORD_PROTECTED_CONTEST, PASSWORD_PROTECTED_GROUP_CONTEST]: if not data["password"]: - return error_response(u"此比赛为有密码的公开赛,密码不可为空") + return error_response(u"此比赛为有密码的比赛,密码不可为空") # 没有密码的公开赛 没有密码的小组赛 - elif data["contest_type"] == GROUP_CONTEST: + if data["contest_type"] == GROUP_CONTEST or data["contest_type"] == PASSWORD_PROTECTED_GROUP_CONTEST: if request.user.admin_type == SUPER_ADMIN: groups = Group.objects.filter(id__in=data["groups"]) else: @@ -107,7 +107,7 @@ class ContestAdminAPIView(APIView): if data["contest_type"] == PASSWORD_PROTECTED_CONTEST: if not data["password"]: return error_response(u"此比赛为有密码的公开赛,密码不可为空") - elif data["contest_type"] == GROUP_CONTEST: + elif data["contest_type"] == GROUP_CONTEST or data["contest_type"] == PASSWORD_PROTECTED_GROUP_CONTEST: if request.user.admin_type == SUPER_ADMIN: groups = Group.objects.filter(id__in=data["groups"]) else: From bbf3b42edc24d1b5f37f528bd222bd4230873021 Mon Sep 17 00:00:00 2001 From: sxw Date: Sat, 5 Dec 2015 15:49:54 +0800 Subject: [PATCH 07/27] =?UTF-8?q?=E5=AF=B9=E5=90=8E=E5=8F=B0=E6=AF=94?= =?UTF-8?q?=E8=B5=9B=E7=AE=A1=E7=90=86=E9=A1=B5=E9=9D=A2=E7=9A=84=E4=BF=AE?= =?UTF-8?q?=E6=94=B9=EF=BC=8C=E5=AF=B9=E6=9C=89=E5=AF=86=E7=A0=81=E7=9A=84?= =?UTF-8?q?=E5=B0=8F=E7=BB=84=E8=B5=9B=E7=9A=84=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- static/src/js/app/admin/contest/addContest.js | 4 ++++ .../src/js/app/admin/contest/editContest.js | 6 +++++- template/src/admin/contest/add_contest.html | 20 +++++++++++++------ template/src/admin/contest/edit_contest.html | 20 +++++++++++++------ 4 files changed, 37 insertions(+), 13 deletions(-) diff --git a/static/src/js/app/admin/contest/addContest.js b/static/src/js/app/admin/contest/addContest.js index e84f6b08..0fd6f9ff 100644 --- a/static/src/js/app/admin/contest/addContest.js +++ b/static/src/js/app/admin/contest/addContest.js @@ -22,6 +22,10 @@ require(["jquery", "avalon", "editor", "uploader", "bsAlert", "csrfToken", "date selectedGroups.push(vm.allGroups[i].id); } } + if (vm.password) { + ajaxData.password = vm.password; + ajaxData.contest_type = 3; + } ajaxData.groups = selectedGroups; } else { diff --git a/static/src/js/app/admin/contest/editContest.js b/static/src/js/app/admin/contest/editContest.js index 67a027c3..a4978177 100644 --- a/static/src/js/app/admin/contest/editContest.js +++ b/static/src/js/app/admin/contest/editContest.js @@ -23,6 +23,10 @@ require(["jquery", "avalon", "editor", "uploader", "bsAlert", "csrfToken", "date selectedGroups.push(vm.allGroups[i].id); } } + if (vm.password) { + ajaxData.password = vm.password; + ajaxData.contest_type = 3; + } ajaxData.groups = selectedGroups; } else { @@ -131,7 +135,7 @@ require(["jquery", "avalon", "editor", "uploader", "bsAlert", "csrfToken", "date vm.startTime = contest.start_time.substring(0, 16).replace("T", " "); vm.endTime = contest.end_time.substring(0, 16).replace("T", " "); vm.password = contest.password; - if (contest.contest_type == 0) { //contest_type == 0, 小组内比赛 + if (contest.contest_type == 0 || contest.contest_type == 3) { //contest_type == 0, 小组内比赛 vm.isGlobal = false; for (var i = 0; i < vm.allGroups.length; i++) { vm.allGroups[i].isSelected = false; diff --git a/template/src/admin/contest/add_contest.html b/template/src/admin/contest/add_contest.html index 010b73eb..e9733161 100644 --- a/template/src/admin/contest/add_contest.html +++ b/template/src/admin/contest/add_contest.html @@ -46,13 +46,13 @@
@@ -60,10 +60,18 @@
-
- -
- +
+
+ +
+ +
+
+
+ +
+ +
diff --git a/template/src/admin/contest/edit_contest.html b/template/src/admin/contest/edit_contest.html index 08f7c09d..3e506036 100644 --- a/template/src/admin/contest/edit_contest.html +++ b/template/src/admin/contest/edit_contest.html @@ -55,13 +55,13 @@
@@ -69,11 +69,19 @@
-
- +
+
+ -
- +
+ +
+
+
+ +
+ +
From 13c74797c418c8ae642f984a42103e8dbc05a957 Mon Sep 17 00:00:00 2001 From: sxw Date: Sat, 5 Dec 2015 16:03:05 +0800 Subject: [PATCH 08/27] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=B0=8F=E7=BB=84?= =?UTF-8?q?=E9=82=80=E8=AF=B7=E8=B5=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- template/src/oj/contest/_contest_header.html | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/template/src/oj/contest/_contest_header.html b/template/src/oj/contest/_contest_header.html index 3fcac447..2e1fdf3c 100644 --- a/template/src/oj/contest/_contest_header.html +++ b/template/src/oj/contest/_contest_header.html @@ -21,7 +21,7 @@
{% ifequal contest.contest_type 0 %} - + {% endifequal %} {% ifequal contest.contest_type 1 %} @@ -29,6 +29,9 @@ {% ifequal contest.contest_type 2 %} {% endifequal %} + {% ifequal contest.contest_type 3 %} + + {% endifequal %} From 8ae485a35cd51cdbf2b874ded9ca5981a98b3005 Mon Sep 17 00:00:00 2001 From: sxw Date: Sat, 5 Dec 2015 16:13:55 +0800 Subject: [PATCH 09/27] =?UTF-8?q?contest=20list=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E5=B0=8F=E7=BB=84=E9=82=80=E8=AF=B7=E8=B5=9B=E5=92=8C=E7=A7=81?= =?UTF-8?q?=E6=9C=89=E5=B0=8F=E7=BB=84=E8=B5=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- template/src/oj/contest/contest_list.html | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/template/src/oj/contest/contest_list.html b/template/src/oj/contest/contest_list.html index 92a59d87..00fde88b 100644 --- a/template/src/oj/contest/contest_list.html +++ b/template/src/oj/contest/contest_list.html @@ -37,7 +37,7 @@ {% ifequal item.contest_type 0 %} - + {% endifequal %} {% ifequal item.contest_type 1 %} @@ -45,6 +45,9 @@ {% ifequal item.contest_type 2 %} {% endifequal %} + {% ifequal item.contest_type 3 %} + + {% endifequal %} From 85b2fef22dc07e29119ec4757a660c1b5bd323f7 Mon Sep 17 00:00:00 2001 From: sxw Date: Sat, 5 Dec 2015 16:19:22 +0800 Subject: [PATCH 10/27] =?UTF-8?q?=E9=AA=8C=E8=AF=81=E5=B0=8F=E7=BB=84?= =?UTF-8?q?=E9=82=80=E8=AF=B7=E8=B5=9B=E5=AF=86=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contest/decorators.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/contest/decorators.py b/contest/decorators.py index 63884119..ebee4823 100644 --- a/contest/decorators.py +++ b/contest/decorators.py @@ -66,7 +66,7 @@ def check_user_contest_permission(func): return error_page(request, u"比赛不存在") # 有密码的公开赛 - if contest.contest_type == PASSWORD_PROTECTED_CONTEST or contest.contest_type == PASSWORD_PROTECTED_GROUP_CONTEST: + if contest.contest_type == PASSWORD_PROTECTED_CONTEST: # 没有输入过密码 if contest.id not in request.session.get("contests", []): if request.is_ajax(): @@ -83,7 +83,15 @@ def check_user_contest_permission(func): else: return render(request, "oj/contest/no_contest_permission.html", {"reason": "group_limited", "show_tab": False, "contest": contest}) - + + if contest.contest_type == PASSWORD_PROTECTED_GROUP_CONTEST: + if not contest.groups.filter(id__in=request.user.group_set.all()).exists(): + if contest.id not in request.session.get("contests", []): + if request.is_ajax(): + return error_response(u"请先输入密码") + else: + return render(request, "oj/contest/no_contest_permission.html", + {"reason": "password_protect", "show_tab": False, "contest": contest}) # 比赛没有开始 if contest.status == CONTEST_NOT_START: if request.is_ajax(): From 7af2c433c4a62b1b6c260d4fa78fea7e4115c992 Mon Sep 17 00:00:00 2001 From: sxw Date: Sat, 5 Dec 2015 16:29:07 +0800 Subject: [PATCH 11/27] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contest/decorators.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/contest/decorators.py b/contest/decorators.py index ebee4823..0dad16fd 100644 --- a/contest/decorators.py +++ b/contest/decorators.py @@ -87,11 +87,12 @@ def check_user_contest_permission(func): if contest.contest_type == PASSWORD_PROTECTED_GROUP_CONTEST: if not contest.groups.filter(id__in=request.user.group_set.all()).exists(): if contest.id not in request.session.get("contests", []): - if request.is_ajax(): - return error_response(u"请先输入密码") - else: - return render(request, "oj/contest/no_contest_permission.html", - {"reason": "password_protect", "show_tab": False, "contest": contest}) + if request.is_ajax(): + return error_response(u"请先输入密码") + else: + return render(request, "oj/contest/no_contest_permission.html", + {"reason": "password_protect", "show_tab": False, "contest": contest}) + # 比赛没有开始 if contest.status == CONTEST_NOT_START: if request.is_ajax(): From 1381797183caa2db8c13ec328cc4686dc99ab51e Mon Sep 17 00:00:00 2001 From: sxw Date: Sun, 6 Dec 2015 10:23:01 +0800 Subject: [PATCH 12/27] =?UTF-8?q?=E5=90=A7if=20=E3=80=82=E3=80=82=E3=80=82?= =?UTF-8?q?or...=E6=94=B9=E6=88=90=20if=20in?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contest/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contest/views.py b/contest/views.py index be6630e5..22539558 100644 --- a/contest/views.py +++ b/contest/views.py @@ -107,7 +107,7 @@ class ContestAdminAPIView(APIView): if data["contest_type"] == PASSWORD_PROTECTED_CONTEST: if not data["password"]: return error_response(u"此比赛为有密码的公开赛,密码不可为空") - elif data["contest_type"] == GROUP_CONTEST or data["contest_type"] == PASSWORD_PROTECTED_GROUP_CONTEST: + elif data["contest_type"] in [GROUP_CONTEST, PASSWORD_PROTECTED_GROUP_CONTEST]: if request.user.admin_type == SUPER_ADMIN: groups = Group.objects.filter(id__in=data["groups"]) else: From 7d358c9e4c4b24930f0667fdfd8726021e84db99 Mon Sep 17 00:00:00 2001 From: sxw Date: Tue, 8 Dec 2015 14:31:43 +0800 Subject: [PATCH 13/27] =?UTF-8?q?=E5=9C=A8UserProfile=E4=B8=AD=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E5=AD=A6=E5=8F=B7=E5=AD=97=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../migrations/0015_userprofile_student_id.py | 20 +++++++++++++++++++ account/models.py | 1 + 2 files changed, 21 insertions(+) create mode 100644 account/migrations/0015_userprofile_student_id.py diff --git a/account/migrations/0015_userprofile_student_id.py b/account/migrations/0015_userprofile_student_id.py new file mode 100644 index 00000000..cb8991bf --- /dev/null +++ b/account/migrations/0015_userprofile_student_id.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9 on 2015-12-08 06:22 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('account', '0014_auto_20151110_1037'), + ] + + operations = [ + migrations.AddField( + model_name='userprofile', + name='student_id', + field=models.CharField(blank=True, max_length=15, null=True), + ), + ] diff --git a/account/models.py b/account/models.py index e08ff6c8..395fc275 100644 --- a/account/models.py +++ b/account/models.py @@ -70,6 +70,7 @@ class UserProfile(models.Model): problems_status = JSONField(default={}) phone_number = models.CharField(max_length=15, blank=True, null=True) school = models.CharField(max_length=200, blank=True, null=True) + student_id = models.CharField(max_length=15, blank=True, null=True) class Meta: From 2d6be12a2f355fe55a206a761e5974e5d6070f6e Mon Sep 17 00:00:00 2001 From: sxw Date: Tue, 8 Dec 2015 14:33:40 +0800 Subject: [PATCH 14/27] =?UTF-8?q?=E9=92=88=E5=AF=B9=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E5=AD=A6=E5=8F=B7=E5=AD=97=E6=AE=B5=E5=AF=B9=E9=A1=B5=E9=9D=A2?= =?UTF-8?q?=E7=9A=84=E4=B8=80=E4=BA=9B=E4=BF=AE=E6=94=B9=EF=BC=8C=E6=B3=A8?= =?UTF-8?q?=E5=86=8C=E6=98=AF=E5=AD=A6=E6=A0=A1=E4=B8=BA=E9=9D=92=E5=B2=9B?= =?UTF-8?q?=E5=A4=A7=E5=AD=A6=E5=88=99=E6=98=BE=E7=A4=BA=E5=AD=A6=E5=8F=B7?= =?UTF-8?q?=E5=AD=97=E6=AE=B5=EF=BC=8C=E5=9C=A8user=20settings=E9=A1=B5?= =?UTF-8?q?=E9=9D=A2=E6=98=BE=E7=A4=BA=E5=AD=A6=E5=8F=B7=EF=BC=8C=E5=B9=B6?= =?UTF-8?q?=E6=8F=90=E4=BE=9B=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- account/serializers.py | 4 +++- account/views.py | 3 ++- static/src/js/app/oj/account/register.js | 14 +++++++++++++- static/src/js/app/oj/account/settings.js | 5 +++-- template/src/oj/account/register.html | 6 +++++- template/src/oj/account/settings.html | 9 ++++++++- 6 files changed, 34 insertions(+), 7 deletions(-) diff --git a/account/serializers.py b/account/serializers.py index 0aac07ae..0d92ae7e 100644 --- a/account/serializers.py +++ b/account/serializers.py @@ -25,6 +25,7 @@ class UserRegisterSerializer(serializers.Serializer): password = serializers.CharField(max_length=30, min_length=6) email = serializers.EmailField(max_length=254) captcha = serializers.CharField(max_length=4, min_length=4) + student_id = serializers.CharField(max_length=15, required=False, default=None) class UserChangePasswordSerializer(serializers.Serializer): @@ -74,6 +75,7 @@ class EditUserProfileSerializer(serializers.Serializer): codeforces_username = serializers.CharField(max_length=30, required=False, allow_blank=True, default='') school = serializers.CharField(max_length=200, required=False, allow_blank=True, default='') phone_number = serializers.CharField(max_length=15, required=False, allow_blank=True, default='') + student_id = serializers.CharField(max_length=15, required=False, default="") class UserProfileSerializer(serializers.ModelSerializer): @@ -81,4 +83,4 @@ class UserProfileSerializer(serializers.ModelSerializer): class Meta: model = UserProfile fields = ["avatar", "blog", "mood", "hduoj_username", "bestcoder_username", "codeforces_username", - "rank", "accepted_number", "submissions_number", "problems_status", "phone_number", "school"] + "rank", "accepted_number", "submissions_number", "problems_status", "phone_number", "school", "student_id"] diff --git a/account/views.py b/account/views.py index 2ba5739c..d1e6b2a6 100644 --- a/account/views.py +++ b/account/views.py @@ -97,7 +97,7 @@ class UserRegisterAPIView(APIView): email=data["email"]) user.set_password(data["password"]) user.save() - UserProfile.objects.create(user=user, school=data["school"]) + UserProfile.objects.create(user=user, school=data["school"], student_id=data["student_id"]) return success_response(u"注册成功!") else: return serializer_invalid_response(serializer) @@ -262,6 +262,7 @@ class UserProfileAPIView(APIView): user_profile.codeforces_username = data["codeforces_username"] user_profile.blog = data["blog"] user_profile.school = data["school"] + user_profile.student_id = data["student_id"] user_profile.phone_number = data["phone_number"] user_profile.save() return success_response(u"修改成功") diff --git a/static/src/js/app/oj/account/register.js b/static/src/js/app/oj/account/register.js index ef23a38c..0557cfbd 100644 --- a/static/src/js/app/oj/account/register.js +++ b/static/src/js/app/oj/account/register.js @@ -1,16 +1,18 @@ require(["jquery", "bsAlert", "csrfToken", "validator"], function ($, bsAlert, csrfTokenHeader) { + $("#stu_id").hide(); $('form').validator().on('submit', function (e) { if (!e.isDefaultPrevented()) { var username = $("#username").val(); var realName = $("#real_name").val(); var school = $('#school').val(); + var student_id = $('#student_id').val(); var password = $("#password").val(); var email = $("#email").val(); var captcha = $("#captcha").val(); $.ajax({ beforeSend: csrfTokenHeader, url: "/api/register/", - data: {username: username, school: school, real_name: realName, password: password, email: email, captcha:captcha}, + data: {username: username, school: school, student_id: student_id, real_name: realName, password: password, email: email, captcha:captcha}, dataType: "json", method: "post", success: function (data) { @@ -29,6 +31,16 @@ require(["jquery", "bsAlert", "csrfToken", "validator"], function ($, bsAlert, c return false; } }); + + $("#school").blur(function () { + if ($("#school").val() == "青岛大学") { + $("#stu_id").show(); + } + if ($("#school").val() == "qdu") { + $("#stu_id").show(); + $("#school").val("青岛大学"); + } + }); function refresh_captcha() { $("#captcha-img")[0].src = "/captcha/?" + Math.random(); $("#captcha")[0].value = ""; diff --git a/static/src/js/app/oj/account/settings.js b/static/src/js/app/oj/account/settings.js index b4538ee5..2c485300 100644 --- a/static/src/js/app/oj/account/settings.js +++ b/static/src/js/app/oj/account/settings.js @@ -8,7 +8,7 @@ require(["jquery", "bsAlert", "csrfToken", "validator"], function ($, bsAlert, c var blog = $("#blog").val(); var mood = $("#mood").val(); var school = $("#school").val(); - + var student_id = $("#student_id").val(); $.ajax({ beforeSend: csrfTokenHeader, url: "/api/account/userprofile/", @@ -19,7 +19,8 @@ require(["jquery", "bsAlert", "csrfToken", "validator"], function ($, bsAlert, c codeforces_username: codeforces_username, blog: blog, mood: mood, - school: school + school: school, + student_id: student_id }, dataType: "json", method: "put", diff --git a/template/src/oj/account/register.html b/template/src/oj/account/register.html index f3b990b3..50436111 100644 --- a/template/src/oj/account/register.html +++ b/template/src/oj/account/register.html @@ -19,10 +19,14 @@
- +
+
+ + +
diff --git a/template/src/oj/account/settings.html b/template/src/oj/account/settings.html index ebfee385..d15411df 100644 --- a/template/src/oj/account/settings.html +++ b/template/src/oj/account/settings.html @@ -69,9 +69,16 @@
+
+ + +
+ +
+ value="{% if request.user.userprofile.school %}{{ request.user.userprofile.blog }}{% endif %}">
From e86f9e59d99bd3d9a2a6ec0ca071282954b55d49 Mon Sep 17 00:00:00 2001 From: sxw Date: Tue, 8 Dec 2015 16:11:14 +0800 Subject: [PATCH 15/27] =?UTF-8?q?=E4=BF=AE=E6=94=B9settings=E4=B8=AD?= =?UTF-8?q?=E8=AF=AD=E8=A8=80=E4=B8=BA=E6=96=B0=E7=89=88=E6=9C=AC=E7=9A=84?= =?UTF-8?q?'zh-hans'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- oj/settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/oj/settings.py b/oj/settings.py index 83d49ef7..f2c3f240 100644 --- a/oj/settings.py +++ b/oj/settings.py @@ -98,7 +98,7 @@ WSGI_APPLICATION = 'oj.wsgi.application' # Internationalization # https://docs.djangoproject.com/en/1.8/topics/i18n/ -LANGUAGE_CODE = 'zh-cn' +LANGUAGE_CODE = 'zh-hans' TIME_ZONE = 'Asia/Shanghai' From 7cd012af4835f81e374a73e055cf4adb4293fa84 Mon Sep 17 00:00:00 2001 From: sxw Date: Tue, 8 Dec 2015 16:14:01 +0800 Subject: [PATCH 16/27] =?UTF-8?q?=E7=BB=9F=E4=B8=80userprofile=E5=AD=97?= =?UTF-8?q?=E6=AE=B5=E7=9A=84=E5=A4=84=E7=90=86=E6=96=B9=E5=BC=8F=EF=BC=8C?= =?UTF-8?q?=E9=83=BD=E5=88=A4=E6=96=AD=E6=98=AF=E5=90=A6=E4=B8=BAnone,?= =?UTF-8?q?=E4=BF=AE=E5=A4=8Dtypo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- template/src/oj/account/settings.html | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/template/src/oj/account/settings.html b/template/src/oj/account/settings.html index d15411df..f97e66db 100644 --- a/template/src/oj/account/settings.html +++ b/template/src/oj/account/settings.html @@ -34,7 +34,7 @@ value="{{ request.user.email }}" readonly>
-
@@ -50,35 +50,35 @@
- +
- +
- +
+ value="{% if request.user.userprofile.student_id %}{{ request.user.userprofile.student_id }}{% endif %}">
+ value="{% if request.user.userprofile.blog %}{{ request.user.userprofile.blog }}{% endif %}">
From 4d975b98fb0c7f7a293e065fed54afab2c0f5bd8 Mon Sep 17 00:00:00 2001 From: sxw Date: Tue, 8 Dec 2015 16:29:27 +0800 Subject: [PATCH 17/27] =?UTF-8?q?=E6=B3=A8=E9=87=8A=E6=8E=89=E4=BA=86?= =?UTF-8?q?=E7=94=A8=E6=88=B7=E4=B8=BB=E9=A1=B5=E9=87=8C=E8=BF=98=E6=B2=A1?= =?UTF-8?q?=E6=9C=89=E5=90=8E=E7=AB=AF=E9=85=8D=E5=A5=97=E7=9A=84submissio?= =?UTF-8?q?n=E9=83=A8=E5=88=86=EF=BC=8C=E6=B7=BB=E5=8A=A0=E5=AD=A6?= =?UTF-8?q?=E6=A0=A1=E6=98=BE=E7=A4=BA=EF=BC=8C=E4=BF=AE=E5=A4=8D=E4=BA=86?= =?UTF-8?q?settings=E9=87=8Ccodeforces=E7=94=A8=E6=88=B7=E5=90=8D=E6=97=A0?= =?UTF-8?q?=E6=B3=95=E7=BC=96=E8=BE=91=E7=9A=84=E9=97=AE=E9=A2=98=EF=BC=8C?= =?UTF-8?q?=E5=8E=9F=E6=9D=A5=E6=98=AFhtml=E9=87=8C=E8=BE=B9=E6=8B=BC?= =?UTF-8?q?=E9=94=99=E4=BA=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- template/src/oj/account/settings.html | 4 ++-- template/src/oj/account/user_index.html | 8 ++++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/template/src/oj/account/settings.html b/template/src/oj/account/settings.html index f97e66db..53560240 100644 --- a/template/src/oj/account/settings.html +++ b/template/src/oj/account/settings.html @@ -64,8 +64,8 @@
- +
diff --git a/template/src/oj/account/user_index.html b/template/src/oj/account/user_index.html index a829a25d..9ae7178e 100644 --- a/template/src/oj/account/user_index.html +++ b/template/src/oj/account/user_index.html @@ -22,6 +22,9 @@ {% if user.userprofile.mood %}

{{ user.userprofile.mood }}

{% endif %} + {% if user.userprofile.school %} +

{{ user.userprofile.school }}

+ {% endif %}
@@ -57,7 +60,7 @@

{% endif %} - +

{{ user.create_time }} @@ -68,7 +71,7 @@ {{ user.userprofile.rank }} Rank

- --> +
{{ user.userprofile.accepted_number }} AC @@ -77,6 +80,7 @@ {{ user.userprofile.submissions_number }} Submissions
+ --> From 8e232a90bd30efdfc969881b145f8d3ce986d25d Mon Sep 17 00:00:00 2001 From: sxw Date: Tue, 8 Dec 2015 16:52:47 +0800 Subject: [PATCH 18/27] =?UTF-8?q?=E7=BB=9F=E4=B8=80=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- static/src/js/app/oj/account/register.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/static/src/js/app/oj/account/register.js b/static/src/js/app/oj/account/register.js index 0557cfbd..c6780992 100644 --- a/static/src/js/app/oj/account/register.js +++ b/static/src/js/app/oj/account/register.js @@ -12,7 +12,7 @@ require(["jquery", "bsAlert", "csrfToken", "validator"], function ($, bsAlert, c $.ajax({ beforeSend: csrfTokenHeader, url: "/api/register/", - data: {username: username, school: school, student_id: student_id, real_name: realName, password: password, email: email, captcha:captcha}, + data: {username: username, school: school, student_id: student_id, real_name: realName, password: password, email: email, captcha: captcha}, dataType: "json", method: "post", success: function (data) { From 350890669118f5c0d0bd5a7c0a1410d2f97845a1 Mon Sep 17 00:00:00 2001 From: sxw Date: Wed, 9 Dec 2015 09:45:31 +0800 Subject: [PATCH 19/27] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=AD=A6=E6=A0=A1?= =?UTF-8?q?=E5=88=A4=E6=96=AD=E5=92=8C=E8=87=AA=E5=8A=A8=E7=BB=9F=E4=B8=80?= =?UTF-8?q?=E9=98=9F=E5=BD=A2=E7=9A=84=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- static/src/js/app/oj/account/register.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/static/src/js/app/oj/account/register.js b/static/src/js/app/oj/account/register.js index c6780992..d5b9a543 100644 --- a/static/src/js/app/oj/account/register.js +++ b/static/src/js/app/oj/account/register.js @@ -33,10 +33,10 @@ require(["jquery", "bsAlert", "csrfToken", "validator"], function ($, bsAlert, c }); $("#school").blur(function () { - if ($("#school").val() == "青岛大学") { - $("#stu_id").show(); - } - if ($("#school").val() == "qdu") { + var school = $("#school").val(); + school = $.trim(school).toLowerCase(); + console.log(school); + if (school == "青岛大学" || school == "qdu" || school == "qdu" || school == "青大") { $("#stu_id").show(); $("#school").val("青岛大学"); } From 09de27667ddbcc2db501bd6e67e60f58ecfe939a Mon Sep 17 00:00:00 2001 From: sxw Date: Wed, 9 Dec 2015 19:48:58 +0800 Subject: [PATCH 20/27] =?UTF-8?q?=E4=BF=AE=E6=94=B9group=E7=9A=84models?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=B0=8F=E7=BB=84=E7=AE=A1=E7=90=86=E5=91=98?= =?UTF-8?q?=E7=9A=84=E5=A4=9A=E5=AF=B9=E5=A4=9A=E5=AD=97=E6=AE=B5=EF=BC=8C?= =?UTF-8?q?=E6=8A=8A=E5=8E=9F=E6=9D=A5=E7=9A=84=E7=AE=A1=E7=90=86=E5=91=98?= =?UTF-8?q?=E5=AD=97=E6=AE=B5=E9=87=8D=E5=91=BD=E5=90=8D=E4=B8=BA=E5=88=9B?= =?UTF-8?q?=E5=BB=BA=E8=80=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- group/migrations/0006_auto_20151209_1834.py | 20 +++++++++++ group/migrations/0007_auto_20151209_1836.py | 38 +++++++++++++++++++++ group/models.py | 13 ++++++- 3 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 group/migrations/0006_auto_20151209_1834.py create mode 100644 group/migrations/0007_auto_20151209_1836.py diff --git a/group/migrations/0006_auto_20151209_1834.py b/group/migrations/0006_auto_20151209_1834.py new file mode 100644 index 00000000..3e5a6e95 --- /dev/null +++ b/group/migrations/0006_auto_20151209_1834.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9 on 2015-12-09 10:34 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('group', '0005_joingrouprequest_accepted'), + ] + + operations = [ + migrations.RenameField( + model_name='group', + old_name='admin', + new_name='created_by', + ), + ] diff --git a/group/migrations/0007_auto_20151209_1836.py b/group/migrations/0007_auto_20151209_1836.py new file mode 100644 index 00000000..937d6f07 --- /dev/null +++ b/group/migrations/0007_auto_20151209_1836.py @@ -0,0 +1,38 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9 on 2015-12-09 10:36 +from __future__ import unicode_literals + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('group', '0006_auto_20151209_1834'), + ] + + operations = [ + migrations.CreateModel( + name='AdminGroupRelation', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('group', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='group.Group')), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + options={ + 'db_table': 'admin_group_relation', + }, + ), + migrations.AddField( + model_name='group', + name='admin', + field=models.ManyToManyField(related_name='managed_groups', through='group.AdminGroupRelation', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterUniqueTogether( + name='admingrouprelation', + unique_together=set([('user', 'group')]), + ), + ] diff --git a/group/models.py b/group/models.py index a2db074a..26059f7e 100644 --- a/group/models.py +++ b/group/models.py @@ -8,10 +8,11 @@ class Group(models.Model): name = models.CharField(max_length=30, unique=True) description = models.TextField() create_time = models.DateTimeField(auto_now_add=True) - admin = models.ForeignKey(User, related_name="my_groups") + created_by = models.ForeignKey(User, related_name="my_groups") # 0是公开 1是需要申请后加入 2是不允许任何人加入 join_group_setting = models.IntegerField(default=1) members = models.ManyToManyField(User, through="UserGroupRelation") + admin = models.ManyToManyField(User, through="AdminGroupRelation", related_name="managed_groups") # 解散小组后,这一项改为False visible = models.BooleanField(default=True) @@ -29,6 +30,16 @@ class UserGroupRelation(models.Model): unique_together = ("group", "user") + +class AdminGroupRelation(models.Model): + user = models.ForeignKey(User) + group = models.ForeignKey(Group) + + class Meta: + db_table = "admin_group_relation" + unique_together = ("user", "group") + + class JoinGroupRequest(models.Model): group = models.ForeignKey(Group) user = models.ForeignKey(User, related_name="my_join_group_requests") From c12ee66c51ddc9b1bd9111acdb56e44d29db851c Mon Sep 17 00:00:00 2001 From: sxw Date: Wed, 9 Dec 2015 19:50:48 +0800 Subject: [PATCH 21/27] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=90=8E=E5=8F=B0?= =?UTF-8?q?=E5=B0=8F=E7=BB=84=E7=AE=A1=E7=90=86=E5=8A=9F=E8=83=BD=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E8=AE=BE=E4=B8=BA=E7=AE=A1=E7=90=86=E5=91=98=E6=8C=89?= =?UTF-8?q?=E9=92=AE=EF=BC=8C=E6=96=B9=E4=BE=BF=E6=B7=BB=E5=8A=A0=E5=A4=9A?= =?UTF-8?q?=E7=AE=A1=E7=90=86=E5=91=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- static/src/js/app/admin/group/groupDetail.js | 13 ++++++++++++- template/src/admin/group/group_detail.html | 4 ++-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/static/src/js/app/admin/group/groupDetail.js b/static/src/js/app/admin/group/groupDetail.js index 7b7e3f38..9edc2355 100644 --- a/static/src/js/app/admin/group/groupDetail.js +++ b/static/src/js/app/admin/group/groupDetail.js @@ -1,6 +1,5 @@ require(["jquery", "avalon", "csrfToken", "bsAlert", "validator"], function ($, avalon, csrfTokenHeader, bsAlert) { - // avalon:定义模式 group_list avalon.ready(function () { @@ -55,6 +54,18 @@ require(["jquery", "avalon", "csrfToken", "bsAlert", "validator"], function ($, showGroupListPage: function () { avalon.vmodels.admin.template_url = "template/group/group.html"; vm.$fire("up!showGroupListPage"); + }, + promotAsAdmin: function (relation) { + $.ajax({ + beforeSend: csrfTokenHeader, + url: "/api/admin/group/promot_as_admin/", + method: "post", + data: JSON.stringify({group_id: relation.group, user_id: relation.user.id}), + contentType: "application/json;charset=UTF-8", + success: function (data) { + bsAlert(data.data); + } + }) } }); } diff --git a/template/src/admin/group/group_detail.html b/template/src/admin/group/group_detail.html index a6e0a3b0..cb1be1fe 100644 --- a/template/src/admin/group/group_detail.html +++ b/template/src/admin/group/group_detail.html @@ -19,13 +19,13 @@
- +
ID
{{ contest.end_time }} {{ contest|contest_status }}小组赛私有小组赛公开赛公开赛(密码保护)小组邀请赛{{ contest.created_by.username }}
{{ item.start_time }}小组赛私有小组赛公开赛公开赛(密码保护)小组邀请赛{{ item|contest_status }}
{{ el.user.username }} {{ el.user.real_name }} {{ el.join_time|date("yyyy-MM-dd HH:mm:ss")}} +
-
页数:{{ page }}/{{ totalPage }}   From f924843ef173dbd78980316726ecd370bd38d772 Mon Sep 17 00:00:00 2001 From: sxw Date: Wed, 9 Dec 2015 19:51:59 +0800 Subject: [PATCH 22/27] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=8F=90=E5=8D=87?= =?UTF-8?q?=E5=B0=8F=E7=BB=84=E7=AE=A1=E7=90=86=E5=91=98=E7=9A=84api?= =?UTF-8?q?=EF=BC=8C=E8=B0=83=E6=95=B4=E5=B0=8F=E7=BB=84=E7=AE=A1=E7=90=86?= =?UTF-8?q?=E6=9D=83=E9=99=90=E7=9A=84=E8=AE=A4=E8=AF=81=E6=96=B9=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- group/views.py | 45 +++++++++++++++++++++++++++++++++++++++------ oj/urls.py | 5 ++++- 2 files changed, 43 insertions(+), 7 deletions(-) diff --git a/group/views.py b/group/views.py index 23e59ad3..527486e6 100644 --- a/group/views.py +++ b/group/views.py @@ -5,14 +5,14 @@ from django.db import IntegrityError from rest_framework.views import APIView from utils.shortcuts import error_response, serializer_invalid_response, success_response, paginate, error_page -from account.models import REGULAR_USER, ADMIN, SUPER_ADMIN +from account.models import REGULAR_USER, ADMIN, SUPER_ADMIN, User from account.decorators import login_required -from .models import Group, JoinGroupRequest, UserGroupRelation +from .models import Group, JoinGroupRequest, UserGroupRelation, AdminGroupRelation from .serializers import (CreateGroupSerializer, EditGroupSerializer, CreateJoinGroupRequestSerializer, GroupSerializer, GroupMemberSerializer, EditGroupMemberSerializer, - JoinGroupRequestSerializer, PutJoinGroupRequestSerializer) + JoinGroupRequestSerializer, PutJoinGroupRequestSerializer, GroupPromoteAdminSerializer) from announcement.models import Announcement from django.core.paginator import Paginator from django.db.models import Q @@ -57,9 +57,10 @@ class GroupAdminAPIView(APIView, GroupAPIViewBase): group = Group.objects.create(name=data["name"], description=data["description"], join_group_setting=data["join_group_setting"], - admin=request.user) + created_by=request.user) except IntegrityError: return error_response(u"小组名已经存在") + AdminGroupRelation.objects.create(group=group, user=request.user) return success_response(GroupSerializer(group).data) else: return serializer_invalid_response(serializer) @@ -132,8 +133,13 @@ class GroupMemberAdminAPIView(APIView, GroupAPIViewBase): group = self.get_group(request, group_id) except Group.DoesNotExist: return error_response(u"小组不存在") - - return paginate(request, UserGroupRelation.objects.filter(group=group), GroupMemberSerializer) + adminOnly = request.GET.get("adminOnly", None) + if adminOnly: + members = AdminGroupRelation.objects.filter(group=group) + else: + members = UserGroupRelation.objects.filter(group=group) + + return paginate(request, members, GroupMemberSerializer) def put(self, request): """ @@ -314,3 +320,30 @@ def application_page(request, request_id): return error_page(request, u"申请不存在") return render(request, "oj/group/my_application.html", {"application": application}) + + +class GroupPrometAdminAPIView(APIView): + def post(self, request): + """ + 创建小组管理员的api + --- + request_serializer: GroupPromoteAdminSerializer + """ + serializer = GroupPromoteAdminSerializer(data=request.data) + if serializer.is_valid(): + data = serializer.data + try: + group = Group.objects.get(id=data["group_id"]) + except Group.DoesNotExist: + return error_response(u"小组不存在") + try: + user = User.objects.get(id=data["user_id"]) + except User.DoesNotExist: + return error_response(u"用户不存在") + try: + AdminGroupRelation.objects.create(user=user, group=group) + except IntegrityError: + return error_response(u"该用户已经是管理员了") + return success_response(u"操作成功") + else: + return serializer_invalid_response(serializer) diff --git a/oj/urls.py b/oj/urls.py index d2beba16..77a92b66 100644 --- a/oj/urls.py +++ b/oj/urls.py @@ -15,7 +15,7 @@ from contest.views import (ContestAdminAPIView, ContestProblemAdminAPIView, MakeContestProblemPublicAPIView) from group.views import (GroupAdminAPIView, GroupMemberAdminAPIView, - JoinGroupAPIView, JoinGroupRequestAdminAPIView) + JoinGroupAPIView, JoinGroupRequestAdminAPIView, GroupPrometAdminAPIView) from admin.views import AdminTemplateView @@ -55,6 +55,7 @@ urlpatterns = [ url(r'^api/contest/submission/$', ContestSubmissionAPIView.as_view(), name="contest_submission_api"), url(r'^api/submission/$', SubmissionAPIView.as_view(), name="submission_api"), url(r'^api/group_join/$', JoinGroupAPIView.as_view(), name="group_join_api"), + url(r'^api/admin/upload_image/$', SimditorImageUploadAPIView.as_view(), name="simditor_upload_image"), url(r'^api/admin/announcement/$', AnnouncementAdminAPIView.as_view(), name="announcement_admin_api"), @@ -62,6 +63,8 @@ urlpatterns = [ url(r'^api/admin/user/$', UserAdminAPIView.as_view(), name="user_admin_api"), url(r'^api/admin/group/$', GroupAdminAPIView.as_view(), name="group_admin_api"), url(r'^api/admin/group_member/$', GroupMemberAdminAPIView.as_view(), name="group_member_admin_api"), + url(r'^api/admin/group/promot_as_admin/$', GroupPrometAdminAPIView.as_view(), name="group_promote_admin_api"), + url(r'^api/admin/problem/$', ProblemAdminAPIView.as_view(), name="problem_admin_api"), url(r'^api/admin/contest_problem/$', ContestProblemAdminAPIView.as_view(), name="contest_problem_admin_api"), From 1dcfe0bc102196d7315e745dbaaf7bbfc25f8a1b Mon Sep 17 00:00:00 2001 From: sxw Date: Wed, 9 Dec 2015 19:52:42 +0800 Subject: [PATCH 23/27] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=B0=8F=E7=BB=84?= =?UTF-8?q?=E5=88=97=E8=A1=A8=E6=A8=A1=E6=9D=BF=EF=BC=8C=E9=80=82=E5=BA=94?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E5=BA=93=E7=9A=84=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- template/src/oj/group/group_list.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/template/src/oj/group/group_list.html b/template/src/oj/group/group_list.html index 500257a0..03e425cb 100644 --- a/template/src/oj/group/group_list.html +++ b/template/src/oj/group/group_list.html @@ -40,7 +40,7 @@ 无需申请 {% endif %} - {{ item.admin }} + {{ item.created_by }} {{ item.create_time }} {% endfor %} From 96b409d1f064c04b18316fa344de2aaa436e9fb2 Mon Sep 17 00:00:00 2001 From: sxw Date: Wed, 9 Dec 2015 20:02:47 +0800 Subject: [PATCH 24/27] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E8=BE=83=E5=A4=9A?= =?UTF-8?q?=EF=BC=8C=E6=B6=89=E5=8F=8A=E5=88=B0=E5=B0=8F=E7=BB=84=E7=AE=A1?= =?UTF-8?q?=E7=90=86=E5=91=98=E5=AF=B9=E6=AF=94=E8=B5=9B=E7=9A=84=E7=AE=A1?= =?UTF-8?q?=E7=90=86=EF=BC=8C=E5=B0=8F=E7=BB=84=E7=AE=A1=E7=90=86=E5=91=98?= =?UTF-8?q?=E5=8F=AF=E4=BB=A5=E7=9C=8B=E5=88=B0=E4=BB=96=E7=AE=A1=E7=90=86?= =?UTF-8?q?=E7=9A=84=E5=B0=8F=E7=BB=84=E7=9A=84=E5=85=B6=E4=BB=96=E7=AE=A1?= =?UTF-8?q?=E7=90=86=E5=91=98=E5=88=9B=E5=BB=BA=E7=9A=84=E6=AF=94=E8=B5=9B?= =?UTF-8?q?=EF=BC=8C=E4=BD=86=E7=9C=8B=E4=B8=8D=E5=88=B0=E5=88=AB=E4=BA=BA?= =?UTF-8?q?=E7=9A=84=E9=A2=98=E7=9B=AE=EF=BC=8C=E4=BD=86=E6=98=AF=E5=8F=AF?= =?UTF-8?q?=E4=BB=A5=E4=BB=8E=E5=89=8D=E5=8F=B0=E7=9C=8B=E5=88=B0=E6=AF=94?= =?UTF-8?q?=E8=B5=9B=E7=9A=84=E9=A2=98=E7=9B=AE=EF=BC=8C=E5=8F=AF=E4=BB=A5?= =?UTF-8?q?=E5=9C=A8=E6=AF=94=E8=B5=9B=E5=BC=80=E5=A7=8B=E5=89=8D=E6=B5=8B?= =?UTF-8?q?=E8=AF=95=E9=A2=98=E7=9B=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contest/decorators.py | 7 +++++-- contest/views.py | 29 +++++++++++++++++++---------- 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/contest/decorators.py b/contest/decorators.py index 0dad16fd..663f8fbe 100644 --- a/contest/decorators.py +++ b/contest/decorators.py @@ -8,7 +8,7 @@ from django.core.urlresolvers import reverse from utils.shortcuts import error_response, error_page -from account.models import SUPER_ADMIN +from account.models import SUPER_ADMIN, ADMIN from .models import (Contest, PASSWORD_PROTECTED_CONTEST, PASSWORD_PROTECTED_GROUP_CONTEST, PUBLIC_CONTEST, GROUP_CONTEST, CONTEST_ENDED, CONTEST_NOT_START, CONTEST_UNDERWAY) @@ -57,7 +57,10 @@ def check_user_contest_permission(func): if request.user.admin_type == SUPER_ADMIN or request.user == contest.created_by: return func(*args, **kwargs) - + if request.user.admin_type == ADMIN: + contest_set = Contest.objects.filter(groups__in=request.user.managed_groups.all()) + if contest in contest_set: + return func(*args, **kwargs) # 管理员可见隐藏的比赛,已经先判断了身份 if not contest.visible: if request.is_ajax(): diff --git a/contest/views.py b/contest/views.py index 22539558..cfc2049b 100644 --- a/contest/views.py +++ b/contest/views.py @@ -17,7 +17,7 @@ from utils.shortcuts import (serializer_invalid_response, error_response, success_response, paginate, error_page, paginate_data) from account.models import SUPER_ADMIN, User from account.decorators import login_required, super_admin_required -from group.models import Group +from group.models import Group, AdminGroupRelation, UserGroupRelation from utils.cache import get_cache_redis from submission.models import Submission from problem.models import Problem @@ -91,8 +91,10 @@ class ContestAdminAPIView(APIView): try: # 超级管理员可以编辑所有的 contest = Contest.objects.get(id=data["id"]) - if request.user.admin_type != SUPER_ADMIN and contest.created_by != request.user: - return error_response(u"无权访问!") + if request.user.admin_type != SUPER_ADMIN: + contest_set = Contest.objects.filter(groups__in=request.user.managed_groups.all()) + if contest not in contest_set: + return error_response(u"无权访问!") except Contest.DoesNotExist: return error_response(u"该比赛不存在!") try: @@ -151,16 +153,18 @@ class ContestAdminAPIView(APIView): # 普通管理员只能获取自己创建的题目 # 超级管理员可以获取全部的题目 contest = Contest.objects.get(id=contest_id) - if request.user.admin_type != SUPER_ADMIN and contest.created_by != request.user: - return error_response(u"题目不存在") + if request.user.admin_type != SUPER_ADMIN: + contest_set = Contest.objects.filter(groups__in=request.user.managed_groups.all()) + if contest not in contest_set: + return error_response(u"比赛不存在") return success_response(ContestSerializer(contest).data) except Contest.DoesNotExist: - return error_response(u"题目不存在") + return error_response(u"比赛不存在") if request.user.admin_type == SUPER_ADMIN: contest = Contest.objects.all().order_by("-create_time") else: - contest = Contest.objects.filter(created_by=request.user).order_by("-create_time") + contest = Contest.objects.filter(groups__in=request.user.managed_groups.all()).distinct().order_by("-create_time") visible = request.GET.get("visible", None) if visible: contest = contest.filter(visible=(visible == "true")) @@ -184,8 +188,10 @@ class ContestProblemAdminAPIView(APIView): data = serializer.data try: contest = Contest.objects.get(id=data["contest_id"]) - if request.user.admin_type != SUPER_ADMIN and contest.created_by != request.user: - return error_response(u"比赛不存在") + if request.user.admin_type != SUPER_ADMIN: + contest_set = Contest.objects.filter(groups__in=request.user.managed_groups.all()) + if contest not in contest_set: + return error_response(u"比赛不存在") except Contest.DoesNotExist: return error_response(u"比赛不存在") contest_problem = ContestProblem.objects.create(title=data["title"], @@ -362,7 +368,10 @@ def contest_problem_page(request, contest_id, contest_problem_id): request.user.admin_type == SUPER_ADMIN or \ request.user == contest.created_by: show_submit_code_area = True - + else: + contest_set = Contest.objects.filter(groups__in=request.user.managed_groups.all()) + if contest in contest_set: + show_submit_code_area = True return render(request, "oj/problem/contest_problem.html", {"problem": problem, "contest": contest, "samples": json.loads(problem.samples), From 023f4ab82fab90f6536c176ea5700af6e904a668 Mon Sep 17 00:00:00 2001 From: sxw Date: Wed, 9 Dec 2015 20:04:11 +0800 Subject: [PATCH 25/27] =?UTF-8?q?=E8=BF=99=E4=B8=AA=E6=98=AF=E5=88=9A?= =?UTF-8?q?=E6=89=8Dapi=E5=9C=B0=E6=96=B9=E7=9A=84=EF=BC=8C=E5=BF=98?= =?UTF-8?q?=E4=BA=86add=E4=B8=8A=E4=BA=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- group/serializers.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/group/serializers.py b/group/serializers.py index 402ea5b9..27490d87 100644 --- a/group/serializers.py +++ b/group/serializers.py @@ -73,4 +73,8 @@ class EditGroupMemberSerializer(serializers.Serializer): class PutJoinGroupRequestSerializer(serializers.Serializer): request_id = serializers.IntegerField() - status = serializers.BooleanField() \ No newline at end of file + status = serializers.BooleanField() + +class GroupPromoteAdminSerializer(serializers.Serializer): + user_id = serializers.IntegerField() + group_id = serializers.IntegerField() From 82b17b1c0487672bac89e748442949818854d9a1 Mon Sep 17 00:00:00 2001 From: sxw Date: Wed, 9 Dec 2015 20:10:31 +0800 Subject: [PATCH 26/27] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=B8=80=E4=BA=9B?= =?UTF-8?q?=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- static/src/js/app/oj/account/register.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/static/src/js/app/oj/account/register.js b/static/src/js/app/oj/account/register.js index d5b9a543..9c2109e3 100644 --- a/static/src/js/app/oj/account/register.js +++ b/static/src/js/app/oj/account/register.js @@ -33,10 +33,8 @@ require(["jquery", "bsAlert", "csrfToken", "validator"], function ($, bsAlert, c }); $("#school").blur(function () { - var school = $("#school").val(); - school = $.trim(school).toLowerCase(); - console.log(school); - if (school == "青岛大学" || school == "qdu" || school == "qdu" || school == "青大") { + var school = $("#school").val().trim(school).toLowerCase(); + if (school == "青岛大学" || school == "qdu" || school == "青大") { $("#stu_id").show(); $("#school").val("青岛大学"); } From 15d7179cae91adb58b44e886dda14fa27b414f04 Mon Sep 17 00:00:00 2001 From: sxw Date: Wed, 9 Dec 2015 20:23:30 +0800 Subject: [PATCH 27/27] =?UTF-8?q?=E7=BB=9F=E4=B8=80get=E5=8F=82=E6=95=B0?= =?UTF-8?q?=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- group/views.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/group/views.py b/group/views.py index 527486e6..29f0a49c 100644 --- a/group/views.py +++ b/group/views.py @@ -133,8 +133,8 @@ class GroupMemberAdminAPIView(APIView, GroupAPIViewBase): group = self.get_group(request, group_id) except Group.DoesNotExist: return error_response(u"小组不存在") - adminOnly = request.GET.get("adminOnly", None) - if adminOnly: + admin_only = request.GET.get("admin_only", None) + if admin_only: members = AdminGroupRelation.objects.filter(group=group) else: members = UserGroupRelation.objects.filter(group=group)