ステップの構成カードを作成する

このガイドでは、Google Workspace Studio のステップでユーザーがカスタマイズして入力を行える構成カードを作成する方法について説明します。

一般に、構成カードを作成するには、他の Google Workspace アドオンと同様にカード インターフェースを作成します。構成カード インターフェースの作成については、以下をご覧ください。

一部のカード ウィジェットには、このガイドで説明する Workspace Studio 固有の特別な機能があります。

設定カードを定義する

Apps Script マニフェストとコードの両方で構成カードを定義します。

次の例は、ユーザーに Google Chat スペースの選択を求める構成カードを作成する方法を示しています。

マニフェスト ファイルを編集する

マニフェスト ファイルで workflowElements を定義します。

JSON

{
  "timeZone": "America/Los_Angeles",
  "exceptionLogging": "STACKDRIVER",
  "runtimeVersion": "V8",
  "addOns": {
    "common": {
      "name": "Chat space selector",
      "logoUrl": "https://www.gstatic.com/images/branding/productlogos/gsuite_addons/v6/web-24dp/logo_gsuite_addons_color_1x_web_24dp.png",
      "useLocaleFromApp": true
    },
    "flows": {
      "workflowElements": [
        {
          "id": "actionElement",
          "state": "ACTIVE",
          "name": "Chat space selector",
          "description": "Lets the user select a space from Google  Chat",
          "workflowAction": {
            "inputs": [
              {
                "id": "chooseSpace",
                "description": "Choose a Chat space",
                "cardinality": "SINGLE",
                "dataType": {
                  "basicType": "STRING"
                }
              }
            ],
            "onConfigFunction": "onConfigSpacePicker",
            "onExecuteFunction": "onExecuteSpacePicker"
          }
        }
      ]
    }
  }
}

コードを編集

アプリケーション コードでカードを返します。

Apps Script

/**
 * Generates and displays a configuration card to choose a Chat space
 */
function onConfigSpacePicker() {

  const selectionInput = CardService.newSelectionInput()
    .setTitle("First Value")
    .setFieldName("chooseSpace")
    .setType(CardService.SelectionInputType.MULTI_SELECT)
    .setPlatformDataSource(
      CardService.newPlatformDataSource()
        .setHostAppDataSource(
          CardService.newHostAppDataSource()
            .setWorkflowDataSource(
              CardService.newWorkflowDataSource()
                .setIncludeVariables(true)
                .setType(CardService.WorkflowDataSourceType.SPACE)
            )
        )
    );

  const cardSection = CardService.newCardSection()
    .setHeader("Select Chat Space")
    .setId("section_1")
    .addWidget(selectionInput)

  var card = CardService.newCardBuilder()
    .addSection(cardSection)
    .build();

  return card;
}

function onExecuteSpacePicker(e) {
}

入力ウィジェットの予測入力を設定する

SelectionInput ウィジェットのオートコンプリートを設定すると、ユーザーがオプションのリストから選択しやすくなります。たとえば、ユーザーが米国の都市を入力するメニューで Atl の入力を開始した場合、ユーザーが入力を完了する前に、要素が Atlanta を自動提案できます。最大 100 個のアイテムを自動補完できます。

予測入力の候補は、次のデータソースから取得できます。

  • サーバーサイドの自動補完: 候補は、ユーザーが定義したサードパーティまたは外部のデータソースから入力されます。
  • Google Workspace のデータ: Google Workspace ユーザーや Google Chat スペースなどの Google Workspace ソースから候補が入力されます。

サーバーサイドのオートコンプリート

SelectionInput ウィジェットを構成して、外部データソースから予測入力の候補を自動補完できます。たとえば、顧客管理(CRM)システムの販売見込み顧客のリストからユーザーが選択できるようにします。

サーバーサイドのオートコンプリートを実装するには、次の操作を行う必要があります。

  1. データソースを定義する: SelectionInput ウィジェットで、RemoteDataSource を指定する DataSourceConfig を追加します。この構成は、予測入力候補を取得する Apps Script 関数を指します。
  2. 予測入力機能を実装する: この関数は、ユーザーが入力フィールドに入力したときにトリガーされます。関数は、ユーザーの入力に基づいて外部データソースをクエリし、候補のリストを返す必要があります。

