diff --git a/libs/event-emitter/src/calendar/calendar.service.ts b/libs/event-emitter/src/calendar/calendar.service.ts index 7011ed0..a7a5ffe 100644 --- a/libs/event-emitter/src/calendar/calendar.service.ts +++ b/libs/event-emitter/src/calendar/calendar.service.ts @@ -42,16 +42,21 @@ export type IssueAndEvent = { @Injectable() export class CalendarService { - private interval = 30 * 24 * 60 * 60 * 1000; // 30 days + private defaultInterval = 30 * 24 * 60 * 60 * 1000; // 30 days constructor( public calendarEventsKey: string, private issuesService: IssuesService, ) {} - async getICalData(filter: any): Promise { + /** + * @param filter фильтр для первичной выборки данных из couchdb через nano.filter + * @param interval период в милисекундах + * @returns + */ + async getICalData(filter: any, interval?: number): Promise { const issues = await this.issuesService.find(filter); - const actualEvents = this.getActualEvents(issues); + const actualEvents = this.getActualEvents(issues, interval); const formattedEvents = actualEvents .map((event) => { return this.generateICalendarEvent(event.issue, event.event); @@ -63,9 +68,21 @@ export class CalendarService { return res; } + /** + * @param filter фильтр для первичной выборки данных из couchdb через nano.filter + * @param interval период в милисекундах + * @returns + */ + async getRawData(filter: any, interval?: number): Promise { + const issues = await this.issuesService.find(filter); + return this.getActualEvents(issues, interval); + } + private getActualEvents( issues: RedmineTypes.ExtendedIssue[], + interval?: number, ): IssueAndEvent[] { + if (typeof interval !== 'number') interval = this.defaultInterval; const res: IssueAndEvent[] = []; for (let i = 0; i < issues.length; i++) { const issue = issues[i]; @@ -78,16 +95,18 @@ export class CalendarService { const events = issue[this.calendarEventsKey]; for (let j = 0; j < events.length; j++) { const event = events[j]; - if (this.actualEvent(event)) res.push({ event: event, issue: issue }); + if (this.actualEvent(event, interval)) { + res.push({ event: event, issue: issue }); + } } } return res; } - private actualEvent(event: CalendarEvent): boolean { + private actualEvent(event: CalendarEvent, interval: number): boolean { const now = Luxon.DateTime.now().toMillis(); - const from = now - this.interval; - const to = now + this.interval; + const from = now - interval; + const to = now + interval; return Boolean( (from <= event.fromTimestamp && event.fromTimestamp <= to) || (from <= event.toTimestamp && event.toTimestamp <= to), diff --git a/libs/event-emitter/src/dashboards/widget-data-loader/calendar.widget-data-loader.service.ts b/libs/event-emitter/src/dashboards/widget-data-loader/calendar.widget-data-loader.service.ts new file mode 100644 index 0000000..70f017c --- /dev/null +++ b/libs/event-emitter/src/dashboards/widget-data-loader/calendar.widget-data-loader.service.ts @@ -0,0 +1,49 @@ +import { Inject, Injectable } from '@nestjs/common'; +import { WidgetDataLoaderInterface } from '../widget-data-loader-interface'; +import { + Result, + AppError, + success, + fail, + createAppError, +} from '@app/event-emitter/utils/result'; +import { + CalendarService, + IssueAndEvent, +} from '@app/event-emitter/calendar/calendar.service'; +import nano from 'nano'; + +export type DataLoaderParams = { + /** Период для выборки предстоящих событий в днях */ + period: number; + /** Фильтр для выборки данных из couchdb */ + filter: nano.MangoQuery; +}; + +@Injectable() +export class CalendarWidgetDataLoaderService + implements WidgetDataLoaderInterface +{ + constructor( + @Inject('CALENDAR_SERVICE') private calendarService: CalendarService, + ) {} + + isMyConfig(): boolean { + return true; + } + + async load( + dataLoaderParams: DataLoaderParams, + ): Promise> { + let data: IssueAndEvent[]; + try { + data = await this.calendarService.getRawData( + dataLoaderParams.filter, + dataLoaderParams.period * 24 * 60 * 60 * 1000, + ); + return success(data); + } catch (ex) { + return fail(createAppError(ex.message ? ex.message : 'UNKNOWN_ERROR')); + } + } +} diff --git a/libs/event-emitter/src/dashboards/widgets-collection.service.ts b/libs/event-emitter/src/dashboards/widgets-collection.service.ts index a09685a..0bcfbbf 100644 --- a/libs/event-emitter/src/dashboards/widgets-collection.service.ts +++ b/libs/event-emitter/src/dashboards/widgets-collection.service.ts @@ -5,6 +5,7 @@ import { ListIssuesByUsersLikeJiraWidgetDataLoaderService } from './widget-data- import { RootIssueSubTreesWidgetDataLoaderService } from './widget-data-loader/root-issue-subtrees.widget-data-loader.service'; import { createInteractiveWidget } from './interactive-widget-factory'; import { Result, success } from '@app/event-emitter/utils/result'; +import { CalendarWidgetDataLoaderService } from './widget-data-loader/calendar.widget-data-loader.service'; @Injectable() export class WidgetsCollectionService { @@ -14,6 +15,7 @@ export class WidgetsCollectionService { private listIssuesByFieldsWidgetDataLoaderService: ListIssuesByFieldsWidgetDataLoaderService, private listIssuesByUsersLikeJiraWidgetDataLoaderService: ListIssuesByUsersLikeJiraWidgetDataLoaderService, private rootIssueSubTreesWidgetDataLoaderService: RootIssueSubTreesWidgetDataLoaderService, + private calendarWidgetDataLoaderService: CalendarWidgetDataLoaderService, ) { const collection = [ createInteractiveWidget( @@ -40,6 +42,10 @@ export class WidgetsCollectionService { this.rootIssueSubTreesWidgetDataLoaderService, 'issues_list_by_tree', ), + createInteractiveWidget( + this.calendarWidgetDataLoaderService, + 'calendar_next_events', + ), ]; collection.forEach((w) => this.appendWidget(w)); diff --git a/libs/event-emitter/src/event-emitter.module.ts b/libs/event-emitter/src/event-emitter.module.ts index 5aef956..2e69e41 100644 --- a/libs/event-emitter/src/event-emitter.module.ts +++ b/libs/event-emitter/src/event-emitter.module.ts @@ -36,6 +36,7 @@ import { ListIssuesByUsersLikeJiraWidgetDataLoaderService } from './dashboards/w import { ListIssuesByFieldsWidgetDataLoaderService } from './dashboards/widget-data-loader/list-issues-by-fields.widget-data-loader.service'; import { WidgetsCollectionService } from './dashboards/widgets-collection.service'; import { DashboardsController } from './dashboards/dashboards.controller'; +import { CalendarWidgetDataLoaderService } from './dashboards/widget-data-loader/calendar.widget-data-loader.service'; @Module({}) export class EventEmitterModule implements OnModuleInit { @@ -104,6 +105,7 @@ export class EventEmitterModule implements OnModuleInit { DashboardsService, DashboardsDataService, WidgetsCollectionService, + CalendarWidgetDataLoaderService, ], exports: [ EventEmitterService, @@ -142,6 +144,7 @@ export class EventEmitterModule implements OnModuleInit { DashboardsService, DashboardsDataService, WidgetsCollectionService, + CalendarWidgetDataLoaderService, ], controllers: [ MainController,