Browse Source

feature(multi-currency): convert to sats before sending coins or making a request, no matter the currency

renovate/lint-staged-8.x
Jack Mallers 7 years ago
parent
commit
e04d308687
  1. 54
      app/components/Activity/ActivityModal.js
  2. 27
      app/components/Activity/ActivityModal.scss
  3. 106
      app/components/Activity/InvoiceModal.js
  4. 143
      app/components/Activity/InvoiceModal.scss
  5. 6
      app/components/Form/Form.js
  6. 4
      app/components/Form/Pay.js
  7. 111
      app/components/Form/Request.js
  8. 147
      app/components/Form/Request.scss
  9. 4
      app/components/ModalRoot/WalletDetails.js
  10. 16
      app/icons/hand.svg
  11. 13
      app/icons/paper_plane.svg
  12. 16
      app/reducers/activity.js
  13. 10
      app/reducers/invoice.js
  14. 6
      app/reducers/payform.js
  15. 15
      app/reducers/requestform.js
  16. 4
      app/reducers/transaction.js
  17. 16
      app/routes/activity/components/components/Modal/Modal.js
  18. 24
      app/routes/activity/components/components/Modal/Modal.scss
  19. 9
      app/routes/app/components/App.js
  20. 43
      app/routes/app/containers/AppContainer.js
  21. 2
      package.json
  22. 48
      yarn.lock

54
app/components/Activity/ActivityModal.js

@ -0,0 +1,54 @@
import React from 'react'
import PropTypes from 'prop-types'
import Isvg from 'react-inlinesvg'
// import Transaction from './Transaction'
// import Payment from './Payment'
import InvoiceModal from './InvoiceModal'
import x from 'icons/x.svg'
import styles from './ActivityModal.scss'
const ActivityModal = ({
modalType,
modalProps,
ticker,
currentTicker,
hideActivityModal,
toggleCurrencyProps
}) => {
const MODAL_COMPONENTS = {
// TRANSACTION: Transaction,
// PAYMENT: Payment,
INVOICE: InvoiceModal
}
if (!modalType) { return null }
const SpecificModal = MODAL_COMPONENTS[modalType]
console.log('toggleCurrencyProps: ', toggleCurrencyProps)
return (
<div className={styles.container}>
<div className={styles.closeContainer}>
<span onClick={() => hideActivityModal()}>
<Isvg src={x} />
</span>
</div>
<SpecificModal
{...modalProps}
ticker={ticker}
currentTicker={currentTicker}
toggleCurrencyProps={toggleCurrencyProps}
/>
</div>
)
}
ActivityModal.propTypes = {
modalType: PropTypes.string,
modalProps: PropTypes.object.isRequired,
hideActivityModal: PropTypes.func.isRequired
}
export default ActivityModal

27
app/components/Activity/ActivityModal.scss

@ -0,0 +1,27 @@
@import '../../variables.scss';
.container {
position: relative;
height: 100vh;
background: $bluegrey;
}
.closeContainer {
text-align: right;
padding: 20px 40px 0px;
span {
cursor: pointer;
opacity: 1.0;
transition: 0.25s all;
&:hover {
opacity: 0.5;
}
}
svg {
color: $white;
}
}

106
app/components/Activity/InvoiceModal.js

