SectionSidebarContextMenu: Delete element and methods for interaction (#20399)

Delete sction-sidebar-context-menu element + context methods
This commit is contained in:
Mads Rasmussen
2025-10-07 12:08:35 +02:00
committed by GitHub
parent 7c0b5b7dd4
commit e3d2001477
8 changed files with 7 additions and 230 deletions

View File

@@ -3,7 +3,6 @@ export * from './constants.js';
export * from './default/default-section.element.js'; export * from './default/default-section.element.js';
export * from './section-main/index.js'; export * from './section-main/index.js';
export * from './section-picker-modal/section-picker-modal.token.js'; export * from './section-picker-modal/section-picker-modal.token.js';
export * from './section-sidebar-context-menu/index.js';
export * from './section-sidebar/index.js'; export * from './section-sidebar/index.js';
export * from './section.context.js'; export * from './section.context.js';
export * from './section.context.token.js'; export * from './section.context.token.js';

View File

@@ -1 +0,0 @@
export * from './section-sidebar-context-menu.element.js';

View File

@@ -1,163 +0,0 @@
import type { UmbSectionSidebarContext } from '../section-sidebar/index.js';
import { UMB_SECTION_SIDEBAR_CONTEXT } from '../section-sidebar/index.js';
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
import { css, html, nothing, customElement, state, ref } from '@umbraco-cms/backoffice/external/lit';
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
import { observeMultiple } from '@umbraco-cms/backoffice/observable-api';
import { UmbContextProxyController } from '@umbraco-cms/backoffice/context-proxy';
@customElement('umb-section-sidebar-context-menu')
export class UmbSectionSidebarContextMenuElement extends UmbLitElement {
#sectionSidebarContext?: UmbSectionSidebarContext;
@state()
private _isOpen = false;
@state()
private _entityType?: string;
@state()
private _unique?: string | null;
@state()
private _headline?: string;
constructor() {
super();
this.consumeContext(UMB_SECTION_SIDEBAR_CONTEXT, (instance) => {
this.#sectionSidebarContext = instance;
this.#observeEntityModel();
if (this.#sectionSidebarContext) {
// make prettier not break the lines on the next 4 lines:
// prettier-ignore
this.observe( this.#sectionSidebarContext.contextMenuIsOpen, (value) => (this._isOpen = value), '_observeContextMenuIsOpen');
// prettier-ignore
this.observe(this.#sectionSidebarContext.headline, (value) => (this._headline = value), '_observeHeadline');
} else {
this.removeUmbControllerByAlias('_observeContextMenuIsOpen');
this.removeUmbControllerByAlias('_observeHeadline');
}
});
}
#observeEntityModel() {
if (!this.#sectionSidebarContext) {
this.removeUmbControllerByAlias('_observeEntityModel');
return;
}
this.observe(
observeMultiple([this.#sectionSidebarContext.unique, this.#sectionSidebarContext.entityType]),
(values) => {
this._unique = values[0];
this._entityType = values[1];
},
'_observeEntityModel',
);
}
#closeContextMenu() {
this.#sectionSidebarContext?.closeContextMenu();
}
#onActionExecuted(event: CustomEvent) {
event.stopPropagation();
this.#closeContextMenu();
}
#setupProxy(target: EventTarget | undefined) {
new UmbContextProxyController(this, target, () =>
this.#sectionSidebarContext?.getContextElement(),
).setIgnoreContextAliases([UMB_SECTION_SIDEBAR_CONTEXT.contextAlias]);
}
override render() {
return html`
${this.#renderBackdrop()}
<div id="relative-wrapper">
<slot></slot>
${this.#renderModal()}
</div>
`;
}
#renderBackdrop() {
// TODO: add keyboard support (close on escape)
return this._isOpen ? html`<div id="backdrop" @click=${this.#closeContextMenu}></div>` : nothing;
}
#renderModal() {
return this._isOpen && this._unique !== undefined && this._entityType
? html`<uui-scroll-container id="action-modal" ${ref(this.#setupProxy)}>
${this._headline ? html`<h3>${this.localize.string(this._headline)}</h3>` : nothing}
<umb-entity-action-list
@action-executed=${this.#onActionExecuted}
.entityType=${this._entityType}
.unique=${this._unique}></umb-entity-action-list>
</uui-scroll-container>`
: nothing;
}
static override styles = [
UmbTextStyles,
css`
:host {
display: block;
width: 100%;
height: 100%;
z-index: 1;
}
#backdrop {
content: '';
position: absolute;
inset: 0px;
background-color: black;
opacity: 0.5;
width: 100vw;
height: 100vh;
z-index: -1;
}
#relative-wrapper {
background-color: var(--uui-color-surface);
position: relative;
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
}
#action-modal {
position: absolute;
height: 100%;
z-index: 1;
top: 0;
right: calc(var(--umb-section-sidebar-width) * -1);
width: var(--umb-section-sidebar-width);
border: none;
border-left: 1px solid var(--uui-color-border);
border-right: 1px solid var(--uui-color-border);
background-color: var(--uui-color-surface);
}
#action-modal h3 {
padding: var(--uui-size-4) var(--uui-size-8);
margin: 0;
min-height: var(--umb-header-layout-height);
box-sizing: border-box;
display: flex;
align-items: center;
}
#action-modal umb-entity-action-list {
--uui-menu-item-flat-structure: 0;
}
`,
];
}
declare global {
interface HTMLElementTagNameMap {
'umb-section-sidebar-context-menu': UmbSectionSidebarContextMenuElement;
}
}

