Skip to content

Commit ec0c57a

Browse files
authored
[Asset] upload image version - Tree preview not updated fix (#3369)
1 parent eb1637b commit ec0c57a

754 files changed

Lines changed: 1187 additions & 1105 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

assets/js/src/core/components/element-tree/element-tree-slice.ts

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,19 @@ const slice = createSlice({
398398
isFetching: payload.isFetching
399399
}))
400400
},
401+
setNodeFetchingInAllTrees: (
402+
state,
403+
{ payload }: PayloadAction<{ nodeId: string, elementType: string, isFetching: boolean }>
404+
) => {
405+
Object.keys(state).forEach(treeId => {
406+
if (state[treeId].nodes[payload.nodeId]?.treeNodeProps?.elementType === payload.elementType) {
407+
updateNodeState(state, treeId, payload.nodeId, node => ({
408+
...node,
409+
isFetching: payload.isFetching
410+
}))
411+
}
412+
})
413+
},
401414
markNodeDeletingForTree: (
402415
state,
403416
{ payload }: PayloadAction<{ treeId: string, nodeId: string, isDeleting: boolean }>
@@ -442,6 +455,24 @@ const slice = createSlice({
442455
}
443456
})
444457
},
458+
updateNodeData: (
459+
state,
460+
{ payload }: PayloadAction<{ nodeId: string, elementType: string, data: Partial<TreeNode> }>
461+
) => {
462+
Object.keys(state).forEach(treeId => {
463+
if (state[treeId].nodes[payload.nodeId]?.treeNodeProps?.elementType === payload.elementType) {
464+
updateNodeState(state, treeId, payload.nodeId, node => ({
465+
...node,
466+
treeNodeProps: !isUndefined(node.treeNodeProps)
467+
? {
468+
...node.treeNodeProps,
469+
...payload.data
470+
}
471+
: undefined
472+
}))
473+
}
474+
})
475+
},
445476
updateNodeType: (
446477
state,
447478
{ payload }: PayloadAction<{ nodeId: string, elementType: string, newType: string, newIcon: ElementIcon }>
@@ -741,7 +772,7 @@ export const treeSliceName = slice.name
741772

742773
injectSliceWithState(slice)
743774

744-
export const { setNodeLoading, setNodeLoadingInAllTree, setNodeExpanded, setNodeHasChildren, setNodePage, setNodeSearchTerm, setSelectedNodeIds, setNodeScrollTo, updateNodesByParentId, locateInTree, setFetchTriggered, setRootFetchTriggered, setNodeFetching, markNodeDeletingForTree, refreshNodeChildren, refreshTargetNode, refreshSourceNode, markNodeDeleting, renameNode, updateNodeType, setNodePublished, setNodeAdditionalAttributes, setRootNode, setDocumentNodeSiteStatus, setNodeLocked, refreshTreeByElementType, setDocumentNodeNavigationExclude } = slice.actions
775+
export const { setNodeLoading, setNodeLoadingInAllTree, setNodeExpanded, setNodeHasChildren, setNodePage, setNodeSearchTerm, setSelectedNodeIds, setNodeScrollTo, updateNodesByParentId, locateInTree, setFetchTriggered, setRootFetchTriggered, setNodeFetching, setNodeFetchingInAllTrees, markNodeDeletingForTree, refreshNodeChildren, refreshTargetNode, refreshSourceNode, markNodeDeleting, renameNode, updateNodeData, updateNodeType, setNodePublished, setNodeAdditionalAttributes, setRootNode, setDocumentNodeSiteStatus, setNodeLocked, refreshTreeByElementType, setDocumentNodeNavigationExclude } = slice.actions
745776

746777
export const selectNodeState = createSelector(
747778
(state: RootState) => state.trees,

assets/js/src/core/components/element-tree/tooltip/element-tree-tooltip.tsx

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import { Flex } from '@Pimcore/components/flex/flex'
1717
import { useTranslation } from 'react-i18next'
1818
import { type DragInfoChangeEvent } from '@Pimcore/components/drag-and-drop/draggable'
1919
import { isNull } from 'lodash'
20+
import { Skeleton } from 'antd'
2021

2122
export interface ElementTreeTooltipProps {
2223
node: TreeNodeProps
@@ -27,6 +28,7 @@ export const ElementTreeTooltip = ({ node, children }: ElementTreeTooltipProps):
2728
const { t } = useTranslation()
2829
const [isTooltipOpen, setIsTooltipOpen] = useState(false)
2930
const [isDragActive, setIsDragActive] = useState(false)
31+
const [isImageLoaded, setIsImageLoaded] = useState(false)
3032
const containerRef = useRef<HTMLDivElement>(null)
3133
const mouseEnterTimeoutRef = useRef<NodeJS.Timeout | null>(null)
3234
const mouseCheckIntervalRef = useRef<NodeJS.Timeout | null>(null)
@@ -36,6 +38,11 @@ export const ElementTreeTooltip = ({ node, children }: ElementTreeTooltipProps):
3638
const isAsset = node.metaData?.asset !== undefined
3739
const isObject = node.metaData?.dataObject !== undefined
3840
const hasTooltip = element?.customAttributes?.tooltip !== null && element?.customAttributes?.tooltip !== undefined
41+
const imageThumbnailPath: string | undefined = element?.imageThumbnailPath
42+
43+
useEffect(() => {
44+
setIsImageLoaded(false)
45+
}, [imageThumbnailPath])
3946

4047
// Listen for global drag state changes
4148
useEffect(() => {
@@ -174,10 +181,17 @@ export const ElementTreeTooltip = ({ node, children }: ElementTreeTooltipProps):
174181
justify="center"
175182
style={ { maxHeight: 200, overflow: 'hidden' } }
176183
>
184+
{!isImageLoaded && (
185+
<Skeleton.Image
186+
active
187+
style={ { width: 248, height: 150 } }
188+
/>
189+
)}
177190
<Image
178191
alt={ element.filename }
192+
onLoad={ () => { setIsImageLoaded(true) } }
179193
src={ element.imageThumbnailPath }
180-
style={ { maxHeight: 200 } }
194+
style={ { maxHeight: 200, display: isImageLoaded ? undefined : 'none' } }
181195
/>
182196
</Flex>
183197
</Box>

assets/js/src/core/modules/asset/actions/upload-new-version/upload-new-version.tsx

Lines changed: 47 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
*/
1010

1111
import { type Asset } from '@Pimcore/modules/asset/asset-api-slice.gen'
12+
import { api } from '@Pimcore/modules/asset/asset-api-slice-enhanced'
1213
import { type TreeNodeProps } from '@Pimcore/components/element-tree/node/tree-node'
1314
import { type ItemType } from '@Pimcore/components/dropdown/dropdown'
1415
import { useTranslation } from 'react-i18next'
@@ -22,7 +23,9 @@ import { useUploadModalContext } from '@Pimcore/components/modal-upload/provider
2223
import { getPrefix } from '@Pimcore/app/api/pimcore/route'
2324
import { isNil } from 'lodash'
2425
import { useAppDispatch } from '@sdk/app'
25-
import { renameNode } from '@Pimcore/components/element-tree/element-tree-slice'
26+
import { updateNodeData, setNodeFetchingInAllTrees } from '@Pimcore/components/element-tree/element-tree-slice'
27+
import { transformApiDataToNode } from '@Pimcore/modules/asset/tree/utils/transform-api-data-to-node'
28+
import { addCacheBusterToUrl } from '@Pimcore/utils/url-cache-buster'
2629

2730
export interface UseUploadNewVersionReturn {
2831
uploadNewVersion: (id: number, onFinish?: () => void) => void
@@ -36,21 +39,55 @@ export const useUploadNewVersion = (): UseUploadNewVersionReturn => {
3639
const { triggerUpload } = useUploadModalContext()
3740
const { isTreeActionAllowed } = useTreePermission()
3841

42+
const refreshTreeNode = async (id: number): Promise<void> => {
43+
dispatch(setNodeFetchingInAllTrees({ nodeId: String(id), elementType: 'asset', isFetching: true }))
44+
45+
const fetcher = dispatch(api.endpoints.assetGetTree.initiate(
46+
{ page: 1, pageSize: 1, pqlQuery: `id = ${id}`, pathIncludeParent: true },
47+
{ forceRefetch: true }
48+
))
49+
50+
try {
51+
const { data } = await fetcher
52+
53+
if (!isNil(data?.items?.[0])) {
54+
const freshNode = transformApiDataToNode(
55+
data.items[0],
56+
{ id: String(id), internalKey: String(id) }
57+
)
58+
59+
const assetItem = data.items[0]
60+
const cacheBustedItem = 'imageThumbnailPath' in assetItem && !isNil(assetItem.imageThumbnailPath)
61+
? { ...assetItem, imageThumbnailPath: addCacheBusterToUrl(assetItem.imageThumbnailPath) }
62+
: assetItem
63+
64+
const cacheBustedIcon = freshNode.icon.type === 'path'
65+
? { ...freshNode.icon, value: addCacheBusterToUrl(freshNode.icon.value) }
66+
: freshNode.icon
67+
68+
dispatch(updateNodeData({
69+
nodeId: String(id),
70+
elementType: 'asset',
71+
data: {
72+
icon: cacheBustedIcon,
73+
label: freshNode.label,
74+
metaData: { asset: cacheBustedItem }
75+
}
76+
}))
77+
}
78+
} finally {
79+
fetcher.unsubscribe()
80+
dispatch(setNodeFetchingInAllTrees({ nodeId: String(id), elementType: 'asset', isFetching: false }))
81+
}
82+
}
83+
3984
const uploadNewVersion = (id: number, onFinish?: () => void): void => {
4085
triggerUpload({
4186
action: `${getPrefix()}/assets/${id}/replace`,
4287
maxItems: 1,
4388
multiple: false,
4489
onSuccess: async (result: any) => {
45-
if (!isNil(result?.[0]?.response?.data)) {
46-
const newFilename = result[0].response.data
47-
48-
dispatch(renameNode({
49-
nodeId: String(id),
50-
elementType: 'asset',
51-
newLabel: newFilename
52-
}))
53-
}
90+
await refreshTreeNode(id)
5491
onFinish?.()
5592
}
5693
})

public/build/0c54e122-004b-447b-9ce6-b96b089f89b8/entrypoints.json

Lines changed: 0 additions & 22 deletions
This file was deleted.

public/build/0c54e122-004b-447b-9ce6-b96b089f89b8/manifest.json

Lines changed: 0 additions & 33 deletions
This file was deleted.

public/build/6be0015d-5ecc-45bc-9e7c-4336a1ea84ad/entrypoints.json

Lines changed: 0 additions & 23 deletions
This file was deleted.

0 commit comments

Comments
 (0)