/* ***** 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) ] });