Akıllı çiplerle bağlantıları önizleme

Bu sayfada Google Dokümanlar, E-Tablolar ve Slaytlar kullanıcılarının üçüncü taraf bir hizmetten bağlantıları önizlemesine olanak tanıyan bir Google Workspace Eklentisini nasıl oluşturacağınız açıklanmaktadır.

Google Workspace Eklentisi, hizmetinizin bağlantılarını algılayıp kullanıcılardan bunları önizlemelerini isteyebilir. Destek vakalarına, satış potansiyellerine ve çalışan profillerine bağlantılar gibi birden fazla URL kalıbını önizlemek için bir eklenti yapılandırabilirsiniz.

Kullanıcılar bağlantıları nasıl önizler?

Kullanıcılar, bağlantıları önizlemek için akıllı çipler ve kartlarla etkileşimde bulunur.

Kullanıcı bir kartı önizler

Kullanıcılar bir dokümana URL yazdığında veya yapıştırdığında Google Dokümanlar, bağlantıyı akıllı çiple değiştirmelerini ister. Akıllı çipte, bağlantı içeriğinin kısa bir başlığı veya açıklaması gösterilir. Kullanıcı fareyle çipin üzerine geldiğinde dosya veya bağlantı hakkında daha fazla bilginin önizlemesini gösteren bir kart arayüzü görür.

Aşağıdaki videoda kullanıcının bağlantıyı akıllı çipe nasıl dönüştürdüğü ve kartı nasıl önizlediği gösterilmektedir:

Kullanıcılar E-Tablolar ve Slaytlar'da bağlantıları nasıl önizler?

E-Tablolar ve Slaytlar'da bağlantı önizlemeleri için üçüncü taraf akıllı çipleri desteklenmez. Kullanıcılar bir e-tabloya veya sunuya bir URL yazdığında ya da yapıştırdığında E-Tablolar veya Slaytlar, kullanıcılardan bağlantıyı çip yerine bağlantı metni olarak başlıkla değiştirmelerini ister. Kullanıcı, imleci bağlantı başlığının üzerine getirdiğinde bağlantıyla ilgili bilgilerin önizlemesini gösteren bir kart arayüzü görür.

Aşağıdaki resimde, bir bağlantı önizlemesinin E-Tablolar ve Slaytlar'da nasıl oluşturulduğu gösterilmektedir:

E-Tablolar ve Slaytlar için bağlantı önizlemesi örneği

Ön koşullar

Apps Komut Dosyası

Node.js

olarak çalışacak şekilde yazılmıştır

Python

Java

İsteğe bağlı: Üçüncü taraf hizmeti için kimlik doğrulamayı ayarlama

Eklentiniz yetkilendirme gerektiren bir hizmete bağlanırsa kullanıcıların bağlantıları önizlemek için hizmetle kimlik doğrulaması yapması gerekir. Diğer bir deyişle, kullanıcılar hizmetinizden bir bağlantıyı ilk kez bir Dokümanlar, E-Tablolar veya Slaytlar dosyasına yapıştırdığında, eklentinizin yetkilendirme akışını çağırması gerekir.

OAuth hizmeti veya özel yetkilendirme istemi ayarlamak için aşağıdaki kılavuzlardan birine bakın:

Bu bölümde, eklentiniz için bağlantı önizlemelerini nasıl ayarlayacağınız açıklanmaktadır. Bu süreç, aşağıdaki adımları içerir:

  1. Eklentinizin dağıtım kaynağında veya manifest dosyasında bağlantı önizlemelerini yapılandırın.
  2. Bağlantılarınız için akıllı çip ve kart arayüzü oluşturun.

Bağlantı önizlemelerini yapılandırma

Bağlantı önizlemelerini yapılandırmak için eklentinizin dağıtım kaynağında veya manifest dosyasında aşağıdaki bölümleri ve alanları belirtin:

  1. addOns bölümünde, Dokümanlar'ı genişletmek için docs alanını, E-Tablolar'ı genişletmek için sheets alanını ve Slaytlar'ı genişletmek için slides alanını ekleyin.
  2. Her alanda, runFunction içeren linkPreviewTriggers tetikleyicisini uygulayın (Bu işlevi Akıllı çip ve kart oluşturma bölümünde tanımlarsınız).

    linkPreviewTriggers tetikleyicisinde hangi alanları belirtebileceğiniz hakkında bilgi edinmek için Apps Komut Dosyası manifest dosyaları veya diğer çalışma zamanları için dağıtım kaynaklarına yönelik referans belgelerine bakın.

  3. Kullanıcıların, bağlantıları kendi adlarına önizlemeleri için eklentiyi yetkilendirebilmesi için oauthScopes alanına https://www.googleapis.com/auth/workspace.linkpreview kapsamını ekleyin.

Örnek olarak, bir destek kaydı hizmeti için bağlantı önizlemelerini yapılandıran aşağıdaki dağıtım kaynağının oauthScopes ve addons bölümüne bakın.

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

Örnekte, Google Workspace Eklentisi, bir şirketin destek kaydı hizmetinin bağlantılarını önizler. Eklenti, önizleme bağlantıları için üç URL kalıbı belirtir. Bir bağlantı, URL kalıplarından biriyle eşleştiğinde, caseLinkPreview geri çağırma işlevi bir kart ve akıllı çip oluşturup görüntüler veya E-Tablolar ve Slaytlar'da, URL'yi bağlantı başlığıyla değiştirir.

Akıllı çip ve kart oluşturun

Bir bağlantı için akıllı çip ve kart döndürmek istiyorsanız linkPreviewTriggers nesnesinde belirttiğiniz tüm işlevleri uygulamanız gerekir.

Bir kullanıcı, belirtilen URL kalıbıyla eşleşen bir bağlantıyla etkileşimde bulunduğunda linkPreviewTriggers tetikleyicisi etkinleşir ve geri çağırma işlevi EDITOR_NAME.matchedUrl.url etkinlik nesnesini bağımsız değişken olarak iletir. Bağlantı önizlemeniz için akıllı çip ve kart oluşturmak amacıyla bu etkinlik nesnesinin yükünü kullanırsınız.

Örneğin, bir kullanıcı Dokümanlar'da https://www.example.com/cases/123456 bağlantısını önizlerse aşağıdaki etkinlik yükü döndürülür:

JSON

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

Kart arayüzünü oluşturmak için bağlantıyla ilgili bilgileri görüntülemek üzere widget'ları kullanırsınız. Ayrıca, kullanıcıların bağlantıyı açmasına veya içeriğini değiştirmesine olanak tanıyan işlemler de oluşturabilirsiniz. Kullanılabilir widget'ların ve işlemlerin listesi için Önizleme kartları için desteklenen bileşenler bölümüne bakın.

Bağlantı önizlemesi için akıllı çip ve kart oluşturmak isterseniz:

  1. Eklentinizin dağıtım kaynağı veya manifest dosyasındaki linkPreviewTriggers bölümünde belirttiğiniz işlevi uygulayın:
    1. İşlev, bağımsız değişken olarak EDITOR_NAME.matchedUrl.url içeren bir etkinlik nesnesini kabul etmeli ve tek bir Card nesnesi döndürmelidir.
    2. Hizmetiniz yetkilendirme gerektiriyorsa işlevin yetkilendirme akışını da çağırması gerekir.
  2. Her bir önizleme kartında, arayüzde widget etkileşimi sağlayan geri çağırma işlevlerini uygulayın. Örneğin, "Bağlantıyı görüntüle" yazan bir düğme eklerseniz bağlantıyı yeni bir pencerede açmak için geri çağırma işlevi belirten bir işlem oluşturabilirsiniz. Widget etkileşimleri hakkında daha fazla bilgi edinmek için Eklenti işlemleri konusuna bakın.

Aşağıdaki kod, Dokümanlar için caseLinkPreview geri çağırma işlevini oluşturur:

Apps Komut Dosyası

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;
}

Node.js

Node/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")
              }
            }]
          }]
        }
      }
    }
  };
}

Python

python/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

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;
}

Önizleme kartları için desteklenen bileşenler

Google Workspace Eklentileri, bağlantı önizleme kartları için aşağıdaki widget'ları ve işlemleri destekler:

Apps Komut Dosyası

Kart Hizmeti alanı Tür
TextParagraph Widget
DecoratedText Widget
Image Widget
IconImage Widget
ButtonSet Widget
TextButton Widget
ImageButton Widget
Grid Widget
Divider Widget
OpenLink İşlem
Navigation İşlem
Yalnızca updateCard yöntemi desteklenir.

JSON

Kart (google.apps.card.v1) alanı Tür
TextParagraph Widget
DecoratedText Widget
Image Widget
Icon Widget
ButtonList Widget
Button Widget
Grid Widget
Divider Widget
OpenLink İşlem
Navigation İşlem
Yalnızca updateCard yöntemi desteklenir.

Tam örnek: Destek kaydı eklentisi

Aşağıdaki örnekte, bir şirketin Google Dokümanlar'daki destek yazışmalarının bağlantılarını önizleyen bir Google Workspace Eklentisi yer almaktadır.

Örnekte aşağıdakiler gerçekleşir:

  • https://www.example.com/support/cases/1234 gibi destek kaydı bağlantılarını önizler. Akıllı çipte bir destek simgesi gösterilir. Önizleme kartında ise destek kaydı kimliği ve açıklama bulunur.
  • Kullanıcının yerel ayarı İspanyolca olarak ayarlanırsa akıllı çip, labelText bilgisini İspanyolcaya yerelleştirir.

Dağıtım kaynağı

Apps Komut Dosyası

apps-script/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"
        }
      ]
    }
  }
}

JSON

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

Kod

Apps Komut Dosyası

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;
}

Node.js

Node/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")
              }
            }]
          }]
        }
      }
    }
  };
}

Python

python/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

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;
  }

}