RED-3765: improve charts
This commit is contained in:
parent
e65db170d9
commit
2d5a2e4809
@ -1,8 +0,0 @@
|
|||||||
<google-chart
|
|
||||||
[columns]="['abc', options.vAxis.title, options.vAxes[1].title, 'license-info-screen.chart.cumulative' | translate]"
|
|
||||||
[data]="data"
|
|
||||||
[height]="300"
|
|
||||||
[options]="options"
|
|
||||||
[type]="type"
|
|
||||||
[width]="1000"
|
|
||||||
></google-chart>
|
|
||||||
@ -1,36 +1,43 @@
|
|||||||
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
|
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
|
||||||
import { ChartType } from 'angular-google-charts';
|
import { ChartType, Column, Row } from 'angular-google-charts';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
import { GoogleChartData } from './models';
|
import ComboChartOptions = google.visualization.ComboChartOptions;
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'redaction-google-chart',
|
selector: 'redaction-google-chart',
|
||||||
templateUrl: './google-chart.component.html',
|
template: ` <google-chart
|
||||||
styleUrls: ['./google-chart.component.scss'],
|
[columns]="columns"
|
||||||
|
[data]="data"
|
||||||
|
[height]="300"
|
||||||
|
[options]="options"
|
||||||
|
[type]="type"
|
||||||
|
[width]="1000"
|
||||||
|
></google-chart>`,
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
})
|
})
|
||||||
export class GoogleChartComponent {
|
export class GoogleChartComponent {
|
||||||
@Input() data: GoogleChartData;
|
@Input() data: Row[];
|
||||||
|
|
||||||
readonly options = {
|
readonly options: ComboChartOptions;
|
||||||
fontName: 'Inter',
|
readonly columns: Column[];
|
||||||
fontSize: 13,
|
|
||||||
vAxis: {
|
|
||||||
title: this._translateService.instant('license-info-screen.chart.pages-per-month'),
|
|
||||||
},
|
|
||||||
seriesType: 'bars',
|
|
||||||
vAxes: {
|
|
||||||
1: {
|
|
||||||
title: this._translateService.instant('license-info-screen.chart.total-pages'),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
series: { 1: { type: 'line', targetAxisIndex: 1 }, 2: { type: 'line', targetAxisIndex: 1 } },
|
|
||||||
colors: ['#0389ec', '#dd4d50', '#5ce594'],
|
|
||||||
legend: { position: 'top' },
|
|
||||||
};
|
|
||||||
readonly type = ChartType.ComboChart;
|
readonly type = ChartType.ComboChart;
|
||||||
readonly width = 1000;
|
|
||||||
readonly height = 300;
|
|
||||||
|
|
||||||
constructor(private readonly _translateService: TranslateService) {}
|
constructor(translateService: TranslateService) {
|
||||||
|
const pagesPerMonth = translateService.instant('license-info-screen.chart.pages-per-month');
|
||||||
|
const totalPages = translateService.instant('license-info-screen.chart.total-pages');
|
||||||
|
const cumulative = translateService.instant('license-info-screen.chart.cumulative');
|
||||||
|
|
||||||
|
this.options = {
|
||||||
|
fontName: 'Inter',
|
||||||
|
fontSize: 13,
|
||||||
|
vAxis: { title: pagesPerMonth },
|
||||||
|
seriesType: 'bars',
|
||||||
|
vAxes: { 1: { title: totalPages } },
|
||||||
|
series: { 1: { type: 'line', targetAxisIndex: 1 }, 2: { type: 'line', targetAxisIndex: 1 } },
|
||||||
|
colors: ['#0389ec', '#dd4d50', '#5ce594'],
|
||||||
|
legend: { position: 'top' },
|
||||||
|
};
|
||||||
|
|
||||||
|
this.columns = ['abc', pagesPerMonth, totalPages, cumulative];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1 +0,0 @@
|
|||||||
export type GoogleChartData = [string, number, number, number][];
|
|
||||||
@ -1 +0,0 @@
|
|||||||
<redaction-google-chart [data]="chartData$ | async"></redaction-google-chart>
|
|
||||||
@ -6,16 +6,13 @@ import { LicenseService } from '../services/license.service';
|
|||||||
import { IDateRange } from '../utils/date-range';
|
import { IDateRange } from '../utils/date-range';
|
||||||
import { ILicense } from '../utils/license';
|
import { ILicense } from '../utils/license';
|
||||||
import { switchMap, tap } from 'rxjs/operators';
|
import { switchMap, tap } from 'rxjs/operators';
|
||||||
import { LoadingService } from '@iqser/common-ui';
|
import { List, LoadingService } from '@iqser/common-ui';
|
||||||
import { generateDateRanges, isCurrentMonth, toDate } from '../utils/functions';
|
import { generateDateRanges, isCurrentMonth, toDate, verboseDate } from '../utils/functions';
|
||||||
import { GoogleChartData } from '../google-chart/models';
|
import { Row } from 'angular-google-charts';
|
||||||
|
|
||||||
const monthNames = dayjs.monthsShort();
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'redaction-license-chart',
|
selector: 'redaction-license-chart',
|
||||||
templateUrl: './license-chart.component.html',
|
template: '<redaction-google-chart [data]="chartData$ | async"></redaction-google-chart>',
|
||||||
styleUrls: ['./license-chart.component.scss'],
|
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
})
|
})
|
||||||
export class LicenseChartComponent {
|
export class LicenseChartComponent {
|
||||||
@ -26,12 +23,12 @@ export class LicenseChartComponent {
|
|||||||
get #chartData$() {
|
get #chartData$() {
|
||||||
return this._licenseService.selectedLicense$.pipe(
|
return this._licenseService.selectedLicense$.pipe(
|
||||||
tap(() => this._loadingService.start()),
|
tap(() => this._loadingService.start()),
|
||||||
switchMap(license => this.#chartData(license)),
|
switchMap(license => this.#getLicenseData(license)),
|
||||||
tap(() => this._loadingService.stop()),
|
tap(() => this._loadingService.stop()),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async #chartData(license: ILicense): Promise<GoogleChartData> {
|
async #getLicenseData(license: ILicense): Promise<Row[]> {
|
||||||
const startDate = dayjs(license.validFrom);
|
const startDate = dayjs(license.validFrom);
|
||||||
const endDate = dayjs(license.validUntil);
|
const endDate = dayjs(license.validUntil);
|
||||||
const startMonth: number = startDate.month();
|
const startMonth: number = startDate.month();
|
||||||
@ -40,31 +37,36 @@ export class LicenseChartComponent {
|
|||||||
const dateRanges = generateDateRanges(startMonth, startYear, endDate.month() as number, endDate.year() as number);
|
const dateRanges = generateDateRanges(startMonth, startYear, endDate.month() as number, endDate.year() as number);
|
||||||
const reports = await this.#getReports(dateRanges);
|
const reports = await this.#getReports(dateRanges);
|
||||||
|
|
||||||
|
return this.#mapRangesToReports(dateRanges, reports);
|
||||||
|
}
|
||||||
|
|
||||||
|
#mapRangesToReports(dateRanges: List<IDateRange>, reports: List<ILicenseReport>): Row[] {
|
||||||
let cumulativePages = 0;
|
let cumulativePages = 0;
|
||||||
|
const processingPages = this._licenseService.processingPages;
|
||||||
|
|
||||||
return dateRanges.map((range, index) => [
|
return dateRanges.map((range, index) => [
|
||||||
`${monthNames[range.startMonth]} ${range.startYear}`,
|
verboseDate(range),
|
||||||
reports[index].numberOfAnalyzedPages,
|
reports[index].numberOfAnalyzedPages,
|
||||||
this._licenseService.totalLicensedNumberOfPages,
|
processingPages,
|
||||||
(cumulativePages += reports[index].numberOfAnalyzedPages),
|
(cumulativePages += reports[index].numberOfAnalyzedPages),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#getReports(dateRanges: IDateRange[]) {
|
#getReports(dateRanges: List<IDateRange>) {
|
||||||
const reports = dateRanges.map(dateRange => {
|
const reports = dateRanges.map(range => {
|
||||||
const startMonth = dateRange.startMonth + 1;
|
const startMonth = range.startMonth + 1;
|
||||||
const endMonth = dateRange.endMonth + 1;
|
const endMonth = range.endMonth + 1;
|
||||||
|
|
||||||
const key = `${startMonth}.${dateRange.startYear}-${endMonth}.${dateRange.endYear}`;
|
const key = `${startMonth}.${range.startYear}-${endMonth}.${range.endYear}`;
|
||||||
const existingReport = this._licenseService.storedReports[key];
|
const existingReport = this._licenseService.storedReports[key];
|
||||||
if (existingReport) {
|
if (existingReport) {
|
||||||
return existingReport;
|
return existingReport;
|
||||||
}
|
}
|
||||||
|
|
||||||
const startDate = toDate(startMonth, dateRange.startYear);
|
const startDate = toDate(startMonth, range.startYear);
|
||||||
const endDate = toDate(endMonth, dateRange.endYear);
|
const endDate = toDate(endMonth, range.endYear);
|
||||||
const requestedReport = this._licenseService.getReport({ startDate, endDate });
|
const requestedReport = this._licenseService.getReport({ startDate, endDate });
|
||||||
return requestedReport.then(report => this.#storeReportIfNotCurrentMonth(dateRange, report, key));
|
return requestedReport.then(report => this.#storeReportIfNotCurrentMonth(range, report, key));
|
||||||
});
|
});
|
||||||
|
|
||||||
return Promise.all(reports);
|
return Promise.all(reports);
|
||||||
|
|||||||
@ -30,7 +30,7 @@ export class LicenseScreenComponent implements OnInit {
|
|||||||
totalInfo: ILicenseReport = {};
|
totalInfo: ILicenseReport = {};
|
||||||
unlicensedInfo: ILicenseReport = {};
|
unlicensedInfo: ILicenseReport = {};
|
||||||
analysisPercentageOfLicense = 100;
|
analysisPercentageOfLicense = 100;
|
||||||
totalLicensedNumberOfPages = this.licenseService.totalLicensedNumberOfPages;
|
totalLicensedNumberOfPages = this.licenseService.processingPages;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
readonly configService: ConfigService,
|
readonly configService: ConfigService,
|
||||||
@ -89,7 +89,7 @@ export class LicenseScreenComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
licenseChanged(license: ILicense) {
|
licenseChanged(license: ILicense) {
|
||||||
this.totalLicensedNumberOfPages = this.licenseService.totalLicensedNumberOfPages;
|
this.totalLicensedNumberOfPages = this.licenseService.processingPages;
|
||||||
return this.loadLicenseData(license);
|
return this.loadLicenseData(license);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -22,7 +22,7 @@ export class LicenseService extends GenericService<ILicenseReport> {
|
|||||||
return this.selectedLicense$.value;
|
return this.selectedLicense$.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
get totalLicensedNumberOfPages() {
|
get processingPages() {
|
||||||
const processingPagesFeature = this.selectedLicense$.value.features.find(f => f.name === 'processingPages');
|
const processingPagesFeature = this.selectedLicense$.value.features.find(f => f.name === 'processingPages');
|
||||||
return Number(processingPagesFeature.value ?? '0');
|
return Number(processingPagesFeature.value ?? '0');
|
||||||
}
|
}
|
||||||
|
|||||||
@ -39,3 +39,7 @@ export function isCurrentMonth(month: number, year: number) {
|
|||||||
|
|
||||||
return month === currentMonth && year === currentYear;
|
return month === currentMonth && year === currentYear;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const monthNames = dayjs.monthsShort();
|
||||||
|
|
||||||
|
export const verboseDate = (range: IDateRange) => `${monthNames[range.startMonth]} ${range.startYear}`;
|
||||||
|
|||||||
@ -79,6 +79,7 @@
|
|||||||
"@nrwl/jest": "13.9.5",
|
"@nrwl/jest": "13.9.5",
|
||||||
"@nrwl/linter": "13.9.5",
|
"@nrwl/linter": "13.9.5",
|
||||||
"@nrwl/workspace": "13.9.5",
|
"@nrwl/workspace": "13.9.5",
|
||||||
|
"@types/google.visualization": "^0.0.68",
|
||||||
"@types/jest": "27.4.1",
|
"@types/jest": "27.4.1",
|
||||||
"@types/lodash-es": "^4.17.6",
|
"@types/lodash-es": "^4.17.6",
|
||||||
"@types/node": "17.0.23",
|
"@types/node": "17.0.23",
|
||||||
|
|||||||
@ -2298,6 +2298,11 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@types/google.visualization/-/google.visualization-0.0.58.tgz#eb2aa3cf05d63a9b42ff5cfcab1fc0594fb45a0e"
|
resolved "https://registry.yarnpkg.com/@types/google.visualization/-/google.visualization-0.0.58.tgz#eb2aa3cf05d63a9b42ff5cfcab1fc0594fb45a0e"
|
||||||
integrity sha512-ldwrhRvqSlrCYjHELGZNNMP8m5oPLBb6iU7CfKF2C/YpgRTlHihqsrL5M293u0GL7mKfjm0AjSIgEE2LU8fuTw==
|
integrity sha512-ldwrhRvqSlrCYjHELGZNNMP8m5oPLBb6iU7CfKF2C/YpgRTlHihqsrL5M293u0GL7mKfjm0AjSIgEE2LU8fuTw==
|
||||||
|
|
||||||
|
"@types/google.visualization@^0.0.68":
|
||||||
|
version "0.0.68"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/google.visualization/-/google.visualization-0.0.68.tgz#773e908c02e08dffe689844f0972dd481516e704"
|
||||||
|
integrity sha512-LkLniL1TYykhz+ZdRof3Bi8cp1OhqoK11Tj1RM2bPtGVBNexQ0eRnOrOWcWTdi80Sz9DzJ4JIG2rTlSJBVV58w==
|
||||||
|
|
||||||
"@types/graceful-fs@^4.1.2":
|
"@types/graceful-fs@^4.1.2":
|
||||||
version "4.1.5"
|
version "4.1.5"
|
||||||
resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.5.tgz#21ffba0d98da4350db64891f92a9e5db3cdb4e15"
|
resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.5.tgz#21ffba0d98da4350db64891f92a9e5db3cdb4e15"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user