Добавлена новая доска по работникам как старая, только как в jira
This commit is contained in:
parent
eacbad3a02
commit
1f3964f5ca
8 changed files with 230 additions and 44 deletions
|
|
@ -24,6 +24,7 @@ import { DynamicLoader } from './configs/dynamic-loader';
|
||||||
import { RedminePublicUrlConverter } from './converters/redmine-public-url.converter';
|
import { RedminePublicUrlConverter } from './converters/redmine-public-url.converter';
|
||||||
import { IssueUrlEnhancer } from './issue-enhancers/issue-url-enhancer';
|
import { IssueUrlEnhancer } from './issue-enhancers/issue-url-enhancer';
|
||||||
import { ListIssuesByUsersWidgetService } from './project-dashboard/widgets/list-issues-by-users.widget.service';
|
import { ListIssuesByUsersWidgetService } from './project-dashboard/widgets/list-issues-by-users.widget.service';
|
||||||
|
import { ListIssuesByUsersLikeJiraWidgetService } from './project-dashboard/widgets/list-issues-by-users-like-jira.widget.service';
|
||||||
|
|
||||||
@Module({})
|
@Module({})
|
||||||
export class EventEmitterModule implements OnModuleInit {
|
export class EventEmitterModule implements OnModuleInit {
|
||||||
|
|
@ -52,6 +53,7 @@ export class EventEmitterModule implements OnModuleInit {
|
||||||
RedminePublicUrlConverter,
|
RedminePublicUrlConverter,
|
||||||
IssueUrlEnhancer,
|
IssueUrlEnhancer,
|
||||||
ListIssuesByUsersWidgetService,
|
ListIssuesByUsersWidgetService,
|
||||||
|
ListIssuesByUsersLikeJiraWidgetService,
|
||||||
],
|
],
|
||||||
exports: [
|
exports: [
|
||||||
EventEmitterService,
|
EventEmitterService,
|
||||||
|
|
@ -72,6 +74,7 @@ export class EventEmitterModule implements OnModuleInit {
|
||||||
RedminePublicUrlConverter,
|
RedminePublicUrlConverter,
|
||||||
IssueUrlEnhancer,
|
IssueUrlEnhancer,
|
||||||
ListIssuesByUsersWidgetService,
|
ListIssuesByUsersWidgetService,
|
||||||
|
ListIssuesByUsersLikeJiraWidgetService,
|
||||||
],
|
],
|
||||||
controllers: [MainController, UsersController, IssuesController],
|
controllers: [MainController, UsersController, IssuesController],
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* eslint-disable @typescript-eslint/no-namespace */
|
||||||
import { RedmineTypes } from '../models/redmine-types';
|
import { RedmineTypes } from '../models/redmine-types';
|
||||||
import { CacheTTL, Injectable, Logger } from '@nestjs/common';
|
import { CacheTTL, Injectable, Logger } from '@nestjs/common';
|
||||||
import { Issues } from '../couchdb-datasources/issues';
|
import { Issues } from '../couchdb-datasources/issues';
|
||||||
|
|
@ -12,6 +13,12 @@ import { GetParentsHint } from '../utils/get-parents-hint';
|
||||||
export const ISSUE_MEMORY_CACHE_LIFETIME = 30 * 1000;
|
export const ISSUE_MEMORY_CACHE_LIFETIME = 30 * 1000;
|
||||||
const ISSUE_MEMORY_CACHE_AUTOCLEAN_INTERVAL = 1000 * 60 * 5;
|
const ISSUE_MEMORY_CACHE_AUTOCLEAN_INTERVAL = 1000 * 60 * 5;
|
||||||
|
|
||||||
|
export namespace IssuesServiceNs {
|
||||||
|
export type IssuesLoader = (
|
||||||
|
ids: number[],
|
||||||
|
) => Promise<Record<number, RedmineTypes.Issue | null>>;
|
||||||
|
}
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class IssuesService {
|
export class IssuesService {
|
||||||
private logger = new Logger(IssuesService.name);
|
private logger = new Logger(IssuesService.name);
|
||||||
|
|
@ -143,4 +150,19 @@ export class IssuesService {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
createDynamicIssuesLoader(): IssuesServiceNs.IssuesLoader {
|
||||||
|
const fn = async (
|
||||||
|
ids: number[],
|
||||||
|
): Promise<Record<number, RedmineTypes.Issue>> => {
|
||||||
|
const issues = await this.getIssues(ids);
|
||||||
|
const res = {} as Record<number, RedmineTypes.Issue | null>;
|
||||||
|
for (let i = 0; i < issues.length; i++) {
|
||||||
|
const issue = issues[i];
|
||||||
|
res[issue.id] = issue;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
};
|
||||||
|
return fn;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,109 @@
|
||||||
|
/* eslint-disable @typescript-eslint/no-namespace */
|
||||||
|
import {
|
||||||
|
IssuesService,
|
||||||
|
IssuesServiceNs,
|
||||||
|
} from '@app/event-emitter/issues/issues.service';
|
||||||
|
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 ListIssuesByUsersLikeJiraWidgetNs {
|
||||||
|
export namespace Models {
|
||||||
|
export type Params = {
|
||||||
|
fromRootIssueId?: number;
|
||||||
|
fromQuery?: nano.MangoQuery;
|
||||||
|
userKeys: string[];
|
||||||
|
userSort?: boolean;
|
||||||
|
statuses: string[];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Params = ListIssuesByUsersLikeJiraWidgetNs.Models.Params;
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class ListIssuesByUsersLikeJiraWidgetService
|
||||||
|
implements WidgetInterface<Params, any, any>
|
||||||
|
{
|
||||||
|
private logger = new Logger(ListIssuesByUsersLikeJiraWidgetService.name);
|
||||||
|
private issuesLoader: IssuesServiceNs.IssuesLoader;
|
||||||
|
|
||||||
|
constructor(private issuesService: IssuesService) {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
const grouped = store.groupByStatusWithExtraToMultipleStories((issue) => {
|
||||||
|
const users = [] as string[];
|
||||||
|
for (let i = 0; i < widgetParams.userKeys.length; i++) {
|
||||||
|
const userKey = widgetParams.userKeys[i];
|
||||||
|
const userValue = GetValueFromObjectByKey(issue, userKey);
|
||||||
|
if (userValue.result) {
|
||||||
|
users.push(userValue.result);
|
||||||
|
} else {
|
||||||
|
users.push('Unknown Unknown');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return users;
|
||||||
|
}, widgetParams.statuses);
|
||||||
|
let res = [] as any[];
|
||||||
|
for (const user in grouped) {
|
||||||
|
if (Object.prototype.hasOwnProperty.call(grouped, user)) {
|
||||||
|
const data = grouped[user];
|
||||||
|
res.push({
|
||||||
|
data: data,
|
||||||
|
metainfo: this.createMetaInfo(user),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (widgetParams.userSort) {
|
||||||
|
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 createMetaInfo(user: string): Record<string, any> {
|
||||||
|
return {
|
||||||
|
title: user,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,11 @@
|
||||||
/* eslint-disable @typescript-eslint/no-namespace */
|
/* eslint-disable @typescript-eslint/no-namespace */
|
||||||
import { IssuesService } from '@app/event-emitter/issues/issues.service';
|
import {
|
||||||
|
IssuesService,
|
||||||
|
IssuesServiceNs,
|
||||||
|
} from '@app/event-emitter/issues/issues.service';
|
||||||
import { RedmineTypes } from '@app/event-emitter/models/redmine-types';
|
import { RedmineTypes } from '@app/event-emitter/models/redmine-types';
|
||||||
import { FlatIssuesStore } from '@app/event-emitter/utils/flat-issues-store';
|
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 { TreeIssuesStore } from '@app/event-emitter/utils/tree-issues-store';
|
||||||
import { Injectable, Logger } from '@nestjs/common';
|
import { Injectable, Logger } from '@nestjs/common';
|
||||||
import nano from 'nano';
|
import nano from 'nano';
|
||||||
|
|
@ -37,9 +41,10 @@ export class ListIssuesByUsersWidgetService
|
||||||
implements WidgetInterface<Params, any, any>
|
implements WidgetInterface<Params, any, any>
|
||||||
{
|
{
|
||||||
private logger = new Logger(ListIssuesByUsersWidgetService.name);
|
private logger = new Logger(ListIssuesByUsersWidgetService.name);
|
||||||
|
private issuesLoader: IssuesServiceNs.IssuesLoader;
|
||||||
|
|
||||||
constructor(private issuesService: IssuesService) {
|
constructor(private issuesService: IssuesService) {
|
||||||
return;
|
this.issuesLoader = this.issuesService.createDynamicIssuesLoader();
|
||||||
}
|
}
|
||||||
|
|
||||||
isMyConfig(): boolean {
|
isMyConfig(): boolean {
|
||||||
|
|
@ -54,7 +59,7 @@ export class ListIssuesByUsersWidgetService
|
||||||
store = await this.getListByQuery(widgetParams.fromQuery);
|
store = await this.getListByQuery(widgetParams.fromQuery);
|
||||||
} else {
|
} else {
|
||||||
const errMsg = `Wrong widgetParams value`;
|
const errMsg = `Wrong widgetParams value`;
|
||||||
this.logger.error(`Wrong widgetParams value`);
|
this.logger.error(errMsg);
|
||||||
throw new Error(errMsg);
|
throw new Error(errMsg);
|
||||||
}
|
}
|
||||||
const grouped = store.groupByStatusWithExtra((issue) => {
|
const grouped = store.groupByStatusWithExtra((issue) => {
|
||||||
|
|
@ -83,7 +88,7 @@ export class ListIssuesByUsersWidgetService
|
||||||
const treeStore = new TreeIssuesStore();
|
const treeStore = new TreeIssuesStore();
|
||||||
const rootIssue = await this.issuesService.getIssue(issueId);
|
const rootIssue = await this.issuesService.getIssue(issueId);
|
||||||
treeStore.setRootIssue(rootIssue);
|
treeStore.setRootIssue(rootIssue);
|
||||||
await treeStore.fillData(this.issuesLoader.bind(this));
|
await treeStore.fillData(this.issuesLoader);
|
||||||
return treeStore.getFlatStore();
|
return treeStore.getFlatStore();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -99,29 +104,13 @@ export class ListIssuesByUsersWidgetService
|
||||||
return store;
|
return store;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async issuesLoader(
|
|
||||||
ids: number[],
|
|
||||||
): Promise<Record<number, RedmineTypes.Issue | null>> {
|
|
||||||
const issues = await this.issuesService.getIssues(ids);
|
|
||||||
const res = {} as Record<number, RedmineTypes.Issue | null>;
|
|
||||||
for (let i = 0; i < issues.length; i++) {
|
|
||||||
const issue = issues[i];
|
|
||||||
res[issue.id] = issue;
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
private getUserValueByKey(issue: ExtendedIssue, key: string): FindResult {
|
private getUserValueByKey(issue: ExtendedIssue, key: string): FindResult {
|
||||||
const keys = key.split('.');
|
const value = GetValueFromObjectByKey(issue, key);
|
||||||
let res: any = issue;
|
if (value.result) {
|
||||||
for (let i = 0; i < keys.length; i++) {
|
return { result: value.result };
|
||||||
const k = keys[i];
|
} else {
|
||||||
if (!res.hasOwnProperty(k)) {
|
|
||||||
return { error: ListIssuesByUsersWidgetNs.Models.FindErrors.NOT_FOUND };
|
return { error: ListIssuesByUsersWidgetNs.Models.FindErrors.NOT_FOUND };
|
||||||
}
|
}
|
||||||
res = res[k];
|
|
||||||
}
|
|
||||||
return { result: res };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private createMetaInfo(user: string): Record<string, any> {
|
private createMetaInfo(user: string): Record<string, any> {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
/* eslint-disable @typescript-eslint/no-namespace */
|
/* eslint-disable @typescript-eslint/no-namespace */
|
||||||
import { IssuesService } from '@app/event-emitter/issues/issues.service';
|
import {
|
||||||
import { RedmineTypes } from '@app/event-emitter/models/redmine-types';
|
IssuesService,
|
||||||
|
IssuesServiceNs,
|
||||||
|
} from '@app/event-emitter/issues/issues.service';
|
||||||
import {
|
import {
|
||||||
TreeIssuesStore,
|
TreeIssuesStore,
|
||||||
TreeIssuesStoreNs,
|
TreeIssuesStoreNs,
|
||||||
|
|
@ -36,7 +38,11 @@ type Params = RootIssueSubTreesWidgetNs.Models.Params;
|
||||||
export class RootIssueSubTreesWidgetService
|
export class RootIssueSubTreesWidgetService
|
||||||
implements WidgetInterface<Params, any, any>
|
implements WidgetInterface<Params, any, any>
|
||||||
{
|
{
|
||||||
constructor(private issuesService: IssuesService) {}
|
private issuesLoader: IssuesServiceNs.IssuesLoader;
|
||||||
|
|
||||||
|
constructor(private issuesService: IssuesService) {
|
||||||
|
this.issuesLoader = this.issuesService.createDynamicIssuesLoader();
|
||||||
|
}
|
||||||
|
|
||||||
isMyConfig(): boolean {
|
isMyConfig(): boolean {
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -48,7 +54,7 @@ export class RootIssueSubTreesWidgetService
|
||||||
widgetParams.rootIssueId,
|
widgetParams.rootIssueId,
|
||||||
);
|
);
|
||||||
treeStore.setRootIssue(rootIssue);
|
treeStore.setRootIssue(rootIssue);
|
||||||
await treeStore.fillData(this.issuesLoader.bind(this));
|
await treeStore.fillData(this.issuesLoader);
|
||||||
let stories: TreeIssuesStoreNs.Models.GetFlatStories.Result;
|
let stories: TreeIssuesStoreNs.Models.GetFlatStories.Result;
|
||||||
if (widgetParams.parentsAsGroups) {
|
if (widgetParams.parentsAsGroups) {
|
||||||
stories = treeStore.getFlatStoriesByParents();
|
stories = treeStore.getFlatStoriesByParents();
|
||||||
|
|
@ -76,16 +82,4 @@ export class RootIssueSubTreesWidgetService
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private async issuesLoader(
|
|
||||||
ids: number[],
|
|
||||||
): Promise<Record<number, RedmineTypes.Issue | null>> {
|
|
||||||
const issues = await this.issuesService.getIssues(ids);
|
|
||||||
const res = {} as Record<number, RedmineTypes.Issue | null>;
|
|
||||||
for (let i = 0; i < issues.length; i++) {
|
|
||||||
const issue = issues[i];
|
|
||||||
res[issue.id] = issue;
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,9 @@
|
||||||
/* eslint-disable @typescript-eslint/no-namespace */
|
/* eslint-disable @typescript-eslint/no-namespace */
|
||||||
|
import { IssuesServiceNs } from '../issues/issues.service';
|
||||||
import { RedmineTypes } from '../models/redmine-types';
|
import { RedmineTypes } from '../models/redmine-types';
|
||||||
|
|
||||||
export namespace FlatIssuesStoreNs {
|
export namespace FlatIssuesStoreNs {
|
||||||
export type IssuesLoader = (
|
export type IssuesLoader = IssuesServiceNs.IssuesLoader;
|
||||||
ids: number[],
|
|
||||||
) => Promise<Record<number, RedmineTypes.Issue | null>>;
|
|
||||||
|
|
||||||
export namespace Models {
|
export namespace Models {
|
||||||
export type ByStatus = {
|
export type ByStatus = {
|
||||||
|
|
@ -178,4 +177,41 @@ export class FlatIssuesStore {
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
groupByToMultipleStories(
|
||||||
|
iteratee: (issue: RedmineTypes.Issue) => (string | number)[],
|
||||||
|
): Record<string | number, FlatIssuesStore> {
|
||||||
|
const res = {} as Record<string | number, FlatIssuesStore>;
|
||||||
|
const items = this.getIssues();
|
||||||
|
for (let i = 0; i < items.length; i++) {
|
||||||
|
const issue = items[i];
|
||||||
|
const keys = iteratee(issue);
|
||||||
|
for (let j = 0; j < keys.length; j++) {
|
||||||
|
const key = keys[j];
|
||||||
|
if (!Object.prototype.hasOwnProperty.call(res, key)) {
|
||||||
|
res[key] = new FlatIssuesStore();
|
||||||
|
}
|
||||||
|
res[key].push(issue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
groupByStatusWithExtraToMultipleStories(
|
||||||
|
iteratee: (issue: RedmineTypes.Issue) => (string | number)[],
|
||||||
|
statuses: string[],
|
||||||
|
): Record<string | number, FlatIssuesStoreNs.Models.ByStatuses> {
|
||||||
|
const res = {} as Record<
|
||||||
|
string | number,
|
||||||
|
FlatIssuesStoreNs.Models.ByStatuses
|
||||||
|
>;
|
||||||
|
const groupedIssues = this.groupByToMultipleStories(iteratee);
|
||||||
|
for (const key in groupedIssues) {
|
||||||
|
if (Object.prototype.hasOwnProperty.call(groupedIssues, key)) {
|
||||||
|
const store = groupedIssues[key];
|
||||||
|
res[key] = store.groupByStatus(statuses);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
15
libs/event-emitter/src/utils/get-value-from-object-by-key.ts
Normal file
15
libs/event-emitter/src/utils/get-value-from-object-by-key.ts
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
export function GetValueFromObjectByKey(
|
||||||
|
obj: any,
|
||||||
|
key: string,
|
||||||
|
): { result?: any; error?: string } {
|
||||||
|
const keys = key.split('.');
|
||||||
|
let res: any = obj;
|
||||||
|
for (let i = 0; i < keys.length; i++) {
|
||||||
|
const k = keys[i];
|
||||||
|
if (!res.hasOwnProperty(k)) {
|
||||||
|
return { error: 'NOT_FOUND' };
|
||||||
|
}
|
||||||
|
res = res[k];
|
||||||
|
}
|
||||||
|
return { result: res };
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import { DynamicLoader } from '@app/event-emitter/configs/dynamic-loader';
|
import { DynamicLoader } from '@app/event-emitter/configs/dynamic-loader';
|
||||||
|
import { ListIssuesByUsersLikeJiraWidgetService } from '@app/event-emitter/project-dashboard/widgets/list-issues-by-users-like-jira.widget.service';
|
||||||
import { ListIssuesByUsersWidgetService } from '@app/event-emitter/project-dashboard/widgets/list-issues-by-users.widget.service';
|
import { ListIssuesByUsersWidgetService } from '@app/event-emitter/project-dashboard/widgets/list-issues-by-users.widget.service';
|
||||||
import { RootIssueSubTreesWidgetService } from '@app/event-emitter/project-dashboard/widgets/root-issue-subtrees.widget.service';
|
import { RootIssueSubTreesWidgetService } from '@app/event-emitter/project-dashboard/widgets/root-issue-subtrees.widget.service';
|
||||||
import { Controller, Get, Param, Render } from '@nestjs/common';
|
import { Controller, Get, Param, Render } from '@nestjs/common';
|
||||||
|
|
@ -14,6 +15,7 @@ export class SimpleKanbanBoardController {
|
||||||
private dynamicLoader: DynamicLoader,
|
private dynamicLoader: DynamicLoader,
|
||||||
private configService: ConfigService,
|
private configService: ConfigService,
|
||||||
private listIssuesByUsersWidgetService: ListIssuesByUsersWidgetService,
|
private listIssuesByUsersWidgetService: ListIssuesByUsersWidgetService,
|
||||||
|
private listIssuesByUsersLikeJiraWidgetService: ListIssuesByUsersLikeJiraWidgetService,
|
||||||
) {
|
) {
|
||||||
this.path = this.configService.get<string>('simpleKanbanBoard.path');
|
this.path = this.configService.get<string>('simpleKanbanBoard.path');
|
||||||
}
|
}
|
||||||
|
|
@ -49,4 +51,20 @@ export class SimpleKanbanBoardController {
|
||||||
async getByUsers(@Param('name') name: string): Promise<any> {
|
async getByUsers(@Param('name') name: string): Promise<any> {
|
||||||
return await this.getByUsersRawData(name);
|
return await this.getByUsersRawData(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Get('/by-users-like-jira/:name/raw')
|
||||||
|
async getByUsersLikeJiraRawData(@Param('name') name: string): Promise<any> {
|
||||||
|
const cfg = this.dynamicLoader.load(name, {
|
||||||
|
path: this.path,
|
||||||
|
ext: 'jsonc',
|
||||||
|
parser: parse,
|
||||||
|
});
|
||||||
|
return await this.listIssuesByUsersLikeJiraWidgetService.render(cfg);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Get('/by-users-like-jira/:name')
|
||||||
|
@Render('simple-kanban-board')
|
||||||
|
async getByUsersLikeJira(@Param('name') name: string): Promise<any> {
|
||||||
|
return await this.getByUsersLikeJiraRawData(name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue