Browse Source

WIP report modal and view.

Rafał Pitoń 10 years ago
parent
commit
b8d35c87da

+ 8 - 0
docs/developers/thread_types.rst

@@ -159,6 +159,14 @@ get_post_delete_url
 Used to obtain url that will delete post.
 Used to obtain url that will delete post.
 
 
 
 
+get_post_report_url
+-------------------
+
+.. function:: get_post_report_url(post)
+
+Used to obtain url for reporting post.
+
+
 get_event_edit_url
 get_event_edit_url
 ------------------
 ------------------
 
 

+ 1 - 0
misago/conf/defaults.py

@@ -77,6 +77,7 @@ PIPELINE_JS = {
             'misago/js/misago-onebox.js',
             'misago/js/misago-onebox.js',
             'misago/js/misago-posting.js',
             'misago/js/misago-posting.js',
             'misago/js/misago-posting-participants.js',
             'misago/js/misago-posting-participants.js',
+            'misago/js/misago-report-post.js',
             'misago/js/misago-posts.js',
             'misago/js/misago-posts.js',
             'misago/js/misago-thread-participants.js',
             'misago/js/misago-thread-participants.js',
         ),
         ),

+ 4 - 0
misago/static/misago/js/misago-modal.js

@@ -44,6 +44,10 @@
         }
         }
       });
       });
     }
     }
+
+    this.close = function() {
+      this.$modal.modal('hide');
+    }
   };
   };
 
 
   Misago.Modal = new MisagoModal();
   Misago.Modal = new MisagoModal();

+ 8 - 0
misago/static/misago/js/misago-posts.js

@@ -59,6 +59,14 @@ $(function() {
 
 
     });
     });
 
 
