fix(ui): refreshes column state during hmr and respects admin.disableListColumn despite preferences (#9846)

Partial fix for #9774. When `admin.disableListColumn` is set
retroactively, it continues to appear in column state, but shouldn't.
This was because the table column context was not refreshing after HMR
runs, and would instead hold onto these stale columns until the page
itself refreshes. Similarly, this was also a problem when the user had
saved any of these columns to their list preferences, where those prefs
would take precedence despite these properties being set on the
underlying fields. The fix is to filter these columns from all requests
that send them, and ensure local component state properly refreshes
itself.
This commit is contained in:
Jacob Fletcher
2024-12-10 15:11:44 -05:00
committed by GitHub
parent 563694d930
commit f7172b5b2c
19 changed files with 194 additions and 120 deletions

View File

@@ -1,7 +1,6 @@
import type { Page } from '@playwright/test'
import { expect } from '@playwright/test'
import { wait } from 'payload/shared'
import { exactText } from '../../helpers.js'

View File

@@ -0,0 +1,59 @@
import type { PayloadTestSDK } from 'helpers/sdk/index.js'
import type { GeneratedTypes } from 'helpers/sdk/types.js'
import type { TypedUser } from 'payload'
export const upsertPrefs = async <
TConfig extends GeneratedTypes<any>,
TGeneratedTypes extends GeneratedTypes<any>,
>({
payload,
user,
value,
}: {
payload: PayloadTestSDK<TConfig>
user: TypedUser
value: Record<string, any>
}): Promise<TGeneratedTypes['collections']['payload-preferences']> => {
let prefs = await payload
.find({
collection: 'payload-preferences',
depth: 0,
limit: 1,
where: {
and: [
{ key: { equals: 'text-fields-list' } },
{ 'user.value': { equals: user.id } },
{ 'user.relationTo': { equals: user.collection } },
],
},
})
?.then((res) => res.docs?.[0])
if (!prefs) {
prefs = await payload.create({
collection: 'payload-preferences',
depth: 0,
data: {
key: 'text-fields-list',
user: {
relationTo: user.collection,
value: user.id,
},
value,
},
})
} else {
prefs = await payload.update({
collection: 'payload-preferences',
id: prefs.id,
data: {
value: {
...(prefs?.value ?? {}),
...value,
},
},
})
}
return prefs
}

View File

@@ -1,7 +1,5 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import type { Where } from 'payload'
import type { Config } from 'payload'
import type { PaginatedDocs } from 'payload'
import type { Config, PaginatedDocs, TypedUser, Where } from 'payload'
import * as qs from 'qs-esm'
@@ -120,6 +118,8 @@ export class RESTClient {
serverURL: string
public user: TypedUser
constructor(config: Config, args: Args) {
this.config = config
this.serverURL = args.serverURL
@@ -254,7 +254,9 @@ export class RESTClient {
const response = await fetch(`${this.serverURL}/api/${slug}${whereQuery}`, options)
const { status } = response
const result = await response.json()
if (result.errors) throw new Error(result.errors[0].message)
if (result.errors) {
throw new Error(result.errors[0].message)
}
return { result, status }
}
@@ -310,7 +312,9 @@ export class RESTClient {
method: 'POST',
})
let { token } = await response.json()
const { user } = await response.json()
let token = user.token
// If the token is not in the response body, then we can extract it from the cookies
if (!token) {
@@ -319,6 +323,7 @@ export class RESTClient {
token = tokenMatchResult?.groups?.token
}
this.user = user
this.token = token
return token

View File

@@ -7,6 +7,7 @@ export const handler: PayloadHandler = async (req) => {
await addDataAndFileToRequest(req)
const { data, payload, user } = req
const operation = data?.operation ? String(data.operation) : undefined
if (data?.operation && typeof payload[operation] === 'function') {