diff options
author | Matěj Cepl <mcepl@redhat.com> | 2010-05-17 02:22:23 +0200 |
---|---|---|
committer | Matěj Cepl <mcepl@redhat.com> | 2010-05-17 02:22:23 +0200 |
commit | f7f1c969292fefc432210d9046753ede4ffc67c9 (patch) | |
tree | a7a6415eac7f4bd31182e8a6c249eb0cfe4b62ac /bugzillaBugTriage.js | |
parent | 6ec4b074ebdd18e2cf9959fe18f338a6e5fddea5 (diff) | |
download | bugzilla-triage-f7f1c969292fefc432210d9046753ede4ffc67c9.tar.gz |
One more step to completness, ready for debugging
Diffstat (limited to 'bugzillaBugTriage.js')
-rw-r--r-- | bugzillaBugTriage.js | 3393 |
1 files changed, 1676 insertions, 1717 deletions
diff --git a/bugzillaBugTriage.js b/bugzillaBugTriage.js index 1c5c100..1dffa51 100644 --- a/bugzillaBugTriage.js +++ b/bugzillaBugTriage.js @@ -17,29 +17,21 @@ var myStorage = jetpack.storage.simple; // ============================================================== // TODO https://wiki.mozilla.org/Labs/Jetpack/JEP/24 var manifest = { - settings : [ - { - name : "BZpassword", - type : "password", - label : "Bugzilla password" - }, - { - name : "JSONURL", - type : "text", - label : "Configuration file URL", - "default" : "http://mcepl.fedorapeople.org/scripts/BugZappers_data.json" - } ] + settings : [ + { + name : "BZpassword", + type : "password", + label : "Bugzilla password" + }, + { + name : "JSONURL", + type : "text", + label : "Configuration file URL", + "default" : "http://mcepl.fedorapeople.org/scripts/BugZappers_data.json" + } ] }; jetpack.future.import("storage.settings"); -var jsonDataURL = jetpack.storage.settings.JSONURL; -var PCIIDsURL = "http://mcepl.fedorapeople.org/scripts/drm_pciids.json"; -var abrtQueryURL = "https://bugzilla.redhat.com/buglist.cgi?" - + "cmdtype=dorem&remaction=run&namedcmd=all%20NEW%20abrt%20crashes&sharer_id=74116"; - -var reqCounter = 0; -var msgStrs = {}; - var CommentRe = new RegExp("^\\s*#"); var BlankLineRe = new RegExp("^\\s*$"); // nová řádka @@ -50,23 +42,11 @@ var AbrtRE = new RegExp("^\\s*\\[abrt\\]"); var signalHandlerRE = new RegExp("^\\s*#[0-9]*\\s*<signal handler called>"); var frameNoRE = new RegExp("^\\s*#([0-9]*)\\s"); -// Initialize data from remote URL -var XMLHttpRequestDone = false; -var hashBugzillaName = []; -var hashBugzillaWholeURL = []; -var defAssigneeList = []; -var suspiciousComponents = []; - -var signatureFedoraString = ""; // TODO we should have an array SpecialFlags instead of multiple Boolean // variables -var parseAbrtBacktraces = false; -var queryButtonAvailable = false; -var upstreamButtonAvailable = false; var logSubmits = false; var chipIDsGroupings = []; var AddrArray = []; -var PCI_ID_Array = []; var topRow = {}; var bottomRow = {}; @@ -85,161 +65,161 @@ var bottomRow = {}; */ function XMLRPCMessage(methodname) { - this.method = methodname || "system.listMethods"; - this.params = []; - return this; + this.method = methodname || "system.listMethods"; + this.params = []; + return this; } XMLRPCMessage.prototype.setMethod = function(methodName) { - if (!methodName) - return; - this.method = methodName; + if (!methodName) + return; + this.method = methodName; }; XMLRPCMessage.prototype.addParameter = function(data) { - if (arguments.length == 0) - return; - this.params[this.params.length] = data; + if (arguments.length == 0) + return; + this.params[this.params.length] = data; }; XMLRPCMessage.prototype.xml = function() { - var method = this.method; + let method = this.method; - // assemble the XML message header - var xml = ""; + // assemble the XML message header + let xml = ""; - xml += "<?xml version=\"1.0\"?>\n"; - xml += "<methodCall>\n"; - xml += "<methodName>" + method + "</methodName>\n"; - xml += "<params>\n"; + xml += "<?xml version=\"1.0\"?>\n"; + xml += "<methodCall>\n"; + xml += "<methodName>" + method + "</methodName>\n"; + xml += "<params>\n"; - // do individual parameters - for ( var i = 0; i < this.params.length; i++) { - var data = this.params[i]; - xml += "<param>\n"; - xml += "<value>" - + this.getParamXML(this.dataTypeOf(data), - data) + "</value>\n"; - xml += "</param>\n"; - } + // do individual parameters + for ( let i = 0; i < this.params.length; i++) { + let data = this.params[i]; + xml += "<param>\n"; + xml += "<value>" + + this.getParamXML(this.dataTypeOf(data), + data) + "</value>\n"; + xml += "</param>\n"; + } - xml += "</params>\n"; - xml += "</methodCall>"; + xml += "</params>\n"; + xml += "</methodCall>"; - return xml; // for now + return xml; // for now }; XMLRPCMessage.prototype.dataTypeOf = function(o) { - // identifies the data type - var type = typeof (o); - type = type.toLowerCase(); - switch (type) { - case "number": - if (Math.round(o) == o) - type = "i4"; - else - type = "double"; - break; - case "object": - var con = o.constructor; - if (con == Date) - type = "date"; - else if (con == Array) - type = "array"; - else - type = "struct"; - break; - } - return type; + // identifies the data type + let type = typeof (o); + type = type.toLowerCase(); + switch (type) { + case "number": + if (Math.round(o) == o) + type = "i4"; + else + type = "double"; + break; + case "object": + let con = o.constructor; + if (con == Date) + type = "date"; + else if (con == Array) + type = "array"; + else + type = "struct"; + break; + } + return type; }; XMLRPCMessage.prototype.doValueXML = function(type, data) { - var xml = "<" + type + ">" + data + "</" + type + ">"; - return xml; + let xml = "<" + type + ">" + data + "</" + type + ">"; + return xml; }; XMLRPCMessage.prototype.doBooleanXML = function(data) { - var value = (data == true) ? 1 : 0; - var xml = "<boolean>" + value + "</boolean>"; - return xml; + let value = (data == true) ? 1 : 0; + let xml = "<boolean>" + value + "</boolean>"; + return xml; }; XMLRPCMessage.prototype.doDateXML = function(data) { - var leadingZero = function (n) { - // pads a single number with a leading zero. Heh. - if (n.length == 1) - n = "0" + n; - return n; - }; - var dateToISO8601 = function(date) { - // wow I hate working with the Date object - var year = new String(date.getYear()); - var month = this.leadingZero(new String(date.getMonth())); - var day = this.leadingZero(new String(date.getDate())); - var time = this.leadingZero(new String(date.getHours())) + ":" - + this.leadingZero(new String(date.getMinutes())) + ":" - + this.leadingZero(new String(date.getSeconds())); - - var converted = year + month + day + "T" + time; - return converted; - }; - - var xml = "<dateTime.iso8601>"; - xml += dateToISO8601(data); - xml += "</dateTime.iso8601>"; - return xml; + let leadingZero = function (n) { + // pads a single number with a leading zero. Heh. + if (n.length == 1) + n = "0" + n; + return n; + }; + let dateToISO8601 = function(date) { + // wow I hate working with the Date object + let year = new String(date.getYear()); + let month = this.leadingZero(new String(date.getMonth())); + let day = this.leadingZero(new String(date.getDate())); + let time = this.leadingZero(new String(date.getHours())) + ":" + + this.leadingZero(new String(date.getMinutes())) + ":" + + this.leadingZero(new String(date.getSeconds())); + + let converted = year + month + day + "T" + time; + return converted; + }; + + let xml = "<dateTime.iso8601>"; + xml += dateToISO8601(data); + xml += "</dateTime.iso8601>"; + return xml; }; XMLRPCMessage.prototype.doArrayXML = function(data) { - var xml = "<array><data>\n"; - for ( var i = 0; i < data.length; i++) { - xml += "<value>" - + this.getParamXML(this.dataTypeOf(data[i]), - data[i]) + "</value>\n"; - } - xml += "</data></array>\n"; - return xml; + let xml = "<array><data>\n"; + for ( let i = 0; i < data.length; i++) { + xml += "<value>" + + this.getParamXML(this.dataTypeOf(data[i]), + data[i]) + "</value>\n"; + } + xml += "</data></array>\n"; + return xml; }; XMLRPCMessage.prototype.doStructXML = function(data) { - var xml = "<struct>\n"; - for ( var i in data) { - xml += "<member>\n"; - xml += "<name>" + i + "</name>\n"; - xml += "<value>" - + this.getParamXML(this.dataTypeOf(data[i]), - data[i]) + "</value>\n"; - xml += "</member>\n"; - } - xml += "</struct>\n"; - return xml; + let xml = "<struct>\n"; + for ( let i in data) { + xml += "<member>\n"; + xml += "<name>" + i + "</name>\n"; + xml += "<value>" + + this.getParamXML(this.dataTypeOf(data[i]), + data[i]) + "</value>\n"; + xml += "</member>\n"; + } + xml += "</struct>\n"; + return xml; }; XMLRPCMessage.prototype.getParamXML = function(type, data) { - var xml; - switch (type) { - case "date": - xml = this.doDateXML(data); - break; - case "array": - xml = this.doArrayXML(data); - break; - case "struct": - xml = this.doStructXML(data); - break; - case "boolean": - xml = this.doBooleanXML(data); - break; - default: - xml = this.doValueXML(type, data); - break; - } - return xml; + let xml; + switch (type) { + case "date": + xml = this.doDateXML(data); + break; + case "array": + xml = this.doArrayXML(data); + break; + case "struct": + xml = this.doStructXML(data); + break; + case "boolean": + xml = this.doBooleanXML(data); + break; + default: + xml = this.doValueXML(type, data); + break; + } + return xml; }; // ============================================================== -var hlpr = function () { +let hlpr = function () { }; /** @@ -278,7 +258,7 @@ hlpr.heir = function(p) { * @return position of the string in the list, or -1 if none found. */ hlpr.isInList = function(mbr, list) { - return (list.indexOf(mbr) !== -1); + return (list.indexOf(mbr) !== -1); }; /** @@ -304,13 +284,13 @@ hlpr.valToArray = function valToArray(val) { */ hlpr.addCSVValue = function addCSVValue(str, value) { str = str.trim(); - let parts = (str ? str.split(",") : []); - // FIXME this doesn't work when value is actually array - // Should it work? (neither original function worked) - if (this.isInList(value,parts)) { - parts.concat(hlpr.valToArray(value)); - } - return parts.join(","); + let parts = (str ? str.split(",") : []); + // FIXME this doesn't work when value is actually array + // Should it work? (neither original function worked) + if (this.isInList(value,parts)) { + parts.concat(hlpr.valToArray(value)); + } + return parts.join(","); }; /** @@ -332,62 +312,35 @@ hlpr.removeCSVValue = function removeCSVValue(str, value) { //Get JSON configuration data hlpr.loadText = function(URL, cb_function, what) { - if (what === undefined) { // missing optional argument - what = this; - } - - var req = new XMLHttpRequest(); - req.open("GET", URL, true); - req.onreadystatechange = function(aEvt) { - if (req.readyState == 4) { - if (req.status == 200) { - cb_function.call(what, req.responseText); - } else { - throw "Getting " + URL + "failed!"; - } - } - }; - req.send(""); + if (what === undefined) { // missing optional argument + what = this; + } + + let req = new XMLHttpRequest(); + req.open("GET", URL, true); + req.onreadystatechange = function(aEvt) { + if (req.readyState == 4) { + if (req.status == 200) { + cb_function.call(what, req.responseText); + } else { + throw "Getting " + URL + "failed!"; + } + } + }; + req.send(""); }; // Initialization hlpr.loadJSON = function(URL, cb_function, what) { - if (what === undefined) { // missing optional argument - what = this; - } - - hlpr.loadText(URL, function(text) { - var data = JSON.parse(text); - cb_function.call(what, data); - }, what); -}; - -hlpr.loadJSON(jsonDataURL, function(response) { - console.log("jsonDataURL = " + jsonDataURL); - msgStrs = response.strings; - signatureFedoraString = response.signature; - suspiciousComponents = response.suspiciousComponents; - hashBugzillaName = response.bugzillalabelNames; - hashBugzillaWholeURL = response.bugzillaIDURLs; - // [{'regexp to match component':'email address of an universal - // maintainer'}, ...] - AddrArray = response.CCmaintainer; - defAssigneeList = response.defaultAssignee; - queryButtonAvailable = response.queryButton; - upstreamButtonAvailable = response.upstreamButton; - parseAbrtBacktraces = response.parseAbrtBacktraces; - logSubmits = response.submitsLogging; - newUpstreamBugsURLArray = response.newUpstreamBug; - queryUpstreamBugsURLArray = response.queryUpstreamBug; - chipIDsGroupings = response.chipIDsGroupings; - topRow = response.topRow; - bottomRow = response.bottomRow; - }); + if (what === undefined) { // missing optional argument + what = this; + } -// Get card translation table -hlpr.loadJSON(PCIIDsURL, function(response) { - PCI_ID_Array = response; -}); + hlpr.loadText(URL, function(text) { + let data = JSON.parse(text); + cb_function.call(what, data); + }, what); +}; // ============================================================================ // Color management methods @@ -396,41 +349,41 @@ hlpr.loadJSON(PCIIDsURL, function(response) { // /rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript function Color(r, g, b) { - this.Luminosity = 0.85; - this.Desaturated = 0.4; - - if (r instanceof Array) { - this.r = r[0]; - this.g = r[1]; - this.b = r[2]; - } else { - this.r = r; - this.g = g; - this.b = b; - } + this.Luminosity = 0.85; + this.Desaturated = 0.4; + + if (r instanceof Array) { + this.r = r[0]; + this.g = r[1]; + this.b = r[2]; + } else { + this.r = r; + this.g = g; + this.b = b; + } } Color.prototype.update = function(r, g, b) { - this.r = r; - this.g = g; - this.b = b; + this.r = r; + this.g = g; + this.b = b; }; Color.prototype.hs = function(nStr) { - if (Number(nStr) === 0) { - return "00"; - } else if (nStr.length < 2) { - return "0" + nStr; - } else { - return nStr; - } + if (Number(nStr) === 0) { + return "00"; + } else if (nStr.length < 2) { + return "0" + nStr; + } else { + return nStr; + } }; Color.prototype.toString = function() { - var rH = Number(this.r.toFixed()).toString(16); - var gH = Number(this.g.toFixed()).toString(16); - var bH = Number(this.b.toFixed()).toString(16); - return "#" + this.hs(rH) + this.hs(gH) + this.hs(bH); + let rH = Number(this.r.toFixed()).toString(16); + let gH = Number(this.g.toFixed()).toString(16); + let bH = Number(this.b.toFixed()).toString(16); + return "#" + this.hs(rH) + this.hs(gH) + this.hs(bH); }; /** @@ -444,32 +397,32 @@ Color.prototype.toString = function() { * @return Array The HSL representation */ Color.prototype.hsl = function() { - var r = this.r / 255; - var g = this.g / 255; - var b = this.b / 255; - var max = Math.max(r, g, b), min = Math.min(r, g, b); - var h, s, l = (max + min) / 2; - - if (max === min) { - h = s = 0; // achromatic - } else { - var d = max - min; - s = l > 0.5 ? d / (2 - max - min) : d / (max + min); - switch (max) { - case r: - h = (g - b) / d + (g < b ? 6 : 0); - break; - case g: - h = (b - r) / d + 2; - break; - case b: - h = (r - g) / d + 4; - break; - } - h /= 6; - } - - return [ h, s, l ]; + let r = this.r / 255; + let g = this.g / 255; + let b = this.b / 255; + let max = Math.max(r, g, b), min = Math.min(r, g, b); + let h, s, l = (max + min) / 2; + + if (max === min) { + h = s = 0; // achromatic + } else { + let d = max - min; + s = l > 0.5 ? d / (2 - max - min) : d / (max + min); + switch (max) { + case r: + h = (g - b) / d + (g < b ? 6 : 0); + break; + case g: + h = (b - r) / d + 2; + break; + case b: + h = (r - g) / d + 4; + break; + } + h /= 6; + } + + return [ h, s, l ]; }; /** @@ -483,38 +436,38 @@ Color.prototype.hsl = function() { * @return Array The RGB representation */ Color.prototype.hslToRgb = function(h, s, l) { - function hue2rgb(p, q, t) { - if (t < 0) { - t += 1; - } - if (t > 1) { - t -= 1; - } - if (t < 1 / 6) { - return p + (q - p) * 6 * t; - } - if (t < 1 / 2) { - return q; - } - if (t < 2 / 3) { - return p + (q - p) * (2 / 3 - t) * 6; - } - return p; - } - - var r, g, b; - - if (s === 0) { - r = g = b = l; // achromatic - } else { - var q = l < 0.5 ? l * (1 + s) : l + s - l * s; - var p = 2 * l - q; - r = hue2rgb(p, q, h + 1 / 3); - g = hue2rgb(p, q, h); - b = hue2rgb(p, q, h - 1 / 3); - } - - return [ r * 255, g * 255, b * 255 ]; + function hue2rgb(p, q, t) { + if (t < 0) { + t += 1; + } + if (t > 1) { + t -= 1; + } + if (t < 1 / 6) { + return p + (q - p) * 6 * t; + } + if (t < 1 / 2) { + return q; + } + if (t < 2 / 3) { + return p + (q - p) * (2 / 3 - t) * 6; + } + return p; + } + + let r, g, b; + + if (s === 0) { + r = g = b = l; // achromatic + } else { + let q = l < 0.5 ? l * (1 + s) : l + s - l * s; + let p = 2 * l - q; + r = hue2rgb(p, q, h + 1 / 3); + g = hue2rgb(p, q, h); + b = hue2rgb(p, q, h - 1 / 3); + } + + return [ r * 255, g * 255, b * 255 ]; }; /** @@ -528,33 +481,33 @@ Color.prototype.hslToRgb = function(h, s, l) { * @return Array The HSV representation */ Color.prototype.hsv = function() { - var r = this.r / 255; - var g = this.g / 255; - var b = this.b / 255; - var max = Math.max(r, g, b), min = Math.min(r, g, b); - var h, s, v = max; - - var d = max - min; - s = max === 0 ? 0 : d / max; - - if (max === min) { - h = 0; // achromatic - } else { - switch (max) { - case r: - h = (g - b) / d + (g < b ? 6 : 0); - break; - case g: - h = (b - r) / d + 2; - break; - case b: - h = (r - g) / d + 4; - break; - } - h /= 6; - } - - return [ h, s, v ]; + let r = this.r / 255; + let g = this.g / 255; + let b = this.b / 255; + let max = Math.max(r, g, b), min = Math.min(r, g, b); + let h, s, v = max; + + let d = max - min; + s = max === 0 ? 0 : d / max; + + if (max === min) { + h = 0; // achromatic + } else { + switch (max) { + case r: + h = (g - b) / d + (g < b ? 6 : 0); + break; + case g: + h = (b - r) / d + 2; + break; + case b: + h = (r - g) / d + 4; + break; + } + h /= 6; + } + + return [ h, s, v ]; }; /** @@ -568,60 +521,60 @@ Color.prototype.hsv = function() { * @return Array The RGB representation */ Color.prototype.hsvToRgb = function(h, s, v) { - var r, g, b; - - var i = Math.floor(h * 6); - var f = h * 6 - i; - var p = v * (1 - s); - var q = v * (1 - f * s); - var t = v * (1 - (1 - f) * s); - - switch (i % 6) { - case 0: - r = v; - g = t; - b = p; - break; - case 1: - r = q; - g = v; - b = p; - break; - case 2: - r = p; - g = v; - b = t; - break; - case 3: - r = p; - g = q; - b = v; - break; - case 4: - r = t; - g = p; - b = v; - break; - case 5: - r = v; - g = p; - b = q; - break; - } - - return [ r * 255, g * 255, b * 255 ]; + let r, g, b; + + let i = Math.floor(h * 6); + let f = h * 6 - i; + let p = v * (1 - s); + let q = v * (1 - f * s); + let t = v * (1 - (1 - f) * s); + + switch (i % 6) { + case 0: + r = v; + g = t; + b = p; + break; + case 1: + r = q; + g = v; + b = p; + break; + case 2: + r = p; + g = v; + b = t; + break; + case 3: + r = p; + g = q; + b = v; + break; + case 4: + r = t; + g = p; + b = v; + break; + case 5: + r = v; + g = p; + b = q; + break; + } + + return [ r * 255, g * 255, b * 255 ]; }; /** * Provide */ Color.prototype.lightColor = function() { - var hslArray = this.hsl(); - var h = Number(hslArray[0]); - var s = Number(hslArray[1]) * this.Desaturated; - var l = this.Luminosity; - var desA = this.hslToRgb(h, s, l); - return new Color(desA[0], desA[1], desA[2]); + let hslArray = this.hsl(); + let h = Number(hslArray[0]); + let s = Number(hslArray[1]) * this.Desaturated; + let l = this.Luminosity; + let desA = this.hslToRgb(h, s, l); + return new Color(desA[0], desA[1], desA[2]); }; // ==================================================================================== @@ -629,16 +582,23 @@ Color.prototype.lightColor = function() { function BZPage(doc) { // constants - this.SalmonPink = new Color(255, 224, 176); // RGB 255, 224, 176; HSL 36, 2, + this.SalmonPink = new Color(255, 224, 176); // RGB 255, 224, 176; HSL 36, 2, // 85 - this.ReporterColor = new Color(255, 255, 166); // RGB 255, 255, 166; HSL 60, 2, + this.ReporterColor = new Color(255, 255, 166); // RGB 255, 255, 166; HSL 60, 2, // 83 - this.EmptyLogsColor = new Color(0, 255, 0); - this.FullLogsColor = new Color(0, 40, 103); + this.EmptyLogsColor = new Color(0, 255, 0); + this.FullLogsColor = new Color(0, 40, 103); // initialize dynamic properties - this.doc = doc; -// this.initCommentsDropdown(); + this.doc = doc; + this.packages = this.getInstalledPackages(); + if ("commentStrings" in config.gJSONData) { + this.commentStrings = config.gJSONData.commentStrings; + } + if ("constantData" in config.gJSONData) { + this.constantData = config.gJSONData.constantData; + } + this.generateButtons(); } /** @@ -646,11 +606,11 @@ function BZPage(doc) { */ BZPage.prototype.getInstalledPackages = function() { let installedPackages = {}; - if (gJSONData && ("commentPackages" in gJSONData)) { + if (config.gJSONData && ("commentPackages" in config.gJSONData)) { let enabledPackages = jetpack.storage.settings.enabledPacks.split(/[, ]/); for each (let pkg in enabledPackages) { - if (pkg in gJSONData.commentPackages) { - installedPackages[pkg] = gJSONData.commentPackages[pkg]; + if (pkg in config.gJSONData.commentPackages) { + installedPackages[pkg] = config.gJSONData.commentPackages[pkg]; } } } @@ -658,155 +618,332 @@ BZPage.prototype.getInstalledPackages = function() { }; /** + * Actual execution function * + * @param cmdLabel String with the name of the command to be executed + * @param cmdParams Object with the appropriate parameters for the command */ -BZPage.prototype.initCommentsDropdown = function() { - let that = this; - this.doc.getElementById("comments").innerHTML += - "<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>"; - let select = this.doc.getElementById("comment_action"); - let packages = this.getInstalledPackages(); - - packages.forEach(function (pkg, idx, arr) { - pkg.forEach(function (comment, iidx, aarr) { - // FIXME idx and iidx shouldn’t be numbers but names of properties - let value = idx + "//" + iidx; - let opt = that.doc.createElement("option"); - opt.setAttribute(value,value); - opt.textContent = comment.name; - select.appendChild(opt); - }) - }); - - select.addEventListener("change", that.onCommentsDropdownChange, false); +BZPage.prototype.centralCommandDispatch = function (cmdLabel, cmdParams) { + switch (cmdLabel) { + // FIXME we don't have guaranteed order of execution, but + // for example resolution can be executed only after status; + // we may need to eliminate these two commands and replace them + // with "closed", "assigned", etc. with parameter resolution? + // or only "closed" and other commands which require resolution? + case "resolution": + case "product": + case "component": + case "version": + case "priority": + this.selectOption(cmdLabel, cmdParams); + break; + case "status": + this.selectOption("bug_status", cmdParams); + break; + case "platform": + this.selectOption("rep_platform", cmdParams); + break; + case "os": + this.selectOption("op_sys", cmdParams); + break; + case "severity": + this.selectOption("bug_severity", cmdParams); + break; + case "target": + this.selectOption("target_milestone", cmdParams); + break; + case "addKeyword": + this.addStuffToTextBox("keywords",cmdParams); + break; + case "removeKeyword": + this.removeStuffFromTextBox("keywords", cmdParams); + break; + case "addWhiteboard": + this.addStuffToTextBox("status_whiteboard",cmdParams); + break; + case "removeWhiteboard": + this.removeStuffFromTextBox("status_whiteboard",cmdParams); + break; + case "assignee": + this.changeAssignee(cmdParams); + break; + case "qacontact": + this.clickMouse("bz_qa_contact_edit_action"); + this.doc.getElementById("qa_contact").value = cmdParams; + break; + case "url": + this.clickMouse("bz_url_edit_action"); + this.doc.getElementById("bug_file_loc").value = cmdParams; + break; + // TODO dependson/blocked doesn't work. Find out why. + case "addDependsOn": + this.clickMouse("dependson_edit_action"); + this.addStuffToTextBox("dependson", cmdParams); + break; + case "removeDependsOn": + this.clickMouse("dependson_edit_action"); + this.removeStuffFromTextBox("dependson", cmdParams); + break; + case "addBlocks": + this.clickMouse("blocked_edit_action"); + this.addStuffToTextBox("blocked", cmdParams); + break; + case "removeBlocks": + this.clickMouse("blocked_edit_action"); + this.removeStuffFromTextBox("blocked", cmdParams) + break; + case "comment": + this.addStuffToTextBox("comment", cmdParams); + break; + case "commentIdx": + let commentText = this.commentStrings[cmdParams]; + this.addStuffToTextBox("comment", commentText); + break; + case "setNeedinfo": + // cmdParams are actually ignored for now; we may in future + // distinguish different actors to be target of needinfo + this.setNeedinfoReporter(); + break; + case "addCC": + this.addToCCList(cmdParams); + break; + // TODO flags, see also + + case "commit": + if (cmdParams) { + // Directly commit the form + this.doc.forms.namedItem("changeform").submit(); + } + break; + } }; -BZPage.prototype.onCommentsDropdownChange = function() { - // $("select#comment_action", this.doc).attr("value"); - let valueElement = this.doc.getElementById("comment_action"); - if (valueElement) { - let value = valueElement.getAttribute("value"); - } else { - return; - } - let [pkg, id] = value.split("//"); +/** + * Take the ID of the package/id combination, and execute it + * + * @param String combined package + "//" + id combination + * Fetches the command object from this.installedPackages and then + * goes through all commands contained in it, and calls + * this.centralCommandDispatch to execute them. + */ +BZPage.prototype.executeCommand = function (cmd) { + let [pkg, id] = cmd.split("//"); let commentObj = this.installedPackages[pkg][id]; - let commentField = this.doc.getElementById("comment"); - let keywordsInput = this.doc.getElementById("keywords"); - let whiteboardsInput = this.doc.getElementById("status_whiteboard"); - let dependson = this.doc.getElementById("dependson"); - let blocks = this.doc.getElementById("blocked"); - - - // TODO make these getters/setters on the bz object instead - console.log("0" + this.doc.getElementById("bug_status")); - - // we need to add element.id to the comment object - commentObj.forEach(function (comment,commIdx,commArr) { - this.selectOption(getID,comment.status); - }); - - // selectOption - if ("status" in commentObj) - this.selectOption("bug_status", commentObj.status); - console.log("1"); - if ("resolution" in commentObj) - this.selectOption("resolution", commentObj.resolution); - console.log("2"); - - if ("addKeyword" in commentObj) - keywordsInput.value = this.addKeyword(keywordsInput.value, - commentObj.addKeyword); - if ("removeKeyword" in commentObj) - keywordsInput.value = this.removeKeyword(keywordsInput.value, - commentObj.removeKeyword); - if ("addWhiteboard" in commentObj) - whiteboardsInput.value = this.addWhiteboard(whiteboardsInput.value, - commentObj.addWhiteboard); - if ("removeWhiteboard" in commentObj) - whiteboardsInput.value = this.removeWhiteboard(whiteboardsInput.value, - commentObj.removeWhiteboard); - if ("product" in commentObj) - this.selectOption("product", commentObj.product); - if ("component" in commentObj) - this.selectOption("component", commentObj.component); - if ("version" in commentObj) - this.selectOption("version", commentObj.version); - if ("platform" in commentObj) - this.selectOption("rep_platform", commentObj.platform); - if ("os" in commentObj) - this.selectOption("op_sys", commentObj.os); - - if ("priority" in commentObj) - this.selectOption("priority", commentObj.priority); - if ("severity" in commentObj) - this.selectOption("bug_severity", commentObj.severity); - if ("target" in commentObj) - this.selectOption("target_milestone", commentObj.target); - - if ("assignee" in commentObj) { - this.clickMouse("bz_assignee_edit_action"); - this.doc.getElementById("assigned_to").value = commentObj.assignee; + for (let key in commentObj) { + this.centralCommandDispatch(key,commentObj[key]); } +}; - if ("qacontact" in commentObj) { - this.clickMouse("bz_qa_contact_edit_action"); - this.doc.getElementById("qa_contact").value = commentObj.qacontact; +/** + * Add XGL to the CC list + * + * @param evt Event which made this function active + * @return none + */ +BZPage.prototype.changeAssignee = function(newAssignee) { + let defAssigneeButton = null; + this.addToCCList(this.owner); + if (newAssignee === null) { + this.doc.getElementById("set_default_assignee").removeAttribute( + "checked"); } - if ("url" in commentObj) { - this.clickMouse("bz_url_edit_action"); - this.doc.getElementById("bug_file_loc").value = commentObj.url; + if (newAssignee == "default" && this.defaultAssignee) { + newAssignee = this.defaultAssignee; } - // TODO dependson/blocked doesn't work. Find out why. - if ("addDependsOn" in commentObj) { - this.clickMouse("dependson_edit_action"); - dependson.value = hlpr.addCSVValue(dependson.value, commentObj.addDependsOn); + if (newAssignee) { + this.clickMouse("bz_assignee_edit_action"); + this.doc.getElementById("assigned_to").value = newAssignee; + this.doc.getElementById("set_default_assignee").checked = false; + if (defAssigneeButton = this.doc + .getElementById("setdefaultassigneebutton")) { + defAssigneeButton.style.display = "none"; + } } - if ("removeDependsOn" in commentObj) { - this.clickMouse("dependson_edit_action"); - dependson.value = hlpr.addCSVValue(dependson.value, commentObj.removeDependsOn); +}; + +/** + * Adds new option to the 'comment_action' scroll down box + * + * @param pkg String package name + * @param cmd String with the name of the command + * If the 'comment_action' scroll down box doesn't exist, this + * function will set up new one. + */ +BZPage.prototype.addToCommentsDropdown = function(pkg, cmd) { + let select = this.doc.getElementById("comment_action"); + if (!select) { + let that = this; + this.doc.getElementById("comments").innerHTML += + "<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>"; + select = this.doc.getElementById("comment_action"); + select.addEventListener("change", function () { + let valueElement = that.doc.getElementById("comment_action"); + if (valueElement) { + let value = valueElement.getAttribute("value"); + } else { + return; + } + that.executeCommand(value); + }, false); } + + let opt = that.doc.createElement("option"); + opt.value = pkg + "//" + cmd; + opt.textContent = this.packages[pkg][cmd].name; + select.appendChild(opt); +}; - if ("addBlocks" in commentObj) { - this.clickMouse("blocked_edit_action"); - blocks.value = hlpr.addCSVValue(blocks.value, commentObj.addBlocks); +/** + * Generic function to add new button to the page. Actually copies new button + * from the old one (in order to have the same look-and-feel, etc. + * + * @param originalLocation Object after which the new button will be added + * @param newId String with the id of the new button; has to be unique in whole + * page + * @param newLabel String with the label which will be shown to user + * @param commentString String with comment to be added to the comment box + * @param nState String with the new state bug should switch to (see + * generalPurposeCureForAllDisease function for details) + * @param secPar String with second parameter for generalPurposeForAllDisease + * @param doSubmit Boolean optional whether the button should submit whole + * page (default true) + * @return none + */ +BZPage.prototype.createNewButton = function(location, after, pkg, id) { + let that = this; + let cmdObj = this.packages[pkg][id]; + let newId = id + "_btn"; + let label = cmdObj["name"]; + + // creation of button might be conditional on existence of data in constantData + if ("ifExist" in cmdObj) { + if (!(cmdObj["ifExist"] in this.constantData)) { + return ; + } } - if ("removeBlocks" in commentObj) { - this.clickMouse("blocked_edit_action"); - blocks.value = hlpr.removeCSVValue(blocks.value, commentObj.removeBlocks); + + let newButton = this.doc.createElement("input"); + newButton.setAttribute("id", newId); + newButton.setAttribute("type", "button"); + newButton.value = label; + newButton.addEventListener("click", function(evt) { + that.executeCommand(pkg + "//" + id); + }, false); + + let originalLocation = this.doc.getElementById(location); + + if (after) { + originalLocation.parentNode.insertBefore(newButton, + originalLocation.nextSibling); + originalLocation.parentNode.insertBefore(this.doc + .createTextNode("\u00A0"), newButton); + } else { + originalLocation.parentNode.insertBefore(newButton, originalLocation); + originalLocation.parentNode.insertBefore(this.doc + .createTextNode("\u00A0"), originalLocation); } +}; - if ("comment" in commentObj) { - commentField.value += commentObj.comment; +/** + * + */ +BZPage.prototype.generateButtons = function() { + let topRowPosition = "topRowPositionID"; + let bottomRowPosition = "commit"; + + // create anchor for the top toolbar + let commentBox = this.doc.getElementById("comment"); + let brElement = this.doc.createElement("br"); + brElement.setAttribute("id",topRowPosition); + commentBox.parentNode.normalize(); + commentBox.parentNode.insertBefore(brElement, commentBox); + + for (let pkg in this.packages) { + for (let cmdIdx in this.packages[pkg]) { + let cmdObj = this.packages[pkg][cmdIdx]; + switch (cmdObj.position) { + "topRow": + this.createNewButton(topRowPosition, false, pkg, cmdIdx); + break; + "bottomRow": + this.createNewButton(bottomRowPosition, false, pkg, cmdIdx); + break; + "dropDown": + this.addToCommentsDropdown(pkg,cmdIdx); + break; + default: // [+-]ID + let firstChr = cmdObj.position.charAt(0); + let newId = cmdObj.position.substr(1); + this.createNewButton(newId, firstChr == "+", pkg, cmdIdx); + break; + } + } } +}; - // TODO cclist, flags, see also +/** + * Get the current email of the reporter of the bug. + * + * @return string + */ +BZPage.prototype.getReporter = function() { + return this.doc + .querySelector("#bz_show_bug_column_2 > table .vcard:first-of-type > a").textContent; +}; - if (("commit" in commentObj) && commentObj.commit) { - // Directly commit the form - this.doc.forms.namedItem("changeform").submit(); +/** + * Get the current version of the Fedora release ... even if changed meanwhile + * by bug triager. + * + * @return string (integer for released Fedora, float for RHEL, rawhide) + */ +BZPage.prototype.getVersion = function() { + let verStr = this.getOptionValue("version").toLowerCase(); + let verNo = 0; + if (/rawhide/.test(verStr)) { + verNo = 999; + } else { + verNo = Number(verStr); } + return verNo; }; -BZPage.prototype.createBlankPage = function (ttl, bodyBuildCB) { - var title = ttl || "Yet another untitled page"; - var that = this; +BZPage.prototype.commentsWalker = function(fce) { + let comments = this.doc.getElementById("comments").getElementsByClassName( + "bz_comment"); + Array.forEach(comments, function(item) { + fce(item); + }, this); +}; + +/** + * Set background color of all comments made by reporter in ReporterColor color + * + */ +BZPage.prototype.checkComments = function() { + let that = this; + this.commentsWalker(function(x) { + let email = x.getElementsByClassName("vcard")[0] + .getElementsByTagName("a")[0].textContent; + if (new RegExp(that.reporter).test(email)) { + x.style.backgroundColor = that.ReporterColor.toString(); + } + }); +}; - var logTab = jetpack.tabs.open("about:blank"); - jetpack.tabs.onReady(function() { - var otherDoc = logTab.contentDocument; - otherDoc.title = title; - otherDoc.body.innerHTML = "<h1>" + title + "</h1>"; - bodyBuildCB.call(that, otherDoc.body); - logTab.focus(); - }); +BZPage.prototype.collectComments = function() { + let outStr = ""; + this.commentsWalker(function(x) { + outStr += x.getElementsByTagName("pre")[0].textContent + "\n"; + }); + return outStr.trim(); }; @@ -822,12 +959,12 @@ BZPage.prototype.createBlankPage = function (ttl, bodyBuildCB) { * FIXME bugzilla-comments version has this signature: * selectOption = function selectOption(select, value) { let doc = select[0].ownerDocument; - select.val(value); + select.val(value); */ BZPage.prototype.selectOption = function(id, label) { - var sel = this.doc.getElementById(id); + let sel = this.doc.getElementById(id); sel.value = label; - var intEvent = this.doc.createEvent("HTMLEvents"); + let intEvent = this.doc.createEvent("HTMLEvents"); intEvent.initEvent("change", true, true); sel.dispatchEvent(intEvent); }; @@ -839,10 +976,10 @@ BZPage.prototype.selectOption = function(id, label) { * @return None */ BZPage.prototype.clickMouse = function(targetID) { - var localEvent = this.doc.createEvent("MouseEvents"); - localEvent.initMouseEvent("click", true, true, this.doc.defaultView, 0, 0, - 0, 0, 0, false, false, false, false, 0, null); - this.doc.getElementById(targetID).dispatchEvent(localEvent); + let localEvent = this.doc.createEvent("MouseEvents"); + localEvent.initMouseEvent("click", true, true, this.doc.defaultView, 0, 0, + 0, 0, 0, false, false, false, false, 0, null); + this.doc.getElementById(targetID).dispatchEvent(localEvent); }; /** @@ -852,12 +989,12 @@ BZPage.prototype.clickMouse = function(targetID) { * @return string with the formatted date */ BZPage.prototype.getISODate = function (dateStr) { - function pad(n) { - return n < 10 ? '0' + n : n; - } - var date = new Date(dateStr); - return date.getFullYear() + '-' + pad(date.getMonth() + 1) + '-' - + pad(date.getDate()); + function pad(n) { + return n < 10 ? '0' + n : n; + } + let date = new Date(dateStr); + return date.getFullYear() + '-' + pad(date.getMonth() + 1) + '-' + + pad(date.getDate()); }; /** @@ -869,58 +1006,45 @@ BZPage.prototype.getISODate = function (dateStr) { * @return String chosen element */ BZPage.prototype.filterByRegexp = function(list, chosingMark) { - var chosenPair = []; - if (list.length > 0) { - chosenPair = list.filter(function(pair) { - return new RegExp(pair.regexp, "i").test(chosingMark); - }); - } - if (chosenPair.length > 0) { - return chosenPair[0].addr.trim(); - } else { - return ""; - } + let chosenPair = []; + if (list.length > 0) { + chosenPair = list.filter(function(pair) { + return new RegExp(pair.regexp, "i").test(chosingMark); + }); + } + if (chosenPair.length > 0) { + return chosenPair[0].addr.trim(); + } else { + return ""; + } }; /** - * Add text to the text box (comment box or status whiteboard) + * Add object to the text box (comment box or status whiteboard) * * @param id String with the id of the element - * @param string2BAdded String to be added to the comment box + * @param stuff String/Array to be added to the comment box * * @return none */ -BZPage.prototype.addTextToTextBox = function(id, string2BAdded) { - var textBox = this.doc.getElementById(id); - var separator = ", "; - if (textBox.tagName.toLowerCase() === "textarea") { - separator = "\n\n"; - } else { - // don't add string if it is already there - if (textBox.value.indexOf(string2BAdded) != -1) { - return; - } - } - - // don't remove the current content of the comment box, - // just behave accordingly - if (textBox.value.length > 0) { - textBox.value = textBox.value.trim() + separator; - } - textBox.value = textBox.value + string2BAdded; +BZPage.prototype.addStuffToTextBox = function(id, stuff) { + let textBox = this.doc.getElementById(id); + if (textBox.tagName.toLowerCase() === "textarea") { + stuff = "\n\n" + stuff; + } + textBox.value = hlpr.addCSVValue(textBox.value,stuff); }; /** - * Add new keyword among the keywords. + * Remove a keyword from the element if it is there * - * @param str String with the new keyword - * @return none - * - * Checks for the existing keywords. + * @param id String with the id of the element + * @param stuff String/Array with keyword(s) to be removed */ -BZPage.prototype.addKeyword = function(str) { - this.addTextToTextBox("keywords", str); -}; +BZPage.prototype.removeStuffFromTextBox = function(id, stuff) { + let changedElement = this.getElementById(id); + changedElement.value = hlpr.removeCSVValue(changedElement.value,stuff); +} /** * generalized hasKeyword ... search in the value of the box with given id @@ -930,14 +1054,14 @@ BZPage.prototype.addKeyword = function(str) { * @return Boolean found? */ BZPage.prototype.idContainsWord = function(id, str) { - try { - var kwd = this.doc.getElementById(id).value; - } catch (e) { - // For those who don't have particular element at all or if it is empty - return false; - } - console.log("id = " + id + ", kwd = " + kwd.trim()); - return (kwd.trim().indexOf(str) != -1); + try { + let kwd = this.doc.getElementById(id).value; + } catch (e) { + // For those who don't have particular element at all or if it is empty + return false; + } + console.log("id = " + id + ", kwd = " + kwd.trim()); + return (kwd.trim().indexOf(str) != -1); }; /** @@ -947,80 +1071,47 @@ BZPage.prototype.idContainsWord = function(id, str) { * @return Boolean */ BZPage.prototype.hasKeyword = function(str) { - return (this.idContainsWord('keywords', str)); + return (this.idContainsWord('keywords', str)); }; /** - * Set additional keyword if it isn't there * - * @param str String with the keyword - * @return none */ -BZPage.prototype.setKeyword = function(str) { - this.addTextToTextBox('keywords', str); -}; - BZPage.prototype.getOptionValue = function(id) { - // Some special bugs don't have version for example - try { - return this.doc.getElementById(id).value; - } catch (e) { - console.error("Failed to find element with id = " + id); - return "#NA"; - } + // Some special bugs don't have version for example + try { + return this.doc.getElementById(id).value; + } catch (e) { + console.error("Failed to find element with id = " + id); + return "#NA"; + } }; /** - * Generic function to add new button to the page. Actually copies new button - * from the old one (in order to have the same look-and-feel, etc. + * Set the bug to NEEDINFO state * - * @param originalLocation Object after which the new button will be added - * @param newId String with the id of the new button; has to be unique in whole - * page - * @param newLabel String with the label which will be shown to user - * @param commentString String with comment to be added to the comment box - * @param nState String with the new state bug should switch to (see - * generalPurposeCureForAllDisease function for details) - * @param secPar String with second parameter for generalPurposeForAllDisease - * @param doSubmit Boolean optional whether the button should submit whole - * page (default true) + * Working function. * @return none + * @todo TODO we may extend this to general setNeedinfo function + * with parameter [reporter|assignee|general-email-address] */ -BZPage.prototype.addNewButton = function(originalLocation, newId, newLabel, - commentString, nState, secPar, doSubmit, after) { - var that = this; - var commStr = ""; - if (doSubmit === undefined) { // missing optional argument - doSubmit = false; - } - if (after === undefined) { // missing optional argument - after = false; - } - if (msgStrs[commentString]) { - commStr = msgStrs[commentString]; - } - var newButton = this.doc.createElement("input"); - newButton.setAttribute("id", newId); - if (doSubmit) { - newButton.setAttribute("type", "submit"); - } else { - newButton.setAttribute("type", "button"); - } - newButton.value = newLabel; - newButton.addEventListener("click", function(evt) { - that.generalPurposeCureForAllDisease(commStr, nState, secPar); - }, false); - - if (after) { - originalLocation.parentNode.insertBefore(newButton, - originalLocation.nextSibling); - originalLocation.parentNode.insertBefore(this.doc - .createTextNode("\u00A0"), newButton); - } else { - originalLocation.parentNode.insertBefore(newButton, originalLocation); - originalLocation.parentNode.insertBefore(this.doc - .createTextNode("\u00A0"), originalLocation); - } +BZPage.prototype.setNeedinfoReporter = function() { + this.clickMouse("needinfo"); + this.selectOption("needinfo_role", "reporter"); +}; + +/** + * + */ +BZPage.prototype.getOwner = function() { + let priorityParent = this.doc.querySelector("label[for~='target_milestone']") + .parentNode.parentNode.parentNode; + let assigneeAElement = priorityParent.querySelector("tr:nth-of-type(1) a.email"); + let assgineeHref = decodeURI(assigneeAElement.getAttribute("href")); + console.log("assignee href = " + assgineeHref); + let email = assgineeHref.split(":")[1]; + console.log("assignee's email = " + email); + return email; }; /** @@ -1029,14 +1120,11 @@ BZPage.prototype.addNewButton = function(originalLocation, newId, newLabel, * @return String with the login name of the currently logged-in user */ BZPage.prototype.getLogin = function () { - var lastLIElement = this.doc.querySelector("#header ul.links li:last-of-type"); - console.log("Testing element:\n"+ lastLIElement); - console.log("Testing element.textContent:\n"+ lastLIElement.textContent); - var loginArr = lastLIElement.textContent.split("\n"); - console.log("loginArr = " + loginArr.toSource()); - var loginStr = loginArr[loginArr.length - 1].trim(); - console.log("loginStr = " + loginStr); - return loginStr; + let lastLIElement = this.doc.querySelector("#header ul.links li:last-of-type"); + let loginArr = lastLIElement.textContent.split("\n"); + let loginStr = loginArr[loginArr.length - 1].trim(); + console.log("login = " + loginStr); + return loginStr; }; /** @@ -1049,12 +1137,12 @@ BZPage.prototype.getLogin = function () { */ BZPage.prototype.getAttachments = function() { let outAtts = []; - let atts = this.doc.getElementById("attachment_table") - .getElementsByTagName("tr"); - for ( var i = 1, ii = atts.length - 1; i < ii; i++) { - outAtts.push(this.parseAttachmentLine(atts[i])); - } - return outAtts; + let atts = this.doc.getElementById("attachment_table") + .getElementsByTagName("tr"); + for ( let i = 1, ii = atts.length - 1; i < ii; i++) { + outAtts.push(this.parseAttachmentLine(atts[i])); + } + return outAtts; }; /** @@ -1067,29 +1155,29 @@ BZPage.prototype.getAttachments = function() { * - more importantly, we should use jetpack.storage.settings */ BZPage.prototype.getPassword = function() { - if (jetpack.storage.settings.BZpassword) { - return jetpack.storage.settings.BZpassword; - } else { - var prompts = Components.classes["@mozilla.org/embedcomp/prompt-service;1"] - .getService(Components.interfaces.nsIPromptService); - var password = { - value : "" - }; // default the password to pass - var check = { - value : true - }; // default the checkbox to true - var result = prompts.promptPassword(null, "Title", "Enter password:", - password, null, check); - // result is true if OK was pressed, false if cancel was pressed. - // password.value is - // set if OK was pressed. The checkbox is not displayed. - if (result) { - let passwordText = password.value; - jetpack.storage.settings.BZpassword = passwordText; - jetpack.storage.simple.sync(); - return passwordText; - } - } + if (jetpack.storage.settings.BZpassword) { + return jetpack.storage.settings.BZpassword; + } else { + let prompts = Components.classes["@mozilla.org/embedcomp/prompt-service;1"] + .getService(Components.interfaces.nsIPromptService); + let password = { + value : "" + }; // default the password to pass + let check = { + value : true + }; // default the checkbox to true + let result = prompts.promptPassword(null, "Title", "Enter password:", + password, null, check); + // result is true if OK was pressed, false if cancel was pressed. + // password.value is + // set if OK was pressed. The checkbox is not displayed. + if (result) { + let passwordText = password.value; + jetpack.storage.settings.BZpassword = passwordText; + jetpack.storage.simple.sync(); + return passwordText; + } + } return null; }; @@ -1102,141 +1190,143 @@ BZPage.prototype.setUpLoggingButtons = function() { .getElementsByClassName("related_actions")[0]; let that = this; - // logging all submits for timesheet - this.doc.forms.namedItem("changeform").addEventListener("submit", - function(evt) { - if (that.addLogRecord() === null) { - // FIXME doesn't work ... still submitting' - evt.stopPropagation(); - evt.preventDefault(); - } - }, false); - - var generateTimeSheetUI = this.doc.createElement("li"); - generateTimeSheetUI.innerHTML = "\u00A0-\u00A0<a href='#' id='generateTSButton'>" - + "Generate timesheet</a>"; - additionalButtons.appendChild(generateTimeSheetUI); - this.doc.getElementById("generateTSButton").addEventListener( - "click", - function(evt) { - that.createBlankPage.call(that, "TimeSheet", - that.generateTimeSheet); - evt.stopPropagation(); - evt.preventDefault(); - }, false); - - var clearLogsUI = this.doc.createElement("li"); - clearLogsUI.innerHTML = "\u00A0-\u00A0<a href='#' id='clearLogs'>" - + "Clear logs</a>"; - additionalButtons.appendChild(clearLogsUI); - var clearLogAElem = this.doc.getElementById("clearLogs"); - clearLogAElem.addEventListener("click", function() { - myStorage.logs = {}; - jetpack.storage.simple.sync(); - this.style.color = that.EmptyLogsColor; - clearLogAElem.style.fontWeight = "normal"; - console.log("mystorage.logs wiped out!"); - }, false); - - if (!myStorage.logs) { - console.log("No myStorage.logs defined!"); - myStorage.logs = {}; - } - - if (myStorage.logs) { - clearLogAElem.style.color = this.FullLogsColor; - clearLogAElem.style.fontWeight = "bolder"; - } else { - clearLogAElem.style.color = this.EmptyLogsColor; - clearLogAElem.style.fontWeight = "normal"; - } -}; - -/** - * - */ -BZPage.prototype.markBadAttachments = function() { - let badMIMEArray = [ "application/octet-stream", "text/x-log", "undefined" ]; - - let badAttachments = this.attachments.filter(function(att, idx, arr) { - return (hlpr.isInList(att[2], badMIMEArray)); - }); + // logging all submits for timesheet + this.doc.forms.namedItem("changeform").addEventListener("submit", + function(evt) { + if (that.addLogRecord() === null) { + // FIXME doesn't work ... still submitting' + evt.stopPropagation(); + evt.preventDefault(); + } + }, false); + + let generateTimeSheetUI = this.doc.createElement("li"); + generateTimeSheetUI.innerHTML = "\u00A0-\u00A0<a href='#' id='generateTSButton'>" + + "Generate timesheet</a>"; + additionalButtons.appendChild(generateTimeSheetUI); + this.doc.getElementById("generateTSButton").addEventListener( + "click", + function(evt) { + that.createBlankPage.call(that, "TimeSheet", + that.generateTimeSheet); + evt.stopPropagation(); + evt.preventDefault(); + }, false); + + let clearLogsUI = this.doc.createElement("li"); + clearLogsUI.innerHTML = "\u00A0-\u00A0<a href='#' id='clearLogs'>" + + "Clear logs</a>"; + additionalButtons.appendChild(clearLogsUI); + let clearLogAElem = this.doc.getElementById("clearLogs"); + clearLogAElem.addEventListener("click", function() { + myStorage.logs = {}; + jetpack.storage.simple.sync(); + this.style.color = that.EmptyLogsColor; + clearLogAElem.style.fontWeight = "normal"; + console.log("mystorage.logs wiped out!"); + }, false); + + if (!myStorage.logs) { + console.log("No myStorage.logs defined!"); + myStorage.logs = {}; + } - if (badAttachments.length > 0) { - var titleElement = this.doc - .getElementsByClassName("bz_alias_short_desc_container")[0]; - titleElement.style.backgroundColor = "olive"; - titleElement.appendChild(this.createFixAllButton(badAttachments)); - badAttachments.forEach(function(x, i, a) { - this.addTextLink(x); - }, this); - } + if (myStorage.logs) { + clearLogAElem.style.color = this.FullLogsColor; + clearLogAElem.style.fontWeight = "bolder"; + } else { + clearLogAElem.style.color = this.EmptyLogsColor; + clearLogAElem.style.fontWeight = "normal"; + } }; /** + * adds a person to the CC list, if it isn't already there + * + * @param who String with email address or "self" if the current user + * of the bugzilla should be added + */ +BZPage.prototype.addToCCList(who) { + if (who == "self") { + this.doc.getElementById("addselfcc").checked = true; + } else { + this.clickMouse("cc_edit_area_showhide"); + if (!hlpr.isInList(who, this.CCList)) { + this.doc.addStuffToTextBox("newcc",who); + } + } +} + +/** * a collect a list of emails on CC list * * @return Array with email addresses as Strings. */ BZPage.prototype.getCCList = function() { - let CCListSelect = this.doc.getElementById("cc"); - outCCList = []; - if (CCListSelect) { - outCCList = Array.map(CCListSelect.options, function(item) { - return item.value; - }); - } + let CCListSelect = this.doc.getElementById("cc"); + outCCList = []; + if (CCListSelect) { + outCCList = Array.map(CCListSelect.options, function(item) { + return item.value; + }); + } return outCCList; }; +/** + * + */ BZPage.prototype.pasteBacktraceInComments = function() { // FIXME This paragraph looks suspicous ... what is it? // Does it belong to this function? - var notedLabel = this.doc.querySelector("label[for='newcc']"); - while (notedLabel.firstChild) { - var node = notedLabel.removeChild(notedLabel.firstChild); - notedLabel.parentNode.insertBefore(node, notedLabel); - } - notedLabel.parentNode.removeChild(notedLabel); - - var mainTitle = this.doc - .getElementsByClassName("bz_alias_short_desc_container")[0]; - var abrtButton = this.doc.createElement("a"); - abrtButton.setAttribute("accesskey", "a"); - abrtButton.setAttribute("href", abrtQueryURL); - abrtButton.textContent = "Abrt bugs"; - mainTitle.appendChild(abrtButton); - - if (this.idContainsWord("cf_devel_whiteboard", 'btparsed')) { - this.addTextToTextBox('status_whiteboard', 'btparsed'); - } - - if (!(this.isTriaged() || this.idContainsWord("status_whiteboard", - 'btparsed'))) { - var btAttachments = this.attachments - .filter(function(att, idx, arr) { - return (/backtrace/.test(att[0])); - }); - // TODO we need to go through all backtrace attachments, but - // just the first one will do for now, we would need to do async - // parsing - btAttachments.forEach(function(x) { - attURL = "https://bugzilla.redhat.com/attachment.cgi?id=" - + x[1]; - console.log("attURL = " + attURL); - console.log("btSnippet = " + this.btSnippet); - if (!this.btSnippet) { - var btRaw = hlpr.loadText(attURL, function(ret) { - this.btSnippet = this.parseBacktrace(ret); - if (this.btSnippet) { - this.addTextToTextBox("comment", this.btSnippet); - this.addTextToTextBox("status_whiteboard", - "btparsed"); - } - }, this); - } - }, this); - } + let notedLabel = this.doc.querySelector("label[for='newcc']"); + while (notedLabel.firstChild) { + let node = notedLabel.removeChild(notedLabel.firstChild); + notedLabel.parentNode.insertBefore(node, notedLabel); + } + notedLabel.parentNode.removeChild(notedLabel); + + let abrtQueryURL = "https://bugzilla.redhat.com/buglist.cgi?" + + "cmdtype=dorem&remaction=run&namedcmd=all%20NEW%20abrt%20crashes&sharer_id=74116"; + + let mainTitle = this.doc + .getElementsByClassName("bz_alias_short_desc_container")[0]; + let abrtButton = this.doc.createElement("a"); + abrtButton.setAttribute("accesskey", "a"); + abrtButton.setAttribute("href", abrtQueryURL); + abrtButton.textContent = "Abrt bugs"; + mainTitle.appendChild(abrtButton); + + if (this.idContainsWord("cf_devel_whiteboard", 'btparsed')) { + this.addStuffToTextBox('status_whiteboard', 'btparsed'); + } + + if (!(this.isTriaged() || this.idContainsWord("status_whiteboard", + 'btparsed'))) { + let btAttachments = this.attachments + .filter(function(att, idx, arr) { + return (/backtrace/.test(att[0])); + }); + // TODO we need to go through all backtrace attachments, but + // just the first one will do for now, we would need to do async + // parsing + btAttachments.forEach(function(x) { + attURL = "https://bugzilla.redhat.com/attachment.cgi?id=" + + x[1]; + console.log("attURL = " + attURL); + console.log("btSnippet = " + this.btSnippet); + if (!this.btSnippet) { + let btRaw = hlpr.loadText(attURL, function(ret) { + this.btSnippet = this.parseBacktrace(ret); + if (this.btSnippet) { + this.addStuffToTextBox("comment", this.btSnippet); + this.addStuffToTextBox("status_whiteboard", + "btparsed"); + } + }, this); + } + }, this); + } }; // ==================================================================================== @@ -1256,90 +1346,89 @@ RHBugzillaPage = function(doc) { // inheritance ... call superobject's constructor BZPage.call(this,doc); - // For identification of graphics card - const manuChipStrs = [ [ "ATI Radeon", "ATI", "1002" ], - [ "ATI Mobility Radeon", "ATI", "1002" ], - [ "Intel Corporation", "INTEL", "8086" ], [ "NVIDIA", "NV", "10de" ] ]; - - // http://en.wikipedia.org/wiki/HSL_color_space - // when only the value of S is changed - // stupido!!! the string is value in hex for each color - this.RHColor = new Color(158, 41, 43); // RGB 158, 41, 43; HSL 359, 1, 39 - this.FedoraColor = new Color(0, 40, 103); // RGB 0, 40, 103; HSL 359, 1, 39 - this.RawhideColor = new Color(0, 119, 0); // or "green", or RGB 0, 119, 0, or - // HSL - // 120, 0, 23 - this.RHITColor = new Color(102, 0, 102); // RGB 102, 0, 102; HSL 300, 0, 20 - // END OF CONSTANTS - - var that = this; - this.originalButton = this.doc.getElementById("commit"); - this.reqCounter = 0; + // For identification of graphics card + const manuChipStrs = [ [ "ATI Radeon", "ATI", "1002" ], + [ "ATI Mobility Radeon", "ATI", "1002" ], + [ "Intel Corporation", "INTEL", "8086" ], [ "NVIDIA", "NV", "10de" ] ]; + + // http://en.wikipedia.org/wiki/HSL_color_space + // when only the value of S is changed + // stupido!!! the string is value in hex for each color + this.RHColor = new Color(158, 41, 43); // RGB 158, 41, 43; HSL 359, 1, 39 + this.FedoraColor = new Color(0, 40, 103); // RGB 0, 40, 103; HSL 359, 1, 39 + this.RawhideColor = new Color(0, 119, 0); // or "green", or RGB 0, 119, 0, or + // HSL + // 120, 0, 23 + this.RHITColor = new Color(102, 0, 102); // RGB 102, 0, 102; HSL 300, 0, 20 + // END OF CONSTANTS + + let that = this; + this.reqCounter = 0; + this.chipMagicInterestingLine = ""; this.login = this.getLogin(); this.password = this.getPassword(); - var bugNoTitle = this.doc.querySelector("#title > p").textContent.trim(); - this.bugNo = new RegExp("[0-9]+").exec(bugNoTitle)[0]; - - this.reporter = this.getReporter(); - this.product = this.getOptionValue("product"); - this.component = this.getOptionValue("component"); - this.version = this.getVersion(); - this.title = this.doc.getElementById("short_desc_nonedit_display").textContent; - var ITbutton = this.doc.getElementById("cf_issuetracker"); - this.its = ITbutton ? ITbutton.value.trim() : ""; + let bugNoTitle = this.doc.querySelector("#title > p").textContent.trim(); + this.bugNo = new RegExp("[0-9]+").exec(bugNoTitle)[0]; + + this.reporter = this.getReporter(); + this.product = this.getOptionValue("product"); + this.component = this.getOptionValue("component"); + this.version = this.getVersion(); + this.defaultAssignee = this.setDefaultAssignee(); + this.title = this.doc.getElementById("short_desc_nonedit_display").textContent; + let ITbutton = this.doc.getElementById("cf_issuetracker"); + this.its = ITbutton ? ITbutton.value.trim() : ""; this.CCList = this.getCCList(); - - // TODO be careful about this, seems breaking for non-RH BugZappers, - // but I cannot see why - this.owner = this.doc.getElementById("bz_assignee_edit_container") - .getElementsByClassName("fn")[0].textContent; - this.defaultAssignee = this.filterByRegexp(defAssigneeList, this.component) - .toLowerCase(); - this.maintCCAddr = this.filterByRegexp(AddrArray, this.component).toLowerCase(); - + + // Prepare for query buttons + let commentArea = this.doc.getElementById("comment_status_commit"); + let brElementPlacer = commentArea.getElementsByTagName("br")[0]; + brElementPlacer.setAttribute("id","brElementPlacer_location"); + brElementPlacer.parentNode.insertBefore(this.doc.createElement("br"), + brElementPlacer); + + // set default assignee on change of the component + this.doc.getElementById("component").addEventListener("change", + function() { + that.component = that.getOptionValue("component"); + that.changeAssignee("default"); + }, false); + // getBadAttachments - this.XorgLogAttList = []; - this.XorgLogAttListIndex = 0; - this.attachments = this.getAttachments(); - this.markBadAttachments(); + this.XorgLogAttList = []; + this.XorgLogAttListIndex = 0; + this.attachments = this.getAttachments(); + this.markBadAttachments(); - // Dig out backtrace - this.btSnippet = ""; + // Dig out backtrace + this.btSnippet = ""; - console.log("parseAbrtBacktraces = " + parseAbrtBacktraces); - if (parseAbrtBacktraces && AbrtRE.test(this.title)) { + let parseAbrtBacktraces = config.gJSONData.configData.parseAbrtBacktraces; + console.log("parseAbrtBacktraces = " + parseAbrtBacktraces); + if (parseAbrtBacktraces && AbrtRE.test(this.title)) { this.pasteBacktraceInComments(); - } - - // Take care of signature for Fedora bugzappers - if (signatureFedoraString.length > 0) { - this.doc.forms.namedItem("changeform").addEventListener("submit", - function() { - that.addTextToTextBox("comment", signatureFedoraString); - }, false); - } - - this.setBranding(); - this.checkComments(); - this.buildButtons(topRow, bottomRow); - - // set default assignee on change of the component - this.doc.getElementById("component").addEventListener( - "change", - function() { - that.component = that.getOptionValue("component"); - that - .changeOwner(that.filterByRegexp(defAssigneeList, - that.component).toLowerCase()); - }, false); - - // offline-capable submit - this.doc.forms.namedItem("changeform").addEventListener('submit', - function(evt) { - that.submitCallback.call(that, evt); - }, false); + } + + // Take care of signature for Fedora bugzappers + if (config.gJSONData.configData.signatureFedoraString.length > 0) { + let signatureFedoraString = config.gJSONData.configData.signatureFedoraString; + this.doc.forms.namedItem("changeform").addEventListener("submit", + function() { + that.addStuffToTextBox("comment", signatureFedoraString); + }, false); + } + + this.setBranding(); + this.checkComments(); + this.buildButtons(topRow, bottomRow); + + // offline-capable submit + this.doc.forms.namedItem("changeform").addEventListener('submit', + function(evt) { + that.submitCallback.call(that, evt); + }, false); if (logSubmits) { this.setUpLoggingButtons(); @@ -1349,6 +1438,88 @@ RHBugzillaPage = function(doc) { RHBugzillaPage.prototype = hlpr.heir(BZPage); RHBugzillaPage.prototype.constructor = RHBugzillaPage; +/** + * Find default assignee based on the current component + * + * @return none + * sets this.defaultAssignee property according to defaultAssignee list + */ +RHBugzillaPage.prototype.setDefaultAssignee = function() { + this.defaultAssignee = this.filterByRegexp( + this.constantData.defaultAssignee, + this.component).toLowerCase(); + + // Add setting default assignee + if ((defAss.length > 0) && (defAss !== this.getOwner())) { + this.constantData.defaultAssigneeTrigger = true; + this.createNewButton("bz_assignee_edit_container",true,"rh-common","setDefaultAssignee"); + } +}; + +/** + * Auxiliary function to computer more complicated resolution + */ +RHBugzillaPage.prototype.closeSomeRelease = function() { + // for RAWHIDE close as RAWHIDE, + // if active selection -> CURRENTRELEASE + // and put the release version to + // "Fixed in Version" textbox + // otherwise -> NEXTRELEASE + let verNo = this.getVersion(); + this.selectOption("bug_status", "CLOSED"); + let text = ""; + let resolution = ""; + + if (jetpack.selection.text) { + text = jetpack.select.text.trim(); + } + if (text.length > 0) { + resolution = "CURRENTRELEASE"; + this.doc.getElementById("cf_fixed_in").value = text; + } else if (verNo === 999) { + resolution = "RAWHIDE"; + } else { + resolution = "NEXTRELEASE"; + } + this.centralCommandDispatch("resolution", resolution); +}; + +/** + * Additional commands specific for this subclass, overriding superclass one. + */ +RHBugzillaPage.prototype.centralCommandDispatch = function(cmdLabel, cmdParams) { + switch (cmdLabel) { + // Set up our own commands + case "closeUpstream": + this.addClosingUpstream(); + break; + case "computeResolution": + this.closeSomeRelease(); + break; + case "queryStringOurBugzilla": + this.queryForSelection(); + break; + case "queryUpstreamBugzilla": + this.queryUpstream(); + break; + case "sendBugUpstream": + this.sendBugUpstream(); + break; + case "markTriaged": + this.markBugTriaged(); + break; + case "chipMagic": + let splitArr = cmdParams.split("\t"); + this.fillInWhiteBoard(splitArr[0], splitArr[1]); + break; + // If we don't have it here, call superclass method + default: + BZPage.centralCommandDispatch.call(this, cmdLabel, cmdParams); + break; + } +}; + + /* Offline supporting functions */ /** * @@ -1369,81 +1540,75 @@ RHBugzillaPage.prototype.constructor = RHBugzillaPage; * http://www.innovation.ch/java/HTTPClient/emulating_forms.html - */ RHBugzillaPage.prototype.serializeForm = function(form) { - var serialForm = { - dataOut : "", - name : form.name, - method : form.method, - acceptCharset : form.acceptCharset, - action : form.action, // TODO shouldn't we get a non-relative URL? - enctype : form.enctype, - cookie : this.doc.cookie, - autocomplete : form.getAttribute("autocomplete"), - bugNo : this.bugNo - }; - - function genURIElement(sName, sValue) { - return encodeURIComponent(sName) + "=" + encodeURIComponent(sValue); - } - - /** - * @param o - * control to be serialized - * @return String with the serialized control - */ - function serializeControl(element) { - var val = element.value; - // console.log("val.toSource() = " + val.toSource()); - /* - * on HTMLSelectElement we have an attribute 'type' of type DOMString, - * readonly The type of this form control. This is the string - * "select-multiple" when the multiple attribute is true and the string - * "select-one" when false. - */ - if ((val == null) || (val == undefined) || (val == "")) { - return; - } else if (val instanceof Array) { - return val.map(function(x) { - return genURIElement(element.name, x.value); - }).join("&"); - } else if (val instanceof String) { - return genURIElement(element.name, val); - } else { // assume HTMLCollection - return Array.map(val, function(x) { - return genURIElement(element.name, x.value); - }).join("&"); - } - } - - serialForm.dataOut = Array - .filter( - form.elements, - function(el) { - return !el.disabled - && el.name - && - // FIXME shouldn't I just add && el.value here? - (el.checked - || /select|textarea/i.test(el.nodeName) || /text|hidden|password|search/i - .test(el.type)); - }).map(serializeControl).join("&"); - return serialForm; + let serialForm = { + dataOut : "", + name : form.name, + method : form.method, + acceptCharset : form.acceptCharset, + action : form.action, // TODO shouldn't we get a non-relative URL? + enctype : form.enctype, + cookie : this.doc.cookie, + autocomplete : form.getAttribute("autocomplete"), + bugNo : this.bugNo + }; + + function genURIElement(sName, sValue) { + return encodeURIComponent(sName) + "=" + encodeURIComponent(sValue); + } + + /** + * @param o + * control to be serialized + * @return String with the serialized control + */ + function serializeControl(element) { + let val = element.value; + // console.log("val.toSource() = " + val.toSource()); + /* + * on HTMLSelectElement we have an attribute 'type' of type DOMString, + * readonly The type of this form control. This is the string + * "select-multiple" when the multiple attribute is true and the string + * "select-one" when false. + */ + if ((val == null) || (val == undefined) || (val == "")) { + return; + } else if (val instanceof Array) { + return val.map(function(x) { + return genURIElement(element.name, x.value); + }).join("&"); + } else if (val instanceof String) { + return genURIElement(element.name, val); + } else { // assume HTMLCollection + return Array.map(val, function(x) { + return genURIElement(element.name, x.value); + }).join("&"); + } + } + + serialForm.dataOut = Array.filter(form.elements,function(el) { + return !el.disabled && el.name && + // FIXME shouldn't I just add && el.value here? + (el.checked || /select|textarea/i.test(el.nodeName) || + /text|hidden|password|search/i.test(el.type)); + }).map(serializeControl).join("&"); + return serialForm; }; RHBugzillaPage.prototype.submitCallback = function(evt) { - console.log("Submit Callback!"); - if (jetpack.__parent__.navigator.onLine) { - var serForm = this - .serializeForm(jetpack.tabs.focused.contentWindow.document.forms - .namedItem("changeform")); - console.log("serForm:\n" + serForm.toSource()); - } else { - var serForm = this - .serializeForm(jetpack.tabs.focused.contentWindow.document.forms - .namedItem("changeform")); - myStorage.forms[this.bugNo] = serForm; - evt.stopPropagation(); - evt.preventDefault(); - } + console.log("Submit Callback!"); + if (jetpack.__parent__.navigator.onLine) { + let serForm = this + .serializeForm(jetpack.tabs.focused.contentWindow.document.forms + .namedItem("changeform")); + console.log("serForm:\n" + serForm.toSource()); + } else { + let serForm = this + .serializeForm(jetpack.tabs.focused.contentWindow.document.forms + .namedItem("changeform")); + myStorage.forms[this.bugNo] = serForm; + evt.stopPropagation(); + evt.preventDefault(); + } }; /** @@ -1451,121 +1616,102 @@ RHBugzillaPage.prototype.submitCallback = function(evt) { * * Yes, this is correct, this is NOT method of RHBugzillaPage! */ -function onlineCallback() { - function deserializeAndSend(formData) { - // FIXME notImplemented - // is it enough to just - // run XMLHttpRequest? Probably yes, this is just a form - // and this is just a HTTP request - // it is probably better to get already processed - // application/x-www-form-urlencoded - // see http://htmlhelp.com/reference/html40/forms/form.html for details - // and also https://developer.mozilla.org/en/AJAX/Getting_Started - // what's? - // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference\ - // /Global_Functions/encodeURI & co. - // this seems to be also interesting - // https://developer.mozilla.org/en/Code_snippets/Post_data_to_window - console.error("Sending bugs not implemented yet!"); - return ""; // FIXME check other HTTP headers to be set - - var bugID = formData.bugNo; - var req = new XMLHttpRequest(); - req.open("POST", formData.action, true); - // FIXME co očekávám za odpověď? req.overrideMimeType("text/xml"); - // * Accept-Encoding - // * Accept-Language - // * Accept (MIME types) - req.setRequestHeader("Connection", "keep-alive"); - req.setRequestHeader("Keep-Alive", 300); - req.setRequestHeader("Content-Type", formData.enctype); - req.setRequestHeader("Referer", bugURL + bugID); - req.setRequestHeader("Accept-Charset", formData.acceptCharset); - req.setRequestHeader("Cookie", formData.cookie); - req.onreadystatechange = function(aEvt) { - if (req.readyState == 4) { - if (req.status == 200) { - console.log("Sent form for bug " + bugID); - delete myStorage.forms[bugID]; - } else { - console.error("Sending form for bug " + bugID + "failed!"); - } - } - }; - req.send(formData.data); - } - - if (myStorage.forms.length > 0) { - myStorage.forms.forEach(function(x) { - deserializeAndSend(x); - }); - } -} +/*function onlineCallback() { + function deserializeAndSend(formData) { + // FIXME notImplemented + // is it enough to just + // run XMLHttpRequest? Probably yes, this is just a form + // and this is just a HTTP request + // it is probably better to get already processed + // application/x-www-form-urlencoded + // see http://htmlhelp.com/reference/html40/forms/form.html for details + // and also https://developer.mozilla.org/en/AJAX/Getting_Started + // what's? + // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference\ + // /Global_Functions/encodeURI & co. + // this seems to be also interesting + // https://developer.mozilla.org/en/Code_snippets/Post_data_to_window + console.error("Sending bugs not implemented yet!"); + return ""; // FIXME check other HTTP headers to be set + + let bugID = formData.bugNo; + let req = new XMLHttpRequest(); + req.open("POST", formData.action, true); + // FIXME co očekávám za odpověď? req.overrideMimeType("text/xml"); + // * Accept-Encoding + // * Accept-Language + // * Accept (MIME types) + req.setRequestHeader("Connection", "keep-alive"); + req.setRequestHeader("Keep-Alive", 300); + req.setRequestHeader("Content-Type", formData.enctype); + req.setRequestHeader("Referer", bugURL + bugID); + req.setRequestHeader("Accept-Charset", formData.acceptCharset); + req.setRequestHeader("Cookie", formData.cookie); + req.onreadystatechange = function(aEvt) { + if (req.readyState == 4) { + if (req.status == 200) { + console.log("Sent form for bug " + bugID); + delete myStorage.forms[bugID]; + } else { + console.error("Sending form for bug " + bugID + "failed!"); + } + } + }; + req.send(formData.data); + } + if (myStorage.forms.length > 0) { + myStorage.forms.forEach(function(x) { + deserializeAndSend(x); + }); + } +} +*/ /* Bugzilla functions. */ /** - * Get the current email of the reporter of the bug. - * - * @return string + * */ -RHBugzillaPage.prototype.getReporter = function() { - return this.doc - .querySelector("#bz_show_bug_column_2 > table .vcard:first-of-type > a").textContent; -}; +RHBugzillaPage.prototype.createBlankPage = function (ttl, bodyBuildCB) { + let title = ttl || "Yet another untitled page"; + let that = this; -/** - * Get the current version of the Fedora release ... even if changed meanwhile - * by bug triager. - * - * @return string (integer for released Fedora, float for RHEL, rawhide) - */ -RHBugzillaPage.prototype.getVersion = function() { - var verStr = this.getOptionValue("version").toLowerCase(); - var verNo = 0; - if (/rawhide/.test(verStr)) { - verNo = 999; - } else { - verNo = Number(verStr); - } - return verNo; + let logTab = jetpack.tabs.open("about:blank"); + jetpack.tabs.onReady(function() { + let otherDoc = logTab.contentDocument; + otherDoc.title = title; + otherDoc.body.innerHTML = "<h1>" + title + "</h1>"; + bodyBuildCB.call(that, otherDoc.body); + logTab.focus(); + }); }; -RHBugzillaPage.prototype.commentsWalker = function(fce) { - var comments = this.doc.getElementById("comments").getElementsByClassName( - "bz_comment"); - Array.forEach(comments, function(item) { - fce(item); - }, this); -}; + +RHBugzillaPage.prototype.ProfessionalProducts = [ + "Red Hat Enterprise Linux", + "Red Hat Enterprise MRG" +]; /** - * Set background color of all comments made by reporter in ReporterColor color * */ -RHBugzillaPage.prototype.checkComments = function() { - var that = this; - this.commentsWalker(function(x) { - var email = x.getElementsByClassName("vcard")[0] - .getElementsByTagName("a")[0].textContent; - if (new RegExp(that.reporter).test(email)) { - x.style.backgroundColor = that.ReporterColor.toString(); - } - }); -}; +RHBugzillaPage.prototype.markBadAttachments = function() { + let badMIMEArray = [ "application/octet-stream", "text/x-log", "undefined" ]; -RHBugzillaPage.prototype.collectComments = function() { - var outStr = ""; - this.commentsWalker(function(x) { - outStr += x.getElementsByTagName("pre")[0].textContent + "\n"; - }); - return outStr.trim(); -}; + let badAttachments = this.attachments.filter(function(att, idx, arr) { + return (hlpr.isInList(att[2], badMIMEArray)); + }); -RHBugzillaPage.prototype.ProfessionalProducts = [ - "Red Hat Enterprise Linux", - "Red Hat Enterprise MRG" -]; + if (badAttachments.length > 0) { + let titleElement = this.doc + .getElementsByClassName("bz_alias_short_desc_container")[0]; + titleElement.style.backgroundColor = "olive"; + titleElement.appendChild(this.createFixAllButton(badAttachments)); + badAttachments.forEach(function(x, i, a) { + this.addTextLink(x); + }, this); + } +}; /** * Is this bug a RHEL bug? @@ -1573,14 +1719,14 @@ RHBugzillaPage.prototype.ProfessionalProducts = [ * @return Boolean true if it is a RHEL bug */ RHBugzillaPage.prototype.isEnterprise = function() { - var prod = this.product; + let prod = this.product; console.log("Testing whether the bug with product = " + prod + " is an enterprise bug."); - var result = this.ProfessionalProducts.some(function(elem,idx,arr) { + let result = this.ProfessionalProducts.some(function(elem,idx,arr) { return new RegExp(elem).test(prod); - }); - console.log("result = " + result); - return result; + }); + console.log("result = " + result); + return result; }; /** @@ -1589,92 +1735,90 @@ RHBugzillaPage.prototype.isEnterprise = function() { * @return Boolean whether the bug has been triaged or not */ RHBugzillaPage.prototype.isTriaged = function() { - // First excceptions - if (this.version > 7 && this.version < 12) { - return this.doc.getElementById("bug_status").value.toUpperCase() !== "NEW"; - } else { // and then the rule - return this.hasKeyword("Triaged"); - } + // First excceptions + if (this.version > 7 && this.version < 12) { + return this.doc.getElementById("bug_status").value.toUpperCase() !== "NEW"; + } else { // and then the rule + return this.hasKeyword("Triaged"); + } }; /** * Set branding colours to easily distinguish between Fedora and RHEL bugs * - * @param brand - * string with product of the current bug - * @param version - * string with the version of the bug - * @param its - * string with the IsueTracker numbers + * @param brand String with product of the current bug + * @param version String with the version of the bug + * @param its String with the IsueTracker numbers * @return none - * */ RHBugzillaPage.prototype.setBranding = function() { - var brandColor = {}; - var TriagedColor = {}; - - if (this.isEnterprise()) { - console.log("This is an enterprise bug."); - if (this.its && (this.its.length > 0)) { - brandColor = this.RHITColor; - } else { - brandColor = this.RHColor; - } - } else if (new RegExp("Fedora").test(this.product)) { - console.log("This is NOT an enterprise bug."); - if (this.version == 999) { - brandColor = this.RawhideColor; - } else { - brandColor = this.FedoraColor; - } - } - - // Comment each of the following lines to get only partial branding - this.doc.getElementsByTagName("body")[0].style.background = brandColor - .toString() - + " none"; - this.doc.getElementById("titles").style.background = brandColor.toString() - + " none"; - - // Remove "Bug" from the title of the bug page, so we have more space with - // plenty of tabs - var titleElem = this.doc.getElementsByTagName("title")[0]; - titleElem.textContent = titleElem.textContent.slice(4); - var bodyTitleParent = this.doc.getElementById("summary_alias_container").parentNode; - var bodyTitleElem = bodyTitleParent.getElementsByTagName("b")[0]; - bodyTitleElem.textContent = bodyTitleElem.textContent.slice(4); - - // Make background-color of the body of bug salmon pink - // for security bugs. - if (this.hasKeyword("Security")) { - this.doc.getElementById("bugzilla-body").style.background = SalmonPink - .toString() + ' none'; - } - - // Make it visible whether the bug has been triaged - if (this.isTriaged()) { - this.doc.getElementById("bz_field_status").style.background = brandColor - .lightColor().toString() - + " none"; - } - - // we should make visible whether maintCCAddr is in CCList - if (hlpr.isInList(this.maintCCAddr, this.CCList)) { - var ccEditBoxElem = this.doc.getElementById("cc_edit_area_showhide"); - // ccEditBoxElem.textContent = "*"+ccEditBoxElem.textContent; - ccEditBoxElem.style.color = "navy"; - ccEditBoxElem.style.fontWeight = "bolder"; - ccEditBoxElem.style.textDecoration = "underline"; - } - - // mark suspicious components - var compElems; - if (suspiciousComponents - && hlpr.isInList(this.component, suspiciousComponents) - && (compElems = this.doc - .getElementById("bz_component_edit_container"))) { - compElems.style.background = "red none"; - } + let brandColor = {}; + let TriagedColor = {}; + + if (this.isEnterprise()) { + console.log("This is an enterprise bug."); + if (this.its && (this.its.length > 0)) { + brandColor = this.RHITColor; + } else { + brandColor = this.RHColor; + } + } else if (new RegExp("Fedora").test(this.product)) { + console.log("This is NOT an enterprise bug."); + if (this.version == 999) { + brandColor = this.RawhideColor; + } else { + brandColor = this.FedoraColor; + } + } + + // Comment each of the following lines to get only partial branding + this.doc.getElementsByTagName("body")[0].style.background = brandColor + .toString() + + " none"; + this.doc.getElementById("titles").style.background = brandColor.toString() + + " none"; + + // Remove "Bug" from the title of the bug page, so we have more space with + // plenty of tabs + let titleElem = this.doc.getElementsByTagName("title")[0]; + + titleElem.textContent = titleElem.textContent.slice(4); + let bodyTitleParent = this.doc.getElementById("summary_alias_container").parentNode; + let bodyTitleElem = bodyTitleParent.getElementsByTagName("b")[0]; + bodyTitleElem.textContent = bodyTitleElem.textContent.slice(4); + + // Make background-color of the body of bug salmon pink + // for security bugs. + if (this.hasKeyword("Security")) { + this.doc.getElementById("bugzilla-body").style.background = SalmonPink + .toString() + ' none'; + } + + // Make it visible whether the bug has been triaged + if (this.isTriaged()) { + this.doc.getElementById("bz_field_status").style.background = brandColor + .lightColor().toString() + + " none"; + } + + // we should make visible whether maintCCAddr is in CCList + if (hlpr.isInList(this.maintCCAddr, this.CCList)) { + let ccEditBoxElem = this.doc.getElementById("cc_edit_area_showhide"); + // ccEditBoxElem.textContent = "*"+ccEditBoxElem.textContent; + ccEditBoxElem.style.color = "navy"; + ccEditBoxElem.style.fontWeight = "bolder"; + ccEditBoxElem.style.textDecoration = "underline"; + } + + // mark suspicious components + let compElems; + let suspiciousComponents = config.gJSONData.configData.suspiciousComponents; + if (suspiciousComponents + && hlpr.isInList(this.component, suspiciousComponents) + && (compElems = this.doc + .getElementById("bz_component_edit_container"))) { + compElems.style.background = "red none"; + } }; /** @@ -1686,77 +1830,77 @@ RHBugzillaPage.prototype.setBranding = function() { * @return None */ RHBugzillaPage.prototype.fillInWhiteBoard = function(iLine, driverStr) { - var that = this; - - function groupIDs(manStr, cardStrID) { - var outStr = that.filterByRegexp(chipIDsGroupings, manStr + "," + cardStrID); - if (outStr.length === 0) { - outStr = "UNGROUPED_" + manStr + "/" + cardStrID; - } - return outStr; - } - ; - - /** - * Given PCI IDs for manufacturer and card ID return chipset string - * - * @param manufacturerNo String with manufacturer PCI ID - * @param cardNo String with card PCI ID - * @return Array with chip string and optinoal variants - */ - function checkChipStringFromID(manufacturerNo, cardNo) { - var soughtID = (manufacturerNo + "," + cardNo).toUpperCase(); - var outList = PCI_ID_Array[soughtID]; - if (outList) { - return outList; - } else { - return ""; - } - } - ; - - var outStr = ""; - var cardIDStr = ""; - var cardIDArr = []; - - chipSwitchboard: if (driverStr === "RADEON") { - var cardID = iLine.replace(ATIgetIDRE, "$1"); - cardIDArr = checkChipStringFromID("1002", cardID); - if (cardIDArr.length > 0) { - cardIDStr = cardIDArr[0]; - if (cardIDArr[1]) { - optionStr = cardIDArr[1]; - outStr = groupIDs(driverStr, cardIDStr) + "/" + optionStr; - } else { - outStr = groupIDs(driverStr, cardIDStr); - optionStr = ""; - } - } else { - outStr = "**** FULLSTRING: " + iLine; - } - } else { - // Intel Corporation, NVIDIA - cardIDArr = manuChipStrs.filter(function(el, ind, arr) { - return new RegExp(el[0], "i").test(iLine); - }); - if (cardIDArr && (cardIDArr.length > 0)) { - cardIDArr = cardIDArr[0]; - } else { - outStr = iLine; - break chipSwitchboard; - } - // cardIDArr [0] = RE, [1] = ("RADEON","INTEL","NOUVEAU"), [2] = manu - // PCIID - iLine = iLine.replace(new RegExp(cardIDArr[0], "i")).trim(); - // nVidia developers opted-out from grouping - if (driverStr === "INTEL") { - outStr = groupIDs(cardIDArr[1], iLine); - } else { - outStr = iLine; - } - } - this.addTextToTextBox("status_whiteboard", ("card_" + outStr).trim()); - this.doc.getElementById("chipmagic").style.display = "none"; + let that = this; + + function groupIDs(manStr, cardStrID) { + let outStr = that.filterByRegexp(chipIDsGroupings, manStr + "," + cardStrID); + if (outStr.length === 0) { + outStr = "UNGROUPED_" + manStr + "/" + cardStrID; + } + return outStr; + } + ; + + /** + * Given PCI IDs for manufacturer and card ID return chipset string + * + * @param manufacturerNo String with manufacturer PCI ID + * @param cardNo String with card PCI ID + * @return Array with chip string and optinoal variants + */ + function checkChipStringFromID(manufacturerNo, cardNo) { + let soughtID = (manufacturerNo + "," + cardNo).toUpperCase(); + let outList = config.PCI_ID_Array[soughtID]; + if (outList) { + return outList; + } else { + return ""; + } + } + ; + + let outStr = ""; + let cardIDStr = ""; + let cardIDArr = []; + + chipSwitchboard: if (driverStr === "RADEON") { + let cardID = iLine.replace(ATIgetIDRE, "$1"); + cardIDArr = checkChipStringFromID("1002", cardID); + if (cardIDArr.length > 0) { + cardIDStr = cardIDArr[0]; + if (cardIDArr[1]) { + optionStr = cardIDArr[1]; + outStr = groupIDs(driverStr, cardIDStr) + "/" + optionStr; + } else { + outStr = groupIDs(driverStr, cardIDStr); + optionStr = ""; + } + } else { + outStr = "**** FULLSTRING: " + iLine; + } + } else { + // Intel Corporation, NVIDIA + cardIDArr = manuChipStrs.filter(function(el, ind, arr) { + return new RegExp(el[0], "i").test(iLine); + }); + if (cardIDArr && (cardIDArr.length > 0)) { + cardIDArr = cardIDArr[0]; + } else { + outStr = iLine; + break chipSwitchboard; + } + // cardIDArr [0] = RE, [1] = ("RADEON","INTEL","NOUVEAU"), [2] = manu + // PCIID + iLine = iLine.replace(new RegExp(cardIDArr[0], "i")).trim(); + // nVidia developers opted-out from grouping + if (driverStr === "INTEL") { + outStr = groupIDs(cardIDArr[1], iLine); + } else { + outStr = iLine; + } + } + this.addStuffToTextBox("status_whiteboard", ("card_" + outStr).trim()); + this.doc.getElementById("chipmagic").style.display = "none"; }; /** @@ -1767,11 +1911,11 @@ RHBugzillaPage.prototype.fillInWhiteBoard = function(iLine, driverStr) { * @return None */ RHBugzillaPage.prototype.fillInChipMagic = function () { - var XorgLogURL = ""; - var XorgLogAttID = ""; - var XorgLogFound = false; - var attURL = "", interestingLine = ""; - var interestingArray = []; + let XorgLogURL = ""; + let XorgLogAttID = ""; + let XorgLogFound = false; + let attURL = "", interestingLine = ""; + let interestingArray = []; // Find out Xorg.0.log attachment URL @@ -1787,13 +1931,13 @@ RHBugzillaPage.prototype.fillInChipMagic = function () { attURL = "https://bugzilla.redhat.com/attachment.cgi?id="+XorgLogAttID; that = this; - var req = new XMLHttpRequest(); + let req = new XMLHttpRequest(); req.open("GET",attURL,true); req.onreadystatechange = function (aEvt) { if (req.readyState == 4) { if (req.status == 200) { - var ret = req.responseText; - var interestingLineArr = ret.split("\n"). + let ret = req.responseText; + let interestingLineArr = ret.split("\n"). filter(function (v,i,a) { return ChipsetRE.test(v); }); @@ -1802,13 +1946,12 @@ RHBugzillaPage.prototype.fillInChipMagic = function () { interestingArray = ChipsetRE.exec(interestingLineArr[0]); interestingLine = interestingArray[2]. replace(/[\s"]+/g," ").trim(); - var whiteboardInput = that.doc. - getElementById("status_whiteboard"); - that.addNewButton(whiteboardInput,"chipmagic","Fill In", - "","CHIPMAGIC", - interestingLine+"\t"+interestingArray[1].toUpperCase(), - false,true); - } + // Persuade createNewButton to have mercy and to actually add + // non-default button + this.constantData.chipMagicTrigger = true; + this.chipMagicInterestingLine = interestingLine+"\t"+interestingArray[1] + .toUpperCase(); + this.createNewButton("status_whiteboard", true, "rh-xorg", "chipMagic"); } else { throw "Getting attachment " + attURL + "failed!"; } @@ -1829,42 +1972,42 @@ RHBugzillaPage.prototype.fillInChipMagic = function () { * */ RHBugzillaPage.prototype.queryInNewTab = function(text, component, product) { - // Optional parameter - if (product === undefined) { - product = this.product; - } - var url = "https://bugzilla.redhat.com/buglist.cgi?query_format=advanced"; - if (product) { - url += "&product=" + product.trim(); - } - if (component) { - url += "&field0-0-0=component&type0-0-0=substring&value0-0-0=" - + component.trim(); - } - // using more complicated query tables here, because they can be more easily - // edited - // for further investigative searches - if (text) { - text = encodeURIComponent(text.trim()); - var searchText = "&field1-0-0=longdesc&type1-0-0=substring&value1-0-0=" - + text - + "&field1-0-1=attach_data.thedata&type1-0-1=substring&value1-0-1=" - + text - + "&field1-0-2=status_whiteboard&type1-0-2=substring&value1-0-2=" - + text; - url += searchText; - jetpack.tabs.open(url); - // Don't do it ... b.m.o is apparently not powerful enough to sustain - // the weight - // of the search - if (false) { - url = "https://bugzilla.mozilla.org/buglist.cgi?query_format=advanced" - + "field0-0-0=product;type0-0-0=regexp;" - + "value0-0-0=thunderbird|firefox|xulrunner" - + searchText.replace("&", ";"); - jetpack.tabs.open(url); - } - } + // Optional parameter + if (product === undefined) { + product = this.product; + } + let url = "https://bugzilla.redhat.com/buglist.cgi?query_format=advanced"; + if (product) { + url += "&product=" + product.trim(); + } + if (component) { + url += "&field0-0-0=component&type0-0-0=substring&value0-0-0=" + + component.trim(); + } + // using more complicated query tables here, because they can be more easily + // edited + // for further investigative searches + if (text) { + text = encodeURIComponent(text.trim()); + let searchText = "&field1-0-0=longdesc&type1-0-0=substring&value1-0-0=" + + text + + "&field1-0-1=attach_data.thedata&type1-0-1=substring&value1-0-1=" + + text + + "&field1-0-2=status_whiteboard&type1-0-2=substring&value1-0-2=" + + text; + url += searchText; + jetpack.tabs.open(url); + // Don't do it ... b.m.o is apparently not powerful enough to sustain + // the weight + // of the search + if (false) { + url = "https://bugzilla.mozilla.org/buglist.cgi?query_format=advanced" + + "field0-0-0=product;type0-0-0=regexp;" + + "value0-0-0=thunderbird|firefox|xulrunner" + + searchText.replace("&", ";"); + jetpack.tabs.open(url); + } + } }; /** @@ -1872,48 +2015,49 @@ RHBugzillaPage.prototype.queryInNewTab = function(text, component, product) { * function this.queryInNewTab, and run it. */ RHBugzillaPage.prototype.queryForSelection = function() { - var text = jetpack.selection.text; - if (!text) { - text = jetpack.clipboard.get(); - } - if (text) { - this.queryInNewTab(text, this.component); - } + let text = jetpack.selection.text; + if (!text) { + text = jetpack.clipboard.get(); + } + if (text) { + this.queryInNewTab(text, this.component); + } }; /** * Search simple query in the upstream bugzilla appropriate for the component. */ RHBugzillaPage.prototype.queryUpstream = function() { - var text = jetpack.selection.text; - if (!text) { - text = jetpack.clipboard.get(); - } - if (text) { - var text = encodeURIComponent(text.trim()); - var url = this.filterByRegexp(queryUpstreamBugsURLArray, this.component); - jetpack.tabs.open(url + text); - } + let text = jetpack.selection.text; + if (!text) { + text = jetpack.clipboard.get(); + } + if (text) { + let text = encodeURIComponent(text.trim()); + let queryUpstreamBugsURLArray = this.constantData.queryUpstreamBug; + let url = this.filterByRegexp(queryUpstreamBugsURLArray, this.component); + jetpack.tabs.open(url + text); + } } /** * */ RHBugzillaPage.prototype.sendBugUpstream = function() { - var url = this.filterByRegexp(newUpstreamBugsURLArray, this - .getOptionValue("component")); + let url = this.filterByRegexp(newUpstreamBugsURLArray, this + .getOptionValue("component")); - var ret = jetpack.tabs.open(url); - var that = this; - jetpack.tabs.onReady(function() { - var otherDoc = ret.contentDocument; - var otherElems = otherDoc.forms.namedItem("Create").elements; - otherElems.namedItem("short_desc").value = that.doc - .getElementById("short_desc_nonedit_display").textContent - .trim(); - otherElems.namedItem("comment").value = that.collectComments(); - ret.focused(); - }); + let ret = jetpack.tabs.open(url); + let that = this; + jetpack.tabs.onReady(function() { + let otherDoc = ret.contentDocument; + let otherElems = otherDoc.forms.namedItem("Create").elements; + otherElems.namedItem("short_desc").value = that.doc + .getElementById("short_desc_nonedit_display").textContent + .trim(); + otherElems.namedItem("comment").value = that.collectComments(); + ret.focused(); + }); }; /** @@ -1925,43 +2069,31 @@ RHBugzillaPage.prototype.sendBugUpstream = function() { * element itself */ RHBugzillaPage.prototype.parseAttachmentLine = function(inElem) { - var MIMEtype = ""; - var size = 0; - - // Skip over obsolete attachments - if (inElem.getElementsByClassName("bz_obsolete").length > 0) { - return ( []); - } + let MIMEtype = ""; + let size = 0; - // getting name of the attachment - var attName = inElem.getElementsByTagName("b")[0].textContent.trim(); + // Skip over obsolete attachments + if (inElem.getElementsByClassName("bz_obsolete").length > 0) { + return ( []); + } - var aHrefsArr = inElem.getElementsByTagName("a"); - var aHref = Array.filter(aHrefsArr, function(x) { - return x.textContent.trim() == "Details"; - })[0]; - var id = parseInt(aHref.getAttribute("href").replace( - /^.*attachment.cgi\?id=/, ""), 10); + // getting name of the attachment + let attName = inElem.getElementsByTagName("b")[0].textContent.trim(); - // getting MIME type and size - var stringArray = inElem.getElementsByClassName("bz_attach_extra_info")[0].textContent - .replace(/[\n ()]+/g, " ").trim().split(", "); - size = parseInt(stringArray[0], 10); - MIMEtype = stringArray[1].split(" ")[0]; + let aHrefsArr = inElem.getElementsByTagName("a"); + let aHref = Array.filter(aHrefsArr, function(x) { + return x.textContent.trim() == "Details"; + })[0]; + let id = parseInt(aHref.getAttribute("href").replace( + /^.*attachment.cgi\?id=/, ""), 10); - return [ attName, id, MIMEtype, size, inElem ]; -}; + // getting MIME type and size + let stringArray = inElem.getElementsByClassName("bz_attach_extra_info")[0].textContent + .replace(/[\n ()]+/g, " ").trim().split(", "); + size = parseInt(stringArray[0], 10); + MIMEtype = stringArray[1].split(" ")[0]; -/** - * Check for the presence of a keyword - * - * @param str String with the keyword - * @return Boolean - * - */ -RHBugzillaPage.prototype.hasKeyword = function(str) { - var kwd = this.doc.getElementById('keywords').value.trim(); - return (new RegExp(str).test(kwd)); + return [ attName, id, MIMEtype, size, inElem ]; }; /** @@ -1971,50 +2103,12 @@ RHBugzillaPage.prototype.hasKeyword = function(str) { * @param beforeText Text before the accesskey character * @param accKey what will be the accesskey itself * @param afterText text after the accesskey character - * @return modified element with the fixed accesskey FIXME isn't this closure - * and possible memleak? + * @return modified element with the fixed accesskey */ RHBugzillaPage.prototype.fixElement = function(elem, beforeText, accKey, afterText) { - elem.setAttribute("accesskey", accKey.toLowerCase()); - elem.innerHTML = beforeText + "<b><u>" + accKey + "</u></b>" + afterText; - return elem; -}; - -/** - * Add XGL to the CC list - * - * @param evt Event which made this function active - * @return none - */ -RHBugzillaPage.prototype.changeOwner = function(newAssignee) { - /** - * Take care that when changing assignment of the bug, current owner is - * added to CC list. Switch off setting to the default assignee - */ - var defAssigneeButton; - if (!hlpr.isInList(newAssignee, this.CCList)) { - this.doc.getElementById("newcc").textContent = newAssignee; - } - if (newAssignee) { - this.clickMouse("bz_assignee_edit_action"); - this.doc.getElementById("assigned_to").value = newAssignee; - this.doc.getElementById("set_default_assignee").checked = false; - if (defAssigneeButton = this.doc - .getElementById("setdefaultassigneebutton")) { - defAssigneeButton.style.display = "none"; - } - } -}; - -/** - * Set the bug to NEEDINFO state - * - * Working function. - * @return none - */ -RHBugzillaPage.prototype.setNeedinfoReporter = function() { - this.clickMouse("needinfo"); - this.selectOption("needinfo_role", "reporter"); + elem.setAttribute("accesskey", accKey.toLowerCase()); + elem.innerHTML = beforeText + "<b><u>" + accKey + "</u></b>" + afterText; + return elem; }; /** @@ -2024,31 +2118,31 @@ RHBugzillaPage.prototype.setNeedinfoReporter = function() { * @return String with the string for the external_id SELECT */ RHBugzillaPage.prototype.getBugzillaName = function(URLhostname) { - var bugzillaID = ""; - if (hashBugzillaName[URLhostname]) { - bugzillaID = hashBugzillaName[URLhostname]; - } else { - bugzillaID = ""; - } - return bugzillaID; + let bugzillaID = ""; + if (this.constantData.bugzillalabelNames[URLhostname]) { + bugzillaID = this.constantData.bugzillalabelNames[URLhostname]; + } else { + bugzillaID = ""; + } + return bugzillaID; }; /** * Generate URL of the bug on remote bugzilla * * @param selectValue Number which is index of the bugzilla - * in hashBugzillaWholeURL + * in this.constantData.bugzillaIDURLs * @param bugID Number which is bug ID * @return string with the URL */ RHBugzillaPage.prototype.getWholeURL = function(selectValue, bugID) { - var returnURL = ""; - if (hashBugzillaWholeURL[selectValue]) { - returnURL = hashBugzillaWholeURL[selectValue] + bugID; - } else { - returnURL = ""; - } - return returnURL; + let returnURL = ""; + if (this.constantData.bugzillaIDURLs[selectValue]) { + returnURL = this.constantData.bugzillaIDURLs[selectValue] + bugID; + } else { + returnURL = ""; + } + return returnURL; }; /** @@ -2061,9 +2155,9 @@ RHBugzillaPage.prototype.getWholeURL = function(selectValue, bugID) { * + responseText */ RHBugzillaPage.prototype.callBack = function(data, textStatus) { - if (--this.reqCounter <= 0) { - setTimeout(this.doc.location.reload, 1000); - } + if (--this.reqCounter <= 0) { + setTimeout(this.doc.location.reload, 1000); + } }; /** @@ -2089,51 +2183,43 @@ RHBugzillaPage.prototype.callBack = function(data, textStatus) { * */ RHBugzillaPage.prototype.fixAttachById = function(id, type, email) { - if (type === undefined) { - type = "text/plain"; - } - if (email === undefined) { - email = false; - } - - var msg = new XMLRPCMessage("bugzilla.updateAttachMimeType"); - console.log("XML-RPC before:\n"+msg.xml()) - msg.addParameter( { - 'attach_id' : id, - 'mime_type' : type, - 'nomail' : !email - }); - console.log("XML-RPC message:\n"+msg.xml()); - msg.addParameter(this.login); - console.log("XML-RPC message:\n"+msg.xml()); - msg.addParameter(this.password); - console.log("XML-RPC message:\n"+msg.xml()); - - var req = new XMLHttpRequest(); - var that = this; - req.open("POST", XMLRPCurl, true); - req.overrideMimeType("text/xml"); - req.setRequestHeader("Content-type", "text/xml"); - req.onreadystatechange = function(aEvt) { - if (req.readyState == 4) { - if (req.status == 200) { - console.log("Fixing attachment MIME type success!"); - that.callBack(); - } else { - console.error("Fixing MIME type attachment failed!"); - } - } - }; - req.send(msg.xml()); - this.reqCounter++; -}; - -// FIXME possibly eliminate this function altogether and -// make it inline? -RHBugzillaPage.prototype.fixAllAttachments = function(list) { - Array.forEach(list, function(x) { - this.fixAttachById(x[1]); - }, this); + if (type === undefined) { + type = "text/plain"; + } + if (email === undefined) { + email = false; + } + + let msg = new XMLRPCMessage("bugzilla.updateAttachMimeType"); + console.log("XML-RPC before:\n"+msg.xml()) + msg.addParameter( { + 'attach_id' : id, + 'mime_type' : type, + 'nomail' : !email + }); + console.log("XML-RPC message:\n"+msg.xml()); + msg.addParameter(this.login); + console.log("XML-RPC message:\n"+msg.xml()); + msg.addParameter(this.password); + console.log("XML-RPC message:\n"+msg.xml()); + + let req = new XMLHttpRequest(); + let that = this; + req.open("POST", XMLRPCurl, true); + req.overrideMimeType("text/xml"); + req.setRequestHeader("Content-type", "text/xml"); + req.onreadystatechange = function(aEvt) { + if (req.readyState == 4) { + if (req.status == 200) { + console.log("Fixing attachment MIME type success!"); + that.callBack(); + } else { + console.error("Fixing MIME type attachment failed!"); + } + } + }; + req.send(msg.xml()); + this.reqCounter++; }; /** @@ -2143,18 +2229,20 @@ RHBugzillaPage.prototype.fixAllAttachments = function(list) { * @return button fixing all bad Attachments */ RHBugzillaPage.prototype.createFixAllButton = function(list) { - if (!XMLRPCMessage) { - return; - } - var that = this; - var elem = this.doc.createElement("a"); - elem.setAttribute("href", ""); - elem.setAttribute("accesskey", "f"); - elem.innerHTML = "<b>F</b>ix all"; - elem.addEventListener("click", function() { - that.fixAllAttachments(list); - }, false); - return elem; + if (!XMLRPCMessage) { + return; + } + let that = this; + let elem = this.doc.createElement("a"); + elem.setAttribute("href", ""); + elem.setAttribute("accesskey", "f"); + elem.innerHTML = "<b>F</b>ix all"; + elem.addEventListener("click", function() { + Array.forEach(list, function(x) { + this.fixAttachById(x[1]); + }, that); + }, false); + return elem; }; /** @@ -2165,13 +2253,13 @@ RHBugzillaPage.prototype.createFixAllButton = function(list) { * @return none */ RHBugzillaPage.prototype.addTextLink = function(row) { - var that = this; - var elemS = row[4].getElementsByTagName("td"); - var elem = elemS[elemS.length - 1]; - elem.innerHTML += "<br/><a href=''>Text</a>"; - elem.addEventListener("click", function(x) { - that.fixAttachById(row[1], "text/plain"); - }, false); + let that = this; + let elemS = row[4].getElementsByTagName("td"); + let elem = elemS[elemS.length - 1]; + elem.innerHTML += "<br/><a href=''>Text</a>"; + elem.addEventListener("click", function(x) { + that.fixAttachById(row[1], "text/plain"); + }, false); }; /** @@ -2181,72 +2269,61 @@ RHBugzillaPage.prototype.addTextLink = function(row) { * @return none */ RHBugzillaPage.prototype.addClosingUpstream = function() { - var refs = this.doc.getElementById("external_bugs_table") - .getElementsByTagName("tr"); - // that's a bad id, if there is a one. :) - var inputBox = this.doc.getElementById("inputbox"); - var externalBugID = 0; - var wholeURL = ""; - - // Fix missing ID on the external_id SELECT - this.doc.getElementsByName("external_id")[0].setAttribute("id", - "external_id"); - - if (inputBox.value.match(/^http.*/)) { - var helpAElem = this.doc.createElement("a"); - wholeURL = inputBox.value; - helpAElem.setAttribute("href", wholeURL); - var paramsArr = helpAElem.search.replace(/^\?/, '').split('&'); - // get ID# - var params = {}, s = []; - paramsArr.forEach(function(par, idx, arr) { - s = par.split('='); - params[s[0]] = s[1]; - }); - if (params.id) { - externalBugID = parseInt(params.id, 10); - inputBox.value = externalBugID; - } - // get host and bugzillaName - var bugzillaName = this.getBugzillaName(helpAElem.hostname); - this.selectOption("external_id", bugzillaName); - } else if (!isNaN(inputBox.value)) { - externalBugID = parseInt(inputBox.value, 10); - var bugzillaID = this.doc.getElementById("external_id").value; - wholeURL = this.getWholeURL(bugzillaID, externalBugID); - } else { - // no inputBox.value -- maybe there is an external bug from - // the previous commit? - } - - // It is not good to close bug as UPSTREAM, if there is no reference - // to the upstream bug. - if ((externalBugID > 0) || (refs.length > 2)) { - this.addTextToTextBox("comment", msgStrs.sentUpstreamString.replace( - "§§§", wholeURL)); - this.selectOption("bug_status", "CLOSED"); - this.selectOption("resolution", "UPSTREAM"); - } else { - console.log("No external bug specified among the External References!"); - } -}; - -/** - * Insert a row of buttons before the marked element - * - * @param anchor Element before which the row of buttons will be inserted - * @param array Array of data for buttons to be generated - * @return none - */ -RHBugzillaPage.prototype.generateToolBar = function(anchor, array) { - for ( var i = 0; i < array.length; i++) { - var butt = array[i]; - this.addNewButton(anchor, butt.idx, butt.msg, butt.string, butt.state, - butt.parameter, butt.submit); - } + let refs = this.doc.getElementById("external_bugs_table") + .getElementsByTagName("tr"); + // that's a bad id, if there is a one. :) + let inputBox = this.doc.getElementById("inputbox"); + let externalBugID = 0; + let wholeURL = ""; + + // Fix missing ID on the external_id SELECT + this.doc.getElementsByName("external_id")[0].setAttribute("id", + "external_id"); + + if (inputBox.value.match(/^http.*/)) { + let helpAElem = this.doc.createElement("a"); + wholeURL = inputBox.value; + helpAElem.setAttribute("href", wholeURL); + let paramsArr = helpAElem.search.replace(/^\?/, '').split('&'); + // get ID# + let params = {}, s = []; + paramsArr.forEach(function(par, idx, arr) { + s = par.split('='); + params[s[0]] = s[1]; + }); + if (params.id) { + externalBugID = parseInt(params.id, 10); + inputBox.value = externalBugID; + } + // get host and bugzillaName + let bugzillaName = this.getBugzillaName(helpAElem.hostname); + this.selectOption("external_id", bugzillaName); + } else if (!isNaN(inputBox.value)) { + externalBugID = parseInt(inputBox.value, 10); + let bugzillaID = this.doc.getElementById("external_id").value; + wholeURL = this.getWholeURL(bugzillaID, externalBugID); + } else { + // no inputBox.value -- maybe there is an external bug from + // the previous commit? + } + + // FIXME THis is not good, we don't have a feedback for other commands, + // not to be run, if this fails. + + // It is not good to close bug as UPSTREAM, if there is no reference + // to the upstream bug. + if ((externalBugID > 0) || (refs.length > 2)) { + let msgStr = this.commentStrings["sentUpstreamString"]; + msgStr.replace( "§§§", wholeURL)); + this.centralCommandDispatch("comment",msgStr); + this.centralCommandDispatch("status", "CLOSED"); + this.centralCommandDispatch("resolution", "UPSTREAM"); + } else { + console.log("No external bug specified among the External References!"); + } }; -RHBugzillaPage.prototype.setBugAssigned = function(ver) { +RHBugzillaPage.prototype.markBugTriaged = function() { // Now we lie completely, we just set keyword Triaged, // this is not just plain ASSIGNED, but // modified according to @@ -2259,135 +2336,48 @@ RHBugzillaPage.prototype.setBugAssigned = function(ver) { // /fedora-meeting.2009-11-24-15.11.log.html // for F13 and later, ASSIGNED is "add Triaged keyword" (as well) // for <F13 it is "add both" (ASSIGNED status and Triaged keyword) + let ver = this.getVersion(); if (!hlpr.isInList(this.maintCCAddr, this.CCList)) { - this.doc.getElementById("newcc").textContent = this.maintCCAddr; + this.addToCCList(this.maintCCAddr); } if ((!this.isEnterprise()) && (ver < TriagedDistro)) { - this.selectOption("bug_status", "ASSIGNED"); + this.selectOption("bug_status", "ASSIGNED"); } - this.setKeyword("Triaged"); + this.addStuffToTextBox("keywords","Triaged"); } -RHBugzillaPage.prototype.closeSomeRelease = function(verNo) { - // for RAWHIDE close as RAWHIDE, - // if active selection -> CURRENTRELEASE - // and put the release version to - // "Fixed in Version" textbox - // otherwise -> NEXTRELEASE - this.selectOption("bug_status", "CLOSED"); - var text = ""; - if (jetpack.selection.text) { - text = jetpack.select.text.trim(); - } - if (text.length > 0) { - this.selectOption("resolution", "CURRENTRELEASE"); - this.doc.getElementById("cf_fixed_in").value = text; - } else if (verNo === 999) { - this.selectOption("resolution", "RAWHIDE"); - } else { - this.selectOption("resolution", "NEXTRELEASE"); - } -} - -/** - * Generalized function for all actions - * - * @param addString String to be added as new comment - * @param nextState String signifying next state of the bug (whatever is in Bugzilla + - * "NEEDINFO" meaning NEEDINFO(Reporter)) - * @param secondParameter String with label on the subbutton for reason of - * closing the bug - * @return none - */ -RHBugzillaPage.prototype.generalPurposeCureForAllDisease = function(addString, - nextState, secondParameter) { - var verNo = this.getVersion(); - - if (addString.length > 0) { - this.addTextToTextBox("comment", addString); - } - - if (nextState === "CLOSED") { - if (secondParameter === "UPSTREAM") { - this.addClosingUpstream(); - } else if (secondParameter === "SOMERELEASE") { - this.closeSomeRelease(verNo); - } else if (secondParameter.length > 0) { - this.selectOption("bug_status", nextState); - this.selectOption("resolution", secondParameter); - return 0; - } else { - throw "Missing resolution for CLOSED status."; - } - } - - // Now closing bugs is done, what about the rest? - if (nextState === "NEEDINFO") { - this.setNeedinfoReporter(); - } else if (nextState === "ADDKEYWORD") { - if (secondParameter.length === 0) { - throw "Keyword has to be defined"; - } - this.addKeyword(secondParameter); - } else if (nextState === "ASSIGNED") { - this.setBugAssigned(verNo); - } else if (nextState === "QUERYSEL") { - this.queryForSelection(); - } else if (nextState === "QUERYUP") { - this.queryUpstream(); - } else if (nextState === "SENDUPSTREAM") { - this.sendBugUpstream(); - } else if (nextState === "SETDEFASS") { - if (secondParameter.length > 0) { - this.changeOwner(secondParameter); - } - } else if (nextState === "CHIPMAGIC") { - var splitArr = secondParameter.split("\t"); - this.fillInWhiteBoard(splitArr[0], splitArr[1]); - } else if (nextState.length > 0) { - this.selectOption("bug_status", nextState); - } - - if (secondParameter === "ADDSELFCC") { - this.doc.getElementById("addselfcc").checked = true; - } else if (secondParameter === "NODEFAULTASSIGNEE") { - this.doc.getElementById("set_default_assignee").removeAttribute( - "checked"); - } -}; - /** * */ RHBugzillaPage.prototype.parseBacktrace = function(ret) { - var splitArray = ret.split("\n"); - var i = 0, ii = splitArray.length; - var outStr = "", curLine = "", numStr = ""; - var lineCounter = 0, endLineNo = 0; - - while (i < ii) { - if (signalHandlerRE.test(splitArray[i])) { - break; - } - i++; - } - - if (i < ii) { - lineCounter = parseInt(frameNoRE.exec(splitArray[i])[1], 10); - endLineNo = lineCounter + NumberOfFrames; - curLine = splitArray[i]; - while ((lineCounter < endLineNo) && (curLine.trim().length > 0) - && (i < ii)) { - outStr += curLine + '\n'; - numStr = frameNoRE.exec(curLine); - if (numStr) { - lineCounter = parseInt(numStr[1], 10); - } - i++; - curLine = splitArray[i]; - } - } - return outStr; + let splitArray = ret.split("\n"); + let i = 0, ii = splitArray.length; + let outStr = "", curLine = "", numStr = ""; + let lineCounter = 0, endLineNo = 0; + + while (i < ii) { + if (signalHandlerRE.test(splitArray[i])) { + break; + } + i++; + } + + if (i < ii) { + lineCounter = parseInt(frameNoRE.exec(splitArray[i])[1], 10); + endLineNo = lineCounter + NumberOfFrames; + curLine = splitArray[i]; + while ((lineCounter < endLineNo) && (curLine.trim().length > 0) + && (i < ii)) { + outStr += curLine + '\n'; + numStr = frameNoRE.exec(curLine); + if (numStr) { + lineCounter = parseInt(numStr[1], 10); + } + i++; + curLine = splitArray[i]; + } + } + return outStr; }; /** @@ -2396,138 +2386,107 @@ RHBugzillaPage.prototype.parseBacktrace = function(ret) { * XMLHttpRequest. * * @param jsonList Array created from JSON - * @return none + * @return none */ RHBugzillaPage.prototype.buildButtons = function(above, below) { - // Generate a list of <input> elements in the page - this.addNewButton(this.doc.getElementById("commit_middle"), - "changeOwnerbtn", "Mark Triaged", "", "ASSIGNED", - "NODEFAULTASSIGNEE"); - - // THE MAIN BUTTON ROWS - var commentBox = this.doc.getElementById("comment"); - var brElement = this.doc.createElement("br"); - commentBox.parentNode.normalize(); - commentBox.parentNode.insertBefore(brElement, commentBox); - // this.generateToolBar(commentBox.previousSibling,above); - this.generateToolBar(brElement, above); - this.generateToolBar(this.originalButton, below); - - var commentArea = this.doc.getElementById("comment_status_commit"); - var brElementPlacer = commentArea.getElementsByTagName("br")[0]; - - if (queryButtonAvailable || upstreamButtonAvailable) { - brElementPlacer.parentNode.insertBefore(this.doc.createElement("br"), - brElementPlacer); - } - - if (queryButtonAvailable) { - // Add query search button - this.addNewButton(brElementPlacer, "newqueryintab", "Query for string", - "", "QUERYSEL", "", false); - } - if (queryUpstreamBugsURLArray) { - console.log("Adding upstream query search box"); - if (this.filterByRegexp(queryUpstreamBugsURLArray, this.component)) { - this.addNewButton(brElementPlacer, "upstreamqueryintab", - "Query upstream", "", "QUERYUP", "", false); - } - } - // Button for upstreaming - if (upstreamButtonAvailable) { - this.addNewButton(brElementPlacer, "sendupstream", "Send upstream", "", - "SENDUPSTREAM", "", false); - } - - // TODO Get compiz bugs as well - if ((chipIDsGroupings.length > 0) - && this.maintCCAddr === "xgl-maint@redhat.com") { - // Add find chip magic button - var whiteboard_string = this.doc.getElementById("status_whiteboard").value; - if (!/card_/.test(whiteboard_string)) { - this.fillInChipMagic(); - } - } - - // Add setting default assignee - if ((this.defaultAssignee.length > 0) - && (this.defaultAssignee !== this.owner)) { - this.addNewButton( - this.doc.getElementById("bz_assignee_edit_container"), - "setdefaultassigneebutton", "Def. Assignee", "", "SETDEFASS", - this.defaultAssignee, false, true); - } + // FIXME REMAINS OF THIS FUNCTION SHOULD BE MOVED SOMEWHERE + // TODO Get compiz bugs as well + if ((chipIDsGroupings.length > 0) + && this.maintCCAddr === "xgl-maint@redhat.com") { + // Add find chip magic button + let whiteboard_string = this.doc.getElementById("status_whiteboard").value; + if (!/card_/.test(whiteboard_string)) { + this.fillInChipMagic(); + } + } }; RHBugzillaPage.prototype.addLogRecord = function() { - var rec = {}; - rec.date = new Date(); - rec.bugId = this.bugNo; - rec.title = this.title; - var comment = jetpack.tabs.focused.contentWindow.prompt( - "Enter comments for this comment").trim(); - if (comment.length > 0) { - rec.comment = comment; - var recKey = this.getISODate(rec.date) + "+" + rec.bugId; - var clearLogAElem = this.doc.getElementById("clearLogs"); - clearLogAElem.style.color = this.FullLogsColor; - clearLogAElem.style.fontWeight = "bolder"; - if (myStorage.logs[recKey]) { - myStorage.logs[recKey].comment += "<br/>\n" + comment; - } else { - myStorage.logs[recKey] = rec; - } - jetpack.storage.simple.sync(); - } else if (comment === null) { - return null; - } + let rec = {}; + rec.date = new Date(); + rec.bugId = this.bugNo; + rec.title = this.title; + let comment = jetpack.tabs.focused.contentWindow.prompt( + "Enter comments for this comment").trim(); + if (comment.length > 0) { + rec.comment = comment; + let recKey = this.getISODate(rec.date) + "+" + rec.bugId; + let clearLogAElem = this.doc.getElementById("clearLogs"); + clearLogAElem.style.color = this.FullLogsColor; + clearLogAElem.style.fontWeight = "bolder"; + if (myStorage.logs[recKey]) { + myStorage.logs[recKey].comment += "<br/>\n" + comment; + } else { + myStorage.logs[recKey] = rec; + } + jetpack.storage.simple.sync(); + } else if (comment === null) { + return null; + } }; RHBugzillaPage.prototype.timeSheetRecordsPrinter = function(body, records) { - var that = this; - // sort the records into temporary array - var tmpArr = []; - - for ( var i in records) { - if (records.hasOwnProperty(i)) { - tmpArr.push( [ i, records[i] ]); - } - } - tmpArr.sort(function(a, b) { - return a[0] > b[0] ? 1 : -1; - }); - - var currentDay = ""; - // now print the array - tmpArr - .forEach(function(rec) { - var x = rec[1]; - var dayStr = that.getISODate(x.date); - if (dayStr != currentDay) { - currentDay = dayStr; - body.innerHTML += "<hr/><p><strong>" + currentDay - + "</strong></p>"; - } - body.innerHTML += "<p><em><a href='https://bugzilla.redhat.com/show_bug.cgi?id=" - + x.bugId - + "'>Bug " - + x.title - + "</a>" - + " </em>\n<br/>" + x.comment + "</p>"; - }); + let that = this; + // sort the records into temporary array + let tmpArr = []; + + for ( let i in records) { + if (records.hasOwnProperty(i)) { + tmpArr.push( [ i, records[i] ]); + } + } + tmpArr.sort(function(a, b) { + return a[0] > b[0] ? 1 : -1; + }); + + let currentDay = ""; + // now print the array + tmpArr + .forEach(function(rec) { + let x = rec[1]; + let dayStr = that.getISODate(x.date); + if (dayStr != currentDay) { + currentDay = dayStr; + body.innerHTML += "<hr/><p><strong>" + currentDay + + "</strong></p>"; + } + body.innerHTML += "<p><em><a href='https://bugzilla.redhat.com/show_bug.cgi?id=" + + x.bugId + + "'>Bug " + + x.title + + "</a>" + + " </em>\n<br/>" + x.comment + "</p>"; + }); }; RHBugzillaPage.prototype.generateTimeSheet = function(body) { - var doc = body.ownerDocument; - this.timeSheetRecordsPrinter(body, myStorage.logs); + let doc = body.ownerDocument; + this.timeSheetRecordsPrinter(body, myStorage.logs); }; // ///////////////////////////////////////////////////////////////////////////// -var callback = function(doc) { - var curPage = new RHBugzillaPage(doc); +let callback = function(doc) { + if (config.gJSONData.configData.objectStyle = "RH") { + let curPage = new RHBugzillaPage(doc); + } else if (config.gJSONData.configData.objectStyle = "RH") { + let curPage = new MozillaBugzilla(doc); + } }; -var options = {}; -options.matches = [ "https://bugzilla.redhat.com/show_bug.cgi" ]; -jetpack.pageMods.add(callback, options); +let config = {}; +config.matches = [ + "https://bugzilla.redhat.com/show_bug.cgi", + "" +]; +hlpr.loadJSON(jetpack.storage.settings.JSONURL, function(parsedData) { + console.log("jsonDataURL = " + jetpack.storage.settings.JSONURL); + config.gJSONData = parsedData; +}); +// Get card translation table +if ("PCIIDsURL" in config.gJSONData.configData) { + hlpr.loadJSON(config.gJSONData.configData.PCIIDsURL, function(response) { + config.PCI_ID_Array = response; + }); +} +jetpack.pageMods.add(callback, config); |