Browse Source

WIP warning levels admin

Rafał Pitoń 11 years ago
parent
commit
bf15ffb9cf

+ 0 - 6
misago/templates/misago/admin/users/list.html

@@ -22,7 +22,6 @@
 <th style="width: 1%;">&nbsp;</th>
 {% endfor %}
 <th>&nbsp;</th>
-<th>&nbsp;</th>
 {% endblock table-header %}
 
 
@@ -77,11 +76,6 @@
     </ul>
   </div>
 </td>
-<td class="row-select">
-  <label>
-    <input type="checkbox">
-  </label>
-</td>
 {% endblock table-row %}
 
 

+ 64 - 0
misago/templates/misago/admin/warnings/form.html

@@ -0,0 +1,64 @@
+{% extends "misago/admin/generic/form.html" %}
+{% load crispy_forms_filters i18n %}
+
+
+{% block title %}
+{% if target.pk %}
+{% trans target.banned_value %}
+{% else %}
+{% trans "New ban" %}
+{% endif %} | {{ active_link.name }} | {{ block.super }}
+{% endblock title %}
+
+
+{% block page-target %}
+{% if target.pk %}
+{% trans target.banned_value %}
+{% else %}
+{% trans "New ban" %}
+{% endif %}
+{% endblock page-target %}
+
+
+{% block form-header %}
+<h1>
+  {% if target.pk %}
+  {% trans target.banned_value %}
+  {% else %}
+  {% trans "New ban" %}
+  {% endif %}
+</h1>
+{% endblock %}
+
+
+{% block form-body %}
+<div class="form-body">
+  <fieldset>
+    <legend>{% trans "Ban settings" %}</legend>
+
+    {{ form.test|as_crispy_field }}
+    {{ form.banned_value|as_crispy_field }}
+    {{ form.valid_until|as_crispy_field }}
+
+  </fieldset>
+  <fieldset>
+    <legend>{% trans "Messages" %}</legend>
+
+    {{ form.user_message|as_crispy_field }}
+    {{ form.staff_message|as_crispy_field }}
+
+  </fieldset>
+</div>
+{% endblock form-body %}
+
+
+{% block javascripts %}
+<script type="text/javascript">
+  $(function() {
+    $('#id_valid_until').datetimepicker({
+      language: $('html').attr('lang'),
+      pickTime: false
+    });
+  });
+</script>
+{% endblock %}

+ 70 - 0
misago/templates/misago/admin/warnings/list.html

@@ -0,0 +1,70 @@
+{% extends "misago/admin/generic/list.html" %}
+{% load i18n %}
+
+
+{% block page-actions %}
+<div class="page-actions">
+  <a href="{% url 'misago:admin:users:ranks:new' %}" class="btn btn-success">
+    <span class="fa fa-plus-circle"></span>
+    {% trans "New level" %}
+  </a>
+</div>
+{% endblock %}
+
+
+{% block table-header %}
+<th>{% trans "Warning level" %}</th>
+{% for action in extra_actions %}
+<th style="width: 1%;">&nbsp;</th>
+{% endfor %}
+<th style="width: 1%;">&nbsp;</th>
+<th style="width: 1%;">&nbsp;</th>
+<th style="width: 1%;">&nbsp;</th>
+<th style="width: 1%;">&nbsp;</th>
+{% endblock table-header %}
+
+
+{% block table-row %}
+<td class="lead">
+  #{{ forloop.counter }} {{ item.name }}
+</td>
+{% for action in extra_actions %}
+<td class="row-action">
+  <a href="{% url action.link rank_id=item.id %}" class="btn btn-{% if action.style %}{{ action.style }}{% else %}default{% endif %} tooltip-top" title="{{ action.name }}">
+    <span class="{{ action.icon }}"></span>
+  </a>
+</td>
+{% endfor %}
+<td class="row-action">
+  <a href="{% url 'misago:admin:users:warnings:edit' warning_id=item.id %}" class="btn btn-primary tooltip-top" title="{% trans "Edit" %}">
+    <span class="fa fa-pencil"></span>
+  </a>
+</td>
+<td class="row-action">
+  <form action="{% url 'misago:admin:users:warnings:delete' warning_id=item.id %}" method="post" class="delete-prompt">
+    <button class="btn btn-danger tooltip-top" title="{% trans "Delete" %}">
+      {% csrf_token %}
+      <span class="fa fa-times"></span>
+    </button>
+  </form>
+</td>
+{% endblock %}
+
+
+{% block emptylist %}
+<td colspan="{{ 5|add:extra_actions_len }}">
+  <p>{% trans "No warning levels are currently defined." %}</p>
+</td>
+{% endblock emptylist %}
+
+
+{% block javascripts %}
+<script type="text/javascript">
+  $(function() {
+    $('.delete-prompt').submit(function() {
+      var decision = confirm("{% trans "Are you sure you want to delete this warning level?" %}");
+      return decision;
+    });
+  });
+</script>
+{% endblock %}

+ 37 - 1
misago/users/forms/admin.py

@@ -3,7 +3,8 @@ from django.utils.translation import ugettext_lazy as _
 from misago.core import forms, threadstore
 from misago.core.validators import validate_sluggable
 from misago.acl.models import Role
-from misago.users.models import BANS_CHOICES, Ban, Rank
+from misago.users.models import (BANS_CHOICES, RESTRICTIONS_CHOICES,
+                                 Ban, Rank, WarningLevel)
 from misago.users.validators import (validate_username, validate_email,
                                      validate_password)
 
