From 38202265a79ea7a6d732707b5753b6d643d36cc3 Mon Sep 17 00:00:00 2001 From: Mozafar Haider Date: Wed, 24 Apr 2024 21:19:15 +0100 Subject: [PATCH] fix(DHIS2-16988): download uncompressed json rather than open inline --- src/utils/helper.js | 53 ++++++++++++++++++++++++++++-------- src/utils/helper.test.js | 59 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 101 insertions(+), 11 deletions(-) create mode 100644 src/utils/helper.test.js diff --git a/src/utils/helper.js b/src/utils/helper.js index 853274c24..71c80067a 100644 --- a/src/utils/helper.js +++ b/src/utils/helper.js @@ -188,22 +188,53 @@ const uploadFile = ({ }) } -const downloadWindowTitle = i18n.t('Loading exported data') -const downloadWindowHtml = ` -
-

${downloadWindowTitle}

-
-` +const propsToInclude = [ + 'program', + 'ouMode', + 'orgUnits', + 'orgUnit', + 'trackedEntityType', +] +const getParamsForFileName = (url) => { + const params = [...new URL(url).searchParams.entries()] + return params + .filter(([prop]) => propsToInclude.includes(prop)) + .map(([prop, val]) => `${prop}_${val}`) + .join('__') +} // call stub function if available -const locationAssign = (url) => { +const locationAssign = (relativeUrl) => { if (window.locationAssign) { - window.locationAssign(url) + window.locationAssign(relativeUrl) } else { - const downloadWindow = window.open(url, '_blank') + try { + const url = relativeUrl.startsWith('..') + ? new URL(relativeUrl, document.baseURI).href + : relativeUrl + + const requestParams = getParamsForFileName(url) + + const urlFilePart = new URL(url).pathname.split('/').pop() + const [, file, extension] = urlFilePart.match(/(^[^.]+)(\..+$)/) - downloadWindow.document.title = downloadWindowTitle - downloadWindow.document.body.innerHTML = downloadWindowHtml // does not work in Chrome + const timeStamp = new Intl.DateTimeFormat('en-CA').format( + new Date() + ) // en-CA is yyyy-MM-dd + + const downloadedFileName = `${file}_${timeStamp}_${requestParams}${extension}` + + const link = document.createElement('a') + link.href = url + link.download = downloadedFileName + link.target = '_blank' + link.click() + + return link + } catch (err) { + console.error(err) + window.open(relativeUrl, '_blank') + } } } diff --git a/src/utils/helper.test.js b/src/utils/helper.test.js new file mode 100644 index 000000000..b9854cb3d --- /dev/null +++ b/src/utils/helper.test.js @@ -0,0 +1,59 @@ +import { locationAssign } from "./helper.js" + +describe('locationAssign', () => { + beforeEach(() => { + jest.useFakeTimers('modern'); + jest.setSystemTime(new Date(2024, 2, 12)); + }); + + afterEach(() => { + jest.useRealTimers(); + }); + + it('should create a file name based on the params', () => { + const url = 'https://debug.dhis2.org/dev/api/tracker/trackedEntities.json?ouMode=CAPTURE&format=json&includeDeleted=false&dataElementIdScheme=UID&eventIdScheme=UID&orgUnitIdScheme=UID&idScheme=UID&attachment=trackedEntities.json&paging=false&totalPages=false&program=lxAQ7Zs9VYR' + const link = locationAssign(url) + expect(link.download).toEqual('trackedEntities_2024-03-12_ouMode_CAPTURE__program_lxAQ7Zs9VYR.json') + + }) + it('should create url with orgUnits', () => { + const url = 'https://debug.dhis2.org/dev/api/tracker/trackedEntities.json?ouMode=SELECTED&includeDeleted=false&dataElementIdScheme=UID&eventIdScheme=UID&orgUnitIdScheme=UID&idScheme=UID&attachment=trackedEntities.json&paging=false&totalPages=false&orgUnits=O6uvpzGd5pu,fdc6uOvgoji&program=kla3mAPgvCH'; + const link = locationAssign(url) + expect(link.download).toEqual('trackedEntities_2024-03-12_ouMode_SELECTED__orgUnits_O6uvpzGd5pu,fdc6uOvgoji__program_kla3mAPgvCH.json') + }) + it('should create url with tracked entities', () => { + const url = 'https://debug.dhis2.org/dev/api/tracker/trackedEntities.json?ouMode=SELECTED&includeDeleted=false&dataElementIdScheme=UID&eventIdScheme=UID&orgUnitIdScheme=UID&idScheme=UID&attachment=trackedEntities.json&paging=false&totalPages=false&orgUnits=ImspTQPwCqd&trackedEntityType=bVkFYAvoUCP'; + const link = locationAssign(url) + expect(link.download).toEqual('trackedEntities_2024-03-12_ouMode_SELECTED__orgUnits_ImspTQPwCqd__trackedEntityType_bVkFYAvoUCP.json') + }) + it('should create url with CSV', () => { + const url = 'https://debug.dhis2.org/dev/api/tracker/trackedEntities.csv?ouMode=SELECTED&includeDeleted=false&dataElementIdScheme=UID&eventIdScheme=UID&orgUnitIdScheme=UID&idScheme=UID&attachment=trackedEntities.csv&paging=false&totalPages=false&orgUnits=ImspTQPwCqd&program=lxAQ7Zs9VYR'; + const link = locationAssign(url) + expect(link.download).toEqual('trackedEntities_2024-03-12_ouMode_SELECTED__orgUnits_ImspTQPwCqd__program_lxAQ7Zs9VYR.csv') + }) + + it('should create url with events zip', () => { + const url = 'https://debug.dhis2.org/dev/api/tracker/events.json.zip?links=false&paging=false&totalPages=false&orgUnit=fwH9ipvXde9&program=VBqh0ynB2wv&includeDeleted=false&dataElementIdScheme=UID&orgUnitIdScheme=UID&idScheme=UID&attachment=events.json.zip&occurredAfter=2023-12-12&occurredBefore=2024-03-12&ouMode=CHILDREN&format=json'; + const link = locationAssign(url) + expect(link.download).toEqual('events_2024-03-12_orgUnit_fwH9ipvXde9__program_VBqh0ynB2wv__ouMode_CHILDREN.json.zip') + }) + + it('should create url with events gzip', () => { + const url = 'https://debug.dhis2.org/dev/api/tracker/events.json.gz?links=false&paging=false&totalPages=false&orgUnit=ImspTQPwCqd&program=lxAQ7Zs9VYR&includeDeleted=false&dataElementIdScheme=UID&orgUnitIdScheme=UID&idScheme=UID&attachment=events.json.gz&occurredAfter=2023-12-12&occurredBefore=2024-03-12&ouMode=SELECTED&format=json'; + const link = locationAssign(url) + expect(link.download).toEqual('events_2024-03-12_orgUnit_ImspTQPwCqd__program_lxAQ7Zs9VYR__ouMode_SELECTED.json.gz') + }) + it('should work with relative URLs when bundled in DHIS2', () => { + Object.defineProperty(global.document, 'baseURI', { value: 'http://localhost:8080/dhis-web-import-export/index.html#/export/tei' }); + const url = '../api/tracker/trackedEntities.json?ouMode=SELECTED&includeDeleted=false&dataElementIdScheme=UID&eventIdScheme=UID&orgUnitIdScheme=UID&idScheme=UID&attachment=trackedEntities.json&paging=false&totalPages=false&orgUnits=ImspTQPwCqd&program=lxAQ7Zs9VYR' + const link = locationAssign(url) + expect(link.download).toEqual('trackedEntities_2024-03-12_ouMode_SELECTED__orgUnits_ImspTQPwCqd__program_lxAQ7Zs9VYR.json') + }) + it('should work with relative URLs when bundled in DHIS2 for zip', () => { + Object.defineProperty(global.document, 'baseURI', { value: 'http://localhost:8080/dhis-web-import-export/index.html#/export/tei' }); + const url ='../api/tracker/events.json.zip?links=false&paging=false&totalPages=false&orgUnit=ImspTQPwCqd&program=lxAQ7Zs9VYR&includeDeleted=false&dataElementIdScheme=UID&orgUnitIdScheme=UID&idScheme=UID&attachment=events.json.zip&occurredAfter=2023-12-12&occurredBefore=2024-03-12&ouMode=SELECTED&format=json' + const link = locationAssign(url) + expect(link.download).toEqual('trackedEntities_2024-03-12_ouMode_SELECTED__orgUnits_ImspTQPwCqd__program_lxAQ7Zs9VYR.json') + }) + +}) \ No newline at end of file