יצירת סדר יום לפגישות

רמת הקידוד: מתחילים
משך: 15 דקות
סוג הפרויקט: אוטומציה עם טריגר מבוסס-אירועים

מטרות

  • להבין מה הפתרון עושה.
  • הסבר על הפעולות של שירותי Apps Script בפתרון.
  • מגדירים את הסקריפט.
  • מריצים את הסקריפט.

מידע על הפתרון הזה

ליצור באופן אוטומטי מסמכי סדר יום ב-Google Docs ולצרף אותם לפגישות ביומן Google.

צילום מסך של סדר היום שנוסף לאירוע ביומן

איך זה עובד

הסקריפט יוצר תבנית של מסמך לסדר יום. כשמעדכנים את היומן, הסקריפט בודק אם יש אירועים בבעלותכם שכוללים את המחרוזת '#agenda' בתיאור. אם התג קיים, הסקריפט יוצר עותק של התבנית, מוסיף אותו לאירוע ביומן ומשתף אותו עם המשתתפים באירוע.

שירותי Apps Script

הפתרון הזה משתמש בשירותים הבאים:

  • שירות Drive – המערכת בודקת אם מסמך התבנית קיים, ואם לא, היא יוצרת תיקייה חדשה בשביל מסמך התבנית. יוצר עותק של מסמך התבנית לכל סדר יום חדש.
  • Document service – יוצר את תבנית סדר היום.
  • שירות היומן – בודק אם יש אירועים עם התג #agenda ומעדכן את תיאור האירוע עם קישור למסמך הנושאים לדיון.
  • שירות בסיסי – משתמש במחלקה Session כדי לקבל את כתובת האימייל של המשתמש. הפעולה הזו עוזרת ליצור את הטריגר עבור המשתמש הנוכחי.
  • שירות Script – יוצר טריגר שמופעל בכל פעם שיש שינוי ביומן של המשתמש.

דרישות מוקדמות

כדי להשתמש בדוגמה הזו, אתם צריכים לעמוד בדרישות המוקדמות הבאות:

  • חשבון Google (יכול להיות שחשבונות Google Workspace ידרשו אישור אדמין).
  • דפדפן אינטרנט עם גישה לאינטרנט.

הגדרת הסקריפט

  1. לוחצים על הלחצן שלמטה כדי לפתוח את פרויקט Apps Script לדוגמה יצירת סדר יום לפגישות.
    פתיחת הפרויקט
  2. לוחצים על סקירה כללית .
  3. בדף הסקירה הכללית, לוחצים על סמל יצירת העותק הסמל ליצירת עותק.
  4. בפרויקט שהעתקתם, בתפריט הנפתח של הפונקציה, בוחרים באפשרות setUp.
  5. לוחצים על Run.
  6. כשמוצגת בקשה, מאשרים את הסקריפט. אם במסך ההסכמה ל-OAuth מוצגת האזהרה האפליקציה הזו לא אומתה, ממשיכים בתהליך על ידי בחירה באפשרות מתקדם > מעבר אל {שם הפרויקט} (לא בטוח).

הפעלת הסקריפט

  1. פותחים את יומן Google.
  2. יוצרים אירוע חדש או עורכים אירוע קיים.
  3. בתיאור, מוסיפים #agenda ושומרים את האירוע.
  4. בודקים אם קיבלתם התראה באימייל על שיתוף מסמך, או מרעננים את היומן ולוחצים שוב על האירוע כדי לראות את הקישור למסמך סדר היום.

כל המשתתפים מקבלים את ההתראה באימייל לצפייה בסדר היום. הסקריפט נותן למשתתפים הרשאת עריכה, אבל אתם יכולים לערוך את הסקריפט כדי לעדכן את הרשאות הגישה של המשתתפים למסמך סדר היום.

בדיקת הקוד

כדי לבדוק את קוד Apps Script של הפתרון הזה, לוחצים על הצגת קוד המקור למטה:

הצגת קוד המקור

Code.gs

solutions/automations/agenda-maker/Code.js
// To learn how to use this script, refer to the documentation:
// https://developers.google.com/apps-script/samples/automations/agenda-maker

/*
Copyright 2022 Google LLC

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    https://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

/**
 * Checks if the folder for Agenda docs exists, and creates it if it doesn't.
 *
 * @return {*} Drive folder ID for the app.
 */
function checkFolder() {
  const folders = DriveApp.getFoldersByName('Agenda Maker - App');
  // Finds the folder if it exists
  while (folders.hasNext()) {
    let folder = folders.next();
    if (
      folder.getDescription() ==
        'Apps Script App - Do not change this description' &&
      folder.getOwner().getEmail() == Session.getActiveUser().getEmail()
    ) {
      return folder.getId();
    }
  }
  // If the folder doesn't exist, creates one
  let folder = DriveApp.createFolder('Agenda Maker - App');
  folder.setDescription('Apps Script App - Do not change this description');
  return folder.getId();
}

/**
 * Finds the template agenda doc, or creates one if it doesn't exist.
 */
function getTemplateId(folderId) {
  const folder = DriveApp.getFolderById(folderId);
  const files = folder.getFilesByName('Agenda TEMPLATE##');

  // If there is a file, returns the ID.
  while (files.hasNext()) {
    const file = files.next();
    return file.getId();
  }

  // Otherwise, creates the agenda template.
  // You can adjust the default template here
  const doc = DocumentApp.create('Agenda TEMPLATE##');
  const body = doc.getBody();

  body
      .appendParagraph('##Attendees##')
      .setHeading(DocumentApp.ParagraphHeading.HEADING1)
      .editAsText()
      .setBold(true);
  body.appendParagraph(' ').editAsText().setBold(false);

  body
      .appendParagraph('Overview')
      .setHeading(DocumentApp.ParagraphHeading.HEADING1)
      .editAsText()
      .setBold(true);
  body.appendParagraph(' ');
  body.appendParagraph('- Topic 1: ').editAsText().setBold(true);
  body.appendParagraph(' ').editAsText().setBold(false);
  body.appendParagraph('- Topic 2: ').editAsText().setBold(true);
  body.appendParagraph(' ').editAsText().setBold(false);
  body.appendParagraph('- Topic 3: ').editAsText().setBold(true);
  body.appendParagraph(' ').editAsText().setBold(false);

  body
      .appendParagraph('Next Steps')
      .setHeading(DocumentApp.ParagraphHeading.HEADING1)
      .editAsText()
      .setBold(true);
  body.appendParagraph('- Takeaway 1: ').editAsText().setBold(true);
  body.appendParagraph('- Responsible: ').editAsText().setBold(false);
  body.appendParagraph('- Accountable: ');
  body.appendParagraph('- Consult: ');
  body.appendParagraph('- Inform: ');
  body.appendParagraph(' ');
  body.appendParagraph('- Takeaway 2: ').editAsText().setBold(true);
  body.appendParagraph('- Responsible: ').editAsText().setBold(false);
  body.appendParagraph('- Accountable: ');
  body.appendParagraph('- Consult: ');
  body.appendParagraph('- Inform: ');
  body.appendParagraph(' ');
  body.appendParagraph('- Takeaway 3: ').editAsText().setBold(true);
  body.appendParagraph('- Responsible: ').editAsText().setBold(false);
  body.appendParagraph('- Accountable: ');
  body.appendParagraph('- Consult: ');
  body.appendParagraph('- Inform: ');

  doc.saveAndClose();

  folder.addFile(DriveApp.getFileById(doc.getId()));

  return doc.getId();
}

/**
 * When there is a change to the calendar, searches for events that include "#agenda"
 * in the decrisption.
 *
 */
function onCalendarChange() {
  // Gets recent events with the #agenda tag
  const now = new Date();
  const events = CalendarApp.getEvents(
      now,
      new Date(now.getTime() + 2 * 60 * 60 * 1000000),
      {search: '#agenda'},
  );

  const folderId = checkFolder();
  const templateId = getTemplateId(folderId);

  const folder = DriveApp.getFolderById(folderId);

  // Loops through any events found
  for (i = 0; i < events.length; i++) {
    const event = events[i];

    // Confirms whether the event has the #agenda tag
    let description = event.getDescription();
    if (description.search('#agenda') == -1) continue;

    // Only works with events created by the owner of this calendar
    if (event.isOwnedByMe()) {
      // Creates a new document from the template for an agenda for this event
      const newDoc = DriveApp.getFileById(templateId).makeCopy();
      newDoc.setName('Agenda for ' + event.getTitle());

      const file = DriveApp.getFileById(newDoc.getId());
      folder.addFile(file);

      const doc = DocumentApp.openById(newDoc.getId());
      const body = doc.getBody();

      // Fills in the template with information about the attendees from the
      // calendar event
      const conf = body.findText('##Attendees##');
      if (conf) {
        const ref = conf.getStartOffset();

        for (let i in event.getGuestList()) {
          let guest = event.getGuestList()[i];

          body.insertParagraph(ref + 2, guest.getEmail());
        }
        body.replaceText('##Attendees##', 'Attendees');
      }

      // Replaces the tag with a link to the agenda document
      const agendaUrl = 'https://docs.google.com/document/d/' + newDoc.getId();
      description = description.replace(
          '#agenda',
          '<a href=' + agendaUrl + '>Agenda Doc</a>',
      );
      event.setDescription(description);

      // Invites attendees to the Google doc so they automatically receive access to the agenda
      newDoc.addEditor(newDoc.getOwner());

      for (let i in event.getGuestList()) {
        let guest = event.getGuestList()[i];

        newDoc.addEditor(guest.getEmail());
      }
    }
  }
  return;
}

/**
 * Creates an event-driven trigger that fires whenever there's a change to the calendar.
 */
function setUp() {
  let email = Session.getActiveUser().getEmail();
  ScriptApp.newTrigger("onCalendarChange").forUserCalendar(email).onEventUpdated().create();
}

שינויים

אפשר לערוך את הדוגמה כמה שרוצים כדי להתאים אותה לצרכים שלכם. בהמשך מפורטים כמה שינויים אופציונליים שאפשר לבצע.

עדכון ההרשאות למסמך סדר היום למשתתפים

הסקריפט נותן למשתתפים הרשאה לערוך. אם רוצים להגביל את ההרשאות להרשאות צפייה בלבד, מחליפים את השיטה addEditor בשיטה addViewer בחלק הבא של הקוד:

     for (let i in event.getGuestList()) {
       let guest = event.getGuestList()[i];

       newDoc.addEditor(guest.getEmail());

עריכת תבנית המסמך של סדר היום

כדי לעדכן את תבנית המסמך של סדר היום:

  1. אחרי שיוצרים את סדר היום הראשון באירוע ביומן, פותחים את Google Drive.
  2. פותחים את התיקייה Agenda Maker - App.
  3. פותחים את המסמך Agenda TEMPLATE## ומבצעים את העריכות הרצויות.

תורמים

הדוגמה הזו נוצרה על ידי ג'רמי גלסנברג (Jeremy Glassenberg), יועץ לניהול מוצר ולאסטרטגיית פלטפורמה. אפשר למצוא את ג'רמי ב-Twitter‏ @jglassenberg.

הדוגמה הזו מתוחזקת על ידי Google בעזרת מומחי Google לפיתוח.

השלבים הבאים