/*jslint onevar: false, browser: true, evil: true, laxbreak: true, undef: true, nomen: true, eqeqeq: true, bitwise: true, maxerr: 100, immed: false, white: false, plusplus: false, regexp: false, undef: false */ /*global jQuery, $, jetpack */ // Released under the MIT/X11 license // http://www.opensource.org/licenses/mit-license.php jetpack.future.import("pageMods"); 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 var RHColor = new Color(158, 41, 43); // RGB 158, 41, 43; HSL 359, 1, 39 var FedoraColor = new Color(0, 40, 103); // RGB 0, 40, 103; HSL 359, 1, 39 var RawhideColor = new Color(0, 119, 0); // or "green", or RGB 0, 119, 0, or HSL 120, 0, 23 var RHITColor = new Color(102, 0, 102); // RGB 102, 0, 102; HSL 300, 0, 20 var SalmonPink = new Color(255, 224, 176); // RGB 255, 224, 176; HSL 36, 2, 85 var ReporterColor = new Color(255, 255, 166); // RGB 255, 255, 166; HSL 60, 2, 83 var Luminosity = 0.85; var Desaturated = 0.4; var TriagedDistro = 13; var NumberOfFrames = 7; var XMLRPCurl = "https://bugzilla.redhat.com/xmlrpc.cgi"; var myConfig = jetpack.storage.simple; var badMIMEArray = ["application/octet-stream","text/x-log","undefined"]; //============================================================== // CONFIGURE: The easiest method how to set up the configuration // value is to uncomment the following line with proper URL as // the second parameter. Then reload the bug page and comment out // again. // myConfig.JSONURL = "URL-somewhere-with-your-JSON"; var jsonDataURL = myConfig.JSONURL ? myConfig.JSONURL : "http://mcepl.fedorapeople.org/scripts/BugZappers_data.json"; var PCIIDsURL = "http://mcepl.fedorapeople.org/scripts/drm_pciids.json"; var abrtQueryURL = "https://bugzilla.redhat.com/buglist.cgi"+ "?cmdtype=runnamed&namedcmd=all%20NEW%20abrt%20crashes"; //var debug = GM_getValue("debug",false); var reqCounter = 0; var msgStrs = {}; var CommentRe = new RegExp("^\\s*#"); var BlankLineRe = new RegExp("^\\s*$"); var ChipsetRE = new RegExp("^\\(--\\) ([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*"); 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 = []; var hashBugzillaWholeURL = []; var defAssigneeList = []; var suspiciousComponents = []; var signatureFedoraString = ""; // TODO we should have an array SpecialFlags instead of multiple Boolean variables var queryButtonAvailable = false; var chipIDsGroupings = []; var AddrArray = []; var PCI_ID_Array = []; var topRow = {}; var bottomRow = {}; // Get JSON configuration data $.getJSON(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; chipIDsGroupings = response.chipIDsGroupings; topRow = response.topRow; bottomRow = response.bottomRow; }); // Get card translation table $.getJSON(PCIIDsURL, function (response) { PCI_ID_Array = response; }); //============================================================== /** * 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 $.trim(chosenPair[0].addr); } else { return ""; } }; /** * 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 = []; list.forEach(function (e, i, a) { if (e.hasAttribute("value")) { outL.push(e.getAttribute("value").trim()); } }); return outL; }; /** * Check whether an item is member of the list. Idea is just to * make long if commands slightly more readable. * * @param mbr string to be searched in the list * @param list list * @return position of the string in the list, or -1 if none found. */ isInList = function(mbr, list) { return (list.indexOf(mbr) !== -1); }; // ============================================================================ // Color management methods // originally from // http://www.mjijackson.com/2008/02\ // /rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript function Color(r,g,b) { 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; }; Color.prototype.hs = function(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); }; /** * Converts an RGB color value to HSL. Conversion formula * adapted from http://en.wikipedia.org/wiki/HSL_color_space. * Assumes r, g, and b are contained in the set [0, 255] and * returns h, s, and l in the set [0, 1]. * * @param Number r The red color value * @param Number g The green color value * @param Number b The blue color value * @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]; }; /** * Converts an HSL color value to RGB. Conversion formula * adapted from http://en.wikipedia.org/wiki/HSL_color_space. * Assumes h, s, and l are contained in the set [0, 1] and * returns r, g, and b in the set [0, 255]. * * @param Number h The hue * @param Number s The saturation * @param Number l The lightness * @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]; }; /** * Converts an RGB color value to HSV. Conversion formula * adapted from http://en.wikipedia.org/wiki/HSV_color_space. * Assumes r, g, and b are contained in the set [0, 255] and * returns h, s, and v in the set [0, 1]. * * @param Number r The red color value * @param Number g The green color value * @param Number b The blue color value * @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]; }; /** * Converts an HSV color value to RGB. Conversion formula * adapted from http://en.wikipedia.org/wiki/HSV_color_space. * Assumes h, s, and v are contained in the set [0, 1] and * returns r, g, and b in the set [0, 255]. * * @param Number h The hue * @param Number s The saturation * @param Number v The value * @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]; }; /** * Provide */ Color.prototype.lightColor = function() { var hslArray = this.hsl(); var h = Number(hslArray[0]); var s = Number(hslArray[1]) * Desaturated; var l = Luminosity; var desA = this.hslToRgb(h, s, l); return new Color(desA[0],desA[1],desA[2]); }; //==================================================================================== // bzPage's methods /** * Check for the presence of a keyword * * @param str string with the keyword * @return Boolean */ bzPage.prototype.hasKeyword = function (str) { var kwd = $.trim($('#keywords', this.doc).val()); return (new RegExp(str).test(kwd)); }; /** * Set additional keyword if it isn't there * * @param str string with the keyword * @return none */ bzPage.prototype.setKeyword = function (str) { var keywordInput = $('#keywords', this.doc); var kwd = $.trim(keywordInput.val()); var strRE = new RegExp(str); if (!strRE.test(kwd)) { keywordInput.val(kwd ? kwd + ", " + str : str); } }; /** * 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 () { var verStr = $("#version option:selected:first", this.doc).text().toLowerCase(); var verNo = 0; if (/rawhide/.test(verStr)) { verNo = 999; } else { verNo = Number(verStr); } return verNo; }; /** * Send mouse click to the specified element * @param element where to send mouseclick to * @return None */ bzPage.prototype.clickMouse = function(target) { var localEvent = this.doc.get(0).createEvent("MouseEvents"); localEvent.initMouseEvent("click", true, true, this.doc.defaultView, 0, 0, 0, 0, 0, false, false, false, false, 0, null); $(target).get(0).dispatchEvent(localEvent); }; /** * Add new keyword among the keywords. * * @param str string with the new keyword * @return none * * Checks for the existing keywords. */ bzPage.prototype.addKeyword = function (str) { var kwd = $('#keywords',this.doc); if (kwd.text().length === 0) { kwd.text(str); }else{ kwd.text(kwd.text() + ", " + str); } }; /* Bugzilla functions.*/ /** * Set background color of all comments made by reporter in ReporterColor color * */ bzPage.prototype.checkComments = function () { var that = this; $("#comments .bz_comment", this.doc).each(function (i) { var email = $(".vcard a", this).text(); if (new RegExp(that.reporter).test(email)) { $(this).css("background-color", ReporterColor.toString()); } }); }; /** * Is this bug a RHEL bug? * * @return Boolean true if it is a RHEL bug */ bzPage.prototype.isRHEL = function() { return (/Red Hat Enterprise Linux/).test(this.product); }; bzPage.prototype.isTriaged = function() { if (this.version > 11) { return this.hasKeyword("Triaged"); } else { return $("#bug_status", this.doc).val().toUpperCase() !== "NEW"; } }; /** * 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 * @return none * */ bzPage.prototype.setBranding = function () { var brandColor = {}; var TriagedColor = {}; if (this.isRHEL()) { if (this.its.length > 0) { brandColor = RHITColor; } else { brandColor = RHColor; } } else if (new RegExp("Fedora").test(this.product)) { if (this.version == 999) { brandColor = RawhideColor; } else { brandColor = FedoraColor; } } // Comment each of the following lines to get only partial branding $("body", this.doc).css("background", brandColor.toString()); $("#titles", this.doc).css("background", brandColor.toString()); // Make background-color of the body of bug salmon pink // for security bugs. if (this.hasKeyword("Security")) { $("#bugzilla-body", this.doc).css({ 'background-image' : 'none', 'background-color' : SalmonPink.toString() }); } // Make it visible whether the bug has been triaged if (this.isTriaged()) { var triagedColor = brandColor.lightColor(); $("#bz_field_status",this.doc).css({ 'background-image' : 'none', 'background-color' : triagedColor.toString() }); } // we should make visible whether maintCCAddr is in CCList if (isInList(this.maintCCAddr, this.CCList)) { $("#cc_edit_area_showhide", this.doc). css({ "color": "navy", "font-weight": "bolder", "text-decoration": "underline"}); } // mark suspicious components // FIXME use https://bugzilla.redhat.com/show_bug.cgi?id=538818 for testing if (suspiciousComponents && isInList(this.component,suspiciousComponents)) { $("#bz_component_edit_container",this.doc). css({ "background-color": "red", "background-image": "none" }); } }; /** */ bzPage.prototype.groupIDs = function (manStr,cardStrID) { var outStr = 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 */ bzPage.prototype.checkChipStringFromID = function (manufacturerNo,cardNo) { var soughtID = (manufacturerNo+","+cardNo).toUpperCase(); var outList = PCI_ID_Array[soughtID]; if (outList) { return outList; } else { return ""; } }; /** * Given line to be parsed, find out which chipset it is and fill in the whiteboard * * @param iLine string with the whole unparsed "interesting line" * @param driverStr string with the driver name * @return None */ bzPage.prototype.fillInWhiteBoard = function (iLine, driverStr) { var outStr = ""; var cardIDStr = ""; var cardIDArr = []; chipSwitchboard: if (driverStr === "RADEON") { var cardID = iLine.replace(ATIgetIDRE,"$1"); cardIDArr = this.checkChipStringFromID("1002",cardID); if (cardIDArr.length > 0) { cardIDStr = cardIDArr[0]; if (cardIDArr[1]) { optionStr = cardIDArr[1]; outStr = this.groupIDs(driverStr,cardIDStr)+"/" + optionStr; } else { outStr = this.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 = $.trim(iLine.replace(new RegExp(cardIDArr[0],"i"))); // nVidia developers opted-out from grouping if (driverStr === "INTEL") { outStr = this.groupIDs(cardIDArr[1],iLine); } else { outStr = iLine; } } var whiteboardInput = $("#status_whiteboard",this.doc); var oldWhiteboard = whiteboardInput.val(); var attachedText = $.trim("card_"+outStr); if (oldWhiteboard) { attachedText += ", " + oldWhiteboard; } whiteboardInput.val(attachedText); $("#chipmagic", this.doc).css("display","none"); }; /** * 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 with the button to be copied from * @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 bool optional whether the button should submit whole page * (default true) * * @return none */ 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.originalButton.clone(true).attr({ "id":newId, "value":newLabel }).click(function (evt) { that.generalPurposeCureForAllDisease(commStr,nState, secPar); }); if (after) { $(originalLocation, this.doc).after(newButton).after("\u00A0"); } else { $(originalLocation, this.doc).before(newButton).before("\u00A0"); } if (!doSubmit) { newButton.get(0).setAttribute("type","button"); } }; /** * Get attached Xorg.0.log, parse it and find the value of chip. * Does not fill the whiteboard itself, just adds button to do so,paramList * so that slow XMLHTTPRequest is done in advance. * * @return None */ bzPage.prototype.fillInChipMagic = function () { var XorgLogURL = ""; var XorgLogAttID = ""; var XorgLogFound = false; var attURL = "", interestingLine = ""; var interestingArray = []; // Find out Xorg.0.log attachment URL this.XorgLogAttList = this.attachments.filter(function (value, index, array) { // Xorg.0.log must be text, otherwise we cannot parse it return (/[xX].*log/.test(value[0]) && /text/.test(value[2])); }); if (this.XorgLogAttList.length === 0) { console.log("No Xorg.0.log attachments found."); return; } XorgLogAttID = this.XorgLogAttList[this.XorgLogAttListIndex][1]; attURL = "https://bugzilla.redhat.com/attachment.cgi?id="+XorgLogAttID; that = this; $.get(attURL,function (ret) { var interestingLineArr = ret.split("\n").filter(function (v,i,a) { return ChipsetRE.test(v); }); if (interestingLineArr.length >0) { interestingArray = ChipsetRE.exec(interestingLineArr[0]); interestingLine = $.trim(interestingArray[2].replace(/[\s"]+/g," ")); var whiteboardInput = $("#status_whiteboard",that.doc); that.addNewButton(whiteboardInput,"chipmagic","Fill In", "","CHIPMAGIC", interestingLine+"\t"+interestingArray[1].toUpperCase(), false,true); } }); this.XorgLogAttListIndex++; }; /** * Opens a new tab with a query for the given text in the selected component * @param text to be searched for * @param component string with the component name (maybe latter regexp?) * @param product (optional) string with the product name * @return None * * TODO make this method parametrized and use it for once for general search (as it is now) * a second time for the search for the same card_ID cards (button next to the Whiteboard field * when it matches card_ string). * FIXME search only in the same product version &version=11 */ bzPage.prototype.queryInNewTab = function(text,component,product) { // Optional parameter if (product === undefined) { product = "Fedora"; } var url = "https://bugzilla.redhat.com/buglist.cgi?query_format=advanced"; if (product) { url += "&product="+$.trim(product); } if (component) { url += "&field0-0-0=component&type0-0-0=substring&value0-0-0="+$.trim(component); } if (text) { text = $.trim(text); url += "&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; } jetpack.tabs.open(url); }; /** * Get the text to search for and prepare other things for the real executive * function this.queryInNewTab, and run it. */ bzPage.prototype.queryForSelection = function() { var text = jetpack.selection.text; console.log("selection = " + text); if (!text) { text = jetpack.clipboard.get(); } if (text) { this.queryInNewTab(text, this.component); } }; /** * Parse the row with the attachment * * @param DOM element to be parsed * @return array with string name of the attachment, integer its id number, string of MIME type, integer of size in kilobytes, and the whole element itself */ bzPage.prototype.parseAttachmentLine = function (inElem,idx) { var MIMEtype = String(); var size = Number(); // Skip over obsolete attachments if ($(".bz_obsolete",inElem).length>0) { return([]); } // getting name of the attachment var attName = $.trim($("b:first", inElem).text()); // getting id var aHrefs = $("a:contains('Details')", inElem); var id = parseInt(aHrefs.attr("href").replace(/^.*attachment.cgi\?id=/, ""),10); //getting MIME type and size var stringArray = $(".bz_attach_extra_info",inElem).text(). replace(/[\n ()]+/g," ").trim().split(", "); size = parseInt(stringArray[0],10); MIMEtype = stringArray[1].split(" ")[0]; return [attName,id,MIMEtype,size,inElem]; }; /** * Select option with given label on the elements in the page var IBLast = $("#commit_top", this.doc); this.addNewButton(IBLast,"changeOwnerbtn","reASSIGN", "","ASSIGNED","NODEFAULTASSIGNEE"); // THE MAIN BUTTON ROWS var commentBox = $("#comment", this.doc); commentBox.before("
"); this.generateToolBar(commentBox.prev(),above); this.generateToolBar(this.originalButton,below); if (queryButtonAvailable) { // Add query search button // Apparently there is a bug in jQuery, we have to use plain DOM //newPosition = $("#newcommentprivacy ~ br", this.doc); newPosition = $(this.doc.get(0).querySelector("#newcommentprivacy ~ br")); newPosition.css("border","solid blue"); this.addNewButton(newPosition,"newqueryintab","Query for string", "","QUERYSEL","",false); } // FIXME Get compiz bugs as well if ((chipIDsGroupings.length >0) && this.maintCCAddr === "xgl-maint@redhat.com") { // Add find chip magic button var whiteboard_string = $("#status_whiteboard", this.doc).val(); if (isInList("card_",whiteboard_string)) { this.fillInChipMagic(); } } // Add setting default assignee if ((this.defaultAssignee.length > 0) && (this.defaultAssignee !== this.owner)) { this.addNewButton($("#bz_assignee_edit_container", this.doc), "setdefaultassigneebutton","Def. Assignee", "","SETDEFASS",this.defaultAssignee,false,true); } }; /////////////////////////////////////////////////////////////////////////////// function bzPage(doc) { this.doc = $(doc); var that = this; this.originalButton = $("#commit", this.doc); var loginArr = $("#header ul:first li:last", this.doc).text().split("\n"); this.login = $.trim(loginArr[loginArr.length-1]); this.password = ""; if (myConfig.BZpassword) { this.password = myConfig.BZpassword; } else { this.password = this.doc.get(0).defaultView.prompt("Enter your Bugzilla password",""); myConfig.BZpassword = this.password; } var bugNoTitle = $.trim($("#title > p:first", this.doc).text()); this.bugNo = new RegExp("[0-9]+").exec(bugNoTitle)[0]; this.reporter = $("#bz_show_bug_column_2 > table .vcard:first > a", this.doc).attr("title"); this.product = $("#product option:selected:first", this.doc).text(); this.component = $("#component option:selected:first", this.doc).text(); this.version = this.getVersion(); this.its = $.trim($("#cf_issuetracker", this.doc).val()); this.CCList = $.makeArray($("#cc", this.doc).val()); this.owner = $("#bz_assignee_edit_container .fn:first", this.doc).text(); this.defaultAssignee = filterByRegexp(defAssigneeList, this.component).toLowerCase(); this.maintCCAddr = filterByRegexp(AddrArray,this.component).toLowerCase(); this.XorgLogAttList = []; this.XorgLogAttListIndex = 0; this.attachments = []; this.reqCounter=0; atts = $.makeArray($(("#attachment_table tr"),this.doc).slice(1,-1)); atts.forEach(function (val,idx,arr) { that.attachments.push(that.parseAttachmentLine(val,idx)); }); var badAttachments = this.attachments.filter(function (att,idx,arr) { return (isInList(att[2],badMIMEArray)); }); if (badAttachments.length > 0) { var titleElement = $(".bz_alias_short_desc_container:first",this.doc). css("background-color","olive"). append($(this.createFixAllButton(badAttachments))); badAttachments.forEach(function (x,i,a) { that.addTextLink(x); }); } // Dig out backtrace this.btSnippet = ""; var bugTitle = $("#short_desc_nonedit_display", this.doc).text(); if (AbrtRE.test(bugTitle)) { $(".bz_alias_short_desc_container:first", this.doc). append("\u00A0Abrt bugs").click(function() { that.doc.location = abrtQueryURL; }); if (!this.hasKeyword("Triaged")) { 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 that = this; btAttachments.forEach(function (x) { attURL = "https://bugzilla.redhat.com/attachment.cgi?id=" + x[1]; console.log("attURL = " + attURL); console.log("btSnippet = " + that.btSnippet); if (!that.btSnippet) { var btRaw = $.get(attURL,function (ret) { that.btSnippet = that.parseBacktrace(ret); console.log("btSnippet = " + that.btSnippet.length); if (that.btSnippet) { that.addTextToComment(that.btSnippet); } }); } }); } } // Take care of signature for Fedora bugzappers if (signatureFedoraString.length > 0) { // (or a form named "changeform") $("form:nth-child(2)", this.doc).submit(function () { var cmntText = $("#comment", this.doc); if ((signatureFedoraString.length > 0) && ($.trim(cmntText.text()).length > 0)) { cmntText.text($.trim(cmntText.text()) + signatureFedoraString); } }); } this.setBranding(); this.checkComments(); this.buildButtons(topRow,bottomRow); // FIXME this doesn't work as it should. // Shouldn't we use .val() again instead of .text()? $("#component",this.doc).change(function (){ that.component = $("#component option:selected:first", this.doc).text(); that.changeOwner(filterByRegexp(defAssigneeList, that.component). toLowerCase()); }); } var callback = function (doc) { var curPage = new bzPage(doc); }; var options = {}; options.matches = [ "https://bugzilla.redhat.com/show_bug.cgi" ]; jetpack.pageMods.add(callback, options);