From c98f611472b65e8be5943fb6e9f134c21d9a0665 Mon Sep 17 00:00:00 2001 From: hrcerqueira Date: Mon, 22 Feb 2010 14:34:10 +0000 Subject: "Reversed" some m2m relations with the user model. Fixed and improved most of modules functionality. Definitevly moved books to a separate module. Fixed some missing imports in views. Adapted some of the interface changes Rick did on robofaqs to osqa. --- forum/management/__init__.py | 3 + forum/models/__init__.py | 22 +- forum/models/question.py | 4 +- forum/models/repute.py | 2 + forum/modules.py | 54 + forum/skins/default/media/style/style.css | 2850 +++++++++++++++++--------- forum/skins/default/templates/index.html | 288 ++- forum/skins/default/templates/index_.html | 124 ++ forum/urls.py | 13 +- forum/views/__init__.py | 1 - forum/views/books.py | 140 -- forum/views/meta.py | 4 +- forum/views/readers.py | 60 +- forum/views/users.py | 1 + forum_modules/__init__.py | 0 forum_modules/books/__init__.py | 3 + forum_modules/books/models.py | 63 + forum_modules/books/urls.py | 10 + forum_modules/books/views.py | 142 ++ forum_modules/pgfulltext/__init__.py | 9 + forum_modules/pgfulltext/handlers.py | 11 + forum_modules/pgfulltext/management.py | 29 + forum_modules/pgfulltext/pg_fts_install.sql | 38 + forum_modules/sphinxfulltext/DISABLED | 0 forum_modules/sphinxfulltext/__init__.py | 0 forum_modules/sphinxfulltext/dependencies.py | 2 + forum_modules/sphinxfulltext/handlers.py | 4 + forum_modules/sphinxfulltext/models.py | 10 + forum_modules/sphinxfulltext/settings.py | 5 + osqa.iml | 9 + pgfulltext/__init__.py | 0 pgfulltext/management.py | 23 - 32 files changed, 2630 insertions(+), 1294 deletions(-) create mode 100755 forum/modules.py mode change 100644 => 100755 forum/skins/default/templates/index.html create mode 100755 forum/skins/default/templates/index_.html delete mode 100644 forum/views/books.py create mode 100755 forum_modules/__init__.py create mode 100755 forum_modules/books/__init__.py create mode 100755 forum_modules/books/models.py create mode 100755 forum_modules/books/urls.py create mode 100755 forum_modules/books/views.py create mode 100755 forum_modules/pgfulltext/__init__.py create mode 100755 forum_modules/pgfulltext/handlers.py create mode 100755 forum_modules/pgfulltext/management.py create mode 100755 forum_modules/pgfulltext/pg_fts_install.sql create mode 100755 forum_modules/sphinxfulltext/DISABLED create mode 100755 forum_modules/sphinxfulltext/__init__.py create mode 100755 forum_modules/sphinxfulltext/dependencies.py create mode 100755 forum_modules/sphinxfulltext/handlers.py create mode 100755 forum_modules/sphinxfulltext/models.py create mode 100755 forum_modules/sphinxfulltext/settings.py delete mode 100644 pgfulltext/__init__.py delete mode 100644 pgfulltext/management.py diff --git a/forum/management/__init__.py b/forum/management/__init__.py index e69de29b..8266592a 100644 --- a/forum/management/__init__.py +++ b/forum/management/__init__.py @@ -0,0 +1,3 @@ +from forum.modules import get_modules_script + +get_modules_script('management') \ No newline at end of file diff --git a/forum/models/__init__.py b/forum/models/__init__.py index 2ab7b263..ccc53a7c 100755 --- a/forum/models/__init__.py +++ b/forum/models/__init__.py @@ -38,11 +38,13 @@ User.add_to_class('email_isvalid', models.BooleanField(default=False)) User.add_to_class('email_key', models.CharField(max_length=32, null=True)) User.add_to_class('reputation', models.PositiveIntegerField(default=1)) User.add_to_class('gravatar', models.CharField(max_length=32)) -User.add_to_class('favorite_questions', - models.ManyToManyField(Question, through=FavoriteQuestion, - related_name='favorited_by')) -User.add_to_class('badges', models.ManyToManyField(Badge, through=Award, - related_name='awarded_to')) + +#User.add_to_class('favorite_questions', +# models.ManyToManyField(Question, through=FavoriteQuestion, +# related_name='favorited_by')) + +#User.add_to_class('badges', models.ManyToManyField(Badge, through=Award, +# related_name='awarded_to')) User.add_to_class('gold', models.SmallIntegerField(default=0)) User.add_to_class('silver', models.SmallIntegerField(default=0)) User.add_to_class('bronze', models.SmallIntegerField(default=0)) @@ -326,4 +328,14 @@ __all__ = [ 'Activity', 'EmailFeedSetting', 'AnonymousEmail', + + 'User' ] + + +from forum.modules import get_modules_script_classes + +for k, v in get_modules_script_classes('models', models.Model).items(): + if not k in __all__: + __all__.append(k) + exec "%s = v" % k \ No newline at end of file diff --git a/forum/models/question.py b/forum/models/question.py index 20779d26..27d6e9d9 100755 --- a/forum/models/question.py +++ b/forum/models/question.py @@ -129,6 +129,8 @@ class Question(Content, DeletableContent): tagnames = models.CharField(max_length=125) summary = models.CharField(max_length=180) + favorited_by = models.ManyToManyField(User, through='FavoriteQuestion', related_name='favorite_questions') + objects = QuestionManager() class Meta(Content.Meta): @@ -283,7 +285,7 @@ class FavoriteQuestion(models.Model): """A favorite Question of a User.""" question = models.ForeignKey(Question) user = models.ForeignKey(User, related_name='user_favorite_questions') - added_at = models.DateTimeField(default=datetime.datetime.now) + added_at = models.DateTimeField(default=datetime.datetime.now) class Meta: app_label = 'forum' diff --git a/forum/models/repute.py b/forum/models/repute.py index 768dbee6..cac761da 100755 --- a/forum/models/repute.py +++ b/forum/models/repute.py @@ -21,6 +21,8 @@ class Badge(models.Model): # Denormalised data awarded_count = models.PositiveIntegerField(default=0) + awarded_to = models.ManyToManyField(User, through='Award', related_name='badges') + class Meta: app_label = 'forum' db_table = u'badge' diff --git a/forum/modules.py b/forum/modules.py new file mode 100755 index 00000000..53cc619a --- /dev/null +++ b/forum/modules.py @@ -0,0 +1,54 @@ +import os +import types + +MODULES_PACKAGE = 'forum_modules' + +MODULES_FOLDER = os.path.join(os.path.dirname(__file__), '../' + MODULES_PACKAGE) + +MODULE_LIST = [ + __import__('forum_modules.%s' % f, globals(), locals(), ['forum_modules']) + for f in os.listdir(MODULES_FOLDER) + if os.path.isdir(os.path.join(MODULES_FOLDER, f)) and + os.path.exists(os.path.join(MODULES_FOLDER, "%s/__init__.py" % f)) and + not os.path.exists(os.path.join(MODULES_FOLDER, "%s/DISABLED" % f)) +] + +def get_modules_script(script_name): + all = [] + + for m in MODULE_LIST: + try: + all.append(__import__('%s.%s' % (m.__name__, script_name), globals(), locals(), [m.__name__])) + except: + pass + + return all + +def get_modules_script_classes(script_name, base_class): + scripts = get_modules_script(script_name) + all_classes = {} + + for script in scripts: + all_classes.update(dict([ + (n, c) for (n, c) in [(n, getattr(script, n)) for n in dir(script)] + if isinstance(c, (type, types.ClassType)) and issubclass(c, base_class) + ])) + + return all_classes + +def get_all_handlers(name): + handler_files = get_modules_script('handlers') + + return [ + h for h in [ + getattr(f, name) for f in handler_files + if hasattr(f, name) + ] + + if callable(h) + ] + +def get_handler(name, default): + all = get_all_handlers(name) + print(len(all)) + return len(all) and all[0] or default \ No newline at end of file diff --git a/forum/skins/default/media/style/style.css b/forum/skins/default/media/style/style.css index 175fcb66..02148ab0 100644 --- a/forum/skins/default/media/style/style.css +++ b/forum/skins/default/media/style/style.css @@ -1,656 +1,1340 @@ @import url(jquery.autocomplete.css); @import url(openid.css); @import url(prettify.css); + /* 公用 */ -body{background:#FFF; font-size:12px; line-height:150%; margin:0; padding:0; color:#000; font-family: sans-serif; -} -div{margin:0 auto; padding:0;} -h1,h2,h3,h4,h5,h6,ul,li,dl,dt,dd,form,img,p{margin:0; padding:0; border:none; } -label {vertical-align:middle;} -hr {border:none;border-top: 1px dashed #ccccce;} -input, select {vertical-align:middle;font-family:Trebuchet MS,"segoe ui",Helvetica,"Microsoft YaHei",宋体,Tahoma,Verdana,MingLiu,PMingLiu,Arial,sans-serif;} -p{margin-bottom:13px; font-size:13px; line-height:140%;} -a {color:#333333; text-decoration:none;} -.badges a {color:#763333;text-decoration:underline;} -a:hover {text-decoration:underline;} -.block{width:960px; height:auto;} -.fleft{float:left;} -.fright{float:right;} -.tleft{text-align:left;} -.tcenter{text-align:center;} -.tright{text-align:right;} -.dis{display:block;} -.inline{display:inline;} -.none{display:none;} -.red{color:#CC0000;} -.b{font-weight:bold;} -.f10{font-size:10px;} -.f11{font-size:11px;} -.f12{font-size:12px;} -.f13{font-size:13px;} -.f14{font-size:14px;} -.white{color:#FFFFFF;} -.u{text-decoration:underline;} -.spacer1{height:6px; line-height:6px; clear:both; visibility:hidden;} -.spacer3{height:30px; line-height:30px; clear:both; visibility:hidden;} -h1{font-size:160%;padding:5px 0 5px 0;} -h2{font-size:140%;padding:3px 0 3px 0;} -h3{font-size:120%;padding:3px 0 3px 0;} -ul -{ - list-style: disc; - margin-left: 20px; - padding-left:0px; - margin-bottom: 1em; -} -ol -{ - list-style: decimal; - margin-left: 30px; - margin-bottom: 1em; - padding-left:0px; +body { + background: #FFF; + font-size: 12px; + line-height: 150%; + margin: 0; + padding: 0; + color: #000; + font-family: sans-serif; +} + +div { + margin: 0 auto; + padding: 0; +} + +h1, h2, h3, h4, h5, h6, ul, li, dl, dt, dd, form, img, p { + margin: 0; + padding: 0; + border: none; +} + +label { + vertical-align: middle; +} + +hr { + border: none; + border-top: 1px dashed #ccccce; +} + +input, select { + vertical-align: middle; + font-family: Trebuchet MS, "segoe ui", Helvetica, "Microsoft YaHei", 宋 体, Tahoma, Verdana, MingLiu, PMingLiu, Arial, sans-serif; +} + +p { + margin-bottom: 13px; + font-size: 13px; + line-height: 140%; +} + +a { + color: #333333; + text-decoration: none; +} + +.badges a { + color: #763333; + text-decoration: underline; +} + +a:hover { + text-decoration: underline; +} + +.block { + width: 960px; + height: auto; +} + +.fleft { + float: left; +} + +.fright { + float: right; +} + +.tleft { + text-align: left; +} + +.tcenter { + text-align: center; +} + +.tright { + text-align: right; +} + +.dis { + display: block; +} + +.inline { + display: inline; +} + +.none { + display: none; +} + +.red { + color: #CC0000; +} + +.b { + font-weight: bold; +} + +.f10 { + font-size: 10px; +} + +.f11 { + font-size: 11px; +} + +.f12 { + font-size: 12px; +} + +.f13 { + font-size: 13px; +} + +.f14 { + font-size: 14px; +} + +.white { + color: #FFFFFF; +} + +.u { + text-decoration: underline; +} + +.spacer1 { + height: 6px; + line-height: 6px; + clear: both; + visibility: hidden; +} + +.spacer3 { + height: 30px; + line-height: 30px; + clear: both; + visibility: hidden; +} + +h1 { + font-size: 160%; + padding: 5px 0 5px 0; +} + +h2 { + font-size: 140%; + padding: 3px 0 3px 0; +} + +h3 { + font-size: 120%; + padding: 3px 0 3px 0; +} + +ul { + list-style: disc; + margin-left: 20px; + padding-left: 0px; + margin-bottom: 1em; +} + +ol { + list-style: decimal; + margin-left: 30px; + margin-bottom: 1em; + padding-left: 0px; } + td ul { - vertical-align:middle; + vertical-align: middle; } + li input { margin: 3px 3px 4px 3px; } -pre -{ - font-family: Consolas, Monaco, Liberation Mono, Lucida Console, Monospace; - font-size:100%; - margin-bottom: 10px; - overflow: auto; - width: 580px; - background-color: #F5F5F5; - padding-left:5px; - padding-top:5px; - padding-bottom: 20px !ie7; + +pre { + font-family: Consolas, Monaco, Liberation Mono, Lucida Console, Monospace; + font-size: 100%; + margin-bottom: 10px; + overflow: auto; + width: 580px; + background-color: #F5F5F5; + padding-left: 5px; + padding-top: 5px; + padding-bottom: 20px ! ie7; } -code{ +code { font-family: Consolas, Monaco, Liberation Mono, Lucida Console, Monospace; - font-size:100%; + font-size: 100%; } -blockquote -{ - margin-bottom: 10px; - margin-right: 15px; - padding: 10px 0px 1px 10px; - background-color: #F5F5F5; +blockquote { + margin-bottom: 10px; + margin-right: 15px; + padding: 10px 0px 1px 10px; + background-color: #F5F5F5; } /*页面布局*/ -#wrapper {width:960px;margin:auto;padding:0;} +#wrapper { + width: 960px; + margin: auto; + padding: 0; +} + #roof { - position:relative; - margin-top:0px; - background:#FFF; -} -#room {padding:10px 0 10px 0;background-color:#FFF;border-bottom:1px solid #777;} -#CALeft{width:710px; float:left; position:relative;} -#CARight{width:240px; float:right;} -#CAFull{float:left;padding:0 5px 0 5px;width:950px;} -#ground {width:100%;border-top:1px solid #000; padding-top:6px; padding-bottom:0px; text-align:center;background:#777;} + position: relative; + margin-top: 0px; + background: #FFF; +} + +#room { + padding: 10px 0 10px 0; + background-color: #FFF; + border-bottom: 1px solid #777; +} + +#CALeft { + width: 710px; + float: left; + position: relative; +} + +#CARight { + width: 240px; + float: right; +} + +#CAFull { + float: left; + padding: 0 5px 0 5px; + width: 950px; +} + +#ground { + width: 100%; + border-top: 1px solid #000; + padding-top: 6px; + padding-bottom: 0px; + text-align: center; + background: #777; +} + /*#licenseLogo {position:absolute;top:10px;right:10px;}*/ /*顶部及导航栏*/ #top { - position:absolute; - top:0px; - right:0px; - height:20px; - text-align:right; - padding:3px; - background-color:#ffffff; - width:500px; + position: absolute; + top: 0px; + right: 0px; + height: 20px; + text-align: right; + padding: 3px; + background-color: #ffffff; + width: 500px; } + /*#header {width:960px;}*/ -#top a {height:35px; text-align:right; - /*letter-spacing:1px; */ - margin-left:20px;text-decoration:underline; font-size:12px; color:#333333;} +#top a { + height: 35px; + text-align: right; /*letter-spacing:1px; */ + margin-left: 20px; + text-decoration: underline; + font-size: 12px; + color: #333333; +} + #logo { - padding: 5px 0px 0px 0px; -} -#navBar {float:clear;position:relative;display:block;width:960px;} -#navBar .nav {margin:20px 0px 0px 16px; - /*letter-spacing:1px; */ - } -#navBar .nav a {color:#333333; background-color:#fff0e0; - /*border-left: 1px solid #eeeeec; - border-right: 1px solid #babdb6; - border-top: 1px solid #eeeeec;*/ - border: 1px solid #888888; - border-bottom: none; - padding:0px 12px 3px 12px; height:25px; line-height:30px;margin-left:10px; font-size:14px; font-weight:400; text-decoration:none;display: block;float: left;} -#navBar .nav a:hover {text-decoration:underline} -#navBar .nav a.on {height:24px;line-height:28px; - border-bottom: 1px solid #a40000; - border-right:1px solid #820000; - border-top:1px solid #d40000; - border-left:1px solid #d40000; - /*background:#A31E39; */ - background:#a40000; - color:#FFF; font-weight:600; text-decoration:none} -#navBar .nav a.special {font-size:14px; color:#B02B2C; font-weight:bold; text-decoration:none; } -#navBar .nav a.special:hover {text-decoration:underline;} -#navBar .nav div.focus {float:right; padding-right:0px;} + padding: 5px 0px 0px 0px; +} + +#navBar { + float: clear; + position: relative; + display: block; + width: 960px; +} + +#navBar .nav { + margin: 20px 0px 0px 16px; /*letter-spacing:1px; */ +} + +#navBar .nav a { + color: #333333; + background-color: #fff0e0; + /*border-left: 1px solid #eeeeec; + border-right: 1px solid #babdb6; + border-top: 1px solid #eeeeec;*/ + border: 1px solid #888888; + border-bottom: none; + padding: 0px 12px 3px 12px; + height: 25px; + line-height: 30px; + margin-left: 10px; + font-size: 14px; + font-weight: 400; + text-decoration: none; + display: block; + float: left; +} + +#navBar .nav a:hover { + text-decoration: underline +} + +#navBar .nav a.on { + height: 24px; + line-height: 28px; + border-bottom: 1px solid #a40000; + border-right: 1px solid #820000; + border-top: 1px solid #d40000; + border-left: 1px solid #d40000; /*background:#A31E39; */ + background: #a40000; + color: #FFF; + font-weight: 600; + text-decoration: none +} + +#navBar .nav a.special { + font-size: 14px; + color: #B02B2C; + font-weight: bold; + text-decoration: none; +} + +#navBar .nav a.special:hover { + text-decoration: underline; +} + +#navBar .nav div.focus { + float: right; + padding-right: 0px; +} + /*搜索栏*/ -#searchBar {width:958px; - background-color:#888a85;/*#e9b96e;*/ +#searchBar { + width: 958px; + background-color: #888a85; /*#e9b96e;*/ border: 1px solid #aaaaaa; - padding:4px 0 0 0;} /* #B02B2C */ -#searchBar .content { } -#searchBar .searchInput {font-size:13px; height:18px; width:400px;} -#searchBar .searchBtn {font-size:14px; height:26px; width:80px;} -#searchBar .options {padding:3px 0 3px 0;font-size:100%;color:#EEE; - /*letter-spacing:1px;*/ - } -#searchBar .options INPUT {margin:0 3px 0 15px;} -#searchBar .options INPUT:hover {cursor:pointer} + padding: 4px 0 0 0; +} + +/* #B02B2C */ +#searchBar .content { +} + +#searchBar .searchInput { + font-size: 13px; + height: 18px; + width: 400px; +} + +#searchBar .searchBtn { + font-size: 14px; + height: 26px; + width: 80px; +} + +#searchBar .options { + padding: 3px 0 3px 0; + font-size: 100%; + color: #EEE; /*letter-spacing:1px;*/ +} + +#searchBar .options INPUT { + margin: 0 3px 0 15px; +} + +#searchBar .options INPUT:hover { + cursor: pointer +} /*问题列表*/ -#listA {float:left; background-color:#FFF;padding:0 0px 0 0px; width:100%;} +#listA { + float: left; + background-color: #FFF; + padding: 0 0px 0 0px; + width: 100%; +} + #listA .qstA { - position:relative; - padding:3px 5px 5px 10px; - border-top:1px dashed #ccccce; + position: relative; + padding: 3px 5px 5px 10px; + border-top: 1px dashed #ccccce; /*border-left:1px solid #ebebbe; border-right:1px solid #b4b48e; border-bottom:1px solid #b4b48e;*/ - background: white;/* #f9f7ed;*/ - /*margin:10px 0 10px 0;*/ - /*background:url(../images/quest-bg.gif) repeat-x top;*/ + background: white; /* #f9f7ed;*/ +/*margin:10px 0 10px 0;*/ +/*background:url(../images/quest-bg.gif) repeat-x top;*/ } -#listA .qstA thumb {float:left; } -#listA .qstA H2 {font-size:14px; font-weight:800; margin:8px auto;padding:0px;} -#listA .qstA H2 a {color:333333/*#2e3436*/;font-size:15px;} + +#listA .qstA thumb { + float: left; +} + +#listA .qstA H2 { + font-size: 14px; + font-weight: 800; + margin: 8px auto; + padding: 0px; +} + +#listA .qstA H2 a { + color: 333333 /*#2e3436*/; + font-size: 15px; +} + #listA .qstA .stat { - position:absolute; - right:0px; - bottom:5px; - font-size:12px; - /*letter-spacing:1px;*/ - float:right; -} -#listA .qstA .stat span {margin-right:5px;} -#listA .qstA .stat td {min-width:40px;text-align:center;} + position: absolute; + right: 0px; + bottom: 5px; + font-size: 12px; /*letter-spacing:1px;*/ + float: right; +} + +#listA .qstA .stat span { + margin-right: 5px; +} + +#listA .qstA .stat td { + min-width: 40px; + text-align: center; +} + #listA .qstA .stat .num { - font-family:sans-serif; - color:#a40000; + font-family: sans-serif; + color: #a40000; /*background:#eeeeec; - border: 1px solid #babdb6;*/ - margin:0px; - font-size:17px; - font-weight:800; -} -#listA .qstA table {border-spacing:0px;} -#listA .qstA table td {padding:0px;width:60px;text-align:center;} -#listA .qstA .stat .unit {color:#777777;margin:0px} -#listA .qstA .from {margin-top:5px; font-size:13px;color:#777777;} -#listA .qstA .from .score {font-family:sans-serif;color:#555555;} -#listA .qstA .date {margin-left:10px; color:#777777;} -#listA .qstA .wiki {color:#763333;font-size:12px;} -#listA .qstA .from a {} -#listA .qstA .from IMG {vertical-align:middle;} -#listA .qstA .author {font-weight:400; } -#listA .qstA .author a{color:#444444; } -#listA .qstA .summary{margin-right:5px;} + border: 1px solid #babdb6;*/ + margin: 0px; + font-size: 17px; + font-weight: 800; +} + +#listA .qstA table { + border-spacing: 0px; +} + +#listA .qstA table td { + padding: 0px; + width: 60px; + text-align: center; +} + +#listA .qstA .stat .unit { + color: #777777; + margin: 0px +} + +#listA .qstA .from { + margin-top: 5px; + font-size: 13px; + color: #777777; +} + +#listA .qstA .from .score { + font-family: sans-serif; + color: #555555; +} + +#listA .qstA .date { + margin-left: 10px; + color: #777777; +} + +#listA .qstA .wiki { + color: #763333; + font-size: 12px; +} + +#listA .qstA .from a { +} + +#listA .qstA .from IMG { + vertical-align: middle; +} + +#listA .qstA .author { + font-weight: 400; +} + +#listA .qstA .author a { + color: #444444; +} + +#listA .qstA .summary { + margin-right: 5px; +} + +.short-summary { + position: relative; + padding: 3px 5px 5px 10px; + border-top: 1px dotted #ccccce; + overflow: hidden; + width: 700px; + float: left; +} + +.short-summary h2 { + font-size: 16px; + font-family: "Trebuchet MS", "segoe ui", arial, sans-serif; +} + +.short-summary .userinfo { + float: right; + margin-top: 8px; +} + +.short-summary .counts { + float: right; + margin-top: 4px; +} + +.short-summary .counts .item-count { + font-size: 17px; + font-weight: 800; +} + +.short-summary .votes, +.short-summary .status, +.short-summary .views { + font-size: 12px; + text-align: center; + margin: 0 0 0 7px; + padding: 4px 2px 0px 2px; + width: 46px; + height: 48px; + float: left; + -moz-border-radius: 5px; + -khtml-border-radius: 5px; + -webkit-border-radius: 5px; +} + #question-table { - margin-bottom:10px; - /*border-bottom:1px solid #888a85;*/ + margin-bottom: 10px; /*border-bottom:1px solid #888a85;*/ } -.evenMore {font-size:14px; font-weight:800;} -.questions-count{ - font-size:32px; - font-family:sans-serif; - font-weight:600; - padding:0 0 5px 0px; - color:#a40000; - margin-top:3px; + +.evenMore { + font-size: 14px; + font-weight: 800; +} + +.questions-count { + font-size: 32px; + font-family: sans-serif; + font-weight: 600; + padding: 0 0 5px 0px; + color: #a40000; + margin-top: 3px; } /*内容块*/ -.boxA {background:#888a85; padding:6px; margin-bottom:8px;border 1px solid #babdb6;} -.boxA H3 {font-size:13px; font-weight:800; color:#FFF; margin:0; padding:0; margin-bottom:4px;} -.boxA .body {border:1px solid #999; padding:8px; background:#FFF; font-size:13px;} -.boxA .more {padding:2px; text-align:right; font-weight:800;} -.boxB {background:#F9F7ED; padding:6px; margin-bottom:8px;border:solid 1px #aaaaaa;} -.boxB H3 {font-size:13px; font-weight:800; color:#000; margin:0; padding:0 0 0 15px; margin-bottom:4px; background:url(../images/dot-g.gif) no-repeat left center;} -.boxB .body {border:1px solid #aaaaaa; padding:8px; background:#FFF; font-size:13px; line-height:160%;} -.boxB .more {padding:1px; text-align:right; font-weight:800;} +.boxA { + background: #888a85; + padding: 6px; + margin-bottom: 8px; + border 1px solid #babdb6; +} + +.boxA H3 { + font-size: 13px; + font-weight: 800; + color: #FFF; + margin: 0; + padding: 0; + margin-bottom: 4px; +} + +.boxA .body { + border: 1px solid #999; + padding: 8px; + background: #FFF; + font-size: 13px; +} + +.boxA .more { + padding: 2px; + text-align: right; + font-weight: 800; +} + +.boxB { + background: #F9F7ED; + padding: 6px; + margin-bottom: 8px; + border: solid 1px #aaaaaa; +} + +.boxB H3 { + font-size: 13px; + font-weight: 800; + color: #000; + margin: 0; + padding: 0 0 0 15px; + margin-bottom: 4px; + background: url(../images/dot-g.gif) no-repeat left center; +} + +.boxB .body { + border: 1px solid #aaaaaa; + padding: 8px; + background: #FFF; + font-size: 13px; + line-height: 160%; +} + +.boxB .more { + padding: 1px; + text-align: right; + font-weight: 800; +} + .boxC { - background: #cacdc6;/*f9f7ed;*/ - padding:10px; - margin-bottom:8px; - border-top:1px solid #eeeeec; - border-left:1px solid #eeeeec; - border-right:1px solid #a9aca5; - border-bottom:1px solid #babdb6; + background: #cacdc6; /*f9f7ed;*/ + padding: 10px; + margin-bottom: 8px; + border-top: 1px solid #eeeeec; + border-left: 1px solid #eeeeec; + border-right: 1px solid #a9aca5; + border-bottom: 1px solid #babdb6; } + .boxC p { - margin-bottom:8px; + margin-bottom: 8px; } + .boxC p.nomargin { - margin:0px; + margin: 0px; } + .boxC p.info-box-follow-up-links { - text-align:right; - margin:0; + text-align: right; + margin: 0; } + /*分页*/ -.pager {margin-top:10px; margin-bottom:16px; float:left;} -.pagesize {margin-top:10px; margin-bottom:16px; float:right;} +.pager { + margin-top: 10px; + margin-bottom: 16px; + float: left; +} + +.pagesize { + margin-top: 10px; + margin-bottom: 16px; + float: right; +} /** PAGINATOR **/ .paginator { - padding:5px 0 10px 0; - font:normal 12px sans-serif; + padding: 5px 0 10px 0; + font: normal 12px sans-serif; } .paginator .prev-na, .paginator .next-na { - padding:.3em; - font:bold .875em sans-serif; + padding: .3em; + font: bold .875em sans-serif; } .paginator .prev-na, .paginator .next-na { - border:1px solid #ccc; - background-color:#f9f9f9; - color:#aaa; - font-weight:normal; + border: 1px solid #ccc; + background-color: #f9f9f9; + color: #aaa; + font-weight: normal; } .paginator .prev a, .paginator .prev a:visited, .paginator .next a, .paginator .next a:visited { - border:1px solid #fff; - background-color:#fff; - color:#777; - padding:2px 4px 3px 4px; - font:bold 100% sans-serif; + border: 1px solid #fff; + background-color: #fff; + color: #777; + padding: 2px 4px 3px 4px; + font: bold 100% sans-serif; } -.paginator .prev, .paginator .prev-na { margin-right:.5em; } -.paginator .next, .paginator .next-na { margin-left:.5em; } +.paginator .prev, .paginator .prev-na { + margin-right: .5em; +} + +.paginator .next, .paginator .next-na { + margin-left: .5em; +} .paginator .page a, .paginator .page a:visited, .paginator .curr { - padding:.25em; - font:normal .875em verdana; - border:1px solid #ccc; - background-color:#fff; - margin:0em .25em; - color:#777; + padding: .25em; + font: normal .875em verdana; + border: 1px solid #ccc; + background-color: #fff; + margin: 0em .25em; + color: #777; } .paginator .curr { - background-color:#777; - color:#fff; - border:1px solid #777; - font-weight:bold; + background-color: #777; + color: #fff; + border: 1px solid #777; + font-weight: bold; } .paginator .page a:hover, .paginator .curr a:hover, .paginator .prev a:hover, .paginator .next a:hover { - color:#fff; - background-color:#777; - border:1px solid #777; - text-decoration:none; + color: #fff; + background-color: #777; + border: 1px solid #777; + text-decoration: none; } -.paginator .text{ - color:#777; - padding:.3em; - font:bold 100% sans-serif; +.paginator .text { + color: #777; + padding: .3em; + font: bold 100% sans-serif; } -.paginator-container{ - float:right; - padding:10px 0 10px 0; +.paginator-container { + float: right; + padding: 10px 0 10px 0; } -.paginator-container-left{ - padding:5px 0 10px 0; +.paginator-container-left { + padding: 5px 0 10px 0; } /*标签*/ -.tag {font-size:13px; font-weight:normal; color:#333; text-decoration:none;background-color:#EEE; border-left:3px solid #777; border-top:1px solid #EEE; border-bottom:1px solid #CCC; border-right:1px solid #CCC; padding:1px 8px 1px 8px;} -.tags {font-family:sans-serif; line-height:200%; display:block; margin-top:5px;} -.tags a {white-space: nowrap; font-size:13px; font-weight:normal; color:#333; text-decoration:none;background-color:#EEE; border-left:3px solid #777; border-top:1px solid #EEE; border-bottom:1px solid #CCC; border-right:1px solid #CCC; padding:1px 8px 1px 8px;} -.tags a:hover {background-color:#fFF;color:#333;} -.tagsbox {line-height:200%;} -.tagsbox a {font-size:13px; font-weight:normal; color:#333; text-decoration:none;background-color:#EEE; border-left:3px solid #777; border-top:1px solid #EEE; border-bottom:1px solid #CCC; border-right:1px solid #CCC; padding:1px 8px 1px 8px;} -.tagsbox a:hover {background-color:#fFF;color:#333;} -.tag-number {font-weight:700;font-family:sans-serif;} -.marked-tags { margin-top: 0px;margin-bottom: 5px; } -.deletable-tag { margin-right: 3px; white-space:nowrap; } +.tag { + font-size: 13px; + font-weight: normal; + color: #333; + text-decoration: none; + background-color: #EEE; + border-left: 3px solid #777; + border-top: 1px solid #EEE; + border-bottom: 1px solid #CCC; + border-right: 1px solid #CCC; + padding: 1px 8px 1px 8px; +} + +.tags { + font-family: sans-serif; + line-height: 200%; + display: block; + margin-top: 5px; +} + +.tags a { + white-space: nowrap; + font-size: 13px; + font-weight: normal; + color: #333; + text-decoration: none; + background-color: #EEE; + border-left: 3px solid #777; + border-top: 1px solid #EEE; + border-bottom: 1px solid #CCC; + border-right: 1px solid #CCC; + padding: 1px 8px 1px 8px; +} + +.tags a:hover { + background-color: #fFF; + color: #333; +} + +.tagsbox { + line-height: 200%; +} + +.tagsbox a { + font-size: 13px; + font-weight: normal; + color: #333; + text-decoration: none; + background-color: #EEE; + border-left: 3px solid #777; + border-top: 1px solid #EEE; + border-bottom: 1px solid #CCC; + border-right: 1px solid #CCC; + padding: 1px 8px 1px 8px; +} + +.tagsbox a:hover { + background-color: #fFF; + color: #333; +} + +.tag-number { + font-weight: 700; + font-family: sans-serif; +} + +.marked-tags { + margin-top: 0px; + margin-bottom: 5px; +} + +.deletable-tag { + margin-right: 3px; + white-space: nowrap; +} /*奖牌*/ -a.medal { font-size:14px; line-height:250%; font-weight:800; color:#333; text-decoration:none; background:url(../images/medala.gif) no-repeat; border-left:1px solid #EEE; border-top:1px solid #EEE; border-bottom:1px solid #CCC; border-right:1px solid #CCC; padding:4px 12px 4px 6px;} -a:hover.medal {color:#333; text-decoration:none; background:url(../images/medala_on.gif) no-repeat; border-left:1px solid #E7E296; border-top:1px solid #E7E296; border-bottom:1px solid #D1CA3D; border-right:1px solid #D1CA3D;} +a.medal { + font-size: 14px; + line-height: 250%; + font-weight: 800; + color: #333; + text-decoration: none; + background: url(../images/medala.gif) no-repeat; + border-left: 1px solid #EEE; + border-top: 1px solid #EEE; + border-bottom: 1px solid #CCC; + border-right: 1px solid #CCC; + padding: 4px 12px 4px 6px; +} + +a:hover.medal { + color: #333; + text-decoration: none; + background: url(../images/medala_on.gif) no-repeat; + border-left: 1px solid #E7E296; + border-top: 1px solid #E7E296; + border-bottom: 1px solid #D1CA3D; + border-right: 1px solid #D1CA3D; +} /*Tab栏*/ -.tabBar{background-color:#FFF;border-bottom: 1px solid white;height: 30px; width: 100%;clear:both; margin-bottom:3px;} -.tabsA {background-color:#FFF;float:right;position:relative;display:block;font-weight:bold;height:20px;} -.tabsB {background-color:#FFF;float:left;position:relative;display:block;font-weight:bold;height:20px;} -.tabsA a.on, .tabsA a:hover,.tabsB a.on, .tabsB a:hover { +.tabBar { + background-color: #FFF; + border-bottom: 1px solid white; + height: 30px; + width: 100%; + clear: both; + margin-bottom: 3px; +} + +.tabsA { + background-color: #FFF; + float: right; + position: relative; + display: block; + font-weight: bold; + height: 20px; +} + +.tabsB { + background-color: #FFF; + float: left; + position: relative; + display: block; + font-weight: bold; + height: 20px; +} + +.tabsA a.on, .tabsA a:hover, .tabsB a.on, .tabsB a:hover { background: #fff; - color:#a40000; - border-top:1px solid #babdb6; - border-left:1px solid #babdb6; - border-right:1px solid #888a85; - border-bottom:1px solid #888a85; - height: 24px; - line-height: 26px; - margin-top: 3px; - padding: 0px 11px 0px 11px;} + color: #a40000; + border-top: 1px solid #babdb6; + border-left: 1px solid #babdb6; + border-right: 1px solid #888a85; + border-bottom: 1px solid #888a85; + height: 24px; + line-height: 26px; + margin-top: 3px; + padding: 0px 11px 0px 11px; +} .tabsA a { background: #f9f7eb; - border-top:1px solid #eeeeec; - border-left:1px solid #eeeeec; - border-right:1px solid #a9aca5; - border-bottom:1px solid #888a85; - color: #888a85; - display: block; - float: left; - height: 20px; - line-height: 22px; - margin: 5px 4px 0 0; - padding: 0 11px 0 11px; - text-decoration: none; -} -.tabsB a {background: #eee; - border: 1px solid #eee; - color: #777; - display: block; - float: left; - height: 22px; - line-height: 28px; - margin: 5px 0px 0 4px; - padding: 0 11px 0 11px; - text-decoration: none; + border-top: 1px solid #eeeeec; + border-left: 1px solid #eeeeec; + border-right: 1px solid #a9aca5; + border-bottom: 1px solid #888a85; + color: #888a85; + display: block; + float: left; + height: 20px; + line-height: 22px; + margin: 5px 4px 0 0; + padding: 0 11px 0 11px; + text-decoration: none; } + +.tabsB a { + background: #eee; + border: 1px solid #eee; + color: #777; + display: block; + float: left; + height: 22px; + line-height: 28px; + margin: 5px 0px 0 4px; + padding: 0 11px 0 11px; + text-decoration: none; +} + /*.tabsA a:hover, .tabsB a:hover {background: #fff;border: 1px solid #777;border-bottom:3px solid #FFF;}*/ -.headlineA {font-size:13px; border-bottom:1px solid #777; padding-bottom:2px; font-weight:800; margin-bottom:12px; text-align:right; height:30px;} -.headQuestions {float:left; height:23px; line-height:23px; margin:5px 0 0 5px;padding:0px 6px 0px 15px; font-size:15px; font-weight:700; border-bottom:0px solid #777; border-left:0px solid #darkred; background-color:#FFF;background:url(../images/dot-list.gif) no-repeat left center;} -.headAnswers {float:left; padding:3px; font-size:18px; font-weight:800; background:url(../images/ico_answers.gif) left 2px no-repeat; padding-left:24px;} -.headTags {float:left; padding:3px; font-size:18px; font-weight:800; background:url(../images/ico_tags.gif) no-repeat; padding-left:24px;} -.headUsers {float:left; height:23px; line-height:23px; margin:5px 0 0 5px;padding:0px 6px 0px 15px; font-size:15px; font-weight:700; border-bottom:0px solid #777; border-left:0px solid #darkred; background-color:#FFF;background:url(../images/dot-list.gif) no-repeat left center;} -.headMedals {float:left; height:23px; line-height:23px; margin:5px 0 0 5px;padding:0px 6px 0px 15px; font-size:15px; font-weight:700; border-bottom:0px solid #777; border-left:0px solid #darkred; background-color:#FFF;background:url(../images/dot-list.gif) no-repeat left center;} -.headLogin {float:left; padding:3px; font-size:15px; font-weight:800; background:url(../images/ico_login.gif) no-repeat; padding-left:24px;} +.headlineA { + font-size: 13px; + border-bottom: 1px solid #777; + padding-bottom: 2px; + font-weight: 800; + margin-bottom: 12px; + text-align: right; + height: 30px; +} + +.headQuestions { + float: left; + height: 23px; + line-height: 23px; + margin: 5px 0 0 5px; + padding: 0px 6px 0px 15px; + font-size: 15px; + font-weight: 700; + border-bottom: 0px solid #777; + border-left: 0px solid #darkred; + background-color: #FFF; + background: url(../images/dot-list.gif) no-repeat left center; +} + +.headAnswers { + float: left; + padding: 3px; + font-size: 18px; + font-weight: 800; + background: url(../images/ico_answers.gif) left 2px no-repeat; + padding-left: 24px; +} + +.headTags { + float: left; + padding: 3px; + font-size: 18px; + font-weight: 800; + background: url(../images/ico_tags.gif) no-repeat; + padding-left: 24px; +} + +.headUsers { + float: left; + height: 23px; + line-height: 23px; + margin: 5px 0 0 5px; + padding: 0px 6px 0px 15px; + font-size: 15px; + font-weight: 700; + border-bottom: 0px solid #777; + border-left: 0px solid #darkred; + background-color: #FFF; + background: url(../images/dot-list.gif) no-repeat left center; +} + +.headMedals { + float: left; + height: 23px; + line-height: 23px; + margin: 5px 0 0 5px; + padding: 0px 6px 0px 15px; + font-size: 15px; + font-weight: 700; + border-bottom: 0px solid #777; + border-left: 0px solid #darkred; + background-color: #FFF; + background: url(../images/dot-list.gif) no-repeat left center; +} + +.headLogin { + float: left; + padding: 3px; + font-size: 15px; + font-weight: 800; + background: url(../images/ico_login.gif) no-repeat; + padding-left: 24px; +} + .headNormal { - text-align:left; - padding:3px; - font-size:15px; - margin-bottom:12px; - font-weight:bold; - border-bottom: 1px solid #777; -} -.headUser {text-align:left;padding:5px; font-size:20px; - /*letter-spacing:1px;*/ - margin-bottom:12px; font-weight:800;border-bottom:1px solid #777;} + text-align: left; + padding: 3px; + font-size: 15px; + margin-bottom: 12px; + font-weight: bold; + border-bottom: 1px solid #777; +} + +.headUser { + text-align: left; + padding: 5px; + font-size: 20px; /*letter-spacing:1px;*/ + margin-bottom: 12px; + font-weight: 800; + border-bottom: 1px solid #777; +} + /*RSS订阅*/ -#feeds {margin:10px 0; } -#feeds a {background:url(../images/feed-icon-small.png) no-repeat 0; padding-left:18px; font-weight:700; font-size:13px; } +#feeds { + margin: 10px 0; +} + +#feeds a { + background: url(../images/feed-icon-small.png) no-repeat 0; + padding-left: 18px; + font-weight: 700; + font-size: 13px; +} /*问题*/ -#question {margin-bottom:30px;} -#question h1{font-size:15px;background:#CCC; padding:6px 8px;;} -#question .body{background:#F7F7F7; padding:20px 10px;} -.starter {padding:10px; background:#E0EAF1;} -.vote {font-size:20px; color:#666; font-weight:800;} -.questions-related{font-weight:700;word-wrap:break-word;} -.questions-related p{line-height:20px; margin-bottom:10px;font-size:100%;} -.question-status{ - margin-top:10px; +#question { + margin-bottom: 30px; +} + +#question h1 { + font-size: 15px; + background: #CCC; + padding: 6px 8px;; +} + +#question .body { + background: #F7F7F7; + padding: 20px 10px; +} + +.starter { + padding: 10px; + background: #E0EAF1; +} + +.vote { + font-size: 20px; + color: #666; + font-weight: 800; +} + +.questions-related { + font-weight: 700; + word-wrap: break-word; +} + +.questions-related p { + line-height: 20px; + margin-bottom: 10px; + font-size: 100%; +} + +.question-status { + margin-top: 10px; padding: 20px; - background-color:#F5F5F5; - text-align:center; + background-color: #F5F5F5; + text-align: center; } -.question-status h3{font-size:125%;} -.question-body{ - min-height:100px; - font-size:13px; - line-height:20px; + +.question-status h3 { + font-size: 125%; } -.question-body IMG{ - max-width:600px; + +.question-body { + min-height: 100px; + font-size: 13px; + line-height: 20px; } -.question-mark{ + +.question-body IMG { + max-width: 600px; +} + +.question-mark { /*background-color:#fff5e0; border-top: 1px solid #eeeeec; border-right: 1px solid #babdb6; border-bottom: 1px solid #babdb6; border-left: 1px solid #eeeeec;*/ - text-align:left; - padding:5px; - overflow:hidden; -} -.question-edit{ - text-align:left; - overflow:hidden; -} -.vote-buttons {float:left;text-align:center;} -.vote-buttons IMG{cursor:pointer;} -.vote-number{ - font-family:Arial; - padding:0px 0 3px 0; - font-size:140%; - font-weight:bold; - color:#777; -} -.question-img-upvote:hover{background:url(../images/vote-arrow-up-on.png)} -.question-img-downvote:hover{background:url(../images/vote-arrow-down-on.png)} -.question-img-favorite:hover{background:url(../images/vote-favorite-on.png)} -.favorite-number{padding:0px;font-size:100%; font-family:Arial;font-weight:bold;color:#777;} -.vote-notification -{ - z-index: 1; - cursor: pointer; - display: none; - position: absolute; - padding: 15px; + text-align: left; + padding: 5px; + overflow: hidden; +} + +.question-edit { + text-align: left; + overflow: hidden; +} + +.vote-buttons { + float: left; + text-align: center; +} + +.vote-buttons IMG { + cursor: pointer; +} + +.vote-number { + font-family: Arial; + padding: 0px 0 3px 0; + font-size: 140%; + font-weight: bold; + color: #777; +} + +.question-img-upvote:hover { + background: url(../images/vote-arrow-up-on.png) +} + +.question-img-downvote:hover { + background: url(../images/vote-arrow-down-on.png) +} + +.question-img-favorite:hover { + background: url(../images/vote-favorite-on.png) +} + +.favorite-number { + padding: 0px; + font-size: 100%; + font-family: Arial; + font-weight: bold; + color: #777; +} + +.vote-notification { + z-index: 1; + cursor: pointer; + display: none; + position: absolute; + padding: 15px; color: White; - background-color: darkred; - text-align: center; + background-color: darkred; + text-align: center; } -.vote-notification a -{ + +.vote-notification a { color: White; - text-decoration:underline; + text-decoration: underline; } -.offensive-flag a{ - color:#777; - padding:3px; - cursor:pointer; + +.offensive-flag a { + color: #777; + padding: 3px; + cursor: pointer; } -.offensive-flag a:hover{ - background-color:#777; - text-decoration:none; - color:#fff; +.offensive-flag a:hover { + background-color: #777; + text-decoration: none; + color: #fff; } -.linksopt a{ - color:#777; - padding:3px; - cursor:pointer; +.linksopt a { + color: #777; + padding: 3px; + cursor: pointer; } -.linksopt a:hover{ - background-color:#777; - text-decoration:none; - color:#fff; +.linksopt a:hover { + background-color: #777; + text-decoration: none; + color: #fff; } -.action-link a{ - color:#777; - padding:3px; - cursor:pointer; +.action-link a { + color: #777; + padding: 3px; + cursor: pointer; } -.action-link: a hover{ - background-color:#777; - text-decoration:none; - color:#fff; +.action-link: a hover { + background-color: #777; + text-decoration: none; + color: #fff; } -.action-link-separator{ - color:#ccc; + +.action-link-separator { + color: #ccc; } -.wiki-category{ - margin-left:5px; - color:#999; - font-size:90%; + +.wiki-category { + margin-left: 5px; + color: #999; + font-size: 90%; } div.comments { - line-height:150%; - padding:10px 0; + line-height: 150%; + padding: 10px 0; } -div.post-comments{ - clear:both; +div.post-comments { + clear: both; background: url(../images/gray-up-arrow-h18px.png) no-repeat; - width:100%; + width: 100%; padding-left: 12px; - margin:3px 0 10px 0; + margin: 3px 0 10px 0; } form.post-comments textarea { - height:6em; - margin-bottom:4px; + height: 6em; + margin-bottom: 4px; } form.post-comments input { - margin-left:10px; - margin-top:1px; - vertical-align:top; - width:100px; + margin-left: 10px; + margin-top: 1px; + vertical-align: top; + width: 100px; } + span.text-counter { - margin-right:20px; - font-size:11px; + margin-right: 20px; + font-size: 11px; } span.form-error { - color:#990000; - font-weight:normal; - margin-left:5px; + color: #990000; + font-weight: normal; + margin-left: 5px; } + p.form-item { - margin:0px; + margin: 0px; } div.comments-container, div.comments-container-accepted, div.comments-container-owner, div.comments-container-deleted { - padding:0; + padding: 0; } .post-comments a { - color:#888888; - padding:0 3px 2px; + color: #888888; + padding: 0 3px 2px; } a.comments-link, a.comments-link-accepted, a.comments-link-owner, a.comments-link-deleted { - color:black; - font-size:11px; + color: black; + font-size: 11px; background: #eeeeee; - padding:3px; - cursor:pointer; + padding: 3px; + cursor: pointer; } .post-comments a:hover { - background-color:#777777; - color:white; - text-decoration:none; + background-color: #777777; + color: white; + text-decoration: none; } a.comment-user, a.comment-user:hover { - background-color:inherit; - color:blue; - padding:0; + background-color: inherit; + color: blue; + padding: 0; } a.comment-user:hover { - text-decoration:underline; + text-decoration: underline; } + /*回答*/ -#answers {} -.answer{ - padding-top:10px; +#answers { +} + +.answer { + padding-top: 10px; width: 100%; - border-bottom:1px solid #ccccce; + border-bottom: 1px solid #ccccce; } -.answer-body{ - min-height:80px; - font-size:13px; - line-height:20px; + +.answer-body { + min-height: 80px; + font-size: 13px; + line-height: 20px; } -.answer-body IMG{ - max-width:600px; +.answer-body IMG { + max-width: 600px; } -.accepted-answer{ - background-color:#EBFFE6; - border-bottom-color:#9BD59B; +.accepted-answer { + background-color: #EBFFE6; + border-bottom-color: #9BD59B; } -.accepted-answer .comments-link{ - background-color:#CCFFBF; +.accepted-answer .comments-link { + background-color: #CCFFBF; } -.accepted-answer .comments-container{ - background-color:#CCFFBF; +.accepted-answer .comments-container { + background-color: #CCFFBF; } -.answered -{ - background: #CCC; - color: #999; +.answered { + background: #CCC; + color: #999; } -.answered-accepted -{ - background: #CCC; - color: #763333; +.answered-accepted { + background: #CCC; + color: #763333; } -.unanswered -{ - background: #777; - color: white; +.unanswered { + background: #777; + color: white; } -.answered-by-owner -{ - background: #E9E9FF; +.answered-by-owner { + background: #E9E9FF; } -.answered-by-owner .comments-link -{ - background-color:#E6ECFF; +.answered-by-owner .comments-link { + background-color: #E6ECFF; } -.answered-by-owner .comments-container -{ - background-color:#E6ECFF; +.answered-by-owner .comments-container { + background-color: #E6ECFF; } -.answered-accepted strong -{ - color: #E1E818; +.answered-accepted strong { + color: #E1E818; } -.answer-img-accept:hover{background:url(../images/vote-accepted-on.png)} +.answer-img-accept:hover { + background: url(../images/vote-accepted-on.png) +} -.deleted{ - background:#F4E7E7 none repeat scroll 0 0; +.deleted { + background: #F4E7E7 none repeat scroll 0 0; } /*标签列表*/ @@ -658,812 +1342,1118 @@ a.comment-user:hover { .tagsbox {} .tagsbox a {color:#000;line-height:30px;margin-right:10px;font-size:100%;background-color:#F9F7ED;padding:3px;border:1px solid #aaaaaa;} .tagsbox a:hover {text-decoration:none;background-color:#F9F7ED;color:#B02B2C;} */ -.tagsList {margin:0; list-style-type:none;padding:0px;min-height:360px;} -.tagsList li {width:235px; float:left;} -.badge-list{margin:0; list-style-type:none;} +.tagsList { + margin: 0; + list-style-type: none; + padding: 0px; + min-height: 360px; +} + +.tagsList li { + width: 235px; + float: left; +} + +.badge-list { + margin: 0; + list-style-type: none; +} + /*登录*/ -.list-item{margin-left:15px;} -.list-item LI{list-style-type:disc; font-size:13px; line-height:20px; margin-bottom:10px;} +.list-item { + margin-left: 15px; +} + +.list-item LI { + list-style-type: disc; + font-size: 13px; + line-height: 20px; + margin-bottom: 10px; +} + /* openid styles */ -.form-row{line-height:25px;} +.form-row { + line-height: 25px; +} + table.form-as-table { - margin-top:5px; + margin-top: 5px; } + table.form-as-table ul { - list-style-type:none; + list-style-type: none; display: inline; } + table.form-as-table li { display: inline; } + table.form-as-table td { - text-align:right; + text-align: right; } + table.form-as-table th { - text-align:left; - font-weight:normal; + text-align: left; + font-weight: normal; } + /*.form-row li label { display: inline }*/ -.submit-row{ - line-height:30px; - padding-top:10px; +.submit-row { + line-height: 30px; + padding-top: 10px; display: block; clear: both; } -.errors{line-height:20px;color:red;} -.error{ - color:darkred; - margin:0; + +.errors { + line-height: 20px; + color: red; +} + +.error { + color: darkred; + margin: 0; font-size: 10px; } -.error-list li{padding:5px;} -.fieldset{ + +.error-list li { + padding: 5px; +} + +.fieldset { /* border:solid 1px #777;*/ - border: none; - margin-top:10px; - padding:10px; + border: none; + margin-top: 10px; + padding: 10px; } -.openid-input{background:url(../images/openid.gif) no-repeat;padding-left:15px;cursor:pointer;} -.openid-login-input{ - background-position:center left; - background:url(../images/openid.gif) no-repeat 0% 50%; - padding:5px 5px 5px 15px; - cursor:pointer; - font-family:Trebuchet MS; - font-weight:300; - font-size:150%; - width:500px; + +.openid-input { + background: url(../images/openid.gif) no-repeat; + padding-left: 15px; + cursor: pointer; } -.openid-login-submit{ - height:40px; - width:80px; - line-height:40px; - cursor:pointer; - border:1px solid #777; - font-weight:bold; - font-size:120%; +.openid-login-input { + background-position: center left; + background: url(../images/openid.gif) no-repeat 0% 50%; + padding: 5px 5px 5px 15px; + cursor: pointer; + font-family: Trebuchet MS; + font-weight: 300; + font-size: 150%; + width: 500px; +} + +.openid-login-submit { + height: 40px; + width: 80px; + line-height: 40px; + cursor: pointer; + border: 1px solid #777; + font-weight: bold; + font-size: 120%; } -.openid-samples{ +.openid-samples { } -.openid-samples .list, .list li{ - font-family:Trebuchet MS,"segoe ui",Helvetica,"Microsoft YaHei",宋体,Tahoma,Verdana,MingLiu,PMingLiu,Arial,sans-serif; - list-style:none !important; - margin-left:-30px !important; - line-height:20px !important; +.openid-samples .list, .list li { + font-family: Trebuchet MS, "segoe ui", Helvetica, "Microsoft YaHei", 宋 体, Tahoma, Verdana, MingLiu, PMingLiu, Arial, sans-serif; + list-style: none !important; + margin-left: -30px !important; + line-height: 20px !important; } /*表单相关*/ span.form-error { - color:#990000; - font-size:90%; - font-weight:normal; - margin-left:5px; + color: #990000; + font-size: 90%; + font-weight: normal; + margin-left: 5px; +} + +.title-desc { + color: #666666; + font-size: 90%; +} + +/*adjustment for editor preview*/ +#editor { + font-size: 100%; + min-height: 200px; + line-height: 18px; + width: 100%; } -.title-desc{ - color:#666666; - font-size:90%; + +.wmd-preview { + margin-top: 10px; + padding: 6px; + width: 100%; + background-color: #F5F5F5; + min-height: 20px; +} + +.wmd-preview pre { + background-color: #E7F1F8; + +} + +.wmd-preview blockquote { + background-color: #eee; +} + +.wmd-preview IMG { + max-width: 600px; +} + +.preview-toggle { + font-weight: 600; + width: 100%; + color: #aaa; /*letter-spacing:1px;*/ + text-align: left; } -/*adjustment for editor preview*/ -#editor{ - font-size:100%; - min-height:200px; - line-height: 18px; - width:100%; +.preview-toggle span:hover { + cursor: pointer; } -.wmd-preview{ - margin-top:10px; - padding:6px; - width:100%; - background-color:#F5F5F5; - min-height:20px; +.edit-content-html { + border-top: 1px dotted #D8D2A9; + border-bottom: 1px dotted #D8D2A9; + margin: 5px 0 5px 0; } -.wmd-preview pre{ - background-color:#E7F1F8; +/*修订记录*/ + +#revisions { + width: 950px; } -.wmd-preview blockquote -{ - background-color: #eee; +.revision { + margin: 10px 0 10px 0; + width: 100%; + font-size: 13px; } -.wmd-preview IMG{ - max-width:600px; +.revision .header { + background-color: #eee; + padding: 5px; + cursor: pointer; } -.preview-toggle{ - font-weight:600; - width:100%; - color:#aaa; - /*letter-spacing:1px;*/ - text-align:left; + +.revision .author { + background-color: #E9E9FF; } -.preview-toggle span:hover{ - cursor:pointer; +.revision .summary { + padding: 5px 0 10px 0; } -.edit-content-html{ - border-top:1px dotted #D8D2A9; - border-bottom:1px dotted #D8D2A9; - margin:5px 0 5px 0; +.revision .summary span { + background-color: yellow; + padding-left: 3px; + padding-right: 3px; + display: inline; } -/*修订记录*/ +.revision h1 { + font-size: 130%; + font-weight: 600; + padding: 15px 0 15px 0; +} -#revisions{ - width:950px; +.revision-mark { + width: 200px; + text-align: left; + display: inline-block; + font-size: 90%; + overflow: hidden; } -.revision{ - margin:10px 0 10px 0; - width:100%; - font-size:13px; +.revision-number { + font-size: 300%; + font-weight: bold; + font-family: sans-serif; } -.revision .header{ - background-color:#eee; - padding:5px; - cursor:pointer; +.revision .body { + padding-left: 10px; + margin-bottom: 50px; } -.revision .author{ - background-color:#E9E9FF; +.revision .answerbody { + padding: 10px 0 5px 10px; } -.revision .summary{ - padding: 5px 0 10px 0; +/* Revision pages */ +del { + color: #FF5F5F; } -.revision .summary span{ - background-color:yellow; - padding-left:3px; - padding-right:3px; - display:inline; +del .post-tag { + color: #FF5F5F; } -.revision h1{ - font-size:130%; - font-weight:600; - padding:15px 0 15px 0; + +ins { + background-color: #97ff97; } -.revision-mark{ - width:200px; - text-align:left; - display:inline-block; - font-size:90%; - overflow:hidden; +ins .post-tag { + background-color: #97ff97; } -.revision-number{ - font-size:300%; - font-weight:bold; - font-family:sans-serif; +/*用户资料页面*/ +.count { + font-family: Arial; + font-size: 200%; + font-weight: 700; + color: #777 } -.revision .body{ - padding-left:10px; - margin-bottom:50px; +.scoreNumber { + font-family: Arial; + font-size: 35px; + font-weight: 800; + color: #777; + line-height: 40px; /*letter-spacing:0px*/ } -.revision .answerbody{ - padding:10px 0 5px 10px; + +.user-details { + font-size: 13px; } -/* Revision pages */ -del { color: #FF5F5F; } -del .post-tag{ -color: #FF5F5F; +.user-about { + background-color: #EEEEEE; + height: 200px; + line-height: 20px; + overflow: auto; + padding: 10px; + width: 90%; } -ins { background-color: #97ff97;} -ins .post-tag{ -background-color: #97ff97; + +.user-edit-link { + background: url(../images/edit.png) no-repeat; + padding-left: 20px; } -/*用户资料页面*/ -.count {font-family:Arial;font-size:200%;font-weight:700;color:#777} -.scoreNumber{font-family:Arial;font-size:35px;font-weight:800;color:#777;line-height:40px; - /*letter-spacing:0px*/ - } -.user-details{font-size:13px;} -.user-about{background-color:#EEEEEE;height:200px;line-height:20px; overflow:auto;padding:10px;width:90%;} -.user-edit-link {background:url(../images/edit.png) no-repeat; padding-left:20px;} .favorites-count-off { - color:#919191; - float:left; - padding:3px; - margin:10px 0 0 0 ; - text-align:center; + color: #919191; + float: left; + padding: 3px; + margin: 10px 0 0 0; + text-align: center; } .favorites-count { - color:#D4A849; - float:left; - padding:3px; - margin:10px 0 0 0 ; - text-align:center; + color: #D4A849; + float: left; + padding: 3px; + margin: 10px 0 0 0; + text-align: center; } -.favorites-empty{ - width: 32px; height: 45px; float: left; + +.favorites-empty { + width: 32px; + height: 45px; + float: left; } + .question-summary { - border-bottom:1px dotted #999999; - float:left; - overflow:hidden; - padding:11px 0; - width:670px; + border-bottom: 1px dotted #999999; + float: left; + overflow: hidden; + padding: 11px 0; + width: 670px; } -.user-info-table{ -width:950;margin-bottom:10px; +.user-info-table { + width: 950; + margin-bottom: 10px; } .user-stats-table .question-summary { - width:800px; + width: 800px; } .narrow .stats { - background:transparent none repeat scroll 0 0; - float:left; - height:48px; - margin:0 0 0 7px; - padding:0; - width:auto; - font-family:Arial; + background: transparent none repeat scroll 0 0; + float: left; + height: 48px; + margin: 0 0 0 7px; + padding: 0; + width: auto; + font-family: Arial; } .stats div { - font-size:11px; - text-align:center; + font-size: 11px; + text-align: center; } .narrow .votes { - background:#EEEEEE none repeat scroll 0 0; - float:left; - height:42px; - margin:0 3px 0 0; - padding:5px; - width:46px; - text-align:center; + background: #EEEEEE none repeat scroll 0 0; + float: left; + height: 42px; + margin: 0 3px 0 0; + padding: 5px; + width: 46px; + text-align: center; -moz-border-radius: 5px; -khtml-border-radius: 5px; -webkit-border-radius: 5px; } .narrow .summary { - width:600px; - display:inline-block; + width: 600px; + display: inline-block; } .narrow .summary h3 { - padding:0px; - margin:0px; + padding: 0px; + margin: 0px; } .narrow .views { - height:42px; - float:left; - margin:0 7px 0 0; - /*padding:5px 0 5px 4px;*/ - padding: 5px; - width:46px; - text-align:center; + height: 42px; + float: left; + margin: 0 7px 0 0; /*padding:5px 0 5px 4px;*/ + padding: 5px; + width: 46px; + text-align: center; -moz-border-radius: 5px; -khtml-border-radius: 5px; -webkit-border-radius: 5px; - color:#777; + color: #777; } .narrow .status { - float:left; - height:42px; - margin:0 3px 0 0; - padding:5px; - width:46px; - text-align:center; + float: left; + height: 42px; + margin: 0 3px 0 0; + padding: 5px; + width: 46px; + text-align: center; -moz-border-radius: 5px; -khtml-border-radius: 5px; -webkit-border-radius: 5px; } .narrow .vote-count-post { - font-weight:800; - display:block; - margin:0; - font-size: 190%; color:#555; line-height:20px; -} -.narrow .answer-count-post{ - font-weight:800; - display:block; - margin:0; - font-size: 190%; -} -.narrow .views-count-post{ - font-weight:800; - display:block; - margin:0; + font-weight: 800; + display: block; + margin: 0; + font-size: 190%; + color: #555; + line-height: 20px; +} + +.narrow .answer-count-post { + font-weight: 800; + display: block; + margin: 0; + font-size: 190%; +} + +.narrow .views-count-post { + font-weight: 800; + display: block; + margin: 0; font-size: 190%; } + div.started { - color:#999999; - float:right; - line-height:18px; - + color: #999999; + float: right; + line-height: 18px; + } .narrow div.started { - line-height:inherit; - padding-top:4px; - white-space:nowrap; - width:auto; + line-height: inherit; + padding-top: 4px; + white-space: nowrap; + width: auto; } .relativetime { - font-weight:bold; - text-decoration:none; + font-weight: bold; + text-decoration: none; } div.started a { - font-weight:bold; + font-weight: bold; } div.started .reputation-score { - margin-left:1px; + margin-left: 1px; } -.narrow .tags{float:left;} +.narrow .tags { + float: left; +} .answer-summary { - display:block; - clear:both; - padding:3px; + display: block; + clear: both; + padding: 3px; } .answer-votes { - background-color:#EEEEEE; - color:#555555; - float:left; - font-family:Arial; - font-size:110%; - font-weight:bold; - height:15px; - padding:4px 4px 5px; - text-align:center; - text-decoration:none; - width:20px; - margin-right:10px; + background-color: #EEEEEE; + color: #555555; + float: left; + font-family: Arial; + font-size: 110%; + font-weight: bold; + height: 15px; + padding: 4px 4px 5px; + text-align: center; + text-decoration: none; + width: 20px; + margin-right: 10px; } -.vote-count{font-family:Arial; font-size:160%; font-weight:700; color:#777;} -.user-action{ +.vote-count { + font-family: Arial; + font-size: 160%; + font-weight: 700; + color: #777; } -.user-action-1{ - font-weight:bold; - color:#333; + +.user-action { + +} + +.user-action-1 { + font-weight: bold; + color: #333; } -.user-action-2{ - font-weight:bold; - color:#CCC; + +.user-action-2 { + font-weight: bold; + color: #CCC; } -.user-action-3{ - color:#333; + +.user-action-3 { + color: #333; } -.user-action-4{ - color:#333; + +.user-action-4 { + color: #333; } -.user-action-5{ - color:darkred; + +.user-action-5 { + color: darkred; } -.user-action-6{ - color:darkred; + +.user-action-6 { + color: darkred; } -.user-action-7{ - color:#333; + +.user-action-7 { + color: #333; } -.user-action-8{ - padding:3px; - font-weight:bold; - background-color:#CCC; - color:#763333; + +.user-action-8 { + padding: 3px; + font-weight: bold; + background-color: #CCC; + color: #763333; } -.revision-summary{ - background-color:#FFFE9B; - padding:2px; +.revision-summary { + background-color: #FFFE9B; + padding: 2px; } -.question-title-link a{ - font-weight:bold; - color:#0077CC; + +.question-title-link a { + font-weight: bold; + color: #0077CC; } -.answer-title-link a{ - color:#333; + +.answer-title-link a { + color: #333; } .post-type-1 a { - font-weight:bold; - + font-weight: bold; + } + .post-type-3 a { - font-weight:bold; - + font-weight: bold; + } + .post-type-5 a { - font-weight:bold; - } -.post-type-2 a{ - color:#333; + font-weight: bold; } -.post-type-4 a{ - color:#333; + +.post-type-2 a { + color: #333; } -.post-type-6 a{ - color:#333; + +.post-type-4 a { + color: #333; } -.post-type-8 a{ - color:#333; + +.post-type-6 a { + color: #333; } +.post-type-8 a { + color: #333; +} /*读书频道*/ -.bookInfo {float:left; width:940px;padding:5px;} -.bookCover {float:left; width:200px;} -.bookCover img{border:1px solid #ccc;max-width:200px;} -.bookSummary {float:left; font-size:13px;} -.blogRss {float:right;margin:0 10px 0 0;width:460px;height:240px;background-color:#EEE; padding:5px;} -.bookQuestions {margin-bottom:10px;} -.bookFeed {float:right;} -.bookAsk{ - /*letter-spacing:1px; */ - float:right;margin:-30px 10px 0 0; padding:3px 5px 3px 5px;} -.bookAsk a {font-size:15px; color:#FFF; font-weight:bold; text-decoration:none;background-color:#EC7000;padding:3px 6px 3px 6px; } -.bookAsk a:hover {text-decoration:underline;} +.bookInfo { + float: left; + width: 940px; + padding: 5px; +} + +.bookCover { + float: left; + width: 200px; +} + +.bookCover img { + border: 1px solid #ccc; + max-width: 200px; +} + +.bookSummary { + float: left; + font-size: 13px; +} + +.blogRss { + float: right; + margin: 0 10px 0 0; + width: 460px; + height: 240px; + background-color: #EEE; + padding: 5px; +} + +.bookQuestions { + margin-bottom: 10px; +} + +.bookFeed { + float: right; +} + +.bookAsk { +/*letter-spacing:1px; */ + float: right; + margin: -30px 10px 0 0; + padding: 3px 5px 3px 5px; +} + +.bookAsk a { + font-size: 15px; + color: #FFF; + font-weight: bold; + text-decoration: none; + background-color: #EC7000; + padding: 3px 6px 3px 6px; +} +.bookAsk a:hover { + text-decoration: underline; +} /*其他全局样式*/ -.hilite { background-color: #ff0; } -.hilite1 { background-color: #ff0; } -.hilite2 { background-color: #f0f; } -.hilite3 { background-color: #0ff; } -.userStatus {margin-left:12px; color:#FFF; float:right;} -.userStatus a {color:#FFF;} -.gold, .badge1 {color:#FFCC00;} -.silver, .badge2 {color:#CCCCCC;} -.bronze, .badge3 {color:#CC9933;} -.score {font-weight:800; color:#333;} -.footerLinks {color:#EEE; font-size:13px; - /* letter-spacing:1px;*/ - } -.footerLinks a {color:#FFF; font-size:13px;} -.subSearch {margin-bottom:12px; padding:4px;} -a.comment {background:#EEE; color:#993300; padding:4px;} -a.permLink {padding:2px;} -a.offensive {color:#999;} -ul.bulleta li {background:url(../images/bullet_green.gif) no-repeat 0px 2px; padding-left:16px; margin-bottom:4px;} -.user {padding:5px; line-height:140%; width:170px;} -.user ul {margin:0; list-style-type:none;} -.user .thumb{clear:both;float:left; margin-right:4px; display:inline;} -.yellowbg{background:yellow;} - -.message{ - padding:5px; - margin:10px 0 10px 0; - background-color:#eee; +.hilite { + background-color: #ff0; +} + +.hilite1 { + background-color: #ff0; +} + +.hilite2 { + background-color: #f0f; +} + +.hilite3 { + background-color: #0ff; +} + +.userStatus { + margin-left: 12px; + color: #FFF; + float: right; +} + +.userStatus a { + color: #FFF; +} + +.gold, .badge1 { + color: #FFCC00; +} + +.silver, .badge2 { + color: #CCCCCC; +} + +.bronze, .badge3 { + color: #CC9933; +} + +.score { + font-weight: 800; + color: #333; +} + +.footerLinks { + color: #EEE; + font-size: 13px; /* letter-spacing:1px;*/ +} + +.footerLinks a { + color: #FFF; + font-size: 13px; +} + +.subSearch { + margin-bottom: 12px; + padding: 4px; +} + +a.comment { + background: #EEE; + color: #993300; + padding: 4px; +} + +a.permLink { + padding: 2px; +} + +a.offensive { + color: #999; +} + +ul.bulleta li { + background: url(../images/bullet_green.gif) no-repeat 0px 2px; + padding-left: 16px; + margin-bottom: 4px; +} + +.user { + padding: 5px; + line-height: 140%; + width: 170px; +} + +.user ul { + margin: 0; + list-style-type: none; +} + +.user .thumb { + clear: both; + float: left; + margin-right: 4px; + display: inline; +} + +.yellowbg { + background: yellow; +} + +.message { + padding: 5px; + margin: 10px 0 10px 0; + background-color: #eee; border: 1px solid #aaaaaa; } + .message h1 { - padding-top:0px; - font-size:15px; + padding-top: 0px; + font-size: 15px; } + .message p { - margin-bottom:0px; + margin-bottom: 0px; } + p.space-above { - margin-top:10px; -} - -.warning{color:red;} -.darkred{color:darkred;} -.submit{ - cursor:pointer; - /*letter-spacing:1px;*/ - background-color:#D4D0C8; - height:40px; - border:1px solid #777777; -/* width:100px; */ - font-weight:bold; - padding-bottom:4px; - font-size:120%;} -.submit:hover{text-decoration:underline;} -.ask-body{padding-right:10px;} -.thousand{color:orange;} - -.notify -{ - position: fixed; - top: 0px; - left: 0px; - width: 100%; - z-index: 100; - padding: 0; - text-align: center; - font-weight: Bold; - color: #444; - background-color: #F4A83D; + margin-top: 10px; +} + +.warning { + color: red; +} + +.darkred { + color: darkred; +} + +.submit { + cursor: pointer; /*letter-spacing:1px;*/ + background-color: #D4D0C8; + height: 40px; + border: 1px solid #777777; /* width:100px; */ + font-weight: bold; + padding-bottom: 4px; + font-size: 120%; +} + +.submit:hover { + text-decoration: underline; +} + +.ask-body { + padding-right: 10px; +} + +.thousand { + color: orange; +} + +.notify { + position: fixed; + top: 0px; + left: 0px; + width: 100%; + z-index: 100; + padding: 0; + text-align: center; + font-weight: Bold; + color: #444; + background-color: #F4A83D; } .notify p { - margin-top:5px; - margin-bottom:5px; - font-size:16px; -} - -#close-notify -{ - position:absolute; - right:5px; - top:5px; - padding:0 3px 0 3px; - color: #735005; - text-decoration: none; - font-size:14px; - line-height:18px; - background-color: #FAD163; - border: 2px #735005 solid; - cursor:pointer; + margin-top: 5px; + margin-bottom: 5px; + font-size: 16px; +} + +#close-notify { + position: absolute; + right: 5px; + top: 5px; + padding: 0 3px 0 3px; + color: #735005; + text-decoration: none; + font-size: 14px; + line-height: 18px; + background-color: #FAD163; + border: 2px #735005 solid; + cursor: pointer; } + #close-notify:hover { - text-decoration:none; + text-decoration: none; } .big { - font-size:15px; + font-size: 15px; } + .bigger { - font-size:14px; + font-size: 14px; } + .strong { - font-weight:bold; + font-weight: bold; } -.orange -{ - color:#d64000; - font-weight:bold; + +.orange { + color: #d64000; + font-weight: bold; } + .grey { - color:#808080; + color: #808080; } + .about div { - padding:10px 5px 10px 5px; - border-top:1px dashed #aaaaaa; + padding: 10px 5px 10px 5px; + border-top: 1px dashed #aaaaaa; } + .about div.first { - padding-top:0; - border-top:none; + padding-top: 0; + border-top: none; } + .about p { - margin-bottom:10px; + margin-bottom: 10px; +} + +.about a { + color: #d64000; + text-decoration: underline; } -.about a {color:#d64000;text-decoration:underline;} -.about h3{ - line-height:30px; - font-size:15px; - font-weight:700; + +.about h3 { + line-height: 30px; + font-size: 15px; + font-weight: 700; padding-top: 0px; } + .highlight { - background-color:#FFF8C6; + background-color: #FFF8C6; } + .nomargin { - margin:0; + margin: 0; } + .margin-bottom { margin-bottom: 10px; } + .margin-top { margin-top: 10px; } + .inline-block { - display:inline-block; + display: inline-block; } + .action-status { - margin:0; - border:none; - text-align:center; - line-height:10px; - font-size:12px; - padding:0; + margin: 0; + border: none; + text-align: center; + line-height: 10px; + font-size: 12px; + padding: 0; } + .action-status span { - padding:3px 5px 3px 5px; - background-color:#fff380;/* nice yellow */ - font-weight:normal; + padding: 3px 5px 3px 5px; + background-color: #fff380; /* nice yellow */ + font-weight: normal; -moz-border-radius: 5px; -khtml-border-radius: 5px; -webkit-border-radius: 5px; } + .tight { - margin:0; - padding:0; + margin: 0; + padding: 0; } .list-table td { - vertical-align:top; + vertical-align: top; } p.comment { border-top: 1px dotted #ccccce; - margin:0; - font-size:11px; + margin: 0; + font-size: 11px; color: #444444; - padding:5px 0 5px 0; + padding: 5px 0 5px 0; } .delete-icon { - vertical-align:middle; - padding-left:3px; + vertical-align: middle; + padding-left: 3px; } + /* these need to go */ table.form-as-table .errorlist { display: block; - margin:0; - padding:0 0 0 5px; - text-align:left; - font-size:10px; - color:darkred; + margin: 0; + padding: 0 0 0 5px; + text-align: left; + font-size: 10px; + color: darkred; } + table.form-as-table input { display: inline; margin-left: 4px; } + table.form-as-table th { - vertical-align:bottom; - padding-bottom:4px; + vertical-align: bottom; + padding-bottom: 4px; } + .form-row-vertical { margin-top: 8px; display: block; } + .form-row-vertical label { - margin-bottom:3px; - display:block; + margin-bottom: 3px; + display: block; } + /* above stuff needs to go */ .text-align-right { text-align: center; } + ul.form-horizontal-rows { - list-style:none; - margin:0; + list-style: none; + margin: 0; } + ul.form-horizontal-rows li { - position:relative; - height:40px; + position: relative; + height: 40px; } + ul.form-horizontal-rows label { - display:inline-block; + display: inline-block; } + ul.form-horizontal-rows ul.errorlist { - list-style:none; - color:darkred; - font-size:10px; - line-height:10px; - position:absolute; - top:2px; - left:180px; - text-align:left; - margin:0; + list-style: none; + color: darkred; + font-size: 10px; + line-height: 10px; + position: absolute; + top: 2px; + left: 180px; + text-align: left; + margin: 0; } + ul.form-horizontal-rows ul.errorlist li { - height:10px; + height: 10px; } + ul.form-horizontal-rows label { - position:absolute; - left:0px; - bottom:6px; - margin:0px; + position: absolute; + left: 0px; + bottom: 6px; + margin: 0px; line-height: 12px; font-size: 12px; } + ul.form-horizontal-rows li input { - position:absolute; - bottom:0px; - left:180px; - margin:0px; + position: absolute; + bottom: 0px; + left: 180px; + margin: 0px; } + #emailpw-form li input { - left:170px; + left: 170px; } + #emailpw-form ul.errorlist { - left:170px; + left: 170px; } + #changepw-form li input { - left:150px; + left: 150px; } + #changepw-form ul.errorlist { - left:150px; + left: 150px; } + .narrow .summary { float: left; } + .narrow .summary .question-title { font-weight: bold; font-size: 120%; } + .user-profile-tool-links { - padding-bottom:10px; + padding-bottom: 10px; font-weight: bold; } + .post-controls { - float:left; - font-size:11px; - line-height:12px; - min-width:200px; - margin-bottom:5px; + float: left; + font-size: 11px; + line-height: 12px; + min-width: 200px; + margin-bottom: 5px; } + #question-controls .tags { - margin:0 0 3px 0; + margin: 0 0 3px 0; } + .post-update-info-container { float: right; - min-width:190px; + min-width: 190px; } + .post-update-info { - display:inline-block; - float:right; - width:190px; - margin-bottom:5px; + display: inline-block; + float: right; + width: 190px; + margin-bottom: 5px; } + .post-update-info p { - font-size:11px; - line-height:15px; - margin:0 0 4px 0; - padding:0; + font-size: 11px; + line-height: 15px; + margin: 0 0 4px 0; + padding: 0; } + .post-update-info img { float: left; width: 32px; margin: 4px 8px 0 0; } + .comments-container { - clear:both; + clear: both; } + .admin { - background-color:#fff380;/* nice yellow */ + background-color: #fff380; /* nice yellow */ border: 1px solid darkred; padding: 0 5px 0 5px; } + .admin p { margin-bottom: 3px; } + .admin #action_status { - text-align:center; - font-weight:bold; + text-align: center; + font-weight: bold; } + #tagSelector { padding-bottom: 2px; } + #hideIgnoredTagsControl { margin: 5px 0 0 0; } + #hideIgnoredTagsCb { margin: 0 2px 0 1px; } + #recaptcha_widget_div { - width:318px; - float:left; - clear:both; + width: 318px; + float: left; + clear: both; } + p.signup_p { margin: 20px 0px 0px 0px; } + .simple-subscribe-options ul { - list-style:none; - list-style-position:outside; - margin:0; + list-style: none; + list-style-position: outside; + margin: 0; } diff --git a/forum/skins/default/templates/index.html b/forum/skins/default/templates/index.html old mode 100644 new mode 100755 index 7fa189ae..5bbb192b --- a/forum/skins/default/templates/index.html +++ b/forum/skins/default/templates/index.html @@ -1,164 +1,124 @@ -{% extends "base.html" %} - -{% load i18n %} -{% load extra_tags %} -{% load humanize %} -{% load extra_filters %} -{% load smart_if %} -{% block title %}{% spaceless %}{% trans "Home" %}{% endspaceless %}{% endblock %} -{% block meta %} - {% endblock %} -{% block forejs %} - - - -{% endblock %} -{% block content %} -
-
{% trans "Questions" %}
- -
- -
- {% for question in questions %} -
-

