pinkmine/libs/event-emitter/src/project-dashboard/widgets/list-issues-by-fields.widget.service.ts

133 lines
4.2 KiB
TypeScript

/* eslint-disable @typescript-eslint/no-namespace */
import { IssueUrlEnhancer } from '@app/event-emitter/issue-enhancers/issue-url-enhancer';
import { TagStyledEnhancerNs } from '@app/event-emitter/issue-enhancers/tag-styled-enhancer';
import { TimePassedHighlightEnhancer } from '@app/event-emitter/issue-enhancers/time-passed-highlight-enhancer';
import {
IssuesService,
IssuesServiceNs,
} from '@app/event-emitter/issues/issues.service';
import { RedmineTypes } from '@app/event-emitter/models/redmine-types';
import { FlatIssuesStore } from '@app/event-emitter/utils/flat-issues-store';
import { GetValueFromObjectByKey } from '@app/event-emitter/utils/get-value-from-object-by-key';
import { TreeIssuesStore } from '@app/event-emitter/utils/tree-issues-store';
import { Injectable, Logger } from '@nestjs/common';
import nano from 'nano';
import { WidgetInterface } from '../widget-interface';
export namespace ListIssuesByFieldsWidgetNs {
export type Params = {
fromRootIssueId?: number;
fromQuery?: nano.MangoQuery;
fields: Field[];
delimiter: string;
sort?: boolean;
statuses: string[];
} & TagStyledEnhancerNs.ConfigWithTagsStyles;
export type Field = {
path: string;
default: string;
};
}
type Params = ListIssuesByFieldsWidgetNs.Params;
@Injectable()
export class ListIssuesByFieldsWidgetService
implements WidgetInterface<Params, any, any>
{
private logger = new Logger(ListIssuesByFieldsWidgetService.name);
private issuesLoader: IssuesServiceNs.IssuesLoader;
constructor(
private issuesService: IssuesService,
private timePassedHighlightEnhancer: TimePassedHighlightEnhancer,
private issueUrlEnhancer: IssueUrlEnhancer,
) {
this.issuesLoader = this.issuesService.createDynamicIssuesLoader();
}
isMyConfig(): boolean {
return true;
}
async render(widgetParams: Params): Promise<any> {
let store: FlatIssuesStore;
if (widgetParams.fromRootIssueId) {
store = await this.getListFromRoot(widgetParams.fromRootIssueId);
} else if (widgetParams.fromQuery) {
store = await this.getListByQuery(widgetParams.fromQuery);
} else {
const errMsg = `Wrong widgetParams value`;
this.logger.error(errMsg);
throw new Error(errMsg);
}
await store.enhanceIssues([
this.timePassedHighlightEnhancer,
this.issueUrlEnhancer,
TagStyledEnhancerNs.CreateTagStyledEnhancerForConfig(widgetParams),
]);
const grouped = store.groupByStatusWithExtra((issue) => {
return this.getGroupFromIssue(issue, widgetParams);
}, widgetParams.statuses);
let res = [] as any[];
for (const key in grouped) {
if (Object.prototype.hasOwnProperty.call(grouped, key)) {
const data = grouped[key];
res.push({
data: data,
metainfo: this.createMetaInfo(key),
});
}
}
if (widgetParams.sort) {
res = res.sort((a, b) => {
return a.metainfo.title.localeCompare(b.metainfo.title);
});
}
return res;
}
private async getListFromRoot(issueId: number): Promise<FlatIssuesStore> {
const treeStore = new TreeIssuesStore();
const rootIssue = await this.issuesService.getIssue(issueId);
treeStore.setRootIssue(rootIssue);
await treeStore.fillData(this.issuesLoader);
return treeStore.getFlatStore();
}
private async getListByQuery(
query: nano.MangoQuery,
): Promise<FlatIssuesStore> {
const rawData = await this.issuesService.find(query);
const store = new FlatIssuesStore();
for (let i = 0; i < rawData.length; i++) {
const issue = rawData[i];
store.push(issue);
}
return store;
}
private getGroupFromIssue(
issue: RedmineTypes.ExtendedIssue,
params: Params,
): string | null {
if (!issue) return null;
const values = [] as string[];
for (let i = 0; i < params.fields.length; i++) {
const field = params.fields[i];
const valueResult = GetValueFromObjectByKey(issue, field.path);
const value: string = valueResult.result
? valueResult.result
: field.default;
values.push(value);
}
return values.join(params.delimiter);
}
private createMetaInfo(title: string): Record<string, any> {
return {
title: title,
};
}
}