<commit_before>import _ from 'lodash';
import {gettext} from 'core/utils';
import {appConfig} from 'appConfig';
import {ISearchOptions} from '../services/SearchService';
import {IPackagesService} from 'types/Services/Packages';

SearchResults.$inject = [
    '$location',
    'preferencesService',
    'packages',
    'asset',
    '$timeout',
    'api',
    'search',
    'session',
    '$rootScope',
    'superdeskFlags',
    'notify',
];

const HEX_REG_EXP = /[a-f0-9]{24}/;

function isObjectId(value) {
    return value.length === 24 && HEX_REG_EXP.test(value);
}

/**
 * @ngdoc directive
 * @module superdesk.apps.search
 * @name sdSearchResults
 *
 * @requires $location
 * @requires preferencesService
 * @requires packages
 * @requires asset
 * @requires $timeout
 * @requires api
 * @requires search
 * @requires session
 * @requires $rootScope
 *
 * @description Item list with sidebar preview
 */
export function SearchResults(
    $location,
    preferencesService,
    packages: IPackagesService,
    asset,
    $timeout,
    api,
    search,
    session,
    $rootScope,
    superdeskFlags,
    notify,
) { // uff - should it use injector instead?
    var preferencesUpdate = {
        'archive:view': {
            allowed: [
                'mgrid',
                'compact',
            ],
            category: 'archive',
            view: 'mgrid',
            default: 'mgrid',
            label: 'Users archive view format',
            type: 'string',
        },
    };

    return {
        require: '^sdSearchContainer',
        templateUrl: asset.templateUrl('apps/search/views/search-results.html'),
        link: function(scope, elem, attr, controller) {
            var containerElem = elem.find('.shadow-list-holder');
            var GRID_VIEW = 'mgrid',
                LIST_VIEW = 'compact';

            var projections = search.getProjectedFields();
            var multiSelectable = attr.multiSelectable !== undefined;

            scope.previewingBroadcast = false;
            superdeskFlags.flags.previewing = false;

            // allow controller overwrite getSearch
            const getSearch = typeof scope.search.getSearch === 'function'
                ? scope.search.getSearch
                : () => $location.search();

            const queryOptions: ISearchOptions = {
                hidePreviousVersions: scope.search.hideNested === true,
            };

            var criteria = search.query(getSearch(), queryOptions).getCriteria(true),
                oldQuery = _.omit(getSearch(), '_id');

            scope.flags = controller.flags;
            scope.selected = scope.selected || {};
            scope.showHistoryTab = true;

            scope.context = 'search';
            scope.$on('item:deleted:archived', itemDelete);
            scope.$on('item:fetch', queryItems);
            scope.$on('item:update', updateItem);
            scope.$on('item:deleted', scheduleIfShouldUpdate);
            scope.$on('item:unlink', queryItems);
            scope.$on('item:spike', scheduleIfShouldUpdate);
            scope.$on('item:unspike', scheduleIfShouldUpdate);
            scope.$on('item:duplicate', queryItems);
            scope.$on('item:translate', queryItems);
            scope.$on('item:marked_desks', queryItems);

            // used by superdesk-fi
            scope.showtags = attr.showtags !== 'false';

            // Custom components for item fields
            scope.customRender = scope.search.customRender || {};

            scope.$on('ingest:update', (event, args) => {
                if (!scope.showRefresh) {
                    queryItems(event, args);
                }
            });

            scope.$on('content:update', queryItems);
            scope.$on('item:move', scheduleIfShouldUpdate);

            scope.$on('aggregations:changed', queryItems);

            scope.$on('broadcast:preview', (event, args) => {
                scope.previewingBroadcast = true;
                scope.preview(args.item);
            });

            scope.$on('broadcast:created', (event, args) => {
                scope.previewingBroadcast = true;
                queryItems();
                scope.preview(args.item);
            });

            scope.$watch('selected', (newVal, oldVal) => {
                if (!newVal && scope.previewingBroadcast) {
                    scope.previewingBroadcast = false;
                }
            });

            scope.$watch(function getSearchParams() {
                return _.omit(getSearch(), ['_id', 'item', 'action']);
            }, (newValue, oldValue) => {
                if (newValue !== oldValue) {
                    scope.refreshList();
                }
            }, true);

            // public api - called by list when needed
            scope.fetchNext = function() {
                render(null, true);
            };

            var nextUpdate;

            function updateItem(e, data) {
                var item = _.find(scope.items._items, {_id: data.item._id});

                if (item) {
                    angular.extend(item, data.item);
                }
            }

            /**
             * Schedule an update if it's not there yet
             */
            function queryItems(event?, data?) {
                if (!nextUpdate) {
                    if (scope.search.repo.search !== 'local' && !getSearch().q && !(data && data.force)) {
                        return; // ignore updates with external content
                    }

                    scope.loading = true;
                    nextUpdate = $timeout(() => {
                        _queryItems(event, data)
                            .finally(() => {
                                scope.$applyAsync(() => {
                                    nextUpdate = null;
                                });
                            });
                    }, 1000, false);
                }
            }
<commit_msg>avoid refreshing the list for search providers (#3837)<commit_after>import _ from 'lodash';
import {gettext} from 'core/utils';
import {appConfig} from 'appConfig';
import {ISearchOptions} from '../services/SearchService';
import {IPackagesService} from 'types/Services/Packages';

SearchResults.$inject = [
    '$location',
    'preferencesService',
    'packages',
    'asset',
    '$timeout',
    'api',
    'search',
    'session',
    '$rootScope',
    'superdeskFlags',
    'notify',
];

const HEX_REG_EXP = /[a-f0-9]{24}/;

function isObjectId(value) {
    return value != null && value.length === 24 && HEX_REG_EXP.test(value);
}

/**
 * @ngdoc directive
 * @module superdesk.apps.search
 * @name sdSearchResults
 *
 * @requires $location
 * @requires preferencesService
 * @requires packages
 * @requires asset
 * @requires $timeout
 * @requires api
 * @requires search
 * @requires session
 * @requires $rootScope
 *
 * @description Item list with sidebar preview
 */
export function SearchResults(
    $location,
    preferencesService,
    packages: IPackagesService,
    asset,
    $timeout,
    api,
    search,
    session,
    $rootScope,
    superdeskFlags,
    notify,
) { // uff - should it use injector instead?
    var preferencesUpdate = {
        'archive:view': {
            allowed: [
                'mgrid',
                'compact',
            ],
            category: 'archive',
            view: 'mgrid',
            default: 'mgrid',
            label: 'Users archive view format',
            type: 'string',
        },
    };

    return {
        require: '^sdSearchContainer',
        templateUrl: asset.templateUrl('apps/search/views/search-results.html'),
        link: function(scope, elem, attr, controller) {
            var containerElem = elem.find('.shadow-list-holder');
            var GRID_VIEW = 'mgrid',
                LIST_VIEW = 'compact';

            var projections = search.getProjectedFields();
            var multiSelectable = attr.multiSelectable !== undefined;

            scope.previewingBroadcast = false;
            superdeskFlags.flags.previewing = false;

            // allow controller overwrite getSearch
            const getSearch = typeof scope.search.getSearch === 'function'
                ? scope.search.getSearch
                : () => $location.search();

            const queryOptions: ISearchOptions = {
                hidePreviousVersions: scope.search.hideNested === true,
            };

            var criteria = search.query(getSearch(), queryOptions).getCriteria(true),
                oldQuery = _.omit(getSearch(), '_id');

            scope.flags = controller.flags;
            scope.selected = scope.selected || {};
            scope.showHistoryTab = true;

            scope.context = 'search';
            scope.$on('item:deleted:archived', itemDelete);
            scope.$on('item:fetch', queryItems);
            scope.$on('item:update', updateItem);
            scope.$on('item:deleted', scheduleIfShouldUpdate);
            scope.$on('item:unlink', queryItems);
            scope.$on('item:spike', scheduleIfShouldUpdate);
            scope.$on('item:unspike', scheduleIfShouldUpdate);
            scope.$on('item:duplicate', queryItems);
            scope.$on('item:translate', queryItems);
            scope.$on('item:marked_desks', queryItems);

            // used by superdesk-fi
            scope.showtags = attr.showtags !== 'false';

            // Custom components for item fields
            scope.customRender = scope.search.customRender || {};

            scope.$on('ingest:update', (event, args) => {
                if (!scope.showRefresh) {
                    queryItems(event, args);
                }
            });

            scope.$on('content:update', queryItems);
            scope.$on('item:move', scheduleIfShouldUpdate);

            scope.$on('aggregations:changed', queryItems);

            scope.$on('broadcast:preview', (event, args) => {
                scope.previewingBroadcast = true;
                scope.preview(args.item);
            });

            scope.$on('broadcast:created', (event, args) => {
                scope.previewingBroadcast = true;
                queryItems();
                scope.preview(args.item);
            });

            scope.$watch('selected', (newVal, oldVal) => {
                if (!newVal && scope.previewingBroadcast) {
                    scope.previewingBroadcast = false;
                }
            });

            scope.$watch(function getSearchParams() {
                return _.omit(getSearch(), ['_id', 'item', 'action']);
            }, (newValue, oldValue) => {
                if (newValue !== oldValue) {
                    scope.refreshList();
                }
            }, true);

            // public api - called by list when needed
            scope.fetchNext = function() {
                render(null, true);
            };

            var nextUpdate;

            function updateItem(e, data) {
                var item = _.find(scope.items._items, {_id: data.item._id});

                if (item) {
                    angular.extend(item, data.item);
                }
            }

            /**
             * Schedule an update if it's not there yet
             */
            function queryItems(event?, data?) {
                if (isObjectId(scope.search.repo.search)) {
                    // external provider, don't refresh on any event
                    return;
                }

                if (!nextUpdate) {
                    if (scope.search.repo.search !== 'local' && !getSearch().q && !(data && data.force)) {
                        return; // ignore updates with external content
                    }

                    scope.loading = true;
                    nextUpdate = $timeout(() => {
                        _queryItems(event, data)
                            .finally(() => {
                                scope.$applyAsync(() => {
                                    nextUpdate = null;
                                });
                            });
                    }, 1000, false);
                }
            }

{'fraction_non_alphanumeric': 0.12685215673361872, 'fraction_numerical': 0.001975633849193283, 'mean_word_length': 1.6143748655046266, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4409', 'n_tokens_mistral': 3192, 'n_tokens_neox': 3003, 'n_words': 647}