-
Notifications
You must be signed in to change notification settings - Fork 3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #45593 from software-mansion-labs/search/export-cs…
…v-native-devices [Search] Export CSV on native devices
- Loading branch information
Showing
8 changed files
with
172 additions
and
79 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
import * as ApiUtils from '@libs/ApiUtils'; | ||
import tryResolveUrlFromApiRoot from '@libs/tryResolveUrlFromApiRoot'; | ||
import * as Link from '@userActions/Link'; | ||
import CONST from '@src/CONST'; | ||
import * as FileUtils from './FileUtils'; | ||
import type {FileDownload} from './types'; | ||
|
||
const createDownloadLink = (href: string, fileName: string) => { | ||
// creating anchor tag to initiate download | ||
const link = document.createElement('a'); | ||
// adding href to anchor | ||
link.href = href; | ||
link.style.display = 'none'; | ||
|
||
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- Disabling this line for safeness as nullish coalescing works only if the value is undefined or null, and since fileName can be an empty string we want to default to `FileUtils.getFileName(url)` | ||
link.download = fileName; | ||
|
||
// Append to html link element page | ||
document.body.appendChild(link); | ||
|
||
// Start download | ||
link.click(); | ||
|
||
// Clean up and remove the link | ||
URL.revokeObjectURL(link.href); | ||
link.parentNode?.removeChild(link); | ||
}; | ||
|
||
/** | ||
* The function downloads an attachment on web/desktop platforms. | ||
*/ | ||
// eslint-disable-next-line @typescript-eslint/no-unused-vars | ||
const fetchFileDownload: FileDownload = (url, fileName, successMessage = '', shouldOpenExternalLink = false, formData = undefined, requestType = 'get', onDownloadFailed?: () => void) => { | ||
const resolvedUrl = tryResolveUrlFromApiRoot(url); | ||
|
||
const isApiUrl = resolvedUrl.startsWith(ApiUtils.getApiRoot()); | ||
const isAttachmentUrl = CONST.ATTACHMENT_LOCAL_URL_PREFIX.some((prefix) => resolvedUrl.startsWith(prefix)); | ||
const isSageUrl = url === CONST.EXPENSIFY_PACKAGE_FOR_SAGE_INTACCT; | ||
if ( | ||
// We have two file download cases that we should allow: 1. downloading attachments 2. downloading Expensify package for Sage Intacct | ||
shouldOpenExternalLink || | ||
(!isApiUrl && !isAttachmentUrl && !isSageUrl) | ||
) { | ||
// Different origin URLs might pose a CORS issue during direct downloads. | ||
// Opening in a new tab avoids this limitation, letting the browser handle the download. | ||
Link.openExternalLink(url); | ||
return Promise.resolve(); | ||
} | ||
|
||
const fetchOptions: RequestInit = { | ||
method: requestType, | ||
body: formData, | ||
}; | ||
|
||
return fetch(url, fetchOptions) | ||
.then((response) => response.blob()) | ||
.then((blob) => { | ||
// Create blob link to download | ||
const href = URL.createObjectURL(new Blob([blob])); | ||
const completeFileName = FileUtils.appendTimeToFileName(fileName ?? FileUtils.getFileName(url)); | ||
createDownloadLink(href, completeFileName); | ||
}) | ||
.catch(() => { | ||
if (onDownloadFailed) { | ||
onDownloadFailed(); | ||
} else { | ||
// file could not be downloaded, open sourceURL in new tab | ||
Link.openExternalLink(url); | ||
} | ||
}); | ||
}; | ||
|
||
export default fetchFileDownload; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,67 +1,10 @@ | ||
import * as ApiUtils from '@libs/ApiUtils'; | ||
import tryResolveUrlFromApiRoot from '@libs/tryResolveUrlFromApiRoot'; | ||
import * as Link from '@userActions/Link'; | ||
import CONST from '@src/CONST'; | ||
import * as FileUtils from './FileUtils'; | ||
import fetchFileDownload from './DownloadUtils'; | ||
import type {FileDownload} from './types'; | ||
|
||
/** | ||
* The function downloads an attachment on web/desktop platforms. | ||
*/ | ||
// eslint-disable-next-line @typescript-eslint/no-unused-vars | ||
const fileDownload: FileDownload = (url, fileName, successMessage = '', shouldOpenExternalLink = false, formData = undefined, requestType = 'get', onDownloadFailed?: () => void) => { | ||
const resolvedUrl = tryResolveUrlFromApiRoot(url); | ||
if ( | ||
// we have two file download cases that we should allow 1. dowloading attachments 2. downloading Expensify package for Sage Intacct | ||
shouldOpenExternalLink || | ||
(!resolvedUrl.startsWith(ApiUtils.getApiRoot()) && | ||
!CONST.ATTACHMENT_LOCAL_URL_PREFIX.some((prefix) => resolvedUrl.startsWith(prefix)) && | ||
url !== CONST.EXPENSIFY_PACKAGE_FOR_SAGE_INTACCT) | ||
) { | ||
// Different origin URLs might pose a CORS issue during direct downloads. | ||
// Opening in a new tab avoids this limitation, letting the browser handle the download. | ||
Link.openExternalLink(url); | ||
return Promise.resolve(); | ||
} | ||
|
||
const fetchOptions: RequestInit = { | ||
method: requestType, | ||
body: formData, | ||
}; | ||
|
||
return fetch(url, fetchOptions) | ||
.then((response) => response.blob()) | ||
.then((blob) => { | ||
// Create blob link to download | ||
const href = URL.createObjectURL(new Blob([blob])); | ||
|
||
// creating anchor tag to initiate download | ||
const link = document.createElement('a'); | ||
|
||
// adding href to anchor | ||
link.href = href; | ||
link.style.display = 'none'; | ||
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- Disabling this line for safeness as nullish coalescing works only if the value is undefined or null, and since fileName can be an empty string we want to default to `FileUtils.getFileName(url)` | ||
link.download = FileUtils.appendTimeToFileName(fileName || FileUtils.getFileName(url)); | ||
|
||
// Append to html link element page | ||
document.body.appendChild(link); | ||
|
||
// Start download | ||
link.click(); | ||
|
||
// Clean up and remove the link | ||
URL.revokeObjectURL(link.href); | ||
link.parentNode?.removeChild(link); | ||
}) | ||
.catch(() => { | ||
if (onDownloadFailed) { | ||
onDownloadFailed(); | ||
} else { | ||
// file could not be downloaded, open sourceURL in new tab | ||
Link.openExternalLink(url); | ||
} | ||
}); | ||
}; | ||
const fileDownload: FileDownload = (url, fileName, successMessage = '', shouldOpenExternalLink = false, formData = undefined, requestType = 'get', onDownloadFailed?: () => void) => | ||
fetchFileDownload(url, fileName, successMessage, shouldOpenExternalLink, formData, requestType, onDownloadFailed); | ||
|
||
export default fileDownload; |