Skip to content

Commit 67c2c47

Browse files
jefferytopaulpopus
andauthored
feat: hide slug field buttons when field is read-only (#14824)
The Generate and Lock/Unlock buttons serve no purpose when the field is read-only. --------- Co-authored-by: Paul Popus <paul@payloadcms.com>
1 parent 359dc94 commit 67c2c47

4 files changed

Lines changed: 421 additions & 109 deletions

File tree

packages/ui/src/fields/Slug/index.tsx

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,9 @@ import './index.scss'
1717
/**
1818
* @experimental This component is experimental and may change or be removed in the future. Use at your own risk.
1919
*/
20-
export const SlugField: React.FC<SlugFieldClientProps> = ({
21-
field,
22-
path,
23-
readOnly: readOnlyFromProps,
24-
useAsSlug,
25-
}) => {
26-
const { label } = field
20+
export const SlugField: React.FC<SlugFieldClientProps> = ({ field, path, useAsSlug }) => {
21+
const { admin, label } = field
22+
const { readOnly: readOnlyFromProps } = admin || {}
2723

2824
const { t } = useTranslation()
2925

@@ -79,14 +75,16 @@ export const SlugField: React.FC<SlugFieldClientProps> = ({
7975
<div className="field-type slug-field-component">
8076
<div className="label-wrapper">
8177
<FieldLabel htmlFor={`field-${path}`} label={label} />
82-
{!isLocked && (
78+
{!readOnlyFromProps && !isLocked && (
8379
<Button buttonStyle="none" className="lock-button" onClick={handleGenerate}>
8480
{t('authentication:generate')}
8581
</Button>
8682
)}
87-
<Button buttonStyle="none" className="lock-button" onClick={toggleLock}>
88-
{isLocked ? t('general:unlock') : t('general:lock')}
89-
</Button>
83+
{!readOnlyFromProps && (
84+
<Button buttonStyle="none" className="lock-button" onClick={toggleLock}>
85+
{isLocked ? t('general:unlock') : t('general:lock')}
86+
</Button>
87+
)}
9088
</div>
9189
<TextInput
9290
onChange={setValue}

test/fields/collections/SlugField/e2e.spec.ts

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ import {
1616
saveDocAndAssert,
1717
} from '../../../__helpers/e2e/helpers.js'
1818
import { AdminUrlUtil } from '../../../__helpers/shared/adminUrlUtil.js'
19-
import { initPayloadE2ENoConfig } from '../../../__helpers/shared/initPayloadE2ENoConfig.js'
2019
import { reInitializeDB } from '../../../__helpers/shared/clearAndSeed/reInitializeDB.js'
20+
import { initPayloadE2ENoConfig } from '../../../__helpers/shared/initPayloadE2ENoConfig.js'
2121
import { RESTClient } from '../../../__helpers/shared/rest.js'
2222
import { TEST_TIMEOUT_LONG } from '../../../playwright.config.js'
2323
import { slugFieldsSlug } from '../../slugs.js'
@@ -162,6 +162,30 @@ describe('SlugField', () => {
162162
})
163163
})
164164

165+
describe('read-only slug field', () => {
166+
test('should hide lock and generate buttons when slug field is read-only', async () => {
167+
await page.goto(url.create)
168+
await page.locator('#field-title').waitFor()
169+
170+
const readOnlySlugField = page
171+
.locator('.slug-field-component')
172+
.filter({ has: page.locator('#field-readOnlySlug') })
173+
174+
await expect(readOnlySlugField.locator('.lock-button')).toHaveCount(0)
175+
})
176+
177+
test('should show lock button for non-read-only slug fields', async () => {
178+
await page.goto(url.create)
179+
await page.locator('#field-title').waitFor()
180+
181+
const regularSlugField = page
182+
.locator('.slug-field-component')
183+
.filter({ has: page.locator('#field-slug') })
184+
185+
await expect(regularSlugField.locator('.lock-button')).toBeVisible()
186+
})
187+
})
188+
165189
describe('A11y', () => {
166190
test('Edit view should have no accessibility violations', async ({}, testInfo) => {
167191
await page.goto(url.create)

test/fields/collections/SlugField/index.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { CollectionConfig } from 'payload'
1+
import type { CollectionConfig, TextField } from 'payload'
22

33
import { slugField } from 'payload'
44

@@ -33,6 +33,24 @@ const SlugField: CollectionConfig = {
3333
required: false,
3434
checkboxName: 'generateLocalizedSlug',
3535
}),
36+
slugField({
37+
name: 'readOnlySlug',
38+
checkboxName: 'generateReadOnlySlug',
39+
required: false,
40+
overrides: (defaultField) => {
41+
console.log({ field: defaultField.fields[1] })
42+
defaultField.fields[1].admin.readOnly = true
43+
44+
return defaultField
45+
},
46+
}),
47+
{
48+
type: 'text',
49+
name: 'test',
50+
admin: {
51+
readOnly: true,
52+
},
53+
},
3654
],
3755
}
3856

0 commit comments

Comments
 (0)