Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
a047a75
Move tree providers to element-tree component and export them in SDK
markus-moser Oct 23, 2025
9b721b7
Automatic frontend build
markus-moser Oct 23, 2025
0a2863e
Add alternative-element-tree icon
markus-moser Oct 27, 2025
c5592b8
Allow wrapping of ContextMenuWrapper
markus-moser Oct 27, 2025
81cef2d
Add addObject action
markus-moser Oct 27, 2025
a47693f
Add locateInTreeContextMenuItem
markus-moser Oct 27, 2025
6bc3527
Fix useElementVisible + useElementResize SDK export
markus-moser Oct 27, 2025
3cc2a57
Fix sorting context menu slot entry name
markus-moser Oct 27, 2025
dcadf48
Fix html entitites in copy success message
markus-moser Oct 27, 2025
1ff3274
Move search + pager container to element-tree component
markus-moser Oct 27, 2025
d28a4ef
Add optional labelAddon prop to tree-node
markus-moser Oct 27, 2025
9d41ea7
Allow int | string tree node ids
markus-moser Oct 27, 2025
ac36724
Allow to set all icon props in WidgetContentTitleView
markus-moser Oct 27, 2025
62e72ec
Rename defaultProps to defaultTreeProps, move components to element-t…
markus-moser Oct 27, 2025
0c87b3b
Merge branch 'element-tree-provider-sdk' of https://github.com/pimcor…
markus-moser Oct 27, 2025
751cbd1
Merge branch '1.x' into element-tree-provider-sdk
markus-moser Oct 27, 2025
79fdf23
Apply eslint-fixer changes
markus-moser Oct 27, 2025
8e97b1f
Fix sonar
markus-moser Oct 27, 2025
b5af0bc
Fix merge conflict
markus-moser Oct 27, 2025
647a3e6
Apply eslint-fixer changes
markus-moser Oct 27, 2025
f1b546f
Automatic frontend build
markus-moser Oct 27, 2025
f119bad
Automatic frontend build
markus-moser Oct 27, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,17 @@ export interface ContextMenuWrapperProps {
renderMenu: () => ReactElement
}

