Browse Source

dex coin icons, swap history, prices, coin list

v0.25
pbca26 7 years ago
parent
commit
3f0c437996
  1. 1
      react/package.json
  2. 30
      react/src/actions/actions/mm.js
  3. 3
      react/src/actions/storeType.js
  4. 1
      react/src/assets/dex/coins/kmd.svg
  5. 10
      react/src/assets/dex/coins/mnz.svg
  6. BIN
      react/src/assets/images/cryptologo/blk.png
  7. BIN
      react/src/assets/images/cryptologo/block.png
  8. BIN
      react/src/assets/images/cryptologo/bsd.png
  9. BIN
      react/src/assets/images/cryptologo/btcz.png
  10. BIN
      react/src/assets/images/cryptologo/chips (copy).png
  11. BIN
      react/src/assets/images/cryptologo/chips.png
  12. BIN
      react/src/assets/images/cryptologo/hodlc.png
  13. BIN
      react/src/assets/images/cryptologo/iop.png
  14. BIN
      react/src/assets/images/cryptologo/maga.png
  15. BIN
      react/src/assets/images/cryptologo/mshark.png
  16. BIN
      react/src/assets/images/cryptologo/zen.png
  17. 3
      react/src/components/dashboard/navbar/navbar.render.js
  18. 338
      react/src/components/dex/dexCoins.js
  19. 4
      react/src/components/dex/dexLogin.js
  20. 32
      react/src/components/dex/dexMain.js
  21. 79
      react/src/components/dex/dexSwapHistory.js
  22. 25
      react/src/components/dex/svg/arrowRight.js
  23. 19
      react/src/components/dex/svg/mnz.js
  24. 216
      react/src/components/dex/table/dexSwapsTable.js
  25. 50
      react/src/components/dex/table/pagination.js
  26. 103
      react/src/components/dex/table/pagination.render.js
  27. 92
      react/src/components/dex/table/table.scss
  28. 38
      react/src/components/main/walletMain.js
  29. 18
      react/src/reducers/dex.js
  30. 52
      react/src/styles/dex/_base.scss
  31. 2
      react/src/styles/dex/_helpers.scss
  32. 2
      react/src/styles/dex/components/coinList.scss

1
react/package.json

@ -41,7 +41,6 @@
"qrcode.react": "^0.7.1",
"rc-tree": "^1.4.6",
"react": "^15.3.1",
"react-cryptocoins": "^1.0.10",
"react-dom": "^15.3.1",
"react-hot-loader": "^1.3.0",
"react-qr-reader": "^1.1.3",

30
react/src/actions/actions/mm.js

@ -10,6 +10,8 @@ import {
DEX_UTXO,
DEX_CACHE_PRELOAD,
DEX_PRICES,
DEX_STATS,
DEX_ACTIVE_SECTION,
} from '../storeType';
import { translate } from '../../translate/translate';
import Config from '../../config';
@ -18,7 +20,7 @@ import {
} from '../actionCreators';
import Store from '../../store';
export function shepherdMMCachePreloadState(isAuth, asks, bids, pair, coins, swaps, rates) {
export function shepherdMMCachePreloadState(isAuth, asks, bids, pair, coins, swaps, rates, coinsHelper, electrumServersList) {
return {
type: DEX_CACHE_PRELOAD,
isAuth,
@ -28,6 +30,8 @@ export function shepherdMMCachePreloadState(isAuth, asks, bids, pair, coins, swa
coins,
swaps,
rates,
coinsHelper,
electrumServersList,
}
}
@ -88,7 +92,6 @@ export function shepherdMMStop() {
}
export function shepherdMMRequest(payload) {
console.warn(payload);
return dispatch => {
return fetch(
`http://127.0.0.1:${Config.agamaPort}/shepherd/mm/request`, {
@ -101,7 +104,7 @@ export function shepherdMMRequest(payload) {
)
.catch((error) => {
console.log(error);
Store.dispatch(
dispatch(
triggerToaster(
'shepherdMMRequest',
'Error',
@ -111,21 +114,34 @@ export function shepherdMMRequest(payload) {
})
.then(response => response.json())
.then(json => {
dispatch(shepherdMMRequstState(payload.mapToProp, json));
console.warn(json);
dispatch(shepherdMMRequestState(payload.mapToProp, json));
});
}
}
export function shepherdMMRequstState(prop, json) {
export function shepherdMMRequestState(prop, json) {
if (prop === 'prices') {
return {
type: DEX_PRICES,
prices: json,
}
} else if (prop === 'statsdisp') {
} else if (prop === 'stats') {
return {
type: DEX_STATS,
prices: json,
stats: json,
}
} else if (prop === 'swaps') {
return {
type: DEX_SWAPS,
swaps: json,
}
}
}
export function dexActiveSection(section) {
return {
type: DEX_ACTIVE_SECTION,
section,
}
}

3
react/src/actions/storeType.js

@ -61,4 +61,5 @@ export const DEX_UTXO = 'DEX_UTXO';
export const DEX_PRICES = 'DEX_PRICES';
export const DEX_RESET = 'DEX_RESET';
export const DEX_STATS = 'DEX_STATS';
export const DEX_CACHE_PRELOAD = 'DEX_CACHE_PRELOAD';
export const DEX_CACHE_PRELOAD = 'DEX_CACHE_PRELOAD';
export const DEX_ACTIVE_SECTION = 'DEX_ACTIVE_SECTION';

1
react/src/assets/dex/coins/kmd.svg

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 250 74.13" width="250" height="74"><defs><style>.kmd_subscribe_cls-1{fill:#567f7f;}.kmd_subscribe_cls-2{fill:#fbb73f;}.kmd_subscribe_cls-3{fill:#2f6363;}.kmd_subscribe_cls-4{fill:#f8a627;}.kmd_subscribe_cls-5{fill:#2f6365;}</style></defs><g id="_998408992" data-name=" 998408992"><path class="kmd_subscribe_cls-1" d="M10.29,61.84l1.89,1.89c8.3,3.47,16.58,7,24.89,10.41V59L21.55,52.58,15.12,37.07l6.43-15.52L10.29,12.29,0,37.07Z"/><path class="kmd_subscribe_cls-2" d="M37.07,0c-8.3,3.44-16.59,6.93-24.89,10.41l-1.89,1.89,11.26,9.25,15.52-6.43Z"/><polygon class="kmd_subscribe_cls-1" points="37.06 21.55 26.09 26.09 21.55 37.06 26.09 48.03 37.06 52.58 37.06 21.55"/><path class="kmd_subscribe_cls-3" d="M37.07,74.13c8.3-3.45,16.59-6.94,24.89-10.41l1.89-1.89L74.13,37.07,63.84,12.29,52.58,21.55,59,37.07,52.58,52.58,37.07,59Z"/><path class="kmd_subscribe_cls-4" d="M63.84,12.29,62,10.41C53.66,6.93,45.37,3.44,37.07,0V15.12l15.52,6.43Z"/><polygon class="kmd_subscribe_cls-3" points="37.06 52.58 48.04 48.03 52.58 37.06 48.04 26.09 37.06 21.55 37.06 52.58"/></g></svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

10
react/src/assets/dex/coins/mnz.svg

@ -1,10 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Calque_1" x="0px" y="0px" width="50px" height="50px" viewBox="0 0 50 50" style="enable-background:new 0 0 148 50;" xml:space="preserve">
<g>
<path class="st1" d="M15.9,17.9"/>
<path d="M39.9,34.5c-0.2-1.2-0.6-2.4-0.9-3.5c-0.3-1.2-0.6-2.4-0.9-3.6c-0.8-3-1.6-6-2.4-9c-0.2-0.7-0.3-1.4-0.5-2.1 c-0.1-0.3-0.2-0.7-0.5-0.9c-0.3-0.1-0.6-0.1-0.9-0.1c-0.4,0-0.8,0-1.2,0c-0.8,0-1.7,0-2.5,0c-0.6,0-1.1,0-1.7,0.1 c-0.5,0.1-1,0.4-1.2,0.9c-0.1,0.2,0,0.5,0.2,0.6c0.1,0.1,0.3,0,0.4-0.1c0.1,0,0.4-0.3,0.5-0.3l4.7,17.3l0,0c0,0,0,0.1,0,0.1 c0.1,0.4,0.3,0.8,0.6,0.9c0.2,0.1,0.4,0.2,0.7,0.2h0.5h0.8h2.4h1.3C39.6,35.1,40,34.9,39.9,34.5z"/>
<path d="M28.3,34.5c-0.2-1.2-0.6-2.4-0.9-3.5c-0.3-1.2-0.6-2.4-0.9-3.6c-0.8-3-1.6-6-2.4-9c-0.2-0.7-0.3-1.4-0.5-2.1 c-0.1-0.3-0.2-0.7-0.5-0.9c-0.3-0.1-0.6-0.1-0.9-0.1c-0.4,0-0.8,0-1.2,0c-0.8,0-1.7,0-2.5,0c-0.6,0-1.1,0-1.7,0.1 c-0.5,0.1-1,0.4-1.2,0.9c-0.1,0.2,0,0.5,0.2,0.6c0.1,0.1,0.3,0,0.4-0.1c0.1,0,0.4-0.3,0.5-0.3l4.7,17.3l0,0c0,0,0,0.1,0,0.1 c0.1,0.4,0.3,0.8,0.6,0.9c0.2,0.1,0.4,0.2,0.7,0.2h0.5h0.8h2.4h1.3C28,35.1,28.4,34.9,28.3,34.5z"/>
<path d="M19.1,30.7l-3.2-12.5h0c0-0.2-0.2-0.4-0.5-0.4c-0.2,0-0.4,0.2-0.5,0.4l0,0L10.7,34l0,0c0,0.1,0,0.2,0,0.2 c0,0.5,0.4,1,1,1H17c0.4,0,0.8-0.3,0.9-0.7l0,0L19.1,30.7z"/>
<path d="M30.9,30.4l-3.5-12.6h0c0-0.2-0.2-0.3-0.4-0.3c-0.2,0-0.4,0.1-0.4,0.3h0l-0.7,2.5l3.5,12.2l0,0l0,0 c0.1,0.2,0.2,0.3,0.4,0.3c0.2,0,0.3-0.1,0.4-0.3l0,0L30.9,30.4z"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

BIN
react/src/assets/images/cryptologo/blk.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
react/src/assets/images/cryptologo/block.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

BIN
react/src/assets/images/cryptologo/bsd.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
react/src/assets/images/cryptologo/btcz.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
react/src/assets/images/cryptologo/chips (copy).png

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

BIN
react/src/assets/images/cryptologo/chips.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.2 KiB

After

Width:  |  Height:  |  Size: 8.8 KiB

BIN
react/src/assets/images/cryptologo/hodlc.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

BIN
react/src/assets/images/cryptologo/iop.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
react/src/assets/images/cryptologo/maga.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

BIN
react/src/assets/images/cryptologo/mshark.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

BIN
react/src/assets/images/cryptologo/zen.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

3
react/src/components/dashboard/navbar/navbar.render.js

@ -1,5 +1,6 @@
import React from 'react';
import { translate } from '../../../translate/translate';
import mainWindow from '../../../util/mainWindow';
const NavbarRender = function() {
return (
@ -52,7 +53,7 @@ const NavbarRender = function() {
<i className="site-menu-icon"></i> { translate('INDEX.WALLETS') }
</a>
</li>
<li className={ this.isSectionActive('dex') ? 'hide active nav-top-menu' : 'hide nav-top-menu' }>
<li className={ (this.isSectionActive('dex') ? 'active nav-top-menu' : 'nav-top-menu') + (mainWindow.argv.indexOf('dexonly') > -1 ? '' : ' hide') }>
<a onClick={ () => this.dashboardChangeSection('dex') }>
<i className="site-menu-icon"></i> BarterDEX
</a>

338
react/src/components/dex/dexCoins.js

@ -1,15 +1,17 @@
import React from 'react';
import { translate } from '../../translate/translate';
import SVGFaviconBlack from './svg/faviconBlack';
import SVGMNZ from './svg/mnz';
import DexLoaderSmall from './dexLoaderSmall';
import mainWindow from '../../util/mainWindow';
import * as coinIcon from 'react-cryptocoins';
import Store from '../../store';
import {
shepherdMMRequest,
dexActiveSection,
} from '../../actions/actionCreators';
import { connect } from 'react-redux';
import DexSwapHistory from './dexSwapHistory';
// TODO: extend price pairs to include all possible combinations
class DexCoins extends React.Component {
constructor() {
@ -20,13 +22,33 @@ class DexCoins extends React.Component {
btc: 0,
},
coinLoading: false,
prices: {},
renderAddCoin: false,
};
this.calcTotalBalance = this.calcTotalBalance.bind(this);
this.togglePrices = this.togglePrices.bind(this);
this.toggleSwaps = this.toggleSwaps.bind(this);
this.toggleAddCoin = this.toggleAddCoin.bind(this);
}
toggleAddCoin() {
this.setState({
renderAddCoin: !this.state.renderAddCoin,
});
}
togglePrices() {
Store.dispatch(dexActiveSection(this.props.Dex.section === 'prices' ? 'coins' : 'prices'));
}
toggleSwaps() {
Store.dispatch(dexActiveSection(this.props.Dex.section === 'swaps' ? 'coins' : 'swaps'));
}
getPrices(props) {
const _dex = props.Dex;
let _prices = {};
let _pairDiv = {};
if (_dex &&
_dex.prices &&
@ -34,61 +56,250 @@ class DexCoins extends React.Component {
for (let i = 0; i < _dex.prices.length; i++) {
for (let j = 0; j < _dex.prices[i].asks.length; j++) {
if (!_prices[_dex.prices[i].asks[j][0] + '/' + _dex.prices[i].asks[j][1]]) {
_pairDiv[_dex.prices[i].asks[j][0] + '/' + _dex.prices[i].asks[j][1]] = 1;
_prices[_dex.prices[i].asks[j][0] + '/' + _dex.prices[i].asks[j][1]] = _dex.prices[i].asks[j][2];
} else {
} else { // average
_pairDiv[_dex.prices[i].asks[j][0] + '/' + _dex.prices[i].asks[j][1]] += 1;
_prices[_dex.prices[i].asks[j][0] + '/' + _dex.prices[i].asks[j][1]] += _dex.prices[i].asks[j][2];
}
}
}
}
console.warn(_prices);
}
renderCoinsList() {
for (let key in _prices) {
_prices[key] = (_prices[key] / _pairDiv[key]).toFixed(8);
}
}
this.setState({
prices: _prices,
});
console.warn('prices', _prices);
}
calcTotalBalance() {
mainWindow.getMMCacheData()
.then((res) => {
const { rates, coins } = res;
let _coins = {};
renderBalanceTotal() {
if (this.props.Dex &&
this.props.Dex.coins &&
this.props.Dex.rates &&
this.state.prices) {
const coins = this.props.Dex.coins;
const prices = this.state.prices;
const rates = this.props.Dex.rates;
let _totalKMDValue = 0;
if (rates &&
rates.BTC &&
rates.USD) {
for (let i = 0; i < coins.length; i++) {
console.log(coins[i].coin + ' ' + coins[i].balance);
_coins[coins[i].coin] = coins[i];
if (Number(coins[i].balance) > 0) {
_totalKMDValue += Number(coins[i].KMDvalue);
for (let i = 0; i < coins.length; i++) {
// console.log(coins[i].coin + ' ' + coins[i].balance);
if (Number(coins[i].balance) > 0) {
console.warn(coins[i].balance, `${coins[i].coin}/KMD ${prices[`${coins[i].coin}/KMD`]}`);
if (coins[i].coin === 'KMD') {
_totalKMDValue += Number(coins[i].balance);
} else {
_totalKMDValue += Number(coins[i].balance) * prices[`${coins[i].coin}/KMD`];
}
}
console.log(_totalKMDValue);
}
});
}
getCoinSVG(coin) {
// todo add asset chains
if (coin !== 'MNZ') {
const SVGCryptoCoins = coinIcon.BtcAlt;
return <SVGCryptoCoins size={40} />;
return (
<h1 style={{ color: '#9e9e9e' }}>
<label>Estimated balance</label>
<span>{ (_totalKMDValue * rates.BTC).toFixed(8) } BTC</span>
<span>{ (_totalKMDValue).toFixed(8) } KMD</span>
<small className="margin-top-10 margin-bottom-25">${ (_totalKMDValue * rates.USD).toFixed(8) }</small>
</h1>
);
} else {
return SVGMNZ;
return null;
}
}
calcTotalBalance(rates, coins, prices) {
let _coins = {};
let _totalKMDValue = 0;
if (rates &&
rates.BTC &&
rates.USD) {
for (let i = 0; i < coins.length; i++) {
console.log(coins[i].coin + ' ' + coins[i].balance);
_coins[coins[i].coin] = coins[i];
if (Number(coins[i].balance) > 0) {
_totalKMDValue += Number(coins[i].KMDvalue);
}
}
console.log(_totalKMDValue);
}
}
componentWillMount() {
this.calcTotalBalance();
// this.calcTotalBalance();
}
componentWillReceiveProps(props) {
this.getPrices(props);
}
renderCoins() {
const _coins = this.props.Dex.coins;
const _coinsHelper = this.props.Dex.coinsHelper;
let _items = [];
if (this.state.renderAddCoin) {
_items.push(
<li
onClick={ this.toggleAddCoin }
key="coinList-coin add-new-coin"
className="coinList-coin add-new-coin">
<span
style={{ position: 'relative', transform: 'rotate(180deg)' }}
className="coinList-coin_action">
<svg id="Layer_1" style={{ enableBackground: 'new 0 0 512 512' }} version="1.1" viewBox="0 0 512 512">
<polygon points="160,115.4 180.7,96 352,256 180.7,416 160,396.7 310.5,256 "></polygon>
</svg>
</span>
<a>
<div className="coinList-coin_icon coin-colorized">
<i className="crypto-icons-pack">
</i>
</div>
<div className="coinList-coin_balance">
<strong>Back</strong>
</div>
</a>
</li>
);
}
for (let i = 0; i < _coins.length; i++) {
const _coinName = _coinsHelper[_coins[i].coin].name ? _coinsHelper[_coins[i].coin].name : (_coinsHelper[_coins[i].coin].asset ? _coinsHelper[_coins[i].coin].asset : _coinsHelper[_coins[i].coin].coin);
if ((!this.state.renderAddCoin && _coins[i].status === 'active') ||
(this.state.renderAddCoin && _coins[i].status === 'inactive')) {
_items.push(
<li
key={ `coinList-coin ${_coins[i].coin}` }
className={ `coinList-coin ${_coins[i].coin}` }>
<a className={ _coins[i].coin }>
<div className="coinList-coin_icon coin-colorized">
<i className={ `coin-icon-svg crypto-icons-pack ${_coins[i].coin}` }>
<img src={ `/assets/images/cryptologo/${_coins[i].coin.toLowerCase()}.png` } />
</i>
</div>
<div className={ `coinList-coin_balance ${_coins[i].coin}` }>
<strong className="coinList-coin_balance-name">{ _coinName.indexOf('coin') > -1 && _coinName.indexOf('itcoin') === -1 ? _coinName.replace('coin', 'Coin') : _coinName }</strong>
<strong className="coinList-coin_balance-amount">
{ _coins[i].balance } { _coins[i].coin }
</strong>
<small>{ _coins[i].electrum ? 'Electrum mode' : 'Native mode' }</small>
</div>
<span className="coinList-coin_action">
<svg id="Layer_1" style={{ enableBackground: 'new 0 0 512 512' }} version="1.1" viewBox="0 0 512 512">
<polygon points="160,115.4 180.7,96 352,256 180.7,416 160,396.7 310.5,256 "></polygon>
</svg>
</span>
{ this.state.coinLoading &&
<DexLoaderSmall />
}
</a>
</li>
);
}
}
if (!this.state.renderAddCoin) {
_items.push(
<li
onClick={ this.toggleAddCoin }
key="coinList-coin add-new-coin"
className="coinList-coin add-new-coin">
<a>
<div className="coinList-coin_icon coin-colorized">
<i className="crypto-icons-pack">
</i>
</div>
<div className="coinList-coin_balance">
<strong>Add new coin</strong>
</div>
<span className="coinList-coin_action">
<svg id="Layer_1" style={{ enableBackground: 'new 0 0 512 512' }} version="1.1" viewBox="0 0 512 512">
<polygon points="160,115.4 180.7,96 352,256 180.7,416 160,396.7 310.5,256 "></polygon>
</svg>
</span>
</a>
</li>
);
}
return _items;
}
renderPrices() {
let _prices = this.state.prices;
let _items = [];
_prices['KMD/USD'] = this.props.Dex.rates.USD;
_prices['BTC/USD'] = this.props.Dex.rates.USD * _prices['BTC/KMD'];
for (let i = 0; i < 2; i++) {
for (let key in _prices) {
const _pair = key.split('/');
if ((i === 1 && key !== 'KMD/USD' && key !== 'BTC/USD') || (i === 0 && (key === 'KMD/USD' || key === 'BTC/USD'))) {
_items.push(
<li
key={ `prices-${key}` }
className="orders-item">
<div className="orders-item-wrapper">
<div className="orders-item-details">
<div className="orders-item-details-coins">
<section className="orders-item-details-coin">
<span className="orders-item-details-coin-amount">
{ _pair[0] }
</span>
<div className="orders-item-details-coin-icon coin-colorized">
<i className="coin-icon-svg">
<img src={ `/assets/images/cryptologo/${_pair[0].toLowerCase()}.png` } />
</i>
</div>
</section>
<div className="orders-item-details-type">
<i className="orders-item-details-coins-tradeType">
<svg fill="#A8A8A8" viewBox="0 0 24 24">
<path d="M6.99 11L3 15l3.99 4v-3H14v-2H6.99v-3zM21 9l-3.99-4v3H10v2h7.01v3L21 9z"/>
<path d="M0 0h24v24H0z" fill="none"/>
</svg>
</i>
</div>
<section className="orders-item-details-coin">
<div className="orders-item-details-coin-icon coin-colorized">
<i className="coin-icon-svg">
<img src={ `/assets/images/cryptologo/${_pair[1].toLowerCase()}.png` } />
</i>
</div>
<span className="orders-item-details-coin-amount">
{ _pair[1] }
</span>
</section>
<section className="orders-item-details-price">
<span className="orders-item-details-type-label">{ _prices[key] } { _pair[1] }</span>
</section>
</div>
</div>
</div>
</li>
);
}
}
}
return (
<section className="balance-action">
<ul className="orders-list singleColumn noHover prices">
{ _items }
</ul>
</section>
);
}
render() {
return (
<section className="dashboard">
@ -100,12 +311,10 @@ class DexCoins extends React.Component {
<div className="recharts-responsive-container dashboard-balances-pie" style={{ width: '250px', height: '450px' }}>
{ /* portfolio chart here */ }
</div>
<h1 style={{ color: '#9e9e9e' }}>
<label>Estimated balance</label>
<span>0.00345625 BTC</span>
<small className="margin-top-10">$32.21</small>
</h1>
<button className="action dark margin-top-15">
{ this.renderBalanceTotal() }
<button
className="action dark margin-top-15"
onClick={ this.toggleSwaps }>
<span>swap history</span>
<i>
<svg id="Layer_1" style={{ enableBackground: 'new 0 0 30 30' }} version="1.1" viewBox="0 0 30 30">
@ -114,33 +323,36 @@ class DexCoins extends React.Component {
</svg>
</i>
</button>
<button
className="action dark margin-top-15"
onClick={ this.togglePrices }>
<span>prices</span>
<i>
<svg id="Layer_1" style={{ enableBackground: 'new 0 0 30 30' }} version="1.1" viewBox="0 0 30 30">
<path d="M26,26h-4V13c0-0.552,0.448-1,1-1h2c0.552,0,1,0.448,1,1V26z"/>
<path d="M20,26h-4v-9c0-0.552,0.448-1,1-1h2c0.552,0,1,0.448,1,1V26z"/>
<path d="M14,26h-4V15c0-0.552,0.448-1,1-1h2c0.552,0,1,0.448,1,1V26z"/>
<path d="M8,26H4v-7c0-0.552,0.448-1,1-1h2c0.552,0,1,0.448,1,1V26z"/>
<circle cx="24" cy="6" r="2"/>
<circle cx="18" cy="11" r="2"/>
<circle cx="12" cy="8" r="2"/>
<circle cx="6" cy="12" r="2"/>
<polyline points=" 6,12 12,8 18,11 24,6 " style={{ fill: 'none', stroke: '#000000', strokeWidth: '2', strokeLinecap: 'round', strokeLinejoin: 'round', strokeMiterlimit: '10' }}/>
</svg>
</i>
</button>
</header>
<ul className="dashboard-wallets-list">
<li className="coinList-coin BTC">
<a className="BTC">
<div className="coinList-coin_icon coin-colorized">
<i className="coin-icon-svg crypto-icons-pack BTC">
{ this.getCoinSVG() }
</i>
</div>
<div className="coinList-coin_balance MNZ">
<strong className="coinList-coin_balance-name">Monaize</strong>
<strong className="coinList-coin_balance-amount">
20.35808051 MNZ
</strong>
<small>Electrum mode</small>
</div>
<span className="coinList-coin_action">
<svg id="Layer_1" style={{ enableBackground: 'new 0 0 512 512' }} version="1.1" viewBox="0 0 512 512">
<polygon points="160,115.4 180.7,96 352,256 180.7,416 160,396.7 310.5,256 "></polygon>
</svg>
</span>
{ this.state.coinLoading &&
<DexLoaderSmall />
}
</a>
</li>
</ul>
{ this.props.Dex.section === 'coins' &&
<ul className="dashboard-wallets-list">
{ this.renderCoins() }
</ul>
}
{ this.props.Dex.section === 'prices' &&
<div>{ this.renderPrices() }</div>
}
{ this.props.Dex.section === 'swaps' &&
<DexSwapHistory />
}
</section>
</section>
);

4
react/src/components/dex/dexLogin.js

@ -36,8 +36,8 @@ class DexLogin extends React.Component {
.then((res) => {
console.warn('mm cache', res);
const { rates, coins, isAuth } = res;
Store.dispatch(shepherdMMCachePreloadState(isAuth, null, null, null, coins, null, rates));
const { rates, coins, isAuth, swaps, asks, bids, pair, coinsHelper, electrumServersList } = res;
Store.dispatch(shepherdMMCachePreloadState(isAuth, asks, bids, pair, coins, swaps, rates, coinsHelper, electrumServersList));
});
});
}

32
react/src/components/dex/dexMain.js

@ -30,12 +30,27 @@ class DexMain extends React.Component {
}
componentWillMount() {
if (mainWindow.argv.indexOf('dexonly') > -1) {
Store.dispatch(shepherdMMRequest({
method: 'statsdisp',
mapToProp: 'stats',
}));
Store.dispatch(shepherdMMRequest({
method: 'getprices',
mapToProp: 'prices',
}));
Store.dispatch(shepherdMMRequest({
method: 'swapstatus',
mapToProp: 'swaps',
}));
}
mainWindow.getMMCacheData()
.then((res) => {
console.warn('mm cache', res);
const { rates, coins, isAuth, swaps, asks, bids, pair } = res;
Store.dispatch(shepherdMMCachePreloadState(isAuth, asks, bids, pair, coins, swaps, rates));
const { rates, coins, isAuth, swaps, asks, bids, pair, coinsHelper, electrumServersList } = res;
Store.dispatch(shepherdMMCachePreloadState(isAuth, asks, bids, pair, coins, swaps, rates, coinsHelper, electrumServersList));
});
}
@ -53,13 +68,17 @@ class DexMain extends React.Component {
method: 'getprices',
mapToProp: 'prices',
}));
Store.dispatch(shepherdMMRequest({
method: 'swapstatus',
mapToProp: 'swaps',
}));
mainWindow.getMMCacheData()
.then((res) => {
console.warn('mm cache', res);
const { rates, coins, isAuth, swaps, asks, bids, pair } = res;
Store.dispatch(shepherdMMCachePreloadState(isAuth, asks, bids, pair, coins, swaps, rates));
const { rates, coins, isAuth, swaps, asks, bids, pair, coinsHelper, electrumServersList } = res;
Store.dispatch(shepherdMMCachePreloadState(isAuth, asks, bids, pair, coins, swaps, rates, coinsHelper, electrumServersList));
});
} else {
console.warn('dex');
@ -87,8 +106,9 @@ class DexMain extends React.Component {
}
render() {
if (this.props.Dashboard &&
this.props.Dashboard.activeSection === 'dex') {
if ((this.props.Dashboard &&
this.props.Dashboard.activeSection === 'dex') ||
mainWindow.argv.indexOf('dexonly') > -1) {
return (
<div className="dex">
<content className="app content-container">

79
react/src/components/dex/dexSwapHistory.js

@ -1,5 +1,7 @@
import React from 'react';
import { connect } from 'react-redux';
import { translate } from '../../translate/translate';
import DexSwapsTable from './table/dexSwapsTable';
class DexSwapHistory extends React.Component {
constructor() {
@ -8,9 +10,70 @@ class DexSwapHistory extends React.Component {
};
}
render() {
renderSwapHistory() {
const _swaps = this.props.Dex.swaps.swaps;
let _items = [];
for (let i = 0; i < _swaps.length; i++) {
_items.push(
<li className="orders-item">
<div className="orders-item-wrapper">
<div className="orders-item-details">
<div className="orders-item-details-coins">
<section className="orders-item-details-coin KMD">
<span className="orders-item-details-coin-amount">
0.00397501
</span>
<div className="orders-item-details-coin-icon coin-colorized">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 226.8 226.8" width="24" height="24" fill="currentColor">
<path d="M113.4 0C50.8 0 0 50.8 0 113.4s50.8 113.4 113.4 113.4S226.8 176 226.8 113.4 176 0 113.4 0zm54.991 164.274l-3.878 3.878c-17.035 7.13-34.055 14.299-51.113 21.374-17.058-7.074-34.078-14.243-51.113-21.374l-3.878-3.878-21.142-50.879 21.142-50.879 3.878-3.878c11.93-4.994 23.858-9.997 35.792-14.982l9.842-4.12 2.725-1.13 2.754-1.141 2.753 1.141 2.725 1.13 9.842 4.12c11.934 4.985 23.862 9.988 35.792 14.982l3.878 3.878 21.142 50.879-21.141 50.879z"></path>
<path d="M113.4 68.322L81.528 81.524l-13.202 31.871 13.202 31.872 31.872 13.202 31.871-13.202 13.202-31.872-13.202-31.871L113.4 68.322zm22.536 67.61l-22.537 9.336-22.536-9.336-9.335-22.536 9.335-22.536 22.536-9.336 22.537 9.336 9.335 22.536-9.335 22.536z"></path>
</svg>
</div>
</section>
<div className="orders-item-details-type">
<span className="orders-item-details-type-label">finished</span>
<i className="orders-item-details-coins-tradeType">
<svg id="Layer_1" style={{ enableBackground: 'new 0 0 512 512' }} version="1.1" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg">
<path d="M370.1,181.3H399v47.3l81-83.2L399,64v54h-28.9c-82.7,0-129.4,61.9-170.6,116.5c-37,49.1-69,95.4-120.6,95.4H32v63.3h46.9 c82.7,0,129.4-65.8,170.6-120.4C286.5,223.7,318.4,181.3,370.1,181.3z M153.2,217.5c3.5-4.6,7.1-9.3,10.7-14.1 c8.8-11.6,18-23.9,28-36.1c-29.6-27.9-65.3-48.5-113-48.5H32v63.3c0,0,13.3-0.6,46.9,0C111.4,182.8,131.8,196.2,153.2,217.5z M399,330.4h-28.9c-31.5,0-55.7-15.8-78.2-39.3c-2.2,3-4.5,6-6.8,9c-9.9,13.1-20.5,27.2-32.2,41.1c30.4,29.9,67.2,52.5,117.2,52.5 H399V448l81-81.4l-81-83.2V330.4z"></path>
</svg>
</i>
</div>
<section className="orders-item-details-coin MNZ">
<div className="orders-item-details-coin-icon coin-colorized">
<i className="coin-icon-svg MNZ">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" id="Calque_1" x="0px" y="0px" viewBox="0 0 50 50" style={{ enableBackground: 'new 0 0 148 50' }}>
<g>
<path className="st1" d="M15.9,17.9"></path>
<path d="M39.9,34.5c-0.2-1.2-0.6-2.4-0.9-3.5c-0.3-1.2-0.6-2.4-0.9-3.6c-0.8-3-1.6-6-2.4-9c-0.2-0.7-0.3-1.4-0.5-2.1 c-0.1-0.3-0.2-0.7-0.5-0.9c-0.3-0.1-0.6-0.1-0.9-0.1c-0.4,0-0.8,0-1.2,0c-0.8,0-1.7,0-2.5,0c-0.6,0-1.1,0-1.7,0.1 c-0.5,0.1-1,0.4-1.2,0.9c-0.1,0.2,0,0.5,0.2,0.6c0.1,0.1,0.3,0,0.4-0.1c0.1,0,0.4-0.3,0.5-0.3l4.7,17.3l0,0c0,0,0,0.1,0,0.1 c0.1,0.4,0.3,0.8,0.6,0.9c0.2,0.1,0.4,0.2,0.7,0.2h0.5h0.8h2.4h1.3C39.6,35.1,40,34.9,39.9,34.5z"></path>
<path d="M28.3,34.5c-0.2-1.2-0.6-2.4-0.9-3.5c-0.3-1.2-0.6-2.4-0.9-3.6c-0.8-3-1.6-6-2.4-9c-0.2-0.7-0.3-1.4-0.5-2.1 c-0.1-0.3-0.2-0.7-0.5-0.9c-0.3-0.1-0.6-0.1-0.9-0.1c-0.4,0-0.8,0-1.2,0c-0.8,0-1.7,0-2.5,0c-0.6,0-1.1,0-1.7,0.1 c-0.5,0.1-1,0.4-1.2,0.9c-0.1,0.2,0,0.5,0.2,0.6c0.1,0.1,0.3,0,0.4-0.1c0.1,0,0.4-0.3,0.5-0.3l4.7,17.3l0,0c0,0,0,0.1,0,0.1 c0.1,0.4,0.3,0.8,0.6,0.9c0.2,0.1,0.4,0.2,0.7,0.2h0.5h0.8h2.4h1.3C28,35.1,28.4,34.9,28.3,34.5z"></path>
<path d="M19.1,30.7l-3.2-12.5h0c0-0.2-0.2-0.4-0.5-0.4c-0.2,0-0.4,0.2-0.5,0.4l0,0L10.7,34l0,0c0,0.1,0,0.2,0,0.2 c0,0.5,0.4,1,1,1H17c0.4,0,0.8-0.3,0.9-0.7l0,0L19.1,30.7z"></path>
<path d="M30.9,30.4l-3.5-12.6h0c0-0.2-0.2-0.3-0.4-0.3c-0.2,0-0.4,0.1-0.4,0.3h0l-0.7,2.5l3.5,12.2l0,0l0,0 c0.1,0.2,0.2,0.3,0.4,0.3c0.2,0,0.3-0.1,0.4-0.3l0,0L30.9,30.4z"></path>
</g>
</svg>
</i>
</div>
<span className="orders-item-details-coin-amount">
0.03048882
</span>
</section>
</div>
</div>
</div>
</li>
);
}
return (
<section className="balance-action">
<ul className="orders-list singleColumn noHover">
{ _items }
</ul>
</section>
);
}
/*
<ul className="orders-list singleColumn noHover">
<li className="orders-item">
<div className="orders-item-wrapper">
@ -58,9 +121,21 @@ class DexSwapHistory extends React.Component {
</div>
</li>
</ul>
*/
render() {
return (
<section className="balance-action">
<DexSwapsTable />
</section>
);
}
}
export default DexSwapHistory;
const mapStateToProps = (state) => {
return {
Dex: state.Dex,
};
};
export default connect(mapStateToProps)(DexSwapHistory);

25
react/src/components/dex/svg/arrowRight.js

@ -0,0 +1,25 @@
import React from 'react';
class SVGArrowRight extends React.Component {
render() {
return (
<svg enableBackground="new 0 0 32 32" height="32px" id="Layer_1" version="1.1" viewBox="0 0 32 32" width="32px">
<g>
<polyline fill="none" points=" 649,137.999 675,137.999 675,155.999 661,155.999 " stroke="#FFFFFF" strokeLinecap="round" strokeLinejoin="round" strokeMiterlimit="10" strokeWidth="2"/>
<polyline fill="none" points=" 653,155.999 649,155.999 649,141.999 " stroke="#FFFFFF" strokeLinecap="round" strokeLinejoin="round" strokeMiterlimit="10" strokeWidth="2"/>
<polyline fill="none" points=" 661,156 653,162 653,156 " stroke="#FFFFFF" strokeLinecap="round" strokeLinejoin="round" strokeMiterlimit="10" strokeWidth="2"/>
</g>
<g>
<g>
<path d="M2.982,17h26.035c0.397,0,0.756-0.244,0.908-0.617c0.152-0.374,0.068-0.804-0.213-1.09l-11.789-12 c-0.384-0.391-1.005-0.391-1.389,0s-0.384,1.023,0,1.414L26.646,15H2.982C2.439,15,2,15.448,2,16S2.439,17,2.982,17z"/>
</g>
<g>
<path d="M17.228,29c0.251,0,0.503-0.098,0.695-0.293l7.86-8c0.384-0.391,0.384-1.023,0-1.414s-1.005-0.391-1.389,0l-7.86,8 c-0.384,0.391-0.384,1.023,0,1.414C16.725,28.902,16.977,29,17.228,29z"/>
</g>
</g>
</svg>
);
}
}
export default SVGArrowRight;

19
react/src/components/dex/svg/mnz.js

@ -1,19 +0,0 @@
import React from 'react';
class SVGMNZ extends React.Component {
render() {
return (
<svg version="1.1" id="Calque_1" x="0px" y="0px" viewBox="0 0 50 50" style={{ enableBackground: 'new 0 0 148 50' }}>
<g>
<path className="st1" d="M15.9,17.9"></path>
<path d="M39.9,34.5c-0.2-1.2-0.6-2.4-0.9-3.5c-0.3-1.2-0.6-2.4-0.9-3.6c-0.8-3-1.6-6-2.4-9c-0.2-0.7-0.3-1.4-0.5-2.1 c-0.1-0.3-0.2-0.7-0.5-0.9c-0.3-0.1-0.6-0.1-0.9-0.1c-0.4,0-0.8,0-1.2,0c-0.8,0-1.7,0-2.5,0c-0.6,0-1.1,0-1.7,0.1 c-0.5,0.1-1,0.4-1.2,0.9c-0.1,0.2,0,0.5,0.2,0.6c0.1,0.1,0.3,0,0.4-0.1c0.1,0,0.4-0.3,0.5-0.3l4.7,17.3l0,0c0,0,0,0.1,0,0.1 c0.1,0.4,0.3,0.8,0.6,0.9c0.2,0.1,0.4,0.2,0.7,0.2h0.5h0.8h2.4h1.3C39.6,35.1,40,34.9,39.9,34.5z"></path>
<path d="M28.3,34.5c-0.2-1.2-0.6-2.4-0.9-3.5c-0.3-1.2-0.6-2.4-0.9-3.6c-0.8-3-1.6-6-2.4-9c-0.2-0.7-0.3-1.4-0.5-2.1 c-0.1-0.3-0.2-0.7-0.5-0.9c-0.3-0.1-0.6-0.1-0.9-0.1c-0.4,0-0.8,0-1.2,0c-0.8,0-1.7,0-2.5,0c-0.6,0-1.1,0-1.7,0.1 c-0.5,0.1-1,0.4-1.2,0.9c-0.1,0.2,0,0.5,0.2,0.6c0.1,0.1,0.3,0,0.4-0.1c0.1,0,0.4-0.3,0.5-0.3l4.7,17.3l0,0c0,0,0,0.1,0,0.1 c0.1,0.4,0.3,0.8,0.6,0.9c0.2,0.1,0.4,0.2,0.7,0.2h0.5h0.8h2.4h1.3C28,35.1,28.4,34.9,28.3,34.5z"></path>
<path d="M19.1,30.7l-3.2-12.5h0c0-0.2-0.2-0.4-0.5-0.4c-0.2,0-0.4,0.2-0.5,0.4l0,0L10.7,34l0,0c0,0.1,0,0.2,0,0.2 c0,0.5,0.4,1,1,1H17c0.4,0,0.8-0.3,0.9-0.7l0,0L19.1,30.7z"></path>
<path d="M30.9,30.4l-3.5-12.6h0c0-0.2-0.2-0.3-0.4-0.3c-0.2,0-0.4,0.1-0.4,0.3h0l-0.7,2.5l3.5,12.2l0,0l0,0 c0.1,0.2,0.2,0.3,0.4,0.3c0.2,0,0.3-0.1,0.4-0.3l0,0L30.9,30.4z"></path>
</g>
</svg>
);
}
}
export default SVGMNZ;

216
react/src/components/dex/table/dexSwapsTable.js

@ -0,0 +1,216 @@
import React from 'react';
import ReactTable from 'react-table';
import TablePaginationRenderer from './pagination';
import { connect } from 'react-redux';
import { translate } from '../../../translate/translate';
import { sortByDate } from '../../../util/sort';
import { formatValue } from '../../../util/formatValue';
import Config from '../../../config';
import {
triggerToaster,
} from '../../../actions/actionCreators';
import Store from '../../../store';
import { secondsToString } from '../../../util/time';
const BOTTOM_BAR_DISPLAY_THRESHOLD = 15;
class DexSwapsTable extends React.Component {
constructor(props) {
super(props);
this.state = {
itemsList: [],
filteredItemsList: [],
itemsListColumns: this.generateItemsListColumns(),
defaultPageSize: 20,
pageSize: 20,
showPagination: true,
searchTerm: null,
loading: false,
};
}
// https://react-table.js.org/#/custom-sorting
tableSorting(a, b) { // ugly workaround, override default sort
if (Date.parse(a)) { // convert date to timestamp
a = Date.parse(a);
}
if (Date.parse(b)) {
b = Date.parse(b);
}
// force null and undefined to the bottom
a = (a === null || a === undefined) ? -Infinity : a;
b = (b === null || b === undefined) ? -Infinity : b;
// force any string values to lowercase
a = typeof a === 'string' ? a.toLowerCase() : a;
b = typeof b === 'string' ? b.toLowerCase() : b;
// Return either 1 or -1 to indicate a sort priority
if (a > b) {
return 1;
}
if (a < b) {
return -1;
}
// returning 0 or undefined will use any subsequent column sorting methods or the row index as a tiebreaker
return 0;
}
generateItemsListColumns(itemsCount) {
let columns = [];
let _col;
_col = [{
id: 'direction',
Header: translate('INDEX.DIRECTION'),
Footer: translate('INDEX.DIRECTION'),
className: 'colum--direction',
headerClassName: 'colum--direction',
footerClassName: 'colum--direction',
accessor: (item) => (item.iambob === 0) ? 'Buyer' : 'Seller',
},
{
id: 'pair',
Header: 'Pair',
Footer: 'Pair',
className: 'colum--pair',
headerClassName: 'colum--pair',
footerClassName: 'colum--pair',
accessor: (item) => (item.iambob === 0) ? `${item.alice}/${item.bob}` : `${item.bob}/${item.alice}`,
},
{
id: 'sent',
Header: 'Sent',
Footer: 'Sent',
className: 'colum--sent',
headerClassName: 'colum--sent',
footerClassName: 'colum--sent',
accessor: (item) => (item.iambob === 0) ? `${formatValue(parseFloat(item.values[3]) + parseFloat(item.values[6]))} ${item.alice}` : `${formatValue(parseFloat(item.values[0]) + parseFloat(item.bobtxfee))} ${item.bob}`,
},
{
id: 'received',
Header: 'Received',
Footer: 'Recevied',
className: 'colum--received',
headerClassName: 'colum--received',
footerClassName: 'colum--received',
accessor: (item) => (item.iambob === 0) ? `${formatValue(item.srcamount)} ${item.bob}` : `${formatValue(item.values[3])} ${item.alice}`,
},
{
id: 'rate',
Header: 'Rate',
Footer: 'Rate',
className: 'colum--rate',
headerClassName: 'colum--rate',
footerClassName: 'colum--rate',
accessor: (item) => (item.iambob === 0) ? `${formatValue(parseFloat(parseFloat(item.values[3]) + parseFloat(item.values[6])) / parseFloat(item.srcamount))} (${parseFloat(item.values[3]) + parseFloat(item.values[6])} ${item.alice} / ${item.srcamount} ${item.bob})`: `${formatValue(parseFloat(item.values[3]) / parseFloat(parseFloat(item.values[0]) + parseFloat(item.bobtxfee)))} (${formatValue(item.values[3])} ${item.bob} / ${formatValue(parseFloat(item.values[0]) + parseFloat(item.bobtxfee))} ${item.bob})`,
},
{
id: 'finishtime',
Header: translate('INDEX.TIME'),
Footer: translate('INDEX.TIME'),
accessor: (item) => secondsToString(item.finishtime),
}];
if (itemsCount <= BOTTOM_BAR_DISPLAY_THRESHOLD) {
delete _col[0].Footer;
delete _col[1].Footer;
delete _col[2].Footer;
delete _col[3].Footer;
}
columns.push(..._col);
return columns;
}
componentWillMount() {
const _swaps = this.props.Dex.swaps.swaps.filter(swap => swap.alice && swap.finishtime);
this.setState({
itemsList: _swaps,
filteredItemsList: this.filterData(_swaps, this.state.searchTerm),
showPagination: _swaps && _swaps.length >= this.state.defaultPageSize,
itemsListColumns: this.generateItemsListColumns(_swaps.length),
});
}
componentWillReceiveProps(props) {
console.warn('table will receive props');
this.setState({
itemsList: this.props.Dex.swaps.swaps,
filteredItemsList: this.filterData(this.props.Dex.swaps.swaps, this.state.searchTerm),
showPagination: this.props.Dex.swaps.swaps && this.props.Dex.swaps.swaps.length >= this.state.defaultPageSize,
itemsListColumns: this.generateItemsListColumns(this.props.Dex.swaps.swaps.length),
});
console.warn(this.state);
}
onPageSizeChange(pageSize, pageIndex) {
this.setState(Object.assign({}, this.state, {
pageSize: pageSize,
showPagination: this.state.itemsList && this.state.itemsList.length >= this.state.defaultPageSize,
}))
}
onSearchTermChange(newSearchTerm) {
this.setState(Object.assign({}, this.state, {
searchTerm: newSearchTerm,
filteredItemsList: this.filterData(this.state.itemsList, newSearchTerm),
}));
}
filterData(list, searchTerm) {
return list.filter(item => this.filterDataByProp(item, searchTerm));
}
filterDataByProp(item, term) {
if (!term) {
return true;
}
return this.contains(item.alice.toLowerCase(), term) ||
this.contains(item.bob.toLowerCase(), term) ||
this.contains(secondsToString(item.finishtime).toLowerCase(), term);
}
contains(value, property) {
return (value + '').indexOf(property) !== -1;
}
render() {
return (
<div className="dex-table">
<input
className="form-control"
onChange={ e => this.onSearchTermChange(e.target.value) }
placeholder={ translate('DASHBOARD.SEARCH') } />
<ReactTable
data={ this.state.filteredItemsList }
columns={ this.state.itemsListColumns }
minRows="0"
sortable={ true }
className="-striped -highlight"
PaginationComponent={ TablePaginationRenderer }
nextText={ translate('INDEX.NEXT_PAGE') }
previousText={ translate('INDEX.PREVIOUS_PAGE') }
showPaginationBottom={ this.state.showPagination }
pageSize={ this.state.pageSize }
defaultSortMethod={ this.tableSorting }
defaultSorted={[{ // default sort
id: 'finishtime',
desc: true,
}]}
onPageSizeChange={ (pageSize, pageIndex) => this.onPageSizeChange(pageSize, pageIndex) } />
</div>
);
}
}
const mapStateToProps = (state) => {
return {
Dex: state.Dex,
};
};
export default connect(mapStateToProps)(DexSwapsTable);

50
react/src/components/dex/table/pagination.js

@ -0,0 +1,50 @@
import React, { Component } from 'react';
import PaginationRender from './pagination.render';
export default class TablePaginationRenderer extends Component {
constructor(props) {
super();
this.state = {
page: props.page,
};
this.getSafePage = this.getSafePage.bind(this);
this.changePage = this.changePage.bind(this);
this.applyPage = this.applyPage.bind(this);
}
componentWillReceiveProps(nextProps) {
this.setState({
page: nextProps.page,
});
}
getSafePage(page) {
if (isNaN(page)) {
page = this.props.page;
}
return Math.min(Math.max(page, 0), this.props.pages - 1);
}
changePage(page) {
page = this.getSafePage(page);
this.setState({
page,
});
if (this.props.page !== page) {
this.props.onPageChange(page);
}
}
applyPage(e) {
const page = this.state.page;
e && e.preventDefault();
this.changePage(page === '' ? this.props.page : page);
}
render() {
return PaginationRender.call(this);
}
}

103
react/src/components/dex/table/pagination.render.js

@ -0,0 +1,103 @@
import React from 'react';
import classnames from 'classnames';
const defaultButton = props =>
<button
type="button"
className="-btn"
{...props}>
{props.children}
</button>
const PaginationRender = function() {
const {
// Computed
pages,
// Props
page,
showPageSizeOptions,
pageSizeOptions,
pageSize,
showPageJump,
canPrevious,
canNext,
onPageSizeChange,
className,
PreviousComponent = defaultButton,
NextComponent = defaultButton,
} = this.props;
return (
<div
className={classnames(className, '-pagination')}
style={this.props.paginationStyle}>
<div className="-previous">
<PreviousComponent
onClick={e => {
if (!canPrevious) return;
this.changePage(page - 1)
}}
disabled={!canPrevious}>
{this.props.previousText}
</PreviousComponent>
</div>
<div className="-center">
<span className="-pageInfo">
{this.props.pageText}{' '}
{showPageJump
?
<div className="-pageJump">
<input
type={this.state.page === '' ? 'text' : 'number'}
onChange={e => {
const val = e.target.value;
this.changePage(val - 1);
}}
value={this.state.page === '' ? '' : this.state.page + 1}
onBlur={this.applyPage}
onKeyPress={e => {
if (e.which === 13 || e.keyCode === 13) {
this.applyPage();
}
}} />
</div>
:
<span className="-currentPage">
{page + 1}
</span>}{' '}
{this.props.ofText}{' '}
<span className="-totalPages">{pages || 1}</span>
</span>
{ showPageSizeOptions &&
<span className="select-wrap -pageSizeOptions">
<select
onChange={e => onPageSizeChange(Number(e.target.value))}
value={pageSize}>
{ pageSizeOptions.map((option, i) => {
return (
<option
key={i}
value={option}>
{option} {this.props.rowsText}
</option>
);
})}
</select>
</span>
}
</div>
<div className="-next">
<NextComponent
onClick={e => {
if (!canNext) return;
this.changePage(page + 1);
}}
disabled={!canNext}>
{this.props.nextText}
</NextComponent>
</div>
</div>
)
};
export default PaginationRender;

92
react/src/components/dex/table/table.scss

@ -0,0 +1,92 @@
.search-box {
float: right;
padding-right: 0;
}
.basilisk-progress-bar {
position: absolute;
width: 100%;
}
.breadcrumb--basilisk,
.breadcrumb--native {
top: 0;
}
.dropdown-menu {
.no--hover {
pointer-events: none;
}
}
.ReactTable {
border: none;
.pagination-bottom {
margin-top: 35px;
}
.rt-td {
text-align: center;
}
.rt-table {
border: 1px solid rgba(0, 0, 0, 0.1);
}
.rt-thead .rt-th,
.rt-thead .rt-td {
padding: 10px 5px;
}
.rt-tr.-odd div,
.rt-tr.-even div {
padding-top: 10px;
padding-bottom: 10px;
}
.-pagination,
.rt-thead,
.rt-tfoot {
border: none;
}
.rt-tfoot {
border-top: 1px solid rgba(0, 0, 0, 0.1);
}
.rt-thead {
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
}
.colum--direction {
width: 40px !important;
flex: 40 0 auto !important;
padding-right: 10px;
}
.colum--txinfo {
width: 40px !important;
flex: 40 0 auto !important;
}
.colum--type {
width: 40px !important;
flex: 40 0 auto !important;
}
.-pagination {
.-pageJump {
margin-right: 5px;
margin-left: 5px;
}
.-btn {
color: #757575;
background-color: #efefef;
border: 1px solid #e0e0e0;
&:hover {
color: #fff;
}
}
.-btn[disabled]:hover {
color: #757575;
}
}
.rt-noData {
top: 46px;
width: 100%;
text-align: center;
height: 98px;
padding: 38px;
background: rgba(255, 255, 255, 0.85);
}
}
.table-cell-offset-16 {
padding-left: 16px;
}

38
react/src/components/main/walletMain.js

@ -5,24 +5,32 @@ import AddCoin from '../addcoin/addcoin';
import Login from '../login/login';
import Dashboard from '../dashboard/main/dashboard';
import DexMain from '../dex/dexMain';
import mainWindow from '../../util/mainWindow';
class WalletMain extends React.Component {
render() {
return (
<div className="full-height">
<input
type="text"
id="js-copytextarea" />
<Dashboard />
{ /*
<DexMain />
*/
}
<AddCoin />
<Login />
<Toaster {...this.props.toaster} />
</div>
);
if (mainWindow.argv.indexOf('dexonly') > -1) {
return (
<div className="full-height">
<input
type="text"
id="js-copytextarea" />
<DexMain />
</div>
);
} else {
return (
<div className="full-height">
<input
type="text"
id="js-copytextarea" />
<Dashboard />
<AddCoin />
<Login />
<Toaster {...this.props.toaster} />
</div>
);
}
}
}

18
react/src/reducers/dex.js

@ -13,6 +13,7 @@ import {
DEX_RESET,
DEX_PRICES,
DEX_STATS,
DEX_ACTIVE_SECTION,
} from '../actions/storeType';
export function Dex(state = {
@ -30,7 +31,10 @@ export function Dex(state = {
prices: {},
utxo: {},
inventory: {},
stats: {}
stats: {},
coinsHelper: {},
electrumServersList: {},
section: 'coins',
}, action) {
switch (action.type) {
case DEX_CACHE_PRELOAD:
@ -41,10 +45,14 @@ export function Dex(state = {
pair: action.pair,
coins: action.coins,
swaps: action.swaps,
stats: action.stats,
rates: action.rates,
prices: action.prices,
utxo: action.utxo,
inventory: action.inventory,
coinsHelper: action.coinsHelper,
electrumServersList: action.electrumServersList,
section: state.section,
};
case DEX_RESET:
return {
@ -62,6 +70,9 @@ export function Dex(state = {
prices: {},
utxo: {},
inventory: {},
coinsHelper: {},
electrumServersList: {},
section: state.section,
};
case DEX_LOGIN:
return {
@ -111,6 +122,11 @@ export function Dex(state = {
...state,
stats: action.stats,
};
case DEX_ACTIVE_SECTION:
return {
...state,
section: action.section,
};
default:
return state;
}

52
react/src/styles/dex/_base.scss

@ -109,19 +109,53 @@
text-decoration: underline;
}
.crypto-icons-pack {
svg {
position: relative;
top: 9px;
left: 10px;
}
}
.dashboard-wallets-list {
.coinList-coin {
width: 32%;
width: calc(33% - 20px);
float: left;
margin-right: 20px;
margin-bottom: 40px;
img {
position: relative;
top: 4px;
left: 5px;
max-height: 58px;
max-width: 50px;
opacity: 0.9;
border-radius: 50%;
}
.coinList-coin_balance-name {
text-transform: capitalize;
}
&:hover {
img {
opacity: 1;
}
}
}
.add-new-coin {
i {
width: 30px;
height: 30px;
transform: rotate(0deg);
border-radius: 50%;
background: #fff;
}
}
}
.prices {
.coin-icon-svg {
img {
width: 24px;
height: 24px;
border-radius: 50%;
}
}
.orders-item-wrapper {
width: 100%;
max-width: 600px;
}
}
}

2
react/src/styles/dex/_helpers.scss

@ -43,7 +43,7 @@
.coin-icon-placeholder,
.coin-icon-svg {
background: rgba(256,256,256,0.1);
background: rgba(255,255,255,1);
box-shadow: $box-shadow-inputs;
border-radius: 50% !important;
}

2
react/src/styles/dex/components/coinList.scss

@ -60,7 +60,7 @@
}
.coinList-coin:hover .coinList-coin_action svg {
fill: #FFF;
/*fill: #FFF;*/
transform: translateX(10px) scale(1.1)
}

Loading…
Cancel
Save