Source:keyword-searcher.service.js

(function () {
    // Keyword Searcher
    angular
        .module('mohistory')
        .service('keywordSearcher', keywordSearcher);
    keywordSearcher.$inject = ['searchFacets', '$http', '$q', '$location', 'configSeparated', 'currentEnvironment'];
    /**
     * Wrapper for http calls to retrieve data for the search interfaces, includes methods to handle
     * both pagination and infinite scrolling.
     * @memberof mohistory
     * @name keywordSearcher
     * @ngdoc service
     */
    function keywordSearcher(searchFacets, $http, $q, $location, configSeparated, currentEnvironment) {
        var service = this;
        /* ----- Variables ----- */
        // Details required to query the APIs given a context
        service.apiConfig = {
            'search-collections': {
                api: configSeparated[currentEnvironment].SERVICES_PATH + 'CCSearchV2/search',
                itemAPI: configSeparated[currentEnvironment].SERVICES_PATH + 'CCSearch/getItem&CCS_id=',
                childList: configSeparated[currentEnvironment].SERVICES_PATH + 'CCSearch/getChildItems',
                eadApi: configSeparated[currentEnvironment].API_BASE + 'collection/',
                reqHeaders: {
                    headers: {
                        'Content-Type': 'application/x-www-form-urlencoded'
                    },
                },
            },
            'search-events': {
                api: configSeparated[currentEnvironment].API_BASE + 'search/events',
                reqHeaders: {
                    headers: {
                        'Content-Type': 'application/x-www-form-urlencoded'
                    },
                },
            },
            'search-all': {
                api: configSeparated[currentEnvironment].API_BASE + 'search',
                reqHeaders: {
                    headers: {
                        'Content-Type': 'application/x-www-form-urlencoded'
                    },
                },
            },
            'search-blog': {
                api: configSeparated[currentEnvironment].API_BASE + 'search/blog',
                reqHeaders: {
                    headers: {
                        'Content-Type': 'application/x-www-form-urlencoded'
                    },
                },
            },
        };
        /* ----- Function Bindings ----- */
        service.getResultsForPage = getResultsForPage;
        service.getCollectionItem = getCollectionItem;
        service.getItemEADFromSearch = getItemEADFromSearch;
        service.getItemChildList = getItemChildList;
        service.getInfinList = getInfinList;
        /* ----- Function Definitions ----- */
        /**
         * Retrieve information for a given collection item.
         * @memberof keywordSearcher
         * @function getCollectionItem
         * @param {string} itemID Slug identifying an item
         * @return {object} a promise which will resolve with data from the API or false
         */
        function getCollectionItem(itemID) {
            var apiInfo = service.apiConfig['search-collections'];
            return $http.get(apiInfo.itemAPI + itemID).then(function (response) {
                return response.data;
            }).catch(function (error) {
                handleError(error, '', error.status);
                return false;
            });
        }
        /**
         * Retrieve EAD information for a given collection item.
         * @memberof keywordSearcher
         * @function getItemEADFromSearch
         * @param {string} collectionID Slug identifying a collection
         * @return {object} a promise which will resolve with data from the API or an empty object
         */
        function getItemEADFromSearch(collectionID) {
            var apiInfo = service.apiConfig['search-collections'];
            return $http.get(apiInfo.eadApi + collectionID).then(function (response) {
                return response.data;
            }).catch(function (error) {
                return {};
            });
        }
        /**
         * Retrieve sub records (i.e. child list) for a given record. This function
         * is called in conjunction with a infinite scroll setup.
         * @memberof keywordSearcher
         * @function getItemChildList
         * @param {string} itemID Slug identifying the item's id
         * @param {number} from Starting index for the returned results
         * @return {object} a promise which will resolve with data from the API or an empty array
         */
        function getItemChildList(itemID, from) {
            var apiInfo = service.apiConfig['search-collections'];
            var params = {
                text: [itemID],
                from: from,
            };
            return $http.post(apiInfo.childList, params, apiInfo.reqHeaders).then(function (response) {
                if (response.data.items) {
                    response.data.total = parseCommaNum(response.data.total);
                    return response.data;
                } else {
                    return [];
                }
            }).catch(function (error) {
                return [];
            });
        }
        /**
         * Get items for search. This function is meant to be called as part of an
         * infinite scroll setup.
         * @memberof keywordSearcher
         * @function getInfinList
         * @param {string} context The context in which the search is being 
         * performed: events, blog, general, collections
         * @param {object} params Object containing all the facets that need to be
         * sent to the API
         * @param {number} from Starting index for the returned results
         * @return {object} a promise which will resolve with data from the API or an empty array
         */
        function getInfinList(context, params, from) {
            params = angular.extend({}, params, {
                text: new Array(params.text),
                from: from,
            });
            var apiInfo = service.apiConfig[context];
            return $http.post(apiInfo.api, JSON.stringify(params),
                apiInfo.reqHeaders).then(function (response) {
                if (response.data.items) {
                    response.data.total = parseCommaNum(response.data.total);
                    service.data = response.data;
                    calculatePage(service.data, params);
                    return service.data;
                } else {
                    return [];
                }
            }).catch(function (error) {
                return 'error'; // normally we would return a $q.reject(), but we want
                // the route to succeed, so we return a value passing it along to the next then in the change were we will handle it.
            });
        }
        /**
         * Get items for search. This function is meant to be called as part of a paged result.
         * @memberof keywordSearcher
         * @function getResultsForPage
         * @param {string} context The context in which the search is being 
         * performed: events, blog, general, collections
         * @param {object} params Object containing all the facets that need to be
         * sent to the API
         * @return {object} a promise which will resolve with data from the API or a string message
         */
        function getResultsForPage(context, params) {
            params = angular.extend({}, params, {
                text: new Array(params.text),
                from: (params.page - 1) * params.size,
            });
            var apiInfo = service.apiConfig[context];
            return $http.post(apiInfo.api,
                JSON.stringify(params),
                apiInfo.reqHeaders).then(function (response) {
                response.data.total = parseCommaNum(response.data.total);
                service.data = response.data;
                calculatePage(service.data, params);
                return service.data;
            }).catch(function (error) {
                return 'error'; // normally we would return a $q.reject(), but we want
                // the route to succeed, so we return a value passing it along to the next then in the change were we will handle it.
            });
        }
        /**
         * Calculate values related to pagination.
         * @memberof keywordSearcher
         * @function calculatePage
         * @param {string} data Results object retrieved from the API
         * @param {object} urlParams Object containing all the facets that need to be
         * sent to the API
         */
        function calculatePage(data, urlParams) {
            var totalPages = Math.ceil(data.total / urlParams.size);
            // Cannot ask for more than 10000 results due to Elastic Search
            data.maxPages = Math.floor(10000 / urlParams.size);
            data.totalPages = totalPages < data.maxPages ? totalPages : (data.maxPages - 1);
            data.curPage = urlParams.from < urlParams.size ? 1 : Math.ceil((urlParams.from + 1) / urlParams.size);
        }
        /**
         * If total results comes back as a string from the API. Remove any commas and
         * convert it to a number.
         * @memberof keywordSearcher
         * @function parseCommaNum
         * @param {string} num Total results returned from the API
         */
        function parseCommaNum(num) {
            if (typeof num !== 'number') {
                num = num.replace(/,/g, "");
                return parseInt(num, 10);
            } else {
                return num;
            }
        }
        /**
         * If something goes wrong redirect to the resolver script.
         * @memberof keywordSearcher
         * @function handleError
         * @param {object} error The problem as reported by the API
         * @param {string} path URL which produced the error
         * @param {string} status Status returned by the API
         */
        function handleError(error, path, status) {
            if (path === '') {
                console.log('Error Redirecting - http://utils.mohistory.org/resolve')
                window.location.href = 'http://utils.mohistory.org/resolve';
            } else {
                console.log('Error Redirecting - http://utils.mohistory.org/resolve' + '?path=' + $location.absUrl() + '&status=' + status)
                window.location.href = 'http://utils.mohistory.org/resolve' + '?path=' + $location.absUrl() + 'status=' + status;
            }
        }
    }
})();