create entity action menu element

This commit is contained in:
Mads Rasmussen
2023-02-02 16:37:36 +01:00
parent acf102220c
commit fbcf5495dc
9 changed files with 154 additions and 79 deletions

View File

@@ -12,7 +12,7 @@ export class TrashDocumentEntityAction {
constructor(host: UmbControllerHostInterface, key: string) {
this.#host = host;
this.#key = key;
this.#documentRepository = new UmbDocumentRepository(this.#host);
this.#documentRepository = new UmbDocumentRepository(this.#host); // TODO: make repository injectable
new UmbContextConsumerController(this.#host, UMB_MODAL_SERVICE_CONTEXT_TOKEN, (instance) => {
this.#modalService = instance;

View File

@@ -1,6 +1,6 @@
import { UUITextStyles } from '@umbraco-ui/uui-css/lib';
import { css, html } from 'lit';
import { customElement, property } from 'lit/decorators.js';
import { css, html, nothing } from 'lit';
import { customElement, property, state } from 'lit/decorators.js';
import type { UmbWorkspaceEntityElement } from '../../../shared/components/workspace/workspace-entity-element.interface';
import { UmbDocumentWorkspaceContext } from './document-workspace.context';
import { UmbLitElement } from '@umbraco-cms/element';
@@ -20,8 +20,12 @@ export class UmbDocumentWorkspaceElement extends UmbLitElement implements UmbWor
private _workspaceContext: UmbDocumentWorkspaceContext = new UmbDocumentWorkspaceContext(this);
@state()
_unique?: string;
public load(entityKey: string) {
this._workspaceContext.load(entityKey);
this._unique = entityKey;
}
public create(parentKey: string | null) {
@@ -29,7 +33,16 @@ export class UmbDocumentWorkspaceElement extends UmbLitElement implements UmbWor
}
render() {
return html`<umb-workspace-content entity-type="document" alias="Umb.Workspace.Document"></umb-workspace-content>`;
return html`<umb-workspace-content alias="Umb.Workspace.Document">
${this._unique
? html`
<umb-workspace-action-menu
slot="action-menu"
entity-type="document"
unique="${this._unique}"></umb-workspace-action-menu>
`
: nothing}
</umb-workspace-content>`;
}
}

View File

@@ -0,0 +1,18 @@
import { TrashMediaEntityAction } from './trash-media.entity-action';
import { ManifestEntityAction } from 'libs/extensions-registry/entity-action.models';
const entityActions: Array<ManifestEntityAction> = [
{
type: 'entityAction',
alias: 'Umb.EntityAction.Media.Trash',
name: 'Trash Media Entity Action ',
meta: {
entityType: 'media',
icon: 'umb:trash',
label: 'Trash',
api: TrashMediaEntityAction,
},
},
];
export const manifests = [...entityActions];

View File

@@ -0,0 +1,15 @@
import { UmbControllerHostInterface } from '@umbraco-cms/controller';
export class TrashMediaEntityAction {
#host: UmbControllerHostInterface;
#key: string;
constructor(host: UmbControllerHostInterface, key: string) {
this.#host = host;
this.#key = key;
}
async execute() {
alert('trash media');
}
}

View File

@@ -1,5 +1,11 @@
import { manifests as sidebarMenuItemManifests } from './sidebar-menu-item/manifests';
import { manifests as treeManifests } from './tree/manifests';
import { manifests as workspaceManifests } from './workspace/manifests';
import { manifests as entityActionsManifests } from './entity-actions/manifests';
export const manifests = [...sidebarMenuItemManifests, ...treeManifests, ...workspaceManifests];
export const manifests = [
...sidebarMenuItemManifests,
...treeManifests,
...workspaceManifests,
...entityActionsManifests,
];

View File

@@ -14,3 +14,4 @@ import './section/section-sidebar/section-sidebar.element';
import './section/section.element';
import './tree/tree.element';
import './workspace/workspace-content/workspace-content.element';
import './workspace/workspace-action-menu/workspace-action-menu.element';

View File

@@ -0,0 +1,88 @@
import { UUITextStyles } from '@umbraco-ui/uui-css';
import { css, html } from 'lit';
import { customElement, property, state } from 'lit/decorators.js';
import { UmbLitElement } from '@umbraco-cms/element';
import { umbExtensionsRegistry } from '@umbraco-cms/extensions-api';
import { ManifestEntityAction } from 'libs/extensions-registry/entity-action.models';
@customElement('umb-workspace-action-menu')
export class UmbWorkspaceActionMenuElement extends UmbLitElement {
static styles = [
UUITextStyles,
css`
#action-menu-popover {
display: block;
}
#action-menu-dropdown {
overflow: hidden;
z-index: -1;
background-color: var(--uui-combobox-popover-background-color, var(--uui-color-surface));
border: 1px solid var(--uui-color-border);
border-radius: var(--uui-border-radius);
width: 100%;
height: 100%;
box-sizing: border-box;
box-shadow: var(--uui-shadow-depth-3);
width: 500px;
}
`,
];
private _entityType = '';
@property({ type: String, attribute: 'entity-type' })
public get entityType() {
return this._entityType;
}
public set entityType(value) {
const oldValue = this._entityType;
this._entityType = value;
if (oldValue !== this._entityType) {
this.#observeEntityActions();
this.requestUpdate('entityType', oldValue);
}
}
@state()
private _entityActions?: Array<ManifestEntityAction>;
@state()
private _actionMenuIsOpen = false;
#observeEntityActions() {
// TODO: filter on entity type
this.observe(umbExtensionsRegistry.extensionsOfType('entityAction'), (actions) => {
this._entityActions = actions;
});
}
#close() {
this._actionMenuIsOpen = false;
}
#open() {
this._actionMenuIsOpen = true;
}
render() {
return html` ${this.#renderActionsMenu()} `;
}
#renderActionsMenu() {
return html`
<uui-popover id="action-menu-popover" .open=${this._actionMenuIsOpen} @close=${this.#close}>
<uui-button slot="trigger" label="Actions" @click=${this.#open}></uui-button>
<div id="action-menu-dropdown" slot="popover">
<uui-scroll-container>
${this._entityActions?.map((manifest) => html`<umb-entity-action .manifest=${manifest}></umb-entity-action>`)}
</uui-scroll-container>
</div>
</uui-popover>
</div>`;
}
}
declare global {
interface HTMLElementTagNameMap {
'umb-workspace-action-menu': UmbWorkspaceActionMenuElement;
}
}

View File

@@ -1,6 +1,6 @@
import { UUITextStyles } from '@umbraco-ui/uui-css/lib';
import { css, html } from 'lit';
import { customElement, property } from 'lit/decorators.js';
import { customElement, property, state } from 'lit/decorators.js';
import '../workspace-layout/workspace-layout.element';
import '../../variant-selector/variant-selector.element';
@@ -11,6 +11,8 @@ import './views/edit/workspace-view-content-edit.element';
import './views/info/workspace-view-content-info.element';
import { UmbLitElement } from '@umbraco-cms/element';
import '../entity-action.element';
/**
* TODO: IMPORTANT TODO: Get rid of the content workspace. Instead we aim to get separate components that can be composed by each workspace.
* Example. Document Workspace would use a Variant-component(variant component would talk directly to the workspace-context)
@@ -43,16 +45,15 @@ export class UmbWorkspaceContentElement extends UmbLitElement {
@property()
alias!: string;
@property({ type: String, attribute: 'entity-type' })
public entityType = '';
render() {
return html`
<umb-workspace-layout entity-type=${this.entityType} alias=${this.alias}>
<umb-workspace-layout alias=${this.alias}>
<div id="header" slot="header">
<umb-variant-selector></umb-variant-selector>
</div>
<slot name="action-menu" slot="action-menu"></slot>
<div id="footer" slot="footer">Breadcrumbs</div>
</umb-workspace-layout>
`;

View File

@@ -16,9 +16,6 @@ import type {
import '../../body-layout/body-layout.element';
import '../../extension-slot/extension-slot.element';
import { UmbLitElement } from '@umbraco-cms/element';
import { ManifestEntityAction } from 'libs/extensions-registry/entity-action.models';
import '../entity-action.element';
/**
* @element umb-workspace-layout
@@ -61,39 +58,9 @@ export class UmbWorkspaceLayout extends UmbLitElement {
display: flex;
gap: var(--uui-size-space-2);
}
#action-menu-popover {
display: block;
}
#action-menu-dropdown {
overflow: hidden;
z-index: -1;
background-color: var(--uui-combobox-popover-background-color, var(--uui-color-surface));
border: 1px solid var(--uui-color-border);
border-radius: var(--uui-border-radius);
width: 100%;
height: 100%;
box-sizing: border-box;
box-shadow: var(--uui-shadow-depth-3);
width: 500px;
}
`,
];
private _entityType = '';
@property({ type: String, attribute: 'entity-type' })
public get entityType() {
return this._entityType;
}
public set entityType(value) {
const oldValue = this._entityType;
this._entityType = value;
if (oldValue !== this._entityType) {
this.#observeEntityActions();
this.requestUpdate('entityType', oldValue);
}
}
@property()
public headline = '';
@@ -130,15 +97,6 @@ export class UmbWorkspaceLayout extends UmbLitElement {
@state()
private _activePath?: string;
@state()
private _entityActions?: Array<ManifestEntityAction>;
#observeEntityActions() {
this.observe(umbExtensionsRegistry.extensionsOfType('entityAction'), (actions) => {
this._entityActions = actions;
});
}
private _observeWorkspaceViews() {
this.observe(
umbExtensionsRegistry
@@ -188,7 +146,8 @@ export class UmbWorkspaceLayout extends UmbLitElement {
return html`
<umb-body-layout .headline=${this.headline}>
<slot name="header" slot="header"></slot>
${this.#renderTabs()} ${this.#renderActionsMenu()}
${this.#renderTabs()}
<slot name="action-menu" slot="action-menu"></slot>
<umb-router-slot
.routes="${this._routes}"
@@ -234,32 +193,6 @@ export class UmbWorkspaceLayout extends UmbLitElement {
: nothing}
`;
}
@state()
private _actionMenuIsOpen = false;
#close() {
this._actionMenuIsOpen = false;
}
#open() {
this._actionMenuIsOpen = true;
}
#renderActionsMenu() {
return html`
<div slot="action-menu">
<uui-popover id="action-menu-popover" .open=${this._actionMenuIsOpen} @close=${this.#close}>
<uui-button slot="trigger" label="Actions" @click=${this.#open}></uui-button>
<div id="action-menu-dropdown" slot="popover">
<uui-scroll-container>
${this._entityActions?.map((manifest) => html`<umb-entity-action .manifest=${manifest}></umb-entity-action>`)}
</uui-scroll-container>
</div>
</uui-popover>
</div>
</div>`;
}
}
declare global {