Merge pull request #46 from lbryio/tx_log

Transaction log on Publish page
This commit is contained in:
alexliebowitz 2016-08-30 05:15:49 -04:00 committed by GitHub
commit aa7abb2451
8 changed files with 231 additions and 36 deletions

View file

@ -4,14 +4,11 @@ var App = React.createClass({
var match, param, val, viewingPage, var match, param, val, viewingPage,
drawerOpenRaw = sessionStorage.getItem('drawerOpen'); drawerOpenRaw = sessionStorage.getItem('drawerOpen');
[match, param, val] = window.location.search.match(/\??([^=]*)(?:=(.*))?/); [match, viewingPage, val] = window.location.search.match(/\??([^=]*)(?:=(.*))?/);
if (param && ['settings', 'discover', 'help', 'start', 'watch', 'report', 'files', 'claim', 'show', 'wallet', 'publish'].indexOf(param) != -1) {
viewingPage = param;
}
return { return {
viewingPage: viewingPage ? viewingPage : 'discover', viewingPage: viewingPage,
drawerOpen: drawerOpenRaw !== null ? JSON.parse(drawerOpenRaw) : true, drawerOpen: drawerOpenRaw !== null ? JSON.parse(drawerOpenRaw) : true,
pageArgs: val, pageArgs: val,
}; };
@ -72,12 +69,28 @@ var App = React.createClass({
pageArgs: term pageArgs: term
}); });
}, },
getHeaderLinks: function()
{
switch(this.state.viewingPage)
{
case 'wallet':
case 'send':
case 'receive':
case 'claim':
return {
'?wallet' : 'Overview',
'?send' : 'Send',
'?receive' : 'Receive',
'?claim' : 'Claim Beta Code'
};
default:
return null;
}
},
getMainContent: function() getMainContent: function()
{ {
switch(this.state.viewingPage) switch(this.state.viewingPage)
{ {
case 'discover':
return <DiscoverPage query={this.state.pageArgs} />;
case 'settings': case 'settings':
return <SettingsPage />; return <SettingsPage />;
case 'help': case 'help':
@ -93,23 +106,33 @@ var App = React.createClass({
case 'claim': case 'claim':
return <ClaimCodePage />; return <ClaimCodePage />;
case 'wallet': case 'wallet':
return <WalletPage />; case 'send':
case 'receive':
return <WalletPage viewingPage={this.state.viewingPage} />;
case 'send':
return <SendPage />;
case 'receive':
return <ReceivePage />;
case 'show': case 'show':
return <DetailPage name={this.state.pageArgs} />; return <DetailPage name={this.state.pageArgs} />;
case 'publish': case 'publish':
return <PublishPage />; return <PublishPage />;
case 'discover':
default:
return <DiscoverPage query={this.state.pageArgs} />;
} }
}, },
render: function() { render: function() {
var mainContent = this.getMainContent(); var mainContent = this.getMainContent(),
headerLinks = this.getHeaderLinks();
return ( return (
this.state.viewingPage == 'watch' ? this.state.viewingPage == 'watch' ?
mainContent : mainContent :
<div id="window" className={ this.state.drawerOpen ? 'drawer-open' : 'drawer-closed' }> <div id="window" className={ this.state.drawerOpen ? 'drawer-open' : 'drawer-closed' }>
<Drawer onCloseDrawer={this.closeDrawer} viewingPage={this.state.viewingPage} /> <Drawer onCloseDrawer={this.closeDrawer} viewingPage={this.state.viewingPage} />
<div id="main-content"> <div id="main-content" className={ headerLinks ? 'with-sub-nav' : 'no-sub-nav' }>
<Header onOpenDrawer={this.openDrawer} onSearch={this.onSearch} /> <Header onOpenDrawer={this.openDrawer} onSearch={this.onSearch} links={headerLinks} viewingPage={this.state.viewingPage} />
{mainContent} {mainContent}
</div> </div>
</div> </div>

View file

@ -77,9 +77,10 @@ var CurrencySymbol = React.createClass({
var CreditAmount = React.createClass({ var CreditAmount = React.createClass({
propTypes: { propTypes: {
amount: React.PropTypes.number, amount: React.PropTypes.number,
precision: React.PropTypes.number
}, },
render: function() { render: function() {
var formattedAmount = lbry.formatCredits(this.props.amount); var formattedAmount = lbry.formatCredits(this.props.amount, this.props.precision ? this.props.precision : 1);
return ( return (
<span className="credit-amount"> <span className="credit-amount">
<span style={creditAmountStyle}>{formattedAmount} {parseFloat(formattedAmount) == 1.0 ? 'credit' : 'credits'}</span> <span style={creditAmountStyle}>{formattedAmount} {parseFloat(formattedAmount) == 1.0 ? 'credit' : 'credits'}</span>

View file

@ -44,14 +44,41 @@ var Header = React.createClass({
}, },
render: function() { render: function() {
return ( return (
<header id="header" className={this.state.isScrolled ? 'header-scrolled' : 'header-unscrolled'}> <header id="header" className={ (this.state.isScrolled ? 'header-scrolled' : 'header-unscrolled') + ' ' + (this.props.links ? 'header-with-subnav' : 'header-no-subnav') }>
<Link onClick={this.props.onOpenDrawer} icon="icon-bars" className="open-drawer-link" /> <div className="header-top-bar">
<h1>{ this.state.title }</h1> <Link onClick={this.props.onOpenDrawer} icon="icon-bars" className="open-drawer-link" />
<div className="header-search"> <h1>{ this.state.title }</h1>
<input type="search" onChange={this.onQueryChange} <div className="header-search">
placeholder="Find movies, music, games, and more"/> <input type="search" onChange={this.onQueryChange}
placeholder="Find movies, music, games, and more"/>
</div>
</div> </div>
{
this.props.links ?
<SubHeader links={this.props.links} viewingPage={this.props.viewingPage} /> :
''
}
</header> </header>
); );
} }
});
var SubHeader = React.createClass({
render: function() {
var links = [],
viewingUrl = '?' + this.props.viewingPage;
for (let link of Object.keys(this.props.links)) {
links.push(
<a href={link} key={link} className={ viewingUrl == link ? 'sub-header-selected' : 'sub-header-unselected' }>
{this.props.links[link]}
</a>
);
}
return (
<nav className="sub-header">
{links}
</nav>
);
}
}); });

View file

@ -65,7 +65,7 @@ var ClaimCodePage = React.createClass({
}); });
}, },
handleSkip: function() { handleSkip: function() {
alert('Welcome to LBRY! You can visit the Settings page to redeem an invite code at any time.'); alert('Welcome to LBRY! You can visit the Wallet page to redeem an invite code at any time.');
window.location = '?landing'; window.location = '?landing';
}, },
render: function() { render: function() {

View file

@ -57,7 +57,7 @@ var SendToAddressSection = React.createClass({
return { return {
address: "", address: "",
amount: 0.0, amount: 0.0,
balance: "Checking balance...", balance: <BusyMessage message="Checking balance" />,
results: "", results: "",
} }
}, },
@ -106,7 +106,94 @@ var SendToAddressSection = React.createClass({
} }
}); });
var TransactionList = React.createClass({
getInitialState: function() {
return {
transactionItems: null,
}
},
componentWillMount: function() {
lbry.call('get_transaction_history', {}, (results) => {
if (results.length == 0) {
this.setState({ transactionItems: [] })
} else {
var transactionItems = [],
condensedTransactions = {};
results.forEach(function(tx) {
var txid = tx["txid"];
if (!(txid in condensedTransactions)) {
condensedTransactions[txid] = 0;
}
condensedTransactions[txid] += parseFloat(tx["value"]);
});
results.reverse().forEach(function(tx) {
var txid = tx["txid"];
if (condensedTransactions[txid] && condensedTransactions[txid] > 0)
{
transactionItems.push({
id: txid,
date: new Date(parseInt(tx["timestamp"]) * 1000),
amount: condensedTransactions[txid]
});
delete condensedTransactions[txid];
}
});
this.setState({ transactionItems: transactionItems });
}
});
},
render: function() {
var rows = [];
if (this.state.transactionItems && this.state.transactionItems.length > 0)
{
this.state.transactionItems.forEach(function(item) {
rows.push(
<tr key={item.id}>
<td>{ (item.amount > 0 ? '+' : '' ) + item.amount }</td>
<td>{ item.date.toLocaleDateString() }</td>
<td>{ item.date.toLocaleTimeString() }</td>
<td>
<a className="button-text" href={"https://explorer.lbry.io/tx/"+item.id} target="_blank">{item.id.substr(0, 7)}</a>
</td>
</tr>
);
});
}
return (
<section className="card">
<h3>Transaction History</h3>
{ this.state.transactionItems === null ? <BusyMessage message="Loading transactions" /> : '' }
{ this.state.transactionItems && rows.length === 0 ? <div className="empty">You have no transactions.</div> : '' }
{ this.state.transactionItems && rows.length > 0 ?
<table className="table-standard table-stretch">
<thead>
<tr>
<th>Amount</th>
<th>Date</th>
<th>Time</th>
<th>Transaction</th>
</tr>
</thead>
<tbody>
{rows}
</tbody>
</table>
: ''
}
</section>
);
}
});
var WalletPage = React.createClass({ var WalletPage = React.createClass({
propTypes: {
viewingPage: React.PropTypes.string,
},
componentDidMount: function() { componentDidMount: function() {
document.title = "My Wallet"; document.title = "My Wallet";
}, },
@ -116,14 +203,14 @@ var WalletPage = React.createClass({
*/ */
getInitialState: function() { getInitialState: function() {
return { return {
balance: "Checking balance...", balance: null,
} }
}, },
componentWillMount: function() { componentWillMount: function() {
lbry.getBalance((results) => { lbry.getBalance((results) => {
this.setState({ this.setState({
balance: results, balance: results,
}); })
}); });
}, },
render: function() { render: function() {
@ -131,15 +218,13 @@ var WalletPage = React.createClass({
<main className="page"> <main className="page">
<section className="card"> <section className="card">
<h3>Balance</h3> <h3>Balance</h3>
{this.state.balance} <CurrencySymbol /> { this.state.balance === null ? <BusyMessage message="Checking balance" /> : ''}
</section> { this.state.balance !== null ? <CreditAmount amount={this.state.balance} precision={8} /> : '' }
<SendToAddressSection />
<NewAddressSection />
<section className="card">
<h3>Claim Invite Code</h3>
<Link href="?claim" label="Claim a LBRY beta invite code" button="alt" />
</section> </section>
{ this.props.viewingPage === 'wallet' ? <TransactionList /> : '' }
{ this.props.viewingPage === 'send' ? <SendToAddressSection /> : '' }
{ this.props.viewingPage === 'receive' ? <NewAddressSection /> : '' }
</main> </main>
); );
} }
}); });

View file

@ -67,7 +67,7 @@ $drawer-width: 240px;
#window.drawer-open #window.drawer-open
{ {
#main-content { margin-left: $drawer-width; } #main-content { margin-left: $drawer-width; }
.open-drawer-link { visibility: hidden; } .open-drawer-link { display: none }
#header { padding-left: $drawer-width + $spacing-vertical / 2; } #header { padding-left: $drawer-width + $spacing-vertical / 2; }
} }
@ -75,8 +75,12 @@ $drawer-width: 240px;
{ {
background: $color-primary; background: $color-primary;
color: white; color: white;
height: $header-height; &.header-no-subnav {
padding: $spacing-vertical / 2; height: $header-height;
}
&.header-with-subnav {
height: $header-height * 2;
}
position: fixed; position: fixed;
top: 0; top: 0;
left: 0; left: 0;
@ -89,6 +93,10 @@ $drawer-width: 240px;
box-shadow: $default-box-shadow; box-shadow: $default-box-shadow;
} }
} }
.header-top-bar
{
padding: $spacing-vertical / 2;
}
.header-search .header-search
{ {
margin-left: 60px; margin-left: 60px;
@ -101,13 +109,54 @@ $drawer-width: 240px;
} }
} }
nav.sub-header
{
background: $color-primary;
text-transform: uppercase;
padding: $spacing-vertical / 2;
> a
{
$sub-header-selected-underline-height: 2px;
display: inline-block;
margin: 0 15px;
padding: 0 5px;
line-height: $header-height - $spacing-vertical - $sub-header-selected-underline-height;
color: #e8e8e8;
&:first-child
{
margin-left: 0;
}
&:last-child
{
margin-right: 0;
}
&.sub-header-selected
{
border-bottom: $sub-header-selected-underline-height solid #fff;
color: #fff;
}
&:hover
{
color: #fff;
}
}
}
#main-content #main-content
{ {
background: $color-canvas; background: $color-canvas;
min-height: calc(100vh - 60px); //should be -$header-height, but I'm dumb I guess? It wouldn't work &.no-sub-nav
{
min-height: calc(100vh - 60px); //should be -$header-height, but I'm dumb I guess? It wouldn't work
main { margin-top: $header-height; }
}
&.with-sub-nav
{
min-height: calc(100vh - 120px); //should be -$header-height, but I'm dumb I guess? It wouldn't work
main { margin-top: $header-height * 2; }
}
main main
{ {
margin-top: $header-height;
padding: $spacing-vertical; padding: $spacing-vertical;
} }
h2 h2

View file

@ -195,6 +195,12 @@ input[type="text"], input[type="search"]
color: $color-meta-light; color: $color-meta-light;
} }
.empty
{
color: $color-meta-light;
font-style: italic;
}
.form-row .form-row
{ {
+ .form-row + .form-row
@ -209,4 +215,4 @@ input[type="text"], input[type="search"]
{ {
margin-top: $spacing-vertical; margin-top: $spacing-vertical;
} }
} }

View file

@ -46,4 +46,8 @@ table.table-standard {
} }
} }
} }
}
table.table-stretch {
width: 100%;
} }