/* 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 { 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 { 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 { 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 { 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 { return { title: title, }; } }