'user': self.hyperlink(self.user.get_profile_url(), self.friendly_username(viewer, self.user)),
'were_was': self.viewer_or_user_verb(viewer, self.user, _('were'), _('was')),
'badge_name': self.award.badge.name,
+ }
+
+class SuspendAction(ActionProxy):
+ def process_data(self, **kwargs):
+ self.extra = kwargs
+
+ def process_action(self):
+ self.user.is_active = False
+ self.user.save()
+
+ def cancel_action(self):
+ self.user.is_active = True
+ self.user._pop_suspension_cache()
+ self.user.save()
+ self.user.message_set.create(message=_("Your suspension has been removed."))
+
+ def describe(self, viewer=None):
+ if self.extra.get('bantype', 'indefinitely') == 'forxdays' and self.extra.get('forxdays', None):
+ suspension = _("for %s days") % self.extra['forxdays']
+ else:
+ suspension = _("indefinetely")
+
+ return _("%(user)s %(were_was)s suspended %(suspension)s: %(msg)s") % {
+ 'user': self.hyperlink(self.user.get_profile_url(), self.friendly_username(viewer, self.user)),
+ 'were_was': self.viewer_or_user_verb(viewer, self.user, _('were'), _('was')),
+ 'suspension': suspension, 'msg': self.extra.get('publicmsg', _('Bad behaviour'))
}
\ No newline at end of file
--- /dev/null
+from django.http import HttpResponse
+from django.template.loader import render_to_string
+
+from forum import settings
+
+class HttpResponseServiceUnavailable(HttpResponse):
+ def __init__(self, message):
+ super(HttpResponseServiceUnavailable, self).__init__(content=render_to_string('503.html', {
+ 'message': message,
+ 'app_logo': settings.APP_LOGO,
+ 'app_title': settings.APP_TITLE
+ }), status=503)
+
+class HttpResponseUnauthorized(HttpResponse):
+ pass
\ No newline at end of file
from django.contrib.auth.middleware import AuthenticationMiddleware\r
+from django.contrib.auth import logout\r
from forum.models.user import AnonymousUser\r
+from forum.views.auth import forward_suspended_user\r
\r
-class ExtendedUser(AuthenticationMiddleware): \r
+class ExtendedUser(AuthenticationMiddleware):\r
def process_request(self, request):\r
super(ExtendedUser, self).process_request(request)\r
if request.user.is_authenticated():\r
try:\r
request.user = request.user.user\r
+\r
+ if request.user.is_suspended():\r
+ user = request.user\r
+ logout(request)\r
+ return forward_suspended_user(request, user)\r
+\r
return None\r
except:\r
pass\r
from forum.settings import MAINTAINANCE_MODE, APP_LOGO, APP_TITLE\r
-from django.http import HttpResponseGone\r
-from django.template.loader import render_to_string\r
\r
+from forum.http_responses import HttpResponseServiceUnavailable\r
\r
class RequestUtils(object):\r
def __init__(self):\r
ip = request.META['REMOTE_ADDR']\r
\r
if not ip in MAINTAINANCE_MODE.value['allow_ips']:\r
- return HttpResponseGone(render_to_string('410.html', {\r
- 'message': MAINTAINANCE_MODE.value.get('message', ''),\r
- 'app_logo': APP_LOGO,\r
- 'app_title': APP_TITLE\r
- }))\r
+ return HttpResponseServiceUnavailable(MAINTAINANCE_MODE.value.get('message', ''))\r
\r
if request.session.get('redirect_POST_data', None):\r
request.POST = request.session.pop('redirect_POST_data')\r
from base import *
+from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned
from django.contrib.contenttypes.models import ContentType
from django.contrib.auth.models import User as DjangoUser, AnonymousUser as DjangoAnonymousUser
from django.db.models import Q
from random import Random
from django.utils.translation import ugettext as _
-import django.dispatch
-
+import logging
QUESTIONS_PER_PAGE_CHOICES = (
- (10, u'10'),
- (30, u'30'),
- (50, u'50'),
+(10, u'10'),
+(30, u'30'),
+(50, u'50'),
)
class UserManager(CachedManager):
def true_if_is_super_or_staff(fn):
def decorated(self, *args, **kwargs):
return self.is_superuser or self.is_staff or fn(self, *args, **kwargs)
+
return decorated
class User(BaseModel, DjangoUser):
gold = models.PositiveIntegerField(default=0)
silver = models.PositiveIntegerField(default=0)
bronze = models.PositiveIntegerField(default=0)
-
+
last_seen = models.DateTimeField(default=datetime.datetime.now)
real_name = models.CharField(max_length=100, blank=True)
website = models.URLField(max_length=200, blank=True)
vote_up_count = DenormalizedField("actions", canceled=False, action_type="voteup")
vote_down_count = DenormalizedField("actions", canceled=False, action_type="votedown")
-
+
objects = UserManager()
def __unicode__(self):
return self.get_profile_url()
def get_profile_link(self):
- profile_link = u'<a href="%s">%s</a>' % (self.get_profile_url(),self.username)
+ profile_link = u'<a href="%s">%s</a>' % (self.get_profile_url(), self.username)
return mark_safe(profile_link)
def get_visible_answers(self, question):
def get_vote_count_today(self):
today = datetime.date.today()
return self.actions.filter(canceled=False, action_type__in=("voteup", "votedown"),
- action_date__gte=(today - datetime.timedelta(days=1))).count()
+ action_date__gte=(today - datetime.timedelta(days=1))).count()
def get_reputation_by_upvoted_today(self):
today = datetime.datetime.now()
- sum = self.reputes.filter(reputed_at__range=(today - datetime.timedelta(days=1), today)).aggregate(models.Sum('value'))
+ sum = self.reputes.filter(reputed_at__range=(today - datetime.timedelta(days=1), today)).aggregate(
+ models.Sum('value'))
#todo: redo this, maybe transform in the daily cap
#if sum.get('value__sum', None) is not None: return sum['value__sum']
return 0
def get_flagged_items_count_today(self):
today = datetime.date.today()
return self.actions.filter(canceled=False, action_type="flag",
- action_date__gte=(today - datetime.timedelta(days=1))).count()
+ action_date__gte=(today - datetime.timedelta(days=1))).count()
@true_if_is_super_or_staff
def can_view_deleted_post(self, post):
@true_if_is_super_or_staff
def can_comment(self, post):
return self == post.author or self.reputation >= int(settings.REP_TO_COMMENT
- ) or (post.__class__.__name__ == "Answer" and self == post.question.author)
+ ) or (post.__class__.__name__ == "Answer" and self == post.question.author)
@true_if_is_super_or_staff
def can_like_comment(self, comment):
return self == comment.author or self.reputation >= int(settings.REP_TO_DELETE_COMMENTS)
def can_convert_to_comment(self, answer):
- return (not answer.marked) and (self.is_superuser or self.is_staff or answer.author == self or self.reputation >= int(settings.REP_TO_CONVERT_TO_COMMENT))
+ return (not answer.marked) and (self.is_superuser or self.is_staff or answer.author == self or self.reputation >= int
+ (settings.REP_TO_CONVERT_TO_COMMENT))
@true_if_is_super_or_staff
def can_accept_answer(self, answer):
@true_if_is_super_or_staff
def can_edit_post(self, post):
return self == post.author or self.reputation >= int(settings.REP_TO_EDIT_OTHERS
- ) or (post.nis.wiki and self.reputation >= int(settings.REP_TO_EDIT_WIKI))
+ ) or (post.nis.wiki and self.reputation >= int(
+ settings.REP_TO_EDIT_WIKI))
@true_if_is_super_or_staff
def can_wikify(self, post):
def can_delete_post(self, post):
if post.node_type == "comment":
return self.can_delete_comment(post)
-
+
return (self == post.author and (post.__class__.__name__ == "Answer" or
- not post.answers.exclude(author=self).count()))
+ not post.answers.exclude(author=self).count()))
@true_if_is_super_or_staff
def can_upload_files(self):
self.__dict__.update(self.__class__.objects.filter(id=self.id).values('password')[0])
return DjangoUser.check_password(self, old_passwd)
+ @property
+ def suspension(self):
+ if self.__dict__.get('_suspension_dencache_', False) != None:
+ try:
+ self.__dict__['_suspension_dencache_'] = self.actions.get(action_type="suspend", canceled=False)
+ except ObjectDoesNotExist:
+ self.__dict__['_suspension_dencache_'] = None
+ except MultipleObjectsReturned:
+ logging.error("Multiple suspension actions found for user %s (%s)" % (self.username, self.id))
+ self.__dict__['_suspension_dencache_'] = self.actions.filter(action_type="suspend", canceled=False
+ ).order_by('-action_date')[0]
+
+ return self.__dict__['_suspension_dencache_']
+
+ def _pop_suspension_cache(self):
+ self.__dict__.pop('_suspension_dencache_', None)
+
+ def is_suspended(self):
+ if not self.is_active:
+ suspension = self.suspension
+
+ if suspension and suspension.extra.get('bantype', None) == 'forxdays' and (
+ datetime.datetime.now() > suspension.action_date + datetime.timedelta(
+ days=int(suspension.extra.get('forxdays', 365)))):
+ suspension.cancel()
+ else:
+ return True
+
+ return False
class Meta:
app_label = 'forum'
new_question = models.CharField(max_length=1, default='d')
new_question_watched_tags = models.CharField(max_length=1, default='i')
subscribed_questions = models.CharField(max_length=1, default='i')
-
+
#auto_subscribe_to
all_questions = models.BooleanField(default=False)
all_questions_watched_tags = models.BooleanField(default=False)
obj.save()
except:
return None
-
+
return obj
def validate(self, hash, user, type, hash_data=[]):
return False
class ValidationHash(models.Model):
- hash_code = models.CharField(max_length=255,unique=True)
+ hash_code = models.CharField(max_length=255, unique=True)
seed = models.CharField(max_length=12)
expiration = models.DateTimeField(default=one_day_from_now)
type = models.CharField(max_length=12)
return self.hash_code
class AuthKeyUserAssociation(models.Model):
- key = models.CharField(max_length=255,null=False,unique=True)
+ key = models.CharField(max_length=255, null=False, unique=True)
provider = models.CharField(max_length=64)
user = models.ForeignKey(User, related_name="auth_keys")
added_at = models.DateTimeField(default=datetime.datetime.now)
$().ready(function() {
var $dropdown = $('#user-menu-dropdown');
- $('#user-menu').click(function(){
+ $('#user-menu').click(function() {
$('.dialog').fadeOut('fast', function() {
$dialog.remove();
});
$dropdown.slideToggle('fast', function() {
if ($dropdown.is(':visible')) {
- $dropdown.one('clickoutside', function() {
+ $dropdown.one('clickoutside', function() {
$dropdown.slideUp('fast')
});
}
+ '<tr><th>' + messages.message + '</th><td><textarea id="award-message"></textarea></td></tr></table>';
show_dialog({
- html: table,
- extra_class: 'award-rep-points',
- event: e,
- yes_callback: function($dialog) {
- var $points_input = $('#points-to-award');
- var _points = parseInt($points_input.val());
+ html: table,
+ extra_class: 'award-rep-points',
+ event: e,
+ yes_callback: function($dialog) {
+ var $points_input = $('#points-to-award');
+ var _points = parseInt($points_input.val());
- if(!isNaN(_points)) {
- $dialog.fadeOut('fast');
- var _message = $('#award-message').val();
- $.post($('#award-rep-points').attr('href'), {points: _points, message: _message}, function(data) {
- if (data.success) {
- $('#user-reputation').css('background', 'yellow');
- $('#user-reputation').html(data.reputation);
+ if (!isNaN(_points)) {
+ $dialog.fadeOut('fast');
+ var _message = $('#award-message').val();
+ $.post($('#award-rep-points').attr('href'), {points: _points, message: _message}, function(data) {
+ if (data.success) {
+ $('#user-reputation').css('background', 'yellow');
+ $('#user-reputation').html(data.reputation);
- $('#user-reputation').animate({ backgroundColor: "transparent" }, 1000);
+ $('#user-reputation').animate({ backgroundColor: "transparent" }, 1000);
- }
- }, 'json')
- }
- },
- show_no: true
- });
+ }
+ }, 'json')
+ }
+ },
+ show_no: true
+ });
return false;
});
+
});
\ No newline at end of file
@import "jquery.autocomplete.css";
body {
- background: none repeat scroll 0 0 #FFFFFF;
- color: #000000;
- font-family: sans-serif;
- font-size: 12px;
- line-height: 150%;
- margin: 0;
- padding: 0;
+ background: none repeat scroll 0 0 #FFFFFF;
+ color: #000000;
+ font-family: sans-serif;
+ font-size: 12px;
+ line-height: 150%;
+ margin: 0;
+ padding: 0;
}
div {
- margin: 0 auto;
- padding: 0;
+ margin: 0 auto;
+ padding: 0;
}
-h1,h2,h3,ul,li,form,img,p {
- border: medium none;
- margin: 0;
- padding: 0;
+h1, h2, h3, ul, li, form, img, p {
+ border: medium none;
+ margin: 0;
+ padding: 0;
}
-label {vertical-align: middle;}
+label {
+ vertical-align: middle;
+}
-.login label {display: block;}
-.login .form-row-vertical {margin-bottom: 8px;}
+.login label {
+ display: block;
+}
+
+.login .form-row-vertical {
+ margin-bottom: 8px;
+}
hr {
- border-color: #CCCCCE -moz-use-text-color -moz-use-text-color;
- border-right: medium none;
- border-style: dashed none none;
- border-width: 1px medium medium;
+ border-color: #CCCCCE -moz-use-text-color -moz-use-text-color;
+ border-right: medium none;
+ border-style: dashed none none;
+ border-width: 1px medium medium;
}
-input,select {
- font-family: Trebuchet MS,"segoe ui",Helvetica,"Microsoft YaHei",Tahoma,Verdana,MingLiu,PMingLiu,Arial,sans-serif;
- vertical-align: middle;
+input, select {
+ font-family: Trebuchet MS, "segoe ui", Helvetica, "Microsoft YaHei", Tahoma, Verdana, MingLiu, PMingLiu, Arial, sans-serif;
+ vertical-align: middle;
}
p {
- font-size: 13px;
- line-height: 140%;
- margin-bottom: 13px;
+ font-size: 13px;
+ line-height: 140%;
+ margin-bottom: 13px;
}
a {
- color: #3060A8;
- text-decoration: none;
+ color: #3060A8;
+ text-decoration: none;
}
.badges a {
- color: #763333;
- text-decoration: underline;
+ color: #763333;
+ text-decoration: underline;
+}
+
+a:hover {
+ text-decoration: underline;
}
-a:hover { text-decoration: underline; }
-.tright { text-align: right; }
+.tright {
+ text-align: right;
+}
.spacer3 {
- clear: both;
- height: 30px;
- line-height: 30px;
- visibility: hidden;
+ clear: both;
+ height: 30px;
+ line-height: 30px;
+ visibility: hidden;
}
h1 {
- font-size: 160%;
- padding: 5px 0;
+ font-size: 160%;
+ padding: 5px 0;
line-height: 110%;
}
h2 {
- font-size: 140%;
- padding: 3px 0;
+ font-size: 140%;
+ padding: 3px 0;
line-height: 110%;
}
h3 {
- font-size: 120%;
- padding: 3px 0;
- line-height: 110%;
+ font-size: 120%;
+ padding: 3px 0;
+ line-height: 110%;
}
ul {
- list-style: disc outside none;
- margin-bottom: 1em;
- margin-left: 20px;
- padding-left: 0;
+ list-style: disc outside none;
+ margin-bottom: 1em;
+ margin-left: 20px;
+ padding-left: 0;
}
ol {
- list-style: decimal outside none;
- margin-bottom: 1em;
- margin-left: 30px;
- padding-left: 0;
+ list-style: decimal outside none;
+ margin-bottom: 1em;
+ margin-left: 30px;
+ padding-left: 0;
+}
+
+td ul {
+ vertical-align: middle;
}
-td ul { vertical-align: middle; }
-li input { margin: 3px 3px 4px; }
+li input {
+ margin: 3px 3px 4px;
+}
pre {
- background-color: #F5F5F5;
- font-family: Consolas,Monaco,Liberation Mono,Lucida Console,Monospace;
- font-size: 100%;
- margin-bottom: 10px;
- overflow: auto;
- padding-left: 5px;
- padding-top: 5px;
- width: 580px;
+ background-color: #F5F5F5;
+ font-family: Consolas, Monaco, Liberation Mono, Lucida Console, Monospace;
+ font-size: 100%;
+ margin-bottom: 10px;
+ overflow: auto;
+ padding-left: 5px;
+ padding-top: 5px;
+ width: 580px;
}
code {
- font-family: Consolas,Monaco,Liberation Mono,Lucida Console,Monospace;
- font-size: 100%;
+ font-family: Consolas, Monaco, Liberation Mono, Lucida Console, Monospace;
+ font-size: 100%;
}
blockquote {
- background-color: #F5F5F5;
- margin-bottom: 10px;
- margin-right: 15px;
- padding: 10px 0 1px 10px;
+ background-color: #F5F5F5;
+ margin-bottom: 10px;
+ margin-right: 15px;
+ padding: 10px 0 1px 10px;
}
#wrapper {
- margin: auto;
- padding: 0;
- width: 990px;
+ margin: auto;
+ padding: 0;
+ width: 990px;
}
#roof {
- background: none repeat scroll 0 0 #FFFFFF;
- margin-top: 0;
- position: relative;
+ background: none repeat scroll 0 0 #FFFFFF;
+ margin-top: 0;
+ position: relative;
}
#room {
- background-color: #FFFFFF;
- border-bottom: 1px solid #777777;
- padding: 10px 0;
+ background-color: #FFFFFF;
+ border-bottom: 1px solid #777777;
+ padding: 10px 0;
}
#CALeft {
- float: left;
- position: relative;
- width: 740px;
+ float: left;
+ position: relative;
+ width: 740px;
}
#CARight {
- float: right;
- width: 240px;
+ float: right;
+ width: 240px;
}
#CAFull {
- float: left;
- padding: 0 5px;
- width: 950px;
+ float: left;
+ padding: 0 5px;
+ width: 950px;
}
#ground {
- background: none repeat scroll 0 0 #BDCCED;
- border-top: 1px solid #000000;
- padding-bottom: 0;
- padding-top: 6px;
- text-align: center;
- width: 100%;
+ background: none repeat scroll 0 0 #BDCCED;
+ border-top: 1px solid #000000;
+ padding-bottom: 0;
+ padding-top: 6px;
+ text-align: center;
+ width: 100%;
}
#top {
- background-color: #FFFFFF;
- height: 20px;
- padding: 3px;
- position: absolute;
- right: 0;
- text-align: right;
- top: 0;
- width: 500px;
+ background-color: #FFFFFF;
+ height: 20px;
+ padding: 3px;
+ position: absolute;
+ right: 0;
+ text-align: right;
+ top: 0;
+ width: 500px;
}
#top a {
- color: #333333;
- font-size: 12px;
- height: 35px;
- margin-left: 20px;
- text-align: right;
- text-decoration: underline;
+ color: #333333;
+ font-size: 12px;
+ height: 35px;
+ margin-left: 20px;
+ text-align: right;
+ text-decoration: underline;
}
-#logo { padding: 5px 0 0; }
+#logo {
+ padding: 5px 0 0;
+}
#navBar {
- display: block;
- position: relative;
- width: 990px;
+ display: block;
+ position: relative;
+ width: 990px;
}
-#navBar .nav { margin: 20px 0 0 16px; }
+#navBar .nav {
+ margin: 20px 0 0 16px;
+}
#navBar .nav a {
- background-color: #E5EBF8;
- border-color: #888888 #888888 -moz-use-text-color;
- border-style: solid solid none;
- border-width: 1px 1px medium;
- color: #333333;
- display: block;
- float: left;
- font-size: 14px;
- font-weight: 400;
- height: 25px;
- line-height: 30px;
- margin-left: 10px;
- padding: 0 12px 3px;
- text-decoration: none;
-}
-
-#navBar .nav a:hover { text-decoration: underline; }
+ background-color: #E5EBF8;
+ border-color: #888888 #888888 -moz-use-text-color;
+ border-style: solid solid none;
+ border-width: 1px 1px medium;
+ color: #333333;
+ display: block;
+ float: left;
+ font-size: 14px;
+ font-weight: 400;
+ height: 25px;
+ line-height: 30px;
+ margin-left: 10px;
+ padding: 0 12px 3px;
+ text-decoration: none;
+}
+
+#navBar .nav a:hover {
+ text-decoration: underline;
+}
#navBar .nav a.on {
- background: none repeat scroll 0 0 #356FCB;
- border: 1px solid #356FCB;
- color: #FFFFFF;
- font-weight: 600;
- height: 24px;
- line-height: 28px;
- text-decoration: none;
+ background: none repeat scroll 0 0 #356FCB;
+ border: 1px solid #356FCB;
+ color: #FFFFFF;
+ font-weight: 600;
+ height: 24px;
+ line-height: 28px;
+ text-decoration: none;
}
#navBar .nav a.special {
- color: #B02B2C;
- font-size: 14px;
- font-weight: bold;
- text-decoration: none;
+ color: #B02B2C;
+ font-size: 14px;
+ font-weight: bold;
+ text-decoration: none;
}
-#navBar .nav a.special:hover { text-decoration: underline; }
+#navBar .nav a.special:hover {
+ text-decoration: underline;
+}
#navBar .nav div.focus {
- float: right;
- padding-right: 0;
+ float: right;
+ padding-right: 0;
}
#searchBar {
- background-color: #B6C4E2;
- border-color: #EEEEEC #A9ACA5 #BABDB6 #EEEEEC;
- border-style: solid;
- border-width: 1px;
- padding: 4px 0 0;
- width: 988px;
+ background-color: #B6C4E2;
+ border-color: #EEEEEC #A9ACA5 #BABDB6 #EEEEEC;
+ border-style: solid;
+ border-width: 1px;
+ padding: 4px 0 0;
+ width: 988px;
}
-#searchBar .content { }
+#searchBar .content {
+}
#searchBar .searchInput {
- font-size: 13px;
- height: 18px;
- width: 400px;
+ font-size: 13px;
+ height: 18px;
+ width: 400px;
}
#searchBar .searchBtn {
- font-size: 14px;
- height: 26px;
- width: 80px;
+ font-size: 14px;
+ height: 26px;
+ width: 80px;
}
#searchBar .options {
- color: #333333;
- font-size: 120%;
- padding: 3px 0;
+ color: #333333;
+ font-size: 120%;
+ padding: 3px 0;
+}
+
+#searchBar .options input {
+ margin: 0 3px 0 15px;
}
-#searchBar .options input { margin: 0 3px 0 15px; }
-#searchBar .options input:hover { cursor: pointer; }
+#searchBar .options input:hover {
+ cursor: pointer;
+}
#listA {
- background-color: #FFFFFF;
- float: left;
- padding: 0 0;
- width: 100%;
+ background-color: #FFFFFF;
+ float: left;
+ padding: 0 0;
+ width: 100%;
}
.thousand {
- color: orange;
+ color: orange;
}
.short-summary {
- border-top: 1px dotted #CCCCCE;
- float: left;
- overflow: hidden;
- padding: 3px 0px 5px 0;
- position: relative;
- width: 740px;
+ border-top: 1px dotted #CCCCCE;
+ float: left;
+ overflow: hidden;
+ padding: 3px 0px 5px 0;
+ position: relative;
+ width: 740px;
}
.short-summary h2 a {
- color: #2A5594;
- font-family: "Trebuchet MS","segoe ui",arial,sans-serif;
- font-size: 17px;
+ color: #2A5594;
+ font-family: "Trebuchet MS", "segoe ui", arial, sans-serif;
+ font-size: 17px;
}
.short-summary .userinfo {
- color: #666666;
- float: right;
- margin-top: 8px;
+ color: #666666;
+ float: right;
+ margin-top: 8px;
}
-.userinfo a,a.userinfo { color: #3060A8; }
+.userinfo a, a.userinfo {
+ color: #3060A8;
+}
.short-summary .counts {
- float: left;
- margin-right: 0px;
- margin-top: 4px;
- padding-right: 2px;
+ float: left;
+ margin-right: 0px;
+ margin-top: 4px;
+ padding-right: 2px;
}
.short-summary .counts .item-count {
- font-size: 17px;
- font-weight: bold;
+ font-size: 17px;
+ font-weight: bold;
}
-.short-summary .votes,.short-summary .status,.short-summary .views {
- -moz-border-radius: 5px 5px 5px 5px;
- border-bottom: 1px solid #CCCCCC;
- border-right: 1px solid #CCCCCC;
- float: left;
- font-size: 11px;
- height: 42px;
- margin: 0 6px 0 0px;
- padding: 8px 2px 0;
- text-align: center;
- width: 46px;
+.short-summary .votes, .short-summary .status, .short-summary .views {
+ -moz-border-radius: 5px 5px 5px 5px;
+ border-bottom: 1px solid #CCCCCC;
+ border-right: 1px solid #CCCCCC;
+ float: left;
+ font-size: 11px;
+ height: 42px;
+ margin: 0 6px 0 0px;
+ padding: 8px 2px 0;
+ text-align: center;
+ width: 46px;
}
-.short-summary .votes,.short-summary .views { color: #666666; }
+.short-summary .votes, .short-summary .views {
+ color: #666666;
+}
.short-summary .favorites {
- width: 24px;
- float: left;
- text-align: center;
+ width: 24px;
+ float: left;
+ text-align: center;
}
-#question-table { margin-bottom: 10px; }
+#question-table {
+ margin-bottom: 10px;
+}
.questions-count {
- color: #A40000;
- font-family: sans-serif;
- font-size: 24px;
- font-weight: 600;
- margin-top: 3px;
+ color: #A40000;
+ font-family: sans-serif;
+ font-size: 24px;
+ font-weight: 600;
+ margin-top: 3px;
margin-right: 5px;
- padding: 0 0 5px 0;
+ padding: 0 0 5px 0;
}
.boxA {
}
.boxA h3 {
- color: #FFFFFF;
- font-size: 13px;
- font-weight: 800;
- margin: 0 0 4px;
- padding: 0;
+ color: #FFFFFF;
+ font-size: 13px;
+ font-weight: 800;
+ margin: 0 0 4px;
+ padding: 0;
}
.boxA .body {
- background: none repeat scroll 0 0 #FFFFFF;
- border: 1px solid #999999;
- font-size: 13px;
- padding: 8px;
+ background: none repeat scroll 0 0 #FFFFFF;
+ border: 1px solid #999999;
+ font-size: 13px;
+ padding: 8px;
}
.boxA .more {
- font-weight: 800;
- padding: 2px;
- text-align: right;
+ font-weight: 800;
+ padding: 2px;
+ text-align: right;
}
.boxC {
- background: none repeat scroll 0 0 #E5EBF8;
- border-color: #EEEEEC #A9ACA5 #BABDB6 #EEEEEC;
- border-style: solid;
- border-width: 1px;
- margin-bottom: 8px;
- padding: 10px;
+ background: none repeat scroll 0 0 #E5EBF8;
+ border-color: #EEEEEC #A9ACA5 #BABDB6 #EEEEEC;
+ border-style: solid;
+ border-width: 1px;
+ margin-bottom: 8px;
+ padding: 10px;
+}
+
+.boxC p {
+ margin-bottom: 8px;
}
-.boxC p { margin-bottom: 8px; }
-.boxC p.nomargin { margin: 0; }
+.boxC p.nomargin {
+ margin: 0;
+}
.boxC p.info-box-follow-up-links {
- margin: 0;
- text-align: right;
+ margin: 0;
+ text-align: right;
}
.pager {
- float: left;
- margin-bottom: 16px;
- margin-top: 10px;
+ float: left;
+ margin-bottom: 16px;
+ margin-top: 10px;
}
.pagesize {
- float: right;
- margin-bottom: 16px;
- margin-top: 10px;
+ float: right;
+ margin-bottom: 16px;
+ margin-top: 10px;
}
.paginator {
- font: 12px sans-serif;
- padding: 5px 0 10px;
+ font: 12px sans-serif;
+ padding: 5px 0 10px;
+}
+
+.paginator .prev a, .paginator .prev a:visited, .paginator .next a, .paginator .next a:visited {
+ background-color: #FFFFFF;
+ border: 1px solid #FFFFFF;
+ color: #777777;
+ font: bold 100% sans-serif;
+ padding: 2px 4px 3px;
}
-.paginator .prev a,.paginator .prev a:visited,.paginator .next a,.paginator .next a:visited {
- background-color: #FFFFFF;
- border: 1px solid #FFFFFF;
- color: #777777;
- font: bold 100% sans-serif;
- padding: 2px 4px 3px;
+.paginator .prev {
+ margin-right: 0.5em;
}
-.paginator .prev { margin-right: 0.5em; }
-.paginator .next { margin-left: 0.5em; }
+.paginator .next {
+ margin-left: 0.5em;
+}
-.paginator .page a,.paginator .page a:visited,.paginator .curr {
- background-color: #FFFFFF;
- border: 1px solid #CCCCCC;
- color: #777777;
- font: 0.875em verdana;
- margin: 0 0.25em;
- padding: 0.25em;
+.paginator .page a, .paginator .page a:visited, .paginator .curr {
+ background-color: #FFFFFF;
+ border: 1px solid #CCCCCC;
+ color: #777777;
+ font: 0.875em verdana;
+ margin: 0 0.25em;
+ padding: 0.25em;
}
.paginator .curr {
- background-color: #777777;
- border: 1px solid #777777;
- color: #FFFFFF;
- font-weight: bold;
+ background-color: #777777;
+ border: 1px solid #777777;
+ color: #FFFFFF;
+ font-weight: bold;
}
-.paginator .page a:hover,.paginator .prev a:hover,.paginator .next a:hover {
- background-color: #777777;
- border: 1px solid #777777;
- color: #FFFFFF;
- text-decoration: none;
+.paginator .page a:hover, .paginator .prev a:hover, .paginator .next a:hover {
+ background-color: #777777;
+ border: 1px solid #777777;
+ color: #FFFFFF;
+ text-decoration: none;
}
.paginator .text {
- color: #777777;
- font: bold 100% sans-serif;
- padding: 0.3em;
+ color: #777777;
+ font: bold 100% sans-serif;
+ padding: 0.3em;
}
-.paginator-container-left { padding: 5px 0 10px; }
+.paginator-container-left {
+ padding: 5px 0 10px;
+}
.tags {
- display: block;
- font-family: sans-serif;
- line-height: 200%;
- margin-top: 5px;
+ display: block;
+ font-family: sans-serif;
+ line-height: 200%;
+ margin-top: 5px;
}
-.tags a,span.tag {
- background-color: #EEEEEE;
- border-bottom: 1px solid #CCCCCC;
- border-right: 1px solid #CCCCCC;
- color: #777777;
- font-size: 11px;
- font-weight: normal;
- padding: 1px 8px;
- text-decoration: none;
- white-space: nowrap;
+.tags a, span.tag {
+ background-color: #EEEEEE;
+ border-bottom: 1px solid #CCCCCC;
+ border-right: 1px solid #CCCCCC;
+ color: #777777;
+ font-size: 11px;
+ font-weight: normal;
+ padding: 1px 8px;
+ text-decoration: none;
+ white-space: nowrap;
}
.tags a:hover {
- background-color: #356FCB;
- color: #FFFFFF;
+ background-color: #356FCB;
+ color: #FFFFFF;
}
.tag-number {
- font-family: sans-serif;
- font-weight: 700;
+ font-family: sans-serif;
+ font-weight: 700;
}
.marked-tags {
- margin-bottom: 5px;
- margin-top: 0;
+ margin-bottom: 5px;
+ margin-top: 0;
}
a.medal {
- background: none repeat scroll 0 0 #FFFFCD;
- border-color: #EEEEEE #CCCCCC #CCCCCC #EEEEEE;
- border-left: 1px solid #EEEEEE;
- border-style: solid;
- border-width: 1px;
- color: #333333;
- font-size: 14px;
- font-weight: bold;
- line-height: 250%;
- padding: 4px 12px 4px 6px;
- text-decoration: none;
+ background: none repeat scroll 0 0 #FFFFCD;
+ border-color: #EEEEEE #CCCCCC #CCCCCC #EEEEEE;
+ border-left: 1px solid #EEEEEE;
+ border-style: solid;
+ border-width: 1px;
+ color: #333333;
+ font-size: 14px;
+ font-weight: bold;
+ line-height: 250%;
+ padding: 4px 12px 4px 6px;
+ text-decoration: none;
}
a.medal:hover {
- background: url("../images/medala_on.gif") no-repeat scroll 0 0 transparent;
- border-color: #E7E296 #D1CA3D #D1CA3D #E7E296;
- border-left: 1px solid #E7E296;
- border-style: solid;
- border-width: 1px;
- color: #333333;
- text-decoration: none;
+ background: url("../images/medala_on.gif") no-repeat scroll 0 0 transparent;
+ border-color: #E7E296 #D1CA3D #D1CA3D #E7E296;
+ border-left: 1px solid #E7E296;
+ border-style: solid;
+ border-width: 1px;
+ color: #333333;
+ text-decoration: none;
}
.tabBar {
- background-color: #FFFFFF;
- border-bottom: 1px solid white;
- clear: both;
- height: 30px;
- margin-bottom: 3px;
- width: 100%;
+ background-color: #FFFFFF;
+ border-bottom: 1px solid white;
+ clear: both;
+ height: 30px;
+ margin-bottom: 3px;
+ width: 100%;
}
.tabsA {
- background-color: #FFFFFF;
- display: block;
- float: right;
- font-weight: bold;
- height: 20px;
- position: relative;
+ background-color: #FFFFFF;
+ display: block;
+ float: right;
+ font-weight: bold;
+ height: 20px;
+ position: relative;
}
.tabsA a {
- background: none repeat scroll 0 0 #EEEEEE;
- border-bottom: 1px solid #CCCCCC;
- border-right: 1px solid #CCCCCC;
- color: #888A85;
- display: block;
- float: left;
- height: 20px;
- line-height: 22px;
- margin: 5px 4px 0 0;
- padding: 0 11px;
- text-decoration: none;
+ background: none repeat scroll 0 0 #EEEEEE;
+ border-bottom: 1px solid #CCCCCC;
+ border-right: 1px solid #CCCCCC;
+ color: #888A85;
+ display: block;
+ float: left;
+ height: 20px;
+ line-height: 22px;
+ margin: 5px 4px 0 0;
+ padding: 0 11px;
+ text-decoration: none;
}
-.tabsA a.on,.tabsA a:hover {
- background: none repeat scroll 0 0 #FFFFFF;
- color: #A40000;
+.tabsA a.on, .tabsA a:hover {
+ background: none repeat scroll 0 0 #FFFFFF;
+ color: #A40000;
}
.tabsA a:hover {
- background: none repeat scroll 0 0 #356FCB;
- color: #FFFFFF;
+ background: none repeat scroll 0 0 #356FCB;
+ color: #FFFFFF;
}
.headlineA {
- border-bottom: 1px solid #777777;
- font-size: 13px;
- font-weight: 800;
- height: 30px;
- margin-bottom: 12px;
- padding-bottom: 2px;
- text-align: right;
+ border-bottom: 1px solid #777777;
+ font-size: 13px;
+ font-weight: 800;
+ height: 30px;
+ margin-bottom: 12px;
+ padding-bottom: 2px;
+ text-align: right;
}
.headQuestions {
- background: url("../images/dot-list.gif") no-repeat scroll left center transparent;
- border-bottom: 0 solid #777777;
- float: left;
- font-size: 15px;
- font-weight: 700;
- height: 23px;
- line-height: 23px;
- margin: 5px 0 0 5px;
- padding: 0 6px 0 15px;
+ background: url("../images/dot-list.gif") no-repeat scroll left center transparent;
+ border-bottom: 0 solid #777777;
+ float: left;
+ font-size: 15px;
+ font-weight: 700;
+ height: 23px;
+ line-height: 23px;
+ margin: 5px 0 0 5px;
+ padding: 0 6px 0 15px;
}
.headUsers {
- background: url("../images/dot-list.gif") no-repeat scroll left center transparent;
- border-bottom: 0 solid #777777;
- float: left;
- font-size: 15px;
- font-weight: 700;
- height: 23px;
- line-height: 23px;
- margin: 5px 0 0 5px;
- padding: 0 6px 0 15px;
+ background: url("../images/dot-list.gif") no-repeat scroll left center transparent;
+ border-bottom: 0 solid #777777;
+ float: left;
+ font-size: 15px;
+ font-weight: 700;
+ height: 23px;
+ line-height: 23px;
+ margin: 5px 0 0 5px;
+ padding: 0 6px 0 15px;
}
.headMedals {
- background: url("../images/dot-list.gif") no-repeat scroll left center transparent;
- border-bottom: 0 solid #777777;
- float: left;
- font-size: 15px;
- font-weight: 700;
- height: 23px;
- line-height: 23px;
- margin: 5px 0 0 5px;
- padding: 0 6px 0 15px;
+ background: url("../images/dot-list.gif") no-repeat scroll left center transparent;
+ border-bottom: 0 solid #777777;
+ float: left;
+ font-size: 15px;
+ font-weight: 700;
+ height: 23px;
+ line-height: 23px;
+ margin: 5px 0 0 5px;
+ padding: 0 6px 0 15px;
}
.headNormal {
- border-bottom: 1px solid #777777;
- font-size: 15px;
- font-weight: bold;
- margin-bottom: 12px;
- padding: 3px;
- text-align: left;
+ border-bottom: 1px solid #777777;
+ font-size: 15px;
+ font-weight: bold;
+ margin-bottom: 12px;
+ padding: 3px;
+ text-align: left;
}
.headUser {
- border-bottom: 1px solid #777777;
- font-size: 20px;
- font-weight: 800;
- margin-bottom: 12px;
- padding: 5px;
- text-align: left;
+ border-bottom: 1px solid #777777;
+ font-size: 20px;
+ font-weight: 800;
+ margin-bottom: 12px;
+ padding: 5px;
+ text-align: left;
}
.questions-related {
- font-weight: 700;
- word-wrap: break-word;
+ font-weight: 700;
+ word-wrap: break-word;
}
.questions-related p {
- font-size: 100%;
- line-height: 20px;
- margin-bottom: 10px;
+ font-size: 100%;
+ line-height: 20px;
+ margin-bottom: 10px;
}
.question-body {
- font-size: 13px;
- line-height: 20px;
- min-height: 100px;
+ font-size: 13px;
+ line-height: 20px;
+ min-height: 100px;
}
-.question-body img { max-width: 640px; }
+.question-body img {
+ max-width: 640px;
+}
.vote-buttons {
- float: left;
- text-align: center;
+ float: left;
+ text-align: center;
}
span.form-error {
- color: #990000;
- font-weight: normal;
- margin-left: 5px;
+ color: #990000;
+ font-weight: normal;
+ margin-left: 5px;
}
ul.errorlist li {
- color: #990000;
- font-weight: normal;
- margin-left: 0px;
+ color: #990000;
+ font-weight: normal;
+ margin-left: 0px;
margin-top: 5px;
}
.answer {
- border-bottom: 1px solid #CCCCCE;
- padding-top: 10px;
- width: 100%;
+ border-bottom: 1px solid #CCCCCE;
+ padding-top: 10px;
+ width: 100%;
}
.answer-body {
- font-size: 13px;
- line-height: 20px;
- min-height: 80px;
+ font-size: 13px;
+ line-height: 20px;
+ min-height: 80px;
}
-.answer-body img { max-width: 640px; }
+.answer-body img {
+ max-width: 640px;
+}
-.answered-by-owner { background: none repeat scroll 0 0 #E9E9FF; }
+.answered-by-owner {
+ background: none repeat scroll 0 0 #E9E9FF;
+}
.accepted-answer {
- background-color: #EBFFE6;
- border-bottom-color: #9BD59B;
+ background-color: #EBFFE6;
+ border-bottom-color: #9BD59B;
}
.answered {
- background: none repeat scroll 0 0 #E5EBF8;
- color: #314362;
+ background: none repeat scroll 0 0 #E5EBF8;
+ color: #314362;
}
-.answered-accepted,.answer-votes.answered-accepted {
- background: none repeat scroll 0 0 #E6F8DD;
- color: #3A6231;
+.answered-accepted, .answer-votes.answered-accepted {
+ background: none repeat scroll 0 0 #E6F8DD;
+ color: #3A6231;
}
.unanswered {
- background: none repeat scroll 0 0 #F3E3E1;
- color: #6B2B28;
+ background: none repeat scroll 0 0 #F3E3E1;
+ color: #6B2B28;
}
.tagsList {
- list-style-type: none;
- margin: 0;
- min-height: 360px;
- padding: 0;
+ list-style-type: none;
+ margin: 0;
+ min-height: 360px;
+ padding: 0;
}
.tagsList li {
- float: left;
- width: 235px;
+ float: left;
+ width: 235px;
}
.badge-list {
- list-style-type: none;
- margin: 0;
+ list-style-type: none;
+ margin: 0;
+}
+
+.badge-list a {
+ color: #3060A8;
}
-.badge-list a { color: #3060A8; }
-.badge-list a.medal { color: #333333; }
-.list-item { margin-left: 15px; }
+.badge-list a.medal {
+ color: #333333;
+}
+
+.list-item {
+ margin-left: 15px;
+}
.list-item li {
- font-size: 13px;
- line-height: 20px;
- list-style-type: disc;
- margin-bottom: 10px;
+ font-size: 13px;
+ line-height: 20px;
+ list-style-type: disc;
+ margin-bottom: 10px;
+}
+
+.form-row {
+ line-height: 25px;
}
-.form-row { line-height: 25px; }
-table.form-as-table { margin-top: 5px; }
+table.form-as-table {
+ margin-top: 5px;
+}
table.form-as-table ul {
- display: inline;
- list-style-type: none;
+ display: inline;
+ list-style-type: none;
+}
+
+table.form-as-table li {
+ display: inline;
+}
+
+table.form-as-table pre {
+ display: inline;
}
-table.form-as-table li { display: inline; }
-table.form-as-table pre { display: inline; }
-table.check-table td { padding-right: 50px; }
+table.check-table td {
+ padding-right: 50px;
+}
.submit-row {
- clear: both;
- display: block;
- line-height: 30px;
- padding-top: 10px;
+ clear: both;
+ display: block;
+ line-height: 30px;
+ padding-top: 10px;
}
.error {
- color: darkred;
- font-size: 10px;
- margin: 0;
+ color: darkred;
+ font-size: 10px;
+ margin: 0;
}
.small {
- font-size: 11px;
+ font-size: 11px;
}
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%;
+ color: #666666;
+ font-size: 90%;
}
#editor {
- font-size: 100%;
- line-height: 18px;
- min-height: 200px;
- width: 100%;
+ font-size: 100%;
+ line-height: 18px;
+ min-height: 200px;
+ width: 100%;
}
.wmd-preview {
- background-color: #F5F5F5;
- margin-top: 10px;
- min-height: 20px;
- padding: 6px;
- width: 98%;
+ background-color: #F5F5F5;
+ margin-top: 10px;
+ min-height: 20px;
+ padding: 6px;
+ width: 98%;
}
.preview-toggle {
- color: #AAAAAA;
- font-weight: 600;
- text-align: left;
- width: 100%;
+ color: #AAAAAA;
+ font-weight: 600;
+ text-align: left;
+ width: 100%;
}
-.preview-toggle span:hover { cursor: pointer; }
-#revisions { width: 950px; }
+.preview-toggle span:hover {
+ cursor: pointer;
+}
+
+#revisions {
+ width: 950px;
+}
.revision {
- font-size: 13px;
- margin: 10px 0;
- width: 100%;
+ font-size: 13px;
+ margin: 10px 0;
+ width: 100%;
}
.revision .header {
- background-color: #EEEEEE;
- cursor: pointer;
- padding: 5px;
+ background-color: #EEEEEE;
+ cursor: pointer;
+ padding: 5px;
+}
+
+.revision .author {
+ background-color: #E9E9FF;
}
-.revision .author { background-color: #E9E9FF; }
-.revision .summary { padding: 5px 0 10px; }
+.revision .summary {
+ padding: 5px 0 10px;
+}
.revision .summary span {
- background-color: yellow;
- display: inline;
- padding-left: 3px;
- padding-right: 3px;
+ background-color: yellow;
+ display: inline;
+ padding-left: 3px;
+ padding-right: 3px;
}
.revision h1 {
- font-size: 130%;
- font-weight: 600;
- padding: 15px 0;
+ font-size: 130%;
+ font-weight: 600;
+ padding: 15px 0;
}
.revision-mark {
- display: inline-block;
- font-size: 90%;
- overflow: hidden;
- text-align: left;
- width: 200px;
+ display: inline-block;
+ font-size: 90%;
+ overflow: hidden;
+ text-align: left;
+ width: 200px;
}
.revision-number {
- font-family: sans-serif;
- font-size: 300%;
- font-weight: bold;
+ font-family: sans-serif;
+ font-size: 300%;
+ font-weight: bold;
}
.revision .body {
- margin-bottom: 50px;
- padding-left: 10px;
+ margin-bottom: 50px;
+ padding-left: 10px;
+}
+
+del {
+ color: #FF5F5F;
}
-del { color: #FF5F5F; }
-ins { background-color: #97FF97; }
+ins {
+ background-color: #97FF97;
+}
.count {
- color: #777777;
- font-family: Arial;
- font-size: 200%;
- font-weight: 700;
+ color: #777777;
+ font-family: Arial;
+ font-size: 200%;
+ font-weight: 700;
}
.scoreNumber {
- color: #777777;
- font-family: Arial;
- font-size: 35px;
- font-weight: 800;
- line-height: 40px;
+ color: #777777;
+ font-family: Arial;
+ font-size: 35px;
+ font-weight: 800;
+ line-height: 40px;
}
-.user-details { font-size: 13px; }
+.user-details {
+ font-size: 13px;
+}
.user-about {
- background-color: #EEEEEE;
- height: 200px;
- line-height: 20px;
- overflow: auto;
- padding: 10px;
- width: 90%;
+ background-color: #EEEEEE;
+ height: 200px;
+ line-height: 20px;
+ overflow: auto;
+ padding: 10px;
+ width: 90%;
}
.user-edit-link {
- background: url("../images/edit.png") no-repeat scroll 0 0 transparent;
- padding-left: 20px;
+ background: url("../images/edit.png") no-repeat scroll 0 0 transparent;
+ padding-left: 20px;
+}
+
+.user-info-table {
+ margin-bottom: 10px;
}
-.user-info-table { margin-bottom: 10px; }
-.relativetime { text-decoration: none; }
+.relativetime {
+ text-decoration: none;
+}
.answer-summary {
- clear: both;
- display: block;
- padding: 3px;
+ clear: both;
+ display: block;
+ padding: 3px;
}
.answer-votes {
- background-color: #EEEEEE;
- color: #555555;
- float: left;
- font-family: Arial;
- font-size: 110%;
- font-weight: bold;
- height: 15px;
- margin-right: 10px;
- padding: 4px 4px 5px;
- text-align: center;
- text-decoration: none;
- width: 20px;
+ background-color: #EEEEEE;
+ color: #555555;
+ float: left;
+ font-family: Arial;
+ font-size: 110%;
+ font-weight: bold;
+ height: 15px;
+ margin-right: 10px;
+ padding: 4px 4px 5px;
+ text-align: center;
+ text-decoration: none;
+ width: 20px;
}
.vote-count {
- color: #777777;
- font-family: Arial;
- font-size: 160%;
- font-weight: 700;
+ color: #777777;
+ font-family: Arial;
+ font-size: 160%;
+ font-weight: 700;
}
.user-action-1 {
- color: #333333;
- font-weight: bold;
+ color: #333333;
+ font-weight: bold;
}
.user-action-2 {
- color: #CCCCCC;
- font-weight: bold;
+ color: #CCCCCC;
+ font-weight: bold;
}
-.user-action-3 { color: #333333; }
-.user-action-4 { color: #333333; }
-.user-action-7 { color: #333333; }
+.user-action-3 {
+ color: #333333;
+}
+
+.user-action-4 {
+ color: #333333;
+}
+
+.user-action-7 {
+ color: #333333;
+}
.user-action-8 {
- background-color: #CCCCCC;
- color: #763333;
- font-weight: bold;
- padding: 3px;
+ background-color: #CCCCCC;
+ color: #763333;
+ font-weight: bold;
+ padding: 3px;
}
.question-title-link a {
- color: #0077CC;
- font-weight: bold;
+ color: #0077CC;
+ font-weight: bold;
+}
+
+.answer-title-link a {
+ color: #333333;
+}
+
+.post-type-1 a {
+ font-weight: bold;
+}
+
+.post-type-3 a {
+ font-weight: bold;
}
-.answer-title-link a { color: #333333; }
-.post-type-1 a { font-weight: bold; }
-.post-type-3 a { font-weight: bold; }
-.post-type-2 a { color: #333333; }
-.post-type-4 a { color: #333333; }
-.post-type-8 a { color: #333333; }
-.badge1 { color: #FFCC00; }
-.silver,.badge2 { color: #CCCCCC; }
-.bronze,.badge3 { color: #CC9933; }
+.post-type-2 a {
+ color: #333333;
+}
+
+.post-type-4 a {
+ color: #333333;
+}
+
+.post-type-8 a {
+ color: #333333;
+}
+
+.badge1 {
+ color: #FFCC00;
+}
+
+.silver, .badge2 {
+ color: #CCCCCC;
+}
+
+.bronze, .badge3 {
+ color: #CC9933;
+}
.score {
- color: #333333;
- font-size: 110%;
- font-weight: bold;
- margin-left: 3px;
+ color: #333333;
+ font-size: 110%;
+ font-weight: bold;
+ margin-left: 3px;
}
.footerLinks {
- color: #3060A8;
- font-size: 13px;
+ color: #3060A8;
+ font-size: 13px;
}
.footerLinks a {
- color: #3060A8;
- font-size: 13px;
+ color: #3060A8;
+ font-size: 13px;
}
.user {
- line-height: 140%;
- padding: 5px;
- width: 170px;
+ line-height: 140%;
+ padding: 5px;
+ width: 170px;
}
.user ul {
- list-style-type: none;
- margin: 0;
+ list-style-type: none;
+ margin: 0;
}
.user .thumb {
- clear: both;
- display: inline;
- float: left;
- margin-right: 4px;
+ clear: both;
+ display: inline;
+ float: left;
+ margin-right: 4px;
}
.message {
- background-color: #EEEEEE;
- border: 1px solid #AAAAAA;
- margin: 10px 0;
- padding: 5px;
+ background-color: #EEEEEE;
+ border: 1px solid #AAAAAA;
+ margin: 10px 0;
+ padding: 5px;
+}
+
+.message p {
+ margin-bottom: 0;
}
-.message p { margin-bottom: 0; }
-.darkred { color: darkred; }
+.darkred {
+ color: darkred;
+}
.submit {
- background-color: #D4D0C8;
- border: 1px solid #777777;
- cursor: pointer;
- font-size: 120%;
- font-weight: bold;
- height: 40px;
- padding-bottom: 4px;
+ background-color: #D4D0C8;
+ border: 1px solid #777777;
+ cursor: pointer;
+ font-size: 120%;
+ font-weight: bold;
+ height: 40px;
+ padding-bottom: 4px;
}
-.submit:hover { text-decoration: underline; }
-.ask-body { padding-right: 10px; }
+.submit:hover {
+ text-decoration: underline;
+}
+
+.ask-body {
+ padding-right: 10px;
+}
.notify {
- background-color: #F4A83D;
- color: #444444;
- font-weight: bold;
- left: 0;
- padding: 0;
- position: fixed;
- text-align: center;
- top: 0;
- width: 100%;
- z-index: 100;
+ background-color: #F4A83D;
+ color: #444444;
+ font-weight: bold;
+ left: 0;
+ padding: 0;
+ position: fixed;
+ text-align: center;
+ top: 0;
+ width: 100%;
+ z-index: 100;
}
.notify p {
- font-size: 16px;
- margin-bottom: 5px;
- margin-top: 5px;
+ font-size: 16px;
+ margin-bottom: 5px;
+ margin-top: 5px;
}
#close-notify {
- background-color: #FAD163;
- border: 2px solid #735005;
- color: #735005;
- cursor: pointer;
- font-size: 14px;
- line-height: 18px;
- padding: 0 3px;
- position: absolute;
- right: 5px;
- text-decoration: none;
- top: 5px;
-}
-
-#close-notify:hover { text-decoration: none; }
-.big { font-size: 15px; }
-.strong { font-weight: bold; }
+ background-color: #FAD163;
+ border: 2px solid #735005;
+ color: #735005;
+ cursor: pointer;
+ font-size: 14px;
+ line-height: 18px;
+ padding: 0 3px;
+ position: absolute;
+ right: 5px;
+ text-decoration: none;
+ top: 5px;
+}
+
+#close-notify:hover {
+ text-decoration: none;
+}
+
+.big {
+ font-size: 15px;
+}
+
+.strong {
+ font-weight: bold;
+}
.orange {
- color: #D64000;
- font-weight: bold;
+ color: #D64000;
+ font-weight: bold;
}
-.grey { color: #808080; }
+.grey {
+ color: #808080;
+}
.about div {
- border-top: 1px dashed #AAAAAA;
- padding: 10px 5px;
+ border-top: 1px dashed #AAAAAA;
+ padding: 10px 5px;
}
.about div.first {
- border-top: medium none;
- padding-top: 0;
+ border-top: medium none;
+ padding-top: 0;
}
-.about p { margin-bottom: 10px; }
+.about p {
+ margin-bottom: 10px;
+}
.about a {
- color: #D64000;
- text-decoration: underline;
+ color: #D64000;
+ text-decoration: underline;
}
.about h3 {
- font-size: 15px;
- font-weight: 700;
- line-height: 30px;
- padding-top: 0;
+ font-size: 15px;
+ font-weight: 700;
+ line-height: 30px;
+ padding-top: 0;
}
-.nomargin { margin: 0; }
-.inline-block { display: inline-block; }
-.list-table td { vertical-align: top; }
+.nomargin {
+ margin: 0;
+}
+
+.inline-block {
+ display: inline-block;
+}
+
+.list-table td {
+ vertical-align: top;
+}
table.form-as-table input {
- display: inline;
- margin-left: 4px;
+ display: inline;
+ margin-left: 4px;
}
ul.form-horizontal-rows {
- list-style: none outside none;
- margin: 0;
+ list-style: none outside none;
+ margin: 0;
}
ul.form-horizontal-rows li {
- height: 40px;
- position: relative;
+ height: 40px;
+ position: relative;
}
-ul.form-horizontal-rows label { display: inline-block; }
+ul.form-horizontal-rows label {
+ display: inline-block;
+}
ul.form-horizontal-rows label {
- bottom: 6px;
- font-size: 12px;
- left: 0;
- line-height: 12px;
- margin: 0;
- position: absolute;
+ bottom: 6px;
+ font-size: 12px;
+ left: 0;
+ line-height: 12px;
+ margin: 0;
+ position: absolute;
}
ul.form-horizontal-rows li input {
- bottom: 0;
- left: 180px;
- margin: 0;
- position: absolute;
+ bottom: 0;
+ left: 180px;
+ margin: 0;
+ position: absolute;
}
-#changepw-form li input { left: 150px; }
+#changepw-form li input {
+ left: 150px;
+}
.user-profile-tool-links {
- font-weight: bold;
- padding-bottom: 10px;
+ font-weight: bold;
+ padding-bottom: 10px;
}
.post-controls, .tags-container {
- font-size: 11px;
- line-height: 12px;
- margin-bottom: 5px;
- min-width: 200px;
+ font-size: 11px;
+ line-height: 12px;
+ margin-bottom: 5px;
+ min-width: 200px;
}
.tags-container {
- margin: 0 0 16px 0;
+ margin: 0 0 16px 0;
}
.post-controls {
float: left;
}
-#question-controls .tags { margin: 0 0 3px; }
+#question-controls .tags {
+ margin: 0 0 3px;
+}
.post-update-info {
- display: inline-block;
- float: right;
- margin-bottom: 5px;
- width: 190px;
+ display: inline-block;
+ float: right;
+ margin-bottom: 5px;
+ width: 190px;
}
.post-update-info p {
- font-size: 11px;
- line-height: 15px;
- margin: 0 0 4px;
- padding: 0;
+ font-size: 11px;
+ line-height: 15px;
+ margin: 0 0 4px;
+ padding: 0;
}
.post-update-info img {
- float: left;
- margin: 4px 8px 0 0;
- width: 32px;
+ float: left;
+ margin: 4px 8px 0 0;
+ width: 32px;
+}
+
+#tagSelector {
+ padding-bottom: 2px;
+}
+
+#hideIgnoredTagsControl {
+ margin: 5px 0 0;
}
-#tagSelector { padding-bottom: 2px; }
-#hideIgnoredTagsControl { margin: 5px 0 0; }
-#hideIgnoredTagsCb { margin: 0 2px 0 1px; }
+#hideIgnoredTagsCb {
+ margin: 0 2px 0 1px;
+}
a.sidebar_button {
- background: none repeat scroll 0 0 #EEEEEE;
- color: black;
- cursor: pointer;
- font-size: 11px;
- padding: 3px;
+ background: none repeat scroll 0 0 #EEEEEE;
+ color: black;
+ cursor: pointer;
+ font-size: 11px;
+ padding: 3px;
}
a.sidebar_button:hover {
- background-color: #777777;
- color: white;
- text-decoration: none;
+ background-color: #777777;
+ color: white;
+ text-decoration: none;
}
-a.post-vote,.favorite-mark,a.accept-answer {
- display: block;
- height: 24px;
- position: relative;
- width: 24px;
+a.post-vote, .favorite-mark, a.accept-answer {
+ display: block;
+ height: 24px;
+ position: relative;
+ width: 24px;
}
-a.post-vote.up { background: url("../images/vote-arrow-up.png") no-repeat scroll center center transparent; }
-a.post-vote.up.on,a.post-vote.up:hover { background: url("../images/vote-arrow-up-on.png") no-repeat scroll center center transparent; }
-a.post-vote.down { background: url("../images/vote-arrow-down.png") no-repeat scroll center center transparent; }
-a.post-vote.down.on,a.post-vote.down:hover { background: url("../images/vote-arrow-down-on.png") no-repeat scroll center center transparent; }
-a.accept-answer { background: url("../images/vote-accepted.png") no-repeat scroll center center transparent; }
-a.accept-answer.on,a.accept-answer:hover { background: url("../images/vote-accepted-on.png") no-repeat scroll center center transparent; }
+a.post-vote.up {
+ background: url("../images/vote-arrow-up.png") no-repeat scroll center center transparent;
+}
+
+a.post-vote.up.on, a.post-vote.up:hover {
+ background: url("../images/vote-arrow-up-on.png") no-repeat scroll center center transparent;
+}
+
+a.post-vote.down {
+ background: url("../images/vote-arrow-down.png") no-repeat scroll center center transparent;
+}
+
+a.post-vote.down.on, a.post-vote.down:hover {
+ background: url("../images/vote-arrow-down-on.png") no-repeat scroll center center transparent;
+}
+
+a.accept-answer {
+ background: url("../images/vote-accepted.png") no-repeat scroll center center transparent;
+}
+
+a.accept-answer.on, a.accept-answer:hover {
+ background: url("../images/vote-accepted-on.png") no-repeat scroll center center transparent;
+}
.community-wiki {
font-size: 11px;
}
.post-score, .comments-char-left-count {
- color: #777777;
- font-family: Arial;
- font-size: 165%;
- font-weight: bold;
- padding: 0 0 3px;
+ color: #777777;
+ font-family: Arial;
+ font-size: 165%;
+ font-weight: bold;
+ padding: 0 0 3px;
+}
+
+.favorite-mark {
+ background: url("../images/vote-favorite-off.png") no-repeat scroll center center transparent;
}
-.favorite-mark { background: url("../images/vote-favorite-off.png") no-repeat scroll center center transparent; }
-.favorite-mark.on,a.favorite-mark:hover { background: url("../images/vote-favorite-on.png") no-repeat scroll center center transparent; }
+.favorite-mark.on, a.favorite-mark:hover {
+ background: url("../images/vote-favorite-on.png") no-repeat scroll center center transparent;
+}
.favorite-count {
- color: #777777;
- font-family: Arial;
- font-size: 100%;
- font-weight: bold;
- padding: 0;
+ color: #777777;
+ font-family: Arial;
+ font-size: 100%;
+ font-weight: bold;
+ padding: 0;
}
-.comments-container { clear: both; }
-.comments-container { padding: 0; }
-.answered-by-owner .comments-container { background-color: #E6ECFF; }
-.accepted-answer .comments-container { background-color: #CCFFBF; }
+.comments-container {
+ clear: both;
+}
+
+.comments-container {
+ padding: 0;
+}
+
+.answered-by-owner .comments-container {
+ background-color: #E6ECFF;
+}
+
+.accepted-answer .comments-container {
+ background-color: #CCFFBF;
+}
.comment {
- border-top: 1px dotted #CCCCCE;
- margin: 0;
+ border-top: 1px dotted #CCCCCE;
+ margin: 0;
position: relative;
}
-.comment.not_top_scorer { display: none; }
+.comment.not_top_scorer {
+ display: none;
+}
.comment-score {
- color: #777777;
- font-family: Arial;
- font-size: 16px;
- font-weight: bold;
- padding-top: 3px;
- vertical-align: top;
+ color: #777777;
+ font-family: Arial;
+ font-size: 16px;
+ font-weight: bold;
+ padding-top: 3px;
+ vertical-align: top;
float: left;
- width: 22px;
+ width: 22px;
height: 100%;
text-align: center;
}
.comment-text {
- color: #444444;
- font-size: 12px;
- margin: 0 0 0 22px;
- padding: 0;
+ color: #444444;
+ font-size: 12px;
+ margin: 0 0 0 22px;
+ padding: 0;
}
.comment-text p {
}
.comment-info {
- font-size: 11px;
- margin: 0 0 4px 0;
+ font-size: 11px;
+ margin: 0 0 4px 0;
text-align: right;
height: 18px;
vertical-align: middle;
.comment-info * {
float: right;
- height: 18px;
- margin-left: 4px;
+ height: 18px;
+ margin-left: 4px;
+}
+
+a.comment-like, a.comment-delete, a.comment-edit {
+ margin-left: 2px;
+ width: 18px;
}
-a.comment-like,a.comment-delete,a.comment-edit {
- margin-left: 2px;
- width: 18px;
+a.comment-like {
+ background: url("../images/comment-like.png") no-repeat scroll center center transparent;
}
-a.comment-like { background: url("../images/comment-like.png") no-repeat scroll center center transparent; }
-a.comment-like:hover,a.comment-like.on { background: url("../images/comment-like-on.png") no-repeat scroll center center transparent; }
-a.comment-delete { background: url("../images/comment-delete.png") no-repeat scroll center center transparent; }
-a.comment-delete:hover { background: url("../images/comment-delete-hover.png") no-repeat scroll center center transparent; }
-a.comment-edit { background: url("../images/comment-edit.png") no-repeat scroll center center transparent; }
-a.comment-edit:hover { background: url("../images/comment-edit-hover.png") no-repeat scroll center center transparent; }
+a.comment-like:hover, a.comment-like.on {
+ background: url("../images/comment-like-on.png") no-repeat scroll center center transparent;
+}
+
+a.comment-delete {
+ background: url("../images/comment-delete.png") no-repeat scroll center center transparent;
+}
+
+a.comment-delete:hover {
+ background: url("../images/comment-delete-hover.png") no-repeat scroll center center transparent;
+}
+
+a.comment-edit {
+ background: url("../images/comment-edit.png") no-repeat scroll center center transparent;
+}
+
+a.comment-edit:hover {
+ background: url("../images/comment-edit-hover.png") no-repeat scroll center center transparent;
+}
.comment-form-container {
- display: none;
- padding-top: 12px;
+ display: none;
+ padding-top: 12px;
}
-.comment-form-widgets-container input { vertical-align: top; }
+.comment-form-widgets-container input {
+ vertical-align: top;
+}
.comment-form-widgets-container textarea {
- height: 80px;
- width: 80%;
+ height: 80px;
+ width: 80%;
float: left;
}
span.comment-chars-left {
- font-size: 11px;
- margin-right: 20px;
+ font-size: 11px;
+ margin-right: 20px;
}
div.comment-tools {
- border-top: 1px dotted #CCCCCE;
- padding-top: 12px;
- text-align: right;
+ border-top: 1px dotted #CCCCCE;
+ padding-top: 12px;
+ text-align: right;
}
div.comment-tools .comments-showing {
- color: #777777;
- font-size: 11px;
+ color: #777777;
+ font-size: 11px;
}
div.comment-tools a {
- background: none repeat scroll 0 0 #EEEEEE;
- color: black;
- cursor: pointer;
- font-size: 11px;
- padding: 3px;
+ background: none repeat scroll 0 0 #EEEEEE;
+ color: black;
+ cursor: pointer;
+ font-size: 11px;
+ padding: 3px;
}
div.comment-tools a:hover {
- background-color: #777777;
- color: white;
- text-decoration: none;
+ background-color: #777777;
+ color: white;
+ text-decoration: none;
}
.action-link {
- color: #777777;
- cursor: pointer;
- padding: 3px;
+ color: #777777;
+ cursor: pointer;
+ padding: 3px;
}
.action-link a {
}
.action-link a.ajax-command:hover {
- background-color: #777777;
- color: #FFFFFF;
- text-decoration: none;
+ background-color: #777777;
+ color: #FFFFFF;
+ text-decoration: none;
}
-.action-link-separator { color: #CCCCCC; }
+.action-link-separator {
+ color: #CCCCCC;
+}
-.deleted {background-color: #F4E7E7;}
+.deleted {
+ background-color: #F4E7E7;
+}
#command-loader {
position: fixed;
}
.comments-char-left-count.warn {
- color: orange;
+ color: orange;
}
#ask-related-questions {
.context-menu-dropdown li.item {
padding: 4px 8px 4px 8px;
- -moz-border-radius: 5px;
+ -moz-border-radius: 5px;
-webkit-border-radius: 5px;
}
.user-prompt .prompt-buttons {
text-align: right;
+}
+
+.suspended-user {
+ text-decoration: line-through;
}
\ No newline at end of file
--- /dev/null
+{% extends "base_content.html" %}
+{% load i18n %}
+{% block title %}{% trans "Forbidden" %}{% endblock %}
+{% block forestyle%}
+ <style type="text/css">
+ form input { margin-right: 5px; }
+ </style>
+{% endblock %}
+{% block forejs %}
+ <script type="text/javascript">
+ $().ready(function(){
+ $("#linkPrevious").bind("click", back=function(){history.go(-1);})
+ });
+
+ </script>
+{% endblock %}
+{% block content %}
+<div id="main-bar" class="headNormal">
+ {% trans "Forbidden" %}
+</div>
+<div id="main-body" class="">
+ <div style="padding:5px 0px 10px 0;line-height:25px;">
+ <h3>{% trans "Sorry, could not find the page you requested." %}</h3>
+ <div style="margin-top:5px">
+ {% trans "This might have happened for the following reasons:" %}<br/>
+ <ul>
+ <li>{% trans "this question or answer has been deleted;" %}</li>
+ <li>{% trans "url has error - please check it;" %}</li>
+ <li>{% trans "the page you tried to visit is protected or you don't have sufficient points, see" %} <a href="{% url faq %}"> faq</a>;</li>
+ <li>{% trans "if you believe this error 404 should not have occured, please" %}
+ <a href="{{feedback_site_url}}" target="_blank">{% trans "report this problem" %}</a></li>
+ </ul>
+ </div>
+ <script type="text/javascript">
+ var GOOG_FIXURL_LANG = '{{settings.LANGUAGE_CODE}}';
+ var GOOG_FIXURL_SITE = '{{site_url}}';
+ </script>
+ <script type="text/javascript" src="http://linkhelp.clients.google.com/tbproxy/lh/wm/fixurl.js"></script>
+ <ul>
+ <li><a href="#" id="linkPrevious">{% trans "back to previous page" %} È</a></li>
+ <li><a href="{% url questions %}">{% trans "see all questions" %} È</a></li>
+ <li><a href="{% url tags %}">{% trans "see all tags" %} È</a></li>
+ </ul>
+ </div>
+
+</div>
+{% endblock %}
{% extends "base_content.html" %}
<!-- template 404.html -->
{% load i18n %}
-{% block title %}{% spaceless %}404 Error{% endspaceless %}{% endblock %}
+{% block title %}{% trans "404 Error" %}{% endblock %}
{% block forestyle%}
<style type="text/css">
form input { margin-right: 5px; }
{% endblock %}
{% block content %}
<div id="main-bar" class="headNormal">
- 404 Not Found
+ {% trans "404 Not Found" %}
</div>
<div id="main-body" class="">
<div style="padding:5px 0px 10px 0;line-height:25px;">
<a href="#" class="add-comment-link">{% trans "add new comment" %}</a>\r
{% endif %}\r
</div>\r
-{% if can_comment %}\r
<div id="comment-{{ post.id }}-form-container" class="comment-form-container">\r
+ {% if can_comment %}\r
<form id="comment-{{ post.id }}-form" method="post" action="{% url comment id=post.id %}" accept-charset="utf-8">\r
<div class="comment-form-widgets-container">\r
<textarea name="comment"></textarea>\r
</div>\r
</script>\r
</form>\r
+ {% endif %}\r
</div>\r
-{% endif %}\r
\ No newline at end of file
<strong>{% diff_date node.added_at %}</strong>
</p>
{% gravatar node.author 32 %}
- <p><a href="{{ node.author.get_profile_url }}">{{ node.author.username }}</a><br/>
+ <p><a {% if node.author.is_suspended %}class="suspended-user" {% endif %}href="{{ node.author.get_profile_url }}">{{ node.author.username }}</a><br/>
{% get_score_badge node.author %}</p>
</div>
{% if node.last_edited %}
</p>
{% ifnotequal node.author node.last_edited.by %}
{% gravatar node.last_edited.by 32 %}
- <p><a href="{{ node.last_edited.by.get_profile_url }}">{{ node.last_edited.by.username }}</a><br/>
+ <p><a {% if node.last_edited.by.is_suspended %}class="suspended-user" {% endif %}href="{{ node.last_edited.by.get_profile_url }}">{{ node.last_edited.by.username }}</a><br/>
{% get_score_badge node.last_edited.by %}</p>
{% endifnotequal %}
</div>
<ul>
<li><a href="{% url admin_maintenance %}">{% trans "Maintenance mode" %}</a></li>
<li><a href="{% url admin_flagged_posts %}">{% trans "Flagged Posts" %}</a></li>
+ {% comment %}<li><a href="{% url admin_moderation %}">{% trans "Moderation" %}</a></li>{% endcomment %}
</ul>
</div>
</div>
--- /dev/null
+{% extends basetemplate %}
+
+{% load i18n humanize %}
+
+{% block subtitle %}{% trans "Moderation" %}{% endblock %}
+{% block pagename %}{% trans "Moderation" %}{% endblock %}
+{% block description %}{% trans "These tools allow you to search for undesired behaviours and cheating patterns." %}{% endblock %}
+
+{% block admincontent %}
+ <div class="module">
+ <form action="" id="changelist" method="POST">
+ <div class="actions">
+ {% trans "Verify:" %}
+ <input type="text" size="3" name="limit" id="filter-limit" value="5" />
+ <select name="sort" id="filter-sort">
+ <option value="high-rep">{% trans "highest ranking users" %}</option>
+ <option value="newer">{% trans "newer users" %}</option>
+ <option value="older">{% trans "older users" %}</option>
+ <option value="ids">{% trans "users with these ids" %}</option>
+ </select>
+ <span id="filter-ids" style="display: none">
+ <input type="text" name="ids" size="15" />
+ <small>{% trans "(Comma separated list of user ids)" %}</small>
+ </span>
+ <input type="submit" value="{% trans "Go" %}" />
+ </div>
+ </form>
+ <script type="text/javascript">
+ $(function() {
+ $limit = $('#filter-limit');
+ $sort = $('#filter-sort');
+ $ids = $('#filter-ids');
+
+ function verify_sort() {
+ if ($sort.val() == "ids") {
+ $ids.show();
+ $limit.hide();
+ } else {
+ $ids.hide();
+ $limit.show();
+ }
+ }
+
+ verify_sort();
+ $sort.change(verify_sort);
+ })
+ </script>
+ {% if cheaters %}
+ <table cellspacing="0" width="100%">
+ <caption>{% trans "Possible cheaters" %}</caption>
+ {% for cheater, fakes in cheaters %}
+ <tr>
+ <td>
+ <div class="cheater-info">
+ <p><a href="{{ cheater.get_profile_url }}">{{ cheater.username }}</a></p>
+ <p><b>{% trans "Email" %}</b>
+ {% if cheater.email_isvalid %}
+ <img src="{{ settings.ADMIN_MEDIA_PREFIX }}img/admin/icon-yes.gif" alt="{% trans "Validated" %}" />
+ {% else %}
+ <img src="{{ settings.ADMIN_MEDIA_PREFIX }}img/admin/icon-no.gif" alt="{% trans "Not validated" %}" />
+ {% endif %}
+ <a href="mailto: {{ cheater.email }}">{{ cheater.email }}</a></p>
+ <p><b>{% trans "Reputation:" %}</b> {{ cheater.reputation|intcomma }}</p>
+ </div>
+ <table cellspacing="0" width="100%">
+ <thead>
+ <tr>
+ <th>{% trans "Profile" %}</th>
+ <th>{% trans "Email" %}</th>
+ <th>{% trans "Reputation" %}</th>
+ <th>{% trans "Affecting actions" %}</th>
+ <th>{% trans "Cross ips" %}</th>
+ <th>{% trans "Cheating score" %}</th>
+ </tr>
+ </thead>
+ <caption>{% trans "Possible fake accounts" %}</caption>
+ {% for fake in fakes %}
+ <tr>
+ <td><a href="{{ fake.get_profile_url }}">{{ fake.username }}</a></td>
+ <td>
+ {% if fake.email_isvalid %}
+ <img src="{{ settings.ADMIN_MEDIA_PREFIX }}img/admin/icon-yes.gif" alt="{% trans "Validated" %}" />
+ {% else %}
+ <img src="{{ settings.ADMIN_MEDIA_PREFIX }}img/admin/icon-no.gif" alt="{% trans "Not validated" %}" />
+ {% endif %}
+ <a href="mailto: {{ fake.email }}">{{ fake.email }}</a>
+ </td>
+ <td>{{ fake.reputation|intcomma }}</td>
+ <td>{{ fake.fdata.affect_count }} {% trans "out of" %} {{ fake.fdata.total_actions }} ({{ fake.fdata.action_ratio|stringformat:".2f" }}%)</td>
+ <td>{{ fake.fdata.cross_ip_count }} {% trans "out of" %} {{ fake.fdata.total_ip_count }} ({{ fake.fdata.cross_ip_ratio|stringformat:".2f" }}%)</td>
+ <td>{{ fake.fdata.fake_score|stringformat:".2f" }}</td>
+ </tr>
+ {% endfor %}
+ </table>
+ </td>
+ </tr>
+ {% endfor %}
+ </table>
+ {% endif %}
+ </div>
+{% endblock %}
\ No newline at end of file
{% load i18n %}\r
{% load smart_if %}\r
\r
+<script type="text/javascript">\r
+ messages['points'] = "{% trans "Points" %}"\r
+</script>\r
+\r
<div id="user-menu-container">\r
<span id="user-menu">{% trans "User tools" %} ▼</span>\r
<ul id="user-menu-dropdown">\r
{% ifnotequal user viewer %}\r
{% if viewer.is_superuser %}\r
<li class="separator">{% trans "Moderation tools" %}</li>\r
+ {% if not user.is_superuser %}\r
+ {% if user.is_suspended %}\r
+ <li class="item"><span></span>\r
+ <a href="{% url user_suspend id=user.id %}" class="ajax-command confirm" id="suspend-user">{% trans "withdraw suspension" %}</a>\r
+ </li>\r
+ {% else %}\r
+ <li class="item"><span></span>\r
+ <a href="{% url user_suspend id=user.id %}" class="ajax-command withprompt" id="suspend-user">{% trans "suspend this user" %}</a>\r
+ </li>\r
+ {% endif %}\r
+ {% endif %}\r
+\r
<li class="item"><span class="user-award_rep"></span><a href="{% url user_award_points id=user.id %}" id="award-rep-points">{% trans "reputation bonus" %}</a></li>\r
{% if not user.is_superuser %}\r
{% if not user.is_staff %}\r
</ul>\r
</div>\r
\r
-{% comment %}\r
-<h3>{% trans "Moderation tools" %}</h3>\r
-<p><a href="#" id="point-award-action">{% trans "Reputation bonus" %}</a></p>\r
-<form action="" method="POST">\r
- <table style="display: none" id="award-points-table" class="moderation-table">\r
- {{ awardform.as_table }}\r
- <tr><td colspan="2" class="moderation-table-footer"><input type="submit" id="award-points-submit" value="{% trans "Send" %}" /></td></tr>\r
- </table> \r
-</form>\r
-<script>\r
- $(function() {\r
- $('#point-award-action').click(function() {\r
- $('#award-points-table').slideToggle('slow');\r
- });\r
-\r
- $('#award-points-submit').click(function() {\r
- $('#award-points-table').find('.error').remove();\r
- var $points_input = $('#award-points-table').find('input[type=text]');\r
- var points = parseInt($points_input.val());\r
-\r
- if (isNaN(points) || points < 1) {\r
- $points_input.before('<p class="error">{% trans "Sorry but that\'s not a valid input" %}</p>');\r
- return false;\r
- }\r
-\r
- $.post('{% url user_award_points id=user.id %}')\r
- });\r
- });\r
-</script>\r
-{% if not user.is_superuser %}\r
-<p><a href="{% url user_powers id=user.id,action="grant",status="super" %}">{% trans "Grant super user status" %}</a></p>\r
- {% if not user.is_staff %}\r
- <p><a href="{% url user_powers id=user.id,action="grant",status="staff" %}">{% trans "Grant moderator status" %}</a></p>\r
- {% else %}\r
- <p><a href="{% url user_powers id=user.id,action="remove",status="staff" %}" class="">{% trans "Remove moderator status" %}</a></p>\r
- {% endif %}\r
-{% else %}\r
- {% ifequal moderator.id 1 %}\r
- {% ifnotequal user.id 1 %}\r
- <p><a href="{% url user_powers id=user.id,action="remove",status="super" %}">{% trans "Remove super user status" %}</a></p>\r
- {% endifnotequal %}\r
- {% endifequal %}\r
-{% endif %}\r
-\r
-{% endcomment %}\r
{% load i18n %}{% spaceless %}\r
-{% ifequal format "full" %}\r
\r
-{% else %}\r
- <a href="{{ user.get_absolute_url }}">{{ user.username }}</a>\r
- <span class="score" title="{{ user.reputation }} {% trans "reputation" %}">{{ user.reputation }}</span>\r
- {% ifequal format "badges" %}\r
- {% if user.gold %}\r
- <span title="{{ user.gold }} {% trans "badges" %}">\r
- <span class="badge1">●</span>\r
- <span class="badgecount">{{ user.gold }}</span>\r
- </span>\r
- {% endif %}\r
- {% if user.silver %}\r
- <span title="{{ user.silver }} {% trans "badges" %}">\r
- <span class="silver">●</span>\r
- <span class="badgecount">{{ user.silver }}</span>\r
- </span>\r
- {% endif %}\r
- {% if user.bronze %}\r
- <span title="{{ user.bronze }} {% trans "badges" %}">\r
- <span class="bronze">●</span>\r
- <span class="badgecount">{{ user.bronze }}</span>\r
- </span>\r
- {% endif %}\r
+{% if not user.is_suspended %}\r
+ {% ifequal format "full" %}\r
+\r
+ {% else %}\r
+ <a href="{{ user.get_absolute_url }}">{{ user.username }}</a>\r
+ <span class="score" title="{{ user.reputation }} {% trans "reputation" %}">{{ user.reputation }}</span>\r
+ {% ifequal format "badges" %}\r
+ {% if user.gold %}\r
+ <span title="{{ user.gold }} {% trans "badges" %}">\r
+ <span class="badge1">●</span>\r
+ <span class="badgecount">{{ user.gold }}</span>\r
+ </span>\r
+ {% endif %}\r
+ {% if user.silver %}\r
+ <span title="{{ user.silver }} {% trans "badges" %}">\r
+ <span class="silver">●</span>\r
+ <span class="badgecount">{{ user.silver }}</span>\r
+ </span>\r
+ {% endif %}\r
+ {% if user.bronze %}\r
+ <span title="{{ user.bronze }} {% trans "badges" %}">\r
+ <span class="bronze">●</span>\r
+ <span class="badgecount">{{ user.bronze }}</span>\r
+ </span>\r
+ {% endif %}\r
+ {% endifequal %}\r
{% endifequal %}\r
-{% endifequal %}\r
-{% endspaceless %}
\ No newline at end of file
+{% else %}\r
+ <a class="suspended-user" href="{{ user.get_absolute_url }}">{{ user.username }}</a>{% trans "(suspended)" %}\r
+{% endif %}\r
+{% endspaceless %}\r
--- /dev/null
+{% load i18n %}
+
+<table>
+ <caption><h2>{% trans "Suspend user" %}</h2></caption>
+ <tr>
+ <td>
+ <select name="bantype" id="bantype">
+ <option value="indefinitely">{% trans "Indefinetly" %}</option>
+ <option value="forxdays">{% trans "For X days" %}</option>
+ </select>
+ </td>
+ </tr>
+ <tr id="forxdays" style="display: none">
+ <td>
+ {% trans "Suspend for" %}<input type="text" size="3" style="width: 30px; height: 1.2em; margin: 0 0.5em 0 0.5em; font-size: 1em;" name="forxdays" value="3" />{% trans "days" %}
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <p><b>{% trans "Public message" %}:</b></p>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <textarea rows="3" name="publicmsg" cols="35"></textarea><br />
+ <small>{% trans "This message will be visible through the user activity log." %}</small>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <p><b>{% trans "Private message" %}:</b></p>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <textarea rows="3" name="privatemsg" cols="35"></textarea><br />
+ <small>{% trans "If set, only the suspended user will see this message." %}</small>
+ </td>
+ </tr>
+</table>
+<script type="text/javascript">
+ $('#bantype').change(function() {
+ if ($(this).val() == 'forxdays') {
+ $('#forxdays').slideDown('fast');
+ } else {
+ $('#forxdays').slideUp('fast');
+ }
+ });
+</script>
\ No newline at end of file
<div class="user">
<ul>
- <li class="thumb"><a href=" {{ user.get_profile_url }} ">{% gravatar user 32 %}</a></li>
- <li><a href=" {{ user.get_profile_url }} ">{{ user.get_profile_link }}</a></li>
- <li>{% get_score_badge user %}</li>
- </ul>
+ <li class="thumb"><a href="{{ user.get_profile_url }} ">{% gravatar user 32 %}</a></li>
+ <li><a {% if user.is_suspended %}class="suspended-user" {% endif %}href=" {{ user.get_profile_url }} ">{{ user.get_profile_link }}</a></li>
+ <li>{% get_score_badge user %}</li>
+ </ul>
</div>
{% if forloop.counter|divisibleby:"7" %}
@register.simple_tag
def get_score_badge(user):
+ if user.is_suspended():
+ return _("(suspended)")
+
BADGE_TEMPLATE = '<span class="score" title="%(reputation)s %(reputationword)s">%(reputation)s</span>'
if user.gold > 0 :
BADGE_TEMPLATE = '%s%s' % (BADGE_TEMPLATE, '<span title="%(gold)s %(badgesword)s">'
admin.autodiscover()
feeds = {
- 'rss': RssLastestQuestionsFeed
+'rss': RssLastestQuestionsFeed
}
sitemaps = {
- 'questions': QuestionsSitemap
+'questions': QuestionsSitemap
}
APP_PATH = os.path.dirname(__file__)
urlpatterns += pattern
urlpatterns += patterns('',
- url(r'^$', app.readers.index, name='index'),
- url(r'^sitemap.xml$', 'django.contrib.sitemaps.views.sitemap', {'sitemaps': sitemaps}, name='sitemap'),
-
- (r'^favicon\.ico$', app.meta.favicon),
- url(r'^cstyle\.css$', app.meta.custom_css, name="custom_css"),
-
- url(r'^m/(?P<skin>\w+)/media/(?P<path>.*)$', app.meta.media , name='osqa_media'),
- url(r'^%s(?P<path>.*)$' % _('upfiles/'), 'django.views.static.serve',
- {'document_root': os.path.join(APP_PATH,'upfiles').replace('\\','/')},
- name='uploaded_file',
- ),
-
- url(r'^%s$' % _('faq/'), app.meta.static, {'content': settings.FAQ_PAGE_TEXT, 'title': _('FAQ')}, name='faq'),
- url(r'^%s$' % _('about/'), app.meta.static, {'content': settings.ABOUT_PAGE_TEXT, 'title': _('About')}, name='about'),
- url(r'^%s$' % _('markdown_help/'), app.meta.markdown_help, name='markdown_help'),
- url(r'^opensearch\.xml$', app.meta.opensearch, name='opensearch'),
- url(r'^%s$' % _('privacy/'), app.meta.privacy, name='privacy'),
- url(r'^%s$' % _('logout/'), app.meta.logout, name='logout'),
- url(r'^%s(?P<id>\d+)/%s$' % (_('answers/'), _('edit/')), app.writers.edit_answer, name='edit_answer'),
- url(r'^%s(?P<id>\d+)/$' % _('revisions/'), app.readers.revisions, name='revisions'),
- url(r'^%s$' % _('questions/'), app.readers.questions, name='questions'),
- url(r'^%s%s$' % (_('questions/'), _('ask/')), app.writers.ask, name='ask'),
- url(r'^%s%s$' % (_('questions/'), _('related_questions/')), app.commands.related_questions, name='related_questions'),
-
- url(r'^%s%s$' % (_('questions/'), _('unanswered/')), app.readers.unanswered, name='unanswered'),
- url(r'^%s(?P<id>\d+)/%s$' % (_('questions/'), _('edit/')), app.writers.edit_question, name='edit_question'),
- url(r'^%s(?P<id>\d+)/%s$' % (_('questions/'), _('close/')), app.commands.close, kwargs=dict(close=True), name='close'),
- url(r'^%s(?P<id>\d+)/%s$' % (_('questions/'), _('reopen/')), app.commands.close, kwargs=dict(close=False), name='reopen'),
- url(r'^%s(?P<id>\d+)/%s$' % (_('questions/'), _('answer/')), app.writers.answer, name='answer'),
-
- url(r'^%s(?P<id>\d+)/(?P<vote_type>[a-z]+)/' % _('vote/'), app.commands.vote_post, name='vote_post'),
- url(r'^%s(?P<id>\d+)/$' % _('like_comment/'), app.commands.like_comment, name="like_comment"),
- url(r'^%s(?P<id>\d+)/' % _('comment/'), app.commands.comment, name='comment'),
- url(r'^%s(?P<id>\d+)/$' % _('delete_comment/'), app.commands.delete_comment, name="delete_comment"),
- url(r'^%s(?P<id>\d+)/$' % _('accept_answer/'), app.commands.accept_answer, name="accept_answer"),
- url(r'^%s(?P<id>\d+)/$' % _('mark_favorite/'), app.commands.mark_favorite, name="mark_favorite"),
- url(r'^%s(?P<id>\d+)/' % _('flag/'), app.commands.flag_post, name='flag_post'),
- url(r'^%s(?P<id>\d+)/' % _('delete/'), app.commands.delete_post, name='delete_post'),
- url(r'^%s(?P<id>\d+)/$' % _('subscribe/'), app.commands.subscribe, name="subscribe"),
- url(r'^%s' % _('matching_tags/'), app.commands.matching_tags, name='matching_tags'),
- url(r'^%s(?P<id>\d+)/' % _('node_markdown/'), app.commands.node_markdown, name='node_markdown'),
- url(r'^%s(?P<id>\d+)/' % _('convert/'), app.commands.convert_to_comment, name='convert_to_comment'),
- url(r'^%s(?P<id>\d+)/' % _('wikify/'), app.commands.wikify, name='wikify'),
-
- url(r'^%s(?P<id>\d+)/(?P<slug>[\w-]*)$' % _('question/'), 'django.views.generic.simple.redirect_to', {'url': '/questions/%(id)s/%(slug)s'}),
- url(r'^%s(?P<id>\d+)/(?P<slug>[\w-]*)$' % _('questions/'), app.readers.question, name='question'),
- url(r'^%s$' % _('tags/'), app.readers.tags, name='tags'),
- url(r'^%s(?P<tag>.*)/$' % _('tags/'), app.readers.tag, name='tag_questions'),
-
- url(r'^%s%s(?P<tag>[^/]+)/$' % (_('mark-tag/'),_('interesting/')), app.commands.mark_tag, \
+ url(r'^$', app.readers.index, name='index'),
+ url(r'^sitemap.xml$', 'django.contrib.sitemaps.views.sitemap', {'sitemaps': sitemaps},
+ name='sitemap'),
+
+ (r'^favicon\.ico$', app.meta.favicon),
+ url(r'^cstyle\.css$', app.meta.custom_css, name="custom_css"),
+
+ url(r'^m/(?P<skin>\w+)/media/(?P<path>.*)$', app.meta.media , name='osqa_media'),
+ url(r'^%s(?P<path>.*)$' % _('upfiles/'), 'django.views.static.serve',
+ {'document_root': os.path.join(APP_PATH, 'upfiles').replace('\\', '/')},
+ name='uploaded_file',
+ ),
+
+ url(r'^%s$' % _('faq/'), app.meta.static, {'content': settings.FAQ_PAGE_TEXT, 'title': _('FAQ')}
+ , name='faq'),
+ url(r'^%s$' % _('about/'), app.meta.static,
+ {'content': settings.ABOUT_PAGE_TEXT, 'title': _('About')}, name='about'),
+ url(r'^%s$' % _('markdown_help/'), app.meta.markdown_help, name='markdown_help'),
+ url(r'^opensearch\.xml$', app.meta.opensearch, name='opensearch'),
+ url(r'^%s$' % _('privacy/'), app.meta.privacy, name='privacy'),
+ url(r'^%s$' % _('logout/'), app.meta.logout, name='logout'),
+ url(r'^%s(?P<id>\d+)/%s$' % (_('answers/'), _('edit/')), app.writers.edit_answer,
+ name='edit_answer'),
+ url(r'^%s(?P<id>\d+)/$' % _('revisions/'), app.readers.revisions, name='revisions'),
+ url(r'^%s$' % _('questions/'), app.readers.questions, name='questions'),
+ url(r'^%s%s$' % (_('questions/'), _('ask/')), app.writers.ask, name='ask'),
+ url(r'^%s%s$' % (_('questions/'), _('related_questions/')), app.commands.related_questions,
+ name='related_questions'),
+
+ url(r'^%s%s$' % (_('questions/'), _('unanswered/')), app.readers.unanswered, name='unanswered'),
+ url(r'^%s(?P<id>\d+)/%s$' % (_('questions/'), _('edit/')), app.writers.edit_question,
+ name='edit_question'),
+ url(r'^%s(?P<id>\d+)/%s$' % (_('questions/'), _('close/')), app.commands.close,
+ kwargs=dict(close=True), name='close'),
+ url(r'^%s(?P<id>\d+)/%s$' % (_('questions/'), _('reopen/')), app.commands.close,
+ kwargs=dict(close=False), name='reopen'),
+ url(r'^%s(?P<id>\d+)/%s$' % (_('questions/'), _('answer/')), app.writers.answer, name='answer'),
+
+ url(r'^%s(?P<id>\d+)/(?P<vote_type>[a-z]+)/' % _('vote/'), app.commands.vote_post,
+ name='vote_post'),
+ url(r'^%s(?P<id>\d+)/$' % _('like_comment/'), app.commands.like_comment, name="like_comment"),
+ url(r'^%s(?P<id>\d+)/' % _('comment/'), app.commands.comment, name='comment'),
+ url(r'^%s(?P<id>\d+)/$' % _('delete_comment/'), app.commands.delete_comment,
+ name="delete_comment"),
+ url(r'^%s(?P<id>\d+)/$' % _('accept_answer/'), app.commands.accept_answer, name="accept_answer")
+ ,
+ url(r'^%s(?P<id>\d+)/$' % _('mark_favorite/'), app.commands.mark_favorite, name="mark_favorite")
+ ,
+ url(r'^%s(?P<id>\d+)/' % _('flag/'), app.commands.flag_post, name='flag_post'),
+ url(r'^%s(?P<id>\d+)/' % _('delete/'), app.commands.delete_post, name='delete_post'),
+ url(r'^%s(?P<id>\d+)/$' % _('subscribe/'), app.commands.subscribe, name="subscribe"),
+ url(r'^%s' % _('matching_tags/'), app.commands.matching_tags, name='matching_tags'),
+ url(r'^%s(?P<id>\d+)/' % _('node_markdown/'), app.commands.node_markdown, name='node_markdown'),
+ url(r'^%s(?P<id>\d+)/' % _('convert/'), app.commands.convert_to_comment,
+ name='convert_to_comment'),
+ url(r'^%s(?P<id>\d+)/' % _('wikify/'), app.commands.wikify, name='wikify'),
+
+ url(r'^%s(?P<id>\d+)/(?P<slug>[\w-]*)$' % _('question/'),
+ 'django.views.generic.simple.redirect_to', {'url': '/questions/%(id)s/%(slug)s'}),
+ url(r'^%s(?P<id>\d+)/(?P<slug>[\w-]*)$' % _('questions/'), app.readers.question, name='question'
+ ),
+ url(r'^%s$' % _('tags/'), app.readers.tags, name='tags'),
+ url(r'^%s(?P<tag>.*)/$' % _('tags/'), app.readers.tag, name='tag_questions'),
+
+ url(r'^%s%s(?P<tag>[^/]+)/$' % (_('mark-tag/'),_('interesting/')), app.commands.mark_tag, \
kwargs={'reason':'good','action':'add'}, \
name='mark_interesting_tag'),
- url(r'^%s%s(?P<tag>[^/]+)/$' % (_('mark-tag/'),_('ignored/')), app.commands.mark_tag, \
+ url(r'^%s%s(?P<tag>[^/]+)/$' % (_('mark-tag/'),_('ignored/')), app.commands.mark_tag, \
kwargs={'reason':'bad','action':'add'}, \
name='mark_ignored_tag'),
- url(r'^%s(?P<tag>[^/]+)/$' % _('unmark-tag/'), app.commands.mark_tag, \
+ url(r'^%s(?P<tag>[^/]+)/$' % _('unmark-tag/'), app.commands.mark_tag, \
kwargs={'action':'remove'}, \
name='mark_ignored_tag'),
-
- url(r'^%s$' % _('users/'),app.users.users, name='users'),
- url(r'^%s(?P<id>\d+)/%s$' % (_('users/'), _('edit/')), app.users.edit_user, name='edit_user'),
- url(r'^%s(?P<id>\d+)/%s$' % (_('users/'), _('award/')), app.users.award_points, name='user_award_points'),
- url(r'^%s(?P<id>\d+)/%s(?P<action>[a-z]+)/(?P<status>[a-z]+)/$' % (_('users/'), _('powers/')), app.users.user_powers, name='user_powers'),
- url(r'^%s(?P<id>\d+)/%s$' % (_('users/'), _('subscriptions/')), app.users.user_subscriptions, name='user_subscriptions'),
- url(r'^%s(?P<id>\d+)/(?P<slug>.+)/%s$' % (_('users/'), _('favorites/')), app.users.user_favorites, name='user_favorites'),
- url(r'^%s(?P<id>\d+)/(?P<slug>.+)/%s$' % (_('users/'), _('reputation/')), app.users.user_reputation, name='user_reputation'),
- url(r'^%s(?P<id>\d+)/(?P<slug>.+)/%s$' % (_('users/'), _('votes/')), app.users.user_votes, name='user_votes'),
- url(r'^%s(?P<id>\d+)/(?P<slug>.+)/%s$' % (_('users/'), _('recent/')), app.users.user_recent, name='user_recent'),
- url(r'^%s(?P<id>\d+)/(?P<slug>.+)/$' % _('users/'), app.users.user_stats, name='user_profile'),
-
- url(r'^%s$' % _('badges/'),app.meta.badges, name='badges'),
- url(r'^%s(?P<id>\d+)/(?P<slug>.+)/$' % _('badges/'), app.meta.badge, name='badge'),
- # (r'^admin/doc/' % _('admin/doc'), include('django.contrib.admindocs.urls')),
- url(r'^%s(.*)' % _('nimda/'), admin.site.root, name='osqa_admin'),
- url(r'^feeds/(?P<url>.*)/$', 'django.contrib.syndication.views.feed', {'feed_dict': feeds}, name='feeds'),
- url(r'^%s$' % _('upload/'), app.writers.upload, name='upload'),
- url(r'^%s$' % _('search/'), app.readers.search, name='search'),
- url(r'^%s$' % _('contact/'), app.meta.feedback, name='feedback'),
-
- (r'^i18n/', include('django.conf.urls.i18n')),
-
- url(r'^%s%s$' % (_('account/'), _('signin/')), app.auth.signin_page, name='auth_signin'),
- url(r'^%s%s$' % (_('account/'), _('signout/')), app.auth.signout, name='user_signout'),
- url(r'^%s%s(?P<action>\w+)/$' % (_('account/'), _('signin/')), app.auth.signin_page, name='auth_action_signin'),
- url(r'^%s(?P<provider>\w+)/%s$' % (_('account/'), _('signin/')), app.auth.prepare_provider_signin, name='auth_provider_signin'),
- url(r'^%s(?P<provider>\w+)/%s$' % (_('account/'), _('done/')), app.auth.process_provider_signin, name='auth_provider_done'),
- url(r'^%s%s$' % (_('account/'), _('register/')), app.auth.external_register, name='auth_external_register'),
- url(r'^%s%s(?P<user>\d+)/(?P<code>.+)/$' % (_('account/'), _('validate/')), app.auth.validate_email, name="auth_validate_email"),
- url(r'^%s%s$' % (_('account/'), _('tempsignin/')), app.auth.request_temp_login, name="auth_request_tempsignin"),
- url(r'^%s%s(?P<user>\d+)/(?P<code>.+)/$' % (_('account/'), _('tempsignin/')), app.auth.temp_signin, name="auth_tempsignin"),
- url(r'^%s(?P<id>\d+)/%s$' % (_('account/'), _('authsettings/')), app.auth.auth_settings, name='user_authsettings'),
- url(r'^%s%s(?P<id>\d+)/%s$' % (_('account/'), _('providers/'), _('remove/')), app.auth.remove_external_provider, name='user_remove_external_provider'),
- url(r'^%s%s%s$' % (_('account/'), _('providers/'), _('add/')), app.auth.signin_page, name='user_add_external_provider'),
-
-
- url(r'^%s$' % _('admin/'), app.admin.dashboard, name="admin_index"),
- url(r'^%s%s$' % (_('admin/'), _('switch_interface/')), app.admin.interface_switch, name="admin_switch_interface"),
- url(r'^%s%s$' % (_('admin/'), _('statistics/')), app.admin.statistics, name="admin_statistics"),
- url(r'^%s%s$' % (_('admin/'), _('denormalize/')), app.admin.recalculate_denormalized, name="admin_denormalize"),
- url(r'^%s%s$' % (_('admin/'), _('go_bootstrap/')), app.admin.go_bootstrap, name="admin_go_bootstrap"),
- url(r'^%s%s$' % (_('admin/'), _('go_defaults/')), app.admin.go_defaults, name="admin_go_defaults"),
- url(r'^%s%s(?P<set_name>\w+)/(?P<var_name>\w+)/$' % (_('admin/'), _('settings/')), app.admin.get_default, name="admin_default"),
- url(r'^%s%s$' % (_('admin/'), _('maintenance/')), app.admin.maintenance, name="admin_maintenance"),
- url(r'^%s%s$' % (_('admin/'), _('flagged_posts/')), app.admin.flagged_posts, name="admin_flagged_posts"),
- url(r'^%s%s$' % (_('admin/'), _('static_pages/')), app.admin.static_pages, name="admin_static_pages"),
-
- url(r'^%s%s%s$' % (_('admin/'), _('static_pages/'), _('new/')), app.admin.edit_page, name="admin_new_page"),
- url(r'^%s%s%s(?P<id>\d+)/$' % (_('admin/'), _('static_pages/'), _('edit/')), app.admin.edit_page, name="admin_edit_page"),
-
- url(r'^%s%s(?P<set_name>\w+)/$' % (_('admin/'), _('settings/')), app.admin.settings_set, name="admin_set"),
-
- url(r'^feeds/rss/$', RssLastestQuestionsFeed, name="latest_questions_feed"),
-
- url(r'^(?P<path>.+)$', app.meta.page, name="static_page")
-)
+ url(r'^%s$' % _('users/'), app.users.users, name='users'),
+ url(r'^%s(?P<id>\d+)/%s$' % (_('users/'), _('edit/')), app.users.edit_user, name='edit_user'),
+ url(r'^%s(?P<id>\d+)/%s$' % (_('users/'), _('award/')), app.users.award_points,
+ name='user_award_points'),
+ url(r'^%s(?P<id>\d+)/%s$' % (_('users/'), _('suspend/')), app.users.suspend, name='user_suspend'
+ ),
+ url(r'^%s(?P<id>\d+)/%s(?P<action>[a-z]+)/(?P<status>[a-z]+)/$' % (_('users/'), _('powers/')),
+ app.users.user_powers, name='user_powers'),
+ url(r'^%s(?P<id>\d+)/%s$' % (_('users/'), _('subscriptions/')), app.users.user_subscriptions,
+ name='user_subscriptions'),
+ url(r'^%s(?P<id>\d+)/(?P<slug>.+)/%s$' % (_('users/'), _('favorites/')),
+ app.users.user_favorites, name='user_favorites'),
+ url(r'^%s(?P<id>\d+)/(?P<slug>.+)/%s$' % (_('users/'), _('reputation/')),
+ app.users.user_reputation, name='user_reputation'),
+ url(r'^%s(?P<id>\d+)/(?P<slug>.+)/%s$' % (_('users/'), _('votes/')), app.users.user_votes,
+ name='user_votes'),
+ url(r'^%s(?P<id>\d+)/(?P<slug>.+)/%s$' % (_('users/'), _('recent/')), app.users.user_recent,
+ name='user_recent'),
+ url(r'^%s(?P<id>\d+)/(?P<slug>.+)/$' % _('users/'), app.users.user_stats, name='user_profile'),
+
+ url(r'^%s$' % _('badges/'), app.meta.badges, name='badges'),
+ url(r'^%s(?P<id>\d+)/(?P<slug>.+)/$' % _('badges/'), app.meta.badge, name='badge'),
+ # (r'^admin/doc/' % _('admin/doc'), include('django.contrib.admindocs.urls')),
+ url(r'^%s(.*)' % _('nimda/'), admin.site.root, name='osqa_admin'),
+ url(r'^feeds/(?P<url>.*)/$', 'django.contrib.syndication.views.feed', {'feed_dict': feeds},
+ name='feeds'),
+ url(r'^%s$' % _('upload/'), app.writers.upload, name='upload'),
+ url(r'^%s$' % _('search/'), app.readers.search, name='search'),
+ url(r'^%s$' % _('contact/'), app.meta.feedback, name='feedback'),
+
+ (r'^i18n/', include('django.conf.urls.i18n')),
+
+ url(r'^%s%s$' % (_('account/'), _('signin/')), app.auth.signin_page, name='auth_signin'),
+ url(r'^%s%s$' % (_('account/'), _('signout/')), app.auth.signout, name='user_signout'),
+ url(r'^%s%s(?P<action>\w+)/$' % (_('account/'), _('signin/')), app.auth.signin_page,
+ name='auth_action_signin'),
+ url(r'^%s(?P<provider>\w+)/%s$' % (_('account/'), _('signin/')),
+ app.auth.prepare_provider_signin, name='auth_provider_signin'),
+ url(r'^%s(?P<provider>\w+)/%s$' % (_('account/'), _('done/')), app.auth.process_provider_signin,
+ name='auth_provider_done'),
+ url(r'^%s%s$' % (_('account/'), _('register/')), app.auth.external_register,
+ name='auth_external_register'),
+ url(r'^%s%s(?P<user>\d+)/(?P<code>.+)/$' % (_('account/'), _('validate/')),
+ app.auth.validate_email, name="auth_validate_email"),
+ url(r'^%s%s$' % (_('account/'), _('tempsignin/')), app.auth.request_temp_login,
+ name="auth_request_tempsignin"),
+ url(r'^%s%s(?P<user>\d+)/(?P<code>.+)/$' % (_('account/'), _('tempsignin/')),
+ app.auth.temp_signin, name="auth_tempsignin"),
+ url(r'^%s(?P<id>\d+)/%s$' % (_('account/'), _('authsettings/')), app.auth.auth_settings,
+ name='user_authsettings'),
+ url(r'^%s%s(?P<id>\d+)/%s$' % (_('account/'), _('providers/'), _('remove/')),
+ app.auth.remove_external_provider, name='user_remove_external_provider'),
+ url(r'^%s%s%s$' % (_('account/'), _('providers/'), _('add/')), app.auth.signin_page,
+ name='user_add_external_provider'),
+
+
+ url(r'^%s$' % _('admin/'), app.admin.dashboard, name="admin_index"),
+ url(r'^%s%s$' % (_('admin/'), _('switch_interface/')), app.admin.interface_switch,
+ name="admin_switch_interface"),
+ url(r'^%s%s$' % (_('admin/'), _('statistics/')), app.admin.statistics, name="admin_statistics"),
+ url(r'^%s%s$' % (_('admin/'), _('denormalize/')), app.admin.recalculate_denormalized,
+ name="admin_denormalize"),
+ url(r'^%s%s$' % (_('admin/'), _('go_bootstrap/')), app.admin.go_bootstrap,
+ name="admin_go_bootstrap"),
+ url(r'^%s%s$' % (_('admin/'), _('go_defaults/')), app.admin.go_defaults,
+ name="admin_go_defaults"),
+ url(r'^%s%s(?P<set_name>\w+)/(?P<var_name>\w+)/$' % (_('admin/'), _('settings/')),
+ app.admin.get_default, name="admin_default"),
+ url(r'^%s%s$' % (_('admin/'), _('maintenance/')), app.admin.maintenance,
+ name="admin_maintenance"),
+ url(r'^%s%s$' % (_('admin/'), _('flagged_posts/')), app.admin.flagged_posts,
+ name="admin_flagged_posts"),
+ url(r'^%s%s$' % (_('admin/'), _('static_pages/')), app.admin.static_pages,
+ name="admin_static_pages"),
+ url(r'^%s%s$' % (_('admin/'), _('moderation/')), app.admin.moderation, name="admin_moderation"),
+
+ url(r'^%s%s%s$' % (_('admin/'), _('static_pages/'), _('new/')), app.admin.edit_page,
+ name="admin_new_page"),
+ url(r'^%s%s%s(?P<id>\d+)/$' % (_('admin/'), _('static_pages/'), _('edit/')), app.admin.edit_page
+ , name="admin_edit_page"),
+
+ url(r'^%s%s(?P<set_name>\w+)/$' % (_('admin/'), _('settings/')), app.admin.settings_set,
+ name="admin_set"),
+
+ url(r'^feeds/rss/$', RssLastestQuestionsFeed, name="latest_questions_feed"),
+
+ url(r'^(?P<path>.+)$', app.meta.page, name="static_page")
+ )
from django.template import RequestContext
from django.utils.translation import ugettext as _
from django.utils import simplejson
-from django.db.models import Sum
+from django.db import models
from forum.settings.base import Setting
from forum.forms import MaintenanceModeForm, PageForm
from forum.settings.forms import SettingsSetForm
def recalculate_denormalized(request):
for n in Node.objects.all():
n = n.leaf
- n.score = n.votes.aggregate(score=Sum('value'))['score']
+ n.score = n.votes.aggregate(score=models.Sum('value'))['score']
if not n.score: n.score = 0
n.save()
for u in User.objects.all():
- u.reputation = u.reputes.aggregate(reputation=Sum('value'))['reputation']
+ u.reputation = u.reputes.aggregate(reputation=models.Sum('value'))['reputation']
u.save()
request.user.message_set.create(message=_('All values recalculated'))
'published': published
})
+@admin_page
+def moderation(request):
+ if request.POST:
+ if not 'ids' in request.POST:
+ verify = None
+ else:
+ sort = {
+ 'high-rep': '-reputation',
+ 'newer': '-date_joined',
+ 'older': 'date_joined',
+ }.get(request.POST.get('sort'), None)
+
+ if sort:
+ try:
+ limit = int(request.POST['limit'])
+ except:
+ limit = 5
+
+ verify = User.objects.order_by(sort)[:limit]
+ else:
+ verify = None
+
+ if verify:
+ possible_cheaters = []
+ verify = User.objects.order_by(sort)[:5]
+
+ cheat_score_sort = lambda c1, c2: cmp(c2.fdata['fake_score'], c1.fdata['fake_score'])
+
+ for user in verify:
+ possible_fakes = []
+ affecters = User.objects.filter(actions__node__author=user, actions__canceled=False).annotate(
+ affect_count=models.Count('actions')).order_by('-affect_count')
+ user_ips = set(Action.objects.filter(user=user).values_list('ip', flat=True).distinct('ip'))
+
+ for affecter in affecters:
+ if affecter == user:
+ continue
+
+ data = {'affect_count': affecter.affect_count}
+
+ total_actions = affecter.actions.filter(canceled=False).exclude(node=None).count()
+ ratio = (float(affecter.affect_count) / float(total_actions)) * 100
+
+ if total_actions > 10 and ratio > 50:
+ data['total_actions'] = total_actions
+ data['action_ratio'] = ratio
+
+ affecter_ips = set(
+ Action.objects.filter(user=affecter).values_list('ip', flat=True).distinct('ip'))
+ cross_ips = len(user_ips & affecter_ips)
+
+ data['cross_ip_count'] = cross_ips
+ data['total_ip_count'] = len(affecter_ips)
+ data['cross_ip_ratio'] = (float(data['cross_ip_count']) / float(data['total_ip_count'])) * 100
+
+ if affecter.email_isvalid:
+ email_score = 0
+ else:
+ email_score = 50.0
+
+ data['fake_score'] = ((data['cross_ip_ratio'] + data['action_ratio'] + email_score) / 100) * 4
+
+ affecter.fdata = data
+ possible_fakes.append(affecter)
+
+ if len(possible_fakes) > 0:
+ possible_fakes = sorted(possible_fakes, cheat_score_sort)
+ possible_cheaters.append((user, possible_fakes))
+
+ return ('osqaadmin/moderation.html', {'cheaters': possible_cheaters})
+
+ return ('osqaadmin/moderation.html', {})
+
from django.contrib.auth.decorators import login_required
from django.contrib.auth import login, logout
from django.http import get_host
+from forum.actions import SuspendAction
import types
import datetime
import logging
auth_provider = request.session['auth_provider']
except:
request.session['auth_error'] = _(
- "Oops, something went wrong in the middle of this process. Please try again.")
+ "Oops, something went wrong in the middle of this process. Please try again. Note that you need to have cookies enabled for the authentication to work."
+ )
logging.error("Missing session data when trying to complete user registration: %s" % ", ".join(
["%s: %s" % (k, v) for k, v in request.META.items()]))
return HttpResponseRedirect(reverse('auth_signin'))
if form.is_valid():
user = form.user_cache
+ if user.is_suspended():
+ return forward_suspended_user(request, user, False)
+
try:
hash = get_object_or_404(ValidationHash, user=user, type='templogin')
if hash.expiration < datetime.datetime.now():
}
def login_and_forward(request, user, forward=None, message=None):
- old_session = request.session.session_key
+ if user.is_suspended():
+ return forward_suspended_user(request, user)
+
user.backend = "django.contrib.auth.backends.ModelBackend"
login(request, user)
request.user.message_set.create(message=message)
return HttpResponseRedirect(forward)
-@login_required
-def signout(request):
- """
- signout from the website. Remove openid from session and kill it.
+def forward_suspended_user(request, user, show_private_msg=True):
+ message = _("Sorry, but this account is suspended")
+ if show_private_msg:
+ msg_type = 'privatemsg'
+ else:
+ msg_type = 'publicmsg'
+
+ suspension = user.suspension
+ if suspension:
+ message += (":<br />" + suspension.extra.get(msg_type, ''))
- url : /signout/"
- """
+ request.user.message_set.create(message)
+ return HttpResponseRedirect(reverse('index'))
+@login_required
+def signout(request):
logout(request)
return HttpResponseRedirect(reverse('index'))
\ No newline at end of file
from django.contrib.auth.decorators import login_required
from forum.utils.decorators import ajax_method, ajax_login_required
from forum.modules.decorators import decoratable
-from decorators import command, CommandException
+from decorators import command, CommandException, RefreshPageCommand
from forum import settings
import logging
class NotEnoughRepPointsException(CommandException):
def __init__(self, action):
super(NotEnoughRepPointsException, self).__init__(
- _("""Sorry, but you don't have enough reputation points to %(action)s.<br />Please check the <a href='%(faq_url)s'>faq</a>""") % {'action': action, 'faq_url': reverse('faq')}
- )
+ _(
+ """Sorry, but you don't have enough reputation points to %(action)s.<br />Please check the <a href='%(faq_url)s'>faq</a>"""
+ ) % {'action': action, 'faq_url': reverse('faq')}
+ )
class CannotDoOnOwnException(CommandException):
def __init__(self, action):
super(CannotDoOnOwnException, self).__init__(
- _("""Sorry but you cannot %(action)s your own post.<br />Please check the <a href='%(faq_url)s'>faq</a>""") % {'action': action, 'faq_url': reverse('faq')}
- )
+ _(
+ """Sorry but you cannot %(action)s your own post.<br />Please check the <a href='%(faq_url)s'>faq</a>"""
+ ) % {'action': action, 'faq_url': reverse('faq')}
+ )
class AnonymousNotAllowedException(CommandException):
def __init__(self, action):
super(AnonymousNotAllowedException, self).__init__(
- _("""Sorry but anonymous users cannot %(action)s.<br />Please login or create an account <a href='%(signin_url)s'>here</a>.""") % {'action': action, 'signin_url': reverse('auth_signin')}
- )
+ _(
+ """Sorry but anonymous users cannot %(action)s.<br />Please login or create an account <a href='%(signin_url)s'>here</a>."""
+ ) % {'action': action, 'signin_url': reverse('auth_signin')}
+ )
class NotEnoughLeftException(CommandException):
def __init__(self, action, limit):
super(NotEnoughLeftException, self).__init__(
- _("""Sorry, but you don't have enough %(action)s left for today..<br />The limit is %(limit)s per day..<br />Please check the <a href='%(faq_url)s'>faq</a>""") % {'action': action, 'limit': limit, 'faq_url': reverse('faq')}
- )
+ _(
+ """Sorry, but you don't have enough %(action)s left for today..<br />The limit is %(limit)s per day..<br />Please check the <a href='%(faq_url)s'>faq</a>"""
+ ) % {'action': action, 'limit': limit, 'faq_url': reverse('faq')}
+ )
class CannotDoubleActionException(CommandException):
def __init__(self, action):
super(CannotDoubleActionException, self).__init__(
- _("""Sorry, but you cannot %(action)s twice the same post.<br />Please check the <a href='%(faq_url)s'>faq</a>""") % {'action': action, 'faq_url': reverse('faq')}
- )
+ _(
+ """Sorry, but you cannot %(action)s twice the same post.<br />Please check the <a href='%(faq_url)s'>faq</a>"""
+ ) % {'action': action, 'faq_url': reverse('faq')}
+ )
@command
if old_vote.action_date < datetime.datetime.now() - datetime.timedelta(days=int(settings.DENY_UNVOTE_DAYS)):
raise CommandException(
_("Sorry but you cannot cancel a vote after %(ndays)d %(tdays)s from the original vote") %
- {'ndays': int(settings.DENY_UNVOTE_DAYS), 'tdays': ungettext('day', 'days', int(settings.DENY_UNVOTE_DAYS))}
- )
+ {'ndays': int(settings.DENY_UNVOTE_DAYS),
+ 'tdays': ungettext('day', 'days', int(settings.DENY_UNVOTE_DAYS))}
+ )
old_vote.cancel(ip=request.META['REMOTE_ADDR'])
score_inc += (old_vote.__class__ == VoteDownAction) and 1 or -1
vote_type = "none"
response = {
- 'commands': {
- 'update_post_score': [id, score_inc],
- 'update_user_post_vote': [id, vote_type]
- }
+ 'commands': {
+ 'update_post_score': [id, score_inc],
+ 'update_user_post_vote': [id, vote_type]
+ }
}
votes_left = (int(settings.MAX_VOTES_PER_DAY) - user_vote_count_today) + (vote_type == 'none' and -1 or 1)
try:
current = FlagAction.objects.get(canceled=False, user=user, node=post)
- raise CommandException(_("You already flagged this post with the following reason: %(reason)s") % {'reason': current.extra})
+ raise CommandException(
+ _("You already flagged this post with the following reason: %(reason)s") % {'reason': current.extra})
except ObjectDoesNotExist:
reason = request.POST.get('prompt', '').strip()
FlagAction(user=user, node=post, extra=reason, ip=request.META['REMOTE_ADDR']).save()
return {'message': _("Thank you for your report. A moderator will review your submission shortly.")}
-
+
@command
def like_comment(request, id):
comment = get_object_or_404(Comment, id=id)
raise CannotDoOnOwnException(_('like'))
if not user.can_like_comment(comment):
- raise NotEnoughRepPointsException( _('like comments'))
+ raise NotEnoughRepPointsException( _('like comments'))
like = VoteAction.get_action_for(node=comment, user=user)
likes = True
return {
- 'commands': {
- 'update_post_score': [comment.id, likes and 1 or -1],
- 'update_user_post_vote': [comment.id, likes and 'up' or 'none']
- }
+ 'commands': {
+ 'update_post_score': [comment.id, likes and 1 or -1],
+ 'update_user_post_vote': [comment.id, likes and 'up' or 'none']
+ }
}
@command
DeleteAction(node=comment, user=user, ip=request.META['REMOTE_ADDR']).save()
return {
- 'commands': {
- 'remove_comment': [comment.id],
- }
+ 'commands': {
+ 'remove_comment': [comment.id],
+ }
}
@command
added = True
return {
- 'commands': {
- 'update_favorite_count': [added and 1 or -1],
- 'update_favorite_mark': [added and 'on' or 'off']
- }
+ 'commands': {
+ 'update_favorite_count': [added and 1 or -1],
+ 'update_favorite_mark': [added and 'on' or 'off']
+ }
}
@decoratable
if not user.can_edit_comment(comment):
raise NotEnoughRepPointsException( _('edit comments'))
- comment = ReviseAction(user=user, node=comment, ip=request.META['REMOTE_ADDR']).save(data=dict(text=comment_text)).node
+ comment = ReviseAction(user=user, node=comment, ip=request.META['REMOTE_ADDR']).save(
+ data=dict(text=comment_text)).node
else:
if not user.can_comment(post):
raise NotEnoughRepPointsException( _('comment'))
- comment = CommentAction(user=user, ip=request.META['REMOTE_ADDR']).save(data=dict(text=comment_text, parent=post)).node
+ comment = CommentAction(user=user, ip=request.META['REMOTE_ADDR']).save(
+ data=dict(text=comment_text, parent=post)).node
if comment.active_revision.revision == 1:
return {
- 'commands': {
- 'insert_comment': [
- id, comment.id, comment.comment, user.username, user.get_profile_url(),
- reverse('delete_comment', kwargs={'id': comment.id}), reverse('node_markdown', kwargs={'id': comment.id})
+ 'commands': {
+ 'insert_comment': [
+ id, comment.id, comment.comment, user.username, user.get_profile_url(),
+ reverse('delete_comment', kwargs={'id': comment.id}),
+ reverse('node_markdown', kwargs={'id': comment.id})
]
- }
+ }
}
else:
return {
- 'commands': {
- 'update_comment': [comment.id, comment.comment]
- }
+ 'commands': {
+ 'update_comment': [comment.id, comment.comment]
+ }
}
@command
return {'commands': commands}
-@command
+@command
def delete_post(request, id):
post = get_object_or_404(Node, id=id)
user = request.user
CloseAction(node=question, user=user, extra=reason, ip=request.META['REMOTE_ADDR']).save()
- return {
- 'commands': {
- 'refresh_page': []
- }
- }
+ return RefreshPageCommand()
@command
def wikify(request, id):
WikifyAction(node=node, user=user, ip=request.META['REMOTE_ADDR']).save()
- return {
- 'commands': {
- 'refresh_page': []
- }
- }
+ return RefreshPageCommand()
@command
def convert_to_comment(request, id):
question = answer.question
if not request.POST:
- description = lambda a: _("Answer by %(uname)s: %(snippet)s...") % {'uname': a.author.username, 'snippet': a.summary[:10]}
+ description = lambda a: _("Answer by %(uname)s: %(snippet)s...") % {'uname': a.author.username,
+ 'snippet': a.summary[:10]}
nodes = [(question.id, _("Question"))]
- [nodes.append((a.id, description(a))) for a in question.answers.filter_state(deleted=False).exclude(id=answer.id)]
+ [nodes.append((a.id, description(a))) for a in
+ question.answers.filter_state(deleted=False).exclude(id=answer.id)]
return render_to_response('node/convert_to_comment.html', {'answer': answer, 'nodes': nodes})
AnswerToCommentAction(user=user, node=answer, ip=request.META['REMOTE_ADDR']).save(data=dict(new_parent=new_parent))
- return {
- 'commands': {
- 'refresh_page': []
- }
- }
+ return RefreshPageCommand()
@command
def subscribe(request, id):
subscribed = True
return {
- 'commands': {
- 'set_subscription_button': [subscribed and _('unsubscribe me') or _('subscribe me')],
- 'set_subscription_status': ['']
- }
+ 'commands': {
+ 'set_subscription_button': [subscribed and _('unsubscribe me') or _('subscribe me')],
+ 'set_subscription_status': ['']
+ }
}
#internally grouped views - used by the tagging system
def matching_tags(request):
if len(request.GET['q']) == 0:
- raise CommandException(_("Invalid request"))
+ raise CommandException(_("Invalid request"))
possible_tags = Tag.active.filter(name__istartswith = request.GET['q'])
tag_output = ''
for tag in possible_tags:
tag_output += (tag.name + "|" + tag.name + "." + tag.used_count.__str__() + "\n")
-
+
return HttpResponse(tag_output, mimetype="text/plain")
def related_questions(request):
if request.POST and request.POST.get('title', None):
return HttpResponse(simplejson.dumps(
[dict(title=q.title, url=q.get_absolute_url(), score=q.score, summary=q.summary)
- for q in Question.objects.search(request.POST['title']).filter_state(deleted=False)[0:10]]), mimetype="application/json")
+ for q in Question.objects.search(request.POST['title']).filter_state(deleted=False)[0:10]]),
+ mimetype="application/json")
else:
raise Http404()
if tab is not None:\r
context['tab'] = tab\r
\r
- return render_to_response(context.pop('template', template), context, context_instance=RequestContext(request))\r
+ return render_to_response(context.pop('template', template), context,\r
+ context_instance=RequestContext(request))\r
+\r
return decorated\r
+\r
return decorator\r
\r
def list(paginate, default_page_size):\r
page_obj = paginator.page(page)\r
except EmptyPage:\r
raise Http404()\r
- \r
+\r
context[paginate] = page_obj.object_list.lazy()\r
\r
base_path = context.get('base_path', None) or request.path\r
sort = request.utils.sort_method('')\r
\r
context["pagination_context"] = {\r
- 'is_paginated' : True,\r
- 'pages': paginator.num_pages,\r
- 'page': page,\r
- 'has_previous': page_obj.has_previous(),\r
- 'has_next': page_obj.has_next(),\r
- 'previous': page_obj.previous_page_number(),\r
- 'next': page_obj.next_page_number(),\r
- 'base_url' : "%s%ssort=%s&" % (base_path, ('?' in base_path) and '&' or '?', sort),\r
- 'pagesize' : pagesize\r
+ 'is_paginated' : True,\r
+ 'pages': paginator.num_pages,\r
+ 'page': page,\r
+ 'has_previous': page_obj.has_previous(),\r
+ 'has_next': page_obj.has_next(),\r
+ 'previous': page_obj.previous_page_number(),\r
+ 'next': page_obj.next_page_number(),\r
+ 'base_url' : "%s%ssort=%s&" % (base_path, ('?' in base_path) and '&' or '?', sort),\r
+ 'pagesize' : pagesize\r
}\r
\r
context['sort_context'] = {\r
- 'base_url': "%s%ssort=" % (base_path, ('?' in base_path) and '&' or '?'),\r
- 'current': sort,\r
+ 'base_url': "%s%ssort=" % (base_path, ('?' in base_path) and '&' or '?'),\r
+ 'current': sort,\r
}\r
\r
return context\r
+\r
return decorated\r
+\r
return decorator\r
\r
\r
class CommandException(Exception):\r
pass\r
\r
+class RefreshPageCommand(HttpResponse):\r
+ def __init__(self):\r
+ super(RefreshPageCommand, self).__init__(\r
+ content=simplejson.dumps({'commands': {'refresh_page': []}, 'success': True}),\r
+ mimetype="application/json")\r
\r
def command(func):\r
def decorated(request, *args, **kwargs):\r
\r
response['success'] = True\r
except Exception, e:\r
- #import sys, traceback\r
- #traceback.print_exc(file=sys.stdout)\r
+ import traceback\r
+ #traceback.print_exc()\r
\r
if isinstance(e, CommandException):\r
response = {\r
- 'success': False,\r
- 'error_message': e.message\r
+ 'success': False,\r
+ 'error_message': e.message\r
}\r
else:\r
logging.error("%s: %s" % (func.__name__, str(e)))\r
+ logging.error(traceback.format_exc())\r
response = {\r
- 'success': False,\r
- 'error_message': _("We're sorry, but an unknown error ocurred.<br />Please try again in a while.")\r
+ 'success': False,\r
+ 'error_message': _("We're sorry, but an unknown error ocurred.<br />Please try again in a while.")\r
}\r
\r
if request.is_ajax():\r
from forum.utils.html import sanitize_html\r
from datetime import datetime, date\r
import decorators\r
-from forum.actions import EditProfileAction, FavoriteAction, BonusRepAction\r
+from forum.actions import EditProfileAction, FavoriteAction, BonusRepAction, SuspendAction\r
\r
import time\r
\r
def users(request):\r
is_paginated = True\r
sortby = request.GET.get('sort', 'reputation')\r
- suser = request.REQUEST.get('q', "")\r
+ suser = request.REQUEST.get('q', "")\r
try:\r
page = int(request.GET.get('page', '1'))\r
except ValueError:\r
objects_list = Paginator(User.objects.all().order_by('username'), USERS_PAGE_SIZE)\r
# default\r
else:\r
- objects_list = Paginator(User.objects.all().order_by('-reputation'), USERS_PAGE_SIZE)\r
+ objects_list = Paginator(User.objects.all().order_by('-is_active', '-reputation'), USERS_PAGE_SIZE)\r
base_url = reverse('users') + '?sort=%s&' % sortby\r
else:\r
sortby = "reputation"\r
- objects_list = Paginator(User.objects.filter(username__icontains=suser).order_by('-reputation'), USERS_PAGE_SIZE)\r
+ objects_list = Paginator(User.objects.filter(username__icontains=suser).order_by('-reputation'), USERS_PAGE_SIZE\r
+ )\r
base_url = reverse('users') + '?name=%s&sort=%s&' % (suser, sortby)\r
\r
try:\r
users = objects_list.page(objects_list.num_pages)\r
\r
return render_to_response('users/users.html', {\r
- "users" : users,\r
- "suser" : suser,\r
- "keywords" : suser,\r
- "tab_id" : sortby,\r
- "context" : {\r
- 'is_paginated' : is_paginated,\r
- 'pages': objects_list.num_pages,\r
- 'page': page,\r
- 'has_previous': users.has_previous(),\r
- 'has_next': users.has_next(),\r
- 'previous': users.previous_page_number(),\r
- 'next': users.next_page_number(),\r
- 'base_url' : base_url\r
- }\r
-\r
- }, context_instance=RequestContext(request))\r
+ "users" : users,\r
+ "suser" : suser,\r
+ "keywords" : suser,\r
+ "tab_id" : sortby,\r
+ "context" : {\r
+ 'is_paginated' : is_paginated,\r
+ 'pages': objects_list.num_pages,\r
+ 'page': page,\r
+ 'has_previous': users.has_previous(),\r
+ 'has_next': users.has_next(),\r
+ 'previous': users.previous_page_number(),\r
+ 'next': users.next_page_number(),\r
+ 'base_url' : base_url\r
+ }\r
+\r
+ }, context_instance=RequestContext(request))\r
\r
def set_new_email(user, new_email, nomessage=False):\r
if new_email != user.email:\r
user.email = new_email\r
user.email_isvalid = False\r
user.save()\r
- #if settings.EMAIL_VALIDATION == 'on':\r
- # send_new_email_key(user,nomessage=nomessage) \r
+ #if settings.EMAIL_VALIDATION == 'on':\r
+ # send_new_email_key(user,nomessage=nomessage)\r
\r
@login_required\r
def edit_user(request, id):\r
else:\r
form = EditUserForm(user)\r
return render_to_response('users/edit.html', {\r
- 'user': user,\r
- 'form' : form,\r
- 'gravatar_faq_url' : reverse('faq') + '#gravatar',\r
- }, context_instance=RequestContext(request))\r
+ 'user': user,\r
+ 'form' : form,\r
+ 'gravatar_faq_url' : reverse('faq') + '#gravatar',\r
+ }, context_instance=RequestContext(request))\r
\r
\r
@login_required\r
else:\r
raise Http404()\r
\r
- user.save() \r
+ user.save()\r
return HttpResponseRedirect(user.get_profile_url())\r
\r
\r
return dict(reputation=user.reputation)\r
\r
\r
+@decorators.command\r
+def suspend(request, id):\r
+ user = get_object_or_404(User, id=id)\r
+\r
+ if not request.POST:\r
+ if user.is_suspended():\r
+ suspension = user.suspension\r
+ suspension.cancel(ip=request.META['REMOTE_ADDR'])\r
+ return decorators.RefreshPageCommand()\r
+ else:\r
+ return render_to_response('users/suspend_user.html')\r
+\r
+ if not request.user.is_superuser:\r
+ raise decorators.CommandException(_("Only superusers can ban other users"))\r
+\r
+ data = {\r
+ 'bantype': request.POST.get('bantype', 'indefinetly').strip(),\r
+ 'publicmsg': request.POST.get('publicmsg', _('Bad behaviour')),\r
+ 'privatemsg': request.POST.get('privatemsg', None) or request.POST.get('publicmsg', ''),\r
+ 'suspender': request.user.id\r
+ }\r
+\r
+ if data['bantype'] == 'forxdays':\r
+ try:\r
+ data['forxdays'] = int(request.POST['forxdays'])\r
+ except:\r
+ raise decorators.CommandException(_('Invalid numeric argument for the number of days.'))\r
+\r
+ SuspendAction(user=user, ip=request.META['REMOTE_ADDR']).save(data=data)\r
+\r
+ return decorators.RefreshPageCommand()\r
+\r
def user_view(template, tab_name, tab_description, page_title, private=False):\r
def decorator(fn):\r
def decorated(request, id, slug=None):\r
rev_page_title = user.username + " - " + page_title\r
\r
context.update({\r
- "tab_name" : tab_name,\r
- "tab_description" : tab_description,\r
- "page_title" : rev_page_title,\r
- "can_view_private": (user == request.user) or request.user.is_superuser\r
+ "tab_name" : tab_name,\r
+ "tab_description" : tab_description,\r
+ "page_title" : rev_page_title,\r
+ "can_view_private": (user == request.user) or request.user.is_superuser\r
})\r
return render_to_response(template, context, context_instance=RequestContext(request))\r
+\r
return decorated\r
+\r
return decorator\r
\r
\r
.annotate(user_tag_usage_count=Count('name')).order_by('-user_tag_usage_count')\r
\r
awards = [(Badge.objects.get(id=b['id']), b['count']) for b in\r
- Badge.objects.filter(awards__user=user).values('id').annotate(count=Count('cls')).order_by('-count')]\r
+ Badge.objects.filter(awards__user=user).values('id').annotate(count=Count('cls')).order_by('-count')]\r
\r
return {\r
- "view_user" : user,\r
- "questions" : questions,\r
- "answers" : answers,\r
- "up_votes" : up_votes,\r
- "down_votes" : down_votes,\r
- "total_votes": up_votes + down_votes,\r
- "votes_today_left": votes_total-votes_today,\r
- "votes_total_per_day": votes_total,\r
- "user_tags" : user_tags[:50],\r
- "awards": awards,\r
- "total_awards" : len(awards),\r
- }\r
+ "view_user" : user,\r
+ "questions" : questions,\r
+ "answers" : answers,\r
+ "up_votes" : up_votes,\r
+ "down_votes" : down_votes,\r
+ "total_votes": up_votes + down_votes,\r
+ "votes_today_left": votes_total-votes_today,\r
+ "votes_total_per_day": votes_total,\r
+ "user_tags" : user_tags[:50],\r
+ "awards": awards,\r
+ "total_awards" : len(awards),\r
+ }\r
\r
@user_view('users/recent.html', 'recent', _('recent user activity'), _('recent activity'))\r
def user_recent(request, user):\r
- activities = user.actions.exclude(action_type__in=("voteup", "votedown", "voteupcomment", "flag", "newpage", "editpage")).order_by('-action_date')[:USERS_PAGE_SIZE]\r
+ activities = user.actions.exclude(\r
+ action_type__in=("voteup", "votedown", "voteupcomment", "flag", "newpage", "editpage")).order_by(\r
+ '-action_date')[:USERS_PAGE_SIZE]\r
\r
return {"view_user" : user, "activities" : activities}\r
\r
\r
@user_view('users/votes.html', 'votes', _('user vote record'), _('votes'), True)\r
def user_votes(request, user):\r
- votes = user.votes.exclude(node__state_string__contains="(deleted").filter(node__node_type__in=("question", "answer")).order_by('-voted_at')[:USERS_PAGE_SIZE]\r
+ votes = user.votes.exclude(node__state_string__contains="(deleted").filter(\r
+ node__node_type__in=("question", "answer")).order_by('-voted_at')[:USERS_PAGE_SIZE]\r
\r
return {"view_user" : user, "votes" : votes}\r
\r
def user_reputation(request, user):\r
rep = list(user.reputes.order_by('date'))\r
values = [r.value for r in rep]\r
- redux = lambda x, y: x+y \r
+ redux = lambda x, y: x+y\r
\r
graph_data = simplejson.dumps([\r
- (time.mktime(rep[i].date.timetuple()) * 1000, reduce(redux, values[:i], 0))\r
- for i in range(len(values))\r
+ (time.mktime(rep[i].date.timetuple()) * 1000, reduce(redux, values[:i], 0))\r
+ for i in range(len(values))\r
])\r
\r
rep = user.reputes.filter(action__canceled=False).order_by('-date')[0:20]\r
- \r
+\r
return {"view_user": user, "reputation": rep, "graph_data": graph_data}\r
\r
-@user_view('users/questions.html', 'favorites', _('favorite questions'), _('favorite questions'))\r
+@user_view('users/questions.html', 'favorites', _('favorite questions'), _('favorite questions'))\r
def user_favorites(request, user):\r
favorites = FavoriteAction.objects.filter(canceled=False, user=user)\r
\r
request.user.message_set.create(message=_('Notifications are now disabled'))\r
\r
form.is_valid()\r
- for k,v in form.cleaned_data.items():\r
+ for k, v in form.cleaned_data.items():\r
setattr(user.subscription_settings, k, v)\r
\r
user.subscription_settings.save()\r
is_openid = False\r
\r
return render_to_response('account_settings.html', {\r
- 'msg': msg,\r
- 'is_openid': is_openid\r
- }, context_instance=RequestContext(request))\r
+ 'msg': msg,\r
+ 'is_openid': is_openid\r
+ }, context_instance=RequestContext(request))\r
\r
-from forum.forms import NextUrlField, UserNameField, UserEmailField, SetPasswordForm
+from forum.forms import NextUrlField, UserNameField, UserEmailField, SetPasswordForm
from forum.models import Question
from forum.modules import call_all_handlers
from django.contrib.contenttypes.models import ContentType
spam_fields = call_all_handlers('create_anti_spam_field')
if spam_fields:
spam_fields = dict(spam_fields)
- for name,field in spam_fields.items():
+ for name, field in spam_fields.items():
self.fields[name] = field
self._anti_spam_fields = spam_fields.keys()
class ClassicLoginForm(forms.Form):
""" legacy account signin form """
next = NextUrlField()
- username = UserNameField(required=False,skip_clean=True)
+ username = UserNameField(required=False, skip_clean=True)
password = forms.CharField(max_length=128,
- widget=forms.widgets.PasswordInput(attrs={'class':'required login'}),
- required=False)
+ widget=forms.widgets.PasswordInput(attrs={'class':'required login'}),
+ required=False)
def __init__(self, data=None, files=None, auto_id='id_%s',
- prefix=None, initial=None):
+ prefix=None, initial=None):
super(ClassicLoginForm, self).__init__(data, files, auto_id,
- prefix, initial)
+ prefix, initial)
self.user_cache = None
- def _clean_nonempty_field(self,field):
+ def _clean_nonempty_field(self, field):
value = None
if field in self.cleaned_data:
value = self.cleaned_data[field].strip()
del self.cleaned_data['username']
del self.cleaned_data['password']
- error_list.insert(0,(_("Please enter valid username and password "
- "(both are case-sensitive).")))
+ error_list.insert(0, (_("Please enter valid username and password "
+ "(both are case-sensitive).")))
- elif not user_.is_active:
- error_list.append(_("This account is inactive."))
if len(error_list) > 0:
- error_list.insert(0,_('Login failed.'))
+ error_list.insert(0, _('Login failed.'))
try:
self.user_cache = user_.user
except: