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: {}, } /* 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, weeklyDevReport, 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 = jsonConvertedData.tasklist // compter les tâches // console.log('counterOfTasks',counterOfTasks); jsonAllData.stats = { // tasksCount : counterOfTasks.length, tasksCount: 0, tasksClosed: 0, tasksOpen: 0, maxTasksCountPerTag: 0, listTags: [], listOpen: [], listOpenWeekly: [], listOpenMonthly: [], listClosed: [], listClosedWeekly: [], 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.tags.tagstore.tag.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 (elem.tasks > gtgData.stats.maxTasksCountPerTag) { // jsonAllData.stats.maxTasksCountPerTag = elem.tasks // } // }) } } // sort tags by name console.log('stats', jsonAllData.stats); return jsonAllData.stats } 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 weeklyDevReport = '' function exportToMarkdown(res) { 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.tags.tagstore.tag, [(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 `; // 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;