tailwind #9
@ -4,12 +4,14 @@ import HCard from "./HCard";
|
||||
import RPlot from "./RPlot";
|
||||
import {NewTickData, PositionState, socket} from "../";
|
||||
import {PositionTable} from "./Tables";
|
||||
import {EventData, Events} from "./Events";
|
||||
|
||||
type AppState = {
|
||||
current_price: number,
|
||||
current_tick: number,
|
||||
last_update: Date,
|
||||
positions: Array<PositionState>
|
||||
positions: Array<PositionState>,
|
||||
events: Array<EventData>
|
||||
}
|
||||
|
||||
|
||||
@ -18,7 +20,8 @@ class App extends Component<{}, AppState> {
|
||||
current_price: 0,
|
||||
current_tick: 0,
|
||||
last_update: new Date(),
|
||||
positions: []
|
||||
positions: [],
|
||||
events: []
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
@ -27,11 +30,14 @@ class App extends Component<{}, AppState> {
|
||||
|
||||
componentDidMount() {
|
||||
socket.on("new_tick", (data: NewTickData) => {
|
||||
const event: EventData = {name: "New Tick", id: data.tick, tick: data.tick}
|
||||
|
||||
this.setState({
|
||||
current_price: data.price,
|
||||
current_tick: data.tick,
|
||||
last_update: new Date(),
|
||||
positions: data.positions
|
||||
positions: data.positions,
|
||||
events: [...this.state.events, event]
|
||||
})
|
||||
})
|
||||
}
|
||||
@ -40,22 +46,25 @@ class App extends Component<{}, AppState> {
|
||||
return (
|
||||
<div className="d-flex flex-fill flex-column">
|
||||
<Navbar bg="light" expand="lg" className="border-bottom">
|
||||
<Navbar.Brand href="#home">Rustico - BfxBot</Navbar.Brand>
|
||||
<Navbar.Brand href="#">Rustico - BfxBot</Navbar.Brand>
|
||||
</Navbar>
|
||||
|
||||
<Container fluid className="mt-2 border flex-fill d-flex">
|
||||
<Row className="flex-fill">
|
||||
{/* Toolbar column */}
|
||||
<Col md={4} lg={4} className="border-right">
|
||||
<Col md={4} lg={4} className="border-right d-flex flex-column">
|
||||
<Row className="justify-content-center border-bottom py-2">
|
||||
<HCard title="Current tick:" content={String(this.state.current_tick)}
|
||||
update={this.state.last_update}/>
|
||||
<HCard title="Current price:" content={String(this.state.current_price)}
|
||||
update={this.state.last_update}/>
|
||||
</Row>
|
||||
<Row>
|
||||
<Row className={"flex-fill"}>
|
||||
<PositionTable/>
|
||||
</Row>
|
||||
<Row className={"my-2"}>
|
||||
<Events events={this.state.events}/>
|
||||
</Row>
|
||||
</Col>
|
||||
|
||||
{/* Graph column */}
|
||||
@ -71,7 +80,7 @@ class App extends Component<{}, AppState> {
|
||||
<RPlot />
|
||||
</Row> */}
|
||||
</Container>
|
||||
<footer className="footer fixed-bottom py-3 bg-light border-top">
|
||||
<footer className="footer py-3 bg-light border-top">
|
||||
<Container className="text-center">
|
||||
<span className="text-muted">Made with ❤️ by the Pepe</span>
|
||||
</Container>
|
||||
|
49
websrc/components/Events.tsx
Normal file
49
websrc/components/Events.tsx
Normal file
@ -0,0 +1,49 @@
|
||||
import React, {Component} from "react";
|
||||
import {Container, ListGroup} from "react-bootstrap";
|
||||
|
||||
|
||||
export type EventData = {
|
||||
id: number,
|
||||
name: string,
|
||||
tick: number
|
||||
}
|
||||
|
||||
|
||||
const testEvent: EventData = {
|
||||
id: 1,
|
||||
name: "Test",
|
||||
tick: 1
|
||||
}
|
||||
|
||||
export class Events extends Component<{ events: Array<EventData> }, { events: Array<EventData> }> {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
state = {
|
||||
events: this.props.events
|
||||
}
|
||||
|
||||
mapEvents() {
|
||||
return this.state.events.map((event: EventData) => {
|
||||
return (
|
||||
<ListGroup.Item action key={event.id}>
|
||||
{event.name} @ Tick {event.tick}
|
||||
</ListGroup.Item>
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Container>
|
||||
<div className={"border-bottom mb-2"}>
|
||||
<h2>Events</h2>
|
||||
</div>
|
||||
<ListGroup>
|
||||
{this.mapEvents()}
|
||||
</ListGroup>
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
}
|
@ -1,33 +1,71 @@
|
||||
import React, {Component} from "react"
|
||||
import {Container, Table} from "react-bootstrap"
|
||||
import {NewTickData, PositionState, socket} from '../';
|
||||
import {Badge, Button, Container, Table} from "react-bootstrap"
|
||||
import {PositionState} from '../';
|
||||
|
||||
|
||||
export class PositionTable extends Component<{}, { positions: Array<PositionState> }> {
|
||||
testPosition: PositionState = {
|
||||
base_price: 1,
|
||||
id: 1,
|
||||
profit_loss: 1000,
|
||||
profit_loss_percentage: 1000,
|
||||
state: "loss",
|
||||
symbol: "PAPARCOIN"
|
||||
}
|
||||
|
||||
state = {
|
||||
positions: []
|
||||
positions: [this.testPosition]
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props)
|
||||
}
|
||||
|
||||
stateVariantFromStr(state: string): string {
|
||||
const lower_state = state.toLowerCase()
|
||||
let res: string;
|
||||
|
||||
if (lower_state.includes("profit")) {
|
||||
res = "success"
|
||||
} else if (lower_state.includes("break")) {
|
||||
res = "primary"
|
||||
} else {
|
||||
res = "danger"
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
plColorFromStr(amount: number): string {
|
||||
if (amount > 0) {
|
||||
return "success"
|
||||
} else {
|
||||
return "danger"
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
socket.on('new_tick', (data: NewTickData) => {
|
||||
this.setState({
|
||||
positions: data.positions
|
||||
})
|
||||
this.setState({
|
||||
positions: [this.testPosition]
|
||||
})
|
||||
|
||||
// socket.on('new_tick', (data: NewTickData) => {
|
||||
// this.setState({
|
||||
// positions: [...this.state.positions, data.positions]
|
||||
// })
|
||||
// })
|
||||
}
|
||||
|
||||
tableData() {
|
||||
return this.state.positions.map((position: PositionState) => {
|
||||
return (<tr key={position.id}>
|
||||
<th>{position.id}</th>
|
||||
<th>{position.symbol}</th>
|
||||
<th>{position.base_price.toFixed(2)}</th>
|
||||
<th>{position.profit_loss.toFixed(2)}</th>
|
||||
<th>{position.profit_loss_percentage.toFixed(2)} %</th>
|
||||
<td className={"align-middle"}><Badge
|
||||
variant={this.stateVariantFromStr(position.state)}>{position.state}</Badge></td>
|
||||
<td className={"align-middle"}>{position.symbol}</td>
|
||||
<td className={"align-middle"}>{position.base_price.toFixed(2)}</td>
|
||||
<td className={"align-middle"}>{position.profit_loss.toFixed(2)}</td>
|
||||
<td className={"align-middle"}>{position.profit_loss_percentage.toFixed(2)} %</td>
|
||||
<td className={"align-middle"}><Button size={"sm"} variant={"danger"}>Close</Button></td>
|
||||
</tr>)
|
||||
})
|
||||
}
|
||||
@ -38,14 +76,15 @@ export class PositionTable extends Component<{}, { positions: Array<PositionStat
|
||||
<div className="border-bottom">
|
||||
<h2>Open positions</h2>
|
||||
</div>
|
||||
<Table id="positions" size="sm" hover striped bordered className="mt-2 text-center">
|
||||
<Table id="positions" size="sm" hover striped bordered className="mt-2 text-center align-middle">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>State</th>
|
||||
<th>Symbol</th>
|
||||
<th>Base price</th>
|
||||
<th>P/L</th>
|
||||
<th>P/L %</th>
|
||||
<th>Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
@ -14,6 +14,7 @@ export type NewTickData = {
|
||||
|
||||
export type PositionState = {
|
||||
id: number,
|
||||
state: string,
|
||||
base_price: number,
|
||||
symbol: string,
|
||||
profit_loss: number,
|
||||
|
Loading…
Reference in New Issue
Block a user