Prévisualiser les liens avec les chips intelligents

.

Cette page explique comment créer un module complémentaire Google Workspace qui permet aux utilisateurs de Google Docs, Sheets et Slides de prévisualiser les liens d'un service tiers.

Un module complémentaire Google Workspace peut détecter les liens de votre service et inviter les utilisateurs à les prévisualiser. Vous pouvez configurer un module complémentaire pour prévisualiser plusieurs formats d'URL, tels que des liens vers des demandes d'assistance, des prospects commerciaux et des profils d'employés.

Pour prévisualiser des liens, les utilisateurs interagissent avec des chips intelligents et des fiches.

L'utilisateur affiche un aperçu d'une carte.

Lorsque les utilisateurs saisissent ou collent une URL dans un document, Google Docs les invite à remplacer le lien par un chip intelligent. Le chip intelligent affiche une icône et un titre ou une description courts du contenu du lien. Lorsque l'utilisateur passe la souris sur le chip, il voit une interface de carte qui affiche plus d'informations sur le fichier ou le lien.

La vidéo suivante montre comment un utilisateur convertit un lien en chip intelligent et affiche un aperçu d'une fiche:

Les chips intelligents tiers ne sont pas compatibles avec la version Preview développeur des aperçus de liens dans Sheets et Slides. Lorsque les utilisateurs saisissent ou collent une URL dans une feuille de calcul ou une présentation, Sheets ou Slides les invite à remplacer le lien par son titre en tant que texte lié plutôt que sous forme de chip. Lorsque l'utilisateur passe la souris sur le titre du lien, une interface de fiche s'affiche avec un aperçu des informations sur le lien.

L'image suivante montre comment l'aperçu d'un lien s'affiche dans Sheets et Slides:

Exemple d'aperçu de lien pour Sheets et Slides

Conditions préalables

Apps Script ;

  • Un compte Google Workspace
  • Un module complémentaire Google Workspace. Pour créer un module complémentaire, suivez ce quickstart.

Node.js

  • Un compte Google Workspace
  • Un module complémentaire Google Workspace. Pour créer un module complémentaire, suivez ce quickstart.

Python

  • Un compte Google Workspace
  • Un module complémentaire Google Workspace. Pour créer un module complémentaire, suivez ce quickstart.

Java

  • Un compte Google Workspace
  • Un module complémentaire Google Workspace. Pour créer un module complémentaire, suivez ce quickstart.

Facultatif: Configurer l'authentification auprès d'un service tiers

Si votre module complémentaire se connecte à un service nécessitant une autorisation, les utilisateurs doivent s'authentifier auprès de ce service pour prévisualiser les liens. Cela signifie que lorsque les utilisateurs collez pour la première fois un lien de votre service dans un fichier Docs, Sheets ou Slides, votre module complémentaire doit appeler le flux d'autorisation.

Pour configurer un service OAuth ou une invite d'autorisation personnalisée, consultez l'un des guides suivants:

Cette section explique comment configurer des aperçus de liens pour votre module complémentaire, et comprend les étapes suivantes:

  1. Configurez les aperçus des liens dans la ressource de déploiement ou le fichier manifeste de votre module complémentaire.
  2. Créez l'interface de carte à puce intelligente et de carte pour vos liens.

Configurer les aperçus de lien

Pour configurer les aperçus de lien, spécifiez les sections et les champs suivants dans la ressource de déploiement ou le fichier manifeste de votre module complémentaire:

  1. Dans la section addOns, ajoutez le champ docs pour étendre Docs, le champ sheets pour étendre Sheets et le champ slides pour étendre Slides.
  2. Dans chaque champ, implémentez le déclencheur linkPreviewTriggers qui inclut un runFunction (vous définirez cette fonction dans la section suivante, Créer le chip et la carte intelligents).

    Pour en savoir plus sur les champs que vous pouvez spécifier dans le déclencheur linkPreviewTriggers, consultez la documentation de référence sur les fichiers manifestes Apps Script ou les ressources de déploiement pour d'autres environnements d'exécution.

  3. Dans le champ oauthScopes, ajoutez le champ d'application https://www.googleapis.com/auth/workspace.linkpreview afin que les utilisateurs puissent autoriser le module complémentaire à prévisualiser les liens en leur nom.

Par exemple, consultez la section oauthScopes et addons de la ressource de déploiement suivante, qui configure les aperçus de lien pour un service de demande d'assistance.

