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

פעולות אוניברסליות הן רכיבים של פריטים בתפריט, שמאפשרים למשתמש לפתוח דף אינטרנט חדש, להציג כרטיסים חדשים של ממשק משתמש או להריץ פונקציה ספציפית של 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"
        }
      ]
    },
    ...
  },
  ...

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

  • Open google.com פותח את https://www.google.com בכרטיסייה חדשה.
  • השדה Open contact URL מפעיל פונקציה שקובעת איזו כתובת URL תפתח, ואז פותחת את הכתובת בכרטיסייה חדשה באמצעות אובייקט OpenLink. הקוד יוצר את כתובת ה-URL באמצעות כתובת האימייל של השולח.
  • Open settings מפעילה את הפונקציה 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.
}