Skip to content

Commit

Permalink
fix(ui): client side doc data not updating after save (#9340)
Browse files Browse the repository at this point in the history
### 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.
  • Loading branch information
JarrodMFlesch authored Nov 19, 2024
1 parent 69b7a11 commit 661f450
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 33 deletions.
54 changes: 31 additions & 23 deletions packages/ui/src/elements/Upload/index.tsx
Original file line number Diff line number Diff line change
@@ -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'
Expand Down Expand Up @@ -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>('')
Expand Down Expand Up @@ -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])
Expand Down Expand Up @@ -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(() => {
Expand All @@ -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

Expand All @@ -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}>
Expand Down Expand Up @@ -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>
Expand All @@ -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}
Expand All @@ -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>
Expand Down
22 changes: 16 additions & 6 deletions packages/ui/src/providers/DocumentInfo/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ const DocumentInfo: React.FC<
hasPublishedDoc: hasPublishedDocFromProps,
hasPublishPermission: hasPublishPermissionFromProps,
hasSavePermission: hasSavePermissionFromProps,
initialData: data,
initialData,
initialState,
isLocked: isLockedFromProps,
lastUpdateTime: lastUpdateTimeFromProps,
Expand Down Expand Up @@ -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,
Expand All @@ -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()
Expand Down Expand Up @@ -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(() => {
Expand Down Expand Up @@ -306,12 +314,13 @@ const DocumentInfo: React.FC<
hasPublishPermission,
hasSavePermission,
incrementVersionCount,
initialData: data,
initialData,
initialState,
isInitializing,
lastUpdateTime,
mostRecentVersionIsAutosaved,
preferencesKey,
savedDocumentData,
setCurrentEditor,
setDocFieldPreferences,
setDocumentIsLocked,
Expand All @@ -324,6 +333,7 @@ const DocumentInfo: React.FC<
unlockDocument,
unpublishedVersionCount,
updateDocumentEditor,
updateSavedDocumentData,
versionCount,
}

Expand Down
2 changes: 2 additions & 0 deletions packages/ui/src/providers/DocumentInfo/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ export type DocumentInfoContext = {
lastUpdateTime?: number
mostRecentVersionIsAutosaved: boolean
preferencesKey?: string
savedDocumentData?: Data
setCurrentEditor?: React.Dispatch<React.SetStateAction<ClientUser>>
setDocFieldPreferences: (
field: string,
Expand All @@ -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
14 changes: 10 additions & 4 deletions packages/ui/src/views/Edit/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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,
Expand All @@ -238,6 +243,7 @@ export const DefaultEditView: React.FC<ClientSideEditViewProps> = ({
await getDocPermissions(json)
},
[
updateSavedDocumentData,
reportUpdate,
id,
entitySlug,
Expand Down Expand Up @@ -479,7 +485,7 @@ export const DefaultEditView: React.FC<ClientSideEditViewProps> = ({
SaveButton,
SaveDraftButton,
}}
data={data}
data={savedDocumentData}
disableActions={disableActions}
disableCreate={disableCreate}
hasPublishPermission={hasPublishPermission}
Expand Down Expand Up @@ -521,15 +527,15 @@ 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}
requirePassword={!id}
setSchemaPathSegments={setSchemaPathSegments}
setValidateBeforeSubmit={setValidateBeforeSubmit}
useAPIKey={auth.useAPIKey}
username={data?.username}
username={savedDocumentData?.username}
verify={auth.verify}
/>
)}
Expand Down

0 comments on commit 661f450

Please sign in to comment.