From 640d6f820232371a9a54bac92b60fb415283a30e Mon Sep 17 00:00:00 2001 From: alexd-bes <129009580+alexd-bes@users.noreply.github.com> Date: Mon, 19 Aug 2024 10:28:15 +1200 Subject: [PATCH 1/4] Working downloads --- env/api-client.env.example | 6 ++- .../src/apiV2/export/DownloadHandler.js | 4 +- .../api/mutations/useExportSurveyResponses.ts | 1 + .../server-utils/src/constructExportEmail.ts | 52 ++++++++++--------- .../tupaia-web-server/src/app/createApp.ts | 1 + .../src/routes/export/utils.ts | 2 +- 6 files changed, 37 insertions(+), 29 deletions(-) diff --git a/env/api-client.env.example b/env/api-client.env.example index e9893627bb..4fb642f30c 100644 --- a/env/api-client.env.example +++ b/env/api-client.env.example @@ -3,5 +3,7 @@ DATA_TABLE_API_URL= CENTRAL_API_URL= ENTITY_API_URL= REPORT_API_URL= -WEB_CONFIG_API_URL= -API_CLIENT_SALT= +WEB_CONFIG_API_URL= +TUPAIA_WEB_SERVER_API_URL= +DATATRAK_WEB_SERVER_API_URL= +ADMIN_PANEL_SERVER_API_URL= diff --git a/packages/central-server/src/apiV2/export/DownloadHandler.js b/packages/central-server/src/apiV2/export/DownloadHandler.js index 8da3f0e86e..3f6f2f96b4 100644 --- a/packages/central-server/src/apiV2/export/DownloadHandler.js +++ b/packages/central-server/src/apiV2/export/DownloadHandler.js @@ -6,11 +6,11 @@ import fs from 'fs'; import { respondWithDownload, ValidationError } from '@tupaia/utils'; import { getExportPathForUser } from './getExportPathForUser'; import { RouteHandler } from '../RouteHandler'; -import { assertAdminPanelAccess } from '../../permissions'; +import { allowNoPermissions } from '../../permissions'; export class DownloadHandler extends RouteHandler { async assertUserHasAccess() { - await this.assertPermissions(assertAdminPanelAccess); + await this.assertPermissions(allowNoPermissions); } async handleRequest() { diff --git a/packages/datatrak-web/src/api/mutations/useExportSurveyResponses.ts b/packages/datatrak-web/src/api/mutations/useExportSurveyResponses.ts index b77612b103..564659495c 100644 --- a/packages/datatrak-web/src/api/mutations/useExportSurveyResponses.ts +++ b/packages/datatrak-web/src/api/mutations/useExportSurveyResponses.ts @@ -55,6 +55,7 @@ export const useExportSurveyResponses = () => { countryCode, startDate, endDate, + platform: 'datatrak', }, }); diff --git a/packages/server-utils/src/constructExportEmail.ts b/packages/server-utils/src/constructExportEmail.ts index 2733c81510..91c4e2acb6 100644 --- a/packages/server-utils/src/constructExportEmail.ts +++ b/packages/server-utils/src/constructExportEmail.ts @@ -3,22 +3,11 @@ * Copyright (c) 2017 - 2024 Beyond Essential Systems Pty Ltd */ import path from 'path'; -import fs from 'fs'; +import { requireEnv } from '@tupaia/utils'; -enum EmailExportFileModes { - ATTACHMENT = 'attachment', - DOWNLOAD_LINK = 'downloadLink', -} - -const createDownloadLink = (filePath: string) => { - const fileName = path.basename(filePath); - return `${process.env.ADMIN_PANEL_SERVER_URL}/v1/export/download/${encodeURIComponent(fileName)}`; -}; - -const generateAttachments = async (filePath: string) => { +const createDownloadLink = (filePath: string, url: string) => { const fileName = path.basename(filePath); - const buffer = await fs.readFileSync(filePath); - return [{ filename: fileName, content: buffer }]; + return `${url}/export/download/${encodeURIComponent(fileName)}`; }; type ResponseBody = { @@ -28,13 +17,13 @@ type ResponseBody = { type Req = { query: { - emailExportFileMode?: EmailExportFileModes; + platform?: 'tupaia' | 'adminPanel' | 'datatrak'; }; }; export const constructExportEmail = async (responseBody: ResponseBody, req: Req) => { - const { emailExportFileMode = EmailExportFileModes.DOWNLOAD_LINK } = req.query; const { error, filePath } = responseBody; + const { platform } = req.query; const subject = 'Your export from Tupaia'; if (error) { return { @@ -48,18 +37,33 @@ ${error}`, throw new Error('No filePath in export response body'); } - if (emailExportFileMode === EmailExportFileModes.ATTACHMENT) { - return { - subject, - message: 'Please find your requested export attached to this email.', - attachments: await generateAttachments(filePath), - }; + const platformKey = platform || 'adminPanel'; + + const PLATFORM_SETTINGS = { + tupaia: { + url: requireEnv('TUPAIA_WEB_SERVER_API_URL'), + friendlyName: 'Tupaia', + }, + adminPanel: { + url: requireEnv('ADMIN_PANEL_SERVER_API_URL'), + friendlyName: 'the Admin Panel', + }, + datatrak: { + url: requireEnv('DATATRAK_WEB_SERVER_API_URL'), + friendlyName: 'DataTrak', + }, + }; + + if (!PLATFORM_SETTINGS[platformKey]) { + throw new Error(`No API config found for platform: ${platformKey}`); } - const downloadLink = createDownloadLink(filePath); + const { friendlyName, url } = PLATFORM_SETTINGS[platformKey]; + + const downloadLink = createDownloadLink(filePath, url); return { subject, message: `Please click this one-time link to download your requested export: ${downloadLink} -Note that you need to be logged in to the admin panel for it to work, and after clicking it once, you won't be able to download the file again.`, + Note that you need to be logged in to ${friendlyName} for it to work, and after clicking it once, you won't be able to download the file again.`, }; }; diff --git a/packages/tupaia-web-server/src/app/createApp.ts b/packages/tupaia-web-server/src/app/createApp.ts index aa6cbd3dc7..743b275ade 100644 --- a/packages/tupaia-web-server/src/app/createApp.ts +++ b/packages/tupaia-web-server/src/app/createApp.ts @@ -99,6 +99,7 @@ export async function createApp(db: TupaiaDatabase = new TupaiaDatabase()) { ) .use('downloadFiles', forwardRequest(CENTRAL_API_URL, { authHandlerProvider })) .use('me/countries', forwardRequest(CENTRAL_API_URL, { authHandlerProvider })) + .use('export/download/:fileName', forwardRequest(CENTRAL_API_URL, { authHandlerProvider })) // Forward everything else to webConfigApi .use('dashboards', forwardRequest(WEB_CONFIG_API_URL, { authHandlerProvider })) .use('export/chart', forwardRequest(WEB_CONFIG_API_URL, { authHandlerProvider })) diff --git a/packages/tupaia-web-server/src/routes/export/utils.ts b/packages/tupaia-web-server/src/routes/export/utils.ts index db3b9c676b..c85ab94a46 100644 --- a/packages/tupaia-web-server/src/routes/export/utils.ts +++ b/packages/tupaia-web-server/src/routes/export/utils.ts @@ -2,7 +2,7 @@ const EMAIL_TIMEOUT = 30 * 1000; // 30 seconds export const EMAIL_TIMEOUT_SETTINGS = { respondWithEmailTimeout: EMAIL_TIMEOUT, - emailExportFileMode: 'attachment', + platform: 'tupaia', }; export const handleExportResponse = async (response: { From b9fe79544d5e1d389bb928ec33f2c36a3c17d670 Mon Sep 17 00:00:00 2001 From: alexd-bes <129009580+alexd-bes@users.noreply.github.com> Date: Mon, 19 Aug 2024 15:09:18 +1200 Subject: [PATCH 2/4] Add comments --- packages/central-server/src/apiV2/export/DownloadHandler.js | 1 + packages/server-utils/src/constructExportEmail.ts | 3 +++ 2 files changed, 4 insertions(+) diff --git a/packages/central-server/src/apiV2/export/DownloadHandler.js b/packages/central-server/src/apiV2/export/DownloadHandler.js index 3f6f2f96b4..2a3a62655f 100644 --- a/packages/central-server/src/apiV2/export/DownloadHandler.js +++ b/packages/central-server/src/apiV2/export/DownloadHandler.js @@ -10,6 +10,7 @@ import { allowNoPermissions } from '../../permissions'; export class DownloadHandler extends RouteHandler { async assertUserHasAccess() { + // This is a special case where we don't need to check permissions, as the user must be logged in anyway and the user can't generate an export without specific permissions await this.assertPermissions(allowNoPermissions); } diff --git a/packages/server-utils/src/constructExportEmail.ts b/packages/server-utils/src/constructExportEmail.ts index 91c4e2acb6..61ce4e0b45 100644 --- a/packages/server-utils/src/constructExportEmail.ts +++ b/packages/server-utils/src/constructExportEmail.ts @@ -39,6 +39,9 @@ ${error}`, const platformKey = platform || 'adminPanel'; + /** + * We don't yet have single sign-on across all platforms, so we need to know which platform the user is on so the correct session is used, from where they requested the export. We also can't use central-server api url for this directly because there needs to be an auth header in the request. + */ const PLATFORM_SETTINGS = { tupaia: { url: requireEnv('TUPAIA_WEB_SERVER_API_URL'), From 8e5545ca63e413d5e50cba4ce117ad630a271a79 Mon Sep 17 00:00:00 2001 From: alexd-bes <129009580+alexd-bes@users.noreply.github.com> Date: Mon, 19 Aug 2024 15:43:28 +1200 Subject: [PATCH 3/4] Fix exports on web config server --- .../central-server/src/apiV2/DownloadFiles.js | 3 +- .../src/apiV2/export/DownloadHandler.js | 2 +- .../export/exportOptionSet/exportOptionSet.js | 2 +- .../exportResponsesToFile.js | 2 +- .../export/exportSurveys/SurveyExporter.js | 3 +- .../src/apiV2/export/getExportPathForUser.js | 7 --- .../central-server/src/apiV2/import/index.js | 2 +- .../src/apiV2/middleware/multipartJson.js | 46 ++++++++++--------- .../central-server/src/utilities/index.js | 1 - .../server-utils/src/getExportPathForUser.ts | 7 +++ .../src/getTempDirectory.ts} | 4 +- packages/server-utils/src/index.ts | 7 +++ .../src/export/ExportSurveyDataHandler.js | 12 +++-- 13 files changed, 53 insertions(+), 45 deletions(-) delete mode 100644 packages/central-server/src/apiV2/export/getExportPathForUser.js create mode 100644 packages/server-utils/src/getExportPathForUser.ts rename packages/{central-server/src/utilities/getTempDirectory.js => server-utils/src/getTempDirectory.ts} (72%) diff --git a/packages/central-server/src/apiV2/DownloadFiles.js b/packages/central-server/src/apiV2/DownloadFiles.js index afb7c1257e..e644d8e497 100644 --- a/packages/central-server/src/apiV2/DownloadFiles.js +++ b/packages/central-server/src/apiV2/DownloadFiles.js @@ -10,9 +10,8 @@ import { getUniqueFileNameParts, getDeDuplicatedFileName, } from '@tupaia/utils'; -import { S3, S3Client } from '@tupaia/server-utils'; +import { S3, S3Client, getTempDirectory } from '@tupaia/server-utils'; import { RouteHandler } from './RouteHandler'; -import { getTempDirectory } from '../utilities'; import { zipMultipleFiles } from './utilities'; export class DownloadFiles extends RouteHandler { diff --git a/packages/central-server/src/apiV2/export/DownloadHandler.js b/packages/central-server/src/apiV2/export/DownloadHandler.js index 2a3a62655f..cb3e59e20f 100644 --- a/packages/central-server/src/apiV2/export/DownloadHandler.js +++ b/packages/central-server/src/apiV2/export/DownloadHandler.js @@ -4,7 +4,7 @@ */ import fs from 'fs'; import { respondWithDownload, ValidationError } from '@tupaia/utils'; -import { getExportPathForUser } from './getExportPathForUser'; +import { getExportPathForUser } from '@tupaia/server-utils'; import { RouteHandler } from '../RouteHandler'; import { allowNoPermissions } from '../../permissions'; diff --git a/packages/central-server/src/apiV2/export/exportOptionSet/exportOptionSet.js b/packages/central-server/src/apiV2/export/exportOptionSet/exportOptionSet.js index e51add3cce..eb24e90e07 100644 --- a/packages/central-server/src/apiV2/export/exportOptionSet/exportOptionSet.js +++ b/packages/central-server/src/apiV2/export/exportOptionSet/exportOptionSet.js @@ -5,7 +5,7 @@ import xlsx from 'xlsx'; import { respondWithDownload, toFilename } from '@tupaia/utils'; -import { getExportPathForUser } from '../getExportPathForUser'; +import { getExportPathForUser } from '@tupaia/server-utils'; const objectToHumanReadableKeyValuePairs = obj => { const entries = []; diff --git a/packages/central-server/src/apiV2/export/exportSurveyResponses/exportResponsesToFile.js b/packages/central-server/src/apiV2/export/exportSurveyResponses/exportResponsesToFile.js index c5c1222825..eac2d277fd 100644 --- a/packages/central-server/src/apiV2/export/exportSurveyResponses/exportResponsesToFile.js +++ b/packages/central-server/src/apiV2/export/exportSurveyResponses/exportResponsesToFile.js @@ -15,11 +15,11 @@ import { truncateString, toFilename, } from '@tupaia/utils'; +import { getExportPathForUser } from '@tupaia/server-utils'; import { RECORDS } from '@tupaia/database'; import { ANSWER_TYPES, NON_DATA_ELEMENT_ANSWER_TYPES } from '../../../database/models/Answer'; import { findAnswersInSurveyResponse, findQuestionsInSurvey } from '../../../dataAccessors'; import { hasBESAdminAccess } from '../../../permissions'; -import { getExportPathForUser } from '../getExportPathForUser'; import { zipMultipleFiles } from '../../utilities'; const FILE_PREFIX = 'survey_response_export'; diff --git a/packages/central-server/src/apiV2/export/exportSurveys/SurveyExporter.js b/packages/central-server/src/apiV2/export/exportSurveys/SurveyExporter.js index b67f00fa45..4dd04925eb 100644 --- a/packages/central-server/src/apiV2/export/exportSurveys/SurveyExporter.js +++ b/packages/central-server/src/apiV2/export/exportSurveys/SurveyExporter.js @@ -5,13 +5,12 @@ import xlsx from 'xlsx'; import { DatabaseError } from '@tupaia/utils'; - +import { getExportPathForUser } from '@tupaia/server-utils'; import { findQuestionsInSurvey } from '../../../dataAccessors'; import { RowBuilder } from './RowBuilder'; import { SurveyMetadataConfigCellBuilder } from './cellBuilders'; import { assertCanExportSurveys } from './assertCanExportSurveys'; import { assertAnyPermissions, assertBESAdminAccess } from '../../../permissions'; -import { getExportPathForUser } from '../getExportPathForUser'; const FILE_PREFIX = 'survey_export'; diff --git a/packages/central-server/src/apiV2/export/getExportPathForUser.js b/packages/central-server/src/apiV2/export/getExportPathForUser.js deleted file mode 100644 index ea68196d7a..0000000000 --- a/packages/central-server/src/apiV2/export/getExportPathForUser.js +++ /dev/null @@ -1,7 +0,0 @@ -/** - * Tupaia - * Copyright (c) 2017 - 2021 Beyond Essential Systems Pty Ltd - */ -import { getTempDirectory } from '../../utilities'; - -export const getExportPathForUser = userId => getTempDirectory(`exports/${userId}`); diff --git a/packages/central-server/src/apiV2/import/index.js b/packages/central-server/src/apiV2/import/index.js index f8f7167db4..06907bf3da 100644 --- a/packages/central-server/src/apiV2/import/index.js +++ b/packages/central-server/src/apiV2/import/index.js @@ -5,6 +5,7 @@ import express from 'express'; import multer from 'multer'; +import { getTempDirectory } from '@tupaia/server-utils'; import { emailAfterTimeout } from '@tupaia/server-boilerplate'; import { catchAsyncErrors } from '../middleware'; @@ -13,7 +14,6 @@ import { importEntities } from './importEntities'; import { importStriveLabResults } from './importStriveLabResults'; import { importUsers } from './importUsers'; import { importSurveyResponses, constructImportEmail } from './importSurveyResponses'; -import { getTempDirectory } from '../../utilities'; import { importDataElements } from './importDataElements'; import { importDataElementDataServices } from './importDataElementDataServices'; import { importUserPermissions } from './importUserPermissions'; diff --git a/packages/central-server/src/apiV2/middleware/multipartJson.js b/packages/central-server/src/apiV2/middleware/multipartJson.js index 469a7b7d65..84118810c8 100644 --- a/packages/central-server/src/apiV2/middleware/multipartJson.js +++ b/packages/central-server/src/apiV2/middleware/multipartJson.js @@ -4,7 +4,7 @@ */ import multer from 'multer'; -import { getTempDirectory } from '../../utilities'; +import { getTempDirectory } from '@tupaia/server-utils'; /** * Parses a multipartJson request where: @@ -19,29 +19,31 @@ import { getTempDirectory } from '../../utilities'; * * @param {boolean} [addFilesToBody] If true, will add each File to the body by the given form part name, e.g. myfile: File */ -export const multipartJson = (addFilesToBody = true) => async (req, res, next) => { - if (req.headers['content-type'].startsWith('multipart/form-data')) { - const parserMiddleware = multer({ - storage: multer.diskStorage({ - destination: getTempDirectory('uploads'), - filename: (req, file, callback) => { - callback(null, `${Date.now()}_${file.originalname}`); - }, - }), - }).any(); +export const multipartJson = + (addFilesToBody = true) => + async (req, res, next) => { + if (req.headers['content-type'].startsWith('multipart/form-data')) { + const parserMiddleware = multer({ + storage: multer.diskStorage({ + destination: getTempDirectory('uploads'), + filename: (req, file, callback) => { + callback(null, `${Date.now()}_${file.originalname}`); + }, + }), + }).any(); - parserMiddleware(req, res, () => { - req.body = JSON.parse(req?.body?.payload || '{}'); + parserMiddleware(req, res, () => { + req.body = JSON.parse(req?.body?.payload || '{}'); - if (req.files && addFilesToBody) { - for (const file of req.files) { - req.body[file.fieldname] = file; + if (req.files && addFilesToBody) { + for (const file of req.files) { + req.body[file.fieldname] = file; + } } - } + next(); + }); + } else { next(); - }); - } else { - next(); - } -}; + } + }; diff --git a/packages/central-server/src/utilities/index.js b/packages/central-server/src/utilities/index.js index 7a94757346..dc841d94a6 100644 --- a/packages/central-server/src/utilities/index.js +++ b/packages/central-server/src/utilities/index.js @@ -4,6 +4,5 @@ */ export { getApiUrl } from './getApiUrl'; -export { getTempDirectory } from './getTempDirectory'; export { resourceToRecordType } from './resourceToRecordType'; export { getStandardisedImageName } from './getStandardisedImageName'; diff --git a/packages/server-utils/src/getExportPathForUser.ts b/packages/server-utils/src/getExportPathForUser.ts new file mode 100644 index 0000000000..c674b83650 --- /dev/null +++ b/packages/server-utils/src/getExportPathForUser.ts @@ -0,0 +1,7 @@ +/** + * Tupaia + * Copyright (c) 2017 - 2024 Beyond Essential Systems Pty Ltd + */ +import { getTempDirectory } from './getTempDirectory'; + +export const getExportPathForUser = (userId: string) => getTempDirectory(`exports/${userId}`); diff --git a/packages/central-server/src/utilities/getTempDirectory.js b/packages/server-utils/src/getTempDirectory.ts similarity index 72% rename from packages/central-server/src/utilities/getTempDirectory.js rename to packages/server-utils/src/getTempDirectory.ts index 273b2424a7..e5808f9a95 100644 --- a/packages/central-server/src/utilities/getTempDirectory.js +++ b/packages/server-utils/src/getTempDirectory.ts @@ -1,13 +1,13 @@ /** * Tupaia - * Copyright (c) 2017 - 2021 Beyond Essential Systems Pty Ltd + * Copyright (c) 2017 - 2024 Beyond Essential Systems Pty Ltd */ import fs from 'fs'; import os from 'os'; import path from 'path'; -export function getTempDirectory(name) { +export function getTempDirectory(name: string) { const directoryPath = path.join(os.tmpdir(), 'tupaia', name); try { diff --git a/packages/server-utils/src/index.ts b/packages/server-utils/src/index.ts index 5c78cfa9e7..4b7e2270b8 100644 --- a/packages/server-utils/src/index.ts +++ b/packages/server-utils/src/index.ts @@ -1,6 +1,13 @@ +/** + * Tupaia + * Copyright (c) 2017 - 2024 Beyond Essential Systems Pty Ltd + */ + export { downloadPageAsPDF } from './downloadPageAsPDF'; export * from './s3'; export { sendEmail } from './sendEmail'; export { generateUnsubscribeToken, verifyUnsubscribeToken } from './unsubscribeToken'; export { configureDotEnv } from './configureDotEnv'; export { constructExportEmail } from './constructExportEmail'; +export { getTempDirectory } from './getTempDirectory'; +export { getExportPathForUser } from './getExportPathForUser'; diff --git a/packages/web-config-server/src/export/ExportSurveyDataHandler.js b/packages/web-config-server/src/export/ExportSurveyDataHandler.js index 07fc75d271..ac8932bf09 100644 --- a/packages/web-config-server/src/export/ExportSurveyDataHandler.js +++ b/packages/web-config-server/src/export/ExportSurveyDataHandler.js @@ -6,6 +6,7 @@ import xlsx from 'xlsx'; import fs from 'fs'; import { getExportDatesString, respondWithDownload } from '@tupaia/utils'; +import { getExportPathForUser } from '@tupaia/server-utils'; import { requestFromTupaiaConfigServer } from './requestFromTupaiaConfigServer'; import { USER_SESSION_CONFIG } from '/authSession'; import { RouteHandler } from '/apiV1/RouteHandler'; @@ -13,7 +14,6 @@ import { ExportSurveyResponsesPermissionsChecker } from '/apiV1/permissions'; import { formatMatrixDataForExcel } from './excelFormatters/formatMatrixDataForExcel'; const EXPORT_FILE_TITLE = 'survey_response_export'; -const EXPORT_DIRECTORY = 'exports'; export class ExportSurveyDataHandler extends RouteHandler { static PermissionsChecker = ExportSurveyResponsesPermissionsChecker; @@ -108,13 +108,15 @@ export class ExportSurveyDataHandler extends RouteHandler { Sheets: sheets, }; - if (!(await fs.existsSync(EXPORT_DIRECTORY))) { - await fs.mkdirSync(EXPORT_DIRECTORY); + const exportDirectory = getExportPathForUser(this.req.user.id); + + if (!(await fs.existsSync(exportDirectory))) { + await fs.mkdirSync(exportDirectory); } - const filePath = `${EXPORT_DIRECTORY}/${EXPORT_FILE_TITLE}_${Date.now()}.xlsx`; + const filePath = `${exportDirectory}/${EXPORT_FILE_TITLE}_${Date.now()}.xlsx`; xlsx.writeFile(workbook, filePath); - respondWithDownload(this.res, filePath, true); + respondWithDownload(this.res, filePath); } } From 5e700dad6d93d720704aa2792200770abd6791d1 Mon Sep 17 00:00:00 2001 From: alexd-bes <129009580+alexd-bes@users.noreply.github.com> Date: Fri, 30 Aug 2024 15:45:53 +1200 Subject: [PATCH 4/4] Add lesmis export handler --- .../src/importExport/ExportModal.jsx | 4 +++ .../getSurveyResponsePageConfig.js | 3 ++ .../server-utils/src/constructExportEmail.ts | 33 +++++++++++-------- 3 files changed, 26 insertions(+), 14 deletions(-) diff --git a/packages/admin-panel/src/importExport/ExportModal.jsx b/packages/admin-panel/src/importExport/ExportModal.jsx index 1c7a2c3803..c7162d7555 100644 --- a/packages/admin-panel/src/importExport/ExportModal.jsx +++ b/packages/admin-panel/src/importExport/ExportModal.jsx @@ -27,6 +27,7 @@ export const ExportModal = React.memo( exportButtonText, cancelButtonText, isExportingMessage, + extraQueryParameters, }) => { const api = useApiContext(); const [status, setStatus] = useState(STATUS.IDLE); @@ -56,6 +57,7 @@ export const ExportModal = React.memo( const queryParameters = { respondWithEmailTimeout: 10 * 1000, // if an export doesn't finish in 10 seconds, email results ...values, + ...extraQueryParameters, }; const { body: response } = await api.download(endpoint, queryParameters, fileName); if (response?.emailTimeoutHit) { @@ -152,6 +154,7 @@ ExportModal.propTypes = { exportButtonText: PropTypes.string, cancelButtonText: PropTypes.string, isExportingMessage: PropTypes.string, + extraQueryParameters: PropTypes.object, }; ExportModal.defaultProps = { @@ -162,4 +165,5 @@ ExportModal.defaultProps = { isExportingMessage: 'Export is taking a while, and will continue in the background. You will be emailed the exported file when the process completes.', values: {}, + extraQueryParameters: {}, }; diff --git a/packages/lesmis/src/views/AdminPanel/routes/surveyResponses/getSurveyResponsePageConfig.js b/packages/lesmis/src/views/AdminPanel/routes/surveyResponses/getSurveyResponsePageConfig.js index 4140717aaa..fa4c05251f 100644 --- a/packages/lesmis/src/views/AdminPanel/routes/surveyResponses/getSurveyResponsePageConfig.js +++ b/packages/lesmis/src/views/AdminPanel/routes/surveyResponses/getSurveyResponsePageConfig.js @@ -106,6 +106,9 @@ export const getSurveyResponsePageConfig = (translate, path, adminUrl) => { cancelButtonText: translate('admin.cancel'), isExportingMessage: 'Export is taking a while, and will continue in the background. You will be emailed the exported file when the process completes.', + extraQueryParameters: { + platform: 'lesmisAdminPanel', + }, }; return { diff --git a/packages/server-utils/src/constructExportEmail.ts b/packages/server-utils/src/constructExportEmail.ts index 61ce4e0b45..401adc7708 100644 --- a/packages/server-utils/src/constructExportEmail.ts +++ b/packages/server-utils/src/constructExportEmail.ts @@ -17,25 +17,13 @@ type ResponseBody = { type Req = { query: { - platform?: 'tupaia' | 'adminPanel' | 'datatrak'; + platform?: 'tupaia' | 'adminPanel' | 'datatrak' | 'lesmisAdminPanel'; }; }; export const constructExportEmail = async (responseBody: ResponseBody, req: Req) => { const { error, filePath } = responseBody; const { platform } = req.query; - const subject = 'Your export from Tupaia'; - if (error) { - return { - subject, - message: `Unfortunately, your export failed. -${error}`, - }; - } - - if (!filePath) { - throw new Error('No filePath in export response body'); - } const platformKey = platform || 'adminPanel'; @@ -49,12 +37,16 @@ ${error}`, }, adminPanel: { url: requireEnv('ADMIN_PANEL_SERVER_API_URL'), - friendlyName: 'the Admin Panel', + friendlyName: 'the Tupaia Admin Panel', }, datatrak: { url: requireEnv('DATATRAK_WEB_SERVER_API_URL'), friendlyName: 'DataTrak', }, + lesmisAdminPanel: { + url: requireEnv('ADMIN_PANEL_SERVER_API_URL'), + friendlyName: 'the Lesmis Admin Panel', + }, }; if (!PLATFORM_SETTINGS[platformKey]) { @@ -63,6 +55,19 @@ ${error}`, const { friendlyName, url } = PLATFORM_SETTINGS[platformKey]; + const subject = `Your export from ${friendlyName}`; + if (error) { + return { + subject, + message: `Unfortunately, your export failed. +${error}`, + }; + } + + if (!filePath) { + throw new Error('No filePath in export response body'); + } + const downloadLink = createDownloadLink(filePath, url); return { subject,