Action
Weekly/Monthly event : prep notes
Instructions
purpose of the action
This action’s original inspiration is to keeps notes throughout the week or month, for a regular meeting or event.
For example if you remember updates to share, or questions to ask in your upcoming weekly meeting, this action will organize them all into 1 draft(“log draft”) for you.
It will also create a reminder for 10 minutes before the next event. The reminder will have a link that opens the “log draft”, so you don’t need to go looking for your draft during the meeting
a little more detail
How it works
How to use the action is very similar to the “add to list” action by @agiletortoise, but for Regularly occurring events.
Tap the action, select a event that you have previously set, and the action will automatically store your draft content to a “log draft”
Instead of a constant list, this action will keep a running note for each upcoming event
e.g. monthly, bi-monthly meetings, events every xx days, etc.)
1 log draft per each event
It is a “log draft” for each meeting.
So the 1st time you use it, it will create a new log draft and add the current text.
For example, for a weekly meeting on Monday at 9:00, it will append the current draft to the same “log draft” until Monday at 9:00, with a time stamp.
After Monday 9:00, it will create a new “log draft” again for the next Monday’s meeting notes and so on.
Time stamp
The time stamp is set to the last edit date of the current draft.
This is so, if you write a note down, but forget to use the action, it will still show when you last wrote down your notes
customization
I’ve made it so you can customize most of the action from 4 “template tags” steps.
This is so you don’t need to know the JavaScript code to do most of the customizations.
Instructions for customizing 4 template tags
1st template tag : category
Set your events in this 1st template tag.
There are examples set by default, but please feel free to change these based on your needs.
This is maybe the most difficult part, but you only need to set this once, and I promise it’s not too bad if you follow the instructions below, so please bare with me…
There are 4 types of dates this action can calculate for
Here are 4 examples
- “Weekly” : e.g. a meeting, every Monday at 9:00
- “Monthly (date)” : e.g. a self evaluation, on the 11th, 21st & 31st of every month, at 21:00
- “Monthly (weekday)” : e.g. an event, every 2nd & 4th Mondays at 13:00. Or a monthly seminar, on the 1st Thursday of the month, at 17:00(Works for once a month or multiple)
- “Every xx days” : e.g. shopping list every 10 days, at 11:00, from Jul 25 2022
These 4 examples will be inputted as the following
Please keep reading to see how to set the template
meeting % mon % 9:00 % weekly
Self evaluation % 11:21:31 % 21:00 % date
event % Monday % 13:00 % month % 2:4
seminar % Thu % 17:00 % month % 1
shopping list % jul 25 2022 % 11:00 % days % 10
Separate with “%”
#1 weekly
“title% day of the week% time of event% type=weekly”
- title = any name, but do not use %
- day of the week = 3 letters or full weekday name, not case sensitive (e.g. monday, Monday, MONDAY, MON, mon)
- time of event = 24 hour formatted time (“:” needed to separate hh:mm)
- type = “weekly”
Example #1 would become
“Meeting 1% monday% 9:00% weekly”
#2 same date of every month
“title% dates:date% time of event% type=date”
- title = any name, but do not use %
- dates = dates of the month, separated by “:” for multiple (e.g. 1:15:30 for 1st, 15th, and the 30th)
- time of event = 24 hour formatted time (“:” needed to separate hh:mm)
- type = “date”
Example #2 would become
“Self evaluation% 11:21:31% 21:00% date”
#3 the xth weekday of every month
“title% weekday% time of event% type=month”% frequency(xth weekday)
- title = any name, but do not use %
- day of the week = 3 letters or full weekday name, not case sensitive (e.g. monday, Monday, MONDAY, MON, mon)
- time of event = 24 hour formatted time (“:” needed to separate hh:mm)
- type = “month”
- frequency : the xth weekday of the month(e.g. every 1st and 3rd Sundays will be “1:3”)
Example #3 would become
event % Monday % 13:00 % month % 2:4
and
seminar % Thu % 17:00 % month % 1
#4 every xx days from a certain date
“title% date of 1st event% time of event% type=days”% frequency(every xx day)
- title = any name, but do not use %
- date of 1st event = the date of the first event to count from in the following format “mmm dd yyyy” (e.g. jul 25 2022)
- time of event = 24 hour formatted time (“:” needed to separate hh:mm)
- type = “days”
- frequency : every xx days(e.g. every 15days will be “15”)
Example #4 would become
shopping % jul 25 2022 % 11:00 % days % 10
2nd template tag : appendTitle
Here you can set part of the title
All log draft’s start with the following 2 lines
“# [[EventTitle]] + [[appendTitle]]”
“## Date(WWW MMM DD YYYY)”
Event title = The title you input on the 1st template tag\
appendTitle = anything you input in the 2nd template tag
For example,
If 2nd template tag is “ : prep notes”
And there is a “Meeting” on Aug 1
It will show as…
“# Meeting : prep notes”
“## Mon Aug 01 2022”
By default the template tag is set to “ : prep notes”
3rd template tag : tagPreset
This action will assign #prep-notes to the log Draft
If you want to add any other tags, write them here
If there are multiple, add them here by separating the lines
This step is blank by default
4th template tag : reminderList
This last template tag will set the reminders list to use
Reminder lists are like folders for the reminders app
Because the action creates a reminder for your log draft, it need to know where to put the reminder.
Set this to whatever list you want the reminder to be created in.
By default it is set to “PrepNotes”
Steps
-
defineTemplateTag
name category
template meeting % mon % 9:00 % weekly Self evaluation % 11:21:31 % 21:00 % date event % Monday % 13:00 % month % 2:4 seminar % Thu % 17:00 % month % 1 shopping list % jul 25 2022 % 11:00 % days % 10
-
defineTemplateTag
name appendTitle
template : prep notes
-
defineTemplateTag
name tagPresets
template -
defineTemplateTag
name reminderList
template PrepNotes
-
script
// use last edit date as time stamp /* import defined template tags */ // main tag to assign to add drafts const listTag = "prep-notes"; // setup categories const categories = draft.processTemplate("[[category]]").trim().split("\n"); // text to add to append to title const appendTitle = draft.processTemplate("[[appendTitle]]"); // tags to add other than "prep-notes" const tags = draft.processTemplate("[[tagPresets]]").trim().split("\n"); // which reminders list to add to const list = ReminderList.findOrCreate(draft.processTemplate("[[reminderList]]").trim()); /* get current draft, date + create a prompt to choose event from */ // grab current draft const currentContent = draft.content.trim();; // set today let today = new Date(); // also time of draft's last edit as "lastEdit" <- needed because "today" will be modified later let lastEdit = new Date(draft.modifiedAt); // prompt to select a event criteria let p = Prompt.create(); p.title = "Select Event"; for (var cat of categories) { ca = cat.trim().split(/\s*%\s*/); p.addButton(ca[0], ca) } if (p.show()) { // user made a selection var criteria = p.buttonPressed; // grab time of the event let criteriaT = criteria[2].split(/\s*:\s*/); // convert time to value var criteriaHour = Number(criteriaT[0]); var criteriaMin = Number(criteriaT[1]); /* set variables */ // find out if current time is before event time var criteriaTime = new Date(today); criteriaTime = new Date(criteriaTime.setHours(criteriaHour, criteriaMin, 0)); let eventYet = (today - criteriaTime); var yet = false; if (eventYet < 0) { yet = true; } else { yet = false; } // template tag week day conversion array var weekday=new Array(7); weekday["sunday"] = 0; weekday["monday"] = 1; weekday["tuesday"] = 2; weekday["wednesday"] = 3; weekday["thursday"] = 4; weekday["friday"] = 5; weekday["saturday"] = 6; weekday["sun"] = 0; weekday["mon"] = 1; weekday["tue"] = 2; weekday["wed"] = 3; weekday["thu"] = 4; weekday["fri"] = 5; weekday["sat"] = 6; // set today's time to 12:00:00 to prevent issues with daylight saving time // (any time between 1:00:01 ~ 22:59:59 is ok, but using 12:00:00 for convenience) today = new Date(today.setHours(12, 0, 0)); /* the key variable for the function "nextEvent" is what the upcoming function will return */ var nextEvent = new Date(today); var daysTilEvent; // set function to get the "nextEvent" function getNextEventDay(title, dayOf, time, type, freq) { // #1 if weekly event if (type == "weekly") { // Current date + dates until next meetingday daysTilEvent = weekday[dayOf.toLowerCase()] - today.getDay(); // if today is the same day as event if (daysTilEvent == 0){ // find out if it is before the event time // if event not started yet, set event date to today if (yet == true) { nextEvent = new Date(nextEvent.setHours(criteriaHour, criteriaMin, 0)); } // if event already started, set event date to next week (+ 7days) else { nextEvent = new Date(nextEvent.setDate(nextEvent.getDate() + 7)); nextEvent = new Date(nextEvent.setHours(criteriaHour, criteriaMin, 0)); } } // event is next week else if (daysTilEvent < 0){ nextEvent = new Date(nextEvent.setDate(nextEvent.getDate() + (daysTilEvent + 7))); nextEvent = new Date(nextEvent.setHours(criteriaHour, criteriaMin, 0)); } // event is this week week else { nextEvent = new Date(nextEvent.setDate(nextEvent.getDate() + daysTilEvent)); nextEvent = new Date(nextEvent.setHours(criteriaHour, criteriaMin, 0)); } } // #2 if event is a date of every month else if (type == "date") { let eventDates = dayOf.split(/\s*:\s*/); eventDates = eventDates.map(str => { return Number(str); }); for (let eventDate of eventDates) { daysTilEvent = eventDate - today.getDate(); // if today is the event date and before the event time if ((daysTilEvent == 0) && (yet == true)) { nextEvent = new Date(nextEvent.setDate(eventDate)); break; } // if today is not the event date nextEvent = new Date(nextEvent.setDate(eventDate)); // end loop the first time nextEvent > today if (daysTilEvent > 0) { break; } } // if loop is complete, but "daysTilEvent" is still < 0 // or if today is the date & it is the last day of the array & it is not the time for the event yet // the "nextEvent" will be the first date of the array in the next month if ((daysTilEvent < 0) || ((daysTilEvent == 0) && (nextEvent.getDate() == eventDates[eventDates.length - 1]) && (yet == false))) { // set date to 1, to avoid issues of (Jan 31 + month) -> (Feb 31 = Mar3) nextEvent = new Date(nextEvent.setDate(1)) // now set to the 1st occurence next month nextEvent = new Date(nextEvent.setMonth(nextEvent.getMonth() + 1)) nextEvent = new Date(nextEvent.setDate(eventDates[0])) } nextEvent = new Date(nextEvent.setHours(criteriaHour, criteriaMin, 0)); } // if event is a weekday of every month else if (type == "month") { // convert weekday string to value let wk = weekday[dayOf.toLowerCase()]; // split occurence and convert to value let eventDates = freq.split(/\s*:\s*/); eventDates = eventDates.map(str => { return Number(str); }); // define new date for upcoming "getDays" function const dte = new Date(today); var specifiedDays // set function to list up all of the weekdays in the month function getDays(dt, dy) { const yr = dt.getFullYear(); const mth = dt.getMonth(); const dys = []; for (let i = 1; i <= 31; i++) { const tmpDate = new Date(yr, mth, i, 12, 0, 10); // end at last day of month if (mth !== tmpDate.getMonth()) break; // ignore unspecified weekdays if (tmpDate.getDay() !== dy) continue; dys.push(tmpDate); } return dys; } // set function to filter the weekdays function filterDays(dt, dy) { const weeks = eventDates; const days = getDays(dt, dy); specifiedDays = days.filter((v, i) => weeks.includes(i+1)); } // run funtions to find specified weekdays filterDays(dte, wk); // find the next specifiedDay from today for (let specifiedDay of specifiedDays) { nextEvent = specifiedDay; // stop on first day after today, or today but before event if ((specifiedDay - today > 0) || (specifiedDay - today == 0 && (yet == true))) { break; } } daysTilEvent = nextEvent.getDate() - today.getDate(); var dtNextM = new Date(today); // if loop is complete but daysTilEvent < 0, or it was today but the time is already after the event if ((daysTilEvent < 0) || ((daysTilEvent == 0) && (nextEvent == specifiedDays[specifiedDays.length - 1]) && (yet == false))) { // set "dtNextM" to a date next month // set date to 1, to avoid issues (Jan 31 + 1 month) -> (Feb 31 = Mar3) dtNextM = new Date(dtNextM.setDate(1)); dtNextM = new Date(dtNextM.setMonth(dtNextM.getMonth() + 1)); // run the function again for next month filterDays(dtNextM, wk); nextEvent = new Date(specifiedDays[0]); } nextEvent = new Date(nextEvent.setHours(criteriaHour, criteriaMin, 0)); } // if event is every xx days else if (type == "days") { let startDate = new Date(dayOf); // to avoid issues with daylight saving time startDate = new Date(startDate.setHours(12, 0, 0)) // get how many days have passed from the start date var daysFromStart = Math.round((today - startDate) / 1000 / 60 / 60 /24); // calculate daysTilEvent daysTilEvent = freq - (daysFromStart - (Math.floor(daysFromStart / freq) * freq)); nextEvent = new Date(nextEvent.setDate(nextEvent.getDate() + daysTilEvent)); // if the event is today, but hasn't happened yet set the date to today // the calculation above is not able to find today if ((daysTilEvent == freq) && (yet == true)) { nextEvent = new Date(today); } // Set the "nextEvent" time to the actual event time nextEvent = new Date(nextEvent.setHours(criteriaHour, criteriaMin, 0)); } } /* run the function to calculate "nextEvent" */ getNextEventDay.apply(null, criteria); /* query for list drafts... */ let drafts = Draft.query(criteria[0] + appendTitle, "inbox", [listTag]); // loop over found drafts looking for a matching list let d; for (let draft of drafts) { if (draft.content.startsWith("# " + criteria[0] + appendTitle + "\n## " + nextEvent.toString().slice(0, 15))) { d = draft; } } if ((currentContent.length == 0) && (!d)) { alert("Draft does not exist yet.") } else { if (currentContent.length > 0) { // if we didn't find the list, create it... if (!d) { d = Draft.create(); // setting the new draft's title d.content = "# " + criteria[0] + appendTitle + "\n## " + nextEvent.toString().slice(0, 15) + "\n" + "****" + "\n"; // create reminder let rem = list.createReminder(); // add link to draft in reminders var cb = d.permalink; rem.title = criteria[0] + " : " + nextEvent.toString().slice(0, 10); rem.notes = cb; // set the reminder notification time // change following "10" to change how many minutes before the event you get a reminder let dStr = new Date(nextEvent - (10 * 60 * 1000)); rem.dueDate = Date.parse(dStr); rem.update(); // tag and update content d.addTag(listTag); for (let tag of tags) { d.addTag(tag); } } // append current draft with the current date and time d.content = d.content + "\n> " + lastEdit.toString().slice(0, 10) + " - " + lastEdit.toString().slice(16, 21) + "\\\n" + currentContent + "\n"; d.update(); } // launch the updated log draft // if the current draft is empty but the log draft already exists, it will just lanch the draft var dURL = CallbackURL.create(); dURL.baseURL = d.permalink; dURL.open(); } } else { // user cancelled prompt context.cancel(); }
Options
-
After Success Trash Notification Info Log Level Info