- {{ question.get_question_title }} -

-
- - - - - - - - - - - -
{{ question.answer_count|intcomma }} {{ question.score|intcomma }} {{ question.view_count|cnprog_intword|safe }}
{% trans "answers" %}{% trans "votes" %}{% trans "views" %}
-
- -
- {{ question.summary }}... -
- - {% ifequal tab_id 'active'%} - {% if question.wiki and settings.WIKI_ON %} - {% trans "community wiki" %} - {% diff_date question.added_at %} - {% else %} -
- {% comment %}{% gravatar question.last_activity_by 24 %}{% endcomment %} - {{ question.last_activity_by }} - {% get_score_badge question.last_activity_by %} - {% diff_date question.last_activity_at %} -
- {% endif %} - {% else %} - {% if question.wiki and settings.WIKI_ON %} - {% trans "community wiki" %} - {% diff_date question.added_at %} - {% else %} -
- {% comment %}{% gravatar question.author 24 %}{% endcomment %} - {% if question.last_activity_at != question.added_at %} - {% if question.author.id != question.last_activity_by.id %} - {% trans "Posted:" %} - {{ question.author }} - {% get_score_badge question.author %} - / {% trans "Updated:" %} - {{ question.last_activity_by }} - {% get_score_badge question.last_activity_by %} - {% diff_date question.last_activity_at %} - {% else %} - {% trans "Updated:" %} - {{ question.last_activity_by }} - {% get_score_badge question.last_activity_by %} - {% diff_date question.last_activity_at %} - {% endif %} - {% else %} - {% trans "Posted:" %} - {{ question.author }} - {% get_score_badge question.author %} - {% diff_date question.added_at %} - {% endif %} -
- {% endif %} - {% endifequal %} - -
- {% for tag in question.tagname_list %} - - {% endfor %} -
-
- {% endfor %} -
-{% endblock %} - -{% block sidebar %} -{% if not request.user.is_authenticated %} -
-

{% trans "welcome to website" %}

-
- {{ settings.APP_INTRO|safe }} - - -
-
-{% else %} -{% include "tag_selector.html" %} -{% endif %} -
-

{% trans "Recent tags" %}

-
-
- {% for tag in tags %} - - {% endfor %} -
- -
-
-{% if awards %} -
-

{% trans "Recent awards" %}

-
- - -
-
-{% endif %} -
-{% trans "subscribe to the questions feed" %} -
-{% endblock %} -{% block tail %} -
-{% trans "Still looking for more? See" %} {% trans "complete list of questions" %} {% trans "or" %} {% trans "popular tags" %}{% trans "." %} {% trans "Please help us answer" %} {% trans "list of unanswered questions" %}{% trans "." %} -
-{% endblock %} - +{% extends "base.html" %} + +{% load i18n %} +{% load extra_tags %} +{% load humanize %} +{% load extra_filters %} +{% load smart_if %} +{% block title %}{% spaceless %}{% trans "Home" %}{% endspaceless %}{% endblock %} +{% block meta %} + {% endblock %} +{% block forejs %} + + + +{% endblock %} +{% block content %} +
+
{% trans "Questions" %}
+ +
+ +
+ {% for question in questions.object_list %} +
+
+
+
{{question.score|intcomma}}
+
{% trans "votes" %}
+
+
+
{{question.answer_count|intcomma}}
+
{% trans "answers" %}
+
+
+
{{question.view_count|cnprog_intword|safe}}
+
{% trans "views" %}
+
+
+ +

