@sambath999/localize-token 19.0.3 → 19.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,28 +1,25 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Injectable, NgModule, Component, ViewEncapsulation, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
3
- import { BehaviorSubject } from 'rxjs';
4
- import * as jwt_decode from 'jwt-decode';
5
- import * as i1 from '@angular/common/http';
6
- import { HttpHeaders } from '@angular/common/http';
7
- import * as i1$1 from 'primeng/api';
2
+ import { Injectable, Component, ViewEncapsulation, NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
3
+ import * as i1 from 'primeng/api';
8
4
  import { MessageService } from 'primeng/api';
9
5
  import * as i2 from 'primeng/dynamicdialog';
10
- import { DialogService, DynamicDialogModule } from 'primeng/dynamicdialog';
11
- import * as i5 from '@angular/common';
6
+ import { DialogService } from 'primeng/dynamicdialog';
7
+ import { BehaviorSubject, takeUntil, catchError, throwError, Subject } from 'rxjs';
8
+ import * as jwt_decode from 'jwt-decode';
9
+ import * as i4 from '@angular/common/http';
10
+ import { HttpHeaders } from '@angular/common/http';
11
+ import * as i5 from '@angular/platform-browser';
12
+ import { BrowserModule } from '@angular/platform-browser';
13
+ import * as i6 from '@angular/common';
12
14
  import { CommonModule } from '@angular/common';
13
- import * as i6 from 'primeng/toast';
15
+ import * as i7 from 'primeng/toast';
14
16
  import { ToastModule } from 'primeng/toast';
15
- import * as i7 from 'primeng/inputtext';
17
+ import * as i8 from 'primeng/inputtext';
16
18
  import { InputTextModule } from 'primeng/inputtext';
17
- import * as i8 from '@angular/forms';
19
+ import * as i9 from '@angular/forms';
18
20
  import { FormsModule } from '@angular/forms';
19
- import * as i9 from 'primeng/button';
21
+ import * as i10 from 'primeng/button';
20
22
  import { ButtonModule } from 'primeng/button';
21
- import * as i10 from 'primeng/inputgroup';
22
- import { InputGroupModule } from 'primeng/inputgroup';
23
- import * as i11 from 'primeng/inputgroupaddon';
24
- import { InputGroupAddonModule } from 'primeng/inputgroupaddon';
25
- import { BrowserModule } from '@angular/platform-browser';
26
23
 
27
24
  /**
28
25
  * Assembly of @package ng2-cookies @see https://www.npmjs.com/package/ng2-cookies
@@ -132,18 +129,6 @@ class LocalizeTokenStorage {
132
129
  }
133
130
 
134
131
  class LocalizeToken {
135
- static init(config) {
136
- LocalizeToken.config = { ...LocalizeToken.config, ...config };
137
- }
138
- static config = {
139
- mainDomain: extractMainDomain(),
140
- authTokenName: 'auth-token',
141
- tenantTokenName: '_lze_tnt_01',
142
- refreshTokenName: '_lze_rftkp_',
143
- needTenant: false,
144
- isProduction: false,
145
- revokeTokenUrl: ''
146
- };
147
132
  static storage = new LocalizeTokenStorage();
148
133
  static httpHeaders = {
149
134
  AUTHORIZATION: 'Authorization',
@@ -169,11 +154,18 @@ async function waitFor(milliseconds, when = true) {
169
154
  * @param intervalNumber - The interval number in milliseconds to check the condition. Default is 50.
170
155
  */
171
156
  async function waitUntil(when, intervalNumber = 50) {
157
+ async function isConditionMet() {
158
+ const cond = when();
159
+ const result = cond instanceof Promise
160
+ ? await cond
161
+ : cond;
162
+ return result;
163
+ }
164
+ if (await isConditionMet())
165
+ return;
172
166
  await new Promise(resolve => {
173
167
  const interval = setInterval(async () => {
174
- const cond = when();
175
- const result = cond instanceof Promise ? await cond : cond;
176
- if (result) {
168
+ if (await isConditionMet()) {
177
169
  clearInterval(interval);
178
170
  resolve(true);
179
171
  }
@@ -187,41 +179,52 @@ function extractMainDomain(subdomain) {
187
179
  }
188
180
 
189
181
  class LocalizeTokenService {
182
+ configSubject = new BehaviorSubject({});
190
183
  isRevokingTokenSubject = new BehaviorSubject(false);
191
- config;
192
- constructor() {
193
- if (!LocalizeToken.config.authTokenName || !LocalizeToken.config.refreshTokenName || !LocalizeToken.config.tenantTokenName) {
194
- throw new Error('authTokenName, refreshTokenName, and tenantTokenName must be defined in LocalizeToken.config');
195
- }
196
- this.config = LocalizeToken.config;
184
+ defaultConfig = {
185
+ mainDomain: extractMainDomain(),
186
+ authToken: {
187
+ name: 'auth-token',
188
+ },
189
+ refreshToken: {
190
+ name: 'refresh-token',
191
+ requestUrl: '/api/token/revoke'
192
+ },
193
+ };
194
+ get config() {
195
+ this.throwIfNotInitialized();
196
+ return this.configSubject.value;
197
+ }
198
+ isInitialized = false;
199
+ init(config) {
200
+ console.log('LocalizeTokenService is initialized.');
201
+ this.configSubject.next({ ...this.defaultConfig, ...config });
202
+ this.isInitialized = true;
203
+ }
204
+ ngOnDestroy() {
205
+ // this.configSubject.complete();
206
+ // this.isRevokingTokenSubject.complete();
197
207
  }
198
208
  get authToken() { return this.storageGet(); }
199
209
  set authToken(value) {
200
210
  value
201
211
  ? this.storageSet(value)
202
- : LocalizeToken.storage.delete(this.config.authTokenName);
212
+ : LocalizeToken.storage.delete(this.config.authToken?.name);
203
213
  }
204
- get refreshToken() { return LocalizeToken.storage.get(this.config.refreshTokenName); }
214
+ get tenantToken() { return LocalizeToken.storage.get(this.config.tenantToken?.name || ''); }
215
+ get refreshToken() { return LocalizeToken.storage.get(this.config.refreshToken?.name || ''); }
205
216
  get accessToken() { return this.authToken?.token; }
206
217
  set accessToken(value) {
207
- if (value) {
208
- this.authToken = { token: value, revoke: false };
209
- }
218
+ value && (this.authToken = { token: value, revoke: false });
210
219
  }
211
220
  get isRevokingToken() { return this.isRevokingTokenSubject.value; /* this.authToken?.revoke ?? false */ }
212
221
  set isRevokingToken(value) {
213
222
  this.isRevokingTokenSubject.next(value);
214
- if (this.authToken) {
215
- this.authToken = { ...this.authToken, revoke: value };
216
- }
217
- }
218
- // get tenantToken() { return LocalizeToken.storage.get(this.config.tenantTokenName!) }
219
- tenantToken(name) {
220
- return LocalizeToken.storage.get(name ?? this.config.tenantTokenName);
223
+ this.authToken && (this.authToken = { ...this.authToken, revoke: value });
221
224
  }
222
225
  storageGet() {
223
226
  try {
224
- const encoded = LocalizeToken.storage.get(this.config.authTokenName);
227
+ const encoded = LocalizeToken.storage.get(this.config.authToken?.name || '');
225
228
  const decoded = atob(encoded || '');
226
229
  return JSON.parse(decoded);
227
230
  }
@@ -231,17 +234,21 @@ class LocalizeTokenService {
231
234
  }
232
235
  storageSet(value) {
233
236
  const base64 = btoa(JSON.stringify(value));
234
- LocalizeToken.storage.set(this.config.authTokenName, base64);
237
+ LocalizeToken.storage.set(this.config.authToken?.name || '', base64);
235
238
  }
236
239
  tokensValid() {
237
- return this.refreshToken?.length && (!this.config.needTenant || this.tenantToken()?.length);
240
+ return !!this.refreshToken?.length
241
+ && (!this.config.tenantToken || !!this.tenantToken?.length);
238
242
  }
239
243
  decodeToken = (token) => jwt_decode.jwtDecode(token);
240
244
  get decodeRefreshToken() {
241
- const token = LocalizeToken.storage.get(this.config.refreshTokenName);
242
- if (!token)
243
- return null;
244
- return this.decodeToken(token);
245
+ const token = this.refreshToken;
246
+ return !token ? null : this.decodeToken(token);
247
+ }
248
+ throwIfNotInitialized() {
249
+ if (!this.isInitialized) {
250
+ throw new Error('LocalizeTokenService is not initialized. Call init() method before using it.');
251
+ }
245
252
  }
246
253
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: LocalizeTokenService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
247
254
  static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: LocalizeTokenService, providedIn: 'root' });
@@ -249,161 +256,6 @@ class LocalizeTokenService {
249
256
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: LocalizeTokenService, decorators: [{
250
257
  type: Injectable,
251
258
  args: [{ providedIn: 'root' }]
252
- }], ctorParameters: () => [] });
253
-
254
- /**
255
- * Http method options
256
- */
257
- var EMethod;
258
- (function (EMethod) {
259
- EMethod[EMethod["POST"] = 1] = "POST";
260
- EMethod[EMethod["GET"] = 2] = "GET";
261
- EMethod[EMethod["PUT"] = 3] = "PUT";
262
- EMethod[EMethod["DELETE"] = 4] = "DELETE";
263
- EMethod[EMethod["PATCH"] = 5] = "PATCH";
264
- })(EMethod || (EMethod = {}));
265
- class LocalizeApiService {
266
- httpClient;
267
- localizeTokenService;
268
- isRequestingSubject = new BehaviorSubject(false);
269
- isResolvedStartupSubject = new BehaviorSubject(false);
270
- get isRequesting() { return this.isRequestingSubject.value; }
271
- get isResolvedStartup() { return this.isResolvedStartupSubject.value; }
272
- apiConfigs = {};
273
- isInitialized = false;
274
- constructor(httpClient, localizeTokenService) {
275
- this.httpClient = httpClient;
276
- this.localizeTokenService = localizeTokenService;
277
- }
278
- /**
279
- * Initialize the API service.
280
- * @param apiConfigs - The API configurations.
281
- */
282
- init(apiConfigs) {
283
- if (this.isInitialized)
284
- return;
285
- this.isInitialized = true;
286
- this.apiConfigs = apiConfigs;
287
- }
288
- /**
289
- * A higher-order function that returns a curried function for making API requests.
290
- *
291
- * @param baseUrl - The base URL of the API.
292
- * @returns A curried function that can be used to make API requests.
293
- */
294
- func = (baseUrl) => (path, method = EMethod.GET, value = null, isFormData = false, headers) => this.base(baseUrl, path, method, value, isFormData, headers);
295
- async base(baseUrl, path, method = EMethod.GET, value = null, isFormData = false, headers) {
296
- await this.ifPromise(this.apiConfigs.onPrepareRequest);
297
- const url = `${baseUrl.trim().replace(/\/?$/, '/')}${path.trim().replace(/^\//, '')}`;
298
- const httpMethod = EMethod[method].toLowerCase();
299
- const request = () => { return { body: value, headers: this.options(isFormData, headers) }; };
300
- // Wait for previous request to complete
301
- await this.toWaitForPreviousRequest();
302
- // Process request
303
- try {
304
- return await this.processRequest(httpMethod, url, request());
305
- }
306
- // Handle unauthorized error if any
307
- catch (error) {
308
- if (error.status !== 401) {
309
- throw error;
310
- }
311
- return await this.onUnauthorizedError(httpMethod, url, request);
312
- }
313
- }
314
- async onUnauthorizedError(httpMethod, url, request) {
315
- await this.revokeToken();
316
- if (!this.isResolvedStartup) {
317
- return await this.processRequest(httpMethod, url, request());
318
- }
319
- }
320
- async toWaitForPreviousRequest() {
321
- if (this.localizeTokenService.isRevokingToken) {
322
- await waitUntil(() => !this.localizeTokenService.isRevokingToken);
323
- }
324
- // to wait for each request in 50ms, even if the request is not completed
325
- if (this.apiConfigs.waitEachRequest?.milliseconds) {
326
- await waitFor(this.apiConfigs.waitEachRequest.milliseconds, this.isRequesting);
327
- }
328
- }
329
- async processRequest(method, url, options) {
330
- this.isRequestingSubject.next(true);
331
- const result = await new Promise((resolve, reject) => this.httpClient.request(method, url, options).subscribe({ next: resolve, error: reject }));
332
- this.isRequestingSubject.next(false);
333
- return result;
334
- }
335
- async revokeToken() {
336
- if (this.localizeTokenService.isRevokingToken) {
337
- await waitUntil(() => !this.localizeTokenService.isRevokingToken);
338
- return;
339
- }
340
- try {
341
- this.localizeTokenService.isRevokingToken = true;
342
- const reqUrl = LocalizeToken.config.revokeTokenUrl;
343
- const reqHeaders = this.options().append(LocalizeToken.httpHeaders.X_REFRESH_TOKEN, `${this.localizeTokenService.refreshToken}`);
344
- const revokeToken = await new Promise((resolve, reject) => this.httpClient.get(reqUrl, { headers: reqHeaders }).subscribe({ next: resolve, error: reject }));
345
- if (revokeToken?.status) {
346
- this.localizeTokenService.accessToken = revokeToken.message;
347
- }
348
- else if (!this.localizeTokenService.refreshToken) {
349
- await this.ifPromise(this.apiConfigs.onAutoLogout);
350
- }
351
- else {
352
- if (this.apiConfigs.onRevokeUnauthorized) {
353
- await this.ifPromise(this.apiConfigs.onRevokeUnauthorized);
354
- // await this.revokeToken();
355
- }
356
- }
357
- }
358
- finally {
359
- this.localizeTokenService.isRevokingToken = false;
360
- }
361
- }
362
- /** default http request options */
363
- options(isFormData = false, headers = {}) {
364
- const defaultHeaders = { [LocalizeToken.httpHeaders.AUTHORIZATION]: `Bearer ${this.localizeTokenService.accessToken}`, };
365
- if (LocalizeToken.config.needTenant) {
366
- defaultHeaders[LocalizeToken.httpHeaders.X_TENANT] = `${this.localizeTokenService.tenantToken(this.apiConfigs.tenantTokenName)}`;
367
- }
368
- if (!isFormData) {
369
- defaultHeaders[LocalizeToken.httpHeaders.CONTENT_TYPE] = 'application/json';
370
- }
371
- const filteredHeaders = Object.keys(defaultHeaders).filter(key => !Object.keys(headers).includes(key))
372
- .reduce((acc, key) => ({ ...acc, [key]: defaultHeaders[key] }), {});
373
- const mergedHeaders = { ...filteredHeaders, ...headers };
374
- return new HttpHeaders(mergedHeaders);
375
- }
376
- async ifPromise(fn) {
377
- if (!fn)
378
- return;
379
- return fn instanceof Promise ? await fn() : fn();
380
- }
381
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: LocalizeApiService, deps: [{ token: i1.HttpClient }, { token: LocalizeTokenService }], target: i0.ɵɵFactoryTarget.Injectable });
382
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: LocalizeApiService, providedIn: 'root' });
383
- } //class
384
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: LocalizeApiService, decorators: [{
385
- type: Injectable,
386
- args: [{
387
- providedIn: 'root'
388
- }]
389
- }], ctorParameters: () => [{ type: i1.HttpClient }, { type: LocalizeTokenService }] });
390
-
391
- class LocalizeTokenModule {
392
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: LocalizeTokenModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
393
- static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.0.5", ngImport: i0, type: LocalizeTokenModule });
394
- static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: LocalizeTokenModule, providers: [
395
- LocalizeTokenService,
396
- LocalizeApiService
397
- ] });
398
- }
399
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: LocalizeTokenModule, decorators: [{
400
- type: NgModule,
401
- args: [{
402
- providers: [
403
- LocalizeTokenService,
404
- LocalizeApiService
405
- ],
406
- }]
407
259
  }] });
