diff options
author | Byron Jones <glob@mozilla.com> | 2015-05-12 15:35:45 +0200 |
---|---|---|
committer | Byron Jones <glob@mozilla.com> | 2015-05-12 15:35:45 +0200 |
commit | 0215f11d5c734cb818ed7b988b8f73e745e45179 (patch) | |
tree | 7d2c7f9b769bfa560aab4f0590597a52378ce438 | |
parent | b7afadc6edb7a8f25acafaf08bd611b8ad5892ab (diff) | |
download | bugzilla-0215f11d5c734cb818ed7b988b8f73e745e45179.tar.gz bugzilla-0215f11d5c734cb818ed7b988b8f73e745e45179.tar.xz |
Bug 1146770: implement comment preview
-rw-r--r-- | Bugzilla/WebService/Server/REST/Resources/Bug.pm | 7 | ||||
-rw-r--r-- | extensions/BugModal/template/en/default/bug_modal/edit.html.tmpl | 12 | ||||
-rw-r--r-- | extensions/BugModal/template/en/default/bug_modal/new_comment.html.tmpl | 32 | ||||
-rw-r--r-- | extensions/BugModal/web/bug_modal.css | 50 | ||||
-rw-r--r-- | extensions/BugModal/web/bug_modal.js | 97 | ||||
-rw-r--r-- | skins/contrib/Mozilla-OpenSans/global.css | 2 | ||||
-rw-r--r-- | skins/contrib/Mozilla/global.css | 2 |
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 %]&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 %]&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; } |