次の例は、サーバーサイドの自動補完用に SelectionInput ウィジェットを構成する方法を示しています。

Apps Script

// In your onConfig function:
var multiSelect1 =
  CardService.newSelectionInput()
    .setFieldName("value1")
    .setTitle("Server Autocomplete")
    .setType(CardService.SelectionInputType.MULTI_SELECT)
    .setMultiSelectMaxSelectedItems(3)
    .addDataSourceConfig(
      CardService.newDataSourceConfig()
        .setRemoteDataSource(
          CardService.newAction().setFunctionName('getAutocompleteResults')
        )
    )
    .addDataSourceConfig(
      CardService.newDataSourceConfig()
        .setPlatformDataSource(
          CardService.newPlatformDataSource()
            .setHostAppDataSource(
              CardService.newHostAppDataSource()
                .setWorkflowDataSource(
                  CardService.newWorkflowDataSource()
                    .setIncludeVariables(true)
                ))
        )
    );

// ... add widget to card ...

予測入力リクエストを処理する

setFunctionName で指定された関数(getAutocompleteResults)は、ユーザーがフィールドに入力したときにイベント オブジェクトを受け取ります。この関数は、次の条件を満たす必要があります。

  1. event.workflow.elementUiAutocomplete.invokedFunction を確認して、想定される関数名と一致していることを確認します。
  2. event.workflow.elementUiAutocomplete.query からユーザーの入力を取得します。
  3. クエリを使用して外部データソースにクエリを実行します。
  4. 必要な形式で最大 100 件の候補を返します。

次の例は、ユーザーのクエリに基づいて候補を返す handleAutocompleteRequest() 関数を実装する方法を示しています。

Apps Script

function handleAutocompleteRequest(event) {
  var invokedFunction = event.workflow.elementUiAutocomplete.invokedFunction;
  var query = event.workflow.elementUiAutocomplete.query;

  if (invokedFunction != "getAutocompleteResults" || query == undefined || query == "") {
    return {};
  }

  // Query your data source to get results based on the query
  let autocompleteResponse = AddOnsResponseService.newUpdateWidget()
    .addSuggestion(
      query + " option 1",
      query + "_option1",
      false,
      "https://developers.google.com/workspace/add-ons/images/person-icon.png",
      "option 1 bottom text"
    )
    .addSuggestion(
      query + " option 2",
      query + "_option2",
      false,
      "https://developers.google.com/workspace/add-ons/images/person-icon.png",
      "option 2 bottom text"
    ).addSuggestion(
      query + " option 3",
      query + "_option3",
      false,
      "https://developers.google.com/workspace/add-ons/images/person-icon.png",
      "option 3 bottom text"
    );

  const modifyAction = AddOnsResponseService.newAction()
    .addModifyCard(
      AddOnsResponseService.newModifyCard()
        .setUpdateWidget(autocompleteResponse)
    );

  return AddOnsResponseService.newRenderActionBuilder()
    .setAction(modifyAction)
    .build();
}

// In your onConfig function, handle the autocomplete event
function onConfigAutocompleteTest(event) {
  // Handle autocomplete request
  if (event.workflow && event.workflow.elementUiAutocomplete) {
    return handleAutocompleteRequest(event);
  }

  // ... rest of your card building logic ...
}

Google Workspace データの自動補完

ユーザーの Google Workspace 環境内のデータから予測入力の候補を入力することもできます。

  • Google Workspace ユーザー: 同じ Google Workspace 組織内のユーザーを入力します。
  • Google Chat スペース: ユーザーがメンバーになっている Google Chat スペースを入力します。

これを構成するには、SelectionInput ウィジェットで PlatformDataSource を設定し、WorkflowDataSourceTypeUSER または SPACE として指定します。

Apps Script

// User Autocomplete
var multiSelect2 =
  CardService.newSelectionInput()
    .setFieldName("value2")
    .setTitle("User Autocomplete")
    .setType(CardService.SelectionInputType.MULTI_SELECT)
    .setMultiSelectMaxSelectedItems(3)
    .setPlatformDataSource(
      CardService.newPlatformDataSource()
        .setHostAppDataSource(
          CardService.newHostAppDataSource()
            .setWorkflowDataSource(
              CardService.newWorkflowDataSource()
                .setIncludeVariables(true)
                .setType(CardService.WorkflowDataSourceType.USER)
            ))
    );

// Chat Space Autocomplete
var multiSelect3 =
  CardService.newSelectionInput()
    .setFieldName("value3")
    .setTitle("Chat Space Autocomplete")
    .setType(CardService.SelectionInputType.MULTI_SELECT)
    .setMultiSelectMaxSelectedItems(3)
    .setPlatformDataSource(
      CardService.newPlatformDataSource()
        .setHostAppDataSource(
          CardService.newHostAppDataSource()
            .setWorkflowDataSource(
              CardService.newWorkflowDataSource()
                .setIncludeVariables(true)
                .setType(CardService.WorkflowDataSourceType.SPACE)
            ))
    );

例: 予測入力タイプを組み合わせる

次の例は、3 つの SelectionInput ウィジェットを含むカードを作成する onConfig 関数を示しています。この関数は、サーバーサイド、ユーザー、スペースの自動補完を示しています。

JSON

{
  "timeZone": "America/Los_Angeles",
  "exceptionLogging": "STACKDRIVER",
  "runtimeVersion": "V8",
  "addOns": {
    "common": {
      "name": "Autocomplete Demo",
      "logoUrl": "https://www.gstatic.com/images/icons/material/system/1x/pets_black_48dp.png",
      "useLocaleFromApp": true
    },
    "flows": {
      "workflowElements": [
        {
          "id": "autocomplete_demo",
          "state": "ACTIVE",
          "name": "Autocomplete Demo",
          "description": "Provide autocompletion in input fields",
          "workflowAction": {
            "inputs": [
              {
                "id": "value1",
                "description": "A multi-select field with autocompletion",
                "cardinality": "SINGLE",
                "dataType": {
                  "basicType": "STRING"
                }
              }
            ],
            "onConfigFunction": "onConfigAutocomplete",
            "onExecuteFunction": "onExecuteAutocomplete"
          }
        }
      ]
    }
  }
}

Apps Script

function onConfigAutocompleteTest(event) {
  // Handle autocomplete request
  if (event.workflow && event.workflow.elementUiAutocomplete) {
    return handleAutocompleteRequest(event);
  }

  // Server-side autocomplete widget
  var multiSelect1 =
    CardService.newSelectionInput()
      .setFieldName("value1")
      .setTitle("Server Autocomplete")
      .setType(CardService.SelectionInputType.MULTI_SELECT)
      .setMultiSelectMaxSelectedItems(3)
      .addDataSourceConfig(
        CardService.newDataSourceConfig()
          .setRemoteDataSource(
            CardService.newAction().setFunctionName('getAutocompleteResults')
          )
      )
      .addDataSourceConfig(
        CardService.newDataSourceConfig()
          .setPlatformDataSource(
            CardService.newPlatformDataSource()
              .setHostAppDataSource(
                CardService.newHostAppDataSource()
                  .setWorkflowDataSource(
                    CardService.newWorkflowDataSource()
                      .setIncludeVariables(true)
                  ))
          )
      );

  // User autocomplete widget
  var multiSelect2 =
    CardService.newSelectionInput()
      .setFieldName("value2")
      .setTitle("User Autocomplete")
      .setType(CardService.SelectionInputType.MULTI_SELECT)
      .setMultiSelectMaxSelectedItems(3)
      .setPlatformDataSource(
        CardService.newPlatformDataSource()
          .setHostAppDataSource(
            CardService.newHostAppDataSource()
              .setWorkflowDataSource(
                CardService.newWorkflowDataSource()
                  .setIncludeVariables(true)
                  .setType(CardService.WorkflowDataSourceType.USER)
              ))
      );

  // Space autocomplete widget
  var multiSelect3 =
    CardService.newSelectionInput()
      .setFieldName("value3")
      .setTitle("Chat Space Autocomplete")
      .setType(CardService.SelectionInputType.MULTI_SELECT)
      .setMultiSelectMaxSelectedItems(3)
      .setPlatformDataSource(
        CardService.newPlatformDataSource()
          .setHostAppDataSource(
            CardService.newHostAppDataSource()
              .setWorkflowDataSource(
                CardService.newWorkflowDataSource()
                  .setIncludeVariables(true)
                  .setType(CardService.WorkflowDataSourceType.SPACE)
              ))
      );

  var sectionBuilder =
    CardService.newCardSection()
      .addWidget(multiSelect1)
      .addWidget(multiSelect2)
      .addWidget(multiSelect3);

  var card =
    CardService.newCardBuilder()
      .addSection(sectionBuilder)
      .build();
  return card;
}

