superdesk/superdesk-client-core

View on GitHub
scripts/apps/contacts/directives/ContactsSearchResultsDirective.ts

Summary

Maintainability
C
1 day
Test Coverage
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<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.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'];