From da7358a1721d0fb69a0d07b0e07622a68c17663c Mon Sep 17 00:00:00 2001 From: Juan Cazala Date: Fri, 14 Dec 2018 10:42:36 -0300 Subject: [PATCH 01/12] chore: linted --- src/modules/transaction/reducer.ts | 8 +++----- src/modules/transaction/sagas.ts | 2 +- src/modules/wallet/sagas.ts | 2 +- src/modules/wallet/types.ts | 2 +- src/modules/wallet/utils.ts | 2 +- 5 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/modules/transaction/reducer.ts b/src/modules/transaction/reducer.ts index d0ec5279..a59c2649 100644 --- a/src/modules/transaction/reducer.ts +++ b/src/modules/transaction/reducer.ts @@ -1,5 +1,7 @@ +import { txUtils } from 'decentraland-eth' + import { Transaction } from './types' -import { getTransactionFromAction } from './utils' +import { getTransactionFromAction, isPending } from './utils' import { loadingReducer, LoadingState } from '../loading/reducer' import { FetchTransactionRequestAction, @@ -21,8 +23,6 @@ import { FixRevertedTransactionAction, FIX_REVERTED_TRANSACTION } from './actions' -import { txUtils } from 'decentraland-eth' -import { isPending } from './utils' export type TransactionState = { data: Transaction[] @@ -148,7 +148,6 @@ export function transactionReducer( error: null, data: state.data.map( (transaction: Transaction) => - // prettier-ignore action.payload.hash === transaction.hash ? { ...transaction, @@ -164,7 +163,6 @@ export function transactionReducer( error: null, data: state.data.map( (transaction: Transaction) => - // prettier-ignore action.payload.hash === transaction.hash ? { ...transaction, diff --git a/src/modules/transaction/sagas.ts b/src/modules/transaction/sagas.ts index 99785357..2b80dbb7 100644 --- a/src/modules/transaction/sagas.ts +++ b/src/modules/transaction/sagas.ts @@ -297,7 +297,7 @@ function* handleWatchRevertedTransaction( ) if (tx != null && tx.type === TRANSACTION_TYPES.confirmed) { yield put(fixRevertedTransaction(hash)) - return + return undefined } } while (!isExpired(txInState, REVERTED_TRANSACTION_THRESHOLD)) } diff --git a/src/modules/wallet/sagas.ts b/src/modules/wallet/sagas.ts index f022222f..09004ec6 100644 --- a/src/modules/wallet/sagas.ts +++ b/src/modules/wallet/sagas.ts @@ -31,7 +31,7 @@ export function createWalletSaga({ try { if (isApprovableWallet()) { const { ethereum } = window as EthereumWindow - yield call(() => ethereum!.enable()) + yield call(() => ethereum!.enable!()) // Unfortunately we need to override the provider supplied to this method // if we're dealing with approbable wallets (the first being Metamask, probably more to come). diff --git a/src/modules/wallet/types.ts b/src/modules/wallet/types.ts index f7d02baf..767ef9f7 100644 --- a/src/modules/wallet/types.ts +++ b/src/modules/wallet/types.ts @@ -24,6 +24,6 @@ export interface EthereumWindow { _metamask: { isApproved: () => Promise } isApproved: () => Promise - enable: () => Promise + enable?: () => Promise } } diff --git a/src/modules/wallet/utils.ts b/src/modules/wallet/utils.ts index 9d6cbb30..d5980ff5 100644 --- a/src/modules/wallet/utils.ts +++ b/src/modules/wallet/utils.ts @@ -76,7 +76,7 @@ export async function isWalletApproved(): Promise { // `Promise.race` will *not* cancel the slower promise let hasFinished = false - return await Promise.race([ + return Promise.race([ approvable.isApproved().then(result => { hasFinished = true return result From a570b4f293ff4421d6bf8dc5167dc645136e6514 Mon Sep 17 00:00:00 2001 From: Juan Cazala Date: Fri, 14 Dec 2018 10:44:15 -0300 Subject: [PATCH 02/12] feat(modules/location): added common functionality around sign in / root --- src/containers/App/index.ts | 2 ++ src/containers/Navbar/Navbar.container.tsx | 6 ++-- src/containers/Navbar/Navbar.types.tsx | 7 ++++- src/modules/location/actions.ts | 12 ++++++++ src/modules/location/reducer.ts | 21 +++++++++++++ src/modules/location/sagas.ts | 34 +++++++++++++++++++++- src/modules/location/selectors.ts | 16 ++++++++++ src/modules/location/types.ts | 4 +++ 8 files changed, 98 insertions(+), 4 deletions(-) create mode 100644 src/containers/App/index.ts create mode 100644 src/modules/location/reducer.ts create mode 100644 src/modules/location/types.ts diff --git a/src/containers/App/index.ts b/src/containers/App/index.ts new file mode 100644 index 00000000..f6653a6a --- /dev/null +++ b/src/containers/App/index.ts @@ -0,0 +1,2 @@ +import App from './App.container' +export default App diff --git a/src/containers/Navbar/Navbar.container.tsx b/src/containers/Navbar/Navbar.container.tsx index 64991500..755f6b7e 100644 --- a/src/containers/Navbar/Navbar.container.tsx +++ b/src/containers/Navbar/Navbar.container.tsx @@ -9,7 +9,8 @@ import { isConnecting } from '../../modules/wallet/selectors' import { isEnabled } from '../../modules/translation/selectors' -import { connectWalletRequest } from '../../modules/wallet/actions' +import { isSignIn } from '../../modules/location/selectors' +import { navigateToSignIn } from '../../modules/location/actions' import { RootDispatch } from '../../types' const mapState = (state: any): MapStateProps => { @@ -19,6 +20,7 @@ const mapState = (state: any): MapStateProps => { address: wallet.address, isConnected: isConnected(state), isConnecting: isConnecting(state), + isSignIn: isSignIn(state), hasTranslations: isEnabled(state) } } @@ -26,7 +28,7 @@ const mapState = (state: any): MapStateProps => { const mapDispatch = ( dispatch: RootDispatch ): MapDispatchProps => ({ - onSignIn: () => dispatch(connectWalletRequest()) + onSignIn: () => dispatch(navigateToSignIn()) }) const mergeProps = ( diff --git a/src/containers/Navbar/Navbar.types.tsx b/src/containers/Navbar/Navbar.types.tsx index 9edbdda5..934348e2 100644 --- a/src/containers/Navbar/Navbar.types.tsx +++ b/src/containers/Navbar/Navbar.types.tsx @@ -6,7 +6,12 @@ export type NavbarProps = NavbarComponentProps & { export type MapStateProps = Pick< NavbarProps, - 'mana' | 'address' | 'isConnected' | 'isConnecting' | 'hasTranslations' + | 'mana' + | 'address' + | 'isConnected' + | 'isConnecting' + | 'isSignIn' + | 'hasTranslations' > export type MapDispatchProps = Pick diff --git a/src/modules/location/actions.ts b/src/modules/location/actions.ts index f84a8240..04ccc100 100644 --- a/src/modules/location/actions.ts +++ b/src/modules/location/actions.ts @@ -5,3 +5,15 @@ export const NAVIGATE_TO = 'Navigate to URL' export const navigateTo = (url: string) => action(NAVIGATE_TO, { url }) export type NavigateToAction = ReturnType + +export const NAVIGATE_TO_SIGN_IN = 'Navigate to sign in' + +export const navigateToSignIn = () => action(NAVIGATE_TO_SIGN_IN) + +export type NavigateToSignInAction = ReturnType + +export const NAVIGATE_TO_ROOT = 'Navigate to root' + +export const navigateToRoot = () => action(NAVIGATE_TO_ROOT) + +export type NavigateToRootAction = ReturnType diff --git a/src/modules/location/reducer.ts b/src/modules/location/reducer.ts new file mode 100644 index 00000000..c9056a35 --- /dev/null +++ b/src/modules/location/reducer.ts @@ -0,0 +1,21 @@ +import { Locations } from './types' + +export type LocationState = { + locations: Locations +} + +export const defaultLocations: Locations = { + root: '/', + signIn: '/sign-in' +} + +export function createLocationReducer(options: Partial = {}) { + const locations: Locations = Object.assign({}, defaultLocations, options) + + const INITIAL_STATE: LocationState = { locations } + return function locationReducer(state: LocationState = INITIAL_STATE) { + return state + } +} + +export const locationReducer = createLocationReducer() diff --git a/src/modules/location/sagas.ts b/src/modules/location/sagas.ts index 2be8d7f1..7bae0481 100644 --- a/src/modules/location/sagas.ts +++ b/src/modules/location/sagas.ts @@ -1,9 +1,24 @@ import { takeLatest, put, select, ForkEffect } from 'redux-saga/effects' import { push } from 'react-router-redux' -import { NavigateToAction, NAVIGATE_TO } from './actions' + +import { + NavigateToAction, + NAVIGATE_TO, + navigateTo, + NAVIGATE_TO_SIGN_IN, + NAVIGATE_TO_ROOT, + NavigateToSignInAction, + NavigateToRootAction +} from './actions' +import { CONNECT_WALLET_SUCCESS } from '../wallet/actions' +import { isSignIn, getLocations } from './selectors' +import { Locations } from './types' export function* locationSaga(): IterableIterator { yield takeLatest(NAVIGATE_TO, handleNavigateTo) + yield takeLatest(NAVIGATE_TO_SIGN_IN, handleNavigateToSignIn) + yield takeLatest(NAVIGATE_TO_ROOT, handleNavigateToRoot) + yield takeLatest(CONNECT_WALLET_SUCCESS, handleConnectWalletSuccess) } function* handleNavigateTo(action: NavigateToAction) { @@ -16,3 +31,20 @@ function* handleNavigateTo(action: NavigateToAction) { yield put(push(action.payload.url)) } } + +function* handleNavigateToSignIn(_: NavigateToSignInAction) { + const locations: Locations = yield select(getLocations) + yield put(navigateTo(locations.signIn)) +} + +function* handleNavigateToRoot(_: NavigateToRootAction) { + const locations: Locations = yield select(getLocations) + yield put(navigateTo(locations.root)) +} + +function* handleConnectWalletSuccess() { + if (yield select(isSignIn)) { + const locations: Locations = yield select(getLocations) + yield put(navigateTo(locations.root)) + } +} diff --git a/src/modules/location/selectors.ts b/src/modules/location/selectors.ts index 1fea98d9..1f55ce24 100644 --- a/src/modules/location/selectors.ts +++ b/src/modules/location/selectors.ts @@ -1,4 +1,6 @@ import { RouterState } from 'react-router-redux' +import { Locations } from './types' +import { LocationState } from '../../../node_modules/@types/history' export const hasRouter = (state: any): boolean => !!state.router @@ -26,3 +28,17 @@ export const getPathAction = (state: any): string | null => { } return pathname.split('/').pop() as string | null } + +export const getState = (state: any): LocationState => state.location + +export const getLocations = (state: any): Locations => getState(state).locations + +export const isSignIn = (state: any): boolean => { + const pathname = getPathname(state) + return pathname === getLocations(state).signIn +} + +export const isRoot = (state: any): boolean => { + const pathname = getPathname(state) + return pathname === getLocations(state).root +} diff --git a/src/modules/location/types.ts b/src/modules/location/types.ts new file mode 100644 index 00000000..375cefc3 --- /dev/null +++ b/src/modules/location/types.ts @@ -0,0 +1,4 @@ +export type Locations = { + root: string + signIn: string +} From 872fd1a9bed6c151b72a3cae011cceebdca8b567 Mon Sep 17 00:00:00 2001 From: Juan Cazala Date: Fri, 14 Dec 2018 14:02:30 -0300 Subject: [PATCH 03/12] feat: added App container --- src/containers/App/App.container.tsx | 29 ++++++++++++++++++++++++++++ src/containers/App/App.tsx | 25 ++++++++++++++++++++++++ src/containers/App/App.types.tsx | 6 ++++++ src/containers/index.ts | 1 + 4 files changed, 61 insertions(+) create mode 100644 src/containers/App/App.container.tsx create mode 100644 src/containers/App/App.tsx create mode 100644 src/containers/App/App.types.tsx diff --git a/src/containers/App/App.container.tsx b/src/containers/App/App.container.tsx new file mode 100644 index 00000000..7da57e7b --- /dev/null +++ b/src/containers/App/App.container.tsx @@ -0,0 +1,29 @@ +import { connect } from 'react-redux' + +import App from './App' +import { MapStateProps, AppProps } from './App.types' +import { isRoot } from '../../modules/location/selectors' + +const mapState = (state: any): MapStateProps => { + return { + isHomePage: isRoot(state) + } +} + +const mapDispatch = () => ({}) + +const mergeProps = ( + stateProps: MapStateProps, + dispatchProps: object, + ownProps: AppProps +) => ({ + ...stateProps, + ...dispatchProps, + ...ownProps +}) + +export default connect( + mapState, + mapDispatch, + mergeProps +)(App) as any diff --git a/src/containers/App/App.tsx b/src/containers/App/App.tsx new file mode 100644 index 00000000..7dbe68ab --- /dev/null +++ b/src/containers/App/App.tsx @@ -0,0 +1,25 @@ +import * as React from 'react' + +import { Page, NavbarProps, PageProps, FooterProps } from 'decentraland-ui' + +import Navbar from '../Navbar' +import Footer from '../Footer' +import { AppProps } from './App.types' + +export default class App extends React.PureComponent< + AppProps & NavbarProps & PageProps & FooterProps +> { + render() { + const { hero, isHomePage, children, ...rest } = this.props + const hasHero = hero !== null && isHomePage + return ( + <> + {hasHero ? hero : null} + + {children} + +