Skip to content

Commit 879f690

Browse files
authored
feat(ui): hides lock icon when locked by current user (#8309)
1 parent 405a6c3 commit 879f690

File tree

5 files changed

+76
-29
lines changed

5 files changed

+76
-29
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ export const DefaultDashboard: React.FC<DashboardProps> = (props) => {
140140
<li key={entityIndex}>
141141
<Card
142142
actions={
143-
lockStatus ? (
143+
lockStatus && user?.id !== userEditing?.id ? (
144144
<Locked className={`${baseClass}__locked`} user={userEditing} />
145145
) : hasCreatePermission && type === EntityType.collection ? (
146146
<Button

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import {
2121
StaggeredShimmers,
2222
Table,
2323
UnpublishMany,
24+
useAuth,
2425
useBulkUpload,
2526
useConfig,
2627
useEditDepth,
@@ -43,6 +44,7 @@ const baseClass = 'collection-list'
4344
const Link = (LinkImport.default || LinkImport) as unknown as typeof LinkImport.default
4445

4546
export const DefaultListView: React.FC = () => {
47+
const { user } = useAuth()
4648
const {
4749
beforeActions,
4850
collectionSlug,
@@ -125,7 +127,7 @@ export const DefaultListView: React.FC = () => {
125127
return (
126128
<div className={`${baseClass} ${baseClass}--${collectionSlug}`}>
127129
<SetViewActions actions={actions} />
128-
<SelectionProvider docs={data.docs} totalDocs={data.totalDocs}>
130+
<SelectionProvider docs={data.docs} totalDocs={data.totalDocs} user={user}>
129131
<RenderComponent mappedComponent={beforeList} />
130132
<Gutter className={`${baseClass}__wrap`}>
131133
{Header || (

packages/ui/src/elements/SelectRow/index.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,22 @@ import React from 'react'
33

44
import { useTableCell } from '../../elements/Table/TableCellProvider/index.js'
55
import { CheckboxInput } from '../../fields/Checkbox/Input.js'
6+
import { useAuth } from '../../providers/Auth/index.js'
67
import { useSelection } from '../../providers/Selection/index.js'
78
import { Locked } from '../Locked/index.js'
89
import './index.scss'
910

1011
const baseClass = 'select-row'
1112

1213
export const SelectRow: React.FC = () => {
14+
const { user } = useAuth()
1315
const { selected, setSelection } = useSelection()
1416
const { rowData } = useTableCell()
1517
const { _isLocked, _userEditing } = rowData || {}
1618

1719
const documentIsLocked = _isLocked && _userEditing
1820

19-
if (documentIsLocked) {
21+
if (documentIsLocked && _userEditing.id !== user?.id) {
2022
return <Locked user={_userEditing} />
2123
}
2224

packages/ui/src/providers/Selection/index.tsx

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
'use client'
2-
import type { Where } from 'payload'
2+
import type { ClientUser, Where } from 'payload'
33

44
import * as qs from 'qs-esm'
55
import React, { createContext, useCallback, useContext, useEffect, useRef, useState } from 'react'
@@ -33,9 +33,10 @@ type Props = {
3333
// eslint-disable-next-line @typescript-eslint/no-explicit-any
3434
readonly docs: any[]
3535
readonly totalDocs: number
36+
user: ClientUser
3637
}
3738

38-
export const SelectionProvider: React.FC<Props> = ({ children, docs = [], totalDocs }) => {
39+
export const SelectionProvider: React.FC<Props> = ({ children, docs = [], totalDocs, user }) => {
3940
const contextRef = useRef({} as SelectionContext)
4041

4142
const { code: locale } = useLocale()
@@ -56,8 +57,8 @@ export const SelectionProvider: React.FC<Props> = ({ children, docs = [], totalD
5657
const rows = new Map()
5758
if (allAvailable) {
5859
setSelectAll(SelectAllStatus.AllAvailable)
59-
docs.forEach(({ id, _isLocked }) => {
60-
if (!_isLocked) {
60+
docs.forEach(({ id, _isLocked, _userEditing }) => {
61+
if (!_isLocked || _userEditing?.id === user?.id) {
6162
rows.set(id, true)
6263
}
6364
})
@@ -67,22 +68,22 @@ export const SelectionProvider: React.FC<Props> = ({ children, docs = [], totalD
6768
) {
6869
setSelectAll(SelectAllStatus.None)
6970
} else {
70-
docs.forEach(({ id, _isLocked }) => {
71-
if (!_isLocked) {
71+
docs.forEach(({ id, _isLocked, _userEditing }) => {
72+
if (!_isLocked || _userEditing?.id === user?.id) {
7273
rows.set(id, selectAll !== SelectAllStatus.Some)
7374
}
7475
})
7576
}
7677
setSelected(rows)
7778
},
78-
[docs, selectAll],
79+
[docs, selectAll, user?.id],
7980
)
8081

8182
const setSelection = useCallback(
8283
(id) => {
8384
const doc = docs.find((doc) => doc.id === id)
8485

85-
if (doc?._isLocked) {
86+
if (doc?._isLocked && user?.id !== doc?._userEditing.id) {
8687
return // Prevent selection if the document is locked
8788
}
8889

@@ -99,7 +100,7 @@ export const SelectionProvider: React.FC<Props> = ({ children, docs = [], totalD
99100

100101
setSelected(newMap)
101102
},
102-
[selected, docs],
103+
[selected, docs, user?.id],
103104
)
104105

105106
const getQueryParams = useCallback(

test/locked-documents/e2e.spec.ts

Lines changed: 59 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ describe('locked documents', () => {
7070

7171
describe('list view - collections', () => {
7272
let postDoc
73+
let anotherPostDoc
7374
let user2
7475
let lockedDoc
7576

@@ -78,6 +79,10 @@ describe('locked documents', () => {
7879
text: 'hello',
7980
})
8081

82+
anotherPostDoc = await createPostDoc({
83+
text: 'another post',
84+
})
85+
8186
user2 = await payload.create({
8287
collection: 'users',
8388
data: {
@@ -114,6 +119,11 @@ describe('locked documents', () => {
114119
id: postDoc.id,
115120
})
116121

122+
await payload.delete({
123+
collection: 'posts',
124+
id: anotherPostDoc.id,
125+
})
126+
117127
await payload.delete({
118128
collection: 'users',
119129
id: user2.id,
@@ -124,22 +134,37 @@ describe('locked documents', () => {
124134
await page.goto(postsUrl.list)
125135
await page.waitForURL(postsUrl.list)
126136

127-
await expect(page.locator('.table .row-1 .locked svg')).toBeVisible()
137+
await expect(page.locator('.table .row-2 .locked svg')).toBeVisible()
128138
})
129139

130-
test('should show no lock icon on document row if unlocked', async () => {
140+
test('should not show lock icon on document row if unlocked', async () => {
141+
await page.goto(postsUrl.list)
142+
await page.waitForURL(postsUrl.list)
143+
144+
await expect(page.locator('.table .row-3 .checkbox-input__input')).toBeVisible()
145+
})
146+
147+
test('should not show lock icon on document row if locked by current user', async () => {
148+
await page.goto(postsUrl.edit(anotherPostDoc.id))
149+
await page.waitForURL(postsUrl.edit(anotherPostDoc.id))
150+
151+
const textInput = page.locator('#field-text')
152+
await textInput.fill('testing')
153+
154+
await page.reload()
155+
131156
await page.goto(postsUrl.list)
132157
await page.waitForURL(postsUrl.list)
133158

134-
await expect(page.locator('.table .row-2 .checkbox-input__input')).toBeVisible()
159+
await expect(page.locator('.table .row-1 .checkbox-input__input')).toBeVisible()
135160
})
136161

137162
test('should only allow bulk delete on unlocked documents', async () => {
138163
await page.goto(postsUrl.list)
139164
await page.locator('input#select-all').check()
140165
await page.locator('.delete-documents__toggle').click()
141166
await expect(page.locator('.delete-documents__content p')).toHaveText(
142-
'You are about to delete 1 Posts',
167+
'You are about to delete 2 Posts',
143168
)
144169
})
145170
})
@@ -744,6 +769,7 @@ describe('locked documents', () => {
744769

745770
describe('dashboard - globals', () => {
746771
let user2
772+
let lockedGlobal
747773

748774
beforeAll(async () => {
749775
user2 = await payload.create({
@@ -753,17 +779,8 @@ describe('locked documents', () => {
753779
password: '1234',
754780
},
755781
})
756-
})
757-
758-
afterAll(async () => {
759-
await payload.delete({
760-
collection: 'users',
761-
id: user2.id,
762-
})
763-
})
764782

765-
test('should show lock on document card in dashboard view if locked', async () => {
766-
const lockedGlobal = await payload.create({
783+
lockedGlobal = await payload.create({
767784
collection: lockedDocumentCollection,
768785
data: {
769786
document: undefined,
@@ -775,23 +792,48 @@ describe('locked documents', () => {
775792
},
776793
},
777794
})
795+
})
778796

779-
// eslint-disable-next-line payload/no-wait-function
780-
await wait(500)
797+
afterAll(async () => {
798+
await payload.delete({
799+
collection: 'users',
800+
id: user2.id,
801+
})
802+
})
781803

804+
test('should show lock on document card in dashboard view if locked', async () => {
782805
await page.goto(postsUrl.admin)
783806
await page.waitForURL(postsUrl.admin)
784807

785808
const globalCardList = page.locator('.dashboard__group').nth(1)
786809
await expect(globalCardList.locator('#card-menu .locked svg')).toBeVisible()
810+
})
787811

812+
test('should not show lock on document card in dashboard view if unlocked', async () => {
788813
await payload.delete({
789814
collection: lockedDocumentCollection,
790815
id: lockedGlobal.id,
791816
})
817+
818+
// eslint-disable-next-line payload/no-wait-function
819+
await wait(500)
820+
821+
await page.goto(postsUrl.admin)
822+
await page.waitForURL(postsUrl.admin)
823+
824+
const globalCardList = page.locator('.dashboard__group').nth(1)
825+
await expect(globalCardList.locator('#card-menu .locked')).toBeHidden()
792826
})
793827

794-
test('should show no lock on document card in dashboard view if unlocked', async () => {
828+
test('should not show lock on document card in dashboard view if locked by current user', async () => {
829+
await page.goto(postsUrl.edit('menu'))
830+
await page.waitForURL(postsUrl.edit('menu'))
831+
832+
const textInput = page.locator('#field-text')
833+
await textInput.fill('this is a global menu text field')
834+
835+
await page.reload()
836+
795837
await page.goto(postsUrl.admin)
796838
await page.waitForURL(postsUrl.admin)
797839

0 commit comments

Comments
 (0)