From 0468df10dbf71d309b4f6a9ff43eb687bdb1777b Mon Sep 17 00:00:00 2001 From: Annika Nowak Date: Thu, 15 Feb 2024 16:33:09 +0100 Subject: [PATCH 1/2] feat: adaption of the translation cache service --- .../utils/caching-translate-loader.utils.ts | 14 +---- .../lib/services/translation-cache.service.ts | 62 +++++++++++++------ 2 files changed, 43 insertions(+), 33 deletions(-) diff --git a/libs/portal-integration-angular/src/lib/core/utils/caching-translate-loader.utils.ts b/libs/portal-integration-angular/src/lib/core/utils/caching-translate-loader.utils.ts index 9aeebe1b..4bcc3c07 100644 --- a/libs/portal-integration-angular/src/lib/core/utils/caching-translate-loader.utils.ts +++ b/libs/portal-integration-angular/src/lib/core/utils/caching-translate-loader.utils.ts @@ -17,18 +17,6 @@ export class CachingTranslateLoader implements TranslateLoader { getTranslation(lang: string): Observable { const url = `${this.prefix}${lang}${this.suffix}` - return this.translationCache.getTranslationFile(url).pipe( - filter((tf) => tf !== null), - first(), - mergeMap((tf) => { - if (tf) { - return of(tf) - } - return this.translationCache.updateTranslationFile(url, null).pipe( - mergeMap(() => this.translateLoader.getTranslation(lang)), - mergeMap((t) => this.translationCache.updateTranslationFile(url, t)) - ) - }) - ) + return this.translationCache.getTranslationFile(url, () => this.translateLoader.getTranslation(lang)) } } diff --git a/libs/portal-integration-angular/src/lib/services/translation-cache.service.ts b/libs/portal-integration-angular/src/lib/services/translation-cache.service.ts index 420757ce..871dede7 100644 --- a/libs/portal-integration-angular/src/lib/services/translation-cache.service.ts +++ b/libs/portal-integration-angular/src/lib/services/translation-cache.service.ts @@ -1,6 +1,6 @@ import { Injectable, OnDestroy } from '@angular/core' import { SyncableTopic } from '@onecx/accelerator' -import { Observable, concat, first, from, map, mergeMap, of } from 'rxjs' +import { BehaviorSubject, Observable, filter, first, map, of, race, tap, withLatestFrom } from 'rxjs' // This topic is defined here and not in integration-interface, because // it is not used as framework independent integration but for improving @@ -13,29 +13,51 @@ class TranslationCacheTopic extends SyncableTopic> { @Injectable({ providedIn: 'root' }) export class TranslationCacheService implements OnDestroy { - translationCache$ = new TranslationCacheTopic() - + private translationCache$ = new TranslationCacheTopic() + private translations$ = new BehaviorSubject({}) + constructor() { + this.translationCache$ + .pipe( + withLatestFrom(this.translations$), + map(([topicTranslations, translations]) => { + let foundValueOthersDoNotKnow = false + let newTranslations = { ...translations } + Object.keys(topicTranslations).forEach((k) => { + if (!topicTranslations[k] && translations[k]) { + foundValueOthersDoNotKnow = true + } + newTranslations[k] ??= topicTranslations[k] + }) + return [newTranslations, foundValueOthersDoNotKnow] + }), + tap(([newTranslations, foundValueOthersDoNotKnow]) => { + if (foundValueOthersDoNotKnow) { + this.translationCache$.publish(newTranslations) + } + }), + map(([newTranslations]) => newTranslations) + ) + .subscribe(this.translations$) + } ngOnDestroy(): void { this.translationCache$.destroy() } - getTranslationFile(url: string): Observable { - return this.getCache().pipe(map((t) => t[url])) - } - - updateTranslationFile(url: string, translations: any): Observable { - return this.getCache().pipe( - first(), - mergeMap((t) => { - return from(this.translationCache$.publish({ ...t, [url]: translations })).pipe(map(() => translations)) - }) - ) - } - - private getCache(): Observable> { - if (this.translationCache$.getValue()) { - return this.translationCache$.asObservable() + getTranslationFile(url: string, cacheMissFunction: () => Observable): Observable { + if (this.translations$.value[url]) { + return of(this.translations$.value[url]) } - return concat(of({}), this.translationCache$.asObservable()) + this.translationCache$.publish({ ...this.translations$.value, [url]: null }) + return race( + this.translations$.pipe( + filter((t) => t[url]), + map((t) => t[url]) + ), + cacheMissFunction().pipe( + tap((t) => { + this.translationCache$.publish({ ...this.translations$.value, [url]: t }) + }) + ) + ).pipe(first()) } } From 3cf10d3a9581bb343c261f71c56f0d3ec27ffacf Mon Sep 17 00:00:00 2001 From: "kim.tran" Date: Fri, 16 Feb 2024 09:46:55 +0100 Subject: [PATCH 2/2] fix: lint issue and renaming --- .../core/utils/caching-translate-loader.utils.ts | 2 +- .../src/lib/services/translation-cache.service.ts | 14 +++++++------- package-lock.json | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/libs/portal-integration-angular/src/lib/core/utils/caching-translate-loader.utils.ts b/libs/portal-integration-angular/src/lib/core/utils/caching-translate-loader.utils.ts index 4bcc3c07..97245e6a 100644 --- a/libs/portal-integration-angular/src/lib/core/utils/caching-translate-loader.utils.ts +++ b/libs/portal-integration-angular/src/lib/core/utils/caching-translate-loader.utils.ts @@ -1,7 +1,7 @@ import { HttpClient } from '@angular/common/http' import { TranslateLoader } from '@ngx-translate/core' import { TranslateHttpLoader } from '@ngx-translate/http-loader' -import { filter, first, mergeMap, Observable, of } from 'rxjs' +import { Observable } from 'rxjs' import { TranslationCacheService } from '../../services/translation-cache.service' export class CachingTranslateLoader implements TranslateLoader { diff --git a/libs/portal-integration-angular/src/lib/services/translation-cache.service.ts b/libs/portal-integration-angular/src/lib/services/translation-cache.service.ts index 871dede7..e8c0846c 100644 --- a/libs/portal-integration-angular/src/lib/services/translation-cache.service.ts +++ b/libs/portal-integration-angular/src/lib/services/translation-cache.service.ts @@ -13,15 +13,15 @@ class TranslationCacheTopic extends SyncableTopic> { @Injectable({ providedIn: 'root' }) export class TranslationCacheService implements OnDestroy { - private translationCache$ = new TranslationCacheTopic() + private translationTopic$ = new TranslationCacheTopic() private translations$ = new BehaviorSubject({}) constructor() { - this.translationCache$ + this.translationTopic$ .pipe( withLatestFrom(this.translations$), map(([topicTranslations, translations]) => { let foundValueOthersDoNotKnow = false - let newTranslations = { ...translations } + const newTranslations = { ...translations } Object.keys(topicTranslations).forEach((k) => { if (!topicTranslations[k] && translations[k]) { foundValueOthersDoNotKnow = true @@ -32,7 +32,7 @@ export class TranslationCacheService implements OnDestroy { }), tap(([newTranslations, foundValueOthersDoNotKnow]) => { if (foundValueOthersDoNotKnow) { - this.translationCache$.publish(newTranslations) + this.translationTopic$.publish(newTranslations) } }), map(([newTranslations]) => newTranslations) @@ -40,14 +40,14 @@ export class TranslationCacheService implements OnDestroy { .subscribe(this.translations$) } ngOnDestroy(): void { - this.translationCache$.destroy() + this.translationTopic$.destroy() } getTranslationFile(url: string, cacheMissFunction: () => Observable): Observable { if (this.translations$.value[url]) { return of(this.translations$.value[url]) } - this.translationCache$.publish({ ...this.translations$.value, [url]: null }) + this.translationTopic$.publish({ ...this.translations$.value, [url]: null }) return race( this.translations$.pipe( filter((t) => t[url]), @@ -55,7 +55,7 @@ export class TranslationCacheService implements OnDestroy { ), cacheMissFunction().pipe( tap((t) => { - this.translationCache$.publish({ ...this.translations$.value, [url]: t }) + this.translationTopic$.publish({ ...this.translations$.value, [url]: t }) }) ) ).pipe(first()) diff --git a/package-lock.json b/package-lock.json index 9b027d24..337af6ef 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@onecx/onecx-portal-ui-libs", - "version": "4.3.0", + "version": "4.5.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@onecx/onecx-portal-ui-libs", - "version": "4.3.0", + "version": "4.5.0", "hasInstallScript": true, "license": "Apache-2.0", "dependencies": {