Skip to content

Instantly share code, notes, and snippets.

@serpro69
Last active February 16, 2023 11:44
Show Gist options
  • Save serpro69/f311f11279a644dc66001785159663ac to your computer and use it in GitHub Desktop.
Save serpro69/f311f11279a644dc66001785159663ac to your computer and use it in GitHub Desktop.
obsidian dataview goals tracker
/**
Tracks mission-related KPIs (goals) targets from daily notes.
Daily notes' frontmatter structure:
```
---
mission:
220_01_332:
water: 2000
sleep: 360
---
```
*/
class DvGoalsProgress {
async getProgress(args, missions, days, folded) {
const {dv} = args
const foldSymbol = folded ? "-" : "+"
let out = '> [!multi-column]\n'
for (const nDays of days) {
const header = nDays === 1 ? "Today's KPIs" : nDays + " Days KPIs"
out = out + '>\n'
out = out + '> > [!info]' + foldSymbol + ' ' + header + '\n> >\n'
out = out + '> > |KPI|Daily Avg.|' + (nDays === 1 ? 'Target (Today)          ' : 'Target (Day/Period)') + '|Progress|\n';
out = out + '> > |---|---|---|---|\n';
for (const mission of missions) {
out = out + await this._getGoalsAverage(args, nDays, mission);
}
}
dv.paragraph(out);
}
async _getGoalsAverage(args, nDays, mission) {
const {app, dv, that} = args
const missionId = mission.id
const kpis = mission.kpis
const columns = kpis.map(kpi => "round(sum(nonnull(rows.M." + kpi.name + ")) / " + nDays + ", 2) as \"" + kpi.name + "\"").join(", ")
const dvQuery = `
TABLE WITHOUT ID
` + columns + `
FROM #daily
WHERE 1=1
AND date(today) - file.day < dur(` + nDays + ` days)
FLATTEN mission["` + missionId + `"] AS M
GROUP BY true
`
const qryAvg = await dv.query(dvQuery)
let avgValues = qryAvg.value.values;
let avgTable = [];
for (let r of avgValues) {
kpis.forEach(({goal, name, unit}, i) => {
const avg = r[i];
const percentOfGoal = Math.round(avg * 100 / goal);
let progressBar = '<progress value="' + percentOfGoal + '" max="100"></progress>'
avgTable.push([name + " (" + unit + ")", avg, goal, percentOfGoal, progressBar]);
})
}
let out = '';
for (let r of avgTable) {
let kpi = r[0];
let dailyAvg = r[1];
let dailyTarget = r[2];
let periodTarget = dailyTarget * nDays;
let percent = r[3];
let bar = r[4];
out = out + '> > |' + kpi + '|' + dailyAvg + '|' + (nDays === 1 ? dailyTarget : dailyTarget + '/' + periodTarget) + '|' + bar + '|\n';
}
return out
}
}
missions
id kpis
22001332
name goal unit
water
2000
ml
name goal unit
liquids
1500
ml
const {DvGoalsProgress} = customJS;
const missions = dv.current().missions
await DvGoalsProgress.getProgress({dv}, missions, [1, 7, 30], false)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment