From 94692cccb71c6f08b469d4b616d9ccdd10f979d3 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 20 Oct 2025 13:43:10 +0200 Subject: [PATCH] Document/Media Recycle Bin: Show full breadcrumb (#20547) * register structure context for recycle bin * Update manifests.ts * export consts * move href construction to context + override for document and media --- ...t-structure-workspace-context.interface.ts | 1 + ...t-tree-structure-workspace-context-base.ts | 38 ++++++++++++++- ...rkspace-variant-menu-breadcrumb.element.ts | 25 +++------- .../menu/document-menu-structure.context.ts | 14 +++++- .../documents/documents/menu/manifests.ts | 5 +- .../documents/recycle-bin/constants.ts | 1 + .../documents/recycle-bin/manifests.ts | 4 +- .../recycle-bin/menu-item/manifests.ts | 23 ---------- .../documents/recycle-bin/menu/constants.ts | 1 + ...ment-recycle-bin-menu-structure.context.ts | 11 +++++ .../documents/recycle-bin/menu/manifests.ts | 46 +++++++++++++++++++ .../packages/media/media/menu/manifests.ts | 6 +-- .../menu/media-menu-structure.context.ts | 14 +++++- .../media/media/recycle-bin/constants.ts | 3 +- .../media/media/recycle-bin/manifests.ts | 4 +- .../media/recycle-bin/menu-item/manifests.ts | 22 --------- .../media/media/recycle-bin/menu/constants.ts | 1 + .../media/media/recycle-bin/menu/manifests.ts | 44 ++++++++++++++++++ ...edia-recycle-bin-menu-structure.context.ts | 11 +++++ 19 files changed, 197 insertions(+), 77 deletions(-) delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/menu-item/manifests.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/menu/constants.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/menu/document-recycle-bin-menu-structure.context.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/menu/manifests.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/menu-item/manifests.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/menu/constants.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/menu/manifests.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/menu/media-recycle-bin-menu-structure.context.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/menu/menu-variant-structure-workspace-context.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/menu/menu-variant-structure-workspace-context.interface.ts index ade079e3cc..bea694e43b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/menu/menu-variant-structure-workspace-context.interface.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/menu/menu-variant-structure-workspace-context.interface.ts @@ -4,4 +4,5 @@ import type { Observable } from '@umbraco-cms/backoffice/external/rxjs'; export interface UmbMenuVariantStructureWorkspaceContext extends UmbContext { structure: Observable; + getItemHref(structureItem: UmbVariantStructureItemModel): string | undefined; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/menu/menu-variant-tree-structure-workspace-context-base.ts b/src/Umbraco.Web.UI.Client/src/packages/core/menu/menu-variant-tree-structure-workspace-context-base.ts index 5cd6290474..db57dba46c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/menu/menu-variant-tree-structure-workspace-context-base.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/menu/menu-variant-tree-structure-workspace-context-base.ts @@ -7,9 +7,14 @@ import { UmbContextBase } from '@umbraco-cms/backoffice/class-api'; import { UmbArrayState, UmbObjectState } from '@umbraco-cms/backoffice/observable-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { UmbAncestorsEntityContext, UmbParentEntityContext, type UmbEntityModel } from '@umbraco-cms/backoffice/entity'; -import { UMB_SUBMITTABLE_TREE_ENTITY_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace'; +import { + UMB_SUBMITTABLE_TREE_ENTITY_WORKSPACE_CONTEXT, + UMB_VARIANT_WORKSPACE_CONTEXT, +} from '@umbraco-cms/backoffice/workspace'; import { linkEntityExpansionEntries } from '@umbraco-cms/backoffice/utils'; import { UMB_MODAL_CONTEXT } from '@umbraco-cms/backoffice/modal'; +import { UMB_SECTION_CONTEXT } from '@umbraco-cms/backoffice/section'; +import { UmbVariantId } from '@umbraco-cms/backoffice/variant'; interface UmbMenuVariantTreeStructureWorkspaceContextBaseArgs { treeRepositoryAlias: string; @@ -31,11 +36,15 @@ export abstract class UmbMenuVariantTreeStructureWorkspaceContextBase extends Um */ public readonly parent = this.#parent.asObservable(); + protected _sectionContext?: typeof UMB_SECTION_CONTEXT.TYPE; + #parentContext = new UmbParentEntityContext(this); #ancestorContext = new UmbAncestorsEntityContext(this); #sectionSidebarMenuContext?: typeof UMB_SECTION_SIDEBAR_MENU_SECTION_CONTEXT.TYPE; #isModalContext: boolean = false; #isNew: boolean | undefined = undefined; + #variantWorkspaceContext?: typeof UMB_VARIANT_WORKSPACE_CONTEXT.TYPE; + #workspaceActiveVariantId?: UmbVariantId; public readonly IS_MENU_VARIANT_STRUCTURE_WORKSPACE_CONTEXT = true; @@ -49,6 +58,16 @@ export abstract class UmbMenuVariantTreeStructureWorkspaceContextBase extends Um this.#isModalContext = modalContext !== undefined; }); + this.consumeContext(UMB_SECTION_CONTEXT, (instance) => { + this._sectionContext = instance; + }); + + this.consumeContext(UMB_VARIANT_WORKSPACE_CONTEXT, (instance) => { + if (!instance) return; + this.#variantWorkspaceContext = instance; + this.#observeWorkspaceActiveVariant(); + }); + this.consumeContext(UMB_SECTION_SIDEBAR_MENU_SECTION_CONTEXT, (instance) => { this.#sectionSidebarMenuContext = instance; }); @@ -75,6 +94,10 @@ export abstract class UmbMenuVariantTreeStructureWorkspaceContextBase extends Um }); } + getItemHref(structureItem: UmbVariantStructureItemModel): string | undefined { + return `section/${this._sectionContext?.getPathname()}/workspace/${structureItem.entityType}/edit/${structureItem.unique}/${this.#workspaceActiveVariantId?.toCultureString()}`; + } + async #requestStructure() { const isNew = this.#workspaceContext?.getIsNew(); const uniqueObservable = isNew @@ -191,6 +214,19 @@ export abstract class UmbMenuVariantTreeStructureWorkspaceContextBase extends Um this.#sectionSidebarMenuContext?.expansion.expandItems(expandableItemsWithMenuItem); } + #observeWorkspaceActiveVariant() { + this.observe( + this.#variantWorkspaceContext?.splitView.activeVariantsInfo, + (value) => { + if (!value) return; + if (value?.length === 0) return; + this.#workspaceActiveVariantId = UmbVariantId.Create(value[0]); + }, + + 'breadcrumbWorkspaceActiveVariantObserver', + ); + } + override destroy(): void { super.destroy(); this.#structure.destroy(); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-breadcrumb/workspace-variant-menu-breadcrumb/workspace-variant-menu-breadcrumb.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-breadcrumb/workspace-variant-menu-breadcrumb/workspace-variant-menu-breadcrumb.element.ts index 04fe73d6a8..b11b0459c4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-breadcrumb/workspace-variant-menu-breadcrumb/workspace-variant-menu-breadcrumb.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-breadcrumb/workspace-variant-menu-breadcrumb/workspace-variant-menu-breadcrumb.element.ts @@ -6,7 +6,6 @@ import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { UmbVariantId } from '@umbraco-cms/backoffice/variant'; import { UMB_APP_LANGUAGE_CONTEXT } from '@umbraco-cms/backoffice/language'; import { UMB_MENU_VARIANT_STRUCTURE_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/menu'; -import { UMB_SECTION_CONTEXT } from '@umbraco-cms/backoffice/section'; import type { UmbAppLanguageContext } from '@umbraco-cms/backoffice/language'; import type { UmbVariantStructureItemModel } from '@umbraco-cms/backoffice/menu'; @@ -24,10 +23,9 @@ export class UmbWorkspaceVariantMenuBreadcrumbElement extends UmbLitElement { @state() private _appDefaultCulture?: string; - #sectionContext?: typeof UMB_SECTION_CONTEXT.TYPE; #workspaceContext?: UmbVariantDatasetWorkspaceContext; #appLanguageContext?: UmbAppLanguageContext; - #structureContext?: typeof UMB_MENU_VARIANT_STRUCTURE_WORKSPACE_CONTEXT.TYPE; + #menuStructureContext?: typeof UMB_MENU_VARIANT_STRUCTURE_WORKSPACE_CONTEXT.TYPE; constructor() { super(); @@ -37,10 +35,6 @@ export class UmbWorkspaceVariantMenuBreadcrumbElement extends UmbLitElement { this.#observeDefaultCulture(); }); - this.consumeContext(UMB_SECTION_CONTEXT, (instance) => { - this.#sectionContext = instance; - }); - this.consumeContext(UMB_VARIANT_WORKSPACE_CONTEXT, (instance) => { if (!instance) return; this.#workspaceContext = instance; @@ -50,15 +44,15 @@ export class UmbWorkspaceVariantMenuBreadcrumbElement extends UmbLitElement { this.consumeContext(UMB_MENU_VARIANT_STRUCTURE_WORKSPACE_CONTEXT, (instance) => { if (!instance) return; - this.#structureContext = instance; + this.#menuStructureContext = instance; this.#observeStructure(); }); } #observeStructure() { - if (!this.#structureContext || !this.#workspaceContext) return; + if (!this.#menuStructureContext || !this.#workspaceContext) return; - this.observe(this.#structureContext.structure, (value) => { + this.observe(this.#menuStructureContext.structure, (value) => { if (!this.#workspaceContext) return; const unique = this.#workspaceContext.getUnique(); // exclude the current unique from the structure. We append this with an observer of the name @@ -113,15 +107,8 @@ export class UmbWorkspaceVariantMenuBreadcrumbElement extends UmbLitElement { return structureItem.variants?.[0]?.name ?? '(#general_unknown)'; } - #getHref(structureItem: any) { - if (structureItem.isFolder) return undefined; - - let href = `section/${this.#sectionContext?.getPathname()}`; - if (structureItem.unique) { - href += `/workspace/${structureItem.entityType}/edit/${structureItem.unique}/${this._workspaceActiveVariantId?.toCultureString()}`; - } - - return href; + #getHref(structureItem: UmbVariantStructureItemModel) { + return this.#menuStructureContext?.getItemHref(structureItem); } override render() { diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/menu/document-menu-structure.context.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/menu/document-menu-structure.context.ts index 55caf0e070..6076367a37 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/menu/document-menu-structure.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/menu/document-menu-structure.context.ts @@ -1,11 +1,23 @@ import { UMB_DOCUMENT_TREE_REPOSITORY_ALIAS } from '../tree/index.js'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { UmbMenuVariantTreeStructureWorkspaceContextBase } from '@umbraco-cms/backoffice/menu'; +import { + UmbMenuVariantTreeStructureWorkspaceContextBase, + type UmbVariantStructureItemModel, +} from '@umbraco-cms/backoffice/menu'; export class UmbDocumentMenuStructureContext extends UmbMenuVariantTreeStructureWorkspaceContextBase { constructor(host: UmbControllerHost) { super(host, { treeRepositoryAlias: UMB_DOCUMENT_TREE_REPOSITORY_ALIAS }); } + + override getItemHref(structureItem: UmbVariantStructureItemModel): string | undefined { + // The Document menu does not have a root item, so we do not have a href for it. + if (!structureItem.unique) { + return `section/${this._sectionContext?.getPathname()}`; + } else { + return super.getItemHref(structureItem); + } + } } export default UmbDocumentMenuStructureContext; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/menu/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/menu/manifests.ts index 50309def83..d12af0177c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/menu/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/menu/manifests.ts @@ -1,3 +1,4 @@ +import { UMB_DOCUMENT_WORKSPACE_ALIAS } from '../constants.js'; import { UMB_DOCUMENT_TREE_ALIAS } from '../tree/index.js'; import { UMB_DOCUMENT_MENU_ITEM_ALIAS } from './constants.js'; import { UMB_ENTITY_IS_NOT_TRASHED_CONDITION_ALIAS } from '@umbraco-cms/backoffice/recycle-bin'; @@ -36,7 +37,7 @@ export const manifests: Array = [ conditions: [ { alias: UMB_WORKSPACE_CONDITION_ALIAS, - match: 'Umb.Workspace.Document', + match: UMB_DOCUMENT_WORKSPACE_ALIAS, }, { alias: UMB_ENTITY_IS_NOT_TRASHED_CONDITION_ALIAS, @@ -51,7 +52,7 @@ export const manifests: Array = [ conditions: [ { alias: UMB_WORKSPACE_CONDITION_ALIAS, - match: 'Umb.Workspace.Document', + match: UMB_DOCUMENT_WORKSPACE_ALIAS, }, ], }, diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/constants.ts index 0002782c2b..82db473915 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/constants.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/constants.ts @@ -1,3 +1,4 @@ +export * from './menu/constants.js'; export * from './repository/constants.js'; export * from './tree/constants.js'; export const UMB_DOCUMENT_RECYCLE_BIN_ROOT_ENTITY_TYPE = 'document-recycle-bin-root'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/manifests.ts index cc3ebf859f..55c305be6e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/manifests.ts @@ -1,5 +1,5 @@ import { manifests as entityActionManifests } from './entity-action/manifests.js'; -import { manifests as menuItemManifests } from './menu-item/manifests.js'; +import { manifests as menuManifests } from './menu/manifests.js'; import { manifests as repositoryManifests } from './repository/manifests.js'; import { manifests as treeManifests } from './tree/manifests.js'; @@ -11,7 +11,7 @@ export const manifests: Array = [ api: () => import('./allow-document-recycle-bin.condition.js'), }, ...entityActionManifests, - ...menuItemManifests, + ...menuManifests, ...repositoryManifests, ...treeManifests, ]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/menu-item/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/menu-item/manifests.ts deleted file mode 100644 index 65fca591fd..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/menu-item/manifests.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { UMB_CONTENT_MENU_ALIAS } from '../../menu/manifests.js'; -import { UMB_DOCUMENT_RECYCLE_BIN_TREE_ALIAS } from '../constants.js'; - -export const manifests: Array = [ - { - type: 'menuItem', - kind: 'tree', - alias: 'Umb.MenuItem.Document.RecycleBin', - name: 'Document Recycle Bin Menu Item', - weight: 100, - meta: { - treeAlias: UMB_DOCUMENT_RECYCLE_BIN_TREE_ALIAS, - label: 'Recycle Bin', - icon: 'icon-trash', - menus: [UMB_CONTENT_MENU_ALIAS], - }, - conditions: [ - { - alias: 'Umb.Condition.CurrentUser.AllowDocumentRecycleBin', - }, - ], - }, -]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/menu/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/menu/constants.ts new file mode 100644 index 0000000000..b7af8eaecb --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/menu/constants.ts @@ -0,0 +1 @@ +export const UMB_DOCUMENT_RECYCLE_BIN_MENU_ITEM_ALIAS = 'Umb.MenuItem.Document.RecycleBin'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/menu/document-recycle-bin-menu-structure.context.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/menu/document-recycle-bin-menu-structure.context.ts new file mode 100644 index 0000000000..94a68d442f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/menu/document-recycle-bin-menu-structure.context.ts @@ -0,0 +1,11 @@ +import { UMB_DOCUMENT_RECYCLE_BIN_TREE_REPOSITORY_ALIAS } from '../tree/constants.js'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import { UmbMenuVariantTreeStructureWorkspaceContextBase } from '@umbraco-cms/backoffice/menu'; + +export class UmbDocumentRecycleBinMenuStructureContext extends UmbMenuVariantTreeStructureWorkspaceContextBase { + constructor(host: UmbControllerHost) { + super(host, { treeRepositoryAlias: UMB_DOCUMENT_RECYCLE_BIN_TREE_REPOSITORY_ALIAS }); + } +} + +export { UmbDocumentRecycleBinMenuStructureContext as api }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/menu/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/menu/manifests.ts new file mode 100644 index 0000000000..9b53239f0f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/menu/manifests.ts @@ -0,0 +1,46 @@ +import { UMB_CONTENT_MENU_ALIAS } from '../../menu/manifests.js'; +import { UMB_DOCUMENT_RECYCLE_BIN_TREE_ALIAS } from '../constants.js'; +import { UMB_DOCUMENT_WORKSPACE_ALIAS } from '../../constants.js'; +import { UMB_DOCUMENT_RECYCLE_BIN_MENU_ITEM_ALIAS } from './constants.js'; +import { UMB_ENTITY_IS_TRASHED_CONDITION_ALIAS } from '@umbraco-cms/backoffice/recycle-bin'; +import { UMB_WORKSPACE_CONDITION_ALIAS } from '@umbraco-cms/backoffice/workspace'; + +export const manifests: Array = [ + { + type: 'menuItem', + kind: 'tree', + alias: UMB_DOCUMENT_RECYCLE_BIN_MENU_ITEM_ALIAS, + name: 'Document Recycle Bin Menu Item', + weight: 100, + meta: { + treeAlias: UMB_DOCUMENT_RECYCLE_BIN_TREE_ALIAS, + label: 'Recycle Bin', + icon: 'icon-trash', + menus: [UMB_CONTENT_MENU_ALIAS], + }, + conditions: [ + { + alias: 'Umb.Condition.CurrentUser.AllowDocumentRecycleBin', + }, + ], + }, + { + type: 'workspaceContext', + kind: 'menuStructure', + name: 'Document Recycle Bin Menu Structure Workspace Context', + alias: 'Umb.Context.DocumentRecycleBin.Menu.Structure', + api: () => import('./document-recycle-bin-menu-structure.context.js'), + meta: { + menuItemAlias: UMB_DOCUMENT_RECYCLE_BIN_MENU_ITEM_ALIAS, + }, + conditions: [ + { + alias: UMB_WORKSPACE_CONDITION_ALIAS, + match: UMB_DOCUMENT_WORKSPACE_ALIAS, + }, + { + alias: UMB_ENTITY_IS_TRASHED_CONDITION_ALIAS, + }, + ], + }, +]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/menu/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/menu/manifests.ts index 2d5ae3ad50..34de09b5b3 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/menu/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/menu/manifests.ts @@ -1,4 +1,4 @@ -import { UMB_MEDIA_TREE_ALIAS } from '../constants.js'; +import { UMB_MEDIA_TREE_ALIAS, UMB_MEDIA_WORKSPACE_ALIAS } from '../constants.js'; import { UMB_MEDIA_MENU_ALIAS, UMB_MEDIA_MENU_ITEM_ALIAS } from './constants.js'; import { UMB_ENTITY_IS_NOT_TRASHED_CONDITION_ALIAS } from '@umbraco-cms/backoffice/recycle-bin'; import { UMB_WORKSPACE_CONDITION_ALIAS } from '@umbraco-cms/backoffice/workspace'; @@ -34,7 +34,7 @@ export const manifests: Array = [ conditions: [ { alias: UMB_WORKSPACE_CONDITION_ALIAS, - match: 'Umb.Workspace.Media', + match: UMB_MEDIA_WORKSPACE_ALIAS, }, { alias: UMB_ENTITY_IS_NOT_TRASHED_CONDITION_ALIAS, @@ -49,7 +49,7 @@ export const manifests: Array = [ conditions: [ { alias: UMB_WORKSPACE_CONDITION_ALIAS, - match: 'Umb.Workspace.Media', + match: UMB_MEDIA_WORKSPACE_ALIAS, }, ], }, diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/menu/media-menu-structure.context.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/menu/media-menu-structure.context.ts index 156b745b3c..8fe321e470 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/menu/media-menu-structure.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/menu/media-menu-structure.context.ts @@ -1,11 +1,23 @@ import { UMB_MEDIA_TREE_REPOSITORY_ALIAS } from '../constants.js'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { UmbMenuVariantTreeStructureWorkspaceContextBase } from '@umbraco-cms/backoffice/menu'; +import { + UmbMenuVariantTreeStructureWorkspaceContextBase, + type UmbVariantStructureItemModel, +} from '@umbraco-cms/backoffice/menu'; export class UmbMediaMenuStructureContext extends UmbMenuVariantTreeStructureWorkspaceContextBase { constructor(host: UmbControllerHost) { super(host, { treeRepositoryAlias: UMB_MEDIA_TREE_REPOSITORY_ALIAS }); } + + override getItemHref(structureItem: UmbVariantStructureItemModel): string | undefined { + // The Media menu does not have a root item, so we do not have a href for it. + if (!structureItem.unique) { + return `section/${this._sectionContext?.getPathname()}`; + } else { + return super.getItemHref(structureItem); + } + } } export default UmbMediaMenuStructureContext; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/constants.ts index e05617eb5a..49ba8c8836 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/constants.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/constants.ts @@ -1,3 +1,4 @@ -export * from './tree/constants.js'; +export * from './menu/constants.js'; export * from './repository/constants.js'; +export * from './tree/constants.js'; export const UMB_MEDIA_RECYCLE_BIN_ROOT_ENTITY_TYPE = 'media-recycle-bin-root'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/manifests.ts index 1765a1dd7b..5f87f5fcf4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/manifests.ts @@ -1,5 +1,5 @@ import { manifests as entityActionManifests } from './entity-action/manifests.js'; -import { manifests as menuItemManifests } from './menu-item/manifests.js'; +import { manifests as menuManifests } from './menu/manifests.js'; import { manifests as repositoryManifests } from './repository/manifests.js'; import { manifests as treeManifests } from './tree/manifests.js'; @@ -11,7 +11,7 @@ export const manifests: Array = [ api: () => import('./allow-media-recycle-bin.condition.js'), }, ...entityActionManifests, - ...menuItemManifests, + ...menuManifests, ...repositoryManifests, ...treeManifests, ]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/menu-item/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/menu-item/manifests.ts deleted file mode 100644 index fdabbc6855..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/menu-item/manifests.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { UMB_MEDIA_MENU_ALIAS, UMB_MEDIA_RECYCLE_BIN_TREE_ALIAS } from '../../constants.js'; - -export const manifests: Array = [ - { - type: 'menuItem', - kind: 'tree', - alias: 'Umb.MenuItem.Media.RecycleBin', - name: 'Media Recycle Bin Menu Item', - weight: 100, - meta: { - treeAlias: UMB_MEDIA_RECYCLE_BIN_TREE_ALIAS, - label: 'Recycle Bin', - icon: 'icon-trash', - menus: [UMB_MEDIA_MENU_ALIAS], - }, - conditions: [ - { - alias: 'Umb.Condition.CurrentUser.AllowMediaRecycleBin', - }, - ], - }, -]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/menu/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/menu/constants.ts new file mode 100644 index 0000000000..2224ce4c3b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/menu/constants.ts @@ -0,0 +1 @@ +export const UMB_MEDIA_RECYCLE_BIN_MENU_ITEM_ALIAS = 'Umb.MenuItem.Media.RecycleBin'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/menu/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/menu/manifests.ts new file mode 100644 index 0000000000..fb7a75f6e9 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/menu/manifests.ts @@ -0,0 +1,44 @@ +import { UMB_WORKSPACE_CONDITION_ALIAS } from '@umbraco-cms/backoffice/workspace'; +import { UMB_MEDIA_MENU_ALIAS, UMB_MEDIA_RECYCLE_BIN_TREE_ALIAS, UMB_MEDIA_WORKSPACE_ALIAS } from '../../constants.js'; +import { UMB_MEDIA_RECYCLE_BIN_MENU_ITEM_ALIAS } from './constants.js'; +import { UMB_ENTITY_IS_TRASHED_CONDITION_ALIAS } from '@umbraco-cms/backoffice/recycle-bin'; + +export const manifests: Array = [ + { + type: 'menuItem', + kind: 'tree', + alias: UMB_MEDIA_RECYCLE_BIN_MENU_ITEM_ALIAS, + name: 'Media Recycle Bin Menu Item', + weight: 100, + meta: { + treeAlias: UMB_MEDIA_RECYCLE_BIN_TREE_ALIAS, + label: 'Recycle Bin', + icon: 'icon-trash', + menus: [UMB_MEDIA_MENU_ALIAS], + }, + conditions: [ + { + alias: 'Umb.Condition.CurrentUser.AllowMediaRecycleBin', + }, + ], + }, + { + type: 'workspaceContext', + kind: 'menuStructure', + name: 'Media Recycle Bin Menu Structure Workspace Context', + alias: 'Umb.Context.MediaRecycleBin.Menu.Structure', + api: () => import('./media-recycle-bin-menu-structure.context.js'), + meta: { + menuItemAlias: UMB_MEDIA_RECYCLE_BIN_MENU_ITEM_ALIAS, + }, + conditions: [ + { + alias: UMB_WORKSPACE_CONDITION_ALIAS, + match: UMB_MEDIA_WORKSPACE_ALIAS, + }, + { + alias: UMB_ENTITY_IS_TRASHED_CONDITION_ALIAS, + }, + ], + }, +]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/menu/media-recycle-bin-menu-structure.context.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/menu/media-recycle-bin-menu-structure.context.ts new file mode 100644 index 0000000000..0b015047e9 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/menu/media-recycle-bin-menu-structure.context.ts @@ -0,0 +1,11 @@ +import { UMB_MEDIA_RECYCLE_BIN_TREE_REPOSITORY_ALIAS } from '../tree/constants.js'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import { UmbMenuVariantTreeStructureWorkspaceContextBase } from '@umbraco-cms/backoffice/menu'; + +export class UmbMediaRecycleBinMenuStructureContext extends UmbMenuVariantTreeStructureWorkspaceContextBase { + constructor(host: UmbControllerHost) { + super(host, { treeRepositoryAlias: UMB_MEDIA_RECYCLE_BIN_TREE_REPOSITORY_ALIAS }); + } +} + +export { UmbMediaRecycleBinMenuStructureContext as api };