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

merge tootsuite pr #6313 into glitch & move getting_started dispatch stuff to mapDispatchToProps
main
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 ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component'; import ImmutablePureComponent from 'react-immutable-pure-component';
import { me } from 'flavours/glitch/util/initial_state'; 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 { createSelector } from 'reselect';
import { fetchLists } from 'flavours/glitch/actions/lists'; import { fetchLists } from 'flavours/glitch/actions/lists';
@ -45,13 +47,31 @@ const makeMapStateToProps = () => {
lists: getOrderedLists(state), lists: getOrderedLists(state),
myAccount: state.getIn(['accounts', me]), myAccount: state.getIn(['accounts', me]),
columns: state.getIn(['settings', 'columns']), columns: state.getIn(['settings', 'columns']),
unreadFollowRequests: state.getIn(['user_lists', 'follow_requests', 'items'], ImmutableList()).size,
unreadNotifications: state.getIn(['notifications', 'unread']),
}); });
return mapStateToProps; 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 @injectIntl
@connect(makeMapStateToProps)
export default class GettingStarted extends ImmutablePureComponent { export default class GettingStarted extends ImmutablePureComponent {
static propTypes = { static propTypes = {
@ -59,25 +79,28 @@ export default class GettingStarted extends ImmutablePureComponent {
myAccount: ImmutablePropTypes.map.isRequired, myAccount: ImmutablePropTypes.map.isRequired,
columns: ImmutablePropTypes.list, columns: ImmutablePropTypes.list,
multiColumn: PropTypes.bool, multiColumn: PropTypes.bool,
dispatch: PropTypes.func.isRequired, fetchFollowRequests: PropTypes.func.isRequired,
unreadFollowRequests: PropTypes.number,
unreadNotifications: PropTypes.number,
lists: ImmutablePropTypes.list, 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 () { componentWillMount () {
this.props.dispatch(fetchLists()); this.props.fetchLists();
}
componentDidMount () {
const { myAccount, fetchFollowRequests } = this.props;
if (myAccount.get('locked')) {
fetchFollowRequests();
}
} }
render () { render () {
const { intl, myAccount, columns, multiColumn, lists } = this.props; const { intl, myAccount, columns, multiColumn, unreadFollowRequests, unreadNotifications, lists, openSettings } = this.props;
const navItems = []; const navItems = [];
let listItems = []; let listItems = [];
@ -88,7 +111,7 @@ export default class GettingStarted extends ImmutablePureComponent {
} }
if (!columns.find(item => item.get('id') === 'NOTIFICATIONS')) { 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')) { if (!columns.find(item => item.get('id') === 'COMMUNITY')) {
@ -105,7 +128,7 @@ export default class GettingStarted extends ImmutablePureComponent {
} }
if (myAccount.get('locked')) { 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' />); 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} {listItems}
<ColumnSubheading text={intl.formatMessage(messages.settings_subheading)} /> <ColumnSubheading text={intl.formatMessage(messages.settings_subheading)} />
<ColumnLink icon='cog' text={intl.formatMessage(messages.preferences)} href='/settings/preferences' /> <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' /> <ColumnLink icon='sign-out' text={intl.formatMessage(messages.sign_out)} href='/auth/sign_out' method='delete' />
</div> </div>

View File

@ -2,12 +2,15 @@ import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { Link } from 'react-router-dom'; 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) { if (href) {
return ( return (
<a href={href} className='column-link' data-method={method}> <a href={href} className='column-link' data-method={method}>
<i className={`fa fa-fw fa-${icon} column-link__icon`} /> <i className={`fa fa-fw fa-${icon} column-link__icon`} />
{text} {text}
{badgeElement}
</a> </a>
); );
} else if (to) { } else if (to) {
@ -15,6 +18,7 @@ const ColumnLink = ({ icon, text, to, onClick, href, method }) => {
<Link to={to} className='column-link'> <Link to={to} className='column-link'>
<i className={`fa fa-fw fa-${icon} column-link__icon`} /> <i className={`fa fa-fw fa-${icon} column-link__icon`} />
{text} {text}
{badgeElement}
</Link> </Link>
); );
} else { } 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}> <a onClick={onClick} className='column-link' role='button' tabIndex='0' data-method={method}>
<i className={`fa fa-fw fa-${icon} column-link__icon`} /> <i className={`fa fa-fw fa-${icon} column-link__icon`} />
{text} {text}
{badgeElement}
</a> </a>
); );
} }
@ -34,6 +39,7 @@ ColumnLink.propTypes = {
onClick: PropTypes.func, onClick: PropTypes.func,
href: PropTypes.string, href: PropTypes.string,
method: PropTypes.string, method: PropTypes.string,
badge: PropTypes.node,
}; };
export default ColumnLink; 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 { .keyboard-shortcuts {
padding: 8px 0 0; padding: 8px 0 0;
overflow: hidden; overflow: hidden;