diff --git a/.github/ISSUE_TEMPLATE/Project_Management_Issue_Template.yml b/.github/ISSUE_TEMPLATE/Project_Management_Issue_Template.yml new file mode 100644 index 0000000..5afe5ae --- /dev/null +++ b/.github/ISSUE_TEMPLATE/Project_Management_Issue_Template.yml @@ -0,0 +1,59 @@ +name: New Issue Form +description: Create an Issue +projects: NASA-IMPACT/# ##replace with desired project that you would like the issues to be automatically added to. Format as project/board number +body: + - type: markdown + attributes: + value: | ##Replace with your project name + This is the Issue template! The values you add will be converted to a properly formatted Issue for the Project. + - type: textarea + id: description + attributes: + label: Description + description: Add two to three sentences that explain the context of this issue and what it will achieve. + placeholder: Questions to consider when completing this section... + - What is the motivation for this issue? + - Is there any needed background knowledge that would be helpful to the assignee? + - Is there a specific requestor for this issue? + - Are there time constraints? + - What are the possible steps to completion? + - Who are the anticipated assignees? + - What problem will this issue solve? + validations: + required: true + - type: textarea + id: Examples + attributes: + label: Examples or References + description: if applicable, include examples of work that the issue will result in or references to use in development. + placeholder: This type of document is what I am looking for... + Use these files when developing your solution... + validations: + required: false + - type: textarea + id: deliverable + attributes: + label: Deliverable + description: Acceptance Criteria in the form of a tasklist. Once the issue has been created, individual tasks can be converted to issues if needed. + value: "- [ ] " + validations: + required: true + - type: textarea + id: implementation-considerations + attributes: + label: Implementation Considerations + description: | + Points that need to be considered when developing this feature/writing this doc + placeholder: Why have you selected multiple quarters? What other organizations or resources does this issue depend on to be completed? + validations: + required: false + - type: textarea + id: dependencies + attributes: + label: Related Issues + description: | + Add cards on which this issue depends + Github automatically provides a list of possible issues if you start by typing a `#` + placeholder: depends on + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/issue.yml b/.github/ISSUE_TEMPLATE/issue.yml deleted file mode 100644 index c28c333..0000000 --- a/.github/ISSUE_TEMPLATE/issue.yml +++ /dev/null @@ -1,43 +0,0 @@ -name: Issue -description: Create an Issue -title: "ADD THE ISSUE TITLE HERE" -body: - - type: markdown - attributes: - value: | - This is the Issue template! The values you add will be converted to a properly formatted Issue. - - type: textarea - id: description - attributes: - label: Description - description: Add two to three sentences that explain the context of this issue and what it will achieve. - placeholder: your text goes here - validations: - required: true - - type: textarea - id: implementation-considerations - attributes: - label: Implementation Considerations - description: | - Points that need to be considered when developing this feature/writing this doc - value: "- type your first consideration here" - validations: - required: true - - type: textarea - id: deliverable - attributes: - label: Deliverable - description: What will be shown to to team to demonstrate acceptance criteria are complete - placeholder: your text goes here - validations: - required: true - - type: textarea - id: dependencies - attributes: - label: Dependencies - description: | - Add cards on which this issue depends - Github automatically provides a list of possible issues if you start by typing a `#` - value: depends on - validations: - required: false diff --git a/PIEtest.js b/PIEtest.js new file mode 100644 index 0000000..413a756 --- /dev/null +++ b/PIEtest.js @@ -0,0 +1,256 @@ +// function: to poulate PI increments and PI events for the 23.4, 24.1, and 24.2 project increments in a public Google Calendar. On the Monday of a PI Planning Week, the next available PI (quarter) generates and populates. + +// feature suggestion: slackbot for posting links + +// access target calendar; Test calendar ID: c_8798ebb71e4f29ffc300845dabe847152b8c92e2afd062e0e31242d7fce780cd@group.calendar.google.com + +// create events for each sprint (Sprint Reviews) and Next PI Planning week (Welcome, Management Review, and Final Presentation) + +/////////////////////////////////////// + +// Global variables +// var calendarId = "c_8798ebb71e4f29ffc300845dabe847152b8c92e2afd062e0e31242d7fce780cd@group.calendar.google.com"; // Test calendar ID; update to preferred calendar ID before deployment + +// immediately invoked function expression - adjustedPIcalculator to calculate current PI ****DO NOT TOUCH**** +var adjustedPIcalculator = (function(){ + // Adjustment Weeks to account for holidays, vacations, etc. Add the first Sunday of the Adjustment Week at the bottom of the list in 'YYYY-MM-DD' format. + var ADJUSTMENT_WEEKS = []; // Add adjustment week dates here. + ADJUSTMENT_WEEKS.push(new Date('2023-07-02')); // Innovation Week #2 + ADJUSTMENT_WEEKS.push(new Date('2023-07-16')); // IGARSS 2023 + // Add dates as 'yyyy-mm-dd' + + /////////////////////////////////////// + + // Global variables + var BASE_DATE = new Date('2023-04-16'); // The date for '23.3.1 Week 1', the beginning sprint of record for the purposes of this script. + var BASE_FY = 23; + var BASE_PI = 3; + var BASE_SPRINT = 1; + var BASE_WEEK = 1; + + // Helper function to convert a date to the number of milliseconds since Jan 1, 1970 + function toMillis(date) { + return Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()); + } + + // Helper function to calculate Adjustment Weeks + function adjustmentWeeks(date) { + var adjustmentWeeks = 0; + var currentTime = toMillis(date); + for(var i = 0; i < ADJUSTMENT_WEEKS.length; i++) { + if(toMillis(ADJUSTMENT_WEEKS[i]) <= currentTime) { + adjustmentWeeks++; + } + } + return adjustmentWeeks; + } + + // Helper function to calculate the current fiscal year + function getFiscalYear(date) { + var year = date.getFullYear(); + var month = date.getMonth(); + + // The fiscal year starts in October (month index 9) + return month >= 9 ? year + 1 : year; + } + + // Helper function to get current PI (Q) (1-4) + function getQuarter(date) { + // In JavaScript, months are 0-indexed, so October is 9 and September is 8 + var month = date.getMonth(); + + // The first quarter of the fiscal year starts in October + if (month >= 9) { + return ((month - 9) / 3 | 0) + 1; + } else { + return ((month + 3) / 3 | 0) + 1; + } + } + + // Helper function to get current Sprint (1-6) + function getSprint(date) { + var fiscalYearStart = new Date(getFiscalYear(date), 9, 1); + var diffWeeks = Math.ceil(((date - fiscalYearStart + 1) / (24 * 60 * 60 * 1000)) / 7); + + // Subtract adjustment weeks + diffWeeks -= adjustmentWeeks(date); + + // Subtract the base week of the quarter + var baseWeek = (getQuarter(date) - 1) * 13; + diffWeeks -= baseWeek; + + // Calculate the sprint based on the week of the fiscal year, after accounting for adjustment weeks + var sprint = Math.ceil(diffWeeks / 2); + + return sprint; + } + + // Helper function to get current week (1-2) + function getWeek(date) { + return Math.ceil(((date - new Date(getFiscalYear(date), 9, 1) + 1) / (24 * 60 * 60 * 1000)) / 7) % 2 === 0 ? 2 : 1; + } + + // Helper function to get week of the year + function getWeekOfYear(date) { + var start = new Date(date.getFullYear(), 0, 1); + var diff = date - start + (start.getTimezoneOffset() - date.getTimezoneOffset()) * 60 * 1000; + var oneDay = 1000 * 60 * 60 * 24; + var day = Math.floor(diff / oneDay); + return Math.ceil(day / 7); + } + + // Helper function to rename FY.Q.6.1 to "Innovation Week" + function renameInnovation(pi) { + return pi.endsWith(".6.1") ? "Innovation Week" : pi; + } + + // Helper function to rename FY.Q.6.2 to "Next PI Planning" + function renameNextPiPlanning(pi) { + return pi.endsWith(".6.2") ? "Next PI Planning" : pi; + } + + // Helper function to calculate the Adjusted PI + function getPI(inputDate) { + if (!(inputDate instanceof Date)) { + // Attempt to parse the inputDate as a string and convert it to a Date object + inputDate = new Date(inputDate); + + // Check if the parsed inputDate is valid + if (isNaN(inputDate.getTime())) { + throw new Error("Invalid date provided to getPI function."); + } + } + + var daysPassed = (toMillis(inputDate) - toMillis(BASE_DATE)) / (24 * 60 * 60 * 1000) - adjustmentWeeks(inputDate) * 7; + var weeksPassed = Math.floor(daysPassed / 7); + + // calculate the total two week periods passed since the BASE_DATE + var totalTwoWeekPeriods = Math.floor(weeksPassed / 2); + + var week = weeksPassed % 2 + 1; + var sprint = totalTwoWeekPeriods % 6 + 1; + var pi = Math.floor(totalTwoWeekPeriods / 6) % 4 + BASE_PI; + var fy = BASE_FY + Math.floor(totalTwoWeekPeriods / (6 * 4)); + var piStr = "FY" + fy + "." + pi + "." + sprint + " Week " + week; // Format result as FY.Q.S Week W + piStr = renameInnovation(piStr); + piStr = renameNextPiPlanning(piStr); + + return piStr; + } + + // Primary function to replace placeholder text {{Adjusted PI}} with the calculated Adjusted PI + function replacePlaceholderWithPI(document, adjustedPI) { + var body = document.getBody(); + var text = body.editAsText(); + text.replaceText("{{Adjusted PI}}", adjustedPI); + } + + // Make the getPI function accessible outside the IIFE + return { + getPI: getPI, + replacePlaceholderWithPI: replacePlaceholderWithPI + }; +})(); + +// Helper function to create Sprint Review events +function createSprintReviewEvents(piStartDate, calendarId, piLabel) { + var sprintDuration = 14; // 14 days + var numSprints = 5; + var reviewHoursStart = 10; // 10am + var reviewHoursEnd = 12; // 12pm + + for (var i = 1; i <= numSprints; i++) { + var sprintStartDate = new Date(piStartDate.getTime() + (i - 1) * sprintDuration * 24 * 60 * 60 * 1000); + var sprintEndDate = new Date(sprintStartDate.getTime() + (sprintDuration - 1) * 24 * 60 * 60 * 1000); + + // Adjusting the endDate to fall on a Friday + var reviewDate = new Date(sprintEndDate); + reviewDate.setDate(sprintEndDate.getDate() - (sprintEndDate.getDay() + 2) % 7); + + // Create start and end date objects for the Sprint Review event + var reviewStartDateTime = new Date(reviewDate.getFullYear(), reviewDate.getMonth(), reviewDate.getDate(), reviewHoursStart); + var reviewEndDateTime = new Date(reviewDate.getFullYear(), reviewDate.getMonth(), reviewDate.getDate(), reviewHoursEnd); + + var sprintLabel = "PI " + piLabel + " Sprint " + i; // Updated event label + + // Update the event title to include only "PI FY.Q Sprint S" + createEvent(sprintLabel, reviewStartDateTime, reviewEndDateTime, calendarId); + } +} + +// Helper function to create PI Planning events +function createPIPlanningEvents(piStartDate, calendarId, piLabel) { + var flexWeekDuration = 7; // 7 days + + for (var i = 1; i <= 2; i++) { // Assuming 2 PI Planning weeks per PI + var piPlanningStartDate = new Date(piStartDate.getTime() + (i * 6 + 5) * 14 * 24 * 60 * 60 * 1000); + var piPlanningEndDate = new Date(piPlanningStartDate.getTime() + (flexWeekDuration - 1) * 24 * 60 * 60 * 1000); + + var piPlanningLabel = "PI " + piLabel + " PI Planning Week " + i; + + // Event details + var eventDetails = [ + { title: "IMPACT PI Planning Welcome", dayOfWeek: 2, startTime: 10, endTime: 11.5 }, + { title: "IMPACT PI Planning Management Review", dayOfWeek: 4, startTime: 9.5, endTime: 12 }, + { title: "IMPACT PI Planning Final Presentation", dayOfWeek: 5, startTime: 10, endTime: 11.5 } + ]; + + // Create the events for the PI Planning week + eventDetails.forEach(function (eventDetail) { + var eventDate = new Date(piPlanningStartDate.getFullYear(), piPlanningStartDate.getMonth(), piPlanningStartDate.getDate() + eventDetail.dayOfWeek); + var eventStartDateTime = new Date(eventDate.getFullYear(), eventDate.getMonth(), eventDate.getDate(), eventDetail.startTime); + var eventEndDateTime = new Date(eventDate.getFullYear(), eventDate.getMonth(), eventDate.getDate(), eventDetail.endTime); + + var eventTitle = "PI " + piLabel + " " + eventDetail.title; + + createEvent(eventTitle, eventStartDateTime, eventEndDateTime, calendarId); + }); + + // Create the PI Planning week itself + createEvent(piPlanningLabel, piPlanningStartDate, piPlanningEndDate, calendarId); + } +} + +// Helper function to create an event in Google Calendar +function createEvent(eventTitle, eventStartDateTime, eventEndDateTime, calendarId) { + // Create an object for the new event + var event = { + 'summary': eventTitle, + 'start': { + 'dateTime': eventStartDateTime.toISOString(), + 'timeZone': 'America/New_York' // Adjust timezone accordingly + }, + 'end': { + 'dateTime': eventEndDateTime.toISOString(), + 'timeZone': 'America/New_York' // Adjust timezone accordingly + } + }; + + // Add the event to the calendar + var calendar = CalendarApp.getCalendarById(calendarId); + var createdEvent = calendar.createEvent(eventTitle, eventStartDateTime, eventEndDateTime, { + 'description': eventTitle, + 'location': 'Location', // Set your desired location + }); + Logger.log('Created event with ID: ' + createdEvent.getId()); +} + +// Primary function to create events for each PI increment +function populatePIEvents() { + var calendarId = "c_8798ebb71e4f29ffc300845dabe847152b8c92e2afd062e0e31242d7fce780cd@group.calendar.google.com"; // Test calendar ID; update to preferred calendar ID before deployment + + // Get the current Adjusted PI using the adjustedPIcalculator library + var currentPI = adjustedPIcalculator.getPI(new Date()); + + // Calculate the next PI + var nextAdjustedPI = getNextAdjustedPI(currentPI); + + // Get the start date for the next PI + var nextStartDate = getStartDateForAdjustedPI(nextAdjustedPI); + + // Create sprints, flex weeks, Sprint Review events, and PI Planning events for the next PI + createSprints(nextStartDate, calendarId, nextAdjustedPI); + createFlexWeeks(nextStartDate, calendarId, nextAdjustedPI); + createSprintReviewEvents(nextStartDate, calendarId, nextAdjustedPI); + createPIPlanningEvents(nextStartDate, calendarId, nextAdjustedPI); +} \ No newline at end of file diff --git a/actionTrackerSheet.js b/actionTrackerSheet.js index 242b809..f3f547b 100644 --- a/actionTrackerSheet.js +++ b/actionTrackerSheet.js @@ -8,6 +8,7 @@ Preserve links in task items from the source documents. Will first require the s To note: This script is developed as a Google Apps Script container script: i.e. a script that is bound to a specific file, such as a Google Sheets, Google Docs, or Google Forms file. This container script acts as the file's custom script, allowing users to extend the functionality of the file by adding custom functions, triggers, and menu items to enhance its behavior and automation. +<<<<<<< HEAD Instructions for Using this Script in your container file: 1. Open a new or existing Google Sheets file where you want to use the script. 2. Click on "Extensions" in the top menu and select "Apps Script" from the dropdown menu. This will open the Google Apps Script editor in a new tab. @@ -28,6 +29,28 @@ Note: Make sure to properly set up the correct folder structure in Google Drive function getSpreadsheetInfoTest() { // Get the active spreadsheet var spreadsheet = SpreadsheetApp.getActiveSpreadsheet(); +======= +// Instructions for Using this Script in your container file: +// 1. Open a new or existing Google Sheets file where you want to use the script. +// 2. Click on "Extensions" in the top menu and select "Apps Script" from the dropdown menu. This will open the Google Apps Script editor in a new tab. +// 3. Copy and paste the provided script into the Apps Script editor, replacing the existing code (if any). +// 4. In the MOPopulate function, replace the placeholder values for folderId and spreadsheetId with the actual IDs of your Google Drive folder containing the agendas and the Google Sheets spreadsheet where you want to track the actions, respectively. +// 5. In the updateStatus function, replace the placeholder value for spreadsheetId with the actual ID of your Google Sheets spreadsheet. +// 6. Save the script by clicking on the floppy disk icon or by pressing "Ctrl + S" (Windows) or "Cmd + S" (Mac). +// 7. Go back to your Google Sheets file, refresh the page, and you'll see a new custom menu labeled "Action Items" in the top menu. +// 8. Click on "Action Items" in the top menu to access the custom menu. You'll find two options: +// a. "Get Actions from Agendas": This option will pull actions from the specified agendas and populate them in the "MO" sheet in your Google Sheets file. +// b. "Update Status in Source Document": This option will push status updates from the "MO" sheet back to the corresponding action items in the source agendas. +// 9. Whenever you want to get actions from the agendas or update status in the source documents, simply click on the corresponding option from the "Action Items" menu. +// Note: Make sure to properly set up the correct folder structure in Google Drive and name your agendas and sheets according to the script's logic for pulling and updating actions. This documentation assumes you have some basic familiarity with Google Apps Script and how to run container-bound scripts within a Google Sheets file. + +////////////////////////////////////////////////// + +// Global Variables: Replace 'folderId' and 'spreadsheetId' with your actual Google Drive folder ID and Google Sheets spreadsheet ID, respectively. +// var folderId = '1WKYw4jnP6ejRkOLAIPoPvbEYClaLE4eR'; // SNWG MO Weekly Internal Planning > FY 23 Google Drive folder +var folderId = '1SRIUs7CUEdGUw0r1PI52e0OJpfXYN0z8'; // SNWG MO Weekly Internal Planning > FY 24 Google Drive folder +var spreadsheetId = '1uYgX660tpizNbIy44ddQogrRphfwZqn1D0Oa2RlSYKg'; // SNWG MO Action Tracking Spreadsheet +>>>>>>> b746d3712728e7b81086aac526d2a6c48e28b83d // Get the spreadsheet name var spreadsheetName = spreadsheet.getName(); @@ -65,6 +88,7 @@ function logExecutionTime(func, functionName) { // Add a custom menu to the spreadsheet function onOpen() { +<<<<<<< HEAD var ui = SpreadsheetApp.getUi(); ui.createMenu('Action Items') .addItem('Pull actions for ALL folders', 'pullActionsForAllFolders') @@ -76,7 +100,15 @@ function onOpen() { .addItem('Push actions from MO', 'pushActionsFromTabMO') .addItem('Push actions from SEP', 'pushActionsFromTabSEP') .addItem('Push actions from DevSeed', 'pushActionsFromTabDevSeed') +======= + SpreadsheetApp.getUi() + .createMenu('Action Items') + .addItem('Get Actions from Agendas','MOPopulate') + .addItem('Push Status Updates to Source Document','updateStatus') +>>>>>>> b746d3712728e7b81086aac526d2a6c48e28b83d .addToUi(); + // to open workbook with up-to-date All Open (Sort Only - Do not Edit) tab + copyDataToAllOpenSheet(); } // Global variables @@ -246,7 +278,11 @@ function populateSheetWithActions(spreadsheetId, sheetName, actions) { } } +<<<<<<< HEAD // Primary Pull function: Pull action items from meeting notes to populate action tracking workbook +======= +// Primary function: Pull action items from meeting notes to populate action tracking workbook +>>>>>>> b746d3712728e7b81086aac526d2a6c48e28b83d function MOPopulate() { var tablePullSheetName = 'MO'; @@ -406,7 +442,13 @@ function getColumnIndex(table, columnName) { return -1; } +<<<<<<< HEAD ////////////////// Push Testing Log ////////////////////////////////////////// +======= +// Primary function: push status updates back to action tracking tables in meeting notes +function updateStatus() { + var sheetName = 'MO'; // <--Replace with the name of your sheet +>>>>>>> b746d3712728e7b81086aac526d2a6c48e28b83d /* 'pushActionsFromTabMO': success 3:59:02 PM execution time: 0 minutes, 13.421 seconds @@ -415,8 +457,17 @@ function getColumnIndex(table, columnName) { 'pushActionsFromAllTabs': 4:16:43 PM execution time: 0 minutes, 31.064 seconds */ +<<<<<<< HEAD ///////////////Combine Open Actions/////////////////////////////////////////////// +======= + Logger.log('Step 2: Syncing status to source documents...'); + syncStatusToSource(actions); + Logger.log('Step 2: Status synced to source documents.'); +} + +////////////////////////////////////////////////////////////// +>>>>>>> b746d3712728e7b81086aac526d2a6c48e28b83d // function to copy all rows of each sheet that do not contain "Done" in the "Status Column". Maintain column D formatting from source sheet to track length of time the action has been open. function copyDataToAllOpenSheet() { // Get a reference to the currently open spreadsheet @@ -470,4 +521,10 @@ function copyDataToAllOpenSheet() { targetRange.setFontWeights([[fonts[rowIndex][3]]]); } }); -} \ No newline at end of file +<<<<<<< HEAD +} +======= +} + + +>>>>>>> b746d3712728e7b81086aac526d2a6c48e28b83d diff --git a/blurbDueDateDialogButton.js b/blurbDueDateDialogButton.js new file mode 100644 index 0000000..6fedb8c --- /dev/null +++ b/blurbDueDateDialogButton.js @@ -0,0 +1,99 @@ +// Helper function to get today's date +function getToday() { + return new Date(); + } + + // Helper function to calculate the next most recent due date + function getNextDueDate() { + const startDate = new Date("December 4, 2023 12:00:00"); + const today = getToday(); + + // Calculate the difference in days from the start date + const daysDiff = Math.floor((today - startDate) / (24 * 60 * 60 * 1000)); + + // Calculate the number of bi-weeks since the start date + const biWeeksSinceStart = Math.floor(daysDiff / 14); + + // Calculate the next due date + const nextDueDate = new Date(startDate); + nextDueDate.setDate(startDate.getDate() + (biWeeksSinceStart + 1) * 14); + nextDueDate.setHours(12, 0, 0, 0); + + return nextDueDate; + } + + // Helper function to format a date in the standard format + function formatDate(date) { + const options = { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' }; + return date.toLocaleDateString('en-US', options); + } + + // Helper function to show a dialog with the next due date + function showNextDueDateDialog() { + const nextDueDate = getNextDueDate(); + const today = getToday(); + + const daysDifference = Math.floor((nextDueDate - today) / (24 * 60 * 60 * 1000)); + + if (daysDifference === 0) { + // If the closest due date is today, show "TODAY AT NOON" with red color, bold font weight, and larger font size; Verified Working + return `

TODAY AT NOON

`; + } else if (daysDifference >= 8 && daysDifference <= 14) { + // If today is within the week AFTER the closest Due Date, show the date in black, the phrase "Due in 2 Weeks: " and no font weight + return `

Due in 2 Weeks: ${formatDate(nextDueDate)}

`; + } else if (daysDifference >= 1 && daysDifference <= 7) { + // If today is within the week BEFORE the closest due date, show the date in blue, "Next Week:" and no font weight; Verified Working + return `

Next Week: ${formatDate(nextDueDate)}

`; + } + } + + + // Primary function to execute all helper actions + function showBlurbsDueDialog() { + const message = showNextDueDateDialog(); + + // Create a custom dialog box with formatted HTML content + const htmlOutput = HtmlService.createHtmlOutput(message) + .setTitle('Blurbs Due') + .setWidth(300) + .setHeight(100); + + // Show the dialog box + DocumentApp.getUi().showModalDialog(htmlOutput, 'Blurbs Due'); + } + + // Function to add a custom menu to the document toolbar + function onOpen() { + DocumentApp.getUi() + .createMenu('When are Blurbs Due?') + .addItem('Check Due Date', 'showBlurbsDueDialog') + .addToUi(); + } + + // Function to simulate blurbs being due today (for testing purposes) + function testBlurbsDueToday() { + const originalGetToday = getToday; + getToday = () => new Date('December 18, 2023 10:00:00'); // Set a specific date and time for testing + showBlurbsDueDialog(); + getToday = originalGetToday; // Restore the original getToday function + } + + // Function to simulate blurbs being due the week before (for testing purposes) + function testDateTheWeekAfterBlurbsAreDue() { + const originalGetToday = getToday; + getToday = () => new Date('December 6, 2023 10:00:00'); // Set a specific date and time for testing (2 days after) + showBlurbsDueDialog(); + getToday = originalGetToday; // Restore the original getToday function + } + + // Function to simulate blurbs being due within the week after (for testing purposes) + function testDateOneWeekBeforeBlurbsAreDue() { + const originalGetToday = getToday; + getToday = () => new Date('December 15, 2023 10:00:00'); // Set a specific date and time for testing (3 days before) + showBlurbsDueDialog(); + getToday = originalGetToday; // Restore the original getToday function + } + + // Run the onOpen function when the document is opened + onOpen(); + \ No newline at end of file diff --git a/createDevSeedCheckinAssessment.js b/createDevSeedCheckinAssessment.js index 49de6b2..7c5ede7 100644 --- a/createDevSeedCheckinAssessment.js +++ b/createDevSeedCheckinAssessment.js @@ -87,34 +87,37 @@ function getMeetingDate() { // Helper function: Rename to YYYY-MM-DD "SNWG/DevSeed Checkin" where YYYY-MM-DD is the meeting date function renameAgendaWithMeetingDate(agenda, meetingDate) { var formattedDate = Utilities.formatDate(meetingDate, Session.getScriptTimeZone(), "yyyy-MM-dd"); - var newName = formattedDate + " SNWG/DevSeed Checkin TEST"; + var newName = formattedDate + " SNWG/DevSeed Checkin"; agenda.setName(newName); } // helper function to update meeting date within the newly created document -function updateAgendaDate(agendaFile,newDate) { - var document = DocumentApp.openById(agendaFile.getId()); // Open the file as a Google Docs document +function updateAgendaDate(agendaFile) { + // Get the meeting date + var meetingDate = getMeetingDate(); + + // Open the file as a Google Docs document + var document = DocumentApp.openById(agendaFile.getId()); var body = document.getBody(); - - // Define a regular expression pattern to match dates in Month day, year format - var datePattern = /\b(January|February|March|April|May|June|July|August|September|October|November|December) \d{1,2}, \d{4}\b/; - + + // Define a regular expression pattern to match dates in Month day, year or yyyy-MM-dd format + var datePattern = /\b\d{4}-\d{1,2}-\d{1,2}\b|\b(January|February|March|April|May|June|July|August|September|October|November|December) \d{1,2}, \d{4}\b/; + // Iterate through the paragraphs in the body var paragraphs = body.getParagraphs(); for (var i = 0; i < paragraphs.length; i++) { - var paragraph = paragraphs[i]; - var text = paragraph.getText(); - var match = text.match(datePattern); - + var paragraph = paragraphs[i]; + var text = paragraph.getText(); + var match = text.match(datePattern); if (match) { // Replace the matched text with the new formatted date - var formattedNewDate = Utilities.formatDate(newDate, Session.getScriptTimeZone(), "MMMM dd, yyyy"); + var formattedNewDate = Utilities.formatDate(meetingDate, Session.getScriptTimeZone(), "MMMM dd, yyyy"); var updatedText = text.replace(datePattern, formattedNewDate); paragraph.setText(updatedText); } } } - + // Helper function to update specific placeholders function updatePlaceholders(agendaFile) { var document = DocumentApp.openById(agendaFile.getId()); diff --git a/newQuadChartSlide b/newQuadChartSlide index 7be0541..a25022b 100644 --- a/newQuadChartSlide +++ b/newQuadChartSlide @@ -331,26 +331,26 @@ function getFilesForCurrentWeekFromSpecificFolder(specificFolderID, currentWeekD } // helper function to get dates for last week -function getLastWeekDates() { - var currentDate = new Date(); - var startOfLastWeek = new Date(currentDate); - startOfLastWeek.setDate(currentDate.getDate() - 7); // Go back one week to find the start - startOfLastWeek.setDate(startOfLastWeek.getDate() - startOfLastWeek.getDay() + 1); // Align to the start of the week (Monday) +//function getLastWeekDates() { +// var currentDate = new Date(); +// var startOfLastWeek = new Date(currentDate); +// startOfLastWeek.setDate(currentDate.getDate() - 7); // Go back one week to find the start +// startOfLastWeek.setDate(startOfLastWeek.getDate() - startOfLastWeek.getDay() + 1); // Align to the start of the week (Monday) - var endOfLastWeek = new Date(startOfLastWeek); - endOfLastWeek.setDate(startOfLastWeek.getDate() + 4); // Last week's end date (Friday) +// var endOfLastWeek = new Date(startOfLastWeek); +// endOfLastWeek.setDate(startOfLastWeek.getDate() + 4); // Last week's end date (Friday) - return { - start: startOfLastWeek, - end: endOfLastWeek - }; -} +// return { +// start: startOfLastWeek, +// end: endOfLastWeek +// }; +//} // helper function to find last week files -function getFilesForLastWeek(folderID) { - var lastWeekDates = getLastWeekDates(); // Get the start and end dates for last week - return getFilesForCurrentWeek(folderID, lastWeekDates); -} +// function getFilesForLastWeek(folderID) { +// var lastWeekDates = getLastWeekDates(); // Get the start and end dates for last week +// return getFilesForCurrentWeek(folderID, lastWeekDates); +//} // helper function to replace slide placeholders function replacePlaceholdersInSlide(slide, replacements) { @@ -438,11 +438,11 @@ function handleCurrentDMPRShape(currentDMPRShape) { // helper function to update Open Action Items function updateOpenActionItems() { - // Open the Google Sheet by ID and get the sheet named 'Table Pull' - var sheet = SpreadsheetApp.openById(sheetID).getSheetByName('Table Pull'); + // Open the Google Sheet by ID and get the sheet named 'MO' + var sheet = SpreadsheetApp.openById(sheetID).getSheetByName('MO'); if (sheet === null) { - Logger.log('Could not find sheet with name Table Pull'); + Logger.log('Could not find sheet with name MO'); return null; } @@ -527,18 +527,18 @@ function updatePresentationOptimized() { } // Get the "Last Week Agendas" shape - var lastWeekAgendasShape = findShapeByAltText(newSlide, "Last Week Agendas"); + // var lastWeekAgendasShape = findShapeByAltText(newSlide, "Last Week Agendas"); // Get files for the last week - var lastWeekFiles = getFilesForLastWeek(agendasFolderID); + // var lastWeekFiles = getFilesForLastWeek(agendasFolderID); // Populate "Last Week Agendas" shape with files for the last week - if (lastWeekAgendasShape) { - var lastWeekAgendasText = lastWeekFiles.map(function(file) { - return file.url; // Format as you like - }).join('\n'); - lastWeekAgendasShape.getText().setText(lastWeekAgendasText); - } + // if (lastWeekAgendasShape) { + // var lastWeekAgendasText = lastWeekFiles.map(function(file) { + // return file.url; // Format as you like + // }).join('\n'); + // lastWeekAgendasShape.getText().setText(lastWeekAgendasText); + // } var currentPI = adjustedPIcalculator.getPI(new Date()); var year = new Date().getFullYear(); @@ -559,4 +559,4 @@ function updatePresentationOptimized() { // Insert the new slide at the beginning var targetPresentation = SlidesApp.openById(targetPresentationId); targetPresentation.insertSlide(0, newSlide); -} \ No newline at end of file +}