var express = require('express'); var fs = require('fs'); var _ = require('lodash'); var parseString = require("xml2js").parseString; var router = express.Router(); let searchTagsForHebdoReport = /\b(dev|sysadmin|écriture|edu|fediverse|april|chapril)\b/g; let convertFiles = true; // let convertFiles = false; let computeDataOnExtract = true; // let computeDataOnExtract = false; let jsonAllData = { all: {}, tasks: {}, stats: {}, projects: {}, tags: {}, weeklyDevReport: '' } /* GET home page. */ /** * convertir le fichier XML et * obtenir la liste de tags que l'on a entré dans GTG */ router.get('/xml', async function (req, res, next) { console.log(' ### lecture de sources/gtg_data.xml'); fs.stat('sources/gtg_data.xml', function (err, stat) { if (err == null) { console.log('File sources/gtg_data.xml exists'); } else if (err.code === 'ENOENT') { // file does not exist res.send('le fichier sources/gtg_data.xml est introuvable. Impossible d en extraire des infos. Importez d abord les fichiers de données xml de Getting Things Gnome dans le dossier sources') } else { console.log('Some other error: ', err.code); } }); convertOneXmlToJson('gtg_data', res) console.log('success conversion xml') res.render('layout', { title: 'Conversion en Json', message: 'ok fichier converti' }) // res.redirect('/') }) /** * voir le compte rendu des tâches */ router.get('/', async function (req, res, next) { console.log(" ### récupérer le contenu des json sources/gtg_data_gtg.json") jsonAllData.all = require('../sources/gtg_data_gtg.json') if (!jsonAllData.all.gtgData) { res.redirect('/xml') } if (computeDataOnExtract) { jsonAllData = computeData(jsonAllData) computeDataOnExtract = false; } else { console.log('================== calcul de stats désactivé dans index.js ================== ') } exportToMarkdown(res) console.log('json files read') res.render('index', { title: "Conversion de GTG tâches", json: jsonAllData, markdown: markdownExportData, getPercent, computeBgColorOnProportionOfOpenTasks, getPercentOfOpenTasks }) }); async function readfileJson(fileToOpen) { fs.readFile(`sources/${fileToOpen}`, "utf-8", function (err, data) { if (err) console.log(err); console.log('ok ', fileToOpen) return JSON.parse(data) }); } function computeData(jsonConvertedData) { let gtgData = jsonConvertedData.all.gtgData console.log('================== calcul des tâches depuis le fichier json ================== ') console.log('gtgData : '); console.log(gtgData); // trouver le nombre de tâches ayant un tag en particulier // et rajouter ce nombre à chaque tag, dans countTasks : N let counterOfTasks = gtgData.tasklist[0].task // compter les tâches // console.log('counterOfTasks',counterOfTasks); jsonAllData.all = gtgData jsonAllData.stats = { tasksCount : counterOfTasks.length, // tasksCount: 0, tasksClosed: 0, tasksOpen: 0, maxTasksCountPerTag: 0, listTags: [], listOpen: [], listOpenWeekly: [], listOpenMonthly: [], listClosed: [], listClosedWeekly: [], tasksListIsDismissByTitle: [], listDevWeeklyClosed: [], listDevWeeklyOpen: [], listClosedMonthly: [], } let now = new Date(); jsonAllData.stats.listTags = gtgData.taglist[0].tag console.log('tasks', gtgData.tasklist[0].task); for (let taskItem of gtgData.tasklist[0].task) { // count open and closed tasks let now = new Date() if (taskItem['$'].status == 'Active') { jsonAllData.stats.listOpen.push(taskItem) let addeddate = new Date(taskItem.addeddate) let daysDiff = getNumberOfDaysDiffTwoDates(addeddate, now); if (daysDiff <= 7) { jsonAllData.stats.listOpenWeekly.push(taskItem) // listDevWeeklyOpen // tâches uniquement de dev if ((searchTagsForHebdoReport).test(taskItem['$'].tags) ) { jsonAllData.stats.listDevWeeklyOpen.push(taskItem) } } else if (daysDiff >= 7 & daysDiff <= 31) { jsonAllData.stats.listOpenMonthly.push(taskItem) } } else if (taskItem['$'].status == 'Done') { jsonAllData.stats.listClosed.push(taskItem) let donedate = new Date(taskItem.donedate) let daysDiff = getNumberOfDaysDiffTwoDates(donedate, now); if (daysDiff <= 7) { jsonAllData.stats.listClosedWeekly.push(taskItem) // tâches uniquement de dev if ((searchTagsForHebdoReport).test(taskItem['$'].tags) ) { jsonAllData.stats.listDevWeeklyClosed.push(taskItem) } } else if (daysDiff >= 7 & daysDiff <= 31) { jsonAllData.stats.listClosedMonthly.push(taskItem) } } for (let tag of jsonAllData.stats.listTags) { // console.log('tag', tag) jsonAllData.stats.listTags.map(elem => { // console.log('elem', elem) if (elem['$'].name == tag) { if (!elem.tasks) { elem.tasks = 0 } if (!elem.tasksListById) { elem.tasksListById = [] } if (!elem.tasksListByTitle) { elem.tasksListByTitle = [] } if (!elem.tasksListIsActiveByTitle) { elem.tasksListIsActiveByTitle = [] } if (!elem.tasksListIsDoneByTitle) { elem.tasksListIsDoneByTitle = [] } elem.tasks++ elem.tasksListById.push(taskItem['$'].id) elem.tasksListByTitle.push(taskItem.title) if (taskItem['$'].status == "Active") { elem.tasksListIsActiveByTitle.push(taskItem.title) } if (taskItem['$'].status == "Done") { elem.tasksListIsDoneByTitle.push(taskItem.title) } if (taskItem['$'].status == "Dismiss") { elem.tasksListIsDismissByTitle.push(taskItem.title) } } if (elem.tasks > jsonAllData.stats.maxTasksCountPerTag) { jsonAllData.stats.maxTasksCountPerTag = elem.tasks } }) } } // sort tags by name console.log('stats', jsonAllData); return jsonAllData } const oneDay = 24 * 60 * 60 * 1000; // hours*minutes*seconds*milliseconds function getNumberOfDaysDiffTwoDates(firstDate, secondDate) { return Math.round(Math.abs((firstDate - secondDate) / oneDay)); } function convertOneXmlToJson(fileToOpen, res) { fs.readFile(`sources/${fileToOpen}.xml`, "utf-8", function (err, data) { if (err) console.log(err); const results = transformToJson(data, fileToOpen, res) console.log('#### fichier converti en json', res) }); } function getPercentOfOpenTasks(someCount) { return Math.round(100 * someCount / jsonAllData.stats.tasksOpen) } function getPercent(someCount, total) { return Math.round(100 * someCount / total) } function computeBgColorOnProportionOfOpenTasks(someProportionNumber) { let result = ''; if (someProportionNumber >= 95) { result = 'proportion-over-95' } else if (someProportionNumber >= 90) { result = 'proportion-over-90' } else if (someProportionNumber >= 80) { result = 'proportion-over-80' } else if (someProportionNumber >= 65) { result = 'proportion-over-65' } else if (someProportionNumber >= 50) { result = 'proportion-over-50' } else if (someProportionNumber >= 40) { result = 'proportion-over-40' } else if (someProportionNumber >= 25) { result = 'proportion-over-25' } else if (someProportionNumber >= 15) { result = 'proportion-over-15' } return result; } let datenow = new Date(); let markdownExportData = '' let dataTagsMd = '' function exportToMarkdown(res) { let weeklyDevReport = '' console.log('jsonAllData.stats', jsonAllData.stats); markdownExportData = `# Export de Tâches GTG \n date: ` + datenow.toLocaleString() // fichier de rapport des tâches fermées durant les 7 derniers jours weeklyDevReport = `\n# Rapport hebdomadaire de dev `; weeklyDevReport += `\n## 1/ Actions passées ou en cours \n ` weeklyDevReport += `\r\n## ${jsonAllData.stats.listDevWeeklyClosed.length} ont été fermées \n___`; jsonAllData.stats.listDevWeeklyClosed.map(elem => { weeklyDevReport += `\n| ${elem['$'].tags} | ${elem.title}|`; }) weeklyDevReport += ` \n___ \n \n## 2/ Actions à venir \n ` weeklyDevReport += `\r\n## ${jsonAllData.stats.listDevWeeklyOpen.length} ont été ouvertes \n___`; jsonAllData.stats.listDevWeeklyOpen.map(elem => { // weeklyDevReport += `\n| ${elem['$'].tags} | ${elem.title}|`; weeklyDevReport += `\n| ${elem.title}|`; }) weeklyDevReport += ` \n___ \n \n## 3/ Points de blocage / points en retard corrigés cette semaine \n \n## 4/ Points de blocage existants / points en retard à traiter \n \n## 5/ Points forts de la semaine \n \n## 6/ Points de vigilance de la semaine \n \n## 7/ Points forts de la réunion \n \n## 8/ Points de vigilance de la réunion `; markdownExportData += `\n ${weeklyDevReport}`; markdownExportData += `\n---`; markdownExportData += `\n `; markdownExportData += `\n# Rapport des tâches durant les 7 derniers jours `; markdownExportData += `\n `; markdownExportData += `\n## ${jsonAllData.stats.listClosedWeekly.length} ont été fermées `; markdownExportData += `\n `; jsonAllData.stats.listClosedWeekly.map(elem => { markdownExportData += `\n * ${elem.title}`; }) markdownExportData += `\n## ${jsonAllData.stats.listOpenWeekly.length} ont été ouvertes `; markdownExportData += `\n `; jsonAllData.stats.listOpenWeekly.map(elem => { markdownExportData += `\n * ${elem.title}`; }) markdownExportData += `\n--- `; // fichier de rapport des tâches fermées durant les 31 derniers jours markdownExportData += `\n# Rapport des autres tâches durant le mois `; markdownExportData += `\n `; markdownExportData += `\n## ${jsonAllData.stats.listClosedMonthly.length} ont été fermées `; markdownExportData += `\n `; jsonAllData.stats.listClosedMonthly.map(elem => { markdownExportData += `\n * ${elem.title}`; }) markdownExportData += `\n## ${jsonAllData.stats.listOpenMonthly.length} ont été ouvertes `; markdownExportData += `\n `; jsonAllData.stats.listOpenMonthly.map(elem => { markdownExportData += `\n * ${elem.title}`; }) markdownExportData += `\n--- `; // stats de fermeture des tâches markdownExportData += `\n# Stats de fermeture des tâches `; markdownExportData += `\n `; markdownExportData += `\n--- `; markdownExportData += `\n `; markdownExportData += `\n# Export de toutes les ${jsonAllData.stats.listOpen.length} tâches ouvertes GTG \n `; markdownExportData += `\n `; jsonAllData.stats.listOpen.map(elem => { dataTagsMd += `\n## ${elem.title} `; dataTagsMd += `\n statut : ${elem['$'].status} `; dataTagsMd += `\n créé le : ${elem.addeddate} `; dataTagsMd += `\n modifié le : ${elem.modified} `; dataTagsMd += `\n prévu pour : ${elem.duedate | ''} `; dataTagsMd += `\n ${elem.content} `; }) markdownExportData += `\n--- `; markdownExportData += `\n `; markdownExportData += `\n# Export de toutes les ${jsonAllData.stats.listClosed.length} tâches fermées GTG \n `; markdownExportData += `\n `; jsonAllData.stats.listClosed.map(elem=>{ dataTagsMd += `\n * ${elem.title} `; }) markdownExportData += `\n `; markdownExportData += `\n# Export de Tags GTG \n `; markdownExportData += `\n `; markdownExportData += `\n `; let sortedTagsByTitle = _.sortBy(jsonAllData.stats.listTags, [(o) => { o["$"].name }]) sortedTagsByTitle.map(elem => { markdownExportData += `\n * ${elem['$'].name} , ${elem.tasks | 0}`; }) markdownExportData += `\n `; markdownExportData += `\n rapport généré avec gtg2nodejs par tykayn - contact@cipherbliss.com `; jsonAllData.weeklyDevReport = weeklyDevReport; // write file to disk fs.writeFile(`output/export_hebdo.md`, markdownExportData, `utf8`, (err) => { if (err) { console.log(`Error writing file: ${err}`); res.send(err) } else { console.log(`File \`output/export_tags.md\` is written successfully!`); } }); } /** * transformToJson * @param xml * @param fileToOpen * @param res * @returns {*} */ function transformToJson(xml, fileToOpen, res) { return parseString(xml, function (err, result) { if (err) console.log(err); // console.dir(JSON.stringify(result)); console.log('Done'); // write file to disk fs.writeFile(`output/${fileToOpen}_gtg.json`, JSON.stringify(result, null, 4), 'utf8', (err) => { if (err) { console.log(`Error writing file: ${err}`); // return JSON.stringify(result) res.send(err) } else { console.log(` ### File \`output/${fileToOpen}_gtg.json\` is written successfully!`); } }); }); } module.exports = router;