mirror of
https://github.com/RoboSats/robosats.git
synced 2025-01-31 02:21:35 +00:00
Implement responsive order book
This commit is contained in:
parent
493684b8c9
commit
6ab8f86b97
@ -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)
|
||||
|
29
frontend/package-lock.json
generated
29
frontend/package-lock.json
generated
@ -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",
|
||||
|
@ -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"
|
||||
}
|
||||
|
@ -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">
|
||||
|
1
setup.md
1
setup.md
@ -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)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user