Compartilhar via


Adicione um serviço personalizado à interface do usuário da Web do acelerador de solução de Monitoramento Remoto

Este artigo mostra como adicionar um novo serviço na interface do usuário Web do acelerador de solução de Monitoramento Remoto. O artigo descreve:

  • Como preparar um ambiente de desenvolvimento local.
  • Como adicionar um novo serviço à interface do usuário Web.

O serviço de exemplo deste artigo fornece os dados para uma grade que a seção Adicionar uma grade personalizada ao artigo explicativo de interface do usuário da Web do acelerador de solução de Monitoramento Remoto mostra como adicionar.

Em um aplicativo React, um serviço normalmente interage com um serviço de back-end. Exemplos no acelerador de solução de Monitoramento Remoto incluem serviços que interagem com o gerenciador do hub IoT e microsserviços de configuração.

Pré-requisitos

Para concluir as etapas neste guia de instruções, você precisa ter o seguinte software instalado em seu computador de desenvolvimento local:

Antes de começar

Você deve concluir as etapas no artigo de instruções Adicionar uma página personalizada à interface do usuário Web do acelerador de solução de Monitoramento Remoto antes de continuar.

Adicionar um serviço

Para adicionar um serviço à interface do usuário da Web, você precisa adicionar os arquivos de origem que definem o serviço e modificar alguns arquivos existentes para criar a interface do usuário Web com suporte do novo serviço.

Adicione os novos arquivos que definem o serviço

Para começar, a pasta src/walkthrough/services contém os arquivos que definem um serviço simples:

exampleService.js


import { Observable } from 'rxjs';
import { toExampleItemModel, toExampleItemsModel } from './models';

/** Normally, you'll need to define the endpoint URL.
 * See app.config.js to add a new service URL.
 *
 * For this example, we'll just hardcode sample data to be returned instead
 * of making an actual service call. See the other service files for examples.
 */
//const ENDPOINT = Config.serviceUrls.example;

/** Contains methods for calling the example service */
export class ExampleService {

  /** Returns an example item */
  static getExampleItem(id) {
    return Observable.of(
      { ID: id, Description: "This is an example item." },
    )
      .map(toExampleItemModel);
  }

  /** Returns a list of example items */
  static getExampleItems() {
    return Observable.of(
      {
        items: [
          { ID: "123", Description: "This is item 123." },
          { ID: "188", Description: "This is item ONE-DOUBLE-EIGHT." },
          { ID: "210", Description: "This is item TWO-TEN." },
          { ID: "277", Description: "This is item 277." },
          { ID: "413", Description: "This is item FOUR-THIRTEEN." },
          { ID: "789", Description: "This is item 789." },
        ]
      }
    ).map(toExampleItemsModel);
  }

  /** Mimics a server call by adding a delay */
  static updateExampleItems() {
    return this.getExampleItems().delay(2000);
  }
}

Para saber mais sobre como os serviços são implementados, confira Introdução à Programação Reativa você está perdendo.

model/exampleModels.js

import { camelCaseReshape, getItems } from 'utilities';

/**
 * Reshape the server side model to match what the UI wants.
 *
 * Left side is the name on the client side.
 * Right side is the name as it comes from the server (dot notation is supported).
 */
export const toExampleItemModel = (data = {}) => camelCaseReshape(data, {
  'id': 'id',
  'description': 'descr'
});

export const toExampleItemsModel = (response = {}) => getItems(response)
  .map(toExampleItemModel);

Copie exampleService.js para a pasta src/services e copie exampleModels.js para a pasta src/services/models.

Atualize o arquivo index.js na pasta src/services para exportar o novo serviço:

export * from './exampleService';

Atualize o arquivo index.js na pasta src/services/models para exportar o novo modelo:

export * from './exampleModels';

Configurar chamadas para o serviço da loja

Para começar, a pasta src/walkthrough/store/reducers contém um redutor de exemplo:

exampleReducer.js

