moderate progress

This commit is contained in:
Jeremy Kauffman 2017-07-16 12:29:46 -04:00
parent b3de4ceee9
commit 16abedbf3a
21 changed files with 228 additions and 78 deletions

View file

@ -8,13 +8,11 @@ import {
selectPageTitle,
selectCurrentPage,
selectCurrentParams,
selectWelcomeModalAcknowledged,
} from "selectors/app";
import { doSearch } from "actions/search";
import { doFetchDaemonSettings } from "actions/settings";
import { doAuthenticate } from "actions/user";
import { doFileList } from "actions/file_info";
import * as modals from "constants/modal_types";
const { remote, ipcRenderer, shell } = require("electron");
const path = require("path");
@ -220,17 +218,13 @@ export function doAlertError(errorList) {
}
export function doDaemonReady() {
return function(dispatch, getState) {
const showWelcome = !selectWelcomeModalAcknowledged(getState());
return function(dispatch) {
dispatch(doAuthenticate());
dispatch({
type: types.DAEMON_READY,
});
dispatch(doFetchDaemonSettings());
dispatch(doFileList());
if (showWelcome) {
dispatch(doOpenModal(modals.WELCOME));
}
};
}

View file

@ -1,18 +1,40 @@
import React from "react";
import { connect } from "react-redux";
import { selectCurrentModal } from "selectors/app";
import { doCheckUpgradeAvailable, doAlertError } from "actions/app";
import {
doCheckUpgradeAvailable,
doOpenModal,
doAlertError,
} from "actions/app";
import { doUpdateBalance } from "actions/wallet";
import { selectWelcomeModalAcknowledged } from "selectors/app";
import rewards from "rewards";
import {
selectFetchingRewards,
makeSelectHasClaimedReward,
} from "selectors/rewards";
import { selectUser } from "selectors/user";
import App from "./view";
import * as modals from "constants/modal_types";
const select = state => ({
modal: selectCurrentModal(state),
});
const select = (state, props) => {
const selectHasClaimed = makeSelectHasClaimedReward();
return {
modal: selectCurrentModal(state),
isWelcomeAcknowledged: selectWelcomeModalAcknowledged(state),
isFetchingRewards: selectFetchingRewards(state),
isWelcomeRewardClaimed: selectHasClaimed(state, {
reward_type: rewards.TYPE_NEW_USER,
}),
user: selectUser(state),
};
};
const perform = dispatch => ({
alertError: errorList => dispatch(doAlertError(errorList)),
checkUpgradeAvailable: () => dispatch(doCheckUpgradeAvailable()),
openWelcomeModal: () => dispatch(doOpenModal(modals.WELCOME)),
updateBalance: balance => dispatch(doUpdateBalance(balance)),
});

View file

@ -11,17 +11,43 @@ import * as modals from "constants/modal_types";
class App extends React.PureComponent {
componentWillMount() {
const { alertError, checkUpgradeAvailable, updateBalance } = this.props;
document.addEventListener("unhandledError", event => {
this.props.alertError(event.detail);
alertError(event.detail);
});
if (!this.props.upgradeSkipped) {
this.props.checkUpgradeAvailable();
checkUpgradeAvailable();
}
lbry.balanceSubscribe(balance => {
this.props.updateBalance(balance);
updateBalance(balance);
});
this.showWelcome(this.props);
}
componentWillReceiveProps(nextProps) {
this.showWelcome(nextProps);
}
showWelcome(props) {
const {
isFetchingRewards,
isWelcomeAcknowledged,
isWelcomeRewardClaimed,
openWelcomeModal,
user,
} = props;
if (
!isWelcomeAcknowledged &&
user &&
(!isFetchingRewards || !isWelcomeRewardClaimed)
) {
openWelcomeModal();
}
}
render() {

View file

@ -4,12 +4,14 @@ import {
selectAuthenticationIsPending,
selectEmailToVerify,
selectUserIsVerificationCandidate,
selectUser,
} from "selectors/user";
import Auth from "./view";
const select = state => ({
isPending: selectAuthenticationIsPending(state),
email: selectEmailToVerify(state),
user: selectUser(state),
isVerificationCandidate: selectUserIsVerificationCandidate(state),
});

View file

@ -2,17 +2,20 @@ import React from "react";
import { BusyMessage } from "component/common";
import UserEmailNew from "component/userEmailNew";
import UserEmailVerify from "component/userEmailVerify";
import UserVerify from "component/userVerify";
export class Auth extends React.PureComponent {
render() {
const { isPending, email, isVerificationCandidate } = this.props;
const { email, isPending, isVerificationCandidate, user } = this.props;
if (isPending) {
return <BusyMessage message={__("Authenticating")} />;
} else if (!email) {
} else if (user && !user.has_verified_email && !email) {
return <UserEmailNew />;
} else if (isVerificationCandidate) {
} else if (user && !user.has_verified_email) {
return <UserEmailVerify />;
} else if (user && !user.is_identity_verified) {
return <UserVerify />;
} else {
return <span className="empty">{__("No further steps.")}</span>;
}

View file

@ -54,7 +54,7 @@ export class AuthOverlay extends React.PureComponent {
? ""
: <div className="form-row-submit">
{!hasEmail && this.state.showNoEmailConfirm
? <div className="help form-input-width">
? <div>
<p>
{__(
"If you continue without an email, you will be ineligible to earn free LBC rewards, as well as unable to receive security related communications."

View file

@ -1,4 +1,5 @@
import React from "react";
import { formatCredits } from "utils";
import lbry from "../lbry.js";
//component/icon.js
@ -78,7 +79,7 @@ export class CreditAmount extends React.PureComponent {
};
render() {
const formattedAmount = lbry.formatCredits(
const formattedAmount = formatCredits(
this.props.amount,
this.props.precision
);
@ -140,7 +141,7 @@ export class Address extends React.PureComponent {
}}
style={addressStyle}
readOnly="readonly"
value={this.props.address}
value={this.props.address || ""}
/>
);
}

View file

@ -1,12 +1,12 @@
import React from "react";
import lbry from "lbry";
import { formatCredits } from "utils";
import { connect } from "react-redux";
import { selectBalance } from "selectors/wallet";
import { doNavigate, doHistoryBack } from "actions/app";
import Header from "./view";
const select = state => ({
balance: lbry.formatCredits(selectBalance(state), 1),
balance: formatCredits(selectBalance(state), 1),
publish: __("Publish"),
});

View file

@ -31,8 +31,11 @@ class ModalWelcome extends React.PureComponent {
)}
</p>
<p>
{__("Thank you for making content freedom possible!")}
{" "}{isRewardApproved ? __("Here's a nickel, kid.") : ""}
{__("Please have")} {" "}
{reward &&
<CreditAmount amount={parseFloat(reward.reward_amount)} />}
{!reward && <span className="credit-amount">{__("??")}</span>}
{" "} {__("as a thank you for building content freedom.")}
</p>
<div className="text-center">
{isRewardApproved &&
@ -40,15 +43,11 @@ class ModalWelcome extends React.PureComponent {
{!isRewardApproved &&
<Link
button="primary"
onClick={closeModal}
label={__("Continue")}
onClick={verifyAccount}
label={__("Get Welcome Credits")}
/>}
{!isRewardApproved &&
<Link
button="alt"
onClick={verifyAccount}
label={__("Do Account Thing")}
/>}
<Link button="alt" onClick={closeModal} label={__("Skip")} />}
</div>
</section>
</Modal>

View file

@ -27,7 +27,6 @@ class UserEmailNew extends React.PureComponent {
return (
<form
className="form-input-width"
onSubmit={event => {
this.handleSubmit(event);
}}

View file

@ -27,7 +27,6 @@ class UserEmailVerify extends React.PureComponent {
return (
<form
className="form-input-width"
onSubmit={event => {
this.handleSubmit(event);
}}

View file

@ -0,0 +1,21 @@
import React from "react";
import { connect } from "react-redux";
import { doUserEmailVerify } from "actions/user";
import {
selectEmailVerifyIsPending,
selectEmailToVerify,
selectEmailVerifyErrorMessage,
} from "selectors/user";
import UserVerify from "./view";
const select = state => ({
isPending: selectEmailVerifyIsPending(state),
email: selectEmailToVerify(state),
errorMessage: selectEmailVerifyErrorMessage(state),
});
const perform = dispatch => ({
verifyUserEmail: code => dispatch(doUserEmailVerify(code)),
});
export default connect(select, perform)(UserVerify);

View file

@ -0,0 +1,69 @@
import React from "react";
import Link from "component/link";
import { FormRow } from "component/form.js";
class UserVerify extends React.PureComponent {
constructor(props) {
super(props);
this.state = {
code: "",
};
}
handleCodeChanged(event) {
this.setState({
code: event.target.value,
});
}
handleSubmit(event) {
event.preventDefault();
this.props.verifyUserEmail(this.state.code);
}
render() {
const { errorMessage, isPending } = this.props;
return <p>VERIFY</p>;
return (
<form
onSubmit={event => {
this.handleSubmit(event);
}}
>
zzzzzzzzzzzzzzzzzzzzzzzzzzzzz
<FormRow
type="text"
label={__("Verification Code")}
placeholder="a94bXXXXXXXXXXXXXX"
name="code"
value={this.state.code}
onChange={event => {
this.handleCodeChanged(event);
}}
errorMessage={errorMessage}
/>
{/* render help separately so it always shows */}
<div className="form-field__helper">
<p>
{__("Email")}{" "}
<Link href="mailto:help@lbry.io" label="help@lbry.io" />{" "}
{__("if you did not receive or are having trouble with your code.")}
</p>
</div>
<div className="form-row-submit form-row-submit--with-footer">
<Link
button="primary"
label={__("Verify")}
disabled={this.state.submitting}
onClick={event => {
this.handleSubmit(event);
}}
/>
</div>
</form>
);
}
}
export default UserVerify;

View file

@ -288,11 +288,6 @@ lbry.setClientSetting = function(setting, value) {
return localStorage.setItem("setting_" + setting, JSON.stringify(value));
};
//utilities
lbry.formatCredits = function(amount, precision) {
return amount.toFixed(precision || 1).replace(/\.?0+$/, "");
};
lbry.formatName = function(name) {
// Converts LBRY name to standard format (all lower case, no special characters, spaces replaced by dashes)
name = name.replace("/s+/g", "-");

View file

@ -1,22 +1,31 @@
import React from "react";
import { connect } from "react-redux";
import { doNavigate } from "actions/app";
import { selectFetchingRewards, selectRewards } from "selectors/rewards";
import {
makeSelectRewardByType,
selectFetchingRewards,
selectRewards,
} from "selectors/rewards";
import {
selectUserIsRewardEligible,
selectUserHasEmail,
selectUserIsVerificationCandidate,
} from "selectors/user";
import { doRewardList } from "actions/rewards";
import rewards from "rewards";
import RewardsPage from "./view";
const select = state => ({
fetching: selectFetchingRewards(state),
rewards: selectRewards(state),
hasEmail: selectUserHasEmail(state),
isEligible: selectUserIsRewardEligible(state),
isVerificationCandidate: selectUserIsVerificationCandidate(state),
});
const select = (state, props) => {
const selectReward = makeSelectRewardByType();
return {
fetching: selectFetchingRewards(state),
rewards: selectRewards(state),
hasEmail: selectUserHasEmail(state),
isEligible: selectUserIsRewardEligible(state),
isVerificationCandidate: selectUserIsVerificationCandidate(state),
newUserReward: selectReward(state, { reward_type: rewards.TYPE_NEW_USER }),
};
};
const perform = dispatch => ({
fetchRewards: () => dispatch(doRewardList()),

View file

@ -1,9 +1,7 @@
import React from "react";
import lbryio from "lbryio";
import { BusyMessage, CreditAmount, Icon } from "component/common";
import SubHeader from "component/subHeader";
import Auth from "component/auth";
import Link from "component/link";
import RewardLink from "component/rewardLink";
const RewardTile = props => {
@ -41,7 +39,9 @@ class RewardsPage extends React.PureComponent {
fetchRewards(props) {
const { fetching, rewards, fetchRewards } = props;
if (!fetching && Object.keys(rewards).length < 1) fetchRewards();
if (!fetching && (!rewards || !rewards.length)) {
fetchRewards();
}
}
render() {
@ -51,6 +51,7 @@ class RewardsPage extends React.PureComponent {
isVerificationCandidate,
hasEmail,
rewards,
newUserReward,
} = this.props;
let content,
@ -59,42 +60,55 @@ class RewardsPage extends React.PureComponent {
if (!hasEmail || isVerificationCandidate) {
content = (
<div>
<p>
{__(
"Additional information is required to be eligible for the rewards program."
)}
</p>
<Auth />
<div className="card__title-primary">
{newUserReward &&
<CreditAmount amount={newUserReward.reward_amount} />}
<h3>Welcome to LBRY</h3>
</div>
<div className="card__content">
<p>
{" "}{__(
"Claim your welcome credits to be able to publish content, pay creators, and have a say over the LBRY network."
)}
</p>
</div>
<div className="card__content"><Auth /></div>
</div>
);
isCard = true;
} else if (!isEligible) {
isCard = true;
content = (
<div className="empty">
<div className="card__content empty">
<p>{__("You are not eligible to claim rewards.")}</p>
</div>
);
} else if (fetching) {
content = <BusyMessage message={__("Fetching rewards")} />;
content = (
<div className="card__content">
<BusyMessage message={__("Fetching rewards")} />
</div>
);
} else if (rewards.length > 0) {
content = rewards.map(reward =>
<RewardTile key={reward.reward_type} reward={reward} />
content = (
<div>
{rewards.map(reward =>
<RewardTile key={reward.reward_type} reward={reward} />
)}
</div>
);
} else {
content = <div className="empty">{__("Failed to load rewards.")}</div>;
content = (
<div className="card__content empty">
{__("Failed to load rewards.")}
</div>
);
}
return (
<main className="main--single-column">
<SubHeader />
{isCard
? <section className="card">
<div className="card__content">
{content}
</div>
</section>
: content}
{isCard ? <section className="card">{content}</section> : content}
</main>
);
}

View file

@ -12,10 +12,7 @@ export const selectUserIsPending = createSelector(
state => state.userIsPending
);
export const selectUser = createSelector(
_selectState,
state => state.user || {}
);
export const selectUser = createSelector(_selectState, state => state.user);
export const selectEmailToVerify = createSelector(
_selectState,
@ -65,7 +62,7 @@ export const selectEmailVerifyErrorMessage = createSelector(
export const selectUserIsVerificationCandidate = createSelector(
selectUser,
user => user && !user.has_verified_email
user => user && (!user.has_verified_email || !user.is_identity_verified)
);
export const selectUserIsAuthRequested = createSelector(

View file

@ -29,3 +29,7 @@ export function getSession(key, fallback = undefined) {
export function setSession(key, value) {
sessionStorage.setItem(key, JSON.stringify(value));
}
export function formatCredits(amount, precision) {
return amount.toFixed(precision || 1).replace(/\.?0+$/, "");
}

View file

@ -3,10 +3,6 @@
$width-input-border: 2px;
$width-input-text: 330px;
.form-input-width {
width: $width-input-text
}
.form-row-submit
{
margin-top: $spacing-vertical;