commit 7d22fdf57fce8dda04cc8be2b4214840f25f2e63 Author: starschen Date: Tue Jul 21 09:32:48 2015 +0800 init diff --git a/auth/models.py b/auth/models.py new file mode 100644 index 0000000..d90c72d --- /dev/null +++ b/auth/models.py @@ -0,0 +1,20 @@ +#encoding:utf8 +from db import db +from flask.ext.security import UserMixin, RoleMixin + +class Role(db.Document, RoleMixin): + name = db.StringField(max_length=80, unique=True) + description = db.StringField(max_length=255) + + def __unicode__(self): + return self.name + +class User(db.Document, UserMixin): + email = db.StringField(max_length=255) + password = db.StringField(max_length=255) + active = db.BooleanField(default=True) + confirmed_at = db.DateTimeField() + roles = db.ListField(db.ReferenceField(Role), default=[]) + + def __unicode__(self): + return self.email \ No newline at end of file diff --git a/auth/views.py b/auth/views.py new file mode 100644 index 0000000..de01599 --- /dev/null +++ b/auth/views.py @@ -0,0 +1,12 @@ +#encoding: utf8 + +from flask.ext.admin.contrib.mongoengine import ModelView +from flask.ext.security import current_user + +class UserAdmin(ModelView): + def is_accessible(self): + return current_user.has_role('admin') + +class RoleAdmin(ModelView): + def is_accessible(self): + return current_user.has_role('admin') \ No newline at end of file diff --git a/babel.cfg b/babel.cfg new file mode 100644 index 0000000..0cc0bac --- /dev/null +++ b/babel.cfg @@ -0,0 +1,3 @@ +[python: **.py] +[jinja2: **/templates/**.html] +extensions=jinja2.ext.autoescape,jinja2.ext.with_ \ No newline at end of file diff --git a/data/.~lock.第二轮汇总表.xls# b/data/.~lock.第二轮汇总表.xls# new file mode 100644 index 0000000..732cc17 --- /dev/null +++ b/data/.~lock.第二轮汇总表.xls# @@ -0,0 +1 @@ +,bjh,bjh-virtual-machine,23.05.2015 19:35,file:///home/bjh/.config/libreoffice/4; \ No newline at end of file diff --git a/data/import_data.py b/data/import_data.py new file mode 100644 index 0000000..8ff9513 --- /dev/null +++ b/data/import_data.py @@ -0,0 +1,57 @@ +#encoding: utf8 +import xlrd +import sys +sys.path.append('..') +from mongodb import guandan_db + +def import_namelist(): + book = xlrd.open_workbook(u'掼蛋比赛名单.xls') + table = book.sheet_by_index(0) + + nrows = table.nrows + ncols = table.ncols + game = guandan_db.game.find_one({'name':u'徐州市第十六届“中国大地保险杯”掼蛋比赛'}) + + for i in range(1, nrows): + record = {} + record['game'] = game['_id'] + record['no'] = i + record['company'] = table.cell(i,0).value + record['team_no'] = table.cell(i,1).value + record['players'] = table.cell(i,2).value + guandan_db.name_list.insert(record) + +def import_gamerecord(): + book = xlrd.open_workbook(u'第二轮汇总表.xls') + table = book.sheet_by_index(0) + calced_teams = set() + + nrows = table.nrows + ncols = table.ncols + + count = 0 + for i in range(1, nrows): + if table.cell(i,3).value in calced_teams: + continue + record = {} + record['round'] = 1 + record['red'] = guandan_db.name_list.find_one(dict(team_no=table.cell(i,1).value))['_id'] + record['blue'] = guandan_db.name_list.find_one(dict(team_no=table.cell(i,3).value))['_id'] + scores = table.cell(i,4).value.split('/') + if int(scores[0]) == 2: + record['result'] = u'红方胜' + elif int(scores[0]) == 0: + record['result'] = u'蓝方胜' + elif int(scores[0]) == 1: + record['result'] = u'平局' + elif int(scores[0]) == -1: + record['result'] = u'红方弃权' + record['diff'] = abs(int(scores[1])) + count += 1 + record['desk_no'] = count + calced_teams.add(table.cell(i,1).value) + calced_teams.add(table.cell(i,3).value) + #print record + guandan_db.game_record.insert(record) + +import_gamerecord() \ No newline at end of file diff --git a/data/掼蛋比赛名单.xls b/data/掼蛋比赛名单.xls new file mode 100644 index 0000000..c3ad517 Binary files /dev/null and b/data/掼蛋比赛名单.xls differ diff --git a/data/第二轮汇总表.xls b/data/第二轮汇总表.xls new file mode 100644 index 0000000..bf65859 Binary files /dev/null and b/data/第二轮汇总表.xls differ diff --git a/db.py b/db.py new file mode 100644 index 0000000..6e9698f --- /dev/null +++ b/db.py @@ -0,0 +1,5 @@ +#encoding:utf8 + +from flask.ext.mongoengine import MongoEngine + +db = MongoEngine() diff --git a/filters.py b/filters.py new file mode 100644 index 0000000..97f1655 --- /dev/null +++ b/filters.py @@ -0,0 +1,15 @@ +#encoding: utf8 +from flask_admin.contrib.mongoengine.filters import BaseMongoEngineFilter +from game.models import Game +from flask_admin.babel import lazy_gettext + +class FilterGame(BaseMongoEngineFilter): + def apply(self, query, value): + return query.filter(game__exact=Game.objects(name__exact=value).first().id) + + def operation(self): + return lazy_gettext('exact') + + def get_options(self, view): + game_list = [(obj.name, obj.name) for obj in Game.objects()] + return game_list \ No newline at end of file diff --git a/forms.py b/forms.py new file mode 100644 index 0000000..97752fe --- /dev/null +++ b/forms.py @@ -0,0 +1,11 @@ +#encoding: utf8 + +from wtforms import Form, SelectField + +class BallotForm(Form): + game = SelectField(u'赛事') + ballot_type = SelectField(u'首轮抽签方式', choices=[('random', u'随机'), ('sequence', u'顺序')]) + +class RankForm(Form): + game = SelectField(u'赛事') + rank_type = SelectField(u'排名类型', choices=[('team', u'队伍排名'), ('company', u'团体排名')]) \ No newline at end of file diff --git a/game/__init__.py b/game/__init__.py new file mode 100644 index 0000000..fab5a41 --- /dev/null +++ b/game/__init__.py @@ -0,0 +1,2 @@ +import models +import views diff --git a/game/models.py b/game/models.py new file mode 100644 index 0000000..663273d --- /dev/null +++ b/game/models.py @@ -0,0 +1,11 @@ +#encoding: utf8 + +import sys +sys.path.append('..') +from db import db + +class Game(db.Document): + name = db.StringField(verbose_name=u'赛事名称') + + def __unicode__(self): + return self.name \ No newline at end of file diff --git a/game/views.py b/game/views.py new file mode 100644 index 0000000..f57617c --- /dev/null +++ b/game/views.py @@ -0,0 +1,9 @@ +#encoding: utf8 + +from flask.ext.admin.contrib.mongoengine import ModelView + +class GameAdmin(ModelView): + page_size = 15 + column_labels = { + 'name': u'赛事名称', + } diff --git a/game_record/__init__.py b/game_record/__init__.py new file mode 100644 index 0000000..fab5a41 --- /dev/null +++ b/game_record/__init__.py @@ -0,0 +1,2 @@ +import models +import views diff --git a/game_record/models.py b/game_record/models.py new file mode 100644 index 0000000..6cdeb6d --- /dev/null +++ b/game_record/models.py @@ -0,0 +1,16 @@ +#encoding: utf8 + +import sys +sys.path.append('..') +from db import db +from namelist.models import NameList +from game.models import Game + +class GameRecord(db.Document): + game = db.ReferenceField(Game, verbose_name=u'赛事') + round = db.IntField(verbose_name=u'轮次') + desk_no = db.IntField(verbose_name=u'桌号') + red = db.ReferenceField(NameList, verbose_name=u'红方') + blue = db.ReferenceField(NameList, verbose_name=u'蓝方') + result = db.StringField(choices=[(u'红方胜', u'红方胜'), (u'蓝方胜', u'蓝方胜'), (u'平局', u'平局'), (u'红方弃权', u'红方弃权'), (u'蓝方弃权', u'蓝方弃权')], verbose_name=u'赛果') + diff = db.IntField(default=6, verbose_name=u'级差') #级差 \ No newline at end of file diff --git a/game_record/views.py b/game_record/views.py new file mode 100644 index 0000000..4d0cf84 --- /dev/null +++ b/game_record/views.py @@ -0,0 +1,21 @@ +#encoding: utf8 + +from flask.ext.admin.contrib.mongoengine import ModelView +from flask.ext.admin import BaseView, expose +import sys +sys.path.append('..') +from filters import FilterGame + +class GameRecordAdmin(ModelView): + page_size = 15 + column_labels = { + 'game': u'赛事', + 'round': u'轮次', + 'desk_no': u'桌号', + 'red': u'红方', + 'blue': u'蓝方', + 'result': u'赛果', + 'diff': u'级差', + } + + column_filters = ['round', FilterGame('game', u'赛事')] \ No newline at end of file diff --git a/main.py b/main.py new file mode 100644 index 0000000..159d6a6 --- /dev/null +++ b/main.py @@ -0,0 +1,33 @@ +#encoding: utf8 + +from flask import Flask, render_template +from flask.ext.basicauth import BasicAuth +from flask.ext.babel import Babel +from flask.ext.admin import Admin, AdminIndexView +import namelist +import game_record +import game +from views import * +from db import db + +app = Flask(__name__) +app.config.from_object("settings") + +basic_auth = BasicAuth(app) +db.init_app(app) +babel = Babel(app) + +#admin +admin = Admin(app, u'掼蛋赛事管理系统', template_mode='bootstrap3', index_view=AdminIndexView( + name=u'主页', + template='admin/index.html', + url='/' + )) +admin.add_view(game.views.GameAdmin(game.models.Game, name=u'赛事', endpoint='game')) +admin.add_view(namelist.views.NameListAdmin(namelist.models.NameList, name=u'比赛名单', endpoint='namelist')) +admin.add_view(game_record.views.GameRecordAdmin(game_record.models.GameRecord, name=u'比赛记录', endpoint='game-record')) +admin.add_view(BallotView(name=u'抽签', endpoint='ballot')) +admin.add_view(RankView(name=u'排名', endpoint='rank')) + +if __name__ == '__main__': + app.run(host='0.0.0.0', debug=True) diff --git a/mongodb.py b/mongodb.py new file mode 100644 index 0000000..8f216e6 --- /dev/null +++ b/mongodb.py @@ -0,0 +1,15 @@ +#encoding: utf8 + +import pymongo + +class MongoDB: + def __init__(self,user,password,dbname, host='127.0.0.1',port=27017): + self.host = host + self.port = port + self.user = user + self.password = password + self.conn = pymongo.Connection(self.host,int(self.port)) + self.db = self.conn[dbname] + self.db.authenticate(self.user,self.password) + +guandan_db = MongoDB(user='guandan', password='jiaojiao', dbname='guandan').db \ No newline at end of file diff --git a/name_list.json b/name_list.json new file mode 100644 index 0000000..e8fcce3 --- /dev/null +++ b/name_list.json @@ -0,0 +1,128 @@ +{"_id":{"$oid":"5558100beea2a606e8d791c5"},"company":"南京周周掼扑克牌俱乐部","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(1),"players":"徐建明/张发利","team_no":"01A"} +{"_id":{"$oid":"5558100beea2a606e8d791c6"},"company":"徐州民政医院","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(2),"players":"杜长军/许亚峰","team_no":"02A"} +{"_id":{"$oid":"5558100beea2a606e8d791c7"},"company":"徐州宣武集团","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(3),"players":"林一林/姚成光","team_no":"03A"} +{"_id":{"$oid":"5558100beea2a606e8d791c8"},"company":"新城区城管执法大队","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(4),"players":"黄晓一/王继刚","team_no":"04A"} +{"_id":{"$oid":"5558100beea2a606e8d791c9"},"company":"徐州市粮食局","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(5),"players":"贾浙宁/谢秀杰","team_no":"05A"} +{"_id":{"$oid":"5558100beea2a606e8d791ca"},"company":"徐州市第三十六中学","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(6),"players":"陈飞荣/高 明","team_no":"06A"} +{"_id":{"$oid":"5558100beea2a606e8d791cb"},"company":"徐州市第一人民医院","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(7),"players":"谢 超/蔡军良","team_no":"07A"} +{"_id":{"$oid":"5558100beea2a606e8d791cc"},"company":"扬州富愉掼蛋俱乐部","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(8),"players":"刘霞/毕海燕","team_no":"08A"} +{"_id":{"$oid":"5558100beea2a606e8d791cd"},"company":"江苏中正房地产公司","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(9),"players":"杨 超/孟 强","team_no":"09A"} +{"_id":{"$oid":"5558100beea2a606e8d791ce"},"company":"徐州市计生委","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(10),"players":"李建光/薛 杰","team_no":"10A"} +{"_id":{"$oid":"5558100beea2a606e8d791cf"},"company":"徐州兴隆国际大酒店","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(11),"players":"张世龙/孟凡森","team_no":"11A"} +{"_id":{"$oid":"5558100beea2a606e8d791d0"},"company":"红星女子掼蛋队","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(12),"players":"蒋 侠(女)/潘月梅(女)","team_no":"12A"} +{"_id":{"$oid":"5558100beea2a606e8d791d1"},"company":"徐州开元名都大酒店一队","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(13),"players":"夏 铭/朱雪松","team_no":"13A"} +{"_id":{"$oid":"5558100beea2a606e8d791d2"},"company":"江苏雅黛掼蛋俱乐部","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(14),"players":"燕 文/谢旭红(女)","team_no":"14A"} +{"_id":{"$oid":"5558100beea2a606e8d791d3"},"company":"徐州市卫生计量检测所","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(15),"players":"张 勇/刘 易","team_no":"15A"} +{"_id":{"$oid":"5558100beea2a606e8d791d4"},"company":"镇江豪友扑克俱乐部","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(16),"players":"江杰豪/张 震","team_no":"16A"} +{"_id":{"$oid":"5558100beea2a606e8d791d5"},"company":"徐州市档案局","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(17),"players":"程昔刚/汪凤国","team_no":"17A"} +{"_id":{"$oid":"5558100beea2a606e8d791d6"},"company":"徐州永宏双升俱乐部","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(18),"players":"霍仁礼/戴茂生","team_no":"18A"} +{"_id":{"$oid":"5558100beea2a606e8d791d7"},"company":"江苏苏铝铝业公司一队","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(19),"players":"忻培清/陈荣水","team_no":"19A"} +{"_id":{"$oid":"5558100beea2a606e8d791d8"},"company":"徐州市卫生局一队","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(20),"players":"鹿启全/吴 兵","team_no":"20A"} +{"_id":{"$oid":"5558100beea2a606e8d791d9"},"company":"徐州市水务局","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(21),"players":"张 浩/贺恒利","team_no":"21A"} +{"_id":{"$oid":"5558100beea2a606e8d791da"},"company":"徐州市城市管理局一队","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(22),"players":"张银河/高吉才","team_no":"22A"} +{"_id":{"$oid":"5558100beea2a606e8d791db"},"company":"徐矿集团有限公司","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(23),"players":"蒋宝淦/郭运良","team_no":"23A"} +{"_id":{"$oid":"5558100beea2a606e8d791dc"},"company":"东海移动公司","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(24),"players":"单新民/仉 东","team_no":"24A"} +{"_id":{"$oid":"5558100beea2a606e8d791dd"},"company":"徐州大地保险公司","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(25),"players":"毛 爽/段卫华","team_no":"25A"} +{"_id":{"$oid":"5558100beea2a606e8d791de"},"company":"云龙公园","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(26),"players":"高 磊/张茂让","team_no":"26A"} +{"_id":{"$oid":"5558100beea2a606e8d791df"},"company":"糖葫芦掼蛋俱乐部","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(27),"players":"张 虎/吴月锋","team_no":"27A"} +{"_id":{"$oid":"5558100beea2a606e8d791e0"},"company":"市侨联","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(28),"players":"吴 彬/田同峰","team_no":"28A"} +{"_id":{"$oid":"5558100beea2a606e8d791e1"},"company":"徐州质量技术监督局","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(29),"players":"刘 幸/王 珲","team_no":"29A"} +{"_id":{"$oid":"5558100beea2a606e8d791e2"},"company":"卡特彼勒徐州公司一队","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(30),"players":"陈兴群/张 震","team_no":"30A"} +{"_id":{"$oid":"5558100beea2a606e8d791e3"},"company":"圣戈班(徐州)管道公司一队","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(31),"players":"张爱民/申福勇","team_no":"31A"} +{"_id":{"$oid":"5558100beea2a606e8d791e4"},"company":"泰州海洋起亚掼蛋俱乐部","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(32),"players":"耿晓军/高志兵","team_no":"32A"} +{"_id":{"$oid":"5558100beea2a606e8d791e5"},"company":"徐州市第一中学","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(33),"players":"张帮程/程 猛","team_no":"33A"} +{"_id":{"$oid":"5558100beea2a606e8d791e6"},"company":"格力电器","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(34),"players":"陈玉顶/陈桂德","team_no":"34A"} +{"_id":{"$oid":"5558100beea2a606e8d791e7"},"company":"市侨办","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(35),"players":"郭振田/周建科","team_no":"35A"} +{"_id":{"$oid":"5558100beea2a606e8d791e8"},"company":"江苏万通酿造有限公司","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(36),"players":"王本强/王心强","team_no":"36A"} +{"_id":{"$oid":"5558100beea2a606e8d791e9"},"company":"徐州幼儿师范高等专科学校","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(37),"players":"李彦松/高 峰","team_no":"37A"} +{"_id":{"$oid":"5558100beea2a606e8d791ea"},"company":"弘扬掼蛋文化俱乐部","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(38),"players":"史先停/王茂军","team_no":"38A"} +{"_id":{"$oid":"5558100beea2a606e8d791eb"},"company":"江苏天勤机电设备公司","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(39),"players":"徐 君/陈光林","team_no":"39A"} +{"_id":{"$oid":"5558100beea2a606e8d791ec"},"company":"淮安市楚淮掼蛋俱乐部","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(40),"players":"王立涛/陈雪生","team_no":"40A"} +{"_id":{"$oid":"5558100beea2a606e8d791ed"},"company":"徐州工商行政管理局","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(41),"players":"朱卫国/彭 勇","team_no":"41A"} +{"_id":{"$oid":"5558100beea2a606e8d791ee"},"company":"徐州建行","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(42),"players":"刘 伟/孙 钢","team_no":"42A"} +{"_id":{"$oid":"5558100beea2a606e8d791ef"},"company":"徐州市城市管理局二队","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(43),"players":"徐 品/石玉雷","team_no":"43A"} +{"_id":{"$oid":"5558100beea2a606e8d791f0"},"company":"万国掼蛋俱乐部","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(44),"players":"徐 跃/苏 可","team_no":"44A"} +{"_id":{"$oid":"5558100beea2a606e8d791f1"},"company":"徐州市彭祖园管理处","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(45),"players":"王继文/陈 明","team_no":"45A"} +{"_id":{"$oid":"5558100beea2a606e8d791f2"},"company":"徐州电大","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(46),"players":"潘 侠/单志毅","team_no":"46A"} +{"_id":{"$oid":"5558100beea2a606e8d791f3"},"company":"徐州医学院","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(47),"players":"刘兴刚/郑朝阳","team_no":"47A"} +{"_id":{"$oid":"5558100beea2a606e8d791f4"},"company":"连云港掼蛋俱乐部","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(48),"players":"江舜超/刘 琇","team_no":"48A"} +{"_id":{"$oid":"5558100beea2a606e8d791f5"},"company":"徐州市体育局","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(49),"players":"贺方全/杨友俊","team_no":"49A"} +{"_id":{"$oid":"5558100beea2a606e8d791f6"},"company":"徐州开元名都大酒店二队","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(50),"players":"侯金栋/叶德波","team_no":"50A"} +{"_id":{"$oid":"5558100beea2a606e8d791f7"},"company":"沂沭泗水利管理局","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(51),"players":"杨 伟/范 宇","team_no":"51A"} +{"_id":{"$oid":"5558100beea2a606e8d791f8"},"company":"徐州出入境检验检疫局","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(52),"players":"吴亚力/顾建华","team_no":"52A"} +{"_id":{"$oid":"5558100beea2a606e8d791f9"},"company":"徐州市卫生局二队","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(53),"players":"甘国永/朱卫东","team_no":"53A"} +{"_id":{"$oid":"5558100beea2a606e8d791fa"},"company":"卡特彼勒徐州公司二队","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(54),"players":"袁 猛/江 楠","team_no":"54A"} +{"_id":{"$oid":"5558100beea2a606e8d791fb"},"company":"淮海蔬菜批发市场","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(55),"players":"贾 勇/宋 兵","team_no":"55A"} +{"_id":{"$oid":"5558100beea2a606e8d791fc"},"company":"宿迁市棋牌协会","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(56),"players":"朱林军/寺胜利","team_no":"56A"} +{"_id":{"$oid":"5558100beea2a606e8d791fd"},"company":"中石化管道储运有限公司","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(57),"players":"马 育/杨全友","team_no":"57A"} +{"_id":{"$oid":"5558100beea2a606e8d791fe"},"company":"润速达货运公司","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(58),"players":"宁连敏/戴建荣","team_no":"58A"} +{"_id":{"$oid":"5558100beea2a606e8d791ff"},"company":"徐州邮政局","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(59),"players":"王 东/张 立","team_no":"59A"} +{"_id":{"$oid":"5558100beea2a606e8d79200"},"company":"江苏苏铝铝业公司二队","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(60),"players":"于徐生/蔡宗洲","team_no":"60A"} +{"_id":{"$oid":"5558100beea2a606e8d79201"},"company":"圣戈班(徐州)管道公司二队","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(61),"players":"何家海/陈洪生","team_no":"61A"} +{"_id":{"$oid":"5558100beea2a606e8d79202"},"company":"徐州市植物园","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(62),"players":"徐万泰/郑百顺","team_no":"62A"} +{"_id":{"$oid":"5558100beea2a606e8d79203"},"company":"徐州农行","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(63),"players":"胡 勇/陈 勇","team_no":"63A"} +{"_id":{"$oid":"5558100beea2a606e8d79204"},"company":"江苏今世缘酒业公司","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(64),"players":"杨晓东/张锡瑞","team_no":"64A"} +{"_id":{"$oid":"5558100beea2a606e8d79205"},"company":"卡特彼勒徐州公司一队","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(65),"players":"张 凯/宁 禹","team_no":"30B"} +{"_id":{"$oid":"5558100beea2a606e8d79206"},"company":"南京周周掼扑克牌俱乐部","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(66),"players":"杜雨光/徐 苏","team_no":"01B"} +{"_id":{"$oid":"5558100beea2a606e8d79207"},"company":"润速达货运公司","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(67),"players":"张 杰/韩 平","team_no":"58B"} +{"_id":{"$oid":"5558100beea2a606e8d79208"},"company":"徐州永宏双升俱乐部","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(68),"players":"刘道宇/吴洪雨","team_no":"18B"} +{"_id":{"$oid":"5558100beea2a606e8d79209"},"company":"徐州建行","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(69),"players":"王慎军/郭 杰","team_no":"42B"} +{"_id":{"$oid":"5558100beea2a606e8d7920a"},"company":"徐矿集团有限公司","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(70),"players":"赵 波/李永刚","team_no":"23B"} +{"_id":{"$oid":"5558100beea2a606e8d7920b"},"company":"淮海蔬菜批发市场","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(71),"players":"吴 宁/何如来","team_no":"55B"} +{"_id":{"$oid":"5558100beea2a606e8d7920c"},"company":"泰州海洋起亚掼蛋俱乐部","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(72),"players":"王小强/田正祥","team_no":"32B"} +{"_id":{"$oid":"5558100beea2a606e8d7920d"},"company":"中石化管道储运有限公司","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(73),"players":"孙成德/黄烈勇","team_no":"57B"} +{"_id":{"$oid":"5558100beea2a606e8d7920e"},"company":"徐州市彭祖园管理处","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(74),"players":"余 瑛(女)/王 霞(女)","team_no":"45B"} +{"_id":{"$oid":"5558100beea2a606e8d7920f"},"company":"徐州出入境检验检疫局","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(75),"players":"伊仰东/陈 焱","team_no":"52B"} +{"_id":{"$oid":"5558100beea2a606e8d79210"},"company":"徐州幼儿师范高等专科学校","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(76),"players":"王 震/严加明","team_no":"37B"} +{"_id":{"$oid":"5558100beea2a606e8d79211"},"company":"弘扬掼蛋文化俱乐部","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(77),"players":"顾再生/袁先林","team_no":"38B"} +{"_id":{"$oid":"5558100beea2a606e8d79212"},"company":"徐州宣武集团","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(78),"players":"盛建东/饶瑞泉","team_no":"03B"} +{"_id":{"$oid":"5558100beea2a606e8d79213"},"company":"江苏苏铝铝业公司一队","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(79),"players":"马树申/汪永居","team_no":"19B"} +{"_id":{"$oid":"5558100beea2a606e8d79214"},"company":"东海移动公司","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(80),"players":"高 源/朱建华","team_no":"24B"} +{"_id":{"$oid":"5558100beea2a606e8d79215"},"company":"云龙公园","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(81),"players":"吕永斌/王元勋","team_no":"26B"} +{"_id":{"$oid":"5558100beea2a606e8d79216"},"company":"徐州市卫生计量检测所","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(82),"players":"陈 腾/陆 强","team_no":"15B"} +{"_id":{"$oid":"5558100beea2a606e8d79217"},"company":"市侨联","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(83),"players":"李秋絮(女)/邬文英(女)","team_no":"28B"} +{"_id":{"$oid":"5558100beea2a606e8d79218"},"company":"徐州开元名都大酒店二队","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(84),"players":"郑 永/赵维灿","team_no":"50B"} +{"_id":{"$oid":"5558100beea2a606e8d79219"},"company":"徐州市卫生局一队","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(85),"players":"史为栋/孙 萍(女)","team_no":"20B"} +{"_id":{"$oid":"5558100beea2a606e8d7921a"},"company":"徐州市第一人民医院","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(86),"players":"李玉强/时晓东","team_no":"07B"} +{"_id":{"$oid":"5558100beea2a606e8d7921b"},"company":"万国掼蛋俱乐部","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(87),"players":"郑 晨/郑庆国","team_no":"44B"} +{"_id":{"$oid":"5558100beea2a606e8d7921c"},"company":"江苏万通酿造有限公司","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(88),"players":"何建军/刘建华","team_no":"36B"} +{"_id":{"$oid":"5558100beea2a606e8d7921d"},"company":"镇江豪友扑克俱乐部","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(89),"players":"郦建纲/吴剑峰","team_no":"16B"} +{"_id":{"$oid":"5558100beea2a606e8d7921e"},"company":"徐州农行","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(90),"players":"张翠虎/赵支援","team_no":"63B"} +{"_id":{"$oid":"5558100beea2a606e8d7921f"},"company":"徐州市植物园","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(91),"players":"周海彬/刘 建","team_no":"62B"} +{"_id":{"$oid":"5558100beea2a606e8d79220"},"company":"圣戈班(徐州)管道公司一队","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(92),"players":"许 明/郝 钢","team_no":"31B"} +{"_id":{"$oid":"5558100beea2a606e8d79221"},"company":"徐州民政医院","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(93),"players":"薛玉光/廖松峰","team_no":"02B"} +{"_id":{"$oid":"5558100beea2a606e8d79222"},"company":"徐州市城市管理局一队","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(94),"players":"郝献宏/张继民","team_no":"22B"} +{"_id":{"$oid":"5558100beea2a606e8d79223"},"company":"格力电器","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(95),"players":"彭 权/徐 强","team_no":"34B"} +{"_id":{"$oid":"5558100beea2a606e8d79224"},"company":"扬州富愉掼蛋俱乐部","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(96),"players":"王义红/金 晨","team_no":"08B"} +{"_id":{"$oid":"5558100beea2a606e8d79225"},"company":"徐州市粮食局","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(97),"players":"孙 新/郭继升","team_no":"05B"} +{"_id":{"$oid":"5558100beea2a606e8d79226"},"company":"徐州市水务局","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(98),"players":"王志刚/张茂生","team_no":"21B"} +{"_id":{"$oid":"5558100beea2a606e8d79227"},"company":"江苏天勤机电设备公司","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(99),"players":"王雪峰/潘建峰","team_no":"39B"} +{"_id":{"$oid":"5558100beea2a606e8d79228"},"company":"新城区城管执法大队","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(100),"players":"许 浒/田苏骥","team_no":"04B"} +{"_id":{"$oid":"5558100beea2a606e8d79229"},"company":"江苏雅黛掼蛋俱乐部","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(101),"players":"祝荣根/周柏林","team_no":"14B"} +{"_id":{"$oid":"5558100beea2a606e8d7922a"},"company":"江苏今世缘酒业公司","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(102),"players":"褚福利/陈 亮","team_no":"64B"} +{"_id":{"$oid":"5558100beea2a606e8d7922b"},"company":"徐州市计生委","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(103),"players":"周 峰/周英慧","team_no":"10B"} +{"_id":{"$oid":"5558100beea2a606e8d7922c"},"company":"徐州工商行政管理局","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(104),"players":"陈金彪/张恒桥","team_no":"41B"} +{"_id":{"$oid":"5558100beea2a606e8d7922d"},"company":"江苏中正房地产公司","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(105),"players":"张金武/丁会兵","team_no":"09B"} +{"_id":{"$oid":"5558100beea2a606e8d7922e"},"company":"沂沭泗水利管理局","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(106),"players":"黄耀光/王世祯","team_no":"51B"} +{"_id":{"$oid":"5558100beea2a606e8d7922f"},"company":"市侨办","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(107),"players":"葛 炜/陈茂林","team_no":"35B"} +{"_id":{"$oid":"5558100beea2a606e8d79230"},"company":"淮安市楚淮掼蛋俱乐部","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(108),"players":"杨鑫铭/杨国龙","team_no":"40B"} +{"_id":{"$oid":"5558100beea2a606e8d79231"},"company":"徐州电大","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(109),"players":"吴志丹/魏金森","team_no":"46B"} +{"_id":{"$oid":"5558100beea2a606e8d79232"},"company":"徐州兴隆国际大酒店","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(110),"players":"欧 晶/伏长海","team_no":"11B"} +{"_id":{"$oid":"5558100beea2a606e8d79233"},"company":"徐州大地保险公司","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(111),"players":"徐 庆/宋友亮","team_no":"25B"} +{"_id":{"$oid":"5558100beea2a606e8d79234"},"company":"徐州开元名都大酒店一队","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(112),"players":"陈 鹏/石时民","team_no":"13B"} +{"_id":{"$oid":"5558100beea2a606e8d79235"},"company":"徐州市第一中学","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(113),"players":"赵 永/王德刚","team_no":"33B"} +{"_id":{"$oid":"5558100beea2a606e8d79236"},"company":"徐州市卫生局二队","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(114),"players":"蒋连峰/杜 雷","team_no":"53B"} +{"_id":{"$oid":"5558100beea2a606e8d79237"},"company":"徐州市体育局","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(115),"players":"王 磊/戴礼军","team_no":"49B"} +{"_id":{"$oid":"5558100beea2a606e8d79238"},"company":"连云港掼蛋俱乐部","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(116),"players":"刘 斌/王华江","team_no":"48B"} +{"_id":{"$oid":"5558100beea2a606e8d79239"},"company":"徐州医学院","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(117),"players":"李汉春/张建忠","team_no":"47B"} +{"_id":{"$oid":"5558100beea2a606e8d7923a"},"company":"卡特彼勒徐州公司二队","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(118),"players":"卢 涛/徐培雷","team_no":"54B"} +{"_id":{"$oid":"5558100beea2a606e8d7923b"},"company":"糖葫芦掼蛋俱乐部","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(119),"players":"高锦生/赵 岩","team_no":"27B"} +{"_id":{"$oid":"5558100beea2a606e8d7923c"},"company":"江苏苏铝铝业公司二队","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(120),"players":"李海松/王 磊","team_no":"60B"} +{"_id":{"$oid":"5558100beea2a606e8d7923d"},"company":"徐州市城市管理局二队","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(121),"players":"单古剑/张成明","team_no":"43B"} +{"_id":{"$oid":"5558100beea2a606e8d7923e"},"company":"红星女子掼蛋队","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(122),"players":"殷雪颖(女)/步云云(女)","team_no":"12B"} +{"_id":{"$oid":"5558100beea2a606e8d7923f"},"company":"圣戈班(徐州)管道公司二队","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(123),"players":"王慎君/王银平","team_no":"61B"} +{"_id":{"$oid":"5558100beea2a606e8d79240"},"company":"宿迁市棋牌协会","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(124),"players":"武传智/程晓东","team_no":"56B"} +{"_id":{"$oid":"5558100beea2a606e8d79241"},"company":"徐州质量技术监督局","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(125),"players":"田 可/惠洪德","team_no":"29B"} +{"_id":{"$oid":"5558100beea2a606e8d79242"},"company":"徐州市档案局","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(126),"players":"赵德恩/牛庆峰","team_no":"17B"} +{"_id":{"$oid":"5558100beea2a606e8d79243"},"company":"徐州邮政局","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(127),"players":"王 刚/王厚诚","team_no":"59B"} +{"_id":{"$oid":"5558100beea2a606e8d79244"},"company":"徐州市第三十六中学","game":{"$oid":"55580ffeeea2a606d590bc99"},"no":NumberInt(128),"players":"代苏建/孙奇军","team_no":"06B"} diff --git a/namelist/__init__.py b/namelist/__init__.py new file mode 100644 index 0000000..fab5a41 --- /dev/null +++ b/namelist/__init__.py @@ -0,0 +1,2 @@ +import models +import views diff --git a/namelist/models.py b/namelist/models.py new file mode 100644 index 0000000..d1b6898 --- /dev/null +++ b/namelist/models.py @@ -0,0 +1,16 @@ +#encoding: utf8 + +import sys +sys.path.append('..') +from db import db +from game.models import Game + +class NameList(db.Document): + game = db.ReferenceField(Game, verbose_name=u'赛事') + no = db.IntField(unique_with='game', verbose_name=u'赛号') + company = db.StringField(verbose_name=u'单位名称') + team_no = db.StringField(verbose_name=u'队伍编号') + players = db.StringField(verbose_name=u'选手') + + def __unicode__(self): + return u'赛号:%d 选手:%s 单位:%s' % (self.no, self.players, self.company) diff --git a/namelist/views.py b/namelist/views.py new file mode 100644 index 0000000..3a6e258 --- /dev/null +++ b/namelist/views.py @@ -0,0 +1,18 @@ +#encoding: utf8 + +from flask.ext.admin.contrib.mongoengine import ModelView +import sys +sys.path.append('..') +from filters import FilterGame + +class NameListAdmin(ModelView): + page_size = 15 + column_searchable_list = ['team_no', 'players', 'company'] + column_labels = { + 'game': u'赛事', + 'no': u'赛号', + 'company': u'单位名称', + 'team_no': u'队伍编号', + 'players': u'选手', + } + column_filters = [FilterGame('game', u'赛事')] \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..41cbb23 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,7 @@ +Flask +Flask-Admin +Flask-BasicAuth +Flask-MongoEngine +Flask-Babel +xlutils +gevent diff --git a/run_server.py b/run_server.py new file mode 100644 index 0000000..c30707b --- /dev/null +++ b/run_server.py @@ -0,0 +1,8 @@ +activate_this = 'venv/bin/activate_this.py' +execfile(activate_this, dict(__file__=activate_this)) + +from gevent.wsgi import WSGIServer +from main import app + +http_server = WSGIServer(('0.0.0.0', 5000), app) +http_server.serve_forever() diff --git a/settings.py b/settings.py new file mode 100644 index 0000000..d2de2c4 --- /dev/null +++ b/settings.py @@ -0,0 +1,19 @@ +# Create dummy secrey key so we can use sessions +SECRET_KEY = '1234567890' + +BASIC_AUTH_USERNAME = 'yourname' +BASIC_AUTH_PASSWORD = 'yourpass' +BASIC_AUTH_FORCE = True + + +""" +DB in remote host +""" +MONGODB_SETTINGS = {'db': "yourdb", + 'username': 'username', + 'password': 'pass', + 'host': 'host', + 'port': 27017 + } + +BABEL_DEFAULT_LOCALE = 'zh_Hans_CN' diff --git a/static/css/dataTables.tableTools.css b/static/css/dataTables.tableTools.css new file mode 100644 index 0000000..c959b11 --- /dev/null +++ b/static/css/dataTables.tableTools.css @@ -0,0 +1,361 @@ +/* + * File: TableTools.css + * Description: Styles for TableTools 2 + * Author: Allan Jardine (www.sprymedia.co.uk) + * Language: Javascript + * License: GPL v2 / 3 point BSD + * Project: DataTables + * + * Copyright 2009-2012 Allan Jardine, all rights reserved. + * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * + * CSS name space: + * DTTT DataTables TableTools + * + * Style sheet provides: + * CONTAINER TableTools container element and styles applying to all components + * BUTTON_STYLES Action specific button styles + * SELECTING Row selection styles + * COLLECTIONS Drop down list (collection) styles + * PRINTING Print display styles + */ + + +/* + * CONTAINER + * TableTools container element and styles applying to all components + */ +div.DTTT_container { + position: relative; + float: right; + margin-bottom: 1em; +} + +@media screen and (max-width: 640px) { + div.DTTT_container { + float: none !important; + text-align: center; + } + + div.DTTT_container:after { + visibility: hidden; + display: block; + content: ""; + clear: both; + height: 0; + } +} + + +button.DTTT_button, +div.DTTT_button, +a.DTTT_button { + position: relative; + display: inline-block; + margin-right: 3px; + padding: 5px 8px; + border: 1px solid #999; + cursor: pointer; + *cursor: hand; + font-size: 0.88em; + color: black !important; + + -webkit-border-radius: 2px; + -moz-border-radius: 2px; + -ms-border-radius: 2px; + -o-border-radius: 2px; + border-radius: 2px; + + -webkit-box-shadow: 1px 1px 3px #ccc; + -moz-box-shadow: 1px 1px 3px #ccc; + -ms-box-shadow: 1px 1px 3px #ccc; + -o-box-shadow: 1px 1px 3px #ccc; + box-shadow: 1px 1px 3px #ccc; + + /* Generated by http://www.colorzilla.com/gradient-editor/ */ + background: #ffffff; /* Old browsers */ + background: -webkit-linear-gradient(top, #ffffff 0%,#f3f3f3 89%,#f9f9f9 100%); /* Chrome10+,Safari5.1+ */ + background: -moz-linear-gradient(top, #ffffff 0%,#f3f3f3 89%,#f9f9f9 100%); /* FF3.6+ */ + background: -ms-linear-gradient(top, #ffffff 0%,#f3f3f3 89%,#f9f9f9 100%); /* IE10+ */ + background: -o-linear-gradient(top, #ffffff 0%,#f3f3f3 89%,#f9f9f9 100%); /* Opera 11.10+ */ + background: linear-gradient(top, #ffffff 0%,#f3f3f3 89%,#f9f9f9 100%); /* W3C */ + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffffff', endColorstr='#f9f9f9',GradientType=0 ); /* IE6-9 */ +} + + +/* Buttons are cunning border-box sizing - we can't just use that for A and DIV due to IE6/7 */ +button.DTTT_button { + height: 30px; + padding: 3px 8px; +} + +.DTTT_button embed { + outline: none; +} + +button.DTTT_button:hover:not(.DTTT_disabled), +div.DTTT_button:hover:not(.DTTT_disabled), +a.DTTT_button:hover:not(.DTTT_disabled) { + border: 1px solid #666; + text-decoration: none !important; + + -webkit-box-shadow: 1px 1px 3px #999; + -moz-box-shadow: 1px 1px 3px #999; + -ms-box-shadow: 1px 1px 3px #999; + -o-box-shadow: 1px 1px 3px #999; + box-shadow: 1px 1px 3px #999; + + background: #f3f3f3; /* Old browsers */ + background: -webkit-linear-gradient(top, #f3f3f3 0%,#e2e2e2 89%,#f4f4f4 100%); /* Chrome10+,Safari5.1+ */ + background: -moz-linear-gradient(top, #f3f3f3 0%,#e2e2e2 89%,#f4f4f4 100%); /* FF3.6+ */ + background: -ms-linear-gradient(top, #f3f3f3 0%,#e2e2e2 89%,#f4f4f4 100%); /* IE10+ */ + background: -o-linear-gradient(top, #f3f3f3 0%,#e2e2e2 89%,#f4f4f4 100%); /* Opera 11.10+ */ + background: linear-gradient(top, #f3f3f3 0%,#e2e2e2 89%,#f4f4f4 100%); /* W3C */ + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#f3f3f3', endColorstr='#f4f4f4',GradientType=0 ); /* IE6-9 */ +} + +button.DTTT_button:focus, +div.DTTT_button:focus, +a.DTTT_button:focus { + border: 1px solid #426c9e; + text-shadow: 0 1px 0 #c4def1; + outline: none; + + background-color: #a3d0ef 100%; + background-image: -webkit-linear-gradient(top, #a3d0ef 0%, #79ace9 65%, #a3d0ef 100%); + background-image: -moz-linear-gradient(top, #a3d0ef 0%, #79ace9 65%, #a3d0ef 100%); + background-image: -ms-linear-gradient(top, #a3d0ef 0%, #79ace9 65%, #a3d0ef 100%); + background-image: -o-linear-gradient(top, #a3d0ef 0%, #79ace9 65%, #a3d0ef 100%); + background-image: linear-gradient(top, #a3d0ef 0%, #79ace9 65%, #a3d0ef 100%); + filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0,StartColorStr='#a3d0ef', EndColorStr='#a3d0ef'); +} + +button.DTTT_button:active:not(.DTTT_disabled), +div.DTTT_button:active:not(.DTTT_disabled), +a.DTTT_button:active:not(.DTTT_disabled) { + -webkit-box-shadow: inset 1px 1px 3px #999999; + -moz-box-shadow: inset 1px 1px 3px #999999; + box-shadow: inset 1px 1px 3px #999999; +} + +button.DTTT_disabled, +div.DTTT_disabled, +a.DTTT_disabled { + color: #999 !important; + border: 1px solid #d0d0d0; + cursor: default; + background: #ffffff; /* Old browsers */ + background: -webkit-linear-gradient(top, #ffffff 0%,#f9f9f9 89%,#fafafa 100%); /* Chrome10+,Safari5.1+ */ + background: -moz-linear-gradient(top, #ffffff 0%,#f9f9f9 89%,#fafafa 100%); /* FF3.6+ */ + background: -ms-linear-gradient(top, #ffffff 0%,#f9f9f9 89%,#fafafa 100%); /* IE10+ */ + background: -o-linear-gradient(top, #ffffff 0%,#f9f9f9 89%,#fafafa 100%); /* Opera 11.10+ */ + background: linear-gradient(top, #ffffff 0%,#f9f9f9 89%,#fafafa 100%); /* W3C */ + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffffff', endColorstr='#fafafa',GradientType=0 ); /* IE6-9 */ +} + + + +/* + * BUTTON_STYLES + * Action specific button styles + * If you want images - comment this back in + +a.DTTT_button_csv, +a.DTTT_button_xls, +a.DTTT_button_copy, +a.DTTT_button_pdf, +a.DTTT_button_print { + padding-right: 0px; +} + +a.DTTT_button_csv span, +a.DTTT_button_xls span, +a.DTTT_button_copy span, +a.DTTT_button_pdf span, +a.DTTT_button_print span { + display: inline-block; + height: 24px; + line-height: 24px; + padding-right: 30px; +} + + +a.DTTT_button_csv span { background: url(../images/csv.png) no-repeat bottom right; } +a.DTTT_button_csv:hover span { background: url(../images/csv_hover.png) no-repeat center right; } + +a.DTTT_button_xls span { background: url(../images/xls.png) no-repeat center right; } +a.DTTT_button_xls:hover span { background: #f0f0f0 url(../images/xls_hover.png) no-repeat center right; } + +a.DTTT_button_copy span { background: url(../images/copy.png) no-repeat center right; } +a.DTTT_button_copy:hover span { background: #f0f0f0 url(../images/copy_hover.png) no-repeat center right; } + +a.DTTT_button_pdf span { background: url(../images/pdf.png) no-repeat center right; } +a.DTTT_button_pdf:hover span { background: #f0f0f0 url(../images/pdf_hover.png) no-repeat center right; } + +a.DTTT_button_print span { background: url(../images/print.png) no-repeat center right; } +a.DTTT_button_print:hover span { background: #f0f0f0 url(../images/print_hover.png) no-repeat center right; } + + */ + +button.DTTT_button_collection span { + padding-right: 17px; + background: url(../images/collection.png) no-repeat center right; +} + +button.DTTT_button_collection:hover span { + padding-right: 17px; + background: #f0f0f0 url(../images/collection_hover.png) no-repeat center right; +} + + +/* + * SELECTING + * Row selection styles + */ +table.DTTT_selectable tbody tr { + cursor: pointer; + *cursor: hand; +} + +table.dataTable tr.DTTT_selected.odd { + background-color: #9FAFD1; +} + +table.dataTable tr.DTTT_selected.odd td.sorting_1 { + background-color: #9FAFD1; +} + +table.dataTable tr.DTTT_selected.odd td.sorting_2 { + background-color: #9FAFD1; +} + +table.dataTable tr.DTTT_selected.odd td.sorting_3 { + background-color: #9FAFD1; +} + + +table.dataTable tr.DTTT_selected.even { + background-color: #B0BED9; +} + +table.dataTable tr.DTTT_selected.even td.sorting_1 { + background-color: #B0BED9; +} + +table.dataTable tr.DTTT_selected.even td.sorting_2 { + background-color: #B0BED9; +} + +table.dataTable tr.DTTT_selected.even td.sorting_3 { + background-color: #B0BED9; +} + + +/* + * COLLECTIONS + * Drop down list (collection) styles + */ + +div.DTTT_collection { + width: 150px; + padding: 8px 8px 4px 8px; + border: 1px solid #ccc; + border: 1px solid rgba( 0, 0, 0, 0.4 ); + background-color: #f3f3f3; + background-color: rgba( 255, 255, 255, 0.3 ); + overflow: hidden; + z-index: 2002; + + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + -ms-border-radius: 5px; + -o-border-radius: 5px; + border-radius: 5px; + + -webkit-box-shadow: 3px 3px 5px rgba(0, 0, 0, 0.3); + -moz-box-shadow: 3px 3px 5px rgba(0, 0, 0, 0.3); + -ms-box-shadow: 3px 3px 5px rgba(0, 0, 0, 0.3); + -o-box-shadow: 3px 3px 5px rgba(0, 0, 0, 0.3); + box-shadow: 3px 3px 5px rgba(0, 0, 0, 0.3); +} + +div.DTTT_collection_background { + background: black; + z-index: 2001; +} + +div.DTTT_collection button.DTTT_button, +div.DTTT_collection div.DTTT_button, +div.DTTT_collection a.DTTT_button { + position: relative; + left: 0; + right: 0; + + display: block; + float: none; + margin-bottom: 4px; + + -webkit-box-shadow: 1px 1px 3px #999; + -moz-box-shadow: 1px 1px 3px #999; + -ms-box-shadow: 1px 1px 3px #999; + -o-box-shadow: 1px 1px 3px #999; + box-shadow: 1px 1px 3px #999; +} + + +/* + * PRINTING + * Print display styles + */ + +.DTTT_print_info { + position: fixed; + top: 50%; + left: 50%; + width: 400px; + height: 150px; + margin-left: -200px; + margin-top: -75px; + text-align: center; + color: #333; + padding: 10px 30px; + + background: #ffffff; /* Old browsers */ + background: -webkit-linear-gradient(top, #ffffff 0%,#f3f3f3 89%,#f9f9f9 100%); /* Chrome10+,Safari5.1+ */ + background: -moz-linear-gradient(top, #ffffff 0%,#f3f3f3 89%,#f9f9f9 100%); /* FF3.6+ */ + background: -ms-linear-gradient(top, #ffffff 0%,#f3f3f3 89%,#f9f9f9 100%); /* IE10+ */ + background: -o-linear-gradient(top, #ffffff 0%,#f3f3f3 89%,#f9f9f9 100%); /* Opera 11.10+ */ + background: linear-gradient(top, #ffffff 0%,#f3f3f3 89%,#f9f9f9 100%); /* W3C */ + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffffff', endColorstr='#f9f9f9',GradientType=0 ); /* IE6-9 */ + + opacity: 0.95; + + border: 1px solid black; + border: 1px solid rgba(0, 0, 0, 0.5); + + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + -ms-border-radius: 6px; + -o-border-radius: 6px; + border-radius: 6px; + + -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.5); + -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.5); + -ms-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.5); + -o-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.5); + box-shadow: 0 3px 7px rgba(0, 0, 0, 0.5); +} + +.DTTT_print_info h6 { + font-weight: normal; + font-size: 28px; + line-height: 28px; + margin: 1em; +} + +.DTTT_print_info p { + font-size: 14px; + line-height: 20px; +} + diff --git a/static/css/jquery.dataTables.css b/static/css/jquery.dataTables.css new file mode 100644 index 0000000..eec02ef --- /dev/null +++ b/static/css/jquery.dataTables.css @@ -0,0 +1,455 @@ +/* + * Table styles + */ +table.dataTable { + width: 100%; + margin: 0 auto; + clear: both; + border-collapse: separate; + border-spacing: 0; + /* + * Header and footer styles + */ + /* + * Body styles + */ +} +table.dataTable thead th, +table.dataTable tfoot th { + font-weight: bold; +} +table.dataTable thead th, +table.dataTable thead td { + padding: 10px 18px; + border-bottom: 1px solid #111; +} +table.dataTable thead th:active, +table.dataTable thead td:active { + outline: none; +} +table.dataTable tfoot th, +table.dataTable tfoot td { + padding: 10px 18px 6px 18px; + border-top: 1px solid #111; +} +table.dataTable thead .sorting, +table.dataTable thead .sorting_asc, +table.dataTable thead .sorting_desc { + cursor: pointer; + *cursor: hand; +} +table.dataTable thead .sorting, +table.dataTable thead .sorting_asc, +table.dataTable thead .sorting_desc, +table.dataTable thead .sorting_asc_disabled, +table.dataTable thead .sorting_desc_disabled { + background-repeat: no-repeat; + background-position: center right; +} +table.dataTable thead .sorting { + background-image: url("../images/sort_both.png"); +} +table.dataTable thead .sorting_asc { + background-image: url("../images/sort_asc.png"); +} +table.dataTable thead .sorting_desc { + background-image: url("../images/sort_desc.png"); +} +table.dataTable thead .sorting_asc_disabled { + background-image: url("../images/sort_asc_disabled.png"); +} +table.dataTable thead .sorting_desc_disabled { + background-image: url("../images/sort_desc_disabled.png"); +} +table.dataTable tbody tr { + background-color: #ffffff; +} +table.dataTable tbody tr.selected { + background-color: #B0BED9; +} +table.dataTable tbody th, +table.dataTable tbody td { + padding: 8px 10px; +} +table.dataTable.row-border tbody th, table.dataTable.row-border tbody td, table.dataTable.display tbody th, table.dataTable.display tbody td { + border-top: 1px solid #ddd; +} +table.dataTable.row-border tbody tr:first-child th, +table.dataTable.row-border tbody tr:first-child td, table.dataTable.display tbody tr:first-child th, +table.dataTable.display tbody tr:first-child td { + border-top: none; +} +table.dataTable.cell-border tbody th, table.dataTable.cell-border tbody td { + border-top: 1px solid #ddd; + border-right: 1px solid #ddd; +} +table.dataTable.cell-border tbody tr th:first-child, +table.dataTable.cell-border tbody tr td:first-child { + border-left: 1px solid #ddd; +} +table.dataTable.cell-border tbody tr:first-child th, +table.dataTable.cell-border tbody tr:first-child td { + border-top: none; +} +table.dataTable.stripe tbody tr.odd, table.dataTable.display tbody tr.odd { + background-color: #f9f9f9; +} +table.dataTable.stripe tbody tr.odd.selected, table.dataTable.display tbody tr.odd.selected { + background-color: #abb9d3; +} +table.dataTable.hover tbody tr:hover, table.dataTable.display tbody tr:hover { + background-color: whitesmoke; +} +table.dataTable.hover tbody tr:hover.selected, table.dataTable.display tbody tr:hover.selected { + background-color: #a9b7d1; +} +table.dataTable.order-column tbody tr > .sorting_1, +table.dataTable.order-column tbody tr > .sorting_2, +table.dataTable.order-column tbody tr > .sorting_3, table.dataTable.display tbody tr > .sorting_1, +table.dataTable.display tbody tr > .sorting_2, +table.dataTable.display tbody tr > .sorting_3 { + background-color: #f9f9f9; +} +table.dataTable.order-column tbody tr.selected > .sorting_1, +table.dataTable.order-column tbody tr.selected > .sorting_2, +table.dataTable.order-column tbody tr.selected > .sorting_3, table.dataTable.display tbody tr.selected > .sorting_1, +table.dataTable.display tbody tr.selected > .sorting_2, +table.dataTable.display tbody tr.selected > .sorting_3 { + background-color: #acbad4; +} +table.dataTable.display tbody tr.odd > .sorting_1, table.dataTable.order-column.stripe tbody tr.odd > .sorting_1 { + background-color: #f1f1f1; +} +table.dataTable.display tbody tr.odd > .sorting_2, table.dataTable.order-column.stripe tbody tr.odd > .sorting_2 { + background-color: #f3f3f3; +} +table.dataTable.display tbody tr.odd > .sorting_3, table.dataTable.order-column.stripe tbody tr.odd > .sorting_3 { + background-color: whitesmoke; +} +table.dataTable.display tbody tr.odd.selected > .sorting_1, table.dataTable.order-column.stripe tbody tr.odd.selected > .sorting_1 { + background-color: #a6b3cd; +} +table.dataTable.display tbody tr.odd.selected > .sorting_2, table.dataTable.order-column.stripe tbody tr.odd.selected > .sorting_2 { + background-color: #a7b5ce; +} +table.dataTable.display tbody tr.odd.selected > .sorting_3, table.dataTable.order-column.stripe tbody tr.odd.selected > .sorting_3 { + background-color: #a9b6d0; +} +table.dataTable.display tbody tr.even > .sorting_1, table.dataTable.order-column.stripe tbody tr.even > .sorting_1 { + background-color: #f9f9f9; +} +table.dataTable.display tbody tr.even > .sorting_2, table.dataTable.order-column.stripe tbody tr.even > .sorting_2 { + background-color: #fbfbfb; +} +table.dataTable.display tbody tr.even > .sorting_3, table.dataTable.order-column.stripe tbody tr.even > .sorting_3 { + background-color: #fdfdfd; +} +table.dataTable.display tbody tr.even.selected > .sorting_1, table.dataTable.order-column.stripe tbody tr.even.selected > .sorting_1 { + background-color: #acbad4; +} +table.dataTable.display tbody tr.even.selected > .sorting_2, table.dataTable.order-column.stripe tbody tr.even.selected > .sorting_2 { + background-color: #adbbd6; +} +table.dataTable.display tbody tr.even.selected > .sorting_3, table.dataTable.order-column.stripe tbody tr.even.selected > .sorting_3 { + background-color: #afbdd8; +} +table.dataTable.display tbody tr:hover > .sorting_1, table.dataTable.order-column.hover tbody tr:hover > .sorting_1 { + background-color: #eaeaea; +} +table.dataTable.display tbody tr:hover > .sorting_2, table.dataTable.order-column.hover tbody tr:hover > .sorting_2 { + background-color: #ebebeb; +} +table.dataTable.display tbody tr:hover > .sorting_3, table.dataTable.order-column.hover tbody tr:hover > .sorting_3 { + background-color: #eeeeee; +} +table.dataTable.display tbody tr:hover.selected > .sorting_1, table.dataTable.order-column.hover tbody tr:hover.selected > .sorting_1 { + background-color: #a1aec7; +} +table.dataTable.display tbody tr:hover.selected > .sorting_2, table.dataTable.order-column.hover tbody tr:hover.selected > .sorting_2 { + background-color: #a2afc8; +} +table.dataTable.display tbody tr:hover.selected > .sorting_3, table.dataTable.order-column.hover tbody tr:hover.selected > .sorting_3 { + background-color: #a4b2cb; +} +table.dataTable.no-footer { + border-bottom: 1px solid #111; +} +table.dataTable.nowrap th, table.dataTable.nowrap td { + white-space: nowrap; +} +table.dataTable.compact thead th, +table.dataTable.compact thead td { + padding: 4px 17px 4px 4px; +} +table.dataTable.compact tfoot th, +table.dataTable.compact tfoot td { + padding: 4px; +} +table.dataTable.compact tbody th, +table.dataTable.compact tbody td { + padding: 4px; +} +table.dataTable th.dt-left, +table.dataTable td.dt-left { + text-align: left; +} +table.dataTable th.dt-center, +table.dataTable td.dt-center, +table.dataTable td.dataTables_empty { + text-align: center; +} +table.dataTable th.dt-right, +table.dataTable td.dt-right { + text-align: right; +} +table.dataTable th.dt-justify, +table.dataTable td.dt-justify { + text-align: justify; +} +table.dataTable th.dt-nowrap, +table.dataTable td.dt-nowrap { + white-space: nowrap; +} +table.dataTable thead th.dt-head-left, +table.dataTable thead td.dt-head-left, +table.dataTable tfoot th.dt-head-left, +table.dataTable tfoot td.dt-head-left { + text-align: left; +} +table.dataTable thead th.dt-head-center, +table.dataTable thead td.dt-head-center, +table.dataTable tfoot th.dt-head-center, +table.dataTable tfoot td.dt-head-center { + text-align: center; +} +table.dataTable thead th.dt-head-right, +table.dataTable thead td.dt-head-right, +table.dataTable tfoot th.dt-head-right, +table.dataTable tfoot td.dt-head-right { + text-align: right; +} +table.dataTable thead th.dt-head-justify, +table.dataTable thead td.dt-head-justify, +table.dataTable tfoot th.dt-head-justify, +table.dataTable tfoot td.dt-head-justify { + text-align: justify; +} +table.dataTable thead th.dt-head-nowrap, +table.dataTable thead td.dt-head-nowrap, +table.dataTable tfoot th.dt-head-nowrap, +table.dataTable tfoot td.dt-head-nowrap { + white-space: nowrap; +} +table.dataTable tbody th.dt-body-left, +table.dataTable tbody td.dt-body-left { + text-align: left; +} +table.dataTable tbody th.dt-body-center, +table.dataTable tbody td.dt-body-center { + text-align: center; +} +table.dataTable tbody th.dt-body-right, +table.dataTable tbody td.dt-body-right { + text-align: right; +} +table.dataTable tbody th.dt-body-justify, +table.dataTable tbody td.dt-body-justify { + text-align: justify; +} +table.dataTable tbody th.dt-body-nowrap, +table.dataTable tbody td.dt-body-nowrap { + white-space: nowrap; +} + +table.dataTable, +table.dataTable th, +table.dataTable td { + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; +} + +/* + * Control feature layout + */ +.dataTables_wrapper { + position: relative; + clear: both; + *zoom: 1; + zoom: 1; +} +.dataTables_wrapper .dataTables_length { + float: left; +} +.dataTables_wrapper .dataTables_filter { + float: right; + text-align: right; +} +.dataTables_wrapper .dataTables_filter input { + margin-left: 0.5em; +} +.dataTables_wrapper .dataTables_info { + clear: both; + float: left; + padding-top: 0.755em; +} +.dataTables_wrapper .dataTables_paginate { + float: right; + text-align: right; + padding-top: 0.25em; +} +.dataTables_wrapper .dataTables_paginate .paginate_button { + box-sizing: border-box; + display: inline-block; + min-width: 1.5em; + padding: 0.5em 1em; + margin-left: 2px; + text-align: center; + text-decoration: none !important; + cursor: pointer; + *cursor: hand; + color: #333 !important; + border: 1px solid transparent; +} +.dataTables_wrapper .dataTables_paginate .paginate_button.current, .dataTables_wrapper .dataTables_paginate .paginate_button.current:hover { + color: #333 !important; + border: 1px solid #cacaca; + background-color: white; + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, white), color-stop(100%, #dcdcdc)); + /* Chrome,Safari4+ */ + background: -webkit-linear-gradient(top, white 0%, #dcdcdc 100%); + /* Chrome10+,Safari5.1+ */ + background: -moz-linear-gradient(top, white 0%, #dcdcdc 100%); + /* FF3.6+ */ + background: -ms-linear-gradient(top, white 0%, #dcdcdc 100%); + /* IE10+ */ + background: -o-linear-gradient(top, white 0%, #dcdcdc 100%); + /* Opera 11.10+ */ + background: linear-gradient(to bottom, white 0%, #dcdcdc 100%); + /* W3C */ +} +.dataTables_wrapper .dataTables_paginate .paginate_button.disabled, .dataTables_wrapper .dataTables_paginate .paginate_button.disabled:hover, .dataTables_wrapper .dataTables_paginate .paginate_button.disabled:active { + cursor: default; + color: #666 !important; + border: 1px solid transparent; + background: transparent; + box-shadow: none; +} +.dataTables_wrapper .dataTables_paginate .paginate_button:hover { + color: white !important; + border: 1px solid #111; + background-color: #585858; + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #585858), color-stop(100%, #111)); + /* Chrome,Safari4+ */ + background: -webkit-linear-gradient(top, #585858 0%, #111 100%); + /* Chrome10+,Safari5.1+ */ + background: -moz-linear-gradient(top, #585858 0%, #111 100%); + /* FF3.6+ */ + background: -ms-linear-gradient(top, #585858 0%, #111 100%); + /* IE10+ */ + background: -o-linear-gradient(top, #585858 0%, #111 100%); + /* Opera 11.10+ */ + background: linear-gradient(to bottom, #585858 0%, #111 100%); + /* W3C */ +} +.dataTables_wrapper .dataTables_paginate .paginate_button:active { + outline: none; + background-color: #2b2b2b; + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #2b2b2b), color-stop(100%, #0c0c0c)); + /* Chrome,Safari4+ */ + background: -webkit-linear-gradient(top, #2b2b2b 0%, #0c0c0c 100%); + /* Chrome10+,Safari5.1+ */ + background: -moz-linear-gradient(top, #2b2b2b 0%, #0c0c0c 100%); + /* FF3.6+ */ + background: -ms-linear-gradient(top, #2b2b2b 0%, #0c0c0c 100%); + /* IE10+ */ + background: -o-linear-gradient(top, #2b2b2b 0%, #0c0c0c 100%); + /* Opera 11.10+ */ + background: linear-gradient(to bottom, #2b2b2b 0%, #0c0c0c 100%); + /* W3C */ + box-shadow: inset 0 0 3px #111; +} +.dataTables_wrapper .dataTables_paginate .ellipsis { + padding: 0 1em; +} +.dataTables_wrapper .dataTables_processing { + position: absolute; + top: 50%; + left: 50%; + width: 100%; + height: 40px; + margin-left: -50%; + margin-top: -25px; + padding-top: 20px; + text-align: center; + font-size: 1.2em; + background-color: white; + background: -webkit-gradient(linear, left top, right top, color-stop(0%, rgba(255, 255, 255, 0)), color-stop(25%, rgba(255, 255, 255, 0.9)), color-stop(75%, rgba(255, 255, 255, 0.9)), color-stop(100%, rgba(255, 255, 255, 0))); + /* Chrome,Safari4+ */ + background: -webkit-linear-gradient(left, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.9) 25%, rgba(255, 255, 255, 0.9) 75%, rgba(255, 255, 255, 0) 100%); + /* Chrome10+,Safari5.1+ */ + background: -moz-linear-gradient(left, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.9) 25%, rgba(255, 255, 255, 0.9) 75%, rgba(255, 255, 255, 0) 100%); + /* FF3.6+ */ + background: -ms-linear-gradient(left, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.9) 25%, rgba(255, 255, 255, 0.9) 75%, rgba(255, 255, 255, 0) 100%); + /* IE10+ */ + background: -o-linear-gradient(left, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.9) 25%, rgba(255, 255, 255, 0.9) 75%, rgba(255, 255, 255, 0) 100%); + /* Opera 11.10+ */ + background: linear-gradient(to right, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.9) 25%, rgba(255, 255, 255, 0.9) 75%, rgba(255, 255, 255, 0) 100%); + /* W3C */ +} +.dataTables_wrapper .dataTables_length, +.dataTables_wrapper .dataTables_filter, +.dataTables_wrapper .dataTables_info, +.dataTables_wrapper .dataTables_processing, +.dataTables_wrapper .dataTables_paginate { + color: #333; +} +.dataTables_wrapper .dataTables_scroll { + clear: both; +} +.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody { + *margin-top: -1px; + -webkit-overflow-scrolling: touch; +} +.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody th > div.dataTables_sizing, +.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody td > div.dataTables_sizing { + height: 0; + overflow: hidden; + margin: 0 !important; + padding: 0 !important; +} +.dataTables_wrapper.no-footer .dataTables_scrollBody { + border-bottom: 1px solid #111; +} +.dataTables_wrapper.no-footer div.dataTables_scrollHead table, +.dataTables_wrapper.no-footer div.dataTables_scrollBody table { + border-bottom: none; +} +.dataTables_wrapper:after { + visibility: hidden; + display: block; + content: ""; + clear: both; + height: 0; +} + +@media screen and (max-width: 767px) { + .dataTables_wrapper .dataTables_info, + .dataTables_wrapper .dataTables_paginate { + float: none; + text-align: center; + } + .dataTables_wrapper .dataTables_paginate { + margin-top: 0.5em; + } +} +@media screen and (max-width: 640px) { + .dataTables_wrapper .dataTables_length, + .dataTables_wrapper .dataTables_filter { + float: none; + text-align: center; + } + .dataTables_wrapper .dataTables_filter { + margin-top: 0.5em; + } +} diff --git a/static/js/dataTables.tableTools.js b/static/js/dataTables.tableTools.js new file mode 100644 index 0000000..749fcd8 --- /dev/null +++ b/static/js/dataTables.tableTools.js @@ -0,0 +1,3230 @@ +/*! TableTools 2.2.4 + * 2009-2015 SpryMedia Ltd - datatables.net/license + * + * ZeroClipboard 1.0.4 + * Author: Joseph Huckaby - MIT licensed + */ + +/** + * @summary TableTools + * @description Tools and buttons for DataTables + * @version 2.2.4 + * @file dataTables.tableTools.js + * @author SpryMedia Ltd (www.sprymedia.co.uk) + * @contact www.sprymedia.co.uk/contact + * @copyright Copyright 2009-2015 SpryMedia Ltd. + * + * This source file is free software, available under the following license: + * MIT license - http://datatables.net/license/mit + * + * This source file is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details. + * + * For details please refer to: http://www.datatables.net + */ + + +/* Global scope for TableTools for backwards compatibility. + * Will be removed in 2.3 + */ +var TableTools; + +(function(window, document, undefined) { + + +var factory = function( $, DataTable ) { +"use strict"; + + +//include ZeroClipboard.js +/* ZeroClipboard 1.0.4 + * Author: Joseph Huckaby + */ + +var ZeroClipboard_TableTools = { + + version: "1.0.4-TableTools2", + clients: {}, // registered upload clients on page, indexed by id + moviePath: '', // URL to movie + nextId: 1, // ID of next movie + + $: function(thingy) { + // simple DOM lookup utility function + if (typeof(thingy) == 'string') { + thingy = document.getElementById(thingy); + } + if (!thingy.addClass) { + // extend element with a few useful methods + thingy.hide = function() { this.style.display = 'none'; }; + thingy.show = function() { this.style.display = ''; }; + thingy.addClass = function(name) { this.removeClass(name); this.className += ' ' + name; }; + thingy.removeClass = function(name) { + this.className = this.className.replace( new RegExp("\\s*" + name + "\\s*"), " ").replace(/^\s+/, '').replace(/\s+$/, ''); + }; + thingy.hasClass = function(name) { + return !!this.className.match( new RegExp("\\s*" + name + "\\s*") ); + }; + } + return thingy; + }, + + setMoviePath: function(path) { + // set path to ZeroClipboard.swf + this.moviePath = path; + }, + + dispatch: function(id, eventName, args) { + // receive event from flash movie, send to client + var client = this.clients[id]; + if (client) { + client.receiveEvent(eventName, args); + } + }, + + register: function(id, client) { + // register new client to receive events + this.clients[id] = client; + }, + + getDOMObjectPosition: function(obj) { + // get absolute coordinates for dom element + var info = { + left: 0, + top: 0, + width: obj.width ? obj.width : obj.offsetWidth, + height: obj.height ? obj.height : obj.offsetHeight + }; + + if ( obj.style.width !== "" ) { + info.width = obj.style.width.replace("px",""); + } + + if ( obj.style.height !== "" ) { + info.height = obj.style.height.replace("px",""); + } + + while (obj) { + info.left += obj.offsetLeft; + info.top += obj.offsetTop; + obj = obj.offsetParent; + } + + return info; + }, + + Client: function(elem) { + // constructor for new simple upload client + this.handlers = {}; + + // unique ID + this.id = ZeroClipboard_TableTools.nextId++; + this.movieId = 'ZeroClipboard_TableToolsMovie_' + this.id; + + // register client with singleton to receive flash events + ZeroClipboard_TableTools.register(this.id, this); + + // create movie + if (elem) { + this.glue(elem); + } + } +}; + +ZeroClipboard_TableTools.Client.prototype = { + + id: 0, // unique ID for us + ready: false, // whether movie is ready to receive events or not + movie: null, // reference to movie object + clipText: '', // text to copy to clipboard + fileName: '', // default file save name + action: 'copy', // action to perform + handCursorEnabled: true, // whether to show hand cursor, or default pointer cursor + cssEffects: true, // enable CSS mouse effects on dom container + handlers: null, // user event handlers + sized: false, + + glue: function(elem, title) { + // glue to DOM element + // elem can be ID or actual DOM element object + this.domElement = ZeroClipboard_TableTools.$(elem); + + // float just above object, or zIndex 99 if dom element isn't set + var zIndex = 99; + if (this.domElement.style.zIndex) { + zIndex = parseInt(this.domElement.style.zIndex, 10) + 1; + } + + // find X/Y position of domElement + var box = ZeroClipboard_TableTools.getDOMObjectPosition(this.domElement); + + // create floating DIV above element + this.div = document.createElement('div'); + var style = this.div.style; + style.position = 'absolute'; + style.left = '0px'; + style.top = '0px'; + style.width = (box.width) + 'px'; + style.height = box.height + 'px'; + style.zIndex = zIndex; + + if ( typeof title != "undefined" && title !== "" ) { + this.div.title = title; + } + if ( box.width !== 0 && box.height !== 0 ) { + this.sized = true; + } + + // style.backgroundColor = '#f00'; // debug + if ( this.domElement ) { + this.domElement.appendChild(this.div); + this.div.innerHTML = this.getHTML( box.width, box.height ).replace(/&/g, '&'); + } + }, + + positionElement: function() { + var box = ZeroClipboard_TableTools.getDOMObjectPosition(this.domElement); + var style = this.div.style; + + style.position = 'absolute'; + //style.left = (this.domElement.offsetLeft)+'px'; + //style.top = this.domElement.offsetTop+'px'; + style.width = box.width + 'px'; + style.height = box.height + 'px'; + + if ( box.width !== 0 && box.height !== 0 ) { + this.sized = true; + } else { + return; + } + + var flash = this.div.childNodes[0]; + flash.width = box.width; + flash.height = box.height; + }, + + getHTML: function(width, height) { + // return HTML for movie + var html = ''; + var flashvars = 'id=' + this.id + + '&width=' + width + + '&height=' + height; + + if (navigator.userAgent.match(/MSIE/)) { + // IE gets an OBJECT tag + var protocol = location.href.match(/^https/i) ? 'https://' : 'http://'; + html += ''; + } + else { + // all other browsers get an EMBED tag + html += ''; + } + return html; + }, + + hide: function() { + // temporarily hide floater offscreen + if (this.div) { + this.div.style.left = '-2000px'; + } + }, + + show: function() { + // show ourselves after a call to hide() + this.reposition(); + }, + + destroy: function() { + // destroy control and floater + if (this.domElement && this.div) { + this.hide(); + this.div.innerHTML = ''; + + var body = document.getElementsByTagName('body')[0]; + try { body.removeChild( this.div ); } catch(e) {} + + this.domElement = null; + this.div = null; + } + }, + + reposition: function(elem) { + // reposition our floating div, optionally to new container + // warning: container CANNOT change size, only position + if (elem) { + this.domElement = ZeroClipboard_TableTools.$(elem); + if (!this.domElement) { + this.hide(); + } + } + + if (this.domElement && this.div) { + var box = ZeroClipboard_TableTools.getDOMObjectPosition(this.domElement); + var style = this.div.style; + style.left = '' + box.left + 'px'; + style.top = '' + box.top + 'px'; + } + }, + + clearText: function() { + // clear the text to be copy / saved + this.clipText = ''; + if (this.ready) { + this.movie.clearText(); + } + }, + + appendText: function(newText) { + // append text to that which is to be copied / saved + this.clipText += newText; + if (this.ready) { this.movie.appendText(newText) ;} + }, + + setText: function(newText) { + // set text to be copied to be copied / saved + this.clipText = newText; + if (this.ready) { this.movie.setText(newText) ;} + }, + + setCharSet: function(charSet) { + // set the character set (UTF16LE or UTF8) + this.charSet = charSet; + if (this.ready) { this.movie.setCharSet(charSet) ;} + }, + + setBomInc: function(bomInc) { + // set if the BOM should be included or not + this.incBom = bomInc; + if (this.ready) { this.movie.setBomInc(bomInc) ;} + }, + + setFileName: function(newText) { + // set the file name + this.fileName = newText; + if (this.ready) { + this.movie.setFileName(newText); + } + }, + + setAction: function(newText) { + // set action (save or copy) + this.action = newText; + if (this.ready) { + this.movie.setAction(newText); + } + }, + + addEventListener: function(eventName, func) { + // add user event listener for event + // event types: load, queueStart, fileStart, fileComplete, queueComplete, progress, error, cancel + eventName = eventName.toString().toLowerCase().replace(/^on/, ''); + if (!this.handlers[eventName]) { + this.handlers[eventName] = []; + } + this.handlers[eventName].push(func); + }, + + setHandCursor: function(enabled) { + // enable hand cursor (true), or default arrow cursor (false) + this.handCursorEnabled = enabled; + if (this.ready) { + this.movie.setHandCursor(enabled); + } + }, + + setCSSEffects: function(enabled) { + // enable or disable CSS effects on DOM container + this.cssEffects = !!enabled; + }, + + receiveEvent: function(eventName, args) { + var self; + + // receive event from flash + eventName = eventName.toString().toLowerCase().replace(/^on/, ''); + + // special behavior for certain events + switch (eventName) { + case 'load': + // movie claims it is ready, but in IE this isn't always the case... + // bug fix: Cannot extend EMBED DOM elements in Firefox, must use traditional function + this.movie = document.getElementById(this.movieId); + if (!this.movie) { + self = this; + setTimeout( function() { self.receiveEvent('load', null); }, 1 ); + return; + } + + // firefox on pc needs a "kick" in order to set these in certain cases + if (!this.ready && navigator.userAgent.match(/Firefox/) && navigator.userAgent.match(/Windows/)) { + self = this; + setTimeout( function() { self.receiveEvent('load', null); }, 100 ); + this.ready = true; + return; + } + + this.ready = true; + this.movie.clearText(); + this.movie.appendText( this.clipText ); + this.movie.setFileName( this.fileName ); + this.movie.setAction( this.action ); + this.movie.setCharSet( this.charSet ); + this.movie.setBomInc( this.incBom ); + this.movie.setHandCursor( this.handCursorEnabled ); + break; + + case 'mouseover': + if (this.domElement && this.cssEffects) { + //this.domElement.addClass('hover'); + if (this.recoverActive) { + this.domElement.addClass('active'); + } + } + break; + + case 'mouseout': + if (this.domElement && this.cssEffects) { + this.recoverActive = false; + if (this.domElement.hasClass('active')) { + this.domElement.removeClass('active'); + this.recoverActive = true; + } + //this.domElement.removeClass('hover'); + } + break; + + case 'mousedown': + if (this.domElement && this.cssEffects) { + this.domElement.addClass('active'); + } + break; + + case 'mouseup': + if (this.domElement && this.cssEffects) { + this.domElement.removeClass('active'); + this.recoverActive = false; + } + break; + } // switch eventName + + if (this.handlers[eventName]) { + for (var idx = 0, len = this.handlers[eventName].length; idx < len; idx++) { + var func = this.handlers[eventName][idx]; + + if (typeof(func) == 'function') { + // actual function reference + func(this, args); + } + else if ((typeof(func) == 'object') && (func.length == 2)) { + // PHP style object + method, i.e. [myObject, 'myMethod'] + func[0][ func[1] ](this, args); + } + else if (typeof(func) == 'string') { + // name of function + window[func](this, args); + } + } // foreach event handler defined + } // user defined handler for event + } + +}; + +// For the Flash binding to work, ZeroClipboard_TableTools must be on the global +// object list +window.ZeroClipboard_TableTools = ZeroClipboard_TableTools; +//include TableTools.js +/* TableTools + * 2009-2015 SpryMedia Ltd - datatables.net/license + */ + +/*globals TableTools,ZeroClipboard_TableTools*/ + + +(function($, window, document) { + +/** + * TableTools provides flexible buttons and other tools for a DataTables enhanced table + * @class TableTools + * @constructor + * @param {Object} oDT DataTables instance. When using DataTables 1.10 this can + * also be a jQuery collection, jQuery selector, table node, DataTables API + * instance or DataTables settings object. + * @param {Object} oOpts TableTools options + * @param {String} oOpts.sSwfPath ZeroClipboard SWF path + * @param {String} oOpts.sRowSelect Row selection options - 'none', 'single', 'multi' or 'os' + * @param {Function} oOpts.fnPreRowSelect Callback function just prior to row selection + * @param {Function} oOpts.fnRowSelected Callback function just after row selection + * @param {Function} oOpts.fnRowDeselected Callback function when row is deselected + * @param {Array} oOpts.aButtons List of buttons to be used + */ +TableTools = function( oDT, oOpts ) +{ + /* Santiy check that we are a new instance */ + if ( ! this instanceof TableTools ) + { + alert( "Warning: TableTools must be initialised with the keyword 'new'" ); + } + + // In 1.10 we can use the API to get the settings object from a number of + // sources + var dtSettings = $.fn.dataTable.Api ? + new $.fn.dataTable.Api( oDT ).settings()[0] : + oDT.fnSettings(); + + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Public class variables + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + + /** + * @namespace Settings object which contains customisable information for TableTools instance + */ + this.s = { + /** + * Store 'this' so the instance can be retrieved from the settings object + * @property that + * @type object + * @default this + */ + "that": this, + + /** + * DataTables settings objects + * @property dt + * @type object + * @default From the oDT init option + */ + "dt": dtSettings, + + /** + * @namespace Print specific information + */ + "print": { + /** + * DataTables draw 'start' point before the printing display was shown + * @property saveStart + * @type int + * @default -1 + */ + "saveStart": -1, + + /** + * DataTables draw 'length' point before the printing display was shown + * @property saveLength + * @type int + * @default -1 + */ + "saveLength": -1, + + /** + * Page scrolling point before the printing display was shown so it can be restored + * @property saveScroll + * @type int + * @default -1 + */ + "saveScroll": -1, + + /** + * Wrapped function to end the print display (to maintain scope) + * @property funcEnd + * @type Function + * @default function () {} + */ + "funcEnd": function () {} + }, + + /** + * A unique ID is assigned to each button in each instance + * @property buttonCounter + * @type int + * @default 0 + */ + "buttonCounter": 0, + + /** + * @namespace Select rows specific information + */ + "select": { + /** + * Select type - can be 'none', 'single' or 'multi' + * @property type + * @type string + * @default "" + */ + "type": "", + + /** + * Array of nodes which are currently selected + * @property selected + * @type array + * @default [] + */ + "selected": [], + + /** + * Function to run before the selection can take place. Will cancel the select if the + * function returns false + * @property preRowSelect + * @type Function + * @default null + */ + "preRowSelect": null, + + /** + * Function to run when a row is selected + * @property postSelected + * @type Function + * @default null + */ + "postSelected": null, + + /** + * Function to run when a row is deselected + * @property postDeselected + * @type Function + * @default null + */ + "postDeselected": null, + + /** + * Indicate if all rows are selected (needed for server-side processing) + * @property all + * @type boolean + * @default false + */ + "all": false, + + /** + * Class name to add to selected TR nodes + * @property selectedClass + * @type String + * @default "" + */ + "selectedClass": "" + }, + + /** + * Store of the user input customisation object + * @property custom + * @type object + * @default {} + */ + "custom": {}, + + /** + * SWF movie path + * @property swfPath + * @type string + * @default "" + */ + "swfPath": "", + + /** + * Default button set + * @property buttonSet + * @type array + * @default [] + */ + "buttonSet": [], + + /** + * When there is more than one TableTools instance for a DataTable, there must be a + * master which controls events (row selection etc) + * @property master + * @type boolean + * @default false + */ + "master": false, + + /** + * Tag names that are used for creating collections and buttons + * @namesapce + */ + "tags": {} + }; + + + /** + * @namespace Common and useful DOM elements for the class instance + */ + this.dom = { + /** + * DIV element that is create and all TableTools buttons (and their children) put into + * @property container + * @type node + * @default null + */ + "container": null, + + /** + * The table node to which TableTools will be applied + * @property table + * @type node + * @default null + */ + "table": null, + + /** + * @namespace Nodes used for the print display + */ + "print": { + /** + * Nodes which have been removed from the display by setting them to display none + * @property hidden + * @type array + * @default [] + */ + "hidden": [], + + /** + * The information display saying telling the user about the print display + * @property message + * @type node + * @default null + */ + "message": null + }, + + /** + * @namespace Nodes used for a collection display. This contains the currently used collection + */ + "collection": { + /** + * The div wrapper containing the buttons in the collection (i.e. the menu) + * @property collection + * @type node + * @default null + */ + "collection": null, + + /** + * Background display to provide focus and capture events + * @property background + * @type node + * @default null + */ + "background": null + } + }; + + /** + * @namespace Name space for the classes that this TableTools instance will use + * @extends TableTools.classes + */ + this.classes = $.extend( true, {}, TableTools.classes ); + if ( this.s.dt.bJUI ) + { + $.extend( true, this.classes, TableTools.classes_themeroller ); + } + + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Public class methods + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + + /** + * Retreieve the settings object from an instance + * @method fnSettings + * @returns {object} TableTools settings object + */ + this.fnSettings = function () { + return this.s; + }; + + + /* Constructor logic */ + if ( typeof oOpts == 'undefined' ) + { + oOpts = {}; + } + + + TableTools._aInstances.push( this ); + this._fnConstruct( oOpts ); + + return this; +}; + + + +TableTools.prototype = { + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Public methods + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + + /** + * Retreieve the settings object from an instance + * @returns {array} List of TR nodes which are currently selected + * @param {boolean} [filtered=false] Get only selected rows which are + * available given the filtering applied to the table. By default + * this is false - i.e. all rows, regardless of filtering are + selected. + */ + "fnGetSelected": function ( filtered ) + { + var + out = [], + data = this.s.dt.aoData, + displayed = this.s.dt.aiDisplay, + i, iLen; + + if ( filtered ) + { + // Only consider filtered rows + for ( i=0, iLen=displayed.length ; i 0 ) + { + sTitle = anTitle[0].innerHTML; + } + } + + /* Strip characters which the OS will object to - checking for UTF8 support in the scripting + * engine + */ + if ( "\u00A1".toString().length < 4 ) { + return sTitle.replace(/[^a-zA-Z0-9_\u00A1-\uFFFF\.,\-_ !\(\)]/g, ""); + } else { + return sTitle.replace(/[^a-zA-Z0-9_\.,\-_ !\(\)]/g, ""); + } + }, + + + /** + * Calculate a unity array with the column width by proportion for a set of columns to be + * included for a button. This is particularly useful for PDF creation, where we can use the + * column widths calculated by the browser to size the columns in the PDF. + * @param {Object} oConfig Button configuration object + * @returns {Array} Unity array of column ratios + */ + "fnCalcColRatios": function ( oConfig ) + { + var + aoCols = this.s.dt.aoColumns, + aColumnsInc = this._fnColumnTargets( oConfig.mColumns ), + aColWidths = [], + iWidth = 0, iTotal = 0, i, iLen; + + for ( i=0, iLen=aColumnsInc.length ; i