Point search requests to search endpoints
- Renamed browse methods to search. - The name on which an autocompleted resource should be searched is now explicitly declared in the factory. - Search results now check for the existence of "q" so that we show some results if a user is merely filtering on properties. - When a 'q' parameter is passed to the searchresults directive, it populates using the /search endpoint rather than the browse endpoint. Change-Id: I973bfe059852e0d345a60b662cc633270405850e
This commit is contained in:
committed by
Michael Krotscheck
parent
e00531e8e9
commit
89e846d9d1
@@ -37,54 +37,79 @@ angular.module('sb.search').directive('searchResults',
|
||||
$scope.isSearching = false;
|
||||
$scope.searchResults = [];
|
||||
|
||||
// Watch for changing criteria
|
||||
$scope.$watchCollection($parse(args.searchCriteria),
|
||||
function (criteria) {
|
||||
/**
|
||||
* Handle error result.
|
||||
*/
|
||||
function handleErrorResult() {
|
||||
$scope.isSearching = false;
|
||||
}
|
||||
|
||||
// Extract the valid critera from the provided ones.
|
||||
$scope.validCriteria = Criteria
|
||||
.filterCriteria(resourceName, criteria);
|
||||
/**
|
||||
* Handle search result.
|
||||
*
|
||||
* @param results
|
||||
*/
|
||||
function handleSearchResult(results) {
|
||||
$scope.searchResults = results;
|
||||
$scope.isSearching = false;
|
||||
}
|
||||
|
||||
// You have criteria, but they may not be valid.
|
||||
$scope.hasCriteria = criteria.length > 0;
|
||||
/**
|
||||
* Update the results when the criteria change
|
||||
*/
|
||||
function updateResults(criteria) {
|
||||
|
||||
// You have criteria, and all of them are valid for
|
||||
// this resource.
|
||||
$scope.hasValidCriteria =
|
||||
searchWithoutCriteria ||
|
||||
($scope.validCriteria.length === criteria.length &&
|
||||
$scope.hasCriteria);
|
||||
// Extract the valid criteria from the provided ones.
|
||||
$scope.validCriteria = Criteria
|
||||
.filterCriteria(resourceName, criteria);
|
||||
|
||||
// No need to search if our criteria aren't valid.
|
||||
if (!$scope.hasValidCriteria) {
|
||||
$scope.searchResults = [];
|
||||
$scope.isSearching = false;
|
||||
return;
|
||||
}
|
||||
// You have criteria, but they may not be valid.
|
||||
$scope.hasCriteria = criteria.length > 0;
|
||||
|
||||
var params = Criteria.mapCriteria(resourceName,
|
||||
$scope.validCriteria);
|
||||
var resource = $injector.get(resourceName);
|
||||
// You have criteria, and all of them are valid for
|
||||
// this resource.
|
||||
$scope.hasValidCriteria =
|
||||
searchWithoutCriteria ||
|
||||
($scope.validCriteria.length === criteria.length &&
|
||||
$scope.hasCriteria);
|
||||
|
||||
if (!resource) {
|
||||
$log.error('Invalid resource name: ' +
|
||||
resourceName);
|
||||
return;
|
||||
}
|
||||
// No need to search if our criteria aren't valid.
|
||||
if (!$scope.hasValidCriteria) {
|
||||
$scope.searchResults = [];
|
||||
$scope.isSearching = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// Apply paging.
|
||||
params.limit = pageSize;
|
||||
var params = Criteria.mapCriteria(resourceName,
|
||||
$scope.validCriteria);
|
||||
var resource = $injector.get(resourceName);
|
||||
|
||||
if (!resource) {
|
||||
$log.error('Invalid resource name: ' +
|
||||
resourceName);
|
||||
return;
|
||||
}
|
||||
|
||||
// Apply paging.
|
||||
params.limit = pageSize;
|
||||
|
||||
// If we don't actually have search criteria, issue a
|
||||
// browse. Otherwise, issue a search.
|
||||
if (!params.hasOwnProperty('q')) {
|
||||
resource.query(params,
|
||||
function (results) {
|
||||
$scope.searchResults = results;
|
||||
$scope.isSearching = false;
|
||||
},
|
||||
function () {
|
||||
$scope.isSearching = false;
|
||||
}
|
||||
);
|
||||
});
|
||||
handleSearchResult,
|
||||
handleErrorResult);
|
||||
} else {
|
||||
resource.search(params,
|
||||
handleSearchResult,
|
||||
handleErrorResult);
|
||||
}
|
||||
}
|
||||
|
||||
// Watch for changing criteria
|
||||
$scope.$watchCollection(
|
||||
$parse(args.searchCriteria),
|
||||
updateResults);
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -31,10 +31,11 @@ angular.module('sb.services').factory('Project',
|
||||
{id: '@id'}
|
||||
);
|
||||
|
||||
ResourceFactory.applyBrowse(
|
||||
ResourceFactory.applySearch(
|
||||
'Project',
|
||||
resource,
|
||||
{Text: 'name'}
|
||||
'name',
|
||||
{Text: 'q'}
|
||||
);
|
||||
|
||||
return resource;
|
||||
|
||||
151
src/app/services/resource/search.js
Normal file
151
src/app/services/resource/search.js
Normal file
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
* Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* A browse service, which wraps common resources and their typeahead
|
||||
* resolution into a single service that returns a common result format.
|
||||
* It is paired with the Criteria service to provide a consistent data
|
||||
* format to identify resources independent of their actual schema.
|
||||
*/
|
||||
angular.module('sb.services').factory('Search',
|
||||
function ($q, $log, Project, Story, User, Criteria) {
|
||||
'use strict';
|
||||
|
||||
return {
|
||||
|
||||
/**
|
||||
* Search projects by search string.
|
||||
*
|
||||
* @param searchString A string to search by.
|
||||
* @return A promise that will resolve with the search results.
|
||||
*/
|
||||
project: function (searchString) {
|
||||
// Search for projects...
|
||||
var deferred = $q.defer();
|
||||
|
||||
Project.search({q: searchString},
|
||||
function (result) {
|
||||
// Transform the results to criteria tags.
|
||||
var projResults = [];
|
||||
result.forEach(function (item) {
|
||||
projResults.push(
|
||||
Criteria.create('project', item.id, item.name)
|
||||
);
|
||||
});
|
||||
deferred.resolve(projResults);
|
||||
}, function () {
|
||||
deferred.resolve([]);
|
||||
}
|
||||
);
|
||||
|
||||
return deferred.promise;
|
||||
},
|
||||
|
||||
/**
|
||||
* Search users by search string.
|
||||
*
|
||||
* @param searchString A string to search by.
|
||||
* @return A promise that will resolve with the search results.
|
||||
*/
|
||||
user: function (searchString) {
|
||||
|
||||
// Search for users...
|
||||
var deferred = $q.defer();
|
||||
User.search({q: searchString},
|
||||
function (result) {
|
||||
// Transform the results to criteria tags.
|
||||
var userResults = [];
|
||||
result.forEach(function (item) {
|
||||
userResults.push(
|
||||
Criteria.create('user', item.id, item.full_name)
|
||||
);
|
||||
});
|
||||
deferred.resolve(userResults);
|
||||
}, function () {
|
||||
deferred.resolve([]);
|
||||
}
|
||||
);
|
||||
|
||||
return deferred.promise;
|
||||
},
|
||||
|
||||
/**
|
||||
* Search stories by search string.
|
||||
*
|
||||
* @param searchString A string to search by.
|
||||
* @return A promise that will resolve with the search results.
|
||||
*/
|
||||
story: function (searchString) {
|
||||
|
||||
// Search for stories...
|
||||
var deferred = $q.defer();
|
||||
Story.search({q: searchString},
|
||||
function (result) {
|
||||
// Transform the results to criteria tags.
|
||||
var storyResults = [];
|
||||
result.forEach(function (item) {
|
||||
storyResults.push(
|
||||
Criteria.create('story', item.id, item.title)
|
||||
);
|
||||
});
|
||||
deferred.resolve(storyResults);
|
||||
}, function () {
|
||||
deferred.resolve([]);
|
||||
}
|
||||
);
|
||||
|
||||
return deferred.promise;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Search all resources by a provided search string.
|
||||
*
|
||||
* @param searchString
|
||||
* @return A promise that will resolve with the search results.
|
||||
*/
|
||||
all: function (searchString) {
|
||||
var deferred = $q.defer();
|
||||
|
||||
// Clear the criteria
|
||||
var criteria = [];
|
||||
|
||||
// Wrap everything into a collective promise
|
||||
$q.all({
|
||||
projects: this.project(searchString),
|
||||
stories: this.story(searchString),
|
||||
users: this.user(searchString)
|
||||
}).then(function (results) {
|
||||
// Add the returned projects to the results list.
|
||||
results.projects.forEach(function (item) {
|
||||
criteria.push(item);
|
||||
});
|
||||
// Add the returned stories to the results list.
|
||||
results.stories.forEach(function (item) {
|
||||
criteria.push(item);
|
||||
});
|
||||
// Add the returned stories to the results list.
|
||||
results.users.forEach(function (item) {
|
||||
criteria.push(item);
|
||||
});
|
||||
deferred.resolve(criteria);
|
||||
});
|
||||
|
||||
// Return the search promise.
|
||||
return deferred.promise;
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -29,11 +29,12 @@ angular.module('sb.services').factory('Story',
|
||||
{id: '@id'}
|
||||
);
|
||||
|
||||
ResourceFactory.applyBrowse(
|
||||
ResourceFactory.applySearch(
|
||||
'Story',
|
||||
resource,
|
||||
'title',
|
||||
{
|
||||
Text: 'title',
|
||||
Text: 'q',
|
||||
StoryStatus: 'status',
|
||||
Project: 'project_id',
|
||||
User: 'assignee_id'
|
||||
|
||||
@@ -30,10 +30,12 @@ angular.module('sb.services').factory('Task',
|
||||
{id: '@id'}
|
||||
);
|
||||
|
||||
ResourceFactory.applyBrowse(
|
||||
ResourceFactory.applySearch(
|
||||
'Task',
|
||||
resource,
|
||||
null,
|
||||
{
|
||||
Text: 'q',
|
||||
Story: 'story_id',
|
||||
User: 'assignee_id'
|
||||
}
|
||||
|
||||
@@ -31,10 +31,11 @@ angular.module('sb.services').factory('User',
|
||||
{id: '@id'}
|
||||
);
|
||||
|
||||
ResourceFactory.applyBrowse(
|
||||
ResourceFactory.applySearch(
|
||||
'User',
|
||||
resource,
|
||||
{Text: 'full_name'}
|
||||
'full_name',
|
||||
{Text: 'q'}
|
||||
);
|
||||
|
||||
return resource;
|
||||
|
||||
@@ -103,27 +103,23 @@ angular.module('sb.services')
|
||||
|
||||
/**
|
||||
* This method takes an already configured resource, and applies
|
||||
* the static methods necessary to support the criteria browse API.
|
||||
* the static methods necessary to support the criteria search API.
|
||||
* Browse parameters should be formatted as an object containing
|
||||
* 'injector name': 'param'. For example, {'Project': 'project_id'}.
|
||||
*
|
||||
* @param resourceName The explicit resource name of this resource
|
||||
* within the injection scope.
|
||||
* @param resource The configured resource.
|
||||
* @param browseParameters The browse parameters to apply.
|
||||
* @param nameField The name field to use while browsing criteria.
|
||||
* @param searchParameters The search parameters to apply.
|
||||
*/
|
||||
applyBrowse: function (resourceName, resource, browseParameters) {
|
||||
applySearch: function (resourceName, resource, nameField,
|
||||
searchParameters) {
|
||||
|
||||
// List of criteria resolvers which we're building.
|
||||
var criteriaResolvers = [];
|
||||
var browseParameter = null; // Default is ''
|
||||
|
||||
for (var type in browseParameters) {
|
||||
|
||||
// Store the browse parameter for later.
|
||||
if (type === 'Text') {
|
||||
browseParameter = browseParameters[type];
|
||||
}
|
||||
for (var type in searchParameters) {
|
||||
|
||||
// If the requested type exists and has a criteriaResolver
|
||||
// method, add it to the list of resolvable browse criteria.
|
||||
@@ -147,7 +143,7 @@ angular.module('sb.services')
|
||||
|
||||
// If we found a browse parameter, add the ability to use
|
||||
// this resource as a source of criteria.
|
||||
if (!!browseParameter) {
|
||||
if (!!nameField) {
|
||||
/**
|
||||
* Add the criteria resolver method.
|
||||
*/
|
||||
@@ -157,7 +153,7 @@ angular.module('sb.services')
|
||||
|
||||
// build the query parameters.
|
||||
var queryParams = {};
|
||||
queryParams[browseParameter] = searchString;
|
||||
queryParams[nameField] = searchString;
|
||||
|
||||
resource.query(queryParams,
|
||||
function (result) {
|
||||
@@ -167,7 +163,7 @@ angular.module('sb.services')
|
||||
criteriaResults.push(
|
||||
Criteria.create(resourceName,
|
||||
item.id,
|
||||
item[browseParameter])
|
||||
item[nameField])
|
||||
);
|
||||
});
|
||||
deferred.resolve(criteriaResults);
|
||||
@@ -185,13 +181,13 @@ angular.module('sb.services')
|
||||
* The criteria filter.
|
||||
*/
|
||||
resource.criteriaFilter = Criteria
|
||||
.buildCriteriaFilter(browseParameters);
|
||||
.buildCriteriaFilter(searchParameters);
|
||||
|
||||
/**
|
||||
* The criteria map.
|
||||
*/
|
||||
resource.criteriaMap = Criteria
|
||||
.buildCriteriaMap(browseParameters);
|
||||
.buildCriteriaMap(searchParameters);
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user