Compare commits

...
Author SHA1 Message Date
Niels Lyngsø 42ae5f1ac9 Merge branch 'release/16.0' into v16/feature/context-proxy
# Conflicts:
#	src/Umbraco.Web.UI.Client/src/packages/core/repository/detail/detail-repository-base.ts
#	src/Umbraco.Web.UI.Client/src/packages/core/tree/default/default-tree.element.ts
2025-04-24 21:24:54 +02:00
Niels Lyngsø 5260aab5c8 implement UmbContextProxy 2025-04-24 21:22:47 +02:00
Niels Lyngsø 3d47dda810 use it self as host 2025-04-24 20:38:49 +02:00
Mads Rasmussen 275478cd93 Merge branch 'v16/dev' into v16/feature/consume-can-be-undefined 2025-04-24 08:54:57 +02:00
Niels LyngsøandGitHub 148935a3fc Merge branch 'v16/dev' into v16/feature/consume-can-be-undefined 2025-04-24 07:59:13 +02:00
Niels Lyngsø b69ab3ad78 make tree store optional 2025-04-23 19:54:41 +02:00
Niels Lyngsø 5adc4702a8 remove log 2025-04-23 16:02:49 +02:00
Niels Lyngsø 5b54e8e469 enable UmbRelationTypeDetailRepository store to be undefined 2025-04-23 16:02:29 +02:00
Niels Lyngsø 5b05094fa2 enable store to be undefined 2025-04-23 16:01:27 +02:00
Mads Rasmussen af004230b2 Update repository-details.manager.ts 2025-04-23 15:15:38 +02:00
Mads RasmussenandGitHub a917858265 Merge branch 'v16/dev' into v16/feature/consume-can-be-undefined 2025-04-23 15:10:12 +02:00
Niels Lyngsø a3848077b4 fix context consumption 2025-04-23 14:37:14 +02:00
Niels Lyngsø 3fc1c3afee more clean up 2025-04-23 14:30:40 +02:00
Niels LyngsøandGitHub f181c2f82b Merge branch 'v16/dev' into v16/feature/consume-can-be-undefined 2025-04-23 13:44:23 +02:00
Niels Lyngsø e4424ff0b5 handle context unprovide 2025-04-23 12:03:10 +02:00
Niels Lyngsø 339c852ec2 Merge branch 'v16/dev' into v16/feature/consume-can-be-undefined
# Conflicts:
#	src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-split-view/workspace-split-view-variant-selector.element.ts
2025-04-23 11:28:06 +02:00
Niels Lyngsø c0bd937216 catch 2025-04-23 11:27:09 +02:00
Niels Lyngsø 7062042cbc catch modal registration that has been destroyed 2025-04-23 11:21:37 +02:00
Niels Lyngsø af0abf252a fix tests 2025-04-23 11:21:24 +02:00
Niels Lyngsø d9a0f3af02 fix tests 2025-04-23 11:10:17 +02:00
Niels Lyngsø 60af1e88f0 Merge branch 'v16/dev' into v16/feature/consume-can-be-undefined 2025-04-23 10:34:35 +02:00
Niels Lyngsø 0ea16b41b8 correct context consumption 2025-04-23 10:30:57 +02:00
Niels Lyngsø ba33de49e7 correct type to use UMB_SUBMITTABLE_WORKSPACE_CONTEXT 2025-04-23 10:29:25 +02:00
Niels Lyngsø ac81973e3b use UMB_ENTITY_WORKSPACE_CONTEXT for right typing 2025-04-23 10:26:36 +02:00
Niels Lyngsø 8fe9599e91 support context not begin present 2025-04-23 10:12:16 +02:00
Niels Lyngsø e017167f57 support gone context 2025-04-23 10:12:08 +02:00
Niels Lyngsø 79ea5c12c1 fix requestAuditLogs 2025-04-23 10:09:48 +02:00
Niels Lyngsø c171882d55 fix resetting structure manager 2025-04-23 10:06:59 +02:00
Niels Lyngsø 20a3e08ae0 fix not existing store 2025-04-23 09:59:44 +02:00
Niels Lyngsø 049fad3261 always return permitted to onChange callback 2025-04-23 09:55:30 +02:00
Niels Lyngsø ede48c1b8b Merge branch 'v16/dev' into v16/feature/consume-can-be-undefined 2025-04-23 09:38:53 +02:00
Niels Lyngsø 1c93d1e6e1 Merge branch 'v16/dev' into v16/feature/consume-can-be-undefined 2025-04-23 09:36:19 +02:00
Niels Lyngsø 3c6cb488d7 do not throw an error when missing 2025-04-23 09:35:41 +02:00
Niels Lyngsø 33ed2482d8 correct error handling 2025-04-23 09:35:29 +02:00
Niels Lyngsø 056656042b correct types 2025-04-23 09:35:19 +02:00
Niels Lyngsø e3eec6ce1f update comment 2025-04-23 09:35:08 +02:00
Niels Lyngsø 37c9d20d60 callback with undefined when disconnected 2025-04-22 22:11:34 +02:00
Niels Lyngsø f2a22bc51b posible undefined context 2025-04-22 22:11:22 +02:00
Niels Lyngsø 3baf6faed4 reset target on disconnect 2025-04-22 22:04:26 +02:00
Niels Lyngsø a4453243e6 refactor UmbContextBase to not use generic types 2025-04-22 21:57:32 +02:00
Niels Lyngsø a24058a0ab jsdocs 2025-04-22 20:42:22 +02:00
Niels Lyngsø 548b14610c rename 2025-04-22 19:59:52 +02:00
Niels Lyngsø bca39401ac unprovide context 2025-04-22 16:48:44 +02:00
Niels Lyngsø b072a4ab60 a few more undefined context handlings 2025-04-22 16:48:37 +02:00
Niels Lyngsø fca17b87da Merge branch 'v16/dev' into v16/feature/consume-can-be-undefined 2025-04-22 16:11:42 +02:00
Niels Lyngsø 0b93561a06 make consume return undefined 2025-04-21 23:34:45 +02:00
Niels Lyngsø 01ea259d74 make consume return undefined 2025-04-21 23:25:43 +02:00
8 changed files with 87 additions and 33 deletions
+1
View File
@@ -10,6 +10,7 @@
"./context-api": "./dist-cms/libs/context-api/index.js",
"./controller-api": "./dist-cms/libs/controller-api/index.js",
"./element-api": "./dist-cms/libs/element-api/index.js",
"./context-proxy": "./dist-cms/libs/context-proxy/index.js",
"./embedded-media": "./dist-cms/packages/embedded-media/index.js",
"./extension-api": "./dist-cms/libs/extension-api/index.js",
"./extension-types": "./dist-cms/packages/extension-types/index.d.ts",
@@ -7,6 +7,7 @@ export const UMB_CONTEXT_PROVIDE_EVENT_TYPE = 'umb:context-provide';
*/
export interface UmbContextProvideEvent extends Event {
readonly contextAlias: string | UmbContextToken;
clone(): UmbContextProvideEvent;
}
/**
@@ -18,6 +19,9 @@ export class UmbContextProvideEventImplementation extends Event implements UmbCo
public constructor(public readonly contextAlias: string | UmbContextToken) {
super(UMB_CONTEXT_PROVIDE_EVENT_TYPE, { bubbles: true, composed: true });
}
public clone(): UmbContextProvideEvent {
return new UmbContextProvideEventImplementation(this.contextAlias);
}
}
export const isUmbContextProvideEventType = (event: Event): event is UmbContextProvideEventImplementation => {
@@ -0,0 +1,64 @@
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import {
UMB_CONTEXT_PROVIDE_EVENT_TYPE,
UMB_CONTEXT_REQUEST_EVENT_TYPE,
type UmbContextProvideEvent,
type UmbContextRequestEvent,
} from '@umbraco-cms/backoffice/context-api';
import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api';
const CtrlAlias = Symbol();
/**
* @internal
* This controller creates a Proxy for the Context API.
* @description It is not advised for anyone to implement this unless they know exactly what they are doing.
*/
export class UmbContextProxy extends UmbControllerBase {
#target?: EventTarget;
#getDestination: () => EventTarget | undefined;
#ignorer: Array<string> = [];
constructor(host: UmbControllerHost, target: EventTarget | undefined, getDestination: () => EventTarget | undefined) {
super(host, CtrlAlias);
this.#target = target;
this.#getDestination = getDestination;
// Only handle something if there is a target. This could seem stupid, but since we support construction this controller despite a missing element, we enable the controller to destroy an already existing controller. aka replace it. [NL]
if (target) {
target.addEventListener(UMB_CONTEXT_REQUEST_EVENT_TYPE, this.#onContextRequest as EventListener);
target.addEventListener(UMB_CONTEXT_PROVIDE_EVENT_TYPE, this.#onContextProvide as EventListener);
}
}
/* We do not currently have a good enough control to ensure that the proxy is last, meaning if another context is provided at this element, it might respond after the proxy event has been dispatched.
To avoid such you can declare context aliases to be ignorer by the proxy.
*/
setIgnoreContextAliases(aliases: Array<string>) {
this.#ignorer = aliases;
return this;
}
#onContextRequest = (event: UmbContextRequestEvent) => {
const destination = this.#getDestination();
if (destination && !this.#ignorer.includes(event.contextAlias)) {
event.stopImmediatePropagation();
destination.dispatchEvent(event.clone());
}
};
#onContextProvide = (event: UmbContextProvideEvent) => {
const destination = this.#getDestination();
if (destination) {
event.stopPropagation();
destination.dispatchEvent(event.clone());
}
};
override destroy() {
super.destroy();
if (this.#target) {
this.#target.removeEventListener(UMB_CONTEXT_REQUEST_EVENT_TYPE, this.#onContextRequest as EventListener);
this.#target.removeEventListener(UMB_CONTEXT_PROVIDE_EVENT_TYPE, this.#onContextProvide as EventListener);
}
}
}
@@ -0,0 +1 @@
export * from './context-proxy.controller.js';
@@ -17,12 +17,8 @@ import {
} from '@umbraco-cms/backoffice/external/uui';
import { UMB_ROUTE_CONTEXT, type UmbRouterSlotElement } from '@umbraco-cms/backoffice/router';
import { createExtensionElement, loadManifestElement } from '@umbraco-cms/backoffice/extension-api';
import type { UmbContextRequestEvent } from '@umbraco-cms/backoffice/context-api';
import {
UMB_CONTEXT_REQUEST_EVENT_TYPE,
UmbContextBoundary,
UmbContextProvider,
} from '@umbraco-cms/backoffice/context-api';
import { UmbContextBoundary, UmbContextProvider } from '@umbraco-cms/backoffice/context-api';
import { UmbContextProxy } from '@umbraco-cms/backoffice/context-proxy';
@customElement('umb-modal')
export class UmbModalElement extends UmbLitElement {
@@ -64,18 +60,9 @@ export class UmbModalElement extends UmbLitElement {
// Makes sure that the modal triggers the reject of the context promise when it is closed by pressing escape.
this.element.addEventListener(UUIModalCloseEvent, this.#onClose);
// The following code is the context api proxy.
// It re-dispatches the context api request event to the origin target of this modal, in other words the element that initiated the modal. [NL]
this.element.addEventListener(UMB_CONTEXT_REQUEST_EVENT_TYPE, ((event: UmbContextRequestEvent) => {
if (!this.#modalContext) return;
// Note for this hack (The if-sentence): [NL]
// We do not currently have a good enough control to ensure that the proxy is last, meaning if another context is provided at this element, it might respond after the proxy event has been dispatched.
// To avoid such this hack just prevents proxying the event if its a request for the Modal Context. [NL]
if (event.contextAlias !== UMB_MODAL_CONTEXT.contextAlias) {
event.stopImmediatePropagation();
this.#modalContext.getHostElement().dispatchEvent(event.clone());
}
}) as EventListener);
new UmbContextProxy(this, this.element, () => this.#modalContext?.getHostElement()).setIgnoreContextAliases([
UMB_MODAL_CONTEXT.contextAlias,
]);
this.#modalContext.onSubmit().then(
() => {
@@ -1,10 +1,10 @@
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 } from '@umbraco-cms/backoffice/external/lit';
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 type { UmbContextRequestEvent } from '@umbraco-cms/backoffice/context-api';
import { UmbContextProxy } from '@umbraco-cms/backoffice/context-proxy';
@customElement('umb-section-sidebar-context-menu')
export class UmbSectionSidebarContextMenuElement extends UmbLitElement {
@@ -67,15 +67,10 @@ export class UmbSectionSidebarContextMenuElement extends UmbLitElement {
this.#closeContextMenu();
}
#proxyContextRequests(event: UmbContextRequestEvent) {
if (!this.#sectionSidebarContext) return;
// Note for this hack (The if-sentence): [NL]
// We do not currently have a good enough control to ensure that the proxy is last, meaning if another context is provided at this element, it might respond after the proxy event has been dispatched.
// To avoid such this hack just prevents proxying the event if its a request for its own context.
if (event.contextAlias !== UMB_SECTION_SIDEBAR_CONTEXT.contextAlias) {
event.stopImmediatePropagation();
this.#sectionSidebarContext.getContextElement()?.dispatchEvent(event.clone());
}
#setupProxy(target: EventTarget | undefined) {
new UmbContextProxy(this, target, () => this.#sectionSidebarContext?.getContextElement()).setIgnoreContextAliases([
UMB_SECTION_SIDEBAR_CONTEXT.contextAlias,
]);
}
override render() {
@@ -96,7 +91,7 @@ export class UmbSectionSidebarContextMenuElement extends UmbLitElement {
#renderModal() {
return this._isOpen && this._unique !== undefined && this._entityType
? html`<uui-scroll-container id="action-modal" @umb:context-request=${this.#proxyContextRequests}>
? 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}
@@ -38,9 +38,9 @@ export class UmbDefaultTreeContext<
public selectableFilter?: (item: TreeItemType) => boolean = () => true;
public filter?: (item: TreeItemType) => boolean = () => true;
public readonly selection = new UmbSelectionManager(this._host);
public readonly selection = new UmbSelectionManager(this);
public readonly pagination = new UmbPaginationManager();
public readonly expansion = new UmbTreeExpansionManager(this._host);
public readonly expansion = new UmbTreeExpansionManager(this);
#hideTreeRoot = new UmbBooleanState(false);
hideTreeRoot = this.#hideTreeRoot.asObservable();
@@ -78,6 +78,7 @@ export class UmbDefaultTreeContext<
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
super(host, UMB_TREE_CONTEXT);
this.pagination.setPageSize(this.#paging.take);
this.#consumeContexts();
@@ -373,7 +374,7 @@ export class UmbDefaultTreeContext<
this,
umbExtensionsRegistry,
repositoryAlias,
[this._host],
[this],
(permitted, ctrl) => {
this.#repository = permitted ? ctrl.api : undefined;
this.#checkIfInitialized();
+1
View File
@@ -38,6 +38,7 @@ DON'T EDIT THIS FILE DIRECTLY. It is generated by /devops/tsconfig/index.js
"@umbraco-cms/backoffice/context-api": ["./src/libs/context-api/index.ts"],
"@umbraco-cms/backoffice/controller-api": ["./src/libs/controller-api/index.ts"],
"@umbraco-cms/backoffice/element-api": ["./src/libs/element-api/index.ts"],
"@umbraco-cms/backoffice/context-proxy": ["./src/libs/context-proxy/index.ts"],
"@umbraco-cms/backoffice/embedded-media": ["./src/packages/embedded-media/index.ts"],
"@umbraco-cms/backoffice/extension-api": ["./src/libs/extension-api/index.ts"],
"@umbraco-cms/backoffice/localization-api": ["./src/libs/localization-api/index.ts"],