aboutsummaryrefslogtreecommitdiffstats
path: root/bugzillaComments.js
diff options
context:
space:
mode:
Diffstat (limited to 'bugzillaComments.js')
-rw-r--r--bugzillaComments.js344
1 files changed, 344 insertions, 0 deletions
diff --git a/bugzillaComments.js b/bugzillaComments.js
new file mode 100644
index 0000000..83b382d
--- /dev/null
+++ b/bugzillaComments.js
@@ -0,0 +1,344 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Bugzilla Comments Jetpack code.
+ *
+ * The Initial Developer of the Original Code is
+ * Philipp Kewisch <mozilla@kewis.ch>
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Matěj Cepl <cepl@redhat.com>
+ * Mark Banner <bugzilla@standard8.plus.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+var manifest = {
+ settings: [
+ {
+ name: "jsonURL",
+ type: "text",
+ label: "URL for Comments Pack"
+ },
+ {
+ name: "enabledPacks",
+ type: "text",
+ label: "Enabled Comment Packages"
+ }
+ ]
+};
+jetpack.future.import("jetpack.storage.settings");
+jetpack.future.import("jetpack.pageMods");
+
+// Container for loaded package json data.
+var gJSONData = null;
+
+////////////////////////////////////////////////////////////////
+// Helper functions
+////////////////////////////////////////////////////////////////
+var hlpr = {
+ valToArray: function valToArray(val) {
+ let arr = [];
+ if (typeof val == "string") {
+ arr = [val];
+ } else if ($.isArray(val)) {
+ arr = val;
+ }
+ return arr;
+ },
+
+ addCSVValue: function addCSVValue(str, value) {
+ let parts = (str.trim().length > 0 ? str.split(",") : []);
+ if (parts.indexOf(value) < 0) {
+ parts.concat(hlpr.valToArray(value));
+ }
+ return parts.join(",");
+ },
+
+ removeCSVValue: function removeCSVValue(str, value) {
+ let parts = (str.trim().length > 0 ? str.split(",") : []);
+ for each (let val in hlpr.valToArray(value)) {
+ let pos = parts.indexOf(val);
+ if (pos > -1) {
+ parts.splice(pos, 1);
+ }
+ }
+ return parts.join(",");
+ },
+
+ selectOption: function selectOption(select, value) {
+ let doc = select[0].ownerDocument;
+ select.val(value);
+
+ let e = doc.createEvent("HTMLEvents");
+ e.initEvent("change", true, true);
+ select[0].dispatchEvent(e);
+ },
+
+ clickElement: function clickElement(element) {
+ let doc = element[0].ownerDocument;
+ let e = doc.createEvent("MouseEvents");
+ e.initMouseEvent("click", true, true, doc.defaultView,
+ 0, 0, 0, 0, 0, false, false, false, false, 0, null);
+ element[0].dispatchEvent(e);
+ }
+};
+
+////////////////////////////////////////////////////////////////
+// Basic Bugzilla modifications
+////////////////////////////////////////////////////////////////
+
+function BaseBugzilla(doc) {
+ this.doc = doc;
+ this.init();
+}
+
+BaseBugzilla.prototype = {
+ doc: null,
+
+ get installedPackages() {
+ // TODO does this really need to by dynamic?
+ let installedPackages = {};
+ if (gJSONData && ("commentPackages" in gJSONData)) {
+ let enabledPackages = jetpack.storage.settings.enabledPacks.split(/[, ]/);
+ for each (let pkg in enabledPackages) {
+ if (pkg in gJSONData.commentPackages) {
+ installedPackages[pkg] = gJSONData.commentPackages[pkg];
+ }
+ }
+ }
+ return installedPackages;
+ },
+
+ init: function base_init() {
+ this.initCommentsDropdown();
+ },
+
+ initCommentsDropdown: function base_initCommentsDropdown() {
+ let ca = $("<div id='make_bugzilla_comment_action'>" +
+ " <label for='comment_action'>Add Comment: </label>" +
+ " <select id='comment_action'>" +
+ " <option value=''>-- Select Comment from List --</option>" +
+ "</div>", this.doc)
+ $("#comments", this.doc).append(ca);
+
+ let select = $("#comment_action", this.doc);
+
+ let packages = this.installedPackages;
+
+ for (let pkg in packages) {
+ for (let commentId in packages[pkg]) {
+ let comment = packages[pkg][commentId];
+ let value = pkg + "//" + commentId;
+ select.append($("<option/>", this.doc).attr({ value: value })
+ .text(comment.name));
+ }
+ }
+ let self = this;
+ select.change(function() { self.onCommentsDropdownChange() });
+ },
+
+ onCommentsDropdownChange: function onCommentsDropdownChange() {
+ let value = $("select#comment_action", this.doc).attr("value");
+ if (!value) {
+ return;
+ }
+ let [pkg, id] = value.split("//");
+ let commentObj = this.installedPackages[pkg][id];
+
+ let commentField = $("#comment", this.doc);
+ let keywordsInput = $("#keywords", this.doc);
+ let whiteboardsInput = $("#status_whiteboard", this.doc);
+ let dependson = $("#dependson", this.doc);
+ let blocks = $("#blocked", this.doc);
+
+
+ // TODO make these getters/setters on the bz object instead
+ console.log("0" + $("#bug_status", this.doc));
+ if ("status" in commentObj) hlpr.selectOption($("#bug_status", this.doc), commentObj.status);
+ console.log("1");
+ if ("resolution" in commentObj) hlpr.selectOption($("#resolution", this.doc), commentObj.resolution);
+ console.log("2");
+
+ if ("addKeyword" in commentObj) keywordsInput.val(this.addKeyword(keywordsInput.val(), commentObj.addKeyword));
+ if ("removeKeyword" in commentObj) keywordsInput.val(this.removeKeyword(keywordsInput.val(), commentObj.removeKeyword));
+ if ("addWhiteboard" in commentObj) whiteboardsInput.val(this.addWhiteboard(whiteboardsInput.val(), commentObj.addWhiteboard));
+ if ("removeWhiteboard" in commentObj) whiteboardsInput.val(this.removeWhiteboard(whiteboardsInput.val(), commentObj.removeWhiteboard));
+ if ("product" in commentObj) hlpr.selectOption($("#product", this.doc), commentObj.product);
+ if ("component" in commentObj) hlpr.selectOption($("#component", this.doc), commentObj.component);
+ if ("version" in commentObj) hlpr.selectOption($("#version", this.doc), commentObj.version);
+ if ("platform" in commentObj) hlpr.selectOption($("#rep_platform", this.doc), commentObj.platform);
+ if ("os" in commentObj) hlpr.selectOption($("#op_sys", this.doc), commentObj.os);
+
+ if ("priority" in commentObj) hlpr.selectOption($("#priority", this.doc), commentObj.priority);
+ if ("severity" in commentObj) hlpr.selectOption($("#bug_severity", this.doc), commentObj.severity);
+ if ("target" in commentObj) hlpr.selectOption($("#target_milestone", this.doc), commentObj.target);
+
+ if ("assignee" in commentObj) {
+ hlpr.clickElement($("#bz_assignee_edit_action", this.doc));
+ $("#assigned_to", this.doc).val(commentObj.assignee);
+ }
+
+ if ("qacontact" in commentObj) {
+ hlpr.clickElement($("#bz_qa_contact_edit_action", this.doc));
+ $("#qa_contact", this.doc).val(commentObj.qacontact);
+ }
+
+ if ("url" in commentObj) {
+ hlpr.clickElement($("#bz_url_edit_action", this.doc));
+ $("#bug_file_loc", this.doc).val(commentObj.url);
+ }
+
+ // TODO dependson/blocked doesn't work. Find out why.
+ if ("addDependsOn" in commentObj) {
+ hlpr.clickElement($("#dependson_edit_action", this.doc));
+ dependson.val(hlpr.addCSVValue(dependson.val(), commentObj.addDependsOn));
+ }
+ if ("removeDependsOn" in commentObj) {
+ hlpr.clickElement($("#dependson_edit_action", this.doc));
+ dependson.val(hlpr.addCSVValue(dependson.val(), commentObj.removeDependsOn));
+ }
+
+ if ("addBlocks" in commentObj) {
+ hlpr.clickElement($("#blocked_edit_action", this.doc));
+ blocks.val(hlpr.addCSVValue(blocks.val(), commentObj.addBlocks));
+ }
+ if ("removeBlocks" in commentObj) {
+ hlpr.clickElement($("#blocked_edit_action", this.doc));
+ blocks.val(hlpr.removeCSVValue(blocks.val(), commentObj.removeBlocks));
+ }
+
+ if ("comment" in commentObj) commentField.val(commentField.val() + commentObj.comment);
+
+
+ // TODO cclist, flags, see also
+
+ if (("commit" in commentObj) && commentObj.commit) {
+ // Directly commit the form
+ hlpr.clickElement($("#commit"));
+ }
+ },
+
+ addKeyword: function addKeyword(str, keyword) {
+ return hlpr.addCSVValue(str, keyword);
+ },
+
+ removeKeyword: function removeKeyword(str, keyword) {
+ return hlpr.removeCSVValue(str, keyword);
+ },
+
+ addWhiteboard: function addWhiteboard(str, wbFlag) {
+ return hlpr.addCSVValue(str, wbFlag);
+ },
+
+ removeWhiteboard: function removeWhiteboard(str, wbFlag) {
+ return hlpr.removeCSVValue(str, wbFlag);
+ }
+};
+
+////////////////////////////////////////////////////////////////
+// Mozilla Specific Bugzilla modifications
+////////////////////////////////////////////////////////////////
+
+function MozillaBugzilla(doc) {
+ BaseBugzilla.apply(this, arguments);
+}
+
+MozillaBugzilla.prototype = {
+ __proto__: BaseBugzilla.prototype,
+
+ addWhiteboard: function(str, wbFlagVal) {
+ // At least calendar uses [foo] for whiteboard flags, do this differently for moz
+ // TODO make this based on current component, if needed.
+ for each (let wbFlag in hlpr.valToArray(wbFlagVal)) {
+ let fullWbFlag = "[" + wbFlag + "]";
+ if (str.indexOf(fullWbFlag) < 0) {
+ str += fullWbFlag;
+ }
+ }
+ return str;
+ },
+
+ removeWhiteboard: function removeWhiteboard(str, wbFlagVal) {
+ for each (let wbFlag in hlpr.valToArray(wbFlagVal)) {
+ let fullWbFlag = "[" + wbFlag + "]";
+ str = str.replace(fullWbFlag, "");
+ }
+ return str;
+ }
+};
+
+////////////////////////////////////////////////////////////////
+// Redhat Specific Bugzilla modifications
+////////////////////////////////////////////////////////////////
+function RedhatBugzilla(doc) {
+ BaseBugzilla.apply(this, arguments);
+}
+
+RedhatBugzilla.prototype = {
+ __proto__: BaseBugzilla
+
+ // TODO integrate mcepl's code
+};
+
+////////////////////////////////////////////////////////////////
+// Initialize the JSON Data on each jetpack reload
+////////////////////////////////////////////////////////////////
+(function initJSONData() {
+ // Load json file into gJSONData
+ if (jetpack.storage.settings.jsonURL) {
+ let req = new XMLHttpRequest();
+ req.open("GET", jetpack.storage.settings.jsonURL, false);
+ req.overrideMimeType("application/json");
+ req.send(null);
+ if (req.status == 200 || req.status == 0) {
+ gJSONData = JSON.parse(req.responseText);
+ }
+ }
+})();
+
+////////////////////////////////////////////////////////////////
+// Initialize page modifications
+////////////////////////////////////////////////////////////////
+const bzMap = {
+ "https://bugzilla.mozilla.org/show_bug.cgi": MozillaBugzilla,
+ "https://bugzilla.redhat.com/show_bug.cgi": RedhatBugzilla,
+};
+
+function figureOutBugzilla(doc) {
+ // We need the url without the query params, strip them.
+ let href = doc.location.href;
+ href = href.substr(0, href.length - doc.location.search.length);
+
+ // Now check if we have a custom implementation
+ let impl = (href in bzMap ? bzMap[href] : BaseBugzilla);
+
+ // Instanciate, this starts modifying the page.
+ new impl(doc);
+}
+
+jetpack.pageMods.add(figureOutBugzilla,
+ { matches: [ uri for (uri in bzMap) ] });