From aacb798f07598766c1fe89955538cd683c753145 Mon Sep 17 00:00:00 2001 From: Dan Connolly Date: Sat, 17 May 2025 19:24:05 -0500 Subject: [PATCH 01/11] feat: google sheet made from calendars (WIP) --- packages/cal-to-sheet/appsscript.json | 7 ++ packages/cal-to-sheet/cal-to-sheet.js | 108 ++++++++++++++++++++++++++ 2 files changed, 115 insertions(+) create mode 100644 packages/cal-to-sheet/appsscript.json create mode 100644 packages/cal-to-sheet/cal-to-sheet.js diff --git a/packages/cal-to-sheet/appsscript.json b/packages/cal-to-sheet/appsscript.json new file mode 100644 index 0000000..50abad2 --- /dev/null +++ b/packages/cal-to-sheet/appsscript.json @@ -0,0 +1,7 @@ +{ + "timeZone": "America/Chicago", + "dependencies": { + }, + "exceptionLogging": "STACKDRIVER", + "runtimeVersion": "V8" +} \ No newline at end of file diff --git a/packages/cal-to-sheet/cal-to-sheet.js b/packages/cal-to-sheet/cal-to-sheet.js new file mode 100644 index 0000000..ed1027e --- /dev/null +++ b/packages/cal-to-sheet/cal-to-sheet.js @@ -0,0 +1,108 @@ +/** + * Adds a custom menu to the spreadsheet. + */ +function onOpen() { + SpreadsheetApp.getUi() + .createMenu('Calendar Sync') + .addItem('Update from Calendar', 'updateSheetFromCalendar') + .addToUi(); +} + +/** + * Updates the spreadsheet with events from the specified Google Calendar. + */ +function updateSheetFromCalendar() { + // --- Configuration --- + const calendarId = 'your_calendar_id@group.calendar.google.com'; // Replace with your calendar ID + const sheetName = 'Calendar Events'; // Replace with the name of your sheet + const firstRow = 1; // The first row to write data to (header row assumed above) + const clearExistingData = true; // Set to true to clear existing data before updating + + // Get the spreadsheet and sheet + const ss = SpreadsheetApp.getActiveSpreadsheet(); + const sheet = ss.getSheetByName(sheetName); + + if (!sheet) { + SpreadsheetApp.getUi().alert( + 'Error', + `Sheet "${sheetName}" not found.`, + SpreadsheetApp.Ui.ButtonSet.OK, + ); + return; + } + + // Get the calendar + const calendar = CalendarApp.getCalendarById(calendarId); + if (!calendar) { + SpreadsheetApp.getUi().alert( + 'Error', + `Calendar with ID "${calendarId}" not found.`, + SpreadsheetApp.Ui.ButtonSet.OK, + ); + return; + } + + // Get today's date (for the start of the query) + const today = new Date(); + today.setHours(0, 0, 0, 0); // Start of the day + + // Get events from the calendar (you can adjust the date range as needed) + const events = calendar.getEvents( + today, + new Date(today.getTime() + 365 * 24 * 60 * 60 * 1000), + ); // Events for the next year + + // Prepare data for the sheet + const eventData = events.map(event => [ + event.getTitle(), + event.getStartTime(), + event.getEndTime(), + event.getLocation(), + event.getDescription(), + event.getHtmlLink(), // Link to the event in Google Calendar + ]); + + // Clear existing data if specified + if (clearExistingData && eventData.length > 0) { + sheet + .getRange(firstRow, 1, sheet.getLastRow(), sheet.getLastColumn()) + .clearContent(); + } + + // Write the event data to the sheet + if (eventData.length > 0) { + sheet + .getRange(firstRow, 1, eventData.length, eventData[0].length) + .setValues(eventData); + + // Add headers if the sheet was empty or cleared + if (clearExistingData || sheet.getLastRow() === 0) { + sheet.insertRowBefore(firstRow); + sheet + .getRange(firstRow, 1, 1, 6) + .setValues([ + [ + 'Title', + 'Start Time', + 'End Time', + 'Location', + 'Description', + 'Calendar Link', + ], + ]); + sheet.getRange(firstRow, 1, 1, 6).setFontWeight('bold'); + } + } else { + SpreadsheetApp.getUi().alert( + 'Info', + 'No events found in the specified calendar for the given date range.', + SpreadsheetApp.Ui.ButtonSet.OK, + ); + } + + SpreadsheetApp.getUi().alert( + 'Success', + 'Calendar updated successfully!', + SpreadsheetApp.Ui.ButtonSet.OK, + ); +} From 4cedb1b18d5b2283893038668093609b7a3dcf2e Mon Sep 17 00:00:00 2001 From: Dan Connolly Date: Sat, 17 May 2025 20:06:05 -0500 Subject: [PATCH 02/11] build(cal-to-sheet): save pull/push scripts --- packages/cal-to-sheet/package.json | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 packages/cal-to-sheet/package.json diff --git a/packages/cal-to-sheet/package.json b/packages/cal-to-sheet/package.json new file mode 100644 index 0000000..fd66de6 --- /dev/null +++ b/packages/cal-to-sheet/package.json @@ -0,0 +1,6 @@ +{ + "scripts": { + "pull": "clasp pull", + "push": "clasp push" + } +} From 52fea7dc18b1aed0c4a612df729d0470ecee5a2a Mon Sep 17 00:00:00 2001 From: Dan Connolly Date: Sat, 17 May 2025 20:07:20 -0500 Subject: [PATCH 03/11] refactor(cal-to-sheet): onOpen was moved to menu.js --- packages/cal-to-sheet/cal-to-sheet.js | 8 -------- 1 file changed, 8 deletions(-) diff --git a/packages/cal-to-sheet/cal-to-sheet.js b/packages/cal-to-sheet/cal-to-sheet.js index ed1027e..af49415 100644 --- a/packages/cal-to-sheet/cal-to-sheet.js +++ b/packages/cal-to-sheet/cal-to-sheet.js @@ -1,11 +1,3 @@ -/** - * Adds a custom menu to the spreadsheet. - */ -function onOpen() { - SpreadsheetApp.getUi() - .createMenu('Calendar Sync') - .addItem('Update from Calendar', 'updateSheetFromCalendar') - .addToUi(); } /** From 329188c5487d888ef98c183095911f60174ca52f Mon Sep 17 00:00:00 2001 From: Dan Connolly Date: Sat, 17 May 2025 20:07:42 -0500 Subject: [PATCH 04/11] chore(cal-to-sheet): NonNullish, die utilities --- packages/cal-to-sheet/cal-to-sheet.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/cal-to-sheet/cal-to-sheet.js b/packages/cal-to-sheet/cal-to-sheet.js index af49415..08158e0 100644 --- a/packages/cal-to-sheet/cal-to-sheet.js +++ b/packages/cal-to-sheet/cal-to-sheet.js @@ -1,3 +1,8 @@ +const die = msg => { + throw Error(msg); +}; +const NonNullish = (x, msg) => x || die(msg); + } /** From 188e47e2851b7b0358ffd7c78c730c566caa7835 Mon Sep 17 00:00:00 2001 From: Dan Connolly Date: Sat, 17 May 2025 20:08:47 -0500 Subject: [PATCH 05/11] chore: fix event.getHtmlLink() hallucination --- packages/cal-to-sheet/cal-to-sheet.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/cal-to-sheet/cal-to-sheet.js b/packages/cal-to-sheet/cal-to-sheet.js index 08158e0..b42733c 100644 --- a/packages/cal-to-sheet/cal-to-sheet.js +++ b/packages/cal-to-sheet/cal-to-sheet.js @@ -3,6 +3,8 @@ const die = msg => { }; const NonNullish = (x, msg) => x || die(msg); +function getCalendarEventUrl(calendarId, eventId) { + return `https://calendar.google.com/calendar/event?cid=${calendarId}&eid=${eventId}`; } /** @@ -56,7 +58,7 @@ function updateSheetFromCalendar() { event.getEndTime(), event.getLocation(), event.getDescription(), - event.getHtmlLink(), // Link to the event in Google Calendar + getCalendarEventUrl(calendarId, event.getId()), ]); // Clear existing data if specified From c6b924d6bd6cc02841f56878c9fed64c7e62d715 Mon Sep 17 00:00:00 2001 From: Dan Connolly Date: Sat, 17 May 2025 20:09:24 -0500 Subject: [PATCH 06/11] chore: punt success notice - SpreadsheetApp.Ui.ButtonSet.OK is bogus --- packages/cal-to-sheet/cal-to-sheet.js | 6 ------ 1 file changed, 6 deletions(-) diff --git a/packages/cal-to-sheet/cal-to-sheet.js b/packages/cal-to-sheet/cal-to-sheet.js index b42733c..fc07552 100644 --- a/packages/cal-to-sheet/cal-to-sheet.js +++ b/packages/cal-to-sheet/cal-to-sheet.js @@ -98,10 +98,4 @@ function updateSheetFromCalendar() { SpreadsheetApp.Ui.ButtonSet.OK, ); } - - SpreadsheetApp.getUi().alert( - 'Success', - 'Calendar updated successfully!', - SpreadsheetApp.Ui.ButtonSet.OK, - ); } From d6492d0f8cbac067faf758d60d64bdfd106896f0 Mon Sep 17 00:00:00 2001 From: Dan Connolly Date: Sat, 17 May 2025 20:10:05 -0500 Subject: [PATCH 07/11] chore: clear condition is rows in sheet, not rows in data --- packages/cal-to-sheet/cal-to-sheet.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cal-to-sheet/cal-to-sheet.js b/packages/cal-to-sheet/cal-to-sheet.js index fc07552..5857b1b 100644 --- a/packages/cal-to-sheet/cal-to-sheet.js +++ b/packages/cal-to-sheet/cal-to-sheet.js @@ -62,7 +62,7 @@ function updateSheetFromCalendar() { ]); // Clear existing data if specified - if (clearExistingData && eventData.length > 0) { + if (clearExistingData && sheet.getLastRow() > 0) { sheet .getRange(firstRow, 1, sheet.getLastRow(), sheet.getLastColumn()) .clearContent(); From eac816b55779487520cfcd1158d0e8289d5a371f Mon Sep 17 00:00:00 2001 From: Dan Connolly Date: Sat, 17 May 2025 20:11:39 -0500 Subject: [PATCH 08/11] chore: use active sheet; hoist io so caller can inject --- packages/cal-to-sheet/cal-to-sheet.js | 47 ++++++++++----------------- 1 file changed, 17 insertions(+), 30 deletions(-) diff --git a/packages/cal-to-sheet/cal-to-sheet.js b/packages/cal-to-sheet/cal-to-sheet.js index 5857b1b..114d3c3 100644 --- a/packages/cal-to-sheet/cal-to-sheet.js +++ b/packages/cal-to-sheet/cal-to-sheet.js @@ -10,39 +10,26 @@ function getCalendarEventUrl(calendarId, eventId) { /** * Updates the spreadsheet with events from the specified Google Calendar. */ -function updateSheetFromCalendar() { - // --- Configuration --- - const calendarId = 'your_calendar_id@group.calendar.google.com'; // Replace with your calendar ID - const sheetName = 'Calendar Events'; // Replace with the name of your sheet - const firstRow = 1; // The first row to write data to (header row assumed above) - const clearExistingData = true; // Set to true to clear existing data before updating +function updateSheetFromCalendar(_nonce, io = {}) { + const { + // Get the spreadsheet and sheet + ss = SpreadsheetApp.getActiveSpreadsheet(), + sheet = ss.getActiveSheet() || ss.getSheets()[0], + sheetName = sheet.getName(), + // Get the calendar + calendar = NonNullish( + CalendarApp.getCalendarsByName(sheetName), + `cannot find calendar ${sheetName}`, + )[0], + // Get today's date (for the start of the query) + today = new Date(), + } = io; - // Get the spreadsheet and sheet - const ss = SpreadsheetApp.getActiveSpreadsheet(); - const sheet = ss.getSheetByName(sheetName); - - if (!sheet) { - SpreadsheetApp.getUi().alert( - 'Error', - `Sheet "${sheetName}" not found.`, - SpreadsheetApp.Ui.ButtonSet.OK, - ); - return; - } + const calendarId = calendar.getId(); - // Get the calendar - const calendar = CalendarApp.getCalendarById(calendarId); - if (!calendar) { - SpreadsheetApp.getUi().alert( - 'Error', - `Calendar with ID "${calendarId}" not found.`, - SpreadsheetApp.Ui.ButtonSet.OK, - ); - return; - } + const firstRow = 1; // The first row to write data to (header row assumed above) + const clearExistingData = true; // Set to true to clear existing data before updating - // Get today's date (for the start of the query) - const today = new Date(); today.setHours(0, 0, 0, 0); // Start of the day // Get events from the calendar (you can adjust the date range as needed) From 7335fcfac39a1c31a3400c91c09946ffbe499edc Mon Sep 17 00:00:00 2001 From: Dan Connolly Date: Sat, 17 May 2025 20:12:18 -0500 Subject: [PATCH 09/11] chore: hoist getUi I/O --- packages/cal-to-sheet/cal-to-sheet.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/cal-to-sheet/cal-to-sheet.js b/packages/cal-to-sheet/cal-to-sheet.js index 114d3c3..6f53166 100644 --- a/packages/cal-to-sheet/cal-to-sheet.js +++ b/packages/cal-to-sheet/cal-to-sheet.js @@ -23,6 +23,7 @@ function updateSheetFromCalendar(_nonce, io = {}) { )[0], // Get today's date (for the start of the query) today = new Date(), + ui = SpreadsheetApp.getUi(), } = io; const calendarId = calendar.getId(); @@ -79,7 +80,7 @@ function updateSheetFromCalendar(_nonce, io = {}) { sheet.getRange(firstRow, 1, 1, 6).setFontWeight('bold'); } } else { - SpreadsheetApp.getUi().alert( + ui.alert( 'Info', 'No events found in the specified calendar for the given date range.', SpreadsheetApp.Ui.ButtonSet.OK, From 7800dc4f82d44bbc0d6a4f91e7dc45fe7cc6665b Mon Sep 17 00:00:00 2001 From: Dan Connolly Date: Sat, 24 May 2025 16:02:05 -0500 Subject: [PATCH 10/11] build(cal-to-sheet): add to workspace --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 286cddb..85ef72a 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,7 @@ "workspaces": [ "packages/br-cal", "packages/br-script", + "packages/cal-to-sheet", "packages/discover-dl", "packages/lm-sync" ], From b5662f1d89e4f8de112fed264614c6c50c5bc650 Mon Sep 17 00:00:00 2001 From: Dan Connolly Date: Sat, 24 May 2025 17:19:36 -0500 Subject: [PATCH 11/11] fixup! feat: google sheet made from calendars (WIP) --- packages/cal-to-sheet/menu.js | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 packages/cal-to-sheet/menu.js diff --git a/packages/cal-to-sheet/menu.js b/packages/cal-to-sheet/menu.js new file mode 100644 index 0000000..6b6f63d --- /dev/null +++ b/packages/cal-to-sheet/menu.js @@ -0,0 +1,9 @@ +/** + * Adds a custom menu to the spreadsheet. + */ +function onOpen() { + SpreadsheetApp.getUi() + .createMenu('Calendar Sync') + .addItem('Update from Calendar', 'updateSheetFromCalendar') + .addToUi(); +}