פעולות אוניברסליות

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

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

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

בכל פעם שיש פעולה שלא תלויה בהקשר הנוכחי, כדאי ליצור אותה פעולה אוניברסלית.

שימוש בפעולות אוניברסליות

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

הגדרת פעולות אוניברסליות

אתם מגדירים פעולות אוניברסליות במניפסט של התוסף. לפרטים נוספים, ראו מניפסטים.

לכל פעולה צריך לציין את הטקסט שאמור להופיע בתפריט של הפעולה הזו. לאחר מכן תוכלו לציין את השדה openLink, שמציין שהפעולה צריכה לפתוח דף אינטרנט ישירות בכרטיסייה חדשה. לחלופין, אפשר לציין שדה runFunction שמציין פונקציית קריאה חוזרת ב-Apps Script שצריך להפעיל כשהפעולה האוניברסלית נבחרת.

כשמשתמשים ב-runFunction, פונקציית הקריאה החוזרת שצוינה בדרך כלל מבצעת אחת מהפעולות הבאות:

  • יצירת כרטיסי ממשק משתמש להצגה מיידית על ידי החזרת אובייקט UniversalActionResponse מובנה.
  • פתיחת כתובת URL, אולי אחרי ביצוע משימות אחרות, על ידי החזרת אובייקט UniversalActionResponse מובנה.
  • מבצע משימות ברקע שלא עוברות לכרטיס חדש או פותחות כתובת URL. במקרה כזה, פונקציית הקריאה החוזרת לא מחזירה שום דבר.

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

דוגמה

בקטע הקוד הבא מוצג קטע לדוגמה של מניפסט מתוסף של Google Workspace שמשתמש בפעולות אוניברסליות בזמן הרחבת Gmail. הקוד מגדיר במפורש היקף של מטא-נתונים כדי שהתוסף יוכל לקבוע מי שלח את ההודעה הפתוחה.

  "oauthScopes": [
    "https://www.googleapis.com/auth/gmail.addons.current.message.metadata"
  ],
  "addOns": {
    "common": {
      "name": "Universal Actions Only Addon",
      "logoUrl": "https://www.example.com/hosted/images/2x/my-icon.png",
      "openLinkUrlPrefixes": [
        "https://www.google.com",
        "https://www.example.com/urlbase"
      ],
      "universalActions": [{
          "label": "Open google.com",
          "openLink": "https://www.google.com"
        }, {
          "label": "Open contact URL",
          "runFunction": "openContactURL"
        }, {
          "label": "Open settings",
          "runFunction": "createSettingsResponse"
        }, {
          "label": "Run background sync",
          "runFunction": "runBackgroundSync"
      }],
      ...
    },
    "gmail": {
      "contextualTriggers": [
        {
          "unconditional": {},
          "onTriggerFunction": "getContextualAddOn"
        }
      ]
    },
    ...
  },
  ...

שלוש הפעולות האוניברסליות שמוגדרות בדוגמה הקודמת עושות את הפעולות הבאות:

  • פתיחת google.com פותחת את https://www.google.com בכרטיסייה חדשה.
  • האפשרות Open contact URL מפעילה פונקציה שקובעת איזו כתובת URL לפתוח, ולאחר מכן פותחת אותה בכרטיסייה חדשה באמצעות אובייקט OpenLink. הקוד בונה את כתובת ה-URL באמצעות כתובת האימייל של השולח.
  • פתיחת ההגדרות מפעילה את הפונקציה createSettingsCards() שהוגדרה בפרויקט הסקריפט של התוסף. הפונקציה הזו מחזירה אובייקט UniversalActionResponse תקין שמכיל קבוצת כרטיסים עם הגדרות לתוסף ומידע נוסף. כשהפונקציה מסיימת ליצור את האובייקט, ממשק המשתמש מציג את רשימת הכרטיסים (ראו החזרת כרטיסים מרובים).
  • הפעלת סנכרון ברקע מפעילה את הפונקציה runBackgroundSync() שמוגדרת בפרויקט הסקריפט להוספה. הפונקציה הזו לא יוצרת כרטיסים. במקום זאת, היא מבצעת כמה משימות אחרות ברקע שלא משנות את ממשק המשתמש. מכיוון שהפונקציה לא מחזירה UniversalActionResponse, ממשק המשתמש לא מציג כרטיס חדש בסיום הפונקציה. במקום זאת, ממשק המשתמש מציג סימן גרפי שמוצג בזמן שהפונקציה פועלת.

הדוגמה הבאה מראה איך אפשר לבנות את הפונקציות openContactURL(), createSettingsResponse() ו-runBackgroundSync():

/**
 * Open a contact URL.
 * @param {Object} e an event object
 * @return {UniversalActionResponse}
 */
function openContactURL(e) {
  // Activate temporary Gmail scopes, in this case so that the
  // open message metadata can be read.
  var accessToken = e.gmail.accessToken;
  GmailApp.setCurrentMessageAccessToken(accessToken);

  // Build URL to open based on a base URL and the sender's email.
  // This URL must be included in the openLinkUrlPrefixes whitelist.
  var messageId = e.gmail.messageId;
  var message = GmailApp.getMessageById(messageId);
  var sender = message.getFrom();
  var url = "https://www.example.com/urlbase/" + sender;
  return CardService.newUniversalActionResponseBuilder()
      .setOpenLink(CardService.newOpenLink()
          .setUrl(url))
      .build();
}

/**
 * Create a collection of cards to control the add-on settings and
 * present other information. These cards are displayed in a list when
 * the user selects the associated "Open settings" universal action.
 *
 * @param {Object} e an event object
 * @return {UniversalActionResponse}
 */
function createSettingsResponse(e) {
  return CardService.newUniversalActionResponseBuilder()
      .displayAddOnCards(
          [createSettingCard(), createAboutCard()])
      .build();
}

/**
 * Create and return a built settings card.
 * @return {Card}
 */
function createSettingCard() {
  return CardService.newCardBuilder()
      .setHeader(CardService.newCardHeader().setTitle('Settings'))
      .addSection(CardService.newCardSection()
          .addWidget(CardService.newSelectionInput()
              .setType(CardService.SelectionInputType.CHECK_BOX)
              .addItem("Ask before deleting contact", "contact", false)
              .addItem("Ask before deleting cache", "cache", false)
              .addItem("Preserve contact ID after deletion", "contactId", false))
          // ... continue adding widgets or other sections here ...
      ).build();   // Don't forget to build the card!
}

/**
 * Create and return a built 'About' informational card.
 * @return {Card}
 */
function createAboutCard() {
  return CardService.newCardBuilder()
      .setHeader(CardService.newCardHeader().setTitle('About'))
      .addSection(CardService.newCardSection()
          .addWidget(CardService.newTextParagraph()
              .setText('This add-on manages contact information. For more '
                  + 'details see the <a href="https://www.example.com/help">'
                  + 'help page</a>.'))
      // ... add other information widgets or sections here ...
      ).build();  // Don't forget to build the card!
}

/**
 * Run background tasks, none of which should alter the UI.
 * Also records the time of sync in the script properties.
 *
 * @param {Object} e an event object
 */
function runBackgroundSync(e) {
  var props = PropertiesService.getUserProperties();
  props.setProperty("syncTime", new Date().toString());

  syncWithContacts();  // Not shown.
  updateCache();       // Not shown.
  validate();          // Not shown.

  // no return value tells the UI to keep showing the current card.
}