پیش نمایش لینک ها با تراشه های هوشمند

این صفحه نحوه ساخت افزونه‌ای برای Google Workspace را توضیح می‌دهد که به کاربران Google Docs، Sheets و Slides اجازه می‌دهد لینک‌های یک سرویس شخص ثالث را پیش‌نمایش کنند.

یک افزونه‌ی Google Workspace می‌تواند لینک‌های سرویس شما را شناسایی کرده و کاربران را به پیش‌نمایش آنها ترغیب کند. می‌توانید افزونه‌ای را برای پیش‌نمایش چندین الگوی URL، مانند لینک‌های مربوط به موارد پشتیبانی، سرنخ‌های فروش و پروفایل‌های کارمندان، پیکربندی کنید.

نحوه پیش‌نمایش لینک‌ها توسط کاربران

برای پیش‌نمایش لینک‌ها، کاربران با تراشه‌ها و کارت‌های هوشمند تعامل دارند.

پیش‌نمایش کارت توسط کاربر

وقتی کاربران یک URL را در یک سند یا صفحه گسترده تایپ یا پیست می‌کنند، Google Docs یا Google Sheets از آنها می‌خواهد که لینک را با یک تراشه هوشمند جایگزین کنند. تراشه هوشمند یک آیکون و عنوان یا توضیح کوتاهی از محتوای لینک را نمایش می‌دهد. وقتی کاربر ماوس را روی تراشه نگه می‌دارد، یک رابط کارتی می‌بیند که اطلاعات بیشتری در مورد فایل یا لینک را پیش‌نمایش می‌دهد.

ویدیوی زیر نشان می‌دهد که چگونه یک کاربر یک لینک را به یک تراشه هوشمند تبدیل می‌کند و پیش‌نمایشی از یک کارت را مشاهده می‌کند:

نحوه پیش‌نمایش لینک‌ها در اسلایدها توسط کاربران

تراشه‌های هوشمند شخص ثالث برای پیش‌نمایش لینک‌ها در اسلایدها پشتیبانی نمی‌شوند. وقتی کاربران یک URL را در یک ارائه تایپ یا پیست می‌کنند، اسلایدها از آنها می‌خواهند که به جای یک تراشه، عنوان لینک را به صورت متن لینک‌شده جایگزین کنند. وقتی کاربر ماوس را روی عنوان لینک نگه می‌دارد، یک رابط کارتی می‌بیند که اطلاعات مربوط به لینک را پیش‌نمایش می‌کند.

تصویر زیر نحوه نمایش پیش‌نمایش لینک در اسلایدها را نشان می‌دهد:

مثال پیش‌نمایش لینک برای اسلایدها

پیش‌نیازها

اسکریپت برنامه‌ها

نود جی اس

پایتون

جاوا

اختیاری: تنظیم احراز هویت برای یک سرویس شخص ثالث

اگر افزونه شما به سرویسی متصل شود که نیاز به مجوز دارد، کاربران برای پیش‌نمایش لینک‌ها باید در سرویس احراز هویت شوند. این بدان معناست که وقتی کاربران برای اولین بار لینکی از سرویس شما را در یک فایل Docs، Sheets یا Slides قرار می‌دهند، افزونه شما باید جریان مجوز را فراخوانی کند.

برای تنظیم سرویس OAuth یا درخواست مجوز سفارشی، به بخش «افزونه خود را به یک سرویس شخص ثالث متصل کنید» مراجعه کنید.

این بخش نحوه تنظیم پیش‌نمایش لینک‌ها برای افزونه شما را توضیح می‌دهد که شامل مراحل زیر است:

  1. پیش‌نمایش لینک‌ها را در مانیفست افزونه خود پیکربندی کنید .
  2. رابط تراشه و کارت هوشمند را برای لینک‌های خود بسازید .

پیکربندی پیش‌نمایش لینک‌ها

برای پیکربندی پیش‌نمایش لینک‌ها، بخش‌ها و فیلدهای زیر را در مانیفست افزونه خود مشخص کنید:

  1. در بخش addOns ، فیلد docs را برای بسط Docs، فیلد sheets را برای بسط Sheets و فیلد slides را برای بسط Slides اضافه کنید.
  2. در هر فیلد، تریگر linkPreviewTriggers را که شامل یک runFunction است، پیاده‌سازی کنید (این تابع را در بخش بعدی، ساخت تراشه و کارت هوشمند ، تعریف می‌کنید).

    برای کسب اطلاعات در مورد اینکه چه فیلدهایی را می‌توانید در تریگر linkPreviewTriggers مشخص کنید، به مستندات مرجع برای Apps Script manifests یا منابع استقرار برای سایر runtimes مراجعه کنید.

  3. در فیلد oauthScopes ، محدوده‌ی https://www.googleapis.com/auth/workspace.linkpreview را اضافه کنید تا کاربران بتوانند افزونه را برای پیش‌نمایش لینک‌ها از طرف خود مجاز کنند.

