Forked from benwaldie/2013-04-12-TUAW_Waldie.applescript
Last active
December 18, 2015 16:39
-
-
Save mathie/5813044 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--============================== | |
-- OmniFocus > Prepare Task Completion Report | |
-- Version 2.0.0 | |
-- Written By: Ben Waldie <[email protected]> | |
-- http://www.automatedworkflows.com | |
-- Description: This script retrieves a list of OmniFocus tasks completed today, yesterday, this week, last week, or this month. It then summarizes the tasks in a new Evernote note. | |
-- Version History: | |
-- 1.0.0 - Initial release | |
-- 2.0.0 - Added support for including full project paths, context names, estimate time, start dates, modification dates, completion dates, and notes in task reports. | |
--============================== | |
-- This property controls whether full project paths (including parent folders) are displayed | |
property includeFullProjectPaths : true | |
-- These properties control whether additional task content is displayed | |
property includeTaskContext : true | |
property includeTaskEstimatedTime : true | |
property includeTaskStartDate : true | |
property includeTaskModificationDate : false | |
property includeTaskCompletionDate : true | |
property includeTaskNotes : true | |
-- This setting specifies a name for the new note | |
property noteNamedAfterDateRange : true | |
property evernoteNotebook : "Journal" | |
-- Extract some more properties for the bits I want to change | |
property defaultReport : "Today" | |
property startOfWeek : Monday | |
property endOfWeek : Sunday | |
property appendToExistingNote : true | |
-- Prompt the user to choose a scope for the report | |
activate | |
set theReportScope to choose from list {"Today", "Yesterday", "This Week", "Last Week", "This Month"} default items {defaultReport} with prompt "Generate a report for:" with title "OmniFocus Completed Task Report" | |
if theReportScope = false then return | |
set theReportScope to item 1 of theReportScope | |
-- Calculate the task start and end dates, based on the specified scope | |
set theStartDate to current date | |
set hours of theStartDate to 0 | |
set minutes of theStartDate to 0 | |
set seconds of theStartDate to 0 | |
set theEndDate to theStartDate + (23 * hours) + (59 * minutes) + 59 | |
if theReportScope = "Today" then | |
set theDateRange to date string of theStartDate | |
set singleDay to true | |
else if theReportScope = "Yesterday" then | |
set theStartDate to theStartDate - 1 * days | |
set theEndDate to theEndDate - 1 * days | |
set theDateRange to date string of theStartDate | |
set singleDay to true | |
else if theReportScope = "This Week" then | |
repeat until (weekday of theStartDate) = startOfWeek | |
set theStartDate to theStartDate - 1 * days | |
end repeat | |
repeat until (weekday of theEndDate) = endOfWeek | |
set theEndDate to theEndDate + 1 * days | |
end repeat | |
set theDateRange to (date string of theStartDate) & " through " & (date string of theEndDate) | |
set singleDay to false | |
else if theReportScope = "Last Week" then | |
set theStartDate to theStartDate - 7 * days | |
set theEndDate to theEndDate - 7 * days | |
repeat until (weekday of theStartDate) = startOfWeek | |
set theStartDate to theStartDate - 1 * days | |
end repeat | |
repeat until (weekday of theEndDate) = endOfWeek | |
set theEndDate to theEndDate + 1 * days | |
end repeat | |
set theDateRange to (date string of theStartDate) & " through " & (date string of theEndDate) | |
set singleDay to false | |
else if theReportScope = "This Month" then | |
repeat until (day of theStartDate) = 1 | |
set theStartDate to theStartDate - 1 * days | |
end repeat | |
repeat until (month of theEndDate) is not equal to (month of theStartDate) | |
set theEndDate to theEndDate + 1 * days | |
end repeat | |
set theEndDate to theEndDate - 1 * days | |
set theDateRange to (date string of theStartDate) & " through " & (date string of theEndDate) | |
set singleDay to false | |
end if | |
-- Begin preparing the task list as HTML. | |
set theProgressDetail to "<h2>" & theDateRange & "</h2><br>" | |
-- Retrieve a list of projects modified within the specified scope | |
set modifiedTasksDetected to false | |
tell application "OmniFocus" | |
tell front document | |
set theModifiedProjects to every flattened project where its modification date is greater than theStartDate | |
-- Loop through any detected projects | |
repeat with a from 1 to length of theModifiedProjects | |
set theCurrentProject to item a of theModifiedProjects | |
-- Retrieve any project tasks modified within the specified scope | |
set theCompletedTasks to (every flattened task of theCurrentProject where its completed = true and modification date is greater than theStartDate and modification date is less than theEndDate and number of tasks = 0) | |
-- Process the project if tasks were found | |
if theCompletedTasks is not equal to {} then | |
set modifiedTasksDetected to true | |
-- Append the project folder path to the project name | |
set theProjectFolderPath to "" | |
if includeFullProjectPaths = true then | |
set theProjectFolderPath to getProjectFolderPath(theCurrentProject) of me | |
if theProjectFolderPath is not equal to "" then set theProjectFolderPath to theProjectFolderPath & " > " | |
end if | |
-- Append the project name to the report | |
set theProgressDetail to theProgressDetail & "<h3>" & theProjectFolderPath & name of theCurrentProject & "</h3>" & return & "<br><ul>" | |
-- Loop through the detected tasks for the project | |
repeat with b from 1 to length of theCompletedTasks | |
set theCurrentTask to item b of theCompletedTasks | |
-- Append the tasks's name to the task list | |
set theProgressDetail to theProgressDetail & "<li>" & name of theCurrentTask | |
-- Append the context to the task detail | |
if includeTaskContext = true then | |
set theContext to context of theCurrentTask | |
if theContext is not equal to missing value then set theProgressDetail to theProgressDetail & " <span style=\"color: gray\">(" & name of theContext & ")</span>" | |
end if | |
-- Set up a variable for the task detail, if relevant | |
set theTaskDetail to "" | |
-- Append the estimated time to the task detail | |
if includeTaskEstimatedTime = true then set theTaskDetail to appendTaskDetail(theTaskDetail, estimated minutes of theCurrentTask, "Estimated Time", " minutes") of me | |
-- Append the start date to the task detail | |
if includeTaskStartDate = true then | |
set theTaskStartDate to start date of theCurrentTask | |
if theTaskStartDate is not equal to missing value then set theTaskStartDate to date string of theTaskStartDate | |
set theTaskDetail to appendTaskDetail(theTaskDetail, theTaskStartDate, "Start on", "") of me | |
end if | |
-- Append the modification date to the task detail | |
if includeTaskModificationDate = true then | |
set theModificationDate to modification date of theCurrentTask | |
if singleDay = true then set theModificationDate to time string of theModificationDate | |
set theTaskDetail to appendTaskDetail(theTaskDetail, theModificationDate, "Last modified at", "") of me | |
end if | |
-- Append the completion date to the task detail | |
if includeTaskCompletionDate = true then | |
set theCompletionDate to completion date of theCurrentTask | |
if singleDay = true then set theCompletionDate to time string of theCompletionDate | |
set theTaskDetail to appendTaskDetail(theTaskDetail, theCompletionDate, "Completed at", "") of me | |
end if | |
-- Append the task's notes to the task detail | |
if includeTaskNotes = true then set theTaskDetail to appendTaskDetail(theTaskDetail, note of theCurrentTask, "Note", "") of me | |
-- Append the task detail to the task list | |
if theTaskDetail is not equal to "" then | |
set theProgressDetail to theProgressDetail & "<br><p style=\"color: gray\">" & theTaskDetail & "</p>" | |
end if | |
-- Finish adding the task's HTML to the list | |
set theProgressDetail to theProgressDetail & "</li>" & return | |
end repeat | |
set theProgressDetail to theProgressDetail & "</ul>" & return | |
end if | |
end repeat | |
end tell | |
end tell | |
-- Notify the user if no projects or tasks were found | |
if modifiedTasksDetected = false then | |
display alert "OmniFocus Completed Task Report" message "No modified tasks were found for " & theReportScope & "." | |
return | |
end if | |
if noteNamedAfterDateRange = true then | |
set theRealNoteName to theDateRange | |
else | |
set theRealNoteName to theNoteName | |
end if | |
-- Create the note in Evernote. | |
tell application "Evernote" | |
activate | |
if appendToExistingNote = true then | |
set theMatchingNotes to find notes "notebook:\"" & evernoteNotebook & "\" intitle:\"" & theRealNoteName & "\"" | |
if theMatchingNotes is not equal to {} then | |
set theNote to item 1 of theMatchingNotes | |
append theNote html "<br><hr><br>" & theProgressDetail | |
else | |
set theProgressDetail to "<html><body><h1>Completed Tasks</h1><br>" & theProgressDetail & "</body></html>" | |
set theNote to create note notebook evernoteNotebook title theRealNoteName with html theProgressDetail | |
end if | |
else | |
set theProgressDetail to "<html><body><h1>Completed Tasks</h1><br>" & theProgressDetail & "</body></html>" | |
set theNote to create note notebook evernoteNotebook title theRealNoteName with html theProgressDetail | |
end if | |
end tell | |
-- This handler gets the folder path for a project | |
on getProjectFolderPath(theProject) | |
tell application "OmniFocus" | |
set theFolderPath to "" | |
if folder of theProject exists then | |
set theFolder to folder of theProject | |
repeat | |
if theFolderPath is not equal to "" then set theFolderPath to " : " & theFolderPath | |
set theFolderPath to name of theFolder & theFolderPath | |
if class of container of theFolder = folder then | |
set theFolder to container of theFolder | |
else | |
exit repeat | |
end if | |
end repeat | |
end if | |
if theFolderPath = "" then set theFolderPath to "" | |
return theFolderPath | |
end tell | |
end getProjectFolderPath | |
-- This handler appends a value to the task detail | |
on appendTaskDetail(theTaskDetail, theValue, thePrefix, theSuffix) | |
if theValue = missing value or theValue = "" then | |
return theTaskDetail | |
else | |
if theTaskDetail is not equal to "" then set theTaskDetail to theTaskDetail & "<br>" | |
set theValue to theValue & theSuffix | |
return theTaskDetail & thePrefix & ": " & theValue | |
end if | |
end appendTaskDetail |
Now onto personal style preferences:
- Don't show modification date (chances are the last thing I'll do to a task is complete it, so completion and modification date are likely the same).
- h3 for the project name, since the date range is an h2.
- Collapse the context down into the title.
- Don't open the note in a new window, ta.
Oh, and tweak the date-related property ifs so it actually honours the right ones.
And (finally, for now, at least):
- Start dates are just shown as dates, not date/times.
- If the report range is a single day, then modification/completion is just a time, not a date.
Tweaked the project fetcher to fetch projects modified between the start date and now, rather than the start date and end date. That way, when reporting on 'yesterday' (or any other historical report) it will also consider tasks completed yesterday inside projects that have been subsequently modified today.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Now tweaked to append to an existing note instead of creating a new one each time.