NotionTimeRecoder の GTD 対応改修 : Notion 解説 (78)

1. はじめに

Notion アンバサダー仲間の円谷さんが GTD を解説する YouTube 動画を公開していました。私も OmniFocus や Todoist などのツールを変遷としながら、Notion での GTD 運用に辿り着きました。

youtu.be

これまでの GTD の運用はこんな感じでした。

  • Inbox: 日付なしタスクとしてページを作成します。声でタスク登録や nt, ntd コマンドで登録します。
  • 次のアクション: 以前は日付なしタスクを全て今日のタスクに変更していました。実施できなかったタスクは日付が変わるのでそれらを今日のタスクに毎日移動していました。
  • カレンダー: 時間に結びついているタスクは普通にカレンダーに入れます。

最初はこれらの仕組みを yuka さんのまいにち Notion のフィルタ付ビューで運用していました。しかし、この毎日のタスク移動が面倒になってしまい、次のアクションと Inbox を融合させた運用をしておりました。改修前の Launchpad はこんな感じになっていました。ここで、日付未確定のタスクが Inbox 兼次のアクションに相当していました。

変更前の Launchpad

この運用は次のアクションのタスク移動がなくなった代わりに、アクションを開始するハードルが高くなってしまいました。今日のタスクの部分にタスクがなくなってしまうと仕事が終わった感覚になってしまい、次のアクション探しを積極的にやらなくなっていました。この結果、日付未確定のタスクにやるべき仕事がどんどん溜まってしまう点が問題となっていました。

今回、円谷さんの動画を閲覧し、再度デビッドアレンの本を読み返したことで、次のアクションからアクションを始めるる部分をハードル下げる必要を感じました。今回の改修はこの部分をよりやりやすくするためのものです。

2. ページの改修

システムを修正する前にページ構成を変更しました。画面は以下のようになりました。

GTD よりに変更した Launchpad

上(白背景): タイムラインビューで一日のタスクの幅をみえるようにしています。 左上(緑背景): 次のアクションを表示します。今日の日付のタスクをフィルタして表示しています。 左中(黄色背景): 明日のタスクを表示します。基本的にはカレンダータスクが表示されています。これを横目に見ながら次のアクションを検討します。 左下(青背景): 最近1週間のタスクを表示します。カレンダータスクのみが表示されます。これも参考程度の情報なので次のアクションからは遠目に置いています。 右上(紫背景): いつかやる 兼 Inbox を表示します。ここには日付なしタスクを表示しています。 右下(オレンジ背景): 昨日以前のやり直しタスクを表示します。日付が過ぎ去った未完了タスクがここに表示されます。

基本的には最初に yuka のページで作成したタスク管理に戻った感じです。

3. NotionTimeRecorder (GAS Web app) の改修

3.1 いつかやるへの登録

いつかやるには、声でタスク登録や後述の nt, ntd コマンドなどで登録します。NotionTimeRecorder はここには絡みません。

3.2 いつかやる→次のアクション

現在、NotionTimeRecoder リンクをクリックすると、日付が設定されるだけでなく時刻まで設定されてしまいます。次のアクションではまだタスクは始まらないので、日付だけを設定するように変更します。

3.3 次のアクション→すぐやる

次のアクションにある時間の設定されていないタスクに対して NotionTimeRecoder を実行すると、開始時刻が記録されます。この仕組みは現在の機能そのままで問題ありません。

3.4 すぐやる→完了

次のアクションにある開始時刻が設定されたタスクに対して NotionTimeRecoder を実行すると、終了時刻と完了が記録されます。この仕組みも現在の機能そのままで問題ありません。

3.5 期限切れ→次のアクション

今日実施できなかった次のアクションは期限切れとなり、機能以前のやり直しタスクに落ちてしまいます。それが嫌なら予め明日のタスクに移動しておく必要があります。

ただし以前このドラッグをするのが面倒でやめてしまった経緯があります。そこで、ここも NotionTimeRecoder を使えるようにしましょう。ここで、次のアクションにないタスク(期限切れや将来のもの)に対して NotionTimeRecoder を実行した場合にも、次のアクションに飛ぶようにします。

これらを踏まえて timeRecording 関数は以下のように変更しました。

// 時間記録本体
function timeRecording(id) {
  const date_name = datePropertyName()
  console.log(date_name)
  const page = retrievePage(id)
  const now = new Date().toLocaleString("sv-SE", { timeZone: "Asia/Tokyo" }).replace(" ", "T") + "+09:00"
  const date_only = now.split("T")[0]
  console.log(date_only)
  const date_property = page.properties[date_name]["date"]
  if (date_property == null || date_property["start"].split("T")[0] != date_only) {
    // 次のアクションへ
    sd = date_only
    ed = null
    finish = false
  } else if (date_property["start"].indexOf("T") == -1) {
    // すぐやるへ
    sd = now
    ed = null
    finish = false
  } else {
    // 完了へ
    sd = date_property["start"]
    ed = now
    finish = true
  }
  const payload = {}
  payload[date_name] = {"date": {"start": sd, "end": ed}}
  payload[checkBoxPropertyName()] = {"checkbox": finish}
  return updatePage(id, {"properties": payload})
}

4. NotionTimeRecording (コマンドラインアプリ) の改修

コマンドライン版の NotionTimeRecording は以下のように変更しました。

  • nt, ntd: Index への登録コマンドです。これらは変更ありません。nt は以前 | を使うことで連続する依存関係を持つタスク一覧を一気に作成できるようになっています。以下のようにすると task1 -> task2 -> task3 という依存関係を持つタスク群が設定できます。これらは全て、「いつかやる」に登録されます。
nt task1|task2|task3
  • na: 次のアクションにするコマンドです。at はすでにコマンドがあったので、Next action から na と言うコマンドにしました。期限切れおよび日付なしタスクを取得し、選択したものを今日の日付に変更します。結果として「次のアクション」に移動したことになります。
  • st タイトル: 登録されていないタスクをすぐやるものです。これも変更ありません。
  • st: 「次のアクション」を「すぐやる」に変更するコマンドです。これまでは日付なしタスクも選択できましたが、次のアクションのみだけを選択するようにします。
  • et: すぐやるのタスクを完了します。これは変更ありません。
  • ot: タスクを表示します。

これらを踏まえた修正したスクリプトはこちらです。

#!/usr/bin/env ruby
# frozen_string_literal: true
require "date"
require "notion_ruby_mapping"
include NotionRubyMapping
NotionRubyMapping.configure do |config|
  config.notion_token = ENV["NOTION_API_KEY"]
  config.wait = 0
end

DATABASE_ID = "2395e3ffb55e4a8abc1ba426243776e3"
CMD_NAME = File.basename $0

def select_task(end_task: false, new_task: false, pre_task: false)
  db = Database.find DATABASE_ID
  dps = db.properties
  dp, cp, tp, pdp = dps.values_at *%w[日付 Done タスク名 PercentPreviousDone]
  now = Time.now
  end_of_day = Time.local(now.year, now.month, now.mday, 23, 59, 59)
  end_of_day -= 1 if pre_task
  date_query = dp.filter_before(end_of_day)
                 .and(cp.filter_equals false)
                 .ascending(dp)
  date_exists = db.query_database(date_query).to_a
  unsettled_query = dp.filter_is_empty
                      .and(cp.filter_equals false)
                      .ascending(tp)
  unless new_task
    query_is_empty = pdp.filter_is_empty another_type: "number"
    query_equals_1 = pdp.filter_equals 1, another_type: "number"
    unsettled_query.and(query_is_empty.or(query_equals_1))
  end
  date_unsettled = end_task ? [] : db.query_database(unsettled_query).to_a
  pages = date_exists + date_unsettled
  if pages.count.zero?
    puts "There are no tasks."
    exit
  else
    pages.each_with_index do |apage, i|
      puts "#{i}: #{apage.title}"
    end
    puts "\nPress number of q"
    num_or_q = STDIN.gets.chomp
    exit if num_or_q == "q"
    pages[num_or_q.to_i]
  end
end

case CMD_NAME
when "nt"
  previous_id = nil
  NotionCache.instance.wait = 0.4
  db = Database.find(DATABASE_ID)
  ARGV.join(" ").split("|").each do |title|
    page = db.create_child_page do |p, pp|
      pp["タスク名"] << title
      pp["前タスク"].relation = previous_id if previous_id
    end
    previous_id = page.id
  end
  exit # nt コマンドの時には Notion を開かない
when "ntd"
  page = select_task new_task: true
  Database.find(DATABASE_ID).create_child_page do |p, pp|
    pp["タスク名"] << ARGV.join(" ")
    pp["前タスク"].relation = page.id
  end
  exit # ntd コマンドの時には Notion を開かない
when "ot"
  page = select_task
when "na"
  page = select_task pre_task: true
  pp = page.properties
  pp["日付"].start_date = Date.today
  pp["日付"].end_date = nil
  pp["Done"].checkbox = false
  page.save
when "et"
  page = select_task end_task: true
  pp = page.properties
  pp["日付"].end_date = DateTime.now
  pp["Done"].checkbox = true
  page.save
when "st"
  if ARGV.empty?
    page = select_task end_task: true
    pp = page.properties
    pp["日付"].start_date = DateTime.now
    page.save
  else
    page = Database.find(DATABASE_ID).create_child_page do |p, pp|
      pp["タスク名"] << ARGV.join(" ")
      pp["日付"].start_date = DateTime.now
    end
  end
end
url = page["url"]
system("open #{url}")

5. おわりに

修正部分は少ないものの、スクリプトが多いので長いブログになってしまいました。とりあえずこれで運用を続けてみたいと思います。


hkob.notion.site