Implement responsive order book

This commit is contained in:
Reckless_Satoshi 2022-01-27 06:40:14 -08:00
parent 493684b8c9
commit 6ab8f86b97
No known key found for this signature in database
GPG Key ID: 9C4585B561315571
5 changed files with 110 additions and 13 deletions

View File

@ -89,7 +89,7 @@ class Logics():
return int(satoshis_now)
def price_and_premium_now(order):
''' computes order premium live '''
''' computes order price and premium with current rates '''
exchange_rate = float(order.currency.exchange_rate)
if not order.is_explicit:
premium = order.premium
@ -244,7 +244,8 @@ class Logics():
return True, None
def dispute_statement(order, user, statement):
''' Updates the dispute statements in DB'''
''' Updates the dispute statements'''
if not order.status == Order.Status.DIS:
return False, {'bad_request':'Only orders in dispute accept a dispute statements'}
@ -278,6 +279,7 @@ class Logics():
def update_invoice(cls, order, user, invoice):
# only the buyer can post a buyer invoice
if not cls.is_buyer(order, user):
return False, {'bad_request':'Only the buyer of this order can provide a buyer invoice.'}
if not order.taker_bond:
@ -364,8 +366,8 @@ class Logics():
@classmethod
def cancel_order(cls, order, user, state=None):
# Do not change order status if an order in any with
# any of these status is sent to expire here
# Do not change order status if an is in order
# any of these status
do_not_cancel = [Order.Status.DEL, Order.Status.UCA,
Order.Status.EXP, Order.Status.TLD,
Order.Status.DIS, Order.Status.CCA,
@ -377,7 +379,7 @@ class Logics():
# 1) When maker cancels before bond
'''The order never shows up on the book and order
status becomes "cancelled". That's it.'''
status becomes "cancelled" '''
if order.status == Order.Status.WFB and order.maker == user:
order.status = Order.Status.UCA
order.save()
@ -744,7 +746,7 @@ class Logics():
def confirm_fiat(cls, order, user):
''' If Order is in the CHAT states:
If user is buyer: fiat_sent goes to true.
If User is tseller and fiat_sent is true: settle the escrow and pay buyer invoice!'''
If User is seller and fiat_sent is true: settle the escrow and pay buyer invoice!'''
if order.status == Order.Status.CHA or order.status == Order.Status.FSE: # TODO Alternatively, if all collateral is locked? test out
@ -786,9 +788,11 @@ class Logics():
@classmethod
def rate_counterparty(cls, order, user, rating):
rating_allowed_status = [Order.Status.PAY, Order.Status.SUC, Order.Status.FAI, Order.Status.MLD, Order.Status.TLD]
# If the trade is finished
if order.status > Order.Status.PAY:
if order.status in rating_allowed_status:
# if maker, rates taker
if order.maker == user and order.maker_rated == False:
cls.add_profile_rating(order.taker.profile, rating)

View File

@ -3253,6 +3253,11 @@
"which": "^2.0.1"
}
},
"css-mediaquery": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/css-mediaquery/-/css-mediaquery-0.1.2.tgz",
"integrity": "sha1-aiw3NEkoYYYxxUvTPO3TAdoYvqA="
},
"css-select": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/css-select/-/css-select-2.1.0.tgz",
@ -5040,6 +5045,14 @@
"object-visit": "^1.0.0"
}
},
"matchmediaquery": {
"version": "0.3.1",
"resolved": "https://registry.npmjs.org/matchmediaquery/-/matchmediaquery-0.3.1.tgz",
"integrity": "sha512-Hlk20WQHRIm9EE9luN1kjRjYXAQToHOIAHPJn9buxBwuhfTHoKUcX+lXBbxc85DVQfXYbEQ4HcwQdd128E3qHQ==",
"requires": {
"css-mediaquery": "^0.1.2"
}
},
"material-ui-image": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/material-ui-image/-/material-ui-image-3.3.2.tgz",
@ -6444,6 +6457,17 @@
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.4.3.tgz",
"integrity": "sha512-Hwln1VNuGl/6bVwnd0Xdn1e84gT/8T9aYNL+HAKDArLCS7LWjwr7StE30IEYbIkx0Vi3vs+coQxe+SQDbGbbpA=="
},
"react-responsive": {
"version": "9.0.0-beta.6",
"resolved": "https://registry.npmjs.org/react-responsive/-/react-responsive-9.0.0-beta.6.tgz",
"integrity": "sha512-Flk6UrnpBBByreva6ja/TsbXiXq4BXOlDEKL6Ur+nshUs3CcN5W0BpGe6ClFWrKcORkMZAAYy7A4N4xlMmpgVw==",
"requires": {
"hyphenate-style-name": "^1.0.0",
"matchmediaquery": "^0.3.0",
"prop-types": "^15.6.1",
"shallow-equal": "^1.2.1"
}
},
"react-router": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/react-router/-/react-router-5.2.0.tgz",
@ -7076,6 +7100,11 @@
"kind-of": "^6.0.2"
}
},
"shallow-equal": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/shallow-equal/-/shallow-equal-1.2.1.tgz",
"integrity": "sha512-S4vJDjHHMBaiZuT9NPb616CSmLf618jawtv3sufLl6ivK8WocjAo58cXwbRV1cgqxH0Qbv+iUt6m05eqEa2IRA=="
},
"shebang-command": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",

