Adición de una cuadrícula personalizada a la interfaz de usuario web del acelerador de soluciones de supervisión remota
En este artículo se muestra cómo agregar una nueva cuadrícula en una pagina de la interfaz de usuario web del acelerador de soluciones de supervisión remota. El artículo describe:
- Cómo preparar un entorno de desarrollo local.
- Cómo agregar una nueva cuadrícula a una página de la interfaz de usuario web.
La cuadrícula de ejemplo de este artículo muestra los datos del servicio que el artículo de procedimientos Adición de un servicio personalizado a la interfaz de usuario web del acelerador de soluciones de supervisión remota muestra cómo agregar.
Requisitos previos
Para completar los pasos de esta guía, necesita que el software siguiente esté instalado en la máquina de desarrollo local:
Antes de comenzar
Debe completar los pasos descritos en los artículos siguientes antes de continuar:
- Adición de una página personalizada a la interfaz de usuario web del acelerador de soluciones de supervisión remota.
- Adición de un servicio personalizado a la interfaz de usuario web del acelerador de soluciones de supervisión remota
Agregar una cuadrícula
Para agregar una cuadrícula a la interfaz de usuario web, deberá agregar los archivos de origen que definen la cuadrícula y modificar algunos archivos existentes para hacer que la interfaz de usuario web sea consciente del nuevo componente.
Adición de los nuevos archivos que definen la cuadrícula
Para comenzar, la carpeta src/walkthrough/components/pages/pageWithGrid/exampleGrid contiene los archivos que definen una cuadrícula:
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'
};
Copie la carpeta src/walkthrough/components/pages/pageWithGrid/exampleGrid en la carpeta src/components/pages/example.
Adición de la cuadrícula a la página
Modifique el archivo src/components/pages/example/basicPage.container.js como se indica a continuación para importar las definiciones del servicio:
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));
Modifique el archivo src/components/pages/example/basicPage.js como se indica a continuación para agregar la cuadrícula:
// 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>
];
}
}
Modifique el archivo src/components/pages/example/basicPage.test.js como se indica a continuación para actualizar las pruebas:
// 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} />
);
});
});
Prueba de la cuadrícula
Si la interfaz de usuario web no se está ejecutando localmente, ejecute el siguiente comando en la raíz de la copia local del repositorio:
npm start
El comando anterior ejecuta la interfaz de usuario localmente en https://localhost:3000/dashboard
. Vaya a la pagina de Ejemplo para ver que la cuadrícula muestra los datos del servicio.
Selección de filas
Hay dos opciones para habilitar a un usuario para que seleccione las filas de la cuadrícula:
Filas de selección fija
Si un usuario necesita actuar en varias filas al mismo tiempo, use las casillas de verificación de las filas:
Puede habilitar la selección fija de filas mediante la adición de un elemento checkboxColumn al elemento columnDefs que se proporciona a la cuadrícula. checkboxColumn se define en /src/components/shared/pcsGrid/pcsGrid.js:
this.columnDefs = [ checkboxColumn, exampleColumnDefs.id, exampleColumnDefs.description ];
Para acceder a los elementos seleccionados, debe obtener una referencia a la API interna de la cuadrícula:
onGridReady = gridReadyEvent => { this.gridApi = gridReadyEvent.api; // Call the onReady props if it exists if (isFunc(this.props.onGridReady)) { this.props.onGridReady(gridReadyEvent); } };
Puede proporcionar botones de contexto a la página cuando se realiza una selección fija de una fila de la cuadrícula:
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); } //... }
Cuando se hace clic en un botón de contexto, puede obtener los elementos de la selección fija para realizar el trabajo:
doSomething = () => { //Just for demo purposes. Don't console log in a real grid. console.log('Hard selected rows', this.gridApi.getSelectedRows()); };
Filas de selección temporal
Si el usuario necesita actuar en una sola fila, puede configurar un vínculo de selección temporal para una o varias columnas del elemento columnDefs.
En el archivo exampleGridConfig.js, agregue SoftSelectLinkRenderer como el elemento cellRendererFramework de un elemento columnDef.
export const exampleColumnDefs = { id: { headerName: 'examples.grid.name', field: 'id', sort: 'asc', cellRendererFramework: SoftSelectLinkRenderer } };
Cuando se hace clic en un vínculo de selección temporal, se desencadena el evento onSoftSelectChange. Puede realizar cualquier acción que desee para esa fila, como abrir un control flotante con detalles. En este ejemplo sencillamente se escribe en la consola:
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); } }
Pasos siguientes
En este artículo, aprendió sobre los recursos que tiene a su disposición para ayudarle a agregar o personalizar páginas en la interfaz de usuario web del acelerador de la solución de supervisión remota.
Ya ha definido una cuadrícula, el paso siguiente consiste en la Adición de un control flotante personalizado a la interfaz de usuario web del acelerador de soluciones de supervisión remota que se muestra en la página de ejemplo.
Para obtener más información conceptual sobre el acelerador de soluciones de supervisión remota, consulte Arquitectura de supervisión remota.