|
// ==UserScript== |
|
// @name Jira Better Search |
|
// @namespace tools.lib.umich.edu |
|
// @description Makes the useless Jira search bar into a palette for saved queries and query fragments |
|
// @include *tools.lib.umich.edu/jira* |
|
// @require https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js |
|
// @require https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js |
|
// @version 1 |
|
// @grant none |
|
// ==/UserScript== |
|
|
|
// If installing in Fluid.app manually fetch the above JS to local disk and uncomment the lines below |
|
//window.fluid.include("~/Library/Application Support/Fluid/FluidApps/Jira/Userscripts/jquery.min.js"); |
|
//window.fluid.include("~/Library/Application Support/Fluid/FluidApps/Jira/Userscripts/jquery-ui.min.js"); |
|
// make multiple jQuery instances coexist |
|
JQP = jQuery; |
|
jQuery.noConflict(true); |
|
window.JQP = JQP; |
|
|
|
window.get_recent_queries = function(){ |
|
ls_item = localStorage.getItem("userscript.recentsearch"); |
|
var ls_obj = []; |
|
if(ls_item){ |
|
ls_obj = JSON.parse(ls_item); |
|
} |
|
else{ |
|
ls_obj = [ |
|
"project in (AEIM,AE)", |
|
"id =", |
|
"text ~ \"", |
|
"status =", |
|
"assignee = currentUser()", |
|
"watcher = currentUser()", |
|
"issue in commentedByUser()", |
|
"updated > startOfDay()", |
|
"sprint in openSprints()", |
|
"statusCategory = Done", |
|
"statusCategory != Done" |
|
]; |
|
} |
|
return ls_obj; |
|
}; |
|
|
|
window.advanced_search_mode = function(){ |
|
var advanced = JQP("#advanced-search").length > 0; |
|
return advanced; |
|
}; |
|
|
|
window.save_recent_query = function(q){ |
|
if(q){ |
|
var ls_obj = get_recent_queries(); |
|
var pos = JQP.inArray(q,ls_obj); |
|
if (pos >=0){ |
|
ls_obj.splice(pos,1); |
|
} |
|
ls_obj.unshift(q); |
|
localStorage.setItem("userscript.recentsearch",JSON.stringify(ls_obj)); |
|
// reset autocomplete seed |
|
JQP('#quickSearchInput').autocomplete("option","source",get_recent_queries()); |
|
} |
|
}; |
|
|
|
window.delete_recent_query = function(q){ |
|
if(q){ |
|
var ls_obj = get_recent_queries(); |
|
var pos = JQP.inArray(q,ls_obj); |
|
if (pos >=0){ |
|
ls_obj.splice(pos,1); |
|
localStorage.setItem("userscript.recentsearch",JSON.stringify(ls_obj)); |
|
// reset autocomplete seed |
|
JQP('#quickSearchInput').autocomplete("option","source",get_recent_queries()); |
|
} |
|
} |
|
}; |
|
|
|
// Not currently used in UI. Run from console to clear list of saved searches. |
|
window.better_search_reset = function(){ |
|
localStorage.removeItem("userscript.recentsearch"); |
|
// reset autocomplete seed |
|
JQP('#quickSearchInput').autocomplete("option","source",get_recent_queries()); |
|
}; |
|
|
|
window.better_submission = function(){ |
|
var q = document.forms.quicksearch.quickSearchInput.value; |
|
|
|
if(advanced_search_mode()){ |
|
if(q && q.length){ |
|
var aq = JQP("#advanced-search").attr('value'); |
|
if(aq){ |
|
aq = aq+" AND "+q; |
|
} |
|
else{ |
|
aq = q; |
|
} |
|
JQP("#advanced-search").attr('value', aq); |
|
document.forms.quicksearch.quickSearchInput.value = ""; |
|
JQP(".better-filter").remove(); |
|
} |
|
else{ |
|
window.location = ("/jira/issues/?jql="+escape(JQP("#advanced-search").attr('value'))); |
|
} |
|
} |
|
else{ |
|
window.location = ("/jira/issues/?jql="+escape(q)); |
|
} |
|
}; |
|
|
|
// make search bar wider |
|
var styleTag = JQP('<style>#quickSearchInput { width: 371px; }</style>'); |
|
JQP('html > head').append(styleTag); |
|
|
|
JQP(document).ready( function() { |
|
// remove useless chrome |
|
//JQP(".jira-feedback-plugin").remove(); |
|
|
|
// inject JQuery-UI CSS |
|
var inject_jquery_ui = document.createElement('link'); |
|
inject_jquery_ui.setAttribute('href','https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/smoothness/jquery-ui.css'); |
|
inject_jquery_ui.setAttribute('rel','stylesheet'); |
|
document.head.appendChild(inject_jquery_ui); |
|
|
|
// make search bar better |
|
JQP('form#quicksearch').attr('action',"javascript:better_submission()"); |
|
|
|
// tell everyone the search bar is better |
|
JQP('#quickSearchInput').attr('placeholder','Better Search'); |
|
|
|
console.log("worthless built in jQuery: "+jQuery.fn.jquery); |
|
console.log("worthless built in jQuery UI: "+jQuery.ui.version); |
|
console.log("Proper jQuery: "+JQP.fn.jquery); |
|
console.log("Proper jQuery UI: "+JQP.ui.version); |
|
|
|
// add autocomplete! |
|
JQP('#quickSearchInput').autocomplete({source: get_recent_queries(), minLength: 0, delay: 0}); |
|
|
|
// draw buttons for better search UI |
|
setInterval(function(){ |
|
advanced_mode_on = JQP("#advanced-search").length > 0; |
|
advanced_mode_save_button_on = JQP(".better-filter").length > 0; |
|
if (!advanced_mode_on){ |
|
// remove buttons, not needed |
|
JQP(".better-filter").remove(); |
|
} |
|
else if(!advanced_mode_save_button_on){ |
|
// get content |
|
content = JQP("#advanced-search").attr('value').trim(); |
|
// draw the appropriate button |
|
delete_mode = JQP.inArray(content,get_recent_queries())>-1; |
|
if(delete_mode){ |
|
JQP("#search-header-view").find('ul.filter-operations').append('<li><button class="aui-button aui-button-light delete-better-filter better-filter">Delete from Better Search</button></li>'); |
|
JQP(".delete-better-filter").on("click",function(){delete_recent_query(content);JQP("#advanced-search").attr('value', "");JQP(".better-filter").remove();}); |
|
} |
|
else{ |
|
JQP("#search-header-view").find('ul.filter-operations').append('<li class="better-filter"><button class="aui-button aui-button-light save-as-better-filter better-filter">Save w/ Better Search</button></li>'); |
|
JQP(".save-as-better-filter").on("click",function(){save_recent_query(content);JQP(".better-filter").remove();}); |
|
} |
|
} |
|
},50); |
|
|
|
}); |
|
|
|
// Tested working in FF w/Greasemonkey, Safari and Chrome w/Tampermonkey, partly working in Fluid as of 2017-06-30 |
|
// next steps: |
|
// interface to reorder saved queries |
|
// work around Fluid localStorage issues |
|
// try/test // @run-at document-start |
|
// clean up and reduce button poll |
|
// fix intermittent issue w/ element overlap |