Skip to content

Instantly share code, notes, and snippets.

@d4hines
Created March 8, 2023 00:56
Show Gist options
  • Save d4hines/15f459026754a0e9da07bb01da046192 to your computer and use it in GitHub Desktop.
Save d4hines/15f459026754a0e9da07bb01da046192 to your computer and use it in GitHub Desktop.
Recurring and Deferred Tasks in Roam Research
let tags = [
'weekly',
'biweekly',
'monthly',
'bimonthly',
'biannually',
'spring',
'fall',
'summer',
'winter',
'yearly'
];
let roamFormat = "MMMM Do, YYYY";
const getNextDate = (tag) => {
const today = new Date();
let date;
switch(tag) {
case "weekly":
date = moment().add(1, "week");
break;
case "biweekly":
date = moment().add(2, "week");
break;
case "monthly":
date = moment().add(1, "month");
break;
case "bimonthly":
date = moment().add(2, "month");
break;
case "biannually":
date = moment().add(2, "year");
break;
case "spring":
case "fall":
case "summer":
case "winter":
case "yearly":
date = moment().add(1, "year");
break;
throw new Error("bad tag");
};
return date.format(roamFormat);
}
const makeTodos = async () => {
for (const tag of tags) {
let references = window.roamAlphaAPI.q(`[
:find ?uid ?text ?page ?child_uid ?next_due_date
:in $ ?title
:where
[?page :node/title ?title]
[?e :block/refs ?page]
[?e :block/string ?text]
[?e :block/uid ?uid]
[?e :block/children ?child]
[?next_due_date_id :node/title "next_due_date"]
[?child :block/refs ?next_due_date_id]
[?child :block/uid ?child_uid]
[?child :block/string ?next_due_date]
]`, tag);
for(const [uid, text, page, child_uid, next_due_date] of references) {
console.log(`Found todo: '${text}'`)
const due_date = moment(next_due_date.slice(17, -2), roamFormat);
if(moment().isSameOrAfter(due_date)) {
const todo_text = `{{[[TODO]]}} ((${uid}))`;
console.log("It's time to create new todo");
await window.roamAlphaAPI.createBlock(
{ location: {"parent-uid": moment().format("MM-DD-YYYY"),
"order": 100000}, // use very large number to add at the bottom
block: {string: todo_text }})
console.log("Todo created");
await window.roamAlphaAPI.deleteBlock({block: {uid: child_uid}});
console.log("Old due date deleted");
let new_due_date = getNextDate(tag);
console.log("new due date is ", new_due_date)
await window.roamAlphaAPI.createBlock({
location: {"parent-uid": uid, order: -1},
block: {string: `#next_due_date [[${new_due_date}]]`}
});
console.log("New due date created");
}
}
}
};
async function promoteDeferredTodos() {
let results = window.roamAlphaAPI.q(`[
:find ?uid ?text ?other_page_title
:in $
:where
[?page :node/title "Deferred TODO"]
[?e :block/refs ?page]
[?e :block/refs ?other_page]
[?e :block/string ?text]
[?e :block/uid ?uid]
[?other_page :node/title ?other_page_title]
[(!= ?page ?other_page)]
]`);
console.log(results);
for (const [uid, text, dateStr] of results) {
let date = moment(dateStr, roamFormat);
const diff = moment().diff(date, 'hours');
if(diff > 0) {
const updatedText = text.replace("[[Deferred TODO]]", "{{[[TODO]]}}");
console.log(`promoting todo '${updatedText}'`);
await window.roamAlphaAPI.updateBlock({
block: { uid, string: updatedText },
});
}
}
}
async function waitUntilReady(n) {
const isSynced = document.getElementsByClassName("rm-sync--synced").length;
if(typeof window.moment == "function" && isSynced) {
await makeTodos();
await promoteDeferredTodos();
} else if (n > 10) {
alert("Recurring Task Management: document never became ready");
} else {
setTimeout(() => waitUntilReady(n + 1), 1000)
}
}
waitUntilReady(0);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment