Acciones universales

Las acciones universales son elementos de elementos de menú que permiten a un usuario abrir una nueva página web, mostrar tarjetas de IU nuevas o ejecutar una función específica de Apps Script cuando se selecciona. En cuanto a la operación, son muy similares a las acciones de tarjeta, excepto que las acciones universales siempre se colocan en cada tarjeta de tu complemento, independientemente del contexto actual del complemento.

Con las acciones universales, puedes asegurarte de que el usuario siempre tenga acceso a ciertas funcionalidades, independientemente de la parte del complemento con la que interactúe. Estos son algunos ejemplos de casos de uso para las acciones universales:

  • Abre una página web de configuración (o muestra una tarjeta de configuración).
  • Muestra información de ayuda al usuario.
  • Inicia un flujo de trabajo nuevo, como "Agregar cliente nuevo".
  • Mostrar una tarjeta que permita al usuario enviar comentarios sobre el complemento

Cuando tengas una acción que no dependa del contexto actual, deberías considerar convertirla en una acción universal.

Cómo usar acciones universales

Las acciones universales se configuran en el manifiesto del proyecto de tu complemento. Una vez que hayas configurado una acción universal, siempre estará disponible para los usuarios de tu complemento. Si el usuario está viendo una tarjeta, el conjunto de acciones universales que definiste siempre aparecerá en el menú de la tarjeta, después de las acciones de tarjeta que hayas definido para esa tarjeta. Las acciones universales aparecen en los menús de tarjetas en el mismo orden en el que se definen en el manifiesto del complemento.

Cómo configurar acciones universales

Puedes configurar acciones universales en el manifiesto de tu complemento. Consulta Manifiestos para obtener más información.

Para cada acción, debes especificar el texto que debe aparecer en el menú de esa acción. Luego, puedes especificar un campo openLink que indique que la acción debe abrir directamente una página web en una pestaña nueva. También puedes establecer un campo runFunction que especifique una función de devolución de llamada de Apps Script que se ejecutará cuando se seleccione la acción universal.

Cuando se usa runFunction, la función de devolución de llamada especificada suele realizar una de las siguientes acciones:

  • Compila tarjetas de IU para que se muestren de inmediato mostrando un objeto UniversalActionResponse compilado.
  • Abre una URL, quizás después de realizar otras tareas, cuando muestra un objeto UniversalActionResponse compilado.
  • Realiza tareas en segundo plano que no cambian a una nueva tarjeta ni abren una URL. En este caso, la función de devolución de llamada no devuelve nada.

Cuando se la llama, la función de devolución de llamada recibe un objeto de evento que contiene información sobre la tarjeta abierta y el contexto del complemento.

Ejemplo

En el siguiente fragmento de código, se muestra un ejemplo de extracto de manifiesto para un complemento de Google Workspace que usa acciones universales mientras extiende Gmail. El código establece de manera explícita un alcance de metadatos para que el complemento pueda determinar quién envió el mensaje abierto.

  "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"
        }
      ]
    },
    ...
  },
  ...

Las tres acciones universales definidas en el ejemplo anterior hacen lo siguiente:

  • Abrir google.com abre https://www.google.com en una pestaña nueva.
  • Abrir URL de contacto ejecuta una función que determina qué URL abrir y, luego, la abre en una pestaña nueva con un objeto OpenLink. El código compila la URL con la dirección de correo electrónico del remitente.
  • Abrir configuración ejecuta la función createSettingsCards() definida en el proyecto de secuencia de comandos del complemento. Esta función muestra un objeto UniversalActionResponse válido que contiene un conjunto de tarjetas con configuración de complementos y otra información. Cuando la función termina de compilar el objeto, la IU muestra la lista de tarjetas (consulta Cómo mostrar varias tarjetas).
  • La opción Ejecutar la sincronización en segundo plano ejecuta la función runBackgroundSync() definida en el proyecto de secuencia de comandos del complemento. Esta función no crea tarjetas. En su lugar, realiza otras tareas en segundo plano que no cambian la IU. Como la función no muestra un UniversalActionResponse, la IU no muestra una tarjeta nueva cuando finaliza la función. En su lugar, la IU mostrará un ícono giratorio de carga mientras se ejecuta la función.

A continuación, se muestra un ejemplo de cómo podrías construir las funciones openContactURL(), createSettingsResponse() y 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.
}