Acciones universales

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

Cuando 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 de acciones universales:

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

Siempre que 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 configures una acción universal, esta estará siempre disponible para los usuarios de tu complemento. Si el usuario ve una tarjeta, el conjunto de acciones universales que definiste siempre aparece en el menú de la tarjeta, después de cualquier acción de la tarjeta que hayas definido para ella. Las acciones universales aparecen en los menús de la tarjeta en el mismo orden en el que se definen en el manifiesto del complemento.

Configura acciones universales

Puedes configurar acciones universales en el manifiesto del 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. Como alternativa, puedes especificar un campo runFunction que especifique una función de devolución de llamada de Apps Script para que se ejecute cuando se selecciona 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 mostrarlas de inmediato mostrando un objeto UniversalActionResponse compilado.
  • Abre una URL, quizás después de realizar otras tareas, mediante la visualización de 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, a la función de devolución de llamada se le pasa 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 extracto de manifiesto de ejemplo para un complemento de Google Workspace que usa acciones universales mientras se extiende Gmail. El código establece de forma 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:

  • Abre google.com abre https://www.google.com en una pestaña nueva.
  • La URL de contacto de apertura ejecuta una función que determina qué URL se abre y, luego, la abre en una pestaña nueva mediante 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. Una vez que la función termina de compilar este objeto, la IU muestra la lista de tarjetas (consulta Cómo mostrar varias tarjetas).
  • 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 cambio, realiza otras tareas en segundo plano que no cambian la IU. Como la función no muestra un UniversalActionResponse, la IU no muestra una nueva tarjeta cuando finaliza la función. En cambio, la IU muestra un ícono giratorio de indicador de carga mientras la función está en ejecución.

A continuación, se muestra un ejemplo de cómo podrías crear 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.
}