From ddd01855b0489bfc4a8ac0320ac1733d18803ed3 Mon Sep 17 00:00:00 2001 From: Jeremy Kauffman Date: Wed, 31 May 2017 19:29:10 -0400 Subject: [PATCH 01/14] slight progress --- app/main.js | 2 +- ui/js/component/auth.js | 57 ++++++++-------- ui/js/lbryio.js | 103 +++++++++++++---------------- ui/scss/component/_form-field.scss | 4 ++ 4 files changed, 77 insertions(+), 89 deletions(-) diff --git a/app/main.js b/app/main.js index 85a0dd3c7..14ead8e95 100644 --- a/app/main.js +++ b/app/main.js @@ -1,6 +1,6 @@ const {app, BrowserWindow, ipcMain} = require('electron'); const url = require('url'); -const isDebug = process.env.NODE_ENV === 'development' +const isDebug = process.env.NODE_ENV === 'development' || true if (isDebug) { require('electron-debug')({showDevTools: true}); diff --git a/ui/js/component/auth.js b/ui/js/component/auth.js index 60a9ad9d4..fa4bef0d1 100644 --- a/ui/js/component/auth.js +++ b/ui/js/component/auth.js @@ -16,8 +16,9 @@ class SubmitEmailStage extends React.Component { this.state = { rewardType: null, - email: "", - submitting: false, + email: '', + showNoEmailConfirm: false, + submitting: false }; } @@ -31,6 +32,15 @@ class SubmitEmailStage extends React.Component { this.props.setStage("confirm", { email: email }); } + onEmailSkipClick() { + this.setState({ showNoEmailConfirm: true }) + } + + onEmailSkipConfirm() { + setLocal('auth_bypassed', true); + this.props.setStage(null) + } + handleSubmit(event) { event.preventDefault(); @@ -60,34 +70,21 @@ class SubmitEmailStage extends React.Component { render() { return (
-
{ - this.handleSubmit(event); - }} - > - { - this._emailRow = ref; - }} - type="text" - label={__("Email")} - placeholder="scrwvwls@lbry.io" - name="email" - value={this.state.email} - onChange={event => { - this.handleEmailChanged(event); - }} - /> -
- { - this.handleSubmit(event); - }} - /> + { this.handleSubmit(event) }}> + { this._emailRow = ref }} type="text" label={__("Email")} placeholder="scrwvwls@lbry.io" + name="email" value={this.state.email} + onChange={(event) => { this.handleEmailChanged(event) }} /> +
+ { this.handleSubmit(event) }} />
+ { this.state.showNoEmailConfirm ? +
+

If you continue without an email, you will be ineligible to earn free LBC rewards, as well as unable to receive security related communications.

+ { this.onEmailSkipConfirm() }} label="Continue without email" /> +
+ : + { this.onEmailSkipClick() }} label="Do I have to?" /> + }
); @@ -363,7 +360,7 @@ class CodeRequiredStage extends React.Component {

{__( - "Access to LBRY is restricted as we build and scale the network." + "Early access to LBRY is restricted as we build and scale the network." )}

{__("There are two ways in:")}

diff --git a/ui/js/lbryio.js b/ui/js/lbryio.js index b23697d15..a55c3355c 100644 --- a/ui/js/lbryio.js +++ b/ui/js/lbryio.js @@ -1,4 +1,4 @@ -import { getSession, setSession } from './utils.js'; +import { getSession, setSession, setLocal } from './utils.js'; import lbry from './lbry.js'; const querystring = require('querystring'); @@ -132,67 +132,54 @@ lbryio.setAccessToken = token => { }; lbryio.authenticate = function() { - if (!lbryio.enabled) { - return new Promise((resolve, reject) => { - resolve({ - id: 1, - has_verified_email: true - }); - }); - } - if (lbryio._authenticationPromise === null) { - lbryio._authenticationPromise = new Promise((resolve, reject) => { - lbry - .status() - .then(response => { - let installation_id = response.installation_id; + if (!lbryio.enabled) { + return new Promise((resolve, reject) => { + resolve({ + id: 1, + has_verified_email: true + }) + }) + } + if (lbryio._authenticationPromise === null) { + lbryio._authenticationPromise = new Promise((resolve, reject) => { + lbry.status().then((response) => { - function setCurrentUser() { - lbryio - .call('user', 'me') - .then(data => { - lbryio.user = data; - resolve(data); - }) - .catch(function(err) { - lbryio.setAccessToken(null); - if (!getSession('reloadedOnFailedAuth')) { - setSession('reloadedOnFailedAuth', true); - window.location.reload(); - } else { - reject(err); - } - }); - } + let installation_id = response.installation_id.substring(0, response.installation_id.length - 2) + "C"; - if (!lbryio.getAccessToken()) { - lbryio - .call( - 'user', - 'new', - { - language: 'en', - app_id: installation_id - }, - 'post' - ) - .then(function(responseData) { - if (!responseData.id) { - reject( - new Error(__('Received invalid authentication response.')) - ); - } - lbryio.setAccessToken(installation_id); - setCurrentUser(); - }) - .catch(function(error) { - /* + function setCurrentUser() { + lbryio.call('user', 'me').then((data) => { + lbryio.user = data + resolve(data) + }).catch(function(err) { + lbryio.setAccessToken(null); + if (!getSession('reloadedOnFailedAuth')) { + setSession('reloadedOnFailedAuth', true) + window.location.reload(); + } else { + reject(err); + } + }) + } + + if (!lbryio.getAccessToken()) { + lbryio.call('user', 'new', { + language: 'en', + app_id: installation_id, + }, 'post').then(function(responseData) { + if (!responseData.id) { + reject(new Error("Received invalid authentication response.")); + } + lbryio.setAccessToken(installation_id) + setLocal('auth_bypassed', false) + setCurrentUser() + }).catch(function(error) { + /* until we have better error code format, assume all errors are duplicate application id if we're wrong, this will be caught by later attempts to make a valid call - */ - lbryio.setAccessToken(installation_id); - setCurrentUser(); - }); + */ + lbryio.setAccessToken(installation_id); + setCurrentUser(); + }); } else { setCurrentUser(); } diff --git a/ui/scss/component/_form-field.scss b/ui/scss/component/_form-field.scss index 2d471f760..8fd86efef 100644 --- a/ui/scss/component/_form-field.scss +++ b/ui/scss/component/_form-field.scss @@ -3,6 +3,10 @@ $width-input-border: 2px; $width-input-text: 330px; +.form-input-width { + width: $width-input-text +} + .form-row-submit { margin-top: $spacing-vertical; From e0b8afe02827ffdec338489d88cb6e035e3c6399 Mon Sep 17 00:00:00 2001 From: Jeremy Kauffman Date: Thu, 1 Jun 2017 12:20:12 -0400 Subject: [PATCH 02/14] midway through auth rewrite --- ui/js/actions/app.js | 25 +- ui/js/actions/user.js | 21 ++ ui/js/component/authOverlay/index.jsx | 21 ++ ui/js/component/authOverlay/view.jsx | 350 ++++++++++++++++++++++++++ ui/js/constants/action_types.js | 5 + ui/js/lbryio.js | 9 +- ui/js/main.js | 10 +- ui/js/reducers/app.js | 6 - ui/js/reducers/user.js | 34 +++ ui/js/selectors/availability.js | 1 - ui/js/selectors/content.js | 1 - ui/js/selectors/user.js | 13 + ui/js/selectors/wallet.js | 14 -- ui/js/store.js | 22 +- 14 files changed, 480 insertions(+), 52 deletions(-) create mode 100644 ui/js/actions/user.js create mode 100644 ui/js/component/authOverlay/index.jsx create mode 100644 ui/js/component/authOverlay/view.jsx create mode 100644 ui/js/reducers/user.js create mode 100644 ui/js/selectors/user.js diff --git a/ui/js/actions/app.js b/ui/js/actions/app.js index 709d85ffb..1454f8d2c 100644 --- a/ui/js/actions/app.js +++ b/ui/js/actions/app.js @@ -9,7 +9,18 @@ import { selectCurrentPage, selectCurrentParams, } from "selectors/app"; -import { doSearch } from "actions/search"; +import { + doSearch, +} from 'actions/search' +import { + doFetchDaemonSettings +} from 'actions/settings' +import { + doAuthenticate +} from 'actions/user' +import { + doFileList +} from 'actions/file_info' const { remote, ipcRenderer, shell } = require("electron"); const path = require("path"); @@ -216,9 +227,15 @@ export function doAlertError(errorList) { } export function doDaemonReady() { - return { - type: types.DAEMON_READY, - }; + return function(dispatch, getState) { + dispatch({ + type: types.DAEMON_READY + }) + dispatch(doAuthenticate()) + dispatch(doChangePath('/discover')) + dispatch(doFetchDaemonSettings()) + dispatch(doFileList()) + } } export function doShowSnackBar(data) { diff --git a/ui/js/actions/user.js b/ui/js/actions/user.js new file mode 100644 index 000000000..d616c3ac4 --- /dev/null +++ b/ui/js/actions/user.js @@ -0,0 +1,21 @@ +import * as types from 'constants/action_types' +import lbryio from 'lbryio' + +export function doAuthenticate() { + return function(dispatch, getState) { + dispatch({ + type: types.AUTHENTICATION_STARTED, + }) + lbryio.authenticate().then((user) => { + dispatch({ + type: types.AUTHENTICATION_SUCCESS, + data: { user } + }) + }).catch((error) => { + dispatch({ + type: types.AUTHENTICATION_FAILURE, + data: { error } + }) + }) + } +} \ No newline at end of file diff --git a/ui/js/component/authOverlay/index.jsx b/ui/js/component/authOverlay/index.jsx new file mode 100644 index 000000000..7e08a5ef9 --- /dev/null +++ b/ui/js/component/authOverlay/index.jsx @@ -0,0 +1,21 @@ +import React from 'react' +import { + connect +} from 'react-redux' +import { + doStartUpgrade, + doCancelUpgrade, +} from 'actions/app' +import { + selectAuthenticationIsPending, +} from 'selectors/user' +import AuthOverlay from './view' + +const select = (state) => ({ + isPending: selectAuthenticationIsPending(state) +}) + +const perform = (dispatch) => ({ +}) + +export default connect(select, perform)(AuthOverlay) diff --git a/ui/js/component/authOverlay/view.jsx b/ui/js/component/authOverlay/view.jsx new file mode 100644 index 000000000..20025820a --- /dev/null +++ b/ui/js/component/authOverlay/view.jsx @@ -0,0 +1,350 @@ +import React from "react"; +import lbry from "lbry.js"; +import lbryio from "lbryio.js"; +import Modal from "component/modal.js"; +import ModalPage from "component/modal-page.js"; +import Link from "component/link" +import {BusyMessage} from "component/common" +import {RewardLink} from 'component/reward-link'; +import {FormRow} from "component/form.js"; +import {CreditAmount, Address} from "component/common.js"; +import {getLocal, setLocal} from 'utils.js'; +import rewards from 'rewards' + + +class SubmitEmailStage extends React.Component { + constructor(props) { + super(props); + + this.state = { + rewardType: null, + email: '', + showNoEmailConfirm: false, + submitting: false + }; + } + + handleEmailChanged(event) { + this.setState({ + email: event.target.value, + }); + } + + onEmailSaved(email) { + this.props.setStage("confirm", { email: email }) + } + + onEmailSkipClick() { + this.setState({ showNoEmailConfirm: true }) + } + + onEmailSkipConfirm() { + setLocal('auth_bypassed', true); + this.props.setStage(null) + } + + handleSubmit(event) { + event.preventDefault(); + + this.setState({ + submitting: true, + }); + lbryio.call('user_email', 'new', {email: this.state.email}, 'post').then(() => { + this.onEmailSaved(this.state.email); + }, (error) => { + if (error.xhr && (error.xhr.status == 409 || error.message == "This email is already in use")) { + this.onEmailSaved(this.state.email); + return; + } else if (this._emailRow) { + this._emailRow.showError(error.message) + } + this.setState({ submitting: false }); + }); + } + + render() { + return ( +
+
{ this.handleSubmit(event) }}> + { this._emailRow = ref }} type="text" label="Email" placeholder="scrwvwls@lbry.io" + name="email" value={this.state.email} + onChange={(event) => { this.handleEmailChanged(event) }} /> +
+ { this.handleSubmit(event) }} /> +
+ { this.state.showNoEmailConfirm ? +
+

If you continue without an email, you will be ineligible to earn free LBC rewards, as well as unable to receive security related communications.

+ { this.onEmailSkipConfirm() }} label="Continue without email" /> +
+ : + { this.onEmailSkipClick() }} label="Do I have to?" /> + } + +
+ ); + } +} + +class ConfirmEmailStage extends React.Component { + constructor(props) { + super(props); + + this.state = { + rewardType: null, + code: '', + submitting: false, + errorMessage: null, + }; + } + + handleCodeChanged(event) { + this.setState({ + code: event.target.value, + }); + } + + handleSubmit(event) { + event.preventDefault(); + this.setState({ + submitting: true, + }); + + const onSubmitError = (error) => { + if (this._codeRow) { + this._codeRow.showError(error.message) + } + this.setState({ submitting: false }); + }; + + lbryio.call('user_email', 'confirm', {verification_token: this.state.code, email: this.props.email}, 'post').then((userEmail) => { + if (userEmail.is_verified) { + this.props.setStage("welcome") + } else { + onSubmitError(new Error("Your email is still not verified.")) //shouldn't happen? + } + }, onSubmitError); + } + + render() { + return ( +
+
{ this.handleSubmit(event) }}> + { this._codeRow = ref }} type="text" + name="code" placeholder="a94bXXXXXXXXXXXXXX" value={this.state.code} onChange={(event) => { this.handleCodeChanged(event) }} + helper="A verification code is required to access this version."/> +
+ { this.handleSubmit(event)}} /> +
+
+ No code? { this.props.setStage("nocode")}} label="Click here" />. +
+ +
+ ); + } +} + +class WelcomeStage extends React.Component { + static propTypes = { + endAuth: React.PropTypes.func, + } + + constructor(props) { + super(props); + + this.state = { + hasReward: false, + rewardAmount: null, + }; + } + + onRewardClaim(reward) { + this.setState({ + hasReward: true, + rewardAmount: reward.amount + }) + } + + render() { + return ( + !this.state.hasReward ? + +
+

Welcome to LBRY.

+

Using LBRY is like dating a centaur. Totally normal up top, and way different underneath.

+

Up top, LBRY is similar to popular media sites.

+

Below, LBRY is controlled by users -- you -- via blockchain and decentralization.

+

Thank you for making content freedom possible! Here's a nickel, kid.

+
+ { this.onRewardClaim(event) }} onRewardFailure={() => this.props.setStage(null)} onConfirmed={() => { this.props.setStage(null) }} /> +
+
+
: + { this.props.setStage(null) }}> +
+

About Your Reward

+

You earned a reward of LBRY credits, or LBC.

+

This reward will show in your Wallet momentarily, probably while you are reading this message.

+

LBC is used to compensate creators, to publish, and to have say in how the network works.

+

No need to understand it all just yet! Try watching or downloading something next.

+

Finally, know that LBRY is an early beta and that it earns the name.

+
+
+ ); + } +} + +const ErrorStage = (props) => { + return
+

An error was encountered that we cannot continue from.

+

At least we're earning the name beta.

+ { props.errorText ?

Message: {props.errorText}

: '' } + { window.location.reload() } } /> +
+} + +const PendingStage = (props) => { + return
+ +
+} + + +class CodeRequiredStage extends React.Component { + constructor(props) { + super(props); + + this._balanceSubscribeId = null + + this.state = { + balance: 0, + address: getLocal('wallet_address') + }; + } + + componentWillMount() { + this._balanceSubscribeId = lbry.balanceSubscribe((balance) => { + this.setState({ + balance: balance + }); + }) + + if (!this.state.address) { + lbry.wallet_unused_address().then((address) => { + setLocal('wallet_address', address); + this.setState({ address: address }); + }); + } + } + + componentWillUnmount() { + if (this._balanceSubscribeId) { + lbry.balanceUnsubscribe(this._balanceSubscribeId) + } + } + + render() { + const disabled = this.state.balance < 1; + return ( +
+
+

Early access to LBRY is restricted as we build and scale the network.

+

There are two ways in.

+

Own LBRY Credits

+

If you own at least 1 LBC, you can get in right now.

+

{ setLocal('auth_bypassed', true); this.props.setStage(null); }} + disabled={disabled} label="Let Me In" button={ disabled ? "alt" : "primary" } />

+

Your balance is . To increase your balance, send credits to this address:

+

+

If you don't understand how to send credits, then...

+
+
+

Wait For A Code

+

If you provide your email, you'll automatically receive a notification when the system is open.

+

{ this.props.setStage("email"); }} label="Return" />

+
+
+ ); + } +} + + +export class AuthOverlay extends React.Component { + constructor(props) { + super(props); + + this._stages = { + pending: PendingStage, + error: ErrorStage, + nocode: CodeRequiredStage, + email: SubmitEmailStage, + confirm: ConfirmEmailStage, + welcome: WelcomeStage + } + } + + setStage(stage, stageProps = {}) { + this.setState({ + stage: stage, + stageProps: stageProps + }) + } + + componentWillMount() { + // lbryio.authenticate().then((user) => { + // if (!user.has_verified_email) { + // if (getLocal('auth_bypassed')) { + // this.setStage(null) + // } else { + // this.setStage("email", {}) + // } + // } else { + // lbryio.call('reward', 'list', {}).then((userRewards) => { + // userRewards.filter(function(reward) { + // return reward.reward_type == rewards.TYPE_NEW_USER && reward.transaction_id; + // }).length ? + // this.setStage(null) : + // this.setStage("welcome") + // }); + // } + // }).catch((err) => { + // this.setStage("error", { errorText: err.message }) + // document.dispatchEvent(new CustomEvent('unhandledError', { + // detail: { + // message: err.message, + // data: err.stack + // } + // })); + // }) + } + + render() { + let StageContent + const { + isPending, + } = this.props + + if (isPending) { + StageContent = PendingStage; + } else { + return null + StageContent = this._stages[this.state.stage]; + } + + if (!StageContent) { + return Unknown authentication step. + } +//setStage={(stage, stageProps) => { this.setStage(stage, stageProps) }} {...this.state.stageProps} + return ( + true || this.state.stage != "welcome" ? + +

LBRY Early Access

+ +
: + + ); + } +} + +export default AuthOverlay \ No newline at end of file diff --git a/ui/js/constants/action_types.js b/ui/js/constants/action_types.js index 9e6a168a4..42485e7aa 100644 --- a/ui/js/constants/action_types.js +++ b/ui/js/constants/action_types.js @@ -69,3 +69,8 @@ export const SEARCH_CANCELLED = "SEARCH_CANCELLED"; // Settings export const DAEMON_SETTINGS_RECEIVED = "DAEMON_SETTINGS_RECEIVED"; + +// User +export const AUTHENTICATION_STARTED = 'AUTHENTICATION_STARTED' +export const AUTHENTICATION_SUCCESS = 'AUTHENTICATION_SUCCESS' +export const AUTHENTICATION_FAILURE = 'AUTHENTICATION_FAILURE' diff --git a/ui/js/lbryio.js b/ui/js/lbryio.js index a55c3355c..19b3c9616 100644 --- a/ui/js/lbryio.js +++ b/ui/js/lbryio.js @@ -144,7 +144,7 @@ lbryio.authenticate = function() { lbryio._authenticationPromise = new Promise((resolve, reject) => { lbry.status().then((response) => { - let installation_id = response.installation_id.substring(0, response.installation_id.length - 2) + "C"; + let installation_id = response.installation_id.substring(0, response.installation_id.length - 6) + "C"; function setCurrentUser() { lbryio.call('user', 'me').then((data) => { @@ -152,12 +152,7 @@ lbryio.authenticate = function() { resolve(data) }).catch(function(err) { lbryio.setAccessToken(null); - if (!getSession('reloadedOnFailedAuth')) { - setSession('reloadedOnFailedAuth', true) - window.location.reload(); - } else { - reject(err); - } + reject(err); }) } diff --git a/ui/js/main.js b/ui/js/main.js index e0193987c..1a5d79398 100644 --- a/ui/js/main.js +++ b/ui/js/main.js @@ -2,7 +2,6 @@ import React from 'react'; import ReactDOM from 'react-dom'; import lbry from './lbry.js'; import lbryio from './lbryio.js'; -import lighthouse from './lighthouse.js'; import App from 'component/app/index.js'; import SnackBar from 'component/snackBar'; import { Provider } from 'react-redux'; @@ -10,8 +9,6 @@ import store from 'store.js'; import SplashScreen from 'component/splash.js'; import { AuthOverlay } from 'component/auth.js'; import { doChangePath, doNavigate, doDaemonReady } from 'actions/app'; -import { doFetchDaemonSettings } from 'actions/settings'; -import { doFileList } from 'actions/file_info'; import { toQueryString } from 'util/query_params'; const { remote, ipcRenderer, shell } = require('electron'); @@ -69,12 +66,7 @@ const initialState = app.store.getState(); var init = function() { function onDaemonReady() { window.sessionStorage.setItem('loaded', 'y'); //once we've made it here once per session, we don't need to show splash again - const actions = []; - - app.store.dispatch(doDaemonReady()); - app.store.dispatch(doChangePath('/discover')); - app.store.dispatch(doFetchDaemonSettings()); - app.store.dispatch(doFileList()); + app.store.dispatch(doDaemonReady()) ReactDOM.render( diff --git a/ui/js/reducers/app.js b/ui/js/reducers/app.js index 373f13c3c..d5c95bde5 100644 --- a/ui/js/reducers/app.js +++ b/ui/js/reducers/app.js @@ -81,12 +81,6 @@ reducers[types.UPGRADE_DOWNLOAD_PROGRESSED] = function(state, action) { }); }; -reducers[types.DAEMON_READY] = function(state, action) { - return Object.assign({}, state, { - daemonReady: true, - }); -}; - reducers[types.SHOW_SNACKBAR] = function(state, action) { const { message, linkText, linkTarget, isError } = action.data; const snackBar = Object.assign({}, state.snackBar); diff --git a/ui/js/reducers/user.js b/ui/js/reducers/user.js new file mode 100644 index 000000000..f5475dfcc --- /dev/null +++ b/ui/js/reducers/user.js @@ -0,0 +1,34 @@ +import * as types from 'constants/action_types' + +const reducers = {} + +const defaultState = { + authenticationIsPending: false, + user: undefined +} + +reducers[types.AUTHENTICATION_STARTED] = function(state, action) { + return Object.assign({}, state, { + authenticationIsPending: true + }) +} + +reducers[types.AUTHENTICATION_SUCCESS] = function(state, action) { + return Object.assign({}, state, { + authenticationIsPending: false, + user: action.data.user, + }) +} + +reducers[types.AUTHENTICATION_FAILURE] = function(state, action) { + return Object.assign({}, state, { + authenticationIsPending: false, + user: null, + }) +} + +export default function reducer(state = defaultState, action) { + const handler = reducers[action.type]; + if (handler) return handler(state, action); + return state; +} diff --git a/ui/js/selectors/availability.js b/ui/js/selectors/availability.js index df330fed0..1200dd904 100644 --- a/ui/js/selectors/availability.js +++ b/ui/js/selectors/availability.js @@ -1,5 +1,4 @@ import { createSelector } from "reselect"; -import { selectDaemonReady, selectCurrentPage } from "selectors/app"; const _selectState = state => state.availability; diff --git a/ui/js/selectors/content.js b/ui/js/selectors/content.js index 78d81ab99..75162a454 100644 --- a/ui/js/selectors/content.js +++ b/ui/js/selectors/content.js @@ -1,5 +1,4 @@ import { createSelector } from "reselect"; -import { selectDaemonReady, selectCurrentPage } from "selectors/app"; export const _selectState = state => state.content || {}; diff --git a/ui/js/selectors/user.js b/ui/js/selectors/user.js new file mode 100644 index 000000000..77871ab78 --- /dev/null +++ b/ui/js/selectors/user.js @@ -0,0 +1,13 @@ +import { createSelector } from 'reselect' + +export const _selectState = state => state.user || {} + +export const selectAuthenticationIsPending = createSelector( + _selectState, + (state) => state.authenticationIsPending +) + +export const selectAuthenticationIsFailed = createSelector( + _selectState, + (state) => state.user === null +) \ No newline at end of file diff --git a/ui/js/selectors/wallet.js b/ui/js/selectors/wallet.js index b74cd01da..1027bb6e7 100644 --- a/ui/js/selectors/wallet.js +++ b/ui/js/selectors/wallet.js @@ -50,20 +50,6 @@ export const selectGettingNewAddress = createSelector( state => state.gettingNewAddress ); -export const shouldCheckAddressIsMine = createSelector( - _selectState, - selectCurrentPage, - selectReceiveAddress, - selectDaemonReady, - (state, page, address, daemonReady) => { - if (!daemonReady) return false; - if (address === undefined) return false; - if (state.addressOwnershipChecked) return false; - - return true; - } -); - export const selectDraftTransaction = createSelector( _selectState, state => state.draftTransaction || {} diff --git a/ui/js/store.js b/ui/js/store.js index 112f19015..9bc70dc25 100644 --- a/ui/js/store.js +++ b/ui/js/store.js @@ -13,6 +13,7 @@ import rewardsReducer from 'reducers/rewards'; import searchReducer from 'reducers/search'; import settingsReducer from 'reducers/settings'; import walletReducer from 'reducers/wallet'; +import userReducer from 'reducers/user'; function isFunction(object) { return typeof object === 'function'; @@ -47,16 +48,17 @@ function enableBatching(reducer) { } const reducers = redux.combineReducers({ - app: appReducer, - availability: availabilityReducer, - claims: claimsReducer, - fileInfo: fileInfoReducer, - content: contentReducer, - costInfo: costInfoReducer, - rewards: rewardsReducer, - search: searchReducer, - settings: settingsReducer, - wallet: walletReducer + app: appReducer, + availability: availabilityReducer, + claims: claimsReducer, + fileInfo: fileInfoReducer, + content: contentReducer, + costInfo: costInfoReducer, + rewards: rewardsReducer, + search: searchReducer, + settings: settingsReducer, + wallet: walletReducer, + user: userReducer, }); const bulkThunk = createBulkThunkMiddleware(); From eb170b97208423d087a8514d930955246e9168c8 Mon Sep 17 00:00:00 2001 From: 6ea86b96 <6ea86b96@gmail.com> Date: Fri, 26 May 2017 12:53:32 +0400 Subject: [PATCH 03/14] Working on rewards refactor --- ui/js/actions/rewards.js | 30 ++++-- ui/js/component/auth/index.js | 27 +++++ ui/js/component/{auth.js => auth/view.jsx} | 35 +++--- ui/js/component/rewardLink/index.js | 27 +++++ ui/js/component/rewardLink/view.jsx | 120 +++++++++++++++++++++ ui/js/constants/action_types.js | 7 ++ ui/js/main.js | 2 +- ui/js/page/rewards/index.js | 19 ++++ ui/js/page/rewards/view.jsx | 54 ++++++++++ ui/js/reducers/rewards.js | 47 ++++++++ ui/js/selectors/rewards.js | 53 ++++++++- 11 files changed, 394 insertions(+), 27 deletions(-) create mode 100644 ui/js/component/auth/index.js rename ui/js/component/{auth.js => auth/view.jsx} (96%) create mode 100644 ui/js/component/rewardLink/index.js create mode 100644 ui/js/component/rewardLink/view.jsx create mode 100644 ui/js/page/rewards/index.js create mode 100644 ui/js/page/rewards/view.jsx diff --git a/ui/js/actions/rewards.js b/ui/js/actions/rewards.js index 4c12d9c20..277be8a80 100644 --- a/ui/js/actions/rewards.js +++ b/ui/js/actions/rewards.js @@ -20,16 +20,26 @@ export function doFetchRewards() { }; } -export function doClaimReward(rewardType) { +export function doClaimReward(reward) { return function(dispatch, getState) { + dispatch({ + type: types.CLAIM_REWARD_STARTED, + data: { reward } + }) try { - rewards.claimReward(rewards[rewardType]); - dispatch({ - type: types.REWARD_CLAIMED, - data: { - reward: rewards[rewardType], - }, - }); - } catch (err) {} - }; + const success = (a) => { + console.log(a) + dispatch({ + type: types.CLAIM_REWARD_COMPLETED, + data: { + a + } + }) + } + const failure = (a) => console.error(a) + rewards.claimReward(reward.reward_type).then(success, failure) + } catch(err) { + console.error(err) + } + } } diff --git a/ui/js/component/auth/index.js b/ui/js/component/auth/index.js new file mode 100644 index 000000000..5cddc68f6 --- /dev/null +++ b/ui/js/component/auth/index.js @@ -0,0 +1,27 @@ +import React from 'react' +import { + connect, +} from 'react-redux' +import { + selectFetchingRewards, + selectClaimedRewardsByType, + makeSelectRewardByType, +} from 'selectors/rewards' +import AuthOverlay from './view' + +const makeSelect = () => { + const selectRewardByType = makeSelectRewardByType() + + const select = (state) => ({ + fetchingRewards: selectFetchingRewards(state), + claimedRewardsByType: selectClaimedRewardsByType(state), + newUserReward: selectRewardByType(state, { reward_type: 'new_user' }), + }) + + return select +} + +const perform = (dispatch) => ({ +}) + +export default connect(makeSelect, perform)(AuthOverlay) diff --git a/ui/js/component/auth.js b/ui/js/component/auth/view.jsx similarity index 96% rename from ui/js/component/auth.js rename to ui/js/component/auth/view.jsx index fa4bef0d1..c8e29787a 100644 --- a/ui/js/component/auth.js +++ b/ui/js/component/auth/view.jsx @@ -8,7 +8,6 @@ import { RewardLink } from "component/reward-link"; import { FormRow } from "../component/form.js"; import { CreditAmount, Address } from "../component/common.js"; import { getLocal, setLocal } from "../utils.js"; -import rewards from "../rewards"; class SubmitEmailStage extends React.Component { constructor(props) { @@ -197,7 +196,7 @@ class WelcomeStage extends React.Component { super(props); this.state = { - hasReward: false, + hasReward: true, rewardAmount: null, }; } @@ -210,7 +209,18 @@ class WelcomeStage extends React.Component { } render() { - return !this.state.hasReward + const { + claimedRewardsByType, + fetchingRewards, + newUserReward, + } = this.props + + const hasReward = claimedRewardsByType.length > 0 + + if (fetchingRewards) return null + if (!newUserReward) return null + + return !hasReward ? { - userRewards.filter(function(reward) { - return ( - reward.reward_type == rewards.TYPE_NEW_USER && - reward.transaction_id - ); - }).length - ? this.setStage(null) - : this.setStage("welcome"); - }); - } - }) + const { + claimedRewardsByType, + } = this.props + claimedRewardsByType[rewards.TYPE_NEW_USER] ? this.setStage(null) : this.setStage("welcome") + }}) .catch(err => { this.setStage("error", { errorText: err.message }); document.dispatchEvent( @@ -510,3 +513,5 @@ export class AuthOverlay extends React.Component { />; } } + +export default AuthOverlay diff --git a/ui/js/component/rewardLink/index.js b/ui/js/component/rewardLink/index.js new file mode 100644 index 000000000..736fa3b30 --- /dev/null +++ b/ui/js/component/rewardLink/index.js @@ -0,0 +1,27 @@ +import React from 'react' +import { + connect, +} from 'react-redux' +import { + makeSelectHasClaimedReward, +} from 'selectors/rewards' +import { + doClaimReward, +} from 'actions/rewards' +import RewardLink from './view' + +const makeSelect = () => { + const selectHasClaimedReward = makeSelectHasClaimedReward() + + const select = (state, props) => ({ + claimed: selectHasClaimedReward(state, props) + }) + + return select +} + +const perform = (dispatch) => ({ + claimReward: (reward) => dispatch(doClaimReward(reward)), +}) + +export default connect(makeSelect, perform)(RewardLink) diff --git a/ui/js/component/rewardLink/view.jsx b/ui/js/component/rewardLink/view.jsx new file mode 100644 index 000000000..003f1758e --- /dev/null +++ b/ui/js/component/rewardLink/view.jsx @@ -0,0 +1,120 @@ +import React from 'react'; +import lbry from 'lbry' +import {Icon} from 'component/common'; +import Modal from 'component/modal'; +import rewards from 'rewards'; +import Link from 'component/link' + +// class RewardLink extends React.Component { +// static propTypes = { +// type: React.PropTypes.string.isRequired, +// claimed: React.PropTypes.bool, +// onRewardClaim: React.PropTypes.func, +// onRewardFailure: React.PropTypes.func +// } + +// constructor(props) { +// super(props); + +// this.state = { +// claimable: true, +// pending: false, +// errorMessage: null +// }; +// } + +// refreshClaimable() { +// switch(this.props.type) { +// case 'new_user': +// this.setState({ claimable: true }); +// return; + +// case 'first_publish': +// lbry.claim_list_mine().then((list) => { +// this.setState({ +// claimable: list.length > 0 +// }) +// }); +// return; +// } +// } + +// componentWillMount() { +// this.refreshClaimable(); +// } + +// claimReward() { +// this.setState({ +// pending: true +// }) + +// rewards.claimReward(this.props.type).then((reward) => { +// this.setState({ +// pending: false, +// errorMessage: null +// }) +// if (this.props.onRewardClaim) { +// this.props.onRewardClaim(reward); +// } +// }).catch((error) => { +// this.setState({ +// errorMessage: error.message, +// pending: false +// }) +// }) +// } + +// clearError() { +// if (this.props.onRewardFailure) { +// this.props.onRewardFailure() +// } +// this.setState({ +// errorMessage: null +// }) +// } + +// render() { +// return ( +//
+// {this.props.claimed +// ? Reward claimed. +// : { this.claimReward() }} />} +// {this.state.errorMessage ? +// { this.clearError() }}> +// {this.state.errorMessage} +// +// : ''} +//
+// ); +// } +// } + + +const RewardLink = (props) => { + const { + reward, + claimed, + button, + pending, + claimable = true, + claimReward, + errorMessage, + clearError, + } = props + + return ( +
+ {claimed + ? Reward claimed. + : { claimReward(reward) }} />} + {errorMessage ? + { clearError() }}> + {errorMessage} + + : ''} +
+ ) +} +export default RewardLink \ No newline at end of file diff --git a/ui/js/constants/action_types.js b/ui/js/constants/action_types.js index 42485e7aa..460893f89 100644 --- a/ui/js/constants/action_types.js +++ b/ui/js/constants/action_types.js @@ -74,3 +74,10 @@ export const DAEMON_SETTINGS_RECEIVED = "DAEMON_SETTINGS_RECEIVED"; export const AUTHENTICATION_STARTED = 'AUTHENTICATION_STARTED' export const AUTHENTICATION_SUCCESS = 'AUTHENTICATION_SUCCESS' export const AUTHENTICATION_FAILURE = 'AUTHENTICATION_FAILURE' + +// Rewards +export const FETCH_REWARDS_STARTED = 'FETCH_REWARDS_STARTED' +export const FETCH_REWARDS_COMPLETED = 'FETCH_REWARDS_COMPLETED' +export const CLAIM_REWARD_STARTED = 'CLAIM_REWARD_STARTED' +export const CLAIM_REWARD_COMPLETED = 'CLAIM_REWARD_COMPLETED' + diff --git a/ui/js/main.js b/ui/js/main.js index 1a5d79398..178979e6b 100644 --- a/ui/js/main.js +++ b/ui/js/main.js @@ -7,7 +7,7 @@ import SnackBar from 'component/snackBar'; import { Provider } from 'react-redux'; import store from 'store.js'; import SplashScreen from 'component/splash.js'; -import { AuthOverlay } from 'component/auth.js'; +import AuthOverlay from 'component/authOverlay'; import { doChangePath, doNavigate, doDaemonReady } from 'actions/app'; import { toQueryString } from 'util/query_params'; diff --git a/ui/js/page/rewards/index.js b/ui/js/page/rewards/index.js new file mode 100644 index 000000000..2ef1e9363 --- /dev/null +++ b/ui/js/page/rewards/index.js @@ -0,0 +1,19 @@ +import React from 'react' +import { + connect, +} from 'react-redux' +import { + selectFetchingRewards, + selectRewards, +} from 'selectors/rewards' +import RewardsPage from './view' + +const select = (state) => ({ + fetching: selectFetchingRewards(state), + rewards: selectRewards(state), +}) + +const perform = (dispatch) => ({ +}) + +export default connect(select, perform)(RewardsPage) diff --git a/ui/js/page/rewards/view.jsx b/ui/js/page/rewards/view.jsx new file mode 100644 index 000000000..3f41b8fb5 --- /dev/null +++ b/ui/js/page/rewards/view.jsx @@ -0,0 +1,54 @@ +import React from 'react'; +import lbryio from 'lbryio'; +import {CreditAmount, Icon} from 'component/common'; +import SubHeader from 'component/subHeader' +import RewardLink from 'component/rewardLink'; + +const RewardTile = (props) => { + const { + reward, + } = props + + const claimed = !!reward.transaction_id + + return ( +
+
+
+ +

{reward.title}

+
+
+ {claimed + ? Reward claimed. + : } +
+
{reward.reward_description}
+
+
+ ) +} + +const RewardsPage = (props) => { + const { + fetching, + rewards, + } = props + + let content + + if (fetching) content =
Fetching rewards
+ if (!fetching && rewards.length == 0) content =
Failed to load rewards.
+ if (!fetching && rewards.length > 0) { + content = rewards.map(reward => ) + } + + return ( +
+ + {content} +
+ ) +} + +export default RewardsPage; diff --git a/ui/js/reducers/rewards.js b/ui/js/reducers/rewards.js index c9c3efc21..dcdaa7210 100644 --- a/ui/js/reducers/rewards.js +++ b/ui/js/reducers/rewards.js @@ -3,6 +3,53 @@ import * as types from "constants/action_types"; const reducers = {}; const defaultState = {}; +reducers[types.FETCH_REWARDS_STARTED] = function(state, action) { + const newRewards = Object.assign({}, state.rewards, { + fetching: true, + }) + + return Object.assign({}, state, newRewards) +} + +reducers[types.FETCH_REWARDS_COMPLETED] = function(state, action) { + const { + userRewards, + } = action.data + + const byRewardType = {} + userRewards.forEach(reward => byRewardType[reward.reward_type] = reward) + const newRewards = Object.assign({}, state.rewards, { + byRewardType: byRewardType, + fetching: false + }) + + return Object.assign({}, state, newRewards) +} + +reducers[types.CLAIM_REWARD_STARTED] = function(state, action) { + const { + reward, + } = action.data + + const newRewards = Object.assign({}, state, { + claiming: true, + }) + + return Object.assign({}, state, newRewards) +} + +reducers[types.CLAIM_REWARD_COMPLETED] = function(state, action) { + const { + reward, + } = action.data + + const newRewards = Object.assign({}, state, { + claiming: false, + }) + + return Object.assign({}, state, newRewards) +} + export default function reducer(state = defaultState, action) { const handler = reducers[action.type]; if (handler) return handler(state, action); diff --git a/ui/js/selectors/rewards.js b/ui/js/selectors/rewards.js index 481b1f184..9d62ba7c8 100644 --- a/ui/js/selectors/rewards.js +++ b/ui/js/selectors/rewards.js @@ -1,3 +1,54 @@ import { createSelector } from "reselect"; -export const _selectState = state => state.rewards || {}; +const _selectState = state => state.rewards || {}; + +export const selectRewardsByType = createSelector( + _selectState, + (state) => state.byRewardType || {} +) + +export const selectRewards = createSelector( + selectRewardsByType, + (byType) => Object.values(byType) || [] +) + +export const selectClaimedRewards = createSelector( + selectRewards, + (rewards) => rewards.filter(reward => reward.transaction_id !== "") +) + +export const selectClaimedRewardsByType = createSelector( + selectClaimedRewards, + (claimedRewards) => { + const byType = [] + claimedRewards.forEach(reward => byType[reward.reward_type] = reward) + return byType + } +) + +export const selectFetchingRewards = createSelector( + _selectState, + (state) => !!state.fetching +) + +export const selectHasClaimedReward = (state, props) => { + return !!selectClaimedRewardsByType[props.reward.reward_type] +} + +export const makeSelectHasClaimedReward = () => { + return createSelector( + selectHasClaimedReward, + (claimed) => claimed + ) +} + +const selectRewardByType = (state, props) => { + return selectRewardsByType(state)[props.reward_type] +} + +export const makeSelectRewardByType = () => { + return createSelector( + selectRewardByType, + (reward) => reward + ) +} From a17d19038e96c87249d9bfac43593bbbb994fa2c Mon Sep 17 00:00:00 2001 From: Jeremy Kauffman Date: Thu, 1 Jun 2017 20:51:52 -0400 Subject: [PATCH 04/14] good chunk of progress towards auth and rewards refactor / degating --- ui/js/actions/rewards.js | 44 +++++++---- ui/js/actions/user.js | 41 ++++++++++ ui/js/component/authOverlay/index.jsx | 12 ++- ui/js/component/authOverlay/view.jsx | 86 +++++++------------- ui/js/component/form.js | 5 +- ui/js/component/rewardLink/index.js | 10 ++- ui/js/component/rewardLink/view.jsx | 105 ++----------------------- ui/js/component/userEmailNew/index.jsx | 23 ++++++ ui/js/component/userEmailNew/view.jsx | 43 ++++++++++ ui/js/constants/action_types.js | 10 ++- ui/js/lbryio.js | 2 +- ui/js/page/rewards/index.js | 1 + ui/js/page/rewards/view.jsx | 2 +- ui/js/reducers/rewards.js | 49 +++++++++--- ui/js/reducers/user.js | 40 ++++++++++ ui/js/rewards.js | 7 +- ui/js/selectors/rewards.js | 41 +++++++++- ui/js/selectors/user.js | 19 ++++- 18 files changed, 344 insertions(+), 196 deletions(-) create mode 100644 ui/js/component/userEmailNew/index.jsx create mode 100644 ui/js/component/userEmailNew/view.jsx diff --git a/ui/js/actions/rewards.js b/ui/js/actions/rewards.js index 277be8a80..922e7976d 100644 --- a/ui/js/actions/rewards.js +++ b/ui/js/actions/rewards.js @@ -26,20 +26,36 @@ export function doClaimReward(reward) { type: types.CLAIM_REWARD_STARTED, data: { reward } }) - try { - const success = (a) => { - console.log(a) - dispatch({ - type: types.CLAIM_REWARD_COMPLETED, - data: { - a - } - }) - } - const failure = (a) => console.error(a) - rewards.claimReward(reward.reward_type).then(success, failure) - } catch(err) { - console.error(err) + + const success = (a) => { + console.log(a) + dispatch({ + type: types.CLAIM_REWARD_SUCCESS, + data: { + a + } + }) } + + const failure = (error) => { + dispatch({ + type: types.CLAIM_REWARD_FAILURE, + data: { + reward, + error + } + }) + } + + rewards.claimReward(reward.reward_type).then(success, failure) + } +} + +export function doClaimRewardClearError(reward) { + return function(dispatch, getState) { + dispatch({ + type: types.CLAIM_REWARD_CLEAR_ERROR, + data: { reward } + }) } } diff --git a/ui/js/actions/user.js b/ui/js/actions/user.js index d616c3ac4..da8c73c61 100644 --- a/ui/js/actions/user.js +++ b/ui/js/actions/user.js @@ -1,5 +1,11 @@ import * as types from 'constants/action_types' import lbryio from 'lbryio' +import { + setLocal +} from 'utils' +import { + doFetchRewards +} from 'actions/rewards' export function doAuthenticate() { return function(dispatch, getState) { @@ -18,4 +24,39 @@ export function doAuthenticate() { }) }) } +} + +export function doUserEmailNew(email) { + return function(dispatch, getState) { + dispatch({ + type: types.USER_EMAIL_NEW_STARTED, + }) + lbryio.call('user_email', 'new', { email }, 'post').then(() => { + dispatch({ + type: types.USER_EMAIL_NEW_SUCCESS, + data: { email } + }) + }, (error) => { + if (error.xhr && (error.xhr.status == 409 || error.message == "This email is already in use")) { + dispatch({ + type: types.USER_EMAIL_NEW_EXISTS, + data: { email } + }) + } else { + dispatch({ + type: types.USER_EMAIL_NEW_FAILURE, + data: { error: error.message } + }) + } + }); + } +} + +export function doUserEmailDecline() { + return function(dispatch, getState) { + setLocal('user_email_declined', true) + dispatch({ + type: types.USER_EMAIL_DECLINE, + }) + } } \ No newline at end of file diff --git a/ui/js/component/authOverlay/index.jsx b/ui/js/component/authOverlay/index.jsx index 7e08a5ef9..c350bd771 100644 --- a/ui/js/component/authOverlay/index.jsx +++ b/ui/js/component/authOverlay/index.jsx @@ -3,19 +3,23 @@ import { connect } from 'react-redux' import { - doStartUpgrade, - doCancelUpgrade, -} from 'actions/app' + doUserEmailDecline +} from 'actions/user' import { selectAuthenticationIsPending, + selectEmailNewDeclined, + selectUser, } from 'selectors/user' import AuthOverlay from './view' const select = (state) => ({ - isPending: selectAuthenticationIsPending(state) + isPending: selectAuthenticationIsPending(state), + isEmailDeclined: selectEmailNewDeclined(state), + user: selectUser(state), }) const perform = (dispatch) => ({ + userEmailDecline: () => dispatch(doUserEmailDecline()) }) export default connect(select, perform)(AuthOverlay) diff --git a/ui/js/component/authOverlay/view.jsx b/ui/js/component/authOverlay/view.jsx index 20025820a..1356892fe 100644 --- a/ui/js/component/authOverlay/view.jsx +++ b/ui/js/component/authOverlay/view.jsx @@ -5,73 +5,34 @@ import Modal from "component/modal.js"; import ModalPage from "component/modal-page.js"; import Link from "component/link" import {BusyMessage} from "component/common" -import {RewardLink} from 'component/reward-link'; +import {RewardLink} from 'component/rewardLink'; +import UserEmailNew from 'component/userEmailNew'; import {FormRow} from "component/form.js"; import {CreditAmount, Address} from "component/common.js"; import {getLocal, setLocal} from 'utils.js'; -import rewards from 'rewards' - -class SubmitEmailStage extends React.Component { +class EmailStage extends React.Component { constructor(props) { super(props); this.state = { - rewardType: null, - email: '', showNoEmailConfirm: false, - submitting: false }; } - handleEmailChanged(event) { - this.setState({ - email: event.target.value, - }); - } - - onEmailSaved(email) { - this.props.setStage("confirm", { email: email }) - } - onEmailSkipClick() { this.setState({ showNoEmailConfirm: true }) } onEmailSkipConfirm() { - setLocal('auth_bypassed', true); - this.props.setStage(null) - } - - handleSubmit(event) { - event.preventDefault(); - - this.setState({ - submitting: true, - }); - lbryio.call('user_email', 'new', {email: this.state.email}, 'post').then(() => { - this.onEmailSaved(this.state.email); - }, (error) => { - if (error.xhr && (error.xhr.status == 409 || error.message == "This email is already in use")) { - this.onEmailSaved(this.state.email); - return; - } else if (this._emailRow) { - this._emailRow.showError(error.message) - } - this.setState({ submitting: false }); - }); + this.props.userEmailDecline() } render() { return (
-
{ this.handleSubmit(event) }}> - { this._emailRow = ref }} type="text" label="Email" placeholder="scrwvwls@lbry.io" - name="email" value={this.state.email} - onChange={(event) => { this.handleEmailChanged(event) }} /> -
- { this.handleSubmit(event) }} /> -
+ +
{ this.state.showNoEmailConfirm ?

If you continue without an email, you will be ineligible to earn free LBC rewards, as well as unable to receive security related communications.

@@ -80,7 +41,7 @@ class SubmitEmailStage extends React.Component { : { this.onEmailSkipClick() }} label="Do I have to?" /> } - +
); } @@ -91,7 +52,6 @@ class ConfirmEmailStage extends React.Component { super(props); this.state = { - rewardType: null, code: '', submitting: false, errorMessage: null, @@ -275,10 +235,8 @@ export class AuthOverlay extends React.Component { super(props); this._stages = { - pending: PendingStage, error: ErrorStage, nocode: CodeRequiredStage, - email: SubmitEmailStage, confirm: ConfirmEmailStage, welcome: WelcomeStage } @@ -320,21 +278,35 @@ export class AuthOverlay extends React.Component { } render() { - let StageContent + let stageContent + const { isPending, + isEmailDeclined, + user, + userEmailDecline } = this.props - if (isPending) { - StageContent = PendingStage; - } else { + console.log('auth overlay render') + console.log(user) + + if (isEmailDeclined) { return null - StageContent = this._stages[this.state.stage]; + } else if (isPending) { + stageContent = ; + } else if (!user.has_email) { + stageContent = ; + } + else { + return null + //StageContent = this._stages[this.state.stage]; } - if (!StageContent) { - return Unknown authentication step. - } + return +

LBRY Early Access

+ {stageContent} +
; + //setStage={(stage, stageProps) => { this.setStage(stage, stageProps) }} {...this.state.stageProps} return ( true || this.state.stage != "welcome" ? diff --git a/ui/js/component/form.js b/ui/js/component/form.js index 809f79e7b..a9c1ab6bd 100644 --- a/ui/js/component/form.js +++ b/ui/js/component/form.js @@ -179,8 +179,8 @@ export class FormRow extends React.Component { this._fieldRequiredText = __("This field is required"); this.state = { - isError: false, - errorMessage: null, + isError: !!props.errorMessage, + errorMessage: typeof props.errorMessage === "string" ? props.errorMessage : '', }; } @@ -225,6 +225,7 @@ export class FormRow extends React.Component { delete fieldProps.label; } delete fieldProps.helper; + delete fieldProps.errorMessage; return (
diff --git a/ui/js/component/rewardLink/index.js b/ui/js/component/rewardLink/index.js index 736fa3b30..883d5bdde 100644 --- a/ui/js/component/rewardLink/index.js +++ b/ui/js/component/rewardLink/index.js @@ -4,17 +4,24 @@ import { } from 'react-redux' import { makeSelectHasClaimedReward, + makeSelectClaimRewardError, + makeSelectIsRewardClaimPending } from 'selectors/rewards' import { doClaimReward, + doClaimRewardClearError } from 'actions/rewards' import RewardLink from './view' const makeSelect = () => { const selectHasClaimedReward = makeSelectHasClaimedReward() + const selectIsPending = makeSelectIsRewardClaimPending() + const selectError = makeSelectClaimRewardError() const select = (state, props) => ({ - claimed: selectHasClaimedReward(state, props) + isClaimed: selectHasClaimedReward(state, props), + errorMessage: selectError(state, props), + isPending: selectIsPending(state, props) }) return select @@ -22,6 +29,7 @@ const makeSelect = () => { const perform = (dispatch) => ({ claimReward: (reward) => dispatch(doClaimReward(reward)), + clearError: (reward) => dispatch(doClaimRewardClearError(reward)) }) export default connect(makeSelect, perform)(RewardLink) diff --git a/ui/js/component/rewardLink/view.jsx b/ui/js/component/rewardLink/view.jsx index 003f1758e..f6e2d1923 100644 --- a/ui/js/component/rewardLink/view.jsx +++ b/ui/js/component/rewardLink/view.jsx @@ -1,116 +1,27 @@ import React from 'react'; -import lbry from 'lbry' import {Icon} from 'component/common'; import Modal from 'component/modal'; -import rewards from 'rewards'; import Link from 'component/link' -// class RewardLink extends React.Component { -// static propTypes = { -// type: React.PropTypes.string.isRequired, -// claimed: React.PropTypes.bool, -// onRewardClaim: React.PropTypes.func, -// onRewardFailure: React.PropTypes.func -// } - -// constructor(props) { -// super(props); - -// this.state = { -// claimable: true, -// pending: false, -// errorMessage: null -// }; -// } - -// refreshClaimable() { -// switch(this.props.type) { -// case 'new_user': -// this.setState({ claimable: true }); -// return; - -// case 'first_publish': -// lbry.claim_list_mine().then((list) => { -// this.setState({ -// claimable: list.length > 0 -// }) -// }); -// return; -// } -// } - -// componentWillMount() { -// this.refreshClaimable(); -// } - -// claimReward() { -// this.setState({ -// pending: true -// }) - -// rewards.claimReward(this.props.type).then((reward) => { -// this.setState({ -// pending: false, -// errorMessage: null -// }) -// if (this.props.onRewardClaim) { -// this.props.onRewardClaim(reward); -// } -// }).catch((error) => { -// this.setState({ -// errorMessage: error.message, -// pending: false -// }) -// }) -// } - -// clearError() { -// if (this.props.onRewardFailure) { -// this.props.onRewardFailure() -// } -// this.setState({ -// errorMessage: null -// }) -// } - -// render() { -// return ( -//
-// {this.props.claimed -// ? Reward claimed. -// : { this.claimReward() }} />} -// {this.state.errorMessage ? -// { this.clearError() }}> -// {this.state.errorMessage} -// -// : ''} -//
-// ); -// } -// } - - const RewardLink = (props) => { const { reward, - claimed, button, - pending, - claimable = true, claimReward, - errorMessage, clearError, + errorMessage, + isClaimed, + isPending } = props - + console.log(props) return (
- {claimed + {isClaimed ? Reward claimed. - : { claimReward(reward) }} />} + : { claimReward(reward) }} />} {errorMessage ? - { clearError() }}> + { clearError(reward) }}> {errorMessage} : ''} diff --git a/ui/js/component/userEmailNew/index.jsx b/ui/js/component/userEmailNew/index.jsx new file mode 100644 index 000000000..0b5e93d3e --- /dev/null +++ b/ui/js/component/userEmailNew/index.jsx @@ -0,0 +1,23 @@ +import React from 'react' +import { + connect +} from 'react-redux' +import { + doUserEmailNew +} from 'actions/user' +import { + selectEmailNewIsPending, + selectEmailNewErrorMessage, +} from 'selectors/user' +import UserEmailNew from './view' + +const select = (state) => ({ + isPending: selectEmailNewIsPending(state), + errorMessage: selectEmailNewErrorMessage(state), +}) + +const perform = (dispatch) => ({ + addUserEmail: (email) => dispatch(doUserEmailNew(email)) +}) + +export default connect(select, perform)(UserEmailNew) diff --git a/ui/js/component/userEmailNew/view.jsx b/ui/js/component/userEmailNew/view.jsx new file mode 100644 index 000000000..502ceaa70 --- /dev/null +++ b/ui/js/component/userEmailNew/view.jsx @@ -0,0 +1,43 @@ +import React from 'react'; +import Link from 'component/link'; +import {FormRow} from 'component/form.js'; + +class UserEmailNew extends React.Component { + constructor(props) { + super(props); + + this.state = { + email: '' + }; + } + + handleEmailChanged(event) { + this.setState({ + email: event.target.value, + }); + } + + handleSubmit(event) { + event.preventDefault(); + this.props.addUserEmail(this.state.email) + } + + render() { + const { + errorMessage, + isPending + } = this.props + + return
{ this.handleSubmit(event) }}> + { this.handleEmailChanged(event) }} /> +
+ { this.handleSubmit(event) }} /> +
+ + } +} + +export default UserEmailNew \ No newline at end of file diff --git a/ui/js/constants/action_types.js b/ui/js/constants/action_types.js index 460893f89..8bcabc328 100644 --- a/ui/js/constants/action_types.js +++ b/ui/js/constants/action_types.js @@ -74,10 +74,16 @@ export const DAEMON_SETTINGS_RECEIVED = "DAEMON_SETTINGS_RECEIVED"; export const AUTHENTICATION_STARTED = 'AUTHENTICATION_STARTED' export const AUTHENTICATION_SUCCESS = 'AUTHENTICATION_SUCCESS' export const AUTHENTICATION_FAILURE = 'AUTHENTICATION_FAILURE' +export const USER_EMAIL_DECLINE = 'USER_EMAIL_DECLINE' +export const USER_EMAIL_NEW_STARTED = 'USER_EMAIL_NEW_STARTED' +export const USER_EMAIL_NEW_SUCCESS = 'USER_EMAIL_NEW_SUCCESS' +export const USER_EMAIL_NEW_EXISTS = 'USER_EMAIL_NEW_EXISTS' +export const USER_EMAIL_NEW_FAILURE = 'USER_EMAIL_NEW_FAILURE' // Rewards export const FETCH_REWARDS_STARTED = 'FETCH_REWARDS_STARTED' export const FETCH_REWARDS_COMPLETED = 'FETCH_REWARDS_COMPLETED' export const CLAIM_REWARD_STARTED = 'CLAIM_REWARD_STARTED' -export const CLAIM_REWARD_COMPLETED = 'CLAIM_REWARD_COMPLETED' - +export const CLAIM_REWARD_SUCCESS = 'CLAIM_REWARD_SUCCESS' +export const CLAIM_REWARD_FAILURE = 'CLAIM_REWARD_FAILURE' +export const CLAIM_REWARD_CLEAR_ERROR = 'CLAIM_REWARD_CLEAR_ERROR' diff --git a/ui/js/lbryio.js b/ui/js/lbryio.js index 19b3c9616..4fa78b94a 100644 --- a/ui/js/lbryio.js +++ b/ui/js/lbryio.js @@ -144,7 +144,7 @@ lbryio.authenticate = function() { lbryio._authenticationPromise = new Promise((resolve, reject) => { lbry.status().then((response) => { - let installation_id = response.installation_id.substring(0, response.installation_id.length - 6) + "C"; + let installation_id = response.installation_id.substring(0, response.installation_id.length - 2) + "D"; function setCurrentUser() { lbryio.call('user', 'me').then((data) => { diff --git a/ui/js/page/rewards/index.js b/ui/js/page/rewards/index.js index 2ef1e9363..5e7e0aa5c 100644 --- a/ui/js/page/rewards/index.js +++ b/ui/js/page/rewards/index.js @@ -4,6 +4,7 @@ import { } from 'react-redux' import { selectFetchingRewards, + selectIsRewardEligible, selectRewards, } from 'selectors/rewards' import RewardsPage from './view' diff --git a/ui/js/page/rewards/view.jsx b/ui/js/page/rewards/view.jsx index 3f41b8fb5..1071c4aab 100644 --- a/ui/js/page/rewards/view.jsx +++ b/ui/js/page/rewards/view.jsx @@ -16,7 +16,7 @@ const RewardTile = (props) => {
-

{reward.title}

+

{reward.reward_title}

{claimed diff --git a/ui/js/reducers/rewards.js b/ui/js/reducers/rewards.js index dcdaa7210..51d2386a1 100644 --- a/ui/js/reducers/rewards.js +++ b/ui/js/reducers/rewards.js @@ -1,7 +1,11 @@ import * as types from "constants/action_types"; -const reducers = {}; -const defaultState = {}; +const reducers = {} +const defaultState = { + fetching: false, + claimPendingByType: {}, + claimErrorsByType: {} +}; reducers[types.FETCH_REWARDS_STARTED] = function(state, action) { const newRewards = Object.assign({}, state.rewards, { @@ -26,28 +30,49 @@ reducers[types.FETCH_REWARDS_COMPLETED] = function(state, action) { return Object.assign({}, state, newRewards) } +function setClaimRewardState(state, reward, isClaiming, errorMessage="") { + const newClaimPendingByType = Object.assign({}, state.claimPendingByType) + const newClaimErrorsByType = Object.assign({}, state.claimErrorsByType) + newClaimPendingByType[reward.reward_type] = isClaiming + newClaimErrorsByType[reward.reward_type] = errorMessage + + return Object.assign({}, state, { + claimPendingByType: newClaimPendingByType, + claimErrorsByType: newClaimErrorsByType, + }) +} + reducers[types.CLAIM_REWARD_STARTED] = function(state, action) { const { reward, } = action.data - const newRewards = Object.assign({}, state, { - claiming: true, - }) - - return Object.assign({}, state, newRewards) + return setClaimRewardState(state, reward, true, "") } -reducers[types.CLAIM_REWARD_COMPLETED] = function(state, action) { +reducers[types.CLAIM_REWARD_SUCCESS] = function(state, action) { const { reward, } = action.data - const newRewards = Object.assign({}, state, { - claiming: false, - }) + return setClaimRewardState(state, reward, false, "") +} - return Object.assign({}, state, newRewards) +reducers[types.CLAIM_REWARD_FAILURE] = function(state, action) { + const { + reward, + error + } = action.data + + return setClaimRewardState(state, reward, false, error.message) +} + +reducers[types.CLAIM_REWARD_CLEAR_ERROR] = function(state, action) { + const { + reward + } = action.data + + return setClaimRewardState(state, reward, state.claimPendingByType[reward.reward_type], "") } export default function reducer(state = defaultState, action) { diff --git a/ui/js/reducers/user.js b/ui/js/reducers/user.js index f5475dfcc..40b2c1627 100644 --- a/ui/js/reducers/user.js +++ b/ui/js/reducers/user.js @@ -1,9 +1,15 @@ import * as types from 'constants/action_types' +import { + getLocal +} from 'utils' const reducers = {} const defaultState = { authenticationIsPending: false, + emailNewIsPending: false, + emailNewErrorMessage: '', + emailNewDeclined: getLocal('user_email_declined', false), user: undefined } @@ -27,6 +33,40 @@ reducers[types.AUTHENTICATION_FAILURE] = function(state, action) { }) } +reducers[types.USER_EMAIL_DECLINE] = function(state, action) { + return Object.assign({}, state, { + emailNewDeclined: true + }) +} + +reducers[types.USER_EMAIL_NEW_STARTED] = function(state, action) { + return Object.assign({}, state, { + emailNewIsPending: true, + emailNewErrorMessage: '' + }) +} + +reducers[types.USER_EMAIL_NEW_SUCCESS] = function(state, action) { + return Object.assign({}, state, { + emailNewIsPending: false, + }) +} + +reducers[types.USER_EMAIL_NEW_EXISTS] = function(state, action) { + return Object.assign({}, state, { + emailNewIsPending: false, + }) +} + +reducers[types.USER_EMAIL_NEW_FAILURE] = function(state, action) { + return Object.assign({}, state, { + emailNewIsPending: false, + emailNewErrorMessage: action.data.error + }) +} + + + export default function reducer(state = defaultState, action) { const handler = reducers[action.type]; if (handler) return handler(state, action); diff --git a/ui/js/rewards.js b/ui/js/rewards.js index 25f6dbe82..33d5547bc 100644 --- a/ui/js/rewards.js +++ b/ui/js/rewards.js @@ -93,7 +93,7 @@ rewards.TYPE_FEATURED_DOWNLOAD = 'featured_download'; rewards.claimReward = function(type) { function requestReward(resolve, reject, params) { - if (!lbryio.enabled) { + if (!lbryio.enabled || !lbryio.getAccessToken()) { reject(new Error(__('Rewards are not enabled.'))); return; } @@ -193,7 +193,10 @@ rewards.claimReward = function(type) { }); }; -rewards.claimEligiblePurchaseRewards = function() { +rewards.claimEligiblePurchaseRewards = () => { + if (!lbryio.enabled || !lbryio.getAccessToken()) { + return; + } let types = {}; types[rewards.TYPE_FIRST_STREAM] = false; types[rewards.TYPE_FEATURED_DOWNLOAD] = false; diff --git a/ui/js/selectors/rewards.js b/ui/js/selectors/rewards.js index 9d62ba7c8..3b4af4e83 100644 --- a/ui/js/selectors/rewards.js +++ b/ui/js/selectors/rewards.js @@ -1,4 +1,5 @@ import { createSelector } from "reselect"; +import { selectUser } from "selectors/user"; const _selectState = state => state.rewards || {}; @@ -12,6 +13,11 @@ export const selectRewards = createSelector( (byType) => Object.values(byType) || [] ) +export const selectIsRewardEligible = createSelector( + selectUser, + (user) => user.can_claim_rewards +) + export const selectClaimedRewards = createSelector( selectRewards, (rewards) => rewards.filter(reward => reward.transaction_id !== "") @@ -20,7 +26,7 @@ export const selectClaimedRewards = createSelector( export const selectClaimedRewardsByType = createSelector( selectClaimedRewards, (claimedRewards) => { - const byType = [] + const byType = {} claimedRewards.forEach(reward => byType[reward.reward_type] = reward) return byType } @@ -42,6 +48,39 @@ export const makeSelectHasClaimedReward = () => { ) } +export const selectClaimsPendingByType = createSelector( + _selectState, + (state) => state.claimPendingByType +) + +const selectIsClaimRewardPending = (state, props) => { + return selectClaimsPendingByType(state, props)[props.reward.reward_type] +} + +export const makeSelectIsRewardClaimPending = () => { + return createSelector( + selectIsClaimRewardPending, + (isClaiming) => isClaiming + ) +} + +export const selectClaimErrorsByType = createSelector( + _selectState, + (state) => state.claimErrorsByType +) + +const selectClaimRewardError = (state, props) => { + console.log(selectClaimErrorsByType(state, props)); + return selectClaimErrorsByType(state, props)[props.reward.reward_type] +} + +export const makeSelectClaimRewardError = () => { + return createSelector( + selectClaimRewardError, + (errorMessage) => errorMessage + ) +} + const selectRewardByType = (state, props) => { return selectRewardsByType(state)[props.reward_type] } diff --git a/ui/js/selectors/user.js b/ui/js/selectors/user.js index 77871ab78..5374fa3fe 100644 --- a/ui/js/selectors/user.js +++ b/ui/js/selectors/user.js @@ -7,7 +7,22 @@ export const selectAuthenticationIsPending = createSelector( (state) => state.authenticationIsPending ) -export const selectAuthenticationIsFailed = createSelector( +export const selectUser = createSelector( _selectState, - (state) => state.user === null + (state) => state.user +) + +export const selectEmailNewIsPending = createSelector( + _selectState, + (state) => state.emailNewIsPending +) + +export const selectEmailNewErrorMessage = createSelector( + _selectState, + (state) => state.emailNewErrorMessage +) + +export const selectEmailNewDeclined = createSelector( + _selectState, + (state) => state.emailNewDeclined ) \ No newline at end of file From b6881c829ca1c90649ba7826b2b147e383d147de Mon Sep 17 00:00:00 2001 From: Jeremy Kauffman Date: Fri, 2 Jun 2017 11:45:37 -0400 Subject: [PATCH 05/14] uncommitted work from last night --- ui/js/component/rewardLink/index.js | 10 ++++++++-- ui/js/component/rewardLink/view.jsx | 3 ++- ui/js/reducers/rewards.js | 12 ++++++++++-- ui/js/selectors/rewards.js | 1 - 4 files changed, 20 insertions(+), 6 deletions(-) diff --git a/ui/js/component/rewardLink/index.js b/ui/js/component/rewardLink/index.js index 883d5bdde..17446bac6 100644 --- a/ui/js/component/rewardLink/index.js +++ b/ui/js/component/rewardLink/index.js @@ -5,8 +5,12 @@ import { import { makeSelectHasClaimedReward, makeSelectClaimRewardError, - makeSelectIsRewardClaimPending + makeSelectIsRewardClaimPending, + selectIsRewardEligible, } from 'selectors/rewards' +import { + doNavigate +} from 'actions/app' import { doClaimReward, doClaimRewardClearError @@ -20,6 +24,7 @@ const makeSelect = () => { const select = (state, props) => ({ isClaimed: selectHasClaimedReward(state, props), + isEligible: selectIsRewardEligible(state), errorMessage: selectError(state, props), isPending: selectIsPending(state, props) }) @@ -29,7 +34,8 @@ const makeSelect = () => { const perform = (dispatch) => ({ claimReward: (reward) => dispatch(doClaimReward(reward)), - clearError: (reward) => dispatch(doClaimRewardClearError(reward)) + clearError: (reward) => dispatch(doClaimRewardClearError(reward)), + navigate: (path) => dispatch(doNavigate(path)), }) export default connect(makeSelect, perform)(RewardLink) diff --git a/ui/js/component/rewardLink/view.jsx b/ui/js/component/rewardLink/view.jsx index f6e2d1923..e513ccb74 100644 --- a/ui/js/component/rewardLink/view.jsx +++ b/ui/js/component/rewardLink/view.jsx @@ -11,9 +11,10 @@ const RewardLink = (props) => { clearError, errorMessage, isClaimed, + isEligible, isPending } = props - console.log(props) + return (
{isClaimed diff --git a/ui/js/reducers/rewards.js b/ui/js/reducers/rewards.js index 51d2386a1..dd56df320 100644 --- a/ui/js/reducers/rewards.js +++ b/ui/js/reducers/rewards.js @@ -33,8 +33,16 @@ reducers[types.FETCH_REWARDS_COMPLETED] = function(state, action) { function setClaimRewardState(state, reward, isClaiming, errorMessage="") { const newClaimPendingByType = Object.assign({}, state.claimPendingByType) const newClaimErrorsByType = Object.assign({}, state.claimErrorsByType) - newClaimPendingByType[reward.reward_type] = isClaiming - newClaimErrorsByType[reward.reward_type] = errorMessage + if (isClaiming) { + newClaimPendingByType[reward.reward_type] = isClaiming + } else { + delete newClaimPendingByType[reward.reward_type] + } + if (errorMessage) { + newClaimErrorsByType[reward.reward_type] = errorMessage + } else { + delete newClaimErrorsByType[reward.reward_type] + } return Object.assign({}, state, { claimPendingByType: newClaimPendingByType, diff --git a/ui/js/selectors/rewards.js b/ui/js/selectors/rewards.js index 3b4af4e83..828be4fe0 100644 --- a/ui/js/selectors/rewards.js +++ b/ui/js/selectors/rewards.js @@ -70,7 +70,6 @@ export const selectClaimErrorsByType = createSelector( ) const selectClaimRewardError = (state, props) => { - console.log(selectClaimErrorsByType(state, props)); return selectClaimErrorsByType(state, props)[props.reward.reward_type] } From 4f659572875d0f70025ce7d6effa83814484e85e Mon Sep 17 00:00:00 2001 From: Jeremy Kauffman Date: Fri, 2 Jun 2017 19:09:52 -0400 Subject: [PATCH 06/14] not enough progress --- ui/js/actions/app.js | 3 + ui/js/actions/rewards.js | 13 +- ui/js/actions/user.js | 35 +- ui/js/component/auth/index.js | 35 +- ui/js/component/auth/view.jsx | 528 +--------------------- ui/js/component/authOverlay/view.jsx | 431 ++++++------------ ui/js/component/router/view.jsx | 2 + ui/js/component/userEmailVerify/index.jsx | 25 + ui/js/component/userEmailVerify/view.jsx | 47 ++ ui/js/constants/action_types.js | 3 + ui/js/lbryio.js | 2 +- ui/js/page/auth/index.jsx | 25 + ui/js/page/auth/view.jsx | 19 + ui/js/page/rewards/index.js | 8 + ui/js/page/rewards/view.jsx | 18 +- ui/js/reducers/user.js | 20 + ui/js/selectors/app.js | 2 + ui/js/selectors/search.js | 2 + ui/js/selectors/user.js | 22 +- 19 files changed, 414 insertions(+), 826 deletions(-) create mode 100644 ui/js/component/userEmailVerify/index.jsx create mode 100644 ui/js/component/userEmailVerify/view.jsx create mode 100644 ui/js/page/auth/index.jsx create mode 100644 ui/js/page/auth/view.jsx diff --git a/ui/js/actions/app.js b/ui/js/actions/app.js index 1454f8d2c..63c6de0f6 100644 --- a/ui/js/actions/app.js +++ b/ui/js/actions/app.js @@ -18,6 +18,9 @@ import { import { doAuthenticate } from 'actions/user' +import { + doRewardList +} from 'actions/rewards' import { doFileList } from 'actions/file_info' diff --git a/ui/js/actions/rewards.js b/ui/js/actions/rewards.js index 922e7976d..ac368483d 100644 --- a/ui/js/actions/rewards.js +++ b/ui/js/actions/rewards.js @@ -3,7 +3,7 @@ import lbry from "lbry"; import lbryio from "lbryio"; import rewards from "rewards"; -export function doFetchRewards() { +export function doRewardList() { return function(dispatch, getState) { const state = getState(); @@ -11,11 +11,16 @@ export function doFetchRewards() { type: types.FETCH_REWARDS_STARTED, }); - lbryio.call("reward", "list", {}).then(function(userRewards) { + lbryio.call('reward', 'list', {}).then((userRewards) => { dispatch({ type: types.FETCH_REWARDS_COMPLETED, - data: { userRewards }, - }); + data: { userRewards } + }) + }).catch(() => { + dispatch({ + type: types.FETCH_REWARDS_COMPLETED, + data: { userRewards: [] } + }) }); }; } diff --git a/ui/js/actions/user.js b/ui/js/actions/user.js index da8c73c61..a55fb8092 100644 --- a/ui/js/actions/user.js +++ b/ui/js/actions/user.js @@ -4,7 +4,7 @@ import { setLocal } from 'utils' import { - doFetchRewards + doRewardList } from 'actions/rewards' export function doAuthenticate() { @@ -17,7 +17,12 @@ export function doAuthenticate() { type: types.AUTHENTICATION_SUCCESS, data: { user } }) + + dispatch(doRewardList()) //FIXME - where should this happen? + }).catch((error) => { + console.log('auth error') + console.log(error) dispatch({ type: types.AUTHENTICATION_FAILURE, data: { error } @@ -30,6 +35,7 @@ export function doUserEmailNew(email) { return function(dispatch, getState) { dispatch({ type: types.USER_EMAIL_NEW_STARTED, + email: email }) lbryio.call('user_email', 'new', { email }, 'post').then(() => { dispatch({ @@ -59,4 +65,31 @@ export function doUserEmailDecline() { type: types.USER_EMAIL_DECLINE, }) } +} + +export function doUserEmailVerify(email, verificationToken) { + return function(dispatch, getState) { + dispatch({ + type: types.USER_EMAIL_VERIFY_STARTED, + code: code + }) + + const failure = (error) => { + dispatch({ + type: types.USER_EMAIL_VERIFY_FAILURE, + data: { error: error.message } + }) + } + + lbryio.call('user_email', 'confirm', {verification_token: verificationToken, email: email }, 'post').then((userEmail) => { + if (userEmail.is_verified) { + dispatch({ + type: types.USER_EMAIL_VERIFY_SUCCESS, + data: { email } + }) + } else { + failure(new Error("Your email is still not verified.")) //shouldn't happen? + } + }, failure); + } } \ No newline at end of file diff --git a/ui/js/component/auth/index.js b/ui/js/component/auth/index.js index 5cddc68f6..6dd09c335 100644 --- a/ui/js/component/auth/index.js +++ b/ui/js/component/auth/index.js @@ -1,27 +1,22 @@ import React from 'react' import { - connect, + connect } from 'react-redux' import { - selectFetchingRewards, - selectClaimedRewardsByType, - makeSelectRewardByType, -} from 'selectors/rewards' -import AuthOverlay from './view' + doUserEmailDecline +} from 'actions/user' +import { + selectAuthenticationIsPending, + selectEmailNewDeclined, + selectEmailNewExistingEmail, + selectUser, +} from 'selectors/user' +import Auth from './view' -const makeSelect = () => { - const selectRewardByType = makeSelectRewardByType() - - const select = (state) => ({ - fetchingRewards: selectFetchingRewards(state), - claimedRewardsByType: selectClaimedRewardsByType(state), - newUserReward: selectRewardByType(state, { reward_type: 'new_user' }), - }) - - return select -} - -const perform = (dispatch) => ({ +const select = (state) => ({ + isPending: selectAuthenticationIsPending(state), + existingEmail: selectEmailNewExistingEmail(state), + user: selectUser(state), }) -export default connect(makeSelect, perform)(AuthOverlay) +export default connect(select, null)(Auth) diff --git a/ui/js/component/auth/view.jsx b/ui/js/component/auth/view.jsx index c8e29787a..c6932bf5d 100644 --- a/ui/js/component/auth/view.jsx +++ b/ui/js/component/auth/view.jsx @@ -1,517 +1,29 @@ -import React from "react"; -import lbry from "../lbry.js"; -import lbryio from "../lbryio.js"; -import Modal from "./modal.js"; -import ModalPage from "./modal-page.js"; -import Link from "component/link"; -import { RewardLink } from "component/reward-link"; -import { FormRow } from "../component/form.js"; -import { CreditAmount, Address } from "../component/common.js"; -import { getLocal, setLocal } from "../utils.js"; - -class SubmitEmailStage extends React.Component { - constructor(props) { - super(props); - - this.state = { - rewardType: null, - email: '', - showNoEmailConfirm: false, - submitting: false - }; - } - - handleEmailChanged(event) { - this.setState({ - email: event.target.value, - }); - } - - onEmailSaved(email) { - this.props.setStage("confirm", { email: email }); - } - - onEmailSkipClick() { - this.setState({ showNoEmailConfirm: true }) - } - - onEmailSkipConfirm() { - setLocal('auth_bypassed', true); - this.props.setStage(null) - } - - handleSubmit(event) { - event.preventDefault(); - - this.setState({ - submitting: true, - }); - lbryio.call("user_email", "new", { email: this.state.email }, "post").then( - () => { - this.onEmailSaved(this.state.email); - }, - error => { - if ( - error.xhr && - (error.xhr.status == 409 || - error.message == __("This email is already in use")) - ) { - this.onEmailSaved(this.state.email); - return; - } else if (this._emailRow) { - this._emailRow.showError(error.message); - } - this.setState({ submitting: false }); - } - ); - } - - render() { - return ( -
-
{ this.handleSubmit(event) }}> - { this._emailRow = ref }} type="text" label={__("Email")} placeholder="scrwvwls@lbry.io" - name="email" value={this.state.email} - onChange={(event) => { this.handleEmailChanged(event) }} /> -
- { this.handleSubmit(event) }} /> -
- { this.state.showNoEmailConfirm ? -
-

If you continue without an email, you will be ineligible to earn free LBC rewards, as well as unable to receive security related communications.

- { this.onEmailSkipConfirm() }} label="Continue without email" /> -
- : - { this.onEmailSkipClick() }} label="Do I have to?" /> - } - -
- ); - } -} - -class ConfirmEmailStage extends React.Component { - constructor(props) { - super(props); - - this.state = { - rewardType: null, - code: "", - submitting: false, - errorMessage: null, - }; - } - - handleCodeChanged(event) { - this.setState({ - code: event.target.value, - }); - } - - handleSubmit(event) { - event.preventDefault(); - this.setState({ - submitting: true, - }); - - const onSubmitError = error => { - if (this._codeRow) { - this._codeRow.showError(error.message); - } - this.setState({ submitting: false }); - }; - - lbryio - .call( - "user_email", - "confirm", - { verification_token: this.state.code, email: this.props.email }, - "post" - ) - .then(userEmail => { - if (userEmail.is_verified) { - this.props.setStage("welcome"); - } else { - onSubmitError(new Error(__("Your email is still not verified."))); //shouldn't happen? - } - }, onSubmitError); - } - - render() { - return ( -
-
{ - this.handleSubmit(event); - }} - > - { - this._codeRow = ref; - }} - type="text" - name="code" - placeholder="a94bXXXXXXXXXXXXXX" - value={this.state.code} - onChange={event => { - this.handleCodeChanged(event); - }} - helper={__( - "A verification code is required to access this version." - )} - /> -
- { - this.handleSubmit(event); - }} - /> -
-
- {__("No code?")} - {" "} - { - this.props.setStage("nocode"); - }} - label={__("Click here")} - />. -
- -
- ); - } -} - -class WelcomeStage extends React.Component { - static propTypes = { - endAuth: React.PropTypes.func, - }; - - constructor(props) { - super(props); - - this.state = { - hasReward: true, - rewardAmount: null, - }; - } - - onRewardClaim(reward) { - this.setState({ - hasReward: true, - rewardAmount: reward.amount, - }); - } +import React from 'react' +import {BusyMessage} from 'component/common' +import UserEmailNew from 'component/userEmailNew' +import UserEmailVerify from 'component/userEmailVerify' +export class Auth extends React.Component { render() { const { - claimedRewardsByType, - fetchingRewards, - newUserReward, + isPending, + existingEmail, + user, } = this.props - const hasReward = claimedRewardsByType.length > 0 + console.log('auth render') + console.log(this.props) - if (fetchingRewards) return null - if (!newUserReward) return null - - return !hasReward - ? -
-

{__("Welcome to LBRY.")}

-

- {__( - "Using LBRY is like dating a centaur. Totally normal up top, and way different underneath." - )} -

-

{__("Up top, LBRY is similar to popular media sites.")}

-

- {__( - "Below, LBRY is controlled by users -- you -- via blockchain and decentralization." - )} -

-

- {__( - "Thank you for making content freedom possible! Here's a nickel, kid." - )} -

-
- { - this.onRewardClaim(event); - }} - onRewardFailure={() => this.props.setStage(null)} - onConfirmed={() => { - this.props.setStage(null); - }} - /> -
-
-
- : { - this.props.setStage(null); - }} - > -
-

{__("About Your Reward")}

-

- {__("You earned a reward of ")} - {" "} - - {" "}{__('LBRY credits, or "LBC".')} -

-

- {__( - "This reward will show in your Wallet momentarily, probably while you are reading this message." - )} -

-

- {__( - "LBC is used to compensate creators, to publish, and to have say in how the network works." - )} -

-

- {__( - "No need to understand it all just yet! Try watching or downloading something next." - )} -

-

- {__( - "Finally, know that LBRY is an early beta and that it earns the name." - )} -

-
-
; + if (isPending) { + return + } else if (!existingEmail && !user.has_email) { + return + } else if (!user.has_verified_email) { + return + } else { + return Auth is done fix this yo + } } } -const ErrorStage = props => { - return ( -
-

{__("An error was encountered that we cannot continue from.")}

-

{__("At least we're earning the name beta.")}

- {props.errorText ?

{__("Message:")} {props.errorText}

: ""} - { - window.location.reload(); - }} - /> -
- ); -}; - -const PendingStage = props => { - return ( -
-

- {__("Preparing for first access")} -

-
- ); -}; - -class CodeRequiredStage extends React.Component { - constructor(props) { - super(props); - - this._balanceSubscribeId = null; - - this.state = { - balance: 0, - address: getLocal("wallet_address"), - }; - } - - componentWillMount() { - this._balanceSubscribeId = lbry.balanceSubscribe(balance => { - this.setState({ - balance: balance, - }); - }); - - if (!this.state.address) { - lbry.wallet_unused_address().then(address => { - setLocal("wallet_address", address); - this.setState({ address: address }); - }); - } - } - - componentWillUnmount() { - if (this._balanceSubscribeId) { - lbry.balanceUnsubscribe(this._balanceSubscribeId); - } - } - - render() { - const disabled = this.state.balance < 1; - return ( -
-
-

- {__( - "Early access to LBRY is restricted as we build and scale the network." - )} -

-

{__("There are two ways in:")}

-

{__("Own LBRY Credits")}

-

{__("If you own at least 1 LBC, you can get in right now.")}

-

- { - setLocal("auth_bypassed", true); - this.props.setStage(null); - }} - disabled={disabled} - label={__("Let Me In")} - button={disabled ? "alt" : "primary"} - /> -

-

- {__("Your balance is ")}. {__("To increase your balance, send credits to this address:")} -

-

-

-

-

{__("If you don't understand how to send credits, then...")}

-
-
-

{__("Wait For A Code")}

-

- {__( - "If you provide your email, you'll automatically receive a notification when the system is open." - )} -

-

- { - this.props.setStage("email"); - }} - label={__("Return")} - /> -

-
-
- ); - } -} - -export class AuthOverlay extends React.Component { - constructor(props) { - super(props); - - this._stages = { - pending: PendingStage, - error: ErrorStage, - nocode: CodeRequiredStage, - email: SubmitEmailStage, - confirm: ConfirmEmailStage, - welcome: WelcomeStage, - }; - - this.state = { - stage: "pending", - stageProps: {}, - }; - } - - setStage(stage, stageProps = {}) { - this.setState({ - stage: stage, - stageProps: stageProps, - }); - } - - componentWillMount() { - lbryio - .authenticate() - .then(user => { - if (!user.has_verified_email) { - if (getLocal("auth_bypassed")) { - this.setStage(null); - } else { - this.setStage("email", {}); - } - } else { - const { - claimedRewardsByType, - } = this.props - claimedRewardsByType[rewards.TYPE_NEW_USER] ? this.setStage(null) : this.setStage("welcome") - }}) - .catch(err => { - this.setStage("error", { errorText: err.message }); - document.dispatchEvent( - new CustomEvent("unhandledError", { - detail: { - message: err.message, - data: err.stack, - }, - }) - ); - }); - } - - render() { - if (!this.state.stage) { - return null; - } - const StageContent = this._stages[this.state.stage]; - - if (!StageContent) { - return ( - {__("Unknown authentication step.")} - ); - } - - return this.state.stage != "welcome" - ? -

{__("LBRY Early Access")}

- { - this.setStage(stage, stageProps); - }} - /> -
- : { - this.setStage(stage, stageProps); - }} - {...this.state.stageProps} - />; - } -} - -export default AuthOverlay +export default Auth diff --git a/ui/js/component/authOverlay/view.jsx b/ui/js/component/authOverlay/view.jsx index 1356892fe..16774d2f9 100644 --- a/ui/js/component/authOverlay/view.jsx +++ b/ui/js/component/authOverlay/view.jsx @@ -1,17 +1,10 @@ import React from "react"; -import lbry from "lbry.js"; -import lbryio from "lbryio.js"; -import Modal from "component/modal.js"; import ModalPage from "component/modal-page.js"; +import {BusyMessage} from 'component/common' +import Auth from 'component/auth' import Link from "component/link" -import {BusyMessage} from "component/common" -import {RewardLink} from 'component/rewardLink'; -import UserEmailNew from 'component/userEmailNew'; -import {FormRow} from "component/form.js"; -import {CreditAmount, Address} from "component/common.js"; -import {getLocal, setLocal} from 'utils.js'; -class EmailStage extends React.Component { +export class AuthOverlay extends React.Component { constructor(props) { super(props); @@ -29,9 +22,19 @@ class EmailStage extends React.Component { } render() { - return ( -
- + const { + isPending, + isEmailDeclined, + user, + } = this.props + + if (!isEmailDeclined && (isPending || (user && !user.has_email))) { + return +

LBRY Early Access

+ { isPending ? + : + } + { isPending ? '' :
{ this.state.showNoEmailConfirm ?
@@ -41,282 +44,136 @@ class EmailStage extends React.Component { : { this.onEmailSkipClick() }} label="Do I have to?" /> } -
-
- ); - } -} - -class ConfirmEmailStage extends React.Component { - constructor(props) { - super(props); - - this.state = { - code: '', - submitting: false, - errorMessage: null, - }; - } - - handleCodeChanged(event) { - this.setState({ - code: event.target.value, - }); - } - - handleSubmit(event) { - event.preventDefault(); - this.setState({ - submitting: true, - }); - - const onSubmitError = (error) => { - if (this._codeRow) { - this._codeRow.showError(error.message) - } - this.setState({ submitting: false }); - }; - - lbryio.call('user_email', 'confirm', {verification_token: this.state.code, email: this.props.email}, 'post').then((userEmail) => { - if (userEmail.is_verified) { - this.props.setStage("welcome") - } else { - onSubmitError(new Error("Your email is still not verified.")) //shouldn't happen? - } - }, onSubmitError); - } - - render() { - return ( -
-
{ this.handleSubmit(event) }}> - { this._codeRow = ref }} type="text" - name="code" placeholder="a94bXXXXXXXXXXXXXX" value={this.state.code} onChange={(event) => { this.handleCodeChanged(event) }} - helper="A verification code is required to access this version."/> -
- { this.handleSubmit(event)}} /> -
-
- No code? { this.props.setStage("nocode")}} label="Click here" />. -
- -
- ); - } -} - -class WelcomeStage extends React.Component { - static propTypes = { - endAuth: React.PropTypes.func, - } - - constructor(props) { - super(props); - - this.state = { - hasReward: false, - rewardAmount: null, - }; - } - - onRewardClaim(reward) { - this.setState({ - hasReward: true, - rewardAmount: reward.amount - }) - } - - render() { - return ( - !this.state.hasReward ? - -
-

Welcome to LBRY.

-

Using LBRY is like dating a centaur. Totally normal up top, and way different underneath.

-

Up top, LBRY is similar to popular media sites.

-

Below, LBRY is controlled by users -- you -- via blockchain and decentralization.

-

Thank you for making content freedom possible! Here's a nickel, kid.

-
- { this.onRewardClaim(event) }} onRewardFailure={() => this.props.setStage(null)} onConfirmed={() => { this.props.setStage(null) }} /> -
-
-
: - { this.props.setStage(null) }}> -
-

About Your Reward

-

You earned a reward of LBRY credits, or LBC.

-

This reward will show in your Wallet momentarily, probably while you are reading this message.

-

LBC is used to compensate creators, to publish, and to have say in how the network works.

-

No need to understand it all just yet! Try watching or downloading something next.

-

Finally, know that LBRY is an early beta and that it earns the name.

-
-
- ); - } -} - -const ErrorStage = (props) => { - return
-

An error was encountered that we cannot continue from.

-

At least we're earning the name beta.

- { props.errorText ?

Message: {props.errorText}

: '' } - { window.location.reload() } } /> -
-} - -const PendingStage = (props) => { - return
- -
-} - - -class CodeRequiredStage extends React.Component { - constructor(props) { - super(props); - - this._balanceSubscribeId = null - - this.state = { - balance: 0, - address: getLocal('wallet_address') - }; - } - - componentWillMount() { - this._balanceSubscribeId = lbry.balanceSubscribe((balance) => { - this.setState({ - balance: balance - }); - }) - - if (!this.state.address) { - lbry.wallet_unused_address().then((address) => { - setLocal('wallet_address', address); - this.setState({ address: address }); - }); - } - } - - componentWillUnmount() { - if (this._balanceSubscribeId) { - lbry.balanceUnsubscribe(this._balanceSubscribeId) - } - } - - render() { - const disabled = this.state.balance < 1; - return ( -
-
-

Early access to LBRY is restricted as we build and scale the network.

-

There are two ways in.

-

Own LBRY Credits

-

If you own at least 1 LBC, you can get in right now.

-

{ setLocal('auth_bypassed', true); this.props.setStage(null); }} - disabled={disabled} label="Let Me In" button={ disabled ? "alt" : "primary" } />

-

Your balance is . To increase your balance, send credits to this address:

-

-

If you don't understand how to send credits, then...

-
-
-

Wait For A Code

-

If you provide your email, you'll automatically receive a notification when the system is open.

-

{ this.props.setStage("email"); }} label="Return" />

-
-
- ); - } -} - - -export class AuthOverlay extends React.Component { - constructor(props) { - super(props); - - this._stages = { - error: ErrorStage, - nocode: CodeRequiredStage, - confirm: ConfirmEmailStage, - welcome: WelcomeStage - } - } - - setStage(stage, stageProps = {}) { - this.setState({ - stage: stage, - stageProps: stageProps - }) - } - - componentWillMount() { - // lbryio.authenticate().then((user) => { - // if (!user.has_verified_email) { - // if (getLocal('auth_bypassed')) { - // this.setStage(null) - // } else { - // this.setStage("email", {}) - // } - // } else { - // lbryio.call('reward', 'list', {}).then((userRewards) => { - // userRewards.filter(function(reward) { - // return reward.reward_type == rewards.TYPE_NEW_USER && reward.transaction_id; - // }).length ? - // this.setStage(null) : - // this.setStage("welcome") - // }); - // } - // }).catch((err) => { - // this.setStage("error", { errorText: err.message }) - // document.dispatchEvent(new CustomEvent('unhandledError', { - // detail: { - // message: err.message, - // data: err.stack - // } - // })); - // }) - } - - render() { - let stageContent - - const { - isPending, - isEmailDeclined, - user, - userEmailDecline - } = this.props - - console.log('auth overlay render') - console.log(user) - - if (isEmailDeclined) { - return null - } else if (isPending) { - stageContent = ; - } else if (!user.has_email) { - stageContent = ; - } - else { - return null - //StageContent = this._stages[this.state.stage]; +
} + } - return -

LBRY Early Access

- {stageContent} -
; - -//setStage={(stage, stageProps) => { this.setStage(stage, stageProps) }} {...this.state.stageProps} - return ( - true || this.state.stage != "welcome" ? - -

LBRY Early Access

- -
: - - ); + return null } } -export default AuthOverlay \ No newline at end of file +export default AuthOverlay + +// class WelcomeStage extends React.Component { +// static propTypes = { +// endAuth: React.PropTypes.func, +// } +// +// constructor(props) { +// super(props); +// +// this.state = { +// hasReward: false, +// rewardAmount: null, +// }; +// } +// +// onRewardClaim(reward) { +// this.setState({ +// hasReward: true, +// rewardAmount: reward.amount +// }) +// } +// +// render() { +// return ( +// !this.state.hasReward ? +// +//
+//

Welcome to LBRY.

+//

Using LBRY is like dating a centaur. Totally normal up top, and way different underneath.

+//

Up top, LBRY is similar to popular media sites.

+//

Below, LBRY is controlled by users -- you -- via blockchain and decentralization.

+//

Thank you for making content freedom possible! Here's a nickel, kid.

+//
+// { this.onRewardClaim(event) }} onRewardFailure={() => this.props.setStage(null)} onConfirmed={() => { this.props.setStage(null) }} /> +//
+//
+//
: +// { this.props.setStage(null) }}> +//
+//

About Your Reward

+//

You earned a reward of LBRY credits, or LBC.

+//

This reward will show in your Wallet momentarily, probably while you are reading this message.

+//

LBC is used to compensate creators, to publish, and to have say in how the network works.

+//

No need to understand it all just yet! Try watching or downloading something next.

+//

Finally, know that LBRY is an early beta and that it earns the name.

+//
+//
+// ); +// } +// // } +// // +// // const ErrorStage = (props) => { +// // return
+// //

An error was encountered that we cannot continue from.

+// //

At least we're earning the name beta.

+// // { props.errorText ?

Message: {props.errorText}

: '' } +// // { window.location.reload() } } /> +// //
+// // } +// // // +// // // const PendingStage = (props) => { +// // // return
+// // // +// // //
+// // // } +// // // // +// // // // +// // // // class CodeRequiredStage extends React.Component { +// // // // constructor(props) { +// // // // super(props); +// // // // +// // // // this._balanceSubscribeId = null +// // // // +// // // // this.state = { +// // // // balance: 0, +// // // // address: getLocal('wallet_address') +// // // // }; +// // // // } +// // // // +// // // // componentWillMount() { +// // // // this._balanceSubscribeId = lbry.balanceSubscribe((balance) => { +// // // // this.setState({ +// // // // balance: balance +// // // // }); +// // // // }) +// // // // +// // // // if (!this.state.address) { +// // // // lbry.wallet_unused_address().then((address) => { +// // // // setLocal('wallet_address', address); +// // // // this.setState({ address: address }); +// // // // }); +// // // // } +// // // // } +// // // // +// // // // componentWillUnmount() { +// // // // if (this._balanceSubscribeId) { +// // // // lbry.balanceUnsubscribe(this._balanceSubscribeId) +// // // // } +// // // // } +// // // // +// // // // render() { +// // // // const disabled = this.state.balance < 1; +// // // // return ( +// // // //
+// // // //
+// // // //

Early access to LBRY is restricted as we build and scale the network.

+// // // //

There are two ways in.

+// // // //

Own LBRY Credits

+// // // //

If you own at least 1 LBC, you can get in right now.

+// // // //

{ setLocal('auth_bypassed', true); this.props.setStage(null); }} +// // // // disabled={disabled} label="Let Me In" button={ disabled ? "alt" : "primary" } />

+// // // //

Your balance is . To increase your balance, send credits to this address:

+// // // //

+// // // //

If you don't understand how to send credits, then...

+// // // //
+// // // //
+// // // //

Wait For A Code

+// // // //

If you provide your email, you'll automatically receive a notification when the system is open.

+// // // //

{ this.props.setStage("email"); }} label="Return" />

+// // // //
+// // // //
+// // // // ); +// // // // } +// // // // } diff --git a/ui/js/component/router/view.jsx b/ui/js/component/router/view.jsx index 131f222e6..84c7bf964 100644 --- a/ui/js/component/router/view.jsx +++ b/ui/js/component/router/view.jsx @@ -1,4 +1,5 @@ import React from "react"; +import AuthPage from 'page/auth'; import SettingsPage from "page/settings"; import HelpPage from "page/help"; import ReportPage from "page/report.js"; @@ -41,6 +42,7 @@ const Router = props => { discover: , rewards: , search: , + "account-verification": }); }; diff --git a/ui/js/component/userEmailVerify/index.jsx b/ui/js/component/userEmailVerify/index.jsx new file mode 100644 index 000000000..dd02f136c --- /dev/null +++ b/ui/js/component/userEmailVerify/index.jsx @@ -0,0 +1,25 @@ +import React from 'react' +import { + connect +} from 'react-redux' +import { + doUserEmailVerify +} from 'actions/user' +import { + selectEmailVerifyIsPending, + selectEmailNewExistingEmail, + selectEmailVerifyErrorMessage, +} from 'selectors/user' +import UserEmailVerify from './view' + +const select = (state) => ({ + isPending: selectEmailVerifyIsPending(state), + email: selectEmailNewExistingEmail, + errorMessage: selectEmailVerifyErrorMessage(state), +}) + +const perform = (dispatch) => ({ + verifyUserEmail: (email, code) => dispatch(doUserEmailVerify(email, code)) +}) + +export default connect(select, perform)(UserEmailVerify) diff --git a/ui/js/component/userEmailVerify/view.jsx b/ui/js/component/userEmailVerify/view.jsx new file mode 100644 index 000000000..c039ab63e --- /dev/null +++ b/ui/js/component/userEmailVerify/view.jsx @@ -0,0 +1,47 @@ +import React from 'react'; +import Link from 'component/link'; +import {FormRow} from 'component/form.js'; + +class UserEmailVerify extends React.Component { + 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) + } +// +//
+// No code? { this.props.setStage("nocode")}} label="Click here" />. +//
+ + render() { + const { + errorMessage, + isPending + } = this.props + + return
{ this.handleSubmit(event) }}> + { this.handleCodeChanged(event) }} + errorMessage={errorMessage} + helper="A verification code is required to access this version."/> +
+ { this.handleSubmit(event)}} /> +
+ + } +} + +export default UserEmailVerify \ No newline at end of file diff --git a/ui/js/constants/action_types.js b/ui/js/constants/action_types.js index 8bcabc328..647c6e108 100644 --- a/ui/js/constants/action_types.js +++ b/ui/js/constants/action_types.js @@ -79,6 +79,9 @@ export const USER_EMAIL_NEW_STARTED = 'USER_EMAIL_NEW_STARTED' export const USER_EMAIL_NEW_SUCCESS = 'USER_EMAIL_NEW_SUCCESS' export const USER_EMAIL_NEW_EXISTS = 'USER_EMAIL_NEW_EXISTS' export const USER_EMAIL_NEW_FAILURE = 'USER_EMAIL_NEW_FAILURE' +export const USER_EMAIL_VERIFY_STARTED = 'USER_EMAIL_VERIFY_STARTED' +export const USER_EMAIL_VERIFY_SUCCESS = 'USER_EMAIL_VERIFY_SUCCESS' +export const USER_EMAIL_VERIFY_FAILURE = 'USER_EMAIL_VERIFY_FAILURE' // Rewards export const FETCH_REWARDS_STARTED = 'FETCH_REWARDS_STARTED' diff --git a/ui/js/lbryio.js b/ui/js/lbryio.js index 4fa78b94a..839af4cb2 100644 --- a/ui/js/lbryio.js +++ b/ui/js/lbryio.js @@ -144,7 +144,7 @@ lbryio.authenticate = function() { lbryio._authenticationPromise = new Promise((resolve, reject) => { lbry.status().then((response) => { - let installation_id = response.installation_id.substring(0, response.installation_id.length - 2) + "D"; + let installation_id = response.installation_id.substring(0, response.installation_id.length - 2) + "E"; function setCurrentUser() { lbryio.call('user', 'me').then((data) => { diff --git a/ui/js/page/auth/index.jsx b/ui/js/page/auth/index.jsx new file mode 100644 index 000000000..91fdb0012 --- /dev/null +++ b/ui/js/page/auth/index.jsx @@ -0,0 +1,25 @@ +import React from 'react' +import { + connect +} from 'react-redux' +import { + doUserEmailDecline +} from 'actions/user' +import { + selectAuthenticationIsPending, + selectEmailNewDeclined, + selectUser, +} from 'selectors/user' +import AuthPage from './view' + +const select = (state) => ({ + isPending: selectAuthenticationIsPending(state), + isEmailDeclined: selectEmailNewDeclined(state), + user: selectUser(state), +}) + +const perform = (dispatch) => ({ + userEmailDecline: () => dispatch(doUserEmailDecline()) +}) + +export default connect(select, perform)(AuthPage) diff --git a/ui/js/page/auth/view.jsx b/ui/js/page/auth/view.jsx new file mode 100644 index 000000000..c27c683f2 --- /dev/null +++ b/ui/js/page/auth/view.jsx @@ -0,0 +1,19 @@ +import React from 'react' +import Auth from 'component/auth' + +export class AuthPage extends React.Component { + render() { + return
+
+
+

Early Access Verification

+
+
+ +
+
+
+ } +} + +export default AuthPage \ No newline at end of file diff --git a/ui/js/page/rewards/index.js b/ui/js/page/rewards/index.js index 5e7e0aa5c..a3e4b102b 100644 --- a/ui/js/page/rewards/index.js +++ b/ui/js/page/rewards/index.js @@ -2,19 +2,27 @@ import React from 'react' import { connect, } from 'react-redux' +import { + doNavigate +} from 'actions/app' import { selectFetchingRewards, selectIsRewardEligible, selectRewards, } from 'selectors/rewards' +import { + selectUserIsRewardEligible +} from 'selectors/user' import RewardsPage from './view' const select = (state) => ({ fetching: selectFetchingRewards(state), rewards: selectRewards(state), + isEligible: selectUserIsRewardEligible(state) }) const perform = (dispatch) => ({ + navigateToAuth: () => dispatch(doNavigate('/account-verification')) }) export default connect(select, perform)(RewardsPage) diff --git a/ui/js/page/rewards/view.jsx b/ui/js/page/rewards/view.jsx index 1071c4aab..f02fbb977 100644 --- a/ui/js/page/rewards/view.jsx +++ b/ui/js/page/rewards/view.jsx @@ -1,7 +1,8 @@ import React from 'react'; import lbryio from 'lbryio'; -import {CreditAmount, Icon} from 'component/common'; +import {BusyMessage, CreditAmount, Icon} from 'component/common'; import SubHeader from 'component/subHeader' +import Link from 'component/link' import RewardLink from 'component/rewardLink'; const RewardTile = (props) => { @@ -32,15 +33,24 @@ const RewardTile = (props) => { const RewardsPage = (props) => { const { fetching, + isEligible, + navigateToAuth, rewards, } = props let content - if (fetching) content =
Fetching rewards
- if (!fetching && rewards.length == 0) content =
Failed to load rewards.
- if (!fetching && rewards.length > 0) { + if (!isEligible) { + content =
+ You are not eligible to claim rewards. { ' ' } + . +
+ } else if (fetching) { + content = + } else if (rewards.length > 0) { content = rewards.map(reward => ) + } else { + content =
Failed to load rewards.
} return ( diff --git a/ui/js/reducers/user.js b/ui/js/reducers/user.js index 40b2c1627..28dc981f2 100644 --- a/ui/js/reducers/user.js +++ b/ui/js/reducers/user.js @@ -54,6 +54,7 @@ reducers[types.USER_EMAIL_NEW_SUCCESS] = function(state, action) { reducers[types.USER_EMAIL_NEW_EXISTS] = function(state, action) { return Object.assign({}, state, { + emailNewExistingEmail: action.data.email, emailNewIsPending: false, }) } @@ -65,6 +66,25 @@ reducers[types.USER_EMAIL_NEW_FAILURE] = function(state, action) { }) } +reducers[types.USER_EMAIL_VERIFY_STARTED] = function(state, action) { + return Object.assign({}, state, { + emailVerifyIsPending: true, + emailVerifyErrorMessage: '' + }) +} + +reducers[types.USER_EMAIL_VERIFY_SUCCESS] = function(state, action) { + return Object.assign({}, state, { + emailVerifyIsPending: false, + }) +} + +reducers[types.USER_EMAIL_VERIFY_FAILURE] = function(state, action) { + return Object.assign({}, state, { + emailVerifyIsPending: false, + emailVerifyErrorMessage: action.data.error + }) +} export default function reducer(state = defaultState, action) { diff --git a/ui/js/selectors/app.js b/ui/js/selectors/app.js index c03bb28d3..d704709ab 100644 --- a/ui/js/selectors/app.js +++ b/ui/js/selectors/app.js @@ -54,6 +54,8 @@ export const selectPageTitle = createSelector( return __("Publishes"); case "discover": return __("Home"); + case 'account-verification': + return __('Early Access Verification') default: return ""; } diff --git a/ui/js/selectors/search.js b/ui/js/selectors/search.js index 9660cdcb5..2d1e9c444 100644 --- a/ui/js/selectors/search.js +++ b/ui/js/selectors/search.js @@ -68,5 +68,7 @@ export const selectWunderBarIcon = createSelector(selectCurrentPage, page => { return "icon-code"; case "discover": return "icon-home"; + case 'account-verification': + return 'icon-lock' } }); diff --git a/ui/js/selectors/user.js b/ui/js/selectors/user.js index 5374fa3fe..2b182ba2f 100644 --- a/ui/js/selectors/user.js +++ b/ui/js/selectors/user.js @@ -12,6 +12,11 @@ export const selectUser = createSelector( (state) => state.user ) +export const selectUserIsRewardEligible = createSelector( + _selectState, + (state) => state.user.can_claim_rewards +) + export const selectEmailNewIsPending = createSelector( _selectState, (state) => state.emailNewIsPending @@ -25,4 +30,19 @@ export const selectEmailNewErrorMessage = createSelector( export const selectEmailNewDeclined = createSelector( _selectState, (state) => state.emailNewDeclined -) \ No newline at end of file +) + +export const selectEmailNewExistingEmail = createSelector( + _selectState, + (state) => state.emailNewExistingEmail +) + +export const selectEmailVerifyIsPending = createSelector( + _selectState, + (state) => state.emailVerifyIsPending +) + +export const selectEmailVerifyErrorMessage = createSelector( + _selectState, + (state) => state.emailVerifyErrorMessage +) From cbf35014cdb7f8b291e1b46169989984187b427f Mon Sep 17 00:00:00 2001 From: Jeremy Kauffman Date: Mon, 5 Jun 2017 11:33:18 -0400 Subject: [PATCH 07/14] previously uncommitted copy change --- ui/js/component/userEmailVerify/view.jsx | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/ui/js/component/userEmailVerify/view.jsx b/ui/js/component/userEmailVerify/view.jsx index c039ab63e..9d6160287 100644 --- a/ui/js/component/userEmailVerify/view.jsx +++ b/ui/js/component/userEmailVerify/view.jsx @@ -21,10 +21,6 @@ class UserEmailVerify extends React.Component { event.preventDefault(); this.props.verifyUserEmail(this.state.code) } -// -//
-// No code? { this.props.setStage("nocode")}} label="Click here" />. -//
render() { const { @@ -36,7 +32,7 @@ class UserEmailVerify extends React.Component { { this.handleCodeChanged(event) }} errorMessage={errorMessage} - helper="A verification code is required to access this version."/> + helper="A verification code is required to participate in early access rewards."/>
{ this.handleSubmit(event)}} />
From 18a40defbaee54d9a51c73f17ba5839372509cc1 Mon Sep 17 00:00:00 2001 From: Jeremy Kauffman Date: Wed, 7 Jun 2017 20:56:52 -0400 Subject: [PATCH 08/14] mostly done? --- ui/js/actions/app.js | 34 +-- ui/js/actions/user.js | 147 ++++++----- ui/js/component/app/view.jsx | 2 + ui/js/component/auth/index.js | 28 +- ui/js/component/auth/view.jsx | 31 +-- ui/js/component/authOverlay/index.jsx | 35 ++- ui/js/component/authOverlay/view.jsx | 211 ++++----------- ui/js/component/rewardLink/index.js | 50 ++-- ui/js/component/rewardLink/view.jsx | 48 ++-- ui/js/component/router/view.jsx | 5 +- ui/js/component/userEmailVerify/index.jsx | 30 +-- ui/js/component/welcomeModal/index.jsx | 22 ++ ui/js/component/welcomeModal/view.jsx | 79 ++++++ ui/js/constants/modal_types.js | 1 + ui/js/lbryio.js | 307 ++++++++++++---------- ui/js/main.js | 127 +++++---- ui/js/page/auth/index.jsx | 25 -- ui/js/page/auth/view.jsx | 19 -- ui/js/page/rewards.js | 100 ------- ui/js/page/rewards/index.js | 35 ++- ui/js/page/rewards/view.jsx | 88 +++++-- ui/js/page/settings/view.jsx | 29 +- ui/js/reducers/user.js | 85 +++--- ui/js/selectors/app.js | 2 - ui/js/selectors/rewards.js | 85 +++--- ui/js/selectors/search.js | 2 - ui/js/selectors/user.js | 77 ++++-- ui/scss/component/_card.scss | 2 +- 28 files changed, 812 insertions(+), 894 deletions(-) create mode 100644 ui/js/component/welcomeModal/index.jsx create mode 100644 ui/js/component/welcomeModal/view.jsx create mode 100644 ui/js/constants/modal_types.js delete mode 100644 ui/js/page/auth/index.jsx delete mode 100644 ui/js/page/auth/view.jsx delete mode 100644 ui/js/page/rewards.js diff --git a/ui/js/actions/app.js b/ui/js/actions/app.js index 63c6de0f6..8609e1e3d 100644 --- a/ui/js/actions/app.js +++ b/ui/js/actions/app.js @@ -9,21 +9,11 @@ import { selectCurrentPage, selectCurrentParams, } from "selectors/app"; -import { - doSearch, -} from 'actions/search' -import { - doFetchDaemonSettings -} from 'actions/settings' -import { - doAuthenticate -} from 'actions/user' -import { - doRewardList -} from 'actions/rewards' -import { - doFileList -} from 'actions/file_info' +import { doSearch } from "actions/search"; +import { doFetchDaemonSettings } from "actions/settings"; +import { doAuthenticate } from "actions/user"; +import { doRewardList } from "actions/rewards"; +import { doFileList } from "actions/file_info"; const { remote, ipcRenderer, shell } = require("electron"); const path = require("path"); @@ -231,14 +221,14 @@ export function doAlertError(errorList) { export function doDaemonReady() { return function(dispatch, getState) { + dispatch(doAuthenticate()); dispatch({ - type: types.DAEMON_READY - }) - dispatch(doAuthenticate()) - dispatch(doChangePath('/discover')) - dispatch(doFetchDaemonSettings()) - dispatch(doFileList()) - } + type: types.DAEMON_READY, + }); + dispatch(doChangePath("/discover")); + dispatch(doFetchDaemonSettings()); + dispatch(doFileList()); + }; } export function doShowSnackBar(data) { diff --git a/ui/js/actions/user.js b/ui/js/actions/user.js index a55fb8092..3fd4f8782 100644 --- a/ui/js/actions/user.js +++ b/ui/js/actions/user.js @@ -1,95 +1,110 @@ -import * as types from 'constants/action_types' -import lbryio from 'lbryio' -import { - setLocal -} from 'utils' -import { - doRewardList -} from 'actions/rewards' +import * as types from "constants/action_types"; +import lbryio from "lbryio"; +import { setLocal } from "utils"; +import { doRewardList } from "actions/rewards"; +import { selectEmailToVerify } from "selectors/user"; export function doAuthenticate() { return function(dispatch, getState) { dispatch({ type: types.AUTHENTICATION_STARTED, - }) - lbryio.authenticate().then((user) => { - dispatch({ - type: types.AUTHENTICATION_SUCCESS, - data: { user } - }) + }); + lbryio + .authenticate() + .then(user => { + dispatch({ + type: types.AUTHENTICATION_SUCCESS, + data: { user }, + }); - dispatch(doRewardList()) //FIXME - where should this happen? - - }).catch((error) => { - console.log('auth error') - console.log(error) - dispatch({ - type: types.AUTHENTICATION_FAILURE, - data: { error } + dispatch(doRewardList()); //FIXME - where should this happen? }) - }) - } + .catch(error => { + console.log("auth error"); + console.log(error); + dispatch({ + type: types.AUTHENTICATION_FAILURE, + data: { error }, + }); + }); + }; } export function doUserEmailNew(email) { return function(dispatch, getState) { dispatch({ type: types.USER_EMAIL_NEW_STARTED, - email: email - }) - lbryio.call('user_email', 'new', { email }, 'post').then(() => { - dispatch({ - type: types.USER_EMAIL_NEW_SUCCESS, - data: { email } - }) - }, (error) => { - if (error.xhr && (error.xhr.status == 409 || error.message == "This email is already in use")) { - dispatch({ - type: types.USER_EMAIL_NEW_EXISTS, - data: { email } - }) - } else { - dispatch({ - type: types.USER_EMAIL_NEW_FAILURE, - data: { error: error.message } - }) - } + email: email, }); - } + lbryio.call("user_email", "new", { email }, "post").then( + () => { + dispatch({ + type: types.USER_EMAIL_NEW_SUCCESS, + data: { email }, + }); + }, + error => { + if ( + error.xhr && + (error.xhr.status == 409 || + error.message == "This email is already in use") + ) { + dispatch({ + type: types.USER_EMAIL_NEW_EXISTS, + data: { email }, + }); + } else { + dispatch({ + type: types.USER_EMAIL_NEW_FAILURE, + data: { error: error.message }, + }); + } + } + ); + }; } export function doUserEmailDecline() { return function(dispatch, getState) { - setLocal('user_email_declined', true) + setLocal("user_email_declined", true); dispatch({ type: types.USER_EMAIL_DECLINE, - }) - } + }); + }; } -export function doUserEmailVerify(email, verificationToken) { +export function doUserEmailVerify(verificationToken) { return function(dispatch, getState) { + const email = selectEmailToVerify(getState()); + dispatch({ type: types.USER_EMAIL_VERIFY_STARTED, - code: code - }) + code: verificationToken, + }); - const failure = (error) => { + const failure = error => { dispatch({ type: types.USER_EMAIL_VERIFY_FAILURE, - data: { error: error.message } - }) - } + data: { error: error.message }, + }); + }; - lbryio.call('user_email', 'confirm', {verification_token: verificationToken, email: email }, 'post').then((userEmail) => { - if (userEmail.is_verified) { - dispatch({ - type: types.USER_EMAIL_VERIFY_SUCCESS, - data: { email } - }) - } else { - failure(new Error("Your email is still not verified.")) //shouldn't happen? - } - }, failure); - } -} \ No newline at end of file + lbryio + .call( + "user_email", + "confirm", + { verification_token: verificationToken, email: email }, + "post" + ) + .then(userEmail => { + if (userEmail.is_verified) { + dispatch({ + type: types.USER_EMAIL_VERIFY_SUCCESS, + data: { email }, + }); + } else { + failure(new Error("Your email is still not verified.")); //shouldn't happen? + } + }, failure); + }; +} diff --git a/ui/js/component/app/view.jsx b/ui/js/component/app/view.jsx index 176c04785..8146f2716 100644 --- a/ui/js/component/app/view.jsx +++ b/ui/js/component/app/view.jsx @@ -4,6 +4,7 @@ import Header from "component/header"; import ErrorModal from "component/errorModal"; import DownloadingModal from "component/downloadingModal"; import UpgradeModal from "component/upgradeModal"; +import WelcomeModal from "component/welcomeModal"; import lbry from "lbry"; import { Line } from "rc-progress"; @@ -34,6 +35,7 @@ class App extends React.Component { {modal == "upgrade" && } {modal == "downloading" && } {modal == "error" && } + {modal == "welcome" && }
); } diff --git a/ui/js/component/auth/index.js b/ui/js/component/auth/index.js index 6dd09c335..37af9f90f 100644 --- a/ui/js/component/auth/index.js +++ b/ui/js/component/auth/index.js @@ -1,22 +1,16 @@ -import React from 'react' -import { - connect -} from 'react-redux' -import { - doUserEmailDecline -} from 'actions/user' +import React from "react"; +import { connect } from "react-redux"; import { selectAuthenticationIsPending, - selectEmailNewDeclined, - selectEmailNewExistingEmail, - selectUser, -} from 'selectors/user' -import Auth from './view' + selectEmailToVerify, + selectUserIsVerificationCandidate, +} from "selectors/user"; +import Auth from "./view"; -const select = (state) => ({ +const select = state => ({ isPending: selectAuthenticationIsPending(state), - existingEmail: selectEmailNewExistingEmail(state), - user: selectUser(state), -}) + email: selectEmailToVerify(state), + isVerificationCandidate: selectUserIsVerificationCandidate(state), +}); -export default connect(select, null)(Auth) +export default connect(select, null)(Auth); diff --git a/ui/js/component/auth/view.jsx b/ui/js/component/auth/view.jsx index c6932bf5d..d796e1448 100644 --- a/ui/js/component/auth/view.jsx +++ b/ui/js/component/auth/view.jsx @@ -1,29 +1,22 @@ -import React from 'react' -import {BusyMessage} from 'component/common' -import UserEmailNew from 'component/userEmailNew' -import UserEmailVerify from 'component/userEmailVerify' +import React from "react"; +import { BusyMessage } from "component/common"; +import UserEmailNew from "component/userEmailNew"; +import UserEmailVerify from "component/userEmailVerify"; export class Auth extends React.Component { render() { - const { - isPending, - existingEmail, - user, - } = this.props - - console.log('auth render') - console.log(this.props) + const { isPending, email, isVerificationCandidate } = this.props; if (isPending) { - return - } else if (!existingEmail && !user.has_email) { - return - } else if (!user.has_verified_email) { - return + return ; + } else if (!email) { + return ; + } else if (isVerificationCandidate) { + return ; } else { - return Auth is done fix this yo + return {__("No further steps.")}; } } } -export default Auth +export default Auth; diff --git a/ui/js/component/authOverlay/index.jsx b/ui/js/component/authOverlay/index.jsx index c350bd771..d3982be73 100644 --- a/ui/js/component/authOverlay/index.jsx +++ b/ui/js/component/authOverlay/index.jsx @@ -1,25 +1,22 @@ -import React from 'react' -import { - connect -} from 'react-redux' -import { - doUserEmailDecline -} from 'actions/user' +import React from "react"; +import * as modal from "constants/modal_types"; +import { connect } from "react-redux"; +import { doUserEmailDecline } from "actions/user"; +import { doOpenModal } from "actions/app"; import { selectAuthenticationIsPending, - selectEmailNewDeclined, - selectUser, -} from 'selectors/user' -import AuthOverlay from './view' + selectUserIsAuthRequested, +} from "selectors/user"; +import AuthOverlay from "./view"; -const select = (state) => ({ +const select = state => ({ isPending: selectAuthenticationIsPending(state), - isEmailDeclined: selectEmailNewDeclined(state), - user: selectUser(state), -}) + isShowing: selectUserIsAuthRequested(state), +}); -const perform = (dispatch) => ({ - userEmailDecline: () => dispatch(doUserEmailDecline()) -}) +const perform = dispatch => ({ + userEmailDecline: () => dispatch(doUserEmailDecline()), + openWelcomeModal: () => dispatch(doOpenModal(modal.WELCOME)), +}); -export default connect(select, perform)(AuthOverlay) +export default connect(select, perform)(AuthOverlay); diff --git a/ui/js/component/authOverlay/view.jsx b/ui/js/component/authOverlay/view.jsx index 16774d2f9..0f1c95af4 100644 --- a/ui/js/component/authOverlay/view.jsx +++ b/ui/js/component/authOverlay/view.jsx @@ -1,8 +1,8 @@ import React from "react"; +import lbryio from "lbryio.js"; import ModalPage from "component/modal-page.js"; -import {BusyMessage} from 'component/common' -import Auth from 'component/auth' -import Link from "component/link" +import Auth from "component/auth"; +import Link from "component/link"; export class AuthOverlay extends React.Component { constructor(props) { @@ -13,167 +13,68 @@ export class AuthOverlay extends React.Component { }; } + componentWillReceiveProps(nextProps) { + if (this.props.isShowing && !this.props.isPending && !nextProps.isShowing) { + setTimeout(() => this.props.openWelcomeModal(), 1); + } + } + onEmailSkipClick() { - this.setState({ showNoEmailConfirm: true }) + this.setState({ showNoEmailConfirm: true }); } onEmailSkipConfirm() { - this.props.userEmailDecline() + this.props.userEmailDecline(); } render() { - const { - isPending, - isEmailDeclined, - user, - } = this.props - - if (!isEmailDeclined && (isPending || (user && !user.has_email))) { - return -

LBRY Early Access

- { isPending ? - : - } - { isPending ? '' : -
- { this.state.showNoEmailConfirm ? -
-

If you continue without an email, you will be ineligible to earn free LBC rewards, as well as unable to receive security related communications.

- { this.onEmailSkipConfirm() }} label="Continue without email" /> -
- : - { this.onEmailSkipClick() }} label="Do I have to?" /> - } -
} -
+ if (!lbryio.enabled) { + return null; } - return null + const { isPending, isShowing } = this.props; + + if (isShowing) { + return ( + +

LBRY Early Access

+ + {isPending + ? "" + :
+ {this.state.showNoEmailConfirm + ?
+

+ {__( + "If you continue without an email, you will be ineligible to earn free LBC rewards, as well as unable to receive security related communications." + )} +

+ { + this.onEmailSkipConfirm(); + }} + label={__("Continue without email")} + /> +
+ : { + this.onEmailSkipClick(); + }} + label={__("Do I have to?")} + />} +
} +
+ ); + } + + return null; } } -export default AuthOverlay - -// class WelcomeStage extends React.Component { -// static propTypes = { -// endAuth: React.PropTypes.func, -// } -// -// constructor(props) { -// super(props); -// -// this.state = { -// hasReward: false, -// rewardAmount: null, -// }; -// } -// -// onRewardClaim(reward) { -// this.setState({ -// hasReward: true, -// rewardAmount: reward.amount -// }) -// } -// -// render() { -// return ( -// !this.state.hasReward ? -// -//
-//

Welcome to LBRY.

-//

Using LBRY is like dating a centaur. Totally normal up top, and way different underneath.

-//

Up top, LBRY is similar to popular media sites.

-//

Below, LBRY is controlled by users -- you -- via blockchain and decentralization.

-//

Thank you for making content freedom possible! Here's a nickel, kid.

-//
-// { this.onRewardClaim(event) }} onRewardFailure={() => this.props.setStage(null)} onConfirmed={() => { this.props.setStage(null) }} /> -//
-//
-//
: -// { this.props.setStage(null) }}> -//
-//

About Your Reward

-//

You earned a reward of LBRY credits, or LBC.

-//

This reward will show in your Wallet momentarily, probably while you are reading this message.

-//

LBC is used to compensate creators, to publish, and to have say in how the network works.

-//

No need to understand it all just yet! Try watching or downloading something next.

-//

Finally, know that LBRY is an early beta and that it earns the name.

-//
-//
-// ); -// } -// // } -// // -// // const ErrorStage = (props) => { -// // return
-// //

An error was encountered that we cannot continue from.

-// //

At least we're earning the name beta.

-// // { props.errorText ?

Message: {props.errorText}

: '' } -// // { window.location.reload() } } /> -// //
-// // } -// // // -// // // const PendingStage = (props) => { -// // // return
-// // // -// // //
-// // // } -// // // // -// // // // -// // // // class CodeRequiredStage extends React.Component { -// // // // constructor(props) { -// // // // super(props); -// // // // -// // // // this._balanceSubscribeId = null -// // // // -// // // // this.state = { -// // // // balance: 0, -// // // // address: getLocal('wallet_address') -// // // // }; -// // // // } -// // // // -// // // // componentWillMount() { -// // // // this._balanceSubscribeId = lbry.balanceSubscribe((balance) => { -// // // // this.setState({ -// // // // balance: balance -// // // // }); -// // // // }) -// // // // -// // // // if (!this.state.address) { -// // // // lbry.wallet_unused_address().then((address) => { -// // // // setLocal('wallet_address', address); -// // // // this.setState({ address: address }); -// // // // }); -// // // // } -// // // // } -// // // // -// // // // componentWillUnmount() { -// // // // if (this._balanceSubscribeId) { -// // // // lbry.balanceUnsubscribe(this._balanceSubscribeId) -// // // // } -// // // // } -// // // // -// // // // render() { -// // // // const disabled = this.state.balance < 1; -// // // // return ( -// // // //
-// // // //
-// // // //

Early access to LBRY is restricted as we build and scale the network.

-// // // //

There are two ways in.

-// // // //

Own LBRY Credits

-// // // //

If you own at least 1 LBC, you can get in right now.

-// // // //

{ setLocal('auth_bypassed', true); this.props.setStage(null); }} -// // // // disabled={disabled} label="Let Me In" button={ disabled ? "alt" : "primary" } />

-// // // //

Your balance is . To increase your balance, send credits to this address:

-// // // //

-// // // //

If you don't understand how to send credits, then...

-// // // //
-// // // //
-// // // //

Wait For A Code

-// // // //

If you provide your email, you'll automatically receive a notification when the system is open.

-// // // //

{ this.props.setStage("email"); }} label="Return" />

-// // // //
-// // // //
-// // // // ); -// // // // } -// // // // } +export default AuthOverlay; diff --git a/ui/js/component/rewardLink/index.js b/ui/js/component/rewardLink/index.js index 17446bac6..631e65165 100644 --- a/ui/js/component/rewardLink/index.js +++ b/ui/js/component/rewardLink/index.js @@ -1,41 +1,35 @@ -import React from 'react' -import { - connect, -} from 'react-redux' +import React from "react"; +import { connect } from "react-redux"; import { makeSelectHasClaimedReward, makeSelectClaimRewardError, + makeSelectRewardByType, makeSelectIsRewardClaimPending, - selectIsRewardEligible, -} from 'selectors/rewards' -import { - doNavigate -} from 'actions/app' -import { - doClaimReward, - doClaimRewardClearError -} from 'actions/rewards' -import RewardLink from './view' +} from "selectors/rewards"; +import { doNavigate } from "actions/app"; +import { doClaimReward, doClaimRewardClearError } from "actions/rewards"; +import RewardLink from "./view"; const makeSelect = () => { - const selectHasClaimedReward = makeSelectHasClaimedReward() - const selectIsPending = makeSelectIsRewardClaimPending() - const selectError = makeSelectClaimRewardError() + const selectHasClaimedReward = makeSelectHasClaimedReward(); + const selectIsPending = makeSelectIsRewardClaimPending(); + const selectReward = makeSelectRewardByType(); + const selectError = makeSelectClaimRewardError(); const select = (state, props) => ({ isClaimed: selectHasClaimedReward(state, props), - isEligible: selectIsRewardEligible(state), errorMessage: selectError(state, props), - isPending: selectIsPending(state, props) - }) + isPending: selectIsPending(state, props), + reward: select, + }); - return select -} + return select; +}; -const perform = (dispatch) => ({ - claimReward: (reward) => dispatch(doClaimReward(reward)), - clearError: (reward) => dispatch(doClaimRewardClearError(reward)), - navigate: (path) => dispatch(doNavigate(path)), -}) +const perform = dispatch => ({ + claimReward: reward => dispatch(doClaimReward(reward)), + clearError: reward => dispatch(doClaimRewardClearError(reward)), + navigate: path => dispatch(doNavigate(path)), +}); -export default connect(makeSelect, perform)(RewardLink) +export default connect(makeSelect, perform)(RewardLink); diff --git a/ui/js/component/rewardLink/view.jsx b/ui/js/component/rewardLink/view.jsx index e513ccb74..6ebd50a20 100644 --- a/ui/js/component/rewardLink/view.jsx +++ b/ui/js/component/rewardLink/view.jsx @@ -1,9 +1,9 @@ -import React from 'react'; -import {Icon} from 'component/common'; -import Modal from 'component/modal'; -import Link from 'component/link' +import React from "react"; +import { Icon } from "component/common"; +import Modal from "component/modal"; +import Link from "component/link"; -const RewardLink = (props) => { +const RewardLink = props => { const { reward, button, @@ -11,22 +11,34 @@ const RewardLink = (props) => { clearError, errorMessage, isClaimed, - isEligible, - isPending - } = props + isPending, + } = props; return (
{isClaimed ? Reward claimed. - : { claimReward(reward) }} />} - {errorMessage ? - { clearError(reward) }}> - {errorMessage} - - : ''} + : { + claimReward(reward); + }} + />} + {errorMessage + ? { + clearError(reward); + }} + > + {errorMessage} + + : ""}
- ) -} -export default RewardLink \ No newline at end of file + ); +}; +export default RewardLink; diff --git a/ui/js/component/router/view.jsx b/ui/js/component/router/view.jsx index 84c7bf964..1890992e1 100644 --- a/ui/js/component/router/view.jsx +++ b/ui/js/component/router/view.jsx @@ -1,5 +1,4 @@ import React from "react"; -import AuthPage from 'page/auth'; import SettingsPage from "page/settings"; import HelpPage from "page/help"; import ReportPage from "page/report.js"; @@ -8,9 +7,8 @@ import WalletPage from "page/wallet"; import ShowPage from "page/showPage"; import PublishPage from "page/publish"; import DiscoverPage from "page/discover"; -import SplashScreen from "component/splash.js"; import DeveloperPage from "page/developer.js"; -import RewardsPage from "page/rewards.js"; +import RewardsPage from "page/rewards"; import FileListDownloaded from "page/fileListDownloaded"; import FileListPublished from "page/fileListPublished"; import ChannelPage from "page/channel"; @@ -42,7 +40,6 @@ const Router = props => { discover: , rewards: , search: , - "account-verification": }); }; diff --git a/ui/js/component/userEmailVerify/index.jsx b/ui/js/component/userEmailVerify/index.jsx index dd02f136c..090b41400 100644 --- a/ui/js/component/userEmailVerify/index.jsx +++ b/ui/js/component/userEmailVerify/index.jsx @@ -1,25 +1,21 @@ -import React from 'react' -import { - connect -} from 'react-redux' -import { - doUserEmailVerify -} from 'actions/user' +import React from "react"; +import { connect } from "react-redux"; +import { doUserEmailVerify } from "actions/user"; import { selectEmailVerifyIsPending, - selectEmailNewExistingEmail, + selectEmailToVerify, selectEmailVerifyErrorMessage, -} from 'selectors/user' -import UserEmailVerify from './view' +} from "selectors/user"; +import UserEmailVerify from "./view"; -const select = (state) => ({ +const select = state => ({ isPending: selectEmailVerifyIsPending(state), - email: selectEmailNewExistingEmail, + email: selectEmailToVerify, errorMessage: selectEmailVerifyErrorMessage(state), -}) +}); -const perform = (dispatch) => ({ - verifyUserEmail: (email, code) => dispatch(doUserEmailVerify(email, code)) -}) +const perform = dispatch => ({ + verifyUserEmail: code => dispatch(doUserEmailVerify(code)), +}); -export default connect(select, perform)(UserEmailVerify) +export default connect(select, perform)(UserEmailVerify); diff --git a/ui/js/component/welcomeModal/index.jsx b/ui/js/component/welcomeModal/index.jsx new file mode 100644 index 000000000..6a6af4f64 --- /dev/null +++ b/ui/js/component/welcomeModal/index.jsx @@ -0,0 +1,22 @@ +import React from "react"; +import { connect } from "react-redux"; +import { doCloseModal } from "actions/app"; +import { selectUserIsRewardApproved } from "selectors/user"; +import { makeSelectHasClaimedReward } from "selectors/rewards"; +import WelcomeModal from "./view"; + +const select = (state, props) => { + const selectHasReward = makeSelectHasClaimedReward(); + + return { + hasReward: selectHasReward(state, { reward_type: "new_user" }), + isRewardApproved: selectUserIsRewardApproved(state), + rewardAmount: 5, + }; +}; + +const perform = dispatch => ({ + closeModal: () => dispatch(doCloseModal()), +}); + +export default connect(select, perform)(WelcomeModal); diff --git a/ui/js/component/welcomeModal/view.jsx b/ui/js/component/welcomeModal/view.jsx new file mode 100644 index 000000000..015df4701 --- /dev/null +++ b/ui/js/component/welcomeModal/view.jsx @@ -0,0 +1,79 @@ +import React from "react"; +import { Modal } from "component/modal"; +import { CreditAmount } from "component/common"; +import Link from "component/link"; +import RewardLink from "component/rewardLink"; + +class WelcomeModal extends React.Component { + render() { + const { + closeModal, + hasReward, + isRewardApproved, + rewardAmount, + } = this.props; + + return !hasReward + ? +
+

Welcome to LBRY.

+

+ Using LBRY is like dating a centaur. Totally normal up top, and + {" "}way different underneath. +

+

Up top, LBRY is similar to popular media sites.

+

+ Below, LBRY is controlled by users -- you -- via blockchain and + decentralization. +

+

+ Thank you for making content freedom possible! + {" "}{isRewardApproved ? __("Here's a nickel, kid.") : ""} +

+
+ {isRewardApproved + ? + : } +
+
+
+ : +
+

About Your Reward

+

+ You earned a reward of + {" "} LBRY + credits, or LBC. +

+

+ This reward will show in your Wallet momentarily, probably while + you are reading this message. +

+

+ LBC is used to compensate creators, to publish, and to have say in + how the network works. +

+

+ No need to understand it all just yet! Try watching or downloading + something next. +

+

+ Finally, know that LBRY is an early beta and that it earns the + name. +

+
+
; + } +} + +export default WelcomeModal; diff --git a/ui/js/constants/modal_types.js b/ui/js/constants/modal_types.js new file mode 100644 index 000000000..b34bb9afb --- /dev/null +++ b/ui/js/constants/modal_types.js @@ -0,0 +1 @@ +export const WELCOME = "welcome"; diff --git a/ui/js/lbryio.js b/ui/js/lbryio.js index 839af4cb2..1ca8f76f1 100644 --- a/ui/js/lbryio.js +++ b/ui/js/lbryio.js @@ -1,134 +1,147 @@ -import { getSession, setSession, setLocal } from './utils.js'; -import lbry from './lbry.js'; +import { getSession, setSession, setLocal } from "./utils.js"; +import lbry from "./lbry.js"; -const querystring = require('querystring'); +const querystring = require("querystring"); const lbryio = { - _accessToken: getSession('accessToken'), - _authenticationPromise: null, - _user: null, - enabled: true + _accessToken: getSession("accessToken"), + _authenticationPromise: null, + _user: null, + enabled: true, }; const CONNECTION_STRING = process.env.LBRY_APP_API_URL - ? process.env.LBRY_APP_API_URL.replace(/\/*$/, '/') // exactly one slash at the end - : 'https://api.lbry.io/'; + ? process.env.LBRY_APP_API_URL.replace(/\/*$/, "/") // exactly one slash at the end + : "https://api.lbry.io/"; const EXCHANGE_RATE_TIMEOUT = 20 * 60 * 1000; lbryio._exchangePromise = null; lbryio._exchangeLastFetched = null; lbryio.getExchangeRates = function() { - if ( - !lbryio._exchangeLastFetched || - Date.now() - lbryio._exchangeLastFetched > EXCHANGE_RATE_TIMEOUT - ) { - lbryio._exchangePromise = new Promise((resolve, reject) => { - lbryio - .call('lbc', 'exchange_rate', {}, 'get', true) - .then(({ lbc_usd, lbc_btc, btc_usd }) => { - const rates = { lbc_usd, lbc_btc, btc_usd }; - resolve(rates); - }) - .catch(reject); - }); - lbryio._exchangeLastFetched = Date.now(); - } - return lbryio._exchangePromise; + if ( + !lbryio._exchangeLastFetched || + Date.now() - lbryio._exchangeLastFetched > EXCHANGE_RATE_TIMEOUT + ) { + lbryio._exchangePromise = new Promise((resolve, reject) => { + lbryio + .call("lbc", "exchange_rate", {}, "get", true) + .then(({ lbc_usd, lbc_btc, btc_usd }) => { + const rates = { lbc_usd, lbc_btc, btc_usd }; + resolve(rates); + }) + .catch(reject); + }); + lbryio._exchangeLastFetched = Date.now(); + } + return lbryio._exchangePromise; }; lbryio.call = function( - resource, - action, - params = {}, - method = 'get', - evenIfDisabled = false + resource, + action, + params = {}, + method = "get", + evenIfDisabled = false ) { - // evenIfDisabled is just for development, when we may have some calls working and some not - return new Promise((resolve, reject) => { - if ( - !lbryio.enabled && - !evenIfDisabled && - (resource != 'discover' || action != 'list') - ) { - console.log(__('Internal API disabled')); - reject(new Error(__('LBRY internal API is disabled'))); - return; - } + // evenIfDisabled is just for development, when we may have some calls working and some not + return new Promise((resolve, reject) => { + if ( + !lbryio.enabled && + !evenIfDisabled && + (resource != "discover" || action != "list") + ) { + console.log(__("Internal API disabled")); + reject(new Error(__("LBRY internal API is disabled"))); + return; + } - const xhr = new XMLHttpRequest(); + const xhr = new XMLHttpRequest(); - xhr.addEventListener('error', function(event) { - reject( - new Error(__('Something went wrong making an internal API call.')) - ); - }); + xhr.addEventListener("error", function(event) { + reject( + new Error(__("Something went wrong making an internal API call.")) + ); + }); - xhr.addEventListener('timeout', function() { - reject(new Error(__('XMLHttpRequest connection timed out'))); - }); + xhr.addEventListener("timeout", function() { + reject(new Error(__("XMLHttpRequest connection timed out"))); + }); - xhr.addEventListener('load', function() { - const response = JSON.parse(xhr.responseText); + xhr.addEventListener("load", function() { + const response = JSON.parse(xhr.responseText); - if (!response.success) { - if (reject) { - let error = new Error(response.error); - error.xhr = xhr; - reject(error); - } else { - document.dispatchEvent( - new CustomEvent('unhandledError', { - detail: { - connectionString: connectionString, - method: action, - params: params, - message: response.error.message, - ...(response.error.data ? { data: response.error.data } : {}) - } - }) - ); - } - } else { - resolve(response.data); - } - }); + if (!response.success) { + if (reject) { + let error = new Error(response.error); + error.xhr = xhr; + reject(error); + } else { + document.dispatchEvent( + new CustomEvent("unhandledError", { + detail: { + connectionString: connectionString, + method: action, + params: params, + message: response.error.message, + ...(response.error.data ? { data: response.error.data } : {}), + }, + }) + ); + } + } else { + resolve(response.data); + } + }); - // For social media auth: - //const accessToken = localStorage.getItem('accessToken'); - //const fullParams = {...params, ... accessToken ? {access_token: accessToken} : {}}; + // For social media auth: + //const accessToken = localStorage.getItem('accessToken'); + //const fullParams = {...params, ... accessToken ? {access_token: accessToken} : {}}; - // Temp app ID based auth: - const fullParams = { app_id: lbryio.getAccessToken(), ...params }; + // Temp app ID based auth: + const fullParams = { app_id: lbryio.getAccessToken(), ...params }; - if (method == 'get') { - xhr.open( - 'get', - CONNECTION_STRING + - resource + - '/' + - action + - '?' + - querystring.stringify(fullParams), - true - ); - xhr.send(); - } else if (method == 'post') { - xhr.open('post', CONNECTION_STRING + resource + '/' + action, true); - xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); - xhr.send(querystring.stringify(fullParams)); - } else { - reject(new Error(__('Invalid method'))); - } - }); + if (method == "get") { + xhr.open( + "get", + CONNECTION_STRING + + resource + + "/" + + action + + "?" + + querystring.stringify(fullParams), + true + ); + xhr.send(); + } else if (method == "post") { + xhr.open("post", CONNECTION_STRING + resource + "/" + action, true); + xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); + xhr.send(querystring.stringify(fullParams)); + } else { + reject(new Error(__("Invalid method"))); + } + }); }; lbryio.getAccessToken = () => { - const token = getSession('accessToken'); - return token ? token.toString().trim() : token; + const token = getSession("accessToken"); + return token ? token.toString().trim() : token; }; lbryio.setAccessToken = token => { - setSession('accessToken', token ? token.toString().trim() : token); + setSession("accessToken", token ? token.toString().trim() : token); +}; + +lbryio.setCurrentUser = (resolve, reject) => { + lbryio + .call("user", "me") + .then(data => { + lbryio.user = data; + resolve(data); + }) + .catch(function(err) { + lbryio.setAccessToken(null); + reject(err); + }); }; lbryio.authenticate = function() { @@ -136,53 +149,57 @@ lbryio.authenticate = function() { return new Promise((resolve, reject) => { resolve({ id: 1, - has_verified_email: true - }) - }) + language: "en", + has_email: true, + has_verified_email: true, + is_reward_approved: false, + is_reward_eligible: false, + }); + }); } if (lbryio._authenticationPromise === null) { lbryio._authenticationPromise = new Promise((resolve, reject) => { - lbry.status().then((response) => { + lbry + .status() + .then(response => { + let installation_id = response.installation_id; - let installation_id = response.installation_id.substring(0, response.installation_id.length - 2) + "E"; - - function setCurrentUser() { - lbryio.call('user', 'me').then((data) => { - lbryio.user = data - resolve(data) - }).catch(function(err) { - lbryio.setAccessToken(null); - reject(err); - }) - } - - if (!lbryio.getAccessToken()) { - lbryio.call('user', 'new', { - language: 'en', - app_id: installation_id, - }, 'post').then(function(responseData) { - if (!responseData.id) { - reject(new Error("Received invalid authentication response.")); - } - lbryio.setAccessToken(installation_id) - setLocal('auth_bypassed', false) - setCurrentUser() - }).catch(function(error) { - /* - until we have better error code format, assume all errors are duplicate application id - if we're wrong, this will be caught by later attempts to make a valid call - */ - lbryio.setAccessToken(installation_id); - setCurrentUser(); - }); - } else { - setCurrentUser(); - } - }) - .catch(reject); - }); - } - return lbryio._authenticationPromise; + if (!lbryio.getAccessToken()) { + lbryio + .call( + "user", + "new", + { + language: "en", + app_id: installation_id, + }, + "post" + ) + .then(function(responseData) { + if (!responseData.id) { + reject( + new Error("Received invalid authentication response.") + ); + } + lbryio.setAccessToken(installation_id); + lbryio.setCurrentUser(resolve, reject); + }) + .catch(function(error) { + /* + until we have better error code format, assume all errors are duplicate application id + if we're wrong, this will be caught by later attempts to make a valid call + */ + lbryio.setAccessToken(installation_id); + lbryio.setCurrentUser(resolve, reject); + }); + } else { + lbryio.setCurrentUser(resolve, reject); + } + }) + .catch(reject); + }); + } + return lbryio._authenticationPromise; }; export default lbryio; diff --git a/ui/js/main.js b/ui/js/main.js index 178979e6b..c8b9e76fc 100644 --- a/ui/js/main.js +++ b/ui/js/main.js @@ -1,86 +1,85 @@ -import React from 'react'; -import ReactDOM from 'react-dom'; -import lbry from './lbry.js'; -import lbryio from './lbryio.js'; -import App from 'component/app/index.js'; -import SnackBar from 'component/snackBar'; -import { Provider } from 'react-redux'; -import store from 'store.js'; -import SplashScreen from 'component/splash.js'; -import AuthOverlay from 'component/authOverlay'; -import { doChangePath, doNavigate, doDaemonReady } from 'actions/app'; -import { toQueryString } from 'util/query_params'; +import React from "react"; +import ReactDOM from "react-dom"; +import lbry from "./lbry.js"; +import App from "component/app/index.js"; +import SnackBar from "component/snackBar"; +import { Provider } from "react-redux"; +import store from "store.js"; +import SplashScreen from "component/splash.js"; +import AuthOverlay from "component/authOverlay"; +import { doChangePath, doNavigate, doDaemonReady } from "actions/app"; +import { toQueryString } from "util/query_params"; -const { remote, ipcRenderer, shell } = require('electron'); -const contextMenu = remote.require('./menu/context-menu'); -const app = require('./app'); +const { remote, ipcRenderer, shell } = require("electron"); +const contextMenu = remote.require("./menu/context-menu"); +const app = require("./app"); lbry.showMenuIfNeeded(); -window.addEventListener('contextmenu', event => { - contextMenu.showContextMenu( - remote.getCurrentWindow(), - event.x, - event.y, - lbry.getClientSetting('showDeveloperMenu') - ); - event.preventDefault(); +window.addEventListener("contextmenu", event => { + contextMenu.showContextMenu( + remote.getCurrentWindow(), + event.x, + event.y, + lbry.getClientSetting("showDeveloperMenu") + ); + event.preventDefault(); }); -window.addEventListener('popstate', (event, param) => { - const params = event.state; - const pathParts = document.location.pathname.split('/'); - const route = '/' + pathParts[pathParts.length - 1]; - const queryString = toQueryString(params); +window.addEventListener("popstate", (event, param) => { + const params = event.state; + const pathParts = document.location.pathname.split("/"); + const route = "/" + pathParts[pathParts.length - 1]; + const queryString = toQueryString(params); - let action; - if (route.match(/html$/)) { - action = doChangePath('/discover'); - } else { - action = doChangePath(`${route}?${queryString}`); - } + let action; + if (route.match(/html$/)) { + action = doChangePath("/discover"); + } else { + action = doChangePath(`${route}?${queryString}`); + } - app.store.dispatch(action); + app.store.dispatch(action); }); -ipcRenderer.on('open-uri-requested', (event, uri) => { - if (uri && uri.startsWith('lbry://')) { - app.store.dispatch(doNavigate('/show', { uri })); - } +ipcRenderer.on("open-uri-requested", (event, uri) => { + if (uri && uri.startsWith("lbry://")) { + app.store.dispatch(doNavigate("/show", { uri })); + } }); -document.addEventListener('click', event => { - var target = event.target; - while (target && target !== document) { - if (target.matches('a[href^="http"]')) { - event.preventDefault(); - shell.openExternal(target.href); - return; - } - target = target.parentNode; - } +document.addEventListener("click", event => { + var target = event.target; + while (target && target !== document) { + if (target.matches('a[href^="http"]')) { + event.preventDefault(); + shell.openExternal(target.href); + return; + } + target = target.parentNode; + } }); const initialState = app.store.getState(); var init = function() { - function onDaemonReady() { - window.sessionStorage.setItem('loaded', 'y'); //once we've made it here once per session, we don't need to show splash again - app.store.dispatch(doDaemonReady()) + function onDaemonReady() { + window.sessionStorage.setItem("loaded", "y"); //once we've made it here once per session, we don't need to show splash again + app.store.dispatch(doDaemonReady()); - ReactDOM.render( - -
{lbryio.enabled ? : ''}
-
, - canvas - ); - } + ReactDOM.render( + +
+
, + canvas + ); + } - if (window.sessionStorage.getItem('loaded') == 'y') { - onDaemonReady(); - } else { - ReactDOM.render(, canvas); - } + if (window.sessionStorage.getItem("loaded") == "y") { + onDaemonReady(); + } else { + ReactDOM.render(, canvas); + } }; init(); diff --git a/ui/js/page/auth/index.jsx b/ui/js/page/auth/index.jsx deleted file mode 100644 index 91fdb0012..000000000 --- a/ui/js/page/auth/index.jsx +++ /dev/null @@ -1,25 +0,0 @@ -import React from 'react' -import { - connect -} from 'react-redux' -import { - doUserEmailDecline -} from 'actions/user' -import { - selectAuthenticationIsPending, - selectEmailNewDeclined, - selectUser, -} from 'selectors/user' -import AuthPage from './view' - -const select = (state) => ({ - isPending: selectAuthenticationIsPending(state), - isEmailDeclined: selectEmailNewDeclined(state), - user: selectUser(state), -}) - -const perform = (dispatch) => ({ - userEmailDecline: () => dispatch(doUserEmailDecline()) -}) - -export default connect(select, perform)(AuthPage) diff --git a/ui/js/page/auth/view.jsx b/ui/js/page/auth/view.jsx deleted file mode 100644 index c27c683f2..000000000 --- a/ui/js/page/auth/view.jsx +++ /dev/null @@ -1,19 +0,0 @@ -import React from 'react' -import Auth from 'component/auth' - -export class AuthPage extends React.Component { - render() { - return
-
-
-

Early Access Verification

-
-
- -
-
-
- } -} - -export default AuthPage \ No newline at end of file diff --git a/ui/js/page/rewards.js b/ui/js/page/rewards.js deleted file mode 100644 index 31017ccdc..000000000 --- a/ui/js/page/rewards.js +++ /dev/null @@ -1,100 +0,0 @@ -import React from "react"; -import lbryio from "lbryio"; -import { CreditAmount, Icon } from "component/common.js"; -import SubHeader from "component/subHeader"; -import { RewardLink } from "component/reward-link"; - -export class RewardTile extends React.Component { - static propTypes = { - type: React.PropTypes.string.isRequired, - title: React.PropTypes.string.isRequired, - description: React.PropTypes.string.isRequired, - claimed: React.PropTypes.bool.isRequired, - value: React.PropTypes.number.isRequired, - onRewardClaim: React.PropTypes.func, - }; - - render() { - return ( -
-
-
- -

{this.props.title}

-
-
- {this.props.claimed - ? {__("Reward claimed.")} - : } -
-
{this.props.description}
-
-
- ); - } -} - -export class RewardsPage extends React.Component { - constructor(props) { - super(props); - - this.state = { - userRewards: null, - failed: null, - }; - } - - componentWillMount() { - this.loadRewards(); - } - - loadRewards() { - lbryio.call("reward", "list", {}).then( - userRewards => { - this.setState({ - userRewards: userRewards, - }); - }, - () => { - this.setState({ failed: true }); - } - ); - } - - render() { - return ( -
- -
- {!this.state.userRewards - ? this.state.failed - ?
{__("Failed to load rewards.")}
- : "" - : this.state.userRewards.map( - ({ - reward_type, - reward_title, - reward_description, - transaction_id, - reward_amount, - }) => { - return ( - - ); - } - )} -
-
- ); - } -} - -export default RewardsPage; diff --git a/ui/js/page/rewards/index.js b/ui/js/page/rewards/index.js index a3e4b102b..51da2f8df 100644 --- a/ui/js/page/rewards/index.js +++ b/ui/js/page/rewards/index.js @@ -1,28 +1,25 @@ -import React from 'react' -import { - connect, -} from 'react-redux' -import { - doNavigate -} from 'actions/app' +import React from "react"; +import { connect } from "react-redux"; +import { doNavigate } from "actions/app"; import { selectFetchingRewards, selectIsRewardEligible, selectRewards, -} from 'selectors/rewards' +} from "selectors/rewards"; import { - selectUserIsRewardEligible -} from 'selectors/user' -import RewardsPage from './view' + selectUserIsRewardEligible, + selectUserHasEmail, + selectUserIsRewardApproved, + selectUserIsVerificationCandidate, +} from "selectors/user"; +import RewardsPage from "./view"; -const select = (state) => ({ +const select = state => ({ fetching: selectFetchingRewards(state), rewards: selectRewards(state), - isEligible: selectUserIsRewardEligible(state) -}) + hasEmail: selectUserHasEmail(state), + isEligible: selectUserIsRewardEligible(state), + isVerificationCandidate: selectUserIsVerificationCandidate(state), +}); -const perform = (dispatch) => ({ - navigateToAuth: () => dispatch(doNavigate('/account-verification')) -}) - -export default connect(select, perform)(RewardsPage) +export default connect(select, null)(RewardsPage); diff --git a/ui/js/page/rewards/view.jsx b/ui/js/page/rewards/view.jsx index f02fbb977..a40afefff 100644 --- a/ui/js/page/rewards/view.jsx +++ b/ui/js/page/rewards/view.jsx @@ -1,16 +1,15 @@ -import React from 'react'; -import lbryio from 'lbryio'; -import {BusyMessage, CreditAmount, Icon} from 'component/common'; -import SubHeader from 'component/subHeader' -import Link from 'component/link' -import RewardLink from 'component/rewardLink'; +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) => { - const { - reward, - } = props +const RewardTile = props => { + const { reward } = props; - const claimed = !!reward.transaction_id + const claimed = !!reward.transaction_id; return (
@@ -22,43 +21,74 @@ const RewardTile = (props) => {
{claimed ? Reward claimed. - : } + : }
{reward.reward_description}
- ) -} + ); +}; -const RewardsPage = (props) => { +const RewardsPage = props => { const { fetching, isEligible, - navigateToAuth, + isVerificationCandidate, + hasEmail, rewards, - } = props + } = props; - let content + console.log(props); - if (!isEligible) { - content =
- You are not eligible to claim rewards. { ' ' } - . -
+ let content, + isCard = false; + + if (!hasEmail || isVerificationCandidate) { + content = ( +
+

+ {__( + "Additional information is required to be eligible for the rewards program." + )} +

+ +
+ ); + isCard = true; + } else if (!isEligible) { + isCard = true; + content = ( +
+

{__("You are not eligible to claim rewards.")}

+

+ To become eligible, email + {" "} with a + link to a public social media profile. +

+
+ ); } else if (fetching) { - content = + content = ; } else if (rewards.length > 0) { - content = rewards.map(reward => ) + content = rewards.map(reward => + + ); } else { - content =
Failed to load rewards.
+ content =
{__("Failed to load rewards.")}
; } return (
- {content} + {isCard + ?
+
+ {content} +
+
+ : content}
- ) -} + ); +}; export default RewardsPage; diff --git a/ui/js/page/settings/view.jsx b/ui/js/page/settings/view.jsx index 82d3c7c60..92d3ab399 100644 --- a/ui/js/page/settings/view.jsx +++ b/ui/js/page/settings/view.jsx @@ -229,25 +229,32 @@ class SettingsPage extends React.Component { - {/*}

{__("Language")}

- { this.onLanguageChange('en') }} - defaultChecked={this.state.language=='en'} /> + { + this.onLanguageChange("en"); + }} + defaultChecked={this.state.language == "en"} + />
- { this.onLanguageChange('rs') }} - defaultChecked={this.state.language=='rs'} /> + { + this.onLanguageChange("rs"); + }} + defaultChecked={this.state.language == "rs"} + />
*/} diff --git a/ui/js/reducers/user.js b/ui/js/reducers/user.js index 28dc981f2..353b9b193 100644 --- a/ui/js/reducers/user.js +++ b/ui/js/reducers/user.js @@ -1,91 +1,98 @@ -import * as types from 'constants/action_types' -import { - getLocal -} from 'utils' +import * as types from "constants/action_types"; +import { getLocal } from "utils"; -const reducers = {} +const reducers = {}; const defaultState = { authenticationIsPending: false, emailNewIsPending: false, - emailNewErrorMessage: '', - emailNewDeclined: getLocal('user_email_declined', false), - user: undefined -} + emailNewErrorMessage: "", + emailNewDeclined: getLocal("user_email_declined", false), + emailToVerify: "", + user: undefined, +}; reducers[types.AUTHENTICATION_STARTED] = function(state, action) { return Object.assign({}, state, { - authenticationIsPending: true - }) -} + authenticationIsPending: true, + }); +}; reducers[types.AUTHENTICATION_SUCCESS] = function(state, action) { return Object.assign({}, state, { authenticationIsPending: false, user: action.data.user, - }) -} + }); +}; reducers[types.AUTHENTICATION_FAILURE] = function(state, action) { return Object.assign({}, state, { authenticationIsPending: false, user: null, - }) -} + }); +}; reducers[types.USER_EMAIL_DECLINE] = function(state, action) { return Object.assign({}, state, { - emailNewDeclined: true - }) -} + emailNewDeclined: true, + }); +}; reducers[types.USER_EMAIL_NEW_STARTED] = function(state, action) { return Object.assign({}, state, { emailNewIsPending: true, - emailNewErrorMessage: '' - }) -} + emailNewErrorMessage: "", + }); +}; reducers[types.USER_EMAIL_NEW_SUCCESS] = function(state, action) { + let user = Object.assign({}, state.user); + user.has_email = true; return Object.assign({}, state, { + emailToVerify: action.data.email, emailNewIsPending: false, - }) -} + user: user, + }); +}; reducers[types.USER_EMAIL_NEW_EXISTS] = function(state, action) { + let user = Object.assign({}, state.user); return Object.assign({}, state, { - emailNewExistingEmail: action.data.email, + emailToVerify: action.data.email, emailNewIsPending: false, - }) -} + }); +}; reducers[types.USER_EMAIL_NEW_FAILURE] = function(state, action) { return Object.assign({}, state, { emailNewIsPending: false, - emailNewErrorMessage: action.data.error - }) -} + emailNewErrorMessage: action.data.error, + }); +}; reducers[types.USER_EMAIL_VERIFY_STARTED] = function(state, action) { return Object.assign({}, state, { emailVerifyIsPending: true, - emailVerifyErrorMessage: '' - }) -} + emailVerifyErrorMessage: "", + }); +}; reducers[types.USER_EMAIL_VERIFY_SUCCESS] = function(state, action) { + let user = Object.assign({}, state.user); + user.has_email = true; return Object.assign({}, state, { + emailToVerify: "", emailVerifyIsPending: false, - }) -} + user: user, + }); +}; reducers[types.USER_EMAIL_VERIFY_FAILURE] = function(state, action) { return Object.assign({}, state, { emailVerifyIsPending: false, - emailVerifyErrorMessage: action.data.error - }) -} - + emailVerifyErrorMessage: action.data.error, + }); +}; export default function reducer(state = defaultState, action) { const handler = reducers[action.type]; diff --git a/ui/js/selectors/app.js b/ui/js/selectors/app.js index d704709ab..c03bb28d3 100644 --- a/ui/js/selectors/app.js +++ b/ui/js/selectors/app.js @@ -54,8 +54,6 @@ export const selectPageTitle = createSelector( return __("Publishes"); case "discover": return __("Home"); - case 'account-verification': - return __('Early Access Verification') default: return ""; } diff --git a/ui/js/selectors/rewards.js b/ui/js/selectors/rewards.js index 828be4fe0..d9e17f927 100644 --- a/ui/js/selectors/rewards.js +++ b/ui/js/selectors/rewards.js @@ -5,88 +5,75 @@ const _selectState = state => state.rewards || {}; export const selectRewardsByType = createSelector( _selectState, - (state) => state.byRewardType || {} -) + state => state.byRewardType || {} +); export const selectRewards = createSelector( selectRewardsByType, - (byType) => Object.values(byType) || [] -) + byType => Object.values(byType) || [] +); export const selectIsRewardEligible = createSelector( selectUser, - (user) => user.can_claim_rewards -) + user => user.can_claim_rewards +); -export const selectClaimedRewards = createSelector( - selectRewards, - (rewards) => rewards.filter(reward => reward.transaction_id !== "") -) +export const selectClaimedRewards = createSelector(selectRewards, rewards => + rewards.filter(reward => reward.transaction_id !== "") +); export const selectClaimedRewardsByType = createSelector( selectClaimedRewards, - (claimedRewards) => { - const byType = {} - claimedRewards.forEach(reward => byType[reward.reward_type] = reward) - return byType + claimedRewards => { + const byType = {}; + claimedRewards.forEach(reward => (byType[reward.reward_type] = reward)); + return byType; } -) +); export const selectFetchingRewards = createSelector( _selectState, - (state) => !!state.fetching -) + state => !!state.fetching +); export const selectHasClaimedReward = (state, props) => { - return !!selectClaimedRewardsByType[props.reward.reward_type] -} + return !!selectClaimedRewardsByType[props.reward_type]; +}; export const makeSelectHasClaimedReward = () => { - return createSelector( - selectHasClaimedReward, - (claimed) => claimed - ) -} + return createSelector(selectHasClaimedReward, claimed => claimed); +}; export const selectClaimsPendingByType = createSelector( _selectState, - (state) => state.claimPendingByType -) + state => state.claimPendingByType +); const selectIsClaimRewardPending = (state, props) => { - return selectClaimsPendingByType(state, props)[props.reward.reward_type] -} + return selectClaimsPendingByType(state, props)[props.reward_type]; +}; export const makeSelectIsRewardClaimPending = () => { - return createSelector( - selectIsClaimRewardPending, - (isClaiming) => isClaiming - ) -} + return createSelector(selectIsClaimRewardPending, isClaiming => isClaiming); +}; export const selectClaimErrorsByType = createSelector( _selectState, - (state) => state.claimErrorsByType -) + state => state.claimErrorsByType +); const selectClaimRewardError = (state, props) => { - return selectClaimErrorsByType(state, props)[props.reward.reward_type] -} + return selectClaimErrorsByType(state, props)[props.reward_type]; +}; export const makeSelectClaimRewardError = () => { - return createSelector( - selectClaimRewardError, - (errorMessage) => errorMessage - ) -} + return createSelector(selectClaimRewardError, errorMessage => errorMessage); +}; const selectRewardByType = (state, props) => { - return selectRewardsByType(state)[props.reward_type] -} + return selectRewardsByType(state)[props.reward_type]; +}; export const makeSelectRewardByType = () => { - return createSelector( - selectRewardByType, - (reward) => reward - ) -} + return createSelector(selectRewardByType, reward => reward); +}; diff --git a/ui/js/selectors/search.js b/ui/js/selectors/search.js index 2d1e9c444..9660cdcb5 100644 --- a/ui/js/selectors/search.js +++ b/ui/js/selectors/search.js @@ -68,7 +68,5 @@ export const selectWunderBarIcon = createSelector(selectCurrentPage, page => { return "icon-code"; case "discover": return "icon-home"; - case 'account-verification': - return 'icon-lock' } }); diff --git a/ui/js/selectors/user.js b/ui/js/selectors/user.js index 2b182ba2f..015ebae62 100644 --- a/ui/js/selectors/user.js +++ b/ui/js/selectors/user.js @@ -1,48 +1,77 @@ -import { createSelector } from 'reselect' +import { createSelector } from "reselect"; -export const _selectState = state => state.user || {} +export const _selectState = state => state.user || {}; export const selectAuthenticationIsPending = createSelector( _selectState, - (state) => state.authenticationIsPending -) + state => state.authenticationIsPending +); export const selectUser = createSelector( _selectState, - (state) => state.user -) + state => state.user || {} +); + +export const selectEmailToVerify = createSelector( + _selectState, + state => state.emailToVerify +); + +export const selectUserHasEmail = createSelector( + selectUser, + selectEmailToVerify, + (user, email) => user.has_email || email +); export const selectUserIsRewardEligible = createSelector( - _selectState, - (state) => state.user.can_claim_rewards -) + selectUser, + user => user.is_reward_eligible +); + +export const selectUserIsRewardApproved = createSelector( + selectUser, + user => user.is_reward_approved +); export const selectEmailNewIsPending = createSelector( _selectState, - (state) => state.emailNewIsPending -) + state => state.emailNewIsPending +); export const selectEmailNewErrorMessage = createSelector( _selectState, - (state) => state.emailNewErrorMessage -) + state => state.emailNewErrorMessage +); export const selectEmailNewDeclined = createSelector( _selectState, - (state) => state.emailNewDeclined -) - -export const selectEmailNewExistingEmail = createSelector( - _selectState, - (state) => state.emailNewExistingEmail -) + state => state.emailNewDeclined +); export const selectEmailVerifyIsPending = createSelector( _selectState, - (state) => state.emailVerifyIsPending -) + state => state.emailVerifyIsPending +); export const selectEmailVerifyErrorMessage = createSelector( _selectState, - (state) => state.emailVerifyErrorMessage -) + state => state.emailVerifyErrorMessage +); + +export const selectUserIsVerificationCandidate = createSelector( + selectUserIsRewardEligible, + selectUserIsRewardApproved, + selectEmailToVerify, + selectUser, + (isEligible, isApproved, emailToVerify, user) => + (isEligible && !isApproved) || (emailToVerify && !user.has_email) +); + +export const selectUserIsAuthRequested = createSelector( + selectEmailNewDeclined, + selectAuthenticationIsPending, + selectUserIsVerificationCandidate, + selectUserHasEmail, + (isEmailDeclined, isPending, isVerificationCandidate, hasEmail) => + !isEmailDeclined && (isPending || !hasEmail || isVerificationCandidate) +); diff --git a/ui/scss/component/_card.scss b/ui/scss/component/_card.scss index 2e325d827..4dd88a91e 100644 --- a/ui/scss/component/_card.scss +++ b/ui/scss/component/_card.scss @@ -25,7 +25,7 @@ $padding-card-horizontal: $spacing-vertical * 2/3; } .card__title-primary { padding: 0 $padding-card-horizontal; - margin-top: $spacing-vertical; + margin-top: $spacing-vertical * 2/3; } .card__title-identity { padding: 0 $padding-card-horizontal; From 09ecae7e0dc8ad8c2611e1ffdb518be98167bd88 Mon Sep 17 00:00:00 2001 From: Jeremy Kauffman Date: Thu, 8 Jun 2017 17:15:34 -0400 Subject: [PATCH 09/14] reviewable --- ui/js/actions/content.js | 5 +- ui/js/actions/rewards.js | 106 +++++-- ui/js/actions/user.js | 26 +- ui/js/component/authOverlay/index.jsx | 2 + ui/js/component/authOverlay/view.jsx | 19 +- ui/js/component/form.js | 14 +- ui/js/component/reward-link.js | 109 ------- ui/js/component/rewardLink/index.js | 4 +- ui/js/component/userEmailNew/view.jsx | 56 ++-- ui/js/component/userEmailVerify/index.jsx | 2 +- ui/js/component/userEmailVerify/view.jsx | 63 ++-- ui/js/component/welcomeModal/index.jsx | 14 +- ui/js/component/welcomeModal/view.jsx | 17 +- ui/js/constants/action_types.js | 37 +-- ui/js/lbryio.js | 17 +- ui/js/main.js | 5 +- ui/js/page/fileListPublished/index.js | 4 + ui/js/page/fileListPublished/view.jsx | 19 +- ui/js/page/publish/index.js | 4 + ui/js/page/publish/view.jsx | 4 +- ui/js/page/rewards/index.js | 7 +- ui/js/reducers/rewards.js | 97 +++--- ui/js/reducers/user.js | 26 ++ ui/js/rewards.js | 354 ++++++++++------------ ui/js/selectors/rewards.js | 18 +- ui/js/selectors/user.js | 13 +- ui/scss/_gui.scss | 5 + 27 files changed, 522 insertions(+), 525 deletions(-) delete mode 100644 ui/js/component/reward-link.js diff --git a/ui/js/actions/content.js b/ui/js/actions/content.js index f9fe0b02b..ca174b261 100644 --- a/ui/js/actions/content.js +++ b/ui/js/actions/content.js @@ -2,7 +2,6 @@ import * as types from "constants/action_types"; import lbry from "lbry"; import lbryio from "lbryio"; import lbryuri from "lbryuri"; -import rewards from "rewards"; import { selectBalance } from "selectors/wallet"; import { selectFileInfoForUri, @@ -10,8 +9,8 @@ import { } from "selectors/file_info"; import { selectResolvingUris } from "selectors/content"; import { selectCostInfoForUri } from "selectors/cost_info"; -import { selectClaimsByUri } from "selectors/claims"; import { doOpenModal } from "actions/app"; +import { doClaimEligiblePurchaseRewards } from "actions/rewards"; export function doResolveUri(uri) { return function(dispatch, getState) { @@ -171,7 +170,7 @@ export function doDownloadFile(uri, streamInfo) { }) .catch(() => {}); - rewards.claimEligiblePurchaseRewards(); + dispatch(doClaimEligiblePurchaseRewards()); }; } diff --git a/ui/js/actions/rewards.js b/ui/js/actions/rewards.js index ac368483d..14a2a8253 100644 --- a/ui/js/actions/rewards.js +++ b/ui/js/actions/rewards.js @@ -2,6 +2,7 @@ import * as types from "constants/action_types"; import lbry from "lbry"; import lbryio from "lbryio"; import rewards from "rewards"; +import { selectRewards, selectRewardsByType } from "selectors/rewards"; export function doRewardList() { return function(dispatch, getState) { @@ -11,56 +12,105 @@ export function doRewardList() { type: types.FETCH_REWARDS_STARTED, }); - lbryio.call('reward', 'list', {}).then((userRewards) => { - dispatch({ - type: types.FETCH_REWARDS_COMPLETED, - data: { userRewards } + lbryio + .call("reward", "list", {}) + .then(userRewards => { + dispatch({ + type: types.FETCH_REWARDS_COMPLETED, + data: { userRewards }, + }); }) - }).catch(() => { - dispatch({ - type: types.FETCH_REWARDS_COMPLETED, - data: { userRewards: [] } - }) - }); + .catch(() => { + dispatch({ + type: types.FETCH_REWARDS_COMPLETED, + data: { userRewards: [] }, + }); + }); }; } -export function doClaimReward(reward) { +export function doClaimRewardType(rewardType) { return function(dispatch, getState) { + const rewardsByType = selectRewardsByType(getState()), + reward = rewardsByType[rewardType]; + + if (reward) { + dispatch(doClaimReward(reward)); + } + }; +} + +export function doClaimReward(reward, saveError = false) { + return function(dispatch, getState) { + if (reward.transaction_id) { + //already claimed, do nothing + return; + } + dispatch({ type: types.CLAIM_REWARD_STARTED, - data: { reward } - }) + data: { reward }, + }); - const success = (a) => { - console.log(a) + const success = reward => { dispatch({ type: types.CLAIM_REWARD_SUCCESS, data: { - a - } - }) - } + reward, + }, + }); + }; - const failure = (error) => { + const failure = error => { dispatch({ type: types.CLAIM_REWARD_FAILURE, data: { reward, - error - } - }) + error: saveError ? error : null, + }, + }); + }; + + rewards.claimReward(reward.reward_type).then(success, failure); + }; +} + +export function doClaimEligiblePurchaseRewards() { + return function(dispatch, getState) { + if (!lbryio.enabled || !lbryio.getAccessToken()) { + return; } - rewards.claimReward(reward.reward_type).then(success, failure) - } + const rewardsByType = selectRewardsByType(getState()); + + let types = {}; + + types[rewards.TYPE_FIRST_STREAM] = false; + types[rewards.TYPE_FEATURED_DOWNLOAD] = false; + types[rewards.TYPE_MANY_DOWNLOADS] = false; + Object.values(rewardsByType).forEach(reward => { + if (types[reward.reward_type] === false && reward.transaction_id) { + types[reward.reward_type] = true; + } + }); + + let unclaimedType = Object.keys(types).find(type => { + return types[type] === false && type !== rewards.TYPE_FEATURED_DOWNLOAD; //handled below + }); + if (unclaimedType) { + dispatch(doClaimRewardType(unclaimedType)); + } + if (types[rewards.TYPE_FEATURED_DOWNLOAD] === false) { + dispatch(doClaimRewardType(rewards.TYPE_FEATURED_DOWNLOAD)); + } + }; } export function doClaimRewardClearError(reward) { return function(dispatch, getState) { dispatch({ type: types.CLAIM_REWARD_CLEAR_ERROR, - data: { reward } - }) - } + data: { reward }, + }); + }; } diff --git a/ui/js/actions/user.js b/ui/js/actions/user.js index 3fd4f8782..972e167eb 100644 --- a/ui/js/actions/user.js +++ b/ui/js/actions/user.js @@ -20,8 +20,6 @@ export function doAuthenticate() { dispatch(doRewardList()); //FIXME - where should this happen? }) .catch(error => { - console.log("auth error"); - console.log(error); dispatch({ type: types.AUTHENTICATION_FAILURE, data: { error }, @@ -30,6 +28,28 @@ export function doAuthenticate() { }; } +export function doUserFetch() { + return function(dispatch, getState) { + dispatch({ + type: types.USER_FETCH_STARTED, + }); + lbryio.setCurrentUser( + user => { + dispatch({ + type: types.USER_FETCH_SUCCESS, + data: { user }, + }); + }, + error => { + dispatch({ + type: types.USER_FETCH_FAILURE, + data: { error }, + }); + } + ); + }; +} + export function doUserEmailNew(email) { return function(dispatch, getState) { dispatch({ @@ -42,6 +62,7 @@ export function doUserEmailNew(email) { type: types.USER_EMAIL_NEW_SUCCESS, data: { email }, }); + dispatch(doUserFetch()); }, error => { if ( @@ -102,6 +123,7 @@ export function doUserEmailVerify(verificationToken) { type: types.USER_EMAIL_VERIFY_SUCCESS, data: { email }, }); + dispatch(doUserFetch()); } else { failure(new Error("Your email is still not verified.")); //shouldn't happen? } diff --git a/ui/js/component/authOverlay/index.jsx b/ui/js/component/authOverlay/index.jsx index d3982be73..ec7d7ee5a 100644 --- a/ui/js/component/authOverlay/index.jsx +++ b/ui/js/component/authOverlay/index.jsx @@ -5,11 +5,13 @@ import { doUserEmailDecline } from "actions/user"; import { doOpenModal } from "actions/app"; import { selectAuthenticationIsPending, + selectUserHasEmail, selectUserIsAuthRequested, } from "selectors/user"; import AuthOverlay from "./view"; const select = state => ({ + hasEmail: selectUserHasEmail(state), isPending: selectAuthenticationIsPending(state), isShowing: selectUserIsAuthRequested(state), }); diff --git a/ui/js/component/authOverlay/view.jsx b/ui/js/component/authOverlay/view.jsx index 0f1c95af4..fcb7e77d4 100644 --- a/ui/js/component/authOverlay/view.jsx +++ b/ui/js/component/authOverlay/view.jsx @@ -32,7 +32,7 @@ export class AuthOverlay extends React.Component { return null; } - const { isPending, isShowing } = this.props; + const { isPending, isShowing, hasEmail } = this.props; if (isShowing) { return ( @@ -46,15 +46,14 @@ export class AuthOverlay extends React.Component { {isPending ? "" :
- {this.state.showNoEmailConfirm - ?
-

+ {!hasEmail && this.state.showNoEmailConfirm + ?

+

{__( "If you continue without an email, you will be ineligible to earn free LBC rewards, as well as unable to receive security related communications." )}

{ this.onEmailSkipConfirm(); }} @@ -62,11 +61,15 @@ export class AuthOverlay extends React.Component { />
: { - this.onEmailSkipClick(); + hasEmail + ? this.onEmailSkipConfirm() + : this.onEmailSkipClick(); }} - label={__("Do I have to?")} + label={ + hasEmail ? __("Skip for now") : __("Do I have to?") + } />}
} diff --git a/ui/js/component/form.js b/ui/js/component/form.js index a9c1ab6bd..d0f192fec 100644 --- a/ui/js/component/form.js +++ b/ui/js/component/form.js @@ -178,9 +178,19 @@ export class FormRow extends React.Component { this._fieldRequiredText = __("This field is required"); - this.state = { + this.state = this.getStateFromProps(props); + } + + componentWillReceiveProps(nextProps) { + this.setState(this.getStateFromProps(nextProps)); + } + + getStateFromProps(props) { + return { isError: !!props.errorMessage, - errorMessage: typeof props.errorMessage === "string" ? props.errorMessage : '', + errorMessage: typeof props.errorMessage === "string" + ? props.errorMessage + : "", }; } diff --git a/ui/js/component/reward-link.js b/ui/js/component/reward-link.js deleted file mode 100644 index baf9df753..000000000 --- a/ui/js/component/reward-link.js +++ /dev/null @@ -1,109 +0,0 @@ -import React from "react"; -import lbry from "lbry"; -import { Icon } from "component/common"; -import Modal from "component/modal"; -import rewards from "rewards"; -import Link from "component/link"; - -export class RewardLink extends React.Component { - static propTypes = { - type: React.PropTypes.string.isRequired, - claimed: React.PropTypes.bool, - onRewardClaim: React.PropTypes.func, - onRewardFailure: React.PropTypes.func, - }; - - constructor(props) { - super(props); - - this.state = { - claimable: true, - pending: false, - errorMessage: null, - }; - } - - refreshClaimable() { - switch (this.props.type) { - case "new_user": - this.setState({ claimable: true }); - return; - - case "first_publish": - lbry.claim_list_mine().then(list => { - this.setState({ - claimable: list.length > 0, - }); - }); - return; - } - } - - componentWillMount() { - this.refreshClaimable(); - } - - claimReward() { - this.setState({ - pending: true, - }); - - rewards - .claimReward(this.props.type) - .then(reward => { - this.setState({ - pending: false, - errorMessage: null, - }); - if (this.props.onRewardClaim) { - this.props.onRewardClaim(reward); - } - }) - .catch(error => { - this.setState({ - errorMessage: error.message, - pending: false, - }); - }); - } - - clearError() { - if (this.props.onRewardFailure) { - this.props.onRewardFailure(); - } - this.setState({ - errorMessage: null, - }); - } - - render() { - return ( -
- {this.props.claimed - ? {__("Reward claimed.")} - : { - this.claimReward(); - }} - />} - {this.state.errorMessage - ? { - this.clearError(); - }} - > - {this.state.errorMessage} - - : ""} -
- ); - } -} diff --git a/ui/js/component/rewardLink/index.js b/ui/js/component/rewardLink/index.js index 631e65165..81b01488b 100644 --- a/ui/js/component/rewardLink/index.js +++ b/ui/js/component/rewardLink/index.js @@ -20,14 +20,14 @@ const makeSelect = () => { isClaimed: selectHasClaimedReward(state, props), errorMessage: selectError(state, props), isPending: selectIsPending(state, props), - reward: select, + reward: selectReward(state, props), }); return select; }; const perform = dispatch => ({ - claimReward: reward => dispatch(doClaimReward(reward)), + claimReward: reward => dispatch(doClaimReward(reward, true)), clearError: reward => dispatch(doClaimRewardClearError(reward)), navigate: path => dispatch(doNavigate(path)), }); diff --git a/ui/js/component/userEmailNew/view.jsx b/ui/js/component/userEmailNew/view.jsx index 502ceaa70..7e0f83b47 100644 --- a/ui/js/component/userEmailNew/view.jsx +++ b/ui/js/component/userEmailNew/view.jsx @@ -1,13 +1,13 @@ -import React from 'react'; -import Link from 'component/link'; -import {FormRow} from 'component/form.js'; +import React from "react"; +import Link from "component/link"; +import { FormRow } from "component/form.js"; class UserEmailNew extends React.Component { constructor(props) { super(props); this.state = { - email: '' + email: "", }; } @@ -19,25 +19,43 @@ class UserEmailNew extends React.Component { handleSubmit(event) { event.preventDefault(); - this.props.addUserEmail(this.state.email) + this.props.addUserEmail(this.state.email); } render() { - const { - errorMessage, - isPending - } = this.props + const { errorMessage, isPending } = this.props; - return
{ this.handleSubmit(event) }}> - { this.handleEmailChanged(event) }} /> -
- { this.handleSubmit(event) }} /> -
- + return ( +
{ + this.handleSubmit(event); + }} + > + { + this.handleEmailChanged(event); + }} + /> +
+ { + this.handleSubmit(event); + }} + /> +
+ + ); } } -export default UserEmailNew \ No newline at end of file +export default UserEmailNew; diff --git a/ui/js/component/userEmailVerify/index.jsx b/ui/js/component/userEmailVerify/index.jsx index 090b41400..f2ae56c86 100644 --- a/ui/js/component/userEmailVerify/index.jsx +++ b/ui/js/component/userEmailVerify/index.jsx @@ -10,7 +10,7 @@ import UserEmailVerify from "./view"; const select = state => ({ isPending: selectEmailVerifyIsPending(state), - email: selectEmailToVerify, + email: selectEmailToVerify(state), errorMessage: selectEmailVerifyErrorMessage(state), }); diff --git a/ui/js/component/userEmailVerify/view.jsx b/ui/js/component/userEmailVerify/view.jsx index 9d6160287..4b9272394 100644 --- a/ui/js/component/userEmailVerify/view.jsx +++ b/ui/js/component/userEmailVerify/view.jsx @@ -1,13 +1,13 @@ -import React from 'react'; -import Link from 'component/link'; -import {FormRow} from 'component/form.js'; +import React from "react"; +import Link from "component/link"; +import { FormRow } from "component/form.js"; class UserEmailVerify extends React.Component { constructor(props) { super(props); this.state = { - code: '', + code: "", }; } @@ -19,25 +19,50 @@ class UserEmailVerify extends React.Component { handleSubmit(event) { event.preventDefault(); - this.props.verifyUserEmail(this.state.code) + this.props.verifyUserEmail(this.state.code); } render() { - const { - errorMessage, - isPending - } = this.props + const { errorMessage, isPending } = this.props; - return
{ this.handleSubmit(event) }}> - { this.handleCodeChanged(event) }} - errorMessage={errorMessage} - helper="A verification code is required to participate in early access rewards."/> -
- { this.handleSubmit(event)}} /> -
- + return ( +
{ + this.handleSubmit(event); + }} + > + { + this.handleCodeChanged(event); + }} + errorMessage={errorMessage} + /> + {/* render help separately so it always shows */} +
+

+ Email if + you did not receive or are having trouble with your code. +

+
+
+ { + this.handleSubmit(event); + }} + /> +
+ + ); } } -export default UserEmailVerify \ No newline at end of file +export default UserEmailVerify; diff --git a/ui/js/component/welcomeModal/index.jsx b/ui/js/component/welcomeModal/index.jsx index 6a6af4f64..bbfc5b6a7 100644 --- a/ui/js/component/welcomeModal/index.jsx +++ b/ui/js/component/welcomeModal/index.jsx @@ -1,17 +1,23 @@ import React from "react"; +import rewards from "rewards"; import { connect } from "react-redux"; import { doCloseModal } from "actions/app"; import { selectUserIsRewardApproved } from "selectors/user"; -import { makeSelectHasClaimedReward } from "selectors/rewards"; +import { + makeSelectHasClaimedReward, + makeSelectClaimRewardError, + makeSelectRewardByType, +} from "selectors/rewards"; import WelcomeModal from "./view"; const select = (state, props) => { - const selectHasReward = makeSelectHasClaimedReward(); + const selectHasClaimed = makeSelectHasClaimedReward(), + selectReward = makeSelectRewardByType(); return { - hasReward: selectHasReward(state, { reward_type: "new_user" }), + hasClaimed: selectHasClaimed(state, { reward_type: rewards.TYPE_NEW_USER }), isRewardApproved: selectUserIsRewardApproved(state), - rewardAmount: 5, + reward: selectReward(state, { reward_type: rewards.TYPE_NEW_USER }), }; }; diff --git a/ui/js/component/welcomeModal/view.jsx b/ui/js/component/welcomeModal/view.jsx index 015df4701..5b0f635c5 100644 --- a/ui/js/component/welcomeModal/view.jsx +++ b/ui/js/component/welcomeModal/view.jsx @@ -6,14 +6,12 @@ import RewardLink from "component/rewardLink"; class WelcomeModal extends React.Component { render() { - const { - closeModal, - hasReward, - isRewardApproved, - rewardAmount, - } = this.props; + const { closeModal, hasClaimed, isRewardApproved, reward } = this.props; - return !hasReward + console.log("welcome"); + console.log(this.props); + + return !hasClaimed ?

Welcome to LBRY.

@@ -30,7 +28,7 @@ class WelcomeModal extends React.Component { Thank you for making content freedom possible! {" "}{isRewardApproved ? __("Here's a nickel, kid.") : ""}

-
+
{isRewardApproved ? : About Your Reward

You earned a reward of - {" "} LBRY + {" "} + {" "}LBRY credits, or LBC.

diff --git a/ui/js/constants/action_types.js b/ui/js/constants/action_types.js index 647c6e108..3450c1c1a 100644 --- a/ui/js/constants/action_types.js +++ b/ui/js/constants/action_types.js @@ -71,22 +71,25 @@ export const SEARCH_CANCELLED = "SEARCH_CANCELLED"; export const DAEMON_SETTINGS_RECEIVED = "DAEMON_SETTINGS_RECEIVED"; // User -export const AUTHENTICATION_STARTED = 'AUTHENTICATION_STARTED' -export const AUTHENTICATION_SUCCESS = 'AUTHENTICATION_SUCCESS' -export const AUTHENTICATION_FAILURE = 'AUTHENTICATION_FAILURE' -export const USER_EMAIL_DECLINE = 'USER_EMAIL_DECLINE' -export const USER_EMAIL_NEW_STARTED = 'USER_EMAIL_NEW_STARTED' -export const USER_EMAIL_NEW_SUCCESS = 'USER_EMAIL_NEW_SUCCESS' -export const USER_EMAIL_NEW_EXISTS = 'USER_EMAIL_NEW_EXISTS' -export const USER_EMAIL_NEW_FAILURE = 'USER_EMAIL_NEW_FAILURE' -export const USER_EMAIL_VERIFY_STARTED = 'USER_EMAIL_VERIFY_STARTED' -export const USER_EMAIL_VERIFY_SUCCESS = 'USER_EMAIL_VERIFY_SUCCESS' -export const USER_EMAIL_VERIFY_FAILURE = 'USER_EMAIL_VERIFY_FAILURE' +export const AUTHENTICATION_STARTED = "AUTHENTICATION_STARTED"; +export const AUTHENTICATION_SUCCESS = "AUTHENTICATION_SUCCESS"; +export const AUTHENTICATION_FAILURE = "AUTHENTICATION_FAILURE"; +export const USER_EMAIL_DECLINE = "USER_EMAIL_DECLINE"; +export const USER_EMAIL_NEW_STARTED = "USER_EMAIL_NEW_STARTED"; +export const USER_EMAIL_NEW_SUCCESS = "USER_EMAIL_NEW_SUCCESS"; +export const USER_EMAIL_NEW_EXISTS = "USER_EMAIL_NEW_EXISTS"; +export const USER_EMAIL_NEW_FAILURE = "USER_EMAIL_NEW_FAILURE"; +export const USER_EMAIL_VERIFY_STARTED = "USER_EMAIL_VERIFY_STARTED"; +export const USER_EMAIL_VERIFY_SUCCESS = "USER_EMAIL_VERIFY_SUCCESS"; +export const USER_EMAIL_VERIFY_FAILURE = "USER_EMAIL_VERIFY_FAILURE"; +export const USER_FETCH_STARTED = "USER_FETCH_STARTED"; +export const USER_FETCH_SUCCESS = "USER_FETCH_SUCCESS"; +export const USER_FETCH_FAILURE = "USER_FETCH_FAILURE"; // Rewards -export const FETCH_REWARDS_STARTED = 'FETCH_REWARDS_STARTED' -export const FETCH_REWARDS_COMPLETED = 'FETCH_REWARDS_COMPLETED' -export const CLAIM_REWARD_STARTED = 'CLAIM_REWARD_STARTED' -export const CLAIM_REWARD_SUCCESS = 'CLAIM_REWARD_SUCCESS' -export const CLAIM_REWARD_FAILURE = 'CLAIM_REWARD_FAILURE' -export const CLAIM_REWARD_CLEAR_ERROR = 'CLAIM_REWARD_CLEAR_ERROR' +export const FETCH_REWARDS_STARTED = "FETCH_REWARDS_STARTED"; +export const FETCH_REWARDS_COMPLETED = "FETCH_REWARDS_COMPLETED"; +export const CLAIM_REWARD_STARTED = "CLAIM_REWARD_STARTED"; +export const CLAIM_REWARD_SUCCESS = "CLAIM_REWARD_SUCCESS"; +export const CLAIM_REWARD_FAILURE = "CLAIM_REWARD_FAILURE"; +export const CLAIM_REWARD_CLEAR_ERROR = "CLAIM_REWARD_CLEAR_ERROR"; diff --git a/ui/js/lbryio.js b/ui/js/lbryio.js index 1ca8f76f1..11416fbd6 100644 --- a/ui/js/lbryio.js +++ b/ui/js/lbryio.js @@ -6,7 +6,6 @@ const querystring = require("querystring"); const lbryio = { _accessToken: getSession("accessToken"), _authenticationPromise: null, - _user: null, enabled: true, }; @@ -36,20 +35,9 @@ lbryio.getExchangeRates = function() { return lbryio._exchangePromise; }; -lbryio.call = function( - resource, - action, - params = {}, - method = "get", - evenIfDisabled = false -) { - // evenIfDisabled is just for development, when we may have some calls working and some not +lbryio.call = function(resource, action, params = {}, method = "get") { return new Promise((resolve, reject) => { - if ( - !lbryio.enabled && - !evenIfDisabled && - (resource != "discover" || action != "list") - ) { + if (!lbryio.enabled && (resource != "discover" || action != "list")) { console.log(__("Internal API disabled")); reject(new Error(__("LBRY internal API is disabled"))); return; @@ -135,7 +123,6 @@ lbryio.setCurrentUser = (resolve, reject) => { lbryio .call("user", "me") .then(data => { - lbryio.user = data; resolve(data); }) .catch(function(err) { diff --git a/ui/js/main.js b/ui/js/main.js index c8b9e76fc..f600843bf 100644 --- a/ui/js/main.js +++ b/ui/js/main.js @@ -51,7 +51,10 @@ ipcRenderer.on("open-uri-requested", (event, uri) => { document.addEventListener("click", event => { var target = event.target; while (target && target !== document) { - if (target.matches('a[href^="http"]')) { + if ( + target.matches('a[href^="http"]') || + target.matches('a[href^="mailto"]') + ) { event.preventDefault(); shell.openExternal(target.href); return; diff --git a/ui/js/page/fileListPublished/index.js b/ui/js/page/fileListPublished/index.js index 41ef8a73f..948b81c7e 100644 --- a/ui/js/page/fileListPublished/index.js +++ b/ui/js/page/fileListPublished/index.js @@ -1,10 +1,12 @@ import React from "react"; +import rewards from "rewards"; import { connect } from "react-redux"; import { doFetchFileInfosAndPublishedClaims } from "actions/file_info"; import { selectFileInfosPublished, selectFileListDownloadedOrPublishedIsPending, } from "selectors/file_info"; +import { doClaimRewardType } from "actions/rewards"; import { doNavigate } from "actions/app"; import FileListPublished from "./view"; @@ -16,6 +18,8 @@ const select = state => ({ const perform = dispatch => ({ navigate: path => dispatch(doNavigate(path)), fetchFileListPublished: () => dispatch(doFetchFileInfosAndPublishedClaims()), + claimFirstPublishReward: () => + dispatch(doClaimRewardType(rewards.TYPE_FIRST_PUBLISH)), }); export default connect(select, perform)(FileListPublished); diff --git a/ui/js/page/fileListPublished/view.jsx b/ui/js/page/fileListPublished/view.jsx index e4dc5f3e9..5bf334cf3 100644 --- a/ui/js/page/fileListPublished/view.jsx +++ b/ui/js/page/fileListPublished/view.jsx @@ -16,24 +16,7 @@ class FileListPublished extends React.Component { } componentDidUpdate() { - if (this.props.fileInfos.length > 0) this._requestPublishReward(); - } - - _requestPublishReward() { - // TODO this is throwing an error now - // Error: LBRY internal API is disabled - // - // lbryio.call('reward', 'list', {}).then(function(userRewards) { - // //already rewarded - // if (userRewards.filter(function (reward) { - // return reward.reward_type == rewards.TYPE_FIRST_PUBLISH && reward.transaction_id - // }).length) { - // return - // } - // else { - // rewards.claimReward(rewards.TYPE_FIRST_PUBLISH).catch(() => {}) - // } - // }) + if (this.props.fileInfos.length > 0) this.props.claimFirstPublishReward(); } render() { diff --git a/ui/js/page/publish/index.js b/ui/js/page/publish/index.js index 4b20b9032..abe8137df 100644 --- a/ui/js/page/publish/index.js +++ b/ui/js/page/publish/index.js @@ -1,7 +1,9 @@ import React from "react"; import { connect } from "react-redux"; import { doNavigate, doHistoryBack } from "actions/app"; +import { doClaimRewardType } from "actions/rewards"; import { selectMyClaims } from "selectors/claims"; +import rewards from "rewards"; import PublishPage from "./view"; const select = state => ({ @@ -11,6 +13,8 @@ const select = state => ({ const perform = dispatch => ({ back: () => dispatch(doHistoryBack()), navigate: path => dispatch(doNavigate(path)), + claimFirstChannelReward: () => + dispatch(doClaimRewardType(rewards.TYPE_FIRST_CHANNEL)), }); export default connect(select, perform)(PublishPage); diff --git a/ui/js/page/publish/view.jsx b/ui/js/page/publish/view.jsx index 19e1e2f25..80fac5ec9 100644 --- a/ui/js/page/publish/view.jsx +++ b/ui/js/page/publish/view.jsx @@ -44,7 +44,7 @@ class PublishPage extends React.Component { // Calls API to update displayed list of channels. If a channel name is provided, will select // that channel at the same time (used immediately after creating a channel) lbry.channel_list_mine().then(channels => { - rewards.claimReward(rewards.TYPE_FIRST_CHANNEL).then(() => {}, () => {}); + this.props.claimFirstChannelReward(); this.setState({ channels: channels, ...(channel ? { channel } : {}), @@ -373,7 +373,7 @@ class PublishPage extends React.Component { lbry .channel_new({ channel_name: newChannelName, - amount: parseInt(this.state.newChannelBid), + amount: parseFloat(this.state.newChannelBid), }) .then( () => { diff --git a/ui/js/page/rewards/index.js b/ui/js/page/rewards/index.js index 51da2f8df..61d0515e9 100644 --- a/ui/js/page/rewards/index.js +++ b/ui/js/page/rewards/index.js @@ -1,15 +1,10 @@ import React from "react"; import { connect } from "react-redux"; import { doNavigate } from "actions/app"; -import { - selectFetchingRewards, - selectIsRewardEligible, - selectRewards, -} from "selectors/rewards"; +import { selectFetchingRewards, selectRewards } from "selectors/rewards"; import { selectUserIsRewardEligible, selectUserHasEmail, - selectUserIsRewardApproved, selectUserIsVerificationCandidate, } from "selectors/user"; import RewardsPage from "./view"; diff --git a/ui/js/reducers/rewards.js b/ui/js/reducers/rewards.js index dd56df320..0994d730b 100644 --- a/ui/js/reducers/rewards.js +++ b/ui/js/reducers/rewards.js @@ -1,87 +1,90 @@ import * as types from "constants/action_types"; -const reducers = {} +const reducers = {}; const defaultState = { fetching: false, + rewardsByType: {}, claimPendingByType: {}, - claimErrorsByType: {} + claimErrorsByType: {}, }; reducers[types.FETCH_REWARDS_STARTED] = function(state, action) { - const newRewards = Object.assign({}, state.rewards, { + return Object.assign({}, state, { fetching: true, - }) - - return Object.assign({}, state, newRewards) -} + }); +}; reducers[types.FETCH_REWARDS_COMPLETED] = function(state, action) { - const { - userRewards, - } = action.data + const { userRewards } = action.data; - const byRewardType = {} - userRewards.forEach(reward => byRewardType[reward.reward_type] = reward) - const newRewards = Object.assign({}, state.rewards, { - byRewardType: byRewardType, - fetching: false - }) + const rewardsByType = {}; + userRewards.forEach(reward => (rewardsByType[reward.reward_type] = reward)); - return Object.assign({}, state, newRewards) -} + return Object.assign({}, state, { + rewardsByType: rewardsByType, + fetching: false, + }); +}; -function setClaimRewardState(state, reward, isClaiming, errorMessage="") { - const newClaimPendingByType = Object.assign({}, state.claimPendingByType) - const newClaimErrorsByType = Object.assign({}, state.claimErrorsByType) +function setClaimRewardState(state, reward, isClaiming, errorMessage = "") { + const newClaimPendingByType = Object.assign({}, state.claimPendingByType); + const newClaimErrorsByType = Object.assign({}, state.claimErrorsByType); if (isClaiming) { - newClaimPendingByType[reward.reward_type] = isClaiming + newClaimPendingByType[reward.reward_type] = isClaiming; } else { - delete newClaimPendingByType[reward.reward_type] + delete newClaimPendingByType[reward.reward_type]; } if (errorMessage) { - newClaimErrorsByType[reward.reward_type] = errorMessage + newClaimErrorsByType[reward.reward_type] = errorMessage; } else { - delete newClaimErrorsByType[reward.reward_type] + delete newClaimErrorsByType[reward.reward_type]; } return Object.assign({}, state, { claimPendingByType: newClaimPendingByType, claimErrorsByType: newClaimErrorsByType, - }) + }); } reducers[types.CLAIM_REWARD_STARTED] = function(state, action) { - const { - reward, - } = action.data + const { reward } = action.data; - return setClaimRewardState(state, reward, true, "") -} + return setClaimRewardState(state, reward, true, ""); +}; reducers[types.CLAIM_REWARD_SUCCESS] = function(state, action) { - const { - reward, - } = action.data + const { reward } = action.data; - return setClaimRewardState(state, reward, false, "") -} + const existingReward = state.rewardsByType[reward.reward_type]; + const newReward = Object.assign({}, reward, { + reward_title: existingReward.reward_title, + reward_description: existingReward.reward_description, + }); + const rewardsByType = Object.assign({}, state.rewardsByType); + + rewardsByType[reward.reward_type] = newReward; + + const newState = Object.assign({}, state, { rewardsByType }); + + return setClaimRewardState(newState, newReward, false, ""); +}; reducers[types.CLAIM_REWARD_FAILURE] = function(state, action) { - const { - reward, - error - } = action.data + const { reward, error } = action.data; - return setClaimRewardState(state, reward, false, error.message) -} + return setClaimRewardState(state, reward, false, error ? error.message : ""); +}; reducers[types.CLAIM_REWARD_CLEAR_ERROR] = function(state, action) { - const { - reward - } = action.data + const { reward } = action.data; - return setClaimRewardState(state, reward, state.claimPendingByType[reward.reward_type], "") -} + return setClaimRewardState( + state, + reward, + state.claimPendingByType[reward.reward_type], + "" + ); +}; export default function reducer(state = defaultState, action) { const handler = reducers[action.type]; diff --git a/ui/js/reducers/user.js b/ui/js/reducers/user.js index 353b9b193..4e4ffda40 100644 --- a/ui/js/reducers/user.js +++ b/ui/js/reducers/user.js @@ -5,6 +5,7 @@ const reducers = {}; const defaultState = { authenticationIsPending: false, + userIsPending: false, emailNewIsPending: false, emailNewErrorMessage: "", emailNewDeclined: getLocal("user_email_declined", false), @@ -15,12 +16,15 @@ const defaultState = { reducers[types.AUTHENTICATION_STARTED] = function(state, action) { return Object.assign({}, state, { authenticationIsPending: true, + userIsPending: true, + user: defaultState.user, }); }; reducers[types.AUTHENTICATION_SUCCESS] = function(state, action) { return Object.assign({}, state, { authenticationIsPending: false, + userIsPending: false, user: action.data.user, }); }; @@ -28,6 +32,28 @@ reducers[types.AUTHENTICATION_SUCCESS] = function(state, action) { reducers[types.AUTHENTICATION_FAILURE] = function(state, action) { return Object.assign({}, state, { authenticationIsPending: false, + userIsPending: false, + user: null, + }); +}; + +reducers[types.USER_FETCH_STARTED] = function(state, action) { + return Object.assign({}, state, { + userIsPending: true, + user: defaultState.user, + }); +}; + +reducers[types.USER_FETCH_SUCCESS] = function(state, action) { + return Object.assign({}, state, { + userIsPending: false, + user: action.data.user, + }); +}; + +reducers[types.USER_FETCH_FAILURE] = function(state, action) { + return Object.assign({}, state, { + userIsPending: true, user: null, }); }; diff --git a/ui/js/rewards.js b/ui/js/rewards.js index 33d5547bc..08d82fd9b 100644 --- a/ui/js/rewards.js +++ b/ui/js/rewards.js @@ -1,225 +1,191 @@ -const hashes = require('jshashes'); -import lbry from 'lbry'; -import lbryio from 'lbryio'; -import { doShowSnackBar } from 'actions/app'; +const hashes = require("jshashes"); +import lbry from "lbry"; +import lbryio from "lbryio"; +import { doShowSnackBar } from "actions/app"; function rewardMessage(type, amount) { - return { - new_developer: __( - 'You earned %s for registering as a new developer.', - amount - ), - new_user: __('You earned %s LBC new user reward.', amount), - confirm_email: __( - 'You earned %s LBC for verifying your email address.', - amount - ), - new_channel: __( - 'You earned %s LBC for creating a publisher identity.', - amount - ), - first_stream: __( - 'You earned %s LBC for streaming your first video.', - amount - ), - many_downloads: __( - 'You earned %s LBC for downloading some of the things.', - amount - ), - first_publish: __( - 'You earned %s LBC for making your first publication.', - amount - ) - }[type]; + return { + new_developer: __( + "You earned %s for registering as a new developer.", + amount + ), + new_user: __("You earned %s LBC new user reward.", amount), + confirm_email: __( + "You earned %s LBC for verifying your email address.", + amount + ), + new_channel: __( + "You earned %s LBC for creating a publisher identity.", + amount + ), + first_stream: __( + "You earned %s LBC for streaming your first video.", + amount + ), + many_downloads: __( + "You earned %s LBC for downloading some of the things.", + amount + ), + first_publish: __( + "You earned %s LBC for making your first publication.", + amount + ), + }[type]; } function toHex(s) { - let h = ''; - for (var i = 0; i < s.length; i++) { - let c = s.charCodeAt(i).toString(16); - if (c.length < 2) { - c = '0'.concat(c); - } - h += c; - } - return h; + let h = ""; + for (var i = 0; i < s.length; i++) { + let c = s.charCodeAt(i).toString(16); + if (c.length < 2) { + c = "0".concat(c); + } + h += c; + } + return h; } function fromHex(h) { - let s = ''; - for (let i = 0; i < h.length; i += 2) { - s += String.fromCharCode(parseInt(h.substr(i, 2), 16)); - } - return s; + let s = ""; + for (let i = 0; i < h.length; i += 2) { + s += String.fromCharCode(parseInt(h.substr(i, 2), 16)); + } + return s; } function reverseString(s) { - let o = ''; - for (let i = s.length - 1; i >= 0; i--) { - o += s[i]; - } - return o; + let o = ""; + for (let i = s.length - 1; i >= 0; i--) { + o += s[i]; + } + return o; } function pack(num) { - return ( - '' + - String.fromCharCode(num & 0xff) + - String.fromCharCode((num >> 8) & 0xff) + - String.fromCharCode((num >> 16) & 0xff) + - String.fromCharCode((num >> 24) & 0xff) - ); + return ( + "" + + String.fromCharCode(num & 0xff) + + String.fromCharCode((num >> 8) & 0xff) + + String.fromCharCode((num >> 16) & 0xff) + + String.fromCharCode((num >> 24) & 0xff) + ); } // Returns true if claim is an initial claim, false if it's an update to an existing claim function isInitialClaim(claim) { - const reversed = reverseString(fromHex(claim.txid)); - const concat = reversed.concat(pack(claim.nout)); - const sha256 = new hashes.SHA256({ utf8: false }).raw(concat); - const ripemd160 = new hashes.RMD160({ utf8: false }).raw(sha256); - const hash = toHex(reverseString(ripemd160)); - return hash == claim.claim_id; + const reversed = reverseString(fromHex(claim.txid)); + const concat = reversed.concat(pack(claim.nout)); + const sha256 = new hashes.SHA256({ utf8: false }).raw(concat); + const ripemd160 = new hashes.RMD160({ utf8: false }).raw(sha256); + const hash = toHex(reverseString(ripemd160)); + return hash == claim.claim_id; } const rewards = {}; -(rewards.TYPE_NEW_DEVELOPER = 'new_developer'), (rewards.TYPE_NEW_USER = - 'new_user'), (rewards.TYPE_CONFIRM_EMAIL = - 'confirm_email'), (rewards.TYPE_FIRST_CHANNEL = - 'new_channel'), (rewards.TYPE_FIRST_STREAM = - 'first_stream'), (rewards.TYPE_MANY_DOWNLOADS = - 'many_downloads'), (rewards.TYPE_FIRST_PUBLISH = 'first_publish'); -rewards.TYPE_FEATURED_DOWNLOAD = 'featured_download'; +(rewards.TYPE_NEW_DEVELOPER = "new_developer"), (rewards.TYPE_NEW_USER = + "new_user"), (rewards.TYPE_CONFIRM_EMAIL = + "confirm_email"), (rewards.TYPE_FIRST_CHANNEL = + "new_channel"), (rewards.TYPE_FIRST_STREAM = + "first_stream"), (rewards.TYPE_MANY_DOWNLOADS = + "many_downloads"), (rewards.TYPE_FIRST_PUBLISH = "first_publish"); +rewards.TYPE_FEATURED_DOWNLOAD = "featured_download"; rewards.claimReward = function(type) { - function requestReward(resolve, reject, params) { - if (!lbryio.enabled || !lbryio.getAccessToken()) { - reject(new Error(__('Rewards are not enabled.'))); - return; - } - lbryio.call('reward', 'new', params, 'post').then(({ reward_amount }) => { - const message = rewardMessage(type, reward_amount), - result = { - type: type, - amount: reward_amount, - message: message - }; + function requestReward(resolve, reject, params) { + if (!lbryio.enabled || !lbryio.getAccessToken()) { + reject(new Error(__("Rewards are not enabled."))); + return; + } + lbryio.call("reward", "new", params, "post").then(reward => { + const message = rewardMessage(type, reward.reward_amount); - // Display global notice - const action = doShowSnackBar({ - message, - linkText: __('Show All'), - linkTarget: '/rewards', - isError: false - }); - window.app.store.dispatch(action); + // Display global notice + const action = doShowSnackBar({ + message, + linkText: __("Show All"), + linkTarget: "/rewards", + isError: false, + }); + window.app.store.dispatch(action); - // Add more events here to display other places + // Add more events here to display other places - resolve(result); - }, reject); - } - - return new Promise((resolve, reject) => { - lbry.wallet_unused_address().then(address => { - const params = { - reward_type: type, - wallet_address: address - }; - - switch (type) { - case rewards.TYPE_FIRST_CHANNEL: - lbry - .claim_list_mine() - .then(function(claims) { - let claim = claims.find(function(claim) { - return ( - claim.name.length && - claim.name[0] == '@' && - claim.txid.length && - isInitialClaim(claim) - ); - }); - if (claim) { - params.transaction_id = claim.txid; - requestReward(resolve, reject, params); - } else { - reject( - new Error(__('Please create a channel identity first.')) - ); - } - }) - .catch(reject); - break; - - case rewards.TYPE_FIRST_PUBLISH: - lbry - .claim_list_mine() - .then(claims => { - let claim = claims.find(function(claim) { - return ( - claim.name.length && - claim.name[0] != '@' && - claim.txid.length && - isInitialClaim(claim) - ); - }); - if (claim) { - params.transaction_id = claim.txid; - requestReward(resolve, reject, params); - } else { - reject( - claims.length - ? new Error( - __( - 'Please publish something and wait for confirmation by the network to claim this reward.' - ) - ) - : new Error( - __('Please publish something to claim this reward.') - ) - ); - } - }) - .catch(reject); - break; - - case rewards.TYPE_FIRST_STREAM: - case rewards.TYPE_NEW_USER: - default: - requestReward(resolve, reject, params); - } - }); - }); -}; - -rewards.claimEligiblePurchaseRewards = () => { - if (!lbryio.enabled || !lbryio.getAccessToken()) { - return; + resolve(reward); + }, reject); } - let types = {}; - types[rewards.TYPE_FIRST_STREAM] = false; - types[rewards.TYPE_FEATURED_DOWNLOAD] = false; - types[rewards.TYPE_MANY_DOWNLOADS] = false; - lbryio.call('reward', 'list', {}).then( - userRewards => { - userRewards.forEach(reward => { - if (types[reward.reward_type] === false && reward.transaction_id) { - types[reward.reward_type] = true; - } - }); - let unclaimedType = Object.keys(types).find(type => { - return types[type] === false && type !== rewards.TYPE_FEATURED_DOWNLOAD; //handled below - }); - if (unclaimedType) { - rewards.claimReward(unclaimedType); - } - if (types[rewards.TYPE_FEATURED_DOWNLOAD] === false) { - rewards.claimReward(rewards.TYPE_FEATURED_DOWNLOAD); - } - }, - () => {} - ); + + return new Promise((resolve, reject) => { + lbry.wallet_unused_address().then(address => { + const params = { + reward_type: type, + wallet_address: address, + }; + + switch (type) { + case rewards.TYPE_FIRST_CHANNEL: + lbry + .claim_list_mine() + .then(function(claims) { + let claim = claims.reverse().find(function(claim) { + return ( + claim.name.length && + claim.name[0] == "@" && + claim.txid.length && + isInitialClaim(claim) + ); + }); + if (claim) { + params.transaction_id = claim.txid; + requestReward(resolve, reject, params); + } else { + reject( + new Error(__("Please create a channel identity first.")) + ); + } + }) + .catch(reject); + break; + + case rewards.TYPE_FIRST_PUBLISH: + lbry + .claim_list_mine() + .then(claims => { + let claim = claims.reverse().find(function(claim) { + return ( + claim.name.length && + claim.name[0] != "@" && + claim.txid.length && + isInitialClaim(claim) + ); + }); + if (claim) { + params.transaction_id = claim.txid; + requestReward(resolve, reject, params); + } else { + reject( + claims.length + ? new Error( + __( + "Please publish something and wait for confirmation by the network to claim this reward." + ) + ) + : new Error( + __("Please publish something to claim this reward.") + ) + ); + } + }) + .catch(reject); + break; + + case rewards.TYPE_FIRST_STREAM: + case rewards.TYPE_NEW_USER: + default: + requestReward(resolve, reject, params); + } + }); + }); }; export default rewards; diff --git a/ui/js/selectors/rewards.js b/ui/js/selectors/rewards.js index d9e17f927..7a6a20429 100644 --- a/ui/js/selectors/rewards.js +++ b/ui/js/selectors/rewards.js @@ -5,7 +5,7 @@ const _selectState = state => state.rewards || {}; export const selectRewardsByType = createSelector( _selectState, - state => state.byRewardType || {} + state => state.rewardsByType || {} ); export const selectRewards = createSelector( @@ -18,26 +18,14 @@ export const selectIsRewardEligible = createSelector( user => user.can_claim_rewards ); -export const selectClaimedRewards = createSelector(selectRewards, rewards => - rewards.filter(reward => reward.transaction_id !== "") -); - -export const selectClaimedRewardsByType = createSelector( - selectClaimedRewards, - claimedRewards => { - const byType = {}; - claimedRewards.forEach(reward => (byType[reward.reward_type] = reward)); - return byType; - } -); - export const selectFetchingRewards = createSelector( _selectState, state => !!state.fetching ); export const selectHasClaimedReward = (state, props) => { - return !!selectClaimedRewardsByType[props.reward_type]; + const reward = selectRewardsByType(state)[props.reward_type]; + return reward && reward.transaction_id !== ""; }; export const makeSelectHasClaimedReward = () => { diff --git a/ui/js/selectors/user.js b/ui/js/selectors/user.js index 015ebae62..f7104d3d4 100644 --- a/ui/js/selectors/user.js +++ b/ui/js/selectors/user.js @@ -7,6 +7,11 @@ export const selectAuthenticationIsPending = createSelector( state => state.authenticationIsPending ); +export const selectUserIsPending = createSelector( + _selectState, + state => state.userIsPending +); + export const selectUser = createSelector( _selectState, state => state.user || {} @@ -20,17 +25,17 @@ export const selectEmailToVerify = createSelector( export const selectUserHasEmail = createSelector( selectUser, selectEmailToVerify, - (user, email) => user.has_email || email + (user, email) => (user && user.has_email) || email ); export const selectUserIsRewardEligible = createSelector( selectUser, - user => user.is_reward_eligible + user => user && user.is_reward_eligible ); export const selectUserIsRewardApproved = createSelector( selectUser, - user => user.is_reward_approved + user => user && user.is_reward_approved ); export const selectEmailNewIsPending = createSelector( @@ -64,7 +69,7 @@ export const selectUserIsVerificationCandidate = createSelector( selectEmailToVerify, selectUser, (isEligible, isApproved, emailToVerify, user) => - (isEligible && !isApproved) || (emailToVerify && !user.has_email) + (isEligible && !isApproved) || (emailToVerify && user && !user.has_email) ); export const selectUserIsAuthRequested = createSelector( diff --git a/ui/scss/_gui.scss b/ui/scss/_gui.scss index f4ededba0..a902fe2da 100644 --- a/ui/scss/_gui.scss +++ b/ui/scss/_gui.scss @@ -165,3 +165,8 @@ p section.section-spaced { margin-bottom: $spacing-vertical; } + +.text-center +{ + text-align: center; +} From 1a6a69914c548f5ac9f4cccdab158248d2f6bb3e Mon Sep 17 00:00:00 2001 From: Jeremy Kauffman Date: Thu, 8 Jun 2017 17:19:02 -0400 Subject: [PATCH 10/14] changelog and bugfix --- CHANGELOG.md | 3 ++- app/main.js | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c5c1bb1dc..8197e7035 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,7 @@ Web UI version numbers should always match the corresponding version of LBRY App ## [Unreleased] ### Added * More file types, like audio and documents, can be streamed and/or served from the app - * + * App is no longer gated. Reward authorization re-written. Added basic flows for new users. ### Changed * All UI strings are now rendered according to gettext standard, in prep for i18n @@ -20,6 +20,7 @@ Web UI version numbers should always match the corresponding version of LBRY App * Updated deprecated LBRY API call signatures * App scrolls to the top of the page on navigation * Download progress works properly for purchased but deleted files + * Publish channels for less than 1 LBC ### Deprecated * diff --git a/app/main.js b/app/main.js index 14ead8e95..85a0dd3c7 100644 --- a/app/main.js +++ b/app/main.js @@ -1,6 +1,6 @@ const {app, BrowserWindow, ipcMain} = require('electron'); const url = require('url'); -const isDebug = process.env.NODE_ENV === 'development' || true +const isDebug = process.env.NODE_ENV === 'development' if (isDebug) { require('electron-debug')({showDevTools: true}); From 9418e780461b6d0036d72e9e3ab10dbaa91382fc Mon Sep 17 00:00:00 2001 From: Jeremy Kauffman Date: Thu, 8 Jun 2017 20:10:53 -0400 Subject: [PATCH 11/14] restore purecomponent, remove console.log --- ui/js/component/auth/view.jsx | 2 +- ui/js/component/authOverlay/view.jsx | 2 +- ui/js/component/userEmailNew/view.jsx | 2 +- ui/js/component/userEmailVerify/view.jsx | 2 +- ui/js/component/welcomeModal/view.jsx | 5 +---- ui/js/page/rewards/view.jsx | 2 -- 6 files changed, 5 insertions(+), 10 deletions(-) diff --git a/ui/js/component/auth/view.jsx b/ui/js/component/auth/view.jsx index d796e1448..551113ffa 100644 --- a/ui/js/component/auth/view.jsx +++ b/ui/js/component/auth/view.jsx @@ -3,7 +3,7 @@ import { BusyMessage } from "component/common"; import UserEmailNew from "component/userEmailNew"; import UserEmailVerify from "component/userEmailVerify"; -export class Auth extends React.Component { +export class Auth extends React.PureComponent { render() { const { isPending, email, isVerificationCandidate } = this.props; diff --git a/ui/js/component/authOverlay/view.jsx b/ui/js/component/authOverlay/view.jsx index fcb7e77d4..0cce29f9b 100644 --- a/ui/js/component/authOverlay/view.jsx +++ b/ui/js/component/authOverlay/view.jsx @@ -4,7 +4,7 @@ import ModalPage from "component/modal-page.js"; import Auth from "component/auth"; import Link from "component/link"; -export class AuthOverlay extends React.Component { +export class AuthOverlay extends React.PureComponent { constructor(props) { super(props); diff --git a/ui/js/component/userEmailNew/view.jsx b/ui/js/component/userEmailNew/view.jsx index 7e0f83b47..5391bdb3f 100644 --- a/ui/js/component/userEmailNew/view.jsx +++ b/ui/js/component/userEmailNew/view.jsx @@ -2,7 +2,7 @@ import React from "react"; import Link from "component/link"; import { FormRow } from "component/form.js"; -class UserEmailNew extends React.Component { +class UserEmailNew extends React.PureComponent { constructor(props) { super(props); diff --git a/ui/js/component/userEmailVerify/view.jsx b/ui/js/component/userEmailVerify/view.jsx index 4b9272394..c6cc65f34 100644 --- a/ui/js/component/userEmailVerify/view.jsx +++ b/ui/js/component/userEmailVerify/view.jsx @@ -2,7 +2,7 @@ import React from "react"; import Link from "component/link"; import { FormRow } from "component/form.js"; -class UserEmailVerify extends React.Component { +class UserEmailVerify extends React.PureComponent { constructor(props) { super(props); diff --git a/ui/js/component/welcomeModal/view.jsx b/ui/js/component/welcomeModal/view.jsx index 5b0f635c5..13e0cd5f1 100644 --- a/ui/js/component/welcomeModal/view.jsx +++ b/ui/js/component/welcomeModal/view.jsx @@ -4,13 +4,10 @@ import { CreditAmount } from "component/common"; import Link from "component/link"; import RewardLink from "component/rewardLink"; -class WelcomeModal extends React.Component { +class WelcomeModal extends React.PureComponent { render() { const { closeModal, hasClaimed, isRewardApproved, reward } = this.props; - console.log("welcome"); - console.log(this.props); - return !hasClaimed ?

diff --git a/ui/js/page/rewards/view.jsx b/ui/js/page/rewards/view.jsx index a40afefff..6f78a6490 100644 --- a/ui/js/page/rewards/view.jsx +++ b/ui/js/page/rewards/view.jsx @@ -38,8 +38,6 @@ const RewardsPage = props => { rewards, } = props; - console.log(props); - let content, isCard = false; From 20fa2bb0e528eb2ffa98d0d56adebbedd24cf047 Mon Sep 17 00:00:00 2001 From: Jeremy Kauffman Date: Thu, 8 Jun 2017 20:11:51 -0400 Subject: [PATCH 12/14] bump daemon version --- build/DAEMON_URL | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/DAEMON_URL b/build/DAEMON_URL index efb0b928e..188944dec 100644 --- a/build/DAEMON_URL +++ b/build/DAEMON_URL @@ -1 +1 @@ -https://github.com/lbryio/lbry/releases/download/v0.11.0rc1/lbrynet-daemon-v0.11.0rc1-OSNAME.zip +https://github.com/lbryio/lbry/releases/download/v0.11.0rc3/lbrynet-daemon-v0.11.0rc3-OSNAME.zip From 668a8b40e97f7819964a858a9f863e1ae351a6b7 Mon Sep 17 00:00:00 2001 From: Alex Grintsvayg Date: Fri, 9 Jun 2017 10:23:36 -0400 Subject: [PATCH 13/14] what is up with these files? --- app/package-lock.json | 1290 ++++++++++++++++++++--------------------- package-lock.json | 958 ++++++++++++++++++++---------- ui/package-lock.json | 334 +++++++++-- 3 files changed, 1548 insertions(+), 1034 deletions(-) diff --git a/app/package-lock.json b/app/package-lock.json index 1f5b44437..431a9e6c0 100644 --- a/app/package-lock.json +++ b/app/package-lock.json @@ -1,160 +1,137 @@ { "name": "LBRY", - "version": "0.12.0rc4", + "version": "0.12.0rc6", "lockfileVersion": 1, "dependencies": { - "asap": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.5.tgz", - "integrity": "sha1-UidltQw1EEkOUtfc/ghe+bqWlY8=" - }, "commander": { - "version": "https://registry.npmjs.org/commander/-/commander-1.3.2.tgz", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/commander/-/commander-1.3.2.tgz", "integrity": "sha1-io8w7GcKb91kr1LxkUuQfXnq1bU=" }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" - }, - "dezalgo": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.3.tgz", - "integrity": "sha1-f3Qt4Gb8dIvI24IFad3c5Jvw1FY=" - }, "electron-dl": { - "version": "https://registry.npmjs.org/electron-dl/-/electron-dl-1.8.0.tgz", - "integrity": "sha1-VmUtpVqv2kpwB09jE/33+UHsdSo=" + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/electron-dl/-/electron-dl-1.9.0.tgz", + "integrity": "sha1-HzBuMLblkLKWzihP+rFPGlREl8c=" }, "es6-promise": { - "version": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz", "integrity": "sha1-oIzd6EzNvzTQJ6FFG8kdS80ophM=" }, "es6-promisify": { - "version": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-3.0.0.tgz", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-3.0.0.tgz", "integrity": "sha1-IiJrkpVzF/llJH7f3pKV+D7+voY=" }, "eyes": { - "version": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz", + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz", "integrity": "sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A=" }, - "hosted-git-info": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.4.2.tgz", - "integrity": "sha1-AHa59GonBQbduq6lZJaJdGBhKmc=" - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" - }, "install": { - "version": "https://registry.npmjs.org/install/-/install-0.8.8.tgz", - "integrity": "sha1-6+ojEEuMEBcsK8dkovbJc4DKfd4=" + "version": "0.8.9", + "resolved": "https://registry.npmjs.org/install/-/install-0.8.9.tgz", + "integrity": "sha1-n0tcDRhR74cunfheT3Fi1OXc2+0=" }, "jayson": { - "version": "https://registry.npmjs.org/jayson/-/jayson-2.0.3.tgz", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/jayson/-/jayson-2.0.3.tgz", "integrity": "sha1-3XULdOozQfOpj4dbQaNcrx1JSe0=" }, "json-stringify-safe": { - "version": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" }, "jsonparse": { - "version": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.0.0.tgz", "integrity": "sha1-JiL05mwI4arH7b63YFPJt+EhH3Y=" }, "JSONStream": { - "version": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.0.3.tgz", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.0.3.tgz", "integrity": "sha1-coVEGJQ4t7ndIYQ5JYGGHrq9liE=" }, "keypress": { - "version": "https://registry.npmjs.org/keypress/-/keypress-0.1.0.tgz", + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/keypress/-/keypress-0.1.0.tgz", "integrity": "sha1-SjGI1CkbZrT2XtuZ+AaqmuKTWSo=" }, "lodash": { - "version": "https://registry.npmjs.org/lodash/-/lodash-3.6.0.tgz", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.6.0.tgz", "integrity": "sha1-Umao9J3Zib5Pn2gbbyoMVShdDZo=" }, "modify-filename": { - "version": "https://registry.npmjs.org/modify-filename/-/modify-filename-1.1.0.tgz", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/modify-filename/-/modify-filename-1.1.0.tgz", "integrity": "sha1-mi3sg4Bvuy2XXyK+7IWcoms5OqE=" }, - "normalize-git-url": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/normalize-git-url/-/normalize-git-url-3.0.2.tgz", - "integrity": "sha1-jl8Uvgva7bc+ByADEKpBbCc1D8Q=" - }, "npm": { - "version": "https://registry.npmjs.org/npm/-/npm-4.4.4.tgz", - "integrity": "sha1-1exmGSOga81qbuw9BDOp2j/Wfjc=", + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/npm/-/npm-4.6.1.tgz", + "integrity": "sha1-+Osa0A3FilUUNjtBylNCgX8L1kY=", "dependencies": { "abbrev": { - "version": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.0.tgz", - "integrity": "sha1-0FVMIlZjbi9W58LlrRg/hZQo2B8=" + "version": "1.1.0", + "bundled": true }, "ansi-regex": { - "version": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + "version": "2.1.1", + "bundled": true }, "ansicolors": { "version": "0.3.2", - "resolved": "https://registry.npmjs.org/ansicolors/-/ansicolors-0.3.2.tgz", - "integrity": "sha1-ZlWX3oap/+Oqm/vmyuXG6kJrSXk=" + "bundled": true }, "ansistyles": { "version": "0.1.3", - "resolved": "https://registry.npmjs.org/ansistyles/-/ansistyles-0.1.3.tgz", - "integrity": "sha1-XeYEFb2gcbs3EnhUyGT0GyMlRTk=" + "bundled": true }, "aproba": { - "version": "https://registry.npmjs.org/aproba/-/aproba-1.1.1.tgz", - "integrity": "sha1-ldNgDwdxCqDpKYxyatXs8urLq6s=" + "version": "1.1.1", + "bundled": true }, "archy": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", - "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=" + "bundled": true }, "asap": { - "version": "https://registry.npmjs.org/asap/-/asap-2.0.5.tgz", - "integrity": "sha1-UidltQw1EEkOUtfc/ghe+bqWlY8=" + "version": "2.0.5", + "bundled": true }, "bluebird": { - "version": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.0.tgz", - "integrity": "sha1-eRQg1/VR7qKJdFOop3ZT+WYG1nw=" + "version": "3.5.0", + "bundled": true }, "call-limit": { - "version": "https://registry.npmjs.org/call-limit/-/call-limit-1.1.0.tgz", - "integrity": "sha1-b9YbA/PaQqLNDsK2DwK9DnGZH+o=" + "version": "1.1.0", + "bundled": true }, "chownr": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.0.1.tgz", - "integrity": "sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE=" + "bundled": true }, "cmd-shim": { - "version": "https://registry.npmjs.org/cmd-shim/-/cmd-shim-2.0.2.tgz", - "integrity": "sha1-b8vamUg6j9FdfTChlspp1oii79s=" + "version": "2.0.2", + "bundled": true }, "columnify": { - "version": "https://registry.npmjs.org/columnify/-/columnify-1.5.4.tgz", - "integrity": "sha1-Rzfd8ce2mop8NAVweC6UfuyOeLs=", + "version": "1.5.4", + "bundled": true, "dependencies": { "wcwidth": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.0.tgz", - "integrity": "sha1-AtBZ/3qPx0Hg9rXaHmmytA2uym8=", + "bundled": true, "dependencies": { "defaults": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", - "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", + "bundled": true, "dependencies": { "clone": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.2.tgz", - "integrity": "sha1-Jgt6meux7f4kdTgXX3gyQ8sZ0Uk=" + "bundled": true } } } @@ -163,62 +140,62 @@ } }, "config-chain": { - "version": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.11.tgz", - "integrity": "sha1-q6CXR9++TD5w52am5BWG4YWfxvI=", + "version": "1.1.11", + "bundled": true, "dependencies": { "proto-list": { "version": "1.2.4", - "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", - "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=" + "bundled": true } } }, "debuglog": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/debuglog/-/debuglog-1.0.1.tgz", - "integrity": "sha1-qiT/uaw9+aI1GDfPstJ5NgzXhJI=" + "bundled": true + }, + "dezalgo": { + "version": "1.0.3", + "bundled": true }, "editor": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/editor/-/editor-1.0.0.tgz", - "integrity": "sha1-YMf4e9YrzGqJT6jM1q+3gjok90I=" + "bundled": true }, "fs-vacuum": { - "version": "https://registry.npmjs.org/fs-vacuum/-/fs-vacuum-1.2.10.tgz", - "integrity": "sha1-t2Kb7AekAxolSP35n17PHMizHjY=" + "version": "1.2.10", + "bundled": true }, "fs-write-stream-atomic": { - "version": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", - "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=" + "version": "1.0.10", + "bundled": true }, "fstream": { - "version": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", - "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=" + "version": "1.0.11", + "bundled": true }, "fstream-npm": { - "version": "https://registry.npmjs.org/fstream-npm/-/fstream-npm-1.2.0.tgz", - "integrity": "sha1-0sPIkQE0aYLWTlcJHDhIe9qRb84=", + "version": "1.2.0", + "bundled": true, "dependencies": { "fstream-ignore": { - "version": "https://registry.npmjs.org/fstream-ignore/-/fstream-ignore-1.0.5.tgz", - "integrity": "sha1-nDHa40dnAY/h0kmyTa2mfQktoQU=", + "version": "1.0.5", + "bundled": true, "dependencies": { "minimatch": { - "version": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.3.tgz", - "integrity": "sha1-Kk5AkLlrLbBqnX3wEFWmKnfJt3Q=", + "version": "3.0.3", + "bundled": true, "dependencies": { "brace-expansion": { - "version": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.6.tgz", - "integrity": "sha1-cZfX6qm4fmSDkOph/GbIRCdCDfk=", + "version": "1.1.6", + "bundled": true, "dependencies": { "balanced-match": { - "version": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", - "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=" + "version": "0.4.2", + "bundled": true }, "concat-map": { "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + "bundled": true } } } @@ -229,254 +206,244 @@ } }, "glob": { - "version": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz", - "integrity": "sha1-gFIR3wT6rxxjo2ADBs31reULLsg=", + "version": "7.1.1", + "bundled": true, "dependencies": { "fs.realpath": { - "version": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + "version": "1.0.0", + "bundled": true }, "minimatch": { - "version": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.3.tgz", - "integrity": "sha1-Kk5AkLlrLbBqnX3wEFWmKnfJt3Q=", + "version": "3.0.3", + "bundled": true, "dependencies": { "brace-expansion": { - "version": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.6.tgz", - "integrity": "sha1-cZfX6qm4fmSDkOph/GbIRCdCDfk=", + "version": "1.1.6", + "bundled": true, "dependencies": { "balanced-match": { - "version": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", - "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=" + "version": "0.4.2", + "bundled": true }, "concat-map": { "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + "bundled": true } } } } }, "path-is-absolute": { - "version": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + "version": "1.0.1", + "bundled": true } } }, "graceful-fs": { - "version": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" + "version": "4.1.11", + "bundled": true }, "has-unicode": { - "version": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" + "version": "2.0.1", + "bundled": true }, "hosted-git-info": { - "version": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.2.0.tgz", - "integrity": "sha1-eg0JeGPYhsD6u9zTe/F1jYvs+KU=" + "version": "2.4.2", + "bundled": true }, "iferr": { "version": "0.1.5", - "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", - "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=" + "bundled": true }, "imurmurhash": { - "version": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" + "version": "0.1.4", + "bundled": true }, "inflight": { - "version": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=" + "version": "1.0.6", + "bundled": true }, "inherits": { - "version": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + "version": "2.0.3", + "bundled": true }, "ini": { "version": "1.3.4", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.4.tgz", - "integrity": "sha1-BTfLedr1m1mhpRff9wbIbsA5Fi4=" + "bundled": true }, "init-package-json": { - "version": "https://registry.npmjs.org/init-package-json/-/init-package-json-1.9.5.tgz", - "integrity": "sha1-fU1komTcdsHx9VfLvoJJeL8QzQk=", + "version": "1.10.1", + "bundled": true, "dependencies": { "promzard": { "version": "0.3.0", - "resolved": "https://registry.npmjs.org/promzard/-/promzard-0.3.0.tgz", - "integrity": "sha1-JqXW7ox97kyxIggwWs+5O6OCqe4=" + "bundled": true } } }, "JSONStream": { - "version": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.1.tgz", - "integrity": "sha1-cH92HgHa6eFvG8+TcDt4xwlmV5o=", + "version": "1.3.1", + "bundled": true, "dependencies": { "jsonparse": { - "version": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.0.tgz", - "integrity": "sha1-hfwkWx2SWazGlBlguQWt9k594Og=" + "version": "1.3.0", + "bundled": true }, "through": { - "version": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + "version": "2.3.8", + "bundled": true } } }, "lazy-property": { - "version": "https://registry.npmjs.org/lazy-property/-/lazy-property-1.0.0.tgz", - "integrity": "sha1-hN3Es3Bnm6i9TNz6TAa0PVcREUc=" + "version": "1.0.0", + "bundled": true }, "lockfile": { - "version": "https://registry.npmjs.org/lockfile/-/lockfile-1.0.3.tgz", - "integrity": "sha1-Jjj8OaAzHpysGgS3F5mTHJxQ33k=" + "version": "1.0.3", + "bundled": true }, "lodash._baseindexof": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/lodash._baseindexof/-/lodash._baseindexof-3.1.0.tgz", - "integrity": "sha1-/lK1OhxnYeQmGNZU5KJXie1hgiw=" + "bundled": true }, "lodash._baseuniq": { - "version": "https://registry.npmjs.org/lodash._baseuniq/-/lodash._baseuniq-4.6.0.tgz", - "integrity": "sha1-DrtE5FaBSveQXGIS+iybLVG4Qeg=", + "version": "4.6.0", + "bundled": true, "dependencies": { "lodash._createset": { - "version": "https://registry.npmjs.org/lodash._createset/-/lodash._createset-4.0.3.tgz", - "integrity": "sha1-D0ZZ+7CddRlPqeK4imZE02PJ/iY=" + "version": "4.0.3", + "bundled": true }, "lodash._root": { - "version": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz", - "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=" + "version": "3.0.1", + "bundled": true } } }, "lodash._bindcallback": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz", - "integrity": "sha1-5THCdkTPi1epnhftlbNcdIeJOS4=" + "bundled": true }, "lodash._cacheindexof": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/lodash._cacheindexof/-/lodash._cacheindexof-3.0.2.tgz", - "integrity": "sha1-PcaayCSY0u5ePOVgkbr9Ktx73pI=" + "bundled": true }, "lodash._createcache": { "version": "3.1.2", - "resolved": "https://registry.npmjs.org/lodash._createcache/-/lodash._createcache-3.1.2.tgz", - "integrity": "sha1-VtagZAF2JeeevKa4AY4XRAvc8JM=" + "bundled": true }, "lodash._getnative": { "version": "3.9.1", - "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", - "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=" + "bundled": true }, "lodash.clonedeep": { - "version": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", - "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=" + "version": "4.5.0", + "bundled": true }, "lodash.restparam": { "version": "3.6.1", - "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", - "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=" + "bundled": true }, "lodash.union": { - "version": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz", - "integrity": "sha1-SLtQiECfFvGCFmZkHETdGqrjzYg=" + "version": "4.6.0", + "bundled": true }, "lodash.uniq": { - "version": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", - "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=" + "version": "4.5.0", + "bundled": true }, "lodash.without": { - "version": "https://registry.npmjs.org/lodash.without/-/lodash.without-4.4.0.tgz", - "integrity": "sha1-PNRXSgC2e643OpS3SHcmQFB7eqw=" + "version": "4.4.0", + "bundled": true }, "mississippi": { - "version": "https://registry.npmjs.org/mississippi/-/mississippi-1.3.0.tgz", - "integrity": "sha1-0gFYPrEjJ+PFwWQqQEqcrPlONPU=", + "version": "1.3.0", + "bundled": true, "dependencies": { "concat-stream": { - "version": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz", - "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=", + "version": "1.6.0", + "bundled": true, "dependencies": { "typedarray": { - "version": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + "version": "0.0.6", + "bundled": true } } }, "duplexify": { - "version": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.0.tgz", - "integrity": "sha1-GqdzAC4VeEV+nZ1KULDMquvL1gQ=", + "version": "3.5.0", + "bundled": true, "dependencies": { "end-of-stream": { - "version": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.0.0.tgz", - "integrity": "sha1-1FlucCc0qT5A6a+GQxnqvZn/Lw4=", + "version": "1.0.0", + "bundled": true, "dependencies": { "once": { - "version": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", - "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=" + "version": "1.3.3", + "bundled": true } } }, "stream-shift": { - "version": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", - "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=" + "version": "1.0.0", + "bundled": true } } }, "end-of-stream": { - "version": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.1.0.tgz", - "integrity": "sha1-6TUyWLqpEIll78QcsO+K3i88+wc=", + "version": "1.1.0", + "bundled": true, "dependencies": { "once": { - "version": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", - "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=" + "version": "1.3.3", + "bundled": true } } }, "flush-write-stream": { - "version": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.0.2.tgz", - "integrity": "sha1-yBuQ2HRnZvGmCaRoCZRsRd2K5Bc=" + "version": "1.0.2", + "bundled": true }, "from2": { - "version": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", - "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=" + "version": "2.3.0", + "bundled": true }, "parallel-transform": { - "version": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.1.0.tgz", - "integrity": "sha1-1BDwZbBdojCB/NEPKIVMKb2jOwY=", + "version": "1.1.0", + "bundled": true, "dependencies": { "cyclist": { - "version": "https://registry.npmjs.org/cyclist/-/cyclist-0.2.2.tgz", - "integrity": "sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA=" + "version": "0.2.2", + "bundled": true } } }, "pump": { - "version": "https://registry.npmjs.org/pump/-/pump-1.0.2.tgz", - "integrity": "sha1-Oz7mUS+U8OV1U4wXmV+fFpkKXVE=" + "version": "1.0.2", + "bundled": true }, "pumpify": { - "version": "https://registry.npmjs.org/pumpify/-/pumpify-1.3.5.tgz", - "integrity": "sha1-G2ccYZlAq8rqwK0OOjwWS+dgmTs=" + "version": "1.3.5", + "bundled": true }, "stream-each": { - "version": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.0.tgz", - "integrity": "sha1-HpXUdXP1gNgU3A/4zQ9m8c5TyZE=", + "version": "1.2.0", + "bundled": true, "dependencies": { "stream-shift": { - "version": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", - "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=" + "version": "1.0.0", + "bundled": true } } }, "through2": { - "version": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", - "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "version": "2.0.3", + "bundled": true, "dependencies": { "xtend": { - "version": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + "version": "4.0.1", + "bundled": true } } } @@ -484,92 +451,93 @@ }, "mkdirp": { "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "bundled": true, "dependencies": { "minimist": { "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + "bundled": true } } }, "move-concurrently": { - "version": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", - "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", + "version": "1.0.1", + "bundled": true, "dependencies": { "copy-concurrently": { - "version": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.3.tgz", - "integrity": "sha1-Rft4ZiSaHKiJqlcI5svSc+dbslA=" + "version": "1.0.3", + "bundled": true }, "run-queue": { - "version": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", - "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=" + "version": "1.0.3", + "bundled": true } } }, "node-gyp": { - "version": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.5.0.tgz", - "integrity": "sha1-qP5eYR0HnsFjSKPrlg544RyFJ0o=", + "version": "3.6.0", + "bundled": true, "dependencies": { "minimatch": { - "version": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.3.tgz", - "integrity": "sha1-Kk5AkLlrLbBqnX3wEFWmKnfJt3Q=", + "version": "3.0.3", + "bundled": true, "dependencies": { "brace-expansion": { - "version": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.6.tgz", - "integrity": "sha1-cZfX6qm4fmSDkOph/GbIRCdCDfk=", + "version": "1.1.6", + "bundled": true, "dependencies": { "balanced-match": { - "version": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", - "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=" + "version": "0.4.2", + "bundled": true }, "concat-map": { - "version": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + "version": "0.0.1", + "bundled": true } } } } }, "nopt": { - "version": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", - "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=" + "version": "3.0.6", + "bundled": true } } }, "nopt": { - "version": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz", - "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", + "version": "4.0.1", + "bundled": true, "dependencies": { "osenv": { - "version": "https://registry.npmjs.org/osenv/-/osenv-0.1.4.tgz", - "integrity": "sha1-Qv5tWVPfBsgGS+bxdsPQWqqjRkQ=", + "version": "0.1.4", + "bundled": true, "dependencies": { "os-homedir": { - "version": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" + "version": "1.0.2", + "bundled": true }, "os-tmpdir": { - "version": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" + "version": "1.0.2", + "bundled": true } } } } }, + "normalize-git-url": { + "version": "3.0.2", + "bundled": true + }, "normalize-package-data": { - "version": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.3.6.tgz", - "integrity": "sha1-SY+kIMlkAfeHQCuiHmAN75+YH/8=", + "version": "2.3.8", + "bundled": true, "dependencies": { "is-builtin-module": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", - "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "bundled": true, "dependencies": { "builtin-modules": { - "version": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", - "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=" + "version": "1.1.1", + "bundled": true } } } @@ -577,367 +545,371 @@ }, "npm-cache-filename": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/npm-cache-filename/-/npm-cache-filename-1.0.2.tgz", - "integrity": "sha1-3tMGxbC/yHCp6fr4I7xfKD4FrhE=" + "bundled": true + }, + "npm-install-checks": { + "version": "3.0.0", + "bundled": true }, "npm-package-arg": { - "version": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-4.2.1.tgz", - "integrity": "sha1-WTMD/eqF98Qid18X+et2cPaA4+w=" + "version": "4.2.1", + "bundled": true }, "npm-registry-client": { - "version": "https://registry.npmjs.org/npm-registry-client/-/npm-registry-client-7.4.6.tgz", - "integrity": "sha1-CqfFXxhjG5Qbe4CnqlAb/Lixlxc=", + "version": "8.1.1", + "bundled": true, "dependencies": { "concat-stream": { - "version": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz", - "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=", + "version": "1.6.0", + "bundled": true, "dependencies": { "typedarray": { "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + "bundled": true } } } } }, "npm-user-validate": { - "version": "https://registry.npmjs.org/npm-user-validate/-/npm-user-validate-0.1.5.tgz", - "integrity": "sha1-UkZdUMLSApSlcSW5lrrtv1bFAEs=" + "version": "0.1.5", + "bundled": true }, "npmlog": { - "version": "https://registry.npmjs.org/npmlog/-/npmlog-4.0.2.tgz", - "integrity": "sha1-0DlQ4OeM4VJ7om0qdZLpNIrD518=", + "version": "4.0.2", + "bundled": true, "dependencies": { "are-we-there-yet": { - "version": "http://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.2.tgz", - "integrity": "sha1-gORw6VoIR5T+GJkmLFZnxuiN4bM=", + "version": "1.1.4", + "bundled": true, "dependencies": { "delegates": { - "version": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" + "version": "1.0.0", + "bundled": true } } }, "console-control-strings": { - "version": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" + "version": "1.1.0", + "bundled": true }, "gauge": { - "version": "https://registry.npmjs.org/gauge/-/gauge-2.7.2.tgz", - "integrity": "sha1-Fc7MMbAtBTRaXWsOFxzbOtIwd3Q=", + "version": "2.7.4", + "bundled": true, "dependencies": { "object-assign": { - "version": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.0.tgz", - "integrity": "sha1-ejs9DpgGPUP0wD8uiubNUahog6A=" + "version": "4.1.1", + "bundled": true }, "signal-exit": { - "version": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" + "version": "3.0.2", + "bundled": true }, "string-width": { - "version": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "version": "1.0.2", + "bundled": true, "dependencies": { "code-point-at": { - "version": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + "version": "1.1.0", + "bundled": true }, "is-fullwidth-code-point": { - "version": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "version": "1.0.0", + "bundled": true, "dependencies": { "number-is-nan": { - "version": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + "version": "1.0.1", + "bundled": true } } } } }, - "supports-color": { - "version": "https://registry.npmjs.org/supports-color/-/supports-color-0.2.0.tgz", - "integrity": "sha1-2S3iaU6z9nMjlz1649i1W0wiGQo=" - }, "wide-align": { - "version": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.0.tgz", - "integrity": "sha1-QO3egCpx/qHwcNo+YtzaLnrdlq0=" + "version": "1.1.0", + "bundled": true } } }, "set-blocking": { - "version": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + "version": "2.0.0", + "bundled": true } } }, "once": { - "version": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=" + "version": "1.4.0", + "bundled": true }, "opener": { - "version": "https://registry.npmjs.org/opener/-/opener-1.4.3.tgz", - "integrity": "sha1-XG2ixdflgx6P+jlklQ+NZnSskLg=" + "version": "1.4.3", + "bundled": true }, "osenv": { - "version": "https://registry.npmjs.org/osenv/-/osenv-0.1.4.tgz", - "integrity": "sha1-Qv5tWVPfBsgGS+bxdsPQWqqjRkQ=", + "version": "0.1.4", + "bundled": true, "dependencies": { "os-homedir": { - "version": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" + "version": "1.0.2", + "bundled": true }, "os-tmpdir": { - "version": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" + "version": "1.0.2", + "bundled": true } } }, "path-is-inside": { - "version": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=" + "version": "1.0.2", + "bundled": true }, "read": { "version": "1.0.7", - "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", - "integrity": "sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ=", + "bundled": true, "dependencies": { "mute-stream": { "version": "0.0.5", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.5.tgz", - "integrity": "sha1-j7+rsKmKJT0xhDMfno3rc3L6xsA=" + "bundled": true } } }, "read-cmd-shim": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-cmd-shim/-/read-cmd-shim-1.0.1.tgz", - "integrity": "sha1-LV0Vd4ajfAVdIgd8MsU/gynpHHs=" + "bundled": true }, "read-installed": { "version": "4.0.3", - "resolved": "https://registry.npmjs.org/read-installed/-/read-installed-4.0.3.tgz", - "integrity": "sha1-/5uLZ/GH0eTCm5/rMfayI6zRkGc=", + "bundled": true, "dependencies": { "util-extend": { - "version": "https://registry.npmjs.org/util-extend/-/util-extend-1.0.3.tgz", - "integrity": "sha1-p8IW0mdUUWljeztu3GypEZ4v+T8=" + "version": "1.0.3", + "bundled": true } } }, "read-package-json": { - "version": "https://registry.npmjs.org/read-package-json/-/read-package-json-2.0.5.tgz", - "integrity": "sha1-+Tpk5kFSnfaKCMZN5GOJ6KP4iEU=", + "version": "2.0.5", + "bundled": true, "dependencies": { "json-parse-helpfulerror": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/json-parse-helpfulerror/-/json-parse-helpfulerror-1.0.3.tgz", - "integrity": "sha1-E/FM4C7tTpgSl7ZOueO5MuLdE9w=", + "bundled": true, "dependencies": { "jju": { - "version": "https://registry.npmjs.org/jju/-/jju-1.3.0.tgz", - "integrity": "sha1-2t2e8BkkvHKLA/L3l5vb1i96Kqo=" + "version": "1.3.0", + "bundled": true } } } } }, "read-package-tree": { - "version": "https://registry.npmjs.org/read-package-tree/-/read-package-tree-5.1.5.tgz", - "integrity": "sha1-rOfmOBx2hPlwqqmPx8XStmat2rY=" + "version": "5.1.5", + "bundled": true }, "readable-stream": { - "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.3.tgz", - "integrity": "sha1-nPSUY5hd8BbIrogTCXqSk6mzNyk=", + "version": "2.2.9", + "bundled": true, "dependencies": { "buffer-shims": { - "version": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz", - "integrity": "sha1-mXjOMXOIxkmth5MCjDR37wRKi1E=" + "version": "1.0.0", + "bundled": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true }, "isarray": { - "version": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + "version": "1.0.0", + "bundled": true }, "process-nextick-args": { - "version": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", - "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" + "version": "1.0.7", + "bundled": true + }, + "string_decoder": { + "version": "1.0.0", + "bundled": true }, "util-deprecate": { - "version": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + "version": "1.0.2", + "bundled": true } } }, "readdir-scoped-modules": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/readdir-scoped-modules/-/readdir-scoped-modules-1.0.2.tgz", - "integrity": "sha1-n6+jfShr5dksuuve4DDcm19AZ0c=" + "bundled": true + }, + "realize-package-specifier": { + "version": "3.0.3", + "bundled": true }, "request": { - "version": "https://registry.npmjs.org/request/-/request-2.81.0.tgz", - "integrity": "sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA=", + "version": "2.81.0", + "bundled": true, "dependencies": { "aws-sign2": { - "version": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", - "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=" + "version": "0.6.0", + "bundled": true }, "aws4": { - "version": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", - "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=" + "version": "1.6.0", + "bundled": true }, "caseless": { - "version": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + "version": "0.12.0", + "bundled": true }, "combined-stream": { - "version": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", - "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=", + "version": "1.0.5", + "bundled": true, "dependencies": { "delayed-stream": { - "version": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + "version": "1.0.0", + "bundled": true } } }, "extend": { - "version": "https://registry.npmjs.org/extend/-/extend-3.0.0.tgz", - "integrity": "sha1-WkdDU7nzNT3dgXbf03uRyDpG8dQ=" + "version": "3.0.0", + "bundled": true }, "forever-agent": { - "version": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + "version": "0.6.1", + "bundled": true }, "form-data": { - "version": "https://registry.npmjs.org/form-data/-/form-data-2.1.2.tgz", - "integrity": "sha1-icNTQAi5fq2ky7FX1Y9vXfAl6uQ=", + "version": "2.1.2", + "bundled": true, "dependencies": { "asynckit": { - "version": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + "version": "0.4.0", + "bundled": true } } }, "har-validator": { - "version": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz", - "integrity": "sha1-M0gdDxu/9gDdID11gSpqX7oALio=", + "version": "4.2.1", + "bundled": true, "dependencies": { "ajv": { - "version": "https://registry.npmjs.org/ajv/-/ajv-4.11.4.tgz", - "integrity": "sha1-6/OlXUsTLqYP9YR66F0u8GmWC0U=", + "version": "4.11.4", + "bundled": true, "dependencies": { "co": { - "version": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" + "version": "4.6.0", + "bundled": true }, "json-stable-stringify": { - "version": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", - "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", + "version": "1.0.1", + "bundled": true, "dependencies": { "jsonify": { - "version": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", - "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=" + "version": "0.0.0", + "bundled": true } } } } }, "har-schema": { - "version": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz", - "integrity": "sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4=" + "version": "1.0.5", + "bundled": true } } }, "hawk": { - "version": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", - "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", + "version": "3.1.3", + "bundled": true, "dependencies": { "boom": { - "version": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", - "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=" + "version": "2.10.1", + "bundled": true }, "cryptiles": { - "version": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", - "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=" + "version": "2.0.5", + "bundled": true }, "hoek": { - "version": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", - "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=" + "version": "2.16.3", + "bundled": true }, "sntp": { - "version": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", - "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=" + "version": "1.0.9", + "bundled": true } } }, "http-signature": { - "version": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", - "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", + "version": "1.1.1", + "bundled": true, "dependencies": { "assert-plus": { - "version": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", - "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=" + "version": "0.2.0", + "bundled": true }, "jsprim": { - "version": "https://registry.npmjs.org/jsprim/-/jsprim-1.3.1.tgz", - "integrity": "sha1-KnJW9wQSop7jZwqspiWZTE3P8lI=", + "version": "1.3.1", + "bundled": true, "dependencies": { "extsprintf": { - "version": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.0.2.tgz", - "integrity": "sha1-4QgOBljjALBilJkMxw4VAiNf1VA=" + "version": "1.0.2", + "bundled": true }, "json-schema": { - "version": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + "version": "0.2.3", + "bundled": true }, "verror": { - "version": "https://registry.npmjs.org/verror/-/verror-1.3.6.tgz", - "integrity": "sha1-z/XfEpRtKX0rqu+qJoniW+AcAFw=" + "version": "1.3.6", + "bundled": true } } }, "sshpk": { - "version": "https://registry.npmjs.org/sshpk/-/sshpk-1.11.0.tgz", - "integrity": "sha1-LY1eu0pvqyj/ujf6YqkPSj6lnXc=", + "version": "1.11.0", + "bundled": true, "dependencies": { "asn1": { - "version": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", - "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=" + "version": "0.2.3", + "bundled": true }, "assert-plus": { - "version": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + "version": "1.0.0", + "bundled": true }, "bcrypt-pbkdf": { - "version": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", - "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", + "version": "1.0.1", + "bundled": true, "optional": true }, "dashdash": { - "version": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=" + "version": "1.14.1", + "bundled": true }, "ecc-jsbn": { - "version": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", - "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", + "version": "0.1.1", + "bundled": true, "optional": true }, "getpass": { - "version": "https://registry.npmjs.org/getpass/-/getpass-0.1.6.tgz", - "integrity": "sha1-KD/9n8ElaECHUxHBtg6MQBhxEOY=" + "version": "0.1.6", + "bundled": true }, "jodid25519": { - "version": "https://registry.npmjs.org/jodid25519/-/jodid25519-1.0.2.tgz", - "integrity": "sha1-BtSRIlUJNBlHfUJWM2BuDpB4KWc=", + "version": "1.0.2", + "bundled": true, "optional": true }, "jsbn": { - "version": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "version": "0.1.1", + "bundled": true, "optional": true }, "tweetnacl": { - "version": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "version": "0.14.5", + "bundled": true, "optional": true } } @@ -945,190 +917,188 @@ } }, "is-typedarray": { - "version": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + "version": "1.0.0", + "bundled": true }, "isstream": { - "version": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + "version": "0.1.2", + "bundled": true }, "json-stringify-safe": { - "version": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + "version": "5.0.1", + "bundled": true }, "mime-types": { - "version": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.14.tgz", - "integrity": "sha1-9+99l1g/yvO30oK2+LVnnaselO4=", + "version": "2.1.14", + "bundled": true, "dependencies": { "mime-db": { - "version": "https://registry.npmjs.org/mime-db/-/mime-db-1.26.0.tgz", - "integrity": "sha1-6v/NDk/Gk1z4E02iRuLmw1MFrf8=" + "version": "1.26.0", + "bundled": true } } }, "oauth-sign": { - "version": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", - "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=" + "version": "0.8.2", + "bundled": true }, "performance-now": { - "version": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz", - "integrity": "sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU=" + "version": "0.2.0", + "bundled": true }, "qs": { - "version": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", - "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=" + "version": "6.4.0", + "bundled": true }, "safe-buffer": { - "version": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.0.1.tgz", - "integrity": "sha1-0mPKVGls2KMGtcplUekt5XkY++c=" + "version": "5.0.1", + "bundled": true }, "stringstream": { - "version": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", - "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=" + "version": "0.0.5", + "bundled": true }, "tough-cookie": { - "version": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.2.tgz", - "integrity": "sha1-8IH3bkyFcg5sN6X6ztc3FQ2EByo=", + "version": "2.3.2", + "bundled": true, "dependencies": { "punycode": { - "version": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + "version": "1.4.1", + "bundled": true } } }, "tunnel-agent": { - "version": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=" + "version": "0.6.0", + "bundled": true } } }, "retry": { - "version": "https://registry.npmjs.org/retry/-/retry-0.10.1.tgz", - "integrity": "sha1-52OI0heZLCUnUCQdPTlW/tmNj/Q=" + "version": "0.10.1", + "bundled": true }, "rimraf": { - "version": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.1.tgz", - "integrity": "sha1-wjOOxkPfeht/5cVPqG9XQopV8z0=" + "version": "2.6.1", + "bundled": true }, "semver": { - "version": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", - "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=" + "version": "5.3.0", + "bundled": true }, "sha": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/sha/-/sha-2.0.1.tgz", - "integrity": "sha1-YDCCL70smCOUn49y7WQR7lzyWq4=" + "bundled": true }, "slide": { "version": "1.1.6", - "resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz", - "integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=" + "bundled": true }, "sorted-object": { - "version": "https://registry.npmjs.org/sorted-object/-/sorted-object-2.0.1.tgz", - "integrity": "sha1-fWMfS9OnmKJK8d/8+/6DM3pd9fw=" + "version": "2.0.1", + "bundled": true }, "sorted-union-stream": { - "version": "https://registry.npmjs.org/sorted-union-stream/-/sorted-union-stream-2.1.3.tgz", - "integrity": "sha1-x3lMfgd4gAUv9xqNSi27Sppjisc=", + "version": "2.1.3", + "bundled": true, "dependencies": { "from2": { - "version": "https://registry.npmjs.org/from2/-/from2-1.3.0.tgz", - "integrity": "sha1-iEE7qqX5pZfP3pIh2GmGzTwGHf0=", + "version": "1.3.0", + "bundled": true, "dependencies": { "readable-stream": { - "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "version": "1.1.14", + "bundled": true, "dependencies": { "core-util-is": { - "version": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + "version": "1.0.2", + "bundled": true }, "isarray": { - "version": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + "version": "0.0.1", + "bundled": true }, "string_decoder": { - "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + "version": "0.10.31", + "bundled": true } } } } }, "stream-iterate": { - "version": "https://registry.npmjs.org/stream-iterate/-/stream-iterate-1.1.1.tgz", - "integrity": "sha1-XX0ZeqUryeJxtEVHyeOIsrGzODY=" + "version": "1.1.1", + "bundled": true } } }, "strip-ansi": { - "version": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=" + "version": "3.0.1", + "bundled": true }, "tar": { "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz", - "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=", + "bundled": true, "dependencies": { "block-stream": { "version": "0.0.8", - "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.8.tgz", - "integrity": "sha1-Boj0baK7+c/wxPaCJaDLlcvopGs=" + "bundled": true } } }, "text-table": { "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=" + "bundled": true }, "uid-number": { "version": "0.0.6", - "resolved": "https://registry.npmjs.org/uid-number/-/uid-number-0.0.6.tgz", - "integrity": "sha1-DqEOgDXo61uOREnwbaHHMGY7qoE=" + "bundled": true }, "umask": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/umask/-/umask-1.1.0.tgz", - "integrity": "sha1-8pzr8B31F5ErtY/5xOUP3o4zMg0=" + "bundled": true }, "unique-filename": { - "version": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.0.tgz", - "integrity": "sha1-0F8v5AMlYIcfMOk8vnNe6iAVFPM=" + "version": "1.1.0", + "bundled": true, + "dependencies": { + "unique-slug": { + "version": "2.0.0", + "bundled": true + } + } }, "unpipe": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + "bundled": true }, "update-notifier": { - "version": "https://registry.npmjs.org/update-notifier/-/update-notifier-2.1.0.tgz", - "integrity": "sha1-7AweU1NrdmR6JLd8uDlm2TFRI9k=", + "version": "2.1.0", + "bundled": true, "dependencies": { "boxen": { - "version": "https://registry.npmjs.org/boxen/-/boxen-1.0.0.tgz", - "integrity": "sha1-smlLrx9gX3CP8Bd8Ehk7IvKaqqs=", + "version": "1.0.0", + "bundled": true, "dependencies": { "ansi-align": { - "version": "https://registry.npmjs.org/ansi-align/-/ansi-align-1.1.0.tgz", - "integrity": "sha1-LwwWWIKXOa3V67FeawxuNCPwFro=", + "version": "1.1.0", + "bundled": true, "dependencies": { "string-width": { - "version": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "version": "1.0.2", + "bundled": true, "dependencies": { "code-point-at": { - "version": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + "version": "1.1.0", + "bundled": true }, "is-fullwidth-code-point": { - "version": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "version": "1.0.0", + "bundled": true, "dependencies": { "number-is-nan": { - "version": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + "version": "1.0.1", + "bundled": true } } } @@ -1137,94 +1107,94 @@ } }, "camelcase": { - "version": "https://registry.npmjs.org/camelcase/-/camelcase-4.0.0.tgz", - "integrity": "sha1-iw+Q1Evl4oG5A7mIc0m5JZXvB/I=" + "version": "4.0.0", + "bundled": true }, "cli-boxes": { - "version": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-1.0.0.tgz", - "integrity": "sha1-T6kXw+WclKAEzWH47lCdplFocUM=" + "version": "1.0.0", + "bundled": true }, "string-width": { - "version": "https://registry.npmjs.org/string-width/-/string-width-2.0.0.tgz", - "integrity": "sha1-Y1xUNsxypuDDh87KJ41OLuxSaH4=", + "version": "2.0.0", + "bundled": true, "dependencies": { "is-fullwidth-code-point": { - "version": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + "version": "2.0.0", + "bundled": true } } }, "term-size": { - "version": "https://registry.npmjs.org/term-size/-/term-size-0.1.1.tgz", - "integrity": "sha1-hzYLljlsq1dgljcUzaDQy+7K2co=", + "version": "0.1.1", + "bundled": true, "dependencies": { "execa": { - "version": "https://registry.npmjs.org/execa/-/execa-0.4.0.tgz", - "integrity": "sha1-TrZGejaglfq7KXD/nV4/t7zm68M=", + "version": "0.4.0", + "bundled": true, "dependencies": { "cross-spawn-async": { - "version": "https://registry.npmjs.org/cross-spawn-async/-/cross-spawn-async-2.2.5.tgz", - "integrity": "sha1-hF/wwINKPe2dFg2sptOQkGuyiMw=", + "version": "2.2.5", + "bundled": true, "dependencies": { "lru-cache": { - "version": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.0.2.tgz", - "integrity": "sha1-HRdnnAac2l0ECZGgnbwsDbN35V4=", + "version": "4.0.2", + "bundled": true, "dependencies": { "pseudomap": { - "version": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" + "version": "1.0.2", + "bundled": true }, "yallist": { - "version": "https://registry.npmjs.org/yallist/-/yallist-2.0.0.tgz", - "integrity": "sha1-MGxUODXwnuGkyyO3vOmrNByRzdQ=" + "version": "2.0.0", + "bundled": true } } } } }, "is-stream": { - "version": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + "version": "1.1.0", + "bundled": true }, "npm-run-path": { - "version": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-1.0.0.tgz", - "integrity": "sha1-9cMr9ZX+ga6Sfa7FLoL4sACsPI8=" + "version": "1.0.0", + "bundled": true }, "object-assign": { - "version": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + "version": "4.1.1", + "bundled": true }, "path-key": { - "version": "https://registry.npmjs.org/path-key/-/path-key-1.0.0.tgz", - "integrity": "sha1-XVPVeAGWRsDWiADbThRua9wqx68=" + "version": "1.0.0", + "bundled": true }, "strip-eof": { - "version": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=" + "version": "1.0.0", + "bundled": true } } } } }, "widest-line": { - "version": "https://registry.npmjs.org/widest-line/-/widest-line-1.0.0.tgz", - "integrity": "sha1-DAnIXCqUaD0Nfq+O4JfVZL8OEFw=", + "version": "1.0.0", + "bundled": true, "dependencies": { "string-width": { - "version": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "version": "1.0.2", + "bundled": true, "dependencies": { "code-point-at": { - "version": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + "version": "1.1.0", + "bundled": true }, "is-fullwidth-code-point": { - "version": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "version": "1.0.0", + "bundled": true, "dependencies": { "number-is-nan": { - "version": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + "version": "1.0.1", + "bundled": true } } } @@ -1235,170 +1205,170 @@ } }, "chalk": { - "version": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "version": "1.1.3", + "bundled": true, "dependencies": { "ansi-styles": { - "version": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" + "version": "2.2.1", + "bundled": true }, "escape-string-regexp": { - "version": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + "version": "1.0.5", + "bundled": true }, "has-ansi": { - "version": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=" + "version": "2.0.0", + "bundled": true }, "supports-color": { - "version": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" + "version": "2.0.0", + "bundled": true } } }, "configstore": { - "version": "https://registry.npmjs.org/configstore/-/configstore-3.0.0.tgz", - "integrity": "sha1-4bhmnBgDzMULVF6S+ObnmqgOAZY=", + "version": "3.0.0", + "bundled": true, "dependencies": { "dot-prop": { - "version": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.1.1.tgz", - "integrity": "sha1-qEk/C3te7sglJbXHWH+n3nyoWcE=", + "version": "4.1.1", + "bundled": true, "dependencies": { "is-obj": { - "version": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", - "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=" + "version": "1.0.1", + "bundled": true } } }, "unique-string": { - "version": "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz", - "integrity": "sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo=", + "version": "1.0.0", + "bundled": true, "dependencies": { "crypto-random-string": { - "version": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz", - "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=" + "version": "1.0.0", + "bundled": true } } } } }, "is-npm": { - "version": "https://registry.npmjs.org/is-npm/-/is-npm-1.0.0.tgz", - "integrity": "sha1-8vtjpl5JBbQGyGBydloaTceTufQ=" + "version": "1.0.0", + "bundled": true }, "latest-version": { - "version": "https://registry.npmjs.org/latest-version/-/latest-version-3.0.0.tgz", - "integrity": "sha1-MQTwCMDDkQhBB/haNEvGHjiXBkk=", + "version": "3.0.0", + "bundled": true, "dependencies": { "package-json": { - "version": "https://registry.npmjs.org/package-json/-/package-json-3.1.0.tgz", - "integrity": "sha1-zigZAP6AUhUMxnCcbABsGP2y83k=", + "version": "3.1.0", + "bundled": true, "dependencies": { "got": { - "version": "https://registry.npmjs.org/got/-/got-6.7.1.tgz", - "integrity": "sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA=", + "version": "6.7.1", + "bundled": true, "dependencies": { "create-error-class": { - "version": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz", - "integrity": "sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=", + "version": "3.0.2", + "bundled": true, "dependencies": { "capture-stack-trace": { - "version": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.0.tgz", - "integrity": "sha1-Sm+gc5nCa7pH8LJJa00PtAjFVQ0=" + "version": "1.0.0", + "bundled": true } } }, "duplexer3": { - "version": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", - "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=" + "version": "0.1.4", + "bundled": true }, "get-stream": { - "version": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=" + "version": "3.0.0", + "bundled": true }, "is-redirect": { - "version": "https://registry.npmjs.org/is-redirect/-/is-redirect-1.0.0.tgz", - "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=" + "version": "1.0.0", + "bundled": true }, "is-retry-allowed": { - "version": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz", - "integrity": "sha1-EaBgVotnM5REAz0BJaYaINVk+zQ=" + "version": "1.1.0", + "bundled": true }, "is-stream": { - "version": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + "version": "1.1.0", + "bundled": true }, "lowercase-keys": { - "version": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.0.tgz", - "integrity": "sha1-TjNms55/VFfjXxMkvfb4jQv8cwY=" + "version": "1.0.0", + "bundled": true }, "safe-buffer": { - "version": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.0.1.tgz", - "integrity": "sha1-0mPKVGls2KMGtcplUekt5XkY++c=" + "version": "5.0.1", + "bundled": true }, "timed-out": { - "version": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", - "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=" + "version": "4.0.1", + "bundled": true }, "unzip-response": { - "version": "https://registry.npmjs.org/unzip-response/-/unzip-response-2.0.1.tgz", - "integrity": "sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c=" + "version": "2.0.1", + "bundled": true }, "url-parse-lax": { - "version": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", - "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", + "version": "1.0.0", + "bundled": true, "dependencies": { "prepend-http": { - "version": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", - "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=" + "version": "1.0.4", + "bundled": true } } } } }, "registry-auth-token": { - "version": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.1.0.tgz", - "integrity": "sha1-mXwIJW4MeZmDe5DpRNs52KeQJ2s=", + "version": "3.1.0", + "bundled": true, "dependencies": { "rc": { - "version": "https://registry.npmjs.org/rc/-/rc-1.1.7.tgz", - "integrity": "sha1-xepWS7B6/5/TpbMukGwdOmWUD+o=", + "version": "1.1.7", + "bundled": true, "dependencies": { "deep-extend": { - "version": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.1.tgz", - "integrity": "sha1-7+QRPQgIX05vlod1mBD4B0aeIlM=" + "version": "0.4.1", + "bundled": true }, "minimist": { - "version": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + "version": "1.2.0", + "bundled": true }, "strip-json-comments": { - "version": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + "version": "2.0.1", + "bundled": true } } } } }, "registry-url": { - "version": "https://registry.npmjs.org/registry-url/-/registry-url-3.1.0.tgz", - "integrity": "sha1-PU74cPc93h138M+aOBQyRE4XSUI=", + "version": "3.1.0", + "bundled": true, "dependencies": { "rc": { - "version": "https://registry.npmjs.org/rc/-/rc-1.1.7.tgz", - "integrity": "sha1-xepWS7B6/5/TpbMukGwdOmWUD+o=", + "version": "1.1.7", + "bundled": true, "dependencies": { "deep-extend": { - "version": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.1.tgz", - "integrity": "sha1-7+QRPQgIX05vlod1mBD4B0aeIlM=" + "version": "0.4.1", + "bundled": true }, "minimist": { - "version": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + "version": "1.2.0", + "bundled": true }, "strip-json-comments": { - "version": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + "version": "2.0.1", + "bundled": true } } } @@ -1409,138 +1379,112 @@ } }, "lazy-req": { - "version": "https://registry.npmjs.org/lazy-req/-/lazy-req-2.0.0.tgz", - "integrity": "sha1-yUUKNj7N2i5vDHATKtTzf48G8rQ=" + "version": "2.0.0", + "bundled": true }, "semver-diff": { - "version": "https://registry.npmjs.org/semver-diff/-/semver-diff-2.1.0.tgz", - "integrity": "sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY=" + "version": "2.1.0", + "bundled": true }, "xdg-basedir": { - "version": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-3.0.0.tgz", - "integrity": "sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ=" + "version": "3.0.0", + "bundled": true } } }, "uuid": { - "version": "https://registry.npmjs.org/uuid/-/uuid-3.0.1.tgz", - "integrity": "sha1-ZUS7ot/ajBzxfmKaOjBeK7H+5sE=" + "version": "3.0.1", + "bundled": true }, "validate-npm-package-license": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz", - "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=", + "bundled": true, "dependencies": { "spdx-correct": { - "version": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz", - "integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=", + "version": "1.0.2", + "bundled": true, "dependencies": { "spdx-license-ids": { - "version": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.0.tgz", - "integrity": "sha1-tUndD2Pct0Whfi6joHQC4OMy0eI=" + "version": "1.2.0", + "bundled": true } } }, "spdx-expression-parse": { - "version": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.2.tgz", - "integrity": "sha1-1SsUtelnB3FECvIlvLVjEirEUvY=", + "version": "1.0.2", + "bundled": true, "dependencies": { "spdx-exceptions": { - "version": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-1.0.4.tgz", - "integrity": "sha1-IguEI5EZrpBFqJLbgag/TOFvgP0=" + "version": "1.0.4", + "bundled": true + }, + "spdx-license-ids": { + "version": "1.2.0", + "bundled": true } } } } }, "validate-npm-package-name": { - "version": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz", - "integrity": "sha1-X6kS2B630MdK/BQN5zF/DKffQ34=", + "version": "3.0.0", + "bundled": true, "dependencies": { "builtins": { - "version": "https://registry.npmjs.org/builtins/-/builtins-1.0.3.tgz", - "integrity": "sha1-y5T662HIaWRR2zZTThQi+U8K7og=" + "version": "1.0.3", + "bundled": true } } }, "which": { - "version": "https://registry.npmjs.org/which/-/which-1.2.12.tgz", - "integrity": "sha1-3me15FAmnxlJCe8j7OTr5Bb6EZI=", + "version": "1.2.14", + "bundled": true, "dependencies": { "isexe": { - "version": "https://registry.npmjs.org/isexe/-/isexe-1.1.2.tgz", - "integrity": "sha1-NvPiLmB1CSD15yQaR2qMakInWtA=" + "version": "2.0.0", + "bundled": true } } }, "wrappy": { - "version": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + "version": "1.0.2", + "bundled": true }, "write-file-atomic": { - "version": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-1.3.1.tgz", - "integrity": "sha1-fUW6MjFjKN0ex9kPYOvA2EW7dZo=" + "version": "1.3.3", + "bundled": true } } }, - "npm-install-checks": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-3.0.0.tgz", - "integrity": "sha1-1K7N/VGlPjcjt7L5Oy7ijjB7wNc=" - }, - "npm-package-arg": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-4.2.1.tgz", - "integrity": "sha1-WTMD/eqF98Qid18X+et2cPaA4+w=" - }, "path-exists": { - "version": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" }, "pupa": { - "version": "https://registry.npmjs.org/pupa/-/pupa-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/pupa/-/pupa-1.0.0.tgz", "integrity": "sha1-mpVopa9+ZXuEYqbp1TKHQ1YM7/Y=" }, - "realize-package-specifier": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/realize-package-specifier/-/realize-package-specifier-3.0.3.tgz", - "integrity": "sha1-0N74gpUrjeP2frpekRmWYScfQfQ=" - }, "semver": { - "version": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=" }, - "spdx-license-ids": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz", - "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=" - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" - }, "through": { - "version": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" }, "tree-kill": { - "version": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.1.0.tgz", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.1.0.tgz", "integrity": "sha1-yWPc8DciiS7FnLpWnpQLcZVNFyk=" }, - "unique-slug": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.0.tgz", - "integrity": "sha1-22Z258fMBimHj/GWCXx4hVrp9Ks=" - }, "unused-filename": { - "version": "https://registry.npmjs.org/unused-filename/-/unused-filename-0.1.0.tgz", + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/unused-filename/-/unused-filename-0.1.0.tgz", "integrity": "sha1-5fM7yeSmP4f2TTwR0xl53vXS5/s=" - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" } } } diff --git a/package-lock.json b/package-lock.json index 4732ba8a6..5f5e82c88 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,9 +1,16 @@ { "lockfileVersion": 1, "dependencies": { + "@types/node": { + "version": "7.0.29", + "resolved": "https://registry.npmjs.org/@types/node/-/node-7.0.29.tgz", + "integrity": "sha512-+8JrLZny/uR+d/jLK9eaV63buRM7X/gNzQk57q76NS4KNKLSKOmxJYFIlwuP2zDvA7wqZj05POPhSd9Z1hYQpQ==", + "dev": true + }, "7zip-bin": { - "version": "https://registry.npmjs.org/7zip-bin/-/7zip-bin-2.0.4.tgz", - "integrity": "sha1-DNKKwzAbEwL72ZkiusuLrZgQPhI=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/7zip-bin/-/7zip-bin-2.1.0.tgz", + "integrity": "sha512-jgBTCcJ0gQedE9o8Jw+H/Gyq//EnQxmVpha7CdprIwzRSC81Uj37inHvPzv6jaZgZwkCcfho52rAaIFBrdbO7w==", "dev": true }, "7zip-bin-linux": { @@ -14,7 +21,8 @@ "optional": true }, "7zip-bin-mac": { - "version": "https://registry.npmjs.org/7zip-bin-mac/-/7zip-bin-mac-1.0.1.tgz", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/7zip-bin-mac/-/7zip-bin-mac-1.0.1.tgz", "integrity": "sha1-Pmh3i78JJq3GgVlCcHRQXUdVXAI=", "dev": true, "optional": true @@ -27,1408 +35,1728 @@ "optional": true }, "ajv": { - "version": "https://registry.npmjs.org/ajv/-/ajv-4.11.6.tgz", - "integrity": "sha1-lH6TBJeQlCsqLWCoKJsokk05+Yc=", + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", + "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", "dev": true }, "ansi-align": { - "version": "https://registry.npmjs.org/ansi-align/-/ansi-align-1.1.0.tgz", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-1.1.0.tgz", "integrity": "sha1-LwwWWIKXOa3V67FeawxuNCPwFro=", "dev": true }, "ansi-regex": { - "version": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", "dev": true }, "ansi-styles": { - "version": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", "dev": true }, "argparse": { - "version": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz", "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=", "dev": true }, "array-find-index": { - "version": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", "dev": true }, "asar-electron-builder": { - "version": "https://registry.npmjs.org/asar-electron-builder/-/asar-electron-builder-0.13.5.tgz", + "version": "0.13.5", + "resolved": "https://registry.npmjs.org/asar-electron-builder/-/asar-electron-builder-0.13.5.tgz", "integrity": "sha1-TM1NEf18nTs8/8eC/ePe7Z75GvY=", "dev": true, "dependencies": { "minimist": { - "version": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", "dev": true }, "mkdirp": { - "version": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", "dev": true } } }, "asn1": { - "version": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=", "dev": true }, "assert-plus": { - "version": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=", "dev": true }, "asynckit": { - "version": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", "dev": true }, "aws-sign2": { - "version": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=", "dev": true }, "aws4": { - "version": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=", "dev": true }, "balanced-match": { - "version": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=", "dev": true }, "base64-js": { - "version": "https://registry.npmjs.org/base64-js/-/base64-js-1.1.2.tgz", - "integrity": "sha1-1kAMrBxMZgl22Q0HoENR2JOV9eg=", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.0.tgz", + "integrity": "sha1-o5mS1yNYSBGYK+XikLtqU9hnAPE=", "dev": true }, "bcrypt-pbkdf": { - "version": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", "dev": true, "optional": true }, "bluebird": { - "version": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.0.tgz", + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.0.tgz", "integrity": "sha1-eRQg1/VR7qKJdFOop3ZT+WYG1nw=", "dev": true }, "bluebird-lst-c": { - "version": "https://registry.npmjs.org/bluebird-lst-c/-/bluebird-lst-c-1.0.6.tgz", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/bluebird-lst-c/-/bluebird-lst-c-1.0.6.tgz", "integrity": "sha1-gfiB0T+d9wD2fVd/E0gLwy2Eu6k=", "dev": true }, "boom": { - "version": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", "dev": true }, "boxen": { - "version": "https://registry.npmjs.org/boxen/-/boxen-0.6.0.tgz", + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-0.6.0.tgz", "integrity": "sha1-g2TUJIrDT/DvGy8r9JpsYM4NgbY=", "dev": true }, "brace-expansion": { - "version": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.7.tgz", + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.7.tgz", "integrity": "sha1-Pv/DxQ4ABTH7cg6v+A8K6O8jz1k=", "dev": true }, - "buffer-shims": { - "version": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz", - "integrity": "sha1-mXjOMXOIxkmth5MCjDR37wRKi1E=", - "dev": true - }, "builtin-modules": { - "version": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", "dev": true }, "camelcase": { - "version": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", "dev": true }, "camelcase-keys": { - "version": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", "dev": true }, "capture-stack-trace": { - "version": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.0.tgz", "integrity": "sha1-Sm+gc5nCa7pH8LJJa00PtAjFVQ0=", "dev": true }, "caseless": { - "version": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", "dev": true }, "chalk": { - "version": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true }, "chromium-pickle-js": { - "version": "https://registry.npmjs.org/chromium-pickle-js/-/chromium-pickle-js-0.2.0.tgz", + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/chromium-pickle-js/-/chromium-pickle-js-0.2.0.tgz", "integrity": "sha1-BKEGZywYsIWrd02YPfo+oTjyIgU=", "dev": true }, "ci-info": { - "version": "https://registry.npmjs.org/ci-info/-/ci-info-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.0.0.tgz", "integrity": "sha1-3FKF8rTiUYIWg2gcOBwziPRuxTQ=", "dev": true }, "cli-boxes": { - "version": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-1.0.0.tgz", "integrity": "sha1-T6kXw+WclKAEzWH47lCdplFocUM=", "dev": true }, "cliui": { - "version": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", "dev": true }, "co": { - "version": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", "dev": true }, "code-point-at": { - "version": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", "dev": true }, "color-convert": { - "version": "https://registry.npmjs.org/color-convert/-/color-convert-0.5.3.tgz", + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-0.5.3.tgz", "integrity": "sha1-vbbGnOZg+t/+CwAHzER+G59ygr0=", "dev": true }, "combined-stream": { - "version": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=", "dev": true }, "commander": { - "version": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", "dev": true }, "compare-version": { - "version": "https://registry.npmjs.org/compare-version/-/compare-version-0.1.2.tgz", + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/compare-version/-/compare-version-0.1.2.tgz", "integrity": "sha1-AWLsLZNR9d3VmpICy6k1NmpyUIA=", "dev": true }, "concat-map": { - "version": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true }, "concat-stream": { - "version": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.5.0.tgz", - "integrity": "sha1-U/fUPFHF5D+ByP3QMyHGMb5o1hE=", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz", + "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=", "dev": true, "dependencies": { "isarray": { - "version": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true }, "readable-stream": { - "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", - "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", + "version": "2.2.11", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.11.tgz", + "integrity": "sha512-h+8+r3MKEhkiVrwdKL8aWs1oc1VvBu33ueshOvS26RsZQ3Amhx/oO3TKe4lApSV9ueY6as8EAh7mtuFjdlhg9Q==", + "dev": true + }, + "safe-buffer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.0.1.tgz", + "integrity": "sha1-0mPKVGls2KMGtcplUekt5XkY++c=", + "dev": true + }, + "string_decoder": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.2.tgz", + "integrity": "sha1-sp4fThEl+pehA4K4pTNze3SR4Xk=", "dev": true } } }, "configstore": { - "version": "https://registry.npmjs.org/configstore/-/configstore-2.1.0.tgz", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-2.1.0.tgz", "integrity": "sha1-c3o6cDbpiGECqmCZ5HuzOrGroaE=", "dev": true, "dependencies": { "uuid": { - "version": "https://registry.npmjs.org/uuid/-/uuid-2.0.3.tgz", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.3.tgz", "integrity": "sha1-Z+LoY3lyFVMN/zGOW/nc6/1Hsho=", "dev": true } } }, "core-util-is": { - "version": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", "dev": true }, "create-error-class": { - "version": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz", "integrity": "sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=", "dev": true }, "cryptiles": { - "version": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", "dev": true }, "cuint": { - "version": "https://registry.npmjs.org/cuint/-/cuint-0.2.2.tgz", + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/cuint/-/cuint-0.2.2.tgz", "integrity": "sha1-QICG1AlVDCYxFVYZ6fp7ytw7mRs=", "dev": true }, "currently-unhandled": { - "version": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", "dev": true }, "dashdash": { - "version": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", "dev": true, "dependencies": { "assert-plus": { - "version": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", "dev": true } } }, "debug": { - "version": "https://registry.npmjs.org/debug/-/debug-2.6.3.tgz", - "integrity": "sha1-D364wwll7AjHKsz6ATDIt5mEFB0=", + "version": "2.6.8", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", + "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", "dev": true }, "decamelize": { - "version": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", "dev": true }, "deep-extend": { - "version": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.1.tgz", - "integrity": "sha1-7+QRPQgIX05vlod1mBD4B0aeIlM=", + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.2.tgz", + "integrity": "sha1-SLaZwn4zS/ifEIkr5DL25MfTSn8=", "dev": true }, "delayed-stream": { - "version": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", "dev": true }, "dot-prop": { - "version": "https://registry.npmjs.org/dot-prop/-/dot-prop-3.0.0.tgz", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-3.0.0.tgz", "integrity": "sha1-G3CK8JSknJoOfbyteQq6U52sEXc=", "dev": true }, "duplexer2": { - "version": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", "dev": true, "dependencies": { "isarray": { - "version": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true }, "readable-stream": { - "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.9.tgz", - "integrity": "sha1-z3jsb0ptHrQ9JkiMrJfwQudLf8g=", + "version": "2.2.11", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.11.tgz", + "integrity": "sha512-h+8+r3MKEhkiVrwdKL8aWs1oc1VvBu33ueshOvS26RsZQ3Amhx/oO3TKe4lApSV9ueY6as8EAh7mtuFjdlhg9Q==", + "dev": true + }, + "safe-buffer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.0.1.tgz", + "integrity": "sha1-0mPKVGls2KMGtcplUekt5XkY++c=", "dev": true }, "string_decoder": { - "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.0.tgz", - "integrity": "sha1-8G9BFXtmTYYGn4S9vcmw2KsoFmc=", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.2.tgz", + "integrity": "sha1-sp4fThEl+pehA4K4pTNze3SR4Xk=", "dev": true } } }, "ecc-jsbn": { - "version": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", "dev": true, "optional": true }, "electron": { - "version": "https://registry.npmjs.org/electron/-/electron-1.6.2.tgz", - "integrity": "sha1-sMzXcD+G0JxNKnJzRVw/mT8ViZQ=", + "version": "1.6.10", + "resolved": "https://registry.npmjs.org/electron/-/electron-1.6.10.tgz", + "integrity": "sha1-Twuc1ZbjVwC1cSj5iMwdLOZ+VnE=", "dev": true }, "electron-builder": { - "version": "https://registry.npmjs.org/electron-builder/-/electron-builder-11.7.0.tgz", + "version": "11.7.0", + "resolved": "https://registry.npmjs.org/electron-builder/-/electron-builder-11.7.0.tgz", "integrity": "sha1-1SkS9uhKxSoGXeGXqS3vkxvZ3CU=", "dev": true, "dependencies": { "electron-download-tf": { - "version": "https://registry.npmjs.org/electron-download-tf/-/electron-download-tf-3.1.0.tgz", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/electron-download-tf/-/electron-download-tf-3.1.0.tgz", "integrity": "sha1-xtYsDgpMY7ZylfV7a2ZRTBO47Y0=", "dev": true }, "fs-extra": { - "version": "https://registry.npmjs.org/fs-extra/-/fs-extra-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-1.0.0.tgz", "integrity": "sha1-zTzl9+fLYUWIP8rjGR6Yd/hYeVA=", "dev": true }, "path-exists": { - "version": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", "dev": true }, "tunnel-agent": { - "version": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=", "dev": true } } }, "electron-builder-core": { - "version": "https://registry.npmjs.org/electron-builder-core/-/electron-builder-core-11.2.1.tgz", + "version": "11.2.1", + "resolved": "https://registry.npmjs.org/electron-builder-core/-/electron-builder-core-11.2.1.tgz", "integrity": "sha1-HcqMGhzui1F1C3cIoEkTrv+s+Kg=", "dev": true }, "electron-builder-http": { - "version": "https://registry.npmjs.org/electron-builder-http/-/electron-builder-http-11.5.0.tgz", + "version": "11.5.0", + "resolved": "https://registry.npmjs.org/electron-builder-http/-/electron-builder-http-11.5.0.tgz", "integrity": "sha1-t3OWY0kDREMp7aO7zQIyFEDgYDg=", "dev": true, "dependencies": { "debug": { - "version": "https://registry.npmjs.org/debug/-/debug-2.6.0.tgz", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.0.tgz", "integrity": "sha1-vFlryr52F/Edn6FTYe3tVgi4SZs=", "dev": true + }, + "ms": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz", + "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=", + "dev": true } } }, "electron-builder-util": { - "version": "https://registry.npmjs.org/electron-builder-util/-/electron-builder-util-11.6.1.tgz", + "version": "11.6.1", + "resolved": "https://registry.npmjs.org/electron-builder-util/-/electron-builder-util-11.6.1.tgz", "integrity": "sha1-D1VvZ6cOTI11GFVp7yp1ZtsBXsw=", "dev": true, "dependencies": { "debug": { - "version": "https://registry.npmjs.org/debug/-/debug-2.6.0.tgz", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.0.tgz", "integrity": "sha1-vFlryr52F/Edn6FTYe3tVgi4SZs=", "dev": true + }, + "ms": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz", + "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=", + "dev": true } } }, "electron-debug": { - "version": "https://registry.npmjs.org/electron-debug/-/electron-debug-1.1.0.tgz", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/electron-debug/-/electron-debug-1.1.0.tgz", "integrity": "sha1-BQqcP5Bv/8JJJRDPisMdDzKleeE=", "dev": true }, "electron-download": { - "version": "https://registry.npmjs.org/electron-download/-/electron-download-3.3.0.tgz", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/electron-download/-/electron-download-3.3.0.tgz", "integrity": "sha1-LP1U1pZsAZxNSa1l++Zcyc3vaMg=", "dev": true }, "electron-is-dev": { - "version": "https://registry.npmjs.org/electron-is-dev/-/electron-is-dev-0.1.2.tgz", + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/electron-is-dev/-/electron-is-dev-0.1.2.tgz", "integrity": "sha1-ihBD4ys6HaHD9VPc4oznZCRhZ+M=", "dev": true }, "electron-localshortcut": { - "version": "https://registry.npmjs.org/electron-localshortcut/-/electron-localshortcut-0.6.1.tgz", + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/electron-localshortcut/-/electron-localshortcut-0.6.1.tgz", "integrity": "sha1-xOJow4puQvQN5WGPyQbR7WCPEao=", "dev": true }, "electron-macos-sign": { - "version": "https://registry.npmjs.org/electron-macos-sign/-/electron-macos-sign-1.5.0.tgz", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/electron-macos-sign/-/electron-macos-sign-1.5.0.tgz", "integrity": "sha1-/jqKy3VbX1aPH+FE6eZs7kQBlEg=", "dev": true }, "error-ex": { - "version": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", "dev": true }, "es6-promise": { - "version": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.1.0.tgz", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.1.0.tgz", "integrity": "sha1-3aA8qPn4m8WX5omEKSnee6jOvfA=", "dev": true }, "escape-string-regexp": { - "version": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", "dev": true }, "esprima": { - "version": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", "dev": true }, "extend": { - "version": "https://registry.npmjs.org/extend/-/extend-3.0.0.tgz", - "integrity": "sha1-WkdDU7nzNT3dgXbf03uRyDpG8dQ=", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", "dev": true }, "extract-zip": { - "version": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.6.0.tgz", - "integrity": "sha1-f0AMlgfqhm7Kt6ptVPuXjusRYho=", + "version": "1.6.5", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.6.5.tgz", + "integrity": "sha1-maBnNbbqIOqbcF13ms/8yHz/BEA=", "dev": true, "dependencies": { "debug": { - "version": "https://registry.npmjs.org/debug/-/debug-0.7.4.tgz", - "integrity": "sha1-BuHqgILCyxTjmAbiLi9vdX+Srzk=", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "dev": true + }, + "ms": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", "dev": true } } }, "extsprintf": { - "version": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.0.2.tgz", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.0.2.tgz", "integrity": "sha1-4QgOBljjALBilJkMxw4VAiNf1VA=", "dev": true }, "fd-slicer": { - "version": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz", "integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=", "dev": true }, "filled-array": { - "version": "https://registry.npmjs.org/filled-array/-/filled-array-1.1.0.tgz", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/filled-array/-/filled-array-1.1.0.tgz", "integrity": "sha1-w8T2xmO5I0WamqKZEtLQMfFQf4Q=", "dev": true }, "find-up": { - "version": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", "dev": true }, "forever-agent": { - "version": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", "dev": true }, "form-data": { - "version": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", "dev": true }, "fs-extra": { - "version": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz", + "version": "0.30.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz", "integrity": "sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A=", "dev": true }, "fs-extra-p": { - "version": "https://registry.npmjs.org/fs-extra-p/-/fs-extra-p-3.1.0.tgz", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/fs-extra-p/-/fs-extra-p-3.1.0.tgz", "integrity": "sha1-7d97uNk4XXkBTeyyH0Wx0MV5ANM=", "dev": true, "dependencies": { "fs-extra": { - "version": "https://registry.npmjs.org/fs-extra/-/fs-extra-2.1.2.tgz", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-2.1.2.tgz", "integrity": "sha1-BGxwFjzvmq1GsOSn+kZ/si1x3jU=", "dev": true } } }, "fs.realpath": { - "version": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true }, "get-caller-file": { - "version": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=", "dev": true }, "get-stdin": { - "version": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", "dev": true }, "getpass": { - "version": "https://registry.npmjs.org/getpass/-/getpass-0.1.6.tgz", - "integrity": "sha1-KD/9n8ElaECHUxHBtg6MQBhxEOY=", + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", "dev": true, "dependencies": { "assert-plus": { - "version": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", "dev": true } } }, "glob": { - "version": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz", - "integrity": "sha1-gFIR3wT6rxxjo2ADBs31reULLsg=", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", "dev": true }, "got": { - "version": "https://registry.npmjs.org/got/-/got-5.7.1.tgz", + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/got/-/got-5.7.1.tgz", "integrity": "sha1-X4FjWmHkplifGAVp6k44FoClHzU=", "dev": true, "dependencies": { "isarray": { - "version": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true }, "readable-stream": { - "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.9.tgz", - "integrity": "sha1-z3jsb0ptHrQ9JkiMrJfwQudLf8g=", + "version": "2.2.11", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.11.tgz", + "integrity": "sha512-h+8+r3MKEhkiVrwdKL8aWs1oc1VvBu33ueshOvS26RsZQ3Amhx/oO3TKe4lApSV9ueY6as8EAh7mtuFjdlhg9Q==", + "dev": true + }, + "safe-buffer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.0.1.tgz", + "integrity": "sha1-0mPKVGls2KMGtcplUekt5XkY++c=", "dev": true }, "string_decoder": { - "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.0.tgz", - "integrity": "sha1-8G9BFXtmTYYGn4S9vcmw2KsoFmc=", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.2.tgz", + "integrity": "sha1-sp4fThEl+pehA4K4pTNze3SR4Xk=", "dev": true } } }, "graceful-fs": { - "version": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", "dev": true }, "graceful-readlink": { - "version": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", "dev": true }, "har-schema": { - "version": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz", "integrity": "sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4=", "dev": true }, "har-validator": { - "version": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz", "integrity": "sha1-M0gdDxu/9gDdID11gSpqX7oALio=", "dev": true }, "has-ansi": { - "version": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", "dev": true }, "hawk": { - "version": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", "dev": true }, "hoek": { - "version": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", + "version": "2.16.3", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=", "dev": true }, "home-path": { - "version": "https://registry.npmjs.org/home-path/-/home-path-1.0.5.tgz", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/home-path/-/home-path-1.0.5.tgz", "integrity": "sha1-eIspgVsS1Tus9XVkhHbm+QQdEz8=", "dev": true }, "hosted-git-info": { - "version": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.4.1.tgz", - "integrity": "sha1-SwRF5BwASovRM3dzpP95DKQDGMg=", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.4.2.tgz", + "integrity": "sha1-AHa59GonBQbduq6lZJaJdGBhKmc=", "dev": true }, "http-signature": { - "version": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", "dev": true }, "imurmurhash": { - "version": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", "dev": true }, "indent-string": { - "version": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", "dev": true }, "inflight": { - "version": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "dev": true }, "inherits": { - "version": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", "dev": true }, "ini": { - "version": "https://registry.npmjs.org/ini/-/ini-1.3.4.tgz", + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.4.tgz", "integrity": "sha1-BTfLedr1m1mhpRff9wbIbsA5Fi4=", "dev": true }, "invert-kv": { - "version": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", "dev": true }, "is-arrayish": { - "version": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", "dev": true }, "is-builtin-module": { - "version": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", "dev": true }, "is-ci": { - "version": "https://registry.npmjs.org/is-ci/-/is-ci-1.0.10.tgz", + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.0.10.tgz", "integrity": "sha1-9zkzayYyNlBhqdSCcM1WrjNpMY4=", "dev": true }, "is-finite": { - "version": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", "dev": true }, "is-fullwidth-code-point": { - "version": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "dev": true }, "is-npm": { - "version": "https://registry.npmjs.org/is-npm/-/is-npm-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-1.0.0.tgz", "integrity": "sha1-8vtjpl5JBbQGyGBydloaTceTufQ=", "dev": true }, "is-obj": { - "version": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", "dev": true }, "is-redirect": { - "version": "https://registry.npmjs.org/is-redirect/-/is-redirect-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-redirect/-/is-redirect-1.0.0.tgz", "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=", "dev": true }, "is-retry-allowed": { - "version": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz", "integrity": "sha1-EaBgVotnM5REAz0BJaYaINVk+zQ=", "dev": true }, "is-stream": { - "version": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", "dev": true }, "is-typedarray": { - "version": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", "dev": true }, "is-utf8": { - "version": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", "dev": true }, "isarray": { - "version": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", "dev": true }, "isbinaryfile": { - "version": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-3.0.2.tgz", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-3.0.2.tgz", "integrity": "sha1-Sj6XTsDLqQBNP8bN5yCeppNopiE=", "dev": true }, "isstream": { - "version": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", "dev": true }, - "jodid25519": { - "version": "https://registry.npmjs.org/jodid25519/-/jodid25519-1.0.2.tgz", - "integrity": "sha1-BtSRIlUJNBlHfUJWM2BuDpB4KWc=", - "dev": true, - "optional": true - }, "js-yaml": { - "version": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.8.3.tgz", - "integrity": "sha1-M6BexIHIUMiHWSkWb+G+thxyh2Y=", + "version": "3.8.4", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.8.4.tgz", + "integrity": "sha1-UgtFZPhlc7qWZir4Woyvp7S1pvY=", "dev": true }, "jsbn": { - "version": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", "dev": true, "optional": true }, "json-schema": { - "version": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", "dev": true }, "json-stable-stringify": { - "version": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", "dev": true }, "json-stringify-safe": { - "version": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", "dev": true }, "jsonfile": { - "version": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", "dev": true }, "jsonify": { - "version": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", "dev": true }, "jsprim": { - "version": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.0.tgz", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.0.tgz", "integrity": "sha1-o7h+QCmNjDgFUtjMdiigu5WiKRg=", "dev": true, "dependencies": { "assert-plus": { - "version": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", "dev": true } } }, "klaw": { - "version": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", "dev": true }, "latest-version": { - "version": "https://registry.npmjs.org/latest-version/-/latest-version-2.0.0.tgz", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-2.0.0.tgz", "integrity": "sha1-VvjWE5YghHuAF/jx9NeOIRMkFos=", "dev": true }, "lazy-req": { - "version": "https://registry.npmjs.org/lazy-req/-/lazy-req-1.1.0.tgz", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/lazy-req/-/lazy-req-1.1.0.tgz", "integrity": "sha1-va6+rTD42CQDnODOFJ1Nqge6H6w=", "dev": true }, "lcid": { - "version": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", "dev": true }, "load-json-file": { - "version": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", "dev": true }, + "lodash": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.12.0.tgz", + "integrity": "sha1-K9bcRqBA9Z5obJcu0h2T3FkFMlg=", + "dev": true + }, "loud-rejection": { - "version": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", "dev": true }, "lowercase-keys": { - "version": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.0.tgz", "integrity": "sha1-TjNms55/VFfjXxMkvfb4jQv8cwY=", "dev": true }, "macaddress": { - "version": "https://registry.npmjs.org/macaddress/-/macaddress-0.2.8.tgz", + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/macaddress/-/macaddress-0.2.8.tgz", "integrity": "sha1-WQTcU3w57G2+/q6QIycTX6hRHxI=", "dev": true }, "map-obj": { - "version": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", "dev": true }, "meow": { - "version": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", "dev": true }, "mime": { - "version": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz", - "integrity": "sha1-EV+eO2s9rylZmDyzjxSaLUDrXVM=", + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.3.6.tgz", + "integrity": "sha1-WR2E02U6awtKO5343lqoEI5y5eA=", "dev": true }, "mime-db": { - "version": "https://registry.npmjs.org/mime-db/-/mime-db-1.27.0.tgz", + "version": "1.27.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.27.0.tgz", "integrity": "sha1-gg9XIpa70g7CXtVeW13oaeVDbrE=", "dev": true }, "mime-types": { - "version": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.15.tgz", + "version": "2.1.15", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.15.tgz", "integrity": "sha1-pOv1BkCUVpI3uM9wBGd20J/JKu0=", "dev": true }, "minimatch": { - "version": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.3.tgz", - "integrity": "sha1-Kk5AkLlrLbBqnX3wEFWmKnfJt3Q=", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true }, "minimist": { - "version": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true }, "mkdirp": { - "version": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz", + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz", "integrity": "sha1-HXMHam35hs2TROFecfzAWkyavxI=", "dev": true, "dependencies": { "minimist": { - "version": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", "dev": true } } }, "ms": { - "version": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz", - "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true }, "node-emoji": { - "version": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.5.1.tgz", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.5.1.tgz", "integrity": "sha1-/ZGOQSdpv4xEgFEjgjOECyr/FqE=", "dev": true }, "node-status-codes": { - "version": "https://registry.npmjs.org/node-status-codes/-/node-status-codes-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-status-codes/-/node-status-codes-1.0.0.tgz", "integrity": "sha1-WuVUHQJGRdMqWPzdyc7s6nrjrC8=", "dev": true }, "normalize-package-data": { - "version": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.3.6.tgz", - "integrity": "sha1-SY+kIMlkAfeHQCuiHmAN75+YH/8=", + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.3.8.tgz", + "integrity": "sha1-2Bntoqne29H/pWPqQHHZNngilbs=", "dev": true }, "nugget": { - "version": "https://registry.npmjs.org/nugget/-/nugget-2.0.1.tgz", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/nugget/-/nugget-2.0.1.tgz", "integrity": "sha1-IBCVpIfhrTYIGzQy+jytpPjQcbA=", "dev": true }, "number-is-nan": { - "version": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", "dev": true }, "oauth-sign": { - "version": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", "dev": true }, "object-assign": { - "version": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", "dev": true }, "object-keys": { - "version": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=", "dev": true }, "once": { - "version": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true }, "os-homedir": { - "version": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", "dev": true }, "os-locale": { - "version": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", "dev": true }, "os-tmpdir": { - "version": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "dev": true }, "osenv": { - "version": "https://registry.npmjs.org/osenv/-/osenv-0.1.4.tgz", + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.4.tgz", "integrity": "sha1-Qv5tWVPfBsgGS+bxdsPQWqqjRkQ=", "dev": true }, "package-json": { - "version": "https://registry.npmjs.org/package-json/-/package-json-2.4.0.tgz", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-2.4.0.tgz", "integrity": "sha1-DRW9Z9HLvduyyiIv8u24a8sxqLs=", "dev": true }, "parse-color": { - "version": "https://registry.npmjs.org/parse-color/-/parse-color-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-color/-/parse-color-1.0.0.tgz", "integrity": "sha1-e3SLlag/A/FqlPU15S1/PZRlhhk=", "dev": true }, "parse-json": { - "version": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", "dev": true }, "path-exists": { - "version": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", "dev": true }, "path-is-absolute": { - "version": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true }, "path-type": { - "version": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", "dev": true }, "pend": { - "version": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", "dev": true }, "performance-now": { - "version": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz", + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz", "integrity": "sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU=", "dev": true }, "pify": { - "version": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true }, "pinkie": { - "version": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", "dev": true }, "pinkie-promise": { - "version": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", "dev": true }, "plist": { - "version": "https://registry.npmjs.org/plist/-/plist-2.0.1.tgz", - "integrity": "sha1-CjLKlIGxw2TpLhjcVch23p0B2os=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/plist/-/plist-2.1.0.tgz", + "integrity": "sha1-V8zbeggh3yGDEhejytVOPhRqECU=", "dev": true }, "prepend-http": { - "version": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", "dev": true }, "pretty-bytes": { - "version": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-1.0.4.tgz", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-1.0.4.tgz", "integrity": "sha1-CiLoIQYJrTVUL4yNXSFZr/B1HIQ=", "dev": true }, "process-nextick-args": { - "version": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", "dev": true }, "progress": { - "version": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz", + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz", "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=", "dev": true }, "progress-stream": { - "version": "https://registry.npmjs.org/progress-stream/-/progress-stream-1.2.0.tgz", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/progress-stream/-/progress-stream-1.2.0.tgz", "integrity": "sha1-LNPP6jO6OonJwSHsM0er6asSX3c=", "dev": true }, "punycode": { - "version": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", "dev": true }, "qs": { - "version": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=", "dev": true }, "rc": { - "version": "https://registry.npmjs.org/rc/-/rc-1.2.1.tgz", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.1.tgz", "integrity": "sha1-LgPo5C7kULjLPc5lvhv4l04d/ZU=", "dev": true }, "read-all-stream": { - "version": "https://registry.npmjs.org/read-all-stream/-/read-all-stream-3.1.0.tgz", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/read-all-stream/-/read-all-stream-3.1.0.tgz", "integrity": "sha1-NcPhd/IHjveJ7kv6+kNzB06u9Po=", "dev": true, "dependencies": { "isarray": { - "version": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true }, "readable-stream": { - "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.9.tgz", - "integrity": "sha1-z3jsb0ptHrQ9JkiMrJfwQudLf8g=", + "version": "2.2.11", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.11.tgz", + "integrity": "sha512-h+8+r3MKEhkiVrwdKL8aWs1oc1VvBu33ueshOvS26RsZQ3Amhx/oO3TKe4lApSV9ueY6as8EAh7mtuFjdlhg9Q==", + "dev": true + }, + "safe-buffer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.0.1.tgz", + "integrity": "sha1-0mPKVGls2KMGtcplUekt5XkY++c=", "dev": true }, "string_decoder": { - "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.0.tgz", - "integrity": "sha1-8G9BFXtmTYYGn4S9vcmw2KsoFmc=", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.2.tgz", + "integrity": "sha1-sp4fThEl+pehA4K4pTNze3SR4Xk=", "dev": true } } }, "read-pkg": { - "version": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", "dev": true }, "read-pkg-up": { - "version": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", "dev": true }, "readable-stream": { - "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", "dev": true }, "redent": { - "version": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", "dev": true }, "registry-auth-token": { - "version": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.1.2.tgz", - "integrity": "sha1-G55RoYXJMNo0qYlLEqUuqZjxra8=", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.3.1.tgz", + "integrity": "sha1-+w0yie4Nmtosu1KvXf5mywcNMAY=", "dev": true }, "registry-url": { - "version": "https://registry.npmjs.org/registry-url/-/registry-url-3.1.0.tgz", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-3.1.0.tgz", "integrity": "sha1-PU74cPc93h138M+aOBQyRE4XSUI=", "dev": true }, "repeating": { - "version": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", "dev": true }, "request": { - "version": "https://registry.npmjs.org/request/-/request-2.81.0.tgz", + "version": "2.81.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.81.0.tgz", "integrity": "sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA=", "dev": true }, "require-directory": { - "version": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", "dev": true }, "require-main-filename": { - "version": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", "dev": true }, "rimraf": { - "version": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.1.tgz", + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.1.tgz", "integrity": "sha1-wjOOxkPfeht/5cVPqG9XQopV8z0=", "dev": true }, "safe-buffer": { - "version": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.0.1.tgz", - "integrity": "sha1-0mPKVGls2KMGtcplUekt5XkY++c=", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.0.tgz", + "integrity": "sha512-aSLEDudu6OoRr/2rU609gRmnYboRLxgDG1z9o2Q0os7236FwvcqIOO8r8U5JUEwivZOhDaKlFO4SbPTJYyBEyQ==", "dev": true }, "sanitize-filename": { - "version": "https://registry.npmjs.org/sanitize-filename/-/sanitize-filename-1.6.1.tgz", + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/sanitize-filename/-/sanitize-filename-1.6.1.tgz", "integrity": "sha1-YS2hyWRz+gLczaktzVtKsWSmdyo=", "dev": true }, "semver": { - "version": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", "dev": true }, "semver-diff": { - "version": "https://registry.npmjs.org/semver-diff/-/semver-diff-2.1.0.tgz", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-2.1.0.tgz", "integrity": "sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY=", "dev": true }, "set-blocking": { - "version": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true }, "signal-exit": { - "version": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", "dev": true }, "single-line-log": { - "version": "https://registry.npmjs.org/single-line-log/-/single-line-log-1.1.2.tgz", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/single-line-log/-/single-line-log-1.1.2.tgz", "integrity": "sha1-wvg/Jzo+GhbtsJlWYdoO1e8DM2Q=", "dev": true }, "slide": { - "version": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz", + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz", "integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=", "dev": true }, "sntp": { - "version": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", "dev": true }, "source-map": { - "version": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz", + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz", "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI=", "dev": true }, "source-map-support": { - "version": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.14.tgz", - "integrity": "sha1-nURjdyWYuGJxtPUj9sH04Cp9au8=", + "version": "0.4.15", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.15.tgz", + "integrity": "sha1-AyAt9lwG0r2MfsI2KhkwVv7407E=", "dev": true }, "spdx-correct": { - "version": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz", "integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=", "dev": true }, "spdx-expression-parse": { - "version": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz", "integrity": "sha1-m98vIOH0DtRH++JzJmGR/O1RYmw=", "dev": true }, "spdx-license-ids": { - "version": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz", "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=", "dev": true }, "speedometer": { - "version": "https://registry.npmjs.org/speedometer/-/speedometer-0.1.4.tgz", + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/speedometer/-/speedometer-0.1.4.tgz", "integrity": "sha1-mHbb0qFp0xFUAtSObqYynIgWpQ0=", "dev": true }, "sprintf-js": { - "version": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", "dev": true }, "sshpk": { - "version": "https://registry.npmjs.org/sshpk/-/sshpk-1.11.0.tgz", - "integrity": "sha1-LY1eu0pvqyj/ujf6YqkPSj6lnXc=", + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz", + "integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=", "dev": true, "dependencies": { "assert-plus": { - "version": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", "dev": true } } }, "stat-mode": { - "version": "https://registry.npmjs.org/stat-mode/-/stat-mode-0.2.2.tgz", + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/stat-mode/-/stat-mode-0.2.2.tgz", "integrity": "sha1-5sgLYjEj19gM8TLOU480YokHJQI=", "dev": true }, "string_decoder": { - "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true }, "string-width": { - "version": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dev": true }, "string.prototype.codepointat": { - "version": "https://registry.npmjs.org/string.prototype.codepointat/-/string.prototype.codepointat-0.2.0.tgz", + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/string.prototype.codepointat/-/string.prototype.codepointat-0.2.0.tgz", "integrity": "sha1-aybpvTr8qnvjtCabUm3huCAArHg=", "dev": true }, "stringstream": { - "version": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=", "dev": true }, "strip-ansi": { - "version": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true }, "strip-bom": { - "version": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", "dev": true }, "strip-indent": { - "version": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", "dev": true }, "strip-json-comments": { - "version": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", "dev": true }, "sumchecker": { - "version": "https://registry.npmjs.org/sumchecker/-/sumchecker-1.3.1.tgz", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-1.3.1.tgz", "integrity": "sha1-ebs7RFbdBPGOvbwNcDodHa7FEF0=", "dev": true }, "supports-color": { - "version": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", "dev": true }, "throttleit": { - "version": "https://registry.npmjs.org/throttleit/-/throttleit-0.0.2.tgz", + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-0.0.2.tgz", "integrity": "sha1-z+34jmDADdlpe2H90qg0OptoDq8=", "dev": true }, "through2": { - "version": "https://registry.npmjs.org/through2/-/through2-0.2.3.tgz", + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.2.3.tgz", "integrity": "sha1-6zKE2k6jEbbMis42U3SKUqvyWj8=", "dev": true }, "timed-out": { - "version": "https://registry.npmjs.org/timed-out/-/timed-out-3.1.3.tgz", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-3.1.3.tgz", "integrity": "sha1-lYYL/MXHbCd/j4Mm/Q9bLiDrohc=", "dev": true }, "tough-cookie": { - "version": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.2.tgz", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.2.tgz", "integrity": "sha1-8IH3bkyFcg5sN6X6ztc3FQ2EByo=", "dev": true }, "trim-newlines": { - "version": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", "dev": true }, "truncate-utf8-bytes": { - "version": "https://registry.npmjs.org/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz", "integrity": "sha1-QFkjkJWS1W94pYGENLC3hInKXys=", "dev": true }, "tunnel-agent": { - "version": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", "dev": true }, "tweetnacl": { - "version": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", "dev": true, "optional": true }, "typedarray": { - "version": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", "dev": true }, "unzip-response": { - "version": "https://registry.npmjs.org/unzip-response/-/unzip-response-1.0.2.tgz", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unzip-response/-/unzip-response-1.0.2.tgz", "integrity": "sha1-uYTwh3/AqJwsdzzB73tbIytbBv4=", "dev": true }, "update-notifier": { - "version": "https://registry.npmjs.org/update-notifier/-/update-notifier-1.0.3.tgz", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-1.0.3.tgz", "integrity": "sha1-j5LFFUgr1oMbfJMBPnD4dVLHz1o=", "dev": true }, "url-parse-lax": { - "version": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", "dev": true }, "utf8-byte-length": { - "version": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.4.tgz", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.4.tgz", "integrity": "sha1-9F8VDExm7uloGGUFq5P8u4rWv2E=", "dev": true }, "util-deprecate": { - "version": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "dev": true }, "uuid": { - "version": "https://registry.npmjs.org/uuid/-/uuid-3.0.1.tgz", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.0.1.tgz", "integrity": "sha1-ZUS7ot/ajBzxfmKaOjBeK7H+5sE=", "dev": true }, "uuid-1345": { - "version": "https://registry.npmjs.org/uuid-1345/-/uuid-1345-0.99.6.tgz", + "version": "0.99.6", + "resolved": "https://registry.npmjs.org/uuid-1345/-/uuid-1345-0.99.6.tgz", "integrity": "sha1-sScK4BWnchx63sbEbsFpxgmK7UA=", "dev": true }, "validate-npm-package-license": { - "version": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz", "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=", "dev": true }, "verror": { - "version": "https://registry.npmjs.org/verror/-/verror-1.3.6.tgz", + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.3.6.tgz", "integrity": "sha1-z/XfEpRtKX0rqu+qJoniW+AcAFw=", "dev": true }, "which-module": { - "version": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", "dev": true }, + "why-did-you-update": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/why-did-you-update/-/why-did-you-update-0.0.8.tgz", + "integrity": "sha1-OJ2X3WwUfh7byfXVRw1E2YXIrjg=", + "dev": true + }, "widest-line": { - "version": "https://registry.npmjs.org/widest-line/-/widest-line-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-1.0.0.tgz", "integrity": "sha1-DAnIXCqUaD0Nfq+O4JfVZL8OEFw=", "dev": true }, "wrap-ansi": { - "version": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", "dev": true }, "wrappy": { - "version": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true }, "write-file-atomic": { - "version": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-1.3.1.tgz", - "integrity": "sha1-fUW6MjFjKN0ex9kPYOvA2EW7dZo=", + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-1.3.4.tgz", + "integrity": "sha1-+Aek8LHZ6ROuekgRLmzDrxmRtF8=", "dev": true }, "xdg-basedir": { - "version": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-2.0.0.tgz", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-2.0.0.tgz", "integrity": "sha1-7byQPMOF/ARSPZZqM1UEtVBNG9I=", "dev": true }, "xmlbuilder": { - "version": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-8.2.2.tgz", + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-8.2.2.tgz", "integrity": "sha1-aSSGc0ELS6QuGmE2VR0pIjNap3M=", "dev": true }, "xmldom": { - "version": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.27.tgz", + "version": "0.1.27", + "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.27.tgz", "integrity": "sha1-1QH5ezvbQDr4757MIFcxh6rawOk=", "dev": true }, "xtend": { - "version": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", "dev": true }, "y18n": { - "version": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", "dev": true }, "yargs": { - "version": "https://registry.npmjs.org/yargs/-/yargs-6.6.0.tgz", + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-6.6.0.tgz", "integrity": "sha1-eC7CHvQDNF+DCoCMo9UTr1YGUgg=", "dev": true, "dependencies": { "camelcase": { - "version": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", "dev": true } } }, "yargs-parser": { - "version": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-4.2.1.tgz", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-4.2.1.tgz", "integrity": "sha1-KczqwNxPA8bIe0qfIX3RjJ90hxw=", "dev": true, "dependencies": { "camelcase": { - "version": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", "dev": true } } }, "yauzl": { - "version": "https://registry.npmjs.org/yauzl/-/yauzl-2.4.1.tgz", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.4.1.tgz", "integrity": "sha1-lSj0QtqxsihOWLQ3m7GU4i4MQAU=", "dev": true } diff --git a/ui/package-lock.json b/ui/package-lock.json index a2ecfaf03..5148958cd 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -1,6 +1,6 @@ { "name": "lbry-web-ui", - "version": "0.12.0rc4", + "version": "0.12.0rc6", "lockfileVersion": 1, "dependencies": { "abbrev": { @@ -89,6 +89,12 @@ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.0.tgz", "integrity": "sha1-o+Uvo5FoyCX/V7AkgSbOWo/5VQc=" }, + "app-root-path": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-2.0.1.tgz", + "integrity": "sha1-zWLc+OT9WkF+/GZNLlsQZTxlG0Y=", + "dev": true + }, "aproba": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.1.2.tgz", @@ -223,14 +229,14 @@ "integrity": "sha1-AnYgvuVnqIwyVhV05/0IAdMxGOQ=" }, "babel-core": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.24.1.tgz", - "integrity": "sha1-jEKFZNzh4fQfszfsNPTDsCK1rYM=" + "version": "6.25.0", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.25.0.tgz", + "integrity": "sha1-fdQrBGPHQunVKW3rPsZ6kyLa1yk=" }, "babel-generator": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.24.1.tgz", - "integrity": "sha1-5xX0hsWN7SVknYiJRNUqoHxdlJc=" + "version": "6.25.0", + "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.25.0.tgz", + "integrity": "sha1-M6GvcNXyiQrrRlpKd5PB32qeqfw=" }, "babel-helper-bindify-decorators": { "version": "6.24.1", @@ -544,9 +550,9 @@ "dev": true }, "babel-plugin-transform-react-display-name": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-display-name/-/babel-plugin-transform-react-display-name-6.23.0.tgz", - "integrity": "sha1-Q5iRDDWEQdxM7xh4cmTQQS7Tazc=" + "version": "6.25.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-display-name/-/babel-plugin-transform-react-display-name-6.25.0.tgz", + "integrity": "sha1-Z+K/Hx6ck6sI25Z5LgU5K/LMKNE=" }, "babel-plugin-transform-react-jsx": { "version": "6.24.1", @@ -616,24 +622,24 @@ "integrity": "sha1-CpSJ8UTecO+zzkMArM2zKeL8VDs=" }, "babel-template": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.24.1.tgz", - "integrity": "sha1-BK5RTx+Ts6JTfyoPYKWkX7gwgzM=" + "version": "6.25.0", + "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.25.0.tgz", + "integrity": "sha1-ZlJBFmt8KqTGGdceGSlpVSsQwHE=" }, "babel-traverse": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.24.1.tgz", - "integrity": "sha1-qzZnP9NW+aCUhlnnszjV/q2zFpU=" + "version": "6.25.0", + "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.25.0.tgz", + "integrity": "sha1-IldJfi/NGbie3BPEyROB+VEklvE=" }, "babel-types": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.24.1.tgz", - "integrity": "sha1-oTaHncFbNga9oNkMH8dDBML/CXU=" + "version": "6.25.0", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.25.0.tgz", + "integrity": "sha1-cK+ySNVmDl0Y+BHZHIMDtUE0oY4=" }, "babylon": { - "version": "6.17.2", - "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.17.2.tgz", - "integrity": "sha1-IB0l71+JLEG65JSIsI2w3Udun1w=" + "version": "6.17.3", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.17.3.tgz", + "integrity": "sha512-mq0x3HCAGGmQyZXviOVe5TRsw37Ijy3D43jCqt/9WVf+onx2dUgW3PosnqCbScAFhRO9DGs8nxoMzU0iiosMqQ==" }, "balanced-match": { "version": "0.4.2", @@ -778,6 +784,12 @@ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=" }, + "ci-info": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.0.0.tgz", + "integrity": "sha1-3FKF8rTiUYIWg2gcOBwziPRuxTQ=", + "dev": true + }, "circular-json": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.1.tgz", @@ -790,12 +802,24 @@ "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", "dev": true }, + "cli-spinners": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-0.1.2.tgz", + "integrity": "sha1-u3ZNiOGF+54eaiofGXcjGPYF4xw=", + "dev": true + }, "cli-table": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.1.tgz", "integrity": "sha1-9TsFJmqLGguTSz0IIebi3FkUriM=", "dev": true }, + "cli-truncate": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-0.2.1.tgz", + "integrity": "sha1-nxXPuwcFAFNpIWxiasfQWrkN1XQ=", + "dev": true + }, "cli-usage": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/cli-usage/-/cli-usage-0.1.4.tgz", @@ -956,6 +980,20 @@ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, + "cosmiconfig": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-1.1.0.tgz", + "integrity": "sha1-DeoPmATv37kp+7GxiOJVU+oFPTc=", + "dev": true, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, "create-react-class": { "version": "15.5.3", "resolved": "https://registry.npmjs.org/create-react-class/-/create-react-class-15.5.3.tgz", @@ -1006,6 +1044,12 @@ } } }, + "date-fns": { + "version": "1.28.5", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.28.5.tgz", + "integrity": "sha1-JXz8RdMi30XvVlhmWWfuhBzXP68=", + "dev": true + }, "date-now": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", @@ -1102,6 +1146,12 @@ "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", "dev": true }, + "elegant-spinner": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/elegant-spinner/-/elegant-spinner-1.0.1.tgz", + "integrity": "sha1-2wQ1IcldfjA/2PNFvtwzSc+wcp4=", + "dev": true + }, "element-class": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/element-class/-/element-class-0.2.2.tgz", @@ -1434,6 +1484,20 @@ "integrity": "sha1-Cs7ehJ7X3RzMMsgRuxG5RNTykjI=", "dev": true }, + "execa": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.6.3.tgz", + "integrity": "sha1-V7aaWU8IF1nGnlNw8NF7nLEWWP4=", + "dev": true, + "dependencies": { + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "dev": true + } + } + }, "exenv": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/exenv/-/exenv-1.2.0.tgz", @@ -1550,6 +1614,12 @@ "integrity": "sha1-yN765XyKUqinhPnjHFfHQumToLk=", "dev": true }, + "find-parent-dir": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/find-parent-dir/-/find-parent-dir-0.3.0.tgz", + "integrity": "sha1-M8RLQpqysvBkYpnF+fcY83b/jVQ=", + "dev": true + }, "find-up": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", @@ -2232,6 +2302,12 @@ "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=" }, + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "dev": true + }, "getpass": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", @@ -2260,9 +2336,9 @@ "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=" }, "globals": { - "version": "9.17.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-9.17.0.tgz", - "integrity": "sha1-DAymltm5u2lNLlRwvTd3fKrVAoY=" + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==" }, "globby": { "version": "5.0.0", @@ -2422,6 +2498,20 @@ "integrity": "sha1-P5E2XKvmC3ftDruiS0VOPgnZWoI=", "dev": true }, + "husky": { + "version": "0.13.4", + "resolved": "https://registry.npmjs.org/husky/-/husky-0.13.4.tgz", + "integrity": "sha1-SHhcUCjeNFKlHEjBLE+UshJKFAc=", + "dev": true, + "dependencies": { + "normalize-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-1.0.0.tgz", + "integrity": "sha1-MtDkcvkf80VwHBWoMRAY07CpA3k=", + "dev": true + } + } + }, "iconv-lite": { "version": "0.4.17", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.17.tgz", @@ -2530,6 +2620,12 @@ "integrity": "sha1-hut1OSgF3cM69xySoO7fdO52BLI=", "dev": true }, + "is-ci": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.0.10.tgz", + "integrity": "sha1-9zkzayYyNlBhqdSCcM1WrjNpMY4=", + "dev": true + }, "is-date-object": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", @@ -2610,6 +2706,12 @@ "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=" }, + "is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", + "dev": true + }, "is-property": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", @@ -2674,12 +2776,6 @@ "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" }, - "jodid25519": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/jodid25519/-/jodid25519-1.0.2.tgz", - "integrity": "sha1-BtSRIlUJNBlHfUJWM2BuDpB4KWc=", - "optional": true - }, "js-base64": { "version": "2.1.9", "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.1.9.tgz", @@ -2795,6 +2891,44 @@ "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", "dev": true }, + "lint-staged": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-3.6.0.tgz", + "integrity": "sha1-zajwvvFueSjMFLc1GGrhLNZiWZw=", + "dev": true + }, + "listr": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/listr/-/listr-0.12.0.tgz", + "integrity": "sha1-a84sD1YD+klYDqF81qAMwOX6RRo=", + "dev": true + }, + "listr-silent-renderer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz", + "integrity": "sha1-kktaN1cVN3C/Go4/v3S4u/P5JC4=", + "dev": true + }, + "listr-update-renderer": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/listr-update-renderer/-/listr-update-renderer-0.2.0.tgz", + "integrity": "sha1-yoDhd5tOcCZoB+ju0a1qvjmFUPk=", + "dev": true, + "dependencies": { + "indent-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.1.0.tgz", + "integrity": "sha1-CP9DNGAziDmbMp5rlTjcejz13n0=", + "dev": true + } + } + }, + "listr-verbose-renderer": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/listr-verbose-renderer/-/listr-verbose-renderer-0.4.0.tgz", + "integrity": "sha1-RNwBuww0oDxXIVTU0Izemx3FYg8=", + "dev": true + }, "load-json-file": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", @@ -2889,6 +3023,12 @@ "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=" }, + "lodash.chunk": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.chunk/-/lodash.chunk-4.2.0.tgz", + "integrity": "sha1-ZuXOH3btJ7QwPYxlEujRIW6BBrw=", + "dev": true + }, "lodash.clonedeep": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", @@ -2918,6 +3058,18 @@ "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", "dev": true }, + "log-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz", + "integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=", + "dev": true + }, + "log-update": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-1.0.2.tgz", + "integrity": "sha1-GZKfZMQJPS0ucHWh2tivWcKWuNE=", + "dev": true + }, "longest": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", @@ -2935,9 +3087,9 @@ "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=" }, "lru-cache": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.0.2.tgz", - "integrity": "sha1-HRdnnAac2l0ECZGgnbwsDbN35V4=" + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.0.tgz", + "integrity": "sha512-aHGs865JXz6bkB4AHL+3AhyvTFKL3iZamKVWjIUKnXOXyasJvqPK8WAjOnAQKQZVpeXDVz19u1DD0r/12bWAdQ==" }, "map-obj": { "version": "1.0.1", @@ -3157,6 +3309,24 @@ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=" }, + "npm-path": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/npm-path/-/npm-path-2.0.3.tgz", + "integrity": "sha1-Fc/04ciaONp39W9gVbJPl137K74=", + "dev": true + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true + }, + "npm-which": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/npm-which/-/npm-which-3.0.1.tgz", + "integrity": "sha1-kiXybsOihcIJyuZ8OxGmtKtxQKo=", + "dev": true + }, "npmlog": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.0.tgz", @@ -3255,6 +3425,12 @@ "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", "dev": true }, + "ora": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/ora/-/ora-0.2.3.tgz", + "integrity": "sha1-N1J9Igrc1Tw5tzVx11QVbV22V6Q=", + "dev": true + }, "original": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/original/-/original-1.0.0.tgz", @@ -3300,6 +3476,12 @@ "resolved": "https://registry.npmjs.org/output-file-sync/-/output-file-sync-1.1.2.tgz", "integrity": "sha1-0KM+7+YaIF+suQCS6CZZjVJFznY=" }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true + }, "p-limit": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.1.0.tgz", @@ -3312,6 +3494,12 @@ "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", "dev": true }, + "p-map": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-1.1.1.tgz", + "integrity": "sha1-BfXkrpegaDcbwqXMhr+9vBnErno=", + "dev": true + }, "pako": { "version": "0.2.9", "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", @@ -3356,6 +3544,12 @@ "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", "dev": true }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, "path-parse": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", @@ -3428,6 +3622,12 @@ "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=" }, + "prettier": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.4.4.tgz", + "integrity": "sha512-GuuPazIvjW1DG26yLQgO+nagmRF/h9M4RaCtZWqu/eFW7csdZkQEwPJUeXX10d+LzmCnR9DuIZndqIOn3p2YoA==", + "dev": true + }, "private": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/private/-/private-0.1.7.tgz", @@ -3542,9 +3742,9 @@ "integrity": "sha1-ugwoeG/VLtfk8hNf4CiNRirvk9o=" }, "react-modal": { - "version": "1.7.7", - "resolved": "https://registry.npmjs.org/react-modal/-/react-modal-1.7.7.tgz", - "integrity": "sha1-cCBfUcWHCMSHr/aBuj/teUbjkdk=" + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/react-modal/-/react-modal-1.7.11.tgz", + "integrity": "sha512-mKKJlDp7mIWAuBpg0ZJLoGEzyVME63vs5jBy+D53R9V+hVJ775y8DXFYRGLQYSZW9IFE0qkmNSLm7HdgDGqzsg==" }, "react-redux": { "version": "5.0.5", @@ -3660,9 +3860,9 @@ } }, "remove-trailing-separator": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.0.1.tgz", - "integrity": "sha1-YV67lq9VlVLUv0BXyENtSGq2PMQ=" + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.0.2.tgz", + "integrity": "sha1-abBi2XhyetFNxrVrpKt3L9jXBRE=" }, "render-media": { "version": "2.10.0", @@ -3694,6 +3894,12 @@ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" }, + "require-from-string": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-1.2.1.tgz", + "integrity": "sha1-UpyczvJzgK3+yaL5ZbZJu+5jZBg=", + "dev": true + }, "require-main-filename": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", @@ -3763,6 +3969,12 @@ "integrity": "sha1-Gc5QLKVyZl87ZHsQk5+X/RYV8QI=", "dev": true }, + "rxjs": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.4.0.tgz", + "integrity": "sha1-p9sUqxV/nXqsalbmVeejhg05vyY=", + "dev": true + }, "safe-buffer": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.0.1.tgz", @@ -3849,10 +4061,22 @@ "integrity": "sha1-F93t3F9yL7ZlAWWIlUYZd4ZzFbo=", "dev": true }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, "shelljs": { - "version": "0.7.7", - "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.7.7.tgz", - "integrity": "sha1-svXHfvlxSPS09uImguELuoZnz/E=", + "version": "0.7.8", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.7.8.tgz", + "integrity": "sha1-3svPh0sNHl+3LhSxZKloMEjprLM=", "dev": true }, "shellwords": { @@ -3960,9 +4184,9 @@ "dev": true }, "sshpk": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.0.tgz", - "integrity": "sha1-/yo+T9BEl1Vf7Zezmg/YL6+zozw=", + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz", + "integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=", "dependencies": { "assert-plus": { "version": "1.0.0", @@ -3971,6 +4195,12 @@ } } }, + "staged-git-files": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/staged-git-files/-/staged-git-files-0.0.4.tgz", + "integrity": "sha1-15fhtVHKemOd7AI33G60u5vhfTU=", + "dev": true + }, "statuses": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", @@ -3999,6 +4229,12 @@ "resolved": "https://registry.npmjs.org/stream-to-blob-url/-/stream-to-blob-url-2.1.0.tgz", "integrity": "sha1-w0HRBQLsUSUGBzJyWOwvWGsH1iY=" }, + "stream-to-observable": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/stream-to-observable/-/stream-to-observable-0.1.0.tgz", + "integrity": "sha1-Rb8dny19wJvtgfHDB8Qw5ouEz/4=", + "dev": true + }, "string_decoder": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.2.tgz", @@ -4030,6 +4266,12 @@ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=" }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "dev": true + }, "strip-indent": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", From 6cf5c144b0a38e86a171af2fae28be8151dd72ae Mon Sep 17 00:00:00 2001 From: Alex Grintsvayg Date: Fri, 9 Jun 2017 10:23:47 -0400 Subject: [PATCH 14/14] =?UTF-8?q?Bump=20version:=200.12.0rc6=20=E2=86=92?= =?UTF-8?q?=200.12.0rc7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bumpversion.cfg | 2 +- app/package.json | 2 +- ui/package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index d2c503426..655e332f9 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.12.0rc6 +current_version = 0.12.0rc7 commit = True tag = True parse = (?P\d+)\.(?P\d+)\.(?P\d+)((?P[a-z]+)(?P\d+))? diff --git a/app/package.json b/app/package.json index cc30f0160..22c89d1fd 100644 --- a/app/package.json +++ b/app/package.json @@ -1,6 +1,6 @@ { "name": "LBRY", - "version": "0.12.0rc6", + "version": "0.12.0rc7", "main": "main.js", "description": "LBRY is a fully decentralized, open-source protocol facilitating the discovery, access, and (sometimes) purchase of data.", "author": { diff --git a/ui/package.json b/ui/package.json index c2cf0a0c7..350e17adb 100644 --- a/ui/package.json +++ b/ui/package.json @@ -1,6 +1,6 @@ { "name": "lbry-web-ui", - "version": "0.12.0rc6", + "version": "0.12.0rc7", "description": "LBRY UI", "scripts": { "test": "echo \"Error: no test specified\" && exit 1",