Merge branch 'master' of github.com:payloadcms/payload

This commit is contained in:
James
2021-11-26 17:10:20 -05:00
31 changed files with 410 additions and 88 deletions

View File

@@ -1,5 +1,5 @@
import React from 'react';
import useFieldType from '../../useFieldType';
import useField from '../../useField';
import Pill from '../../../elements/Pill';
import { Props } from './types';
@@ -10,7 +10,7 @@ const baseClass = 'section-title';
const SectionTitle: React.FC<Props> = (props) => {
const { label, path, readOnly } = props;
const { value, setValue } = useFieldType({ path });
const { value, setValue } = useField({ path });
const classes = [
baseClass,

View File

@@ -7,7 +7,7 @@ import DraggableSection from '../../DraggableSection';
import reducer from '../rowReducer';
import { useForm } from '../../Form/context';
import buildStateFromSchema from '../../Form/buildStateFromSchema';
import useFieldType from '../../useFieldType';
import useField from '../../useField';
import Error from '../../Error';
import { array } from '../../../../../fields/validations';
import Banner from '../../../elements/Banner';
@@ -66,7 +66,7 @@ const ArrayFieldType: React.FC<Props> = (props) => {
errorMessage,
value,
setValue,
} = useFieldType({
} = useField({
path,
validate: memoizedValidate,
disableFormData,

View File

@@ -12,7 +12,7 @@ import { useForm } from '../../Form/context';
import buildStateFromSchema from '../../Form/buildStateFromSchema';
import DraggableSection from '../../DraggableSection';
import Error from '../../Error';
import useFieldType from '../../useFieldType';
import useField from '../../useField';
import Popup from '../../../elements/Popup';
import BlockSelector from './BlockSelector';
import { blocks as blocksValidator } from '../../../../../fields/validations';
@@ -76,7 +76,7 @@ const Blocks: React.FC<Props> = (props) => {
errorMessage,
value,
setValue,
} = useFieldType({
} = useField({
path,
validate: memoizedValidate,
disableFormData,
@@ -110,7 +110,7 @@ const Blocks: React.FC<Props> = (props) => {
if (preferencesKey) {
const preferences: DocumentPreferences = await getPreference(preferencesKey);
const preferencesToSet = preferences || { fields: { } };
const preferencesToSet = preferences || { fields: {} };
let newCollapsedState = preferencesToSet?.fields?.[path]?.collapsed
.filter((filterID) => (rows.find((row) => row.id === filterID)))
|| [];

View File

@@ -1,5 +1,5 @@
import React, { useCallback } from 'react';
import useFieldType from '../../useFieldType';
import useField from '../../useField';
import withCondition from '../../withCondition';
import Error from '../../Error';
import { checkbox } from '../../../../../fields/validations';
@@ -41,7 +41,7 @@ const Checkbox: React.FC<Props> = (props) => {
showError,
errorMessage,
setValue,
} = useFieldType({
} = useField({
path,
validate: memoizedValidate,
disableFormData,

View File

@@ -3,7 +3,7 @@ import Editor from 'react-simple-code-editor';
import { highlight, languages } from 'prismjs/components/prism-core';
import 'prismjs/components/prism-clike';
import 'prismjs/components/prism-javascript';
import useFieldType from '../../useFieldType';
import useField from '../../useField';
import withCondition from '../../withCondition';
import Label from '../../Label';
import Error from '../../Error';
@@ -52,7 +52,7 @@ const Code: React.FC<Props> = (props) => {
showError,
setValue,
errorMessage,
} = useFieldType({
} = useField({
path,
validate: memoizedValidate,
enableDebouncedValue: true,

View File

@@ -1,5 +1,5 @@
import React, { useCallback } from 'react';
import useFieldType from '../../useFieldType';
import useField from '../../useField';
import Label from '../../Label';
import Error from '../../Error';
import { useWatchForm } from '../../Form/context';
@@ -23,7 +23,7 @@ const ConfirmPassword: React.FC = () => {
showError,
setValue,
errorMessage,
} = useFieldType({
} = useField({
path: 'confirm-password',
disableFormData: true,
validate,

View File

@@ -2,7 +2,7 @@ import React, { useCallback } from 'react';
import DatePicker from '../../../elements/DatePicker';
import withCondition from '../../withCondition';
import useFieldType from '../../useFieldType';
import useField from '../../useField';
import Label from '../../Label';
import Error from '../../Error';
import FieldDescription from '../../FieldDescription';
@@ -43,7 +43,7 @@ const DateTime: React.FC<Props> = (props) => {
showError,
errorMessage,
setValue,
} = useFieldType({
} = useField({
path,
validate: memoizedValidate,
condition,

View File

@@ -1,6 +1,6 @@
import React, { useCallback } from 'react';
import withCondition from '../../withCondition';
import useFieldType from '../../useFieldType';
import useField from '../../useField';
import Label from '../../Label';
import Error from '../../Error';
import FieldDescription from '../../FieldDescription';
@@ -34,7 +34,7 @@ const Email: React.FC<Props> = (props) => {
return validationResult;
}, [validate, required]);
const fieldType = useFieldType({
const fieldType = useField({
path,
validate: memoizedValidate,
enableDebouncedValue: true,

View File

@@ -1,5 +1,5 @@
import React, { useEffect } from 'react';
import useFieldType from '../../useFieldType';
import useField from '../../useField';
import withCondition from '../../withCondition';
import { Props } from './types';
@@ -13,7 +13,7 @@ const HiddenInput: React.FC<Props> = (props) => {
const path = pathFromProps || name;
const { value, setValue } = useFieldType({
const { value, setValue } = useField({
path,
});

View File

@@ -1,5 +1,5 @@
import React, { useCallback } from 'react';
import useFieldType from '../../useFieldType';
import useField from '../../useField';
import Label from '../../Label';
import Error from '../../Error';
import FieldDescription from '../../FieldDescription';
@@ -41,7 +41,7 @@ const NumberField: React.FC<Props> = (props) => {
showError,
setValue,
errorMessage,
} = useFieldType({
} = useField({
path,
validate: memoizedValidate,
enableDebouncedValue: true,

View File

@@ -1,5 +1,5 @@
import React, { useCallback } from 'react';
import useFieldType from '../../useFieldType';
import useField from '../../useField';
import Label from '../../Label';
import Error from '../../Error';
import withCondition from '../../withCondition';
@@ -33,7 +33,7 @@ const Password: React.FC<Props> = (props) => {
formProcessing,
setValue,
errorMessage,
} = useFieldType({
} = useField({
path,
validate: memoizedValidate,
enableDebouncedValue: true,

View File

@@ -1,5 +1,5 @@
import React, { useCallback } from 'react';
import useFieldType from '../../useFieldType';
import useField from '../../useField';
import Label from '../../Label';
import Error from '../../Error';
import FieldDescription from '../../FieldDescription';
@@ -41,7 +41,7 @@ const PointField: React.FC<Props> = (props) => {
showError,
setValue,
errorMessage,
} = useFieldType<[number, number]>({
} = useField<[number, number]>({
path,
validate: memoizedValidate,
enableDebouncedValue: true,

View File

@@ -1,6 +1,6 @@
import React, { useCallback } from 'react';
import useFieldType from '../../useFieldType';
import useField from '../../useField';
import withCondition from '../../withCondition';
import Error from '../../Error';
import Label from '../../Label';
@@ -44,7 +44,7 @@ const RadioGroup: React.FC<Props> = (props) => {
showError,
errorMessage,
setValue,
} = useFieldType({
} = useField({
path,
validate: memoizedValidate,
condition,

View File

@@ -5,7 +5,7 @@ import { useConfig } from '@payloadcms/config-provider';
import withCondition from '../../withCondition';
import ReactSelect from '../../../elements/ReactSelect';
import { Value } from '../../../elements/ReactSelect/types';
import useFieldType from '../../useFieldType';
import useField from '../../useField';
import Label from '../../Label';
import Error from '../../Error';
import FieldDescription from '../../FieldDescription';
@@ -70,7 +70,7 @@ const Relationship: React.FC<Props> = (props) => {
showError,
errorMessage,
setValue,
} = useFieldType({
} = useField({
path: path || name,
validate: memoizedValidate,
condition,

View File

@@ -4,7 +4,7 @@ import { createEditor, Transforms, Node, Element as SlateElement, Text, BaseEdit
import { ReactEditor, Editable, withReact, Slate } from 'slate-react';
import { HistoryEditor, withHistory } from 'slate-history';
import { richText } from '../../../../../fields/validations';
import useFieldType from '../../useFieldType';
import useField from '../../useField';
import withCondition from '../../withCondition';
import Label from '../../Label';
import Error from '../../Error';
@@ -29,7 +29,7 @@ const defaultElements: RichTextElement[] = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6',
const defaultLeaves: RichTextLeaf[] = ['bold', 'italic', 'underline', 'strikethrough', 'code'];
const baseClass = 'rich-text';
type CustomText = { text: string; [x: string]: unknown }
type CustomText = { text: string;[x: string]: unknown }
type CustomElement = { type: string; children: CustomText[] }
@@ -115,7 +115,7 @@ const RichText: React.FC<Props> = (props) => {
return validationResult;
}, [validate, required]);
const fieldType = useFieldType({
const fieldType = useField({
path,
validate: memoizedValidate,
stringify: true,
@@ -194,7 +194,7 @@ const RichText: React.FC<Props> = (props) => {
}}
>
<div className={`${baseClass}__wrap`}>
{ !hideGutter && (<FieldTypeGutter />) }
{!hideGutter && (<FieldTypeGutter />)}
<Error
showError={showError}
message={errorMessage}

View File

@@ -1,7 +1,7 @@
import React, { useCallback, useState } from 'react';
import React, { useCallback, useState, useEffect } from 'react';
import withCondition from '../../withCondition';
import ReactSelect from '../../../elements/ReactSelect';
import useFieldType from '../../useFieldType';
import useField from '../../useField';
import Label from '../../Label';
import Error from '../../Error';
import FieldDescription from '../../FieldDescription';
@@ -40,6 +40,8 @@ const Select: React.FC<Props> = (props) => {
description,
condition,
} = {},
value: valueFromProps,
onChange: onChangeFromProps
} = props;
const path = pathFromProps || name;
@@ -52,16 +54,42 @@ const Select: React.FC<Props> = (props) => {
}, [validate, required, options]);
const {
value,
value: valueFromContext,
showError,
setValue,
errorMessage,
} = useFieldType({
} = useField({
path,
validate: memoizedValidate,
condition,
});
const onChange = useCallback((selectedOption) => {
if (!readOnly) {
let newValue;
if (hasMany) {
if (Array.isArray(selectedOption)) {
newValue = selectedOption.map((option) => option.value);
} else {
newValue = [];
}
} else {
newValue = selectedOption.value;
}
if (typeof onChangeFromProps === 'function') {
onChangeFromProps(newValue);
} else {
setValue(newValue);
}
}
}, [
readOnly,
hasMany,
onChangeFromProps,
setValue
])
const classes = [
'field-type',
baseClass,
@@ -71,6 +99,8 @@ const Select: React.FC<Props> = (props) => {
let valueToRender;
const value = valueFromProps || valueFromContext || '';
if (hasMany && Array.isArray(value)) {
valueToRender = value.map((val) => options.find((option) => option.value === val));
} else {
@@ -95,17 +125,7 @@ const Select: React.FC<Props> = (props) => {
required={required}
/>
<ReactSelect
onChange={!readOnly ? (selectedOption) => {
if (hasMany) {
if (Array.isArray(selectedOption)) {
setValue(selectedOption.map((option) => option.value));
} else {
setValue([]);
}
} else {
setValue(selectedOption.value);
}
} : undefined}
onChange={onChange}
value={valueToRender}
showError={showError}
isDisabled={readOnly}

View File

@@ -1,5 +1,5 @@
import React from 'react';
import useFieldType from '../../useFieldType';
import React, { useCallback, useEffect } from 'react';
import useField from '../../useField';
import withCondition from '../../withCondition';
import Label from '../../Label';
import Error from '../../Error';
@@ -24,11 +24,13 @@ const Text: React.FC<Props> = (props) => {
description,
condition,
} = {},
value: valueFromProps,
onChange: onChangeFromProps,
} = props;
const path = pathFromProps || name;
const fieldType = useFieldType<string>({
const fieldType = useField<string>({
path,
validate,
enableDebouncedValue: true,
@@ -36,12 +38,24 @@ const Text: React.FC<Props> = (props) => {
});
const {
value,
value: valueFromContext,
showError,
setValue,
errorMessage,
} = fieldType;
const onChange = useCallback((e) => {
const { value: incomingValue } = e.target;
if (typeof onChangeFromProps === 'function') {
onChangeFromProps(incomingValue);
} else {
setValue(e);
}
}, [
onChangeFromProps,
setValue,
]);
const classes = [
'field-type',
'text',
@@ -49,6 +63,8 @@ const Text: React.FC<Props> = (props) => {
readOnly && 'read-only',
].filter(Boolean).join(' ');
const value = valueFromProps || valueFromContext || '';
return (
<div
className={classes}
@@ -67,8 +83,8 @@ const Text: React.FC<Props> = (props) => {
required={required}
/>
<input
value={value || ''}
onChange={setValue}
value={value}
onChange={onChange}
disabled={readOnly}
placeholder={placeholder}
type="text"

View File

@@ -1,5 +1,5 @@
import React, { useCallback } from 'react';
import useFieldType from '../../useFieldType';
import useField from '../../useField';
import withCondition from '../../withCondition';
import Label from '../../Label';
import Error from '../../Error';
@@ -41,7 +41,7 @@ const Textarea: React.FC<Props> = (props) => {
showError,
setValue,
errorMessage,
} = useFieldType({
} = useField({
path,
validate: memoizedValidate,
enableDebouncedValue: true,

View File

@@ -1,7 +1,7 @@
import React, { useState, useEffect, useCallback } from 'react';
import { useModal } from '@faceless-ui/modal';
import { useConfig } from '@payloadcms/config-provider';
import useFieldType from '../../useFieldType';
import useField from '../../useField';
import withCondition from '../../withCondition';
import Button from '../../../elements/Button';
import Label from '../../Label';
@@ -38,6 +38,8 @@ const Upload: React.FC<Props> = (props) => {
validate = upload,
relationTo,
fieldTypes,
value: valueFromProps,
onChange: onChangeFromProps,
} = props;
const collection = collections.find((coll) => coll.slug === relationTo);
@@ -51,19 +53,21 @@ const Upload: React.FC<Props> = (props) => {
return validationResult;
}, [validate, required]);
const fieldType = useFieldType({
const fieldType = useField({
path,
validate: memoizedValidate,
condition,
});
const {
value,
value: valueFromContext,
showError,
setValue,
errorMessage,
} = fieldType;
const value = valueFromProps || valueFromContext || '';
const classes = [
'field-type',
baseClass,
@@ -81,14 +85,28 @@ const Upload: React.FC<Props> = (props) => {
setInternalValue(json);
} else {
setInternalValue(undefined);
setValue(null);
setMissingFile(true);
}
};
fetchFile();
}
}, [value, setInternalValue, relationTo, api, serverURL, setValue]);
}, [
value,
relationTo,
api,
serverURL,
setValue
]);
useEffect(() => {
const { id: incomingID } = internalValue || {};
if (typeof onChangeFromProps === 'function') {
onChangeFromProps(incomingID)
} else {
setValue(incomingID);
}
}, [internalValue]);
return (
<div
@@ -147,7 +165,6 @@ const Upload: React.FC<Props> = (props) => {
fieldTypes,
setValue: (val) => {
setMissingFile(false);
setValue(val.id);
setInternalValue(val);
},
}}
@@ -157,7 +174,6 @@ const Upload: React.FC<Props> = (props) => {
slug: selectExistingModalSlug,
setValue: (val) => {
setMissingFile(false);
setValue(val.id);
setInternalValue(val);
},
addModalSlug,

View File

@@ -5,7 +5,7 @@ import { useFormProcessing, useFormSubmitted, useFormModified, useForm } from '.
import useDebounce from '../../../hooks/useDebounce';
import { Options, FieldType } from './types';
const useFieldType = <T extends unknown>(options: Options): FieldType<T> => {
const useField = <T extends unknown>(options: Options): FieldType<T> => {
const {
path,
validate,
@@ -22,8 +22,10 @@ const useFieldType = <T extends unknown>(options: Options): FieldType<T> => {
const modified = useFormModified();
const {
dispatchFields, getField, setModified,
} = formContext;
dispatchFields,
getField,
setModified,
} = formContext || {};
const [internalValue, setInternalValue] = useState(undefined);
@@ -64,21 +66,38 @@ const useFieldType = <T extends unknown>(options: Options): FieldType<T> => {
fieldToDispatch.valid = validationResult;
}
dispatchFields(fieldToDispatch);
}, [path, dispatchFields, validate, disableFormData, ignoreWhileFlattening, initialValue, stringify, condition]);
if (typeof dispatchFields === 'function') {
dispatchFields(fieldToDispatch);
}
}, [
path,
dispatchFields,
validate,
disableFormData,
ignoreWhileFlattening,
initialValue,
stringify,
condition
]);
// Method to return from `useFieldType`, used to
// Method to return from `useField`, used to
// update internal field values from field component(s)
// as fast as they arrive. NOTE - this method is NOT debounced
const setValue = useCallback((e, modifyForm = true) => {
const val = (e && e.target) ? e.target.value : e;
if ((!ignoreWhileFlattening && !modified) && modifyForm) {
setModified(true);
if (typeof setModified === 'function') {
setModified(true);
}
}
setInternalValue(val);
}, [setModified, modified, ignoreWhileFlattening]);
}, [
setModified,
modified,
ignoreWhileFlattening
]);
useEffect(() => {
setInternalValue(initialValue);
@@ -94,7 +113,11 @@ const useFieldType = <T extends unknown>(options: Options): FieldType<T> => {
if (field?.value !== valueToSend && valueToSend !== undefined) {
sendField(valueToSend);
}
}, [valueToSend, sendField, field]);
}, [
valueToSend,
sendField,
field
]);
return {
...options,
@@ -107,4 +130,4 @@ const useFieldType = <T extends unknown>(options: Options): FieldType<T> => {
};
};
export default useFieldType;
export default useField;

View File

@@ -1,6 +1,6 @@
import React, { useMemo, useState, useEffect } from 'react';
import { v4 as uuidv4 } from 'uuid';
import useFieldType from '../../../../forms/useFieldType';
import useField from '../../../../forms/useField';
import Label from '../../../../forms/Label';
import CopyToClipboard from '../../../../elements/CopyToClipboard';
import { text } from '../../../../../../fields/validations';
@@ -31,7 +31,7 @@ const APIKey: React.FC = () => {
</div>
), [apiKeyValue]);
const fieldType = useFieldType({
const fieldType = useField({
path: 'apiKey',
validate,
});

View File

@@ -1,7 +1,7 @@
import React, {
useState, useRef, useEffect, useCallback,
} from 'react';
import useFieldType from '../../../../forms/useFieldType';
import useField from '../../../../forms/useField';
import Button from '../../../../elements/Button';
import FileDetails from '../../../../elements/FileDetails';
import Error from '../../../../forms/Error';
@@ -45,7 +45,7 @@ const Upload: React.FC<Props> = (props) => {
setValue,
showError,
errorMessage,
} = useFieldType<{name: string}>({
} = useField<{ name: string }>({
path: 'file',
validate,
});

View File

@@ -99,6 +99,8 @@ export type TextField = FieldBase & {
placeholder?: string
autoComplete?: string
}
value?: string
onChange?: (value: string) => void
}
export type EmailField = FieldBase & {
@@ -167,9 +169,11 @@ export type UIField = {
}
export type UploadField = FieldBase & {
type: 'upload';
relationTo: string;
maxDepth?: number;
type: 'upload'
relationTo: string
maxDepth?: number
value?: string
onChange?: (value: string) => void
}
type CodeAdmin = Admin & {
@@ -184,9 +188,11 @@ export type CodeField = Omit<FieldBase, 'admin'> & {
}
export type SelectField = FieldBase & {
type: 'select';
options: Option[];
hasMany?: boolean;
type: 'select'
options: Option[]
hasMany?: boolean
value?: string
onChange?: (value: string) => void
}
export type RelationshipField = FieldBase & {