Compartilhar via


Criar uma aplicação de separador do dashboard

Um dashboard é uma ferramenta para monitorizar, analisar e apresentar dados para obter informações sobre uma organização ou um processo específico. Os dashboards no Teams permitem-lhe monitorizar e ver métricas importantes.

O modelo de separador do dashboard do Teams Toolkit permite-lhe começar a integrar uma tela com vários cartões que fornecem uma descrição geral dos conteúdos no Teams. Você pode:

  • Utilize widgets para apresentar conteúdos de aplicações e serviços no separador do dashboard.
  • Integre a sua aplicação com o Graph API para visualizar detalhes sobre a implementação dos dados selecionados.
  • Crie dashboards personalizáveis que permitam à sua empresa definir objetivos específicos que o ajudam a controlar as informações que precisa de ver em várias áreas e em vários departamentos.

Captura de ecrã a mostrar o exemplo de um dashboard.

A sua equipa pode obter as atualizações mais recentes de diferentes origens no Teams através da aplicação de separador dashboard do Teams. Utilize aplicações de separador do dashboard para ligar várias métricas, origens de dados, APIs e serviços. As aplicações de separador do dashboard ajudam a sua empresa a extrair informações relevantes das origens e a apresentá-la aos utilizadores. Para obter mais informações sobre como criar uma aplicação de separador de dashboard, veja Guia passo a passo.

Adicionar um novo dashboard

Depois de criar uma aplicação de separador do dashboard, pode adicionar um novo dashboard.

Para adicionar um novo dashboard, siga estes passos:

  1. Criar uma classe de dashboard
  2. Substituir métodos para personalizar a aplicação de separador do dashboard
  3. Adicionar uma rota para a nova aplicação de separador do dashboard
  4. Modificar manifesto para adicionar uma nova aplicação de separador do dashboard

Criar uma classe de dashboard

Crie um ficheiro com a extensão para o .tsx dashboard no src/dashboards diretório, por exemplo, YourDashboard.tsx. Em seguida, crie uma classe que expanda o BaseDashboard class from
@microsoft/teamsfx-react.

//YourDashboard.tsx
import { BaseDashboard } from "@microsoft/teamsfx-react";

export default class YourDashboard extends BaseDashboard<any, any> {}

Observação

Todos os métodos são opcionais. Se não substituir nenhum método, é utilizado o esquema de dashboard predefinido.

Substituir métodos para personalizar a aplicação de separador do dashboard

A BaseDashboard classe fornece poucos métodos que pode substituir para personalizar o esquema do dashboard. A tabela seguinte lista os métodos que pode substituir:

Métodos Function
styling() Personalize o estilo do dashboard.
layout() Definir esquema de widgets.

O código seguinte é um exemplo para personalizar o esquema do dashboard:

.your-dashboard-layout {
  grid-template-columns: 6fr 4fr;
}
import { BaseDashboard } from "@microsoft/teamsfx-react";
import ListWidget from "../widgets/ListWidget";
import ChartWidget from "../widgets/ChartWidget";

export default class YourDashboard extends BaseDashboard<any, any> {
  override styling(): string {
    return "your-dashboard-layout";
  }

  override layout(): JSX.Element | undefined {
    return (
      <>
        <ListWidget />
        <ChartWidget />
      </>
    );
  }
}

Adicionar uma rota para a nova aplicação de separador do dashboard

Tem de ligar o widget a um ficheiro de origem de dados. O widget recolhe os dados apresentados no dashboard a partir do ficheiro de origem.

Abra o src/App.tsx ficheiro e adicione uma rota para o novo dashboard. Veja um exemplo:

import YourDashboard from "./dashboards/YourDashboard";

export default function App() {
  ...
  <Route path="/yourdashboard" element={<YourDashboard />} />
  ...
}

Modificar manifesto para adicionar uma nova aplicação de separador do dashboard

Abra o appPackage/manifest.json ficheiro e adicione um novo separador do dashboard em staticTabs. Para obter mais informações, consulte o manifesto do aplicativo. Veja um exemplo:

{
  "entityId": "index1",
  "name": "Your Dashboard",
  "contentUrl": "${{TAB_ENDPOINT}}/index.html#/yourdashboard",
  "websiteUrl": "${{TAB_ENDPOINT}}/index.html#/yourdashboard",
  "scopes": ["personal"]
}

Personalizar o esquema do dashboard

O TeamsFx fornece métodos convenientes para definir e modificar o esquema do dashboard. Seguem-se os métodos:

  • Três widgets seguidos com a altura de 350 px ocupando 20 por cento, 60 por cento e 20 por cento da largura, respetivamente.

    .customize-class-name {
      grid-template-rows: 350px;
      grid-template-columns: 2fr 6fr 2fr;
    }
    
    export default class SampleDashboard extends BaseDashboard<any, any> {
    
      override styling(): string {
        return "customize-class-name";
      }
    
      override layout(): JSX.Element | undefined {
        return (
          <>
           <ListWidget />
           <ChartWidget />
           <NewsWidget />
          </>
        );
      }
    }
    

    Captura de ecrã a mostrar o esquema do dashboard personalizado.

  • Dois widgets numa linha com uma largura de 600 px e 1100 px. A altura da primeira linha é a altura máxima do conteúdo e a altura da segunda linha é de 400 px.

    .customize-class-name {
      grid-template-rows: max-content 400px;
      grid-template-columns: 600px 1100px;
    }
    
        export default class SampleDashboard extends Dashboard {
      override styling(): string {
        return "customize-class-name";
      }
    
      override layout(): JSX.Element | undefined {
        return (
          <>
        <ListWidget />
        <ChartWidget />
        <NewsWidget />
          </>
        );
      }
        }
    

    Captura de ecrã a mostrar a personalização da altura e largura do esquema do dashboard.

  • Disponha dois widgets numa coluna.

    .one-column {
        display: grid;
        gap: 20px;
        grid-template-rows: 1fr 1fr;
      }
    
      export default class SampleDashboard extends BaseDashboard<any, any> {
        override layout(): JSX.Element | undefined {
          return (
            <>
              <NewsWidget />
              <div className="one-column">
                <ListWidget />
                <ChartWidget />          
              </div>
            </>
          );
        }
      }
    

    Captura de ecrã a mostrar a personalização de dois widgets.

Abstração da aplicação do separador Dashboard

Para ajustar o esquema do dashboard, o TeamsFx fornece uma BaseDashboard classe para os programadores implementarem um dashboard.

O código seguinte é um exemplo de uma BaseDashboard classe:

function dashboardStyle(isMobile?: boolean) {
  return mergeStyles({
    display: "grid",
    gap: "20px",
    padding: "20px",
    gridTemplateRows: "1fr",
    gridTemplateColumns: "4fr 6fr",
    ...(isMobile === true ? { gridTemplateColumns: "1fr", gridTemplateRows: "1fr" } : {}),
  });
}

interface BaseDashboardState {
  isMobile?: boolean;
  showLogin?: boolean;
  observer?: ResizeObserver;
}

export class BaseDashboard<P, S> extends Component<P, S & BaseDashboardState> {
  private ref: React.RefObject<HTMLDivElement>;

  public constructor(props: Readonly<P>) {
    super(props);
    this.state = {
      isMobile: undefined,
      showLogin: undefined,
      observer: undefined,
    } as S & BaseDashboardState;
    this.ref = React.createRef<HTMLDivElement>();
  }

  public async componentDidMount() {
    const observer = new ResizeObserver((entries) => {
      for (const entry of entries) {
        if (entry.target === this.ref.current) {
          const { width } = entry.contentRect;
          this.setState({ isMobile: width < 600 } as S & BaseDashboardState);
        }
      }
    });
    observer.observe(this.ref.current!);
  }

  public componentWillUnmount(): void {
    if (this.state.observer && this.ref.current) {
      this.state.observer.unobserve(this.ref.current);
    }
  }

