Add UI info and icons on order pager

This commit is contained in:
Reckless_Satoshi 2022-01-14 04:00:53 -08:00
parent abb1bdd0be
commit 135c4c59e5
No known key found for this signature in database
GPG Key ID: 9C4585B561315571
7 changed files with 102 additions and 22 deletions

View File

@ -133,6 +133,27 @@ class Order(models.Model):
maker_cancel = models.ForeignKey(LNPayment, related_name='maker_cancel', on_delete=models.SET_NULL, null=True, default=None, blank=True)
taker_cancel = models.ForeignKey(LNPayment, related_name='taker_cancel', on_delete=models.SET_NULL, null=True, default=None, blank=True)
total_time_to_expire = {
0 : int(config('EXP_MAKER_BOND_INVOICE')) , # 'Waiting for maker bond'
1 : 60*60*int(config('PUBLIC_ORDER_DURATION')), # 'Public'
2 : 0, # 'Deleted'
3 : int(config('EXP_TAKER_BOND_INVOICE')), # 'Waiting for taker bond'
4 : 0, # 'Cancelled'
5 : 0, # 'Expired'
6 : 60*int(config('INVOICE_AND_ESCROW_DURATION')), # 'Waiting for trade collateral and buyer invoice'
7 : 60*int(config('INVOICE_AND_ESCROW_DURATION')), # 'Waiting only for seller trade collateral'
8 : 60*int(config('INVOICE_AND_ESCROW_DURATION')), # 'Waiting only for buyer invoice'
9 : 60*60*int(config('FIAT_EXCHANGE_DURATION')), # 'Sending fiat - In chatroom'
10 : 60*60*int(config('FIAT_EXCHANGE_DURATION')), # 'Fiat sent - In chatroom'
11 : 24*60*60, # 'In dispute'
12 : 0, # 'Collaboratively cancelled'
13 : 24*60*60, # 'Sending satoshis to buyer'
14 : 24*60*60, # 'Sucessful trade'
15 : 24*60*60, # 'Failed lightning network routing'
16 : 24*60*60, # 'Maker lost dispute'
17 : 24*60*60, # 'Taker lost dispute'
}
def __str__(self):
# Make relational back to ORDER
return (f'Order {self.id}: {self.Types(self.type).label} BTC for {float(self.amount)} {self.currency_dict[str(self.currency)]}')

View File

