diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/property-dataset-context/document-property-dataset.context.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/property-dataset-context/document-property-dataset.context.ts index 5b34ca61e1cd..52f782f3a64e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/property-dataset-context/document-property-dataset.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/property-dataset-context/document-property-dataset.context.ts @@ -1,9 +1,71 @@ -import type { UmbDocumentDetailModel, UmbDocumentVariantModel } from '../types.js'; +import type { UmbDocumentDetailModel, UmbDocumentVariantModel, UmbDocumentWorkspaceContext } from '../types.js'; +import { UMB_DOCUMENT_CONFIGURATION_CONTEXT } from '../global-contexts/index.js'; import { UmbContentPropertyDatasetContext } from '@umbraco-cms/backoffice/content'; import type { UmbDocumentTypeDetailModel } from '@umbraco-cms/backoffice/document-type'; +import type { UmbVariantId } from '@umbraco-cms/backoffice/variant'; +import type { DocumentConfigurationResponseModel } from '@umbraco-cms/backoffice/external/backend-api'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import { observeMultiple } from '@umbraco-cms/backoffice/observable-api'; +import type { UmbVariantPropertyGuardRule } from '@umbraco-cms/backoffice/property'; export class UmbDocumentPropertyDatasetContext extends UmbContentPropertyDatasetContext< UmbDocumentDetailModel, UmbDocumentTypeDetailModel, UmbDocumentVariantModel -> {} +> { + #dataSetVariantId?: UmbVariantId; + #documentConfiguration?: DocumentConfigurationResponseModel; + #allowEditInvariantFromNonDefault: boolean | undefined = undefined; + + constructor(host: UmbControllerHost, dataOwner: UmbDocumentWorkspaceContext, variantId?: UmbVariantId) { + super(host, dataOwner, variantId); + + this.#dataSetVariantId = variantId; + + this.consumeContext(UMB_DOCUMENT_CONFIGURATION_CONTEXT, async (context) => { + if (!context) return; + this.#documentConfiguration = (await context?.getDocumentConfiguration()) ?? undefined; + this.#allowEditInvariantFromNonDefault = this.#documentConfiguration?.allowEditInvariantFromNonDefault; + if (this.#allowEditInvariantFromNonDefault === false) { + this.#preventEditInvariantFromNonDefault(); + } + }); + } + + #preventEditInvariantFromNonDefault() { + this.observe( + observeMultiple([this._dataOwner.structure.contentTypeProperties, this._dataOwner.variantOptions]), + ([properties, variantOptions]) => { + if (properties.length === 0) return; + if (variantOptions.length === 0) return; + + const currentVariantOption = variantOptions.find( + (option) => option.culture === this.#dataSetVariantId?.culture, + ); + + const isDefaultLanguage = currentVariantOption?.language.isDefault; + + properties.forEach((property) => { + const unique = 'UMB_PREVENT_EDIT_INVARIANT_FROM_NON_DEFAULT_' + property.unique; + + // Clean up the rule if it exists before adding a new one + this._dataOwner.propertyWriteGuard.removeRule(unique); + + // If the property is invariant and not in the default language, we need to add a rule + if (!property.variesByCulture && !isDefaultLanguage) { + const rule: UmbVariantPropertyGuardRule = { + unique, + message: 'Shared properties can only be edited in the default language', + propertyType: { + unique: property.unique, + }, + permitted: false, + }; + + this._dataOwner.propertyWriteGuard.addRule(rule); + } + }); + }, + ); + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace.context.ts index b6b0e49287a8..74034de7aa35 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace.context.ts @@ -37,8 +37,6 @@ import type { UmbDocumentTypeDetailModel } from '@umbraco-cms/backoffice/documen import { UmbIsTrashedEntityContext } from '@umbraco-cms/backoffice/recycle-bin'; import { ensurePathEndsWithSlash, UmbDeprecation } from '@umbraco-cms/backoffice/utils'; import { createExtensionApiByAlias } from '@umbraco-cms/backoffice/extension-registry'; -import { observeMultiple } from '@umbraco-cms/backoffice/observable-api'; -import { UMB_LANGUAGE_USER_PERMISSION_CONDITION_ALIAS } from '@umbraco-cms/backoffice/language'; import { UMB_SERVER_CONTEXT } from '@umbraco-cms/backoffice/server'; type ContentModel = UmbDocumentDetailModel; @@ -104,14 +102,6 @@ export class UmbDocumentWorkspaceContext }; }); - this.consumeContext(UMB_DOCUMENT_CONFIGURATION_CONTEXT, async (context) => { - const documentConfiguration = (await context?.getDocumentConfiguration()) ?? undefined; - - if (documentConfiguration?.allowEditInvariantFromNonDefault !== true) { - this.#preventEditInvariantFromNonDefault(); - } - }); - this.observe( this.contentTypeUnique, (unique) => { @@ -226,46 +216,6 @@ export class UmbDocumentWorkspaceContext ]); } - #preventEditInvariantFromNonDefault() { - this.observe( - observeMultiple([this.structure.contentTypeProperties, this.languages]), - ([properties, languages]) => { - if (properties.length === 0) return; - if (languages.length === 0) return; - - const defaultLanguageUnique = languages.find((x) => x.isDefault)?.unique; - const ruleUnique = 'UMB_preventEditInvariantFromNonDefault'; - - const rule = { - unique: ruleUnique, - permitted: false, - message: 'Shared properties can only be edited in the default language', - variantId: UmbVariantId.CreateInvariant(), - }; - - /* The permission is false by default, and the onChange callback will not be triggered if the permission hasn't changed. - Therefore, we add the rule to the readOnlyGuard here. */ - this.propertyWriteGuard.addRule(rule); - - createExtensionApiByAlias(this, UMB_LANGUAGE_USER_PERMISSION_CONDITION_ALIAS, [ - { - config: { - allOf: [defaultLanguageUnique], - }, - onChange: (permitted: boolean) => { - if (permitted) { - this.propertyWriteGuard.removeRule(ruleUnique); - } else { - this.propertyWriteGuard.addRule(rule); - } - }, - }, - ]); - }, - 'observePreventEditInvariantFromNonDefault', - ); - } - override resetState(): void { super.resetState(); this.#isTrashedContext.setIsTrashed(false);