Implementar widgets no portal do desenvolvedor

Neste tutorial, você irá implementar um widget que consome dados de uma API externa e exibi-lo no portal do desenvolvedor de Gerenciamento de API.

O widget recuperará as descrições de sessão no exemplo da API de conferência. O identificador de sessão será definido por meio de um editor de widget designado.

Para ajudá-lo no processo de desenvolvimento, veja o widget concluído localizado na pasta examples do repositório do GitHub no portal do desenvolvedor de Gerenciamento de API: /examples/widgets/conference-session.

Screenshot of published widget

Pré-requisitos

Copie o scaffold

Use um scaffold widget da pasta /scaffolds como ponto de partida para criar o novo widget.

  1. Copie a pasta /scaffolds/widget na /community/widgets.
  2. Renomeie a pasta como conference-session.

Renomear as classes de módulo exportadas

Renomeie as classes de módulo exportadas, substituindo o prefixo Widget por ConferenceSession, e altere o nome da Associação para evitar a colisão de nomes, nesses arquivos:

  • widget.design.module.ts

  • widget.publish.module.ts

  • widget.runtime.module.ts

Por exemplo, no arquivo widget.design.module.ts, altere WidgetDesignModule para ConferenceSessionDesignModule:

export class WidgetDesignModule implements IInjectorModule {
    public register(injector: IInjector): void {
        injector.bind("widget", WidgetViewModel);
        injector.bind("widgetEditor", WidgetEditorViewModel);

como

export class ConferenceSessionDesignModule implements IInjectorModule {
    public register(injector: IInjector): void {
        injector.bind("conferenceSession", WidgetViewModel);
        injector.bind("conferenceSessionEditor", WidgetEditorViewModel);

Registrar o widget

Registre os módulos do widget nos módulos raiz do portal, adicionando as seguintes linhas aos respectivos arquivos:

  1. src/apim.design.module.ts – um módulo que registra as dependências de tempo de design.

    import { ConferenceSessionDesignModule } from "../community/widgets/conference-session/widget.design.module";
    
    ...
    injector.bindModule(new ConferenceSessionDesignModule());
    
  2. src/apim.publish.module.ts – um módulo que registra as dependências de tempo de publicação.

    import { ConferenceSessionPublishModule } from "../community/widgets/conference-session/widget.publish.module";
    
     ...
    
     injector.bindModule(new ConferenceSessionPublishModule());
    
  3. src/apim.runtime.module.ts – dependências de runtime.

    import { ConferenceSessionRuntimeModule } from "../community/widgets/conference-session/widget.runtime.module";
    
    ...
    
    injector.bindModule(new ConferenceSessionRuntimeModule());
    

Coloque o widget no portal

Agora você está pronto para conectar o scaffold duplicado e usá-lo no portal do desenvolvedor.

  1. Execute o comando npm start.

  2. Quando o aplicativo for carregado, coloque o novo widget em uma página. Você pode encontrá-lo com o nome Your widget na categoria Community no seletor de widget.

    Screenshot of widget selector

  3. Salve a página pressionando Ctrl+S (ou +S no macOS).

    Observação

    Em tempo de design, você ainda pode interagir com o site segurando a tecla Ctrl (ou ).

Adicionar propriedades personalizadas

Para que o widget busque as descrições da sessão, ele precisa se lembrar do identificador da sessão. Adicione a propriedade Session ID às respectivas interfaces e classes:

Para que o widget busque a descrição da sessão, ele precisa se lembrar do identificador da sessão. Adicione a propriedade ID da sessão às respectivas interfaces e classes:

  1. widgetContract.ts – contrato de dados (camada de dados) definindo como a configuração do widget é persistente.

    export interface WidgetContract extends Contract {
        sessionNumber: string;
    }
    
  2. widgetModel.ts – modelo (camada de negócios) – uma representação principal do widget no sistema. Ele é atualizado pelos editores e renderizado pela camada de apresentação.

    export class WidgetModel {
        public sessionNumber: string;
    }
    
  3. ko/widgetViewModel.ts – viewmodel (camada de apresentação) – um objeto específico da estrutura da interface do usuário que o portal do desenvolvedor renderiza com o modelo HTML.

    Observação

    Você não precisa alterar nada nesse arquivo.

Configurar os associadores

Habilite o fluxo do sessionNumber na fonte de dados para a apresentação do widget. Edite as entidades ModelBinder e ViewModelBinder:

  1. widgetModelBinder.ts ajuda a preparar o modelo usando os dados descritos no contrato.

    export class WidgetModelBinder implements IModelBinder<WidgetModel> {
        public async contractToModel(contract: WidgetContract): Promise<WidgetModel> {
            model.sessionNumber = contract.sessionNumber || "107"; // 107 is the default session id
            ...
        }
    
        public modelToContract(model: WidgetModel): Contract {
            const contract: WidgetContract = {
                sessionNumber: model.sessionNumber
                ...
            };
            ...
        }
    }
    
  2. ko/widgetViewModelBinder.ts sabe como o portal do desenvolvedor precisa apresentar o modelo (como viewmodel) em uma estrutura da interface do usuário específica.

    ...
    public async updateViewModel(model: WidgetModel, viewModel: WidgetViewModel): Promise<void> {
            viewModel.runtimeConfig(JSON.stringify({
                sessionNumber: model.sessionNumber
            }));
        }
    }
    ...
    

Ajustar o modelo de widget do tempo de design

Os componentes de cada escopo são executados de forma independente. Eles têm contêineres de injeção de dependência separados, sua própria configuração, ciclo de vida, etc. Eles podem até mesmo ser alimentados por diferentes estruturas da interface do usuário (neste exemplo, é o Knockout JS).

Da perspectiva do tempo de design, qualquer componente do runtime é apenas uma marca HTML com determinados atributos e/ou conteúdo. A configuração, se necessário, é passada com marcação simples. Em casos simples, como neste exemplo, o parâmetro é passado no atributo. Se a configuração for mais complexa, você poderá usar um identificador das configurações necessárias buscadas por um provedor de configuração designado (por exemplo, ISettingsProvider).

  1. Atualize o arquivo ko/widgetView.html:

    <widget-runtime data-bind="attr: { params: runtimeConfig }"></widget-runtime>
    

    Quando o portal do desenvolvedor executa a associação attr no tempo de design ou no tempo de publicação, o HTML resultante é:

    <widget-runtime params="{ sessionNumber: 107 }"></widget-runtime>
    

    Em seguida, no runtime, o componente widget-runtime lerá sessionNumber e o usará no código de inicialização (veja abaixo).

  2. Atualize o arquivo widgetHandlers.ts para atribuir a ID da sessão na criação:

    ...
    createModel: async () => {
        var model = new WidgetModel();
        model.sessionNumber = "107";
            return model;
        }
    ...
    

Revisar o modelo de exibição do runtime

Os componentes do runtime são o código em execução no próprio site. Por exemplo, no portal do desenvolvedor de Gerenciamento de API, todos eles são os scripts que protegem os componentes dinâmicos (por exemplo, detalhes da API, console da API), resolvendo operações como a geração de exemplo de código, o envio de solicitações, etc.

O modelo de exibição do componente do runtime precisa ter os seguintes métodos e propriedades:

  • A propriedade sessionNumber (marcada com o decorador Param) usada como o parâmetro de entrada de componente passado de fora (a marcação gerada no tempo de design, confira a etapa anterior).

  • A propriedade sessionDescription limitada ao modelo de widget (confira widget-runtime.html mais adiante neste artigo).

  • O método initialize (com o decorador OnMounted) invocado depois que o widget é criado e todos os parâmetros são atribuídos. É um bom local para ler sessionNumber e invocar a API usando o HttpClient. O HttpClient é uma dependência injetada pelo contêiner de IoC (inversão de controle).

  • Primeiro, o portal do desenvolvedor cria o widget e atribui todos os parâmetros. Em seguida, ele invoca o método initialize.

    ...
    import * as ko from "knockout";
    import { Component, RuntimeComponent, OnMounted, OnDestroyed, Param } from "@paperbits/common/ko/decorators";
    import { HttpClient, HttpRequest } from "@paperbits/common/http";
    ...
    
    export class WidgetRuntime {
        public readonly sessionDescription: ko.Observable<string>;
    
        constructor(private readonly httpClient: HttpClient) {
            ...
            this.sessionNumber = ko.observable();
            this.sessionDescription = ko.observable();
            ...
        }
    
        @Param()
        public readonly sessionNumber: ko.Observable<string>;
    
        @OnMounted()
        public async initialize(): Promise<void> {
            ...
            const sessionNumber = this.sessionNumber();
    
            const request: HttpRequest = {
                url: `https://conferenceapi.azurewebsites.net/session/${sessionNumber}`,
                method: "GET"
            };
    
            const response = await this.httpClient.send<string>(request);
            const sessionDescription = response.toText();
    
            this.sessionDescription(sessionDescription);
            ...
        }
        ...
    }
    

Ajustar o modelo de widget

Atualize o widget para exibir a descrição da sessão.

Use uma marca de parágrafo e uma associação markdown (ou text) no arquivo ko/runtime/widget-runtime.html para renderizar a descrição:

<p data-bind="markdown: sessionDescription"></p>

Adicionar o editor de widget

Agora o widget está configurado para buscar a descrição da sessão 107. Você especificou 107 no código como a sessão padrão. Para verificar se você fez tudo corretamente, execute npm start e confirme se o portal do desenvolvedor mostra a descrição na página.

Agora, realize estas etapas para permitir que o usuário configure a ID da sessão por meio de um editor de widget:

  1. Atualize o arquivo ko/widgetEditorViewModel.ts:

    export class WidgetEditor implements WidgetEditor<WidgetModel> {
        public readonly sessionNumber: ko.Observable<string>;
    
        constructor() {
            this.sessionNumber = ko.observable();
        }
    
        @Param()
        public model: WidgetModel;
    
        @Event()
        public onChange: (model: WidgetModel) => void;
    
        @OnMounted()
        public async initialize(): Promise<void> {
            this.sessionNumber(this.model.sessionNumber);
            this.sessionNumber.subscribe(this.applyChanges);
        }
    
        private applyChanges(): void {
            this.model.sessionNumber = this.sessionNumber();
            this.onChange(this.model);
        }
    }
    

    O modelo de exibição do editor usa a mesma abordagem observada anteriormente, mas há uma nova propriedade onChange, decorada com @Event(). Ela conecta o retorno de chamada para notificar os ouvintes (neste caso, um editor de conteúdo) sobre as alterações no modelo.

  2. Atualize o arquivo ko/widgetEditorView.html:

    <input type="text" class="form-control" data-bind="textInput: sessionNumber" />
    
  3. Execute npm start novamente. Você deve estar apto a alterar o sessionNumber no editor de widget. Altere a ID para 108, salve as alterações e atualize a guia do navegador. Se você estiver enfrentando problemas, talvez seja necessário adicionar o widget à página novamente.

    Screenshot of widget editor

Renomear o widget

Altere o nome do widget no arquivo constants.ts:

...
export const widgetName = "conference-session";
export const widgetDisplayName = "Conference session";
...

Observação

Se você estiver contribuindo com o widget para o repositório, o widgetName precisará ser igual ao nome da pasta e derivar do nome de exibição (letras minúsculas e espaços substituídos por traços). A categoria deve permanecer Community.

Próximas etapas

Saiba mais sobre o portal do desenvolvedor: