feat: adds experimental.allLocaleStatus flag to add new group status field

This commit is contained in:
Jessica Chowdhury
2025-08-19 13:26:43 +01:00
parent 8996a3177e
commit 7425b04040
12 changed files with 147 additions and 10 deletions

View File

@@ -9,6 +9,7 @@ import type {
import { authCollectionEndpoints } from '../../auth/endpoints/index.js'
import { getBaseAuthFields } from '../../auth/getAuthFields.js'
import { TimestampsRequired } from '../../errors/TimestampsRequired.js'
import { baseAllLocaleStatusField } from '../../fields/baseFields/baseAllLocaleStatusField.js'
import { sanitizeFields } from '../../fields/config/sanitize.js'
import { fieldAffectsData } from '../../fields/config/types.js'
import { mergeBaseFields } from '../../fields/mergeBaseFields.js'
@@ -256,6 +257,10 @@ export const sanitizeCollection = async (
sanitized.fields = mergeBaseFields(sanitized.fields, getBaseAuthFields(sanitized.auth))
}
if (config.experimental?.allLocaleStatus) {
sanitized.fields = mergeBaseFields(sanitized.fields, baseAllLocaleStatusField)
}
if (collection?.admin?.pagination?.limits?.length) {
sanitized.admin!.pagination!.limits = collection.admin.pagination.limits
}

View File

@@ -158,6 +158,21 @@ export const createClientConfig = ({
break
case 'experiental':
if (config.experimental) {
if (!clientConfig.experimental) {
clientConfig.experimental = {}
}
if (config.experimental?.localizeStatus) {
clientConfig.experimental.localizeStatus = config.experimental.localizeStatus
}
if (config.experimental?.allLocaleStatus) {
clientConfig.experimental.allLocaleStatus = config.experimental.allLocaleStatus
}
}
break
case 'folders':
if (config.folders) {
clientConfig.folders = {
@@ -193,13 +208,6 @@ export const createClientConfig = ({
config.localization.defaultLocalePublishOption
}
if (config.experimental?.localizeStatus) {
if (!clientConfig.experimental) {
clientConfig.experimental = {}
}
clientConfig.experimental.localizeStatus = config.experimental.localizeStatus
}
if (config.localization.fallback) {
clientConfig.localization.fallback = config.localization.fallback
}

View File

@@ -725,6 +725,15 @@ export type ImportMapGenerators = Array<
* These may be unstable and may change or be removed in future releases.
*/
export type ExperimentalConfig = {
/**
* Adds `_allLocaleStatus` group field which maintains the statuses of all locales.
* @default false
*/
allLocaleStatus?: boolean
/**
* Returns status of the current locale instead of overall document.
* @default false
*/
localizeStatus?: boolean
}

View File

@@ -0,0 +1,38 @@
import type { Field } from '../config/types.js'
export const baseAllLocaleStatusField: Field[] = [
{
name: '_allLocaleStatus',
type: 'json',
admin: {
components: {
Cell: '@payloadcms/ui/rsc#AllLocaleStatusCell',
},
hidden: true,
},
hooks: {
afterRead: [
async (args) => {
const { collection, data, req } = args
const id = data?.id
if (id && collection && collection.versions) {
const version = await req.payload.findVersions({
collection: collection.slug,
limit: 1,
where: {
parent: {
equals: id,
},
},
})
if (version.docs && version.docs[0]?.localeStatus) {
return version.docs[0].localeStatus
}
}
},
],
},
label: 'Status - All Locales',
},
]

View File

@@ -63,7 +63,7 @@ export const buildVersionCollectionFields = <T extends boolean = false>(
}),
})
if (config.experimental?.localizeStatus) {
if (config.experimental?.localizeStatus || config.experimental?.allLocaleStatus) {
const localeStatusFields = buildLocaleStatusField(config)
fields.push({

View File

@@ -57,7 +57,7 @@ export const buildVersionGlobalFields = <T extends boolean = false>(
}),
})
if (config.experimental.localizeStatus) {
if (config.experimental.localizeStatus || config.experimental?.allLocaleStatus) {
const localeStatusFields = buildLocaleStatusField(config)
fields.push({

View File

@@ -137,7 +137,8 @@ export const saveVersion = async ({
if (
localizationEnabled &&
payload.config.localization !== false &&
payload.config.experimental?.localizeStatus
(payload.config.experimental?.localizeStatus ||
payload.config.experimental?.allLocaleStatus)
) {
const allLocales = (
(payload.config.localization && payload.config.localization?.locales) ||

View File

@@ -0,0 +1,35 @@
'use client'
import type { Data } from 'payload'
import React from 'react'
import { Pill } from '../../Pill/index.js'
import './index.scss'
type Props = {
readonly availableLocales: string[]
readonly data: Data
}
const baseClass = 'locale-status-cell'
export const AllLocaleStatusCellClient = ({ availableLocales, data }: Props) => {
const localesToRender = Object.fromEntries(
Object.entries(data).filter(([key]) => availableLocales.includes(key))
)
if (Object.keys(localesToRender).length === 0) {
return null
}
return (
<div className={baseClass}>
{Object.entries(localesToRender).map(([locale, status]) => (
<Pill key={locale} pillStyle={status === 'published' ? 'success' : 'light-gray'} size="small">
{locale}
</Pill>
))}
</div>
)
}

View File

@@ -0,0 +1,10 @@
@import '../../../scss/styles.scss';
@layer payload-default {
.locale-status-cell {
display: flex;
align-items: center;
gap: calc(var(--base) / 2);
flex-wrap: wrap;
}
}

View File

@@ -0,0 +1,29 @@
import { createLocalReq, type DefaultServerCellComponentProps } from 'payload'
import React from 'react'
import { AllLocaleStatusCellClient } from './index.client.js'
export const AllLocaleStatusCell = async ({ cellData, payload }: DefaultServerCellComponentProps) => {
const { localization } = payload.config
const req = await createLocalReq({}, payload)
let availableLocales: string[] = []
if (localization) {
const filtered =
(await localization.filterAvailableLocales?.({
locales: localization.locales,
req,
})) ?? localization.locales
availableLocales = filtered.map((locale) => locale.code)
}
return (
<AllLocaleStatusCellClient
availableLocales={availableLocales}
data={cellData}
/>
)
}

View File

@@ -3,6 +3,7 @@ export { FieldDiffLabel } from '../../elements/FieldDiffLabel/index.js'
export { FolderTableCell } from '../../elements/FolderView/Cell/index.server.js'
export { FolderField } from '../../elements/FolderView/FolderField/index.server.js'
export { getHTMLDiffComponents } from '../../elements/HTMLDiff/index.js'
export { AllLocaleStatusCell } from '../../elements/Status/AllLocaleStatusCell/index.server.js'
export { File } from '../../graphics/File/index.js'
export { CheckIcon } from '../../icons/Check/index.js'
export { copyDataFromLocaleHandler } from '../../utilities/copyDataFromLocale.js'

View File

@@ -430,6 +430,7 @@ export default buildConfigWithDefaults({
],
experimental: {
localizeStatus: true,
allLocaleStatus: true,
},
localization: {
filterAvailableLocales: ({ locales }) => {