diff options
Diffstat (limited to 'bugzillaBugTriage.js')
-rw-r--r-- | bugzillaBugTriage.js | 322 |
1 files changed, 233 insertions, 89 deletions
diff --git a/bugzillaBugTriage.js b/bugzillaBugTriage.js index 87eb78a..517df99 100644 --- a/bugzillaBugTriage.js +++ b/bugzillaBugTriage.js @@ -24,7 +24,7 @@ var TriagedDistro = 13; var NumberOfFrames = 7; var XMLRPCurl = "https://bugzilla.redhat.com/xmlrpc.cgi"; var bugURL = "https://bugzilla.redhat.com/show_bug.cgi?id="; -var myConfig = jetpack.storage.simple; +var myStorage = jetpack.storage.simple; var badMIMEArray = ["application/octet-stream","text/x-log","undefined"]; //============================================================== @@ -41,7 +41,7 @@ jetpack.future.import("storage.settings"); // jetpack.settings.open(); //} -var jsonDataURL = myConfig.JSONURL ? myConfig.JSONURL : +var jsonDataURL = myStorage.JSONURL ? myStorage.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?"+ @@ -85,6 +85,7 @@ var suspiciousComponents = []; var signatureFedoraString = ""; // TODO we should have an array SpecialFlags instead of multiple Boolean variables var queryButtonAvailable = false; +var upstreamButtonAvailable = false; var chipIDsGroupings = []; var AddrArray = []; var PCI_ID_Array = []; @@ -146,6 +147,25 @@ loadJSON(PCIIDsURL, PCI_ID_Array = response; }); +//======== load external library =============================== + +var XMLRPCMessage = {}; +var req = new XMLHttpRequest(); +req.open("GET","http://mcepl.fedorapeople.org/scripts/xmlrpc.js",true); +req.onreadystatechange = function (aEvt) { + if (req.readyState == 4) { + if (req.status == 200) { + var thisDoc = jetpack.tabs.focused.contentDocument; + var script = thisDoc.createElement("script"); + script.setAttribute("type","text/javascript"); + script.innerHTML = req.responseText; + thisDoc.getElementsByTagName("head")[0].appendChild(script); + XMLRPCMessage = jetpack.tabs.focused.contentWindow.wrappedJSObject.XMLRPCMessage; + } + } +}; +req.send(""); + //============================================================== /** @@ -459,6 +479,152 @@ BzPage.prototype.getOptionValue = function (id) { return this.dok.getElementById(id).value; }; +/* Offline supporting functions */ +/** + * + * @todo FIXME this probably makes a closure and a memory leak + * name='changeform' + * investigate https://developer.mozilla.org/en/How_to_Turn_Off_Form_Autocompletion + * + * <form method="post" action="process_bug.cgi" autocomplete="off"> + + Reading http://www.w3.org/TR/1999/REC-html401-19991224/interact/forms.html#h-17.13 + random notes: + - 17.13.3 provides all steps necessary + - enctype != application/x-www-form-urlencoded => SHOULD fails (no further questions needed) + - http://www.w3.org/MarkUp/html-spec/html-spec_8.html#SEC8.2.1. is nice explanation + (albeit quite dated) + - on multiple values http://www.w3.org/TR/1999/REC-html401-19991224/interact/forms.html#h-17.6.1 + - příliš jednoduché http://www.innovation.ch/java/HTTPClient/emulating_forms.html + - + */ +BzPage.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.dok.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; +}; + +BzPage.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(); + } +}; + +/** + * + * + * Yes, this is correct, this is NOT method of bzPage! + */ +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); + }); + } +} + /* Bugzilla functions.*/ /** @@ -776,7 +942,7 @@ BzPage.prototype.addNewButton = function (originalLocation,newId,newLabel, newButton.value = newLabel; newButton.addEventListener("click",function (evt) { that.generalPurposeCureForAllDisease(commStr,nState, secPar); - },false); + }, false); if (after) { originalLocation.parentNode.insertBefore(newButton, @@ -834,7 +1000,7 @@ BzPage.prototype.fillInChipMagic = function () { interestingArray = ChipsetRE.exec(interestingLineArr[0]); interestingLine = interestingArray[2]. replace(/[\s"]+/g," ").trim(); - var whiteboardInput = this.dok. + var whiteboardInput = that.dok. getElementById("status_whiteboard"); that.addNewButton(whiteboardInput,"chipmagic","Fill In", "","CHIPMAGIC", @@ -912,13 +1078,24 @@ BzPage.prototype.sendBugUpstream = function() { var url = filterByRegexp(upstreamBugzillasArray, this.getOptionValue("component")); - var text = this.dok.getElementById("short_desc_nonedit_display"). - textContent.trim() + "\n\n"; - text += this.collectComments(); - jetpack.clipboard.set(text); var ret = jetpack.tabs.open(url); - console.log("opening new tab returned"); - console.log(ret); + var that = this; + console.log("Setting up load listener"); + jetpack.tabs.onReady(function() { + var otherDoc = ret.contentDocument; + console.log("otherDoc"); + console.log(otherDoc); + var otherElems = otherDoc.forms.namedItem("Create").elements; + otherElems.namedItem("short_desc").value = + that.dok.getElementById("short_desc_nonedit_display"). + textContent.trim(); + otherElems.namedItem("comment").value = that.collectComments(); + ret.focused(); + + console.log("opening new tab returned"); + console.log(ret); + + }); }; /** @@ -943,9 +1120,6 @@ BzPage.prototype.parseAttachmentLine = function (inElem) { // getting name of the attachment var attName = inElem.getElementsByTagName("b")[0].textContent.trim(); - // getting id - // $("a:contains('Details')", inElem); - // FIXME isn't there more simple way to replace above? querySelector? var aHrefsArr = inElem.getElementsByTagName("a"); var aHref = Array.filter(aHrefsArr,function (x) { return x.textContent.trim() == "Details"; @@ -1091,21 +1265,18 @@ BzPage.prototype.getWholeURL = function(selectValue,bugID) { */ BzPage.prototype.callBack = function(data,textStatus) { if (--this.reqCounter <= 0) { - setTimeout(document.location.reload,1000); + setTimeout(this.dok.location.reload,1000); } }; /** - * Create XML-RPC message for updateAttachMimeType procedure with given parameters. - * Yes, I know this is very ugly, but in the current state of jetpack it is not possible - * to import external jQuery modules, so I cannot use jquery.rpc as much as I would like to. + * The worker function -- call XMLRPC to fix MIME type of the + * particular attachment * - * @param login string with login - * @param password string with password - * @param attachID Number with the attachment ID# - * @param mimeType stri ng with MIME type, optional and defaults to text/plain - * @param email Boolean whether we should send email or not - * @return string with the XML-RPC message + * @param id integer with the attachment id to be fixed + * @param type string with the new MIME type, optional defaults to "text/plain" + * @param email Boolean whether email should be sent to appropriate person; option, + defaults to false updateAttachMimeType($data_ref, $username, $password) @@ -1119,56 +1290,24 @@ Update the attachment mime type of an attachment. The first argument is a data h "nomail" => 0, # OPTIONAL Flag that is either 1 or 0 if you want email to be sent or not for this change }; + */ -BzPage.prototype.createXMLRPCMessage = function(login,password,attachId,mimeType,email) { - if (mimeType === undefined) { - mimeType = "text/plain"; +BzPage.prototype.fixAttachById = function(id,type,email) { + if (type === undefined) { + type = "text/plain"; } if (email === undefined) { email = false; } - var emailStr = email ? "0" : "1"; - - var msg = <methodCall> - <methodName>bugzilla.updateAttachMimeType</methodName> - <params> - <param> - <value><struct> - <member> - <name>attach_id</name> - <value><i4>{attachId}</i4></value> - </member> - <member> - <name>mime_type</name> - <value><string>{mimeType}</string></value> - </member> - <member> - <name>nomail</name> - <value><boolean>{emailStr}</boolean></value> - </member> - </struct></value> - </param> - <param> - <value><string>{login}</string></value> - </param> - <param> - <value><string>{password}</string></value> - </param> - </params> - </methodCall>; - return msg.toXMLString(); -}; -/** - * The worker function -- call XMLRPC to fix MIME type of the - * particular attachment - * - * @param id integer with the attachment id to be fixed - * @param type string with the new MIME type, e.g. "text/plain" - */ -BzPage.prototype.fixAttachById = function(id,type) { - var msg = this.createXMLRPCMessage(this.login,this.password,id,type); + var msg = new XMLRPCMessage("bugzilla.updateAttachMimeType"); + msg.addParameter({'attach_id':id, 'mime_type':type, 'nomail':!email}); + msg.addParameter(this.login); + msg.addParameter(this.password); + console.log("testing XMLRPCMessage:\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"); @@ -1182,17 +1321,16 @@ BzPage.prototype.fixAttachById = function(id,type) { } } }; - req.send(msg); + req.send(msg.xml()); this.reqCounter++; }; +// FIXME possibly eliminate this function altogether and +// make it inline? BzPage.prototype.fixAllAttachments = function(list) { - var tmpElem = {}; - - for(var i=0;i<list.length;i++) { - tmpElem = list[i]; - this.fixAttachById(tmpElem[1]); - } + Array.forEach(list,function (x) { + this.fixAttachById(x[1]); + }, this); }; /** @@ -1209,7 +1347,7 @@ BzPage.prototype.createFixAllButton = function (list) { elem.innerHTML = "<b>F</b>ix all"; elem.addEventListener("click", function() { that.fixAllAttachments(list); - },false); + }, false); return elem; }; @@ -1469,12 +1607,12 @@ BzPage.prototype.buildButtons = function (above,below) { if (queryButtonAvailable) { // Add query search button this.addNewButton(brElementPlacer,"newqueryintab", - "Query for string","","QUERYSEL","",false); + "Query for string","","QUERYSEL","", false); } // Button for upstreaming if (upstreamButtonAvailable) { this.addNewButton(brElementPlacer,"sendupstream", - "Send upstream","","SENDUPSTREAM","",false); + "Send upstream","","SENDUPSTREAM","", false); } // var brElement2BMoved = this.dok.querySelector("#comment_status_commit br:last-of-type"); @@ -1508,18 +1646,16 @@ function BzPage(doc) { var that = this; this.originalButton = this.dok.getElementById("commit"); - console.log(this.dok.querySelector("#header ul.links li:last-of-type")); var loginArr = this.dok. querySelector("#header ul.links li:last-of-type"). textContent.split("\n"); this.login = loginArr[loginArr.length-1].trim(); - this.password = ""; // the following is quite awful brutal hack console.log("on __parent__ navigator.online = " + jetpack.__parent__.navigator.onLine); - if (myConfig.BZpassword) { - this.password = myConfig.BZpassword; + if (myStorage.BZpassword) { + this.password = myStorage.BZpassword; } else { var prompts = Components.classes["@mozilla.org/embedcomp/prompt-service;1"] .getService(Components.interfaces.nsIPromptService); @@ -1531,7 +1667,7 @@ function BzPage(doc) { // set if OK was pressed. The checkbox is not displayed. if (result) { this.password = password.value; - myConfig.BZpassword = this.password; + myStorage.BZpassword = this.password; jetpack.storage.simple.sync(); } } @@ -1583,7 +1719,8 @@ function BzPage(doc) { // Dig out backtrace this.btSnippet = ""; - var bugTitle = this.dok.getElementById("short_desc_nonedit_display").textContent; + var bugTitle = this.dok.getElementById("short_desc_nonedit_display"). + textContent; if (AbrtRE.test(bugTitle)) { var notedLabel = this.dok.querySelector("label[for='newcc']"); @@ -1601,7 +1738,8 @@ function BzPage(doc) { abrtButton.textContent = "Abrt bugs"; mainTitle.appendChild(abrtButton); var develWhiteboardElem = this.dok.getElementById("cf_devel_whiteboard"); - var develWhiteboard = develWhiteboardElem ? develWhiteboardElem.value : "btparsed"; + var develWhiteboard = develWhiteboardElem ? develWhiteboardElem. + value : "btparsed"; if (!(this.hasKeyword("Triaged") || (/btparsed/.test(develWhiteboard)))) { var btAttachments = this.attachments.filter(function (att,idx,arr) { @@ -1632,7 +1770,7 @@ function BzPage(doc) { function () { that.addTextToTextBox("comment", signatureFedoraString); } - ,false); + , false); } this.setBranding(); @@ -1643,7 +1781,7 @@ function BzPage(doc) { var additionalButtons = this.dok.getElementById("bugzilla-body"). getElementsByClassName("related_actions")[0]; var customJSONURLUI = this.dok.createElement("li"); - customJSONURLUI.innerHTML = " - <a href='#' id='customJSONbutton'>" + + customJSONURLUI.innerHTML = "\u00A0-\u00A0<a href='#' id='customJSONbutton'>" + "BugZap config</a>"; additionalButtons.appendChild(customJSONURLUI); this.dok.getElementById("customJSONbutton"). @@ -1651,11 +1789,11 @@ function BzPage(doc) { var newURL = jetpack.tabs.focused.contentWindow. prompt("URL for your JSON customization file"); if (newURL) { - myConfig.JSONURL = newURL; + myStorage.JSONURL = newURL; jetpack.storage.simple.sync(); jetpack.tabs.focused.contentWindow.location.reload(); } - },false); + }, false); // set default assignee on change of the component this.dok.getElementById("component").addEventListener("change", @@ -1663,7 +1801,13 @@ function BzPage(doc) { that.component = that.getOptionValue("component"); that.changeOwner(filterByRegexp(defAssigneeList, that.component). toLowerCase()); - },false); + }, false); + + // offline-capable submit + this.dok.forms.namedItem("changeform"). + addEventListener('submit', function (evt) { + that.submitCallback.call(that, evt)}, + false); } var callback = function (doc) { @@ -1673,5 +1817,5 @@ var callback = function (doc) { var options = {}; options.matches = [ "https://bugzilla.redhat.com/show_bug.cgi" - ]; +]; jetpack.pageMods.add(callback, options); |