-
Notifications
You must be signed in to change notification settings - Fork 1
/
Projects list.applescript
386 lines (194 loc) · 8.82 KB
/
Projects list.applescript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
use application "OmniFocus"
use scripting additions
tell application "OmniOutliner"
if version ³ 5 then
set template to ((path to application support from user domain as string) & "The Omni Group:OmniOutliner:Pro Templates:" & "Blank.otemplate:") --- template path for OO5
else
set template to ((path to application support from user domain as string) & "The Omni Group:OmniOutliner:Templates:" & "Blank.oo3template:") --- template for OO3 or OO4
end if
set currentDate to current date
activate
open template
tell front document
tell application "OmniFocus"
if version < 3 then
error "You need to have OmniFocus version 3 or later. Early versions are not supported!"
end if
end tell
(*
ask user whether to display current projects or on-hold
*)
set userChoice to display dialog "Which projects to display?
(will self-close in 5 seconds)" buttons {"Active", "On-Hold", "All"} default button 1 giving up after 5
if gave up of userChoice is true then
return
end if
(*
create custom named styles
*)
delete named styles
set _green to make named style with properties {name:"Green highlight"}
set value of attribute "text-background-color" of _green to {r:0.470589, g:0.768627, b:0.270588, a:0.25}
set _yellow to make named style with properties {name:"Yellow highlight"}
set value of attribute "text-background-color" of _yellow to {r:1.0, g:0.774726, b:0.0, a:0.25}
set _red to make named style with properties {name:"Red highlight"}
set value of attribute "text-background-color" of _red to {r:0.968049, g:0.472297, b:0.539657, a:0.25}
(*
create columns in OmniOutliner
*)
set title of second column to "Project Name"
make new column with properties {title:"Project Status", sort order:ascending}
make new column with properties {title:"Project Due Date", column type:datetime}
make new column with properties {title:"Root Folder"}
(*
iterate through projects which are (must match ALL conditions):
- active
- on hold
- not dropped
- not (effectively) dropped
*)
if button returned of userChoice is "Active" then
set _projects to flattened projects of default document whose effective status is active status
else if button returned of userChoice is "On-Hold" then
set _projects to flattened projects of default document whose effective status is on hold status
else if button returned of userChoice is "All" then
set _projects to flattened projects of default document whose (effective status is active status or effective status is on hold status)
else
error "Reached primary loop but user choice is undetermined!"
end if
repeat with thisProject in _projects
using terms from application "OmniFocus" --- workaround for "folder" term collision (future use)
(*
find root folder of the project (start section)
*)
set rootFolder to folder of thisProject
set rootFolderName to missing value
if folder of thisProject is not missing value then
set folderName to name of folder of thisProject
else
set folderName to missing value
end if
if rootFolder is missing value then --- checking for root level projects
set rootFolderName to "n/a"
set foundRootFolderName to true
else
set foundRootFolderName to false
end if
repeat until foundRootFolderName is true
set upperFolder to container of rootFolder
set upperFolderName to name of upperFolder
if upperFolderName is equal to "OmniFocus" then
set rootFolderName to name of rootFolder as string
if folderName is not equal to rootFolderName then
set rootFolderName to folderName & " (" & rootFolderName & ")" as string
end if
set foundRootFolderName to true
else
set rootFolder to upperFolder
end if
end repeat
end using terms from
(*
create new row in OmniOutliner
*)
if text of second cell of first row is equal to "" then
set newRow to first row
else
set newRow to make new row at end of (parent of last row)
end if
(*
add OmniFocus project name and create deep link to it
*)
set text of second cell of newRow to name of thisProject
set value of attribute named "link" of style of text of second cell of newRow to "omnifocus:///task/" & id of thisProject
(*
add OmniFocus project status
*)
set projectStatus to status of thisProject as string
--- singleton projects are not given granularity as they simply hold a list of tasks (actions)
if singleton action holder of thisProject as boolean is true then
set projectStatus to "action list"
else
--- regular (active) projects (sequential or parallel) are given high level granurality
if thisProject's status is active status then
--- internal variables used to determine project's status
set cAvailTasks to 0
set cAvailTasksTags to 0
set cRemainTasks to 0
set cRemainTasksTags to 0
set cWaitingTasks to 0
set cDeferredTasks to 0
set bFirstAvailTaskIsWaiting to false
--- iterate through every remaining task of the project
repeat with thisTask in (flattened tasks of thisProject whose effectively completed is false and effectively dropped is false)
set cRemainTasks to cRemainTasks + 1
if thisTask's primary tag is not missing value then
set cRemainTasksTags to cRemainTasksTags + 1
if thisTask's primary tag's name contains "wait" then
set cWaitingTasks to cWaitingTasks + 1
end if
end if
if thisTask's defer date ² currentDate and thisTask's blocked is false then
set cAvailTasks to cAvailTasks + 1
if thisTask's primary tag is not missing value then
set cAvailTasksTags to cAvailTasksTags + 1
end if
else
set cDeferredTasks to cDeferredTasks + 1
end if
end repeat
--- check if first available task is "wait-for" for sequential projects
set tmpVar to missing value
if thisProject is sequential and next task of thisProject is not missing value then
if primary tag of next task of thisProject is not missing value then
if name of primary tag of next task of thisProject is not missing value then
set tmpVar to name of primary tag of next task of thisProject
end if
end if
end if
if tmpVar contains "wait" then
set bFirstAvailTaskIsWaiting to true
end if
--- project has no remaining tasks
if cRemainTasks = 0 then
set projectStatus to "stalled (no tasks)"
end if
--- project has remaining tasks with no tags
if cRemainTasks > 0 and cRemainTasksTags = 0 then
set projectStatus to "stalled (no tags)"
end if
--- all project's available tasks are "wait-for" context
if cWaitingTasks > 0 and (cAvailTasksTags = cWaitingTasks or bFirstAvailTaskIsWaiting is true) then
set projectStatus to "waiting"
end if
--- project has no available tasks but has remaining tasks
if thisProject's defer date is missing value and cAvailTasksTags = 0 and cRemainTasksTags > 0 then
set projectStatus to "deferred (tasks)"
end if
--- project is deferred by project's defer date
if thisProject's defer date is not missing value and thisProject's defer date ³ currentDate then
set projectStatus to "deferred (project)"
end if
--- rename project's status from "active status" to "active"
if projectStatus is "active status" then
set projectStatus to "active"
end if
--- project is on hold
else if thisProject's status is on hold status then
set projectStatus to "on hold"
end if
end if
set text of third cell of newRow to projectStatus
(*
add OmniFocus project due date
*)
if due date of thisProject is not equal to missing value then
set value of fourth cell of newRow to due date of thisProject as date
end if
(*
add OmniFocus root folder name of the project
*)
set text of fifth cell of newRow to rootFolderName as string
end repeat
end tell
end tell