better?
merging is hard releasable?
This commit is contained in:
parent
2fb0bf4a14
commit
c7522dc0a5
46 changed files with 519 additions and 276 deletions
|
@ -26,6 +26,10 @@ const { lbrySettings: config } = require("../../../app/package.json");
|
||||||
|
|
||||||
export function doNavigate(path, params = {}, options = {}) {
|
export function doNavigate(path, params = {}, options = {}) {
|
||||||
return function(dispatch, getState) {
|
return function(dispatch, getState) {
|
||||||
|
if (!path) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let url = path;
|
let url = path;
|
||||||
if (params) url = `${url}?${toQueryString(params)}`;
|
if (params) url = `${url}?${toQueryString(params)}`;
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ import * as modals from "constants/modal_types";
|
||||||
import lbryio from "lbryio";
|
import lbryio from "lbryio";
|
||||||
import rewards from "rewards";
|
import rewards from "rewards";
|
||||||
import { selectUnclaimedRewardsByType } from "selectors/rewards";
|
import { selectUnclaimedRewardsByType } from "selectors/rewards";
|
||||||
|
import { selectUserIsRewardApproved } from "selectors/user";
|
||||||
|
|
||||||
export function doRewardList() {
|
export function doRewardList() {
|
||||||
return function(dispatch, getState) {
|
return function(dispatch, getState) {
|
||||||
|
@ -31,14 +32,23 @@ export function doRewardList() {
|
||||||
|
|
||||||
export function doClaimRewardType(rewardType) {
|
export function doClaimRewardType(rewardType) {
|
||||||
return function(dispatch, getState) {
|
return function(dispatch, getState) {
|
||||||
const rewardsByType = selectUnclaimedRewardsByType(getState()),
|
const state = getState(),
|
||||||
reward = rewardsByType[rewardType];
|
rewardsByType = selectUnclaimedRewardsByType(state),
|
||||||
|
reward = rewardsByType[rewardType],
|
||||||
|
userIsRewardApproved = selectUserIsRewardApproved(state);
|
||||||
|
|
||||||
if (reward.transaction_id) {
|
if (reward.transaction_id) {
|
||||||
//already claimed, do nothing
|
//already claimed, do nothing
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!userIsRewardApproved) {
|
||||||
|
return dispatch({
|
||||||
|
type: types.OPEN_MODAL,
|
||||||
|
data: { modal: modals.REWARD_APPROVAL_REQUIRED },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
type: types.CLAIM_REWARD_STARTED,
|
type: types.CLAIM_REWARD_STARTED,
|
||||||
data: { reward },
|
data: { reward },
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import * as types from "constants/action_types";
|
import * as types from "constants/action_types";
|
||||||
import * as modals from "constants/modal_types";
|
import * as modals from "constants/modal_types";
|
||||||
import lbryio from "lbryio";
|
import lbryio from "lbryio";
|
||||||
import { doOpenModal } from "actions/app";
|
|
||||||
import { doOpenModal, doShowSnackBar } from "actions/app";
|
import { doOpenModal, doShowSnackBar } from "actions/app";
|
||||||
import { doRewardList, doClaimRewardType } from "actions/rewards";
|
import { doRewardList, doClaimRewardType } from "actions/rewards";
|
||||||
import { selectEmailToVerify, selectUser } from "selectors/user";
|
import { selectEmailToVerify, selectUser } from "selectors/user";
|
||||||
|
|
|
@ -165,7 +165,7 @@ class CardVerify extends React.Component {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<Link
|
<Link
|
||||||
button="primary"
|
button="alt"
|
||||||
label={this.props.label}
|
label={this.props.label}
|
||||||
icon="icon-lock"
|
icon="icon-lock"
|
||||||
disabled={
|
disabled={
|
||||||
|
|
|
@ -167,18 +167,20 @@ class FileActions extends React.PureComponent {
|
||||||
<section className="file-actions">
|
<section className="file-actions">
|
||||||
{content}
|
{content}
|
||||||
{showMenu
|
{showMenu
|
||||||
? <DropDownMenu>
|
? <div className="button-set-item">
|
||||||
<DropDownMenuItem
|
<DropDownMenu>
|
||||||
key={0}
|
<DropDownMenuItem
|
||||||
onClick={() => openInFolder(fileInfo)}
|
key={0}
|
||||||
label={openInFolderMessage}
|
onClick={() => openInFolder(fileInfo)}
|
||||||
/>
|
label={openInFolderMessage}
|
||||||
<DropDownMenuItem
|
/>
|
||||||
key={1}
|
<DropDownMenuItem
|
||||||
onClick={() => openModal(modals.CONFIRM_FILE_REMOVE)}
|
key={1}
|
||||||
label={__("Remove...")}
|
onClick={() => openModal(modals.CONFIRM_FILE_REMOVE)}
|
||||||
/>
|
label={__("Remove...")}
|
||||||
</DropDownMenu>
|
/>
|
||||||
|
</DropDownMenu>
|
||||||
|
</div>
|
||||||
: ""}
|
: ""}
|
||||||
<Modal
|
<Modal
|
||||||
type="confirm"
|
type="confirm"
|
||||||
|
|
|
@ -47,11 +47,14 @@ class InviteList extends React.PureComponent {
|
||||||
<td className="text-center">
|
<td className="text-center">
|
||||||
{invitee.invite_reward_claimed
|
{invitee.invite_reward_claimed
|
||||||
? <Icon icon="icon-check" />
|
? <Icon icon="icon-check" />
|
||||||
: <RewardLink
|
: invitee.invite_accepted
|
||||||
label={__("Claim")}
|
? <RewardLink
|
||||||
button="text"
|
label={__("Claim")}
|
||||||
reward_type={rewards.TYPE_FIRST_PUBLISH}
|
reward_type={rewards.TYPE_FIRST_PUBLISH}
|
||||||
/>}
|
/>
|
||||||
|
: <span className="empty">
|
||||||
|
{__("unclaimable")}
|
||||||
|
</span>}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
);
|
);
|
||||||
|
|
|
@ -6,13 +6,21 @@ import {
|
||||||
selectUserInviteNewIsPending,
|
selectUserInviteNewIsPending,
|
||||||
selectUserInviteNewErrorMessage,
|
selectUserInviteNewErrorMessage,
|
||||||
} from "selectors/user";
|
} from "selectors/user";
|
||||||
|
import rewards from "rewards";
|
||||||
|
import { makeSelectRewardAmountByType } from "selectors/rewards";
|
||||||
|
|
||||||
import { doUserInviteNew } from "actions/user";
|
import { doUserInviteNew } from "actions/user";
|
||||||
|
|
||||||
const select = state => ({
|
const select = state => {
|
||||||
errorMessage: selectUserInviteNewErrorMessage(state),
|
const selectReward = makeSelectRewardAmountByType();
|
||||||
invitesRemaining: selectUserInvitesRemaining(state),
|
|
||||||
isPending: selectUserInviteNewIsPending(state),
|
return {
|
||||||
});
|
errorMessage: selectUserInviteNewErrorMessage(state),
|
||||||
|
invitesRemaining: selectUserInvitesRemaining(state),
|
||||||
|
isPending: selectUserInviteNewIsPending(state),
|
||||||
|
rewardAmount: selectReward(state, { reward_type: rewards.TYPE_REFERRAL }),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
const perform = dispatch => ({
|
const perform = dispatch => ({
|
||||||
inviteNew: email => dispatch(doUserInviteNew(email)),
|
inviteNew: email => dispatch(doUserInviteNew(email)),
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { BusyMessage } from "component/common";
|
import { BusyMessage, CreditAmount } from "component/common";
|
||||||
import Link from "component/link";
|
import Link from "component/link";
|
||||||
import { FormRow } from "component/form.js";
|
import { FormRow } from "component/form.js";
|
||||||
|
|
||||||
|
@ -62,15 +62,15 @@ class InviteNew extends React.PureComponent {
|
||||||
inviteNew,
|
inviteNew,
|
||||||
inviteStatusIsPending,
|
inviteStatusIsPending,
|
||||||
isPending,
|
isPending,
|
||||||
|
rewardAmount,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className="card">
|
<section className="card">
|
||||||
<div className="card__title-primary">
|
<div className="card__title-primary">
|
||||||
|
<CreditAmount amount={rewardAmount} />
|
||||||
<h3>
|
<h3>
|
||||||
{__(
|
{__("Invite a Friend")}
|
||||||
"Invite a Friend (or Enemy) (or Someone You Are Somewhat Ambivalent About)"
|
|
||||||
)}
|
|
||||||
</h3>
|
</h3>
|
||||||
</div>
|
</div>
|
||||||
{/*
|
{/*
|
||||||
|
@ -81,6 +81,11 @@ class InviteNew extends React.PureComponent {
|
||||||
<p className="empty">{__("You have no invites.")}</p>}
|
<p className="empty">{__("You have no invites.")}</p>}
|
||||||
</div> */}
|
</div> */}
|
||||||
<div className="card__content">
|
<div className="card__content">
|
||||||
|
<p>
|
||||||
|
{__(
|
||||||
|
"Or an enemy. Or your cousin Jerry, who you're kind of unsure about."
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
<FormInviteNew
|
<FormInviteNew
|
||||||
errorMessage={errorMessage}
|
errorMessage={errorMessage}
|
||||||
inviteNew={inviteNew}
|
inviteNew={inviteNew}
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
import React from "react";
|
|
||||||
import { connect } from "react-redux";
|
|
||||||
import {
|
|
||||||
selectUserInvitesRemaining,
|
|
||||||
selectUserInviteNewIsPending,
|
|
||||||
} from "selectors/user";
|
|
||||||
import InviteSummary from "./view";
|
|
||||||
|
|
||||||
const select = state => ({
|
|
||||||
invitesRemaining: selectUserInvitesRemaining(state),
|
|
||||||
isPending: selectUserInviteNewIsPending(state),
|
|
||||||
});
|
|
||||||
|
|
||||||
export default connect(select)(InviteSummary);
|
|
|
@ -1,35 +0,0 @@
|
||||||
import React from "react";
|
|
||||||
import Link from "component/link";
|
|
||||||
import { CreditAmount, BusyMessage } from "component/common";
|
|
||||||
|
|
||||||
const InviteSummary = props => {
|
|
||||||
const { isPending, invitesRemaining } = props;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<section className="card">
|
|
||||||
<div className="card__title-primary">
|
|
||||||
<h3>{__("Invites")}</h3>
|
|
||||||
</div>
|
|
||||||
<div className="card__content">
|
|
||||||
{isPending && <BusyMessage message={__("Checking invite status")} />}
|
|
||||||
{!isPending &&
|
|
||||||
<p>
|
|
||||||
{__n(
|
|
||||||
"You have %d invite remaining.",
|
|
||||||
"You have %d invites remaining.",
|
|
||||||
invitesRemaining
|
|
||||||
)}
|
|
||||||
</p>}
|
|
||||||
</div>
|
|
||||||
<div className="card__content">
|
|
||||||
<Link
|
|
||||||
button={invitesRemaining > 0 ? "primary" : "text"}
|
|
||||||
navigate="/invite"
|
|
||||||
label={__("Go To Invites")}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default InviteSummary;
|
|
|
@ -22,11 +22,11 @@ const Link = props => {
|
||||||
(button ? " button-block button-" + button + " button-set-item" : "") +
|
(button ? " button-block button-" + button + " button-set-item" : "") +
|
||||||
(disabled ? " disabled" : "");
|
(disabled ? " disabled" : "");
|
||||||
|
|
||||||
const onClick = props.onClick
|
const onClick = !props.onClick && navigate
|
||||||
? props.onClick
|
? () => {
|
||||||
: () => {
|
|
||||||
doNavigate(navigate);
|
doNavigate(navigate);
|
||||||
};
|
}
|
||||||
|
: props.onClick;
|
||||||
|
|
||||||
let content;
|
let content;
|
||||||
if (children) {
|
if (children) {
|
||||||
|
|
|
@ -16,7 +16,7 @@ const RewardLink = props => {
|
||||||
return (
|
return (
|
||||||
<div className="reward-link">
|
<div className="reward-link">
|
||||||
<Link
|
<Link
|
||||||
button={button ? button : "alt"}
|
button={button}
|
||||||
disabled={isPending}
|
disabled={isPending}
|
||||||
label={
|
label={
|
||||||
isPending ? __("Claiming...") : label ? label : __("Claim Reward")
|
isPending ? __("Claiming...") : label ? label : __("Claim Reward")
|
||||||
|
|
|
@ -18,12 +18,9 @@ const RewardSummary = props => {
|
||||||
unclaimed rewards.
|
unclaimed rewards.
|
||||||
</p>}
|
</p>}
|
||||||
</div>
|
</div>
|
||||||
<div className="card__content">
|
<div className="card__actions card__actions--bottom">
|
||||||
<Link
|
<Link button="text" navigate="/rewards" label={__("Rewards")} />
|
||||||
button={unclaimedRewardAmount > 0 ? "primary" : "text"}
|
<Link button="text" navigate="/invite" label={__("Invites")} />
|
||||||
navigate="/rewards"
|
|
||||||
label={__("Go To Rewards")}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { CreditAmount, Icon } from "component/common";
|
import { CreditAmount, Icon } from "component/common";
|
||||||
import RewardLink from "component/rewardLink";
|
import RewardLink from "component/rewardLink";
|
||||||
|
import Link from "component/link";
|
||||||
|
import rewards from "rewards";
|
||||||
|
|
||||||
const RewardTile = props => {
|
const RewardTile = props => {
|
||||||
const { reward } = props;
|
const { reward } = props;
|
||||||
|
@ -14,12 +16,19 @@ const RewardTile = props => {
|
||||||
<CreditAmount amount={reward.reward_amount} />
|
<CreditAmount amount={reward.reward_amount} />
|
||||||
<h3>{reward.reward_title}</h3>
|
<h3>{reward.reward_title}</h3>
|
||||||
</div>
|
</div>
|
||||||
<div className="card__actions">
|
|
||||||
{claimed
|
|
||||||
? <span><Icon icon="icon-check" /> {__("Reward claimed.")}</span>
|
|
||||||
: <RewardLink reward_type={reward.reward_type} />}
|
|
||||||
</div>
|
|
||||||
<div className="card__content">{reward.reward_description}</div>
|
<div className="card__content">{reward.reward_description}</div>
|
||||||
|
<div className="card__actions card__actions--bottom ">
|
||||||
|
{reward.reward_type == rewards.TYPE_REFERRAL &&
|
||||||
|
<Link
|
||||||
|
button="alt"
|
||||||
|
navigate="/invite"
|
||||||
|
label={__("Go To Invites")}
|
||||||
|
/>}
|
||||||
|
{reward.reward_type !== rewards.TYPE_REFERRAL &&
|
||||||
|
(claimed
|
||||||
|
? <span><Icon icon="icon-check" /> {__("Reward claimed.")}</span>
|
||||||
|
: <RewardLink button="alt" reward_type={reward.reward_type} />)}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
|
|
|
@ -30,7 +30,6 @@ const Router = props => {
|
||||||
const { currentPage, params } = props;
|
const { currentPage, params } = props;
|
||||||
|
|
||||||
return route(currentPage, {
|
return route(currentPage, {
|
||||||
address: <ReceiveCreditsPage params={params} />,
|
|
||||||
auth: <AuthPage params={params} />,
|
auth: <AuthPage params={params} />,
|
||||||
backup: <BackupPage params={params} />,
|
backup: <BackupPage params={params} />,
|
||||||
channel: <ChannelPage params={params} />,
|
channel: <ChannelPage params={params} />,
|
||||||
|
@ -42,6 +41,7 @@ const Router = props => {
|
||||||
invite: <InvitePage params={params} />,
|
invite: <InvitePage params={params} />,
|
||||||
publish: <PublishPage params={params} />,
|
publish: <PublishPage params={params} />,
|
||||||
published: <FileListPublished params={params} />,
|
published: <FileListPublished params={params} />,
|
||||||
|
receive: <ReceiveCreditsPage params={params} />,
|
||||||
report: <ReportPage params={params} />,
|
report: <ReportPage params={params} />,
|
||||||
rewards: <RewardsPage params={params} />,
|
rewards: <RewardsPage params={params} />,
|
||||||
search: <SearchPage params={params} />,
|
search: <SearchPage params={params} />,
|
||||||
|
|
|
@ -26,7 +26,7 @@ class TransactionListRecent extends React.PureComponent {
|
||||||
/>}
|
/>}
|
||||||
</div>
|
</div>
|
||||||
{hasTransactions &&
|
{hasTransactions &&
|
||||||
<div className="card__content">
|
<div className="card__actions card__actions--bottom">
|
||||||
<Link
|
<Link
|
||||||
navigate="/history"
|
navigate="/history"
|
||||||
label={__("See Full History")}
|
label={__("See Full History")}
|
||||||
|
|
|
@ -31,6 +31,16 @@ class UserEmailNew extends React.PureComponent {
|
||||||
this.handleSubmit(event);
|
this.handleSubmit(event);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
<p>
|
||||||
|
{__(
|
||||||
|
"This process is required to prevent abuse of the rewards program."
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
{__(
|
||||||
|
"We will also contact you about updates and new content, but you can unsubscribe at any time."
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
<FormRow
|
<FormRow
|
||||||
type="text"
|
type="text"
|
||||||
label="Email"
|
label="Email"
|
||||||
|
|
|
@ -26,37 +26,121 @@ class UserVerify extends React.PureComponent {
|
||||||
const { errorMessage, isPending, navigate } = this.props;
|
const { errorMessage, isPending, navigate } = this.props;
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<p>
|
<section className="card card--form">
|
||||||
{__(
|
<div className="card__title-primary">
|
||||||
"To ensure you are a real person, we require a valid credit or debit card."
|
<h1>{__("Final Human Proof")}</h1>
|
||||||
) +
|
</div>
|
||||||
" " +
|
<div className="card__content">
|
||||||
__("There is no charge at all, now or in the future.") +
|
<p>
|
||||||
" "}
|
Finally, please complete <strong>one and only one</strong> of the
|
||||||
<Link
|
options below.
|
||||||
href="https://lbry.io/faq/identity-requirements"
|
</p>
|
||||||
label={__("Read More")}
|
</div>
|
||||||
/>
|
</section>
|
||||||
</p>
|
<section className="card card--form">
|
||||||
{errorMessage && <p className="form-field__error">{errorMessage}</p>}
|
<div className="card__title-primary">
|
||||||
<p>
|
<h3>{__("1) Proof via Credit")}</h3>
|
||||||
<CardVerify
|
</div>
|
||||||
label={__("Link Card and Finish")}
|
<div className="card__content">
|
||||||
disabled={isPending}
|
<p>
|
||||||
token={this.onToken.bind(this)}
|
{__(
|
||||||
stripeKey={lbryio.getStripeToken()}
|
"If you have a valid credit or debit card, you can instantly prove your humanity."
|
||||||
/>
|
) +
|
||||||
</p>
|
" " +
|
||||||
<p>
|
__(
|
||||||
{__(
|
"There is no charge at all for this, now or in the future."
|
||||||
"You can continue without this step, but you will not be eligible to earn rewards."
|
) +
|
||||||
)}
|
" "}
|
||||||
</p>
|
<Link
|
||||||
<Link
|
href="https://lbry.io/faq/identity-requirements"
|
||||||
onClick={() => navigate("/discover")}
|
label={__("Read More")}
|
||||||
button="alt"
|
/>
|
||||||
label={__("Skip Rewards")}
|
</p>
|
||||||
/>
|
{errorMessage &&
|
||||||
|
<p className="form-field__error">{errorMessage}</p>}
|
||||||
|
<p>
|
||||||
|
<CardVerify
|
||||||
|
label={__("Perform Card Verification")}
|
||||||
|
disabled={isPending}
|
||||||
|
token={this.onToken.bind(this)}
|
||||||
|
stripeKey={lbryio.getStripeToken()}
|
||||||
|
/>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<section className="card card--form">
|
||||||
|
<div className="card__title-primary">
|
||||||
|
<h3>{__("2) Proof via YouTube")}</h3>
|
||||||
|
</div>
|
||||||
|
<div className="card__content">
|
||||||
|
<p>
|
||||||
|
{__(
|
||||||
|
"If you have a YouTube account with published videos that you want to make available on LBRY, syncing your account will grant instant authorization."
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="card__actions">
|
||||||
|
<Link
|
||||||
|
href="https://api.lbry.io/yt/sync"
|
||||||
|
button="alt"
|
||||||
|
icon="icon-youtube"
|
||||||
|
label={__("YouTube Account Sync")}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="card__content">
|
||||||
|
<div className="meta">
|
||||||
|
This will not automatically refresh after approval. Once you have
|
||||||
|
synced your account, just navigate away or click
|
||||||
|
{" "} <Link navigate="/rewards" label="here" />.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<section className="card card--form">
|
||||||
|
<div className="card__title-primary">
|
||||||
|
<h3>{__("3) Proof via Chat")}</h3>
|
||||||
|
</div>
|
||||||
|
<div className="card__content">
|
||||||
|
<p>
|
||||||
|
{__(
|
||||||
|
"A moderator capable of approving you is typically available in the #verification channel of our chat room."
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
{__(
|
||||||
|
"This process will likely involve providing proof of a stable and established online identity of some kind."
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="card__actions">
|
||||||
|
<Link
|
||||||
|
href="https://slack.lbry.io"
|
||||||
|
button="alt"
|
||||||
|
icon="icon-slack"
|
||||||
|
label={__("Join LBRY Chat")}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<section className="card card--form">
|
||||||
|
<div className="card__title-primary">
|
||||||
|
<h5>{__("Or, Skip It Entirely")}</h5>
|
||||||
|
</div>
|
||||||
|
<div className="card__content">
|
||||||
|
|
||||||
|
<p className="meta">
|
||||||
|
{__(
|
||||||
|
"You can continue without this step, but you will not be eligible to earn rewards."
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div className="card__actions">
|
||||||
|
<Link
|
||||||
|
onClick={() => navigate("/discover")}
|
||||||
|
button="alt"
|
||||||
|
label={__("Skip Rewards")}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ class WalletAddress extends React.PureComponent {
|
||||||
<div className="card__content">
|
<div className="card__content">
|
||||||
<p>
|
<p>
|
||||||
{__(
|
{__(
|
||||||
'Other LBRY users may send credits to you by entering this address on the "Send" page.'
|
"Use this address to receive credits send by another user (or yourself)."
|
||||||
)}
|
)}
|
||||||
</p>
|
</p>
|
||||||
<Address address={receiveAddress} />
|
<Address address={receiveAddress} />
|
||||||
|
|
|
@ -21,13 +21,19 @@ const WalletBalance = props => {
|
||||||
{(balance || balance === 0) &&
|
{(balance || balance === 0) &&
|
||||||
<CreditAmount amount={balance} precision={8} />}
|
<CreditAmount amount={balance} precision={8} />}
|
||||||
</div>
|
</div>
|
||||||
<div className="card__content">
|
<div className="card__actions card__actions--bottom">
|
||||||
<Link button="text" navigate="/send" label={__("Send")} />
|
|
||||||
<Link button="text" navigate="/address" label={__("Address")} />
|
|
||||||
<Link
|
<Link
|
||||||
button="text"
|
button="text"
|
||||||
|
navigate="/send"
|
||||||
|
disabled={balance === 0}
|
||||||
|
label={__("Send")}
|
||||||
|
/>
|
||||||
|
<Link button="text" navigate="/receive" label={__("Receive")} />
|
||||||
|
<Link
|
||||||
|
button="text"
|
||||||
|
disabled={balance === 0}
|
||||||
navigate="/backup"
|
navigate="/backup"
|
||||||
label={__("Backup Your Wallet")}
|
label={__("Backup")}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
|
@ -42,15 +42,15 @@ const WalletSend = props => {
|
||||||
onChange={setAddress}
|
onChange={setAddress}
|
||||||
value={address}
|
value={address}
|
||||||
/>
|
/>
|
||||||
</div>
|
<div className="form-row-submit">
|
||||||
<div className="card__actions card__actions--form-submit">
|
<Link
|
||||||
<Link
|
button="primary"
|
||||||
button="primary"
|
label={__("Send")}
|
||||||
label={__("Send")}
|
onClick={sendToAddress}
|
||||||
onClick={sendToAddress}
|
disabled={!(parseFloat(amount) > 0.0) || !address}
|
||||||
disabled={!(parseFloat(amount) > 0.0) || !address}
|
/>
|
||||||
/>
|
<input type="submit" className="hidden" />
|
||||||
<input type="submit" className="hidden" />
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
{modal == "insufficientBalance" &&
|
{modal == "insufficientBalance" &&
|
||||||
|
|
|
@ -7,4 +7,5 @@ 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 REWARD_APPROVAL_REQUIRED = "REWARD_APPROVAL_REQUIRED";
|
||||||
export const CREDIT_INTRO = "credit_intro";
|
export const CREDIT_INTRO = "credit_intro";
|
||||||
|
|
|
@ -2,7 +2,7 @@ import React from "react";
|
||||||
import { Modal } from "modal/modal";
|
import { Modal } from "modal/modal";
|
||||||
import { CreditAmount, CurrencySymbol } from "component/common";
|
import { CreditAmount, CurrencySymbol } from "component/common";
|
||||||
import Link from "component/link/index";
|
import Link from "component/link/index";
|
||||||
import { formatCredits } from "utils";
|
import { formatCredits } from "util/formatCredits";
|
||||||
|
|
||||||
const ModalCreditIntro = props => {
|
const ModalCreditIntro = props => {
|
||||||
const { closeModal, currentBalance, totalRewardValue, verifyAccount } = props;
|
const { closeModal, currentBalance, totalRewardValue, verifyAccount } = props;
|
||||||
|
@ -12,50 +12,51 @@ const ModalCreditIntro = props => {
|
||||||
return (
|
return (
|
||||||
<Modal type="custom" isOpen={true} contentLabel="Welcome to LBRY">
|
<Modal type="custom" isOpen={true} contentLabel="Welcome to LBRY">
|
||||||
<section>
|
<section>
|
||||||
<h3 className="modal__header">{__("Quick Credit Intro")}</h3>
|
<h3 className="modal__header">{__("Blockchain 101")}</h3>
|
||||||
<p>
|
<p>
|
||||||
The LBRY network is controlled and powered by credits called{" "}
|
LBRY is controlled and powered by a blockchain asset called {" "}
|
||||||
<em><CurrencySymbol /></em>, a blockchain asset. {" "}
|
<em><CurrencySymbol /></em>.{" "}
|
||||||
<CurrencySymbol />{" "}
|
<CurrencySymbol />{" "}
|
||||||
{__(
|
{__(
|
||||||
"is used to publish content, to have a say in the network rules, and to access paid content."
|
"is used to publish content, to have a say in the network rules, and to access paid content."
|
||||||
)}
|
)}
|
||||||
</p>
|
</p>
|
||||||
<p>
|
|
||||||
{__("New verified users can receive more than ")} {" "}
|
|
||||||
{totalRewardValue
|
|
||||||
? <CreditAmount amount={totalRewardRounded} />
|
|
||||||
: <span className="credit-amount">{__("credits")}</span>}
|
|
||||||
{" "} {__(" in rewards for usage and influence of the network.")}
|
|
||||||
</p>
|
|
||||||
{currentBalance <= 0
|
{currentBalance <= 0
|
||||||
? <p>
|
? <div>
|
||||||
<strong>
|
<p>
|
||||||
|
You currently have <CreditAmount amount={currentBalance} />, so
|
||||||
|
the actions you can take are limited.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
However, there are a variety of ways to get credits, including
|
||||||
|
more than {" "}
|
||||||
|
{totalRewardValue
|
||||||
|
? <CreditAmount amount={totalRewardRounded} />
|
||||||
|
: <span className="credit-amount">{__("?? credits")}</span>}
|
||||||
|
{" "}{" "}
|
||||||
{__(
|
{__(
|
||||||
"Without any credits, you will not be able to take this action."
|
" in rewards available for being a proven human during the LBRY beta."
|
||||||
)}
|
)}
|
||||||
</strong>
|
</p>
|
||||||
</p>
|
</div>
|
||||||
: <p>
|
: <div>
|
||||||
{__(
|
<p>
|
||||||
"But you probably knew all this, since you've already got %s of them!",
|
But you probably knew this, since you've already got{" "}
|
||||||
formatCredits(currentBalance, 2)
|
<CreditAmount amount={currentBalance} />.
|
||||||
)}
|
</p>
|
||||||
</p>}
|
</div>}
|
||||||
|
|
||||||
<div className="modal__buttons">
|
<div className="modal__buttons">
|
||||||
<Link
|
<Link
|
||||||
button="primary"
|
button="primary"
|
||||||
onClick={verifyAccount}
|
onClick={verifyAccount}
|
||||||
label={__("You Had Me At Free LBC")}
|
label={__("I'm Totally A Human")}
|
||||||
/>
|
/>
|
||||||
<Link
|
<Link
|
||||||
button="alt"
|
button="alt"
|
||||||
onClick={closeModal}
|
onClick={closeModal}
|
||||||
label={
|
label={
|
||||||
currentBalance <= 0
|
currentBalance <= 0 ? __("Use Without LBC") : __("Meh, Not Now")
|
||||||
? __("Continue Without LBC")
|
|
||||||
: __("Meh, Not Now")
|
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -7,7 +7,7 @@ const select = state => ({});
|
||||||
|
|
||||||
const perform = dispatch => ({
|
const perform = dispatch => ({
|
||||||
addFunds: () => {
|
addFunds: () => {
|
||||||
dispatch(doNavigate("/rewards"));
|
dispatch(doNavigate("/wallet"));
|
||||||
dispatch(doCloseModal());
|
dispatch(doCloseModal());
|
||||||
},
|
},
|
||||||
closeModal: () => dispatch(doCloseModal()),
|
closeModal: () => dispatch(doCloseModal()),
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { Modal } from "modal/modal";
|
import { Modal } from "modal/modal";
|
||||||
|
import { CurrencySymbol } from "component/common";
|
||||||
|
|
||||||
class ModalInsufficientCredits extends React.PureComponent {
|
class ModalInsufficientCredits extends React.PureComponent {
|
||||||
render() {
|
render() {
|
||||||
|
@ -15,7 +16,8 @@ class ModalInsufficientCredits extends React.PureComponent {
|
||||||
onAborted={closeModal}
|
onAborted={closeModal}
|
||||||
onConfirmed={addFunds}
|
onConfirmed={addFunds}
|
||||||
>
|
>
|
||||||
<p>{__("More LBRY credits are required to take this action.")}</p>
|
<h3 className="modal__header">{__("More Credits Required")}</h3>
|
||||||
|
<p>You'll need more <CurrencySymbol /> to do this.</p>
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
14
ui/js/modal/modalRewardApprovalRequired/index.js
Normal file
14
ui/js/modal/modalRewardApprovalRequired/index.js
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
import React from "react";
|
||||||
|
import { connect } from "react-redux";
|
||||||
|
import { doCloseModal, doAuthNavigate } from "actions/app";
|
||||||
|
import ModalRewardApprovalRequired from "./view";
|
||||||
|
|
||||||
|
const perform = dispatch => ({
|
||||||
|
doAuth: () => {
|
||||||
|
dispatch(doCloseModal());
|
||||||
|
dispatch(doAuthNavigate());
|
||||||
|
},
|
||||||
|
closeModal: () => dispatch(doCloseModal()),
|
||||||
|
});
|
||||||
|
|
||||||
|
export default connect(null, perform)(ModalRewardApprovalRequired);
|
33
ui/js/modal/modalRewardApprovalRequired/view.jsx
Normal file
33
ui/js/modal/modalRewardApprovalRequired/view.jsx
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
import React from "react";
|
||||||
|
import { Modal } from "modal/modal";
|
||||||
|
|
||||||
|
class ModalRewardApprovalRequired extends React.PureComponent {
|
||||||
|
render() {
|
||||||
|
const { closeModal, doAuth } = this.props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
isOpen={true}
|
||||||
|
contentLabel={__("Human Verification Required")}
|
||||||
|
onConfirmed={doAuth}
|
||||||
|
onAborted={closeModal}
|
||||||
|
type="confirm"
|
||||||
|
confirmButtonLabel={__("I'm Totally Real")}
|
||||||
|
abortButtonLabel={__("Nevermind")}
|
||||||
|
>
|
||||||
|
<section>
|
||||||
|
<h3 className="modal__header">
|
||||||
|
{__("This is awkward. Are you real?")}
|
||||||
|
</h3>
|
||||||
|
<p>
|
||||||
|
{__(
|
||||||
|
"Before we can give you any credits, we need to perform a brief check to make sure you're a new and unique person."
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ModalRewardApprovalRequired;
|
|
@ -6,9 +6,11 @@ import { makeSelectClientSetting } from "selectors/settings";
|
||||||
import { selectUser } from "selectors/user";
|
import { selectUser } from "selectors/user";
|
||||||
import { selectCostForCurrentPageUri } from "selectors/cost_info";
|
import { selectCostForCurrentPageUri } from "selectors/cost_info";
|
||||||
import * as settings from "constants/settings";
|
import * as settings from "constants/settings";
|
||||||
|
import { selectBalance } from "selectors/wallet";
|
||||||
import ModalRouter from "./view";
|
import ModalRouter from "./view";
|
||||||
|
|
||||||
const select = (state, props) => ({
|
const select = (state, props) => ({
|
||||||
|
balance: selectBalance(state),
|
||||||
showPageCost: selectCostForCurrentPageUri(state),
|
showPageCost: selectCostForCurrentPageUri(state),
|
||||||
modal: selectCurrentModal(state),
|
modal: selectCurrentModal(state),
|
||||||
page: selectCurrentPage(state),
|
page: selectCurrentPage(state),
|
||||||
|
|
|
@ -6,10 +6,20 @@ import ModalInsufficientCredits from "modal/modalInsufficientCredits";
|
||||||
import ModalUpgrade from "modal/modalUpgrade";
|
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 * as modals from "constants/modal_types";
|
import * as modals from "constants/modal_types";
|
||||||
import ModalCreditIntro from "modal/modalCreditIntro";
|
import ModalCreditIntro from "modal/modalCreditIntro";
|
||||||
|
|
||||||
class ModalRouter extends React.PureComponent {
|
class ModalRouter extends React.PureComponent {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
lastTransitionModal: null,
|
||||||
|
lastTransitionPage: null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
componentWillMount() {
|
componentWillMount() {
|
||||||
this.showTransitionModals(this.props);
|
this.showTransitionModals(this.props);
|
||||||
}
|
}
|
||||||
|
@ -19,55 +29,72 @@ class ModalRouter extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
showTransitionModals(props) {
|
showTransitionModals(props) {
|
||||||
const { modal } = props;
|
const { modal, openModal, page } = props;
|
||||||
|
|
||||||
if (modal) {
|
if (modal) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
[
|
const transitionModal = [
|
||||||
this.checkShowWelcome.bind(this),
|
this.checkShowWelcome,
|
||||||
this.checkShowCreditIntro.bind(this),
|
this.checkShowCreditIntro,
|
||||||
].find(func => func(props));
|
this.checkShowInsufficientCredits,
|
||||||
|
].reduce((acc, func) => {
|
||||||
|
return !acc ? func.bind(this)(props) : acc;
|
||||||
|
}, false);
|
||||||
|
|
||||||
|
if (
|
||||||
|
transitionModal &&
|
||||||
|
(transitionModal != this.state.lastTransitionModal ||
|
||||||
|
page != this.state.lastTransitionPage)
|
||||||
|
) {
|
||||||
|
openModal(transitionModal);
|
||||||
|
this.setState({
|
||||||
|
lastTransitionModal: transitionModal,
|
||||||
|
lastTransitionPage: page,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
checkShowWelcome(props) {
|
checkShowWelcome(props) {
|
||||||
const { isWelcomeAcknowledged, openModal, user } = props;
|
const { isWelcomeAcknowledged, user } = props;
|
||||||
if (
|
if (
|
||||||
!isWelcomeAcknowledged &&
|
!isWelcomeAcknowledged &&
|
||||||
user &&
|
user &&
|
||||||
!user.is_reward_approved &&
|
!user.is_reward_approved &&
|
||||||
!user.is_identity_verified
|
!user.is_identity_verified
|
||||||
) {
|
) {
|
||||||
openModal(modals.WELCOME);
|
return modals.WELCOME;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
checkShowCreditIntro(props) {
|
checkShowCreditIntro(props) {
|
||||||
const {
|
const { page, isCreditIntroAcknowledged, user } = props;
|
||||||
page,
|
|
||||||
isCreditIntroAcknowledged,
|
|
||||||
openModal,
|
|
||||||
user,
|
|
||||||
showPageCost,
|
|
||||||
} = props;
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
!isCreditIntroAcknowledged &&
|
!isCreditIntroAcknowledged &&
|
||||||
user &&
|
user &&
|
||||||
!user.is_reward_approved &&
|
!user.is_reward_approved &&
|
||||||
!user.is_identity_verified &&
|
(["rewards", "send", "receive", "publish", "wallet"].includes(page) ||
|
||||||
["rewards", "send", "address", "show", "publish", "wallet"].includes(
|
this.isPaidShowPage(props))
|
||||||
page
|
|
||||||
) &&
|
|
||||||
(page != "show" || showPageCost > 0)
|
|
||||||
) {
|
) {
|
||||||
openModal(modals.CREDIT_INTRO);
|
return modals.CREDIT_INTRO;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
checkShowInsufficientCredits(props) {
|
||||||
|
const { balance, page } = props;
|
||||||
|
|
||||||
|
if (balance <= 0 && ["send", "publish"].includes(page)) {
|
||||||
|
return modals.INSUFFICIENT_CREDITS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
isPaidShowPage(props) {
|
||||||
|
const { page, showPageCost } = props;
|
||||||
|
return page === "show" && showPageCost > 0;
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { modal } = this.props;
|
const { modal } = this.props;
|
||||||
|
|
||||||
|
@ -88,6 +115,8 @@ class ModalRouter extends React.PureComponent {
|
||||||
return <ModalAuthFailure />;
|
return <ModalAuthFailure />;
|
||||||
case modals.CREDIT_INTRO:
|
case modals.CREDIT_INTRO:
|
||||||
return <ModalCreditIntro />;
|
return <ModalCreditIntro />;
|
||||||
|
case modals.REWARD_APPROVAL_REQUIRED:
|
||||||
|
return <ModalRewardApprovalRequired />;
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,11 +30,11 @@ export class AuthPage extends React.PureComponent {
|
||||||
const { email, isPending, isVerificationCandidate, user } = this.props;
|
const { email, isPending, isVerificationCandidate, user } = this.props;
|
||||||
|
|
||||||
if (isPending || (user && !user.has_verified_email && !email)) {
|
if (isPending || (user && !user.has_verified_email && !email)) {
|
||||||
return __("Welcome to LBRY");
|
return __("Human Proofing");
|
||||||
} else if (user && !user.has_verified_email) {
|
} else if (user && !user.has_verified_email) {
|
||||||
return __("Confirm Email");
|
return __("Confirm Email");
|
||||||
} else if (user && !user.is_identity_verified && !user.is_reward_approved) {
|
} else if (user && !user.is_identity_verified && !user.is_reward_approved) {
|
||||||
return __("Confirm Identity");
|
return __("Final Verification");
|
||||||
} else {
|
} else {
|
||||||
return __("Welcome to LBRY");
|
return __("Welcome to LBRY");
|
||||||
}
|
}
|
||||||
|
@ -44,51 +44,45 @@ export class AuthPage extends React.PureComponent {
|
||||||
const { email, isPending, isVerificationCandidate, user } = this.props;
|
const { email, isPending, isVerificationCandidate, user } = this.props;
|
||||||
|
|
||||||
if (isPending) {
|
if (isPending) {
|
||||||
return <BusyMessage message={__("Authenticating")} />;
|
return [<BusyMessage message={__("Authenticating")} />, true];
|
||||||
} else if (user && !user.has_verified_email && !email) {
|
} else if (user && !user.has_verified_email && !email) {
|
||||||
return <UserEmailNew />;
|
return [<UserEmailNew />, true];
|
||||||
} else if (user && !user.has_verified_email) {
|
} else if (user && !user.has_verified_email) {
|
||||||
return <UserEmailVerify />;
|
return [<UserEmailVerify />, true];
|
||||||
} else if (user && !user.is_identity_verified) {
|
} else if (user && !user.is_identity_verified) {
|
||||||
return <UserVerify />;
|
return [<UserVerify />, false];
|
||||||
} else {
|
} else {
|
||||||
return <span className="empty">{__("No further steps.")}</span>;
|
return [<span className="empty">{__("No further steps.")}</span>, true];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { email, user, isPending, navigate } = this.props;
|
const { email, user, isPending, navigate } = this.props;
|
||||||
|
const [innerContent, useTemplate] = this.renderMain();
|
||||||
|
|
||||||
return (
|
return useTemplate
|
||||||
<main className="">
|
? <main>
|
||||||
<section className="card card--form">
|
<section className="card card--form">
|
||||||
<div className="card__title-primary">
|
<div className="card__title-primary">
|
||||||
<h1>{this.getTitle()}</h1>
|
<h1>{this.getTitle()}</h1>
|
||||||
</div>
|
|
||||||
<div className="card__content">
|
|
||||||
{!isPending &&
|
|
||||||
!email &&
|
|
||||||
user &&
|
|
||||||
!user.has_verified_email &&
|
|
||||||
<p>
|
|
||||||
{__("Create a verified identity and receive LBC rewards.")}
|
|
||||||
</p>}
|
|
||||||
{this.renderMain()}
|
|
||||||
</div>
|
|
||||||
<div className="card__content">
|
|
||||||
<div className="help">
|
|
||||||
{__(
|
|
||||||
"This information is disclosed only to LBRY, Inc. and not to the LBRY network. It is only required to earn LBRY rewards."
|
|
||||||
) + " "}
|
|
||||||
<Link
|
|
||||||
onClick={() => navigate("/discover")}
|
|
||||||
label={__("Return home")}
|
|
||||||
/>.
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div className="card__content">
|
||||||
</section>
|
{innerContent}
|
||||||
</main>
|
</div>
|
||||||
);
|
<div className="card__content">
|
||||||
|
<div className="help">
|
||||||
|
{__(
|
||||||
|
"This information is disclosed only to LBRY, Inc. and not to the LBRY network. It is only required to earn LBRY rewards."
|
||||||
|
) + " "}
|
||||||
|
<Link
|
||||||
|
onClick={() => navigate("/discover")}
|
||||||
|
label={__("Return home")}
|
||||||
|
/>.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
: innerContent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { doNavigate } from "actions/app";
|
import { doAuthNavigate } from "actions/app";
|
||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
import { doFetchAccessToken } from "actions/user";
|
import { doFetchAccessToken } from "actions/user";
|
||||||
import { selectAccessToken, selectUser } from "selectors/user";
|
import { selectAccessToken, selectUser } from "selectors/user";
|
||||||
|
@ -11,7 +11,7 @@ const select = state => ({
|
||||||
});
|
});
|
||||||
|
|
||||||
const perform = dispatch => ({
|
const perform = dispatch => ({
|
||||||
navigate: (path, params) => dispatch(doNavigate(path, params)),
|
doAuth: () => dispatch(doAuthNavigate("/help")),
|
||||||
fetchAccessToken: () => dispatch(doFetchAccessToken()),
|
fetchAccessToken: () => dispatch(doFetchAccessToken()),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ import React from "react";
|
||||||
import lbry from "lbry.js";
|
import lbry from "lbry.js";
|
||||||
import Link from "component/link";
|
import Link from "component/link";
|
||||||
import SubHeader from "component/subHeader";
|
import SubHeader from "component/subHeader";
|
||||||
import { BusyMessage } from "component/common";
|
import { BusyMessage, Icon } from "component/common";
|
||||||
|
|
||||||
class HelpPage extends React.PureComponent {
|
class HelpPage extends React.PureComponent {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
|
@ -50,7 +50,7 @@ class HelpPage extends React.PureComponent {
|
||||||
render() {
|
render() {
|
||||||
let ver, osName, platform, newVerLink;
|
let ver, osName, platform, newVerLink;
|
||||||
|
|
||||||
const { navigate, user } = this.props;
|
const { doAuth, user } = this.props;
|
||||||
|
|
||||||
if (this.state.versionInfo) {
|
if (this.state.versionInfo) {
|
||||||
ver = this.state.versionInfo;
|
ver = this.state.versionInfo;
|
||||||
|
@ -119,7 +119,7 @@ class HelpPage extends React.PureComponent {
|
||||||
<p>{__("Did you find something wrong?")}</p>
|
<p>{__("Did you find something wrong?")}</p>
|
||||||
<p>
|
<p>
|
||||||
<Link
|
<Link
|
||||||
onClick={() => navigate("report")}
|
navigate="/report"
|
||||||
label={__("Submit a Bug Report")}
|
label={__("Submit a Bug Report")}
|
||||||
icon="icon-bug"
|
icon="icon-bug"
|
||||||
button="alt"
|
button="alt"
|
||||||
|
@ -143,7 +143,7 @@ class HelpPage extends React.PureComponent {
|
||||||
</p>
|
</p>
|
||||||
: <p>{__("Your copy of LBRY is up to date.")}</p>}
|
: <p>{__("Your copy of LBRY is up to date.")}</p>}
|
||||||
{this.state.uiVersion && ver
|
{this.state.uiVersion && ver
|
||||||
? <table className="table-standard">
|
? <table className="table-standard table-stretch table-standard--definition-list">
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<th>{__("App")}</th>
|
<th>{__("App")}</th>
|
||||||
|
@ -162,7 +162,21 @@ class HelpPage extends React.PureComponent {
|
||||||
<td>
|
<td>
|
||||||
{user && user.primary_email
|
{user && user.primary_email
|
||||||
? user.primary_email
|
? user.primary_email
|
||||||
: <span className="empty">{__("none")}</span>}
|
: <span>
|
||||||
|
<span className="empty">{__("none")} </span>
|
||||||
|
(<Link
|
||||||
|
onClick={() => doAuth()}
|
||||||
|
label={__("set email")}
|
||||||
|
/>)
|
||||||
|
</span>}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>{__("Reward Eligible")}</th>
|
||||||
|
<td>
|
||||||
|
{user && user.is_reward_approved
|
||||||
|
? <Icon icon="icon-check" />
|
||||||
|
: <Icon icon="icon-ban" />}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
|
|
|
@ -16,10 +16,12 @@ import {
|
||||||
doCreateChannel,
|
doCreateChannel,
|
||||||
doPublish,
|
doPublish,
|
||||||
} from "actions/content";
|
} from "actions/content";
|
||||||
|
import { selectBalance } from "selectors/wallet";
|
||||||
import rewards from "rewards";
|
import rewards from "rewards";
|
||||||
import PublishPage from "./view";
|
import PublishPage from "./view";
|
||||||
|
|
||||||
const select = state => ({
|
const select = state => ({
|
||||||
|
balance: selectBalance(state),
|
||||||
myClaims: selectMyClaims(state),
|
myClaims: selectMyClaims(state),
|
||||||
fetchingChannels: selectFetchingMyChannels(state),
|
fetchingChannels: selectFetchingMyChannels(state),
|
||||||
channels: selectMyChannelClaims(state),
|
channels: selectMyChannelClaims(state),
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import SubHeader from "component/subHeader";
|
import SubHeader from "component/subHeader";
|
||||||
import WalletBalance from "component/walletBalance";
|
import Link from "component/link";
|
||||||
import WalletAddress from "component/walletAddress";
|
import WalletAddress from "component/walletAddress";
|
||||||
|
|
||||||
const ReceiveCreditsPage = props => {
|
const ReceiveCreditsPage = props => {
|
||||||
|
@ -8,6 +8,25 @@ const ReceiveCreditsPage = props => {
|
||||||
<main className="main--single-column">
|
<main className="main--single-column">
|
||||||
<SubHeader />
|
<SubHeader />
|
||||||
<WalletAddress />
|
<WalletAddress />
|
||||||
|
<section className="card">
|
||||||
|
<div className="card__title-primary">
|
||||||
|
<h3>{__("Where To Find Credits")}</h3>
|
||||||
|
</div>
|
||||||
|
<div className="card__content">
|
||||||
|
<p>
|
||||||
|
{
|
||||||
|
"LBRY credits can be purchased on exchanges, earned for contributions, for mining, and more."
|
||||||
|
}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="card__actions">
|
||||||
|
<Link
|
||||||
|
button="alt"
|
||||||
|
href="https://lbry.io/faq/earn-credits"
|
||||||
|
label={__("Read More")}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
</main>
|
</main>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -33,13 +33,20 @@ class RewardsPage extends React.PureComponent {
|
||||||
) {
|
) {
|
||||||
return (
|
return (
|
||||||
<section className="card">
|
<section className="card">
|
||||||
|
<div className="card__title-primary">
|
||||||
|
<h3>{__("Humans Only")}</h3>
|
||||||
|
</div>
|
||||||
<div className="card__content empty">
|
<div className="card__content empty">
|
||||||
<p>
|
<p>
|
||||||
{__("Only verified accounts are eligible to earn rewards.")}
|
{__("Rewards are for human beings only.")}
|
||||||
|
{" "}
|
||||||
|
{__(
|
||||||
|
"You'll have to prove you're one of us before you can claim any rewards."
|
||||||
|
)}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="card__content">
|
<div className="card__content">
|
||||||
<Link onClick={doAuth} button="primary" label="Become Verified" />
|
<Link onClick={doAuth} button="primary" label="Prove Humanity" />
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
|
@ -89,12 +96,11 @@ class RewardsPage extends React.PureComponent {
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
} else if (user === null) {
|
} else if (user === null) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="card__content empty">
|
<div className="card__content empty">
|
||||||
<p>
|
<p>
|
||||||
{__(
|
{__(
|
||||||
"This application is unable to earn rewards due to an authentication failure."
|
"This application is unable to earn rewards due to an authentication failure."
|
||||||
)}
|
)}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
@ -106,8 +112,12 @@ class RewardsPage extends React.PureComponent {
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return rewards.map(reward =>
|
return (
|
||||||
<RewardTile key={reward.reward_type} reward={reward} />
|
<div className="card-grid">
|
||||||
|
{rewards.map(reward =>
|
||||||
|
<RewardTile key={reward.reward_type} reward={reward} />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import SubHeader from "component/subHeader";
|
import SubHeader from "component/subHeader";
|
||||||
import WalletBalance from "component/walletBalance";
|
|
||||||
import WalletSend from "component/walletSend";
|
import WalletSend from "component/walletSend";
|
||||||
|
|
||||||
const SendCreditsPage = props => {
|
const SendCreditsPage = props => {
|
||||||
|
|
|
@ -2,16 +2,16 @@ import React from "react";
|
||||||
import SubHeader from "component/subHeader";
|
import SubHeader from "component/subHeader";
|
||||||
import WalletBalance from "component/walletBalance";
|
import WalletBalance from "component/walletBalance";
|
||||||
import RewardSummary from "component/rewardSummary";
|
import RewardSummary from "component/rewardSummary";
|
||||||
import InviteSummary from "component/inviteSummary";
|
|
||||||
import TransactionListRecent from "component/transactionListRecent";
|
import TransactionListRecent from "component/transactionListRecent";
|
||||||
|
|
||||||
const WalletPage = props => {
|
const WalletPage = props => {
|
||||||
return (
|
return (
|
||||||
<main className="main--single-column">
|
<main className="main--single-column page--wallet">
|
||||||
<SubHeader />
|
<SubHeader />
|
||||||
<WalletBalance />
|
<div className="card-grid">
|
||||||
<RewardSummary />
|
<WalletBalance />
|
||||||
<InviteSummary />
|
<RewardSummary />
|
||||||
|
</div>
|
||||||
<TransactionListRecent />
|
<TransactionListRecent />
|
||||||
</main>
|
</main>
|
||||||
);
|
);
|
||||||
|
|
|
@ -96,6 +96,17 @@ rewards.TYPE_MANY_DOWNLOADS = "many_downloads";
|
||||||
rewards.TYPE_FIRST_PUBLISH = "first_publish";
|
rewards.TYPE_FIRST_PUBLISH = "first_publish";
|
||||||
rewards.TYPE_FEATURED_DOWNLOAD = "featured_download";
|
rewards.TYPE_FEATURED_DOWNLOAD = "featured_download";
|
||||||
rewards.TYPE_REFERRAL = "referral";
|
rewards.TYPE_REFERRAL = "referral";
|
||||||
|
rewards.SORT_ORDER = [
|
||||||
|
rewards.TYPE_NEW_USER,
|
||||||
|
rewards.TYPE_CONFIRM_EMAIL,
|
||||||
|
rewards.TYPE_FIRST_STREAM,
|
||||||
|
rewards.TYPE_FIRST_CHANNEL,
|
||||||
|
rewards.TYPE_FIRST_PUBLISH,
|
||||||
|
rewards.TYPE_FEATURED_DOWNLOAD,
|
||||||
|
rewards.TYPE_MANY_DOWNLOADS,
|
||||||
|
rewards.TYPE_REFERRAL,
|
||||||
|
rewards.TYPE_NEW_DEVELOPER,
|
||||||
|
];
|
||||||
|
|
||||||
rewards.claimReward = function(type) {
|
rewards.claimReward = function(type) {
|
||||||
function requestReward(resolve, reject, params) {
|
function requestReward(resolve, reject, params) {
|
||||||
|
|
|
@ -39,7 +39,7 @@ export const selectPageTitle = createSelector(
|
||||||
return __("Wallet");
|
return __("Wallet");
|
||||||
case "send":
|
case "send":
|
||||||
return __("Send Credits");
|
return __("Send Credits");
|
||||||
case "address":
|
case "receive":
|
||||||
return __("Wallet Address");
|
return __("Wallet Address");
|
||||||
case "backup":
|
case "backup":
|
||||||
return __("Backup Your Wallet");
|
return __("Backup Your Wallet");
|
||||||
|
@ -143,17 +143,17 @@ export const selectHeaderLinks = createSelector(selectCurrentPage, page => {
|
||||||
case "wallet":
|
case "wallet":
|
||||||
case "history":
|
case "history":
|
||||||
case "send":
|
case "send":
|
||||||
case "address":
|
case "receive":
|
||||||
case "invite":
|
case "invite":
|
||||||
case "rewards":
|
case "rewards":
|
||||||
case "backup":
|
case "backup":
|
||||||
return {
|
return {
|
||||||
wallet: __("Overview"),
|
wallet: __("Overview"),
|
||||||
rewards: __("Rewards"),
|
|
||||||
invite: __("Invites"),
|
|
||||||
history: __("History"),
|
history: __("History"),
|
||||||
send: __("Send"),
|
send: __("Send"),
|
||||||
address: __("Address"),
|
receive: __("Receive"),
|
||||||
|
rewards: __("Rewards"),
|
||||||
|
invite: __("Invites"),
|
||||||
};
|
};
|
||||||
case "downloaded":
|
case "downloaded":
|
||||||
case "published":
|
case "published":
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { createSelector } from "reselect";
|
import { createSelector } from "reselect";
|
||||||
import { selectUser } from "selectors/user";
|
import { selectUser } from "selectors/user";
|
||||||
|
import rewards from "rewards";
|
||||||
|
|
||||||
const _selectState = state => state.rewards || {};
|
const _selectState = state => state.rewards || {};
|
||||||
|
|
||||||
|
@ -20,7 +21,13 @@ export const selectClaimedRewards = createSelector(
|
||||||
|
|
||||||
export const selectUnclaimedRewards = createSelector(
|
export const selectUnclaimedRewards = createSelector(
|
||||||
selectUnclaimedRewardsByType,
|
selectUnclaimedRewardsByType,
|
||||||
byType => Object.values(byType) || []
|
byType =>
|
||||||
|
Object.values(byType).sort(function(a, b) {
|
||||||
|
return rewards.SORT_ORDER.indexOf(a.reward_type) <
|
||||||
|
rewards.SORT_ORDER.indexOf(b.reward_type)
|
||||||
|
? -1
|
||||||
|
: 1;
|
||||||
|
}) || []
|
||||||
);
|
);
|
||||||
|
|
||||||
export const selectIsRewardEligible = createSelector(
|
export const selectIsRewardEligible = createSelector(
|
||||||
|
@ -83,3 +90,10 @@ const selectRewardByType = (state, props) => {
|
||||||
export const makeSelectRewardByType = () => {
|
export const makeSelectRewardByType = () => {
|
||||||
return createSelector(selectRewardByType, reward => reward);
|
return createSelector(selectRewardByType, reward => reward);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const makeSelectRewardAmountByType = () => {
|
||||||
|
return createSelector(
|
||||||
|
selectRewardByType,
|
||||||
|
reward => (reward ? reward.reward_amount : 0)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
|
@ -38,6 +38,8 @@ export const selectWunderBarAddress = createSelector(
|
||||||
|
|
||||||
export const selectWunderBarIcon = createSelector(selectCurrentPage, page => {
|
export const selectWunderBarIcon = createSelector(selectCurrentPage, page => {
|
||||||
switch (page) {
|
switch (page) {
|
||||||
|
case "auth":
|
||||||
|
return "icon-user";
|
||||||
case "search":
|
case "search":
|
||||||
return "icon-search";
|
return "icon-search";
|
||||||
case "settings":
|
case "settings":
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
|
|
||||||
$spacing-vertical: 24px;
|
$spacing-vertical: 24px;
|
||||||
|
|
||||||
$padding-button: 12px;
|
$padding-button: $spacing-vertical * 2/3;
|
||||||
$padding-text-link: 4px;
|
$padding-text-link: 0px;
|
||||||
|
|
||||||
$color-primary: #155B4A;
|
$color-primary: #155B4A;
|
||||||
$color-primary-light: saturate(lighten($color-primary, 50%), 20%);
|
$color-primary-light: saturate(lighten($color-primary, 50%), 20%);
|
||||||
|
|
|
@ -134,15 +134,6 @@ p
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*should this be here or work this way? had to hack additional rule below*/
|
|
||||||
.icon:only-child {
|
|
||||||
position: relative;
|
|
||||||
top: 0.16em;
|
|
||||||
}
|
|
||||||
.icon-featured > .icon {
|
|
||||||
top: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.help {
|
.help {
|
||||||
font-size: .85em;
|
font-size: .85em;
|
||||||
color: $color-help;
|
color: $color-help;
|
||||||
|
|
|
@ -8,7 +8,7 @@ $button-focus-shift: 12%;
|
||||||
|
|
||||||
+ .button-set-item
|
+ .button-set-item
|
||||||
{
|
{
|
||||||
margin-left: $padding-button;
|
margin-left: $spacing-vertical;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,10 +23,11 @@ $width-card-small: $spacing-vertical * 10;
|
||||||
}
|
}
|
||||||
.card__title-primary,
|
.card__title-primary,
|
||||||
.card__title-identity,
|
.card__title-identity,
|
||||||
.card__actions,
|
|
||||||
.card__content,
|
.card__content,
|
||||||
.card__subtext {
|
.card__subtext,
|
||||||
padding: 0 $padding-card-horizontal;
|
.card__actions {
|
||||||
|
padding-left: $padding-card-horizontal;
|
||||||
|
padding-right: $padding-card-horizontal;
|
||||||
}
|
}
|
||||||
.card--small {
|
.card--small {
|
||||||
.card__title-primary,
|
.card__title-primary,
|
||||||
|
@ -39,6 +40,7 @@ $width-card-small: $spacing-vertical * 10;
|
||||||
}
|
}
|
||||||
.card__title-primary {
|
.card__title-primary {
|
||||||
margin-top: $spacing-vertical * 2/3;
|
margin-top: $spacing-vertical * 2/3;
|
||||||
|
margin-bottom: $spacing-vertical * 2/3;
|
||||||
}
|
}
|
||||||
.card__title-identity {
|
.card__title-identity {
|
||||||
margin-top: $spacing-vertical * 1/3;
|
margin-top: $spacing-vertical * 1/3;
|
||||||
|
@ -46,13 +48,6 @@ $width-card-small: $spacing-vertical * 10;
|
||||||
}
|
}
|
||||||
.card__actions {
|
.card__actions {
|
||||||
margin-top: $spacing-vertical * 2/3;
|
margin-top: $spacing-vertical * 2/3;
|
||||||
}
|
|
||||||
.card__actions--bottom {
|
|
||||||
margin-top: $spacing-vertical * 1/3;
|
|
||||||
margin-bottom: $spacing-vertical * 1/3;
|
|
||||||
}
|
|
||||||
.card__actions--form-submit {
|
|
||||||
margin-top: $spacing-vertical;
|
|
||||||
margin-bottom: $spacing-vertical * 2/3;
|
margin-bottom: $spacing-vertical * 2/3;
|
||||||
}
|
}
|
||||||
.card__content {
|
.card__content {
|
||||||
|
@ -259,4 +254,21 @@ $padding-right-card-hover-hack: 30px;
|
||||||
|
|
||||||
.card__icon-featured-content {
|
.card__icon-featured-content {
|
||||||
color: orangered;
|
color: orangered;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
if we keep doing things like this, we should add a real grid system, but I'm going to be a selective dick about it - Jeremy
|
||||||
|
*/
|
||||||
|
.card-grid {
|
||||||
|
$margin-card-grid: $spacing-vertical * 2/3;
|
||||||
|
display:flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
> .card {
|
||||||
|
width: $width-page-constrained / 2 - $margin-card-grid / 2;
|
||||||
|
flex-grow:1;
|
||||||
|
}
|
||||||
|
> .card:nth-of-type(2n - 1) {
|
||||||
|
margin-right: $margin-card-grid;
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -52,6 +52,11 @@ table.table-standard {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.table-standard--definition-list {
|
||||||
|
th {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
table.table-stretch {
|
table.table-stretch {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
Loading…
Add table
Reference in a new issue