Invocar e ignorar diálogos no SDK do Teams

Este artigo aborda como invocar e ignorar caixas de diálogo (anteriormente conhecidas como módulos de tarefa) usando o SDK do Teams (Biblioteca de IA do Teams). No SDK do Teams, as caixas de diálogo são invocadas a partir de ações do Cartão Adaptável usando as TaskFetchAction caixas de diálogo abertas e enviadas App na classe.

O registro do evento varia de acordo com o idioma:

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

O conteúdo da caixa de diálogo pode ser um Cartão Adaptável ou uma página da Web baseada em URL.

As caixas de diálogo também podem ser invocadas por meio de outras abordagens, dependendo da arquitetura do aplicativo:

Para obter diretrizes de migração do Bot Framework para o SDK do Teams, consulte Migrar do BotBuilder.

A tabela a seguir resume como os diálogos funcionam no SDK do Teams:

Etapa Caixa de diálogo com o Cartão Adaptável Caixa de diálogo com URL da página da Web
Disparar a caixa de diálogo 1. Envie um Cartão Adaptável com um TaskFetchAction botão para o usuário. Os dados da value ação especificam o tipo de caixa de diálogo a ser aberta.

2. Quando o usuário seleciona o botão, o Teams envia uma invocação de busca de tarefa para seu aplicativo.
1. Envie um Cartão Adaptável com um TaskFetchAction botão para o usuário.

2. Quando o usuário seleciona o botão, o Teams envia uma invocação de busca de tarefa para seu aplicativo.
Manipular o evento de abertura da caixa de diálogo 3. No manipulador de abertura da caixa de diálogo, retorne uma resposta contínua do módulo de tarefa contendo metadados da caixa de diálogo (título, dimensões e o Cartão Adaptativo a ser exibido). Em C#, use TaskInfo com um ContinueTask wrapper. Em TypeScript, use CardTaskModuleTaskInfo. Em Python, use CardTaskModuleTaskInfo em um .TaskModuleContinueResponse 3. No manipulador de abertura da caixa de diálogo, retorne uma resposta contínua do módulo de tarefa contendo metadados da caixa de diálogo com uma url propriedade apontando para a página da Web. O domínio da URL deve estar na matriz do manifesto do validDomains aplicativo. Em C#, use TaskInfo. Em TypeScript, use UrlTaskModuleTaskInfo. Em Python, use UrlTaskModuleTaskInfo em um .TaskModuleContinueResponse
Lidar com o envio de diálogos 4. Quando o usuário pressiona um Action.Submit botão, o Teams envia uma invocação de envio de tarefa para seu aplicativo com os dados do formulário.

