Browse Source

- Example alert added to post reply.
- Alerts mechanic simplified.

Ralfp 12 years ago
parent
commit
eaa4fc5e84

+ 2 - 4
misago/alerts/views.py

@@ -8,11 +8,9 @@ from misago.views import error404
 def show_alerts(request):
 def show_alerts(request):
     now = timezone.now()
     now = timezone.now()
     alerts = {}
     alerts = {}
-    all_alerts = 0
     if not request.user.alerts_date:
     if not request.user.alerts_date:
         request.user.alerts_date = request.user.join_date
         request.user.alerts_date = request.user.join_date
     for alert in request.user.alert_set.order_by('-id'):
     for alert in request.user.alert_set.order_by('-id'):
-        all_alerts += 1
         alert.new = alert.date > request.user.alerts_date
         alert.new = alert.date > request.user.alerts_date
         diff = now - alert.date
         diff = now - alert.date
         if diff.days <= 0:
         if diff.days <= 0:
@@ -45,8 +43,8 @@ def show_alerts(request):
                                                  'alerts': alerts
                                                  'alerts': alerts
                                                  },
                                                  },
                                                 context_instance=RequestContext(request));
                                                 context_instance=RequestContext(request));
-    request.user.alerts = all_alerts
-    request.user.alerts_new = 0
+    # Sync alerts
+    request.user.alerts = 0
     request.user.alerts_date = now
     request.user.alerts_date = now
     request.user.save(force_update=True)
     request.user.save(force_update=True)
     return response
     return response

+ 8 - 1
misago/threads/acl.py

@@ -144,7 +144,7 @@ class ThreadsACL(BaseACL):
     
     
     def allow_thread_view(self, user, thread):
     def allow_thread_view(self, user, thread):
         try:
         try:
-            forum_role = self.acl[thread.forum.pk]
+            forum_role = self.acl[thread.forum_id]
             if forum_role['can_read_threads'] == 0:
             if forum_role['can_read_threads'] == 0:
                 raise ACLError403(_("You don't have permission to read threads in this forum."))
                 raise ACLError403(_("You don't have permission to read threads in this forum."))
             if thread.moderated and not (forum_role['can_approve'] or (user.is_authenticated() and user == thread.start_poster)):
             if thread.moderated and not (forum_role['can_approve'] or (user.is_authenticated() and user == thread.start_poster)):
@@ -152,6 +152,13 @@ class ThreadsACL(BaseACL):
         except KeyError:
         except KeyError:
             raise ACLError403(_("You don't have permission to read threads in this forum."))
             raise ACLError403(_("You don't have permission to read threads in this forum."))
     
     
+    def allow_post_view(self, user, thread, post):
+        forum_role = self.acl[thread.forum_id]
+        if post.moderated and not (forum_role['can_approve'] or (user.is_authenticated() and user == post.user)):
+            raise ACLError404()
+        if post.deleted and not (forum_role['can_delete_posts'] or (user.is_authenticated() and user == post.user)):
+            raise ACLError404()
+    
     def get_readable_forums(self, acl):
     def get_readable_forums(self, acl):
         readable = []
         readable = []
         for forum in self.acl:
         for forum in self.acl:

+ 1 - 0
misago/threads/urls.py

