Добавлены улучшатели задачи
This commit is contained in:
parent
d858c7e228
commit
2cf5ccf118
6 changed files with 129 additions and 7 deletions
|
|
@ -1,4 +1,10 @@
|
|||
import { DynamicModule, Logger, Module, OnModuleInit } from '@nestjs/common';
|
||||
import {
|
||||
DynamicModule,
|
||||
Inject,
|
||||
Logger,
|
||||
Module,
|
||||
OnModuleInit,
|
||||
} from '@nestjs/common';
|
||||
import { EventEmitterService } from './event-emitter.service';
|
||||
import { RedmineEventsGateway } from './events/redmine-events.gateway';
|
||||
import { ServeStaticModule } from '@nestjs/serve-static';
|
||||
|
|
@ -18,6 +24,9 @@ import { RedmineTypes } from './models/redmine-types';
|
|||
import { UsersService } from './users/users.service';
|
||||
import { IssuesService } from './issues/issues.service';
|
||||
import { IssuesController } from './issues/issues.controller';
|
||||
import { IssueEnhancerInterface } from './issue-enhancers/issue-enhancer-interface';
|
||||
import { TimestampEnhancer } from './issue-enhancers/timestamps-enhancer';
|
||||
import { ModuleRef } from '@nestjs/core';
|
||||
|
||||
@Module({})
|
||||
export class EventEmitterModule implements OnModuleInit {
|
||||
|
|
@ -41,6 +50,11 @@ export class EventEmitterModule implements OnModuleInit {
|
|||
RedmineUserCacheWriterService,
|
||||
UsersService,
|
||||
IssuesService,
|
||||
TimestampEnhancer,
|
||||
{
|
||||
provide: 'ENHANCERS',
|
||||
useValue: params?.enhancers || null,
|
||||
},
|
||||
],
|
||||
exports: [
|
||||
EventEmitterService,
|
||||
|
|
@ -53,6 +67,7 @@ export class EventEmitterModule implements OnModuleInit {
|
|||
RedmineUserCacheWriterService,
|
||||
UsersService,
|
||||
IssuesService,
|
||||
TimestampEnhancer,
|
||||
],
|
||||
controllers: [MainController, UsersController, IssuesController],
|
||||
};
|
||||
|
|
@ -63,7 +78,12 @@ export class EventEmitterModule implements OnModuleInit {
|
|||
constructor(
|
||||
private redmineEventsGateway: RedmineEventsGateway,
|
||||
private redmineIssuesCacheWriterService: RedmineIssuesCacheWriterService,
|
||||
) {}
|
||||
private moduleRef: ModuleRef,
|
||||
@Inject('ENHANCERS')
|
||||
private enhancers: IssueEnhancerInterface[],
|
||||
) {
|
||||
this.enhancers.forEach((e) => e.init(this.moduleRef));
|
||||
}
|
||||
|
||||
onModuleInit() {
|
||||
const queue = this.redmineEventsGateway.getIssuesChangesQueue();
|
||||
|
|
@ -72,7 +92,7 @@ export class EventEmitterModule implements OnModuleInit {
|
|||
this.logger.debug(`Changed issues = ${JSON.stringify(issues)}`);
|
||||
|
||||
for (let i = 0; i < issues.length; i++) {
|
||||
const issue: RedmineTypes.Issue = issues[i];
|
||||
const issue: RedmineTypes.Issue = await this.enhanceIssue(issues[i]);
|
||||
|
||||
try {
|
||||
this.logger.debug(
|
||||
|
|
@ -94,4 +114,18 @@ export class EventEmitterModule implements OnModuleInit {
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
private async enhanceIssue(
|
||||
issue: RedmineTypes.Issue & Record<string, any>,
|
||||
): Promise<RedmineTypes.Issue & Record<string, any>> {
|
||||
const enhancers = this.enhancers;
|
||||
for (let i = 0; i < enhancers.length; i++) {
|
||||
const enhancer = enhancers[i];
|
||||
issue = await enhancer.enhance(issue);
|
||||
this.logger.debug(
|
||||
`Issue after enhancer: issue = ${JSON.stringify(issue)}`,
|
||||
);
|
||||
}
|
||||
return issue;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,9 @@
|
|||
import { ModuleRef } from '@nestjs/core';
|
||||
import { RedmineTypes } from '../models/redmine-types';
|
||||
|
||||
export interface IssueEnhancerInterface {
|
||||
enhance(issue: RedmineTypes.Issue): RedmineTypes.Issue & Record<string, any>;
|
||||
init(moduleRef: ModuleRef);
|
||||
enhance(
|
||||
issue: RedmineTypes.Issue,
|
||||
): Promise<RedmineTypes.Issue & Record<string, any>>;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,16 @@
|
|||
import { Injectable } from '@nestjs/common';
|
||||
import { RedmineTypes } from '../models/redmine-types';
|
||||
import { IssueEnhancerInterface } from './issue-enhancer-interface';
|
||||
|
||||
@Injectable()
|
||||
export class TimestampEnhancer implements IssueEnhancerInterface {
|
||||
enhance(issue: RedmineTypes.Issue): RedmineTypes.Issue & Record<string, any> {
|
||||
init() {
|
||||
return;
|
||||
}
|
||||
|
||||
async enhance(
|
||||
issue: RedmineTypes.Issue,
|
||||
): Promise<RedmineTypes.Issue & Record<string, any>> {
|
||||
return this.createTimestamp(this.enhanceJournal(issue), [
|
||||
'closed_on',
|
||||
'created_on',
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
import { IssueEnhancerInterface } from '../issue-enhancers/issue-enhancer-interface';
|
||||
import { MainConfigModel } from './main-config-model';
|
||||
|
||||
export type ModuleParams = {
|
||||
config?: MainConfigModel;
|
||||
enhancers?: IssueEnhancerInterface[];
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,19 +1,28 @@
|
|||
import { EventEmitterModule } from '@app/event-emitter';
|
||||
import { TimestampEnhancer } from '@app/event-emitter/issue-enhancers/timestamps-enhancer';
|
||||
import { MainController } from '@app/event-emitter/main/main.controller';
|
||||
import { UsersService } from '@app/event-emitter/users/users.service';
|
||||
import { Module } from '@nestjs/common';
|
||||
import { ConfigModule } from '@nestjs/config';
|
||||
import { AppController } from './app.controller';
|
||||
import { AppService } from './app.service';
|
||||
import configuration from './configs/app';
|
||||
import { CustomFieldsEnhancer } from './issue-enhancers/custom-fields-enhancer';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
EventEmitterModule.register({
|
||||
config: configuration().redmineIssueEventEmitterConfig,
|
||||
enhancers: [new TimestampEnhancer(), new CustomFieldsEnhancer()],
|
||||
}),
|
||||
ConfigModule.forRoot({ load: [configuration] }),
|
||||
],
|
||||
controllers: [AppController, MainController],
|
||||
providers: [AppService],
|
||||
providers: [AppService, UsersService, CustomFieldsEnhancer],
|
||||
})
|
||||
export class AppModule {}
|
||||
export class AppModule {
|
||||
constructor(
|
||||
private timestampEnhancer: TimestampEnhancer,
|
||||
private customFieldsEnhancer: CustomFieldsEnhancer,
|
||||
) {}
|
||||
}
|
||||
|
|
|
|||
65
src/issue-enhancers/custom-fields-enhancer.ts
Normal file
65
src/issue-enhancers/custom-fields-enhancer.ts
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
import { IssueEnhancerInterface } from '@app/event-emitter/issue-enhancers/issue-enhancer-interface';
|
||||
import { RedmineTypes } from '@app/event-emitter/models/redmine-types';
|
||||
import { UsersService } from '@app/event-emitter/users/users.service';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { ModuleRef } from '@nestjs/core';
|
||||
|
||||
@Injectable()
|
||||
export class CustomFieldsEnhancer implements IssueEnhancerInterface {
|
||||
private usersService: UsersService;
|
||||
|
||||
init(moduleRef: ModuleRef): void {
|
||||
this.usersService = moduleRef.get(UsersService);
|
||||
}
|
||||
|
||||
async enhance(
|
||||
issue: RedmineTypes.Issue,
|
||||
): Promise<RedmineTypes.Issue & Record<string, any>> {
|
||||
const res: RedmineTypes.Issue & Record<string, any> = { ...issue };
|
||||
|
||||
const customFields = issue.custom_fields;
|
||||
if (!customFields) {
|
||||
return issue;
|
||||
}
|
||||
|
||||
const qa = customFields.find(
|
||||
(cf) => cf.name === 'Quality Assurance' || cf.name === 'QA',
|
||||
);
|
||||
if (qa && this.isNumber(qa.value)) {
|
||||
const qaUserId = Number(qa.value);
|
||||
const qaUser = await this.usersService.getUser(qaUserId);
|
||||
if (qaUser) {
|
||||
res.qa = { ...qaUser };
|
||||
}
|
||||
}
|
||||
|
||||
const cr = customFields.find(
|
||||
(cf) => cf.name === 'Code Reviewer' || cf.name === 'CR',
|
||||
);
|
||||
if (cr && this.isNumber(cr.value)) {
|
||||
const crUserId = Number(cr.value);
|
||||
const crUser = await this.usersService.getUser(crUserId);
|
||||
if (crUser) {
|
||||
res.cr = { ...crUser };
|
||||
}
|
||||
}
|
||||
|
||||
const tags = customFields.find((cf) => cf.name === 'Tags');
|
||||
if (tags && tags.value) {
|
||||
res.tags = tags.value.split(',; ');
|
||||
}
|
||||
|
||||
const sp = customFields.find(
|
||||
(cf) => cf.name === 'Story Points' || cf.name === 'SP',
|
||||
);
|
||||
if (sp && this.isNumber(sp.value)) {
|
||||
res.sp = Number(sp.value);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
private isNumber(value): boolean {
|
||||
return !Number.isNaN(value) && Number.isFinite(Number(value));
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue