sforkowany z mirror/soapbox
CryptoDonate: refactor, rename, reorganize
rodzic
149c7718c3
commit
483fadb7c2
|
@ -0,0 +1,35 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
import QRCode from 'qrcode.react';
|
||||
import CoinDB from '../utils/coin_db';
|
||||
import { getCoinIcon } from '../utils/coin_icons';
|
||||
|
||||
export default class CryptoAddress extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
address: PropTypes.string.isRequired,
|
||||
ticker: PropTypes.string.isRequired,
|
||||
note: PropTypes.string,
|
||||
}
|
||||
|
||||
render() {
|
||||
const { address, ticker, note } = this.props;
|
||||
const title = CoinDB.getIn([ticker, 'name']);
|
||||
|
||||
return (
|
||||
<div className='crypto-address'>
|
||||
<div className='crypto-address__icon'>
|
||||
<img src={getCoinIcon(ticker)} alt={title} />
|
||||
</div>
|
||||
<div className='crypto-address__qr-code'>
|
||||
<QRCode value={address} />
|
||||
</div>
|
||||
<div className='crypto-address__title'>{title}</div>
|
||||
<div className='crypto-address__address'>{address}</div>
|
||||
{note && <div className='crypto-address__note'>{note}</div>}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
import CryptoAddress from './crypto_address';
|
||||
|
||||
const mapStateToProps = state => {
|
||||
// Address example:
|
||||
// {"ticker": "btc", "address": "bc1q9cx35adpm73aq2fw40ye6ts8hfxqzjr5unwg0n", "note": "This is our main address"}
|
||||
return {
|
||||
coinList: state.getIn(['soapbox', 'crypto_addresses']),
|
||||
};
|
||||
};
|
||||
|
||||
export default @connect(mapStateToProps)
|
||||
class CoinList extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
coinList: ImmutablePropTypes.list,
|
||||
}
|
||||
|
||||
render() {
|
||||
const { coinList } = this.props;
|
||||
if (!coinList) return null;
|
||||
|
||||
return (
|
||||
<div className='site-wallet'>
|
||||
{coinList.map(coin => (
|
||||
<CryptoAddress
|
||||
key={coin.get('ticker')}
|
||||
{...coin.toJS()}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -3,15 +3,15 @@ import { defineMessages, injectIntl } from 'react-intl';
|
|||
import PropTypes from 'prop-types';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
import Column from '../ui/components/column';
|
||||
import CoinList from './coin_list';
|
||||
import SiteWallet from './components/site_wallet';
|
||||
|
||||
const messages = defineMessages({
|
||||
heading: { id: 'column.cryptocoin', defaultMessage: 'Donate Cryptocurrency' },
|
||||
heading: { id: 'column.crypto_donate', defaultMessage: 'Donate Cryptocurrency' },
|
||||
});
|
||||
|
||||
export default
|
||||
@injectIntl
|
||||
class Cryptocoin extends ImmutablePureComponent {
|
||||
class CryptoDonate extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
intl: PropTypes.object.isRequired,
|
||||
|
@ -22,8 +22,8 @@ class Cryptocoin extends ImmutablePureComponent {
|
|||
|
||||
return (
|
||||
<Column icon='bitcoin' heading={intl.formatMessage(messages.heading)} backBtnSlim>
|
||||
<div className='cryptocoin'>
|
||||
<CoinList />
|
||||
<div className='crypto-donate'>
|
||||
<SiteWallet />
|
||||
</div>
|
||||
</Column>
|
||||
);
|
|
@ -0,0 +1,6 @@
|
|||
import { fromJS } from 'immutable';
|
||||
import manifestMap from './manifest_map';
|
||||
|
||||
// All this does is converts the result from manifest_map.js into an ImmutableMap
|
||||
const coinDB = fromJS(manifestMap);
|
||||
export default coinDB;
|
|
@ -0,0 +1,20 @@
|
|||
// Does some trickery to import all the icons into the project
|
||||
// See: https://stackoverflow.com/questions/42118296/dynamically-import-images-from-a-directory-using-webpack
|
||||
|
||||
const icons = {};
|
||||
|
||||
function importAll(r) {
|
||||
const pathRegex = /\.\/(.*)\.svg/i;
|
||||
|
||||
r.keys().forEach((key) => {
|
||||
const ticker = pathRegex.exec(key)[1];
|
||||
return icons[ticker] = r(key).default;
|
||||
});
|
||||
}
|
||||
|
||||
importAll(require.context('cryptocurrency-icons/svg/color/', true, /\.svg$/));
|
||||
|
||||
export default icons;
|
||||
|
||||
// For getting the icon
|
||||
export const getCoinIcon = ticker => icons[ticker] || icons.generic || null;
|
|
@ -0,0 +1,12 @@
|
|||
// @preval
|
||||
// Converts cryptocurrency-icon's manifest file from a list to a map.
|
||||
// See: https://github.com/spothq/cryptocurrency-icons/blob/master/manifest.json
|
||||
|
||||
const manifest = require('cryptocurrency-icons/manifest.json');
|
||||
const { Map: ImmutableMap, fromJS } = require('immutable');
|
||||
|
||||
const manifestMap = fromJS(manifest).reduce((acc, entry) => {
|
||||
return acc.set(entry.get('symbol').toLowerCase(), entry);
|
||||
}, ImmutableMap());
|
||||
|
||||
module.exports = manifestMap.toJS();
|
|
@ -1,30 +0,0 @@
|
|||
import React from 'react';
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
import QRCode from 'qrcode.react';
|
||||
import { getCoinIcon } from './icons';
|
||||
|
||||
export default class Coin extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
coin: ImmutablePropTypes.map.isRequired,
|
||||
}
|
||||
|
||||
render() {
|
||||
const { coin } = this.props;
|
||||
|
||||
return (
|
||||
<div className='coin'>
|
||||
<div className='coin__icon'>
|
||||
<img src={getCoinIcon(coin.get('ticker'))} alt={coin.get('title')} />
|
||||
</div>
|
||||
<div className='coin__qr-code'>
|
||||
<QRCode value={coin.get('address')} />
|
||||
</div>
|
||||
<div className='coin__title'>{coin.get('title')}</div>
|
||||
<div className='coin__address'>{coin.get('address')}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
{
|
||||
"supportedCoins": [
|
||||
"btc",
|
||||
"eth",
|
||||
"ltc",
|
||||
"doge",
|
||||
"ubq",
|
||||
"xmr"
|
||||
],
|
||||
"coinData": {
|
||||
"btc": { "title": "Bitcoin" },
|
||||
"eth": { "title": "Ethereum" },
|
||||
"ltc": { "title": "Litecoin" },
|
||||
"doge": { "title": "Dogecoin" },
|
||||
"xmr": { "title": "Monero" }
|
||||
}
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
import { List as ImmutableList, fromJS } from 'immutable';
|
||||
import coinDB from './coin_db.json';
|
||||
import Coin from './coin';
|
||||
|
||||
const supportedCoins = ImmutableList(coinDB.supportedCoins);
|
||||
const coinData = fromJS(coinDB.coinData);
|
||||
|
||||
const makeCoinList = crypto => {
|
||||
return supportedCoins.reduce((acc, ticker) => {
|
||||
const address = crypto.get(ticker);
|
||||
const data = coinData.get(ticker);
|
||||
if (!address || !data) return acc;
|
||||
|
||||
const coin = data.merge({ ticker, address });
|
||||
|
||||
return acc.push(coin);
|
||||
}, ImmutableList());
|
||||
};
|
||||
|
||||
const mapStateToProps = state => {
|
||||
const crypto = state.getIn(['soapbox', 'cryptocoin']);
|
||||
|
||||
return {
|
||||
coinList: makeCoinList(crypto),
|
||||
};
|
||||
};
|
||||
|
||||
export default @connect(mapStateToProps)
|
||||
class CoinList extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
coinList: ImmutablePropTypes.list,
|
||||
}
|
||||
|
||||
render() {
|
||||
const { coinList } = this.props;
|
||||
if (!coinList) return null;
|
||||
|
||||
return (
|
||||
<div className='crypto'>
|
||||
{coinList.map(coin => (
|
||||
<Coin coin={coin} key={coin.get('ticker')} />
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
const icons = {};
|
||||
|
||||
function importAll(r) {
|
||||
const pathRegex = /\.\/(.*)\.svg/i;
|
||||
|
||||
r.keys().forEach((key) => {
|
||||
const ticker = pathRegex.exec(key)[1];
|
||||
return icons[ticker] = r(key).default;
|
||||
});
|
||||
}
|
||||
|
||||
importAll(require.context('cryptocurrency-icons/svg/color/', true, /\.svg$/));
|
||||
|
||||
const getCoinIcon = ticker => icons[ticker] || icons.generic || null;
|
||||
|
||||
module.exports = {
|
||||
default: icons,
|
||||
getCoinIcon,
|
||||
};
|
|
@ -92,7 +92,7 @@ import {
|
|||
AwaitingApproval,
|
||||
Reports,
|
||||
ModerationLog,
|
||||
Cryptocoin,
|
||||
CryptoDonate,
|
||||
} from './util/async-components';
|
||||
|
||||
// Dummy import, to make sure that <Status /> ends up in the application bundle.
|
||||
|
@ -290,7 +290,7 @@ class SwitchingColumnsArea extends React.PureComponent {
|
|||
<WrappedRoute path='/admin/log' page={AdminPage} component={ModerationLog} content={children} exact />
|
||||
<WrappedRoute path='/info' layout={LAYOUT.EMPTY} component={ServerInfo} content={children} />
|
||||
|
||||
<WrappedRoute path='/donate/crypto' layout={LAYOUT.DEFAULT} component={Cryptocoin} content={children} />
|
||||
<WrappedRoute path='/donate/crypto' layout={LAYOUT.DEFAULT} component={CryptoDonate} content={children} />
|
||||
|
||||
<WrappedRoute layout={LAYOUT.EMPTY} component={GenericNotFound} content={children} />
|
||||
</Switch>
|
||||
|
|
|
@ -230,6 +230,6 @@ export function ModerationLog() {
|
|||
return import(/* webpackChunkName: "features/admin/moderation_log" */'../../admin/moderation_log');
|
||||
}
|
||||
|
||||
export function Cryptocoin() {
|
||||
return import(/* webpackChunkName: "features/cryptocoin" */'../../cryptocoin');
|
||||
export function CryptoDonate() {
|
||||
return import(/* webpackChunkName: "features/crypto_donate" */'../../crypto_donate');
|
||||
}
|
||||
|
|
|
@ -81,7 +81,7 @@
|
|||
@import 'components/server-info';
|
||||
@import 'components/admin';
|
||||
@import 'components/backups';
|
||||
@import 'components/cryptocoin';
|
||||
@import 'components/crypto-donate';
|
||||
|
||||
// Holiday
|
||||
@import 'holiday/halloween';
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
.coin {
|
||||
.crypto-address {
|
||||
padding: 20px;
|
||||
}
|
Ładowanie…
Reference in New Issue