5. Você pode responder por:
• Não fazer nada (tarefa concluída)
• Exibindo uma mensagem (C#: MessageTask, TypeScript/Python: TaskModuleMessageResponse)
• Encadeamento para outra caixa de diálogo (C#: ContinueTask, TypeScript/Python: TaskModuleContinueResponse)
4. A página da Web chama a biblioteca de clientes do Teams JS para enviar dados de volta. O Teams envia uma invocação de envio de tarefa para seu aplicativo com o resultado.

A próxima seção descreve os metadados de caixa de diálogo que definem o conteúdo e a aparência de uma caixa de diálogo.

Metadados de caixa de diálogo

Os metadados da caixa de diálogo definem o conteúdo e a aparência de uma caixa de diálogo. Cada idioma usa seus próprios tipos para representar esses metadados:

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

A tabela a seguir lista as propriedades comuns em todos os idiomas:

Atributo Tipo Descrição
title string Esse atributo aparece abaixo do nome do aplicativo e à direita do ícone do aplicativo.
height número ou cadeia de caracteres Esse atributo pode ser um número que representa a altura da caixa de diálogo em pixels, ou small, medium, ou large. Em C#, use Union<int, Size>.
width número ou cadeia de caracteres Esse atributo pode ser um número que representa a largura da caixa de diálogo em pixels ou small, medium, ou large. Em C#, use Union<int, Size>.
url string A URL da página carregada como um <iframe> dentro da caixa de diálogo. O domínio da URL deve estar na matriz validDomains do aplicativo no manifesto do aplicativo. Use UrlTaskModuleTaskInfo em TypeScript/Python ou defina a Url propriedade em TaskInfo C#.
card Anexo O Cartão Adaptável a ser exibido na caixa de diálogo. Em C#, defina a Card propriedade com TaskInfo um Attachment. No TypeScript, use cardAttachment() com CardTaskModuleTaskInfo. Em Python, use card_attachment(AdaptiveCardAttachment(...)) com CardTaskModuleTaskInfo.

Observação

O recurso de diálogo requer que os domínios de todas as URLs que você deseja carregar estejam incluídos na matriz no manifesto validDomains do seu aplicativo.

A próxima seção especifica o dimensionamento da caixa de diálogo que permite ao usuário definir a altura e a largura da caixa de diálogo.

Dimensionamento da caixa de diálogo

Os valores de width e height defina a altura e a largura da caixa de diálogo em pixels. Dependendo do tamanho da janela do Teams e da resolução da tela, esses valores podem ser reduzidos proporcionalmente, mantendo a taxa de proporção.

Se width e height forem small, medium ou large, o tamanho do retângulo vermelho na imagem a seguir é uma proporção do espaço disponível, 20%, 50% e 60% para width e 20%, 50% e 66% para height:

Exemplo de dimensionamento da caixa de diálogo

A próxima seção fornece exemplos de como disparar e manipular caixas de diálogo usando o SDK do Teams.

Disparar uma caixa de diálogo com TaskFetchAction

Para abrir uma caixa de diálogo, envie um Cartão Adaptável com um TaskFetchAction botão. Quando o usuário seleciona o botão, o Teams envia uma invocação de busca de tarefa para seu aplicativo. Os dados de value cada botão especificam o tipo de caixa de diálogo a ser aberta (por exemplo, { "data": "AdaptiveCard" }).

using Microsoft.Teams.Api.Activities;
using Microsoft.Teams.Cards;

teamsApp.OnMessage(async (context) =>
{
    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" }
        }
    };

    await context.Send(new MessageActivity
    {
        Attachments = new List<Attachment>
        {
            new Attachment
            {
                ContentType = new ContentType("application/vnd.microsoft.card.adaptive"),
                Content = card
            }
        }
    });
});

Manipular o evento de abertura da caixa de diálogo

Quando o Teams envia uma invocação de busca de tarefa, seu aplicativo retorna o conteúdo da caixa de diálogo. O conteúdo pode ser um Cartão Adaptável ou uma URL da página da Web. Em C#, encapsule os metadados da caixa de diálogo em uma ContinueTask resposta. No TypeScript, retorna um TaskModuleResponse com type: 'continue'. Em Python, retorna um InvokeResponse contendo um TaskModuleContinueResponse.

using System.Text.Json;
using Microsoft.Teams.Api.TaskModules;
using Microsoft.Teams.Cards;
using Microsoft.Teams.Common;

