fix: show the action button inside a button-group only if there are extensions registered

by moving the calculation of the extension controllers from the action-menu element into the action element itself, we can save a few states, simplify the calculation, and conditionally render the action-menu element ensuring, that the UUI styling is correctly applied
This commit is contained in:
Jacob Overgaard
2024-07-24 11:41:33 +02:00
parent 1783ee433b
commit ae2b36982b
2 changed files with 87 additions and 101 deletions

View File

@@ -1,85 +1,24 @@
import type { CSSResultGroup } from '@umbraco-cms/backoffice/external/lit';
import { css, html, customElement, property, state, nothing, repeat } from '@umbraco-cms/backoffice/external/lit';
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
import {
umbExtensionsRegistry,
type ManifestWorkspaceActionMenuItem,
} from '@umbraco-cms/backoffice/extension-registry';
import type { ManifestWorkspaceActionMenuItem } from '@umbraco-cms/backoffice/extension-registry';
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
import type { UUIInterfaceColor, UUIInterfaceLook } from '@umbraco-cms/backoffice/external/uui';
import {
type UmbExtensionElementAndApiInitializer,
UmbExtensionsElementAndApiInitializer,
} from '@umbraco-cms/backoffice/extension-api';
import type { UmbExtensionElementAndApiInitializer } from '@umbraco-cms/backoffice/extension-api';
function ExtensionApiArgsMethod(manifest: ManifestWorkspaceActionMenuItem) {
return [{ meta: manifest.meta }];
}
@customElement('umb-workspace-action-menu')
export class UmbWorkspaceActionMenuElement extends UmbLitElement {
#extensionsController?: UmbExtensionsElementAndApiInitializer<
ManifestWorkspaceActionMenuItem,
'workspaceActionMenuItem',
ManifestWorkspaceActionMenuItem
>;
/**
* The workspace actions to filter the available actions by.
* @example ['Umb.WorkspaceAction.Document.Save', 'Umb.WorkspaceAction.Document.SaveAndPublishNew']
*/
@property({ attribute: false })
public set forWorkspaceActions(value: Array<string>) {
if (value === this._forWorkspaceActions) return;
this._forWorkspaceActions = value;
this._filter = (action) => {
return Array.isArray(action.forWorkspaceActions)
? action.forWorkspaceActions.some((alias) => this.forWorkspaceActions.includes(alias))
: this.forWorkspaceActions.includes(action.forWorkspaceActions);
};
this.#observeExtensions();
}
public get forWorkspaceActions(): Array<string> {
return this._forWorkspaceActions;
}
private _forWorkspaceActions: Array<string> = [];
@state()
_filter?: (action: ManifestWorkspaceActionMenuItem) => boolean;
@property()
look: UUIInterfaceLook = 'secondary';
@property()
color: UUIInterfaceColor = 'default';
@state()
_items: Array<UmbExtensionElementAndApiInitializer<ManifestWorkspaceActionMenuItem>> = [];
@property({ type: Array, attribute: false })
items: Array<UmbExtensionElementAndApiInitializer<ManifestWorkspaceActionMenuItem>> = [];
@state()
_popoverOpen = false;
#observeExtensions(): void {
this.#extensionsController?.destroy();
if (this._filter) {
this.#extensionsController = new UmbExtensionsElementAndApiInitializer<
ManifestWorkspaceActionMenuItem,
'workspaceActionMenuItem',
ManifestWorkspaceActionMenuItem
>(
this,
umbExtensionsRegistry,
'workspaceActionMenuItem',
ExtensionApiArgsMethod,
this._filter,
(extensionControllers) => {
this._items = extensionControllers;
},
undefined, // We can leave the alias to undefined, as we destroy this our selfs.
);
//this.#extensionsController.elementProperties = this.#elProps;
}
}
#onPopoverToggle(event: ToggleEvent) {
// TODO: This ignorer is just neede for JSON SCHEMA TO WORK, As its not updated with latest TS jet.
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
@@ -88,7 +27,7 @@ export class UmbWorkspaceActionMenuElement extends UmbLitElement {
}
override render() {
return this._items && this._items.length > 0
return this.items?.length
? html`
<uui-button
id="popover-trigger"
@@ -106,13 +45,11 @@ export class UmbWorkspaceActionMenuElement extends UmbLitElement {
@toggle=${this.#onPopoverToggle}>
<umb-popover-layout>
<uui-scroll-container>
${this._items.length > 0
? repeat(
this._items,
(ext) => ext.alias,
(ext) => ext.component,
)
: ''}
${repeat(
this.items,
(ext) => ext.alias,
(ext) => ext.component,
)}
</uui-scroll-container>
</umb-popover-layout>
</uui-popover-container>
@@ -120,7 +57,7 @@ export class UmbWorkspaceActionMenuElement extends UmbLitElement {
: nothing;
}
static override styles: CSSResultGroup = [
static override styles = [
UmbTextStyles,
css`
:host {
@@ -143,7 +80,6 @@ export class UmbWorkspaceActionMenuElement extends UmbLitElement {
#popover-trigger {
--uui-button-padding-top-factor: 0.5;
--uui-button-padding-bottom-factor: 0.1;
--uui-button-border-radius: 0;
}
`,
];

View File

@@ -1,12 +1,18 @@
import type { UmbWorkspaceAction } from '../workspace-action.interface.js';
import { UmbActionExecutedEvent } from '@umbraco-cms/backoffice/event';
import { html, customElement, property, state, ifDefined } from '@umbraco-cms/backoffice/external/lit';
import { html, customElement, property, state, ifDefined, when } from '@umbraco-cms/backoffice/external/lit';
import type { UUIButtonState } from '@umbraco-cms/backoffice/external/uui';
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
import type {
ManifestWorkspaceAction,
MetaWorkspaceActionDefaultKind,
import {
umbExtensionsRegistry,
type ManifestWorkspaceAction,
type ManifestWorkspaceActionMenuItem,
type MetaWorkspaceActionDefaultKind,
} from '@umbraco-cms/backoffice/extension-registry';
import {
type UmbExtensionElementAndApiInitializer,
UmbExtensionsElementAndApiInitializer,
} from '@umbraco-cms/backoffice/extension-api';
import '../../workspace-action-menu/index.js';
@@ -17,13 +23,15 @@ export class UmbWorkspaceActionElement<
> extends UmbLitElement {
#manifest?: ManifestWorkspaceAction<MetaType>;
#api?: ApiType;
#extensionsController?: UmbExtensionsElementAndApiInitializer<
ManifestWorkspaceActionMenuItem,
'workspaceActionMenuItem',
ManifestWorkspaceActionMenuItem
>;
@state()
private _buttonState?: UUIButtonState;
@state()
private _aliases: Array<string> = [];
@state()
_href?: string;
@@ -60,6 +68,9 @@ export class UmbWorkspaceActionElement<
return this.#api;
}
@state()
private _items: Array<UmbExtensionElementAndApiInitializer<ManifestWorkspaceActionMenuItem>> = [];
/**
* Create a list of original and overwritten aliases of workspace actions for the action.
*/
@@ -77,7 +88,8 @@ export class UmbWorkspaceActionElement<
}
}
}
this._aliases = Array.from(aliases);
this.#observeExtensions(Array.from(aliases));
}
private async _onClick(event: MouseEvent) {
@@ -108,27 +120,61 @@ export class UmbWorkspaceActionElement<
);
}
override render() {
#observeExtensions(aliases: string[]): void {
this.#extensionsController?.destroy();
this.#extensionsController = new UmbExtensionsElementAndApiInitializer<
ManifestWorkspaceActionMenuItem,
'workspaceActionMenuItem',
ManifestWorkspaceActionMenuItem
>(
this,
umbExtensionsRegistry,
'workspaceActionMenuItem',
ExtensionApiArgsMethod,
(action) => {
return Array.isArray(action.forWorkspaceActions)
? action.forWorkspaceActions.some((alias) => aliases.includes(alias))
: aliases.includes(action.forWorkspaceActions);
},
(extensionControllers) => {
this._items = extensionControllers;
},
undefined, // We can leave the alias to undefined, as we destroy this our selfs.
);
}
#renderButton() {
return html`
<uui-button-group>
<uui-button
id="action-button"
.href=${this._href}
@click=${this._onClick}
look=${this.#manifest?.meta.look || 'default'}
color=${this.#manifest?.meta.color || 'default'}
label=${ifDefined(
this.#manifest?.meta.label ? this.localize.string(this.#manifest.meta.label) : this.#manifest?.name,
)}
.disabled=${this._isDisabled}
.state=${this._buttonState}></uui-button>
<umb-workspace-action-menu
.forWorkspaceActions=${this._aliases}
color="${this.#manifest?.meta.color || 'default'}"
look="${this.#manifest?.meta.look || 'default'}"></umb-workspace-action-menu>
</uui-button-group>
<uui-button
id="action-button"
.href=${this._href}
@click=${this._onClick}
look=${this.#manifest?.meta.look || 'default'}
color=${this.#manifest?.meta.color || 'default'}
label=${ifDefined(
this.#manifest?.meta.label ? this.localize.string(this.#manifest.meta.label) : this.#manifest?.name,
)}
.disabled=${this._isDisabled}
.state=${this._buttonState}></uui-button>
`;
}
#renderActionMenu() {
return html`
<umb-workspace-action-menu
.items=${this._items}
color="${this.#manifest?.meta.color || 'default'}"
look="${this.#manifest?.meta.look || 'default'}"></umb-workspace-action-menu>
`;
}
override render() {
return when(
this._items.length,
() => html` <uui-button-group> ${this.#renderButton()} ${this.#renderActionMenu()} </uui-button-group> `,
() => this.#renderButton(),
);
}
}
export default UmbWorkspaceActionElement;
@@ -138,3 +184,7 @@ declare global {
'umb-workspace-action': UmbWorkspaceActionElement;
}
}
function ExtensionApiArgsMethod(manifest: ManifestWorkspaceActionMenuItem) {
return [{ meta: manifest.meta }];
}