From 5864db704287d4e8d8863f3955a174e502a14b87 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 11 Mar 2025 13:54:34 +0100 Subject: [PATCH 001/106] add property visibility state manager --- .../src/packages/core/property/index.ts | 1 + .../core/property/property-visibility-state.manager.ts | 7 +++++++ 2 files changed, 8 insertions(+) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/property/property-visibility-state.manager.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property/index.ts index e5d236cee9be..f47426e531c4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/property/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property/index.ts @@ -3,4 +3,5 @@ export * from './conditions/index.js'; export * from './property-dataset/index.js'; export * from './property-value-cloner/property-value-clone.controller.js'; export * from './property-value-preset/index.js'; +export * from './property-visibility-state.manager.js'; export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property/property-visibility-state.manager.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property/property-visibility-state.manager.ts new file mode 100644 index 000000000000..0968a3e20a00 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property/property-visibility-state.manager.ts @@ -0,0 +1,7 @@ +import { UmbStateManager, type UmbState } from '@umbraco-cms/backoffice/utils'; + +export interface UmbPropertyVisibilityState extends UmbState { + propertyAlias: string; +} + +export class UmbPropertyVisibilityStateManager extends UmbStateManager {} From 65b4571ee48ed2b0e1dc8eebcaa759a46af577b9 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 11 Mar 2025 13:54:51 +0100 Subject: [PATCH 002/106] implement in structure manager --- .../structure/content-type-structure-manager.class.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/structure/content-type-structure-manager.class.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/structure/content-type-structure-manager.class.ts index fee663e92577..d1ef5dceed6f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/structure/content-type-structure-manager.class.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/structure/content-type-structure-manager.class.ts @@ -19,6 +19,7 @@ import { incrementString } from '@umbraco-cms/backoffice/utils'; import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; import { UmbExtensionApiInitializer } from '@umbraco-cms/backoffice/extension-api'; import { umbExtensionsRegistry, type ManifestRepository } from '@umbraco-cms/backoffice/extension-registry'; +import { UmbPropertyVisibilityStateManager } from '@umbraco-cms/backoffice/property'; type UmbPropertyTypeId = UmbPropertyTypeModel['id']; @@ -98,6 +99,8 @@ export class UmbContentTypeStructureManager< readonly variesByCulture = createObservablePart(this.ownerContentType, (x) => x?.variesByCulture); readonly variesBySegment = createObservablePart(this.ownerContentType, (x) => x?.variesBySegment); + public readonly propertyVisibilityState = new UmbPropertyVisibilityStateManager(this); + #containers: UmbArrayState = new UmbArrayState( [], (x) => x.id, From cef5981b7f8a33826949454d71a149b9ca812bf3 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 11 Mar 2025 13:55:04 +0100 Subject: [PATCH 003/106] filter properties based on visibility --- .../edit/content-editor-properties.element.ts | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/content-editor-properties.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/content-editor-properties.element.ts index 139982020193..260f2c7442fa 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/content-editor-properties.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/content-editor-properties.element.ts @@ -31,6 +31,12 @@ export class UmbContentWorkspaceViewEditPropertiesElement extends UmbLitElement @state() _dataPaths?: Array; + @state() + _visiblePropertyAliases: Array = []; + + @state() + _visibleProperties: Array = []; + constructor() { super(); @@ -39,11 +45,17 @@ export class UmbContentWorkspaceViewEditPropertiesElement extends UmbLitElement // Assuming its the same content model type that we are working with here... [NL] workspaceContext.structure as unknown as UmbContentTypeStructureManager, ); + + this.observe(workspaceContext.structure.propertyVisibilityState.states, (states) => { + this._visiblePropertyAliases = states.map((state) => state.propertyAlias) ?? []; + }); }); + this.consumeContext(UMB_PROPERTY_DATASET_CONTEXT, (datasetContext) => { this.#variantId = datasetContext.getVariantId(); this.#generatePropertyDataPath(); }); + this.observe( this.#propertyStructureHelper.propertyStructure, (propertyStructure) => { @@ -66,10 +78,14 @@ export class UmbContentWorkspaceViewEditPropertiesElement extends UmbLitElement ); } + #getVisibleProperties() { + return this._propertyStructure?.filter((property) => this._visiblePropertyAliases.includes(property.alias)) ?? []; + } + override render() { return this._propertyStructure && this._dataPaths ? repeat( - this._propertyStructure, + this.#getVisibleProperties(), (property) => property.alias, (property, index) => html` Date: Tue, 11 Mar 2025 14:57:03 +0100 Subject: [PATCH 004/106] wip document type structure permissions --- .../documents/document-types/manifests.ts | 2 + .../document-types/structure/manifests.ts | 4 + ...ucture-granular-user-permission.element.ts | 240 ++++++++++++++++++ .../structure/permission/manifests.ts | 18 ++ .../structure/permission/types.ts | 12 + 5 files changed, 276 insertions(+) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/manifests.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/permission/input-document-type-structure-granular-user-permission/input-document-type-structure-granular-user-permission.element.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/permission/manifests.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/permission/types.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/manifests.ts index 3562f9d6a7c9..8198e4695f3a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/manifests.ts @@ -3,6 +3,7 @@ import { manifests as menuManifests } from './menu/manifests.js'; import { manifests as propertyEditorManifests } from './property-editors/manifests.js'; import { manifests as repositoryManifests } from './repository/manifests.js'; import { manifests as searchManifests } from './search/manifests.js'; +import { manifests as structureManifests } from './structure/manifests.js'; import { manifests as treeManifests } from './tree/manifests.js'; import { manifests as workspaceManifests } from './workspace/manifests.js'; import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; @@ -13,6 +14,7 @@ export const manifests: Array = ...propertyEditorManifests, ...repositoryManifests, ...searchManifests, + ...structureManifests, ...treeManifests, ...workspaceManifests, ]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/manifests.ts new file mode 100644 index 000000000000..4f57a2f3f192 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/manifests.ts @@ -0,0 +1,4 @@ +import { manifests as permissionManifests } from './permission/manifests.js'; +import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [...permissionManifests]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/permission/input-document-type-structure-granular-user-permission/input-document-type-structure-granular-user-permission.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/permission/input-document-type-structure-granular-user-permission/input-document-type-structure-granular-user-permission.element.ts new file mode 100644 index 000000000000..ce66987564cc --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/permission/input-document-type-structure-granular-user-permission/input-document-type-structure-granular-user-permission.element.ts @@ -0,0 +1,240 @@ +import type { UmbDocumentTypeStructureUserPermissionModel } from '../types.js'; +import { UmbDocumentTypeItemRepository } from '../../../repository/item/index.js'; +import type { UmbDocumentTypeItemModel } from '../../../repository/item/types.js'; +import type { UmbDocumentTypeTreeItemModel } from '../../../tree/types.js'; +import { UMB_DOCUMENT_TYPE_PICKER_MODAL } from '../../../modals/index.js'; +import { css, customElement, html, repeat, state } from '@umbraco-cms/backoffice/external/lit'; +import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; +import type { UmbModalManagerContext } from '@umbraco-cms/backoffice/modal'; +import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; +import type { UmbDeselectedEvent } from '@umbraco-cms/backoffice/event'; +import { UmbChangeEvent, UmbSelectedEvent } from '@umbraco-cms/backoffice/event'; +import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; +import { UUIFormControlMixin } from '@umbraco-cms/backoffice/external/uui'; +import { + UMB_ENTITY_USER_PERMISSION_MODAL, + type ManifestEntityUserPermission, +} from '@umbraco-cms/backoffice/user-permission'; + +@customElement('umb-content-type-structure-document-granular-user-permission') +export class UmbInputDocumentTypeStructureGranularUserPermissionElement extends UUIFormControlMixin(UmbLitElement, '') { + _permissions: Array = []; + public get permissions(): Array { + return this._permissions; + } + public set permissions(value: Array) { + this._permissions = value; + const uniques = value.map((item) => item.documentType.unique); + this.#observePickedDocumentTypes(uniques); + } + + @state() + private _items?: Array; + + #documentTypeItemRepository = new UmbDocumentTypeItemRepository(this); + #modalManagerContext?: UmbModalManagerContext; + #documentTypePickerModalContext?: any; + #entityUserPermissionModalContext?: any; + + constructor() { + super(); + + this.consumeContext(UMB_MODAL_MANAGER_CONTEXT, (instance) => (this.#modalManagerContext = instance)); + } + + protected override getFormElement() { + return undefined; + } + + async #observePickedDocumentTypes(uniques: Array) { + const { asObservable } = await this.#documentTypeItemRepository.requestItems(uniques); + this.observe(asObservable(), (items) => (this._items = items)); + } + + /* + async #editGranularPermission(item: UmbDocumentTypeItemModel) { + const currentPermissionVerbs = this.#getPermissionForDocumentType(item.unique)?.verbs ?? []; + const result = await this.#selectEntityUserPermissionsForDocumentType(item, currentPermissionVerbs); + // don't do anything if the verbs have not been updated + if (JSON.stringify(result) === JSON.stringify(currentPermissionVerbs)) return; + + // update permission with new verbs + this.permissions = this._permissions.map((permission) => { + if (permission.documentType.unique === item.unique) { + return { + ...permission, + verbs: result, + }; + } + return permission; + }); + + this.dispatchEvent(new UmbChangeEvent()); + } + */ + + async #addGranularPermission() { + this.#documentTypePickerModalContext = this.#modalManagerContext?.open(this, UMB_DOCUMENT_TYPE_PICKER_MODAL, { + data: { + hideTreeRoot: true, + // prevent already selected items to be picked again + pickableFilter: (treeItem: UmbDocumentTypeTreeItemModel) => + !this._items?.map((i) => i.unique).includes(treeItem.unique), + }, + }); + + this.#documentTypePickerModalContext?.addEventListener(UmbSelectedEvent.TYPE, async (event: UmbDeselectedEvent) => { + const selectedEvent = event as UmbSelectedEvent; + const unique = selectedEvent.unique; + if (!unique) return; + + const documentTypeItem = await this.#requestDocumentTypeItem(unique); + + this.#selectEntityUserPermissionsForDocumentType(documentTypeItem).then( + (result) => { + this.#documentTypePickerModalContext?.reject(); + + const permissionItem: UmbDocumentTypeStructureUserPermissionModel = { + $type: 'DocumentTypeStructurePermissionPresentationModel', + documentType: { unique }, + verbs: result, + }; + + this.permissions = [...this._permissions, permissionItem]; + this.dispatchEvent(new UmbChangeEvent()); + }, + () => { + this.#documentTypePickerModalContext?.reject(); + }, + ); + }); + } + + async #requestDocumentTypeItem(unique: string) { + if (!unique) throw new Error('Could not open permissions modal, no unique was provided'); + + const { data } = await this.#documentTypeItemRepository.requestItems([unique]); + + const documentItem = data?.[0]; + if (!documentItem) throw new Error('No document item found'); + return documentItem; + } + + async #selectEntityUserPermissionsForDocumentType(item: UmbDocumentTypeItemModel, allowedVerbs: Array = []) { + // TODO: get correct variant name + const name = item.name; + const headline = name ? `Permissions for ${name}` : 'Permissions'; + + this.#entityUserPermissionModalContext = this.#modalManagerContext?.open(this, UMB_ENTITY_USER_PERMISSION_MODAL, { + data: { + unique: item.unique, + entityType: item.entityType, + headline, + }, + value: { + allowedVerbs, + }, + }); + + try { + const value = await this.#entityUserPermissionModalContext?.onSubmit(); + return value?.allowedVerbs; + } catch { + throw new Error(); + } + } + + #removeGranularPermission(item: UmbDocumentTypeItemModel) { + const permission = this.#getPermissionForDocumentType(item.unique); + if (!permission) return; + + this.permissions = this._permissions.filter((v) => JSON.stringify(v) !== JSON.stringify(permission)); + this.dispatchEvent(new UmbChangeEvent()); + } + + override render() { + return html`${this.#renderItems()} ${this.#renderAddButton()}`; + } + + #renderItems() { + if (!this._items) return; + return html` + + ${repeat( + this._items, + (item) => item.unique, + (item) => this.#renderRef(item), + )} + + `; + } + + #renderAddButton() { + return html``; + } + + #renderRef(item: UmbDocumentTypeItemModel) { + if (!item.unique) return; + const name = item.name; + const permissionNames = this.#getPermissionNamesForDocumentType(item.unique); + + return html` + + ${this.#renderIcon(item)} + ${this.#renderRemoveButton(item)} + + `; + } + + #renderIcon(item: UmbDocumentTypeItemModel) { + if (!item.icon) return; + return html``; + } + + #renderRemoveButton(item: UmbDocumentTypeItemModel) { + return html` this.#removeGranularPermission(item)} + label=${this.localize.term('general_remove')}>`; + } + + #getPermissionForDocumentType(unique: string) { + return this._permissions?.find((permission) => permission.documentType.unique === unique); + } + + #getPermissionNamesForDocumentType(unique: string) { + const permission = this.#getPermissionForDocumentType(unique); + if (!permission) return; + + return umbExtensionsRegistry + .getAllExtensions() + .filter((manifest) => manifest.type === 'entityUserPermission') + .filter((manifest) => + (manifest as ManifestEntityUserPermission).meta.verbs.every((verb) => permission.verbs.includes(verb)), + ) + .map((m) => { + const manifest = m as ManifestEntityUserPermission; + return manifest.meta.label ? this.localize.string(manifest.meta.label) : manifest.name; + }) + .join(', '); + } + + static override styles = [ + css` + #btn-add { + width: 100%; + } + `, + ]; +} + +export { UmbInputDocumentTypeStructureGranularUserPermissionElement as element }; + +declare global { + interface HTMLElementTagNameMap { + 'umb-document-type-structure-granular-user-permission': UmbInputDocumentTypeStructureGranularUserPermissionElement; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/permission/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/permission/manifests.ts new file mode 100644 index 000000000000..0ea5009c7549 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/permission/manifests.ts @@ -0,0 +1,18 @@ +import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'userGranularPermission', + alias: 'Umb.UserGranularPermission.ContentType.Structure', + name: 'Content Type Structure Granular User Permission', + element: () => + import( + './input-document-type-structure-granular-user-permission/input-document-type-structure-granular-user-permission.element.js' + ), + meta: { + schemaType: 'DocumentTypeStructurePermissionPresentationModel', + label: 'Document Type Structure', + description: 'Assign Permissions to Document Type structures', + }, + }, +]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/permission/types.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/permission/types.ts new file mode 100644 index 000000000000..2c3d9b9c6807 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/permission/types.ts @@ -0,0 +1,12 @@ +import type { UmbUserPermissionModel } from '@umbraco-cms/backoffice/user-permission'; + +export interface UmbReferencedByAlias { + alias: string; +} + +export interface UmbDocumentTypeStructureUserPermissionModel extends UmbUserPermissionModel { + documentType: { + unique: string; + }; + properties: Array; +} From b94625567fb2e173d39414c06c5c0fad13d8d45f Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 11 Mar 2025 14:58:15 +0100 Subject: [PATCH 005/106] rename --- ...ut-document-type-structure-granular-user-permission.element.ts | 0 .../structure/{permission => user-permission}/manifests.ts | 0 .../structure/{permission => user-permission}/types.ts | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/{permission => user-permission}/input-document-type-structure-granular-user-permission/input-document-type-structure-granular-user-permission.element.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/{permission => user-permission}/manifests.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/{permission => user-permission}/types.ts (100%) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/permission/input-document-type-structure-granular-user-permission/input-document-type-structure-granular-user-permission.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/user-permission/input-document-type-structure-granular-user-permission/input-document-type-structure-granular-user-permission.element.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/permission/input-document-type-structure-granular-user-permission/input-document-type-structure-granular-user-permission.element.ts rename to src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/user-permission/input-document-type-structure-granular-user-permission/input-document-type-structure-granular-user-permission.element.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/permission/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/user-permission/manifests.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/permission/manifests.ts rename to src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/user-permission/manifests.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/permission/types.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/user-permission/types.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/permission/types.ts rename to src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/user-permission/types.ts From ceb3564c7cc806754d2596624781f4476fc973f1 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 11 Mar 2025 15:21:29 +0100 Subject: [PATCH 006/106] register entity permission for document type property --- .../documents/document-types/structure/manifests.ts | 2 +- .../structure/user-permission/constants.ts | 1 + .../structure/user-permission/manifests.ts | 12 ++++++++++++ 3 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/user-permission/constants.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/manifests.ts index 4f57a2f3f192..75df1047993e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/manifests.ts @@ -1,4 +1,4 @@ -import { manifests as permissionManifests } from './permission/manifests.js'; +import { manifests as permissionManifests } from './user-permission/manifests.js'; import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; export const manifests: Array = [...permissionManifests]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/user-permission/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/user-permission/constants.ts new file mode 100644 index 000000000000..d0d695ec43b8 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/user-permission/constants.ts @@ -0,0 +1 @@ +export const UMB_USER_PERMISSION_DOCUMENT_TYPE_STRUCTURE_PROPERTY_SEE = 'Umb.DocumentType.Structure.Property.See'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/user-permission/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/user-permission/manifests.ts index 0ea5009c7549..60bf252dabad 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/user-permission/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/user-permission/manifests.ts @@ -1,6 +1,18 @@ +import { UMB_USER_PERMISSION_DOCUMENT_TYPE_STRUCTURE_PROPERTY_SEE } from './constants.js'; import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; export const manifests: Array = [ + { + type: 'entityUserPermission', + alias: 'Umb.EntityUserPermission.DocumentType.Structure.Property.See', + name: 'See Document Type Structure Property User Permission', + forEntityTypes: ['document-type-property'], + meta: { + verbs: [UMB_USER_PERMISSION_DOCUMENT_TYPE_STRUCTURE_PROPERTY_SEE], + label: 'See', + description: 'See Document Type Property when editing documents', + }, + }, { type: 'userGranularPermission', alias: 'Umb.UserGranularPermission.ContentType.Structure', From 5281ded9fed22f380c583ed6ec395106bc7804a5 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 11 Mar 2025 15:33:31 +0100 Subject: [PATCH 007/106] add entity permission for media type property --- .../structure/user-permission/manifests.ts | 3 ++- .../src/packages/media/media-types/manifests.ts | 11 +++++++---- .../media/media-types/structure/manifests.ts | 4 ++++ .../structure/user-permission/constants.ts | 1 + .../structure/user-permission/manifests.ts | 17 +++++++++++++++++ .../structure/user-permission/types.ts | 12 ++++++++++++ 6 files changed, 43 insertions(+), 5 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/media/media-types/structure/manifests.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/media/media-types/structure/user-permission/constants.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/media/media-types/structure/user-permission/manifests.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/media/media-types/structure/user-permission/types.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/user-permission/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/user-permission/manifests.ts index 60bf252dabad..cf4de120b199 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/user-permission/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/user-permission/manifests.ts @@ -7,10 +7,11 @@ export const manifests: Array = alias: 'Umb.EntityUserPermission.DocumentType.Structure.Property.See', name: 'See Document Type Structure Property User Permission', forEntityTypes: ['document-type-property'], + weight: 200, meta: { verbs: [UMB_USER_PERMISSION_DOCUMENT_TYPE_STRUCTURE_PROPERTY_SEE], label: 'See', - description: 'See Document Type Property when editing documents', + description: 'See Document Type Property', }, }, { diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/manifests.ts index 49a80defb64c..78e3466724c7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/manifests.ts @@ -1,18 +1,21 @@ import { manifests as entityActionsManifests } from './entity-actions/manifests.js'; import { manifests as menuManifests } from './menu/manifests.js'; +import { manifests as propertyEditorUiManifests } from './property-editors/manifests.js'; import { manifests as repositoryManifests } from './repository/manifests.js'; +import { manifests as searchManifests } from './search/manifests.js'; +import { manifests as structureManifests } from './structure/manifests.js'; import { manifests as treeManifests } from './tree/manifests.js'; import { manifests as workspaceManifests } from './workspace/manifests.js'; -import { manifests as propertyEditorUiManifests } from './property-editors/manifests.js'; -import { manifests as searchManifests } from './search/manifests.js'; + import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; export const manifests: Array = [ ...entityActionsManifests, ...menuManifests, + ...propertyEditorUiManifests, ...repositoryManifests, + ...searchManifests, + ...structureManifests, ...treeManifests, ...workspaceManifests, - ...propertyEditorUiManifests, - ...searchManifests, ]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/structure/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/structure/manifests.ts new file mode 100644 index 000000000000..75df1047993e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/structure/manifests.ts @@ -0,0 +1,4 @@ +import { manifests as permissionManifests } from './user-permission/manifests.js'; +import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [...permissionManifests]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/structure/user-permission/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/structure/user-permission/constants.ts new file mode 100644 index 000000000000..5d19d2ab6774 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/structure/user-permission/constants.ts @@ -0,0 +1 @@ +export const UMB_USER_PERMISSION_MEDIA_TYPE_STRUCTURE_PROPERTY_SEE = 'Umb.MediaType.Structure.Property.See'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/structure/user-permission/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/structure/user-permission/manifests.ts new file mode 100644 index 000000000000..dba73d979340 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/structure/user-permission/manifests.ts @@ -0,0 +1,17 @@ +import { UMB_USER_PERMISSION_MEDIA_TYPE_STRUCTURE_PROPERTY_SEE } from './constants.js'; +import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'entityUserPermission', + alias: 'Umb.EntityUserPermission.MediaType.Structure.Property.See', + name: 'See Media Type Structure Property User Permission', + forEntityTypes: ['media-type-property'], + weight: 100, + meta: { + verbs: [UMB_USER_PERMISSION_MEDIA_TYPE_STRUCTURE_PROPERTY_SEE], + label: 'See', + description: 'See Media Type Property', + }, + }, +]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/structure/user-permission/types.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/structure/user-permission/types.ts new file mode 100644 index 000000000000..bab52d3bd0df --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/structure/user-permission/types.ts @@ -0,0 +1,12 @@ +import type { UmbUserPermissionModel } from '@umbraco-cms/backoffice/user-permission'; + +export interface UmbReferencedByAlias { + alias: string; +} + +export interface UmbMediaTypeStructureUserPermissionModel extends UmbUserPermissionModel { + mediaType: { + unique: string; + }; + properties: Array; +} From b68c7a0c5524db460cf1db9451c1ee84ea11dd2f Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 11 Mar 2025 20:43:02 +0100 Subject: [PATCH 008/106] pass fallback permissions to document granular permissions --- ...cument-granular-user-permission.element.ts | 33 +++++++++++++++---- ...-group-granular-permission-list.element.ts | 5 +++ 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/input-document-granular-user-permission/input-document-granular-user-permission.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/input-document-granular-user-permission/input-document-granular-user-permission.element.ts index 512fc7af2a04..15609d2eaff4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/input-document-granular-user-permission/input-document-granular-user-permission.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/input-document-granular-user-permission/input-document-granular-user-permission.element.ts @@ -2,7 +2,7 @@ import type { UmbDocumentUserPermissionModel } from '../types.js'; import { UmbDocumentItemRepository } from '../../item/index.js'; import type { UmbDocumentItemModel } from '../../item/types.js'; import { UMB_DOCUMENT_PICKER_MODAL } from '../../constants.js'; -import { css, customElement, html, repeat, state } from '@umbraco-cms/backoffice/external/lit'; +import { css, customElement, html, property, repeat, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import type { UmbModalManagerContext } from '@umbraco-cms/backoffice/modal'; import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; @@ -27,6 +27,9 @@ export class UmbInputDocumentGranularUserPermissionElement extends UUIFormContro this.#observePickedDocuments(uniques); } + @property({ type: Array, attribute: false }) + fallbackPermissions: Array = []; + @state() private _items?: Array; @@ -118,10 +121,17 @@ export class UmbInputDocumentGranularUserPermissionElement extends UUIFormContro return documentItem; } - async #selectEntityUserPermissionsForDocument(item: UmbDocumentItemModel, allowedVerbs: Array = []) { + async #selectEntityUserPermissionsForDocument(item: UmbDocumentItemModel, allowedVerbs?: Array) { // TODO: get correct variant name const name = item.variants[0]?.name; const headline = name ? `Permissions for ${name}` : 'Permissions'; + const fallbackVerbs = this.#getFallbackPermissionVerbsForEntityType(item.entityType).flatMap( + (permission) => permission.meta.verbs, + ); + + const uniqueFallbackVerbs = [...new Set([...fallbackVerbs])]; + + const value = allowedVerbs || uniqueFallbackVerbs; this.#entityUserPermissionModalContext = this.#modalManagerContext?.open(this, UMB_ENTITY_USER_PERMISSION_MODAL, { data: { @@ -130,7 +140,7 @@ export class UmbInputDocumentGranularUserPermissionElement extends UUIFormContro headline, }, value: { - allowedVerbs, + allowedVerbs: value, }, }); @@ -224,10 +234,8 @@ export class UmbInputDocumentGranularUserPermissionElement extends UUIFormContro if (!permission) return; return umbExtensionsRegistry - .getAllExtensions() - .filter((manifest) => manifest.type === 'entityUserPermission') - .filter((manifest) => - (manifest as ManifestEntityUserPermission).meta.verbs.every((verb) => permission.verbs.includes(verb)), + .getByTypeAndFilter('entityUserPermission', (manifest) => + manifest.meta.verbs.every((verb) => permission.verbs.includes(verb)), ) .map((m) => { const manifest = m as ManifestEntityUserPermission; @@ -236,6 +244,17 @@ export class UmbInputDocumentGranularUserPermissionElement extends UUIFormContro .join(', '); } + #getFallbackPermissionVerbsForEntityType(entityType: string) { + // get all permissions that are allowed for the entity type and have at least one of the fallback permissions + // this is used to determine the default permissions for a document + return umbExtensionsRegistry.getByTypeAndFilter( + 'entityUserPermission', + (manifest) => + manifest.forEntityTypes.includes(entityType) && + this.fallbackPermissions.map((verb) => manifest.meta.verbs.includes(verb)).includes(true), + ); + } + static override styles = [ css` #btn-add { diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user-group/workspace/user-group/components/user-group-granular-permission-list.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user-group/workspace/user-group/components/user-group-granular-permission-list.element.ts index d830d2b74868..0ca6b1926e29 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user-group/workspace/user-group/components/user-group-granular-permission-list.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user-group/workspace/user-group/components/user-group-granular-permission-list.element.ts @@ -11,6 +11,9 @@ export class UmbUserGroupGranularPermissionListElement extends UmbLitElement { @state() _userGroupPermissions?: Array; + @state() + _userGroupFallbackPermissions?: Array; + #workspaceContext?: typeof UMB_USER_GROUP_WORKSPACE_CONTEXT.TYPE; constructor() { @@ -23,6 +26,7 @@ export class UmbUserGroupGranularPermissionListElement extends UmbLitElement { this.#workspaceContext.data, (userGroup) => { this._userGroupPermissions = userGroup?.permissions; + this._userGroupFallbackPermissions = userGroup?.fallbackPermissions; }, 'umbUserGroupGranularPermissionObserver', ); @@ -75,6 +79,7 @@ export class UmbUserGroupGranularPermissionListElement extends UmbLitElement { this._userGroupPermissions.filter((permission) => permission.$type === schemaType) || []; (extension.component as any).permissions = permissionsForSchemaType; + (extension.component as any).fallbackPermissions = this._userGroupFallbackPermissions; extension.component.addEventListener(UmbChangeEvent.TYPE, this.#onValueChange); return html` From f5a4947c443d3e2eaa52b127b1cb9a4d320d2a2d Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 12 Mar 2025 09:52:16 +0100 Subject: [PATCH 009/106] set as preset --- ...nput-document-granular-user-permission.element.ts | 9 +++++---- .../entity-user-permission-settings-modal.element.ts | 12 ++++++++++++ .../entity-user-permission-settings-modal.token.ts | 1 + 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/input-document-granular-user-permission/input-document-granular-user-permission.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/input-document-granular-user-permission/input-document-granular-user-permission.element.ts index 15609d2eaff4..82172d23ba08 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/input-document-granular-user-permission/input-document-granular-user-permission.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/input-document-granular-user-permission/input-document-granular-user-permission.element.ts @@ -121,7 +121,7 @@ export class UmbInputDocumentGranularUserPermissionElement extends UUIFormContro return documentItem; } - async #selectEntityUserPermissionsForDocument(item: UmbDocumentItemModel, allowedVerbs?: Array) { + async #selectEntityUserPermissionsForDocument(item: UmbDocumentItemModel, allowedVerbs: Array = []) { // TODO: get correct variant name const name = item.variants[0]?.name; const headline = name ? `Permissions for ${name}` : 'Permissions'; @@ -131,16 +131,17 @@ export class UmbInputDocumentGranularUserPermissionElement extends UUIFormContro const uniqueFallbackVerbs = [...new Set([...fallbackVerbs])]; - const value = allowedVerbs || uniqueFallbackVerbs; - this.#entityUserPermissionModalContext = this.#modalManagerContext?.open(this, UMB_ENTITY_USER_PERMISSION_MODAL, { data: { unique: item.unique, entityType: item.entityType, headline, + preset: { + allowedVerbs: uniqueFallbackVerbs, + }, }, value: { - allowedVerbs: value, + allowedVerbs: allowedVerbs, }, }); diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user-permission/modals/settings/entity-user-permission-settings-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user-permission/modals/settings/entity-user-permission-settings-modal.element.ts index b09adc176a2a..a01df5aab180 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user-permission/modals/settings/entity-user-permission-settings-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user-permission/modals/settings/entity-user-permission-settings-modal.element.ts @@ -16,6 +16,7 @@ export class UmbEntityUserPermissionSettingsModalElement extends UmbModalBaseEle super.data = data; this._entityType = data?.entityType; this._headline = data?.headline ?? this._headline; + this._preset = data?.preset; } @state() @@ -24,6 +25,17 @@ export class UmbEntityUserPermissionSettingsModalElement extends UmbModalBaseEle @state() _entityType?: string; + @state() + _preset?: UmbEntityUserPermissionSettingsModalValue; + + override connectedCallback(): void { + super.connectedCallback(); + + if (this._preset?.allowedVerbs) { + this.updateValue({ allowedVerbs: this._preset?.allowedVerbs }); + } + } + #onPermissionChange(event: UmbSelectionChangeEvent) { const target = event.target as any; this.updateValue({ allowedVerbs: target.allowedVerbs }); diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user-permission/modals/settings/entity-user-permission-settings-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user-permission/modals/settings/entity-user-permission-settings-modal.token.ts index a63dc036d284..88ceb2d8fd86 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user-permission/modals/settings/entity-user-permission-settings-modal.token.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user-permission/modals/settings/entity-user-permission-settings-modal.token.ts @@ -4,6 +4,7 @@ export interface UmbEntityUserPermissionSettingsModalData { unique: string; entityType: string; headline?: string; + preset?: UmbEntityUserPermissionSettingsModalValue; } export type UmbEntityUserPermissionSettingsModalValue = { From 715a785f4536e1ac18be2d46cb7421b2d5742ea2 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 12 Mar 2025 10:06:32 +0100 Subject: [PATCH 010/106] clean up --- ...cument-granular-user-permission.element.ts | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/input-document-granular-user-permission/input-document-granular-user-permission.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/input-document-granular-user-permission/input-document-granular-user-permission.element.ts index 82172d23ba08..e66458cd5c3a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/input-document-granular-user-permission/input-document-granular-user-permission.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/input-document-granular-user-permission/input-document-granular-user-permission.element.ts @@ -125,19 +125,14 @@ export class UmbInputDocumentGranularUserPermissionElement extends UUIFormContro // TODO: get correct variant name const name = item.variants[0]?.name; const headline = name ? `Permissions for ${name}` : 'Permissions'; - const fallbackVerbs = this.#getFallbackPermissionVerbsForEntityType(item.entityType).flatMap( - (permission) => permission.meta.verbs, - ); - - const uniqueFallbackVerbs = [...new Set([...fallbackVerbs])]; - + const fallbackVerbs = this.#getFallbackPermissionVerbsForEntityType(item.entityType); this.#entityUserPermissionModalContext = this.#modalManagerContext?.open(this, UMB_ENTITY_USER_PERMISSION_MODAL, { data: { unique: item.unique, entityType: item.entityType, headline, preset: { - allowedVerbs: uniqueFallbackVerbs, + allowedVerbs: fallbackVerbs, }, }, value: { @@ -248,12 +243,17 @@ export class UmbInputDocumentGranularUserPermissionElement extends UUIFormContro #getFallbackPermissionVerbsForEntityType(entityType: string) { // get all permissions that are allowed for the entity type and have at least one of the fallback permissions // this is used to determine the default permissions for a document - return umbExtensionsRegistry.getByTypeAndFilter( - 'entityUserPermission', - (manifest) => - manifest.forEntityTypes.includes(entityType) && - this.fallbackPermissions.map((verb) => manifest.meta.verbs.includes(verb)).includes(true), - ); + const verbs = umbExtensionsRegistry + .getByTypeAndFilter( + 'entityUserPermission', + (manifest) => + manifest.forEntityTypes.includes(entityType) && + this.fallbackPermissions.map((verb) => manifest.meta.verbs.includes(verb)).includes(true), + ) + .flatMap((permission) => permission.meta.verbs); + + // ensure that the verbs are unique + return [...new Set([...verbs])]; } static override styles = [ From 9f93a6ad4fe2fef518f44ef506a17693f367887b Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 12 Mar 2025 10:39:22 +0100 Subject: [PATCH 011/106] wip document type property picker --- .../document-types/structure/manifests.ts | 6 +- .../property-picker-modal/constants.ts | 1 + ...ment-type-property-picker-modal.element.ts | 99 +++++++++++++++++++ ...cument-type-property-picker-modal.token.ts | 21 ++++ .../property-picker-modal/manifests.ts | 11 +++ ...ucture-granular-user-permission.element.ts | 85 +++++++++++----- .../structure/user-permission/types.ts | 2 +- 7 files changed, 197 insertions(+), 28 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-picker-modal/constants.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-picker-modal/document-type-property-picker-modal.element.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-picker-modal/document-type-property-picker-modal.token.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-picker-modal/manifests.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/manifests.ts index 75df1047993e..038eea56727b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/manifests.ts @@ -1,4 +1,8 @@ import { manifests as permissionManifests } from './user-permission/manifests.js'; +import { manifests as propertyPickerModalManifests } from './property-picker-modal/manifests.js'; import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; -export const manifests: Array = [...permissionManifests]; +export const manifests: Array = [ + ...permissionManifests, + ...propertyPickerModalManifests, +]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-picker-modal/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-picker-modal/constants.ts new file mode 100644 index 000000000000..b51d51c550f2 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-picker-modal/constants.ts @@ -0,0 +1 @@ +export const UMB_DOCUMENT_TYPE_PROPERTY_PICKER_MODAL_ALIAS = 'Umb.Modal.DocumentType.PropertyPicker'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-picker-modal/document-type-property-picker-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-picker-modal/document-type-property-picker-modal.element.ts new file mode 100644 index 000000000000..0e1c2cc448a5 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-picker-modal/document-type-property-picker-modal.element.ts @@ -0,0 +1,99 @@ +import { UmbDocumentTypeDetailRepository } from '../../repository/index.js'; +import type { + UmbDocumentTypePropertyPickerModalData, + UmbDocumentTypePropertyPickerModalValue, +} from './document-type-property-picker-modal.token.js'; +import { html, customElement, state, repeat } from '@umbraco-cms/backoffice/external/lit'; +import { UmbSelectionManager } from '@umbraco-cms/backoffice/utils'; +import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; +import type { UmbPropertyTypeModel } from '@umbraco-cms/backoffice/content-type'; +import { UmbDeselectedEvent, UmbSelectedEvent } from '@umbraco-cms/backoffice/event'; + +@customElement('umb-document-type-property-picker-modal') +export class UmbDocumentTypePropertyPickerModalElement extends UmbModalBaseElement< + UmbDocumentTypePropertyPickerModalData, + UmbDocumentTypePropertyPickerModalValue +> { + @state() + private _properties: Array = []; + + #detailRepository = new UmbDocumentTypeDetailRepository(this); + #selectionManager = new UmbSelectionManager(this); + + override connectedCallback(): void { + super.connectedCallback(); + this.#selectionManager.setSelectable(true); + this.#selectionManager.setMultiple(this.data?.multiple ?? false); + this.#selectionManager.setSelection(this.value?.selection ?? []); + + this.observe(this.#selectionManager.selection, (selection) => { + this.value = { selection }; + }); + } + + #onItemSelected(event: CustomEvent, item: UmbPropertyTypeModel) { + event.stopPropagation(); + this.#selectionManager.select(item.alias); + this.modalContext?.dispatchEvent(new UmbSelectedEvent(item.alias)); + } + + #onItemDeselected(event: CustomEvent, item: UmbPropertyTypeModel) { + event.stopPropagation(); + this.#selectionManager.deselect(item.alias); + this.modalContext?.dispatchEvent(new UmbDeselectedEvent(item.alias)); + } + + override async firstUpdated() { + if (!this.data?.documentType?.unique) { + throw new Error('Document type unique is required'); + } + + const { data } = await this.#detailRepository.requestByUnique(this.data.documentType.unique); + this._properties = data?.properties ?? []; + } + + get #filteredProperties() { + if (this.data?.filter) { + return this._properties.filter(this.data.filter); + } else { + return this._properties; + } + } + + override render() { + return html` + + ${this.#filteredProperties.length > 0 + ? repeat( + this.#filteredProperties, + (item) => item.alias, + (item) => html` + this.#onItemSelected(event, item)} + @deselected=${(event: CustomEvent) => this.#onItemDeselected(event, item)} + ?selected=${this.value.selection.includes(item.alias)}> + + + `, + ) + : html`There are no properties to choose from.`} + +
+ + +
+
`; + } +} + +export { UmbDocumentTypePropertyPickerModalElement as element }; + +declare global { + interface HTMLElementTagNameMap { + 'umb-document-type-property-picker-modal': UmbDocumentTypePropertyPickerModalElement; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-picker-modal/document-type-property-picker-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-picker-modal/document-type-property-picker-modal.token.ts new file mode 100644 index 000000000000..a21dee27c4ac --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-picker-modal/document-type-property-picker-modal.token.ts @@ -0,0 +1,21 @@ +import { UMB_DOCUMENT_TYPE_PROPERTY_PICKER_MODAL_ALIAS } from './constants.js'; +import { UmbModalToken, type UmbPickerModalData, type UmbPickerModalValue } from '@umbraco-cms/backoffice/modal'; + +export interface UmbDocumentTypePropertyPickerModalData extends UmbPickerModalData { + documentType: { + unique: string; + }; +} + +// eslint-disable-next-line @typescript-eslint/no-empty-object-type +export interface UmbDocumentTypePropertyPickerModalValue extends UmbPickerModalValue {} + +export const UMB_DOCUMENT_TYPE_PROPERTY_PICKER_MODAL = new UmbModalToken< + UmbDocumentTypePropertyPickerModalData, + UmbDocumentTypePropertyPickerModalValue +>(UMB_DOCUMENT_TYPE_PROPERTY_PICKER_MODAL_ALIAS, { + modal: { + type: 'sidebar', + size: 'small', + }, +}); diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-picker-modal/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-picker-modal/manifests.ts new file mode 100644 index 000000000000..ebc4343602eb --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-picker-modal/manifests.ts @@ -0,0 +1,11 @@ +import { UMB_DOCUMENT_TYPE_PROPERTY_PICKER_MODAL_ALIAS } from './constants.js'; +import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'modal', + alias: UMB_DOCUMENT_TYPE_PROPERTY_PICKER_MODAL_ALIAS, + name: 'Document Type Property Picker Modal', + element: () => import('./document-type-property-picker-modal.element.js'), + }, +]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/user-permission/input-document-type-structure-granular-user-permission/input-document-type-structure-granular-user-permission.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/user-permission/input-document-type-structure-granular-user-permission/input-document-type-structure-granular-user-permission.element.ts index ce66987564cc..7e3c86a8afca 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/user-permission/input-document-type-structure-granular-user-permission/input-document-type-structure-granular-user-permission.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/user-permission/input-document-type-structure-granular-user-permission/input-document-type-structure-granular-user-permission.element.ts @@ -3,6 +3,7 @@ import { UmbDocumentTypeItemRepository } from '../../../repository/item/index.js import type { UmbDocumentTypeItemModel } from '../../../repository/item/types.js'; import type { UmbDocumentTypeTreeItemModel } from '../../../tree/types.js'; import { UMB_DOCUMENT_TYPE_PICKER_MODAL } from '../../../modals/index.js'; +import { UMB_DOCUMENT_TYPE_PROPERTY_PICKER_MODAL } from '../../property-picker-modal/document-type-property-picker-modal.token.js'; import { css, customElement, html, repeat, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import type { UmbModalManagerContext } from '@umbraco-cms/backoffice/modal'; @@ -34,7 +35,7 @@ export class UmbInputDocumentTypeStructureGranularUserPermissionElement extends #documentTypeItemRepository = new UmbDocumentTypeItemRepository(this); #modalManagerContext?: UmbModalManagerContext; #documentTypePickerModalContext?: any; - #entityUserPermissionModalContext?: any; + #documentTypePropertyPickerModalContext?: any; constructor() { super(); @@ -86,25 +87,53 @@ export class UmbInputDocumentTypeStructureGranularUserPermissionElement extends this.#documentTypePickerModalContext?.addEventListener(UmbSelectedEvent.TYPE, async (event: UmbDeselectedEvent) => { const selectedEvent = event as UmbSelectedEvent; const unique = selectedEvent.unique; - if (!unique) return; + if (!unique) { + throw new Error('Could not open Document type property modal, no unique was provided'); + } const documentTypeItem = await this.#requestDocumentTypeItem(unique); - this.#selectEntityUserPermissionsForDocumentType(documentTypeItem).then( - (result) => { - this.#documentTypePickerModalContext?.reject(); - - const permissionItem: UmbDocumentTypeStructureUserPermissionModel = { - $type: 'DocumentTypeStructurePermissionPresentationModel', - documentType: { unique }, - verbs: result, - }; - - this.permissions = [...this._permissions, permissionItem]; - this.dispatchEvent(new UmbChangeEvent()); + this.#documentTypePropertyPickerModalContext = this.#modalManagerContext?.open( + this, + UMB_DOCUMENT_TYPE_PROPERTY_PICKER_MODAL, + { + data: { + documentType: { + unique: documentTypeItem.unique, + }, + }, }, - () => { - this.#documentTypePickerModalContext?.reject(); + ); + + this.#documentTypePropertyPickerModalContext?.addEventListener( + UmbSelectedEvent.TYPE, + async (event: UmbSelectedEvent) => { + const selectedEvent = event as UmbSelectedEvent; + const propertyAlias = selectedEvent.unique; + + if (!propertyAlias) { + throw new Error('Could not open permissions modal, no property alias was provided'); + } + + this.#selectEntityUserPermissionsForDocumentType(documentTypeItem).then( + (result) => { + this.#documentTypePickerModalContext?.reject(); + this.#documentTypePropertyPickerModalContext?.reject(); + + const permissionItem: UmbDocumentTypeStructureUserPermissionModel = { + $type: 'DocumentTypeStructurePermissionPresentationModel', + documentType: { unique }, + property: { alias: propertyAlias }, + verbs: result, + }; + + this.permissions = [...this._permissions, permissionItem]; + this.dispatchEvent(new UmbChangeEvent()); + }, + () => { + this.#documentTypePickerModalContext?.reject(); + }, + ); }, ); }); @@ -125,19 +154,23 @@ export class UmbInputDocumentTypeStructureGranularUserPermissionElement extends const name = item.name; const headline = name ? `Permissions for ${name}` : 'Permissions'; - this.#entityUserPermissionModalContext = this.#modalManagerContext?.open(this, UMB_ENTITY_USER_PERMISSION_MODAL, { - data: { - unique: item.unique, - entityType: item.entityType, - headline, - }, - value: { - allowedVerbs, + this.#documentTypePropertyPickerModalContext = this.#modalManagerContext?.open( + this, + UMB_ENTITY_USER_PERMISSION_MODAL, + { + data: { + unique: item.unique, + entityType: 'document-type-property', + headline, + }, + value: { + allowedVerbs, + }, }, - }); + ); try { - const value = await this.#entityUserPermissionModalContext?.onSubmit(); + const value = await this.#documentTypePropertyPickerModalContext?.onSubmit(); return value?.allowedVerbs; } catch { throw new Error(); diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/user-permission/types.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/user-permission/types.ts index 2c3d9b9c6807..4aee83eb0e48 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/user-permission/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/user-permission/types.ts @@ -8,5 +8,5 @@ export interface UmbDocumentTypeStructureUserPermissionModel extends UmbUserPerm documentType: { unique: string; }; - properties: Array; + property: UmbReferencedByAlias; } From 29b4cc6c8acf0c79c000f4e9dc6658422ee79405 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 12 Mar 2025 12:32:10 +0100 Subject: [PATCH 012/106] add preset value --- ...ucture-granular-user-permission.element.ts | 49 +++++++++++++++---- 1 file changed, 40 insertions(+), 9 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/user-permission/input-document-type-structure-granular-user-permission/input-document-type-structure-granular-user-permission.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/user-permission/input-document-type-structure-granular-user-permission/input-document-type-structure-granular-user-permission.element.ts index 7e3c86a8afca..f59b2ad45128 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/user-permission/input-document-type-structure-granular-user-permission/input-document-type-structure-granular-user-permission.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/user-permission/input-document-type-structure-granular-user-permission/input-document-type-structure-granular-user-permission.element.ts @@ -4,7 +4,7 @@ import type { UmbDocumentTypeItemModel } from '../../../repository/item/types.js import type { UmbDocumentTypeTreeItemModel } from '../../../tree/types.js'; import { UMB_DOCUMENT_TYPE_PICKER_MODAL } from '../../../modals/index.js'; import { UMB_DOCUMENT_TYPE_PROPERTY_PICKER_MODAL } from '../../property-picker-modal/document-type-property-picker-modal.token.js'; -import { css, customElement, html, repeat, state } from '@umbraco-cms/backoffice/external/lit'; +import { css, customElement, html, property, repeat, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import type { UmbModalManagerContext } from '@umbraco-cms/backoffice/modal'; import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; @@ -16,6 +16,8 @@ import { UMB_ENTITY_USER_PERMISSION_MODAL, type ManifestEntityUserPermission, } from '@umbraco-cms/backoffice/user-permission'; +import { UmbDocumentTypeDetailRepository } from '../../../repository/detail/index.js'; +import type { UmbPropertyTypeModel } from '@umbraco-cms/backoffice/content-type'; @customElement('umb-content-type-structure-document-granular-user-permission') export class UmbInputDocumentTypeStructureGranularUserPermissionElement extends UUIFormControlMixin(UmbLitElement, '') { @@ -29,10 +31,14 @@ export class UmbInputDocumentTypeStructureGranularUserPermissionElement extends this.#observePickedDocumentTypes(uniques); } + @property({ type: Array, attribute: false }) + fallbackPermissions: Array = []; + @state() private _items?: Array; #documentTypeItemRepository = new UmbDocumentTypeItemRepository(this); + #documentTypeDetailRepository = new UmbDocumentTypeDetailRepository(this); #modalManagerContext?: UmbModalManagerContext; #documentTypePickerModalContext?: any; #documentTypePropertyPickerModalContext?: any; @@ -115,7 +121,14 @@ export class UmbInputDocumentTypeStructureGranularUserPermissionElement extends throw new Error('Could not open permissions modal, no property alias was provided'); } - this.#selectEntityUserPermissionsForDocumentType(documentTypeItem).then( + const { data: documentTypeDetails } = await this.#documentTypeDetailRepository.requestByUnique(unique); + const property = documentTypeDetails?.properties.find((p) => p.alias === propertyAlias); + + if (!property) { + throw new Error('Could not open permissions modal, no property was found'); + } + + this.#selectEntityUserPermissionsForProperty(property).then( (result) => { this.#documentTypePickerModalContext?.reject(); this.#documentTypePropertyPickerModalContext?.reject(); @@ -149,19 +162,23 @@ export class UmbInputDocumentTypeStructureGranularUserPermissionElement extends return documentItem; } - async #selectEntityUserPermissionsForDocumentType(item: UmbDocumentTypeItemModel, allowedVerbs: Array = []) { + async #selectEntityUserPermissionsForProperty(property: UmbPropertyTypeModel, allowedVerbs: Array = []) { // TODO: get correct variant name - const name = item.name; + const name = property.name; const headline = name ? `Permissions for ${name}` : 'Permissions'; + const fallbackVerbs = this.#getFallbackPermissionVerbsForEntityType('document-type-property'); this.#documentTypePropertyPickerModalContext = this.#modalManagerContext?.open( this, UMB_ENTITY_USER_PERMISSION_MODAL, { data: { - unique: item.unique, + unique: property.alias, entityType: 'document-type-property', headline, + preset: { + allowedVerbs: fallbackVerbs, + }, }, value: { allowedVerbs, @@ -243,10 +260,8 @@ export class UmbInputDocumentTypeStructureGranularUserPermissionElement extends if (!permission) return; return umbExtensionsRegistry - .getAllExtensions() - .filter((manifest) => manifest.type === 'entityUserPermission') - .filter((manifest) => - (manifest as ManifestEntityUserPermission).meta.verbs.every((verb) => permission.verbs.includes(verb)), + .getByTypeAndFilter('entityUserPermission', (manifest) => + manifest.meta.verbs.every((verb) => permission.verbs.includes(verb)), ) .map((m) => { const manifest = m as ManifestEntityUserPermission; @@ -255,6 +270,22 @@ export class UmbInputDocumentTypeStructureGranularUserPermissionElement extends .join(', '); } + #getFallbackPermissionVerbsForEntityType(entityType: string) { + // get all permissions that are allowed for the entity type and have at least one of the fallback permissions + // this is used to determine the default permissions for a document + const verbs = umbExtensionsRegistry + .getByTypeAndFilter( + 'entityUserPermission', + (manifest) => + manifest.forEntityTypes.includes(entityType) && + this.fallbackPermissions.map((verb) => manifest.meta.verbs.includes(verb)).includes(true), + ) + .flatMap((permission) => permission.meta.verbs); + + // ensure that the verbs are unique + return [...new Set([...verbs])]; + } + static override styles = [ css` #btn-add { From eb113e026e3ced56f5566542e24c096c9ae79859 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 12 Mar 2025 12:32:36 +0100 Subject: [PATCH 013/106] Update input-document-type-structure-granular-user-permission.element.ts --- ...-document-type-structure-granular-user-permission.element.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/user-permission/input-document-type-structure-granular-user-permission/input-document-type-structure-granular-user-permission.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/user-permission/input-document-type-structure-granular-user-permission/input-document-type-structure-granular-user-permission.element.ts index f59b2ad45128..59a0bd508627 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/user-permission/input-document-type-structure-granular-user-permission/input-document-type-structure-granular-user-permission.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/user-permission/input-document-type-structure-granular-user-permission/input-document-type-structure-granular-user-permission.element.ts @@ -4,6 +4,7 @@ import type { UmbDocumentTypeItemModel } from '../../../repository/item/types.js import type { UmbDocumentTypeTreeItemModel } from '../../../tree/types.js'; import { UMB_DOCUMENT_TYPE_PICKER_MODAL } from '../../../modals/index.js'; import { UMB_DOCUMENT_TYPE_PROPERTY_PICKER_MODAL } from '../../property-picker-modal/document-type-property-picker-modal.token.js'; +import { UmbDocumentTypeDetailRepository } from '../../../repository/detail/index.js'; import { css, customElement, html, property, repeat, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import type { UmbModalManagerContext } from '@umbraco-cms/backoffice/modal'; @@ -16,7 +17,6 @@ import { UMB_ENTITY_USER_PERMISSION_MODAL, type ManifestEntityUserPermission, } from '@umbraco-cms/backoffice/user-permission'; -import { UmbDocumentTypeDetailRepository } from '../../../repository/detail/index.js'; import type { UmbPropertyTypeModel } from '@umbraco-cms/backoffice/content-type'; @customElement('umb-content-type-structure-document-granular-user-permission') From cb2e5bfd948363656920a159646d6602c6adec69 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 12 Mar 2025 13:18:32 +0100 Subject: [PATCH 014/106] move files --- .../document-types/structure/manifests.ts | 6 +--- .../structure/user-permission/manifests.ts | 2 +- .../document-value}/constants.ts | 0 ...value-granular-user-permission.element.ts} | 14 ++++----- .../document-value/manifests.ts | 29 +++++++++++++++++++ .../user-permissions/document-value}/types.ts | 0 6 files changed, 38 insertions(+), 13 deletions(-) rename src/Umbraco.Web.UI.Client/src/packages/documents/{document-types/structure/user-permission => documents/user-permissions/document-value}/constants.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/documents/{document-types/structure/user-permission/input-document-type-structure-granular-user-permission/input-document-type-structure-granular-user-permission.element.ts => documents/user-permissions/document-value/input-document-value-granular-user-permission/input-docum-value-granular-user-permission.element.ts} (93%) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/manifests.ts rename src/Umbraco.Web.UI.Client/src/packages/documents/{document-types/structure/user-permission => documents/user-permissions/document-value}/types.ts (100%) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/manifests.ts index 038eea56727b..1634134e33e8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/manifests.ts @@ -1,8 +1,4 @@ -import { manifests as permissionManifests } from './user-permission/manifests.js'; import { manifests as propertyPickerModalManifests } from './property-picker-modal/manifests.js'; import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; -export const manifests: Array = [ - ...permissionManifests, - ...propertyPickerModalManifests, -]; +export const manifests: Array = [...propertyPickerModalManifests]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/user-permission/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/user-permission/manifests.ts index cf4de120b199..b945e21f237b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/user-permission/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/user-permission/manifests.ts @@ -20,7 +20,7 @@ export const manifests: Array = name: 'Content Type Structure Granular User Permission', element: () => import( - './input-document-type-structure-granular-user-permission/input-document-type-structure-granular-user-permission.element.js' + '../../../documents/user-permissions/document-value/input-document-value-granular-user-permission/input-docum-value-granular-user-permission.element.js' ), meta: { schemaType: 'DocumentTypeStructurePermissionPresentationModel', diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/user-permission/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/constants.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/user-permission/constants.ts rename to src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/constants.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/user-permission/input-document-type-structure-granular-user-permission/input-document-type-structure-granular-user-permission.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/input-document-value-granular-user-permission/input-docum-value-granular-user-permission.element.ts similarity index 93% rename from src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/user-permission/input-document-type-structure-granular-user-permission/input-document-type-structure-granular-user-permission.element.ts rename to src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/input-document-value-granular-user-permission/input-docum-value-granular-user-permission.element.ts index 59a0bd508627..b718ac904562 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/user-permission/input-document-type-structure-granular-user-permission/input-document-type-structure-granular-user-permission.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/input-document-value-granular-user-permission/input-docum-value-granular-user-permission.element.ts @@ -1,10 +1,10 @@ -import type { UmbDocumentTypeStructureUserPermissionModel } from '../types.js'; -import { UmbDocumentTypeItemRepository } from '../../../repository/item/index.js'; -import type { UmbDocumentTypeItemModel } from '../../../repository/item/types.js'; -import type { UmbDocumentTypeTreeItemModel } from '../../../tree/types.js'; -import { UMB_DOCUMENT_TYPE_PICKER_MODAL } from '../../../modals/index.js'; -import { UMB_DOCUMENT_TYPE_PROPERTY_PICKER_MODAL } from '../../property-picker-modal/document-type-property-picker-modal.token.js'; -import { UmbDocumentTypeDetailRepository } from '../../../repository/detail/index.js'; +import type { UmbDocumentTypeStructureUserPermissionModel } from '../../../../document-types/structure/user-permission/types.js'; +import { UmbDocumentTypeItemRepository } from '../../../../document-types/repository/item/index.js'; +import type { UmbDocumentTypeItemModel } from '../../../../document-types/repository/item/types.js'; +import type { UmbDocumentTypeTreeItemModel } from '../../../../document-types/tree/types.js'; +import { UMB_DOCUMENT_TYPE_PICKER_MODAL } from '../../../../document-types/modals/index.js'; +import { UMB_DOCUMENT_TYPE_PROPERTY_PICKER_MODAL } from '../../../../document-types/structure/property-picker-modal/document-type-property-picker-modal.token.js'; +import { UmbDocumentTypeDetailRepository } from '../../../../document-types/repository/detail/index.js'; import { css, customElement, html, property, repeat, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import type { UmbModalManagerContext } from '@umbraco-cms/backoffice/modal'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/manifests.ts new file mode 100644 index 000000000000..338f306d0615 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/manifests.ts @@ -0,0 +1,29 @@ +import { UMB_USER_PERMISSION_DOCUMENT_TYPE_STRUCTURE_PROPERTY_SEE } from './constants.js'; +import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'entityUserPermission', + alias: 'Umb.EntityUserPermission.DocumentType.Structure.Property.See', + name: 'See Document Type Structure Property User Permission', + forEntityTypes: ['document-type-property'], + weight: 200, + meta: { + verbs: [UMB_USER_PERMISSION_DOCUMENT_TYPE_STRUCTURE_PROPERTY_SEE], + label: 'See', + description: 'See Document Type Property', + }, + }, + { + type: 'userGranularPermission', + alias: 'Umb.UserGranularPermission.ContentType.Structure', + name: 'Content Type Structure Granular User Permission', + element: () => + import('./input-document-value-granular-user-permission/input-docum-value-granular-user-permission.element.js'), + meta: { + schemaType: 'DocumentTypeStructurePermissionPresentationModel', + label: 'Document Type Structure', + description: 'Assign Permissions to Document Type structures', + }, + }, +]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/user-permission/types.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/types.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/user-permission/types.ts rename to src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/types.ts From 3eb75199bd4ebc1f1c1b3ff1e4ce90bf0c98907d Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 12 Mar 2025 13:36:46 +0100 Subject: [PATCH 015/106] rename --- .../documents/document-types/constants.ts | 5 +-- .../documents/document-types/index.ts | 2 ++ .../document-types/structure/constants.ts | 1 + .../document-types/structure/index.ts | 1 + .../structure/property-picker-modal/index.ts | 1 + .../structure/user-permission/manifests.ts | 31 ------------------ .../document-value/constants.ts | 2 +- ...value-granular-user-permission.element.ts} | 32 ++++++++++--------- .../document-value/manifests.ts | 26 ++++++++------- .../user-permissions/document-value/types.ts | 2 +- .../documents/user-permissions/manifests.ts | 2 ++ 11 files changed, 43 insertions(+), 62 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/constants.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/index.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-picker-modal/index.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/user-permission/manifests.ts rename src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/input-document-value-granular-user-permission/{input-docum-value-granular-user-permission.element.ts => input-document-value-granular-user-permission.element.ts} (86%) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/constants.ts index 1b4981f65ab4..18d226f5b8cb 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/constants.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/constants.ts @@ -1,7 +1,8 @@ -export * from './paths.js'; export * from './entity-actions/constants.js'; -export * from './search/constants.js'; +export * from './paths.js'; export * from './repository/constants.js'; +export * from './search/constants.js'; +export * from './structure/constants.js'; export * from './tree/constants.js'; export * from './workspace/constants.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/index.ts index 42ee1a2779d0..a9526fbaa6cd 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/index.ts @@ -4,5 +4,7 @@ export * from './components/index.js'; export * from './constants.js'; export * from './modals/index.js'; export * from './repository/index.js'; +export * from './structure/index.js'; export * from './workspace/index.js'; + export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/constants.ts new file mode 100644 index 000000000000..fb9627ee49e7 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/constants.ts @@ -0,0 +1 @@ +export * from './property-picker-modal/constants.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/index.ts new file mode 100644 index 000000000000..96d0469957fc --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/index.ts @@ -0,0 +1 @@ +export * from './property-picker-modal/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-picker-modal/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-picker-modal/index.ts new file mode 100644 index 000000000000..32e2e67d37d6 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-picker-modal/index.ts @@ -0,0 +1 @@ +export { UMB_DOCUMENT_TYPE_PROPERTY_PICKER_MODAL } from './document-type-property-picker-modal.token.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/user-permission/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/user-permission/manifests.ts deleted file mode 100644 index b945e21f237b..000000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/user-permission/manifests.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { UMB_USER_PERMISSION_DOCUMENT_TYPE_STRUCTURE_PROPERTY_SEE } from './constants.js'; -import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; - -export const manifests: Array = [ - { - type: 'entityUserPermission', - alias: 'Umb.EntityUserPermission.DocumentType.Structure.Property.See', - name: 'See Document Type Structure Property User Permission', - forEntityTypes: ['document-type-property'], - weight: 200, - meta: { - verbs: [UMB_USER_PERMISSION_DOCUMENT_TYPE_STRUCTURE_PROPERTY_SEE], - label: 'See', - description: 'See Document Type Property', - }, - }, - { - type: 'userGranularPermission', - alias: 'Umb.UserGranularPermission.ContentType.Structure', - name: 'Content Type Structure Granular User Permission', - element: () => - import( - '../../../documents/user-permissions/document-value/input-document-value-granular-user-permission/input-docum-value-granular-user-permission.element.js' - ), - meta: { - schemaType: 'DocumentTypeStructurePermissionPresentationModel', - label: 'Document Type Structure', - description: 'Assign Permissions to Document Type structures', - }, - }, -]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/constants.ts index d0d695ec43b8..2a47c96ce50c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/constants.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/constants.ts @@ -1 +1 @@ -export const UMB_USER_PERMISSION_DOCUMENT_TYPE_STRUCTURE_PROPERTY_SEE = 'Umb.DocumentType.Structure.Property.See'; +export const UMB_USER_PERMISSION_DOCUMENT_VALUE_SEE = 'Umb.DocumentValue.See'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/input-document-value-granular-user-permission/input-docum-value-granular-user-permission.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/input-document-value-granular-user-permission/input-document-value-granular-user-permission.element.ts similarity index 86% rename from src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/input-document-value-granular-user-permission/input-docum-value-granular-user-permission.element.ts rename to src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/input-document-value-granular-user-permission/input-document-value-granular-user-permission.element.ts index b718ac904562..42e47d3b5e1f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/input-document-value-granular-user-permission/input-docum-value-granular-user-permission.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/input-document-value-granular-user-permission/input-document-value-granular-user-permission.element.ts @@ -1,10 +1,4 @@ -import type { UmbDocumentTypeStructureUserPermissionModel } from '../../../../document-types/structure/user-permission/types.js'; -import { UmbDocumentTypeItemRepository } from '../../../../document-types/repository/item/index.js'; -import type { UmbDocumentTypeItemModel } from '../../../../document-types/repository/item/types.js'; -import type { UmbDocumentTypeTreeItemModel } from '../../../../document-types/tree/types.js'; -import { UMB_DOCUMENT_TYPE_PICKER_MODAL } from '../../../../document-types/modals/index.js'; -import { UMB_DOCUMENT_TYPE_PROPERTY_PICKER_MODAL } from '../../../../document-types/structure/property-picker-modal/document-type-property-picker-modal.token.js'; -import { UmbDocumentTypeDetailRepository } from '../../../../document-types/repository/detail/index.js'; +import type { UmbDocumentValueUserPermissionModel } from '../types.js'; import { css, customElement, html, property, repeat, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import type { UmbModalManagerContext } from '@umbraco-cms/backoffice/modal'; @@ -18,14 +12,22 @@ import { type ManifestEntityUserPermission, } from '@umbraco-cms/backoffice/user-permission'; import type { UmbPropertyTypeModel } from '@umbraco-cms/backoffice/content-type'; - -@customElement('umb-content-type-structure-document-granular-user-permission') -export class UmbInputDocumentTypeStructureGranularUserPermissionElement extends UUIFormControlMixin(UmbLitElement, '') { - _permissions: Array = []; - public get permissions(): Array { +import { + UMB_DOCUMENT_TYPE_PICKER_MODAL, + UMB_DOCUMENT_TYPE_PROPERTY_PICKER_MODAL, + UmbDocumentTypeDetailRepository, + UmbDocumentTypeItemRepository, + type UmbDocumentTypeItemModel, + type UmbDocumentTypeTreeItemModel, +} from '@umbraco-cms/backoffice/document-type'; + +@customElement('umb-document-value-granular-user-permission') +export class UmbInputDocumentValueGranularUserPermissionElement extends UUIFormControlMixin(UmbLitElement, '') { + _permissions: Array = []; + public get permissions(): Array { return this._permissions; } - public set permissions(value: Array) { + public set permissions(value: Array) { this._permissions = value; const uniques = value.map((item) => item.documentType.unique); this.#observePickedDocumentTypes(uniques); @@ -295,10 +297,10 @@ export class UmbInputDocumentTypeStructureGranularUserPermissionElement extends ]; } -export { UmbInputDocumentTypeStructureGranularUserPermissionElement as element }; +export { UmbInputDocumentValueGranularUserPermissionElement as element }; declare global { interface HTMLElementTagNameMap { - 'umb-document-type-structure-granular-user-permission': UmbInputDocumentTypeStructureGranularUserPermissionElement; + 'umb-document-value-granular-user-permission': UmbInputDocumentValueGranularUserPermissionElement; } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/manifests.ts index 338f306d0615..d8675c9c6698 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/manifests.ts @@ -1,29 +1,31 @@ -import { UMB_USER_PERMISSION_DOCUMENT_TYPE_STRUCTURE_PROPERTY_SEE } from './constants.js'; +import { UMB_USER_PERMISSION_DOCUMENT_VALUE_SEE } from './constants.js'; import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; export const manifests: Array = [ { type: 'entityUserPermission', - alias: 'Umb.EntityUserPermission.DocumentType.Structure.Property.See', - name: 'See Document Type Structure Property User Permission', - forEntityTypes: ['document-type-property'], + alias: 'Umb.EntityUserPermission.DocumentValue.See', + name: 'See Document Value User Permission', + forEntityTypes: ['document-value'], weight: 200, meta: { - verbs: [UMB_USER_PERMISSION_DOCUMENT_TYPE_STRUCTURE_PROPERTY_SEE], + verbs: [UMB_USER_PERMISSION_DOCUMENT_VALUE_SEE], label: 'See', - description: 'See Document Type Property', + description: 'See Document value', }, }, { type: 'userGranularPermission', - alias: 'Umb.UserGranularPermission.ContentType.Structure', - name: 'Content Type Structure Granular User Permission', + alias: 'Umb.UserGranularPermission.DocumentValue', + name: 'Document Values Granular User Permission', element: () => - import('./input-document-value-granular-user-permission/input-docum-value-granular-user-permission.element.js'), + import( + './input-document-value-granular-user-permission/input-document-value-granular-user-permission.element.js' + ), meta: { - schemaType: 'DocumentTypeStructurePermissionPresentationModel', - label: 'Document Type Structure', - description: 'Assign Permissions to Document Type structures', + schemaType: 'DocumentValuePermissionPresentationModel', + label: 'Document Values', + description: 'Assign Permissions to Document values', }, }, ]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/types.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/types.ts index 4aee83eb0e48..48e1e3c9ba71 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/types.ts @@ -4,7 +4,7 @@ export interface UmbReferencedByAlias { alias: string; } -export interface UmbDocumentTypeStructureUserPermissionModel extends UmbUserPermissionModel { +export interface UmbDocumentValueUserPermissionModel extends UmbUserPermissionModel { documentType: { unique: string; }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/manifests.ts index 30505ba03ad9..e6bda43b0828 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/manifests.ts @@ -18,6 +18,7 @@ import { } from './constants.js'; import { manifests as repositoryManifests } from './repository/manifests.js'; import { manifests as conditionManifests } from './conditions/manifests.js'; +import { manifests as documentValueManifests } from './document-value/manifests.js'; import type { ManifestGranularUserPermission, ManifestEntityUserPermission, @@ -217,4 +218,5 @@ export const manifests: Array = [ ...permissions, ...granularPermissions, ...conditionManifests, + ...documentValueManifests, ]; From be467a3c8c9dd3a38f6572e8370ad131cf4819cc Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 12 Mar 2025 13:45:44 +0100 Subject: [PATCH 016/106] Update input-document-value-granular-user-permission.element.ts --- .../input-document-value-granular-user-permission.element.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/input-document-value-granular-user-permission/input-document-value-granular-user-permission.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/input-document-value-granular-user-permission/input-document-value-granular-user-permission.element.ts index 42e47d3b5e1f..d0d8d622b230 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/input-document-value-granular-user-permission/input-document-value-granular-user-permission.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/input-document-value-granular-user-permission/input-document-value-granular-user-permission.element.ts @@ -135,8 +135,8 @@ export class UmbInputDocumentValueGranularUserPermissionElement extends UUIFormC this.#documentTypePickerModalContext?.reject(); this.#documentTypePropertyPickerModalContext?.reject(); - const permissionItem: UmbDocumentTypeStructureUserPermissionModel = { - $type: 'DocumentTypeStructurePermissionPresentationModel', + const permissionItem: UmbDocumentValueUserPermissionModel = { + $type: 'DocumentValuePermissionPresentationModel', documentType: { unique }, property: { alias: propertyAlias }, verbs: result, From 3a74ec1b0a9ea7b0144debdbd9355bbf7eb5fa81 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 12 Mar 2025 13:47:04 +0100 Subject: [PATCH 017/106] remove temp test --- .../media/media-types/structure/manifests.ts | 4 ---- .../structure/user-permission/constants.ts | 1 - .../structure/user-permission/manifests.ts | 17 ----------------- .../structure/user-permission/types.ts | 12 ------------ 4 files changed, 34 deletions(-) delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/media/media-types/structure/manifests.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/media/media-types/structure/user-permission/constants.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/media/media-types/structure/user-permission/manifests.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/media/media-types/structure/user-permission/types.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/structure/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/structure/manifests.ts deleted file mode 100644 index 75df1047993e..000000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/structure/manifests.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { manifests as permissionManifests } from './user-permission/manifests.js'; -import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; - -export const manifests: Array = [...permissionManifests]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/structure/user-permission/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/structure/user-permission/constants.ts deleted file mode 100644 index 5d19d2ab6774..000000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/structure/user-permission/constants.ts +++ /dev/null @@ -1 +0,0 @@ -export const UMB_USER_PERMISSION_MEDIA_TYPE_STRUCTURE_PROPERTY_SEE = 'Umb.MediaType.Structure.Property.See'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/structure/user-permission/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/structure/user-permission/manifests.ts deleted file mode 100644 index dba73d979340..000000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/structure/user-permission/manifests.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { UMB_USER_PERMISSION_MEDIA_TYPE_STRUCTURE_PROPERTY_SEE } from './constants.js'; -import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; - -export const manifests: Array = [ - { - type: 'entityUserPermission', - alias: 'Umb.EntityUserPermission.MediaType.Structure.Property.See', - name: 'See Media Type Structure Property User Permission', - forEntityTypes: ['media-type-property'], - weight: 100, - meta: { - verbs: [UMB_USER_PERMISSION_MEDIA_TYPE_STRUCTURE_PROPERTY_SEE], - label: 'See', - description: 'See Media Type Property', - }, - }, -]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/structure/user-permission/types.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/structure/user-permission/types.ts deleted file mode 100644 index bab52d3bd0df..000000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/structure/user-permission/types.ts +++ /dev/null @@ -1,12 +0,0 @@ -import type { UmbUserPermissionModel } from '@umbraco-cms/backoffice/user-permission'; - -export interface UmbReferencedByAlias { - alias: string; -} - -export interface UmbMediaTypeStructureUserPermissionModel extends UmbUserPermissionModel { - mediaType: { - unique: string; - }; - properties: Array; -} From e9bd236c06a909fbfba0f54323ca0762fcb91886 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 12 Mar 2025 15:28:22 +0100 Subject: [PATCH 018/106] Update manifests.ts --- .../documents/user-permissions/document-value/manifests.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/manifests.ts index d8675c9c6698..28bb890636ac 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/manifests.ts @@ -11,7 +11,7 @@ export const manifests: Array = meta: { verbs: [UMB_USER_PERMISSION_DOCUMENT_VALUE_SEE], label: 'See', - description: 'See Document value', + description: 'See Document values', }, }, { From 398f83f8c91cbb797d87c242f38b1ac90ea08376 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 13 Mar 2025 13:36:36 +0100 Subject: [PATCH 019/106] remove unused --- .../src/packages/media/media-types/manifests.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/manifests.ts index 78e3466724c7..be8ede9dc42e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/manifests.ts @@ -3,7 +3,6 @@ import { manifests as menuManifests } from './menu/manifests.js'; import { manifests as propertyEditorUiManifests } from './property-editors/manifests.js'; import { manifests as repositoryManifests } from './repository/manifests.js'; import { manifests as searchManifests } from './search/manifests.js'; -import { manifests as structureManifests } from './structure/manifests.js'; import { manifests as treeManifests } from './tree/manifests.js'; import { manifests as workspaceManifests } from './workspace/manifests.js'; @@ -15,7 +14,6 @@ export const manifests: Array = ...propertyEditorUiManifests, ...repositoryManifests, ...searchManifests, - ...structureManifests, ...treeManifests, ...workspaceManifests, ]; From 8fe8e1c257a3d749e3202d0a99905a6752a1b01d Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 13 Mar 2025 14:06:20 +0100 Subject: [PATCH 020/106] Update input-document-value-granular-user-permission.element.ts --- .../input-document-value-granular-user-permission.element.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/input-document-value-granular-user-permission/input-document-value-granular-user-permission.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/input-document-value-granular-user-permission/input-document-value-granular-user-permission.element.ts index d0d8d622b230..5165d313b648 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/input-document-value-granular-user-permission/input-document-value-granular-user-permission.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/input-document-value-granular-user-permission/input-document-value-granular-user-permission.element.ts @@ -168,7 +168,7 @@ export class UmbInputDocumentValueGranularUserPermissionElement extends UUIFormC // TODO: get correct variant name const name = property.name; const headline = name ? `Permissions for ${name}` : 'Permissions'; - const fallbackVerbs = this.#getFallbackPermissionVerbsForEntityType('document-type-property'); + const fallbackVerbs = this.#getFallbackPermissionVerbsForEntityType('document-value'); this.#documentTypePropertyPickerModalContext = this.#modalManagerContext?.open( this, @@ -176,7 +176,7 @@ export class UmbInputDocumentValueGranularUserPermissionElement extends UUIFormC { data: { unique: property.alias, - entityType: 'document-type-property', + entityType: 'document-value', headline, preset: { allowedVerbs: fallbackVerbs, From 437f44311e0ae21c2d61fdceea037014c47960a5 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 13 Mar 2025 14:16:35 +0100 Subject: [PATCH 021/106] rename see permission + add write permission --- .../document-value/constants.ts | 3 ++- .../document-value/manifests.ts | 24 ++++++++++++++----- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/constants.ts index 2a47c96ce50c..f27f8ea5af58 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/constants.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/constants.ts @@ -1 +1,2 @@ -export const UMB_USER_PERMISSION_DOCUMENT_VALUE_SEE = 'Umb.DocumentValue.See'; +export const UMB_USER_PERMISSION_DOCUMENT_VALUE_READ = 'Umb.DocumentValue.Read'; +export const UMB_USER_PERMISSION_DOCUMENT_VALUE_WRITE = 'Umb.DocumentValue.Write'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/manifests.ts index 28bb890636ac..c80f66e4512f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/manifests.ts @@ -1,17 +1,29 @@ -import { UMB_USER_PERMISSION_DOCUMENT_VALUE_SEE } from './constants.js'; +import { UMB_USER_PERMISSION_DOCUMENT_VALUE_READ, UMB_USER_PERMISSION_DOCUMENT_VALUE_WRITE } from './constants.js'; import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; export const manifests: Array = [ { type: 'entityUserPermission', - alias: 'Umb.EntityUserPermission.DocumentValue.See', - name: 'See Document Value User Permission', + alias: 'Umb.EntityUserPermission.DocumentValue.Read', + name: 'Read Document Value User Permission', forEntityTypes: ['document-value'], weight: 200, meta: { - verbs: [UMB_USER_PERMISSION_DOCUMENT_VALUE_SEE], - label: 'See', - description: 'See Document values', + verbs: [UMB_USER_PERMISSION_DOCUMENT_VALUE_READ], + label: 'Read', + description: 'Read Document values', + }, + }, + { + type: 'entityUserPermission', + alias: 'Umb.EntityUserPermission.DocumentValue.Write', + name: 'Write Document Value User Permission', + forEntityTypes: ['document-value'], + weight: 200, + meta: { + verbs: [UMB_USER_PERMISSION_DOCUMENT_VALUE_WRITE], + label: 'Write', + description: 'Write Document values', }, }, { From 8e474d67f8bf6b1f4e507a741c5462e2eaed28c0 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 13 Mar 2025 14:28:40 +0100 Subject: [PATCH 022/106] fix missing type --- .../packages/documents/documents/user-permissions/manifests.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/manifests.ts index e6bda43b0828..9b675f48fd9d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/manifests.ts @@ -23,6 +23,7 @@ import type { ManifestGranularUserPermission, ManifestEntityUserPermission, } from '@umbraco-cms/backoffice/user-permission'; +import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; const permissions: Array = [ { @@ -213,7 +214,7 @@ export const granularPermissions: Array = [ }, ]; -export const manifests: Array = [ +export const manifests: Array = [ ...repositoryManifests, ...permissions, ...granularPermissions, From 66f20827bf549a554a84998246897e5274f88905 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 13 Mar 2025 14:29:00 +0100 Subject: [PATCH 023/106] require property type unique --- .../documents/user-permissions/document-value/types.ts | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/types.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/types.ts index 48e1e3c9ba71..58387acd798a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/types.ts @@ -1,12 +1,10 @@ import type { UmbUserPermissionModel } from '@umbraco-cms/backoffice/user-permission'; -export interface UmbReferencedByAlias { - alias: string; -} - export interface UmbDocumentValueUserPermissionModel extends UmbUserPermissionModel { documentType: { unique: string; }; - property: UmbReferencedByAlias; + property: { + unique: string; + }; } From c4e3b6da870e232e3b9ecfa298afd82124c98ca7 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 13 Mar 2025 14:29:22 +0100 Subject: [PATCH 024/106] add unique to property type --- .../src/packages/core/content-type/types.ts | 1 + .../detail/document-type-detail.server.data-source.ts | 1 + ...put-document-value-granular-user-permission.element.ts | 8 ++++---- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/types.ts index 857c3b0705de..f5f96da428f7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/types.ts @@ -47,6 +47,7 @@ export interface UmbPropertyTypeScaffoldModel extends Omit { return { id: property.id, + unique: property.id, container: property.container, sortOrder: property.sortOrder, alias: property.alias, diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/input-document-value-granular-user-permission/input-document-value-granular-user-permission.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/input-document-value-granular-user-permission/input-document-value-granular-user-permission.element.ts index 5165d313b648..625f5b5c288e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/input-document-value-granular-user-permission/input-document-value-granular-user-permission.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/input-document-value-granular-user-permission/input-document-value-granular-user-permission.element.ts @@ -117,14 +117,14 @@ export class UmbInputDocumentValueGranularUserPermissionElement extends UUIFormC UmbSelectedEvent.TYPE, async (event: UmbSelectedEvent) => { const selectedEvent = event as UmbSelectedEvent; - const propertyAlias = selectedEvent.unique; + const propertyUnique = selectedEvent.unique; - if (!propertyAlias) { + if (!propertyUnique) { throw new Error('Could not open permissions modal, no property alias was provided'); } const { data: documentTypeDetails } = await this.#documentTypeDetailRepository.requestByUnique(unique); - const property = documentTypeDetails?.properties.find((p) => p.alias === propertyAlias); + const property = documentTypeDetails?.properties.find((p) => p.unique === propertyUnique); if (!property) { throw new Error('Could not open permissions modal, no property was found'); @@ -138,7 +138,7 @@ export class UmbInputDocumentValueGranularUserPermissionElement extends UUIFormC const permissionItem: UmbDocumentValueUserPermissionModel = { $type: 'DocumentValuePermissionPresentationModel', documentType: { unique }, - property: { alias: propertyAlias }, + property: { unique: propertyUnique }, verbs: result, }; From de626ff65c270ea90c8f770acdf29c6e9ce0d94d Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 13 Mar 2025 14:30:21 +0100 Subject: [PATCH 025/106] rename to property type --- .../input-document-value-granular-user-permission.element.ts | 2 +- .../documents/user-permissions/document-value/types.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/input-document-value-granular-user-permission/input-document-value-granular-user-permission.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/input-document-value-granular-user-permission/input-document-value-granular-user-permission.element.ts index 625f5b5c288e..43354182b583 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/input-document-value-granular-user-permission/input-document-value-granular-user-permission.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/input-document-value-granular-user-permission/input-document-value-granular-user-permission.element.ts @@ -138,7 +138,7 @@ export class UmbInputDocumentValueGranularUserPermissionElement extends UUIFormC const permissionItem: UmbDocumentValueUserPermissionModel = { $type: 'DocumentValuePermissionPresentationModel', documentType: { unique }, - property: { unique: propertyUnique }, + propertyType: { unique: propertyUnique }, verbs: result, }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/types.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/types.ts index 58387acd798a..47c5f5421ff1 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/types.ts @@ -4,7 +4,7 @@ export interface UmbDocumentValueUserPermissionModel extends UmbUserPermissionMo documentType: { unique: string; }; - property: { + propertyType: { unique: string; }; } From ae34369d8ce53b8c0da294743ab9df289dbaeff6 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 13 Mar 2025 14:31:27 +0100 Subject: [PATCH 026/106] map to unique --- .../repository/detail/media-type-detail.server.data-source.ts | 1 + .../repository/detail/member-type-detail.server.data-source.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/detail/media-type-detail.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/detail/media-type-detail.server.data-source.ts index 7fc5078ce846..b97fa63dd737 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/detail/media-type-detail.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/detail/media-type-detail.server.data-source.ts @@ -87,6 +87,7 @@ export class UmbMediaTypeServerDataSource implements UmbDetailDataSource { return { id: property.id, + unique: property.id, container: property.container, sortOrder: property.sortOrder, alias: property.alias, diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member-type/repository/detail/member-type-detail.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member-type/repository/detail/member-type-detail.server.data-source.ts index c78aeda13b08..c998d90cfa94 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member-type/repository/detail/member-type-detail.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member-type/repository/detail/member-type-detail.server.data-source.ts @@ -87,6 +87,7 @@ export class UmbMemberTypeServerDataSource implements UmbDetailDataSource { return { id: property.id, + unique: property.id, container: property.container ? { id: property.container.id } : null, sortOrder: property.sortOrder, alias: property.alias, From e7708f301bcd16e557df3cb95eb9bc4e3974de9a Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 13 Mar 2025 14:33:37 +0100 Subject: [PATCH 027/106] deprecate id on property type --- .../src/packages/core/content-type/types.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/types.ts index f5f96da428f7..8622e3fd9d0b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/types.ts @@ -46,6 +46,12 @@ export interface UmbPropertyTypeScaffoldModel extends Omit Date: Thu, 13 Mar 2025 15:02:37 +0100 Subject: [PATCH 028/106] return unique from property picker --- ...ment-type-property-picker-modal.element.ts | 12 +++---- ...-value-granular-user-permission.element.ts | 36 +++++++------------ ...ty-user-permission-settings-modal.token.ts | 8 ++++- 3 files changed, 25 insertions(+), 31 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-picker-modal/document-type-property-picker-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-picker-modal/document-type-property-picker-modal.element.ts index 0e1c2cc448a5..a4dbbe45655a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-picker-modal/document-type-property-picker-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-picker-modal/document-type-property-picker-modal.element.ts @@ -33,14 +33,14 @@ export class UmbDocumentTypePropertyPickerModalElement extends UmbModalBaseEleme #onItemSelected(event: CustomEvent, item: UmbPropertyTypeModel) { event.stopPropagation(); - this.#selectionManager.select(item.alias); - this.modalContext?.dispatchEvent(new UmbSelectedEvent(item.alias)); + this.#selectionManager.select(item.unique); + this.modalContext?.dispatchEvent(new UmbSelectedEvent(item.unique)); } #onItemDeselected(event: CustomEvent, item: UmbPropertyTypeModel) { event.stopPropagation(); - this.#selectionManager.deselect(item.alias); - this.modalContext?.dispatchEvent(new UmbDeselectedEvent(item.alias)); + this.#selectionManager.deselect(item.unique); + this.modalContext?.dispatchEvent(new UmbDeselectedEvent(item.unique)); } override async firstUpdated() { @@ -66,7 +66,7 @@ export class UmbDocumentTypePropertyPickerModalElement extends UmbModalBaseEleme ${this.#filteredProperties.length > 0 ? repeat( this.#filteredProperties, - (item) => item.alias, + (item) => item.unique, (item) => html` this.#onItemSelected(event, item)} @deselected=${(event: CustomEvent) => this.#onItemDeselected(event, item)} - ?selected=${this.value.selection.includes(item.alias)}> + ?selected=${this.value.selection.includes(item.unique)}> `, diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/input-document-value-granular-user-permission/input-document-value-granular-user-permission.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/input-document-value-granular-user-permission/input-document-value-granular-user-permission.element.ts index 43354182b583..2591e57150d6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/input-document-value-granular-user-permission/input-document-value-granular-user-permission.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/input-document-value-granular-user-permission/input-document-value-granular-user-permission.element.ts @@ -3,7 +3,6 @@ import { css, customElement, html, property, repeat, state } from '@umbraco-cms/ import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import type { UmbModalManagerContext } from '@umbraco-cms/backoffice/modal'; import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; -import type { UmbDeselectedEvent } from '@umbraco-cms/backoffice/event'; import { UmbChangeEvent, UmbSelectedEvent } from '@umbraco-cms/backoffice/event'; import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; import { UUIFormControlMixin } from '@umbraco-cms/backoffice/external/uui'; @@ -92,22 +91,21 @@ export class UmbInputDocumentValueGranularUserPermissionElement extends UUIFormC }, }); - this.#documentTypePickerModalContext?.addEventListener(UmbSelectedEvent.TYPE, async (event: UmbDeselectedEvent) => { + this.#documentTypePickerModalContext?.addEventListener(UmbSelectedEvent.TYPE, async (event: UmbSelectedEvent) => { const selectedEvent = event as UmbSelectedEvent; - const unique = selectedEvent.unique; - if (!unique) { + const documentTypeUnique = selectedEvent.unique; + + if (!documentTypeUnique) { throw new Error('Could not open Document type property modal, no unique was provided'); } - const documentTypeItem = await this.#requestDocumentTypeItem(unique); - this.#documentTypePropertyPickerModalContext = this.#modalManagerContext?.open( this, UMB_DOCUMENT_TYPE_PROPERTY_PICKER_MODAL, { data: { documentType: { - unique: documentTypeItem.unique, + unique: documentTypeUnique, }, }, }, @@ -117,14 +115,15 @@ export class UmbInputDocumentValueGranularUserPermissionElement extends UUIFormC UmbSelectedEvent.TYPE, async (event: UmbSelectedEvent) => { const selectedEvent = event as UmbSelectedEvent; - const propertyUnique = selectedEvent.unique; + const propertyTypeUnique = selectedEvent.unique; - if (!propertyUnique) { + if (!propertyTypeUnique) { throw new Error('Could not open permissions modal, no property alias was provided'); } - const { data: documentTypeDetails } = await this.#documentTypeDetailRepository.requestByUnique(unique); - const property = documentTypeDetails?.properties.find((p) => p.unique === propertyUnique); + const { data: documentTypeDetails } = + await this.#documentTypeDetailRepository.requestByUnique(documentTypeUnique); + const property = documentTypeDetails?.properties.find((p) => p.unique === propertyTypeUnique); if (!property) { throw new Error('Could not open permissions modal, no property was found'); @@ -137,8 +136,8 @@ export class UmbInputDocumentValueGranularUserPermissionElement extends UUIFormC const permissionItem: UmbDocumentValueUserPermissionModel = { $type: 'DocumentValuePermissionPresentationModel', - documentType: { unique }, - propertyType: { unique: propertyUnique }, + documentType: { unique: documentTypeUnique }, + propertyType: { unique: propertyTypeUnique }, verbs: result, }; @@ -154,16 +153,6 @@ export class UmbInputDocumentValueGranularUserPermissionElement extends UUIFormC }); } - async #requestDocumentTypeItem(unique: string) { - if (!unique) throw new Error('Could not open permissions modal, no unique was provided'); - - const { data } = await this.#documentTypeItemRepository.requestItems([unique]); - - const documentItem = data?.[0]; - if (!documentItem) throw new Error('No document item found'); - return documentItem; - } - async #selectEntityUserPermissionsForProperty(property: UmbPropertyTypeModel, allowedVerbs: Array = []) { // TODO: get correct variant name const name = property.name; @@ -175,7 +164,6 @@ export class UmbInputDocumentValueGranularUserPermissionElement extends UUIFormC UMB_ENTITY_USER_PERMISSION_MODAL, { data: { - unique: property.alias, entityType: 'document-value', headline, preset: { diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user-permission/modals/settings/entity-user-permission-settings-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user-permission/modals/settings/entity-user-permission-settings-modal.token.ts index 88ceb2d8fd86..3babce3f3a3f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user-permission/modals/settings/entity-user-permission-settings-modal.token.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user-permission/modals/settings/entity-user-permission-settings-modal.token.ts @@ -1,8 +1,14 @@ import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; export interface UmbEntityUserPermissionSettingsModalData { - unique: string; entityType: string; + /** + * Unique identifier for the entity + * @deprecated The unique is not used in the modal as it is not needed. It is kept for backwards compatibility. Will be removed in v17. + * @type {string} + * @memberof UmbEntityUserPermissionSettingsModalData + */ + unique?: string; headline?: string; preset?: UmbEntityUserPermissionSettingsModalValue; } From cf8c8c0d05e034f0dad3d0d55cc5db74c5e8b5d8 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 13 Mar 2025 15:05:24 +0100 Subject: [PATCH 029/106] more explicit naming --- .../document-types/structure/constants.ts | 2 +- .../document-types/structure/index.ts | 2 +- .../document-types/structure/manifests.ts | 4 ++-- .../property-picker-modal/constants.ts | 1 - ...cument-type-property-picker-modal.token.ts | 21 ------------------- .../property-picker-modal/manifests.ts | 11 ---------- .../property-type-picker-modal/constants.ts | 1 + ...ype-property-type-picker-modal.element.ts} | 10 ++++----- ...t-type-property-type-picker-modal.token.ts | 21 +++++++++++++++++++ .../index.ts | 2 +- .../property-type-picker-modal/manifests.ts | 11 ++++++++++ 11 files changed, 43 insertions(+), 43 deletions(-) delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-picker-modal/constants.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-picker-modal/document-type-property-picker-modal.token.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-picker-modal/manifests.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-type-picker-modal/constants.ts rename src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/{property-picker-modal/document-type-property-picker-modal.element.ts => property-type-picker-modal/document-type-property-type-picker-modal.element.ts} (93%) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-type-picker-modal/document-type-property-type-picker-modal.token.ts rename src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/{property-picker-modal => property-type-picker-modal}/index.ts (57%) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-type-picker-modal/manifests.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/constants.ts index fb9627ee49e7..67d537b6b74a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/constants.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/constants.ts @@ -1 +1 @@ -export * from './property-picker-modal/constants.js'; +export * from './property-type-picker-modal/constants.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/index.ts index 96d0469957fc..f5b29f018651 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/index.ts @@ -1 +1 @@ -export * from './property-picker-modal/index.js'; +export * from './property-type-picker-modal/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/manifests.ts index 1634134e33e8..a80467bc6ed3 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/manifests.ts @@ -1,4 +1,4 @@ -import { manifests as propertyPickerModalManifests } from './property-picker-modal/manifests.js'; +import { manifests as propertyTypePickerModalManifests } from './property-type-picker-modal/manifests.js'; import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; -export const manifests: Array = [...propertyPickerModalManifests]; +export const manifests: Array = [...propertyTypePickerModalManifests]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-picker-modal/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-picker-modal/constants.ts deleted file mode 100644 index b51d51c550f2..000000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-picker-modal/constants.ts +++ /dev/null @@ -1 +0,0 @@ -export const UMB_DOCUMENT_TYPE_PROPERTY_PICKER_MODAL_ALIAS = 'Umb.Modal.DocumentType.PropertyPicker'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-picker-modal/document-type-property-picker-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-picker-modal/document-type-property-picker-modal.token.ts deleted file mode 100644 index a21dee27c4ac..000000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-picker-modal/document-type-property-picker-modal.token.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { UMB_DOCUMENT_TYPE_PROPERTY_PICKER_MODAL_ALIAS } from './constants.js'; -import { UmbModalToken, type UmbPickerModalData, type UmbPickerModalValue } from '@umbraco-cms/backoffice/modal'; - -export interface UmbDocumentTypePropertyPickerModalData extends UmbPickerModalData { - documentType: { - unique: string; - }; -} - -// eslint-disable-next-line @typescript-eslint/no-empty-object-type -export interface UmbDocumentTypePropertyPickerModalValue extends UmbPickerModalValue {} - -export const UMB_DOCUMENT_TYPE_PROPERTY_PICKER_MODAL = new UmbModalToken< - UmbDocumentTypePropertyPickerModalData, - UmbDocumentTypePropertyPickerModalValue ->(UMB_DOCUMENT_TYPE_PROPERTY_PICKER_MODAL_ALIAS, { - modal: { - type: 'sidebar', - size: 'small', - }, -}); diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-picker-modal/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-picker-modal/manifests.ts deleted file mode 100644 index ebc4343602eb..000000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-picker-modal/manifests.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { UMB_DOCUMENT_TYPE_PROPERTY_PICKER_MODAL_ALIAS } from './constants.js'; -import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; - -export const manifests: Array = [ - { - type: 'modal', - alias: UMB_DOCUMENT_TYPE_PROPERTY_PICKER_MODAL_ALIAS, - name: 'Document Type Property Picker Modal', - element: () => import('./document-type-property-picker-modal.element.js'), - }, -]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-type-picker-modal/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-type-picker-modal/constants.ts new file mode 100644 index 000000000000..8920683ad5c1 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-type-picker-modal/constants.ts @@ -0,0 +1 @@ +export const UMB_DOCUMENT_TYPE_PROPERTY_TYPE_PICKER_MODAL_ALIAS = 'Umb.Modal.DocumentType.PropertyTypePicker'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-picker-modal/document-type-property-picker-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-type-picker-modal/document-type-property-type-picker-modal.element.ts similarity index 93% rename from src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-picker-modal/document-type-property-picker-modal.element.ts rename to src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-type-picker-modal/document-type-property-type-picker-modal.element.ts index a4dbbe45655a..437019e4e248 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-picker-modal/document-type-property-picker-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-type-picker-modal/document-type-property-type-picker-modal.element.ts @@ -1,8 +1,8 @@ import { UmbDocumentTypeDetailRepository } from '../../repository/index.js'; import type { - UmbDocumentTypePropertyPickerModalData, - UmbDocumentTypePropertyPickerModalValue, -} from './document-type-property-picker-modal.token.js'; + UmbDocumentTypePropertyTypePickerModalData, + UmbDocumentTypePropertyTypePickerModalValue, +} from './document-type-property-type-picker-modal.token.js'; import { html, customElement, state, repeat } from '@umbraco-cms/backoffice/external/lit'; import { UmbSelectionManager } from '@umbraco-cms/backoffice/utils'; import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; @@ -11,8 +11,8 @@ import { UmbDeselectedEvent, UmbSelectedEvent } from '@umbraco-cms/backoffice/ev @customElement('umb-document-type-property-picker-modal') export class UmbDocumentTypePropertyPickerModalElement extends UmbModalBaseElement< - UmbDocumentTypePropertyPickerModalData, - UmbDocumentTypePropertyPickerModalValue + UmbDocumentTypePropertyTypePickerModalData, + UmbDocumentTypePropertyTypePickerModalValue > { @state() private _properties: Array = []; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-type-picker-modal/document-type-property-type-picker-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-type-picker-modal/document-type-property-type-picker-modal.token.ts new file mode 100644 index 000000000000..1c86d6c7685c --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-type-picker-modal/document-type-property-type-picker-modal.token.ts @@ -0,0 +1,21 @@ +import { UMB_DOCUMENT_TYPE_PROPERTY_TYPE_PICKER_MODAL_ALIAS } from './constants.js'; +import { UmbModalToken, type UmbPickerModalData, type UmbPickerModalValue } from '@umbraco-cms/backoffice/modal'; + +export interface UmbDocumentTypePropertyTypePickerModalData extends UmbPickerModalData { + documentType: { + unique: string; + }; +} + +// eslint-disable-next-line @typescript-eslint/no-empty-object-type +export interface UmbDocumentTypePropertyTypePickerModalValue extends UmbPickerModalValue {} + +export const UMB_DOCUMENT_TYPE_PROPERTY_PICKER_MODAL = new UmbModalToken< + UmbDocumentTypePropertyTypePickerModalData, + UmbDocumentTypePropertyTypePickerModalValue +>(UMB_DOCUMENT_TYPE_PROPERTY_TYPE_PICKER_MODAL_ALIAS, { + modal: { + type: 'sidebar', + size: 'small', + }, +}); diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-picker-modal/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-type-picker-modal/index.ts similarity index 57% rename from src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-picker-modal/index.ts rename to src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-type-picker-modal/index.ts index 32e2e67d37d6..58e15a35fa67 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-picker-modal/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-type-picker-modal/index.ts @@ -1 +1 @@ -export { UMB_DOCUMENT_TYPE_PROPERTY_PICKER_MODAL } from './document-type-property-picker-modal.token.js'; +export { UMB_DOCUMENT_TYPE_PROPERTY_PICKER_MODAL } from './document-type-property-type-picker-modal.token.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-type-picker-modal/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-type-picker-modal/manifests.ts new file mode 100644 index 000000000000..d6ad8ffc496b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-type-picker-modal/manifests.ts @@ -0,0 +1,11 @@ +import { UMB_DOCUMENT_TYPE_PROPERTY_TYPE_PICKER_MODAL_ALIAS } from './constants.js'; +import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'modal', + alias: UMB_DOCUMENT_TYPE_PROPERTY_TYPE_PICKER_MODAL_ALIAS, + name: 'Document Type Property Type Picker Modal', + element: () => import('./document-type-property-type-picker-modal.element.js'), + }, +]; From 7e4daa9bf8fc14ea246e4ea96026364239f15ef4 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 13 Mar 2025 15:08:30 +0100 Subject: [PATCH 030/106] use type --- .../document-type-property-type-picker-modal.token.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-type-picker-modal/document-type-property-type-picker-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-type-picker-modal/document-type-property-type-picker-modal.token.ts index 1c86d6c7685c..29122ccaf40d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-type-picker-modal/document-type-property-type-picker-modal.token.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-type-picker-modal/document-type-property-type-picker-modal.token.ts @@ -1,7 +1,8 @@ import { UMB_DOCUMENT_TYPE_PROPERTY_TYPE_PICKER_MODAL_ALIAS } from './constants.js'; +import type { UmbPropertyTypeModel } from '@umbraco-cms/backoffice/content-type'; import { UmbModalToken, type UmbPickerModalData, type UmbPickerModalValue } from '@umbraco-cms/backoffice/modal'; -export interface UmbDocumentTypePropertyTypePickerModalData extends UmbPickerModalData { +export interface UmbDocumentTypePropertyTypePickerModalData extends UmbPickerModalData { documentType: { unique: string; }; From d5e6317c4c3b03d9a9d8aa9e3d60326282acb1f3 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 13 Mar 2025 20:57:07 +0100 Subject: [PATCH 031/106] render detail --- .../document-type-property-type-picker-modal.element.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-type-picker-modal/document-type-property-type-picker-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-type-picker-modal/document-type-property-type-picker-modal.element.ts index 437019e4e248..5f07b817b2f8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-type-picker-modal/document-type-property-type-picker-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-type-picker-modal/document-type-property-type-picker-modal.element.ts @@ -60,6 +60,13 @@ export class UmbDocumentTypePropertyPickerModalElement extends UmbModalBaseEleme } } + #getItemDetail(item: UmbPropertyTypeModel): string { + const isMandatory = item.validation?.mandatory ? ' - Mandatory' : ''; + const variesByCulture = item.variesByCulture ? ' - Varies by culture' : ''; + const variesBySegment = item.variesBySegment ? ' - Varies by segment' : ''; + return `${item.alias} ${isMandatory} ${variesByCulture} ${variesBySegment}`; + } + override render() { return html` @@ -70,7 +77,7 @@ export class UmbDocumentTypePropertyPickerModalElement extends UmbModalBaseEleme (item) => html` this.#onItemSelected(event, item)} From 7db7f48d127db4e91ce9ea776e612bfda235a786 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 14 Mar 2025 09:47:49 +0100 Subject: [PATCH 032/106] Update input-document-value-granular-user-permission.element.ts --- ...-value-granular-user-permission.element.ts | 169 +++++++++--------- 1 file changed, 86 insertions(+), 83 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/input-document-value-granular-user-permission/input-document-value-granular-user-permission.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/input-document-value-granular-user-permission/input-document-value-granular-user-permission.element.ts index 2591e57150d6..babdf0f6062c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/input-document-value-granular-user-permission/input-document-value-granular-user-permission.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/input-document-value-granular-user-permission/input-document-value-granular-user-permission.element.ts @@ -16,6 +16,7 @@ import { UMB_DOCUMENT_TYPE_PROPERTY_PICKER_MODAL, UmbDocumentTypeDetailRepository, UmbDocumentTypeItemRepository, + type UmbDocumentTypeDetailModel, type UmbDocumentTypeItemModel, type UmbDocumentTypeTreeItemModel, } from '@umbraco-cms/backoffice/document-type'; @@ -41,8 +42,10 @@ export class UmbInputDocumentValueGranularUserPermissionElement extends UUIFormC #documentTypeItemRepository = new UmbDocumentTypeItemRepository(this); #documentTypeDetailRepository = new UmbDocumentTypeDetailRepository(this); #modalManagerContext?: UmbModalManagerContext; - #documentTypePickerModalContext?: any; - #documentTypePropertyPickerModalContext?: any; + + #documentTypePickerModal?: any; + #propertyTypePickerModal?: any; + #entityUserPermissionModal?: any; constructor() { super(); @@ -82,7 +85,7 @@ export class UmbInputDocumentValueGranularUserPermissionElement extends UUIFormC */ async #addGranularPermission() { - this.#documentTypePickerModalContext = this.#modalManagerContext?.open(this, UMB_DOCUMENT_TYPE_PICKER_MODAL, { + this.#documentTypePickerModal = this.#modalManagerContext?.open(this, UMB_DOCUMENT_TYPE_PICKER_MODAL, { data: { hideTreeRoot: true, // prevent already selected items to be picked again @@ -91,97 +94,97 @@ export class UmbInputDocumentValueGranularUserPermissionElement extends UUIFormC }, }); - this.#documentTypePickerModalContext?.addEventListener(UmbSelectedEvent.TYPE, async (event: UmbSelectedEvent) => { - const selectedEvent = event as UmbSelectedEvent; - const documentTypeUnique = selectedEvent.unique; + this.#documentTypePickerModal?.onSubmit().catch(() => { + this.#documentTypePickerModal.value = []; + }); - if (!documentTypeUnique) { - throw new Error('Could not open Document type property modal, no unique was provided'); - } + this.#documentTypePickerModal?.addEventListener(UmbSelectedEvent.TYPE, async (event: UmbSelectedEvent) => + this.#onDocumentTypeSelected(event), + ); + } - this.#documentTypePropertyPickerModalContext = this.#modalManagerContext?.open( - this, - UMB_DOCUMENT_TYPE_PROPERTY_PICKER_MODAL, - { - data: { - documentType: { - unique: documentTypeUnique, - }, - }, - }, - ); - - this.#documentTypePropertyPickerModalContext?.addEventListener( - UmbSelectedEvent.TYPE, - async (event: UmbSelectedEvent) => { - const selectedEvent = event as UmbSelectedEvent; - const propertyTypeUnique = selectedEvent.unique; - - if (!propertyTypeUnique) { - throw new Error('Could not open permissions modal, no property alias was provided'); - } - - const { data: documentTypeDetails } = - await this.#documentTypeDetailRepository.requestByUnique(documentTypeUnique); - const property = documentTypeDetails?.properties.find((p) => p.unique === propertyTypeUnique); - - if (!property) { - throw new Error('Could not open permissions modal, no property was found'); - } - - this.#selectEntityUserPermissionsForProperty(property).then( - (result) => { - this.#documentTypePickerModalContext?.reject(); - this.#documentTypePropertyPickerModalContext?.reject(); - - const permissionItem: UmbDocumentValueUserPermissionModel = { - $type: 'DocumentValuePermissionPresentationModel', - documentType: { unique: documentTypeUnique }, - propertyType: { unique: propertyTypeUnique }, - verbs: result, - }; - - this.permissions = [...this._permissions, permissionItem]; - this.dispatchEvent(new UmbChangeEvent()); - }, - () => { - this.#documentTypePickerModalContext?.reject(); - }, - ); + #onDocumentTypeSelected(event: UmbSelectedEvent) { + const selectedEvent = event as UmbSelectedEvent; + const documentTypeUnique = selectedEvent.unique; + + if (!documentTypeUnique) { + throw new Error('Could not open Document type property modal, no unique was provided'); + } + + this.#propertyTypePickerModal = this.#modalManagerContext?.open(this, UMB_DOCUMENT_TYPE_PROPERTY_PICKER_MODAL, { + data: { + documentType: { + unique: documentTypeUnique, }, - ); + }, }); + + this.#propertyTypePickerModal?.addEventListener(UmbSelectedEvent.TYPE, (event: UmbSelectedEvent) => + this.#onPropertyTypeSelected(documentTypeUnique, event), + ); } - async #selectEntityUserPermissionsForProperty(property: UmbPropertyTypeModel, allowedVerbs: Array = []) { - // TODO: get correct variant name - const name = property.name; - const headline = name ? `Permissions for ${name}` : 'Permissions'; + async #onPropertyTypeSelected(documentTypeUnique: string, event: UmbSelectedEvent) { + const selectedEvent = event as UmbSelectedEvent; + const propertyTypeUnique = selectedEvent.unique; + + if (!propertyTypeUnique) { + throw new Error('Could not open permissions modal, no property alias was provided'); + } + + const { data: documentTypeDetails } = await this.#documentTypeDetailRepository.requestByUnique(documentTypeUnique); + + if (!documentTypeDetails) { + throw new Error('Could not open permissions modal, no document type was found'); + } + + const property = documentTypeDetails.properties.find((p) => p.unique === propertyTypeUnique); + + if (!property) { + throw new Error('Could not open permissions modal, no property was found'); + } + + this.#selectEntityUserPermissionsForProperty(documentTypeDetails, property) + .then((result) => { + this.#propertyTypePickerModal?.reject(); + this.#documentTypePickerModal?.reject(); + + const permissionItem: UmbDocumentValueUserPermissionModel = { + $type: 'DocumentValuePermissionPresentationModel', + documentType: { unique: documentTypeUnique }, + propertyType: { unique: propertyTypeUnique }, + verbs: result, + }; + + this.permissions = [...this._permissions, permissionItem]; + this.dispatchEvent(new UmbChangeEvent()); + }) + .catch(() => undefined); + } + + async #selectEntityUserPermissionsForProperty( + documentType: UmbDocumentTypeDetailModel, + propertyType: UmbPropertyTypeModel, + allowedVerbs: Array = [], + ) { + const headline = `Permissions for ${documentType.name}: ${propertyType.name}`; const fallbackVerbs = this.#getFallbackPermissionVerbsForEntityType('document-value'); - this.#documentTypePropertyPickerModalContext = this.#modalManagerContext?.open( - this, - UMB_ENTITY_USER_PERMISSION_MODAL, - { - data: { - entityType: 'document-value', - headline, - preset: { - allowedVerbs: fallbackVerbs, - }, - }, - value: { - allowedVerbs, + this.#entityUserPermissionModal = this.#modalManagerContext?.open(this, UMB_ENTITY_USER_PERMISSION_MODAL, { + data: { + entityType: 'document-value', + headline, + preset: { + allowedVerbs: fallbackVerbs, }, }, - ); + value: { + allowedVerbs, + }, + }); - try { - const value = await this.#documentTypePropertyPickerModalContext?.onSubmit(); - return value?.allowedVerbs; - } catch { - throw new Error(); - } + const value = await this.#entityUserPermissionModal?.onSubmit().catch(() => undefined); + return value?.allowedVerbs; } #removeGranularPermission(item: UmbDocumentTypeItemModel) { From 4e94ad94b38e1b16c7146aff758485c1c691987a Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 14 Mar 2025 22:01:06 +0100 Subject: [PATCH 033/106] wip modal flow --- .../documents/document-types/constants.ts | 1 - .../documents/document-types/index.ts | 1 - .../documents/document-types/manifests.ts | 2 - .../document-types/structure/constants.ts | 1 - .../document-types/structure/index.ts | 1 - .../document-types/structure/manifests.ts | 4 - .../property-type-picker-modal/constants.ts | 1 - ...type-property-type-picker-modal.element.ts | 106 ----------- ...t-type-property-type-picker-modal.token.ts | 22 --- .../property-type-picker-modal/index.ts | 1 - .../property-type-picker-modal/manifests.ts | 11 -- ...-granular-permission-flow-modal.element.ts | 96 ++++++++++ ...ue-granular-permission-flow-modal.token.ts | 26 +++ .../index.ts | 1 + .../manifests.ts | 12 ++ .../property-type-modal/constants.ts | 2 + .../property-type-modal/index.ts | 1 + .../property-type-modal/manifests.ts | 11 ++ .../property-type-modal.element.ts | 151 ++++++++++++++++ .../property-type-modal.token.ts | 26 +++ ...-value-granular-user-permission.element.ts | 165 +++--------------- .../document-value/manifests.ts | 2 + 22 files changed, 349 insertions(+), 295 deletions(-) delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/constants.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/index.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/manifests.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-type-picker-modal/constants.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-type-picker-modal/document-type-property-type-picker-modal.element.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-type-picker-modal/document-type-property-type-picker-modal.token.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-type-picker-modal/index.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-type-picker-modal/manifests.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/document-value-granular-permission-flow-modal.element.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/document-value-granular-permission-flow-modal.token.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/index.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/manifests.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/property-type-modal/constants.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/property-type-modal/index.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/property-type-modal/manifests.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/property-type-modal/property-type-modal.element.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/property-type-modal/property-type-modal.token.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/constants.ts index 18d226f5b8cb..ca74d4d4000e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/constants.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/constants.ts @@ -2,7 +2,6 @@ export * from './entity-actions/constants.js'; export * from './paths.js'; export * from './repository/constants.js'; export * from './search/constants.js'; -export * from './structure/constants.js'; export * from './tree/constants.js'; export * from './workspace/constants.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/index.ts index a9526fbaa6cd..429c4a3bfa08 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/index.ts @@ -4,7 +4,6 @@ export * from './components/index.js'; export * from './constants.js'; export * from './modals/index.js'; export * from './repository/index.js'; -export * from './structure/index.js'; export * from './workspace/index.js'; export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/manifests.ts index 8198e4695f3a..3562f9d6a7c9 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/manifests.ts @@ -3,7 +3,6 @@ import { manifests as menuManifests } from './menu/manifests.js'; import { manifests as propertyEditorManifests } from './property-editors/manifests.js'; import { manifests as repositoryManifests } from './repository/manifests.js'; import { manifests as searchManifests } from './search/manifests.js'; -import { manifests as structureManifests } from './structure/manifests.js'; import { manifests as treeManifests } from './tree/manifests.js'; import { manifests as workspaceManifests } from './workspace/manifests.js'; import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; @@ -14,7 +13,6 @@ export const manifests: Array = ...propertyEditorManifests, ...repositoryManifests, ...searchManifests, - ...structureManifests, ...treeManifests, ...workspaceManifests, ]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/constants.ts deleted file mode 100644 index 67d537b6b74a..000000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/constants.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './property-type-picker-modal/constants.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/index.ts deleted file mode 100644 index f5b29f018651..000000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './property-type-picker-modal/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/manifests.ts deleted file mode 100644 index a80467bc6ed3..000000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/manifests.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { manifests as propertyTypePickerModalManifests } from './property-type-picker-modal/manifests.js'; -import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; - -export const manifests: Array = [...propertyTypePickerModalManifests]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-type-picker-modal/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-type-picker-modal/constants.ts deleted file mode 100644 index 8920683ad5c1..000000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-type-picker-modal/constants.ts +++ /dev/null @@ -1 +0,0 @@ -export const UMB_DOCUMENT_TYPE_PROPERTY_TYPE_PICKER_MODAL_ALIAS = 'Umb.Modal.DocumentType.PropertyTypePicker'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-type-picker-modal/document-type-property-type-picker-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-type-picker-modal/document-type-property-type-picker-modal.element.ts deleted file mode 100644 index 5f07b817b2f8..000000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-type-picker-modal/document-type-property-type-picker-modal.element.ts +++ /dev/null @@ -1,106 +0,0 @@ -import { UmbDocumentTypeDetailRepository } from '../../repository/index.js'; -import type { - UmbDocumentTypePropertyTypePickerModalData, - UmbDocumentTypePropertyTypePickerModalValue, -} from './document-type-property-type-picker-modal.token.js'; -import { html, customElement, state, repeat } from '@umbraco-cms/backoffice/external/lit'; -import { UmbSelectionManager } from '@umbraco-cms/backoffice/utils'; -import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; -import type { UmbPropertyTypeModel } from '@umbraco-cms/backoffice/content-type'; -import { UmbDeselectedEvent, UmbSelectedEvent } from '@umbraco-cms/backoffice/event'; - -@customElement('umb-document-type-property-picker-modal') -export class UmbDocumentTypePropertyPickerModalElement extends UmbModalBaseElement< - UmbDocumentTypePropertyTypePickerModalData, - UmbDocumentTypePropertyTypePickerModalValue -> { - @state() - private _properties: Array = []; - - #detailRepository = new UmbDocumentTypeDetailRepository(this); - #selectionManager = new UmbSelectionManager(this); - - override connectedCallback(): void { - super.connectedCallback(); - this.#selectionManager.setSelectable(true); - this.#selectionManager.setMultiple(this.data?.multiple ?? false); - this.#selectionManager.setSelection(this.value?.selection ?? []); - - this.observe(this.#selectionManager.selection, (selection) => { - this.value = { selection }; - }); - } - - #onItemSelected(event: CustomEvent, item: UmbPropertyTypeModel) { - event.stopPropagation(); - this.#selectionManager.select(item.unique); - this.modalContext?.dispatchEvent(new UmbSelectedEvent(item.unique)); - } - - #onItemDeselected(event: CustomEvent, item: UmbPropertyTypeModel) { - event.stopPropagation(); - this.#selectionManager.deselect(item.unique); - this.modalContext?.dispatchEvent(new UmbDeselectedEvent(item.unique)); - } - - override async firstUpdated() { - if (!this.data?.documentType?.unique) { - throw new Error('Document type unique is required'); - } - - const { data } = await this.#detailRepository.requestByUnique(this.data.documentType.unique); - this._properties = data?.properties ?? []; - } - - get #filteredProperties() { - if (this.data?.filter) { - return this._properties.filter(this.data.filter); - } else { - return this._properties; - } - } - - #getItemDetail(item: UmbPropertyTypeModel): string { - const isMandatory = item.validation?.mandatory ? ' - Mandatory' : ''; - const variesByCulture = item.variesByCulture ? ' - Varies by culture' : ''; - const variesBySegment = item.variesBySegment ? ' - Varies by segment' : ''; - return `${item.alias} ${isMandatory} ${variesByCulture} ${variesBySegment}`; - } - - override render() { - return html` - - ${this.#filteredProperties.length > 0 - ? repeat( - this.#filteredProperties, - (item) => item.unique, - (item) => html` - this.#onItemSelected(event, item)} - @deselected=${(event: CustomEvent) => this.#onItemDeselected(event, item)} - ?selected=${this.value.selection.includes(item.unique)}> - - - `, - ) - : html`There are no properties to choose from.`} - -
- - -
-
`; - } -} - -export { UmbDocumentTypePropertyPickerModalElement as element }; - -declare global { - interface HTMLElementTagNameMap { - 'umb-document-type-property-picker-modal': UmbDocumentTypePropertyPickerModalElement; - } -} diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-type-picker-modal/document-type-property-type-picker-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-type-picker-modal/document-type-property-type-picker-modal.token.ts deleted file mode 100644 index 29122ccaf40d..000000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-type-picker-modal/document-type-property-type-picker-modal.token.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { UMB_DOCUMENT_TYPE_PROPERTY_TYPE_PICKER_MODAL_ALIAS } from './constants.js'; -import type { UmbPropertyTypeModel } from '@umbraco-cms/backoffice/content-type'; -import { UmbModalToken, type UmbPickerModalData, type UmbPickerModalValue } from '@umbraco-cms/backoffice/modal'; - -export interface UmbDocumentTypePropertyTypePickerModalData extends UmbPickerModalData { - documentType: { - unique: string; - }; -} - -// eslint-disable-next-line @typescript-eslint/no-empty-object-type -export interface UmbDocumentTypePropertyTypePickerModalValue extends UmbPickerModalValue {} - -export const UMB_DOCUMENT_TYPE_PROPERTY_PICKER_MODAL = new UmbModalToken< - UmbDocumentTypePropertyTypePickerModalData, - UmbDocumentTypePropertyTypePickerModalValue ->(UMB_DOCUMENT_TYPE_PROPERTY_TYPE_PICKER_MODAL_ALIAS, { - modal: { - type: 'sidebar', - size: 'small', - }, -}); diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-type-picker-modal/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-type-picker-modal/index.ts deleted file mode 100644 index 58e15a35fa67..000000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-type-picker-modal/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { UMB_DOCUMENT_TYPE_PROPERTY_PICKER_MODAL } from './document-type-property-type-picker-modal.token.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-type-picker-modal/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-type-picker-modal/manifests.ts deleted file mode 100644 index d6ad8ffc496b..000000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/structure/property-type-picker-modal/manifests.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { UMB_DOCUMENT_TYPE_PROPERTY_TYPE_PICKER_MODAL_ALIAS } from './constants.js'; -import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; - -export const manifests: Array = [ - { - type: 'modal', - alias: UMB_DOCUMENT_TYPE_PROPERTY_TYPE_PICKER_MODAL_ALIAS, - name: 'Document Type Property Type Picker Modal', - element: () => import('./document-type-property-type-picker-modal.element.js'), - }, -]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/document-value-granular-permission-flow-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/document-value-granular-permission-flow-modal.element.ts new file mode 100644 index 000000000000..bd8d6a3f82f0 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/document-value-granular-permission-flow-modal.element.ts @@ -0,0 +1,96 @@ +import { UMB_DOCUMENT_VALUE_GRANULAR_USER_PERMISSION_FLOW_PROPERTY_TYPE_MODAL } from './property-type-modal/property-type-modal.token.js'; +import type { + UmbDocumentValueGranularUserPermissionFlowModalData, + UmbDocumentValueGranularUserPermissionFlowModalValue, +} from './document-value-granular-permission-flow-modal.token.js'; +import { html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; +import { UMB_MODAL_MANAGER_CONTEXT, UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; +import { UMB_DOCUMENT_TYPE_TREE_ALIAS } from '@umbraco-cms/backoffice/document-type'; +import type { UmbSelectionChangeEvent } from '@umbraco-cms/backoffice/event'; +import type { UmbTreeElement } from '@umbraco-cms/backoffice/tree'; + +@customElement('umb-document-value-granular-user-permission-flow-modal') +export class UmbDocumentValueGranularUserPermissionFlowModalElement extends UmbModalBaseElement< + UmbDocumentValueGranularUserPermissionFlowModalData, + UmbDocumentValueGranularUserPermissionFlowModalValue +> { + @state() + _documentTypeUnique?: string; + + async #next() { + if (!this._documentTypeUnique) { + throw new Error('No document type selected'); + } + + const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT); + if (!modalManager) { + throw new Error('Could not get modal manager context'); + } + + const modal = modalManager.open(this, UMB_DOCUMENT_VALUE_GRANULAR_USER_PERMISSION_FLOW_PROPERTY_TYPE_MODAL, { + data: { + documentType: { + unique: this._documentTypeUnique, + }, + }, + }); + + try { + const value = await modal.onSubmit(); + + this.updateValue({ + documentType: { + unique: this._documentTypeUnique, + }, + propertyType: value.propertyType, + verbs: value.verbs, + }); + + this._submitModal(); + } catch (error) { + console.error(error); + } + } + + #onTreeSelectionChange(event: UmbSelectionChangeEvent) { + const target = event.target as UmbTreeElement; + const selection = target.getSelection(); + this._documentTypeUnique = selection[0]; + } + + override render() { + return html` + + + + !this._items?.map((i) => i.unique).includes(treeItem.unique), + */ + }} + alias=${UMB_DOCUMENT_TYPE_TREE_ALIAS}> + +
+ + +
+
+ `; + } +} + +export { UmbDocumentValueGranularUserPermissionFlowModalElement as element }; + +declare global { + interface HTMLElementTagNameMap { + 'umb-document-value-granular-user-permission-flow-modal': UmbDocumentValueGranularUserPermissionFlowModalElement; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/document-value-granular-permission-flow-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/document-value-granular-permission-flow-modal.token.ts new file mode 100644 index 000000000000..74edc6c75af3 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/document-value-granular-permission-flow-modal.token.ts @@ -0,0 +1,26 @@ +import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; + +// eslint-disable-next-line @typescript-eslint/no-empty-object-type +export interface UmbDocumentValueGranularUserPermissionFlowModalData { + preset?: UmbDocumentValueGranularUserPermissionFlowModalValue; +} + +export interface UmbDocumentValueGranularUserPermissionFlowModalValue { + documentType: { + unique: string; + }; + propertyType: { + unique: string; + }; + verbs: Array; +} + +export const UMB_DOCUMENT_VALUE_GRANULAR_USER_PERMISSION_FLOW_MODAL = new UmbModalToken< + UmbDocumentValueGranularUserPermissionFlowModalData, + UmbDocumentValueGranularUserPermissionFlowModalValue +>('Umb.Modal.DocumentValueGranularUserPermissionFlow', { + modal: { + type: 'sidebar', + size: 'small', + }, +}); diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/index.ts new file mode 100644 index 000000000000..f1ea72a84b7f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/index.ts @@ -0,0 +1 @@ +export { UMB_DOCUMENT_VALUE_GRANULAR_USER_PERMISSION_FLOW_MODAL } from './document-value-granular-permission-flow-modal.token.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/manifests.ts new file mode 100644 index 000000000000..86d550370e5d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/manifests.ts @@ -0,0 +1,12 @@ +import { manifests as propertyTypeModalManifests } from './property-type-modal/manifests.js'; +import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'modal', + alias: 'Umb.Modal.DocumentValueGranularUserPermissionFlow', + name: 'Document Value Granular User Permission Flow Modal', + element: () => import('./document-value-granular-permission-flow-modal.element.js'), + }, + ...propertyTypeModalManifests, +]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/property-type-modal/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/property-type-modal/constants.ts new file mode 100644 index 000000000000..5282128b74cc --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/property-type-modal/constants.ts @@ -0,0 +1,2 @@ +export const UMB_DOCUMENT_VALUE_GRANULAR_USER_PERMISSION_FLOW_PROPERTY_TYPE_MODAL_ALIAS = + 'Umb.Modal.DocumentValueGranularUserPermissionFlow.PropertyType'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/property-type-modal/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/property-type-modal/index.ts new file mode 100644 index 000000000000..8520671d94d1 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/property-type-modal/index.ts @@ -0,0 +1 @@ +export { UMB_DOCUMENT_VALUE_GRANULAR_USER_PERMISSION_FLOW_PROPERTY_TYPE_MODAL } from './property-type-modal.token.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/property-type-modal/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/property-type-modal/manifests.ts new file mode 100644 index 000000000000..c8a330632b97 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/property-type-modal/manifests.ts @@ -0,0 +1,11 @@ +import { UMB_DOCUMENT_VALUE_GRANULAR_USER_PERMISSION_FLOW_PROPERTY_TYPE_MODAL_ALIAS } from './constants.js'; +import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'modal', + alias: UMB_DOCUMENT_VALUE_GRANULAR_USER_PERMISSION_FLOW_PROPERTY_TYPE_MODAL_ALIAS, + name: 'Document Value Granular User Permission Flow Property Type Modal', + element: () => import('./property-type-modal.element.js'), + }, +]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/property-type-modal/property-type-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/property-type-modal/property-type-modal.element.ts new file mode 100644 index 000000000000..63906f887564 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/property-type-modal/property-type-modal.element.ts @@ -0,0 +1,151 @@ +import type { + UmbDocumentValueGranularUserPermissionFlowPropertyTypeModalData, + UmbDocumentValueGranularUserPermissionFlowPropertyTypeModalValue, +} from './property-type-modal.token.js'; +import { html, customElement, state, repeat } from '@umbraco-cms/backoffice/external/lit'; +import { UMB_MODAL_MANAGER_CONTEXT, UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; +import type { UmbPropertyTypeModel } from '@umbraco-cms/backoffice/content-type'; +import { UmbDocumentTypeDetailRepository } from '@umbraco-cms/backoffice/document-type'; +import { UMB_ENTITY_USER_PERMISSION_MODAL } from '@umbraco-cms/backoffice/user-permission'; + +@customElement('umb-document-value-granular-user-permission-flow-property-type-modal') +export class UmbDocumentValueGranularUserPermissionFlowPropertyTypeModalElement extends UmbModalBaseElement< + UmbDocumentValueGranularUserPermissionFlowPropertyTypeModalData, + UmbDocumentValueGranularUserPermissionFlowPropertyTypeModalValue +> { + @state() + private _documentTypeProperties: Array = []; + + @state() + private _documentTypeName?: string; + + @state() + _selectedItem: UmbPropertyTypeModel | null = null; + + #detailRepository = new UmbDocumentTypeDetailRepository(this); + + #onItemSelected(event: CustomEvent, item: UmbPropertyTypeModel) { + event.stopPropagation(); + this._selectedItem = item; + } + + #onItemDeselected(event: CustomEvent) { + event.stopPropagation(); + this._selectedItem = null; + } + + override async firstUpdated() { + if (!this.data?.documentType?.unique) { + throw new Error('Document type unique is required'); + } + + const { data } = await this.#detailRepository.requestByUnique(this.data.documentType.unique); + this._documentTypeProperties = data?.properties ?? []; + this._documentTypeName = data?.name; + } + + #getItemDetail(item: UmbPropertyTypeModel): string { + const isMandatory = item.validation?.mandatory ? ' - Mandatory' : ''; + const variesByCulture = item.variesByCulture ? ' - Varies by culture' : ''; + const variesBySegment = item.variesBySegment ? ' - Varies by segment' : ''; + return `${item.alias} ${isMandatory} ${variesByCulture} ${variesBySegment}`; + } + + #next() { + if (!this._selectedItem) { + throw new Error('Could not proceed, no property was selected'); + } + + this.#selectEntityUserPermissionsForProperty(); + } + + async #selectEntityUserPermissionsForProperty() { + if (!this._selectedItem) { + throw new Error('Could not open permissions modal, no property was provided'); + } + + const headline = `Permissions for ${this._documentTypeName}: ${this._selectedItem.name}`; + + const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT); + if (!modalManager) { + throw new Error('Could not open permissions modal, modal manager is not available'); + } + + const modal = modalManager.open(this, UMB_ENTITY_USER_PERMISSION_MODAL, { + data: { + entityType: 'document-value', + headline, + }, + }); + + try { + const value = await modal.onSubmit(); + this.updateValue({ + propertyType: { unique: this._selectedItem.unique }, + verbs: value.allowedVerbs, + }); + this._submitModal(); + } catch (error) { + console.log(error); + } + } + + /* + async #editGranularPermission(item: UmbDocumentTypeItemModel) { + const currentPermissionVerbs = this.#getPermissionForDocumentType(item.unique)?.verbs ?? []; + const result = await this.#selectEntityUserPermissionsForDocumentType(item, currentPermissionVerbs); + // don't do anything if the verbs have not been updated + if (JSON.stringify(result) === JSON.stringify(currentPermissionVerbs)) return; + + // update permission with new verbs + this.permissions = this._permissions.map((permission) => { + if (permission.documentType.unique === item.unique) { + return { + ...permission, + verbs: result, + }; + } + return permission; + }); + + this.dispatchEvent(new UmbChangeEvent()); + } + */ + + override render() { + return html` + + ${this._documentTypeProperties.length > 0 + ? repeat( + this._documentTypeProperties, + (item) => item.unique, + (item) => html` + this.#onItemSelected(event, item)} + @deselected=${(event: CustomEvent) => this.#onItemDeselected(event)} + ?selected=${this._selectedItem?.unique === item.unique}> + + + `, + ) + : html`There are no properties to choose from.`} + +
+ + +
+
`; + } +} + +export { UmbDocumentValueGranularUserPermissionFlowPropertyTypeModalElement as element }; + +declare global { + interface HTMLElementTagNameMap { + 'umb-document-value-granular-user-permission-flow-property-type-modal': UmbDocumentValueGranularUserPermissionFlowPropertyTypeModalElement; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/property-type-modal/property-type-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/property-type-modal/property-type-modal.token.ts new file mode 100644 index 000000000000..2598fcfb2370 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/property-type-modal/property-type-modal.token.ts @@ -0,0 +1,26 @@ +import { UMB_DOCUMENT_VALUE_GRANULAR_USER_PERMISSION_FLOW_PROPERTY_TYPE_MODAL_ALIAS } from './constants.js'; +import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; + +export interface UmbDocumentValueGranularUserPermissionFlowPropertyTypeModalData { + documentType: { + unique: string; + }; + preset?: UmbDocumentValueGranularUserPermissionFlowPropertyTypeModalValue; +} + +export interface UmbDocumentValueGranularUserPermissionFlowPropertyTypeModalValue { + propertyType: { + unique: string; + }; + verbs: Array; +} + +export const UMB_DOCUMENT_VALUE_GRANULAR_USER_PERMISSION_FLOW_PROPERTY_TYPE_MODAL = new UmbModalToken< + UmbDocumentValueGranularUserPermissionFlowPropertyTypeModalData, + UmbDocumentValueGranularUserPermissionFlowPropertyTypeModalValue +>(UMB_DOCUMENT_VALUE_GRANULAR_USER_PERMISSION_FLOW_PROPERTY_TYPE_MODAL_ALIAS, { + modal: { + type: 'sidebar', + size: 'small', + }, +}); diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/input-document-value-granular-user-permission/input-document-value-granular-user-permission.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/input-document-value-granular-user-permission/input-document-value-granular-user-permission.element.ts index babdf0f6062c..86a1bc582855 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/input-document-value-granular-user-permission/input-document-value-granular-user-permission.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/input-document-value-granular-user-permission/input-document-value-granular-user-permission.element.ts @@ -1,25 +1,13 @@ import type { UmbDocumentValueUserPermissionModel } from '../types.js'; +import { UMB_DOCUMENT_VALUE_GRANULAR_USER_PERMISSION_FLOW_MODAL } from '../document-value-granular-permission-flow-modal/index.js'; import { css, customElement, html, property, repeat, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -import type { UmbModalManagerContext } from '@umbraco-cms/backoffice/modal'; import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; -import { UmbChangeEvent, UmbSelectedEvent } from '@umbraco-cms/backoffice/event'; import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; import { UUIFormControlMixin } from '@umbraco-cms/backoffice/external/uui'; -import { - UMB_ENTITY_USER_PERMISSION_MODAL, - type ManifestEntityUserPermission, -} from '@umbraco-cms/backoffice/user-permission'; -import type { UmbPropertyTypeModel } from '@umbraco-cms/backoffice/content-type'; -import { - UMB_DOCUMENT_TYPE_PICKER_MODAL, - UMB_DOCUMENT_TYPE_PROPERTY_PICKER_MODAL, - UmbDocumentTypeDetailRepository, - UmbDocumentTypeItemRepository, - type UmbDocumentTypeDetailModel, - type UmbDocumentTypeItemModel, - type UmbDocumentTypeTreeItemModel, -} from '@umbraco-cms/backoffice/document-type'; +import type { ManifestEntityUserPermission } from '@umbraco-cms/backoffice/user-permission'; +import { UmbDocumentTypeItemRepository, type UmbDocumentTypeItemModel } from '@umbraco-cms/backoffice/document-type'; +import { UmbChangeEvent } from '@umbraco-cms/backoffice/event'; @customElement('umb-document-value-granular-user-permission') export class UmbInputDocumentValueGranularUserPermissionElement extends UUIFormControlMixin(UmbLitElement, '') { @@ -40,18 +28,6 @@ export class UmbInputDocumentValueGranularUserPermissionElement extends UUIFormC private _items?: Array; #documentTypeItemRepository = new UmbDocumentTypeItemRepository(this); - #documentTypeDetailRepository = new UmbDocumentTypeDetailRepository(this); - #modalManagerContext?: UmbModalManagerContext; - - #documentTypePickerModal?: any; - #propertyTypePickerModal?: any; - #entityUserPermissionModal?: any; - - constructor() { - super(); - - this.consumeContext(UMB_MODAL_MANAGER_CONTEXT, (instance) => (this.#modalManagerContext = instance)); - } protected override getFormElement() { return undefined; @@ -62,129 +38,30 @@ export class UmbInputDocumentValueGranularUserPermissionElement extends UUIFormC this.observe(asObservable(), (items) => (this._items = items)); } - /* - async #editGranularPermission(item: UmbDocumentTypeItemModel) { - const currentPermissionVerbs = this.#getPermissionForDocumentType(item.unique)?.verbs ?? []; - const result = await this.#selectEntityUserPermissionsForDocumentType(item, currentPermissionVerbs); - // don't do anything if the verbs have not been updated - if (JSON.stringify(result) === JSON.stringify(currentPermissionVerbs)) return; - - // update permission with new verbs - this.permissions = this._permissions.map((permission) => { - if (permission.documentType.unique === item.unique) { - return { - ...permission, - verbs: result, - }; - } - return permission; - }); - - this.dispatchEvent(new UmbChangeEvent()); - } - */ - async #addGranularPermission() { - this.#documentTypePickerModal = this.#modalManagerContext?.open(this, UMB_DOCUMENT_TYPE_PICKER_MODAL, { - data: { - hideTreeRoot: true, - // prevent already selected items to be picked again - pickableFilter: (treeItem: UmbDocumentTypeTreeItemModel) => - !this._items?.map((i) => i.unique).includes(treeItem.unique), - }, - }); - - this.#documentTypePickerModal?.onSubmit().catch(() => { - this.#documentTypePickerModal.value = []; - }); - - this.#documentTypePickerModal?.addEventListener(UmbSelectedEvent.TYPE, async (event: UmbSelectedEvent) => - this.#onDocumentTypeSelected(event), - ); - } - - #onDocumentTypeSelected(event: UmbSelectedEvent) { - const selectedEvent = event as UmbSelectedEvent; - const documentTypeUnique = selectedEvent.unique; - - if (!documentTypeUnique) { - throw new Error('Could not open Document type property modal, no unique was provided'); + const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT); + if (!modalManager) { + throw new Error('Could not open modal, no modal manager found'); } - this.#propertyTypePickerModal = this.#modalManagerContext?.open(this, UMB_DOCUMENT_TYPE_PROPERTY_PICKER_MODAL, { - data: { - documentType: { - unique: documentTypeUnique, - }, - }, - }); + const modal = modalManager.open(this, UMB_DOCUMENT_VALUE_GRANULAR_USER_PERMISSION_FLOW_MODAL); - this.#propertyTypePickerModal?.addEventListener(UmbSelectedEvent.TYPE, (event: UmbSelectedEvent) => - this.#onPropertyTypeSelected(documentTypeUnique, event), - ); - } - - async #onPropertyTypeSelected(documentTypeUnique: string, event: UmbSelectedEvent) { - const selectedEvent = event as UmbSelectedEvent; - const propertyTypeUnique = selectedEvent.unique; - - if (!propertyTypeUnique) { - throw new Error('Could not open permissions modal, no property alias was provided'); - } + try { + const value = await modal?.onSubmit(); + if (!value) throw new Error('No result from modal'); - const { data: documentTypeDetails } = await this.#documentTypeDetailRepository.requestByUnique(documentTypeUnique); + const permissionItem: UmbDocumentValueUserPermissionModel = { + $type: 'DocumentValuePermissionPresentationModel', + documentType: value.documentType, + propertyType: value.propertyType, + verbs: value.verbs, + }; - if (!documentTypeDetails) { - throw new Error('Could not open permissions modal, no document type was found'); + this.permissions = [...this._permissions, permissionItem]; + this.dispatchEvent(new UmbChangeEvent()); + } catch (error) { + console.error(error); } - - const property = documentTypeDetails.properties.find((p) => p.unique === propertyTypeUnique); - - if (!property) { - throw new Error('Could not open permissions modal, no property was found'); - } - - this.#selectEntityUserPermissionsForProperty(documentTypeDetails, property) - .then((result) => { - this.#propertyTypePickerModal?.reject(); - this.#documentTypePickerModal?.reject(); - - const permissionItem: UmbDocumentValueUserPermissionModel = { - $type: 'DocumentValuePermissionPresentationModel', - documentType: { unique: documentTypeUnique }, - propertyType: { unique: propertyTypeUnique }, - verbs: result, - }; - - this.permissions = [...this._permissions, permissionItem]; - this.dispatchEvent(new UmbChangeEvent()); - }) - .catch(() => undefined); - } - - async #selectEntityUserPermissionsForProperty( - documentType: UmbDocumentTypeDetailModel, - propertyType: UmbPropertyTypeModel, - allowedVerbs: Array = [], - ) { - const headline = `Permissions for ${documentType.name}: ${propertyType.name}`; - const fallbackVerbs = this.#getFallbackPermissionVerbsForEntityType('document-value'); - - this.#entityUserPermissionModal = this.#modalManagerContext?.open(this, UMB_ENTITY_USER_PERMISSION_MODAL, { - data: { - entityType: 'document-value', - headline, - preset: { - allowedVerbs: fallbackVerbs, - }, - }, - value: { - allowedVerbs, - }, - }); - - const value = await this.#entityUserPermissionModal?.onSubmit().catch(() => undefined); - return value?.allowedVerbs; } #removeGranularPermission(item: UmbDocumentTypeItemModel) { diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/manifests.ts index c80f66e4512f..582f7b779022 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/manifests.ts @@ -1,4 +1,5 @@ import { UMB_USER_PERMISSION_DOCUMENT_VALUE_READ, UMB_USER_PERMISSION_DOCUMENT_VALUE_WRITE } from './constants.js'; +import { manifests as documentValueGranularPermissionFlowModalManifests } from './document-value-granular-permission-flow-modal/manifests.js'; import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; export const manifests: Array = [ @@ -40,4 +41,5 @@ export const manifests: Array = description: 'Assign Permissions to Document values', }, }, + ...documentValueGranularPermissionFlowModalManifests, ]; From 8e882c583110ee391817bd9198d7389c09d1b0f4 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 14 Mar 2025 22:12:26 +0100 Subject: [PATCH 034/106] clean up --- ...-granular-permission-flow-modal.element.ts | 22 ++++++++----------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/document-value-granular-permission-flow-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/document-value-granular-permission-flow-modal.element.ts index bd8d6a3f82f0..0141ba8d0de1 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/document-value-granular-permission-flow-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/document-value-granular-permission-flow-modal.element.ts @@ -15,13 +15,15 @@ export class UmbDocumentValueGranularUserPermissionFlowModalElement extends UmbM UmbDocumentValueGranularUserPermissionFlowModalValue > { @state() - _documentTypeUnique?: string; + _selection: Array = []; async #next() { - if (!this._documentTypeUnique) { + if (this._selection.length === 0) { throw new Error('No document type selected'); } + const documentType = { unique: this._selection[0] }; + const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT); if (!modalManager) { throw new Error('Could not get modal manager context'); @@ -29,9 +31,7 @@ export class UmbDocumentValueGranularUserPermissionFlowModalElement extends UmbM const modal = modalManager.open(this, UMB_DOCUMENT_VALUE_GRANULAR_USER_PERMISSION_FLOW_PROPERTY_TYPE_MODAL, { data: { - documentType: { - unique: this._documentTypeUnique, - }, + documentType, }, }); @@ -39,23 +39,19 @@ export class UmbDocumentValueGranularUserPermissionFlowModalElement extends UmbM const value = await modal.onSubmit(); this.updateValue({ - documentType: { - unique: this._documentTypeUnique, - }, + documentType, propertyType: value.propertyType, verbs: value.verbs, }); this._submitModal(); - } catch (error) { - console.error(error); - } + } catch {} } #onTreeSelectionChange(event: UmbSelectionChangeEvent) { const target = event.target as UmbTreeElement; const selection = target.getSelection(); - this._documentTypeUnique = selection[0]; + this._selection = [...selection]; } override render() { @@ -80,7 +76,7 @@ export class UmbDocumentValueGranularUserPermissionFlowModalElement extends UmbM look="primary" color="positive" @click=${this.#next} - ?disabled=${!this._documentTypeUnique}> + ?disabled=${this._selection.length === 0}>
`; From 038fd4be83a46feaed30882094fa03ace5730b02 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 14 Mar 2025 22:17:37 +0100 Subject: [PATCH 035/106] add headlines --- ...-granular-permission-flow-modal.element.ts | 2 +- .../property-type-modal.element.ts | 31 +++++-------------- 2 files changed, 8 insertions(+), 25 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/document-value-granular-permission-flow-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/document-value-granular-permission-flow-modal.element.ts index 0141ba8d0de1..3de93c7581ac 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/document-value-granular-permission-flow-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/document-value-granular-permission-flow-modal.element.ts @@ -56,7 +56,7 @@ export class UmbDocumentValueGranularUserPermissionFlowModalElement extends UmbM override render() { return html` - + { - if (permission.documentType.unique === item.unique) { - return { - ...permission, - verbs: result, - }; - } - return permission; - }); - - this.dispatchEvent(new UmbChangeEvent()); - } - */ - override render() { - return html` + return html` ${this._documentTypeProperties.length > 0 ? repeat( @@ -136,7 +114,12 @@ export class UmbDocumentValueGranularUserPermissionFlowPropertyTypeModalElement
- +
`; } From 526b09eafd590015bf0ac5975d68f2718296427b Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 17 Mar 2025 08:36:49 +0100 Subject: [PATCH 036/106] hide actions --- .../document-value-granular-permission-flow-modal.element.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/document-value-granular-permission-flow-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/document-value-granular-permission-flow-modal.element.ts index 3de93c7581ac..509f207464c6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/document-value-granular-permission-flow-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/document-value-granular-permission-flow-modal.element.ts @@ -62,6 +62,7 @@ export class UmbDocumentValueGranularUserPermissionFlowModalElement extends UmbM @selection-change=${this.#onTreeSelectionChange} .props=${{ hideTreeRoot: true, + hideTreeItemActions: true, /* pickableFilter: (treeItem: UmbDocumentTypeTreeItemModel) => !this._items?.map((i) => i.unique).includes(treeItem.unique), From 0f77ca24ac7da631775f5df8ce7c7fa503266afd Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 17 Mar 2025 08:49:53 +0100 Subject: [PATCH 037/106] pass preset value --- ...cument-value-granular-permission-flow-modal.element.ts | 3 +++ ...document-value-granular-permission-flow-modal.token.ts | 2 +- .../property-type-modal/property-type-modal.element.ts | 3 +++ .../property-type-modal/property-type-modal.token.ts | 2 +- ...put-document-value-granular-user-permission.element.ts | 8 +++++++- 5 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/document-value-granular-permission-flow-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/document-value-granular-permission-flow-modal.element.ts index 509f207464c6..588fce3f3e79 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/document-value-granular-permission-flow-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/document-value-granular-permission-flow-modal.element.ts @@ -32,6 +32,9 @@ export class UmbDocumentValueGranularUserPermissionFlowModalElement extends UmbM const modal = modalManager.open(this, UMB_DOCUMENT_VALUE_GRANULAR_USER_PERMISSION_FLOW_PROPERTY_TYPE_MODAL, { data: { documentType, + preset: { + verbs: this.data?.preset?.verbs, + }, }, }); diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/document-value-granular-permission-flow-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/document-value-granular-permission-flow-modal.token.ts index 74edc6c75af3..a08b9de75fe2 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/document-value-granular-permission-flow-modal.token.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/document-value-granular-permission-flow-modal.token.ts @@ -2,7 +2,7 @@ import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; // eslint-disable-next-line @typescript-eslint/no-empty-object-type export interface UmbDocumentValueGranularUserPermissionFlowModalData { - preset?: UmbDocumentValueGranularUserPermissionFlowModalValue; + preset?: Partial; } export interface UmbDocumentValueGranularUserPermissionFlowModalValue { diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/property-type-modal/property-type-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/property-type-modal/property-type-modal.element.ts index e87d9e1f0b68..fc6d0c3f2a6b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/property-type-modal/property-type-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/property-type-modal/property-type-modal.element.ts @@ -75,6 +75,9 @@ export class UmbDocumentValueGranularUserPermissionFlowPropertyTypeModalElement data: { entityType: 'document-value', headline, + preset: { + allowedVerbs: this.data?.preset?.verbs ?? [], + }, }, }); diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/property-type-modal/property-type-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/property-type-modal/property-type-modal.token.ts index 2598fcfb2370..ba748ce4cbed 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/property-type-modal/property-type-modal.token.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/property-type-modal/property-type-modal.token.ts @@ -5,7 +5,7 @@ export interface UmbDocumentValueGranularUserPermissionFlowPropertyTypeModalData documentType: { unique: string; }; - preset?: UmbDocumentValueGranularUserPermissionFlowPropertyTypeModalValue; + preset?: Partial; } export interface UmbDocumentValueGranularUserPermissionFlowPropertyTypeModalValue { diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/input-document-value-granular-user-permission/input-document-value-granular-user-permission.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/input-document-value-granular-user-permission/input-document-value-granular-user-permission.element.ts index 86a1bc582855..cf5f3eef1fef 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/input-document-value-granular-user-permission/input-document-value-granular-user-permission.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/input-document-value-granular-user-permission/input-document-value-granular-user-permission.element.ts @@ -44,7 +44,13 @@ export class UmbInputDocumentValueGranularUserPermissionElement extends UUIFormC throw new Error('Could not open modal, no modal manager found'); } - const modal = modalManager.open(this, UMB_DOCUMENT_VALUE_GRANULAR_USER_PERMISSION_FLOW_MODAL); + const modal = modalManager.open(this, UMB_DOCUMENT_VALUE_GRANULAR_USER_PERMISSION_FLOW_MODAL, { + data: { + preset: { + verbs: this.#getFallbackPermissionVerbsForEntityType('document-value'), + }, + }, + }); try { const value = await modal?.onSubmit(); From 3dfa4afab02bb611d89c9edb5dba52f3178e5de3 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 17 Mar 2025 09:42:32 +0100 Subject: [PATCH 038/106] add edit permission method --- ...-value-granular-user-permission.element.ts | 184 ++++++++++++------ 1 file changed, 125 insertions(+), 59 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/input-document-value-granular-user-permission/input-document-value-granular-user-permission.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/input-document-value-granular-user-permission/input-document-value-granular-user-permission.element.ts index cf5f3eef1fef..c7cecacb7ff4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/input-document-value-granular-user-permission/input-document-value-granular-user-permission.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/input-document-value-granular-user-permission/input-document-value-granular-user-permission.element.ts @@ -5,8 +5,14 @@ import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; import { UUIFormControlMixin } from '@umbraco-cms/backoffice/external/uui'; -import type { ManifestEntityUserPermission } from '@umbraco-cms/backoffice/user-permission'; -import { UmbDocumentTypeItemRepository, type UmbDocumentTypeItemModel } from '@umbraco-cms/backoffice/document-type'; +import { + UMB_ENTITY_USER_PERMISSION_MODAL, + type ManifestEntityUserPermission, +} from '@umbraco-cms/backoffice/user-permission'; +import { + UmbDocumentTypeDetailRepository, + type UmbDocumentTypeDetailModel, +} from '@umbraco-cms/backoffice/document-type'; import { UmbChangeEvent } from '@umbraco-cms/backoffice/event'; @customElement('umb-document-value-granular-user-permission') @@ -25,17 +31,23 @@ export class UmbInputDocumentValueGranularUserPermissionElement extends UUIFormC fallbackPermissions: Array = []; @state() - private _items?: Array; + private _documentTypes?: Array; - #documentTypeItemRepository = new UmbDocumentTypeItemRepository(this); + #documentTypeDetailRepository = new UmbDocumentTypeDetailRepository(this); protected override getFormElement() { return undefined; } async #observePickedDocumentTypes(uniques: Array) { - const { asObservable } = await this.#documentTypeItemRepository.requestItems(uniques); - this.observe(asObservable(), (items) => (this._items = items)); + const promises = uniques.map((unique) => this.#documentTypeDetailRepository.requestByUnique(unique)); + const responses = await Promise.allSettled(promises); + + // TODO: handle errors + this._documentTypes = responses + .filter((response) => response.status === 'fulfilled') + .map((response) => response.value.data) + .filter((item) => item) as Array; } async #addGranularPermission() { @@ -70,70 +82,67 @@ export class UmbInputDocumentValueGranularUserPermissionElement extends UUIFormC } } - #removeGranularPermission(item: UmbDocumentTypeItemModel) { - const permission = this.#getPermissionForDocumentType(item.unique); - if (!permission) return; + async #editGranularPermission(currentPermission: UmbDocumentValueUserPermissionModel) { + if (!currentPermission) { + throw new Error('Could not open permissions modal, no item was provided'); + } - this.permissions = this._permissions.filter((v) => JSON.stringify(v) !== JSON.stringify(permission)); - this.dispatchEvent(new UmbChangeEvent()); - } + const documentType = this._documentTypes?.find((item) => item.unique === currentPermission.documentType.unique); - override render() { - return html`${this.#renderItems()} ${this.#renderAddButton()}`; - } + if (!documentType) { + throw new Error('Could not open permissions modal, no document type was found'); + } - #renderItems() { - if (!this._items) return; - return html` - - ${repeat( - this._items, - (item) => item.unique, - (item) => this.#renderRef(item), - )} - - `; - } + // TODO: show document type and property type name + const headline = `Permissions`; - #renderAddButton() { - return html``; - } - - #renderRef(item: UmbDocumentTypeItemModel) { - if (!item.unique) return; - const name = item.name; - const permissionNames = this.#getPermissionNamesForDocumentType(item.unique); + const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT); + if (!modalManager) { + throw new Error('Could not open permissions modal, modal manager is not available'); + } - return html` - - ${this.#renderIcon(item)} - ${this.#renderRemoveButton(item)} - - `; - } + const modal = modalManager.open(this, UMB_ENTITY_USER_PERMISSION_MODAL, { + data: { + entityType: 'document-value', + headline, + preset: { + allowedVerbs: currentPermission.verbs, + }, + }, + }); - #renderIcon(item: UmbDocumentTypeItemModel) { - if (!item.icon) return; - return html``; - } + try { + const value = await modal.onSubmit(); + + // don't do anything if the verbs have not been updated + if (JSON.stringify(value.allowedVerbs) === JSON.stringify(currentPermission.verbs)) return; + + // update permission with new verbs + this.permissions = this._permissions.map((permission) => { + if (permission.propertyType.unique === currentPermission.propertyType.unique) { + return { + ...permission, + verbs: value.allowedVerbs, + }; + } + return permission; + }); - #renderRemoveButton(item: UmbDocumentTypeItemModel) { - return html` this.#removeGranularPermission(item)} - label=${this.localize.term('general_remove')}>`; + this.dispatchEvent(new UmbChangeEvent()); + } catch (error) { + console.log(error); + } } - #getPermissionForDocumentType(unique: string) { - return this._permissions?.find((permission) => permission.documentType.unique === unique); + #removeGranularPermission(permission: UmbDocumentValueUserPermissionModel) { + this.permissions = this._permissions.filter((v) => JSON.stringify(v) !== JSON.stringify(permission)); + this.dispatchEvent(new UmbChangeEvent()); } - #getPermissionNamesForDocumentType(unique: string) { - const permission = this.#getPermissionForDocumentType(unique); - if (!permission) return; + #getVerbNamesForPermission(permission: UmbDocumentValueUserPermissionModel) { + if (!permission) { + throw new Error('Could not find permission for property type'); + } return umbExtensionsRegistry .getByTypeAndFilter('entityUserPermission', (manifest) => @@ -162,6 +171,63 @@ export class UmbInputDocumentValueGranularUserPermissionElement extends UUIFormC return [...new Set([...verbs])]; } + override render() { + return html`${this.#renderItems()} ${this.#renderAddButton()}`; + } + + #renderItems() { + if (!this.permissions) return; + return html` + + ${repeat( + this.permissions, + (item) => item.propertyType.unique, + (item) => this.#renderRef(item), + )} + + `; + } + + #renderAddButton() { + return html``; + } + + #renderRef(permission: UmbDocumentValueUserPermissionModel) { + if (!permission.propertyType.unique) { + throw new Error('Property type unique is required'); + } + + const documentType = this._documentTypes?.find((item) => item.unique === permission.documentType.unique); + const propertyType = documentType?.properties.find((item) => item.unique === permission.propertyType.unique); + const permissionName = `${documentType?.name}: ${propertyType?.name}`; + const verbNames = this.#getVerbNamesForPermission(permission); + + return html` + + + ${this.#renderEditButton(permission)} ${this.#renderRemoveButton(permission)} + + `; + } + + #renderEditButton(permission: UmbDocumentValueUserPermissionModel) { + return html` this.#editGranularPermission(permission)} + label=${this.localize.term('general_edit')}>`; + } + + #renderRemoveButton(permission: UmbDocumentValueUserPermissionModel) { + return html` this.#removeGranularPermission(permission)} + label=${this.localize.term('general_remove')}>`; + } + static override styles = [ css` #btn-add { From 2d666bf1b10ebcf48e5658256171156a9b831485 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 17 Mar 2025 10:15:34 +0100 Subject: [PATCH 039/106] include property in permission name --- .../document-property-value/constants.ts | 2 + ...granular-permission-flow-modal.element.ts} | 36 +++++++------- ...ue-granular-permission-flow-modal.token.ts | 25 ++++++++++ .../index.ts | 1 + .../manifests.ts | 6 +-- .../property-type-modal/constants.ts | 2 + .../property-type-modal/index.ts | 1 + .../property-type-modal/manifests.ts | 11 +++++ .../property-type-modal.element.ts | 18 +++---- .../property-type-modal.token.ts | 26 ++++++++++ ...value-granular-user-permission.element.ts} | 40 ++++++++-------- .../document-property-value/manifests.ts | 48 +++++++++++++++++++ .../types.ts | 2 +- .../document-value/constants.ts | 2 - ...ue-granular-permission-flow-modal.token.ts | 26 ---------- .../index.ts | 1 - .../property-type-modal/constants.ts | 2 - .../property-type-modal/index.ts | 1 - .../property-type-modal/manifests.ts | 11 ----- .../property-type-modal.token.ts | 26 ---------- .../document-value/manifests.ts | 45 ----------------- .../documents/user-permissions/manifests.ts | 4 +- 22 files changed, 171 insertions(+), 165 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/constants.ts rename src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/{document-value/document-value-granular-permission-flow-modal/document-value-granular-permission-flow-modal.element.ts => document-property-value/document-property-value-granular-permission-flow-modal/document-property-value-granular-permission-flow-modal.element.ts} (65%) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/document-property-value-granular-permission-flow-modal.token.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/index.ts rename src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/{document-value/document-value-granular-permission-flow-modal => document-property-value/document-property-value-granular-permission-flow-modal}/manifests.ts (58%) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/property-type-modal/constants.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/property-type-modal/index.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/property-type-modal/manifests.ts rename src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/{document-value/document-value-granular-permission-flow-modal => document-property-value/document-property-value-granular-permission-flow-modal}/property-type-modal/property-type-modal.element.ts (82%) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/property-type-modal/property-type-modal.token.ts rename src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/{document-value/input-document-value-granular-user-permission/input-document-value-granular-user-permission.element.ts => document-property-value/input-document-property-value-granular-user-permission/input-document-property-value-granular-user-permission.element.ts} (79%) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/manifests.ts rename src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/{document-value => document-property-value}/types.ts (64%) delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/constants.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/document-value-granular-permission-flow-modal.token.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/index.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/property-type-modal/constants.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/property-type-modal/index.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/property-type-modal/manifests.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/property-type-modal/property-type-modal.token.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/manifests.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/constants.ts new file mode 100644 index 000000000000..2a87652aa032 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/constants.ts @@ -0,0 +1,2 @@ +export const UMB_USER_PERMISSION_DOCUMENT_PROPERTY_VALUE_READ = 'Umb.Document.PropertyValue.Read'; +export const UMB_USER_PERMISSION_DOCUMENT_PROPERTY_VALUE_WRITE = 'Umb.Document.PropertyValue.Write'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/document-value-granular-permission-flow-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/document-property-value-granular-permission-flow-modal.element.ts similarity index 65% rename from src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/document-value-granular-permission-flow-modal.element.ts rename to src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/document-property-value-granular-permission-flow-modal.element.ts index 588fce3f3e79..d2f31a0a4c66 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/document-value-granular-permission-flow-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/document-property-value-granular-permission-flow-modal.element.ts @@ -1,18 +1,18 @@ -import { UMB_DOCUMENT_VALUE_GRANULAR_USER_PERMISSION_FLOW_PROPERTY_TYPE_MODAL } from './property-type-modal/property-type-modal.token.js'; +import { UMB_DOCUMENT_PROPERTY_VALUE_GRANULAR_USER_PERMISSION_FLOW_PROPERTY_TYPE_MODAL } from './property-type-modal/property-type-modal.token.js'; import type { - UmbDocumentValueGranularUserPermissionFlowModalData, - UmbDocumentValueGranularUserPermissionFlowModalValue, -} from './document-value-granular-permission-flow-modal.token.js'; + UmbDocumentPropertyValueGranularUserPermissionFlowModalData, + UmbDocumentPropertyValueGranularUserPermissionFlowModalValue, +} from './document-property-value-granular-permission-flow-modal.token.js'; import { html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; import { UMB_MODAL_MANAGER_CONTEXT, UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; import { UMB_DOCUMENT_TYPE_TREE_ALIAS } from '@umbraco-cms/backoffice/document-type'; import type { UmbSelectionChangeEvent } from '@umbraco-cms/backoffice/event'; import type { UmbTreeElement } from '@umbraco-cms/backoffice/tree'; -@customElement('umb-document-value-granular-user-permission-flow-modal') -export class UmbDocumentValueGranularUserPermissionFlowModalElement extends UmbModalBaseElement< - UmbDocumentValueGranularUserPermissionFlowModalData, - UmbDocumentValueGranularUserPermissionFlowModalValue +@customElement('umb-document-property-value-granular-user-permission-flow-modal') +export class UmbDocumentPropertyValueGranularUserPermissionFlowModalElement extends UmbModalBaseElement< + UmbDocumentPropertyValueGranularUserPermissionFlowModalData, + UmbDocumentPropertyValueGranularUserPermissionFlowModalValue > { @state() _selection: Array = []; @@ -29,14 +29,18 @@ export class UmbDocumentValueGranularUserPermissionFlowModalElement extends UmbM throw new Error('Could not get modal manager context'); } - const modal = modalManager.open(this, UMB_DOCUMENT_VALUE_GRANULAR_USER_PERMISSION_FLOW_PROPERTY_TYPE_MODAL, { - data: { - documentType, - preset: { - verbs: this.data?.preset?.verbs, + const modal = modalManager.open( + this, + UMB_DOCUMENT_PROPERTY_VALUE_GRANULAR_USER_PERMISSION_FLOW_PROPERTY_TYPE_MODAL, + { + data: { + documentType, + preset: { + verbs: this.data?.preset?.verbs, + }, }, }, - }); + ); try { const value = await modal.onSubmit(); @@ -87,10 +91,10 @@ export class UmbDocumentValueGranularUserPermissionFlowModalElement extends UmbM } } -export { UmbDocumentValueGranularUserPermissionFlowModalElement as element }; +export { UmbDocumentPropertyValueGranularUserPermissionFlowModalElement as element }; declare global { interface HTMLElementTagNameMap { - 'umb-document-value-granular-user-permission-flow-modal': UmbDocumentValueGranularUserPermissionFlowModalElement; + 'umb-document-property-value-granular-user-permission-flow-modal': UmbDocumentPropertyValueGranularUserPermissionFlowModalElement; } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/document-property-value-granular-permission-flow-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/document-property-value-granular-permission-flow-modal.token.ts new file mode 100644 index 000000000000..048bcb80ea68 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/document-property-value-granular-permission-flow-modal.token.ts @@ -0,0 +1,25 @@ +import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; + +export interface UmbDocumentPropertyValueGranularUserPermissionFlowModalData { + preset?: Partial; +} + +export interface UmbDocumentPropertyValueGranularUserPermissionFlowModalValue { + documentType: { + unique: string; + }; + propertyType: { + unique: string; + }; + verbs: Array; +} + +export const UMB_DOCUMENT_PROPERTY_VALUE_GRANULAR_USER_PERMISSION_FLOW_MODAL = new UmbModalToken< + UmbDocumentPropertyValueGranularUserPermissionFlowModalData, + UmbDocumentPropertyValueGranularUserPermissionFlowModalValue +>('Umb.Modal.DocumentPropertyValueGranularUserPermissionFlow', { + modal: { + type: 'sidebar', + size: 'small', + }, +}); diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/index.ts new file mode 100644 index 000000000000..e75e208ccc00 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/index.ts @@ -0,0 +1 @@ +export { UMB_DOCUMENT_PROPERTY_VALUE_GRANULAR_USER_PERMISSION_FLOW_MODAL } from './document-property-value-granular-permission-flow-modal.token.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/manifests.ts similarity index 58% rename from src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/manifests.ts rename to src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/manifests.ts index 86d550370e5d..5bab0422bcc3 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/manifests.ts @@ -4,9 +4,9 @@ import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension export const manifests: Array = [ { type: 'modal', - alias: 'Umb.Modal.DocumentValueGranularUserPermissionFlow', - name: 'Document Value Granular User Permission Flow Modal', - element: () => import('./document-value-granular-permission-flow-modal.element.js'), + alias: 'Umb.Modal.DocumentPropertyValueGranularUserPermissionFlow', + name: 'Document Property Value Granular User Permission Flow Modal', + element: () => import('./document-property-value-granular-permission-flow-modal.element.js'), }, ...propertyTypeModalManifests, ]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/property-type-modal/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/property-type-modal/constants.ts new file mode 100644 index 000000000000..b6c2bf5f5225 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/property-type-modal/constants.ts @@ -0,0 +1,2 @@ +export const UMB_DOCUMENT_PROPERTY_VALUE_GRANULAR_USER_PERMISSION_FLOW_PROPERTY_TYPE_MODAL_ALIAS = + 'Umb.Modal.DocumentPropertyValueGranularUserPermissionFlow.PropertyType'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/property-type-modal/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/property-type-modal/index.ts new file mode 100644 index 000000000000..e99afaf2b5c1 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/property-type-modal/index.ts @@ -0,0 +1 @@ +export { UMB_DOCUMENT_PROPERTY_VALUE_GRANULAR_USER_PERMISSION_FLOW_PROPERTY_TYPE_MODAL } from './property-type-modal.token.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/property-type-modal/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/property-type-modal/manifests.ts new file mode 100644 index 000000000000..109e45a5532b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/property-type-modal/manifests.ts @@ -0,0 +1,11 @@ +import { UMB_DOCUMENT_PROPERTY_VALUE_GRANULAR_USER_PERMISSION_FLOW_PROPERTY_TYPE_MODAL_ALIAS } from './constants.js'; +import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'modal', + alias: UMB_DOCUMENT_PROPERTY_VALUE_GRANULAR_USER_PERMISSION_FLOW_PROPERTY_TYPE_MODAL_ALIAS, + name: 'Document Property Value Granular User Permission Flow Property Type Modal', + element: () => import('./property-type-modal.element.js'), + }, +]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/property-type-modal/property-type-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/property-type-modal/property-type-modal.element.ts similarity index 82% rename from src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/property-type-modal/property-type-modal.element.ts rename to src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/property-type-modal/property-type-modal.element.ts index fc6d0c3f2a6b..6ce0d24fa4fe 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/property-type-modal/property-type-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/property-type-modal/property-type-modal.element.ts @@ -1,6 +1,6 @@ import type { - UmbDocumentValueGranularUserPermissionFlowPropertyTypeModalData, - UmbDocumentValueGranularUserPermissionFlowPropertyTypeModalValue, + UmbDocumentPropertyValueGranularUserPermissionFlowPropertyTypeModalData, + UmbDocumentPropertyValueGranularUserPermissionFlowPropertyTypeModalValue, } from './property-type-modal.token.js'; import { html, customElement, state, repeat } from '@umbraco-cms/backoffice/external/lit'; import { UMB_MODAL_MANAGER_CONTEXT, UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; @@ -8,10 +8,10 @@ import type { UmbPropertyTypeModel } from '@umbraco-cms/backoffice/content-type' import { UmbDocumentTypeDetailRepository } from '@umbraco-cms/backoffice/document-type'; import { UMB_ENTITY_USER_PERMISSION_MODAL } from '@umbraco-cms/backoffice/user-permission'; -@customElement('umb-document-value-granular-user-permission-flow-property-type-modal') -export class UmbDocumentValueGranularUserPermissionFlowPropertyTypeModalElement extends UmbModalBaseElement< - UmbDocumentValueGranularUserPermissionFlowPropertyTypeModalData, - UmbDocumentValueGranularUserPermissionFlowPropertyTypeModalValue +@customElement('umb-document-property-value-granular-user-permission-flow-property-type-modal') +export class UmbDocumentPropertyValueGranularUserPermissionFlowPropertyTypeModalElement extends UmbModalBaseElement< + UmbDocumentPropertyValueGranularUserPermissionFlowPropertyTypeModalData, + UmbDocumentPropertyValueGranularUserPermissionFlowPropertyTypeModalValue > { @state() private _documentTypeProperties: Array = []; @@ -73,7 +73,7 @@ export class UmbDocumentValueGranularUserPermissionFlowPropertyTypeModalElement const modal = modalManager.open(this, UMB_ENTITY_USER_PERMISSION_MODAL, { data: { - entityType: 'document-value', + entityType: 'document-property-value', headline, preset: { allowedVerbs: this.data?.preset?.verbs ?? [], @@ -128,10 +128,10 @@ export class UmbDocumentValueGranularUserPermissionFlowPropertyTypeModalElement } } -export { UmbDocumentValueGranularUserPermissionFlowPropertyTypeModalElement as element }; +export { UmbDocumentPropertyValueGranularUserPermissionFlowPropertyTypeModalElement as element }; declare global { interface HTMLElementTagNameMap { - 'umb-document-value-granular-user-permission-flow-property-type-modal': UmbDocumentValueGranularUserPermissionFlowPropertyTypeModalElement; + 'umb-document-property-value-granular-user-permission-flow-property-type-modal': UmbDocumentPropertyValueGranularUserPermissionFlowPropertyTypeModalElement; } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/property-type-modal/property-type-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/property-type-modal/property-type-modal.token.ts new file mode 100644 index 000000000000..b2df35ddeefa --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/property-type-modal/property-type-modal.token.ts @@ -0,0 +1,26 @@ +import { UMB_DOCUMENT_PROPERTY_VALUE_GRANULAR_USER_PERMISSION_FLOW_PROPERTY_TYPE_MODAL_ALIAS } from './constants.js'; +import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; + +export interface UmbDocumentPropertyValueGranularUserPermissionFlowPropertyTypeModalData { + documentType: { + unique: string; + }; + preset?: Partial; +} + +export interface UmbDocumentPropertyValueGranularUserPermissionFlowPropertyTypeModalValue { + propertyType: { + unique: string; + }; + verbs: Array; +} + +export const UMB_DOCUMENT_PROPERTY_VALUE_GRANULAR_USER_PERMISSION_FLOW_PROPERTY_TYPE_MODAL = new UmbModalToken< + UmbDocumentPropertyValueGranularUserPermissionFlowPropertyTypeModalData, + UmbDocumentPropertyValueGranularUserPermissionFlowPropertyTypeModalValue +>(UMB_DOCUMENT_PROPERTY_VALUE_GRANULAR_USER_PERMISSION_FLOW_PROPERTY_TYPE_MODAL_ALIAS, { + modal: { + type: 'sidebar', + size: 'small', + }, +}); diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/input-document-value-granular-user-permission/input-document-value-granular-user-permission.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/input-document-property-value-granular-user-permission/input-document-property-value-granular-user-permission.element.ts similarity index 79% rename from src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/input-document-value-granular-user-permission/input-document-value-granular-user-permission.element.ts rename to src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/input-document-property-value-granular-user-permission/input-document-property-value-granular-user-permission.element.ts index c7cecacb7ff4..249e47cbfe54 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/input-document-value-granular-user-permission/input-document-value-granular-user-permission.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/input-document-property-value-granular-user-permission/input-document-property-value-granular-user-permission.element.ts @@ -1,5 +1,5 @@ -import type { UmbDocumentValueUserPermissionModel } from '../types.js'; -import { UMB_DOCUMENT_VALUE_GRANULAR_USER_PERMISSION_FLOW_MODAL } from '../document-value-granular-permission-flow-modal/index.js'; +import type { UmbDocumentPropertyValueUserPermissionModel as UmbDocumentPropertyValueUserPermissionModel } from '../types.js'; +import { UMB_DOCUMENT_PROPERTY_VALUE_GRANULAR_USER_PERMISSION_FLOW_MODAL } from '../document-property-value-granular-permission-flow-modal/index.js'; import { css, customElement, html, property, repeat, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; @@ -15,13 +15,13 @@ import { } from '@umbraco-cms/backoffice/document-type'; import { UmbChangeEvent } from '@umbraco-cms/backoffice/event'; -@customElement('umb-document-value-granular-user-permission') -export class UmbInputDocumentValueGranularUserPermissionElement extends UUIFormControlMixin(UmbLitElement, '') { - _permissions: Array = []; - public get permissions(): Array { +@customElement('umb-document-property-value-granular-user-permission') +export class UmbInputDocumentPropertyValueGranularUserPermissionElement extends UUIFormControlMixin(UmbLitElement, '') { + _permissions: Array = []; + public get permissions(): Array { return this._permissions; } - public set permissions(value: Array) { + public set permissions(value: Array) { this._permissions = value; const uniques = value.map((item) => item.documentType.unique); this.#observePickedDocumentTypes(uniques); @@ -56,10 +56,10 @@ export class UmbInputDocumentValueGranularUserPermissionElement extends UUIFormC throw new Error('Could not open modal, no modal manager found'); } - const modal = modalManager.open(this, UMB_DOCUMENT_VALUE_GRANULAR_USER_PERMISSION_FLOW_MODAL, { + const modal = modalManager.open(this, UMB_DOCUMENT_PROPERTY_VALUE_GRANULAR_USER_PERMISSION_FLOW_MODAL, { data: { preset: { - verbs: this.#getFallbackPermissionVerbsForEntityType('document-value'), + verbs: this.#getFallbackPermissionVerbsForEntityType('document-property-value'), }, }, }); @@ -68,8 +68,8 @@ export class UmbInputDocumentValueGranularUserPermissionElement extends UUIFormC const value = await modal?.onSubmit(); if (!value) throw new Error('No result from modal'); - const permissionItem: UmbDocumentValueUserPermissionModel = { - $type: 'DocumentValuePermissionPresentationModel', + const permissionItem: UmbDocumentPropertyValueUserPermissionModel = { + $type: 'DocumentPropertyValuePermissionPresentationModel', documentType: value.documentType, propertyType: value.propertyType, verbs: value.verbs, @@ -82,7 +82,7 @@ export class UmbInputDocumentValueGranularUserPermissionElement extends UUIFormC } } - async #editGranularPermission(currentPermission: UmbDocumentValueUserPermissionModel) { + async #editGranularPermission(currentPermission: UmbDocumentPropertyValueUserPermissionModel) { if (!currentPermission) { throw new Error('Could not open permissions modal, no item was provided'); } @@ -103,7 +103,7 @@ export class UmbInputDocumentValueGranularUserPermissionElement extends UUIFormC const modal = modalManager.open(this, UMB_ENTITY_USER_PERMISSION_MODAL, { data: { - entityType: 'document-value', + entityType: 'document-property-value', headline, preset: { allowedVerbs: currentPermission.verbs, @@ -134,12 +134,12 @@ export class UmbInputDocumentValueGranularUserPermissionElement extends UUIFormC } } - #removeGranularPermission(permission: UmbDocumentValueUserPermissionModel) { + #removeGranularPermission(permission: UmbDocumentPropertyValueUserPermissionModel) { this.permissions = this._permissions.filter((v) => JSON.stringify(v) !== JSON.stringify(permission)); this.dispatchEvent(new UmbChangeEvent()); } - #getVerbNamesForPermission(permission: UmbDocumentValueUserPermissionModel) { + #getVerbNamesForPermission(permission: UmbDocumentPropertyValueUserPermissionModel) { if (!permission) { throw new Error('Could not find permission for property type'); } @@ -196,7 +196,7 @@ export class UmbInputDocumentValueGranularUserPermissionElement extends UUIFormC label=${this.localize.term('general_add')}>`; } - #renderRef(permission: UmbDocumentValueUserPermissionModel) { + #renderRef(permission: UmbDocumentPropertyValueUserPermissionModel) { if (!permission.propertyType.unique) { throw new Error('Property type unique is required'); } @@ -216,13 +216,13 @@ export class UmbInputDocumentValueGranularUserPermissionElement extends UUIFormC `; } - #renderEditButton(permission: UmbDocumentValueUserPermissionModel) { + #renderEditButton(permission: UmbDocumentPropertyValueUserPermissionModel) { return html` this.#editGranularPermission(permission)} label=${this.localize.term('general_edit')}>`; } - #renderRemoveButton(permission: UmbDocumentValueUserPermissionModel) { + #renderRemoveButton(permission: UmbDocumentPropertyValueUserPermissionModel) { return html` this.#removeGranularPermission(permission)} label=${this.localize.term('general_remove')}>`; @@ -237,10 +237,10 @@ export class UmbInputDocumentValueGranularUserPermissionElement extends UUIFormC ]; } -export { UmbInputDocumentValueGranularUserPermissionElement as element }; +export { UmbInputDocumentPropertyValueGranularUserPermissionElement as element }; declare global { interface HTMLElementTagNameMap { - 'umb-document-value-granular-user-permission': UmbInputDocumentValueGranularUserPermissionElement; + 'umb-document-property-value-granular-user-permission': UmbInputDocumentPropertyValueGranularUserPermissionElement; } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/manifests.ts new file mode 100644 index 000000000000..1b3f29fdafa4 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/manifests.ts @@ -0,0 +1,48 @@ +import { + UMB_USER_PERMISSION_DOCUMENT_PROPERTY_VALUE_READ, + UMB_USER_PERMISSION_DOCUMENT_PROPERTY_VALUE_WRITE, +} from './constants.js'; +import { manifests as documentPropertyValueGranularPermissionFlowModalManifests } from './document-property-value-granular-permission-flow-modal/manifests.js'; +import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'entityUserPermission', + alias: 'Umb.EntityUserPermission.Document.PropertyValue.Read', + name: 'Read Document Property Value User Permission', + forEntityTypes: ['document-property-value'], + weight: 200, + meta: { + verbs: [UMB_USER_PERMISSION_DOCUMENT_PROPERTY_VALUE_READ], + label: 'Read', + description: 'Read Document property values', + }, + }, + { + type: 'entityUserPermission', + alias: 'Umb.EntityUserPermission.DocumentPropertyValue.Write', + name: 'Write Document Property Value User Permission', + forEntityTypes: ['document-property-value'], + weight: 200, + meta: { + verbs: [UMB_USER_PERMISSION_DOCUMENT_PROPERTY_VALUE_WRITE], + label: 'Write', + description: 'Write Document property values', + }, + }, + { + type: 'userGranularPermission', + alias: 'Umb.UserGranularPermission.Document.PropertyValue', + name: 'Document Property Values Granular User Permission', + element: () => + import( + './input-document-property-value-granular-user-permission/input-document-property-value-granular-user-permission.element.js' + ), + meta: { + schemaType: 'DocumentPropertyValuePermissionPresentationModel', + label: 'Document Property Values', + description: 'Assign Permissions to Document property values', + }, + }, + ...documentPropertyValueGranularPermissionFlowModalManifests, +]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/types.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/types.ts similarity index 64% rename from src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/types.ts rename to src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/types.ts index 47c5f5421ff1..08d64e35de3e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/types.ts @@ -1,6 +1,6 @@ import type { UmbUserPermissionModel } from '@umbraco-cms/backoffice/user-permission'; -export interface UmbDocumentValueUserPermissionModel extends UmbUserPermissionModel { +export interface UmbDocumentPropertyValueUserPermissionModel extends UmbUserPermissionModel { documentType: { unique: string; }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/constants.ts deleted file mode 100644 index f27f8ea5af58..000000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/constants.ts +++ /dev/null @@ -1,2 +0,0 @@ -export const UMB_USER_PERMISSION_DOCUMENT_VALUE_READ = 'Umb.DocumentValue.Read'; -export const UMB_USER_PERMISSION_DOCUMENT_VALUE_WRITE = 'Umb.DocumentValue.Write'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/document-value-granular-permission-flow-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/document-value-granular-permission-flow-modal.token.ts deleted file mode 100644 index a08b9de75fe2..000000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/document-value-granular-permission-flow-modal.token.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; - -// eslint-disable-next-line @typescript-eslint/no-empty-object-type -export interface UmbDocumentValueGranularUserPermissionFlowModalData { - preset?: Partial; -} - -export interface UmbDocumentValueGranularUserPermissionFlowModalValue { - documentType: { - unique: string; - }; - propertyType: { - unique: string; - }; - verbs: Array; -} - -export const UMB_DOCUMENT_VALUE_GRANULAR_USER_PERMISSION_FLOW_MODAL = new UmbModalToken< - UmbDocumentValueGranularUserPermissionFlowModalData, - UmbDocumentValueGranularUserPermissionFlowModalValue ->('Umb.Modal.DocumentValueGranularUserPermissionFlow', { - modal: { - type: 'sidebar', - size: 'small', - }, -}); diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/index.ts deleted file mode 100644 index f1ea72a84b7f..000000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { UMB_DOCUMENT_VALUE_GRANULAR_USER_PERMISSION_FLOW_MODAL } from './document-value-granular-permission-flow-modal.token.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/property-type-modal/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/property-type-modal/constants.ts deleted file mode 100644 index 5282128b74cc..000000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/property-type-modal/constants.ts +++ /dev/null @@ -1,2 +0,0 @@ -export const UMB_DOCUMENT_VALUE_GRANULAR_USER_PERMISSION_FLOW_PROPERTY_TYPE_MODAL_ALIAS = - 'Umb.Modal.DocumentValueGranularUserPermissionFlow.PropertyType'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/property-type-modal/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/property-type-modal/index.ts deleted file mode 100644 index 8520671d94d1..000000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/property-type-modal/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { UMB_DOCUMENT_VALUE_GRANULAR_USER_PERMISSION_FLOW_PROPERTY_TYPE_MODAL } from './property-type-modal.token.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/property-type-modal/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/property-type-modal/manifests.ts deleted file mode 100644 index c8a330632b97..000000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/property-type-modal/manifests.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { UMB_DOCUMENT_VALUE_GRANULAR_USER_PERMISSION_FLOW_PROPERTY_TYPE_MODAL_ALIAS } from './constants.js'; -import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; - -export const manifests: Array = [ - { - type: 'modal', - alias: UMB_DOCUMENT_VALUE_GRANULAR_USER_PERMISSION_FLOW_PROPERTY_TYPE_MODAL_ALIAS, - name: 'Document Value Granular User Permission Flow Property Type Modal', - element: () => import('./property-type-modal.element.js'), - }, -]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/property-type-modal/property-type-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/property-type-modal/property-type-modal.token.ts deleted file mode 100644 index ba748ce4cbed..000000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/document-value-granular-permission-flow-modal/property-type-modal/property-type-modal.token.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { UMB_DOCUMENT_VALUE_GRANULAR_USER_PERMISSION_FLOW_PROPERTY_TYPE_MODAL_ALIAS } from './constants.js'; -import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; - -export interface UmbDocumentValueGranularUserPermissionFlowPropertyTypeModalData { - documentType: { - unique: string; - }; - preset?: Partial; -} - -export interface UmbDocumentValueGranularUserPermissionFlowPropertyTypeModalValue { - propertyType: { - unique: string; - }; - verbs: Array; -} - -export const UMB_DOCUMENT_VALUE_GRANULAR_USER_PERMISSION_FLOW_PROPERTY_TYPE_MODAL = new UmbModalToken< - UmbDocumentValueGranularUserPermissionFlowPropertyTypeModalData, - UmbDocumentValueGranularUserPermissionFlowPropertyTypeModalValue ->(UMB_DOCUMENT_VALUE_GRANULAR_USER_PERMISSION_FLOW_PROPERTY_TYPE_MODAL_ALIAS, { - modal: { - type: 'sidebar', - size: 'small', - }, -}); diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/manifests.ts deleted file mode 100644 index 582f7b779022..000000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-value/manifests.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { UMB_USER_PERMISSION_DOCUMENT_VALUE_READ, UMB_USER_PERMISSION_DOCUMENT_VALUE_WRITE } from './constants.js'; -import { manifests as documentValueGranularPermissionFlowModalManifests } from './document-value-granular-permission-flow-modal/manifests.js'; -import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; - -export const manifests: Array = [ - { - type: 'entityUserPermission', - alias: 'Umb.EntityUserPermission.DocumentValue.Read', - name: 'Read Document Value User Permission', - forEntityTypes: ['document-value'], - weight: 200, - meta: { - verbs: [UMB_USER_PERMISSION_DOCUMENT_VALUE_READ], - label: 'Read', - description: 'Read Document values', - }, - }, - { - type: 'entityUserPermission', - alias: 'Umb.EntityUserPermission.DocumentValue.Write', - name: 'Write Document Value User Permission', - forEntityTypes: ['document-value'], - weight: 200, - meta: { - verbs: [UMB_USER_PERMISSION_DOCUMENT_VALUE_WRITE], - label: 'Write', - description: 'Write Document values', - }, - }, - { - type: 'userGranularPermission', - alias: 'Umb.UserGranularPermission.DocumentValue', - name: 'Document Values Granular User Permission', - element: () => - import( - './input-document-value-granular-user-permission/input-document-value-granular-user-permission.element.js' - ), - meta: { - schemaType: 'DocumentValuePermissionPresentationModel', - label: 'Document Values', - description: 'Assign Permissions to Document values', - }, - }, - ...documentValueGranularPermissionFlowModalManifests, -]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/manifests.ts index 9b675f48fd9d..d67602fed40e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/manifests.ts @@ -18,7 +18,7 @@ import { } from './constants.js'; import { manifests as repositoryManifests } from './repository/manifests.js'; import { manifests as conditionManifests } from './conditions/manifests.js'; -import { manifests as documentValueManifests } from './document-value/manifests.js'; +import { manifests as documentPropertyValueManifests } from './document-property-value/manifests.js'; import type { ManifestGranularUserPermission, ManifestEntityUserPermission, @@ -219,5 +219,5 @@ export const manifests: Array = ...permissions, ...granularPermissions, ...conditionManifests, - ...documentValueManifests, + ...documentPropertyValueManifests, ]; From 94076977dc8a32aee44c59aee82280888f71fa2f Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 17 Mar 2025 11:32:20 +0100 Subject: [PATCH 040/106] add read and write managers --- .../content-type-structure-manager.class.ts | 5 +++-- .../content-type-workspace-context-base.ts | 1 + .../edit/content-editor-properties.element.ts | 22 ++++++++++++++----- .../src/packages/core/property/index.ts | 3 ++- .../property/property-read-state.manager.ts | 9 ++++++++ .../property-visibility-state.manager.ts | 7 ------ .../property/property-write-state.manager.ts | 9 ++++++++ 7 files changed, 40 insertions(+), 16 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/property/property-read-state.manager.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/property/property-visibility-state.manager.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/property/property-write-state.manager.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/structure/content-type-structure-manager.class.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/structure/content-type-structure-manager.class.ts index d1ef5dceed6f..d8598f508be3 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/structure/content-type-structure-manager.class.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/structure/content-type-structure-manager.class.ts @@ -19,7 +19,7 @@ import { incrementString } from '@umbraco-cms/backoffice/utils'; import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; import { UmbExtensionApiInitializer } from '@umbraco-cms/backoffice/extension-api'; import { umbExtensionsRegistry, type ManifestRepository } from '@umbraco-cms/backoffice/extension-registry'; -import { UmbPropertyVisibilityStateManager } from '@umbraco-cms/backoffice/property'; +import { UmbPropertyReadStateManager, UmbPropertyWriteStateManager } from '@umbraco-cms/backoffice/property'; type UmbPropertyTypeId = UmbPropertyTypeModel['id']; @@ -99,7 +99,8 @@ export class UmbContentTypeStructureManager< readonly variesByCulture = createObservablePart(this.ownerContentType, (x) => x?.variesByCulture); readonly variesBySegment = createObservablePart(this.ownerContentType, (x) => x?.variesBySegment); - public readonly propertyVisibilityState = new UmbPropertyVisibilityStateManager(this); + public readonly propertyReadState = new UmbPropertyReadStateManager(this); + public readonly propertyWriteState = new UmbPropertyReadStateManager(this); #containers: UmbArrayState = new UmbArrayState( [], diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/workspace/content-type-workspace-context-base.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/workspace/content-type-workspace-context-base.ts index 42fd9945506f..382d4b67e97f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/workspace/content-type-workspace-context-base.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/workspace/content-type-workspace-context-base.ts @@ -17,6 +17,7 @@ import { UmbRequestReloadStructureForEntityEvent, } from '@umbraco-cms/backoffice/entity-action'; import type { UmbEntityModel } from '@umbraco-cms/backoffice/entity'; +import { UmbPropertyReadStateManager } from '@umbraco-cms/backoffice/property'; // eslint-disable-next-line @typescript-eslint/no-empty-object-type export interface UmbContentTypeWorkspaceContextArgs extends UmbEntityDetailWorkspaceContextArgs {} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/content-editor-properties.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/content-editor-properties.element.ts index 260f2c7442fa..a87243050b24 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/content-editor-properties.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/content-editor-properties.element.ts @@ -32,10 +32,10 @@ export class UmbContentWorkspaceViewEditPropertiesElement extends UmbLitElement _dataPaths?: Array; @state() - _visiblePropertyAliases: Array = []; + _readablePropertyUniques: Array = []; @state() - _visibleProperties: Array = []; + _writeablePropertyUniques: Array = []; constructor() { super(); @@ -46,12 +46,17 @@ export class UmbContentWorkspaceViewEditPropertiesElement extends UmbLitElement workspaceContext.structure as unknown as UmbContentTypeStructureManager, ); - this.observe(workspaceContext.structure.propertyVisibilityState.states, (states) => { - this._visiblePropertyAliases = states.map((state) => state.propertyAlias) ?? []; + this.observe(workspaceContext.structure.propertyReadState.states, (states) => { + this._readablePropertyUniques = states.map((state) => state.propertyType.unique) ?? []; + }); + + this.observe(workspaceContext.structure.propertyWriteState.states, (states) => { + this._writeablePropertyUniques = states.map((state) => state.propertyType.unique) ?? []; }); }); this.consumeContext(UMB_PROPERTY_DATASET_CONTEXT, (datasetContext) => { + debugger; this.#variantId = datasetContext.getVariantId(); this.#generatePropertyDataPath(); }); @@ -79,7 +84,11 @@ export class UmbContentWorkspaceViewEditPropertiesElement extends UmbLitElement } #getVisibleProperties() { - return this._propertyStructure?.filter((property) => this._visiblePropertyAliases.includes(property.alias)) ?? []; + return this._propertyStructure?.filter((property) => this._readablePropertyUniques.includes(property.unique)) ?? []; + } + + #isWritable(unique: string) { + return this._writeablePropertyUniques.includes(unique); } override render() { @@ -91,7 +100,8 @@ export class UmbContentWorkspaceViewEditPropertiesElement extends UmbLitElement html` `, + .property=${property} + ?readonly=${this.#isWritable(property.unique)}>
`, ) : ''; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property/index.ts index f47426e531c4..0918bd588447 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/property/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property/index.ts @@ -3,5 +3,6 @@ export * from './conditions/index.js'; export * from './property-dataset/index.js'; export * from './property-value-cloner/property-value-clone.controller.js'; export * from './property-value-preset/index.js'; -export * from './property-visibility-state.manager.js'; +export * from './property-read-state.manager.js'; +export * from './property-write-state.manager.js'; export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property/property-read-state.manager.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property/property-read-state.manager.ts new file mode 100644 index 000000000000..58e4541a66ea --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property/property-read-state.manager.ts @@ -0,0 +1,9 @@ +import { UmbStateManager, type UmbState } from '@umbraco-cms/backoffice/utils'; + +export interface UmbPropertyReadState extends UmbState { + propertyType: { + unique: string; + }; +} + +export class UmbPropertyReadStateManager extends UmbStateManager {} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property/property-visibility-state.manager.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property/property-visibility-state.manager.ts deleted file mode 100644 index 0968a3e20a00..000000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/core/property/property-visibility-state.manager.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { UmbStateManager, type UmbState } from '@umbraco-cms/backoffice/utils'; - -export interface UmbPropertyVisibilityState extends UmbState { - propertyAlias: string; -} - -export class UmbPropertyVisibilityStateManager extends UmbStateManager {} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property/property-write-state.manager.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property/property-write-state.manager.ts new file mode 100644 index 000000000000..7eabc09fe50d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property/property-write-state.manager.ts @@ -0,0 +1,9 @@ +import { UmbStateManager, type UmbState } from '@umbraco-cms/backoffice/utils'; + +export interface UmbPropertyWriteState extends UmbState { + propertyType: { + unique: string; + }; +} + +export class UmbPropertyWriteStateManager extends UmbStateManager {} From 38eccd783849053bd3f1b890e20b239e94d9b2e0 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 17 Mar 2025 12:54:07 +0100 Subject: [PATCH 041/106] implement read and write state managers --- .../property-type-based-property.element.ts | 11 ++++++- .../edit/content-editor-properties.element.ts | 9 +++--- .../components/property/property.context.ts | 19 ++++++++---- .../components/property/property.element.ts | 25 ++++++++++++++++ .../state-manager/read-only-state.manager.ts | 8 +++++ .../utils/state-manager/state.manager.test.ts | 30 +++++++++++++++++++ .../core/utils/state-manager/state.manager.ts | 18 +++++++++++ 7 files changed, 109 insertions(+), 11 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content/components/property-type-based-property/property-type-based-property.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content/components/property-type-based-property/property-type-based-property.element.ts index 745b97c7c012..37eae27d6f1a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content/components/property-type-based-property/property-type-based-property.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content/components/property-type-based-property/property-type-based-property.element.ts @@ -39,6 +39,14 @@ export class UmbPropertyTypeBasedPropertyElement extends UmbLitElement { private _ownerEntityType?: string; + /** + * Sets the property to readonly, meaning value cannot be changed but still able to read and select its content. + * @type {boolean} + * @default false + */ + @property({ type: Boolean, reflect: true }) + public readonly: boolean = false; + @state() private _propertyEditorUiAlias?: string; @@ -120,7 +128,8 @@ export class UmbPropertyTypeBasedPropertyElement extends UmbLitElement { .appearance=${this._property.appearance} property-editor-ui-alias=${ifDefined(this._propertyEditorUiAlias)} .config=${this._dataTypeData} - .validation=${this._property.validation}> + .validation=${this._property.validation} + ?readonly=${this.readonly}> `; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/content-editor-properties.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/content-editor-properties.element.ts index a87243050b24..94a7822dfbab 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/content-editor-properties.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/content-editor-properties.element.ts @@ -56,7 +56,6 @@ export class UmbContentWorkspaceViewEditPropertiesElement extends UmbLitElement }); this.consumeContext(UMB_PROPERTY_DATASET_CONTEXT, (datasetContext) => { - debugger; this.#variantId = datasetContext.getVariantId(); this.#generatePropertyDataPath(); }); @@ -83,25 +82,25 @@ export class UmbContentWorkspaceViewEditPropertiesElement extends UmbLitElement ); } - #getVisibleProperties() { + #getReadableProperties() { return this._propertyStructure?.filter((property) => this._readablePropertyUniques.includes(property.unique)) ?? []; } - #isWritable(unique: string) { + #isWritablePropertyType(unique: string) { return this._writeablePropertyUniques.includes(unique); } override render() { return this._propertyStructure && this._dataPaths ? repeat( - this.#getVisibleProperties(), + this.#getReadableProperties(), (property) => property.alias, (property, index) => html` `, + ?readonly=${!this.#isWritablePropertyType(property.unique)}>`, ) : ''; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property/components/property/property.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property/components/property/property.context.ts index 1a2608931b6d..6926a35ffbd2 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/property/components/property/property.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property/components/property/property.context.ts @@ -22,6 +22,7 @@ import type { UmbPropertyTypeAppearanceModel, UmbPropertyTypeValidationModel, } from '@umbraco-cms/backoffice/content-type'; +import { UmbReadOnlyStateManager, UmbStateManager } from '@umbraco-cms/backoffice/utils'; export class UmbPropertyContext extends UmbContextBase> { #alias = new UmbStringState(undefined); @@ -60,8 +61,8 @@ export class UmbPropertyContext extends UmbContextBase(undefined); public readonly editorManifest = this.#editorManifest.asObservable(); - #isReadOnly = new UmbBooleanState(false); - public readonly isReadOnly = this.#isReadOnly.asObservable(); + public readonly readonlyState = new UmbReadOnlyStateManager(this); + public readonly isReadOnly = this.readonlyState.isReadOnly; /** * Set the property editor UI element for this property. @@ -160,7 +161,16 @@ export class UmbPropertyContext extends UmbContextBase { - this.#isReadOnly.setValue(value); + const unique = 'UMB_DATASET'; + + if (value) { + this.readonlyState.addState({ + unique, + message: '', + }); + } else { + this.readonlyState.removeState(unique); + } }); } @@ -334,7 +344,7 @@ export class UmbPropertyContext extends UmbContextBase extends UmbContextBase extends UmbStateManager { readonly isReadOnly = this.isOn; + + /** + * Get the read only state + * @returns {boolean} True if the state is read only + */ + getIsReadOnly(): boolean { + return this.getIsOn(); + } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/utils/state-manager/state.manager.test.ts b/src/Umbraco.Web.UI.Client/src/packages/core/utils/state-manager/state.manager.test.ts index 5f86281b339f..1b93daeaeeaf 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/utils/state-manager/state.manager.test.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/utils/state-manager/state.manager.test.ts @@ -52,6 +52,14 @@ describe('UmbSelectionManager', () => { it('has a clear method', () => { expect(manager).to.have.property('clear').that.is.a('function'); }); + + it('has a getIsOn method', () => { + expect(manager).to.have.property('getIsOn').that.is.a('function'); + }); + + it('has a getIsOff method', () => { + expect(manager).to.have.property('getIsOff').that.is.a('function'); + }); }); }); @@ -138,4 +146,26 @@ describe('UmbSelectionManager', () => { .unsubscribe(); }); }); + + describe('getIsOn', () => { + it('returns true if there are states', () => { + manager.addState(state1); + expect(manager.getIsOn()).to.be.true; + }); + + it('returns false if there are no states', () => { + expect(manager.getIsOn()).to.be.false; + }); + }); + + describe('getIsOff', () => { + it('returns true if there are no states', () => { + expect(manager.getIsOff()).to.be.true; + }); + + it('returns false if there are states', () => { + manager.addState(state1); + expect(manager.getIsOff()).to.be.false; + }); + }); }); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/utils/state-manager/state.manager.ts b/src/Umbraco.Web.UI.Client/src/packages/core/utils/state-manager/state.manager.ts index 4c163593df02..f86ef1fb0bc3 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/utils/state-manager/state.manager.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/utils/state-manager/state.manager.ts @@ -93,6 +93,24 @@ export class UmbStateManager extends UmbC this._states.setValue([]); } + /** + * Get if there are any states in the state manager + * @returns {boolean} True if there are any states in the state manager + * @memberof UmbStateManager + */ + getIsOn(): boolean { + return this.getStates().length > 0; + } + + /** + * Get if there are no states in the state manager + * @returns {boolean} True if there are no states in the state manager + * @memberof UmbStateManager + */ + getIsOff(): boolean { + return this.getStates().length === 0; + } + override destroy() { super.destroy(); this._states.destroy(); From 5f637048b6a753373cc2b72b09636489a78c0d97 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 17 Mar 2025 13:40:52 +0100 Subject: [PATCH 042/106] Update content-type-structure-manager.class.ts --- .../structure/content-type-structure-manager.class.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/structure/content-type-structure-manager.class.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/structure/content-type-structure-manager.class.ts index d8598f508be3..639fc825c555 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/structure/content-type-structure-manager.class.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/structure/content-type-structure-manager.class.ts @@ -100,7 +100,7 @@ export class UmbContentTypeStructureManager< readonly variesBySegment = createObservablePart(this.ownerContentType, (x) => x?.variesBySegment); public readonly propertyReadState = new UmbPropertyReadStateManager(this); - public readonly propertyWriteState = new UmbPropertyReadStateManager(this); + public readonly propertyWriteState = new UmbPropertyWriteStateManager(this); #containers: UmbArrayState = new UmbArrayState( [], From 066d59e70035ef4f94069f5fb78a2a0803fce126 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 17 Mar 2025 14:25:32 +0100 Subject: [PATCH 043/106] enforce property permissions --- .../conditions/constants.ts | 2 + ...roperty-value-user-permission.condition.ts | 105 ++++++++++++++++++ .../conditions/manifests.ts | 10 ++ .../conditions/types.ts | 30 +++++ .../conditions/utils.ts | 15 +++ .../document-property-value/manifests.ts | 2 + .../workspace/document-workspace.context.ts | 67 +++++++++++ .../src/packages/user/current-user/types.ts | 4 +- 8 files changed, 232 insertions(+), 3 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/conditions/constants.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/conditions/document-property-value-user-permission.condition.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/conditions/manifests.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/conditions/types.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/conditions/utils.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/conditions/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/conditions/constants.ts new file mode 100644 index 000000000000..bff1ca601d35 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/conditions/constants.ts @@ -0,0 +1,2 @@ +export const UMB_DOCUMENT_PROPERTY_VALUE_USER_PERMISSION_CONDITION_ALIAS = + 'Umb.Condition.UserPermission.Document.PropertyValue'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/conditions/document-property-value-user-permission.condition.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/conditions/document-property-value-user-permission.condition.ts new file mode 100644 index 000000000000..2332d0d03bff --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/conditions/document-property-value-user-permission.condition.ts @@ -0,0 +1,105 @@ +import type { UmbDocumentPropertyValueUserPermissionModel } from '../types.js'; +import type { UmbDocumentPropertyValueUserPermissionConditionConfig } from './types.js'; +import { isDocumentPropertyValueUserPermission } from './utils.js'; +import { UMB_CURRENT_USER_CONTEXT } from '@umbraco-cms/backoffice/current-user'; +import type { UmbConditionControllerArguments, UmbExtensionCondition } from '@umbraco-cms/backoffice/extension-api'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; + +// Do not export - for internal use only +type UmbOnChangeCallbackType = (permitted: boolean) => void; + +export class UmbDocumentPropertyValueUserPermissionCondition + extends UmbControllerBase + implements UmbExtensionCondition +{ + config: UmbDocumentPropertyValueUserPermissionConditionConfig; + permitted = false; + + #documentPropertyValuePermissions: Array = []; + #fallbackPermissions: string[] = []; + #onChange: UmbOnChangeCallbackType; + + constructor( + host: UmbControllerHost, + args: UmbConditionControllerArguments< + UmbDocumentPropertyValueUserPermissionConditionConfig, + UmbOnChangeCallbackType + >, + ) { + super(host); + this.config = args.config; + this.#onChange = args.onChange; + + this.consumeContext(UMB_CURRENT_USER_CONTEXT, (context) => { + this.observe( + context.currentUser, + (currentUser) => { + this.#documentPropertyValuePermissions = + currentUser?.permissions?.filter(isDocumentPropertyValueUserPermission) || []; + this.#fallbackPermissions = currentUser?.fallbackPermissions || []; + this.#checkPermissions(); + }, + 'umbDocumentPropertyValueUserPermissionConditionObserver', + ); + }); + } + + #checkPermissions() { + const hasDocumentPropertyValuePermissions = this.#documentPropertyValuePermissions.length > 0; + + // if there is no permissions for any documents we use the fallback permissions + if (!hasDocumentPropertyValuePermissions) { + this.#check(this.#fallbackPermissions); + return; + } + + /* If there are document permission we check if there are permissions for the current document property value + If there aren't we use the fallback permissions */ + if (hasDocumentPropertyValuePermissions) { + const permissionsForCurrentDocumentPropertyValue = this.#documentPropertyValuePermissions.find( + (permission) => permission.propertyType.unique === this.config.match.propertyType.unique, + ); + + // no permissions for the current document property value - use the fallback permissions + if (!permissionsForCurrentDocumentPropertyValue) { + this.#check(this.#fallbackPermissions); + return; + } + + // we found permissions for the current document property value - check them + this.#check(permissionsForCurrentDocumentPropertyValue.verbs); + } + } + + #check(verbs: Array) { + /* we default to true se we don't require both allOf and oneOf to be defined + but they can be combined for more complex scenarios */ + let allOfPermitted = true; + let oneOfPermitted = true; + + // check if all of the verbs are present + if (this.config.allOf?.length) { + allOfPermitted = this.config.allOf.every((verb) => verbs.includes(verb)); + } + + // check if at least one of the verbs is present + if (this.config.oneOf?.length) { + oneOfPermitted = this.config.oneOf.some((verb) => verbs.includes(verb)); + } + + // if neither allOf or oneOf is defined we default to false + if (!allOfPermitted && !oneOfPermitted) { + allOfPermitted = false; + oneOfPermitted = false; + } + + const permitted = allOfPermitted && oneOfPermitted; + if (permitted === this.permitted) return; + + this.permitted = permitted; + this.#onChange(permitted); + } +} + +export { UmbDocumentPropertyValueUserPermissionCondition as api }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/conditions/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/conditions/manifests.ts new file mode 100644 index 000000000000..527dc8dcc200 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/conditions/manifests.ts @@ -0,0 +1,10 @@ +import { UMB_DOCUMENT_PROPERTY_VALUE_USER_PERMISSION_CONDITION_ALIAS } from './constants.js'; + +export const manifests: Array = [ + { + type: 'condition', + name: 'Document Property Value User Permission Condition', + alias: UMB_DOCUMENT_PROPERTY_VALUE_USER_PERMISSION_CONDITION_ALIAS, + api: () => import('./document-property-value-user-permission.condition.js'), + }, +]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/conditions/types.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/conditions/types.ts new file mode 100644 index 000000000000..99e208ff01c5 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/conditions/types.ts @@ -0,0 +1,30 @@ +import type { UmbConditionConfigBase } from '@umbraco-cms/backoffice/extension-api'; + +export type UmbDocumentPropertyValueUserPermissionConditionConfig = + UmbConditionConfigBase<'Umb.Condition.UserPermission.Document.PropertyValue'> & { + /** + * The user must have all of the permissions in this array for the condition to be met. + * @example + * ["Umb.Document.PropertyValue.Read", "Umb.Document.PropertyValue.Write"] + */ + allOf?: Array; + + /** + * The user must have at least one of the permissions in this array for the condition to be met. + * @example + * ["Umb.Document.PropertyValue.Read", "Umb.Document.PropertyValue.Write"] + */ + oneOf?: Array; + + match: { + propertyType: { + unique: string; + }; + }; + }; + +declare global { + interface UmbExtensionConditionConfigMap { + umbDocumentPropertyValueUserPermissionConditionConfig: UmbDocumentPropertyValueUserPermissionConditionConfig; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/conditions/utils.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/conditions/utils.ts new file mode 100644 index 000000000000..66ee2de3bc56 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/conditions/utils.ts @@ -0,0 +1,15 @@ +import type { UmbDocumentPropertyValueUserPermissionModel } from '../types.js'; + +/** + * + * @param permission + * @returns {boolean} True if the permission is a DocumentPropertyValuePermissionPresentationModel + */ +export function isDocumentPropertyValueUserPermission( + permission: unknown, +): permission is UmbDocumentPropertyValueUserPermissionModel { + return ( + (permission as UmbDocumentPropertyValueUserPermissionModel).$type === + 'DocumentPropertyValuePermissionPresentationModel' + ); +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/manifests.ts index 1b3f29fdafa4..4b82fffcf4b6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/manifests.ts @@ -3,6 +3,7 @@ import { UMB_USER_PERMISSION_DOCUMENT_PROPERTY_VALUE_WRITE, } from './constants.js'; import { manifests as documentPropertyValueGranularPermissionFlowModalManifests } from './document-property-value-granular-permission-flow-modal/manifests.js'; +import { manifests as conditionManifests } from './conditions/manifests.js'; import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; export const manifests: Array = [ @@ -45,4 +46,5 @@ export const manifests: Array = }, }, ...documentPropertyValueGranularPermissionFlowModalManifests, + ...conditionManifests, ]; 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 2134817942f8..c1e5065edfbb 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 @@ -17,6 +17,11 @@ import { import { UmbDocumentPreviewRepository } from '../repository/preview/index.js'; import { UMB_DOCUMENT_PUBLISHING_WORKSPACE_CONTEXT, UmbDocumentPublishingRepository } from '../publishing/index.js'; import { UmbDocumentValidationRepository } from '../repository/validation/index.js'; +import { + UMB_USER_PERMISSION_DOCUMENT_PROPERTY_VALUE_READ, + UMB_USER_PERMISSION_DOCUMENT_PROPERTY_VALUE_WRITE, +} from '../user-permissions/document-property-value/constants.js'; +import { UMB_DOCUMENT_PROPERTY_VALUE_USER_PERMISSION_CONDITION_ALIAS } from '../user-permissions/document-property-value/conditions/constants.js'; import { UMB_DOCUMENT_DETAIL_MODEL_VARIANT_SCAFFOLD, UMB_DOCUMENT_WORKSPACE_ALIAS } from './constants.js'; import type { UmbEntityModel } from '@umbraco-cms/backoffice/entity'; import { UMB_INVARIANT_CULTURE, UmbVariantId } from '@umbraco-cms/backoffice/variant'; @@ -176,6 +181,68 @@ export class UmbDocumentWorkspaceContext }, }, ]); + + this.observe(this.structure.contentTypeProperties, (properties) => { + properties.forEach((property) => { + createExtensionApiByAlias(this, UMB_DOCUMENT_PROPERTY_VALUE_USER_PERMISSION_CONDITION_ALIAS, [ + { + config: { + allOf: [UMB_USER_PERMISSION_DOCUMENT_PROPERTY_VALUE_READ], + match: { + propertyType: { + unique: property.unique, + }, + }, + }, + onChange: (permitted: boolean) => { + const unique = 'UMB_PROPERTY_' + property.unique; + + if (permitted) { + const state = { + unique, + message: '', + propertyType: { + unique: property.unique, + }, + }; + this.structure.propertyReadState.addState(state); + } else { + this.structure.propertyReadState.removeState(unique); + } + }, + }, + ]); + + createExtensionApiByAlias(this, UMB_DOCUMENT_PROPERTY_VALUE_USER_PERMISSION_CONDITION_ALIAS, [ + { + config: { + allOf: [UMB_USER_PERMISSION_DOCUMENT_PROPERTY_VALUE_WRITE], + match: { + propertyType: { + unique: property.unique, + }, + }, + }, + onChange: (permitted: boolean) => { + const unique = 'UMB_PROPERTY_' + property.unique; + + if (permitted) { + const state = { + unique, + message: '', + propertyType: { + unique: property.unique, + }, + }; + this.structure.propertyWriteState.addState(state); + } else { + this.structure.propertyWriteState.removeState(unique); + } + }, + }, + ]); + }); + }); } override resetState(): void { diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/types.ts b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/types.ts index e199d687806a..4c26a67af309 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/types.ts @@ -1,8 +1,6 @@ import type { ApiError, CancelError, - DocumentPermissionPresentationModel, - UnknownTypePermissionPresentationModel, UserExternalLoginProviderModel, UserTwoFactorProviderModel, } from '@umbraco-cms/backoffice/external/backend-api'; @@ -27,7 +25,7 @@ export interface UmbCurrentUserModel { languages: Array; mediaStartNodeUniques: Array; name: string; - permissions: Array; + permissions: Array; unique: string; userName: string; userGroupUniques: string[]; From ecc05bc1d177338be46f31d16dccd2f041703dbe Mon Sep 17 00:00:00 2001 From: kjac Date: Mon, 17 Mar 2025 15:04:48 +0100 Subject: [PATCH 044/106] Storage for granular permissions at property type level --- .../UserGroupsBuilderExtensions.cs | 7 +- .../DocumentTypePermissionMapper.cs | 71 +++++++++++++++++++ src/Umbraco.Cms.Api.Management/OpenApi.json | 54 ++++++++++++++ ...DocumentTypePermissionPresentationModel.cs | 10 +++ .../DocumentTypeGranularPermission.cs | 36 ++++++++++ 5 files changed, 175 insertions(+), 3 deletions(-) create mode 100644 src/Umbraco.Cms.Api.Management/Mapping/Permissions/DocumentTypePermissionMapper.cs create mode 100644 src/Umbraco.Cms.Api.Management/ViewModels/UserGroup/Permissions/DocumentTypePermissionPresentationModel.cs create mode 100644 src/Umbraco.Core/Models/Membership/Permissions/DocumentTypeGranularPermission.cs diff --git a/src/Umbraco.Cms.Api.Management/DependencyInjection/UserGroupsBuilderExtensions.cs b/src/Umbraco.Cms.Api.Management/DependencyInjection/UserGroupsBuilderExtensions.cs index b7902e490a8c..b8501ca7d92f 100644 --- a/src/Umbraco.Cms.Api.Management/DependencyInjection/UserGroupsBuilderExtensions.cs +++ b/src/Umbraco.Cms.Api.Management/DependencyInjection/UserGroupsBuilderExtensions.cs @@ -13,10 +13,11 @@ internal static IUmbracoBuilder AddUserGroups(this IUmbracoBuilder builder) builder.Services.AddTransient(); builder.Services.AddSingleton(); + builder.Services.AddSingleton(); + builder.Services.AddSingleton(); - builder.Services.AddSingleton(); - builder.Services.AddSingleton(x=>x.GetRequiredService()); - builder.Services.AddSingleton(x=>x.GetRequiredService()); + builder.Services.AddSingleton(); + builder.Services.AddSingleton(); return builder; } diff --git a/src/Umbraco.Cms.Api.Management/Mapping/Permissions/DocumentTypePermissionMapper.cs b/src/Umbraco.Cms.Api.Management/Mapping/Permissions/DocumentTypePermissionMapper.cs new file mode 100644 index 000000000000..8163cc08a553 --- /dev/null +++ b/src/Umbraco.Cms.Api.Management/Mapping/Permissions/DocumentTypePermissionMapper.cs @@ -0,0 +1,71 @@ +using Umbraco.Cms.Api.Management.ViewModels; +using Umbraco.Cms.Api.Management.ViewModels.UserGroup.Permissions; +using Umbraco.Cms.Core.Models.Membership.Permissions; +using Umbraco.Cms.Infrastructure.Persistence.Dtos; +using Umbraco.Cms.Infrastructure.Persistence.Mappers; +using Umbraco.Extensions; + +namespace Umbraco.Cms.Api.Management.Mapping.Permissions; + +public class DocumentTypePermissionMapper : IPermissionPresentationMapper, IPermissionMapper +{ + public string Context => DocumentTypeGranularPermission.ContextType; + + public IGranularPermission MapFromDto(UserGroup2GranularPermissionDto dto) => + new DocumentTypeGranularPermission() + { + Key = dto.UniqueId!.Value, + Permission = dto.Permission, + }; + + public Type PresentationModelToHandle => typeof(DocumentTypePermissionPresentationModel); + + public IEnumerable MapManyAsync(IEnumerable granularPermissions) + { + var intermediate = granularPermissions.Where(p => p.Key.HasValue).Select(p => + { + var parts = p.Permission.Split('|'); + return parts.Length == 2 && Guid.TryParse(parts[0], out Guid propertyTypeId) + ? new { DocumentTypeId = p.Key!.Value, PropertyTypeId = propertyTypeId, Verb = parts[1] } + : null; + }) + .WhereNotNull() + .ToArray(); + + var intermediateByDocumentType = intermediate.GroupBy(x => x.DocumentTypeId); + foreach (var documentTypeGroup in intermediateByDocumentType) + { + foreach (var propertyTypeGroup in documentTypeGroup.GroupBy(x => x.PropertyTypeId)) + { + yield return new DocumentTypePermissionPresentationModel + { + DocumentType = new ReferenceByIdModel(documentTypeGroup.Key), + PropertyType = new ReferenceByIdModel(propertyTypeGroup.Key), + Verbs = propertyTypeGroup.Select(x => x.Verb).ToHashSet(), + }; + } + } + } + + public IEnumerable MapToGranularPermissions(IPermissionPresentationModel permissionViewModel) + { + if (permissionViewModel is not DocumentTypePermissionPresentationModel documentTypePermissionPresentationModel) + { + yield break; + } + + foreach (var verb in documentTypePermissionPresentationModel.Verbs) + { + if (string.IsNullOrEmpty(verb)) + { + continue; + } + + yield return new DocumentTypeGranularPermission + { + Key = documentTypePermissionPresentationModel.DocumentType.Id, + Permission = $"{documentTypePermissionPresentationModel.PropertyType.Id}|{verb}" + }; + } + } +} diff --git a/src/Umbraco.Cms.Api.Management/OpenApi.json b/src/Umbraco.Cms.Api.Management/OpenApi.json index fd63df819443..573631f4a48b 100644 --- a/src/Umbraco.Cms.Api.Management/OpenApi.json +++ b/src/Umbraco.Cms.Api.Management/OpenApi.json @@ -35920,6 +35920,9 @@ { "$ref": "#/components/schemas/DocumentPermissionPresentationModel" }, + { + "$ref": "#/components/schemas/DocumentTypePermissionPresentationModel" + }, { "$ref": "#/components/schemas/UnknownTypePermissionPresentationModel" } @@ -36208,6 +36211,9 @@ { "$ref": "#/components/schemas/DocumentPermissionPresentationModel" }, + { + "$ref": "#/components/schemas/DocumentTypePermissionPresentationModel" + }, { "$ref": "#/components/schemas/UnknownTypePermissionPresentationModel" } @@ -37478,6 +37484,48 @@ }, "additionalProperties": false }, + "DocumentTypePermissionPresentationModel": { + "required": [ + "$type", + "documentType", + "propertyType", + "verbs" + ], + "type": "object", + "properties": { + "$type": { + "type": "string" + }, + "documentType": { + "oneOf": [ + { + "$ref": "#/components/schemas/ReferenceByIdModel" + } + ] + }, + "propertyType": { + "oneOf": [ + { + "$ref": "#/components/schemas/ReferenceByIdModel" + } + ] + }, + "verbs": { + "uniqueItems": true, + "type": "array", + "items": { + "type": "string" + } + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "$type", + "mapping": { + "DocumentTypePermissionPresentationModel": "#/components/schemas/DocumentTypePermissionPresentationModel" + } + } + }, "DocumentTypePropertyTypeContainerResponseModel": { "required": [ "id", @@ -45432,6 +45480,9 @@ { "$ref": "#/components/schemas/DocumentPermissionPresentationModel" }, + { + "$ref": "#/components/schemas/DocumentTypePermissionPresentationModel" + }, { "$ref": "#/components/schemas/UnknownTypePermissionPresentationModel" } @@ -45855,6 +45906,9 @@ { "$ref": "#/components/schemas/DocumentPermissionPresentationModel" }, + { + "$ref": "#/components/schemas/DocumentTypePermissionPresentationModel" + }, { "$ref": "#/components/schemas/UnknownTypePermissionPresentationModel" } diff --git a/src/Umbraco.Cms.Api.Management/ViewModels/UserGroup/Permissions/DocumentTypePermissionPresentationModel.cs b/src/Umbraco.Cms.Api.Management/ViewModels/UserGroup/Permissions/DocumentTypePermissionPresentationModel.cs new file mode 100644 index 000000000000..7aece5918a02 --- /dev/null +++ b/src/Umbraco.Cms.Api.Management/ViewModels/UserGroup/Permissions/DocumentTypePermissionPresentationModel.cs @@ -0,0 +1,10 @@ +namespace Umbraco.Cms.Api.Management.ViewModels.UserGroup.Permissions; + +public class DocumentTypePermissionPresentationModel : IPermissionPresentationModel +{ + public required ReferenceByIdModel DocumentType { get; set; } + + public required ReferenceByIdModel PropertyType { get; set; } + + public required ISet Verbs { get; set; } +} diff --git a/src/Umbraco.Core/Models/Membership/Permissions/DocumentTypeGranularPermission.cs b/src/Umbraco.Core/Models/Membership/Permissions/DocumentTypeGranularPermission.cs new file mode 100644 index 000000000000..dbf1ae5fbb1c --- /dev/null +++ b/src/Umbraco.Core/Models/Membership/Permissions/DocumentTypeGranularPermission.cs @@ -0,0 +1,36 @@ +namespace Umbraco.Cms.Core.Models.Membership.Permissions; + +public class DocumentTypeGranularPermission : INodeGranularPermission +{ + public const string ContextType = "DocumentType"; + + public required Guid Key { get; set; } + + public string Context => ContextType; + + public required string Permission { get; set; } + + protected bool Equals(DocumentTypeGranularPermission other) => Key.Equals(other.Key) && Permission == other.Permission; + + public override bool Equals(object? obj) + { + if (ReferenceEquals(null, obj)) + { + return false; + } + + if (ReferenceEquals(this, obj)) + { + return true; + } + + if (obj.GetType() != GetType()) + { + return false; + } + + return Equals((DocumentTypeGranularPermission)obj); + } + + public override int GetHashCode() => HashCode.Combine(Key, Permission); +} From 6e04afe494e09943a6e0e566468761ac2a7263e8 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 17 Mar 2025 19:42:25 +0100 Subject: [PATCH 045/106] add guards --- .../edit/content-editor-properties.element.ts | 61 +++++++++++++++---- .../src/packages/core/models/index.ts | 4 ++ .../property/property-read-state.manager.ts | 6 +- .../property/property-write-state.manager.ts | 6 +- .../src/packages/core/utils/index.ts | 1 + .../packages/core/utils/reference/index.ts | 3 + .../utils/reference/is-reference-by-alias.ts | 10 +++ .../utils/reference/is-reference-by-unique.ts | 10 +++ .../reference/is-reference-by-variant-id.ts | 10 +++ .../src/packages/core/variant/types.ts | 4 ++ .../document-property-value/types.ts | 9 +-- .../workspace/document-workspace.context.ts | 5 +- 12 files changed, 102 insertions(+), 27 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/utils/reference/index.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/utils/reference/is-reference-by-alias.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/utils/reference/is-reference-by-unique.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/utils/reference/is-reference-by-variant-id.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/content-editor-properties.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/content-editor-properties.element.ts index 94a7822dfbab..0ef6a6c6ec82 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/content-editor-properties.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/content-editor-properties.element.ts @@ -10,7 +10,12 @@ import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UmbDataPathPropertyValueQuery } from '@umbraco-cms/backoffice/validation'; import { UMB_PROPERTY_STRUCTURE_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace'; import type { UmbVariantId } from '@umbraco-cms/backoffice/variant'; -import { UMB_PROPERTY_DATASET_CONTEXT } from '@umbraco-cms/backoffice/property'; +import { + UMB_PROPERTY_DATASET_CONTEXT, + type UmbPropertyReadState, + type UmbPropertyWriteState, +} from '@umbraco-cms/backoffice/property'; +import { isReferenceByAlias, isReferenceByUnique, isReferenceByVariantId } from '@umbraco-cms/backoffice/utils'; @customElement('umb-content-workspace-view-edit-properties') export class UmbContentWorkspaceViewEditPropertiesElement extends UmbLitElement { @@ -32,10 +37,10 @@ export class UmbContentWorkspaceViewEditPropertiesElement extends UmbLitElement _dataPaths?: Array; @state() - _readablePropertyUniques: Array = []; + _propertyReadStates: Array = []; @state() - _writeablePropertyUniques: Array = []; + _propertyWriteStates: Array = []; constructor() { super(); @@ -46,13 +51,21 @@ export class UmbContentWorkspaceViewEditPropertiesElement extends UmbLitElement workspaceContext.structure as unknown as UmbContentTypeStructureManager, ); - this.observe(workspaceContext.structure.propertyReadState.states, (states) => { - this._readablePropertyUniques = states.map((state) => state.propertyType.unique) ?? []; - }); + this.observe( + workspaceContext.structure.propertyReadState.states, + (states) => { + this._propertyReadStates = states; + }, + 'umbObservePropertyReadStates', + ); - this.observe(workspaceContext.structure.propertyWriteState.states, (states) => { - this._writeablePropertyUniques = states.map((state) => state.propertyType.unique) ?? []; - }); + this.observe( + workspaceContext.structure.propertyWriteState.states, + (states) => { + this._propertyWriteStates = states; + }, + 'umbObservePropertyWriteStates', + ); }); this.consumeContext(UMB_PROPERTY_DATASET_CONTEXT, (datasetContext) => { @@ -83,11 +96,33 @@ export class UmbContentWorkspaceViewEditPropertiesElement extends UmbLitElement } #getReadableProperties() { - return this._propertyStructure?.filter((property) => this._readablePropertyUniques.includes(property.unique)) ?? []; + return this._propertyStructure?.filter((property) => this.#isReadablePropertyType(property)) || []; + } + + #isReadablePropertyType(property: UmbPropertyTypeModel) { + return this._propertyReadStates.some((state) => { + if (isReferenceByUnique(state.propertyType)) { + return state.propertyType.unique === property.unique; + } else if (isReferenceByAlias(state.propertyType)) { + return state.propertyType.alias === property.alias; + } else if (isReferenceByVariantId(state.propertyType)) { + return state.propertyType.variantId === this.#variantId; + } + return false; + }); } - #isWritablePropertyType(unique: string) { - return this._writeablePropertyUniques.includes(unique); + #isWritablePropertyType(property: UmbPropertyTypeModel) { + return this._propertyWriteStates.some((state) => { + if (isReferenceByUnique(state.propertyType)) { + return state.propertyType.unique === property.unique; + } else if (isReferenceByAlias(state.propertyType)) { + return state.propertyType.alias === property.alias; + } else if (isReferenceByVariantId(state.propertyType)) { + return state.propertyType.variantId === this.#variantId; + } + return false; + }); } override render() { @@ -100,7 +135,7 @@ export class UmbContentWorkspaceViewEditPropertiesElement extends UmbLitElement class="property" data-path=${this._dataPaths![index]} .property=${property} - ?readonly=${!this.#isWritablePropertyType(property.unique)}>`, + ?readonly=${!this.#isWritablePropertyType(property)}>`, ) : ''; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/models/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/models/index.ts index c992d6388f2e..804ef8093476 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/models/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/models/index.ts @@ -19,6 +19,10 @@ export interface UmbReferenceByUnique { unique: string; } +export interface UmbReferenceByAlias { + alias: string; +} + export interface UmbReferenceByUniqueAndType { type: string; unique: string; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property/property-read-state.manager.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property/property-read-state.manager.ts index 58e4541a66ea..119ad3ac927c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/property/property-read-state.manager.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property/property-read-state.manager.ts @@ -1,9 +1,9 @@ import { UmbStateManager, type UmbState } from '@umbraco-cms/backoffice/utils'; +import type { UmbReferenceByAlias, UmbReferenceByUnique } from '@umbraco-cms/backoffice/models'; +import type { UmbReferenceByVariantId } from '@umbraco-cms/backoffice/variant'; export interface UmbPropertyReadState extends UmbState { - propertyType: { - unique: string; - }; + propertyType: UmbReferenceByUnique | UmbReferenceByAlias | UmbReferenceByVariantId; } export class UmbPropertyReadStateManager extends UmbStateManager {} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property/property-write-state.manager.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property/property-write-state.manager.ts index 7eabc09fe50d..cc2012346327 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/property/property-write-state.manager.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property/property-write-state.manager.ts @@ -1,9 +1,9 @@ import { UmbStateManager, type UmbState } from '@umbraco-cms/backoffice/utils'; +import type { UmbReferenceByAlias, UmbReferenceByUnique } from '@umbraco-cms/backoffice/models'; +import type { UmbReferenceByVariantId } from '@umbraco-cms/backoffice/variant'; export interface UmbPropertyWriteState extends UmbState { - propertyType: { - unique: string; - }; + propertyType: UmbReferenceByUnique | UmbReferenceByAlias | UmbReferenceByVariantId; } export class UmbPropertyWriteStateManager extends UmbStateManager {} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/utils/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/utils/index.ts index e6aabbc8d175..0b4c37c6494f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/utils/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/utils/index.ts @@ -26,4 +26,5 @@ export * from './selection-manager/selection.manager.js'; export * from './state-manager/index.js'; export * from './string/index.js'; export * from './deprecation/index.js'; +export * from './reference/index.js'; export type * from './type/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/utils/reference/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/utils/reference/index.ts new file mode 100644 index 000000000000..c318159eb6d5 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/utils/reference/index.ts @@ -0,0 +1,3 @@ +export * from './is-reference-by-alias.js'; +export * from './is-reference-by-unique.js'; +export * from './is-reference-by-variant-id.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/utils/reference/is-reference-by-alias.ts b/src/Umbraco.Web.UI.Client/src/packages/core/utils/reference/is-reference-by-alias.ts new file mode 100644 index 000000000000..717f71187462 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/utils/reference/is-reference-by-alias.ts @@ -0,0 +1,10 @@ +import type { UmbReferenceByAlias } from '@umbraco-cms/backoffice/models'; + +/** + * + * @param {unknown} data The data to check if it is a ReferencedByUnique + * @returns {boolean} True if the data is a ReferencedByUnique + */ +export function isReferenceByAlias(data: unknown): data is UmbReferenceByAlias { + return (data as UmbReferenceByAlias).alias !== undefined; +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/utils/reference/is-reference-by-unique.ts b/src/Umbraco.Web.UI.Client/src/packages/core/utils/reference/is-reference-by-unique.ts new file mode 100644 index 000000000000..3f10748d216d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/utils/reference/is-reference-by-unique.ts @@ -0,0 +1,10 @@ +import type { UmbReferenceByUnique } from '@umbraco-cms/backoffice/models'; + +/** + * + * @param {unknown} data The data to check if it is a ReferencedByUnique + * @returns {boolean} True if the data is a ReferencedByUnique + */ +export function isReferenceByUnique(data: unknown): data is UmbReferenceByUnique { + return (data as UmbReferenceByUnique).unique !== undefined; +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/utils/reference/is-reference-by-variant-id.ts b/src/Umbraco.Web.UI.Client/src/packages/core/utils/reference/is-reference-by-variant-id.ts new file mode 100644 index 000000000000..51709e5f9d85 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/utils/reference/is-reference-by-variant-id.ts @@ -0,0 +1,10 @@ +import type { UmbReferenceByVariantId } from '@umbraco-cms/backoffice/variant'; + +/** + * + * @param {unknown} data The data to check if it is a ReferencedByVariantId + * @returns {boolean} True if the data is a ReferencedByVariantId + */ +export function isReferenceByVariantId(data: unknown): data is UmbReferenceByVariantId { + return (data as UmbReferenceByVariantId).variantId !== undefined; +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/variant/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/variant/types.ts index 80444415e000..8cd6eb5f1d35 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/variant/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/variant/types.ts @@ -48,6 +48,10 @@ export interface UmbEntityVariantPublishModel { schedule?: ScheduleRequestModel | null; } +export interface UmbReferenceByVariantId { + variantId: UmbVariantId; +} + /** @deprecated use `UmbEntityVariantPublishModel` instead */ // eslint-disable-next-line @typescript-eslint/no-empty-object-type export interface UmbVariantPublishModel extends UmbEntityVariantPublishModel {} diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/types.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/types.ts index 08d64e35de3e..ad384408bc12 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/types.ts @@ -1,10 +1,7 @@ +import type { UmbReferenceByUnique } from '@umbraco-cms/backoffice/models'; import type { UmbUserPermissionModel } from '@umbraco-cms/backoffice/user-permission'; export interface UmbDocumentPropertyValueUserPermissionModel extends UmbUserPermissionModel { - documentType: { - unique: string; - }; - propertyType: { - unique: string; - }; + documentType: UmbReferenceByUnique; + propertyType: UmbReferenceByUnique; } 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 c1e5065edfbb..6d47fdf9e38d 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 @@ -195,7 +195,7 @@ export class UmbDocumentWorkspaceContext }, }, onChange: (permitted: boolean) => { - const unique = 'UMB_PROPERTY_' + property.unique; + const unique = 'UMB_PROPERTY_UNIQUE_' + property.unique; if (permitted) { const state = { @@ -224,7 +224,7 @@ export class UmbDocumentWorkspaceContext }, }, onChange: (permitted: boolean) => { - const unique = 'UMB_PROPERTY_' + property.unique; + const unique = 'UMB_PROPERTY_UNIQUE_' + property.unique; if (permitted) { const state = { @@ -234,6 +234,7 @@ export class UmbDocumentWorkspaceContext unique: property.unique, }, }; + this.structure.propertyWriteState.addState(state); } else { this.structure.propertyWriteState.removeState(unique); From 84f5b28f29d38f176c1dfe7f271be977959a4df2 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 17 Mar 2025 20:22:15 +0100 Subject: [PATCH 046/106] make variant property version --- .../content-type-structure-manager.class.ts | 9 ++++++--- .../edit/content-editor-properties.element.ts | 16 ++++++++-------- .../src/packages/core/property/index.ts | 2 ++ .../core/property/property-read-state.manager.ts | 12 +++++++----- .../property/property-write-state.manager.ts | 12 +++++++----- .../src/packages/core/property/types/index.ts | 4 ++++ .../src/packages/core/variant/index.ts | 2 ++ .../src/packages/core/variant/types.ts | 6 ++++++ .../variant-property-read-state.manager.ts | 10 ++++++++++ .../variant-property-write-state.manager.ts | 10 ++++++++++ .../documents/user-permissions/utils.ts | 9 ++------- 11 files changed, 64 insertions(+), 28 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/variant/variant-property-read-state.manager.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/variant/variant-property-write-state.manager.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/structure/content-type-structure-manager.class.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/structure/content-type-structure-manager.class.ts index 639fc825c555..53c3ce5331f7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/structure/content-type-structure-manager.class.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/structure/content-type-structure-manager.class.ts @@ -19,7 +19,10 @@ import { incrementString } from '@umbraco-cms/backoffice/utils'; import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; import { UmbExtensionApiInitializer } from '@umbraco-cms/backoffice/extension-api'; import { umbExtensionsRegistry, type ManifestRepository } from '@umbraco-cms/backoffice/extension-registry'; -import { UmbPropertyReadStateManager, UmbPropertyWriteStateManager } from '@umbraco-cms/backoffice/property'; +import { + UmbVariantPropertyReadStateManager, + UmbVariantPropertyWriteStateManager, +} from '@umbraco-cms/backoffice/variant'; type UmbPropertyTypeId = UmbPropertyTypeModel['id']; @@ -99,8 +102,8 @@ export class UmbContentTypeStructureManager< readonly variesByCulture = createObservablePart(this.ownerContentType, (x) => x?.variesByCulture); readonly variesBySegment = createObservablePart(this.ownerContentType, (x) => x?.variesBySegment); - public readonly propertyReadState = new UmbPropertyReadStateManager(this); - public readonly propertyWriteState = new UmbPropertyWriteStateManager(this); + public readonly propertyReadState = new UmbVariantPropertyReadStateManager(this); + public readonly propertyWriteState = new UmbVariantPropertyWriteStateManager(this); #containers: UmbArrayState = new UmbArrayState( [], diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/content-editor-properties.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/content-editor-properties.element.ts index 0ef6a6c6ec82..5216a7518b27 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/content-editor-properties.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/content-editor-properties.element.ts @@ -9,12 +9,12 @@ import { UmbContentTypePropertyStructureHelper } from '@umbraco-cms/backoffice/c import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UmbDataPathPropertyValueQuery } from '@umbraco-cms/backoffice/validation'; import { UMB_PROPERTY_STRUCTURE_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace'; -import type { UmbVariantId } from '@umbraco-cms/backoffice/variant'; -import { - UMB_PROPERTY_DATASET_CONTEXT, - type UmbPropertyReadState, - type UmbPropertyWriteState, -} from '@umbraco-cms/backoffice/property'; +import type { + UmbVariantId, + UmbVariantPropertyReadState, + UmbVariantPropertyWriteState, +} from '@umbraco-cms/backoffice/variant'; +import { UMB_PROPERTY_DATASET_CONTEXT } from '@umbraco-cms/backoffice/property'; import { isReferenceByAlias, isReferenceByUnique, isReferenceByVariantId } from '@umbraco-cms/backoffice/utils'; @customElement('umb-content-workspace-view-edit-properties') @@ -37,10 +37,10 @@ export class UmbContentWorkspaceViewEditPropertiesElement extends UmbLitElement _dataPaths?: Array; @state() - _propertyReadStates: Array = []; + _propertyReadStates: Array = []; @state() - _propertyWriteStates: Array = []; + _propertyWriteStates: Array = []; constructor() { super(); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property/index.ts index 0918bd588447..ed281fb9774f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/property/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property/index.ts @@ -5,4 +5,6 @@ export * from './property-value-cloner/property-value-clone.controller.js'; export * from './property-value-preset/index.js'; export * from './property-read-state.manager.js'; export * from './property-write-state.manager.js'; +export * from './property-read-state.manager.js'; +export * from './property-write-state.manager.js'; export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property/property-read-state.manager.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property/property-read-state.manager.ts index 119ad3ac927c..80eb07f5adde 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/property/property-read-state.manager.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property/property-read-state.manager.ts @@ -1,9 +1,11 @@ +import type { UmbPropertyTypeReferenceTypeUnion } from './types/index.js'; import { UmbStateManager, type UmbState } from '@umbraco-cms/backoffice/utils'; -import type { UmbReferenceByAlias, UmbReferenceByUnique } from '@umbraco-cms/backoffice/models'; -import type { UmbReferenceByVariantId } from '@umbraco-cms/backoffice/variant'; -export interface UmbPropertyReadState extends UmbState { - propertyType: UmbReferenceByUnique | UmbReferenceByAlias | UmbReferenceByVariantId; +export interface UmbPropertyReadState extends UmbState { + propertyType: PropertyTypeReferenceType; } -export class UmbPropertyReadStateManager extends UmbStateManager {} +export class UmbPropertyReadStateManager< + ReferenceType = UmbPropertyTypeReferenceTypeUnion, + ReadStateType extends UmbPropertyReadState = UmbPropertyReadState, +> extends UmbStateManager {} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property/property-write-state.manager.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property/property-write-state.manager.ts index cc2012346327..84c162f0ca42 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/property/property-write-state.manager.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property/property-write-state.manager.ts @@ -1,9 +1,11 @@ +import type { UmbPropertyTypeReferenceTypeUnion } from './types/index.js'; import { UmbStateManager, type UmbState } from '@umbraco-cms/backoffice/utils'; -import type { UmbReferenceByAlias, UmbReferenceByUnique } from '@umbraco-cms/backoffice/models'; -import type { UmbReferenceByVariantId } from '@umbraco-cms/backoffice/variant'; -export interface UmbPropertyWriteState extends UmbState { - propertyType: UmbReferenceByUnique | UmbReferenceByAlias | UmbReferenceByVariantId; +export interface UmbPropertyWriteState extends UmbState { + propertyType: PropertyTypeReferenceType; } -export class UmbPropertyWriteStateManager extends UmbStateManager {} +export class UmbPropertyWriteStateManager< + ReferenceType = UmbPropertyTypeReferenceTypeUnion, + WriteStateType extends UmbPropertyWriteState = UmbPropertyWriteState, +> extends UmbStateManager {} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property/types/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property/types/index.ts index b1800898cf99..b75d4ec4d2ed 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/property/types/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property/types/index.ts @@ -1,2 +1,6 @@ +import type { UmbReferenceByAlias, UmbReferenceByUnique } from '@umbraco-cms/backoffice/models'; + export type * from './property-value-data.type.js'; export type * from './unsupported-properties.type.js'; + +export type UmbPropertyTypeReferenceTypeUnion = UmbReferenceByUnique | UmbReferenceByAlias; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/variant/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/variant/index.ts index 5a6c69cbf2ec..831be38b4a56 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/variant/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/variant/index.ts @@ -1,3 +1,5 @@ export * from './variant-id.class.js'; export * from './variant-object-compare.function.js'; +export * from './variant-property-read-state.manager.js'; +export * from './variant-property-write-state.manager.js'; export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/variant/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/variant/types.ts index 8cd6eb5f1d35..75b0b29417ac 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/variant/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/variant/types.ts @@ -2,6 +2,7 @@ import type { UmbVariantId } from './variant-id.class.js'; import type { UmbLanguageDetailModel } from '@umbraco-cms/backoffice/language'; import type { ScheduleRequestModel } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbPropertyValueData } from '@umbraco-cms/backoffice/property'; +import type { UmbReferenceByAlias, UmbReferenceByUnique } from '@umbraco-cms/backoffice/models'; export type UmbObjectWithVariantProperties = { culture: string | null; @@ -52,6 +53,11 @@ export interface UmbReferenceByVariantId { variantId: UmbVariantId; } +export type UmbVariantPropertyTypeReferenceTypeUnion = + | UmbReferenceByUnique + | UmbReferenceByAlias + | UmbReferenceByVariantId; + /** @deprecated use `UmbEntityVariantPublishModel` instead */ // eslint-disable-next-line @typescript-eslint/no-empty-object-type export interface UmbVariantPublishModel extends UmbEntityVariantPublishModel {} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/variant/variant-property-read-state.manager.ts b/src/Umbraco.Web.UI.Client/src/packages/core/variant/variant-property-read-state.manager.ts new file mode 100644 index 000000000000..ae733f5889d2 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/variant/variant-property-read-state.manager.ts @@ -0,0 +1,10 @@ +import type { UmbVariantPropertyTypeReferenceTypeUnion } from './types.js'; +import { UmbPropertyReadStateManager, type UmbPropertyReadState } from '@umbraco-cms/backoffice/property'; + +// eslint-disable-next-line @typescript-eslint/no-empty-object-type +export interface UmbVariantPropertyReadState extends UmbPropertyReadState {} + +export class UmbVariantPropertyReadStateManager extends UmbPropertyReadStateManager< + UmbVariantPropertyTypeReferenceTypeUnion, + UmbVariantPropertyReadState +> {} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/variant/variant-property-write-state.manager.ts b/src/Umbraco.Web.UI.Client/src/packages/core/variant/variant-property-write-state.manager.ts new file mode 100644 index 000000000000..f22bfc7cd1d7 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/variant/variant-property-write-state.manager.ts @@ -0,0 +1,10 @@ +import type { UmbVariantPropertyTypeReferenceTypeUnion } from './types.js'; +import { UmbPropertyWriteStateManager, type UmbPropertyWriteState } from '@umbraco-cms/backoffice/property'; + +// eslint-disable-next-line @typescript-eslint/no-empty-object-type +export interface UmbVariantPropertyWriteState extends UmbPropertyWriteState {} + +export class UmbVariantPropertyWriteStateManager extends UmbPropertyWriteStateManager< + UmbVariantPropertyTypeReferenceTypeUnion, + UmbVariantPropertyWriteState +> {} diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/utils.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/utils.ts index c9b647678dee..003d3017f684 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/utils.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/utils.ts @@ -1,14 +1,9 @@ -import type { - DocumentPermissionPresentationModel, - UnknownTypePermissionPresentationModel, -} from '@umbraco-cms/backoffice/external/backend-api'; +import type { DocumentPermissionPresentationModel } from '@umbraco-cms/backoffice/external/backend-api'; /** * * @param permission */ -export function isDocumentUserPermission( - permission: DocumentPermissionPresentationModel | UnknownTypePermissionPresentationModel, -): permission is DocumentPermissionPresentationModel { +export function isDocumentUserPermission(permission: unknown): permission is DocumentPermissionPresentationModel { return (permission as DocumentPermissionPresentationModel).$type === 'DocumentPermissionPresentationModel'; } From e7d2c3e4e2e903ad20e9b581edd2dd81602328c9 Mon Sep 17 00:00:00 2001 From: kjac Date: Tue, 18 Mar 2025 09:35:17 +0100 Subject: [PATCH 047/106] Rename server models to include "property" --- .../UserGroupsBuilderExtensions.cs | 4 ++-- ....cs => DocumentTypePropertyPermissionMapper.cs} | 14 +++++++------- src/Umbraco.Cms.Api.Management/OpenApi.json | 12 ++++++------ ...mentTypePropertyPermissionPresentationModel.cs} | 2 +- ...s => DocumentTypePropertyGranularPermission.cs} | 8 ++++---- 5 files changed, 20 insertions(+), 20 deletions(-) rename src/Umbraco.Cms.Api.Management/Mapping/Permissions/{DocumentTypePermissionMapper.cs => DocumentTypePropertyPermissionMapper.cs} (81%) rename src/Umbraco.Cms.Api.Management/ViewModels/UserGroup/Permissions/{DocumentTypePermissionPresentationModel.cs => DocumentTypePropertyPermissionPresentationModel.cs} (74%) rename src/Umbraco.Core/Models/Membership/Permissions/{DocumentTypeGranularPermission.cs => DocumentTypePropertyGranularPermission.cs} (63%) diff --git a/src/Umbraco.Cms.Api.Management/DependencyInjection/UserGroupsBuilderExtensions.cs b/src/Umbraco.Cms.Api.Management/DependencyInjection/UserGroupsBuilderExtensions.cs index b8501ca7d92f..33bce7fa88e8 100644 --- a/src/Umbraco.Cms.Api.Management/DependencyInjection/UserGroupsBuilderExtensions.cs +++ b/src/Umbraco.Cms.Api.Management/DependencyInjection/UserGroupsBuilderExtensions.cs @@ -16,8 +16,8 @@ internal static IUmbracoBuilder AddUserGroups(this IUmbracoBuilder builder) builder.Services.AddSingleton(); builder.Services.AddSingleton(); - builder.Services.AddSingleton(); - builder.Services.AddSingleton(); + builder.Services.AddSingleton(); + builder.Services.AddSingleton(); return builder; } diff --git a/src/Umbraco.Cms.Api.Management/Mapping/Permissions/DocumentTypePermissionMapper.cs b/src/Umbraco.Cms.Api.Management/Mapping/Permissions/DocumentTypePropertyPermissionMapper.cs similarity index 81% rename from src/Umbraco.Cms.Api.Management/Mapping/Permissions/DocumentTypePermissionMapper.cs rename to src/Umbraco.Cms.Api.Management/Mapping/Permissions/DocumentTypePropertyPermissionMapper.cs index 8163cc08a553..fb73a186eb37 100644 --- a/src/Umbraco.Cms.Api.Management/Mapping/Permissions/DocumentTypePermissionMapper.cs +++ b/src/Umbraco.Cms.Api.Management/Mapping/Permissions/DocumentTypePropertyPermissionMapper.cs @@ -7,18 +7,18 @@ namespace Umbraco.Cms.Api.Management.Mapping.Permissions; -public class DocumentTypePermissionMapper : IPermissionPresentationMapper, IPermissionMapper +public class DocumentTypePropertyPermissionMapper : IPermissionPresentationMapper, IPermissionMapper { - public string Context => DocumentTypeGranularPermission.ContextType; + public string Context => DocumentTypePropertyGranularPermission.ContextType; public IGranularPermission MapFromDto(UserGroup2GranularPermissionDto dto) => - new DocumentTypeGranularPermission() + new DocumentTypePropertyGranularPermission() { Key = dto.UniqueId!.Value, Permission = dto.Permission, }; - public Type PresentationModelToHandle => typeof(DocumentTypePermissionPresentationModel); + public Type PresentationModelToHandle => typeof(DocumentTypePropertyPermissionPresentationModel); public IEnumerable MapManyAsync(IEnumerable granularPermissions) { @@ -37,7 +37,7 @@ public IEnumerable MapManyAsync(IEnumerable x.PropertyTypeId)) { - yield return new DocumentTypePermissionPresentationModel + yield return new DocumentTypePropertyPermissionPresentationModel { DocumentType = new ReferenceByIdModel(documentTypeGroup.Key), PropertyType = new ReferenceByIdModel(propertyTypeGroup.Key), @@ -49,7 +49,7 @@ public IEnumerable MapManyAsync(IEnumerable MapToGranularPermissions(IPermissionPresentationModel permissionViewModel) { - if (permissionViewModel is not DocumentTypePermissionPresentationModel documentTypePermissionPresentationModel) + if (permissionViewModel is not DocumentTypePropertyPermissionPresentationModel documentTypePermissionPresentationModel) { yield break; } @@ -61,7 +61,7 @@ public IEnumerable MapToGranularPermissions(IPermissionPres continue; } - yield return new DocumentTypeGranularPermission + yield return new DocumentTypePropertyGranularPermission { Key = documentTypePermissionPresentationModel.DocumentType.Id, Permission = $"{documentTypePermissionPresentationModel.PropertyType.Id}|{verb}" diff --git a/src/Umbraco.Cms.Api.Management/OpenApi.json b/src/Umbraco.Cms.Api.Management/OpenApi.json index 573631f4a48b..2c6589e9013e 100644 --- a/src/Umbraco.Cms.Api.Management/OpenApi.json +++ b/src/Umbraco.Cms.Api.Management/OpenApi.json @@ -35921,7 +35921,7 @@ "$ref": "#/components/schemas/DocumentPermissionPresentationModel" }, { - "$ref": "#/components/schemas/DocumentTypePermissionPresentationModel" + "$ref": "#/components/schemas/DocumentTypePropertyPermissionPresentationModel" }, { "$ref": "#/components/schemas/UnknownTypePermissionPresentationModel" @@ -36212,7 +36212,7 @@ "$ref": "#/components/schemas/DocumentPermissionPresentationModel" }, { - "$ref": "#/components/schemas/DocumentTypePermissionPresentationModel" + "$ref": "#/components/schemas/DocumentTypePropertyPermissionPresentationModel" }, { "$ref": "#/components/schemas/UnknownTypePermissionPresentationModel" @@ -37484,7 +37484,7 @@ }, "additionalProperties": false }, - "DocumentTypePermissionPresentationModel": { + "DocumentTypePropertyPermissionPresentationModel": { "required": [ "$type", "documentType", @@ -37522,7 +37522,7 @@ "discriminator": { "propertyName": "$type", "mapping": { - "DocumentTypePermissionPresentationModel": "#/components/schemas/DocumentTypePermissionPresentationModel" + "DocumentTypePropertyPermissionPresentationModel": "#/components/schemas/DocumentTypePropertyPermissionPresentationModel" } } }, @@ -45481,7 +45481,7 @@ "$ref": "#/components/schemas/DocumentPermissionPresentationModel" }, { - "$ref": "#/components/schemas/DocumentTypePermissionPresentationModel" + "$ref": "#/components/schemas/DocumentTypePropertyPermissionPresentationModel" }, { "$ref": "#/components/schemas/UnknownTypePermissionPresentationModel" @@ -45907,7 +45907,7 @@ "$ref": "#/components/schemas/DocumentPermissionPresentationModel" }, { - "$ref": "#/components/schemas/DocumentTypePermissionPresentationModel" + "$ref": "#/components/schemas/DocumentTypePropertyPermissionPresentationModel" }, { "$ref": "#/components/schemas/UnknownTypePermissionPresentationModel" diff --git a/src/Umbraco.Cms.Api.Management/ViewModels/UserGroup/Permissions/DocumentTypePermissionPresentationModel.cs b/src/Umbraco.Cms.Api.Management/ViewModels/UserGroup/Permissions/DocumentTypePropertyPermissionPresentationModel.cs similarity index 74% rename from src/Umbraco.Cms.Api.Management/ViewModels/UserGroup/Permissions/DocumentTypePermissionPresentationModel.cs rename to src/Umbraco.Cms.Api.Management/ViewModels/UserGroup/Permissions/DocumentTypePropertyPermissionPresentationModel.cs index 7aece5918a02..41a527679f19 100644 --- a/src/Umbraco.Cms.Api.Management/ViewModels/UserGroup/Permissions/DocumentTypePermissionPresentationModel.cs +++ b/src/Umbraco.Cms.Api.Management/ViewModels/UserGroup/Permissions/DocumentTypePropertyPermissionPresentationModel.cs @@ -1,6 +1,6 @@ namespace Umbraco.Cms.Api.Management.ViewModels.UserGroup.Permissions; -public class DocumentTypePermissionPresentationModel : IPermissionPresentationModel +public class DocumentTypePropertyPermissionPresentationModel : IPermissionPresentationModel { public required ReferenceByIdModel DocumentType { get; set; } diff --git a/src/Umbraco.Core/Models/Membership/Permissions/DocumentTypeGranularPermission.cs b/src/Umbraco.Core/Models/Membership/Permissions/DocumentTypePropertyGranularPermission.cs similarity index 63% rename from src/Umbraco.Core/Models/Membership/Permissions/DocumentTypeGranularPermission.cs rename to src/Umbraco.Core/Models/Membership/Permissions/DocumentTypePropertyGranularPermission.cs index dbf1ae5fbb1c..c0f61c1f63bb 100644 --- a/src/Umbraco.Core/Models/Membership/Permissions/DocumentTypeGranularPermission.cs +++ b/src/Umbraco.Core/Models/Membership/Permissions/DocumentTypePropertyGranularPermission.cs @@ -1,8 +1,8 @@ namespace Umbraco.Cms.Core.Models.Membership.Permissions; -public class DocumentTypeGranularPermission : INodeGranularPermission +public class DocumentTypePropertyGranularPermission : INodeGranularPermission { - public const string ContextType = "DocumentType"; + public const string ContextType = "DocumentTypeProperty"; public required Guid Key { get; set; } @@ -10,7 +10,7 @@ public class DocumentTypeGranularPermission : INodeGranularPermission public required string Permission { get; set; } - protected bool Equals(DocumentTypeGranularPermission other) => Key.Equals(other.Key) && Permission == other.Permission; + protected bool Equals(DocumentTypePropertyGranularPermission other) => Key.Equals(other.Key) && Permission == other.Permission; public override bool Equals(object? obj) { @@ -29,7 +29,7 @@ public override bool Equals(object? obj) return false; } - return Equals((DocumentTypeGranularPermission)obj); + return Equals((DocumentTypePropertyGranularPermission)obj); } public override int GetHashCode() => HashCode.Combine(Key, Permission); From 908240ed277a330066971cbdc16b99df5fca43d4 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 18 Mar 2025 10:11:46 +0100 Subject: [PATCH 048/106] generate server types --- .../src/external/backend-api/src/types.gen.ts | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/external/backend-api/src/types.gen.ts b/src/Umbraco.Web.UI.Client/src/external/backend-api/src/types.gen.ts index 5e831e2da328..107f245962bf 100644 --- a/src/Umbraco.Web.UI.Client/src/external/backend-api/src/types.gen.ts +++ b/src/Umbraco.Web.UI.Client/src/external/backend-api/src/types.gen.ts @@ -408,7 +408,7 @@ export type CreateUserGroupRequestModel = { mediaStartNode?: ((ReferenceByIdModel) | null); mediaRootAccess: boolean; fallbackPermissions: Array<(string)>; - permissions: Array<(DocumentPermissionPresentationModel | UnknownTypePermissionPresentationModel)>; + permissions: Array<(DocumentPermissionPresentationModel | DocumentTypePropertyPermissionPresentationModel | UnknownTypePermissionPresentationModel)>; id?: (string) | null; }; @@ -460,7 +460,7 @@ export type CurrentUserResponseModel = { hasAccessToAllLanguages: boolean; hasAccessToSensitiveData: boolean; fallbackPermissions: Array<(string)>; - permissions: Array<(DocumentPermissionPresentationModel | UnknownTypePermissionPresentationModel)>; + permissions: Array<(DocumentPermissionPresentationModel | DocumentTypePropertyPermissionPresentationModel | UnknownTypePermissionPresentationModel)>; allowedSections: Array<(string)>; isAdmin: boolean; }; @@ -768,6 +768,13 @@ export type DocumentTypeItemResponseModel = { description?: (string) | null; }; +export type DocumentTypePropertyPermissionPresentationModel = { + $type: string; + documentType: (ReferenceByIdModel); + propertyType: (ReferenceByIdModel); + verbs: Array<(string)>; +}; + export type DocumentTypePropertyTypeContainerResponseModel = { id: string; parent?: ((ReferenceByIdModel) | null); @@ -2659,7 +2666,7 @@ export type UpdateUserGroupRequestModel = { mediaStartNode?: ((ReferenceByIdModel) | null); mediaRootAccess: boolean; fallbackPermissions: Array<(string)>; - permissions: Array<(DocumentPermissionPresentationModel | UnknownTypePermissionPresentationModel)>; + permissions: Array<(DocumentPermissionPresentationModel | DocumentTypePropertyPermissionPresentationModel | UnknownTypePermissionPresentationModel)>; }; export type UpdateUserGroupsOnUserRequestModel = { @@ -2759,7 +2766,7 @@ export type UserGroupResponseModel = { mediaStartNode?: ((ReferenceByIdModel) | null); mediaRootAccess: boolean; fallbackPermissions: Array<(string)>; - permissions: Array<(DocumentPermissionPresentationModel | UnknownTypePermissionPresentationModel)>; + permissions: Array<(DocumentPermissionPresentationModel | DocumentTypePropertyPermissionPresentationModel | UnknownTypePermissionPresentationModel)>; id: string; isDeletable: boolean; aliasCanBeChanged: boolean; From 8129789e6d48f29cad548a8aa791a546f1909434 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 18 Mar 2025 13:16:31 +0100 Subject: [PATCH 049/106] add permissionType to model --- .../src/packages/user/user-permission/types.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user-permission/types.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user-permission/types.ts index 7f10a7e1b0bd..575b120ae30b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user-permission/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user-permission/types.ts @@ -2,5 +2,6 @@ export type * from './user-granular-permission.extension.js'; export type * from './entity-user-permission.extension.js'; export interface UmbUserPermissionModel { $type: string; + permissionType: string; verbs: Array; } From 86d7aceb709f97de91d219ddf56ed49497416325 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 18 Mar 2025 13:16:57 +0100 Subject: [PATCH 050/106] add mappers to user group permission data --- .../user-group-detail.server.data-source.ts | 73 ++++++++++++++----- 1 file changed, 53 insertions(+), 20 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user-group/repository/detail/user-group-detail.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user-group/repository/detail/user-group-detail.server.data-source.ts index fe1e4bef9933..08af21b12548 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user-group/repository/detail/user-group-detail.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user-group/repository/detail/user-group-detail.server.data-source.ts @@ -6,26 +6,20 @@ import type { } from '@umbraco-cms/backoffice/external/backend-api'; import { UserGroupService } from '@umbraco-cms/backoffice/external/backend-api'; import { UmbId } from '@umbraco-cms/backoffice/id'; -import type { UmbDetailDataSource } from '@umbraco-cms/backoffice/repository'; -import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import { UmbManagementApiDataMapper, type UmbDetailDataSource } from '@umbraco-cms/backoffice/repository'; import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; /** * A data source for the User Group that fetches data from the server * @class UmbUserGroupServerDataSource * @implements {RepositoryDetailDataSource} */ -export class UmbUserGroupServerDataSource implements UmbDetailDataSource { - #host: UmbControllerHost; - - /** - * Creates an instance of UmbUserGroupServerDataSource. - * @param {UmbControllerHost} host - The controller host for this controller to be appended to - * @memberof UmbUserGroupServerDataSource - */ - constructor(host: UmbControllerHost) { - this.#host = host; - } +export class UmbUserGroupServerDataSource + extends UmbControllerBase + implements UmbDetailDataSource +{ + #dataMapper = new UmbManagementApiDataMapper(this); /** * Creates a new User Group scaffold @@ -65,12 +59,27 @@ export class UmbUserGroupServerDataSource implements UmbDetailDataSource { + return this.#dataMapper.map({ + forDataModel: item.$type, + data: item, + fallback: async () => { + return { + ...item, + permissionType: 'unknown', + }; + }, + }); + }); + + const permissions = await Promise.all(permissionDataPromises); + // TODO: make data mapper to prevent errors const userGroup: UmbUserGroupDetailModel = { alias: data.alias, @@ -86,7 +95,7 @@ export class UmbUserGroupServerDataSource implements UmbDetailDataSource { + return this.#dataMapper.map({ + forDataModel: item.permissionType, + data: item, + fallback: async () => item, + }); + }); + + const permissions = await Promise.all(permissionDataPromises); + // TODO: make data mapper to prevent errors const requestBody: CreateUserGroupRequestModel = { alias: model.alias, @@ -115,12 +134,12 @@ export class UmbUserGroupServerDataSource implements UmbDetailDataSource { + return this.#dataMapper.map({ + forDataModel: item.permissionType, + data: item, + fallback: async () => { + return { + ...item, + }; + }, + }); + }); + + const permissions = await Promise.all(permissionDataPromises); + // TODO: make data mapper to prevent errors const requestBody: UpdateUserGroupRequestModel = { alias: model.alias, @@ -155,12 +188,12 @@ export class UmbUserGroupServerDataSource implements UmbDetailDataSource Date: Tue, 18 Mar 2025 13:17:24 +0100 Subject: [PATCH 051/106] add mapper to current user permission data --- .../current-user.server.data-source.ts | 41 +++++++++++-------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/repository/current-user.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/repository/current-user.server.data-source.ts index 55a12a7824c8..113feb2b6a3f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/repository/current-user.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/repository/current-user.server.data-source.ts @@ -1,23 +1,15 @@ import type { UmbCurrentUserModel } from '../types.js'; import { UserService } from '@umbraco-cms/backoffice/external/backend-api'; -import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { tryExecute, tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; +import { UmbManagementApiDataMapper } from '@umbraco-cms/backoffice/repository'; /** * A data source for the current user that fetches data from the server * @class UmbCurrentUserServerDataSource */ -export class UmbCurrentUserServerDataSource { - #host: UmbControllerHost; - - /** - * Creates an instance of UmbCurrentUserServerDataSource. - * @param {UmbControllerHost} host - The controller host for this controller to be appended to - * @memberof UmbCurrentUserServerDataSource - */ - constructor(host: UmbControllerHost) { - this.#host = host; - } +export class UmbCurrentUserServerDataSource extends UmbControllerBase { + #dataMapper = new UmbManagementApiDataMapper(this); /** * Get the current user @@ -25,9 +17,24 @@ export class UmbCurrentUserServerDataSource { * @memberof UmbCurrentUserServerDataSource */ async getCurrentUser() { - const { data, error } = await tryExecuteAndNotify(this.#host, UserService.getUserCurrent()); + const { data, error } = await tryExecuteAndNotify(this, UserService.getUserCurrent()); if (data) { + const permissionDataPromises = data.permissions.map(async (item) => { + return this.#dataMapper.map({ + forDataModel: item.$type, + data: item, + fallback: async () => { + return { + ...item, + permissionType: 'unknown', + }; + }, + }); + }); + + const permissions = await Promise.all(permissionDataPromises); + const user: UmbCurrentUserModel = { allowedSections: data.allowedSections, avatarUrls: data.avatarUrls, @@ -51,7 +58,7 @@ export class UmbCurrentUserServerDataSource { }; }), name: data.name, - permissions: data.permissions, + permissions, unique: data.id, userName: data.userName, userGroupUniques: data.userGroupIds.map((group) => group.id), @@ -67,7 +74,7 @@ export class UmbCurrentUserServerDataSource { * @memberof UmbCurrentUserServerDataSource */ async getExternalLoginProviders() { - return tryExecuteAndNotify(this.#host, UserService.getUserCurrentLoginProviders()); + return tryExecuteAndNotify(this, UserService.getUserCurrentLoginProviders()); } /** @@ -75,7 +82,7 @@ export class UmbCurrentUserServerDataSource { * @memberof UmbCurrentUserServerDataSource */ async getMfaLoginProviders() { - const { data, error } = await tryExecuteAndNotify(this.#host, UserService.getUserCurrent2Fa()); + const { data, error } = await tryExecuteAndNotify(this, UserService.getUserCurrent2Fa()); if (data) { return { data }; @@ -127,7 +134,7 @@ export class UmbCurrentUserServerDataSource { */ async changePassword(newPassword: string, oldPassword: string) { return tryExecuteAndNotify( - this.#host, + this, UserService.postUserCurrentChangePassword({ requestBody: { newPassword, From f23c6c96fada0ca28ef5048bc48de98a2f8b3e76 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 18 Mar 2025 13:17:52 +0100 Subject: [PATCH 052/106] destroy --- .../structure/content-type-structure-manager.class.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/structure/content-type-structure-manager.class.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/structure/content-type-structure-manager.class.ts index 53c3ce5331f7..e3512137cb01 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/structure/content-type-structure-manager.class.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/structure/content-type-structure-manager.class.ts @@ -816,6 +816,8 @@ export class UmbContentTypeStructureManager< public override destroy() { this.#contentTypes.destroy(); this.#containers.destroy(); + this.propertyReadState.destroy(); + this.propertyWriteState.destroy(); super.destroy(); } } From 7a306a9cf5862f189ce78f387c49c9afdcee6e0b Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 18 Mar 2025 13:18:04 +0100 Subject: [PATCH 053/106] clear state --- .../documents/documents/workspace/document-workspace.context.ts | 2 ++ 1 file changed, 2 insertions(+) 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 6d47fdf9e38d..439bc4ac8be9 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 @@ -249,6 +249,8 @@ export class UmbDocumentWorkspaceContext override resetState(): void { super.resetState(); this.#isTrashedContext.setIsTrashed(false); + this.structure.propertyReadState.clear(); + this.structure.propertyWriteState.clear(); } override async load(unique: string) { From 14080c769274deb6bd524037c3ff6516873ac1a8 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 18 Mar 2025 13:18:18 +0100 Subject: [PATCH 054/106] use permission type for guard check --- .../document-property-value/conditions/utils.ts | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/conditions/utils.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/conditions/utils.ts index 66ee2de3bc56..caca66dc3686 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/conditions/utils.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/conditions/utils.ts @@ -3,13 +3,10 @@ import type { UmbDocumentPropertyValueUserPermissionModel } from '../types.js'; /** * * @param permission - * @returns {boolean} True if the permission is a DocumentPropertyValuePermissionPresentationModel + * @returns {boolean} True if the permission is a document-property-value' permission */ export function isDocumentPropertyValueUserPermission( permission: unknown, ): permission is UmbDocumentPropertyValueUserPermissionModel { - return ( - (permission as UmbDocumentPropertyValueUserPermissionModel).$type === - 'DocumentPropertyValuePermissionPresentationModel' - ); + return (permission as UmbDocumentPropertyValueUserPermissionModel).permissionType === 'document-property-value'; } From 2b843ee26cbf106691edfe041bbd2369cbd4b43d Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 18 Mar 2025 13:18:39 +0100 Subject: [PATCH 055/106] add permission type --- ...document-property-value-granular-user-permission.element.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/input-document-property-value-granular-user-permission/input-document-property-value-granular-user-permission.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/input-document-property-value-granular-user-permission/input-document-property-value-granular-user-permission.element.ts index 249e47cbfe54..85986a3f8110 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/input-document-property-value-granular-user-permission/input-document-property-value-granular-user-permission.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/input-document-property-value-granular-user-permission/input-document-property-value-granular-user-permission.element.ts @@ -69,7 +69,8 @@ export class UmbInputDocumentPropertyValueGranularUserPermissionElement extends if (!value) throw new Error('No result from modal'); const permissionItem: UmbDocumentPropertyValueUserPermissionModel = { - $type: 'DocumentPropertyValuePermissionPresentationModel', + $type: 'DocumentTypePropertyPermissionPresentationModel', + permissionType: 'document-property-value', documentType: value.documentType, propertyType: value.propertyType, verbs: value.verbs, From d21a13d2d697e505d257dc6531786ff207ec7dd4 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 18 Mar 2025 13:19:01 +0100 Subject: [PATCH 056/106] require specific permission type --- .../documents/user-permissions/document-property-value/types.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/types.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/types.ts index ad384408bc12..551d8bfc0571 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/types.ts @@ -2,6 +2,7 @@ import type { UmbReferenceByUnique } from '@umbraco-cms/backoffice/models'; import type { UmbUserPermissionModel } from '@umbraco-cms/backoffice/user-permission'; export interface UmbDocumentPropertyValueUserPermissionModel extends UmbUserPermissionModel { + permissionType: 'document-property-value'; documentType: UmbReferenceByUnique; propertyType: UmbReferenceByUnique; } From 8da65504a7b5101274ea5698676869ad35e8dede Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 18 Mar 2025 13:20:02 +0100 Subject: [PATCH 057/106] use correct schema type --- .../user-permissions/document-property-value/manifests.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/manifests.ts index 4b82fffcf4b6..348755c7a664 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/manifests.ts @@ -4,6 +4,7 @@ import { } from './constants.js'; import { manifests as documentPropertyValueGranularPermissionFlowModalManifests } from './document-property-value-granular-permission-flow-modal/manifests.js'; import { manifests as conditionManifests } from './conditions/manifests.js'; +import { manifests as dataManifests } from './data/manifests.js'; import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; export const manifests: Array = [ @@ -40,11 +41,12 @@ export const manifests: Array = './input-document-property-value-granular-user-permission/input-document-property-value-granular-user-permission.element.js' ), meta: { - schemaType: 'DocumentPropertyValuePermissionPresentationModel', + schemaType: 'DocumentTypePropertyPermissionPresentationModel', label: 'Document Property Values', description: 'Assign Permissions to Document property values', }, }, ...documentPropertyValueGranularPermissionFlowModalManifests, ...conditionManifests, + ...dataManifests, ]; From ac58500d2a2b8dccb2616063327ca21ab49ae983 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 18 Mar 2025 13:55:36 +0100 Subject: [PATCH 058/106] add mappings --- .../conditions/utils.ts | 8 +++-- .../from-server.management-api.mapping.ts | 32 +++++++++++++++++++ .../document-property-value/data/manifests.ts | 22 +++++++++++++ .../data/to-server.management-api.mapping.ts | 30 +++++++++++++++++ ...-value-granular-user-permission.element.ts | 3 +- .../document-property-value/types.ts | 3 +- .../user-permission.ts | 3 ++ .../packages/user/user-permission/types.ts | 2 +- 8 files changed, 98 insertions(+), 5 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/data/from-server.management-api.mapping.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/data/manifests.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/data/to-server.management-api.mapping.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/user-permission.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/conditions/utils.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/conditions/utils.ts index caca66dc3686..04e05d6156ef 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/conditions/utils.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/conditions/utils.ts @@ -1,12 +1,16 @@ import type { UmbDocumentPropertyValueUserPermissionModel } from '../types.js'; +import { UMB_DOCUMENT_PROPERTY_VALUE_USER_PERMISSION_TYPE } from '../user-permission.js'; /** * * @param permission - * @returns {boolean} True if the permission is a document-property-value' permission + * @returns {boolean} True if the permission is a permission for document property values */ export function isDocumentPropertyValueUserPermission( permission: unknown, ): permission is UmbDocumentPropertyValueUserPermissionModel { - return (permission as UmbDocumentPropertyValueUserPermissionModel).permissionType === 'document-property-value'; + return ( + (permission as UmbDocumentPropertyValueUserPermissionModel).userPermissionType === + UMB_DOCUMENT_PROPERTY_VALUE_USER_PERMISSION_TYPE + ); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/data/from-server.management-api.mapping.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/data/from-server.management-api.mapping.ts new file mode 100644 index 000000000000..bbb10f425cef --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/data/from-server.management-api.mapping.ts @@ -0,0 +1,32 @@ +import type { UmbDocumentPropertyValueUserPermissionModel } from '../types.js'; +import { UMB_DOCUMENT_PROPERTY_VALUE_USER_PERMISSION_TYPE } from '../user-permission.js'; +import type { UmbDataSourceDataMapping } from '@umbraco-cms/backoffice/repository'; +import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; +import type { DocumentTypePropertyPermissionPresentationModel } from '@umbraco-cms/backoffice/external/backend-api'; + +export class UmbDocumentPropertyValueUserPermissionFromManagementApiDataMapping + extends UmbControllerBase + implements + UmbDataSourceDataMapping< + DocumentTypePropertyPermissionPresentationModel, + UmbDocumentPropertyValueUserPermissionModel + > +{ + async map( + data: DocumentTypePropertyPermissionPresentationModel, + ): Promise { + return { + $type: data.$type, + userPermissionType: UMB_DOCUMENT_PROPERTY_VALUE_USER_PERMISSION_TYPE, + documentType: { + unique: data.documentType.id, + }, + propertyType: { + unique: data.propertyType.id, + }, + verbs: data.verbs, + }; + } +} + +export { UmbDocumentPropertyValueUserPermissionFromManagementApiDataMapping as api }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/data/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/data/manifests.ts new file mode 100644 index 000000000000..bf6f17f878f6 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/data/manifests.ts @@ -0,0 +1,22 @@ +import { UMB_DOCUMENT_PROPERTY_VALUE_USER_PERMISSION_TYPE } from '../user-permission.js'; +import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; +import { UMB_MANAGEMENT_API_DATA_SOURCE_ALIAS } from '@umbraco-cms/backoffice/repository'; + +export const manifests: Array = [ + { + type: 'dataSourceDataMapping', + alias: 'Umb.DataSourceDataMapping.ManagementApi.To.DocumentTypePropertyPermissionPresentationModel', + name: 'Document Property Value Permission To Management Api Data Mapping', + api: () => import('./to-server.management-api.mapping.js'), + forDataSource: UMB_MANAGEMENT_API_DATA_SOURCE_ALIAS, + forDataModel: UMB_DOCUMENT_PROPERTY_VALUE_USER_PERMISSION_TYPE, + }, + { + type: 'dataSourceDataMapping', + alias: 'Umb.DataSourceDataMapping.ManagementApi.From.DocumentTypePropertyPermissionPresentationModel', + name: 'Document Property Value Permission From Management Api Data Mapping', + api: () => import('./from-server.management-api.mapping.js'), + forDataSource: UMB_MANAGEMENT_API_DATA_SOURCE_ALIAS, + forDataModel: 'DocumentTypePropertyPermissionPresentationModel', + }, +]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/data/to-server.management-api.mapping.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/data/to-server.management-api.mapping.ts new file mode 100644 index 000000000000..4390977d18f0 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/data/to-server.management-api.mapping.ts @@ -0,0 +1,30 @@ +import type { UmbDocumentPropertyValueUserPermissionModel } from '../types.js'; +import type { UmbDataSourceDataMapping } from '@umbraco-cms/backoffice/repository'; +import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; +import type { DocumentTypePropertyPermissionPresentationModel } from '@umbraco-cms/backoffice/external/backend-api'; + +export class UmbDocumentPropertyValueUserPermissionToManagementApiDataMapping + extends UmbControllerBase + implements + UmbDataSourceDataMapping< + UmbDocumentPropertyValueUserPermissionModel, + DocumentTypePropertyPermissionPresentationModel + > +{ + async map( + data: UmbDocumentPropertyValueUserPermissionModel, + ): Promise { + return { + $type: 'DocumentTypePropertyPermissionPresentationModel', + documentType: { + id: data.documentType.unique, + }, + propertyType: { + id: data.propertyType.unique, + }, + verbs: data.verbs, + }; + } +} + +export { UmbDocumentPropertyValueUserPermissionToManagementApiDataMapping as api }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/input-document-property-value-granular-user-permission/input-document-property-value-granular-user-permission.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/input-document-property-value-granular-user-permission/input-document-property-value-granular-user-permission.element.ts index 85986a3f8110..edc25e684dd3 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/input-document-property-value-granular-user-permission/input-document-property-value-granular-user-permission.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/input-document-property-value-granular-user-permission/input-document-property-value-granular-user-permission.element.ts @@ -1,5 +1,6 @@ import type { UmbDocumentPropertyValueUserPermissionModel as UmbDocumentPropertyValueUserPermissionModel } from '../types.js'; import { UMB_DOCUMENT_PROPERTY_VALUE_GRANULAR_USER_PERMISSION_FLOW_MODAL } from '../document-property-value-granular-permission-flow-modal/index.js'; +import { UMB_DOCUMENT_PROPERTY_VALUE_USER_PERMISSION_TYPE } from '../user-permission.js'; import { css, customElement, html, property, repeat, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; @@ -70,7 +71,7 @@ export class UmbInputDocumentPropertyValueGranularUserPermissionElement extends const permissionItem: UmbDocumentPropertyValueUserPermissionModel = { $type: 'DocumentTypePropertyPermissionPresentationModel', - permissionType: 'document-property-value', + userPermissionType: UMB_DOCUMENT_PROPERTY_VALUE_USER_PERMISSION_TYPE, documentType: value.documentType, propertyType: value.propertyType, verbs: value.verbs, diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/types.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/types.ts index 551d8bfc0571..d5334bb7572f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/types.ts @@ -1,8 +1,9 @@ +import type { UmbDocumentPropertyValueUserPermissionType } from './user-permission.js'; import type { UmbReferenceByUnique } from '@umbraco-cms/backoffice/models'; import type { UmbUserPermissionModel } from '@umbraco-cms/backoffice/user-permission'; export interface UmbDocumentPropertyValueUserPermissionModel extends UmbUserPermissionModel { - permissionType: 'document-property-value'; + userPermissionType: UmbDocumentPropertyValueUserPermissionType; documentType: UmbReferenceByUnique; propertyType: UmbReferenceByUnique; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/user-permission.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/user-permission.ts new file mode 100644 index 000000000000..f261a0c8ef61 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/user-permission.ts @@ -0,0 +1,3 @@ +export const UMB_DOCUMENT_PROPERTY_VALUE_USER_PERMISSION_TYPE = 'document-property-value'; + +export type UmbDocumentPropertyValueUserPermissionType = typeof UMB_DOCUMENT_PROPERTY_VALUE_USER_PERMISSION_TYPE; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user-permission/types.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user-permission/types.ts index 575b120ae30b..81599abe2e80 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user-permission/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user-permission/types.ts @@ -2,6 +2,6 @@ export type * from './user-granular-permission.extension.js'; export type * from './entity-user-permission.extension.js'; export interface UmbUserPermissionModel { $type: string; - permissionType: string; + userPermissionType: string; verbs: Array; } From 6fe3b80567cf689c8a43197c02e85a3f7f80cc89 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 18 Mar 2025 15:01:30 +0100 Subject: [PATCH 059/106] clean up --- .../block/copy/block-grid-to-block-copy-translator.test.ts | 1 + .../paste/block-to-block-grid-paste-translator.test.ts | 1 + .../copy/block-grid-to-grid-block-copy-translator.test.ts | 1 + .../grid-block-to-block-grid-paste-translator.test.ts | 1 + .../block/copy/block-list-to-block-copy-translator.test.ts | 1 + .../paste/block-to-block-list-paste-translator.test.ts | 1 + .../merge-content-variant-data.controller.test.ts | 4 ++++ .../src/packages/core/content/types.ts | 3 ++- .../src/packages/documents/document-blueprints/index.ts | 1 + .../detail/document-blueprint-detail.server.data-source.ts | 2 ++ .../src/packages/documents/document-blueprints/types.ts | 1 + .../src/packages/documents/documents/entity.ts | 4 ++++ .../src/packages/documents/documents/index.ts | 1 + .../document-published-pending-changes.manager.test.ts | 5 ++++- .../repository/document-publishing.server.data-source.ts | 3 ++- .../detail/document-detail.server.data-source.ts | 3 ++- .../src/packages/documents/documents/types.ts | 2 +- .../property-type-modal/property-type-modal.element.ts | 3 ++- ...ment-property-value-granular-user-permission.element.ts | 5 +++-- .../user-permissions/document-property-value/manifests.ts | 5 +++-- .../media/media/dropzone/dropzone-manager.class.ts | 2 ++ .../src/packages/media/media/entity.ts | 4 ++++ .../src/packages/media/media/types.ts | 2 +- .../src/packages/members/member/entity.ts | 4 ++++ .../repository/detail/member-detail.server.data-source.ts | 7 ++++--- .../src/packages/members/member/types.ts | 2 +- .../src/packages/user/user-permission/types.ts | 2 +- 27 files changed, 55 insertions(+), 16 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/clipboard/block/copy/block-grid-to-block-copy-translator.test.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/clipboard/block/copy/block-grid-to-block-copy-translator.test.ts index 8f34c4aa0f55..ab9ef567f496 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/clipboard/block/copy/block-grid-to-block-copy-translator.test.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/clipboard/block/copy/block-grid-to-block-copy-translator.test.ts @@ -25,6 +25,7 @@ describe('UmbBlockListToBlockClipboardCopyPropertyValueTranslator', () => { alias: 'headline', editorAlias: 'Umbraco.TextBox', value: 'Headline value', + entityType: '', }, ], }, diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/clipboard/block/paste/block-to-block-grid-paste-translator.test.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/clipboard/block/paste/block-to-block-grid-paste-translator.test.ts index 571720619f55..d0609714d26b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/clipboard/block/paste/block-to-block-grid-paste-translator.test.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/clipboard/block/paste/block-to-block-grid-paste-translator.test.ts @@ -26,6 +26,7 @@ describe('UmbBlockToBlockGridClipboardPastePropertyValueTranslator', () => { alias: 'headline', editorAlias: 'Umbraco.TextBox', value: 'Headline value', + entityType: '', }, ], }, diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/clipboard/grid-block/copy/block-grid-to-grid-block-copy-translator.test.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/clipboard/grid-block/copy/block-grid-to-grid-block-copy-translator.test.ts index 6129436f8242..9d83d875297a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/clipboard/grid-block/copy/block-grid-to-grid-block-copy-translator.test.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/clipboard/grid-block/copy/block-grid-to-grid-block-copy-translator.test.ts @@ -30,6 +30,7 @@ describe('UmbBlockListToBlockClipboardCopyPropertyValueTranslator', () => { alias: 'headline', editorAlias: 'Umbraco.TextBox', value: 'Headline value', + entityType: '', }, ], }, diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/clipboard/grid-block/paste/grid-block-to-block-grid-paste-translator.test.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/clipboard/grid-block/paste/grid-block-to-block-grid-paste-translator.test.ts index 105cfa9e18a7..ace3d0d20c54 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/clipboard/grid-block/paste/grid-block-to-block-grid-paste-translator.test.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/clipboard/grid-block/paste/grid-block-to-block-grid-paste-translator.test.ts @@ -24,6 +24,7 @@ describe('UmbGridBlockToBlockGridClipboardPastePropertyValueTranslator', () => { alias: 'headline', editorAlias: 'Umbraco.TextBox', value: 'Headline value', + entityType: '', }, ], }, diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/clipboard/block/copy/block-list-to-block-copy-translator.test.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/clipboard/block/copy/block-list-to-block-copy-translator.test.ts index bc71ec139f9c..e96719af56e8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/clipboard/block/copy/block-list-to-block-copy-translator.test.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/clipboard/block/copy/block-list-to-block-copy-translator.test.ts @@ -25,6 +25,7 @@ describe('UmbBlockListToBlockClipboardCopyPropertyValueTranslator', () => { alias: 'headline', editorAlias: 'Umbraco.TextBox', value: 'Headline value', + entityType: '', }, ], }, diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/clipboard/block/paste/block-to-block-list-paste-translator.test.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/clipboard/block/paste/block-to-block-list-paste-translator.test.ts index 56fb74df4221..dab83b27b64a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/clipboard/block/paste/block-to-block-list-paste-translator.test.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/clipboard/block/paste/block-to-block-list-paste-translator.test.ts @@ -25,6 +25,7 @@ describe('UmbBlockToBlockListClipboardPastePropertyValueTranslator', () => { alias: 'headline', editorAlias: 'Umbraco.TextBox', value: 'Headline value', + entityType: '', }, ], }, diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content/controller/merge-content-variant-data.controller.test.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content/controller/merge-content-variant-data.controller.test.ts index d2ee6658955f..53008678a729 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content/controller/merge-content-variant-data.controller.test.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content/controller/merge-content-variant-data.controller.test.ts @@ -74,6 +74,7 @@ describe('UmbMergeContentVariantDataController', () => { alias: 'test', culture: null, segment: null, + entityType: '', value: { nestedValue: { editorAlias: 'some-editor', @@ -94,6 +95,7 @@ describe('UmbMergeContentVariantDataController', () => { alias: 'test', culture: null, segment: null, + entityType: '', value: { nestedValue: { editorAlias: 'some-editor', @@ -123,6 +125,7 @@ describe('UmbMergeContentVariantDataController', () => { alias: 'test', culture: null, segment: null, + entityType: '', value: { nestedValue: { editorAlias: 'some-editor', @@ -143,6 +146,7 @@ describe('UmbMergeContentVariantDataController', () => { alias: 'test', culture: null, segment: null, + entityType: '', value: { nestedValue: { editorAlias: 'some-editor', diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content/types.ts index 4cded9d86cb2..0a3e945fca9f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content/types.ts @@ -8,8 +8,9 @@ export interface UmbElementDetailModel { } export interface UmbElementValueModel extends UmbPropertyValueData { - editorAlias: string; culture: string | null; + editorAlias: string; + entityType: string; segment: string | null; } // eslint-disable-next-line @typescript-eslint/no-empty-object-type diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/index.ts index 4c28e6c8da47..a5e20e96523c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/index.ts @@ -1,4 +1,5 @@ export * from './constants.js'; export * from './repository/index.js'; +export * from './entity.js'; export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/repository/detail/document-blueprint-detail.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/repository/detail/document-blueprint-detail.server.data-source.ts index b823c9bfe3e6..4301d43f9fad 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/repository/detail/document-blueprint-detail.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/repository/detail/document-blueprint-detail.server.data-source.ts @@ -9,6 +9,7 @@ import type { import { DocumentBlueprintService } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { UMB_DOCUMENT_PROPERTY_VALUE_ENTITY_TYPE } from '@umbraco-cms/backoffice/document'; /** * A data source for the Document that fetches data from the server @@ -93,6 +94,7 @@ export class UmbDocumentBlueprintServerDataSource implements UmbDetailDataSource values: data.values.map((value) => { return { editorAlias: value.editorAlias, + entityType: UMB_DOCUMENT_PROPERTY_VALUE_ENTITY_TYPE, culture: value.culture || null, segment: value.segment || null, alias: value.alias, diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/types.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/types.ts index c6a4d4f66497..da735359b897 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/types.ts @@ -3,6 +3,7 @@ import type { UmbEntityVariantModel, UmbEntityVariantOptionModel } from '@umbrac import type { UmbReferenceByUnique } from '@umbraco-cms/backoffice/models'; import { DocumentVariantStateModel as UmbDocumentBlueprintVariantState } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbElementValueModel } from '@umbraco-cms/backoffice/content'; +import type { UmbDocumentPropertyValueEntityType } from '@umbraco-cms/backoffice/document'; export { UmbDocumentBlueprintVariantState }; export type * from './tree/types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity.ts index 13602ef85d70..ff1bbcf4c5dd 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity.ts @@ -5,3 +5,7 @@ export type UmbDocumentEntityType = typeof UMB_DOCUMENT_ENTITY_TYPE; export type UmbDocumentRootEntityType = typeof UMB_DOCUMENT_ROOT_ENTITY_TYPE; export type UmbDocumentEntityTypeUnion = UmbDocumentEntityType | UmbDocumentRootEntityType; + +// TODO: move this to a better location inside the document module +export const UMB_DOCUMENT_PROPERTY_VALUE_ENTITY_TYPE = 'document-property-value'; +export type UmbDocumentPropertyValueEntityType = typeof UMB_DOCUMENT_PROPERTY_VALUE_ENTITY_TYPE; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/index.ts index a14bf00b99e1..317a4ffda72f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/index.ts @@ -4,6 +4,7 @@ export * from './audit-log/index.js'; export * from './components/index.js'; export * from './constants.js'; export * from './entity-actions/index.js'; +export * from './entity.js'; export * from './global-contexts/index.js'; export * from './item/index.js'; export * from './modals/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/pending-changes/document-published-pending-changes.manager.test.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/pending-changes/document-published-pending-changes.manager.test.ts index a3257a21e856..7df1d7e55692 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/pending-changes/document-published-pending-changes.manager.test.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/pending-changes/document-published-pending-changes.manager.test.ts @@ -5,7 +5,7 @@ import { UmbControllerHostElementMixin } from '@umbraco-cms/backoffice/controlle import { UmbDocumentPublishedPendingChangesManager } from './document-published-pending-changes.manager.js'; import { DocumentVariantStateModel } from '@umbraco-cms/backoffice/external/backend-api'; import { type UmbDocumentDetailModel } from '../../types.js'; -import { UMB_DOCUMENT_ENTITY_TYPE } from '../../entity.js'; +import { UMB_DOCUMENT_ENTITY_TYPE, UMB_DOCUMENT_PROPERTY_VALUE_ENTITY_TYPE } from '../../entity.js'; @customElement('test-my-controller-host') class UmbTestControllerHostElement extends UmbControllerHostElementMixin(HTMLElement) {} @@ -77,6 +77,7 @@ describe('UmbSelectionManager', () => { values: [ { editorAlias: 'Umbraco.TextBox', + entityType: UMB_DOCUMENT_PROPERTY_VALUE_ENTITY_TYPE, alias: 'prop1', culture: null, segment: null, @@ -158,6 +159,7 @@ describe('UmbSelectionManager', () => { values: [ { editorAlias: 'Umbraco.TextBox', + entityType: UMB_DOCUMENT_PROPERTY_VALUE_ENTITY_TYPE, alias: 'prop1', culture: 'en-US', segment: null, @@ -165,6 +167,7 @@ describe('UmbSelectionManager', () => { }, { editorAlias: 'Umbraco.TextBox', + entityType: UMB_DOCUMENT_PROPERTY_VALUE_ENTITY_TYPE, alias: 'prop1', culture: 'da-DK', segment: null, diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/repository/document-publishing.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/repository/document-publishing.server.data-source.ts index add5a266fa1a..2e54d41e2b25 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/repository/document-publishing.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/repository/document-publishing.server.data-source.ts @@ -1,5 +1,5 @@ import type { UmbDocumentDetailModel, UmbDocumentVariantPublishModel } from '../../types.js'; -import { UMB_DOCUMENT_ENTITY_TYPE } from '../../entity.js'; +import { UMB_DOCUMENT_ENTITY_TYPE, UMB_DOCUMENT_PROPERTY_VALUE_ENTITY_TYPE } from '../../entity.js'; import type { CultureAndScheduleRequestModel, PublishDocumentRequestModel, @@ -137,6 +137,7 @@ export class UmbDocumentPublishingServerDataSource { values: data.values.map((value) => { return { editorAlias: value.editorAlias, + entityType: UMB_DOCUMENT_PROPERTY_VALUE_ENTITY_TYPE, culture: value.culture || null, segment: value.segment || null, alias: value.alias, diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/detail/document-detail.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/detail/document-detail.server.data-source.ts index 1b96b586c547..2938f7709e9e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/detail/document-detail.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/repository/detail/document-detail.server.data-source.ts @@ -1,5 +1,5 @@ import type { UmbDocumentDetailModel } from '../../types.js'; -import { UMB_DOCUMENT_ENTITY_TYPE } from '../../entity.js'; +import { UMB_DOCUMENT_ENTITY_TYPE, UMB_DOCUMENT_PROPERTY_VALUE_ENTITY_TYPE } from '../../entity.js'; import { UmbId } from '@umbraco-cms/backoffice/id'; import type { UmbDetailDataSource } from '@umbraco-cms/backoffice/repository'; import type { @@ -94,6 +94,7 @@ export class UmbDocumentServerDataSource implements UmbDetailDataSource { return { editorAlias: value.editorAlias, + entityType: UMB_DOCUMENT_PROPERTY_VALUE_ENTITY_TYPE, culture: value.culture || null, segment: value.segment || null, alias: value.alias, diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/types.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/types.ts index bf3fe6fd1f18..6ce273ef1c57 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/types.ts @@ -1,4 +1,4 @@ -import type { UmbDocumentEntityType } from './entity.js'; +import type { UmbDocumentEntityType, UmbDocumentPropertyValueEntityType } from './entity.js'; import type { UmbEntityVariantModel, UmbEntityVariantOptionModel, diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/property-type-modal/property-type-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/property-type-modal/property-type-modal.element.ts index 6ce0d24fa4fe..bce2e80a1497 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/property-type-modal/property-type-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/property-type-modal/property-type-modal.element.ts @@ -1,3 +1,4 @@ +import { UMB_DOCUMENT_PROPERTY_VALUE_ENTITY_TYPE } from '../../../../entity.js'; import type { UmbDocumentPropertyValueGranularUserPermissionFlowPropertyTypeModalData, UmbDocumentPropertyValueGranularUserPermissionFlowPropertyTypeModalValue, @@ -73,7 +74,7 @@ export class UmbDocumentPropertyValueGranularUserPermissionFlowPropertyTypeModal const modal = modalManager.open(this, UMB_ENTITY_USER_PERMISSION_MODAL, { data: { - entityType: 'document-property-value', + entityType: UMB_DOCUMENT_PROPERTY_VALUE_ENTITY_TYPE, headline, preset: { allowedVerbs: this.data?.preset?.verbs ?? [], diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/input-document-property-value-granular-user-permission/input-document-property-value-granular-user-permission.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/input-document-property-value-granular-user-permission/input-document-property-value-granular-user-permission.element.ts index edc25e684dd3..c5ebe59a5815 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/input-document-property-value-granular-user-permission/input-document-property-value-granular-user-permission.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/input-document-property-value-granular-user-permission/input-document-property-value-granular-user-permission.element.ts @@ -1,6 +1,7 @@ import type { UmbDocumentPropertyValueUserPermissionModel as UmbDocumentPropertyValueUserPermissionModel } from '../types.js'; import { UMB_DOCUMENT_PROPERTY_VALUE_GRANULAR_USER_PERMISSION_FLOW_MODAL } from '../document-property-value-granular-permission-flow-modal/index.js'; import { UMB_DOCUMENT_PROPERTY_VALUE_USER_PERMISSION_TYPE } from '../user-permission.js'; +import { UMB_DOCUMENT_PROPERTY_VALUE_ENTITY_TYPE } from '../../../entity.js'; import { css, customElement, html, property, repeat, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; @@ -60,7 +61,7 @@ export class UmbInputDocumentPropertyValueGranularUserPermissionElement extends const modal = modalManager.open(this, UMB_DOCUMENT_PROPERTY_VALUE_GRANULAR_USER_PERMISSION_FLOW_MODAL, { data: { preset: { - verbs: this.#getFallbackPermissionVerbsForEntityType('document-property-value'), + verbs: this.#getFallbackPermissionVerbsForEntityType(UMB_DOCUMENT_PROPERTY_VALUE_ENTITY_TYPE), }, }, }); @@ -105,7 +106,7 @@ export class UmbInputDocumentPropertyValueGranularUserPermissionElement extends const modal = modalManager.open(this, UMB_ENTITY_USER_PERMISSION_MODAL, { data: { - entityType: 'document-property-value', + entityType: UMB_DOCUMENT_PROPERTY_VALUE_ENTITY_TYPE, headline, preset: { allowedVerbs: currentPermission.verbs, diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/manifests.ts index 348755c7a664..9b67fb6bfa9c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/manifests.ts @@ -1,3 +1,4 @@ +import { UMB_DOCUMENT_PROPERTY_VALUE_ENTITY_TYPE } from '../../entity.js'; import { UMB_USER_PERMISSION_DOCUMENT_PROPERTY_VALUE_READ, UMB_USER_PERMISSION_DOCUMENT_PROPERTY_VALUE_WRITE, @@ -12,7 +13,7 @@ export const manifests: Array = type: 'entityUserPermission', alias: 'Umb.EntityUserPermission.Document.PropertyValue.Read', name: 'Read Document Property Value User Permission', - forEntityTypes: ['document-property-value'], + forEntityTypes: [UMB_DOCUMENT_PROPERTY_VALUE_ENTITY_TYPE], weight: 200, meta: { verbs: [UMB_USER_PERMISSION_DOCUMENT_PROPERTY_VALUE_READ], @@ -24,7 +25,7 @@ export const manifests: Array = type: 'entityUserPermission', alias: 'Umb.EntityUserPermission.DocumentPropertyValue.Write', name: 'Write Document Property Value User Permission', - forEntityTypes: ['document-property-value'], + forEntityTypes: [UMB_DOCUMENT_PROPERTY_VALUE_ENTITY_TYPE], weight: 200, meta: { verbs: [UMB_USER_PERMISSION_DOCUMENT_PROPERTY_VALUE_WRITE], diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/dropzone/dropzone-manager.class.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/dropzone/dropzone-manager.class.ts index b58069b537bc..be04d1ff1039 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/dropzone/dropzone-manager.class.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/dropzone/dropzone-manager.class.ts @@ -1,5 +1,6 @@ import { UmbMediaDetailRepository } from '../repository/index.js'; import type { UmbMediaDetailModel, UmbMediaValueModel } from '../types.js'; +import { UMB_MEDIA_PROPERTY_VALUE_ENTITY_TYPE } from '../entity.js'; import { UmbFileDropzoneItemStatus } from './types.js'; import { UMB_DROPZONE_MEDIA_TYPE_PICKER_MODAL } from './modals/index.js'; import type { @@ -280,6 +281,7 @@ export class UmbDropzoneManager extends UmbControllerBase { value: { temporaryFileId: item.temporaryFile?.temporaryUnique }, culture: null, segment: null, + entityType: UMB_MEDIA_PROPERTY_VALUE_ENTITY_TYPE, }; const preset: Partial = { diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/entity.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/entity.ts index 06dc488450e5..11775327fbd8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/entity.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/entity.ts @@ -8,3 +8,7 @@ export type UmbMediaRootEntityType = typeof UMB_MEDIA_ROOT_ENTITY_TYPE; export type UmbMediaPlaceholderEntityType = typeof UMB_MEDIA_PLACEHOLDER_ENTITY_TYPE; export type UmbMediaEntityTypeUnion = UmbMediaEntityType | UmbMediaRootEntityType; + +// TODO: move this to a better location inside the media module +export const UMB_MEDIA_PROPERTY_VALUE_ENTITY_TYPE = 'media-property-value'; +export type UmbMediaPropertyValueEntityType = typeof UMB_MEDIA_PROPERTY_VALUE_ENTITY_TYPE; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/types.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/types.ts index c9545de5a05e..99c31330c7c8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/types.ts @@ -1,4 +1,4 @@ -import type { UmbMediaEntityType } from './entity.js'; +import type { UmbMediaEntityType, UmbMediaPropertyValueEntityType } from './entity.js'; import type { UmbEntityVariantModel, UmbEntityVariantOptionModel } from '@umbraco-cms/backoffice/variant'; import type { UmbReferenceByUnique } from '@umbraco-cms/backoffice/models'; import type { UmbContentDetailModel, UmbElementValueModel } from '@umbraco-cms/backoffice/content'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/entity.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/entity.ts index 3878b8d0d59b..59dd937a22c8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member/entity.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/entity.ts @@ -3,3 +3,7 @@ export const UMB_MEMBER_ROOT_ENTITY_TYPE = 'member-root'; export type UmbMemberEntityType = typeof UMB_MEMBER_ENTITY_TYPE; export type UmbMemberRootEntityType = typeof UMB_MEMBER_ROOT_ENTITY_TYPE; + +// TODO: move this to a better location inside the member module +export const UMB_MEMBER_PROPERTY_VALUE_ENTITY_TYPE = 'member-property-value'; +export type UmbMemberPropertyValueEntityType = typeof UMB_MEMBER_PROPERTY_VALUE_ENTITY_TYPE; diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/repository/detail/member-detail.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/repository/detail/member-detail.server.data-source.ts index 30d4bddac99c..7b26ad573bf8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member/repository/detail/member-detail.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/repository/detail/member-detail.server.data-source.ts @@ -1,5 +1,5 @@ import type { UmbMemberDetailModel } from '../../types.js'; -import { UMB_MEMBER_ENTITY_TYPE } from '../../entity.js'; +import { UMB_MEMBER_ENTITY_TYPE, UMB_MEMBER_PROPERTY_VALUE_ENTITY_TYPE } from '../../entity.js'; import { UmbMemberKind } from '../../utils/index.js'; import { UmbId } from '@umbraco-cms/backoffice/id'; import type { UmbDetailDataSource } from '@umbraco-cms/backoffice/repository'; @@ -102,10 +102,11 @@ export class UmbMemberServerDataSource implements UmbDetailDataSource { return { - editorAlias: value.editorAlias, + alias: value.alias, culture: value.culture || null, + editorAlias: value.editorAlias, + entityType: UMB_MEMBER_PROPERTY_VALUE_ENTITY_TYPE, segment: value.segment || null, - alias: value.alias, value: value.value, }; }), diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/types.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/types.ts index cb8c9c153dcc..60e1b6d09721 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/types.ts @@ -1,4 +1,4 @@ -import type { UmbMemberEntityType } from './entity.js'; +import type { UmbMemberEntityType, UmbMemberPropertyValueEntityType } from './entity.js'; import type { UmbMemberKindType } from './utils/index.js'; import type { UmbEntityVariantModel, UmbEntityVariantOptionModel } from '@umbraco-cms/backoffice/variant'; import type { UmbContentDetailModel, UmbElementValueModel } from '@umbraco-cms/backoffice/content'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user-permission/types.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user-permission/types.ts index 81599abe2e80..ffba0215efa7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user-permission/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user-permission/types.ts @@ -2,6 +2,6 @@ export type * from './user-granular-permission.extension.js'; export type * from './entity-user-permission.extension.js'; export interface UmbUserPermissionModel { $type: string; - userPermissionType: string; + userPermissionType?: string; verbs: Array; } From 3b3832d456dbebb09fcbf8aa4a937660963bb0a9 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 18 Mar 2025 15:38:55 +0100 Subject: [PATCH 060/106] log errors --- .../repository/data-mapper/data-mapper.ts | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/repository/data-mapper/data-mapper.ts b/src/Umbraco.Web.UI.Client/src/packages/core/repository/data-mapper/data-mapper.ts index 88f0fbd27450..3cbce72a028b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/repository/data-mapper/data-mapper.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/repository/data-mapper/data-mapper.ts @@ -13,21 +13,29 @@ export class UmbDataSourceDataMapper) { if (!args.forDataSource) { - throw new Error('data source identifier is required'); + const message = 'data source identifier is required'; + console.error(message); + throw new Error(message); } if (!args.forDataModel) { - throw new Error('data identifier is required'); + const message = 'forDataModel is missing'; + console.error(message); + throw new Error(message); } if (!args.data) { - throw new Error('data is required'); + const message = 'data is required'; + console.error(message); + throw new Error(message); } const dataMapping = await this.#dataMappingResolver.resolve(args.forDataSource, args.forDataModel); if (!dataMapping && !args.fallback) { - throw new Error('Data mapping not found and no fallback provided.'); + const message = 'Data mapping not found and no fallback provided.'; + console.error(message); + throw new Error(message); } if (!dataMapping && args.fallback) { @@ -35,7 +43,9 @@ export class UmbDataSourceDataMapper Date: Tue, 18 Mar 2025 15:39:14 +0100 Subject: [PATCH 061/106] fix mapping --- .../detail/user-group-detail.server.data-source.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user-group/repository/detail/user-group-detail.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user-group/repository/detail/user-group-detail.server.data-source.ts index 08af21b12548..15d8e29e3160 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user-group/repository/detail/user-group-detail.server.data-source.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user-group/repository/detail/user-group-detail.server.data-source.ts @@ -164,13 +164,9 @@ export class UmbUserGroupServerDataSource const permissionDataPromises = model.permissions.map(async (item) => { return this.#dataMapper.map({ - forDataModel: item.permissionType, + forDataModel: item.userPermissionType, data: item, - fallback: async () => { - return { - ...item, - }; - }, + fallback: async () => item, }); }); From 1a1c770859dbb83071c98f7513954682e6289665 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 18 Mar 2025 16:57:57 +0100 Subject: [PATCH 062/106] null check for icon --- ...operty-value-granular-user-permission.element.ts | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/input-document-property-value-granular-user-permission/input-document-property-value-granular-user-permission.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/input-document-property-value-granular-user-permission/input-document-property-value-granular-user-permission.element.ts index c5ebe59a5815..3e689f66ea77 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/input-document-property-value-granular-user-permission/input-document-property-value-granular-user-permission.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/input-document-property-value-granular-user-permission/input-document-property-value-granular-user-permission.element.ts @@ -2,7 +2,16 @@ import type { UmbDocumentPropertyValueUserPermissionModel as UmbDocumentProperty import { UMB_DOCUMENT_PROPERTY_VALUE_GRANULAR_USER_PERMISSION_FLOW_MODAL } from '../document-property-value-granular-permission-flow-modal/index.js'; import { UMB_DOCUMENT_PROPERTY_VALUE_USER_PERMISSION_TYPE } from '../user-permission.js'; import { UMB_DOCUMENT_PROPERTY_VALUE_ENTITY_TYPE } from '../../../entity.js'; -import { css, customElement, html, property, repeat, state } from '@umbraco-cms/backoffice/external/lit'; +import { + css, + customElement, + html, + ifDefined, + nothing, + property, + repeat, + state, +} from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; @@ -211,7 +220,7 @@ export class UmbInputDocumentPropertyValueGranularUserPermissionElement extends return html` - + ${documentType?.icon ? html`` : nothing} ${this.#renderEditButton(permission)} ${this.#renderRemoveButton(permission)} From d8f05e36df88b270cf71ffc60a6f630ece58c85d Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 18 Mar 2025 16:58:15 +0100 Subject: [PATCH 063/106] use fallback if there is no forDataModel --- .../core/repository/data-mapper/data-mapper.ts | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/repository/data-mapper/data-mapper.ts b/src/Umbraco.Web.UI.Client/src/packages/core/repository/data-mapper/data-mapper.ts index 3cbce72a028b..2022d024df03 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/repository/data-mapper/data-mapper.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/repository/data-mapper/data-mapper.ts @@ -18,18 +18,22 @@ export class UmbDataSourceDataMapper Date: Tue, 18 Mar 2025 17:07:37 +0100 Subject: [PATCH 064/106] add translations --- src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts | 6 ++---- src/Umbraco.Web.UI.Client/src/assets/lang/en.ts | 3 ++- .../user-permissions/document-property-value/manifests.ts | 1 + .../documents/documents/user-permissions/manifests.ts | 1 + 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts index d864c5ce7fa9..952b2b168dc7 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts @@ -1247,7 +1247,8 @@ export default { colorsTitle: 'Colors', colorsDescription: 'Add, remove or sort colors', showLabelTitle: 'Include labels?', - showLabelDescription: 'Stores colors as a JSON object containing both the color hex string and label, rather than just the hex string.', + showLabelDescription: + 'Stores colors as a JSON object containing both the color hex string and label, rather than just the hex string.', }, contentPicker: { allowedItemTypes: 'You can only select items of type(s): %0%', @@ -1982,9 +1983,6 @@ export default { permissionsGranularHelp: 'Set permissions for specific nodes', granularRightsLabel: 'Documents', granularRightsDescription: 'Assign permissions to specific documents', - permissionsEntityGroup_document: 'Content', - permissionsEntityGroup_media: 'Media', - permissionsEntityGroup_member: 'Member', profile: 'Profile', searchAllChildren: 'Search all children', languagesHelp: 'Limit the languages users have access to edit', diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/en.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/en.ts index 96c68fe39ec1..47801373d859 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/en.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/en.ts @@ -2051,9 +2051,10 @@ export default { permissionsGranularHelp: 'Set permissions for specific nodes', granularRightsLabel: 'Documents', granularRightsDescription: 'Assign permissions to specific documents', - permissionsEntityGroup_document: 'Content', + permissionsEntityGroup_document: 'Document', permissionsEntityGroup_media: 'Media', permissionsEntityGroup_member: 'Member', + 'permissionsEntityGroup_document-property-value': 'Document Property Value', profile: 'Profile', searchAllChildren: 'Search all children', languagesHelp: 'Limit the languages users have access to edit', diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/manifests.ts index 9b67fb6bfa9c..8bc1f7f2b956 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/manifests.ts @@ -37,6 +37,7 @@ export const manifests: Array = type: 'userGranularPermission', alias: 'Umb.UserGranularPermission.Document.PropertyValue', name: 'Document Property Values Granular User Permission', + weight: 950, element: () => import( './input-document-property-value-granular-user-permission/input-document-property-value-granular-user-permission.element.js' diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/manifests.ts index d67602fed40e..7763246f3828 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/manifests.ts @@ -204,6 +204,7 @@ export const granularPermissions: Array = [ type: 'userGranularPermission', alias: 'Umb.UserGranularPermission.Document', name: 'Document Granular User Permission', + weight: 1000, element: () => import('./input-document-granular-user-permission/input-document-granular-user-permission.element.js'), meta: { From 9c83a1ef7d5c45708e9ffbcc7a0608650abddfcd Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 18 Mar 2025 18:55:53 +0100 Subject: [PATCH 065/106] sort group alphabetically --- ...oup-entity-user-permission-list.element.ts | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user-group/workspace/user-group/components/user-group-entity-user-permission-list.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user-group/workspace/user-group/components/user-group-entity-user-permission-list.element.ts index 778d8fe846ca..107c6563cb2f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user-group/workspace/user-group/components/user-group-entity-user-permission-list.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user-group/workspace/user-group/components/user-group-entity-user-permission-list.element.ts @@ -11,7 +11,7 @@ export class UmbUserGroupEntityUserPermissionListElement extends UmbLitElement { private _fallBackPermissions?: Array; @state() - private _entityTypes: Array = []; + private _groups: Array<{ entityType: string; headline: string }> = []; #userGroupWorkspaceContext?: typeof UMB_USER_GROUP_WORKSPACE_CONTEXT.TYPE; @@ -36,7 +36,15 @@ export class UmbUserGroupEntityUserPermissionListElement extends UmbLitElement { this.observe( umbExtensionsRegistry.byType('entityUserPermission'), (manifests) => { - this._entityTypes = [...new Set(manifests.flatMap((manifest) => manifest.forEntityTypes))]; + const entityTypes = [...new Set(manifests.flatMap((manifest) => manifest.forEntityTypes))]; + this._groups = entityTypes + .map((entityType) => { + return { + entityType, + headline: this.localize.term(`user_permissionsEntityGroup_${entityType}`), + }; + }) + .sort((a, b) => a.headline.localeCompare(b.headline)); }, 'umbUserPermissionsObserver', ); @@ -51,14 +59,14 @@ export class UmbUserGroupEntityUserPermissionListElement extends UmbLitElement { } override render() { - return html` ${this._entityTypes.map((entityType) => this.#renderPermissionsByEntityType(entityType))} `; + return html` ${this._groups.map((group) => this.#renderPermissionsForEntityType(group))}`; } - #renderPermissionsByEntityType(entityType: string) { + #renderPermissionsForEntityType(group: { entityType: string; headline: string }) { return html` -

${entityType}

+

${group.headline}

`; From 3531dcc01604c4ecc93d9af41bf79a7acde78250 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 18 Mar 2025 19:14:32 +0100 Subject: [PATCH 066/106] add empty state for no verbs --- src/Umbraco.Web.UI.Client/src/assets/lang/en.ts | 1 + ...ocument-property-value-granular-user-permission.element.ts | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/en.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/en.ts index 47801373d859..92b0a03ba254 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/en.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/en.ts @@ -2055,6 +2055,7 @@ export default { permissionsEntityGroup_media: 'Media', permissionsEntityGroup_member: 'Member', 'permissionsEntityGroup_document-property-value': 'Document Property Value', + permissionNoVerbs: 'No allowed permissions', profile: 'Profile', searchAllChildren: 'Search all children', languagesHelp: 'Limit the languages users have access to edit', diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/input-document-property-value-granular-user-permission/input-document-property-value-granular-user-permission.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/input-document-property-value-granular-user-permission/input-document-property-value-granular-user-permission.element.ts index 3e689f66ea77..7105e27aad7a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/input-document-property-value-granular-user-permission/input-document-property-value-granular-user-permission.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/input-document-property-value-granular-user-permission/input-document-property-value-granular-user-permission.element.ts @@ -156,6 +156,10 @@ export class UmbInputDocumentPropertyValueGranularUserPermissionElement extends throw new Error('Could not find permission for property type'); } + if (permission.verbs.length === 0) { + return this.localize.term('user_permissionNoVerbs'); + } + return umbExtensionsRegistry .getByTypeAndFilter('entityUserPermission', (manifest) => manifest.meta.verbs.every((verb) => permission.verbs.includes(verb)), From f5cb387fb376614dc0f4199084994a571a87c821 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 18 Mar 2025 19:26:45 +0100 Subject: [PATCH 067/106] organize folders --- .../create-blueprint/manifests.ts | 2 +- .../entity-actions/create/manifests.ts | 2 +- .../culture-and-hostnames/manifests.ts | 2 +- .../entity-actions/duplicate/manifests.ts | 2 +- .../documents/entity-actions/manifests.ts | 2 +- .../entity-actions/move-to/manifests.ts | 2 +- .../entity-actions/notifications/manifests.ts | 2 +- .../entity-actions/public-access/manifests.ts | 2 +- .../sort-children-of/manifests.ts | 2 +- .../duplicate-to/manifests.ts | 2 +- .../entity-bulk-actions/move-to/manifests.ts | 2 +- .../workspace-action/manifests.ts | 2 +- .../publish/entity-action/manifests.ts | 2 +- .../publish/entity-bulk-action/manifests.ts | 2 +- .../save-and-publish.action.ts | 4 +- .../workspace-action/manifests.ts | 2 +- .../unpublish/entity-action/manifests.ts | 2 +- .../unpublish/entity-bulk-action/manifests.ts | 2 +- .../unpublish/workspace-action/manifests.ts | 2 +- .../entity-action/bulk-trash/manifests.ts | 2 +- .../src/packages/documents/documents/types.ts | 2 +- .../documents/user-permissions/constants.ts | 20 +- .../{ => document}/conditions/constants.ts | 0 .../document-user-permission.condition.ts | 0 .../{ => document}/conditions/manifests.ts | 0 .../{ => document}/conditions/types.ts | 0 .../user-permissions/document/constants.ts | 18 ++ .../user-permissions/document/index.ts | 1 + ...cument-granular-user-permission.element.ts | 6 +- .../user-permissions/document/manifests.ts | 222 ++++++++++++++++++ .../{ => document}/repository/constants.ts | 0 .../document-permission.repository.ts | 0 .../document-permission.server.data.ts | 0 .../{ => document}/repository/index.ts | 0 .../{ => document}/repository/manifests.ts | 0 .../user-permissions/document/types.ts | 6 + .../user-permissions/{ => document}/utils.ts | 0 .../documents/user-permissions/index.ts | 4 +- .../documents/user-permissions/manifests.ts | 220 +---------------- .../documents/user-permissions/types.ts | 8 +- .../actions/save-and-preview.action.ts | 4 +- 41 files changed, 281 insertions(+), 272 deletions(-) rename src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/{ => document}/conditions/constants.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/{ => document}/conditions/document-user-permission.condition.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/{ => document}/conditions/manifests.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/{ => document}/conditions/types.ts (100%) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document/constants.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document/index.ts rename src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/{ => document}/input-document-granular-user-permission/input-document-granular-user-permission.element.ts (97%) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document/manifests.ts rename src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/{ => document}/repository/constants.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/{ => document}/repository/document-permission.repository.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/{ => document}/repository/document-permission.server.data.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/{ => document}/repository/index.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/{ => document}/repository/manifests.ts (100%) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document/types.ts rename src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/{ => document}/utils.ts (100%) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create-blueprint/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create-blueprint/manifests.ts index 12c47060b23c..80e2fcddc45d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create-blueprint/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create-blueprint/manifests.ts @@ -1,5 +1,5 @@ import { UMB_DOCUMENT_ENTITY_TYPE } from '../../entity.js'; -import { UMB_USER_PERMISSION_DOCUMENT_CREATE_BLUEPRINT } from '../../user-permissions/constants.js'; +import { UMB_USER_PERMISSION_DOCUMENT_CREATE_BLUEPRINT } from '../../user-permissions/document/constants.js'; import { UMB_ENTITY_IS_NOT_TRASHED_CONDITION_ALIAS } from '@umbraco-cms/backoffice/recycle-bin'; export const manifests: Array = [ diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create/manifests.ts index 121cf7a77c92..1cdd48b96d9b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create/manifests.ts @@ -1,5 +1,5 @@ import { UMB_DOCUMENT_ENTITY_TYPE, UMB_DOCUMENT_ROOT_ENTITY_TYPE } from '../../entity.js'; -import { UMB_USER_PERMISSION_DOCUMENT_CREATE } from '../../user-permissions/index.js'; +import { UMB_USER_PERMISSION_DOCUMENT_CREATE } from '../../user-permissions/document/constants.js'; import { UMB_ENTITY_IS_NOT_TRASHED_CONDITION_ALIAS } from '@umbraco-cms/backoffice/recycle-bin'; export const manifests: Array = [ diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/culture-and-hostnames/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/culture-and-hostnames/manifests.ts index 1e5c788b21b7..f62616ada41b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/culture-and-hostnames/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/culture-and-hostnames/manifests.ts @@ -1,5 +1,5 @@ import { UMB_DOCUMENT_ENTITY_TYPE } from '../../entity.js'; -import { UMB_USER_PERMISSION_DOCUMENT_CULTURE_AND_HOSTNAMES } from '../../user-permissions/index.js'; +import { UMB_USER_PERMISSION_DOCUMENT_CULTURE_AND_HOSTNAMES } from '../../user-permissions/document/constants.js'; import { UMB_ENTITY_IS_NOT_TRASHED_CONDITION_ALIAS } from '@umbraco-cms/backoffice/recycle-bin'; export const manifests: Array = [ diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/duplicate/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/duplicate/manifests.ts index 019e1ed39e23..a435844c3013 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/duplicate/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/duplicate/manifests.ts @@ -1,5 +1,5 @@ import { UMB_DOCUMENT_ENTITY_TYPE } from '../../entity.js'; -import { UMB_USER_PERMISSION_DOCUMENT_DUPLICATE } from '../../user-permissions/constants.js'; +import { UMB_USER_PERMISSION_DOCUMENT_DUPLICATE } from '../../user-permissions/document/constants.js'; import { manifests as repositoryManifests } from './repository/manifests.js'; import { manifests as modalManifests } from './modal/manifests.js'; import { UMB_ENTITY_IS_NOT_TRASHED_CONDITION_ALIAS } from '@umbraco-cms/backoffice/recycle-bin'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/manifests.ts index ecbb1a7e5c24..2959afa4655f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/manifests.ts @@ -1,7 +1,7 @@ import { UMB_DOCUMENT_DETAIL_REPOSITORY_ALIAS } from '../repository/index.js'; import { UMB_DOCUMENT_ITEM_REPOSITORY_ALIAS } from '../item/constants.js'; import { UMB_DOCUMENT_ENTITY_TYPE } from '../entity.js'; -import { UMB_USER_PERMISSION_DOCUMENT_DELETE } from '../user-permissions/constants.js'; +import { UMB_USER_PERMISSION_DOCUMENT_DELETE } from '../user-permissions/document/constants.js'; import { UMB_DOCUMENT_REFERENCE_REPOSITORY_ALIAS } from '../reference/constants.js'; import { manifests as createBlueprintManifests } from './create-blueprint/manifests.js'; import { manifests as createManifests } from './create/manifests.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/move-to/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/move-to/manifests.ts index 422421304cde..8b01534fd594 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/move-to/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/move-to/manifests.ts @@ -1,6 +1,6 @@ import { UMB_DOCUMENT_ENTITY_TYPE } from '../../entity.js'; import { UMB_DOCUMENT_TREE_ALIAS, UMB_DOCUMENT_TREE_REPOSITORY_ALIAS } from '../../tree/index.js'; -import { UMB_USER_PERMISSION_DOCUMENT_MOVE } from '../../user-permissions/constants.js'; +import { UMB_USER_PERMISSION_DOCUMENT_MOVE } from '../../user-permissions/document/constants.js'; import { UMB_MOVE_DOCUMENT_REPOSITORY_ALIAS } from './repository/index.js'; import { manifests as repositoryManifests } from './repository/manifests.js'; import { UMB_ENTITY_IS_NOT_TRASHED_CONDITION_ALIAS } from '@umbraco-cms/backoffice/recycle-bin'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/notifications/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/notifications/manifests.ts index b45851616ca3..9c4cb83b5d61 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/notifications/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/notifications/manifests.ts @@ -1,5 +1,5 @@ import { UMB_DOCUMENT_ENTITY_TYPE } from '../../entity.js'; -import { UMB_USER_PERMISSION_DOCUMENT_NOTIFICATIONS } from '../../user-permissions/constants.js'; +import { UMB_USER_PERMISSION_DOCUMENT_NOTIFICATIONS } from '../../user-permissions/document/constants.js'; import { manifests as repositoryManifests } from './repository/manifests.js'; import { manifests as modalManifests } from './modal/manifests.js'; import type { ManifestEntityAction } from '@umbraco-cms/backoffice/entity-action'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/public-access/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/public-access/manifests.ts index 354dbf2f57d5..124335ac9abd 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/public-access/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/public-access/manifests.ts @@ -1,5 +1,5 @@ import { UMB_DOCUMENT_ENTITY_TYPE } from '../../entity.js'; -import { UMB_USER_PERMISSION_DOCUMENT_PUBLIC_ACCESS } from '../../user-permissions/index.js'; +import { UMB_USER_PERMISSION_DOCUMENT_PUBLIC_ACCESS } from '../../user-permissions/document/constants.js'; import { UMB_SECTION_USER_PERMISSION_CONDITION_ALIAS } from '@umbraco-cms/backoffice/section'; import { UMB_ENTITY_IS_NOT_TRASHED_CONDITION_ALIAS } from '@umbraco-cms/backoffice/recycle-bin'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/sort-children-of/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/sort-children-of/manifests.ts index 39f00ca0f828..2eb5289fc5e1 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/sort-children-of/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/sort-children-of/manifests.ts @@ -1,7 +1,7 @@ import { UMB_DOCUMENT_ENTITY_TYPE, UMB_DOCUMENT_ROOT_ENTITY_TYPE } from '../../entity.js'; import { UMB_DOCUMENT_ITEM_REPOSITORY_ALIAS } from '../../item/constants.js'; import { UMB_DOCUMENT_TREE_REPOSITORY_ALIAS } from '../../tree/index.js'; -import { UMB_USER_PERMISSION_DOCUMENT_SORT } from '../../user-permissions/index.js'; +import { UMB_USER_PERMISSION_DOCUMENT_SORT } from '../../user-permissions/document/constants.js'; import { UMB_SORT_CHILDREN_OF_DOCUMENT_REPOSITORY_ALIAS } from './repository/constants.js'; import { manifests as repositoryManifests } from './repository/manifests.js'; import { UMB_ENTITY_IS_NOT_TRASHED_CONDITION_ALIAS } from '@umbraco-cms/backoffice/recycle-bin'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-bulk-actions/duplicate-to/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-bulk-actions/duplicate-to/manifests.ts index 6acd5a69c6f0..cd6babebd346 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-bulk-actions/duplicate-to/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-bulk-actions/duplicate-to/manifests.ts @@ -1,7 +1,7 @@ import { UMB_DOCUMENT_COLLECTION_ALIAS } from '../../collection/constants.js'; import { UMB_DOCUMENT_ENTITY_TYPE } from '../../entity.js'; import { UMB_DOCUMENT_TREE_ALIAS } from '../../tree/manifests.js'; -import { UMB_USER_PERMISSION_DOCUMENT_DUPLICATE } from '../../user-permissions/constants.js'; +import { UMB_USER_PERMISSION_DOCUMENT_DUPLICATE } from '../../user-permissions/document/constants.js'; import { UMB_BULK_DUPLICATE_DOCUMENT_REPOSITORY_ALIAS } from './repository/constants.js'; import { manifests as repositoryManifests } from './repository/manifests.js'; import { UMB_COLLECTION_ALIAS_CONDITION } from '@umbraco-cms/backoffice/collection'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-bulk-actions/move-to/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-bulk-actions/move-to/manifests.ts index 57e351c8f578..835beba3486d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-bulk-actions/move-to/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-bulk-actions/move-to/manifests.ts @@ -1,7 +1,7 @@ import { UMB_DOCUMENT_COLLECTION_ALIAS } from '../../collection/constants.js'; import { UMB_DOCUMENT_ENTITY_TYPE } from '../../entity.js'; import { UMB_DOCUMENT_TREE_ALIAS } from '../../tree/manifests.js'; -import { UMB_USER_PERMISSION_DOCUMENT_MOVE } from '../../user-permissions/constants.js'; +import { UMB_USER_PERMISSION_DOCUMENT_MOVE } from '../../user-permissions/document/constants.js'; import { UMB_BULK_MOVE_DOCUMENT_REPOSITORY_ALIAS } from './repository/constants.js'; import { manifests as repositoryManifests } from './repository/manifests.js'; import { UMB_COLLECTION_ALIAS_CONDITION } from '@umbraco-cms/backoffice/collection'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/publish-with-descendants/workspace-action/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/publish-with-descendants/workspace-action/manifests.ts index 75854fc50e22..d66d02909ef0 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/publish-with-descendants/workspace-action/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/publish-with-descendants/workspace-action/manifests.ts @@ -2,7 +2,7 @@ import { UMB_DOCUMENT_USER_PERMISSION_CONDITION_ALIAS, UMB_USER_PERMISSION_DOCUMENT_PUBLISH, UMB_USER_PERMISSION_DOCUMENT_UPDATE, -} from '../../../user-permissions/constants.js'; +} from '../../../user-permissions/document/constants.js'; import { UMB_WORKSPACE_ENTITY_IS_NEW_CONDITION_ALIAS } from '@umbraco-cms/backoffice/workspace'; import { UMB_ENTITY_IS_NOT_TRASHED_CONDITION_ALIAS } from '@umbraco-cms/backoffice/recycle-bin'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/publish/entity-action/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/publish/entity-action/manifests.ts index f501f4a7f9a5..7fd3ec4b660d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/publish/entity-action/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/publish/entity-action/manifests.ts @@ -1,5 +1,5 @@ import { UMB_DOCUMENT_ENTITY_TYPE } from '../../../entity.js'; -import { UMB_USER_PERMISSION_DOCUMENT_PUBLISH } from '../../../user-permissions/constants.js'; +import { UMB_USER_PERMISSION_DOCUMENT_PUBLISH } from '../../../user-permissions/document/constants.js'; import { UMB_ENTITY_IS_NOT_TRASHED_CONDITION_ALIAS } from '@umbraco-cms/backoffice/recycle-bin'; export const manifests: Array = [ diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/publish/entity-bulk-action/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/publish/entity-bulk-action/manifests.ts index 9b50bc1ed379..017228b8c5ed 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/publish/entity-bulk-action/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/publish/entity-bulk-action/manifests.ts @@ -1,6 +1,6 @@ import { UMB_DOCUMENT_ENTITY_TYPE } from '../../../entity.js'; import { UMB_DOCUMENT_COLLECTION_ALIAS } from '../../../collection/constants.js'; -import { UMB_USER_PERMISSION_DOCUMENT_PUBLISH } from '../../../user-permissions/constants.js'; +import { UMB_USER_PERMISSION_DOCUMENT_PUBLISH } from '../../../user-permissions/document/constants.js'; import { UMB_COLLECTION_ALIAS_CONDITION } from '@umbraco-cms/backoffice/collection'; export const manifests: Array = [ diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/publish/workspace-action/save-and-publish.action.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/publish/workspace-action/save-and-publish.action.ts index 142e5393a5ad..a636510a0b95 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/publish/workspace-action/save-and-publish.action.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/publish/workspace-action/save-and-publish.action.ts @@ -1,8 +1,8 @@ -import { UmbDocumentUserPermissionCondition } from '../../../user-permissions/conditions/document-user-permission.condition.js'; +import { UmbDocumentUserPermissionCondition } from '../../../user-permissions/document/conditions/document-user-permission.condition.js'; import { UMB_USER_PERMISSION_DOCUMENT_PUBLISH, UMB_USER_PERMISSION_DOCUMENT_UPDATE, -} from '../../../user-permissions/constants.js'; +} from '../../../user-permissions/document/constants.js'; import { UMB_DOCUMENT_PUBLISHING_WORKSPACE_CONTEXT } from '../../workspace-context/constants.js'; import { UMB_DOCUMENT_WORKSPACE_CONTEXT } from '../../../constants.js'; import { UmbWorkspaceActionBase, type UmbWorkspaceActionArgs } from '@umbraco-cms/backoffice/workspace'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/schedule-publish/workspace-action/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/schedule-publish/workspace-action/manifests.ts index 99fb381eaf2a..fae0243493a7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/schedule-publish/workspace-action/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/schedule-publish/workspace-action/manifests.ts @@ -3,7 +3,7 @@ import { UMB_DOCUMENT_USER_PERMISSION_CONDITION_ALIAS, UMB_USER_PERMISSION_DOCUMENT_PUBLISH, UMB_USER_PERMISSION_DOCUMENT_UPDATE, -} from '../../../user-permissions/constants.js'; +} from '../../../user-permissions/document/constants.js'; import { UMB_ENTITY_IS_NOT_TRASHED_CONDITION_ALIAS } from '@umbraco-cms/backoffice/recycle-bin'; export const manifests: Array = [ diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/unpublish/entity-action/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/unpublish/entity-action/manifests.ts index 436dff320a34..b89880060d80 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/unpublish/entity-action/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/unpublish/entity-action/manifests.ts @@ -1,5 +1,5 @@ import { UMB_DOCUMENT_ENTITY_TYPE } from '../../../entity.js'; -import { UMB_USER_PERMISSION_DOCUMENT_UNPUBLISH } from '../../../user-permissions/constants.js'; +import { UMB_USER_PERMISSION_DOCUMENT_UNPUBLISH } from '../../../user-permissions/document/constants.js'; import { UMB_ENTITY_IS_NOT_TRASHED_CONDITION_ALIAS } from '@umbraco-cms/backoffice/recycle-bin'; export const manifests: Array = [ diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/unpublish/entity-bulk-action/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/unpublish/entity-bulk-action/manifests.ts index e473c143633d..0bd4d3396cd4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/unpublish/entity-bulk-action/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/unpublish/entity-bulk-action/manifests.ts @@ -1,6 +1,6 @@ import { UMB_DOCUMENT_ENTITY_TYPE } from '../../../entity.js'; import { UMB_DOCUMENT_COLLECTION_ALIAS } from '../../../collection/constants.js'; -import { UMB_USER_PERMISSION_DOCUMENT_UNPUBLISH } from '../../../user-permissions/constants.js'; +import { UMB_USER_PERMISSION_DOCUMENT_UNPUBLISH } from '../../../user-permissions/document/constants.js'; import { UMB_COLLECTION_ALIAS_CONDITION } from '@umbraco-cms/backoffice/collection'; export const manifests: Array = [ diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/unpublish/workspace-action/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/unpublish/workspace-action/manifests.ts index 432a1eb33483..f67a92aebf42 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/unpublish/workspace-action/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/unpublish/workspace-action/manifests.ts @@ -1,7 +1,7 @@ import { UMB_DOCUMENT_USER_PERMISSION_CONDITION_ALIAS, UMB_USER_PERMISSION_DOCUMENT_UNPUBLISH, -} from '../../../user-permissions/constants.js'; +} from '../../../user-permissions/document/constants.js'; import { UMB_WORKSPACE_ENTITY_IS_NEW_CONDITION_ALIAS } from '@umbraco-cms/backoffice/workspace'; import { UMB_ENTITY_IS_NOT_TRASHED_CONDITION_ALIAS } from '@umbraco-cms/backoffice/recycle-bin'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/entity-action/bulk-trash/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/entity-action/bulk-trash/manifests.ts index 2ac56f94f52d..4ef514fef747 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/entity-action/bulk-trash/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/entity-action/bulk-trash/manifests.ts @@ -1,4 +1,4 @@ -import { UMB_USER_PERMISSION_DOCUMENT_DELETE } from '../../../user-permissions/constants.js'; +import { UMB_USER_PERMISSION_DOCUMENT_DELETE } from '../../../user-permissions/document/constants.js'; import { UMB_DOCUMENT_ENTITY_TYPE } from '../../../entity.js'; import { UMB_DOCUMENT_ITEM_REPOSITORY_ALIAS } from '../../../item/constants.js'; import { UMB_DOCUMENT_RECYCLE_BIN_REPOSITORY_ALIAS } from '../../repository/constants.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/types.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/types.ts index 6ce273ef1c57..bf3fe6fd1f18 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/types.ts @@ -1,4 +1,4 @@ -import type { UmbDocumentEntityType, UmbDocumentPropertyValueEntityType } from './entity.js'; +import type { UmbDocumentEntityType } from './entity.js'; import type { UmbEntityVariantModel, UmbEntityVariantOptionModel, diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/constants.ts index bb0fa17977ac..0fc894b76f39 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/constants.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/constants.ts @@ -1,18 +1,2 @@ -export const UMB_USER_PERMISSION_DOCUMENT_CREATE = 'Umb.Document.Create'; -export const UMB_USER_PERMISSION_DOCUMENT_READ = 'Umb.Document.Read'; -export const UMB_USER_PERMISSION_DOCUMENT_UPDATE = 'Umb.Document.Update'; -export const UMB_USER_PERMISSION_DOCUMENT_DELETE = 'Umb.Document.Delete'; -export const UMB_USER_PERMISSION_DOCUMENT_CREATE_BLUEPRINT = 'Umb.Document.CreateBlueprint'; -export const UMB_USER_PERMISSION_DOCUMENT_NOTIFICATIONS = 'Umb.Document.Notifications'; -export const UMB_USER_PERMISSION_DOCUMENT_PUBLISH = 'Umb.Document.Publish'; -export const UMB_USER_PERMISSION_DOCUMENT_PERMISSIONS = 'Umb.Document.Permissions'; -export const UMB_USER_PERMISSION_DOCUMENT_UNPUBLISH = 'Umb.Document.Unpublish'; -export const UMB_USER_PERMISSION_DOCUMENT_DUPLICATE = 'Umb.Document.Duplicate'; -export const UMB_USER_PERMISSION_DOCUMENT_MOVE = 'Umb.Document.Move'; -export const UMB_USER_PERMISSION_DOCUMENT_SORT = 'Umb.Document.Sort'; -export const UMB_USER_PERMISSION_DOCUMENT_CULTURE_AND_HOSTNAMES = 'Umb.Document.CultureAndHostnames'; -export const UMB_USER_PERMISSION_DOCUMENT_PUBLIC_ACCESS = 'Umb.Document.PublicAccess'; -export const UMB_USER_PERMISSION_DOCUMENT_ROLLBACK = 'Umb.Document.Rollback'; - -export * from './conditions/constants.js'; -export * from './repository/constants.js'; +export * from './document/constants.js'; +export * from './document-property-value/constants.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/conditions/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document/conditions/constants.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/conditions/constants.ts rename to src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document/conditions/constants.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/conditions/document-user-permission.condition.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document/conditions/document-user-permission.condition.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/conditions/document-user-permission.condition.ts rename to src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document/conditions/document-user-permission.condition.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/conditions/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document/conditions/manifests.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/conditions/manifests.ts rename to src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document/conditions/manifests.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/conditions/types.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document/conditions/types.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/conditions/types.ts rename to src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document/conditions/types.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document/constants.ts new file mode 100644 index 000000000000..bb0fa17977ac --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document/constants.ts @@ -0,0 +1,18 @@ +export const UMB_USER_PERMISSION_DOCUMENT_CREATE = 'Umb.Document.Create'; +export const UMB_USER_PERMISSION_DOCUMENT_READ = 'Umb.Document.Read'; +export const UMB_USER_PERMISSION_DOCUMENT_UPDATE = 'Umb.Document.Update'; +export const UMB_USER_PERMISSION_DOCUMENT_DELETE = 'Umb.Document.Delete'; +export const UMB_USER_PERMISSION_DOCUMENT_CREATE_BLUEPRINT = 'Umb.Document.CreateBlueprint'; +export const UMB_USER_PERMISSION_DOCUMENT_NOTIFICATIONS = 'Umb.Document.Notifications'; +export const UMB_USER_PERMISSION_DOCUMENT_PUBLISH = 'Umb.Document.Publish'; +export const UMB_USER_PERMISSION_DOCUMENT_PERMISSIONS = 'Umb.Document.Permissions'; +export const UMB_USER_PERMISSION_DOCUMENT_UNPUBLISH = 'Umb.Document.Unpublish'; +export const UMB_USER_PERMISSION_DOCUMENT_DUPLICATE = 'Umb.Document.Duplicate'; +export const UMB_USER_PERMISSION_DOCUMENT_MOVE = 'Umb.Document.Move'; +export const UMB_USER_PERMISSION_DOCUMENT_SORT = 'Umb.Document.Sort'; +export const UMB_USER_PERMISSION_DOCUMENT_CULTURE_AND_HOSTNAMES = 'Umb.Document.CultureAndHostnames'; +export const UMB_USER_PERMISSION_DOCUMENT_PUBLIC_ACCESS = 'Umb.Document.PublicAccess'; +export const UMB_USER_PERMISSION_DOCUMENT_ROLLBACK = 'Umb.Document.Rollback'; + +export * from './conditions/constants.js'; +export * from './repository/constants.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document/index.ts new file mode 100644 index 000000000000..3d76f338dddc --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document/index.ts @@ -0,0 +1 @@ +export * from './repository/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/input-document-granular-user-permission/input-document-granular-user-permission.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document/input-document-granular-user-permission/input-document-granular-user-permission.element.ts similarity index 97% rename from src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/input-document-granular-user-permission/input-document-granular-user-permission.element.ts rename to src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document/input-document-granular-user-permission/input-document-granular-user-permission.element.ts index e66458cd5c3a..58bc8b86ad94 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/input-document-granular-user-permission/input-document-granular-user-permission.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document/input-document-granular-user-permission/input-document-granular-user-permission.element.ts @@ -1,7 +1,7 @@ import type { UmbDocumentUserPermissionModel } from '../types.js'; -import { UmbDocumentItemRepository } from '../../item/index.js'; -import type { UmbDocumentItemModel } from '../../item/types.js'; -import { UMB_DOCUMENT_PICKER_MODAL } from '../../constants.js'; +import { UmbDocumentItemRepository } from '../../../item/index.js'; +import type { UmbDocumentItemModel } from '../../../item/types.js'; +import { UMB_DOCUMENT_PICKER_MODAL } from '../../../constants.js'; import { css, customElement, html, property, repeat, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import type { UmbModalManagerContext } from '@umbraco-cms/backoffice/modal'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document/manifests.ts new file mode 100644 index 000000000000..f1b18cc04e30 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document/manifests.ts @@ -0,0 +1,222 @@ +import { UMB_DOCUMENT_ENTITY_TYPE } from '../../entity.js'; +import { + UMB_USER_PERMISSION_DOCUMENT_READ, + UMB_USER_PERMISSION_DOCUMENT_CREATE_BLUEPRINT, + UMB_USER_PERMISSION_DOCUMENT_DELETE, + UMB_USER_PERMISSION_DOCUMENT_CREATE, + UMB_USER_PERMISSION_DOCUMENT_NOTIFICATIONS, + UMB_USER_PERMISSION_DOCUMENT_PUBLISH, + UMB_USER_PERMISSION_DOCUMENT_PERMISSIONS, + UMB_USER_PERMISSION_DOCUMENT_UNPUBLISH, + UMB_USER_PERMISSION_DOCUMENT_UPDATE, + UMB_USER_PERMISSION_DOCUMENT_DUPLICATE, + UMB_USER_PERMISSION_DOCUMENT_MOVE, + UMB_USER_PERMISSION_DOCUMENT_SORT, + UMB_USER_PERMISSION_DOCUMENT_CULTURE_AND_HOSTNAMES, + UMB_USER_PERMISSION_DOCUMENT_PUBLIC_ACCESS, + UMB_USER_PERMISSION_DOCUMENT_ROLLBACK, +} from './constants.js'; +import { manifests as repositoryManifests } from './repository/manifests.js'; +import { manifests as conditionManifests } from './conditions/manifests.js'; +import type { + ManifestGranularUserPermission, + ManifestEntityUserPermission, +} from '@umbraco-cms/backoffice/user-permission'; +import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +const permissions: Array = [ + { + type: 'entityUserPermission', + alias: UMB_USER_PERMISSION_DOCUMENT_READ, + name: 'Read Document User Permission', + forEntityTypes: [UMB_DOCUMENT_ENTITY_TYPE], + meta: { + verbs: ['Umb.Document.Read'], + label: '#actions_browse', + description: '#actionDescriptions_browse', + }, + }, + { + type: 'entityUserPermission', + alias: UMB_USER_PERMISSION_DOCUMENT_CREATE_BLUEPRINT, + name: 'Create Document Blueprint User Permission', + forEntityTypes: [UMB_DOCUMENT_ENTITY_TYPE], + meta: { + verbs: ['Umb.Document.CreateBlueprint'], + label: '#actions_createblueprint', + description: '#actionDescriptions_createblueprint', + }, + }, + { + type: 'entityUserPermission', + alias: UMB_USER_PERMISSION_DOCUMENT_DELETE, + name: 'Delete Document User Permission', + forEntityTypes: [UMB_DOCUMENT_ENTITY_TYPE], + meta: { + verbs: ['Umb.Document.Delete'], + label: '#actions_delete', + description: '#actionDescriptions_delete', + }, + }, + { + type: 'entityUserPermission', + alias: UMB_USER_PERMISSION_DOCUMENT_CREATE, + name: 'Create Document User Permission', + forEntityTypes: [UMB_DOCUMENT_ENTITY_TYPE], + meta: { + verbs: ['Umb.Document.Create'], + label: '#actions_create', + description: '#actionDescriptions_create', + }, + }, + { + type: 'entityUserPermission', + alias: UMB_USER_PERMISSION_DOCUMENT_NOTIFICATIONS, + name: 'Document Notifications User Permission', + forEntityTypes: [UMB_DOCUMENT_ENTITY_TYPE], + meta: { + verbs: ['Umb.Document.Notifications'], + label: '#actions_notify', + description: '#actionDescriptions_notify', + }, + }, + { + type: 'entityUserPermission', + alias: UMB_USER_PERMISSION_DOCUMENT_PUBLISH, + name: 'Publish Document User Permission', + forEntityTypes: [UMB_DOCUMENT_ENTITY_TYPE], + meta: { + verbs: ['Umb.Document.Publish'], + label: '#actions_publish', + description: '#actionDescriptions_publish', + }, + }, + { + type: 'entityUserPermission', + alias: UMB_USER_PERMISSION_DOCUMENT_PERMISSIONS, + name: 'Document Permissions User Permission', + forEntityTypes: [UMB_DOCUMENT_ENTITY_TYPE], + meta: { + verbs: ['Umb.Document.Permissions'], + label: '#actions_setPermissions', + description: '#actionDescriptions_rights', + }, + }, + { + type: 'entityUserPermission', + alias: UMB_USER_PERMISSION_DOCUMENT_UNPUBLISH, + name: 'Unpublish Document User Permission', + forEntityTypes: [UMB_DOCUMENT_ENTITY_TYPE], + meta: { + verbs: ['Umb.Document.Unpublish'], + label: '#actions_unpublish', + description: '#actionDescriptions_unpublish', + }, + }, + { + type: 'entityUserPermission', + alias: UMB_USER_PERMISSION_DOCUMENT_UPDATE, + name: 'Update Document User Permission', + forEntityTypes: [UMB_DOCUMENT_ENTITY_TYPE], + meta: { + verbs: ['Umb.Document.Update'], + label: '#actions_update', + description: '#actionDescriptions_update', + }, + }, + { + type: 'entityUserPermission', + alias: UMB_USER_PERMISSION_DOCUMENT_DUPLICATE, + name: 'Duplicate Document User Permission', + forEntityTypes: [UMB_DOCUMENT_ENTITY_TYPE], + meta: { + verbs: ['Umb.Document.Duplicate'], + label: '#actions_copy', + description: '#actionDescriptions_copy', + group: 'structure', + }, + }, + { + type: 'entityUserPermission', + alias: UMB_USER_PERMISSION_DOCUMENT_MOVE, + name: 'Move Document User Permission', + forEntityTypes: [UMB_DOCUMENT_ENTITY_TYPE], + meta: { + verbs: ['Umb.Document.Move'], + label: '#actions_move', + description: '#actionDescriptions_move', + group: 'structure', + }, + }, + { + type: 'entityUserPermission', + alias: UMB_USER_PERMISSION_DOCUMENT_SORT, + name: 'Sort Document User Permission', + forEntityTypes: [UMB_DOCUMENT_ENTITY_TYPE], + meta: { + verbs: ['Umb.Document.Sort'], + label: '#actions_sort', + description: '#actionDescriptions_sort', + group: 'structure', + }, + }, + { + type: 'entityUserPermission', + alias: UMB_USER_PERMISSION_DOCUMENT_CULTURE_AND_HOSTNAMES, + name: 'Document Culture And Hostnames User Permission', + forEntityTypes: [UMB_DOCUMENT_ENTITY_TYPE], + meta: { + verbs: ['Umb.Document.CultureAndHostnames'], + label: '#actions_assigndomain', + description: '#actionDescriptions_assignDomain', + group: 'administration', + }, + }, + { + type: 'entityUserPermission', + alias: UMB_USER_PERMISSION_DOCUMENT_PUBLIC_ACCESS, + name: 'Document Public Access User Permission', + forEntityTypes: [UMB_DOCUMENT_ENTITY_TYPE], + meta: { + verbs: ['Umb.Document.PublicAccess'], + label: '#actions_protect', + description: '#actionDescriptions_protect', + group: 'administration', + }, + }, + { + type: 'entityUserPermission', + alias: UMB_USER_PERMISSION_DOCUMENT_ROLLBACK, + name: 'Document Rollback User Permission', + forEntityTypes: [UMB_DOCUMENT_ENTITY_TYPE], + meta: { + verbs: ['Umb.Document.Rollback'], + label: '#actions_rollback', + description: '#actionDescriptions_rollback', + group: 'administration', + }, + }, +]; + +export const granularPermissions: Array = [ + { + type: 'userGranularPermission', + alias: 'Umb.UserGranularPermission.Document', + name: 'Document Granular User Permission', + weight: 1000, + element: () => + import('./input-document-granular-user-permission/input-document-granular-user-permission.element.js'), + meta: { + schemaType: 'DocumentPermissionPresentationModel', + label: '#user_granularRightsLabel', + description: '{#user_granularRightsDescription}', + }, + }, +]; + +export const manifests: Array = [ + ...repositoryManifests, + ...permissions, + ...granularPermissions, + ...conditionManifests, +]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/repository/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document/repository/constants.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/repository/constants.ts rename to src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document/repository/constants.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/repository/document-permission.repository.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document/repository/document-permission.repository.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/repository/document-permission.repository.ts rename to src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document/repository/document-permission.repository.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/repository/document-permission.server.data.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document/repository/document-permission.server.data.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/repository/document-permission.server.data.ts rename to src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document/repository/document-permission.server.data.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/repository/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document/repository/index.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/repository/index.ts rename to src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document/repository/index.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/repository/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document/repository/manifests.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/repository/manifests.ts rename to src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document/repository/manifests.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document/types.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document/types.ts new file mode 100644 index 000000000000..0028a6bf3533 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document/types.ts @@ -0,0 +1,6 @@ +import type { UmbUserPermissionModel } from '@umbraco-cms/backoffice/user-permission'; +export type * from './conditions/types.js'; +export interface UmbDocumentUserPermissionModel extends UmbUserPermissionModel { + // TODO: this should be unique instead of an id, but we currently have now way to map a mixed server response. + document: { id: string }; +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/utils.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document/utils.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/utils.ts rename to src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document/utils.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/index.ts index 3ed3c5c183d5..fbad52ff40a9 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/index.ts @@ -1,3 +1 @@ -export * from './repository/index.js'; -export * from './constants.js'; -export type * from './types.js'; +export * from './document/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/manifests.ts index 7763246f3828..386fae38d02f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/manifests.ts @@ -1,224 +1,8 @@ -import { UMB_DOCUMENT_ENTITY_TYPE } from '../entity.js'; -import { - UMB_USER_PERMISSION_DOCUMENT_READ, - UMB_USER_PERMISSION_DOCUMENT_CREATE_BLUEPRINT, - UMB_USER_PERMISSION_DOCUMENT_DELETE, - UMB_USER_PERMISSION_DOCUMENT_CREATE, - UMB_USER_PERMISSION_DOCUMENT_NOTIFICATIONS, - UMB_USER_PERMISSION_DOCUMENT_PUBLISH, - UMB_USER_PERMISSION_DOCUMENT_PERMISSIONS, - UMB_USER_PERMISSION_DOCUMENT_UNPUBLISH, - UMB_USER_PERMISSION_DOCUMENT_UPDATE, - UMB_USER_PERMISSION_DOCUMENT_DUPLICATE, - UMB_USER_PERMISSION_DOCUMENT_MOVE, - UMB_USER_PERMISSION_DOCUMENT_SORT, - UMB_USER_PERMISSION_DOCUMENT_CULTURE_AND_HOSTNAMES, - UMB_USER_PERMISSION_DOCUMENT_PUBLIC_ACCESS, - UMB_USER_PERMISSION_DOCUMENT_ROLLBACK, -} from './constants.js'; -import { manifests as repositoryManifests } from './repository/manifests.js'; -import { manifests as conditionManifests } from './conditions/manifests.js'; +import { manifests as documentManifests } from './document/manifests.js'; import { manifests as documentPropertyValueManifests } from './document-property-value/manifests.js'; -import type { - ManifestGranularUserPermission, - ManifestEntityUserPermission, -} from '@umbraco-cms/backoffice/user-permission'; import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; -const permissions: Array = [ - { - type: 'entityUserPermission', - alias: UMB_USER_PERMISSION_DOCUMENT_READ, - name: 'Read Document User Permission', - forEntityTypes: [UMB_DOCUMENT_ENTITY_TYPE], - meta: { - verbs: ['Umb.Document.Read'], - label: '#actions_browse', - description: '#actionDescriptions_browse', - }, - }, - { - type: 'entityUserPermission', - alias: UMB_USER_PERMISSION_DOCUMENT_CREATE_BLUEPRINT, - name: 'Create Document Blueprint User Permission', - forEntityTypes: [UMB_DOCUMENT_ENTITY_TYPE], - meta: { - verbs: ['Umb.Document.CreateBlueprint'], - label: '#actions_createblueprint', - description: '#actionDescriptions_createblueprint', - }, - }, - { - type: 'entityUserPermission', - alias: UMB_USER_PERMISSION_DOCUMENT_DELETE, - name: 'Delete Document User Permission', - forEntityTypes: [UMB_DOCUMENT_ENTITY_TYPE], - meta: { - verbs: ['Umb.Document.Delete'], - label: '#actions_delete', - description: '#actionDescriptions_delete', - }, - }, - { - type: 'entityUserPermission', - alias: UMB_USER_PERMISSION_DOCUMENT_CREATE, - name: 'Create Document User Permission', - forEntityTypes: [UMB_DOCUMENT_ENTITY_TYPE], - meta: { - verbs: ['Umb.Document.Create'], - label: '#actions_create', - description: '#actionDescriptions_create', - }, - }, - { - type: 'entityUserPermission', - alias: UMB_USER_PERMISSION_DOCUMENT_NOTIFICATIONS, - name: 'Document Notifications User Permission', - forEntityTypes: [UMB_DOCUMENT_ENTITY_TYPE], - meta: { - verbs: ['Umb.Document.Notifications'], - label: '#actions_notify', - description: '#actionDescriptions_notify', - }, - }, - { - type: 'entityUserPermission', - alias: UMB_USER_PERMISSION_DOCUMENT_PUBLISH, - name: 'Publish Document User Permission', - forEntityTypes: [UMB_DOCUMENT_ENTITY_TYPE], - meta: { - verbs: ['Umb.Document.Publish'], - label: '#actions_publish', - description: '#actionDescriptions_publish', - }, - }, - { - type: 'entityUserPermission', - alias: UMB_USER_PERMISSION_DOCUMENT_PERMISSIONS, - name: 'Document Permissions User Permission', - forEntityTypes: [UMB_DOCUMENT_ENTITY_TYPE], - meta: { - verbs: ['Umb.Document.Permissions'], - label: '#actions_setPermissions', - description: '#actionDescriptions_rights', - }, - }, - { - type: 'entityUserPermission', - alias: UMB_USER_PERMISSION_DOCUMENT_UNPUBLISH, - name: 'Unpublish Document User Permission', - forEntityTypes: [UMB_DOCUMENT_ENTITY_TYPE], - meta: { - verbs: ['Umb.Document.Unpublish'], - label: '#actions_unpublish', - description: '#actionDescriptions_unpublish', - }, - }, - { - type: 'entityUserPermission', - alias: UMB_USER_PERMISSION_DOCUMENT_UPDATE, - name: 'Update Document User Permission', - forEntityTypes: [UMB_DOCUMENT_ENTITY_TYPE], - meta: { - verbs: ['Umb.Document.Update'], - label: '#actions_update', - description: '#actionDescriptions_update', - }, - }, - { - type: 'entityUserPermission', - alias: UMB_USER_PERMISSION_DOCUMENT_DUPLICATE, - name: 'Duplicate Document User Permission', - forEntityTypes: [UMB_DOCUMENT_ENTITY_TYPE], - meta: { - verbs: ['Umb.Document.Duplicate'], - label: '#actions_copy', - description: '#actionDescriptions_copy', - group: 'structure', - }, - }, - { - type: 'entityUserPermission', - alias: UMB_USER_PERMISSION_DOCUMENT_MOVE, - name: 'Move Document User Permission', - forEntityTypes: [UMB_DOCUMENT_ENTITY_TYPE], - meta: { - verbs: ['Umb.Document.Move'], - label: '#actions_move', - description: '#actionDescriptions_move', - group: 'structure', - }, - }, - { - type: 'entityUserPermission', - alias: UMB_USER_PERMISSION_DOCUMENT_SORT, - name: 'Sort Document User Permission', - forEntityTypes: [UMB_DOCUMENT_ENTITY_TYPE], - meta: { - verbs: ['Umb.Document.Sort'], - label: '#actions_sort', - description: '#actionDescriptions_sort', - group: 'structure', - }, - }, - { - type: 'entityUserPermission', - alias: UMB_USER_PERMISSION_DOCUMENT_CULTURE_AND_HOSTNAMES, - name: 'Document Culture And Hostnames User Permission', - forEntityTypes: [UMB_DOCUMENT_ENTITY_TYPE], - meta: { - verbs: ['Umb.Document.CultureAndHostnames'], - label: '#actions_assigndomain', - description: '#actionDescriptions_assignDomain', - group: 'administration', - }, - }, - { - type: 'entityUserPermission', - alias: UMB_USER_PERMISSION_DOCUMENT_PUBLIC_ACCESS, - name: 'Document Public Access User Permission', - forEntityTypes: [UMB_DOCUMENT_ENTITY_TYPE], - meta: { - verbs: ['Umb.Document.PublicAccess'], - label: '#actions_protect', - description: '#actionDescriptions_protect', - group: 'administration', - }, - }, - { - type: 'entityUserPermission', - alias: UMB_USER_PERMISSION_DOCUMENT_ROLLBACK, - name: 'Document Rollback User Permission', - forEntityTypes: [UMB_DOCUMENT_ENTITY_TYPE], - meta: { - verbs: ['Umb.Document.Rollback'], - label: '#actions_rollback', - description: '#actionDescriptions_rollback', - group: 'administration', - }, - }, -]; - -export const granularPermissions: Array = [ - { - type: 'userGranularPermission', - alias: 'Umb.UserGranularPermission.Document', - name: 'Document Granular User Permission', - weight: 1000, - element: () => - import('./input-document-granular-user-permission/input-document-granular-user-permission.element.js'), - meta: { - schemaType: 'DocumentPermissionPresentationModel', - label: '#user_granularRightsLabel', - description: '{#user_granularRightsDescription}', - }, - }, -]; - export const manifests: Array = [ - ...repositoryManifests, - ...permissions, - ...granularPermissions, - ...conditionManifests, + ...documentManifests, ...documentPropertyValueManifests, ]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/types.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/types.ts index 0028a6bf3533..edcc7ad260db 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/types.ts @@ -1,6 +1,2 @@ -import type { UmbUserPermissionModel } from '@umbraco-cms/backoffice/user-permission'; -export type * from './conditions/types.js'; -export interface UmbDocumentUserPermissionModel extends UmbUserPermissionModel { - // TODO: this should be unique instead of an id, but we currently have now way to map a mixed server response. - document: { id: string }; -} +export type * from './document/types.js'; +export type * from './document-property-value/types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/actions/save-and-preview.action.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/actions/save-and-preview.action.ts index ff4d77318840..231629d3c761 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/actions/save-and-preview.action.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/actions/save-and-preview.action.ts @@ -1,6 +1,6 @@ -import { UmbDocumentUserPermissionCondition } from '../../user-permissions/conditions/document-user-permission.condition.js'; +import { UmbDocumentUserPermissionCondition } from '../../user-permissions/document/conditions/document-user-permission.condition.js'; import { UMB_DOCUMENT_WORKSPACE_CONTEXT } from '../document-workspace.context-token.js'; -import { UMB_USER_PERMISSION_DOCUMENT_UPDATE } from '../../user-permissions/index.js'; +import { UMB_USER_PERMISSION_DOCUMENT_UPDATE } from '../../user-permissions/document/constants.js'; import { UmbWorkspaceActionBase } from '@umbraco-cms/backoffice/workspace'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; From 7ba643f9f30b6bfad47a7b4db1d88bd2ab5fa4e4 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 19 Mar 2025 09:22:40 +0100 Subject: [PATCH 068/106] always require unique and variant id --- .../edit/content-editor-properties.element.ts | 27 +++++-------------- .../property/property-read-state.manager.ts | 9 +++---- .../property/property-write-state.manager.ts | 9 +++---- .../src/packages/core/property/types/index.ts | 4 --- .../src/packages/core/utils/index.ts | 1 - .../packages/core/utils/reference/index.ts | 3 --- .../utils/reference/is-reference-by-alias.ts | 10 ------- .../utils/reference/is-reference-by-unique.ts | 10 ------- .../reference/is-reference-by-variant-id.ts | 10 ------- .../src/packages/core/variant/types.ts | 6 ----- .../variant-property-read-state.manager.ts | 13 +++++---- .../variant-property-write-state.manager.ts | 13 +++++---- 12 files changed, 26 insertions(+), 89 deletions(-) delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/utils/reference/index.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/utils/reference/is-reference-by-alias.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/utils/reference/is-reference-by-unique.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/utils/reference/is-reference-by-variant-id.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/content-editor-properties.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/content-editor-properties.element.ts index 5216a7518b27..664f26d4626c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/content-editor-properties.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/content-editor-properties.element.ts @@ -15,7 +15,6 @@ import type { UmbVariantPropertyWriteState, } from '@umbraco-cms/backoffice/variant'; import { UMB_PROPERTY_DATASET_CONTEXT } from '@umbraco-cms/backoffice/property'; -import { isReferenceByAlias, isReferenceByUnique, isReferenceByVariantId } from '@umbraco-cms/backoffice/utils'; @customElement('umb-content-workspace-view-edit-properties') export class UmbContentWorkspaceViewEditPropertiesElement extends UmbLitElement { @@ -100,29 +99,15 @@ export class UmbContentWorkspaceViewEditPropertiesElement extends UmbLitElement } #isReadablePropertyType(property: UmbPropertyTypeModel) { - return this._propertyReadStates.some((state) => { - if (isReferenceByUnique(state.propertyType)) { - return state.propertyType.unique === property.unique; - } else if (isReferenceByAlias(state.propertyType)) { - return state.propertyType.alias === property.alias; - } else if (isReferenceByVariantId(state.propertyType)) { - return state.propertyType.variantId === this.#variantId; - } - return false; - }); + return this._propertyReadStates.some( + (state) => state.propertyType.unique === property.unique && state.propertyType.variantId.equal(this.#variantId!), + ); } #isWritablePropertyType(property: UmbPropertyTypeModel) { - return this._propertyWriteStates.some((state) => { - if (isReferenceByUnique(state.propertyType)) { - return state.propertyType.unique === property.unique; - } else if (isReferenceByAlias(state.propertyType)) { - return state.propertyType.alias === property.alias; - } else if (isReferenceByVariantId(state.propertyType)) { - return state.propertyType.variantId === this.#variantId; - } - return false; - }); + return this._propertyWriteStates.some( + (state) => state.propertyType.unique === property.unique && state.propertyType.variantId.equal(this.#variantId!), + ); } override render() { diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property/property-read-state.manager.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property/property-read-state.manager.ts index 80eb07f5adde..6e1151551ad7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/property/property-read-state.manager.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property/property-read-state.manager.ts @@ -1,11 +1,10 @@ -import type { UmbPropertyTypeReferenceTypeUnion } from './types/index.js'; +import type { UmbReferenceByUnique } from '@umbraco-cms/backoffice/models'; import { UmbStateManager, type UmbState } from '@umbraco-cms/backoffice/utils'; -export interface UmbPropertyReadState extends UmbState { - propertyType: PropertyTypeReferenceType; +export interface UmbPropertyReadState extends UmbState { + propertyType: UmbReferenceByUnique; } export class UmbPropertyReadStateManager< - ReferenceType = UmbPropertyTypeReferenceTypeUnion, - ReadStateType extends UmbPropertyReadState = UmbPropertyReadState, + ReadStateType extends UmbPropertyReadState = UmbPropertyReadState, > extends UmbStateManager {} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property/property-write-state.manager.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property/property-write-state.manager.ts index 84c162f0ca42..96b02234ae0e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/property/property-write-state.manager.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property/property-write-state.manager.ts @@ -1,11 +1,10 @@ -import type { UmbPropertyTypeReferenceTypeUnion } from './types/index.js'; import { UmbStateManager, type UmbState } from '@umbraco-cms/backoffice/utils'; +import type { UmbReferenceByUnique } from '@umbraco-cms/backoffice/models'; -export interface UmbPropertyWriteState extends UmbState { - propertyType: PropertyTypeReferenceType; +export interface UmbPropertyWriteState extends UmbState { + propertyType: UmbReferenceByUnique; } export class UmbPropertyWriteStateManager< - ReferenceType = UmbPropertyTypeReferenceTypeUnion, - WriteStateType extends UmbPropertyWriteState = UmbPropertyWriteState, + WriteStateType extends UmbPropertyWriteState = UmbPropertyWriteState, > extends UmbStateManager {} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property/types/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property/types/index.ts index b75d4ec4d2ed..b1800898cf99 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/property/types/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property/types/index.ts @@ -1,6 +1,2 @@ -import type { UmbReferenceByAlias, UmbReferenceByUnique } from '@umbraco-cms/backoffice/models'; - export type * from './property-value-data.type.js'; export type * from './unsupported-properties.type.js'; - -export type UmbPropertyTypeReferenceTypeUnion = UmbReferenceByUnique | UmbReferenceByAlias; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/utils/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/utils/index.ts index 0b4c37c6494f..e6aabbc8d175 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/utils/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/utils/index.ts @@ -26,5 +26,4 @@ export * from './selection-manager/selection.manager.js'; export * from './state-manager/index.js'; export * from './string/index.js'; export * from './deprecation/index.js'; -export * from './reference/index.js'; export type * from './type/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/utils/reference/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/utils/reference/index.ts deleted file mode 100644 index c318159eb6d5..000000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/core/utils/reference/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from './is-reference-by-alias.js'; -export * from './is-reference-by-unique.js'; -export * from './is-reference-by-variant-id.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/utils/reference/is-reference-by-alias.ts b/src/Umbraco.Web.UI.Client/src/packages/core/utils/reference/is-reference-by-alias.ts deleted file mode 100644 index 717f71187462..000000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/core/utils/reference/is-reference-by-alias.ts +++ /dev/null @@ -1,10 +0,0 @@ -import type { UmbReferenceByAlias } from '@umbraco-cms/backoffice/models'; - -/** - * - * @param {unknown} data The data to check if it is a ReferencedByUnique - * @returns {boolean} True if the data is a ReferencedByUnique - */ -export function isReferenceByAlias(data: unknown): data is UmbReferenceByAlias { - return (data as UmbReferenceByAlias).alias !== undefined; -} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/utils/reference/is-reference-by-unique.ts b/src/Umbraco.Web.UI.Client/src/packages/core/utils/reference/is-reference-by-unique.ts deleted file mode 100644 index 3f10748d216d..000000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/core/utils/reference/is-reference-by-unique.ts +++ /dev/null @@ -1,10 +0,0 @@ -import type { UmbReferenceByUnique } from '@umbraco-cms/backoffice/models'; - -/** - * - * @param {unknown} data The data to check if it is a ReferencedByUnique - * @returns {boolean} True if the data is a ReferencedByUnique - */ -export function isReferenceByUnique(data: unknown): data is UmbReferenceByUnique { - return (data as UmbReferenceByUnique).unique !== undefined; -} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/utils/reference/is-reference-by-variant-id.ts b/src/Umbraco.Web.UI.Client/src/packages/core/utils/reference/is-reference-by-variant-id.ts deleted file mode 100644 index 51709e5f9d85..000000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/core/utils/reference/is-reference-by-variant-id.ts +++ /dev/null @@ -1,10 +0,0 @@ -import type { UmbReferenceByVariantId } from '@umbraco-cms/backoffice/variant'; - -/** - * - * @param {unknown} data The data to check if it is a ReferencedByVariantId - * @returns {boolean} True if the data is a ReferencedByVariantId - */ -export function isReferenceByVariantId(data: unknown): data is UmbReferenceByVariantId { - return (data as UmbReferenceByVariantId).variantId !== undefined; -} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/variant/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/variant/types.ts index 75b0b29417ac..8cd6eb5f1d35 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/variant/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/variant/types.ts @@ -2,7 +2,6 @@ import type { UmbVariantId } from './variant-id.class.js'; import type { UmbLanguageDetailModel } from '@umbraco-cms/backoffice/language'; import type { ScheduleRequestModel } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbPropertyValueData } from '@umbraco-cms/backoffice/property'; -import type { UmbReferenceByAlias, UmbReferenceByUnique } from '@umbraco-cms/backoffice/models'; export type UmbObjectWithVariantProperties = { culture: string | null; @@ -53,11 +52,6 @@ export interface UmbReferenceByVariantId { variantId: UmbVariantId; } -export type UmbVariantPropertyTypeReferenceTypeUnion = - | UmbReferenceByUnique - | UmbReferenceByAlias - | UmbReferenceByVariantId; - /** @deprecated use `UmbEntityVariantPublishModel` instead */ // eslint-disable-next-line @typescript-eslint/no-empty-object-type export interface UmbVariantPublishModel extends UmbEntityVariantPublishModel {} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/variant/variant-property-read-state.manager.ts b/src/Umbraco.Web.UI.Client/src/packages/core/variant/variant-property-read-state.manager.ts index ae733f5889d2..238936799078 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/variant/variant-property-read-state.manager.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/variant/variant-property-read-state.manager.ts @@ -1,10 +1,9 @@ -import type { UmbVariantPropertyTypeReferenceTypeUnion } from './types.js'; +import type { UmbReferenceByVariantId } from './types.js'; +import type { UmbReferenceByUnique } from '@umbraco-cms/backoffice/models'; import { UmbPropertyReadStateManager, type UmbPropertyReadState } from '@umbraco-cms/backoffice/property'; -// eslint-disable-next-line @typescript-eslint/no-empty-object-type -export interface UmbVariantPropertyReadState extends UmbPropertyReadState {} +export interface UmbVariantPropertyReadState extends UmbPropertyReadState { + propertyType: UmbReferenceByUnique & UmbReferenceByVariantId; +} -export class UmbVariantPropertyReadStateManager extends UmbPropertyReadStateManager< - UmbVariantPropertyTypeReferenceTypeUnion, - UmbVariantPropertyReadState -> {} +export class UmbVariantPropertyReadStateManager extends UmbPropertyReadStateManager {} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/variant/variant-property-write-state.manager.ts b/src/Umbraco.Web.UI.Client/src/packages/core/variant/variant-property-write-state.manager.ts index f22bfc7cd1d7..14de48496b7a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/variant/variant-property-write-state.manager.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/variant/variant-property-write-state.manager.ts @@ -1,10 +1,9 @@ -import type { UmbVariantPropertyTypeReferenceTypeUnion } from './types.js'; +import type { UmbReferenceByVariantId } from './types.js'; import { UmbPropertyWriteStateManager, type UmbPropertyWriteState } from '@umbraco-cms/backoffice/property'; +import type { UmbReferenceByUnique } from '@umbraco-cms/backoffice/models'; -// eslint-disable-next-line @typescript-eslint/no-empty-object-type -export interface UmbVariantPropertyWriteState extends UmbPropertyWriteState {} +export interface UmbVariantPropertyWriteState extends UmbPropertyWriteState { + propertyType: UmbReferenceByUnique & UmbReferenceByVariantId; +} -export class UmbVariantPropertyWriteStateManager extends UmbPropertyWriteStateManager< - UmbVariantPropertyTypeReferenceTypeUnion, - UmbVariantPropertyWriteState -> {} +export class UmbVariantPropertyWriteStateManager extends UmbPropertyWriteStateManager {} From 533b81d843fe5704c432b18073d7707a75d6551d Mon Sep 17 00:00:00 2001 From: kjac Date: Wed, 19 Mar 2025 09:38:33 +0100 Subject: [PATCH 069/106] Allow storing empty lists of verbs --- .../Permissions/DocumentTypePropertyPermissionMapper.cs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/Umbraco.Cms.Api.Management/Mapping/Permissions/DocumentTypePropertyPermissionMapper.cs b/src/Umbraco.Cms.Api.Management/Mapping/Permissions/DocumentTypePropertyPermissionMapper.cs index fb73a186eb37..87278b53e4c8 100644 --- a/src/Umbraco.Cms.Api.Management/Mapping/Permissions/DocumentTypePropertyPermissionMapper.cs +++ b/src/Umbraco.Cms.Api.Management/Mapping/Permissions/DocumentTypePropertyPermissionMapper.cs @@ -54,13 +54,8 @@ public IEnumerable MapToGranularPermissions(IPermissionPres yield break; } - foreach (var verb in documentTypePermissionPresentationModel.Verbs) + foreach (var verb in documentTypePermissionPresentationModel.Verbs.Distinct().DefaultIfEmpty(string.Empty)) { - if (string.IsNullOrEmpty(verb)) - { - continue; - } - yield return new DocumentTypePropertyGranularPermission { Key = documentTypePermissionPresentationModel.DocumentType.Id, From 9eaa0da618bb5c97ec89a54a5b63e5c51f87f97e Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 19 Mar 2025 09:42:21 +0100 Subject: [PATCH 070/106] pass variant id to all states --- .../workspace/document-workspace.context.ts | 60 ++++++++++++------- 1 file changed, 38 insertions(+), 22 deletions(-) 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 439bc4ac8be9..423400cd409e 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 @@ -24,7 +24,12 @@ import { import { UMB_DOCUMENT_PROPERTY_VALUE_USER_PERMISSION_CONDITION_ALIAS } from '../user-permissions/document-property-value/conditions/constants.js'; import { UMB_DOCUMENT_DETAIL_MODEL_VARIANT_SCAFFOLD, UMB_DOCUMENT_WORKSPACE_ALIAS } from './constants.js'; import type { UmbEntityModel } from '@umbraco-cms/backoffice/entity'; -import { UMB_INVARIANT_CULTURE, UmbVariantId } from '@umbraco-cms/backoffice/variant'; +import { + UMB_INVARIANT_CULTURE, + UmbVariantId, + type UmbVariantPropertyReadState, + type UmbVariantPropertyWriteState, +} from '@umbraco-cms/backoffice/variant'; import { type UmbPublishableWorkspaceContext, UmbWorkspaceIsNewRedirectController, @@ -195,19 +200,25 @@ export class UmbDocumentWorkspaceContext }, }, onChange: (permitted: boolean) => { - const unique = 'UMB_PROPERTY_UNIQUE_' + property.unique; + const variantOptions = this.getVariants(); + const variantIds = variantOptions?.map((variant) => new UmbVariantId(variant.culture, variant.segment)); + + const states: Array = + variantIds?.map((variantId) => { + return { + unique: 'UMB_PROPERTY_' + property.unique + '_' + variantId.toString(), + message: '', + propertyType: { + unique: property.unique, + variantId, + }, + }; + }) || []; if (permitted) { - const state = { - unique, - message: '', - propertyType: { - unique: property.unique, - }, - }; - this.structure.propertyReadState.addState(state); + this.structure.propertyReadState.addStates(states); } else { - this.structure.propertyReadState.removeState(unique); + this.structure.propertyReadState.removeStates(states.map((state) => state.unique)); } }, }, @@ -224,20 +235,25 @@ export class UmbDocumentWorkspaceContext }, }, onChange: (permitted: boolean) => { - const unique = 'UMB_PROPERTY_UNIQUE_' + property.unique; + const variantOptions = this.getVariants(); + const variantIds = variantOptions?.map((variant) => new UmbVariantId(variant.culture, variant.segment)); + + const states: Array = + variantIds?.map((variantId) => { + return { + unique: 'UMB_PROPERTY_' + property.unique + '_' + variantId.toString(), + message: '', + propertyType: { + unique: property.unique, + variantId, + }, + }; + }) || []; if (permitted) { - const state = { - unique, - message: '', - propertyType: { - unique: property.unique, - }, - }; - - this.structure.propertyWriteState.addState(state); + this.structure.propertyWriteState.addStates(states); } else { - this.structure.propertyWriteState.removeState(unique); + this.structure.propertyWriteState.removeStates(states.map((state) => state.unique)); } }, }, From bdf639fcba5ac4689260342bb03b51f559868b65 Mon Sep 17 00:00:00 2001 From: kjac Date: Wed, 19 Mar 2025 10:06:13 +0100 Subject: [PATCH 071/106] Remove empty verbs --- .../Permissions/DocumentTypePropertyPermissionMapper.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Cms.Api.Management/Mapping/Permissions/DocumentTypePropertyPermissionMapper.cs b/src/Umbraco.Cms.Api.Management/Mapping/Permissions/DocumentTypePropertyPermissionMapper.cs index 87278b53e4c8..4e7dd5333a96 100644 --- a/src/Umbraco.Cms.Api.Management/Mapping/Permissions/DocumentTypePropertyPermissionMapper.cs +++ b/src/Umbraco.Cms.Api.Management/Mapping/Permissions/DocumentTypePropertyPermissionMapper.cs @@ -41,7 +41,10 @@ public IEnumerable MapManyAsync(IEnumerable x.Verb).ToHashSet(), + Verbs = propertyTypeGroup + .Select(x => x.Verb) + .Where(verb => verb.IsNullOrWhiteSpace() is false) + .ToHashSet(), }; } } From 2969517dd41bd8014faf4b9f074df61fc153b685 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 19 Mar 2025 10:23:40 +0100 Subject: [PATCH 072/106] add alias to name --- ...-document-property-value-granular-user-permission.element.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/input-document-property-value-granular-user-permission/input-document-property-value-granular-user-permission.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/input-document-property-value-granular-user-permission/input-document-property-value-granular-user-permission.element.ts index 7105e27aad7a..8e25eec8cd20 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/input-document-property-value-granular-user-permission/input-document-property-value-granular-user-permission.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/input-document-property-value-granular-user-permission/input-document-property-value-granular-user-permission.element.ts @@ -219,7 +219,7 @@ export class UmbInputDocumentPropertyValueGranularUserPermissionElement extends const documentType = this._documentTypes?.find((item) => item.unique === permission.documentType.unique); const propertyType = documentType?.properties.find((item) => item.unique === permission.propertyType.unique); - const permissionName = `${documentType?.name}: ${propertyType?.name}`; + const permissionName = `${documentType?.name}: ${propertyType?.name} (${propertyType?.alias})`; const verbNames = this.#getVerbNamesForPermission(permission); return html` From 4e2039f6da58e2f3581202ae6621cfdb46681438 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 19 Mar 2025 11:06:30 +0100 Subject: [PATCH 073/106] prevent picking the same property type multiple times --- ...rty-value-granular-permission-flow-modal.element.ts | 5 +---- ...perty-value-granular-permission-flow-modal.token.ts | 2 ++ .../property-type-modal/property-type-modal.element.ts | 10 ++++++++-- .../property-type-modal/property-type-modal.token.ts | 2 ++ ...-property-value-granular-user-permission.element.ts | 2 ++ 5 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/document-property-value-granular-permission-flow-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/document-property-value-granular-permission-flow-modal.element.ts index d2f31a0a4c66..8ac8f5d3133f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/document-property-value-granular-permission-flow-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/document-property-value-granular-permission-flow-modal.element.ts @@ -38,6 +38,7 @@ export class UmbDocumentPropertyValueGranularUserPermissionFlowModalElement exte preset: { verbs: this.data?.preset?.verbs, }, + pickableFilter: this.data?.pickablePropertyTypeFilter, }, }, ); @@ -70,10 +71,6 @@ export class UmbDocumentPropertyValueGranularUserPermissionFlowModalElement exte .props=${{ hideTreeRoot: true, hideTreeItemActions: true, - /* - pickableFilter: (treeItem: UmbDocumentTypeTreeItemModel) => - !this._items?.map((i) => i.unique).includes(treeItem.unique), - */ }} alias=${UMB_DOCUMENT_TYPE_TREE_ALIAS}> diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/document-property-value-granular-permission-flow-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/document-property-value-granular-permission-flow-modal.token.ts index 048bcb80ea68..7de1101c6094 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/document-property-value-granular-permission-flow-modal.token.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/document-property-value-granular-permission-flow-modal.token.ts @@ -1,7 +1,9 @@ +import type { UmbPropertyTypeModel } from '@umbraco-cms/backoffice/content-type'; import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; export interface UmbDocumentPropertyValueGranularUserPermissionFlowModalData { preset?: Partial; + pickablePropertyTypeFilter?: (propertyType: UmbPropertyTypeModel) => boolean; } export interface UmbDocumentPropertyValueGranularUserPermissionFlowModalValue { diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/property-type-modal/property-type-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/property-type-modal/property-type-modal.element.ts index bce2e80a1497..788b0bca66ed 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/property-type-modal/property-type-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/property-type-modal/property-type-modal.element.ts @@ -23,6 +23,9 @@ export class UmbDocumentPropertyValueGranularUserPermissionFlowPropertyTypeModal @state() _selectedItem: UmbPropertyTypeModel | null = null; + @state() + _pickableFilter: (propertyType: UmbPropertyTypeModel) => boolean = () => true; + #detailRepository = new UmbDocumentTypeDetailRepository(this); #onItemSelected(event: CustomEvent, item: UmbPropertyTypeModel) { @@ -40,6 +43,8 @@ export class UmbDocumentPropertyValueGranularUserPermissionFlowPropertyTypeModal throw new Error('Document type unique is required'); } + this._pickableFilter = this.data.pickableFilter ?? this._pickableFilter; + const { data } = await this.#detailRepository.requestByUnique(this.data.documentType.unique); this._documentTypeProperties = data?.properties ?? []; this._documentTypeName = data?.name; @@ -105,11 +110,12 @@ export class UmbDocumentPropertyValueGranularUserPermissionFlowPropertyTypeModal this.#onItemSelected(event, item)} @deselected=${(event: CustomEvent) => this.#onItemDeselected(event)} - ?selected=${this._selectedItem?.unique === item.unique}> + ?selected=${this._selectedItem?.unique === item.unique} + ?disabled=${!this._pickableFilter(item)}> `, diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/property-type-modal/property-type-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/property-type-modal/property-type-modal.token.ts index b2df35ddeefa..5d1182d14412 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/property-type-modal/property-type-modal.token.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/property-type-modal/property-type-modal.token.ts @@ -1,4 +1,5 @@ import { UMB_DOCUMENT_PROPERTY_VALUE_GRANULAR_USER_PERMISSION_FLOW_PROPERTY_TYPE_MODAL_ALIAS } from './constants.js'; +import type { UmbPropertyTypeModel } from '@umbraco-cms/backoffice/content-type'; import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; export interface UmbDocumentPropertyValueGranularUserPermissionFlowPropertyTypeModalData { @@ -6,6 +7,7 @@ export interface UmbDocumentPropertyValueGranularUserPermissionFlowPropertyTypeM unique: string; }; preset?: Partial; + pickableFilter?: (propertyType: UmbPropertyTypeModel) => boolean; } export interface UmbDocumentPropertyValueGranularUserPermissionFlowPropertyTypeModalValue { diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/input-document-property-value-granular-user-permission/input-document-property-value-granular-user-permission.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/input-document-property-value-granular-user-permission/input-document-property-value-granular-user-permission.element.ts index 8e25eec8cd20..3f251554cdf9 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/input-document-property-value-granular-user-permission/input-document-property-value-granular-user-permission.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/input-document-property-value-granular-user-permission/input-document-property-value-granular-user-permission.element.ts @@ -72,6 +72,8 @@ export class UmbInputDocumentPropertyValueGranularUserPermissionElement extends preset: { verbs: this.#getFallbackPermissionVerbsForEntityType(UMB_DOCUMENT_PROPERTY_VALUE_ENTITY_TYPE), }, + pickablePropertyTypeFilter: (propertyType) => + !this._permissions.some((permission) => permission.propertyType.unique === propertyType.unique), }, }); From 77ac3ff057dc7ec6651298f760a80f0b30932705 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 19 Mar 2025 11:27:50 +0100 Subject: [PATCH 074/106] fix lint errors --- .../workspace/content-type-workspace-context-base.ts | 1 - .../core/property/components/property/property.context.ts | 3 +-- .../src/packages/documents/document-blueprints/types.ts | 1 - ...t-property-value-granular-permission-flow-modal.element.ts | 4 +++- .../documents/workspace/document-workspace.context.ts | 1 - src/Umbraco.Web.UI.Client/src/packages/media/media/types.ts | 2 +- .../src/packages/members/member/types.ts | 2 +- 7 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/workspace/content-type-workspace-context-base.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/workspace/content-type-workspace-context-base.ts index 382d4b67e97f..42fd9945506f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/workspace/content-type-workspace-context-base.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/workspace/content-type-workspace-context-base.ts @@ -17,7 +17,6 @@ import { UmbRequestReloadStructureForEntityEvent, } from '@umbraco-cms/backoffice/entity-action'; import type { UmbEntityModel } from '@umbraco-cms/backoffice/entity'; -import { UmbPropertyReadStateManager } from '@umbraco-cms/backoffice/property'; // eslint-disable-next-line @typescript-eslint/no-empty-object-type export interface UmbContentTypeWorkspaceContextArgs extends UmbEntityDetailWorkspaceContextArgs {} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property/components/property/property.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property/components/property/property.context.ts index 6926a35ffbd2..76d17d0de4fa 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/property/components/property/property.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property/components/property/property.context.ts @@ -4,7 +4,6 @@ import { UmbContextBase } from '@umbraco-cms/backoffice/class-api'; import { UmbArrayState, UmbBasicState, - UmbBooleanState, UmbClassState, UmbDeepState, UmbObjectState, @@ -22,7 +21,7 @@ import type { UmbPropertyTypeAppearanceModel, UmbPropertyTypeValidationModel, } from '@umbraco-cms/backoffice/content-type'; -import { UmbReadOnlyStateManager, UmbStateManager } from '@umbraco-cms/backoffice/utils'; +import { UmbReadOnlyStateManager } from '@umbraco-cms/backoffice/utils'; export class UmbPropertyContext extends UmbContextBase> { #alias = new UmbStringState(undefined); diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/types.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/types.ts index da735359b897..c6a4d4f66497 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/types.ts @@ -3,7 +3,6 @@ import type { UmbEntityVariantModel, UmbEntityVariantOptionModel } from '@umbrac import type { UmbReferenceByUnique } from '@umbraco-cms/backoffice/models'; import { DocumentVariantStateModel as UmbDocumentBlueprintVariantState } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbElementValueModel } from '@umbraco-cms/backoffice/content'; -import type { UmbDocumentPropertyValueEntityType } from '@umbraco-cms/backoffice/document'; export { UmbDocumentBlueprintVariantState }; export type * from './tree/types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/document-property-value-granular-permission-flow-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/document-property-value-granular-permission-flow-modal.element.ts index 8ac8f5d3133f..1a28f1aa05a7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/document-property-value-granular-permission-flow-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/document-property-value-granular-permission-flow-modal.element.ts @@ -53,7 +53,9 @@ export class UmbDocumentPropertyValueGranularUserPermissionFlowModalElement exte }); this._submitModal(); - } catch {} + } catch (err) { + console.error(err); + } } #onTreeSelectionChange(event: UmbSelectionChangeEvent) { 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 423400cd409e..b0b65c364053 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 @@ -27,7 +27,6 @@ import type { UmbEntityModel } from '@umbraco-cms/backoffice/entity'; import { UMB_INVARIANT_CULTURE, UmbVariantId, - type UmbVariantPropertyReadState, type UmbVariantPropertyWriteState, } from '@umbraco-cms/backoffice/variant'; import { diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/types.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/types.ts index 99c31330c7c8..c9545de5a05e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/types.ts @@ -1,4 +1,4 @@ -import type { UmbMediaEntityType, UmbMediaPropertyValueEntityType } from './entity.js'; +import type { UmbMediaEntityType } from './entity.js'; import type { UmbEntityVariantModel, UmbEntityVariantOptionModel } from '@umbraco-cms/backoffice/variant'; import type { UmbReferenceByUnique } from '@umbraco-cms/backoffice/models'; import type { UmbContentDetailModel, UmbElementValueModel } from '@umbraco-cms/backoffice/content'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/types.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/types.ts index 60e1b6d09721..cb8c9c153dcc 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/types.ts @@ -1,4 +1,4 @@ -import type { UmbMemberEntityType, UmbMemberPropertyValueEntityType } from './entity.js'; +import type { UmbMemberEntityType } from './entity.js'; import type { UmbMemberKindType } from './utils/index.js'; import type { UmbEntityVariantModel, UmbEntityVariantOptionModel } from '@umbraco-cms/backoffice/variant'; import type { UmbContentDetailModel, UmbElementValueModel } from '@umbraco-cms/backoffice/content'; From fc5bd249d84ebede31859099f21c8bad32ec8865 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 19 Mar 2025 11:46:31 +0100 Subject: [PATCH 075/106] fix create state by observing variant options --- .../edit/content-editor-properties.element.ts | 8 +- .../workspace/document-workspace.context.ts | 139 +++++++++--------- 2 files changed, 74 insertions(+), 73 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/content-editor-properties.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/content-editor-properties.element.ts index 664f26d4626c..9bb3a1acb2fe 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/content-editor-properties.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/content-editor-properties.element.ts @@ -52,17 +52,13 @@ export class UmbContentWorkspaceViewEditPropertiesElement extends UmbLitElement this.observe( workspaceContext.structure.propertyReadState.states, - (states) => { - this._propertyReadStates = states; - }, + (states) => (this._propertyReadStates = states), 'umbObservePropertyReadStates', ); this.observe( workspaceContext.structure.propertyWriteState.states, - (states) => { - this._propertyWriteStates = states; - }, + (states) => (this._propertyWriteStates = states), 'umbObservePropertyWriteStates', ); }); 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 b0b65c364053..4bd410930662 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 @@ -46,6 +46,7 @@ import { UmbIsTrashedEntityContext } from '@umbraco-cms/backoffice/recycle-bin'; import { UMB_APP_CONTEXT } from '@umbraco-cms/backoffice/app'; import { ensurePathEndsWithSlash, UmbDeprecation } from '@umbraco-cms/backoffice/utils'; import { createExtensionApiByAlias } from '@umbraco-cms/backoffice/extension-registry'; +import { observeMultiple } from '@umbraco-cms/backoffice/observable-api'; type ContentModel = UmbDocumentDetailModel; type ContentTypeModel = UmbDocumentTypeDetailModel; @@ -186,79 +187,83 @@ export class UmbDocumentWorkspaceContext }, ]); - this.observe(this.structure.contentTypeProperties, (properties) => { - properties.forEach((property) => { - createExtensionApiByAlias(this, UMB_DOCUMENT_PROPERTY_VALUE_USER_PERMISSION_CONDITION_ALIAS, [ - { - config: { - allOf: [UMB_USER_PERMISSION_DOCUMENT_PROPERTY_VALUE_READ], - match: { - propertyType: { - unique: property.unique, + this.observe( + observeMultiple([this.structure.contentTypeProperties, this.variantOptions]), + ([properties, variantOptions]) => { + if (properties.length === 0) return; + if (variantOptions.length === 0) return; + + properties.forEach((property) => { + createExtensionApiByAlias(this, UMB_DOCUMENT_PROPERTY_VALUE_USER_PERMISSION_CONDITION_ALIAS, [ + { + config: { + allOf: [UMB_USER_PERMISSION_DOCUMENT_PROPERTY_VALUE_READ], + match: { + propertyType: { + unique: property.unique, + }, }, }, + onChange: (permitted: boolean) => { + const variantIds = variantOptions?.map((variant) => new UmbVariantId(variant.culture, variant.segment)); + + const states: Array = + variantIds?.map((variantId) => { + return { + unique: 'UMB_PROPERTY_' + property.unique + '_' + variantId.toString(), + message: '', + propertyType: { + unique: property.unique, + variantId, + }, + }; + }) || []; + + if (permitted) { + this.structure.propertyReadState.addStates(states); + } else { + this.structure.propertyReadState.removeStates(states.map((state) => state.unique)); + } + }, }, - onChange: (permitted: boolean) => { - const variantOptions = this.getVariants(); - const variantIds = variantOptions?.map((variant) => new UmbVariantId(variant.culture, variant.segment)); - - const states: Array = - variantIds?.map((variantId) => { - return { - unique: 'UMB_PROPERTY_' + property.unique + '_' + variantId.toString(), - message: '', - propertyType: { - unique: property.unique, - variantId, - }, - }; - }) || []; - - if (permitted) { - this.structure.propertyReadState.addStates(states); - } else { - this.structure.propertyReadState.removeStates(states.map((state) => state.unique)); - } - }, - }, - ]); - - createExtensionApiByAlias(this, UMB_DOCUMENT_PROPERTY_VALUE_USER_PERMISSION_CONDITION_ALIAS, [ - { - config: { - allOf: [UMB_USER_PERMISSION_DOCUMENT_PROPERTY_VALUE_WRITE], - match: { - propertyType: { - unique: property.unique, + ]); + + createExtensionApiByAlias(this, UMB_DOCUMENT_PROPERTY_VALUE_USER_PERMISSION_CONDITION_ALIAS, [ + { + config: { + allOf: [UMB_USER_PERMISSION_DOCUMENT_PROPERTY_VALUE_WRITE], + match: { + propertyType: { + unique: property.unique, + }, }, }, + onChange: (permitted: boolean) => { + const variantIds = variantOptions?.map((variant) => new UmbVariantId(variant.culture, variant.segment)); + + const states: Array = + variantIds?.map((variantId) => { + return { + unique: 'UMB_PROPERTY_' + property.unique + '_' + variantId.toString(), + message: '', + propertyType: { + unique: property.unique, + variantId, + }, + }; + }) || []; + + if (permitted) { + this.structure.propertyWriteState.addStates(states); + } else { + this.structure.propertyWriteState.removeStates(states.map((state) => state.unique)); + } + }, }, - onChange: (permitted: boolean) => { - const variantOptions = this.getVariants(); - const variantIds = variantOptions?.map((variant) => new UmbVariantId(variant.culture, variant.segment)); - - const states: Array = - variantIds?.map((variantId) => { - return { - unique: 'UMB_PROPERTY_' + property.unique + '_' + variantId.toString(), - message: '', - propertyType: { - unique: property.unique, - variantId, - }, - }; - }) || []; - - if (permitted) { - this.structure.propertyWriteState.addStates(states); - } else { - this.structure.propertyWriteState.removeStates(states.map((state) => state.unique)); - } - }, - }, - ]); - }); - }); + ]); + }); + }, + ); } override resetState(): void { From 313577bcc87a68b432a21f3f26447cdd617ee887 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 19 Mar 2025 13:26:14 +0100 Subject: [PATCH 076/106] move to workspace context --- .../document-property-value/manifests.ts | 4 +- ...user-permission.workspace-context.token.ts | 7 ++ ...value-user-permission.workspace-context.ts | 104 ++++++++++++++++++ .../workspace-context/manifests.ts | 18 +++ .../workspace/document-workspace.context.ts | 91 +-------------- 5 files changed, 134 insertions(+), 90 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/workspace-context/document-property-value-user-permission.workspace-context.token.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/workspace-context/document-property-value-user-permission.workspace-context.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/workspace-context/manifests.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/manifests.ts index 8bc1f7f2b956..7a239146c949 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/manifests.ts @@ -6,6 +6,7 @@ import { import { manifests as documentPropertyValueGranularPermissionFlowModalManifests } from './document-property-value-granular-permission-flow-modal/manifests.js'; import { manifests as conditionManifests } from './conditions/manifests.js'; import { manifests as dataManifests } from './data/manifests.js'; +import { manifests as workspaceContextManifests } from './workspace-context/manifests.js'; import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; export const manifests: Array = [ @@ -48,7 +49,8 @@ export const manifests: Array = description: 'Assign Permissions to Document property values', }, }, - ...documentPropertyValueGranularPermissionFlowModalManifests, ...conditionManifests, ...dataManifests, + ...documentPropertyValueGranularPermissionFlowModalManifests, + ...workspaceContextManifests, ]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/workspace-context/document-property-value-user-permission.workspace-context.token.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/workspace-context/document-property-value-user-permission.workspace-context.token.ts new file mode 100644 index 000000000000..ee94d8a0f82e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/workspace-context/document-property-value-user-permission.workspace-context.token.ts @@ -0,0 +1,7 @@ +import type { UmbDocumentPropertyValueUserPermissionWorkspaceContext } from './document-property-value-user-permission.workspace-context.js'; +import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; + +export const UMB_DOCUMENT_PROPERTY_VALUE_USER_PERMISSION_WORKSPACE_CONTEXT = + new UmbContextToken( + 'UmbDocumentPropertyValueUserPermissionWorkspaceContext', + ); diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/workspace-context/document-property-value-user-permission.workspace-context.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/workspace-context/document-property-value-user-permission.workspace-context.ts new file mode 100644 index 000000000000..47d1cb254d14 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/workspace-context/document-property-value-user-permission.workspace-context.ts @@ -0,0 +1,104 @@ +import { UMB_DOCUMENT_WORKSPACE_CONTEXT } from '../../../workspace/constants.js'; +import { UMB_DOCUMENT_PROPERTY_VALUE_USER_PERMISSION_CONDITION_ALIAS } from '../conditions/constants.js'; +import { + UMB_USER_PERMISSION_DOCUMENT_PROPERTY_VALUE_READ, + UMB_USER_PERMISSION_DOCUMENT_PROPERTY_VALUE_WRITE, +} from '../constants.js'; +import type { UmbDocumentVariantModel } from '../../../types.js'; +import { UMB_DOCUMENT_PROPERTY_VALUE_USER_PERMISSION_WORKSPACE_CONTEXT } from './document-property-value-user-permission.workspace-context.token.js'; +import { UmbContextBase } from '@umbraco-cms/backoffice/class-api'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import { observeMultiple } from '@umbraco-cms/backoffice/observable-api'; +import { createExtensionApiByAlias } from '@umbraco-cms/backoffice/extension-registry'; +import { + UmbVariantId, + type UmbEntityVariantOptionModel, + type UmbVariantPropertyReadState, + type UmbVariantPropertyWriteState, +} from '@umbraco-cms/backoffice/variant'; +import type { UmbPropertyTypeModel } from '@umbraco-cms/backoffice/content-type'; +import type { UmbStateManager } from '@umbraco-cms/backoffice/utils'; + +export class UmbDocumentPropertyValueUserPermissionWorkspaceContext extends UmbContextBase { + #workspaceContext?: typeof UMB_DOCUMENT_WORKSPACE_CONTEXT.TYPE; + + constructor(host: UmbControllerHost) { + super(host, UMB_DOCUMENT_PROPERTY_VALUE_USER_PERMISSION_WORKSPACE_CONTEXT); + + this.consumeContext(UMB_DOCUMENT_WORKSPACE_CONTEXT, (context) => { + this.#workspaceContext = context; + this.#observeStructure(); + }); + } + + #observeStructure() { + if (!this.#workspaceContext) return; + + this.observe( + observeMultiple([this.#workspaceContext.structure.contentTypeProperties, this.#workspaceContext.variantOptions]), + ([properties, variantOptions]) => { + if (properties.length === 0) return; + if (variantOptions.length === 0) return; + + properties.forEach((property) => { + this.#setPermissionForProperty({ + verb: UMB_USER_PERMISSION_DOCUMENT_PROPERTY_VALUE_READ, + stateManager: this.#workspaceContext!.structure.propertyReadState, + property, + variantOptions, + }); + + this.#setPermissionForProperty({ + verb: UMB_USER_PERMISSION_DOCUMENT_PROPERTY_VALUE_WRITE, + stateManager: this.#workspaceContext!.structure.propertyWriteState, + property, + variantOptions, + }); + }); + }, + ); + } + + #setPermissionForProperty(args: { + verb: string; + stateManager: UmbStateManager; + property: UmbPropertyTypeModel; + variantOptions: Array>; + }) { + createExtensionApiByAlias(this, UMB_DOCUMENT_PROPERTY_VALUE_USER_PERMISSION_CONDITION_ALIAS, [ + { + config: { + allOf: [args.verb], + match: { + propertyType: { + unique: args.property.unique, + }, + }, + }, + onChange: (permitted: boolean) => { + const variantIds = args.variantOptions?.map((variant) => new UmbVariantId(variant.culture, variant.segment)); + + const states: Array = + variantIds?.map((variantId) => { + return { + unique: 'UMB_PROPERTY_' + args.property.unique + '_' + variantId.toString(), + message: '', + propertyType: { + unique: args.property.unique, + variantId, + }, + }; + }) || []; + + if (permitted) { + args.stateManager.addStates(states); + } else { + args.stateManager.removeStates(states.map((state) => state.unique)); + } + }, + }, + ]); + } +} + +export { UmbDocumentPropertyValueUserPermissionWorkspaceContext as api }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/workspace-context/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/workspace-context/manifests.ts new file mode 100644 index 000000000000..8db7ef6acc4c --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/workspace-context/manifests.ts @@ -0,0 +1,18 @@ +import { UMB_DOCUMENT_WORKSPACE_ALIAS } from '../../../workspace/constants.js'; +import { UMB_WORKSPACE_CONDITION_ALIAS } from '@umbraco-cms/backoffice/workspace'; +import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'workspaceContext', + name: 'Document Property Value User Permission Workspace Context', + alias: 'Umb.WorkspaceContext.DocumentPropertyValueUserPermission', + api: () => import('./document-property-value-user-permission.workspace-context.js'), + conditions: [ + { + alias: UMB_WORKSPACE_CONDITION_ALIAS, + match: UMB_DOCUMENT_WORKSPACE_ALIAS, + }, + ], + }, +]; 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 4bd410930662..79e057fe5c25 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 @@ -17,18 +17,10 @@ import { import { UmbDocumentPreviewRepository } from '../repository/preview/index.js'; import { UMB_DOCUMENT_PUBLISHING_WORKSPACE_CONTEXT, UmbDocumentPublishingRepository } from '../publishing/index.js'; import { UmbDocumentValidationRepository } from '../repository/validation/index.js'; -import { - UMB_USER_PERMISSION_DOCUMENT_PROPERTY_VALUE_READ, - UMB_USER_PERMISSION_DOCUMENT_PROPERTY_VALUE_WRITE, -} from '../user-permissions/document-property-value/constants.js'; -import { UMB_DOCUMENT_PROPERTY_VALUE_USER_PERMISSION_CONDITION_ALIAS } from '../user-permissions/document-property-value/conditions/constants.js'; +import {} from '../user-permissions/document-property-value/constants.js'; import { UMB_DOCUMENT_DETAIL_MODEL_VARIANT_SCAFFOLD, UMB_DOCUMENT_WORKSPACE_ALIAS } from './constants.js'; import type { UmbEntityModel } from '@umbraco-cms/backoffice/entity'; -import { - UMB_INVARIANT_CULTURE, - UmbVariantId, - type UmbVariantPropertyWriteState, -} from '@umbraco-cms/backoffice/variant'; +import { UMB_INVARIANT_CULTURE, UmbVariantId } from '@umbraco-cms/backoffice/variant'; import { type UmbPublishableWorkspaceContext, UmbWorkspaceIsNewRedirectController, @@ -46,7 +38,6 @@ import { UmbIsTrashedEntityContext } from '@umbraco-cms/backoffice/recycle-bin'; import { UMB_APP_CONTEXT } from '@umbraco-cms/backoffice/app'; import { ensurePathEndsWithSlash, UmbDeprecation } from '@umbraco-cms/backoffice/utils'; import { createExtensionApiByAlias } from '@umbraco-cms/backoffice/extension-registry'; -import { observeMultiple } from '@umbraco-cms/backoffice/observable-api'; type ContentModel = UmbDocumentDetailModel; type ContentTypeModel = UmbDocumentTypeDetailModel; @@ -186,84 +177,6 @@ export class UmbDocumentWorkspaceContext }, }, ]); - - this.observe( - observeMultiple([this.structure.contentTypeProperties, this.variantOptions]), - ([properties, variantOptions]) => { - if (properties.length === 0) return; - if (variantOptions.length === 0) return; - - properties.forEach((property) => { - createExtensionApiByAlias(this, UMB_DOCUMENT_PROPERTY_VALUE_USER_PERMISSION_CONDITION_ALIAS, [ - { - config: { - allOf: [UMB_USER_PERMISSION_DOCUMENT_PROPERTY_VALUE_READ], - match: { - propertyType: { - unique: property.unique, - }, - }, - }, - onChange: (permitted: boolean) => { - const variantIds = variantOptions?.map((variant) => new UmbVariantId(variant.culture, variant.segment)); - - const states: Array = - variantIds?.map((variantId) => { - return { - unique: 'UMB_PROPERTY_' + property.unique + '_' + variantId.toString(), - message: '', - propertyType: { - unique: property.unique, - variantId, - }, - }; - }) || []; - - if (permitted) { - this.structure.propertyReadState.addStates(states); - } else { - this.structure.propertyReadState.removeStates(states.map((state) => state.unique)); - } - }, - }, - ]); - - createExtensionApiByAlias(this, UMB_DOCUMENT_PROPERTY_VALUE_USER_PERMISSION_CONDITION_ALIAS, [ - { - config: { - allOf: [UMB_USER_PERMISSION_DOCUMENT_PROPERTY_VALUE_WRITE], - match: { - propertyType: { - unique: property.unique, - }, - }, - }, - onChange: (permitted: boolean) => { - const variantIds = variantOptions?.map((variant) => new UmbVariantId(variant.culture, variant.segment)); - - const states: Array = - variantIds?.map((variantId) => { - return { - unique: 'UMB_PROPERTY_' + property.unique + '_' + variantId.toString(), - message: '', - propertyType: { - unique: property.unique, - variantId, - }, - }; - }) || []; - - if (permitted) { - this.structure.propertyWriteState.addStates(states); - } else { - this.structure.propertyWriteState.removeStates(states.map((state) => state.unique)); - } - }, - }, - ]); - }); - }, - ); } override resetState(): void { From bd94afc1867185386711f057f38f32829064927d Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 19 Mar 2025 20:41:27 +0100 Subject: [PATCH 077/106] Update document-property-value-user-permission.workspace-context.ts --- ...ment-property-value-user-permission.workspace-context.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/workspace-context/document-property-value-user-permission.workspace-context.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/workspace-context/document-property-value-user-permission.workspace-context.ts index 47d1cb254d14..f130f224bf7f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/workspace-context/document-property-value-user-permission.workspace-context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/workspace-context/document-property-value-user-permission.workspace-context.ts @@ -76,7 +76,11 @@ export class UmbDocumentPropertyValueUserPermissionWorkspaceContext extends UmbC }, }, onChange: (permitted: boolean) => { - const variantIds = args.variantOptions?.map((variant) => new UmbVariantId(variant.culture, variant.segment)); + // If the property is invariant we only need one state for the property + const isInvariant = args.property.variesByCulture === false && args.property.variesBySegment === false; + const variantIds = isInvariant + ? [new UmbVariantId()] + : args.variantOptions?.map((variant) => new UmbVariantId(variant.culture, variant.segment)) || []; const states: Array = variantIds?.map((variantId) => { From 12a97dab3b933b52a95843fdeb04f411bb8f23f2 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 19 Mar 2025 20:44:47 +0100 Subject: [PATCH 078/106] Update content-editor-properties.element.ts --- .../edit/content-editor-properties.element.ts | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/content-editor-properties.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/content-editor-properties.element.ts index 9bb3a1acb2fe..c8deaa05f809 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/content-editor-properties.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/content-editor-properties.element.ts @@ -9,10 +9,10 @@ import { UmbContentTypePropertyStructureHelper } from '@umbraco-cms/backoffice/c import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UmbDataPathPropertyValueQuery } from '@umbraco-cms/backoffice/validation'; import { UMB_PROPERTY_STRUCTURE_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace'; -import type { +import { UmbVariantId, - UmbVariantPropertyReadState, - UmbVariantPropertyWriteState, + type UmbVariantPropertyReadState, + type UmbVariantPropertyWriteState, } from '@umbraco-cms/backoffice/variant'; import { UMB_PROPERTY_DATASET_CONTEXT } from '@umbraco-cms/backoffice/property'; @@ -95,14 +95,23 @@ export class UmbContentWorkspaceViewEditPropertiesElement extends UmbLitElement } #isReadablePropertyType(property: UmbPropertyTypeModel) { + const propertyVariantId = this.#getPropertyVariantId(property); return this._propertyReadStates.some( - (state) => state.propertyType.unique === property.unique && state.propertyType.variantId.equal(this.#variantId!), + (state) => state.propertyType.unique === property.unique && state.propertyType.variantId.equal(propertyVariantId), ); } #isWritablePropertyType(property: UmbPropertyTypeModel) { + const propertyVariantId = this.#getPropertyVariantId(property); return this._propertyWriteStates.some( - (state) => state.propertyType.unique === property.unique && state.propertyType.variantId.equal(this.#variantId!), + (state) => state.propertyType.unique === property.unique && state.propertyType.variantId.equal(propertyVariantId), + ); + } + + #getPropertyVariantId(property: UmbPropertyTypeModel) { + return new UmbVariantId( + property.variesByCulture ? this.#variantId!.culture : null, + property.variesBySegment ? this.#variantId!.segment : null, ); } From b321f7ece9221a73bdf33d81a0950b4765056629 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 20 Mar 2025 11:36:58 +0100 Subject: [PATCH 079/106] clean up --- ...ue-granular-permission-flow-modal.token.ts | 27 ------------- .../index.ts | 1 - .../property-type-modal/constants.ts | 2 - .../property-type-modal/index.ts | 1 - .../property-type-modal/manifests.ts | 11 ------ .../property-type-modal.token.ts | 28 -------------- ...ty-value-permission-flow-modal.element.ts} | 38 +++++++++---------- ...perty-value-permission-flow-modal.token.ts | 27 +++++++++++++ .../index.ts | 1 + .../manifests.ts | 6 +-- .../property-type-modal/constants.ts | 2 + .../property-type-modal/index.ts | 1 + .../property-type-modal/manifests.ts | 11 ++++++ .../property-type-modal.element.ts | 16 ++++---- .../property-type-modal.token.ts | 28 ++++++++++++++ ...property-value-user-permission.element.ts} | 24 ++++++------ .../document-property-value/manifests.ts | 6 +-- 17 files changed, 113 insertions(+), 117 deletions(-) delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/document-property-value-granular-permission-flow-modal.token.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/index.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/property-type-modal/constants.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/property-type-modal/index.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/property-type-modal/manifests.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/property-type-modal/property-type-modal.token.ts rename src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/{document-property-value-granular-permission-flow-modal/document-property-value-granular-permission-flow-modal.element.ts => document-property-value-permission-flow-modal/document-property-value-permission-flow-modal.element.ts} (63%) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-permission-flow-modal/document-property-value-permission-flow-modal.token.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-permission-flow-modal/index.ts rename src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/{document-property-value-granular-permission-flow-modal => document-property-value-permission-flow-modal}/manifests.ts (58%) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-permission-flow-modal/property-type-modal/constants.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-permission-flow-modal/property-type-modal/index.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-permission-flow-modal/property-type-modal/manifests.ts rename src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/{document-property-value-granular-permission-flow-modal => document-property-value-permission-flow-modal}/property-type-modal/property-type-modal.element.ts (84%) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-permission-flow-modal/property-type-modal/property-type-modal.token.ts rename src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/{input-document-property-value-granular-user-permission/input-document-property-value-granular-user-permission.element.ts => input-document-property-value-user-permission/input-document-property-value-user-permission.element.ts} (89%) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/document-property-value-granular-permission-flow-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/document-property-value-granular-permission-flow-modal.token.ts deleted file mode 100644 index 7de1101c6094..000000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/document-property-value-granular-permission-flow-modal.token.ts +++ /dev/null @@ -1,27 +0,0 @@ -import type { UmbPropertyTypeModel } from '@umbraco-cms/backoffice/content-type'; -import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; - -export interface UmbDocumentPropertyValueGranularUserPermissionFlowModalData { - preset?: Partial; - pickablePropertyTypeFilter?: (propertyType: UmbPropertyTypeModel) => boolean; -} - -export interface UmbDocumentPropertyValueGranularUserPermissionFlowModalValue { - documentType: { - unique: string; - }; - propertyType: { - unique: string; - }; - verbs: Array; -} - -export const UMB_DOCUMENT_PROPERTY_VALUE_GRANULAR_USER_PERMISSION_FLOW_MODAL = new UmbModalToken< - UmbDocumentPropertyValueGranularUserPermissionFlowModalData, - UmbDocumentPropertyValueGranularUserPermissionFlowModalValue ->('Umb.Modal.DocumentPropertyValueGranularUserPermissionFlow', { - modal: { - type: 'sidebar', - size: 'small', - }, -}); diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/index.ts deleted file mode 100644 index e75e208ccc00..000000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { UMB_DOCUMENT_PROPERTY_VALUE_GRANULAR_USER_PERMISSION_FLOW_MODAL } from './document-property-value-granular-permission-flow-modal.token.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/property-type-modal/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/property-type-modal/constants.ts deleted file mode 100644 index b6c2bf5f5225..000000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/property-type-modal/constants.ts +++ /dev/null @@ -1,2 +0,0 @@ -export const UMB_DOCUMENT_PROPERTY_VALUE_GRANULAR_USER_PERMISSION_FLOW_PROPERTY_TYPE_MODAL_ALIAS = - 'Umb.Modal.DocumentPropertyValueGranularUserPermissionFlow.PropertyType'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/property-type-modal/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/property-type-modal/index.ts deleted file mode 100644 index e99afaf2b5c1..000000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/property-type-modal/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { UMB_DOCUMENT_PROPERTY_VALUE_GRANULAR_USER_PERMISSION_FLOW_PROPERTY_TYPE_MODAL } from './property-type-modal.token.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/property-type-modal/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/property-type-modal/manifests.ts deleted file mode 100644 index 109e45a5532b..000000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/property-type-modal/manifests.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { UMB_DOCUMENT_PROPERTY_VALUE_GRANULAR_USER_PERMISSION_FLOW_PROPERTY_TYPE_MODAL_ALIAS } from './constants.js'; -import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; - -export const manifests: Array = [ - { - type: 'modal', - alias: UMB_DOCUMENT_PROPERTY_VALUE_GRANULAR_USER_PERMISSION_FLOW_PROPERTY_TYPE_MODAL_ALIAS, - name: 'Document Property Value Granular User Permission Flow Property Type Modal', - element: () => import('./property-type-modal.element.js'), - }, -]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/property-type-modal/property-type-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/property-type-modal/property-type-modal.token.ts deleted file mode 100644 index 5d1182d14412..000000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/property-type-modal/property-type-modal.token.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { UMB_DOCUMENT_PROPERTY_VALUE_GRANULAR_USER_PERMISSION_FLOW_PROPERTY_TYPE_MODAL_ALIAS } from './constants.js'; -import type { UmbPropertyTypeModel } from '@umbraco-cms/backoffice/content-type'; -import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; - -export interface UmbDocumentPropertyValueGranularUserPermissionFlowPropertyTypeModalData { - documentType: { - unique: string; - }; - preset?: Partial; - pickableFilter?: (propertyType: UmbPropertyTypeModel) => boolean; -} - -export interface UmbDocumentPropertyValueGranularUserPermissionFlowPropertyTypeModalValue { - propertyType: { - unique: string; - }; - verbs: Array; -} - -export const UMB_DOCUMENT_PROPERTY_VALUE_GRANULAR_USER_PERMISSION_FLOW_PROPERTY_TYPE_MODAL = new UmbModalToken< - UmbDocumentPropertyValueGranularUserPermissionFlowPropertyTypeModalData, - UmbDocumentPropertyValueGranularUserPermissionFlowPropertyTypeModalValue ->(UMB_DOCUMENT_PROPERTY_VALUE_GRANULAR_USER_PERMISSION_FLOW_PROPERTY_TYPE_MODAL_ALIAS, { - modal: { - type: 'sidebar', - size: 'small', - }, -}); diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/document-property-value-granular-permission-flow-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-permission-flow-modal/document-property-value-permission-flow-modal.element.ts similarity index 63% rename from src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/document-property-value-granular-permission-flow-modal.element.ts rename to src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-permission-flow-modal/document-property-value-permission-flow-modal.element.ts index 1a28f1aa05a7..d9c8e9b90c48 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/document-property-value-granular-permission-flow-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-permission-flow-modal/document-property-value-permission-flow-modal.element.ts @@ -1,18 +1,18 @@ -import { UMB_DOCUMENT_PROPERTY_VALUE_GRANULAR_USER_PERMISSION_FLOW_PROPERTY_TYPE_MODAL } from './property-type-modal/property-type-modal.token.js'; +import { UMB_DOCUMENT_PROPERTY_VALUE_USER_PERMISSION_FLOW_PROPERTY_TYPE_MODAL } from './property-type-modal/property-type-modal.token.js'; import type { - UmbDocumentPropertyValueGranularUserPermissionFlowModalData, - UmbDocumentPropertyValueGranularUserPermissionFlowModalValue, -} from './document-property-value-granular-permission-flow-modal.token.js'; + UmbDocumentPropertyValueUserPermissionFlowModalData, + UmbDocumentPropertyValueUserPermissionFlowModalValue, +} from './document-property-value-permission-flow-modal.token.js'; import { html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; import { UMB_MODAL_MANAGER_CONTEXT, UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; import { UMB_DOCUMENT_TYPE_TREE_ALIAS } from '@umbraco-cms/backoffice/document-type'; import type { UmbSelectionChangeEvent } from '@umbraco-cms/backoffice/event'; import type { UmbTreeElement } from '@umbraco-cms/backoffice/tree'; -@customElement('umb-document-property-value-granular-user-permission-flow-modal') -export class UmbDocumentPropertyValueGranularUserPermissionFlowModalElement extends UmbModalBaseElement< - UmbDocumentPropertyValueGranularUserPermissionFlowModalData, - UmbDocumentPropertyValueGranularUserPermissionFlowModalValue +@customElement('umb-document-property-value-user-permission-flow-modal') +export class UmbDocumentPropertyValueUserPermissionFlowModalElement extends UmbModalBaseElement< + UmbDocumentPropertyValueUserPermissionFlowModalData, + UmbDocumentPropertyValueUserPermissionFlowModalValue > { @state() _selection: Array = []; @@ -29,19 +29,15 @@ export class UmbDocumentPropertyValueGranularUserPermissionFlowModalElement exte throw new Error('Could not get modal manager context'); } - const modal = modalManager.open( - this, - UMB_DOCUMENT_PROPERTY_VALUE_GRANULAR_USER_PERMISSION_FLOW_PROPERTY_TYPE_MODAL, - { - data: { - documentType, - preset: { - verbs: this.data?.preset?.verbs, - }, - pickableFilter: this.data?.pickablePropertyTypeFilter, + const modal = modalManager.open(this, UMB_DOCUMENT_PROPERTY_VALUE_USER_PERMISSION_FLOW_PROPERTY_TYPE_MODAL, { + data: { + documentType, + preset: { + verbs: this.data?.preset?.verbs, }, + pickableFilter: this.data?.pickablePropertyTypeFilter, }, - ); + }); try { const value = await modal.onSubmit(); @@ -90,10 +86,10 @@ export class UmbDocumentPropertyValueGranularUserPermissionFlowModalElement exte } } -export { UmbDocumentPropertyValueGranularUserPermissionFlowModalElement as element }; +export { UmbDocumentPropertyValueUserPermissionFlowModalElement as element }; declare global { interface HTMLElementTagNameMap { - 'umb-document-property-value-granular-user-permission-flow-modal': UmbDocumentPropertyValueGranularUserPermissionFlowModalElement; + 'umb-document-property-value-user-permission-flow-modal': UmbDocumentPropertyValueUserPermissionFlowModalElement; } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-permission-flow-modal/document-property-value-permission-flow-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-permission-flow-modal/document-property-value-permission-flow-modal.token.ts new file mode 100644 index 000000000000..be0a2f26984a --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-permission-flow-modal/document-property-value-permission-flow-modal.token.ts @@ -0,0 +1,27 @@ +import type { UmbPropertyTypeModel } from '@umbraco-cms/backoffice/content-type'; +import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; + +export interface UmbDocumentPropertyValueUserPermissionFlowModalData { + preset?: Partial; + pickablePropertyTypeFilter?: (propertyType: UmbPropertyTypeModel) => boolean; +} + +export interface UmbDocumentPropertyValueUserPermissionFlowModalValue { + documentType: { + unique: string; + }; + propertyType: { + unique: string; + }; + verbs: Array; +} + +export const UMB_DOCUMENT_PROPERTY_VALUE_USER_PERMISSION_FLOW_MODAL = new UmbModalToken< + UmbDocumentPropertyValueUserPermissionFlowModalData, + UmbDocumentPropertyValueUserPermissionFlowModalValue +>('Umb.Modal.DocumentPropertyValueUserPermissionFlow', { + modal: { + type: 'sidebar', + size: 'small', + }, +}); diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-permission-flow-modal/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-permission-flow-modal/index.ts new file mode 100644 index 000000000000..6913b07b66e7 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-permission-flow-modal/index.ts @@ -0,0 +1 @@ +export { UMB_DOCUMENT_PROPERTY_VALUE_USER_PERMISSION_FLOW_MODAL } from './document-property-value-permission-flow-modal.token.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-permission-flow-modal/manifests.ts similarity index 58% rename from src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/manifests.ts rename to src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-permission-flow-modal/manifests.ts index 5bab0422bcc3..eaa896c9a446 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-permission-flow-modal/manifests.ts @@ -4,9 +4,9 @@ import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension export const manifests: Array = [ { type: 'modal', - alias: 'Umb.Modal.DocumentPropertyValueGranularUserPermissionFlow', - name: 'Document Property Value Granular User Permission Flow Modal', - element: () => import('./document-property-value-granular-permission-flow-modal.element.js'), + alias: 'Umb.Modal.DocumentPropertyValueUserPermissionFlow', + name: 'Document Property Value User Permission Flow Modal', + element: () => import('./document-property-value-permission-flow-modal.element.js'), }, ...propertyTypeModalManifests, ]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-permission-flow-modal/property-type-modal/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-permission-flow-modal/property-type-modal/constants.ts new file mode 100644 index 000000000000..80d43fb26c7d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-permission-flow-modal/property-type-modal/constants.ts @@ -0,0 +1,2 @@ +export const UMB_DOCUMENT_PROPERTY_VALUE_USER_PERMISSION_FLOW_PROPERTY_TYPE_MODAL_ALIAS = + 'Umb.Modal.DocumentPropertyValueUserPermissionFlow.PropertyType'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-permission-flow-modal/property-type-modal/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-permission-flow-modal/property-type-modal/index.ts new file mode 100644 index 000000000000..e711dbfbfc77 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-permission-flow-modal/property-type-modal/index.ts @@ -0,0 +1 @@ +export { UMB_DOCUMENT_PROPERTY_VALUE_USER_PERMISSION_FLOW_PROPERTY_TYPE_MODAL } from './property-type-modal.token.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-permission-flow-modal/property-type-modal/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-permission-flow-modal/property-type-modal/manifests.ts new file mode 100644 index 000000000000..53589f52552a --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-permission-flow-modal/property-type-modal/manifests.ts @@ -0,0 +1,11 @@ +import { UMB_DOCUMENT_PROPERTY_VALUE_USER_PERMISSION_FLOW_PROPERTY_TYPE_MODAL_ALIAS } from './constants.js'; +import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'modal', + alias: UMB_DOCUMENT_PROPERTY_VALUE_USER_PERMISSION_FLOW_PROPERTY_TYPE_MODAL_ALIAS, + name: 'Document Property Value User Permission Flow Property Type Modal', + element: () => import('./property-type-modal.element.js'), + }, +]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/property-type-modal/property-type-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-permission-flow-modal/property-type-modal/property-type-modal.element.ts similarity index 84% rename from src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/property-type-modal/property-type-modal.element.ts rename to src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-permission-flow-modal/property-type-modal/property-type-modal.element.ts index 788b0bca66ed..cccfe38107a7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-granular-permission-flow-modal/property-type-modal/property-type-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-permission-flow-modal/property-type-modal/property-type-modal.element.ts @@ -1,7 +1,7 @@ import { UMB_DOCUMENT_PROPERTY_VALUE_ENTITY_TYPE } from '../../../../entity.js'; import type { - UmbDocumentPropertyValueGranularUserPermissionFlowPropertyTypeModalData, - UmbDocumentPropertyValueGranularUserPermissionFlowPropertyTypeModalValue, + UmbDocumentPropertyValueUserPermissionFlowPropertyTypeModalData, + UmbDocumentPropertyValueUserPermissionFlowPropertyTypeModalValue, } from './property-type-modal.token.js'; import { html, customElement, state, repeat } from '@umbraco-cms/backoffice/external/lit'; import { UMB_MODAL_MANAGER_CONTEXT, UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; @@ -9,10 +9,10 @@ import type { UmbPropertyTypeModel } from '@umbraco-cms/backoffice/content-type' import { UmbDocumentTypeDetailRepository } from '@umbraco-cms/backoffice/document-type'; import { UMB_ENTITY_USER_PERMISSION_MODAL } from '@umbraco-cms/backoffice/user-permission'; -@customElement('umb-document-property-value-granular-user-permission-flow-property-type-modal') -export class UmbDocumentPropertyValueGranularUserPermissionFlowPropertyTypeModalElement extends UmbModalBaseElement< - UmbDocumentPropertyValueGranularUserPermissionFlowPropertyTypeModalData, - UmbDocumentPropertyValueGranularUserPermissionFlowPropertyTypeModalValue +@customElement('umb-document-property-value-user-permission-flow-property-type-modal') +export class UmbDocumentPropertyValueUserPermissionFlowPropertyTypeModalElement extends UmbModalBaseElement< + UmbDocumentPropertyValueUserPermissionFlowPropertyTypeModalData, + UmbDocumentPropertyValueUserPermissionFlowPropertyTypeModalValue > { @state() private _documentTypeProperties: Array = []; @@ -135,10 +135,10 @@ export class UmbDocumentPropertyValueGranularUserPermissionFlowPropertyTypeModal } } -export { UmbDocumentPropertyValueGranularUserPermissionFlowPropertyTypeModalElement as element }; +export { UmbDocumentPropertyValueUserPermissionFlowPropertyTypeModalElement as element }; declare global { interface HTMLElementTagNameMap { - 'umb-document-property-value-granular-user-permission-flow-property-type-modal': UmbDocumentPropertyValueGranularUserPermissionFlowPropertyTypeModalElement; + 'umb-document-property-value-user-permission-flow-property-type-modal': UmbDocumentPropertyValueUserPermissionFlowPropertyTypeModalElement; } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-permission-flow-modal/property-type-modal/property-type-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-permission-flow-modal/property-type-modal/property-type-modal.token.ts new file mode 100644 index 000000000000..a9701f8c369c --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-permission-flow-modal/property-type-modal/property-type-modal.token.ts @@ -0,0 +1,28 @@ +import { UMB_DOCUMENT_PROPERTY_VALUE_USER_PERMISSION_FLOW_PROPERTY_TYPE_MODAL_ALIAS } from './constants.js'; +import type { UmbPropertyTypeModel } from '@umbraco-cms/backoffice/content-type'; +import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; + +export interface UmbDocumentPropertyValueUserPermissionFlowPropertyTypeModalData { + documentType: { + unique: string; + }; + preset?: Partial; + pickableFilter?: (propertyType: UmbPropertyTypeModel) => boolean; +} + +export interface UmbDocumentPropertyValueUserPermissionFlowPropertyTypeModalValue { + propertyType: { + unique: string; + }; + verbs: Array; +} + +export const UMB_DOCUMENT_PROPERTY_VALUE_USER_PERMISSION_FLOW_PROPERTY_TYPE_MODAL = new UmbModalToken< + UmbDocumentPropertyValueUserPermissionFlowPropertyTypeModalData, + UmbDocumentPropertyValueUserPermissionFlowPropertyTypeModalValue +>(UMB_DOCUMENT_PROPERTY_VALUE_USER_PERMISSION_FLOW_PROPERTY_TYPE_MODAL_ALIAS, { + modal: { + type: 'sidebar', + size: 'small', + }, +}); diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/input-document-property-value-granular-user-permission/input-document-property-value-granular-user-permission.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/input-document-property-value-user-permission/input-document-property-value-user-permission.element.ts similarity index 89% rename from src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/input-document-property-value-granular-user-permission/input-document-property-value-granular-user-permission.element.ts rename to src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/input-document-property-value-user-permission/input-document-property-value-user-permission.element.ts index 3f251554cdf9..bcd6df17d69a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/input-document-property-value-granular-user-permission/input-document-property-value-granular-user-permission.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/input-document-property-value-user-permission/input-document-property-value-user-permission.element.ts @@ -1,5 +1,5 @@ import type { UmbDocumentPropertyValueUserPermissionModel as UmbDocumentPropertyValueUserPermissionModel } from '../types.js'; -import { UMB_DOCUMENT_PROPERTY_VALUE_GRANULAR_USER_PERMISSION_FLOW_MODAL } from '../document-property-value-granular-permission-flow-modal/index.js'; +import { UMB_DOCUMENT_PROPERTY_VALUE_USER_PERMISSION_FLOW_MODAL } from '../document-property-value-permission-flow-modal/index.js'; import { UMB_DOCUMENT_PROPERTY_VALUE_USER_PERMISSION_TYPE } from '../user-permission.js'; import { UMB_DOCUMENT_PROPERTY_VALUE_ENTITY_TYPE } from '../../../entity.js'; import { @@ -26,8 +26,8 @@ import { } from '@umbraco-cms/backoffice/document-type'; import { UmbChangeEvent } from '@umbraco-cms/backoffice/event'; -@customElement('umb-document-property-value-granular-user-permission') -export class UmbInputDocumentPropertyValueGranularUserPermissionElement extends UUIFormControlMixin(UmbLitElement, '') { +@customElement('umb-input-document-property-value-user-permission') +export class UmbInputDocumentPropertyValueUserPermissionElement extends UUIFormControlMixin(UmbLitElement, '') { _permissions: Array = []; public get permissions(): Array { return this._permissions; @@ -61,13 +61,13 @@ export class UmbInputDocumentPropertyValueGranularUserPermissionElement extends .filter((item) => item) as Array; } - async #addGranularPermission() { + async #addPermission() { const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT); if (!modalManager) { throw new Error('Could not open modal, no modal manager found'); } - const modal = modalManager.open(this, UMB_DOCUMENT_PROPERTY_VALUE_GRANULAR_USER_PERMISSION_FLOW_MODAL, { + const modal = modalManager.open(this, UMB_DOCUMENT_PROPERTY_VALUE_USER_PERMISSION_FLOW_MODAL, { data: { preset: { verbs: this.#getFallbackPermissionVerbsForEntityType(UMB_DOCUMENT_PROPERTY_VALUE_ENTITY_TYPE), @@ -96,7 +96,7 @@ export class UmbInputDocumentPropertyValueGranularUserPermissionElement extends } } - async #editGranularPermission(currentPermission: UmbDocumentPropertyValueUserPermissionModel) { + async #editPermission(currentPermission: UmbDocumentPropertyValueUserPermissionModel) { if (!currentPermission) { throw new Error('Could not open permissions modal, no item was provided'); } @@ -148,7 +148,7 @@ export class UmbInputDocumentPropertyValueGranularUserPermissionElement extends } } - #removeGranularPermission(permission: UmbDocumentPropertyValueUserPermissionModel) { + #removePermission(permission: UmbDocumentPropertyValueUserPermissionModel) { this.permissions = this._permissions.filter((v) => JSON.stringify(v) !== JSON.stringify(permission)); this.dispatchEvent(new UmbChangeEvent()); } @@ -210,7 +210,7 @@ export class UmbInputDocumentPropertyValueGranularUserPermissionElement extends return html``; } @@ -236,13 +236,13 @@ export class UmbInputDocumentPropertyValueGranularUserPermissionElement extends #renderEditButton(permission: UmbDocumentPropertyValueUserPermissionModel) { return html` this.#editGranularPermission(permission)} + @click=${() => this.#editPermission(permission)} label=${this.localize.term('general_edit')}>`; } #renderRemoveButton(permission: UmbDocumentPropertyValueUserPermissionModel) { return html` this.#removeGranularPermission(permission)} + @click=${() => this.#removePermission(permission)} label=${this.localize.term('general_remove')}>`; } @@ -255,10 +255,10 @@ export class UmbInputDocumentPropertyValueGranularUserPermissionElement extends ]; } -export { UmbInputDocumentPropertyValueGranularUserPermissionElement as element }; +export { UmbInputDocumentPropertyValueUserPermissionElement as element }; declare global { interface HTMLElementTagNameMap { - 'umb-document-property-value-granular-user-permission': UmbInputDocumentPropertyValueGranularUserPermissionElement; + 'umb-input-document-property-value-user-permission': UmbInputDocumentPropertyValueUserPermissionElement; } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/manifests.ts index 7a239146c949..33e89ab67dec 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/manifests.ts @@ -3,7 +3,7 @@ import { UMB_USER_PERMISSION_DOCUMENT_PROPERTY_VALUE_READ, UMB_USER_PERMISSION_DOCUMENT_PROPERTY_VALUE_WRITE, } from './constants.js'; -import { manifests as documentPropertyValueGranularPermissionFlowModalManifests } from './document-property-value-granular-permission-flow-modal/manifests.js'; +import { manifests as documentPropertyValueUserPermissionFlowModalManifests } from './document-property-value-permission-flow-modal/manifests.js'; import { manifests as conditionManifests } from './conditions/manifests.js'; import { manifests as dataManifests } from './data/manifests.js'; import { manifests as workspaceContextManifests } from './workspace-context/manifests.js'; @@ -41,7 +41,7 @@ export const manifests: Array = weight: 950, element: () => import( - './input-document-property-value-granular-user-permission/input-document-property-value-granular-user-permission.element.js' + './input-document-property-value-user-permission/input-document-property-value-user-permission.element.js' ), meta: { schemaType: 'DocumentTypePropertyPermissionPresentationModel', @@ -51,6 +51,6 @@ export const manifests: Array = }, ...conditionManifests, ...dataManifests, - ...documentPropertyValueGranularPermissionFlowModalManifests, + ...documentPropertyValueUserPermissionFlowModalManifests, ...workspaceContextManifests, ]; From 0ecc361a213af3ce2f6c7dd2698fa031bb7e6c33 Mon Sep 17 00:00:00 2001 From: kjac Date: Thu, 20 Mar 2025 13:18:37 +0100 Subject: [PATCH 080/106] Rename models (last time, promise!) --- .../UserGroupsBuilderExtensions.cs | 4 +- ... DocumentPropertyValuePermissionMapper.cs} | 14 +-- src/Umbraco.Cms.Api.Management/OpenApi.json | 92 +++++++++---------- ...opertyValuePermissionPresentationModel.cs} | 2 +- ...ocumentPropertyValueGranularPermission.cs} | 6 +- 5 files changed, 59 insertions(+), 59 deletions(-) rename src/Umbraco.Cms.Api.Management/Mapping/Permissions/{DocumentTypePropertyPermissionMapper.cs => DocumentPropertyValuePermissionMapper.cs} (79%) rename src/Umbraco.Cms.Api.Management/ViewModels/UserGroup/Permissions/{DocumentTypePropertyPermissionPresentationModel.cs => DocumentPropertyValuePermissionPresentationModel.cs} (73%) rename src/Umbraco.Core/Models/Membership/Permissions/{DocumentTypePropertyGranularPermission.cs => DocumentPropertyValueGranularPermission.cs} (70%) diff --git a/src/Umbraco.Cms.Api.Management/DependencyInjection/UserGroupsBuilderExtensions.cs b/src/Umbraco.Cms.Api.Management/DependencyInjection/UserGroupsBuilderExtensions.cs index 33bce7fa88e8..525215157392 100644 --- a/src/Umbraco.Cms.Api.Management/DependencyInjection/UserGroupsBuilderExtensions.cs +++ b/src/Umbraco.Cms.Api.Management/DependencyInjection/UserGroupsBuilderExtensions.cs @@ -16,8 +16,8 @@ internal static IUmbracoBuilder AddUserGroups(this IUmbracoBuilder builder) builder.Services.AddSingleton(); builder.Services.AddSingleton(); - builder.Services.AddSingleton(); - builder.Services.AddSingleton(); + builder.Services.AddSingleton(); + builder.Services.AddSingleton(); return builder; } diff --git a/src/Umbraco.Cms.Api.Management/Mapping/Permissions/DocumentTypePropertyPermissionMapper.cs b/src/Umbraco.Cms.Api.Management/Mapping/Permissions/DocumentPropertyValuePermissionMapper.cs similarity index 79% rename from src/Umbraco.Cms.Api.Management/Mapping/Permissions/DocumentTypePropertyPermissionMapper.cs rename to src/Umbraco.Cms.Api.Management/Mapping/Permissions/DocumentPropertyValuePermissionMapper.cs index 4e7dd5333a96..ed0964abdaf2 100644 --- a/src/Umbraco.Cms.Api.Management/Mapping/Permissions/DocumentTypePropertyPermissionMapper.cs +++ b/src/Umbraco.Cms.Api.Management/Mapping/Permissions/DocumentPropertyValuePermissionMapper.cs @@ -7,18 +7,18 @@ namespace Umbraco.Cms.Api.Management.Mapping.Permissions; -public class DocumentTypePropertyPermissionMapper : IPermissionPresentationMapper, IPermissionMapper +public class DocumentPropertyValuePermissionMapper : IPermissionPresentationMapper, IPermissionMapper { - public string Context => DocumentTypePropertyGranularPermission.ContextType; + public string Context => DocumentPropertyValueGranularPermission.ContextType; public IGranularPermission MapFromDto(UserGroup2GranularPermissionDto dto) => - new DocumentTypePropertyGranularPermission() + new DocumentPropertyValueGranularPermission() { Key = dto.UniqueId!.Value, Permission = dto.Permission, }; - public Type PresentationModelToHandle => typeof(DocumentTypePropertyPermissionPresentationModel); + public Type PresentationModelToHandle => typeof(DocumentPropertyValuePermissionPresentationModel); public IEnumerable MapManyAsync(IEnumerable granularPermissions) { @@ -37,7 +37,7 @@ public IEnumerable MapManyAsync(IEnumerable x.PropertyTypeId)) { - yield return new DocumentTypePropertyPermissionPresentationModel + yield return new DocumentPropertyValuePermissionPresentationModel { DocumentType = new ReferenceByIdModel(documentTypeGroup.Key), PropertyType = new ReferenceByIdModel(propertyTypeGroup.Key), @@ -52,14 +52,14 @@ public IEnumerable MapManyAsync(IEnumerable MapToGranularPermissions(IPermissionPresentationModel permissionViewModel) { - if (permissionViewModel is not DocumentTypePropertyPermissionPresentationModel documentTypePermissionPresentationModel) + if (permissionViewModel is not DocumentPropertyValuePermissionPresentationModel documentTypePermissionPresentationModel) { yield break; } foreach (var verb in documentTypePermissionPresentationModel.Verbs.Distinct().DefaultIfEmpty(string.Empty)) { - yield return new DocumentTypePropertyGranularPermission + yield return new DocumentPropertyValueGranularPermission { Key = documentTypePermissionPresentationModel.DocumentType.Id, Permission = $"{documentTypePermissionPresentationModel.PropertyType.Id}|{verb}" diff --git a/src/Umbraco.Cms.Api.Management/OpenApi.json b/src/Umbraco.Cms.Api.Management/OpenApi.json index 2c6589e9013e..142c6e09b915 100644 --- a/src/Umbraco.Cms.Api.Management/OpenApi.json +++ b/src/Umbraco.Cms.Api.Management/OpenApi.json @@ -35921,7 +35921,7 @@ "$ref": "#/components/schemas/DocumentPermissionPresentationModel" }, { - "$ref": "#/components/schemas/DocumentTypePropertyPermissionPresentationModel" + "$ref": "#/components/schemas/DocumentPropertyValuePermissionPresentationModel" }, { "$ref": "#/components/schemas/UnknownTypePermissionPresentationModel" @@ -36212,7 +36212,7 @@ "$ref": "#/components/schemas/DocumentPermissionPresentationModel" }, { - "$ref": "#/components/schemas/DocumentTypePropertyPermissionPresentationModel" + "$ref": "#/components/schemas/DocumentPropertyValuePermissionPresentationModel" }, { "$ref": "#/components/schemas/UnknownTypePermissionPresentationModel" @@ -37079,6 +37079,48 @@ } } }, + "DocumentPropertyValuePermissionPresentationModel": { + "required": [ + "$type", + "documentType", + "propertyType", + "verbs" + ], + "type": "object", + "properties": { + "$type": { + "type": "string" + }, + "documentType": { + "oneOf": [ + { + "$ref": "#/components/schemas/ReferenceByIdModel" + } + ] + }, + "propertyType": { + "oneOf": [ + { + "$ref": "#/components/schemas/ReferenceByIdModel" + } + ] + }, + "verbs": { + "uniqueItems": true, + "type": "array", + "items": { + "type": "string" + } + } + }, + "additionalProperties": false, + "discriminator": { + "propertyName": "$type", + "mapping": { + "DocumentPropertyValuePermissionPresentationModel": "#/components/schemas/DocumentPropertyValuePermissionPresentationModel" + } + } + }, "DocumentRecycleBinItemResponseModel": { "required": [ "createDate", @@ -37484,48 +37526,6 @@ }, "additionalProperties": false }, - "DocumentTypePropertyPermissionPresentationModel": { - "required": [ - "$type", - "documentType", - "propertyType", - "verbs" - ], - "type": "object", - "properties": { - "$type": { - "type": "string" - }, - "documentType": { - "oneOf": [ - { - "$ref": "#/components/schemas/ReferenceByIdModel" - } - ] - }, - "propertyType": { - "oneOf": [ - { - "$ref": "#/components/schemas/ReferenceByIdModel" - } - ] - }, - "verbs": { - "uniqueItems": true, - "type": "array", - "items": { - "type": "string" - } - } - }, - "additionalProperties": false, - "discriminator": { - "propertyName": "$type", - "mapping": { - "DocumentTypePropertyPermissionPresentationModel": "#/components/schemas/DocumentTypePropertyPermissionPresentationModel" - } - } - }, "DocumentTypePropertyTypeContainerResponseModel": { "required": [ "id", @@ -45481,7 +45481,7 @@ "$ref": "#/components/schemas/DocumentPermissionPresentationModel" }, { - "$ref": "#/components/schemas/DocumentTypePropertyPermissionPresentationModel" + "$ref": "#/components/schemas/DocumentPropertyValuePermissionPresentationModel" }, { "$ref": "#/components/schemas/UnknownTypePermissionPresentationModel" @@ -45907,7 +45907,7 @@ "$ref": "#/components/schemas/DocumentPermissionPresentationModel" }, { - "$ref": "#/components/schemas/DocumentTypePropertyPermissionPresentationModel" + "$ref": "#/components/schemas/DocumentPropertyValuePermissionPresentationModel" }, { "$ref": "#/components/schemas/UnknownTypePermissionPresentationModel" diff --git a/src/Umbraco.Cms.Api.Management/ViewModels/UserGroup/Permissions/DocumentTypePropertyPermissionPresentationModel.cs b/src/Umbraco.Cms.Api.Management/ViewModels/UserGroup/Permissions/DocumentPropertyValuePermissionPresentationModel.cs similarity index 73% rename from src/Umbraco.Cms.Api.Management/ViewModels/UserGroup/Permissions/DocumentTypePropertyPermissionPresentationModel.cs rename to src/Umbraco.Cms.Api.Management/ViewModels/UserGroup/Permissions/DocumentPropertyValuePermissionPresentationModel.cs index 41a527679f19..dc12a56bd70f 100644 --- a/src/Umbraco.Cms.Api.Management/ViewModels/UserGroup/Permissions/DocumentTypePropertyPermissionPresentationModel.cs +++ b/src/Umbraco.Cms.Api.Management/ViewModels/UserGroup/Permissions/DocumentPropertyValuePermissionPresentationModel.cs @@ -1,6 +1,6 @@ namespace Umbraco.Cms.Api.Management.ViewModels.UserGroup.Permissions; -public class DocumentTypePropertyPermissionPresentationModel : IPermissionPresentationModel +public class DocumentPropertyValuePermissionPresentationModel : IPermissionPresentationModel { public required ReferenceByIdModel DocumentType { get; set; } diff --git a/src/Umbraco.Core/Models/Membership/Permissions/DocumentTypePropertyGranularPermission.cs b/src/Umbraco.Core/Models/Membership/Permissions/DocumentPropertyValueGranularPermission.cs similarity index 70% rename from src/Umbraco.Core/Models/Membership/Permissions/DocumentTypePropertyGranularPermission.cs rename to src/Umbraco.Core/Models/Membership/Permissions/DocumentPropertyValueGranularPermission.cs index c0f61c1f63bb..0f386ea6d11e 100644 --- a/src/Umbraco.Core/Models/Membership/Permissions/DocumentTypePropertyGranularPermission.cs +++ b/src/Umbraco.Core/Models/Membership/Permissions/DocumentPropertyValueGranularPermission.cs @@ -1,6 +1,6 @@ namespace Umbraco.Cms.Core.Models.Membership.Permissions; -public class DocumentTypePropertyGranularPermission : INodeGranularPermission +public class DocumentPropertyValueGranularPermission : INodeGranularPermission { public const string ContextType = "DocumentTypeProperty"; @@ -10,7 +10,7 @@ public class DocumentTypePropertyGranularPermission : INodeGranularPermission public required string Permission { get; set; } - protected bool Equals(DocumentTypePropertyGranularPermission other) => Key.Equals(other.Key) && Permission == other.Permission; + protected bool Equals(DocumentPropertyValueGranularPermission other) => Key.Equals(other.Key) && Permission == other.Permission; public override bool Equals(object? obj) { @@ -29,7 +29,7 @@ public override bool Equals(object? obj) return false; } - return Equals((DocumentTypePropertyGranularPermission)obj); + return Equals((DocumentPropertyValueGranularPermission)obj); } public override int GetHashCode() => HashCode.Combine(Key, Permission); From 94d36a1381e20131814b7b6bb2d900ab9086e076 Mon Sep 17 00:00:00 2001 From: kjac Date: Thu, 20 Mar 2025 13:34:21 +0100 Subject: [PATCH 081/106] Add migration for default document property value permissions --- .../Actions/ActionDocumentPropertyRead.cs | 29 ++++++++++++ .../Actions/ActionDocumentPropertyWrite.cs | 29 ++++++++++++ .../Migrations/Upgrade/UmbracoPlan.cs | 1 + .../AddDocumentPropertyPermissions.cs | 47 +++++++++++++++++++ 4 files changed, 106 insertions(+) create mode 100644 src/Umbraco.Core/Actions/ActionDocumentPropertyRead.cs create mode 100644 src/Umbraco.Core/Actions/ActionDocumentPropertyWrite.cs create mode 100644 src/Umbraco.Infrastructure/Migrations/Upgrade/V_15_4_0/AddDocumentPropertyPermissions.cs diff --git a/src/Umbraco.Core/Actions/ActionDocumentPropertyRead.cs b/src/Umbraco.Core/Actions/ActionDocumentPropertyRead.cs new file mode 100644 index 000000000000..6a367d996b06 --- /dev/null +++ b/src/Umbraco.Core/Actions/ActionDocumentPropertyRead.cs @@ -0,0 +1,29 @@ +namespace Umbraco.Cms.Core.Actions; + +public class ActionDocumentPropertyRead : IAction +{ + /// + public const string ActionLetter = "Umb.Document.Property.Read"; + + /// + public const string ActionAlias = "documentpropertyread"; + + /// + public string Letter => ActionLetter; + + /// + public string Alias => ActionAlias; + + /// + public bool ShowInNotifier => false; + + /// + public bool CanBePermissionAssigned => true; + + /// + public string Icon => string.Empty; + + /// + public string Category => Constants.Conventions.PermissionCategories.OtherCategory; +} + diff --git a/src/Umbraco.Core/Actions/ActionDocumentPropertyWrite.cs b/src/Umbraco.Core/Actions/ActionDocumentPropertyWrite.cs new file mode 100644 index 000000000000..774fdd60324f --- /dev/null +++ b/src/Umbraco.Core/Actions/ActionDocumentPropertyWrite.cs @@ -0,0 +1,29 @@ +namespace Umbraco.Cms.Core.Actions; + +public class ActionDocumentPropertyWrite : IAction +{ + /// + public const string ActionLetter = "Umb.Document.Property.Write"; + + /// + public const string ActionAlias = "documentpropertywrite"; + + /// + public string Letter => ActionLetter; + + /// + public string Alias => ActionAlias; + + /// + public bool ShowInNotifier => false; + + /// + public bool CanBePermissionAssigned => true; + + /// + public string Icon => string.Empty; + + /// + public string Category => Constants.Conventions.PermissionCategories.OtherCategory; +} + diff --git a/src/Umbraco.Infrastructure/Migrations/Upgrade/UmbracoPlan.cs b/src/Umbraco.Infrastructure/Migrations/Upgrade/UmbracoPlan.cs index fe14f785d8b9..2e8ddb1a9f31 100644 --- a/src/Umbraco.Infrastructure/Migrations/Upgrade/UmbracoPlan.cs +++ b/src/Umbraco.Infrastructure/Migrations/Upgrade/UmbracoPlan.cs @@ -114,5 +114,6 @@ protected virtual void DefinePlan() // To 15.4.0 To("{A9E72794-4036-4563-B543-1717C73B8879}"); + To("{D1568C33-A697-455F-8D16-48060CB954A1}"); } } diff --git a/src/Umbraco.Infrastructure/Migrations/Upgrade/V_15_4_0/AddDocumentPropertyPermissions.cs b/src/Umbraco.Infrastructure/Migrations/Upgrade/V_15_4_0/AddDocumentPropertyPermissions.cs new file mode 100644 index 000000000000..916788272338 --- /dev/null +++ b/src/Umbraco.Infrastructure/Migrations/Upgrade/V_15_4_0/AddDocumentPropertyPermissions.cs @@ -0,0 +1,47 @@ +using Umbraco.Cms.Core.Actions; +using Umbraco.Cms.Infrastructure.Persistence.Dtos; + +namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_15_4_0; + +[Obsolete("Remove in Umbraco 18.")] +internal class AddDocumentPropertyPermissions : MigrationBase +{ + public AddDocumentPropertyPermissions(IMigrationContext context) + : base(context) + { + } + + protected override void Migrate() + { + List? userGroups = Database.Fetch(); + + foreach (UserGroupDto userGroupDto in userGroups ?? []) + { + List? currentPermissions = Database.Fetch( + "WHERE userGroupKey = @UserGroupKey", + new { UserGroupKey = userGroupDto.Key }); + + if (currentPermissions is null || currentPermissions.Count is 0) + { + continue; + } + + if (currentPermissions.Any(p => p.Permission == ActionDocumentPropertyRead.ActionLetter)) + { + return; + } + + Database.InsertBulk( + [ + new UserGroup2PermissionDto + { + UserGroupKey = userGroupDto.Key, Permission = ActionDocumentPropertyRead.ActionLetter + }, + new UserGroup2PermissionDto + { + UserGroupKey = userGroupDto.Key, Permission = ActionDocumentPropertyWrite.ActionLetter + } + ]); + } + } +} From 3ca7ad00cf095bea9af5b9f9ed5939b7e5f70e56 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 20 Mar 2025 20:08:42 +0100 Subject: [PATCH 082/106] generate new server models --- .../src/external/backend-api/src/sdk.gen.ts | 6 +++++ .../src/external/backend-api/src/types.gen.ts | 25 +++++++++++-------- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/external/backend-api/src/sdk.gen.ts b/src/Umbraco.Web.UI.Client/src/external/backend-api/src/sdk.gen.ts index 9b36b8ffd2a2..2d35f0942470 100644 --- a/src/Umbraco.Web.UI.Client/src/external/backend-api/src/sdk.gen.ts +++ b/src/Umbraco.Web.UI.Client/src/external/backend-api/src/sdk.gen.ts @@ -1491,6 +1491,7 @@ export class DocumentService { /** * @param data The data for the request. * @param data.query + * @param data.trashed * @param data.skip * @param data.take * @param data.parentId @@ -1504,6 +1505,7 @@ export class DocumentService { url: '/umbraco/management/api/v1/item/document/search', query: { query: data.query, + trashed: data.trashed, skip: data.skip, take: data.take, parentId: data.parentId, @@ -2504,6 +2506,7 @@ export class DocumentTypeService { /** * @param data The data for the request. * @param data.query + * @param data.isElement * @param data.skip * @param data.take * @returns unknown OK @@ -2515,6 +2518,7 @@ export class DocumentTypeService { url: '/umbraco/management/api/v1/item/document-type/search', query: { query: data.query, + isElement: data.isElement, skip: data.skip, take: data.take }, @@ -3498,6 +3502,7 @@ export class MediaService { /** * @param data The data for the request. * @param data.query + * @param data.trashed * @param data.skip * @param data.take * @param data.parentId @@ -3511,6 +3516,7 @@ export class MediaService { url: '/umbraco/management/api/v1/item/media/search', query: { query: data.query, + trashed: data.trashed, skip: data.skip, take: data.take, parentId: data.parentId, diff --git a/src/Umbraco.Web.UI.Client/src/external/backend-api/src/types.gen.ts b/src/Umbraco.Web.UI.Client/src/external/backend-api/src/types.gen.ts index 107f245962bf..3813be9a8bbc 100644 --- a/src/Umbraco.Web.UI.Client/src/external/backend-api/src/types.gen.ts +++ b/src/Umbraco.Web.UI.Client/src/external/backend-api/src/types.gen.ts @@ -408,7 +408,7 @@ export type CreateUserGroupRequestModel = { mediaStartNode?: ((ReferenceByIdModel) | null); mediaRootAccess: boolean; fallbackPermissions: Array<(string)>; - permissions: Array<(DocumentPermissionPresentationModel | DocumentTypePropertyPermissionPresentationModel | UnknownTypePermissionPresentationModel)>; + permissions: Array<(DocumentPermissionPresentationModel | DocumentPropertyValuePermissionPresentationModel | UnknownTypePermissionPresentationModel)>; id?: (string) | null; }; @@ -460,7 +460,7 @@ export type CurrentUserResponseModel = { hasAccessToAllLanguages: boolean; hasAccessToSensitiveData: boolean; fallbackPermissions: Array<(string)>; - permissions: Array<(DocumentPermissionPresentationModel | DocumentTypePropertyPermissionPresentationModel | UnknownTypePermissionPresentationModel)>; + permissions: Array<(DocumentPermissionPresentationModel | DocumentPropertyValuePermissionPresentationModel | UnknownTypePermissionPresentationModel)>; allowedSections: Array<(string)>; isAdmin: boolean; }; @@ -679,6 +679,13 @@ export type DocumentPermissionPresentationModel = { verbs: Array<(string)>; }; +export type DocumentPropertyValuePermissionPresentationModel = { + $type: string; + documentType: (ReferenceByIdModel); + propertyType: (ReferenceByIdModel); + verbs: Array<(string)>; +}; + export type DocumentRecycleBinItemResponseModel = { id: string; createDate: string; @@ -768,13 +775,6 @@ export type DocumentTypeItemResponseModel = { description?: (string) | null; }; -export type DocumentTypePropertyPermissionPresentationModel = { - $type: string; - documentType: (ReferenceByIdModel); - propertyType: (ReferenceByIdModel); - verbs: Array<(string)>; -}; - export type DocumentTypePropertyTypeContainerResponseModel = { id: string; parent?: ((ReferenceByIdModel) | null); @@ -2666,7 +2666,7 @@ export type UpdateUserGroupRequestModel = { mediaStartNode?: ((ReferenceByIdModel) | null); mediaRootAccess: boolean; fallbackPermissions: Array<(string)>; - permissions: Array<(DocumentPermissionPresentationModel | DocumentTypePropertyPermissionPresentationModel | UnknownTypePermissionPresentationModel)>; + permissions: Array<(DocumentPermissionPresentationModel | DocumentPropertyValuePermissionPresentationModel | UnknownTypePermissionPresentationModel)>; }; export type UpdateUserGroupsOnUserRequestModel = { @@ -2766,7 +2766,7 @@ export type UserGroupResponseModel = { mediaStartNode?: ((ReferenceByIdModel) | null); mediaRootAccess: boolean; fallbackPermissions: Array<(string)>; - permissions: Array<(DocumentPermissionPresentationModel | DocumentTypePropertyPermissionPresentationModel | UnknownTypePermissionPresentationModel)>; + permissions: Array<(DocumentPermissionPresentationModel | DocumentPropertyValuePermissionPresentationModel | UnknownTypePermissionPresentationModel)>; id: string; isDeletable: boolean; aliasCanBeChanged: boolean; @@ -3364,6 +3364,7 @@ export type GetItemDocumentSearchData = { query?: string; skip?: number; take?: number; + trashed?: boolean; }; export type GetItemDocumentSearchResponse = ((PagedModelDocumentItemResponseModel)); @@ -3647,6 +3648,7 @@ export type GetItemDocumentTypeData = { export type GetItemDocumentTypeResponse = (Array<(DocumentTypeItemResponseModel)>); export type GetItemDocumentTypeSearchData = { + isElement?: boolean; query?: string; skip?: number; take?: number; @@ -3934,6 +3936,7 @@ export type GetItemMediaSearchData = { query?: string; skip?: number; take?: number; + trashed?: boolean; }; export type GetItemMediaSearchResponse = ((PagedModelMediaItemResponseModel)); From fe834aa96822fd89fcf9f45ed78b6a3a43e71725 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 20 Mar 2025 20:13:33 +0100 Subject: [PATCH 083/106] update after model changes --- .../data/from-server.management-api.mapping.ts | 6 +++--- .../document-property-value/data/manifests.ts | 6 +++--- .../data/to-server.management-api.mapping.ts | 8 ++++---- ...put-document-property-value-user-permission.element.ts | 2 +- .../user-permissions/document-property-value/manifests.ts | 2 +- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/data/from-server.management-api.mapping.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/data/from-server.management-api.mapping.ts index bbb10f425cef..903cd8215f1f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/data/from-server.management-api.mapping.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/data/from-server.management-api.mapping.ts @@ -2,18 +2,18 @@ import type { UmbDocumentPropertyValueUserPermissionModel } from '../types.js'; import { UMB_DOCUMENT_PROPERTY_VALUE_USER_PERMISSION_TYPE } from '../user-permission.js'; import type { UmbDataSourceDataMapping } from '@umbraco-cms/backoffice/repository'; import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; -import type { DocumentTypePropertyPermissionPresentationModel } from '@umbraco-cms/backoffice/external/backend-api'; +import type { DocumentPropertyValuePermissionPresentationModel } from '@umbraco-cms/backoffice/external/backend-api'; export class UmbDocumentPropertyValueUserPermissionFromManagementApiDataMapping extends UmbControllerBase implements UmbDataSourceDataMapping< - DocumentTypePropertyPermissionPresentationModel, + DocumentPropertyValuePermissionPresentationModel, UmbDocumentPropertyValueUserPermissionModel > { async map( - data: DocumentTypePropertyPermissionPresentationModel, + data: DocumentPropertyValuePermissionPresentationModel, ): Promise { return { $type: data.$type, diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/data/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/data/manifests.ts index bf6f17f878f6..afde9143747a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/data/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/data/manifests.ts @@ -5,7 +5,7 @@ import { UMB_MANAGEMENT_API_DATA_SOURCE_ALIAS } from '@umbraco-cms/backoffice/re export const manifests: Array = [ { type: 'dataSourceDataMapping', - alias: 'Umb.DataSourceDataMapping.ManagementApi.To.DocumentTypePropertyPermissionPresentationModel', + alias: 'Umb.DataSourceDataMapping.ManagementApi.To.DocumentPropertyValuePermissionPresentationModel', name: 'Document Property Value Permission To Management Api Data Mapping', api: () => import('./to-server.management-api.mapping.js'), forDataSource: UMB_MANAGEMENT_API_DATA_SOURCE_ALIAS, @@ -13,10 +13,10 @@ export const manifests: Array = }, { type: 'dataSourceDataMapping', - alias: 'Umb.DataSourceDataMapping.ManagementApi.From.DocumentTypePropertyPermissionPresentationModel', + alias: 'Umb.DataSourceDataMapping.ManagementApi.From.DocumentPropertyValuePermissionPresentationModel', name: 'Document Property Value Permission From Management Api Data Mapping', api: () => import('./from-server.management-api.mapping.js'), forDataSource: UMB_MANAGEMENT_API_DATA_SOURCE_ALIAS, - forDataModel: 'DocumentTypePropertyPermissionPresentationModel', + forDataModel: 'DocumentPropertyValuePermissionPresentationModel', }, ]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/data/to-server.management-api.mapping.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/data/to-server.management-api.mapping.ts index 4390977d18f0..8ca9e5c58e2f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/data/to-server.management-api.mapping.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/data/to-server.management-api.mapping.ts @@ -1,21 +1,21 @@ import type { UmbDocumentPropertyValueUserPermissionModel } from '../types.js'; import type { UmbDataSourceDataMapping } from '@umbraco-cms/backoffice/repository'; import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; -import type { DocumentTypePropertyPermissionPresentationModel } from '@umbraco-cms/backoffice/external/backend-api'; +import type { DocumentPropertyValuePermissionPresentationModel } from '@umbraco-cms/backoffice/external/backend-api'; export class UmbDocumentPropertyValueUserPermissionToManagementApiDataMapping extends UmbControllerBase implements UmbDataSourceDataMapping< UmbDocumentPropertyValueUserPermissionModel, - DocumentTypePropertyPermissionPresentationModel + DocumentPropertyValuePermissionPresentationModel > { async map( data: UmbDocumentPropertyValueUserPermissionModel, - ): Promise { + ): Promise { return { - $type: 'DocumentTypePropertyPermissionPresentationModel', + $type: 'DocumentPropertyValuePermissionPresentationModel', documentType: { id: data.documentType.unique, }, diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/input-document-property-value-user-permission/input-document-property-value-user-permission.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/input-document-property-value-user-permission/input-document-property-value-user-permission.element.ts index bcd6df17d69a..f2548a45b7b8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/input-document-property-value-user-permission/input-document-property-value-user-permission.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/input-document-property-value-user-permission/input-document-property-value-user-permission.element.ts @@ -82,7 +82,7 @@ export class UmbInputDocumentPropertyValueUserPermissionElement extends UUIFormC if (!value) throw new Error('No result from modal'); const permissionItem: UmbDocumentPropertyValueUserPermissionModel = { - $type: 'DocumentTypePropertyPermissionPresentationModel', + $type: 'DocumentPropertyValuePermissionPresentationModel', userPermissionType: UMB_DOCUMENT_PROPERTY_VALUE_USER_PERMISSION_TYPE, documentType: value.documentType, propertyType: value.propertyType, diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/manifests.ts index 33e89ab67dec..a12076297d1c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/manifests.ts @@ -44,7 +44,7 @@ export const manifests: Array = './input-document-property-value-user-permission/input-document-property-value-user-permission.element.js' ), meta: { - schemaType: 'DocumentTypePropertyPermissionPresentationModel', + schemaType: 'DocumentPropertyValuePermissionPresentationModel', label: 'Document Property Values', description: 'Assign Permissions to Document property values', }, From ead5df17367ad490a1c3a7632a062f9d0ba4405e Mon Sep 17 00:00:00 2001 From: kjac Date: Fri, 21 Mar 2025 07:12:23 +0100 Subject: [PATCH 084/106] Correct the default permission identifiers --- src/Umbraco.Core/Actions/ActionDocumentPropertyRead.cs | 2 +- src/Umbraco.Core/Actions/ActionDocumentPropertyWrite.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Core/Actions/ActionDocumentPropertyRead.cs b/src/Umbraco.Core/Actions/ActionDocumentPropertyRead.cs index 6a367d996b06..bf5515b97a97 100644 --- a/src/Umbraco.Core/Actions/ActionDocumentPropertyRead.cs +++ b/src/Umbraco.Core/Actions/ActionDocumentPropertyRead.cs @@ -3,7 +3,7 @@ public class ActionDocumentPropertyRead : IAction { /// - public const string ActionLetter = "Umb.Document.Property.Read"; + public const string ActionLetter = "Umb.Document.PropertyValue.Read"; /// public const string ActionAlias = "documentpropertyread"; diff --git a/src/Umbraco.Core/Actions/ActionDocumentPropertyWrite.cs b/src/Umbraco.Core/Actions/ActionDocumentPropertyWrite.cs index 774fdd60324f..dec8ad0e3294 100644 --- a/src/Umbraco.Core/Actions/ActionDocumentPropertyWrite.cs +++ b/src/Umbraco.Core/Actions/ActionDocumentPropertyWrite.cs @@ -3,7 +3,7 @@ public class ActionDocumentPropertyWrite : IAction { /// - public const string ActionLetter = "Umb.Document.Property.Write"; + public const string ActionLetter = "Umb.Document.PropertyValue.Write"; /// public const string ActionAlias = "documentpropertywrite"; From 57f71fa4624479f7f132aef444d0d9e235f1c1f5 Mon Sep 17 00:00:00 2001 From: kjac Date: Fri, 21 Mar 2025 08:13:35 +0100 Subject: [PATCH 085/106] Add default permissions to newly created DBs --- .../Migrations/Install/DatabaseDataCreator.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Infrastructure/Migrations/Install/DatabaseDataCreator.cs b/src/Umbraco.Infrastructure/Migrations/Install/DatabaseDataCreator.cs index 379a3a91da90..f6464b6168b5 100644 --- a/src/Umbraco.Infrastructure/Migrations/Install/DatabaseDataCreator.cs +++ b/src/Umbraco.Infrastructure/Migrations/Install/DatabaseDataCreator.cs @@ -195,10 +195,10 @@ private void CreateUserGroup2PermissionData() { var userGroupKeyToPermissions = new Dictionary>() { - [Constants.Security.AdminGroupKey] = [ActionNew.ActionLetter, ActionUpdate.ActionLetter, ActionDelete.ActionLetter, ActionMove.ActionLetter, ActionCopy.ActionLetter, ActionSort.ActionLetter, ActionRollback.ActionLetter, ActionProtect.ActionLetter, ActionAssignDomain.ActionLetter, ActionPublish.ActionLetter, ActionRights.ActionLetter, ActionUnpublish.ActionLetter, ActionBrowse.ActionLetter, ActionCreateBlueprintFromContent.ActionLetter, ActionNotify.ActionLetter, ":", "5", "7", "T"], - [Constants.Security.EditorGroupKey] = [ActionNew.ActionLetter, ActionUpdate.ActionLetter, ActionDelete.ActionLetter, ActionMove.ActionLetter, ActionCopy.ActionLetter, ActionSort.ActionLetter, ActionRollback.ActionLetter, ActionProtect.ActionLetter, ActionPublish.ActionLetter, ActionUnpublish.ActionLetter, ActionBrowse.ActionLetter, ActionCreateBlueprintFromContent.ActionLetter, ActionNotify.ActionLetter, ":", "5", "T"], - [Constants.Security.WriterGroupKey] = [ActionNew.ActionLetter, ActionUpdate.ActionLetter, ActionBrowse.ActionLetter, ActionNotify.ActionLetter, ":" ], - [Constants.Security.TranslatorGroupKey] = [ActionUpdate.ActionLetter, ActionBrowse.ActionLetter], + [Constants.Security.AdminGroupKey] = [ActionNew.ActionLetter, ActionUpdate.ActionLetter, ActionDelete.ActionLetter, ActionMove.ActionLetter, ActionCopy.ActionLetter, ActionSort.ActionLetter, ActionRollback.ActionLetter, ActionProtect.ActionLetter, ActionAssignDomain.ActionLetter, ActionPublish.ActionLetter, ActionRights.ActionLetter, ActionUnpublish.ActionLetter, ActionBrowse.ActionLetter, ActionCreateBlueprintFromContent.ActionLetter, ActionNotify.ActionLetter, ":", "5", "7", "T", ActionDocumentPropertyRead.ActionLetter, ActionDocumentPropertyWrite.ActionLetter], + [Constants.Security.EditorGroupKey] = [ActionNew.ActionLetter, ActionUpdate.ActionLetter, ActionDelete.ActionLetter, ActionMove.ActionLetter, ActionCopy.ActionLetter, ActionSort.ActionLetter, ActionRollback.ActionLetter, ActionProtect.ActionLetter, ActionPublish.ActionLetter, ActionUnpublish.ActionLetter, ActionBrowse.ActionLetter, ActionCreateBlueprintFromContent.ActionLetter, ActionNotify.ActionLetter, ":", "5", "T", ActionDocumentPropertyRead.ActionLetter, ActionDocumentPropertyWrite.ActionLetter], + [Constants.Security.WriterGroupKey] = [ActionNew.ActionLetter, ActionUpdate.ActionLetter, ActionBrowse.ActionLetter, ActionNotify.ActionLetter, ":" , ActionDocumentPropertyRead.ActionLetter, ActionDocumentPropertyWrite.ActionLetter], + [Constants.Security.TranslatorGroupKey] = [ActionUpdate.ActionLetter, ActionBrowse.ActionLetter, ActionDocumentPropertyRead.ActionLetter, ActionDocumentPropertyWrite.ActionLetter], }; var i = 1; From 6e943f796addd15d553af9c3ac8fb18dd403cd2c Mon Sep 17 00:00:00 2001 From: kjac Date: Fri, 21 Mar 2025 14:18:43 +0100 Subject: [PATCH 086/106] Add validation and clean-up --- .../UserGroup/UserGroupControllerBase.cs | 8 +- .../UserGroupOperationStatus.cs | 1 + src/Umbraco.Core/Services/UserGroupService.cs | 22 +- .../Implement/ContentTypeRepository.cs | 3 + .../Implement/UserGroupRepository.cs | 1 - .../UserGroupPresentationFactoryTests.cs | 206 +++++++++++++++++- 6 files changed, 227 insertions(+), 14 deletions(-) diff --git a/src/Umbraco.Cms.Api.Management/Controllers/UserGroup/UserGroupControllerBase.cs b/src/Umbraco.Cms.Api.Management/Controllers/UserGroup/UserGroupControllerBase.cs index a5691932b1aa..0112df812797 100644 --- a/src/Umbraco.Cms.Api.Management/Controllers/UserGroup/UserGroupControllerBase.cs +++ b/src/Umbraco.Cms.Api.Management/Controllers/UserGroup/UserGroupControllerBase.cs @@ -54,8 +54,12 @@ protected IActionResult UserGroupOperationStatusResult(UserGroupOperationStatus .WithDetail("The assigned media start node does not exists.") .Build()), UserGroupOperationStatus.DocumentPermissionKeyNotFound => NotFound(new ProblemDetailsBuilder() - .WithTitle("A document permission key not found") - .WithDetail("A assigned document permission not exists.") + .WithTitle("Document permission key not found") + .WithDetail("An assigned document permission does not reference an existing document.") + .Build()), + UserGroupOperationStatus.DocumentTypePermissionKeyNotFound => NotFound(new ProblemDetailsBuilder() + .WithTitle("Document type permission key not found") + .WithDetail("An assigned document type permission does not reference an existing document type.") .Build()), UserGroupOperationStatus.LanguageNotFound => NotFound(problemDetailsBuilder .WithTitle("Language not found") diff --git a/src/Umbraco.Core/Services/OperationStatus/UserGroupOperationStatus.cs b/src/Umbraco.Core/Services/OperationStatus/UserGroupOperationStatus.cs index 7870429e4cc1..d658e07565e0 100644 --- a/src/Umbraco.Core/Services/OperationStatus/UserGroupOperationStatus.cs +++ b/src/Umbraco.Core/Services/OperationStatus/UserGroupOperationStatus.cs @@ -14,6 +14,7 @@ public enum UserGroupOperationStatus MediaStartNodeKeyNotFound, DocumentStartNodeKeyNotFound, DocumentPermissionKeyNotFound, + DocumentTypePermissionKeyNotFound, LanguageNotFound, NameTooLong, AliasTooLong, diff --git a/src/Umbraco.Core/Services/UserGroupService.cs b/src/Umbraco.Core/Services/UserGroupService.cs index 1bf0a2870d00..ac7d1a40aaab 100644 --- a/src/Umbraco.Core/Services/UserGroupService.cs +++ b/src/Umbraco.Core/Services/UserGroupService.cs @@ -612,20 +612,26 @@ private UserGroupOperationStatus ValidateStartNodesExists(IUserGroup userGroup) private UserGroupOperationStatus ValidateGranularPermissionsExists(IUserGroup userGroup) { - IEnumerable documentKeys = userGroup.GranularPermissions.Select(granularPermission => - { - if (granularPermission is DocumentGranularPermission nodeGranularPermission) - { - return (Guid?)nodeGranularPermission.Key; - } + Guid[] documentKeys = userGroup.GranularPermissions + .OfType() + .Select(p => p.Key) + .ToArray(); - return null; - }).Where(x => x.HasValue).Cast().ToArray(); if (documentKeys.Any() && _entityService.Exists(documentKeys) is false) { return UserGroupOperationStatus.DocumentPermissionKeyNotFound; } + Guid[] documentTypeKeys = userGroup.GranularPermissions + .OfType() + .Select(p => p.Key) + .ToArray(); + + if (documentTypeKeys.Any() && _entityService.Exists(documentTypeKeys) is false) + { + return UserGroupOperationStatus.DocumentTypePermissionKeyNotFound; + } + return UserGroupOperationStatus.Success; } diff --git a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/ContentTypeRepository.cs b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/ContentTypeRepository.cs index cd9f104bc085..f437c0cd0d1d 100644 --- a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/ContentTypeRepository.cs +++ b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/ContentTypeRepository.cs @@ -220,6 +220,9 @@ protected override void PersistDeletedItem(IContentType entity) // Delete all PropertyData where propertytypeid EXISTS in the subquery above Database.Execute(SqlSyntax.GetDeleteSubquery(Constants.DatabaseSchema.Tables.PropertyData, "propertytypeid", sql)); + // delete all granular permissions for this content type + Database.Delete(Sql().Where(dto => dto.UniqueId == entity.Key)); + base.PersistDeletedItem(entity); } diff --git a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/UserGroupRepository.cs b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/UserGroupRepository.cs index 7a6b2132913f..1eb3fa47a7dc 100644 --- a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/UserGroupRepository.cs +++ b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/UserGroupRepository.cs @@ -447,7 +447,6 @@ protected override IEnumerable GetDeleteClauses() "DELETE FROM umbracoUserGroup2App WHERE userGroupId = @id", "DELETE FROM umbracoUserGroup2Permission WHERE userGroupKey IN (SELECT [umbracoUserGroup].[Key] FROM umbracoUserGroup WHERE Id = @id)", "DELETE FROM umbracoUserGroup2GranularPermission WHERE userGroupKey IN (SELECT [umbracoUserGroup].[Key] FROM umbracoUserGroup WHERE Id = @id)", - "DELETE FROM umbracoUserGroup2GranularPermission WHERE userGroupKey IN (SELECT [umbracoUserGroup].[Key] FROM umbracoUserGroup WHERE Id = @id)", "DELETE FROM umbracoUserGroup WHERE id = @id", }; return list; diff --git a/tests/Umbraco.Tests.Integration/ManagementApi/Factories/UserGroupPresentationFactoryTests.cs b/tests/Umbraco.Tests.Integration/ManagementApi/Factories/UserGroupPresentationFactoryTests.cs index 8a279222763a..76377920b4ec 100644 --- a/tests/Umbraco.Tests.Integration/ManagementApi/Factories/UserGroupPresentationFactoryTests.cs +++ b/tests/Umbraco.Tests.Integration/ManagementApi/Factories/UserGroupPresentationFactoryTests.cs @@ -7,6 +7,7 @@ using Umbraco.Cms.Api.Management.ViewModels.UserGroup.Permissions; using Umbraco.Cms.Core; using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Models.Membership.Permissions; using Umbraco.Cms.Core.Services; using Umbraco.Cms.Core.Services.ContentTypeEditing; using Umbraco.Cms.Core.Services.OperationStatus; @@ -33,9 +34,10 @@ protected override void ConfigureTestServices(IServiceCollection services) { services.AddTransient(); services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(x=>x.GetRequiredService()); - services.AddSingleton(x=>x.GetRequiredService()); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); } @@ -101,6 +103,40 @@ public async Task Cannot_Create_UserGroup_With_Unexisting_Document_Reference() }); } + [Test] + public async Task Cannot_Create_UserGroup_With_Unexisting_DocumentType_Reference() + { + var updateModel = new CreateUserGroupRequestModel() + { + Alias = "testAlias", + FallbackPermissions = new HashSet(), + HasAccessToAllLanguages = true, + Languages = new List(), + Name = "Test Name", + Sections = new [] {"Umb.Section.Content"}, + Permissions = new HashSet() + { + new DocumentPropertyValuePermissionPresentationModel() + { + DocumentType = new ReferenceByIdModel(Guid.NewGuid()), + PropertyType = new ReferenceByIdModel(Guid.NewGuid()), + Verbs = new HashSet() + } + } + }; + + var attempt = await UserGroupPresentationFactory.CreateAsync(updateModel); + Assert.IsTrue(attempt.Success); + + var userGroupCreateAttempt = await UserGroupService.CreateAsync(attempt.Result, Constants.Security.SuperUserKey); + + Assert.Multiple(() => + { + Assert.IsFalse(userGroupCreateAttempt.Success); + Assert.AreEqual(UserGroupOperationStatus.DocumentTypePermissionKeyNotFound, userGroupCreateAttempt.Status); + }); + } + [Test] public async Task Can_Create_Usergroup_With_Empty_Granluar_Permissions_For_Document() { @@ -140,6 +176,170 @@ public async Task Can_Create_Usergroup_With_Empty_Granluar_Permissions_For_Docum }); } + [Test] + public async Task Can_Create_Usergroup_With_Granluar_Permissions_For_Document_PropertyValue() + { + var template = TemplateBuilder.CreateTextPageTemplate("defaultTemplate"); + await TemplateService.CreateAsync(template, Constants.Security.SuperUserKey); + + var contentType = (await ContentTypeEditingService.CreateAsync( + ContentTypeEditingBuilder.CreateSimpleContentType(defaultTemplateKey: template.Key), + Constants.Security.SuperUserKey)).Result!; + + var propertyType = contentType.PropertyTypes.First(); + + var updateModel = new CreateUserGroupRequestModel() + { + Alias = "testAlias", + FallbackPermissions = new HashSet(), + HasAccessToAllLanguages = true, + Languages = new List(), + Name = "Test Name", + Sections = new [] {"Umb.Section.Content"}, + Permissions = new HashSet + { + new DocumentPropertyValuePermissionPresentationModel + { + DocumentType = new ReferenceByIdModel(contentType.Key), + PropertyType = new ReferenceByIdModel(propertyType.Key), + Verbs = new HashSet(["Some", "Another"]) + } + } + }; + + var attempt = await UserGroupPresentationFactory.CreateAsync(updateModel); + Assert.IsTrue(attempt.Success); + + var userGroupCreateAttempt = await UserGroupService.CreateAsync(attempt.Result, Constants.Security.SuperUserKey); + var userGroup = userGroupCreateAttempt.Result; + + Assert.Multiple(() => + { + Assert.IsTrue(userGroupCreateAttempt.Success); + Assert.IsNotNull(userGroup); + }); + + Assert.AreEqual(2, userGroup.GranularPermissions.Count); + var documentTypeGranularPermissions = userGroup.GranularPermissions.OfType().ToArray(); + Assert.AreEqual(2, documentTypeGranularPermissions.Length); + Assert.Multiple(() => + { + Assert.IsTrue(documentTypeGranularPermissions.All(x => x.Key == contentType.Key)); + Assert.AreEqual($"{propertyType.Key}|Some", documentTypeGranularPermissions.First().Permission); + Assert.AreEqual($"{propertyType.Key}|Another", documentTypeGranularPermissions.Last().Permission); + }); + } + + [Test] + public async Task Can_Create_Usergroup_With_Granluar_Permissions_For_Document_PropertyValue_Without_Verbs() + { + var template = TemplateBuilder.CreateTextPageTemplate("defaultTemplate"); + await TemplateService.CreateAsync(template, Constants.Security.SuperUserKey); + + var contentType = (await ContentTypeEditingService.CreateAsync( + ContentTypeEditingBuilder.CreateSimpleContentType(defaultTemplateKey: template.Key), + Constants.Security.SuperUserKey)).Result!; + + var propertyType = contentType.PropertyTypes.First(); + + var updateModel = new CreateUserGroupRequestModel() + { + Alias = "testAlias", + FallbackPermissions = new HashSet(), + HasAccessToAllLanguages = true, + Languages = new List(), + Name = "Test Name", + Sections = new [] {"Umb.Section.Content"}, + Permissions = new HashSet + { + new DocumentPropertyValuePermissionPresentationModel + { + DocumentType = new ReferenceByIdModel(contentType.Key), + PropertyType = new ReferenceByIdModel(propertyType.Key), + Verbs = new HashSet() + } + } + }; + + var attempt = await UserGroupPresentationFactory.CreateAsync(updateModel); + Assert.IsTrue(attempt.Success); + + var userGroupCreateAttempt = await UserGroupService.CreateAsync(attempt.Result, Constants.Security.SuperUserKey); + var userGroup = userGroupCreateAttempt.Result; + + Assert.Multiple(() => + { + Assert.IsTrue(userGroupCreateAttempt.Success); + Assert.IsNotNull(userGroup); + }); + + Assert.AreEqual(1, userGroup.GranularPermissions.Count); + var documentTypeGranularPermissions = userGroup.GranularPermissions.OfType().ToArray(); + Assert.AreEqual(1, documentTypeGranularPermissions.Length); + Assert.Multiple(() => + { + Assert.IsTrue(documentTypeGranularPermissions.All(x => x.Key == contentType.Key)); + Assert.AreEqual($"{propertyType.Key}|", documentTypeGranularPermissions.First().Permission); + }); + } + + [Test] + public async Task Usergroup_Granluar_Permissions_For_Document_PropertyValue_Are_Cleaned_Up_When_DocumentType_Is_Deleted() + { + var template = TemplateBuilder.CreateTextPageTemplate("defaultTemplate"); + await TemplateService.CreateAsync(template, Constants.Security.SuperUserKey); + + var contentType1 = (await ContentTypeEditingService.CreateAsync( + ContentTypeEditingBuilder.CreateSimpleContentType(defaultTemplateKey: template.Key), + Constants.Security.SuperUserKey)).Result!; + + var contentType2 = (await ContentTypeEditingService.CreateAsync( + ContentTypeEditingBuilder.CreateSimpleContentType(alias: "anotherAlias", defaultTemplateKey: template.Key), + Constants.Security.SuperUserKey)).Result!; + + var propertyType1 = contentType1.PropertyTypes.First(); + var propertyType2 = contentType2.PropertyTypes.First(); + + var updateModel = new CreateUserGroupRequestModel() + { + Alias = "testAlias", + FallbackPermissions = new HashSet(), + HasAccessToAllLanguages = true, + Languages = new List(), + Name = "Test Name", + Sections = new [] {"Umb.Section.Content"}, + Permissions = new HashSet + { + new DocumentPropertyValuePermissionPresentationModel + { + DocumentType = new ReferenceByIdModel(contentType1.Key), + PropertyType = new ReferenceByIdModel(propertyType1.Key), + Verbs = new HashSet(["Some", "Another"]) + }, + new DocumentPropertyValuePermissionPresentationModel + { + DocumentType = new ReferenceByIdModel(contentType2.Key), + PropertyType = new ReferenceByIdModel(propertyType2.Key), + Verbs = new HashSet(["Even", "More"]) + } + } + }; + + var attempt = await UserGroupPresentationFactory.CreateAsync(updateModel); + + var userGroupCreateAttempt = await UserGroupService.CreateAsync(attempt.Result, Constants.Security.SuperUserKey); + Assert.IsTrue(userGroupCreateAttempt.Success); + Assert.AreEqual(4, userGroupCreateAttempt.Result!.GranularPermissions.Count); + + var deleteResult = await GetRequiredService().DeleteAsync(contentType1.Key, Constants.Security.SuperUserKey); + Assert.AreEqual(ContentTypeOperationStatus.Success, deleteResult); + + var userGroup = await UserGroupService.GetAsync(userGroupCreateAttempt.Result!.Key); + Assert.IsNotNull(userGroup); + + Assert.AreEqual(2, userGroup.GranularPermissions.Count); + } + private async Task CreateContent() { // NOTE Maybe not the best way to create/save test data as we are using the services, which are being tested. From 9b7ffdf0691b5d25450973324a2a74872e48a75f Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 21 Mar 2025 15:40:44 +0100 Subject: [PATCH 087/106] rename to visibility state --- .../content-type-structure-manager.class.ts | 6 +++--- ...-detail-validation-path-translator.test.ts | 1 + .../edit/content-editor-properties.element.ts | 20 +++++++++---------- .../src/packages/core/property/index.ts | 4 ++-- .../property/property-read-state.manager.ts | 10 ---------- .../property-visibility-state.manager.ts | 10 ++++++++++ .../src/packages/core/variant/index.ts | 2 +- .../variant-property-read-state.manager.ts | 9 --------- ...riant-property-visibility-state.manager.ts | 9 +++++++++ ...value-user-permission.workspace-context.ts | 6 +++--- .../workspace/document-workspace.context.ts | 2 +- 11 files changed, 40 insertions(+), 39 deletions(-) delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/property/property-read-state.manager.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/property/property-visibility-state.manager.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/variant/variant-property-read-state.manager.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/variant/variant-property-visibility-state.manager.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/structure/content-type-structure-manager.class.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/structure/content-type-structure-manager.class.ts index e3512137cb01..361c1fb09ac3 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/structure/content-type-structure-manager.class.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/structure/content-type-structure-manager.class.ts @@ -20,7 +20,7 @@ import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; import { UmbExtensionApiInitializer } from '@umbraco-cms/backoffice/extension-api'; import { umbExtensionsRegistry, type ManifestRepository } from '@umbraco-cms/backoffice/extension-registry'; import { - UmbVariantPropertyReadStateManager, + UmbVariantPropertyVisibilityStateManager, UmbVariantPropertyWriteStateManager, } from '@umbraco-cms/backoffice/variant'; @@ -102,7 +102,7 @@ export class UmbContentTypeStructureManager< readonly variesByCulture = createObservablePart(this.ownerContentType, (x) => x?.variesByCulture); readonly variesBySegment = createObservablePart(this.ownerContentType, (x) => x?.variesBySegment); - public readonly propertyReadState = new UmbVariantPropertyReadStateManager(this); + public readonly propertyVisibilityState = new UmbVariantPropertyVisibilityStateManager(this); public readonly propertyWriteState = new UmbVariantPropertyWriteStateManager(this); #containers: UmbArrayState = new UmbArrayState( @@ -816,7 +816,7 @@ export class UmbContentTypeStructureManager< public override destroy() { this.#contentTypes.destroy(); this.#containers.destroy(); - this.propertyReadState.destroy(); + this.propertyVisibilityState.destroy(); this.propertyWriteState.destroy(); super.destroy(); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/content-detail-validation-path-translator.test.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/content-detail-validation-path-translator.test.ts index 6e88784da4ad..f2df7ff95b28 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/content-detail-validation-path-translator.test.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/content-detail-validation-path-translator.test.ts @@ -33,6 +33,7 @@ describe('UmbValidationPropertyPathTranslationController', () => { value: 'value1', culture: null, segment: null, + entityType: 'document-property-value', }, ], variants: [], diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/content-editor-properties.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/content-editor-properties.element.ts index c8deaa05f809..e66d92dfeeb7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/content-editor-properties.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/content-editor-properties.element.ts @@ -11,7 +11,7 @@ import { UmbDataPathPropertyValueQuery } from '@umbraco-cms/backoffice/validatio import { UMB_PROPERTY_STRUCTURE_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace'; import { UmbVariantId, - type UmbVariantPropertyReadState, + type UmbVariantPropertyVisibilityState, type UmbVariantPropertyWriteState, } from '@umbraco-cms/backoffice/variant'; import { UMB_PROPERTY_DATASET_CONTEXT } from '@umbraco-cms/backoffice/property'; @@ -36,7 +36,7 @@ export class UmbContentWorkspaceViewEditPropertiesElement extends UmbLitElement _dataPaths?: Array; @state() - _propertyReadStates: Array = []; + _propertyVisibilityStates: Array = []; @state() _propertyWriteStates: Array = []; @@ -51,9 +51,9 @@ export class UmbContentWorkspaceViewEditPropertiesElement extends UmbLitElement ); this.observe( - workspaceContext.structure.propertyReadState.states, - (states) => (this._propertyReadStates = states), - 'umbObservePropertyReadStates', + workspaceContext.structure.propertyVisibilityState.states, + (states) => (this._propertyVisibilityStates = states), + 'umbObservePropertyVisibilityStates', ); this.observe( @@ -90,13 +90,13 @@ export class UmbContentWorkspaceViewEditPropertiesElement extends UmbLitElement ); } - #getReadableProperties() { - return this._propertyStructure?.filter((property) => this.#isReadablePropertyType(property)) || []; + #getVisibleProperties() { + return this._propertyStructure?.filter((property) => this.#isVisiblePropertyType(property)) || []; } - #isReadablePropertyType(property: UmbPropertyTypeModel) { + #isVisiblePropertyType(property: UmbPropertyTypeModel) { const propertyVariantId = this.#getPropertyVariantId(property); - return this._propertyReadStates.some( + return this._propertyVisibilityStates.some( (state) => state.propertyType.unique === property.unique && state.propertyType.variantId.equal(propertyVariantId), ); } @@ -118,7 +118,7 @@ export class UmbContentWorkspaceViewEditPropertiesElement extends UmbLitElement override render() { return this._propertyStructure && this._dataPaths ? repeat( - this.#getReadableProperties(), + this.#getVisibleProperties(), (property) => property.alias, (property, index) => html` extends UmbStateManager {} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property/property-visibility-state.manager.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property/property-visibility-state.manager.ts new file mode 100644 index 000000000000..ead90a47b98c --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property/property-visibility-state.manager.ts @@ -0,0 +1,10 @@ +import type { UmbReferenceByUnique } from '@umbraco-cms/backoffice/models'; +import { UmbStateManager, type UmbState } from '@umbraco-cms/backoffice/utils'; + +export interface UmbPropertyVisibilityState extends UmbState { + propertyType: UmbReferenceByUnique; +} + +export class UmbPropertyVisibilityStateManager< + VisibilityStateType extends UmbPropertyVisibilityState = UmbPropertyVisibilityState, +> extends UmbStateManager {} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/variant/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/variant/index.ts index 831be38b4a56..0e96b473ce98 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/variant/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/variant/index.ts @@ -1,5 +1,5 @@ export * from './variant-id.class.js'; export * from './variant-object-compare.function.js'; -export * from './variant-property-read-state.manager.js'; +export * from './variant-property-visibility-state.manager.js'; export * from './variant-property-write-state.manager.js'; export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/variant/variant-property-read-state.manager.ts b/src/Umbraco.Web.UI.Client/src/packages/core/variant/variant-property-read-state.manager.ts deleted file mode 100644 index 238936799078..000000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/core/variant/variant-property-read-state.manager.ts +++ /dev/null @@ -1,9 +0,0 @@ -import type { UmbReferenceByVariantId } from './types.js'; -import type { UmbReferenceByUnique } from '@umbraco-cms/backoffice/models'; -import { UmbPropertyReadStateManager, type UmbPropertyReadState } from '@umbraco-cms/backoffice/property'; - -export interface UmbVariantPropertyReadState extends UmbPropertyReadState { - propertyType: UmbReferenceByUnique & UmbReferenceByVariantId; -} - -export class UmbVariantPropertyReadStateManager extends UmbPropertyReadStateManager {} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/variant/variant-property-visibility-state.manager.ts b/src/Umbraco.Web.UI.Client/src/packages/core/variant/variant-property-visibility-state.manager.ts new file mode 100644 index 000000000000..0212edbf1565 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/variant/variant-property-visibility-state.manager.ts @@ -0,0 +1,9 @@ +import type { UmbReferenceByVariantId } from './types.js'; +import type { UmbReferenceByUnique } from '@umbraco-cms/backoffice/models'; +import { UmbPropertyVisibilityStateManager, type UmbPropertyVisibilityState } from '@umbraco-cms/backoffice/property'; + +export interface UmbVariantPropertyVisibilityState extends UmbPropertyVisibilityState { + propertyType: UmbReferenceByUnique & UmbReferenceByVariantId; +} + +export class UmbVariantPropertyVisibilityStateManager extends UmbPropertyVisibilityStateManager {} diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/workspace-context/document-property-value-user-permission.workspace-context.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/workspace-context/document-property-value-user-permission.workspace-context.ts index f130f224bf7f..325f6fa09493 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/workspace-context/document-property-value-user-permission.workspace-context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/workspace-context/document-property-value-user-permission.workspace-context.ts @@ -13,7 +13,7 @@ import { createExtensionApiByAlias } from '@umbraco-cms/backoffice/extension-reg import { UmbVariantId, type UmbEntityVariantOptionModel, - type UmbVariantPropertyReadState, + type UmbVariantPropertyVisibilityState, type UmbVariantPropertyWriteState, } from '@umbraco-cms/backoffice/variant'; import type { UmbPropertyTypeModel } from '@umbraco-cms/backoffice/content-type'; @@ -43,7 +43,7 @@ export class UmbDocumentPropertyValueUserPermissionWorkspaceContext extends UmbC properties.forEach((property) => { this.#setPermissionForProperty({ verb: UMB_USER_PERMISSION_DOCUMENT_PROPERTY_VALUE_READ, - stateManager: this.#workspaceContext!.structure.propertyReadState, + stateManager: this.#workspaceContext!.structure.propertyVisibilityState, property, variantOptions, }); @@ -61,7 +61,7 @@ export class UmbDocumentPropertyValueUserPermissionWorkspaceContext extends UmbC #setPermissionForProperty(args: { verb: string; - stateManager: UmbStateManager; + stateManager: UmbStateManager; property: UmbPropertyTypeModel; variantOptions: Array>; }) { 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 79e057fe5c25..ec86f766efe8 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 @@ -182,7 +182,7 @@ export class UmbDocumentWorkspaceContext override resetState(): void { super.resetState(); this.#isTrashedContext.setIsTrashed(false); - this.structure.propertyReadState.clear(); + this.structure.propertyVisibilityState.clear(); this.structure.propertyWriteState.clear(); } From 82968d1cecd36360519e354b29c634dac5f05f86 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Sun, 23 Mar 2025 19:36:27 +0100 Subject: [PATCH 088/106] rename to view --- .../content-type-structure-manager.class.ts | 6 +++--- .../views/edit/content-editor-properties.element.ts | 12 ++++++------ .../src/packages/core/property/index.ts | 4 ++-- .../core/property/property-view-state.manager.ts | 10 ++++++++++ .../property/property-visibility-state.manager.ts | 10 ---------- .../src/packages/core/variant/index.ts | 2 +- .../variant/variant-property-view-state.manager.ts | 9 +++++++++ .../variant-property-visibility-state.manager.ts | 9 --------- ...operty-value-user-permission.workspace-context.ts | 6 +++--- .../workspace/document-workspace.context.ts | 2 +- 10 files changed, 35 insertions(+), 35 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/property/property-view-state.manager.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/property/property-visibility-state.manager.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/variant/variant-property-view-state.manager.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/variant/variant-property-visibility-state.manager.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/structure/content-type-structure-manager.class.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/structure/content-type-structure-manager.class.ts index 361c1fb09ac3..0e3f852a0187 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/structure/content-type-structure-manager.class.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/structure/content-type-structure-manager.class.ts @@ -20,7 +20,7 @@ import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; import { UmbExtensionApiInitializer } from '@umbraco-cms/backoffice/extension-api'; import { umbExtensionsRegistry, type ManifestRepository } from '@umbraco-cms/backoffice/extension-registry'; import { - UmbVariantPropertyVisibilityStateManager, + UmbVariantPropertyViewStateManager, UmbVariantPropertyWriteStateManager, } from '@umbraco-cms/backoffice/variant'; @@ -102,7 +102,7 @@ export class UmbContentTypeStructureManager< readonly variesByCulture = createObservablePart(this.ownerContentType, (x) => x?.variesByCulture); readonly variesBySegment = createObservablePart(this.ownerContentType, (x) => x?.variesBySegment); - public readonly propertyVisibilityState = new UmbVariantPropertyVisibilityStateManager(this); + public readonly propertyViewState = new UmbVariantPropertyViewStateManager(this); public readonly propertyWriteState = new UmbVariantPropertyWriteStateManager(this); #containers: UmbArrayState = new UmbArrayState( @@ -816,7 +816,7 @@ export class UmbContentTypeStructureManager< public override destroy() { this.#contentTypes.destroy(); this.#containers.destroy(); - this.propertyVisibilityState.destroy(); + this.propertyViewState.destroy(); this.propertyWriteState.destroy(); super.destroy(); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/content-editor-properties.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/content-editor-properties.element.ts index e66d92dfeeb7..e39945f29192 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/content-editor-properties.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/content-editor-properties.element.ts @@ -11,7 +11,7 @@ import { UmbDataPathPropertyValueQuery } from '@umbraco-cms/backoffice/validatio import { UMB_PROPERTY_STRUCTURE_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace'; import { UmbVariantId, - type UmbVariantPropertyVisibilityState, + type UmbVariantPropertyViewState, type UmbVariantPropertyWriteState, } from '@umbraco-cms/backoffice/variant'; import { UMB_PROPERTY_DATASET_CONTEXT } from '@umbraco-cms/backoffice/property'; @@ -36,7 +36,7 @@ export class UmbContentWorkspaceViewEditPropertiesElement extends UmbLitElement _dataPaths?: Array; @state() - _propertyVisibilityStates: Array = []; + _propertyViewStates: Array = []; @state() _propertyWriteStates: Array = []; @@ -51,9 +51,9 @@ export class UmbContentWorkspaceViewEditPropertiesElement extends UmbLitElement ); this.observe( - workspaceContext.structure.propertyVisibilityState.states, - (states) => (this._propertyVisibilityStates = states), - 'umbObservePropertyVisibilityStates', + workspaceContext.structure.propertyViewState.states, + (states) => (this._propertyViewStates = states), + 'umbObservePropertyViewStates', ); this.observe( @@ -96,7 +96,7 @@ export class UmbContentWorkspaceViewEditPropertiesElement extends UmbLitElement #isVisiblePropertyType(property: UmbPropertyTypeModel) { const propertyVariantId = this.#getPropertyVariantId(property); - return this._propertyVisibilityStates.some( + return this._propertyViewStates.some( (state) => state.propertyType.unique === property.unique && state.propertyType.variantId.equal(propertyVariantId), ); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property/index.ts index aeb6a54f93be..c7376d55ca65 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/property/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property/index.ts @@ -3,8 +3,8 @@ export * from './conditions/index.js'; export * from './property-dataset/index.js'; export * from './property-value-cloner/property-value-clone.controller.js'; export * from './property-value-preset/index.js'; -export * from './property-visibility-state.manager.js'; +export * from './property-view-state.manager.js'; export * from './property-write-state.manager.js'; -export * from './property-visibility-state.manager.js'; +export * from './property-view-state.manager.js'; export * from './property-write-state.manager.js'; export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property/property-view-state.manager.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property/property-view-state.manager.ts new file mode 100644 index 000000000000..2f52ccc060ac --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property/property-view-state.manager.ts @@ -0,0 +1,10 @@ +import type { UmbReferenceByUnique } from '@umbraco-cms/backoffice/models'; +import { UmbStateManager, type UmbState } from '@umbraco-cms/backoffice/utils'; + +export interface UmbPropertyViewState extends UmbState { + propertyType: UmbReferenceByUnique; +} + +export class UmbPropertyViewStateManager< + ViewStateType extends UmbPropertyViewState = UmbPropertyViewState, +> extends UmbStateManager {} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property/property-visibility-state.manager.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property/property-visibility-state.manager.ts deleted file mode 100644 index ead90a47b98c..000000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/core/property/property-visibility-state.manager.ts +++ /dev/null @@ -1,10 +0,0 @@ -import type { UmbReferenceByUnique } from '@umbraco-cms/backoffice/models'; -import { UmbStateManager, type UmbState } from '@umbraco-cms/backoffice/utils'; - -export interface UmbPropertyVisibilityState extends UmbState { - propertyType: UmbReferenceByUnique; -} - -export class UmbPropertyVisibilityStateManager< - VisibilityStateType extends UmbPropertyVisibilityState = UmbPropertyVisibilityState, -> extends UmbStateManager {} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/variant/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/variant/index.ts index 0e96b473ce98..1640f73a84a8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/variant/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/variant/index.ts @@ -1,5 +1,5 @@ export * from './variant-id.class.js'; export * from './variant-object-compare.function.js'; -export * from './variant-property-visibility-state.manager.js'; +export * from './variant-property-view-state.manager.js'; export * from './variant-property-write-state.manager.js'; export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/variant/variant-property-view-state.manager.ts b/src/Umbraco.Web.UI.Client/src/packages/core/variant/variant-property-view-state.manager.ts new file mode 100644 index 000000000000..df8c12874fb4 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/variant/variant-property-view-state.manager.ts @@ -0,0 +1,9 @@ +import type { UmbReferenceByVariantId } from './types.js'; +import type { UmbReferenceByUnique } from '@umbraco-cms/backoffice/models'; +import { UmbPropertyViewStateManager, type UmbPropertyViewState } from '@umbraco-cms/backoffice/property'; + +export interface UmbVariantPropertyViewState extends UmbPropertyViewState { + propertyType: UmbReferenceByUnique & UmbReferenceByVariantId; +} + +export class UmbVariantPropertyViewStateManager extends UmbPropertyViewStateManager {} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/variant/variant-property-visibility-state.manager.ts b/src/Umbraco.Web.UI.Client/src/packages/core/variant/variant-property-visibility-state.manager.ts deleted file mode 100644 index 0212edbf1565..000000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/core/variant/variant-property-visibility-state.manager.ts +++ /dev/null @@ -1,9 +0,0 @@ -import type { UmbReferenceByVariantId } from './types.js'; -import type { UmbReferenceByUnique } from '@umbraco-cms/backoffice/models'; -import { UmbPropertyVisibilityStateManager, type UmbPropertyVisibilityState } from '@umbraco-cms/backoffice/property'; - -export interface UmbVariantPropertyVisibilityState extends UmbPropertyVisibilityState { - propertyType: UmbReferenceByUnique & UmbReferenceByVariantId; -} - -export class UmbVariantPropertyVisibilityStateManager extends UmbPropertyVisibilityStateManager {} diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/workspace-context/document-property-value-user-permission.workspace-context.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/workspace-context/document-property-value-user-permission.workspace-context.ts index 325f6fa09493..42c98c06090e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/workspace-context/document-property-value-user-permission.workspace-context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/workspace-context/document-property-value-user-permission.workspace-context.ts @@ -13,7 +13,7 @@ import { createExtensionApiByAlias } from '@umbraco-cms/backoffice/extension-reg import { UmbVariantId, type UmbEntityVariantOptionModel, - type UmbVariantPropertyVisibilityState, + type UmbVariantPropertyViewState, type UmbVariantPropertyWriteState, } from '@umbraco-cms/backoffice/variant'; import type { UmbPropertyTypeModel } from '@umbraco-cms/backoffice/content-type'; @@ -43,7 +43,7 @@ export class UmbDocumentPropertyValueUserPermissionWorkspaceContext extends UmbC properties.forEach((property) => { this.#setPermissionForProperty({ verb: UMB_USER_PERMISSION_DOCUMENT_PROPERTY_VALUE_READ, - stateManager: this.#workspaceContext!.structure.propertyVisibilityState, + stateManager: this.#workspaceContext!.structure.propertyViewState, property, variantOptions, }); @@ -61,7 +61,7 @@ export class UmbDocumentPropertyValueUserPermissionWorkspaceContext extends UmbC #setPermissionForProperty(args: { verb: string; - stateManager: UmbStateManager; + stateManager: UmbStateManager; property: UmbPropertyTypeModel; variantOptions: Array>; }) { 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 ec86f766efe8..a44503f70cbe 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 @@ -182,7 +182,7 @@ export class UmbDocumentWorkspaceContext override resetState(): void { super.resetState(); this.#isTrashedContext.setIsTrashed(false); - this.structure.propertyVisibilityState.clear(); + this.structure.propertyViewState.clear(); this.structure.propertyWriteState.clear(); } From 2ca216c80b7f743ac69022d76aabf48f8bd80d2c Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Sun, 23 Mar 2025 19:42:25 +0100 Subject: [PATCH 089/106] add helpers --- .../property/property-view-state.manager.ts | 18 +++++++++++++++++- .../property/property-write-state.manager.ts | 17 ++++++++++++++++- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property/property-view-state.manager.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property/property-view-state.manager.ts index 2f52ccc060ac..b7d8fea74ab0 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/property/property-view-state.manager.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property/property-view-state.manager.ts @@ -1,5 +1,6 @@ import type { UmbReferenceByUnique } from '@umbraco-cms/backoffice/models'; import { UmbStateManager, type UmbState } from '@umbraco-cms/backoffice/utils'; +import type { Observable } from '@umbraco-cms/backoffice/observable-api'; export interface UmbPropertyViewState extends UmbState { propertyType: UmbReferenceByUnique; @@ -7,4 +8,19 @@ export interface UmbPropertyViewState extends UmbState { export class UmbPropertyViewStateManager< ViewStateType extends UmbPropertyViewState = UmbPropertyViewState, -> extends UmbStateManager {} +> extends UmbStateManager { + /** + * Get the viewable state + * @returns {Observable} True if the property is viewable + * @memberof UmbPropertyViewStateManager + */ + public readonly isViewable = this.isOn; + + /** + * Get the property viewable state + * @returns {boolean} True if the property is viewable + */ + public getIsViewable(): boolean { + return this.getIsOn(); + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property/property-write-state.manager.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property/property-write-state.manager.ts index 96b02234ae0e..4f2e9d42e481 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/property/property-write-state.manager.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property/property-write-state.manager.ts @@ -7,4 +7,19 @@ export interface UmbPropertyWriteState extends UmbState { export class UmbPropertyWriteStateManager< WriteStateType extends UmbPropertyWriteState = UmbPropertyWriteState, -> extends UmbStateManager {} +> extends UmbStateManager { + /** + * Get the writable state + * @returns {Observable} True if the property is writable + * @memberof UmbPropertyWriteStateManager + */ + public readonly isWritable = this.isOn; + + /** + * Get the property writable state + * @returns {boolean} True if the property is writable + */ + public getIsWritable(): boolean { + return this.getIsOn(); + } +} From fa8cd66e68216c327a411db1904159dac4304c3b Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Sun, 23 Mar 2025 20:21:25 +0100 Subject: [PATCH 090/106] apply to blocks --- ...-workspace-view-edit-properties.element.ts | 57 ++++++++- ...user-permission.workspace-context.token.ts | 7 -- ...value-user-permission.workspace-context.ts | 112 +++++++++++++----- .../workspace-context/manifests.ts | 17 ++- 4 files changed, 150 insertions(+), 43 deletions(-) delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/workspace-context/document-property-value-user-permission.workspace-context.token.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/views/edit/block-workspace-view-edit-properties.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/views/edit/block-workspace-view-edit-properties.element.ts index 1b1acc7425cf..ce5f2d31a71b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/views/edit/block-workspace-view-edit-properties.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/views/edit/block-workspace-view-edit-properties.element.ts @@ -5,7 +5,11 @@ import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import type { UmbContentTypeModel, UmbPropertyTypeModel } from '@umbraco-cms/backoffice/content-type'; import { UmbContentTypePropertyStructureHelper } from '@umbraco-cms/backoffice/content-type'; import { UmbLitElement, umbDestroyOnDisconnect } from '@umbraco-cms/backoffice/lit-element'; -import type { UmbVariantId } from '@umbraco-cms/backoffice/variant'; +import { + UmbVariantId, + type UmbVariantPropertyViewState, + type UmbVariantPropertyWriteState, +} from '@umbraco-cms/backoffice/variant'; import { UmbDataPathPropertyValueQuery } from '@umbraco-cms/backoffice/validation'; @customElement('umb-block-workspace-view-edit-properties') @@ -40,6 +44,12 @@ export class UmbBlockWorkspaceViewEditPropertiesElement extends UmbLitElement { @state() private _ownerEntityType?: string; + @state() + _propertyViewStates: Array = []; + + @state() + _propertyWriteStates: Array = []; + #variantId?: UmbVariantId; constructor() { @@ -62,7 +72,10 @@ export class UmbBlockWorkspaceViewEditPropertiesElement extends UmbLitElement { #setStructureManager() { if (!this.#blockWorkspace || !this.#managerName) return; - this.#propertyStructureHelper.setStructureManager(this.#blockWorkspace[this.#managerName].structure); + + const structureManager = this.#blockWorkspace[this.#managerName].structure; + + this.#propertyStructureHelper.setStructureManager(structureManager); this.observe( this.#propertyStructureHelper.propertyStructure, (propertyStructure) => { @@ -71,6 +84,18 @@ export class UmbBlockWorkspaceViewEditPropertiesElement extends UmbLitElement { }, 'observePropertyStructure', ); + + this.observe( + structureManager.propertyViewState.states, + (states) => (this._propertyViewStates = states), + 'umbObservePropertyReadStates', + ); + + this.observe( + structureManager.propertyWriteState.states, + (states) => (this._propertyWriteStates = states), + 'umbObservePropertyWriteStates', + ); } /* @@ -92,9 +117,34 @@ export class UmbBlockWorkspaceViewEditPropertiesElement extends UmbLitElement { ); } + #getVisibleProperties() { + return this._propertyStructure?.filter((property) => this.#isVisiblePropertyType(property)) || []; + } + + #isVisiblePropertyType(property: UmbPropertyTypeModel) { + const propertyVariantId = this.#getPropertyVariantId(property); + return this._propertyViewStates.some( + (state) => state.propertyType.unique === property.unique && state.propertyType.variantId.equal(propertyVariantId), + ); + } + + #isWritablePropertyType(property: UmbPropertyTypeModel) { + const propertyVariantId = this.#getPropertyVariantId(property); + return this._propertyWriteStates.some( + (state) => state.propertyType.unique === property.unique && state.propertyType.variantId.equal(propertyVariantId), + ); + } + + #getPropertyVariantId(property: UmbPropertyTypeModel) { + return new UmbVariantId( + property.variesByCulture ? this.#variantId!.culture : null, + property.variesBySegment ? this.#variantId!.segment : null, + ); + } + override render() { return repeat( - this._propertyStructure, + this.#getVisibleProperties(), (property) => property.alias, (property, index) => html``, ); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/workspace-context/document-property-value-user-permission.workspace-context.token.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/workspace-context/document-property-value-user-permission.workspace-context.token.ts deleted file mode 100644 index ee94d8a0f82e..000000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/workspace-context/document-property-value-user-permission.workspace-context.token.ts +++ /dev/null @@ -1,7 +0,0 @@ -import type { UmbDocumentPropertyValueUserPermissionWorkspaceContext } from './document-property-value-user-permission.workspace-context.js'; -import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; - -export const UMB_DOCUMENT_PROPERTY_VALUE_USER_PERMISSION_WORKSPACE_CONTEXT = - new UmbContextToken( - 'UmbDocumentPropertyValueUserPermissionWorkspaceContext', - ); diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/workspace-context/document-property-value-user-permission.workspace-context.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/workspace-context/document-property-value-user-permission.workspace-context.ts index 42c98c06090e..beb64db072b5 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/workspace-context/document-property-value-user-permission.workspace-context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/workspace-context/document-property-value-user-permission.workspace-context.ts @@ -4,66 +4,118 @@ import { UMB_USER_PERMISSION_DOCUMENT_PROPERTY_VALUE_READ, UMB_USER_PERMISSION_DOCUMENT_PROPERTY_VALUE_WRITE, } from '../constants.js'; -import type { UmbDocumentVariantModel } from '../../../types.js'; -import { UMB_DOCUMENT_PROPERTY_VALUE_USER_PERMISSION_WORKSPACE_CONTEXT } from './document-property-value-user-permission.workspace-context.token.js'; -import { UmbContextBase } from '@umbraco-cms/backoffice/class-api'; +import { UMB_DOCUMENT_PROPERTY_DATASET_CONTEXT } from '../../../constants.js'; +import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { observeMultiple } from '@umbraco-cms/backoffice/observable-api'; import { createExtensionApiByAlias } from '@umbraco-cms/backoffice/extension-registry'; import { UmbVariantId, - type UmbEntityVariantOptionModel, type UmbVariantPropertyViewState, type UmbVariantPropertyWriteState, } from '@umbraco-cms/backoffice/variant'; import type { UmbPropertyTypeModel } from '@umbraco-cms/backoffice/content-type'; import type { UmbStateManager } from '@umbraco-cms/backoffice/utils'; +import { UMB_BLOCK_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/block'; +import { UMB_PROPERTY_DATASET_CONTEXT } from '@umbraco-cms/backoffice/property'; -export class UmbDocumentPropertyValueUserPermissionWorkspaceContext extends UmbContextBase { - #workspaceContext?: typeof UMB_DOCUMENT_WORKSPACE_CONTEXT.TYPE; +export class UmbDocumentPropertyValueUserPermissionWorkspaceContext extends UmbControllerBase { + #documentWorkspaceContext?: typeof UMB_DOCUMENT_WORKSPACE_CONTEXT.TYPE; + #blockWorkspaceContext?: typeof UMB_BLOCK_WORKSPACE_CONTEXT.TYPE; constructor(host: UmbControllerHost) { - super(host, UMB_DOCUMENT_PROPERTY_VALUE_USER_PERMISSION_WORKSPACE_CONTEXT); + super(host); this.consumeContext(UMB_DOCUMENT_WORKSPACE_CONTEXT, (context) => { - this.#workspaceContext = context; - this.#observeStructure(); + this.#documentWorkspaceContext = context; + this.#observeDocumentProperties(); + }); + + // TODO: investigate if block workspace can provide a property structure context so we can use the same context for both block and document + // TODO: only apply to blocks within a document + this.consumeContext(UMB_BLOCK_WORKSPACE_CONTEXT, async (context) => { + this.#blockWorkspaceContext = context; + this.#observeDocumentBlockProperties(); }); } - #observeStructure() { - if (!this.#workspaceContext) return; + #observeDocumentProperties() { + if (!this.#documentWorkspaceContext) return; + + const structureManager = this.#documentWorkspaceContext.structure; this.observe( - observeMultiple([this.#workspaceContext.structure.contentTypeProperties, this.#workspaceContext.variantOptions]), + observeMultiple([ + this.#documentWorkspaceContext.structure.contentTypeProperties, + this.#documentWorkspaceContext.variantOptions, + ]), ([properties, variantOptions]) => { if (properties.length === 0) return; if (variantOptions.length === 0) return; - properties.forEach((property) => { - this.#setPermissionForProperty({ - verb: UMB_USER_PERMISSION_DOCUMENT_PROPERTY_VALUE_READ, - stateManager: this.#workspaceContext!.structure.propertyViewState, - property, - variantOptions, - }); - - this.#setPermissionForProperty({ - verb: UMB_USER_PERMISSION_DOCUMENT_PROPERTY_VALUE_WRITE, - stateManager: this.#workspaceContext!.structure.propertyWriteState, - property, - variantOptions, - }); - }); + const variantIds = variantOptions?.map((variant) => new UmbVariantId(variant.culture, variant.segment)); + + this.#setPermissions( + properties, + variantIds, + structureManager.propertyViewState, + structureManager.propertyWriteState, + ); }, ); } + async #observeDocumentBlockProperties() { + if (!this.#blockWorkspaceContext) return; + const datasetContext = await this.getContext(UMB_PROPERTY_DATASET_CONTEXT); + if (!datasetContext) return; + + const structureManager = this.#blockWorkspaceContext.content.structure; + + this.observe( + observeMultiple([structureManager.contentTypeProperties, this.#blockWorkspaceContext.variantId]), + ([properties, variantId]) => { + if (properties.length === 0) return; + if (!variantId) return; + + this.#setPermissions( + properties, + [variantId], + structureManager.propertyViewState, + structureManager.propertyWriteState, + ); + }, + ); + } + + #setPermissions( + properties: Array, + variantIds: Array, + propertyVisibilityState: UmbStateManager, + propertyWriteState: UmbStateManager, + ) { + properties.forEach((property) => { + this.#setPermissionForProperty({ + verb: UMB_USER_PERMISSION_DOCUMENT_PROPERTY_VALUE_READ, + stateManager: propertyVisibilityState, + property, + variantIds, + }); + + this.#setPermissionForProperty({ + verb: UMB_USER_PERMISSION_DOCUMENT_PROPERTY_VALUE_WRITE, + stateManager: propertyWriteState, + property, + variantIds, + }); + }); + } + #setPermissionForProperty(args: { verb: string; stateManager: UmbStateManager; property: UmbPropertyTypeModel; - variantOptions: Array>; + variantIds: Array; }) { createExtensionApiByAlias(this, UMB_DOCUMENT_PROPERTY_VALUE_USER_PERMISSION_CONDITION_ALIAS, [ { @@ -78,9 +130,7 @@ export class UmbDocumentPropertyValueUserPermissionWorkspaceContext extends UmbC onChange: (permitted: boolean) => { // If the property is invariant we only need one state for the property const isInvariant = args.property.variesByCulture === false && args.property.variesBySegment === false; - const variantIds = isInvariant - ? [new UmbVariantId()] - : args.variantOptions?.map((variant) => new UmbVariantId(variant.culture, variant.segment)) || []; + const variantIds = isInvariant ? [new UmbVariantId()] : args.variantIds; const states: Array = variantIds?.map((variantId) => { diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/workspace-context/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/workspace-context/manifests.ts index 8db7ef6acc4c..2877f6230d67 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/workspace-context/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/workspace-context/manifests.ts @@ -1,12 +1,13 @@ import { UMB_DOCUMENT_WORKSPACE_ALIAS } from '../../../workspace/constants.js'; import { UMB_WORKSPACE_CONDITION_ALIAS } from '@umbraco-cms/backoffice/workspace'; import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; +import { UMB_BLOCK_WORKSPACE_ALIAS } from '@umbraco-cms/backoffice/block'; export const manifests: Array = [ { type: 'workspaceContext', - name: 'Document Property Value User Permission Workspace Context', - alias: 'Umb.WorkspaceContext.DocumentPropertyValueUserPermission', + name: 'Document Property Value User Permission Document Workspace Context', + alias: 'Umb.WorkspaceContext.Document.DocumentPropertyValueUserPermission', api: () => import('./document-property-value-user-permission.workspace-context.js'), conditions: [ { @@ -15,4 +16,16 @@ export const manifests: Array = }, ], }, + { + type: 'workspaceContext', + name: 'Document Property Value User Permission Block Workspace Context', + alias: 'Umb.WorkspaceContext.Block.DocumentPropertyValueUserPermission', + api: () => import('./document-property-value-user-permission.workspace-context.js'), + conditions: [ + { + alias: UMB_WORKSPACE_CONDITION_ALIAS, + match: UMB_BLOCK_WORKSPACE_ALIAS, + }, + ], + }, ]; From ece77887cdeaec2479a9acb82bdde8e264fb0b7f Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Sun, 23 Mar 2025 20:23:53 +0100 Subject: [PATCH 091/106] Update document-property-value-user-permission.workspace-context.ts --- .../document-property-value-user-permission.workspace-context.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/workspace-context/document-property-value-user-permission.workspace-context.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/workspace-context/document-property-value-user-permission.workspace-context.ts index beb64db072b5..3058224ef9ca 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/workspace-context/document-property-value-user-permission.workspace-context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/workspace-context/document-property-value-user-permission.workspace-context.ts @@ -4,7 +4,6 @@ import { UMB_USER_PERMISSION_DOCUMENT_PROPERTY_VALUE_READ, UMB_USER_PERMISSION_DOCUMENT_PROPERTY_VALUE_WRITE, } from '../constants.js'; -import { UMB_DOCUMENT_PROPERTY_DATASET_CONTEXT } from '../../../constants.js'; import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { observeMultiple } from '@umbraco-cms/backoffice/observable-api'; From 7b7ebc862995c7ac5fb292be65754042c9cdfd44 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 24 Mar 2025 08:13:48 +0100 Subject: [PATCH 092/106] disable view and write state by default --- .../.vscode/settings.json | 4 +- ...-workspace-view-edit-properties.element.ts | 37 +++++++++++++---- .../edit/content-editor-properties.element.ts | 41 ++++++++++++++++--- .../property/property-view-state.manager.ts | 9 +++- .../property/property-write-state.manager.ts | 8 ++++ .../core/utils/state-manager/state.manager.ts | 35 ++++++++++++---- .../workspace/document-workspace.context.ts | 5 +++ 7 files changed, 117 insertions(+), 22 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/.vscode/settings.json b/src/Umbraco.Web.UI.Client/.vscode/settings.json index 8fc1bce8e6c8..4b30430f590d 100644 --- a/src/Umbraco.Web.UI.Client/.vscode/settings.json +++ b/src/Umbraco.Web.UI.Client/.vscode/settings.json @@ -28,7 +28,9 @@ "uninitialize", "unprovide", "unpublishing", - "variantable" + "variantable", + "viewability", + "writability" ], "exportall.config.folderListener": [], "exportall.config.relExclusion": [], diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/views/edit/block-workspace-view-edit-properties.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/views/edit/block-workspace-view-edit-properties.element.ts index ce5f2d31a71b..c4f1f66242aa 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/views/edit/block-workspace-view-edit-properties.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/views/edit/block-workspace-view-edit-properties.element.ts @@ -11,6 +11,7 @@ import { type UmbVariantPropertyWriteState, } from '@umbraco-cms/backoffice/variant'; import { UmbDataPathPropertyValueQuery } from '@umbraco-cms/backoffice/validation'; +import { observeMultiple } from '@umbraco-cms/backoffice/observable-api'; @customElement('umb-block-workspace-view-edit-properties') export class UmbBlockWorkspaceViewEditPropertiesElement extends UmbLitElement { @@ -44,9 +45,15 @@ export class UmbBlockWorkspaceViewEditPropertiesElement extends UmbLitElement { @state() private _ownerEntityType?: string; + @state() + _propertyViewStateIsRunning = true; + @state() _propertyViewStates: Array = []; + @state() + _propertyWriteStateIsRunning = true; + @state() _propertyWriteStates: Array = []; @@ -86,14 +93,20 @@ export class UmbBlockWorkspaceViewEditPropertiesElement extends UmbLitElement { ); this.observe( - structureManager.propertyViewState.states, - (states) => (this._propertyViewStates = states), - 'umbObservePropertyReadStates', + observeMultiple([structureManager.propertyViewState.isRunning, structureManager.propertyViewState.states]), + ([isRunning, states]) => { + this._propertyViewStateIsRunning = isRunning; + this._propertyViewStates = states; + }, + 'umbObservePropertyViewStates', ); this.observe( - structureManager.propertyWriteState.states, - (states) => (this._propertyWriteStates = states), + observeMultiple([structureManager.propertyWriteState.isRunning, structureManager.propertyWriteState.states]), + ([isEnabled, states]) => { + this._propertyWriteStateIsRunning = isEnabled; + this._propertyWriteStates = states; + }, 'umbObservePropertyWriteStates', ); } @@ -118,10 +131,15 @@ export class UmbBlockWorkspaceViewEditPropertiesElement extends UmbLitElement { } #getVisibleProperties() { - return this._propertyStructure?.filter((property) => this.#isVisiblePropertyType(property)) || []; + return this._propertyStructure?.filter((property) => this.#isViewablePropertyType(property)) || []; } - #isVisiblePropertyType(property: UmbPropertyTypeModel) { + #isViewablePropertyType(property: UmbPropertyTypeModel) { + // The state is not running, so the property is viewable by default. + if (this._propertyViewStateIsRunning === false) { + return true; + } + const propertyVariantId = this.#getPropertyVariantId(property); return this._propertyViewStates.some( (state) => state.propertyType.unique === property.unique && state.propertyType.variantId.equal(propertyVariantId), @@ -129,6 +147,11 @@ export class UmbBlockWorkspaceViewEditPropertiesElement extends UmbLitElement { } #isWritablePropertyType(property: UmbPropertyTypeModel) { + // The state is not running, so the property is writable by default. + if (this._propertyWriteStateIsRunning === false) { + return true; + } + const propertyVariantId = this.#getPropertyVariantId(property); return this._propertyWriteStates.some( (state) => state.propertyType.unique === property.unique && state.propertyType.variantId.equal(propertyVariantId), diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/content-editor-properties.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/content-editor-properties.element.ts index e39945f29192..d5bb9a3e92bf 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/content-editor-properties.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/content-editor-properties.element.ts @@ -15,6 +15,7 @@ import { type UmbVariantPropertyWriteState, } from '@umbraco-cms/backoffice/variant'; import { UMB_PROPERTY_DATASET_CONTEXT } from '@umbraco-cms/backoffice/property'; +import { observeMultiple } from '@umbraco-cms/backoffice/observable-api'; @customElement('umb-content-workspace-view-edit-properties') export class UmbContentWorkspaceViewEditPropertiesElement extends UmbLitElement { @@ -35,9 +36,15 @@ export class UmbContentWorkspaceViewEditPropertiesElement extends UmbLitElement @state() _dataPaths?: Array; + @state() + _propertyViewStateIsRunning = true; + @state() _propertyViewStates: Array = []; + @state() + _propertyWriteStateIsRunning = true; + @state() _propertyWriteStates: Array = []; @@ -51,14 +58,26 @@ export class UmbContentWorkspaceViewEditPropertiesElement extends UmbLitElement ); this.observe( - workspaceContext.structure.propertyViewState.states, - (states) => (this._propertyViewStates = states), + observeMultiple([ + workspaceContext.structure.propertyViewState.isRunning, + workspaceContext.structure.propertyViewState.states, + ]), + ([isRunning, states]) => { + this._propertyViewStateIsRunning = isRunning; + this._propertyViewStates = states; + }, 'umbObservePropertyViewStates', ); this.observe( - workspaceContext.structure.propertyWriteState.states, - (states) => (this._propertyWriteStates = states), + observeMultiple([ + workspaceContext.structure.propertyWriteState.isRunning, + workspaceContext.structure.propertyWriteState.states, + ]), + ([isEnabled, states]) => { + this._propertyWriteStateIsRunning = isEnabled; + this._propertyWriteStates = states; + }, 'umbObservePropertyWriteStates', ); }); @@ -91,10 +110,15 @@ export class UmbContentWorkspaceViewEditPropertiesElement extends UmbLitElement } #getVisibleProperties() { - return this._propertyStructure?.filter((property) => this.#isVisiblePropertyType(property)) || []; + return this._propertyStructure?.filter((property) => this.#isViewablePropertyType(property)) || []; } - #isVisiblePropertyType(property: UmbPropertyTypeModel) { + #isViewablePropertyType(property: UmbPropertyTypeModel) { + // The state is not running, so the property is viewable by default. + if (this._propertyViewStateIsRunning === false) { + return true; + } + const propertyVariantId = this.#getPropertyVariantId(property); return this._propertyViewStates.some( (state) => state.propertyType.unique === property.unique && state.propertyType.variantId.equal(propertyVariantId), @@ -102,6 +126,11 @@ export class UmbContentWorkspaceViewEditPropertiesElement extends UmbLitElement } #isWritablePropertyType(property: UmbPropertyTypeModel) { + // The state is not running, so the property is writable by default. + if (this._propertyWriteStateIsRunning === false) { + return true; + } + const propertyVariantId = this.#getPropertyVariantId(property); return this._propertyWriteStates.some( (state) => state.propertyType.unique === property.unique && state.propertyType.variantId.equal(propertyVariantId), diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property/property-view-state.manager.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property/property-view-state.manager.ts index b7d8fea74ab0..bb19e358fa97 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/property/property-view-state.manager.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property/property-view-state.manager.ts @@ -1,6 +1,6 @@ +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import type { UmbReferenceByUnique } from '@umbraco-cms/backoffice/models'; import { UmbStateManager, type UmbState } from '@umbraco-cms/backoffice/utils'; -import type { Observable } from '@umbraco-cms/backoffice/observable-api'; export interface UmbPropertyViewState extends UmbState { propertyType: UmbReferenceByUnique; @@ -9,6 +9,13 @@ export interface UmbPropertyViewState extends UmbState { export class UmbPropertyViewStateManager< ViewStateType extends UmbPropertyViewState = UmbPropertyViewState, > extends UmbStateManager { + constructor(host: UmbControllerHost) { + super(host); + // To avoid breaking changes in rendering this state is stopped by default. This means that properties are viewable by default. + // We start this state in workspaces where we want to control the viewability of properties. + this.stop(); + } + /** * Get the viewable state * @returns {Observable} True if the property is viewable diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property/property-write-state.manager.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property/property-write-state.manager.ts index 4f2e9d42e481..75cf2c047f7b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/property/property-write-state.manager.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property/property-write-state.manager.ts @@ -1,5 +1,6 @@ import { UmbStateManager, type UmbState } from '@umbraco-cms/backoffice/utils'; import type { UmbReferenceByUnique } from '@umbraco-cms/backoffice/models'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; export interface UmbPropertyWriteState extends UmbState { propertyType: UmbReferenceByUnique; @@ -8,6 +9,13 @@ export interface UmbPropertyWriteState extends UmbState { export class UmbPropertyWriteStateManager< WriteStateType extends UmbPropertyWriteState = UmbPropertyWriteState, > extends UmbStateManager { + constructor(host: UmbControllerHost) { + super(host); + // To avoid breaking changes in rendering this state is stopped by default. This means that properties are viewable by default. + // We start this state in workspaces where we want to control the writability of properties. + this.stop(); + } + /** * Get the writable state * @returns {Observable} True if the property is writable diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/utils/state-manager/state.manager.ts b/src/Umbraco.Web.UI.Client/src/packages/core/utils/state-manager/state.manager.ts index f86ef1fb0bc3..ba5230a818e3 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/utils/state-manager/state.manager.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/utils/state-manager/state.manager.ts @@ -1,6 +1,5 @@ import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; -import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { UmbArrayState } from '@umbraco-cms/backoffice/observable-api'; +import { UmbArrayState, UmbBooleanState } from '@umbraco-cms/backoffice/observable-api'; export interface UmbState { unique: string; @@ -15,6 +14,9 @@ export class UmbStateManager extends UmbC protected _states = new UmbArrayState([], (x) => x.unique); public states = this._states.asObservable(); + protected _isRunning = new UmbBooleanState(true); + public readonly isRunning = this._isRunning.asObservable(); + /** * Observable that emits true if there are any states in the state manager * @memberof UmbStateManager @@ -28,12 +30,30 @@ export class UmbStateManager extends UmbC public isOff = this._states.asObservablePart((x) => x.length === 0); /** - * Creates an instance of UmbStateManager. - * @param {UmbControllerHost} host + * Start the state - this will allow the state to be used. + * @memberof UmbPropertyWriteStateManager + */ + public start() { + this._states.unmute(); + this._isRunning.setValue(true); + } + + /** + * Stop the state - this will prevent the state from being used + * @memberof UmbPropertyWriteStateManager + */ + public stop() { + this._states.mute(); + this._isRunning.setValue(false); + } + + /** + * Get whether the state is running + * @returns {boolean} True if the state is running * @memberof UmbStateManager */ - constructor(host: UmbControllerHost) { - super(host); + public getIsRunning(): boolean { + return this._isRunning.getValue(); } /** @@ -112,7 +132,8 @@ export class UmbStateManager extends UmbC } override destroy() { - super.destroy(); this._states.destroy(); + this._isRunning.destroy(); + super.destroy(); } } 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 a44503f70cbe..c021c9a39899 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 @@ -87,6 +87,11 @@ export class UmbDocumentWorkspaceContext saveModalToken: UMB_DOCUMENT_SAVE_MODAL, }); + /* Start the property view and write states for the document workspace. This means that the properties are not viewable or writable by default + but requires an entry in the state to be able to view or write to the properties. */ + this.structure.propertyViewState.start(); + this.structure.propertyWriteState.start(); + this.observe(this.contentTypeUnique, (unique) => this.structure.loadType(unique), null); // TODO: Remove this in v17 as we have moved the publishing methods to the UMB_DOCUMENT_PUBLISHING_WORKSPACE_CONTEXT. From e56eb09dbdcf65979cc9b5b1b50a09709403a76a Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 24 Mar 2025 08:22:12 +0100 Subject: [PATCH 093/106] add tests for start and stopping a state --- .../utils/state-manager/state.manager.test.ts | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/utils/state-manager/state.manager.test.ts b/src/Umbraco.Web.UI.Client/src/packages/core/utils/state-manager/state.manager.test.ts index 1b93daeaeeaf..ce7e62e25d29 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/utils/state-manager/state.manager.test.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/utils/state-manager/state.manager.test.ts @@ -33,6 +33,14 @@ describe('UmbSelectionManager', () => { }); describe('methods', () => { + it('has a start method', () => { + expect(manager).to.have.property('start').that.is.a('function'); + }); + + it('has a stop method', () => { + expect(manager).to.have.property('stop').that.is.a('function'); + }); + it('has a addState method', () => { expect(manager).to.have.property('addState').that.is.a('function'); }); @@ -89,6 +97,11 @@ describe('UmbSelectionManager', () => { }) .unsubscribe(); }); + + it('throws an error if the state manager is not running', () => { + manager.stop(); + expect(() => manager.addState(state1)).to.throw(); + }); }); describe('Remove State', () => { @@ -168,4 +181,19 @@ describe('UmbSelectionManager', () => { expect(manager.getIsOff()).to.be.false; }); }); + + describe('start', () => { + it('starts the state manager', () => { + manager.stop(); + manager.start(); + expect(manager.getIsRunning()).to.be.true; + }); + }); + + describe('stop', () => { + it('stops the state manager', () => { + manager.stop(); + expect(manager.getIsRunning()).to.be.false; + }); + }); }); From df8b3cd2d2c98d3e2e8c9b43834b52d8ce8b2253 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 24 Mar 2025 08:22:36 +0100 Subject: [PATCH 094/106] throw errors if adding to a state that is not running --- .../core/utils/state-manager/state.manager.ts | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/utils/state-manager/state.manager.ts b/src/Umbraco.Web.UI.Client/src/packages/core/utils/state-manager/state.manager.ts index ba5230a818e3..c847fac3fc6d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/utils/state-manager/state.manager.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/utils/state-manager/state.manager.ts @@ -31,7 +31,6 @@ export class UmbStateManager extends UmbC /** * Start the state - this will allow the state to be used. - * @memberof UmbPropertyWriteStateManager */ public start() { this._states.unmute(); @@ -40,7 +39,6 @@ export class UmbStateManager extends UmbC /** * Stop the state - this will prevent the state from being used - * @memberof UmbPropertyWriteStateManager */ public stop() { this._states.mute(); @@ -62,6 +60,10 @@ export class UmbStateManager extends UmbC * @memberof UmbStateManager */ addState(state: StateType) { + if (this.getIsRunning() === false) { + throw new Error('State manager is not running. Call start() before adding states'); + } + if (!state) throw new Error('State must be defined'); if (!state.unique) throw new Error('State must have a unique property'); if (this._states.getValue().find((x) => x.unique === state.unique)) { throw new Error('State with unique already exists'); @@ -75,12 +77,16 @@ export class UmbStateManager extends UmbC * @memberof UmbStateManager */ addStates(states: StateType[]) { + if (this.getIsRunning() === false) { + throw new Error('State manager is not running. Call start() before adding states'); + } + states.forEach((state) => this.addState(state)); } /** * Remove a state from the state manager - * @param {StateType['unique']} unique + * @param {StateType['unique']} unique Unique value of the state to remove * @memberof UmbStateManager */ removeState(unique: StateType['unique']) { @@ -89,7 +95,7 @@ export class UmbStateManager extends UmbC /** * Remove multiple states from the state manager - * @param {StateType['unique'][]} uniques + * @param {StateType['unique'][]} uniques Array of unique values to remove * @memberof UmbStateManager */ removeStates(uniques: StateType['unique'][]) { From 84f442bf637563b785b69b50a05e1089176c2521 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 24 Mar 2025 08:22:46 +0100 Subject: [PATCH 095/106] export consts --- .../user-permissions/document-property-value/constants.ts | 2 ++ .../src/packages/media/media/constants.ts | 7 ++++++- .../src/packages/members/member/constants.ts | 6 +++++- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/constants.ts index 2a87652aa032..caeaf45c4c61 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/constants.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/constants.ts @@ -1,2 +1,4 @@ export const UMB_USER_PERMISSION_DOCUMENT_PROPERTY_VALUE_READ = 'Umb.Document.PropertyValue.Read'; export const UMB_USER_PERMISSION_DOCUMENT_PROPERTY_VALUE_WRITE = 'Umb.Document.PropertyValue.Write'; + +export * from './conditions/constants.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/constants.ts index 5b8f281fe258..bb8d65901c8f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/constants.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/constants.ts @@ -15,4 +15,9 @@ export * from './workspace/constants.js'; export * from './paths.js'; export { UMB_MEDIA_VARIANT_CONTEXT } from './property-dataset-context/media-property-dataset-context.token.js'; -export { UMB_MEDIA_ENTITY_TYPE, UMB_MEDIA_ROOT_ENTITY_TYPE, UMB_MEDIA_PLACEHOLDER_ENTITY_TYPE } from './entity.js'; +export { + UMB_MEDIA_ENTITY_TYPE, + UMB_MEDIA_ROOT_ENTITY_TYPE, + UMB_MEDIA_PLACEHOLDER_ENTITY_TYPE, + UMB_MEDIA_PROPERTY_VALUE_ENTITY_TYPE, +} from './entity.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/constants.ts index c2e40ebfe7fd..e457c9c89a42 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member/constants.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/constants.ts @@ -1,4 +1,8 @@ -export { UMB_MEMBER_ENTITY_TYPE, UMB_MEMBER_ROOT_ENTITY_TYPE } from './entity.js'; +export { + UMB_MEMBER_ENTITY_TYPE, + UMB_MEMBER_ROOT_ENTITY_TYPE, + UMB_MEMBER_PROPERTY_VALUE_ENTITY_TYPE, +} from './entity.js'; export { UMB_MEMBER_VARIANT_CONTEXT } from './property-dataset-context/member-property-dataset.context-token.js'; export * from './collection/constants.js'; From 04764340f7f5e8750bfa05817d4864fab0ec1139 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 24 Mar 2025 08:29:37 +0100 Subject: [PATCH 096/106] export consts --- .../user-permissions/document-property-value/constants.ts | 6 ++++-- .../constants.ts | 2 ++ .../property-type-modal/constants.ts | 2 ++ .../property-type-modal/index.ts | 1 - 4 files changed, 8 insertions(+), 3 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-permission-flow-modal/constants.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-permission-flow-modal/property-type-modal/index.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/constants.ts index caeaf45c4c61..c6eda198592f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/constants.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/constants.ts @@ -1,4 +1,6 @@ +export * from './conditions/constants.js'; +export * from './document-property-value-permission-flow-modal/constants.js'; +export { UMB_DOCUMENT_PROPERTY_VALUE_USER_PERMISSION_TYPE } from './user-permission.js'; + export const UMB_USER_PERMISSION_DOCUMENT_PROPERTY_VALUE_READ = 'Umb.Document.PropertyValue.Read'; export const UMB_USER_PERMISSION_DOCUMENT_PROPERTY_VALUE_WRITE = 'Umb.Document.PropertyValue.Write'; - -export * from './conditions/constants.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-permission-flow-modal/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-permission-flow-modal/constants.ts new file mode 100644 index 000000000000..5dac179a5893 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-permission-flow-modal/constants.ts @@ -0,0 +1,2 @@ +export { UMB_DOCUMENT_PROPERTY_VALUE_USER_PERMISSION_FLOW_MODAL } from './document-property-value-permission-flow-modal.token.js'; +export * from './property-type-modal/constants.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-permission-flow-modal/property-type-modal/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-permission-flow-modal/property-type-modal/constants.ts index 80d43fb26c7d..d04c37bf9713 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-permission-flow-modal/property-type-modal/constants.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-permission-flow-modal/property-type-modal/constants.ts @@ -1,2 +1,4 @@ +export { UMB_DOCUMENT_PROPERTY_VALUE_USER_PERMISSION_FLOW_PROPERTY_TYPE_MODAL } from './property-type-modal.token.js'; + export const UMB_DOCUMENT_PROPERTY_VALUE_USER_PERMISSION_FLOW_PROPERTY_TYPE_MODAL_ALIAS = 'Umb.Modal.DocumentPropertyValueUserPermissionFlow.PropertyType'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-permission-flow-modal/property-type-modal/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-permission-flow-modal/property-type-modal/index.ts deleted file mode 100644 index e711dbfbfc77..000000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-permission-flow-modal/property-type-modal/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { UMB_DOCUMENT_PROPERTY_VALUE_USER_PERMISSION_FLOW_PROPERTY_TYPE_MODAL } from './property-type-modal.token.js'; From 87be7d2d83a46791412c9b6c108bef4dad7d15f8 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 24 Mar 2025 08:44:20 +0100 Subject: [PATCH 097/106] fix circular --- .../property-type-modal/constants.ts | 4 +--- .../property-type-modal/manifests.ts | 4 +++- .../property-type-modal/property-type-modal.token.ts | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-permission-flow-modal/property-type-modal/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-permission-flow-modal/property-type-modal/constants.ts index d04c37bf9713..b30d1cbca3d6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-permission-flow-modal/property-type-modal/constants.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-permission-flow-modal/property-type-modal/constants.ts @@ -1,4 +1,2 @@ +export { UMB_DOCUMENT_PROPERTY_VALUE_USER_PERMISSION_FLOW_PROPERTY_TYPE_MODAL_ALIAS } from './manifests.js'; export { UMB_DOCUMENT_PROPERTY_VALUE_USER_PERMISSION_FLOW_PROPERTY_TYPE_MODAL } from './property-type-modal.token.js'; - -export const UMB_DOCUMENT_PROPERTY_VALUE_USER_PERMISSION_FLOW_PROPERTY_TYPE_MODAL_ALIAS = - 'Umb.Modal.DocumentPropertyValueUserPermissionFlow.PropertyType'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-permission-flow-modal/property-type-modal/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-permission-flow-modal/property-type-modal/manifests.ts index 53589f52552a..7ddec3db6683 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-permission-flow-modal/property-type-modal/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-permission-flow-modal/property-type-modal/manifests.ts @@ -1,6 +1,8 @@ -import { UMB_DOCUMENT_PROPERTY_VALUE_USER_PERMISSION_FLOW_PROPERTY_TYPE_MODAL_ALIAS } from './constants.js'; import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; +export const UMB_DOCUMENT_PROPERTY_VALUE_USER_PERMISSION_FLOW_PROPERTY_TYPE_MODAL_ALIAS = + 'Umb.Modal.DocumentPropertyValueUserPermissionFlow.PropertyType'; + export const manifests: Array = [ { type: 'modal', diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-permission-flow-modal/property-type-modal/property-type-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-permission-flow-modal/property-type-modal/property-type-modal.token.ts index a9701f8c369c..9ea7fbf02247 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-permission-flow-modal/property-type-modal/property-type-modal.token.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/document-property-value-permission-flow-modal/property-type-modal/property-type-modal.token.ts @@ -1,4 +1,4 @@ -import { UMB_DOCUMENT_PROPERTY_VALUE_USER_PERMISSION_FLOW_PROPERTY_TYPE_MODAL_ALIAS } from './constants.js'; +import { UMB_DOCUMENT_PROPERTY_VALUE_USER_PERMISSION_FLOW_PROPERTY_TYPE_MODAL_ALIAS } from './manifests.js'; import type { UmbPropertyTypeModel } from '@umbraco-cms/backoffice/content-type'; import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; From 44b0a789aaf29b3cd2f46df0539df652272a3284 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 24 Mar 2025 08:58:30 +0100 Subject: [PATCH 098/106] fix circular --- .../edit/block-workspace-view-edit-properties.element.ts | 7 ++----- .../structure/content-type-structure-manager.class.ts | 2 +- .../views/edit/content-editor-properties.element.ts | 7 ++----- .../src/packages/core/property/index.ts | 3 +++ .../variant-property-view-state.manager.ts | 4 ++-- .../variant-property-write-state.manager.ts | 4 ++-- .../src/packages/core/variant/index.ts | 2 -- ...ent-property-value-user-permission.workspace-context.ts | 7 ++----- 8 files changed, 14 insertions(+), 22 deletions(-) rename src/Umbraco.Web.UI.Client/src/packages/core/{variant => property}/variant-property-view-state.manager.ts (76%) rename src/Umbraco.Web.UI.Client/src/packages/core/{variant => property}/variant-property-write-state.manager.ts (76%) diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/views/edit/block-workspace-view-edit-properties.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/views/edit/block-workspace-view-edit-properties.element.ts index c4f1f66242aa..6debd6e580fd 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/views/edit/block-workspace-view-edit-properties.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/views/edit/block-workspace-view-edit-properties.element.ts @@ -5,11 +5,8 @@ import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import type { UmbContentTypeModel, UmbPropertyTypeModel } from '@umbraco-cms/backoffice/content-type'; import { UmbContentTypePropertyStructureHelper } from '@umbraco-cms/backoffice/content-type'; import { UmbLitElement, umbDestroyOnDisconnect } from '@umbraco-cms/backoffice/lit-element'; -import { - UmbVariantId, - type UmbVariantPropertyViewState, - type UmbVariantPropertyWriteState, -} from '@umbraco-cms/backoffice/variant'; +import type { UmbVariantPropertyViewState, UmbVariantPropertyWriteState } from '@umbraco-cms/backoffice/property'; +import { UmbVariantId } from '@umbraco-cms/backoffice/variant'; import { UmbDataPathPropertyValueQuery } from '@umbraco-cms/backoffice/validation'; import { observeMultiple } from '@umbraco-cms/backoffice/observable-api'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/structure/content-type-structure-manager.class.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/structure/content-type-structure-manager.class.ts index 0e3f852a0187..342a37b39dda 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/structure/content-type-structure-manager.class.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/structure/content-type-structure-manager.class.ts @@ -22,7 +22,7 @@ import { umbExtensionsRegistry, type ManifestRepository } from '@umbraco-cms/bac import { UmbVariantPropertyViewStateManager, UmbVariantPropertyWriteStateManager, -} from '@umbraco-cms/backoffice/variant'; +} from '@umbraco-cms/backoffice/property'; type UmbPropertyTypeId = UmbPropertyTypeModel['id']; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/content-editor-properties.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/content-editor-properties.element.ts index d5bb9a3e92bf..bd2e550894e4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/content-editor-properties.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/content-editor-properties.element.ts @@ -9,11 +9,8 @@ import { UmbContentTypePropertyStructureHelper } from '@umbraco-cms/backoffice/c import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UmbDataPathPropertyValueQuery } from '@umbraco-cms/backoffice/validation'; import { UMB_PROPERTY_STRUCTURE_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace'; -import { - UmbVariantId, - type UmbVariantPropertyViewState, - type UmbVariantPropertyWriteState, -} from '@umbraco-cms/backoffice/variant'; +import { UmbVariantId } from '@umbraco-cms/backoffice/variant'; +import type { UmbVariantPropertyViewState, UmbVariantPropertyWriteState } from '@umbraco-cms/backoffice/property'; import { UMB_PROPERTY_DATASET_CONTEXT } from '@umbraco-cms/backoffice/property'; import { observeMultiple } from '@umbraco-cms/backoffice/observable-api'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property/index.ts index c7376d55ca65..a415c0e81df0 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/property/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property/index.ts @@ -7,4 +7,7 @@ export * from './property-view-state.manager.js'; export * from './property-write-state.manager.js'; export * from './property-view-state.manager.js'; export * from './property-write-state.manager.js'; +export * from './variant-property-view-state.manager.js'; +export * from './variant-property-write-state.manager.js'; + export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/variant/variant-property-view-state.manager.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property/variant-property-view-state.manager.ts similarity index 76% rename from src/Umbraco.Web.UI.Client/src/packages/core/variant/variant-property-view-state.manager.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/property/variant-property-view-state.manager.ts index df8c12874fb4..ec38d7904d28 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/variant/variant-property-view-state.manager.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property/variant-property-view-state.manager.ts @@ -1,6 +1,6 @@ -import type { UmbReferenceByVariantId } from './types.js'; +import { UmbPropertyViewStateManager, type UmbPropertyViewState } from './property-view-state.manager.js'; import type { UmbReferenceByUnique } from '@umbraco-cms/backoffice/models'; -import { UmbPropertyViewStateManager, type UmbPropertyViewState } from '@umbraco-cms/backoffice/property'; +import type { UmbReferenceByVariantId } from '@umbraco-cms/backoffice/variant'; export interface UmbVariantPropertyViewState extends UmbPropertyViewState { propertyType: UmbReferenceByUnique & UmbReferenceByVariantId; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/variant/variant-property-write-state.manager.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property/variant-property-write-state.manager.ts similarity index 76% rename from src/Umbraco.Web.UI.Client/src/packages/core/variant/variant-property-write-state.manager.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/property/variant-property-write-state.manager.ts index 14de48496b7a..a6aaa1320d44 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/variant/variant-property-write-state.manager.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property/variant-property-write-state.manager.ts @@ -1,6 +1,6 @@ -import type { UmbReferenceByVariantId } from './types.js'; -import { UmbPropertyWriteStateManager, type UmbPropertyWriteState } from '@umbraco-cms/backoffice/property'; +import { UmbPropertyWriteStateManager, type UmbPropertyWriteState } from './property-write-state.manager.js'; import type { UmbReferenceByUnique } from '@umbraco-cms/backoffice/models'; +import type { UmbReferenceByVariantId } from '@umbraco-cms/backoffice/variant'; export interface UmbVariantPropertyWriteState extends UmbPropertyWriteState { propertyType: UmbReferenceByUnique & UmbReferenceByVariantId; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/variant/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/variant/index.ts index 1640f73a84a8..5a6c69cbf2ec 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/variant/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/variant/index.ts @@ -1,5 +1,3 @@ export * from './variant-id.class.js'; export * from './variant-object-compare.function.js'; -export * from './variant-property-view-state.manager.js'; -export * from './variant-property-write-state.manager.js'; export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/workspace-context/document-property-value-user-permission.workspace-context.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/workspace-context/document-property-value-user-permission.workspace-context.ts index 3058224ef9ca..c8beb7e882ba 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/workspace-context/document-property-value-user-permission.workspace-context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/workspace-context/document-property-value-user-permission.workspace-context.ts @@ -8,11 +8,8 @@ import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { observeMultiple } from '@umbraco-cms/backoffice/observable-api'; import { createExtensionApiByAlias } from '@umbraco-cms/backoffice/extension-registry'; -import { - UmbVariantId, - type UmbVariantPropertyViewState, - type UmbVariantPropertyWriteState, -} from '@umbraco-cms/backoffice/variant'; +import { UmbVariantId } from '@umbraco-cms/backoffice/variant'; +import type { UmbVariantPropertyViewState, UmbVariantPropertyWriteState } from '@umbraco-cms/backoffice/property'; import type { UmbPropertyTypeModel } from '@umbraco-cms/backoffice/content-type'; import type { UmbStateManager } from '@umbraco-cms/backoffice/utils'; import { UMB_BLOCK_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/block'; From d08eb3e505c276e8b146e401bcb7ed6c51baaa0d Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 24 Mar 2025 10:55:47 +0100 Subject: [PATCH 099/106] set the entity type when setting values --- .../content/workspace/content-detail-workspace-base.ts | 10 +++++++++- .../src/packages/documents/documents/entity.ts | 2 +- .../src/packages/media/media/entity.ts | 2 +- .../src/packages/members/member/entity.ts | 2 +- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/content-detail-workspace-base.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/content-detail-workspace-base.ts index 197aa90498ba..3f5962b71d90 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/content-detail-workspace-base.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/content-detail-workspace-base.ts @@ -503,7 +503,15 @@ export abstract class UmbContentDetailWorkspaceContextBase< } // Notice the order of the properties is important for our JSON String Compare function. [NL] - const entry = { editorAlias, ...variantId.toObject(), alias, value } as UmbElementValueModel; + const entry: UmbElementValueModel = { + editorAlias, + // Be aware that this solution is a bit magical, and based on a naming convention. + // We might want to make this more flexible at some point and get the entityType from somewhere instead of constructing it here. + entityType: `${this.getEntityType()}-property-value`, + ...variantId.toObject(), + alias, + value, + }; const currentData = this.getData(); if (currentData) { diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity.ts index ff1bbcf4c5dd..e805d28f3f8e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity.ts @@ -7,5 +7,5 @@ export type UmbDocumentRootEntityType = typeof UMB_DOCUMENT_ROOT_ENTITY_TYPE; export type UmbDocumentEntityTypeUnion = UmbDocumentEntityType | UmbDocumentRootEntityType; // TODO: move this to a better location inside the document module -export const UMB_DOCUMENT_PROPERTY_VALUE_ENTITY_TYPE = 'document-property-value'; +export const UMB_DOCUMENT_PROPERTY_VALUE_ENTITY_TYPE = `${UMB_DOCUMENT_ENTITY_TYPE}-property-value`; export type UmbDocumentPropertyValueEntityType = typeof UMB_DOCUMENT_PROPERTY_VALUE_ENTITY_TYPE; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/entity.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/entity.ts index 11775327fbd8..d13b1eac8d21 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/entity.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/entity.ts @@ -10,5 +10,5 @@ export type UmbMediaPlaceholderEntityType = typeof UMB_MEDIA_PLACEHOLDER_ENTITY_ export type UmbMediaEntityTypeUnion = UmbMediaEntityType | UmbMediaRootEntityType; // TODO: move this to a better location inside the media module -export const UMB_MEDIA_PROPERTY_VALUE_ENTITY_TYPE = 'media-property-value'; +export const UMB_MEDIA_PROPERTY_VALUE_ENTITY_TYPE = `${UMB_MEDIA_ENTITY_TYPE}-property-value`; export type UmbMediaPropertyValueEntityType = typeof UMB_MEDIA_PROPERTY_VALUE_ENTITY_TYPE; diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/entity.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/entity.ts index 59dd937a22c8..ff071dabbc5a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member/entity.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/entity.ts @@ -5,5 +5,5 @@ export type UmbMemberEntityType = typeof UMB_MEMBER_ENTITY_TYPE; export type UmbMemberRootEntityType = typeof UMB_MEMBER_ROOT_ENTITY_TYPE; // TODO: move this to a better location inside the member module -export const UMB_MEMBER_PROPERTY_VALUE_ENTITY_TYPE = 'member-property-value'; +export const UMB_MEMBER_PROPERTY_VALUE_ENTITY_TYPE = `${UMB_MEMBER_ENTITY_TYPE}-property-value`; export type UmbMemberPropertyValueEntityType = typeof UMB_MEMBER_PROPERTY_VALUE_ENTITY_TYPE; From 654f8b0bdd19cae67996d1cc7fc63810dcf27a05 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 25 Mar 2025 11:22:33 +0100 Subject: [PATCH 100/106] only apply for block in document values --- ...operty-value-user-permission.workspace-context.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/workspace-context/document-property-value-user-permission.workspace-context.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/workspace-context/document-property-value-user-permission.workspace-context.ts index c8beb7e882ba..4e8f631fed75 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/workspace-context/document-property-value-user-permission.workspace-context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/workspace-context/document-property-value-user-permission.workspace-context.ts @@ -27,11 +27,17 @@ export class UmbDocumentPropertyValueUserPermissionWorkspaceContext extends UmbC this.#observeDocumentProperties(); }); - // TODO: investigate if block workspace can provide a property structure context so we can use the same context for both block and document - // TODO: only apply to blocks within a document this.consumeContext(UMB_BLOCK_WORKSPACE_CONTEXT, async (context) => { this.#blockWorkspaceContext = context; - this.#observeDocumentBlockProperties(); + + // We only want to apply the permission logic if the block is in a document + const documentWorkspaceContext = await this.consumeContext(UMB_DOCUMENT_WORKSPACE_CONTEXT, () => {}) + .passContextAliasMatches() + .asPromise(); + + if (documentWorkspaceContext) { + this.#observeDocumentBlockProperties(); + } }); } From 0172302a25d658a7b7b076a8624593d771e3dd8a Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 25 Mar 2025 11:56:44 +0100 Subject: [PATCH 101/106] split logic --- ...value-user-permission.workspace-context.ts | 52 ++++++++ ...value-user-permission.workspace-context.ts | 120 +----------------- .../workspace-context/manifests.ts | 2 +- ...-user-permission-workspace-context-base.ts | 81 ++++++++++++ 4 files changed, 137 insertions(+), 118 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/workspace-context/document-block-property-value-user-permission.workspace-context.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/workspace-context/property-value-user-permission-workspace-context-base.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/workspace-context/document-block-property-value-user-permission.workspace-context.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/workspace-context/document-block-property-value-user-permission.workspace-context.ts new file mode 100644 index 000000000000..3d5c22d38706 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/workspace-context/document-block-property-value-user-permission.workspace-context.ts @@ -0,0 +1,52 @@ +import { UMB_DOCUMENT_WORKSPACE_CONTEXT } from '../../../workspace/constants.js'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import { observeMultiple } from '@umbraco-cms/backoffice/observable-api'; +import { UMB_BLOCK_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/block'; +import { UMB_PROPERTY_DATASET_CONTEXT } from '@umbraco-cms/backoffice/property'; +import { UmbPropertyValueUserPermissionWorkspaceContextBase } from './property-value-user-permission-workspace-context-base.js'; + +export class UmbDocumentBlockPropertyValueUserPermissionWorkspaceContext extends UmbPropertyValueUserPermissionWorkspaceContextBase { + #blockWorkspaceContext?: typeof UMB_BLOCK_WORKSPACE_CONTEXT.TYPE; + + constructor(host: UmbControllerHost) { + super(host); + + this.consumeContext(UMB_BLOCK_WORKSPACE_CONTEXT, async (context) => { + this.#blockWorkspaceContext = context; + + // We only want to apply the permission logic if the block is in a document + const documentWorkspaceContext = await this.consumeContext(UMB_DOCUMENT_WORKSPACE_CONTEXT, () => {}) + .passContextAliasMatches() + .asPromise(); + + if (documentWorkspaceContext) { + this.#observeDocumentBlockProperties(); + } + }); + } + + async #observeDocumentBlockProperties() { + if (!this.#blockWorkspaceContext) return; + const datasetContext = await this.getContext(UMB_PROPERTY_DATASET_CONTEXT); + if (!datasetContext) return; + + const structureManager = this.#blockWorkspaceContext.content.structure; + + this.observe( + observeMultiple([structureManager.contentTypeProperties, this.#blockWorkspaceContext.variantId]), + ([properties, variantId]) => { + if (properties.length === 0) return; + if (!variantId) return; + + this._setPermissions( + properties, + [variantId], + structureManager.propertyViewState, + structureManager.propertyWriteState, + ); + }, + ); + } +} + +export { UmbDocumentBlockPropertyValueUserPermissionWorkspaceContext as api }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/workspace-context/document-property-value-user-permission.workspace-context.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/workspace-context/document-property-value-user-permission.workspace-context.ts index 4e8f631fed75..83f587a2ee7c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/workspace-context/document-property-value-user-permission.workspace-context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/workspace-context/document-property-value-user-permission.workspace-context.ts @@ -1,23 +1,11 @@ import { UMB_DOCUMENT_WORKSPACE_CONTEXT } from '../../../workspace/constants.js'; -import { UMB_DOCUMENT_PROPERTY_VALUE_USER_PERMISSION_CONDITION_ALIAS } from '../conditions/constants.js'; -import { - UMB_USER_PERMISSION_DOCUMENT_PROPERTY_VALUE_READ, - UMB_USER_PERMISSION_DOCUMENT_PROPERTY_VALUE_WRITE, -} from '../constants.js'; -import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { observeMultiple } from '@umbraco-cms/backoffice/observable-api'; -import { createExtensionApiByAlias } from '@umbraco-cms/backoffice/extension-registry'; import { UmbVariantId } from '@umbraco-cms/backoffice/variant'; -import type { UmbVariantPropertyViewState, UmbVariantPropertyWriteState } from '@umbraco-cms/backoffice/property'; -import type { UmbPropertyTypeModel } from '@umbraco-cms/backoffice/content-type'; -import type { UmbStateManager } from '@umbraco-cms/backoffice/utils'; -import { UMB_BLOCK_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/block'; -import { UMB_PROPERTY_DATASET_CONTEXT } from '@umbraco-cms/backoffice/property'; +import { UmbPropertyValueUserPermissionWorkspaceContextBase } from './property-value-user-permission-workspace-context-base.js'; -export class UmbDocumentPropertyValueUserPermissionWorkspaceContext extends UmbControllerBase { +export class UmbDocumentPropertyValueUserPermissionWorkspaceContext extends UmbPropertyValueUserPermissionWorkspaceContextBase { #documentWorkspaceContext?: typeof UMB_DOCUMENT_WORKSPACE_CONTEXT.TYPE; - #blockWorkspaceContext?: typeof UMB_BLOCK_WORKSPACE_CONTEXT.TYPE; constructor(host: UmbControllerHost) { super(host); @@ -26,19 +14,6 @@ export class UmbDocumentPropertyValueUserPermissionWorkspaceContext extends UmbC this.#documentWorkspaceContext = context; this.#observeDocumentProperties(); }); - - this.consumeContext(UMB_BLOCK_WORKSPACE_CONTEXT, async (context) => { - this.#blockWorkspaceContext = context; - - // We only want to apply the permission logic if the block is in a document - const documentWorkspaceContext = await this.consumeContext(UMB_DOCUMENT_WORKSPACE_CONTEXT, () => {}) - .passContextAliasMatches() - .asPromise(); - - if (documentWorkspaceContext) { - this.#observeDocumentBlockProperties(); - } - }); } #observeDocumentProperties() { @@ -57,7 +32,7 @@ export class UmbDocumentPropertyValueUserPermissionWorkspaceContext extends UmbC const variantIds = variantOptions?.map((variant) => new UmbVariantId(variant.culture, variant.segment)); - this.#setPermissions( + this._setPermissions( properties, variantIds, structureManager.propertyViewState, @@ -66,95 +41,6 @@ export class UmbDocumentPropertyValueUserPermissionWorkspaceContext extends UmbC }, ); } - - async #observeDocumentBlockProperties() { - if (!this.#blockWorkspaceContext) return; - const datasetContext = await this.getContext(UMB_PROPERTY_DATASET_CONTEXT); - if (!datasetContext) return; - - const structureManager = this.#blockWorkspaceContext.content.structure; - - this.observe( - observeMultiple([structureManager.contentTypeProperties, this.#blockWorkspaceContext.variantId]), - ([properties, variantId]) => { - if (properties.length === 0) return; - if (!variantId) return; - - this.#setPermissions( - properties, - [variantId], - structureManager.propertyViewState, - structureManager.propertyWriteState, - ); - }, - ); - } - - #setPermissions( - properties: Array, - variantIds: Array, - propertyVisibilityState: UmbStateManager, - propertyWriteState: UmbStateManager, - ) { - properties.forEach((property) => { - this.#setPermissionForProperty({ - verb: UMB_USER_PERMISSION_DOCUMENT_PROPERTY_VALUE_READ, - stateManager: propertyVisibilityState, - property, - variantIds, - }); - - this.#setPermissionForProperty({ - verb: UMB_USER_PERMISSION_DOCUMENT_PROPERTY_VALUE_WRITE, - stateManager: propertyWriteState, - property, - variantIds, - }); - }); - } - - #setPermissionForProperty(args: { - verb: string; - stateManager: UmbStateManager; - property: UmbPropertyTypeModel; - variantIds: Array; - }) { - createExtensionApiByAlias(this, UMB_DOCUMENT_PROPERTY_VALUE_USER_PERMISSION_CONDITION_ALIAS, [ - { - config: { - allOf: [args.verb], - match: { - propertyType: { - unique: args.property.unique, - }, - }, - }, - onChange: (permitted: boolean) => { - // If the property is invariant we only need one state for the property - const isInvariant = args.property.variesByCulture === false && args.property.variesBySegment === false; - const variantIds = isInvariant ? [new UmbVariantId()] : args.variantIds; - - const states: Array = - variantIds?.map((variantId) => { - return { - unique: 'UMB_PROPERTY_' + args.property.unique + '_' + variantId.toString(), - message: '', - propertyType: { - unique: args.property.unique, - variantId, - }, - }; - }) || []; - - if (permitted) { - args.stateManager.addStates(states); - } else { - args.stateManager.removeStates(states.map((state) => state.unique)); - } - }, - }, - ]); - } } export { UmbDocumentPropertyValueUserPermissionWorkspaceContext as api }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/workspace-context/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/workspace-context/manifests.ts index 2877f6230d67..78a7953b7d3b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/workspace-context/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/workspace-context/manifests.ts @@ -20,7 +20,7 @@ export const manifests: Array = type: 'workspaceContext', name: 'Document Property Value User Permission Block Workspace Context', alias: 'Umb.WorkspaceContext.Block.DocumentPropertyValueUserPermission', - api: () => import('./document-property-value-user-permission.workspace-context.js'), + api: () => import('./document-block-property-value-user-permission.workspace-context.js'), conditions: [ { alias: UMB_WORKSPACE_CONDITION_ALIAS, diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/workspace-context/property-value-user-permission-workspace-context-base.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/workspace-context/property-value-user-permission-workspace-context-base.ts new file mode 100644 index 000000000000..815b003899b7 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/workspace-context/property-value-user-permission-workspace-context-base.ts @@ -0,0 +1,81 @@ +import { UMB_DOCUMENT_PROPERTY_VALUE_USER_PERMISSION_CONDITION_ALIAS } from '../conditions/constants.js'; +import { + UMB_USER_PERMISSION_DOCUMENT_PROPERTY_VALUE_READ, + UMB_USER_PERMISSION_DOCUMENT_PROPERTY_VALUE_WRITE, +} from '../constants.js'; +import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; +import { createExtensionApiByAlias } from '@umbraco-cms/backoffice/extension-registry'; +import { UmbVariantId } from '@umbraco-cms/backoffice/variant'; +import type { UmbVariantPropertyViewState, UmbVariantPropertyWriteState } from '@umbraco-cms/backoffice/property'; +import type { UmbPropertyTypeModel } from '@umbraco-cms/backoffice/content-type'; +import type { UmbStateManager } from '@umbraco-cms/backoffice/utils'; + +export class UmbPropertyValueUserPermissionWorkspaceContextBase extends UmbControllerBase { + protected _setPermissions( + properties: Array, + variantIds: Array, + propertyVisibilityState: UmbStateManager, + propertyWriteState: UmbStateManager, + ) { + properties.forEach((property) => { + this.#setPermissionForProperty({ + verb: UMB_USER_PERMISSION_DOCUMENT_PROPERTY_VALUE_READ, + stateManager: propertyVisibilityState, + property, + variantIds, + }); + + this.#setPermissionForProperty({ + verb: UMB_USER_PERMISSION_DOCUMENT_PROPERTY_VALUE_WRITE, + stateManager: propertyWriteState, + property, + variantIds, + }); + }); + } + + #setPermissionForProperty(args: { + verb: string; + stateManager: UmbStateManager; + property: UmbPropertyTypeModel; + variantIds: Array; + }) { + createExtensionApiByAlias(this, UMB_DOCUMENT_PROPERTY_VALUE_USER_PERMISSION_CONDITION_ALIAS, [ + { + config: { + allOf: [args.verb], + match: { + propertyType: { + unique: args.property.unique, + }, + }, + }, + onChange: (permitted: boolean) => { + // If the property is invariant we only need one state for the property + const isInvariant = args.property.variesByCulture === false && args.property.variesBySegment === false; + const variantIds = isInvariant ? [new UmbVariantId()] : args.variantIds; + + const states: Array = + variantIds?.map((variantId) => { + return { + unique: 'UMB_PROPERTY_' + args.property.unique + '_' + variantId.toString(), + message: '', + propertyType: { + unique: args.property.unique, + variantId, + }, + }; + }) || []; + + if (permitted) { + args.stateManager.addStates(states); + } else { + args.stateManager.removeStates(states.map((state) => state.unique)); + } + }, + }, + ]); + } +} + +export { UmbPropertyValueUserPermissionWorkspaceContextBase as api }; From 2dab66ec106be75b9ea8b0cf16d09452083f13f7 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 25 Mar 2025 12:16:21 +0100 Subject: [PATCH 102/106] start states for document blocks --- .../block/document-block.workspace-context.ts | 32 +++++++++++++++++++ .../documents/documents/block/manifests.ts | 18 +++++++++++ .../packages/documents/documents/manifests.ts | 2 ++ ...value-user-permission.workspace-context.ts | 1 + 4 files changed, 53 insertions(+) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/block/document-block.workspace-context.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/block/manifests.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/block/document-block.workspace-context.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/block/document-block.workspace-context.ts new file mode 100644 index 000000000000..ffdf955aaee1 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/block/document-block.workspace-context.ts @@ -0,0 +1,32 @@ +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import { UMB_BLOCK_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/block'; +import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; +import { UMB_DOCUMENT_WORKSPACE_CONTEXT } from '../workspace/constants.js'; + +/** + * Document Block Workspace Context + * Extension to configure the workspace context for a block in a document. + * @export + * @class UmbDocumentBlockWorkspaceContext + * @extends {UmbControllerBase} + */ +export class UmbDocumentBlockWorkspaceContext extends UmbControllerBase { + constructor(host: UmbControllerHost) { + super(host); + + this.consumeContext(UMB_BLOCK_WORKSPACE_CONTEXT, async (context) => { + // TODO: revisit this when getContext supports passContextAliasMatches + const documentWorkspaceContext = await this.consumeContext(UMB_DOCUMENT_WORKSPACE_CONTEXT, () => {}) + .passContextAliasMatches() + .asPromise(); + + if (context && documentWorkspaceContext) { + // Start the states for blocks inside documents to allow for property value permissions + context.content.structure.propertyViewState.start(); + context.content.structure.propertyWriteState.start(); + } + }); + } +} + +export { UmbDocumentBlockWorkspaceContext as api }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/block/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/block/manifests.ts new file mode 100644 index 000000000000..1aa08184dfc9 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/block/manifests.ts @@ -0,0 +1,18 @@ +import { UMB_WORKSPACE_CONDITION_ALIAS } from '@umbraco-cms/backoffice/workspace'; +import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension-registry'; +import { UMB_BLOCK_WORKSPACE_ALIAS } from '@umbraco-cms/backoffice/block'; + +export const manifests: Array = [ + { + type: 'workspaceContext', + name: 'Document Block Workspace Context', + alias: 'Umb.WorkspaceContext.Block.Document', + api: () => import('./document-block.workspace-context.js'), + conditions: [ + { + alias: UMB_WORKSPACE_CONDITION_ALIAS, + match: UMB_BLOCK_WORKSPACE_ALIAS, + }, + ], + }, +]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/manifests.ts index c7910bc1b5c3..0817b8ab977d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/manifests.ts @@ -1,4 +1,5 @@ import { manifests as auditLogManifests } from './audit-log/manifests.js'; +import { manifests as blockManifests } from './block/manifests.js'; import { manifests as collectionManifests } from './collection/manifests.js'; import { manifests as entityActionManifests } from './entity-actions/manifests.js'; import { manifests as entityBulkActionManifests } from './entity-bulk-actions/manifests.js'; @@ -23,6 +24,7 @@ import type { UmbExtensionManifestKind } from '@umbraco-cms/backoffice/extension export const manifests: Array = [ ...auditLogManifests, + ...blockManifests, ...collectionManifests, ...entityActionManifests, ...entityBulkActionManifests, diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/workspace-context/document-block-property-value-user-permission.workspace-context.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/workspace-context/document-block-property-value-user-permission.workspace-context.ts index 3d5c22d38706..42007dd0d74f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/workspace-context/document-block-property-value-user-permission.workspace-context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/workspace-context/document-block-property-value-user-permission.workspace-context.ts @@ -15,6 +15,7 @@ export class UmbDocumentBlockPropertyValueUserPermissionWorkspaceContext extends this.#blockWorkspaceContext = context; // We only want to apply the permission logic if the block is in a document + // TODO: revisit this when getContext supports passContextAliasMatches const documentWorkspaceContext = await this.consumeContext(UMB_DOCUMENT_WORKSPACE_CONTEXT, () => {}) .passContextAliasMatches() .asPromise(); From 2714fed4e56b52b0c6d1c1986c205c9203665174 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 25 Mar 2025 12:20:38 +0100 Subject: [PATCH 103/106] only apply states when state is running --- ...-user-permission-workspace-context-base.ts | 65 ++++++++++--------- 1 file changed, 35 insertions(+), 30 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/workspace-context/property-value-user-permission-workspace-context-base.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/workspace-context/property-value-user-permission-workspace-context-base.ts index 815b003899b7..42975972764b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/workspace-context/property-value-user-permission-workspace-context-base.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/workspace-context/property-value-user-permission-workspace-context-base.ts @@ -40,41 +40,46 @@ export class UmbPropertyValueUserPermissionWorkspaceContextBase extends UmbContr property: UmbPropertyTypeModel; variantIds: Array; }) { - createExtensionApiByAlias(this, UMB_DOCUMENT_PROPERTY_VALUE_USER_PERMISSION_CONDITION_ALIAS, [ - { - config: { - allOf: [args.verb], - match: { - propertyType: { - unique: args.property.unique, + // We can only apply states if the state manager is running + this.observe(args.stateManager.isRunning, (isRunning) => { + if (!isRunning) return; + + createExtensionApiByAlias(this, UMB_DOCUMENT_PROPERTY_VALUE_USER_PERMISSION_CONDITION_ALIAS, [ + { + config: { + allOf: [args.verb], + match: { + propertyType: { + unique: args.property.unique, + }, }, }, - }, - onChange: (permitted: boolean) => { - // If the property is invariant we only need one state for the property - const isInvariant = args.property.variesByCulture === false && args.property.variesBySegment === false; - const variantIds = isInvariant ? [new UmbVariantId()] : args.variantIds; + onChange: (permitted: boolean) => { + // If the property is invariant we only need one state for the property + const isInvariant = args.property.variesByCulture === false && args.property.variesBySegment === false; + const variantIds = isInvariant ? [new UmbVariantId()] : args.variantIds; - const states: Array = - variantIds?.map((variantId) => { - return { - unique: 'UMB_PROPERTY_' + args.property.unique + '_' + variantId.toString(), - message: '', - propertyType: { - unique: args.property.unique, - variantId, - }, - }; - }) || []; + const states: Array = + variantIds?.map((variantId) => { + return { + unique: 'UMB_PROPERTY_' + args.property.unique + '_' + variantId.toString(), + message: '', + propertyType: { + unique: args.property.unique, + variantId, + }, + }; + }) || []; - if (permitted) { - args.stateManager.addStates(states); - } else { - args.stateManager.removeStates(states.map((state) => state.unique)); - } + if (permitted) { + args.stateManager.addStates(states); + } else { + args.stateManager.removeStates(states.map((state) => state.unique)); + } + }, }, - }, - ]); + ]); + }); } } From 6e16484dd9732c66d992dbff1c511bdb92e2faff Mon Sep 17 00:00:00 2001 From: Andy Butland Date: Tue, 25 Mar 2025 15:31:53 +0100 Subject: [PATCH 104/106] Fixed typos in test method names. --- .../Factories/UserGroupPresentationFactoryTests.cs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/tests/Umbraco.Tests.Integration/ManagementApi/Factories/UserGroupPresentationFactoryTests.cs b/tests/Umbraco.Tests.Integration/ManagementApi/Factories/UserGroupPresentationFactoryTests.cs index 76377920b4ec..a91092efda32 100644 --- a/tests/Umbraco.Tests.Integration/ManagementApi/Factories/UserGroupPresentationFactoryTests.cs +++ b/tests/Umbraco.Tests.Integration/ManagementApi/Factories/UserGroupPresentationFactoryTests.cs @@ -1,4 +1,4 @@ -using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection; using NUnit.Framework; using Umbraco.Cms.Api.Management.Factories; using Umbraco.Cms.Api.Management.Mapping.Permissions; @@ -24,8 +24,11 @@ namespace Umbraco.Cms.Tests.Integration.ManagementApi.Factories; public class UserGroupPresentationFactoryTests : UmbracoIntegrationTest { public IUserGroupPresentationFactory UserGroupPresentationFactory => GetRequiredService(); + public IUserGroupService UserGroupService => GetRequiredService(); + public ITemplateService TemplateService => GetRequiredService(); + public IContentTypeEditingService ContentTypeEditingService => GetRequiredService(); public IContentEditingService ContentEditingService => GetRequiredService(); @@ -40,7 +43,6 @@ protected override void ConfigureTestServices(IServiceCollection services) services.AddSingleton(); } - [Test] public async Task Can_Map_Create_Model_And_Create() { @@ -138,7 +140,7 @@ public async Task Cannot_Create_UserGroup_With_Unexisting_DocumentType_Reference } [Test] - public async Task Can_Create_Usergroup_With_Empty_Granluar_Permissions_For_Document() + public async Task Can_Create_Usergroup_With_Empty_Granular_Permissions_For_Document() { var contentKey = await CreateContent(); @@ -177,7 +179,7 @@ public async Task Can_Create_Usergroup_With_Empty_Granluar_Permissions_For_Docum } [Test] - public async Task Can_Create_Usergroup_With_Granluar_Permissions_For_Document_PropertyValue() + public async Task Can_Create_Usergroup_With_Granular_Permissions_For_Document_PropertyValue() { var template = TemplateBuilder.CreateTextPageTemplate("defaultTemplate"); await TemplateService.CreateAsync(template, Constants.Security.SuperUserKey); @@ -231,7 +233,7 @@ public async Task Can_Create_Usergroup_With_Granluar_Permissions_For_Document_Pr } [Test] - public async Task Can_Create_Usergroup_With_Granluar_Permissions_For_Document_PropertyValue_Without_Verbs() + public async Task Can_Create_Usergroup_With_Granular_Permissions_For_Document_PropertyValue_Without_Verbs() { var template = TemplateBuilder.CreateTextPageTemplate("defaultTemplate"); await TemplateService.CreateAsync(template, Constants.Security.SuperUserKey); @@ -284,7 +286,7 @@ public async Task Can_Create_Usergroup_With_Granluar_Permissions_For_Document_Pr } [Test] - public async Task Usergroup_Granluar_Permissions_For_Document_PropertyValue_Are_Cleaned_Up_When_DocumentType_Is_Deleted() + public async Task Usergroup_Granular_Permissions_For_Document_PropertyValue_Are_Cleaned_Up_When_DocumentType_Is_Deleted() { var template = TemplateBuilder.CreateTextPageTemplate("defaultTemplate"); await TemplateService.CreateAsync(template, Constants.Security.SuperUserKey); From 5f6c2741cde27ddd6c18ff37867893be7d560c14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Tue, 1 Apr 2025 09:38:07 +0200 Subject: [PATCH 105/106] add readonly type --- .../src/packages/core/utils/state-manager/state.manager.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/utils/state-manager/state.manager.ts b/src/Umbraco.Web.UI.Client/src/packages/core/utils/state-manager/state.manager.ts index c847fac3fc6d..430829f5dd35 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/utils/state-manager/state.manager.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/utils/state-manager/state.manager.ts @@ -12,7 +12,7 @@ export class UmbStateManager extends UmbC * @memberof UmbStateManager */ protected _states = new UmbArrayState([], (x) => x.unique); - public states = this._states.asObservable(); + public readonly states = this._states.asObservable(); protected _isRunning = new UmbBooleanState(true); public readonly isRunning = this._isRunning.asObservable(); @@ -21,13 +21,13 @@ export class UmbStateManager extends UmbC * Observable that emits true if there are any states in the state manager * @memberof UmbStateManager */ - public isOn = this._states.asObservablePart((x) => x.length > 0); + public readonly isOn = this._states.asObservablePart((x) => x.length > 0); /** * Observable that emits true if there are no states in the state manager * @memberof UmbStateManager */ - public isOff = this._states.asObservablePart((x) => x.length === 0); + public readonly isOff = this._states.asObservablePart((x) => x.length === 0); /** * Start the state - this will allow the state to be used. From cf331cba5fd44587f769e3269d1615135351ac9a Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 1 Apr 2025 12:47:41 +0200 Subject: [PATCH 106/106] Enforce: AllowEditInvariantFromNonDefault configuration (#18758) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * add read only state * handle read only property state in properties element * prevent editing shared props on non default * enforce configuration * clean up * set variant id * move to property module --------- Co-authored-by: Niels Lyngsø --- .../content-type-structure-manager.class.ts | 3 + .../edit/content-editor-properties.element.ts | 22 ++++++- .../src/packages/core/property/index.ts | 4 +- .../property-read-only-state.manager.ts | 10 ++++ ...ariant-property-read-only-state.manager.ts | 9 +++ .../src/packages/core/variant/index.ts | 1 + .../document-property-dataset.context.ts | 60 ++++++++++++++++++- .../workspace/document-workspace.context.ts | 1 + 8 files changed, 105 insertions(+), 5 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/property/property-read-only-state.manager.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/property/variant-property-read-only-state.manager.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/structure/content-type-structure-manager.class.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/structure/content-type-structure-manager.class.ts index 342a37b39dda..df515cf37415 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/structure/content-type-structure-manager.class.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/structure/content-type-structure-manager.class.ts @@ -20,6 +20,7 @@ import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; import { UmbExtensionApiInitializer } from '@umbraco-cms/backoffice/extension-api'; import { umbExtensionsRegistry, type ManifestRepository } from '@umbraco-cms/backoffice/extension-registry'; import { + UmbVariantPropertyReadOnlyStateManager, UmbVariantPropertyViewStateManager, UmbVariantPropertyWriteStateManager, } from '@umbraco-cms/backoffice/property'; @@ -104,6 +105,7 @@ export class UmbContentTypeStructureManager< public readonly propertyViewState = new UmbVariantPropertyViewStateManager(this); public readonly propertyWriteState = new UmbVariantPropertyWriteStateManager(this); + public readonly propertyReadOnlyState = new UmbVariantPropertyReadOnlyStateManager(this); #containers: UmbArrayState = new UmbArrayState( [], @@ -818,6 +820,7 @@ export class UmbContentTypeStructureManager< this.#containers.destroy(); this.propertyViewState.destroy(); this.propertyWriteState.destroy(); + this.propertyReadOnlyState.destroy(); super.destroy(); } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/content-editor-properties.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/content-editor-properties.element.ts index bd2e550894e4..ea8f593b8871 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/content-editor-properties.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/content-editor-properties.element.ts @@ -45,6 +45,9 @@ export class UmbContentWorkspaceViewEditPropertiesElement extends UmbLitElement @state() _propertyWriteStates: Array = []; + @state() + _propertyReadOnlyStates: Array = []; + constructor() { super(); @@ -77,6 +80,12 @@ export class UmbContentWorkspaceViewEditPropertiesElement extends UmbLitElement }, 'umbObservePropertyWriteStates', ); + + this.observe( + workspaceContext.structure.propertyReadOnlyState.states, + (states) => (this._propertyReadOnlyStates = states), + 'umbObservePropertyWriteStates', + ); }); this.consumeContext(UMB_PROPERTY_DATASET_CONTEXT, (datasetContext) => { @@ -129,9 +138,20 @@ export class UmbContentWorkspaceViewEditPropertiesElement extends UmbLitElement } const propertyVariantId = this.#getPropertyVariantId(property); - return this._propertyWriteStates.some( + + // Check if the property is writable + const isWriteAllowed = this._propertyWriteStates.some( (state) => state.propertyType.unique === property.unique && state.propertyType.variantId.equal(propertyVariantId), ); + + // Check if the property is read only + const isReadOnly = this._propertyReadOnlyStates.some( + (state) => state.propertyType.unique === property.unique && state.propertyType.variantId.equal(propertyVariantId), + ); + + // If the property has a read only state it will override the write state + // and the property will always be read only + return isWriteAllowed && !isReadOnly; } #getPropertyVariantId(property: UmbPropertyTypeModel) { diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property/index.ts index a415c0e81df0..795963351f5d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/property/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property/index.ts @@ -1,12 +1,12 @@ export * from './components/index.js'; export * from './conditions/index.js'; export * from './property-dataset/index.js'; +export * from './property-read-only-state.manager.js'; export * from './property-value-cloner/property-value-clone.controller.js'; export * from './property-value-preset/index.js'; export * from './property-view-state.manager.js'; export * from './property-write-state.manager.js'; -export * from './property-view-state.manager.js'; -export * from './property-write-state.manager.js'; +export * from './variant-property-read-only-state.manager.js'; export * from './variant-property-view-state.manager.js'; export * from './variant-property-write-state.manager.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property/property-read-only-state.manager.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property/property-read-only-state.manager.ts new file mode 100644 index 000000000000..bdd967107733 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property/property-read-only-state.manager.ts @@ -0,0 +1,10 @@ +import type { UmbReferenceByUnique } from '@umbraco-cms/backoffice/models'; +import { UmbReadOnlyStateManager, type UmbState } from '@umbraco-cms/backoffice/utils'; + +export interface UmbPropertyReadOnlyState extends UmbState { + propertyType: UmbReferenceByUnique; +} + +export class UmbPropertyReadOnlyStateManager< + ReadOnlyStateType extends UmbPropertyReadOnlyState = UmbPropertyReadOnlyState, +> extends UmbReadOnlyStateManager {} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property/variant-property-read-only-state.manager.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property/variant-property-read-only-state.manager.ts new file mode 100644 index 000000000000..e92b1a498840 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property/variant-property-read-only-state.manager.ts @@ -0,0 +1,9 @@ +import { UmbPropertyReadOnlyStateManager, type UmbPropertyReadOnlyState } from './property-read-only-state.manager.js'; +import type { UmbReferenceByUnique } from '@umbraco-cms/backoffice/models'; +import type { UmbReferenceByVariantId } from '@umbraco-cms/backoffice/variant'; + +export interface UmbVariantPropertyReadOnlyState extends UmbPropertyReadOnlyState { + propertyType: UmbReferenceByUnique & UmbReferenceByVariantId; +} + +export class UmbVariantPropertyReadOnlyStateManager extends UmbPropertyReadOnlyStateManager {} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/variant/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/variant/index.ts index 5a6c69cbf2ec..d190db617d65 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/variant/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/variant/index.ts @@ -1,3 +1,4 @@ export * from './variant-id.class.js'; export * from './variant-object-compare.function.js'; + export type * from './types.js'; 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..0da536938ca9 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,65 @@ -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 { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import type { UmbDocumentTypeDetailModel } from '@umbraco-cms/backoffice/document-type'; +import { observeMultiple } from '@umbraco-cms/backoffice/observable-api'; +import { UmbVariantId, type UmbVariantPropertyReadOnlyState } from '@umbraco-cms/backoffice/variant'; +import type { DocumentConfigurationResponseModel } from '@umbraco-cms/backoffice/external/backend-api'; export class UmbDocumentPropertyDatasetContext extends UmbContentPropertyDatasetContext< UmbDocumentDetailModel, UmbDocumentTypeDetailModel, UmbDocumentVariantModel -> {} +> { + #dataSetVariantId?: UmbVariantId; + #documentConfiguration?: DocumentConfigurationResponseModel; + + constructor(host: UmbControllerHost, dataOwner: UmbDocumentWorkspaceContext, variantId?: UmbVariantId) { + super(host, dataOwner, variantId); + + this.#dataSetVariantId = variantId; + + this.consumeContext(UMB_DOCUMENT_CONFIGURATION_CONTEXT, async (context) => { + this.#documentConfiguration = (await context?.getDocumentConfiguration()) ?? undefined; + + if (this.#documentConfiguration?.allowEditInvariantFromNonDefault !== true) { + 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; + + this._dataOwner.structure.propertyReadOnlyState.removeState(unique); + + if (!property.variesByCulture && !isDefaultLanguage) { + const state: UmbVariantPropertyReadOnlyState = { + unique, + message: 'Shared properties can only be edited in the default language', + propertyType: { + unique: property.unique, + variantId: new UmbVariantId(), + }, + }; + + this._dataOwner.structure.propertyReadOnlyState.addState(state); + } + }); + }, + ); + } +} 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 c021c9a39899..7a04577c087e 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 @@ -189,6 +189,7 @@ export class UmbDocumentWorkspaceContext this.#isTrashedContext.setIsTrashed(false); this.structure.propertyViewState.clear(); this.structure.propertyWriteState.clear(); + this.structure.propertyReadOnlyState.clear(); } override async load(unique: string) {