fix: RichText link custom fields (#2756)
Co-authored-by: Dan Ribbens <dan.ribbens@gmail.com>
This commit is contained in:
@@ -8,10 +8,8 @@ import LinkIcon from '../../../../../../icons/Link';
|
||||
import reduceFieldsToValues from '../../../../../Form/reduceFieldsToValues';
|
||||
import { useConfig } from '../../../../../../utilities/Config';
|
||||
import isElementActive from '../../isActive';
|
||||
import { unwrapLink } from '../utilities';
|
||||
import { getBaseFields } from '../LinkDrawer/baseFields';
|
||||
import { transformExtraFields, unwrapLink } from '../utilities';
|
||||
import { LinkDrawer } from '../LinkDrawer';
|
||||
import { Field } from '../../../../../../../../fields/config/types';
|
||||
import { Props as RichTextFieldProps } from '../../../types';
|
||||
import buildStateFromSchema from '../../../../../Form/buildStateFromSchema';
|
||||
import { useAuth } from '../../../../../../utilities/Auth';
|
||||
@@ -19,6 +17,9 @@ import { Fields } from '../../../../../Form/types';
|
||||
import { useLocale } from '../../../../../../utilities/Locale';
|
||||
import { useDrawerSlug } from '../../../../../../elements/Drawer/useDrawerSlug';
|
||||
|
||||
/**
|
||||
* This function is called when an new link is created - not when an existing link is edited.
|
||||
*/
|
||||
const insertLink = (editor, fields) => {
|
||||
const isCollapsed = editor.selection && Range.isCollapsed(editor.selection);
|
||||
const data = reduceFieldsToValues(fields, true);
|
||||
@@ -29,7 +30,7 @@ const insertLink = (editor, fields) => {
|
||||
url: data.url,
|
||||
doc: data.doc,
|
||||
newTab: data.newTab,
|
||||
fields: data.fields,
|
||||
fields: data.fields, // Any custom user-added fields are part of data.fields
|
||||
children: [],
|
||||
};
|
||||
|
||||
@@ -68,25 +69,7 @@ export const LinkButton: React.FC<{
|
||||
const config = useConfig();
|
||||
|
||||
const [fieldSchema] = useState(() => {
|
||||
const baseFields: Field[] = getBaseFields(config);
|
||||
|
||||
const fields = typeof customFieldSchema === 'function' ? customFieldSchema({ defaultFields: baseFields, config, i18n }) : baseFields;
|
||||
|
||||
if (Array.isArray(customFieldSchema)) {
|
||||
fields.push({
|
||||
name: 'fields',
|
||||
type: 'group',
|
||||
admin: {
|
||||
style: {
|
||||
margin: 0,
|
||||
padding: 0,
|
||||
borderTop: 0,
|
||||
borderBottom: 0,
|
||||
},
|
||||
},
|
||||
fields: customFieldSchema,
|
||||
});
|
||||
}
|
||||
const fields = transformExtraFields(customFieldSchema, config, i18n);
|
||||
|
||||
return fields;
|
||||
});
|
||||
|
||||
@@ -3,7 +3,7 @@ import { ReactEditor, useSlate } from 'slate-react';
|
||||
import { Transforms, Node, Editor } from 'slate';
|
||||
import { useModal } from '@faceless-ui/modal';
|
||||
import { Trans, useTranslation } from 'react-i18next';
|
||||
import { unwrapLink } from '../utilities';
|
||||
import { transformExtraFields, unwrapLink } from '../utilities';
|
||||
import Popup from '../../../../../../elements/Popup';
|
||||
import { LinkDrawer } from '../LinkDrawer';
|
||||
import { Fields } from '../../../../../Form/types';
|
||||
@@ -11,8 +11,6 @@ import buildStateFromSchema from '../../../../../Form/buildStateFromSchema';
|
||||
import { useAuth } from '../../../../../../utilities/Auth';
|
||||
import { useLocale } from '../../../../../../utilities/Locale';
|
||||
import { useConfig } from '../../../../../../utilities/Config';
|
||||
import { getBaseFields } from '../LinkDrawer/baseFields';
|
||||
import { Field } from '../../../../../../../../fields/config/types';
|
||||
import reduceFieldsToValues from '../../../../../Form/reduceFieldsToValues';
|
||||
import deepCopyObject from '../../../../../../../../utilities/deepCopyObject';
|
||||
import Button from '../../../../../../elements/Button';
|
||||
@@ -23,6 +21,10 @@ import { useDrawerSlug } from '../../../../../../elements/Drawer/useDrawerSlug';
|
||||
|
||||
const baseClass = 'rich-text-link';
|
||||
|
||||
/**
|
||||
* This function is called when an existing link is edited.
|
||||
* When a link is first created, another function is called: {@link ../Button/index.tsx#insertLink}
|
||||
*/
|
||||
const insertChange = (editor, fields, customFieldSchema) => {
|
||||
const data = reduceFieldsToValues(fields, true);
|
||||
|
||||
@@ -79,25 +81,8 @@ export const LinkElement: React.FC<{
|
||||
const [renderPopup, setRenderPopup] = useState(false);
|
||||
const [initialState, setInitialState] = useState<Fields>({});
|
||||
const [fieldSchema] = useState(() => {
|
||||
const baseFields: Field[] = getBaseFields(config);
|
||||
const fields = transformExtraFields(customFieldSchema, config, i18n);
|
||||
|
||||
const fields = typeof customFieldSchema === 'function' ? customFieldSchema({ defaultFields: baseFields, config, i18n }) : baseFields;
|
||||
|
||||
if (Array.isArray(customFieldSchema)) {
|
||||
fields.push({
|
||||
name: 'fields',
|
||||
type: 'group',
|
||||
admin: {
|
||||
style: {
|
||||
margin: 0,
|
||||
padding: 0,
|
||||
borderTop: 0,
|
||||
borderBottom: 0,
|
||||
},
|
||||
},
|
||||
fields: customFieldSchema,
|
||||
});
|
||||
}
|
||||
|
||||
return fields;
|
||||
});
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
import { Editor, Transforms, Range, Element } from 'slate';
|
||||
import type { i18n } from 'i18next';
|
||||
import type { SanitizedConfig } from 'payload/config';
|
||||
import { getBaseFields } from './LinkDrawer/baseFields';
|
||||
import { Field } from '../../../../../../../fields/config/types';
|
||||
|
||||
export const unwrapLink = (editor: Editor): void => {
|
||||
Transforms.unwrapNodes(editor, { match: (n) => Element.isElement(n) && n.type === 'link' });
|
||||
@@ -37,3 +41,48 @@ export const withLinks = (incomingEditor: Editor): Editor => {
|
||||
|
||||
return editor;
|
||||
};
|
||||
|
||||
/**
|
||||
* This function is run to enrich the basefields which every link has with potential, custom user-added fields.
|
||||
*/
|
||||
export function transformExtraFields(customFieldSchema: Field[] | ((args: {
|
||||
defaultFields: Field[];
|
||||
config: SanitizedConfig;
|
||||
i18n: i18n;
|
||||
}) => Field[]), config: SanitizedConfig, i18n: i18n): Field[] {
|
||||
const baseFields: Field[] = getBaseFields(config);
|
||||
|
||||
const fields = typeof customFieldSchema === 'function' ? customFieldSchema({ defaultFields: baseFields, config, i18n }) : baseFields;
|
||||
|
||||
// Wrap fields which are not part of the base schema in a group named 'fields' - otherwise they will be rendered but not saved
|
||||
const extraFields = [];
|
||||
fields.forEach((field) => {
|
||||
if ('name' in field) {
|
||||
if (!baseFields.find((baseField) => !('name' in baseField) || baseField.name === field.name)) {
|
||||
if (field.name !== 'fields' && field.type !== 'group') {
|
||||
extraFields.push(field);
|
||||
// Remove from fields from now, as they need to be part of the fields group below
|
||||
fields.splice(fields.indexOf(field), 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
if (Array.isArray(customFieldSchema) || fields.length > 0) {
|
||||
fields.push({
|
||||
name: 'fields',
|
||||
type: 'group',
|
||||
admin: {
|
||||
style: {
|
||||
margin: 0,
|
||||
padding: 0,
|
||||
borderTop: 0,
|
||||
borderBottom: 0,
|
||||
},
|
||||
},
|
||||
fields: Array.isArray(customFieldSchema) ? customFieldSchema.concat(extraFields) : extraFields,
|
||||
});
|
||||
}
|
||||
return fields;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user