Merge branch 'dev' into sxw-dev

Conflicts:
	template/admin/admin.html
This commit is contained in:
sxw
2015-08-07 19:28:24 +08:00
17 changed files with 288 additions and 211 deletions

View File

@@ -97,6 +97,7 @@ class UsernameCheckAPIView(APIView):
else: else:
return serializer_invalid_response(serializer) return serializer_invalid_response(serializer)
class EmailCheckAPIView(APIView): class EmailCheckAPIView(APIView):
def post(self, request): def post(self, request):
""" """

View File

@@ -22,3 +22,9 @@ class AnnouncementSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = Announcement model = Announcement
class EditAnnouncementSerializer(serializers.Serializer):
id = serializers.IntegerField()
title = serializers.CharField(max_length=50)
content = serializers.CharField(max_length=10000)
visible = serializers.BooleanField()

View File

@@ -4,9 +4,10 @@ from django.core.urlresolvers import reverse
from rest_framework.test import APITestCase, APIClient from rest_framework.test import APITestCase, APIClient
from account.models import User from account.models import User
from announcement.models import Announcement
class AnnouncementAPITest(APITestCase): class AnnouncementAdminAPITest(APITestCase):
def setUp(self): def setUp(self):
self.client = APIClient() self.client = APIClient()
self.url = reverse("announcement_admin_api") self.url = reverse("announcement_admin_api")
@@ -14,6 +15,7 @@ class AnnouncementAPITest(APITestCase):
user.set_password("test") user.set_password("test")
user.save() user.save()
# 以下是发布公告的测试
def test_invalid_format(self): def test_invalid_format(self):
self.client.login(username="test", password="test") self.client.login(username="test", password="test")
data = {"title": "test1"} data = {"title": "test1"}
@@ -25,3 +27,41 @@ class AnnouncementAPITest(APITestCase):
data = {"title": "title0", "content": "content0"} data = {"title": "title0", "content": "content0"}
response = self.client.post(self.url, data=data) response = self.client.post(self.url, data=data)
self.assertEqual(response.data, {"code": 0, "data": u"公告发布成功!"}) 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)

View File

@@ -6,7 +6,8 @@ from utils.shortcuts import serializer_invalid_response, error_response, success
from account.models import User from account.models import User
from utils.shortcuts import paginate from utils.shortcuts import paginate
from .models import Announcement from .models import Announcement
from .serializers import CreateAnnouncementSerializer, AnnouncementSerializer from .serializers import (CreateAnnouncementSerializer, AnnouncementSerializer,
EditAnnouncementSerializer)
class AnnouncementAdminAPIView(APIView): class AnnouncementAdminAPIView(APIView):
@@ -26,6 +27,28 @@ class AnnouncementAdminAPIView(APIView):
else: else:
return serializer_invalid_response(serializer) 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): class AnnouncementAPIView(APIView):
def get(self, request): def get(self, request):

View File

@@ -1,25 +1,15 @@
@import url("global.css");
@import url("bootstrap/bootstrap.min.css"); @import url("bootstrap/bootstrap.min.css");
@import url("bootstrap/todc-bootstrap.min.css"); @import url("bootstrap/todc-bootstrap.min.css");
@import url("codeMirror/codemirror.css"); @import url("codeMirror/codemirror.css");
@import url("simditor/simditor.css"); @import url("simditor/simditor.css");
@import url("webuploader/webuploader.css"); @import url("webuploader/webuploader.css");
@import url("datetime_picker/bootstrap-datetimepicker.css"); @import url("datetime_picker/bootstrap-datetimepicker.css");
html, body {
height: 100%;
}
img { #loading-gif{
max-width: 100%; width: 40px;
height: auto; height: 40px;
} margin: auto;
position: absolute;
.footer { top: 0; left: 0; bottom: 0; right: 0;
padding-top: 30px;
padding-bottom: 30px;
float: bottom;
bottom: 0;
}
label {
font-size: 16px;
} }

27
static/src/css/global.css Normal file
View File

@@ -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;
}

View File

