/*
* This file is part of Invenio.
* Copyright (C) 2017 CERN.
*
* Invenio is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* Invenio is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Invenio; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*
* In applying this license, CERN does not
* waive the privileges and immunities granted to it by virtue of its status
* as an Intergovernmental Organization or submit itself to any jurisdiction.
*/
/**
* @ngdoc controller
* @name invenioSearchCtrl
* @namespace invenioSearchCtrl
* @description
* Invenio search controller.
*/
function invenioSearchCtrl($scope, invenioSearchHandler,
invenioSearchAPI) {
// Assign controller to `vm`
var vm = this;
// Parameters
// Initialize search results
vm.invenioSearchResults = {};
// Initialize error results
vm.invenioSearchErrorResults = {};
// Search Loading - if invenioSearch has the state loading
vm.invenioSearchLoading = true;
// Search Error - if invenioSearch has the state error
vm.invenioSearchError = {};
// Search Initialized - if the invenioSearch is initialized
vm.invenioSearchInitialized = false;
// Search Query Args - invenioSearch query arguments
vm.invenioSearchArgs = {};
vm.invenioSearchSortArgs = {};
// Initialize current search args
vm.invenioSearchCurrentArgs = {
method: 'GET',
params: {
page: 1,
size: 20,
}
};
////////////
// Functions
/**
* Get url parameters.
* @memberof invenioSearchCtrl
* @function invenioSearchGetUrlArgs
* @returns {Object} The url parameters.
*/
function invenioSearchGetUrlArgs() {
return invenioSearchHandler.get();
}
/**
* Do the search
* @memberof invenioSearchCtrl
* @function invenioDoSearch
*/
function invenioDoSearch() {
// Broadcast search requested
$scope.$broadcast('invenio.search.requested');
// Set state to loading
vm.invenioSearchLoading = true;
// Clear any previous errors
vm.invenioSearchError = {};
vm.invenioSearchErrorsResults = {};
/**
* After the request finish proccesses
* @memberof invenioDoSearch
* @function clearRequest
*/
function clearRequest() {
vm.invenioSearchLoading = false;
// Broadcast the search finished
$scope.$broadcast('invenio.search.finished');
}
/**
* After a successful request
* @memberof invenioDoSearch
* @function successfulRequest
* @param {Object} response - The search request response.
*/
function successfulRequest(response) {
// Broadcast the success
$scope.$broadcast('invenio.search.success', response);
}
/**
* After an errored request
* @memberof invenioDoSearch
* @function erroredRequest
* @param {Object} response - The search request response.
*/
function erroredRequest(response) {
// Broadcast the error
$scope.$broadcast('invenio.search.error', response);
}
invenioSearchAPI
.search(vm.invenioSearchCurrentArgs, vm.invenioSearchHiddenParams)
.then(successfulRequest, erroredRequest)
.finally(clearRequest);
}
/**
* Parse query string args from a full URL
* @memberof invenioSearchCtrl
* @function parseURLQueryString
* @param {String} url - The URL to parse.
*/
function parseURLQueryString(url) {
var query_string = (url.split('?')[1] || '').split('&');
var data = {};
for (var i = 0; i < query_string.length; i += 1) {
var param = (query_string[i] || '').split('=');
var key = decodeURIComponent(param[0] || '');
if (key) {
data[key] = decodeURIComponent(param[1] || '');
}
}
return data;
}
/**
* Process a search error
* @memberof invenioSearchCtrl
* @function invenioSearchErrorHandler
* @param {Object} evt - The event object.
* @param {Object} response - The error response.
*/
function invenioSearchErrorHandler(evt, response) {
vm.invenioSearchErrorResults = response.data;
// Set the new error
vm.invenioSearchError = evt;
}
/**
* Process a search success
* @memberof invenioSearchCtrl
* @function invenioSearchSuccessHandler
* @param {Object} evt - The event object.
* @param {Object} response - The success response.
*/
function invenioSearchSuccessHandler(evt, response) {
// Set results
vm.invenioSearchResults = response.data;
// Set error to none
vm.invenioSearchErrorResults = {};
// Save parameters from request
if (response.data.links) {
var data = parseURLQueryString(response.data.links.self);
if (data['page']) {
data['page'] = parseInt(data['page']);
}
if (data['size']) {
data['size'] = parseInt(data['size']);
}
delete data['q'];
if (!angular.equals(vm.invenioSearchCurrentArgs, data)) {
vm.invenioSearchSortArgs = data;
}
}
}
/**
* Process the initialization
* @memberof invenioSearchCtrl
* @function invenioSearchInitialization
* @param {Object} evt - The event object.
* @param {Object} params - The search parameters.
*/
function invenioSearchInitialization(evt, params) {
vm.invenioSearchCurrentArgs = angular.merge(
{},
vm.invenioSearchCurrentArgs,
params
);
vm.invenioSearchArgs = angular.merge(
{},
vm.invenioSearchCurrentArgs.params
);
// Update url if is not disabled
if (!vm.disableUrlHandler) {
// Update url
invenioSearchHandler.set(vm.invenioSearchArgs);
// Repalce url, resolves browser's back button issues
invenioSearchHandler.replace();
}
// Update searcbox query
vm.userQuery = vm.invenioSearchArgs.q;
// Invenio Search is now initialized
vm.invenioSearchInitialized = true;
// Do the initial search
vm.invenioDoSearch();
// Broadcast initialiazation
$scope.$broadcast('invenio.search.initialiazed');
}
/**
* Process the search request
* @memberof invenioSearchCtrl
* @function invenioSearchRequestSearch
* @param {Object} evt - The event object.
* @param {Object} params - The search parameters.
* @param {Boolean} force - Ommit merge and force search with parameters.
*/
function invenioSearchRequestSearch(evt, params, force) {
// If force (mostly comming from the url overwrite everything
if (force !== undefined && force === true) {
vm.invenioSearchCurrentArgs.params = angular.copy(params);
} else {
// Otherwise just merge
// If the page is the same and the query different reset it
if (vm.invenioSearchCurrentArgs.params.page === params.page) {
params.page = 1;
}
// FIXME: Maybe loDash?
angular.forEach(params, function(value, key) {
vm.invenioSearchCurrentArgs.params[key] = value;
});
}
// InvenioSearchArgs update
vm.invenioSearchArgs = angular.copy(
vm.invenioSearchCurrentArgs.params
);
// Update url if is not disabled
if (!vm.disableUrlHandler) {
// Update url
invenioSearchHandler.set(vm.invenioSearchCurrentArgs.params);
}
// Update searcbox query
vm.userQuery = vm.invenioSearchArgs.q;
// Do the search
vm.invenioDoSearch();
}
/**
* Process the search URL request
* @memberof invenioSearchCtrl
* @function invenioSearchRequestFromLocation
* @param {Object} evt - The event object.
* @param {String} before - The current url.
* @param {String} after - The new url.
*/
function invenioSearchRequestFromLocation(evt, before, after) {
if (!vm.disableUrlHandler) {
// When location changed check if there is any difference
var urlArgs = invenioSearchHandler.get();
if (!angular.equals(urlArgs, vm.invenioSearchCurrentArgs.params)) {
// Request a search
$scope.$broadcast('invenio.search.request', urlArgs, true);
}
}
}
/**
* Process the search URL request
* @memberof invenioSearchCtrl
* @function invenioSearchRequestFromChange
* @param {Object} evt - The event object.
* @param {Object} params - The requested search parameters.
*/
function invenioSearchRequestFromChange(evt, params) {
// Get the current and apply the changes
var current = angular.copy(vm.invenioSearchCurrentArgs.params);
angular.forEach(params, function(value, key) {
current[key] = angular.copy(params[key]);
});
if (!angular.equals(vm.invenioSearchCurrentArgs.params, current)) {
// Request a search
$scope.$broadcast('invenio.search.request', current);
}
}
/**
* Process the search URL request
* @memberof invenioSearchCtrl
* @function invenioSearchRequestFromInternal
* @param {Object} before - The current object.
* @param {Object} after - The new object.
*/
function invenioSearchRequestFromInternal(after, before) {
// When the vm invenioSearchArgs changed
if (!angular.equals(after, vm.invenioSearchCurrentArgs.params)) {
// Request a search
$scope.$broadcast('invenio.search.request', after);
}
}
////////////
// Assignments
// Search URL arguments
vm.invenioSearchGetUrlArgs = invenioSearchGetUrlArgs;
// Invenio Do Search
vm.invenioDoSearch = invenioDoSearch;
// URL Parser
vm.parseURLQueryString = parseURLQueryString;
////////////
// Listeners
// When invenio.search initialazation request
$scope.$on('invenio.search.initialazation', invenioSearchInitialization);
// When the search was requested
$scope.$on('invenio.search.request', invenioSearchRequestSearch);
// When the search was successful
$scope.$on('invenio.search.success', invenioSearchSuccessHandler);
// When the search errored
$scope.$on('invenio.search.error', invenioSearchErrorHandler);
// When change parameters have been requested
$scope.$on('invenio.search.params.change', invenioSearchRequestFromChange);
// When URL parameters changed
$scope.$on('$locationChangeStart', invenioSearchRequestFromLocation);
////////////
// Watchers
// When invenioSearchArgs.params has changed
$scope.$watch(
'vm.invenioSearchArgs', invenioSearchRequestFromInternal, true
);
}
invenioSearchCtrl.$inject = [
'$scope', 'invenioSearchHandler', 'invenioSearchAPI'
];
angular.module('invenioSearch.controllers')
.controller('invenioSearchCtrl', invenioSearchCtrl);