  public render() {
    return (
      <div
        ref={this.ref}
        className={mergeStyles(dashboardStyle(this.state.isMobile), this.styling())}
      >
        {this.layout()}
      </div>
    );
  }

  protected layout(): JSX.Element | undefined {
    return undefined;
  }

  protected styling(): string {
    return null;
  }
}

Na classe , o BaseDashboard TeamsFx fornece esquemas básicos com métodos personalizáveis. O dashboard continua a ser um componente de reação e o TeamsFx fornece implementações básicas de funções com base no ciclo de vida dos componentes do React, tais como:

  • Implementar uma lógica de composição básica com base no esquema de grelha.
  • Adicionar um observador para se adaptar automaticamente aos dispositivos móveis.

Seguem-se os métodos personalizáveis a substituir:

Métodos Função Recomendamos que substitua
constructor() Inicializa o estado e as variáveis do dashboard. Não
componentDidMount() Invoca após a montagem de um componente. Não
componentWillUnmount() Invoca quando um componente é desmontado. Não
render() Invoca quando existe uma atualização. O esquema predefinido do dashboard é definido neste método. Não
layout Define o esquema do widget no dashboard. Pode substituir este método. Sim
styling() Para personalizar o estilo do dashboard. Pode substituir este método. Sim

Utilizar um widget no dashboard

Os widgets apresentam informações configuráveis e gráficos nos dashboards. Aparecem no quadro de widget onde pode afixar, remover, dispor, redimensionar e personalizar widgets para refletir os seus interesses. O seu quadro de widget está otimizado para mostrar widgets relevantes e conteúdos personalizados com base na sua utilização.

Personalizar o widget

Pode personalizar o widget ao substituir os seguintes métodos na BaseWidget classe :

  • Substitua header(), body()e footer() para personalizar o widget.

    export class NewsWidget extends BaseWidget<any, any> {
    override header(): JSX.Element | undefined {
    return (
      <div>
        <News28Regular />
        <Text>Your News</Text>
        <Button icon={<MoreHorizontal32Regular />} appearance="transparent" />
      </div>
    );
    }
    
    override body(): JSX.Element | undefined {
    return (
      <div>
        <Image src="image.svg" />
        <Text>Lorem Ipsum Dolor</Text>
        <Text>
          Lorem ipsum dolor sit amet, consectetur adipiscing elit. Enim,
          elementum sed
        </Text>
      </div>
    );
    }
    
    override footer(): JSX.Element | undefined {
    return (
      <Button
        appearance="transparent"
        icon={<ArrowRight16Filled />}
        iconPosition="after"
        size="small"
      >
        View details
      </Button>
    );
    }
    }
    

    Captura de ecrã a mostrar o exemplo de conteúdo de cabeçalho, corpo e rodapé num widget.

  • Substitua body() e footer() personalize o widget.

    export class NewsWidget extends BaseWidget<any, any> {
    override body(): JSX.Element | undefined {
    return (
      <div>
        <Image src="image.svg" />
        <Text>Lorem Ipsum Dolor</Text>
        <Text>
          Lorem ipsum dolor sit amet, consectetur adipiscing elit. Enim,
          elementum sed
        </Text>
      </div>
    );
    }
    
    override footer(): JSX.Element | undefined {
    return (
      <Button
        appearance="transparent"
        icon={<ArrowRight16Filled />}
        iconPosition="after"
        size="small"
      >
        View details
      </Button>
    );
    }
    }
    

    Captura de ecrã a mostrar o conteúdo do corpo e do rodapé num widget.

  • Substitua body() para personalizar o widget.

    export class NewsWidget extends BaseWidget<any, any> {
    override body(): JSX.Element | undefined {
    return (
      <div>
        <Image src="image.svg" />
        <Text>Lorem Ipsum Dolor</Text>
        <Text>
          Lorem ipsum dolor sit amet, consectetur adipiscing elit. Enim,
          elementum sed
        </Text>
      </div>
    );
    }
    }
    

    Captura de ecrã a mostrar o conteúdo do corpo num widget.