{
  "oauthScopes": [
    "https://www.googleapis.com/auth/workspace.linkpreview"
  ],
  "addOns": {
    "common": {
      "name": "Preview support cases",
      "logoUrl": "https://www.example.com/images/company-logo.png",
      "layoutProperties": {
        "primaryColor": "#dd4b39"
      }
    },
    "docs": {
      "linkPreviewTriggers": [
        {
          "runFunction": "caseLinkPreview",
          "patterns": [
            {
              "hostPattern": "example.com",
              "pathPrefix": "support/cases"
            },
            {
              "hostPattern": "*.example.com",
              "pathPrefix": "cases"
            },
            {
              "hostPattern": "cases.example.com"
            }
          ],
          "labelText": "Support case",
          "logoUrl": "https://www.example.com/images/support-icon.png",
          "localizedLabelText": {
            "es": "Caso de soporte"
          }
        }
      ]
    },
    "sheets": {
      "linkPreviewTriggers": [
        {
          "runFunction": "caseLinkPreview",
          "patterns": [
            {
              "hostPattern": "example.com",
              "pathPrefix": "support/cases"
            },
            {
              "hostPattern": "*.example.com",
              "pathPrefix": "cases"
            },
            {
              "hostPattern": "cases.example.com"
            }
          ],
          "labelText": "Support case",
          "logoUrl": "https://www.example.com/images/support-icon.png",
          "localizedLabelText": {
            "es": "Caso de soporte"
          }
        }
      ]
    },
    "slides": {
      "linkPreviewTriggers": [
        {
          "runFunction": "caseLinkPreview",
          "patterns": [
            {
              "hostPattern": "example.com",
              "pathPrefix": "support/cases"
            },
            {
              "hostPattern": "*.example.com",
              "pathPrefix": "cases"
            },
            {
              "hostPattern": "cases.example.com"
            }
          ],
          "labelText": "Support case",
          "logoUrl": "https://www.example.com/images/support-icon.png",
          "localizedLabelText": {
            "es": "Caso de soporte"
          }
        }
      ]
    }
  }
}

Dans cet exemple, le module complémentaire Google Workspace affiche un aperçu des liens vers le service de demande d'assistance d'une entreprise. Le module complémentaire spécifie trois formats d'URL pour les liens d'aperçu. Chaque fois qu'un lien correspond à l'un des formats d'URL, la fonction de rappel caseLinkPreview crée et affiche une fiche et un chip intelligent, ou dans Sheets et Slides, remplace l'URL par le titre du lien.

Créer la puce et la carte intelligentes

Pour renvoyer une puce intelligente pour un lien, vous devez implémenter toutes les fonctions que vous avez spécifiées dans l'objet linkPreviewTriggers.

Lorsqu'un utilisateur interagit avec un lien correspondant à un format d'URL spécifié, le déclencheur linkPreviewTriggers s'active et sa fonction de rappel transmet l'objet d'événement EDITOR_NAME.matchedUrl.url en tant qu'argument. Vous utiliserez la charge utile de cet objet événement pour créer le chip intelligent et la carte pour l'aperçu de votre lien.

Par exemple, pour un module complémentaire qui spécifie le format d'URL example.com/cases pour Docs, si un utilisateur affiche l'aperçu du lien https://www.example.com/cases/123456, la charge utile d'événement suivante est renvoyée:

JSON

{
  "docs": {
    "matchedUrl": {
        "url": "https://www.example.com/support/cases/123456"
    }
  }
}

Pour créer l'interface de la fiche, vous utilisez des widgets afin d'afficher des informations sur le lien. Vous pouvez également créer des actions permettant aux utilisateurs d'ouvrir le lien ou de modifier son contenu. Pour obtenir la liste des widgets et des actions disponibles, consultez la section Composants compatibles avec les fiches d'aperçu.

Pour créer le chip et la carte intelligents pour un aperçu de lien:

  1. Mettez en œuvre la fonction que vous avez spécifiée dans la section linkPreviewTriggers de la ressource de déploiement ou du fichier manifeste de votre module complémentaire :
    1. La fonction doit accepter un objet d'événement contenant EDITOR_NAME.matchedUrl.url comme argument et renvoyer un seul objet Card.
    2. Si votre service nécessite une autorisation, la fonction doit également appeler le flux d'autorisation.
  2. Pour chaque fiche d'aperçu, implémentez des fonctions de rappel qui fournissent une interactivité des widgets pour l'interface. Par exemple, si vous incluez un bouton "Afficher le lien", vous pouvez créer une action qui spécifie une fonction de rappel pour ouvrir le lien dans une nouvelle fenêtre. Pour en savoir plus sur les interactions avec les widgets, consultez la section Actions complémentaires.

