summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorByron Jones <glob@mozilla.com>2015-05-12 15:35:45 +0200
committerByron Jones <glob@mozilla.com>2015-05-12 15:35:45 +0200
commit0215f11d5c734cb818ed7b988b8f73e745e45179 (patch)
tree7d2c7f9b769bfa560aab4f0590597a52378ce438
parentb7afadc6edb7a8f25acafaf08bd611b8ad5892ab (diff)
downloadbugzilla-0215f11d5c734cb818ed7b988b8f73e745e45179.tar.gz
bugzilla-0215f11d5c734cb818ed7b988b8f73e745e45179.tar.xz
Bug 1146770: implement comment preview
-rw-r--r--Bugzilla/WebService/Server/REST/Resources/Bug.pm7
-rw-r--r--extensions/BugModal/template/en/default/bug_modal/edit.html.tmpl12
-rw-r--r--extensions/BugModal/template/en/default/bug_modal/new_comment.html.tmpl32
-rw-r--r--extensions/BugModal/web/bug_modal.css50
-rw-r--r--extensions/BugModal/web/bug_modal.js97
-rw-r--r--skins/contrib/Mozilla-OpenSans/global.css2
-rw-r--r--skins/contrib/Mozilla/global.css2
7 files changed, 175 insertions, 27 deletions
diff --git a/Bugzilla/WebService/Server/REST/Resources/Bug.pm b/Bugzilla/WebService/Server/REST/Resources/Bug.pm
index 8c73e32e6..163790b77 100644
--- a/Bugzilla/WebService/Server/REST/Resources/Bug.pm
+++ b/Bugzilla/WebService/Server/REST/Resources/Bug.pm
@@ -62,7 +62,7 @@ sub _rest_resources {
success_code => STATUS_CREATED
}
},
- qr{^/bug/comment/([^/]+)$}, {
+ qr{^/bug/comment/(\d+)$}, {
GET => {
method => 'comments',
params => sub {
@@ -86,6 +86,11 @@ sub _rest_resources {
},
},
},
+ qr{^/bug/comment/render$}, {
+ POST => {
+ method => 'render_comment',
+ },
+ },
qr{^/bug/([^/]+)/history$}, {
GET => {
method => 'history',
diff --git a/extensions/BugModal/template/en/default/bug_modal/edit.html.tmpl b/extensions/BugModal/template/en/default/bug_modal/edit.html.tmpl
index dd673537c..67c94f499 100644
--- a/extensions/BugModal/template/en/default/bug_modal/edit.html.tmpl
+++ b/extensions/BugModal/template/en/default/bug_modal/edit.html.tmpl
@@ -978,6 +978,13 @@
INCLUDE bug_modal/activity_stream.html.tmpl stream=bug.activity_stream;
IF user.id;
INCLUDE bug_modal/new_comment.html.tmpl;
+ ELSE;
+ %]
+ <div id="new-comment-notice">
+ You need to <a href="show_bug.cgi?id=[% bug.bug_id FILTER none %]&amp;GoAheadAndLogIn=1">log in</a>
+ before you can comment on or make changes to this [% terms.bug %].
+ </div>
+ [%
END;
%]
@@ -1007,11 +1014,6 @@
</div>
</div>
</form>
-[% ELSE %]
- <div id="login-required">
- You need to <a href="show_bug.cgi?id=[% bug.bug_id FILTER none %]&amp;GoAheadAndLogIn=1">log in</a>
- before you can comment on or make changes to this [% terms.bug %].
- </div>
[% END %]
[%# === blocks === %]
diff --git a/extensions/BugModal/template/en/default/bug_modal/new_comment.html.tmpl b/extensions/BugModal/template/en/default/bug_modal/new_comment.html.tmpl
index f6c3bb3fa..17bf38200 100644
--- a/extensions/BugModal/template/en/default/bug_modal/new_comment.html.tmpl
+++ b/extensions/BugModal/template/en/default/bug_modal/new_comment.html.tmpl
@@ -12,8 +12,15 @@
#%]
<div id="add-comment">
- <div id="add-comment-label">Add Comment:</div>
- [% IF user.is_insider && bug.check_can_change_field('longdesc', 0, 1) %]
+
+ [% IF !bug.check_can_change_field('longdesc', 0, 1) %]
+ <div id="new-comment-notice">
+ You are not allowed to make an additional comment on this [% terms.bug %].
+ </div>
+ [% RETURN %]
+ [% END %]
+
+ [% IF user.is_insider %]
<div id="add-comment-private"
title="Make comment visible only to members of the '[% Param('insidergroup') FILTER html %]' group"
>
@@ -22,7 +29,26 @@
<label for="add-comment-private-cb">Private</label>
</div>
[% END %]
- <textarea rows="5" cols="80" name="comment" id="comment"></textarea>
+
+ <ul id="comment-tabs">
+ <li id="comment-edit-tab" data-tab="comment-tab-add" data-focus="comment" class="current">
+ Add Comment
+ </li>
+ [%~ ~%]
+ <li id="comment-preview-tab" data-tab="comment-tab-preview" data-focus="">
+ Preview
+ <img id="preview-throbber" src="extensions/BugModal/web/throbber.gif" width="16" height="11" style="display:none">
+ </li>
+ </ul>
+
+ <div id="comment-tab-add" class="comment-tab">
+ <textarea rows="5" cols="80" name="comment" id="comment"></textarea>
+ </div>
+ <div id="comment-tab-preview" class="comment-tab" style="display:none">
+ <pre id="comment-preview" class="comment-text"></pre>
+ </div>
+ </div>
+
<div id="after-comment-commit-button">
[% Hook.process("after_comment_commit_button", 'bug/edit.html.tmpl') %]
diff --git a/extensions/BugModal/web/bug_modal.css b/extensions/BugModal/web/bug_modal.css
index 910199a53..acb18638f 100644
--- a/extensions/BugModal/web/bug_modal.css
+++ b/extensions/BugModal/web/bug_modal.css
@@ -270,7 +270,7 @@ input[type="number"] {
float: right;
}
-#login-required {
+#new-comment-notice {
padding: 20px 8px;
margin-bottom: 50px;
}
@@ -576,18 +576,56 @@ td.flag-requestee {
margin-top: 20px;
}
-#add-comment-label {
- display: inline;
- font-weight: bold;
-}
-
#add-comment-private {
float: right;
}
#comment {
+ border: 1px solid #ccc;
+}
+
+#comment, #comment-preview {
+ clear: both;
width: 100%;
box-sizing: border-box !important;
+ margin: 0 0 1em;
+}
+
+#comment-preview {
+ border: 1px solid #fff;
+ -moz-box-shadow: none;
+ -webkit-box-shadow: none;
+ box-shadow: none;
+ padding: 4px 3px 5px;
+}
+
+#preview-throbber {
+ margin-left: 8px;
+}
+
+#comment-tabs {
+ margin: 0px;
+ padding: 0px;
+ list-style: none;
+}
+
+#comment-tabs li {
+ display: inline-block;
+ padding: 4px 8px;
+ cursor: pointer;
+ border: 1px solid silver;
+ border-top-left-radius: 2px;
+ border-top-right-radius: 2px;
+}
+
+#comment-tabs li.current {
+ background: #fff;
+ border-bottom: 1px solid #fff;
+}
+
+.preview-error {
+ color: #666;
+ font-style: italic;
}
/* controls */
diff --git a/extensions/BugModal/web/bug_modal.js b/extensions/BugModal/web/bug_modal.js
index 9e7f5f8f9..419ac1e84 100644
--- a/extensions/BugModal/web/bug_modal.js
+++ b/extensions/BugModal/web/bug_modal.js
@@ -742,14 +742,31 @@ $(function() {
.keydown(function(event) {
if (!(event.ctrlKey || event.metaKey))
return;
- // don't conflict with text input shortcut
- if (document.activeElement.nodeNode == 'INPUT' || document.activeElement.nodeName == 'TEXTAREA')
- return;
- if (String.fromCharCode(event.which).toLowerCase() == 'e') {
- if ($('#cancel-btn:visible').length === 0) {
- event.preventDefault();
- $('#mode-btn').click();
- }
+ switch(String.fromCharCode(event.which).toLowerCase()) {
+ // ctrl+e or meta+e = enter edit mode
+ case 'e':
+ // don't conflict with text input shortcut
+ if (document.activeElement.nodeNode == 'INPUT' || document.activeElement.nodeName == 'TEXTAREA')
+ return;
+ if ($('#cancel-btn:visible').length === 0) {
+ event.preventDefault();
+ $('#mode-btn').click();
+ }
+ break;
+
+ // ctrl+shift+p = toggle comment preview
+ case 'p':
+ if (event.metaKey || !event.shiftKey)
+ return;
+ if (document.activeElement.id == 'comment') {
+ event.preventDefault();
+ $('#comment-preview-tab').click();
+ }
+ else if ($('#comment-preview:visible').length !== 0) {
+ event.preventDefault();
+ $('#comment-edit-tab').click();
+ }
+ break;
}
});
@@ -892,6 +909,60 @@ $(function() {
.prop('title', message)
.show();
});
+
+ // comment preview
+ var last_comment_text = '';
+ $('#comment-tabs li').click(function() {
+ var that = $(this);
+ if (that.hasClass('current'))
+ return;
+
+ // ensure preview's height matches the comment
+ var comment = $('#comment');
+ var preview = $('#comment-preview');
+ var comment_height = comment[0].offsetHeight;
+
+ // change tabs
+ $('#comment-tabs li').removeClass('current').attr('aria-selected', false);
+ $('.comment-tab').hide();
+ that.addClass('current').attr('aria-selected', true);
+ var tab = that.attr('data-tab');
+ $('#' + tab).show();
+ var focus = that.data('focus');
+ if (focus === '') {
+ document.activeElement.blur();
+ }
+ else {
+ $('#' + focus).focus();
+ }
+
+ // update preview
+ preview.css('height', comment_height + 'px');
+ if (tab != 'comment-tab-preview' || last_comment_text == comment.val())
+ return;
+ $('#preview-throbber').show();
+ preview.html('');
+ bugzilla_ajax(
+ {
+ url: 'rest/bug/comment/render',
+ type: 'POST',
+ data: { text: comment.val() },
+ hideError: true
+ },
+ function(data) {
+ $('#preview-throbber').hide();
+ preview.html(data.html);
+ },
+ function(message) {
+ $('#preview-throbber').hide();
+ var container = $('<div/>');
+ container.addClass('preview-error');
+ container.text(message);
+ preview.html(container);
+ }
+ );
+ last_comment_text = comment.val();
+ });
});
function confirmUnsafeURL(url) {
@@ -921,6 +992,10 @@ function bugzilla_ajax(request, done_fn, error_fn) {
'Bugzilla_api_token=' + encodeURIComponent(BUGZILLA.api_token);
if (request.type != 'GET') {
request.contentType = 'application/json';
+ request.processData = false;
+ if (request.data && request.data.constructor === Object) {
+ request.data = JSON.stringify(request.data);
+ }
}
$.ajax(request)
.done(function(data) {
@@ -936,8 +1011,10 @@ function bugzilla_ajax(request, done_fn, error_fn) {
})
.error(function(data) {
var message = data.responseJSON ? data.responseJSON.message : 'Unexpected Error'; // all errors are unexpected :)
- $('#xhr-error').html(message);
- $('#xhr-error').show('fast');
+ if (!request.hideError) {
+ $('#xhr-error').html(message);
+ $('#xhr-error').show('fast');
+ }
if (error_fn)
error_fn(message);
});
diff --git a/skins/contrib/Mozilla-OpenSans/global.css b/skins/contrib/Mozilla-OpenSans/global.css
index a6c82deb8..044e631b6 100644
--- a/skins/contrib/Mozilla-OpenSans/global.css
+++ b/skins/contrib/Mozilla-OpenSans/global.css
@@ -462,7 +462,7 @@ table.edit_form hr {
margin: 0 0 20px;
}
-.bz_comment pre, #comment {
+.bz_comment pre, #comment, #comment-preview {
font: 13px/1.2 "Droid Sans Mono", Menlo, Monaco, "Courier New", Courier, monospace;
}
diff --git a/skins/contrib/Mozilla/global.css b/skins/contrib/Mozilla/global.css
index fd3288cc1..832d7f162 100644
--- a/skins/contrib/Mozilla/global.css
+++ b/skins/contrib/Mozilla/global.css
@@ -505,7 +505,7 @@ table.edit_form hr {
margin: 0 0 20px;
}
-.bz_comment pre, #comment {
+.bz_comment pre, #comment, #comment-preview {
font: 13px/1.2 "Droid Sans Mono", Menlo, Monaco, "Courier New", Courier, monospace;
}