# containers/Logbook/SelectionFilterHelper.js

## Maintainability

60.63

## Lines of code

181

## Difficulty

43.01

## Estimated Errors

1.31

## Function weight

### By Complexity

### By SLOC

import { DOC_VIEW } from '../../constants/EventTypes.js'; import StringConverterForRegexp from 'escape-string-regexp'; import UI from '../../config/ui/config'; const REGEXP_FILTER_TYPE = 'regexpFilterType'; const EQUALITY_FILTER_TYPE = 'equalityFilterType'; /** * Get selecton filters combining find, sort selection filters for mongoDB query * @param {*} findCriteria what will be the find parameter in mongo query * @param {*} sortCriteria what will be the sort parameter in mongo query * @param {*} view current logbook view */ export function getSelectionFiltersForMongoQuery(findCriteria, sortCriteria, view) { if (!findCriteria) { findCriteria = []; } if (!sortCriteria) { sortCriteria = { [UI.logbook.SORT_EVENTS_BY]: UI.logbook.SORTING_ORDER }; } return { find: getSelectionFiltersBySearchCriteria(findCriteria, view), sort: sortCriteria } } /** * Get the selection filter to be used in mongoDB query which returns all annotations and all notifications */ export function getSelectionFilterForAllAnnotationsAndNotifications() { let filter = {}; let andExpressions = []; andExpressions.push(getNotificationOrAnnotationFilter()); filter['$and'] = andExpressions; return filter; } /** * Get selection filters to be used in mongoDB query * @param {array} criteria user specified search criteria * @param {string} view current view of the logbook */ export function getSelectionFiltersBySearchCriteria(criteria, view) { let filter = {}; let andExpressions = []; // the first part of the AND filter which selects annotation and notification systematically if (view === DOC_VIEW) { andExpressions.push({ $or: [ { type: 'annotation' }, { $and: [ { type: 'notification' }, { previousVersionEvent: { $ne: null } } ] } ] }); } else { andExpressions.push(getNotificationOrAnnotationFilter()); } let userSpecificFilters = getUserSpecificSelectionFilters(criteria); if (userSpecificFilters) { andExpressions.push(userSpecificFilters); } filter['$and'] = andExpressions; return filter; } /** * Generate the user specific part of the selection filters from GUI specified search criteria. * @param {array} criteria search criteria as provided by the combosearch component. When not provided, this indicates that the user has not set any search criteria. * @returns {Object} user specific part of the selection filter query to be used for the mongoDB query */ export function getUserSpecificSelectionFilters(criteria) { let filters = {}; let userSearchANDArray = []; if (criteria && criteria instanceof Array) { criteria.forEach(criterion => { if (criterion.criteria && criterion.search) { if (criterion.criteria.toLowerCase() === 'everywhere') { let orFilter = []; let orFilterItem = popSingleFilter({}, { criteria: 'title', search: criterion.search }, REGEXP_FILTER_TYPE); orFilter.push(orFilterItem); orFilterItem = popSingleFilter({}, { criteria: 'type', search: criterion.search }, REGEXP_FILTER_TYPE); orFilter.push(orFilterItem); orFilterItem = popSingleFilter({}, { criteria: 'category', search: criterion.search }, REGEXP_FILTER_TYPE); orFilter.push(orFilterItem); orFilterItem = popSingleFilter({}, { criteria: 'username', search: criterion.search }, REGEXP_FILTER_TYPE); orFilter.push(orFilterItem); orFilterItem = popSingleFilter({}, { criteria: 'content.text', search: criterion.search }, REGEXP_FILTER_TYPE); orFilter.push(orFilterItem); userSearchANDArray.push({ '$or': orFilter }); } else { let singleFilter = popSingleFilter({}, criterion, REGEXP_FILTER_TYPE); if (singleFilter) { userSearchANDArray.push(singleFilter); } } } }); if (userSearchANDArray.length !== 0) { filters['$and'] = userSearchANDArray; } else { filters = null; } } return filters; } /** * Create the or filter which is used in all requests to get only event which type is annotation of * notification but not attachment. */ function getNotificationOrAnnotationFilter() { let filter = {}; let orFilter = []; let orFilterItem = popSingleFilter({}, { criteria: 'type', search: 'annotation' }, EQUALITY_FILTER_TYPE); orFilter.push(orFilterItem); orFilterItem = popSingleFilter({}, { criteria: 'type', search: 'notification' }, EQUALITY_FILTER_TYPE); orFilter.push(orFilterItem); filter['$or'] = orFilter; return filter; } /** * pop a filter inside a array oof filters. Used for $and and $or filters * @param {Array} filter the array to pop the filter in * @param {*} criterion the criterion which is searched * @param {*} filterType the type of filter, 'regexpFilter' or 'equalityFilter' */ function popSingleFilter(filter, criterion, filterType) { if (criterion.criteria.toLowerCase() === 'author') { filter['username'] = regexpFilterOnSingleCriterion(criterion); } else if (criterion.criteria.toLowerCase() === 'creation date') { if (getDateFilterOnSingleCriterion(criterion)) { filter['creationDate'] = getDateFilterOnSingleCriterion(criterion); } else { return null; } } else if (criterion.criteria.toLowerCase() === 'content') { filter['content.text'] = regexpFilterOnSingleCriterion(criterion); } else { if (filterType === REGEXP_FILTER_TYPE) { filter[criterion.criteria.toLowerCase()] = regexpFilterOnSingleCriterion(criterion); } else if (filterType === EQUALITY_FILTER_TYPE) { filter = equalityFilterOnSingleCriterion(criterion); } } return filter; } /** * A filter used to search a single word inside text, using regexp, not dates * @param {*} criterion the single criterion */ function regexpFilterOnSingleCriterion(criterion) { return { $regex: '.*' + StringConverterForRegexp(criterion.search) + '.*', $options: 'i' }; } function getDateFilterOnSingleCriterion(criterion) { if (criterion.momentDate) { if (criterion.search === 'before') { return { $lt: criterion.momentDate.format('YYYY-MM-DDTHH:mm:ss.SSS') + 'Z' }; } if (criterion.search === 'after') { return { $gte: criterion.momentDate.format('YYYY-MM-DDTHH:mm:ss.SSS') + 'Z' }; } }; return null; } function equalityFilterOnSingleCriterion(criterion) { let filter = {}; if (criterion && criterion.criteria && criterion.search) { filter[criterion.criteria.toLowerCase()] = criterion.search; return filter; }; }