// ==UserScript==
// @name Jira Annoying Guy
// @namespace http://ciandt.com/
// @version 0.4.2
// @description Jira custom options
// @match https://jiracloud.cit.com.br/secure/RapidBoard.jspa?rapidView=7215*
// @copyright rafaelh
// ==/UserScript==
/*Change log
Teste
0.4.1 - 07/07/2014
Refactors, Constants
Bug when trying to attach file fixed
0.4.0 - 03/07/2014
When moving tasks to IN PROGRESS or IN CODE REVIEW, check if there is already a task assigned for the user
0.3.2 - 03/07/2014
Refresh work view was improved; refresh fails are going to happen less frequently
0.3.1 - 01/07/2014
Backlog column missing fix
0.3.0 - 30/06/2014
Task grab events - refreshing is still improvised
0.2 - 30/06/2014
ScrollTo error message
0.1 - 28/06/2014
Create Issue - Bug - Environment
Not working if issue is created in a new tab
*/
//Constants
var Constants = {
ISSUE_TYPE_BUG: ["1", "8"],
COLUMN_INDEX_IN_PROGRESS: 2,
COLUMN_INDEX_IN_CODE_REVIEW: 4
}
//Utils
var Utils = {
obtainNthIndex: function(str, pat, n){
var L= str.length, i= -1;
while(n-- && i++<L){
i= str.indexOf(pat, i);
}
return i;
},
parseFieldsBody: function(body, splitter) {
var obj = {};
var text = body.split(splitter);
var field;
var fieldName;
var fieldVal;
text.forEach(function(attr) {
field = attr.split('=');
fieldName = field[0];
fieldVal = field[1];
obj[fieldName] = fieldVal;
});
return obj;
},
parseReturnUrlFromDocumentUrl: function(documentUrl) {
var returnUrl = document.URL.substring(this.obtainNthIndex(document.URL, '/', 3), document.URL.length);
returnUrl = returnUrl.replace(/\?/g,'%3F');
returnUrl = returnUrl.replace(/\=/g,'%3D');
returnUrl = returnUrl.replace(/\&/g,'%26');
return returnUrl;
},
refreshView: function() {
GH.RefreshHandler.Poller.stopPoller();
GH.RefreshHandler.Poller.startPoller(true);
},
removeInsertedErrorMessages: function() {
$('#inserted-error-message').remove();
},
addErrorAndScrollTo: function(fieldText, fieldId) {
var errorMsg = '<div id="inserted-error-message" style="color:red; font-weight: bold;">You must specify '+fieldText+' of the issue.</div>';
$(fieldId+'-wiki-edit').append(errorMsg);
var scrollPosition = 0;
$('.form-body')[0].scrollTop = scrollPosition;
scrollPosition = $(fieldId).position().top - 5;
$('.form-body')[0].scrollTop = scrollPosition;
},
};
//Overwriting .send
XMLHttpRequest.prototype.reallySend = XMLHttpRequest.prototype.send;
XMLHttpRequest.prototype.send = function(body) {
if (body != null) {
//If .send body is a string (i.e. not a file)
if (typeof body == 'string' || body instanceof String) {
var obj = Utils.parseFieldsBody(body, '&');
//Create-issue
if (obj.isCreateIssue) {
Utils.removeInsertedErrorMessages();
//Bug
if (Constants.ISSUE_TYPE_BUG.indexOf(obj.issuetype)!=-1) {
//Environment
if (obj.environment == '') {
Utils.addErrorAndScrollTo('an environment', '#environment');
this.abort();
}
}
}
}
}
this.reallySend(body);
};
function checkIfColumnHasAssignedTasks(args, column, index, task) {
var taskAssignee = $(task).find('.ghx-avatar img').attr('alt');
var user = $('meta[name="ajs-remote-user-fullname"]').attr('content');
if (taskAssignee == user) {
args.alreadyAssignedToTask = true;
args.alreadyAssignedTaskColumn = column;
args.alreadyAssignedTaskIndex = index;
}
return args;
}
function checkIfUserHasAssignedTasks() {
var $allTasksInProgress = $('ul li:nth-child('+Constants.COLUMN_INDEX_IN_PROGRESS+') .ghx-has-avatar');
var $allTasksInCodeReview = $('ul li:nth-child('+Constants.COLUMN_INDEX_IN_CODE_REVIEW+') .ghx-has-avatar');
var args = {
alreadyAssignedTaskColumn: null,
alreadyAssignedTaskIndex: null,
alreadyAssignedToTask: false
};
$allTasksInProgress.each( function(index, task) {
args = checkIfColumnHasAssignedTasks(args, Constants.COLUMN_INDEX_IN_PROGRESS, index, task);
});
$allTasksInCodeReview.each( function(index, task) {;
args = checkIfColumnHasAssignedTasks(args, Constants.COLUMN_INDEX_IN_CODE_REVIEW, index, task);
});
if (args.alreadyAssignedToTask) {
alert('Warning: You already have a task assigned to you!');
window.scrollTo(0, $($('ul li:nth-child('+args.alreadyAssignedTaskColumn+') .ghx-has-avatar')[args.alreadyAssignedTaskIndex]).offset().top - 200);
}
}
//Overwriting .open
XMLHttpRequest.prototype.reallyOpen = XMLHttpRequest.prototype.open;
XMLHttpRequest.prototype.open = function() {
var abortedRequest = false;
var method = this.open.arguments[0];
var url = this.open.arguments[1];
var async = this.open.arguments[2];
//GET
if (method=="GET") {
//Parsing url
var parsedUrl = url.split('?');
var file = parsedUrl[0];
var body = parsedUrl[1];
var fileFormat = file.substring(file.lastIndexOf('.')+1);
var fileType = file.substring(file.lastIndexOf('/')+1, file.lastIndexOf('.'));
//JSPA
if (fileFormat == "jspa") {
//WorkflowUIDispatcher
if (fileType == "WorkflowUIDispatcher") {
var obj = Utils.parseFieldsBody(body, '&');
//When moved to IN PROGRESS(41) and IN CODE REVIEW(61) columns
if ((obj.action==41)||(obj.action==61)) {
checkIfUserHasAssignedTasks();
//Assign
this.onload = function() {
xmlHttp = new XMLHttpRequest();
xmlHttp.open("POST", "/secure/AssignIssue.jspa", true);
//Refresh
xmlHttp.onload = function(){
Utils.refreshView();
};
xmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
var returnUrl = Utils.parseReturnUrlFromDocumentUrl(document.URL);
xmlHttp.send("inline=true&decorator=dialog&returnUrl="+returnUrl+"&id="+obj.id+"&assignee="+$("meta[name='ajs-remote-user']").attr('content')+"&comment=&commentLevel=&atl_token="+$("meta[name='atlassian-token']").attr('content'));
};
}
//When moved to TO DO(backlog (81), development(31)) and AWAITING CODE REVIEW(51) columns
if ((obj.action==81)||(obj.action==31)||(obj.action==51)) {
//Unassign
this.onload = function() {
setTimeout( function() {
$('[data-issue-id = '+obj.id+']').attr('class', $('[data-issue-id = '+obj.id+']').attr('class').replace('ghx-has-avatar ', ''));
}, 1000);
xmlHttp = new XMLHttpRequest();
xmlHttp.open("POST", "/secure/AssignIssue.jspa", true);
//Refresh
xmlHttp.onload = function(){
Utils.refreshView();
};
xmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
var returnUrl = Utils.parseReturnUrlFromDocumentUrl(document.URL);
xmlHttp.send("inline=true&decorator=dialog&returnUrl="+returnUrl+"&id="+obj.id+"&assignee=&comment=&commentLevel=&atl_token="+$("meta[name='atlassian-token']").attr('content'));
};
}
}
}
}
this.reallyOpen(method, url, async);
};