notion_ruby_mapping 0.7.4 → 0.7.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +2 -0
- data/exe/notionTimeRecorder.rb +284 -0
- data/lib/notion_ruby_mapping/controllers/notion_cache.rb +6 -3
- data/lib/notion_ruby_mapping/properties/date_property.rb +22 -0
- data/lib/notion_ruby_mapping/properties/property.rb +1 -1
- data/lib/notion_ruby_mapping/version.rb +1 -1
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f757b8eab76be0d30120c595afffc53dba4cde99a872c53eae58334d6d1ecd73
|
4
|
+
data.tar.gz: d342baef240aaf0cbabc1b9fe298eb99216367e72eeb9c0ed49f15bc58ffc930
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4e043303f49438475ef9ef87b2e7d91af74105bf2069286986d9727622e4056c8e9ab6921b3c06c55f24a3c10ad6ecb9b103fec88ddb3f90fde482fad6fc90dd
|
7
|
+
data.tar.gz: 30934684ec64206c5fcb6123dea99fdaa6fd3721ecb3ace0a1574980e2c93eb4ee4d2574f09c9eefb98a5b01fce761b2c4c09e5ab7a8b46f36d9bd3714615cee
|
data/README.md
CHANGED
@@ -119,6 +119,7 @@ NotionRubyMapping.configuration { |c| c.notion_token = ENV["NOTION_API_TOKEN"] }
|
|
119
119
|
4. [Create ER Diagram from Notion database / Notion データベースの ER 図を作成](https://hkob.notion.site/notionErDiagram-Sample-1720c2199c534ca08138cde38f31f710)
|
120
120
|
5. [Create Sitemap from Notion pages / Notion page からサイトマップを作成](https://hkob.notion.site/notionSitemap-sample-14e195c83d024c5382aab09210916c87)
|
121
121
|
6. [Create Notion databases from ER Diagram / ER 図から Notion データベースを作成](https://hkob.notion.site/erdToNotionDb-sample-87e5e52a6b9f46abbdeebcb3c902a516)
|
122
|
+
6. [NotionTimeRecorder & GTD template](https://hkob.notion.site/NotionTimeRecorder-GTD-template-8c4b5813dbbe4774a517314c9b20bafa)
|
122
123
|
|
123
124
|
### 2.5 API reference / API リファレンス
|
124
125
|
|
@@ -126,6 +127,7 @@ NotionRubyMapping.configuration { |c| c.notion_token = ENV["NOTION_API_TOKEN"] }
|
|
126
127
|
|
127
128
|
## 3. ChangeLog
|
128
129
|
|
130
|
+
- 2023/3/8 [v0.7.5] add notionTimeRecorder.rb
|
129
131
|
- 2023/2/9 [v0.7.4] bug fix for rollup property of erdToNotionRb.rb script
|
130
132
|
- 2023/1/26 [v0.7.3] release beta version of erdToNotionRb.rb script
|
131
133
|
- 2023/1/25 [v0.7.2] bug fix for creating relation property / add erdToNotionRb.rb script
|
@@ -0,0 +1,284 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
|
3
|
+
require "tk"
|
4
|
+
require "notion_ruby_mapping"
|
5
|
+
require "yaml"
|
6
|
+
require "time"
|
7
|
+
include Tk
|
8
|
+
include NotionRubyMapping
|
9
|
+
|
10
|
+
CONF_FILE_NAME = "#{ENV["HOME"]}/.notionTimeRecorder.yml"
|
11
|
+
|
12
|
+
class TaskConf
|
13
|
+
KEY_TO_METHOD = {
|
14
|
+
api_key: "NOTION_API_KEY",
|
15
|
+
db_id: "TASK_DB_ID",
|
16
|
+
tpn: "TITLE_PROPERTY_NAME",
|
17
|
+
dpn: "DATE_PROPERTY_NAME",
|
18
|
+
fpn: "FINISH_PROPERTY_NAME",
|
19
|
+
fpt: "FINISH_PROPERTY_TYPE",
|
20
|
+
ipv: "IN_PROGRESS_PROPERTY_VALUE",
|
21
|
+
fpv: "FINISH_PROPERTY_VALUE",
|
22
|
+
bln: "BLOCKING_PROPERTY_NAME",
|
23
|
+
bbn: "BLOCKED_BY_PROPERTY_NAME",
|
24
|
+
ppd: "PERCENT_PREVIOUS_DONE_FUNC_NAME",
|
25
|
+
}
|
26
|
+
|
27
|
+
# @param [Boolean] force_setup
|
28
|
+
def initialize(yaml_name, force_setup = false)
|
29
|
+
@yaml_name = yaml_name
|
30
|
+
@config = {}
|
31
|
+
setup(force_setup) if force_setup || !File.exist?(@yaml_name)
|
32
|
+
load_conf
|
33
|
+
end
|
34
|
+
|
35
|
+
# @param [Boolean] force_setup
|
36
|
+
def setup(force_setup)
|
37
|
+
load_conf if force_setup
|
38
|
+
@variables = {}
|
39
|
+
@conf_frame = TkLabelFrame.new(nil, text: "Configuration").pack(padx: 10, pady: 10)
|
40
|
+
KEY_TO_METHOD.each do |method, key|
|
41
|
+
@variables[method] = TkVariable.new @config[key]&.to_s
|
42
|
+
label_frame = TkLabelFrame.new(@conf_frame, text: key).pack(padx: 10, pady: 5)
|
43
|
+
if method == :fpt
|
44
|
+
TkRadioButton.new(label_frame, text: "status", variable: @variables[method], value: "status").pack
|
45
|
+
TkRadioButton.new(label_frame, text: "checkbox", variable: @variables[method], value: "checkbox").pack
|
46
|
+
else
|
47
|
+
TkEntry.new(label_frame, textvariable: @variables[method]).pack
|
48
|
+
end
|
49
|
+
end
|
50
|
+
cmd_frame = TkFrame.new(@conf_frame).pack
|
51
|
+
TkButton.new(cmd_frame, text: "Quit", command: ->{ exit }).pack(side: :left)
|
52
|
+
TkButton.new(cmd_frame, text: "Save", command: ->{ save }).pack(side: :right)
|
53
|
+
Tk.mainloop
|
54
|
+
end
|
55
|
+
|
56
|
+
def load_conf
|
57
|
+
@config = YAML.load_file @yaml_name
|
58
|
+
KEY_TO_METHOD.each do |method, key|
|
59
|
+
self.class.define_method(method) { @config[key] }
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def save
|
64
|
+
KEY_TO_METHOD.each do |method, key|
|
65
|
+
@config[key] = @variables[method].value.chomp
|
66
|
+
end
|
67
|
+
@config["FINISH_PROPERTY_VALUE"] = true if @config["FINISH_PROPERTY_VALUE"] == "true"
|
68
|
+
File.open(@yaml_name, "w") do |f|
|
69
|
+
YAML.dump @config, f
|
70
|
+
end
|
71
|
+
load_conf
|
72
|
+
@conf_frame.destroy
|
73
|
+
@task_cache = TaskCache.new self
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
class Task
|
78
|
+
# @param [NotionRubyMapping::Page] page
|
79
|
+
# @param [TaskCache] tc
|
80
|
+
def initialize(page, tc)
|
81
|
+
@page = page
|
82
|
+
@tc = tc
|
83
|
+
@conf = tc.conf
|
84
|
+
@date_property = @page.properties[@conf.dpn]
|
85
|
+
@finish_property = @page.properties[@conf.fpn]
|
86
|
+
@finish = (@conf.fpt == "status" ? @finish_property.status_name : @finish_property.checkbox) == @conf.fpv
|
87
|
+
@start_date = @date_property.start_date_obj
|
88
|
+
@end_date = @date_property.end_date_obj
|
89
|
+
end
|
90
|
+
|
91
|
+
def save
|
92
|
+
@page.save
|
93
|
+
@start_date = @date_property.start_date_obj
|
94
|
+
@end_date = @date_property.end_date_obj
|
95
|
+
@finish = (@conf.fpt == "status" ? @finish_property.status_name : @finish_property.checkbox) == @conf.fpv
|
96
|
+
end
|
97
|
+
|
98
|
+
def start_time_str
|
99
|
+
@start_date.nil? || @start_date.is_a?(Date) ? "-" : @start_date.strftime("%H:%M")
|
100
|
+
end
|
101
|
+
|
102
|
+
def end_time_str
|
103
|
+
@end_date.nil? || @end_date.is_a?(Date) ? "-" : @end_date.strftime("%H:%M")
|
104
|
+
end
|
105
|
+
|
106
|
+
def state
|
107
|
+
@finish ? "disabled" : "normal"
|
108
|
+
end
|
109
|
+
|
110
|
+
def time_recording(force_set_date = false)
|
111
|
+
if @start_date.nil? || force_set_date
|
112
|
+
@date_property.start_date = Date.today
|
113
|
+
@date_property.end_date = nil
|
114
|
+
save
|
115
|
+
@tc.move_to_today self
|
116
|
+
elsif @start_date.is_a?(Date)
|
117
|
+
@date_property.start_date = Time.now
|
118
|
+
@finish_property.send("#{@conf.fpt}=", @conf.ipv) unless @conf.ipv.empty?
|
119
|
+
@date_property.end_date = nil
|
120
|
+
save
|
121
|
+
@tc.update_today_tasks
|
122
|
+
else
|
123
|
+
@date_property.start_date = @date_property.start_date_obj
|
124
|
+
@date_property.end_date = Time.now
|
125
|
+
@finish_property.send("#{@conf.fpt}=", @conf.fpv)
|
126
|
+
save
|
127
|
+
if blocking_count&.positive?
|
128
|
+
@tc.reload_someday
|
129
|
+
@tc.update_today_tasks
|
130
|
+
else
|
131
|
+
@tc.update_today_tasks
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def blocking_count
|
137
|
+
@conf.bln.empty? ? nil : @page.properties[@conf.bln].relation.count
|
138
|
+
end
|
139
|
+
|
140
|
+
def view_task(frame, index, today_task = true)
|
141
|
+
TkButton.new(frame, text: @page.title, state: state, command: -> { time_recording }).grid(row: index, column: 0)
|
142
|
+
if today_task
|
143
|
+
TkLabel.new(frame, text: start_time_str).grid(row: index, column: 1)
|
144
|
+
TkLabel.new(frame, text: end_time_str).grid(row: index, column: 2)
|
145
|
+
elsif (bcnt = blocking_count)
|
146
|
+
TkLabel.new(frame, text: "+#{bcnt}").grid(row: index, column: 1)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
class TaskCache
|
152
|
+
# @param [TaskConf] conf
|
153
|
+
def initialize(conf)
|
154
|
+
@conf = conf
|
155
|
+
NotionRubyMapping.configure do |c|
|
156
|
+
c.notion_token = @conf.api_key
|
157
|
+
end
|
158
|
+
|
159
|
+
@db = Database.find conf.db_id
|
160
|
+
@db_date_property, @db_finish_property = @db.properties.values_at @conf.dpn, @conf.fpn
|
161
|
+
@today_tasks = []
|
162
|
+
@someday_tasks = []
|
163
|
+
@unfinished_tasks = []
|
164
|
+
@new_today_task_val = TkVariable.new
|
165
|
+
create_view
|
166
|
+
end
|
167
|
+
attr_reader :conf
|
168
|
+
|
169
|
+
def create_view
|
170
|
+
@today_outer_frame = TkLabelFrame.new(nil, text: "Today's tasks").pack(padx: 10, pady: 5)
|
171
|
+
@today_inner_frame = nil
|
172
|
+
@someday_outer_frame = TkLabelFrame.new(nil, text: "Someday").pack(padx: 10, pady: 5)
|
173
|
+
@someday_inner_frame = nil
|
174
|
+
@new_frame = TkLabelFrame.new(nil, text: "New task").pack(padx: 10, pady: 5)
|
175
|
+
entry = TkEntry.new(@new_frame, textvariable: @new_today_task_val).pack(side: :left)
|
176
|
+
entry.focus
|
177
|
+
entry.bind("Return", -> { add_someday_task })
|
178
|
+
TkButton.new(@new_frame, text: "Add", command: -> { add_someday_task }).pack(side: :right)
|
179
|
+
|
180
|
+
cmd_frame = TkFrame.new(nil).pack(pady: 5)
|
181
|
+
TkButton.new(cmd_frame, text: "Reload", command: ->{ reload }).pack(side: :left)
|
182
|
+
TkButton.new(cmd_frame, text: "Quit", command: ->{ exit }).pack(side: :right)
|
183
|
+
reload
|
184
|
+
end
|
185
|
+
|
186
|
+
def reload
|
187
|
+
NotionCache.instance.clear_object_hash
|
188
|
+
load_today_tasks
|
189
|
+
load_unfinished_tasks
|
190
|
+
update_today_tasks
|
191
|
+
load_someday_tasks
|
192
|
+
update_someday_tasks
|
193
|
+
end
|
194
|
+
|
195
|
+
def reload_someday
|
196
|
+
NotionCache.instance.clear_object_hash
|
197
|
+
load_someday_tasks
|
198
|
+
update_someday_tasks
|
199
|
+
end
|
200
|
+
|
201
|
+
def load_unfinished_tasks
|
202
|
+
now = Time.now
|
203
|
+
end_of_day = Time.local(now.year, now.month, now.mday, 23, 59, 59) - 86400
|
204
|
+
query = @db_date_property.filter_before(end_of_day)
|
205
|
+
.and(@db_finish_property.filter_does_not_equal(@conf.fpv))
|
206
|
+
@unfinished_tasks = @db.query_database(query).map { |tp| Task.new tp, self }
|
207
|
+
end
|
208
|
+
|
209
|
+
def load_today_tasks
|
210
|
+
query = @db_date_property.filter_equals(Date.today)
|
211
|
+
.ascending(@db_date_property)
|
212
|
+
@today_tasks = @db.query_database(query).map { |tp| Task.new tp, self }
|
213
|
+
end
|
214
|
+
|
215
|
+
def update_today_tasks
|
216
|
+
@today_inner_frame&.destroy
|
217
|
+
@today_inner_frame = TkFrame.new(@today_outer_frame).pack
|
218
|
+
@today_tasks.sort! { |a, b| a.start_time_str <=> b.start_time_str }
|
219
|
+
@today_tasks.each_with_index { |task, i| task.view_task @today_inner_frame, i }
|
220
|
+
uc = @unfinished_tasks.count
|
221
|
+
TkButton.new(@today_inner_frame, text: "Add unfinished #{uc} tasks", command: -> { add_unfinished_tasks })
|
222
|
+
.grid(row: @today_tasks.count, column: 0) if uc.positive?
|
223
|
+
end
|
224
|
+
|
225
|
+
def load_someday_tasks
|
226
|
+
query = @db_date_property.filter_is_empty
|
227
|
+
.and(@db_finish_property.filter_does_not_equal(@conf.fpv))
|
228
|
+
unless @conf.ppd.empty?
|
229
|
+
ppd_p = @db.properties[@conf.ppd]
|
230
|
+
query_is_empty = ppd_p.filter_is_empty another_type: "number"
|
231
|
+
query_equals_1 = ppd_p.filter_equals 1, another_type: "number"
|
232
|
+
query.and(query_is_empty.or(query_equals_1))
|
233
|
+
end
|
234
|
+
@someday_tasks = @db.query_database(query).map { |tp| Task.new tp, self }
|
235
|
+
end
|
236
|
+
|
237
|
+
def update_someday_tasks
|
238
|
+
@someday_inner_frame&.destroy
|
239
|
+
@someday_inner_frame = TkFrame.new(@someday_outer_frame).pack
|
240
|
+
@someday_tasks.each_with_index { |task, i| task.view_task @someday_inner_frame, i, false }
|
241
|
+
end
|
242
|
+
|
243
|
+
def add_someday_task
|
244
|
+
task_name = @new_today_task_val.value
|
245
|
+
if !@conf.bbn.empty? && task_name.include?("|")
|
246
|
+
previous_id = nil
|
247
|
+
task_name.split("|").each do |title|
|
248
|
+
page = @db.create_child_page do |_, pp|
|
249
|
+
pp[@conf.tpn] << title
|
250
|
+
pp[@conf.bbn].relation = previous_id if previous_id
|
251
|
+
end
|
252
|
+
previous_id = page.id
|
253
|
+
end
|
254
|
+
@new_today_task_val.value = ""
|
255
|
+
reload
|
256
|
+
else
|
257
|
+
tp = @db.create_child_page do |_, pp|
|
258
|
+
pp[@conf.tpn] << task_name
|
259
|
+
end
|
260
|
+
@new_today_task_val.value = ""
|
261
|
+
@someday_tasks << Task.new(tp, self)
|
262
|
+
update_someday_tasks
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
def add_unfinished_tasks
|
267
|
+
@unfinished_tasks.each do |task|
|
268
|
+
task.time_recording true
|
269
|
+
end
|
270
|
+
@unfinished_tasks = []
|
271
|
+
update_today_tasks
|
272
|
+
end
|
273
|
+
|
274
|
+
def move_to_today(task)
|
275
|
+
@someday_tasks.delete task
|
276
|
+
@today_tasks << task
|
277
|
+
update_today_tasks
|
278
|
+
update_someday_tasks
|
279
|
+
end
|
280
|
+
end
|
281
|
+
|
282
|
+
@task_conf = TaskConf.new CONF_FILE_NAME, ARGV.first == "-c"
|
283
|
+
@task_cache = TaskCache.new @task_conf
|
284
|
+
Tk.mainloop
|
@@ -22,10 +22,11 @@ module NotionRubyMapping
|
|
22
22
|
@notion_token = nil
|
23
23
|
@wait = 0.3333
|
24
24
|
@debug = false
|
25
|
+
@use_cache = true
|
25
26
|
end
|
26
27
|
attr_reader :object_hash
|
27
28
|
attr_writer :client # for test only
|
28
|
-
attr_accessor :notion_token, :wait, :debug
|
29
|
+
attr_accessor :notion_token, :wait, :debug, :use_cache
|
29
30
|
|
30
31
|
# @param [String] block_id
|
31
32
|
# @return [String (frozen)] block_path
|
@@ -175,10 +176,12 @@ module NotionRubyMapping
|
|
175
176
|
# @return [NotionRubyMapping::Base]
|
176
177
|
def object_for_key(id)
|
177
178
|
key = hex_id(id)
|
178
|
-
return @object_hash[key] if @object_hash.key?
|
179
|
+
return @object_hash[key] if @use_cache && @object_hash.key?(key)
|
179
180
|
|
180
181
|
json = yield(@client)
|
181
|
-
|
182
|
+
ans = Base.create_from_json json
|
183
|
+
@object_hash[key] = ans if @use_cache
|
184
|
+
ans
|
182
185
|
end
|
183
186
|
|
184
187
|
# @param [String] id page_id (with or without "-")
|
@@ -24,6 +24,17 @@ module NotionRubyMapping
|
|
24
24
|
@json["end"]
|
25
25
|
end
|
26
26
|
|
27
|
+
def end_date_obj
|
28
|
+
assert_page_property __method__
|
29
|
+
jet = @json["end"]
|
30
|
+
case jet
|
31
|
+
when String
|
32
|
+
jet.include?("T") ? Time.parse(jet) : Date.parse(jet)
|
33
|
+
else
|
34
|
+
jet
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
27
38
|
# @param [Date, Time, DateTime, String] edt
|
28
39
|
# @see https://www.notion.so/hkob/DateProperty-c6e815c060cb430889dbb33b697f00c6#944c02096101429084527c22155683bf
|
29
40
|
def end_date=(edt)
|
@@ -41,6 +52,17 @@ module NotionRubyMapping
|
|
41
52
|
@json["start"]
|
42
53
|
end
|
43
54
|
|
55
|
+
def start_date_obj
|
56
|
+
assert_page_property __method__
|
57
|
+
jst = @json["start"]
|
58
|
+
case jst
|
59
|
+
when String
|
60
|
+
jst.include?("T") ? Time.parse(jst) : Date.parse(jst)
|
61
|
+
else
|
62
|
+
jst
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
44
66
|
# @param [Date, Time, DateTime, String] sdt
|
45
67
|
# @see https://www.notion.so/hkob/DateProperty-c6e815c060cb430889dbb33b697f00c6#4f5931f1588a43f7857af8ab2d73df74
|
46
68
|
def start_date=(sdt)
|
@@ -24,7 +24,7 @@ module NotionRubyMapping
|
|
24
24
|
:last_edited_by, :last_edited_time, :multi_select, :multi_select=, :multi_select_names, :number,
|
25
25
|
:number=, :people, :people=, :phone_number, :phone_number=, :property_values_json, :relation=,
|
26
26
|
:rollup, :start_date, :start_date=, :time_zone, :time_zone=, :select, :select=, :select_name, :url,
|
27
|
-
:url
|
27
|
+
:url=, :start_date_obj, :end_date_obj
|
28
28
|
|
29
29
|
## Database property only methods
|
30
30
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: notion_ruby_mapping
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.7.
|
4
|
+
version: 0.7.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Hiroyuki KOBAYASHI
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-03-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faraday
|
@@ -143,6 +143,7 @@ executables:
|
|
143
143
|
- erdToNotionDb.rb
|
144
144
|
- notionErDiagram.rb
|
145
145
|
- notionSitemap.rb
|
146
|
+
- notionTimeRecorder.rb
|
146
147
|
extensions: []
|
147
148
|
extra_rdoc_files: []
|
148
149
|
files:
|
@@ -164,6 +165,7 @@ files:
|
|
164
165
|
- exe/erdToNotionDb.rb
|
165
166
|
- exe/notionErDiagram.rb
|
166
167
|
- exe/notionSitemap.rb
|
168
|
+
- exe/notionTimeRecorder.rb
|
167
169
|
- images/post_set_icon.png
|
168
170
|
- images/pre_set_icon.png
|
169
171
|
- images/serial_number.png
|
@@ -276,7 +278,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
276
278
|
- !ruby/object:Gem::Version
|
277
279
|
version: '0'
|
278
280
|
requirements: []
|
279
|
-
rubygems_version: 3.4.
|
281
|
+
rubygems_version: 3.4.7
|
280
282
|
signing_key:
|
281
283
|
specification_version: 4
|
282
284
|
summary: Notion Ruby mapping tool
|