diff --git a/controllers/project.js b/controllers/project.js index c3da144..f555917 100644 --- a/controllers/project.js +++ b/controllers/project.js @@ -258,4 +258,29 @@ async function getCompletionState(projectId, schema) { } } -module.exports = { getUserProjects, getCompletionState, getUserProjectMetrics, addRiskScoreToProject }; \ No newline at end of file +async function getProjectOwner(project) { + try { + // Validate that the project object has an owner field + if (!project || !project.owner) { + throw new Error("Invalid project object or missing owner field"); + } + + // Find the owner user by ID + const owner = await User.findById(project.owner); + if (!owner) { + throw new Error("Owner not found"); + } + + // Return owner details + return { + id: owner._id, + name: owner.name, + email: owner.email + }; + } catch (error) { + console.error("Error retrieving project owner:", error); + throw error; // Propagate the error to the caller + } +} + +module.exports = { getUserProjects, getCompletionState, getUserProjectMetrics, addRiskScoreToProject, getProjectOwner }; \ No newline at end of file diff --git a/lib/docxBuilder.js b/lib/docxBuilder.js index 069d531..5184b16 100644 --- a/lib/docxBuilder.js +++ b/lib/docxBuilder.js @@ -79,7 +79,7 @@ async function getImage(riskCounts) { return buf; } -async function buildDocx(project,metrics) { +async function buildDocx(project,metrics, owner) { const donutChartData = await getImage(metrics.riskCounts); try { @@ -87,6 +87,9 @@ async function buildDocx(project,metrics) { const doc = await docx.patchDocument(fs.readFileSync("./public/data/template.docx"), { outputType: "nodebuffer", + features: { + updateFields: true, + }, patches: { doctitle: { type: docx.PatchType.PARAGRAPH, @@ -103,6 +106,12 @@ async function buildDocx(project,metrics) { new docx.TextRun(project.title) ] }, + author: { + type: docx.PatchType.PARAGRAPH, + children: [ + new docx.TextRun(owner.name + " (" + owner.email + ")") + ] + }, footertitle: { type: docx.PatchType.PARAGRAPH, children: [ diff --git a/routes/project.js b/routes/project.js index 84ebd3c..71161c4 100644 --- a/routes/project.js +++ b/routes/project.js @@ -194,10 +194,11 @@ router.get('/:id', ensureAuthenticated, checkProjectAccess, loadProject, async ( } else if (acceptHeader === 'application/vnd.openxmlformats-officedocument.wordprocessingml.document') { // Respond with DOCX project = await projectController.addRiskScoreToProject(project); + let owner = await projectController.getProjectOwner(project); const userProjects = []; userProjects.push(project); let metrics = await projectController.getUserProjectMetrics(userProjects); - const tempFilePath = await buildDocx(project,metrics); + const tempFilePath = await buildDocx(project,metrics, owner); const fileName = `${project.title.replace(/\s+/g, '_').trim()}.docx`; //const buffer = await docx.Packer.toBuffer(doc); res.set('Content-Disposition', `attachment; filename="${fileName}"`); diff --git a/views/pages/home.ejs b/views/pages/home.ejs index fb61640..b18d50e 100644 --- a/views/pages/home.ejs +++ b/views/pages/home.ejs @@ -45,7 +45,7 @@ height: auto; vertical-align: bottom; padding-right: 10px;" src="/images/icons_arrow-blue-2d56bf3e.svg" alt=">"/>Select from example case studies: -

Learn how to conduct a Consequence Scan by working through one of our example case studies and identify consequences, determine risk and plan actions.

+

Learn how to conduct a Consequence Scan by working through one of our example case studies and identify consequences, determine risks and plan actions.

{ try { + // Show an alert to inform users about updating the table of contents + alert("Once the document has downloaded, you will need to update the table of contents to correct page numbering and titles."); + + // Fetch the document const response = await fetch(`/project/${projectId}`, { headers: { "Accept": "application/vnd.openxmlformats-officedocument.wordprocessingml.document"