@ -0,0 +1,106 @@
import React from 'react'
import PropTypes from 'prop-types'
import Moment from 'react-moment'
import 'moment-timezone'
import QRCode from 'qrcode.react'
import copy from 'copy-to-clipboard'
import { showNotification } from 'notifications'
import { FaAngleDown } from 'react-icons/lib/fa'
import { btc } from 'utils'
import Value from 'components/Value'
import styles from './InvoiceModal.scss'
const InvoiceModal = ({
invoice,
ticker,
currentTicker,
toggleCurrencyProps: {
setActivityModalCurrencyFilters,
showCurrencyFilters,
currencyName,
currentCurrencyFilters,
setCurrency
}
}) => {
const copyPaymentRequest = () => {
copy(invoice.payment_request)
showNotification('Noice', 'Successfully copied to clipboard')
}
const onCurrencyFilterClick = (currency) => {
setCurrency(currency)
setActivityModalCurrencyFilters(false)
}
return (
<div className={styles.container}>
<div className={styles.content}>
<section className={styles.left}>
<QRCode
value={invoice.payment_request}
renderAs='svg'
size={150}
bgColor='transparent'
fgColor='white'
level='L'
/>
</section>
<section className={styles.right}>
<div className={styles.details}>
<section className={styles.amount}>
<h1>
<Value value={invoice.value} currency={ticker.currency} currentTicker={currentTicker} />
</h1>
<section className={styles.currentCurrency} onClick={() => setActivityModalCurrencyFilters(!showCurrencyFilters)}>
<span>{currencyName}</span><span><FaAngleDown /></span>
</section>
<ul className={showCurrencyFilters && styles.active}>
{
currentCurrencyFilters.map(filter =>
<li key={filter.key} onClick={() => onCurrencyFilterClick(filter.key)}>{filter.name}</li>
)
}
</ul>
</section>
<section className={styles.date}>
<p>
<Moment format='MM/DD/YYYY'>{invoice.creation_date * 1000}</Moment>
</p>
<p className={styles.notPaid}>
{!invoice.settled && 'Not Paid'}
</p>
</section>
</div>
<div className={styles.memo}>
<h4>Memo</h4>
<p>{invoice.memo}</p>
</div>
<div className={styles.request}>
<h4>Request</h4>
<p>{invoice.payment_request}</p>
</div>
</section>
</div>
<div className={styles.actions}>
<div>Save as image</div>
<div>Copy Request</div>
</div>
</div>
)
}
InvoiceModal.propTypes = {
invoice: PropTypes.object.isRequired
}
export default InvoiceModal

143
app/components/Activity/InvoiceModal.scss

@ -0,0 +1,143 @@
@import '../../variables.scss';
.container {
color: $white;
}
.content {
display: flex;
flex-direction: row;
align-items: center;
background: $spaceblue;
width: 85%;
margin: 50px auto;
padding: 30px 0;
.left {
width: 25%;
padding: 0 60px;
}
.right {
width: 75%;
min-height: 220px;
border-left: 1px solid $spaceborder;
padding: 10px 60px;
.details {
display: flex;
flex-direction: row;
justify-content: space-between;
margin-bottom: 40px;
.amount {
display: flex;
flex-direction: row;
align-items: center;
position: relative;
h1 {
font-size: 40px;
margin-right: 10px;
}
.currentCurrency {
cursor: pointer;
transition: 0.25s all;
&:hover {
opacity: 0.5;
}
span {
font-size: 14px;
&:nth-child(1) {
font-weight: bold;
}
}
}
ul {
visibility: hidden;
position: absolute;
top: 40px;
right: -50px;
&.active {
visibility: visible;
}
li {
padding: 8px 15px;
background: #191919;
cursor: pointer;
transition: 0.25s hover;
border-bottom: 1px solid #0f0f0f;
&:hover {
background: #0f0f0f;
}
}
}
}
.date {
font-size: 12px;
text-align: right;
.notPaid {
color: #FF8A65;
margin-top: 5px;
}
}
}
.memo, .request {
h4 {
font-size: 10px;
margin-bottom: 10px;
}
p {
word-wrap: break-word;
max-width: 450px;
}
}
.memo {
margin-bottom: 40px;
p {
font-size: 20px;
}
}
.request p {
font-size: 10px;
max-width: 450px;
line-height: 1.5;
}
}
}
.actions {
display: flex;
flex-direction: row;
justify-content: center;
div {
text-align: center;
margin: 35px 10px;
width: 235px;
padding: 20px 10px;
background: #31343f;
cursor: pointer;
transition: 0.25s all;
&:hover {
background: darken(#31343f, 5%);
}
}
}

6
app/components/Form/Form.js

@ -5,16 +5,14 @@ import Isvg from 'react-inlinesvg'
import { MdClose } from 'react-icons/lib/md'
import Pay from './Pay'
import PayForm from './PayForm'
import RequestForm from './RequestForm'
import Request from './Request'
import x from 'icons/x.svg'
import styles from './Form.scss'
const FORM_TYPES = {
// PAY_FORM: PayForm,
PAY_FORM: Pay,
REQUEST_FORM: RequestForm
REQUEST_FORM: Request
}
const Form = ({ formType, formProps, closeForm }) => {

4
app/components/Form/Pay.js

@ -121,7 +121,7 @@ class Pay extends Component {
<section className={styles.amount}>
<div className={styles.top}>
<label>Amount</label>
<label htmlFor='amount'>Amount</label>
<span></span>
</div>
<div className={styles.bottom}>
@ -171,7 +171,7 @@ Pay.propTypes = {
amount: PropTypes.oneOfType([
PropTypes.string,
PropTypes.number
]).isRequired,
]),
payInput: PropTypes.string.isRequired,
showErrors: PropTypes.object.isRequired
}).isRequired,

111
app/components/Form/Request.js

@ -0,0 +1,111 @@
import React from 'react'
import PropTypes from 'prop-types'
import Isvg from 'react-inlinesvg'
import hand from 'icons/hand.svg'
import { FaAngleDown } from 'react-icons/lib/fa'
import { btc } from 'utils'
import CurrencyIcon from 'components/CurrencyIcon'
import styles from './Request.scss'
const Request = ({
requestform: { amount, memo, showCurrencyFilters },
ticker,
setRequestAmount,
setRequestMemo,
setCurrency,
setRequestCurrencyFilters,
currencyName,
currentCurrencyFilters,
onRequestSubmit
}) => {
const onCurrencyFilterClick = (currency) => {
// change the input amount
setRequestAmount(btc.convert(ticker.currency, currency, amount))
setCurrency(currency)
setRequestCurrencyFilters(false)
}
return (
<div className={styles.container}>
<header className={styles.header}>
<Isvg src={hand} />
<h1>Request Payment</h1>
</header>
<div className={styles.content}>
<section className={styles.memo}>
<div className={styles.top}>
<label htmlFor='memo'>Memo</label>
</div>
<div className={styles.bottom}>
<input
type='text'
placeholder='Dinner, Rent, etc'
value={memo}
onChange={event => setRequestMemo(event.target.value)}
id='memo'
/>
</div>
</section>
<section className={styles.amount}>
<div className={styles.top}>
<label htmlFor='amount'>Amount</label>
<span></span>
</div>
<div className={styles.bottom}>
<input
type='number'
value={amount || ''}
onChange={event => setRequestAmount(event.target.value)}
id='amount'
placeholder='0.00000000'
/>
<div className={styles.currency}>
<section className={styles.currentCurrency} onClick={() => setRequestCurrencyFilters(!showCurrencyFilters)}>
<span>{currencyName}</span><span><FaAngleDown /></span>
</section>
<ul className={showCurrencyFilters && styles.active}>
{
currentCurrencyFilters.map(filter =>
<li key={filter.key} onClick={() => onCurrencyFilterClick(filter.key)}>{filter.name}</li>
)
}
</ul>
</div>
</div>
<div className={styles.usdAmount}>
</div>
</section>
<section className={styles.submit}>
<div className={`${styles.button} ${amount > 0 && styles.active}`} onClick={onRequestSubmit}>
Request
</div>
</section>
</div>
</div>
)
}
Request.propTypes = {
requestform: PropTypes.shape({
amount: PropTypes.string,
memo: PropTypes.string
}).isRequired,
setRequestAmount: PropTypes.func.isRequired,
setRequestMemo: PropTypes.func.isRequired,
onRequestSubmit: PropTypes.func.isRequired
}
export default Request

147
app/components/Form/Request.scss

@ -0,0 +1,147 @@
@import '../../variables.scss';
.container {
padding: 0 40px;
font-family: Roboto;
}
.header {
text-align: center;
padding-bottom: 20px;
color: $white;
border-bottom: 1px solid $spaceborder;
h1 {
font-size: 22px;
font-weight: 100;
margin-top: 10px;
letter-spacing: 1.5px;
}
}
.content {
margin-top: 50px;
color: $white;
.memo {
margin-bottom: 25px;
}
.amount .bottom {
display: flex;
flex-direction: row;
align-items: center;
input {
font-size: 40px;
max-width: 230px;
}
}
.top {
margin-bottom: 25px;
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
label {
font-size: 14px;
}
}
.bottom {
input {
background: transparent;
outline: none;
border: 0;
color: $gold;
-webkit-text-fill-color: $white;
font-size: 20px;
width: 100%;
font-weight: 200;
}
input::-webkit-input-placeholder {
text-shadow: none;
-webkit-text-fill-color: initial;
}
}
.currency {
position: relative;
display: flex;
flex-direction: row;
align-items: center;
.currentCurrency {
cursor: pointer;
transition: 0.25s all;
&:hover {
opacity: 0.5;
}
span {
font-size: 14px;
&:nth-child(1) {
font-weight: bold;
}
}
}
ul {
visibility: hidden;
position: absolute;
top: 30px;
&.active {
visibility: visible;
}
li {
padding: 8px 15px;
background: #191919;
cursor: pointer;
transition: 0.25s hover;
border-bottom: 1px solid #0f0f0f;
&:hover {
background: #0f0f0f;
}
}
}
}
.usdAmount {
margin-top: 20px;
opacity: 0.5;
}
.submit {
margin-top: 50px;
text-align: center;
.button {
width: 235px;
margin: 0 auto;
padding: 20px 10px;
background: #31343f;
opacity: 0.5;
cursor: pointer;
transition: 0.25s all;
&.active {
background: $gold;
opacity: 1.0;
&:hover {
background: darken($gold, 5%);
}
}
}
}
}

