summaryrefslogtreecommitdiffstats
path: root/extensions/BugModal
diff options
context:
space:
mode:
authorByron Jones <glob@mozilla.com>2015-06-05 06:40:01 +0200
committerByron Jones <glob@mozilla.com>2015-06-05 06:40:01 +0200
commit907fbcfd19dfa436567bf4a75f566b8f81f43298 (patch)
treebdbe5df647bdc5bbdbfe0a228bdb9d56d864ba40 /extensions/BugModal
parenta34e675b4ac3ebce28c2a0450fe75f8df38c540c (diff)
downloadbugzilla-907fbcfd19dfa436567bf4a75f566b8f81f43298.tar.gz
bugzilla-907fbcfd19dfa436567bf4a75f566b8f81f43298.tar.xz
Bug 1146775: implement comment collapse all and by tag
Diffstat (limited to 'extensions/BugModal')
-rw-r--r--extensions/BugModal/template/en/default/bug_modal/activity_stream.html.tmpl34
-rw-r--r--extensions/BugModal/template/en/default/bug_modal/header.html.tmpl2
-rw-r--r--extensions/BugModal/web/bug_modal.css17
-rw-r--r--extensions/BugModal/web/bug_modal.js45
-rw-r--r--extensions/BugModal/web/comments.js218
5 files changed, 274 insertions, 42 deletions
diff --git a/extensions/BugModal/template/en/default/bug_modal/activity_stream.html.tmpl b/extensions/BugModal/template/en/default/bug_modal/activity_stream.html.tmpl
index 11442985c..4bc860996 100644
--- a/extensions/BugModal/template/en/default/bug_modal/activity_stream.html.tmpl
+++ b/extensions/BugModal/template/en/default/bug_modal/activity_stream.html.tmpl
@@ -6,9 +6,25 @@
# defined by the Mozilla Public License, v. 2.0.
#%]
+<div id="comment-actions">
+ <button type="button" id="comment-tags-btn" style="display:none" class="minor">Tags &#9662;</button>
+ <button type="button" id="comment-toggle-btn" class="minor">Comments &#9662;</button>
+</div>
+
+<menu id="comment-toggle-menu" type="context" style="display:none">
+ <menuitem id="comment-reset" label="Reset"></menuitem>
+ <hr>
+ <menuitem id="comment-collapse-all" label="Collapse All"></menuitem>
+ <menuitem id="comment-expand-all" label="Expand All"></menuitem>
+ <hr>
+ <menuitem id="comments-only" label="Comments Only"></menuitem>
+ [% Hook.process('comments-toggle-menu') %]
+</menu>
+
[%
PROCESS bug/time.html.tmpl;
+ activity_counter = 0;
FOREACH change_set IN bug.activity_stream;
'<div class="change-set" id="' _ change_set.id _ '">';
@@ -22,7 +38,8 @@
IF change_set.comment;
PROCESS comment_header comment=change_set.comment;
ELSE;
- PROCESS activity_header activities=change_set.activity id=change_set.id;
+ activity_counter = activity_counter + 1;
+ PROCESS activity_header activities=change_set.activity id=activity_counter;
END;
IF change_set.comment;
@@ -95,16 +112,16 @@
data-no="[% comment.count FILTER none %]"
>Tag</button>
[% END %]
- <button class="reply-btn minor" type="button"
+ <button type="button" class="reply-btn minor"
data-reply-id="[% comment.count FILTER none %]"
data-reply-name="[% comment.author.name || comment.author.moz_nick FILTER html %]"
>Reply</button>
[% END %]
- <button class="comment-spinner minor" id="cs-[% comment.count FILTER none%]">-</button>
+ <button type="button" class="change-spinner minor" id="cs-[% comment.count FILTER none %]">-</button>
</td>
</tr>
- <tr>
+ <tr id="cr-[% comment.count FILTER none %]" [%= IF comment.collapsed %]style="display:none"[% END %]>
<td colspan="2">
<div class="change-name">
<a href="show_bug.cgi?id=[% bug.bug_id FILTER none %]#c[% comment.count FILTER none %]">
@@ -138,7 +155,7 @@
Comment hidden ([% comment.tags.join(', ') FILTER html %])
</td>
<td class="comment-actions">
- <button class="comment-spinner minor" id="ccs-[% comment.count FILTER none%]">
+ <button type="button" class="change-spinner minor" id="ccs-[% comment.count FILTER none %]">
[%~ comment.collapsed ? "+" : "-" ~%]
</button>
</td>
@@ -150,7 +167,7 @@
[% BLOCK activity_header %]
[% action = activities.0 %]
- <div id="[% id FILTER none %]" class="change">
+ <div class="change" id="a[% id FILTER none %]">
<table class="layout-table change-head [% extra_class FILTER none %]">
<tr>
<td rowspan="2" class="change-gravatar">
@@ -168,8 +185,11 @@
<span class="user-role">([% extra_class.ucfirst FILTER none %])</span>
[% END %]
</td>
+ <td class="comment-actions">
+ <button type="button" class="change-spinner minor" id="as-[% id FILTER none %]">-</button>
+ </td>
</tr>
- <tr>
+ <tr id="ar-[% id FILTER none %]">
<td colspan="2">
<div class="change-name">
<a href="show_bug.cgi?id=[% bug.bug_id FILTER none %]#[% id FILTER none %]">Updated</a>
diff --git a/extensions/BugModal/template/en/default/bug_modal/header.html.tmpl b/extensions/BugModal/template/en/default/bug_modal/header.html.tmpl
index a1aee3cfd..7fdb2ed49 100644
--- a/extensions/BugModal/template/en/default/bug_modal/header.html.tmpl
+++ b/extensions/BugModal/template/en/default/bug_modal/header.html.tmpl
@@ -58,11 +58,13 @@
);
jquery.push(
"datetimepicker",
+ "contextMenu",
);
style_urls.push(
"extensions/BugModal/web/bug_modal.css",
"skins/custom/bug_groups.css",
"js/jquery/plugins/datetimepicker/datetimepicker.css",
+ "js/jquery/plugins/contextMenu/contextMenu.css",
);
IF user.in_group('canconfirm');
diff --git a/extensions/BugModal/web/bug_modal.css b/extensions/BugModal/web/bug_modal.css
index 0d34039af..e3070f2a6 100644
--- a/extensions/BugModal/web/bug_modal.css
+++ b/extensions/BugModal/web/bug_modal.css
@@ -325,8 +325,7 @@ input[type="number"] {
/* actions */
#top-actions {
- margin-top: 5px;
- padding-bottom: 20px;
+ margin: 4px 0;
}
#top-actions .save-btn {
@@ -465,13 +464,18 @@ td.flag-requestee {
/* comments and activity */
+#comment-actions {
+ margin-top: 4px;
+ text-align: right;
+}
+
.change-set {
clear: both;
-webkit-box-shadow: 1px 1px 5px rgba(0, 0, 0, 0.1);
-moz-box-shadow: 1px 1px 5px rgba(0, 0, 0, 0.1);
box-shadow: 1px 1px 5px rgba(0, 0, 0, 0.1);
border-bottom: 1px solid rgba(0, 0, 0, 0.2);
- margin-top: 20px;
+ margin-top: 8px;
border: 1px solid #ddd;
}
@@ -488,10 +492,15 @@ td.flag-requestee {
padding-left: 8px !important;
}
+.change-gravatar .vcard {
+ width: 36px;
+ text-align: center;
+}
+
.change-author {
width: 100%;
vertical-align: top;
- padding-top: 4px !important;
+ padding: 5px 0 !important;
}
.change-author .vcard {
diff --git a/extensions/BugModal/web/bug_modal.js b/extensions/BugModal/web/bug_modal.js
index 473de438e..87cfcffdf 100644
--- a/extensions/BugModal/web/bug_modal.js
+++ b/extensions/BugModal/web/bug_modal.js
@@ -25,19 +25,6 @@ $(function() {
// products with descriptions (also lazy-loaded)
var products = [];
- // scroll to an element
- function scroll_to(el, complete) {
- var offset = el.offset();
- $('html, body')
- .animate({
- scrollTop: offset.top - 20,
- scrollLeft: offset.left = 20
- },
- 200,
- complete
- );
- }
-
// expand/collapse module
function slide_module(module, action, fast) {
if (!module.attr('id'))
@@ -120,7 +107,7 @@ $(function() {
.click(function(event) {
event.preventDefault();
var id = $('.comment:last')[0].parentNode.id;
- scroll_to($('#' + id));
+ $.scrollTo($('#' + id));
window.location.hash = id;
});
@@ -128,7 +115,7 @@ $(function() {
$('#top-btn')
.click(function(event) {
event.preventDefault();
- scroll_to($('body'));
+ $.scrollTo($('body'));
});
// use non-native tooltips for relative times and bug summaries
@@ -450,14 +437,14 @@ $(function() {
event.preventDefault();
// focus first to grow the textarea, so we scroll to the correct location
$('#comment').focus();
- scroll_to($('#bottom-save-btn'));
+ $.scrollTo($('#bottom-save-btn'));
});
// needinfo in people section -> scroll to near-comment ui
$('#needinfo-scroll')
.click(function(event) {
event.preventDefault();
- scroll_to($('#needinfo_role'), function() { $('#needinfo_role').focus(); });
+ $.scrollTo($('#needinfo_role'), function() { $('#needinfo_role').focus(); });
});
// knob
@@ -569,7 +556,7 @@ $(function() {
if ($('#comment').val() != reply_text) {
$('#comment').val($('#comment').val() + reply_text);
}
- scroll_to($('#comment'), function() { $('#comment').focus(); });
+ $.scrollTo($('#comment'), function() { $('#comment').focus(); });
});
// add comment --> enlarge on focus
@@ -606,10 +593,10 @@ $(function() {
$('#resolution').val($(event.target).text()).change();
$('#top-save-btn').show();
if ($(event.target).text() == "DUPLICATE") {
- scroll_to($('body'));
+ $.scrollTo($('body'));
}
else {
- scroll_to($('body'), function() { $('#resolution').focus(); });
+ $.scrollTo($('body'), function() { $('#resolution').focus(); });
}
});
$('.status-btn')
@@ -619,7 +606,7 @@ $(function() {
$('#field-status-edit').show();
$('#bug_status').val($(event.target).data('status')).change();
$('#top-save-btn').show();
- scroll_to($('body'), function() { $('#bug_status').focus(); });
+ $.scrollTo($('body'), function() { $('#bug_status').focus(); });
});
// vote button
@@ -651,7 +638,7 @@ $(function() {
if (current != text) {
$('#comment').val(current + text);
$('#comment').focus();
- scroll_to($('#bottom-save-btn'));
+ $.scrollTo($('#bottom-save-btn'));
}
});
@@ -1158,7 +1145,21 @@ function lb_close(event) {
}
// stick with inArray/indexOf and return -1 on no match
return -1;
+ },
+
+ // Animated scroll to bring an element into view
+ scrollTo: function(el, complete) {
+ var offset = el.offset();
+ $('html, body')
+ .animate({
+ scrollTop: offset.top - 20,
+ scrollLeft: offset.left = 20
+ },
+ 200,
+ complete
+ );
}
+
});
})(jQuery);
diff --git a/extensions/BugModal/web/comments.js b/extensions/BugModal/web/comments.js
index 1f0b18696..f0d689b3e 100644
--- a/extensions/BugModal/web/comments.js
+++ b/extensions/BugModal/web/comments.js
@@ -9,22 +9,220 @@ $(function() {
'use strict';
// comment collapse/expand
- $('.comment-spinner')
- .click(function(event) {
- event.preventDefault();
- var spinner = $(event.target);
- var id = spinner.attr('id').match(/\d+$/)[0];
- // switch to full header for initially collapsed comments
- if (spinner.attr('id').match(/^ccs-/)) {
+
+ function toggleChange(spinner, forced) {
+ // find and cache the id
+ var id = spinner.data('cid');
+ if (!id) {
+ id = spinner.attr('id').match(/\d+$/)[0];
+ spinner.data('cid', id);
+ }
+
+ // non-comment toggle
+ if (spinner.attr('id').substr(0, 1) == 'a') {
+ var changeSet = spinner.parents('.change-set');
+ if (forced == 'hide') {
+ changeSet.find('.activity').hide();
+ changeSet.find('.gravatar').css('width', '16px').css('height', '16px');
+ $('#ar-' + id).hide();
+ spinner.text('+');
+ }
+ else if (forced == 'show' || forced == 'reset') {
+ changeSet.find('.activity').show();
+ changeSet.find('.gravatar').css('width', '32px').css('height', '32px');
+ $('#ar-' + id).show();
+ spinner.text('-');
+ }
+ else {
+ changeSet.find('.activity').slideToggle('fast', function() {
+ $('#ar-' + id).toggle();
+ if (changeSet.find('.activity:visible').length) {
+ changeSet.find('.gravatar').css('width', '32px').css('height', '32px');
+ spinner.text('-');
+ }
+ else {
+ changeSet.find('.gravatar').css('width', '16px').css('height', '16px');
+ spinner.text('+');
+ }
+ });
+ }
+ return;
+ }
+
+ // find the "real spinner", which is the one on the non-default-collapsed block
+ var realSpinner = $('#cs-' + id);
+ var defaultCollapsed = realSpinner.data('ch');
+ if (defaultCollapsed === undefined) {
+ defaultCollapsed = spinner.attr('id').substring(0, 4) === 'ccs-';
+ realSpinner.data('ch', defaultCollapsed);
+ }
+ if (forced === 'reset') {
+ forced = defaultCollapsed ? 'hide' : 'show';
+ }
+
+ // comment toggle
+ if (forced === 'hide') {
+ if (defaultCollapsed) {
+ $('#ch-' + id).hide();
+ $('#cc-' + id).show();
+ }
+ $('#ct-' + id).hide();
+ if (BUGZILLA.user.id !== 0)
+ $('#ctag-' + id).hide();
+ $('#c' + id).find('.activity').hide();
+ $('#c' + id).find('.comment-tags').hide();
+ $('#c' + id).find('.comment-tags').hide();
+ $('#c' + id).find('.gravatar').css('width', '16px').css('height', '16px');
+ $('#cr-' + id).hide();
+ spinner.text('+');
+ }
+ else if (forced == 'show') {
+ if (defaultCollapsed) {
$('#cc-' + id).hide();
$('#ch-' + id).show();
}
- $('#ct-' + id + ', #ctag-' + id).slideToggle('fast', function() {
+ $('#ct-' + id).show();
+ if (BUGZILLA.user.id !== 0)
+ $('#ctag-' + id).show();
+ $('#c' + id).find('.activity').show();
+ $('#c' + id).find('.comment-tags').show();
+ $('#c' + id).find('.comment-tags').show();
+ $('#c' + id).find('.gravatar').css('width', '32px').css('height', '32px');
+ $('#cr-' + id).show();
+ spinner.text('-');
+ }
+ else {
+ $('#ct-' + id).slideToggle('fast', function() {
$('#c' + id).find('.activity').toggle();
- spinner.text($('#ct-' + id + ':visible').length ? '-' : '+');
+ $('#c' + id).find('.comment-tags').toggle();
+ if ($('#ct-' + id + ':visible').length) {
+ spinner.text('-');
+ $('#cr-' + id).show();
+ if (BUGZILLA.user.id !== 0)
+ $('#ctag-' + id).show();
+ $('#c' + id).find('.gravatar').css('width', '32px').css('height', '32px');
+ if (defaultCollapsed) {
+ $('#cc-' + id).hide();
+ $('#ch-' + id).show();
+ }
+ }
+ else {
+ spinner.text('+');
+ $('#cr-' + id).hide();
+ if (BUGZILLA.user.id !== 0)
+ $('#ctag-' + id).hide();
+ $('#c' + id).find('.gravatar').css('width', '16px').css('height', '16px');
+ if (defaultCollapsed) {
+ $('#ch-' + id).hide();
+ $('#cc-' + id).show();
+ }
+ }
});
+ }
+ }
+
+ $('.change-spinner')
+ .click(function(event) {
+ event.preventDefault();
+ toggleChange($(this));
});
+ // comment and tag menus
+
+ $('#comment-reset')
+ .click(function() {
+ $('.change-spinner:visible').each(function() {
+ toggleChange($(this), 'reset');
+ });
+ });
+
+ $('#comment-collapse-all')
+ .click(function() {
+ $('.change-spinner:visible').each(function() {
+ toggleChange($(this), 'hide');
+ });
+ });
+
+ $('#comment-expand-all')
+ .click(function() {
+ $('.change-spinner:visible').each(function() {
+ toggleChange($(this), 'show');
+ });
+ });
+
+ $('#comments-only')
+ .click(function() {
+ $('.change-spinner:visible').each(function() {
+ toggleChange($(this), this.id.substr(0, 3) === 'cs-' ? 'show' : 'hide');
+ });
+ });
+
+ $.contextMenu({
+ selector: '#comment-toggle-btn',
+ trigger: 'left',
+ items: $.contextMenu.fromMenu($('#comment-toggle-menu'))
+ });
+
+ function updateTagsMenu() {
+ var tags = [];
+ $('.comment-tags').each(function() {
+ $.each(tagsFromDom($(this)), function() {
+ var tag = this.toLowerCase();
+ if (tag in tags) {
+ tags[tag]++;
+ }
+ else {
+ tags[tag] = 1;
+ }
+ });
+ });
+ var tagNames = Object.keys(tags);
+ tagNames.sort();
+
+ var btn = $('#comment-tags-btn');
+ if (tagNames.length === 0) {
+ btn.hide();
+ return;
+ }
+ btn.show();
+
+ var menuItems = [
+ { name: 'Reset', tag: '' },
+ "--"
+ ];
+ $.each(tagNames, function(key, value) {
+ menuItems.push({ name: value + ' (' + tags[value] + ')', tag: value });
+ });
+
+ $.contextMenu('destroy', '#comment-tags-btn');
+ $.contextMenu({
+ selector: '#comment-tags-btn',
+ trigger: 'left',
+ items: menuItems,
+ callback: function(key, opt) {
+ var tag = opt.commands[key].tag;
+ if (tag === '') {
+ $('.change-spinner:visible').each(function() {
+ toggleChange($(this), 'reset');
+ });
+ return;
+ }
+ var firstComment = false;
+ $('.change-spinner:visible').each(function() {
+ var that = $(this);
+ var commentTags = tagsFromDom(that.parents('.comment').find('.comment-tags'));
+ var hasTag = $.inArrayIn(tag, commentTags) >= 0;
+ toggleChange(that, hasTag ? 'show' : 'hide');
+ if (hasTag && !firstComment) {
+ firstComment = that;
+ }
+ });
+ if (firstComment)
+ $.scrollTo(firstComment);
+ }
+ });
+ }
+
//
// anything after this point is only executed for logged in users
//
@@ -259,4 +457,6 @@ $(function() {
event.preventDefault();
$('#' + $(this).data('for')).hide();
});
+
+ updateTagsMenu();
});