Skip to content

Commit

Permalink
feat: adds recursion to richText field to populate relationship and u…
Browse files Browse the repository at this point in the history
…pload nested fields
  • Loading branch information
JarrodMFlesch committed Jan 19, 2022
1 parent e76f7c8 commit 42af22c
Show file tree
Hide file tree
Showing 4 changed files with 262 additions and 48 deletions.
54 changes: 54 additions & 0 deletions src/fields/richText/populate.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/* eslint-disable @typescript-eslint/no-use-before-define */
import { Collection } from '../../collections/config/types';
import { Payload } from '../..';
import { RichTextField, Field } from '../config/types';
import { PayloadRequest } from '../../express/types';

type Arguments = {
data: unknown
overrideAccess?: boolean
depth: number
currentDepth?: number
payload: Payload
field: RichTextField
req: PayloadRequest
showHiddenFields: boolean
}

export const populate = async ({
id,
collection,
data,
overrideAccess,
depth,
currentDepth,
payload,
req,
showHiddenFields,
}: Omit<Arguments, 'field'> & {
id: string,
field: Field
collection: Collection
}): Promise<void> => {
let dataRef = data as Record<string, unknown>;

const doc = await payload.operations.collections.findByID({
req: {
...req,
payloadAPI: 'local',
},
collection,
id,
currentDepth: currentDepth + 1,
overrideAccess,
disableErrors: true,
depth,
showHiddenFields,
});

if (doc) {
dataRef = doc;
} else {
dataRef = null;
}
};
183 changes: 183 additions & 0 deletions src/fields/richText/recurseNestedFields.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
/* eslint-disable @typescript-eslint/no-use-before-define */
import { Payload } from '../..';
import { Field, fieldHasSubFields, fieldIsArrayType, fieldAffectsData } from '../config/types';
import { PayloadRequest } from '../../express/types';
import { populate } from './populate';
import { recurseRichText } from './relationshipPromise';

type NestedRichTextFieldsArgs = {
promises: Promise<void>[]
data: unknown
fields: Field[]
req: PayloadRequest
payload: Payload
overrideAccess: boolean
depth: number
currentDepth?: number
showHiddenFields: boolean
}

export const recurseNestedFields = ({
promises,
data,
fields,
req,
payload,
overrideAccess = false,
depth,
currentDepth = 0,
showHiddenFields,
}: NestedRichTextFieldsArgs): void => {
fields.forEach((field) => {
if (field.type === 'relationship' || field.type === 'upload') {
if (field.type === 'relationship') {
if (field.hasMany && Array.isArray(data[field.name])) {
if (Array.isArray(field.relationTo)) {
data[field.name].forEach(({ relationTo, value }, i) => {
const collection = payload.collections[relationTo];
if (collection) {
promises.push(populate({
id: value,
field,
collection,
data: data[field.name][i],
overrideAccess,
depth,
currentDepth,
payload,
req,
showHiddenFields,
}));
}
});
} else {
data[field.name].forEach((id, i) => {
const collection = payload.collections[field.relationTo as string];
if (collection) {
promises.push(populate({
id,
field,
collection,
data: data[field.name][i],
overrideAccess,
depth,
currentDepth,
payload,
req,
showHiddenFields,
}));
}
});
}
} else if (Array.isArray(field.relationTo) && data[field.name]?.value && data[field.name]?.relationTo) {
const collection = payload.collections[data[field.name].relationTo];
promises.push(populate({
id: data[field.name].value,
field,
collection,
data: data[field.name].value,
overrideAccess,
depth,
currentDepth,
payload,
req,
showHiddenFields,
}));
}
} else if (typeof data[field.name] !== undefined) {
const collection = payload.collections[field.relationTo];
promises.push(populate({
id: data[field.name],
field,
collection,
data: data[field.name],
overrideAccess,
depth,
currentDepth,
payload,
req,
showHiddenFields,
}));
}
} else if (fieldHasSubFields(field) && !fieldIsArrayType(field)) {
if (fieldAffectsData(field) && typeof data[field.name] === 'object') {
recurseNestedFields({
promises,
data: data[field.name],
fields: field.fields,
req,
payload,
overrideAccess,
depth,
currentDepth,
showHiddenFields,
});
} else {
recurseNestedFields({
promises,
data,
fields: field.fields,
req,
payload,
overrideAccess,
depth,
currentDepth,
showHiddenFields,
});
}
} else if (Array.isArray(data[field.name])) {
if (field.type === 'blocks') {
data[field.name].forEach((row, i) => {
const block = field.blocks.find(({ slug }) => slug === row?.blockType);
if (block) {
recurseNestedFields({
promises,
data: data[field.name][i],
fields: block.fields,
req,
payload,
overrideAccess,
depth,
currentDepth,
showHiddenFields,
});
}
});
}

if (field.type === 'array') {
data[field.name].forEach((_, i) => {
recurseNestedFields({
promises,
data: data[field.name][i],
fields: field.fields,
req,
payload,
overrideAccess,
depth,
currentDepth,
showHiddenFields,
});
});
}
}

if (field.type === 'richText' && Array.isArray(data[field.name])) {
data[field.name].forEach((node) => {
if (Array.isArray(node.children)) {
recurseRichText({
req,
children: node.children,
payload,
overrideAccess,
depth,
currentDepth,
field,
promises,
showHiddenFields,
});
}
});
}
});
};
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { Collection } from '../collections/config/types';
import { Payload } from '..';
import { RichTextField } from './config/types';
import { PayloadRequest } from '../express/types';
import { Payload } from '../..';
import { RichTextField } from '../config/types';
import { PayloadRequest } from '../../express/types';
import { recurseNestedFields } from './recurseNestedFields';
import { populate } from './populate';

type Arguments = {
data: unknown
Expand All @@ -26,44 +27,7 @@ type RecurseRichTextArgs = {
showHiddenFields: boolean
}

const populate = async ({
id,
collection,
data,
overrideAccess,
depth,
currentDepth,
payload,
req,
showHiddenFields,
}: Arguments & {
id: string,
collection: Collection
}) => {
const dataRef = data as Record<string, unknown>;

const doc = await payload.operations.collections.findByID({
req: {
...req,
payloadAPI: 'local',
},
collection,
id,
currentDepth: currentDepth + 1,
overrideAccess,
disableErrors: true,
depth,
showHiddenFields,
});

if (doc) {
dataRef.value = doc;
} else {
dataRef.value = null;
}
};

const recurseRichText = ({
export const recurseRichText = ({
req,
children,
payload,
Expand All @@ -73,7 +37,7 @@ const recurseRichText = ({
field,
promises,
showHiddenFields,
}: RecurseRichTextArgs) => {
}: RecurseRichTextArgs): void => {
if (Array.isArray(children)) {
(children as any[]).forEach((element) => {
const collection = payload.collections[element?.relationTo];
Expand All @@ -82,10 +46,23 @@ const recurseRichText = ({
&& element?.value?.id
&& collection
&& (depth && currentDepth <= depth)) {
if (element.type === 'upload' && Array.isArray(field.admin?.upload?.collections?.[element?.relationTo]?.fields)) {
recurseNestedFields({
promises,
data: element.fields || {},
fields: field.admin.upload.collections[element.relationTo].fields,
req,
payload,
overrideAccess,
depth,
currentDepth,
showHiddenFields,
});
}
promises.push(populate({
req,
id: element.value.id,
data: element,
data: element.value,
overrideAccess,
depth,
currentDepth,
Expand Down
8 changes: 4 additions & 4 deletions src/fields/traverseFields.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Field, fieldHasSubFields, fieldIsArrayType, fieldIsBlockType, fieldAffe
import { Operation } from '../types';
import { PayloadRequest } from '../express/types';
import { Payload } from '..';
import richTextRelationshipPromise from './richTextRelationshipPromise';
import richTextRelationshipPromise from './richText/relationshipPromise';

type Arguments = {
fields: Field[]
Expand All @@ -28,7 +28,7 @@ type Arguments = {
fullOriginalDoc: Record<string, any>
fullData: Record<string, any>
validationPromises: (() => Promise<string | boolean>)[]
errors: {message: string, field: string}[]
errors: { message: string, field: string }[]
payload: Payload
showHiddenFields: boolean
unflattenLocales: boolean
Expand Down Expand Up @@ -96,7 +96,7 @@ const traverseFields = (args: Arguments): void => {
}

if ((field.type === 'upload' || field.type === 'relationship')
&& (data[field.name] === '' || data[field.name] === 'none' || data[field.name] === 'null')) {
&& (data[field.name] === '' || data[field.name] === 'none' || data[field.name] === 'null')) {
if (field.type === 'relationship' && field.hasMany === true) {
dataCopy[field.name] = [];
} else {
Expand Down Expand Up @@ -304,7 +304,7 @@ const traverseFields = (args: Arguments): void => {
if (field.type === 'relationship' || field.type === 'upload') {
if (Array.isArray(field.relationTo)) {
if (Array.isArray(dataCopy[field.name])) {
dataCopy[field.name].forEach((relatedDoc: {value: unknown, relationTo: string}, i) => {
dataCopy[field.name].forEach((relatedDoc: { value: unknown, relationTo: string }, i) => {
const relatedCollection = payload.config.collections.find((collection) => collection.slug === relatedDoc.relationTo);
const relationshipIDField = relatedCollection.fields.find((collectionField) => fieldAffectsData(collectionField) && collectionField.name === 'id');
if (relationshipIDField?.type === 'number') {
Expand Down

0 comments on commit 42af22c

Please sign in to comment.