From 9db4ce1f9123f28b9bbfdcd9441d3a27968f2044 Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Wed, 21 Feb 2024 10:53:06 +0100 Subject: [PATCH] add UmbDocumentVariantManagerContext to handle picking variants --- .../document-variant-manager.context.ts | 113 ++++++++++++++++++ .../documents/global-contexts/index.ts | 1 + .../documents/global-contexts/manifests.ts | 10 ++ 3 files changed, 124 insertions(+) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/global-contexts/document-variant-manager.context.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/global-contexts/index.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/global-contexts/manifests.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/global-contexts/document-variant-manager.context.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/global-contexts/document-variant-manager.context.ts new file mode 100644 index 0000000000..ff6ec56942 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/global-contexts/document-variant-manager.context.ts @@ -0,0 +1,113 @@ +import { UmbDocumentVariantState, type UmbDocumentVariantModel } from '../types.js'; +import { UmbDocumentDetailRepository } from '../repository/detail/document-detail.repository.js'; +import { + UMB_DOCUMENT_LANGUAGE_PICKER_MODAL, + type UmbDocumentVariantPickerModalData, +} from '../modals/variant-picker/index.js'; +import { UmbDocumentPublishingRepository } from '../repository/publishing/index.js'; +import { UmbContextBase } from '@umbraco-cms/backoffice/class-api'; +import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import type { UmbApi } from '@umbraco-cms/backoffice/extension-api'; +import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; +import { UmbVariantId } from '@umbraco-cms/backoffice/variant'; + +export class UmbDocumentVariantManagerContext + extends UmbContextBase + implements UmbApi +{ + #publishingRepository = new UmbDocumentPublishingRepository(this); + #documentRepository = new UmbDocumentDetailRepository(this); + #modalManagerContext?: typeof UMB_MODAL_MANAGER_CONTEXT.TYPE; + + constructor(host: UmbControllerHost) { + super(host, UMB_DOCUMENT_VARIANT_MANAGER_CONTEXT); + + this.consumeContext(UMB_MODAL_MANAGER_CONTEXT, (instance) => { + this.#modalManagerContext = instance; + }); + } + + /** + * Helps the user pick variants for a specific operation. + * If there is only one variant, it will be selected automatically. + * If there are multiple variants, a modal will be shown to the user. + * @param type The type of operation to perform. + * @param documentUnique The unique identifier of the document. + * @param activeVariantCulture The culture of the active variant (will be pre-selected in the modal). + * @param filterFn Optional filter function to filter the available variants. + * @returns The selected variants to perform the operation on. + */ + async pickVariants( + availableVariants: Array, + type: UmbDocumentVariantPickerModalData['type'], + activeVariantCulture?: string, + ): Promise { + // If there is only one variant, we don't need to select anything. + if (availableVariants.length === 1) { + return [UmbVariantId.Create(availableVariants[0])]; + } + + if (!this.#modalManagerContext) throw new Error('Modal manager context is missing'); + + const modalData: UmbDocumentVariantPickerModalData = { + type, + variants: availableVariants, + }; + + const modalContext = this.#modalManagerContext.open(UMB_DOCUMENT_LANGUAGE_PICKER_MODAL, { + data: modalData, + value: { selection: activeVariantCulture ? [activeVariantCulture] : [] }, + }); + + const result = await modalContext.onSubmit().catch(() => undefined); + + if (!result?.selection.length) return []; + + const selectedVariants = result.selection.map((x) => x?.toLowerCase() ?? ''); + + // Match the result to the available variants. + const variantIds = availableVariants + .filter((x) => selectedVariants.includes(x.culture!)) + .map((x) => UmbVariantId.Create(x)); + + return variantIds; + } + + /** + * Publish the latest version of a document indescriminately. + * @param documentUnique The unique identifier of the document. + */ + async publish(documentUnique: string) { + const { data } = await this.#documentRepository.requestByUnique(documentUnique); + if (!data) throw new Error('Document not found'); + const variantIds = await this.pickVariants(data.variants, 'publish'); + if (variantIds.length) { + await this.#publishingRepository.publish(documentUnique, variantIds); + } + } + + /** + * Unpublish the latest version of a document indescriminately. + * @param documentUnique The unique identifier of the document. + */ + async unpublish(documentUnique: string) { + const { data } = await this.#documentRepository.requestByUnique(documentUnique); + if (!data) throw new Error('Document not found'); + + // Only show published variants + const variants = data.variants.filter((variant) => variant.state === UmbDocumentVariantState.PUBLISHED); + + const variantIds = await this.pickVariants(variants, 'unpublish'); + + if (variantIds.length) { + await this.#publishingRepository.unpublish(documentUnique, variantIds); + } + } +} + +export default UmbDocumentVariantManagerContext; + +export const UMB_DOCUMENT_VARIANT_MANAGER_CONTEXT = new UmbContextToken( + 'UmbDocumentVariantManagerContext', +); diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/global-contexts/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/global-contexts/index.ts new file mode 100644 index 0000000000..8eed586555 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/global-contexts/index.ts @@ -0,0 +1 @@ +export * from './document-variant-manager.context.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/global-contexts/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/global-contexts/manifests.ts new file mode 100644 index 0000000000..2b5b972ebb --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/global-contexts/manifests.ts @@ -0,0 +1,10 @@ +import type { ManifestGlobalContext } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'globalContext', + alias: 'Umb.GlobalContext.DocumentVariantManager', + name: 'Document Variant Manager Context', + js: () => import('./document-variant-manager.context.js'), + }, +];