Incluir um carregador de dados

Se quiser incluir um carregador de dados no widget antes de o widget ser carregado, pode adicionar uma propriedade ao estado do widget para indicar que o carregador de dados é loading(). Pode utilizar esta propriedade para mostrar um indicador de carregamento ao utilizador.

Exemplo:

    override loading(): JSX.Element | undefined {
     return (
      <div className="loading">
       <Spinner label="Loading..." labelPosition="below" />
      </div>
     );
    }

Agora, o controlo giratório de carregamento é apresentado enquanto os dados estão a ser carregados. Quando os dados são carregados, o controlo giratório de carregamento é ocultado e os dados da lista e o botão de rodapé são apresentados.

A representação gráfica mostra o controlo giratório de carregamento enquanto os dados estão a ser carregados.

Processar o estado vazio

Pode apresentar um conteúdo específico no seu widget quando os dados estiverem vazios. Para tal, tem de modificar o body método no ficheiro widget para adotar diferentes estados dos dados.

O exemplo seguinte mostra como apresentar uma imagem vazia quando os dados de ListWidget estão vazios.

override body(): JSX.Element | undefined {
  let hasData = this.state.data && this.state.data.length > 0;
  return (
    <div>
      {hasData ? (
        <>
          {this.state.data?.map((t: ListModel) => {
            ...
          })}
        </>
      ) : (
        <div>
          <Image src="empty-default.svg" height="150px" />
          <Text align="center">No data</Text>
        </div>
      )}
    </div>
  );
}

Pode utilizar uma abordagem semelhante para remover o conteúdo do rodapé do widget quando os dados estão vazios.

  override footer(): JSX.Element | undefined {
    let hasData = this.state.data && this.state.data.length > 0;
    if (hasData) {
      return <Button>...</Button>;
    }
  }

Quando os dados estão vazios, o widget de lista é apresentado da seguinte forma:

Captura de ecrã que não mostra dados na lista.

Atualizar dados conforme agendado

O exemplo seguinte mostra como apresentar dados em tempo real num widget. O widget apresenta a hora e as atualizações atuais.

interface IRefreshWidgetState {
  data: string;
}

export class RefreshWidget extends BaseWidget<any, IRefreshWidgetState> {
  override body(): JSX.Element | undefined {
    return <>{this.state.data}</>;
  }

  async componentDidMount() {
    setInterval(() => {
      this.setState({ data: new Date().toLocaleTimeString() });
    }, 1000);
  }
}

Pode modificar setInterval o método para chamar a sua própria função para atualizar dados como este setInterval(() => yourGetDataFunction(), 1000).

Abstração de widget

Para simplificar o desenvolvimento de um widget, o SDK teamsFx fornece uma BaseWidget classe para os programadores herdarem para implementar um widget que satisfaz as suas necessidades sem prestar muita atenção para implementar o esquema de widget.

O código seguinte é um exemplo da classe BaseWidget:

export interface IWidgetClassNames {
  root?: string;
  header?: string;
  body?: string;
  footer?: string;
}

const classNames: IWidgetClassNames = mergeStyleSets({
  root: {
    display: "grid",
    padding: "1.25rem 2rem 1.25rem 2rem",
    backgroundColor: tokens.colorNeutralBackground1,
    border: "1px solid var(--colorTransparentStroke)",
    boxShadow: tokens.shadow4,
    borderRadius: tokens.borderRadiusMedium,
    gap: tokens.spacingHorizontalL,
    gridTemplateRows: "max-content 1fr max-content",
  },
  header: {
    display: "grid",
    height: "max-content",
    "& div": {
      display: "grid",
      gap: tokens.spacingHorizontalS,
      alignItems: "center",
      gridTemplateColumns: "min-content 1fr min-content",
    },
    "& svg": {
      height: "1.5rem",
      width: "1.5rem",
    },
    "& span": {
      fontWeight: tokens.fontWeightSemibold,
      lineHeight: tokens.lineHeightBase200,
      fontSize: tokens.fontSizeBase200,
    },
  },
  footer: {
    "& button": {
      width: "fit-content",
    },
  },
});

interface BaseWidgetState {
  loading?: boolean;
}

export class BaseWidget<P, S> extends Component<P, S & BaseWidgetState> {
  public constructor(props: Readonly<P>) {
    super(props);
    this.state = { loading: undefined } as S & BaseWidgetState;
  }

  public async componentDidMount() {
    this.setState({ ...(await this.getData()), loading: false });
  }

  public render() {
    const { root, header, body, footer } = this.styling();
    const showLoading = this.state.loading !== false && this.loading() !== undefined;
    return (
      <div className={mergeStyles(classNames.root, root)}>
        {this.header() && (
          <div className={mergeStyles(classNames.header, header)}>{this.header()}</div>
        )}
        {showLoading ? (
          this.loading()
        ) : (
          <>
            {this.body() !== undefined && <div className={body}>{this.body()}</div>}
            {this.footer() !== undefined && (
              <div className={mergeStyles(classNames.footer, footer)}>{this.footer()}</div>
            )}
          </>
        )}
      </div>
    );
  }

  protected async getData(): Promise<S> {
    return undefined;
  }

  protected header(): JSX.Element | undefined {
    return undefined;
  }

  protected body(): JSX.Element | undefined {
    return undefined;
  }

  protected footer(): JSX.Element | undefined {
    return undefined;
  }

  protected loading(): JSX.Element | undefined {
    return undefined;
  }

  protected styling(): IWidgetClassNames {
    return {};
  }
}

Seguem-se os métodos recomendados para substituir:

Métodos Função Recomendamos que substitua
constructor() Invoca a inicial this.state e chama o construtor da super classe React.Component. Não
componentDidMount() Invoca depois de um componente ser montado e atribui um valor à data propriedade do estado ao chamar o getData() método . Não
render() Invoca sempre que existir uma atualização. O esquema predefinido do dashboard é definido neste método. Não
getData() Invoca os dados necessários para o widget. O valor devolvido por este método está definido como this.state.data. Sim
header() Invoca o aspeto do cabeçalho do widget. Pode optar por substituir este método para personalizar um widget ou não, caso contrário, o widget não terá um cabeçalho. Sim
body() Invoca o aspeto do corpo do widget. Pode optar por substituir este método para personalizar um widget ou não, caso contrário, o widget não terá um corpo. Sim
footer() Invoca o aspeto do rodapé do widget. Pode optar por substituir este método para personalizar um widget ou não, caso contrário, o widget não terá um rodapé. Sim
loading() Invoca quando o widget está em processo de obtenção de dados. Se for necessário um indicador de carregamento, o método pode devolver um JSX.Element que contém os componentes necessários para compor o indicador de carregamento. Sim
style() Invoca um objeto que define os nomes de classe para as diferentes partes do widget. Sim

Microsoft Graph Toolkit como conteúdo de widget

O Microsoft Graph Toolkit é um conjunto de componentes Web renováveis e agnósticos, que ajudam a aceder e trabalhar com o Microsoft Graph. Pode utilizar o Microsoft Graph Toolkit com qualquer arquitetura Web ou sem uma arquitetura.

