feat(ui): use document drawers for folder edit/create (#12676)
This PR re-uses the document drawers for editing and creating folders. This allows us to easily render document fields that are added inside `collectionOverrides` on the folder config. Not much changed, the folder drawer UI now resembles what you would expect when you create a document in payload. It is a bit slimmed back but generally very similar.
This commit is contained in:
@@ -4,11 +4,13 @@
|
||||
.doc-drawer {
|
||||
&__header {
|
||||
width: 100%;
|
||||
margin-top: base(2.5);
|
||||
margin-top: calc(var(--base) * 2);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: base(0.5);
|
||||
gap: calc(var(--base) * 0.5);
|
||||
align-items: flex-start;
|
||||
border-bottom: 1px solid var(--theme-elevation-100);
|
||||
padding-bottom: var(--base);
|
||||
}
|
||||
|
||||
&__header-content {
|
||||
@@ -46,12 +48,12 @@
|
||||
padding: 0;
|
||||
cursor: pointer;
|
||||
overflow: hidden;
|
||||
width: base(2);
|
||||
height: base(2);
|
||||
width: calc(var(--base) * 2);
|
||||
height: calc(var(--base) * 2);
|
||||
|
||||
svg {
|
||||
width: base(2);
|
||||
height: base(2);
|
||||
width: calc(var(--base) * 2);
|
||||
height: calc(var(--base) * 2);
|
||||
position: relative;
|
||||
|
||||
.stroke {
|
||||
@@ -61,10 +63,16 @@
|
||||
}
|
||||
}
|
||||
|
||||
&__divider {
|
||||
height: 1px;
|
||||
background: var(--theme-elevation-100);
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@include mid-break {
|
||||
.doc-drawer__header {
|
||||
margin-top: base(1.5);
|
||||
margin-bottom: base(0.5);
|
||||
margin-top: calc(var(--base) * 1.5);
|
||||
margin-bottom: calc(var(--base) * 0.5);
|
||||
padding-left: var(--gutter-h);
|
||||
padding-right: var(--gutter-h);
|
||||
}
|
||||
|
||||
@@ -13,7 +13,8 @@ import './index.scss'
|
||||
|
||||
export const DocumentDrawerHeader: React.FC<{
|
||||
drawerSlug: string
|
||||
}> = ({ drawerSlug }) => {
|
||||
showDocumentID?: boolean
|
||||
}> = ({ drawerSlug, showDocumentID = true }) => {
|
||||
const { closeModal } = useModal()
|
||||
const { t } = useTranslation()
|
||||
|
||||
@@ -32,12 +33,12 @@ export const DocumentDrawerHeader: React.FC<{
|
||||
<XIcon />
|
||||
</button>
|
||||
</div>
|
||||
<DocumentTitle />
|
||||
{showDocumentID && <DocumentID />}
|
||||
</Gutter>
|
||||
)
|
||||
}
|
||||
|
||||
const DocumentTitle: React.FC = () => {
|
||||
const DocumentID: React.FC = () => {
|
||||
const { id } = useDocumentInfo()
|
||||
const { title } = useDocumentTitle()
|
||||
return id && id !== title ? <IDLabel id={id.toString()} /> : null
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
.drawerHeader {
|
||||
.drawer-action-header {
|
||||
padding-top: calc(var(--base) * 2);
|
||||
padding-bottom: calc(var(--base) * 1);
|
||||
border-bottom: 1px solid var(--theme-border-color);
|
||||
border-bottom: 1px solid var(--theme-elevation-100);
|
||||
|
||||
&__content {
|
||||
margin-left: var(--gutter-h);
|
||||
|
||||
@@ -7,10 +7,11 @@ import { useTranslation } from '../../providers/Translation/index.js'
|
||||
import { Button } from '../Button/index.js'
|
||||
import './index.scss'
|
||||
|
||||
const baseClass = 'drawerHeader'
|
||||
const baseClass = 'drawer-action-header'
|
||||
|
||||
type DrawerActionHeaderArgs = {
|
||||
readonly cancelLabel?: string
|
||||
className?: string
|
||||
readonly onCancel?: () => void
|
||||
readonly onSave?: () => void
|
||||
readonly saveLabel?: string
|
||||
@@ -18,6 +19,7 @@ type DrawerActionHeaderArgs = {
|
||||
}
|
||||
export const DrawerActionHeader = ({
|
||||
cancelLabel,
|
||||
className,
|
||||
onCancel,
|
||||
onSave,
|
||||
saveLabel,
|
||||
@@ -26,7 +28,7 @@ export const DrawerActionHeader = ({
|
||||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<div className={baseClass}>
|
||||
<div className={[baseClass, className].filter(Boolean).join(' ')}>
|
||||
<div className={`${baseClass}__content`}>
|
||||
<h1 className={`${baseClass}__title`}>{title}</h1>
|
||||
|
||||
|
||||
@@ -8,12 +8,11 @@ import { useConfig } from '../../../providers/Config/index.js'
|
||||
import { useFolder } from '../../../providers/Folders/index.js'
|
||||
import { useTranslation } from '../../../providers/Translation/index.js'
|
||||
import { ConfirmationModal } from '../../ConfirmationModal/index.js'
|
||||
import { useDocumentDrawer } from '../../DocumentDrawer/index.js'
|
||||
import { Popup, PopupList } from '../../Popup/index.js'
|
||||
import { Translation } from '../../Translation/index.js'
|
||||
import { MoveItemsToFolderDrawer } from '../Drawers/MoveToFolder/index.js'
|
||||
import { RenameFolderDrawer } from '../Drawers/RenameFolder/index.js'
|
||||
|
||||
const renameFolderDrawerSlug = 'rename-folder--current-folder'
|
||||
const moveToFolderDrawerSlug = 'move-to-folder--current-folder'
|
||||
const confirmDeleteDrawerSlug = 'confirm-many-delete'
|
||||
|
||||
@@ -34,6 +33,11 @@ export function CurrentFolderActions({ className }: Props) {
|
||||
renameFolder,
|
||||
setFolderID,
|
||||
} = useFolder()
|
||||
const [FolderDocumentDrawer, , { closeDrawer: closeFolderDrawer, openDrawer: openFolderDrawer }] =
|
||||
useDocumentDrawer({
|
||||
id: folderID,
|
||||
collectionSlug: folderCollectionSlug,
|
||||
})
|
||||
const { config } = useConfig()
|
||||
const { routes, serverURL } = config
|
||||
const { closeModal, openModal } = useModal()
|
||||
@@ -60,10 +64,12 @@ export function CurrentFolderActions({ className }: Props) {
|
||||
<PopupList.ButtonGroup>
|
||||
<PopupList.Button
|
||||
onClick={() => {
|
||||
openModal(renameFolderDrawerSlug)
|
||||
openFolderDrawer()
|
||||
}}
|
||||
>
|
||||
{t('folder:renameFolder')}
|
||||
{t('general:editLabel', {
|
||||
label: getTranslation(folderCollectionConfig.labels.singular, i18n),
|
||||
})}
|
||||
</PopupList.Button>
|
||||
<PopupList.Button
|
||||
onClick={() => {
|
||||
@@ -136,15 +142,13 @@ export function CurrentFolderActions({ className }: Props) {
|
||||
onConfirm={deleteCurrentFolder}
|
||||
/>
|
||||
|
||||
<RenameFolderDrawer
|
||||
drawerSlug={renameFolderDrawerSlug}
|
||||
folderToRename={currentFolder}
|
||||
onRenameConfirm={({ folderID: updatedFolderID, updatedName }) => {
|
||||
<FolderDocumentDrawer
|
||||
onSave={(result) => {
|
||||
renameFolder({
|
||||
folderID: updatedFolderID,
|
||||
newName: updatedName,
|
||||
folderID: result.doc.id,
|
||||
newName: result.doc[folderCollectionConfig.admin.useAsTitle],
|
||||
})
|
||||
closeModal(renameFolderDrawerSlug)
|
||||
closeFolderDrawer()
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
@layer payload-default {
|
||||
.drawerHeader {
|
||||
padding-top: calc(var(--base) * 2);
|
||||
padding-bottom: calc(var(--base) * 1.5);
|
||||
border-bottom: 1px solid var(--theme-border-color);
|
||||
|
||||
&__content {
|
||||
margin-left: var(--gutter-h);
|
||||
margin-right: var(--gutter-h);
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
&__title {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
&__actions {
|
||||
display: flex;
|
||||
margin-left: auto;
|
||||
padding-left: var(--base);
|
||||
gap: var(--base);
|
||||
|
||||
button {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
'use client'
|
||||
|
||||
import React from 'react'
|
||||
|
||||
import { FormSubmit } from '../../../../forms/Submit/index.js'
|
||||
import { useTranslation } from '../../../../providers/Translation/index.js'
|
||||
import { Button } from '../../../Button/index.js'
|
||||
import './index.scss'
|
||||
|
||||
const baseClass = 'drawerHeader'
|
||||
|
||||
type DrawerHeaderArgs = {
|
||||
readonly onCancel?: () => void
|
||||
readonly onSave?: () => void
|
||||
readonly title: string
|
||||
}
|
||||
export const DrawerHeader = ({ onCancel, onSave, title }: DrawerHeaderArgs) => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<div className={baseClass}>
|
||||
<div className={`${baseClass}__content`}>
|
||||
<h1 className={`${baseClass}__title`}>{title}</h1>
|
||||
|
||||
<div className={`${baseClass}__actions`}>
|
||||
<Button aria-label={t('general:cancel')} buttonStyle="secondary" onClick={onCancel}>
|
||||
{t('general:cancel')}
|
||||
</Button>
|
||||
|
||||
<FormSubmit aria-label={t('general:applyChanges')} onClick={onSave}>
|
||||
{t('general:applyChanges')}
|
||||
</FormSubmit>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
import type { DocumentDrawerContextProps } from '../../../DocumentDrawer/Provider.js'
|
||||
|
||||
import { useTranslation } from '../../../../providers/Translation/index.js'
|
||||
import { useDocumentDrawer } from '../../../DocumentDrawer/index.js'
|
||||
import { ListSelectionButton } from '../../../ListSelection/index.js'
|
||||
|
||||
type EditFolderActionProps = {
|
||||
folderCollectionSlug: string
|
||||
id: number | string
|
||||
onSave: DocumentDrawerContextProps['onSave']
|
||||
}
|
||||
export const EditFolderAction = ({ id, folderCollectionSlug, onSave }: EditFolderActionProps) => {
|
||||
const { t } = useTranslation()
|
||||
const [FolderDocumentDrawer, , { closeDrawer, openDrawer }] = useDocumentDrawer({
|
||||
id,
|
||||
collectionSlug: folderCollectionSlug,
|
||||
})
|
||||
|
||||
if (!id) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<ListSelectionButton onClick={openDrawer} type="button">
|
||||
{t('general:edit')}
|
||||
</ListSelectionButton>
|
||||
|
||||
<FolderDocumentDrawer
|
||||
onSave={async (args) => {
|
||||
await onSave(args)
|
||||
closeDrawer()
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
&__breadcrumbs-section {
|
||||
padding: calc(var(--base) * 0.75) var(--gutter-h);
|
||||
border-bottom: 1px solid var(--theme-border-color);
|
||||
border-bottom: 1px solid var(--theme-elevation-100);
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ import { FolderProvider, useFolder } from '../../../../providers/Folders/index.j
|
||||
import { useTranslation } from '../../../../providers/Translation/index.js'
|
||||
import { Button } from '../../../Button/index.js'
|
||||
import { ConfirmationModal } from '../../../ConfirmationModal/index.js'
|
||||
import { useDocumentDrawer } from '../../../DocumentDrawer/index.js'
|
||||
import { Drawer } from '../../../Drawer/index.js'
|
||||
import { DrawerActionHeader } from '../../../DrawerActionHeader/index.js'
|
||||
import { DrawerContentContainer } from '../../../DrawerContentContainer/index.js'
|
||||
@@ -28,13 +29,11 @@ import { Translation } from '../../../Translation/index.js'
|
||||
import { FolderBreadcrumbs } from '../../Breadcrumbs/index.js'
|
||||
import { ColoredFolderIcon } from '../../ColoredFolderIcon/index.js'
|
||||
import { ItemCardGrid } from '../../ItemCardGrid/index.js'
|
||||
import { NewFolderDrawer } from '../NewFolder/index.js'
|
||||
import './index.scss'
|
||||
|
||||
const baseClass = 'move-folder-drawer'
|
||||
const baseModalSlug = 'move-folder-drawer'
|
||||
const confirmModalSlug = `${baseModalSlug}-confirm-move`
|
||||
const newFolderDrawerSlug = `${baseModalSlug}-new-folder`
|
||||
|
||||
type ActionProps =
|
||||
| {
|
||||
@@ -158,10 +157,15 @@ function Content({
|
||||
folderCollectionConfig,
|
||||
folderCollectionSlug,
|
||||
folderFieldName,
|
||||
folderID,
|
||||
getSelectedItems,
|
||||
setFolderID,
|
||||
subfolders,
|
||||
} = useFolder()
|
||||
const [FolderDocumentDrawer, , { closeDrawer: closeFolderDrawer, openDrawer: openFolderDrawer }] =
|
||||
useDocumentDrawer({
|
||||
collectionSlug: folderCollectionSlug,
|
||||
})
|
||||
const { getEntityConfig } = useConfig()
|
||||
|
||||
const getSelectedFolder = React.useCallback((): {
|
||||
@@ -268,24 +272,27 @@ function Content({
|
||||
className={`${baseClass}__add-folder-button`}
|
||||
margin={false}
|
||||
onClick={() => {
|
||||
openModal(newFolderDrawerSlug)
|
||||
openFolderDrawer()
|
||||
}}
|
||||
>
|
||||
{t('fields:addLabel', {
|
||||
label: getTranslation(folderCollectionConfig.labels?.singular, i18n),
|
||||
})}
|
||||
</Button>
|
||||
<NewFolderDrawer
|
||||
drawerSlug={newFolderDrawerSlug}
|
||||
onNewFolderSuccess={(doc) => {
|
||||
closeModal(newFolderDrawerSlug)
|
||||
<FolderDocumentDrawer
|
||||
initialData={{
|
||||
[folderFieldName]: folderID,
|
||||
}}
|
||||
onSave={(result) => {
|
||||
if (typeof onCreateSuccess === 'function') {
|
||||
void onCreateSuccess({
|
||||
collectionSlug: folderCollectionConfig.slug,
|
||||
doc,
|
||||
doc: result.doc,
|
||||
})
|
||||
}
|
||||
closeFolderDrawer()
|
||||
}}
|
||||
redirectAfterCreate={false}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
|
||||
@@ -1,95 +0,0 @@
|
||||
'use client'
|
||||
|
||||
import type { FolderInterface } from 'payload/shared'
|
||||
|
||||
import { useModal } from '@faceless-ui/modal'
|
||||
import React from 'react'
|
||||
|
||||
import { HiddenField } from '../../../../fields/Hidden/index.js'
|
||||
import { TextField } from '../../../../fields/Text/index.js'
|
||||
import { Form } from '../../../../forms/Form/index.js'
|
||||
import { useConfig } from '../../../../providers/Config/index.js'
|
||||
import { useFolder } from '../../../../providers/Folders/index.js'
|
||||
import { useTranslation } from '../../../../providers/Translation/index.js'
|
||||
import { Drawer } from '../../../Drawer/index.js'
|
||||
import { DrawerActionHeader } from '../../../DrawerActionHeader/index.js'
|
||||
import { DrawerContentContainer } from '../../../DrawerContentContainer/index.js'
|
||||
|
||||
type Props = {
|
||||
readonly drawerSlug: string
|
||||
readonly onNewFolderSuccess: (doc: FolderInterface) => Promise<void> | void
|
||||
}
|
||||
|
||||
export const NewFolderDrawer = ({ drawerSlug, onNewFolderSuccess }: Props) => {
|
||||
const { config } = useConfig()
|
||||
const { routes, serverURL } = config
|
||||
const { closeModal } = useModal()
|
||||
const { t } = useTranslation()
|
||||
const { folderCollectionSlug, folderFieldName, folderID } = useFolder()
|
||||
|
||||
return (
|
||||
<Drawer gutter={false} Header={null} slug={drawerSlug}>
|
||||
<Form
|
||||
action={`${serverURL}${routes.api}/${folderCollectionSlug}?depth=0`}
|
||||
handleResponse={async (res, successToast, errorToast) => {
|
||||
try {
|
||||
const { doc } = await res.json()
|
||||
successToast(
|
||||
t('general:successfullyCreated', {
|
||||
label: `"${doc.name}"`,
|
||||
}),
|
||||
)
|
||||
await onNewFolderSuccess(doc)
|
||||
} catch (_) {
|
||||
errorToast(t('general:error'))
|
||||
}
|
||||
}}
|
||||
initialState={{
|
||||
name: {
|
||||
initialValue: '',
|
||||
valid: true,
|
||||
validate: (value) => {
|
||||
if (!value) {
|
||||
return t('validation:required')
|
||||
}
|
||||
return true
|
||||
},
|
||||
value: '',
|
||||
},
|
||||
[folderFieldName]: {
|
||||
initialValue: '',
|
||||
valid: true,
|
||||
value: '',
|
||||
},
|
||||
}}
|
||||
method="POST"
|
||||
>
|
||||
<DrawerActionHeader
|
||||
onCancel={() => {
|
||||
closeModal(drawerSlug)
|
||||
}}
|
||||
saveLabel={t('general:create')}
|
||||
title={t('folder:newFolder')}
|
||||
/>
|
||||
|
||||
<DrawerContentContainer>
|
||||
<TextField
|
||||
field={{
|
||||
name: 'name',
|
||||
label: t('folder:folderName'),
|
||||
required: true,
|
||||
}}
|
||||
path="name"
|
||||
validate={(value) => {
|
||||
if (!value) {
|
||||
return t('validation:required')
|
||||
}
|
||||
return true
|
||||
}}
|
||||
/>
|
||||
<HiddenField key={folderID} path={folderFieldName} value={folderID} />
|
||||
</DrawerContentContainer>
|
||||
</Form>
|
||||
</Drawer>
|
||||
)
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
'use client'
|
||||
import type { FolderOrDocument } from 'payload/shared'
|
||||
|
||||
import { useModal } from '@faceless-ui/modal'
|
||||
import React from 'react'
|
||||
|
||||
import { TextField } from '../../../../fields/Text/index.js'
|
||||
import { Form } from '../../../../forms/Form/index.js'
|
||||
import { useConfig } from '../../../../providers/Config/index.js'
|
||||
import { useFolder } from '../../../../providers/Folders/index.js'
|
||||
import { useTranslation } from '../../../../providers/Translation/index.js'
|
||||
import { Drawer } from '../../../Drawer/index.js'
|
||||
import { DrawerContentContainer } from '../../../DrawerContentContainer/index.js'
|
||||
import { DrawerHeader } from '../DrawerHeader/index.js'
|
||||
|
||||
type Props = {
|
||||
readonly drawerSlug: string
|
||||
readonly folderToRename: FolderOrDocument
|
||||
readonly onRenameConfirm: ({
|
||||
folderID,
|
||||
updatedName,
|
||||
}: {
|
||||
folderID: number | string
|
||||
updatedName: string
|
||||
}) => void
|
||||
}
|
||||
export function RenameFolderDrawer(props: Props) {
|
||||
const { drawerSlug, folderToRename, onRenameConfirm } = props
|
||||
const { t } = useTranslation()
|
||||
const { folderCollectionConfig, folderCollectionSlug } = useFolder()
|
||||
const { config } = useConfig()
|
||||
const { closeModal } = useModal()
|
||||
const { routes, serverURL } = config
|
||||
|
||||
const folderName = folderToRename.value._folderOrDocumentTitle
|
||||
const folderID = folderToRename.value.id
|
||||
const folderUseAsTitle = folderCollectionConfig.admin.useAsTitle
|
||||
|
||||
return (
|
||||
<Drawer gutter={false} Header={null} slug={drawerSlug}>
|
||||
<Form
|
||||
action={`${serverURL}${routes.api}/${folderCollectionSlug}/${folderToRename.value.id}?depth=0`}
|
||||
initialState={{
|
||||
name: {
|
||||
initialValue: folderName,
|
||||
valid: true,
|
||||
validate: (value) => {
|
||||
if (!value) {
|
||||
return t('validation:required')
|
||||
}
|
||||
return true
|
||||
},
|
||||
value: folderName,
|
||||
},
|
||||
}}
|
||||
method="PATCH"
|
||||
onSuccess={(data: { doc: FolderOrDocument['value'] }) => {
|
||||
return onRenameConfirm({
|
||||
folderID,
|
||||
updatedName: data?.doc?.[folderUseAsTitle],
|
||||
})
|
||||
}}
|
||||
>
|
||||
<DrawerHeader onCancel={() => closeModal(drawerSlug)} title={t('folder:renameFolder')} />
|
||||
|
||||
<DrawerContentContainer>
|
||||
<TextField
|
||||
field={{
|
||||
name: 'name',
|
||||
label: t('folder:folderName'),
|
||||
required: true,
|
||||
}}
|
||||
path="name"
|
||||
validate={(value) => {
|
||||
if (!value) {
|
||||
return t('validation:required')
|
||||
}
|
||||
return true
|
||||
}}
|
||||
/>
|
||||
</DrawerContentContainer>
|
||||
</Form>
|
||||
</Drawer>
|
||||
)
|
||||
}
|
||||
@@ -10,8 +10,7 @@ import { useConfig } from '../../../providers/Config/index.js'
|
||||
import { useFolder } from '../../../providers/Folders/index.js'
|
||||
import { useTranslation } from '../../../providers/Translation/index.js'
|
||||
import { Button } from '../../Button/index.js'
|
||||
import { DocumentDrawer } from '../../DocumentDrawer/index.js'
|
||||
import { NewFolderDrawer } from '../../FolderView/Drawers/NewFolder/index.js'
|
||||
import { DocumentDrawer, useDocumentDrawer } from '../../DocumentDrawer/index.js'
|
||||
import { Popup, PopupList } from '../../Popup/index.js'
|
||||
|
||||
const baseClass = 'create-new-doc-in-folder'
|
||||
@@ -30,12 +29,15 @@ export function ListCreateNewDocInFolderButton({
|
||||
}) => Promise<void> | void
|
||||
slugPrefix: string
|
||||
}) {
|
||||
const newFolderDrawerSlug = `${slugPrefix}-new-folder-drawer`
|
||||
const newDocInFolderDrawerSlug = `${slugPrefix}-new-doc-in-folder-drawer`
|
||||
const { i18n } = useTranslation()
|
||||
const { closeModal, openModal } = useModal()
|
||||
const { config } = useConfig()
|
||||
const { folderCollectionConfig, folderFieldName, folderID } = useFolder()
|
||||
const { folderCollectionConfig, folderCollectionSlug, folderFieldName, folderID } = useFolder()
|
||||
const [FolderDocumentDrawer, , { closeDrawer: closeFolderDrawer, openDrawer: openFolderDrawer }] =
|
||||
useDocumentDrawer({
|
||||
collectionSlug: folderCollectionSlug,
|
||||
})
|
||||
const [createCollectionSlug, setCreateCollectionSlug] = React.useState<string | undefined>()
|
||||
const [enabledCollections] = React.useState<ClientCollectionConfig[]>(() =>
|
||||
collectionSlugs.reduce((acc, collectionSlug) => {
|
||||
@@ -61,7 +63,7 @@ export function ListCreateNewDocInFolderButton({
|
||||
el="div"
|
||||
onClick={() => {
|
||||
if (enabledCollections[0].slug === folderCollectionConfig.slug) {
|
||||
openModal(newFolderDrawerSlug)
|
||||
openFolderDrawer()
|
||||
} else {
|
||||
setCreateCollectionSlug(enabledCollections[0].slug)
|
||||
openModal(newDocInFolderDrawerSlug)
|
||||
@@ -94,7 +96,7 @@ export function ListCreateNewDocInFolderButton({
|
||||
key={index}
|
||||
onClick={() => {
|
||||
if (collection.slug === folderCollectionConfig.slug) {
|
||||
openModal(newFolderDrawerSlug)
|
||||
openFolderDrawer()
|
||||
} else {
|
||||
setCreateCollectionSlug(collection.slug)
|
||||
openModal(newDocInFolderDrawerSlug)
|
||||
@@ -128,17 +130,20 @@ export function ListCreateNewDocInFolderButton({
|
||||
)}
|
||||
|
||||
{collectionSlugs.includes(folderCollectionConfig.slug) && (
|
||||
<NewFolderDrawer
|
||||
drawerSlug={newFolderDrawerSlug}
|
||||
onNewFolderSuccess={(doc) => {
|
||||
closeModal(newFolderDrawerSlug)
|
||||
<FolderDocumentDrawer
|
||||
initialData={{
|
||||
[folderFieldName]: folderID,
|
||||
}}
|
||||
onSave={(result) => {
|
||||
if (typeof onCreateSuccess === 'function') {
|
||||
void onCreateSuccess({
|
||||
collectionSlug: folderCollectionConfig.slug,
|
||||
doc,
|
||||
doc: result.doc,
|
||||
})
|
||||
}
|
||||
closeFolderDrawer()
|
||||
}}
|
||||
redirectAfterCreate={false}
|
||||
/>
|
||||
)}
|
||||
</React.Fragment>
|
||||
|
||||
@@ -58,7 +58,6 @@ export {
|
||||
useBulkUpload,
|
||||
useBulkUploadDrawerSlug,
|
||||
} from '../../elements/BulkUpload/index.js'
|
||||
export { DrawerActionHeader } from '../../elements/DrawerActionHeader/index.js'
|
||||
export { DrawerContentContainer } from '../../elements/DrawerContentContainer/index.js'
|
||||
export type { BulkUploadProps } from '../../elements/BulkUpload/index.js'
|
||||
export { Banner } from '../../elements/Banner/index.js'
|
||||
|
||||
@@ -9,8 +9,8 @@ import { toast } from 'sonner'
|
||||
|
||||
import { DeleteMany_v4 } from '../../../elements/DeleteMany/index.js'
|
||||
import { EditMany_v4 } from '../../../elements/EditMany/index.js'
|
||||
import { EditFolderAction } from '../../../elements/FolderView/Drawers/EditFolderAction/index.js'
|
||||
import { MoveItemsToFolderDrawer } from '../../../elements/FolderView/Drawers/MoveToFolder/index.js'
|
||||
import { RenameFolderDrawer } from '../../../elements/FolderView/Drawers/RenameFolder/index.js'
|
||||
import { ListSelection_v4, ListSelectionButton } from '../../../elements/ListSelection/index.js'
|
||||
import { PublishMany_v4 } from '../../../elements/PublishMany/index.js'
|
||||
import { UnpublishMany_v4 } from '../../../elements/UnpublishMany/index.js'
|
||||
@@ -19,7 +19,6 @@ import { useFolder } from '../../../providers/Folders/index.js'
|
||||
import { useTranslation } from '../../../providers/Translation/index.js'
|
||||
|
||||
const moveToFolderDrawerSlug = 'move-to-folder--list'
|
||||
const renameFolderDrawerSlug = 'rename-folder--list'
|
||||
|
||||
type GroupedSelections = {
|
||||
[relationTo: string]: {
|
||||
@@ -41,6 +40,7 @@ export const ListSelection: React.FC<ListSelectionProps> = ({
|
||||
const {
|
||||
clearSelections,
|
||||
currentFolder,
|
||||
folderCollectionConfig,
|
||||
folderCollectionSlug,
|
||||
folderFieldName,
|
||||
folderID,
|
||||
@@ -117,22 +117,17 @@ export const ListSelection: React.FC<ListSelectionProps> = ({
|
||||
</Fragment>
|
||||
),
|
||||
count === 1 && !singleNonFolderCollectionSelected && (
|
||||
<React.Fragment key="rename-folder">
|
||||
<ListSelectionButton onClick={() => openModal(renameFolderDrawerSlug)} type="button">
|
||||
{t('general:rename')}
|
||||
</ListSelectionButton>
|
||||
<RenameFolderDrawer
|
||||
drawerSlug={renameFolderDrawerSlug}
|
||||
folderToRename={items[0]}
|
||||
onRenameConfirm={({ folderID: updatedFolderID, updatedName }) => {
|
||||
renameFolder({
|
||||
folderID: updatedFolderID,
|
||||
newName: updatedName,
|
||||
})
|
||||
closeModal(renameFolderDrawerSlug)
|
||||
}}
|
||||
/>
|
||||
</React.Fragment>
|
||||
<EditFolderAction
|
||||
folderCollectionSlug={folderCollectionSlug}
|
||||
id={groupedSelections[folderCollectionSlug].ids[0]}
|
||||
key="edit-folder-action"
|
||||
onSave={({ doc }) => {
|
||||
renameFolder({
|
||||
folderID: doc.id,
|
||||
newName: doc[folderCollectionConfig.admin.useAsTitle],
|
||||
})
|
||||
}}
|
||||
/>
|
||||
),
|
||||
count > 0 ? (
|
||||
<React.Fragment key={moveToFolderDrawerSlug}>
|
||||
|
||||
@@ -445,6 +445,8 @@ export function DefaultEditView({
|
||||
!documentLockStateRef.current?.hasShownLockedModal &&
|
||||
!isLockExpired
|
||||
|
||||
const isFolderCollection = config.folders && collectionSlug === config.folders?.slug
|
||||
|
||||
return (
|
||||
<main className={classes.filter(Boolean).join(' ')}>
|
||||
<OperationProvider operation={operation}>
|
||||
@@ -460,8 +462,10 @@ export function DefaultEditView({
|
||||
onChange={[onChange]}
|
||||
onSuccess={onSave}
|
||||
>
|
||||
{isInDrawer && <DocumentDrawerHeader drawerSlug={drawerSlug} />}
|
||||
{isLockingEnabled && shouldShowDocumentLockedModal && !isReadOnlyForIncomingUser && (
|
||||
{isInDrawer && (
|
||||
<DocumentDrawerHeader drawerSlug={drawerSlug} showDocumentID={!isFolderCollection} />
|
||||
)}
|
||||
{isLockingEnabled && shouldShowDocumentLockedModal && (
|
||||
<DocumentLocked
|
||||
handleGoBack={() => handleGoBack({ adminRoute, collectionSlug, router })}
|
||||
isActive={shouldShowDocumentLockedModal}
|
||||
@@ -522,7 +526,7 @@ export function DefaultEditView({
|
||||
SaveDraftButton,
|
||||
}}
|
||||
data={savedDocumentData}
|
||||
disableActions={disableActions}
|
||||
disableActions={disableActions || isFolderCollection}
|
||||
disableCreate={disableCreate}
|
||||
EditMenuItems={EditMenuItems}
|
||||
hasPublishPermission={hasPublishPermission}
|
||||
|
||||
@@ -21,6 +21,10 @@ export default buildConfigWithDefaults({
|
||||
// debug: true,
|
||||
collectionOverrides: [
|
||||
({ collection }) => {
|
||||
collection.fields.push({
|
||||
name: 'folderSlug',
|
||||
type: 'text',
|
||||
})
|
||||
return collection
|
||||
},
|
||||
],
|
||||
|
||||
@@ -201,6 +201,7 @@ export interface FolderInterface {
|
||||
hasNextPage?: boolean;
|
||||
totalDocs?: number;
|
||||
};
|
||||
belongsToCollections?: ('posts' | 'media' | 'drafts' | 'autosave' | 'all')[] | null;
|
||||
updatedAt: string;
|
||||
createdAt: string;
|
||||
}
|
||||
@@ -418,6 +419,7 @@ export interface PayloadFoldersSelect<T extends boolean = true> {
|
||||
name?: T;
|
||||
folder?: T;
|
||||
documentsAndFolders?: T;
|
||||
belongsToCollections?: T;
|
||||
updatedAt?: T;
|
||||
createdAt?: T;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user