Merge pull request #344 from chriswmartin/getting-started-badge-merge

merge tootsuite pr #6313 into glitch & move getting_started dispatch stuff to mapDispatchToProps
shrike
Gô Shoemake 2018-03-12 13:07:59 -07:00 committed by GitHub
commit 2395a4c313
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 57 additions and 17 deletions

View File

@ -9,6 +9,8 @@ import PropTypes from 'prop-types';
import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { me } from 'flavours/glitch/util/initial_state';
import { fetchFollowRequests } from 'flavours/glitch/actions/accounts';
import { List as ImmutableList } from 'immutable';
import { createSelector } from 'reselect';
import { fetchLists } from 'flavours/glitch/actions/lists';
@ -45,13 +47,31 @@ const makeMapStateToProps = () => {
lists: getOrderedLists(state),
myAccount: state.getIn(['accounts', me]),
columns: state.getIn(['settings', 'columns']),
unreadFollowRequests: state.getIn(['user_lists', 'follow_requests', 'items'], ImmutableList()).size,
unreadNotifications: state.getIn(['notifications', 'unread']),
});
return mapStateToProps;
};
const mapDispatchToProps = dispatch => ({
fetchFollowRequests: () => dispatch(fetchFollowRequests()),
fetchLists: () => dispatch(fetchLists()),
openSettings: () => dispatch(openModal('SETTINGS', {})),
});
const badgeDisplay = (number, limit) => {
if (number === 0) {
return undefined;
} else if (limit && number >= limit) {
return `${limit}+`;
} else {
return number;
}
};
@connect(makeMapStateToProps, mapDispatchToProps)
@injectIntl
@connect(makeMapStateToProps)
export default class GettingStarted extends ImmutablePureComponent {
static propTypes = {
@ -59,25 +79,28 @@ export default class GettingStarted extends ImmutablePureComponent {
myAccount: ImmutablePropTypes.map.isRequired,
columns: ImmutablePropTypes.list,
multiColumn: PropTypes.bool,
dispatch: PropTypes.func.isRequired,
fetchFollowRequests: PropTypes.func.isRequired,
unreadFollowRequests: PropTypes.number,
unreadNotifications: PropTypes.number,
lists: ImmutablePropTypes.list,
fetchLists: PropTypes.func.isRequired,
openSettings: PropTypes.func.isRequired,
};
openSettings = () => {
this.props.dispatch(openModal('SETTINGS', {}));
}
openOnboardingModal = (e) => {
e.preventDefault();
this.props.dispatch(openModal('ONBOARDING'));
}
componentWillMount () {
this.props.dispatch(fetchLists());
this.props.fetchLists();
}
componentDidMount () {
const { myAccount, fetchFollowRequests } = this.props;
if (myAccount.get('locked')) {
fetchFollowRequests();
}
}
render () {
const { intl, myAccount, columns, multiColumn, lists } = this.props;
const { intl, myAccount, columns, multiColumn, unreadFollowRequests, unreadNotifications, lists, openSettings } = this.props;
const navItems = [];
let listItems = [];
@ -88,7 +111,7 @@ export default class GettingStarted extends ImmutablePureComponent {
}
if (!columns.find(item => item.get('id') === 'NOTIFICATIONS')) {
navItems.push(<ColumnLink key='1' icon='bell' text={intl.formatMessage(messages.notifications)} to='/notifications' />);
navItems.push(<ColumnLink key='1' icon='bell' text={intl.formatMessage(messages.notifications)} badge={badgeDisplay(unreadNotifications)} to='/notifications' />);
}
if (!columns.find(item => item.get('id') === 'COMMUNITY')) {
@ -105,7 +128,7 @@ export default class GettingStarted extends ImmutablePureComponent {
}
if (myAccount.get('locked')) {
navItems.push(<ColumnLink key='5' icon='users' text={intl.formatMessage(messages.follow_requests)} to='/follow_requests' />);
navItems.push(<ColumnLink key='5' icon='users' text={intl.formatMessage(messages.follow_requests)} badge={badgeDisplay(unreadFollowRequests, 40)} to='/follow_requests' />);
}
navItems.push(<ColumnLink key='6' icon='ellipsis-h' text={intl.formatMessage(messages.misc)} to='/getting-started-misc' />);
@ -129,7 +152,7 @@ export default class GettingStarted extends ImmutablePureComponent {
{listItems}
<ColumnSubheading text={intl.formatMessage(messages.settings_subheading)} />
<ColumnLink icon='cog' text={intl.formatMessage(messages.preferences)} href='/settings/preferences' />
<ColumnLink icon='cogs' text={intl.formatMessage(messages.settings)} onClick={this.openSettings} />
<ColumnLink icon='cogs' text={intl.formatMessage(messages.settings)} onClick={openSettings} />
<ColumnLink icon='sign-out' text={intl.formatMessage(messages.sign_out)} href='/auth/sign_out' method='delete' />
</div>

View File

@ -2,12 +2,15 @@ import React from 'react';
import PropTypes from 'prop-types';
import { Link } from 'react-router-dom';
const ColumnLink = ({ icon, text, to, onClick, href, method }) => {
const ColumnLink = ({ icon, text, to, onClick, href, method, badge }) => {
const badgeElement = typeof badge !== 'undefined' ? <span className='column-link__badge'>{badge}</span> : null;
if (href) {
return (
<a href={href} className='column-link' data-method={method}>
<i className={`fa fa-fw fa-${icon} column-link__icon`} />
{text}
{badgeElement}
</a>
);
} else if (to) {
@ -15,6 +18,7 @@ const ColumnLink = ({ icon, text, to, onClick, href, method }) => {
<Link to={to} className='column-link'>
<i className={`fa fa-fw fa-${icon} column-link__icon`} />
{text}
{badgeElement}
</Link>
);
} else {
@ -22,6 +26,7 @@ const ColumnLink = ({ icon, text, to, onClick, href, method }) => {
<a onClick={onClick} className='column-link' role='button' tabIndex='0' data-method={method}>
<i className={`fa fa-fw fa-${icon} column-link__icon`} />
{text}
{badgeElement}
</a>
);
}
@ -34,6 +39,7 @@ ColumnLink.propTypes = {
onClick: PropTypes.func,
href: PropTypes.string,
method: PropTypes.string,
badge: PropTypes.node,
};
export default ColumnLink;

View File

@ -753,6 +753,17 @@
}
}
.column-link__badge {
display: inline-block;
border-radius: 4px;
font-size: 12px;
line-height: 19px;
font-weight: 500;
background: $ui-base-color;
padding: 4px 8px;
margin: -6px 10px;
}
.keyboard-shortcuts {
padding: 8px 0 0;
overflow: hidden;