Acciones universales

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

Si usas acciones universales, puedes asegurarte de que el usuario siempre tenga acceso a ciertas funcionalidades, sin importar con qué parte del complemento interactúe. Estos son algunos ejemplos de casos de uso para 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”.
  • Muestra una tarjeta que le permita al usuario enviar comentarios sobre el complemento.

Siempre que tengas una acción que no dependa del contexto actual, deberías considerar que sea 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 del complemento. Si el usuario está viendo una tarjeta, el conjunto de acciones universales que definiste siempre aparece en el menú de la tarjeta, después de cualquier acción de tarjeta que hayas definido para esa tarjeta. Las acciones universales aparecen en los menús de las tarjetas en el mismo orden en el que se definen en el manifiesto del complemento.

Cómo configurar acciones universales

Las acciones universales se configuran en el manifiesto del complemento. Para obtener más información, consulta Manifiestos.

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. Como alternativa, puedes especificar 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 generalmente realiza una de las siguientes acciones:

  • Compila tarjetas de IU para mostrar 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 tarjeta nueva ni abren una URL. En este caso, la función de devolución de llamada no muestra nada.

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

Ejemplo

En el siguiente fragmento de código, se muestra un extracto de manifiesto de ejemplo para un complemento de Google Workspace que usa acciones universales mientras extiende Gmail. El código establece de manera explícita un permiso 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.
  • Open contact URL 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 parámetros de configuración de complementos y otra información. Cuando la función termina de compilar este objeto, la IU muestra la lista de tarjetas (consulta Cómo mostrar varias tarjetas).
  • 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 compila tarjetas, sino que realiza algunas otras tareas en segundo plano que no cambian la IU. Dado que la función no muestra un UniversalActionResponse, la IU no muestra una tarjeta nueva cuando finaliza la función. En cambio, la IU muestra 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.
}