Skip to content
This repository has been archived by the owner on Mar 13, 2024. It is now read-only.

Commit

Permalink
Added Admin Badge to Profile Popover (#1487)
Browse files Browse the repository at this point in the history
Add Admin Badges to Profile Popover
  • Loading branch information
DSchalla committed Nov 23, 2018
1 parent b3edb1f commit 3fb08ea
Show file tree
Hide file tree
Showing 6 changed files with 217 additions and 57 deletions.
28 changes: 28 additions & 0 deletions actions/views/profile_popover.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.

import {getTeamMember} from 'mattermost-redux/actions/teams';
import {getChannelMember} from 'mattermost-redux/actions/channels';
import {getCurrentChannel} from 'mattermost-redux/selectors/entities/channels';
import {getCurrentTeamId} from 'mattermost-redux/selectors/entities/teams';

import {getSelectedPost} from 'selectors/rhs';

export function getMembershipForCurrentEntities(userId) {
return async (dispatch, getState) => {
const state = getState();
const currentTeamId = getCurrentTeamId(state);

const selectedPost = getSelectedPost(state);
const currentChannel = getCurrentChannel(state);

let channelId;
if (selectedPost.exists === false) {
channelId = currentChannel.id;
} else {
channelId = selectedPost.channel_id;
}

return Promise.all([dispatch(getTeamMember(currentTeamId, userId)), dispatch(getChannelMember(channelId, userId))]);
};
}
37 changes: 34 additions & 3 deletions components/profile_popover/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,49 @@ import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';

import {getCurrentUserId} from 'mattermost-redux/selectors/entities/users';
import {getCurrentTeam} from 'mattermost-redux/selectors/entities/teams';
import {getCurrentTeam, getTeamMember} from 'mattermost-redux/selectors/entities/teams';
import {getCurrentChannel, getChannelMembersInChannels} from 'mattermost-redux/selectors/entities/channels';

import {openDirectChannelToUserId} from 'actions/channel_actions.jsx';
import {getMembershipForCurrentEntities} from 'actions/views/profile_popover';
import {openModal} from 'actions/views/modals';
import {areTimezonesEnabledAndSupported} from 'selectors/general';
import {getSelectedPost, getRhsState} from 'selectors/rhs';

import ProfilePopover from './profile_popover.jsx';

function mapStateToProps(state) {
function mapStateToProps(state, ownProps) {
const team = getCurrentTeam(state);
const teamMember = getTeamMember(state, team.id, ownProps.user.id) || {};

let isTeamAdmin = false;
if (teamMember != null && teamMember.scheme_admin) {
isTeamAdmin = true;
}

const selectedPost = getSelectedPost(state);
const currentChannel = getCurrentChannel(state);

let channelId;
if (selectedPost.exists === false) {
channelId = currentChannel.id;
} else {
channelId = selectedPost.channel_id;
}

const channelMember = getChannelMembersInChannels(state)[channelId][ownProps.user.id] || {};

let isChannelAdmin = false;
if (getRhsState(state) !== 'search' && channelMember != null && channelMember.scheme_admin) {
isChannelAdmin = true;
}

return {
enableTimezone: areTimezonesEnabledAndSupported(state),
currentUserId: getCurrentUserId(state),
teamUrl: '/' + getCurrentTeam(state).name,
teamUrl: '/' + team.name,
isTeamAdmin,
isChannelAdmin,
};
}

Expand All @@ -26,6 +56,7 @@ function mapDispatchToProps(dispatch) {
actions: bindActionCreators({
openDirectChannelToUserId,
openModal,
getMembershipForCurrentEntities,
}, dispatch),
};
}
Expand Down
87 changes: 49 additions & 38 deletions components/profile_popover/profile_popover.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import Pluggable from 'plugins/pluggable';
* The profile popover, or hovercard, that appears with user information when clicking
* on the username or profile picture of a user.
*/
class ProfilePopover extends React.Component {
class ProfilePopover extends React.PureComponent {
static getComponentName() {
return 'ProfilePopover';
}
Expand Down Expand Up @@ -58,15 +58,36 @@ class ProfilePopover extends React.Component {
*/
hasMention: PropTypes.bool,

/**
* @internal
*/
currentUserId: PropTypes.string.isRequired,

/**
* @internal
*/
teamUrl: PropTypes.string.isRequired,

...Popover.propTypes,
/**
* @internal
*/
isTeamAdmin: PropTypes.bool.isRequired,

/**
* @internal
*/
isChannelAdmin: PropTypes.bool.isRequired,

/**
* @internal
*/
actions: PropTypes.shape({
getMembershipForCurrentEntities: PropTypes.func.isRequired,
openDirectChannelToUserId: PropTypes.func.isRequired,
openModal: PropTypes.func.isRequred,
openModal: PropTypes.func.isRequired,
}).isRequired,

...Popover.propTypes,
}

static defaultProps = {
Expand All @@ -84,41 +105,9 @@ class ProfilePopover extends React.Component {
loadingDMChannel: -1,
};
}
shouldComponentUpdate(nextProps) {
if (!Utils.areObjectsEqual(nextProps.user, this.props.user)) {
return true;
}

if (nextProps.src !== this.props.src) {
return true;
}

if (nextProps.status !== this.props.status) {
return true;
}

if (nextProps.isBusy !== this.props.isBusy) {
return true;
}

// React-Bootstrap Forwarded Props from OverlayTrigger to Popover
if (nextProps.arrowOffsetLeft !== this.props.arrowOffsetLeft) {
return true;
}

if (nextProps.arrowOffsetTop !== this.props.arrowOffsetTop) {
return true;
}

if (nextProps.positionLeft !== this.props.positionLeft) {
return true;
}

if (nextProps.positionTop !== this.props.positionTop) {
return true;
}

return false;
componentDidMount() {
this.props.actions.getMembershipForCurrentEntities(this.props.user.id);
}

handleShowDirectChannel(e) {
Expand Down Expand Up @@ -189,6 +178,8 @@ class ProfilePopover extends React.Component {
delete popoverProps.currentUserId;
delete popoverProps.teamUrl;
delete popoverProps.actions;
delete popoverProps.isTeamAdmin;
delete popoverProps.isChannelAdmin;

var dataContent = [];
dataContent.push(
Expand All @@ -203,6 +194,16 @@ class ProfilePopover extends React.Component {
);

const fullname = Utils.getFullName(this.props.user);

if (fullname || this.props.user.position) {
dataContent.push(
<hr
key='user-popover-hr'
className='divider divider--expanded'
/>
);
}

if (fullname) {
dataContent.push(
<OverlayTrigger
Expand Down Expand Up @@ -242,7 +243,7 @@ class ProfilePopover extends React.Component {
if (email) {
dataContent.push(
<hr
key='user-popover-hr'
key='user-popover-hr2'
className='divider divider--expanded'
/>
);
Expand Down Expand Up @@ -345,10 +346,20 @@ class ProfilePopover extends React.Component {
/>
);

let roleTitle;
if (Utils.isSystemAdmin(this.props.user.roles)) {
roleTitle = <span className='user-popover__role'>{Utils.localizeMessage('admin.permissions.roles.system_admin.name', 'System Admin')}</span>;
} else if (this.props.isTeamAdmin) {
roleTitle = <span className='user-popover__role'>{Utils.localizeMessage('admin.permissions.roles.team_admin.name', 'Team Admin')}</span>;
} else if (this.props.isChannelAdmin) {
roleTitle = <span className='user-popover__role'>{Utils.localizeMessage('admin.permissions.roles.channel_admin.name', 'Channel Admin')}</span>;
}

let title = `@${this.props.user.username}`;
if (this.props.hasMention) {
title = <a onClick={this.handleMentionKeyClick}>{title}</a>;
}
title = <span><span className='user-popover__username'>{title}</span> {roleTitle}</span>;

return (
<Popover
Expand Down
45 changes: 35 additions & 10 deletions plugins/pluggable/__snapshots__/pluggable.test.jsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -233,26 +233,31 @@ exports[`plugins/Pluggable should match snapshot with no overridden component 1`
theme={Object {}}
user={
Object {
"id": "someid",
"name": "name",
}
}
>
<ProfilePopover
actions={
Object {
"getMembershipForCurrentEntities": [Function],
"openDirectChannelToUserId": [Function],
"openModal": [Function],
}
}
currentUserId=""
currentUserId="someid"
enableTimezone={false}
hasMention={false}
isChannelAdmin={false}
isRHS={false}
isTeamAdmin={false}
src="src"
teamUrl="/somename"
theme={Object {}}
user={
Object {
"id": "someid",
"name": "name",
}
}
Expand All @@ -262,7 +267,16 @@ exports[`plugins/Pluggable should match snapshot with no overridden component 1`
id="user-profile-popover"
placement="right"
theme={Object {}}
title="@undefined"
title={
<span>
<span
className="user-popover__username"
>
@undefined
</span>
</span>
}
>
<div
className="popover right"
Expand All @@ -289,7 +303,14 @@ exports[`plugins/Pluggable should match snapshot with no overridden component 1`
<h3
className="popover-title"
>
@undefined
<span>
<span
className="user-popover__username"
>
@undefined
</span>
</span>
</h3>
<div
className="popover-content"
Expand All @@ -307,6 +328,7 @@ exports[`plugins/Pluggable should match snapshot with no overridden component 1`
pluggableName="PopoverUserAttributes"
user={
Object {
"id": "someid",
"name": "name",
}
}
Expand Down Expand Up @@ -346,6 +368,7 @@ exports[`plugins/Pluggable should match snapshot with no overridden component 1`
}
user={
Object {
"id": "someid",
"name": "name",
}
}
Expand All @@ -354,24 +377,23 @@ exports[`plugins/Pluggable should match snapshot with no overridden component 1`
<div
className="popover__row first"
data-toggle="tooltip"
key="user-popover-dm"
key="user-popover-settings"
>
<a
className="text-nowrap user-popover__email"
href="#"
onClick={[Function]}
>
<i
className="fa fa-paper-plane"
title="Send Message Icon"
className="fa fa-pencil-square-o"
title="Edit Icon"
/>
<FormattedMessage
defaultMessage="Send Message"
id="user_profile.send.dm"
defaultMessage="Edit Account Settings"
id="user_profile.account.editSettings"
values={Object {}}
>
<span>
Send Message
Edit Account Settings
</span>
</FormattedMessage>
</a>
Expand All @@ -381,6 +403,7 @@ exports[`plugins/Pluggable should match snapshot with no overridden component 1`
pluggableName="PopoverUserActions"
user={
Object {
"id": "someid",
"name": "name",
}
}
Expand Down Expand Up @@ -420,6 +443,7 @@ exports[`plugins/Pluggable should match snapshot with no overridden component 1`
}
user={
Object {
"id": "someid",
"name": "name",
}
}
Expand Down Expand Up @@ -473,6 +497,7 @@ exports[`plugins/Pluggable should match snapshot with overridden component 1`] =
}
user={
Object {
"id": "someid",
"name": "name",
}
}
Expand Down
Loading

0 comments on commit 3fb08ea

Please sign in to comment.