AG-420 Improve React implementation
This commit is contained in:
26
src-trader-dashboard/components/FxPanel.jsx
Normal file
26
src-trader-dashboard/components/FxPanel.jsx
Normal 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>
|
||||
);
|
||||
}
|
||||
};
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
|
||||
105
src-trader-dashboard/components/TopMoversGrid.jsx
Normal file
105
src-trader-dashboard/components/TopMoversGrid.jsx
Normal 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);
|
||||
Reference in New Issue
Block a user