به عنوان مثال، به بخش oauthScopes و addons مانیفست زیر که پیش‌نمایش‌های لینک را برای یک سرویس مورد پشتیبانی پیکربندی می‌کند، مراجعه کنید.

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

در مثال، افزونه‌ی Google Workspace پیش‌نمایشی از لینک‌های مربوط به سرویس پرونده‌ی پشتیبانی یک شرکت را نمایش می‌دهد. این افزونه سه الگوی URL را برای پیش‌نمایش لینک‌ها مشخص می‌کند. هر زمان که لینکی با یکی از الگوهای URL مطابقت داشته باشد، تابع فراخوانی caseLinkPreview یک کارت و یک تراشه‌ی هوشمند در Docs، Sheets یا Slides می‌سازد و نمایش می‌دهد و URL را با عنوان لینک جایگزین می‌کند.

ساخت تراشه و کارت هوشمند

برای برگرداندن یک تراشه و کارت هوشمند برای یک لینک، باید هر تابعی را که در شیء linkPreviewTriggers مشخص کرده‌اید، پیاده‌سازی کنید.

وقتی کاربری با لینکی که با الگوی URL مشخص‌شده‌ای مطابقت دارد، تعامل می‌کند، triggerهای linkPreviewTriggers فعال می‌شوند و تابع فراخوانی آن، شیء رویداد EDITOR_NAME .matchedUrl.url را به عنوان آرگومان ارسال می‌کند. شما از payload این شیء رویداد برای ساخت تراشه و کارت هوشمند برای پیش‌نمایش لینک خود استفاده می‌کنید.

برای مثال، اگر کاربری پیش‌نمایشی از لینک https://www.example.com/cases/123456 در Docs را مشاهده کند، رویداد payload زیر بازگردانده می‌شود:

جی‌سون

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

برای ایجاد رابط کارت، از ویجت‌ها برای نمایش اطلاعات مربوط به لینک استفاده می‌کنید. همچنین می‌توانید اکشن‌هایی بسازید که به کاربران اجازه می‌دهد لینک را باز کنند یا محتوای آن را تغییر دهند. برای مشاهده لیستی از ویجت‌ها و اکشن‌های موجود، به کامپوننت‌های پشتیبانی شده برای کارت‌های پیش‌نمایش مراجعه کنید.

برای ساخت تراشه و کارت هوشمند برای پیش‌نمایش لینک:

  1. تابعی را که در بخش linkPreviewTriggers از فایل manifest افزونه خود مشخص کرده‌اید، پیاده‌سازی کنید:
    1. این تابع باید یک شیء رویداد حاوی EDITOR_NAME .matchedUrl.url را به عنوان آرگومان بپذیرد و یک شیء Card واحد را برگرداند.
    2. اگر سرویس شما نیاز به مجوز دارد، تابع باید جریان مجوز را نیز فراخوانی کند .
  2. برای هر کارت پیش‌نمایش، هرگونه تابع فراخوانی که تعامل ویجت را برای رابط فراهم می‌کند، پیاده‌سازی کنید. برای مثال، اگر دکمه‌ای با عنوان «مشاهده لینک» اضافه کنید، می‌توانید عملی ایجاد کنید که یک تابع فراخوانی برای باز کردن لینک در یک پنجره جدید را مشخص کند. برای کسب اطلاعات بیشتر در مورد تعاملات ویجت، به اقدامات افزونه مراجعه کنید.

کد زیر تابع فراخوانی caseLinkPreview برای Docs ایجاد می‌کند:

اسکریپت برنامه‌ها

apps-script/3p-resources/3p-resources.gs
/**
* Entry point for a support case link preview.
*
* @param {!Object} event The event object.
* @return {!Card} The resulting preview link card.
*/
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 details.
    const caseDetails = parseQuery(event.docs.matchedUrl.url);

    // Builds a preview card with the case name, and description
    const caseHeader = CardService.newCardHeader()
      .setTitle(`Case ${caseDetails["name"][0]}`);
    const caseDescription = CardService.newTextParagraph()
      .setText(caseDetails["description"][0]);

    // 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();
  }
}

/**
* Extracts the URL parameters from the given URL.
*
* @param {!string} url The URL to parse.
* @return {!Map} A map with the extracted URL parameters.
*/
function parseQuery(url) {
  const query = url.split("?")[1];
  if (query) {
    return query.split("&")
    .reduce(function(o, e) {
      var temp = e.split("=");
      var key = temp[0].trim();
      var value = temp[1].trim();
      value = isNaN(value) ? value : Number(value);
      if (o[key]) {
        o[key].push(value);
      } else {
        o[key] = [value];
      }
      return o;
    }, {});
  }
  return null;
}

نود جی اس

گره/3p-resources/index.js
/**
 * 
 * A support case link preview.
 *
 * @param {!URL} url The event object.
 * @return {!Card} The resulting preview link card.
 */
function caseLinkPreview(url) {
  // Builds a preview card with the case name, and description
  // Uses the text from the card's header for the title of the smart chip.
  // Parses the URL and identify the case details.
  const name = `Case ${url.searchParams.get("name")}`;
  return {
    action: {
      linkPreview: {
        title: name,
        previewCard: {
          header: {
            title: name
          },
          sections: [{
            widgets: [{
              textParagraph: {
                text: url.searchParams.get("description")
              }
            }]
          }]
        }
      }
    }
  };
}

پایتون

پایتون/3p-resources/create_link_preview/main.py
def case_link_preview(url):
    """A support case link preview.
    Args:
      url: A matching URL.
    Returns:
      The resulting preview link card.
    """

    # Parses the URL and identify the case details.
    query_string = parse_qs(url.query)
    name = f'Case {query_string["name"][0]}'
    # Uses the text from the card's header for the title of the smart chip.
    return {
        "action": {
            "linkPreview": {
                "title": name,
                "previewCard": {
                    "header": {
                        "title": name
                    },
                    "sections": [{
                        "widgets": [{
                            "textParagraph": {
                                "text": query_string["description"][0]
                            }
                        }]
                    }],
                }
            }
        }
    }

جاوا

java/3p-resources/src/main/java/CreateLinkPreview.java
/**
 * A support case link preview.
 *
 * @param url A matching URL.
 * @return The resulting preview link card.
 */
JsonObject caseLinkPreview(URL url) throws UnsupportedEncodingException {
  // Parses the URL and identify the case details.
  Map<String, String> caseDetails = new HashMap<String, String>();
  for (String pair : url.getQuery().split("&")) {
      caseDetails.put(URLDecoder.decode(pair.split("=")[0], "UTF-8"), URLDecoder.decode(pair.split("=")[1], "UTF-8"));
  }

  // Builds a preview card with the case name, and description
  // Uses the text from the card's header for the title of the smart chip.
  JsonObject cardHeader = new JsonObject();
  String caseName = String.format("Case %s", caseDetails.get("name"));
  cardHeader.add("title", new JsonPrimitive(caseName));

  JsonObject textParagraph = new JsonObject();
  textParagraph.add("text", new JsonPrimitive(caseDetails.get("description")));

  JsonObject widget = new JsonObject();
  widget.add("textParagraph", textParagraph);

  JsonArray widgets = new JsonArray();
  widgets.add(widget);

  JsonObject section = new JsonObject();
  section.add("widgets", widgets);

  JsonArray sections = new JsonArray();
  sections.add(section);

  JsonObject previewCard = new JsonObject();
  previewCard.add("header", cardHeader);
  previewCard.add("sections", sections);

  JsonObject linkPreview = new JsonObject();
  linkPreview.add("title", new JsonPrimitive(caseName));
  linkPreview.add("previewCard", previewCard);

  JsonObject action = new JsonObject();
  action.add("linkPreview", linkPreview);

  JsonObject renderActions = new JsonObject();
  renderActions.add("action", action);

  return renderActions;
}

اجزای پشتیبانی شده برای کارت‌های پیش‌نمایش

افزونه‌های Google Workspace از ابزارک‌ها و اقدامات زیر برای کارت‌های پیش‌نمایش لینک پشتیبانی می‌کنند:

اسکریپت برنامه‌ها

فیلد خدمات کارت نوع
TextParagraph ویجت
DecoratedText ویجت
Image ویجت
IconImage ویجت
ButtonSet ویجت
TextButton ویجت
ImageButton ویجت
Grid ویجت
Divider ویجت
OpenLink اکشن
Navigation اکشن
فقط متد updateCard پشتیبانی می‌شود.

جی‌سون

فیلد کارت ( google.apps.card.v1 ) نوع
TextParagraph ویجت
DecoratedText ویجت
Image ویجت
Icon ویجت
ButtonList ویجت
Button ویجت
Grid ویجت
Divider ویجت
OpenLink اکشن
Navigation اکشن
فقط متد updateCard پشتیبانی می‌شود.

مثال کامل: افزونه‌ی مورد پشتیبانی

مثال زیر یک افزونه Google Workspace را نشان می‌دهد که لینک‌های مربوط به پرونده‌های پشتیبانی یک شرکت را در Google Docs پیش‌نمایش می‌دهد.

مثال زیر موارد زیر را انجام می‌دهد:

  • پیش‌نمایش پیوندهای مربوط به موارد پشتیبانی، مانند https://www.example.com/support/cases/1234 . تراشه هوشمند یک نماد پشتیبانی را نمایش می‌دهد و کارت پیش‌نمایش شامل شناسه مورد و توضیحات است.
  • اگر زبان کاربر روی اسپانیایی تنظیم شده باشد، تراشه هوشمند labelText خود را به اسپانیایی ترجمه می‌کند.

مانیفست

اسکریپت برنامه‌ها

اسکریپت برنامه‌ها/3p-resources/appsscript.json
{
  "timeZone": "America/New_York",
  "exceptionLogging": "STACKDRIVER",
  "runtimeVersion": "V8",
  "oauthScopes": [
    "https://www.googleapis.com/auth/workspace.linkpreview",
    "https://www.googleapis.com/auth/workspace.linkcreate"
  ],
  "addOns": {
    "common": {
      "name": "Manage support cases",
      "logoUrl": "https://developers.google.com/workspace/add-ons/images/support-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"
        }
      ],
      "createActionTriggers": [
        {
          "id": "createCase",
          "labelText": "Create support case",
          "localizedLabelText": {
            "es": "Crear caso de soporte"
          },
          "runFunction": "createCaseInputCard",
          "logoUrl": "https://developers.google.com/workspace/add-ons/images/support-icon.png"
        }
      ]
    }
  }
}

جی‌سون

{
  "oauthScopes": [
    "https://www.googleapis.com/auth/workspace.linkpreview"
  ],
  "addOns": {
    "common": {
      "name": "Preview support cases",
      "logoUrl": "https://developers.google.com/workspace/add-ons/images/support-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"
        }
      ]
    }
  }
}

کد

اسکریپت برنامه‌ها

apps-script/3p-resources/3p-resources.gs
/**
* Entry point for a support case link preview.
*
* @param {!Object} event The event object.
* @return {!Card} The resulting preview link card.
*/
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 details.
    const caseDetails = parseQuery(event.docs.matchedUrl.url);

    // Builds a preview card with the case name, and description
    const caseHeader = CardService.newCardHeader()
      .setTitle(`Case ${caseDetails["name"][0]}`);
    const caseDescription = CardService.newTextParagraph()
      .setText(caseDetails["description"][0]);

    // 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();
  }
}

/**
* Extracts the URL parameters from the given URL.
*
* @param {!string} url The URL to parse.
* @return {!Map} A map with the extracted URL parameters.
*/
function parseQuery(url) {
  const query = url.split("?")[1];
  if (query) {
    return query.split("&")
    .reduce(function(o, e) {
      var temp = e.split("=");
      var key = temp[0].trim();
      var value = temp[1].trim();
      value = isNaN(value) ? value : Number(value);
      if (o[key]) {
        o[key].push(value);
      } else {
        o[key] = [value];
      }
      return o;
    }, {});
  }
  return null;
}

نود جی اس

گره/3p-resources/index.js
/**
 * Responds to any HTTP request related to link previews.
 *
 * @param {Object} req An HTTP request context.
 * @param {Object} res An HTTP response context.
 */
exports.createLinkPreview = (req, res) => {
  const event = req.body;
  if (event.docs.matchedUrl.url) {
    const url = event.docs.matchedUrl.url;
    const parsedUrl = new URL(url);
    // If the event object URL matches a specified pattern for preview links.
    if (parsedUrl.hostname === 'example.com') {
      if (parsedUrl.pathname.startsWith('/support/cases/')) {
        return res.json(caseLinkPreview(parsedUrl));
      }
    }
  }
};


/**
 * 
 * A support case link preview.
 *
 * @param {!URL} url The event object.
 * @return {!Card} The resulting preview link card.
 */
function caseLinkPreview(url) {
  // Builds a preview card with the case name, and description
  // Uses the text from the card's header for the title of the smart chip.
  // Parses the URL and identify the case details.
  const name = `Case ${url.searchParams.get("name")}`;
  return {
    action: {
      linkPreview: {
        title: name,
        previewCard: {
          header: {
            title: name
          },
          sections: [{
            widgets: [{
              textParagraph: {
                text: url.searchParams.get("description")
              }
            }]
          }]
        }
      }
    }
  };
}

پایتون

پایتون/3p-resources/create_link_preview/main.py
from typing import Any, Mapping
from urllib.parse import urlparse, parse_qs

import flask
import functions_framework


@functions_framework.http
def create_link_preview(req: flask.Request):
    """Responds to any HTTP request related to link previews.
    Args:
      req: An HTTP request context.
    Returns:
      An HTTP response context.
    """
    event = req.get_json(silent=True)
    if event["docs"]["matchedUrl"]["url"]:
        url = event["docs"]["matchedUrl"]["url"]
        parsed_url = urlparse(url)
        # If the event object URL matches a specified pattern for preview links.
        if parsed_url.hostname == "example.com":
            if parsed_url.path.startswith("/support/cases/"):
                return case_link_preview(parsed_url)

    return {}




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

    # Parses the URL and identify the case details.
    query_string = parse_qs(url.query)
    name = f'Case {query_string["name"][0]}'
    # Uses the text from the card's header for the title of the smart chip.
    return {
        "action": {
            "linkPreview": {
                "title": name,
                "previewCard": {
                    "header": {
                        "title": name
                    },
                    "sections": [{
                        "widgets": [{
                            "textParagraph": {
                                "text": query_string["description"][0]
                            }
                        }]
                    }],
                }
            }
        }
    }

جاوا

java/3p-resources/src/main/java/CreateLinkPreview.java
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.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;

import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.Map;

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

  /**
   * Responds to any HTTP request related to link previews.
   *
   * @param request An HTTP request context.
   * @param response An HTTP response context.
   */
  @Override
  public void service(HttpRequest request, HttpResponse response) throws Exception {
    JsonObject event = gson.fromJson(request.getReader(), JsonObject.class);
    String url = event.getAsJsonObject("docs")
        .getAsJsonObject("matchedUrl")
        .get("url")
        .getAsString();
    URL parsedURL = new URL(url);
    // If the event object URL matches a specified pattern for preview links.
    if ("example.com".equals(parsedURL.getHost())) {
      if (parsedURL.getPath().startsWith("/support/cases/")) {
        response.getWriter().write(gson.toJson(caseLinkPreview(parsedURL)));
        return;
      }
    }

    response.getWriter().write("{}");
  }


  /**
   * A support case link preview.
   *
   * @param url A matching URL.
   * @return The resulting preview link card.
   */
  JsonObject caseLinkPreview(URL url) throws UnsupportedEncodingException {
    // Parses the URL and identify the case details.
    Map<String, String> caseDetails = new HashMap<String, String>();
    for (String pair : url.getQuery().split("&")) {
        caseDetails.put(URLDecoder.decode(pair.split("=")[0], "UTF-8"), URLDecoder.decode(pair.split("=")[1], "UTF-8"));
    }

    // Builds a preview card with the case name, and description
    // Uses the text from the card's header for the title of the smart chip.
    JsonObject cardHeader = new JsonObject();
    String caseName = String.format("Case %s", caseDetails.get("name"));
    cardHeader.add("title", new JsonPrimitive(caseName));

    JsonObject textParagraph = new JsonObject();
    textParagraph.add("text", new JsonPrimitive(caseDetails.get("description")));

    JsonObject widget = new JsonObject();
    widget.add("textParagraph", textParagraph);

    JsonArray widgets = new JsonArray();
    widgets.add(widget);

    JsonObject section = new JsonObject();
    section.add("widgets", widgets);

    JsonArray sections = new JsonArray();
    sections.add(section);

    JsonObject previewCard = new JsonObject();
    previewCard.add("header", cardHeader);
    previewCard.add("sections", sections);

    JsonObject linkPreview = new JsonObject();
    linkPreview.add("title", new JsonPrimitive(caseName));
    linkPreview.add("previewCard", previewCard);

    JsonObject action = new JsonObject();
    action.add("linkPreview", linkPreview);

    JsonObject renderActions = new JsonObject();
    renderActions.add("action", action);

    return renderActions;
  }

}