Skip to content

Commit

Permalink
reduce/remove boilerplate by using bindActionCreators \o/
Browse files Browse the repository at this point in the history
  • Loading branch information
jebeck committed Jan 22, 2016
1 parent 5ce9b26 commit 0686be9
Showing 1 changed file with 56 additions and 103 deletions.
159 changes: 56 additions & 103 deletions lib/containers/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import _ from 'lodash';
import React, { Component, PropTypes } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';

import bows from '../bows.js';

Expand Down Expand Up @@ -46,27 +47,19 @@ export default class App extends Component {
constructor(props) {
super(props);
this.log = bows('App');
this.handleAddDevice = this.handleAddDevice.bind(this);
this.handleClickChooseDevices = this.handleClickChooseDevices.bind(this);
this.handleDismissDropdown = this.handleDismissDropdown.bind(this);
this.handleLogin = this.handleLogin.bind(this);
this.handleLogout = this.handleLogout.bind(this);
this.handleRemoveDevice = this.handleRemoveDevice.bind(this);
this.handleSetTimezone = this.handleSetTimezone.bind(this);
this.handleSetUploadTargetUser = this.handleSetUploadTargetUser.bind(this);
this.handleStoreTargets = this.handleStoreTargets.bind(this);
this.handleToggleDropdown = this.handleToggleDropdown.bind(this);
}

componentWillMount() {
const { api, dispatch } = this.props;
dispatch(asyncActions.doAppInit(config, {
const { api } = this.props;
this.props.async.doAppInit(config, {
api,
carelink,
device,
localStore,
log: this.log
}));
});
}

render() {
Expand All @@ -80,69 +73,21 @@ export default class App extends Component {
);
}

handleAddDevice(userId, deviceKey) {
const { dispatch } = this.props;
dispatch(syncActions.addTargetDevice(userId, deviceKey));
}

handleClickChooseDevices() {
const { dispatch } = this.props;
dispatch(syncActions.setPage(pages.SETTINGS, true));
const { setPage, toggleDropdown } = this.props.sync;
// ensure dropdown closes after click
dispatch(
syncActions.toggleDropdown(true, actionSources.UNDER_THE_HOOD)
);
setPage(pages.SETTINGS, true);
toggleDropdown(true, actionSources.UNDER_THE_HOOD);
}

handleDismissDropdown() {
const { dispatch } = this.props;
const { dropdown } = this.props;
// only toggle the dropdown by clicking elsewhere if it's open
if (this.props.dropdown === true) {
dispatch(syncActions.toggleDropdown(this.props.dropdown));
if (dropdown === true) {
this.props.sync.toggleDropdown(dropdown);
}
}

handleLogin(creds, opts) {
const { dispatch } = this.props;
dispatch(asyncActions.doLogin(creds, opts));
}

handleLogout() {
const { dispatch } = this.props;
dispatch(asyncActions.doLogout());
}

handleRemoveDevice(userId, deviceKey) {
const { dispatch } = this.props;
dispatch(syncActions.removeTargetDevice(userId, deviceKey));
}

handleSetTimezone(userId, timezoneName) {
const { dispatch } = this.props;
dispatch(syncActions.setTargetTimezone(userId, timezoneName));
}

handleSetUploadTargetUser(userId) {
const { dispatch } = this.props;
dispatch(syncActions.setUploadTargetUser(userId));
}

handleStoreTargets() {
const { dispatch } = this.props;
dispatch(asyncActions.putTargetsInStorage());
}

handleToggleDropdown() {
const { dispatch } = this.props;
dispatch(syncActions.toggleDropdown(this.props.dropdown));
}

showUserSelectionDropdown() {
const { users } = this.props;
return (!_.isEmpty(users.targetsForUpload) &&
users.targetsForUpload.length > 1);
}

renderHeader() {
const { dropdown, isLoggedIn, page, url, users } = this.props;
if (page === pages.LOADING) {
Expand All @@ -162,16 +107,16 @@ export default class App extends Component {
<LoggedInAs
dropMenu={dropdown}
user={users[users.loggedInUser]}
onClicked={this.handleToggleDropdown}
onClicked={this.props.sync.toggleDropdown.bind(this, this.props.dropdown)}
onChooseDevices={this.handleClickChooseDevices}
onLogout={this.handleLogout} />
onLogout={this.props.async.doLogout} />
);
}

renderPage() {
const { devices, os, page, url, users } = this.props;
const { devices, os, page, showingUserSelectionDropdown, url, users } = this.props;

let userDropdown = this.showUserSelectionDropdown() ?
let userDropdown = showingUserSelectionDropdown ?
this.renderUserDropdown() : null;

if (page === pages.LOADING) {
Expand Down Expand Up @@ -199,11 +144,11 @@ export default class App extends Component {
targetDevices={this.props.selectedTargetDevices}
targetId={users.uploadTargetUser}
timezoneIsSelected={Boolean(this.props.selectedTimezone)}
userDropdownShowing={this.showUserSelectionDropdown()}
userDropdownShowing={showingUserSelectionDropdown}
userIsSelected={users.uploadTargetUser !== null}
addDevice={this.handleAddDevice}
removeDevice={this.handleRemoveDevice}
onDone={this.handleStoreTargets} />
addDevice={this.props.sync.addTargetDevice}
removeDevice={this.props.sync.removeTargetDevice}
onDone={this.props.async.putTargetsInStorage} />
</div>
);
} else {
Expand All @@ -227,7 +172,7 @@ export default class App extends Component {
const { users } = this.props;
return (
<TimezoneDropdown
onTimezoneChange={this.handleSetTimezone}
onTimezoneChange={this.props.sync.setTargetTimezone}
selectorLabel={'Choose timezone'}
targetId={users.uploadTargetUser || null}
targetTimezone={this.props.selectedTimezone} />
Expand All @@ -239,7 +184,7 @@ export default class App extends Component {
return (
<UserDropdown
page={page}
onGroupChange={this.handleSetUploadTargetUser}
onGroupChange={this.props.sync.setUploadTargetUser}
users={users}
isUploadInProgress={null}
targetId={users.uploadTargetUser} />
Expand All @@ -251,32 +196,40 @@ App.propTypes = {
page: React.PropTypes.string.isRequired
};

function select(state) {
return {
// plain state
devices: state.devices,
dropdown: state.dropdown,
os: state.os,
page: state.page,
version: state.version,
url: state.url,
users: state.users,
// derived state
isLoggedIn: !_.includes([pages.LOADING, pages.LOGIN], state.page),
selectedTargetDevices: _.get(
state.users[state.users.uploadTargetUser],
['targets', 'devices'],
// fall back to the targets stored under 'noUserSelected', if any
_.get(state.users['noUserSelected'], ['targets', 'devices'], [])
),
selectedTimezone: _.get(
state.users[state.users.uploadTargetUser],
['targets', 'timezone'],
// fall back to the timezone stored under 'noUserSelected', if any
_.get(state.users['noUserSelected'], ['targets', 'timezone'], null)
)
};
}

// wrap the component to inject dispatch and state into it
export default connect(select)(App);
export default connect(
(state) => {
return {
// plain state
devices: state.devices,
dropdown: state.dropdown,
os: state.os,
page: state.page,
version: state.version,
url: state.url,
users: state.users,
// derived state
isLoggedIn: !_.includes([pages.LOADING, pages.LOGIN], state.page),
selectedTargetDevices: _.get(
state.users[state.users.uploadTargetUser],
['targets', 'devices'],
// fall back to the targets stored under 'noUserSelected', if any
_.get(state.users['noUserSelected'], ['targets', 'devices'], [])
),
selectedTimezone: _.get(
state.users[state.users.uploadTargetUser],
['targets', 'timezone'],
// fall back to the timezone stored under 'noUserSelected', if any
_.get(state.users['noUserSelected'], ['targets', 'timezone'], null)
),
showingUserSelectionDropdown: !_.isEmpty(state.users.targetsForUpload) &&
state.users.targetsForUpload.length > 1
};
},
(dispatch) => {
return {
async: bindActionCreators(asyncActions, dispatch),
sync: bindActionCreators(syncActions, dispatch)
};
}
)(App);

0 comments on commit 0686be9

Please sign in to comment.