chore: merge master
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
## [0.13.13-beta.0](https://github.com/payloadcms/payload/compare/v0.13.6...v0.13.13-beta.0) (2021-12-28)
|
||||
## [0.13.20-beta.0](https://github.com/payloadcms/payload/compare/v0.13.6...v0.13.20-beta.0) (2021-12-29)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
@@ -6,9 +6,15 @@
|
||||
* [#370](https://github.com/payloadcms/payload/issues/370), only performs password functions when auth enabled ([9738873](https://github.com/payloadcms/payload/commit/97388738def687f3b26eaf8de6b067f4d3758418))
|
||||
* [#390](https://github.com/payloadcms/payload/issues/390), safari rich text link bug ([a16b99b](https://github.com/payloadcms/payload/commit/a16b99b0c87d55f768ed74ab35708a291fc7bbb0))
|
||||
* [#393](https://github.com/payloadcms/payload/issues/393), ensures preview button gets up to date data ([2f47e39](https://github.com/payloadcms/payload/commit/2f47e39a9f765bd8ce437d4b7500a5b314a192a5))
|
||||
* [#408](https://github.com/payloadcms/payload/issues/408) ([5c3cfa4](https://github.com/payloadcms/payload/commit/5c3cfa4c93767a5ead9e816bf11a000ebdac9761))
|
||||
* [#408](https://github.com/payloadcms/payload/issues/408) ([e2c5d93](https://github.com/payloadcms/payload/commit/e2c5d93751cb1902d6dce2147953b97c2dc17939))
|
||||
* 407 ([a09570c](https://github.com/payloadcms/payload/commit/a09570c78dc923f3553f36d726e5cfac925290a0))
|
||||
* allows null in ImageSize width and height types ([ba79fd4](https://github.com/payloadcms/payload/commit/ba79fd42dbf20ba712a0632da9193fcc516c0257))
|
||||
* cross-browser upload drag and drop ([4119eec](https://github.com/payloadcms/payload/commit/4119eec796794d6a026f34f8b097b379eb9895a0))
|
||||
* ensures getDataByPath works ([140a3aa](https://github.com/payloadcms/payload/commit/140a3aa9eafa29b2a43bdfd8883c79c6ee4a93e4))
|
||||
* ensures local findByID retains user ([05288ee](https://github.com/payloadcms/payload/commit/05288ee08c077019e4432bf385aeacc23a0643f3))
|
||||
* ensures row count is set properly in block fields ([9e091af](https://github.com/payloadcms/payload/commit/9e091af67e944e6a15d1d1174a18cde6deda40d7))
|
||||
* ensures searching relationships works with many pages of results ([961787d](https://github.com/payloadcms/payload/commit/961787d681882e5ab48bb676490555c93f5d4a2e))
|
||||
* globals model typing ([da7c0c9](https://github.com/payloadcms/payload/commit/da7c0c984c1fb57038d620fc59bcd27972919ade))
|
||||
|
||||
|
||||
|
||||
@@ -107,6 +107,11 @@ const LocalizedPosts: CollectionConfig = {
|
||||
name: 'text',
|
||||
label: 'Text',
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
name: 'demoHiddenField',
|
||||
hidden: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
|
||||
@@ -56,6 +56,11 @@ const RelationshipA: CollectionConfig = {
|
||||
hasMany: true,
|
||||
localized: true,
|
||||
},
|
||||
{
|
||||
name: 'demoHiddenField',
|
||||
type: 'text',
|
||||
hidden: true,
|
||||
},
|
||||
],
|
||||
timestamps: true,
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "payload",
|
||||
"version": "0.13.13-beta.0",
|
||||
"version": "0.13.20-beta.0",
|
||||
"description": "Node, React and MongoDB Headless CMS and Application Framework",
|
||||
"license": "SEE LICENSE IN license.md",
|
||||
"author": {
|
||||
@@ -35,6 +35,7 @@
|
||||
"demo:build:analyze": "cross-env PAYLOAD_CONFIG_PATH=demo/payload.config.ts PAYLOAD_ANALYZE_BUNDLE=true node dist/bin/build",
|
||||
"demo:build": "cross-env PAYLOAD_CONFIG_PATH=demo/payload.config.ts node dist/bin/build",
|
||||
"demo:generate:types": "cross-env PAYLOAD_CONFIG_PATH=demo/payload.config.ts node dist/bin/generateTypes",
|
||||
"demo:serve": "cross-env PAYLOAD_CONFIG_PATH=demo/payload.config.ts NODE_ENV=production nodemon",
|
||||
"dev": "cross-env PAYLOAD_CONFIG_PATH=demo/payload.config.ts nodemon",
|
||||
"test": "yarn test:int && yarn test:client",
|
||||
"pretest": "yarn build",
|
||||
|
||||
@@ -141,6 +141,8 @@ const Blocks: React.FC<Props> = (props) => {
|
||||
moveRow(sourceIndex, destinationIndex);
|
||||
}, [moveRow]);
|
||||
|
||||
// Get preferences, and once retrieved,
|
||||
// Reset rows with preferences included
|
||||
useEffect(() => {
|
||||
const fetchPreferences = async () => {
|
||||
const preferences = preferencesKey ? await getPreference<DocumentPreferences>(preferencesKey) : undefined;
|
||||
@@ -151,6 +153,12 @@ const Blocks: React.FC<Props> = (props) => {
|
||||
fetchPreferences();
|
||||
}, [formContext, path, preferencesKey, getPreference]);
|
||||
|
||||
// Set row count on mount and when form context is reset
|
||||
useEffect(() => {
|
||||
const data = formContext.getDataByPath(path);
|
||||
dispatchRows({ type: 'SET_ALL', data: data || [] });
|
||||
}, [formContext, path]);
|
||||
|
||||
useEffect(() => {
|
||||
setValue(rows?.length || 0);
|
||||
|
||||
|
||||
@@ -48,7 +48,6 @@ const Relationship: React.FC<Props> = (props) => {
|
||||
collections,
|
||||
} = useConfig();
|
||||
|
||||
|
||||
const formProcessing = useFormProcessing();
|
||||
|
||||
const hasMultipleRelations = Array.isArray(relationTo);
|
||||
@@ -308,7 +307,7 @@ const Relationship: React.FC<Props> = (props) => {
|
||||
}
|
||||
} : undefined}
|
||||
onMenuScrollToBottom={() => {
|
||||
getResults({ lastFullyLoadedRelation, lastLoadedPage: lastLoadedPage + 1 });
|
||||
getResults({ lastFullyLoadedRelation, lastLoadedPage: lastLoadedPage + 1, search });
|
||||
}}
|
||||
value={valueToRender}
|
||||
showError={showError}
|
||||
|
||||
@@ -27,7 +27,6 @@ const validate = (value) => {
|
||||
const Upload: React.FC<Props> = (props) => {
|
||||
const inputRef = useRef(null);
|
||||
const dropRef = useRef(null);
|
||||
const [fileList, setFileList] = useState(undefined);
|
||||
const [selectingFile, setSelectingFile] = useState(false);
|
||||
const [dragging, setDragging] = useState(false);
|
||||
const [dragCounter, setDragCounter] = useState(0);
|
||||
@@ -53,16 +52,16 @@ const Upload: React.FC<Props> = (props) => {
|
||||
const handleDragIn = useCallback((e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
setDragCounter(dragCounter + 1);
|
||||
setDragCounter((count) => count + 1);
|
||||
if (e.dataTransfer.items && e.dataTransfer.items.length > 0) {
|
||||
setDragging(true);
|
||||
}
|
||||
}, [dragCounter]);
|
||||
}, []);
|
||||
|
||||
const handleDragOut = useCallback((e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
setDragCounter(dragCounter - 1);
|
||||
setDragCounter((count) => count - 1);
|
||||
if (dragCounter > 1) return;
|
||||
setDragging(false);
|
||||
}, [dragCounter]);
|
||||
@@ -73,7 +72,7 @@ const Upload: React.FC<Props> = (props) => {
|
||||
setDragging(false);
|
||||
|
||||
if (e.dataTransfer.files && e.dataTransfer.files.length > 0) {
|
||||
setFileList(e.dataTransfer.files);
|
||||
setValue(e.dataTransfer.files[0]);
|
||||
setDragging(false);
|
||||
|
||||
e.dataTransfer.clearData();
|
||||
@@ -81,11 +80,13 @@ const Upload: React.FC<Props> = (props) => {
|
||||
} else {
|
||||
setDragging(false);
|
||||
}
|
||||
}, []);
|
||||
}, [setValue]);
|
||||
|
||||
// Only called when input is interacted with directly
|
||||
// Not called when drag + drop is used
|
||||
// Or when input is cleared
|
||||
const handleInputChange = useCallback(() => {
|
||||
setSelectingFile(false);
|
||||
setFileList(inputRef?.current?.files || null);
|
||||
setValue(inputRef?.current?.files?.[0] || null);
|
||||
}, [inputRef, setValue]);
|
||||
|
||||
@@ -113,13 +114,7 @@ const Upload: React.FC<Props> = (props) => {
|
||||
}
|
||||
|
||||
return () => null;
|
||||
}, [handleDragIn, handleDragOut, handleDrop, dropRef]);
|
||||
|
||||
useEffect(() => {
|
||||
if (inputRef.current && fileList !== undefined) {
|
||||
inputRef.current.files = fileList;
|
||||
}
|
||||
}, [fileList]);
|
||||
}, [handleDragIn, handleDragOut, handleDrop, value]);
|
||||
|
||||
useEffect(() => {
|
||||
setReplacingFile(false);
|
||||
@@ -143,7 +138,6 @@ const Upload: React.FC<Props> = (props) => {
|
||||
collection={collection}
|
||||
handleRemove={() => {
|
||||
setReplacingFile(true);
|
||||
setFileList(null);
|
||||
setValue(null);
|
||||
}}
|
||||
/>
|
||||
@@ -163,7 +157,6 @@ const Upload: React.FC<Props> = (props) => {
|
||||
buttonStyle="icon-label"
|
||||
iconStyle="with-border"
|
||||
onClick={() => {
|
||||
setFileList(null);
|
||||
setValue(null);
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -50,7 +50,9 @@ export default async function create<T = any>(options: Options<T>): Promise<T> {
|
||||
locale,
|
||||
fallbackLocale,
|
||||
payload: this,
|
||||
file: getFileByPath(filePath),
|
||||
files: {
|
||||
file: getFileByPath(filePath),
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -51,4 +51,71 @@ describe('Collections - Local', () => {
|
||||
expect(result.width).toStrictEqual(640);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Read with Hidden Fields', () => {
|
||||
it('should allow a document with nested hidden fields to be retrieved with hidden fields shown.', async () => {
|
||||
const demoHiddenField = 'this is going to be hidden';
|
||||
|
||||
const result = await payload.create({
|
||||
collection: 'localized-posts',
|
||||
data: {
|
||||
title: 'this post has a hidden field present',
|
||||
description: 'desc',
|
||||
priority: 1,
|
||||
nonLocalizedGroup: {
|
||||
text: '40w5g534gw34j',
|
||||
},
|
||||
localizedGroup: {
|
||||
text: '34lijgw45ligjw4li5j',
|
||||
demoHiddenField,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
expect(result.id).toBeDefined();
|
||||
expect(result.localizedGroup).toBeDefined();
|
||||
expect(result.localizedGroup.demoHiddenField).toBeUndefined();
|
||||
|
||||
const withHiddenFields = await payload.findByID({
|
||||
collection: 'localized-posts',
|
||||
id: result.id,
|
||||
showHiddenFields: true,
|
||||
});
|
||||
|
||||
expect(withHiddenFields.localizedGroup.demoHiddenField).toStrictEqual(demoHiddenField);
|
||||
expect(withHiddenFields.id).toStrictEqual(result.id);
|
||||
});
|
||||
|
||||
it('should allow a document with a relationship to a document with hidden fields to read the related document hidden fields', async () => {
|
||||
const demoHiddenField = 'this is going to be hidden';
|
||||
|
||||
const relationshipA = await payload.create({
|
||||
collection: 'relationship-a',
|
||||
data: {
|
||||
demoHiddenField,
|
||||
},
|
||||
});
|
||||
|
||||
expect(relationshipA.id).toBeDefined();
|
||||
expect(relationshipA.demoHiddenField).toBeUndefined();
|
||||
|
||||
const relationshipB = await payload.create({
|
||||
collection: 'relationship-b',
|
||||
data: {
|
||||
title: 'pretty clever name here',
|
||||
post: [relationshipA.id],
|
||||
},
|
||||
});
|
||||
|
||||
expect(relationshipB.id).toBeDefined();
|
||||
|
||||
const relationshipBWithHiddenNestedField = await payload.findByID({
|
||||
collection: 'relationship-b',
|
||||
id: relationshipB.id,
|
||||
showHiddenFields: true,
|
||||
});
|
||||
|
||||
expect(relationshipBWithHiddenNestedField.post[0].demoHiddenField).toStrictEqual(demoHiddenField);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -49,7 +49,9 @@ export default async function update<T = any>(options: Options<T>): Promise<T> {
|
||||
locale,
|
||||
fallbackLocale,
|
||||
payload: this,
|
||||
file: getFileByPath(filePath),
|
||||
files: {
|
||||
file: getFileByPath(filePath),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -11,7 +11,9 @@ export type PayloadRequest = Request & {
|
||||
fallbackLocale?: string;
|
||||
collection?: Collection;
|
||||
payloadAPI: 'REST' | 'local' | 'graphQL'
|
||||
file?: UploadedFile
|
||||
files?: {
|
||||
file: UploadedFile
|
||||
}
|
||||
user: User | null
|
||||
payloadUploadSizes?: Record<string, Buffer>
|
||||
findByID?: {
|
||||
|
||||
@@ -18,12 +18,12 @@ type Arguments = {
|
||||
currentDepth: number
|
||||
hook: HookName
|
||||
payload: Payload
|
||||
showHiddenFields: boolean
|
||||
}
|
||||
|
||||
const accessPromise = async ({
|
||||
data,
|
||||
fullData,
|
||||
originalDoc,
|
||||
field,
|
||||
operation,
|
||||
overrideAccess,
|
||||
@@ -34,6 +34,7 @@ const accessPromise = async ({
|
||||
currentDepth,
|
||||
hook,
|
||||
payload,
|
||||
showHiddenFields,
|
||||
}: Arguments): Promise<void> => {
|
||||
const resultingData = data;
|
||||
|
||||
@@ -56,6 +57,7 @@ const accessPromise = async ({
|
||||
|
||||
if ((field.type === 'relationship' || field.type === 'upload') && hook === 'afterRead') {
|
||||
relationshipPopulations.push(relationshipPopulationPromise({
|
||||
showHiddenFields,
|
||||
data,
|
||||
field,
|
||||
depth,
|
||||
|
||||
@@ -12,6 +12,7 @@ type PopulateArgs = {
|
||||
field: RelationshipField | UploadField
|
||||
index?: number
|
||||
payload: Payload
|
||||
showHiddenFields: boolean
|
||||
}
|
||||
|
||||
const populate = async ({
|
||||
@@ -24,6 +25,7 @@ const populate = async ({
|
||||
field,
|
||||
index,
|
||||
payload,
|
||||
showHiddenFields,
|
||||
}: PopulateArgs) => {
|
||||
const dataToUpdate = dataReference;
|
||||
|
||||
@@ -44,10 +46,11 @@ const populate = async ({
|
||||
req,
|
||||
collection: relatedCollection.config.slug,
|
||||
id: idString as string,
|
||||
depth,
|
||||
currentDepth: currentDepth + 1,
|
||||
overrideAccess,
|
||||
disableErrors: true,
|
||||
depth,
|
||||
showHiddenFields,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -76,6 +79,7 @@ type PromiseArgs = {
|
||||
req: PayloadRequest
|
||||
overrideAccess: boolean
|
||||
payload: Payload
|
||||
showHiddenFields: boolean
|
||||
}
|
||||
|
||||
const relationshipPopulationPromise = ({
|
||||
@@ -86,6 +90,7 @@ const relationshipPopulationPromise = ({
|
||||
req,
|
||||
overrideAccess,
|
||||
payload,
|
||||
showHiddenFields,
|
||||
}: PromiseArgs) => async (): Promise<void> => {
|
||||
const resultingData = data;
|
||||
const populateDepth = fieldHasMaxDepth(field) && field.maxDepth < depth ? field.maxDepth : depth;
|
||||
@@ -106,6 +111,7 @@ const relationshipPopulationPromise = ({
|
||||
field,
|
||||
index,
|
||||
payload,
|
||||
showHiddenFields,
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -124,6 +130,7 @@ const relationshipPopulationPromise = ({
|
||||
data: data[field.name],
|
||||
field,
|
||||
payload,
|
||||
showHiddenFields,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -11,6 +11,7 @@ type Arguments = {
|
||||
payload: Payload
|
||||
field: RichTextField
|
||||
req: PayloadRequest
|
||||
showHiddenFields: boolean
|
||||
}
|
||||
|
||||
type RecurseRichTextArgs = {
|
||||
@@ -22,6 +23,7 @@ type RecurseRichTextArgs = {
|
||||
field: RichTextField
|
||||
req: PayloadRequest
|
||||
promises: Promise<void>[]
|
||||
showHiddenFields: boolean
|
||||
}
|
||||
|
||||
const populate = async ({
|
||||
@@ -33,6 +35,7 @@ const populate = async ({
|
||||
currentDepth,
|
||||
payload,
|
||||
req,
|
||||
showHiddenFields,
|
||||
}: Arguments & {
|
||||
id: string,
|
||||
collection: Collection
|
||||
@@ -49,6 +52,7 @@ const populate = async ({
|
||||
overrideAccess,
|
||||
disableErrors: true,
|
||||
depth,
|
||||
showHiddenFields,
|
||||
});
|
||||
|
||||
if (doc) {
|
||||
@@ -67,6 +71,7 @@ const recurseRichText = ({
|
||||
currentDepth = 0,
|
||||
field,
|
||||
promises,
|
||||
showHiddenFields,
|
||||
}: RecurseRichTextArgs) => {
|
||||
if (Array.isArray(children)) {
|
||||
(children as any[]).forEach((element) => {
|
||||
@@ -86,6 +91,7 @@ const recurseRichText = ({
|
||||
payload,
|
||||
field,
|
||||
collection,
|
||||
showHiddenFields,
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -99,6 +105,7 @@ const recurseRichText = ({
|
||||
currentDepth,
|
||||
field,
|
||||
promises,
|
||||
showHiddenFields,
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -113,6 +120,7 @@ const richTextRelationshipPromise = ({
|
||||
depth,
|
||||
currentDepth,
|
||||
field,
|
||||
showHiddenFields,
|
||||
}: Arguments) => async (): Promise<void> => {
|
||||
const promises = [];
|
||||
|
||||
@@ -125,6 +133,7 @@ const richTextRelationshipPromise = ({
|
||||
currentDepth,
|
||||
field,
|
||||
promises,
|
||||
showHiddenFields,
|
||||
});
|
||||
|
||||
await Promise.all(promises);
|
||||
|
||||
@@ -149,6 +149,7 @@ const traverseFields = (args: Arguments): void => {
|
||||
depth,
|
||||
field,
|
||||
currentDepth,
|
||||
showHiddenFields,
|
||||
}));
|
||||
}
|
||||
}
|
||||
@@ -215,6 +216,7 @@ const traverseFields = (args: Arguments): void => {
|
||||
currentDepth,
|
||||
hook,
|
||||
payload,
|
||||
showHiddenFields,
|
||||
}));
|
||||
|
||||
hookPromises.push(() => hookPromise({
|
||||
@@ -256,6 +258,7 @@ const traverseFields = (args: Arguments): void => {
|
||||
docWithLocales: docWithLocales?.[field.name]?.[i],
|
||||
path: `${path}${field.name}.${i}.`,
|
||||
skipValidation: skipValidationFromHere,
|
||||
showHiddenFields,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -268,6 +271,7 @@ const traverseFields = (args: Arguments): void => {
|
||||
docWithLocales: docWithLocales?.[field.name],
|
||||
path: `${path}${field.name}.`,
|
||||
skipValidation: skipValidationFromHere,
|
||||
showHiddenFields,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -286,6 +290,7 @@ const traverseFields = (args: Arguments): void => {
|
||||
docWithLocales: docWithLocales?.[field.name]?.[i],
|
||||
path: `${path}${field.name}.${i}.`,
|
||||
skipValidation: skipValidationFromHere,
|
||||
showHiddenFields,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -55,6 +55,7 @@ function buildObjectType(name: string, fields: Field[], parentName: string, base
|
||||
payload: context.req.payload,
|
||||
depth: args.depth,
|
||||
field,
|
||||
showHiddenFields: false,
|
||||
});
|
||||
|
||||
await richTextRelationshipPromise();
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { UploadedFile } from 'express-fileupload';
|
||||
import mkdirp from 'mkdirp';
|
||||
import path from 'path';
|
||||
import { SanitizedConfig } from '../config/types';
|
||||
@@ -39,7 +38,7 @@ const uploadFile = async ({
|
||||
|
||||
const { staticDir, imageSizes, disableLocalStorage } = collectionConfig.upload;
|
||||
|
||||
const file = ((req.files && req.files.file) ? req.files.file : req.file) as UploadedFile;
|
||||
const { file } = req.files || {};
|
||||
|
||||
if (throwOnMissingFile && !file) {
|
||||
throw new MissingFile();
|
||||
|
||||
Reference in New Issue
Block a user