4
app/components/ModalRoot/WalletDetails.js

@ -25,9 +25,7 @@ const WalletDetails = ({ info, address }) => (
</div>
<div className={styles.right}>
<section>
<h2>
Network
</h2>
<h2>Network</h2>
</section>
</div>
</div>

16
app/icons/hand.svg

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="32px" height="14px" viewBox="0 0 32 14" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 48.2 (47327) - http://www.bohemiancoding.com/sketch -->
<title>Group 20 Copy</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Generate-Request-Invoice" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" transform="translate(-496.000000, -77.000000)">
<g id="Group-9" transform="translate(423.000000, 78.000000)" stroke="#FFFFFF" stroke-width="0.75">
<g id="Group-20-Copy" transform="translate(74.000000, 0.000000)">
<path d="M6,1.07778574 C10.0254503,0.706033518 13.3396626,1.66678494 15.9426369,3.96004002 C17.6659089,3.96004002 19.2069713,3.96004002 20.5658241,3.96004002 C22.6041032,3.96004002 22.3477222,7 20.5658241,7 C19.377892,7 16.9999136,7 13.4318889,7" id="Path-5"></path>
<path d="M2.10931173,9.9245745 L6,9.9245745 L6,0 L0,0 C0.208329331,5.0351144 0.965722589,8.36844774 2.27217977,10" id="Path-2"></path>
<path d="M6,8.84278961 C11.4341037,10.9475965 15.0785314,12 16.933283,12 C19.7154105,12 27.7492176,7.1560437 29.2844267,6.15768359 C30.8196358,5.15932348 29.5244956,4 28.7375913,4 C28.2129884,4 25.9404234,4.75236148 21.9198962,6.25708445" id="Path-4"></path>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

13
app/icons/paper_plane.svg

@ -1,16 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="22px" height="22px" viewBox="0 0 22 22" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 48.2 (47327) - http://www.bohemiancoding.com/sketch -->
<title>Shape</title>
<title>send</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Pay-(Onchain)" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" transform="translate(-502.000000, -68.000000)" stroke-linecap="round" stroke-linejoin="round">
<g id="Group-3" transform="translate(423.000000, 69.000000)" stroke="#FFFFFF" stroke-width="0.75">
<g id="Group">
<g id="send" transform="translate(79.000000, 0.000000)">
<polygon id="Shape" points="21 0 13.65 21 9.45 11.55 0 7.35"></polygon>
</g>
</g>
<g id="Pay-(LN)" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" transform="translate(-502.000000, -68.000000)" stroke-linecap="round" stroke-linejoin="round">
<g id="send" transform="translate(502.000000, 69.000000)" stroke="#FFFFFF" stroke-width="0.75">
<path d="M20.5,0.5 L9.5,11.5" id="Shape"></path>
<polygon id="Shape" points="21 0 13.65 21 9.45 11.55 0 7.35"></polygon>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 897 B

After

Width:  |  Height:  |  Size: 803 B

16
app/reducers/activity.js

@ -15,7 +15,8 @@ const initialState = {
],
modal: {
modalType: null,
modalProps: {}
modalProps: {},
showCurrencyFilters: false
},
searchText: ''
}
@ -30,6 +31,8 @@ export const CHANGE_FILTER = 'CHANGE_FILTER'
export const TOGGLE_PULLDOWN = 'TOGGLE_PULLDOWN'
export const SET_ACTIVITY_MODAL_CURRENCY_FILTERS = 'SET_ACTIVITY_MODAL_CURRENCY_FILTERS'
export const UPDATE_SEARCH_TEXT = 'UPDATE_SEARCH_TEXT'
// ------------------------------------
@ -69,6 +72,13 @@ export function updateSearchText(searchText) {
}
}
export function setActivityModalCurrencyFilters(showCurrencyFilters) {
return {
type: SET_ACTIVITY_MODAL_CURRENCY_FILTERS,
showCurrencyFilters
}
}
// ------------------------------------
// Action Handlers
// ------------------------------------
@ -77,6 +87,10 @@ const ACTION_HANDLERS = {
[HIDE_ACTIVITY_MODAL]: state => ({ ...state, modal: { modalType: null, modalProps: {} } }),
[CHANGE_FILTER]: (state, { filter }) => ({ ...state, filter, filterPulldown: false }),
[TOGGLE_PULLDOWN]: state => ({ ...state, filterPulldown: !state.filterPulldown }),
[SET_ACTIVITY_MODAL_CURRENCY_FILTERS]: (state, { showCurrencyFilters }) => (
{ ...state, modal: { modalType: state.modal.modalType, modalProps: state.modal.modalProps, showCurrencyFilters } }
),
[UPDATE_SEARCH_TEXT]: (state, { searchText }) => ({ ...state, searchText })
}

10
app/reducers/invoice.js

@ -97,7 +97,9 @@ export const receiveInvoices = (event, { invoices }) => dispatch => dispatch({ t
// Send IPC event for creating an invoice
export const createInvoice = (amount, memo, currency, rate) => (dispatch) => {
const value = currency === 'btc' ? btc.btcToSatoshis(amount) : btc.btcToSatoshis(usd.usdToBtc(amount, rate))
// backend needs value in satoshis no matter what currency we are using
const value = btc.convert(currency, 'sats', amount)
dispatch(sendInvoice())
ipcRenderer.send('lnd', { msg: 'createInvoice', data: { value, memo } })
}
@ -189,6 +191,12 @@ invoiceSelectors.invoices = createSelector(
(invoices, invoicesSearchText) => invoices.filter(invoice => invoice.memo.includes(invoicesSearchText))
)
invoiceSelectors.invoices = createSelector(
invoicesSelector,
invoicesSearchTextSelector,
(invoices, invoicesSearchText) => invoices.filter(invoice => invoice.memo.includes(invoicesSearchText))
)
export { invoiceSelectors }
// ------------------------------------

6
app/reducers/payform.js

@ -34,7 +34,7 @@ export const SET_PAY_AMOUNT = 'SET_PAY_AMOUNT'
export const SET_PAY_INPUT = 'SET_PAY_INPUT'
export const SET_PAY_INVOICE = 'SET_PAY_INVOICE'
export const SET_CURRENCY_FILTERS = 'SET_CURRENCY_FILTERS'
export const SET_PAY_CURRENCY_FILTERS = 'SET_PAY_CURRENCY_FILTERS'
export const UPDATE_PAY_ERRORS = 'UPDATE_PAY_ERRORS'
@ -66,7 +66,7 @@ export function setPayInvoice(invoice) {
export function setCurrencyFilters(showCurrencyFilters) {
return {
type: SET_CURRENCY_FILTERS,
type: SET_PAY_CURRENCY_FILTERS,
showCurrencyFilters
}
}
@ -98,7 +98,7 @@ const ACTION_HANDLERS = {
[SET_PAY_AMOUNT]: (state, { amount }) => ({ ...state, amount, showErrors: Object.assign(state.showErrors, { amount: false }) }),
[SET_PAY_INPUT]: (state, { payInput }) => ({ ...state, payInput, showErrors: Object.assign(state.showErrors, { payInput: false }) }),
[SET_PAY_INVOICE]: (state, { invoice }) => ({ ...state, invoice, showErrors: Object.assign(state.showErrors, { amount: false }) }),
[SET_CURRENCY_FILTERS]: (state, { showCurrencyFilters }) => ({ ...state, showCurrencyFilters }),
[SET_PAY_CURRENCY_FILTERS]: (state, { showCurrencyFilters }) => ({ ...state, showCurrencyFilters }),
[UPDATE_PAY_ERRORS]: (state, { errorsObject }) => ({ ...state, showErrors: Object.assign(state.showErrors, errorsObject) }),

15
app/reducers/requestform.js

@ -1,7 +1,8 @@
// Initial State
const initialState = {
amount: '0',
memo: ''
amount: '',
memo: '',
showCurrencyFilters: false
}
// Constants
@ -10,6 +11,8 @@ export const SET_REQUEST_AMOUNT = 'SET_REQUEST_AMOUNT'
export const SET_REQUEST_MEMO = 'SET_REQUEST_MEMO'
export const SET_PAY_INVOICE = 'SET_PAY_INVOICE'
export const SET_REQUEST_CURRENCY_FILTERS = 'SET_REQUEST_CURRENCY_FILTERS'
export const RESET_FORM = 'RESET_FORM'
// ------------------------------------
@ -35,12 +38,20 @@ export function resetRequestForm() {
}
}
export function setRequestCurrencyFilters(showCurrencyFilters) {
return {
type: SET_REQUEST_CURRENCY_FILTERS,
showCurrencyFilters
}
}
// ------------------------------------
// Action Handlers
// ------------------------------------
const ACTION_HANDLERS = {
[SET_REQUEST_AMOUNT]: (state, { amount }) => ({ ...state, amount }),
[SET_REQUEST_MEMO]: (state, { memo }) => ({ ...state, memo }),
[SET_REQUEST_CURRENCY_FILTERS]: (state, { showCurrencyFilters }) => ({ ...state, showCurrencyFilters }),
[RESET_FORM]: () => (initialState)
}

4
app/reducers/transaction.js

@ -48,7 +48,9 @@ export const receiveTransactions = (event, { transactions }) => dispatch => disp
export const sendCoins = ({
value, addr, currency, rate
}) => (dispatch) => {
const amount = currency === 'usd' ? btc.btcToSatoshis(usd.usdToBtc(value, rate)) : btc.btcToSatoshis(value)
// backend needs amount in satoshis no matter what currency we are using
const amount = btc.convert(currency, 'sats', value)
dispatch(sendTransaction())
ipcRenderer.send('lnd', { msg: 'sendCoins', data: { amount, addr } })
}

16
app/routes/activity/components/components/Modal/Modal.js

@ -2,11 +2,13 @@ import React from 'react'
import PropTypes from 'prop-types'
import ReactModal from 'react-modal'
import { MdClose } from 'react-icons/lib/md'
import Isvg from 'react-inlinesvg'
import Transaction from './Transaction'
import Payment from './Payment'
import Invoice from './Invoice'
import x from 'icons/x.svg'
import styles from './Modal.scss'
const Modal = ({
@ -39,22 +41,14 @@ const Modal = ({
const SpecificModal = MODAL_COMPONENTS[modalType]
return (
<ReactModal
isOpen
ariaHideApp
shouldCloseOnOverlayClick
contentLabel='No Overlay Click Modal'
onRequestClose={() => hideActivityModal()}
parentSelector={() => document.body}
style={customStyles}
>
<div className={styles.container}>
<div className={styles.closeContainer}>
<span onClick={() => hideActivityModal()}>
<MdClose />
<Isvg src={x} />
</span>
</div>
<SpecificModal {...modalProps} ticker={ticker} currentTicker={currentTicker} />
</ReactModal>
</div>
)
}

24
app/routes/activity/components/components/Modal/Modal.scss

@ -1,13 +1,27 @@
@import '../../../../../variables.scss';
.container {
position: relative;
height: 100vh;
background: $spaceblue;
}
.closeContainer {
background: $lightgrey;
text-align: right;
padding: 10px;
padding: 20px 40px 0px;
span {
color: $darkestgrey;
font-size: 20px;
cursor: pointer;
opacity: 1.0;
transition: 0.25s all;
&:hover {
opacity: 0.5;
}
}
}
svg {
color: $white;
}
}

9
app/routes/app/components/App.js

@ -11,6 +11,8 @@ import Network from 'components/Contacts/Network'
import ContactModal from 'components/Contacts/ContactModal'
import ContactsForm from 'components/Contacts/ContactsForm'
import ActivityModal from 'components/activity/ActivityModal'
import styles from './App.scss'
class App extends Component {
@ -33,6 +35,9 @@ class App extends Component {
render() {
const {
activity,
hideActivityModal,
modal: { modalType, modalProps },
hideModal,
ticker,
@ -48,10 +53,12 @@ class App extends Component {
contactModalProps,
contactsFormProps,
networkTabProps,
activityModalProps,
children
} = this.props
console.log('activityModalProps: ', activityModalProps)
if (!currentTicker) { return <LoadingBolt /> }
return (
@ -71,6 +78,8 @@ class App extends Component {
<Form formType={form.formType} formProps={formProps} closeForm={closeForm} />
<ActivityModal {...activityModalProps} />
<div className={styles.content}>
{children}
</div>

43
app/routes/app/containers/AppContainer.js

@ -13,7 +13,7 @@ import { setFormType } from 'reducers/form'
import { setPayAmount, setPayInput, setCurrencyFilters, updatePayErrors, payFormSelectors } from 'reducers/payform'
import { setRequestAmount, setRequestMemo } from 'reducers/requestform'
import { setRequestAmount, setRequestMemo, setRequestCurrencyFilters } from 'reducers/requestform'
import { sendCoins } from 'reducers/transaction'
@ -52,6 +52,8 @@ import { fetchDescribeNetwork } from 'reducers/network'
import { clearError } from 'reducers/error'
import { hideActivityModal, setActivityModalCurrencyFilters } from 'reducers/activity'
import App from '../components/App'
const mapDispatchToProps = {
@ -74,7 +76,7 @@ const mapDispatchToProps = {
setRequestAmount,
setRequestMemo,
setRequestCurrencyFilters,
sendCoins,
payInvoice,
@ -103,10 +105,15 @@ const mapDispatchToProps = {
contactFormSelectors,
updateManualFormErrors,
fetchDescribeNetwork
fetchDescribeNetwork,
hideActivityModal,
setActivityModalCurrencyFilters
}
const mapStateToProps = state => ({
activity: state.activity,
lnd: state.lnd,
ticker: state.ticker,
@ -231,11 +238,16 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => {
const requestFormProps = {
requestform: stateProps.requestform,
currency: stateProps.ticker.currency,
crypto: stateProps.ticker.crypto,
ticker: stateProps.ticker,
currentCurrencyFilters: stateProps.currentCurrencyFilters,
showCurrencyFilters: stateProps.showCurrencyFilters,
currencyName: stateProps.currencyName,
setRequestAmount: dispatchProps.setRequestAmount,
setRequestMemo: dispatchProps.setRequestMemo,
setCurrency: dispatchProps.setCurrency,
setRequestCurrencyFilters: dispatchProps.setRequestCurrencyFilters,
onRequestSubmit: () => (
dispatchProps.createInvoice(
@ -303,6 +315,25 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => {
closingChannelIds: stateProps.channels.closingChannelIds
}
const activityModalProps = {
modalType: stateProps.activity.modal.modalType,
modalProps: stateProps.activity.modal.modalProps,
ticker: stateProps.ticker,
currentTicker: stateProps.currentTicker,
hideActivityModal: dispatchProps.hideActivityModal,
toggleCurrencyProps: {
currentCurrencyFilters: stateProps.currentCurrencyFilters,
currencyName: stateProps.currencyName,
showCurrencyFilters: stateProps.activity.modal.showCurrencyFilters,
setActivityModalCurrencyFilters: dispatchProps.setActivityModalCurrencyFilters,
setCurrencyFilters: dispatchProps.setCurrencyFilters,
setCurrency: dispatchProps.setCurrency,
}
}
return {
...stateProps,
...dispatchProps,
@ -314,6 +345,8 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => {
contactsFormProps,
// props for the contact modal
contactModalProps,
// props for the activity modals
activityModalProps,
// Props to pass to the pay form
formProps: formProps(stateProps.form.formType),
// action to close form

2
package.json

@ -215,7 +215,7 @@
"lodash": "^4.17.4",
"moment-timezone": "^0.5.13",
"prop-types": "^15.5.10",
"qrcode.react": "^0.7.1",
"qrcode.react": "0.8.0",
"react": "^15.6.1",
"react-dom": "^15.6.1",
"react-hot-loader": "3.0.0-beta.6",

48
yarn.lock

@ -336,8 +336,8 @@ arrify@^1.0.0, arrify@^1.0.1:
resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d"
asap@~2.0.3:
version "2.0.5"
resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.5.tgz#522765b50c3510490e52d7dcfe085ef9ba96958f"
version "2.0.6"
resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46"
asar-integrity@0.2.3:
version "0.2.3"
@ -3904,9 +3904,9 @@ fbjs-scripts@^0.8.0:
semver "^5.1.0"
through2 "^2.0.0"
fbjs@^0.8.9:
version "0.8.12"
resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.12.tgz#10b5d92f76d45575fd63a217d4ea02bea2f8ed04"
fbjs@^0.8.16, fbjs@^0.8.9:
version "0.8.16"
resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.16.tgz#5e67432f550dc41b572bf55847b8aca64e5337db"
dependencies:
core-js "^1.0.0"
isomorphic-fetch "^2.1.1"
@ -4729,11 +4729,11 @@ iconv-lite@0.4.13:
version "0.4.13"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.13.tgz#1f88aba4ab0b1508e8312acc39345f36e992e2f2"
iconv-lite@^0.4.17, iconv-lite@~0.4.13:
iconv-lite@^0.4.17:
version "0.4.17"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.17.tgz#4fdaa3b38acbc2c031b045d0edcdfe1ecab18c8d"
iconv-lite@^0.4.19:
iconv-lite@^0.4.19, iconv-lite@~0.4.13:
version "0.4.19"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b"
@ -5437,8 +5437,8 @@ js-base64@^2.1.8, js-base64@^2.1.9:
resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.1.9.tgz#f0e80ae039a4bd654b5f281fc93f04a914a7fcce"
js-tokens@^3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.1.tgz#08e9f132484a2c45a30907e9dc4d5567b7f114d7"
version "3.0.2"
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b"
js-yaml@^3.10.0:
version "3.10.0"
@ -6295,8 +6295,8 @@ node-emoji@^1.8.1:
lodash.toarray "^4.4.0"
node-fetch@^1.0.1:
version "1.7.1"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.1.tgz#899cb3d0a3c92f952c47f1b876f4c8aeabd400d5"
version "1.7.3"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef"
dependencies:
encoding "^0.1.11"
is-stream "^1.0.1"
@ -7309,18 +7309,26 @@ progress@^2.0.0:
resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.0.tgz#8a1be366bf8fc23db2bd23f10c6fe920b4389d1f"
promise@^7.1.1:
version "7.1.1"
resolved "https://registry.yarnpkg.com/promise/-/promise-7.1.1.tgz#489654c692616b8aa55b0724fa809bb7db49c5bf"
version "7.3.1"
resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf"
dependencies:
asap "~2.0.3"
prop-types@^15.5.10, prop-types@^15.5.4, prop-types@^15.5.8:
prop-types@^15.5.10, prop-types@^15.5.4:
version "15.5.10"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.5.10.tgz#2797dfc3126182e3a95e3dfbb2e893ddd7456154"
dependencies:
fbjs "^0.8.9"
loose-envify "^1.3.1"
prop-types@^15.6.0:
version "15.6.0"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.0.tgz#ceaf083022fc46b4a35f69e13ef75aed0d639856"
dependencies:
fbjs "^0.8.16"
loose-envify "^1.3.1"
object-assign "^4.1.1"
proxy-addr@~1.1.4:
version "1.1.4"
resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-1.1.4.tgz#27e545f6960a44a627d9b44467e35c1b6b4ce2f3"
@ -7390,11 +7398,11 @@ qr.js@0.0.0:
version "0.0.0"
resolved "https://registry.yarnpkg.com/qr.js/-/qr.js-0.0.0.tgz#cace86386f59a0db8050fa90d9b6b0e88a1e364f"
qrcode.react@^0.7.1:
version "0.7.1"
resolved "https://registry.yarnpkg.com/qrcode.react/-/qrcode.react-0.7.1.tgz#6fc5017f17025048919115581da5e375b0946742"
qrcode.react@0.8.0:
version "0.8.0"
resolved "https://registry.yarnpkg.com/qrcode.react/-/qrcode.react-0.8.0.tgz#413b31cc3b62910e39513f7bead945e01c4c34fb"
dependencies:
prop-types "^15.5.8"
prop-types "^15.6.0"
qr.js "0.0.0"
qs@6.4.0, qs@~6.4.0:
@ -9128,8 +9136,8 @@ typeforce@^1.11.3:
inherits "^2.0.1"
ua-parser-js@^0.7.9:
version "0.7.12"
resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.12.tgz#04c81a99bdd5dc52263ea29d24c6bf8d4818a4bb"
version "0.7.17"
resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.17.tgz#e9ec5f9498b9ec910e7ae3ac626a805c4d09ecac"
uglify-js@3.0.x:
version "3.0.15"

Loading…
Cancel
Save