Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(Upload): define max file size for file type #3859

Merged
merged 22 commits into from
Aug 25, 2024
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,37 @@ export const UploadAcceptedFormats = () => (
</ComponentBox>
)

export const UploadFileMaxSizeBasedOnFileType = () => (
<ComponentBox
data-visual-test="upload-file-max-size-based-on-file-format"
hideCode
>
<Upload
id="upload-file-max-size-based-on-file-format"
fileMaxSize={99}
acceptedFileTypes={[
{ fileType: 'jpg', fileMaxSize: 1 },
{ fileType: 'doc', fileMaxSize: 1 },
{ fileType: 'svg', fileMaxSize: 1 },
{ fileType: 'gif', fileMaxSize: 1 },
{ fileType: 'doc', fileMaxSize: 4 },
{ fileType: 'docx', fileMaxSize: 4 },
{ fileType: 'tiff', fileMaxSize: 5 },
{ fileType: 'tif', fileMaxSize: 5 },
{ fileType: 'html', fileMaxSize: 6 },
{ fileType: 'htm', fileMaxSize: 6 },
{ fileType: 'xls', fileMaxSize: 7 },
{ fileType: 'xlsx', fileMaxSize: 7 },
{ fileType: 'odt' },
{ fileType: 'pdf' },
{ fileType: 'text', fileMaxSize: false },
{ fileType: 'txt', fileMaxSize: 0 },
{ fileType: 'zip', fileMaxSize: 99 },
]}
/>
</ComponentBox>
)

