Plug-In: Guided Processing of Inbox Tasks

Based upon a concept by Scotty Jackson (heyscottyj.com), this plug-in will iterate the tasks in the Inbox, prompting the user to select the processing procedures (if any) to be applied to the iterated task.

This plug-in achieves the sequential display of Action Forms by incorporating an asynchronous version of the single-file plug-in that uses await statements within an asynchronous wrapper rather than relying on explicit Promise handlers. When used within a standard JavaScript for loop, an individually selected set of form interfaces can be displayed in sequence for each of the inbox tasks.

Return to: OmniFocus Plug-In Collection

DISCLAIMER: Mention of third-party websites and products is for informational purposes only and constitutes neither an endorsement nor a recommendation. OMNI-AUTOMATION.COM assumes no responsibility with regard to the selection, performance or use of information or products found at third-party websites. OMNI-AUTOMATION.COM provides this only as a convenience to our users. OMNI-AUTOMATION.COM has not tested the information found on these sites and makes no representations regarding its accuracy or reliability. There are risks inherent in the use of any information or products found on the Internet, and OMNI-AUTOMATION.COM assumes no responsibility in this regard. Please understand that a third-party site is independent from OMNI-AUTOMATION.COM and that OMNI-AUTOMATION.COM has no control over the content on that website. Please contact the vendor for additional information.

Process Inbox
  