@@ -1,25 +1,8 @@
@import url("global.css");
@import url("bootstrap/bootstrap.min.css"); @import url("bootstrap/bootstrap.min.css");
@import url("bootstrap/todc-bootstrap.min.css"); @import url("bootstrap/todc-bootstrap.min.css");
@import url("codeMirror/codemirror.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 { #language-selector {
width: 130px; width: 130px;
@@ -47,7 +30,6 @@ label {
font-size: 15px; font-size: 15px;
} }
/* index css */
.jumbotron { .jumbotron {
text-align: center; text-align: center;
background-color: transparent; background-color: transparent;

View File

@@ -7,25 +7,36 @@ define("admin", ["jquery", "avalon"], function($, avalon){
$(".list-group-item").attr("class", "list-group-item"); $(".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); var hash = window.location.hash.substring(1);
if(hash){ if(hash){
li_active("#li-" + hash); li_active("#li-" + hash.replace("/", "-"));
show_template("template/" + hash + ".html");
}else { }else {
li_active("#li-index"); li_active("#li-index-index");
} }
window.onhashchange = function() { window.onhashchange = function() {
var hash = window.location.hash.substring(1); var hash = window.location.hash.substring(1);
if(hash){ if(hash){
li_inactive(".list-group-item"); li_inactive(".list-group-item");
li_active("#li-" + hash); li_active("#li-" + hash.replace("/", "-"));
vm.template_url = "template/index/" + hash + ".html"; show_template("template/" + hash + ".html");
} }
}; };
var vm = avalon.define({
$id: "admin",
template_url: "template/index/index.html"
});
}); });

View File

@@ -2,6 +2,7 @@ require(["jquery", "avalon", "editor", "uploader", "datetimepicker",
"validation" "validation"
], ],
function ($, avalon, editor, uploader) { function ($, avalon, editor, uploader) {
avalon.vmodels.add_contest = null;
$("#add-contest-form") $("#add-contest-form")
.formValidation({ .formValidation({
framework: "bootstrap", framework: "bootstrap",

View File

@@ -67,23 +67,25 @@
<![endif]--> <![endif]-->
<!-- browser happy end --> <!-- browser happy end -->
<div class="container" ms-controller="admin"> <div class="container main" ms-controller="admin">
<div class="row"> <div class="row">
<!-- admin left begin--> <!-- admin left begin-->
<div class="col-md-2"> <div class="col-md-2">
<ul class="list-group"> <ul class="list-group">
<li class="list-group-header">List header</li> <li class="list-group-header">List header</li>
<li class="list-group-item" id="li-index"><a href="#index">主页</a></li> <li class="list-group-item" id="li-index-index"><a href="#index/index">主页</a></li>
<li class="list-group-item" id="li-announcement"><a href="#announcement">公告</a></li> <li class="list-group-item" id="li-announcement-announcement"><a href="#announcement/announcement">公告</a></li>
<li class="list-group-item"><a href="#">Applications</a></li> <li class="list-group-item"><a href="#">Applications</a></li>
<li class="list-group-header">Another list header</li> <li class="list-group-header">比赛管理</li>
<li class="list-group-item"><a href="#">Help</a></li> <li class="list-group-item" id="li-contest-add_contest"><a href="#contest/add_contest">创建比赛</a></li>
</ul> </ul>
</div> </div>
<!-- admin left end --> <!-- admin left end -->
<img src="/static/img/loading.gif" id="loading-gif">
<!-- custom body begin --> <!-- custom body begin -->
<div class='col-md-8'ms-include-src="template_url"></div>
<div class='col-md-8' ms-include-src="template_url" data-include-rendered="hide_loading"></div>
<!-- custom body end --> <!-- custom body end -->
</div> </div>
</div> </div>

View File

@@ -1,7 +1,4 @@
{% extends "admin_base.html" %} <div ms-controller="add_contest">
{% block body %}
{% verbatim %}
<div ms-controller="add_contest">
<form id="add-contest-form"> <form id="add-contest-form">
@@ -177,9 +174,6 @@
</div> </div>
</div> </div>
</form> </form>
</div> </div>
{% endverbatim %}
{% endblock %} <script src="/static/js/app/admin/contest/contest.js"></script>
{% block js_block %}
<script src="/static/js/app/admin/contest/contest.js"></script>
{% endblock %}

View File

@@ -1,6 +1,6 @@
{% extends "oj_base.html" %} {% extends "oj_base.html" %}
{% block body %} {% block body %}
<div class="container"> <div class="container main">
<div class="col-md-6 col-md-offset-3"> <div class="col-md-6 col-md-offset-3">
<h2 class="text-center">修改密码</h2> <h2 class="text-center">修改密码</h2>

View File

@@ -1,6 +1,6 @@
{% extends "oj_base.html" %} {% extends "oj_base.html" %}
{% block body %} {% block body %}
<div class="container"> <div class="container main">
<div class="col-md-6 col-md-offset-3"> <div class="col-md-6 col-md-offset-3">
<h2 class="text-center">用户登录</h2> <h2 class="text-center">用户登录</h2>

View File

@@ -1,6 +1,6 @@
{% extends "oj_base.html" %} {% extends "oj_base.html" %}
{% block body %} {% block body %}
<div class="container"> <div class="container main">
<div class="col-md-6 col-md-offset-3"> <div class="col-md-6 col-md-offset-3">
<h2 class="text-center">用户注册</h2> <h2 class="text-center">用户注册</h2>

View File

@@ -1,6 +1,6 @@
{% extends "oj_base.html" %} {% extends "oj_base.html" %}
{% block body %} {% block body %}
<div class="container"> <div class="container main">
<ul class="nav nav-tabs nav-tabs-google"> <ul class="nav nav-tabs nav-tabs-google">
<li role="presentation" class="active"> <li role="presentation" class="active">
<a href="problem.html">题目</a></li> <a href="problem.html">题目</a></li>

View File

@@ -1,7 +1,7 @@
{% extends 'oj_base.html' %} {% extends 'oj_base.html' %}
{% block body %} {% block body %}
<div class="container"> <div class="container main">
<ul class="nav nav-tabs nav-tabs-google"> <ul class="nav nav-tabs nav-tabs-google">
<li role="presentation" class="active"> <li role="presentation" class="active">
<a href="problem.html">题目</a></li> <a href="problem.html">题目</a></li>

View File

@@ -1,6 +1,6 @@
{% extends "oj_base.html" %} {% extends "oj_base.html" %}
{% block body %} {% block body %}
<div class="container" ms-controller="problem_list"> <div class="container main" ms-controller="problem_list">
<div class="row"> <div class="row">
<div class="col-lg-9"> <div class="col-lg-9">
<div class="row"> <div class="row">