Admin: display awaiting-approval counter in nav

This commit is contained in:
Alex Gleason 2020-12-29 19:48:39 -06:00
parent 19e1e15263
commit 03344756e5
No known key found for this signature in database
GPG key ID: 7211D1F99744FBB7
4 changed files with 60 additions and 4 deletions

View file

@ -0,0 +1,23 @@
import React from 'react';
import PropTypes from 'prop-types';
import Icon from 'soapbox/components/icon';
import { shortNumberFormat } from 'soapbox/utils/numbers';
const IconWithCounter = ({ icon, count, fixedWidth }) => {
return (
<div className='icon-with-counter'>
<Icon id={icon} fixedWidth={fixedWidth} />
{count > 0 && <i className='icon-with-counter__counter'>
{shortNumberFormat(count)}
</i>}
</div>
);
};
IconWithCounter.propTypes = {
icon: PropTypes.string.isRequired,
count: PropTypes.number.isRequired,
fixedWidth: PropTypes.bool,
};
export default IconWithCounter;

View file

@ -1,12 +1,16 @@
import React from 'react'; import React from 'react';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePropTypes from 'react-immutable-proptypes';
import Icon from 'soapbox/components/icon'; import Icon from 'soapbox/components/icon';
import IconWithCounter from 'soapbox/components/icon_with_counter';
import { NavLink } from 'react-router-dom'; import { NavLink } from 'react-router-dom';
import { FormattedMessage } from 'react-intl'; import { FormattedMessage } from 'react-intl';
const mapStateToProps = (state, props) => ({ const mapStateToProps = (state, props) => ({
instance: state.get('instance'), instance: state.get('instance'),
approvalCount: state.getIn(['admin', 'awaitingApproval']).count(),
reportsCount: state.getIn(['admin', 'open_report_count']),
}); });
export default @connect(mapStateToProps) export default @connect(mapStateToProps)
@ -14,10 +18,12 @@ class AdminNav extends React.PureComponent {
static propTypes = { static propTypes = {
instance: ImmutablePropTypes.map.isRequired, instance: ImmutablePropTypes.map.isRequired,
approvalCount: PropTypes.number,
reportsCount: PropTypes.number,
}; };
render() { render() {
const { instance } = this.props; const { instance, approvalCount, reportsCount } = this.props;
return ( return (
<> <>
@ -28,12 +34,12 @@ class AdminNav extends React.PureComponent {
<FormattedMessage id='admin_nav.dashboard' defaultMessage='Dashboard' /> <FormattedMessage id='admin_nav.dashboard' defaultMessage='Dashboard' />
</NavLink> </NavLink>
<a className='promo-panel-item' href='/pleroma/admin/#/reports/index' target='_blank'> <a className='promo-panel-item' href='/pleroma/admin/#/reports/index' target='_blank'>
<Icon id='gavel' className='promo-panel-item__icon' fixedWidth /> <IconWithCounter icon='gavel' count={reportsCount} fixedWidth />
<FormattedMessage id='admin_nav.reports' defaultMessage='Reports' /> <FormattedMessage id='admin_nav.reports' defaultMessage='Reports' />
</a> </a>
{instance.get('approval_required') && ( {instance.get('approval_required') && (
<NavLink className='promo-panel-item' to='/admin/approval'> <NavLink className='promo-panel-item' to='/admin/approval'>
<Icon id='user' className='promo-panel-item__icon' fixedWidth /> <IconWithCounter icon='user' count={approvalCount} fixedWidth />
<FormattedMessage id='admin_nav.awaiting_approval' defaultMessage='Awaiting Approval' /> <FormattedMessage id='admin_nav.awaiting_approval' defaultMessage='Awaiting Approval' />
</NavLink> </NavLink>
)} )}

View file

@ -28,7 +28,8 @@
} }
} }
&__icon { &__icon,
.icon-with-counter {
margin-right: 12px; margin-right: 12px;
} }
} }

View file

@ -699,3 +699,29 @@
text-align: center; text-align: center;
} }
} }
.icon-with-counter {
position: relative;
display: inline;
&__counter {
@include font-montserrat;
@include font-size(14);
@include line-height(14);
position: absolute;
box-sizing: border-box;
left: 8px;
top: -12px;
min-width: 16px;
height: 16px;
padding: 1px 3px 0;
border-radius: 8px;
text-align: center;
color: #fff;
background: var(--accent-color);
@media screen and (max-width: 895px) {
top: 0;
}
}
}