Invocar y descartar cuadros de diálogo en el SDK de Teams

En este artículo se explica cómo invocar y descartar cuadros de diálogo (anteriormente conocidos como módulos de tareas) mediante el SDK de Teams (biblioteca de IA de Teams). En el SDK de Teams, los cuadros de diálogo se invocan desde acciones de tarjeta adaptativa mediante los TaskFetchAction eventos de abrir y enviar diálogos en la App clase.

El registro del evento varía según el idioma:

  • TypeScript: app.on('dialog.open', ...) y app.on('dialog.submit', ...)
  • C#: teams.OnTaskFetch(...) y teams.OnTaskSubmit(...)
  • Python: @app.on_dialog_open y @app.on_dialog_submit

El contenido del cuadro de diálogo puede ser una tarjeta adaptable o una página web basada en URL.

Los diálogos también se pueden invocar a través de otros enfoques en función de la arquitectura de la aplicación:

Para obtener instrucciones de migración de Bot Framework al SDK de Teams, consulte Migrar desde BotBuilder.

En la tabla siguiente se resume cómo funcionan los cuadros de diálogo en el SDK de Teams:

Paso Cuadro de diálogo con tarjeta adaptativa Cuadro de diálogo con la dirección URL de la página web
Activar el cuadro de diálogo 1. Enviar una tarjeta adaptable con un TaskFetchAction botón al usuario. Los datos de value la acción especifican el tipo de cuadro de diálogo que se abrirá.

2. Cuando el usuario selecciona el botón, Teams envía una tarea para invocar captura en la aplicación.
1. Enviar una tarjeta adaptable con un TaskFetchAction botón al usuario.

2. Cuando el usuario selecciona el botón, Teams envía una tarea para invocar captura en la aplicación.
Controlar el evento de apertura del cuadro de diálogo 3. En el controlador de diálogo abierto, devuelva una respuesta continua del módulo de tareas que contenga los metadatos del cuadro de diálogo (título, dimensiones y tarjeta adaptativa que se va a mostrar). En C#, úselo TaskInfo con una ContinueTask envoltura. En TypeScript, use CardTaskModuleTaskInfo. En Python, use CardTaskModuleTaskInfo within a TaskModuleContinueResponse. 3. En el controlador de diálogo abierto, devuelva una respuesta continua del módulo de tareas que contenga metadatos de cuadro de diálogo con una url propiedad que apunte a la página web. El dominio de la dirección URL debe estar en la matriz en el manifiesto de la validDomains aplicación. En C#, use TaskInfo. En TypeScript, use UrlTaskModuleTaskInfo. En Python, use UrlTaskModuleTaskInfo within a TaskModuleContinueResponse.
Controlar el envío del cuadro de diálogo 4. Cuando el usuario presiona un Action.Submit botón, Teams envía una tarea para enviar invocar a la aplicación con los datos del formulario.

