見出し画像

Obsidianプラグイン「Tasks」とCanvasを組み合わせてタスク管理したい

はじめに

前回の記事では、ObsidianのTasksプラグインを使ってタスク管理をする方法や、Mermaidを利用したガントチャート作成について紹介しました。
この記事ではさらに一歩進んで、Canvas機能を使った「すべてのタスク・今日のタスク・今週のタスク・完了したタスク」の一覧表示方法と、その横にガントチャートを配置して「見てすぐ分かるタスク管理画面」を作る手順を紹介します。(既存のタスク管理方法と比較すると改善の余地があると感じているので、改善案があればコメントしてもらえると嬉しいです。)


1. Canvasの準備

1-1. Canvas機能を有効にする

Obsidianの設定画面(左下の歯車アイコン)→「コアプラグイン」から「Canvas」を探してオンにします。
有効にすると、左サイドバーの「+」ボタンを押したときなどに「新規Canvas」のオプションが出てくるはずです。

1-2. 新しいCanvasを作成

  1. 左サイドバーの「+」から「新規Canvas」をクリックするか、コマンドパレット(Ctrl+P / Cmd+P)で「Canvas: New Canvas」を実行します。

  2. 好きなファイル名を付けて、任意の場所に保存します。

作成すると、広いキャンバス上にノード(カード)を配置できる状態になります。
ここに「Tasksプラグインのクエリ結果」や「ガントチャート」などをEmbedded Note
Markdownカードとして配置していきます。


2. すべてのタスク、今日、今週、終了したタスクを表示する

2-1. Tasksのクエリブロックを用意

例えば、以下のように「All Tasks」「Today’s Tasks」「This Week’s Tasks」「Completed Tasks」などを表示するクエリを個別のMarkdownファイルに書いておく方法がおすすめです。後述するCanvas上のカードで、それらのファイルを埋め込んで使います。

(A) すべてのタスクを表示する例

```tasks
not done
sort by due
sort by priority
```  
  • not done:未完了タスクだけ表示

  • sort by due:期限日順で並べる

  • sort by priority:優先度がある場合、高優先度を上に

(B) 今日が期限のタスクを表示する例

```tasks
not done
due today
sort by priority
```  
  • due today:期限が今日(=当日)のタスク

(C) 今週が期限のタスクを表示する例

```tasks
not done
due before next week
sort by due
```  
  • due before next week:来週になる前(=今週中)のタスクを取得

(D) 完了したタスクを表示する例

```tasks
done
sort by done descending
limit 20
```  
  • done:既に完了済みタスクのみ

  • limit 20:直近20件だけ表示する

ポイント:
Canvas上では「Markdownファイルを埋め込んで表示」した方が見やすく編集しやすいです。もちろん、Canvas内で直接Markdownカードを作り、その中にコードブロックを書くのもOKです。


3. ガントチャートの表示(Mermaid + DataviewJS)

前回の記事で紹介したDataviewJSを使ったサンプルコードを使い、指定期間内のタスクをガントチャートに描画してみましょう。
以下は一例です。Due Date(📅)が必須・開始日は🛫や⏳で指定可能、という仕様で動作します。

```dataviewjs
const RANGE_DAYS = 1;  
const today = new Date();
const startRange = new Date(today);
const endRange = new Date(today);
startRange.setDate(today.getDate() - RANGE_DAYS);
endRange.setDate(today.getDate() + RANGE_DAYS);

const formattedToday = today.toISOString().slice(0, 16).replace("T", " ");
const formattedStart = startRange.toISOString().slice(0, 16).replace("T", " ");
const formattedEnd = endRange.toISOString().slice(0, 16).replace("T", " ");

// タスクデータを解析する関数(📅 Due Date が必須 & HH:mm に対応)
function parseTask(taskText) {
    function extractDate(emoji) {
        const match = taskText.match(new RegExp(`${emoji} (\\d{4}-\\d{2}-\\d{2}(?: \\d{2}:\\d{2})?)`));
        return match ? match[1] : "";
    }

    let dueDate = extractDate("📅");  // 📅 Due Date(必須)

    if (!dueDate) return null;  // Due Date がないタスクは無視

    let taskName = taskText.split(" ")[0] || "Unnamed Task"; // タスク名(デフォルト値)

    // **タスク名のクリーニング**
    taskName = taskName
        .replace(/[\n\t\r]/g, " ")  // 改行やタブをスペースに置換
        .replace(/["|:]/g, "")  // Mermaidでエラーになる記号を削除
        .trim();

    // 長すぎる名前を省略(50文字以上は省略)
    if (taskName.length > 50) {
        taskName = taskName.slice(0, 50) + "...";
    }

    return {
        due: dueDate,  
        start: extractDate("🛫"),  
        scheduled: extractDate(""),  
        priority: taskText.includes("🔺") ? "Highest" : taskText.includes("") ? "High" : taskText.includes("") ? "Medium" : taskText.includes("🔽") ? "Low" : "",
        name: taskName,  
    };
}

// ガントチャートデータを作成
let ganttData = `gantt
    title Task Schedule (Due Date Required)
    dateFormat YYYY-MM-DD HH:mm
    axisFormat %H:%M\n`;

const pages = dv.pages("").where(p => p.file.tasks.length > 0);
let taskEntries = [];

for (const page of pages) {
    for (const task of page.file.tasks) {
        const taskObj = parseTask(task.text);

        if (!taskObj) continue;  // 📅 Due Date のないタスクをスキップ

        // 表示範囲に含まれないタスクはスキップ
        if (taskObj.due < formattedStart || taskObj.due > formattedEnd) continue;

        // 開始日・終了日を決定
        let startDate = taskObj.start || taskObj.scheduled || formattedToday;
        let endDate = taskObj.due;

        // タスクの状態を設定
        let status = "active";
        if (taskObj.due < formattedToday) status = "crit";
        if (task.text.includes("")) status = "done";

        // タスクを追加
        taskEntries.push(`    ${taskObj.name} :${status}, ${startDate}, ${endDate}`);
    }
}

// タスクデータを追加
ganttData += taskEntries.join("\n");

// 今日の日付を強制表示
ganttData += `\n    🧍 Today :active, ${formattedToday}, ${formattedToday}\n`;

dv.paragraph("```mermaid\n" + ganttData + "\n```");

```