/*{ "type": "action", "targets": ["omnifocus"], "author": "Otto Automator", "identifier": "com.omni-automation.of.process-inbox", "version": "1.1", "description": "A plug-in that performs operations with the contents of the inbox.", "label": "Process Inbox", "shortLabel": "Process Inbox", "paletteLabel": "Process Inbox", "image": "checkmark.rectangle.stack.fill" }*/ (() => { const action = new PlugIn.Action(async function(selection, sender){ try { await new Alert("Process Inbox", "Based upon a concept by Scotty Jackson.").show() processableTasks = inbox.filter(item => { itemsTaskStatus = item.taskStatus if( itemsTaskStatus === Task.Status.Available || itemsTaskStatus === Task.Status.DueSoon || itemsTaskStatus === Task.Status.Overdue ){return true} }) inboxCount = processableTasks.length if(inboxCount === 0){ throw { name : "Missing Items", message : "The Inbox does not contain any tasks whose status is Available, Due Soon, or Overdue." } } taskIDs = processableTasks.map(task => task.id.primaryKey) masterOperationsList = ["Rename", "Assign to Project", "Assign Tag", "Set Defer Date", "Set Due Date", "Flag/UnFlag", "Add/Edit Note", "Complete", "Drop"] masterOperationIndexes = new Array() masterOperationsList.forEach((item, index) => {masterOperationIndexes.push(index)}) console.log("masterOperationIndexes", JSON.stringify(masterOperationIndexes)) var i; for (i = 0; i < taskIDs.length; i++) { console.log(i) taskID = taskIDs[i] task = Task.byIdentifier(taskID) taskName = task.name console.log(taskName, taskID) // PROMPT USER FOR TASK PROCSSSING alertTitle = "CONFIRM" alertMessage = `TASK (${i + 1}/${inboxCount}): ${taskName}` alert = new Alert(alertTitle, alertMessage) alert.addOption("Process") alert.addOption("Skip") alert.addOption("Stop") buttonIndex = await alert.show() console.log("button", buttonIndex) if(buttonIndex === 1){continue} if(buttonIndex === 2){throw "user canceled"} console.log("choose processing options") // PROCESSING OPTIONS inputForm = new Form() taskPrompt = "Processing options:" multiOptionMenu = new Form.Field.MultipleOptions( "operationsKey", taskPrompt, masterOperationIndexes, masterOperationsList, [] ) inputForm.addField(multiOptionMenu) inputForm.validate = function(){return true} formMessage = `TASK (${i + 1}/${inboxCount}): ${taskName}` formButton = "Process" formObject = await inputForm.show(formMessage,formButton) taskOperationIndexes = formObject.values['operationsKey'] console.log("taskOperationIndexes", JSON.stringify(taskOperationIndexes)) // RENAME TASK if(taskOperationIndexes.includes(0)){ console.log("RENAME", taskID) var namingForm = new Form() var nameInputField = new Form.Field.String( "newName", "Name", taskName, null ) namingForm.addField(nameInputField) namingForm.validate = function(namingFormObj){ newName = namingFormObj.values["newName"] if(!newName){return false} return (newName.length > 0)?true:false } var formMessage = "Enter new name for task:" var formButtonTitle = "Rename" namingFormObj = await namingForm.show(formMessage, formButtonTitle) newName = namingFormObj.values["newName"] task.name = newName taskName = newName } // ASSIGN TO PROJECT if(taskOperationIndexes.includes(1)){ console.log("ASSIGN TO PROJECT", taskID) var projectSearchForm = new Form() var textInputField = new Form.Field.String( "targetProjectName", null, null, null ) projectSearchForm.addField(textInputField) projectSearchForm.validate = function(searchFormObj){ targetProjectName = searchFormObj.values["targetProjectName"] if(!targetProjectName){return false} return (targetProjectName.length > 0)?true:false } var formMessage = "Search for project:" var formButtonTitle = "Search" var projectSearchFormObj = await projectSearchForm.show(formMessage, formButtonTitle) var targetProjectName = projectSearchFormObj.values["targetProjectName"] var projectSearchResults = projectsMatching(targetProjectName) console.log("projectSearchResults", projectSearchResults) console.log("projectSearchResults.length", projectSearchResults.length) if(projectSearchResults.length === 0){ var projectNamingForm = new Form() var textInputField = new Form.Field.String( "targetProjectName", null, null, null ) projectNamingForm.addField(textInputField) projectNamingForm.validate = function(searchFormObj){ targetProjectName = searchFormObj.values["targetProjectName"] if(!targetProjectName){return false} return (targetProjectName.length > 0)?true:false } var formMessage = "No matches, enter name for new project:" var formButtonTitle = "Create" var projectNamingFormObj = await projectNamingForm.show(formMessage, formButtonTitle) var targetProjectName = projectNamingFormObj.values["targetProjectName"] var project = new Project(targetProjectName) moveTasks([task], project) } else if (projectSearchResults.length === 1){ moveTasks([task], projectSearchResults[0]) } else { // get names of matching projectSearchForm var projectTitles = projectSearchResults.map(project => project.name) var projectIndexes = projectTitles.map((project, index) => {return index}) var projectAssignmentForm = new Form() var projectsMenu = new Form.Field.Option( "matchingProject", null, projectIndexes, projectTitles, 0 ) projectAssignmentForm.addField(projectsMenu) projectAssignmentForm.validate = function(){return true} var formMessage = "Select matching project:" var formButtonTitle = "Add Task" var projectAssignmentFormObj = await projectAssignmentForm.show(formMessage, formButtonTitle) var targetProjectIndex = projectAssignmentFormObj.values["matchingProject"] var parentProject = projectSearchResults[targetProjectIndex] moveTasks([task], parentProject) } } // ASSIGN TAG if(taskOperationIndexes.includes(2)){ console.log("ASSIGN TAGS", taskID) var tagTitles = flattenedTags.map(tag => tag.name) var tagIDs = flattenedTags.map(tag => tag.id.primaryKey) var tagIndexes = tagTitles.map((title, index) => {return index}) if(tagTitles.length > 0){ var tagOptionsForm = new Form() var multiOptionMenu = new Form.Field.MultipleOptions( "tagTitles", null, tagIndexes, tagTitles, [] ) tagOptionsForm.addField(multiOptionMenu) var formMessage = "Select the tags to assign:" var formButtonTitle = "Add Tags" var tagOptionsFormObj = await tagOptionsForm.show(formMessage, formButtonTitle) task.clearTags() var targetTagsIndexes = tagOptionsFormObj.values["tagTitles"] targetTagsIndexes.forEach(tagIndex => { var tag = Tag.byIdentifier(tagIDs[tagIndex]) task.addTag(tag) }) } else { // create new tag var tagCreationForm = new Form() var textInputField = new Form.Field.String( "newTagName", null, null, null ) tagCreationForm.addField(textInputField) tagCreationForm.validate = function(searchFormObj){ var newTagName = searchFormObj.values["newTagName"] if(!newTagName){return false} return (newTagName.length > 0)?true:false } var formMessage = "No tags. Enter new tag:" var formButtonTitle = "Create" var tagCreationFormObj = await tagCreationForm.show(formMessage, formButtonTitle) task.clearTags() var newTagName = tagCreationFormObj.values["newTagName"] task.addTag(new Tag(newTagName)) } } // SET DEFER DATE if(taskOperationIndexes.includes(3)){ console.log("SET DEFER DATE", taskID) var defermentForm = new Form() var defermentDateInput = new Form.Field.Date( "defermentDate", null, task.deferDate, null ) defermentForm.addField(defermentDateInput) var formMessage = "Enter defer date:" var formButtonTitle = "Add Date" var defermentFormObj = await defermentForm.show(formMessage, formButtonTitle) var defermentDate = defermentFormObj.values["defermentDate"] if(defermentDate){ task.deferDate = defermentDate } else { task.deferDate = null } } // SET DUE DATE if(taskOperationIndexes.includes(4)){ console.log("SET DUE DATE", taskID) var dueForm = new Form() var dueDateInput = new Form.Field.Date( "taskDueDate", null, task.dueDate, null ) dueForm.addField(dueDateInput) dueForm.validate = function(dueFormObj){ var temptDueDate = dueFormObj.values["taskDueDate"] if(temptDueDate){ if(task.deferDate >= temptDueDate){throw "Due date must come after defer date."} } return true } var formMessage = "Enter due date:" var formButtonTitle = "Add Date" var dueFormObj = await dueForm.show(formMessage, formButtonTitle) var taskDueDate = dueFormObj.values["taskDueDate"] if(taskDueDate){ task.dueDate = taskDueDate } else { task.dueDate = null } } // SET FLAG if(taskOperationIndexes.includes(5)){ console.log("SET FLAG", taskID) var flagStatus = task.flagged var alertTitle = (flagStatus)? "Task Flagged":"Task Not Flagged" var alertMessage = "Choose flag status:" var alert = new Alert(alertTitle, alertMessage) alert.addOption("Flag") alert.addOption("Un-Flag") var flagOptionAlertButtonIndex = await alert.show() if(flagOptionAlertButtonIndex === 0){ task.flagged = true } else { task.flagged = false } } // SET NOTE if(taskOperationIndexes.includes(6)){ console.log("SET NOTE", taskID) var noteForm = new Form() var taskNote = task.note var noteTextInputField = new Form.Field.String( "taskNote", null, taskNote, null ) var shouldAppendSwitch = new Form.Field.Checkbox( "shouldAppendToNote", "Append to existing note", null ) noteForm.addField(noteTextInputField) noteForm.addField(shouldAppendSwitch) var formMessage = "Enter task note:" var formButtonTitle = "Add" var noteFormObj = await noteForm.show(formMessage, formButtonTitle) var newNote = noteFormObj.values["taskNote"] var shouldAppendToNote = noteFormObj.values["shouldAppendToNote"] if (newNote === null || newNote === undefined){ newNote = "" } if(shouldAppendToNote){ task.appendStringToNote(newNote) } else { task.note = newNote } } // COMPLETE if(taskOperationIndexes.includes(7)){ console.log("SET COMPLETE", taskID) var completionStatus = task.completed var alertTitle = (completionStatus)? "Task Completed":"Task Incomplete" var alertMessage = "Choose completion status:" var alert = new Alert(alertTitle, alertMessage) alert.addOption("Mark Completed") alert.addOption("Mark Incomplete") var flagOptionAlertButtonIndex = await alert.show() if(flagOptionAlertButtonIndex === 0){ task.markComplete() } else { task.markIncomplete() } } // DROP if(taskOperationIndexes.includes(8)){ console.log("SET DROP", taskID) var dropStatus = (task.dropDate) ? true:false console.log("dropStatus", dropStatus) var alertTitle = (dropStatus) ? "Task Dropped":"Task Not Dropped" var alertMessage = "Choose drop status:" var alert = new Alert(alertTitle, alertMessage) alert.addOption("Drop Task") alert.addOption("Un-Drop Task") var dropStatusAlertButtonIndex = await alert.show() if(dropStatusAlertButtonIndex === 0){ task.drop(true) } else { task.active = true } } } } catch(err){ if (!err.causedByUserCancelling){ new Alert(err.name, err.message).show() } } }); action.validate = function(selection, sender){ // validation code return (inbox.length > 0) }; return action; })();