summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorErik Larkö <erik@mullvad.net>2017-06-26 15:19:03 +0200
committerErik Larkö <erik@mullvad.net>2017-07-03 12:41:51 +0200
commit1bb1bdbe31da5c23e4cb2b414a8756c645049998 (patch)
tree5d875318d24b327b20da40762b31115c608f0652
parent4e8f44c7ef6ffee09d9d3abd70bfd093f87d6b18 (diff)
downloadmullvadvpn-1bb1bdbe31da5c23e4cb2b414a8756c645049998.tar.xz
mullvadvpn-1bb1bdbe31da5c23e4cb2b414a8756c645049998.zip
Moved the redux stuff into separate folder and renamed user->account and connect->connection
-rw-r--r--app/app.js23
-rw-r--r--app/components/Account.js9
-rw-r--r--app/components/Connect.js38
-rw-r--r--app/components/Login.js13
-rw-r--r--app/components/SelectLocation.js2
-rw-r--r--app/components/Settings.js12
-rw-r--r--app/containers/AccountPage.js4
-rw-r--r--app/containers/ConnectPage.js2
-rw-r--r--app/containers/LoginPage.js4
-rw-r--r--app/containers/SelectLocationPage.js2
-rw-r--r--app/containers/SettingsPage.js2
-rw-r--r--app/enums.js3
-rw-r--r--app/lib/backend-redux-actions.js29
-rw-r--r--app/redux/account/actions.js (renamed from app/actions/user.js)6
-rw-r--r--app/redux/account/reducers.js (renamed from app/reducers/user.js)14
-rw-r--r--app/redux/connection/actions.js (renamed from app/actions/connect.js)4
-rw-r--r--app/redux/connection/reducers.js (renamed from app/reducers/connect.js)10
-rw-r--r--app/redux/settings/actions.js (renamed from app/actions/settings.js)2
-rw-r--r--app/redux/settings/reducers.js (renamed from app/reducers/settings.js)5
-rw-r--r--app/redux/store.js (renamed from app/store.js)29
-rw-r--r--app/routes.js8
-rw-r--r--test/actions.spec.js21
-rw-r--r--test/mocks/redux.js4
-rw-r--r--test/reducers.spec.js12
-rw-r--r--test/routing.spec.js10
25 files changed, 138 insertions, 130 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..b592bbd850 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 || '');
+ let paidUntil = moment(this.props.account.paidUntil);
+ let formattedAccountId = formatAccount(this.props.account.account || '');
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..dc0f9e9baa 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,7 +28,7 @@ export default class Login extends Component {
onFocus = () => this.setState({ isActive: true });
onBlur = () => this.setState({ isActive: false });
onLogin = () => {
- const { account } = this.props.user;
+ const { account } = this.props.account;
if(account && account.length > 0) {
this.props.onLogin(account);
}
@@ -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 { account, status, error } = this.props.account;
const title = this.formTitle(status);
const subtitle = this.formSubtitle(status, error);
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..0b09e673b5 100644
--- a/app/containers/LoginPage.js
+++ b/app/containers/LoginPage.js
@@ -3,12 +3,12 @@ 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')),
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..0ca63b0aab 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,11 +55,11 @@ 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: '',
paidUntil: null,
@@ -63,7 +68,7 @@ export default function mapBackendEventsToReduxActions(backend, store) {
};
const onReachability = (isOnline) => {
- store.dispatch(connectActions.connectionChange({ isOnline }));
+ store.dispatch(connectionActions.connectionChange({ isOnline }));
};
backend.on('updatedIp', onUpdateIp);
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..fb85008930 100644
--- a/app/reducers/user.js
+++ b/app/redux/account/reducers.js
@@ -1,13 +1,13 @@
// @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 = {
+export type LoginState = 'none' | 'connecting' | 'failed' | 'ok';
+export type AccountReduxState = {
account: ?string,
paidUntil: ?string, // ISO8601
location: ?Coordinate2d,
@@ -17,7 +17,7 @@ export type UserReduxState = {
error: ?BackendError
};
-const initialState: UserReduxState = {
+const initialState: AccountReduxState = {
account: null,
paidUntil: null,
location: 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..1b9da89125 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.js';
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..683927de86 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() {
@@ -33,7 +34,7 @@ describe('actions', function() {
done();
});
- store.dispatch(userActions.login(backend, '1'));
+ store.dispatch(accountActions.login(backend, '1'));
});
it('should logout', (done) => {
@@ -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,7 +96,7 @@ describe('actions', function() {
];
let state = Object.assign(mockState(), {
- user: {
+ account: {
account: '3333234567890',
paidUntil: '2038-01-01T00:00:00.000Z',
status: 'ok'
@@ -117,7 +118,7 @@ describe('actions', function() {
done();
});
- store.dispatch(connectActions.disconnect(backend));
+ store.dispatch(connectionActions.disconnect(backend));
});
it('should disconnect from VPN server on logout', (done) => {
@@ -127,7 +128,7 @@ describe('actions', function() {
];
let state = Object.assign(mockState(), {
- user: {
+ account: {
account: '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..d120eafec1 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: {
account: 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'));
});
});