Para utilizar o Microsoft Graph Toolkit como conteúdo do widget, siga estes passos:

  1. Adicionar a funcionalidade SSO à sua aplicação Teams: o Microsoft Teams fornece uma função de início de sessão único (SSO) para uma aplicação obter o token de utilizador com sessão iniciada no Teams para aceder ao Microsoft Graph. Para obter mais informações, consulte a funcionalidade SSO para a sua aplicação Teams.

  2. Instale os npm pacotes necessários.

    Execute o seguinte comando na pasta do projeto tabs para instalar os pacotes necessários npm :

    npm install @microsoft/mgt-react @microsoft/mgt-teamsfx-provider
    
  3. Adicionar um novo widget Graph Toolkit: crie um novo ficheiro widget na pasta do projeto src/views/widgets , por exemplo, GraphWidget.tsx. Neste widget, iremos orientar os utilizadores para dar consentimento à nossa aplicação para aceder ao Microsoft Graph e, em seguida, mostrar a lista Todo do utilizador com o Microsoft Graph Toolkit.

    O código seguinte é um exemplo da utilização do componente Todo do Microsoft Graph Toolkit no widget:

    import { Providers, ProviderState, Todo } from "@microsoft/mgt-react";
    import { TeamsFxProvider } from "@microsoft/mgt-teamsfx-provider";
    
    import { loginAction } from "../../internal/login";
    import { TeamsUserCredentialContext } from "../../internal/singletonContext";
    import { BaseWidget } from "@microsoft/teamsfx-react";
    
    interface IGraphWidgetState {
      needLogin: boolean;
    }
    
    export class GraphWidget extends Widget<any, IGraphWidgetState> {
      override body(): JSX.Element | undefined {
        return <div>{this.state.needLogin === false && <Todo />}</div>;
      }
    
      async componentDidMount() {
        super.componentDidMount();
    
        // Initialize TeamsFx provider
        const provider = new TeamsFxProvider(TeamsUserCredentialContext.getInstance().getCredential(), [
         "Tasks.ReadWrite",
    ]);
        Providers.globalProvider = provider;
    
        // Check if user is signed in
        if (await this.checkIsConsentNeeded()) {
          await loginAction(["Tasks.ReadWrite"]);
    }
    
    // Update signed in state
    Providers.globalProvider.setState(ProviderState.SignedIn);
    this.setState({ needLogin: false });
    
      }
    
      /**
    
      * Check if user needs to consent
      * @returns true if user needs to consent
      */
    
      async checkIsConsentNeeded() {
        let needConsent = false;
        try {
          await TeamsUserCredentialContext.getInstance().getCredential().getToken(["Tasks.ReadWrite"]);
        } catch (error) {
          needConsent = true;
        }
        return needConsent;
      }
    }
    

    Pode utilizar componentes alternativos do Microsoft Graph Toolkit no seu widget. Para obter mais informações, consulte Microsoft Graph Toolkit.

  4. Adicione o widget ao esquema do dashboard. Inclua o novo widget no seu ficheiro de dashboard.

    ...
    export default class YourDashboard extends BaseDashboard<any, any> {
      ...
      override layout(): undefined | JSX.Element {
        return (
          <>
            <GraphWiget />
          </>
        );
      }
      ...
    }
    

Agora, inicie ou atualize a sua aplicação Teams, verá o novo widget com o Microsoft Graph Toolkit.

Chamada à Graph API

A Microsoft Graph API é uma API Web que pode utilizar para comunicar com a Microsoft Cloud e outros serviços. Aplicativos personalizados podem usar a API do Microsoft Graph para se conectar aos dados e usá-los em aplicativos personalizados para aprimorar a produtividade organizacional.

Antes de implementar a lógica de chamadas da Graph API, é necessário ativar o SSO para o projeto de dashboard. Para obter mais informações, consulte Adicionar início de sessão único à aplicação Teams.

Para adicionar uma chamada à Graph API:

Chamar a Graph API a partir do front-end (utilizar permissões delegadas)

Se quiser chamar uma Graph API a partir do separador de front-end, siga estes passos:

  1. Para obter o nome do âmbito de permissão associado à Graph API que pretende invocar, veja Graph API.

  2. Crie um cliente do Graph ao adicionar o âmbito relacionado com a Graph API que pretende chamar.

    let credential: TeamsUserCredential;  
    credential = TeamsUserCredentialContext.getInstance().getCredential();
    const graphClient: Client = createMicrosoftGraphClientWithCredential(credential, scope);
    
  3. Chame a Graph API e analise a resposta num determinado modelo.

    try {
      const graphApiResult = await graphClient.api("<GRAPH_API_PATH>").get();
      // Parse the graphApiResult into a Model you defined, used by the front-end.
    } catch (e) {}
    