{{question.title}}

+ +
+ {% diff_date question.last_activity_at %} + {% if question.last_activity_by %} + {{ question.last_activity_by }} {% get_score_badge question.last_activity_by %} + {% endif %} +
+ +
+ {% for tag in question.tagname_list %} + + {% endfor %} +
+
+ {% endfor %} +
+{% endblock %} + +{% block sidebar %} +{% if not request.user.is_authenticated %} +
+

{% trans "welcome to website" %}

+
+ {{ settings.APP_INTRO|safe }} + + +
+
+{% else %} +{% include "tag_selector.html" %} +{% endif %} +
+

{% trans "Recent tags" %}

+
+
+ {% for tag in tags %} + + {% endfor %} +
+ +
+
+{% if awards %} +
+

{% trans "Recent awards" %}

+
+ + +
+
+{% endif %} +
+{% trans "subscribe to the questions feed" %} +
+{% endblock %} +{% block tail %} +
{% cnprog_paginator context %}
+
{% cnprog_pagesize context %}
+ +{% endblock %} + \ No newline at end of file diff --git a/forum/skins/default/templates/index_.html b/forum/skins/default/templates/index_.html new file mode 100755 index 00000000..5e4cf533 --- /dev/null +++ b/forum/skins/default/templates/index_.html @@ -0,0 +1,124 @@ +{% extends "base.html" %} + +{% load i18n %} +{% load extra_tags %} +{% load humanize %} +{% load extra_filters %} +{% load smart_if %} +{% block title %}{% spaceless %}{% trans "Home" %}{% endspaceless %}{% endblock %} +{% block meta %} + {% endblock %} +{% block forejs %} + + + +{% endblock %} +{% block content %} +
+
{% trans "Questions" %}
+ +
+ +
+ {% for question in questions.object_list %} +
+
+
+
{{question.score|intcomma}}
+
{% trans "votes" %}
+
+
+
{{question.answer_count|intcomma}}
+
{% trans "answers" %}
+
+
+
{{question.view_count|cnprog_intword|safe}}
+
{% trans "views" %}
+
+
+ +

