1. はじめに
Notion アンバサダー仲間の円谷さんが GTD を解説する YouTube 動画を公開していました。私も OmniFocus や Todoist などのツールを変遷としながら、Notion での GTD 運用に辿り着きました。
これまでの GTD の運用はこんな感じでした。
- Inbox: 日付なしタスクとしてページを作成します。声でタスク登録や nt, ntd コマンドで登録します。
- 次のアクション: 以前は日付なしタスクを全て今日のタスクに変更していました。実施できなかったタスクは日付が変わるのでそれらを今日のタスクに毎日移動していました。
- カレンダー: 時間に結びついているタスクは普通にカレンダーに入れます。
最初はこれらの仕組みを yuka さんのまいにち Notion のフィルタ付ビューで運用していました。しかし、この毎日のタスク移動が面倒になってしまい、次のアクションと Inbox を融合させた運用をしておりました。改修前の Launchpad はこんな感じになっていました。ここで、日付未確定のタスクが Inbox 兼次のアクションに相当していました。
この運用は次のアクションのタスク移動がなくなった代わりに、アクションを開始するハードルが高くなってしまいました。今日のタスクの部分にタスクがなくなってしまうと仕事が終わった感覚になってしまい、次のアクション探しを積極的にやらなくなっていました。この結果、日付未確定のタスクにやるべき仕事がどんどん溜まってしまう点が問題となっていました。
今回、円谷さんの動画を閲覧し、再度デビッドアレンの本を読み返したことで、次のアクションからアクションを始めるる部分をハードル下げる必要を感じました。今回の改修はこの部分をよりやりやすくするためのものです。
2. ページの改修
システムを修正する前にページ構成を変更しました。画面は以下のようになりました。
上(白背景): タイムラインビューで一日のタスクの幅をみえるようにしています。 左上(緑背景): 次のアクションを表示します。今日の日付のタスクをフィルタして表示しています。 左中(黄色背景): 明日のタスクを表示します。基本的にはカレンダータスクが表示されています。これを横目に見ながら次のアクションを検討します。 左下(青背景): 最近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. おわりに
修正部分は少ないものの、スクリプトが多いので長いブログになってしまいました。とりあえずこれで運用を続けてみたいと思います。