5. Puedes responder de la siguiente manera:
• No hacer nada (tarea completada)
• Mostrar un mensaje (C#: MessageTask, TypeScript/Python: TaskModuleMessageResponse)
• Encadenamiento a otro cuadro de diálogo (C#: ContinueTask, TypeScript/Python: TaskModuleContinueResponse)
4. La página web llama a la biblioteca cliente JS de Teams para volver a enviar los datos. Teams envía una tarea para invocar el envío a la aplicación con el resultado.

En la siguiente sección se describen los metadatos del cuadro de diálogo que definen el contenido y la apariencia de un cuadro de diálogo.

Metadatos del cuadro de diálogo

Los metadatos del cuadro de diálogo definen el contenido y la apariencia de un cuadro de diálogo. Cada lenguaje utiliza sus propios tipos para representar estos metadatos:

  • C#: TaskInfo (de Microsoft.Teams.Api.TaskModules)
  • TypeScript: CardTaskModuleTaskInfo or UrlTaskModuleTaskInfo (from @microsoft/teams.api)
  • Python: CardTaskModuleTaskInfo or UrlTaskModuleTaskInfo (from microsoft_teams.api)

En la tabla siguiente se enumeran las propiedades comunes en todos los idiomas:

Atributo Tipo Descripción
title string Este atributo aparece debajo del nombre de la aplicación y a la derecha del icono de la aplicación.
height número o cadena Este atributo puede ser un número que representa la altura del cuadro de diálogo en píxeles, o , smallmedium, o large. En C#, use Union<int, Size>.
width número o cadena Este atributo puede ser un número que representa el ancho del cuadro de diálogo en píxeles, o , smallmedium, o large. En C#, use Union<int, Size>.
url string La dirección URL de la página cargada como dentro <iframe> del cuadro de diálogo. El dominio de la dirección URL debe estar en la matriz validDomains de la aplicación en el manifiesto de la aplicación. Úselo UrlTaskModuleTaskInfo en TypeScript/Python o establezca la Url propiedad TaskInfo en C#.
card Datos adjuntos La tarjeta adaptativa que se mostrará en el cuadro de diálogo. En C#, establezca la Card propiedad con TaskInfo un Attachment. En TypeScript, use cardAttachment() con CardTaskModuleTaskInfo. En Python, use card_attachment(AdaptiveCardAttachment(...)) with CardTaskModuleTaskInfo.

Nota:

La característica de cuadro de diálogo requiere que los dominios de las direcciones URL que quieras cargar se incluyan en la matriz en el validDomains manifiesto de la aplicación.

En la sección siguiente se especifica el tamaño del cuadro de diálogo que permite al usuario establecer la altura y el ancho del cuadro de diálogo.

Tamaño de cuadro de diálogo

Los valores de width y height establecen la altura y el ancho del cuadro de diálogo en píxeles. Según el tamaño de la ventana de Teams y la resolución de pantalla, estos valores pueden reducirse proporcionalmente mientras se mantiene la relación de aspecto.

Si width y height son small, medium o large, el tamaño del rectángulo rojo de la imagen siguiente es una proporción del espacio disponible, 20 %, 50 % y 60 % para width y 20 %, 50 % y 66 % para height:

Ejemplo de cambio de tamaño de cuadro de diálogo

En la siguiente sección se proporcionan ejemplos de desencadenamiento y control de diálogos mediante el SDK de Teams.

Desencadenar un cuadro de diálogo con TaskFetchAction

Para abrir un cuadro de diálogo, envía una tarjeta adaptativa con un TaskFetchAction botón. Cuando el usuario selecciona el botón, Teams envía una función de Invocar captura de tareas a la aplicación. Los datos de value cada botón especifican el tipo de cuadro de diálogo que se abrirá (por ejemplo, { "data": "AdaptiveCard" }).

using System.Text.Json;
using Microsoft.Teams.Apps;
using Microsoft.Teams.Apps.Schema;
using Microsoft.Teams.Cards;

teams.OnMessage(async (context, cancellationToken) =>
{
    var card = new AdaptiveCard
    {
        Body = new List<CardElement>
        {
            new TextBlock("Task Module Invocation from Adaptive Card")
            {
                Weight = TextWeight.Bolder,
                Size = TextSize.Large
            }
        },
        Actions = new List<Action>
        {
            new TaskFetchAction(new Dictionary<string, object?> { { "data", "AdaptiveCard" } })
            { Title = "Adaptive Card" },
            new TaskFetchAction(new Dictionary<string, object?> { { "data", "CustomForm" } })
            { Title = "Custom Form" },
            new TaskFetchAction(new Dictionary<string, object?> { { "data", "MultiStep" } })
            { Title = "Multi-step Form" }
        }
    };

    TeamsAttachment attachment = TeamsAttachment.CreateBuilder()
        .WithAdaptiveCard(JsonSerializer.SerializeToElement(card))
        .Build();

    await context.SendAsync(new MessageActivityInput().AddAttachment(attachment), cancellationToken);
});

Controlar el evento de apertura del cuadro de diálogo

Cuando Teams envía una función Invocar captura de tareas, la aplicación devuelve el contenido del cuadro de diálogo. El contenido puede ser una tarjeta adaptable o una dirección URL de una página web. En C#, ajuste los metadatos del cuadro de diálogo en una ContinueTask respuesta. En TypeScript, devuelve un con type: 'continue'.TaskModuleResponse En Python, devolver un que InvokeResponse contenga un TaskModuleContinueResponse.

using System.Text.Json;
using Microsoft.Teams.Apps;
using Microsoft.Teams.Apps.Schema;
using Microsoft.Teams.Apps.TaskModules;
using Microsoft.Teams.Cards;

teams.OnTaskFetch(async (context, cancellationToken) =>
{
    await Task.CompletedTask;

    // The button's Action.Submit payload arrives on the invoke value, nested under "data".
    string? data = context.Activity.Value?.Data is JsonElement value
        && value.TryGetProperty("data", out JsonElement dataProp)
            ? dataProp.GetString()
            : null;

    if (data == "CustomForm")
    {
        return TaskModuleResponse.CreateBuilder()
            .WithType(TaskModuleResponseTypes.Continue)
            .WithTitle("Custom Form")
            .WithWidth(510)
            .WithHeight(450)
            .WithUrl($"{botEndpoint}/customform")
            .WithFallbackUrl($"{botEndpoint}/customform")
            .Build();
    }

    if (data == "MultiStep")
    {
        var step1Card = new AdaptiveCard
        {
            Version = "1.5",
            Body = new List<CardElement>
            {
                new TextBlock("Multi-step Form: Step 1") { Wrap = true },
                new TextInput { Id = "name", Label = "Name" }
            },
            Actions = new List<Microsoft.Teams.Cards.Action>
            {
                new SubmitAction { Title = "Next" }
            }
        };

        TeamsAttachment step1Attachment = TeamsAttachment.CreateBuilder()
            .WithAdaptiveCard(JsonSerializer.SerializeToElement(step1Card))
            .Build();

        return TaskModuleResponse.CreateBuilder()
            .WithType(TaskModuleResponseTypes.Continue)
            .WithTitle("Multi-step Form")
            .WithWidth(400)
            .WithHeight(300)
            .WithCard(step1Attachment)
            .Build();
    }

    var dialogCard = new AdaptiveCard
    {
        Version = "1.5",
        Body = new List<CardElement>
        {
            new TextInput { Id = "usertext", Label = "Enter text" }
        },
        Actions = new List<Microsoft.Teams.Cards.Action>
        {
            new SubmitAction { Title = "Submit" }
        }
    };

    TeamsAttachment attachment = TeamsAttachment.CreateBuilder()
        .WithAdaptiveCard(JsonSerializer.SerializeToElement(dialogCard))
        .Build();

    return TaskModuleResponse.CreateBuilder()
        .WithType(TaskModuleResponseTypes.Continue)
        .WithTitle("Adaptive Card: Inputs")
        .WithWidth(400)
        .WithHeight(200)
        .WithCard(attachment)
        .Build();
});

Controlar el envío del cuadro de diálogo

Cuando un usuario presiona un cuadro de Action.Submit diálogo, Teams envía una tarea de invocación de envío a la aplicación. Puede responder completando la tarea, mostrando un mensaje o abriendo otro cuadro de diálogo (por ejemplo, para encadenar formularios de varios pasos).

using System.Text.Json;
using Microsoft.Teams.Apps.TaskModules;
using Microsoft.Teams.Cards;

teams.OnTaskSubmit(async (context, cancellationToken) =>
{
    var activity = context.Activity;
    var json = JsonSerializer.Deserialize<JsonElement>(JsonSerializer.Serialize(activity));
    var submitData = JsonSerializer.Deserialize<Dictionary<string, object>>(
        json.GetProperty("value").GetProperty("data").GetRawText());
    var submissionType = submitData?.GetValueOrDefault("submissiontype")?.ToString();

    if (submissionType == "multi_step_1")
    {
        var name = submitData["name"]?.ToString();
        var step2Card = new AdaptiveCard
        {
            Body = new List<CardElement>
            {
                new TextBlock("Step 2 of 2 - Your Email") { Size = TextSize.Large, Weight = TextWeight.Bolder },
                new TextInput { Id = "email", Label = "Email", Placeholder = "Enter your email", IsRequired = true }
            },
            Actions = new List<Action>
            {
                new SubmitAction().WithTitle("Submit").WithData(
                    new Union<string, SubmitActionData>(new SubmitActionData
                    {
                        NonSchemaProperties = new Dictionary<string, object?>
                        {
                            { "submissiontype", "multi_step_2" },
                            { "name", name! }
                        }
                    }))
            }
        };

        TeamsAttachment step2Attachment = TeamsAttachment.CreateBuilder()
            .WithAdaptiveCard(JsonSerializer.SerializeToElement(step2Card))
            .Build();

        return TaskModuleResponse.CreateBuilder()
            .WithType(TaskModuleResponseTypes.Continue)
            .WithTitle("Multi-step Form: Step 2")
            .WithWidth(400)
            .WithHeight(300)
            .WithCard(step2Attachment)
            .Build();
    }

    if (submissionType == "multi_step_2")
    {
        await context.SendAsync($"Hi {submitData["name"]}, thanks for submitting! Your email is {submitData["email"]}", cancellationToken);
        return TaskModuleResponse.CreateBuilder()
            .WithType(TaskModuleResponseTypes.Message)
            .WithMessage("Multi-step form completed!")
            .Build();
    }

    var usertext = submitData?.GetValueOrDefault("usertext")?.ToString();
    await context.SendAsync($"You submitted: {usertext}", cancellationToken);
    return TaskModuleResponse.CreateBuilder()
        .WithType(TaskModuleResponseTypes.Message)
        .WithMessage("Thanks for submitting!")
        .Build();
});

Instrucciones de teclado y accesibilidad

Para los cuadros de diálogo basados en URL que cargan contenido HTML, asegúrese de la accesibilidad del teclado:

  • Use el atributo tabindex en las etiquetas HTML para controlar qué elementos se pueden enfocar y para definir una navegación secuencial por teclado con las teclas Tab y Mayús-Tab .
  • Controle la tecla Esc correctamente en el JavaScript de la página de diálogo.

Microsoft Teams garantiza que la navegación con el teclado funcione correctamente desde el encabezado del cuadro de diálogo al HTML y viceversa.

Ejemplo de código

Ejemplo de nombre Descripción .NET Node.js Python
Módulos de tareas del bot En esta aplicación de ejemplo se muestra cómo usar cuadros de diálogo (denominados módulos de tareas en TeamsJS v1.x) con el SDK de IA de Teams. View View View

Paso siguiente

Vea también