diff --git a/ExpressAPI/package-lock.json b/ExpressAPI/package-lock.json index 7b82bc40ff98cb51d828583d96533e78872d6388..86b94895ffa3cf83a5d35c3af3aa07b7015511fa 100644 --- a/ExpressAPI/package-lock.json +++ b/ExpressAPI/package-lock.json @@ -21,6 +21,7 @@ "express": "^4.19.2", "express-validator": "^7.1.0", "form-data": "^4.0.0", + "handlebars": "^4.7.8", "helmet": "^7.1.0", "http-status-codes": "^2.3.0", "json5": "^2.2.3", @@ -4080,7 +4081,7 @@ "version": "4.7.8", "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", - "dev": true, + "license": "MIT", "dependencies": { "minimist": "^1.2.5", "neo-async": "^2.6.2", @@ -5080,8 +5081,7 @@ "node_modules/neo-async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" }, "node_modules/node": { "version": "20.12.0", @@ -9169,7 +9169,6 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -9589,7 +9588,6 @@ "version": "3.17.4", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==", - "dev": true, "optional": true, "bin": { "uglifyjs": "bin/uglifyjs" @@ -9784,8 +9782,7 @@ "node_modules/wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", - "dev": true + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==" }, "node_modules/wrap-ansi": { "version": "6.2.0", diff --git a/ExpressAPI/package.json b/ExpressAPI/package.json index 0b162346c2906bed229f2cd67216f4941dbbaef6..6a9fe760324df089ab5763985c0ad7f66adcd73b 100644 --- a/ExpressAPI/package.json +++ b/ExpressAPI/package.json @@ -40,6 +40,7 @@ "express": "^4.19.2", "express-validator": "^7.1.0", "form-data": "^4.0.0", + "handlebars": "^4.7.8", "helmet": "^7.1.0", "http-status-codes": "^2.3.0", "json5": "^2.2.3", diff --git a/ExpressAPI/src/routes/UserRoutes.ts b/ExpressAPI/src/routes/UserRoutes.ts index b48a6465ed76f754548c8c4bf4b3c06af3786af9..0426ce51d03ab8c58400562b816d6874adf62606 100644 --- a/ExpressAPI/src/routes/UserRoutes.ts +++ b/ExpressAPI/src/routes/UserRoutes.ts @@ -9,8 +9,8 @@ import fs from 'fs'; import path from 'path'; import logger from '../shared/logging/WinstonLogger.js'; import GitlabManager from '../managers/GitlabManager.js'; -import archiver from 'archiver'; - +import archiver from 'archiver'; +import Handlebars from 'handlebars'; class UserRoutes implements RoutesManager { registerOnBackend(backend: Express): void { @@ -21,6 +21,7 @@ class UserRoutes implements RoutesManager { backend.get('/users/:userId/resume', SecurityMiddleware.check(true, SecurityCheckType.TEACHING_STAFF), this.createResume.bind(this) as RequestHandler); backend.get('/users/:userId/portfolio', SecurityMiddleware.check(true, SecurityCheckType.TEACHING_STAFF), this.createPortfolio.bind(this) as RequestHandler); backend.get('/users/:userId/zip', SecurityMiddleware.check(true, SecurityCheckType.TEACHING_STAFF), this.zipExport.bind(this) as RequestHandler); + backend.get('/users/:userId/staticpage', SecurityMiddleware.check(true, SecurityCheckType.TEACHING_STAFF), this.createStaticPage.bind(this) as RequestHandler); } private async getUsers(req: express.Request, res: express.Response) { @@ -94,16 +95,10 @@ class UserRoutes implements RoutesManager { } }, }); - const contentIndex = `+++ -title = "Resume" -description = "Resume for all assignments" -template = "docs/section.html" -sort_by = "weight" -weight = 0 -+++`; const folderPath = `/tmp/` + dataUser?.gitlabUsername; const pathResume = path.join(folderPath, "resume"); + // create folder try { fs.mkdirSync(folderPath); @@ -119,52 +114,44 @@ weight = 0 return req.session.sendResponse(res, StatusCodes.OK, false); } - const indexPath = path.join(pathResume, "_index.md"); - // write _index file - fs.writeFile(indexPath, contentIndex, (err) => { - if (err) { - console.log(err); - return req.session.sendResponse(res, StatusCodes.OK, false); + if (dataUser) { + interface Assignment { + assignmentName: string; + assignmentLink: string; } - else { - console.log("_index file written successfully\n"); + + const data: { title: string; assign: Assignment[] } = { + title: 'Resume', + assign: [] + }; + + if (dataUser) { + dataUser.assignments.forEach(el => { + data.assign.push({ assignmentName : el.name, assignmentLink : el.gitlabLink}); + }); } - }); - if (dataUser) { - let cpt = 1; - dataUser.assignments.forEach(a => { - const gitlabCreationInfo = a.gitlabCreationInfo as any; - const nameFile = a.name.replace(/ /g, "_"); - const filePath = path.join(pathResume, `${cpt}_${nameFile}.md`); - const templateFile = `+++ -title = "Resume of ${a.name}" -description = "TEST" -slug = "${nameFile}" -template = "docs/page.html" -weight = ${cpt} -+++ + + const templatePath = path.join(__dirname, 'templates', 'index.handlebars'); + + fs.readFile(templatePath, 'utf-8', (err, template) => { + if (err) { + res.status(500).send('Error exporting assignment'); + return; + } -## Description + const compiledTemplate = Handlebars.compile(template); + const html = compiledTemplate(data); -${gitlabCreationInfo.description} - -## Lien git -[Repository link](${a.gitlabLink})`; - cpt++; + if (!fs.existsSync(pathResume)) { + fs.mkdirSync(pathResume, { recursive: true }); + } - fs.writeFile(filePath, templateFile, (err) => { - if (err) { - console.log(err); - return req.session.sendResponse(res, StatusCodes.OK, false); - } - else { - console.log(`File ${a.name} written successfully\n`); - } - }); + const outputPath = path.join(pathResume, 'index.html'); + fs.writeFileSync(outputPath, html); + + return req.session.sendResponse(res, StatusCodes.OK, true); }); } - - return req.session.sendResponse(res, StatusCodes.OK, true); } private async createPortfolio(req: express.Request, res: express.Response) { @@ -203,7 +190,7 @@ ${gitlabCreationInfo.description} const zipName = a.name.replace(/ /g, "_") + '.tar.gz'; const zipPath = path.join(pathPortfolio+ '/assignments', zipName); - fs.writeFile(zipPath, buffer, (err) => { + await fs.writeFile(zipPath, buffer, (err) => { if (err) { console.error('Error saving archive:', err); } else { @@ -218,7 +205,7 @@ ${gitlabCreationInfo.description} const zipName = a.name.replace(/ /g, "_") + '.tar.gz'; const zipPath = path.join(pathPortfolio + '/exercises', zipName); - fs.writeFile(zipPath, buffer, (err) => { + await fs.writeFile(zipPath, buffer, (err) => { if (err) { console.error('Error saving archive:', err); } else { @@ -241,6 +228,7 @@ ${gitlabCreationInfo.description} id: id, } }); + if (dataUser) { const folderPath = path.join('/tmp', `${dataUser.gitlabUsername}`); const zipPath = path.join('/tmp', `${dataUser.gitlabUsername}.zip`); @@ -277,6 +265,67 @@ ${gitlabCreationInfo.description} }); } } + + private async createStaticPage(req : express.Request, res : express.Response) { + const id = +req.params.userId; + + const dataUser = await db.user.findUnique({ + where: { + id: id, + }, + include: { + assignments: { + where: { + deleted: false + } + }, + exercises : true + }, + }); + + const data = { + title: 'Resume', + assign: [ + { assignmentName : '', assignmentLink : ''} + ], + exo : [ + { exerciseName: '', exerciseLink : ''} + ] + }; + + if (dataUser) { + dataUser.assignments.forEach(el => { + data.assign.push({ assignmentName : el.name, assignmentLink : el.gitlabLink}); + }); + + dataUser.exercises.forEach(el => { + data.exo.push({ exerciseName : el.name, exerciseLink : el.gitlabLink}); + }); + } + + const outputDir = path.join('/tmp/kelly.nguyen'); + + const templatePath = path.join(__dirname, 'templates', 'index.handlebars'); + console.log(templatePath); + fs.readFile(templatePath, 'utf-8', (err, template) => { + if (err) { + res.status(500).send('Error exporting assignment'); + return; + } + + const compiledTemplate = Handlebars.compile(template); + const html = compiledTemplate(data); + + if (!fs.existsSync(outputDir)) { + fs.mkdirSync(outputDir, { recursive: true }); + } + + const outputPath = path.join(outputDir, 'index.html'); + fs.writeFileSync(outputPath, html); + + return req.session.sendResponse(res, StatusCodes.OK, 'Its working'); + }); + } } export default new UserRoutes(); diff --git a/ExpressAPI/src/routes/templates/index.handlebars b/ExpressAPI/src/routes/templates/index.handlebars new file mode 100644 index 0000000000000000000000000000000000000000..576f59801efa3a99882ac931de18f5bf905823ee --- /dev/null +++ b/ExpressAPI/src/routes/templates/index.handlebars @@ -0,0 +1,35 @@ +<!DOCTYPE html> +<html lang="fr" data-bs-theme="dark"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous"> + <title>{{title}}</title> +</head> +<body> + <header> + <h1>{{title}}</h1> + </header> + <main> + <div class="container"> + <h2>Informations sur les utilisateurs</h2> + <table class="table table-dark"> + <thead> + <tr class="table-dark"> + <th scope="col">Assignment</th> + <th scope="col">Link</th> + </tr> + </thead> + <tbody> + {{#each assign}} + <tr class="table-dark"> + <th>{{assignmentName}}</th> + <td><a href="{{assignmentLink}}">Test</a></td> + </tr> + {{/each}} + </tbody> + </table> + </div> + </main> +</body> +</html>