@ -106,6 +106,7 @@ class OrderView(viewsets.ViewSet):
return Response({'bad_request':'This order has been cancelled collaborativelly'},status.HTTP_400_BAD_REQUEST)
data = ListOrderSerializer(order).data
data['total_secs_exp'] = Order.total_time_to_expire[order.status]
# if user is under a limit (penalty), inform him.
is_penalized, time_out = Logics.is_penalized(request.user)
@ -116,12 +117,21 @@ class OrderView(viewsets.ViewSet):
data['is_maker'] = order.maker == request.user
data['is_taker'] = order.taker == request.user
data['is_participant'] = data['is_maker'] or data['is_taker']
data['ur_nick'] = request.user.username
# 3) If not a participant and order is not public, forbid.
# 3.a) If not a participant and order is not public, forbid.
if not data['is_participant'] and order.status != Order.Status.PUB:
return Response({'bad_request':'You are not allowed to see this order'},status.HTTP_403_FORBIDDEN)
# 3.b If public
if order.status == Order.Status.PUB:
data['price_now'], data['premium_now'] = Logics.price_and_premium_now(order)
# 3. c) If maker and Public, add num robots in book, premium percentile and num similar orders.
if data['is_maker']:
data['robots_in_book'] = None # TODO
data['premium_percentile'] = None # TODO
data['num_similar_orders'] = len(Order.objects.filter(currency=order.currency, status=Order.Status.PUB))
# 4) Non participants can view details (but only if PUB)
elif not data['is_participant'] and order.status != Order.Status.PUB:
return Response(data, status=status.HTTP_200_OK)
@ -134,6 +144,7 @@ class OrderView(viewsets.ViewSet):
data['status_message'] = Order.Status(order.status).label
data['is_fiat_sent'] = order.is_fiat_sent
data['is_disputed'] = order.is_disputed
data['ur_nick'] = request.user.username
# If both bonds are locked, participants can see the final trade amount in sats.
if order.taker_bond:
@ -281,14 +292,14 @@ class UserView(APIView):
Response with Avatar and Nickname.
'''
# if request.user.id:
# context = {}
# context['nickname'] = request.user.username
# participant = not Logics.validate_already_maker_or_taker(request.user)
# context['bad_request'] = f'You are already logged in as {request.user}'
# if participant:
# context['bad_request'] = f'You are already logged in as as {request.user} and have an active order'
# return Response(context,status.HTTP_200_OK)
if request.user.id:
context = {}
context['nickname'] = request.user.username
participant = not Logics.validate_already_maker_or_taker(request.user)
context['bad_request'] = f'You are already logged in as {request.user}'
if participant:
context['bad_request'] = f'You are already logged in as as {request.user} and have an active order'
return Response(context,status.HTTP_200_OK)
token = request.GET.get(self.lookup_url_kwarg)

View File

@ -1581,6 +1581,14 @@
"react-is": "^17.0.2"
}
},
"@mui/icons-material": {
"version": "5.2.5",
"resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-5.2.5.tgz",
"integrity": "sha512-uQiUz+l0xy+2jExyKyU19MkMAR2F7bQFcsQ5hdqAtsB14Jw2zlmIAD55mV6f0NxKCut7Rx6cA3ZpfzlzAfoK8Q==",
"requires": {
"@babel/runtime": "^7.16.3"
}
},
"@mui/material": {
"version": "5.2.7",
"resolved": "https://registry.npmjs.org/@mui/material/-/material-5.2.7.tgz",

View File

@ -26,6 +26,7 @@
"@emotion/styled": "^11.6.0",
"@material-ui/core": "^4.12.3",
"@material-ui/icons": "^4.11.2",
"@mui/icons-material": "^5.2.5",
"@mui/material": "^5.2.7",
"@mui/system": "^5.2.6",
"material-ui-image": "^3.3.2",

View File

@ -1,8 +1,15 @@
import React, { Component } from "react";
import { Alert, Paper, CircularProgress, Button , Grid, Typography, List, ListItem, ListItemText, ListItemAvatar, Avatar, Divider, Box, LinearProgress} from "@mui/material"
import { Alert, Paper, CircularProgress, Button , Grid, Typography, List, ListItem, ListItemIcon, ListItemText, ListItemAvatar, Avatar, Divider, Box, LinearProgress} from "@mui/material"
import Countdown, { zeroPad, calcTimeDelta } from 'react-countdown';
import TradeBox from "./TradeBox";
// icons
import AccessTimeIcon from '@mui/icons-material/AccessTime';
import NumbersIcon from '@mui/icons-material/Numbers';
import PriceChangeIcon from '@mui/icons-material/PriceChange';
import PaymentsIcon from '@mui/icons-material/Payments';
import MoneyIcon from '@mui/icons-material/Money';
import ArticleIcon from '@mui/icons-material/Article';
function getCookie(name) {
let cookieValue = null;
@ -75,6 +82,13 @@ export default class OrderPage extends Component {
escrowInvoice: data.escrow_invoice,
escrowSatoshis: data.escrow_satoshis,
invoiceAmount: data.invoice_amount,
total_secs_expiry: data.total_secs_exp,
numSimilarOrders: data.num_similar_orders,
priceNow: data.price_now,
premiumNow: data.premium_now,
robotsInBook: data.robots_in_book,
premiumPercentile: data.premium_percentile,
numSimilarOrders: data.num_similar_orders
})
});
}
@ -106,15 +120,15 @@ export default class OrderPage extends Component {
if (completed) {
// Render a completed state
this.getOrderDetails();
return null;
} else {
var col = 'black'
var fraction_left = (total/1000) / this.state.total_secs_expiry
console.log(fraction_left)
// Make orange at -25% of time left
// Make orange at 25% of time left
if (fraction_left < 0.25){col = 'orange'}
// Make red at 10% of time left
if (fraction_left < 0.1){col = 'red'}
// Render a countdown
// Render a countdown, bold when less than 25%
return (
fraction_left < 0.25 ? <b><span style={{color:col}}>{hours}h {zeroPad(minutes)}m {zeroPad(seconds)}s </span></b>
:<span style={{color:col}}>{hours}h {zeroPad(minutes)}m {zeroPad(seconds)}s </span>
@ -226,6 +240,9 @@ export default class OrderPage extends Component {
""
}
<ListItem>
<ListItemIcon>
<ArticleIcon/>
</ListItemIcon>
<ListItemText primary={this.state.statusText} secondary="Order status"/>
</ListItem>
<Divider />
@ -234,28 +251,49 @@ export default class OrderPage extends Component {
}
<ListItem>
<ListItemIcon>
<MoneyIcon/>
</ListItemIcon>
<ListItemText primary={parseFloat(parseFloat(this.state.amount).toFixed(4))+" "+this.state.currencyCode} secondary="Amount"/>
</ListItem>
<Divider />
<ListItem>
<ListItemIcon>
<PaymentsIcon/>
</ListItemIcon>
<ListItemText primary={this.state.paymentMethod} secondary="Accepted payment methods"/>
</ListItem>
<Divider />
{/* If there is live Price and Premium data, show it. Otherwise show the order maker settings */}
<ListItem>
{this.state.isExplicit ?
<ListItemText primary={pn(this.state.satoshis)} secondary="Amount of Satoshis"/>
:
<ListItemText primary={parseFloat(parseFloat(this.state.premium).toFixed(2))+"%"} secondary="Premium over market price"/>
}
<ListItemIcon>
<PriceChangeIcon/>
</ListItemIcon>
{this.state.priceNow?
<ListItemText primary={pn(this.state.priceNow)+" "+this.state.currencyCode+"/BTC - Premium: "+this.state.premiumNow+"%"} secondary="Price and Premium"/>
:
(this.state.isExplicit ?
<ListItemText primary={pn(this.state.satoshis)} secondary="Amount of Satoshis"/>
:
<ListItemText primary={parseFloat(parseFloat(this.state.premium).toFixed(2))+"%"} secondary="Premium over market price"/>
)
}
</ListItem>
<Divider />
<ListItem>
<ListItemText primary={'#'+this.orderId} secondary="Order ID"/>
<ListItemIcon>
<NumbersIcon/>
</ListItemIcon>
<ListItemText primary={this.orderId} secondary="Order ID"/>
</ListItem>
<Divider />
<ListItem>
<ListItemText secondary="Expires">
<ListItemIcon>
<AccessTimeIcon/>
</ListItemIcon>
<ListItemText secondary="Expires in">
<Countdown onTick={console.log(this.seconds)} date={new Date(this.state.expiresAt)} renderer={this.countdownRenderer} />
</ListItemText>
</ListItem>

View File

@ -163,7 +163,7 @@ export default class TradeBox extends Component {
<Divider/>
<ListItem>
<ListItemText primary={999} secondary={"Active orders for " + this.props.data.currencyCode}/>
<ListItemText primary={this.props.data.numSimilarOrders} secondary={"Public orders for " + this.props.data.currencyCode}/>
</ListItem>
<Divider/>

View File

@ -115,6 +115,7 @@ npm install @mui/material
npm install react-markdown
npm install websocket
npm install react-countdown
npm install @mui/icons-material
```
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)