notebook

都内でWEB系エンジニアやってます。

ObsidianでToDoの数をグラフ化する

最近ToDo消化が追いつかない…ということで

Obsidianで使えるプラグインObsidian Chartsを使って、DailyNoteで記録したToDoの推移をグラフ化し変化を分かるようにした

可視化して消化モチベーションを高めよう()という取り組み

ToDoの運用

ObsidianのデイリーノートでTodoというセクションを設けタスクが発生したらタスクを追加するという運用にしている

また、大きめなタスクの場合はずっと消えないのが嫌なので細かくできるところまで細かくして追加

日付が変わったら、前日の未完了タスクをコピー&ペーストで当日のデイリーノートに書く

といった感じでやっている

## Todo
- [ ] 案件Aの資料確認
- [ ] 案件Bの依頼

Obsidian Charts

phibr0/obsidian-charts: Charts - Obsidian Plugin | Create editable, interactive and animated Charts in Obsidian via Chart.js

github.com

Obsidian上で数値データをグラフ化して表示するプラグイン

このプラグインを使うことで、何かしらのデータをもとにObsidian上でもグラフ表示ができる

中身でグラフ化する部分に関してはChart.jsを使っているので渡すオプションの値など詳しく知りたい場合はChart.jsのドキュメントも参考にできる

Chart.js | Chart.js

www.chartjs.org

今回はこのプラグインとDataviewプラグインを組み合わせてToDoの数を日別でグラフに変換した

なお、プラグインのインストール方法については公式読めば分かるので割愛する

Dataviewプラグインとの連携

Dataview Integration - Obsidian Charts

charts.phibr0.de

dataviewjswindow.renderChart(data, element);と記述することでグラフをレンダリングできる

dataには渡すデータを、elementにはthis.containerを指定する

dataの中身を変えて複数のグラフを描画することも可能

Dataviewで集計してChartsでグラフ描画

コードはこんな感じ

const pages = dv.pages('#daily').filter(p => p.file.name != "daily_note" && p.file.name > "2023-03-02").sort(p => p.file.name);

const days = pages.map(p => p.file.name).values
const uncompleted = pages.map(p => p.file.tasks.where(t => !t.completed && t.section.subpath == "Todo")).values.map(v => v.length);
const completed = pages.map(p => p.file.tasks.where(t => t.completed && t.section.subpath == "Todo")).values.map(v => v.length);

function taskChart(terms, completed, uncompleted) {
  return {
    type: 'bar',
    data: {
      labels: terms,
      datasets: [{
        label: 'completed',
        data: completed,
        borderColor: ['rgba(89, 162, 230, 1)'],
        backgroundColor: ['rgba(89, 162, 230, 0.8)']
      },{
        label: 'uncompleted',
        data: uncompleted ,
        borderColor: ['rgba(246, 206, 102, 1)'],
        backgroundColor: ['rgba(246, 206, 102, 0.8)']
      }]
    },
    options: {
      scales: {
        x: {
          stacked: true
        },
        y: {
          stacked: true
        }
      }
    }
  }
}

const dailyTask = taskChart(days, completed, uncompleted )
window.renderChart(dailyTask, this.container)

1行目のpagesは自分のユースケースの場合はこれという感じなのでもし流用する場合は適宜変えてもらえれば…

  • #dailyというタグがついているノート(デイリーノート)
  • ファイル名がdaily_noteという名前のものは除く(テンプレートファイルtemplates/daily_noteを除外したいため)
  • 特定日時以降のファイル

デイリーノートの中に仕事以外のタスクリストがある場合を考慮し,4,5行目でt.completed && t.section.subpath == "Todo"のように特定セクション以下のタスクのみを取得するようにしている

このsubpathはリストのときも使えるので覚えておくと色々と活用がはかどる

結果はこんな感じ

消化してないものがどんどん増えているので精査含めて減らしていきたい…