diff options
| author | Erik Larkö <erik@mullvad.net> | 2017-07-03 12:53:03 +0200 |
|---|---|---|
| committer | Erik Larkö <erik@mullvad.net> | 2017-07-03 12:53:03 +0200 |
| commit | e7fd60d8bffc33cf6e1a6a33c9fffc28dc112142 (patch) | |
| tree | c07bc5fb92bbfbf28bb9481e0003b36e0981d035 | |
| parent | 4e8f44c7ef6ffee09d9d3abd70bfd093f87d6b18 (diff) | |
| parent | 104778a6ebc33a4e7caeac40917fb7e29377b552 (diff) | |
| download | mullvadvpn-e7fd60d8bffc33cf6e1a6a33c9fffc28dc112142.tar.xz mullvadvpn-e7fd60d8bffc33cf6e1a6a33c9fffc28dc112142.zip | |
Merge branch 'move-and-rename-redux-stuff'
26 files changed, 155 insertions, 147 deletions
diff --git a/app/app.js b/app/app.js index ee59f1c0f4..499ffe18c4 100644 --- a/app/app.js +++ b/app/app.js @@ -7,14 +7,15 @@ import { createMemoryHistory } from 'history'; import { webFrame, ipcRenderer } from 'electron'; import log from 'electron-log'; import makeRoutes from './routes'; -import configureStore from './store'; -import userActions from './actions/user'; -import connectActions from './actions/connect'; +import configureStore from './redux/store'; +import accountActions from './redux/account/actions'; +import connectionActions from './redux/connection/actions'; import { Backend } from './lib/backend'; import mapBackendEventsToReduxActions from './lib/backend-redux-actions'; import mapBackendEventsToRouter from './lib/backend-routing'; -import type { LoginState, ConnectionState } from './enums'; +import type { LoginState } from './redux/account/reducers'; +import type { ConnectionState } from './redux/connection/reducers'; import type { TrayIconType } from './lib/tray-icon-manager'; const initialState = null; @@ -23,15 +24,15 @@ const store = configureStore(initialState, memoryHistory); const backend = new Backend(); // reset login state if user quit the app during login -if((['connecting', 'failed']: Array<LoginState>).includes(store.getState().user.status)) { - store.dispatch(userActions.loginChange({ +if((['connecting', 'failed']: Array<LoginState>).includes(store.getState().account.status)) { + store.dispatch(accountActions.loginChange({ status: 'none' })); } // reset connection state if user quit the app when connecting -if(store.getState().connect.status === 'connecting') { - store.dispatch(connectActions.connectionChange({ +if(store.getState().connection.status === 'connecting') { + store.dispatch(connectionActions.connectionChange({ status: 'disconnected' })); } @@ -53,8 +54,8 @@ const getIconType = (s: ConnectionState): TrayIconType => { * Update tray icon via IPC call */ const updateTrayIcon = () => { - const { connect } = store.getState(); - ipcRenderer.send('changeTrayIcon', getIconType(connect.status)); + const { connection } = store.getState(); + ipcRenderer.send('changeTrayIcon', getIconType(connection.status)); }; // Setup primary event handlers to translate backend events into redux dispatch @@ -106,4 +107,4 @@ ReactDOM.render( </ConnectedRouter> </Provider>, rootElement -);
\ No newline at end of file +); diff --git a/app/components/Account.js b/app/components/Account.js index e817baa280..06947be7f2 100644 --- a/app/components/Account.js +++ b/app/components/Account.js @@ -6,10 +6,10 @@ import { Layout, Container, Header } from './Layout'; import { formatAccount } from '../lib/formatters'; import ExternalLinkSVG from '../assets/images/icon-extLink.svg'; -import type { UserReduxState } from '../reducers/user'; +import type { AccountReduxState } from '../redux/account/reducers'; export type AccountProps = { - user: UserReduxState; + account: AccountReduxState; onLogout: () => void; onClose: () => void; onExternalLink: (type: string) => void; @@ -23,9 +23,8 @@ export default class Account extends Component { onLogout = () => this.props.onLogout(); render(): React.Element<*> { - const user = this.props.user; - const paidUntil = moment(user.paidUntil); - const formattedAccountId = formatAccount(user.account || ''); + const paidUntil = moment(this.props.account.paidUntil); + const formattedAccountId = formatAccount(this.props.account.accountNumber || ''); const formattedPaidUntil = paidUntil.format('hA, D MMMM YYYY').toUpperCase(); const isOutOfTime = paidUntil.isSameOrBefore(moment()); diff --git a/app/components/Connect.js b/app/components/Connect.js index 7ad0d4cc8b..602ac5299e 100644 --- a/app/components/Connect.js +++ b/app/components/Connect.js @@ -12,9 +12,9 @@ import ExternalLinkSVG from '../assets/images/icon-extLink.svg'; import type { Coordinate2d } from '../types'; import type { ServerInfo } from '../lib/backend'; import type { HeaderBarStyle } from './HeaderBar'; -import type { UserReduxState } from '../reducers/user'; -import type { ConnectReduxState } from '../reducers/connect'; -import type { SettingsReduxState } from '../reducers/settings'; +import type { AccountReduxState } from '../redux/account/reducers'; +import type { ConnectionReduxState } from '../redux/connection/reducers'; +import type { SettingsReduxState } from '../redux/settings/reducers'; type DisplayLocation = { location: Coordinate2d; @@ -23,8 +23,8 @@ type DisplayLocation = { }; export type ConnectProps = { - user: UserReduxState, - connect: ConnectReduxState, + account: AccountReduxState, + connection: ConnectionReduxState, settings: SettingsReduxState, onSettings: () => void, onSelectLocation: () => void, @@ -112,7 +112,7 @@ export default class Connect extends Component { let isConnecting = false; let isConnected = false; let isDisconnected = false; - switch(this.props.connect.status) { + switch(this.props.connection.status) { case 'connecting': isConnecting = true; break; case 'connected': isConnected = true; break; case 'disconnected': isDisconnected = true; break; @@ -122,7 +122,7 @@ export default class Connect extends Component { const displayLocation = this.displayLocation(); const mapBounds = this.calculateMapBounds(displayLocation.location, altitude); const mapBoundsOptions = { offset: [0, -113], animate: !this.state.isFirstPass }; - const userLocation = this.convertToMapCoordinate(this.props.user.location || [0, 0]); + const accountLocation = this.convertToMapCoordinate(this.props.account.location || [0, 0]); const serverLocation = this.convertToMapCoordinate(serverInfo.location); return ( @@ -144,7 +144,7 @@ export default class Connect extends Component { </If> <If condition={ !isConnected }> <Then> - <Marker coordinates={ userLocation } offset={ [0, -10] }> + <Marker coordinates={ accountLocation } offset={ [0, -10] }> <img src='./assets/images/location-marker-unsecure.svg' /> </Marker> </Then> @@ -229,7 +229,7 @@ export default class Connect extends Component { <div className={ this.ipAddressClass() } onClick={ this.onIPAddressClick.bind(this) }> <If condition={ this.state.showCopyIPMessage }> <Then><span>{ 'IP copied to clipboard!' }</span></Then> - <Else><span>{ this.props.connect.clientIp }</span></Else> + <Else><span>{ this.props.connection.clientIp }</span></Else> </If> </div> </div> @@ -341,7 +341,7 @@ export default class Connect extends Component { // Private headerStyle(): HeaderBarStyle { - switch(this.props.connect.status) { + switch(this.props.connection.status) { case 'connecting': case 'disconnected': return 'error'; @@ -353,9 +353,9 @@ export default class Connect extends Component { networkSecurityClass(): string { let classes = ['connect__status-security']; - if(this.props.connect.status === 'connected') { + if(this.props.connection.status === 'connected') { classes.push('connect__status-security--secure'); - } else if(this.props.connect.status === 'disconnected') { + } else if(this.props.connection.status === 'disconnected') { classes.push('connect__status-security--unsecured'); } @@ -363,7 +363,7 @@ export default class Connect extends Component { } networkSecurityMessage(): string { - switch(this.props.connect.status) { + switch(this.props.connection.status) { case 'connected': return 'Secure connection'; case 'connecting': return 'Creating secure connection'; default: return 'Unsecured connection'; @@ -372,7 +372,7 @@ export default class Connect extends Component { spinnerClass(): string { var classes = ['connect__status-icon']; - if(this.props.connect.status !== 'connecting') { + if(this.props.connection.status !== 'connecting') { classes.push('connect__status-icon--hidden'); } return classes.join(' '); @@ -380,7 +380,7 @@ export default class Connect extends Component { ipAddressClass(): string { var classes = ['connect__status-ipaddress']; - if(this.props.connect.status === 'connecting') { + if(this.props.connection.status === 'connecting') { classes.push('connect__status-ipaddress--invisible'); } return classes.join(' '); @@ -388,8 +388,8 @@ export default class Connect extends Component { displayLocation(): DisplayLocation { // return user location when disconnected - if(this.props.connect.status === 'disconnected') { - let { location, country, city } = this.props.user; + if(this.props.connection.status === 'disconnected') { + let { location, country, city } = this.props.account; return { location: location || [0, 0], country, city @@ -407,12 +407,12 @@ export default class Connect extends Component { displayError(): ?BackendError { // Offline? - if(!this.props.connect.isOnline) { + if(!this.props.connection.isOnline) { return new BackendError('NO_INTERNET'); } // No credit? - const { paidUntil } = this.props.user; + const { paidUntil } = this.props.account; if(paidUntil && moment(paidUntil).isSameOrBefore(moment())) { return new BackendError('NO_CREDIT'); } diff --git a/app/components/Login.js b/app/components/Login.js index 9daa3f7e78..0427832973 100644 --- a/app/components/Login.js +++ b/app/components/Login.js @@ -6,11 +6,10 @@ import AccountInput from './AccountInput'; import ExternalLinkSVG from '../assets/images/icon-extLink.svg'; import LoginArrowSVG from '../assets/images/icon-arrow.svg'; -import type { LoginState } from '../enums'; -import type { UserReduxState } from '../reducers/user'; +import type { AccountReduxState, LoginState } from '../redux/account/reducers'; export type LoginPropTypes = { - user: UserReduxState, + account: AccountReduxState, onLogin: (accountNumber: string) => void, onSettings: ?(() => void), onChange: (input: string) => void, @@ -29,9 +28,9 @@ export default class Login extends Component { onFocus = () => this.setState({ isActive: true }); onBlur = () => this.setState({ isActive: false }); onLogin = () => { - const { account } = this.props.user; - if(account && account.length > 0) { - this.props.onLogin(account); + const { accountNumber } = this.props.account; + if(accountNumber && accountNumber.length > 0) { + this.props.onLogin(accountNumber); } } @@ -91,10 +90,10 @@ export default class Login extends Component { return classes.join(' '); } - submitClass(s: LoginState, account: ?string): string { + submitClass(s: LoginState, accountNumber: ?string): string { const classes = ['login-form__submit']; - if(account && account.length > 0) { + if(accountNumber && accountNumber.length > 0) { classes.push('login-form__submit--active'); } @@ -106,8 +105,8 @@ export default class Login extends Component { } componentWillReceiveProps(nextProps: LoginPropTypes) { - const prev = this.props.user || {}; - const next = nextProps.user || {}; + const prev = this.props.account || {}; + const next = nextProps.account || {}; if(prev.status !== next.status && next.status === 'failed') { this.setState({ notifyOnFirstChangeAfterFailure: true }); @@ -115,7 +114,7 @@ export default class Login extends Component { } render(): React.Element<*> { - const { account, status, error } = this.props.user; + const { accountNumber, status, error } = this.props.account; const title = this.formTitle(status); const subtitle = this.formSubtitle(status, error); @@ -130,7 +129,7 @@ export default class Login extends Component { const inputWrapClass = this.inputWrapClass(status); const footerClass = this.footerClass(status); - const submitClass = this.submitClass(status, account); + const submitClass = this.submitClass(status, accountNumber); const autoFocusRef = input => { if(isFailed && input) { @@ -182,7 +181,7 @@ export default class Login extends Component { onBlur={ this.onBlur } onChange={ this.onInputChange } onEnter={ this.onLogin } - value={ account || '' } + value={ accountNumber || '' } disabled={ isConnecting } autoFocus={ true } ref={ autoFocusRef } /> diff --git a/app/components/SelectLocation.js b/app/components/SelectLocation.js index c94df2a11d..5a1fb5d342 100644 --- a/app/components/SelectLocation.js +++ b/app/components/SelectLocation.js @@ -5,7 +5,7 @@ import { Layout, Container, Header } from './Layout'; import { servers } from '../config'; import CustomScrollbars from './CustomScrollbars'; -import type { SettingsReduxState } from '../reducers/settings'; +import type { SettingsReduxState } from '../redux/settings/reducers'; export type SelectLocationProps = { settings: SettingsReduxState, diff --git a/app/components/Settings.js b/app/components/Settings.js index 9b8eff5321..ade9dba8f5 100644 --- a/app/components/Settings.js +++ b/app/components/Settings.js @@ -6,11 +6,11 @@ import { Layout, Container, Header } from './Layout'; import Switch from './Switch'; import CustomScrollbars from './CustomScrollbars'; -import type { UserReduxState } from '../reducers/user'; -import type { SettingsReduxState } from '../reducers/settings'; +import type { AccountReduxState } from '../redux/account/reducers'; +import type { SettingsReduxState } from '../redux/settings/reducers'; export type SettingsProps = { - user: UserReduxState, + account: AccountReduxState, settings: SettingsReduxState, onQuit: () => void, onClose: () => void, @@ -31,12 +31,12 @@ export default class Settings extends Component { } render(): React.Element<*> { - const isLoggedIn = this.props.user.status === 'ok'; + const isLoggedIn = this.props.account.status === 'ok'; let isOutOfTime = false, formattedPaidUntil = ''; - let paidUntilIso = this.props.user.paidUntil; + let paidUntilIso = this.props.account.paidUntil; if(isLoggedIn && paidUntilIso) { - let paidUntil = moment(this.props.user.paidUntil); + let paidUntil = moment(this.props.account.paidUntil); isOutOfTime = paidUntil.isSameOrBefore(moment()); formattedPaidUntil = paidUntil.fromNow(true) + ' left'; } diff --git a/app/containers/AccountPage.js b/app/containers/AccountPage.js index 5e695e1d4a..5e61bdf22d 100644 --- a/app/containers/AccountPage.js +++ b/app/containers/AccountPage.js @@ -2,7 +2,7 @@ import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; import { push } from 'react-router-redux'; import Account from '../components/Account'; -import userActions from '../actions/user'; +import accountActions from '../redux/account/actions'; import { shell } from 'electron'; import { links } from '../config'; @@ -11,7 +11,7 @@ const mapStateToProps = (state) => { }; const mapDispatchToProps = (dispatch, props) => { - const { logout } = bindActionCreators(userActions, dispatch); + const { logout } = bindActionCreators(accountActions, dispatch); return { onLogout: () => logout(props.backend), onClose: () => dispatch(push('/settings')), diff --git a/app/containers/ConnectPage.js b/app/containers/ConnectPage.js index fdcc9463af..ab288bd0e3 100644 --- a/app/containers/ConnectPage.js +++ b/app/containers/ConnectPage.js @@ -4,7 +4,7 @@ import { push } from 'react-router-redux'; import { shell } from 'electron'; import { links } from '../config'; import Connect from '../components/Connect'; -import connectActions from '../actions/connect'; +import connectActions from '../redux/connection/actions'; const mapStateToProps = (state) => { return state; diff --git a/app/containers/LoginPage.js b/app/containers/LoginPage.js index 163e55f145..c9dbe385f8 100644 --- a/app/containers/LoginPage.js +++ b/app/containers/LoginPage.js @@ -3,17 +3,17 @@ import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; import { push } from 'react-router-redux'; import Login from '../components/Login'; -import userActions from '../actions/user'; +import accountActions from '../redux/account/actions'; import { links } from '../config'; const mapStateToProps = (state) => state; const mapDispatchToProps = (dispatch, props) => { - const { loginChange, login } = bindActionCreators(userActions, dispatch); + const { loginChange, login } = bindActionCreators(accountActions, dispatch); const { backend } = props; return { onSettings: () => dispatch(push('/settings')), onLogin: (account) => login(backend, account), - onChange: (account) => loginChange({ account }), + onChange: (accountNumber) => loginChange({ accountNumber }), onFirstChangeAfterFailure: () => loginChange({ status: 'none', error: null }), onExternalLink: (type) => shell.openExternal(links[type]) }; diff --git a/app/containers/SelectLocationPage.js b/app/containers/SelectLocationPage.js index 462ffd7bb4..824274c15c 100644 --- a/app/containers/SelectLocationPage.js +++ b/app/containers/SelectLocationPage.js @@ -2,7 +2,7 @@ import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; import { push } from 'react-router-redux'; import SelectLocation from '../components/SelectLocation'; -import settingsActions from '../actions/settings'; +import settingsActions from '../redux/settings/actions'; const mapStateToProps = (state) => state; const mapDispatchToProps = (dispatch, props) => { diff --git a/app/containers/SettingsPage.js b/app/containers/SettingsPage.js index b6807a0a22..6152774c4b 100644 --- a/app/containers/SettingsPage.js +++ b/app/containers/SettingsPage.js @@ -2,7 +2,7 @@ import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; import { push } from 'react-router-redux'; import Settings from '../components/Settings'; -import settingsActions from '../actions/settings'; +import settingsActions from '../redux/settings/actions'; import { remote, shell } from 'electron'; import { links } from '../config'; diff --git a/app/enums.js b/app/enums.js deleted file mode 100644 index 6f4647efa6..0000000000 --- a/app/enums.js +++ /dev/null @@ -1,3 +0,0 @@ -// @flow -export type LoginState = 'none' | 'connecting' | 'failed' | 'ok'; -export type ConnectionState = 'disconnected' | 'connecting' | 'connected'; diff --git a/app/lib/backend-redux-actions.js b/app/lib/backend-redux-actions.js index 654651942f..bf5f2cc59d 100644 --- a/app/lib/backend-redux-actions.js +++ b/app/lib/backend-redux-actions.js @@ -1,6 +1,10 @@ +// @flow + import log from 'electron-log'; -import userActions from '../actions/user'; -import connectActions from '../actions/connect'; +import accountActions from '../redux/account/actions.js'; +import connectionActions from '../redux/connection/actions.js'; +import { Backend } from './backend.js'; +import type { ReduxStore } from '../redux/store.js'; /** * Add event listeners to translate backend events to redux dispatch. @@ -9,17 +13,18 @@ import connectActions from '../actions/connect'; * @param {Backend} backend * @param {Redux.Store} store */ -export default function mapBackendEventsToReduxActions(backend, store) { +export default function mapBackendEventsToReduxActions(backend: Backend, store: ReduxStore) { + const onUpdateIp = (clientIp) => { - store.dispatch(connectActions.connectionChange({ clientIp })); + store.dispatch(connectionActions.connectionChange({ clientIp })); }; const onUpdateLocation = (data) => { - store.dispatch(userActions.loginChange(data)); + store.dispatch(accountActions.loginChange(data)); }; const onConnecting = (serverAddress) => { - store.dispatch(connectActions.connectionChange({ + store.dispatch(connectionActions.connectionChange({ status: 'connecting', serverAddress })); @@ -29,19 +34,19 @@ export default function mapBackendEventsToReduxActions(backend, store) { if (error) { log.error('Unable to connect to', serverAddress, error); } else { - store.dispatch(connectActions.connectionChange({ status: 'connected' })); + store.dispatch(connectionActions.connectionChange({ status: 'connected' })); } }; const onDisconnect = () => { - store.dispatch(connectActions.connectionChange({ + store.dispatch(connectionActions.connectionChange({ status: 'disconnected', serverAddress: null })); }; const onLoggingIn = (info) => { - store.dispatch(userActions.loginChange(Object.assign({ + store.dispatch(accountActions.loginChange(Object.assign({ status: 'connecting', error: null }, info))); @@ -50,20 +55,20 @@ export default function mapBackendEventsToReduxActions(backend, store) { const onLogin = (info, error) => { const status = error ? 'failed' : 'ok'; const paidUntil = info.paidUntil ? info.paidUntil : null; - store.dispatch(userActions.loginChange({ paidUntil, status, error })); + store.dispatch(accountActions.loginChange({ paidUntil, status, error })); }; const onLogout = () => { - store.dispatch(userActions.loginChange({ + store.dispatch(accountActions.loginChange({ status: 'none', - account: '', + accountNumber: '', paidUntil: null, error: null })); }; const onReachability = (isOnline) => { - store.dispatch(connectActions.connectionChange({ isOnline })); + store.dispatch(connectionActions.connectionChange({ isOnline })); }; backend.on('updatedIp', onUpdateIp); diff --git a/app/lib/backend.js b/app/lib/backend.js index bf3a1382f1..076a49ca32 100644 --- a/app/lib/backend.js +++ b/app/lib/backend.js @@ -135,7 +135,7 @@ export class Backend { log.info('Attempting to login with account number', account); // emit: logging in - this._emit('logging', { account }, null); + this._emit('logging', { accountNumber: account }, null); this._ipc.getAccountData(account) .then( response => { diff --git a/app/actions/user.js b/app/redux/account/actions.js index 1b4d46ad2d..ab9b8cf463 100644 --- a/app/actions/user.js +++ b/app/redux/account/actions.js @@ -1,11 +1,11 @@ // @flow import { createAction } from 'redux-actions'; -import type { Backend } from '../lib/backend'; -import type { UserReduxState } from '../reducers/user'; +import type { Backend } from '../../lib/backend'; +import type { AccountReduxState } from './reducers.js'; import type { ReduxAction } from '../store'; -export type LoginChangeAction = <T: $Shape<UserReduxState>>(state: T) => ReduxAction<T>; +export type LoginChangeAction = <T: $Shape<AccountReduxState>>(state: T) => ReduxAction<T>; const loginChange: LoginChangeAction = createAction('USER_LOGIN_CHANGE'); const login = (backend: Backend, account: string) => () => backend.login(account); diff --git a/app/reducers/user.js b/app/redux/account/reducers.js index 8222e60299..06dfb05941 100644 --- a/app/reducers/user.js +++ b/app/redux/account/reducers.js @@ -1,14 +1,14 @@ // @flow import { handleActions } from 'redux-actions'; -import actions from '../actions/user'; +import actions from './actions.js'; -import type { Coordinate2d } from '../types'; +import type { Coordinate2d } from '../../types'; import type { ReduxAction } from '../store'; -import type { LoginState } from '../enums'; -import type { BackendError } from '../lib/backend'; +import type { BackendError } from '../../lib/backend'; -export type UserReduxState = { - account: ?string, +export type LoginState = 'none' | 'connecting' | 'failed' | 'ok'; +export type AccountReduxState = { + accountNumber: ?string, paidUntil: ?string, // ISO8601 location: ?Coordinate2d, country: ?string, @@ -17,8 +17,8 @@ export type UserReduxState = { error: ?BackendError }; -const initialState: UserReduxState = { - account: null, +const initialState: AccountReduxState = { + accountNumber: null, paidUntil: null, location: null, country: null, @@ -28,7 +28,7 @@ const initialState: UserReduxState = { }; export default handleActions({ - [actions.loginChange.toString()]: (state: UserReduxState, action: ReduxAction<$Shape<UserReduxState>>) => { + [actions.loginChange.toString()]: (state: AccountReduxState, action: ReduxAction<$Shape<AccountReduxState>>) => { return { ...state, ...action.payload }; } }, initialState); diff --git a/app/actions/connect.js b/app/redux/connection/actions.js index 11e88e99b0..d91c77f848 100644 --- a/app/actions/connect.js +++ b/app/redux/connection/actions.js @@ -2,10 +2,10 @@ import { clipboard } from 'electron'; import { createAction } from 'redux-actions'; import type { Backend } from '../lib/backend'; -import type { ConnectReduxState } from '../reducers/connect'; +import type { ConnectionReduxState } from './reducers.js'; import type { ReduxAction, ReduxGetStateFn, ReduxDispatchFn } from '../store'; -export type ConnectionChangeAction = <T: $Shape<ConnectReduxState>>(state: T) => ReduxAction<T>; +export type ConnectionChangeAction = <T: $Shape<ConnectionReduxState>>(state: T) => ReduxAction<T>; const connectionChange: ConnectionChangeAction = createAction('CONNECTION_CHANGE'); const connect = (backend: Backend, addr: string) => () => backend.connect(addr); diff --git a/app/reducers/connect.js b/app/redux/connection/reducers.js index 8ed4a564dc..bf44281602 100644 --- a/app/reducers/connect.js +++ b/app/redux/connection/reducers.js @@ -1,18 +1,18 @@ // @flow import { handleActions } from 'redux-actions'; -import actions from '../actions/connect'; +import actions from './actions'; import type { ReduxAction } from '../store'; -import type { ConnectionState } from '../enums'; -export type ConnectReduxState = { +export type ConnectionState = 'disconnected' | 'connecting' | 'connected'; +export type ConnectionReduxState = { status: ConnectionState, isOnline: boolean, serverAddress: ?string, clientIp: ?string }; -const initialState: ConnectReduxState = { +const initialState: ConnectionReduxState = { status: 'disconnected', isOnline: true, serverAddress: null, @@ -20,7 +20,7 @@ const initialState: ConnectReduxState = { }; export default handleActions({ - [actions.connectionChange.toString()]: (state: ConnectReduxState, action: ReduxAction<$Shape<ConnectReduxState>>) => { + [actions.connectionChange.toString()]: (state: ConnectionReduxState, action: ReduxAction<$Shape<ConnectionReduxState>>) => { return { ...state, ...action.payload }; } }, initialState); diff --git a/app/actions/settings.js b/app/redux/settings/actions.js index 4788a88f85..16a7a79414 100644 --- a/app/actions/settings.js +++ b/app/redux/settings/actions.js @@ -1,7 +1,7 @@ // @flow import { createAction } from 'redux-actions'; -import type { SettingsReduxState } from '../reducers/settings'; +import type { SettingsReduxState } from './reducers'; import type { ReduxAction } from '../store'; export type UpdateSettingsAction = <T: $Shape<SettingsReduxState>>(state: T) => ReduxAction<T>; diff --git a/app/reducers/settings.js b/app/redux/settings/reducers.js index 2339d1fc3a..bd899d21f9 100644 --- a/app/reducers/settings.js +++ b/app/redux/settings/reducers.js @@ -1,7 +1,8 @@ // @flow import { handleActions } from 'redux-actions'; -import { defaultServer } from '../config'; -import actions from '../actions/settings'; +import actions from './actions'; + +import { defaultServer } from '../../config'; import type { ReduxAction } from '../store'; diff --git a/app/store.js b/app/redux/store.js index 83f7ff5430..e86fc1373c 100644 --- a/app/store.js +++ b/app/redux/store.js @@ -3,22 +3,23 @@ import { createStore, applyMiddleware, combineReducers, compose } from 'redux'; import { routerMiddleware, routerReducer, push, replace } from 'react-router-redux'; import persistState from 'redux-localstorage'; import thunk from 'redux-thunk'; -import user from './reducers/user'; -import connect from './reducers/connect'; -import settings from './reducers/settings'; -import userActions from './actions/user'; -import connectActions from './actions/connect'; -import settingsActions from './actions/settings'; + +import account from './account/reducers.js'; +import accountActions from './account/actions.js'; +import connection from './connection/reducers.js'; +import connectionActions from './connection/actions.js'; +import settings from './settings/reducers.js'; +import settingsActions from './settings/actions.js'; import type { Store, Dispatch } from 'redux'; import type { History } from 'history'; -import type { UserReduxState } from './reducers/user'; -import type { ConnectReduxState } from './reducers/connect'; -import type { SettingsReduxState } from './reducers/settings'; +import type { AccountReduxState } from './account/reducers.js'; +import type { ConnectionReduxState } from './connection/reducers.js'; +import type { SettingsReduxState } from './settings/reducers.js'; export type ReduxState = { - user: UserReduxState, - connect: ConnectReduxState, + account: AccountReduxState, + connection: ConnectionReduxState, settings: SettingsReduxState }; export type ReduxAction<T> = { type: string, payload: T }; @@ -30,15 +31,15 @@ export default function configureStore(initialState: ?ReduxState, routerHistory: const router = routerMiddleware(routerHistory); const actionCreators: { [string]: Function } = { - ...userActions, - ...connectActions, + ...accountActions, + ...connectionActions, ...settingsActions, pushRoute: (route) => push(route), replaceRoute: (route) => replace(route), }; const reducers = { - user, connect, settings, router: routerReducer + account, connection, settings, router: routerReducer }; const middlewares = [ thunk, router ]; diff --git a/app/routes.js b/app/routes.js index d815d12100..5440027c6b 100644 --- a/app/routes.js +++ b/app/routes.js @@ -53,8 +53,8 @@ export default function makeRoutes(getState, componentProps) { const PrivateRoute = ({ component, ...rest }) => { return ( <Route {...rest} render={ (routeProps) => { - const { user } = getState(); - const isLoggedIn = user.status === 'ok'; + const { account } = getState(); + const isLoggedIn = account.status === 'ok'; if(isLoggedIn) { return renderMergedProps(component, routeProps, ...rest); @@ -74,8 +74,8 @@ export default function makeRoutes(getState, componentProps) { const LoginRoute = ({ component, ...rest }) => { return ( <Route {...rest} render={ (routeProps) => { - const { user } = getState(); - const isLoggedIn = user.status === 'ok'; + const { account } = getState(); + const isLoggedIn = account.status === 'ok'; if(isLoggedIn) { return (<Redirect to={ '/connect' } />); diff --git a/test/actions.spec.js b/test/actions.spec.js index d1bffe2d5e..af98cd83a9 100644 --- a/test/actions.spec.js +++ b/test/actions.spec.js @@ -1,10 +1,11 @@ // @flow + import { expect } from 'chai'; import { filterMinorActions, mockState, mockStore } from './mocks/redux'; import { Backend } from '../app/lib/backend'; import { newMockIpc } from './mocks/ipc'; -import userActions from '../app/actions/user'; -import connectActions from '../app/actions/connect'; +import accountActions from '../app/redux/account/actions'; +import connectionActions from '../app/redux/connection/actions'; import mapBackendEventsToReduxActions from '../app/lib/backend-redux-actions'; describe('actions', function() { @@ -12,7 +13,7 @@ describe('actions', function() { it('should login', (done) => { const expectedActions = [ - { type: 'USER_LOGIN_CHANGE', payload: { status: 'connecting', error: null, account: '1'} }, + { type: 'USER_LOGIN_CHANGE', payload: { status: 'connecting', error: null, accountNumber: '1'} }, { type: 'USER_LOGIN_CHANGE', payload: { paidUntil: '2013-01-01T00:00:00.000Z', status: 'ok', error: undefined } } ]; const store = mockStore(mockState()); @@ -33,12 +34,12 @@ describe('actions', function() { done(); }); - store.dispatch(userActions.login(backend, '1')); + store.dispatch(accountActions.login(backend, '1')); }); it('should logout', (done) => { const expectedActions = [ - { type: 'USER_LOGIN_CHANGE', payload: { account: '', paidUntil: null, status: 'none', error: null } }, + { type: 'USER_LOGIN_CHANGE', payload: { accountNumber: '', paidUntil: null, status: 'none', error: null } }, ]; const store = mockStore(mockState()); @@ -53,7 +54,7 @@ describe('actions', function() { done(); }); - store.dispatch(userActions.logout(backend)); + store.dispatch(accountActions.logout(backend)); }); it('should connect to VPN server', (done) => { @@ -84,9 +85,9 @@ describe('actions', function() { }); backend.once('login', () => { - store.dispatch(connectActions.connect(backend, '1.2.3.4')); + store.dispatch(connectionActions.connect(backend, '1.2.3.4')); }); - store.dispatch(userActions.login(backend, '1')); + store.dispatch(accountActions.login(backend, '1')); }); it('should disconnect from VPN server', (done) => { @@ -95,8 +96,8 @@ describe('actions', function() { ]; let state = Object.assign(mockState(), { - user: { - account: '3333234567890', + account: { + accountNumber: '3333234567890', paidUntil: '2038-01-01T00:00:00.000Z', status: 'ok' }, @@ -117,18 +118,18 @@ describe('actions', function() { done(); }); - store.dispatch(connectActions.disconnect(backend)); + store.dispatch(connectionActions.disconnect(backend)); }); it('should disconnect from VPN server on logout', (done) => { const expectedActions = [ - { type: 'USER_LOGIN_CHANGE', payload: { account: '', paidUntil: null, status: 'none', error: null } }, + { type: 'USER_LOGIN_CHANGE', payload: { accountNumber: '', paidUntil: null, status: 'none', error: null } }, { type: 'CONNECTION_CHANGE', payload: { serverAddress: null, status: 'disconnected' } } ]; let state = Object.assign(mockState(), { - user: { - account: '3333234567890', + account: { + accountNumber: '3333234567890', paidUntil: '2038-01-01T00:00:00.000Z', status: 'ok' }, @@ -149,7 +150,7 @@ describe('actions', function() { done(); }); - store.dispatch(userActions.logout(backend)); + store.dispatch(accountActions.logout(backend)); }); }); diff --git a/test/mocks/redux.js b/test/mocks/redux.js index 0d4d73518f..070c76c9b2 100644 --- a/test/mocks/redux.js +++ b/test/mocks/redux.js @@ -10,12 +10,12 @@ const middlewares = [ thunk ]; export const mockStore = configureMockStore(middlewares); export const mockState = () => { return { - user: { - account: null, + account: { + accountNumber: null, status: 'none', error: null }, - connect: { + connection: { status: 'disconnected', serverAddress: null, clientIp: null diff --git a/test/reducers.spec.js b/test/reducers.spec.js index 7a5470e930..5a0ec8f0a7 100644 --- a/test/reducers.spec.js +++ b/test/reducers.spec.js @@ -1,7 +1,9 @@ +// @flow + import { expect } from 'chai'; -import userReducer from '../app/reducers/user'; -import connectReducer from '../app/reducers/connect'; -import settingsReducer from '../app/reducers/settings'; +import accountReducer from '../app/redux/account/reducers'; +import connectionReducer from '../app/redux/connection/reducers'; +import settingsReducer from '../app/redux/settings/reducers'; import { defaultServer } from '../app/config'; describe('reducers', () => { @@ -16,7 +18,7 @@ describe('reducers', () => { } }; const test = Object.assign({}, action.payload); - expect(userReducer({}, action)).to.deep.equal(test); + expect(accountReducer({}, action)).to.deep.equal(test); }); it('should handle CONNECTION_CHANGE', () => { @@ -29,7 +31,7 @@ describe('reducers', () => { } }; const test = Object.assign({}, action.payload); - expect(connectReducer({}, action)).to.deep.equal(test); + expect(connectionReducer({}, action)).to.deep.equal(test); }); it('should handle SETTINGS_UPDATE', () => { diff --git a/test/routing.spec.js b/test/routing.spec.js index 062c1e5246..66fe3e72e3 100644 --- a/test/routing.spec.js +++ b/test/routing.spec.js @@ -1,7 +1,9 @@ +// @flow + import { expect } from 'chai'; import { filterMinorActions, mockState, mockStore } from './mocks/redux'; -import userActions from '../app/actions/user'; +import accountActions from '../app/redux/account/actions'; import mapBackendEventsToRouter from '../app/lib/backend-routing'; import { Backend } from '../app/lib/backend'; import { newMockIpc } from './mocks/ipc'; @@ -15,7 +17,7 @@ describe('routing', function() { ]; let state = Object.assign(mockState(), { - user: { + account: { account: '1111234567890', status: 'ok' } @@ -25,7 +27,7 @@ describe('routing', function() { const backend = new Backend(newMockIpc()); mapBackendEventsToRouter(backend, store); - store.dispatch(userActions.logout(backend)); + store.dispatch(accountActions.logout(backend)); setTimeout(() => { const storeActions = filterMinorActions(store.getActions()); @@ -47,7 +49,7 @@ describe('routing', function() { expect(storeActions).deep.equal(expectedActions); done(); }); - store.dispatch(userActions.login(backend, '1')); + store.dispatch(accountActions.login(backend, '1')); }); }); |