View File

@ -35,6 +35,7 @@
"react-native": "^0.66.4",
"react-native-svg": "^12.1.1",
"react-qr-code": "^2.0.3",
"react-responsive": "^9.0.0-beta.6",
"react-router-dom": "^5.2.0",
"websocket": "^1.0.34"
}

View File

@ -2,6 +2,8 @@ import React, { Component } from "react";
import { Paper, Button , CircularProgress, ListItemButton, Typography, Grid, Select, MenuItem, FormControl, FormHelperText, List, ListItem, ListItemText, Avatar, RouterLink, ListItemAvatar} from "@mui/material";
import { Link } from 'react-router-dom'
import { DataGrid } from '@mui/x-data-grid';
import MediaQuery from 'react-responsive'
import getFlags from './getFlags'
export default class BookPage extends Component {
@ -68,8 +70,8 @@ export default class BookPage extends Component {
pn(x) {
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
bookListTable=()=>{
bookListTableDesktop=()=>{
return (
<div style={{ height: 475, width: '100%' }}>
<DataGrid
@ -124,6 +126,58 @@ export default class BookPage extends Component {
);
}
bookListTablePhone=()=>{
return (
<div style={{ height: 425, width: '100%' }}>
<DataGrid
rows={
this.state.orders.map((order) =>
({id: order.id,
avatar: window.location.origin +'/static/assets/avatars/' + order.maker_nick + '.png',
robosat: order.maker_nick,
type: order.type ? "Sell": "Buy",
amount: parseFloat(parseFloat(order.amount).toFixed(4)),
currency: this.getCurrencyCode(order.currency),
payment_method: order.payment_method,
price: order.price,
premium: order.premium,
})
)}
columns={[
// { field: 'id', headerName: 'ID', width: 40 },
{ field: 'robosat', headerName: 'Robot', width: 80,
renderCell: (params) => {return (
<ListItemButton style={{ cursor: "pointer" }}>
<Avatar alt={params.row.robosat} src={params.row.avatar} />
</ListItemButton>
);
} },
{ field: 'type', headerName: 'Type', width: 60, hide:'true'},
{ field: 'amount', headerName: 'Amount', type: 'number', width: 80 },
{ field: 'currency', headerName: 'Currency', width: 100,
renderCell: (params) => {return (
<div style={{ cursor: "pointer" }}>{params.row.currency + " " + getFlags(params.row.currency)}</div>
)} },
{ field: 'payment_method', headerName: 'Payment Method', width: 180, hide:'true'},
{ field: 'price', headerName: 'Price', type: 'number', width: 140, hide:'true',
renderCell: (params) => {return (
<div style={{ cursor: "pointer" }}>{this.pn(params.row.price) + " " +params.row.currency+ "/BTC" }</div>
)} },
{ field: 'premium', headerName: 'Premium', type: 'number', width: 85,
renderCell: (params) => {return (
<div style={{ cursor: "pointer" }}>{parseFloat(parseFloat(params.row.premium).toFixed(4))+"%" }</div>
)} },
]}
pageSize={6}
onRowClick={(params) => this.handleRowClick(params.row.id)} // Whole row is clickable, but the mouse only looks clickly in some places.
rowsPerPageOptions={[6]}
/>
</div>
);
}
render() {
return (
<Grid className='orderBook' container spacing={1}>
@ -206,11 +260,19 @@ export default class BookPage extends Component {
</Grid>)
:
<Grid item xs={12} align="center">
<Paper elevation={0} style={{width: 910, maxHeight: 500, overflow: 'auto'}}>
{/* Desktop Book */}
<MediaQuery minWidth={920}>
<Paper elevation={0} style={{width: 910, maxHeight: 500, overflow: 'auto'}}>
{this.state.loading ? null : this.bookListTableDesktop()}
</Paper>
</MediaQuery>
{this.state.loading ? null : this.bookListTable()}
</Paper>
{/* Smartphone Book */}
<MediaQuery maxWidth={919}>
<Paper elevation={0} style={{width: 380, maxHeight: 450, overflow: 'auto'}}>
{this.state.loading ? null : this.bookListTablePhone()}
</Paper>
</MediaQuery>
</Grid>
}
<Grid item xs={12} align="center">

View File

@ -126,6 +126,7 @@ npm install websocket
npm install react-countdown
npm install @mui/icons-material
npm install @mui/x-data-grid
npm install react-responsive
```
Note we are using mostly MaterialUI V5 (@mui/material) but Image loading from V4 (@material-ui/core) extentions (so both V4 and V5 are needed)