Добавлены улучшатели задачи
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 { EventEmitterService } from './event-emitter.service';
|
||||||
import { RedmineEventsGateway } from './events/redmine-events.gateway';
|
import { RedmineEventsGateway } from './events/redmine-events.gateway';
|
||||||
import { ServeStaticModule } from '@nestjs/serve-static';
|
import { ServeStaticModule } from '@nestjs/serve-static';
|
||||||
|
|
@ -18,6 +24,9 @@ import { RedmineTypes } from './models/redmine-types';
|
||||||
import { UsersService } from './users/users.service';
|
import { UsersService } from './users/users.service';
|
||||||
import { IssuesService } from './issues/issues.service';
|
import { IssuesService } from './issues/issues.service';
|
||||||
import { IssuesController } from './issues/issues.controller';
|
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({})
|
@Module({})
|
||||||
export class EventEmitterModule implements OnModuleInit {
|
export class EventEmitterModule implements OnModuleInit {
|
||||||
|
|
@ -41,6 +50,11 @@ export class EventEmitterModule implements OnModuleInit {
|
||||||
RedmineUserCacheWriterService,
|
RedmineUserCacheWriterService,
|
||||||
UsersService,
|
UsersService,
|
||||||
IssuesService,
|
IssuesService,
|
||||||
|
TimestampEnhancer,
|
||||||
|
{
|
||||||
|
provide: 'ENHANCERS',
|
||||||
|
useValue: params?.enhancers || null,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
exports: [
|
exports: [
|
||||||
EventEmitterService,
|
EventEmitterService,
|
||||||
|
|
@ -53,6 +67,7 @@ export class EventEmitterModule implements OnModuleInit {
|
||||||
RedmineUserCacheWriterService,
|
RedmineUserCacheWriterService,
|
||||||
UsersService,
|
UsersService,
|
||||||
IssuesService,
|
IssuesService,
|
||||||
|
TimestampEnhancer,
|
||||||
],
|
],
|
||||||
controllers: [MainController, UsersController, IssuesController],
|
controllers: [MainController, UsersController, IssuesController],
|
||||||
};
|
};
|
||||||
|
|
@ -63,7 +78,12 @@ export class EventEmitterModule implements OnModuleInit {
|
||||||
constructor(
|
constructor(
|
||||||
private redmineEventsGateway: RedmineEventsGateway,
|
private redmineEventsGateway: RedmineEventsGateway,
|
||||||
private redmineIssuesCacheWriterService: RedmineIssuesCacheWriterService,
|
private redmineIssuesCacheWriterService: RedmineIssuesCacheWriterService,
|
||||||
) {}
|
private moduleRef: ModuleRef,
|
||||||
|
@Inject('ENHANCERS')
|
||||||
|
private enhancers: IssueEnhancerInterface[],
|
||||||
|
) {
|
||||||
|
this.enhancers.forEach((e) => e.init(this.moduleRef));
|
||||||
|
}
|
||||||
|
|
||||||
onModuleInit() {
|
onModuleInit() {
|
||||||
const queue = this.redmineEventsGateway.getIssuesChangesQueue();
|
const queue = this.redmineEventsGateway.getIssuesChangesQueue();
|
||||||
|
|
@ -72,7 +92,7 @@ export class EventEmitterModule implements OnModuleInit {
|
||||||
this.logger.debug(`Changed issues = ${JSON.stringify(issues)}`);
|
this.logger.debug(`Changed issues = ${JSON.stringify(issues)}`);
|
||||||
|
|
||||||
for (let i = 0; i < issues.length; i++) {
|
for (let i = 0; i < issues.length; i++) {
|
||||||
const issue: RedmineTypes.Issue = issues[i];
|
const issue: RedmineTypes.Issue = await this.enhanceIssue(issues[i]);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this.logger.debug(
|
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';
|
import { RedmineTypes } from '../models/redmine-types';
|
||||||
|
|
||||||
export interface IssueEnhancerInterface {
|
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 { RedmineTypes } from '../models/redmine-types';
|
||||||
import { IssueEnhancerInterface } from './issue-enhancer-interface';
|
import { IssueEnhancerInterface } from './issue-enhancer-interface';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
export class TimestampEnhancer implements IssueEnhancerInterface {
|
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), [
|
return this.createTimestamp(this.enhanceJournal(issue), [
|
||||||
'closed_on',
|
'closed_on',
|
||||||
'created_on',
|
'created_on',
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
|
import { IssueEnhancerInterface } from '../issue-enhancers/issue-enhancer-interface';
|
||||||
import { MainConfigModel } from './main-config-model';
|
import { MainConfigModel } from './main-config-model';
|
||||||
|
|
||||||
export type ModuleParams = {
|
export type ModuleParams = {
|
||||||
config?: MainConfigModel;
|
config?: MainConfigModel;
|
||||||
|
enhancers?: IssueEnhancerInterface[];
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,28 @@
|
||||||
import { EventEmitterModule } from '@app/event-emitter';
|
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 { MainController } from '@app/event-emitter/main/main.controller';
|
||||||
|
import { UsersService } from '@app/event-emitter/users/users.service';
|
||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
import { ConfigModule } from '@nestjs/config';
|
import { ConfigModule } from '@nestjs/config';
|
||||||
import { AppController } from './app.controller';
|
import { AppController } from './app.controller';
|
||||||
import { AppService } from './app.service';
|
import { AppService } from './app.service';
|
||||||
import configuration from './configs/app';
|
import configuration from './configs/app';
|
||||||
|
import { CustomFieldsEnhancer } from './issue-enhancers/custom-fields-enhancer';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
EventEmitterModule.register({
|
EventEmitterModule.register({
|
||||||
config: configuration().redmineIssueEventEmitterConfig,
|
config: configuration().redmineIssueEventEmitterConfig,
|
||||||
|
enhancers: [new TimestampEnhancer(), new CustomFieldsEnhancer()],
|
||||||
}),
|
}),
|
||||||
ConfigModule.forRoot({ load: [configuration] }),
|
ConfigModule.forRoot({ load: [configuration] }),
|
||||||
],
|
],
|
||||||
controllers: [AppController, MainController],
|
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