AG-420 Improve React implementation
This commit is contained in:
@@ -48,6 +48,7 @@ export default class extends Component {
|
||||
|
||||
// grid events
|
||||
this.onGridReady = this.onGridReady.bind(this);
|
||||
this.onRowClicked = this.onRowClicked.bind(this);
|
||||
|
||||
// component events
|
||||
this.updateQuote = this.updateQuote.bind(this);
|
||||
@@ -70,6 +71,10 @@ export default class extends Component {
|
||||
this.gridApi.sizeColumnsToFit();
|
||||
}
|
||||
|
||||
onRowClicked(params) {
|
||||
this.props.onRowClicked(params.data.symbol);
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
this.props.selectedExchange.supportedStocks.forEach(symbol => {
|
||||
this.exchangeService.addSubscriber(this.updateQuote, symbol);
|
||||
@@ -151,7 +156,8 @@ export default class extends Component {
|
||||
enableSorting="true"
|
||||
|
||||
// events
|
||||
onGridReady={this.onGridReady}>
|
||||
onGridReady={this.onGridReady}
|
||||
onRowClicked={this.onRowClicked}>
|
||||
</AgGridReact>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import React, {Component} from "react";
|
||||
|
||||
import ExchangeService from "../services/ExchangeService.jsx";
|
||||
|
||||
import StockPriceDeltaPanel from "./StockPriceDeltaPanel.jsx";
|
||||
import StockTimestampPanel from "./StockTimestampPanel.jsx";
|
||||
import StockSummaryPanel from "./StockSummaryPanel.jsx";
|
||||
@@ -8,15 +10,42 @@ import StockHistoricalChartPanel from "./StockHistoricalChartPanel.jsx";
|
||||
export default class extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.exchangeService = new ExchangeService();
|
||||
|
||||
this.state = {
|
||||
priceDelta: null,
|
||||
timestamp: null,
|
||||
tickerSummary: null,
|
||||
historicalData: null
|
||||
}
|
||||
}
|
||||
|
||||
shouldComponentUpdate(nextProps, nextState) {
|
||||
return nextProps.selectedSymbol !== this.props.selectedSymbol;
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps, nextState) {
|
||||
if (nextProps.selectedSymbol !== this.props.selectedSymbol) {
|
||||
let stockDetail = this.exchangeService.getTickerDetail(nextProps.selectedSymbol);
|
||||
|
||||
this.setState({
|
||||
pricingDelta: stockDetail.pricingDelta,
|
||||
timestamp: stockDetail.timestamp,
|
||||
tickerSummary: stockDetail.tickerSummary,
|
||||
historicalData: stockDetail.historicalData
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<StockPriceDeltaPanel />
|
||||
<StockTimestampPanel />
|
||||
<StockSummaryPanel />
|
||||
<StockHistoricalChartPanel />
|
||||
<StockPriceDeltaPanel pricingDelta={this.state.pricingDelta}/>
|
||||
<StockTimestampPanel timestamp={this.state.timestamp}
|
||||
exchangeName={this.props.exchangeName}/>
|
||||
<StockSummaryPanel tickerSummary={this.state.tickerSummary}/>
|
||||
<StockHistoricalChartPanel historicalData={this.state.historicalData} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -6,16 +6,30 @@ import StockDetailPanel from "./StockDetailPanel.jsx";
|
||||
export default class extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
selectedSymbol: null
|
||||
};
|
||||
|
||||
this.onRowClicked = this.onRowClicked.bind(this);
|
||||
}
|
||||
|
||||
onRowClicked(selectedSymbol) {
|
||||
this.setState({
|
||||
selectedSymbol
|
||||
})
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<div style={{float: "left", marginRight: 25}}>
|
||||
<LiveUpdatesGrid selectedExchange={this.props.selectedExchange}></LiveUpdatesGrid>
|
||||
<LiveUpdatesGrid selectedExchange={this.props.selectedExchange}
|
||||
onRowClicked={this.onRowClicked} />
|
||||
</div>
|
||||
<div style={{float: "left"}}>
|
||||
<StockDetailPanel></StockDetailPanel>
|
||||
<StockDetailPanel selectedSymbol={this.state.selectedSymbol}
|
||||
exchangeName={this.props.selectedExchange.name}/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,8 +1,38 @@
|
||||
import React, {Component} from "react";
|
||||
|
||||
import isEqual from "lodash/isEqual";
|
||||
|
||||
export default class extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
currentPrice: null,
|
||||
delta: null,
|
||||
deltaPercentage: null
|
||||
}
|
||||
}
|
||||
|
||||
shouldComponentUpdate(nextProps, nextState) {
|
||||
return !isEqual(this.props.pricingDelta, nextProps.pricingDelta);
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps, nextState) {
|
||||
if (!isEqual(this.props.pricingDelta, nextProps.pricingDelta)) {
|
||||
let pricingDelta = nextProps.pricingDelta;
|
||||
let delta = pricingDelta.currentPrice - pricingDelta.previousPrice;
|
||||
let deltaPercentage = (pricingDelta.currentPrice - pricingDelta.previousPrice) / pricingDelta.currentPrice;
|
||||
|
||||
this.setState({
|
||||
currentPrice: pricingDelta.currentPrice,
|
||||
delta,
|
||||
deltaPercentage
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
numberFormatter(input) {
|
||||
return input.toFixed(2);
|
||||
}
|
||||
|
||||
render() {
|
||||
@@ -32,18 +62,25 @@ export default class extends Component {
|
||||
marginRight: 5
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<span style={priceStyle}>
|
||||
155.47
|
||||
</span>
|
||||
<div style={containerStyle}>
|
||||
<span style={deltaStyle}>
|
||||
<span style={negativeSwingStyle}>-0.23</span>
|
||||
<span style={negativeSwingStyle}>(-0.15%)</span>
|
||||
let swingStyle = this.state.delta >= 0 ? positiveSwingStyle : negativeSwingStyle;
|
||||
|
||||
if(!this.props.pricingDelta) {
|
||||
return null;
|
||||
} else {
|
||||
return (
|
||||
<div>
|
||||
<span style={priceStyle}>
|
||||
{this.numberFormatter(this.state.currentPrice)}
|
||||
</span>
|
||||
<div style={containerStyle}>
|
||||
<span style={deltaStyle}>
|
||||
<span style={swingStyle}>{this.numberFormatter(this.state.delta)}</span>
|
||||
<span
|
||||
style={swingStyle}>({this.numberFormatter(this.state.deltaPercentage)}%)</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,9 +13,9 @@ export default class extends Component {
|
||||
let tableStyle = {
|
||||
display: "inline-block",
|
||||
verticalAlign: "top",
|
||||
borderCollapse:"collapse"
|
||||
borderCollapse: "collapse"
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
let keyStyle = {
|
||||
color: "#666"
|
||||
@@ -25,70 +25,54 @@ export default class extends Component {
|
||||
textAlign: "right"
|
||||
};
|
||||
|
||||
return (
|
||||
<div style={containerStyle}>
|
||||
<table style={tableStyle}>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style={keyStyle}>Range
|
||||
</td>
|
||||
<td style={valueStyle}>154.72 - 156.06
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style={keyStyle}>52 week
|
||||
</td>
|
||||
<td style={valueStyle}>91.50 - 156.65
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style={keyStyle}>Open
|
||||
</td>
|
||||
<td style={valueStyle}>155.94
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style={keyStyle}>
|
||||
Vol / Avg.
|
||||
</td>
|
||||
<td style={valueStyle}>15,931.00/24.94M
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table style={tableStyle}>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style={keyStyle}>
|
||||
Div/yield
|
||||
</td>
|
||||
<td style={valueStyle}>0.63/1.62
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style={keyStyle}>
|
||||
EPS
|
||||
</td>
|
||||
<td style={valueStyle}>8.55
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style={keyStyle}>
|
||||
Shares
|
||||
</td>
|
||||
<td style={valueStyle}>5,213.84M
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style={keyStyle}>
|
||||
Mkt cap
|
||||
</td>
|
||||
<td style={valueStyle}>808,518.60M
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
);
|
||||
if (!this.props.tickerSummary) {
|
||||
return null;
|
||||
} else {
|
||||
return (
|
||||
<div style={containerStyle}>
|
||||
<table style={tableStyle}>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style={keyStyle}>Range</td>
|
||||
<td style={valueStyle}>{this.props.tickerSummary.range}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style={keyStyle}>52 week</td>
|
||||
<td style={valueStyle}>{this.props.tickerSummary.fiftyTwoWeek}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style={keyStyle}>Open</td>
|
||||
<td style={valueStyle}>{this.props.tickerSummary.open}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style={keyStyle}>Vol / Avg.</td>
|
||||
<td style={valueStyle}>{this.props.tickerSummary.vol}/{this.props.tickerSummary.avg}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table style={tableStyle}>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style={keyStyle}>Div/yield</td>
|
||||
<td style={valueStyle}>{this.props.tickerSummary.dividend}/{this.props.tickerSummary.yld}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style={keyStyle}>EPS</td>
|
||||
<td style={valueStyle}>{this.props.tickerSummary.eps}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style={keyStyle}>Shares</td>
|
||||
<td style={valueStyle}>{this.props.tickerSummary.shares}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style={keyStyle}>Market Cap</td>
|
||||
<td style={valueStyle}>{this.props.tickerSummary.marketCap}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,41 +6,25 @@ export default class extends Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
let containerStyle = {
|
||||
display: "inline-block"
|
||||
};
|
||||
|
||||
let priceStyle = {
|
||||
fontSize: "2.6em",
|
||||
fontWeight: "bold",
|
||||
marginRight: 10
|
||||
};
|
||||
|
||||
let minorStyle = {
|
||||
fontSize: 11,
|
||||
color: "#6F6F6F"
|
||||
};
|
||||
|
||||
let negativeSwingStyle = {
|
||||
color: "#d14836",
|
||||
marginRight: 5
|
||||
};
|
||||
|
||||
let positiveSwingStyle = {
|
||||
color: "#093",
|
||||
marginRight: 5
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div id="ref_304466804484872_elt">
|
||||
May 17, 6:17am GMT-4
|
||||
<div style={minorStyle}>
|
||||
<span>NASDAQ</span>
|
||||
<div>Currency in USD</div>
|
||||
if (!this.props.timestamp) {
|
||||
return null;
|
||||
} else {
|
||||
return (
|
||||
<div>
|
||||
<div>
|
||||
{this.props.timestamp}
|
||||
<div style={minorStyle}>
|
||||
<span>{this.props.exchangeName}</span>
|
||||
<div>Currency in USD</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -36,7 +36,7 @@ export default class TraderDashboard extends Component {
|
||||
onExchangeChanged={this.onExchangeChanged}>
|
||||
</ControlPanel>
|
||||
</div>
|
||||
<StockPanel selectedExchange={this.state.selectedExchange}></StockPanel>
|
||||
<StockPanel selectedExchange={this.state.selectedExchange}/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -17,6 +17,8 @@ export default class {
|
||||
];
|
||||
|
||||
this.initialiseTickerData();
|
||||
|
||||
this.timestamp = new Date();
|
||||
}
|
||||
|
||||
initialiseTickerData() {
|
||||
@@ -95,6 +97,102 @@ export default class {
|
||||
return exchange.symbol === exchangeName;
|
||||
})
|
||||
}
|
||||
|
||||
formatNumber(input) {
|
||||
return input.toFixed(2);
|
||||
}
|
||||
|
||||
formatWithDecimalPlaces(x) {
|
||||
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
||||
}
|
||||
|
||||
getTickerDetail(symbol) {
|
||||
let ticker = this.getTicker(symbol);
|
||||
let currentPrice = ticker.price;
|
||||
let tenthOfCurrentPrice = currentPrice / 10;
|
||||
let previousPrice = +currentPrice + this.random(-tenthOfCurrentPrice, tenthOfCurrentPrice);
|
||||
|
||||
let twentiethOfCurrentPrice = currentPrice / 20;
|
||||
let yearAgoPrice = this.random(-twentiethOfCurrentPrice, twentiethOfCurrentPrice);
|
||||
|
||||
let range = `${this.formatNumber(previousPrice)} - ${this.formatNumber(currentPrice)}`;
|
||||
let fiftyTwoWeek = `${this.formatNumber(yearAgoPrice)} - ${this.formatNumber(currentPrice)}`;
|
||||
|
||||
let open = this.formatNumber(ticker.bid); // not the same, but will do for demo purposes
|
||||
|
||||
let vol = this.formatWithDecimalPlaces(this.random(5000, 20000).toFixed(2));
|
||||
let avg = `${this.formatNumber(this.random(10, 30))}M`;
|
||||
|
||||
let dividend = this.random(0, 1).toFixed(2);
|
||||
let yld = this.random(1, 2).toFixed(2);
|
||||
|
||||
let eps = this.random(5, 10).toFixed(2);
|
||||
|
||||
let shares = `${this.random(3000, 10000).toFixed(2)}M`;
|
||||
|
||||
let marketCap = `${this.random(100000, 900000).toFixed(2)}M`;
|
||||
|
||||
let historicalData = this.generateHistoricalData(100, this.timestamp, currentPrice);
|
||||
|
||||
return {
|
||||
pricingDelta: {
|
||||
currentPrice,
|
||||
previousPrice
|
||||
},
|
||||
timestamp: this.timestamp.toDateString(),
|
||||
tickerSummary: {
|
||||
range,
|
||||
fiftyTwoWeek,
|
||||
open,
|
||||
vol,
|
||||
avg,
|
||||
dividend,
|
||||
yld,
|
||||
eps,
|
||||
shares,
|
||||
marketCap
|
||||
},
|
||||
historicalData
|
||||
}
|
||||
}
|
||||
|
||||
formatDate(date) {
|
||||
// todo remove substring(2,4) and change parseTime instead
|
||||
let year = ("" + date.getFullYear()).substring(2, 4);
|
||||
return `${date.getDate()}-${date.getMonth()+1}-${year}`
|
||||
// return `${date.getDate()}-${date.getMonth()+1}-${date.getFullYear()
|
||||
}
|
||||
|
||||
generateHistoricalData(numberOfPoints, endDate, endPrice) {
|
||||
let historicalData = [{
|
||||
"date": this.formatDate(endDate),
|
||||
"price": endPrice
|
||||
}
|
||||
];
|
||||
|
||||
let numberOfTransitions = 15;
|
||||
let pointsPerTransition = numberOfPoints / numberOfTransitions;
|
||||
|
||||
let lastDate = endDate;
|
||||
let lastPrice = endPrice;
|
||||
for (let transition = 0; transition < numberOfTransitions; transition++) {
|
||||
let swing = (Math.random() >= 0.5) ? 1 : -1;
|
||||
|
||||
for (let i = 0; i <= pointsPerTransition; i++) {
|
||||
lastDate.setDate(lastDate.getDate() - 1);
|
||||
lastPrice = lastPrice + (swing * this.random(-1, 10));
|
||||
|
||||
historicalData.push({
|
||||
"date": this.formatDate(lastDate),
|
||||
"price": lastPrice
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
historicalData = historicalData.reverse();
|
||||
|
||||
return historicalData;
|
||||
}
|
||||
}
|
||||
|
||||
const NASDAQ_SYMBOLS = [
|
||||
|
||||
Reference in New Issue
Block a user