diff --git a/CHANGELOG.md b/CHANGELOG.md index f5936d296..b38bfb0f2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,8 +8,8 @@ Web UI version numbers should always match the corresponding version of LBRY App ## [Unreleased] ### Added - * - * + * Added a tipping button to send LBRY Credits to the publisher + * ### Changed * diff --git a/ui/js/actions/claims.js b/ui/js/actions/claims.js new file mode 100644 index 000000000..71f94852c --- /dev/null +++ b/ui/js/actions/claims.js @@ -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); + }; +} diff --git a/ui/js/actions/wallet.js b/ui/js/actions/wallet.js index e97675d18..368247d16 100644 --- a/ui/js/actions/wallet.js +++ b/ui/js/actions/wallet.js @@ -5,7 +5,8 @@ import { selectDraftTransactionAmount, selectBalance, } 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) { return { @@ -22,7 +23,7 @@ export function doFetchTransactions() { type: types.FETCH_TRANSACTIONS_STARTED, }); - lbry.transaction_list().then(results => { + lbry.transaction_list({ include_tip_info: true }).then(results => { dispatch({ type: types.FETCH_TRANSACTIONS_COMPLETED, data: { @@ -72,8 +73,8 @@ export function doSendDraftTransaction() { const balance = selectBalance(state); const amount = selectDraftTransactionAmount(state); - if (balance - amount < 1) { - return dispatch(doOpenModal("insufficientBalance")); + if (balance - amount <= 0) { + return dispatch(doOpenModal(modals.INSUFFICIENT_BALANCE)); } dispatch({ @@ -85,13 +86,19 @@ export function doSendDraftTransaction() { dispatch({ type: types.SEND_TRANSACTION_COMPLETED, }); - dispatch(doOpenModal("transactionSuccessful")); + dispatch( + doShowSnackBar({ + message: __(`You sent ${amount} LBC`), + linkText: __("History"), + linkTarget: __("/wallet"), + }) + ); } else { dispatch({ type: types.SEND_TRANSACTION_FAILED, data: { error: results }, }); - dispatch(doOpenModal("transactionFailed")); + dispatch(doOpenModal(modals.TRANSACTION_FAILED)); } }; @@ -100,7 +107,7 @@ export function doSendDraftTransaction() { type: types.SEND_TRANSACTION_FAILED, data: { error: error.message }, }); - dispatch(doOpenModal("transactionFailed")); + dispatch(doOpenModal(modals.TRANSACTION_FAILED)); }; lbry diff --git a/ui/js/component/app/index.js b/ui/js/component/app/index.js index 38527d94b..574c5f862 100644 --- a/ui/js/component/app/index.js +++ b/ui/js/component/app/index.js @@ -2,10 +2,7 @@ import React from "react"; import { connect } from "react-redux"; import { selectPageTitle } from "selectors/navigation"; import { selectUser } from "selectors/user"; -import { - doCheckUpgradeAvailable, - doAlertError, -} from "actions/app"; +import { doCheckUpgradeAvailable, doAlertError } from "actions/app"; import { doRecordScroll } from "actions/navigation"; import { doFetchRewardedContent } from "actions/content"; import { doUpdateBalance } from "actions/wallet"; diff --git a/ui/js/component/common.js b/ui/js/component/common.js index d92669262..8af8733c2 100644 --- a/ui/js/component/common.js +++ b/ui/js/component/common.js @@ -71,6 +71,7 @@ export class CreditAmount extends React.PureComponent { showFullPrice: React.PropTypes.bool, showPlus: React.PropTypes.bool, look: React.PropTypes.oneOf(["indicator", "plain"]), + fee: React.PropTypes.bool, }; static defaultProps = { @@ -81,6 +82,7 @@ export class CreditAmount extends React.PureComponent { showFree: false, showFullPrice: false, showPlus: false, + fee: false, }; render() { @@ -117,7 +119,10 @@ export class CreditAmount extends React.PureComponent { return ( diff --git a/ui/js/component/fileActions/index.js b/ui/js/component/fileActions/index.js index 759abee47..02fb213da 100644 --- a/ui/js/component/fileActions/index.js +++ b/ui/js/component/fileActions/index.js @@ -11,7 +11,10 @@ import { makeSelectCostInfoForUri } from "selectors/cost_info"; import { doCloseModal, doOpenModal } from "actions/app"; import { doFetchAvailability } from "actions/availability"; 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 FileActions from "./view"; @@ -22,6 +25,7 @@ const makeSelect = () => { const selectCostInfoForUri = makeSelectCostInfoForUri(); const selectLoadingForUri = makeSelectLoadingForUri(); const selectClaimForUriIsMine = makeSelectClaimForUriIsMine(); + const selectClaimForUri = makeSelectClaimForUri(); const select = (state, props) => ({ fileInfo: selectFileInfoForUri(state, props), @@ -33,6 +37,7 @@ const makeSelect = () => { costInfo: selectCostInfoForUri(state, props), loading: selectLoadingForUri(state, props), claimIsMine: selectClaimForUriIsMine(state, props), + claimInfo: selectClaimForUri(state, props), }); return select; diff --git a/ui/js/component/fileActions/view.jsx b/ui/js/component/fileActions/view.jsx index 73b48ba3b..2642ea7e4 100644 --- a/ui/js/component/fileActions/view.jsx +++ b/ui/js/component/fileActions/view.jsx @@ -57,6 +57,10 @@ class FileActions extends React.PureComponent { this.props.loadVideo(this.props.uri); } + handleSupportButtonClicked() { + this.props.onTipShow(); + } + render() { const { fileInfo, @@ -73,6 +77,7 @@ class FileActions extends React.PureComponent { costInfo, loading, claimIsMine, + claimInfo, } = this.props; const metadata = fileInfo ? fileInfo.metadata : null, @@ -166,6 +171,12 @@ class FileActions extends React.PureComponent { return (
{content} + {showMenu ?
diff --git a/ui/js/component/publishForm/view.jsx b/ui/js/component/publishForm/view.jsx index fd0886935..f770ae38e 100644 --- a/ui/js/component/publishForm/view.jsx +++ b/ui/js/component/publishForm/view.jsx @@ -116,7 +116,7 @@ class PublishForm extends React.PureComponent { ? { channel_name: this.state.channel } : {}), }; - + const { source } = this.state; if (this.refs.file.getValue() !== "") { @@ -262,7 +262,7 @@ class PublishForm extends React.PureComponent { } handlePrefillClicked() { - const claimInfo = this.myClaimInfo(); + const claimInfo = this.myClaimInfo(); const { source } = claimInfo.value.stream; const { license, diff --git a/ui/js/component/tipLink/index.js b/ui/js/component/tipLink/index.js new file mode 100644 index 000000000..b43f225ac --- /dev/null +++ b/ui/js/component/tipLink/index.js @@ -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); diff --git a/ui/js/component/tipLink/view.jsx b/ui/js/component/tipLink/view.jsx new file mode 100644 index 000000000..831806d48 --- /dev/null +++ b/ui/js/component/tipLink/view.jsx @@ -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 ( +
+
+

{__("Support")}

+
+
+ {__( + "Support the creator and the success of their content by sending a tip. " + )} + +
+
+ this.handleSupportPriceChange(event)} + /> +
+
+ + +
+
+ ); + } +} + +export default TipLink; diff --git a/ui/js/component/transactionList/index.js b/ui/js/component/transactionList/index.js index 9e2d9ec6b..0b4d0e1af 100644 --- a/ui/js/component/transactionList/index.js +++ b/ui/js/component/transactionList/index.js @@ -1,5 +1,10 @@ import React from "react"; import { connect } from "react-redux"; +import { doNavigate } from "actions/navigation"; 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); diff --git a/ui/js/component/transactionList/internal/TransactionListBody.jsx b/ui/js/component/transactionList/internal/TransactionListBody.jsx new file mode 100644 index 000000000..12beb2e8d --- /dev/null +++ b/ui/js/component/transactionList/internal/TransactionListBody.jsx @@ -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 ( + this.props.navigate(uri)}> + {claim_name} + + ); + } + + 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 ( + + + {date + ? date.toLocaleDateString("en-US", options) + : + {__("(Transaction pending)")} + } + + + +
+ + + + {this.getClaimLink(item.claim_name, item.claim_id)} + + + + + + ); + }) + : + + {date + ? date.toLocaleDateString("en-US", options) + : + {__("(Transaction pending)")} + } + + + +
+ + + + + + ; + } + + 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 ( + + {transactions + .filter(this.filterList, this) + .filter(this.removeFeeTx, this) + .map(this.renderBody, this)} + + ); + } +} + +export default TransactionTableBody; diff --git a/ui/js/component/transactionList/internal/TransactionListHeader.jsx b/ui/js/component/transactionList/internal/TransactionListHeader.jsx new file mode 100644 index 000000000..52f735fb9 --- /dev/null +++ b/ui/js/component/transactionList/internal/TransactionListHeader.jsx @@ -0,0 +1,19 @@ +import React from "react"; + +class TransactionTableHeader extends React.PureComponent { + render() { + const { filter } = this.props; + return ( + + + {__("Date")} + {__("Amount(Fee)")} + {filter != "unfiltered" && {__("Claim Name")} } + {__("Transaction")} + + + ); + } +} + +export default TransactionTableHeader; diff --git a/ui/js/component/transactionList/view.jsx b/ui/js/component/transactionList/view.jsx index 0ad7f4eeb..ee78e2acc 100644 --- a/ui/js/component/transactionList/view.jsx +++ b/ui/js/component/transactionList/view.jsx @@ -1,57 +1,65 @@ import React from "react"; -import LinkTransaction from "component/linkTransaction"; -import { CreditAmount } from "component/common"; +import TransactionTableHeader from "./internal/TransactionListHeader"; +import TransactionTableBody from "./internal/TransactionListBody"; +import FormField from "component/formField"; -const TransactionList = props => { - const { emptyMessage, transactions } = props; +class TransactionList extends React.PureComponent { + 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 ( +
+ {emptyMessage || __("No transactions to list.")} +
+ ); + } - if (!transactions || !transactions.length) { return ( -
- {emptyMessage || __("No transactions to list.")} +
+ + {__("Filter")} {" "} + + + + + + + + + + + +
); } - - return ( - - - - - - - - - - {transactions.map(item => { - return ( - - - - - - ); - })} - -
{__("Date")}{__("Amount")}{__("Transaction")}
- {item.date - ? item.date.toLocaleDateString() + - " " + - item.date.toLocaleTimeString() - : - {__("(Transaction pending)")} - } - - {" "} - - -
- ); -}; +} export default TransactionList; diff --git a/ui/js/component/walletSend/index.js b/ui/js/component/walletSend/index.js index ab13440db..50712e14c 100644 --- a/ui/js/component/walletSend/index.js +++ b/ui/js/component/walletSend/index.js @@ -1,12 +1,10 @@ import React from "react"; import { connect } from "react-redux"; -import { doCloseModal } from "actions/app"; import { doSendDraftTransaction, doSetDraftTransactionAmount, doSetDraftTransactionAddress, } from "actions/wallet"; -import { selectCurrentModal } from "selectors/app"; import { selectDraftTransactionAmount, selectDraftTransactionAddress, @@ -15,13 +13,11 @@ import { import WalletSend from "./view"; const select = state => ({ - modal: selectCurrentModal(state), address: selectDraftTransactionAddress(state), amount: selectDraftTransactionAmount(state), }); const perform = dispatch => ({ - closeModal: () => dispatch(doCloseModal()), sendToAddress: () => dispatch(doSendDraftTransaction()), setAmount: event => dispatch(doSetDraftTransactionAmount(event.target.value)), setAddress: event => diff --git a/ui/js/component/walletSend/view.jsx b/ui/js/component/walletSend/view.jsx index 680106584..8c41d1000 100644 --- a/ui/js/component/walletSend/view.jsx +++ b/ui/js/component/walletSend/view.jsx @@ -4,15 +4,7 @@ import Modal from "modal/modal"; import { FormRow } from "component/form"; const WalletSend = props => { - const { - sendToAddress, - closeModal, - modal, - setAmount, - setAddress, - amount, - address, - } = props; + const { sendToAddress, setAmount, setAddress, amount, address } = props; return (
@@ -53,32 +45,6 @@ const WalletSend = props => {
- {modal == "insufficientBalance" && - - {__( - "Insufficient balance: after this transaction you would have less than 1 LBC in your wallet." - )} - } - {modal == "transactionSuccessful" && - - {__("Your transaction was successfully placed in the queue.")} - } - {modal == "transactionFailed" && - - {__("Something went wrong")}: - }
); }; diff --git a/ui/js/constants/action_types.js b/ui/js/constants/action_types.js index 84c8e0e06..97f321f31 100644 --- a/ui/js/constants/action_types.js +++ b/ui/js/constants/action_types.js @@ -131,6 +131,11 @@ export const CLAIM_REWARD_FAILURE = "CLAIM_REWARD_FAILURE"; export const CLAIM_REWARD_CLEAR_ERROR = "CLAIM_REWARD_CLEAR_ERROR"; 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 export const DOWNLOAD_LANGUAGE_SUCCEEDED = "DOWNLOAD_LANGUAGE_SUCCEEDED"; export const DOWNLOAD_LANGUAGE_FAILED = "DOWNLOAD_LANGUAGE_FAILED"; diff --git a/ui/js/constants/modal_types.js b/ui/js/constants/modal_types.js index 7dd057046..09ddb8451 100644 --- a/ui/js/constants/modal_types.js +++ b/ui/js/constants/modal_types.js @@ -7,5 +7,7 @@ export const UPGRADE = "upgrade"; export const WELCOME = "welcome"; export const FIRST_REWARD = "first_reward"; 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 CREDIT_INTRO = "credit_intro"; diff --git a/ui/js/modal/modalInsufficientBalance/index.js b/ui/js/modal/modalInsufficientBalance/index.js new file mode 100644 index 000000000..c56232caf --- /dev/null +++ b/ui/js/modal/modalInsufficientBalance/index.js @@ -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); diff --git a/ui/js/modal/modalInsufficientBalance/view.jsx b/ui/js/modal/modalInsufficientBalance/view.jsx new file mode 100644 index 000000000..5b43583cd --- /dev/null +++ b/ui/js/modal/modalInsufficientBalance/view.jsx @@ -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 ( + + {__( + "Insufficient balance: after this transaction you would have less than 0 LBCs in your wallet." + )} + + ); + } +} + +export default ModalInsufficientBalance; diff --git a/ui/js/modal/modalRouter/view.jsx b/ui/js/modal/modalRouter/view.jsx index a21851c3b..47ff2d80c 100644 --- a/ui/js/modal/modalRouter/view.jsx +++ b/ui/js/modal/modalRouter/view.jsx @@ -7,8 +7,10 @@ import ModalUpgrade from "modal/modalUpgrade"; import ModalWelcome from "modal/modalWelcome"; import ModalFirstReward from "modal/modalFirstReward"; import ModalRewardApprovalRequired from "modal/modalRewardApprovalRequired"; -import * as modals from "constants/modal_types"; 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 { constructor(props) { @@ -115,6 +117,10 @@ class ModalRouter extends React.PureComponent { return ; case modals.CREDIT_INTRO: return ; + case modals.TRANSACTION_FAILED: + return ; + case modals.INSUFFICIENT_BALANCE: + return ; case modals.REWARD_APPROVAL_REQUIRED: return ; default: diff --git a/ui/js/modal/modalTransactionFailed/index.js b/ui/js/modal/modalTransactionFailed/index.js new file mode 100644 index 000000000..4b370a7c8 --- /dev/null +++ b/ui/js/modal/modalTransactionFailed/index.js @@ -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); diff --git a/ui/js/modal/modalTransactionFailed/view.jsx b/ui/js/modal/modalTransactionFailed/view.jsx new file mode 100644 index 000000000..b2d4a3558 --- /dev/null +++ b/ui/js/modal/modalTransactionFailed/view.jsx @@ -0,0 +1,20 @@ +import React from "react"; +import { Modal } from "modal/modal"; + +class ModalTransactionFailed extends React.PureComponent { + render() { + const { closeModal } = this.props; + + return ( + + {__("Something went wrong")}: + + ); + } +} + +export default ModalTransactionFailed; diff --git a/ui/js/page/file/view.jsx b/ui/js/page/file/view.jsx index 8459ed01c..08568c5b5 100644 --- a/ui/js/page/file/view.jsx +++ b/ui/js/page/file/view.jsx @@ -3,6 +3,7 @@ import ReactMarkdown from "react-markdown"; import lbry from "lbry.js"; import lbryuri from "lbryuri.js"; import Video from "component/video"; +import TipLink from "component/tipLink"; import { Thumbnail } from "component/common"; import FilePrice from "component/filePrice"; import FileActions from "component/fileActions"; @@ -33,6 +34,13 @@ const FormatItem = props => { }; class FilePage extends React.PureComponent { + constructor(props) { + super(props); + this.state = { + showTipBox: false, + }; + } + componentDidMount() { this.fetchFileInfo(this.props); this.fetchCostInfo(this.props); @@ -54,6 +62,18 @@ class FilePage extends React.PureComponent { } } + handleTipShow() { + this.setState({ + showTipBox: true, + }); + } + + handleTipHide() { + this.setState({ + showTipBox: false, + }); + } + render() { const { claim, @@ -64,6 +84,8 @@ class FilePage extends React.PureComponent { rewardedContentClaimIds, } = this.props; + const { showTipBox } = this.state; + if (!claim || !metadata) { return ( {__("Empty claim or metadata info.")} @@ -126,29 +148,41 @@ class FilePage extends React.PureComponent { : uriIndicator}
- +
-
- -
+ {!showTipBox && +
+ +
} - {metadata + {metadata && !showTipBox ?
: ""} -
- -
+ {showTipBox + ? + : ""} + {!showTipBox && +
+ +
} ); diff --git a/ui/js/reducers/claims.js b/ui/js/reducers/claims.js index a8d86e929..4b830731d 100644 --- a/ui/js/reducers/claims.js +++ b/ui/js/reducers/claims.js @@ -190,6 +190,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) { const handler = reducers[action.type]; if (handler) return handler(state, action); diff --git a/ui/js/selectors/wallet.js b/ui/js/selectors/wallet.js index 84ca37f8e..60e0dd1aa 100644 --- a/ui/js/selectors/wallet.js +++ b/ui/js/selectors/wallet.js @@ -28,6 +28,10 @@ export const selectTransactionItems = createSelector( id: txid, date: tx.timestamp ? new Date(parseInt(tx.timestamp) * 1000) : null, 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();