UNPKG

@paperbits/common

Version:
295 lines (224 loc) 11.5 kB
import * as Utils from "../utils"; import * as Constants from "../constants"; import * as Objects from "../objects"; import { PopupContract } from "../popups/popupContract"; import { IPopupService } from "../popups/IPopupService"; import { IObjectStorage, Query, Page } from "../persistence"; import { Contract } from "../contract"; import { ILocaleService } from "../localization"; import { PopupMetadata } from "./popupMetadata"; import { PopupLocalizedContract } from "./popupLocalizedContract"; import { IBlockService } from "../blocks"; import { Logger } from "../logging"; const popupsPath = "popups"; const documentsPath = "files"; const defaultTemplateBlockKey = "blocks/new-popup-template"; export class PopupService implements IPopupService { constructor( private readonly objectStorage: IObjectStorage, private readonly localeService: ILocaleService, private readonly blockService: IBlockService, private readonly logger: Logger ) { } public async getPopupByKey(key: string, requestedLocale?: string): Promise<PopupContract> { if (!key) { throw new Error(`Parameter "key" not specified.`); } const popupContract = await this.objectStorage.getObject<PopupLocalizedContract>(key); if (!popupContract) { return null; } const defaultLocale = await this.localeService.getDefaultLocaleCode(); const currentLocale = await this.localeService.getCurrentLocaleCode(); return this.localizedContractToContract(defaultLocale, currentLocale, requestedLocale, popupContract); } /** * Copies limited number of metadata properties. */ private copyMetadata(sourceMetadata: PopupMetadata, targetMetadata: PopupMetadata): PopupMetadata { if (!sourceMetadata) { throw new Error(`Parameter "sourceMetadata" not specified.`); } if (!targetMetadata) { throw new Error(`Parameter "targetMetadata" not specified.`); } targetMetadata.title = sourceMetadata.title; targetMetadata.description = sourceMetadata.description; return targetMetadata; } private localizedContractToContract(defaultLocale: string, currentLocale: string, requestedLocale: string, localizedPopupContract: PopupLocalizedContract): PopupContract { const locales = localizedPopupContract[Constants.localePrefix]; const popupMetadata = (requestedLocale ? locales[requestedLocale] : locales[currentLocale]) || this.copyMetadata(locales[defaultLocale], {}); if (!popupMetadata) { return null; } const popupContract: any = { key: localizedPopupContract.key, ...popupMetadata }; return popupContract; } private convertPopup(localizedPopup: Page<PopupLocalizedContract>, defaultLocale: string, searchLocale: string, requestedLocale: string): Page<PopupContract> { const resultPopup: Page<PopupContract> = { value: localizedPopup.value.map(x => this.localizedContractToContract(defaultLocale, searchLocale, requestedLocale, x)), takeNext: async (): Promise<Page<PopupContract>> => { const nextLocalizedPopup = await localizedPopup.takeNext(); return this.convertPopup(nextLocalizedPopup, defaultLocale, searchLocale, requestedLocale); } }; if (!localizedPopup.takeNext) { resultPopup.takeNext = null; } return resultPopup; } public async search(query: Query<PopupContract>, requestedLocale?: string): Promise<Page<PopupContract>> { if (!query) { throw new Error(`Parameter "query" not specified.`); } const defaultLocale = await this.localeService.getDefaultLocaleCode(); const currentLocale = await this.localeService.getCurrentLocaleCode(); const searchLocale = requestedLocale || currentLocale; const localizedQuery = Utils.localizeQuery(query, searchLocale); try { const popupOfResults = await this.objectStorage.searchObjects<PopupLocalizedContract>(popupsPath, localizedQuery); return this.convertPopup(popupOfResults, defaultLocale, searchLocale, requestedLocale); } catch (error) { throw new Error(`Unable to search popups: ${error.stack || error.message}`); } } public async deletePopup(popup: PopupContract): Promise<void> { const deletePopupPromise = this.objectStorage.deleteObject(popup.key); await Promise.all([deletePopupPromise]); } public async createPopup(title: string, description: string = null, templateBlockKey: string = defaultTemplateBlockKey): Promise<PopupContract> { const locale = await this.localeService.getDefaultLocaleCode(); const identifier = Utils.guid(); const popupKey = `${popupsPath}/${identifier}`; const contentKey = `${documentsPath}/${identifier}`; const localizedPopup: PopupLocalizedContract = { key: popupKey, locales: { [locale]: { title: title, description: description, contentKey: contentKey } } }; await this.objectStorage.addObject<PopupLocalizedContract>(popupKey, localizedPopup); const template = await this.blockService.getBlockContent(templateBlockKey); template["key"] = contentKey; // rewriting own key await this.objectStorage.addObject<Contract>(contentKey, template); const popupContract: PopupContract = { key: popupKey, title: title, description: description, contentKey: contentKey }; return popupContract; } public async copyPopup(key: string): Promise<PopupContract> { const originalPopup = await this.objectStorage.getObject<PopupLocalizedContract>(key); const identifier = Utils.guid(); const targetKey = `${popupsPath}/${identifier}`; const targetPage: PopupLocalizedContract = { key: targetKey, locales: {} }; const sourceLocales = Object.keys(originalPopup.locales); for (const locale of sourceLocales) { const sourceMetadata = originalPopup.locales[locale]; const sourceContentKey = sourceMetadata.contentKey; const sourcePageContent = await this.objectStorage.getObject<Contract>(sourceContentKey); const targetIdentifier = Utils.guid(); const targetContentKey = `${documentsPath}/${targetIdentifier}`; const targetMetadata: PopupMetadata = { title: sourceMetadata.title + " (copy)", description: sourceMetadata.description, contentKey: targetContentKey }; targetPage.locales[locale] = targetMetadata; const targetPageContent = Objects.clone<Contract>(sourcePageContent); targetPageContent["key"] = targetContentKey; await this.objectStorage.addObject<Contract>(targetContentKey, targetPageContent); this.logger.trackEvent("PopupCopied", { key: targetKey, sourcePageKey: key }); } await this.objectStorage.addObject<PopupLocalizedContract>(targetKey, targetPage); return this.getPopupByKey(targetKey); } public async updatePopup(popup: PopupContract, requestedLocale?: string): Promise<void> { if (!popup) { throw new Error(`Parameter "popup" not specified.`); } if (!requestedLocale) { requestedLocale = await this.localeService.getCurrentLocaleCode(); } const popupContract = await this.objectStorage.getObject<PopupLocalizedContract>(popup.key); if (!popupContract) { throw new Error(`Could not update popup. Popup with key "${popup.key}" doesn't exist.`); } const existingLocaleMetadata = popupContract.locales[requestedLocale] || <PopupMetadata>{}; popupContract.locales[requestedLocale] = this.copyMetadata(popup, existingLocaleMetadata); await this.objectStorage.updateObject<PopupLocalizedContract>(popup.key, popupContract); } public async getPopupContent(popupKey: string, requestedLocale?: string): Promise<Contract> { if (!popupKey) { throw new Error(`Parameter "popupKey" not specified.`); } if (!requestedLocale) { requestedLocale = await this.localeService.getCurrentLocaleCode(); } const defaultLocale = await this.localeService.getDefaultLocaleCode(); const localizedPopupContract = await this.objectStorage.getObject<PopupLocalizedContract>(popupKey); let popupMetadata = localizedPopupContract.locales[requestedLocale]; if (!popupMetadata) { popupMetadata = localizedPopupContract.locales[defaultLocale]; } let popupContent; if (popupMetadata.contentKey) { popupContent = await this.objectStorage.getObject<Contract>(popupMetadata.contentKey); } else { const popupDefaultLocaleMetadata = localizedPopupContract.locales[defaultLocale]; popupContent = await this.objectStorage.getObject<Contract>(popupDefaultLocaleMetadata.contentKey); } return popupContent; } public async updatePopupContent(popupKey: string, content: Contract, requestedLocale?: string): Promise<void> { if (!popupKey) { throw new Error(`Parameter "popupKey" not specified.`); } if (!content) { throw new Error(`Parameter "content" not specified.`); } const localizedPopupContract = await this.objectStorage.getObject<PopupLocalizedContract>(popupKey); if (!localizedPopupContract) { throw new Error(`Popup with key "${popupKey}" not found.`); } if (!requestedLocale) { requestedLocale = await this.localeService.getCurrentLocaleCode(); } let popupMetadata = localizedPopupContract.locales[requestedLocale]; if (!popupMetadata) { const defaultLocale = await this.localeService.getDefaultLocaleCode(); const defaultPopupMetadata = localizedPopupContract.locales[defaultLocale]; const identifier = Utils.guid(); popupMetadata = this.copyMetadata(defaultPopupMetadata, { contentKey: `${documentsPath}/${identifier}` }); localizedPopupContract.locales[requestedLocale] = popupMetadata; await this.objectStorage.updateObject(popupKey, localizedPopupContract); } else if (!popupMetadata.contentKey) { const identifier = Utils.guid(); popupMetadata.contentKey = `${documentsPath}/${identifier}`; await this.objectStorage.updateObject(popupKey, popupMetadata); } content["key"] = popupMetadata.contentKey; await this.objectStorage.updateObject(popupMetadata.contentKey, content); } }