Share via


Lägga till ett anpassat rutnät i webbgränssnittet för fjärrövervakningslösningsacceleratorn

Den här artikeln visar hur du lägger till ett nytt rutnät på en sida i webbgränssnittet för lösningsacceleratorn för fjärrövervakning. Artikeln beskriver:

  • Förbereda en lokal utvecklingsmiljö.
  • Så här lägger du till ett nytt rutnät på en sida i webbgränssnittet.

Exempelrutnätet i den här artikeln visar data från tjänsten som artikeln Lägg till en anpassad tjänst i webbgränssnittet för fjärrövervakningslösningsacceleratorn visar hur du lägger till.

Förutsättningar

För att slutföra stegen i den här instruktionsguiden behöver du följande programvara installerad på din lokala utvecklingsdator:

Innan du börjar

Du bör slutföra stegen i följande artiklar innan du fortsätter:

Lägg till ett rutnät

Om du vill lägga till ett rutnät i webbgränssnittet måste du lägga till källfilerna som definierar rutnätet och ändra vissa befintliga filer för att göra webbgränssnittet medvetet om den nya komponenten.

Lägg till de nya filerna som definierar rutnätet

För att komma igång innehåller mappen src/walkthrough/components/pages/pageWithGrid/exampleGrid de filer som definierar ett rutnät:

exampleGrid.js


import React, { Component } from 'react';
import { Btn, ComponentArray, PcsGrid } from 'components/shared';
import { exampleColumnDefs, defaultExampleGridProps } from './exampleGridConfig';
import { isFunc, svgs, translateColumnDefs } from 'utilities';
import { checkboxColumn } from 'components/shared/pcsGrid/pcsGridConfig';

const initialState = {
  softSelectedId: undefined
};

/**
 * A grid for displaying example data
 *
 * Encapsulates the PcsGrid props
 */
export class ExampleGrid extends Component {
  constructor(props) {
    super(props);

    // Set the initial state
    this.state = initialState;

    // Default device grid columns
    this.columnDefs = [
      checkboxColumn,
      exampleColumnDefs.id,
      exampleColumnDefs.description
    ];

    // Set up the available context buttons.
    // If these are subject to user permissions, use the Protected component (src/components/shared/protected).
    this.contextBtns =
      <ComponentArray>
        <Btn svg={svgs.reconfigure} onClick={this.clickContextBtn('btn1')}>{props.t('walkthrough.pageWithGrid.grid.btn1')}</Btn>
        <Btn svg={svgs.trash} onClick={this.clickContextBtn('btn2')}>{props.t('walkthrough.pageWithGrid.grid.btn2')}</Btn>
      </ComponentArray>;
  }

  /**
   * Get the grid api options
   *
   * @param {Object} gridReadyEvent An object containing access to the grid APIs
  */
  onGridReady = gridReadyEvent => {
    this.gridApi = gridReadyEvent.api;
    // Call the onReady props if it exists
    if (isFunc(this.props.onGridReady)) {
      this.props.onGridReady(gridReadyEvent);
    }
  };

  clickContextBtn = (input) => () => {
    //Just for demo purposes. Don't console log in a real grid.
    console.log('Context button clicked', input);
    console.log('Hard selected rows', this.gridApi.getSelectedRows());
  };

  /**
   * Handles soft select props method.
   * Soft selection happens when the user clicks on the row.
   *
   * @param rowId The id of the currently soft selected item
   * @param rowData The rowData from the underlying grid. MAY BE OUT OF DATE.
   */
  onSoftSelectChange = (rowId, rowData) => {
    //Note: only the Id is reliable, rowData may be out of date
    const { onSoftSelectChange } = this.props;
    if (rowId) {
      console.log('Soft selected', rowId); //Just for demo purposes. Don't console log a real grid.
      this.setState({ softSelectedId: rowId });
    }
    if (isFunc(onSoftSelectChange)) {
      onSoftSelectChange(rowId, rowData);
    }
  }

  /**
   * Handles context filter changes and calls any hard select props method.
   * Hard selection happens when the user checks the box for the row.
   *
   * @param {Array} selectedObjs A list of currently selected objects in the grid
   */
  onHardSelectChange = (selectedObjs) => {
    const { onContextMenuChange, onHardSelectChange } = this.props;
    // Show the context buttons when there are rows checked.
    if (isFunc(onContextMenuChange)) {
      onContextMenuChange(selectedObjs.length > 0 ? this.contextBtns : null);
    }
    if (isFunc(onHardSelectChange)) {
      onHardSelectChange(selectedObjs);
    }
  }

