Skip to content

Commit

Permalink
chore(Upload & Value.Upload): share anchor & button (#4376)
Browse files Browse the repository at this point in the history
  • Loading branch information
langz authored Dec 9, 2024
1 parent 82f16f0 commit dc1bf01
Show file tree
Hide file tree
Showing 5 changed files with 205 additions and 43 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,7 @@ export const UploadOnFileDeleteAsync = () => (

export const UploadOnFileClick = () => (
<ComponentBox
scope={{ createMockFile }}
scope={{ createMockFile, createRequest }}
data-visual-test="upload-on-file-click"
>
{() => {
Expand Down
24 changes: 8 additions & 16 deletions packages/dnb-eufemia/src/components/upload/UploadFileListCell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import React, { useRef } from 'react'
import classnames from 'classnames'

// Components
import Anchor from '../../components/Anchor'
import Button from '../button/Button'
import Icon from '../../components/Icon'
import FormStatus from '../../components/FormStatus'
Expand All @@ -29,6 +28,7 @@ import { UploadFile, UploadFileNative } from './types'
import { getPreviousSibling, warn } from '../../shared/component-helper'
import useUpload from './useUpload'
import { getFileTypeFromExtension } from './UploadVerify'
import UploadFileLink from './UploadFileListLink'

// Will be deprecated - and then default to only showing the file icon,
// and not file icon per file extension type
Expand Down Expand Up @@ -188,21 +188,13 @@ const UploadFileListCell = ({
</div>
) : (
<div className="dnb-upload__file-cell__text-container">
{onClick ? (
<Button icon={false} variant="tertiary" onClick={onClick}>
{file.name}
</Button>
) : (
<Anchor
target="_blank"
href={imageUrl}
download={download ? file.name : null}
className="dnb-anchor--no-launch-icon"
rel="noopener noreferrer"
>
{file.name}
</Anchor>
)}
<UploadFileLink
left="small"
text={file.name}
href={imageUrl}
download={download}
onClick={onClick}
/>
</div>
)
}
Expand Down
71 changes: 71 additions & 0 deletions packages/dnb-eufemia/src/components/upload/UploadFileListLink.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import React from 'react'

import Anchor from '../../components/Anchor'
import Button from '../button/Button'
import { SpacingProps } from '../space/types'
import { createSpacingClasses } from '../space/SpacingUtils'
import classNames from 'classnames'

export type UploadFileLinkProps = UploadFileAnchorProps &
UploadFileButtonProps

export const UploadFileLink = (props: UploadFileLinkProps) => {
const { onClick, text, href, download, ...rest } = props
if (onClick)
return <UploadFileButton text={text} onClick={onClick} {...rest} />
return (
<UploadFileAnchor
text={text}
href={href}
download={download}
{...rest}
/>
)
}

export default UploadFileLink

type UploadFileButtonProps = {
text: string
onClick?: () => void
} & SpacingProps

const UploadFileButton = (props: UploadFileButtonProps) => {
const { text, onClick } = props

const spacingClasses = createSpacingClasses(props)
return (
<Button
icon={false}
variant="tertiary"
onClick={onClick}
className={classNames(spacingClasses)}
>
{text}
</Button>
)
}

type UploadFileAnchorProps = {
text: string
href: string
download?: boolean
} & SpacingProps

const UploadFileAnchor = (props: UploadFileAnchorProps) => {
const { text, href, download } = props

const spacingClasses = createSpacingClasses(props)

return (
<Anchor
target="_blank"
href={href}
download={download ? text : null}
className={classNames('dnb-anchor--no-launch-icon', spacingClasses)}
rel="noopener noreferrer"
>
{text}
</Anchor>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import UploadFileLink, { UploadFileLinkProps } from '../UploadFileListLink'
import { fireEvent, render, screen } from '@testing-library/react'
import React from 'react'

global.URL.createObjectURL = jest.fn(() => 'url')

const defaultProps: UploadFileLinkProps = {
text: 'text',
href: 'href',
download: false,
onClick: undefined,
}

describe('UploadFileListLink', () => {
describe('as an anchor', () => {
it('renders the anchor', () => {
render(<UploadFileLink {...defaultProps} />)
expect(document.querySelector('.dnb-button')).not.toBeInTheDocument()
expect(document.querySelector('.dnb-a')).toBeInTheDocument()
})

it('renders the anchor text', () => {
const fileName = 'file.png'

render(<UploadFileLink {...defaultProps} text={fileName} />)
expect(screen.queryByText(fileName)).toBeInTheDocument()
})

it('renders the anchor href', () => {
const fileName = 'file.png'

const href = 'mock-url'

render(
<UploadFileLink {...defaultProps} text={fileName} href={href} />
)

const anchorElement = screen.queryByText(
fileName
) as HTMLAnchorElement
expect(anchorElement.href).toMatch(href)
})

it('renders the download attribute', () => {
const fileName = 'file.png'

render(
<UploadFileLink
{...defaultProps}
text={fileName}
download={true}
/>
)

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

expect(element).toHaveAttribute('download', fileName)
})

it('supports spacing props', () => {
render(<UploadFileLink {...defaultProps} top="large" />)

const element = document.querySelector('.dnb-a')
expect(element).toHaveClass('dnb-space__top--large')
})
})

describe('as a button', () => {
it('renders the button', () => {
render(<UploadFileLink {...defaultProps} onClick={jest.fn()} />)
expect(document.querySelector('.dnb-a')).not.toBeInTheDocument()
expect(document.querySelector('.dnb-button')).toBeInTheDocument()
})

it('renders the button text', () => {
const fileName = 'file.png'

render(
<UploadFileLink
{...defaultProps}
onClick={jest.fn()}
text={fileName}
/>
)
expect(screen.queryByText(fileName)).toBeInTheDocument()
})

it('executes onClick event when button is clicked', () => {
const onClick = jest.fn()

render(<UploadFileLink {...defaultProps} onClick={onClick} />)
const element = document.querySelector('.dnb-button')

fireEvent.click(element)

expect(onClick).toHaveBeenCalledTimes(1)
})

it('supports spacing props', () => {
render(
<UploadFileLink
{...defaultProps}
onClick={jest.fn()}
top="large"
/>
)

const element = document.querySelector('.dnb-button')
expect(element).toHaveClass('dnb-space__top--large')
})
})
})
39 changes: 13 additions & 26 deletions packages/dnb-eufemia/src/extensions/forms/Value/Upload/Upload.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import classnames from 'classnames'
import { useValueProps } from '../../hooks'
import { ValueProps } from '../../types'
import ValueBlock from '../../ValueBlock'
import { Anchor, Button } from '../../../../components'
import Icon from '../../../../components/Icon'
import ListFormat, {
ListFormatProps,
Expand All @@ -16,6 +15,7 @@ import {
} from '../../../../components/upload/UploadVerify'
import { Props as FieldUploadProps } from '../../Field/Upload/Upload'
import { format } from '../../../../components/number-format/NumberUtils'
import { UploadFileLink } from '../../../../components/upload/UploadFileListLink'

export type Props = ValueProps<Array<UploadFile>> &
Omit<ListFormatProps, 'value'> &
Expand Down Expand Up @@ -51,34 +51,21 @@ function Upload(props: Props) {
}

const imageUrl = URL.createObjectURL(file)

const text =
file.name + (displaySize ? ' ' + getSize(file.size) : '')

return (
<span key={index}>
{getIcon(file)}
{onFileClick ? (
<Button
icon={false}
size="small"
variant="tertiary"
className={classnames('dnb-upload__file-cell__title')}
onClick={onFileClickHandler}
left="x-small"
>
{file.name}
{displaySize && getSize(file.size)}
</Button>
) : (
<Anchor
target="_blank"
href={imageUrl}
download={download ? file.name : null}
rel="noopener noreferrer"
className="dnb-anchor--no-launch-icon"
left="x-small"
>
{file.name}
{displaySize && getSize(file.size)}
</Anchor>
)}

<UploadFileLink
left="x-small"
text={text}
href={imageUrl}
download={download}
onClick={onFileClick && onFileClickHandler}
/>
</span>
)
}) || undefined
Expand Down

0 comments on commit dc1bf01

Please sign in to comment.