Compare commits

...

9 Commits

  1. 12165
      package-lock.json
  2. 6
      package.json
  3. 3
      src/app.js
  4. 12
      src/assets/js/main.js
  5. 10
      src/config/params.json
  6. 7
      src/services/file.js
  7. 20
      src/services/template.js
  8. 32
      src/subscribers/consoleSubscriber.js
  9. 114
      src/subscribers/emailSubscriber.js
  10. 2
      src/subscribers/ioSubscriber.js
  11. 7
      src/views/emails/parse-success.hbs
  12. 13
      src/views/layout/email.hbs

12165
package-lock.json

File diff suppressed because it is too large

6
package.json

@ -10,6 +10,8 @@
"watch": "webpack --watch --mode development"
},
"dependencies": {
"@popperjs/core": "^2.11.8",
"axios": "^1.5.1",
"bootstrap": "^5.3.2",
"cookie-parser": "^1.4.6",
"csv-parser": "^3.0.0",
@ -22,13 +24,13 @@
"http-errors": "^2.0.0",
"jquery": "^3.7.1",
"morgan": "^1.10.0",
"popper.js": "^1.16.1",
"slugify": "^1.6.6",
"socket.io": "^4.7.2",
"socket.io-client": "^4.7.2",
"toastr": "^2.1.4"
},
"devDependencies": {
"@babel/core": "^7.23.2",
"@babel/preset-env": "^7.22.20",
"babel-core": "^6.26.3",
"babel-loader": "^9.1.3",
@ -37,7 +39,7 @@
"css-loader": "^6.8.1",
"css-minimizer-webpack-plugin": "^5.0.1",
"mini-css-extract-plugin": "^2.7.6",
"node-sass": "^4.9.4",
"node-sass": "^9.0.0",
"nodemon": "^3.0.1",
"sass-loader": "^13.3.2",
"webpack": "^5.88.2",

3
src/app.js

@ -8,6 +8,7 @@ const { basedir } = require('./config/constants');
var indexRouter = require('./routes/index');
const consoleSubscriber = require('./subscribers/consoleSubscriber');
const mailerSubscriber = require('./subscribers/emailSubscriber');
var app = express();
@ -26,6 +27,8 @@ app.use(express.urlencoded({ extended: true }));
app.use(cookieParser());
app.use(express.static(path.join(basedir, 'public')));
mailerSubscriber(app);
app.use('/', indexRouter);
// catch 404 and forward to error handler

12
src/assets/js/main.js

@ -95,7 +95,7 @@ const initSubmitForm = () => {
sendRequest($form.attr('action'), data)
.then((response) => {
toastr.success(response.message);
// toastr.success(response.message);
$submitBtn.prop('disabled', false);
$spinner.addClass('d-none');
if ( response.generated ) {
@ -143,6 +143,16 @@ const initSocket = () => {
return;
}
if (eventName === 'parse.end') {
toastr.success(data.message, '', {
closeButton: true,
hideDuration: 0,
timeOut: 0,
extendedTimeOut: 0,
});
return;
}
toastr.info(data.message);
});
}

10
src/config/params.json

@ -0,0 +1,10 @@
{
"sendgrid": {
"to": "onja@blastream.com",
"from": "contact@blastream.com",
"fromName": "Blastream",
"uri": "https://api.sendgrid.com/v3/mail/send",
"application_key": "YABUthwqTla79YQbR7gToQ",
"application_secret": "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"
}
}

7
src/services/file.js

@ -76,15 +76,16 @@ class FileService {
emitter.emit('checkLastOperationDate.start', { dateFilePath });
try {
const oneDay = 48 * 60 * 60 * 1000; // Un jour en millisecondes
const oneDay = 5 * 24 * 60 * 60 * 1000; // 5 jour en millisecondes
const fileDate = 6 * 24 * 60 * 60 * 1000; // 6 jour en millisecondes
const currentDate = new Date();
// Check if file exists and create it if not with a default date of 48 hours ago
if (!fs.existsSync(dateFilePath)) {
emitter.emit('checkLastOperationDate.created', { dateFilePath });
const twodaysdate = new Date(currentDate - (1.5*oneDay));
fs.writeFileSync(dateFilePath, twodaysdate.toISOString(), 'utf-8');
const defaultFiledate = new Date(currentDate - (fileDate)); // 6 jours avant la date actuelle
fs.writeFileSync(dateFilePath, defaultFiledate.toISOString(), 'utf-8');
}
const lastOperationDate = fs.readFileSync(dateFilePath, 'utf-8');

20
src/services/template.js

@ -74,6 +74,26 @@ class TemplateService {
return layoutTemplate;
}
renderEmail(name, data = {}, params = {}) {
// Get the page template
const pageTemplate = this.render(`emails/${name}`, data, params);
if ( !pageTemplate ) {
return '';
}
// Get the layout template
const layoutTemplate = this.render(`layout/email`, {...data, ...{ body: pageTemplate }}, params);
if ( !layoutTemplate ) {
return '';
}
return layoutTemplate;
}
}

32
src/subscribers/consoleSubscriber.js

@ -3,7 +3,7 @@ const emitter = require('../services/eventEmitter');
// Create a log function that logs the event name and the data
const log = (event, data) => {
console.log(`----- Event: ${event} ----- `);
console.log(`----- [${(new Date()).toLocaleString()}] Event: ${event} ----- `);
console.log(data);
console.log('-----');
};
@ -44,9 +44,9 @@ emitter.on('parseFromUrl.start', ({ url, columns }) => {
});
// Create a new listener for the parseFromUrl.end event
emitter.on('parseFromUrl.end', ({ url, columns, filepath }) => {
// log('parseFromUrl.end', `Parsed ${url} with columns ${columns.join(', ')} to ${filepath}`);
log('parseFromUrl.end', `Parsed with columns to ${filepath}`);
emitter.on('parseFromUrl.end', ({ url, columns, filename }) => {
// log('parseFromUrl.end', `Parsed ${url} with columns ${columns.join(', ')} to ${filename}`);
log('parseFromUrl.end', `Parsed with columns to ${filename}`);
});
// Create a new listener for the parseFromUrl.error event
@ -131,3 +131,27 @@ emitter.on('checkLastOperationDate.updated', ({ dateFilePath, date }) => {
emitter.on('checkLastOperationDate.skipped', ({ dateFilePath, date }) => {
log('checkLastOperationDate.skipped', `Skipped last operation date - Date: ${date}`);
});
emitter.on('mailer.parse.end.success', ({ response }) => {
log('mailer.parse.end.success', response);
});
emitter.on('mailer.parse.end.error', ({ error }) => {
log('mailer.parse.end.error', error);
});
emitter.on('mailer.parse.error.success', ({ response }) => {
log('mailer.parse.error.success', response);
});
emitter.on('mailer.parse.error.error', ({ error }) => {
log('mailer.parse.error.error', error);
});
emitter.on('mailer.parseFromUrl.error.success', ({ response }) => {
log('mailer.parseFromUrl.error.success', response);
});
emitter.on('mailer.parseFromUrl.error.error', ({ error }) => {
log('mailer.parseFromUrl.error.error', error);
});

114
src/subscribers/emailSubscriber.js

@ -0,0 +1,114 @@
const emitter = require('../services/eventEmitter');
const axios = require('axios');
const params = require('../config/params');
const TemplateService = require('../services/template');
const templateService = new TemplateService();
const errorResponse = (error) => {
if (error.response) {
return error.response.status + ' - ' + error.response.statusText;
} else if (error.request) {
// The request was made but no response was received
// `error.request` is an instance of XMLHttpRequest in the browser and an instance of
// http.ClientRequest in node.js
return error.request;
} else {
return error.message;
}
};
module.exports = (app) => {
// Get app url
let host = '';
app.use((req, res, next) => {
console.log('--- APP_URL ---', req.protocol + '://' + req.get('host'));
host = req.protocol + '://' + req.get('host');
next();
});
// Check if sendgrid params exists
if ( !params.sendgrid ) {
console.log('--- No sendgrid params ---');
return;
}
console.log('--- sendgrid params exists ---');
const sendgridParams = params.sendgrid;
const defaultParams = {
url: sendgridParams.uri,
headers: {
Authorization: 'Bearer ' + sendgridParams.application_secret,
'Content-Type': 'application/json',
},
};
const sendEmail = async (to, subject, message) => {
const data = {
personalizations: [
{
to: [
{
email: to,
}
],
subject: subject
}
],
content: [
{
type: "text/html",
value: message
}
],
from: {
email: sendgridParams.from,
name: sendgridParams.fromName,
}
};
const response = await axios.post(defaultParams.url, data, { headers: defaultParams.headers });
return response;
}
// Create a new listener for the parse.end event
emitter.on('parse.end', async ({ url, columns, count, generated }) => {
console.log('HOST', host);
try {
const message = templateService.renderEmail('parse-success', {
host,
generated,
count,
columns,
url,
});
const response = await sendEmail(sendgridParams.to, 'BODACC - Traitement terminé', message);
emitter.emit('mailer.parse.end.success', { response: response.data });
} catch (error) {
emitter.emit('mailer.parse.end.error', { error: errorResponse(error) });
}
});
// Create a new listener for the parse.error event
emitter.on('parse.error', async ({ filepath, columns, error }) => {
try {
const reponse = await sendEmail(sendgridParams.to, 'BODACC - Erreur traitement', '<p>Erreur traitement</p><br /><p>Voici le message d\'erreur: ' + error + '</p>')
emitter.emit('mailer.parse.error.success', { response: response });
} catch (error) {
emitter.emit('mailer.parse.error.error', { error: errorResponse(error) });
}
});
// Create a new listener for the parseFromUrl.error event
emitter.on('parseFromUrl.error', async ({ url, columns, error }) => {
try {
const response = await sendEmail(sendgridParams.to, 'BODACC - Erreur génération fichier', '<p>Erreur génération fichier</p><br /><p>Voici le message d\'erreur: ' + error + '</p>')
emitter.emit('mailer.parseFromUrl.error.success', { response: response.data });
} catch (error) {
emitter.emit('mailer.parseFromUrl.error.error', { error: errorResponse(error) });
}
});
};

2
src/subscribers/ioSubscriber.js

@ -32,7 +32,7 @@ const configure = (socket) => {
// Create a new listener for the parse.end event
emitter.on('parse.end', ({ filepath, columns, count, generated }) => {
socket.emit('parse.end', { event: 'parse.end', message: 'Traitement terminé', generated });
socket.emit('parse.end', { event: 'parse.end', message: 'Traitement terminé: <br /><br />Lien de téléchargement <a href="/csv/' + generated + '">' + generated + '</a>', generated });
});
// Create a new listener for the parse.error event

7
src/views/emails/parse-success.hbs

@ -0,0 +1,7 @@
<p>Bonjour, </p>
<br />
<p>Le traitement de votre fichier depuis l'url <strong>{{url}}</strong> est terminé</p>
<p><strong>{{count}} lignes</strong> ont été générés</p>
<br />
<p>Voici le lien pour télécharger le fichier généré: <a href="{{host}}/csv/{{generated}}"><strong>{{host}}/csv/{{generated}}</strong></a></p>

13
src/views/layout/email.hbs

@ -0,0 +1,13 @@
<div class="email-layout">
<div class="email-layout__inner">
<div class="email-layout__header">
</div>
<div class="email-layout__body">
{{{body}}}
</div>
<div class="email-layout__footer">
</div>
</div>
</div>
Loading…
Cancel
Save