Canvasに埋め込んで表示することができます。
表示期間(RANGE_DAYS)やタスク名のトリミング部分などは好みに合わせて調整してみてください。


4. Canvasで並べて配置する

4-1. MarkdownファイルをCanvasに埋め込む

  1. Canvas画面を開き、ボタンから「ノードを追加 → ノート」を選ぶ。

  2. 「既存ノートを選択」の画面が開くので、先ほど作った「AllTasks.md」や「TodayTasks.md」など、クエリを含むファイルを選択する。

  3. 選択すると、Canvas上にそのノートの内容が表示されるカードが作成される。

  4. 必要に応じて四隅をドラッグしてサイズを調整し、見やすい位置に配置する。

「すべてのタスク」「今日のタスク」「今週のタスク」「完了したタスク」を同様の手順でそれぞれ配置すれば、4つのカードが並びます。

4-2. ガントチャートのノートを埋め込む

同じように、GanttChart.mdファイルなどガントチャート用のノートをCanvasに埋め込みます。すると、Tasksプラグインのクエリ結果+ガントチャートを一度に確認できるようになります。

ヒント:
カード同士を線で結び付けたり、背景色を変えたりしてデザイン面をカスタマイズすると、より「ダッシュボード」感が出ます。


5. 運用のポイント

  1. Canvasのレイアウトを整える

    • 各カードは横に並べる、あるいはタスク一覧を左・ガントチャートを右側に配置するなど、好みのレイアウトを試してみてください。

    • Canvas上で右クリックし、グリッド表示や自動配置などをオンにすると整列しやすくなります。

  2. クエリ内容をこまめに調整

    • 「今週のタスク」や「来週のタスク」など、抽出条件が適切かどうか定期的に見直すと良いです。

    • 完了したタスク一覧は上限(limit)を設けて長さが膨大にならないようにしましょう。

  3. ガントチャートの期間設定

    • DataviewJSのRANGE_DAYSを変更して1日〜数週間など自由に調整可能。期間を長くすると全体的に把握しやすくなりますが、表示が混雑する場合は注意が必要です。

  4. タスク名の付け方・アイコンの使い方

    • タスクが長くなりすぎるとガントチャートで崩れがちです。概要を短めに記載し、詳細はノート本文に書いておくとスッキリします。

    • 📅や🛫などのアイコンを使うと、コード上で日付抽出が楽になるためおすすめです。

  5. Canvas以外でも同じMarkdownを使い回せる

    • ここで作ったAllTasks.mdなどのクエリファイルは、Canvas外でも通常のObsidianノートとして利用できます。

    • デイリーノートやウィークリーノートに埋め込んで運用するのも便利です。


まとめ

ObsidianのCanvas上に「Tasksプラグインのクエリ結果」を並べて配置し、さらにガントチャートを合わせて表示すると、タスク全体を俯瞰しながら日々の進捗を確認できるダッシュボードが簡単に作れます。

  • すべてのタスクの洗い出し → 「All Tasks」

  • 今日やるべきタスクの確認 → 「Today’s Tasks」

  • 週単位での進捗管理 → 「This Week’s Tasks」

  • 完了タスクの振り返り → 「Completed Tasks」

  • 予定と進捗をビジュアル化 → 「Gantt Chart (Mermaid + DataviewJS)」

これらをCanvasに集約するだけで、毎回同じ場所で自分のやること・進捗状況を手軽に把握できます。
Tasksプラグインの細かい設定(グローバルフィルタ、繰り返し、依存関係など)を組み合わせれば、チームでも個人でも強力なタスク管理環境が整うでしょう。

ぜひ一度試してみて、自分好みのレイアウトやクエリ条件を探求してみてください。慣れてくると「Canvas + Tasks + ガントチャート」の使い方がどんどん進化して、Obsidianがますます手放せなくなるはずです。


いいなと思ったら応援しよう!