GitLab will be upgraded on June 23th evening. During the upgrade the service will be unavailable, sorry for the inconvenience.

Commit 845aef2b authored by Marjolaine Bodin's avatar Marjolaine Bodin

#487 search events bbased on new categoryTypes array

parent ff4f5bf0
Pipeline #46553 passed with stage
in 3 minutes and 31 seconds
......@@ -6,6 +6,8 @@ import {
EVENT_CATEGORY_INFO,
ANNOTATION,
NOTIFICATION,
EVENT_CATEGORY_COMMENT,
EVENT_CATEGORY_DEBUG,
} from '../../../constants/eventTypes';
import { useDispatch, useSelector } from 'react-redux';
import styles from './EventFilterPanel.module.css';
......@@ -15,12 +17,18 @@ const checkBoxes = [
{
name: 'showComments',
label: 'Comments',
value: [{ type: ANNOTATION }],
value: [
{ type: ANNOTATION },
{ type: NOTIFICATION, category: EVENT_CATEGORY_COMMENT },
],
},
{
name: 'showInformation',
label: 'Information',
value: [{ type: NOTIFICATION, category: EVENT_CATEGORY_INFO }],
value: [
{ type: NOTIFICATION, category: EVENT_CATEGORY_INFO },
{ type: NOTIFICATION, category: EVENT_CATEGORY_DEBUG },
],
},
{
name: 'showError',
......
......@@ -16,13 +16,7 @@ import UserMessage from '../../components/UserMessage';
*/
function EventsProvider(props) {
const { children, investigationId, sortingFilter } = props;
const {
searchCriteria,
forceReload,
filterType,
filterCategory,
page,
} = props;
const { searchCriteria, forceReload, categoryTypes, page } = props;
const [downloadedEvents, setDownloadedEvents] = useState({}); //{ isFetching: bool, events: [], startIndex: Number, endIndex: Number, isError: bool}
......@@ -38,8 +32,7 @@ function EventsProvider(props) {
investigationId,
sortingFilter,
searchCriteria,
filterType,
filterCategory,
categoryTypes,
forceReload,
]);
......@@ -48,17 +41,16 @@ function EventsProvider(props) {
return;
}
const selectionFilter = buildSearchFilter(
searchCriteria,
filterType,
filterCategory
);
const selectionFilter = buildSearchFilter(searchCriteria, categoryTypes);
setDownloadedEvents({ isFetching: true });
getEvents(selectionFilter, sortingFilter, skip, investigationId)
.then(({ data }) => {
// Filter notifications that have been annotated which annotation is empty
if (filterType.length === 1 && filterType[0] === ANNOTATION) {
if (
categoryTypes.length === 1 &&
categoryTypes[0].type === ANNOTATION
) {
// debugger;
data = data.filter(
(event) =>
......@@ -83,8 +75,7 @@ function EventsProvider(props) {
skip,
sortingFilter,
searchCriteria,
filterType,
filterCategory,
categoryTypes,
isDownloaded,
isFetching,
isError,
......@@ -127,8 +118,7 @@ EventsProvider.propTypes = {
/** search criteria */
searchCriteria: PropTypes.array,
/** filter criteria, by type and by category */
filterType: PropTypes.array,
filterCategory: PropTypes.array,
categoryTypes: PropTypes.array,
/** Whether the events must be forced reloaded. (when no others props changed such as page, sorting filter, searchCriteria, ...) */
forceReload: PropTypes.bool,
};
......
......@@ -17,7 +17,6 @@ import PublicEventPanel from '../../components/Logbook/PublicEventPanel';
import UserMessage from '../../components/UserMessage';
import UI from '../../config/ui';
import {
ANNOTATION,
LOGBOOK_CONTEXT_NAME_PROPOSAL,
NEW_EVENT_INVISIBLE,
NEW_EVENT_VISIBLE,
......@@ -66,8 +65,6 @@ export class LogbookContainerClass extends React.Component {
sortingFilter: { [UI.logbook.SORT_EVENTS_BY]: UI.logbook.SORTING_ORDER }, // current sorting flter
searchCriteria: [],
forceReloadEventList: false,
filterType: [ANNOTATION],
filterCategory: [],
};
this.createEvent = this.createEvent.bind(this);
......@@ -99,8 +96,6 @@ export class LogbookContainerClass extends React.Component {
page,
errorMessage,
forceReloadEventList,
filterType,
filterCategory,
categoryTypes,
} = this.state;
......@@ -131,7 +126,7 @@ export class LogbookContainerClass extends React.Component {
onCallbackSuccess={this.onNewEventCountReceived}
periodicCallback={(onSuccess, onFailure) => {
this.getEventCountBySelectionFilter(
buildSearchFilter(searchCriteria, filterType, filterCategory)
buildSearchFilter(searchCriteria, categoryTypes)
).then(
(eventCount) => onSuccess(eventCount),
(error) => onFailure(error)
......@@ -168,8 +163,7 @@ export class LogbookContainerClass extends React.Component {
selectionFilter={getSelectionFiltersForMongoQuery(
searchCriteria,
sortingFilter,
filterType,
filterCategory
categoryTypes
)}
sessionId={user.sessionId}
setNewEventVisibility={this.setNewEventVisibility}
......@@ -233,8 +227,7 @@ export class LogbookContainerClass extends React.Component {
<EventsProvider
page={page}
searchCriteria={searchCriteria}
filterType={filterType}
filterCategory={filterCategory}
categoryTypes={categoryTypes}
sortingFilter={sortingFilter}
forceReload={forceReloadEventList}
investigationId={investigation.id}
......@@ -271,7 +264,7 @@ export class LogbookContainerClass extends React.Component {
*/
componentDidMount() {
const { releaseDate } = this.props.investigation;
const { searchCriteria, filterType, filterCategory } = this.state;
const { searchCriteria, categoryTypes } = this.state;
const isReleased = !!releaseDate && moment().isAfter(releaseDate);
......@@ -281,7 +274,7 @@ export class LogbookContainerClass extends React.Component {
});
this.getEventCountBySelectionFilter(
buildSearchFilter(searchCriteria, filterType, filterCategory)
buildSearchFilter(searchCriteria, categoryTypes)
).then((eventCount) => {
this.setState({
allEventsCountAtLastRefresh: parseInt(eventCount, 10),
......@@ -375,11 +368,7 @@ export class LogbookContainerClass extends React.Component {
this.setState({ searchCriteria, page: 1 });
this.getEventCountBySelectionFilter(
buildSearchFilter(
searchCriteria,
this.state.filterType,
this.state.filterCategory
)
buildSearchFilter(searchCriteria, this.state.categoryTypes)
).then((eventCount) => {
this.setState({ eventCountBySelectionFilter: parseInt(eventCount, 10) });
});
......@@ -419,21 +408,14 @@ export class LogbookContainerClass extends React.Component {
this.setState({ isShowingPublicEventUI: false });
}
filterEvents(filterTypes, filterCategories) {
filterEvents(categoryType) {
this.setState({
filterType: filterTypes,
filterCategory: filterCategories,
categoryTypes: categoryType,
page: 1,
});
console.log(filterTypes);
console.log(filterCategories);
this.getEventCountBySelectionFilter(
buildSearchFilter(
this.state.searchCriteria,
filterTypes,
filterCategories
)
buildSearchFilter(this.state.searchCriteria, categoryType)
).then((eventCount) => {
this.setState({
allEventsCountAtLastRefresh: parseInt(eventCount, 10),
......@@ -446,12 +428,7 @@ export class LogbookContainerClass extends React.Component {
* Function triggered whne the user clicks in the menu to change to event sorting order
*/
flipEventsSortingOrder() {
const {
sortingFilter,
searchCriteria,
filterType,
filterCategory,
} = this.state;
const { sortingFilter, searchCriteria, categoryTypes } = this.state;
const newSortingFilter = {};
const sortingCriteria = Object.keys(sortingFilter)[0];
newSortingFilter[sortingCriteria] = getSortingOrder(sortingFilter) * -1;
......@@ -459,7 +436,7 @@ export class LogbookContainerClass extends React.Component {
this.setState({ sortingFilter: newSortingFilter });
this.getEventCountBySelectionFilter(
buildSearchFilter(searchCriteria, filterType, filterCategory)
buildSearchFilter(searchCriteria, categoryTypes)
).then((eventCount) => {
this.setState({ eventCountBySelectionFilter: parseInt(eventCount) });
});
......@@ -543,7 +520,7 @@ export class LogbookContainerClass extends React.Component {
* @param {*} event event to be created or updated
*/
onSaveButtonClicked(event) {
const { searchCriteria, filterType, filterCategory } = this.state;
const { searchCriteria, categoryTypes } = this.state;
if (this.state.event) {
//editing an event
this.updateEvent(event).then(() => {
......@@ -563,7 +540,7 @@ export class LogbookContainerClass extends React.Component {
});
this.getEventCountBySelectionFilter(
buildSearchFilter(searchCriteria, filterType, filterCategory)
buildSearchFilter(searchCriteria, categoryTypes)
).then((eventCount) =>
this.setState({
eventCountBySelectionFilter: parseInt(eventCount),
......@@ -571,7 +548,7 @@ export class LogbookContainerClass extends React.Component {
);
this.getEventCountBySelectionFilter(
buildSearchFilter([], filterType, filterCategory)
buildSearchFilter([], categoryTypes)
).then((eventCount) =>
this.setState({
allEventsCountAtLastRefresh: parseInt(eventCount),
......
......@@ -10,13 +10,12 @@ 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
* @param {*} filterTypeCategory array of filter on event type/category
*/
export function getSelectionFiltersForMongoQuery(
findCriteria,
sortCriteria,
filterType,
filterCategory
filterTypeCategory
) {
if (!findCriteria) {
findCriteria = [];
......@@ -26,7 +25,7 @@ export function getSelectionFiltersForMongoQuery(
}
return {
find: buildSearchFilter(findCriteria, filterType, filterCategory),
find: buildSearchFilter(findCriteria, filterTypeCategory),
sort: sortCriteria,
};
}
......@@ -45,15 +44,14 @@ export function getSelectionFilterForAllAnnotationsAndNotifications() {
/**
* builds the selection filter based on filter on events type / category and user search criteria
* @param {*} criteria search criteria as provided by the combosearch component.
* @param {*} filterType array of filter on event type
* @param {*} filterCategory array of filter on event category
* @param {*} filterTypeCategory array of filter on event type/category
* @returns {Object} selection filter query to be used
*/
export function buildSearchFilter(criteria, filterType, filterCategory) {
export function buildSearchFilter(criteria, filterTypeCategory) {
const filter = {};
const andExpressions = [];
// the first part of the AND filter which selects annotation and notification systematically
andExpressions.push(buildEventFilter(filterType, filterCategory));
andExpressions.push(buildEventFilter(filterTypeCategory));
const userSpecificFilters = getUserSpecificSelectionFilters(criteria);
if (userSpecificFilters) {
......@@ -65,95 +63,63 @@ export function buildSearchFilter(criteria, filterType, filterCategory) {
/**
* builds the selection filter based on filter on events type / category
* @param {*} filterType array of filter on event type
* @param {*} filterCategory array of filter on event category
* @param {*} filterTypeCategory array of filter on event type/category
* @returns {Object} selection filter query to be used
*/
export function buildEventFilter(filterType, filterCategory) {
export function buildEventFilter(filterTypeCategory) {
const filter = {};
if (
isArrayUndefinedOrEmpty(filterType) ||
(isFilterOnlyNotification(filterType) &&
isArrayUndefinedOrEmpty(filterCategory))
) {
if (isArrayUndefinedOrEmpty(filterTypeCategory)) {
return buildNoTypeFilter();
}
const orFilter = [];
Array.prototype.forEach.call(filterType, (filter) => {
if (filter === ANNOTATION) {
orFilter.push(buildEventFilterForUserComment());
}
if (filter === NOTIFICATION) {
orFilter.push(buildEventFilterForNotifcation(filterCategory));
}
Array.prototype.forEach.call(filterTypeCategory, (filter) => {
orFilter.push(buildSingleEventFilter(filter));
});
filter.$or = orFilter;
return filter;
}
function isFilterOnlyNotification(filterType) {
return filterType.length === 1 && filterType[0] === NOTIFICATION;
}
function isArrayUndefinedOrEmpty(array) {
return !array || array.length === 0;
}
function buildNoTypeFilter() {
function buildSingleEventFilter(singleFilter) {
if (singleFilter.type === ANNOTATION && !singleFilter.category) {
return buildEventFilterForUserComment();
}
const filter = {};
const andExpressions = [];
const filterItem = popSingleFilter(
{},
{ criteria: 'type', search: 'undefined' },
{ criteria: 'type', search: singleFilter.type },
EQUALITY_FILTER_TYPE
);
andExpressions.push(filterItem);
if (singleFilter.category) {
const filterItem = popSingleFilter(
{},
{ criteria: 'category', search: singleFilter.category },
EQUALITY_FILTER_TYPE
);
andExpressions.push(filterItem);
}
filter.$and = andExpressions;
return filter;
}
/**
* builds the selection filter for notification events
* @param {*} filterCategory array of filter on event category
* @returns {Object} selection filter query to be used
*/
export function buildEventFilterForNotifcation(filterCategory) {
function isArrayUndefinedOrEmpty(array) {
return !array || array.length === 0;
}
function buildNoTypeFilter() {
const filter = {};
if (!filterCategory || filterCategory.length === 0) {
return filter;
}
const andExpressions = [];
const filterItem = popSingleFilter(
{},
{ criteria: 'type', search: NOTIFICATION },
{ criteria: 'type', search: 'undefined' },
EQUALITY_FILTER_TYPE
);
andExpressions.push(filterItem);
andExpressions.push(buildEventCategoryFilter(filterCategory));
filter.$and = andExpressions;
return filter;
}
/**
* builds the selection filter based on category
* @param {*} filterCategory array of filter on event category
* @returns {Object} selection filter query to be used
*/
export function buildEventCategoryFilter(filterCategory) {
const filter = {};
const orFilter = [];
Array.prototype.forEach.call(filterCategory, (filter) => {
const orFilterItem = popSingleFilter(
{},
{ criteria: 'category', search: filter },
EQUALITY_FILTER_TYPE
);
orFilter.push(orFilterItem);
});
filter.$or = orFilter;
return filter;
}
/**
* builds the selection filter for annotation events + notification with previous events
* @returns {Object} selection filter query to be used
......
......@@ -5,8 +5,8 @@ import {
} from '../constants/actionTypes';
import {
ANNOTATION,
EVENT_CATEGORY_COMMENT,
EVENT_CATEGORY_ERROR,
EVENT_CATEGORY_INFO,
NOTIFICATION,
} from '../constants/eventTypes';
......@@ -18,7 +18,7 @@ const initialState = {
},
categoryTypes: [
{ type: ANNOTATION },
{ type: NOTIFICATION, category: EVENT_CATEGORY_INFO },
{ type: NOTIFICATION, category: EVENT_CATEGORY_COMMENT },
{ type: NOTIFICATION, category: EVENT_CATEGORY_ERROR },
],
};
......
......@@ -161,13 +161,7 @@ describe('EventsProviderUnitTests', () => {
*/
function getWrapper(props) {
let { forceReload, investigationId, page, setErrorMessage } = props;
let {
sessionId,
searchCriteria,
filterType,
filterCategory,
sortingFilter,
} = props;
let { sessionId, searchCriteria, categoryTypes, sortingFilter } = props;
if (props) {
page = page || 1;
......@@ -177,8 +171,7 @@ function getWrapper(props) {
sortingFilter = sortingFilter || { _id: -1 };
forceReload = forceReload || false;
searchCriteria = searchCriteria || [];
filterType = filterType || [ANNOTATION];
filterCategory = filterCategory || [];
categoryTypes = categoryTypes || [{ type: ANNOTATION }];
const FakeEventList = function () {
return <div> </div>;
......@@ -198,8 +191,7 @@ function getWrapper(props) {
sortingFilter={sortingFilter}
setErrorMessage={setErrorMessage}
searchCriteria={searchCriteria}
filterType={filterType}
filterCategory={filterCategory}
categoryTypes={categoryTypes}
forceReload={forceReload}
>
{(events) => <FakeEventList events={events} />}
......
......@@ -42,8 +42,7 @@ describe('selectionFilterHelper', () => {
getSelectionFiltersForMongoQuery(
element.criteria,
{ [element.SORT_EVENTS_BY]: element.SORTING_ORDER },
element.filterType,
element.filterCategory
element.filterTypeCategory
)
).toEqual(element.expected);
next();
......@@ -67,41 +66,21 @@ describe('selectionFilterHelper', () => {
});
});
describe('buildEventCategoryFilter', () => {
/* describe('buildSingleEventFilter', () => {
describe('handle errors', () => {
it.each(
resources.buildEventCategoryFilter,
resources.buildSingleEventFilter,
'[note: %s ]',
['description'],
(element, next) => {
const buildEventCategoryFilter = require('../../containers/Logbook/SelectionFilterHelper')
.buildEventCategoryFilter;
expect(buildEventCategoryFilter(element.filterCategory)).toEqual(
element.expected
);
next();
}
);
});
});
describe('buildEventFilterForNotifcation', () => {
describe('handle errors', () => {
it.each(
resources.buildEventFilterForNotifcation,
'[note: %s ]',
['description'],
(element, next) => {
const buildEventFilterForNotifcation = require('../../containers/Logbook/SelectionFilterHelper')
.buildEventFilterForNotifcation;
expect(
buildEventFilterForNotifcation(element.filterCategory)
).toEqual(element.expected);
const buildSingleEventFilter = require('../../containers/Logbook/SelectionFilterHelper')
.buildSingleEventFilter;
expect(buildSingleEventFilter(element.filter)).toEqual(element.expected);
next();
}
);
});
});
});*/
describe('buildEventFilter', () => {
describe('handle errors', () => {
......@@ -112,9 +91,9 @@ describe('selectionFilterHelper', () => {
(element, next) => {
const buildEventFilter = require('../../containers/Logbook/SelectionFilterHelper')
.buildEventFilter;
expect(
buildEventFilter(element.filterType, element.filterCategory)
).toEqual(element.expected);
expect(buildEventFilter(element.filterTypeCategory)).toEqual(
element.expected
);
next();
}
);
......@@ -131,11 +110,7 @@ describe('selectionFilterHelper', () => {
const buildSearchFilter = require('../../containers/Logbook/SelectionFilterHelper')
.buildSearchFilter;
expect(
buildSearchFilter(
element.criteria,
element.filterType,
element.filterCategory
)
buildSearchFilter(element.criteria, element.filterTypeCategory)
).toEqual(element.expected);
next();
}
......
......@@ -3,7 +3,6 @@ import {
EVENT_CATEGORY_COMMANDLINE,
EVENT_CATEGORY_COMMENT,
EVENT_CATEGORY_ERROR,
EVENT_CATEGORY_INFO,
ANNOTATION,
NOTIFICATION,
} from '../../../constants/eventTypes';
......@@ -482,8 +481,7 @@ module.exports = {
criteria: [],
SORT_EVENTS_BY: 'creationDate',
SORTING_ORDER: -1,
filterType: [ANNOTATION],
filterCategory: [],
filterTypeCategory: [{ type: ANNOTATION }],
expected: {
find: {
$and: [SINGLE_ANNOTATION_FILTER],
......@@ -496,8 +494,7 @@ module.exports = {
criteria: [],
SORT_EVENTS_BY: '_id',
SORTING_ORDER: 1,
filterType: [ANNOTATION],
filterCategory: [],
filterTypeCategory: [{ type: ANNOTATION }],
expected: {
find: {
$and: [SINGLE_ANNOTATION_FILTER],
......@@ -510,8 +507,7 @@ module.exports = {
criteria: [{ criteria: 'Title', search: 'title 1', selectText: 'Title' }],
SORT_EVENTS_BY: 'creationDate',
SORTING_ORDER: -1,
filterType: [ANNOTATION],
filterCategory: [],
filterTypeCategory: [{ type: ANNOTATION }],
expected: {
find: {
$and: [
......@@ -531,90 +527,21 @@ module.exports = {
},
],
buildEventCategoryFilter: [
{
description: 'returns the event filter for category with empty array',
filterCategory: [],
expected: {
$or: [],
},
},
{
description: 'returns the event filter for category with one category',
filterCategory: [EVENT_CATEGORY_COMMENT],
expected: {
$or: [{ category: 'comment' }],
},
},
{
description:
'returns the event filter for category for multiple categories',
filterCategory: [
EVENT_CATEGORY_COMMENT,
EVENT_CATEGORY_ERROR,
EVENT_CATEGORY_INFO,
],
expected: {
$or: [
{ category: 'comment' },
{ category: 'error' },
{ category: 'info' },
],
},
},
],
buildEventFilterForNotifcation: [
{
description: 'returns the event filter for notification type',
filterCategory: [
EVENT_CATEGORY_COMMENT,
EVENT_CATEGORY_ERROR,
EVENT_CATEGORY_COMMANDLINE,
],
expected: {
$and: [