Le code suivant crée la fonction de rappel caseLinkPreview pour Docs:

Apps Script ;

apps-script/preview-links/preview-link.gs
/**
* Entry point for a support case link preview
*
* @param {!Object} event
* @return {!Card}
*/
// Creates a function that passes an event object as a parameter.
function caseLinkPreview(event) {

  // If the event object URL matches a specified pattern for support case links.
  if (event.docs.matchedUrl.url) {

    // Uses the event object to parse the URL and identify the case ID.
    const segments = event.docs.matchedUrl.url.split('/');
    const caseId = segments[segments.length - 1];

    // Builds a preview card with the case ID, title, and description
    const caseHeader = CardService.newCardHeader()
      .setTitle(`Case ${caseId}: Title bar is broken.`);
    const caseDescription = CardService.newTextParagraph()
      .setText('Customer can\'t view title on mobile device.');

    // Returns the card.
    // Uses the text from the card's header for the title of the smart chip.
    return CardService.newCardBuilder()
      .setHeader(caseHeader)
      .addSection(CardService.newCardSection().addWidget(caseDescription))
      .build();
  }
}

Node.js

node/preview-links/index.js
/**
 * 
 * A support case link preview.
 *
 * @param {!string} url
 * @return {!Card}
 */
function caseLinkPreview(url) {

  // Parses the URL to identify the case ID.
  const segments = url.split('/');
  const caseId = segments[segments.length - 1];

  // Returns the card.
  // Uses the text from the card's header for the title of the smart chip.
  return {
    header: {
      title: `Case ${caseId}: Title bar is broken.`
    },
    sections: [{
      widgets: [{
        textParagraph: {
          text: `Customer can't view title on mobile device.`
        }
      }]
    }]
  };
}

Python

python/preview-links/main.py

def case_link_preview(url):
    """A support case link preview.
    Args:
      url: The case link.
    Returns:
      A case link preview card.
    """

    # Parses the URL to identify the case ID.
    segments = url.split("/")
    case_id = segments[-1]

    # Returns the card.
    # Uses the text from the card's header for the title of the smart chip.
    return {
        "header": {"title": f"Case {case_id}: Title bar is broken."},
        "sections": [
            {
                "widgets": [
                    {
                        "textParagraph": {
                            "text": "Customer can't view title on mobile device."
                        }
                    }
                ]
            }
        ],
    }

Java

java/preview-links/src/main/java/PreviewLink.java
/**
 * Creates a case link preview card.
 *
 * @param url A URL.
 * @return A case link preview card.
 */
Card caseLinkPreview(String url) {
  String[] segments = url.split("/");
  String caseId = segments[segments.length - 1];

  CardHeader cardHeader = new CardHeader();
  cardHeader.setTitle(String.format("Case %s: Title bar is broken.", caseId));

  TextParagraph textParagraph = new TextParagraph();
  textParagraph.setText("Customer can't view title on mobile device.");

  WidgetMarkup widget = new WidgetMarkup();
  widget.setTextParagraph(textParagraph);
  Section section = new Section();
  section.setWidgets(List.of(widget));

  Card card = new Card();
  card.setHeader(cardHeader);
  card.setSections(List.of(section));

  return card;
}

Composants compatibles avec les cartes d'aperçu

Les modules complémentaires Google Workspace sont compatibles avec les widgets et actions suivants pour les fiches d'aperçu des liens:

Apps Script ;

Champ du service de carte de paiement Type
TextParagraph Widget
DecoratedText Widget
Image Widget
IconImage Widget
ButtonSet Widget
TextButton Widget
ImageButton Widget
Grid Widget
Divider Widget
OpenLink Action
Navigation Action
Seule la méthode updateCard est acceptée.

JSON

Champ de la fiche (google.apps.card.v1) Type
TextParagraph Widget
DecoratedText Widget
Image Widget
Icon Widget
ButtonList Widget
Button Widget
Grid Widget
Divider Widget
OpenLink Action
Navigation Action
Seule la méthode updateCard est prise en charge.

Exemple complet: module complémentaire pour la demande d'assistance

L'exemple suivant présente un module complémentaire Google Workspace qui affiche un aperçu des liens vers les demandes d'assistance d'une entreprise et les profils d'employés dans Google Docs.

