-
Notifications
You must be signed in to change notification settings - Fork 974
WIP - Add Payment History dialog to Payments Tab (#2994) #3391
Changes from 17 commits
5774667
36c896a
08ec7ba
8ca3f4a
bd84215
8593ef1
6c8274d
b30a5e0
a33b901
d89268d
cb27dc9
48b0171
ba8ff14
3cb85fe
fb828b5
fe5ae39
1eded36
934dde1
2a729d9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -683,16 +683,28 @@ var ledgerInfo = { | |
transactions: | ||
[ | ||
/* | ||
{ viewingId : undefined | ||
, submissionStamp : undefined | ||
, satoshis : undefined | ||
, currency : undefined | ||
, amount : undefined | ||
, ballots : | ||
{ 'publisher1' : undefined | ||
... | ||
{ | ||
viewingId: undefined, | ||
surveyorId: undefined, | ||
contribution: { | ||
fiat: { | ||
amount: undefined, | ||
currency: undefined | ||
}, | ||
rates: { | ||
[currency]: undefined // bitcoin value in <currency> | ||
}, | ||
satoshis: undefined, | ||
fee: undefined | ||
}, | ||
submissionStamp: undefined, | ||
submissionId: undefined, | ||
count: undefined, | ||
satoshis: undefined, | ||
votes: undefined, | ||
ballots: { | ||
[publisher]: undefined | ||
} | ||
} | ||
, ... | ||
*/ | ||
], | ||
|
@@ -995,7 +1007,9 @@ var getPaymentInfo = () => { | |
info.address = client.getWalletAddress() | ||
if ((amount) && (currency)) { | ||
info = underscore.extend(info, { amount: amount, currency: currency }) | ||
if ((body.rates) && (body.rates[currency])) info.btc = (amount / body.rates[currency]).toFixed(8) | ||
if ((body.rates) && (body.rates[currency])) { | ||
info.btc = (amount / body.rates[currency]).toFixed(8) | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i don't quite understand this change. it looks like 1 line got split to 3, but no other changes... what are my eyes not seeing? thanks! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Whoops! I had added a line for A pure whitespace change also happened merging #3434 because we both added 'contribution' to the whitelist. But I needed to be up to date with master, so only change was whitespsce. |
||
} | ||
ledgerInfo._internal.paymentInfo = info | ||
updateLedgerInfo() | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -323,6 +323,83 @@ class BitcoinDashboard extends ImmutableComponent { | |
} | ||
} | ||
|
||
class PaymentHistory extends ImmutableComponent { | ||
get ledgerData () { | ||
return this.props.ledgerData | ||
} | ||
|
||
render () { | ||
const transactions = this.props.ledgerData.get('transactions') | ||
|
||
return <div id='paymentHistory'> | ||
<table className='sort'> | ||
<thead> | ||
<tr> | ||
<th className='sort-header' data-l10n-id='date' /> | ||
<th className='sort-header' data-l10n-id='totalAmount' /> | ||
<th className='sort-header' data-l10n-id='receiptLink' /> | ||
</tr> | ||
</thead> | ||
<tbody> | ||
{ | ||
transactions.map(function (row) { | ||
return <PaymentHistoryRow transaction={row} ledgerData={this.props.ledgerData} /> | ||
}.bind(this)) | ||
} | ||
</tbody> | ||
</table> | ||
</div> | ||
} | ||
} | ||
|
||
class PaymentHistoryRow extends ImmutableComponent { | ||
|
||
get transaction () { | ||
return this.props.transaction | ||
} | ||
|
||
get timestamp () { | ||
return this.transaction.get('submissionStamp') | ||
} | ||
|
||
get formattedDate () { | ||
return formattedDateFromTimestamp(this.timestamp) | ||
} | ||
|
||
get numericDateStr () { | ||
return (new Date(this.timestamp)).toLocaleDateString().replace(/\//g, '-') | ||
} | ||
|
||
get ledgerData () { | ||
return this.props.ledgerData | ||
} | ||
|
||
get satoshis () { | ||
return this.transaction.get('contribution').get('satoshis') | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
} | ||
|
||
get currency () { | ||
return this.transaction.get('contribution').get('fiat').get('currency') | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same as above; if undefined, return an empty string for now. |
||
} | ||
|
||
get totalAmount () { | ||
var fiatAmount = this.transaction.get('contribution').get('fiat').get('amount') | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same as above |
||
return fiatAmount.toFixed(2) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this is available directly now, via There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this should check that |
||
} | ||
|
||
render () { | ||
var date = this.formattedDate | ||
var totalAmountStr = this.totalAmount + ' ' + this.currency | ||
var receiptFileName = 'brave_ledger' + this.numericDateStr + '.pdf' | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is minor, but we prefer to use JS template strings here. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals |
||
|
||
return <tr> | ||
<td className='narrow' data-sort={this.timestamp}>{date}</td> | ||
<td className='wide' data-sort={this.satoshis}>{totalAmountStr}</td> | ||
<td className='wide'>{receiptFileName}</td> | ||
</tr> | ||
} | ||
} | ||
|
||
class GeneralTab extends ImmutableComponent { | ||
enabled (keyArray) { | ||
return keyArray.every((key) => getSetting(key, this.props.settings) === true) | ||
|
@@ -498,6 +575,20 @@ class PaymentsTab extends ImmutableComponent { | |
return <Button l10nId={buttonText} className='primaryButton' onClick={onButtonClick.bind(this)} disabled={this.props.ledgerData.get('creating')} /> | ||
} | ||
|
||
get paymentHistoryButton () { | ||
const walletCreated = this.props.ledgerData.get('created') && !this.props.ledgerData.get('creating') | ||
const walletTransactions = this.props.ledgerData.get('transactions') | ||
const walletHasTransactions = walletTransactions && walletTransactions.size | ||
|
||
if (!walletCreated || !walletHasTransactions) { | ||
return null | ||
} | ||
|
||
const buttonText = 'viewPaymentHistory' | ||
const onButtonClick = this.props.showOverlay.bind(this, 'paymentHistory') | ||
return <Button className='paymentHistoryButton' l10nId={buttonText} onClick={onButtonClick.bind(this)} disabled={this.props.ledgerData.get('creating')} /> | ||
} | ||
|
||
get walletStatus () { | ||
let status = {} | ||
if (this.props.ledgerData.get('created')) { | ||
|
@@ -536,6 +627,27 @@ class PaymentsTab extends ImmutableComponent { | |
hideParentOverlay={this.props.hideOverlay.bind(this, 'addFunds')} /> | ||
} | ||
|
||
get paymentHistoryContent () { | ||
return <PaymentHistory ledgerData={this.props.ledgerData} /> | ||
} | ||
|
||
get paymentHistoryFooter () { | ||
let ledgerData = this.props.ledgerData | ||
if (!ledgerData.get('reconcileStamp')) { | ||
return | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. return |
||
} | ||
let nextReconcileDate = formattedDateFromTimestamp(ledgerData.get('reconcileStamp')) | ||
let l10nDataArgs = { | ||
reconcileDate: nextReconcileDate | ||
} | ||
return <div className='paymentHistoryFooter'> | ||
<div className='nextPaymentSubmission'> | ||
<span data-l10n-id='paymentHistoryFooterText' data-l10n-args={JSON.stringify(l10nDataArgs)} /> | ||
</div> | ||
<Button l10nId='paymentHistoryOKText' className='okButton primaryButton' onClick={this.props.hideOverlay.bind(this, 'paymentHistory')} /> | ||
</div> | ||
} | ||
|
||
btcToCurrencyString (btc) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you can simplify this using There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. actually There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @mrose17 what do you mean? btcPrice was needed to convert There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. +1 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nvm comment above, @willy-b you can leave |
||
const balance = Number(btc || 0) | ||
const currency = this.props.ledgerData.get('currency') | ||
|
@@ -545,8 +657,7 @@ class PaymentsTab extends ImmutableComponent { | |
if (balance === 0) { | ||
return `0 ${currency}` | ||
} | ||
if (this.props.ledgerData.get('btc') && | ||
typeof this.props.ledgerData.get('amount') === 'number') { | ||
if (this.props.ledgerData.get('btc') && typeof this.props.ledgerData.get('amount') === 'number') { | ||
const btcValue = this.props.ledgerData.get('btc') / this.props.ledgerData.get('amount') | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i suspect that sometime post-beta we will need to use something like https://github.com/xsolla/currency-format in order to format properly... |
||
return `${(balance / btcValue).toFixed(2)} ${currency}` | ||
} | ||
|
@@ -582,6 +693,7 @@ class PaymentsTab extends ImmutableComponent { | |
{this.btcToCurrencyString(this.props.ledgerData.get('balance'))} | ||
</span> | ||
{this.walletButton} | ||
{this.paymentHistoryButton} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this button should not show up if there is empty payment history (ex: before wallet has been created) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
</td> | ||
<td> | ||
<SettingsList> | ||
|
@@ -616,6 +728,11 @@ class PaymentsTab extends ImmutableComponent { | |
? <ModalOverlay title={'addFunds'} content={this.overlayContent} onHide={this.props.hideOverlay.bind(this, 'addFunds')} /> | ||
: null | ||
} | ||
{ | ||
this.enabled && this.props.paymentHistoryOverlayVisible | ||
? <ModalOverlay title={'paymentHistoryTitle'} customTitleClasses={'paymentHistory'} content={this.paymentHistoryContent} footer={this.paymentHistoryFooter} onHide={this.props.hideOverlay.bind(this, 'paymentHistory')} /> | ||
: null | ||
} | ||
<div className='titleBar'> | ||
<div className='sectionTitle pull-left' data-l10n-id='publisherPaymentsTitle' value='publisherPaymentsTitle' /> | ||
<div className='pull-left' id='enablePaymentsSwitch'> | ||
|
@@ -997,6 +1114,7 @@ class AboutPreferences extends React.Component { | |
let hash = window.location.hash ? window.location.hash.slice(1) : '' | ||
this.state = { | ||
bitcoinOverlayVisible: false, | ||
paymentHistoryOverlayVisible: false, | ||
addFundsOverlayVisible: false, | ||
preferenceTab: hash.toUpperCase() in preferenceTabs ? hash : preferenceTabs.GENERAL, | ||
hintNumber: this.getNextHintNumber(), | ||
|
@@ -1109,6 +1227,7 @@ class AboutPreferences extends React.Component { | |
braveryDefaults={braveryDefaults} ledgerData={ledgerData} | ||
onChangeSetting={this.onChangeSetting} | ||
bitcoinOverlayVisible={this.state.bitcoinOverlayVisible} | ||
paymentHistoryOverlayVisible={this.state.paymentHistoryOverlayVisible} | ||
addFundsOverlayVisible={this.state.addFundsOverlayVisible} | ||
showOverlay={this.setOverlayVisible.bind(this, true)} | ||
hideOverlay={this.setOverlayVisible.bind(this, false)} /> | ||
|
@@ -1134,4 +1253,9 @@ class AboutPreferences extends React.Component { | |
} | ||
} | ||
|
||
let formattedDateFromTimestamp = function (timestamp) { | ||
var date = new Date(timestamp) | ||
return date.toLocaleDateString() | ||
} | ||
|
||
module.exports = <AboutPreferences /> |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,10 +18,19 @@ class ModalOverlay extends ImmutableComponent { | |
close = <button type='button' className='close pull-right' onClick={this.props.onHide}><span>×</span></button> | ||
title = <div className='sectionTitle' data-l10n-id={this.props.title} /> | ||
} | ||
return <div className='dialog'> | ||
{close} | ||
{title} | ||
{this.props.content} | ||
let customTitleClassesStr = (this.props.customTitleClasses ? this.props.customTitleClasses : '') | ||
|
||
return <div className={'dialog ' + customTitleClassesStr}> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wow, glad you caught this :-). |
||
<div className='dialog-header'> | ||
{close} | ||
{title} | ||
</div> | ||
<div className='dialog-body'> | ||
{this.props.content} | ||
</div> | ||
<div className='dialog-footer'> | ||
{this.props.footer} | ||
</div> | ||
</div> | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -455,6 +455,61 @@ table.sortableTable { | |
overflow-y: scroll; | ||
} | ||
|
||
.modal .dialog.paymentHistory .sectionTitle { | ||
text-align: left; | ||
} | ||
|
||
span.paymentHistoryButton.browserButton { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice catch! FIXED in fb828b5#diff-4b50ff14dadc9756719a577a72f520d6R466 BTW, this screenshot points out another issue: The currency for the balance is BTC when the wallet is empty, and always USD when non-empty (just confirmed locally). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @willy-b before the wallet is created, we have no idea what the user's currency is, so it defaults to BTC. it could just say 'empty' or something. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes... Add Funds should be "Add funds..." and use smaller text. Button should match height of budget menu. Said menu should move up to align with "Add funds..." button. |
||
display: block; | ||
color: @braveOrange; | ||
font-size: 14px; | ||
white-space: nowrap; | ||
} | ||
|
||
.paymentHistoryFooter span.okButton.primaryButton { | ||
background-color: gray; | ||
float: right; | ||
margin-top: -10px; | ||
display: inline; | ||
padding-top: 5px; | ||
padding-left: 35px; | ||
padding-right: 35px; | ||
padding-bottom: 5px; | ||
} | ||
|
||
div.nextPaymentSubmission { | ||
display: inline; | ||
} | ||
.nextPaymentSubmission span { | ||
font-size: 12px; | ||
display: inline; | ||
} | ||
|
||
.modal .dialog.paymentHistory { | ||
padding: 0px; | ||
|
||
.dialog-header { | ||
background-color: #EEE; | ||
height: 20px; | ||
padding-bottom: 10px; | ||
} | ||
|
||
.dialog-body { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Your recommendation fixed this: 2a729d9#diff-4b50ff14dadc9756719a577a72f520d6R500 |
||
background-color: #FFF; | ||
height: 300px; | ||
} | ||
|
||
.dialog-footer { | ||
background-color: #EEE; | ||
height: 5px; | ||
} | ||
|
||
.dialog-header, .dialog-body, .dialog-footer { | ||
padding: 20px; | ||
} | ||
} | ||
|
||
|
||
#paymentsContainer { | ||
position: relative; | ||
overflow-x: hidden; | ||
|
@@ -485,6 +540,28 @@ table.sortableTable { | |
} | ||
} | ||
|
||
#paymentHistory { | ||
background-color: #FFF; | ||
tr { | ||
th { | ||
color: @darkGray; | ||
font-weight: 500; | ||
border-bottom: 2px solid @lightGray; | ||
text-align: left; | ||
width: 18%; | ||
} | ||
td { | ||
text-align: left; | ||
&.narrow { | ||
color: @darkGray; | ||
} | ||
&.wide { | ||
color: #777; | ||
} | ||
} | ||
} | ||
} | ||
|
||
.sort { | ||
text-align: left; | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
need @mrose17 to review this part
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i guess this is obsolete now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
agreed. no longer needed.