diff options
Diffstat (limited to 'bugzillaBugTriage.js')
-rw-r--r-- | bugzillaBugTriage.js | 1172 |
1 files changed, 620 insertions, 552 deletions
diff --git a/bugzillaBugTriage.js b/bugzillaBugTriage.js index 56523c1..55d3dea 100644 --- a/bugzillaBugTriage.js +++ b/bugzillaBugTriage.js @@ -8,29 +8,6 @@ jetpack.future.import("storage.simple"); jetpack.future.import("selection"); jetpack.future.import("clipboard"); -// 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 -const -RHColor = new Color(158, 41, 43); // RGB 158, 41, 43; HSL 359, 1, 39 -const -FedoraColor = new Color(0, 40, 103); // RGB 0, 40, 103; HSL 359, 1, 39 -const -RawhideColor = new Color(0, 119, 0); // or "green", or RGB 0, 119, 0, or HSL -// 120, 0, 23 -const -RHITColor = new Color(102, 0, 102); // RGB 102, 0, 102; HSL 300, 0, 20 -const -SalmonPink = new Color(255, 224, 176); // RGB 255, 224, 176; HSL 36, 2, 85 -const -ReporterColor = new Color(255, 255, 166); // RGB 255, 255, 166; HSL 60, 2, 83 -const -EmptyLogsColor = new Color(0, 255, 0); -const -FullLogsColor = FedoraColor; - -var Luminosity = 0.85; -var Desaturated = 0.4; var TriagedDistro = 13; var NumberOfFrames = 7; var XMLRPCurl = "https://bugzilla.redhat.com/xmlrpc.cgi"; @@ -71,27 +48,13 @@ var msgStrs = {}; var CommentRe = new RegExp("^\\s*#"); var BlankLineRe = new RegExp("^\\s*$"); // nová řádka -// [ 65.631] (--) intel(0): Chipset: "845G" +// [ 65.631] (--) intel(0): Chipset: "845G" var ChipsetRE = new RegExp("^\\s*\\[?[ 0-9.]*\\]?\\s*\\(--\\) ([A-Za-z]+)\\([0-9]?\\): Chipset: (.*)$"); var ATIgetIDRE = new RegExp("^.*\\(ChipID = 0x([0-9a-fA-F]+)\\).*$"); 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"); -// For identification of graphics card -var manuChipStrs = [ [ "ATI Radeon", "ATI", "1002" ], - [ "ATI Mobility Radeon", "ATI", "1002" ], - [ "Intel Corporation", "INTEL", "8086" ], [ "NVIDIA", "NV", "10de" ] ]; -var backTranslateManufacturerPCIID = [ { - regexp : "ATI Technologies Inc", - addr : "1002" -}, { - regexp : "Intel Corporation", - addr : "8086" -}, { - regexp : "nVidia Corporation", - addr : "10de" -} ]; // Initialize data from remote URL var XMLHttpRequestDone = false; var hashBugzillaName = []; @@ -112,63 +75,6 @@ var PCI_ID_Array = []; var topRow = {}; var bottomRow = {}; -// Get JSON configuration data -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(""); -}; - -loadJSON = function(URL, cb_function, what) { - if (what === undefined) { // missing optional argument - what = this; - } - - loadText(URL, function(text) { - var data = JSON.parse(text); - cb_function.call(what, data); - }, what); -}; - -loadJSON(jsonDataURL, function(response) { - 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; - }); - -// Get card translation table -loadJSON(PCIIDsURL, function(response) { - PCI_ID_Array = response; -}); - // ======== load external library =============================== // var XMLRPCMessage = {}; @@ -253,7 +159,7 @@ XMLRPCMessage.prototype.xml = function() { return xml; // for now }; -XMLRPCMessage.dataTypeOf = function(o) { +XMLRPCMessage.prototype.dataTypeOf = function(o) { // identifies the data type var type = typeof (o); type = type.toLowerCase(); @@ -277,25 +183,44 @@ XMLRPCMessage.dataTypeOf = function(o) { return type; }; -XMLRPCMessage.doValueXML = function(type, data) { +XMLRPCMessage.prototype.doValueXML = function(type, data) { var xml = "<" + type + ">" + data + "</" + type + ">"; return xml; }; -XMLRPCMessage.doBooleanXML = function(data) { +XMLRPCMessage.prototype.doBooleanXML = function(data) { var value = (data == true) ? 1 : 0; var xml = "<boolean>" + value + "</boolean>"; return xml; }; -XMLRPCMessage.doDateXML = function(data) { +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; }; -XMLRPCMessage.doArrayXML = function(data) { +XMLRPCMessage.prototype.doArrayXML = function(data) { var xml = "<array><data>\n"; for ( var i = 0; i < data.length; i++) { xml += "<value>" @@ -306,7 +231,7 @@ XMLRPCMessage.doArrayXML = function(data) { return xml; }; -XMLRPCMessage.doStructXML = function(data) { +XMLRPCMessage.prototype.doStructXML = function(data) { var xml = "<struct>\n"; for ( var i in data) { xml += "<member>\n"; @@ -320,7 +245,7 @@ XMLRPCMessage.doStructXML = function(data) { return xml; }; -XMLRPCMessage.getParamXML = function(type, data) { +XMLRPCMessage.prototype.getParamXML = function(type, data) { var xml; switch (type) { case "date": @@ -342,85 +267,54 @@ XMLRPCMessage.getParamXML = function(type, data) { return xml; }; -function dateToISO8601(date) { - // wow I hate working with the Date object - var year = new String(date.getYear()); - var month = leadingZero(new String(date.getMonth())); - var day = leadingZero(new String(date.getDate())); - var time = leadingZero(new String(date.getHours())) + ":" - + leadingZero(new String(date.getMinutes())) + ":" - + leadingZero(new String(date.getSeconds())); - - var converted = year + month + day + "T" + time; - return converted; -} - -function leadingZero(n) { - // pads a single number with a leading zero. Heh. - if (n.length == 1) - n = "0" + n; - return n; -} - -// ============================================================== -/** - * format date to be in ISO format (just day part) +/* + * Create and return an object that has p as its prototype * - * @param date - * @return string with the formatted date + * @param p parent Object + * @return child Object */ -function getISODate(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()); +if (typeof Object.create !== 'function') { + Object.prototype.create = function () { + function F() {} + F.prototype = this; + return new F(); + }; } -/** - * select element of the array where regexp in the first element matches second - * parameter of this function - * - * @param list - * array with regexps and return values - * @param chosingMark - * string by which the element of array is to be matched - * @return string chosen element - */ -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 ""; - } +// ============================================================== +var hlpr = function () { }; -/** - * Converts attributes value of the given list of elements to the Javascript - * list. - * - * @param list - * array of elements - * @return array of values - */ -valuesToList = function(list) { - var outL = []; +hlpr.valToArray = function valToArray(val) { + let arr = []; + if (typeof val == "string") { + arr = [val]; + } else if (val instanceof Array) { + arr = val; + } + return arr; +}; - list.forEach(function(e, i, a) { - if (e.hasAttribute("value")) { - outL.push(e.getAttribute("value").trim()); - } - }); - return outL; +hlpr.addCSVValue = function addCSVValue(str, value) { + let parts = (str.trim().length > 0 ? str.split(",") : []); + if (parts.indexOf(value) < 0) { + parts.concat(hlpr.valToArray(value)); + } + return parts.join(","); }; +// FIXME rewrite so that it doesn't break Eclipse +//hlpr.removeCSVValue = function removeCSVValue(str, value) { +// let parts = (str.trim().length > 0 ? str.split(",") : []); +// for each (let val in hlpr.valToArray(value)) { +// let pos = parts.indexOf(val); +// if (pos > -1) { +// parts.splice(pos, 1); +// } +// } +// return parts.join(","); +//}; + /** * Check whether an item is member of the list. Idea is just to make long if * commands slightly more readable. @@ -431,11 +325,11 @@ valuesToList = function(list) { * list * @return position of the string in the list, or -1 if none found. */ -isInList = function(mbr, list) { +hlpr.isInList = function(mbr, list) { return (list.indexOf(mbr) !== -1); }; -function createBlankPage(ttl, bodyBuildCB) { +hlpr.createBlankPage = function (ttl, bodyBuildCB) { var title = ttl || "Yet another untitled page"; var that = this; @@ -447,7 +341,85 @@ function createBlankPage(ttl, bodyBuildCB) { bodyBuildCB.call(that, otherDoc.body); logTab.focus(); }); -} +}; + +//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(""); +}; + +/** + * Converts attributes value of the given list of elements to the Javascript + * list. + * + * @param list + * array of elements + * @return array of values + * @depreceated FIXME never used + */ +hlpr.valuesToList = function(list) { + var outL = []; + + list.forEach(function(e, i, a) { + if (e.hasAttribute("value")) { + outL.push(e.getAttribute("value").trim()); + } + }); + return outL; +}; + +// 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) { + 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; + }); + +// Get card translation table +hlpr.loadJSON(PCIIDsURL, function(response) { + PCI_ID_Array = response; +}); // ============================================================================ // Color management methods @@ -456,6 +428,9 @@ function createBlankPage(ttl, bodyBuildCB) { // /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]; @@ -687,14 +662,371 @@ Color.prototype.hsvToRgb = function(h, s, v) { Color.prototype.lightColor = function() { var hslArray = this.hsl(); var h = Number(hslArray[0]); - var s = Number(hslArray[1]) * Desaturated; - var l = Luminosity; + 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]); }; // ==================================================================================== -// BzPage's methods +// BZPage's methods + +function BZPage(doc) { + +} + +/** + * Select option with given label on the <SELECT> element with given id. + * + * Also execute change HTMLEvent, so that the form behaves accordingly. + * + * @param id + * @param label + * @return none + * + * FIXME bugzilla-comments version has this signature: + * selectOption = function selectOption(select, value) { + let doc = select[0].ownerDocument; + select.val(value); + */ +BZPage.prototype.selectOption = function(id, label) { + var sel = this.doc.getElementById(id); + var options = Array.filter(sel.getElementsByTagName("option"), function(x) { + return x.textContent.trim() == label; + }); + theOption = options.length ? options[0] : []; + if (theOption) { + theOption.selected = true; + var intEvent = this.doc.createEvent("HTMLEvents"); + intEvent.initEvent("change", true, true); + theOption.dispatchEvent(intEvent); + } +}; + +/** + * Send mouse click to the specified element + * + * @param element + * where to send mouseclick to + * @return None + * + * FIXME depreceated version from bugzilla-comments + hlpr.clickElement = function clickElement(element) { + let doc = element[0].ownerDocument; + ... + element[0].dispatchEvent(e); + */ +BZPage.prototype.clickMouse = function(target) { + 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); + target.dispatchEvent(localEvent); +}; + +/** + * select element of the array where regexp in the first element matches second + * parameter of this function + * + * @param list + * array with regexps and return values + * @param chosingMark + * string by which the element of array is to be matched + * @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 ""; + } +}; + +// ==================================================================================== +// MozillaBugzilla object + +function MozillaBugzilla() { + +} + +MozillaBugzilla.prototype = BZPage.prototype.create(); + +// ==================================================================================== +// RHBugzillaPage object + +function RHBugzillaPage(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 + 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, + // 83 + this.EmptyLogsColor = new Color(0, 255, 0); + this.FullLogsColor = this.FedoraColor; + // END OF CONSTANTS + + this.doc = doc; + var that = this; + this.originalButton = this.doc.getElementById("commit"); + + var loginArr = this.doc.querySelector("#header ul.links li:last-of-type").textContent + .split("\n"); + this.login = loginArr[loginArr.length - 1].trim(); + + if (myStorage.BZpassword) { + this.password = myStorage.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) { + this.password = password.value; + myStorage.BZpassword = this.password; + jetpack.storage.simple.sync(); + } + } + + 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() : ""; + this.CCList = Array.map(this.doc.getElementById("cc"), function(item) { + return item.value; + }); + // 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(); + + this.XorgLogAttList = []; + this.XorgLogAttListIndex = 0; + this.attachments = []; + this.reqCounter = 0; + var atts = this.doc.getElementById("attachment_table") + .getElementsByTagName("tr"); + for ( var i = 1, ii = atts.length - 1; i < ii; i++) { + this.attachments.push(this.parseAttachmentLine(atts[i])); + } + + var badAttachments = this.attachments.filter(function(att, idx, arr) { + return (hlpr.isInList(att[2], badMIMEArray)); + }); + + 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); + } + + // Dig out backtrace + this.btSnippet = ""; + + console.log("parseAbrtBacktraces = " + parseAbrtBacktraces); + if (parseAbrtBacktraces && AbrtRE.test(this.title)) { + + 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); + } + } + + // 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); + + // UI for the customization JSON URL + var additionalButtons = this.doc.getElementById("bugzilla-body") + .getElementsByClassName("related_actions")[0]; + var customJSONURLUI = this.doc.createElement("li"); + customJSONURLUI.innerHTML = "\u00A0-\u00A0<a href='#' id='customJSONbutton'>" + + "BugZap config</a>"; + additionalButtons.appendChild(customJSONURLUI); + this.doc.getElementById("customJSONbutton").addEventListener( + "click", + function() { + var newURL = jetpack.tabs.focused.contentWindow + .prompt("URL for your JSON customization file"); + if (newURL) { + myStorage.JSONURL = newURL; + jetpack.storage.simple.sync(); + jetpack.tabs.focused.contentWindow.location.reload(); + } + }, false); + + // 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); + + // logging all submits for timesheet + console.log("logSubmits = " + logSubmits); + if (logSubmits) { + 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) { + 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 = 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 = EmptyLogsColor; + clearLogAElem.style.fontWeight = "normal"; + } + } +} // END OF RHBugzillaPage CONSTRUCTOR + +RHBugzillaPage.prototype = BZPage.prototype.create(); + +/** + * format date to be in ISO format (just day part) + * + * @param date + * @return string with the formatted date + */ +RHBugzillaPage.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()); +}; /** * generalized hasKeyword ... search in the value of the box with given id @@ -705,9 +1037,9 @@ Color.prototype.lightColor = function() { * String to be searched for * @return Boolean found? */ -BzPage.prototype.idContainsWord = function(id, str) { +RHBugzillaPage.prototype.idContainsWord = function(id, str) { try { - var kwd = this.dok.getElementById(id).value; + 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; @@ -723,7 +1055,7 @@ BzPage.prototype.idContainsWord = function(id, str) { * string with the keyword * @return Boolean */ -BzPage.prototype.hasKeyword = function(str) { +RHBugzillaPage.prototype.hasKeyword = function(str) { return (this.idContainsWord('keywords', str)); }; @@ -734,14 +1066,14 @@ BzPage.prototype.hasKeyword = function(str) { * string with the keyword * @return none */ -BzPage.prototype.setKeyword = function(str) { +RHBugzillaPage.prototype.setKeyword = function(str) { this.addTextToTextBox('keywords', str); }; -BzPage.prototype.getOptionValue = function(id) { +RHBugzillaPage.prototype.getOptionValue = function(id) { // Some special bugs don't have version for example try { - return this.dok.getElementById(id).value; + return this.doc.getElementById(id).value; } catch (e) { console.error("Failed to find element with id = " + id); return "#NA"; @@ -767,7 +1099,7 @@ BzPage.prototype.getOptionValue = function(id) { * příliš jednoduché * http://www.innovation.ch/java/HTTPClient/emulating_forms.html - */ -BzPage.prototype.serializeForm = function(form) { +RHBugzillaPage.prototype.serializeForm = function(form) { var serialForm = { dataOut : "", name : form.name, @@ -775,7 +1107,7 @@ BzPage.prototype.serializeForm = function(form) { acceptCharset : form.acceptCharset, action : form.action, // TODO shouldn't we get a non-relative URL? enctype : form.enctype, - cookie : this.dok.cookie, + cookie : this.doc.cookie, autocomplete : form.getAttribute("autocomplete"), bugNo : this.bugNo }; @@ -828,7 +1160,7 @@ BzPage.prototype.serializeForm = function(form) { return serialForm; }; -BzPage.prototype.submitCallback = function(evt) { +RHBugzillaPage.prototype.submitCallback = function(evt) { console.log("Submit Callback!"); if (jetpack.__parent__.navigator.onLine) { var serForm = this @@ -848,7 +1180,7 @@ BzPage.prototype.submitCallback = function(evt) { /** * * - * Yes, this is correct, this is NOT method of bzPage! + * Yes, this is correct, this is NOT method of RHBugzillaPage! */ function onlineCallback() { function deserializeAndSend(formData) { @@ -908,8 +1240,8 @@ function onlineCallback() { * * @return string */ -BzPage.prototype.getReporter = function() { - return this.dok +RHBugzillaPage.prototype.getReporter = function() { + return this.doc .querySelector("#bz_show_bug_column_2 > table .vcard:first-of-type > a").textContent; }; @@ -919,7 +1251,7 @@ BzPage.prototype.getReporter = function() { * * @return string (integer for released Fedora, float for RHEL, rawhide) */ -BzPage.prototype.getVersion = function() { +RHBugzillaPage.prototype.getVersion = function() { var verStr = this.getOptionValue("version").toLowerCase(); var verNo = 0; if (/rawhide/.test(verStr)) { @@ -931,20 +1263,6 @@ BzPage.prototype.getVersion = function() { }; /** - * Send mouse click to the specified element - * - * @param element - * where to send mouseclick to - * @return None - */ -BzPage.prototype.clickMouse = function(target) { - var localEvent = this.dok.createEvent("MouseEvents"); - localEvent.initMouseEvent("click", true, true, this.dok.defaultView, 0, 0, - 0, 0, 0, false, false, false, false, 0, null); - target.dispatchEvent(localEvent); -}; - -/** * Add text to the text box (comment box or status whiteboard) * * @param id @@ -954,8 +1272,8 @@ BzPage.prototype.clickMouse = function(target) { * * @return none */ -BzPage.prototype.addTextToTextBox = function(id, string2BAdded) { - var textBox = this.dok.getElementById(id); +RHBugzillaPage.prototype.addTextToTextBox = function(id, string2BAdded) { + var textBox = this.doc.getElementById(id); var separator = ", "; if (textBox.tagName.toLowerCase() === "textarea") { separator = "\n\n"; @@ -983,12 +1301,12 @@ BzPage.prototype.addTextToTextBox = function(id, string2BAdded) { * * Checks for the existing keywords. */ -BzPage.prototype.addKeyword = function(str) { +RHBugzillaPage.prototype.addKeyword = function(str) { this.addTextToTextBox("keywords", str); }; -BzPage.prototype.commentsWalker = function(fce) { - var comments = this.dok.getElementById("comments").getElementsByClassName( +RHBugzillaPage.prototype.commentsWalker = function(fce) { + var comments = this.doc.getElementById("comments").getElementsByClassName( "bz_comment"); Array.forEach(comments, function(item) { fce(item); @@ -999,18 +1317,18 @@ BzPage.prototype.commentsWalker = function(fce) { * Set background color of all comments made by reporter in ReporterColor color * */ -BzPage.prototype.checkComments = function() { +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 = ReporterColor.toString(); + x.style.backgroundColor = that.ReporterColor.toString(); } }); }; -BzPage.prototype.collectComments = function() { +RHBugzillaPage.prototype.collectComments = function() { var outStr = ""; this.commentsWalker(function(x) { outStr += x.getElementsByTagName("pre")[0].textContent + "\n"; @@ -1023,7 +1341,7 @@ BzPage.prototype.collectComments = function() { * * @return Boolean true if it is a RHEL bug */ -BzPage.prototype.isRHEL = function() { +RHBugzillaPage.prototype.isRHEL = function() { return (/Red Hat Enterprise Linux/).test(this.product); }; @@ -1032,10 +1350,10 @@ BzPage.prototype.isRHEL = function() { * * @return Boolean whether the bug has been triaged or not */ -BzPage.prototype.isTriaged = function() { +RHBugzillaPage.prototype.isTriaged = function() { // First excceptions if (this.version > 7 && this.version < 13) { - return this.dok.getElementById("bug_status").value.toUpperCase() !== "NEW"; + return this.doc.getElementById("bug_status").value.toUpperCase() !== "NEW"; } else { // and then the rule return this.hasKeyword("Triaged"); } @@ -1053,56 +1371,56 @@ BzPage.prototype.isTriaged = function() { * @return none * */ -BzPage.prototype.setBranding = function() { +RHBugzillaPage.prototype.setBranding = function() { var brandColor = {}; var TriagedColor = {}; if (this.isRHEL()) { if (this.its && (this.its.length > 0)) { - brandColor = RHITColor; + brandColor = this.RHITColor; } else { - brandColor = RHColor; + brandColor = this.RHColor; } } else if (new RegExp("Fedora").test(this.product)) { if (this.version == 999) { - brandColor = RawhideColor; + brandColor = this.RawhideColor; } else { - brandColor = FedoraColor; + brandColor = this.FedoraColor; } } // Comment each of the following lines to get only partial branding - this.dok.getElementsByTagName("body")[0].style.background = brandColor + this.doc.getElementsByTagName("body")[0].style.background = brandColor .toString() + " none"; - this.dok.getElementById("titles").style.background = brandColor.toString() + 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.dok.getElementsByTagName("title")[0]; + var titleElem = this.doc.getElementsByTagName("title")[0]; titleElem.textContent = titleElem.textContent.slice(4); - var bodyTitleParent = this.dok.getElementById("summary_alias_container").parentNode; + 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.dok.getElementById("bugzilla-body").style.background = SalmonPink + this.doc.getElementById("bugzilla-body").style.background = SalmonPink .toString() + ' none'; } // Make it visible whether the bug has been triaged if (this.isTriaged()) { - this.dok.getElementById("bz_field_status").style.background = brandColor + this.doc.getElementById("bz_field_status").style.background = brandColor .lightColor().toString() + " none"; } // we should make visible whether maintCCAddr is in CCList - if (isInList(this.maintCCAddr, this.CCList)) { - var ccEditBoxElem = this.dok.getElementById("cc_edit_area_showhide"); + 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"; @@ -1112,8 +1430,8 @@ BzPage.prototype.setBranding = function() { // mark suspicious components var compElems; if (suspiciousComponents - && isInList(this.component, suspiciousComponents) - && (compElems = this.dok + && hlpr.isInList(this.component, suspiciousComponents) + && (compElems = this.doc .getElementById("bz_component_edit_container"))) { compElems.style.background = "red none"; } @@ -1129,9 +1447,11 @@ BzPage.prototype.setBranding = function() { * string with the driver name * @return None */ -BzPage.prototype.fillInWhiteBoard = function(iLine, driverStr) { +RHBugzillaPage.prototype.fillInWhiteBoard = function(iLine, driverStr) { + var that = this; + function groupIDs(manStr, cardStrID) { - var outStr = filterByRegexp(chipIDsGroupings, manStr + "," + cardStrID); + var outStr = that.filterByRegexp(chipIDsGroupings, manStr + "," + cardStrID); if (outStr.length === 0) { outStr = "UNGROUPED_" + manStr + "/" + cardStrID; } @@ -1201,7 +1521,7 @@ BzPage.prototype.fillInWhiteBoard = function(iLine, driverStr) { } } this.addTextToTextBox("status_whiteboard", ("card_" + outStr).trim()); - this.dok.getElementById("chipmagic").style.display = "none"; + this.doc.getElementById("chipmagic").style.display = "none"; }; /** @@ -1228,7 +1548,7 @@ BzPage.prototype.fillInWhiteBoard = function(iLine, driverStr) { * * @return none */ -BzPage.prototype.addNewButton = function(originalLocation, newId, newLabel, +RHBugzillaPage.prototype.addNewButton = function(originalLocation, newId, newLabel, commentString, nState, secPar, doSubmit, after) { var that = this; var commStr = ""; @@ -1241,7 +1561,7 @@ BzPage.prototype.addNewButton = function(originalLocation, newId, newLabel, if (msgStrs[commentString]) { commStr = msgStrs[commentString]; } - var newButton = this.dok.createElement("input"); + var newButton = this.doc.createElement("input"); newButton.setAttribute("id", newId); if (doSubmit) { newButton.setAttribute("type", "submit"); @@ -1256,11 +1576,11 @@ BzPage.prototype.addNewButton = function(originalLocation, newId, newLabel, if (after) { originalLocation.parentNode.insertBefore(newButton, originalLocation.nextSibling); - originalLocation.parentNode.insertBefore(this.dok + originalLocation.parentNode.insertBefore(this.doc .createTextNode("\u00A0"), newButton); } else { originalLocation.parentNode.insertBefore(newButton, originalLocation); - originalLocation.parentNode.insertBefore(this.dok + originalLocation.parentNode.insertBefore(this.doc .createTextNode("\u00A0"), originalLocation); } }; @@ -1272,7 +1592,7 @@ BzPage.prototype.addNewButton = function(originalLocation, newId, newLabel, * * @return None */ -BzPage.prototype.fillInChipMagic = function () { +RHBugzillaPage.prototype.fillInChipMagic = function () { var XorgLogURL = ""; var XorgLogAttID = ""; var XorgLogFound = false; @@ -1337,7 +1657,7 @@ BzPage.prototype.fillInChipMagic = function () { * @return None * */ -BzPage.prototype.queryInNewTab = function(text, component, product) { +RHBugzillaPage.prototype.queryInNewTab = function(text, component, product) { // Optional parameter if (product === undefined) { product = this.product; @@ -1380,7 +1700,7 @@ BzPage.prototype.queryInNewTab = function(text, component, product) { * Get the text to search for and prepare other things for the real executive * function this.queryInNewTab, and run it. */ -BzPage.prototype.queryForSelection = function() { +RHBugzillaPage.prototype.queryForSelection = function() { var text = jetpack.selection.text; if (!text) { text = jetpack.clipboard.get(); @@ -1393,14 +1713,14 @@ BzPage.prototype.queryForSelection = function() { /** * Search simple query in the upstream bugzilla appropriate for the component. */ -BzPage.prototype.queryUpstream = function() { +RHBugzillaPage.prototype.queryUpstream = function() { var text = jetpack.selection.text; if (!text) { text = jetpack.clipboard.get(); } if (text) { var text = encodeURIComponent(text.trim()); - var url = filterByRegexp(queryUpstreamBugsURLArray, this.component); + var url = this.filterByRegexp(queryUpstreamBugsURLArray, this.component); jetpack.tabs.open(url + text); } } @@ -1408,8 +1728,8 @@ BzPage.prototype.queryUpstream = function() { /** * */ -BzPage.prototype.sendBugUpstream = function() { - var url = filterByRegexp(newUpstreamBugsURLArray, this +RHBugzillaPage.prototype.sendBugUpstream = function() { + var url = this.filterByRegexp(newUpstreamBugsURLArray, this .getOptionValue("component")); var ret = jetpack.tabs.open(url); @@ -1434,7 +1754,7 @@ BzPage.prototype.sendBugUpstream = function() { * string of MIME type, integer of size in kilobytes, and the whole * element itself */ -BzPage.prototype.parseAttachmentLine = function(inElem) { +RHBugzillaPage.prototype.parseAttachmentLine = function(inElem) { var MIMEtype = ""; var size = 0; @@ -1463,29 +1783,6 @@ BzPage.prototype.parseAttachmentLine = function(inElem) { }; /** - * Select option with given label on the <SELECT> element with given id. - * - * Also execute change HTMLEvent, so that the form behaves accordingly. - * - * @param id - * @param label - * @return none - */ -BzPage.prototype.selectOption = function(id, label) { - var sel = this.dok.getElementById(id); - var options = Array.filter(sel.getElementsByTagName("option"), function(x) { - return x.textContent.trim() == label; - }); - theOption = options.length ? options[0] : []; - if (theOption) { - theOption.selected = true; - var intEvent = this.dok.createEvent("HTMLEvents"); - intEvent.initEvent("change", true, true); - theOption.dispatchEvent(intEvent); - } -}; - -/** * Check for the presence of a keyword * * @param str @@ -1493,8 +1790,8 @@ BzPage.prototype.selectOption = function(id, label) { * @return Boolean * */ -BzPage.prototype.hasKeyword = function(str) { - var kwd = this.dok.getElementById('keywords').value.trim(); +RHBugzillaPage.prototype.hasKeyword = function(str) { + var kwd = this.doc.getElementById('keywords').value.trim(); return (new RegExp(str).test(kwd)); }; @@ -1512,7 +1809,7 @@ BzPage.prototype.hasKeyword = function(str) { * @return modified element with the fixed accesskey FIXME isn't this closure * and possible memleak? */ -BzPage.prototype.fixElement = function(elem, beforeText, accKey, afterText) { +RHBugzillaPage.prototype.fixElement = function(elem, beforeText, accKey, afterText) { elem.setAttribute("accesskey", accKey.toLowerCase()); elem.innerHTML = beforeText + "<b><u>" + accKey + "</u></b>" + afterText; return elem; @@ -1525,20 +1822,20 @@ BzPage.prototype.fixElement = function(elem, beforeText, accKey, afterText) { * event which made this function active * @return none */ -BzPage.prototype.changeOwner = function(newAssignee) { +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 (!isInList(newAssignee, this.CCList)) { - this.dok.getElementById("newcc").textContent = newAssignee; + if (!hlpr.isInList(newAssignee, this.CCList)) { + this.doc.getElementById("newcc").textContent = newAssignee; } if (newAssignee) { - this.clickMouse(this.dok.getElementById("bz_assignee_edit_action")); - this.dok.getElementById("assigned_to").value = newAssignee; - this.dok.getElementById("set_default_assignee").checked = false; - if (defAssigneeButton = this.dok + this.clickMouse(this.doc.getElementById("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"; } @@ -1552,8 +1849,8 @@ BzPage.prototype.changeOwner = function(newAssignee) { * * @return none */ -BzPage.prototype.setNeedinfoReporter = function() { - this.clickMouse(this.dok.getElementById("needinfo")); +RHBugzillaPage.prototype.setNeedinfoReporter = function() { + this.clickMouse(this.doc.getElementById("needinfo")); this.selectOption("needinfo_role", "reporter"); }; @@ -1564,7 +1861,7 @@ BzPage.prototype.setNeedinfoReporter = function() { * string hostname of the external bugzilla * @return string with the string for the external_id SELECT */ -BzPage.prototype.getBugzillaName = function(URLhostname) { +RHBugzillaPage.prototype.getBugzillaName = function(URLhostname) { var bugzillaID = ""; if (hashBugzillaName[URLhostname]) { bugzillaID = hashBugzillaName[URLhostname]; @@ -1583,7 +1880,7 @@ BzPage.prototype.getBugzillaName = function(URLhostname) { * Number which is bug ID * @return string with the URL */ -BzPage.prototype.getWholeURL = function(selectValue, bugID) { +RHBugzillaPage.prototype.getWholeURL = function(selectValue, bugID) { var returnURL = ""; if (hashBugzillaWholeURL[selectValue]) { returnURL = hashBugzillaWholeURL[selectValue] + bugID; @@ -1600,9 +1897,9 @@ BzPage.prototype.getWholeURL = function(selectValue, bugID) { * object with xmlhttprequest response with attributes: + status -- * int return code + statusText + responseHeaders + responseText */ -BzPage.prototype.callBack = function(data, textStatus) { +RHBugzillaPage.prototype.callBack = function(data, textStatus) { if (--this.reqCounter <= 0) { - setTimeout(this.dok.location.reload, 1000); + setTimeout(this.doc.location.reload, 1000); } }; @@ -1631,7 +1928,7 @@ BzPage.prototype.callBack = function(data, textStatus) { * this change }; * */ -BzPage.prototype.fixAttachById = function(id, type, email) { +RHBugzillaPage.prototype.fixAttachById = function(id, type, email) { if (type === undefined) { type = "text/plain"; } @@ -1669,7 +1966,7 @@ BzPage.prototype.fixAttachById = function(id, type, email) { // FIXME possibly eliminate this function altogether and // make it inline? -BzPage.prototype.fixAllAttachments = function(list) { +RHBugzillaPage.prototype.fixAllAttachments = function(list) { Array.forEach(list, function(x) { this.fixAttachById(x[1]); }, this); @@ -1682,12 +1979,12 @@ BzPage.prototype.fixAllAttachments = function(list) { * Array of all bad attachmentss * @return button fixing all bad Attachments */ -BzPage.prototype.createFixAllButton = function(list) { +RHBugzillaPage.prototype.createFixAllButton = function(list) { if (!XMLRPCMessage) { return; } var that = this; - var elem = this.dok.createElement("a"); + var elem = this.doc.createElement("a"); elem.setAttribute("href", ""); elem.setAttribute("accesskey", "f"); elem.innerHTML = "<b>F</b>ix all"; @@ -1704,7 +2001,7 @@ BzPage.prototype.createFixAllButton = function(list) { * <TR> DOM jQuery element with a bad attachment * @return none */ -BzPage.prototype.addTextLink = function(row) { +RHBugzillaPage.prototype.addTextLink = function(row) { var that = this; var elemS = row[4].getElementsByTagName("td"); var elem = elemS[elemS.length - 1]; @@ -1722,20 +2019,20 @@ BzPage.prototype.addTextLink = function(row) { * * @return none */ -BzPage.prototype.addClosingUpstream = function() { - var refs = this.dok.getElementById("external_bugs_table") +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.dok.getElementById("inputbox"); + var inputBox = this.doc.getElementById("inputbox"); var externalBugID = 0; var wholeURL = ""; // Fix missing ID on the external_id SELECT - this.dok.getElementsByName("external_id")[0].setAttribute("id", + this.doc.getElementsByName("external_id")[0].setAttribute("id", "external_id"); if (inputBox.value.match(/^http.*/)) { - var helpAElem = this.dok.createElement("a"); + var helpAElem = this.doc.createElement("a"); wholeURL = inputBox.value; helpAElem.setAttribute("href", wholeURL); var paramsArr = helpAElem.search.replace(/^\?/, '').split('&'); @@ -1754,7 +2051,7 @@ BzPage.prototype.addClosingUpstream = function() { this.selectOption("external_id", bugzillaName); } else if (!isNaN(inputBox.value)) { externalBugID = parseInt(inputBox.value, 10); - var bugzillaID = this.dok.getElementById("external_id").value; + var bugzillaID = this.doc.getElementById("external_id").value; wholeURL = this.getWholeURL(bugzillaID, externalBugID); } else { // no inputBox.value -- maybe there is an external bug from @@ -1782,7 +2079,7 @@ BzPage.prototype.addClosingUpstream = function() { * array of data for buttons to be generated * @return none */ -BzPage.prototype.generateToolBar = function(anchor, array) { +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, @@ -1802,7 +2099,7 @@ BzPage.prototype.generateToolBar = function(anchor, array) { * string with label on the subbutton for reason of closing the bug * @return none */ -BzPage.prototype.generalPurposeCureForAllDisease = function(addString, +RHBugzillaPage.prototype.generalPurposeCureForAllDisease = function(addString, nextState, secondParameter) { var verNo = this.getVersion(); @@ -1826,7 +2123,7 @@ BzPage.prototype.generalPurposeCureForAllDisease = function(addString, } if (text.length > 0) { this.selectOption("resolution", "CURRENTRELEASE"); - this.dok.getElementById("cf_fixed_in").value = text; + this.doc.getElementById("cf_fixed_in").value = text; } else if (verNo === 999) { this.selectOption("resolution", "RAWHIDE"); } else { @@ -1862,8 +2159,8 @@ BzPage.prototype.generalPurposeCureForAllDisease = function(addString, // /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) - if (!isInList(this.maintCCAddr, this.CCList)) { - this.dok.getElementById("newcc").textContent = this.maintCCAddr; + if (!hlpr.isInList(this.maintCCAddr, this.CCList)) { + this.doc.getElementById("newcc").textContent = this.maintCCAddr; } if ((!this.isRHEL()) && (verNo < TriagedDistro)) { this.selectOption("bug_status", nextState); @@ -1887,9 +2184,9 @@ BzPage.prototype.generalPurposeCureForAllDisease = function(addString, } if (secondParameter === "ADDSELFCC") { - this.dok.getElementById("addselfcc").checked = true; + this.doc.getElementById("addselfcc").checked = true; } else if (secondParameter === "NODEFAULTASSIGNEE") { - this.dok.getElementById("set_default_assignee").removeAttribute( + this.doc.getElementById("set_default_assignee").removeAttribute( "checked"); } }; @@ -1897,7 +2194,7 @@ BzPage.prototype.generalPurposeCureForAllDisease = function(addString, /** * */ -BzPage.prototype.parseBacktrace = function(ret) { +RHBugzillaPage.prototype.parseBacktrace = function(ret) { var splitArray = ret.split("\n"); var i = 0, ii = splitArray.length; var outStr = "", curLine = "", numStr = ""; @@ -1937,26 +2234,26 @@ BzPage.prototype.parseBacktrace = function(ret) { * Array created from JSON * @return none */ -BzPage.prototype.buildButtons = function(above, below) { +RHBugzillaPage.prototype.buildButtons = function(above, below) { // Generate a list of <input> elements in the page - this.addNewButton(this.dok.getElementById("commit_middle"), + this.addNewButton(this.doc.getElementById("commit_middle"), "changeOwnerbtn", "Mark Triaged", "", "ASSIGNED", "NODEFAULTASSIGNEE"); // THE MAIN BUTTON ROWS - var commentBox = this.dok.getElementById("comment"); - var brElement = this.dok.createElement("br"); + 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.dok.getElementById("comment_status_commit"); + var commentArea = this.doc.getElementById("comment_status_commit"); var brElementPlacer = commentArea.getElementsByTagName("br")[0]; if (queryButtonAvailable || upstreamButtonAvailable) { - brElementPlacer.parentNode.insertBefore(this.dok.createElement("br"), + brElementPlacer.parentNode.insertBefore(this.doc.createElement("br"), brElementPlacer); } @@ -1967,7 +2264,7 @@ BzPage.prototype.buildButtons = function(above, below) { } if (queryUpstreamBugsURLArray) { console.log("Adding upstream query search box"); - if (filterByRegexp(queryUpstreamBugsURLArray, this.component)) { + if (this.filterByRegexp(queryUpstreamBugsURLArray, this.component)) { this.addNewButton(brElementPlacer, "upstreamqueryintab", "Query upstream", "", "QUERYUP", "", false); } @@ -1978,9 +2275,9 @@ BzPage.prototype.buildButtons = function(above, below) { "SENDUPSTREAM", "", false); } - // var brElement2BMoved = this.dok.querySelector("#comment_status_commit + // var brElement2BMoved = this.doc.querySelector("#comment_status_commit // br:last-of-type"); - // var brWhereMove = this.dok.getElementsByClassName("status")[0]; + // var brWhereMove = this.doc.getElementsByClassName("status")[0]; // brWhereMove.parentNode.insertBefore(brElement2BMoved.cloneNode(true), // brWhereMove); // brElement2BMoved.parentNode.removeChild(brElement2BMoved); @@ -1989,7 +2286,7 @@ BzPage.prototype.buildButtons = function(above, below) { if ((chipIDsGroupings.length > 0) && this.maintCCAddr === "xgl-maint@redhat.com") { // Add find chip magic button - var whiteboard_string = this.dok.getElementById("status_whiteboard").value; + var whiteboard_string = this.doc.getElementById("status_whiteboard").value; if (!/card_/.test(whiteboard_string)) { this.fillInChipMagic(); } @@ -1999,13 +2296,13 @@ BzPage.prototype.buildButtons = function(above, below) { if ((this.defaultAssignee.length > 0) && (this.defaultAssignee !== this.owner)) { this.addNewButton( - this.dok.getElementById("bz_assignee_edit_container"), + this.doc.getElementById("bz_assignee_edit_container"), "setdefaultassigneebutton", "Def. Assignee", "", "SETDEFASS", this.defaultAssignee, false, true); } }; -BzPage.prototype.addLogRecord = function() { +RHBugzillaPage.prototype.addLogRecord = function() { var rec = {}; rec.date = new Date(); rec.bugId = this.bugNo; @@ -2014,9 +2311,9 @@ BzPage.prototype.addLogRecord = function() { "Enter comments for this comment").trim(); if (comment.length > 0) { rec.comment = comment; - var recKey = getISODate(rec.date) + "+" + rec.bugId; - var clearLogAElem = this.dok.getElementById("clearLogs"); - clearLogAElem.style.color = FullLogsColor; + 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; @@ -2029,7 +2326,7 @@ BzPage.prototype.addLogRecord = function() { } }; -BzPage.prototype.timeSheetRecordsPrinter = function(body, records) { +RHBugzillaPage.prototype.timeSheetRecordsPrinter = function(body, records) { // sort the records into temporary array var tmpArr = []; @@ -2047,7 +2344,7 @@ BzPage.prototype.timeSheetRecordsPrinter = function(body, records) { tmpArr .forEach(function(rec) { var x = rec[1]; - var dayStr = getISODate(x.date); + var dayStr = this.getISODate(x.date); if (dayStr != currentDay) { currentDay = dayStr; body.innerHTML += "<hr/><p><strong>" + currentDay @@ -2062,244 +2359,15 @@ BzPage.prototype.timeSheetRecordsPrinter = function(body, records) { }); }; -BzPage.prototype.generateTimeSheet = function(body) { +RHBugzillaPage.prototype.generateTimeSheet = function(body) { var doc = body.ownerDocument; this.timeSheetRecordsPrinter(body, myStorage.logs); }; // ///////////////////////////////////////////////////////////////////////////// -function BzPage(doc) { - this.dok = doc; - var that = this; - this.originalButton = this.dok.getElementById("commit"); - - var loginArr = this.dok.querySelector("#header ul.links li:last-of-type").textContent - .split("\n"); - this.login = loginArr[loginArr.length - 1].trim(); - - if (myStorage.BZpassword) { - this.password = myStorage.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) { - this.password = password.value; - myStorage.BZpassword = this.password; - jetpack.storage.simple.sync(); - } - } - - var bugNoTitle = this.dok.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.dok.getElementById("short_desc_nonedit_display").textContent; - var ITbutton = this.dok.getElementById("cf_issuetracker"); - this.its = ITbutton ? ITbutton.value.trim() : ""; - this.CCList = Array.map(this.dok.getElementById("cc"), function(item) { - return item.value; - }); - // TODO be careful about this, seems breaking for non-RH BugZappers, - // but I cannot see why - this.owner = this.dok.getElementById("bz_assignee_edit_container") - .getElementsByClassName("fn")[0].textContent; - this.defaultAssignee = filterByRegexp(defAssigneeList, this.component) - .toLowerCase(); - this.maintCCAddr = filterByRegexp(AddrArray, this.component).toLowerCase(); - - this.XorgLogAttList = []; - this.XorgLogAttListIndex = 0; - this.attachments = []; - this.reqCounter = 0; - var atts = this.dok.getElementById("attachment_table") - .getElementsByTagName("tr"); - for ( var i = 1, ii = atts.length - 1; i < ii; i++) { - this.attachments.push(this.parseAttachmentLine(atts[i])); - } - - var badAttachments = this.attachments.filter(function(att, idx, arr) { - return (isInList(att[2], badMIMEArray)); - }); - - if (badAttachments.length > 0) { - var titleElement = this.dok - .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); - } - - // Dig out backtrace - this.btSnippet = ""; - - console.log("parseAbrtBacktraces = " + parseAbrtBacktraces); - if (parseAbrtBacktraces && AbrtRE.test(this.title)) { - - var notedLabel = this.dok.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.dok - .getElementsByClassName("bz_alias_short_desc_container")[0]; - var abrtButton = this.dok.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 = loadText(attURL, function(ret) { - this.btSnippet = this.parseBacktrace(ret); - if (this.btSnippet) { - this.addTextToTextBox("comment", this.btSnippet); - this.addTextToTextBox("status_whiteboard", - "btparsed"); - } - }, this); - } - }, this); - } - } - - // Take care of signature for Fedora bugzappers - if (signatureFedoraString.length > 0) { - this.dok.forms.namedItem("changeform").addEventListener("submit", - function() { - that.addTextToTextBox("comment", signatureFedoraString); - }, false); - } - - this.setBranding(); - this.checkComments(); - this.buildButtons(topRow, bottomRow); - - // UI for the customization JSON URL - var additionalButtons = this.dok.getElementById("bugzilla-body") - .getElementsByClassName("related_actions")[0]; - var customJSONURLUI = this.dok.createElement("li"); - customJSONURLUI.innerHTML = "\u00A0-\u00A0<a href='#' id='customJSONbutton'>" - + "BugZap config</a>"; - additionalButtons.appendChild(customJSONURLUI); - this.dok.getElementById("customJSONbutton").addEventListener( - "click", - function() { - var newURL = jetpack.tabs.focused.contentWindow - .prompt("URL for your JSON customization file"); - if (newURL) { - myStorage.JSONURL = newURL; - jetpack.storage.simple.sync(); - jetpack.tabs.focused.contentWindow.location.reload(); - } - }, false); - - // set default assignee on change of the component - this.dok.getElementById("component").addEventListener( - "change", - function() { - that.component = that.getOptionValue("component"); - that - .changeOwner(filterByRegexp(defAssigneeList, - that.component).toLowerCase()); - }, false); - - // offline-capable submit - this.dok.forms.namedItem("changeform").addEventListener('submit', - function(evt) { - that.submitCallback.call(that, evt); - }, false); - - // logging all submits for timesheet - console.log("logSubmits = " + logSubmits); - if (logSubmits) { - this.dok.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.dok.createElement("li"); - generateTimeSheetUI.innerHTML = "\u00A0-\u00A0<a href='#' id='generateTSButton'>" - + "Generate timesheet</a>"; - additionalButtons.appendChild(generateTimeSheetUI); - this.dok.getElementById("generateTSButton").addEventListener( - "click", - function(evt) { - createBlankPage.call(that, "TimeSheet", - that.generateTimeSheet); - evt.stopPropagation(); - evt.preventDefault(); - }, false); - - var clearLogsUI = this.dok.createElement("li"); - clearLogsUI.innerHTML = "\u00A0-\u00A0<a href='#' id='clearLogs'>" - + "Clear logs</a>"; - additionalButtons.appendChild(clearLogsUI); - var clearLogAElem = this.dok.getElementById("clearLogs"); - clearLogAElem.addEventListener("click", function() { - myStorage.logs = {}; - jetpack.storage.simple.sync(); - this.style.color = 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 = FullLogsColor; - clearLogAElem.style.fontWeight = "bolder"; - } else { - clearLogAElem.style.color = EmptyLogsColor; - clearLogAElem.style.fontWeight = "normal"; - } - } -} var callback = function(doc) { - var curPage = new BzPage(doc); + var curPage = new RHBugzillaPage(doc); }; var options = {}; |