en effectuant les opérations suivantes :

  • Aperçu des liens vers des demandes d'assistance, telles que https://www.example.com/support/cases/1234. Le chip intelligent affiche une icône d'assistance, et la fiche d'aperçu inclut le numéro de demande et une description.
  • Aperçu des liens vers les agents de demande d'assistance, tels que https://www.example.com/people/rosario-cruz. Le chip intelligent affiche une icône de personne, et la fiche d'aperçu inclut le nom, l'adresse e-mail, le titre du poste et la photo de profil de l'employé.
  • Si les paramètres régionaux de l'utilisateur sont définis sur l'espagnol, le chip intelligent localise sa labelText en espagnol.

Ressource de déploiement

Apps Script ;

apps-script/preview-links/appsscript.json
{
  "timeZone": "America/New_York",
  "exceptionLogging": "STACKDRIVER",
  "runtimeVersion": "V8",
  "oauthScopes": [
    "https://www.googleapis.com/auth/workspace.linkpreview"
  ],
  "addOns": {
    "common": {
      "name": "Preview support cases",
      "logoUrl": "https://developers.google.com/workspace/add-ons/images/link-icon.png",
      "layoutProperties": {
        "primaryColor": "#dd4b39"
      }
    },
    "docs": {
      "linkPreviewTriggers": [
        {
          "runFunction": "caseLinkPreview",
          "patterns": [
            {
              "hostPattern": "example.com",
              "pathPrefix": "support/cases"
            },
            {
              "hostPattern": "*.example.com",
              "pathPrefix": "cases"
            },
            {
              "hostPattern": "cases.example.com"
            }
          ],
          "labelText": "Support case",
          "localizedLabelText": {
            "es": "Caso de soporte"
          },
          "logoUrl": "https://developers.google.com/workspace/add-ons/images/support-icon.png"
        },
        {
          "runFunction": "peopleLinkPreview",
          "patterns": [
            {
              "hostPattern": "example.com",
              "pathPrefix": "people"
            }
          ],
          "labelText": "People",
          "localizedLabelText": {
            "es": "Personas"
          },
          "logoUrl": "https://developers.google.com/workspace/add-ons/images/person-icon.png"
        }
      ]
    }
  }
}

JSON

{
  "oauthScopes": [
    "https://www.googleapis.com/auth/workspace.linkpreview"
  ],
  "addOns": {
    "common": {
      "name": "Preview support cases",
      "logoUrl": "https://developers.google.com/workspace/add-ons/images/link-icon.png",
      "layoutProperties": {
        "primaryColor": "#dd4b39"
      }
    },
    "docs": {
      "linkPreviewTriggers": [
        {
          "runFunction": "URL",
          "patterns": [
            {
              "hostPattern": "example.com",
              "pathPrefix": "support/cases"
            },
            {
              "hostPattern": "*.example.com",
              "pathPrefix": "cases"
            },
            {
              "hostPattern": "cases.example.com"
            }
          ],
          "labelText": "Support case",
          "localizedLabelText": {
            "es": "Caso de soporte"
          },
          "logoUrl": "https://developers.google.com/workspace/add-ons/images/support-icon.png"
        },
        {
          "runFunction": "URL",
          "patterns": [
            {
              "hostPattern": "example.com",
              "pathPrefix": "people"
            }
          ],
          "labelText": "People",
          "localizedLabelText": {
            "es": "Personas"
          },
          "logoUrl": "https://developers.google.com/workspace/add-ons/images/person-icon.png"
        }
      ]
    }
  }
}

Code

Apps Script ;

apps-script/preview-links/preview-link.gs
/**
* Entry point for a support case link preview
*
* @param {!Object} event
* @return {!Card}
*/
// Creates a function that passes an event object as a parameter.
function caseLinkPreview(event) {

  // If the event object URL matches a specified pattern for support case links.
  if (event.docs.matchedUrl.url) {

    // Uses the event object to parse the URL and identify the case ID.
    const segments = event.docs.matchedUrl.url.split('/');
    const caseId = segments[segments.length - 1];

    // Builds a preview card with the case ID, title, and description
    const caseHeader = CardService.newCardHeader()
      .setTitle(`Case ${caseId}: Title bar is broken.`);
    const caseDescription = CardService.newTextParagraph()
      .setText('Customer can\'t view title on mobile device.');

    // Returns the card.
    // Uses the text from the card's header for the title of the smart chip.
    return CardService.newCardBuilder()
      .setHeader(caseHeader)
      .addSection(CardService.newCardSection().addWidget(caseDescription))
      .build();
  }
}