{{question.title}}

+ +
+ {% diff_date question.last_activity_at %} + {% if question.last_activity_by %} + {{ question.last_activity_by }} {% get_score_badge question.last_activity_by %} + {% endif %} +
+ +
+ {% for tag in question.tagname_list %} + + {% endfor %} +
+
+ {% endfor %} +
+{% endblock %} + +{% block sidebar %} +{% if not request.user.is_authenticated %} +
+

{% trans "welcome to website" %}

+
+ {{ settings.APP_INTRO|safe }} + + +
+
+{% else %} +{% include "tag_selector.html" %} +{% endif %} +
+

{% trans "Recent tags" %}

+
+
+ {% for tag in tags %} + + {% endfor %} +
+ +
+
+{% if awards %} +
+

{% trans "Recent awards" %}

+
+ + +
+
+{% endif %} +
+{% trans "subscribe to the questions feed" %} +
+{% endblock %} +{% block tail %} +
{% cnprog_paginator context %}
+
{% cnprog_pagesize context %}
+ +{% endblock %} + diff --git a/forum/urls.py b/forum/urls.py index 219364cb..fd9ebdc1 100644 --- a/forum/urls.py +++ b/forum/urls.py @@ -84,12 +84,19 @@ urlpatterns = patterns('', url(r'^%s(.*)' % _('nimda/'), admin.site.root, name='osqa_admin'), url(r'^feeds/(?P.*)/$', 'django.contrib.syndication.views.feed', {'feed_dict': feeds}, name='feeds'), url(r'^%s$' % _('upload/'), app.writers.upload, name='upload'), - #url(r'^%s$' % _('books/'), app.books.books, name='books'), - #url(r'^%s%s(?P[^/]+)/$' % (_('books/'), _('ask/')), app.books.ask_book, name='ask_book'), - #url(r'^%s(?P[^/]+)/$' % _('books/'), app.books.book, name='book'), url(r'^%s$' % _('search/'), app.readers.search, name='search'), url(r'^%s$' % _('feedback/'), app.meta.feedback, name='feedback'), (r'^%sfb/' % _('account/'), include('fbconnect.urls')), (r'^%s' % _('account/'), include('django_authopenid.urls')), (r'^i18n/', include('django.conf.urls.i18n')), ) + +from forum.modules import get_modules_script + +module_patterns = get_modules_script('urls') + +for pattern_file in module_patterns: + pattern = getattr(pattern_file, 'urlpatterns', None) + if pattern: + urlpatterns += pattern + diff --git a/forum/views/__init__.py b/forum/views/__init__.py index faea1179..291fee2a 100644 --- a/forum/views/__init__.py +++ b/forum/views/__init__.py @@ -3,4 +3,3 @@ import writers import commands import users import meta -#import books diff --git a/forum/views/books.py b/forum/views/books.py deleted file mode 100644 index bb2ada6a..00000000 --- a/forum/views/books.py +++ /dev/null @@ -1,140 +0,0 @@ -from django.contrib.auth.decorators import login_required -from django.core.urlresolvers import reverse -from django.shortcuts import render_to_response -from forum.models import BookAuthorInfo, BookAuthorRss, Book -from forum.models import Question, QuestionRevision -from django.core.urlresolvers import reverse -from django.http import HttpResponseRedirect - -def books(request): - """this view seems to redirect to a default book - maybe it should instead show some popular titles? - """ - return HttpResponseRedirect(reverse('books') + 'mysql-zhaoyang') - -def book(request, short_name, unanswered=False): - """ - 1. questions list - 2. book info - 3. author info and blog rss items - """ - """ - List of Questions, Tagged questions, and Unanswered questions. - """ - books = Book.objects.extra(where=['short_name = %s'], params=[short_name]) - match_count = len(books) - if match_count == 0: - raise Http404 - else: - # the book info - book = books[0] - # get author info - author_info = BookAuthorInfo.objects.get(book=book) - # get author rss info - author_rss = BookAuthorRss.objects.filter(book=book) - - # get pagesize from session, if failed then get default value - user_page_size = request.session.get("pagesize", QUESTIONS_PAGE_SIZE) - # set pagesize equal to logon user specified value in database - if request.user.is_authenticated() and request.user.questions_per_page > 0: - user_page_size = request.user.questions_per_page - - try: - page = int(request.GET.get('page', '1')) - except ValueError: - page = 1 - - view_id = request.GET.get('sort', None) - view_dic = {"latest":"-added_at", "active":"-last_activity_at", "hottest":"-answer_count", "mostvoted":"-score" } - try: - orderby = view_dic[view_id] - except KeyError: - view_id = "latest" - orderby = "-added_at" - - # check if request is from tagged questions - if unanswered: - # check if request is from unanswered questions - # Article.objects.filter(publications__id__exact=1) - objects = Question.objects.filter(book__id__exact=book.id, deleted=False, answer_count=0).order_by(orderby) - else: - objects = Question.objects.filter(book__id__exact=book.id, deleted=False).order_by(orderby) - - # RISK - inner join queries - objects = objects.select_related(); - objects_list = Paginator(objects, user_page_size) - questions = objects_list.page(page) - - return render_to_response('book.html', { - "book" : book, - "author_info" : author_info, - "author_rss" : author_rss, - "questions" : questions, - "context" : { - 'is_paginated' : True, - 'pages': objects_list.num_pages, - 'page': page, - 'has_previous': questions.has_previous(), - 'has_next': questions.has_next(), - 'previous': questions.previous_page_number(), - 'next': questions.next_page_number(), - 'base_url' : request.path + '?sort=%s&' % view_id, - 'pagesize' : user_page_size - } - }, context_instance=RequestContext(request)) - -@login_required -def ask_book(request, short_name): - if request.method == "POST": - form = AskForm(request.POST) - if form.is_valid(): - added_at = datetime.datetime.now() - html = sanitize_html(markdowner.convert(form.cleaned_data['text'])) - question = Question( - title = strip_tags(form.cleaned_data['title']), - author = request.user, - added_at = added_at, - last_activity_at = added_at, - last_activity_by = request.user, - wiki = form.cleaned_data['wiki'], - tagnames = form.cleaned_data['tags'].strip(), - html = html, - summary = strip_tags(html)[:120] - ) - if question.wiki: - question.last_edited_by = question.author - question.last_edited_at = added_at - question.wikified_at = added_at - - question.save() - - # create the first revision - QuestionRevision.objects.create( - question = question, - revision = 1, - title = question.title, - author = request.user, - revised_at = added_at, - tagnames = question.tagnames, - summary = CONST['default_version'], - text = form.cleaned_data['text'] - ) - - books = Book.objects.extra(where=['short_name = %s'], params=[short_name]) - match_count = len(books) - if match_count == 1: - # the book info - book = books[0] - book.questions.add(question) - - return HttpResponseRedirect(question.get_absolute_url()) - else: - form = AskForm() - - tags = _get_tags_cache_json() - return render_to_response('ask.html', { - 'form' : form, - 'tags' : tags, - 'email_validation_faq_url': reverse('faq') + '#validate', - }, context_instance=RequestContext(request)) - diff --git a/forum/views/meta.py b/forum/views/meta.py index 164c056a..b4c7a37f 100644 --- a/forum/views/meta.py +++ b/forum/views/meta.py @@ -61,8 +61,8 @@ def badges(request):#user status/reputation system badges = Badge.objects.all().order_by('type') my_badges = [] if request.user.is_authenticated(): - my_badges = Award.objects.filter(user=request.user) - my_badges.query.group_by = ['badge_id'] + my_badges = Award.objects.filter(user=request.user).values('badge_id') + #my_badges.query.group_by = ['badge_id'] return render_to_response('badges.html', { 'badges' : badges, diff --git a/forum/views/readers.py b/forum/views/readers.py index 72378218..6b0da476 100644 --- a/forum/views/readers.py +++ b/forum/views/readers.py @@ -28,13 +28,13 @@ from forum.utils.forms import get_next_url # used in index page #refactor - move these numbers somewhere? -INDEX_PAGE_SIZE = 20 +INDEX_PAGE_SIZE = 30 INDEX_AWARD_SIZE = 15 -INDEX_TAGS_SIZE = 100 +INDEX_TAGS_SIZE = 25 # used in tags list DEFAULT_PAGE_SIZE = 60 # used in questions -QUESTIONS_PAGE_SIZE = 10 +QUESTIONS_PAGE_SIZE = 30 # used in answers ANSWERS_PAGE_SIZE = 10 @@ -87,10 +87,19 @@ def index(request):#generates front page - shows listing of questions sorted in } view_id, orderby = _get_and_remember_questions_sort_method(request, view_dic, 'latest') - page_size = request.session.get('pagesize', QUESTIONS_PAGE_SIZE) - questions = Question.objects.exclude(deleted=True).order_by(orderby)[:page_size] + pagesize = request.session.get("pagesize",QUESTIONS_PAGE_SIZE) + try: + page = int(request.GET.get('page', '1')) + except ValueError: + page = 1 + + qs = Question.objects.exclude(deleted=True).order_by(orderby) + + objects_list = Paginator(qs, pagesize) + questions = objects_list.page(page) + # RISK - inner join queries - questions = questions.select_related() + #questions = questions.select_related() tags = Tag.objects.get_valid_tags(INDEX_TAGS_SIZE) awards = Award.objects.get_recent_awards() @@ -111,7 +120,17 @@ def index(request):#generates front page - shows listing of questions sorted in "tab_id" : view_id, "tags" : tags, "awards" : awards[:INDEX_AWARD_SIZE], - }, context_instance=RequestContext(request)) + "context" : { + 'is_paginated' : True, + 'pages': objects_list.num_pages, + 'page': page, + 'has_previous': questions.has_previous(), + 'has_next': questions.has_next(), + 'previous': questions.previous_page_number(), + 'next': questions.next_page_number(), + 'base_url' : request.path + '?sort=%s&' % view_id, + 'pagesize' : pagesize + }}, context_instance=RequestContext(request)) def unanswered(request):#generates listing of unanswered questions return questions(request, unanswered=True) @@ -126,7 +145,7 @@ def questions(request, tagname=None, unanswered=False):#a view generating listin # Set flag to False by default. If it is equal to True, then need to be saved. pagesize_changed = False # get pagesize from session, if failed then get default value - pagesize = request.session.get("pagesize",10) + pagesize = request.session.get("pagesize",QUESTIONS_PAGE_SIZE) try: page = int(request.GET.get('page', '1')) except ValueError: @@ -287,25 +306,16 @@ def search(request): #generates listing of questions matching a search query - i view_id = "latest" orderby = "-added_at" - if settings.USE_PG_FTS: - objects = Question.objects.filter(deleted=False).extra( - select={ - 'ranking': "ts_rank_cd(tsv, plainto_tsquery(%s), 32)", - }, - where=["tsv @@ plainto_tsquery(%s)"], - params=[keywords], - select_params=[keywords] - ).order_by('-ranking') - - elif settings.USE_SPHINX_SEARCH == True: - #search index is now free of delete questions and answers - #so there is not "antideleted" filtering here - objects = Question.search.query(keywords) - #no related selection either because we're relying on full text search here - else: + def question_search(keywords, orderby): objects = Question.objects.filter(deleted=False).extra(where=['title like %s'], params=['%' + keywords + '%']).order_by(orderby) # RISK - inner join queries - objects = objects.select_related(); + return objects.select_related(); + + from forum.modules import get_handler + + question_search = get_handler('question_search', question_search) + + objects = question_search(keywords, orderby) objects_list = Paginator(objects, pagesize) questions = objects_list.page(page) diff --git a/forum/views/users.py b/forum/views/users.py index 517bb170..04ffb690 100644 --- a/forum/views/users.py +++ b/forum/views/users.py @@ -1,6 +1,7 @@ from django.contrib.auth.decorators import login_required from django.contrib.auth.models import User from django.core.paginator import Paginator, EmptyPage, InvalidPage +from django.template.defaultfilters import slugify from django.contrib.contenttypes.models import ContentType from django.core.urlresolvers import reverse from django.shortcuts import render_to_response, get_object_or_404 diff --git a/forum_modules/__init__.py b/forum_modules/__init__.py new file mode 100755 index 00000000..e69de29b diff --git a/forum_modules/books/__init__.py b/forum_modules/books/__init__.py new file mode 100755 index 00000000..bdd27b2b --- /dev/null +++ b/forum_modules/books/__init__.py @@ -0,0 +1,3 @@ +NAME = 'Osqa Books' +DESCRIPTION = "Allows discussion around books." +CAN_ENABLE = True diff --git a/forum_modules/books/models.py b/forum_modules/books/models.py new file mode 100755 index 00000000..ecde34b3 --- /dev/null +++ b/forum_modules/books/models.py @@ -0,0 +1,63 @@ +from django.db import models +from django.contrib.auth.models import User +from forum.models import Question +from django.core.urlresolvers import reverse +from django.utils.http import urlquote as django_urlquote +from django.template.defaultfilters import slugify + +class Book(models.Model): + """ + Model for book info + """ + user = models.ForeignKey(User) + title = models.CharField(max_length=255) + short_name = models.CharField(max_length=255) + author = models.CharField(max_length=255) + price = models.DecimalField(max_digits=6, decimal_places=2) + pages = models.SmallIntegerField() + published_at = models.DateTimeField() + publication = models.CharField(max_length=255) + cover_img = models.CharField(max_length=255) + tagnames = models.CharField(max_length=125) + added_at = models.DateTimeField() + last_edited_at = models.DateTimeField() + questions = models.ManyToManyField(Question, related_name='book', db_table='book_question') + + def get_absolute_url(self): + return reverse('book', args=[django_urlquote(slugify(self.short_name))]) + + def __unicode__(self): + return self.title + + class Meta: + app_label = 'forum' + db_table = u'book' + +class BookAuthorInfo(models.Model): + """ + Model for book author info + """ + user = models.ForeignKey(User) + book = models.ForeignKey(Book) + blog_url = models.CharField(max_length=255) + added_at = models.DateTimeField() + last_edited_at = models.DateTimeField() + + class Meta: + app_label = 'forum' + db_table = u'book_author_info' + +class BookAuthorRss(models.Model): + """ + Model for book author blog rss + """ + user = models.ForeignKey(User) + book = models.ForeignKey(Book) + title = models.CharField(max_length=255) + url = models.CharField(max_length=255) + rss_created_at = models.DateTimeField() + added_at = models.DateTimeField() + + class Meta: + app_label = 'forum' + db_table = u'book_author_rss' \ No newline at end of file diff --git a/forum_modules/books/urls.py b/forum_modules/books/urls.py new file mode 100755 index 00000000..0e0432ba --- /dev/null +++ b/forum_modules/books/urls.py @@ -0,0 +1,10 @@ +from django.conf.urls.defaults import * +from django.utils.translation import ugettext as _ + +import views as app + +urlpatterns = patterns('', + url(r'^%s$' % _('books/'), app.books, name='books'), + url(r'^%s%s(?P[^/]+)/$' % (_('books/'), _('ask/')), app.ask_book, name='ask_book'), + url(r'^%s(?P[^/]+)/$' % _('books/'), app.book, name='book'), +) \ No newline at end of file diff --git a/forum_modules/books/views.py b/forum_modules/books/views.py new file mode 100755 index 00000000..31c82971 --- /dev/null +++ b/forum_modules/books/views.py @@ -0,0 +1,142 @@ +from django.shortcuts import render_to_response, get_object_or_404 +from django.http import HttpResponseRedirect, HttpResponse, HttpResponseForbidden, Http404 +from django.template import RequestContext +from django.contrib.auth.decorators import login_required +from django.core.urlresolvers import reverse +from django.utils.html import * + +from models import * + +from forum.forms import AskForm +from forum.views.readers import _get_tags_cache_json +from forum.models import * +from forum.utils.html import sanitize_html + +def books(request): + return HttpResponseRedirect(reverse('books') + '/mysql-zhaoyang') + +def book(request, short_name, unanswered=False): + """ + 1. questions list + 2. book info + 3. author info and blog rss items + """ + """ + List of Questions, Tagged questions, and Unanswered questions. + """ + books = Book.objects.extra(where=['short_name = %s'], params=[short_name]) + match_count = len(books) + if match_count == 0: + raise Http404 + else: + # the book info + book = books[0] + # get author info + author_info = BookAuthorInfo.objects.get(book=book) + # get author rss info + author_rss = BookAuthorRss.objects.filter(book=book) + + # get pagesize from session, if failed then get default value + user_page_size = request.session.get("pagesize", QUESTIONS_PAGE_SIZE) + # set pagesize equal to logon user specified value in database + if request.user.is_authenticated() and request.user.questions_per_page > 0: + user_page_size = request.user.questions_per_page + + try: + page = int(request.GET.get('page', '1')) + except ValueError: + page = 1 + + view_id = request.GET.get('sort', None) + view_dic = {"latest":"-added_at", "active":"-last_activity_at", "hottest":"-answer_count", "mostvoted":"-score" } + try: + orderby = view_dic[view_id] + except KeyError: + view_id = "latest" + orderby = "-added_at" + + # check if request is from tagged questions + if unanswered: + # check if request is from unanswered questions + # Article.objects.filter(publications__id__exact=1) + objects = Question.objects.filter(book__id__exact=book.id, deleted=False, answer_count=0).order_by(orderby) + else: + objects = Question.objects.filter(book__id__exact=book.id, deleted=False).order_by(orderby) + + # RISK - inner join queries + objects = objects.select_related(); + objects_list = Paginator(objects, user_page_size) + questions = objects_list.page(page) + + return render_to_response('book.html', { + "book" : book, + "author_info" : author_info, + "author_rss" : author_rss, + "questions" : questions, + "context" : { + 'is_paginated' : True, + 'pages': objects_list.num_pages, + 'page': page, + 'has_previous': questions.has_previous(), + 'has_next': questions.has_next(), + 'previous': questions.previous_page_number(), + 'next': questions.next_page_number(), + 'base_url' : request.path + '?sort=%s&' % view_id, + 'pagesize' : user_page_size + } + }, context_instance=RequestContext(request)) + +@login_required +def ask_book(request, short_name): + if request.method == "POST": + form = AskForm(request.POST) + if form.is_valid(): + added_at = datetime.datetime.now() + html = sanitize_html(markdowner.convert(form.cleaned_data['text'])) + question = Question( + title = strip_tags(form.cleaned_data['title']), + author = request.user, + added_at = added_at, + last_activity_at = added_at, + last_activity_by = request.user, + wiki = form.cleaned_data['wiki'], + tagnames = form.cleaned_data['tags'].strip(), + html = html, + summary = strip_tags(html)[:120] + ) + if question.wiki: + question.last_edited_by = question.author + question.last_edited_at = added_at + question.wikified_at = added_at + + question.save() + + # create the first revision + QuestionRevision.objects.create( + question = question, + revision = 1, + title = question.title, + author = request.user, + revised_at = added_at, + tagnames = question.tagnames, + summary = CONST['default_version'], + text = form.cleaned_data['text'] + ) + + books = Book.objects.extra(where=['short_name = %s'], params=[short_name]) + match_count = len(books) + if match_count == 1: + # the book info + book = books[0] + book.questions.add(question) + + return HttpResponseRedirect(question.get_absolute_url()) + else: + form = AskForm() + + tags = _get_tags_cache_json() + return render_to_response('ask.html', { + 'form' : form, + 'tags' : tags, + 'email_validation_faq_url': reverse('faq') + '#validate', + }, context_instance=RequestContext(request)) \ No newline at end of file diff --git a/forum_modules/pgfulltext/__init__.py b/forum_modules/pgfulltext/__init__.py new file mode 100755 index 00000000..ec4892c7 --- /dev/null +++ b/forum_modules/pgfulltext/__init__.py @@ -0,0 +1,9 @@ +NAME = 'Postgresql Full Text Search' +DESCRIPTION = "Enables PostgreSql full text search functionality." + +try: + import psycopg2 + CAN_ENABLE = True +except: + CAN_ENABLE = False + \ No newline at end of file diff --git a/forum_modules/pgfulltext/handlers.py b/forum_modules/pgfulltext/handlers.py new file mode 100755 index 00000000..17fb1762 --- /dev/null +++ b/forum_modules/pgfulltext/handlers.py @@ -0,0 +1,11 @@ +from forum.models import Question + +def question_search(keywords, orderby): + return Question.objects.filter(deleted=False).extra( + select={ + 'ranking': "ts_rank_cd(tsv, plainto_tsquery(%s), 32)", + }, + where=["tsv @@ plainto_tsquery(%s)"], + params=[keywords], + select_params=[keywords] + ).order_by(orderby, '-ranking') \ No newline at end of file diff --git a/forum_modules/pgfulltext/management.py b/forum_modules/pgfulltext/management.py new file mode 100755 index 00000000..89eb1395 --- /dev/null +++ b/forum_modules/pgfulltext/management.py @@ -0,0 +1,29 @@ +import os + +from django.db import connection, transaction +from django.conf import settings + +import forum.models + +if settings.DATABASE_ENGINE in ('postgresql_psycopg2', 'postgresql', ): + from django.db.models.signals import post_syncdb + + def setup_pgfulltext(sender, **kwargs): + if sender == forum.models: + install_pg_fts() + + post_syncdb.connect(setup_pgfulltext) + +def install_pg_fts(): + f = open(os.path.join(os.path.dirname(__file__), 'pg_fts_install.sql'), 'r') + + try: + cursor = connection.cursor() + cursor.execute(f.read()) + transaction.commit_unless_managed() + except: + pass + finally: + cursor.close() + + f.close() diff --git a/forum_modules/pgfulltext/pg_fts_install.sql b/forum_modules/pgfulltext/pg_fts_install.sql new file mode 100755 index 00000000..72eca516 --- /dev/null +++ b/forum_modules/pgfulltext/pg_fts_install.sql @@ -0,0 +1,38 @@ +ALTER TABLE question ADD COLUMN tsv tsvector; + +CREATE OR REPLACE FUNCTION public.create_plpgsql_language () + RETURNS TEXT + AS $$ + CREATE LANGUAGE plpgsql; + SELECT 'language plpgsql created'::TEXT; + $$ +LANGUAGE 'sql'; + +SELECT CASE WHEN + (SELECT true::BOOLEAN + FROM pg_language + WHERE lanname='plpgsql') + THEN + (SELECT 'language already installed'::TEXT) + ELSE + (SELECT public.create_plpgsql_language()) + END; + +DROP FUNCTION public.create_plpgsql_language (); + +CREATE OR REPLACE FUNCTION set_question_tsv() RETURNS TRIGGER AS $$ +begin + new.tsv := + setweight(to_tsvector('english', coalesce(new.tagnames,'')), 'A') || + setweight(to_tsvector('english', coalesce(new.title,'')), 'B') || + setweight(to_tsvector('english', coalesce(new.summary,'')), 'C'); + RETURN new; +end +$$ LANGUAGE plpgsql; + +CREATE TRIGGER tsvectorupdate BEFORE INSERT OR UPDATE +ON question FOR EACH ROW EXECUTE PROCEDURE set_question_tsv(); + + CREATE INDEX question_tsv ON question USING gin(tsv); + +UPDATE question SET title = title; diff --git a/forum_modules/sphinxfulltext/DISABLED b/forum_modules/sphinxfulltext/DISABLED new file mode 100755 index 00000000..e69de29b diff --git a/forum_modules/sphinxfulltext/__init__.py b/forum_modules/sphinxfulltext/__init__.py new file mode 100755 index 00000000..e69de29b diff --git a/forum_modules/sphinxfulltext/dependencies.py b/forum_modules/sphinxfulltext/dependencies.py new file mode 100755 index 00000000..5ddb91d2 --- /dev/null +++ b/forum_modules/sphinxfulltext/dependencies.py @@ -0,0 +1,2 @@ +DJANGO_APPS = ('djangosphinx', ) + diff --git a/forum_modules/sphinxfulltext/handlers.py b/forum_modules/sphinxfulltext/handlers.py new file mode 100755 index 00000000..665c9380 --- /dev/null +++ b/forum_modules/sphinxfulltext/handlers.py @@ -0,0 +1,4 @@ +from forum.models import Question + +def question_search(keywords, orderby): + return Question.search.query(keywords) \ No newline at end of file diff --git a/forum_modules/sphinxfulltext/models.py b/forum_modules/sphinxfulltext/models.py new file mode 100755 index 00000000..66b8ddf9 --- /dev/null +++ b/forum_modules/sphinxfulltext/models.py @@ -0,0 +1,10 @@ +from forum.models import Question +from django.conf import settings +from djangosphinx.manager import SphinxSearch + + +Question.add_to_class('search', SphinxSearch( + index=' '.join(settings.SPHINX_SEARCH_INDICES), + mode='SPH_MATCH_ALL', + ) + ) diff --git a/forum_modules/sphinxfulltext/settings.py b/forum_modules/sphinxfulltext/settings.py new file mode 100755 index 00000000..c98de7b3 --- /dev/null +++ b/forum_modules/sphinxfulltext/settings.py @@ -0,0 +1,5 @@ +SPHINX_API_VERSION = 0x113 #refer to djangosphinx documentation +SPHINX_SEARCH_INDICES=('osqa',) #a tuple of index names remember about a comma after the +#last item, especially if you have just one :) +SPHINX_SERVER='localhost' +SPHINX_PORT=3312 diff --git a/osqa.iml b/osqa.iml index 4e760f0a..f565f75f 100755 --- a/osqa.iml +++ b/osqa.iml @@ -1,5 +1,14 @@ + + + + + + diff --git a/pgfulltext/__init__.py b/pgfulltext/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/pgfulltext/management.py b/pgfulltext/management.py deleted file mode 100644 index 46f51edc..00000000 --- a/pgfulltext/management.py +++ /dev/null @@ -1,23 +0,0 @@ -import os - -from django.db import connection, transaction -from django.conf import settings - -import forum.models - -if settings.USE_PG_FTS: - from django.db.models.signals import post_syncdb - - def setup_pgfulltext(sender, **kwargs): - if sender == forum.models_: - install_pg_fts() - - post_syncdb.connect(setup_pgfulltext) - -def install_pg_fts(): - f = open(os.path.join(os.path.dirname(__file__), '../sql_scripts/pg_fts_install.sql'), 'r') - cursor = connection.cursor() - cursor.execute(f.read()) - transaction.commit_unless_managed() - f.close() - \ No newline at end of file -- cgit v1.2.3-1-g7c22