Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions assets/js/src/examples/data-object-context-menu/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { type IAbstractPlugin } from '@pimcore/studio-ui-bundle'
import { DataObjectContextMenuExtension } from './modules/data-object-context-menu-extension'

export const DataObjectContextMenuPlugin: IAbstractPlugin = {
name: 'DataObjectContextMenuPlugin',

onStartup ({ moduleSystem }) {
moduleSystem.registerModule(DataObjectContextMenuExtension)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import React from 'react'
import { type AbstractModule, container } from '@pimcore/studio-ui-bundle'
import { serviceIds } from '@pimcore/studio-ui-bundle/app'
import { useAlertModal, Icon } from '@pimcore/studio-ui-bundle/components'
import { contextMenuConfig, type ContextMenuRegistryInterface, type DataObjectTreeContextMenuProps } from '@pimcore/studio-ui-bundle/modules/app'

export const DataObjectContextMenuExtension: AbstractModule = {
onInit () {
// Get the ContextMenuRegistry from the dependency injection container
const contextMenuRegistry = container.get<ContextMenuRegistryInterface>(serviceIds['App/ContextMenuRegistry/ContextMenuRegistry'])

// contextMenuConfig provides configurations for all available context menu locations
// Available: dataObjectTree, assetTree, documentTree, etc.
const config = contextMenuConfig.dataObjectTree

// Example 1: Add a new custom menu item
contextMenuRegistry.registerToSlot(config.name, {
name: 'custom-item',

// Priority controls the position in the menu (lower number = higher position)
// Use config.priority to position items relative to existing ones (e.g., rename - 1 places it just above "rename")
priority: config.priority.rename - 1,

// useMenuItem hook returns the menu item configuration
useMenuItem: (context: DataObjectTreeContextMenuProps) => {
const alertModal = useAlertModal()

return {
key: 'custom-item',
label: 'Custom Item',
icon: <Icon value="pimcore" />,

// context.target contains information about the selected node (id, type, etc.)
onClick: () => {
alertModal.info({
title: `Custom item clicked for data object with id: ${context.target.id}`,
content: 'This is a custom context menu item for the data object.'
})
}
}
}
})

// Example 2: Modify an existing menu item
contextMenuRegistry.updateSlotProvider(config.name, 'delete', (existingItem) => {
return {
...existingItem,
useMenuItem: (context: DataObjectTreeContextMenuProps) => {
// Get the original menu item configuration
const existingMenuItem = existingItem.useMenuItem(context)

// Preserve existing visibility logic
if (existingMenuItem === null) {
return null
}

// Hide delete option for non-folder items
if (context.target.type !== 'folder') {
return null
}

// Customize the menu item properties
return {
...existingMenuItem,
label: 'Customized Delete (visible only for folders)',
icon: <Icon
subIconName="pimcore"
value="trash"
/>
}
}
}
})
}
}
4 changes: 3 additions & 1 deletion assets/js/src/plugins.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { CustomIconPlugin } from './examples/custom-icons'
import { CustomWidgetsPlugin } from './examples/custom-widgets'
import { DynamicTypePlugin } from './examples/dynamic-types'
import { ApiDataPlugin } from './examples/api-data'
import { DataObjectContextMenuPlugin } from './examples/data-object-context-menu'

// Examples are splitted into separate plugins to create a clear separation for better understanding.
// You can also combine them into one plugin if you want to.
Expand All @@ -17,5 +18,6 @@ export {
CustomIconPlugin,
CustomWidgetsPlugin,
DynamicTypePlugin,
ApiDataPlugin
ApiDataPlugin,
DataObjectContextMenuPlugin
}
Loading