Plug-In Forms: Sequential Forms

The following example plug-in demonstrates the use of sequential forms to gather multiple instances of user input data.

In order to maintain the ability to easily read and edit plug-in code that contains multiple alerts and forms, the example code avoids the use of nested functions by using an asynchronous version of the single-file plug-in that incorporates await statements within an asynchronous wrapper rather than relying on explicit Promise handlers and code blocks.

In the example plug-in, three forms and two alerts are presented, with input data from each form logged to the console, and a confirmation dialog presented to the user at the end of the plug-in’s execution.

Sequential Forms
  

/*{ "type": "action", "targets": ["omnigraffle", "omnifocus", "omniplan", "omnioutliner"], "author": "Otto Automator", "identifier": "com.omni-automation.all.sequential-forms", "version": "1.1", "description": "A plug-in that presents a series of forms.", "label": "Sequential Forms", "shortLabel": "Sequential Forms", "paletteLabel": "Sequential Forms", "image": "gearshape.fill" }*/ (() => { const action = new PlugIn.Action(async function(selection, sender){ try { // USER ALERT alertTitle = "Sequential Forms" alertMessage = "This plug-in presents a series of forms." await new Alert(alertTitle, alertMessage).show() menu1Items = ["Monday","Tuesday","Wednesday","Thursday","Friday"] menu1Indexes = new Array() menu1Items.forEach((item, index) => menu1Indexes.push(index)) menu2Items = ["9:00 AM", "9:15 AM", "9:30 AM", "9:45 AM", "10:00 AM", "10:15 AM", "10:30 AM", "10:45 AM", "11:00 AM", "11:15 AM", "11:30 AM", "11:45 AM", "12:00 PM", "12:15 PM", "12:30 PM", "12:45 PM", "1:00 PM", "1:15 PM", "1:30 PM", "1:45 PM", "2:00 PM", "2:15 PM", "2:30 PM", "2:45 PM", "3:00 PM", "3:15 PM", "3:30 PM", "3:45 PM", "4:00 PM", "4:15 PM", "4:30 PM", "4:45 PM"] menu2Indexes = menu2Items.map((item, index) => index) menu1Element = new Form.Field.Option( "menu1Element", null, menu1Indexes, menu1Items, 0 ) menu2Element = new Form.Field.Option( "menu2Element", null, menu2Indexes, menu2Items, 0 ) workdayTimeForm = new Form() workdayTimeForm.addField(menu1Element) workdayTimeForm.addField(menu2Element) workdayTimeForm.validate = function(formObject){ return true } formPrompt = "Select an appointment day and time:" buttonTitle = "Continue" workdayTimeFormObject = await workdayTimeForm.show(formPrompt, buttonTitle) menu1Index = workdayTimeFormObject.values['menu1Element'] chosen1Item = menu1Items[menu1Index] menu2Index = workdayTimeFormObject.values['menu2Element'] chosen2Item = menu2Items[menu2Index] chosen2Item = chosen2Item.replace(' ', '') fmatr = Formatter.Date.withStyle(Formatter.Date.Style.Full, Formatter.Date.Style.Short) appointmentDateObj = fmatr.dateFromString(`${chosen1Item} @ ${chosen2Item}`) appointmentDateStr = fmatr.stringFromDate(appointmentDateObj) console.log("Appointment Date Object •", appointmentDateObj) // AREAS OF CONCERN FORM menu3Items = ["Tire Rotation","Wheel Alignment","Battery Check","Exterior/Interior Lights","Brake Systems","Other"] menu3Indexes = new Array() menu3Items.forEach((item,index) => menu3Indexes.push(index)) multiOptionMenu1 = new Form.Field.MultipleOptions( "areasOfConcernKey", null, menu3Indexes, menu3Items, [] ) appointmentConcernsForm = new Form() appointmentConcernsForm.addField(multiOptionMenu1) appointmentConcernsForm.validate = function(formObject){ indexes = formObject.values["areasOfConcernKey"] return (indexes.length > 0) } formPrompt = "Select areas of concern:" buttonTitle = "Continue" appointmentConcernsFormObject = await appointmentConcernsForm.show(formPrompt, buttonTitle) concernsIndexes = appointmentConcernsFormObject.values["areasOfConcernKey"] concernsIndexes.forEach(index => { console.log("Area of concern •", menu3Items[index]) }) // CUSTOMER COMMENTS FORM textInputField1 = new Form.Field.String( "textInput1", null, null ) customerCommentsForm = new Form() customerCommentsForm.addField(textInputField1) customerCommentsForm.validate = function(formObject){ textInput1 = formObject.values['textInput1'] return (textInput1 && textInput1.length > 0) ? true:false } formPrompt = "Your comments:" buttonTitle = "Continue" customerCommentsFormObject = await customerCommentsForm.show(formPrompt, buttonTitle) customerComments = customerCommentsFormObject.values['textInput1'] console.log("Customer Comments •", customerComments) // CONFIRMATION ALERT alertTitle = "CONFIRMATION" alertMessage = "Your appointment is for:\n\n" + appointmentDateStr await new Alert(alertTitle, alertMessage).show() } catch(err){ if(!err.causedByUserCancelling){ new Alert(err.name, err.message).show() } } }); action.validate = function(selection, sender){ return true }; return action; })();