add month stat for done

This commit is contained in:
Tykayn 2022-07-21 16:06:44 +02:00 committed by caligulanorris
parent 9774c15d65
commit ced08a36ac
1 changed files with 225 additions and 168 deletions

195
app.js
View File

@ -1,15 +1,18 @@
const fs = require('node-fs') const fs = require('node-fs');
const sourceFilePath = './sources/tasks.json'; const sourceFilePath = './sources/tasks.json';
const stats = { const stats = {
countAllTasks: 0, countAllTasks: 0,
tasksByDay: {} tasksByDay : [],
} tasksByMonth : [],
tasksByYear : [],
};
// const enableFilterByTag = true; // const enableFilterByTag = true;
const enableFilterByTag = false; const enableFilterByTag = false;
const filterByTag = "work"; const filterByTag = 'work';
// const outputFileName = "work_report"; // const outputFileName = "work_report";
const outputFileName = "all_tasks_report"; const outputFileName = 'all_tasks_report';
let countExcluded = 0; let countExcluded = 0;
let countIncluded = 0; let countIncluded = 0;
@ -19,10 +22,10 @@ console.log(` ### lecture de ${sourceFilePath}`);
fs.stat(sourceFilePath, function (err, stat) { fs.stat(sourceFilePath, function (err, stat) {
if (err == null) { if (err == null) {
console.log(`File ${sourceFilePath} exists`); console.log(`File ${sourceFilePath} exists`);
sortTasksFromJson(stat) sortTasksFromJson(stat);
} else if (err.code === 'ENOENT') { } else if (err.code === 'ENOENT') {
// file does not exist // file does not exist
console.error(`le fichier ${sourceFilePath} est introuvable. Impossible d en extraire des infos.`, err) console.error(`le fichier ${sourceFilePath} est introuvable. Impossible d en extraire des infos.`, err);
} else { } else {
console.log('Some other error: ', err.code); console.log('Some other error: ', err.code);
} }
@ -30,22 +33,21 @@ fs.stat(sourceFilePath, function (err, stat) {
// parcourir les tâches // parcourir les tâches
function sortTasksFromJson(statObject) { function sortTasksFromJson(statObject) {
console.log('sortTasksFromJson') console.log('sortTasksFromJson');
fs.readFile(sourceFilePath, 'utf8', function (err, data) { fs.readFile(sourceFilePath, 'utf8', function (err, data) {
if (err) { if (err) {
return console.log(err); return console.log(err);
} }
let dataTransformed = JSON.parse(data); let dataTransformed = JSON.parse(data);
// console.log('data keys ', Object.keys(dataTransformed)) // console.log('data keys ', Object.keys(dataTransformed))
if (dataTransformed["contents"]) { if (dataTransformed['contents']) {
countTasks = dataTransformed['contents'].length;
countTasks = dataTransformed["contents"].length
stats.countAllTasks = countTasks; stats.countAllTasks = countTasks;
console.log('yes data ! tasks:', countTasks) console.log('yes data ! tasks:', countTasks);
dataTransformed["contents"].forEach((elem, index) => { dataTransformed['contents'].forEach((elem, index) => {
// console.log('tâche ', index) // console.log('tâche ', index)
// évacuer les sous tâches // évacuer les sous tâches
@ -56,29 +58,28 @@ function sortTasksFromJson(statObject) {
// } // }
// filtrer par tag les tâches // filtrer par tag les tâches
if (enableFilterByTag) { if (enableFilterByTag) {
console.log('filtre activé', filterByTag) console.log('filtre activé', filterByTag);
if (!elem['drawer'] || !elem['properties']['tags']) { if (!elem['drawer'] || !elem['properties']['tags']) {
console.log('on vire cette tâche n\'ayant pas de drawer :', elem);
console.log('on vire cette tâche n\'ayant pas de drawer :', elem)
countExcluded++; countExcluded++;
return; return;
} else if ( } else if (
elem['properties'] && elem['properties'] &&
typeof elem['properties']['tags'] !== "undefined" && typeof elem['properties']['tags'] !== 'undefined' &&
elem['properties']['tags'].indexOf(filterByTag) === -1 elem['properties']['tags'].indexOf(filterByTag) === -1
) { ) {
console.log('on vire cette tâche ayant les itags :', elem['drawer']['ARCHIVE_ITAGS']) console.log('on vire cette tâche ayant les itags :', elem['drawer']['ARCHIVE_ITAGS']);
countExcluded++; countExcluded++;
return; return;
} }
} else { } else {
console.log(' - filtre désactivé') console.log(' - filtre désactivé');
} }
// après le filtre, on range les tâches // après le filtre, on range les tâches
if (elem['properties']) { if (elem['properties']) {
console.log(' - ref ', elem['ref']) console.log(' - ref ', elem['ref']);
let title = elem['properties']['raw-value']; let title = elem['properties']['raw-value'];
let tags = elem['tags'] ? elem['tags'] : []; let tags = elem['tags'] ? elem['tags'] : [];
let closeDate = 'Indéfini'; let closeDate = 'Indéfini';
@ -101,44 +102,100 @@ function sortTasksFromJson(statObject) {
// jour, 11 premiers caractères // jour, 11 premiers caractères
let day = closeDate.substring(0, 10); let day = closeDate.substring(0, 10);
if (!stats.tasksByDay[day]) { let month = closeDate.substring(0, 7);
stats.tasksByDay[day] = [] console.log('month', month)
} let year = closeDate.substring(0, 4);
stats.tasksByDay[day].push({ let taskDescription = {
todoKeyword, todoKeyword,
title, title,
day, day,
closeDate, closeDate,
tags, tags,
}) };
if (!stats.tasksByDay[day]) {
stats.tasksByDay[day] = [];
}
if (!stats.tasksByMonth[month]) {
stats.tasksByMonth[month] = {
period: month,
tasks : [],
};
}
if (!stats.tasksByYear[year]) {
stats.tasksByYear[year] = {
period: year,
tasks : [],
};
}
stats.tasksByDay[day].push(taskDescription);
stats.tasksByMonth[month].tasks.push(taskDescription);
stats.tasksByYear[year].tasks.push(taskDescription);
// console.log(' ' + title) // console.log(' ' + title)
countIncluded++; countIncluded++;
} else { } else {
console.log('no', elem['properties']['raw-value']) console.log('no', elem['properties']['raw-value']);
} }
})
} else {
console.log('no content')
}
// console.log(data);
console.log('tâches inclues:', countIncluded)
writeHtmlOutput()
}); });
} else {
console.log('no content');
}
// console.log(data);
console.log('tâches inclues:', countIncluded);
writeHtmlOutput();
});
// les répartir dans des tableaux selon les périodes de temps // les répartir dans des tableaux selon les périodes de temps
} }
/**
* Retourne un html présentant le nombre de tâches réalisées pour chaque mois
* @return {string}
*/
function RenderStatsMonth() {
let months = Object.keys(stats.tasksByMonth);
console.log('months.length', months.length);
let monthHTML = '';
months.forEach((elem) => {
monthData = stats.tasksByMonth[elem]
console.log('monthData.tasks.length', monthData.tasks.length)
monthHTML += `
<div class='columns'>
<div class='column'>
<h2 class='title is-2'>
${monthData.period}
</h2>
</div>
<div class='column'>
${monthData.tasks.length}
</div>
</div>
`;
});
return `
<div class='box'>
<h1 class='title is-1'>Stats mensuelles</h1>
${monthHTML}
</div>
`;
}
// sortir un html présentant les périodes de temps et les tâches réalisées // sortir un html présentant les périodes de temps et les tâches réalisées
function writeHtmlOutput() { function writeHtmlOutput() {
console.log('writeHtmlOutput', stats.countAllTasks) console.log('writeHtmlOutput', stats.countAllTasks);
let daysListRef = Object.keys(stats.tasksByDay).sort() let daysListRef = Object.keys(stats.tasksByDay).sort();
let filterInfo = `` let filterInfo = ``;
if (enableFilterByTag) { if (enableFilterByTag) {
filterInfo = `<p class="is-info">Contenu filtré sur le tag: ${filterByTag}. ${countExcluded} tâches exclues, ${countIncluded} tâches inclues sur le total de ${countExcluded + countIncluded}</p>` filterInfo = `<p class='is-info'>Contenu filtré sur le tag: ${filterByTag}. ${countExcluded} tâches exclues, ${countIncluded} tâches inclues sur le total de ${countExcluded + countIncluded}</p>`;
} }
let htmlOut = ` let htmlOut = `
@ -147,104 +204,104 @@ function writeHtmlOutput() {
<title> <title>
Rapport d'activité Rapport d'activité
</title> </title>
<meta charset="UTF-8" /> <meta charset='UTF-8' />
<style> <style>
@import "https://cdn.jsdelivr.net/npm/bulma@0.9.4/css/bulma.min.css"; @import "https://cdn.jsdelivr.net/npm/bulma@0.9.4/css/bulma.min.css";
</style> </style>
</head> </head>
<body> <body>
<div id="report_days" class="container content"> <div id='report_days' class='container content'>
<h1 class="title is-1">Feuille de rapport d'activité</h1> <h1 class='title is-1'>Feuille de rapport d'activité</h1>
<p class="subtitle is-1">par <a href="https://www.cipherbliss.com">Tykayn</a> </p> <p class='subtitle is-1'>par <a href='https://www.cipherbliss.com'>Tykayn</a> </p>
${filterInfo} ${filterInfo}
${RenderStatsMonth()}
` `;
daysListRef.reverse().forEach((dayRefString) => { daysListRef.reverse().forEach((dayRefString) => {
let tasksOfTheDay = ''; let tasksOfTheDay = '';
stats.tasksByDay[dayRefString].forEach((dayObj) => { stats.tasksByDay[dayRefString].forEach((dayObj) => {
let graphicKeyword = '✅' let graphicKeyword = '✅';
if ('DONE' !== dayObj.todoKeyword) { if ('DONE' !== dayObj.todoKeyword) {
graphicKeyword = dayObj.todoKeyword; graphicKeyword = dayObj.todoKeyword;
} }
let tagDisplay = ''; let tagDisplay = '';
// console.log('dayObj.tags', dayObj.tags) // console.log('dayObj.tags', dayObj.tags)
if (dayObj.tags && dayObj.tags.length ) { if (dayObj.tags && dayObj.tags.length) {
tagDisplay = ` <p class="archived-tags tag is-light is-primary"> tagDisplay = ` <p class='archived-tags tag is-light is-primary'>
${dayObj.tags} ${dayObj.tags}
</p> </p>
` `;
} }
tasksOfTheDay += ` <li> tasksOfTheDay += ` <li>
<h2> <h2>
<span class="keyword"> ${graphicKeyword}</span> <span class='keyword'> ${graphicKeyword}</span>
<span class="title"> ${dayObj.title} </span> <span class='title'> ${dayObj.title} </span>
</h2> </h2>
${tagDisplay} ${tagDisplay}
</li>` </li>`;
}) });
htmlOut += ` htmlOut += `
<div class="box"> <div class='box'>
<h1 class="title is-1"> <h1 class='title is-1'>
<span class="day-ref"> <span class='day-ref'>
${dayRefString} ${dayRefString}
</span> </span>
<span class="counter pull-right tag is-success is-light"> <span class='counter pull-right tag is-success is-light'>
${stats.tasksByDay[dayRefString].length} ${stats.tasksByDay[dayRefString].length}
</span> </span>
</h1> </h1>
<div class="day-detail"> <div class='day-detail'>
<ul> <ul>
${tasksOfTheDay} ${tasksOfTheDay}
</ul> </ul>
</div> </div>
</div> ` </div> `;
}) });
htmlOut += ` htmlOut += `
<div class="box"> <div class='box'>
<h1 class="title is-1"> <h1 class='title is-1'>
Tadam, c'est tout! Tadam, c'est tout!
</h1> </h1>
<p> <p>
Source: <a href="https://forge.chapril.org/tykayn/org-report-stats">org-report-stats</a> Source: <a href='https://forge.chapril.org/tykayn/org-report-stats'>org-report-stats</a>
<br> <br>
Contactez-moi: <a href="https://www.cipherbliss.com/contact">par un de ces moyens</a> Contactez-moi: <a href='https://www.cipherbliss.com/contact'>par un de ces moyens</a>
</p> </p>
</div> </div>
</div> </div>
</body> </body>
</html> </html>
` `;
fs.writeFile('output/output.json', JSON.stringify(stats), function (err, data) { fs.writeFile('output/output.json', JSON.stringify(stats), function (err, data) {
if (err) { if (err) {
return console.log(err); return console.log(err);
} }
console.log('wrote output json', data) console.log('wrote output json', data);
}) });
fs.writeFile('output/output_' + outputFileName + '.html', htmlOut, function (err, data) { fs.writeFile('output/output_' + outputFileName + '.html', htmlOut, function (err, data) {
if (err) { if (err) {
return console.log(err); return console.log(err);
} }
console.log('wrote output html ' + outputFileName, data) console.log('wrote output html ' + outputFileName, data);
}) });
if (enableFilterByTag) { if (enableFilterByTag) {
console.log('excluded tasks by tag filter ', countExcluded) console.log('excluded tasks by tag filter ', countExcluded);
} }
} }
function sortObj(obj) { function sortObj(obj) {
return Object.keys(obj).sort().reduce(function (result, key) { return Object.keys(obj).sort().reduce(function (result, key) {
result[key] = obj[key]; result[key] = obj[key];