From ed72a692b60ef4c689676ffb86b044e5f08786fd Mon Sep 17 00:00:00 2001 From: Andy Butland Date: Thu, 2 Jan 2025 09:36:40 +0000 Subject: [PATCH 1/5] Timing updates for rendering and preparation of user group granular permissions details to resolve intermittent error on race condition --- ...user-group-granular-permission-list.element.ts | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) 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 edb6f56031..e84f99ff55 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 @@ -3,7 +3,7 @@ import { UmbChangeEvent } from '@umbraco-cms/backoffice/event'; import { createExtensionElement } from '@umbraco-cms/backoffice/extension-api'; import type { ManifestGranularUserPermission } from '@umbraco-cms/backoffice/user-permission'; import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; -import { html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; +import { html, customElement, state, nothing } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { filterFrozenArray } from '@umbraco-cms/backoffice/observable-api'; @@ -31,7 +31,7 @@ export class UmbUserGroupGranularPermissionListElement extends UmbLitElement { return; } - manifests.forEach(async (manifest) => this.#extensionElementSetup(manifest)); + manifests.forEach(async (manifest) => await this.#extensionElementSetup(manifest)); }); } @@ -40,6 +40,8 @@ export class UmbUserGroupGranularPermissionListElement extends UmbLitElement { if (!element) throw new Error(`Failed to create extension element for manifest ${manifest.alias}`); if (!this.#workspaceContext) throw new Error('User Group Workspace context is not available'); + this._extensionElements.push(element); + this.observe( this.#workspaceContext.data, (userGroup) => { @@ -52,12 +54,10 @@ export class UmbUserGroupGranularPermissionListElement extends UmbLitElement { element.permissions = permissionsForSchemaType; element.manifest = manifest; element.addEventListener(UmbChangeEvent.TYPE, this.#onValueChange); + this.requestUpdate('_extensionElements'); }, 'umbUserGroupGranularPermissionObserver', ); - - this._extensionElements.push(element); - this.requestUpdate('_extensionElements'); } #onValueChange = (e: UmbChangeEvent) => { @@ -88,6 +88,11 @@ export class UmbUserGroupGranularPermissionListElement extends UmbLitElement { #renderProperty(element: any) { const manifest = element.manifest as ManifestGranularUserPermission; + if (!manifest) { + console.log("no manifest"); + return nothing; + } + const label = manifest.meta.labelKey ? this.localize.term(manifest.meta.labelKey) : manifest.meta.label; const description = manifest.meta.descriptionKey ? this.localize.term(manifest.meta.descriptionKey) From a3c45c0fe968a1f73fa381901d0c9eb1afd979bb Mon Sep 17 00:00:00 2001 From: Andy Butland Date: Thu, 2 Jan 2025 10:02:56 +0000 Subject: [PATCH 2/5] Removed debug code. --- .../components/user-group-granular-permission-list.element.ts | 1 - 1 file changed, 1 deletion(-) 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 e84f99ff55..873a41876a 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 @@ -89,7 +89,6 @@ export class UmbUserGroupGranularPermissionListElement extends UmbLitElement { #renderProperty(element: any) { const manifest = element.manifest as ManifestGranularUserPermission; if (!manifest) { - console.log("no manifest"); return nothing; } From 12ab1d6da2fdc0b96fd4f297bf2207f502173090 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Tue, 7 Jan 2025 13:28:59 +0100 Subject: [PATCH 3/5] fix types --- .../components/extension-slot/extension-slot.element.ts | 4 ++-- .../extension-with-api-slot.element.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/components/extension-slot/extension-slot.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/components/extension-slot/extension-slot.element.ts index 974102a025..8e6cd128a0 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/components/extension-slot/extension-slot.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/components/extension-slot/extension-slot.element.ts @@ -1,5 +1,5 @@ import { umbExtensionsRegistry } from '../../registry.js'; -import type { TemplateResult } from '@umbraco-cms/backoffice/external/lit'; +import type { TemplateResult, nothing } from '@umbraco-cms/backoffice/external/lit'; import { css, repeat, customElement, property, state, html } from '@umbraco-cms/backoffice/external/lit'; import { type UmbExtensionElementInitializer, @@ -95,7 +95,7 @@ export class UmbExtensionSlotElement extends UmbLitElement { public renderMethod?: ( extension: UmbExtensionElementInitializer, index: number, - ) => TemplateResult | HTMLElement | null | undefined; + ) => TemplateResult | TemplateResult<1> | HTMLElement | null | undefined | typeof nothing; override connectedCallback(): void { super.connectedCallback(); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/components/extension-with-api-slot/extension-with-api-slot.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/components/extension-with-api-slot/extension-with-api-slot.element.ts index b9d73fac90..14c1dac3b3 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/components/extension-with-api-slot/extension-with-api-slot.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/components/extension-with-api-slot/extension-with-api-slot.element.ts @@ -1,5 +1,5 @@ import { umbExtensionsRegistry } from '../../registry.js'; -import type { TemplateResult } from '@umbraco-cms/backoffice/external/lit'; +import type { TemplateResult, nothing } from '@umbraco-cms/backoffice/external/lit'; import { css, repeat, customElement, property, state, html } from '@umbraco-cms/backoffice/external/lit'; import { type UmbExtensionElementAndApiInitializer, @@ -141,7 +141,7 @@ export class UmbExtensionWithApiSlotElement extends UmbLitElement { public renderMethod?: ( extension: UmbExtensionElementAndApiInitializer, index: number, - ) => TemplateResult | HTMLElement | null | undefined; + ) => TemplateResult | TemplateResult<1> | HTMLElement | null | undefined | typeof nothing; override connectedCallback(): void { super.connectedCallback(); From 87c48c379b24ae373c318f5f0f78b51a9500b336 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Tue, 7 Jan 2025 13:29:09 +0100 Subject: [PATCH 4/5] use extension slot --- ...-group-granular-permission-list.element.ts | 84 +++++++------------ 1 file changed, 30 insertions(+), 54 deletions(-) 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 873a41876a..aaa6fc4549 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 @@ -1,8 +1,7 @@ import { UMB_USER_GROUP_WORKSPACE_CONTEXT } from '../user-group-workspace.context-token.js'; import { UmbChangeEvent } from '@umbraco-cms/backoffice/event'; -import { createExtensionElement } from '@umbraco-cms/backoffice/extension-api'; +import type { UmbExtensionElementInitializer } from '@umbraco-cms/backoffice/extension-api'; import type { ManifestGranularUserPermission } from '@umbraco-cms/backoffice/user-permission'; -import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; import { html, customElement, state, nothing } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { filterFrozenArray } from '@umbraco-cms/backoffice/observable-api'; @@ -10,7 +9,7 @@ import { filterFrozenArray } from '@umbraco-cms/backoffice/observable-api'; @customElement('umb-user-group-granular-permission-list') export class UmbUserGroupGranularPermissionListElement extends UmbLitElement { @state() - _extensionElements: Array = []; + _userGroupPermissions?: Array; #workspaceContext?: typeof UMB_USER_GROUP_WORKSPACE_CONTEXT.TYPE; @@ -19,45 +18,15 @@ export class UmbUserGroupGranularPermissionListElement extends UmbLitElement { this.consumeContext(UMB_USER_GROUP_WORKSPACE_CONTEXT, (instance) => { this.#workspaceContext = instance; + + this.observe( + this.#workspaceContext.data, + (userGroup) => { + this._userGroupPermissions = userGroup?.permissions; + }, + 'umbUserGroupGranularPermissionObserver', + ); }); - - this.#observeExtensionRegistry(); - } - - #observeExtensionRegistry() { - this.observe(umbExtensionsRegistry.byType('userGranularPermission'), (manifests) => { - if (!manifests) { - this._extensionElements = []; - return; - } - - manifests.forEach(async (manifest) => await this.#extensionElementSetup(manifest)); - }); - } - - async #extensionElementSetup(manifest: ManifestGranularUserPermission) { - const element = (await createExtensionElement(manifest)) as any; - if (!element) throw new Error(`Failed to create extension element for manifest ${manifest.alias}`); - if (!this.#workspaceContext) throw new Error('User Group Workspace context is not available'); - - this._extensionElements.push(element); - - this.observe( - this.#workspaceContext.data, - (userGroup) => { - if (!userGroup) return; - - const schemaType = manifest.meta.schemaType; - const permissionsForSchemaType = - userGroup.permissions.filter((permission) => permission.$type === schemaType) || []; - - element.permissions = permissionsForSchemaType; - element.manifest = manifest; - element.addEventListener(UmbChangeEvent.TYPE, this.#onValueChange); - this.requestUpdate('_extensionElements'); - }, - 'umbUserGroupGranularPermissionObserver', - ); } #onValueChange = (e: UmbChangeEvent) => { @@ -83,31 +52,38 @@ export class UmbUserGroupGranularPermissionListElement extends UmbLitElement { }; override render() { - return html`${this._extensionElements.map((element) => this.#renderProperty(element))}`; + if (!this._userGroupPermissions) return; + //return html`${this._extensionElements.map((element) => this.#renderProperty(element))}`; + return html``; } - #renderProperty(element: any) { - const manifest = element.manifest as ManifestGranularUserPermission; - if (!manifest) { - return nothing; - } + #renderProperty = (extension: UmbExtensionElementInitializer) => { + if (!this._userGroupPermissions) return nothing; + if (!extension.component) return nothing; + + const manifest = extension.manifest; + if (!manifest) throw new Error('Manifest is not available'); const label = manifest.meta.labelKey ? this.localize.term(manifest.meta.labelKey) : manifest.meta.label; const description = manifest.meta.descriptionKey ? this.localize.term(manifest.meta.descriptionKey) : manifest.meta.description; + const schemaType = manifest.meta.schemaType; + const permissionsForSchemaType = + this._userGroupPermissions.filter((permission) => permission.$type === schemaType) || []; + + (extension.component as any).permissions = permissionsForSchemaType; + extension.component.addEventListener(UmbChangeEvent.TYPE, this.#onValueChange); + return html` -
${element}
+
${extension.component}
`; - } - - override disconnectedCallback(): void { - this._extensionElements.forEach((element) => element.removeEventListener(UmbChangeEvent.TYPE, this.#onValueChange)); - super.disconnectedCallback(); - } + }; } export default UmbUserGroupGranularPermissionListElement; From 7ac941de77d269400f6b48e6105d3f342c880fde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Wed, 8 Jan 2025 09:35:09 +0100 Subject: [PATCH 5/5] remove comment --- .../components/user-group-granular-permission-list.element.ts | 1 - 1 file changed, 1 deletion(-) 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 aaa6fc4549..d830d2b748 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 @@ -53,7 +53,6 @@ export class UmbUserGroupGranularPermissionListElement extends UmbLitElement { override render() { if (!this._userGroupPermissions) return; - //return html`${this._extensionElements.map((element) => this.#renderProperty(element))}`; return html``;