Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
91 commits
Select commit Hold shift + click to select a range
eefd4e9
chore: adds lock icon
PatrikKozak Aug 15, 2024
41ed357
chore: adds new lockWhenEditing prop to collections & globals config
PatrikKozak Aug 15, 2024
e14264c
feat: adds payload-locks collection
PatrikKozak Aug 18, 2024
9fd3b65
feat: adds DocumentLockProvider & locks document when editing
PatrikKozak Aug 18, 2024
583520c
Merge branch 'beta' of https://github.com/payloadcms/payload into fea…
PatrikKozak Aug 18, 2024
905e91a
feat: adds document-locked & document-take-over modal
PatrikKozak Aug 20, 2024
6ec24ef
Merge branch 'beta' of https://github.com/payloadcms/payload into fea…
PatrikKozak Aug 20, 2024
e439fba
chore: locked-document progress
PatrikKozak Aug 22, 2024
cc9c73d
feat: correctly fire to form-state on a 10 second interval
PatrikKozak Aug 22, 2024
07d1829
feat: renders take over modal only once new user starts editing
PatrikKozak Aug 23, 2024
8c096d1
chore: destructures state where getFormState is called
PatrikKozak Aug 23, 2024
495d12e
Merge branch 'beta' of https://github.com/payloadcms/payload into fea…
PatrikKozak Aug 23, 2024
5211f58
feat: adds Locked component & translations for DocumentLocked comp & …
PatrikKozak Aug 26, 2024
184698e
feat: adds Locked comp and take over button to document-controls comp
PatrikKozak Aug 26, 2024
926d32c
feat: updates new collection name to payload-locked-documents
PatrikKozak Aug 26, 2024
2a4e429
feat: prevents locked documents from being selected in the list view
PatrikKozak Aug 26, 2024
7b8efde
Merge branch 'beta' of https://github.com/payloadcms/payload into fea…
PatrikKozak Aug 26, 2024
b726401
feat: adds editingTakenOver to translations for DocumentTakeOver modal
PatrikKozak Aug 26, 2024
2d278ff
Merge branch 'beta' of https://github.com/payloadcms/payload into fea…
PatrikKozak Aug 26, 2024
00b114a
feat: handles global document locking
PatrikKozak Aug 27, 2024
9fda6fd
Merge branch 'beta' of https://github.com/payloadcms/payload into fea…
PatrikKozak Aug 27, 2024
89612aa
feat: removes polling & updates user off of form-state in onChange call
PatrikKozak Aug 28, 2024
281ba92
Merge branch 'beta' of https://github.com/payloadcms/payload into fea…
PatrikKozak Aug 28, 2024
3fe58f6
feat: more translations & updates to effects
PatrikKozak Aug 29, 2024
33c8a60
Merge branch 'beta' of https://github.com/payloadcms/payload into fea…
PatrikKozak Aug 29, 2024
6fc89e8
feat: locking and updating functionality & adds proper reset timer
PatrikKozak Aug 29, 2024
b402b81
Merge branch 'beta' of https://github.com/payloadcms/payload into fea…
PatrikKozak Aug 29, 2024
d6abec9
feat: disables document locking if lockWhenEditing is false
PatrikKozak Aug 29, 2024
ee14b8b
chore: fix build
PatrikKozak Aug 29, 2024
8f872ef
Merge branch 'beta' of https://github.com/payloadcms/payload into fea…
PatrikKozak Aug 29, 2024
e75980d
Merge branch 'beta' of https://github.com/payloadcms/payload into fea…
PatrikKozak Aug 30, 2024
3f5cd79
chore: merge beta
PatrikKozak Aug 30, 2024
e616a45
Merge branch 'beta' of https://github.com/payloadcms/payload into fea…
PatrikKozak Aug 30, 2024
4e100f3
chore: adds locked-documents test suite
PatrikKozak Aug 30, 2024
0db687f
chore: adds optional chaining to lockWhenEditing prop
PatrikKozak Aug 30, 2024
d71b3e2
Merge branch 'beta' of https://github.com/payloadcms/payload into fea…
PatrikKozak Aug 30, 2024
e115860
feat: simplifies document locking & unlocking handling
PatrikKozak Sep 2, 2024
8640fc7
Merge branch 'beta' of https://github.com/payloadcms/payload into fea…
PatrikKozak Sep 2, 2024
3404dc9
chore: undo lint fixes in db packages
PatrikKozak Sep 3, 2024
af543d4
Merge branch 'beta' of https://github.com/payloadcms/payload into fea…
PatrikKozak Sep 3, 2024
b370181
Merge branch 'beta' of https://github.com/payloadcms/payload into fea…
PatrikKozak Sep 3, 2024
35c7e3e
feat: prevent updating / deleting of documents using the local API wh…
PatrikKozak Sep 3, 2024
9543afc
Merge branch 'beta' of https://github.com/payloadcms/payload into fea…
PatrikKozak Sep 3, 2024
ec2e262
chore: reverts buildConfigWithDefaults
PatrikKozak Sep 4, 2024
8d61179
chore: reverts type updates for _community test suite
PatrikKozak Sep 4, 2024
b034291
feat: removes doc from payload-locked-documents after update
PatrikKozak Sep 4, 2024
32102fa
Merge branch 'beta' of https://github.com/payloadcms/payload into fea…
PatrikKozak Sep 4, 2024
a6cb6cc
feat: handle global updating of locked documents
PatrikKozak Sep 4, 2024
a3d6256
chore: reintroduce editedAt date for DocumentLocked modal
PatrikKozak Sep 4, 2024
4b4c267
chore: adds locked-documents e2e tests
PatrikKozak Sep 5, 2024
1e33397
Merge branch 'beta' of https://github.com/payloadcms/payload into fea…
PatrikKozak Sep 5, 2024
b824e95
chore: handles lock icon for light & dark mode
PatrikKozak Sep 6, 2024
7322e61
Merge branch 'beta' of https://github.com/payloadcms/payload into fea…
PatrikKozak Sep 6, 2024
08dcabe
chore: add wait to allow proper unlock in field-error-state test
PatrikKozak Sep 6, 2024
14272ce
chore: fixes bug in delete & update oeprations not properly deleting …
PatrikKozak Sep 6, 2024
042c1d8
feat: adds int tests for locked-documents
PatrikKozak Sep 6, 2024
a860019
Merge branch 'beta' of https://github.com/payloadcms/payload into fea…
PatrikKozak Sep 6, 2024
9b38350
chore: adds corresponding documentation
PatrikKozak Sep 6, 2024
185c38e
Merge branch 'beta' of https://github.com/payloadcms/payload into fea…
PatrikKozak Sep 6, 2024
7e1b3e8
chore: update int test names for locked-documents
PatrikKozak Sep 9, 2024
ba8a19a
Merge branch 'beta' of https://github.com/payloadcms/payload into fea…
PatrikKozak Sep 9, 2024
bc2763f
chore: revert link button changes in richtext-slate
PatrikKozak Sep 9, 2024
8265bf7
fix: deletes docs using db operations
PatrikKozak Sep 10, 2024
df85ebd
fix: added handling for relationships where newCollectionPath was an …
PatrikKozak Sep 10, 2024
b2ab773
chore: cleans up int tests for locked-documents
PatrikKozak Sep 10, 2024
f6adba3
Merge branch 'beta' of https://github.com/payloadcms/payload into fea…
PatrikKozak Sep 10, 2024
97f98be
chore: create checkDocumentLockStatus function
PatrikKozak Sep 11, 2024
af5ac4d
Merge branch 'beta' of https://github.com/payloadcms/payload into fea…
PatrikKozak Sep 11, 2024
630fbbe
chore: return early in checkDocumentLockStatus if locking is disabled
PatrikKozak Sep 11, 2024
b006beb
Merge branch 'beta' of https://github.com/payloadcms/payload into fea…
PatrikKozak Sep 11, 2024
e631c70
fix: queries with in operator for document value
PatrikKozak Sep 11, 2024
7a203ab
Merge branch 'beta' of https://github.com/payloadcms/payload into fea…
PatrikKozak Sep 11, 2024
7be0230
chore: casts id columns to text
PatrikKozak Sep 12, 2024
129b9e1
Merge branch 'beta' of https://github.com/payloadcms/payload into fea…
PatrikKozak Sep 12, 2024
207dead
chore: workaround for postgres and sqlite adapeters
PatrikKozak Sep 12, 2024
4728738
Merge branch 'beta' of https://github.com/payloadcms/payload into fea…
PatrikKozak Sep 12, 2024
0e1e6b4
fix: polymorphic relationship querying with different relationTo ID t…
PatrikKozak Sep 12, 2024
09bbbcc
Merge branch 'beta' of https://github.com/payloadcms/payload into fea…
PatrikKozak Sep 12, 2024
9c9afe2
Merge branch 'beta' of https://github.com/payloadcms/payload into fea…
PatrikKozak Sep 13, 2024
4c537c3
test: adds e2e test for list view bulk delete
PatrikKozak Sep 13, 2024
964d1ea
chore: filter out collections that are not GraphQL enabled in buildOb…
PatrikKozak Sep 13, 2024
861c8ad
Merge branch 'beta' of https://github.com/payloadcms/payload into fea…
PatrikKozak Sep 13, 2024
417c128
chore: adds locked-documents e2e test suite to github workflow
PatrikKozak Sep 16, 2024
44f47bf
Merge branch 'beta' of https://github.com/payloadcms/payload into fea…
PatrikKozak Sep 16, 2024
5a2b1a2
chore: updates locked document queries to use equals operator
PatrikKozak Sep 16, 2024
e4fbe02
Merge branch 'beta' of https://github.com/payloadcms/payload into fea…
PatrikKozak Sep 16, 2024
cea9d61
fix: reverts operator to use in for find-many payload-locked-documents
PatrikKozak Sep 16, 2024
9da8999
Merge branch 'beta' of https://github.com/payloadcms/payload into fea…
PatrikKozak Sep 16, 2024
f37c198
chore: updates documentation & prop name to lockDocuments
PatrikKozak Sep 16, 2024
0368a7a
Merge branch 'beta' of https://github.com/payloadcms/payload into fea…
PatrikKozak Sep 16, 2024
e084153
Merge branch 'beta' of https://github.com/payloadcms/payload into fea…
PatrikKozak Sep 17, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,7 @@ jobs:
- fields__collections__Upload
- live-preview
- localization
- locked-documents
- i18n
- plugin-cloud-storage
- plugin-form-builder
Expand Down
7 changes: 7 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,13 @@
"request": "launch",
"type": "node-terminal"
},
{
"command": "node --no-deprecation test/dev.js locked-documents",
"cwd": "${workspaceFolder}",
"name": "Run Dev Locked Documents",
"request": "launch",
"type": "node-terminal"
},
{
"command": "node --no-deprecation test/dev.js uploads",
"cwd": "${workspaceFolder}",
Expand Down
60 changes: 60 additions & 0 deletions docs/admin/locked-documents.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
---
title: Document Locking
label: Document Locking
order: 90
desc: Ensure your documents are locked while being edited, preventing concurrent edits from multiple users and preserving data integrity.
keywords: locking, document locking, edit locking, document, concurrency, Payload, headless, Content Management System, cms, javascript, react, node, nextjs
---

Document locking in Payload ensures that only one user at a time can edit a document, preventing data conflicts and accidental overwrites. When a document is locked, other users are prevented from making changes until the lock is released, ensuring data integrity in collaborative environments.

The lock is automatically triggered when a user begins editing a document within the Admin Panel and remains in place until the user exits the editing view or the lock expires due to inactivity.

## How it works

When a user starts editing a document, Payload locks the document for that user. If another user tries to access the same document, they will be notified that it is currently being edited and can choose one of the following options:

- View in Read-Only Mode: View the document without making any changes.
- Take Over Editing: Take over editing from the current user, which locks the document for the new editor and notifies the original user.
- Return to Dashboard: Navigate away from the locked document and continue with other tasks.

The lock will automatically expire after a set period of inactivity, configurable using the duration property in the lockDocuments configuration, after which others can resume editing.

<Banner type="info"> <strong>Note:</strong> If your application does not require document locking, you can disable this feature for any collection by setting the <code>lockDocuments</code> property to <code>false</code>. </Banner>

### Config Options

The lockDocuments property exists on both the Collection Config and the Global Config. By default, document locking is enabled for all collections and globals, but you can customize the lock duration or disable the feature entirely.

Here’s an example configuration for document locking:

```ts
import { CollectionConfig } from 'payload'

export const Posts: CollectionConfig = {
slug: 'posts',
fields: [
{
name: 'title',
type: 'text',
},
// other fields...
],
lockDocuments: {
duration: 600, // Duration in seconds
},
}
```

#### Locking Options

| Option | Description |
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **`lockDocuments`** | Enables or disables document locking for the collection or global. By default, document locking is enabled. Set to an object to configure, or set to false to disable locking. |
| **`duration`** | Specifies the duration (in seconds) for how long a document remains locked without user interaction. The default is 300 seconds (5 minutes). |

### Impact on APIs

Document locking affects both the Local API and the REST API, ensuring that if a document is locked, concurrent users will not be able to perform updates or deletes on that document (including globals). If a user attempts to update or delete a locked document, they will receive an error.

Once the document is unlocked or the lock duration has expired, other users can proceed with updates or deletes as normal.
39 changes: 20 additions & 19 deletions docs/configuration/collections.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -57,25 +57,26 @@ export const Posts: CollectionConfig = {

The following options are available:

| Option | Description |
|------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| **`admin`** | The configuration options for the Admin Panel. [More details](../admin/collections). |
| **`access`** | Provide Access Control functions to define exactly who should be able to do what with Documents in this Collection. [More details](../access-control/collections). |
| **`auth`** | Specify options if you would like this Collection to feature authentication. [More details](../authentication/overview). |
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
| **`disableDuplicate`** | When true, do not show the "Duplicate" button while editing documents within this Collection and prevent `duplicate` from all APIs. |
| **`defaultSort`** | Pass a top-level field to sort by default in the Collection List View. Prefix the name of the field with a minus symbol ("-") to sort in descending order. |
| **`dbName`** | Custom table or Collection name depending on the Database Adapter. Auto-generated from slug if not defined. |
| **`endpoints`** | Add custom routes to the REST API. Set to `false` to disable routes. [More details](../rest-api/overview#custom-endpoints). |
| **`fields`** \* | Array of field types that will determine the structure and functionality of the data stored within this Collection. [More details](../fields/overview). |
| **`graphQL`** | An object with `singularName` and `pluralName` strings used in schema generation. Auto-generated from slug if not defined. Set to `false` to disable GraphQL. |
| **`hooks`** | Entry point for Hooks. [More details](../hooks/overview#collection-hooks). |
| **`labels`** | Singular and plural labels for use in identifying this Collection throughout Payload. Auto-generated from slug if not defined. |
| **`slug`** \* | Unique, URL-friendly string that will act as an identifier for this Collection. |
| **`timestamps`** | Set to false to disable documents' automatically generated `createdAt` and `updatedAt` timestamps. |
| **`typescript`** | An object with property `interface` as the text used in schema generation. Auto-generated from slug if not defined. |
| **`upload`** | Specify options if you would like this Collection to support file uploads. For more, consult the [Uploads](../upload/overview) documentation. |
| **`versions`** | Set to true to enable default options, or configure with object properties. [More details](../versions/overview#collection-config). |
| Option | Description |
|------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **`admin`** | The configuration options for the Admin Panel. [More details](../admin/collections). |
| **`access`** | Provide Access Control functions to define exactly who should be able to do what with Documents in this Collection. [More details](../access-control/collections). |
| **`auth`** | Specify options if you would like this Collection to feature authentication. [More details](../authentication/overview). |
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
| **`disableDuplicate`** | When true, do not show the "Duplicate" button while editing documents within this Collection and prevent `duplicate` from all APIs. |
| **`defaultSort`** | Pass a top-level field to sort by default in the Collection List View. Prefix the name of the field with a minus symbol ("-") to sort in descending order. |
| **`dbName`** | Custom table or Collection name depending on the Database Adapter. Auto-generated from slug if not defined. |
| **`endpoints`** | Add custom routes to the REST API. Set to `false` to disable routes. [More details](../rest-api/overview#custom-endpoints). |
| **`fields`** \* | Array of field types that will determine the structure and functionality of the data stored within this Collection. [More details](../fields/overview). |
| **`graphQL`** | An object with `singularName` and `pluralName` strings used in schema generation. Auto-generated from slug if not defined. Set to `false` to disable GraphQL. |
| **`hooks`** | Entry point for Hooks. [More details](../hooks/overview#collection-hooks). |
| **`labels`** | Singular and plural labels for use in identifying this Collection throughout Payload. Auto-generated from slug if not defined. |
| **`lockDocuments`** | Enables or disables document locking. By default, document locking is enabled. Set to an object to configure, or set to `false` to disable locking. [More details](../admin/locked-documents). |
| **`slug`** \* | Unique, URL-friendly string that will act as an identifier for this Collection. |
| **`timestamps`** | Set to false to disable documents' automatically generated `createdAt` and `updatedAt` timestamps. |
| **`typescript`** | An object with property `interface` as the text used in schema generation. Auto-generated from slug if not defined. |
| **`upload`** | Specify options if you would like this Collection to support file uploads. For more, consult the [Uploads](../upload/overview) documentation. |
| **`versions`** | Set to true to enable default options, or configure with object properties. [More details](../versions/overview#collection-config). |

_\* An asterisk denotes that a property is required._

Expand Down
31 changes: 16 additions & 15 deletions docs/configuration/globals.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -65,21 +65,22 @@ export const Nav: GlobalConfig = {

The following options are available:

| Option | Description |
| ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **`access`** | Provide Access Control functions to define exactly who should be able to do what with this Global. [More details](../access-control/globals). |
| **`admin`** | The configuration options for the Admin Panel. [More details](../admin/globals). |
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
| **`dbName`** | Custom table or collection name for this Global depending on the Database Adapter. Auto-generated from slug if not defined. |
| **`description`** | Text or React component to display below the Global header to give editors more information. |
| **`endpoints`** | Add custom routes to the REST API. [More details](../rest-api/overview#custom-endpoints). |
| **`fields`** \* | Array of field types that will determine the structure and functionality of the data stored within this Global. [More details](../fields/overview). |
| **`graphQL.name`** | Text used in schema generation. Auto-generated from slug if not defined. |
| **`hooks`** | Entry point for Hooks. [More details](../hooks/overview#global-hooks). |
| **`label`** | Text for the name in the Admin Panel or an object with keys for each language. Auto-generated from slug if not defined. |
| **`slug`** \* | Unique, URL-friendly string that will act as an identifier for this Global. |
| **`typescript`** | An object with property `interface` as the text used in schema generation. Auto-generated from slug if not defined. |
| **`versions`** | Set to true to enable default options, or configure with object properties. [More details](../versions/overview#globals-config). |
| Option | Description |
| ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **`access`** | Provide Access Control functions to define exactly who should be able to do what with this Global. [More details](../access-control/globals). |
| **`admin`** | The configuration options for the Admin Panel. [More details](../admin/globals). |
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
| **`dbName`** | Custom table or collection name for this Global depending on the Database Adapter. Auto-generated from slug if not defined. |
| **`description`** | Text or React component to display below the Global header to give editors more information. |
| **`endpoints`** | Add custom routes to the REST API. [More details](../rest-api/overview#custom-endpoints). |
| **`fields`** \* | Array of field types that will determine the structure and functionality of the data stored within this Global. [More details](../fields/overview). |
| **`graphQL.name`** | Text used in schema generation. Auto-generated from slug if not defined. |
| **`hooks`** | Entry point for Hooks. [More details](../hooks/overview#global-hooks). |
| **`label`** | Text for the name in the Admin Panel or an object with keys for each language. Auto-generated from slug if not defined. |
| **`lockDocuments`** | Enables or disables document locking. By default, document locking is enabled. Set to an object to configure, or set to `false` to disable locking. [More details](../admin/locked-documents). |
| **`slug`** \* | Unique, URL-friendly string that will act as an identifier for this Global. |
| **`typescript`** | An object with property `interface` as the text used in schema generation. Auto-generated from slug if not defined. |
| **`versions`** | Set to true to enable default options, or configure with object properties. [More details](../versions/overview#globals-config). |

_\* An asterisk denotes that a property is required._

Expand Down
Loading