View File

@@ -1,2 +1,2 @@
export * from './section-sidebar.context.js';
export * from './section-sidebar.element.js'; export * from './section-sidebar.element.js';
export * from './section-sidebar.context.token.js';

View File

@@ -0,0 +1,4 @@
import type { UmbSectionSidebarContext } from './section-sidebar.context.js';
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
export const UMB_SECTION_SIDEBAR_CONTEXT = new UmbContextToken<UmbSectionSidebarContext>('UmbSectionSidebarContext');

View File

@@ -1,53 +1,9 @@
import type { UmbOpenContextMenuArgs } from './types.js'; import { UMB_SECTION_SIDEBAR_CONTEXT } from './section-sidebar.context.token.js';
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
import { UmbContextBase } from '@umbraco-cms/backoffice/class-api'; import { UmbContextBase } from '@umbraco-cms/backoffice/class-api';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import { UmbStringState, UmbBooleanState } from '@umbraco-cms/backoffice/observable-api';
export class UmbSectionSidebarContext extends UmbContextBase { export class UmbSectionSidebarContext extends UmbContextBase {
#contextMenuIsOpen = new UmbBooleanState(false);
contextMenuIsOpen = this.#contextMenuIsOpen.asObservable();
#entityType = new UmbStringState<undefined>(undefined);
entityType = this.#entityType.asObservable();
#unique = new UmbStringState<null | undefined>(undefined);
unique = this.#unique.asObservable();
#headline = new UmbStringState<undefined>(undefined);
headline = this.#headline.asObservable();
#contextElement: Element | undefined = undefined;
constructor(host: UmbControllerHost) { constructor(host: UmbControllerHost) {
super(host, UMB_SECTION_SIDEBAR_CONTEXT); super(host, UMB_SECTION_SIDEBAR_CONTEXT);
} }
toggleContextMenu(host: Element, args: UmbOpenContextMenuArgs) {
this.openContextMenu(host, args);
}
// TODO: we wont get notified about tree item name changes because we don't have a subscription
// we need to figure out how we best can handle this when we only know the entity and unique id
openContextMenu(host: Element, args: UmbOpenContextMenuArgs) {
this.#entityType.setValue(args.entityType);
this.#unique.setValue(args.unique);
this.#headline.setValue(args.headline);
this.#contextMenuIsOpen.setValue(true);
this.#contextElement = host;
}
closeContextMenu() {
this.#contextMenuIsOpen.setValue(false);
this.#entityType.setValue(undefined);
this.#unique.setValue(undefined);
this.#headline.setValue(undefined);
this.#contextElement = undefined;
}
getContextElement() {
return this.#contextElement;
}
} }
export const UMB_SECTION_SIDEBAR_CONTEXT = new UmbContextToken<UmbSectionSidebarContext>('UmbSectionSidebarContext');

