scripts/apps/content-api/directives/ContentAPISearchResultsDirective.ts
import _ from 'lodash';
import {gettext} from 'core/utils';
class LinkFunction {
scope: any;
elem: any;
containerElem: any;
notify: any;
$location: any;
contentApiSearch: any;
search: any;
criteria: any;
constructor(contentApiSearch, search, notify, $location, scope, elem) {
this.scope = scope;
this.elem = elem;
this.containerElem = elem.find('.shadow-list-holder');
this.notify = notify;
this.$location = $location;
this.contentApiSearch = contentApiSearch;
this.search = search;
this.criteria = this.contentApiSearch.getCriteria();
this.queryItems();
this.scope.fetchNext = this.fetchNext.bind(this);
this.scope.refreshList = this.refreshList.bind(this);
// set the watch
this.scope.$watch(() => _.omit(this.$location.search(), ['_id', 'item']),
(newValue, oldValue) => {
if (newValue !== oldValue) {
this.scope.refreshList();
}
}, true);
this.scope.$on('refresh:list', (event, group) => {
this.scope.refreshList();
});
}
/**
* @ngdoc method
* @name sdContentApiSearchResults#_getAggregations
* @private
* @description Set the aggregations args based on filters tab or not.
*/
_getAggregations() {
this.criteria.aggregations = this.scope.tab === 'filters' ? 1 : 0;
}
/**
* @ngdoc method
* @name sdContentApiSearchResults#refreshList
* @public
* @description Refresh the search results
*/
refreshList() {
this.queryItems(null, {force: true});
}
/**
* @ngdoc method
* @name sdContentApiSearchResults#queryItems
* @public
* @description Function for fetching the items in case of first time.
* @return {promise}
*/
queryItems(event?, data?) {
this.criteria = this.contentApiSearch.getCriteria();
this._getAggregations();
return this.contentApiSearch.query(this.criteria).then((items) => {
this.scope.$applyAsync(() => {
this.render(items, null, data && data.force);
});
}, (error) => {
this.notify.error(gettext('Failed to run the query!'));
})
.finally(() => {
this.scope.loading = false;
// update scroll position to top, when forced refresh
if (data && data.force) {
this.containerElem[0].scrollTop = 0;
}
});
}
/**
* @ngdoc method
* @name sdContentApiSearchResults#fetchNext
* @public
* @description Function for fetching next page
*/
fetchNext() {
this.render(null, true);
}
/**
* @ngdoc method
* @name sdContentApiSearchResults#render
* @public
* @param {Array<object>} items - Array of items to display.
* @param {boolean} next - true then fetch next page and update the existing list of items.
* @param {boolean} force - initialize and refresh the list to display.
* @description Fetch the items from backend and display the items.
*/
render(items, next, force?) {
this.scope.loading = true;
const setScopeItems = (_items, _force) => {
this.scope.items = this.search.mergeItems(_items, this.scope.items, next, _force);
this.scope.items._aggregations = _items._aggregations;
this.scope.total = _items._meta.total;
this.scope.loading = false;
};
if (items) {
setScopeItems(items, force);
} else if (next) {
this.scope.loading = true;
this.criteria.page = (this.criteria.page || 0) + 1;
this._getAggregations();
this.contentApiSearch.query(this.criteria)
.then(setScopeItems)
.finally(() => {
this.scope.loading = false;
});
}
}
}
/**
* @ngdoc directive
* @module superdesk.apps.content-api
* @name sdContentApiSearchResults
* @requires contentApiSearch
* @requires search
* @requires notify
* @requires https://docs.angularjs.org/api/ng/service/$location $location
* @description sd-content-api-search-results displays the search based on the change to the route.
*/
export function ContentAPISearchResultsDirective(contentApiSearch, search, notify, $location) {
return {
template: require('scripts/apps/content-api/views/search-results.html'),
link: (scope, elem) => new LinkFunction(contentApiSearch, search, notify, $location, scope, elem),
};
}
ContentAPISearchResultsDirective.$inject = ['contentApiSearch', 'search', 'notify', '$location'];