feat: dynamically populates richtext relationships

* feat: adds relationship field to test searchable input

* fix: searching on relationship fields properly fetches results

* chore: more dry relationship field

* feat: sets default access control to requiring a user to be logged in

* feat: dynamically populates richtext relationships

* feat: allows depth param in graphql richText field

* feat: ensures relationship input is initialized with up to 3 related collections
This commit is contained in:
James Mikrut
2021-04-18 15:29:54 -04:00
committed by GitHub
parent b86c3daa99
commit 353042467f
17 changed files with 259 additions and 35 deletions

View File

@@ -246,19 +246,44 @@ const Relationship: React.FC<Props> = (props) => {
useEffect(() => {
const getFirstResults = async () => {
const relation = relations[0];
const res = await fetch(`${serverURL}${api}/${relation}?limit=${maxResultsPerRequest}&depth=0`);
const res = await fetch(`${serverURL}${api}/${relations[0]}?limit=${maxResultsPerRequest}&depth=0`);
if (res.ok) {
const data: PaginatedDocs = await res.json();
addOptions(data, relation);
addOptions(data, relations[0]);
if (!data.hasNextPage) {
setLastFullyLoadedRelation(relations.indexOf(relation));
} else {
setLastLoadedPage(2);
setLastFullyLoadedRelation(0);
if (relations[1]) {
const secondRes = await fetch(`${serverURL}${api}/${relations[1]}?limit=${maxResultsPerRequest}&depth=0`);
if (res.ok) {
const secondData: PaginatedDocs = await secondRes.json();
addOptions(secondData, relations[1]);
if (!secondData.hasNextPage) {
setLastFullyLoadedRelation(1);
if (relations[2]) {
const thirdRes = await fetch(`${serverURL}${api}/${relations[2]}?limit=${maxResultsPerRequest}&depth=0`);
if (res.ok) {
const thirdData: PaginatedDocs = await thirdRes.json();
addOptions(thirdData, relations[2]);
if (!thirdData.hasNextPage) {
setLastFullyLoadedRelation(2);
}
}
}
}
}
}
}
setHasLoadedFirstOptions(true);

View File

@@ -2,10 +2,8 @@ import React, { Fragment, useState, useEffect } from 'react';
import { useConfig, useAuth } from '@payloadcms/config-provider';
import { useWatchForm } from '../../../../../../Form/context';
import Relationship from '../../../../../Relationship';
import Number from '../../../../../Number';
import Select from '../../../../../Select';
const createOptions = (collections, permissions) => collections.reduce((options, collection) => {
if (permissions?.collections?.[collection.slug]?.read?.permission && collection?.admin?.enableRichTextRelationship) {
return [
@@ -21,7 +19,7 @@ const createOptions = (collections, permissions) => collections.reduce((options,
}, []);
const RelationshipFields = () => {
const { collections, maxDepth } = useConfig();
const { collections } = useConfig();
const { permissions } = useAuth();
const [options, setOptions] = useState(() => createOptions(collections, permissions));
@@ -49,13 +47,6 @@ const RelationshipFields = () => {
required
/>
)}
<Number
required
name="depth"
label="Depth"
min={0}
max={maxDepth}
/>
</Fragment>
);
};

View File

@@ -15,19 +15,16 @@ import { requests } from '../../../../../../../api';
import './index.scss';
const initialFormData = {
depth: 0,
};
const initialFormData = {};
const baseClass = 'relationship-rich-text-button';
const insertRelationship = (editor, { value, relationTo, depth }) => {
const insertRelationship = (editor, { value, relationTo }) => {
const text = { text: ' ' };
const relationship = {
type: 'relationship',
value,
depth,
relationTo,
children: [
text,
@@ -58,13 +55,13 @@ const RelationshipButton: React.FC<{path: string}> = ({ path }) => {
const [hasEnabledCollections] = useState(() => collections.find(({ admin: { enableRichTextRelationship } }) => enableRichTextRelationship));
const modalSlug = `${path}-add-relationship`;
const handleAddRelationship = useCallback(async (_, { relationTo, value, depth }) => {
const handleAddRelationship = useCallback(async (_, { relationTo, value }) => {
setLoading(true);
const res = await requests.get(`${serverURL}${api}/${relationTo}/${value}?depth=${depth}`);
const res = await requests.get(`${serverURL}${api}/${relationTo}/${value}?depth=0`);
const json = await res.json();
insertRelationship(editor, { value: json, depth, relationTo });
insertRelationship(editor, { value: { id: json.id }, relationTo });
closeAll();
setRenderModal(false);
setLoading(false);

View File

@@ -6,7 +6,7 @@
align-items: flex-start;
background: $color-background-gray;
max-width: base(15);
margin-bottom: $baseline;
margin-bottom: base(.5);
svg {
width: base(1.25);

View File

@@ -1,16 +1,26 @@
import React, { useState } from 'react';
import { useConfig } from '@payloadcms/config-provider';
import RelationshipIcon from '../../../../../../icons/Relationship';
import usePayloadAPI from '../../../../../../../hooks/usePayloadAPI';
import './index.scss';
const baseClass = 'rich-text-relationship';
const initialParams = {
depth: 0,
};
const Element = ({ attributes, children, element }) => {
const { relationTo, value } = element;
const { collections } = useConfig();
const { collections, serverURL, routes: { api } } = useConfig();
const [relatedCollection] = useState(() => collections.find((coll) => coll.slug === relationTo));
const [{ data }] = usePayloadAPI(
`${serverURL}${api}/${relatedCollection.slug}/${value?.id}`,
{ initialParams },
);
return (
<div
className={baseClass}
@@ -24,7 +34,7 @@ const Element = ({ attributes, children, element }) => {
{' '}
Relationship
</div>
<h5>{value[relatedCollection?.admin?.useAsTitle || 'id']}</h5>
<h5>{data[relatedCollection?.admin?.useAsTitle || 'id']}</h5>
</div>
{children}
</div>