En esta guía, se explica cómo crear una tarjeta de configuración que permita a los usuarios personalizar y proporcionar entradas para un paso en Google Workspace Studio.
En general, para crear una tarjeta de configuración, debes crear una interfaz de tarjeta como lo harías para cualquier otro complemento de Google Workspace. Si necesitas ayuda para crear interfaces de tarjetas de configuración, consulta los siguientes recursos:
- Card Builder, una herramienta interactiva que te ayuda a crear y definir tarjetas
- Card en la documentación de referencia de la API de complementos de Google Workspace
- Card Service, un servicio de Apps Script que permite que las secuencias de comandos configuren y compilen tarjetas.
- Interfaces basadas en tarjetas en la documentación para desarrolladores de complementos de Google Workspace
Algunos widgets de tarjetas tienen funciones y características especiales específicas de Workspace Studio, que se detallan en esta guía.
Define una tarjeta de configuración
Define una tarjeta de configuración en el manifiesto de Apps Script y en el código.
En el siguiente ejemplo, se muestra cómo compilar una tarjeta de configuración que les solicite a los usuarios que seleccionen un espacio de Google Chat.
Edita el archivo de manifiesto
En el archivo de manifiesto, define 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"
}
}
]
}
}
}
Editar código
En el código de la aplicación, devuelve una tarjeta.
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) {
}
Configura la función de autocompletar para los widgets de entrada
Puedes configurar el autocompletado para los widgets de SelectionInput y ayudar a los usuarios a seleccionar opciones de una lista. Por ejemplo, si un usuario comienza a escribir Atl para un menú que completa ciudades en Estados Unidos, tu elemento puede sugerir automáticamente Atlanta antes de que el usuario termine de escribir. Puedes autocompletar hasta 100 elementos.
Las sugerencias de Autocomplete pueden provenir de las siguientes fuentes de datos:
- Autocompletado del servidor: Las sugerencias se propagan desde una fuente de datos externa o de terceros que tú defines.
- Datos de Google Workspace: Las sugerencias se completan a partir de fuentes de Google Workspace, como usuarios de Google Workspace o espacios de Google Chat.
Autocompletar del servidor
Puedes configurar un widget de SelectionInput para que autocomplete sugerencias de una fuente de datos externa. Por ejemplo, puedes ayudar a los usuarios a seleccionar clientes potenciales de ventas de una lista de un sistema de administración de relaciones con clientes (CRM).
Para implementar la función de autocompletar del servidor, debes hacer lo siguiente:
- Define la fuente de datos: En el widget
SelectionInput, agrega unDataSourceConfigque especifique unRemoteDataSource. Esta configuración apunta a una función de Apps Script que recupera sugerencias de autocompletado. - Implementa la función de autocompletar: Esta función se activa cuando el usuario escribe en el campo de entrada. La función debe consultar tu fuente de datos externa según la entrada del usuario y devolver una lista de sugerencias.
En el siguiente ejemplo, se muestra cómo configurar un widget SelectionInput para la función de autocompletar del servidor:
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 ...
Controla la solicitud de autocompletar
La función especificada en setFunctionName (p.ej., getAutocompleteResults) recibe un objeto de evento cuando el usuario escribe en el campo. Esta función debe hacer lo siguiente:
- Verifica el
event.workflow.elementUiAutocomplete.invokedFunctionpara asegurarte de que coincida con el nombre de la función esperada. - Obtén la entrada del usuario de
event.workflow.elementUiAutocomplete.query. - Consulta la fuente de datos externa con la consulta.
- Devuelve hasta 100 sugerencias en el formato requerido.
En el siguiente ejemplo, se muestra cómo implementar la función handleAutocompleteRequest() para devolver sugerencias basadas en la búsqueda del usuario:
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 ...
}
Autocompletado de datos de Google Workspace
También puedes propagar sugerencias de autocompletar a partir de los datos del entorno de Google Workspace del usuario:
- Usuarios de Google Workspace: Se completan los usuarios dentro de la misma organización de Google Workspace.
- Espacios de Google Chat: Se completan los espacios de Google Chat de los que el usuario es miembro.
Para configurar esto, establece PlatformDataSource en el widget SelectionInput y especifica WorkflowDataSourceType como USER o 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)
))
);
Ejemplo: Combinación de tipos de autocompletado
En el siguiente ejemplo, se muestra una función onConfig que crea una tarjeta con tres widgets SelectionInput, lo que demuestra la función de autocompletar del servidor, del usuario y del espacio:
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();
}
Personaliza los botones del selector de variables
Puedes personalizar el botón del selector de variables configurando el tamaño y la etiqueta del botón.
Tamaño del botón
Para establecer el tamaño del botón, usa setVariableButtonSize() con una de las siguientes enumeraciones de VariableButtonSize:
UNSPECIFIED: Es el valor predeterminado. El botón es compacto en el panel lateral y de tamaño completo en otros contextos.COMPACT: El botón solo muestra un signo más (+).FULL_SIZE: El botón muestra la etiqueta de texto completa.
Etiqueta del botón
Para establecer el texto del botón, usa setVariableButtonLabel().
Ejemplo: Personalización del selector de variables
En el siguiente ejemplo, se muestra cómo configurar widgets TextInput con diferentes tamaños de botones del selector de variables y una etiqueta personalizada.
-
Figura 1: Personalización del botón del selector de variables en la Web. -
Figura 2: Personalización del botón del selector de variables en un panel lateral del complemento.
Este es el archivo de manifiesto para personalizar los botones del selector de variables:
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"
}
}
]
}
}
}
Este es el código para personalizar los botones del selector de variables:
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) {
}
Funciones específicas de Workspace Studio
Algunos widgets de tarjetas tienen funciones especiales específicas de Workspace Studio, que se detallan aquí.
TextInput y SelectionInput
Los widgets TextInput y SelectionInput tienen estas funciones específicas de Workspace Studio:
includeVariables: Es una propiedad booleana que permite a los usuarios seleccionar variables de pasos anteriores. Para que el selector de variables se muestre en pasos posteriores, tanto el evento de inicio como al menos una variable de salida correspondiente deben asignarse a la variable.type: Es un valor enumerado que autocompleta las sugerencias. Entre los valores admitidos, se incluyen los siguientes:USER: Proporciona sugerencias de autocompletar para las personas en los contactos del usuario.SPACE: Proporciona sugerencias de autocompletado para los espacios de Google Chat de los que el usuario es miembro.
Cuando se configuran includeVariables y type, el campo de entrada combina sus experiencias. Los usuarios pueden seleccionar una variable del type coincidente en un menú desplegable y ver sugerencias de autocompletar para ella.
-
Figura 3: Un usuario revisa las sugerencias de autocompletar cuando elige un espacio. -
Figura 4: Un usuario selecciona la variable de salida de un paso anterior en el menú desplegable ➕Variables.
Selecciona solo una variable de salida con un menú ampliado
Puedes configurar un widget SelectionInput para permitir que los usuarios seleccionen una sola variable de salida de un paso anterior con un menú de desbordamiento.
Cuando configuras SelectionInputType como OVERFLOW_MENU, el widget funciona como un selector de variables exclusivo. A diferencia del uso de includeVariables con TextInput, que convierte los valores de las variables en cadenas, OVERFLOW_MENU conserva el tipo de datos original de la variable seleccionada.
Apps Script
const selectionInput = CardService.newSelectionInput()
.setFieldName("variable_picker_1")
.setTitle("Variable Picker")
.setType(
CardService.SelectionInputType.OVERFLOW_MENU
);
Permitir que los usuarios combinen texto y variables de salida
Puedes configurar widgets de TextInput para controlar cómo los usuarios interactúan con el texto y las variables de salida con setInputMode().
RICH_TEXT: Permite a los usuarios combinar texto y variables de salida. El resultado es una sola cadena concatenada.PLAIN_TEXT: Restringe la entrada. Los usuarios pueden escribir texto o seleccionar una sola variable de salida. Si seleccionas una variable, se reemplazará cualquier texto existente. Usa este modo para aplicar tipos de datos específicos definidos en el manifiesto.
En la siguiente imagen, se muestran dos widgets de TextInput. El primero se configura como RICH_TEXT y contiene texto y una variable de salida. El segundo se configura como PLAIN_TEXT y solo permite una variable de salida.
-
Figura 5: Widgets de entrada de texto configurados como RICH_TEXTyPLAIN_TEXT.
Te recomendamos que establezcas de forma explícita el modo de entrada para todos los widgets TextInput.
Este es el archivo de manifiesto para configurar widgets TextInput con diferentes modos de entrada:
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"
}
}
]
}
}
}
Este es el código para configurar widgets de TextInput con diferentes modos de entrada:
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) {
}
Consideraciones y limitaciones de las tarjetas
La navegación con tarjetas, como
popCard(),pushCard()yupdateCard(), no se admite en los complementos que extienden Workspace Studio.Cuando se usa
SelectionInputen un selector de variables, los widgets solo admiten"type": "MULTI_SELECT". En otras partes de las tarjetas de configuración,SelectionInputadmite todos los valores deSelectionType.
Temas relacionados
- Cómo crear un paso
- Variables de entrada
- Cómo validar una variable de entrada
- Variables de salida
- Registra la actividad y los errores
- Objetos de eventos de Workspace Studio