見出し画像

Notion で(自分なりの)タスク管理を行う方法?(日次レビュー編)

前回は、定期的に YouTube チャンネルの更新をチェックし、
新しい動画を観るためのタスクを自動的に「タスクリスト」へ追加しておくという荒技を紹介しましたが、

今回も「番外編」として、しかし、実は、タスクシュート的にも、結構、重要かもしれない「日次レビュー」について、考えてみたいと思います。

厳密に言うと、タスクシュート的というよりは、特に「先送り0」的に、鍵となり得るもの、と言った方が適切かもしれません。

一応、久しぶりに、宣伝?しておきましょうか。

つまり、やらなければならないことを、つい先送りにして、いつも締め切りギリギリになってしまうとか、
今やらなくてもいいことを、ダラダラと続けてしまって、やりたいことができないなどと悩んでいる人には、

まず、タスクシュート的なメソッドによる、タスク・時間管理を試してみることをオススメしているわけですが、
少なくとも、「先送り0」を一つの目標とするのであれば、その過程で大切になってくるのが、ここで言う「日次レビュー」なのです。

と言っても、始めるのは簡単で、とりあえず、最低限、1日のログを見返して、「先送りの数」を確認してみるだけでも良いでしょう。

そうして、何か気づいたことがあれば、随時、次の日のプランや、ルーチンを見直すようにし、
メソッドに慣れないうちや、環境や状況が変化したり、心身の調子が悪い時期などにも、この「日次レビュー」を元に、方針を再検討していきます。

例えば、昨日のログを表示する「テーブルビュー」を作成しておき、
ステータス列の一番下の「計算」で「カウント」→「グループごとのカウント」→「Complete」を選択すれば、それだけで十分かもしれません。

昨日のログを表示する「テーブルビュー」を作成する

そう言えば、「超過時間」プロパティについては、触れたことがなかったかもしれないので、ついでに紹介しておきましょうか。

「超過時間」プロパティを追加する

数式は、こんな感じで、単に「実績時間」の値が「見積値」を超えていたら、その差分を赤色太字で表示するようにしているだけですね。

if(empty(prop("実績時間")), "0分",
  let(
    over, subtract(toNumber(prop("実績時間").replace("分", "")), prop("見積値")),
    if(over > 0, style(over + "分", "b", "red"), "0分")
  )
)

ちなみに、開始終了時刻なども、何やら色が変わっている部分があったりしますが、その話は、ちょっと長くなりそうなので、またいつか。

ともかく、このテーブルを確認するだけなら、「日次レビュー」を行うこと自体は、特に難しい作業でもないでしょう。

しかし、どうですかね?

問題は、そもそも、このテーブルを、毎日、ちゃんと確認するかどうかだという気もします。

もちろん、それもルーチンにして、習慣化してしまえばいいだけですし、
どうしても継続できなかったり、いまいちモチベーションが上がらないという人は「100日チャレンジ」に参加するのもオススメなのですが、

今回、提案してみたいのは、例えば、昨日のログを、Notion からマークダウンファイルとして(無理やり)エクスポート?し、
それを、普通のエディタで開くようにした方が、なんとなく、レビューしやすい場合もあるのではないかという、
分かる人には分かるというか、分かる人にしか分からないような、なかなか特殊なニーズを満たす内容です。

あえて説明してみるなら、Notion に書かれていることを、同じ Notion の中でレビューするより、いったん外へ出力し、切り離して考えた方が、
客観的に捉えやすいとも思うのですが、どうでしょうか?

まぁ、単純に、クラウド上で作業するのではなく、ローカルにもファイルを確保しておきたいというような、好みの問題もあるかもしれません。

というわけで、いつも以上に前置きが長くなってしまいましたが、そろそろ、始めていきましょう!


昨日のログを取得してみる

まずは、データベースから必要なデータを取ってくるわけですが、
フィルターの条件が違うだけで、基本的には「セクションリスト」や「ルーチンリスト」などを取得した際と、同様の流れとなります。

今までは、例えば、「有効」チェックボックスがオンのものだけを取得するといったような、比較的、簡単な条件が多かったと思いますが、
今回は、「タスクリスト」データベースから「実行日」が「昨日」の「24時間以内」に当てはまるデータを取ってくるわけですね。

function test() {
  const today = new Date();
  const before = new Date(today.setHours(0, 0, 0, 0));
  const ago = new Date(today.getTime() - (24 * 60 * 60 * 1000));
  const after = new Date(ago.setHours(0, 0, 0, 0));
  getLogs(after, before, "xxxxx", "secret_XXXXX");
}

function getLogs(after, before, database_id, secret) {
  const data = {
    "filter": { "and": [
      { "property": "実行日", "date": { "on_or_after": after } },
      { "property": "実行日", "date": { "on_or_before": before } }
    ] },
    "sorts": [{ "property": "開始日時", "direction": "ascending" }]
  };
  const options = {
    'method': 'post',
    'headers': {
      'Authorization': 'Bearer ' + secret,
      'Content-Type': 'application/json',
      'Notion-Version': '2022-06-28'
    },
    'payload': JSON.stringify(data)
  };
  const response = UrlFetchApp.fetch('https://api.notion.com/v1/databases/' + database_id + '/query', options);
  const contents = JSON.parse(response.getContentText());
  const results = contents.results;
  results.forEach((result) => {
    const properties = result.properties;
    const title = properties["名前"].title[0].plain_text;
    console.log(title);
    const projects = properties["プロジェクト"].relation;
    console.log(projects);
    const status = properties["ステータス"].status.name;
    console.log(status);
    if (status == "完了") {
      const startDate = properties["開始日時"].date.start;
      console.log(startDate);
      const endDate = properties["終了日時"].date.start;
      console.log(endDate);
      const record = properties["実績時間"].formula.string;
      console.log(record);
    }
  });
}

これで、「実行日」プロパティが、変数「after」と「before」の間の時間帯、すなわち「昨日の0時」から「今日の0時」までのタスクの一覧が、
ソートの条件も指定しているので、「開始日時」の昇順(ascending)で、取得できるはずです。

例によって、"xxxxx" と "secret_XXXXX" の部分は、「タスクリストデータベースの ID」と「Notion API のシークレット」に書き換えてください。

また、ここでは、「console.log()」で、各タスクの「名前」や「ステータス」などを表示しようとしていますが、
もちろん、日次レビューに用いたいプロパティを、自由に選択できます。

それこそ、人によっては、上述した「超過時間」プロパティを参考にしたいという場合もあるでしょう。

ただし、例えば、「開始日時」や「終了日時」などは、「未着手」のタスクには設定されておらず、出力しようとするとエラーになってしまうので、
上のコードのように、「ステータス」の値で、場合分けしておく必要があるかもしれません。

プロジェクトの ID を名前に変換する

さらに、「プロジェクト」などの「リレーション」プロパティを使いたいなら、もうひと工夫必要ですね。

実は、以前「セクションリスト」で、似たようなことやっているのですが、
その時は、任意の「開始時刻」に対応した「セクションの ID」を出力する関数を作成しました。

今回は「プロジェクトの ID」から、対応する「プロジェクト名」へと変換して、出力に利用したいところです。

今のままだと、「プロジェクト」プロパティの出力は、以下のような、「プロジェクト ID の配列」になっているのではないでしょうか?

「プロジェクト」プロパティの出力を確認する

では、「プロジェクトリスト」のデータを Notion から取得し、ID と「プロジェクト名」との対応関係を保管したオブジェクトを作成してみます。

function getProjects(database_id, secret) {
  const options = {
    'method': 'post',
    'headers': {
      'Authorization': 'Bearer ' + secret,
      'Content-Type': 'application/json',
      'Notion-Version': '2022-06-28'
    }
  };
  const response = UrlFetchApp.fetch('https://api.notion.com/v1/databases/' + database_id + '/query', options);
  const contents = JSON.parse(response.getContentText());
  const object = {};
  for (const result of contents.results) {
    object[result.id] = result.properties["名前"].title[0].plain_text;
  }
  return object;
}

これを使えば、次のようにして、各「プロジェクトの ID」を元に、「プロジェクト名」が出力できるはずです。

const id2project = getProjects("yyyyy", secret);
const projects = properties["プロジェクト"].relation;
projects.forEach((relation) => {
  const project = id2project[relation.id];
  console.log(project);
});

もちろん、こちらの "yyyyy" に入れるのは、「プロジェクトリストデータベースの ID」なので、ご注意ください。

出力するテキストデータを作成する

さて、これで、必要なデータは出揃ったので、いよいよ、ファイルへ出力するためのテキストを作成していきましょう。

基本的には、好きな順番で、自由にデータを連結していって、改行を含む、一つの文字列にまとめればいいだけです。

例えば、以下のように書くと、ある種のマークダウン形式の文字列「text」が出来上がります。

function getLogs(after, before, database_id, secret) {
  const id2project = getProjects("yyyyy", secret);
  const data = {
    "filter": { "and": [
      { "property": "実行日", "date": { "on_or_after": after } },
      { "property": "実行日", "date": { "on_or_before": before } }
    ] },
    "sorts": [{ "property": "開始日時", "direction": "ascending" }]
  };
  const options = {
    'method': 'post',
    'headers': {
      'Authorization': 'Bearer ' + secret,
      'Content-Type': 'application/json',
      'Notion-Version': '2022-06-28'
    },
    'payload': JSON.stringify(data)
  };
  const response = UrlFetchApp.fetch('https://api.notion.com/v1/databases/' + database_id + '/query', options);
  const contents = JSON.parse(response.getContentText());
  const results = contents.results;
  const date = after.toLocaleDateString("ja-JP", { weekday: "long", year: "numeric", month: "long", day: "numeric" });
  let text = `### ログ(${date})\n\n`;
  let todo = 0;
  let complete = 0;
  results.forEach((result) => {
    text += "- ";
    const properties = result.properties;
    const status = properties["ステータス"].status.name;
    text += `(**${status}**)`;
    const projects = properties["プロジェクト"].relation;
    projects.forEach((relation) => {
      const project = id2project[relation.id];
      text += `[[${project}]] `;
    });
    const title = properties["名前"].title[0].plain_text;
    text = `${text.trim()}${title}」`;
    if (status == "完了") {
      const startDate = properties["開始日時"].date.start;
      const start = new Date(startDate).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', hour12: false })
      const endDate = properties["終了日時"].date.start;
      const end = new Date(endDate).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', hour12: false });
      const record = properties["実績時間"].formula.string;
      text += `${start} ~ ${end}${record})`;
      complete += 1;
    } else {
      todo += 1;
    }
    text += "\n";
  });
  const sum = todo + complete;
  text += `#### ${complete} / ${sum} 着手(**先送り ${todo}**)\n`;
  console.log(text);
}

タスクのステータスが「完了」かどうかにより、開始終了日時等が取得できるかどうかを判断するだけでなく、
ここでは、変数「todo」と「complete」で、各ステータスのタスクの数をカウントし、下の方で「先送りの数」などを出力している点にも注目です。

マークダウンファイルとして出力する

それでは、最後に、作成したテキストを、マークダウンファイルとして書き出してみましょう。

GAS(Google Apps Script)を使っているなら、Google ドライブに保存してしまうのが、最も簡単です。

ただ「console.log(text)」で出力する代わりに、例えば、以下のような行を追記するだけですね。

const fileName = after.toLocaleDateString("ja-JP", { year: "numeric", month: "2-digit", day: "2-digit" }).replaceAll('/', '-');
DriveApp.createFile(fileName + ".md", text);

今回、ファイル名は、「2024-08-22」のような形式にしておきました。

Google ドライブ( https://drive.google.com/drive/my-drive )上でファイルをプレビューしてみると、次のように出力されましたでしょうか?

Google ドライブでファイルを確認する

また、Google ドライブのアプリをインストールした PC で、「マイドライブ」フォルダを「Obsidian」の「Vault」に指定し、
このファイルを表示すると、おそらく、以下のようになります。

マークダウンファイルを Obsidian で開く

そもそも、「プロジェクト名」を「[[two square brackets]]」で囲んでいるのは、実は、このためでした。
その他の点も含め、マークダウンの書き方は、人それぞれになるでしょう。

そして、そろそろ細かい説明は省略させてもらいますが、上の「test()」関数を「review()」などという名前に変えたりしつつ、
これまでの記事でやってきたのと同様に、その関数を、例えば、毎日「午前1時〜2時」の間に実行するようにするなど、
いつものように、お好みで、「トリガー」を設定しておいてください。

「トリガーを追加」する

まとめ

今回は、場合によっては「日次レビュー」に取り組みやすくなるよう、昨日のログをマークダウンファイルとして出力する方法を紹介してみましたが、
これは、結構、応用範囲が広い内容でもあるのではないでしょうか?

関連して、クラウドとローカルの使い分けというか、その辺りも含めた運用方針についても、いずれは考えていきたいところですし、
Notion で書いたノートをマークダウンに変換するのは、意外と面倒臭いらしいのですが、そちらも検討してみたいですね。

ともあれ、そろそろ長くなってきたので、今回は、この辺で。

ではまた。

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