Google Chat kullanıcılarından bilgi toplama ve işleme

Bu kılavuzda, Google Chat uygulamalarının kart tabanlı arayüzlerde form girişleri oluşturarak kullanıcılardan nasıl bilgi toplayıp işleyebileceği açıklanmaktadır.

Çeşitli widget'ların yer aldığı bir iletişim kutusu.
Şekil 1: İletişim bilgilerini toplamak için iletişim kutusu açan örnek bir Chat uygulaması.

Chat uygulamaları, Chat'te veya Chat dışında işlem yapmak için kullanıcılardan bilgi ister. Bu işlemler arasında şunlar yer alır:

  • Ayarları yapılandırın. Örneğin, kullanıcıların bildirim ayarlarını özelleştirmesine veya Chat uygulamasını yapılandırıp bir ya da daha fazla alana eklemesine olanak tanımak için.
  • Diğer Google Workspace uygulamalarında bilgi oluşturma veya güncelleme Örneğin, kullanıcıların Google Takvim etkinliği oluşturmasına izin verebilirsiniz.
  • Kullanıcıların diğer uygulamalardaki veya web hizmetlerindeki kaynaklara erişmesine ve bunları güncellemesine izin verin. Örneğin, bir Chat uygulaması, kullanıcıların destek kaydının durumunu doğrudan bir Chat alanından güncellemesine yardımcı olabilir.

Ön koşullar

HTTP

Kullanıcı etkileşimlerini alıp yanıtlayan bir Google Chat uygulaması. HTTP uç noktası oluşturmak için HTTP hızlı başlangıç kılavuzunu tamamlayın.

Apps Komut Dosyası

Kullanıcı etkileşimlerini alıp yanıtlayan bir Google Chat uygulaması. Eklenti oluşturmak için Apps Komut Dosyası hızlı başlangıç kılavuzunu tamamlayın.

Kartları kullanarak form oluşturma

Chat uygulamaları, bilgi toplamak için formlar ve form girişleri tasarlayıp bunları kartlara yerleştirir. Chat uygulamaları, kullanıcılara kart göstermek için aşağıdaki Chat arayüzlerini kullanabilir:

  • Bir veya daha fazla kart içeren mesajlar.
  • Ana sayfalar: Chat uygulamasıyla doğrudan mesajlarda Ana Sayfa sekmesinden görüntülenen bir karttır.
  • Mesajlardan ve ana sayfalardan yeni bir pencerede açılan kartlar olan iletişim kutuları.

Chat uygulamaları, aşağıdaki widget'ları kullanarak kart oluşturabilir:

  • Kullanıcılardan bilgi isteyen form girişi widget'ları. İsteğe bağlı olarak, kullanıcıların bilgileri doğru şekilde girmesini ve biçimlendirmesini sağlamak için form giriş widget'larına doğrulama ekleyebilirsiniz. Sohbet Uygulamaları aşağıdaki form girişi widget'larını kullanabilir:

    • Serbest biçimli veya önerilen metin için metin girişleri (textInput).
    • Seçim girişleri (selectionInput); onay kutuları, radyo düğmeleri ve açılır menüler gibi seçilebilir kullanıcı arayüzü öğeleridir. Seçim girişi widget'ları, Google Workspace verilerinden (ör. Chat alanı) veya dinamik bir veri kaynağından öğeleri doldurup önerebilir. Ayrıntılar için aşağıdaki Açılır menü ekleme ve Çoklu seçim menüsü ekleme bölümlerine bakın.
    • Tarih ve saat seçiciler (dateTimePicker) tarih ve saat girişleri için kullanılır.
  • Kullanıcıların karta girdikleri değerleri gönderebilmeleri için bir düğme widget'ı. Kullanıcı düğmeyi tıkladıktan sonra Chat uygulaması aldığı bilgileri işleyebilir.

Aşağıdaki örnekte, bir kart metin girişi, tarih saat seçici ve seçim girişi kullanarak iletişim bilgilerini toplar:

Bilgi toplamak için kullanabileceğiniz etkileşimli widget'larla ilgili daha fazla örnek için Etkileşimli kart veya iletişim kutusu tasarlama başlıklı makaleyi inceleyin.

Açılır menü ekleme

Chat uygulamaları, seçim öğelerini özelleştirmek veya kullanıcıların dinamik bir veri kaynağından tek bir öğe seçmesine olanak tanımak için bir tür SelectionInput widget'ı olan açılır menüleri kullanabilir. Örneğin, aşağıdaki kartta kullanıcıların bir kişi listesinden dinamik olarak seçim yapabileceği bir açılır menü gösterilmektedir:

Açılır menüdeki öğeleri aşağıdaki veri kaynaklarından doldurabilirsiniz:

Google Workspace veri kaynağından öğe ekleme

Google Workspace kullanıcıları gibi Google Workspace veri kaynaklarından öğeleri doldurmak için bir DataSourceConfig nesnesinde platformDataSource alanını belirtin. Diğer seçim girişi türlerinin aksine, bu seçim öğeleri Google Workspace'ten dinamik olarak alındığı için SelectionItem nesnelerini atlarsınız.

Aşağıdaki kodda, Google Workspace kullanıcılarının açılır menüsü gösterilmektedir:

JSON

{
  "sections": [
    {
      "header": "Section Header",
      "widgets": [
        {
          "selectionInput": {
            "name": "contacts",
            "type": "DROPDOWN",
            "label": "Select contact from organization",
            "dataSourceConfigs": [
              {
                "platformDataSource": {
                  "commonDataSource": "USER"
                },
                "minCharactersTrigger": 1
              }
            ]
          }
        }
      ]
    }
  ]
}

Öğeleri harici bir veri kaynağından doldurma

Açılır menüler, üçüncü taraf veya harici bir veri kaynağından da öğe doldurabilir. Harici bir veri kaynağı kullanmak için, veri kaynağından öğeleri sorgulayan ve döndüren işlevi içeren bir DataSourceConfig nesnesinde remoteDataSource alanını belirtirsiniz.

Harici bir veri kaynağına gönderilen istekleri azaltmak için, kullanıcılar menüye yazmadan önce açılır menüde görünen önerilen öğeleri ekleyebilirsiniz. Önerilen öğeleri harici bir veri kaynağından doldurmak için statik SelectionItem nesneleri belirtin.

Aşağıdaki kodda, harici bir veri kaynağından öğeleri sorgulayan ve dolduran bir açılır menü gösterilmektedir:

