From 6fdb8984672d8d95546edf83f5517cda683e23b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 9 Jan 2025 10:15:42 +0100 Subject: [PATCH 1/5] ensure controller host destroys sub controllers (#17916) --- .../src/libs/controller-api/controller-host-element.mixin.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/libs/controller-api/controller-host-element.mixin.ts b/src/Umbraco.Web.UI.Client/src/libs/controller-api/controller-host-element.mixin.ts index 22278e8c61..34802081e5 100644 --- a/src/Umbraco.Web.UI.Client/src/libs/controller-api/controller-host-element.mixin.ts +++ b/src/Umbraco.Web.UI.Client/src/libs/controller-api/controller-host-element.mixin.ts @@ -26,8 +26,6 @@ export const UmbControllerHostElementMixin = ( super.disconnectedCallback?.(); this.hostDisconnected(); } - - override destroy(): void {} } return UmbControllerHostElementClass as unknown as HTMLElementConstructor & T; From 0eb6a160174cedf66e8179be855e0ca06fe5d6a7 Mon Sep 17 00:00:00 2001 From: Andy Butland Date: Thu, 9 Jan 2025 14:24:33 +0100 Subject: [PATCH 2/5] Reload children of destination after duplicate of content (#17878) * Reload children of destination after duplicate of content. * Revert changes to generic duplicate to action. * Don't assume entity type of duplicated item is the same as the destination. Instead treat as "document" unless destination unique is null, when it will be "document-root". * add todo back * remove console log --------- Co-authored-by: Mads Rasmussen --- .../duplicate/duplicate-document.action.ts | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/duplicate/duplicate-document.action.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/duplicate/duplicate-document.action.ts index a0d46d1456..6b2872c074 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/duplicate/duplicate-document.action.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/duplicate/duplicate-document.action.ts @@ -1,8 +1,9 @@ +import { UMB_DOCUMENT_ENTITY_TYPE, UMB_DOCUMENT_ROOT_ENTITY_TYPE } from '../../entity.js'; import { UMB_DUPLICATE_DOCUMENT_MODAL } from './modal/index.js'; import { UmbDuplicateDocumentRepository } from './repository/index.js'; import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; import { UMB_ACTION_EVENT_CONTEXT } from '@umbraco-cms/backoffice/action'; -import { UmbEntityActionBase, UmbRequestReloadStructureForEntityEvent } from '@umbraco-cms/backoffice/entity-action'; +import { UmbEntityActionBase, UmbRequestReloadChildrenOfEntityEvent } from '@umbraco-cms/backoffice/entity-action'; export class UmbDuplicateDocumentEntityAction extends UmbEntityActionBase { override async execute() { @@ -32,22 +33,28 @@ export class UmbDuplicateDocumentEntityAction extends UmbEntityActionBase }); if (!error) { - this.#reloadMenu(); + this.#reloadMenu(destinationUnique); } } catch (error) { console.log(error); } } - async #reloadMenu() { + async #reloadMenu(destinationUnique: string | null) { const actionEventContext = await this.getContext(UMB_ACTION_EVENT_CONTEXT); - const event = new UmbRequestReloadStructureForEntityEvent({ - unique: this.args.unique, - entityType: this.args.entityType, + + // When duplicating, the destination entity type may or may not be the same as that of + // the item selected for duplication (that is available in this.args). + // For documents though, we know the entity type will be "document", unless we are duplicating + // to the root (when the destinationUnique will be null). + const destinationEntityType = destinationUnique === null ? UMB_DOCUMENT_ROOT_ENTITY_TYPE : UMB_DOCUMENT_ENTITY_TYPE; + + const event = new UmbRequestReloadChildrenOfEntityEvent({ + unique: destinationUnique, + entityType: destinationEntityType, }); actionEventContext.dispatchEvent(event); - // TODO: Reload destination } } From 75e7bb48eae9399d978f9d643cd66a061f4b38c3 Mon Sep 17 00:00:00 2001 From: Andy Butland Date: Thu, 9 Jan 2025 16:19:33 +0100 Subject: [PATCH 3/5] Render all URLs in document workspace info tab and ensure protocol-less links can be used to access the intended URL. (#17926) * Render all URLs in document workspace info tab and ensure protocol-less links can be used to access the intended URL. * Removed unused import. * Removed scheme from resolved URL. --- ...ument-workspace-view-info-links.element.ts | 36 ++++++++++++++----- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info-links.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info-links.element.ts index 983a30607f..6bb1ebf9e5 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info-links.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info-links.element.ts @@ -10,6 +10,7 @@ import { UMB_ACTION_EVENT_CONTEXT } from '@umbraco-cms/backoffice/action'; import { observeMultiple } from '@umbraco-cms/backoffice/observable-api'; import { DocumentVariantStateModel } from '@umbraco-cms/backoffice/external/backend-api'; import { debounce } from '@umbraco-cms/backoffice/utils'; +import { UMB_APP_LANGUAGE_CONTEXT } from '@umbraco-cms/backoffice/language'; interface UmbDocumentInfoViewLink { culture: string; @@ -36,6 +37,9 @@ export class UmbDocumentWorkspaceViewInfoLinksElement extends UmbLitElement { @state() private _links: Array = []; + @state() + private _defaultCulture?: string; + #urls: Array = []; #documentWorkspaceContext?: typeof UMB_DOCUMENT_WORKSPACE_CONTEXT.TYPE; @@ -75,17 +79,19 @@ export class UmbDocumentWorkspaceViewInfoLinksElement extends UmbLitElement { this.#setLinks(); }); }); + + this.consumeContext(UMB_APP_LANGUAGE_CONTEXT, (instance) => { + this.observe(instance.appDefaultLanguage, (value) => { + this._defaultCulture = value?.unique; + this.#setLinks(); + }); + }); } #setLinks() { - const possibleVariantCultures = this._variantOptions?.map((variantOption) => variantOption.culture) ?? []; - const possibleUrlCultures = this.#urls.map((link) => link.culture); - const possibleCultures = [...new Set([...possibleVariantCultures, ...possibleUrlCultures])].filter( - Boolean, - ) as string[]; - - const links: Array = possibleCultures.map((culture) => { - const url = this.#urls.find((link) => link.culture === culture)?.url; + const links: Array = this.#urls.map((u) => { + const culture = u.culture ?? this._defaultCulture ?? ""; + const url = u.url; const state = this._variantOptions?.find((variantOption) => variantOption.culture === culture)?.variant?.state; return { culture, url, state }; }); @@ -93,6 +99,18 @@ export class UmbDocumentWorkspaceViewInfoLinksElement extends UmbLitElement { this._links = links; } + #getTargetUrl (url: string | undefined) { + if (!url || url.length === 0) { + return url; + } + + if (url.includes(".") && !url.includes("//")) { + return "//" + url; + } + + return url; + } + async #requestUrls() { if (this._isNew) return; if (!this._unique) return; @@ -181,7 +199,7 @@ export class UmbDocumentWorkspaceViewInfoLinksElement extends UmbLitElement { } return html` - + ${this.#renderLinkCulture(link.culture)} ${link.url} From f86273616316344b45da8644b8f14910de9d8475 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 9 Jan 2025 20:23:28 +0100 Subject: [PATCH 4/5] make sure callback can be undefined --- .../src/libs/class-api/class.mixin.ts | 14 +++++++++----- .../src/libs/element-api/element.mixin.ts | 14 +++++++++----- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/libs/class-api/class.mixin.ts b/src/Umbraco.Web.UI.Client/src/libs/class-api/class.mixin.ts index d727346364..3cb7f91fc0 100644 --- a/src/Umbraco.Web.UI.Client/src/libs/class-api/class.mixin.ts +++ b/src/Umbraco.Web.UI.Client/src/libs/class-api/class.mixin.ts @@ -53,21 +53,25 @@ export const UmbClassMixin = >(superClas >( // This type dance checks if the Observable given could be undefined, if it potentially could be undefined it means that this potentially could return undefined and then call the callback with undefined. [NL] source: ObservableType, - callback: ObserverCallback, + callback?: ObserverCallback, controllerAlias?: UmbControllerAlias | null, ): SpecificR { - // Fallback to use a hash of the provided method, but only if the alias is undefined. - controllerAlias ??= controllerAlias === undefined ? simpleHashCode(callback.toString()) : undefined; + // Fallback to use a hash of the provided method, but only if the alias is undefined and there is a callback. + if (controllerAlias === undefined && callback) { + controllerAlias = simpleHashCode(callback.toString()); + } else { + controllerAlias = undefined; + } if (source) { return new UmbObserverController( this, source, - callback as unknown as ObserverCallback, + callback as unknown as ObserverCallback | undefined, controllerAlias, ) as unknown as SpecificR; } else { - callback(undefined as SpecificT); + callback?.(undefined as SpecificT); this.removeUmbControllerByAlias(controllerAlias); return undefined as SpecificR; } diff --git a/src/Umbraco.Web.UI.Client/src/libs/element-api/element.mixin.ts b/src/Umbraco.Web.UI.Client/src/libs/element-api/element.mixin.ts index 45f24e3351..dfb35472e9 100644 --- a/src/Umbraco.Web.UI.Client/src/libs/element-api/element.mixin.ts +++ b/src/Umbraco.Web.UI.Client/src/libs/element-api/element.mixin.ts @@ -29,21 +29,25 @@ export const UmbElementMixin = (superClass: T) >( // This type dance checks if the Observable given could be undefined, if it potentially could be undefined it means that this potentially could return undefined and then call the callback with undefined. [NL] source: ObservableType, - callback: ObserverCallback, + callback?: ObserverCallback, controllerAlias?: UmbControllerAlias | null, ): SpecificR { - // Fallback to use a hash of the provided method, but only if the alias is undefined. - controllerAlias ??= controllerAlias === undefined ? simpleHashCode(callback.toString()) : undefined; + // Fallback to use a hash of the provided method, but only if the alias is undefined and there is a callback. + if (controllerAlias === undefined && callback) { + controllerAlias = simpleHashCode(callback.toString()); + } else { + controllerAlias = undefined; + } if (source) { return new UmbObserverController( this, source, - callback as unknown as ObserverCallback, + callback as unknown as ObserverCallback | undefined, controllerAlias, ) as unknown as SpecificR; } else { - callback(undefined as SpecificT); + callback?.(undefined as SpecificT); this.removeUmbControllerByAlias(controllerAlias); return undefined as SpecificR; } From bd456a1dfaf6dcdd869f2adc059fd963740bf5e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 9 Jan 2025 20:28:58 +0100 Subject: [PATCH 5/5] correct null case --- src/Umbraco.Web.UI.Client/src/libs/class-api/class.mixin.ts | 3 ++- .../src/libs/element-api/element.mixin.ts | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/libs/class-api/class.mixin.ts b/src/Umbraco.Web.UI.Client/src/libs/class-api/class.mixin.ts index 3cb7f91fc0..0b1c893bcd 100644 --- a/src/Umbraco.Web.UI.Client/src/libs/class-api/class.mixin.ts +++ b/src/Umbraco.Web.UI.Client/src/libs/class-api/class.mixin.ts @@ -59,7 +59,8 @@ export const UmbClassMixin = >(superClas // Fallback to use a hash of the provided method, but only if the alias is undefined and there is a callback. if (controllerAlias === undefined && callback) { controllerAlias = simpleHashCode(callback.toString()); - } else { + } else if (controllerAlias === null) { + // if value is null, then reset it to undefined. Null is used to explicitly tell that we do not want a controller alias. [NL] controllerAlias = undefined; } diff --git a/src/Umbraco.Web.UI.Client/src/libs/element-api/element.mixin.ts b/src/Umbraco.Web.UI.Client/src/libs/element-api/element.mixin.ts index dfb35472e9..9b46710c58 100644 --- a/src/Umbraco.Web.UI.Client/src/libs/element-api/element.mixin.ts +++ b/src/Umbraco.Web.UI.Client/src/libs/element-api/element.mixin.ts @@ -35,7 +35,8 @@ export const UmbElementMixin = (superClass: T) // Fallback to use a hash of the provided method, but only if the alias is undefined and there is a callback. if (controllerAlias === undefined && callback) { controllerAlias = simpleHashCode(callback.toString()); - } else { + } else if (controllerAlias === null) { + // if value is null, then reset it to undefined. Null is used to explicitly tell that we do not want a controller alias. [NL] controllerAlias = undefined; }