Добавлен загрузчик данных для календаря в дашбордах
This commit is contained in:
parent
d7b37470ef
commit
50f7aeaf2f
4 changed files with 84 additions and 7 deletions
|
|
@ -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<string> {
|
||||
/**
|
||||
* @param filter фильтр для первичной выборки данных из couchdb через nano.filter
|
||||
* @param interval период в милисекундах
|
||||
* @returns
|
||||
*/
|
||||
async getICalData(filter: any, interval?: number): Promise<string> {
|
||||
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<IssueAndEvent[]> {
|
||||
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),
|
||||
|
|
|
|||
|
|
@ -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<DataLoaderParams, any, IssueAndEvent[]>
|
||||
{
|
||||
constructor(
|
||||
@Inject('CALENDAR_SERVICE') private calendarService: CalendarService,
|
||||
) {}
|
||||
|
||||
isMyConfig(): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
async load(
|
||||
dataLoaderParams: DataLoaderParams,
|
||||
): Promise<Result<IssueAndEvent[], AppError>> {
|
||||
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'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Reference in a new issue