Skip to content

Commit c558e96

Browse files
🎨 fix download links (#3427)
1 parent f1e2d48 commit c558e96

22 files changed

Lines changed: 267 additions & 315 deletions

File tree

web/common/helpers/getUrlFromAction.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ export const getUrlFromAction = ({
1818
return link?.slug + anchor || ''
1919
}
2020

21-
if (!href && type !== 'downloadableFile') {
21+
if (!href && !(type === 'downloadableFile' || type === 'downloadableImage')) {
2222
console.warn('Missing external url in action:', fileName)
2323
}
2424

web/core/Carousel/CarouselImageItem.tsx

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
1-
import envisTwMerge from '../../twMerge'
2-
import Image, { getPxSmSizes } from '../SanityImage/SanityImage'
3-
import { ImageWithAlt, LinkData } from '../../types/index'
4-
import { DisplayModes } from './Carousel'
5-
import { forwardRef, HTMLAttributes, useEffect, useMemo, useRef } from 'react'
6-
import { PortableTextBlock } from '@portabletext/types'
7-
import { SanityImageObject } from '@sanity/image-url/lib/types/types'
1+
import { ImageWithOverlay } from '@core/Image/ImageWithOverlay'
82
import { BaseLink, ResourceLink } from '@core/Link'
3+
import { mergeRefs } from '@equinor/eds-utils'
4+
import type { PortableTextBlock } from '@portabletext/types'
5+
import type { SanityImageObject } from '@sanity/image-url/lib/types/types'
6+
import { forwardRef, type HTMLAttributes, useEffect, useMemo, useRef } from 'react'
97
import { getUrlFromAction } from '../../common/helpers'
10-
import { getLocaleFromName } from '../../lib/localization'
118
import { ArrowRight } from '../../icons'
12-
import { ImageWithOverlay } from '@core/Image/ImageWithOverlay'
9+
import { getLocaleFromName } from '../../lib/localization'
1310
import Blocks from '../../pageComponents/shared/portableText/Blocks'
14-
import { mergeRefs } from '@equinor/eds-utils'
11+
import envisTwMerge from '../../twMerge'
12+
import type { ImageWithAlt, LinkData } from '../../types/index'
13+
import Image, { getPxSmSizes } from '../SanityImage/SanityImage'
14+
import type { DisplayModes } from './Carousel'
1515

1616
type CarouselImageItemProps = {
1717
type: string
@@ -103,7 +103,9 @@ export const CarouselImageItem = forwardRef<HTMLLIElement, CarouselImageItemProp
103103
<div className="h-full w-full fade-in-black-gradient pt-20 flex items-end rounded-b-md">
104104
<BaseLink
105105
href={url as string}
106-
{...(action.link?.lang && { locale: getLocaleFromName(action.link?.lang) })}
106+
{...(action.link?.lang && {
107+
locale: getLocaleFromName(action.link?.lang),
108+
})}
107109
type={action.type}
108110
className="group flex gap-2"
109111
>
@@ -118,7 +120,7 @@ export const CarouselImageItem = forwardRef<HTMLLIElement, CarouselImageItemProp
118120
return (
119121
<ImageWithOverlay
120122
teaserTitle={captionTeaserTitle}
121-
//@ts-ignore:TODO
123+
//@ts-expect-error:TODO
122124
title={captionTitle as PortableTextBlock[]}
123125
text={captionText}
124126
image={image}
@@ -142,16 +144,21 @@ export const CarouselImageItem = forwardRef<HTMLLIElement, CarouselImageItemProp
142144
>
143145
{caption && (
144146
<Blocks
145-
//@ts-ignore:TODO
147+
//@ts-expect-error:TODO
146148
value={caption}
147149
/>
148150
)}
149151
{action && url && (
150152
<ResourceLink
151153
href={url}
152-
extension={action?.extension}
154+
file={{
155+
...action?.file,
156+
label: action?.label,
157+
}}
153158
showExtensionIcon={true}
154-
{...(action?.link?.lang && { locale: getLocaleFromName(action?.link?.lang) })}
159+
{...(action?.link?.lang && {
160+
locale: getLocaleFromName(action?.link?.lang),
161+
})}
155162
type={action?.type}
156163
variant="fit"
157164
className="mt-4"

web/core/Image/ImageWithOverlay.tsx

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
11
/* eslint-disable @typescript-eslint/ban-ts-comment */
2-
import { forwardRef, HTMLAttributes, useId, useState } from 'react'
3-
import { PortableTextBlock } from '@portabletext/types'
4-
import { ImageWithAlt, LinkData } from '../../types'
5-
import Image, { getPxSmSizes } from '../SanityImage/SanityImage'
6-
import envisTwMerge from '../../twMerge'
7-
import { SanityImageObject } from '@sanity/image-url/lib/types/types'
8-
import { Typography } from '@equinor/eds-core-react'
9-
import { Heading } from '@core/Typography'
10-
import Blocks from '../../pageComponents/shared/portableText/Blocks'
2+
3+
import type { DisplayModes } from '@core/Carousel/Carousel'
114
import { ResourceLink } from '@core/Link'
5+
import { Heading } from '@core/Typography'
6+
import { Typography } from '@equinor/eds-core-react'
7+
import type { PortableTextBlock } from '@portabletext/types'
8+
import type { SanityImageObject } from '@sanity/image-url/lib/types/types'
9+
import { forwardRef, type HTMLAttributes, useId, useState } from 'react'
10+
import { FormattedMessage } from 'react-intl'
1211
import { getUrlFromAction } from '../../common/helpers'
1312
import { getLocaleFromName } from '../../lib/localization'
14-
import { DisplayModes } from '@core/Carousel/Carousel'
15-
import { FormattedMessage } from 'react-intl'
13+
import Blocks from '../../pageComponents/shared/portableText/Blocks'
14+
import envisTwMerge from '../../twMerge'
15+
import type { ImageWithAlt, LinkData } from '../../types'
16+
import Image, { getPxSmSizes } from '../SanityImage/SanityImage'
1617

1718
export type ImageWithOverlayProps = {
1819
image?: SanityImageObject
@@ -53,7 +54,7 @@ export const ImageWithOverlay = forwardRef<HTMLDivElement, ImageWithOverlayProps
5354
{title}
5455
</Typography>
5556
) : (
56-
//@ts-ignore: Checked earlier for undefined title
57+
//@ts-expect-error: Checked earlier for undefined title
5758
<Heading as="h2" variant="h4" className="text-md lg:text-lg" value={title} />
5859
)}
5960
</>
@@ -103,9 +104,14 @@ export const ImageWithOverlay = forwardRef<HTMLDivElement, ImageWithOverlayProps
103104
{action && (
104105
<ResourceLink
105106
href={url as string}
106-
extension={action.extension}
107+
file={{
108+
...action?.file,
109+
label: action?.label,
110+
}}
107111
showExtensionIcon={true}
108-
{...(action.link?.lang && { locale: getLocaleFromName(action.link?.lang) })}
112+
{...(action.link?.lang && {
113+
locale: getLocaleFromName(action.link?.lang),
114+
})}
109115
type={action.type}
110116
variant="fit"
111117
>

web/core/Link/DownloadableLink.tsx

Lines changed: 67 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ import { Typography } from '@core/Typography'
22
import { Modal } from '@sections/Modal'
33
import FriendlyCaptcha from '@templates/forms/FriendlyCaptcha'
44
import { forwardRef, useCallback, useState } from 'react'
5-
import { BsFiletypePdf, BsFiletypeXlsx } from 'react-icons/bs'
5+
//BsFiletypeDoc, BsFiletypeMov,
6+
import { BsFiletypeJpg, BsFiletypePdf, BsFiletypePng, BsFiletypeXls, BsFiletypeXlsx, BsFileZip } from 'react-icons/bs'
67
import { useIntl } from 'react-intl'
78
import { ArrowRight } from '../../icons'
89
import envisTwMerge from '../../twMerge'
@@ -17,25 +18,19 @@ export type DownloadableLinkProps = {
1718
} & Omit<ResourceLinkProps, 'variant'>
1819

1920
const DownloadableLink = forwardRef<HTMLDivElement, DownloadableLinkProps>(function DownloadableLink(
20-
{
21-
children,
22-
fileName,
23-
fileId,
24-
label,
25-
type = 'downloadableFile',
26-
extension,
27-
showExtensionIcon = true,
28-
ariaHideText,
29-
variant = 'fit',
30-
isAttachment = false,
31-
},
21+
{ children, file, type = 'downloadableFile', showExtensionIcon = true, variant = 'fit', isAttachment = false },
3222
ref,
3323
) {
24+
const { label, originalFilename, url, extension } = file || {}
25+
const fileUrl = url
26+
? `${url.replace('cdn.sanity.io', 'cdn.equinor.com')}?${originalFilename.replace(/ /g, '-')}`
27+
: null
3428
const intl = useIntl()
3529
const [showModal, setShowModal] = useState(false)
3630
const [isFriendlyChallengeDone, setIsFriendlyChallengeDone] = useState(false)
37-
const [downloadRequestUrl, setDownloadRequestUrl] = useState(null)
38-
const downloadLabel = label ?? (Array.isArray(children) ? children?.[0] : '')
31+
const assetLabel = label ?? (Array.isArray(children) ? children?.[0] : originalFilename)
32+
const hasIcon = ['pdf', 'png', 'jpg', 'xlsx', 'xls', 'zip']
33+
const openInNewTab = ['pdf', 'png', 'jpg']
3934

4035
const [notHuman, setNotHuman] = useState(false)
4136

@@ -59,92 +54,45 @@ const DownloadableLink = forwardRef<HTMLDivElement, DownloadableLinkProps>(funct
5954
setShowModal(false)
6055
}
6156

62-
const getTranslation = () => {
63-
return intl.formatMessage({
64-
id: 'downloadDocument',
65-
defaultMessage: 'Download document',
66-
})
67-
}
68-
69-
const getContentElements = (children?: React.ReactNode) => {
70-
const textClassNames = `pt-1 grow leading-none`
71-
switch (type) {
72-
case 'downloadableFile':
73-
return extension &&
74-
(extension.toUpperCase() === 'PDF' ||
75-
extension.toUpperCase() === 'XLS' ||
76-
extension.toUpperCase() === 'XLSX') &&
77-
showExtensionIcon ? (
78-
<>
79-
{extension.toUpperCase() === 'PDF' ? (
80-
<BsFiletypePdf title="pdf" size={24} className="mr-2 min-w-6 min-h-6" />
81-
) : (
82-
<BsFiletypeXlsx title="xlsx" size={24} className="mr-2 min-w-6 min-h-6" />
83-
)}
84-
<span
85-
className={textClassNames}
86-
{...(ariaHideText && {
87-
'aria-hidden': true,
88-
})}
89-
>
90-
{children}
91-
</span>
92-
</>
93-
) : (
94-
<span
95-
className={textClassNames}
96-
{...(ariaHideText && {
97-
'aria-hidden': true,
98-
})}
99-
>
100-
{children}
101-
{(extension && !showExtensionIcon) ||
102-
(extension &&
103-
(extension.toUpperCase() !== 'PDF' ||
104-
extension.toUpperCase() !== 'XLS' ||
105-
extension.toUpperCase() !== 'XLSX') &&
106-
showExtensionIcon) ? (
107-
<span>{`(${extension.toUpperCase()})`}</span>
108-
) : null}
109-
</span>
110-
)
57+
const getExtensionIcon = () => {
58+
const iconClassName = 'min-w-5'
59+
switch (extension?.toUpperCase()) {
60+
case 'PDF':
61+
return <BsFiletypePdf title="pdf" size={20} className={iconClassName} />
62+
case 'XLSX':
63+
return <BsFiletypeXlsx title="xlsx" size={20} className={iconClassName} />
64+
case 'PNG':
65+
return <BsFiletypePng title="png" size={20} className={iconClassName} />
66+
case 'JPG':
67+
return <BsFiletypeJpg title="jpg" size={20} className={iconClassName} />
68+
case 'XLS':
69+
return <BsFiletypeXls title="xls" size={20} className={iconClassName} />
70+
case 'ZIP':
71+
return <BsFileZip title="zip" size={20} className={iconClassName} />
11172
default:
112-
return (
113-
<span
114-
className={textClassNames}
115-
{...(ariaHideText && {
116-
'aria-hidden': true,
117-
})}
118-
>
119-
{children}
120-
{extension ? <span>{`(${extension.toUpperCase()})`}</span> : null}
121-
</span>
122-
)
73+
return null
12374
}
12475
}
12576

126-
const handleSuccessfullFriendlyChallenge = useCallback(
127-
async (event: any) => {
128-
const solution = event.detail.response
129-
if (fileId || fileName) {
130-
setIsFriendlyChallengeDone(true)
131-
const response = await fetch('/api/download/getFileUrl', {
132-
body: JSON.stringify({
133-
fileName: fileName,
134-
fileId: fileId,
135-
frcCaptchaSolution: solution,
136-
}),
137-
headers: {
138-
'Content-Type': 'application/json',
139-
},
140-
method: 'POST',
141-
})
142-
const url = await response.json()
143-
setDownloadRequestUrl(url.url)
144-
}
145-
},
146-
[fileName, fileId],
147-
)
77+
const handleSuccessfullFriendlyChallenge = useCallback(async (event: any) => {
78+
const solution = event.detail.response
79+
setIsFriendlyChallengeDone(true)
80+
const response = await fetch('/api/download/getFileUrl', {
81+
body: JSON.stringify({
82+
frcCaptchaSolution: solution,
83+
}),
84+
headers: {
85+
'Content-Type': 'application/json',
86+
},
87+
method: 'POST',
88+
})
89+
console.log('response')
90+
if (!response.ok) {
91+
setNotHuman(true)
92+
}
93+
/* const url = await response.json()
94+
setDownloadRequestUrl(url.url) */
95+
}, [])
14896

14997
const commonResourceLinkWrapperClassName = `
15098
group
@@ -163,6 +111,18 @@ const DownloadableLink = forwardRef<HTMLDivElement, DownloadableLinkProps>(funct
163111
no-underline
164112
${variantClassName[variant]}`
165113

114+
const linkElement = (
115+
<div className="flex gap-1 items-baseline">
116+
{showExtensionIcon && getExtensionIcon()}
117+
<div className="pt-1 leading-none">
118+
{assetLabel}
119+
{extension && (!showExtensionIcon || !hasIcon.includes(extension)) ? (
120+
<span>{`(${extension.toLowerCase()})`}</span>
121+
) : null}
122+
</div>
123+
</div>
124+
)
125+
166126
return (
167127
<div ref={ref}>
168128
<button
@@ -179,9 +139,9 @@ const DownloadableLink = forwardRef<HTMLDivElement, DownloadableLinkProps>(funct
179139
w-fit
180140
underline-offset-2
181141
text-slate-80
182-
text-sm`
142+
text-sm `
183143
}
184-
title={`${getTranslation()}: ${fileName}`}
144+
title={`${assetLabel}`}
185145
aria-haspopup="dialog"
186146
>
187147
<div
@@ -206,10 +166,9 @@ const DownloadableLink = forwardRef<HTMLDivElement, DownloadableLinkProps>(funct
206166
variant === 'stickyMenu'
207167
? 'w-fit group-hover:underline no-underline leading-none align-middle items-end'
208168
: ''
209-
}
210-
`}
169+
}`}
211170
>
212-
{getContentElements(<>{`${downloadLabel}`}</>)}
171+
{linkElement}
213172
</div>
214173
{variant !== 'stickyMenu' && !isAttachment && (
215174
<div className={`flex flex-col px-1 translate-y-[1px]`}>
@@ -241,7 +200,7 @@ const DownloadableLink = forwardRef<HTMLDivElement, DownloadableLinkProps>(funct
241200
id: 'request_download_action_prefix',
242201
defaultMessage: 'Request',
243202
})}
244-
{` ${downloadLabel}`}
203+
{` ${assetLabel}`}
245204
</Typography>
246205
<Typography group="plain" variant="div" className="mb-10">
247206
{intl.formatMessage({
@@ -268,16 +227,15 @@ const DownloadableLink = forwardRef<HTMLDivElement, DownloadableLinkProps>(funct
268227
})}
269228
</Typography>
270229
)}
271-
{downloadRequestUrl && isFriendlyChallengeDone && !notHuman && (
230+
{isFriendlyChallengeDone && !notHuman && (
272231
<BaseLink
273232
className={envisTwMerge(`${commonResourceLinkWrapperClassName}`, 'pt-20')}
274233
type={type}
275-
href={downloadRequestUrl}
234+
href={type === 'downloadableFile' ? fileUrl : url}
276235
{...(extension &&
277-
extension.toLowerCase() === 'pdf' && {
236+
openInNewTab?.includes(extension.toLowerCase()) && {
278237
target: '_blank',
279238
})}
280-
aria-description={fileName}
281239
>
282240
<span
283241
className={`h-full
@@ -288,8 +246,8 @@ const DownloadableLink = forwardRef<HTMLDivElement, DownloadableLinkProps>(funct
288246
gap-x-2
289247
${contentVariantClassName[variant]}`}
290248
>
291-
{getContentElements(`${downloadLabel}`)}
292-
{getArrowElement(extension && extension.toLowerCase() === 'pdf' ? 'externalUrl' : type)}
249+
{linkElement}
250+
{getArrowElement(extension && openInNewTab?.includes(extension.toLowerCase()) ? 'externalUrl' : type)}
293251
</span>
294252

295253
<span className="w-[0%] h-[1px] bg-grey-40 transition-all duration-300 group-hover:w-full" />

0 commit comments

Comments
 (0)