From 5ab97453f04826be12be71173f736a744fe06308 Mon Sep 17 00:00:00 2001 From: Reckless_Satoshi Date: Sat, 29 Jan 2022 11:51:26 -0800 Subject: [PATCH] Add user profile bottom left icon with active order reminder --- api/logics.py | 13 +-- api/views.py | 12 +- frontend/src/components/App.js | 11 +- frontend/src/components/BottomBar.js | 148 +++++++++++++++++++------ frontend/src/components/HomePage.js | 3 +- frontend/src/components/InfoDialog.js | 6 +- frontend/src/components/MakerPage.js | 1 - frontend/src/components/UserGenPage.js | 11 +- frontend/static/css/index.css | 17 +++ 9 files changed, 166 insertions(+), 56 deletions(-) diff --git a/api/logics.py b/api/logics.py index 4818d908..291cb572 100644 --- a/api/logics.py +++ b/api/logics.py @@ -40,12 +40,12 @@ class Logics(): '''Checks if the user is already partipant of an active order''' queryset = Order.objects.filter(maker=user, status__in=active_order_status) if queryset.exists(): - return False, {'bad_request':'You are already maker of an active order'} + return False, {'bad_request':'You are already maker of an active order'}, queryset[0] queryset = Order.objects.filter(taker=user, status__in=active_order_status) if queryset.exists(): - return False, {'bad_request':'You are already taker of an active order'} - return True, None + return False, {'bad_request':'You are already taker of an active order'}, queryset[0] + return True, None, None def validate_order_size(order): '''Validates if order is withing limits in satoshis at t0''' @@ -769,13 +769,12 @@ class Logics(): # Double check the escrow is settled. if LNNode.double_check_htlc_is_settled(order.trade_escrow.payment_hash): + # RETURN THE BONDS // Probably best also do it even if payment failed + cls.return_bond(order.taker_bond) + cls.return_bond(order.maker_bond) is_payed, context = follow_send_payment(order.payout) ##### !!! KEY LINE - PAYS THE BUYER INVOICE !!! if is_payed: - # RETURN THE BONDS // Probably best also do it even if payment failed - cls.return_bond(order.taker_bond) - cls.return_bond(order.maker_bond) order.save() - return True, context else: # error handling here diff --git a/api/views.py b/api/views.py index 33a669b8..21b7b9b8 100644 --- a/api/views.py +++ b/api/views.py @@ -49,7 +49,7 @@ class MakerView(CreateAPIView): satoshis = serializer.data.get('satoshis') is_explicit = serializer.data.get('is_explicit') - valid, context = Logics.validate_already_maker_or_taker(request.user) + valid, context, _ = Logics.validate_already_maker_or_taker(request.user) if not valid: return Response(context, status.HTTP_409_CONFLICT) # Creates a new order @@ -270,7 +270,7 @@ class OrderView(viewsets.ViewSet): # 1) If action is take, it is a taker request! if action == 'take': if order.status == Order.Status.PUB: - valid, context = Logics.validate_already_maker_or_taker(request.user) + valid, context, _ = Logics.validate_already_maker_or_taker(request.user) if not valid: return Response(context, status=status.HTTP_409_CONFLICT) valid, context = Logics.take(order, request.user) if not valid: return Response(context, status=status.HTTP_403_FORBIDDEN) @@ -345,7 +345,7 @@ class UserView(APIView): # If an existing user opens the main page by mistake, we do not want it to create a new nickname/profile for him if request.user.is_authenticated: context = {'nickname': request.user.username} - not_participant, _ = Logics.validate_already_maker_or_taker(request.user) + not_participant, _, _ = Logics.validate_already_maker_or_taker(request.user) # Does not allow this 'mistake' if an active order if not not_participant: @@ -449,7 +449,6 @@ class BookView(ListAPIView): if len(queryset)== 0: return Response({'not_found':'No orders found, be the first to make one'}, status=status.HTTP_404_NOT_FOUND) - # queryset = queryset.order_by('created_at') book_data = [] for order in queryset: data = ListOrderSerializer(order).data @@ -509,6 +508,11 @@ class InfoView(ListAPIView): context['robosats_running_commit_hash'] = get_commit_robosats() context['fee'] = FEE context['bond_size'] = float(config('BOND_SIZE')) + if request.user.is_authenticated: + context['nickname'] = request.user.username + has_no_active_order, _, order = Logics.validate_already_maker_or_taker(request.user) + if not has_no_active_order: + context['active_order_id'] = order.id return Response(context, status.HTTP_200_OK) diff --git a/frontend/src/components/App.js b/frontend/src/components/App.js index 6cf5659a..b07b8b20 100644 --- a/frontend/src/components/App.js +++ b/frontend/src/components/App.js @@ -7,16 +7,23 @@ import BottomBar from "./BottomBar"; export default class App extends Component { constructor(props) { super(props); + this.state = { + nickname: null, + } + } + + setAppState=(newState)=>{ + this.setState(newState) } render() { return ( <>
- +
- +
); diff --git a/frontend/src/components/BottomBar.js b/frontend/src/components/BottomBar.js index e33aacd2..5dbbce8a 100644 --- a/frontend/src/components/BottomBar.js +++ b/frontend/src/components/BottomBar.js @@ -1,5 +1,5 @@ import React, { Component } from 'react' -import {Badge, Paper, Grid, IconButton, Typography, Select, MenuItem, List, ListItemText, ListItem, ListItemIcon, ListItemButton, Divider, Dialog, DialogContent} from "@mui/material"; +import {Badge, ListItemAvatar, Avatar,Paper, Grid, IconButton, Typography, Select, MenuItem, List, ListItemText, ListItem, ListItemIcon, ListItemButton, Divider, Dialog, DialogContent} from "@mui/material"; import MediaQuery from 'react-responsive' // Icons @@ -15,6 +15,7 @@ import GitHubIcon from '@mui/icons-material/GitHub'; import EqualizerIcon from '@mui/icons-material/Equalizer'; import SendIcon from '@mui/icons-material/Send'; import PublicIcon from '@mui/icons-material/Public'; +import NumbersIcon from '@mui/icons-material/Numbers'; // pretty numbers function pn(x) { @@ -36,10 +37,12 @@ export default class BottomBar extends Component { today_total_volume: 0, lifetime_satoshis_settled: 0, robosats_running_commit_hash: '000000000000000', + openProfile: false, + profileShown: false, }; this.getInfo(); } - + handleClickSuppport = () => { window.open("https://t.me/robosats"); }; @@ -48,7 +51,8 @@ export default class BottomBar extends Component { this.setState(null) fetch('/api/info/') .then((response) => response.json()) - .then((data) => this.setState(data)); + .then((data) => this.setState(data) & + this.props.setAppState({nickname:data.nickname})); } handleClickOpenStatsForNerds = () => { @@ -166,20 +170,82 @@ export default class BottomBar extends Component { ) } + handleClickOpenProfile = () => { + this.getInfo(); + this.setState({openProfile: true, profileShown: true}); + }; + handleClickCloseProfile = () => { + this.setState({openProfile: false}); + }; + + dialogProfile =() =>{ + return( + + + Your Profile + + + + + + {this.props.nickname ? "⚡"+this.props.nickname+"⚡" : ""} + + + + + + + + {this.state.active_order_id ? + // TODO Link to router and do this.props.history.push + + + + + + + : + + + + + } + + + + + ) + } bottomBarDesktop =()=>{ return( + - - - - + + + + 0 & !this.state.profileShown) ? "1": null} color="primary"> + + + + + @@ -234,7 +300,7 @@ bottomBarDesktop =()=>{ - + @@ -243,12 +309,12 @@ bottomBarDesktop =()=>{ primaryTypographyProps={{fontSize: '14px'}} secondaryTypographyProps={{fontSize: '12px'}} primary={this.state.fee*100} - secondary="Trading Fee" /> + secondary="Trade Fee" /> - + - - + + + + + + @@ -275,13 +347,14 @@ bottomBarDesktop =()=>{ } handleClickOpenExchangeSummary = () => { + this.getInfo(); this.setState({openExchangeSummary: true}); }; handleClickCloseExchangeSummary = () => { this.setState({openExchangeSummary: false}); }; - phoneExchangeSummaryDialog =() =>{ + exchangeSummaryDialogPhone =() =>{ return( { ) } - bottomBarPhone =()=>{ return( - + + - - - - + + + 0 & !this.state.profileShown) ? "1": null} color="primary"> + + + - + @@ -382,7 +458,7 @@ bottomBarPhone =()=>{ - + @@ -390,7 +466,7 @@ bottomBarPhone =()=>{ - + @@ -398,7 +474,7 @@ bottomBarPhone =()=>{ - + @@ -406,8 +482,8 @@ bottomBarPhone =()=>{ - - + + - - + + + + + + diff --git a/frontend/src/components/HomePage.js b/frontend/src/components/HomePage.js index 011fa492..2d61c892 100644 --- a/frontend/src/components/HomePage.js +++ b/frontend/src/components/HomePage.js @@ -14,8 +14,7 @@ export default class HomePage extends Component { return ( - -

You are at the start page

+ }/> diff --git a/frontend/src/components/InfoDialog.js b/frontend/src/components/InfoDialog.js index 5bda1a98..eca99f13 100644 --- a/frontend/src/components/InfoDialog.js +++ b/frontend/src/components/InfoDialog.js @@ -27,10 +27,10 @@ export default class InfoDialog extends Component { received the fiat, then the satoshis are released to Bob. Enjoy your satoshis, Bob!

-

At no point, AdequateAlice01 and BafflingBob02 have to trust the - bitcoin to each other. In case they have a conflict, RoboSats staff +

At no point, AnonymousAlice01 and BafflingBob02 have to trust the + bitcoin funds to each other. In case they have a conflict, RoboSats staff will help resolving the dispute. You can find a step-by-step - description of the trade pipeline in 'How it works'

+ description of the trade pipeline in How it works

What payment methods are accepted? diff --git a/frontend/src/components/MakerPage.js b/frontend/src/components/MakerPage.js index a4f482ca..5d066770 100644 --- a/frontend/src/components/MakerPage.js +++ b/frontend/src/components/MakerPage.js @@ -1,7 +1,6 @@ import React, { Component } from 'react'; import { Paper, Button , Grid, Typography, TextField, Select, FormHelperText, MenuItem, FormControl, Radio, FormControlLabel, RadioGroup} from "@mui/material" import { Link } from 'react-router-dom' - import getFlags from './getFlags' function getCookie(name) { diff --git a/frontend/src/components/UserGenPage.js b/frontend/src/components/UserGenPage.js index 57ce671e..b5f58781 100644 --- a/frontend/src/components/UserGenPage.js +++ b/frontend/src/components/UserGenPage.js @@ -45,7 +45,7 @@ export default class UserGenPage extends Component { .substring(0, length); } - getGeneratedUser(token) { + getGeneratedUser=(token)=>{ fetch('/api/user' + '?token=' + token) .then((response) => response.json()) .then((data) => { @@ -57,7 +57,11 @@ export default class UserGenPage extends Component { bad_request: data.bad_request, found: data.found, showRobosat:true, - }); + }) + & + this.props.setAppState({ + nickname: data.nickname, + }); }); } @@ -112,11 +116,10 @@ export default class UserGenPage extends Component { ) } - render() { return ( - + {this.state.showRobosat ?
diff --git a/frontend/static/css/index.css b/frontend/static/css/index.css index 096f9b29..81e52a49 100644 --- a/frontend/static/css/index.css +++ b/frontend/static/css/index.css @@ -37,6 +37,11 @@ body { top: -14px; } +.profileNickname { + margin: 0; + left: -22px; +} + .newAvatar { background-color:white; border-radius: 50%; @@ -44,4 +49,16 @@ body { filter: drop-shadow(1px 1px 1px #000000); height: 200px; width: 200px; +} + +.avatar { + border: 0.5px solid #555; + filter: drop-shadow(0.5px 0.5px 0.5px #000000); + left: 35px; +} + +.rotatedAvatar { + transform: scaleX(-1); + border: 0.5px solid #555; + filter: drop-shadow(0.5px 0.5px 0.5px #000000); } \ No newline at end of file