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

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