  getSoftSelectId = ({ id } = '') => id;

  render() {
    const gridProps = {
      /* Grid Properties */
      ...defaultExampleGridProps,
      columnDefs: translateColumnDefs(this.props.t, this.columnDefs),
      sizeColumnsToFit: true,
      getSoftSelectId: this.getSoftSelectId,
      softSelectId: (this.state.softSelectedDevice || {}).id,
      ...this.props, // Allow default property overrides
      deltaRowDataMode: true,
      enableSorting: true,
      unSortIcon: true,
      getRowNodeId: ({ id }) => id,
      context: {
        t: this.props.t
      },
      /* Grid Events */
      onRowClicked: ({ node }) => node.setSelected(!node.isSelected()),
      onGridReady: this.onGridReady,
      onSoftSelectChange: this.onSoftSelectChange,
      onHardSelectChange: this.onHardSelectChange
    };

    return (
      <PcsGrid key="example-grid-key" {...gridProps} />
    );
  }
}

exampleGridConfig.js


import Config from 'app.config';
import { SoftSelectLinkRenderer } from 'components/shared/cellRenderers';

/** A collection of column definitions for the example grid */
export const exampleColumnDefs = {
  id: {
    headerName: 'walkthrough.pageWithGrid.grid.name',
    field: 'id',
    sort: 'asc',
    cellRendererFramework: SoftSelectLinkRenderer
  },
  description: {
    headerName: 'walkthrough.pageWithGrid.grid.description',
    field: 'descr'
  }
};

/** Given an example object, extract and return the device Id */
export const getSoftSelectId = ({ id }) => id;

/** Shared example grid AgGrid properties */
export const defaultExampleGridProps = {
  enableColResize: true,
  multiSelect: true,
  pagination: false,
  paginationPageSize: Config.paginationPageSize,
  rowSelection: 'multiple'
};

Kopiera mappen src/walkthrough/components/pages/pageWithGrid/exampleGrid till mappen src/components/pages/example .

Lägg till rutnätet på sidan

Ändra src/components/pages/example/basicPage.container.js så här för att importera tjänstdefinitionerna:

import { connect } from 'react-redux';
import { translate } from 'react-i18next';

import {
  epics as exampleEpics,
  getExamples,
  getExamplesError,
  getExamplesLastUpdated,
  getExamplesPendingStatus
} from 'store/reducers/exampleReducer';
import { BasicPage } from './basicPage';

// Pass the data
const mapStateToProps = state => ({
  data: getExamples(state),
  error: getExamplesError(state),
  isPending: getExamplesPendingStatus(state),
  lastUpdated: getExamplesLastUpdated(state)
});

// Wrap the dispatch method
const mapDispatchToProps = dispatch => ({
  fetchData: () => dispatch(exampleEpics.actions.fetchExamples())
});

export const BasicPageContainer = translate()(connect(mapStateToProps, mapDispatchToProps)(BasicPage));

Ändra src/components/pages/example/basicPage.js så här för att lägga till rutnätet:

// Copyright (c) Microsoft. All rights reserved.

import React, { Component } from 'react';

import {
  AjaxError,
  ContextMenu,
  PageContent,
  RefreshBar
} from 'components/shared';
import { ExampleGrid } from './exampleGrid';

import './basicPage.css';

export class BasicPage extends Component {
  constructor(props) {
    super(props);
    this.state = { contextBtns: null };
  }

  componentDidMount() {
    const { isPending, lastUpdated, fetchData } = this.props;
    if (!lastUpdated && !isPending) fetchData();
  }

  onGridReady = gridReadyEvent => this.gridApi = gridReadyEvent.api;

  onContextMenuChange = contextBtns => this.setState({ contextBtns });

  render() {
    const { t, data, error, isPending, lastUpdated, fetchData } = this.props;
    const gridProps = {
      onGridReady: this.onGridReady,
      rowData: isPending ? undefined : data || [],
      onContextMenuChange: this.onContextMenuChange,
      t: this.props.t
    };

    return [
      <ContextMenu key="context-menu">
        {this.state.contextBtns}
      </ContextMenu>,
      <PageContent className="basic-page-container" key="page-content">
        <RefreshBar refresh={fetchData} time={lastUpdated} isPending={isPending} t={t} />
        {!!error && <AjaxError t={t} error={error} />}
        {!error && <ExampleGrid {...gridProps} />}
      </PageContent>
    ];
  }
}

Ändra src/components/pages/example/basicPage.test.js enligt följande för att uppdatera testerna:

