feat: default tab labels from name (#3129)

This commit is contained in:
Dan Ribbens
2023-08-05 13:48:56 -04:00
committed by GitHub
parent a776e06111
commit e8f05165eb
4 changed files with 15 additions and 13 deletions

View File

@@ -25,14 +25,14 @@ _Tabs field type used to separate Hero fields from Page Layout_
#### Tab-specific Config #### Tab-specific Config
Each tab has its own required `label` and `fields` array. You can also optionally pass a `description` to render within each individual tab. Each tab must have either a `name` or `label` and the required `fields` array. You can also optionally pass a `description` to render within each individual tab.
| Option | Description | | Option | Description |
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | ---------------- |--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| **`name`** | An optional property name to be used when stored and retrieved from the database. [More](/docs/fields/overview#field-names) | | **`name`** | Groups field data into an object when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
| **`label`** \* | The label to render on the tab itself. | | **`label`** | The label to render on the tab itself. Required when name is undefined, defaults to name converted to words. |
| **`fields`** \* | The fields to render within this tab. | | **`fields`** \* | The fields to render within this tab. |
| **`description`** | Optionally render a description within this tab to describe the contents of the tab itself. | | **`description`** | Optionally render a description within this tab to describe the contents of the tab itself. |
| **`interfaceName`** | Create a top level, reusable [Typescript interface](/docs/typescript/generating-types#custom-field-interfaces) & [GraphQL type](/docs/graphql/graphql-schema#custom-field-schemas). (`name` must be present) | | **`interfaceName`** | Create a top level, reusable [Typescript interface](/docs/typescript/generating-types#custom-field-interfaces) & [GraphQL type](/docs/graphql/graphql-schema#custom-field-schemas). (`name` must be present) |
_\* An asterisk denotes that a property is required._ _\* An asterisk denotes that a property is required._

View File

@@ -1,9 +1,9 @@
import { formatLabels, toWords } from '../../utilities/formatLabels'; import { formatLabels, toWords } from '../../utilities/formatLabels';
import { MissingFieldType, InvalidFieldRelationship, InvalidFieldName } from '../../errors'; import { InvalidFieldName, InvalidFieldRelationship, MissingFieldType } from '../../errors';
import { baseBlockFields } from '../baseFields/baseBlockFields'; import { baseBlockFields } from '../baseFields/baseBlockFields';
import validations from '../validations'; import validations from '../validations';
import { baseIDField } from '../baseFields/baseIDField'; import { baseIDField } from '../baseFields/baseIDField';
import { Field, fieldAffectsData } from './types'; import { Field, fieldAffectsData, tabHasName } from './types';
import withCondition from '../../admin/components/forms/withCondition'; import withCondition from '../../admin/components/forms/withCondition';
const sanitizeFields = (fields: Field[], validRelationships: string[]): Field[] => { const sanitizeFields = (fields: Field[], validRelationships: string[]): Field[] => {
@@ -87,6 +87,9 @@ const sanitizeFields = (fields: Field[], validRelationships: string[]): Field[]
if (field.type === 'tabs') { if (field.type === 'tabs') {
field.tabs = field.tabs.map((tab) => { field.tabs = field.tabs.map((tab) => {
const unsanitizedTab = { ...tab }; const unsanitizedTab = { ...tab };
if (tabHasName(tab) && typeof tab.label === 'undefined') {
unsanitizedTab.label = toWords(tab.name);
}
unsanitizedTab.fields = sanitizeFields(tab.fields, validRelationships); unsanitizedTab.fields = sanitizeFields(tab.fields, validRelationships);
return unsanitizedTab; return unsanitizedTab;
}); });

View File

@@ -224,13 +224,14 @@ export const collapsible = baseField.keys({
}); });
const tab = baseField.keys({ const tab = baseField.keys({
name: joi.string().when('localized', { is: joi.exist(), then: joi.required() }), name: joi.string()
.when('localized', { is: joi.exist(), then: joi.required() }),
localized: joi.boolean(), localized: joi.boolean(),
interfaceName: joi.string().when('name', { not: joi.exist(), then: joi.forbidden() }), interfaceName: joi.string().when('name', { not: joi.exist(), then: joi.forbidden() }),
label: joi.alternatives().try( label: joi.alternatives().try(
joi.string(), joi.string(),
joi.object().pattern(joi.string(), [joi.string()]), joi.object().pattern(joi.string(), [joi.string()]),
).required(), ).when('name', { is: joi.not(), then: joi.required() }),
fields: joi.array().items(joi.link('#field')).required(), fields: joi.array().items(joi.link('#field')).required(),
description: joi.alternatives().try( description: joi.alternatives().try(
joi.string(), joi.string(),

View File

@@ -135,7 +135,6 @@ const TabsFields: CollectionConfig = {
}, },
{ {
name: 'namedTabWithDefaultValue', name: 'namedTabWithDefaultValue',
label: 'Tab with Default Value',
description: 'This tab has a name, which should namespace the contained fields.', description: 'This tab has a name, which should namespace the contained fields.',
fields: [ fields: [
{ {
@@ -159,7 +158,6 @@ const TabsFields: CollectionConfig = {
}, },
{ {
name: 'accessControlTab', name: 'accessControlTab',
label: 'Access Control Tab',
access: { access: {
read: () => false, read: () => false,
}, },