diff options
Diffstat (limited to 'bugzillaComments.js')
-rw-r--r-- | bugzillaComments.js | 344 |
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) ] }); |