export const UploadDisabledFileMaxSize = () => (
<ComponentBox hideCode>
langz marked this conversation as resolved.
Show resolved Hide resolved
{() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
UploadErrorMessage,
UploadAcceptedFormats,
UploadDisabledFileMaxSize,
UploadFileMaxSizeBasedOnFileType,
} from 'Docs/uilib/components/upload/Examples'

## Demos
Expand Down Expand Up @@ -53,10 +54,14 @@ You can pass the file formats as a string array. This will restrict which files

<UploadPrefilledFileList />

### Upload with file max size based on file type

<UploadFileMaxSizeBasedOnFileType />

### Upload without file max size, and custom error handling of file size

You can disable the file max size, which will deactivate all file size verifications in the Upload component.
This can also be used to manually implement more complex file max size verifications, like file max size based on file type, see the example below:
This can also be used to manually implement more complex file max size verifications, like file max size based on file format/type, see the example below:

<VisibleWhenNotVisualTest>
<UploadDisabledFileMaxSize />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,23 @@ showTabs: true

import TranslationsTable from 'dnb-design-system-portal/src/shared/parts/TranslationsTable'
import PropertiesTable from 'dnb-design-system-portal/src/shared/parts/PropertiesTable'
import { UploadProperties } from '@dnb/eufemia/src/components/upload/UploadDocs'
import {
UploadProperties,
AcceptedFileTypeProperties,
} from '@dnb/eufemia/src/components/upload/UploadDocs'

## Properties

<PropertiesTable props={UploadProperties} />

## AcceptedFileType

The accepted file type object is used to define file max size for specific file types.

When providing a list of AcceptedFileType to [Uploads](/uilib/components/upload/properties/#properties) `acceptedFileTypes`, the accepted file types will be presented in a table(see [example](/uilib/components/upload/demos/#upload-with-file-max-size-based-on-file-type)).
langz marked this conversation as resolved.
Show resolved Hide resolved

<PropertiesTable props={AcceptedFileTypeProperties} />

## Translations

All translation keys listed in the translations table below, can be used as a component property (like `title` or `text`).
Expand Down
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 @@ -54,6 +54,7 @@ const Upload = (localProps: UploadAllProps) => {
onFileDelete, // eslint-disable-line
title, // eslint-disable-line
text, // eslint-disable-line
fileTypeTableCaption, // eslint-disable-line
fileTypeDescription, // eslint-disable-line
fileSizeDescription, // eslint-disable-line
fileAmountDescription, // eslint-disable-line
Expand Down
19 changes: 16 additions & 3 deletions packages/dnb-eufemia/src/components/upload/UploadDocs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { PropertiesTableProps } from '../../shared/types'

export const UploadProperties: PropertiesTableProps = {
acceptedFileTypes: {
doc: 'List of accepted file types.',
type: 'Array<string>',
doc: 'List of accepted file types. Either as string or [AcceptedFileType](/uilib/components/upload/properties/#acceptedfiletype). When providing a list of [AcceptedFileType](/uilib/components/upload/properties/#acceptedfiletype), the accepted file types will be presented in a table(see [example](/uilib/components/upload/demos/#upload-with-file-max-size-based-on-file-type)).',
type: ['Array<string>', 'Array<AcceptedFileType>'],
status: 'required',
},
filesAmountLimit: {
Expand All @@ -13,7 +13,7 @@ export const UploadProperties: PropertiesTableProps = {
},
fileMaxSize: {
doc: 'Defines the max file size of each file in MB. Use either `0` or `false` to disable. Defaults to 5 MB.',
type: 'number',
type: ['number', 'false'],
status: 'optional',
},
title: {
Expand All @@ -38,6 +38,19 @@ export const UploadProperties: PropertiesTableProps = {
},
}

export const AcceptedFileTypeProperties: PropertiesTableProps = {
fileType: {
doc: 'The name of the accepted file type.',
type: 'string',
status: 'required',
},
fileMaxSize: {
doc: 'Defines the max file size of the given file type in MB. Use either `0` or `false` to disable. If not provided, it defaults to the value of [Uploads](/uilib/components/upload/properties/#properties) `fileMaxSize` which defaults to 5 MB.',
type: ['number', 'false'],
status: 'optional',
},
}

export const UploadEvents: PropertiesTableProps = {
onChange: {
doc: 'Will be called on `files` changes made by the user. Access the files with `{ files }` (containing each a `fileItem`).',
Expand Down
180 changes: 145 additions & 35 deletions packages/dnb-eufemia/src/components/upload/UploadInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,15 @@ import Dl from '../../elements/Dl'
import Dt from '../../elements/Dt'
import Dd from '../../elements/Dd'
import { format } from '../number-format/NumberUtils'
import { isArrayOfObjects, isArrayOfStrings } from './UploadVerify'
import Table from '../Table'
import Tr from '../table/TableTr'
import Th from '../table/TableTh'
import Td from '../table/TableTd'
import { UploadAcceptedFileTypeObject, UploadProps } from './types'

const prettifyAcceptedFileFormats = (acceptedFileTypes) =>
acceptedFileTypes.sort().join(', ').toUpperCase()

const UploadInfo = () => {
const context = React.useContext(UploadContext)
Expand All @@ -23,9 +32,28 @@ const UploadInfo = () => {
children,
} = context

const prettifiedAcceptedFileFormats = acceptedFileTypes
.join(', ')
.toUpperCase()
const prettifiedAcceptedFileFormats =
prettifyAcceptedFileFormats(acceptedFileTypes)

const isAcceptedFileTypeListOfStrings =
isArrayOfStrings(acceptedFileTypes)

const displayAcceptedFileFormatsListItem =
isAcceptedFileTypeListOfStrings && prettifiedAcceptedFileFormats

const displayFileMaxSizeItem =
isAcceptedFileTypeListOfStrings && fileMaxSize !== 0 && fileMaxSize

const displayFilesAmountLimitItem =
filesAmountLimit < defaultProps.filesAmountLimit

const displayAcceptedFileFormatsTable =
isArrayOfObjects(acceptedFileTypes)

const displayDl =
displayAcceptedFileFormatsListItem ||
displayFileMaxSizeItem ||
displayFilesAmountLimitItem

return (
<>
Expand All @@ -37,40 +65,122 @@ const UploadInfo = () => {

{children}

<Dl
top="small"
bottom={0}
layout="horizontal"
className="dnb-upload__condition-list"
>
{prettifiedAcceptedFileFormats && (
<Dl.Item>
<Dt>{fileTypeDescription}</Dt>
<Dd>{prettifiedAcceptedFileFormats}</Dd>
</Dl.Item>
)}

{fileMaxSize && (
<Dl.Item>
<Dt>{fileSizeDescription}</Dt>
<Dd>
{String(fileSizeContent).replace(
'%size',
format(fileMaxSize).toString()
)}
</Dd>
</Dl.Item>
)}

{filesAmountLimit < defaultProps.filesAmountLimit && (
<Dl.Item>
<Dt>{fileAmountDescription}</Dt>
<Dd>{filesAmountLimit}</Dd>
</Dl.Item>
)}
</Dl>
{displayDl && (
<Dl top="small" bottom={0} layout="horizontal">
{displayAcceptedFileFormatsListItem && (
<Dl.Item>
<Dt>{fileTypeDescription}</Dt>
<Dd>{prettifiedAcceptedFileFormats}</Dd>
</Dl.Item>
)}

{displayFileMaxSizeItem && (
<Dl.Item>
<Dt>{fileSizeDescription}</Dt>
<Dd>
{String(fileSizeContent).replace(
'%size',
format(fileMaxSize).toString()
)}
</Dd>
</Dl.Item>
)}

{displayFilesAmountLimitItem && (
<Dl.Item>
<Dt>{fileAmountDescription}</Dt>
<Dd>{filesAmountLimit}</Dd>
</Dl.Item>
)}
</Dl>
)}
{displayAcceptedFileFormatsTable && (
<UploadInfoAcceptedFileTypesTable />
)}
</>
)
}

function UploadInfoAcceptedFileTypesTable() {
const context = React.useContext(UploadContext)

const {
acceptedFileTypes,
fileTypeTableCaption,
fileTypeDescription,
fileSizeDescription,
fileSizeContent,
fileMaxSize,
} = context

const groupByFileMaxSize = (
acceptedFileTypes: UploadProps['acceptedFileTypes'],
fallBackFileMaxSize: UploadProps['fileMaxSize']
) => {
const group = {}
acceptedFileTypes.forEach((item) => {
const itemFileMaxSize = item.fileMaxSize
const groupName =
itemFileMaxSize === false || itemFileMaxSize === 0
? 0
: itemFileMaxSize
? itemFileMaxSize
: fallBackFileMaxSize === false || fallBackFileMaxSize === 0
? 0
: fallBackFileMaxSize
langz marked this conversation as resolved.
Show resolved Hide resolved
group[groupName] = group[groupName] || []
group[groupName].push(item)
})

return group
}

const acceptedFileTypesGroupedByFileMaxSize = groupByFileMaxSize(
acceptedFileTypes,
fileMaxSize
)

return (
<Table
border
className="dnb-upload__accepted-file-types-table"
size="small"
>
<caption className="dnb-sr-only">{fileTypeTableCaption}</caption>
<thead>
<Tr variant="odd" cellSpacing={0}>
<Th>{fileTypeDescription}</Th>
<Th>{fileSizeDescription}</Th>
</Tr>
</thead>
<tbody>
{Object.keys(acceptedFileTypesGroupedByFileMaxSize)
.sort((a, b) => Number(b) - Number(a))
.map((key) => {
return (
<Tr variant="odd" key={key}>
<Td>
{prettifyAcceptedFileFormats(
acceptedFileTypesGroupedByFileMaxSize[key].map(
(
acceptedFileTypesObj: UploadAcceptedFileTypeObject
) => acceptedFileTypesObj.fileType
)
)}
</Td>
<Td>
{key !== '0' &&
String(fileSizeContent).replace(
'%size',
format(key).toString()
)}
</Td>
</Tr>
)
})}
</tbody>
</Table>
)
}

export default UploadInfo
Loading
Loading