fix(ui): client side doc data not updating after save (#9340)
### What? When a document is saved the data from useDocumentInfo was stale. ### Why? Previously we would refresh the entire document by calling the form-state endpoint, we no longer do that. ### How? Adds a new variable accessible from useDocumentInfo, `savedDocumentData`, that is updated when the document is successfully saved and defaults to initialData.
This commit is contained in:
@@ -1,13 +1,13 @@
|
||||
'use client'
|
||||
import type { FormState, SanitizedCollectionConfig, UploadEdits } from 'payload'
|
||||
|
||||
import { isImage, reduceFieldsToValues } from 'payload/shared'
|
||||
import { isImage } from 'payload/shared'
|
||||
import React, { useCallback, useEffect, useRef, useState } from 'react'
|
||||
import { toast } from 'sonner'
|
||||
|
||||
import { FieldError } from '../../fields/FieldError/index.js'
|
||||
import { fieldBaseClass } from '../../fields/shared/index.js'
|
||||
import { useForm } from '../../forms/Form/index.js'
|
||||
import { useForm, useFormProcessing } from '../../forms/Form/index.js'
|
||||
import { useField } from '../../forms/useField/index.js'
|
||||
import { useDocumentInfo } from '../../providers/DocumentInfo/index.js'
|
||||
import { EditDepthProvider } from '../../providers/EditDepth/index.js'
|
||||
@@ -94,15 +94,15 @@ export const Upload: React.FC<UploadProps> = (props) => {
|
||||
const { t } = useTranslation()
|
||||
const { setModified } = useForm()
|
||||
const { resetUploadEdits, updateUploadEdits, uploadEdits } = useUploadEdits()
|
||||
const { docPermissions } = useDocumentInfo()
|
||||
const { docPermissions, savedDocumentData } = useDocumentInfo()
|
||||
const isFormSubmitting = useFormProcessing()
|
||||
const { errorMessage, setValue, showError, value } = useField<File>({
|
||||
path: 'file',
|
||||
validate,
|
||||
})
|
||||
|
||||
const [doc, setDoc] = useState(reduceFieldsToValues(initialState || {}, true))
|
||||
const [fileSrc, setFileSrc] = useState<null | string>(null)
|
||||
const [replacingFile, setReplacingFile] = useState(false)
|
||||
const [removedFile, setRemovedFile] = useState(false)
|
||||
const [filename, setFilename] = useState<string>(value?.name || '')
|
||||
const [showUrlInput, setShowUrlInput] = useState(false)
|
||||
const [fileUrl, setFileUrl] = useState<string>('')
|
||||
@@ -156,11 +156,10 @@ export const Upload: React.FC<UploadProps> = (props) => {
|
||||
)
|
||||
|
||||
const handleFileRemoval = useCallback(() => {
|
||||
setReplacingFile(true)
|
||||
setRemovedFile(true)
|
||||
handleFileChange(null)
|
||||
setFileSrc('')
|
||||
setFileUrl('')
|
||||
setDoc({})
|
||||
resetUploadEdits()
|
||||
setShowUrlInput(false)
|
||||
}, [handleFileChange, resetUploadEdits])
|
||||
@@ -192,11 +191,10 @@ export const Upload: React.FC<UploadProps> = (props) => {
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
setDoc(reduceFieldsToValues(initialState || {}, true))
|
||||
if (initialState?.file?.value instanceof File) {
|
||||
setFileSrc(URL.createObjectURL(initialState.file.value))
|
||||
setRemovedFile(false)
|
||||
}
|
||||
setReplacingFile(false)
|
||||
}, [initialState])
|
||||
|
||||
useEffect(() => {
|
||||
@@ -205,6 +203,12 @@ export const Upload: React.FC<UploadProps> = (props) => {
|
||||
}
|
||||
}, [showUrlInput])
|
||||
|
||||
useEffect(() => {
|
||||
if (isFormSubmitting) {
|
||||
setRemovedFile(false)
|
||||
}
|
||||
}, [isFormSubmitting])
|
||||
|
||||
const canRemoveUpload =
|
||||
docPermissions?.update && 'delete' in docPermissions && docPermissions?.delete
|
||||
|
||||
@@ -222,19 +226,19 @@ export const Upload: React.FC<UploadProps> = (props) => {
|
||||
return (
|
||||
<div className={[fieldBaseClass, baseClass].filter(Boolean).join(' ')}>
|
||||
<FieldError message={errorMessage} showError={showError} />
|
||||
{doc.filename && !replacingFile && (
|
||||
{savedDocumentData && savedDocumentData.filename && !removedFile && (
|
||||
<FileDetails
|
||||
collectionSlug={collectionSlug}
|
||||
customUploadActions={customActions}
|
||||
doc={doc}
|
||||
doc={savedDocumentData}
|
||||
enableAdjustments={showCrop || showFocalPoint}
|
||||
handleRemove={canRemoveUpload ? handleFileRemoval : undefined}
|
||||
hasImageSizes={hasImageSizes}
|
||||
imageCacheTag={doc.updatedAt}
|
||||
imageCacheTag={savedDocumentData.updatedAt}
|
||||
uploadConfig={uploadConfig}
|
||||
/>
|
||||
)}
|
||||
{(!doc.filename || replacingFile) && (
|
||||
{(!savedDocumentData?.filename || removedFile) && (
|
||||
<div className={`${baseClass}__upload`}>
|
||||
{!value && !showUrlInput && (
|
||||
<Dropzone onChange={handleFileSelection}>
|
||||
@@ -339,7 +343,7 @@ export const Upload: React.FC<UploadProps> = (props) => {
|
||||
<UploadActions
|
||||
customActions={customActions}
|
||||
enableAdjustments={showCrop || showFocalPoint}
|
||||
enablePreviewSizes={hasImageSizes && doc.filename && !replacingFile}
|
||||
enablePreviewSizes={hasImageSizes && savedDocumentData?.filename && !removedFile}
|
||||
mimeType={value.type}
|
||||
/>
|
||||
</div>
|
||||
@@ -356,17 +360,17 @@ export const Upload: React.FC<UploadProps> = (props) => {
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
{(value || doc.filename) && (
|
||||
{(value || savedDocumentData?.filename) && (
|
||||
<EditDepthProvider>
|
||||
<Drawer Header={null} slug={editDrawerSlug}>
|
||||
<EditUpload
|
||||
fileName={value?.name || doc?.filename}
|
||||
fileSrc={doc?.url || fileSrc}
|
||||
imageCacheTag={doc.updatedAt}
|
||||
fileName={value?.name || savedDocumentData?.filename}
|
||||
fileSrc={savedDocumentData?.url || fileSrc}
|
||||
imageCacheTag={savedDocumentData?.updatedAt}
|
||||
initialCrop={uploadEdits?.crop ?? undefined}
|
||||
initialFocalPoint={{
|
||||
x: uploadEdits?.focalPoint?.x || doc.focalX || 50,
|
||||
y: uploadEdits?.focalPoint?.y || doc.focalY || 50,
|
||||
x: uploadEdits?.focalPoint?.x || savedDocumentData?.focalX || 50,
|
||||
y: uploadEdits?.focalPoint?.y || savedDocumentData?.focalY || 50,
|
||||
}}
|
||||
onSave={onEditsSave}
|
||||
showCrop={showCrop}
|
||||
@@ -375,14 +379,18 @@ export const Upload: React.FC<UploadProps> = (props) => {
|
||||
</Drawer>
|
||||
</EditDepthProvider>
|
||||
)}
|
||||
{doc && hasImageSizes && (
|
||||
{savedDocumentData && hasImageSizes && (
|
||||
<Drawer
|
||||
className={`${baseClass}__previewDrawer`}
|
||||
hoverTitle
|
||||
slug={sizePreviewSlug}
|
||||
title={t('upload:sizesFor', { label: doc?.filename })}
|
||||
title={t('upload:sizesFor', { label: savedDocumentData.filename })}
|
||||
>
|
||||
<PreviewSizes doc={doc} imageCacheTag={doc.updatedAt} uploadConfig={uploadConfig} />
|
||||
<PreviewSizes
|
||||
doc={savedDocumentData}
|
||||
imageCacheTag={savedDocumentData.updatedAt}
|
||||
uploadConfig={uploadConfig}
|
||||
/>
|
||||
</Drawer>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -42,7 +42,7 @@ const DocumentInfo: React.FC<
|
||||
hasPublishedDoc: hasPublishedDocFromProps,
|
||||
hasPublishPermission: hasPublishPermissionFromProps,
|
||||
hasSavePermission: hasSavePermissionFromProps,
|
||||
initialData: data,
|
||||
initialData,
|
||||
initialState,
|
||||
isLocked: isLockedFromProps,
|
||||
lastUpdateTime: lastUpdateTimeFromProps,
|
||||
@@ -84,7 +84,7 @@ const DocumentInfo: React.FC<
|
||||
const [documentTitle, setDocumentTitle] = useState(() =>
|
||||
formatDocTitle({
|
||||
collectionConfig,
|
||||
data: { ...data, id },
|
||||
data: { ...(initialData || {}), id },
|
||||
dateFormat,
|
||||
fallback: id?.toString(),
|
||||
globalConfig,
|
||||
@@ -105,8 +105,9 @@ const DocumentInfo: React.FC<
|
||||
const [documentIsLocked, setDocumentIsLocked] = useState<boolean | undefined>(isLockedFromProps)
|
||||
const [currentEditor, setCurrentEditor] = useState<ClientUser | null>(currentEditorFromProps)
|
||||
const [lastUpdateTime, setLastUpdateTime] = useState<number>(lastUpdateTimeFromProps)
|
||||
const [savedDocumentData, setSavedDocumentData] = useState(initialData)
|
||||
|
||||
const isInitializing = initialState === undefined || data === undefined
|
||||
const isInitializing = initialState === undefined || initialData === undefined
|
||||
|
||||
const { getPreference, setPreference } = usePreferences()
|
||||
const { code: locale } = useLocale()
|
||||
@@ -251,18 +252,25 @@ const DocumentInfo: React.FC<
|
||||
}
|
||||
}, [collectionConfig, globalConfig, versionCount])
|
||||
|
||||
const updateSavedDocumentData = React.useCallback<DocumentInfoContext['updateSavedDocumentData']>(
|
||||
(json) => {
|
||||
setSavedDocumentData(json)
|
||||
},
|
||||
[],
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
setDocumentTitle(
|
||||
formatDocTitle({
|
||||
collectionConfig,
|
||||
data: { ...data, id },
|
||||
data: { ...savedDocumentData, id },
|
||||
dateFormat,
|
||||
fallback: id?.toString(),
|
||||
globalConfig,
|
||||
i18n,
|
||||
}),
|
||||
)
|
||||
}, [collectionConfig, globalConfig, data, dateFormat, i18n, id])
|
||||
}, [collectionConfig, globalConfig, savedDocumentData, dateFormat, i18n, id])
|
||||
|
||||
// clean on unmount
|
||||
useEffect(() => {
|
||||
@@ -306,12 +314,13 @@ const DocumentInfo: React.FC<
|
||||
hasPublishPermission,
|
||||
hasSavePermission,
|
||||
incrementVersionCount,
|
||||
initialData: data,
|
||||
initialData,
|
||||
initialState,
|
||||
isInitializing,
|
||||
lastUpdateTime,
|
||||
mostRecentVersionIsAutosaved,
|
||||
preferencesKey,
|
||||
savedDocumentData,
|
||||
setCurrentEditor,
|
||||
setDocFieldPreferences,
|
||||
setDocumentIsLocked,
|
||||
@@ -324,6 +333,7 @@ const DocumentInfo: React.FC<
|
||||
unlockDocument,
|
||||
unpublishedVersionCount,
|
||||
updateDocumentEditor,
|
||||
updateSavedDocumentData,
|
||||
versionCount,
|
||||
}
|
||||
|
||||
|
||||
@@ -57,6 +57,7 @@ export type DocumentInfoContext = {
|
||||
lastUpdateTime?: number
|
||||
mostRecentVersionIsAutosaved: boolean
|
||||
preferencesKey?: string
|
||||
savedDocumentData?: Data
|
||||
setCurrentEditor?: React.Dispatch<React.SetStateAction<ClientUser>>
|
||||
setDocFieldPreferences: (
|
||||
field: string,
|
||||
@@ -72,5 +73,6 @@ export type DocumentInfoContext = {
|
||||
unlockDocument: (docId: number | string, slug: string) => Promise<void>
|
||||
unpublishedVersionCount: number
|
||||
updateDocumentEditor: (docId: number | string, slug: string, user: ClientUser) => Promise<void>
|
||||
updateSavedDocumentData: (data: Data) => void
|
||||
versionCount: number
|
||||
} & DocumentInfoProps
|
||||
|
||||
@@ -71,17 +71,18 @@ export const DefaultEditView: React.FC<ClientSideEditViewProps> = ({
|
||||
hasPublishPermission,
|
||||
hasSavePermission,
|
||||
incrementVersionCount,
|
||||
initialData: data,
|
||||
initialState,
|
||||
isEditing,
|
||||
isInitializing,
|
||||
lastUpdateTime,
|
||||
redirectAfterDelete,
|
||||
redirectAfterDuplicate,
|
||||
savedDocumentData,
|
||||
setCurrentEditor,
|
||||
setDocumentIsLocked,
|
||||
unlockDocument,
|
||||
updateDocumentEditor,
|
||||
updateSavedDocumentData,
|
||||
} = useDocumentInfo()
|
||||
|
||||
const {
|
||||
@@ -212,6 +213,10 @@ export const DefaultEditView: React.FC<ClientSideEditViewProps> = ({
|
||||
|
||||
incrementVersionCount()
|
||||
|
||||
if (typeof updateSavedDocumentData === 'function') {
|
||||
void updateSavedDocumentData(json?.doc || {})
|
||||
}
|
||||
|
||||
if (typeof onSaveFromContext === 'function') {
|
||||
void onSaveFromContext({
|
||||
...json,
|
||||
@@ -238,6 +243,7 @@ export const DefaultEditView: React.FC<ClientSideEditViewProps> = ({
|
||||
await getDocPermissions(json)
|
||||
},
|
||||
[
|
||||
updateSavedDocumentData,
|
||||
reportUpdate,
|
||||
id,
|
||||
entitySlug,
|
||||
@@ -479,7 +485,7 @@ export const DefaultEditView: React.FC<ClientSideEditViewProps> = ({
|
||||
SaveButton,
|
||||
SaveDraftButton,
|
||||
}}
|
||||
data={data}
|
||||
data={savedDocumentData}
|
||||
disableActions={disableActions}
|
||||
disableCreate={disableCreate}
|
||||
hasPublishPermission={hasPublishPermission}
|
||||
@@ -521,7 +527,7 @@ export const DefaultEditView: React.FC<ClientSideEditViewProps> = ({
|
||||
className={`${baseClass}__auth`}
|
||||
collectionSlug={collectionConfig.slug}
|
||||
disableLocalStrategy={collectionConfig.auth?.disableLocalStrategy}
|
||||
email={data?.email}
|
||||
email={savedDocumentData?.email}
|
||||
loginWithUsername={auth?.loginWithUsername}
|
||||
operation={operation}
|
||||
readOnly={!hasSavePermission}
|
||||
@@ -529,7 +535,7 @@ export const DefaultEditView: React.FC<ClientSideEditViewProps> = ({
|
||||
setSchemaPathSegments={setSchemaPathSegments}
|
||||
setValidateBeforeSubmit={setValidateBeforeSubmit}
|
||||
useAPIKey={auth.useAPIKey}
|
||||
username={data?.username}
|
||||
username={savedDocumentData?.username}
|
||||
verify={auth.verify}
|
||||
/>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user