plansheet 0.9.0 → 0.12.0
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/.rubocop_todo.yml +4 -5
- data/Gemfile.lock +1 -1
- data/exe/plansheet +8 -1
- data/lib/plansheet/project.rb +133 -34
- data/lib/plansheet/sheet.rb +1 -1
- data/lib/plansheet/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d1c4e7e5e45d00a1218ac7346c60ba9182c7b73ac2761958c24ea8c8dcf15d9d
|
4
|
+
data.tar.gz: 50cc492240c458e5bc13539f03203007b8922dcd2e00e5108d6f929c81419f2e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2fe3310c09dfe7d4e79172a476f3bcfc0a3ef6261757a4070a6f49d9857673524663ee97622db603acae911201d5f1acc9cdb65d7c30547ea0e3f4610dc5e0bf
|
7
|
+
data.tar.gz: 58aee2a5ab4f95c114461a8ef614823b5c4e22e0961c792623d0720b033a40c1abbdf1d23887b7b5a38b4823138994116d3eb6b42f2675263d0825d567fee173
|
data/.rubocop_todo.yml
CHANGED
@@ -9,28 +9,27 @@
|
|
9
9
|
# Offense count: 1
|
10
10
|
# Configuration parameters: CountComments, CountAsOne.
|
11
11
|
Metrics/ClassLength:
|
12
|
-
|
12
|
+
Enabled: false
|
13
13
|
|
14
14
|
# Offense count: 1
|
15
15
|
# Configuration parameters: IgnoredMethods.
|
16
16
|
Metrics/CyclomaticComplexity:
|
17
|
-
|
17
|
+
Enabled: false
|
18
18
|
|
19
19
|
# Offense count: 2
|
20
20
|
# Configuration parameters: CountComments, CountAsOne, ExcludedMethods, IgnoredMethods.
|
21
21
|
Metrics/MethodLength:
|
22
|
-
|
22
|
+
Enabled: false
|
23
23
|
|
24
24
|
# Offense count: 1
|
25
25
|
# Configuration parameters: IgnoredMethods.
|
26
26
|
Metrics/PerceivedComplexity:
|
27
|
-
|
27
|
+
Enabled: false
|
28
28
|
|
29
29
|
# Offense count: 2
|
30
30
|
# Configuration parameters: AllowedConstants.
|
31
31
|
Style/Documentation:
|
32
32
|
Exclude:
|
33
|
-
- 'spec/**/*'
|
34
33
|
- 'test/**/*'
|
35
34
|
- 'lib/plansheet.rb'
|
36
35
|
- 'lib/plansheet/project.rb'
|
data/Gemfile.lock
CHANGED
data/exe/plansheet
CHANGED
@@ -17,6 +17,10 @@ parser.on(
|
|
17
17
|
"--cli",
|
18
18
|
"CLI dump of projects (WIP)"
|
19
19
|
)
|
20
|
+
parser.on(
|
21
|
+
"--location_filter LOCATION",
|
22
|
+
"location filter for CLI dump (WIP)"
|
23
|
+
)
|
20
24
|
options = {}
|
21
25
|
parser.parse!(into: options)
|
22
26
|
|
@@ -32,7 +36,10 @@ elsif options[:sort]
|
|
32
36
|
Plansheet.resort_projects_in_dir config["projects_dir"]
|
33
37
|
elsif options[:cli]
|
34
38
|
project_arr = Plansheet.load_projects_dir config["projects_dir"]
|
35
|
-
project_arr.sort
|
39
|
+
project_arr.sort!
|
40
|
+
project_arr.delete_if { |x| x.status == "dropped" || x.status == "done" }
|
41
|
+
project_arr.select! { |x| x.location == options[:location_filter] } if options[:location_filter]
|
42
|
+
project_arr.each do |proj|
|
36
43
|
puts proj
|
37
44
|
puts "\n"
|
38
45
|
end
|
data/lib/plansheet/project.rb
CHANGED
@@ -8,10 +8,11 @@ module Plansheet
|
|
8
8
|
"wip" => 1,
|
9
9
|
"ready" => 2,
|
10
10
|
"blocked" => 3,
|
11
|
-
"
|
12
|
-
"
|
13
|
-
"
|
14
|
-
"
|
11
|
+
"waiting" => 4,
|
12
|
+
"planning" => 5,
|
13
|
+
"idea" => 6,
|
14
|
+
"dropped" => 7,
|
15
|
+
"done" => 8
|
15
16
|
}.freeze
|
16
17
|
|
17
18
|
PROJECT_PRIORITY = {
|
@@ -44,9 +45,10 @@ module Plansheet
|
|
44
45
|
type: str
|
45
46
|
enum:
|
46
47
|
- wip # project is a work-in-progress
|
47
|
-
- ready # project
|
48
|
-
-
|
49
|
-
-
|
48
|
+
- ready # project has tasks, ready to go
|
49
|
+
- waiting # project in waiting on some external person/event
|
50
|
+
- blocked # project is blocked by another project, but otherwise ready/wip
|
51
|
+
- planning # project in planning phase (set manually)
|
50
52
|
- idea # project is little more than an idea
|
51
53
|
- dropped # project has been explicitly dropped, but
|
52
54
|
# want to keep around for reference, etc
|
@@ -58,12 +60,35 @@ module Plansheet
|
|
58
60
|
"notes":
|
59
61
|
desc: Free-form notes string
|
60
62
|
type: str
|
63
|
+
"time_estimate":
|
64
|
+
desc: The estimated amount of time before a project is completed
|
65
|
+
type: str
|
66
|
+
"frequency":
|
67
|
+
desc: The amount of time before a recurring project moves to ready status again from when it was last done (WIP)
|
68
|
+
type: str
|
69
|
+
pattern: /\\d+[dwDW]/
|
70
|
+
"lead_time":
|
71
|
+
desc: The amount of time before a recurring project is "due" moved to ready where the project (sort of a deferral mechanism) (WIP)
|
72
|
+
type: str
|
73
|
+
pattern: /\\d+[dwDW]/
|
61
74
|
"due":
|
62
75
|
desc: Due date of the task
|
63
76
|
type: date
|
64
77
|
"defer":
|
65
78
|
desc: Defer task until this day
|
66
79
|
type: date
|
80
|
+
"created_on":
|
81
|
+
desc: When the project was created
|
82
|
+
type: date
|
83
|
+
"starts_on":
|
84
|
+
desc: For ICS (WIP)
|
85
|
+
type: date
|
86
|
+
"last_reviewed":
|
87
|
+
desc: When the project was last reviewed (WIP)
|
88
|
+
type: date
|
89
|
+
"last_done":
|
90
|
+
desc: When the recurring project was last completed (WIP)
|
91
|
+
type: date
|
67
92
|
"dependencies":
|
68
93
|
desc: The names of projects that need to be completed before this project can be started/completed
|
69
94
|
type: seq
|
@@ -89,9 +114,21 @@ module Plansheet
|
|
89
114
|
type: seq
|
90
115
|
sequence:
|
91
116
|
- type: str
|
117
|
+
"tags":
|
118
|
+
desc: List of tags (WIP)
|
119
|
+
type: seq
|
120
|
+
sequence:
|
121
|
+
- type: str
|
92
122
|
YAML
|
93
123
|
PROJECT_SCHEMA = YAML.safe_load(PROJECT_YAML_SCHEMA)
|
94
124
|
|
125
|
+
def self.parse_date_duration(str)
|
126
|
+
return Regexp.last_match(1).to_i if str.strip.match(/(\d+)[dD]/)
|
127
|
+
return (Regexp.last_match(1).to_i * 7) if str.strip.match(/(\d+)[wW]/)
|
128
|
+
|
129
|
+
raise "Can't parse time duration string #{str}"
|
130
|
+
end
|
131
|
+
|
95
132
|
# The use of instance_variable_set/get probably seems a bit weird, but the
|
96
133
|
# intent is to avoid object allocation on non-existent project properties, as
|
97
134
|
# well as avoiding a bunch of copy-paste boilerplate when adding a new
|
@@ -101,10 +138,18 @@ module Plansheet
|
|
101
138
|
class Project
|
102
139
|
include Comparable
|
103
140
|
|
141
|
+
DEFAULT_COMPARISON_ORDER = %w[
|
142
|
+
completeness
|
143
|
+
dependency
|
144
|
+
priority
|
145
|
+
defer
|
146
|
+
due
|
147
|
+
status
|
148
|
+
].map { |x| "compare_#{x}".to_sym }.freeze
|
104
149
|
# NOTE: The order of these affects presentation!
|
105
|
-
STRING_PROPERTIES = %w[priority status location notes].freeze
|
106
|
-
DATE_PROPERTIES = %w[due defer].freeze
|
107
|
-
ARRAY_PROPERTIES = %w[dependencies externals urls tasks done].freeze
|
150
|
+
STRING_PROPERTIES = %w[priority status location notes time_estimate frequency lead_time].freeze
|
151
|
+
DATE_PROPERTIES = %w[due defer created_on starts_on last_done last_reviewed].freeze
|
152
|
+
ARRAY_PROPERTIES = %w[dependencies externals urls tasks done tags].freeze
|
108
153
|
|
109
154
|
ALL_PROPERTIES = STRING_PROPERTIES + DATE_PROPERTIES + ARRAY_PROPERTIES
|
110
155
|
|
@@ -132,14 +177,7 @@ module Plansheet
|
|
132
177
|
|
133
178
|
def <=>(other)
|
134
179
|
ret_val = 0
|
135
|
-
|
136
|
-
compare_completeness
|
137
|
-
compare_dependency
|
138
|
-
compare_priority
|
139
|
-
compare_due
|
140
|
-
compare_defer
|
141
|
-
compare_status
|
142
|
-
].each do |method|
|
180
|
+
DEFAULT_COMPARISON_ORDER.each do |method|
|
143
181
|
ret_val = send(method, other)
|
144
182
|
break if ret_val != 0
|
145
183
|
end
|
@@ -177,40 +215,101 @@ module Plansheet
|
|
177
215
|
|
178
216
|
def compare_dependency(other)
|
179
217
|
return 0 if @dependencies.nil? && other.dependencies.nil?
|
218
|
+
|
180
219
|
if @dependencies.nil?
|
181
|
-
return -1 if other.dependencies.any?
|
220
|
+
return -1 if other.dependencies.any? do |dep|
|
182
221
|
@name.downcase == dep.downcase
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
222
|
+
end
|
223
|
+
elsif @dependencies.any? do |dep|
|
224
|
+
other.name.downcase == dep.downcase
|
225
|
+
end
|
226
|
+
return 1
|
188
227
|
end
|
189
|
-
|
228
|
+
0
|
190
229
|
end
|
191
230
|
|
192
231
|
# Projects that are dropped or done are considered "complete", insofar as
|
193
232
|
# they are only kept around for later reference.
|
194
233
|
def compare_completeness(other)
|
195
|
-
return 0 if
|
196
|
-
return 0 if !
|
197
|
-
|
234
|
+
return 0 if dropped_or_done? && other.dropped_or_done?
|
235
|
+
return 0 if !dropped_or_done? && !other.dropped_or_done?
|
236
|
+
|
237
|
+
dropped_or_done? ? 1 : -1
|
198
238
|
end
|
199
239
|
|
200
240
|
def status
|
201
241
|
return @status if @status
|
242
|
+
return recurring_status if recurring?
|
243
|
+
return task_based_status if (@tasks || @done)
|
244
|
+
# TODO: return done if done count is positive...
|
202
245
|
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
246
|
+
"idea"
|
247
|
+
end
|
248
|
+
|
249
|
+
def task_based_status
|
250
|
+
if @tasks&.count&.positive? && @done&.count&.positive?
|
251
|
+
"wip"
|
252
|
+
elsif @tasks&.count&.positive?
|
253
|
+
"ready"
|
254
|
+
elsif @done&.count&.positive?
|
255
|
+
"done"
|
209
256
|
else
|
210
257
|
"idea"
|
211
258
|
end
|
212
259
|
end
|
213
260
|
|
261
|
+
def recurring_status
|
262
|
+
# add frequency to last_done
|
263
|
+
unless @last_done
|
264
|
+
# This recurring project is being done for the first time
|
265
|
+
task_based_status
|
266
|
+
else
|
267
|
+
# This project has been done once before
|
268
|
+
subsequent_recurring_status
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
272
|
+
def subsequent_recurring_status
|
273
|
+
return "done" if @lead_time && defer > Date.today
|
274
|
+
return "done" if due > Date.today
|
275
|
+
task_based_status
|
276
|
+
end
|
277
|
+
|
278
|
+
def process_recurring
|
279
|
+
# TODO: Tasks will be moved from done->tasks if recurring project is
|
280
|
+
# starting again
|
281
|
+
end
|
282
|
+
|
283
|
+
# Due date either explicit or recurring
|
284
|
+
def due
|
285
|
+
return @due if @due
|
286
|
+
return recurring_due_date if recurring?
|
287
|
+
nil
|
288
|
+
end
|
289
|
+
|
290
|
+
def recurring_due_date
|
291
|
+
if @last_done
|
292
|
+
@last_done + Plansheet.parse_date_duration(@frequency)
|
293
|
+
else
|
294
|
+
Date.today
|
295
|
+
end
|
296
|
+
end
|
297
|
+
|
298
|
+
def defer
|
299
|
+
return @defer if @defer
|
300
|
+
return lead_time_deferral if @lead_time && due
|
301
|
+
nil
|
302
|
+
end
|
303
|
+
|
304
|
+
def lead_time_deferral
|
305
|
+
[(due - Plansheet.parse_date_duration(@lead_time)),
|
306
|
+
Date.today].max
|
307
|
+
end
|
308
|
+
|
309
|
+
def recurring?
|
310
|
+
!@frequency.nil?
|
311
|
+
end
|
312
|
+
|
214
313
|
def dropped_or_done?
|
215
314
|
status == "dropped" || status == "done"
|
216
315
|
end
|
data/lib/plansheet/sheet.rb
CHANGED
data/lib/plansheet/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: plansheet
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.12.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Crosby
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-06-
|
11
|
+
date: 2022-06-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: dc-kwalify
|