Chamar a Graph API a partir do back-end (utilizar permissões de aplicação)

Se quiser chamar uma Graph API a partir do back-end, siga estes passos:

  1. Consent application permissions (Consent application permissions)
  2. Adicionar uma função do Azure
  3. Adicionar a lógica na função do Azure
  4. Chamar a função do Azure a partir do front-end

Para dar consentimento às permissões da aplicação, siga estes passos:

  1. Acesse o portal do Azure.
  2. Selecione Microsoft Entra ID.
  3. Selecione Registos de aplicações no painel esquerdo.
  4. Selecione a sua aplicação de dashboard.
  5. Selecione Permissões de API no painel esquerdo.
  6. Selecione Adicionar permissão.
  7. Selecione Microsoft Graph.
  8. Selecione Permissões de aplicativos.
  9. Localize as permissões de que precisa.
  10. Selecione o botão Adicionar permissões na parte inferior.
  11. Selecione ✔Conceder consentimento do administrador.
  12. Selecione o botão Sim para concluir o consentimento do administrador.

Adicionar uma função do Azure

No painel esquerdo do Visual Studio Code, aceda a Toolkit> do TeamsAdicionar funcionalidades>funções do Azure e introduza o nome da função.

Captura de ecrã a mostrar a seleção das Funções do Azure.

Para obter mais informações sobre como adicionar uma Função do Azure ao seu projeto, veja Integrar as Funções do Azure com a sua aplicação Teams.

Adicionar a lógica na função do Azure

Na pasta com o nome Função do Azure, pode adicionar a index.ts/index.ts sua lógica que contém chamadas de Graph API de back-end com permissões de aplicação. Veja o seguinte fragmento de código:

/**
 * This function handles requests from teamsfx client.
 * The HTTP request should contain an SSO token queried from Teams in the header.
 * Before triggering this function, teamsfx binding would process the SSO token and generate teamsfx configuration.
 *
 * You should initializes the teamsfx SDK with the configuration and calls these APIs.
 *
 * The response contains multiple message blocks constructed into a JSON object, including:
 * - An echo of the request body.
 * - The display name encoded in the SSO token.
 * - Current user's Microsoft 365 profile if the user has consented.
 *
 * @param {Context} context - The Azure Functions context object.
 * @param {HttpRequest} req - The HTTP request.
 * @param {teamsfxContext} TeamsfxContext - The context generated by teamsfx binding.
 */
export default async function run(
  context: Context,
  req: HttpRequest,
  teamsfxContext: TeamsfxContext
): Promise<Response> {
  context.log("HTTP trigger function processed a request.");

  // Initialize response.
  const res: Response = {
    status: 200,
    body: {},
  };

  // Your logic here.

  return res;
}

Chamar a função do Azure a partir do front-end

Chame a função do Azure pelo nome da função. Veja o fragmento de código seguinte para chamar a função do Azure:

const functionName = process.env.REACT_APP_FUNC_NAME || "myFunc";
export let taskName: string;

export async function callFunction(params?: string) {
  taskName = params || "";
  const credential = TeamsUserCredentialContext.getInstance().getCredential();
  if (!credential) {
    throw new Error("TeamsFx SDK is not initialized.");
  }
  try {
    const apiBaseUrl = process.env.REACT_APP_FUNC_ENDPOINT + "/api/";    
    const apiClient = createApiClient(
      apiBaseUrl,
      new BearerTokenAuthProvider(async () => (await credential.getToken(""))!.token)
    );
    const response = await apiClient.get(functionName);
    return response.data;
  } catch (err: unknown) {
    ...
  }
}

Para saber mais, confira:

Incorporar o Power BI no dashboard

Para incorporar o Power BI no dashboard, veja Reação do cliente do Power BI.

Guias passo a passo

Siga o guia passo a passo para criar um dashboard e saiba como adicionar um widget e uma chamada à Graph API ao dashboard.

Confira também