JSON

{
  "sections": [
    {
      "header": "Section Header",
      "widgets": [
        {
          "selectionInput": {
            "name": "crm_leads",
            "type": "DROPDOWN",
            "label": "Select CRM Lead",
            "dataSourceConfigs": [
              {
                "remoteDataSource": {
                  "function": "getCrmLeads"
                },
                "minCharactersTrigger": 2
              }
            ],
            "items": [
              {
                "text": "Suggested Lead 1",
                "value": "lead-1"
              }
            ]
          }
        }
      ]
    }
  ]
}

Önerilen öğelerin nasıl döndürüleceğini gösteren eksiksiz bir örnek için Seçim öğeleri önerme bölümüne bakın.

Çoklu seçim menüsü ekleme

Chat uygulamaları, seçim öğelerini özelleştirmek veya kullanıcıların dinamik bir veri kaynağından öğe seçmesine olanak tanımak için çoklu seçim menülerini kullanabilir. Çoklu seçim menüleri, bir tür SelectionInput widget'ıdır. Örneğin, aşağıdaki kartta kullanıcıların bir kişi listesinden dinamik olarak seçim yapabileceği çoklu seçim menüsü gösterilmektedir:

Çoklu seçim menüsünün öğelerini aşağıdaki veri kaynaklarından doldurabilirsiniz:

  • Kullanıcıları veya kullanıcının üyesi olduğu Chat alanlarını içeren Google Workspace verileri. Menüde yalnızca aynı Google Workspace kuruluşundaki öğeler gösterilir.
  • Harici veri kaynakları (ör. ilişkisel veritabanı) Örneğin, bir kullanıcının müşteri ilişkileri yönetimi (CRM) sistemindeki olası satış listesinden seçim yapmasına yardımcı olmak için çoklu seçim menülerini kullanabilirsiniz.

Google Workspace veri kaynağından öğe doldurma

Google Workspace veri kaynaklarını kullanmak için SelectionInput widget'ında platformDataSource alanını belirtin. Diğer seçim girişi türlerinin aksine, bu seçim öğeleri Google Workspace'ten dinamik olarak alındığı için SelectionItem nesnelerini atlarsınız.

Aşağıdaki kodda, Google Workspace kullanıcılarının çoklu seçim menüsü gösterilmektedir. Kullanıcıları doldurmak için seçim girişi, commonDataSource değerini USER olarak ayarlar:

JSON

{
  "selectionInput": {
    "name": "contacts",
    "type": "MULTI_SELECT",
    "label": "Selected contacts",
    "multiSelectMaxSelectedItems": 5,
    "multiSelectMinQueryLength": 1,
    "platformDataSource": {
      "commonDataSource": "USER"
    }
  }
}

Aşağıdaki kodda, Chat alanlarının çoklu seçim menüsü gösterilmektedir. Seçim girişi, alanları doldurmak için hostAppDataSource alanını belirtir. Çoklu seçim menüsü, defaultToCurrentSpace değerini true olarak ayarlar. Bu sayede, mevcut alan menüdeki varsayılan seçim olur:

JSON

{
  "selectionInput": {
    "name": "spaces",
    "type": "MULTI_SELECT",
    "label": "Selected contacts",
    "multiSelectMaxSelectedItems": 3,
    "multiSelectMinQueryLength": 1,
    "platformDataSource": {
      "hostAppDataSource": {
        "chatDataSource": {
          "spaceDataSource": {
            "defaultToCurrentSpace": true
          }
        }
      }
    }
  }
}

Öğeleri harici bir veri kaynağından doldurma

Çoklu seçim menüleri, üçüncü taraf veya harici bir veri kaynağından da öğe doldurabilir. Harici bir veri kaynağı kullanmak için SelectionInput widget'ında, veri kaynağından öğeleri sorgulayan ve döndüren işlevi içeren externalDataSource alanını belirtirsiniz.

Harici bir veri kaynağına gönderilen istekleri azaltmak için, kullanıcılar menüye yazmadan önce çoklu seçim menüsünde görünen önerilen öğeleri ekleyebilirsiniz. Örneğin, kullanıcı için son aranan kişileri doldurabilirsiniz. Önerilen öğeleri harici bir veri kaynağından doldurmak için statik SelectionItem nesneleri belirtin.

Aşağıdaki kod örneğinde, harici bir veri kaynağından öğeleri sorgulayan ve dolduran çoklu seçim menüsü gösterilmektedir:

Node.js

node/chat/selection-input/index.js
selectionInput: {
  name: "contacts",
  type: "MULTI_SELECT",
  label: "Selected contacts",
  multiSelectMaxSelectedItems: 3,
  multiSelectMinQueryLength: 1,
  externalDataSource: { function: FUNCTION_URL },
  // Suggested items loaded by default.
  // The list is static here but it could be dynamic.
  items: [getSuggestedContact("3")]
}

FUNCTION_URL yerine harici veri kaynağını sorgulayan HTTP uç noktasını yazın.

Python

python/chat/selection-input/main.py
'selectionInput': {
  'name': "contacts",
  'type': "MULTI_SELECT",
  'label': "Selected contacts",
  'multiSelectMaxSelectedItems': 3,
  'multiSelectMinQueryLength': 1,
  'externalDataSource': { 'function': FUNCTION_URL },
  # Suggested items loaded by default.
  # The list is static here but it could be dynamic.
  'items': [get_suggested_contact("3")]
}

FUNCTION_URL yerine harici veri kaynağını sorgulayan HTTP uç noktasını yazın.

Java

java/chat/selection-input/src/main/java/com/google/chat/selectionInput/App.java
.setSelectionInput(new GoogleAppsCardV1SelectionInput()
  .setName("contacts")
  .setType("MULTI_SELECT")
  .setLabel("Selected contacts")
  .setMultiSelectMaxSelectedItems(3)
  .setMultiSelectMinQueryLength(1)
  .setExternalDataSource(new GoogleAppsCardV1Action().setFunction(FUNCTION_URL))
  // Suggested items loaded by default.
  // The list is static here but it could be dynamic.
  .setItems(List.of(getSuggestedContact("3")))))))))));

FUNCTION_URL yerine harici veri kaynağını sorgulayan HTTP uç noktasını yazın.

Apps Komut Dosyası

Bu örnekte, kart JSON'u döndürülerek bir kart mesajı gönderilir. Apps Komut Dosyası kart hizmetini de kullanabilirsiniz.

apps-script/chat/selection-input/selection-input.gs
selectionInput: {
  name: "contacts",
  type: "MULTI_SELECT",
  label: "Selected contacts",
  multiSelectMaxSelectedItems: 3,
  multiSelectMinQueryLength: 1,
  externalDataSource: { function: "queryContacts" },
  // Suggested items loaded by default.
  // The list is static here but it could be dynamic.
  items: [getSuggestedContact("3")]
}

Önerilen öğelerin nasıl döndürüleceğini gösteren eksiksiz bir örnek için Seçim öğeleri önerme bölümüne bakın.

Etkileşimli widget'lardan veri alma

Kullanıcılar bir düğmeyi her tıkladığında, etkileşimle ilgili bilgilerle birlikte Chat uygulamasının işlemi tetiklenir. Etkinlik yükünün commonEventObject bölümünde, formInputs nesnesi kullanıcının girdiği tüm değerleri içerir.

Değerleri event.commonEventObject.formInputs.WIDGET_NAME nesnesinden alabilirsiniz. Burada WIDGET_NAME, widget için belirttiğiniz name alanıdır. Değerler, widget için belirli bir veri türü olarak döndürülür.

Aşağıda, kullanıcının her widget için değer girdiği bir olay nesnesinin bir kısmı gösterilmektedir:

{
  "commonEventObject": { "formInputs": {
    "contactName": { "stringInputs": {
      "value": ["Kai 0"]
    }},
    "contactBirthdate": { "dateInput": {
      "msSinceEpoch": 1000425600000
    }},
    "contactType": { "stringInputs": {
      "value": ["Personal"]
    }}
  }}
}

Chat uygulamanız, verileri almak için kullanıcıların widget'lara girdiği değerleri almak üzere olay nesnesini işler. Aşağıdaki tabloda, belirli bir form girişi widget'ının değerinin nasıl alınacağı gösterilmektedir. Tabloda her widget için widget'ın kabul ettiği veri türü, değerin olay nesnesinde depolandığı yer ve örnek bir değer gösterilir.

Form girişi widget'ı Giriş verilerinin türü Olay nesnesinden giriş değeri Örnek değer
textInput stringInputs event.commonEventObject.formInputs.contactName.stringInputs.value[0] Kai O
selectionInput stringInputs İlk veya tek değeri almak için event.commonEventObject.formInputs.contactType.stringInputs.value[0] Personal
Yalnızca tarihleri kabul eden dateTimePicker. dateInput event.commonEventObject.formInputs.contactBirthdate.dateInput.msSinceEpoch. 1000425600000

Chat uygulaması, verileri aldıktan sonra aşağıdakilerden herhangi birini yapabilir:

Seçim öğeleri önerme

Bir kartta, harici bir veri kaynağından öğelerle doldurulan çoklu seçim menüsü veya açılır menü varsa Chat uygulaması, kullanıcıların menüye yazdıklarına göre önerilen öğeler döndürebilir. Örneğin, bir kullanıcı ABD'deki şehirleri dolduran bir menü için Atl yazmaya başlarsa Chat uygulamanız, kullanıcı yazmayı bitirmeden önce Atlanta ifadesini otomatik olarak önerebilir. Chat uygulaması en fazla 100 öğe önerebilir.

Seçim girişindeki öğeleri önermek ve dinamik olarak doldurmak için karttaki SelectionInput widget'ı, harici veri kaynağını sorgulayan bir işlev belirtmelidir. Çoklu seçim menüleri için externalDataSource alanını belirtirsiniz. Açılır menüler için bir DataSourceConfig nesnesinde remoteDataSource alanını belirtirsiniz.

Menüde öneriler gösterilmeden önce kullanıcının yazması gereken karakter sayısını da yapılandırabilirsiniz. Çoklu seçim menüleri için multiSelectMinQueryLength alanını ayarlayın. Açılır menüler için DataSourceConfig içindeki min_characters_trigger alanını ayarlayın.

Önerilen öğeleri döndürmek için işlevin aşağıdakileri yapması gerekir:

  1. Kullanıcılar menüye yazdığında Chat uygulamasının aldığı bir olay nesnesini işleyin.
  2. Olay nesnesinden, kullanıcının yazdığı değeri alın. Bu değer, event.commonEventObject.parameters["autocomplete_widget_query"] alanında gösterilir.
  3. Kullanıcıya önerilecek bir veya daha fazla SelectionItems almak için kullanıcı giriş değerini kullanarak veri kaynağını sorgulayın.
  4. modifyCard nesnesiyle RenderActions işlemini döndürerek önerilen öğeleri döndürün.

Aşağıdaki kod örneğinde, bir Chat uygulamasının karttaki çoklu seçim menüsünde öğeleri dinamik olarak nasıl önerdiği gösterilmektedir. Kullanıcı menüye bir şey yazdığında widget'ın externalDataSource alanında sağlanan işlev veya uç nokta, harici bir veri kaynağını sorgular ve kullanıcının seçebileceği öğeler önerir.

Node.js

node/chat/selection-input/index.js
/**
 * Web app that responds to events sent from a Google Chat space.
 *
 * @param {Object} req Request sent from Google Chat space
 * @param {Object} res Response to send back
 */
app.post('/', async (req, res) => {
  // Stores the Google Chat event
  const chatEvent = req.body.chat;

  // Handle user interaction with multiselect.
  if(chatEvent.widgetUpdatedPayload) {
    return res.json(queryContacts(req.body));
  }

  // Replies with a card that contains the multiselect menu.
  return res.json({ hostAppDataAction: { chatDataAction: { createMessageAction: { message: {
    cardsV2: [{
      cardId: "contactSelector",
      card: { sections:[{ widgets: [{
        selectionInput: {
          name: "contacts",
          type: "MULTI_SELECT",
          label: "Selected contacts",
          multiSelectMaxSelectedItems: 3,
          multiSelectMinQueryLength: 1,
          externalDataSource: { function: FUNCTION_URL },
          // Suggested items loaded by default.
          // The list is static here but it could be dynamic.
          items: [getSuggestedContact("3")]
        }
      }]}]}
    }]
  }}}}});
});

/**
 * Get contact suggestions based on text typed by users.
 *
 * @param {Object} event the event object that contains the user's query
 * @return {Object} suggestions
 */
function queryContacts(event) {
  const query = event.commonEventObject.parameters["autocomplete_widget_query"];
  return { action: { modifyOperations: [{ updateWidget: { selectionInputWidgetSuggestions: { suggestions: [
    // The list is static here but it could be dynamic.
    getSuggestedContact("1"), getSuggestedContact("2"), getSuggestedContact("3"), getSuggestedContact("4"), getSuggestedContact("5")
  // Only return items based on the query from the user.
  ].filter(e => !query || e.text.includes(query)) }}}]}};
}

/**
 * Generate a suggested contact given an ID.
 *
 * @param {String} id The ID of the contact to return.
 * @return {Object} The contact formatted as a selection item in the menu.
 */
function getSuggestedContact(id) {
  return {
    value: id,
    startIconUri: "https://www.gstatic.com/images/branding/product/2x/contacts_48dp.png",
    text: "Contact " + id
  };
}

FUNCTION_URL yerine harici veri kaynağını sorgulayan HTTP uç noktasını yazın.

Python

python/chat/selection-input/main.py
@app.route('/', methods=['POST'])
def post() -> Mapping[str, Any]:
  """Handle requests from Google Chat

  Returns:
      Mapping[str, Any]: The response
  """
  # Stores the Google Chat event
  chatEvent = request.get_json().get('chat')

  # Handle user interaction with multiselect.
  if chatEvent.get('widgetUpdatedPayload') is not None:
    return json.jsonify(query_contacts(request.get_json()))

  # Replies with a card that contains the multiselect menu.
  return json.jsonify({ 'hostAppDataAction': { 'chatDataAction': { 'createMessageAction': {
    'message': { 'cardsV2': [{
      'cardId': "contactSelector",
      'card': { 'sections':[{ 'widgets': [{
        'selectionInput': {
          'name': "contacts",
          'type': "MULTI_SELECT",
          'label': "Selected contacts",
          'multiSelectMaxSelectedItems': 3,
          'multiSelectMinQueryLength': 1,
          'externalDataSource': { 'function': FUNCTION_URL },
          # Suggested items loaded by default.
          # The list is static here but it could be dynamic.
          'items': [get_suggested_contact("3")]
        }
      }]}]}
    }]}
  }}}})


def query_contacts(event: dict) -> dict:
  """Get contact suggestions based on text typed by users.

  Args:
      event (Mapping[str, Any]): The event object that contains the user's query

  Returns:
      Mapping[str, Any]: The response with contact suggestions.
  """
  query = event.get("commonEventObject").get("parameters").get("autocomplete_widget_query")
  return { 'action': { 'modifyOperations': [{ 'updateWidget': { 'selectionInputWidgetSuggestions': { 'suggestions': list(
    filter(lambda e: query is None or query in e["text"], [
      # The list is static here but it could be dynamic.
      get_suggested_contact("1"), get_suggested_contact("2"), get_suggested_contact("3"), get_suggested_contact("4"), get_suggested_contact("5")
    # Only return items based on the query from the user
    ])
  )}}}]}}


def get_suggested_contact(id: str) -> dict:
  """Generate a suggested contact given an ID.

  Args:
      id (str): The ID of the contact to return.

  Returns:
      Mapping[str, Any]: The contact formatted as a selection item in the menu.
  """
  return {
    'value': id,
    'startIconUri': "https://www.gstatic.com/images/branding/product/2x/contacts_48dp.png",
    'text': "Contact " + id
  }

FUNCTION_URL yerine harici veri kaynağını sorgulayan HTTP uç noktasını yazın.

Java

java/chat/selection-input/src/main/java/com/google/chat/selectionInput/App.java
@SpringBootApplication
@RestController
// Web app that responds to events sent from a Google Chat space.
public class App {
  private static final String FUNCTION_URL = "your-function-url";

  public static void main(String[] args) {
    SpringApplication.run(App.class, args);
  }

  /**
   * Handle requests from Google Chat
   * 
   * @param event the event object sent by Google Chat
   * @return The response to be sent back to Google Chat
   */
  @PostMapping("/")
  @ResponseBody
  public GenericJson onEvent(@RequestBody JsonNode event) throws Exception {
    // Stores the Google Chat event
    JsonNode chatEvent = event.at("/chat");

    // Handle user interaction with multiselect.
    if (!chatEvent.at("/widgetUpdatedPayload").isEmpty()) {
      return queryContacts(event);
    }

    // Replies with a card that contains the multiselect menu.
    Message message = new Message().setCardsV2(List.of(new CardWithId()
      .setCardId("contactSelector")
      .setCard(new GoogleAppsCardV1Card()
        .setSections(List.of(new GoogleAppsCardV1Section().setWidgets(List.of(new GoogleAppsCardV1Widget()
          .setSelectionInput(new GoogleAppsCardV1SelectionInput()
            .setName("contacts")
            .setType("MULTI_SELECT")
            .setLabel("Selected contacts")
            .setMultiSelectMaxSelectedItems(3)
            .setMultiSelectMinQueryLength(1)
            .setExternalDataSource(new GoogleAppsCardV1Action().setFunction(FUNCTION_URL))
            // Suggested items loaded by default.
            // The list is static here but it could be dynamic.
            .setItems(List.of(getSuggestedContact("3")))))))))));

    return new GenericJson() {{
      put("hostAppDataAction", new GenericJson() {{
        put("chatDataAction", new GenericJson() {{
          put("createMessageAction", new GenericJson() {{
            put("message", message);
          }});
        }});
      }});
    }};
  }

  /**
   * Get contact suggestions based on text typed by users.
   *
   * @param event the event object that contains the user's query.
   * @return The response with contact suggestions.
   */
  GenericJson queryContacts(JsonNode event) throws Exception {
    String query = event.at("/commonEventObject/parameters/autocomplete_widget_query").asText();
    List<GoogleAppsCardV1SelectionItem> suggestions = List.of(
      // The list is static here but it could be dynamic.
      getSuggestedContact("1"), getSuggestedContact("2"), getSuggestedContact("3"), getSuggestedContact("4"), getSuggestedContact("5")
    // Only return items based on the query from the user
    ).stream().filter(e -> query == null || e.getText().indexOf(query) > -1).toList();

    return new GenericJson() {{
      put("action", new GenericJson() {{
        put("modifyOperations", List.of(new GenericJson() {{
          put("updateWidget", new GenericJson() {{
            put("selectionInputWidgetSuggestions", new GenericJson() {{
              put("suggestions", suggestions);
            }});
          }});
        }}));
      }});
    }};
  }

  /**
   * Generate a suggested contact given an ID.
   * 
   * @param id The ID of the contact to return.
   * @return The contact formatted as a selection item in the menu.
   */
  GoogleAppsCardV1SelectionItem getSuggestedContact(String id) {
    return new GoogleAppsCardV1SelectionItem()
      .setValue(id)
      .setStartIconUri("https://www.gstatic.com/images/branding/product/2x/contacts_48dp.png")
      .setText("Contact " + id);
  }
}

FUNCTION_URL yerine harici veri kaynağını sorgulayan HTTP uç noktasını yazın.

Apps Komut Dosyası

Bu örnekte, kart JSON'u döndürülerek bir kart mesajı gönderilir. Apps Komut Dosyası kart hizmetini de kullanabilirsiniz.

apps-script/chat/selection-input/selection-input.gs
/**
* Responds to a Message trigger in Google Chat.
*
* @param {Object} event the event object from Google Chat
* @return {Object} Response from the Chat app.
*/
function onMessage(event) {
  // Replies with a card that contains the multiselect menu.
  return { hostAppDataAction: { chatDataAction: { createMessageAction: { message: {
    cardsV2: [{
      cardId: "contactSelector",
      card: { sections:[{ widgets: [{
        selectionInput: {
          name: "contacts",
          type: "MULTI_SELECT",
          label: "Selected contacts",
          multiSelectMaxSelectedItems: 3,
          multiSelectMinQueryLength: 1,
          externalDataSource: { function: "queryContacts" },
          // Suggested items loaded by default.
          // The list is static here but it could be dynamic.
          items: [getSuggestedContact("3")]
        }
      }]}]}
    }]
  }}}}};
}

/**
* Get contact suggestions based on text typed by users.
*
* @param {Object} event the event object that contains the user's query
* @return {Object} suggestions
*/
function queryContacts(event) {
  const query = event.commonEventObject.parameters["autocomplete_widget_query"];
  return { action: { modifyOperations: [{ updateWidget: { selectionInputWidgetSuggestions: { suggestions: [
    // The list is static here but it could be dynamic.
    getSuggestedContact("1"), getSuggestedContact("2"), getSuggestedContact("3"), getSuggestedContact("4"), getSuggestedContact("5")
  // Only return items based on the query from the user.
  ].filter(e => !query || e.text.includes(query)) }}}]}};
}

/**
* Generate a suggested contact given an ID.
*
* @param {String} id The ID of the contact to return.
* @return {Object} The contact formatted as a selection item in the menu.
*/
function getSuggestedContact(id) {
  return {
    value: id,
    startIconUri: "https://www.gstatic.com/images/branding/product/2x/contacts_48dp.png",
    text: "Contact " + id
  };
}

Verileri başka bir karta aktarma

Kullanıcı bir karttan bilgi gönderdikten sonra, aşağıdakilerden herhangi birini yapmak için ek kartlar döndürmeniz gerekebilir:

  • Ayrı bölümler oluşturarak kullanıcıların daha uzun formları doldurmasına yardımcı olun.
  • Kullanıcıların ilk karttaki bilgileri önizlemesine ve onaylamasına izin verin. Böylece, yanıtlarını göndermeden önce inceleyebilirler.
  • Formun geri kalan kısımlarını dinamik olarak doldurun. Örneğin, kullanıcıların randevu oluşturmasını isteyen bir Chat uygulaması, randevu nedenini soran bir ilk kart gösterebilir ve ardından randevu türüne göre uygun saatleri gösteren başka bir kart doldurabilir.

İlk karttan veri girişini aktarmak için widget'ın name ve kullanıcının girdiği değeri içeren actionParameters ile button widget'ını oluşturabilirsiniz. Aşağıdaki örnekte gösterilmiştir:

Node.js

node/chat/contact-form-app/index.js
{ buttonList: { buttons: [{
  text: "SUBMIT",
  onClick: { action: {
    function: FUNCTION_URL,
    parameters: [
      { key: "actionName", value: "submitDialog" },
      // Pass input values as parameters for last dialog step (submission)
      { key: "contactName", value: name },
      { key: "contactBirthdate", value: birthdate },
      { key: "contactType", value: type }
    ]
  }}
}]}}

FUNCTION_URL ifadesini, düğme tıklamalarını işleyen HTTP uç noktasıyla değiştirin.

Python

python/chat/contact-form-app/main.py
{ 'buttonList': { 'buttons': [{
  'text': "SUBMIT",
  'onClick': { 'action': {
    'function': FUNCTION_URL,
    'parameters': [
      { 'key': "actionName", 'value': "submitDialog" },
      # Pass input values as parameters for last dialog step (submission)
      { 'key': "contactName", 'value': name },
      { 'key': "contactBirthdate", 'value': birthdate },
      { 'key': "contactType", 'value': type }
    ]
  }}
}]}}

FUNCTION_URL ifadesini, düğme tıklamalarını işleyen HTTP uç noktasıyla değiştirin.

Java

java/chat/contact-form-app/src/main/java/com/google/chat/contact/App.java
new GoogleAppsCardV1Widget().setButtonList(new GoogleAppsCardV1ButtonList().setButtons(List.of(
  new GoogleAppsCardV1Button()
    .setText("SUBMIT")
    .setOnClick(new GoogleAppsCardV1OnClick().setAction(new GoogleAppsCardV1Action()
      .setFunction(FUNCTION_URL)
      .setParameters(List.of(
        new GoogleAppsCardV1ActionParameter().setKey("actionName").setValue("submitDialog"),
        // Pass input values as parameters for last dialog step (submission)
        new GoogleAppsCardV1ActionParameter().setKey("contactName").setValue(name),
        new GoogleAppsCardV1ActionParameter().setKey("contactBirthdate").setValue(birthdate),
        new GoogleAppsCardV1ActionParameter().setKey("contactType").setValue(type))))))))))));

FUNCTION_URL ifadesini, düğme tıklamalarını işleyen HTTP uç noktasıyla değiştirin.

Apps Komut Dosyası

Bu örnekte, kart JSON'u döndürülerek bir kart mesajı gönderilir. Apps Komut Dosyası kart hizmetini de kullanabilirsiniz.

apps-script/chat/contact-form-app/Code.gs
{ buttonList: { buttons: [{
  text: "SUBMIT",
  onClick: { action: {
    function: "submitDialog",
    // Pass input values as parameters for last dialog step (submission)
    parameters: [
      { key: "contactName", value: name },
      { key: "contactBirthdate", value: birthdate },
      { key: "contactType", value: type }
    ]
  }}
}]}}

Kullanıcı düğmeyi tıkladığında Chat uygulamanız, veri alabileceğiniz bir olay nesnesi alır.

Form gönderimine yanıt verme

Chat uygulaması, kart mesajından veya iletişim kutusundan verileri aldıktan sonra, alındığını onaylayarak ya da hata döndürerek yanıt verir.

Aşağıdaki örnekte, bir Chat uygulaması, kart mesajından gönderilen bir formu başarıyla aldığını onaylamak için kısa mesaj gönderir.

Node.js

node/chat/contact-form-app/index.js
return { hostAppDataAction: { chatDataAction: { createMessageAction: { message: {
  text: "✅ " + event.commonEventObject.parameters["contactName"] + " has been added to your contacts."
}}}}};

Python

python/chat/contact-form-app/main.py
return { 'hostAppDataAction': { 'chatDataAction': { 'createMessageAction': { 'message': {
  'text': "✅ " + event.get('commonEventObject').get('parameters')["contactName"] + " has been added to your contacts."
}}}}}

Java

java/chat/contact-form-app/src/main/java/com/google/chat/contact/App.java
return new GenericJson() {{
  put("hostAppDataAction", new GenericJson() {{
    put("chatDataAction", new GenericJson() {{
      put("createMessageAction", new GenericJson() {{
        put("message", new Message()
          .setText( "✅ " + event.at("/commonEventObject/parameters/contactName").asText() +
                    " has been added to your contacts."));
      }});
    }});
  }});
}};

Apps Komut Dosyası

Bu örnekte, kart JSON'u döndürülerek bir kart mesajı gönderilir. Apps Komut Dosyası kart hizmetini de kullanabilirsiniz.

apps-script/chat/contact-form-app/Code.gs
return { hostAppDataAction: { chatDataAction: { createMessageAction: { message: {
  text: "✅ " + event.commonEventObject.parameters["contactName"] + " has been added to your contacts."
}}}}};

Bir iletişim kutusunu işlemek ve kapatmak için onay mesajı göndermek, orijinal mesajı veya kartı güncellemek ya da yalnızca iletişim kutusunu kapatmak isteyip istemediğinizi belirten bir RenderActions nesnesi döndürürsünüz. Adımlar için İletişim kutusunu kapatma bölümüne bakın.

Sorun giderme

Bu bölümde, Chat'te iletişim kutularıyla etkileşim kurarken karşılaşılan belirli hata kodları ve çalışma zamanı davranışları için sorun giderme adımları sağlanmaktadır.

İletişim kutusu etkileşimleri "Eklenti çağrılırken belirtilmemiş hata oluştu" hatasını döndürüyor

Bir iletişim kutusuyla etkileşimde bulunurken "Eklenti çağrılırken belirtilmemiş hata" mesajını ve 13 kodunu içeren hata günlükleri görüyorsanız bu genellikle dahili bir hata olduğunu veya Chat uygulamasının HTTP uç noktasının isteği işleyemediğini ya da geçerli bir yanıt döndüremediğini gösterir.

Bu hatayı gidermek için:

  • HTTP uç noktanızın günlüklerinde işlenmemiş istisnalar veya kilitlenmeler olup olmadığını kontrol edin.
  • Uç noktanızın isteklere 30 saniye içinde yanıt verdiğini doğrulayın. Uç noktanın çalışması 30 saniyeden uzun sürerse Chat, yanıtı işleyemez ve etkileşim başarısız olur. Ayrıntılı bilgi için Sıklık sınırları ve en iyi uygulamalar başlıklı makaleyi inceleyin.
  • Uç noktanızın geçerli bir yanıt döndürdüğünden emin olun. İletişim kutusu gönderimleri için uç nokta, doğru JSON biçiminde bir RenderActions nesnesi döndürmelidir. Yanıt hatalı biçimlendirilmişse veya zorunlu alanları içermiyorsa iletişim kutusu etkileşimi başarısız olabilir.

Bir Google Chat uygulaması veya kartı hata döndürdüğünde Chat arayüzünde "Bir hata oluştu" veya "İsteğiniz işlenemiyor" mesajı gösterilir. Bazen Chat kullanıcı arayüzünde hata mesajı gösterilmez ancak Chat uygulaması veya kartı beklenmedik bir sonuç üretir. Örneğin, kart mesajı görünmeyebilir.

Chat kullanıcı arayüzünde hata mesajı gösterilmeyebilir ancak Chat uygulamaları için hata günlüğü etkinleştirildiğinde hataları düzeltmenize yardımcı olacak açıklayıcı hata mesajları ve günlük verileri kullanılabilir. Hataları görüntüleme, hata ayıklama ve düzeltme konusunda yardım için Google Chat hatalarını giderme ve düzeltme başlıklı makaleyi inceleyin.

Eklenti olmayan Chat uygulamaları: Kartlarda kullanıcılar tarafından girilen form verilerini okuma

Aşağıdaki belgeler, Google Workspace eklentisi olmayan Chat uygulamaları için geçerlidir. Eklenti olmayan bir Chat uygulamasını taşımak için Google Chat uygulamasını Google Workspace eklentisine dönüştürme başlıklı makaleyi inceleyin.

Kartları kullanarak form oluşturma

Metin girişi, tarih/saat seçici ve seçim girişi içeren bir iletişim formu kullanan ve eklenti olmayan bir Chat uygulaması örneği için aşağıdaki koda bakın:

Node.js

node/contact-form-app/index.js
/**
 * The section of the contact card that contains the form input widgets. Used in a dialog and card message.
 * To add and preview widgets, use the Card Builder: https://addons.gsuite.google.com/uikit/builder
 */
const CONTACT_FORM_WIDGETS = [
  {
    "textInput": {
      "name": "contactName",
      "label": "First and last name",
      "type": "SINGLE_LINE"
    }
  },
  {
    "dateTimePicker": {
      "name": "contactBirthdate",
      "label": "Birthdate",
      "type": "DATE_ONLY"
    }
  },
  {
    "selectionInput": {
      "name": "contactType",
      "label": "Contact type",
      "type": "RADIO_BUTTON",
      "items": [
        {
          "text": "Work",
          "value": "Work",
          "selected": false
        },
        {
          "text": "Personal",
          "value": "Personal",
          "selected": false
        }
      ]
    }
  }
];

Python

python/contact-form-app/main.py
# The section of the contact card that contains the form input widgets. Used in a dialog and card message.
# To add and preview widgets, use the Card Builder: https://addons.gsuite.google.com/uikit/builder
CONTACT_FORM_WIDGETS = [
  {
    "textInput": {
      "name": "contactName",
      "label": "First and last name",
      "type": "SINGLE_LINE"
    }
  },
  {
    "dateTimePicker": {
      "name": "contactBirthdate",
      "label": "Birthdate",
      "type": "DATE_ONLY"
    }
  },
  {
    "selectionInput": {
      "name": "contactType",
      "label": "Contact type",
      "type": "RADIO_BUTTON",
      "items": [
        {
          "text": "Work",
          "value": "Work",
          "selected": False
        },
        {
          "text": "Personal",
          "value": "Personal",
          "selected": False
        }
      ]
    }
  }
]

Java

java/contact-form-app/src/main/java/com/google/chat/contact/App.java
// The section of the contact card that contains the form input widgets. Used in a dialog and card message.
// To add and preview widgets, use the Card Builder: https://addons.gsuite.google.com/uikit/builder
final static private List<GoogleAppsCardV1Widget> CONTACT_FORM_WIDGETS = List.of(
  new GoogleAppsCardV1Widget().setTextInput(new GoogleAppsCardV1TextInput()
    .setName("contactName")
    .setLabel("First and last name")
    .setType("SINGLE_LINE")),
  new GoogleAppsCardV1Widget().setDateTimePicker(new GoogleAppsCardV1DateTimePicker()
    .setName("contactBirthdate")
    .setLabel("Birthdate")
    .setType("DATE_ONLY")),
  new GoogleAppsCardV1Widget().setSelectionInput(new GoogleAppsCardV1SelectionInput()
    .setName("contactType")
    .setLabel("Contact type")
    .setType("RADIO_BUTTON")
    .setItems(List.of(
      new GoogleAppsCardV1SelectionItem()
        .setText("Work")
        .setValue("Work")
        .setSelected(false),
      new GoogleAppsCardV1SelectionItem()
        .setText("Personal")
        .setValue("Personal")
        .setSelected(false)))));

Apps Komut Dosyası

apps-script/contact-form-app/contactForm.gs
/**
 * The section of the contact card that contains the form input widgets. Used in a dialog and card message.
 * To add and preview widgets, use the Card Builder: https://addons.gsuite.google.com/uikit/builder
 */
const CONTACT_FORM_WIDGETS = [
  {
    "textInput": {
      "name": "contactName",
      "label": "First and last name",
      "type": "SINGLE_LINE"
    }
  },
  {
    "dateTimePicker": {
      "name": "contactBirthdate",
      "label": "Birthdate",
      "type": "DATE_ONLY"
    }
  },
  {
    "selectionInput": {
      "name": "contactType",
      "label": "Contact type",
      "type": "RADIO_BUTTON",
      "items": [
        {
          "text": "Work",
          "value": "Work",
          "selected": false
        },
        {
          "text": "Personal",
          "value": "Personal",
          "selected": false
        }
      ]
    }
  }
];

Etkileşimli widget'lardan veri alma

Kullanıcılar bir düğmeyi tıkladığında, eklenti olmayan Chat uygulamaları, düğmenin konumuna bağlı olarak bir etkileşim etkinliği alır:

  • Düğme bir mesajda veya iletişim kutusundaysa eklenti olmayan Chat uygulamaları, etkileşimle ilgili bilgileri içeren bir CARD_CLICKED etkileşim etkinliği alır. Etkileşim etkinliklerinin CARD_CLICKED yükü, kullanıcının girdiği değerleri içeren bir common.formInputs nesnesi (event.common.formInputs) içerir.

    Değerleri common.formInputs.WIDGET_NAME nesnesinden alabilirsiniz. Burada WIDGET_NAME, widget için belirttiğiniz name alanıdır. Değerler, widget için belirli bir veri türü olarak döndürülür (Inputs nesnesi olarak temsil edilir).

    Aşağıda, kullanıcının her widget için değer girdiği bir CARD_CLICKED etkileşim etkinliğinin bir kısmı gösterilmektedir:

    HTTP

    {
      "type": "CARD_CLICKED",
      "common": { "formInputs": {
        "contactName": { "stringInputs": {
          "value": ["Kai 0"]
        }},
        "contactBirthdate": { "dateInput": {
          "msSinceEpoch": 1000425600000
        }},
        "contactType": { "stringInputs": {
          "value": ["Personal"]
        }}
      }}
    }
    

    Apps Komut Dosyası

    {
      "type": "CARD_CLICKED",
      "common": { "formInputs": {
        "contactName": { "": { "stringInputs": {
          "value": ["Kai 0"]
        }}},
        "contactBirthdate": { "": { "dateInput": {
          "msSinceEpoch": 1000425600000
        }}},
          "contactType": { "": { "stringInputs": {
          "value": ["Personal"]
        }}}
      }}
    }
    
  • Düğme bir ana sayfadaysa, eklenti olmayan Chat uygulamaları bir SUBMIT_FORM etkileşim etkinliği alır. Etkileşim etkinliğinin yükü, kullanıcının girdiği değerleri içeren bir commonEventObject.formInputs nesnesi (event.commonEventObject.formInputs) içerir.

    Değerleri commonEventObject.formInputs.WIDGET_NAME nesnesinden alabilirsiniz. Burada WIDGET_NAME, widget için belirttiğiniz name alanıdır. Değerler, widget için belirli bir veri türü olarak döndürülür (Inputs nesnesi olarak temsil edilir).

    Aşağıda, kullanıcının her widget için değer girdiği bir SUBMIT_FORM etkileşim etkinliğinin bir kısmı gösterilmektedir:

    HTTP

    {
      "type": "SUBMIT_FORM",
      "commonEventObject": { "formInputs": {
        "contactName": { "stringInputs": {
          "value": ["Kai 0"]
        }},
        "contactBirthdate": { "dateInput": {
          "msSinceEpoch": 1000425600000
        }},
        "contactType": { "stringInputs": {
          "value": ["Personal"]
        }}
      }}
    }
    

    Apps Komut Dosyası

    {
      "type": "SUBMIT_FORM",
      "commonEventObject": { "formInputs": {
        "contactName": { "": { "stringInputs": {
          "value": ["Kai 0"]
        }}},
        "contactBirthdate": { "": { "dateInput": {
          "msSinceEpoch": 1000425600000
        }}},
          "contactType": { "": { "stringInputs": {
          "value": ["Personal"]
        }}}
      }}
    }
    

