在遠端監視解決方案加速器 Web UI 中新增自訂格線
本文說明如何在遠端監視解決方案加速器 Web UI 中的頁面上,新增方格。 本文章說明:
- 如何準備本機開發環境。
- 如何在 Web UI 中的頁面上新增方格。
本文中的方格範例會顯示來自服務的資料,而在遠端監視解決方案加速器 Web UI 中新增自訂服務操作說明文章會說明新增方式。
必要條件
若要完成本操作指南中的部署,您必須在本機開發機器上安裝下列軟體:
在您開始使用 Intune 之前
請先完成下列文章中的步驟再繼續:
新增格線
若要在 Web UI 中新增方格,您必須新增定義方格的原始程式檔,並修改一些現有檔案讓 Web UI 知道新的元件。
新增可定義方格的檔案
為了讓您能夠開始,src/walkthrough/components/pages/pageWithGrid/exampleGrid 資料夾包含可定義方格的檔案:
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'
};
將 src/walkthrough/components/pages/pageWithGrid/exampleGrid 資料夾複製到 src/components/pages/example 資料夾。
在頁面上新增方格
如下所示修改 src/components/pages/example/basicPage.container.js 以匯入服務定義:
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));
如下所示修改 src/components/pages/example/basicPage.js 以新增方格:
// 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>
];
}
}
如下所示修改 src/components/pages/example/basicPage.test.js 以更新測試:
// 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} />
);
});
});
測試方格
如果 Web UI 已不在本機執行,請在存放庫本機複本的根目錄中執行下列命令:
npm start
上一個命令會在本機於 https://localhost:3000/dashboard
執行 UI。 瀏覽至 [範例] 頁面,以查看來自服務的方格顯示資料。
選取資料列
有兩個選項可讓使用者選取方格中的資料列:
硬式選取資料列
如果使用者需要同時處理多個資料列,請在資料列上使用核取方塊:
將 checkboxColumn 新增至提供給方格的 columnDefs,以啟用資料列硬式選取。 checkboxColumn 定義於 /src/components/shared/pcsGrid/pcsGrid.js:
this.columnDefs = [ checkboxColumn, exampleColumnDefs.id, exampleColumnDefs.description ];
若要存取所選的項目,您可取得內部方格 API 的參考:
onGridReady = gridReadyEvent => { this.gridApi = gridReadyEvent.api; // Call the onReady props if it exists if (isFunc(this.props.onGridReady)) { this.props.onGridReady(gridReadyEvent); } };
硬式選取方格中的資料列時,請提供頁面的內容按鈕:
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); } //... }
按一下內容按鈕後,即可取得硬式選取的項目來執行工作:
doSomething = () => { //Just for demo purposes. Don't console log in a real grid. console.log('Hard selected rows', this.gridApi.getSelectedRows()); };
軟式選取資料列
如果使用者只需要處理單一資料列,請為 columnDefs 中的一或多個資料行設定軟式選取連結。
在 exampleGridConfig.js 中,新增 SoftSelectLinkRenderer 作為 columnDef 的 cellRendererFramework。
export const exampleColumnDefs = { id: { headerName: 'examples.grid.name', field: 'id', sort: 'asc', cellRendererFramework: SoftSelectLinkRenderer } };
按一下軟式選取連結後,它會觸發 onSoftSelectChange 事件。 對該資料列執行任何所需的動作,例如開啟詳細資料飛出視窗。 此範例只會寫入至主控台:
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); } }
後續步驟
在本文中,您已了解可用來協助您在遠端監視解決方案加速器 Web UI 中新增或自訂頁面的資源。
您現在已定義了一個方格,下一個步驟是將自訂飛出視窗新增至遠端監視解決方案加速器 Web UI (其顯示在範例頁面上)。
如需遠端監視解決方案加速器的詳細資訊,請參閱 遠端監視架構。