Skip to content

Commit 57f93c9

Browse files
authored
fix: lock documents using the live-preview view (#8343)
Updates: - Exports `handleGoBack`, `handleBackToDashboard`, & `handleTakeOver` functions to consolidate logic in default edit view & live-preview edit view. - Only unlock document on navigation away from edit view entirely (aka do not unlock document if switching between tabs like `edit` --> `live-preview` --> `versions` --> `api`
1 parent 32c8d28 commit 57f93c9

File tree

8 files changed

+393
-98
lines changed

8 files changed

+393
-98
lines changed

packages/next/src/views/Edit/Default/index.tsx

Lines changed: 50 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,13 @@ import {
1717
useEditDepth,
1818
useUploadEdits,
1919
} from '@payloadcms/ui'
20-
import { formatAdminURL, getFormState } from '@payloadcms/ui/shared'
20+
import {
21+
formatAdminURL,
22+
getFormState,
23+
handleBackToDashboard,
24+
handleGoBack,
25+
handleTakeOver,
26+
} from '@payloadcms/ui/shared'
2127
import { useRouter, useSearchParams } from 'next/navigation.js'
2228
import React, { Fragment, useCallback, useEffect, useRef, useState } from 'react'
2329

@@ -151,89 +157,6 @@ export const DefaultEditView: React.FC = () => {
151157
return false
152158
})
153159

154-
const handleTakeOver = useCallback(() => {
155-
if (!isLockingEnabled) {
156-
return
157-
}
158-
159-
try {
160-
// Call updateDocumentEditor to update the document's owner to the current user
161-
void updateDocumentEditor(id, collectionSlug ?? globalSlug, user)
162-
163-
documentLockStateRef.current.hasShownLockedModal = true
164-
165-
// Update the locked state to reflect the current user as the owner
166-
documentLockStateRef.current = {
167-
hasShownLockedModal: documentLockStateRef.current?.hasShownLockedModal,
168-
isLocked: true,
169-
user,
170-
}
171-
setCurrentEditor(user)
172-
} catch (error) {
173-
// eslint-disable-next-line no-console
174-
console.error('Error during document takeover:', error)
175-
}
176-
}, [
177-
updateDocumentEditor,
178-
id,
179-
collectionSlug,
180-
globalSlug,
181-
user,
182-
setCurrentEditor,
183-
isLockingEnabled,
184-
])
185-
186-
const handleTakeOverWithinDoc = useCallback(() => {
187-
if (!isLockingEnabled) {
188-
return
189-
}
190-
191-
try {
192-
// Call updateDocumentEditor to update the document's owner to the current user
193-
void updateDocumentEditor(id, collectionSlug ?? globalSlug, user)
194-
195-
// Update the locked state to reflect the current user as the owner
196-
documentLockStateRef.current = {
197-
hasShownLockedModal: documentLockStateRef.current?.hasShownLockedModal,
198-
isLocked: true,
199-
user,
200-
}
201-
setCurrentEditor(user)
202-
203-
// Ensure the document is editable for the incoming user
204-
setIsReadOnlyForIncomingUser(false)
205-
} catch (error) {
206-
// eslint-disable-next-line no-console
207-
console.error('Error during document takeover:', error)
208-
}
209-
}, [
210-
updateDocumentEditor,
211-
id,
212-
collectionSlug,
213-
globalSlug,
214-
user,
215-
setCurrentEditor,
216-
isLockingEnabled,
217-
])
218-
219-
const handleGoBack = useCallback(() => {
220-
const redirectRoute = formatAdminURL({
221-
adminRoute,
222-
path: collectionSlug ? `/collections/${collectionSlug}` : '/',
223-
})
224-
router.push(redirectRoute)
225-
}, [adminRoute, collectionSlug, router])
226-
227-
const handleBackToDashboard = useCallback(() => {
228-
setShowTakeOverModal(false)
229-
const redirectRoute = formatAdminURL({
230-
adminRoute,
231-
path: '/',
232-
})
233-
234-
router.push(redirectRoute)
235-
}, [adminRoute, router])
236-
237160
const onSave = useCallback(
238161
(json) => {
239162
reportUpdate({
@@ -373,7 +296,19 @@ export const DefaultEditView: React.FC = () => {
373296
return
374297
}
375298

376-
if ((id || globalSlug) && documentIsLocked) {
299+
const currentPath = window.location.pathname
300+
301+
const documentId = id || globalSlug
302+
303+
// Routes where we do NOT want to unlock the document
304+
const stayWithinDocumentPaths = ['preview', 'api', 'versions']
305+
306+
const isStayingWithinDocument = stayWithinDocumentPaths.some((path) =>
307+
currentPath.includes(path),
308+
)
309+
310+
// Unlock the document only if we're actually navigating away from the document
311+
if (documentId && documentIsLocked && !isStayingWithinDocument) {
377312
// Check if this user is still the current editor
378313
if (documentLockStateRef.current?.user?.id === user.id) {
379314
void unlockDocument(id, collectionSlug ?? globalSlug)
@@ -421,20 +356,32 @@ export const DefaultEditView: React.FC = () => {
421356
{BeforeDocument}
422357
{isLockingEnabled && shouldShowDocumentLockedModal && !isReadOnlyForIncomingUser && (
423358
<DocumentLocked
424-
handleGoBack={handleGoBack}
359+
handleGoBack={() => handleGoBack({ adminRoute, collectionSlug, router })}
425360
isActive={shouldShowDocumentLockedModal}
426361
onReadOnly={() => {
427362
setIsReadOnlyForIncomingUser(true)
428363
setShowTakeOverModal(false)
429364
}}
430-
onTakeOver={handleTakeOver}
365+
onTakeOver={() =>
366+
handleTakeOver(
367+
id,
368+
collectionSlug,
369+
globalSlug,
370+
user,
371+
false,
372+
updateDocumentEditor,
373+
setCurrentEditor,
374+
documentLockStateRef,
375+
isLockingEnabled,
376+
)
377+
}
431378
updatedAt={lastUpdateTime}
432379
user={currentEditor}
433380
/>
434381
)}
435382
{isLockingEnabled && showTakeOverModal && (
436383
<DocumentTakeOver
437-
handleBackToDashboard={handleBackToDashboard}
384+
handleBackToDashboard={() => handleBackToDashboard({ adminRoute, router })}
438385
isActive={showTakeOverModal}
439386
onReadOnly={() => {
440387
setIsReadOnlyForIncomingUser(true)
@@ -469,7 +416,20 @@ export const DefaultEditView: React.FC = () => {
469416
onDrawerCreate={onDrawerCreate}
470417
onDuplicate={onDuplicate}
471418
onSave={onSave}
472-
onTakeOver={handleTakeOverWithinDoc}
419+
onTakeOver={() =>
420+
handleTakeOver(
421+
id,
422+
collectionSlug,
423+
globalSlug,
424+
user,
425+
true,
426+
updateDocumentEditor,
427+
setCurrentEditor,
428+
documentLockStateRef,
429+
isLockingEnabled,
430+
setIsReadOnlyForIncomingUser,
431+
)
432+
}
473433
permissions={docPermissions}
474434
readOnlyForIncomingUser={isReadOnlyForIncomingUser}
475435
redirectAfterDelete={redirectAfterDelete}
@@ -494,6 +454,7 @@ export const DefaultEditView: React.FC = () => {
494454
requirePassword={!id}
495455
setSchemaPath={setSchemaPath}
496456
setValidateBeforeSubmit={setValidateBeforeSubmit}
457+
// eslint-disable-next-line react-compiler/react-compiler
497458
useAPIKey={auth.useAPIKey}
498459
username={data?.username}
499460
verify={auth.verify}

0 commit comments

Comments
 (0)