auths
objectEnter your notion API Token here. Do not share this with anyone!
Enter the target Notion database ID here.
The name for a task's "Completed" property in Notion.
Type: Checkbox
The name for a task's "Due Date" property in Notion.
Type: Date
The name for a task's "Interval" property in Notion.
Type: Select
return
or this.key = 'value'
, pass input data to your code viaparams
, and maintain state across executions with$checkpoint.async
(event, steps, params) => {
}
/*******************************************************************************/
/*** DO NOT EDIT ANY CODE. ENTER YOUR CONFIGURATION VALUES IN THE FORM ABOVE ***/
/*******************************************************************************/
// Collect and assign user input
this.API_TOKEN = params.notionApiToken
this.DB_ID = params.taskDatabaseId
this.PROPS = {
complete: params.completedPropertyName, // Type: Checkbox
dueDate: params.dueDatePropertyName, // Type: Date
interval: params.intervalPropertyName // Type: Select
}
this.INTERVALS = params.intervals && Object.keys(params.intervals).length > 0 ? params.intervals : {
"Daily" : [1, 'days'],
"Weekly" : [1, 'weeks'],
"Biweekly" : [2, 'weeks'],
"Monthly" : [1, 'months'],
"Quarterly" : [1, 'quarters'],
"Semi-Annually" : [6, 'months'],
"Annually" : [1, 'years']
}
// Validation
console.log('Validating user input...')
if (!/^secret_[\d|a-z|A-Z]+$/.test(this.API_TOKEN)) { throw new Error('Invalid Notion API token format')}
if (!/^[\d|a-f]{8}-?([\d|a-f]{4}-?){3}[\d|a-f]{12}$/.test(this.DB_ID)) { throw new Error('Invalid database ID format')}
const validIntervalUnits = ['days', 'weeks', 'months', 'quarters', 'years']
for (const interval in this.INTERVALS) {
if (!(Array.isArray(this.INTERVALS[interval]) && this.INTERVALS[interval].length === 2)) { throw new Error(`Invalid recurring interval configuration for option: ${interval}.`)}
if (!Number.isInteger(this.INTERVALS[interval][0])) { throw new Error(`Recurring interval must be an integer for option: ${interval}.`)}
if (!(typeof this.INTERVALS[interval][1] === 'string' || this.INTERVALS[interval][1] instanceof String)) { throw new Error(`Recurring unit must be a string for option: ${interval}.`)}
if (!validIntervalUnits.includes(this.INTERVALS[interval][1])) { throw new Error(`Recurring unit for option ${interval} must be one of: ${validIntervalUnits.join(', ')}.`)}
}
console.log('Validation complete!')
auths
objectreturn
or this.key = 'value'
, pass input data to your code viaparams
, and maintain state across executions with$checkpoint.async
(event, steps) => {
}
const axios = require("axios")
// Fetch completed recurring tasks
console.log("Fetch completed recurring tasks...")
const resp = await axios({
method: "POST",
url: `https://api.notion.com/v1/databases/${steps.config.DB_ID}/query`,
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${steps.config.API_TOKEN}`, // API KEY
"Notion-Version": "2021-05-13"
},
data : {
filter : {
and : [
{
property : steps.config.PROPS.complete,
checkbox : {
equals : true
}
},
{
property : steps.config.PROPS.interval,
select : {
is_not_empty : true
}
},
{
property : steps.config.PROPS.dueDate,
date : {
is_not_empty : true
}
}
]
}
}
}).catch(err => {
console.log(err.response.data)
throw err
})
console.log("Fetch complete!")
this.tasks = resp.data.results
auths
objectreturn
or this.key = 'value'
, pass input data to your code viaparams
, and maintain state across executions with$checkpoint.async
(event, steps) => {
}
const axios = require("axios")
const moment = require("moment")
const DATE_TIME_REGEX = /^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(.[0-9]{3})?(-[0-9]{2}:[0-9]{2})?$/
this.updatedTasks = []
// Update tasks
console.log("Update recurring tasks with new dates...")
for (const task of steps.fetchCompletedRecurringTasks.tasks) {
let patch = { properties : {} }
// Uncheck the Complete checkbox
patch.properties[steps.config.PROPS.complete] = { checkbox: false }
// Modify the due date
patch.properties[steps.config.PROPS.dueDate] = { date : {} }
// Modify the start date
let startDate = task.properties[steps.config.PROPS.dueDate].date.start ? moment.parseZone(task.properties[steps.config.PROPS.dueDate].date.start) : null
if (!(task.properties[steps.config.PROPS.interval].select.name in steps.config.INTERVALS)) continue
startDate.add(...steps.config.INTERVALS[task.properties[steps.config.PROPS.interval].select.name])
let startDateFormat = DATE_TIME_REGEX.test(task.properties[steps.config.PROPS.dueDate].date.start) ? "YYYY-MM-DDTHH:mm:ss.SSSZ" : "YYYY-MM-DD" // Date only or Date & Time
patch.properties[steps.config.PROPS.dueDate].date.start = startDate.format(startDateFormat)
// Modify the end date, if it exists
if (task.properties[steps.config.PROPS.dueDate].date.end) {
let endDate = moment.parseZone(task.properties[steps.config.PROPS.dueDate].date.end)
endDate.add(...steps.config.INTERVALS[task.properties[steps.config.PROPS.interval].select.name])
let endDateFormat = DATE_TIME_REGEX.test(task.properties[steps.config.PROPS.dueDate].date.end) ? "YYYY-MM-DDTHH:mm:ss.SSSZ" : "YYYY-MM-DD" // Date only or Date & Time
patch.properties[steps.config.PROPS.dueDate].date.end = endDate.format(endDateFormat)
}
const updatedTaskResp = await axios({
method: "PATCH",
url: `https://api.notion.com/v1/pages/${task.id}`,
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${steps.config.API_TOKEN}`, // API KEY
"Notion-Version": "2021-05-13"
},
data : JSON.stringify(patch)
}).catch(err => {
console.log(err.response.data)
throw err
})
this.updatedTasks.push(updatedTaskResp.data)
}
console.log("Update complete!")
console.log('Workflow finished ✅')