Skip to content

Commit 2961bac

Browse files
authored
Merge pull request #481 from codex-team/events-manual-grouping
Events manual grouping to stage
2 parents 1b7f630 + b56f450 commit 2961bac

File tree

12 files changed

+439
-64
lines changed

12 files changed

+439
-64
lines changed

.eslintrc.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,13 @@ module.exports = {
1111
'require-jsdoc': 'warn',
1212
'no-shadow': 'warn',
1313
'no-unused-expressions': 'warn'
14-
}
14+
},
15+
overrides: [
16+
{
17+
files: ['*.js'],
18+
rules: {
19+
'@typescript-eslint/explicit-function-return-type': 'off'
20+
}
21+
}
22+
]
1523
};

package.json

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "hawk.api",
3-
"version": "1.1.15",
3+
"version": "1.1.16",
44
"main": "index.ts",
55
"license": "UNLICENSED",
66
"scripts": {
@@ -37,7 +37,7 @@
3737
"@graphql-tools/schema": "^8.5.1",
3838
"@graphql-tools/utils": "^8.9.0",
3939
"@hawk.so/nodejs": "^3.1.1",
40-
"@hawk.so/types": "^0.1.26",
40+
"@hawk.so/types": "^0.1.28",
4141
"@types/amqp-connection-manager": "^2.0.4",
4242
"@types/bson": "^4.0.5",
4343
"@types/debug": "^4.1.5",
@@ -49,6 +49,7 @@
4949
"@types/node": "^16.11.46",
5050
"@types/node-fetch": "^2.5.4",
5151
"@types/uuid": "^8.3.4",
52+
"@types/safe-regex": "^1.1.6",
5253
"amqp-connection-manager": "^3.1.0",
5354
"amqplib": "^0.5.5",
5455
"apollo-server-express": "^3.10.0",
@@ -73,6 +74,7 @@
7374
"mime-types": "^2.1.25",
7475
"mongodb": "^3.7.3",
7576
"ts-node-dev": "^2.0.0",
76-
"uuid": "^8.3.2"
77+
"uuid": "^8.3.2",
78+
"safe-regex": "^2.1.0"
7779
}
7880
}

src/models/project.ts

Lines changed: 123 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,9 @@
11
import { Collection, ObjectId } from 'mongodb';
22
import AbstractModel from './abstractModel';
33
import { NotificationsChannelsDBScheme } from '../types/notification-channels';
4-
import { ProjectDBScheme } from '@hawk.so/types';
4+
import { ProjectDBScheme, ProjectNotificationsRuleDBScheme, ProjectEventGroupingPatternsDBScheme } from '@hawk.so/types';
55
import { v4 as uuid } from 'uuid';
66

7-
/**
8-
* This structure represents a single rule of notifications settings
9-
*/
10-
export interface ProjectNotificationsRuleDBScheme {
11-
/**
12-
* Id of Rule
13-
*/
14-
_id: ObjectId;
15-
16-
/**
17-
* Allows to disable rule without removing
18-
*/
19-
isEnabled: boolean;
20-
21-
/**
22-
* Creator of the rule
23-
*/
24-
uidAdded: ObjectId;
25-
26-
/**
27-
* Receive type: 'SEEN_MORE' or 'ONLY_NEW'
28-
*/
29-
whatToReceive: ReceiveTypes;
30-
31-
/**
32-
* Only those which contains passed words
33-
*/
34-
including: string[];
35-
36-
/**
37-
* Skip those which contains passed words
38-
*/
39-
excluding: string[];
40-
41-
/**
42-
* Available channels to receive
43-
*/
44-
channels: NotificationsChannelsDBScheme;
45-
46-
/**
47-
* If this number of events is reached in the eventThresholdPeriod, the rule will be triggered
48-
*/
49-
threshold?: number;
50-
51-
/**
52-
* Size of period (in milliseconds) to count events to compare to rule threshold
53-
*/
54-
thresholdPeriod?: number;
55-
}
56-
577
/**
588
* Available options of 'What to receive'
599
*/
@@ -159,6 +109,36 @@ interface UpdateProjectNotificationsRulePayload {
159109
thresholdPeriod?: number;
160110
}
161111

112+
/**
113+
* Payload for creating new project pattern
114+
*/
115+
type CreateProjectPatternPayload = {
116+
pattern: string;
117+
};
118+
119+
/**
120+
* Payload for updating project patterns
121+
* It will just rewrite the whole lits of patterns
122+
*/
123+
type UpdateProjectPatternPayload = {
124+
/**
125+
* Id of the pattern to be updated
126+
*/
127+
id: string;
128+
129+
/**
130+
* New pattern string
131+
*/
132+
pattern: string;
133+
};
134+
135+
type RemoveProjectPatternPayload = {
136+
/**
137+
* Id of the pattern to be removed
138+
*/
139+
id: string;
140+
}
141+
162142
/**
163143
* Project model to work with project data
164144
*/
@@ -208,6 +188,11 @@ export default class ProjectModel extends AbstractModel<ProjectDBScheme> impleme
208188
*/
209189
public notifications!: ProjectNotificationsRuleDBScheme[];
210190

191+
/**
192+
* Project events grouping pattern list
193+
*/
194+
public eventGroupingPatterns!: ProjectEventGroupingPatternsDBScheme[];
195+
211196
/**
212197
* Model's collection
213198
*/
@@ -282,6 +267,93 @@ export default class ProjectModel extends AbstractModel<ProjectDBScheme> impleme
282267
return rule;
283268
}
284269

270+
/**
271+
* Method for appending patterns list with new pattern
272+
* @param payload - object that contains pattern string
273+
* @returns - pattern, that has been added
274+
*/
275+
public async createProjectEventGroupingPattern(payload: CreateProjectPatternPayload): Promise<ProjectEventGroupingPatternsDBScheme> {
276+
const pattern: ProjectEventGroupingPatternsDBScheme = {
277+
_id: new ObjectId(),
278+
pattern: payload.pattern,
279+
};
280+
281+
await this.collection.updateOne({
282+
_id: this._id,
283+
},
284+
{
285+
$push: {
286+
eventGroupingPatterns: {
287+
$each: [ pattern ],
288+
$position: 0,
289+
},
290+
},
291+
});
292+
293+
return pattern;
294+
}
295+
296+
/**
297+
* Method that rewrites pattern by id
298+
* @param payload - object that contains id of the pattern to be updated and new pattern string
299+
* @returns - updated pattern
300+
*/
301+
public async updateProjectEventGroupingPattern(payload: UpdateProjectPatternPayload): Promise<ProjectEventGroupingPatternsDBScheme> {
302+
const udpatedPattern = {
303+
_id: new ObjectId(payload.id),
304+
pattern: payload.pattern,
305+
};
306+
307+
await this.collection.updateOne({
308+
_id: this._id,
309+
'eventGroupingPatterns._id': new ObjectId(udpatedPattern._id),
310+
},
311+
{
312+
$set: { 'eventGroupingPatterns.$.pattern': udpatedPattern.pattern },
313+
});
314+
315+
return udpatedPattern;
316+
}
317+
318+
/**
319+
* Method that removes pattern by its id
320+
* @param payload - object that contains id of the pattern to be removed
321+
*/
322+
public async removeProjectEventGroupingPattern(payload: RemoveProjectPatternPayload): Promise<ProjectEventGroupingPatternsDBScheme> {
323+
const project = await this.collection.findOne({
324+
_id: this._id,
325+
});
326+
327+
if (!project) {
328+
throw new Error('Project with such id does not exist');
329+
}
330+
331+
const patternList = await this.collection.findOne(
332+
{
333+
_id: this._id,
334+
'eventGroupingPatterns._id': new ObjectId(payload.id),
335+
},
336+
{ projection: { 'eventGroupingPatterns.$': 1 } }
337+
);
338+
339+
const deletedPattern = patternList?.eventGroupingPatterns[0];
340+
341+
if (deletedPattern === undefined) {
342+
throw new Error('Pattern with such id does not exist');
343+
}
344+
345+
await this.collection.updateOne(
346+
{
347+
_id: new ObjectId(this._id),
348+
},
349+
{
350+
$pull: { eventGroupingPatterns: { _id: new ObjectId(payload.id) } },
351+
}
352+
);
353+
354+
return deletedPattern;
355+
}
356+
285357
/**
286358
* Updates notifications rule in project
287359
* @param payload - data for updating

src/resolvers/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ const project = require('./project');
1313
const event = require('./event');
1414
const plans = require('./plans').default;
1515
const projectNotifications = require('./projectNotifications').default;
16+
const projectPatterns = require('./projectPatterns').default;
1617
const userNotifications = require('./userNotifications').default;
1718
const billing = require('./billingNew').default;
1819
const EncodedJSON = require('./encodedJSON').default;
@@ -71,6 +72,7 @@ const resolvers = [
7172
project,
7273
event,
7374
projectNotifications,
75+
projectPatterns,
7476
userNotifications,
7577
plans,
7678
billing,

src/resolvers/project.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ const ProjectModel = require('../models/project').default;
1111
const EVENTS_GROUP_HASH_INDEX_NAME = 'groupHashUnique';
1212
const REPETITIONS_GROUP_HASH_INDEX_NAME = 'groupHash_hashed';
1313
const REPETITIONS_USER_ID_INDEX_NAME = 'userId';
14+
const MAX_SEARCH_QUERY_LENGTH = 50;
1415

1516
/**
1617
* See all types and fields here {@see ../typeDefs/project.graphql}
@@ -310,8 +311,8 @@ module.exports = {
310311
*/
311312
async recentEvents(project, { limit, skip, sort, filters, search }) {
312313
if (search) {
313-
if (search.length > 100) {
314-
throw new UserInputError('Search query is too long. Maximum length is 100 characters');
314+
if (search.length > MAX_SEARCH_QUERY_LENGTH) {
315+
search = search.slice(0, MAX_SEARCH_QUERY_LENGTH);
315316
}
316317
}
317318

src/resolvers/projectNotifications.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import {
2-
ProjectNotificationsRuleDBScheme,
32
ReceiveTypes
43
} from '../models/project';
4+
import { ProjectNotificationsRuleDBScheme } from '@hawk.so/types';
55
import { ResolverContextWithUser } from '../types/graphql';
66
import { ApolloError, UserInputError } from 'apollo-server-express';
7-
import { NotificationsChannelsDBScheme, NotificationsChannelSettingsDBScheme } from '../types/notification-channels';
7+
import { NotificationsChannelsDBScheme } from '../types/notification-channels';
88

99
/**
1010
* Mutation payload for creating notifications rule from GraphQL Schema
@@ -223,7 +223,7 @@ export default {
223223
},
224224

225225
/**
226-
* Toggles isEnabled field in in project notifications rule
226+
* Toggles isEnabled field in project notifications rule
227227
* @param _obj - parent object
228228
* @param user - current authorized user {@see ../index.js}
229229
* @param factories - factories for working with models

0 commit comments

Comments
 (0)