408
260
 
409
261
  class LocalizeLogindlgComponent {
@@ -413,24 +265,28 @@ class LocalizeLogindlgComponent {
413
265
  dlgConfig;
414
266
  tokenService;
415
267
  httpClient;
268
+ sanitizer;
416
269
  messageKey = "$login-dlg";
417
270
  password;
418
271
  decodeToken;
419
272
  loading = false;
420
273
  success = false;
421
- config = LocalizeToken.config;
274
+ get config() { return this.tokenService.config; }
422
275
  loginConfig;
423
276
  logout;
424
277
  loginUrl;
425
- constructor(messageService, cdt, dlgRef, dlgConfig, tokenService, httpClient) {
278
+ properties;
279
+ constructor(messageService, cdt, dlgRef, dlgConfig, tokenService, httpClient, sanitizer) {
426
280
  this.messageService = messageService;
427
281
  this.cdt = cdt;
428
282
  this.dlgRef = dlgRef;
429
283
  this.dlgConfig = dlgConfig;
430
284
  this.tokenService = tokenService;
431
285
  this.httpClient = httpClient;
286
+ this.sanitizer = sanitizer;
432
287
  this.decodeToken = this.tokenService.decodeRefreshToken;
433
288
  this.loginConfig = this.dlgConfig.data.loginConfig;
289
+ this.properties = this.loginConfig.properties;
434
290
  }
435
291
  ngOnInit() {
436
292
  this.dlgConfig.closable = false;
@@ -446,29 +302,34 @@ class LocalizeLogindlgComponent {
446
302
  }
447
303
  async clickLogin() {
448
304
  if (!this.isValidPassword) {
449
- this.showMessage("error", "Password is required and must be at least 6 characters");
450
- return;
305
+ return this.showMessage("error", "Password is required and must be at least 6 characters");
451
306
  }
452
307
  this.loading = true;
453
308
  const loginRes = await this.login();
454
309
  if (!loginRes?.status) {
455
- this.showMessage("error", loginRes.message ?? "An error occurred");
456
- return;
310
+ return this.showMessage("error", loginRes.message ?? "An error occurred");
457
311
  }
458
312
  this.tokenService.accessToken = loginRes.tokens.accessToken;
459
- const cookieOptions = { expires: this.loginConfig.expire ?? 5 };
460
- LocalizeToken.storage.set(this.config.refreshTokenName, loginRes.tokens.refreshToken, cookieOptions);
313
+ const cookieOptions = { expires: this.loginConfig.expire ?? 365 };
314
+ LocalizeToken.storage.set(this.config.refreshToken?.name || '', loginRes.tokens.refreshToken, cookieOptions);
461
315
  this.success = true;
462
- setTimeout(() => this.dlgRef.close(true), 2000);
316
+ setTimeout(() => {
317
+ this.dlgConfig.dismissableMask = true;
318
+ this.dlgConfig.modal = false;
319
+ this.dlgRef.close(true);
320
+ }, 2000);
463
321
  }
464
322
  async login() {
465
- if (!this.loginUrl || !this.loginUrl.trim().length) {
323
+ if (!this.loginUrl?.trim().length) {
466
324
  this.showMessage("error", "Login url is required");
467
325
  throw new Error("Login url is required");
468
326
  }
469
327
  try {
470
- return await new Promise((resolve, reject) => this.httpClient.post(this.loginUrl, { password: this.password.trim() }, { headers: this.getHeaders() })
471
- .subscribe({ next: resolve, error: reject }));
328
+ if (this.loginConfig.loginFunction) {
329
+ console.log("Using custom login function");
330
+ return await this.loginConfig.loginFunction(this.decodeToken?.email ?? '', this.password.trim(), this.getHeaders());
331
+ }
332
+ return await new Promise((resolve, reject) => this.httpClient.post(this.loginUrl, { password: this.password.trim() }, { headers: this.getHeaders() }).subscribe({ next: resolve, error: reject }));
472
333
  }
473
334
  catch (e) {
474
335
  this.showMessage("error", e.message);
@@ -477,26 +338,31 @@ class LocalizeLogindlgComponent {
477
338
  }
478
339
  getHeaders() {
479
340
  return {
480
- [LocalizeToken.httpHeaders.X_REFRESH_TOKEN]: LocalizeToken.storage.get(this.config.refreshTokenName) ?? "",
481
- [LocalizeToken.httpHeaders.X_TENANT]: LocalizeToken.storage.get(this.config.tenantTokenName) ?? "",
341
+ [LocalizeToken.httpHeaders.X_REFRESH_TOKEN]: this.tokenService.refreshToken ?? "",
342
+ [LocalizeToken.httpHeaders.X_TENANT]: this.tokenService.tenantToken ?? "",
482
343
  };
483
344
  }
484
345
  get isValidPassword() {
485
346
  this.loading = false;
486
- return this.password && this.password.trim().length >= 6 && this.password.trim().length <= 50;
347
+ return this.properties.passwordValidator
348
+ ? this.properties.passwordValidator(this.password)
349
+ : this.password && this.password.trim().length >= 6 && this.password.trim().length <= 50;
487
350
  }
488
351
  clickLogout = () => this.logout?.();
489
352
  showMessage(severity, summary) {
490
353
  this.messageService.add({ key: this.messageKey, severity, summary });
491
354
  this.loading = false;
492
355
  }
493
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: LocalizeLogindlgComponent, deps: [{ token: i1$1.MessageService }, { token: i0.ChangeDetectorRef }, { token: i2.DynamicDialogRef }, { token: i2.DynamicDialogConfig }, { token: LocalizeTokenService }, { token: i1.HttpClient }], target: i0.ɵɵFactoryTarget.Component });
356
+ get sanitizedTitle() {
357
+ return this.sanitizer.bypassSecurityTrustHtml(this.properties.title ?? '');
358
+ }
359
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: LocalizeLogindlgComponent, deps: [{ token: i1.MessageService }, { token: i0.ChangeDetectorRef }, { token: i2.DynamicDialogRef }, { token: i2.DynamicDialogConfig }, { token: LocalizeTokenService }, { token: i4.HttpClient }, { token: i5.DomSanitizer }], target: i0.ɵɵFactoryTarget.Component });
494
360
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.0.5", type: LocalizeLogindlgComponent, isStandalone: false, selector: "app-localize-logindlg", providers: [MessageService], ngImport: i0, template: `<p-toast key="$login-dlg" position="top-center"></p-toast>
495
361
  <div id="login-dlg-wrap">
496
362
  <div id="login-dlg-header">
497
- <div id="login-logo" class="p-mb-2"></div>
498
- <h3 *ngIf="!success">Your session is expired! <br> Please login again to continue.</h3>
499
- <h3 *ngIf="success" style="color:green !important;">You haved successfully logged in.</h3>
363
+ <div id="login-logo" class="p-mb-2" style="background: url('{{properties.logoImage}}') no-repeat"></div>
364
+ <h3 *ngIf="!success" [innerHTML]="sanitizedTitle"></h3>
365
+ <h3 *ngIf="success" style="color:green !important;">{{properties.loginSuccessMessage}}</h3>
500
366
  </div>
501
367
  <div id="login-dlg-content">
502
368
  <ng-container *ngIf="!success">
@@ -504,35 +370,33 @@ class LocalizeLogindlgComponent {
504
370
  <div class="login-dlg-loader"></div>
505
371
  </div>
506
372
  <div class="login-dlg-elm">
507
- <p-inputgroup>
508
- <p-inputgroup-addon [style]="{background:'var(--p-inputtext-disabled-background)'}">
509
- <span class="p-inputgroup-addon">
510
- <i class="material-icons-round" style="color: var(--p-inputtext-disabled-color);">person</i>
511
- </span>
512
- </p-inputgroup-addon>
513
- <input disabled pInputText type="text" placeholder="Username" [value]="decodeToken?.email" />
514
- </p-inputgroup>
373
+ <div class="p-inputgroup">
374
+ <span class="p-inputgroup-addon">
375
+ <i class="material-icons-round">person</i>
376
+ </span>
377
+ <input disabled pInputText type="text" placeholder="{{properties.username?.placeHolder}}" [value]="decodeToken?.email" />
378
+ </div>
515
379
  </div>
516
380
 
517
381
  <div class="login-dlg-elm">
518
- <p-inputgroup>
519
- <p-inputgroup-addon>
520
- <span class="p-inputgroup-addon">
521
- <i class="material-icons-round">lock</i>
522
- </span>
523
- </p-inputgroup-addon>
524
- <input [disabled]="loading" (keydown.enter)="clickLogin()" pInputText type="password" placeholder="Password" [(ngModel)]="password"
382
+ <div class="p-inputgroup">
383
+ <span class="p-inputgroup-addon">
384
+ <i class="material-icons-round">lock</i>
385
+ </span>
386
+ <input [disabled]="loading" (keydown.enter)="clickLogin()" pInputText type="password"
387
+ placeholder="{{properties.password?.placeHolder}}" [(ngModel)]="password"
525
388
  autofocus />
526
- </p-inputgroup>
389
+ </div>
527
390
  </div>
528
391
  <div class="login-dlg-elm">
529
- <button style="width: 100%;" pButton type="button" label="Login" (click)="clickLogin()"
392
+ <button style="width: 100%;" pButton type="button" label="{{properties.loginButton?.placeHolder}}" (click)="clickLogin()"
530
393
  [disabled]="!password || loading"></button>
531
394
  </div>
532
395
 
533
- <div class="login-dlg-elm" style="display:flex;align-items: center;user-select: none;">
534
- <span>No, I want to login with another user.</span>
535
- <button class="p-button-text" pButton type="button" label="Logout" (click)="clickLogout()"></button>
396
+ <div class="login-dlg-elm login-dlg-suggest" style="display:flex;align-items: center;user-select: none;">
397
+ <span>{{properties.logoutButton?.message}}</span>
398
+ <button class="p-button-text" pButton type="button" label="{{properties.logoutButton?.placeHolder}}"
399
+ (click)="clickLogout()"></button>
536
400
  </div>
537
401
  </ng-container>
538
402
 
@@ -552,16 +416,16 @@ class LocalizeLogindlgComponent {
552
416
  </div>
553
417
  </ng-container>
554
418
  </div>
555
- </div>`, isInline: true, styles: ["#login-dlg-wrap{width:100%;max-width:400px;margin:0 auto;padding:30px}.login-dlg-elm{margin-top:1rem}#login-dlg-header{display:flex;flex-direction:column;align-items:center;justify-content:center}#login-dlg-header h3{font-weight:700;font-size:.9rem;color:orange;text-align:center}#login-logo{height:40px;width:40px;background:url(/assets/images/logo-300px.png) no-repeat;background-size:contain}#login-dlg-content .p-inputgroup{height:45px}#login-dlg-content .p-inputgroup .p-inputgroup-addon *{font-size:1rem}#login-dlg-content .p-inputgroup input{height:45px;border-radius:0 15px 15px 0}#login-dlg-content button{height:45px;border-radius:15px}.check-animation-wrap{top:0;left:0;position:absolute;display:flex;flex-direction:column;align-items:center;justify-content:center;width:100%;height:calc(100% - 200px);min-height:400px}.check-main-container{width:100%;height:100vh;display:flex;flex-flow:column;justify-content:center;align-items:center}.check-container{width:6.25rem;height:7.5rem;display:flex;flex-flow:column;align-items:center;justify-content:space-between}.check-container .check-background{width:100%;height:calc(100% - 1.25rem);background:linear-gradient(to bottom right,#5de593,#41d67c);box-shadow:0 0 0 65px #ffffff40 inset,0 0 0 65px #ffffff40 inset;transform:scale(.84);border-radius:50%;animation:animateContainer .75s ease-out forwards .75s;display:flex;align-items:center;justify-content:center;opacity:0}.check-container .check-background svg{width:65%;transform:translateY(.25rem);stroke-dasharray:80;stroke-dashoffset:80;animation:animateCheck .35s forwards 1.25s ease-out;min-width:auto!important}.check-container .check-shadow{bottom:calc(-15% - 5px);left:0;border-radius:50%;background:radial-gradient(closest-side,rgba(73,218,131,1),transparent);animation:animateShadow .75s ease-out forwards .75s}@keyframes animateContainer{0%{opacity:0;transform:scale(0);box-shadow:0 0 0 65px #ffffff40 inset,0 0 0 65px #ffffff40 inset}25%{opacity:1;transform:scale(.9);box-shadow:0 0 0 65px #ffffff40 inset,0 0 0 65px #ffffff40 inset}43.75%{transform:scale(1.15);box-shadow:0 0 0 43.334px #ffffff40 inset,0 0 0 65px #ffffff40 inset}62.5%{transform:scale(1);box-shadow:0 0 #ffffff40 inset,0 0 0 21.667px #ffffff40 inset}81.25%{box-shadow:0 0 #ffffff40 inset,0 0 #ffffff40 inset}to{opacity:1;box-shadow:0 0 #ffffff40 inset,0 0 #ffffff40 inset}}@keyframes animateCheck{0%{stroke-dashoffset:80}to{stroke-dashoffset:0}}@keyframes animateShadow{0%{opacity:0;width:100%;height:15%}25%{opacity:.25}43.75%{width:40%;height:7%;opacity:.35}to{width:85%;height:15%;opacity:.25}}#login-dlg-wrap .loader-wrap{display:flex;justify-content:center;align-items:center;height:100%;width:100%;position:absolute;top:0;left:0;z-index:100;background:#ffffff42;-webkit-backdrop-filter:blur(1px);backdrop-filter:blur(1px)}#login-dlg-wrap .login-dlg-loader{border:15px solid #e7e7e7;border-top:15px solid #52dba1;border-radius:50%;width:100px;height:100px;animation:spinloader 2s linear infinite}#login-dlg-wrap .loader-wrap:before{content:\"\";position:absolute;width:70px;height:70px;transform:translate(-50%,-50%);z-index:1;border:15px solid #e7e7e700;border-top:15px solid #52dba1c9;border-radius:50%;animation:spinloader .75s linear infinite}@keyframes spinloader{0%{transform:rotate(0)}to{transform:rotate(360deg)}}\n"], dependencies: [{ kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i6.Toast, selector: "p-toast", inputs: ["key", "autoZIndex", "baseZIndex", "life", "style", "styleClass", "position", "preventOpenDuplicates", "preventDuplicates", "showTransformOptions", "hideTransformOptions", "showTransitionOptions", "hideTransitionOptions", "breakpoints"], outputs: ["onClose"] }, { kind: "directive", type: i7.InputText, selector: "[pInputText]", inputs: ["variant", "fluid", "pSize"] }, { kind: "directive", type: i8.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i8.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i8.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i9.ButtonDirective, selector: "[pButton]", inputs: ["iconPos", "loadingIcon", "loading", "severity", "raised", "rounded", "text", "outlined", "size", "plain", "fluid", "label", "icon", "buttonProps"] }, { kind: "component", type: i10.InputGroup, selector: "p-inputgroup, p-inputGroup, p-input-group", inputs: ["style", "styleClass"] }, { kind: "component", type: i11.InputGroupAddon, selector: "p-inputgroup-addon, p-inputGroupAddon", inputs: ["style", "styleClass"] }], encapsulation: i0.ViewEncapsulation.None });
419
+ </div>`, isInline: true, styles: ["#login-dlg-wrap{width:100%;max-width:400px;margin:0 auto;padding:30px;height:100%}.login-dlg-elm{margin-top:1rem}.login-dlg-elm.login-dlg-suggest{display:flex;align-items:center;-webkit-user-select:none;user-select:none;border-bottom:solid 1px #ddd;border-radius:5px;padding:5px 10px;background:#f9f9f9;box-shadow:1px 5px 10px -12px #000}#login-dlg-header{display:flex;flex-direction:column;align-items:center;justify-content:center}#login-dlg-header h3{font-weight:700;font-size:.9rem;color:orange;text-align:center}#login-logo{height:55px;width:55px;background-size:contain!important}#login-dlg-content .p-inputgroup{height:45px}#login-dlg-content .p-inputgroup .p-inputgroup-addon{height:45px;border-radius:15px 0 0 15px;width:50px}#login-dlg-content *{font-size:.9rem}#login-dlg-content .p-inputgroup .p-inputgroup-addon *{font-size:1rem}#login-dlg-content .p-inputgroup input{height:45px;border-radius:0 15px 15px 0}#login-dlg-content button{height:45px;border-radius:15px}.check-animation-wrap{top:0;left:0;position:absolute;display:flex;flex-direction:column;align-items:center;justify-content:center;width:100%;height:calc(100% - 200px);min-height:400px}.check-main-container{width:100%;height:100vh;display:flex;flex-flow:column;justify-content:center;align-items:center}.check-container{width:6.25rem;height:7.5rem;display:flex;flex-flow:column;align-items:center;justify-content:space-between}.check-container .check-background{width:100%;height:calc(100% - 1.25rem);background:linear-gradient(to bottom right,#5de593,#41d67c);box-shadow:0 0 0 65px #ffffff40 inset,0 0 0 65px #ffffff40 inset;transform:scale(.84);border-radius:50%;animation:animateContainer .75s ease-out forwards .75s;display:flex;align-items:center;justify-content:center;opacity:0}.check-container .check-background svg{width:65%;transform:translateY(.25rem);stroke-dasharray:80;stroke-dashoffset:80;animation:animateCheck .35s forwards 1.25s ease-out;min-width:auto!important}.check-container .check-shadow{bottom:calc(-15% - 5px);left:0;border-radius:50%;background:radial-gradient(closest-side,rgba(73,218,131,1),transparent);animation:animateShadow .75s ease-out forwards .75s}@keyframes animateContainer{0%{opacity:0;transform:scale(0);box-shadow:0 0 0 65px #ffffff40 inset,0 0 0 65px #ffffff40 inset}25%{opacity:1;transform:scale(.9);box-shadow:0 0 0 65px #ffffff40 inset,0 0 0 65px #ffffff40 inset}43.75%{transform:scale(1.15);box-shadow:0 0 0 43.334px #ffffff40 inset,0 0 0 65px #ffffff40 inset}62.5%{transform:scale(1);box-shadow:0 0 #ffffff40 inset,0 0 0 21.667px #ffffff40 inset}81.25%{box-shadow:0 0 #ffffff40 inset,0 0 #ffffff40 inset}to{opacity:1;box-shadow:0 0 #ffffff40 inset,0 0 #ffffff40 inset}}@keyframes animateCheck{0%{stroke-dashoffset:80}to{stroke-dashoffset:0}}@keyframes animateShadow{0%{opacity:0;width:100%;height:15%}25%{opacity:.25}43.75%{width:40%;height:7%;opacity:.35}to{width:85%;height:15%;opacity:.25}}#login-dlg-wrap .loader-wrap{display:flex;justify-content:center;align-items:center;height:100%;width:100%;position:absolute;top:0;left:0;z-index:100;background:#ffffff42;-webkit-backdrop-filter:blur(1px);backdrop-filter:blur(1px)}#login-dlg-wrap .login-dlg-loader{border:15px solid #e7e7e7;border-top:15px solid #52dba1;border-radius:50%;width:100px;height:100px;animation:spinloader 2s linear infinite}#login-dlg-wrap .loader-wrap:before{content:\"\";position:absolute;width:70px;height:70px;transform:translate(-50%,-50%);z-index:1;border:15px solid #e7e7e700;border-top:15px solid #52dba1c9;border-radius:50%;animation:spinloader .75s linear infinite}@keyframes spinloader{0%{transform:rotate(0)}to{transform:rotate(360deg)}}\n"], dependencies: [{ kind: "directive", type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i7.Toast, selector: "p-toast", inputs: ["key", "autoZIndex", "baseZIndex", "life", "style", "styleClass", "position", "preventOpenDuplicates", "preventDuplicates", "showTransformOptions", "hideTransformOptions", "showTransitionOptions", "hideTransitionOptions", "breakpoints"], outputs: ["onClose"] }, { kind: "directive", type: i8.InputText, selector: "[pInputText]", inputs: ["variant", "fluid", "pSize"] }, { kind: "directive", type: i9.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i9.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i9.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i10.ButtonDirective, selector: "[pButton]", inputs: ["iconPos", "loadingIcon", "loading", "severity", "raised", "rounded", "text", "outlined", "size", "plain", "fluid", "label", "icon", "buttonProps"] }], encapsulation: i0.ViewEncapsulation.None });
556
420
  }
557
421
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: LocalizeLogindlgComponent, decorators: [{
558
422
  type: Component,
559
423
  args: [{ standalone: false, template: `<p-toast key="$login-dlg" position="top-center"></p-toast>
560
424
  <div id="login-dlg-wrap">
561
425
  <div id="login-dlg-header">
562
- <div id="login-logo" class="p-mb-2"></div>
563
- <h3 *ngIf="!success">Your session is expired! <br> Please login again to continue.</h3>
564
- <h3 *ngIf="success" style="color:green !important;">You haved successfully logged in.</h3>
426
+ <div id="login-logo" class="p-mb-2" style="background: url('{{properties.logoImage}}') no-repeat"></div>
427
+ <h3 *ngIf="!success" [innerHTML]="sanitizedTitle"></h3>
428
+ <h3 *ngIf="success" style="color:green !important;">{{properties.loginSuccessMessage}}</h3>
565
429
  </div>
566
430
  <div id="login-dlg-content">
567
431
  <ng-container *ngIf="!success">
@@ -569,35 +433,33 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImpor
569
433
  <div class="login-dlg-loader"></div>
570
434
  </div>
571
435
  <div class="login-dlg-elm">
572
- <p-inputgroup>
573
- <p-inputgroup-addon [style]="{background:'var(--p-inputtext-disabled-background)'}">
574
- <span class="p-inputgroup-addon">
575
- <i class="material-icons-round" style="color: var(--p-inputtext-disabled-color);">person</i>
576
- </span>
577
- </p-inputgroup-addon>
578
- <input disabled pInputText type="text" placeholder="Username" [value]="decodeToken?.email" />
579
- </p-inputgroup>
436
+ <div class="p-inputgroup">
437
+ <span class="p-inputgroup-addon">
438
+ <i class="material-icons-round">person</i>
439
+ </span>
440
+ <input disabled pInputText type="text" placeholder="{{properties.username?.placeHolder}}" [value]="decodeToken?.email" />
441
+ </div>
580
442
  </div>
581
443
 
582
444
  <div class="login-dlg-elm">
583
- <p-inputgroup>
584
- <p-inputgroup-addon>
585
- <span class="p-inputgroup-addon">
586
- <i class="material-icons-round">lock</i>
587
- </span>
588
- </p-inputgroup-addon>
589
- <input [disabled]="loading" (keydown.enter)="clickLogin()" pInputText type="password" placeholder="Password" [(ngModel)]="password"
445
+ <div class="p-inputgroup">
446
+ <span class="p-inputgroup-addon">
447
+ <i class="material-icons-round">lock</i>
448
+ </span>
449
+ <input [disabled]="loading" (keydown.enter)="clickLogin()" pInputText type="password"
450
+ placeholder="{{properties.password?.placeHolder}}" [(ngModel)]="password"
590
451
  autofocus />
591
- </p-inputgroup>
452
+ </div>
592
453
  </div>
593
454
  <div class="login-dlg-elm">
594
- <button style="width: 100%;" pButton type="button" label="Login" (click)="clickLogin()"
455
+ <button style="width: 100%;" pButton type="button" label="{{properties.loginButton?.placeHolder}}" (click)="clickLogin()"
595
456
  [disabled]="!password || loading"></button>
596
457
  </div>
597
458
 
598
- <div class="login-dlg-elm" style="display:flex;align-items: center;user-select: none;">
599
- <span>No, I want to login with another user.</span>
600
- <button class="p-button-text" pButton type="button" label="Logout" (click)="clickLogout()"></button>
459
+ <div class="login-dlg-elm login-dlg-suggest" style="display:flex;align-items: center;user-select: none;">
460
+ <span>{{properties.logoutButton?.message}}</span>
461
+ <button class="p-button-text" pButton type="button" label="{{properties.logoutButton?.placeHolder}}"
462
+ (click)="clickLogout()"></button>
601
463
  </div>
602
464
  </ng-container>
603
465
 
@@ -617,8 +479,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImpor
617
479
  </div>
618
480
  </ng-container>
619
481
  </div>
620
- </div>`, selector: "app-localize-logindlg", providers: [MessageService], encapsulation: ViewEncapsulation.None, styles: ["#login-dlg-wrap{width:100%;max-width:400px;margin:0 auto;padding:30px}.login-dlg-elm{margin-top:1rem}#login-dlg-header{display:flex;flex-direction:column;align-items:center;justify-content:center}#login-dlg-header h3{font-weight:700;font-size:.9rem;color:orange;text-align:center}#login-logo{height:40px;width:40px;background:url(/assets/images/logo-300px.png) no-repeat;background-size:contain}#login-dlg-content .p-inputgroup{height:45px}#login-dlg-content .p-inputgroup .p-inputgroup-addon *{font-size:1rem}#login-dlg-content .p-inputgroup input{height:45px;border-radius:0 15px 15px 0}#login-dlg-content button{height:45px;border-radius:15px}.check-animation-wrap{top:0;left:0;position:absolute;display:flex;flex-direction:column;align-items:center;justify-content:center;width:100%;height:calc(100% - 200px);min-height:400px}.check-main-container{width:100%;height:100vh;display:flex;flex-flow:column;justify-content:center;align-items:center}.check-container{width:6.25rem;height:7.5rem;display:flex;flex-flow:column;align-items:center;justify-content:space-between}.check-container .check-background{width:100%;height:calc(100% - 1.25rem);background:linear-gradient(to bottom right,#5de593,#41d67c);box-shadow:0 0 0 65px #ffffff40 inset,0 0 0 65px #ffffff40 inset;transform:scale(.84);border-radius:50%;animation:animateContainer .75s ease-out forwards .75s;display:flex;align-items:center;justify-content:center;opacity:0}.check-container .check-background svg{width:65%;transform:translateY(.25rem);stroke-dasharray:80;stroke-dashoffset:80;animation:animateCheck .35s forwards 1.25s ease-out;min-width:auto!important}.check-container .check-shadow{bottom:calc(-15% - 5px);left:0;border-radius:50%;background:radial-gradient(closest-side,rgba(73,218,131,1),transparent);animation:animateShadow .75s ease-out forwards .75s}@keyframes animateContainer{0%{opacity:0;transform:scale(0);box-shadow:0 0 0 65px #ffffff40 inset,0 0 0 65px #ffffff40 inset}25%{opacity:1;transform:scale(.9);box-shadow:0 0 0 65px #ffffff40 inset,0 0 0 65px #ffffff40 inset}43.75%{transform:scale(1.15);box-shadow:0 0 0 43.334px #ffffff40 inset,0 0 0 65px #ffffff40 inset}62.5%{transform:scale(1);box-shadow:0 0 #ffffff40 inset,0 0 0 21.667px #ffffff40 inset}81.25%{box-shadow:0 0 #ffffff40 inset,0 0 #ffffff40 inset}to{opacity:1;box-shadow:0 0 #ffffff40 inset,0 0 #ffffff40 inset}}@keyframes animateCheck{0%{stroke-dashoffset:80}to{stroke-dashoffset:0}}@keyframes animateShadow{0%{opacity:0;width:100%;height:15%}25%{opacity:.25}43.75%{width:40%;height:7%;opacity:.35}to{width:85%;height:15%;opacity:.25}}#login-dlg-wrap .loader-wrap{display:flex;justify-content:center;align-items:center;height:100%;width:100%;position:absolute;top:0;left:0;z-index:100;background:#ffffff42;-webkit-backdrop-filter:blur(1px);backdrop-filter:blur(1px)}#login-dlg-wrap .login-dlg-loader{border:15px solid #e7e7e7;border-top:15px solid #52dba1;border-radius:50%;width:100px;height:100px;animation:spinloader 2s linear infinite}#login-dlg-wrap .loader-wrap:before{content:\"\";position:absolute;width:70px;height:70px;transform:translate(-50%,-50%);z-index:1;border:15px solid #e7e7e700;border-top:15px solid #52dba1c9;border-radius:50%;animation:spinloader .75s linear infinite}@keyframes spinloader{0%{transform:rotate(0)}to{transform:rotate(360deg)}}\n"] }]
621
- }], ctorParameters: () => [{ type: i1$1.MessageService }, { type: i0.ChangeDetectorRef }, { type: i2.DynamicDialogRef }, { type: i2.DynamicDialogConfig }, { type: LocalizeTokenService }, { type: i1.HttpClient }] });
482
+ </div>`, selector: "app-localize-logindlg", providers: [MessageService], encapsulation: ViewEncapsulation.None, styles: ["#login-dlg-wrap{width:100%;max-width:400px;margin:0 auto;padding:30px;height:100%}.login-dlg-elm{margin-top:1rem}.login-dlg-elm.login-dlg-suggest{display:flex;align-items:center;-webkit-user-select:none;user-select:none;border-bottom:solid 1px #ddd;border-radius:5px;padding:5px 10px;background:#f9f9f9;box-shadow:1px 5px 10px -12px #000}#login-dlg-header{display:flex;flex-direction:column;align-items:center;justify-content:center}#login-dlg-header h3{font-weight:700;font-size:.9rem;color:orange;text-align:center}#login-logo{height:55px;width:55px;background-size:contain!important}#login-dlg-content .p-inputgroup{height:45px}#login-dlg-content .p-inputgroup .p-inputgroup-addon{height:45px;border-radius:15px 0 0 15px;width:50px}#login-dlg-content *{font-size:.9rem}#login-dlg-content .p-inputgroup .p-inputgroup-addon *{font-size:1rem}#login-dlg-content .p-inputgroup input{height:45px;border-radius:0 15px 15px 0}#login-dlg-content button{height:45px;border-radius:15px}.check-animation-wrap{top:0;left:0;position:absolute;display:flex;flex-direction:column;align-items:center;justify-content:center;width:100%;height:calc(100% - 200px);min-height:400px}.check-main-container{width:100%;height:100vh;display:flex;flex-flow:column;justify-content:center;align-items:center}.check-container{width:6.25rem;height:7.5rem;display:flex;flex-flow:column;align-items:center;justify-content:space-between}.check-container .check-background{width:100%;height:calc(100% - 1.25rem);background:linear-gradient(to bottom right,#5de593,#41d67c);box-shadow:0 0 0 65px #ffffff40 inset,0 0 0 65px #ffffff40 inset;transform:scale(.84);border-radius:50%;animation:animateContainer .75s ease-out forwards .75s;display:flex;align-items:center;justify-content:center;opacity:0}.check-container .check-background svg{width:65%;transform:translateY(.25rem);stroke-dasharray:80;stroke-dashoffset:80;animation:animateCheck .35s forwards 1.25s ease-out;min-width:auto!important}.check-container .check-shadow{bottom:calc(-15% - 5px);left:0;border-radius:50%;background:radial-gradient(closest-side,rgba(73,218,131,1),transparent);animation:animateShadow .75s ease-out forwards .75s}@keyframes animateContainer{0%{opacity:0;transform:scale(0);box-shadow:0 0 0 65px #ffffff40 inset,0 0 0 65px #ffffff40 inset}25%{opacity:1;transform:scale(.9);box-shadow:0 0 0 65px #ffffff40 inset,0 0 0 65px #ffffff40 inset}43.75%{transform:scale(1.15);box-shadow:0 0 0 43.334px #ffffff40 inset,0 0 0 65px #ffffff40 inset}62.5%{transform:scale(1);box-shadow:0 0 #ffffff40 inset,0 0 0 21.667px #ffffff40 inset}81.25%{box-shadow:0 0 #ffffff40 inset,0 0 #ffffff40 inset}to{opacity:1;box-shadow:0 0 #ffffff40 inset,0 0 #ffffff40 inset}}@keyframes animateCheck{0%{stroke-dashoffset:80}to{stroke-dashoffset:0}}@keyframes animateShadow{0%{opacity:0;width:100%;height:15%}25%{opacity:.25}43.75%{width:40%;height:7%;opacity:.35}to{width:85%;height:15%;opacity:.25}}#login-dlg-wrap .loader-wrap{display:flex;justify-content:center;align-items:center;height:100%;width:100%;position:absolute;top:0;left:0;z-index:100;background:#ffffff42;-webkit-backdrop-filter:blur(1px);backdrop-filter:blur(1px)}#login-dlg-wrap .login-dlg-loader{border:15px solid #e7e7e7;border-top:15px solid #52dba1;border-radius:50%;width:100px;height:100px;animation:spinloader 2s linear infinite}#login-dlg-wrap .loader-wrap:before{content:\"\";position:absolute;width:70px;height:70px;transform:translate(-50%,-50%);z-index:1;border:15px solid #e7e7e700;border-top:15px solid #52dba1c9;border-radius:50%;animation:spinloader .75s linear infinite}@keyframes spinloader{0%{transform:rotate(0)}to{transform:rotate(360deg)}}\n"] }]
483
+ }], ctorParameters: () => [{ type: i1.MessageService }, { type: i0.ChangeDetectorRef }, { type: i2.DynamicDialogRef }, { type: i2.DynamicDialogConfig }, { type: LocalizeTokenService }, { type: i4.HttpClient }, { type: i5.DomSanitizer }] });
622
484
 
623
485
  class LocalizeLogindlgService {
624
486
  injector;
@@ -626,12 +488,9 @@ class LocalizeLogindlgService {
626
488
  this.injector = injector;
627
489
  }
628
490
  async openLoginDialog(loginConfig, config) {
629
- config ??= {
630
- header: 'Login',
631
- height: '650px',
632
- style: { 'max-width': '400px', width: '100%', 'height': '650px' },
633
- };
634
- config.data = { ...config.data || {}, ...{ loginConfig } };
491
+ config = this.intercepDialogConfig(config);
492
+ this.initConfig(loginConfig);
493
+ config.data = { ...(config.data || {}), ...{ loginConfig } };
635
494
  const dialogService = this.injector.get(DialogService);
636
495
  const dialog = dialogService.open(LocalizeLogindlgComponent, config);
637
496
  await new Promise((resolve) => dialog.onClose.subscribe(res => {
@@ -640,6 +499,37 @@ class LocalizeLogindlgService {
640
499
  }
641
500
  }));
642
501
  }
502
+ intercepDialogConfig(config) {
503
+ config ??= {
504
+ header: 'Login',
505
+ style: { 'max-width': '400px', width: '100%', 'height': '650px' },
506
+ modal: true,
507
+ closable: false,
508
+ showHeader: false,
509
+ };
510
+ config = {
511
+ ...config, ...{
512
+ contentStyle: { 'height': '100%', 'border-radius': '20px' }
513
+ }
514
+ };
515
+ config.style = { ...config.style, ...{ 'border-radius': '20px' } };
516
+ return config;
517
+ }
518
+ initConfig(loginConfig) {
519
+ loginConfig ??= {};
520
+ loginConfig.properties ??= {
521
+ title: 'Your session is expired!<br/> Please login again to continue.',
522
+ loginSuccessMessage: 'You have successfully logged in.',
523
+ logoImage: '/assets/images/logo-300px.png',
524
+ username: { placeHolder: 'Username' },
525
+ password: { placeHolder: 'Password' },
526
+ loginButton: { placeHolder: 'Login' },
527
+ logoutButton: {
528
+ message: 'No, I want to login with another user.',
529
+ placeHolder: 'Logout'
530
+ }
531
+ };
532
+ }
643
533
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: LocalizeLogindlgService, deps: [{ token: i0.Injector }], target: i0.ɵɵFactoryTarget.Injectable });
644
534
  static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: LocalizeLogindlgService, providedIn: 'root' });
645
535
  }
@@ -657,19 +547,13 @@ class LocalizeLogindlgModule {
657
547
  InputTextModule,
658
548
  BrowserModule,
659
549
  FormsModule,
660
- ButtonModule,
661
- DynamicDialogModule,
662
- InputGroupModule,
663
- InputGroupAddonModule], exports: [LocalizeLogindlgComponent] });
550
+ ButtonModule], exports: [LocalizeLogindlgComponent] });
664
551
  static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: LocalizeLogindlgModule, providers: [LocalizeLogindlgService], imports: [CommonModule,
665
552
  ToastModule,
666
553
  InputTextModule,
667
554
  BrowserModule,
668
555
  FormsModule,
669
- ButtonModule,
670
- DynamicDialogModule,
671
- InputGroupModule,
672
- InputGroupAddonModule] });
556
+ ButtonModule] });
673
557
  }
674
558
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: LocalizeLogindlgModule, decorators: [{
675
559
  type: NgModule,
@@ -683,18 +567,558 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImpor
683
567
  BrowserModule,
684
568
  FormsModule,
685
569
  ButtonModule,
686
- DynamicDialogModule,
687
- InputGroupModule,
688
- InputGroupAddonModule
689
570
  ],
690
571
  providers: [LocalizeLogindlgService],
691
572
  schemas: [CUSTOM_ELEMENTS_SCHEMA],
692
573
  }]
693
574
  }] });
694
575
 
576
+ const LOCALIZE_API_ASSETS = {
577
+ network: {
578
+ noConnection: `<?xml version="1.0" encoding="UTF-8"?>
579
+ <svg id="lze-no-connection" data-name="Layer 2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 77.29 70.98">
580
+ <defs>
581
+ <style> .cls-1 { fill: #fff; } .cls-2, .cls-3 { fill: #e30613; } .cls-3 { stroke: #e30613; stroke-miterlimit: 10; stroke-width: .25px; } </style>
582
+ </defs>
583
+ <g id="Layer_3" data-name="Layer 3">
584
+ <g>
585
+ <path class="cls-1" d="m73.29,35c-1.2,0-2.33-.53-3.09-1.46-.48-.57-11.23-13.2-31.55-13.2s-31.11,12.66-31.56,13.2c-1.4,1.71-3.92,1.95-5.63.55-1.71-1.4-1.95-3.92-.55-5.63.54-.66,13.47-16.12,37.74-16.12s37.2,15.46,37.74,16.12c1.4,1.71,1.15,4.23-.56,5.62-.71.58-1.61.9-2.53.9Z"/>
586
+ <path class="cls-1" d="m63.96,45.66c-1.19,0-2.32-.53-3.08-1.44-5.79-6.05-13.86-9.39-22.24-9.21-8.38-.18-16.45,3.16-22.24,9.22-1.46,1.65-3.99,1.81-5.64.35-1.57-1.39-1.8-3.77-.52-5.43,7.32-7.89,17.64-12.29,28.4-12.12,10.76-.17,21.08,4.24,28.4,12.12,1.4,1.71,1.15,4.23-.56,5.62-.71.58-1.6.9-2.53.9Z"/>
587
+ <path class="cls-1" d="m53.3,56.32c-1.24,0-2.41-.57-3.16-1.55-5.73-6.35-15.52-6.85-21.87-1.13-.4.36-.77.73-1.13,1.13-1.36,1.73-3.88,2.03-5.61.67-1.71-1.34-2.03-3.8-.73-5.54,8.39-9.85,23.18-11.04,33.03-2.65.95.81,1.84,1.69,2.65,2.65,1.34,1.75,1,4.26-.75,5.6-.7.53-1.55.82-2.43.82Z"/>
588
+ </g>
589
+ <path class="cls-2" d="m47.21,9.45l-4.06,41.36c-.64,5.42-8.39,5.39-9.01,0,0,0-4.06-41.36-4.06-41.36-.46-4.73,2.99-8.94,7.72-9.4,5.33-.58,9.97,4.09,9.4,9.4h0Z"/>
590
+ <circle class="cls-3" cx="38.64" cy="64.79" r="6.07"/>
591
+ </g>
592
+ </svg>`
593
+ }
594
+ };
595
+
596
+ /**
597
+ * Http method options
598
+ */
599
+ var EMethod;
600
+ (function (EMethod) {
601
+ EMethod["POST"] = "post";
602
+ EMethod["GET"] = "get";
603
+ EMethod["PUT"] = "put";
604
+ EMethod["DELETE"] = "delete";
605
+ EMethod["PATCH"] = "patch";
606
+ })(EMethod || (EMethod = {}));
607
+ // export interface INormalizedError {
608
+ // error: any;
609
+ // code: string;
610
+ // message: string;
611
+ // details?: any;
612
+ // status: number;
613
+ // }
614
+
615
+ class LocalizeApiHelper {
616
+ defaultRetryOptions = {
617
+ connectionError: {
618
+ message: 'Connection error occurred. Please wait',
619
+ blockScreen: true,
620
+ blockScreenZIndex: 10000
621
+ }
622
+ };
623
+ async performRetry(options) {
624
+ let attempts = 0;
625
+ let lastError;
626
+ let consoleCount = 0;
627
+ // Merge default retry options with provided options
628
+ options = { ...this.defaultRetryOptions, ...options };
629
+ let styleElement;
630
+ while (attempts < options.maxRetries()) {
631
+ try {
632
+ const result = await options.callback();
633
+ this.removeBlocker(styleElement);
634
+ return result;
635
+ }
636
+ catch (error) {
637
+ lastError = error;
638
+ if (consoleCount >= 7) {
639
+ console.clear();
640
+ consoleCount = 0;
641
+ }
642
+ if (options.retryUnless && !options.retryUnless(error))
643
+ throw error; // If the error should not be retried, rethrow it
644
+ // Handle connection error
645
+ styleElement = await this.onConnectionError(options, error);
646
+ if (options.onError)
647
+ await this.invokeHook(options.onError.bind(this, error));
648
+ if (attempts >= options.maxRetries() - 1)
649
+ throw error;
650
+ attempts++;
651
+ consoleCount++;
652
+ console.warn(`Attempt ${attempts} failed. Retrying...`, error);
653
+ await waitFor(options.delay);
654
+ }
655
+ }
656
+ console.warn(`Failed after ${options.maxRetries} attempts`);
657
+ throw lastError;
658
+ }
659
+ async performRequestWithRetry(options, config, performRequest) {
660
+ const retryUnless = config.retryOptions?.retryFunction
661
+ || this.isConnectionError;
662
+ return await this.performRetry({
663
+ connectionError: config.retryOptions?.onConnectionError,
664
+ maxRetries: () => config.retryOptions?.maxRetries ?? 1000,
665
+ delay: config.retryOptions?.delay ?? 500,
666
+ callback: () => performRequest(options),
667
+ retryUnless: retryUnless,
668
+ });
669
+ }
670
+ buildUrl(baseUrl, path) {
671
+ const normalizedUrl = `${baseUrl.trim().replace(/\/?$/, '/')}${path.trim().replace(/^\//, '')}`;
672
+ return normalizedUrl.endsWith('/')
673
+ ? normalizedUrl.slice(0, -1)
674
+ : normalizedUrl;
675
+ }
676
+ async invokeHook(callback) {
677
+ if (!callback)
678
+ return;
679
+ const result = callback();
680
+ if (result instanceof Promise) {
681
+ await result;
682
+ }
683
+ }
684
+ createRequest(instance, method, url, body, options) {
685
+ const request$ = instance.client.request(method, url, {
686
+ ...options,
687
+ body,
688
+ observe: 'response',
689
+ }).pipe(takeUntil(instance.destroy$()), catchError((error) => {
690
+ // Convert to a non-observable error to handle in the promise
691
+ return throwError(() => error);
692
+ }));
693
+ return request$;
694
+ }
695
+ defaultRetryFunction(error) {
696
+ // Don't retry for other errors (like 400, 401, 403, etc.)
697
+ if (!this.isConnectionError(error))
698
+ throw error;
699
+ return true;
700
+ }
701
+ isConnectionError(error) {
702
+ const isNetworkError = error.status === 0;
703
+ const isServerError = error.status >= 1000 && error.status < 600;
704
+ return isNetworkError || isServerError;
705
+ }
706
+ async onConnectionError(options, error) {
707
+ if (!options.connectionError)
708
+ return;
709
+ let styleElement;
710
+ if (this.isConnectionError(error)) {
711
+ styleElement = this.screenBlocker(options, error, true);
712
+ await this.invokeHook(options.connectionError.callback?.bind(this, error));
713
+ return styleElement;
714
+ }
715
+ else {
716
+ this.screenBlocker(options, error, false);
717
+ styleElement?.remove();
718
+ }
719
+ }
720
+ screenBlocker(optons, error, add = true) {
721
+ if (!optons.connectionError?.blockScreen)
722
+ return;
723
+ const message = optons.connectionError?.message
724
+ || 'Connection error occurred. Please wait';
725
+ const errorMessage = error?.error?.message || 'An error occurred';
726
+ const suggestinMessage = optons.connectionError?.suggestionMessage
727
+ || 'Please check your internet connection or the server status.';
728
+ const zIndex = optons.connectionError?.blockScreenZIndex || 10000;
729
+ const body = document.body;
730
+ const blcokerHtml = `
731
+ <div class="lze-blocker">
732
+ ${LOCALIZE_API_ASSETS.network.noConnection}
733
+ <div class="lze-blocker__message">
734
+ ${message}
735
+ <span class="lze-blocker__dotting">
736
+ <span class="lze-blocker__dot"></span>
737
+ <span class="lze-blocker__dot"></span>
738
+ <span class="lze-blocker__dot"></span>
739
+ </span>
740
+ </div>
741
+ <div class="lze-blocker__error">${errorMessage}</div>
742
+ <div class="lze-blocker__error_suggestion">${suggestinMessage}</div>
743
+ </div>
744
+ `;
745
+ const style = `
746
+ div.lze-blocker {
747
+ position: fixed;
748
+ top: 0;
749
+ left: 0;
750
+ width: 100%;
751
+ height: 100%;
752
+ background: rgba(0, 0, 0, 0.85) !important;
753
+ z-index: ${zIndex};
754
+ display: flex;
755
+ align-items: center;
756
+ justify-content: center;
757
+ flex-direction: column;
758
+ color: #fff !important;
759
+ font-family: Arial, sans-serif;
760
+ text-align: center;
761
+ padding: 20px;
762
+ box-sizing: border-box;
763
+ overflow: hidden;
764
+ user-select: none;
765
+ }
766
+
767
+ svg#lze-no-connection {
768
+ width: 75px;
769
+ height: 75px;
770
+ margin-bottom: 20px;
771
+ }
772
+
773
+ div.lze-blocker__message {
774
+ color: #fff !important;
775
+ font-size: 18px !important;
776
+ margin-bottom: 10px;
777
+ }
778
+
779
+ .lze-blocker__dotting {
780
+ display: inline-block;
781
+ vertical-align: middle;
782
+ }
783
+ span.lze-blocker__dot {
784
+ display: inline-block;
785
+ width: 7px;
786
+ height: 7px;
787
+ background-color: #ffffff !important;
788
+ border-radius: 50%;
789
+ margin-left: 3px;
790
+ opacity: 0.3;
791
+ animation: dotting 1s infinite;
792
+ }
793
+ .lze-blocker__dot:nth-child(1) {
794
+ animation-delay: 0s;
795
+ opacity: 1;
796
+ }
797
+ .lze-blocker__dot:nth-child(2) {
798
+ animation-delay: 0.2s;
799
+ }
800
+ .lze-blocker__dot:nth-child(3) {
801
+ animation-delay: 0.4s;
802
+ }
803
+
804
+ @keyframes dotting {
805
+ 0%, 80%, 100% { opacity: 0.3; }
806
+ 40% { opacity: 1; }
807
+ }
808
+
809
+ div.lze-blocker__error {
810
+ color: #f00;
811
+ font-size: 14px !important;
812
+ margin-bottom: 10px;
813
+ text-shadow: 0 0 1px #ff5f5f !important;
814
+ }
815
+
816
+ div.lze-blocker__error_suggestion {
817
+ color: #ccc !important;
818
+ font-size: 14px !important;
819
+ margin-top: 10px;
820
+ }
821
+
822
+ @keyframes spin {
823
+ 0% { transform: rotate(0deg); }
824
+ 100% { transform: rotate(360deg); }
825
+ }
826
+ `;
827
+ const styleElement = document.createElement('style');
828
+ if (add) {
829
+ if (!document.querySelector('.lze-blocker')) {
830
+ styleElement.innerHTML = style;
831
+ document.head.appendChild(styleElement);
832
+ body.insertAdjacentHTML('beforeend', blcokerHtml);
833
+ }
834
+ }
835
+ else {
836
+ this.removeBlocker(styleElement);
837
+ }
838
+ return styleElement;
839
+ }
840
+ removeBlocker(styleElement) {
841
+ const blocker = document.querySelector('.lze-blocker');
842
+ blocker?.remove();
843
+ styleElement?.remove();
844
+ }
845
+ }
846
+ const ApiHelper = new LocalizeApiHelper();
847
+
848
+ const SCHEMES = LocalizeToken.httpHeaders;
849
+ class LocalizeApiService {
850
+ httpClient;
851
+ localizeTokenService;
852
+ destroy$ = new Subject();
853
+ configSubject = new BehaviorSubject({});
854
+ isRequestingSubject = new BehaviorSubject(false);
855
+ isResolvingStartupSubject = new BehaviorSubject(false);
856
+ get isResolvingStartup() { return this.isResolvingStartupSubject.value; }
857
+ get needTenant() { return this.localizeTokenService.config.tenantToken !== undefined; }
858
+ get isRequesting() { return this.isRequestingSubject.value; }
859
+ get isRevokingToken() { return this.localizeTokenService.isRevokingToken; }
860
+ set isRevokingToken(value) { this.localizeTokenService.isRevokingToken = value; }
861
+ get accessToken() { return this.localizeTokenService.accessToken; }
862
+ set accessToken(value) { this.localizeTokenService.accessToken = value; }
863
+ get refreshToken() { return this.localizeTokenService.refreshToken; }
864
+ get tenantToken() { return this.localizeTokenService.tenantToken; }
865
+ defaultConfig = {
866
+ waitEachRequest: { milliseconds: 0 },
867
+ enableRequestCancellation: true,
868
+ retryOptions: {
869
+ maxRetries: 1000,
870
+ delay: 1000,
871
+ retryFunction: ApiHelper.defaultRetryFunction.bind(this),
872
+ },
873
+ };
874
+ get config() {
875
+ this.validateConfig();
876
+ return this.configSubject.value;
877
+ }
878
+ apiOptions = {
879
+ method: EMethod.GET,
880
+ requestBody: null,
881
+ };
882
+ constructor(httpClient, localizeTokenService) {
883
+ this.httpClient = httpClient;
884
+ this.localizeTokenService = localizeTokenService;
885
+ }
886
+ /**
887
+ * Initialize the API service.
888
+ * @param apiConfigs - The API configurations.
889
+ */
890
+ init(apiConfigs) {
891
+ console.log('LocalizeApiService is initialized.');
892
+ this.configSubject.next({ ...this.defaultConfig, ...apiConfigs });
893
+ }
894
+ cancelPendingRequests() {
895
+ this.config.enableRequestCancellation
896
+ && this.destroy$.next();
897
+ }
898
+ ngOnDestroy() {
899
+ this.destroy$.next();
900
+ this.destroy$.complete();
901
+ }
902
+ /**
903
+ * A higher-order function that returns a curried function for making API requests.
904
+ *
905
+ * @param baseUrl - The base URL of the API.
906
+ * @returns A curried function that can be used to make API requests.
907
+ */
908
+ func = (baseUrl) => (path, method = EMethod.GET, reqBody = null, reqHeaders) => this.request(baseUrl, path, method, reqBody, reqHeaders);
909
+ async request(baseUrl, path, method = EMethod.GET, reqBody = null, reqHeaders) {
910
+ await waitUntil(() => !this.isResolvingStartup, 500);
911
+ await ApiHelper.invokeHook(this.config.onPrepareRequest);
912
+ const apiOptions = this.buildApiOptions(baseUrl, path, method, reqBody, reqHeaders);
913
+ try {
914
+ await this.toWaitForPreviousRequest();
915
+ return await ApiHelper.performRequestWithRetry(apiOptions, this.config, this.performRequest.bind(this));
916
+ }
917
+ catch (error) {
918
+ return await this.handleOnRequestError(error, apiOptions);
919
+ }
920
+ }
921
+ async handleOnRequestError(error, options) {
922
+ if (error.status !== 401)
923
+ throw error;
924
+ await waitUntil(() => !this.isResolvingStartup, 50);
925
+ return await ApiHelper.performRetry({
926
+ maxRetries: () => 1000,
927
+ delay: 10,
928
+ retryUnless: (error) => error.status === 401 || ApiHelper.isConnectionError(error),
929
+ callback: async () => {
930
+ // Only handle 401 Unauthorized errors
931
+ await this.revokeToken();
932
+ // Retry the request with the new access token
933
+ return await this.performRequest(options);
934
+ }
935
+ });
936
+ }
937
+ async performRequest(options) {
938
+ // Build the request options
939
+ const buildOptions = { headers: this.buildHeaderOptions(options) };
940
+ // Create the request observable
941
+ const request$ = ApiHelper.createRequest({
942
+ client: this.httpClient,
943
+ destroy$: () => this.destroy$
944
+ }, options.method, options.requestUrl, options.requestBody, buildOptions);
945
+ // Set the isRequesting state to true before making the request
946
+ this.isRequestingSubject.next(true);
947
+ const response = await new Promise((resolve, reject) => request$.subscribe({ next: (res) => resolve(res.body), error: reject }));
948
+ // Reset the isRequesting state after the request completes
949
+ this.isRequestingSubject.next(false);
950
+ return response;
951
+ }
952
+ async revokeToken() {
953
+ try {
954
+ if (await this.interceptRevokeToken())
955
+ return;
956
+ this.isRevokingToken = true;
957
+ const apiOptions = {
958
+ ...this.buildApiOptions(this.localizeTokenService.config.refreshToken?.requestUrl || ''),
959
+ refreshToken: true,
960
+ };
961
+ // const revokeToken = await this.performRequest(apiOptions);
962
+ const revokeToken = await ApiHelper.performRequestWithRetry(apiOptions, this.config, this.performRequest.bind(this));
963
+ await this.handleOnTokenRevoked(revokeToken);
964
+ }
965
+ catch (error) {
966
+ // Handle the error, log it
967
+ await ApiHelper.invokeHook(this.config.onAutoLogout);
968
+ }
969
+ finally {
970
+ // Reset the revoking token state
971
+ this.isRevokingToken = false;
972
+ }
973
+ }
974
+ /** default http request options */
975
+ buildHeaderOptions(options) {
976
+ const headers = {
977
+ ...(options.refreshToken && { [SCHEMES.X_REFRESH_TOKEN]: `${this.refreshToken}` }),
978
+ ...(!options.isFormData && { [SCHEMES.CONTENT_TYPE]: 'application/json' }),
979
+ [SCHEMES.AUTHORIZATION]: `Bearer ${this.accessToken}`,
980
+ ...(this.needTenant && { [SCHEMES.X_TENANT]: `${this.tenantToken}` })
981
+ };
982
+ return new HttpHeaders({ ...headers, ...options.headers });
983
+ }
984
+ buildApiOptions(baseUrl, path = '', method = EMethod.GET, requestBody = null, headers) {
985
+ const requestUrl = ApiHelper.buildUrl(baseUrl, path);
986
+ const isFormData = requestBody && requestBody instanceof FormData;
987
+ return {
988
+ ...this.apiOptions,
989
+ ...{ headers, method, requestUrl, requestBody, isFormData }
990
+ };
991
+ }
992
+ async toWaitForPreviousRequest() {
993
+ if (this.isRevokingToken) {
994
+ // console.warn('A token refresh is in progress. Request is waiting.');
995
+ await waitUntil(() => !this.isRevokingToken);
996
+ // console.info('Token refresh complete. Resuming request.');
997
+ }
998
+ // to wait for each request in 50ms, even if the request is not completed
999
+ const waitMilliseconds = this.config.waitEachRequest?.milliseconds;
1000
+ if (waitMilliseconds && this.isRequesting) {
1001
+ // console.warn(`Request throttling: Another request is in progress. Waiting for ${waitMilliseconds}ms.`);
1002
+ await waitFor(waitMilliseconds, this.isRequesting);
1003
+ }
1004
+ }
1005
+ async handleOnTokenRevoked(response) {
1006
+ if (response?.status) {
1007
+ // If the response is successful, update the access token
1008
+ this.accessToken = response.message;
1009
+ }
1010
+ else {
1011
+ // If the response indicates an error, invoke the onRevokeUnauthorized hook
1012
+ console.warn('Token revocation failed, refresh token is expired.', response.message);
1013
+ await ApiHelper.invokeHook(this.config.onRevokeUnauthorized);
1014
+ }
1015
+ }
1016
+ async interceptRevokeToken() {
1017
+ if (this.isRevokingToken) {
1018
+ console.warn('Token is already being revoked. Waiting for the current operation to complete...');
1019
+ await waitUntil(() => !this.isRevokingToken);
1020
+ return true;
1021
+ }
1022
+ if (!this.refreshToken) {
1023
+ // await ApiHelper.invokeHook(this.apiConfigs.onAutoLogout);
1024
+ throw new Error('Refresh token is missing. Please login again.');
1025
+ }
1026
+ return false;
1027
+ }
1028
+ validateConfig() {
1029
+ if (this.localizeTokenService.config.tenantToken
1030
+ && !this.localizeTokenService.config.tenantToken?.name?.trim().length) {
1031
+ throw Error('Tenant token is required but tenantTokenName is not configured');
1032
+ }
1033
+ if (!this.localizeTokenService.config.refreshToken?.requestUrl?.trim().length) {
1034
+ throw Error('Revoke token URL is not configured - token refresh will not work');
1035
+ }
1036
+ }
1037
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: LocalizeApiService, deps: [{ token: i4.HttpClient }, { token: LocalizeTokenService }], target: i0.ɵɵFactoryTarget.Injectable });
1038
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: LocalizeApiService, providedIn: 'root' });
1039
+ }
1040
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: LocalizeApiService, decorators: [{
1041
+ type: Injectable,
1042
+ args: [{
1043
+ providedIn: 'root'
1044
+ }]
1045
+ }], ctorParameters: () => [{ type: i4.HttpClient }, { type: LocalizeTokenService }] });
1046
+
1047
+ class LocalizeTokenModule {
1048
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: LocalizeTokenModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
1049
+ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.0.5", ngImport: i0, type: LocalizeTokenModule });
1050
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: LocalizeTokenModule, providers: [
1051
+ LocalizeTokenService,
1052
+ LocalizeApiService
1053
+ ] });
1054
+ }
1055
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: LocalizeTokenModule, decorators: [{
1056
+ type: NgModule,
1057
+ args: [{
1058
+ providers: [
1059
+ LocalizeTokenService,
1060
+ LocalizeApiService
1061
+ ]
1062
+ }]
1063
+ }] });
1064
+
1065
+ class LocalizeApiTokenService {
1066
+ api;
1067
+ token;
1068
+ loginDialog;
1069
+ constructor(tokenService, apiService, loginDialogService) {
1070
+ this.api = apiService;
1071
+ this.token = tokenService;
1072
+ this.loginDialog = loginDialogService;
1073
+ }
1074
+ initialize(tokenConfig, apiConfig) {
1075
+ // Initialize the LocalizeTokenService with the provided token configuration
1076
+ this.token.init(tokenConfig);
1077
+ // Initialize the LocalizeApiService with the provided API configuration
1078
+ this.api.init(apiConfig);
1079
+ console.log('LocalizeApiTokenService initialized with token and API configurations.');
1080
+ }
1081
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: LocalizeApiTokenService, deps: [{ token: LocalizeTokenService }, { token: LocalizeApiService }, { token: LocalizeLogindlgService }], target: i0.ɵɵFactoryTarget.Injectable });
1082
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: LocalizeApiTokenService, providedIn: 'root' });
1083
+ }
1084
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: LocalizeApiTokenService, decorators: [{
1085
+ type: Injectable,
1086
+ args: [{
1087
+ providedIn: 'root'
1088
+ }]
1089
+ }], ctorParameters: () => [{ type: LocalizeTokenService }, { type: LocalizeApiService }, { type: LocalizeLogindlgService }] });
1090
+
1091
+ class LocalizeApiTokenModule {
1092
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: LocalizeApiTokenModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
1093
+ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.0.5", ngImport: i0, type: LocalizeApiTokenModule, imports: [CommonModule,
1094
+ LocalizeTokenModule,
1095
+ LocalizeLogindlgModule] });
1096
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: LocalizeApiTokenModule, providers: [
1097
+ LocalizeApiTokenService
1098
+ ], imports: [CommonModule,
1099
+ LocalizeTokenModule,
1100
+ LocalizeLogindlgModule] });
1101
+ }
1102
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: LocalizeApiTokenModule, decorators: [{
1103
+ type: NgModule,
1104
+ args: [{
1105
+ declarations: [],
1106
+ imports: [
1107
+ CommonModule,
1108
+ LocalizeTokenModule,
1109
+ LocalizeLogindlgModule
1110
+ ],
1111
+ providers: [
1112
+ LocalizeApiTokenService
1113
+ ]
1114
+ }]
1115
+ }] });
1116
+
1117
+ //#region login dialog
1118
+
695
1119
  /**
696
1120
  * Generated bundle index. Do not edit.
697
1121
  */
698
1122
 
699
- export { EMethod, LocalizeApiService, LocalizeLogindlgComponent, LocalizeLogindlgModule, LocalizeLogindlgService, LocalizeToken, LocalizeTokenModule, LocalizeTokenService, LocalizeTokenStorage, extractMainDomain, waitFor, waitUntil };
1123
+ export { ApiHelper, EMethod, LOCALIZE_API_ASSETS, LocalizeApiService, LocalizeApiTokenModule, LocalizeApiTokenService, LocalizeLogindlgComponent, LocalizeLogindlgModule, LocalizeLogindlgService, LocalizeToken, LocalizeTokenModule, LocalizeTokenService, LocalizeTokenStorage, extractMainDomain, waitFor, waitUntil };
700
1124
  //# sourceMappingURL=sambath999-localize-token.mjs.map