Created
September 1, 2024 08:41
-
-
Save tsemachh/803ab2a117d1ea1d6ce83cf1423cfd7f to your computer and use it in GitHub Desktop.
Compound Relation View in Edit View Component
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import type { EditViewComponent, PayloadServerReactComponent } from 'payload' | |
import { EditView } from '@payloadcms/next/views' | |
import React from 'react' | |
import { DocumentDrawerContent } from './DocumentView' | |
const CustomDefaultEditView: PayloadServerReactComponent<EditViewComponent> = () => { | |
return ( | |
<div style={{ display: 'flex' }}> | |
<div style={{ width: '50%' }}> | |
<EditView /> | |
</div> | |
<div style={{ border: '1px solid' }}> | |
<DocumentDrawerContent | |
collectionSlug={'individualcontent'} | |
id={'66aa0d24bff0d3e456f6790b'} | |
/> | |
</div> | |
</div> | |
) | |
} | |
export default CustomDefaultEditView |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use client' | |
import React, { useCallback, useEffect, useState } from 'react' | |
import { toast } from 'sonner' | |
import { XIcon } from '@payloadcms/ui/icons/X' | |
import { RenderComponent } from '@payloadcms/ui' | |
import { useConfig } from '@payloadcms/ui' | |
import { DocumentInfoProvider, useDocumentInfo } from '@payloadcms/ui' | |
import { useLocale } from '@payloadcms/ui' | |
import { useTranslation } from '@payloadcms/ui' | |
import { useRelatedCollections } from './useRelatedCollections' | |
import { Gutter } from '@payloadcms/ui' | |
import { IDLabel } from '@payloadcms/ui/elements/IDLabel' | |
import { RenderTitle } from '@payloadcms/ui/elements/RenderTitle' | |
import { DocumentInfoContext } from '@payloadcms/ui' | |
export type DrawerProps = { | |
readonly Header?: React.ReactNode | |
readonly children: React.ReactNode | |
readonly className?: string | |
readonly gutter?: boolean | |
readonly hoverTitle?: boolean | |
readonly slug: string | |
readonly title?: string | |
} | |
export type DocumentDrawerProps = { | |
readonly collectionSlug: string | |
readonly drawerSlug?: string | |
readonly id?: null | number | string | |
readonly onSave?: DocumentInfoContext['onSave'] | |
} & Pick<DrawerProps, 'Header'> | |
const baseClass = 'doc-drawer' | |
export const DocumentDrawerContent: React.FC<DocumentDrawerProps> = ({ | |
id: existingDocID, | |
Header, | |
collectionSlug, | |
drawerSlug, | |
onSave: onSaveFromProps, | |
}) => { | |
const { config } = useConfig() | |
const { | |
routes: { api: apiRoute }, | |
serverURL, | |
} = config | |
const locale = useLocale() | |
const { t } = useTranslation() | |
const [docID, setDocID] = useState(existingDocID) | |
const [isOpen] = useState(false) | |
const [collectionConfig] = useRelatedCollections(collectionSlug) | |
const Edit = collectionConfig.admin.components.views.edit.default.Component | |
const isEditing = Boolean(docID) | |
const apiURL = docID | |
? `${serverURL}${apiRoute}/${collectionSlug}/${docID}${ | |
locale?.code ? `?locale=${locale.code}` : '' | |
}` | |
: null | |
const onLoadError = React.useCallback(() => { | |
if (isOpen) { | |
toast.error(data.errors?.[0].message || t('error:unspecific')) | |
} | |
}, [isOpen, t]) | |
const onSave = useCallback<DocumentDrawerProps['onSave']>( | |
(args) => { | |
setDocID(args.doc.id) | |
if (typeof onSaveFromProps === 'function') { | |
void onSaveFromProps({ | |
...args, | |
collectionConfig, | |
}) | |
} | |
}, | |
[onSaveFromProps, collectionConfig], | |
) | |
return ( | |
<DocumentInfoProvider | |
BeforeDocument={ | |
<Gutter className={`${baseClass}__header`}> | |
<div className={`${baseClass}__header-content`}> | |
<h2 className={`${baseClass}__header-text`}> | |
{Header || <RenderTitle element="span" />} | |
</h2> | |
{/* TODO: the `button` HTML element breaks CSS transitions on the drawer for some reason... | |
i.e. changing to a `div` element will fix the animation issue but will break accessibility | |
*/} | |
<button | |
aria-label={t('general:close')} | |
className={`${baseClass}__header-close`} | |
onClick={() => closePanel()} | |
type="button" | |
> | |
<XIcon /> | |
</button> | |
</div> | |
<DocumentTitle /> | |
</Gutter> | |
} | |
apiURL={apiURL} | |
collectionSlug={collectionConfig.slug} | |
disableActions | |
disableLeaveWithoutSaving | |
id={docID} | |
isEditing={isEditing} | |
onLoadError={onLoadError} | |
onSave={onSave} | |
> | |
<RenderComponent mappedComponent={Edit} /> | |
</DocumentInfoProvider> | |
) | |
} | |
const DocumentTitle: React.FC = () => { | |
const { id, title } = useDocumentInfo() | |
return id && id !== title ? <IDLabel id={id.toString()} /> : null | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment