import _ from 'lodash'; import {getUrlParameters} from '../constants'; import {gettext} from 'core/utils'; class LinkFunction { scope: any; elem: any; containerElem: any; notify: any; $location: any; $timeout: any; contacts: any; search: any; criteria: any; constructor(contacts, search, notify, $location, $timeout, scope, elem) { this.scope = scope; this.elem = elem; this.containerElem = elem.find('.contacts-list__holder'); this.notify = notify; this.$location = $location; this.$timeout = $timeout; this.contacts = contacts; this.search = search; this.criteria = this.contacts.getCriteria(); this.queryItems(); this.scope.fetchNext = this.fetchNext.bind(this); this.scope.refreshList = this.refreshList.bind(this); this.scope.$watch(() => _.omit(this.$location.search(), '_id'), (newValue, oldValue) => { if (newValue !== oldValue && this.$location.path() === '/contacts') { this.scope.refreshList({force: true}); } }, true); angular.forEach(['refresh:list'], (evt) => { this.scope.$on(evt, (event) => { this.scope.refreshList({force: true}); }); }); this.scope.$on('contacts:update', this.scope.refreshList); this.scope.$on('contacts:create', this.scope.refreshList); this.scope.urlParams = getUrlParameters(); } /** * @ngdoc method * @name sdContactsSearchResults#refreshList * @public * @description Refresh the search results */ refreshList(data) { this.$timeout(() => { this.queryItems(null, data); }, 800, false); } /** * @ngdoc method * @name sdContactsSearchResults#queryItems * @public * @description Function for fetching the items. * @return {promise} */ queryItems(event?, data?) { this.criteria = this.contacts.getCriteria(); if (!(data && data.force) && this.scope.items && this.scope.items._items.length > this.criteria.max_results) { this.criteria.max_results = this.scope.items._items.length; } return this.contacts.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 sdContactsSearchResults#fetchNext * @public * @description Function for fetching next page */ fetchNext() { this.render(null, true); } /** * @ngdoc method * @name sdContactsSearchResults#render * @public * @param {Array} 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.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.contacts.query(this.criteria) .then(setScopeItems) .finally(() => { this.scope.loading = false; }); } } } /** * @ngdoc directive * @module superdesk.apps.contacts * @name sdContactsSearchResults * @requires Contacts service * @requires search * @requires notify * @requires https://docs.angularjs.org/api/ng/service/$location $location * @description sd-contacts-search-results displays the search based on the change to the route. */ export function ContactsSearchResultsDirective(contacts, search, notify, $location, $timeout) { return { template: require('scripts/apps/contacts/views/search-results.html'), link: (scope, elem) => new LinkFunction(contacts, search, notify, $location, $timeout, scope, elem), }; } ContactsSearchResultsDirective.$inject = ['contacts', 'search', 'notify', '$location', '$timeout'];