AG-420 Improve React implementation

This commit is contained in:
Sean Landsman
2017-05-23 17:51:33 +01:00
parent e183a0503a
commit 06ebb8bf18
11 changed files with 217 additions and 321 deletions

View File

@@ -0,0 +1,26 @@
import React, {Component} from "react";
import FxDataService from "../services/FxDataService.jsx";
import FxQuoteMatrix from "./FxQuoteMatrix.jsx";
import TopMoversGrid from "./TopMoversGrid.jsx";
export default class extends Component {
constructor(props) {
super(props);
this.fxDataService = new FxDataService();
}
render() {
return (
<div>
<div style={{float: "left", marginRight: 25}}>
<FxQuoteMatrix fxDataService={this.fxDataService}/>
</div>
<div style={{float: "left"}}>
<TopMoversGrid fxDataService={this.fxDataService}/>
</div>
</div>
);
}
};

View File

@@ -5,18 +5,13 @@ import {AgGridReact} from "ag-grid-react";
import assign from "lodash/assign";
import uniq from "lodash/uniq";
import cloneDeep from "lodash/cloneDeep";
import FxDataService from "../services/FxDataService.jsx";
class FxQuoteMatrix extends Component {
constructor(props) {
super(props);
this.fxDataService = new FxDataService();
this.state = {
columnDefs: this.fxDataService.getFxMatrixHeaderNames()
columnDefs: this.props.fxDataService.getFxMatrixHeaderNames()
};
// grid events
@@ -28,48 +23,43 @@ class FxQuoteMatrix extends Component {
this.columnApi = params.columnApi;
}
componentDidMount() {
this.gridApi.setRowData(this.props.rowData);
}
componentWillReceiveProps(nextProps) {
if (!this.gridApi) {
return;
}
const newRowData = nextProps.rowData;
if (!this.props.rowData ||
this.props.rowData.length === 0) {
this.gridApi.setRowData(nextProps.rowData);
} else {
const newRowData = nextProps.rowData;
const updatedNodes = [];
const updatedCols = [];
const updatedNodes = [];
const updatedCols = [];
for (let i = 0; i < newRowData.length; i++) {
// note that for this use case we assume the existing and new row data have the same
// row and column order
let node = this.gridApi.getModel().getRow(i);
let newRow = newRowData[i];
for (let i = 0; i < newRowData.length; i++) {
// note that for this use case we assume the existing and new row data have the same
// row and column order
let node = this.gridApi.getModel().getRow(i);
let newRow = newRowData[i];
const {data} = node;
let updated = false;
for (const def of this.state.columnDefs) {
if (data[def.field] !== newRow[def.field]) {
updatedCols.push(def.field);
const {data} = node;
let updated = false;
for (const def of this.state.columnDefs) {
if (data[def.field] !== newRow[def.field]) {
updatedCols.push(def.field);
updated = true;
}
}
if(updated) {
assign(data, newRow);
updatedNodes.push(node);
updated = true;
}
}
this.gridApi.refreshCells(updatedNodes, uniq(updatedCols));
if(updated) {
assign(data, newRow);
updatedNodes.push(node);
}
}
this.gridApi.refreshCells(updatedNodes, uniq(updatedCols));
}
render() {
return (
<div style={{height: 410, width: "100%"}}
<div style={{height: 410, width: 800}}
className="ag-fresh">
<AgGridReact
// properties

View File

@@ -41,15 +41,6 @@ export default class extends Component {
cellFormatter: this.numberFormatter,
cellRenderer: 'animateShowChange',
cellStyle: {'text-align': 'right'}
},
{
headerName: 'Recommendation',
field: 'recommendation',
cellEditor: 'richSelect',
cellEditorParams: {
values: ['Buy', 'Hold', 'Sell']
},
editable: true
}
]
};

View File

@@ -2,7 +2,7 @@ import React, {Component} from "react";
import PriceChangesGrid from "./PriceChangesGrid.jsx";
import StockDetailPanel from "./StockDetailPanel.jsx";
import FxQuoteMatrix from "./FxQuoteMatrix.jsx";
import FxPanel from "./FxPanel.jsx";
export default class extends Component {
constructor(props) {
@@ -48,7 +48,7 @@ export default class extends Component {
</div>
</div>
<div style={{width: "100%", clear: "both", paddingTop: 25}}>
<FxQuoteMatrix/>
<FxPanel/>
</div>
</div>
);

View File

@@ -0,0 +1,105 @@
import React, {Component} from "react";
import {connect} from "react-redux";
import {AgGridReact} from "ag-grid-react";
class TopMoversGrid extends Component {
constructor(props) {
super(props);
this.state = {
columnDefs: [
{
field: 'symbol',
headerName: 'Symbol'
},
{
field: 'last',
headerName: 'Last',
headerClass: 'align-right',
cellRenderer: 'animateShowChange',
cellClass: 'align-right'
},
{
field: 'net',
headerName: 'Net',
headerClass: 'align-right',
cellRenderer: 'animateShowChange',
cellClass: 'align-right'
},
{
field: 'pct_net_change',
headerName: '% NC',
headerClass: 'align-right',
cellRenderer: 'animateShowChange',
cellClass: 'align-right'
},
]
};
// grid events
this.onGridReady = this.onGridReady.bind(this);
}
onGridReady(params) {
this.gridApi = params.api;
this.columnApi = params.columnApi;
}
componentDidMount() {
this.gridApi.setRowData(this.props.rowData);
this.gridApi.sizeColumnsToFit();
}
componentWillReceiveProps(nextProps) {
let newRowData = nextProps.rowData;
let model = this.gridApi.getModel();
// remove nodes not in new data set
let nodesToRemove = [];
for (let rowIndex = 0; rowIndex < model.getRowCount(); rowIndex++) {
let rowNode = model.getRow(rowIndex);
if (rowNode.data.symbol !== newRowData[rowIndex].symbol) {
nodesToRemove.push(rowNode);
}
}
this.gridApi.removeItems(nodesToRemove);
// add new items in set
for (let rowIndex = 0; rowIndex < newRowData.length; rowIndex++) {
let model = this.gridApi.getModel();
let rowNode = model.getRow(rowIndex);
if (!rowNode ||
rowNode.data.symbol !== newRowData[rowIndex].symbol) {
this.gridApi.insertItemsAtIndex(rowIndex, [newRowData[rowIndex]])
}
}
}
render() {
return (
<div style={{height: 410, width: 400}}
className="ag-fresh">
<AgGridReact
// properties
columnDefs={this.state.columnDefs}
enableSorting="false"
enableFilter="false"
animateRows="true"
// events
onGridReady={this.onGridReady}>
</AgGridReact>
</div>
);
}
}
export default connect(
(state) => {
return {
rowData: state.fxTopMovers
}
}
)(TopMoversGrid);