const ContextMenuWrapper = ({ children, renderMenu }: ContextMenuWrapperProps): React.JSX.Element => {
export const ContextMenuWrapper = ({ children, renderMenu }: ContextMenuWrapperProps): React.JSX.Element => {
const [open, setOpen] = useState(false)

const closeMenu = (): void => {
setOpen(false)
}

const handleContextMenu = (event: React.MouseEvent): void => {
event.stopPropagation()
}

const contextValue: ContextMenuContextType = {
closeMenu
}
Expand All @@ -53,7 +57,10 @@ const ContextMenuWrapper = ({ children, renderMenu }: ContextMenuWrapperProps):
open={ open }
trigger={ ['contextMenu'] }
>
<span>{children}</span>
<span
onContextMenu={ handleContextMenu }
role="none"
>{children}</span>
</Dropdown>
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export interface TreeNode {
fullPath?: string
icon: ElementIcon
label: string
labelAddon?: string
type?: string

permissions: ElementPermissions
Expand Down
34 changes: 18 additions & 16 deletions assets/js/src/core/components/element-tree/element-tree.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import { Box } from '../box/box'
import { useElementTreeNode } from './hooks/use-element-tree-node'
import { type TreeNode } from './element-tree-slice'
import { TreeList } from './list/tree-list'
import { useTreeId } from '@Pimcore/modules/element/tree/provider/tree-id-provider/use-tree-id'
import { useTreeId } from '@Pimcore/components/element-tree/provider/tree-id-provider/use-tree-id'
import { createTreeTestId } from '@Pimcore/utils/test-id-generator'

export interface TreeSearchProps {
Expand All @@ -44,7 +44,7 @@ export interface TreeContextMenuProps {
}

export interface TreeProps {
nodeId: number
nodeId: number | string
rootNode?: TreeNode

renderNode: typeof TreeNodeComponent
Expand All @@ -71,21 +71,21 @@ export interface ITreeContext extends TreeProps {
nodeOrder?: () => string[]
}

export const defaultProps: TreeProps = {
export const defaultTreeProps: TreeProps = {
nodeId: 1,
renderNodeContent: TreeNodeContent,
renderNode: TreeNodeComponent,
showRoot: true
}

export const TreeContext = createContext<ITreeContext>({
...defaultProps
...defaultTreeProps
})

const ElementTree = (
{
renderNode = defaultProps.renderNode,
renderNodeContent = defaultProps.renderNodeContent,
renderNode = defaultTreeProps.renderNode,
renderNodeContent = defaultTreeProps.renderNodeContent,
contextMenu: ContextMenu,
rootNode,
...props
Expand Down Expand Up @@ -152,17 +152,19 @@ const ElementTree = (
</div>
)

return (
<>
{isLoading === true && !hasRootNode && (
<Box padding={ { left: 'extra-small' } }>
<Skeleton />
</Box>
)}
if (isLoading === true && !hasRootNode) {
return (
<Box padding={ { left: 'extra-small' } }>
<Skeleton />
</Box>
)
}

{(items.length !== 0 || hasRootNode) && (treeContent)}
</>
)
if (items.length !== 0 || hasRootNode) {
return treeContent
}

return <></>
}

export { ElementTree }
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import { type RootState, useAppDispatch } from '@sdk/app'
import { type InternalNodeState, selectNodeState, setFetchTriggered } from '../element-tree-slice'
import { useSelector } from 'react-redux'
import { useTreeId } from '@Pimcore/modules/element/tree/provider/tree-id-provider/use-tree-id'
import { useTreeId } from '@Pimcore/components/element-tree/provider/tree-id-provider/use-tree-id'
import { useElementTree } from './use-element-tree'

export type NodeState = InternalNodeState
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { useTranslation } from 'react-i18next'
import { setRootFetchTriggered, setRootNode as setRootNodeAction, type TreeNode } from '../element-tree-slice'
import { type ElementIcon } from '@Pimcore/modules/asset/asset-api-slice-enhanced'
import { isNil } from 'lodash'
import { useTreeId } from '@Pimcore/modules/element/tree/provider/tree-id-provider/use-tree-id'
import { useTreeId } from '@Pimcore/components/element-tree/provider/tree-id-provider/use-tree-id'
import trackError, { GeneralError } from '@Pimcore/modules/app/error-handler'
import { useElementTreeNode } from './use-element-tree-node'
import { useNodeApiHook } from '../provider/node-api-hook-provider/use-node-api-hook'
Expand All @@ -24,7 +24,7 @@ export interface UseElementTreeRootNodeResult {
isLoading: boolean
}

export const useElementTreeRootNode = (id: number, showRoot: boolean): UseElementTreeRootNodeResult => {
export const useElementTreeRootNode = (id: number | string, showRoot: boolean): UseElementTreeRootNodeResult => {
const dispatch = useDispatch()
const { t } = useTranslation()
const { treeId } = useTreeId()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { type InternalNodeState, selectNodeState, setNodeExpanded, setNodeLoadin
import { isUndefined } from 'lodash'
import { type DataTransformerReturnType, type DataTransformerSourceNode } from '../types/node-api-hook'
import { useNodeApiHook } from '../provider/node-api-hook-provider/use-node-api-hook'
import { useTreeId } from '@Pimcore/modules/element/tree/provider/tree-id-provider/use-tree-id'
import { useTreeId } from '@Pimcore/components/element-tree/provider/tree-id-provider/use-tree-id'

export type NodeState = InternalNodeState

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import { Flex } from '@Pimcore/components/flex/flex'
import { SlotRenderer } from '@Pimcore/modules/app/component-registry/slot-renderer'
import { componentConfig } from '@Pimcore/modules/app/component-registry/component-config'
import { elementTypes } from '@Pimcore/types/enums/element/element-type'
import { Text } from '@sdk/components'
import { isUndefined } from 'lodash'

export interface TreeNodeContentProps {
node: TreeNodeProps
Expand All @@ -27,7 +29,7 @@ export interface TreeNodeContentMetaProps {
}

const TreeNodeContent = forwardRef(function TreeNodeContent (props: TreeNodeContentProps, ref: MutableRefObject<HTMLDivElement>): React.JSX.Element {
const { icon, label, isPublished, elementType } = props.node
const { icon, label, labelAddon, isPublished, elementType } = props.node
const { styles } = useStyles()

const getMetaSlotName = (): string => {
Expand Down Expand Up @@ -66,7 +68,14 @@ const TreeNodeContent = forwardRef(function TreeNodeContent (props: TreeNodeCont
<span
className="tree-node-content__label"
data-testid={ `tree-node-label-${props.node.id}` }
>{label}</span>
>
{label}
{!isUndefined(labelAddon) && (
<Text type="secondary">
{` ${labelAddon}`}
</Text>
)}
</span>
</Flex>

<Flex
Expand Down
2 changes: 2 additions & 0 deletions assets/js/src/core/components/element-tree/node/tree-node.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export interface TreeNodeProps {
id: string
icon: ElementIcon
label: string
labelAddon?: string
internalKey: string
children?: TreeNodeProps[]
level: number
Expand Down Expand Up @@ -58,6 +59,7 @@ export const defaultProps: TreeNodeProps = {
value: 'folder'
},
label: '',
labelAddon: undefined,
children: [],
permissions: {
list: false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
*/

import React, { createContext, useMemo } from 'react'
import { type TreePermission } from '../../../../perspectives/enums/tree-permission'
import { type TreePermission } from '../../../../modules/perspectives/enums/tree-permission'

export interface ITreePermissionContext {
permissions: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
*/

import { useContext } from 'react'
import { type TreePermission } from '../../../../perspectives/enums/tree-permission'
import { type TreePermission } from '../../../../modules/perspectives/enums/tree-permission'
import { type ITreePermissionContext, TreePermissionContext } from './tree-permission-provider'
import { isNil } from 'lodash'

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,6 @@ export interface DataTransformerReturnType {
}

export interface NodeApiHookReturnType {
fetchRoot: (id: number) => Promise<DataTransformerReturnType | undefined>
fetchRoot: (id: number | string) => Promise<DataTransformerReturnType | undefined>
fetchChildren: (node: DataTransformerSourceNode, nodeState: NodeState) => Promise<DataTransformerReturnType | undefined>
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { getPrefix } from '@Pimcore/app/api/pimcore/route'
import { saveFileLocal } from '@Pimcore/utils/files'
import type { GridContextMenuProps } from '@Pimcore/components/grid/grid'
import { checkElementPermission } from '@Pimcore/modules/element/permissions/permission-helper'
import { useTreePermission } from '@Pimcore/modules/element/tree/provider/tree-permission-provider/use-tree-permission'
import { useTreePermission } from '@Pimcore/components/element-tree/provider/tree-permission-provider/use-tree-permission'
import { TreePermission } from '@Pimcore/modules/perspectives/enums/tree-permission'
import { ContextMenuActionName } from '@Pimcore/modules/element/actions'

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { useFormModal } from '@Pimcore/components/modal/form-modal/hooks/use-for
import { useMessage } from '@Pimcore/components/message/useMessage'
import { useCacheUpdate } from '@Pimcore/modules/element/hooks/use-cache-update'
import { checkElementPermission } from '@Pimcore/modules/element/permissions/permission-helper'
import { useTreePermission } from '@Pimcore/modules/element/tree/provider/tree-permission-provider/use-tree-permission'
import { useTreePermission } from '@Pimcore/components/element-tree/provider/tree-permission-provider/use-tree-permission'
import { TreePermission } from '@Pimcore/modules/perspectives/enums/tree-permission'
import { ContextMenuActionName } from '@Pimcore/modules/element/actions'

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { ContextMenuActionName } from '@Pimcore/modules/element/actions'
import { useUploadModalContext } from '@Pimcore/components/modal-upload/provider/upload-modal-provider/use-upload-modal-context'
import { useRefreshTree } from '@Pimcore/modules/element/actions/refresh-tree/use-refresh-tree'
import { TreePermission } from '@Pimcore/modules/perspectives/enums/tree-permission'
import { useTreePermission } from '@Pimcore/modules/element/tree/provider/tree-permission-provider/use-tree-permission'
import { useTreePermission } from '@Pimcore/components/element-tree/provider/tree-permission-provider/use-tree-permission'
import { checkElementPermission } from '@Pimcore/modules/element/permissions/permission-helper'
import { useJobs } from '@Pimcore/modules/execution-engine/hooks/useJobs'
import { defaultTopics, topics } from '@Pimcore/modules/execution-engine/topics'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { Icon } from '@Pimcore/components/icon/icon'
import React, { useEffect } from 'react'
import { checkElementPermission } from '@Pimcore/modules/element/permissions/permission-helper'
import { type Element, getElementKey } from '@Pimcore/modules/element/element-helper'
import { useTreePermission } from '@Pimcore/modules/element/tree/provider/tree-permission-provider/use-tree-permission'
import { useTreePermission } from '@Pimcore/components/element-tree/provider/tree-permission-provider/use-tree-permission'
import { TreePermission } from '@Pimcore/modules/perspectives/enums/tree-permission'
import trackError, { ApiError } from '@Pimcore/modules/app/error-handler'
import { ContextMenuActionName } from '@Pimcore/modules/element/actions'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import { useRename } from '@Pimcore/modules/element/actions/rename/use-rename'
import { getElementActionCacheKey } from '@Pimcore/modules/element/element-helper'
import { checkElementPermission } from '@Pimcore/modules/element/permissions/permission-helper'
import { TreePermission } from '@Pimcore/modules/perspectives/enums/tree-permission'
import { useTreePermission } from '@Pimcore/modules/element/tree/provider/tree-permission-provider/use-tree-permission'
import { useTreePermission } from '@Pimcore/components/element-tree/provider/tree-permission-provider/use-tree-permission'
import { useUpload } from '../../actions/upload/use-upload'
import { useTranslation } from 'react-i18next'
import { Icon } from '@Pimcore/components/icon/icon'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
type AssetGetTreeApiArg
} from '@Pimcore/modules/asset/asset-api-slice-enhanced'
import { transformApiDataToNodes } from '../utils/transform-api-data-to-node'
import { useTreeFilter } from '@Pimcore/modules/element/tree/provider/tree-filter-provider/use-tree-filter'
import { useTreeFilter } from '@Pimcore/components/element-tree/provider/tree-filter-provider/use-tree-filter'
import { type NodeApiHookReturnType, type DataTransformerReturnType, type DataTransformerSourceNode } from '@Pimcore/components/element-tree/types/node-api-hook'
import { useAppDispatch } from '@sdk/app'
import trackError, { ApiError } from '@Pimcore/modules/app/error-handler'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

import React, { type ReactElement, type Ref, type ComponentProps, forwardRef } from 'react'
import { type TreeNode } from '@Pimcore/components/element-tree/node/tree-node'
import ContextMenuWrapper from '@Pimcore/components/context-menu-wrapper/context-menu-wrapper'
import { ContextMenuWrapper } from '@Pimcore/components/context-menu-wrapper/context-menu-wrapper'
import { AssetTreeContextMenu } from '../context-menu/context-menu'
import { isUndefined } from 'lodash'

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
*/

import React from 'react'
import { SearchContainer as BaseSearchContainer } from '@Pimcore/modules/element/tree/search/search-container'
import { SearchContainer as BaseSearchContainer } from '@Pimcore/components/element-tree/search/search-container'
import { type TreeSearchProps } from '@Pimcore/components/element-tree/element-tree'
import { useTranslation } from 'react-i18next'

Expand Down
6 changes: 3 additions & 3 deletions assets/js/src/core/modules/asset/tree/tree-container.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@
* @license Pimcore Open Core License (POCL)
*/

import { defaultProps, ElementTree, type TreeContextMenuProps } from '@Pimcore/components/element-tree/element-tree'
import { defaultTreeProps, ElementTree, type TreeContextMenuProps } from '@Pimcore/components/element-tree/element-tree'
import React from 'react'
import { TreeNode as TreeNodeComponent } from '@Pimcore/components/element-tree/node/tree-node'
import { PagerContainer } from '@Pimcore/modules/element/tree/pager/pager-container'
import { PagerContainer } from '@Pimcore/components/element-tree/pager/pager-container'
import { useAssetHelper } from '@Pimcore/modules/asset/hooks/use-asset-helper'
import { SearchContainer } from './search/search-container'
import { withDraggable } from './node/with-draggable'
Expand Down Expand Up @@ -63,7 +63,7 @@ const TreeContainer = ({ id = 1, showRoot = true }: TreeContainerProps): React.J
onSelect={ onSelect }
renderFilter={ SearchContainer }
renderNode={ AssetTreeNode }
renderNodeContent={ defaultProps.renderNodeContent }
renderNodeContent={ defaultTreeProps.renderNodeContent }
renderPager={ PagerContainer }
rootNode={ rootNode }
showRoot={ showRoot }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import {
type ClassDefinitionListItem
} from '@Pimcore/modules/class-definition/class-definition-slice.gen'
import { checkElementPermission } from '@Pimcore/modules/element/permissions/permission-helper'
import { useTreePermission } from '@Pimcore/modules/element/tree/provider/tree-permission-provider/use-tree-permission'
import { useTreePermission } from '@Pimcore/components/element-tree/provider/tree-permission-provider/use-tree-permission'
import { TreePermission } from '@Pimcore/modules/perspectives/enums/tree-permission'
import { isEmpty, isNil } from 'lodash'
import React from 'react'
Expand All @@ -31,6 +31,7 @@ import { ContextMenuActionName } from '@Pimcore/modules/element/actions'

interface UseAddObjectHookReturn {
addObjectTreeContextMenuItem: (node: TreeNodeProps) => ItemType
addObject: (className: string, classId: string, parentId: number, onFinish?: (newName: string) => void) => void
}

export const useAddObject = (): UseAddObjectHookReturn => {
Expand Down Expand Up @@ -106,25 +107,34 @@ export const useAddObject = (): UseAddObjectHookReturn => {
}
}

const createDataObject = (
classDefinition: ClassDefinitionListItem,
const addObject = (
className: string,
classId: string,
parentId: number,
onFinish?: (newName: string) => void
): void => {
modal.input({
title: t('data-object.create-data-object', { className: classDefinition.name }),
title: t('data-object.create-data-object', { className }),
label: t('form.label.new-item'),
rule: {
required: true,
message: t('form.validation.required')
},
onOk: async (value: string) => {
await createDataObjectMutation(classDefinition.id, value, parentId)
await createDataObjectMutation(classId, value, parentId)
onFinish?.(value)
}
})
}

const createDataObject = (
classDefinition: ClassDefinitionListItem,
parentId: number,
onFinish?: (newName: string) => void
): void => {
addObject(classDefinition.name, classDefinition.id, parentId, onFinish)
}

const createDataObjectMutation = async (
classId: string,
name: string,
Expand Down Expand Up @@ -172,6 +182,7 @@ export const useAddObject = (): UseAddObjectHookReturn => {
}

return {
addObjectTreeContextMenuItem
addObjectTreeContextMenuItem,
addObject
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import {
type ClassDefinitionListItem
} from '@Pimcore/modules/class-definition/class-definition-slice.gen'
import { checkElementPermission } from '@Pimcore/modules/element/permissions/permission-helper'
import { useTreePermission } from '@Pimcore/modules/element/tree/provider/tree-permission-provider/use-tree-permission'
import { useTreePermission } from '@Pimcore/components/element-tree/provider/tree-permission-provider/use-tree-permission'
import { TreePermission } from '@Pimcore/modules/perspectives/enums/tree-permission'
import { isEmpty, isNil } from 'lodash'
import React from 'react'
Expand Down
Loading