Merge branch 'tipping_button' of https://github.com/hackrush01/lbry-app into hackrush01-tipping_button
This commit is contained in:
commit
0a543a3dcd
26 changed files with 569 additions and 123 deletions
|
@ -8,11 +8,11 @@ Web UI version numbers should always match the corresponding version of LBRY App
|
||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
### Added
|
### Added
|
||||||
|
* Added a tipping button to send LBRY Credits to the publisher
|
||||||
* File pages now show the time of a publish.
|
* File pages now show the time of a publish.
|
||||||
* The "auth token" displayable on Help offers security warning
|
* The "auth token" displayable on Help offers security warning
|
||||||
* Added a new component for rendering dates and times. This component can render the date and time of a block height, as well.
|
* Added a new component for rendering dates and times. This component can render the date and time of a block height, as well.
|
||||||
|
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
|
|
56
ui/js/actions/claims.js
Normal file
56
ui/js/actions/claims.js
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
import lbry from "lbry";
|
||||||
|
import { selectBalance } from "selectors/wallet";
|
||||||
|
import { doOpenModal, doShowSnackBar } from "actions/app";
|
||||||
|
import * as types from "constants/action_types";
|
||||||
|
import * as modals from "constants/modal_types";
|
||||||
|
|
||||||
|
export function doSendSupport(amount, claim_id) {
|
||||||
|
return function(dispatch, getState) {
|
||||||
|
const state = getState();
|
||||||
|
const balance = selectBalance(state);
|
||||||
|
|
||||||
|
if (balance - amount <= 0) {
|
||||||
|
return dispatch(doOpenModal(modals.INSUFFICIENT_BALANCE));
|
||||||
|
}
|
||||||
|
|
||||||
|
dispatch({
|
||||||
|
type: types.SUPPORT_TRANSACTION_STARTED,
|
||||||
|
});
|
||||||
|
|
||||||
|
const successCallback = results => {
|
||||||
|
if (results.txid) {
|
||||||
|
dispatch({
|
||||||
|
type: types.SUPPORT_TRANSACTION_COMPLETED,
|
||||||
|
});
|
||||||
|
dispatch(
|
||||||
|
doShowSnackBar({
|
||||||
|
message: __(`You sent ${amount} LBC as support, Mahalo!`),
|
||||||
|
linkText: __("History"),
|
||||||
|
linkTarget: __("/wallet"),
|
||||||
|
})
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
dispatch({
|
||||||
|
type: types.SUPPORT_TRANSACTION_FAILED,
|
||||||
|
data: { error: results },
|
||||||
|
});
|
||||||
|
dispatch(doOpenModal(modals.TRANSACTION_FAILED));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const errorCallback = error => {
|
||||||
|
dispatch({
|
||||||
|
type: types.SUPPORT_TRANSACTION_FAILED,
|
||||||
|
data: { error: error.message },
|
||||||
|
});
|
||||||
|
dispatch(doOpenModal(modals.TRANSACTION_FAILED));
|
||||||
|
};
|
||||||
|
|
||||||
|
lbry
|
||||||
|
.wallet_send({
|
||||||
|
claim_id: claim_id,
|
||||||
|
amount: amount,
|
||||||
|
})
|
||||||
|
.then(successCallback, errorCallback);
|
||||||
|
};
|
||||||
|
}
|
|
@ -5,7 +5,8 @@ import {
|
||||||
selectDraftTransactionAmount,
|
selectDraftTransactionAmount,
|
||||||
selectBalance,
|
selectBalance,
|
||||||
} from "selectors/wallet";
|
} from "selectors/wallet";
|
||||||
import { doOpenModal } from "actions/app";
|
import { doOpenModal, doShowSnackBar } from "actions/app";
|
||||||
|
import * as modals from "constants/modal_types";
|
||||||
|
|
||||||
export function doUpdateBalance(balance) {
|
export function doUpdateBalance(balance) {
|
||||||
return {
|
return {
|
||||||
|
@ -22,7 +23,7 @@ export function doFetchTransactions() {
|
||||||
type: types.FETCH_TRANSACTIONS_STARTED,
|
type: types.FETCH_TRANSACTIONS_STARTED,
|
||||||
});
|
});
|
||||||
|
|
||||||
lbry.transaction_list().then(results => {
|
lbry.transaction_list({ include_tip_info: true }).then(results => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.FETCH_TRANSACTIONS_COMPLETED,
|
type: types.FETCH_TRANSACTIONS_COMPLETED,
|
||||||
data: {
|
data: {
|
||||||
|
@ -83,8 +84,8 @@ export function doSendDraftTransaction() {
|
||||||
const balance = selectBalance(state);
|
const balance = selectBalance(state);
|
||||||
const amount = selectDraftTransactionAmount(state);
|
const amount = selectDraftTransactionAmount(state);
|
||||||
|
|
||||||
if (balance - amount < 1) {
|
if (balance - amount <= 0) {
|
||||||
return dispatch(doOpenModal("insufficientBalance"));
|
return dispatch(doOpenModal(modals.INSUFFICIENT_BALANCE));
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
|
@ -96,13 +97,19 @@ export function doSendDraftTransaction() {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.SEND_TRANSACTION_COMPLETED,
|
type: types.SEND_TRANSACTION_COMPLETED,
|
||||||
});
|
});
|
||||||
dispatch(doOpenModal("transactionSuccessful"));
|
dispatch(
|
||||||
|
doShowSnackBar({
|
||||||
|
message: __(`You sent ${amount} LBC`),
|
||||||
|
linkText: __("History"),
|
||||||
|
linkTarget: __("/wallet"),
|
||||||
|
})
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.SEND_TRANSACTION_FAILED,
|
type: types.SEND_TRANSACTION_FAILED,
|
||||||
data: { error: results },
|
data: { error: results },
|
||||||
});
|
});
|
||||||
dispatch(doOpenModal("transactionFailed"));
|
dispatch(doOpenModal(modals.TRANSACTION_FAILED));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -111,7 +118,7 @@ export function doSendDraftTransaction() {
|
||||||
type: types.SEND_TRANSACTION_FAILED,
|
type: types.SEND_TRANSACTION_FAILED,
|
||||||
data: { error: error.message },
|
data: { error: error.message },
|
||||||
});
|
});
|
||||||
dispatch(doOpenModal("transactionFailed"));
|
dispatch(doOpenModal(modals.TRANSACTION_FAILED));
|
||||||
};
|
};
|
||||||
|
|
||||||
lbry
|
lbry
|
||||||
|
|
|
@ -2,10 +2,7 @@ import React from "react";
|
||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
import { selectPageTitle } from "selectors/navigation";
|
import { selectPageTitle } from "selectors/navigation";
|
||||||
import { selectUser } from "selectors/user";
|
import { selectUser } from "selectors/user";
|
||||||
import {
|
import { doCheckUpgradeAvailable, doAlertError } from "actions/app";
|
||||||
doCheckUpgradeAvailable,
|
|
||||||
doAlertError,
|
|
||||||
} from "actions/app";
|
|
||||||
import { doRecordScroll } from "actions/navigation";
|
import { doRecordScroll } from "actions/navigation";
|
||||||
import { doFetchRewardedContent } from "actions/content";
|
import { doFetchRewardedContent } from "actions/content";
|
||||||
import { doUpdateBalance } from "actions/wallet";
|
import { doUpdateBalance } from "actions/wallet";
|
||||||
|
|
|
@ -71,6 +71,7 @@ export class CreditAmount extends React.PureComponent {
|
||||||
showFullPrice: React.PropTypes.bool,
|
showFullPrice: React.PropTypes.bool,
|
||||||
showPlus: React.PropTypes.bool,
|
showPlus: React.PropTypes.bool,
|
||||||
look: React.PropTypes.oneOf(["indicator", "plain"]),
|
look: React.PropTypes.oneOf(["indicator", "plain"]),
|
||||||
|
fee: React.PropTypes.bool,
|
||||||
};
|
};
|
||||||
|
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
|
@ -81,6 +82,7 @@ export class CreditAmount extends React.PureComponent {
|
||||||
showFree: false,
|
showFree: false,
|
||||||
showFullPrice: false,
|
showFullPrice: false,
|
||||||
showPlus: false,
|
showPlus: false,
|
||||||
|
fee: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
@ -117,7 +119,10 @@ export class CreditAmount extends React.PureComponent {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<span
|
<span
|
||||||
className={`credit-amount credit-amount--${this.props.look}`}
|
className={`credit-amount credit-amount--${this.props.look} ${this.props
|
||||||
|
.fee
|
||||||
|
? " meta"
|
||||||
|
: ""}`}
|
||||||
title={fullPrice}
|
title={fullPrice}
|
||||||
>
|
>
|
||||||
<span>
|
<span>
|
||||||
|
|
|
@ -11,7 +11,10 @@ import { makeSelectCostInfoForUri } from "selectors/cost_info";
|
||||||
import { doCloseModal, doOpenModal } from "actions/app";
|
import { doCloseModal, doOpenModal } from "actions/app";
|
||||||
import { doFetchAvailability } from "actions/availability";
|
import { doFetchAvailability } from "actions/availability";
|
||||||
import { doOpenFileInShell, doOpenFileInFolder } from "actions/file_info";
|
import { doOpenFileInShell, doOpenFileInFolder } from "actions/file_info";
|
||||||
import { makeSelectClaimForUriIsMine } from "selectors/claims";
|
import {
|
||||||
|
makeSelectClaimForUriIsMine,
|
||||||
|
makeSelectClaimForUri,
|
||||||
|
} from "selectors/claims";
|
||||||
import { doPurchaseUri, doLoadVideo, doStartDownload } from "actions/content";
|
import { doPurchaseUri, doLoadVideo, doStartDownload } from "actions/content";
|
||||||
import FileActions from "./view";
|
import FileActions from "./view";
|
||||||
|
|
||||||
|
@ -22,6 +25,7 @@ const makeSelect = () => {
|
||||||
const selectCostInfoForUri = makeSelectCostInfoForUri();
|
const selectCostInfoForUri = makeSelectCostInfoForUri();
|
||||||
const selectLoadingForUri = makeSelectLoadingForUri();
|
const selectLoadingForUri = makeSelectLoadingForUri();
|
||||||
const selectClaimForUriIsMine = makeSelectClaimForUriIsMine();
|
const selectClaimForUriIsMine = makeSelectClaimForUriIsMine();
|
||||||
|
const selectClaimForUri = makeSelectClaimForUri();
|
||||||
|
|
||||||
const select = (state, props) => ({
|
const select = (state, props) => ({
|
||||||
fileInfo: selectFileInfoForUri(state, props),
|
fileInfo: selectFileInfoForUri(state, props),
|
||||||
|
@ -33,6 +37,7 @@ const makeSelect = () => {
|
||||||
costInfo: selectCostInfoForUri(state, props),
|
costInfo: selectCostInfoForUri(state, props),
|
||||||
loading: selectLoadingForUri(state, props),
|
loading: selectLoadingForUri(state, props),
|
||||||
claimIsMine: selectClaimForUriIsMine(state, props),
|
claimIsMine: selectClaimForUriIsMine(state, props),
|
||||||
|
claimInfo: selectClaimForUri(state, props),
|
||||||
});
|
});
|
||||||
|
|
||||||
return select;
|
return select;
|
||||||
|
|
|
@ -57,6 +57,10 @@ class FileActions extends React.PureComponent {
|
||||||
this.props.loadVideo(this.props.uri);
|
this.props.loadVideo(this.props.uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleSupportButtonClicked() {
|
||||||
|
this.props.onTipShow();
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
fileInfo,
|
fileInfo,
|
||||||
|
@ -73,6 +77,7 @@ class FileActions extends React.PureComponent {
|
||||||
costInfo,
|
costInfo,
|
||||||
loading,
|
loading,
|
||||||
claimIsMine,
|
claimIsMine,
|
||||||
|
claimInfo,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
const metadata = fileInfo ? fileInfo.metadata : null,
|
const metadata = fileInfo ? fileInfo.metadata : null,
|
||||||
|
@ -166,6 +171,12 @@ class FileActions extends React.PureComponent {
|
||||||
return (
|
return (
|
||||||
<section className="file-actions">
|
<section className="file-actions">
|
||||||
{content}
|
{content}
|
||||||
|
<Link
|
||||||
|
label={__("Support")}
|
||||||
|
button="text"
|
||||||
|
icon="icon-gift"
|
||||||
|
onClick={this.handleSupportButtonClicked.bind(this)}
|
||||||
|
/>
|
||||||
{showMenu
|
{showMenu
|
||||||
? <div className="button-set-item">
|
? <div className="button-set-item">
|
||||||
<DropDownMenu>
|
<DropDownMenu>
|
||||||
|
|
|
@ -116,7 +116,7 @@ class PublishForm extends React.PureComponent {
|
||||||
? { channel_name: this.state.channel }
|
? { channel_name: this.state.channel }
|
||||||
: {}),
|
: {}),
|
||||||
};
|
};
|
||||||
|
|
||||||
const { source } = this.state;
|
const { source } = this.state;
|
||||||
|
|
||||||
if (this.refs.file.getValue() !== "") {
|
if (this.refs.file.getValue() !== "") {
|
||||||
|
@ -262,7 +262,7 @@ class PublishForm extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
handlePrefillClicked() {
|
handlePrefillClicked() {
|
||||||
const claimInfo = this.myClaimInfo();
|
const claimInfo = this.myClaimInfo();
|
||||||
const { source } = claimInfo.value.stream;
|
const { source } = claimInfo.value.stream;
|
||||||
const {
|
const {
|
||||||
license,
|
license,
|
||||||
|
|
12
ui/js/component/tipLink/index.js
Normal file
12
ui/js/component/tipLink/index.js
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
import React from "react";
|
||||||
|
import { connect } from "react-redux";
|
||||||
|
import { doSendSupport } from "actions/claims";
|
||||||
|
import TipLink from "./view";
|
||||||
|
|
||||||
|
const select = state => ({});
|
||||||
|
|
||||||
|
const perform = dispatch => ({
|
||||||
|
sendSupport: (amount, claim_id) => dispatch(doSendSupport(amount, claim_id)),
|
||||||
|
});
|
||||||
|
|
||||||
|
export default connect(select, perform)(TipLink);
|
71
ui/js/component/tipLink/view.jsx
Normal file
71
ui/js/component/tipLink/view.jsx
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
import React from "react";
|
||||||
|
import Link from "component/link";
|
||||||
|
import { FormRow } from "component/form";
|
||||||
|
|
||||||
|
class TipLink extends React.PureComponent {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
tipAmount: 1.0,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
handleSendButtonClicked() {
|
||||||
|
let claim_id = this.props.claim_id;
|
||||||
|
let amount = this.state.tipAmount;
|
||||||
|
this.props.sendSupport(amount, claim_id);
|
||||||
|
this.props.onTipHide();
|
||||||
|
}
|
||||||
|
|
||||||
|
handleSupportCancelButtonClicked() {
|
||||||
|
this.props.onTipHide();
|
||||||
|
}
|
||||||
|
|
||||||
|
handleSupportPriceChange(event) {
|
||||||
|
this.setState({
|
||||||
|
tipAmount: Number(event.target.value),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div className="card__content">
|
||||||
|
<div className="card__title-primary">
|
||||||
|
<h4>{__("Support")}</h4>
|
||||||
|
</div>
|
||||||
|
<div className="card__content">
|
||||||
|
{__(
|
||||||
|
"Support the creator and the success of their content by sending a tip. "
|
||||||
|
)}
|
||||||
|
<Link label={__("Learn more")} href="https://lbry.io/faq/tipping" />
|
||||||
|
</div>
|
||||||
|
<div className="card__content">
|
||||||
|
<FormRow
|
||||||
|
label={__("Amount")}
|
||||||
|
postfix={__("LBC")}
|
||||||
|
min="0"
|
||||||
|
step="0.1"
|
||||||
|
type="number"
|
||||||
|
placeholder="1.00"
|
||||||
|
onChange={event => this.handleSupportPriceChange(event)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="card__actions">
|
||||||
|
<Link
|
||||||
|
label={__("Send")}
|
||||||
|
button="primary"
|
||||||
|
onClick={this.handleSendButtonClicked.bind(this)}
|
||||||
|
/>
|
||||||
|
<Link
|
||||||
|
label={__("Cancel")}
|
||||||
|
button="alt"
|
||||||
|
onClick={this.handleSupportCancelButtonClicked.bind(this)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default TipLink;
|
|
@ -1,5 +1,10 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
|
import { doNavigate } from "actions/navigation";
|
||||||
import TransactionList from "./view";
|
import TransactionList from "./view";
|
||||||
|
|
||||||
export default connect(null, null)(TransactionList);
|
const perform = dispatch => ({
|
||||||
|
navigate: (path, params) => dispatch(doNavigate(path, params)),
|
||||||
|
});
|
||||||
|
|
||||||
|
export default connect(null, perform)(TransactionList);
|
||||||
|
|
140
ui/js/component/transactionList/internal/TransactionListBody.jsx
Normal file
140
ui/js/component/transactionList/internal/TransactionListBody.jsx
Normal file
|
@ -0,0 +1,140 @@
|
||||||
|
import React from "react";
|
||||||
|
import LinkTransaction from "component/linkTransaction";
|
||||||
|
import { CreditAmount } from "component/common";
|
||||||
|
|
||||||
|
class TransactionTableBody extends React.PureComponent {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
}
|
||||||
|
|
||||||
|
getClaimLink(claim_name, claim_id) {
|
||||||
|
let uri = `lbry://${claim_name}#${claim_id}`;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<a className="button-text" onClick={() => this.props.navigate(uri)}>
|
||||||
|
{claim_name}
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
filterList(transaction) {
|
||||||
|
if (this.props.filter == "claim") {
|
||||||
|
return transaction.claim_info.length > 0;
|
||||||
|
} else if (this.props.filter == "support") {
|
||||||
|
return transaction.support_info.length > 0;
|
||||||
|
} else if (this.props.filter == "update") {
|
||||||
|
return transaction.update_info.length > 0;
|
||||||
|
} else {
|
||||||
|
return transaction;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
renderBody(transaction) {
|
||||||
|
const txid = transaction.id;
|
||||||
|
const date = transaction.date;
|
||||||
|
const fee = transaction.fee;
|
||||||
|
const filter = this.props.filter;
|
||||||
|
const options = {
|
||||||
|
weekday: "short",
|
||||||
|
year: "2-digit",
|
||||||
|
month: "short",
|
||||||
|
day: "numeric",
|
||||||
|
hour: "2-digit",
|
||||||
|
minute: "2-digit",
|
||||||
|
second: "2-digit",
|
||||||
|
};
|
||||||
|
|
||||||
|
if (filter == "tipSupport")
|
||||||
|
transaction["tipSupport_info"] = transaction["support_info"].filter(
|
||||||
|
tx => tx.is_tip
|
||||||
|
);
|
||||||
|
|
||||||
|
return filter != "unfiltered"
|
||||||
|
? transaction[`${filter}_info`].map(item => {
|
||||||
|
return (
|
||||||
|
<tr key={`${txid}:${item.nout}`}>
|
||||||
|
<td>
|
||||||
|
{date
|
||||||
|
? date.toLocaleDateString("en-US", options)
|
||||||
|
: <span className="empty">
|
||||||
|
{__("(Transaction pending)")}
|
||||||
|
</span>}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<CreditAmount
|
||||||
|
amount={item.amount}
|
||||||
|
look="plain"
|
||||||
|
label={false}
|
||||||
|
showPlus={true}
|
||||||
|
precision={8}
|
||||||
|
/>
|
||||||
|
<br />
|
||||||
|
<CreditAmount
|
||||||
|
amount={fee}
|
||||||
|
look="plain"
|
||||||
|
fee={true}
|
||||||
|
label={false}
|
||||||
|
precision={8}
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{this.getClaimLink(item.claim_name, item.claim_id)}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<LinkTransaction id={txid} />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
);
|
||||||
|
})
|
||||||
|
: <tr key={txid}>
|
||||||
|
<td>
|
||||||
|
{date
|
||||||
|
? date.toLocaleDateString("en-US", options)
|
||||||
|
: <span className="empty">
|
||||||
|
{__("(Transaction pending)")}
|
||||||
|
</span>}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<CreditAmount
|
||||||
|
amount={transaction.amount}
|
||||||
|
look="plain"
|
||||||
|
label={false}
|
||||||
|
showPlus={true}
|
||||||
|
precision={8}
|
||||||
|
/>
|
||||||
|
<br />
|
||||||
|
<CreditAmount
|
||||||
|
amount={fee}
|
||||||
|
look="plain"
|
||||||
|
fee={true}
|
||||||
|
label={false}
|
||||||
|
precision={8}
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<LinkTransaction id={txid} />
|
||||||
|
</td>
|
||||||
|
</tr>;
|
||||||
|
}
|
||||||
|
|
||||||
|
removeFeeTx(transaction) {
|
||||||
|
if (this.props.filter == "unfiltered")
|
||||||
|
return Math.abs(transaction.amount) != Math.abs(transaction.fee);
|
||||||
|
else return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { transactions, filter } = this.props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<tbody>
|
||||||
|
{transactions
|
||||||
|
.filter(this.filterList, this)
|
||||||
|
.filter(this.removeFeeTx, this)
|
||||||
|
.map(this.renderBody, this)}
|
||||||
|
</tbody>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default TransactionTableBody;
|
|
@ -0,0 +1,19 @@
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
class TransactionTableHeader extends React.PureComponent {
|
||||||
|
render() {
|
||||||
|
const { filter } = this.props;
|
||||||
|
return (
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>{__("Date")}</th>
|
||||||
|
<th>{__("Amount(Fee)")}</th>
|
||||||
|
{filter != "unfiltered" && <th> {__("Claim Name")} </th>}
|
||||||
|
<th>{__("Transaction")}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default TransactionTableHeader;
|
|
@ -1,57 +1,65 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import LinkTransaction from "component/linkTransaction";
|
import TransactionTableHeader from "./internal/TransactionListHeader";
|
||||||
import { CreditAmount } from "component/common";
|
import TransactionTableBody from "./internal/TransactionListBody";
|
||||||
|
import FormField from "component/formField";
|
||||||
|
|
||||||
const TransactionList = props => {
|
class TransactionList extends React.PureComponent {
|
||||||
const { emptyMessage, transactions } = props;
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
filter: "unfiltered",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
handleFilterChanged(event) {
|
||||||
|
this.setState({
|
||||||
|
filter: event.target.value,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
handleClaimNameClicked(uri) {
|
||||||
|
this.props.navigate("/show", { uri });
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { emptyMessage, transactions } = this.props;
|
||||||
|
const { filter } = this.state;
|
||||||
|
|
||||||
|
if (!transactions || !transactions.length) {
|
||||||
|
return (
|
||||||
|
<div className="empty">
|
||||||
|
{emptyMessage || __("No transactions to list.")}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (!transactions || !transactions.length) {
|
|
||||||
return (
|
return (
|
||||||
<div className="empty">
|
<div>
|
||||||
{emptyMessage || __("No transactions to list.")}
|
<span className="sort-section">
|
||||||
|
{__("Filter")} {" "}
|
||||||
|
<FormField
|
||||||
|
type="select"
|
||||||
|
onChange={this.handleFilterChanged.bind(this)}
|
||||||
|
>
|
||||||
|
<option value="unfiltered">{__("All")}</option>
|
||||||
|
<option value="claim">{__("Publishes")}</option>
|
||||||
|
<option value="support">{__("Supports")}</option>
|
||||||
|
<option value="tipSupport">{__("Tips")}</option>
|
||||||
|
<option value="update">{__("Updates")}</option>
|
||||||
|
</FormField>
|
||||||
|
</span>
|
||||||
|
<table className="table-standard table-stretch">
|
||||||
|
<TransactionTableHeader filter={filter} />
|
||||||
|
<TransactionTableBody
|
||||||
|
transactions={transactions}
|
||||||
|
filter={filter}
|
||||||
|
navigate={this.handleClaimNameClicked.bind(this)}
|
||||||
|
/>
|
||||||
|
</table>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return (
|
|
||||||
<table className="table-standard table-stretch">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>{__("Date")}</th>
|
|
||||||
<th>{__("Amount")}</th>
|
|
||||||
<th>{__("Transaction")}</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{transactions.map(item => {
|
|
||||||
return (
|
|
||||||
<tr key={item.id}>
|
|
||||||
<td>
|
|
||||||
{item.date
|
|
||||||
? item.date.toLocaleDateString() +
|
|
||||||
" " +
|
|
||||||
item.date.toLocaleTimeString()
|
|
||||||
: <span className="empty">
|
|
||||||
{__("(Transaction pending)")}
|
|
||||||
</span>}
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<CreditAmount
|
|
||||||
amount={item.amount}
|
|
||||||
look="plain"
|
|
||||||
showPlus={true}
|
|
||||||
precision={8}
|
|
||||||
/>{" "}
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<LinkTransaction id={item.id} />
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default TransactionList;
|
export default TransactionList;
|
||||||
|
|
|
@ -1,12 +1,10 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
import { doCloseModal } from "actions/app";
|
|
||||||
import {
|
import {
|
||||||
doSendDraftTransaction,
|
doSendDraftTransaction,
|
||||||
doSetDraftTransactionAmount,
|
doSetDraftTransactionAmount,
|
||||||
doSetDraftTransactionAddress,
|
doSetDraftTransactionAddress,
|
||||||
} from "actions/wallet";
|
} from "actions/wallet";
|
||||||
import { selectCurrentModal } from "selectors/app";
|
|
||||||
import {
|
import {
|
||||||
selectDraftTransactionAmount,
|
selectDraftTransactionAmount,
|
||||||
selectDraftTransactionAddress,
|
selectDraftTransactionAddress,
|
||||||
|
@ -16,14 +14,12 @@ import {
|
||||||
import WalletSend from "./view";
|
import WalletSend from "./view";
|
||||||
|
|
||||||
const select = state => ({
|
const select = state => ({
|
||||||
modal: selectCurrentModal(state),
|
|
||||||
address: selectDraftTransactionAddress(state),
|
address: selectDraftTransactionAddress(state),
|
||||||
amount: selectDraftTransactionAmount(state),
|
amount: selectDraftTransactionAmount(state),
|
||||||
error: selectDraftTransactionError(state),
|
error: selectDraftTransactionError(state),
|
||||||
});
|
});
|
||||||
|
|
||||||
const perform = dispatch => ({
|
const perform = dispatch => ({
|
||||||
closeModal: () => dispatch(doCloseModal()),
|
|
||||||
sendToAddress: () => dispatch(doSendDraftTransaction()),
|
sendToAddress: () => dispatch(doSendDraftTransaction()),
|
||||||
setAmount: event => dispatch(doSetDraftTransactionAmount(event.target.value)),
|
setAmount: event => dispatch(doSetDraftTransactionAmount(event.target.value)),
|
||||||
setAddress: event =>
|
setAddress: event =>
|
||||||
|
|
|
@ -1,20 +1,10 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import Link from "component/link";
|
import Link from "component/link";
|
||||||
import Modal from "modal/modal";
|
|
||||||
import { FormRow } from "component/form";
|
import { FormRow } from "component/form";
|
||||||
import lbryuri from "lbryuri";
|
import lbryuri from "lbryuri";
|
||||||
|
|
||||||
const WalletSend = props => {
|
const WalletSend = props => {
|
||||||
const {
|
const { sendToAddress, setAmount, setAddress, amount, address } = props;
|
||||||
sendToAddress,
|
|
||||||
closeModal,
|
|
||||||
modal,
|
|
||||||
setAmount,
|
|
||||||
setAddress,
|
|
||||||
amount,
|
|
||||||
address,
|
|
||||||
error,
|
|
||||||
} = props;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className="card">
|
<section className="card">
|
||||||
|
@ -57,32 +47,6 @@ const WalletSend = props => {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
{modal == "insufficientBalance" &&
|
|
||||||
<Modal
|
|
||||||
isOpen={true}
|
|
||||||
contentLabel={__("Insufficient balance")}
|
|
||||||
onConfirmed={closeModal}
|
|
||||||
>
|
|
||||||
{__(
|
|
||||||
"Insufficient balance: after this transaction you would have less than 1 LBC in your wallet."
|
|
||||||
)}
|
|
||||||
</Modal>}
|
|
||||||
{modal == "transactionSuccessful" &&
|
|
||||||
<Modal
|
|
||||||
isOpen={true}
|
|
||||||
contentLabel={__("Transaction successful")}
|
|
||||||
onConfirmed={closeModal}
|
|
||||||
>
|
|
||||||
{__("Your transaction was successfully placed in the queue.")}
|
|
||||||
</Modal>}
|
|
||||||
{modal == "transactionFailed" &&
|
|
||||||
<Modal
|
|
||||||
isOpen={true}
|
|
||||||
contentLabel={__("Transaction failed")}
|
|
||||||
onConfirmed={closeModal}
|
|
||||||
>
|
|
||||||
{error}
|
|
||||||
</Modal>}
|
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -132,6 +132,11 @@ export const CLAIM_REWARD_FAILURE = "CLAIM_REWARD_FAILURE";
|
||||||
export const CLAIM_REWARD_CLEAR_ERROR = "CLAIM_REWARD_CLEAR_ERROR";
|
export const CLAIM_REWARD_CLEAR_ERROR = "CLAIM_REWARD_CLEAR_ERROR";
|
||||||
export const FETCH_REWARD_CONTENT_COMPLETED = "FETCH_REWARD_CONTENT_COMPLETED";
|
export const FETCH_REWARD_CONTENT_COMPLETED = "FETCH_REWARD_CONTENT_COMPLETED";
|
||||||
|
|
||||||
|
// Supports
|
||||||
|
export const SUPPORT_TRANSACTION_STARTED = "SUPPORT_TRANSACTION_STARTED";
|
||||||
|
export const SUPPORT_TRANSACTION_COMPLETED = "SUPPORT_TRANSACTION_COMPLETED";
|
||||||
|
export const SUPPORT_TRANSACTION_FAILED = "SUPPORT_TRANSACTION_FAILED";
|
||||||
|
|
||||||
//Language
|
//Language
|
||||||
export const DOWNLOAD_LANGUAGE_SUCCEEDED = "DOWNLOAD_LANGUAGE_SUCCEEDED";
|
export const DOWNLOAD_LANGUAGE_SUCCEEDED = "DOWNLOAD_LANGUAGE_SUCCEEDED";
|
||||||
export const DOWNLOAD_LANGUAGE_FAILED = "DOWNLOAD_LANGUAGE_FAILED";
|
export const DOWNLOAD_LANGUAGE_FAILED = "DOWNLOAD_LANGUAGE_FAILED";
|
||||||
|
|
|
@ -7,5 +7,7 @@ export const UPGRADE = "upgrade";
|
||||||
export const WELCOME = "welcome";
|
export const WELCOME = "welcome";
|
||||||
export const FIRST_REWARD = "first_reward";
|
export const FIRST_REWARD = "first_reward";
|
||||||
export const AUTHENTICATION_FAILURE = "auth_failure";
|
export const AUTHENTICATION_FAILURE = "auth_failure";
|
||||||
|
export const TRANSACTION_FAILED = "transaction_failed";
|
||||||
|
export const INSUFFICIENT_BALANCE = "insufficient_balance";
|
||||||
export const REWARD_APPROVAL_REQUIRED = "reward_approval_required";
|
export const REWARD_APPROVAL_REQUIRED = "reward_approval_required";
|
||||||
export const CREDIT_INTRO = "credit_intro";
|
export const CREDIT_INTRO = "credit_intro";
|
||||||
|
|
16
ui/js/modal/modalInsufficientBalance/index.js
Normal file
16
ui/js/modal/modalInsufficientBalance/index.js
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
import React from "react";
|
||||||
|
import { connect } from "react-redux";
|
||||||
|
import { doCloseModal, doNavigate } from "actions/app";
|
||||||
|
import ModalInsufficientBalance from "./view";
|
||||||
|
|
||||||
|
const select = state => ({});
|
||||||
|
|
||||||
|
const perform = dispatch => ({
|
||||||
|
addBalance: () => {
|
||||||
|
dispatch(doNavigate("/wallet"));
|
||||||
|
dispatch(doCloseModal());
|
||||||
|
},
|
||||||
|
closeModal: () => dispatch(doCloseModal()),
|
||||||
|
});
|
||||||
|
|
||||||
|
export default connect(select, perform)(ModalInsufficientBalance);
|
26
ui/js/modal/modalInsufficientBalance/view.jsx
Normal file
26
ui/js/modal/modalInsufficientBalance/view.jsx
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
import React from "react";
|
||||||
|
import { Modal } from "modal/modal";
|
||||||
|
|
||||||
|
class ModalInsufficientBalance extends React.PureComponent {
|
||||||
|
render() {
|
||||||
|
const { addBalance, closeModal } = this.props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
isOpen={true}
|
||||||
|
type="confirm"
|
||||||
|
contentLabel={__("Not enough credits")}
|
||||||
|
confirmButtonLabel={__("Get Credits")}
|
||||||
|
abortButtonLabel={__("Cancel")}
|
||||||
|
onAborted={closeModal}
|
||||||
|
onConfirmed={addBalance}
|
||||||
|
>
|
||||||
|
{__(
|
||||||
|
"Insufficient balance: after this transaction you would have less than 0 LBCs in your wallet."
|
||||||
|
)}
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ModalInsufficientBalance;
|
|
@ -7,8 +7,10 @@ import ModalUpgrade from "modal/modalUpgrade";
|
||||||
import ModalWelcome from "modal/modalWelcome";
|
import ModalWelcome from "modal/modalWelcome";
|
||||||
import ModalFirstReward from "modal/modalFirstReward";
|
import ModalFirstReward from "modal/modalFirstReward";
|
||||||
import ModalRewardApprovalRequired from "modal/modalRewardApprovalRequired";
|
import ModalRewardApprovalRequired from "modal/modalRewardApprovalRequired";
|
||||||
import * as modals from "constants/modal_types";
|
|
||||||
import ModalCreditIntro from "modal/modalCreditIntro";
|
import ModalCreditIntro from "modal/modalCreditIntro";
|
||||||
|
import ModalTransactionFailed from "modal/modalTransactionFailed";
|
||||||
|
import ModalInsufficientBalance from "modal/modalInsufficientBalance";
|
||||||
|
import * as modals from "constants/modal_types";
|
||||||
|
|
||||||
class ModalRouter extends React.PureComponent {
|
class ModalRouter extends React.PureComponent {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
|
@ -115,6 +117,10 @@ class ModalRouter extends React.PureComponent {
|
||||||
return <ModalAuthFailure />;
|
return <ModalAuthFailure />;
|
||||||
case modals.CREDIT_INTRO:
|
case modals.CREDIT_INTRO:
|
||||||
return <ModalCreditIntro />;
|
return <ModalCreditIntro />;
|
||||||
|
case modals.TRANSACTION_FAILED:
|
||||||
|
return <ModalTransactionFailed />;
|
||||||
|
case modals.INSUFFICIENT_BALANCE:
|
||||||
|
return <ModalInsufficientBalance />;
|
||||||
case modals.REWARD_APPROVAL_REQUIRED:
|
case modals.REWARD_APPROVAL_REQUIRED:
|
||||||
return <ModalRewardApprovalRequired />;
|
return <ModalRewardApprovalRequired />;
|
||||||
default:
|
default:
|
||||||
|
|
12
ui/js/modal/modalTransactionFailed/index.js
Normal file
12
ui/js/modal/modalTransactionFailed/index.js
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
import React from "react";
|
||||||
|
import { connect } from "react-redux";
|
||||||
|
import { doCloseModal } from "actions/app";
|
||||||
|
import ModalTransactionFailed from "./view";
|
||||||
|
|
||||||
|
const select = state => ({});
|
||||||
|
|
||||||
|
const perform = dispatch => ({
|
||||||
|
closeModal: () => dispatch(doCloseModal()),
|
||||||
|
});
|
||||||
|
|
||||||
|
export default connect(select, perform)(ModalTransactionFailed);
|
20
ui/js/modal/modalTransactionFailed/view.jsx
Normal file
20
ui/js/modal/modalTransactionFailed/view.jsx
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
import React from "react";
|
||||||
|
import { Modal } from "modal/modal";
|
||||||
|
|
||||||
|
class ModalTransactionFailed extends React.PureComponent {
|
||||||
|
render() {
|
||||||
|
const { closeModal } = this.props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
isOpen={true}
|
||||||
|
contentLabel={__("Transaction failed")}
|
||||||
|
onConfirmed={closeModal}
|
||||||
|
>
|
||||||
|
{__("Something went wrong")}:
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ModalTransactionFailed;
|
|
@ -3,6 +3,7 @@ import ReactMarkdown from "react-markdown";
|
||||||
import lbry from "lbry.js";
|
import lbry from "lbry.js";
|
||||||
import lbryuri from "lbryuri.js";
|
import lbryuri from "lbryuri.js";
|
||||||
import Video from "component/video";
|
import Video from "component/video";
|
||||||
|
import TipLink from "component/tipLink";
|
||||||
import { Thumbnail } from "component/common";
|
import { Thumbnail } from "component/common";
|
||||||
import FilePrice from "component/filePrice";
|
import FilePrice from "component/filePrice";
|
||||||
import FileActions from "component/fileActions";
|
import FileActions from "component/fileActions";
|
||||||
|
@ -42,6 +43,13 @@ const FormatItem = props => {
|
||||||
};
|
};
|
||||||
|
|
||||||
class FilePage extends React.PureComponent {
|
class FilePage extends React.PureComponent {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
showTipBox: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
this.fetchFileInfo(this.props);
|
this.fetchFileInfo(this.props);
|
||||||
this.fetchCostInfo(this.props);
|
this.fetchCostInfo(this.props);
|
||||||
|
@ -63,6 +71,18 @@ class FilePage extends React.PureComponent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleTipShow() {
|
||||||
|
this.setState({
|
||||||
|
showTipBox: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
handleTipHide() {
|
||||||
|
this.setState({
|
||||||
|
showTipBox: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
claim,
|
claim,
|
||||||
|
@ -73,6 +93,8 @@ class FilePage extends React.PureComponent {
|
||||||
rewardedContentClaimIds,
|
rewardedContentClaimIds,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
|
const { showTipBox } = this.state;
|
||||||
|
|
||||||
if (!claim || !metadata) {
|
if (!claim || !metadata) {
|
||||||
return (
|
return (
|
||||||
<span className="empty">{__("Empty claim or metadata info.")}</span>
|
<span className="empty">{__("Empty claim or metadata info.")}</span>
|
||||||
|
@ -135,18 +157,22 @@ class FilePage extends React.PureComponent {
|
||||||
: uriIndicator}
|
: uriIndicator}
|
||||||
</div>
|
</div>
|
||||||
<div className="card__actions">
|
<div className="card__actions">
|
||||||
<FileActions uri={uri} />
|
<FileActions
|
||||||
|
uri={uri}
|
||||||
|
onTipShow={this.handleTipShow.bind(this)}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="card__content card__subtext card__subtext card__subtext--allow-newlines">
|
{!showTipBox &&
|
||||||
<ReactMarkdown
|
<div className="card__content card__subtext card__subtext card__subtext--allow-newlines">
|
||||||
source={(metadata && metadata.description) || ""}
|
<ReactMarkdown
|
||||||
escapeHtml={true}
|
source={(metadata && metadata.description) || ""}
|
||||||
disallowedTypes={["Heading", "HtmlInline", "HtmlBlock"]}
|
escapeHtml={true}
|
||||||
/>
|
disallowedTypes={["Heading", "HtmlInline", "HtmlBlock"]}
|
||||||
</div>
|
/>
|
||||||
|
</div>}
|
||||||
</div>
|
</div>
|
||||||
{metadata && claim
|
{metadata && claim && !showTipBox
|
||||||
? <div className="card__content">
|
? <div className="card__content">
|
||||||
<FormatItem
|
<FormatItem
|
||||||
metadata={metadata}
|
metadata={metadata}
|
||||||
|
@ -155,13 +181,21 @@ class FilePage extends React.PureComponent {
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
: ""}
|
: ""}
|
||||||
<div className="card__content">
|
{showTipBox
|
||||||
<Link
|
? <TipLink
|
||||||
href={`https://lbry.io/dmca?claim_id=${claim.claim_id}`}
|
onTipShow={this.handleTipShow.bind(this)}
|
||||||
label={__("report")}
|
onTipHide={this.handleTipHide.bind(this)}
|
||||||
className="button-text-help"
|
claim_id={claim.claim_id}
|
||||||
/>
|
/>
|
||||||
</div>
|
: ""}
|
||||||
|
{!showTipBox &&
|
||||||
|
<div className="card__content">
|
||||||
|
<Link
|
||||||
|
href={`https://lbry.io/dmca?claim_id=${claim.claim_id}`}
|
||||||
|
label={__("report")}
|
||||||
|
className="button-text-help"
|
||||||
|
/>
|
||||||
|
</div>}
|
||||||
</section>
|
</section>
|
||||||
</main>
|
</main>
|
||||||
);
|
);
|
||||||
|
|
|
@ -189,6 +189,31 @@ reducers[types.CREATE_CHANNEL_COMPLETED] = function(state, action) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
reducers[types.SUPPORT_TRANSACTION_STARTED] = function(state, action) {
|
||||||
|
const newSupportTransaction = Object.assign({}, state.supportTransaction, {
|
||||||
|
sendingSupport: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
return Object.assign({}, state, {
|
||||||
|
supportTransaction: newSupportTransaction,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
reducers[types.SUPPORT_TRANSACTION_COMPLETED] = function(state, action) {
|
||||||
|
return Object.assign({}, state);
|
||||||
|
};
|
||||||
|
|
||||||
|
reducers[types.SUPPORT_TRANSACTION_FAILED] = function(state, action) {
|
||||||
|
const newSupportTransaction = Object.assign({}, state.supportTransaction, {
|
||||||
|
sendingSupport: false,
|
||||||
|
error: action.data.error,
|
||||||
|
});
|
||||||
|
|
||||||
|
return Object.assign({}, state, {
|
||||||
|
supportTransaction: newSupportTransaction,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
export default function reducer(state = defaultState, action) {
|
export default function reducer(state = defaultState, action) {
|
||||||
const handler = reducers[action.type];
|
const handler = reducers[action.type];
|
||||||
if (handler) return handler(state, action);
|
if (handler) return handler(state, action);
|
||||||
|
|
|
@ -28,6 +28,10 @@ export const selectTransactionItems = createSelector(
|
||||||
id: txid,
|
id: txid,
|
||||||
date: tx.timestamp ? new Date(parseInt(tx.timestamp) * 1000) : null,
|
date: tx.timestamp ? new Date(parseInt(tx.timestamp) * 1000) : null,
|
||||||
amount: parseFloat(tx.value),
|
amount: parseFloat(tx.value),
|
||||||
|
claim_info: tx.claim_info,
|
||||||
|
support_info: tx.support_info,
|
||||||
|
update_info: tx.update_info,
|
||||||
|
fee: tx.fee,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
return transactionItems.reverse();
|
return transactionItems.reverse();
|
||||||
|
|
Loading…
Add table
Reference in a new issue