// Copyright (c) Microsoft. All rights reserved.

import React from 'react';
import { shallow } from 'enzyme';
import 'polyfills';

import { BasicPage } from './basicPage';

describe('BasicPage Component', () => {
  it('Renders without crashing', () => {

    const fakeProps = {
      data: undefined,
      error: undefined,
      isPending: false,
      lastUpdated: undefined,
      fetchData: () => { },
      t: () => { },
    };

    const wrapper = shallow(
      <BasicPage {...fakeProps} />
    );
  });
});

Testa rutnätet

Om webbgränssnittet inte redan körs lokalt kör du följande kommando i roten för din lokala kopia av lagringsplatsen:

npm start

Föregående kommando kör användargränssnittet lokalt på https://localhost:3000/dashboard. Gå till sidan Exempel om du vill se rutnätets visningsdata från tjänsten.

Markera rader

Det finns två alternativ för att göra det möjligt för en användare att välja rader i rutnätet:

Hårdvalsrader

Om en användare behöver agera på flera rader samtidigt använder du kryssrutor på rader:

  1. Aktivera hård markering av rader genom att lägga till en kryssrutaColumn i columnDefs som tillhandahålls i rutnätet. checkboxColumn definieras i /src/components/shared/pcsGrid/pcsGrid.js:

    this.columnDefs = [
      checkboxColumn,
      exampleColumnDefs.id,
      exampleColumnDefs.description
    ];
    
  2. Om du vill komma åt de markerade objekten får du en referens till det interna rutnäts-API:et:

    onGridReady = gridReadyEvent => {
      this.gridApi = gridReadyEvent.api;
      // Call the onReady props if it exists
      if (isFunc(this.props.onGridReady)) {
        this.props.onGridReady(gridReadyEvent);
      }
    };
    
  3. Ange kontextknappar till sidan när en rad i rutnätet är hårdvald:

    this.contextBtns = [
      <Btn key="context-btn-1" svg={svgs.reconfigure} onClick={this.doSomething()}>Button 1</Btn>,
      <Btn key="context-btn-2" svg={svgs.trash} onClick={this.doSomethingElse()}>Button 2</Btn>
    ];
    
    onHardSelectChange = (selectedObjs) => {
      const { onContextMenuChange, onHardSelectChange } = this.props;
      // Show the context buttons when there are rows checked.
      if (isFunc(onContextMenuChange)) {
        onContextMenuChange(selectedObjs.length > 0 ? this.contextBtns : null);
      }
      //...
    }
    
  4. När du klickar på en kontextknapp hämtar du de hårt valda objekten att utföra ditt arbete med:

    doSomething = () => {
      //Just for demo purposes. Don't console log in a real grid.
      console.log('Hard selected rows', this.gridApi.getSelectedRows());
    };
    

Mjukt valda rader

Om användaren bara behöver agera på en enda rad konfigurerar du en mjukvalslänk för en eller flera kolumner i columnDefs.

  1. I exampleGridConfig.jslägger du till SoftSelectLinkRenderer som cellRendererFramework för en columnDef.

    export const exampleColumnDefs = {
      id: {
        headerName: 'examples.grid.name',
        field: 'id',
        sort: 'asc',
        cellRendererFramework: SoftSelectLinkRenderer
      }
    };
    
  2. När en soft-select-länk klickas utlöses händelsen onSoftSelectChange . Utför den åtgärd som önskas för den raden, till exempel att öppna en utfälld utfälld information. Det här exemplet skriver helt enkelt till konsolen:

    onSoftSelectChange = (rowId, rowData) => {
      //Note: only the Id is reliable, rowData may be out of date
      const { onSoftSelectChange } = this.props;
      if (rowId) {
        //Just for demo purposes. Don't console log a real grid.
        console.log('Soft selected', rowId);
        this.setState({ softSelectedId: rowId });
      }
      if (isFunc(onSoftSelectChange)) {
        onSoftSelectChange(rowId, rowData);
      }
    }
    

Nästa steg

I den här artikeln har du lärt dig om de resurser som är tillgängliga för att hjälpa dig att lägga till eller anpassa sidor i webbgränssnittet i acceleratorn fjärrövervakningslösning.

Nu när du har definierat ett rutnät är nästa steg att lägga till en anpassad utfällbara meny i webbgränssnittet för fjärrövervakningslösningsacceleratorn som visas på exempelsidan.

Mer konceptuell information om acceleratorn fjärrövervakningslösning finns i Arkitektur för fjärrövervakning.