Skip to content

Commit a76be81

Browse files
fix: upload has many field updates (#7894)
## Description Implements fixes and style changes for the upload field component. Fixes #7819 ![CleanShot 2024-08-27 at 16 22 33](https://github.com/user-attachments/assets/fa27251c-20b8-45ad-9109-55dee2e19e2f) ![CleanShot 2024-08-27 at 16 22 49](https://github.com/user-attachments/assets/de2d24f9-b2f5-4b72-abbe-24a6c56a4c21) - [x] I have read and understand the [CONTRIBUTING.md](https://github.com/payloadcms/payload/blob/main/CONTRIBUTING.md) document in this repository. ## Type of change - [ ] Chore (non-breaking change which does not add functionality) - [x] Bug fix (non-breaking change which fixes an issue) - [x] New feature (non-breaking change which adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) - [ ] Change to the [templates](https://github.com/payloadcms/payload/tree/main/templates) directory (does not affect core functionality) - [ ] Change to the [examples](https://github.com/payloadcms/payload/tree/main/examples) directory (does not affect core functionality) - [ ] This change requires a documentation update ## Checklist: - [ ] I have added tests that prove my fix is effective or that my feature works - [ ] Existing test suite passes locally with my changes - [ ] I have made corresponding changes to the documentation --------- Co-authored-by: Paul Popus <paul@nouance.io>
1 parent 5d97d57 commit a76be81

File tree

46 files changed

+1906
-1487
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+1906
-1487
lines changed

packages/next/src/templates/Default/index.tsx

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { MappedComponent, ServerProps, VisibleEntities } from 'payload'
22

3-
import { AppHeader, EntityVisibilityProvider, NavToggler } from '@payloadcms/ui'
3+
import { AppHeader, BulkUploadProvider, EntityVisibilityProvider, NavToggler } from '@payloadcms/ui'
44
import { RenderComponent, getCreateMappedComponent } from '@payloadcms/ui/shared'
55
import React from 'react'
66

@@ -59,21 +59,23 @@ export const DefaultTemplate: React.FC<DefaultTemplateProps> = ({
5959

6060
return (
6161
<EntityVisibilityProvider visibleEntities={visibleEntities}>
62-
<div>
63-
<div className={`${baseClass}__nav-toggler-wrapper`} id="nav-toggler">
64-
<NavToggler className={`${baseClass}__nav-toggler`}>
65-
<NavHamburger />
66-
</NavToggler>
67-
</div>
68-
<Wrapper baseClass={baseClass} className={className}>
69-
<RenderComponent mappedComponent={MappedDefaultNav} />
70-
71-
<div className={`${baseClass}__wrap`}>
72-
<AppHeader />
73-
{children}
62+
<BulkUploadProvider>
63+
<div>
64+
<div className={`${baseClass}__nav-toggler-wrapper`} id="nav-toggler">
65+
<NavToggler className={`${baseClass}__nav-toggler`}>
66+
<NavHamburger />
67+
</NavToggler>
7468
</div>
75-
</Wrapper>
76-
</div>
69+
<Wrapper baseClass={baseClass} className={className}>
70+
<RenderComponent mappedComponent={MappedDefaultNav} />
71+
72+
<div className={`${baseClass}__wrap`}>
73+
<AppHeader />
74+
{children}
75+
</div>
76+
</Wrapper>
77+
</div>
78+
</BulkUploadProvider>
7779
</EntityVisibilityProvider>
7880
)
7981
}

packages/next/src/views/List/Default/index.tsx

Lines changed: 15 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import type { ClientCollectionConfig } from 'payload'
44

55
import { getTranslation } from '@payloadcms/translations'
66
import {
7-
BulkUploadDrawer,
87
Button,
98
DeleteMany,
109
EditMany,
@@ -14,7 +13,6 @@ import {
1413
ListSelection,
1514
Pagination,
1615
PerPage,
17-
PopupList,
1816
PublishMany,
1917
RelationshipProvider,
2018
RenderComponent,
@@ -24,7 +22,7 @@ import {
2422
Table,
2523
UnpublishMany,
2624
ViewDescription,
27-
bulkUploadDrawerSlug,
25+
useBulkUpload,
2826
useConfig,
2927
useEditDepth,
3028
useListInfo,
@@ -60,6 +58,8 @@ export const DefaultListView: React.FC = () => {
6058
const { searchParams } = useSearchParams()
6159
const { openModal } = useModal()
6260
const { clearRouteCache } = useRouteCache()
61+
const { setCollectionSlug, setOnSuccess } = useBulkUpload()
62+
const { drawerSlug } = useBulkUpload()
6363

6464
const { getEntityConfig } = useConfig()
6565

@@ -106,6 +106,12 @@ export const DefaultListView: React.FC = () => {
106106
})
107107
}
108108

109+
const openBulkUpload = React.useCallback(() => {
110+
setCollectionSlug(collectionSlug)
111+
openModal(drawerSlug)
112+
setOnSuccess(clearRouteCache)
113+
}, [clearRouteCache, collectionSlug, drawerSlug, openModal, setCollectionSlug, setOnSuccess])
114+
109115
useEffect(() => {
110116
if (drawerDepth <= 1) {
111117
setStepNav([
@@ -116,6 +122,8 @@ export const DefaultListView: React.FC = () => {
116122
}
117123
}, [setStepNav, labels, drawerDepth])
118124

125+
const isBulkUploadEnabled = isUploadCollection && collectionConfig.upload.bulkUpload
126+
119127
return (
120128
<div className={`${baseClass} ${baseClass}--${collectionSlug}`}>
121129
<SetViewActions actions={actions} />
@@ -126,23 +134,15 @@ export const DefaultListView: React.FC = () => {
126134
<ListHeader heading={getTranslation(labels?.plural, i18n)}>
127135
{hasCreatePermission && (
128136
<Button
129-
Link={Link}
130-
SubMenuPopupContent={
131-
isUploadCollection && collectionConfig.upload.bulkUpload ? (
132-
<PopupList.ButtonGroup>
133-
<PopupList.Button onClick={() => openModal(bulkUploadDrawerSlug)}>
134-
{t('upload:bulkUpload')}
135-
</PopupList.Button>
136-
</PopupList.ButtonGroup>
137-
) : null
138-
}
137+
Link={!isBulkUploadEnabled ? Link : undefined}
139138
aria-label={i18n.t('general:createNewLabel', {
140139
label: getTranslation(labels?.singular, i18n),
141140
})}
142141
buttonStyle="pill"
143-
el="link"
142+
el={!isBulkUploadEnabled ? 'link' : 'button'}
143+
onClick={isBulkUploadEnabled ? openBulkUpload : undefined}
144144
size="small"
145-
to={newDocumentURL}
145+
to={!isBulkUploadEnabled ? newDocumentURL : undefined}
146146
>
147147
{i18n.t('general:createNew')}
148148
</Button>
@@ -155,12 +155,6 @@ export const DefaultListView: React.FC = () => {
155155
<ViewDescription Description={Description} description={description} />
156156
</div>
157157
)}
158-
{isUploadCollection && collectionConfig.upload.bulkUpload ? (
159-
<BulkUploadDrawer
160-
collectionSlug={collectionSlug}
161-
onSuccess={() => clearRouteCache()}
162-
/>
163-
) : null}
164158
</ListHeader>
165159
)}
166160
<ListControls collectionConfig={collectionConfig} fields={fields} />

packages/plugin-seo/src/fields/MetaImage/MetaImageComponent.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
'use client'
22

3-
import type { FieldType, Options, UploadFieldProps } from '@payloadcms/ui'
3+
import type { FieldType, Options } from '@payloadcms/ui'
4+
import type { UploadFieldProps } from 'payload'
45

56
import {
67
FieldLabel,
@@ -156,6 +157,7 @@ export const MetaImageComponent: React.FC<MetaImageProps> = (props) => {
156157
setValue(null)
157158
}
158159
}}
160+
path={field.path}
159161
relationTo={relationTo}
160162
required={required}
161163
serverURL={serverURL}

packages/ui/src/elements/BulkUpload/AddFilesView/index.scss

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,22 @@
77
height: 100%;
88
padding: calc(var(--base) * 2) var(--gutter-h);
99
}
10-
10+
1111
.dropzone {
1212
flex-direction: column;
1313
justify-content: center;
14+
display: flex;
15+
gap: var(--base);
16+
background-color: var(--theme-elevation-50);
17+
18+
p {
19+
margin: 0;
20+
}
21+
}
22+
23+
&__dragAndDropText {
24+
margin: 0;
25+
text-transform: lowercase;
26+
align-self: center;
1427
}
1528
}

packages/ui/src/elements/BulkUpload/AddFilesView/index.tsx

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import React from 'react'
44

55
import { useTranslation } from '../../../providers/Translation/index.js'
6+
import { Button } from '../../Button/index.js'
67
import { Dropzone } from '../../Dropzone/index.js'
78
import { DrawerHeader } from '../Header/index.js'
89
import './index.scss'
@@ -16,11 +17,43 @@ type Props = {
1617
export function AddFilesView({ onCancel, onDrop }: Props) {
1718
const { t } = useTranslation()
1819

20+
const inputRef = React.useRef(null)
21+
1922
return (
2023
<div className={baseClass}>
2124
<DrawerHeader onClose={onCancel} title={t('upload:addFiles')} />
2225
<div className={`${baseClass}__dropArea`}>
23-
<Dropzone multipleFiles onChange={onDrop} />
26+
<Dropzone multipleFiles onChange={onDrop}>
27+
<Button
28+
buttonStyle="pill"
29+
iconPosition="left"
30+
onClick={() => {
31+
if (inputRef.current) {
32+
inputRef.current.click()
33+
}
34+
}}
35+
size="small"
36+
>
37+
{t('upload:selectFile')}
38+
</Button>
39+
<input
40+
aria-hidden="true"
41+
className={`${baseClass}__hidden-input`}
42+
hidden
43+
onChange={(e) => {
44+
if (e.target.files && e.target.files.length > 0) {
45+
onDrop(e.target.files)
46+
}
47+
}}
48+
ref={inputRef}
49+
type="file"
50+
/>
51+
52+
<p className={`${baseClass}__dragAndDropText`}>
53+
{t('general:or')} {t('upload:dragAndDrop')}
54+
</p>
55+
</Dropzone>
56+
{/* <Dropzone multipleFiles onChange={onDrop} /> */}
2457
</div>
2558
</div>
2659
)

packages/ui/src/elements/BulkUpload/AddingFilesView/index.tsx

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { useConfig } from '../../../providers/Config/index.js'
99
import { DocumentInfoProvider } from '../../../providers/DocumentInfo/index.js'
1010
import { useTranslation } from '../../../providers/Translation/index.js'
1111
import { ActionsBar } from '../ActionsBar/index.js'
12-
import { discardBulkUploadModalSlug } from '../DiscardWithoutSaving/index.js'
12+
import { DiscardWithoutSaving, discardBulkUploadModalSlug } from '../DiscardWithoutSaving/index.js'
1313
import { EditForm } from '../EditForm/index.js'
1414
import { FileSidebar } from '../FileSidebar/index.js'
1515
import { useFormsManager } from '../FormsManager/index.js'
@@ -44,20 +44,24 @@ export function AddingFilesView() {
4444
onClose={() => openModal(discardBulkUploadModalSlug)}
4545
title={getTranslation(collection.labels.singular, i18n)}
4646
/>
47-
<DocumentInfoProvider
48-
collectionSlug={collectionSlug}
49-
docPermissions={docPermissions}
50-
hasPublishPermission={hasPublishPermission}
51-
hasSavePermission={hasSavePermission}
52-
id={null}
53-
initialData={reduceFieldsToValues(activeForm.formState, true)}
54-
initialState={activeForm.formState}
55-
key={`${activeIndex}-${forms.length}`}
56-
>
57-
<ActionsBar />
58-
<EditForm submitted={hasSubmitted} />
59-
</DocumentInfoProvider>
47+
{activeForm ? (
48+
<DocumentInfoProvider
49+
collectionSlug={collectionSlug}
50+
docPermissions={docPermissions}
51+
hasPublishPermission={hasPublishPermission}
52+
hasSavePermission={hasSavePermission}
53+
id={null}
54+
initialData={reduceFieldsToValues(activeForm.formState, true)}
55+
initialState={activeForm.formState}
56+
key={`${activeIndex}-${forms.length}`}
57+
>
58+
<ActionsBar />
59+
<EditForm submitted={hasSubmitted} />
60+
</DocumentInfoProvider>
61+
) : null}
6062
</div>
63+
64+
<DiscardWithoutSaving />
6165
</div>
6266
)
6367
}

packages/ui/src/elements/BulkUpload/DiscardWithoutSaving/index.tsx

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,18 @@
33
import { useModal } from '@faceless-ui/modal'
44
import React from 'react'
55

6-
import { useEditDepth } from '../../../providers/EditDepth/index.js'
76
import { useTranslation } from '../../../providers/Translation/index.js'
87
import { Button } from '../../Button/index.js'
98
import { FullscreenModal } from '../../FullscreenModal/index.js'
10-
import { drawerSlug } from '../index.js'
9+
import { useBulkUpload } from '../index.js'
1110

1211
export const discardBulkUploadModalSlug = 'bulk-upload--discard-without-saving'
1312
const baseClass = 'leave-without-saving'
1413

1514
export function DiscardWithoutSaving() {
1615
const { t } = useTranslation()
17-
const editDepth = useEditDepth()
1816
const { closeModal } = useModal()
17+
const { drawerSlug } = useBulkUpload()
1918

2019
const onCancel = React.useCallback(() => {
2120
closeModal(discardBulkUploadModalSlug)
@@ -24,16 +23,10 @@ export function DiscardWithoutSaving() {
2423
const onConfirm = React.useCallback(() => {
2524
closeModal(drawerSlug)
2625
closeModal(discardBulkUploadModalSlug)
27-
}, [closeModal])
26+
}, [closeModal, drawerSlug])
2827

2928
return (
30-
<FullscreenModal
31-
className={baseClass}
32-
slug={discardBulkUploadModalSlug}
33-
style={{
34-
zIndex: `calc(100 + ${editDepth || 0} + 1)`,
35-
}}
36-
>
29+
<FullscreenModal className={baseClass} slug={discardBulkUploadModalSlug}>
3730
<div className={`${baseClass}__wrapper`}>
3831
<div className={`${baseClass}__content`}>
3932
<h1>{t('general:leaveWithoutSaving')}</h1>

packages/ui/src/elements/BulkUpload/DrawerCloseButton/index.tsx

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,12 @@ const baseClass = 'drawer-close-button'
99

1010
type Props = {
1111
readonly onClick: () => void
12-
readonly slug: string
1312
}
14-
export function DrawerCloseButton({ slug, onClick }: Props) {
13+
export function DrawerCloseButton({ onClick }: Props) {
1514
const { t } = useTranslation()
1615

1716
return (
18-
<button
19-
aria-label={t('general:close')}
20-
className={baseClass}
21-
id={`close-drawer__${slug}`}
22-
onClick={onClick}
23-
type="button"
24-
>
17+
<button aria-label={t('general:close')} className={baseClass} onClick={onClick} type="button">
2518
<XIcon />
2619
</button>
2720
)

0 commit comments

Comments
 (0)