backup draft
This commit is contained in:
parent
628412ffc5
commit
5913609f96
8 changed files with 223 additions and 81 deletions
75
frontend/package-lock.json
generated
75
frontend/package-lock.json
generated
|
|
@ -17,6 +17,7 @@
|
|||
"@types/react": "^18.0.28",
|
||||
"@types/react-dom": "^18.0.11",
|
||||
"axios": "^1.4.0",
|
||||
"jsonpath-plus": "^10.3.0",
|
||||
"luxon": "^3.3.0",
|
||||
"mobx": "^6.9.0",
|
||||
"mobx-react-lite": "^3.4.3",
|
||||
|
|
@ -2974,6 +2975,28 @@
|
|||
"@jridgewell/sourcemap-codec": "1.4.14"
|
||||
}
|
||||
},
|
||||
"node_modules/@jsep-plugin/assignment": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@jsep-plugin/assignment/-/assignment-1.3.0.tgz",
|
||||
"integrity": "sha512-VVgV+CXrhbMI3aSusQyclHkenWSAm95WaiKrMxRFam3JSUiIaQjoMIw2sEs/OX4XifnqeQUN4DYbJjlA8EfktQ==",
|
||||
"engines": {
|
||||
"node": ">= 10.16.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"jsep": "^0.4.0||^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@jsep-plugin/regex": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@jsep-plugin/regex/-/regex-1.0.4.tgz",
|
||||
"integrity": "sha512-q7qL4Mgjs1vByCaTnDFcBnV9HS7GVPJX5vyVoCgZHNSC9rjwIlmbXG5sUuorR5ndfHAIlJ8pVStxvjXHbNvtUg==",
|
||||
"engines": {
|
||||
"node": ">= 10.16.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"jsep": "^0.4.0||^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@leichtgewicht/ip-codec": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz",
|
||||
|
|
@ -11430,6 +11453,14 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"node_modules/jsep": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/jsep/-/jsep-1.4.0.tgz",
|
||||
"integrity": "sha512-B7qPcEVE3NVkmSJbaYxvv4cHkVW7DQsZz13pUMrfS8z8Q/BuShN+gcTXrUlPiGqM2/t/EEaI030bpxMqY8gMlw==",
|
||||
"engines": {
|
||||
"node": ">= 10.16.0"
|
||||
}
|
||||
},
|
||||
"node_modules/jsesc": {
|
||||
"version": "2.5.2",
|
||||
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
|
||||
|
|
@ -11483,6 +11514,23 @@
|
|||
"graceful-fs": "^4.1.6"
|
||||
}
|
||||
},
|
||||
"node_modules/jsonpath-plus": {
|
||||
"version": "10.3.0",
|
||||
"resolved": "https://registry.npmjs.org/jsonpath-plus/-/jsonpath-plus-10.3.0.tgz",
|
||||
"integrity": "sha512-8TNmfeTCk2Le33A3vRRwtuworG/L5RrgMvdjhKZxvyShO+mBu2fP50OWUjRLNtvw344DdDarFh9buFAZs5ujeA==",
|
||||
"dependencies": {
|
||||
"@jsep-plugin/assignment": "^1.3.0",
|
||||
"@jsep-plugin/regex": "^1.0.4",
|
||||
"jsep": "^1.4.0"
|
||||
},
|
||||
"bin": {
|
||||
"jsonpath": "bin/jsonpath-cli.js",
|
||||
"jsonpath-plus": "bin/jsonpath-cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/jsonpointer": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.1.tgz",
|
||||
|
|
@ -19116,6 +19164,18 @@
|
|||
"@jridgewell/sourcemap-codec": "1.4.14"
|
||||
}
|
||||
},
|
||||
"@jsep-plugin/assignment": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@jsep-plugin/assignment/-/assignment-1.3.0.tgz",
|
||||
"integrity": "sha512-VVgV+CXrhbMI3aSusQyclHkenWSAm95WaiKrMxRFam3JSUiIaQjoMIw2sEs/OX4XifnqeQUN4DYbJjlA8EfktQ==",
|
||||
"requires": {}
|
||||
},
|
||||
"@jsep-plugin/regex": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@jsep-plugin/regex/-/regex-1.0.4.tgz",
|
||||
"integrity": "sha512-q7qL4Mgjs1vByCaTnDFcBnV9HS7GVPJX5vyVoCgZHNSC9rjwIlmbXG5sUuorR5ndfHAIlJ8pVStxvjXHbNvtUg==",
|
||||
"requires": {}
|
||||
},
|
||||
"@leichtgewicht/ip-codec": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz",
|
||||
|
|
@ -25275,6 +25335,11 @@
|
|||
"xml-name-validator": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"jsep": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/jsep/-/jsep-1.4.0.tgz",
|
||||
"integrity": "sha512-B7qPcEVE3NVkmSJbaYxvv4cHkVW7DQsZz13pUMrfS8z8Q/BuShN+gcTXrUlPiGqM2/t/EEaI030bpxMqY8gMlw=="
|
||||
},
|
||||
"jsesc": {
|
||||
"version": "2.5.2",
|
||||
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
|
||||
|
|
@ -25314,6 +25379,16 @@
|
|||
"universalify": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"jsonpath-plus": {
|
||||
"version": "10.3.0",
|
||||
"resolved": "https://registry.npmjs.org/jsonpath-plus/-/jsonpath-plus-10.3.0.tgz",
|
||||
"integrity": "sha512-8TNmfeTCk2Le33A3vRRwtuworG/L5RrgMvdjhKZxvyShO+mBu2fP50OWUjRLNtvw344DdDarFh9buFAZs5ujeA==",
|
||||
"requires": {
|
||||
"@jsep-plugin/assignment": "^1.3.0",
|
||||
"@jsep-plugin/regex": "^1.0.4",
|
||||
"jsep": "^1.4.0"
|
||||
}
|
||||
},
|
||||
"jsonpointer": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.1.tgz",
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
"@types/react": "^18.0.28",
|
||||
"@types/react-dom": "^18.0.11",
|
||||
"axios": "^1.4.0",
|
||||
"jsonpath-plus": "^10.3.0",
|
||||
"luxon": "^3.3.0",
|
||||
"mobx": "^6.9.0",
|
||||
"mobx-react-lite": "^3.4.3",
|
||||
|
|
|
|||
|
|
@ -58,6 +58,8 @@ import { DailyEccmV2ReportTaskRunnerService } from './reports/daily-eccm-v2-repo
|
|||
import { DashboardsService } from '@app/event-emitter/dashboards/dashboards.service';
|
||||
import { DailyEccmReportsV2Datasource } from './couchdb-datasources/daily-eccm-reports-v2.datasource';
|
||||
import { DailyEccmReportsV2DataLoaderService } from './eccm-statistic/dashboards/widget-data-loader/daily-eccm-v2.widget-data-loader.service';
|
||||
import { DailyEccmV2ReportController } from './reports/daily-eccm-v2-report.controller';
|
||||
import { DailyEccmV2ReportService } from './reports/daily-eccm-v2-report.service';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
|
|
@ -82,6 +84,7 @@ import { DailyEccmReportsV2DataLoaderService } from './eccm-statistic/dashboards
|
|||
SimpleIssuesListController,
|
||||
TagsManagerController,
|
||||
TelegramBotController,
|
||||
DailyEccmV2ReportController,
|
||||
],
|
||||
providers: [
|
||||
AppService,
|
||||
|
|
@ -123,6 +126,7 @@ import { DailyEccmReportsV2DataLoaderService } from './eccm-statistic/dashboards
|
|||
DailyEccmReportsV2Datasource,
|
||||
DailyEccmV2ReportTaskRunnerService,
|
||||
DailyEccmReportsV2DataLoaderService,
|
||||
DailyEccmV2ReportService,
|
||||
],
|
||||
})
|
||||
export class AppModule implements OnModuleInit {
|
||||
|
|
|
|||
13
src/eccm-statistic/reviewers.service.ts
Normal file
13
src/eccm-statistic/reviewers.service.ts
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
import { RedmineTypes } from '@app/event-emitter/models/redmine-types';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
@Injectable()
|
||||
export class ReviewersService {
|
||||
constructor() {
|
||||
return;
|
||||
}
|
||||
|
||||
async getTasks(): Promise<RedmineTypes.ExtendedIssue[]> {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,77 +0,0 @@
|
|||
import { Logger } from '@nestjs/common';
|
||||
import { IssuesService } from '@app/event-emitter/issues/issues.service';
|
||||
|
||||
export type Params = {
|
||||
query: any; // TODO: add type
|
||||
schedule: string;
|
||||
};
|
||||
|
||||
export type Report = {
|
||||
id: string;
|
||||
name: string;
|
||||
datetime: number;
|
||||
datetimeFormatted: string;
|
||||
jobInfo: JobInfo;
|
||||
params: Params; // query?, schedule?, etc TODO
|
||||
data: any;
|
||||
};
|
||||
|
||||
export type JobInfo = {
|
||||
jobId: string;
|
||||
dashboardId: string;
|
||||
widgetId: string;
|
||||
};
|
||||
|
||||
export class DailyEccmV2ReportTaskHandlerService {
|
||||
private logger = new Logger(DailyEccmV2ReportTaskHandlerService.name);
|
||||
|
||||
private issuesService: IssuesService | null = null;
|
||||
|
||||
constructor(public params: Params, public jobInfo: JobInfo) {
|
||||
return;
|
||||
}
|
||||
|
||||
setIssuesService(issuesService: IssuesService): void {
|
||||
this.issuesService = issuesService;
|
||||
}
|
||||
|
||||
getIssuesService(): IssuesService | null {
|
||||
if (!this.issuesService) {
|
||||
this.logger.warn(
|
||||
'DailyEccmV2ReportTaskHandlerService is not initialized, issuesService is null',
|
||||
);
|
||||
return null;
|
||||
}
|
||||
return this.issuesService;
|
||||
}
|
||||
|
||||
async createReport(): Promise<void> {
|
||||
try {
|
||||
const report = await this.prepareReportData();
|
||||
await this.saveNewReport(report);
|
||||
} catch (error) {
|
||||
this.logger.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
async prepareReportData(): Promise<Report> {
|
||||
const issuesService = this.getIssuesService();
|
||||
if (!issuesService) {
|
||||
throw new Error(
|
||||
'Cannot create report without issuesService, DailyEccmV2ReportTaskHandlerService is not initialized',
|
||||
);
|
||||
}
|
||||
const issues = await this.issuesService.mergedTreesAndFind(
|
||||
this.params.query,
|
||||
);
|
||||
return {} as Report;
|
||||
}
|
||||
|
||||
async saveNewReport(report: Report): Promise<boolean> {
|
||||
return true;
|
||||
}
|
||||
|
||||
async updatePreviousReport(report: Report): Promise<boolean> {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -8,11 +8,11 @@ import { DailyEccmReportsV2Datasource } from 'src/couchdb-datasources/daily-eccm
|
|||
import { randomUUID } from 'crypto';
|
||||
import { RedmineTypes } from '@app/event-emitter/models/redmine-types';
|
||||
import { DateTime } from 'luxon';
|
||||
import { Params } from './daily-eccm-v2-report-task-handler';
|
||||
// import { Params } from './daily-eccm-v2-report-task-handler';
|
||||
|
||||
export type Job = {
|
||||
id: string;
|
||||
params: Params;
|
||||
params: any;
|
||||
};
|
||||
|
||||
export type JobHandlerParams = {
|
||||
|
|
|
|||
30
src/reports/daily-eccm-v2-report.controller.ts
Normal file
30
src/reports/daily-eccm-v2-report.controller.ts
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
import { Controller, Get, Param, Query, Logger } from '@nestjs/common';
|
||||
import { DailyEccmV2ReportService } from './daily-eccm-v2-report.service';
|
||||
|
||||
@Controller('/api/daily-eccm-v2-report')
|
||||
export class DailyEccmV2ReportController {
|
||||
private logger = new Logger(DailyEccmV2ReportController.name);
|
||||
|
||||
constructor(private dailyEccmV2ReportService: DailyEccmV2ReportService) {
|
||||
return;
|
||||
}
|
||||
|
||||
@Get(':dashboardId/:widgetId/list')
|
||||
async getList(@Param() params: any, @Query() query: any): Promise<any> {
|
||||
const getListParams: any = {
|
||||
dashboardId: params.dashboardId,
|
||||
widgetId: params.widgetId,
|
||||
};
|
||||
if (query.limit) getListParams.limit = parseInt(query.limit);
|
||||
if (query.after) getListParams.after = query.after;
|
||||
if (query.before) getListParams.before = query.before;
|
||||
return this.dailyEccmV2ReportService.getList(getListParams);
|
||||
}
|
||||
|
||||
@Get(':dashboardId/:widgetId/latest')
|
||||
async getLatest(@Param() params: any): Promise<any> {
|
||||
const dashboardId = params.dashboardId;
|
||||
const widgetId = params.widgetId;
|
||||
return this.dailyEccmV2ReportService.getLatest(dashboardId, widgetId);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,100 @@
|
|||
import { Injectable } from '@nestjs/common';
|
||||
import { Injectable, Logger } from '@nestjs/common';
|
||||
import { DailyEccmReportsV2Datasource } from 'src/couchdb-datasources/daily-eccm-reports-v2.datasource';
|
||||
import { DateTime } from 'luxon';
|
||||
|
||||
export type ListProps = {
|
||||
dashboardId: string;
|
||||
widgetId: string;
|
||||
limit?: number;
|
||||
/** Milliseconds since Unix epoch */
|
||||
after?: number | string;
|
||||
/** Milliseconds since Unix epoch */
|
||||
before?: number | string;
|
||||
};
|
||||
|
||||
@Injectable()
|
||||
export class DailyEccmV2ReportService {}
|
||||
export class DailyEccmV2ReportService {
|
||||
private logger = new Logger(DailyEccmV2ReportService.name);
|
||||
|
||||
constructor() {
|
||||
return;
|
||||
}
|
||||
|
||||
async getList(props: ListProps): Promise<any[]> {
|
||||
const ds = await DailyEccmReportsV2Datasource.getDatasource();
|
||||
const findQuery: any = {
|
||||
selector: {
|
||||
$and: [
|
||||
{ dashboardId: props.dashboardId },
|
||||
{ widgetId: props.widgetId },
|
||||
],
|
||||
},
|
||||
fields: [
|
||||
'id',
|
||||
'dashboardId',
|
||||
'widgetId',
|
||||
'datetime',
|
||||
'datetimeFormatted',
|
||||
],
|
||||
sort: [
|
||||
{
|
||||
datetime: 'asc',
|
||||
},
|
||||
],
|
||||
};
|
||||
if (props.after) {
|
||||
const after =
|
||||
typeof props.after === 'string'
|
||||
? DateTime.fromISO(props.after).toMillis()
|
||||
: Number(props.after);
|
||||
findQuery.selector.$and.push({ datetime: { $gte: after } });
|
||||
}
|
||||
if (props.before) {
|
||||
const before =
|
||||
typeof props.before === 'string'
|
||||
? DateTime.fromISO(props.before).toMillis()
|
||||
: Number(props.before);
|
||||
findQuery.selector.$and.push({ datetime: { $lte: before } });
|
||||
}
|
||||
if (props.limit) {
|
||||
findQuery.limit = props.limit;
|
||||
}
|
||||
this.logger.log(
|
||||
`Get list daily eccm v2 report with query: ${JSON.stringify(findQuery)}`,
|
||||
);
|
||||
|
||||
const result = await ds.find(findQuery);
|
||||
if (result && result.docs) {
|
||||
return result.docs as any;
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
async getLatest(dashboardId: string, widgetId: string): Promise<any> {
|
||||
const ds = await DailyEccmReportsV2Datasource.getDatasource();
|
||||
const findQuery: any = {
|
||||
selector: {
|
||||
$and: [
|
||||
{ dashboardId: dashboardId },
|
||||
{ widgetId: widgetId },
|
||||
{ latest: true },
|
||||
],
|
||||
},
|
||||
fields: [
|
||||
'id',
|
||||
'dashboardId',
|
||||
'widgetId',
|
||||
'datetime',
|
||||
'datetimeFormatted',
|
||||
'reportIssues',
|
||||
'issuesMetrics',
|
||||
],
|
||||
limit: 1,
|
||||
};
|
||||
const result = await ds.find(findQuery);
|
||||
if (result && result.docs) {
|
||||
return result.docs[0] as any;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue