(後日追加) ここで説明している Notion workflow はこちらで配布しています。 github.com
1. はじめに
土曜日に作った Alfred の記事で二回目の Script Filter の使い方を理解しました。そこで、以前作った当日用の Notion タスク作成「an」に対して、プロジェクトを同時に設置するように修正してみることにしました。
2. 設計指針
以下のような指針で設計します。
- 「an タスク名 日付 開始時刻」の使い方は同じ。開始時刻を省略したら時刻なし、日付を省略したら自動的に今日になる。基本は「an タスク名」での利用を想定している。
- ここで、現在策定済のプロジェクト一覧を表示し、プロジェクトのリレーションを自動的に設定する。
- プロジェクトはそうそう変化しないので、取得後に YAML でファイルとして保存しておく。
- 二回目以降は Notion アクセスはせず、YAML から一覧を表示する。
- Shift + Return を押したときには、プロジェクトの再取得を行う。
3. 実装
3.1 プロジェクト側の設定
土曜日にポモの名前でハマったので、「プロジェクト」→「Project」に変換しました。まず、API から Project データベースにアクセスできるように、Share で「Input tasks」を招待します。
次に Alfred 側の環境設定です。Project のデータベースID を PROJECT_ID として登録しておきました。本来なら、DATABASE_ID は TASK_ID に直すべきなのですが、このままにしておきます。
3.2 共通スクリプトの修正
データベースが複数になったことと、Relation の設定を行いたいことから、二つのメソッドを修正しました。一つ目は get_notion_pages で database_id を変更できるようにしています。これまでのものを修正したくないので、省略可能な二番目の引数として、database_id を渡せるようにしました。省略時はこれまで通り、タスクデータベースになります。
# ページの取得 def get_notion_pages(payload, database_id = DATABASE_ID) post_notion URI.parse("https://api.notion.com/v1/databases/#{database_id}/query"), payload end
次に create_task に project_id を設定できるようにします。これも、省略可能な 3 番目の引数として、project_id を渡せるようにしました。せっかくなので、Hash 表記も Ruby っぽく直しています。project_id が渡された時だけ、relation が設定されるようになっています。
def create_task(title, datetime, project_id = nil) relation = project_id ? [{id: "#{project_id}"}] : [] post_notion URI.parse("https://api.notion.com/v1/pages"), { parent: { database_id: DATABASE_ID }, properties: { "タスク名" => { title: [ { text: { content: title } } ] }, "日付" => { type: "date", date: { start: datetime } }, Project: { type: "relation", relation: relation } } } end
3.3 flow の設置
Workflow は以下のような形になりました。Keyword と Run Script の間に、二つの「Arg and Vars」と一つの「Script Filter」を設置しました。
3.4 二つの Arg and Vars
左の通常時の Arg and Vars は、query を input という変数に逃しているだけです。 右の「Shift」キーを押された時の Arg and Vars は reload というフラグを追加で設定しています。違いはこれだけです。
3.5 Project 表示のための Script Filter
Script Filter の設定はこんな感じです。
Script の部分には、プロジェクトの呼び出しと YAML 書き出しがあります。すでに YAML がある場合には、この部分がスキップされます。ただし、「Shift」キーを押したときには、reload フラグがついているので、YAML 存在時にもプロジェクトを再読み込みするようになっています。ポモの場合と異なり今回は選択したプロジェクトを学習してほしいため、「uid」をちゃんと設定しています。この結果、前回選択したものが優先的に選ばれるようになっています。
require "./notion.rb" require "yaml" PROJECT_FNAME = "projects.yml" PROJECT_ID = ENV["PROJECT_ID"] if !ENV["reload"] && File.exists?(PROJECT_FNAME) projects = open(PROJECT_FNAME, "r") { |f| YAML.load f } else projects = get_notion_pages({ sorts: [ { "property": "name", "direction": "ascending" } ], }, PROJECT_ID).map { |p| prs = p["properties"] { id: p["id"], title: (prs["name"]["title"][0]["plain_text"] || ""), } } YAML.dump projects, File.open(PROJECT_FNAME, "w") end items = { items: projects.map do |p| { uid: p[:id], title: p[:title], arg: p[:id] } end } print JSON.dump(items)
3.6 タスク作成スクリプトの修正
最後にタスク作成スクリプトを修正します。引数には project_id だけが入ってくるので、ARGV[0] で取得しています。Keyword で入力されたタスク文字列は input 変数に入っているので、ENV["input"]で取得しています。あとは、最後に選択された project_id を create_task の最終パラメータに追加しただけです。
require './notion.rb' project_id = ARGV[0] date = nil summary = nil time = nil query = ENV["input"] words = query.split " " # 時間が存在するか? time = words.pop if words[-1] =~ /\d+:\d+/ # time が nil でなければ timezone を追加 time += TZ unless time.nil? begin date = Date.parse words[-1] # resque されてないなら words から抜いておく words.pop rescue end # 日付がなければ今日にする datetime = [(date || Date.today), time].compact.join " " summary = words.join " " create_task(summary, datetime, project_id)
4. テスト
プロジェクトが見えるように明日の日付でテストしてみました。すでに記事は今日書いているんだけど。うまくプロジェクトが設定できていますね。
Alfred からタスク作成する時にプロジェクトを選択して自動設定できるようにしてみた。#notion #まいにちnotion pic.twitter.com/vqC9drwOWO
— hkob (@hkob) 2021年7月12日
5. おわりに
これができるならカレンダーの方にもプロジェクトを入れてみたくなりました。カレンダーって使っていい属性とかがあるのか調べてみようと思います。