UNPKG

@c8y/ngx-components

Version:

Angular modules for Cumulocity IoT applications

183 lines (179 loc) 7.71 kB
import * as i0 from '@angular/core'; import { Injectable } from '@angular/core'; import * as i1 from '@c8y/client'; import { ApplicationType, ApplicationAvailability } from '@c8y/client'; import * as i2 from '@c8y/ngx-components'; import { uniq } from 'lodash-es'; class TranslationStoreService { constructor(appService, appState, zip) { this.appService = appService; this.appState = appState; this.zip = zip; this.translationAppName = 'User defined translations'; this.translationAppContextPath = 'user-defined-translations'; } /** * Retrieves a list of available translations for the given locales from all the hosted apps available on the tenant. */ async getAvailableTranslations(locales) { const { data: hostedApps } = await this.appService.list({ tenant: this.appState.currentTenant.value.name, type: 'HOSTED', pageSize: 2000 }); const uniqueContextPaths = uniq(hostedApps .filter(app => app.contextPath && app.manifest?.webSdkVersion) .map(app => app.contextPath)); const translations = {}; for (const contextPath of uniqueContextPaths) { for (const locale of locales) { try { const translationsForLanguageAndApp = await this.getFileFromPath(`/apps/${contextPath}/${locale}.json`); for (const key of Object.keys(translationsForLanguageAndApp)) { if (!translations[key]) { translations[key] = {}; } translations[key][locale] = translationsForLanguageAndApp[key]; } } catch (e) { continue; } } } return translations; } /** * Retrieves the translations for the given locale from the translation app. */ async getTranslationsForLocale(locale) { try { const translations = await this.getFileFromTranslationApp(`${locale}.json`); if (translations[locale]) { return translations[locale]; } } catch (e) { // do nothing. } return {}; } /** * Retrieves the translations for the given locales from the translation app. */ async loadTranslationsForLocales(locales) { const translations = {}; const loadAndAddLocale = async (locale) => { translations[locale] = await this.getTranslationsForLocale(locale); }; await Promise.all(locales.map(loadAndAddLocale)); return translations; } /** * Retrieves a combined list of translations for all the provided locales. * The locales are combined into a single object per key and an array of these objects is returned. */ async getCombinedListOfTranslationsForPerKey(locales) { const translations = await this.loadTranslationsForLocales(locales); const translationMap = {}; for (const locale of Object.keys(translations)) { for (const key of Object.keys(translations[locale])) { let translationsForKey = translationMap[key]; if (!translationsForKey) { translationsForKey = {}; translationMap[key] = translationsForKey; } translationsForKey[locale] = translations[locale][key]; } } const keys = Object.keys(translationMap).sort((a, b) => a.localeCompare(b)); return keys.map(key => Object.assign({ key }, translationMap[key])); } /** * Updates the files of the translation application with the provided translations. */ async updateTranslations(translations) { const filesToUpload = new Array(); const translationsPerLocale = {}; for (const entry of translations) { const key = entry.key; for (const locale of Object.keys(entry)) { if (locale === 'key') { continue; } if (!translationsPerLocale[locale]) { translationsPerLocale[locale] = {}; } if (entry[locale]) { translationsPerLocale[locale][key] = entry[locale]; } } } const langs = this.appState.state.langs; for (const locale of langs) { const fileName = `${locale}.json`; filesToUpload.push({ path: fileName, contents: new File([JSON.stringify({ [locale]: translationsPerLocale[locale] || {} })], fileName) }); } const app = await this.getOrCreateTranslationApp(); await this.appService.binary(app).updateFiles(filesToUpload); } /** * @returns The translation app for the current tenant. If it does not exist, it will be created. */ async getOrCreateTranslationApp() { const { data: apps } = await this.appService.listByName(this.translationAppName); const ownApp = apps.find(app => app.contextPath === this.translationAppContextPath && app.owner.tenant.id === this.appState.currentTenant.value.name); if (ownApp) { return ownApp; } const { data: app } = await this.appService.create({ name: this.translationAppName, contextPath: this.translationAppContextPath, key: `${this.translationAppContextPath}-app-key`, type: ApplicationType.HOSTED, availability: ApplicationAvailability.MARKET, config: { icon: { class: 'language1' } }, noAppSwitcher: true, description: 'Providing user defined translations' }); const zip = await this.zip.createZip([]); const { data: binary } = await this.appService.binary(app).upload(zip, 'translations.zip'); const { data: updatedApp } = await this.appService.update({ id: app.id, activeVersionId: binary.id }); return updatedApp; } async getFileFromTranslationApp(file) { return this.getFileFromPath(`/apps/public/${this.translationAppContextPath}/${file}`); } async getFileFromPath(path) { const finalPath = `${path}?nocache=${Date.now()}`; const response = await fetch(finalPath); if (response.status !== 200) { throw new Error(`Failed to fetch file from ${path}`); } return response.json(); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TranslationStoreService, deps: [{ token: i1.ApplicationService }, { token: i2.AppStateService }, { token: i2.ZipService }], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TranslationStoreService, providedIn: 'root' }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TranslationStoreService, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }], ctorParameters: () => [{ type: i1.ApplicationService }, { type: i2.AppStateService }, { type: i2.ZipService }] }); /** * Generated bundle index. Do not edit. */ export { TranslationStoreService }; //# sourceMappingURL=c8y-ngx-components-translation-editor-data.mjs.map