diff --git a/account/views.py b/account/views.py index ea136631..7214c8a9 100644 --- a/account/views.py +++ b/account/views.py @@ -97,6 +97,7 @@ class UsernameCheckAPIView(APIView): else: return serializer_invalid_response(serializer) + class EmailCheckAPIView(APIView): def post(self, request): """ diff --git a/announcement/serializers.py b/announcement/serializers.py index a195b2ea..d6380b06 100644 --- a/announcement/serializers.py +++ b/announcement/serializers.py @@ -22,3 +22,9 @@ class AnnouncementSerializer(serializers.ModelSerializer): class Meta: model = Announcement + +class EditAnnouncementSerializer(serializers.Serializer): + id = serializers.IntegerField() + title = serializers.CharField(max_length=50) + content = serializers.CharField(max_length=10000) + visible = serializers.BooleanField() diff --git a/announcement/tests.py b/announcement/tests.py index f337a9c7..a7fd1208 100644 --- a/announcement/tests.py +++ b/announcement/tests.py @@ -4,9 +4,10 @@ from django.core.urlresolvers import reverse from rest_framework.test import APITestCase, APIClient from account.models import User +from announcement.models import Announcement -class AnnouncementAPITest(APITestCase): +class AnnouncementAdminAPITest(APITestCase): def setUp(self): self.client = APIClient() self.url = reverse("announcement_admin_api") @@ -14,6 +15,7 @@ class AnnouncementAPITest(APITestCase): user.set_password("test") user.save() + # 以下是发布公告的测试 def test_invalid_format(self): self.client.login(username="test", password="test") data = {"title": "test1"} @@ -24,4 +26,42 @@ class AnnouncementAPITest(APITestCase): self.client.login(username="test", password="test") data = {"title": "title0", "content": "content0"} response = self.client.post(self.url, data=data) - self.assertEqual(response.data, {"code": 0, "data": u"公告发布成功!"}) \ No newline at end of file + self.assertEqual(response.data, {"code": 0, "data": u"公告发布成功!"}) + + def test_post_invalid_data(self): + self.client.login(username="test", password="test") + data = {"title": "test"} + response = self.client.post(self.url, data=data) + self.assertEqual(response.data["code"], 1) + + # 以下是编辑公告的测试 + def test_put_invalid_data(self): + self.client.login(username="test", password="test") + data = {"title": "test0", "content": "test0", "visible": "True"} + response = self.client.put(self.url, data=data) + self.assertEqual(response.data["code"], 1) + + def test_announcement_does_not_exist(self): + announcement = Announcement.objects.create(title="aa", + content="AA", + created_by=User.objects.get(username="test")) + data = {"id": announcement.id + 1, "title": "11", "content": "22", "visible": True} + response = self.client.put(self.url, data=data) + self.assertEqual(response.data, {"code": 1, "data": u"该公告不存在!"}) + + def test_success_edit_announcement(self): + announcement = Announcement.objects.create(title="bb", + content="BB", + created_by=User.objects.get(username="test")) + data = {"id": announcement.id, "title": "11", "content": "22", "visible": True} + response = self.client.put(self.url, data=data) + self.assertEqual(response.data["code"], 0) + + +class AnnouncementAPITest(APITestCase): + def setUp(self): + self.client = APIClient() + self.url = reverse("announcement_list_api") + + def test_success_get_data(self): + self.assertEqual(self.client.get(self.url).data["code"], 0) diff --git a/announcement/views.py b/announcement/views.py index 9649875b..bc148893 100644 --- a/announcement/views.py +++ b/announcement/views.py @@ -6,7 +6,8 @@ from utils.shortcuts import serializer_invalid_response, error_response, success from account.models import User from utils.shortcuts import paginate from .models import Announcement -from .serializers import CreateAnnouncementSerializer, AnnouncementSerializer +from .serializers import (CreateAnnouncementSerializer, AnnouncementSerializer, + EditAnnouncementSerializer) class AnnouncementAdminAPIView(APIView): @@ -26,6 +27,28 @@ class AnnouncementAdminAPIView(APIView): else: return serializer_invalid_response(serializer) + def put(self, request): + """ + 公告编辑json api接口 + --- + request_serializer: EditAnnouncementSerializer + response_serializer: AnnouncementSerializer + """ + serializer = EditAnnouncementSerializer(data=request.DATA) + if serializer.is_valid(): + data = serializer.data + try: + announcement = Announcement.objects.get(id=data["id"]) + except Announcement.DoesNotExist: + return error_response(u"该公告不存在!") + announcement.title = data["title"] + announcement.content = data["content"] + announcement.visible = data["visible"] + announcement.save() + return success_response(AnnouncementSerializer(announcement).data) + else: + return serializer_invalid_response(serializer) + class AnnouncementAPIView(APIView): def get(self, request): diff --git a/static/src/css/admin.css b/static/src/css/admin.css index 75fc901e..e54f0e3e 100644 --- a/static/src/css/admin.css +++ b/static/src/css/admin.css @@ -1,25 +1,15 @@ +@import url("global.css"); @import url("bootstrap/bootstrap.min.css"); @import url("bootstrap/todc-bootstrap.min.css"); @import url("codeMirror/codemirror.css"); @import url("simditor/simditor.css"); @import url("webuploader/webuploader.css"); @import url("datetime_picker/bootstrap-datetimepicker.css"); -html, body { - height: 100%; -} -img { - max-width: 100%; - height: auto; -} - -.footer { - padding-top: 30px; - padding-bottom: 30px; - float: bottom; - bottom: 0; -} - -label { - font-size: 16px; +#loading-gif{ + width: 40px; + height: 40px; + margin: auto; + position: absolute; + top: 0; left: 0; bottom: 0; right: 0; } \ No newline at end of file diff --git a/static/src/css/global.css b/static/src/css/global.css new file mode 100644 index 00000000..c55a0bb3 --- /dev/null +++ b/static/src/css/global.css @@ -0,0 +1,27 @@ +html{ + height: 100%; +} + +body{ + height:100%; /*使内容高度和body一样*/ + margin-bottom:-80px;/*向上缩减80像素,不至于footer超出屏幕可视范围*/ +} + +.main{ + padding-bottom: 120px; +} + +img { + max-width: 100%; + height: auto; +} + +.footer { + left: 0; + right: 0; + height: 80px +} + +label { + font-size: 16px; +} \ No newline at end of file diff --git a/static/src/css/oj.css b/static/src/css/oj.css index fcf80ddb..cc6ac62d 100644 --- a/static/src/css/oj.css +++ b/static/src/css/oj.css @@ -1,25 +1,8 @@ +@import url("global.css"); @import url("bootstrap/bootstrap.min.css"); @import url("bootstrap/todc-bootstrap.min.css"); @import url("codeMirror/codemirror.css"); -html, body { - height: 100%; -} -img { - max-width: 100%; - height: auto; -} - -.footer { - padding-top: 30px; - padding-bottom: 30px; - float: bottom; - bottom: 0; -} - -label { - font-size: 16px; -} #language-selector { width: 130px; @@ -47,7 +30,6 @@ label { font-size: 15px; } -/* index css */ .jumbotron { text-align: center; background-color: transparent; diff --git a/static/src/js/app/admin/admin.js b/static/src/js/app/admin/admin.js index d3e30ac8..4145a45d 100644 --- a/static/src/js/app/admin/admin.js +++ b/static/src/js/app/admin/admin.js @@ -7,25 +7,36 @@ define("admin", ["jquery", "avalon"], function($, avalon){ $(".list-group-item").attr("class", "list-group-item"); } + function show_template(url){ + $("#loading-gif").show(); + vm.template_url = url; + } + + var vm = avalon.define({ + $id: "admin", + template_url: "template/index/index.html", + hide_loading: function(){ + $("#loading-gif").hide(); + } + }); + var hash = window.location.hash.substring(1); if(hash){ - li_active("#li-" + hash); + li_active("#li-" + hash.replace("/", "-")); + show_template("template/" + hash + ".html"); }else { - li_active("#li-index"); + li_active("#li-index-index"); } window.onhashchange = function() { var hash = window.location.hash.substring(1); if(hash){ li_inactive(".list-group-item"); - li_active("#li-" + hash); - vm.template_url = "template/index/" + hash + ".html"; + li_active("#li-" + hash.replace("/", "-")); + show_template("template/" + hash + ".html"); } }; - var vm = avalon.define({ - $id: "admin", - template_url: "template/index/index.html" - }); + }); \ No newline at end of file diff --git a/static/src/js/app/admin/contest/contest.js b/static/src/js/app/admin/contest/contest.js index bc13d9d3..6cd531d9 100644 --- a/static/src/js/app/admin/contest/contest.js +++ b/static/src/js/app/admin/contest/contest.js @@ -2,6 +2,7 @@ require(["jquery", "avalon", "editor", "uploader", "datetimepicker", "validation" ], function ($, avalon, editor, uploader) { + avalon.vmodels.add_contest = null; $("#add-contest-form") .formValidation({ framework: "bootstrap", diff --git a/template/admin/admin.html b/template/admin/admin.html index 3672a359..99d5b894 100644 --- a/template/admin/admin.html +++ b/template/admin/admin.html @@ -67,23 +67,25 @@ -