diff options
author | Aurélien Bompard <aurelien@bompard.org> | 2013-06-03 20:23:45 +0200 |
---|---|---|
committer | Aurélien Bompard <aurelien@bompard.org> | 2013-06-03 20:23:45 +0200 |
commit | fcdaa7f3fd2b830ca566386a1711070407c7f191 (patch) | |
tree | 24648e4e8c299addc68d44445c52d4d5cf35fd12 | |
parent | 30be2dbbcff4b01869bbb0120eb6679cc4b55cd0 (diff) | |
download | hyperkitty-fcdaa7f3fd2b830ca566386a1711070407c7f191.tar.gz hyperkitty-fcdaa7f3fd2b830ca566386a1711070407c7f191.tar.xz hyperkitty-fcdaa7f3fd2b830ca566386a1711070407c7f191.zip |
Add a navigation bar to skip through unread messages
-rw-r--r-- | hyperkitty/static/css/hyperkitty-message.css | 33 | ||||
-rw-r--r-- | hyperkitty/static/js/hyperkitty.js | 21 | ||||
-rw-r--r-- | hyperkitty/templates/thread.html | 62 | ||||
-rw-r--r-- | hyperkitty/templates/threads/right_col.html | 18 | ||||
-rw-r--r-- | hyperkitty/views/thread.py | 10 |
5 files changed, 101 insertions, 43 deletions
diff --git a/hyperkitty/static/css/hyperkitty-message.css b/hyperkitty/static/css/hyperkitty-message.css index 3e43e3d..3525aed 100644 --- a/hyperkitty/static/css/hyperkitty-message.css +++ b/hyperkitty/static/css/hyperkitty-message.css @@ -88,15 +88,22 @@ margin-right: 2em; } -.favorite a { +#thread-overview-info form.favorite { + margin-bottom: 0; +} +#thread-overview-info .favorite a { color: rgb(167, 169, 172); } -.favorite a.saved, -.favorite a.notsaved { +#thread-overview-info .favorite a.saved, +#thread-overview-info .favorite a.notsaved { /* Will be shown via Javascript */ display: none; } +#thread-overview-info .unread { + margin: 0 2px 0 2px; +} + /* Tags */ #tags { color: rgb(167, 169, 172); @@ -261,3 +268,23 @@ border-left: 2px solid rgb(55, 113, 200); padding-left: 0.2em; } + + +/* + * Navigation for unread messages + */ +#unreadnavbar { + position: fixed; + bottom: 0; + right: 0; + text-align: right; + padding-right: 2em; + display: none; +} +#unreadnavbar div { + width: auto; + padding: 0.2em 1em; + border: 1px solid #888; + border-bottom: none; + background-color: #eee; +} diff --git a/hyperkitty/static/js/hyperkitty.js b/hyperkitty/static/js/hyperkitty.js index 4b64b91..e43f766 100644 --- a/hyperkitty/static/js/hyperkitty.js +++ b/hyperkitty/static/js/hyperkitty.js @@ -263,14 +263,15 @@ function setup_replies(baseElem) { }).change(); } -function setup_navkeys() { +function setup_unreadnavbar(element) { + element = $(element); + if (element.length === 0) { + return; + } var current_index; - function scroll(e) { - var inc; + function scroll(inc) { var unreads = $(".email.unread"); if (unreads.length == 0) { return; } - if (e.data == "j") { inc = 1; } - if (e.data == "k") { inc = -1; } if (typeof current_index == "undefined") { if (inc == 1) { current_index = -1; } if (inc == -1) { current_index = unreads.length; } @@ -278,14 +279,18 @@ function setup_navkeys() { current_index = current_index + inc; if (current_index < 0) { current_index = unreads.length - 1; } if (current_index >= unreads.length) { current_index = 0; } + element.find(".unreadindex").text(current_index + 1); // compensate for the fixed banner at the top var target = unreads.eq(current_index).offset().top - 70; - $("html,body").animate({ + $("html,body").stop(true, false).animate({ scrollTop: target }, 500); } - $(document).bind("keydown", "j", scroll); - $(document).bind("keydown", "k", scroll); + element.find(".nextunread").click(function(e) { e.preventDefault(); scroll(1); }); + element.find(".prevunread").click(function(e) { e.preventDefault(); scroll(-1); }); + $(document).bind("keydown", "j", function(e) { scroll(1); }); + $(document).bind("keydown", "k", function(e) { scroll(-1); }); + element.animate({height: "show"}, 700); } diff --git a/hyperkitty/templates/thread.html b/hyperkitty/templates/thread.html index a25046e..e8b8139 100644 --- a/hyperkitty/templates/thread.html +++ b/hyperkitty/templates/thread.html @@ -31,38 +31,38 @@ <div class="row-fluid"> - <div class="span9"> - <!-- main section, the email thread --> - <section id="thread-content"> - - <!-- Start first email --> - {% include 'messages/message.html' with email=first_mail unfolded='True' %} - <!-- End first email --> - - <p class="sort-mode"> - {% if sort_mode == "date" %} - <a href="{% url 'thread' threadid=threadid mlist_fqdn=mlist.name %}?sort=thread" - >Show replies by thread</a> - {% else %} - <a href="{% url 'thread' threadid=threadid mlist_fqdn=mlist.name %}?sort=date" - >Show replies by date</a> - {% endif %} - </p> - - <div class="replies"> - {% if is_bot %} - {% include 'ajax/replies.html' %} - {% else %} - <img alt="Loading..." class="ajaxloader" src="{{ STATIC_URL }}img/ajax-loader.gif" /> - {% endif %} + <div class="span9"> + <!-- main section, the email thread --> + <section id="thread-content"> + + <!-- Start first email --> + {% include 'messages/message.html' with email=first_mail unfolded='True' %} + <!-- End first email --> + + <p class="sort-mode"> + {% if sort_mode == "date" %} + <a href="{% url 'thread' threadid=threadid mlist_fqdn=mlist.name %}?sort=thread" + >Show replies by thread</a> + {% else %} + <a href="{% url 'thread' threadid=threadid mlist_fqdn=mlist.name %}?sort=date" + >Show replies by date</a> + {% endif %} + </p> + + <div class="replies"> + {% if is_bot %} + {% include 'ajax/replies.html' %} + {% else %} + <img alt="Loading..." class="ajaxloader" src="{{ STATIC_URL }}img/ajax-loader.gif" /> + {% endif %} + </div> + + </section> </div> - </section> - </div> - - <div class="span3"> - {% include 'threads/right_col.html' %} - </div> + <div class="span3"> + {% include 'threads/right_col.html' %} + </div> </div> @@ -81,7 +81,7 @@ fold_quotes(); // Load the replies update_thread_replies("{% url 'thread_replies' threadid=threadid mlist_fqdn=mlist.name %}?sort={{sort_mode}}&last_view={{last_view|date:'U'}}"); - setup_navkeys(); + setup_unreadnavbar("#unreadnavbar"); }); </script> diff --git a/hyperkitty/templates/threads/right_col.html b/hyperkitty/templates/threads/right_col.html index 7f200fc..5011993 100644 --- a/hyperkitty/templates/threads/right_col.html +++ b/hyperkitty/templates/threads/right_col.html @@ -23,6 +23,7 @@ old </div> </div> + <!-- End dates --> <form id="fav_form" name="favorite" method="post" class="favorite" action="{% url 'favorite' mlist_fqdn=mlist.name threadid=threadid %}"> {% csrf_token %} @@ -32,7 +33,11 @@ <a href="#RmFav" class="saved">Remove from favorite discussions</a> </p> </form> - <!-- End dates --> + <p class="unread"> + {% if user.is_authenticated %} + <i class="unread icon-eye-close"></i> {{ unread_count }} unread messages + {% endif %} + </p> <div id="tags"> {% include 'threads/tags.html' %} </div> @@ -56,4 +61,15 @@ </div> </section> +{% if user.is_authenticated %} +<div id="unreadnavbar"> + <div> + Unreads: <span class="unreadindex">0</span>/{{unread_count}} + + Go to: <a href="#" class="nextunread">next ↓</a> + - <a href="#" class="prevunread">prev ↑</a> + </div> +</div> +{% endif %} + {# vim: set noet: #} diff --git a/hyperkitty/views/thread.py b/hyperkitty/views/thread.py index 03cfd6a..1e44714 100644 --- a/hyperkitty/views/thread.py +++ b/hyperkitty/views/thread.py @@ -118,6 +118,15 @@ def thread_index(request, mlist_fqdn, threadid, month=None, year=None): if not created: last_view = last_view_obj.view_date last_view_obj.save() # update timestamp + # get the number of unread messages + if last_view is None: + if request.user.is_authenticated(): + unread_count = len(thread) + else: + unread_count = 0 + else: + # XXX: Storm-specific + unread_count = thread.replies_after(last_view).count() # TODO: eventually move to a middleware ? # http://djangosnippets.org/snippets/1865/ @@ -145,6 +154,7 @@ def thread_index(request, mlist_fqdn, threadid, month=None, year=None): 'is_bot': is_bot, 'participants': thread.participants, 'last_view': last_view, + 'unread_count': unread_count, } context["participants"].sort(key=lambda x: x[0].lower()) |