diff --git a/src/components/Link/index.tsx b/src/components/Link/index.tsx index 6339cec2..6196cc0e 100644 --- a/src/components/Link/index.tsx +++ b/src/components/Link/index.tsx @@ -24,6 +24,7 @@ interface Props extends Omit { target?: string; variant?: Variant; title?: React.ReactNode; + download?: boolean; } // NOTE: this does not support relative links @@ -34,6 +35,7 @@ function Link(props: Props) { variant = 'transparent', className, title, + download = false, ...rest } = props; @@ -56,6 +58,23 @@ function Link(props: Props) { } } + let { target, rel } = rest; + if (download) { + // NOTE: the server is configured to set the Content-Disposition + // header for media files when treat_as_download is set, which + // makes the browser download the file instead of opening it. + // NOTE: media URLs do not have query params so we can safely + // append the query param with `?` + if (typeof href === 'string') { + href = `${href}?treat_as_download=true`; + } + // NOTE: fallback for when the server does not handle + // treat_as_download: open the file in a new tab instead of + // navigating away from the page + target = target ?? '_blank'; + rel = rel ?? 'noopener noreferrer'; + } + return ( diff --git a/src/pages/[locale]/data/index.tsx b/src/pages/[locale]/data/index.tsx index d8d3a3b9..782af27c 100644 --- a/src/pages/[locale]/data/index.tsx +++ b/src/pages/[locale]/data/index.tsx @@ -979,6 +979,7 @@ function Data(props: Props) { href={asset.file.url} variant="buttonTransparent" className={styles.link} + download > {t('download')} diff --git a/src/pages/[locale]/projects/[id].tsx b/src/pages/[locale]/projects/[id].tsx index c504542b..ac7b0d76 100644 --- a/src/pages/[locale]/projects/[id].tsx +++ b/src/pages/[locale]/projects/[id].tsx @@ -1,5 +1,4 @@ import React, { - useCallback, useEffect, useState, useMemo, @@ -27,7 +26,6 @@ import OgMeta from 'components/OgMeta'; import Page from 'components/Page'; import ProjectTypeIcon from 'components/ProjectTypeIcon'; import ImageWrapper from 'components/ImageWrapper'; -import Button from 'components/Button'; import Hero from 'components/Hero'; import Tag from 'components/Tag'; import Card from 'components/Card'; @@ -151,7 +149,6 @@ function Project(props: Props) { exportModerateToHighAgreementYesMaybeGeometries, numberOfContributorUsers, aoiGeometry, - firebaseId, id: projectId, } = props; @@ -338,31 +335,6 @@ function Project(props: Props) { transformAoiToGeoJson(aoiGeometry) ), [aoiGeometry]); - const aoiGeometryBlob = useMemo(() => { - if (!aoiGeometryFeature) { - return undefined; - } - const blob = new Blob( - [JSON.stringify(aoiGeometryFeature, null, 2)], - { type: 'application/geo+json' }, - ); - return blob; - }, [aoiGeometryFeature]); - - const onAoiDownloadClick = useCallback(() => { - if (!aoiGeometryBlob) { - return; - } - const url = URL.createObjectURL(aoiGeometryBlob); - - const a = document.createElement('a'); - a.href = url; - a.download = `area_of_interest_${firebaseId}.geojson`; - a.click(); - - URL.revokeObjectURL(url); - }, [aoiGeometryBlob, firebaseId]); - return ( {t('download')} @@ -662,6 +635,7 @@ function Project(props: Props) { href={exportAggregatedResultsWithGeometry?.file?.url} variant="buttonTransparent" className={styles.link} + download > {t('download')} @@ -690,6 +664,7 @@ function Project(props: Props) { href={exportGroups?.file.url} variant="buttonTransparent" className={styles.link} + download > {t('download')} @@ -718,6 +693,7 @@ function Project(props: Props) { href={exportHistory?.file.url} variant="buttonTransparent" className={styles.link} + download > {t('download')} @@ -746,6 +722,7 @@ function Project(props: Props) { href={exportResults?.file.url} variant="buttonTransparent" className={styles.link} + download > {t('download')} @@ -774,6 +751,7 @@ function Project(props: Props) { href={exportTasks?.file.url} variant="buttonTransparent" className={styles.link} + download > {t('download')} @@ -802,50 +780,14 @@ function Project(props: Props) { href={exportUsers?.file.url} variant="buttonTransparent" className={styles.link} + download > {t('download')} )} - {aoiGeometry && ( - -
- GEOJSON -
- {t('download-size', { - size: getFileSizeProperties( - aoiGeometryBlob?.size ?? 0, - ).size, - formatParams: { - size: { - style: 'unit', - unit: getFileSizeProperties( - aoiGeometryBlob?.size ?? 0, - ).unit, - maximumFractionDigits: 1, - }, - }, - })} -
-
- -
- )} - {/* NOTE: If in case there is no aoiGeometry, - we show exportAreaOfInterest if present */} - {!aoiGeometry && exportAreaOfInterest && ( + {exportAreaOfInterest && ( {t('download')} @@ -899,6 +842,7 @@ function Project(props: Props) { href={exportHotTaskingManagerGeometries?.file.url} variant="buttonTransparent" className={styles.link} + download > {t('download')} @@ -929,6 +873,7 @@ function Project(props: Props) { href={exportModerateToHighAgreementYesMaybeGeometries?.file.url} variant="buttonTransparent" className={styles.link} + download > {t('download')}