View File

@@ -12,7 +12,7 @@ import { UmbBooleanState, UmbObjectState, UmbStringState } from '@umbraco-cms/ba
import { UmbContextBase } from '@umbraco-cms/backoffice/class-api'; import { UmbContextBase } from '@umbraco-cms/backoffice/class-api';
import { UmbDeprecation, debounce } from '@umbraco-cms/backoffice/utils'; import { UmbDeprecation, debounce } from '@umbraco-cms/backoffice/utils';
import { UmbParentEntityContext } from '@umbraco-cms/backoffice/entity'; import { UmbParentEntityContext } from '@umbraco-cms/backoffice/entity';
import { UMB_SECTION_CONTEXT, UMB_SECTION_SIDEBAR_CONTEXT } from '@umbraco-cms/backoffice/section'; import { UMB_SECTION_CONTEXT } from '@umbraco-cms/backoffice/section';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import type { UmbEntityModel, UmbEntityUnique } from '@umbraco-cms/backoffice/entity'; import type { UmbEntityModel, UmbEntityUnique } from '@umbraco-cms/backoffice/entity';
@@ -69,7 +69,6 @@ export abstract class UmbTreeItemContextBase<
public treeContext?: typeof UMB_TREE_CONTEXT.TYPE; public treeContext?: typeof UMB_TREE_CONTEXT.TYPE;
#sectionContext?: typeof UMB_SECTION_CONTEXT.TYPE; #sectionContext?: typeof UMB_SECTION_CONTEXT.TYPE;
#sectionSidebarContext?: typeof UMB_SECTION_SIDEBAR_CONTEXT.TYPE;
#parentContext = new UmbParentEntityContext(this); #parentContext = new UmbParentEntityContext(this);
@@ -172,18 +171,6 @@ export abstract class UmbTreeItemContextBase<
*/ */
public loadNextItems = (): Promise<void> => this.#treeItemChildrenManager.loadNextChildren(); public loadNextItems = (): Promise<void> => this.#treeItemChildrenManager.loadNextChildren();
public toggleContextMenu() {
if (!this.getTreeItem() || !this.entityType || this.unique === undefined) {
throw new Error('Could not request children, tree item is not set');
}
this.#sectionSidebarContext?.toggleContextMenu(this.getHostElement(), {
entityType: this.entityType,
unique: this.unique,
headline: this.getTreeItem()?.name || '',
});
}
/** /**
* Selects the tree item * Selects the tree item
* @memberof UmbTreeItemContextBase * @memberof UmbTreeItemContextBase
@@ -241,10 +228,6 @@ export abstract class UmbTreeItemContextBase<
this.#observeSectionPath(); this.#observeSectionPath();
}); });
this.consumeContext(UMB_SECTION_SIDEBAR_CONTEXT, (instance) => {
this.#sectionSidebarContext = instance;
});
this.consumeContext(UMB_TREE_CONTEXT, (treeContext) => { this.consumeContext(UMB_TREE_CONTEXT, (treeContext) => {
this.treeContext = treeContext; this.treeContext = treeContext;
this.#observeIsSelectable(); this.#observeIsSelectable();

View File

@@ -25,7 +25,6 @@ export interface UmbTreeItemContext<TreeItemType extends UmbTreeItemModel = UmbT
targetPagination: UmbTargetPaginationManager; targetPagination: UmbTargetPaginationManager;
getTreeItem(): TreeItemType | undefined; getTreeItem(): TreeItemType | undefined;
setTreeItem(treeItem: TreeItemType | undefined): void; setTreeItem(treeItem: TreeItemType | undefined): void;
toggleContextMenu(): void;
select(): void; select(): void;
deselect(): void; deselect(): void;
constructPath(pathname: string, entityType: string, unique: string): string; constructPath(pathname: string, entityType: string, unique: string): string;