+    this.$e.find('.btn-report').click(function() {
+
+      if (!Misago.ReportPost.is_open()) {
+        Misago.ReportPost.open(_this.$e.data('report-url'));
+      }
+
+    });
+
     this.quote = function() {
     this.quote = function() {
 
 
       $.get(_this.$e.data('quote-url'), function(data) {
       $.get(_this.$e.data('quote-url'), function(data) {

+ 94 - 0
misago/static/misago/js/misago-report-post.js

@@ -0,0 +1,94 @@
+// Controller for reporting posts
+$(function() {
+
+  MisagoReportPost = function() {
+
+    this._clear = function() {
+
+      this.api_url = null;
+      this.on_report = null;
+      this.posted = false;
+
+      this.$error = null;
+      this.$form = null;
+
+    }
+
+    this._clear();
+
+    var _this = this;
+
+    this.open = function(api_url, on_report) {
+
+      this._clear();
+
+      if (!this.is_open()) {
+
+        this.api_url = api_url;
+        this.on_report = on_report;
+
+        $.get(api_url, function(data) {
+
+          if (data.is_reported) {
+            Misago.Alerts.info(data.message);
+          } else {
+            Misago.Modal.show(data);
+
+            _this.$form = Misago.Modal.$modal.find('form');
+
+            _this.$error = Misago.Modal.$modal.find('.text-danger');
+            _this.$error.hide();
+
+            _this.$form.submit(function(e) {
+              if (!_this.posted) {
+                _this.posted = true;
+                _this.submit();
+              }
+              e.preventDefault();
+              return false;
+            });
+
+          }
+
+        });
+
+      }
+
+    }
+
+    this.submit = function() {
+
+      $.post(this.api_url, this.$form.serialize(), function(data) {
+
+        if (data.is_error) {
+
+          _this.$error.text(data.message);
+          _this.$error.slideDown();
+          _this.posted = false;
+
+        } else {
+
+          Misago.Modal.close();
+          Misago.Alerts.success(data.message);
+
+          if (this.on_report) {
+            this.on_report(data);
+          }
+
+        }
+
+      });
+
+    }
+
+    this.is_open = function() {
+
+      return Misago.Modal.is_visible();
+
+    }
+
+  }
+
+  Misago.ReportPost = new MisagoReportPost();
+
+});

+ 8 - 9
misago/templates/misago/thread/post.html

@@ -1,6 +1,6 @@
 {% load i18n misago_avatars %}
 {% load i18n misago_avatars %}
 <div id="post-{{ post.pk }}" class="post-fragment"></div>
 <div id="post-{{ post.pk }}" class="post-fragment"></div>
-<div class="media post thread-post{% if post.poster_id and post.poster.rank.css_class %} rank-{{ post.poster.rank.css_class }}{% endif %}" data-id="{{ post.pk }}" data-edit-url="{{ post.get_edit_url }}" data-quote-url="{{ post.get_quote_url }}">
+<div class="media post thread-post{% if post.poster_id and post.poster.rank.css_class %} rank-{{ post.poster.rank.css_class }}{% endif %}" data-id="{{ post.pk }}" data-edit-url="{{ post.get_edit_url }}" data-quote-url="{{ post.get_quote_url }}" data-report-url="{{ post.get_report_url }}">
   {% if post.poster %}
   {% if post.poster %}
   <a class="user-avatar pull-left" href="{% url USER_PROFILE_URL user_slug=post.poster.slug user_id=post.poster.id %}">
   <a class="user-avatar pull-left" href="{% url USER_PROFILE_URL user_slug=post.poster.slug user_id=post.poster.id %}">
     <img class="media-object" src="{{ post.poster|avatar:100 }}" alt="{% trans "Poster avatar" %}">
     <img class="media-object" src="{{ post.poster|avatar:100 }}" alt="{% trans "Poster avatar" %}">
@@ -69,7 +69,7 @@
       </div>
       </div>
       {% endif %}
       {% endif %}
 
 
-      {% if post.is_reported %}
+      {% if post.is_reported and thread.acl.can_see_reports %}
       <div class="alert alert-danger">
       <div class="alert alert-danger">
         <span class="fa fa-exclamation-triangle fa-fw fa-lg"></span>
         <span class="fa fa-exclamation-triangle fa-fw fa-lg"></span>
         {% trans "This post was reported to moderators." %}
         {% trans "This post was reported to moderators." %}
@@ -142,13 +142,12 @@
           </form>
           </form>
           {% endif %}
           {% endif %}
 
 
-          <form action="" method="post">
-            {% csrf_token %}
-            <button type="submit" class="btn btn-warning btn-flat pull-right">
-              <span class="fa fa-exclamation-triangle">
-              {% trans "Report" %}
-            </button>
-          </form>
+          {% if post.acl.can_report %}
+          <button type="submit" class="btn btn-warning btn-report btn-flat pull-right">
+            <span class="fa fa-exclamation-triangle">
+            {% trans "Report" %}
+          </button>
+          {% endif %}
 
 
           {% if post.acl.can_approve %}
           {% if post.acl.can_approve %}
           <form action="{{ post.get_approve_url }}" method="post">
           <form action="{{ post.get_approve_url }}" method="post">

+ 22 - 0
misago/templates/misago/thread/report_modal.html

@@ -0,0 +1,22 @@
+{% load i18n misago_forms %}
+<form method="POST">
+  {% csrf_token %}
+  <div class="modal-header">
+    <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">{% trans "Close" %}</span></button>
+    <h4 class="modal-title" id="ajaxModalLabel">
+      <span class="fa fa-exclamation-triangle fa-fw"></span>
+      {% trans "Report post" %}
+    </h4>
+  </div>
+  <div class="modal-body modal-form">
+
+    <p class="lead text-danger">Lorem ipsum dolor met</p>
+
+    {% form_row form.report_message %}
+
+  </div>
+  <div class="modal-footer text-left">
+    <button class="btn btn-primary" name="submit">{% trans "Report post" %}</button>
+    <button type="button" class="btn btn-default" data-dismiss="modal">{% trans "Cancel" %}</button>
+  </div>
+</form>

+ 15 - 0
misago/threads/forms/report.py

@@ -0,0 +1,15 @@
+from django.utils.translation import ugettext_lazy as _
+from misago.core import forms
+
+
+class ReportPostForm(forms.Form):
+    report_message = forms.CharField(label=_("Optional report message"),
+                                     widget=forms.Textarea(attrs={'rows': 3}),
+                                     required=False)
+
+    def clean_report_message(self):
+        data = self.cleaned_data['report_message']
+        if len(data) > 2000:
+            raise forms.ValidationError("Report message cannot be "
+                                        "longer than 2000 characters.")
+        return data

+ 3 - 0
misago/threads/models/post.py

@@ -107,6 +107,9 @@ class Post(models.Model):
     def get_delete_url(self):
     def get_delete_url(self):
         return self.thread_type.get_post_delete_url(self)
         return self.thread_type.get_post_delete_url(self)
 
 
+    def get_report_url(self):
+        return self.thread_type.get_post_report_url(self)
+
     @property
     @property
     def short(self):
     def short(self):
         if self.is_valid:
         if self.is_valid:

+ 0 - 0
misago/threads/reports.py


+ 5 - 0
misago/threads/threadtypes/forumthread.py

@@ -102,6 +102,11 @@ class ForumThread(ThreadTypeBase):
             'post_id': post.id
             'post_id': post.id
         })
         })
 
 
+    def get_post_report_url(self, post):
+        return reverse('misago:report_post', kwargs={
+            'post_id': post.id
+        })
+
     def get_event_edit_url(self, event):
     def get_event_edit_url(self, event):
         return reverse('misago:edit_event', kwargs={
         return reverse('misago:edit_event', kwargs={
             'event_id': event.id
             'event_id': event.id

+ 5 - 0
misago/threads/threadtypes/privatethread.py

@@ -96,6 +96,11 @@ class PrivateThread(ThreadTypeBase):
             'post_id': post.id
             'post_id': post.id
         })
         })
 
 
+    def get_post_report_url(self, post):
+        return reverse('misago:report_private_post', kwargs={
+            'post_id': post.id
+        })
+
     def get_event_edit_url(self, event):
     def get_event_edit_url(self, event):
         return reverse('misago:edit_private_event', kwargs={
         return reverse('misago:edit_private_event', kwargs={
             'event_id': event.id
             'event_id': event.id

+ 1 - 1
misago/threads/urls/privatethreads.py

@@ -64,7 +64,7 @@ urlpatterns += patterns('',
     url(r'^private-post/(?P<post_id>\d+)/unhide/$', UnhidePostView.as_view(), name='unhide_private_post'),
     url(r'^private-post/(?P<post_id>\d+)/unhide/$', UnhidePostView.as_view(), name='unhide_private_post'),
     url(r'^private-post/(?P<post_id>\d+)/hide/$', HidePostView.as_view(), name='hide_private_post'),
     url(r'^private-post/(?P<post_id>\d+)/hide/$', HidePostView.as_view(), name='hide_private_post'),
     url(r'^private-post/(?P<post_id>\d+)/delete/$', DeletePostView.as_view(), name='delete_private_post'),
     url(r'^private-post/(?P<post_id>\d+)/delete/$', DeletePostView.as_view(), name='delete_private_post'),
-    url(r'^private-post/(?P<post_id>\d+)/report/$', ReportPostView.as_view(), name='report_post'),
+    url(r'^private-post/(?P<post_id>\d+)/report/$', ReportPostView.as_view(), name='report_private_post'),
 )
 )
 
 
 
 

+ 27 - 2
misago/threads/views/generic/post.py

@@ -9,6 +9,7 @@ from misago.acl import add_acl
 from misago.core.errorpages import not_allowed
 from misago.core.errorpages import not_allowed
 
 
 from misago.threads import permissions, moderation, goto
 from misago.threads import permissions, moderation, goto
+from misago.threads.forms.report import ReportPostForm
 from misago.threads.views.generic.base import ViewBase
 from misago.threads.views.generic.base import ViewBase
 
 
 
 
@@ -140,10 +141,12 @@ class DeletePostView(PostView):
         return self.redirect_to_post(request.user, target_post)
         return self.redirect_to_post(request.user, target_post)
 
 
 
 
-class ReportPostView(ViewBase):
+class ReportPostView(PostView):
     is_atomic = False
     is_atomic = False
     require_post = False
     require_post = False
 
 
+    template = 'misago/thread/report_modal.html'
+
     def dispatch(self, request, *args, **kwargs):
     def dispatch(self, request, *args, **kwargs):
         if not request.is_ajax():
         if not request.is_ajax():
             return not_allowed(request)
             return not_allowed(request)
@@ -151,4 +154,26 @@ class ReportPostView(ViewBase):
         return super(ReportPostView, self).dispatch(request, *args, **kwargs)
         return super(ReportPostView, self).dispatch(request, *args, **kwargs)
 
 
     def real_dispatch(self, request, post):
     def real_dispatch(self, request, post):
-        raise Exception("NOT YET IMPLEMENTED!")
+        if not post.acl['can_report']:
+            raise PermissionDenied(_("You can't report posts."))
+
+        form = ReportPostForm()
+        if request.method == 'POST':
+            form = ReportPostForm(request.POST)
+            if form.is_valid():
+                message = _("%(user)s's post has been "
+                            "reported to moderators.")
+                message = message % {'user': post.poster_name}
+                return JsonResponse({'message': message})
+            else:
+                field_errors = form.errors.get('report_message')
+                if field_errors:
+                    field_error = field_errors[0]
+                else:
+                    field_error = _("Error reporting post.")
+
+                return JsonResponse({'is_error': True, 'message': field_error})
+
+        return self.render(request, {'form': form})
+
+