teamsApp.OnTaskFetch(async (context) =>
{
    var activity = context.Activity;
    var json = JsonSerializer.Deserialize<JsonElement>(JsonSerializer.Serialize(activity));
    var data = json.GetProperty("value").GetProperty("data").GetProperty("data").GetString();

    TaskInfo taskInfo;

    if (data == "CustomForm")
    {
        taskInfo = new TaskInfo
        {
            Title = "Custom Form",
            Width = new Union<int, Size>(510),
            Height = new Union<int, Size>(450),
            Url = $"{botEndpoint}/customform",
            FallbackUrl = $"{botEndpoint}/customform"
        };
    }
    else if (data == "MultiStep")
    {
        var step1Card = new AdaptiveCard
        {
            Body = new List<CardElement>
            {
                new TextBlock("Step 1 of 2 - Your Name") { Size = TextSize.Large, Weight = TextWeight.Bolder },
                new TextInput { Id = "name", Label = "Name", Placeholder = "Enter your name", IsRequired = true }
            },
            Actions = new List<Action>
            {
                new SubmitAction().WithTitle("Next").WithData(
                    new Union<string, SubmitActionData>(new SubmitActionData
                    {
                        NonSchemaProperties = new Dictionary<string, object?> { { "submissiontype", "multi_step_1" } }
                    }))
            }
        };

        taskInfo = new TaskInfo
        {
            Title = "Multi-step Form",
            Width = new Union<int, Size>(400),
            Height = new Union<int, Size>(300),
            Card = new Attachment
            {
                ContentType = new ContentType("application/vnd.microsoft.card.adaptive"),
                Content = step1Card
            }
        };
    }
    else
    {
        var dialogCard = new AdaptiveCard
        {
            Body = new List<CardElement>
            {
                new TextBlock("Enter Text Here") { Weight = TextWeight.Bolder },
                new TextInput { Id = "usertext", Placeholder = "add some text and submit", IsMultiline = true }
            },
            Actions = new List<Action> { new SubmitAction { Title = "Submit" } }
        };

        taskInfo = new TaskInfo
        {
            Title = "Adaptive Card: Inputs",
            Width = new Union<int, Size>(400),
            Height = new Union<int, Size>(200),
            Card = new Attachment
            {
                ContentType = new ContentType("application/vnd.microsoft.card.adaptive"),
                Content = dialogCard
            }
        };
    }

    return new Response(new ContinueTask(taskInfo));
});

Lidar com o envio de diálogos

Quando um usuário pressiona uma caixa de Action.Submit diálogo, o Teams envia uma invocação de envio de tarefa para o seu aplicativo. Você pode responder concluindo a tarefa, mostrando uma mensagem ou abrindo outra caixa de diálogo (por exemplo, para encadear formulários de várias etapas).

using System.Text.Json;
using Microsoft.Teams.Api.TaskModules;
using Microsoft.Teams.Cards;
using Microsoft.Teams.Common;

teamsApp.OnTaskSubmit(async (context) =>
{
    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! }
                        }
                    }))
            }
        };

        var taskInfo = new TaskInfo
        {
            Title = "Multi-step Form: Step 2",
            Width = new Union<int, Size>(400),
            Height = new Union<int, Size>(300),
            Card = new Attachment
            {
                ContentType = new ContentType("application/vnd.microsoft.card.adaptive"),
                Content = step2Card
            }
        };

        return new Response(new ContinueTask(taskInfo));
    }

    if (submissionType == "multi_step_2")
    {
        await context.Send($"Hi {submitData["name"]}, thanks for submitting! Your email is {submitData["email"]}");
        return new Response(new MessageTask("Multi-step form completed!"));
    }

    var usertext = submitData?.GetValueOrDefault("usertext")?.ToString();
    await context.Send($"You submitted: {usertext}");
    return new Response(new MessageTask("Thanks for submitting!"));
});

Diretrizes de teclado e acessibilidade

Para caixas de diálogo baseadas em URL que carregam conteúdo HTML, verifique a acessibilidade do teclado:

  • Use o atributo tabindex em suas marcas HTML para controlar quais elementos podem ser focalizados e para definir a navegação sequencial do teclado com as teclas Tab e Shift-Tab .
  • Manipule a tecla Esc adequadamente no JavaScript para sua página de diálogo.

O Microsoft Teams garante que a navegação pelo teclado funcione corretamente desde o cabeçalho da caixa de diálogo até o HTML e vice-versa.

Exemplo de código

Nome do exemplo Descrição .NET Node.js Python
Módulos de tarefas de bot Este aplicativo de exemplo demonstra como usar caixas de diálogo (chamadas de módulos de tarefa no TeamsJS v1.x) usando o SDK de IA do Teams. View View View

Próxima etapa

Confira também