Skip to content
Draft
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ uploads
globalConfig.json
coverage
tls
.history
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "hawk.api",
"version": "1.1.28",
"version": "1.1.29",
"main": "index.ts",
"license": "UNLICENSED",
"scripts": {
Expand Down
71 changes: 43 additions & 28 deletions src/models/eventsFactory.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,11 @@ const { ObjectID } = require('mongodb');

/**
* @typedef {Object} EventsFilters
* @property {boolean} [starred] - if true, events with 'starred' mark should be included to the output
* @property {boolean} [resolved] - if true, events with 'resolved' should be included to the output
* @property {boolean} [ignored] - if true, events with 'ignored' mark should be included to the output
* @property {boolean} [starred]
* @property {boolean} [resolved]
* @property {boolean} [ignored]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

redundant jsdoc removal

* @property {string|number} [dateFrom]
* @property {string|number} [dateTo]
*/

/**
Expand Down Expand Up @@ -149,8 +151,8 @@ class EventsFactory extends Factory {
* @param {Number} limit - events count limitations
* @param {Number} skip - certain number of documents to skip
* @param {'BY_DATE' | 'BY_COUNT'} sort - events sort order
* @param {EventsFilters} filters - marks by which events should be filtered
* @param {String} search - Search query
* @param {EventsFilters} filters - filter object
* @param {String} search - search query
*
* @return {RecentEventSchema[]}
*/
Expand All @@ -165,9 +167,6 @@ class EventsFactory extends Factory {
throw new Error('Search parameter must be a string');
}

/**
* Check if pattern is safe RegExp
*/
Comment on lines 225 to 227
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unexpected jsdoc removal

if (!safe(search)) {
throw new Error('Invalid regular expression pattern');
}
Expand Down Expand Up @@ -231,13 +230,41 @@ class EventsFactory extends Factory {
}
: {};

const matchFilter = filters
? Object.fromEntries(
Object
.entries(filters)
.map(([mark, exists]) => [`event.marks.${mark}`, { $exists: exists } ])
)
: {};
const matchFilter = {
...searchFilter,
};

// Filter by marks (event.marks.{key})
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// Filter by marks (event.marks.{key})

['starred', 'resolved', 'ignored'].forEach((mark) => {
if (typeof filters[mark] === 'boolean') {
matchFilter[`event.marks.${mark}`] = { $exists: filters[mark] };
}
});

// Filter by date (groupingTimestamp)
if (filters.dateFrom || filters.dateTo) {
matchFilter.groupingTimestamp = {};

if (filters.dateFrom) {
const from = typeof filters.dateFrom === 'string'
? Math.floor(new Date(filters.dateFrom).getTime() / 1000)
: filters.dateFrom;

matchFilter.groupingTimestamp.$gte = from;
}

if (filters.dateTo) {
const to = typeof filters.dateTo === 'string'
? Math.floor(new Date(filters.dateTo).getTime() / 1000)
: filters.dateTo;

matchFilter.groupingTimestamp.$lte = to;
}

if (Object.keys(matchFilter.groupingTimestamp).length === 0) {
delete matchFilter.groupingTimestamp;
}
}

pipeline.push(
{
Expand All @@ -252,10 +279,7 @@ class EventsFactory extends Factory {
$unwind: '$event',
},
{
$match: {
...matchFilter,
...searchFilter,
},
$match: matchFilter,
},
{ $skip: skip },
{ $limit: limit },
Expand All @@ -272,17 +296,8 @@ class EventsFactory extends Factory {
);

const cursor = this.getCollection(this.TYPES.DAILY_EVENTS).aggregate(pipeline);

const result = (await cursor.toArray()).shift();

/**
* aggregation can return empty array so that
* result can be undefined
*
* for that we check result existence
*
* extra field `projectId` needs to satisfy GraphQL query
*/
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

leave jsdoc please

if (result && result.events) {
result.events.forEach(event => {
event.projectId = this.projectId;
Expand Down
25 changes: 21 additions & 4 deletions src/typeDefs/project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,29 @@ Events filters input type
"""
input EventsFiltersInput {
"""
If True, includes events with resolved mark to the output
If true, includes events with resolved mark
"""
resolved: Boolean

"""
If True, includes events with starred mark to the output
If true, includes events with starred mark
"""
starred: Boolean

"""
If True, includes events with ignored mark to the output
If true, includes events with ignored mark
"""
ignored: Boolean

"""
Include events with groupingTimestamp >= dateFrom (ISO or timestamp in seconds)
"""
dateFrom: Timestamp

"""
Include events with groupingTimestamp <= dateTo (ISO or timestamp in seconds)
"""
dateTo: Timestamp
}

"""
Expand Down Expand Up @@ -122,12 +134,17 @@ type Project {
"Events sort order"
sort: EventsSortOrder = lastRepetitionTime

"Event marks by which events should be sorted"
"""
Filters for narrowing down the event results:
- By marks (e.g., starred, resolved)
- By date range (dateFrom / dateTo)
"""
filters: EventsFiltersInput

"Search query"
search: String
): RecentEvents

"""
Return events that occurred after a certain timestamp
"""
Expand Down
Loading