import 'rxjs';
import { Observable } from 'rxjs';
import moment from 'moment';
import { schema, normalize } from 'normalizr';
import update from 'immutability-helper';
import { createSelector } from 'reselect';
import { ExampleService } from 'walkthrough/services';
import {
  createReducerScenario,
  createEpicScenario,
  errorPendingInitialState,
  pendingReducer,
  errorReducer,
  setPending,
  toActionCreator,
  getPending,
  getError
} from 'store/utilities';

// ========================= Epics - START
const handleError = fromAction => error =>
  Observable.of(redux.actions.registerError(fromAction.type, { error, fromAction }));

export const epics = createEpicScenario({
  /** Loads the example items */
  fetchExamples: {
    type: 'EXAMPLES_FETCH',
    epic: fromAction =>
      ExampleService.getExampleItems()
        .map(toActionCreator(redux.actions.updateExamples, fromAction))
        .catch(handleError(fromAction))
  }
});
// ========================= Epics - END

// ========================= Schemas - START
const itemSchema = new schema.Entity('examples');
const itemListSchema = new schema.Array(itemSchema);
// ========================= Schemas - END

// ========================= Reducers - START
const initialState = { ...errorPendingInitialState, entities: {}, items: [], lastUpdated: '' };

const updateExamplesReducer = (state, { payload, fromAction }) => {
  const { entities: { examples }, result } = normalize(payload, itemListSchema);
  return update(state, {
    entities: { $set: examples },
    items: { $set: result },
    lastUpdated: { $set: moment() },
    ...setPending(fromAction.type, false)
  });
};

/* Action types that cause a pending flag */
const fetchableTypes = [
  epics.actionTypes.fetchExamples
];

export const redux = createReducerScenario({
  updateExamples: { type: 'EXAMPLES_UPDATE', reducer: updateExamplesReducer },
  registerError: { type: 'EXAMPLE_REDUCER_ERROR', reducer: errorReducer },
  isFetching: { multiType: fetchableTypes, reducer: pendingReducer }
});

export const reducer = { examples: redux.getReducer(initialState) };
// ========================= Reducers - END

// ========================= Selectors - START
export const getExamplesReducer = state => state.examples;
export const getEntities = state => getExamplesReducer(state).entities || {};
export const getItems = state => getExamplesReducer(state).items || [];
export const getExamplesLastUpdated = state => getExamplesReducer(state).lastUpdated;
export const getExamplesError = state =>
  getError(getExamplesReducer(state), epics.actionTypes.fetchExamples);
export const getExamplesPendingStatus = state =>
  getPending(getExamplesReducer(state), epics.actionTypes.fetchExamples);
export const getExamples = createSelector(
  getEntities, getItems,
  (entities, items) => items.map(id => entities[id])
);
// ========================= Selectors - END

Copie exampleReducer.js para a pasta store/src/redutores.

Para saber mais sobre o redutor e Épicos, confira redux-observable.

Configurar o middleware

Para configurar o middleware, adicione o redutor ao arquivo rootReducer.js na pasta src/store:

import { reducer as exampleReducer } from './reducers/exampleReducer';

const rootReducer = combineReducers({
  ...appReducer,
  ...devicesReducer,
  ...rulesReducer,
  ...simulationReducer,
  ...exampleReducer
});

Adicionar os épicos ao arquivo rootEpics.js na pasta src/store:

import { epics as exampleEpics } from './reducers/exampleReducer';

// Extract the epic function from each property object
const epics = [
  ...appEpics.getEpics(),
  ...devicesEpics.getEpics(),
  ...rulesEpics.getEpics(),
  ...simulationEpics.getEpics(),
  ...exampleEpics.getEpics()
];

Próximas etapas

Neste artigo, você aprendeu sobre os recursos disponíveis para ajudá-lo a adicionar ou personalizar serviços na interface do usuário da Web no acelerador de solução de monitoramento remoto.

Agora que você definiu um serviço, a próxima etapa é Adicionar uma grade personalizada para a interface do usuário Web do acelerador de solução de Monitoramento Remoto que exibe dados retornados pelo serviço.

Para obter mais informações conceituais sobre o acelerador de solução de Monitoramento Remoto, consulte a arquitetura de Monitoramento Remoto.