update react-bootstrap

This commit is contained in:
zmagod 2017-09-28 15:00:54 +02:00
parent 26b526d61b
commit c8c8afdd1d
13 changed files with 175 additions and 475 deletions

View file

@ -76,21 +76,6 @@ module ClientApi
:time_zone)
end
def change_notification(dinamic_param, params)
user = current_user
user[dinamic_param] = params['status']
status =
if user.save
user[dinamic_param]
else
user.reload[dinamic_param]
end
respond_to do |format|
format.json { render json: { status: status } }
end
end
def success_response(template = nil, locals = nil)
respond_to do |format|
format.json do

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

View file

@ -1,22 +1,7 @@
import axios from "../../config/axios";
import {
CHANGE_USER_TIMEZONE_PATH,
CHANGE_USER_ASSIGNEMENTS_NOTIFICATION_PATH,
CHANGE_USER_ASSIGNMENTS_NOTIFICATION_EMAIL_PATH,
CHANGE_USER_RECENT_NOTIFICATION_PATH,
CHANGE_USER_RECENT_NOTIFICATION_EMAIL_PATH,
CHANGE_USER_SYSTEM_MESSAGE_NOTIFICATION_EMAIL_PATH
} from "../../config/api_endpoints";
import {
SET_CURRENT_USER,
CHANGE_CURRENT_USER_TIMEZONE,
CHANGE_ASSIGNMENTS_NOTIFICATION,
CHANGE_ASSIGNMENTS_NOTIFICATION_EMAIL,
CHANGE_RECENT_NOTIFICATION,
CHANGE_RECENT_NOTIFICATION_EMAIL,
CHANGE_SYSTEM_MESSAGE_NOTIFICATION_EMAIL
} from "../../config/action_types";
export function addCurrentUser(data) {
@ -25,126 +10,3 @@ export function addCurrentUser(data) {
payload: data
};
}
export function saveTimezone({ timezone }) {
return {
type: CHANGE_CURRENT_USER_TIMEZONE,
payload: timezone
};
}
export function changeTimezone(timezone) {
return dispatch => {
axios
.post(CHANGE_USER_TIMEZONE_PATH, { withCredentials: true, timezone })
.then(({ data }) => {
dispatch(saveTimezone(data));
})
.catch(err => console.log(err));
};
}
export function saveAssignmentsNotification({ status }) {
return {
type: CHANGE_ASSIGNMENTS_NOTIFICATION,
payload: status
};
}
export function changeAssignmentsNotification(status) {
return dispatch => {
axios
.post(CHANGE_USER_ASSIGNEMENTS_NOTIFICATION_PATH, {
withCredentials: true,
status
})
.then(({ data }) => {
dispatch(saveAssignmentsNotification(data));
})
.catch(err => console.log(err));
};
}
export function saveAssignmentsNotificationEmail({ status }) {
return {
type: CHANGE_ASSIGNMENTS_NOTIFICATION_EMAIL,
payload: status
};
}
export function changeAssignmentsNotificationEmail(status) {
return dispatch => {
axios
.post(CHANGE_USER_ASSIGNMENTS_NOTIFICATION_EMAIL_PATH, {
withCredentials: true,
status
})
.then(({ data }) => {
dispatch(saveAssignmentsNotificationEmail(data));
})
.catch(err => console.log(err));
};
}
export function saveRecentNotification({ status }) {
return {
type: CHANGE_RECENT_NOTIFICATION,
payload: status
};
}
export function changeRecentNotification(status) {
return dispatch => {
axios
.post(CHANGE_USER_RECENT_NOTIFICATION_PATH, {
withCredentials: true,
status
})
.then(({ data }) => {
dispatch(saveRecentNotification(data));
})
.catch(err => console.log(err));
};
}
export function saveRecentNotificationEmail({ status }) {
return {
type: CHANGE_RECENT_NOTIFICATION_EMAIL,
payload: status
};
}
export function changeRecentNotificationEmail(status) {
return dispatch => {
axios
.post(CHANGE_USER_RECENT_NOTIFICATION_EMAIL_PATH, {
withCredentials: true,
status
})
.then(({ data }) => {
dispatch(saveRecentNotificationEmail(data));
})
.catch(err => console.log(err));
};
}
export function saveSystemMessageNotificationEmail({ status }) {
return {
type: CHANGE_SYSTEM_MESSAGE_NOTIFICATION_EMAIL,
payload: status
};
}
export function changeSystemMessageNotificationEmail(status) {
return dispatch => {
axios
.post(CHANGE_USER_SYSTEM_MESSAGE_NOTIFICATION_EMAIL_PATH, {
withCredentials: true,
status
})
.then(({ data }) => {
dispatch(saveSystemMessageNotificationEmail(data));
})
.catch(err => console.log(err));
};
}

View file

@ -1,54 +1,17 @@
import {
SET_CURRENT_USER,
CHANGE_CURRENT_USER_TIMEZONE,
CHANGE_ASSIGNMENTS_NOTIFICATION,
CHANGE_ASSIGNMENTS_NOTIFICATION_EMAIL,
CHANGE_RECENT_NOTIFICATION,
CHANGE_RECENT_NOTIFICATION_EMAIL,
CHANGE_SYSTEM_MESSAGE_NOTIFICATION_EMAIL
} from "../../config/action_types";
import { SET_CURRENT_USER } from "../../config/action_types";
export function currentUser(
state = {
id: 0,
fullName: "",
initials: "",
email: "",
avatarPath: "",
avatarThumbPath: "",
timezone: "",
assignmentsNotification: false,
assignmentsNotificationEmail: false,
recentNotification: false,
recentNotificationEmail: false,
systemMessageNotificationEmail: false
},
action
) {
switch (action.type) {
case SET_CURRENT_USER:
return Object.assign({}, state, action.payload);
case CHANGE_CURRENT_USER_TIMEZONE:
return Object.assign({}, state, { timezone: action.payload });
case CHANGE_ASSIGNMENTS_NOTIFICATION:
return Object.assign({}, state, {
assignmentsNotification: action.payload
});
case CHANGE_ASSIGNMENTS_NOTIFICATION_EMAIL:
return Object.assign({}, state, {
assignmentsNotificationEmail: action.payload
});
case CHANGE_RECENT_NOTIFICATION:
return Object.assign({}, state, { recentNotification: action.payload });
case CHANGE_RECENT_NOTIFICATION_EMAIL:
return Object.assign({}, state, {
recentNotificationEmail: action.payload
});
case CHANGE_SYSTEM_MESSAGE_NOTIFICATION_EMAIL:
return Object.assign({}, state, {
systemMessageNotificationEmail: action.payload
});
default:
return state;
const initialState = {
id: 0,
fullName: "",
initials: "",
email: "",
avatarPath: "",
avatarThumbPath: ""
};
export function currentUser(state = initialState, action) {
if (action.type === SET_CURRENT_USER) {
return Object.assign({}, state, action.payload);
}
return state;
}

View file

@ -9,16 +9,6 @@ export const DESTROY_GLOBAL_ACTIVITIES_DATA = "DESTROY_GLOBAL_ACTIVITIES_DATA";
// users
export const SET_CURRENT_USER = "SET_CURRENT_USER";
export const CHANGE_CURRENT_USER_TIMEZONE = "CHANGE_CURRENT_USER_TIMEZONE";
export const CHANGE_ASSIGNMENTS_NOTIFICATION =
"CHANGE_ASSIGNMENTS_NOTIFICATION";
export const CHANGE_ASSIGNMENTS_NOTIFICATION_EMAIL =
"CHANGE_ASSIGNMENTS_NOTIFICATION_EMAIL";
export const CHANGE_RECENT_NOTIFICATION = "CHANGE_RECENT_NOTIFICATION";
export const CHANGE_RECENT_NOTIFICATION_EMAIL =
"CHANGE_RECENT_NOTIFICATION_EMAIL";
export const CHANGE_SYSTEM_MESSAGE_NOTIFICATION_EMAIL =
"CHANGE_SYSTEM_MESSAGE_NOTIFICATION_EMAIL";
// user teams
export const LEAVE_TEAM = "LEAVE_TEAM";

View file

@ -17,8 +17,6 @@ export const SEARCH_PATH = "/search";
// notifications
export const RECENT_NOTIFICATIONS_PATH = "/client_api/recent_notifications";
// users
// info dropdown_title
export const CUSTOMER_SUPPORT_LINK = "http://scinote.net/support";
export const TUTORIALS_LINK = "http://scinote.net/product/tutorials/";

View file

@ -55,6 +55,7 @@ export default {
time_zone_warning:
"Time zone setting affects all time & date fields throughout application.",
repeat_tutorial: "Repeat tutorial",
notifications: "Notifications",
profile: "Profile",
preferences: "Preferences",
assignement: "Assignement",

View file

@ -1,10 +1,17 @@
import React, { Component } from "react";
import PropTypes from "prop-types";
import { string, bool, func } from "prop-types";
import styled from "styled-components";
import { FormattedMessage } from "react-intl";
import NotificationsSwitchGroup from "./NotificationsSwitchGroup";
import { updateUser } from "../../../../../services/api/users_api";
import NotificationsSwitch from "./NotificationsSwitch";
import {
RECENT_NOTIFICATION,
SYSTEM_NOTIFICATION,
ASSIGNMENT_NOTIFICATION
} from "../../../../../config/constants/strings";
import { WHITE_COLOR } from "../../../../../config/constants/colors";
import avatarImg from "../../../../../assets/missing.png";
const Wrapper = styled.div`margin-bottom: 6px;`;
@ -40,29 +47,66 @@ const Image = styled.span`
class NotificationsGroup extends Component {
constructor(props) {
super(props);
this.notificationImage = this.notificationImage.bind(this);
this.inAppNotificationField = this.inAppNotificationField.bind(this);
this.emailNotificationField = this.emailNotificationField.bind(this);
this.updateStatus = this.updateStatus.bind(this);
}
render() {
let imgOrIcon;
if (this.props.imgUrl === "") {
imgOrIcon = (
<Icon style={{ backgroundColor: this.props.iconBackground }}>
<i className={this.props.iconClasses} />
</Icon>
);
} else {
imgOrIcon = (
notificationImage() {
if (this.props.type === RECENT_NOTIFICATION) {
return (
<Image>
<img src={this.props.imgUrl} alt="default avatar" />
<img src={avatarImg} alt="default avatar" />
</Image>
);
}
return (
<Icon style={{ backgroundColor: this.props.iconBackground }}>
<i className={this.props.iconClasses} />
</Icon>
);
}
inAppNotificationField() {
switch (this.props.type) {
case ASSIGNMENT_NOTIFICATION:
return "assignmentsNotification";
case RECENT_NOTIFICATION:
return "recentNotification";
case SYSTEM_NOTIFICATION:
return "systemMessageEmailNofification";
default:
return "";
}
}
emailNotificationField() {
switch (this.props.type) {
case ASSIGNMENT_NOTIFICATION:
return "assignmentsEmailNotification";
case RECENT_NOTIFICATION:
return "recentEmailNotification";
default:
return "";
}
}
updateStatus(actionType, value) {
if (actionType === "inAppNotification") {
const inAppField = this.inAppNotificationField();
updateUser({ [inAppField]: value }).then(() => this.props.reloadInfo());
} else if (actionType === "emailNotification") {
const emailField = this.emailNotificationField();
updateUser({ [emailField]: value }).then(() => this.props.reloadInfo());
}
}
render() {
return (
<Wrapper className="row">
<IconWrapper className="col-sm-1">
{imgOrIcon}
{this.notificationImage()}
</IconWrapper>
<div className="col-sm-10">
<h5>
@ -73,7 +117,22 @@ class NotificationsGroup extends Component {
<p>
<FormattedMessage id={this.props.subtitle} />
</p>
<NotificationsSwitchGroup type={this.props.type} />
<div>
<NotificationsSwitch
title="settings_page.show_in_scinote"
status={this.props.inAppNotification}
updateStatus={value =>
this.updateStatus("inAppNotification", value)}
isDisabled={false}
/>
<NotificationsSwitch
title="settings_page.notify_me_via_email"
status={this.props.emailNotification}
updateStatus={value =>
this.updateStatus("emailNotification", value)}
isDisabled={this.props.type === SYSTEM_NOTIFICATION}
/>
</div>
</div>
</Wrapper>
);
@ -81,12 +140,21 @@ class NotificationsGroup extends Component {
}
NotificationsGroup.propTypes = {
title: PropTypes.string.isRequired,
subtitle: PropTypes.string.isRequired,
type: PropTypes.string.isRequired,
imgUrl: PropTypes.string.isRequired,
iconClasses: PropTypes.string.isRequired,
iconBackground: PropTypes.string.isRequired
title: string.isRequired,
subtitle: string.isRequired,
type: string.isRequired,
iconClasses: string,
iconBackground: string,
inAppNotification: bool,
emailNotification: bool,
reloadInfo: func.isRequired
};
NotificationsGroup.defaultProps = {
iconClasses: "",
iconBackground: "",
emailNotification: false,
inAppNotification: false
};
export default NotificationsGroup;

View file

@ -1,5 +1,10 @@
import React, { Component } from "react";
import PropTypes from "prop-types";
import { string, bool, func } from "prop-types";
import {
ButtonToolbar,
ToggleButtonGroup,
ToggleButton
} from "react-bootstrap";
import styled from "styled-components";
import { FormattedMessage } from "react-intl";
@ -27,66 +32,59 @@ const RightButton = styled.button`
class NotificationsSwitch extends Component {
constructor(props) {
super(props);
this.state = { status: this.props.status };
this.handleClick = this.handleClick.bind(this);
this.disabledButton = this.disabledButton.bind(this);
}
handleClick() {
handleClick(value) {
if (!this.props.isDisabled) {
this.props.toggleSwitch();
this.props.updateStatus(value);
}
}
render() {
let switchBtn;
if (this.props.isSwitchOn) {
switchBtn = (
<div className="btn-group">
<LeftButton
className="btn btn-default"
disabled={this.props.isDisabled}
onClick={this.handleClick}
>
<FormattedMessage id="settings_page.no" />
</LeftButton>
<RightButton
className="btn btn-primary"
disabled
onClick={this.handleClick}
>
<FormattedMessage id="settings_page.yes" />
</RightButton>
</div>
);
} else {
switchBtn = (
<div className="btn-group">
<LeftButton
className="btn btn-danger"
disabled
onClick={this.handleClick}
>
<FormattedMessage id="settings_page.no" />
</LeftButton>
<RightButton
className="btn btn-default"
disabled={this.props.isDisabled}
onClick={this.handleClick}
>
<FormattedMessage id="settings_page.yes" />
</RightButton>
</div>
disabledButton() {
if (this.props.isDisabled) {
return (
<ToggleButtonGroup
type="radio"
name={this.props.title}
defaultValue={this.state.status}
disabled
>
<ToggleButton disabled value={false}>
No
</ToggleButton>
<ToggleButton disabled value={true}>
Yes
</ToggleButton>
</ToggleButtonGroup>
);
}
return (
<ToggleButtonGroup
type="radio"
name={this.props.title}
onChange={this.handleClick}
defaultValue={this.state.status}
>
<ToggleButton value={false}>
No
</ToggleButton>
<ToggleButton value={true}>
Yes
</ToggleButton>
</ToggleButtonGroup>
);
}
render() {
return (
<Wrapper className="row">
<div className="col-sm-4 col-sm-offset-1">
<FormattedMessage id={this.props.title} />
</div>
<div className="col-sm-7">
{switchBtn}
<ButtonToolbar>{this.disabledButton()}</ButtonToolbar>
</div>
</Wrapper>
);
@ -94,10 +92,10 @@ class NotificationsSwitch extends Component {
}
NotificationsSwitch.propTypes = {
title: PropTypes.string.isRequired,
isSwitchOn: PropTypes.bool.isRequired,
isDisabled: PropTypes.bool.isRequired,
toggleSwitch: PropTypes.func.isRequired
title: string.isRequired,
status: bool.isRequired,
isDisabled: bool.isRequired,
updateStatus: func.isRequired
};
export default NotificationsSwitch;

View file

@ -1,158 +0,0 @@
import React, { Component } from "react";
import { connect } from "react-redux";
import { string, bool, func } from "prop-types";
import NotificationsSwitch from "./NotificationsSwitch";
import {
ASSIGNMENT_NOTIFICATION,
RECENT_NOTIFICATION,
SYSTEM_NOTIFICATION
} from "../../../../../config/constants/strings";
import {
changeAssignmentsNotification,
changeAssignmentsNotificationEmail,
changeRecentNotification,
changeRecentNotificationEmail,
changeSystemMessageNotificationEmail
} from "../../../../../components/actions/UsersActions";
class NotificationsSwitchGroup extends Component {
constructor(props) {
super(props);
this.state = {
isSwitchOn: false,
isEmailSwitchOn: false
};
this.toggleFirstSwitch = this.toggleFirstSwitch.bind(this);
this.toggleSecondSwitch = this.toggleSecondSwitch.bind(this);
this.isSwitchDisabled = this.isSwitchDisabled.bind(this);
}
componentWillMount() {
switch (this.props.type) {
case ASSIGNMENT_NOTIFICATION:
this.setState({
isSwitchOn: this.props.assignmentsNotification,
isEmailSwitchOn: this.props.assignmentsNotificationEmail,
sciNoteDispatch: state =>
this.props.changeAssignmentsNotification(state),
emailDispatch: state =>
this.props.changeAssignmentsNotificationEmail(state)
});
break;
case RECENT_NOTIFICATION:
this.setState({
isSwitchOn: this.props.recentNotification,
isEmailSwitchOn: this.props.recentNotificationEmail,
sciNoteDispatch: state => this.props.changeRecentNotification(state),
emailDispatch: state =>
this.props.changeRecentNotificationEmail(state)
});
break;
case SYSTEM_NOTIFICATION:
this.setState({
isSwitchOn: true,
isEmailSwitchOn: this.props.systemMessageNotificationEmail,
sciNoteDispatch: state => `${state}: Do Nothing`,
emailDispatch: state =>
this.props.changeSystemMessageNotificationEmail(state)
});
break;
default:
this.setState({
isSwitchOn: false,
isEmailSwitchOn: false
});
}
}
toggleFirstSwitch() {
if (this.state.isSwitchOn) {
this.setState({ isSwitchOn: false, isEmailSwitchOn: false });
this.state.sciNoteDispatch(false);
this.state.emailDispatch(false);
} else {
this.setState({ isSwitchOn: true });
this.state.sciNoteDispatch(true);
}
}
toggleSecondSwitch() {
if (this.state.isEmailSwitchOn) {
this.setState({ isEmailSwitchOn: false });
this.state.emailDispatch(false);
} else {
this.setState({ isEmailSwitchOn: true });
this.state.emailDispatch(true);
}
}
isSwitchDisabled() {
if (this.props.type === SYSTEM_NOTIFICATION) {
return true;
}
return false;
}
render() {
return (
<div>
<NotificationsSwitch
title="settings_page.show_in_scinote"
isSwitchOn={this.state.isSwitchOn}
toggleSwitch={this.toggleFirstSwitch}
isDisabled={this.isSwitchDisabled()}
/>
<NotificationsSwitch
title="settings_page.notify_me_via_email"
isSwitchOn={this.state.isEmailSwitchOn}
toggleSwitch={this.toggleSecondSwitch}
isDisabled={!this.state.isSwitchOn}
/>
</div>
);
}
}
// TODO get rid of unnecesary proptypes
NotificationsSwitchGroup.propTypes = {
type: string.isRequired,
assignmentsNotification: bool.isRequired,
assignmentsNotificationEmail: bool.isRequired,
recentNotification: bool.isRequired,
recentNotificationEmail: bool.isRequired,
systemMessageNotificationEmail: bool.isRequired,
changeAssignmentsNotification: func.isRequired,
changeAssignmentsNotificationEmail: func.isRequired,
changeRecentNotification: func.isRequired,
changeRecentNotificationEmail: func.isRequired,
changeSystemMessageNotificationEmail: func.isRequired
};
const mapStateToProps = state => state.current_user;
const mapDispatchToProps = dispatch => ({
changeAssignmentsNotification(status) {
dispatch(changeAssignmentsNotification(status));
},
changeAssignmentsNotificationEmail(status) {
dispatch(changeAssignmentsNotificationEmail(status));
},
changeRecentNotification(status) {
dispatch(changeRecentNotification(status));
},
changeRecentNotificationEmail(status) {
dispatch(changeRecentNotificationEmail(status));
},
changeSystemMessageNotificationEmail(status) {
dispatch(changeSystemMessageNotificationEmail(status));
}
});
export default connect(mapStateToProps, mapDispatchToProps)(
NotificationsSwitchGroup
);

View file

@ -1,7 +1,5 @@
import React, { Component } from "react";
import { FormattedMessage } from "react-intl";
import { Button } from "react-bootstrap";
import styled from "styled-components";
import { getUserPreferencesInfo } from "../../../../services/api/users_api";
import SettingsAccountWrapper from "../../components/SettingsAccountWrapper";
@ -16,15 +14,9 @@ import {
import {
MAIN_COLOR_BLUE,
ICON_GREEN_COLOR,
BORDER_LIGHT_COLOR
ICON_GREEN_COLOR
} from "../../../../config/constants/colors";
const TutorialWrapper = styled.div`
margin: 20px 0;
padding-bottom: 15px;
border-bottom: 1px solid ${BORDER_LIGHT_COLOR};
`
class SettingsPreferences extends Component {
constructor(props) {
super(props);
@ -38,7 +30,7 @@ class SettingsPreferences extends Component {
systemMessageEmailNofification: false
};
this.getPreferencesInfo = this.getPreferencesInfo.bind(this)
this.getPreferencesInfo = this.getPreferencesInfo.bind(this);
}
componentDidMount() {
@ -59,35 +51,39 @@ class SettingsPreferences extends Component {
value={this.state.timeZone}
loadPreferences={this.getPreferencesInfo}
/>
<TutorialWrapper>
<Button bsStyle="success">
<FormattedMessage id="settings_page.repeat_tutorial" />
</Button>
</TutorialWrapper>
<h3>Notifications</h3>
<h3>
<FormattedMessage id="settings_page.notifications" />
</h3>
<NotificationsGroup
type={ASSIGNMENT_NOTIFICATION}
title="settings_page.assignement"
subtitle="settings_page.assignement_msg"
imgUrl=""
iconClasses="fa fa-newspaper-o"
inAppNotification={this.state.assignmentsNotification}
emailNotification={
this.state.assignmentsEmailNotification
}
iconBackground={MAIN_COLOR_BLUE}
reloadInfo={this.getPreferencesInfo}
/>
<NotificationsGroup
type={RECENT_NOTIFICATION}
title="settings_page.recent_changes"
subtitle="settings_page.recent_changes_msg"
imgUrl={this.props.avatarPath}
iconClasses=""
iconBackground=""
inAppNotification={this.state.recentNotification}
emailNotification={this.state.recentEmailNotification}
reloadInfo={this.getPreferencesInfo}
/>
<NotificationsGroup
type={SYSTEM_NOTIFICATION}
title="settings_page.system_message"
subtitle="settings_page.system_message_msg"
imgUrl=""
inAppNotification={
this.state.systemMessageEmailNofification
}
iconClasses="glyphicon glyphicon-tower"
iconBackground={ICON_GREEN_COLOR}
reloadInfo={this.getPreferencesInfo}
/>
</div>
</SettingsAccountWrapper>

View file

@ -48,12 +48,8 @@ class User < ApplicationRecord
system_message_email: false
}
)
# json.assignmentsNotification notifications['assignments']
# json.assignmentsEmailNotification notifications['assignments_email']
# json.recentNotification notifications['recent']
# json.recentEmailNotification notifications['recent_email']
# json.systemMessageEmailNofification notifications['system_message_email']
# joson friendly attributes
# json friendly attributes
NOTIFICATIONS_TYPES = %w(assignmentsNotification assignmentsEmailNotification
recentNotification recentEmailNotification
systemMessageEmailNofification)
@ -67,6 +63,7 @@ class User < ApplicationRecord
# declare notifications setters
NOTIFICATIONS_TYPES.each do |name|
next if name == 'systemMessageEmailNofification'
define_method("#{name}=") do |value|
attr_name = name.slice!('Notification').underscore
self.notifications[attr_name.to_sym] = value

View file

@ -4685,8 +4685,8 @@ react-bootstrap-timezone-picker@^1.0.11:
prop-types "^15.5.10"
react-bootstrap@^0.31.1:
version "0.31.2"
resolved "https://registry.yarnpkg.com/react-bootstrap/-/react-bootstrap-0.31.2.tgz#f59184676ecedfc4c572d29ffdd6f9126ea8fe6a"
version "0.31.3"
resolved "https://registry.yarnpkg.com/react-bootstrap/-/react-bootstrap-0.31.3.tgz#db2b7d45b00b5dac1ab8b6de3dd97feb3091b849"
dependencies:
babel-runtime "^6.11.6"
classnames "^2.2.5"