@@ -6,6 +6,7 @@ urlpatterns = patterns('misago.threads.views',
     url(r'^forum/(?P<slug>(\w|-)+)-(?P<forum>\d+)/new/$', 'PostingView', name="thread_new", kwargs={'mode': 'new_thread'}),
     url(r'^forum/(?P<slug>(\w|-)+)-(?P<forum>\d+)/new/$', 'PostingView', name="thread_new", kwargs={'mode': 'new_thread'}),
     url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/$', 'ThreadView', name="thread"),
     url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/$', 'ThreadView', name="thread"),
     url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/last/$', 'LastReplyView', name="thread_last"),
     url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/last/$', 'LastReplyView', name="thread_last"),
+    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/find-(?P<post>\d+)/$', 'FindReplyView', name="thread_find"),
     url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/new/$', 'NewReplyView', name="thread_new"),
     url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/new/$', 'NewReplyView', name="thread_new"),
     url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/moderated/$', 'FirstModeratedView', name="thread_moderated"),
     url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/moderated/$', 'FirstModeratedView', name="thread_moderated"),
     url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/reported/$', 'FirstReportedView', name="thread_reported"),
     url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/reported/$', 'FirstReportedView', name="thread_reported"),

+ 13 - 2
misago/threads/views/jumps.py

@@ -16,6 +16,10 @@ class JumpView(BaseView):
         self.request.acl.forums.allow_forum_view(self.forum)
         self.request.acl.forums.allow_forum_view(self.forum)
         self.request.acl.threads.allow_thread_view(self.request.user, self.thread)
         self.request.acl.threads.allow_thread_view(self.request.user, self.thread)
         
         
+    def fetch_post(self, post):
+        self.post = self.thread.post_set.get(pk=post)
+        self.request.acl.threads.allow_post_view(self.request.user, self.thread, self.post)
+        
     def redirect(self, post):
     def redirect(self, post):
         pagination = make_pagination(0, self.request.acl.threads.filter_posts(self.request, self.thread, self.thread.post_set.filter(date__lt=post.date)).count() + 1, self.request.settings.posts_per_page)
         pagination = make_pagination(0, self.request.acl.threads.filter_posts(self.request, self.thread, self.thread.post_set.filter(date__lt=post.date)).count() + 1, self.request.settings.posts_per_page)
         if pagination['total'] > 1:
         if pagination['total'] > 1:
@@ -25,12 +29,14 @@ class JumpView(BaseView):
     def make_jump(self):
     def make_jump(self):
         raise NotImplementedError('JumpView cannot be called directly.')
         raise NotImplementedError('JumpView cannot be called directly.')
         
         
-    def __call__(self, request, slug=None, thread=None):
+    def __call__(self, request, slug=None, thread=None, post=None):
         self.request = request
         self.request = request
         try:
         try:
             self.fetch_thread(thread)
             self.fetch_thread(thread)
+            if post:
+                self.fetch_post(post)
             return self.make_jump()
             return self.make_jump()
-        except Thread.DoesNotExist:
+        except (Thread.DoesNotExist, Post.DoesNotExist):
             return error404(self.request)
             return error404(self.request)
         except ACLError403 as e:
         except ACLError403 as e:
             return error403(request, e.message)
             return error403(request, e.message)
@@ -43,6 +49,11 @@ class LastReplyView(JumpView):
         return self.redirect(self.thread.post_set.order_by('-id')[:1][0])
         return self.redirect(self.thread.post_set.order_by('-id')[:1][0])
 
 
 
 
+class FindReplyView(JumpView):
+    def make_jump(self):
+        return self.redirect(self.post)
+
+    
 class NewReplyView(JumpView):
 class NewReplyView(JumpView):
     def make_jump(self):
     def make_jump(self):
         if not self.request.user.is_authenticated():
         if not self.request.user.is_authenticated():

+ 11 - 2
misago/threads/views/posting.py

@@ -12,7 +12,7 @@ from misago.threads.forms import PostForm
 from misago.threads.models import Thread, Post
 from misago.threads.models import Thread, Post
 from misago.threads.views.base import BaseView
 from misago.threads.views.base import BaseView
 from misago.views import error403, error404
 from misago.views import error403, error404
-from misago.utils import make_pagination, slugify
+from misago.utils import make_pagination, slugify, ugettext_lazy
 
 
 class PostingView(BaseView):
 class PostingView(BaseView):
     def fetch_target(self, kwargs):
     def fetch_target(self, kwargs):
@@ -36,6 +36,7 @@ class PostingView(BaseView):
         self.parents = Forum.objects.forum_parents(self.forum.pk, True)
         self.parents = Forum.objects.forum_parents(self.forum.pk, True)
         if kwargs.get('quote'):
         if kwargs.get('quote'):
             self.quote = Post.objects.select_related('user').get(pk=kwargs['quote'], thread=self.thread.pk)
             self.quote = Post.objects.select_related('user').get(pk=kwargs['quote'], thread=self.thread.pk)
+            self.request.acl.threads.allow_post_view(self.request.user, self.thread, self.quote)
         
         
     def get_form(self, bound=False):            
     def get_form(self, bound=False):            
         if bound:            
         if bound:            
@@ -46,7 +47,7 @@ class PostingView(BaseView):
                 quote_post.append('@%s' % self.quote.user.username)
                 quote_post.append('@%s' % self.quote.user.username)
             else:
             else:
                 quote_post.append('@%s' % self.quote.user_name)
                 quote_post.append('@%s' % self.quote.user_name)
-            for line in self.quote.post.split('\n'):
+            for line in self.quote.post.splitlines():
                 quote_post.append('> %s' % line)
                 quote_post.append('> %s' % line)
             quote_post.append('\n')
             quote_post.append('\n')
             return PostForm(request=self.request,mode=self.mode,initial={'post': '\n'.join(quote_post)})
             return PostForm(request=self.request,mode=self.mode,initial={'post': '\n'.join(quote_post)})
@@ -130,11 +131,18 @@ class PostingView(BaseView):
                         thread.replies += 1
                         thread.replies += 1
                         if thread.last_poster_id != request.user.pk:
                         if thread.last_poster_id != request.user.pk:
                             thread.score += request.settings['thread_ranking_reply_score']
                             thread.score += request.settings['thread_ranking_reply_score']
+                        # Notify quoted poster of reply?
+                        if self.quote and self.quote.user_id and self.quote.user_id != request.user.pk:
+                            alert = self.quote.user.alert(ugettext_lazy("%(username)s has replied to your post in thread %(thread)s.").message)
+                            alert.url('username', request.user.username, reverse('user', kwargs={'user': request.user.pk, 'username': request.user.username_slug}))
+                            alert.url('thread', self.thread.name, reverse('thread_find', kwargs={'thread': self.thread.pk, 'slug': self.thread.slug, 'post': post.pk}))
+                            alert.save_all()
                         if (self.request.settings.thread_length > 0
                         if (self.request.settings.thread_length > 0
                             and not thread.closed
                             and not thread.closed
                             and thread.replies >= self.request.settings.thread_length):
                             and thread.replies >= self.request.settings.thread_length):
                             thread.closed = True
                             thread.closed = True
                             post.set_checkpoint(self.request, 'limit')
                             post.set_checkpoint(self.request, 'limit')
+                
                 if not moderation:
                 if not moderation:
                     thread.last = now
                     thread.last = now
                     thread.last_post = post
                     thread.last_post = post
@@ -201,6 +209,7 @@ class PostingView(BaseView):
                                                  'forum': self.forum,
                                                  'forum': self.forum,
                                                  'thread': self.thread,
                                                  'thread': self.thread,
                                                  'post': self.post,
                                                  'post': self.post,
+                                                 'quote': self.quote,
                                                  'parents': self.parents,
                                                  'parents': self.parents,
                                                  'message': message,
                                                  'message': message,
                                                  'form': FormLayout(form),
                                                  'form': FormLayout(form),

+ 0 - 2
misago/users/models.py

@@ -155,7 +155,6 @@ class User(models.Model):
     last_post = models.DateTimeField(null=True,blank=True)
     last_post = models.DateTimeField(null=True,blank=True)
     last_search = models.DateTimeField(null=True,blank=True)
     last_search = models.DateTimeField(null=True,blank=True)
     alerts = models.PositiveIntegerField(default=0)
     alerts = models.PositiveIntegerField(default=0)
-    alerts_new = models.PositiveIntegerField(default=0)
     alerts_date = models.DateTimeField(null=True,blank=True)
     alerts_date = models.DateTimeField(null=True,blank=True)
     activation = models.IntegerField(default=0)
     activation = models.IntegerField(default=0)
     token = models.CharField(max_length=12,null=True,blank=True)
     token = models.CharField(max_length=12,null=True,blank=True)
@@ -464,7 +463,6 @@ class User(models.Model):
     def alert(self, message):
     def alert(self, message):
         from misago.alerts.models import Alert
         from misago.alerts.models import Alert
         self.alerts += 1
         self.alerts += 1
-        self.alerts_new += 1
         return Alert(user=self, message=message, date=tz_util.now())
         return Alert(user=self, message=message, date=tz_util.now())
     
     
     def get_date(self):
     def get_date(self):

+ 0 - 2
misago/views.py

@@ -15,8 +15,6 @@ from misago.sessions.models import Session
 from misago.threads.models import Thread
 from misago.threads.models import Thread
 
 
 def home(request):
 def home(request):
-    # Alert ourselves
-    request.user.alert("%(username)s, you have checked board index page.").url('username', request.user.username, reverse('user', kwargs={'user': request.user.pk, 'username': request.user.username_slug})).save_all()
     # Threads ranking
     # Threads ranking
     popular_threads = cache.get('thread_ranking_%s' % request.user.make_acl_key(), 'nada')
     popular_threads = cache.get('thread_ranking_%s' % request.user.make_acl_key(), 'nada')
     if popular_threads == 'nada' and request.settings['thread_ranking_size'] > 0:
     if popular_threads == 'nada' and request.settings['thread_ranking_size'] > 0:

+ 1 - 2
static/sora/css/sora.css

@@ -934,8 +934,7 @@ td.lead-cell{color:#555555;font-weight:bold;}
 .navbar-userbar li a:hover,.navbar-userbar li a:active,.navbar-userbar li button.btn-link:hover,.navbar-userbar li button.btn-link:active{opacity:1;filter:alpha(opacity=100);color:#000000;}
 .navbar-userbar li a:hover,.navbar-userbar li a:active,.navbar-userbar li button.btn-link:hover,.navbar-userbar li button.btn-link:active{opacity:1;filter:alpha(opacity=100);color:#000000;}
 .navbar-userbar li i{background-image:url("../img/glyphicons-halflings.png");opacity:1;filter:alpha(opacity=100);}
 .navbar-userbar li i{background-image:url("../img/glyphicons-halflings.png");opacity:1;filter:alpha(opacity=100);}
 .navbar-userbar li form{margin:0px;padding:0px;}
 .navbar-userbar li form{margin:0px;padding:0px;}
-.navbar-userbar li span{-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;padding:2px 6px;margin:-1px 0px;margin-left:4px;color:#ffffff;font-size:90%;text-shadow:1px 1px 0px #000000;}.navbar-userbar li span.stat{background:#049cdb;}
-.navbar-userbar li span.stat.att{background:#9d261d;}
+.navbar-userbar li span{-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;padding:2px 6px;margin:-1px 0px;margin-left:4px;color:#ffffff;font-size:90%;text-shadow:1px 1px 0px #000000;}.navbar-userbar li span.stat{background:#ef2929;}
 .navbar-header{border-bottom:1px solid #0077b3;}.navbar-header .navbar-inner{background:none;background-color:#00aaff;border-bottom:4px solid #0099e6;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;}
 .navbar-header{border-bottom:1px solid #0077b3;}.navbar-header .navbar-inner{background:none;background-color:#00aaff;border-bottom:4px solid #0099e6;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;}
 .navbar-header .container{height:auto;}
 .navbar-header .container{height:auto;}
 .navbar-header a.brand{margin:24px 0px;padding:0px;font-size:230%;}.navbar-header a.brand span{color:#005580;text-shadow:0px 1px 0px #80d4ff;}
 .navbar-header a.brand{margin:24px 0px;padding:0px;font-size:230%;}.navbar-header a.brand span{color:#005580;text-shadow:0px 1px 0px #80d4ff;}

+ 1 - 5
static/sora/css/sora/navbar.less

@@ -62,11 +62,7 @@
       text-shadow: 1px 1px 0px @black;
       text-shadow: 1px 1px 0px @black;
       
       
       &.stat {
       &.stat {
-        background: @blue;
-      }
-      
-      &.stat.att {
-        background: @red;
+        background: #ef2929;
       }
       }
     }
     }
   }
   }

+ 4 - 4
templates/sora/alerts.html

@@ -2,7 +2,7 @@
 {% load i18n %}
 {% load i18n %}
 {% import "sora/macros.html" as macros with context %}
 {% import "sora/macros.html" as macros with context %}
 
 
-{% block title %}{% if user.alerts_new -%}
+{% block title %}{% if user.alerts -%}
 {{ macros.page_title(title=get_title(),parent=_('Your Notifications')) }}
 {{ macros.page_title(title=get_title(),parent=_('Your Notifications')) }}
 {%- else -%}
 {%- else -%}
 {{ macros.page_title(title=get_title()) }}
 {{ macros.page_title(title=get_title()) }}
@@ -10,7 +10,7 @@
 
 
 {% block content %}
 {% block content %}
 <div class="page-header">
 <div class="page-header">
-  <h1>{% if user.alerts_new %}{{ get_title() }} <small>{% trans %}Your Notifications{% endtrans %}</small>
+  <h1>{% if user.alerts %}{{ get_title() }} <small>{% trans %}Your Notifications{% endtrans %}</small>
       {%- else -%}
       {%- else -%}
       {% trans %}Your Notifications{% endtrans %}{% endif %}</h1>
       {% trans %}Your Notifications{% endtrans %}{% endif %}</h1>
 </div>
 </div>
@@ -28,8 +28,8 @@
 {% endblock %}
 {% endblock %}
 
 
 {% macro get_title() -%}
 {% macro get_title() -%}
-{% if user.alerts_new -%}
-{% trans count=user.alerts_new -%}
+{% if user.alerts -%}
+{% trans count=user.alerts -%}
 You have one new alert
 You have one new alert
 {%- pluralize -%}
 {%- pluralize -%}
 You have {{ count }} new alerts
 You have {{ count }} new alerts

+ 4 - 24
templates/sora/threads/posting.html

@@ -51,30 +51,6 @@
 </div>
 </div>
 {% endblock %}
 {% endblock %}
 
 
-{% block javascripts %}
-{{ super() }}
-    <script type="text/javascript">
-      $(function($){
-        var xhr = false;
-        preview = $('#md-preview')
-        $('#md-border').fadeIn(200);
-        $('#id_post').keyup(function() {
-          if (xhr != false) {
-            xhr.abort();
-          }
-          xhr = $.ajax({
-            type: "POST",
-            url: "{% url 'md_preview' %}",
-            data: { raw: $(this).val() },
-            success: function(data) {
-              $(preview).html(data);
-            }
-          });
-        });
-      });
-    </script>
-{% endblock %}
-
 
 
 {% macro get_action() -%}
 {% macro get_action() -%}
 {% if mode == 'new_thread' -%}
 {% if mode == 'new_thread' -%}
@@ -82,7 +58,11 @@
 {%- elif mode == 'edit_thread' -%}
 {%- elif mode == 'edit_thread' -%}
 NADA!
 NADA!
 {%- elif mode in ['new_post', 'new_post_quick'] -%}
 {%- elif mode in ['new_post', 'new_post_quick'] -%}
+{%- if quote -%}
+{% url 'thread_reply' thread=thread.pk, slug=thread.slug, quote=quote.pk %}
+{%- else -%}
 {% url 'thread_reply' thread=thread.pk, slug=thread.slug %}
 {% url 'thread_reply' thread=thread.pk, slug=thread.slug %}
+{%- endif -%}
 {%- elif mode == 'edit_post' -%}
 {%- elif mode == 'edit_post' -%}
 NADA!
 NADA!
 {%- endif %}
 {%- endif %}

+ 1 - 1
templates/sora/userbar.html

@@ -3,7 +3,7 @@
     <div class="container">
     <div class="container">
       <ul class="nav">{% if user.is_authenticated() %}
       <ul class="nav">{% if user.is_authenticated() %}
         <li><a href="#" title="{% trans %}Active Reports{% endtrans %}" class="tooltip-bottom"><i class="icon-warning-sign"></i><span class="stat">5</span></a></li>
         <li><a href="#" title="{% trans %}Active Reports{% endtrans %}" class="tooltip-bottom"><i class="icon-warning-sign"></i><span class="stat">5</span></a></li>
-        <li><a href="{% url 'alerts' %}" title="{% if user.alerts_new %}{% trans %}You have new notifications!{% endtrans %}{% else %}{% trans %}Your Notifications{% endtrans %}{% endif %}" class="tooltip-bottom"><i class="icon-fire"></i><span class="stat{% if user.alerts_new %} att{% endif %}">{% if user.alerts_new %}{{ user.alerts_new }}{% else %}{{ user.alerts }}{% endif %}</span></a></li>
+        <li><a href="{% url 'alerts' %}" title="{% if user.alerts %}{% trans %}You have new notifications!{% endtrans %}{% else %}{% trans %}Your Notifications{% endtrans %}{% endif %}" class="tooltip-bottom"><i class="icon-fire"></i>{% if user.alerts %}<span class="stat">{{ user.alerts }}</span>{% endif %}</a></li>
         <li><a href="#" title="{% trans %}Private messages{% endtrans %}" class="tooltip-bottom"><i class="icon-inbox"></i><span class="stat">2</span></a></li>
         <li><a href="#" title="{% trans %}Private messages{% endtrans %}" class="tooltip-bottom"><i class="icon-inbox"></i><span class="stat">2</span></a></li>
         <li><a href="#" title="{% trans %}People you are following{% endtrans %}" class="tooltip-bottom"><i class="icon-heart"></i></a></li>
         <li><a href="#" title="{% trans %}People you are following{% endtrans %}" class="tooltip-bottom"><i class="icon-heart"></i></a></li>
         <li><a href="#" title="{% trans %}Threads you are watching{% endtrans %}" class="tooltip-bottom"><i class="icon-bookmark"></i></a></li>{% endif %}
         <li><a href="#" title="{% trans %}Threads you are watching{% endtrans %}" class="tooltip-bottom"><i class="icon-bookmark"></i></a></li>{% endif %}