From 60d27f4dff45b7ff9d85ce95cd77644ca05ceb75 Mon Sep 17 00:00:00 2001 From: Dan Percic Date: Thu, 5 May 2022 17:53:55 +0300 Subject: [PATCH] RED-3765: extract chart to a separate component --- .../src/app/modules/admin/admin.module.ts | 6 +- .../screens/license-information/date-range.ts | 9 ++ .../license-chart.component.html | 18 +++ .../license-chart.component.scss | 0 .../license-chart/license-chart.component.ts | 123 ++++++++++++++++ .../license-information-screen.component.html | 44 ++---- .../license-information-screen.component.ts | 136 ++---------------- ...ent.html => select-license.component.html} | 2 +- ...ent.scss => select-license.component.scss} | 0 ...mponent.ts => select-license.component.ts} | 13 +- .../admin/services/licence-report.service.ts | 14 +- 11 files changed, 201 insertions(+), 164 deletions(-) create mode 100644 apps/red-ui/src/app/modules/admin/screens/license-information/date-range.ts create mode 100644 apps/red-ui/src/app/modules/admin/screens/license-information/license-chart/license-chart.component.html create mode 100644 apps/red-ui/src/app/modules/admin/screens/license-information/license-chart/license-chart.component.scss create mode 100644 apps/red-ui/src/app/modules/admin/screens/license-information/license-chart/license-chart.component.ts rename apps/red-ui/src/app/modules/admin/screens/license-information/select-licence/{select-licence.component.html => select-license.component.html} (91%) rename apps/red-ui/src/app/modules/admin/screens/license-information/select-licence/{select-licence.component.scss => select-license.component.scss} (100%) rename apps/red-ui/src/app/modules/admin/screens/license-information/select-licence/{select-licence.component.ts => select-license.component.ts} (68%) diff --git a/apps/red-ui/src/app/modules/admin/admin.module.ts b/apps/red-ui/src/app/modules/admin/admin.module.ts index 19db479bd..4693a3792 100644 --- a/apps/red-ui/src/app/modules/admin/admin.module.ts +++ b/apps/red-ui/src/app/modules/admin/admin.module.ts @@ -48,7 +48,8 @@ import { ConfirmDeleteDossierStateDialogComponent } from './dialogs/confirm-dele import { TrashTableItemComponent } from './screens/trash/trash-table-item/trash-table-item.component'; import { BaseEntityScreenComponent } from './base-entity-screen/base-entity-screen.component'; import { CloneDossierTemplateDialogComponent } from './dialogs/clone-dossier-template-dialog/clone-dossier-template-dialog.component'; -import { SelectLicenceComponent } from './screens/license-information/select-licence/select-licence.component'; +import { SelectLicenseComponent } from './screens/license-information/select-licence/select-license.component'; +import { LicenseChartComponent } from './screens/license-information/license-chart/license-chart.component'; const dialogs = [ AddEditDossierTemplateDialogComponent, @@ -103,7 +104,8 @@ const components = [ AddEditDossierStateDialogComponent, ConfirmDeleteDossierStateDialogComponent, TrashTableItemComponent, - SelectLicenceComponent, + SelectLicenseComponent, + LicenseChartComponent, ], providers: [AdminDialogService, AuditService, DigitalSignatureService, RulesService, SmtpConfigService], imports: [CommonModule, SharedModule, AdminRoutingModule, SharedAdminModule, NgxChartsModule, ColorPickerModule, A11yModule], diff --git a/apps/red-ui/src/app/modules/admin/screens/license-information/date-range.ts b/apps/red-ui/src/app/modules/admin/screens/license-information/date-range.ts new file mode 100644 index 000000000..6c18cc6d5 --- /dev/null +++ b/apps/red-ui/src/app/modules/admin/screens/license-information/date-range.ts @@ -0,0 +1,9 @@ +export interface IMonthYear { + readonly month: number; + readonly year: number; +} + +export interface IDateRange { + readonly startDate: IMonthYear; + readonly endDate: IMonthYear; +} diff --git a/apps/red-ui/src/app/modules/admin/screens/license-information/license-chart/license-chart.component.html b/apps/red-ui/src/app/modules/admin/screens/license-information/license-chart/license-chart.component.html new file mode 100644 index 000000000..8da1b9488 --- /dev/null +++ b/apps/red-ui/src/app/modules/admin/screens/license-information/license-chart/license-chart.component.html @@ -0,0 +1,18 @@ + diff --git a/apps/red-ui/src/app/modules/admin/screens/license-information/license-chart/license-chart.component.scss b/apps/red-ui/src/app/modules/admin/screens/license-information/license-chart/license-chart.component.scss new file mode 100644 index 000000000..e69de29bb diff --git a/apps/red-ui/src/app/modules/admin/screens/license-information/license-chart/license-chart.component.ts b/apps/red-ui/src/app/modules/admin/screens/license-information/license-chart/license-chart.component.ts new file mode 100644 index 000000000..207c1eca6 --- /dev/null +++ b/apps/red-ui/src/app/modules/admin/screens/license-information/license-chart/license-chart.component.ts @@ -0,0 +1,123 @@ +import { Component } from '@angular/core'; +import { ComboBarScheme, LineChartScheme } from '../constants'; +import dayjs from 'dayjs'; +import { TranslateService } from '@ngx-translate/core'; +import { ILicenseReport } from '@red/domain'; +import { LicenseService } from '../../../services/licence-report.service'; +import { IDateRange } from '../date-range'; +import { ILicense } from '../licence'; +import { switchMap } from 'rxjs/operators'; +import { ILineChartSeries } from '../../../components/combo-chart/models'; +import { ConfigService } from '../../../../../services/config.service'; + +const monthNames = dayjs.monthsShort(); + +function toDate(month: number, year: number) { + return dayjs(`01-${month}-${year}`, 'DD-M-YYYY').toDate(); +} + +@Component({ + selector: 'redaction-license-chart', + templateUrl: './license-chart.component.html', + styleUrls: ['./license-chart.component.scss'], +}) +export class LicenseChartComponent { + readonly lineChartScheme = LineChartScheme; + readonly comboBarScheme = ComboBarScheme; + + lineChartSeries$ = this._licenseService.selectedLicense$.pipe(switchMap(license => this.#setMonthlyStats(license))); + barChart: any[]; + + constructor( + private readonly _translateService: TranslateService, + private readonly _licenseService: LicenseService, + private readonly _configService: ConfigService, + ) {} + + async #setMonthlyStats(licence: ILicense): Promise { + const startDate = dayjs(licence.validFrom, 'DD-MM-YYYY'); + const endDate = dayjs(licence.validUntil, 'DD-MM-YYYY'); + const startMonth: number = startDate.month(); + const startYear: number = startDate.year(); + + const dateRanges = this.#generateDateRanges(startMonth, startYear, endDate.month(), endDate.year()); + const reports = await this.#getReports(dateRanges); + + return [ + { + name: this._translateService.instant('license-info-screen.chart.licensed-total'), + series: this.#totalLicensedPagesSeries(dateRanges), + }, + { + name: this._translateService.instant('license-info-screen.chart.cumulative'), + series: this.#setBarChartAndGetCumulativePageSeries(startMonth, startYear, reports), + }, + ]; + } + + #setBarChartAndGetCumulativePageSeries(month: number, year: number, reports: ILicenseReport[]) { + let cumulativePages = 0; + const cumulativePagesSeries = []; + this.barChart = []; + + for (const report of reports) { + cumulativePages += report.numberOfAnalyzedPages; + + const name = `${monthNames[month]} ${year}`; + this.barChart.push({ + name, + value: report.numberOfAnalyzedPages, + }); + + cumulativePagesSeries.push({ + name, + value: cumulativePages, + }); + + month++; + if (month === 12) { + month = 0; + year++; + } + } + + return cumulativePagesSeries; + } + + #getReports(dateRanges: IDateRange[]) { + const reports = dateRanges.map(dateRange => { + const startDate = toDate(dateRange.startDate.month + 1, dateRange.startDate.year); + const endDate = toDate(dateRange.endDate.month + 1, dateRange.endDate.year); + return this._licenseService.getReport({ startDate, endDate }); + }); + + return Promise.all(reports); + } + + #totalLicensedPagesSeries(dateRanges: IDateRange[]) { + return dateRanges.map(dateRange => ({ + name: `${monthNames[dateRange.startDate.month]} ${dateRange.startDate.year}`, + value: this._licenseService.totalLicensedNumberOfPages, + })); + } + + #generateDateRanges(month: number, year: number, endMonth: number, endYear: number) { + const dates: IDateRange[] = []; + + while (month <= endMonth && year <= endYear) { + let nextMonth = month + 1; + let nextYear = year; + if (nextMonth === 12) { + nextMonth = 0; + nextYear++; + } + + dates.push({ startDate: { month, year }, endDate: { month: nextMonth, year: nextYear } }); + + year = nextYear; + month = nextMonth; + } + + return dates; + } +} diff --git a/apps/red-ui/src/app/modules/admin/screens/license-information/license-information-screen.component.html b/apps/red-ui/src/app/modules/admin/screens/license-information/license-information-screen.component.html index 947c16001..5d0f57dd6 100644 --- a/apps/red-ui/src/app/modules/admin/screens/license-information/license-information-screen.component.html +++ b/apps/red-ui/src/app/modules/admin/screens/license-information/license-information-screen.component.html @@ -41,22 +41,24 @@
- +
-
-
-
{{ selectedLicense.licensedTo || '-' }}
-
- -
-
-
- {{ (selectedLicense.validFrom | date: 'dd-MM-YYYY') || '-' }} / - {{ (selectedLicense.validUntil | date: 'dd-MM-YYYY') || '-' }} + +
+
+
{{ selectedLicense.licensedTo || '-' }}
-
+ +
+
+
+ {{ (selectedLicense.validFrom | date: 'dd-MM-YYYY') || '-' }} / + {{ (selectedLicense.validUntil | date: 'dd-MM-YYYY') || '-' }} +
+
+
{{ 'license-info-screen.licensed-page-count' | translate }}
@@ -93,23 +95,7 @@
- + diff --git a/apps/red-ui/src/app/modules/admin/screens/license-information/license-information-screen.component.ts b/apps/red-ui/src/app/modules/admin/screens/license-information/license-information-screen.component.ts index 57703c432..0deef09ea 100644 --- a/apps/red-ui/src/app/modules/admin/screens/license-information/license-information-screen.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/license-information/license-information-screen.component.ts @@ -8,25 +8,8 @@ import { RouterHistoryService } from '@services/router-history.service'; import { LicenseService } from '../../services/licence-report.service'; import { ILicenseReport } from '@red/domain'; import dayjs from 'dayjs'; -import { ComboBarScheme, LineChartScheme } from './constants'; import { ILicense } from './licence'; -const monthNames = dayjs.monthsShort(); - -function toDate(month: number, year: number) { - return dayjs(`01-${month}-${year}`, 'DD-M-YYYY').toDate(); -} - -interface IMonthYear { - readonly month: number; - readonly year: number; -} - -interface IDateRange { - readonly startDate: IMonthYear; - readonly endDate: IMonthYear; -} - @Component({ selector: 'redaction-license-information-screen', templateUrl: './license-information-screen.component.html', @@ -34,8 +17,6 @@ interface IDateRange { providers: [LicenseService], }) export class LicenseInformationScreenComponent implements OnInit { - readonly lineChartScheme = LineChartScheme; - readonly comboBarScheme = ComboBarScheme; readonly currentYear = new Date().getFullYear(); readonly currentUser = this._userService.currentUser; readonly buttonConfigs: readonly ButtonConfig[] = [ @@ -50,10 +31,7 @@ export class LicenseInformationScreenComponent implements OnInit { totalInfo: ILicenseReport = {}; unlicensedInfo: ILicenseReport = {}; analysisPercentageOfLicense = 100; - barChart: any[]; - lineChartSeries: any[] = []; - selectedLicense = this.licenseService.getActiveLicense(); - totalLicensedNumberOfPages = this.#processingPages; + totalLicensedNumberOfPages = this.licenseService.totalLicensedNumberOfPages; constructor( readonly configService: ConfigService, @@ -66,22 +44,13 @@ export class LicenseInformationScreenComponent implements OnInit { _loadingService.start(); } - get #processingPages() { - const processingPagesFeature = this.selectedLicense.features.find(f => f.name === 'processingPages'); - return Number(processingPagesFeature.value ?? '0'); - } - ngOnInit() { - return this.loadLicenceData(); + return this.loadLicenceData(this.licenseService.selectedLicense); } - async loadLicenceData() { - // const startDate = dayjs(this.selectedLicense.validFrom, 'DD-MM-YYYY'); - // const endDate = dayjs(this.selectedLicense.validUntil, 'DD-MM-YYYY'); - const startDate = dayjs(this.configService.values.LICENSE_START, 'DD-MM-YYYY'); - const endDate = dayjs(this.configService.values.LICENSE_END, 'DD-MM-YYYY'); - - await this._setMonthlyStats(startDate, endDate); + async loadLicenceData(license: ILicense) { + const startDate = dayjs(license.validFrom, 'DD-MM-YYYY'); + const endDate = dayjs(license.validUntil, 'DD-MM-YYYY'); const currentConfig = { startDate: startDate.toDate(), @@ -103,7 +72,7 @@ export class LicenseInformationScreenComponent implements OnInit { } sendMail(): void { - const licenseCustomer = this.selectedLicense.licensedTo; + const licenseCustomer = this.licenseService.selectedLicense.licensedTo; const subject = this._translateService.instant('license-info-screen.email.title', { licenseCustomer, }); @@ -116,97 +85,12 @@ export class LicenseInformationScreenComponent implements OnInit { pages: this.totalLicensedNumberOfPages, }), ].join(lineBreak); - window.location.href = `mailto:${this.selectedLicense.licensedToEmail}?subject=${subject}&body=${body}`; + const mail = this.licenseService.selectedLicense.licensedToEmail; + window.location.href = `mailto:${mail}?subject=${subject}&body=${body}`; } licenceChanged(license: ILicense) { - this.selectedLicense = license; - this.totalLicensedNumberOfPages = this.#processingPages; - return this.loadLicenceData(); - } - - private async _setMonthlyStats(startDate: dayjs.Dayjs, endDate: dayjs.Dayjs) { - const startMonth: number = startDate.month(); - const startYear: number = startDate.year(); - - const dateRanges = this.#generateDateRanges(startMonth, startYear, endDate.month(), endDate.year()); - const reports = await this.#getReports(dateRanges); - - this.lineChartSeries = [ - { - name: this._translateService.instant('license-info-screen.chart.licensed-total'), - series: this.#totalLicensedPagesSeries(dateRanges), - }, - { - name: this._translateService.instant('license-info-screen.chart.cumulative'), - series: this.#setBarChartAndGetCumulativePageSeries(startMonth, startYear, reports), - }, - ]; - } - - #setBarChartAndGetCumulativePageSeries(month: number, year: number, reports: ILicenseReport[]) { - let cumulativePages = 0; - const cumulativePagesSeries = []; - this.barChart = []; - - for (const report of reports) { - cumulativePages += report.numberOfAnalyzedPages; - - const name = `${monthNames[month]} ${year}`; - this.barChart.push({ - name, - value: report.numberOfAnalyzedPages, - }); - - cumulativePagesSeries.push({ - name, - value: cumulativePages, - }); - - month++; - if (month === 12) { - month = 0; - year++; - } - } - - return cumulativePagesSeries; - } - - #getReports(dateRanges: IDateRange[]) { - const reports = dateRanges.map(dateRange => { - const startDate = toDate(dateRange.startDate.month + 1, dateRange.startDate.year); - const endDate = toDate(dateRange.endDate.month + 1, dateRange.endDate.year); - return this.licenseService.getReport({ startDate, endDate }); - }); - - return Promise.all(reports); - } - - #totalLicensedPagesSeries(dateRanges: IDateRange[]) { - return dateRanges.map(dateRange => ({ - name: `${monthNames[dateRange.startDate.month]} ${dateRange.startDate.year}`, - value: this.totalLicensedNumberOfPages, - })); - } - - #generateDateRanges(month: number, year: number, endMonth: number, endYear: number) { - const dates: IDateRange[] = []; - - while (month <= endMonth && year <= endYear) { - let nextMonth = month + 1; - let nextYear = year; - if (nextMonth === 12) { - nextMonth = 0; - nextYear++; - } - - dates.push({ startDate: { month, year }, endDate: { month: nextMonth, year: nextYear } }); - - year = nextYear; - month = nextMonth; - } - - return dates; + this.totalLicensedNumberOfPages = this.licenseService.totalLicensedNumberOfPages; + return this.loadLicenceData(license); } } diff --git a/apps/red-ui/src/app/modules/admin/screens/license-information/select-licence/select-licence.component.html b/apps/red-ui/src/app/modules/admin/screens/license-information/select-licence/select-license.component.html similarity index 91% rename from apps/red-ui/src/app/modules/admin/screens/license-information/select-licence/select-licence.component.html rename to apps/red-ui/src/app/modules/admin/screens/license-information/select-licence/select-license.component.html index e697dddfa..8e0ee84ac 100644 --- a/apps/red-ui/src/app/modules/admin/screens/license-information/select-licence/select-licence.component.html +++ b/apps/red-ui/src/app/modules/admin/screens/license-information/select-licence/select-license.component.html @@ -1,5 +1,5 @@
- + diff --git a/apps/red-ui/src/app/modules/admin/screens/license-information/select-licence/select-licence.component.scss b/apps/red-ui/src/app/modules/admin/screens/license-information/select-licence/select-license.component.scss similarity index 100% rename from apps/red-ui/src/app/modules/admin/screens/license-information/select-licence/select-licence.component.scss rename to apps/red-ui/src/app/modules/admin/screens/license-information/select-licence/select-license.component.scss diff --git a/apps/red-ui/src/app/modules/admin/screens/license-information/select-licence/select-licence.component.ts b/apps/red-ui/src/app/modules/admin/screens/license-information/select-licence/select-license.component.ts similarity index 68% rename from apps/red-ui/src/app/modules/admin/screens/license-information/select-licence/select-licence.component.ts rename to apps/red-ui/src/app/modules/admin/screens/license-information/select-licence/select-license.component.ts index a033f39f1..954521f9c 100644 --- a/apps/red-ui/src/app/modules/admin/screens/license-information/select-licence/select-licence.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/license-information/select-licence/select-license.component.ts @@ -9,11 +9,11 @@ const translations = { } as const; @Component({ - selector: 'redaction-select-licence', - templateUrl: './select-licence.component.html', - styleUrls: ['./select-licence.component.scss'], + selector: 'redaction-select-license', + templateUrl: './select-license.component.html', + styleUrls: ['./select-license.component.scss'], }) -export class SelectLicenceComponent { +export class SelectLicenseComponent { @Output() readonly valueChanges = new EventEmitter(); value = this.licenseService.getActiveLicense(); @@ -23,4 +23,9 @@ export class SelectLicenceComponent { getStatus(id) { return id === this.licenseService.activeLicenseId ? translations.active : translations.inactive; } + + licenseChanged($event: ILicense) { + this.valueChanges.emit($event); + this.licenseService.selectedLicense$.next($event); + } } diff --git a/apps/red-ui/src/app/modules/admin/services/licence-report.service.ts b/apps/red-ui/src/app/modules/admin/services/licence-report.service.ts index 1e80657d7..303112868 100644 --- a/apps/red-ui/src/app/modules/admin/services/licence-report.service.ts +++ b/apps/red-ui/src/app/modules/admin/services/licence-report.service.ts @@ -1,18 +1,28 @@ import { Injectable, Injector } from '@angular/core'; import { GenericService, QueryParam, RequiredParam, Validate } from '@iqser/common-ui'; import { ILicenseReport, ILicenseReportRequest } from '@red/domain'; -import { firstValueFrom } from 'rxjs'; -import { LICENSE_DATA } from '../screens/license-information/licence'; +import { BehaviorSubject, firstValueFrom } from 'rxjs'; +import { ILicense, LICENSE_DATA } from '../screens/license-information/licence'; @Injectable() export class LicenseService extends GenericService { readonly licenseData = LICENSE_DATA; readonly activeLicenseId = this.licenseData.activeLicense; + readonly selectedLicense$ = new BehaviorSubject(this.getActiveLicense()); constructor(protected readonly _injector: Injector) { super(_injector, 'report'); } + get selectedLicense() { + return this.selectedLicense$.value; + } + + get totalLicensedNumberOfPages() { + const processingPagesFeature = this.selectedLicense$.value.features.find(f => f.name === 'processingPages'); + return Number(processingPagesFeature.value ?? '0'); + } + getActiveLicense() { return this.licenseData.licenses.find(license => license.id === this.activeLicenseId); }