Skip to content

Commit

Permalink
feat(Upload): add download prop to enable file downloads instead of…
Browse files Browse the repository at this point in the history
… opening in a new tab (#4213)

Co-authored-by: -l <anderslangseth@gmail.com>
  • Loading branch information
tujoworker and langz authored Nov 6, 2024
1 parent b24fdfd commit 3e92934
Show file tree
Hide file tree
Showing 9 changed files with 96 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,9 @@ By default, the Upload component accepts multiple files. You can use the propert
Once the Upload component mounts, it also adds support for dropping files to the entire browser body.

**NB:** When you have several mounted components, only the first Upload component will receive the dropped files.

## The `download` property

Each file item is displayed as a clickable link with its original file name, which opens the file source in a new browser tab.

In some situations, it's more suitable to have each link download the file instead of opening it in a new browser tab. To achieve this, set the `download={true}` property on the Upload component.
1 change: 1 addition & 0 deletions packages/dnb-eufemia/src/components/upload/Upload.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ const Upload = (localProps: UploadAllProps) => {
fileMaxSize,
onChange,
onFileDelete, // eslint-disable-line
download, // eslint-disable-line
title, // eslint-disable-line
text, // eslint-disable-line
fileTypeTableCaption, // eslint-disable-line
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { UploadContextProps } from './types'
export const defaultProps = {
fileMaxSize: 5,
filesAmountLimit: 100,
download: false,
}

export const UploadContext = createContext<UploadContextProps>(null)
5 changes: 5 additions & 0 deletions packages/dnb-eufemia/src/components/upload/UploadDocs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ export const UploadProperties: PropertiesTableProps = {
type: 'string',
status: 'optional',
},
download: {
doc: 'Causes the browser to treat all listed files as downloadable instead of opening them in a new browser tab or window. Defaults to `false`.',
type: 'boolean',
status: 'optional',
},
skeleton: {
doc: 'Skeleton should be applied when loading content.',
type: 'boolean',
Expand Down
2 changes: 2 additions & 0 deletions packages/dnb-eufemia/src/components/upload/UploadFileList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ function UploadFileList() {
id,
fileListAriaLabel,
deleteButton,
download,
loadingText,
onFileDelete,
onChange,
Expand Down Expand Up @@ -50,6 +51,7 @@ function UploadFileList() {
onDelete={onDeleteHandler}
deleteButtonText={deleteButton}
loadingText={loadingText}
download={download}
/>
)
})}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@ export type UploadFileListCellProps = {
*/
onDelete: () => void

/**
* Causes the browser to treat all listed files as downloadable instead of opening them in a new browser tab or window.
* Default: false
*/
download?: boolean

/**
* Text
*/
Expand All @@ -62,6 +68,7 @@ const UploadFileListCell = ({
onDelete,
loadingText,
deleteButtonText,
download,
}: UploadFileListCellProps) => {
const { file, errorMessage, isLoading } = uploadFile
const hasWarning = errorMessage != null
Expand Down Expand Up @@ -159,6 +166,7 @@ const UploadFileListCell = ({
<a
target="_blank"
href={imageUrl}
download={download ? file.name : null}
className={classnames(
'dnb-anchor',
'dnb-upload__file-cell__title'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -664,6 +664,56 @@ describe('Upload', () => {
expect(fileCells.length).toBe(files.length)
})

it('treats all the linked URLs of the files as a download when providing download prop', async () => {
const files = [
{ file: createMockFile('fileName.png', 100, 'image/png') },
{ file: createMockFile('fileName2.png', 100, 'image/png') },
{ file: createMockFile('fileName3.png', 100, 'image/png') },
]

const id = 'random-id'

render(<Upload {...defaultProps} id={id} download={true} />)

const MockComponent = () => {
const { setFiles } = useUpload(id)

useEffect(() => setFiles(files), [])

return <div />
}

render(<MockComponent />)

expect(document.querySelectorAll('[download]').length).toBe(
files.length
)
})

it('does not treat linked URLs of the files as a download by default', async () => {
const files = [
{ file: createMockFile('fileName.png', 100, 'image/png') },
{ file: createMockFile('fileName2.png', 100, 'image/png') },
{ file: createMockFile('fileName3.png', 100, 'image/png') },
]

const id = 'random-id'

render(<Upload {...defaultProps} id={id} />)

const MockComponent = () => {
const { setFiles } = useUpload(id)

useEffect(() => setFiles(files), [])

return <div />
}

render(<MockComponent />)

expect(document.querySelectorAll('[download]').length).toBe(0)
})

it('shows no files', async () => {
const files = []

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,23 @@ describe('UploadFileListCell', () => {
expect(element.className).toMatch('dnb-upload__file-cell--warning')
})

it('renders the upload attribute', () => {
render(
<UploadFileListCell
{...defaultProps}
download={true}
uploadFile={{
file: createMockFile('file.png', 100, 'image/png'),
errorMessage: 'error message',
}}
/>
)

const element = document.querySelector('.dnb-upload__file-cell a')

expect(element).toHaveAttribute('download', 'file.png')
})

it('supports special file extensions', async () => {
render(
<UploadFileListCell
Expand Down
6 changes: 6 additions & 0 deletions packages/dnb-eufemia/src/components/upload/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,12 @@ export type UploadProps = {
*/
onFileDelete?: ({ fileItem }: { fileItem: UploadFile }) => void

/**
* Causes the browser to treat all listed files as downloadable instead of opening them in a new browser tab or window.
* Default: false
*/
download?: boolean

/**
* Custom text properties
*/
Expand Down

0 comments on commit 3e92934

Please sign in to comment.