From 886c81c05668f24e02889aa029f4fcc135d3870d Mon Sep 17 00:00:00 2001 From: Dan Percic Date: Tue, 31 May 2022 16:03:57 +0300 Subject: [PATCH] RED-3765: use license endpoint --- apps/red-ui/src/app/app.module.ts | 2 + .../license-chart/license-chart.component.ts | 12 ++- .../license-screen.component.html | 4 +- .../license-screen.component.ts | 14 +-- .../license-select.component.html | 6 +- .../license-select.component.ts | 18 ++-- .../admin/screens/license/license.module.ts | 2 +- .../license/services/license.service.ts | 81 ----------------- .../admin/screens/license/utils/functions.ts | 9 +- .../admin/screens/license/utils/license.ts | 69 --------------- .../watermark-screen.component.ts | 20 ++++- .../file-preview/services/stamp.service.ts | 6 +- .../file-preview/utils/compare-mode.utils.ts | 16 +++- .../compare-file-input.component.ts | 6 +- .../pdf-viewer/services/pdf-viewer.service.ts | 8 +- .../src/app/services/license.service.ts | 88 +++++++++++++++++++ .../app/utils/configuration.initializer.ts | 3 + apps/red-ui/src/app/utils/page-stamper.ts | 80 ++++++++--------- libs/red-domain/src/index.ts | 1 + .../red-domain/src/lib/license}/date-range.ts | 0 libs/red-domain/src/lib/license/index.ts | 2 + libs/red-domain/src/lib/license/license.ts | 21 +++++ 22 files changed, 230 insertions(+), 238 deletions(-) delete mode 100644 apps/red-ui/src/app/modules/admin/screens/license/services/license.service.ts delete mode 100644 apps/red-ui/src/app/modules/admin/screens/license/utils/license.ts create mode 100644 apps/red-ui/src/app/services/license.service.ts rename {apps/red-ui/src/app/modules/admin/screens/license/utils => libs/red-domain/src/lib/license}/date-range.ts (100%) create mode 100644 libs/red-domain/src/lib/license/index.ts create mode 100644 libs/red-domain/src/lib/license/license.ts diff --git a/apps/red-ui/src/app/app.module.ts b/apps/red-ui/src/app/app.module.ts index 0e923f032..67aa30345 100644 --- a/apps/red-ui/src/app/app.module.ts +++ b/apps/red-ui/src/app/app.module.ts @@ -53,6 +53,7 @@ import { LoggerRulesService } from '@services/logger-rules.service'; import { ILoggerConfig } from '@red/domain'; import { SystemPreferencesService } from '@services/system-preferences.service'; import { PdfViewerModule } from './modules/pdf-viewer/pdf-viewer.module'; +import { LicenseService } from '@services/license.service'; export function httpLoaderFactory(httpClient: HttpClient, configService: ConfigService): PruningTranslationLoader { return new PruningTranslationLoader(httpClient, '/assets/i18n/', `.json?version=${configService.values.FRONTEND_APP_VERSION}`); @@ -181,6 +182,7 @@ const components = [AppComponent, AuthErrorComponent, NotificationsComponent, Sp LanguageService, UserService, UserPreferenceService, + LicenseService, ], }, { 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 7be6657de..fcf188256 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,10 +1,8 @@ import { ChangeDetectionStrategy, Component } from '@angular/core'; import { LICENSE_STORAGE_KEY } from '../utils/constants'; import dayjs from 'dayjs'; -import { ILicenseReport } from '@red/domain'; -import { LicenseService } from '../services/license.service'; -import { IDateRange } from '../utils/date-range'; -import { ILicense } from '../utils/license'; +import { IDateRange, ILicense, ILicenseReport } from '@red/domain'; +import { LicenseService } from '../../../../../services/license.service'; import { switchMap, tap } from 'rxjs/operators'; import { List, LoadingService } from '@iqser/common-ui'; import { generateDateRanges, isCurrentMonth, toDate, verboseDate } from '../utils/functions'; @@ -35,7 +33,7 @@ export class LicenseChartComponent { const startYear: number = startDate.year(); 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, license.id); return this.#mapRangesToReports(dateRanges, reports); } @@ -52,12 +50,12 @@ export class LicenseChartComponent { ]); } - #getReports(dateRanges: List) { + #getReports(dateRanges: List, id: string) { const reports = dateRanges.map(range => { const startMonth = range.startMonth + 1; const endMonth = range.endMonth + 1; - const key = `${startMonth}.${range.startYear}-${endMonth}.${range.endYear}`; + const key = `${id}-${startMonth}.${range.startYear}-${endMonth}.${range.endYear}`; const existingReport = this._licenseService.storedReports[key]; if (existingReport) { return existingReport; 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 5b18cfd15..046e5e489 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 @@ -9,7 +9,7 @@
-
+
{{ configService.values.BACKEND_APP_VERSION || '-' }}
@@ -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 1d749b7c5..68ab95b66 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 @@ -5,11 +5,11 @@ import { ButtonConfig, IconButtonTypes, LoadingService } from '@iqser/common-ui' import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { UserService } from '@services/user.service'; import { RouterHistoryService } from '@services/router-history.service'; -import { LicenseService } from '../services/license.service'; -import { ILicenseReport } from '@red/domain'; +import { LicenseService } from '../../../../../services/license.service'; +import { ILicense, ILicenseReport } from '@red/domain'; import dayjs from 'dayjs'; -import { ILicense } from '../utils/license'; import { UserPreferenceService } from '@services/user-preference.service'; +import { firstValueFrom } from 'rxjs'; @Component({ templateUrl: './license-screen.component.html', @@ -30,7 +30,7 @@ export class LicenseScreenComponent implements OnInit { totalInfo: ILicenseReport = {}; unlicensedInfo: ILicenseReport = {}; analysisPercentageOfLicense = 100; - totalLicensedNumberOfPages = this.licenseService.processingPages; + totalLicensedNumberOfPages: number; constructor( readonly configService: ConfigService, @@ -44,8 +44,10 @@ export class LicenseScreenComponent implements OnInit { _loadingService.start(); } - ngOnInit() { - return this.loadLicenseData(this.licenseService.selectedLicense); + async ngOnInit() { + await firstValueFrom(this.licenseService.loadLicense()); + this.totalLicensedNumberOfPages = this.licenseService.processingPages; + await this.loadLicenseData(this.licenseService.selectedLicense); } async loadLicenseData(license: ILicense) { diff --git a/apps/red-ui/src/app/modules/admin/screens/license/license-select/license-select.component.html b/apps/red-ui/src/app/modules/admin/screens/license/license-select/license-select.component.html index 8e0ee84ac..1f258ddf8 100644 --- a/apps/red-ui/src/app/modules/admin/screens/license/license-select/license-select.component.html +++ b/apps/red-ui/src/app/modules/admin/screens/license/license-select/license-select.component.html @@ -1,10 +1,10 @@ -
- +
+ - + diff --git a/apps/red-ui/src/app/modules/admin/screens/license/license-select/license-select.component.ts b/apps/red-ui/src/app/modules/admin/screens/license/license-select/license-select.component.ts index 6c088558d..ba71aa5a4 100644 --- a/apps/red-ui/src/app/modules/admin/screens/license/license-select/license-select.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/license/license-select/license-select.component.ts @@ -1,7 +1,8 @@ import { Component, EventEmitter, Output } from '@angular/core'; -import { LicenseService } from '../services/license.service'; -import { ILicense } from '../utils/license'; +import { LicenseService } from '../../../../../services/license.service'; +import { ILicense } from '@red/domain'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; +import { map, tap } from 'rxjs/operators'; const translations = { active: _('license-info-screen.status.active'), @@ -15,8 +16,15 @@ const translations = { }) export class LicenseSelectComponent { @Output() readonly valueChanges = new EventEmitter(); - - value = this.licenseService.getActiveLicense(); + value: ILicense; + licenses$ = this.licenseService.licenseData$.pipe( + map(data => data.licenses), + tap(() => { + if (!this.value) { + this.value = this.licenseService.activeLicense; + } + }), + ); constructor(readonly licenseService: LicenseService) {} @@ -26,6 +34,6 @@ export class LicenseSelectComponent { licenseChanged($event: ILicense) { this.valueChanges.emit($event); - this.licenseService.selectedLicense$.next($event); + this.licenseService.setSelectedLicense($event); } } diff --git a/apps/red-ui/src/app/modules/admin/screens/license/license.module.ts b/apps/red-ui/src/app/modules/admin/screens/license/license.module.ts index 8960051f5..998a40851 100644 --- a/apps/red-ui/src/app/modules/admin/screens/license/license.module.ts +++ b/apps/red-ui/src/app/modules/admin/screens/license/license.module.ts @@ -2,7 +2,7 @@ import { NgModule } from '@angular/core'; import { LicenseScreenComponent } from './license-screen/license-screen.component'; import { LicenseSelectComponent } from './license-select/license-select.component'; import { LicenseChartComponent } from './license-chart/license-chart.component'; -import { LicenseService } from './services/license.service'; +import { LicenseService } from '../../../../services/license.service'; import { RouterModule, Routes } from '@angular/router'; import { TranslateModule } from '@ngx-translate/core'; import { MatSelectModule } from '@angular/material/select'; 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 deleted file mode 100644 index 047497f4e..000000000 --- a/apps/red-ui/src/app/modules/admin/screens/license/services/license.service.ts +++ /dev/null @@ -1,81 +0,0 @@ -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, 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 { - storedReports = getStoredReports(); - readonly licenseData = this.#licenseData; - readonly activeLicenseId = this.licenseData.activeLicense; - readonly selectedLicense$ = new BehaviorSubject(this.getActiveLicense()); - - constructor(protected readonly _injector: Injector, private readonly _configService: ConfigService) { - super(_injector, 'report'); - } - - get selectedLicense() { - return this.selectedLicense$.value; - } - - get processingPages() { - const processingPagesFeature = this.selectedLicense$.value.features.find(f => f.name === 'processingPages'); - return Number(processingPagesFeature.value ?? '0'); - } - - get #licenseData(): 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); - } - - @Validate() - getReport$(@RequiredParam() body: ILicenseReportRequest, limit?: number, offset?: number) { - const queryParams: QueryParam[] = []; - if (limit) { - queryParams.push({ key: 'limit', value: limit }); - } - - if (offset) { - queryParams.push({ key: 'offset', value: offset }); - } - - return this._post(body, `${this._defaultModelPath}/license`, queryParams); - } - - getReport(body: ILicenseReportRequest, limit?: number, offset?: number) { - return firstValueFrom(this.getReport$(body, limit, offset)); - } -} 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 index ea346cb6c..bf8a7829d 100644 --- 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 @@ -1,7 +1,5 @@ import dayjs from 'dayjs'; -import { IDateRange } from './date-range'; -import { LICENSE_STORAGE_KEY } from './constants'; -import { ILicenseReport } from '@red/domain'; +import { IDateRange } from '@red/domain'; export function toDate(month: number, year: number) { return dayjs(`01-${month}-${year}`, 'DD-M-YYYY').toDate(); @@ -27,11 +25,6 @@ export function generateDateRanges(month: number, year: number, endMonth: number 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; 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 deleted file mode 100644 index 5d525ee42..000000000 --- a/apps/red-ui/src/app/modules/admin/screens/license/utils/license.ts +++ /dev/null @@ -1,69 +0,0 @@ -export interface ILicenseFeature { - readonly name: string; - readonly type: string; - readonly value: string; -} - -export interface ILicense { - readonly id: string; - readonly name: string; - readonly product: string; - readonly licensedTo: string; - readonly licensedToEmail: string; - readonly validFrom: string; - readonly validUntil: string; - readonly features: readonly ILicenseFeature[]; -} - -export interface ILicenses { - readonly activeLicense: string; - readonly licenses: readonly ILicense[]; -} - -export const LICENSE_DATA: ILicenses = { - activeLicense: 'guid-0', - licenses: [ - { - id: 'guid-1', - name: '1 Year cumulative (2022)', - product: 'RedactManager', - licensedTo: 'Customer company name 1', - licensedToEmail: 'customer@example.com', - validFrom: '2022-01-01T00:00:00.000Z', - validUntil: '2022-12-31T23:59:59.999Z', - features: [ - { - name: 'pdftron', - type: 'STRING', - value: 'base64 encoded pdftron webviewer license key', - }, - { - name: 'processingPages', - type: 'NUMBER', - value: '200000', - }, - ], - }, - { - id: 'guid-2', - name: '2 Year cumulative (2021)', - product: 'RedactManager', - licensedTo: 'Customer company name 2', - licensedToEmail: 'customer@example.com', - validFrom: '2021-01-01T00:00:00.000Z', - validUntil: '2021-12-31T23:59:59.999Z', - features: [ - { - name: 'pdftron', - type: 'STRING', - value: 'base64 encoded pdftron webviewer license key', - }, - { - name: 'processingPages', - type: 'NUMBER', - value: '100000', - }, - ], - }, - ], -}; diff --git a/apps/red-ui/src/app/modules/admin/screens/watermark/watermark-screen/watermark-screen.component.ts b/apps/red-ui/src/app/modules/admin/screens/watermark/watermark-screen/watermark-screen.component.ts index 26ff136f2..d79206942 100644 --- a/apps/red-ui/src/app/modules/admin/screens/watermark/watermark-screen/watermark-screen.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/watermark/watermark-screen/watermark-screen.component.ts @@ -1,18 +1,18 @@ import { ChangeDetectorRef, Component, ElementRef, Inject, OnInit, ViewChild } from '@angular/core'; import { PermissionsService } from '@services/permissions.service'; import WebViewer, { WebViewerInstance } from '@pdftron/webviewer'; -import { environment } from '@environments/environment'; import { HttpClient } from '@angular/common/http'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { Debounce, IconButtonTypes, LoadingService, Toaster } from '@iqser/common-ui'; import { DOSSIER_TEMPLATE_ID, IWatermark, WatermarkOrientation, WatermarkOrientations } from '@red/domain'; -import { BASE_HREF, BASE_HREF_FN, BaseHrefFn } from '../../../../../tokens'; +import { BASE_HREF_FN, BaseHrefFn } from '../../../../../tokens'; import { stampPDFPage } from '@utils/page-stamper'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { WatermarkService } from '@services/entity-services/watermark.service'; import { firstValueFrom, Observable, of, switchMap } from 'rxjs'; import { catchError, tap } from 'rxjs/operators'; import { ActivatedRoute } from '@angular/router'; +import { LicenseService } from '../../../../../services/license.service'; export const DEFAULT_WATERMARK: IWatermark = { text: null, @@ -44,6 +44,7 @@ export class WatermarkScreenComponent implements OnInit { private readonly _formBuilder: FormBuilder, readonly permissionsService: PermissionsService, private readonly _loadingService: LoadingService, + private readonly _licenseService: LicenseService, @Inject(BASE_HREF_FN) private readonly _convertPath: BaseHrefFn, private readonly _watermarkService: WatermarkService, private readonly _changeDetectorRef: ChangeDetectorRef, @@ -125,7 +126,7 @@ export class WatermarkScreenComponent implements OnInit { if (!this._instance) { WebViewer( { - licenseKey: environment.licenseKey ? atob(environment.licenseKey) : null, + licenseKey: this._licenseService.activeLicenseKey, path: this._convertPath('/assets/wv-resources'), css: this._convertPath('/assets/pdftron/stylesheet.css'), fullAPI: true, @@ -169,7 +170,18 @@ export class WatermarkScreenComponent implements OnInit { const opacity: number = this.form.get('opacity').value; const color: string = this.form.get('hexColor').value; - await stampPDFPage(document, pdfNet, text, fontSize, fontType, orientation, opacity, color, [1]); + await stampPDFPage( + document, + pdfNet, + text, + fontSize, + fontType, + orientation, + opacity, + color, + [1], + this._licenseService.activeLicenseKey, + ); this._instance.Core.documentViewer.refreshAll(); this._instance.Core.documentViewer.updateView([0], 0); this._changeDetectorRef.detectChanges(); diff --git a/apps/red-ui/src/app/modules/file-preview/services/stamp.service.ts b/apps/red-ui/src/app/modules/file-preview/services/stamp.service.ts index 82f7805c1..5f629fd30 100644 --- a/apps/red-ui/src/app/modules/file-preview/services/stamp.service.ts +++ b/apps/red-ui/src/app/modules/file-preview/services/stamp.service.ts @@ -9,6 +9,7 @@ import { firstValueFrom } from 'rxjs'; import { WatermarkService } from '@services/entity-services/watermark.service'; import { PdfViewer } from '../../pdf-viewer/services/pdf-viewer.service'; import { REDDocumentViewer } from '../../pdf-viewer/services/document-viewer.service'; +import { LicenseService } from '../../../services/license.service'; import PDFNet = Core.PDFNet; @Injectable() @@ -21,6 +22,7 @@ export class StampService { private readonly _viewModeService: ViewModeService, private readonly _translateService: TranslateService, private readonly _watermarkService: WatermarkService, + private readonly _licenseService: LicenseService, ) {} async stampPDF(): Promise { @@ -33,7 +35,7 @@ export class StampService { const allPages = [...Array(file.numberOfPages).keys()].map(page => page + 1); try { - await clearStamps(pdfDoc, this._pdf.PDFNet, allPages); + await clearStamps(pdfDoc, this._pdf.PDFNet, allPages, this._licenseService.activeLicenseKey); } catch (e) { console.error('Error clearing stamps: ', e); return; @@ -63,6 +65,7 @@ export class StampService { 50, '#dd4d50', excludedPages, + this._licenseService.activeLicenseKey, ); } } @@ -79,6 +82,7 @@ export class StampService { watermark.opacity, watermark.hexColor, Array.from({ length: await document.getPageCount() }, (x, i) => i + 1), + this._licenseService.activeLicenseKey, ); } } diff --git a/apps/red-ui/src/app/modules/file-preview/utils/compare-mode.utils.ts b/apps/red-ui/src/app/modules/file-preview/utils/compare-mode.utils.ts index ea5d62117..61bdeccda 100644 --- a/apps/red-ui/src/app/modules/file-preview/utils/compare-mode.utils.ts +++ b/apps/red-ui/src/app/modules/file-preview/utils/compare-mode.utils.ts @@ -7,6 +7,7 @@ export const processPage = async ( document2: Core.PDFNet.PDFDoc, mergedDocument: Core.PDFNet.PDFDoc, pdfNet: typeof Core.PDFNet, + licenseKey: string, ) => { const document1PageCount = await document1.getPageCount(); @@ -19,7 +20,16 @@ export const processPage = async ( const blankPage = await mergedDocument.pageCreate(await pageToCopy.getCropBox()); await blankPage.setRotation(await pageToCopy.getRotation()); await mergedDocument.pagePushBack(blankPage); - await stampPDFPage(mergedDocument, pdfNet, '<< Compare Placeholder Page >>', 20, 'courier', 'DIAGONAL', 33, '#ffb83b', [ - await mergedDocument.getPageCount(), - ]); + await stampPDFPage( + mergedDocument, + pdfNet, + '<< Compare Placeholder Page >>', + 20, + 'courier', + 'DIAGONAL', + 33, + '#ffb83b', + [await mergedDocument.getPageCount()], + licenseKey, + ); }; diff --git a/apps/red-ui/src/app/modules/pdf-viewer/components/compare-file-input/compare-file-input.component.ts b/apps/red-ui/src/app/modules/pdf-viewer/components/compare-file-input/compare-file-input.component.ts index 99e3e961e..59f9ab9b0 100644 --- a/apps/red-ui/src/app/modules/pdf-viewer/components/compare-file-input/compare-file-input.component.ts +++ b/apps/red-ui/src/app/modules/pdf-viewer/components/compare-file-input/compare-file-input.component.ts @@ -12,6 +12,7 @@ import { firstValueFrom } from 'rxjs'; import { MatDialogRef } from '@angular/material/dialog'; import { processPage } from '../../../file-preview/utils/compare-mode.utils'; import { NGXLogger } from 'ngx-logger'; +import { LicenseService } from '@services/license.service'; import PDFDoc = Core.PDFNet.PDFDoc; @Component({ @@ -28,6 +29,7 @@ export class CompareFileInputComponent { private readonly _loadingService: LoadingService, private readonly _documentViewer: REDDocumentViewer, private readonly _filesMapService: FilesMapService, + private readonly _licenseService: LicenseService, private readonly _dialogService: SharedDialogService, private readonly _viewerHeaderService: ViewerHeaderService, ) {} @@ -113,8 +115,8 @@ export class CompareFileInputComponent { const maxPageCount = Math.max(await current.getPageCount(), await compare.getPageCount()); for (let idx = 1; idx <= maxPageCount; idx++) { - await processPage(idx, current, compare, merged, pdfNet); - await processPage(idx, compare, current, merged, pdfNet); + await processPage(idx, current, compare, merged, pdfNet, this._licenseService.activeLicenseKey); + await processPage(idx, compare, current, merged, pdfNet, this._licenseService.activeLicenseKey); } const buffer = await merged.saveMemoryBuffer(pdfNet.SDFDoc.SaveOptions.e_linearized); diff --git a/apps/red-ui/src/app/modules/pdf-viewer/services/pdf-viewer.service.ts b/apps/red-ui/src/app/modules/pdf-viewer/services/pdf-viewer.service.ts index 4927ea785..b27acefef 100644 --- a/apps/red-ui/src/app/modules/pdf-viewer/services/pdf-viewer.service.ts +++ b/apps/red-ui/src/app/modules/pdf-viewer/services/pdf-viewer.service.ts @@ -1,6 +1,5 @@ import { Inject, Injectable, Injector } from '@angular/core'; import WebViewer, { Core, WebViewerInstance, WebViewerOptions } from '@pdftron/webviewer'; -import { environment } from '@environments/environment'; import { BASE_HREF_FN, BaseHrefFn } from '../../../tokens'; import { File, IHeaderElement } from '@red/domain'; import { ErrorService, shareDistinctLast } from '@iqser/common-ui'; @@ -14,6 +13,7 @@ import { Rgb } from '../utils/types'; import { asList } from '../utils/functions'; import { REDAnnotationManager } from './annotation-manager.service'; import { TranslateService } from '@ngx-translate/core'; +import { LicenseService } from '@services/license.service'; import TextTool = Core.Tools.TextTool; import Annotation = Core.Annotations.Annotation; import TextHighlightAnnotation = Core.Annotations.TextHighlightAnnotation; @@ -52,6 +52,7 @@ export class PdfViewer { private readonly _logger: NGXLogger, private readonly _injector: Injector, private readonly _activatedRoute: ActivatedRoute, + private readonly _licenseService: LicenseService, private readonly _translateService: TranslateService, private readonly _annotationManager: REDAnnotationManager, @Inject(BASE_HREF_FN) private readonly _convertPath: BaseHrefFn, @@ -127,7 +128,8 @@ export class PdfViewer { async init(htmlElement: HTMLElement) { this.#instance = await this.#getInstance(htmlElement); - await this.PDFNet.initialize(environment.licenseKey ? window.atob(environment.licenseKey) : null); + + await this.PDFNet.initialize(this._licenseService.activeLicenseKey); this._logger.info('[PDF] Initialized'); this.documentViewer = this.#instance.Core.documentViewer; @@ -271,7 +273,7 @@ export class PdfViewer { #getInstance(htmlElement: HTMLElement) { const options: WebViewerOptions = { - licenseKey: environment.licenseKey ? window.atob(environment.licenseKey) : null, + licenseKey: this._licenseService.activeLicenseKey, fullAPI: true, path: this._convertPath('/assets/wv-resources'), css: this._convertPath('/assets/pdftron/stylesheet.css'), diff --git a/apps/red-ui/src/app/services/license.service.ts b/apps/red-ui/src/app/services/license.service.ts new file mode 100644 index 000000000..bbc30a2db --- /dev/null +++ b/apps/red-ui/src/app/services/license.service.ts @@ -0,0 +1,88 @@ +import { Injectable, Injector } from '@angular/core'; +import { GenericService, QueryParam, RequiredParam, Validate } from '@iqser/common-ui'; +import { ILicense, ILicenseReport, ILicenseReportRequest, ILicenses } from '@red/domain'; +import { BehaviorSubject, firstValueFrom, Observable } from 'rxjs'; +import { ConfigService } from './config.service'; +import { filter, tap } from 'rxjs/operators'; +import { LICENSE_STORAGE_KEY } from '../modules/admin/screens/license/utils/constants'; + +export function getStoredReports() { + const rawStoredReports = localStorage.getItem(LICENSE_STORAGE_KEY); + return JSON.parse(rawStoredReports ?? '{}') as Record; +} + +@Injectable({ + providedIn: 'root', +}) +export class LicenseService extends GenericService { + storedReports = getStoredReports(); + readonly licenseData$: Observable; + readonly selectedLicense$: Observable; + activeLicenseId: string; + readonly #licenseData$ = new BehaviorSubject(undefined); + readonly #selectedLicense$ = new BehaviorSubject(undefined); + + constructor(protected readonly _injector: Injector, private readonly _configService: ConfigService) { + super(_injector, 'report'); + this.selectedLicense$ = this.#selectedLicense$.pipe(filter(license => !!license)); + this.licenseData$ = this.#licenseData$.pipe( + filter(licenses => !!licenses), + tap(data => (this.activeLicenseId = data.activeLicense)), + ); + } + + get selectedLicense() { + return this.#selectedLicense$.value; + } + + get processingPages() { + const processingPagesFeature = this.#selectedLicense$.value?.features?.find(f => f.name === 'processingPages'); + return Number(processingPagesFeature?.value ?? '0'); + } + + get activeLicense() { + if (!this.#licenseData$.value) { + return undefined; + } + + const { licenses, activeLicense: activeLicenseId } = this.#licenseData$.value; + return licenses.find(license => license.id === activeLicenseId); + } + + get activeLicenseKey(): string { + return this.activeLicense.features.find(f => f.name === 'pdftron').value; + } + + setDefaultSelectedLicense() { + this.setSelectedLicense(this.activeLicense); + } + + @Validate() + getReport$(@RequiredParam() body: ILicenseReportRequest, limit?: number, offset?: number) { + const queryParams: QueryParam[] = []; + if (limit) { + queryParams.push({ key: 'limit', value: limit }); + } + + if (offset) { + queryParams.push({ key: 'offset', value: offset }); + } + + return this._post(body, `${this._defaultModelPath}/license`, queryParams); + } + + getReport(body: ILicenseReportRequest, limit?: number, offset?: number) { + return firstValueFrom(this.getReport$(body, limit, offset)); + } + + loadLicense() { + return this._http.get('/license').pipe( + tap(licenses => this.#licenseData$.next(licenses)), + tap(() => this.setDefaultSelectedLicense()), + ); + } + + setSelectedLicense($event: ILicense) { + this.#selectedLicense$.next($event); + } +} diff --git a/apps/red-ui/src/app/utils/configuration.initializer.ts b/apps/red-ui/src/app/utils/configuration.initializer.ts index e60a1cdf6..1710b8e14 100644 --- a/apps/red-ui/src/app/utils/configuration.initializer.ts +++ b/apps/red-ui/src/app/utils/configuration.initializer.ts @@ -9,6 +9,7 @@ import { UserPreferenceService } from '@services/user-preference.service'; import { UserService } from '@services/user.service'; import { FeaturesService } from '@services/features.service'; import { SystemPreferencesService } from '@services/system-preferences.service'; +import { LicenseService } from '@services/license.service'; function lastDossierTemplateRedirect(baseHref: string, userPreferenceService: UserPreferenceService) { const url = window.location.href.split('/').filter(s => s.length > 0); @@ -29,6 +30,7 @@ export function configurationInitializer( languageService: LanguageService, userService: UserService, userPreferenceService: UserPreferenceService, + licenseService: LicenseService, ) { return () => firstValueFrom( @@ -53,6 +55,7 @@ export function configurationInitializer( }), switchMap(() => languageService.chooseAndSetInitialLanguage()), tap(() => userService.initialize()), + switchMap(() => licenseService.loadLicense()), take(1), ), ); diff --git a/apps/red-ui/src/app/utils/page-stamper.ts b/apps/red-ui/src/app/utils/page-stamper.ts index b139afe00..0efc57e5f 100644 --- a/apps/red-ui/src/app/utils/page-stamper.ts +++ b/apps/red-ui/src/app/utils/page-stamper.ts @@ -1,5 +1,4 @@ import { hexToRgb } from './functions'; -import { environment } from '@environments/environment'; import { Core } from '@pdftron/webviewer'; import PDFDoc = Core.PDFNet.PDFDoc; @@ -25,15 +24,12 @@ function convertFont(type: string): number { return 4; } -export async function clearStamps(document: PDFDoc, pdfNet: typeof Core.PDFNet, pages: number[]) { - await pdfNet.runWithCleanup( - async () => { - await document.lock(); - const pageSet = await createPageSet(pdfNet, pages); - await pdfNet.Stamper.deleteStamps(document, pageSet); - }, - environment.licenseKey ? atob(environment.licenseKey) : null, - ); +export async function clearStamps(document: PDFDoc, pdfNet: typeof Core.PDFNet, pages: number[], licenseKey: string) { + await pdfNet.runWithCleanup(async () => { + await document.lock(); + const pageSet = await createPageSet(pdfNet, pages); + await pdfNet.Stamper.deleteStamps(document, pageSet); + }, licenseKey); } export async function stampPDFPage( @@ -46,43 +42,41 @@ export async function stampPDFPage( opacity: number, color: string, pages: number[], + licenseKey: string, ) { - await pdfNet.runWithCleanup( - async () => { - await document.lock(); + await pdfNet.runWithCleanup(async () => { + await document.lock(); - const pageSet = await createPageSet(pdfNet, pages); - await pdfNet.Stamper.deleteStamps(document, pageSet); + const pageSet = await createPageSet(pdfNet, pages); + await pdfNet.Stamper.deleteStamps(document, pageSet); - const rgbColor = hexToRgb(color); + const rgbColor = hexToRgb(color); - const stamper = await pdfNet.Stamper.create(3, fontSize, 0); - await stamper.setFontColor(await pdfNet.ColorPt.init(rgbColor.r / 255, rgbColor.g / 255, rgbColor.b / 255)); - await stamper.setOpacity(opacity / 100); + const stamper = await pdfNet.Stamper.create(3, fontSize, 0); + await stamper.setFontColor(await pdfNet.ColorPt.init(rgbColor.r / 255, rgbColor.g / 255, rgbColor.b / 255)); + await stamper.setOpacity(opacity / 100); - switch (orientation) { - case 'VERTICAL': - await stamper.setAlignment(0, 0); - await stamper.setRotation(-90); - break; - case 'HORIZONTAL': - break; - case 'TOP_LEFT': - await stamper.setAlignment(-1, 1); - await stamper.setRotation(90); - await stamper.setPosition(20, 20); - break; - case 'DIAGONAL': - default: - await stamper.setAlignment(0, 0); - await stamper.setRotation(-45); - } + switch (orientation) { + case 'VERTICAL': + await stamper.setAlignment(0, 0); + await stamper.setRotation(-90); + break; + case 'HORIZONTAL': + break; + case 'TOP_LEFT': + await stamper.setAlignment(-1, 1); + await stamper.setRotation(90); + await stamper.setPosition(20, 20); + break; + case 'DIAGONAL': + default: + await stamper.setAlignment(0, 0); + await stamper.setRotation(-45); + } - const font = await pdfNet.Font.createAndEmbed(document, convertFont(fontType)); - await stamper.setFont(font); - await stamper.setTextAlignment(0); - await stamper.stampText(document, text, pageSet); - }, - environment.licenseKey ? atob(environment.licenseKey) : null, - ); + const font = await pdfNet.Font.createAndEmbed(document, convertFont(fontType)); + await stamper.setFont(font); + await stamper.setTextAlignment(0); + await stamper.stampText(document, text, pageSet); + }, licenseKey); } diff --git a/libs/red-domain/src/index.ts b/libs/red-domain/src/index.ts index bd2f2a0df..31a7e92e8 100644 --- a/libs/red-domain/src/index.ts +++ b/libs/red-domain/src/index.ts @@ -24,3 +24,4 @@ export * from './lib/dossier-state'; export * from './lib/trash'; export * from './lib/text-highlight'; export * from './lib/permissions'; +export * from './lib/license'; diff --git a/apps/red-ui/src/app/modules/admin/screens/license/utils/date-range.ts b/libs/red-domain/src/lib/license/date-range.ts similarity index 100% rename from apps/red-ui/src/app/modules/admin/screens/license/utils/date-range.ts rename to libs/red-domain/src/lib/license/date-range.ts diff --git a/libs/red-domain/src/lib/license/index.ts b/libs/red-domain/src/lib/license/index.ts new file mode 100644 index 000000000..3a4eb8ba2 --- /dev/null +++ b/libs/red-domain/src/lib/license/index.ts @@ -0,0 +1,2 @@ +export * from './date-range'; +export * from './license'; diff --git a/libs/red-domain/src/lib/license/license.ts b/libs/red-domain/src/lib/license/license.ts new file mode 100644 index 000000000..add1048c9 --- /dev/null +++ b/libs/red-domain/src/lib/license/license.ts @@ -0,0 +1,21 @@ +export interface ILicenseFeature { + readonly name: string; + readonly type: string; + readonly value: string; +} + +export interface ILicense { + readonly id: string; + readonly name: string; + readonly product: string; + readonly licensedTo: string; + readonly licensedToEmail: string; + readonly validFrom: string; + readonly validUntil: string; + readonly features: readonly ILicenseFeature[]; +} + +export interface ILicenses { + readonly activeLicense: string; + readonly licenses: readonly ILicense[]; +}