/**
* Entry point for an employee profile link preview
*
* @param {!Object} event
* @return {!Card}
*/
function peopleLinkPreview(event) {

  // If the event object URL matches a specified pattern for employee profile links.
  if (event.docs.matchedUrl.url) {

    // Builds a preview card with an employee's name, title, email, and profile photo.
    const userHeader = CardService.newCardHeader().setTitle("Rosario Cruz");
    const userImage = CardService.newImage()
      .setImageUrl("https://developers.google.com/workspace/add-ons/images/employee-profile.png");
    const userInfo = CardService.newDecoratedText()
      .setText("rosario@example.com")
      .setBottomLabel("Case Manager")
      .setIcon(CardService.Icon.EMAIL);
    const userSection = CardService.newCardSection()
      .addWidget(userImage)
      .addWidget(userInfo);

    // Returns the card. Uses the text from the card's header for the title of the smart chip.
    return CardService.newCardBuilder()
      .setHeader(userHeader)
      .addSection(userSection)
      .build();
  }
}

Node.js

node/preview-links/index.js
const UrlParser = require('url');

/**
 * Responds to any HTTP request.
 *
 * @param {Object} req HTTP request context.
 * @param {Object} res HTTP response context.
 */
exports.createLinkPreview = (req, res) => {
  const event = req.body;
  if (event.docs.matchedUrl.url) {
    res.json(createCard(event.docs.matchedUrl.url));
  }
};

/**
 * Creates a preview link card for either a case link or people link.
 * 
 * @param {!String} url
 * @return {!Card}
 */
function createCard(url) {
  const parsedUrl = UrlParser.parse(url);
  if (parsedUrl.hostname === 'www.example.com') {
    if (parsedUrl.path.startsWith('/support/cases/')) {
      return caseLinkPreview(url);
    }

    if (parsedUrl.path.startsWith('/people/')) {
      return peopleLinkPreview();
    }
  }
}


/**
 * 
 * A support case link preview.
 *
 * @param {!string} url
 * @return {!Card}
 */
function caseLinkPreview(url) {

  // Parses the URL to identify the case ID.
  const segments = url.split('/');
  const caseId = segments[segments.length - 1];

  // Returns the card.
  // Uses the text from the card's header for the title of the smart chip.
  return {
    header: {
      title: `Case ${caseId}: Title bar is broken.`
    },
    sections: [{
      widgets: [{
        textParagraph: {
          text: `Customer can't view title on mobile device.`
        }
      }]
    }]
  };
}


/**
 * An employee profile link preview.
 *
 * @return {!Card}
 */
function peopleLinkPreview() {

  // Builds a preview card with an employee's name, title, email, and profile photo.
  // Returns the card. Uses the text from the card's header for the title of the smart chip.
  return {
    header: {
      title: "Rosario Cruz"
    },
    sections: [{
      widgets: [
        {
          image: {
            imageUrl: 'https://developers.google.com/workspace/add-ons/images/employee-profile.png'
          }
        }, {
          keyValue: {
            icon: "EMAIL",
            content: "rosario@example.com",
            bottomLabel: "Case Manager"
          }
        }
      ]
    }]
  };
}

Python

python/preview-links/main.py
from typing import Any, Mapping
from urllib.parse import urlparse

import flask
import functions_framework


@functions_framework.http
def create_link_preview(req: flask.Request):
    """Responds to any HTTP request.
    Args:
      req: HTTP request context.
    Returns:
      The response object.
    """
    event = req.get_json(silent=True)
    if event["docs"]["matchedUrl"]["url"]:
        return create_card(event["docs"]["matchedUrl"]["url"])


def create_card(url):
    """Creates a preview link card for either a case link or people link.
    Args:
      url: The matched url.
    Returns:
      A case link preview card or a people link preview card.
    """
    parsed_url = urlparse(url)
    if parsed_url.hostname != "www.example.com":
        return {}

    if parsed_url.path.startswith("/support/cases/"):
        return case_link_preview(url)

    if parsed_url.path.startswith("/people/"):
        return people_link_preview()

    return {}




def case_link_preview(url):
    """A support case link preview.
    Args:
      url: The case link.
    Returns:
      A case link preview card.
    """

    # Parses the URL to identify the case ID.
    segments = url.split("/")
    case_id = segments[-1]

    # Returns the card.
    # Uses the text from the card's header for the title of the smart chip.
    return {
        "header": {"title": f"Case {case_id}: Title bar is broken."},
        "sections": [
            {
                "widgets": [
                    {
                        "textParagraph": {
                            "text": "Customer can't view title on mobile device."
                        }
                    }
                ]
            }
        ],
    }