function handleAutocompleteRequest(event) {
  var invokedFunction = event.workflow.elementUiAutocomplete.invokedFunction;
  var query = event.workflow.elementUiAutocomplete.query;

  if (invokedFunction != "getAutocompleteResults" || query == undefined || query == "") {
    return {};
  }

  // Query your data source to get results
  let autocompleteResponse = AddOnsResponseService.newUpdateWidget()
    .addSuggestion(
      query + " option 1",
      query + "_option1",
      false,
      "https://developers.google.com/workspace/add-ons/images/person-icon.png",
      "option 1 bottom text"
    )
    .addSuggestion(
      query + " option 2",
      query + "_option2",
      false,
      "https://developers.google.com/workspace/add-ons/images/person-icon.png",
      "option 2 bottom text"
    ).addSuggestion(
      query + " option 3",
      query + "_option3",
      false,
      "https://developers.google.com/workspace/add-ons/images/person-icon.png",
      "option 3 bottom text"
    );

  const modifyAction = AddOnsResponseService.newAction()
    .addModifyCard(
      AddOnsResponseService.newModifyCard()
        .setUpdateWidget(autocompleteResponse)
    );

  return AddOnsResponseService.newRenderActionBuilder()
    .setAction(modifyAction)
    .build();
}

変数ピッカーのボタンをカスタマイズする

ボタンのサイズとラベルを設定することで、変数ピッカー ボタンをカスタマイズできます。

ボタンのサイズ

ボタンのサイズを設定するには、次のいずれかの VariableButtonSize 列挙型を指定して setVariableButtonSize() を使用します。

  • UNSPECIFIED: デフォルト。ボタンは、サイドパネルではコンパクトに、その他のコンテキストではフルサイズで表示されます。
  • COMPACT: ボタンにプラス記号(+)のみが表示されます。
  • FULL_SIZE: ボタンにテキストラベル全体が表示されます。

ボタンのラベル

ボタンのテキストを設定するには、setVariableButtonLabel() を使用します。

例: 変数ピッカーのカスタマイズ

次の例は、さまざまなサイズの変数ピッカー ボタンとカスタムラベルを使用して TextInput ウィジェットを構成する方法を示しています。

  • ウェブでの変数選択ツールのボタンのカスタマイズ。
    図 1: ウェブでの変数選択ツールボタンのカスタマイズ。
  • アドオンのサイドパネルでの変数選択ボタンのカスタマイズ。
    図 2: アドオンのサイドパネルでの変数選択ツールボタンのカスタマイズ。

変数ピッカー ボタンをカスタマイズするためのマニフェスト ファイルを次に示します。

JSON

{
  "timeZone": "America/Los_Angeles",
  "dependencies": {},
  "exceptionLogging": "STACKDRIVER",
  "runtimeVersion": "V8",
  "oauthScopes": [
    "https://www.googleapis.com/auth/script.locale"
  ],
  "addOns": {
    "common": {
      "name": "Variable button customization",
      "logoUrl": "https://www.gstatic.com/images/icons/material/system/1x/pets_black_48dp.png",
      "useLocaleFromApp": true
    },
    "flows": {
      "workflowElements": [
        {
          "id": "variable_picker_customization",
          "state": "ACTIVE",
          "name": "Variable Picker demo",
          "description": "List all possible variable picker customization options",
          "workflowAction": {
            "onConfigFunction": "onUpdateCardConfigFunction",
            "onExecuteFunction": "onUpdateCardExecuteFunction"
          }
        }
      ]
    }
  }
}

変数ピッカー ボタンをカスタマイズするコードは次のとおりです。

Apps Script

function onUpdateCardConfigFunction(event) {
  const textInput1 = CardService.newTextInput()
    .setFieldName("value1")
    .setTitle("Regular variable picker button")
    .setHostAppDataSource(
      CardService.newHostAppDataSource().setWorkflowDataSource(
        CardService.newWorkflowDataSource()
          .setIncludeVariables(true)
          .setVariableButtonSize(CardService.VariableButtonSize.UNSPECIFIED)
      )
    );

  const textInput2 = CardService.newTextInput()
    .setFieldName("value2")
    .setTitle("Size: Unspecified")
    .setHostAppDataSource(
      CardService.newHostAppDataSource().setWorkflowDataSource(
        CardService.newWorkflowDataSource()
          .setIncludeVariables(true)
          .setVariableButtonSize(CardService.VariableButtonSize.UNSPECIFIED)
      )
    );

  const textInput3 = CardService.newTextInput()
    .setFieldName("value3")
    .setTitle("Size: Full size")
    .setHostAppDataSource(
      CardService.newHostAppDataSource().setWorkflowDataSource(
        CardService.newWorkflowDataSource()
          .setIncludeVariables(true)
          .setVariableButtonSize(CardService.VariableButtonSize.FULL_SIZE)
      )
    );

  const textInput4 = CardService.newTextInput()
    .setFieldName("value4")
    .setTitle("Size: Compact")
    .setHostAppDataSource(
      CardService.newHostAppDataSource().setWorkflowDataSource(
        CardService.newWorkflowDataSource()
          .setIncludeVariables(true)
          .setVariableButtonSize(CardService.VariableButtonSize.COMPACT)
      )
    );

  const textInput5 = CardService.newTextInput()
    .setFieldName("value5")
    .setTitle("Custom button label")
    .setHostAppDataSource(
      CardService.newHostAppDataSource().setWorkflowDataSource(
        CardService.newWorkflowDataSource()
          .setIncludeVariables(true)
          .setVariableButtonLabel("New button label!")
      )
    );

  var cardSection = CardService.newCardSection()
    .addWidget(textInput1)
    .addWidget(textInput2)
    .addWidget(textInput3)
    .addWidget(textInput4)
    .addWidget(textInput5)
    .setId("section_1");

  var card = CardService.newCardBuilder().addSection(cardSection).build();

  return card;
}

function onUpdateCardExecuteFunction(event) {
}

Workspace Studio 固有の機能

一部のカード ウィジェットには、Workspace Studio 固有の特別な機能があります。詳細については、こちらをご覧ください。

TextInput と SelectionInput

TextInput ウィジェットと SelectionInput ウィジェットには、Workspace Studio 固有の次の機能があります。

  • includeVariables: ユーザーが前のステップから変数を選択できるようにするブール値プロパティ。後の手順で変数ピッカーを表示するには、開始イベントと少なくとも 1 つの対応する出力変数の両方を変数にマッピングする必要があります。
  • type: 候補を自動補完する列挙値。サポートされている値は次のとおりです。
    • USER: ユーザーの連絡先に登録されている人物の予測入力候補を提供します。
    • SPACE: ユーザーがメンバーになっている Google Chat スペースのオートコンプリート候補を提供します。

includeVariablestype の両方が設定されている場合、入力フィールドはそれらのエクスペリエンスを組み合わせます。ユーザーは、一致する type の変数を選択して、その予測入力の候補を表示できます。

  • Google Chat スペースの候補の自動補完。
    図 3: スペースを選択する際に、ユーザーが予測入力の候補を確認している様子。
  • [変数] メニューでは、前のステップの出力変数を選択できます。
    図 4: ユーザーが [➕変数] プルダウンから前のステップの出力変数を選択する。

オーバーフロー メニューで出力変数を 1 つだけ選択する

SelectionInput ウィジェットを構成して、ユーザーがオーバーフロー メニューを使用して前のステップの単一の出力変数を選択できるようにすることができます。

SelectionInputTypeOVERFLOW_MENU に設定すると、ウィジェットは専用の変数ピッカーとして機能します。TextInputincludeVariables を使用すると、変数の値が文字列に変換されますが、OVERFLOW_MENU では、選択した変数の元のデータ型が保持されます。

Apps Script

const selectionInput = CardService.newSelectionInput()
  .setFieldName("variable_picker_1")
  .setTitle("Variable Picker")
  .setType(
    CardService.SelectionInputType.OVERFLOW_MENU
  );

ユーザーがテキストと出力変数を組み合わせられるようにする

setInputMode() を使用して、ユーザーがテキストと出力変数を操作する方法を制御するように TextInput ウィジェットを構成できます。

  • RICH_TEXT: ユーザーがテキストと出力変数を組み合わせることができます。結果は 1 つの連結された文字列になります。
  • PLAIN_TEXT: 入力を制限します。ユーザーはテキストを入力するか、単一の出力変数を選択できます。変数を選択すると、既存のテキストが置き換えられます。このモードを使用して、マニフェストで定義された特定のデータ型を適用します。

次の画像は、2 つの TextInput ウィジェットを示しています。1 つ目は RICH_TEXT として構成され、テキストと出力変数が含まれています。2 つ目は PLAIN_TEXT として構成され、出力変数のみが許可されます。

  • RICH_TEXT と PLAIN_TEXT として構成されたテキスト入力ウィジェット
    図 5: RICH_TEXTPLAIN_TEXT として構成されたテキスト入力ウィジェット。

すべての TextInput ウィジェットの入力モードを明示的に設定することをおすすめします。

さまざまな入力モードで TextInput ウィジェットを構成するためのマニフェスト ファイルを次に示します。

JSON

{
  "timeZone": "America/Toronto",
  "dependencies": {},
  "exceptionLogging": "STACKDRIVER",
  "runtimeVersion": "V8",
  "addOns": {
    "common": {
      "name": "Text and output variable demo",
      "logoUrl": "https://www.gstatic.com/images/icons/material/system/1x/pets_black_48dp.png",
      "useLocaleFromApp": true
    },
    "flows": {
      "workflowElements": [
        {
          "id": "richTextDemo",
          "state": "ACTIVE",
          "name": "Rich Text Demo",
          "description": "Show the difference between rich text and plain text TextInput widgets",
          "workflowAction": {
            "inputs": [
              {
                "id": "value1",
                "description": "First user input",
                "cardinality": "SINGLE",
                "dataType": {
                  "basicType": "STRING"
                }
              },
              {
                "id": "value2",
                "description": "Second user input",
                "cardinality": "SINGLE",
                "dataType": {
                  "basicType": "STRING"
                }
              }
            ],
            "onConfigFunction": "onConfiguration",
            "onExecuteFunction": "onExecution"
          }
        }
      ]
    }
  }
}

さまざまな入力モードで TextInput ウィジェットを構成するコードは次のとおりです。

Apps Script

function onConfiguration() {
  const input1 = CardService.newTextInput()
    .setFieldName("value1")
    .setId("value1")
    .setTitle("Rich Text")
    .setHostAppDataSource(
      CardService.newHostAppDataSource()
        .setWorkflowDataSource(
          CardService.newWorkflowDataSource()
            .setIncludeVariables(true)
        )
    )
    // Set input mode to RICH_TEXT to allow mixed text and variables.
    .setInputMode(CardService.TextInputMode.RICH_TEXT);

  const input2 = CardService.newTextInput()
    .setFieldName("value2")
    .setId("value2")
    .setTitle("Plain text")
    .setHostAppDataSource(
      CardService.newHostAppDataSource()
        .setWorkflowDataSource(
          CardService.newWorkflowDataSource()
            .setIncludeVariables(true)
        )
    )
    // Set input mode to PLAIN_TEXT to enforce single variable selection.
    .setInputMode(CardService.TextInputMode.PLAIN_TEXT);

  const section = CardService.newCardSection()
    .addWidget(input1)
    .addWidget(input2);

  const card = CardService.newCardBuilder()
    .addSection(section)
    .build();

  return card;
}

function onExecution(e) {
}

カードに関する考慮事項と制限事項

  • Workspace Studio を拡張するアドオンでは、popCard()pushCard()updateCard() などのカード ナビゲーションはサポートされていません。

  • SelectionInput が変数ピッカーで使用されている場合、ウィジェットは "type": "MULTI_SELECT" のみをサポートします。構成カードの他の場所では、SelectionInputSelectionType のすべての値をサポートしています。