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
commit 76e3188360
17 changed files with 288 additions and 211 deletions

View File

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

View File

@ -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()

View File

@ -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"公告发布成功!"})
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 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):

View File

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

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/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;

View File

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

View File

@ -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",

View File

@ -67,23 +67,25 @@
<![endif]-->
<!-- browser happy end -->
<div class="container" ms-controller="admin">
<div class="container main" ms-controller="admin">
<div class="row">
<!-- admin left begin-->
<div class="col-md-2">
<ul class="list-group">
<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-announcement"><a href="#announcement">公告</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-announcement"><a href="#announcement/announcement">公告</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-item"><a href="#">Help</a></li>
<li class="list-group-header">比赛管理</li>
<li class="list-group-item" id="li-contest-add_contest"><a href="#contest/add_contest">创建比赛</a></li>
</ul>
</div>
<!-- admin left end -->
<img src="/static/img/loading.gif" id="loading-gif">
<!-- 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 -->
</div>
</div>

View File

@ -1,185 +1,179 @@
{% extends "admin_base.html" %}
{% block body %}
{% verbatim %}
<div ms-controller="add_contest">
<div ms-controller="add_contest">
<form id="add-contest-form">
<div class="col-md-9">
<div class="col-md-12">
<label>比赛题目</label>
<form id="add-contest-form">
<div class="col-md-9">
<div class="col-md-12">
<label>比赛题目</label>
</div>
<div class="col-md-12">
<div class="form-group">
<input type="text" name="name" class="form-control">
</div>
<div class="col-md-12">
<div class="form-group">
<input type="text" name="name" class="form-control">
</div>
</div>
<div class="col-md-12">
<label>说明</label>
</div>
<div class="col-md-12">
<div class="form-group">
<textarea id="editor" placeholder="这里输入内容" autofocus></textarea>
</div>
<div class="col-md-12">
<label>说明</label>
</div>
<div class="col-md-6">
<label>开始时间</label>
</div>
<div class="col-md-6">
<label>结束时间</label>
</div>
<div class="col-md-6">
<div class="form-group">
<input type="text" class="form-control" name="start_time" id="contest_start_time">
</div>
<div class="col-md-12">
<div class="form-group">
<textarea id="editor" placeholder="这里输入内容" autofocus></textarea>
</div>
</div>
<div class="col-md-6">
<label>开始时间</label>
</div>
<div class="col-md-6">
<label>结束时间</label>
</div>
<div class="col-md-6">
<div class="form-group">
<input type="text" class="form-control" name="start_time" id="contest_start_time">
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<input type="text" class="form-control" name="end_time" id="contest_end_time">
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<input type="text" class="form-control" name="end_time" id="contest_end_time">
</div>
</div>
<div class="col-md-6">
<label>
密码保护
</label>
<div class="col-md-6">
<label>
密码保护
</label>
</div>
<div class="col-md-3">
<label>
模式
</label>
</div>
<div class="col-md-3">
<label>
结束前是否开放排名
</label>
</div>
<div class="col-md-6">
<div class="form-group">
<input type="text" class="form-control" name="password" placeholder="留空就是公开赛">
</div>
<div class="col-md-3">
<label>
模式
</label>
</div>
<div class="col-md-3">
<div class="form-group">
<input type="radio" name="mode">OI
<input type="radio" name="mode">ACM
</div>
<div class="col-md-3">
<label>
结束前是否开放排名
</label>
</div>
<div class="col-md-6">
<div class="form-group">
<input type="text" class="form-control" name="password" placeholder="留空就是公开赛">
</div>
</div>
<div class="col-md-3">
<div class="form-group">
<input type="radio" name="mode">OI
<input type="radio" name="mode">ACM
</div>
</div>
<div class="col-md-3">
<div class="form-group">
<input type="checkbox" value="open_rank">开放排名
</div>
</div>
<div class="col-md-3">
<div class="form-group">
<input type="checkbox" value="open_rank">开放排名
</div>
</div>
<div class="col-md-12">
<label>添加题目</label>
<a href="javascript:void(0)" class="btn btn-primary btn-sm" ms-click="add_problem()">添加</a>
</div>
<div class="col-md-12">
<div class="problem" ms-repeat-problem="problems">
<div class="panel panel-default problem-panel" ms-attr-id="problem-{{ problem.id }}">
<div class="panel-heading">
<span class="panel-title">题目{{$index + 1}} </span>
<a href="javascript:void(0)" class="btn btn-primary btn-sm"
ms-click="toggle_problem(problem)">
{{ problem.toggle_string }}
</a>
<a href="javascript:void(0)" class="btn btn-danger btn-sm"
ms-click="del_problem(problem)">
删除
</a>
<div class="col-md-12">
<label>添加题目</label>
<a href="javascript:void(0)" class="btn btn-primary btn-sm" ms-click="add_problem()">添加</a>
</div>
<div class="col-md-12">
<div class="problem" ms-repeat-problem="problems">
<div class="panel panel-default problem-panel" ms-attr-id="problem-{{ problem.id }}">
<div class="panel-heading">
<span class="panel-title">题目{{$index + 1}} </span>
<a href="javascript:void(0)" class="btn btn-primary btn-sm"
ms-click="toggle_problem(problem)">
{{ problem.toggle_string }}
</a>
<a href="javascript:void(0)" class="btn btn-danger btn-sm"
ms-click="del_problem(problem)">
删除
</a>
</div>
<div class="panel-body" ms-attr-id="problem-{{ problem.id }}-body">
<div class="col-md-12">
<label>题目</label>
</div>
<div class="panel-body" ms-attr-id="problem-{{ problem.id }}-body">
<div class="col-md-12">
<label>题目</label>
</div>
<div class="col-md-12">
<div class="form-group">
<input type="text" name="problem_name[]" class="form-control">
</div>
<div class="col-md-12">
<div class="form-group">
<input type="text" name="problem_name[]" class="form-control">
</div>
<div class="col-md-6">
<label>cpu</label>
</div>
<div class="col-md-6">
<label>cpu</label>
</div>
<div class="col-md-6">
<label>内存</label>
</div>
<div class="col-md-6">
<div class="form-group">
<input type="text" name="cpu[]" class="form-control">
</div>
<div class="col-md-6">
<label>内存</label>
</div>
<div class="col-md-6">
<div class="form-group">
<input type="text" name="memory[]" class="form-control">
</div>
<div class="col-md-6">
<div class="form-group">
<input type="text" name="cpu[]" class="form-control">
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<input type="text" name="memory[]" class="form-control">
</div>
</div>
<div class="col-md-12">
</div>
<div class="col-md-12">
<label>样例</label>
<a href="javascript:void(0)" class="btn btn-primary btn-sm"
ms-click="add_sample(problem)">
添加
</a>
<label>样例</label>
<a href="javascript:void(0)" class="btn btn-primary btn-sm"
ms-click="add_sample(problem)">
添加
</a>
<div class="sample">
<div class="panel panel-default sample-panel"
ms-repeat-sample="problem.samples">
<div class="panel-heading">
<span class="panel-title">样例{{$index + 1}}</span>
<div class="sample">
<div class="panel panel-default sample-panel"
ms-repeat-sample="problem.samples">
<div class="panel-heading">
<span class="panel-title">样例{{$index + 1}}</span>
<a href="javascript:void(0)" class="btn btn-primary btn-sm"
ms-click="toggle_sample(problem, sample)">
{{ sample.toggle_string }}
</a>
<a href="javascript:void(0)" class="btn btn-danger btn-sm"
ms-click="del_sample(problem, sample)">
删除
</a>
<a href="javascript:void(0)" class="btn btn-primary btn-sm"
ms-click="toggle_sample(problem, sample)">
{{ sample.toggle_string }}
</a>
<a href="javascript:void(0)" class="btn btn-danger btn-sm"
ms-click="del_sample(problem, sample)">
删除
</a>
</div>
<div class="panel-body"
ms-attr-id="problem-{{ problem.id }}-sampleio-{{ sample.id }}-body">
<div class="col-md-12">
<label>样例输入</label>
</div>
<div class="panel-body"
ms-attr-id="problem-{{ problem.id }}-sampleio-{{ sample.id }}-body">
<div class="col-md-12">
<label>样例输入</label>
<div class="col-md-12">
<div class="form-group">
<textarea class="form-control" rows="5"></textarea>
</div>
<div class="col-md-12">
<div class="form-group">
<textarea class="form-control" rows="5"></textarea>
</div>
</div>
<div class="col-md-12">
<label>样例输出</label>
</div>
<div class="col-md-12">
<div class="form-group">
<textarea class="form-control" rows="5"></textarea>
</div>
</div>
<div class="col-md-12">
<label>样例输出</label>
</div>
<div class="col-md-12">
<div class="form-group">
<textarea class="form-control" rows="5"></textarea>
</div>
</div>
</div>
</div>
</div>
<div class="col-md-12">
<label>测试数据</label>
</div>
<div class="col-md-12">
<div class="form-group">
<div ms-attr-id="problem-{{ problem.id }}-uploader">选择文件</div>
</div>
<div class="col-md-12">
<label>测试数据</label>
</div>
<div class="col-md-12">
<div class="form-group">
<div ms-attr-id="problem-{{ problem.id }}-uploader">选择文件</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</form>
</div>
{% endverbatim %}
{% endblock %}
{% block js_block %}
<script src="/static/js/app/admin/contest/contest.js"></script>
{% endblock %}
</div>
</form>
</div>
<script src="/static/js/app/admin/contest/contest.js"></script>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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