diff --git a/apps/red-ui/src/app/modules/admin/screens/license/license-chart/license-chart.component.ts b/apps/red-ui/src/app/modules/admin/screens/license/license-chart/license-chart.component.ts index 1f64cec27..107353d82 100644 --- a/apps/red-ui/src/app/modules/admin/screens/license/license-chart/license-chart.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/license/license-chart/license-chart.component.ts @@ -1,21 +1,18 @@ import { Component } from '@angular/core'; -import { ComboBarScheme, LineChartScheme } from '../utils/constants'; +import { ComboBarScheme, LICENSE_STORAGE_KEY, LineChartScheme } from '../utils/constants'; import dayjs from 'dayjs'; import { TranslateService } from '@ngx-translate/core'; import { ILicenseReport } from '@red/domain'; import { LicenseService } from '../services/license.service'; import { IDateRange } from '../utils/date-range'; import { ILicense } from '../utils/license'; -import { switchMap } from 'rxjs/operators'; +import { switchMap, tap } from 'rxjs/operators'; import { ILineChartSeries } from '../combo-chart/models'; -import { ConfigService } from '../../../../../services/config.service'; +import { LoadingService } from '@iqser/common-ui'; +import { generateDateRanges, isCurrentMonth, toDate } from '../utils/functions'; 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', @@ -25,22 +22,30 @@ export class LicenseChartComponent { readonly lineChartScheme = LineChartScheme; readonly comboBarScheme = ComboBarScheme; - lineChartSeries$ = this._licenseService.selectedLicense$.pipe(switchMap(license => this.#setMonthlyStats(license))); + lineChartSeries$ = this.#licenseChartSeries$; barChart: any[]; constructor( private readonly _translateService: TranslateService, private readonly _licenseService: LicenseService, - private readonly _configService: ConfigService, + private readonly _loadingService: LoadingService, ) {} + get #licenseChartSeries$() { + return this._licenseService.selectedLicense$.pipe( + tap(() => this._loadingService.start()), + switchMap(license => this.#setMonthlyStats(license)), + tap(() => this._loadingService.stop()), + ); + } + async #setMonthlyStats(licence: ILicense): Promise { - const startDate = dayjs(licence.validFrom, 'DD-MM-YYYY'); - const endDate = dayjs(licence.validUntil, 'DD-MM-YYYY'); + const startDate = dayjs(licence.validFrom); + const endDate = dayjs(licence.validUntil); const startMonth: number = startDate.month(); const startYear: number = startDate.year(); - const dateRanges = this.#generateDateRanges(startMonth, startYear, endDate.month(), endDate.year()); + const dateRanges = generateDateRanges(startMonth, startYear, endDate.month(), endDate.year()); const reports = await this.#getReports(dateRanges); return [ @@ -86,38 +91,37 @@ export class LicenseChartComponent { #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 }); + const startMonth = dateRange.startMonth + 1; + const endMonth = dateRange.endMonth + 1; + + const key = `${startMonth}.${dateRange.startYear}-${endMonth}.${dateRange.endYear}`; + const existingReport = this._licenseService.storedReports[key]; + if (existingReport) { + return existingReport; + } + + const startDate = toDate(startMonth, dateRange.startYear); + const endDate = toDate(endMonth, dateRange.endYear); + const requestedReport = this._licenseService.getReport({ startDate, endDate }); + return requestedReport.then(report => this.#storeReportIfNotCurrentMonth(dateRange, report, key)); }); return Promise.all(reports); } + #storeReportIfNotCurrentMonth(dateRange: IDateRange, report: ILicenseReport, key: string) { + if (!isCurrentMonth(dateRange.startMonth + 1, dateRange.startYear)) { + this._licenseService.storedReports[key] = report; + localStorage.setItem(LICENSE_STORAGE_KEY, JSON.stringify(this._licenseService.storedReports)); + } + + return report; + } + #totalLicensedPagesSeries(dateRanges: IDateRange[]) { return dateRanges.map(dateRange => ({ - name: `${monthNames[dateRange.startDate.month]} ${dateRange.startDate.year}`, + name: `${monthNames[dateRange.startMonth]} ${dateRange.startYear}`, 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/license-screen/license-screen.component.html b/apps/red-ui/src/app/modules/admin/screens/license/license-screen/license-screen.component.html index a762eefda..1d4e9834f 100644 --- a/apps/red-ui/src/app/modules/admin/screens/license/license-screen/license-screen.component.html +++ b/apps/red-ui/src/app/modules/admin/screens/license/license-screen/license-screen.component.html @@ -34,7 +34,7 @@
-
+
diff --git a/apps/red-ui/src/app/modules/admin/screens/license/license-screen/license-screen.component.ts b/apps/red-ui/src/app/modules/admin/screens/license/license-screen/license-screen.component.ts index b42e04ca2..8f080de93 100644 --- a/apps/red-ui/src/app/modules/admin/screens/license/license-screen/license-screen.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/license/license-screen/license-screen.component.ts @@ -9,6 +9,7 @@ import { LicenseService } from '../services/license.service'; import { ILicenseReport } from '@red/domain'; import dayjs from 'dayjs'; import { ILicense } from '../utils/license'; +import { UserPreferenceService } from '../../../../../services/user-preference.service'; @Component({ templateUrl: './license-screen.component.html', @@ -33,6 +34,7 @@ export class LicenseScreenComponent implements OnInit { constructor( readonly configService: ConfigService, + readonly userPreferenceService: UserPreferenceService, readonly licenseService: LicenseService, private readonly _userService: UserService, private readonly _loadingService: LoadingService, @@ -47,8 +49,8 @@ export class LicenseScreenComponent implements OnInit { } async loadLicenceData(license: ILicense) { - const startDate = dayjs(license.validFrom, 'DD-MM-YYYY'); - const endDate = dayjs(license.validUntil, 'DD-MM-YYYY'); + const startDate = dayjs(license.validFrom); + const endDate = dayjs(license.validUntil); const currentConfig = { startDate: startDate.toDate(), @@ -64,7 +66,6 @@ export class LicenseScreenComponent implements OnInit { } [this.currentInfo, this.totalInfo, this.unlicensedInfo] = await Promise.all(reports); - this._loadingService.stop(); this.analysisPercentageOfLicense = this.totalLicensedNumberOfPages > 0 ? (this.currentInfo.numberOfAnalyzedPages / this.totalLicensedNumberOfPages) * 100 : 100; } diff --git a/apps/red-ui/src/app/modules/admin/screens/license/services/license.service.ts b/apps/red-ui/src/app/modules/admin/screens/license/services/license.service.ts index d16c98ca0..d3081f9da 100644 --- a/apps/red-ui/src/app/modules/admin/screens/license/services/license.service.ts +++ b/apps/red-ui/src/app/modules/admin/screens/license/services/license.service.ts @@ -2,15 +2,19 @@ import { Injectable, Injector } from '@angular/core'; import { GenericService, QueryParam, RequiredParam, Validate } from '@iqser/common-ui'; import { ILicenseReport, ILicenseReportRequest } from '@red/domain'; import { BehaviorSubject, firstValueFrom } from 'rxjs'; -import { ILicense, LICENSE_DATA } from '../utils/license'; +import { ILicense, ILicenses, LICENSE_DATA } from '../utils/license'; +import { ConfigService } from '../../../../../services/config.service'; +import dayjs from 'dayjs'; +import { getStoredReports } from '../utils/functions'; @Injectable() export class LicenseService extends GenericService { - readonly licenseData = LICENSE_DATA; + storedReports = getStoredReports(); + readonly licenseData = this.#licenceData; readonly activeLicenseId = this.licenseData.activeLicense; readonly selectedLicense$ = new BehaviorSubject(this.getActiveLicense()); - constructor(protected readonly _injector: Injector) { + constructor(protected readonly _injector: Injector, private readonly _configService: ConfigService) { super(_injector, 'report'); } @@ -23,6 +27,36 @@ export class LicenseService extends GenericService { return Number(processingPagesFeature.value ?? '0'); } + get #licenceData(): ILicenses { + return { + ...LICENSE_DATA, + licenses: [ + ...LICENSE_DATA.licenses, + { + id: 'guid-0', + name: this._configService.values.LICENSE_CUSTOMER, + product: 'RedactManager', + licensedTo: this._configService.values.LICENSE_CUSTOMER, + licensedToEmail: this._configService.values.LICENSE_EMAIL, + validFrom: dayjs(this._configService.values.LICENSE_START, 'DD-MM-YYYY').toISOString(), + validUntil: dayjs(this._configService.values.LICENSE_END, 'DD-MM-YYYY').toISOString(), + features: [ + { + name: 'pdftron', + type: 'STRING', + value: 'base64 encoded pdftron webviewer license key', + }, + { + name: 'processingPages', + type: 'NUMBER', + value: this._configService.values.LICENSE_PAGE_COUNT.toString(), + }, + ], + }, + ], + }; + } + getActiveLicense() { return this.licenseData.licenses.find(license => license.id === this.activeLicenseId); } diff --git a/apps/red-ui/src/app/modules/admin/screens/license/utils/constants.ts b/apps/red-ui/src/app/modules/admin/screens/license/utils/constants.ts index 766035b64..a139c9732 100644 --- a/apps/red-ui/src/app/modules/admin/screens/license/utils/constants.ts +++ b/apps/red-ui/src/app/modules/admin/screens/license/utils/constants.ts @@ -13,3 +13,5 @@ export const LineChartScheme: Color = { group: ScaleType.Ordinal, domain: ['#dd4d50', '#5ce594', '#0389ec'], }; + +export const LICENSE_STORAGE_KEY = 'redaction-license-reports'; diff --git a/apps/red-ui/src/app/modules/admin/screens/license/utils/date-range.ts b/apps/red-ui/src/app/modules/admin/screens/license/utils/date-range.ts index 6c18cc6d5..c18962cd6 100644 --- a/apps/red-ui/src/app/modules/admin/screens/license/utils/date-range.ts +++ b/apps/red-ui/src/app/modules/admin/screens/license/utils/date-range.ts @@ -1,9 +1,6 @@ -export interface IMonthYear { - readonly month: number; - readonly year: number; -} - export interface IDateRange { - readonly startDate: IMonthYear; - readonly endDate: IMonthYear; + readonly startMonth: number; + readonly startYear: number; + readonly endMonth: number; + readonly endYear: number; } diff --git a/apps/red-ui/src/app/modules/admin/screens/license/utils/functions.ts b/apps/red-ui/src/app/modules/admin/screens/license/utils/functions.ts new file mode 100644 index 000000000..4e445c7ae --- /dev/null +++ b/apps/red-ui/src/app/modules/admin/screens/license/utils/functions.ts @@ -0,0 +1,41 @@ +import dayjs from 'dayjs'; +import { IDateRange } from './date-range'; +import { LICENSE_STORAGE_KEY } from './constants'; +import { ILicenseReport } from '@red/domain'; + +export function toDate(month: number, year: number) { + return dayjs(`01-${month}-${year}`, 'DD-M-YYYY').toDate(); +} + +export function 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({ startMonth: month, startYear: year, endMonth: nextMonth, endYear: nextYear }); + + year = nextYear; + month = nextMonth; + } + + return dates; +} + +export function getStoredReports() { + const rawStoredReports = localStorage.getItem(LICENSE_STORAGE_KEY); + return JSON.parse(rawStoredReports ?? '{}') as Record; +} + +export function isCurrentMonth(month: number, year: number) { + const now = dayjs(); + const currentMonth = now.month() + 1; + const currentYear = now.year(); + + return month === currentMonth && year === currentYear; +} diff --git a/apps/red-ui/src/app/modules/admin/screens/license/utils/license.ts b/apps/red-ui/src/app/modules/admin/screens/license/utils/license.ts index 51da73235..63cf5b4bf 100644 --- a/apps/red-ui/src/app/modules/admin/screens/license/utils/license.ts +++ b/apps/red-ui/src/app/modules/admin/screens/license/utils/license.ts @@ -21,7 +21,7 @@ export interface ILicenses { } export const LICENSE_DATA: ILicenses = { - activeLicense: 'guid-1', + activeLicense: 'guid-0', licenses: [ { id: 'guid-1', diff --git a/apps/red-ui/src/assets/config/config.json b/apps/red-ui/src/assets/config/config.json index 0cb5f13c3..684210fa7 100644 --- a/apps/red-ui/src/assets/config/config.json +++ b/apps/red-ui/src/assets/config/config.json @@ -1,7 +1,7 @@ { "ADMIN_CONTACT_NAME": null, "ADMIN_CONTACT_URL": null, - "API_URL": "https://dev-04.iqser.cloud/redaction-gateway-v1", + "API_URL": "https://dev-08.iqser.cloud/redaction-gateway-v1", "APP_NAME": "RedactManager", "AUTO_READ_TIME": 3, "BACKEND_APP_VERSION": "4.4.40", @@ -17,7 +17,7 @@ "MAX_RETRIES_ON_SERVER_ERROR": 3, "OAUTH_CLIENT_ID": "redaction", "OAUTH_IDP_HINT": null, - "OAUTH_URL": "https://dev-04.iqser.cloud/auth/realms/redaction", + "OAUTH_URL": "https://dev-08.iqser.cloud/auth/realms/redaction", "RECENT_PERIOD_IN_HOURS": 24, "SELECTION_MODE": "structural", "MANUAL_BASE_URL": "https://docs.redactmanager.com/preview"