Skip to content

Commit

Permalink
Improves search.
Browse files Browse the repository at this point in the history
Improves UX when caching search results
Cleans up issue formatting

Issue #81
  • Loading branch information
steyep committed Oct 27, 2017
1 parent ee92b3e commit e129e61
Show file tree
Hide file tree
Showing 10 changed files with 365 additions and 273 deletions.
139 changes: 139 additions & 0 deletions lib/issues.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
const Jira = require('./jira');
const Workflow = require('./workflow');
const config = require('./jira/config');

let wf = new Workflow();
let enabledItems = config.menuItems;
let options = Jira.getOptions();

if (options['enabled_menu_items']) {
enabledItems = options['enabled_menu_items'];
}

module.exports = {

format: function (issues) {
let self = this;
issues = issues
.map(issue => ({
title: issue.Key,
subtitle: issue.Summary,
valid: false,
autocomplete: wf.path('tickets', issue.Key),
data: self.getTicket(issue),
projectIcon: issue.Key.replace(/-.*$/, '') + '.png',
cmdMod: {
subtitle: 'Open issue in browser',
arg: `openIssue ${issue.Key}`
}
}));

return issues;
},

getTicket: function (ticket) {
ticket = ticket || {};
let menu = [];

// Summary
if (ticket.Summary) {
let url = ticket.URL || null
menu.push({
title: ticket.Summary,
valid: url !== null,
arg:'openURL ' + url,
icon: 'title.png',
wfId: 'summary'
});
}

// Description
if (ticket.Description) {
menu.push({
title: ticket.Description,
valid: false,
icon: 'description.png',
wfId: 'description'
})
}

// Progress
let progress = Jira.getProgress(ticket.Key);
let startProgress = progress === false;
menu.push({
title: startProgress ? 'Start Progress' : `Stop Progress (${progress})`,
arg: startProgress ? `startProgress ${ticket.Key}` : `stopProgress ${ticket.Key}`,
valid: true,
icon: startProgress ? 'play.png' : 'stop.png',
wfId: 'progress',
cmdMod: startProgress ? null : {
subtitle: 'Stop progress without logging time',
arg: `clearProgress ${ticket.Key}`
}
})

// Assignee
let assignee = ticket.Assignee || 'Unassigned';
menu.push({
title: 'Assigned: ' + assignee,
valid: false,
userIcon: assignee.replace(/[^a-z0-9]/gi,'_') + '.png',
data: {
'_key': ticket.Key + '-assign',
currentAssignee: assignee
},
autocomplete: wf.path('assign', ticket.Key),
wfId: 'assignee'
});

// Status
if (ticket.Status) {
menu.push({
title: 'Status: ' + ticket.Status,
valid: false,
icon: ticket.StatCategory + '.png',
data: {
'_key': ticket.Key + '-status'
},
autocomplete: wf.path('status', ticket.Key),
wfId: 'status'
});
}

// Comment
menu.push({
title: 'Add a comment',
valid: false,
icon: 'comment.png',
data: {
'_key': ticket.Key + '-comment'
},
autocomplete: wf.path('comment', ticket.Key),
wfId: 'comment'
});

// Watch
if (ticket.Watching !== undefined) {
menu.push({
title: ticket.Watching ? 'Stop watching this issue' : 'Start watching this issue',
valid: true,
icon: ticket.Watching ? 'watch.png' : 'unwatch.png',
arg: `toggleWatch ${ticket.Key} ${ticket.Watching}`,
wfId: 'watch'
});
}

// Priority
if (ticket.Priority) {
menu.push({
title: ticket.Priority,
valid: false,
priorityIcon: ticket.Priority + '.png',
wfId: 'priority'
});
}

return menu.filter(issue => enabledItems.includes(issue.wfId));
}

}
3 changes: 2 additions & 1 deletion lib/jira/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const worklog = require('./worklog');
const log = require('../alfred-log');
const create = require('./create');
const issueTypes = require('./issuetypes');
const search = require('./search');

