summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAurélien Bompard <aurelien@bompard.org>2013-06-03 20:23:45 +0200
committerAurélien Bompard <aurelien@bompard.org>2013-06-03 20:23:45 +0200
commitfcdaa7f3fd2b830ca566386a1711070407c7f191 (patch)
tree24648e4e8c299addc68d44445c52d4d5cf35fd12
parent30be2dbbcff4b01869bbb0120eb6679cc4b55cd0 (diff)
downloadhyperkitty-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.css33
-rw-r--r--hyperkitty/static/js/hyperkitty.js21
-rw-r--r--hyperkitty/templates/thread.html62
-rw-r--r--hyperkitty/templates/threads/right_col.html18
-rw-r--r--hyperkitty/views/thread.py10
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}}
+ &nbsp;
+ Go to: <a href="#" class="nextunread">next &darr;</a>
+ - <a href="#" class="prevunread">prev &uarr;</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())