PLT-3132 Add a direct message link to the contact pop-over (#4853)
* added DM button to the user picture and name popover * removed isRequired from status and busy properties from profile_popover.jsx
Этот коммит содержится в:
@@ -7,6 +7,11 @@ import React from 'react';
|
|||||||
import {OverlayTrigger} from 'react-bootstrap';
|
import {OverlayTrigger} from 'react-bootstrap';
|
||||||
|
|
||||||
export default class ProfilePicture extends React.Component {
|
export default class ProfilePicture extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.hideProfilePopover = this.hideProfilePopover.bind(this);
|
||||||
|
}
|
||||||
shouldComponentUpdate(nextProps) {
|
shouldComponentUpdate(nextProps) {
|
||||||
if (!Utils.areObjectsEqual(nextProps.user, this.props.user)) {
|
if (!Utils.areObjectsEqual(nextProps.user, this.props.user)) {
|
||||||
return true;
|
return true;
|
||||||
@@ -35,6 +40,10 @@ export default class ProfilePicture extends React.Component {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hideProfilePopover() {
|
||||||
|
this.refs.overlay.hide();
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let statusClass = '';
|
let statusClass = '';
|
||||||
if (this.props.status) {
|
if (this.props.status) {
|
||||||
@@ -43,6 +52,7 @@ export default class ProfilePicture extends React.Component {
|
|||||||
if (this.props.user) {
|
if (this.props.user) {
|
||||||
return (
|
return (
|
||||||
<OverlayTrigger
|
<OverlayTrigger
|
||||||
|
ref='overlay'
|
||||||
trigger='click'
|
trigger='click'
|
||||||
placement='right'
|
placement='right'
|
||||||
rootClose={true}
|
rootClose={true}
|
||||||
@@ -52,6 +62,7 @@ export default class ProfilePicture extends React.Component {
|
|||||||
src={this.props.src}
|
src={this.props.src}
|
||||||
status={this.props.status}
|
status={this.props.status}
|
||||||
isBusy={this.props.isBusy}
|
isBusy={this.props.isBusy}
|
||||||
|
hide={this.hideProfilePopover}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -4,14 +4,17 @@
|
|||||||
import * as Utils from 'utils/utils.jsx';
|
import * as Utils from 'utils/utils.jsx';
|
||||||
import UserStore from 'stores/user_store.jsx';
|
import UserStore from 'stores/user_store.jsx';
|
||||||
import WebrtcStore from 'stores/webrtc_store.jsx';
|
import WebrtcStore from 'stores/webrtc_store.jsx';
|
||||||
|
import TeamStore from 'stores/team_store.jsx';
|
||||||
import * as GlobalActions from 'actions/global_actions.jsx';
|
import * as GlobalActions from 'actions/global_actions.jsx';
|
||||||
import * as WebrtcActions from 'actions/webrtc_actions.jsx';
|
import * as WebrtcActions from 'actions/webrtc_actions.jsx';
|
||||||
|
import {openDirectChannelToUser} from 'actions/channel_actions.jsx';
|
||||||
import Constants from 'utils/constants.jsx';
|
import Constants from 'utils/constants.jsx';
|
||||||
const UserStatuses = Constants.UserStatuses;
|
const UserStatuses = Constants.UserStatuses;
|
||||||
const PreReleaseFeatures = Constants.PRE_RELEASE_FEATURES;
|
const PreReleaseFeatures = Constants.PRE_RELEASE_FEATURES;
|
||||||
|
|
||||||
import {Popover, OverlayTrigger, Tooltip} from 'react-bootstrap';
|
import {Popover, OverlayTrigger, Tooltip} from 'react-bootstrap';
|
||||||
import {FormattedMessage} from 'react-intl';
|
import {FormattedMessage} from 'react-intl';
|
||||||
|
import {browserHistory} from 'react-router/es6';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
export default class ProfilePopover extends React.Component {
|
export default class ProfilePopover extends React.Component {
|
||||||
@@ -19,8 +22,10 @@ export default class ProfilePopover extends React.Component {
|
|||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
this.initWebrtc = this.initWebrtc.bind(this);
|
this.initWebrtc = this.initWebrtc.bind(this);
|
||||||
|
this.handleShowDirectChannel = this.handleShowDirectChannel.bind(this);
|
||||||
this.state = {
|
this.state = {
|
||||||
currentUserId: UserStore.getCurrentId()
|
currentUserId: UserStore.getCurrentId(),
|
||||||
|
loadingDMChannel: -1
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
shouldComponentUpdate(nextProps) {
|
shouldComponentUpdate(nextProps) {
|
||||||
@@ -60,6 +65,33 @@ export default class ProfilePopover extends React.Component {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleShowDirectChannel(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
if (!this.props.user) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const user = this.props.user;
|
||||||
|
|
||||||
|
if (this.state.loadingDMChannel !== -1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setState({loadingDMChannel: user.id});
|
||||||
|
|
||||||
|
openDirectChannelToUser(
|
||||||
|
user,
|
||||||
|
(channel) => {
|
||||||
|
this.setState({loadingDMChannel: -1});
|
||||||
|
if (this.props.hide) {
|
||||||
|
this.props.hide();
|
||||||
|
}
|
||||||
|
browserHistory.push(TeamStore.getCurrentTeamRelativeUrl() + '/channels/' + channel.name);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
initWebrtc() {
|
initWebrtc() {
|
||||||
if (this.props.status !== UserStatuses.OFFLINE && !WebrtcStore.isBusy()) {
|
if (this.props.status !== UserStatuses.OFFLINE && !WebrtcStore.isBusy()) {
|
||||||
GlobalActions.emitCloseRightHandSide();
|
GlobalActions.emitCloseRightHandSide();
|
||||||
@@ -73,6 +105,7 @@ export default class ProfilePopover extends React.Component {
|
|||||||
delete popoverProps.src;
|
delete popoverProps.src;
|
||||||
delete popoverProps.status;
|
delete popoverProps.status;
|
||||||
delete popoverProps.isBusy;
|
delete popoverProps.isBusy;
|
||||||
|
delete popoverProps.hide;
|
||||||
|
|
||||||
let webrtc;
|
let webrtc;
|
||||||
const userMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
|
const userMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
|
||||||
@@ -203,6 +236,28 @@ export default class ProfilePopover extends React.Component {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.props.user.id !== UserStore.getCurrentId()) {
|
||||||
|
dataContent.push(
|
||||||
|
<div
|
||||||
|
data-toggle='tooltip'
|
||||||
|
key='user-popover-dm'
|
||||||
|
className='popover-dm__content'
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
href='#'
|
||||||
|
className='text-nowrap text-lowercase user-popover__email'
|
||||||
|
onClick={this.handleShowDirectChannel}
|
||||||
|
>
|
||||||
|
<i className='fa fa-paper-plane'/>
|
||||||
|
<FormattedMessage
|
||||||
|
id='user_profile.send.dm'
|
||||||
|
defaultMessage='Send Message'
|
||||||
|
/>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Popover
|
<Popover
|
||||||
{...popoverProps}
|
{...popoverProps}
|
||||||
@@ -218,7 +273,8 @@ export default class ProfilePopover extends React.Component {
|
|||||||
ProfilePopover.propTypes = Object.assign({
|
ProfilePopover.propTypes = Object.assign({
|
||||||
src: React.PropTypes.string.isRequired,
|
src: React.PropTypes.string.isRequired,
|
||||||
user: React.PropTypes.object.isRequired,
|
user: React.PropTypes.object.isRequired,
|
||||||
status: React.PropTypes.string.isRequired,
|
status: React.PropTypes.string,
|
||||||
isBusy: React.PropTypes.bool.isRequired
|
isBusy: React.PropTypes.bool,
|
||||||
|
hide: React.PropTypes.func
|
||||||
}, Popover.propTypes);
|
}, Popover.propTypes);
|
||||||
delete ProfilePopover.propTypes.id;
|
delete ProfilePopover.propTypes.id;
|
||||||
|
|||||||
@@ -10,6 +10,11 @@ import {OverlayTrigger} from 'react-bootstrap';
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
export default class UserProfile extends React.Component {
|
export default class UserProfile extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.hideProfilePopover = this.hideProfilePopover.bind(this);
|
||||||
|
}
|
||||||
shouldComponentUpdate(nextProps) {
|
shouldComponentUpdate(nextProps) {
|
||||||
if (!Utils.areObjectsEqual(nextProps.user, this.props.user)) {
|
if (!Utils.areObjectsEqual(nextProps.user, this.props.user)) {
|
||||||
return true;
|
return true;
|
||||||
@@ -42,6 +47,10 @@ export default class UserProfile extends React.Component {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hideProfilePopover() {
|
||||||
|
this.refs.overlay.hide();
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let name = '...';
|
let name = '...';
|
||||||
let profileImg = '';
|
let profileImg = '';
|
||||||
@@ -60,6 +69,7 @@ export default class UserProfile extends React.Component {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<OverlayTrigger
|
<OverlayTrigger
|
||||||
|
ref='overlay'
|
||||||
trigger='click'
|
trigger='click'
|
||||||
placement='right'
|
placement='right'
|
||||||
rootClose={true}
|
rootClose={true}
|
||||||
@@ -69,6 +79,7 @@ export default class UserProfile extends React.Component {
|
|||||||
src={profileImg}
|
src={profileImg}
|
||||||
status={this.props.status}
|
status={this.props.status}
|
||||||
isBusy={this.props.isBusy}
|
isBusy={this.props.isBusy}
|
||||||
|
hide={this.hideProfilePopover}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -2162,6 +2162,7 @@
|
|||||||
"user.settings.security.title": "Security Settings",
|
"user.settings.security.title": "Security Settings",
|
||||||
"user.settings.security.viewHistory": "View Access History",
|
"user.settings.security.viewHistory": "View Access History",
|
||||||
"user_list.notFound": "No users found",
|
"user_list.notFound": "No users found",
|
||||||
|
"user_profile.send.dm": "Send Message",
|
||||||
"user_profile.webrtc.call": "Start Video Call",
|
"user_profile.webrtc.call": "Start Video Call",
|
||||||
"user_profile.webrtc.offline": "The user is offline",
|
"user_profile.webrtc.offline": "The user is offline",
|
||||||
"user_profile.webrtc.unavailable": "New call unavailable until your existing call ends",
|
"user_profile.webrtc.unavailable": "New call unavailable until your existing call ends",
|
||||||
|
|||||||
@@ -34,6 +34,32 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.popover-dm__content {
|
||||||
|
-webkit-border-radius: 0;
|
||||||
|
-moz-border-radius: 0;
|
||||||
|
-ms-border-radius: 0;
|
||||||
|
-o-border-radius: 0;
|
||||||
|
border-radius: 0;
|
||||||
|
max-width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
padding: 5px 5px 5px 0px;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
margin: 0;
|
||||||
|
font-size: 14px;
|
||||||
|
border-top: 1px solid #ebebeb;
|
||||||
|
border-color: rgba(221, 221, 221, 0.2);
|
||||||
|
margin-top: 5px;
|
||||||
|
margin-bottom: -5px;
|
||||||
|
> a {
|
||||||
|
> i {
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
> span {
|
||||||
|
text-transform: capitalize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.channel-header__info {
|
.channel-header__info {
|
||||||
|
|||||||
@@ -595,6 +595,7 @@ export function applyTheme(theme) {
|
|||||||
changeCss('.app__body .popover.left>.arrow', 'border-left-color:' + changeOpacity(theme.centerChannelColor, 0.25));
|
changeCss('.app__body .popover.left>.arrow', 'border-left-color:' + changeOpacity(theme.centerChannelColor, 0.25));
|
||||||
changeCss('.app__body .popover.top>.arrow', 'border-top-color:' + changeOpacity(theme.centerChannelColor, 0.25));
|
changeCss('.app__body .popover.top>.arrow', 'border-top-color:' + changeOpacity(theme.centerChannelColor, 0.25));
|
||||||
changeCss('.app__body .suggestion-list__content .command, .app__body .popover .popover-title', 'border-color:' + changeOpacity(theme.centerChannelColor, 0.2));
|
changeCss('.app__body .suggestion-list__content .command, .app__body .popover .popover-title', 'border-color:' + changeOpacity(theme.centerChannelColor, 0.2));
|
||||||
|
changeCss('.app__body .suggestion-list__content .command, .app__body .popover .popover-dm__content', 'border-color:' + changeOpacity(theme.centerChannelColor, 0.2));
|
||||||
changeCss('.app__body .suggestion-list__divider:before, .app__body .dropdown-menu .divider, .app__body .search-help-popover .search-autocomplete__divider:before', 'background:' + theme.centerChannelColor);
|
changeCss('.app__body .suggestion-list__divider:before, .app__body .dropdown-menu .divider, .app__body .search-help-popover .search-autocomplete__divider:before', 'background:' + theme.centerChannelColor);
|
||||||
changeCss('.app__body .custom-textarea', 'color:' + theme.centerChannelColor);
|
changeCss('.app__body .custom-textarea', 'color:' + theme.centerChannelColor);
|
||||||
changeCss('.app__body .post-image__column', 'border-color:' + changeOpacity(theme.centerChannelColor, 0.2));
|
changeCss('.app__body .post-image__column', 'border-color:' + changeOpacity(theme.centerChannelColor, 0.2));
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user