@@ -348,3 +349,38 @@ class SearchBansForm(forms.Form):
             queryset = queryset.filter(is_valid=False)
 
         return queryset
+
+
+"""
+Warning levels
+"""
+class WarningLevelForm(forms.ModelForm):
+    name = forms.CharField(label=_("Level name"), max_length=255)
+    description = forms.CharField(
+        label=_("Optional level description"), required=False, max_length=1000,
+        widget=forms.Textarea(attrs={'rows': 3}),
+        error_messages={
+            'max_length': _("Description can't be longer "
+                            "than 1000 characters.")
+        })
+    expires_after_minutes = forms.IntegerField(
+        label=_("Expiration time"), min_value=0,
+        help_text=_("Enter number of minutes since this warning level was "
+                    "imposed on member until it's reduced, or 0 to make "
+                    "this warning level permanent."))
+    restricts_posting_replies = forms.TypedChoicefield(
+        label=_("Restrictions on posting replies"),
+        coerce=int, choices=RESTRICTIONS_CHOICES)
+    restricts_posting_threads = forms.TypedChoicefield(
+        label=_("Restrictions on posting threads"),
+        coerce=int, choices=RESTRICTIONS_CHOICES)
+
+    class Meta:
+        model = WarningLevel
+        fields = [
+            'name',
+            'description',
+            'expires_after_minutes',
+            'restricts_posting_replies',
+            'restricts_posting_threads',
+        ]

+ 37 - 2
misago/users/models.py

@@ -8,6 +8,7 @@ from django.utils import timezone
 from django.utils.translation import ugettext_lazy as _
 from misago.acl import get_user_acl, version as acl_version
 from misago.acl.models import Role
+from misago.core.cache import cache
 from misago.core.utils import slugify
 from misago.users.utils import hash_email
 from misago.users.validators import (validate_email, validate_password,
@@ -360,8 +361,8 @@ class Ban(models.Model):
 
     def test_value(self, value):
         if '*' in self.banned_value:
-            regex = '^' + re.escape(self.banned_value).replace('\*', '(.*?)') + '$'
-            return re.search(regex, value) != None
+            regex = re.escape(self.banned_value).replace('\*', '(.*?)')
+            return re.search('^%s$' % regex, value) != None
         else:
             return self.banned_value == value
 
@@ -371,3 +372,37 @@ class BanCache(models.Model):
     is_banned = models.BooleanField(default=False)
     bans_version = models.PositiveIntegerField(default=0)
     valid_until = models.DateField(null=True, blank=True)
+
+
+"""
+Warning level
+"""
+RESTRICT_NO = 0
+RESTRICT_MODERATOR_REVIEW = 1
+RESTRICT_DISALLOW = 2
+
+
+RESTRICTIONS_CHOICES = (
+    (WarnLevel.RESTRICT_NO, _("No restrictions")),
+    (WarnLevel.RESTRICT_MODERATOR_REVIEW, _("Review by moderator")),
+    (WarnLevel.RESTRICT_DISALLOW, _("Disallowed")),
+)
+
+
+class WarningLevel(models.Model):
+    name = models.CharField(max_length=255)
+    description = models.TextField(null=True, blank=True)
+    warning_level = models.PositiveIntegerField(default=1, db_index=True)
+    expires_after_minutes = models.PositiveIntegerField(default=0)
+    restricts_posting_replies = models.PositiveIntegerField(
+        default=RESTRICT_NO)
+    restricts_posting_threads = models.PositiveIntegerField(
+        default=RESTRICT_NO)
+
+    def save(self, *args, **kwargs):
+        super(WarnLevel, self).save(*args, **kwargs)
+        cache.delete('warning_levels')
+
+    def delete(self, *args, **kwargs):
+        super(WarnLevel, self).delete(*args, **kwargs)
+        cache.delete('warning_levels')

+ 0 - 5
misago/users/views/admin/bans.py

@@ -13,11 +13,6 @@ class BanAdmin(generic.AdminBaseMixin):
     templates_dir = 'misago/admin/bans'
     message_404 = _("Requested ban does not exist.")
 
-    def update_roles(self, target, roles):
-        target.roles.clear()
-        if roles:
-            target.roles.add(*roles)
-
     def handle_form(self, form, request, target):
         super(BanAdmin, self).handle_form(form, request, target)
         cachebuster.invalidate('misago_bans')

+ 33 - 0
misago/users/views/admin/warnings.py

@@ -0,0 +1,33 @@
+from django.contrib import messages
+from django.utils.translation import ugettext_lazy as _
+from misago.admin.views import generic
+from misago.core import cachebuster
+from misago.users.models import WarningLevel
+from misago.users.forms.admin import WarningLevelForm
+
+
+class WarningsAdmin(generic.AdminBaseMixin):
+    root_link = 'misago:admin:users:warnings:index'
+    Model = WarningLevel
+    Form = WarningLevelForm
+    templates_dir = 'misago/admin/warnings'
+    message_404 = _("Requested warning level does not exist.")
+
+
+class WarningsList(WarningsAdmin, generic.ListView):
+    pass
+
+
+class NewWarning(WarningsAdmin, generic.ModelFormView):
+    message_submit = _('New warning level "%s" has been saved.')
+
+
+class EditWarning(WarningsAdmin, generic.ModelFormView):
+    message_submit = _('Warning level "%s" has been edited.')
+
+
+class DeleteWarning(WarningsAdmin, generic.ButtonView):
+    def button_action(self, request, target):
+        target.delete()
+        message = _('Warning level "%s" has been deleted.')
+        messages.success(request, message % unicode(target.name))