Wyświetl podgląd linków z elementami inteligentnymi

Na tej stronie dowiesz się, jak utworzyć dodatek do Google Workspace, który umożliwia użytkownikom Dokumentów Google podgląd linków z usługi innej firmy.

Dodatek do Google Workspace może wykrywać linki do Twojej usługi i prosić użytkowników Dokumentów Google o wyświetlenie podglądu tych linków. Możesz skonfigurować dodatek, aby wyświetlać podgląd wielu wzorców adresów URL, takich jak linki do zgłoszeń do zespołu pomocy, kontakty do potencjalnych klientów i profile pracowników.

Aby wyświetlać podgląd linków w dokumencie Dokumentów Google, użytkownicy mogą korzystać z elementów inteligentnych i kart:

Użytkownik wyświetla podgląd karty

Gdy użytkownik wpisze lub wklei adres URL do dokumentu, Dokumenty Google proszą o zastąpienie linku elementem inteligentnym. Element inteligentny wyświetla ikonę i krótki tytuł lub opis treści linku. Gdy użytkownik najedzie kursorem na element, zobaczy interfejs karty z podglądem dodatkowych informacji o pliku lub linku.

Ten film pokazuje, jak użytkownik konwertuje link na element inteligentny i wyświetla podgląd karty:

Wymagania wstępne

Google Apps Script

Node.js

Python

Java

Opcjonalnie: konfigurowanie uwierzytelniania w usłudze innej firmy

Jeśli dodatek łączy się z usługą, która wymaga autoryzacji, użytkownicy muszą uwierzytelnić się w usłudze, aby wyświetlać podgląd linków. Oznacza to, że gdy użytkownik po raz pierwszy wklei link z Twojej usługi do dokumentu w Dokumentach Google, dodatek musi wywołać proces autoryzacji.

Aby skonfigurować usługę OAuth lub niestandardową prośbę o autoryzację, zapoznaj się z tymi przewodnikami:

Z tej sekcji dowiesz się, jak skonfigurować podgląd linków dla dodatku:

  1. Skonfiguruj podgląd linków w zasobie wdrożenia dodatku lub pliku manifestu.
  2. Utwórz interfejs układu inteligentnego i karty dla swoich linków.

Skonfiguruj podgląd linków

Aby skonfigurować podglądy linków, określ te sekcje i pola w zasobie wdrożenia dodatku lub pliku manifestu:

  1. W sekcji addOns dodaj pole docs, aby rozszerzyć zakres Dokumentów Google.
  2. W polu docs zaimplementuj aktywator linkPreviewTriggers, który zawiera runFunction (Funkcję tę definiujesz w kolejnej sekcji Utwórz element inteligentny i kartę).

    Aby dowiedzieć się, jakie pola możesz określić w aktywatorze linkPreviewTriggers, zapoznaj się z dokumentacją dotyczącą plików manifestu Apps Script lub zasobów wdrażania innych środowiska wykonawczego.

  3. W polu oauthScopes dodaj zakres https://www.googleapis.com/auth/workspace.linkpreview, aby użytkownicy mogli autoryzować dodatek do podglądu linków w ich imieniu.

Oto przykład w sekcji oauthScopes i addons zasobu wdrożenia, który konfiguruje podgląd linków do obsługi zgłoszeń do zespołu pomocy:

{
  "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"
          }
        }
      ]
    }
  }
}

W tym przykładzie Dodatek do Google Workspace wyświetla podgląd linków do firmowej usługi zgłoszeń do zespołu pomocy. Dodatek określa 3 wzorce adresów URL do podglądu linków. Gdy link pasuje do jednego ze wzorców adresów URL w dokumencie Dokumentów Google, funkcja wywołania zwrotnego caseLinkPreview skompilowa i wyświetli element inteligentny oraz kartę.

Utwórz układ inteligentny i kartę

Aby zwrócić element inteligentny i kartę dla linku, musisz zaimplementować wszystkie funkcje określone w obiekcie linkPreviewTriggers.

