Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes #639: Add ability to load search results from URL params for non-logged in users #650

Merged
merged 7 commits into from
Jul 31, 2015
24 changes: 23 additions & 1 deletion tests/functional/issue-list.js
Original file line number Diff line number Diff line change
Expand Up @@ -230,11 +230,33 @@ define([
});
},

'results are loaded from the query params': function() {
'results are loaded from the query params (logged out)': function() {
var params = '?q=vladvlad';
return this.remote
.setFindTimeout(intern.config.wc.pageLoadTimeout)
.get(require.toUrl(url + params))
// log out
.findByCssSelector('.js-login-link').click()
.end()
.findByCssSelector('.wc-IssueItem:nth-of-type(1) a').getVisibleText()
.then(function(text){
assert.include(text, 'vladvlad', 'The search query results show up on the page.');
})
.end()
.getCurrentUrl()
.then(function(currUrl){
assert.include(currUrl, 'q=vladvlad', 'Our params didn\'t go anywhere.');
});
},

'results are loaded from the query params (logged in)': function() {
var params = '?q=vladvlad';
return this.remote
.setFindTimeout(intern.config.wc.pageLoadTimeout)
.get(require.toUrl(url + params))
// log in
.findByCssSelector('.js-login-link').click()
.end()
.findByCssSelector('.wc-IssueItem:nth-of-type(1) a').getVisibleText()
.then(function(text){
assert.include(text, 'vladvlad', 'The search query results show up on the page.');
Expand Down
8 changes: 6 additions & 2 deletions webcompat/api/endpoints.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,14 @@ def proxy_issues():
params = request.args.copy()

# If there's a q param, then we need to use the Search API
# and load those results. Unfortunately, we restrict search requests
# to logged in users.
# and load those results. For logged in users, we handle this at the
# server level.
if g.user and params.get('q'):
return get_search_results(params.get('q'), params)
# Non-authed users should never get here--the request is made to
# GitHub client-side)--but return out of paranoia anyways.
elif params.get('q'):
abort(404)

if g.user:
issues = github.raw_request('GET', 'repos/{0}'.format(ISSUES_PATH),
Expand Down
34 changes: 24 additions & 10 deletions webcompat/static/js/lib/issue-list.js
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,7 @@ issueList.IssueView = Backbone.View.extend({
'click .js-issue-label': 'labelSearch',
},
_filterRegex: /(stage=(?:new|status-needscontact|status-needsdiagnosis|status-contactready|status-sitewait|status-closed))/ig,
_searchRegex: /&*q=&*/i,
_isLoggedIn: $('body').data('username'),
_loadingIndicator: $('.js-loader'),
_nextButton: $('.js-pagination-next'),
Expand Down Expand Up @@ -321,9 +322,18 @@ issueList.IssueView = Backbone.View.extend({
// get params excluding the leading ?
var urlParams = location.search.slice(1);

if (location.search.length !== 0) {
// There are some params in the URL
if (category = window.location.search.match(this._filterRegex)) {
// There are some params in the URL
if (urlParams.length !== 0) {
if (!this._isLoggedIn && urlParams.match(this._searchRegex)) {
// We're dealing with an un-authed user, with a q param.
// So we bypass our server and request from GitHub to avoid
// being penalized for unauthed Search API requests.
var githubSearchAPI = "https://api.github.com/search/issues";
var paramsArray = _.uniq(urlParams.split('&'));
var normalizedParams = this.issues.normalizeAPIParams(paramsArray);
this.issues.setURLState(githubSearchAPI, normalizedParams);
this.fetchAndRenderIssues();
} else if (category = window.location.search.match(this._filterRegex)) {
// If there was a stage filter match, fire an event which loads results
this.updateModelParams(urlParams);
_.delay(function() {
Expand Down Expand Up @@ -485,6 +495,16 @@ issueList.IssueView = Backbone.View.extend({

this.fetchAndRenderIssues();
},
addParamsToModel: function(paramsArray) {
// this method just puts the params in the model's params property.
// paramsArray is an array of param 'key=value' string pairs
_.forEach(paramsArray, _.bind(function(param) {
var kvArray = param.split('=');
var key = kvArray[0];
var value = kvArray[1];
this.issues.params[key] = value;
}, this));
},
updateModelParams: function(params, options) {
// we convert the params string into an array, splitting
// on '&' in case of multiple params. those are then
Expand All @@ -500,13 +520,7 @@ issueList.IssueView = Backbone.View.extend({
delete this.issues.params['q'];
}

// paramsArray is an array of param 'key=value' string pairs
_.forEach(paramsArray, _.bind(function(param) {
var kvArray = param.split('=');
var key = kvArray[0];
var value = kvArray[1];
this.issues.params[key] = value;
}, this));
this.addParamsToModel(paramsArray);

//broadcast to each of the dropdowns that they need to update
var pageDropdown;
Expand Down
43 changes: 43 additions & 0 deletions webcompat/static/js/lib/models/issue.js
Original file line number Diff line number Diff line change
Expand Up @@ -198,4 +198,47 @@ issueList.IssueCollection = Backbone.Collection.extend({
return null;
}
},
normalizeAPIParams: function(paramsArray) {
/* ported version of normalize_api_params from helpers.py
Normalize GitHub Issues API params to Search API conventions:

Issues API params | Search API converted values
-------------------------|---------------------------------------
state | into q as "state:open", "state:closed"
creator | into q as "author:username"
mentioned | into q as "mentions:username"
direction | order
*/
var params = {};
var qMap = {
state: 'state',
creator: 'author',
mentioned: 'mentions'
};

_.forEach(paramsArray, _.bind(function(param) {
var kvArray = param.split('=');
var key = kvArray[0];
var value = kvArray[1];
params[key] = value;
}, this));

if ('direction' in params) {
params.order = params.direction;
delete params.direction;
}

// The rest need to be added to the "q" param as substrings
_.forEach(qMap, function(val, key) {
if (key in params) {
params.q += ' ' + val + ':' + params[key];
delete params[key];
}
});

// Finally, scope this to our issues repo.
params.q += ' repo:' + repoPath.slice(0,-7);

return params;
}
});