Skip to content

Instantly share code, notes, and snippets.

@rrotter
Last active June 4, 2024 20:19
Show Gist options
  • Save rrotter/6737f0b01e51c04dbac8d76e5770d4b0 to your computer and use it in GitHub Desktop.
Save rrotter/6737f0b01e51c04dbac8d76e5770d4b0 to your computer and use it in GitHub Desktop.
Userscript to make Jira search suck less

Better Search

Userscript for making Jira search bar more useful

  • save queries from advanced search screen
  • recall them w/ autocomplete from quick search bar
  • on advanced search screen quick search bar acts as a palette for query fragments, adding saved query queries to your main query

Installation

  1. Install Tampermonkey or Greasemonkey
  2. Click on the "Raw" button below, your browser extension should now offer to install the Better Search user script
  3. Customize the "@include" line for your domain

Usage Tutorial

  1. Click in the Jira search bar (if the script is installed correctly it is now labeled "Better Search")
  2. Press down arrow (for the full list) or start typing (autocomplete search) to navigate a list of default saved searches
  3. Navigate to "assignee = currentUser()"
  • Press return to select this item, and return again to excure search
  • You will now see a list of your assigned issues
  1. If you aren't already in advanced search mode, click "Advanced"
  2. Now return to the Better Search box and select another query
  • Now, when you press return, rather than sunning the search the query fragment is appended to the Advanced Search box
  • Still in the Better Search box, press return again to execute the search
  • This is a very quick way to formulate complicated searches: Try making a query to find all tickets assigned to you that are not complete and in a particular project
  1. Finally, let's save a query:
  • Formulate a new query in the Advanced Search box; if this search isn't already saved you'll see a "Save w/ Better Search" button
  • Click there to save. Now return to the Better Search box and you'll see your query there
  • If an already saved search is in the Advanced Search box, you can delete is from the autocomplete list with "Delete from Better Search"
// ==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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment