Skip to content

Commit ff2d224

Browse files
author
Furkan Yavuz
authored
Merge pull request #66 from open-template-hub/develop
Release/event search updates
2 parents b63433a + 577a89b commit ff2d224

18 files changed

Lines changed: 265 additions & 73 deletions

.github/workflows/cron-dependency-checker-workflow.yml

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,18 @@ jobs:
2424
- name: Npm Outdated
2525
run: npm run outdated
2626

27+
- name: Check for Changes
28+
run: |
29+
if git diff --exit-code; then
30+
echo "changes_exist=false" >> $GITHUB_ENV
31+
else
32+
echo "changes_exist=true" >> $GITHUB_ENV
33+
fi
34+
2735
- name: Git Commit and Push
36+
if: ${{ env.changes_exist == 'true' }}
2837
run: |
29-
git config --global user.email "furknyavuz@gmail.com"
30-
git config --global user.name "Furkan Yavuz"
38+
git config --global user.email "98660390+oth-service-user@users.noreply.github.com"
39+
git config --global user.name "OTH Service User"
3140
git commit -am "Workflow/dependency check"
3241
git push

README.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
</p>
66

77
<h1 align="center">
8-
Open Template Hub - Analytics Server Template v3
8+
Open Template Hub - Analytics Server Template v4
99
</h1>
1010

1111
[![License](https://img.shields.io/github/license/open-template-hub/analytics-server-template?color=43b043&style=for-the-badge)](LICENSE)
@@ -74,6 +74,12 @@ ACCESS_TOKEN_SECRET={Access Token Secret}
7474
RESPONSE_ENCRYPTION_SECRET={Response Encryption Secret}
7575
```
7676

77+
## Postman Regression Tests
78+
79+
To be able to configure regression tests, refer to **[REGRESSION_TESTS.md](docs/REGRESSION_TESTS.md)** file.
80+
81+
<br/>
82+
7783
## Http Requests
7884

7985
You can find list of available http request in the [requests](assets/requests) directory. You can run http requests directly via **WebStorm**, for more information check out: [jetbrains.com/help/idea/http-client-in-product-code-editor.html](https://jetbrains.com/help/idea/http-client-in-product-code-editor.html)

app/controller/event.controller.ts

Lines changed: 39 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,34 +3,40 @@
33
*/
44

55
import { Context } from '@open-template-hub/common';
6-
import { EventCategory } from '../enum/event-category.enum';
6+
import { Environment } from '../../environment';
77
import { EventFilter } from '../interface/event-filter.interface';
88
import { Event } from '../interface/event.interface';
9+
import { EventConfigRepository } from '../repository/event-config.repository';
910
import { EventRepository } from '../repository/event.repository';
1011

1112
export class EventController {
13+
14+
constructor( private environment = new Environment() ) {
15+
// Intentionally blank
16+
}
17+
1218
/**
1319
* creates event
1420
* @param context context
1521
* @param event event
1622
* @returns created event
1723
*/
18-
createEvent = async (context: Context, event: Event) => {
24+
createEvent = async ( context: Context, event: Event ) => {
1925
const eventRepository = await new EventRepository().initialize(
20-
context.mongodb_provider.getConnection()
26+
context.mongodb_provider.getConnection()
2127
);
2228

23-
if (!event.timestamp) {
29+
if ( !event.timestamp ) {
2430
event.timestamp = Date.now();
2531
}
2632

27-
if (!event.category) {
28-
event.category = EventCategory.DEFAULT;
33+
if ( !event.category ) {
34+
event.category = 'DEFAULT';
2935
}
3036

3137
event.reporter = context.username;
3238

33-
return eventRepository.createEvent(event);
39+
return eventRepository.createEvent( event );
3440
};
3541

3642
/**
@@ -39,42 +45,58 @@ export class EventController {
3945
* @param filter filter
4046
* @returns filtered events
4147
*/
42-
filterEvents = async (context: Context, filter: EventFilter) => {
48+
filterEvents = async ( context: Context, filter: EventFilter ) => {
4349
const eventRepository = await new EventRepository().initialize(
44-
context.mongodb_provider.getConnection()
50+
context.mongodb_provider.getConnection()
4551
);
4652

47-
const query = this.getQueryFromFilter(context, filter);
53+
const query = this.getQueryFromFilter( context, filter );
4854

49-
return eventRepository.filterEvents(query, filter.limit);
55+
return eventRepository.filterEvents( query, filter.skip, filter.limit );
5056
};
5157

5258
/**
5359
* creates query from the filter
60+
*@param context context
5461
* @param filter filter
5562
* @returns query
5663
*/
57-
getQueryFromFilter = (context: Context, filter: EventFilter) => {
58-
var query = {} as any;
64+
getQueryFromFilter = ( context: Context, filter: EventFilter ) => {
65+
let query = {} as any;
5966

6067
query.reporter = context.username;
6168

62-
if (filter.name) {
69+
if ( filter.name ) {
6370
query.name = { $eq: filter.name };
6471
}
6572

66-
if (filter.category) {
73+
if ( filter.category && filter.category !== 'ALL' ) {
6774
query.category = { $eq: filter.category };
6875
}
6976

70-
if (filter.start) {
77+
if ( filter.start ) {
7178
query.timestamp = { $gte: filter.start };
7279
}
7380

74-
if (filter.end) {
81+
if ( filter.end ) {
7582
query.timestamp = { $lte: filter.end };
7683
}
7784

85+
const maxQueryLimit = +( this.environment.args().serverSpecificArgs?.maxQueryLimit ?? '1000' );
86+
if ( filter.limit > maxQueryLimit ) {
87+
filter.limit = maxQueryLimit;
88+
}
89+
7890
return query;
7991
};
92+
93+
getCategories = async ( context: Context, language: string ) => {
94+
const eventConfigRepository = await new EventConfigRepository().initialize(
95+
context.mongodb_provider.getConnection()
96+
);
97+
98+
const defaultLanguage = process.env.DEFAULT_LANGUAGE ?? 'en';
99+
100+
return eventConfigRepository.getCategories( context.role, language, defaultLanguage );
101+
};
80102
}

app/data/event-config.data.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/**
2+
* @description holds event model
3+
*/
4+
5+
import mongoose from 'mongoose';
6+
7+
export class EventConfigDataModel {
8+
private readonly collectionName: string = 'event_config';
9+
private dataSchema: mongoose.Schema;
10+
11+
constructor() {
12+
/**
13+
* Provider schema
14+
*/
15+
const schema: mongoose.SchemaDefinition = {
16+
key: { type: String, required: true },
17+
roles: { type: Array, default: [] },
18+
messages: { type: Number, default: [] }
19+
};
20+
this.dataSchema = new mongoose.Schema( schema );
21+
}
22+
23+
/**
24+
* creates provider model
25+
* @returns provider model
26+
*/
27+
getDataModel = async ( conn: mongoose.Connection ) => {
28+
return conn.model(
29+
this.collectionName,
30+
this.dataSchema,
31+
this.collectionName
32+
);
33+
};
34+
}
35+

app/enum/event-category.enum.ts

Lines changed: 0 additions & 10 deletions
This file was deleted.

app/interface/event-filter.interface.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,12 @@
22
* @description holds event filter interface
33
*/
44

5-
import { EventCategory } from '../enum/event-category.enum';
6-
75
export interface EventFilter {
86
name: string;
9-
category: EventCategory;
7+
category: string;
108
start: number;
119
end: number;
10+
skip: number;
1211
limit: number;
1312
reporter: string;
1413
}

app/interface/event.interface.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,11 @@
22
* @description holds event interface
33
*/
44

5-
import { EventCategory } from '../enum/event-category.enum';
65

76
export interface Event {
87
source: string;
98
timestamp: number;
109
payload: any;
11-
category: EventCategory;
10+
category: string;
1211
reporter: string;
1312
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import { UserRole } from "@open-template-hub/common";
2+
import { EventConfigDataModel } from "../data/event-config.data";
3+
4+
export class EventConfigRepository {
5+
private dataModel: any = null;
6+
7+
/**
8+
* initializes eventConfig repository
9+
* @param connection db connection
10+
*/
11+
initialize = async ( connection: any ) => {
12+
this.dataModel = await new EventConfigDataModel().getDataModel( connection );
13+
return this;
14+
};
15+
16+
getCategory = async ( key: string ) => {
17+
try {
18+
return await this.dataModel.findOne( key );
19+
} catch(error) {
20+
console.error( '> getCategory error: ', error );
21+
throw error;
22+
}
23+
}
24+
25+
getCategories = async ( userRole: UserRole, language: string, defaultLanguage: string ) => {
26+
try {
27+
let dataModel = await this.dataModel.aggregate( [
28+
{ $match: { roles: { $in: [userRole] } } },
29+
{ $project: {
30+
key: 1,
31+
messages: {
32+
$filter: {
33+
input: "$messages",
34+
as: "item",
35+
cond: {
36+
$or: [ 
37+
{ $eq: [ "$$item.language", language ] },
38+
{ $eq: ["$$item.language", defaultLanguage ] }
39+
] }
40+
}
41+
}
42+
} }
43+
] );
44+
45+
let newMessagesArray: string[] = [];
46+
for(let i = 0; i < dataModel.length; i++) {
47+
if( dataModel[i].messages?.length > 1 ) {
48+
for(let j = 0; j < dataModel[i].messages.length; j++ ) {
49+
if( dataModel[i].messages[j].language === language ) {
50+
newMessagesArray.push( dataModel[i].messages[j] );
51+
}
52+
}
53+
54+
if( newMessagesArray.length > 0 ) {
55+
dataModel[i].messages = newMessagesArray;
56+
}
57+
}
58+
}
59+
60+
return dataModel
61+
62+
} catch ( error ) {
63+
console.error( '> getCategories error: ', error );
64+
throw error;
65+
}
66+
};
67+
}

app/repository/event.repository.ts

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,37 @@ export class EventRepository {
3737
* @param limit limit
3838
* @returns filtered events
3939
*/
40-
filterEvents = async ( query: any, limit: number ) => {
40+
filterEvents = async ( query: any, skip: number, limit: number ) => {
4141
try {
42-
return await this.dataModel.find( query ).sort( { timestamp: -1 } ).limit( limit );
42+
let queryResult = await this.dataModel.aggregate([
43+
{ $match: query },
44+
{ $sort: { timestamp: -1 } },
45+
{ $facet: {
46+
data: [
47+
{ $match: { } },
48+
{ $skip: skip },
49+
{ $limit: limit }
50+
],
51+
meta: [
52+
{ $count: "count" },
53+
{ $addFields: {
54+
skip: skip,
55+
limit: limit
56+
}}
57+
]
58+
}}
59+
]);
60+
61+
if( queryResult.length > 0 ) {
62+
queryResult = queryResult[0];
63+
64+
if( queryResult.meta.length > 0 ) {
65+
queryResult.meta = queryResult.meta[0]
66+
}
67+
68+
return queryResult
69+
}
70+
return { }
4371
} catch ( error ) {
4472
console.error( '> filterEvents error: ', error );
4573
throw error;

0 commit comments

Comments
 (0)