Gdy użytkownik wchodzi w interakcję z linkiem pasującym do określonego wzorca adresu URL, uruchamia się aktywator linkPreviewTriggers, a jego funkcja wywołania zwrotnego przekazuje obiekt zdarzenia docs.matchedUrl.url jako argument. Ładunek tego obiektu zdarzenia służy do utworzenia elementu inteligentnego i karty na potrzeby podglądu linku.

Na przykład w przypadku dodatku, który określa wzorzec adresu URL example.com/cases, jeśli użytkownik wyświetli podgląd linku https://www.example.com/cases/123456, zostanie zwrócony następujący ładunek zdarzenia:

JSON

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

Aby utworzyć interfejs karty, użyj widżetów do wyświetlania informacji o linku. Możesz też tworzyć działania, które pozwolą użytkownikom otworzyć link lub zmodyfikować jego zawartość. Listę dostępnych widżetów i działań znajdziesz w sekcji Komponenty kart podglądu.

Aby utworzyć element inteligentny i kartę do podglądu linku:

  1. Zaimplementuj funkcję podaną w sekcji linkPreviewTriggers zasobu wdrożenia dodatku lub pliku manifestu:
    1. Funkcja musi akceptować obiekt zdarzenia zawierający docs.matchedUrl.url jako argument i zwracać pojedynczy obiekt Card.
    2. Jeśli Twoja usługa wymaga autoryzacji, musi ona też wywoływać proces autoryzacji.
  2. Dla każdej karty podglądu implementuj dowolne funkcje wywołania zwrotnego, które zapewniają interaktywność widżetów dla interfejsu. Jeśli np. dodasz przycisk „Wyświetl link”, możesz utworzyć działanie określające funkcję wywołania zwrotnego w celu otwarcia linku w nowym oknie. Więcej informacji o interakcjach z widżetami znajdziesz w artykule Działania dodatkowe.

Ten kod tworzy funkcję wywołania zwrotnego caseLinkPreview:

Google 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

węzeł/link-podglądu/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/linki-podglądu/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;
}

Obsługiwane komponenty kart podglądu

Dodatki do Google Workspace obsługują te widżety i działania na kartach podglądu linków:

Google Apps Script

Pole Usługa karty Typ
TextParagraph Widżet
DecoratedText Widżet
Image Widżet
IconImage Widżet
ButtonSet Widżet
TextButton Widżet
ImageButton Widżet
Grid Widżet
Divider Widżet
OpenLink Działanie
Navigation Czynność
Obsługiwana jest tylko metoda updateCard.

JSON

Pole karty (google.apps.card.v1) Typ
TextParagraph Widżet
DecoratedText Widżet
Image Widżet
Icon Widżet
ButtonList Widżet
Button Widżet
Grid Widżet
Divider Widżet
OpenLink Działanie
Navigation Czynność
Obsługiwana jest tylko metoda updateCard.

Pełny przykład: dodatek do zgłoszenia do zespołu pomocy

Poniższy przykład przedstawia dodatek do Google Workspace, który wyświetla podgląd linków do zgłoszeń do zespołu pomocy i profili pracowników.

W tym przykładzie wykonano te działania:

  • Podgląd linków do zgłoszeń do zespołu pomocy, np. https://www.example.com/support/cases/1234. Element inteligentny ma ikonę pomocy, a karta podglądu zawiera identyfikator zgłoszenia i opis.
  • Wyświetla podgląd linków do obsługi zgłoszeń do zespołu pomocy, np. https://www.example.com/people/rosario-cruz. Element inteligentny zawiera ikonę osoby, a na karcie podglądu znajduje się imię i nazwisko pracownika, adres e-mail, stanowisko oraz zdjęcie profilowe.
  • Jeśli język użytkownika jest ustawiony na hiszpański, element inteligentny przetłumaczy labelText na hiszpański.

Zasób wdrożenia

Google 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"
        }
      ]
    }
  }
}

Kod

Google 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

węzeł/link-podglądu/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/linki-podglądu/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;
  }

}