def people_link_preview():
    """An employee profile link preview.
    Returns:
      A people link preview card.
    """

    # Builds a preview card with an employee's name, title, email, and profile photo.
    # Returns the card. Uses the text from the card's header for the title of the smart chip.
    return {
        "header": {"title": "Rosario Cruz"},
        "sections": [
            {
                "widgets": [
                    {
                        "image": {
                            "imageUrl": "https:#developers.google.com/workspace/add-ons/images/employee-profile.png"
                        }
                    },
                    {
                        "keyValue": {
                            "icon": "EMAIL",
                            "content": "rosario@example.com",
                            "bottomLabel": "Case Manager",
                        }
                    },
                ]
            }
        ],
    }

Java

java/preview-links/src/main/java/PreviewLink.java
import com.google.api.services.chat.v1.model.Card;
import com.google.api.services.chat.v1.model.CardHeader;
import com.google.api.services.chat.v1.model.Image;
import com.google.api.services.chat.v1.model.KeyValue;
import com.google.api.services.chat.v1.model.Section;
import com.google.api.services.chat.v1.model.TextParagraph;
import com.google.api.services.chat.v1.model.WidgetMarkup;
import com.google.cloud.functions.HttpFunction;
import com.google.cloud.functions.HttpRequest;
import com.google.cloud.functions.HttpResponse;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;

public class PreviewLink implements HttpFunction {
  private static final Gson gson = new Gson();

  /**
   * Responds to any HTTP request.
   *
   * @param request  An HTTP request context.
   * @param response An HTTP response context.
   */
  @Override
  public void service(HttpRequest request, HttpResponse response) throws Exception {
    JsonObject body = gson.fromJson(request.getReader(), JsonObject.class);
    String url = body.getAsJsonObject("docs")
        .getAsJsonObject("matchedUrl")
        .get("url")
        .getAsString();

    response.getWriter().write(gson.toJson(createCard(url)));
  }

  /**
   * Creates a preview link card for either a case link or people link.
   *
   * @param url A URL.
   * @return A case link preview card or a people link preview card.
   */
  Card createCard(String url) throws MalformedURLException {
    URL parsedURL = new URL(url);

    if (!parsedURL.getHost().equals("www.example.com")) {
      return new Card();
    }

    if (parsedURL.getPath().startsWith("/support/cases/")) {
      return caseLinkPreview(url);
    }

    if (parsedURL.getPath().startsWith("/people/")) {
      return peopleLinkPreview();
    }

    return new Card();
  }


  /**
   * Creates a case link preview card.
   *
   * @param url A URL.
   * @return A case link preview card.
   */
  Card caseLinkPreview(String url) {
    String[] segments = url.split("/");
    String caseId = segments[segments.length - 1];

    CardHeader cardHeader = new CardHeader();
    cardHeader.setTitle(String.format("Case %s: Title bar is broken.", caseId));

    TextParagraph textParagraph = new TextParagraph();
    textParagraph.setText("Customer can't view title on mobile device.");

    WidgetMarkup widget = new WidgetMarkup();
    widget.setTextParagraph(textParagraph);
    Section section = new Section();
    section.setWidgets(List.of(widget));

    Card card = new Card();
    card.setHeader(cardHeader);
    card.setSections(List.of(section));

    return card;
  }


  /**
   * Creates a people link preview card.
   *
   * @return A people link preview card.
   */
  Card peopleLinkPreview() {
    CardHeader cardHeader = new CardHeader();
    cardHeader.setTitle("Rosario Cruz");

    Image image = new Image();
    image.setImageUrl("https://developers.google.com/workspace/add-ons/images/employee-profile.png");

    WidgetMarkup imageWidget = new WidgetMarkup();
    imageWidget.setImage(image);

    KeyValue keyValue = new KeyValue();
    keyValue.setIcon("EMAIL");
    keyValue.setContent("rosario@example.com");
    keyValue.setBottomLabel("Case Manager");

    WidgetMarkup keyValueWidget = new WidgetMarkup();
    keyValueWidget.setKeyValue(keyValue);

    Section section = new Section();
    section.setWidgets(List.of(imageWidget, keyValueWidget));

    Card card = new Card();
    card.setHeader(cardHeader);
    card.setSections(List.of(section));

    return card;
  }

}