Jira = {
'auth': () => auth.setConfig(),
Expand Down Expand Up @@ -113,7 +114,7 @@ Jira = {
let self = this;
return new Promise((resolve, reject) => {
self.auth()
.then(() => resolve(ls.search(query)))
.then(() => resolve(search.search(query)))
.catch(reject);
})
},
Expand Down
110 changes: 9 additions & 101 deletions lib/jira/list.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
const config = require('./config');
const search = require('./search');
const auth = require('./auth');
const request = require('axios');
const cache = require('./cache');
const log = require('../alfred-log');

const AvailableStatuses = () => ' AND status in ("' + config.options.available_issues_statuses.map(decodeURI).join('","') + '")';
const SearchInProjects = () => {
Expand All @@ -29,28 +29,8 @@ function IssueRequest(bookmark) {
query += AvailableStatuses();
}
query = [query, sort].filter(Boolean).join(' order by ');

// Query cleanup
let parensWithoutQuotes = query.match(/\([^\(\)"]+\)/g);
if (parensWithoutQuotes) {
parensWithoutQuotes.forEach(group => {
if (/,/.test(group)) {
let clean = group.split(/[\(\),]/);
group = group.replace(/([\(\)])/g, '\\$1');
clean = clean.map(s => s.trim()).filter(String).join('","')
clean = `("${clean}")`
query = query.replace(new RegExp(group, ''), clean);
}
});
}

// Escape escape characters (\)
query = query.replace(/\\/g, '\\\\');

// Log query to help with debugging.
log('Searching for query:\n%s', query);

this.query = 'rest/api/2/search?jql=' + encodeURIComponent(query);
this.query = query;
var cache = bookmark.cache || 0;
this.cacheId = bookmark.cacheId;
this.setCache = cache > 0;
Expand All @@ -60,6 +40,7 @@ function IssueRequest(bookmark) {
}

let list = {

getIssues: function(params) {
let self = this;
return new Promise((resolve, reject) => {
Expand All @@ -69,54 +50,13 @@ let list = {
return resolve(cachedData);
}
}
request
.get(config.url + params.query, config.req)
.then(function(res) {
if (res.status != 200) {
reject(new Error(res.statusText));
}

let issues = res.data.issues;
let table = [];
for (let i =0; i < issues.length; i++) {
let issue = issues[i],
fields = issue.fields;
if (!fields.priority) {
fields.priority = { name: '' }
}

if (!fields.status) {
fields.status = { name: '' }
}

if (!fields.assignee) {
fields.assignee = { displayName: '' }
}

if (!fields.status.statusCategory) {
fields.status.statusCategory = { name: '' }
}

if (!fields.watches) {
fields.watches = { isWatching: null };
}

table.push({
'Key': issue.key,
'Priority': fields.priority.name,
'Summary': fields.summary,
'Description': fields.description,
'Status': fields.status.name,
'StatCategory': fields.status.statusCategory.name,
'Assignee': fields.assignee.displayName,
'URL': config.url + 'browse/' + issue.key,
'Watching': fields.watches.isWatching
});
}
search.getIssues(params.query)
.then(issues => {
if (params.setCache) {
cache.set(params.cacheId, table);
cache.set(params.cacheId, issues);
}
resolve(table);
resolve(issues);
})
.catch(reject);
});
Expand All @@ -132,40 +72,8 @@ let list = {
bookmarkConfig.cacheId = id;
}
return this.getIssues(new IssueRequest(bookmarkConfig));
},

findIssue: function(ticket){
let req = new IssueRequest({
cache: 0,
query: `issueKey="${ticket}"`,
limitStatuses: false,
limitProjects: false
});
return this.getIssues(req);
},

search: function (query) {
let options = config.options || {};
let basicSearch = !options.advancedSearch;

if (/^\w+-\d+$/.test(query.trim())) {
return this.findIssue(query);
}

if (basicSearch) {
query = 'summary+~+"' + query + '"'
+ '+OR+description+~+"' + query + '"'
+ '+OR+comment+~+"' + query + '"';
}
let req = new IssueRequest({
query: query,
cacheId: 'search',
cache: 45*1000, // 45 seconds
limitStatuses: false,
limitProjects: false
})
return this.getIssues(req);
}

};

module.exports = list;
module.exports = list;
Loading

0 comments on commit e129e61

Please sign in to comment.