Eklenti olmayan bir Chat uygulaması, verileri almak için etkileşim etkinliğini işleyerek kullanıcıların widget'lara girdiği değerleri alır. Aşağıdaki tabloda, belirli bir form girişi widget'ının değerinin nasıl alınacağı gösterilmektedir. Tabloda her widget için widget'ın kabul ettiği veri türü, değerin etkileşim etkinliğinde nerede depolandığı ve örnek bir değer gösterilir.

Form girişi widget'ı Giriş verilerinin türü Etkileşim etkinliğinden giriş değeri Örnek değer
textInput stringInputs event.common.formInputs.contactName.stringInputs.value[0] Kai O
selectionInput stringInputs İlk veya tek değeri almak için event.common.formInputs.contactType.stringInputs.value[0] Personal
Yalnızca tarihleri kabul eden dateTimePicker. dateInput event.common.formInputs.contactBirthdate.dateInput.msSinceEpoch. 1000425600000

Verileri başka bir karta aktarma

Eklenti olmayan bir Chat uygulamasındaki ilk karttan veri girişini aktarmak için button widget'ını, widget'ın name değerini ve kullanıcının girdiği değeri içeren actionParameters ile oluşturun. Aşağıdaki örnekte gösterildiği gibi:

Node.js

node/contact-form-app/index.js
buttonList: { buttons: [{
  text: "Submit",
  onClick: { action: {
    function: "submitForm",
    parameters: [{
      key: "contactName", value: name }, {
      key: "contactBirthdate", value: birthdate }, {
      key: "contactType", value: type
    }]
  }}
}]}

Python

python/contact-form-app/main.py
'buttonList': { 'buttons': [{
  'text': "Submit",
  'onClick': { 'action': {
    'function': "submitForm",
    'parameters': [{
      'key': "contactName", 'value': name }, {
      'key': "contactBirthdate", 'value': birthdate }, {
      'key': "contactType", 'value': type
    }]
  }}
}]}

Java

java/contact-form-app/src/main/java/com/google/chat/contact/App.java
new GoogleAppsCardV1Widget().setButtonList(new GoogleAppsCardV1ButtonList().setButtons(List.of(new GoogleAppsCardV1Button()
  .setText("Submit")
  .setOnClick(new GoogleAppsCardV1OnClick().setAction(new GoogleAppsCardV1Action()
    .setFunction("submitForm")
    .setParameters(List.of(
      new GoogleAppsCardV1ActionParameter().setKey("contactName").setValue(name),
      new GoogleAppsCardV1ActionParameter().setKey("contactBirthdate").setValue(birthdate),
      new GoogleAppsCardV1ActionParameter().setKey("contactType").setValue(type))))))))));

Apps Komut Dosyası

apps-script/contact-form-app/main.gs
buttonList: { buttons: [{
  text: "Submit",
  onClick: { action: {
    function: "submitForm",
    parameters: [{
      key: "contactName", value: name }, {
      key: "contactBirthdate", value: birthdate }, {
      key: "contactType", value: type
    }]
  }}
}]}

Kullanıcı düğmeyi tıkladığında, eklenti olmayan Chat uygulaması, veri alabileceğiniz bir CARD_CLICKED etkileşim etkinliği alır.

Form gönderimine yanıt verme

Aşağıdaki örnekte, eklenti olmayan bir Chat uygulaması, bir iletişim kutusundan veya kart mesajından gönderilen formu başarıyla aldığını onaylamak için kısa mesaj gönderir:

Node.js

node/contact-form-app/index.js
const contactName = event.common.parameters["contactName"];
// Checks to make sure the user entered a contact name.
// If no name value detected, returns an error message.
const errorMessage = "Don't forget to name your new contact!";
if (!contactName && event.dialogEventType === "SUBMIT_DIALOG") {
  return { actionResponse: {
    type: "DIALOG",
    dialogAction: { actionStatus: {
      statusCode: "INVALID_ARGUMENT",
      userFacingMessage: errorMessage
    }}
  }};
}

Python

python/contact-form-app/main.py
contact_name = event.get('common').get('parameters')["contactName"]
# Checks to make sure the user entered a contact name.
# If no name value detected, returns an error message.
error_message = "Don't forget to name your new contact!"
if contact_name == "" and "SUBMIT_DIALOG" == event.get('dialogEventType'):
  return { 'actionResponse': {
    'type': "DIALOG",
    'dialogAction': { 'actionStatus': {
      'statusCode': "INVALID_ARGUMENT",
      'userFacingMessage': error_message
    }}
  }}

Java

java/contact-form-app/src/main/java/com/google/chat/contact/App.java
String contactName = event.at("/common/parameters/contactName").asText();
// Checks to make sure the user entered a contact name.
// If no name value detected, returns an error message.
String errorMessage = "Don't forget to name your new contact!";
if (contactName.isEmpty() && event.at("/dialogEventType") != null && "SUBMIT_DIALOG".equals(event.at("/dialogEventType").asText())) {
  return new Message().setActionResponse(new ActionResponse()
    .setType("DIALOG")
    .setDialogAction(new DialogAction().setActionStatus(new ActionStatus()
      .setStatusCode("INVALID_ARGUMENT")
      .setUserFacingMessage(errorMessage))));
}

Apps Komut Dosyası

apps-script/contact-form-app/main.gs
const contactName = event.common.parameters["contactName"];
// Checks to make sure the user entered a contact name.
// If no name value detected, returns an error message.
const errorMessage = "Don't forget to name your new contact!";
if (!contactName && event.dialogEventType === "SUBMIT_DIALOG") {
  return { actionResponse: {
    type: "DIALOG",
    dialogAction: { actionStatus: {
      statusCode: "INVALID_ARGUMENT",
      userFacingMessage: errorMessage
    }}
  }};
}

Eklenti olmayan bir Chat uygulamasında iletişim kutusunu işlemek ve kapatmak için onay mesajı göndermek, orijinal mesajı veya kartı güncellemek ya da yalnızca iletişim kutusunu kapatmak isteyip istemediğinizi belirten bir ActionResponse nesnesi döndürün. Adımlar için İletişim kutusunu kapatma bölümüne bakın.