summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Bugzilla/WebService/Bug.pm67
-rw-r--r--js/field.js76
-rw-r--r--skins/contrib/Mozilla/global.css20
-rw-r--r--skins/standard/global.css34
-rw-r--r--template/en/default/bug/comment.html.tmpl36
-rw-r--r--template/en/default/bug/create/create.html.tmpl4
-rw-r--r--template/en/default/bug/edit.html.tmpl4
7 files changed, 232 insertions, 9 deletions
diff --git a/Bugzilla/WebService/Bug.pm b/Bugzilla/WebService/Bug.pm
index ab2e85a93..e37d1cd00 100644
--- a/Bugzilla/WebService/Bug.pm
+++ b/Bugzilla/WebService/Bug.pm
@@ -325,6 +325,30 @@ sub comments {
return { bugs => \%bugs, comments => \%comments };
}
+sub render_comment {
+ my ($self, $params) = @_;
+
+ unless (defined $params->{text}) {
+ ThrowCodeError('params_required',
+ { function => 'Bug.render_comment',
+ params => ['text'] });
+ }
+
+ Bugzilla->switch_to_shadow_db();
+ my $bug = $params->{id} ? Bugzilla::Bug->check($params->{id}) : undef;
+
+ my $tmpl = '[% text FILTER quoteUrls(bug) %]';
+ my $html;
+ my $template = Bugzilla->template;
+ $template->process(
+ \$tmpl,
+ { bug => $bug, text => $params->{text}},
+ \$html
+ );
+
+ return { html => $html };
+}
+
# Helper for Bug.comments
sub _translate_comment {
my ($self, $comment, $filters) = @_;
@@ -4508,3 +4532,46 @@ this bug.
=back
=back
+
+=head2 render_comment
+
+B<UNSTABLE>
+
+=over
+
+=item B<Description>
+
+Returns the HTML rendering of the provided comment text.
+
+=item B<Params>
+
+=over
+
+=item C<text>
+
+B<Required> C<strings> Text comment text to render.
+
+=item C<id>
+
+C<int> The ID of the bug to render the comment against.
+
+=back
+
+=item B<Returns>
+
+C<html> containing the HTML rendering.
+
+=item B<Errors>
+
+This method can throw all of the errors that L</get> throws.
+
+=item B<History>
+
+=over
+
+=item Added in Bugzilla B<5.0>.
+
+=back
+
+=back
+
diff --git a/js/field.js b/js/field.js
index 6f42fe8a4..92eb50418 100644
--- a/js/field.js
+++ b/js/field.js
@@ -853,3 +853,79 @@ function initDirtyFieldTracking() {
});
}
}
+
+/**
+ * Comment preview
+ */
+
+var last_comment_text = '';
+
+function show_comment_preview(bug_id) {
+ var Dom = YAHOO.util.Dom;
+ var comment = document.getElementById('comment');
+ var preview = document.getElementById('comment_preview');
+ if (!comment || !preview) return;
+ if (Dom.hasClass('comment_preview_tab', 'active_comment_tab')) return;
+
+ preview.style.width = (comment.clientWidth - 4) + 'px';
+ preview.style.height = comment.offsetHeight + 'px';
+
+ Dom.addClass(comment, 'bz_default_hidden');
+ Dom.removeClass('comment_tab', 'active_comment_tab');
+ Dom.removeClass(preview, 'bz_default_hidden');
+ Dom.addClass('comment_preview_tab', 'active_comment_tab');
+
+ Dom.addClass('comment_preview_error', 'bz_default_hidden');
+
+ if (last_comment_text == comment.value)
+ return;
+
+ Dom.addClass('comment_preview_text', 'bz_default_hidden');
+ Dom.removeClass('comment_preview_loading', 'bz_default_hidden');
+
+ YAHOO.util.Connect.setDefaultPostHeader('application/json', true);
+ YAHOO.util.Connect.asyncRequest('POST', 'jsonrpc.cgi',
+ {
+ success: function(res) {
+ data = YAHOO.lang.JSON.parse(res.responseText);
+ if (data.error) {
+ Dom.addClass('comment_preview_loading', 'bz_default_hidden');
+ Dom.removeClass('comment_preview_error', 'bz_default_hidden');
+ Dom.get('comment_preview_error').innerHTML =
+ YAHOO.lang.escapeHTML(data.error.message);
+ } else {
+ document.getElementById('comment_preview_text').innerHTML = data.result.html;
+ Dom.addClass('comment_preview_loading', 'bz_default_hidden');
+ Dom.removeClass('comment_preview_text', 'bz_default_hidden');
+ last_comment_text = comment.value;
+ }
+ },
+ failure: function(res) {
+ Dom.addClass('comment_preview_loading', 'bz_default_hidden');
+ Dom.removeClass('comment_preview_error', 'bz_default_hidden');
+ Dom.get('comment_preview_error').innerHTML =
+ YAHOO.lang.escapeHTML(res.responseText);
+ }
+ },
+ YAHOO.lang.JSON.stringify({
+ version: "1.1",
+ method: 'Bug.render_comment',
+ params: {
+ id: bug_id,
+ text: comment.value
+ }
+ })
+ );
+}
+
+function show_comment_edit() {
+ var comment = document.getElementById('comment');
+ var preview = document.getElementById('comment_preview');
+ if (!comment || !preview) return;
+ if (YAHOO.util.Dom.hasClass(comment, 'active_comment_tab')) return;
+
+ YAHOO.util.Dom.addClass(preview, 'bz_default_hidden');
+ YAHOO.util.Dom.removeClass('comment_preview_tab', 'active_comment_tab');
+ YAHOO.util.Dom.removeClass(comment, 'bz_default_hidden');
+ YAHOO.util.Dom.addClass('comment_tab', 'active_comment_tab');
+}
diff --git a/skins/contrib/Mozilla/global.css b/skins/contrib/Mozilla/global.css
index 4d6fd7113..d47c4e2f8 100644
--- a/skins/contrib/Mozilla/global.css
+++ b/skins/contrib/Mozilla/global.css
@@ -449,11 +449,15 @@ table.edit_form hr {
}
.bz_comment {
- width: 65em !important;
+ width: 65em;
margin: 0 0 20px;
}
-.bz_comment pre {
+.bz_comment_table .bz_comment {
+ width: 65em !important;
+}
+
+.bz_comment pre, #comment {
font: 13px/1.2 "Droid Sans Mono", Menlo, Monaco, "Courier New", Courier, monospace;
}
@@ -618,7 +622,17 @@ table.edit_form hr {
-moz-box-sizing: content-box;
-webkit-box-sizing: content-box;
box-sizing: content-box;
- margin: 5px 0 20px;
+}
+
+#comment_tabs {
+ margin-top: 2px;
+}
+
+#comment_preview_text {
+ background: transparent;
+ border: none;
+ box-shadow: none;
+ padding: 2px 2px 2px 1px;
}
#footer {
diff --git a/skins/standard/global.css b/skins/standard/global.css
index bb44a919b..25a60f750 100644
--- a/skins/standard/global.css
+++ b/skins/standard/global.css
@@ -586,6 +586,40 @@ input.required, select.required, span.required_explanation {
margin-left: -1px;
}
+.comment_tab {
+ float: left;
+ border: 1px solid silver;
+ border-bottom: 0px;
+ padding: 2px 1em;
+ cursor: pointer;
+ background: transparent;
+}
+
+.active_comment_tab {
+ background: #fff;
+ font-weight: bold;
+}
+
+#comment_preview {
+ border: 1px solid silver;
+ padding: 2px;
+ overflow: auto;
+ margin: 0px;
+}
+
+#comment_preview_text {
+ margin: 0px;
+ width: auto;
+}
+
+#comment_preview_loading {
+ font-style: italic;
+}
+
+#comment {
+ margin-top: 0px;
+}
+
/*******************/
/* Form Validation */
/*******************/
diff --git a/template/en/default/bug/comment.html.tmpl b/template/en/default/bug/comment.html.tmpl
new file mode 100644
index 000000000..1d8cf0b30
--- /dev/null
+++ b/template/en/default/bug/comment.html.tmpl
@@ -0,0 +1,36 @@
+[%# This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ #
+ # This Source Code Form is "Incompatible With Secondary Licenses", as
+ # defined by the Mozilla Public License, v. 2.0.
+ #%]
+
+[%# INTERFACE:
+ #
+ # This template supports the same parameters as global/textarea.html.tmpl
+ # with the exception of "name" and "id", which will always be "comment".
+ #%]
+
+[% IF feature_enabled('jsonrpc') %]
+ <div id="comment_tabs">
+ <div id="comment_tab" class="comment_tab active_comment_tab"
+ onclick="show_comment_edit()">Comment</div>
+ <div id="comment_preview_tab" class="comment_tab"
+ onclick="show_comment_preview([% bug.id FILTER none %])">Preview</div>
+ </div>
+[% END %]
+
+[% INCLUDE global/textarea.html.tmpl
+ name = "comment"
+ id = "comment"
+%]
+<br>
+
+[% IF feature_enabled('jsonrpc') %]
+ <div id="comment_preview" class="bz_default_hidden bz_comment">
+ <div id="comment_preview_loading" class="bz_default_hidden">Generating Preview...</div>
+ <div id="comment_preview_error" class="bz_default_hidden"></div>
+ <pre id="comment_preview_text" class="bz_comment_text"></pre>
+ </div>
+[% END %]
diff --git a/template/en/default/bug/create/create.html.tmpl b/template/en/default/bug/create/create.html.tmpl
index b357b3eb0..02256721c 100644
--- a/template/en/default/bug/create/create.html.tmpl
+++ b/template/en/default/bug/create/create.html.tmpl
@@ -522,9 +522,7 @@ TUI_hide_default('attachment_text_field');
# by global/textarea.html.tmpl. So we must not escape the comment here. %]
[% comment FILTER none %]
[%- END %]
- [% INCLUDE global/textarea.html.tmpl
- name = 'comment'
- id = 'comment'
+ [% INCLUDE bug/comment.html.tmpl
minrows = 10
maxrows = 25
cols = constants.COMMENT_COLS
diff --git a/template/en/default/bug/edit.html.tmpl b/template/en/default/bug/edit.html.tmpl
index 3c2ce47c2..fe6b27bc7 100644
--- a/template/en/default/bug/edit.html.tmpl
+++ b/template/en/default/bug/edit.html.tmpl
@@ -1156,9 +1156,7 @@
<!-- This table keeps the submit button aligned with the box. -->
<table><tr><td>
[% IF bug.check_can_change_field('longdesc', 0, 1) %]
- [% INCLUDE global/textarea.html.tmpl
- name = 'comment'
- id = 'comment'
+ [% INCLUDE bug/comment.html.tmpl
minrows = 10
maxrows = 25
cols = constants.COMMENT_COLS