From 3170e6853ece86b2e184020ec1f1923ea9f6cde7 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Sun, 24 Mar 2024 16:08:40 +0100 Subject: [PATCH 1/8] wip render first entity action --- .../entity-actions-bundle.element.ts | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/entity-actions-bundle/entity-actions-bundle.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/entity-actions-bundle/entity-actions-bundle.element.ts index b856c443da..01648402da 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/components/entity-actions-bundle/entity-actions-bundle.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/entity-actions-bundle/entity-actions-bundle.element.ts @@ -3,7 +3,7 @@ import { map } from '@umbraco-cms/backoffice/external/rxjs'; import type { UmbSectionSidebarContext } from '@umbraco-cms/backoffice/section'; import { UMB_SECTION_SIDEBAR_CONTEXT } from '@umbraco-cms/backoffice/section'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; +import { ManifestEntityAction, umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; @customElement('umb-entity-actions-bundle') export class UmbEntityActionsBundleElement extends UmbLitElement { @@ -15,7 +15,6 @@ export class UmbEntityActionsBundleElement extends UmbLitElement { public set entityType(value: string | undefined) { const oldValue = this._entityType; if (oldValue === value) return; - this._entityType = value; this.#observeEntityActions(); this.requestUpdate('entityType', oldValue); @@ -30,6 +29,9 @@ export class UmbEntityActionsBundleElement extends UmbLitElement { @state() private _hasActions = false; + @state() + private _firstAction?: ManifestEntityAction; + #sectionSidebarContext?: UmbSectionSidebarContext; constructor() { @@ -42,11 +44,11 @@ export class UmbEntityActionsBundleElement extends UmbLitElement { #observeEntityActions() { this.observe( - umbExtensionsRegistry - .byType('entityAction') - .pipe(map((actions) => actions.some((action) => action.forEntityTypes.includes(this.entityType!)))), - (hasActions) => { - this._hasActions = hasActions; + umbExtensionsRegistry.byType('entityAction'), + (manifests) => { + const actions = manifests.filter((manifest) => manifest.forEntityTypes.includes(this.entityType!)); + this._hasActions = actions.length > 0; + this._firstAction = this._hasActions ? actions[0] : undefined; }, 'umbEntityActionsObserver', ); @@ -66,8 +68,9 @@ export class UmbEntityActionsBundleElement extends UmbLitElement { + - ` + ` : nothing} `; } From ec5a5dfa3e586d7e1d50d2ff6d4d04e1b0b10870 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Sun, 24 Mar 2024 19:32:18 +0100 Subject: [PATCH 2/8] render first entity action next to more button --- .../entity-actions-bundle.element.ts | 48 +++++++++++++------ 1 file changed, 34 insertions(+), 14 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/entity-actions-bundle/entity-actions-bundle.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/entity-actions-bundle/entity-actions-bundle.element.ts index 01648402da..16da646483 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/components/entity-actions-bundle/entity-actions-bundle.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/entity-actions-bundle/entity-actions-bundle.element.ts @@ -1,9 +1,11 @@ +import type { UmbEntityAction } from '@umbraco-cms/backoffice/entity-action'; import { html, nothing, customElement, property, state } from '@umbraco-cms/backoffice/external/lit'; -import { map } from '@umbraco-cms/backoffice/external/rxjs'; import type { UmbSectionSidebarContext } from '@umbraco-cms/backoffice/section'; import { UMB_SECTION_SIDEBAR_CONTEXT } from '@umbraco-cms/backoffice/section'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -import { ManifestEntityAction, umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; +import type { ManifestEntityAction } from '@umbraco-cms/backoffice/extension-registry'; +import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; +import { createExtensionApi } from '@umbraco-cms/backoffice/extension-api'; @customElement('umb-entity-actions-bundle') export class UmbEntityActionsBundleElement extends UmbLitElement { @@ -30,7 +32,10 @@ export class UmbEntityActionsBundleElement extends UmbLitElement { private _hasActions = false; @state() - private _firstAction?: ManifestEntityAction; + private _firstActionManifest?: ManifestEntityAction; + + @state() + private _firstActionApi?: UmbEntityAction; #sectionSidebarContext?: UmbSectionSidebarContext; @@ -45,35 +50,50 @@ export class UmbEntityActionsBundleElement extends UmbLitElement { #observeEntityActions() { this.observe( umbExtensionsRegistry.byType('entityAction'), - (manifests) => { + async (manifests) => { const actions = manifests.filter((manifest) => manifest.forEntityTypes.includes(this.entityType!)); this._hasActions = actions.length > 0; - this._firstAction = this._hasActions ? actions[0] : undefined; + this._firstActionManifest = this._hasActions ? actions[0] : undefined; + if (!this._firstActionManifest) return; + this._firstActionApi = await createExtensionApi(this, this._firstActionManifest, [ + { unique: this.unique, entityType: this.entityType }, + ]); }, 'umbEntityActionsObserver', ); } - private _openActions() { + #openContextMenu() { if (!this.entityType) throw new Error('Entity type is not defined'); if (this.unique === undefined) throw new Error('Unique is not defined'); this.#sectionSidebarContext?.toggleContextMenu(this.entityType, this.unique, this.label); } + async #onFirstActionClick(event: PointerEvent) { + event.stopPropagation(); + await this._firstActionApi?.execute(); + } + render() { return html` ${this._hasActions - ? html` - - - - - - - ` + ? html` ${this.#renderFirstAction()} ${this.#renderMore()} ` : nothing} `; } + + #renderMore() { + return html` + + `; + } + + #renderFirstAction() { + if (!this._firstActionApi) return nothing; + return html` + + `; + } } declare global { From 060fdb41d822f47c70e227057e4f5464c2dbf3c6 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Sun, 24 Mar 2024 19:36:11 +0100 Subject: [PATCH 3/8] don't render more button if there is only one action --- .../entity-actions-bundle.element.ts | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/entity-actions-bundle/entity-actions-bundle.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/entity-actions-bundle/entity-actions-bundle.element.ts index 16da646483..a60adfb9cd 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/components/entity-actions-bundle/entity-actions-bundle.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/entity-actions-bundle/entity-actions-bundle.element.ts @@ -29,7 +29,7 @@ export class UmbEntityActionsBundleElement extends UmbLitElement { public label?: string; @state() - private _hasActions = false; + private _numberOfActions = 0; @state() private _firstActionManifest?: ManifestEntityAction; @@ -52,8 +52,8 @@ export class UmbEntityActionsBundleElement extends UmbLitElement { umbExtensionsRegistry.byType('entityAction'), async (manifests) => { const actions = manifests.filter((manifest) => manifest.forEntityTypes.includes(this.entityType!)); - this._hasActions = actions.length > 0; - this._firstActionManifest = this._hasActions ? actions[0] : undefined; + this._numberOfActions = actions.length; + this._firstActionManifest = this._numberOfActions > 0 ? actions[0] : undefined; if (!this._firstActionManifest) return; this._firstActionApi = await createExtensionApi(this, this._firstActionManifest, [ { unique: this.unique, entityType: this.entityType }, @@ -75,14 +75,12 @@ export class UmbEntityActionsBundleElement extends UmbLitElement { } render() { - return html` - ${this._hasActions - ? html` ${this.#renderFirstAction()} ${this.#renderMore()} ` - : nothing} - `; + if (this._numberOfActions === 0) return nothing; + return html` ${this.#renderFirstAction()} ${this.#renderMore()} `; } #renderMore() { + if (this._numberOfActions === 1) return nothing; return html` `; From 5836dbeadabcfb292e940c5d93b3325939bf820a Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Sun, 24 Mar 2024 19:58:44 +0100 Subject: [PATCH 4/8] expect a default kind --- .../entity-actions-bundle/entity-actions-bundle.element.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/entity-actions-bundle/entity-actions-bundle.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/entity-actions-bundle/entity-actions-bundle.element.ts index a60adfb9cd..24efed15d0 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/components/entity-actions-bundle/entity-actions-bundle.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/entity-actions-bundle/entity-actions-bundle.element.ts @@ -3,7 +3,7 @@ import { html, nothing, customElement, property, state } from '@umbraco-cms/back import type { UmbSectionSidebarContext } from '@umbraco-cms/backoffice/section'; import { UMB_SECTION_SIDEBAR_CONTEXT } from '@umbraco-cms/backoffice/section'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -import type { ManifestEntityAction } from '@umbraco-cms/backoffice/extension-registry'; +import type { ManifestEntityAction, ManifestEntityActionDefaultKind } from '@umbraco-cms/backoffice/extension-registry'; import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; import { createExtensionApi } from '@umbraco-cms/backoffice/extension-api'; @@ -32,7 +32,7 @@ export class UmbEntityActionsBundleElement extends UmbLitElement { private _numberOfActions = 0; @state() - private _firstActionManifest?: ManifestEntityAction; + private _firstActionManifest?: ManifestEntityActionDefaultKind; @state() private _firstActionApi?: UmbEntityAction; From 7c6449fc6ea1f7ca9ac5a20d74742044d63f35c5 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Sun, 24 Mar 2024 20:54:06 +0100 Subject: [PATCH 5/8] expect icon and label --- .../entity-actions-bundle.element.ts | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/entity-actions-bundle/entity-actions-bundle.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/entity-actions-bundle/entity-actions-bundle.element.ts index 24efed15d0..d146a8aa59 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/components/entity-actions-bundle/entity-actions-bundle.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/entity-actions-bundle/entity-actions-bundle.element.ts @@ -1,9 +1,9 @@ import type { UmbEntityAction } from '@umbraco-cms/backoffice/entity-action'; -import { html, nothing, customElement, property, state } from '@umbraco-cms/backoffice/external/lit'; +import { html, nothing, customElement, property, state, ifDefined } from '@umbraco-cms/backoffice/external/lit'; import type { UmbSectionSidebarContext } from '@umbraco-cms/backoffice/section'; import { UMB_SECTION_SIDEBAR_CONTEXT } from '@umbraco-cms/backoffice/section'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -import type { ManifestEntityAction, ManifestEntityActionDefaultKind } from '@umbraco-cms/backoffice/extension-registry'; +import type { ManifestEntityActionDefaultKind } from '@umbraco-cms/backoffice/extension-registry'; import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; import { createExtensionApi } from '@umbraco-cms/backoffice/extension-api'; @@ -53,7 +53,8 @@ export class UmbEntityActionsBundleElement extends UmbLitElement { async (manifests) => { const actions = manifests.filter((manifest) => manifest.forEntityTypes.includes(this.entityType!)); this._numberOfActions = actions.length; - this._firstActionManifest = this._numberOfActions > 0 ? actions[0] : undefined; + this._firstActionManifest = + this._numberOfActions > 0 ? (actions[0] as ManifestEntityActionDefaultKind) : undefined; if (!this._firstActionManifest) return; this._firstActionApi = await createExtensionApi(this, this._firstActionManifest, [ { unique: this.unique, entityType: this.entityType }, @@ -88,8 +89,10 @@ export class UmbEntityActionsBundleElement extends UmbLitElement { #renderFirstAction() { if (!this._firstActionApi) return nothing; - return html` - + return html` + `; } } From 900cefb306faa45631c30c7dcacc1f57b1e269f7 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Sun, 24 Mar 2024 21:09:38 +0100 Subject: [PATCH 6/8] first create api when we have both entity type and unique --- .../entity-actions-bundle.element.ts | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/entity-actions-bundle/entity-actions-bundle.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/entity-actions-bundle/entity-actions-bundle.element.ts index d146a8aa59..d963a30df3 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/components/entity-actions-bundle/entity-actions-bundle.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/entity-actions-bundle/entity-actions-bundle.element.ts @@ -1,4 +1,5 @@ import type { UmbEntityAction } from '@umbraco-cms/backoffice/entity-action'; +import type { PropertyValueMap } from '@umbraco-cms/backoffice/external/lit'; import { html, nothing, customElement, property, state, ifDefined } from '@umbraco-cms/backoffice/external/lit'; import type { UmbSectionSidebarContext } from '@umbraco-cms/backoffice/section'; import { UMB_SECTION_SIDEBAR_CONTEXT } from '@umbraco-cms/backoffice/section'; @@ -9,18 +10,8 @@ import { createExtensionApi } from '@umbraco-cms/backoffice/extension-api'; @customElement('umb-entity-actions-bundle') export class UmbEntityActionsBundleElement extends UmbLitElement { - private _entityType?: string; @property({ type: String, attribute: 'entity-type' }) - public get entityType() { - return this._entityType; - } - public set entityType(value: string | undefined) { - const oldValue = this._entityType; - if (oldValue === value) return; - this._entityType = value; - this.#observeEntityActions(); - this.requestUpdate('entityType', oldValue); - } + entityType?: string; @property({ type: String }) unique?: string | null; @@ -47,6 +38,12 @@ export class UmbEntityActionsBundleElement extends UmbLitElement { }); } + protected updated(_changedProperties: PropertyValueMap | Map): void { + if (_changedProperties.has('entityType') && _changedProperties.has('unique')) { + this.#observeEntityActions(); + } + } + #observeEntityActions() { this.observe( umbExtensionsRegistry.byType('entityAction'), From 961ac401ccef3110d558cc149598bd26150707ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Mon, 25 Mar 2024 10:45:57 +0100 Subject: [PATCH 7/8] put filter into observablePart for performance gain --- .../entity-actions-bundle.element.ts | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/entity-actions-bundle/entity-actions-bundle.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/entity-actions-bundle/entity-actions-bundle.element.ts index d963a30df3..3cd91404b0 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/components/entity-actions-bundle/entity-actions-bundle.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/entity-actions-bundle/entity-actions-bundle.element.ts @@ -46,12 +46,9 @@ export class UmbEntityActionsBundleElement extends UmbLitElement { #observeEntityActions() { this.observe( - umbExtensionsRegistry.byType('entityAction'), - async (manifests) => { - const actions = manifests.filter((manifest) => manifest.forEntityTypes.includes(this.entityType!)); - this._numberOfActions = actions.length; - this._firstActionManifest = - this._numberOfActions > 0 ? (actions[0] as ManifestEntityActionDefaultKind) : undefined; + umbExtensionsRegistry.byTypeAndFilter('entityAction', (ext) => ext.forEntityTypes.includes(this.entityType!)), + async (actions) => { + this._firstActionManifest = actions.length > 0 ? (actions[0] as ManifestEntityActionDefaultKind) : undefined; if (!this._firstActionManifest) return; this._firstActionApi = await createExtensionApi(this, this._firstActionManifest, [ { unique: this.unique, entityType: this.entityType }, From 6395585c16244852da871bbd025694eb565e914e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Mon, 25 Mar 2024 11:00:01 +0100 Subject: [PATCH 8/8] introduce number of actions state prop --- .../entity-actions-bundle/entity-actions-bundle.element.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/entity-actions-bundle/entity-actions-bundle.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/entity-actions-bundle/entity-actions-bundle.element.ts index 3cd91404b0..fa9655b2ff 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/components/entity-actions-bundle/entity-actions-bundle.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/entity-actions-bundle/entity-actions-bundle.element.ts @@ -48,7 +48,9 @@ export class UmbEntityActionsBundleElement extends UmbLitElement { this.observe( umbExtensionsRegistry.byTypeAndFilter('entityAction', (ext) => ext.forEntityTypes.includes(this.entityType!)), async (actions) => { - this._firstActionManifest = actions.length > 0 ? (actions[0] as ManifestEntityActionDefaultKind) : undefined; + this._numberOfActions = actions.length; + this._firstActionManifest = + this._numberOfActions > 0 ? (actions[0] as ManifestEntityActionDefaultKind) : undefined; if (!this._firstActionManifest) return; this._firstActionApi = await createExtensionApi(this, this._firstActionManifest, [ { unique: this.unique, entityType: this.entityType },