PLT-6905 - Updating channel header design (#6789)
* PLT-6905 - Updating channel header design * Updating border-radius * Updating radius for wide icons * Updating trigger for overlay * Updating UI for channel header * Updating channel header sizing * Updating channel header css * Updating sidebar css * Updating status icons * Adjusting border * Updating comment * Removing type from status icon * Fixing UI issues for the channel header/sidebar * make "Add a channel description" open the channel header modal * Updating status and opacity * Updating stauts icon positioning * Updating description and heading size * Updating UI changes * Updating UI changes * add a focused class to the parent div .search__form and then remove when hover away * Fix active state for pinned posts icon * Updating UI changes * Update channel header text
Этот коммит содержится в:
коммит произвёл
Joram Wilander
родитель
97cfe62309
Коммит
d64d1f4029
@@ -31,6 +31,7 @@ export default function TableChart(props) {
|
||||
<tr key={'table-entry-' + item.name}>
|
||||
<td>
|
||||
<OverlayTrigger
|
||||
trigger={['hover', 'focus']}
|
||||
delayShow={Constants.OVERLAY_TIME_DELAY}
|
||||
placement='top'
|
||||
overlay={tooltip}
|
||||
|
||||
@@ -180,6 +180,7 @@ export default class ChangeUrlModal extends React.Component {
|
||||
<div className='col-sm-10'>
|
||||
<div className={urlClass}>
|
||||
<OverlayTrigger
|
||||
trigger={['hover', 'focus']}
|
||||
delayShow={Constants.OVERLAY_TIME_DELAY}
|
||||
placement='top'
|
||||
overlay={urlTooltip}
|
||||
|
||||
@@ -64,6 +64,7 @@ export default class ChannelHeader extends React.Component {
|
||||
this.hideLeaveChannelModal = this.hideLeaveChannelModal.bind(this);
|
||||
|
||||
const state = this.getStateFromStores();
|
||||
state.showEditChannelHeaderModal = false;
|
||||
state.showEditChannelPurposeModal = false;
|
||||
state.showMembersModal = false;
|
||||
state.showRenameChannelModal = false;
|
||||
@@ -90,7 +91,8 @@ export default class ChannelHeader extends React.Component {
|
||||
enableFormatting: PreferenceStore.getBool(Preferences.CATEGORY_ADVANCED_SETTINGS, 'formatting', true),
|
||||
isBusy: WebrtcStore.isBusy(),
|
||||
isFavorite: channel && ChannelUtils.isFavoriteChannel(channel),
|
||||
showLeaveChannelModal: false
|
||||
showLeaveChannelModal: false,
|
||||
pinsOpen: SearchStore.getIsPinnedPosts()
|
||||
};
|
||||
}
|
||||
|
||||
@@ -281,7 +283,8 @@ export default class ChannelHeader extends React.Component {
|
||||
|
||||
render() {
|
||||
const flagIcon = Constants.FLAG_ICON_SVG;
|
||||
const pinIcon = Constants.PIN_ICON;
|
||||
const pinIcon = Constants.PIN_ICON_SVG;
|
||||
const mentionsIcon = Constants.MENTIONS_ICON_SVG;
|
||||
|
||||
if (!this.validState()) {
|
||||
// Use an empty div to make sure the header's height stays constant
|
||||
@@ -300,6 +303,15 @@ export default class ChannelHeader extends React.Component {
|
||||
</Tooltip>
|
||||
);
|
||||
|
||||
const pinnedPostTooltip = (
|
||||
<Tooltip id='pinnedPostTooltip'>
|
||||
<FormattedMessage
|
||||
id='channel_header.pinnedPosts'
|
||||
defaultMessage='Pinned Posts'
|
||||
/>
|
||||
</Tooltip>
|
||||
);
|
||||
|
||||
const flaggedTooltip = (
|
||||
<Tooltip
|
||||
id='flaggedTooltip'
|
||||
@@ -382,13 +394,14 @@ export default class ChannelHeader extends React.Component {
|
||||
);
|
||||
|
||||
webrtc = (
|
||||
<div className='webrtc__header'>
|
||||
<div className='webrtc__header channel-header__icon'>
|
||||
<a
|
||||
href='#'
|
||||
onClick={() => this.initWebrtc(otherUserId, !isOffline)}
|
||||
disabled={isOffline}
|
||||
>
|
||||
<OverlayTrigger
|
||||
trigger={['hover', 'focus']}
|
||||
delayShow={Constants.WEBRTC_TIME_DELAY}
|
||||
placement='bottom'
|
||||
overlay={webrtcTooltip}
|
||||
@@ -754,11 +767,62 @@ export default class ChannelHeader extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
let headerText;
|
||||
if (this.state.enableFormatting) {
|
||||
headerText = TextFormatting.formatText(channel.header, {singleline: true, mentionHighlight: false, siteURL: getSiteURL()});
|
||||
let headerTextContainer;
|
||||
if (channel.header) {
|
||||
let headerTextElement;
|
||||
if (this.state.enableFormatting) {
|
||||
headerTextElement = (
|
||||
<div
|
||||
onClick={Utils.handleFormattedTextClick}
|
||||
className='channel-header__description'
|
||||
dangerouslySetInnerHTML={{__html: TextFormatting.formatText(channel.header, {singleline: true, mentionHighlight: false, siteURL: getSiteURL()})}}
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
headerTextElement = (
|
||||
<div
|
||||
onClick={Utils.handleFormattedTextClick}
|
||||
className='channel-header__description'
|
||||
>
|
||||
{channel.header}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
headerTextContainer = (
|
||||
<OverlayTrigger
|
||||
trigger={'click'}
|
||||
placement='bottom'
|
||||
rootClose={true}
|
||||
overlay={popoverContent}
|
||||
ref='headerOverlay'
|
||||
>
|
||||
{headerTextElement}
|
||||
</OverlayTrigger>
|
||||
);
|
||||
} else {
|
||||
headerText = channel.header;
|
||||
headerTextContainer = (
|
||||
<a
|
||||
href='#'
|
||||
className='channel-header__description light'
|
||||
onClick={() => this.setState({showEditChannelHeaderModal: true})}
|
||||
>
|
||||
<FormattedMessage
|
||||
id='channel_header.addChannelHeader'
|
||||
defaultMessage='Add a channel description'
|
||||
/>
|
||||
</a>
|
||||
);
|
||||
}
|
||||
|
||||
let editHeaderModal;
|
||||
if (this.state.showEditChannelHeaderModal) {
|
||||
editHeaderModal = (
|
||||
<EditChannelHeaderModal
|
||||
onHide={() => this.setState({showEditChannelHeaderModal: false})}
|
||||
channel={channel}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
let toggleFavoriteTooltip;
|
||||
@@ -784,6 +848,7 @@ export default class ChannelHeader extends React.Component {
|
||||
|
||||
const toggleFavorite = (
|
||||
<OverlayTrigger
|
||||
trigger={['hover', 'focus']}
|
||||
delayShow={Constants.OVERLAY_TIME_DELAY}
|
||||
placement='bottom'
|
||||
overlay={toggleFavoriteTooltip}
|
||||
@@ -792,7 +857,7 @@ export default class ChannelHeader extends React.Component {
|
||||
id='toggleFavorite'
|
||||
href='#'
|
||||
onClick={this.toggleFavorite}
|
||||
className='channel-header__favorites'
|
||||
className={'channel-header__favorites ' + (this.state.isFavorite ? 'active' : 'inactive')}
|
||||
>
|
||||
<i className={'icon fa ' + (this.state.isFavorite ? 'fa-star' : 'fa-star-o')}/>
|
||||
</a>
|
||||
@@ -822,19 +887,23 @@ export default class ChannelHeader extends React.Component {
|
||||
|
||||
const leaveChannelModal = this.createLeaveChannelModal();
|
||||
|
||||
let pinnedIconClass = 'channel-header__icon';
|
||||
if (this.state.pinsOpen) {
|
||||
pinnedIconClass += ' active';
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
id='channel-header'
|
||||
className='channel-header'
|
||||
className='channel-header alt'
|
||||
>
|
||||
<table className='channel-header alt'>
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>
|
||||
<div className='channel-header__info'>
|
||||
{webrtc}
|
||||
{toggleFavorite}
|
||||
<div className='dropdown'>
|
||||
<div className='channel-header__title dropdown'>
|
||||
<a
|
||||
id='channelHeaderDropdown'
|
||||
href='#'
|
||||
@@ -844,7 +913,7 @@ export default class ChannelHeader extends React.Component {
|
||||
aria-expanded='true'
|
||||
>
|
||||
<strong className='heading'>{channelTitle} </strong>
|
||||
<span className='fa fa-chevron-down header-dropdown__icon'/>
|
||||
<span className='fa fa-angle-down header-dropdown__icon'/>
|
||||
</a>
|
||||
<ul
|
||||
className='dropdown-menu'
|
||||
@@ -854,35 +923,33 @@ export default class ChannelHeader extends React.Component {
|
||||
{dropdownContents}
|
||||
</ul>
|
||||
</div>
|
||||
<OverlayTrigger
|
||||
trigger={'click'}
|
||||
placement='bottom'
|
||||
rootClose={true}
|
||||
overlay={popoverContent}
|
||||
ref='headerOverlay'
|
||||
>
|
||||
<div
|
||||
onClick={Utils.handleFormattedTextClick}
|
||||
className='description'
|
||||
dangerouslySetInnerHTML={{__html: headerText}}
|
||||
/>
|
||||
</OverlayTrigger>
|
||||
{headerTextContainer}
|
||||
</div>
|
||||
</th>
|
||||
<th className='header-list__right'>
|
||||
<th>
|
||||
{webrtc}
|
||||
</th>
|
||||
<th>
|
||||
{popoverListMembers}
|
||||
<a
|
||||
href='#'
|
||||
type='button'
|
||||
id='pinnedPostsButton'
|
||||
className='pinned-posts-button'
|
||||
onClick={this.getPinnedPosts}
|
||||
</th>
|
||||
<th>
|
||||
<OverlayTrigger
|
||||
trigger={['hover', 'focus']}
|
||||
delayShow={Constants.OVERLAY_TIME_DELAY}
|
||||
placement='bottom'
|
||||
overlay={pinnedPostTooltip}
|
||||
>
|
||||
<span
|
||||
dangerouslySetInnerHTML={{__html: pinIcon}}
|
||||
aria-hidden='true'
|
||||
/>
|
||||
</a>
|
||||
<div
|
||||
className={pinnedIconClass}
|
||||
onClick={this.getPinnedPosts}
|
||||
>
|
||||
<span
|
||||
className='icon icon__pin'
|
||||
dangerouslySetInnerHTML={{__html: pinIcon}}
|
||||
aria-hidden='true'
|
||||
/>
|
||||
</div>
|
||||
</OverlayTrigger>
|
||||
</th>
|
||||
<th className='search-bar__container'>
|
||||
<NavbarSearchBox
|
||||
@@ -891,47 +958,44 @@ export default class ChannelHeader extends React.Component {
|
||||
/>
|
||||
</th>
|
||||
<th>
|
||||
<div className='dropdown channel-header__links search-btns'>
|
||||
<OverlayTrigger
|
||||
delayShow={Constants.OVERLAY_TIME_DELAY}
|
||||
placement='bottom'
|
||||
overlay={recentMentionsTooltip}
|
||||
>
|
||||
<a
|
||||
id='searchMentions'
|
||||
href='#'
|
||||
type='button'
|
||||
onClick={this.searchMentions}
|
||||
>
|
||||
{'@'}
|
||||
</a>
|
||||
</OverlayTrigger>
|
||||
</div>
|
||||
<OverlayTrigger
|
||||
trigger={['hover', 'focus']}
|
||||
delayShow={Constants.OVERLAY_TIME_DELAY}
|
||||
placement='bottom'
|
||||
overlay={recentMentionsTooltip}
|
||||
>
|
||||
<div className='channel-header__icon icon--hidden'>
|
||||
<span
|
||||
className='icon icon__mentions'
|
||||
dangerouslySetInnerHTML={{__html: mentionsIcon}}
|
||||
aria-hidden='true'
|
||||
/>
|
||||
</div>
|
||||
</OverlayTrigger>
|
||||
</th>
|
||||
<th>
|
||||
<div className='dropdown channel-header__links search-btns'>
|
||||
<OverlayTrigger
|
||||
delayShow={Constants.OVERLAY_TIME_DELAY}
|
||||
placement='bottom'
|
||||
overlay={flaggedTooltip}
|
||||
<OverlayTrigger
|
||||
trigger={['hover', 'focus']}
|
||||
delayShow={Constants.OVERLAY_TIME_DELAY}
|
||||
placement='bottom'
|
||||
overlay={flaggedTooltip}
|
||||
>
|
||||
<div
|
||||
className='channel-header__icon icon--hidden'
|
||||
onClick={this.getFlagged}
|
||||
|
||||
>
|
||||
<a
|
||||
id='flaggedPostsButton'
|
||||
href='#'
|
||||
type='button'
|
||||
onClick={this.getFlagged}
|
||||
>
|
||||
<span
|
||||
className='icon icon__flag'
|
||||
dangerouslySetInnerHTML={{__html: flagIcon}}
|
||||
/>
|
||||
</a>
|
||||
</OverlayTrigger>
|
||||
</div>
|
||||
<span
|
||||
className='icon icon__flag'
|
||||
dangerouslySetInnerHTML={{__html: flagIcon}}
|
||||
/>
|
||||
</div>
|
||||
</OverlayTrigger>
|
||||
</th>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
{editHeaderModal}
|
||||
{editPurposeModal}
|
||||
{channelMembersModal}
|
||||
{leaveChannelModal}
|
||||
|
||||
@@ -29,6 +29,8 @@ export default class ChannelInfoModal extends React.Component {
|
||||
render() {
|
||||
let channel = this.props.channel;
|
||||
let channelIcon;
|
||||
const globeIcon = Constants.GLOBE_ICON_SVG;
|
||||
const lockIcon = Constants.LOCK_ICON_SVG;
|
||||
|
||||
if (!channel) {
|
||||
const notFound = Utils.localizeMessage('channel_info.notFound', 'No Channel Found');
|
||||
@@ -43,9 +45,19 @@ export default class ChannelInfoModal extends React.Component {
|
||||
}
|
||||
|
||||
if (channel.type === 'O') {
|
||||
channelIcon = (<span className='fa fa-globe'/>);
|
||||
channelIcon = (
|
||||
<span
|
||||
className='icon icon__globe icon--body'
|
||||
dangerouslySetInnerHTML={{__html: globeIcon}}
|
||||
/>
|
||||
);
|
||||
} else if (channel.type === 'P') {
|
||||
channelIcon = (<span className='fa fa-lock'/>);
|
||||
channelIcon = (
|
||||
<span
|
||||
className='icon icon__globe icon--body'
|
||||
dangerouslySetInnerHTML={{__html: lockIcon}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
const channelURL = TeamStore.getCurrentTeamUrl() + '/channels/' + channel.name;
|
||||
|
||||
@@ -178,6 +178,7 @@ export default class TeamUrl extends React.Component {
|
||||
<div className='col-sm-11'>
|
||||
<div className='input-group input-group--limit'>
|
||||
<OverlayTrigger
|
||||
trigger={['hover', 'focus']}
|
||||
delayShow={Constants.OVERLAY_TIME_DELAY}
|
||||
placement='top'
|
||||
overlay={urlTooltip}
|
||||
|
||||
@@ -105,6 +105,7 @@ export default class FileAttachment extends React.Component {
|
||||
if (this.props.compactDisplay) {
|
||||
filenameOverlay = (
|
||||
<OverlayTrigger
|
||||
trigger={['hover', 'focus']}
|
||||
delayShow={1000}
|
||||
placement='top'
|
||||
overlay={<Tooltip id='file-name__tooltip'>{fileName}</Tooltip>}
|
||||
@@ -126,6 +127,7 @@ export default class FileAttachment extends React.Component {
|
||||
} else {
|
||||
filenameOverlay = (
|
||||
<OverlayTrigger
|
||||
trigger={['hover', 'focus']}
|
||||
delayShow={1000}
|
||||
placement='top'
|
||||
overlay={<Tooltip id='file-name__tooltip'>{Utils.localizeMessage('file_attachment.download', 'Download') + ' "' + fileName + '"'}</Tooltip>}
|
||||
|
||||
@@ -279,6 +279,7 @@ export default class Navbar extends React.Component {
|
||||
|
||||
createDropdown(channel, channelTitle, isSystemAdmin, isTeamAdmin, isChannelAdmin, isDirect, isGroup, popoverContent) {
|
||||
const isAdmin = isSystemAdmin || isTeamAdmin;
|
||||
const infoIcon = Constants.INFO_ICON_SVG;
|
||||
|
||||
if (channel) {
|
||||
let viewInfoOption;
|
||||
@@ -599,7 +600,13 @@ export default class Navbar extends React.Component {
|
||||
className='description'
|
||||
rootClose={true}
|
||||
>
|
||||
<div className='pull-right description info-popover'/>
|
||||
<div className='pull-right description navbar-right__icon info-popover'>
|
||||
<span
|
||||
className='icon icon__info'
|
||||
dangerouslySetInnerHTML={{__html: infoIcon}}
|
||||
aria-hidden='true'
|
||||
/>
|
||||
</div>
|
||||
</OverlayTrigger>
|
||||
<a
|
||||
href='#'
|
||||
@@ -652,6 +659,8 @@ export default class Navbar extends React.Component {
|
||||
|
||||
createCollapseButtons(currentId) {
|
||||
var buttons = [];
|
||||
const menuIcon = Constants.MENU_ICON_SVG;
|
||||
|
||||
if (currentId == null) {
|
||||
buttons.push(
|
||||
<button
|
||||
@@ -688,9 +697,11 @@ export default class Navbar extends React.Component {
|
||||
defaultMessage='Toggle sidebar'
|
||||
/>
|
||||
</span>
|
||||
<span className='icon-bar'/>
|
||||
<span className='icon-bar'/>
|
||||
<span className='icon-bar'/>
|
||||
<span
|
||||
className='icon icon__menu'
|
||||
dangerouslySetInnerHTML={{__html: menuIcon}}
|
||||
aria-hidden='true'
|
||||
/>
|
||||
<NotifyCounts/>
|
||||
</button>
|
||||
);
|
||||
@@ -699,7 +710,7 @@ export default class Navbar extends React.Component {
|
||||
<button
|
||||
key='navbar-toggle-menu'
|
||||
type='button'
|
||||
className='navbar-toggle menu-toggle pull-right'
|
||||
className='navbar-toggle navbar-right__icon menu-toggle pull-right'
|
||||
data-toggle='collapse'
|
||||
data-target='#sidebar-nav'
|
||||
onClick={this.toggleRightSidebar}
|
||||
@@ -917,13 +928,18 @@ export default class Navbar extends React.Component {
|
||||
|
||||
var collapseButtons = this.createCollapseButtons(currentId);
|
||||
|
||||
const searchIcon = Constants.SEARCH_ICON_SVG;
|
||||
const searchButton = (
|
||||
<button
|
||||
type='button'
|
||||
className='navbar-toggle navbar-search pull-right'
|
||||
className='navbar-toggle navbar-right__icon navbar-search pull-right'
|
||||
onClick={this.showSearch}
|
||||
>
|
||||
<span className='fa fa-search icon-search icon--white'/>
|
||||
<span
|
||||
className='icon icon__search'
|
||||
dangerouslySetInnerHTML={{__html: searchIcon}}
|
||||
aria-hidden='true'
|
||||
/>
|
||||
</button>
|
||||
);
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ import {canManageMembers} from 'utils/channel_utils.jsx';
|
||||
import $ from 'jquery';
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import {Popover, Overlay} from 'react-bootstrap';
|
||||
import {Tooltip, OverlayTrigger, Popover, Overlay} from 'react-bootstrap';
|
||||
import {FormattedMessage} from 'react-intl';
|
||||
import {browserHistory} from 'react-router/es6';
|
||||
|
||||
@@ -94,6 +94,7 @@ export default class PopoverListMembers extends React.Component {
|
||||
const isSystemAdmin = UserStore.isSystemAdminForCurrentUser();
|
||||
const isTeamAdmin = TeamStore.isTeamAdminForCurrentTeam();
|
||||
const isChannelAdmin = ChannelStore.isChannelAdminForCurrentChannel();
|
||||
const membersIcon = Constants.MEMBERS_ICON_SVG;
|
||||
|
||||
if (members && teamMembers) {
|
||||
members.sort((a, b) => {
|
||||
@@ -104,20 +105,9 @@ export default class PopoverListMembers extends React.Component {
|
||||
});
|
||||
|
||||
members.forEach((m, i) => {
|
||||
let button = '';
|
||||
let messageIcon = '';
|
||||
if (currentUserId !== m.id && this.props.channel.type !== Constants.DM_CHANNEl) {
|
||||
button = (
|
||||
<a
|
||||
href='#'
|
||||
className='btn-message'
|
||||
onClick={(e) => this.handleShowDirectChannel(m, e)}
|
||||
>
|
||||
<FormattedMessage
|
||||
id='members_popover.msg'
|
||||
defaultMessage='Message'
|
||||
/>
|
||||
</a>
|
||||
);
|
||||
messageIcon = Constants.MESSAGE_ICON_SVG;
|
||||
}
|
||||
|
||||
let name = '';
|
||||
@@ -129,12 +119,13 @@ export default class PopoverListMembers extends React.Component {
|
||||
popoverHtml.push(
|
||||
<div
|
||||
className='more-modal__row'
|
||||
onClick={(e) => this.handleShowDirectChannel(m, e)}
|
||||
key={'popover-member-' + i}
|
||||
>
|
||||
<ProfilePicture
|
||||
src={Client4.getProfilePictureUrl(m.id, m.last_picture_update)}
|
||||
width='26'
|
||||
height='26'
|
||||
width='32'
|
||||
height='32'
|
||||
/>
|
||||
<div className='more-modal__details'>
|
||||
<div
|
||||
@@ -146,7 +137,11 @@ export default class PopoverListMembers extends React.Component {
|
||||
<div
|
||||
className='more-modal__actions'
|
||||
>
|
||||
{button}
|
||||
<span
|
||||
className='icon icon__message'
|
||||
dangerouslySetInnerHTML={{__html: messageIcon}}
|
||||
aria-hidden='true'
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
@@ -175,21 +170,15 @@ export default class PopoverListMembers extends React.Component {
|
||||
|
||||
popoverHtml.push(
|
||||
<div
|
||||
className='more-modal__row'
|
||||
className='more-modal__row more-modal__row--button'
|
||||
key={'popover-member-more'}
|
||||
>
|
||||
<div className='more-modal__details text-center'>
|
||||
<div
|
||||
className='more-modal__name'
|
||||
>
|
||||
<a
|
||||
href='#'
|
||||
onClick={this.showMembersModal}
|
||||
>
|
||||
{membersName}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
className='btn btn-primary'
|
||||
onClick={this.showMembersModal}
|
||||
>
|
||||
{membersName}
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -239,23 +228,40 @@ export default class PopoverListMembers extends React.Component {
|
||||
);
|
||||
}
|
||||
|
||||
const channelMembersTooltip = (
|
||||
<Tooltip id='channelMembersTooltip'>
|
||||
<FormattedMessage
|
||||
id='channel_header.channelMembers'
|
||||
defaultMessage='Members'
|
||||
/>
|
||||
</Tooltip>
|
||||
);
|
||||
|
||||
return (
|
||||
<div className='member-popover__container'>
|
||||
<div
|
||||
id='member_popover'
|
||||
className='member-popover__trigger'
|
||||
ref='member_popover_target'
|
||||
onClick={(e) => {
|
||||
this.setState({popoverTarget: e.target, showPopover: !this.state.showPopover});
|
||||
this.props.actions.getProfilesInChannel(this.props.channel.id, 0);
|
||||
}}
|
||||
<div className='channel-header__icon wide'>
|
||||
<OverlayTrigger
|
||||
trigger={['hover', 'focus']}
|
||||
delayShow={Constants.OVERLAY_TIME_DELAY}
|
||||
placement='bottom'
|
||||
overlay={channelMembersTooltip}
|
||||
>
|
||||
{countText}
|
||||
<span
|
||||
className='fa fa-user'
|
||||
aria-hidden='true'
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
id='member_popover'
|
||||
className='member-popover__trigger'
|
||||
ref='member_popover_target'
|
||||
onClick={(e) => {
|
||||
this.setState({popoverTarget: e.target, showPopover: !this.state.showPopover});
|
||||
this.props.actions.getProfilesInChannel(this.props.channel.id, 0);
|
||||
}}
|
||||
>
|
||||
<span className='icon__text'>{countText}</span>
|
||||
<span
|
||||
className='icon icon__members'
|
||||
dangerouslySetInnerHTML={{__html: membersIcon}}
|
||||
aria-hidden='true'
|
||||
/>
|
||||
</div>
|
||||
</OverlayTrigger>
|
||||
<Overlay
|
||||
rootClose={true}
|
||||
onHide={this.closePopover}
|
||||
@@ -265,10 +271,17 @@ export default class PopoverListMembers extends React.Component {
|
||||
>
|
||||
<Popover
|
||||
ref='memebersPopover'
|
||||
title={title}
|
||||
className='member-list__popover'
|
||||
id='member-list-popover'
|
||||
>
|
||||
<div className='more-modal__header'>
|
||||
<span
|
||||
className='icon icon__members'
|
||||
dangerouslySetInnerHTML={{__html: membersIcon}}
|
||||
aria-hidden='true'
|
||||
/>
|
||||
{title}
|
||||
</div>
|
||||
<div className='more-modal__list'>{popoverHtml}</div>
|
||||
</Popover>
|
||||
</Overlay>
|
||||
|
||||
@@ -21,11 +21,17 @@ function flagToolTip(isFlagged) {
|
||||
);
|
||||
}
|
||||
|
||||
function flagIcon() {
|
||||
function flagIcon(isFlagged) {
|
||||
let flagIconSvg = Constants.FLAG_ICON_SVG;
|
||||
|
||||
if (isFlagged) {
|
||||
flagIconSvg = Constants.FLAG_FILLED_ICON_SVG;
|
||||
}
|
||||
|
||||
return (
|
||||
<span
|
||||
className='icon'
|
||||
dangerouslySetInnerHTML={{__html: Constants.FLAG_ICON_SVG}}
|
||||
dangerouslySetInnerHTML={{__html: flagIconSvg}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -52,6 +58,7 @@ export default function PostFlagIcon(props) {
|
||||
if (!props.isEphemeral) {
|
||||
return (
|
||||
<OverlayTrigger
|
||||
trigger={['hover', 'focus']}
|
||||
key={'flagtooltipkey' + flagVisible}
|
||||
delayShow={Constants.OVERLAY_TIME_DELAY}
|
||||
placement='top'
|
||||
@@ -63,7 +70,7 @@ export default function PostFlagIcon(props) {
|
||||
className={'flag-icon__container ' + flagVisible}
|
||||
onClick={flagFunc}
|
||||
>
|
||||
{flagIcon()}
|
||||
{flagIcon(props.isFlagged)}
|
||||
</a>
|
||||
</OverlayTrigger>
|
||||
);
|
||||
|
||||
@@ -219,6 +219,7 @@ export default class Reaction extends React.PureComponent {
|
||||
|
||||
return (
|
||||
<OverlayTrigger
|
||||
trigger={['hover', 'focus']}
|
||||
delayShow={1000}
|
||||
placement='top'
|
||||
shouldUpdatePosition={true}
|
||||
|
||||
@@ -273,6 +273,7 @@ export class RenameChannelModal extends React.Component {
|
||||
|
||||
<div className='input-group input-group--limit'>
|
||||
<OverlayTrigger
|
||||
trigger={['hover', 'focus']}
|
||||
delayShow={Constants.OVERLAY_TIME_DELAY}
|
||||
placement='top'
|
||||
overlay={urlTooltip}
|
||||
|
||||
@@ -136,6 +136,7 @@ export default class RhsHeaderPost extends React.Component {
|
||||
className='sidebar--right__back'
|
||||
>
|
||||
<OverlayTrigger
|
||||
trigger={['hover', 'focus']}
|
||||
delayShow={Constants.OVERLAY_TIME_DELAY}
|
||||
placement='top'
|
||||
overlay={backToResultsTooltip}
|
||||
@@ -163,6 +164,7 @@ export default class RhsHeaderPost extends React.Component {
|
||||
onClick={this.toggleSize}
|
||||
>
|
||||
<OverlayTrigger
|
||||
trigger={['hover', 'focus']}
|
||||
delayShow={Constants.OVERLAY_TIME_DELAY}
|
||||
placement='top'
|
||||
overlay={expandSidebarTooltip}
|
||||
@@ -170,6 +172,7 @@ export default class RhsHeaderPost extends React.Component {
|
||||
<i className='fa fa-expand'/>
|
||||
</OverlayTrigger>
|
||||
<OverlayTrigger
|
||||
trigger={['hover', 'focus']}
|
||||
delayShow={Constants.OVERLAY_TIME_DELAY}
|
||||
placement='top'
|
||||
overlay={shrinkSidebarTooltip}
|
||||
@@ -185,6 +188,7 @@ export default class RhsHeaderPost extends React.Component {
|
||||
>
|
||||
|
||||
<OverlayTrigger
|
||||
trigger={['hover', 'focus']}
|
||||
delayShow={Constants.OVERLAY_TIME_DELAY}
|
||||
placement='top'
|
||||
overlay={closeSidebarTooltip}
|
||||
|
||||
@@ -216,6 +216,9 @@ export default class SearchBar extends React.Component {
|
||||
|
||||
render() {
|
||||
const flagIcon = Constants.FLAG_ICON_SVG;
|
||||
const searchIcon = Constants.SEARCH_ICON_SVG;
|
||||
const mentionsIcon = Constants.MENTIONS_ICON_SVG;
|
||||
|
||||
var isSearching = null;
|
||||
if (this.state.isSearching) {
|
||||
isSearching = <span className={'fa fa-refresh fa-refresh-animate icon--refresh icon--rotate'}/>;
|
||||
@@ -253,50 +256,49 @@ export default class SearchBar extends React.Component {
|
||||
var mentionBtnClass = SearchStore.isMentionSearch ? 'active' : '';
|
||||
|
||||
mentionBtn = (
|
||||
<div
|
||||
className='dropdown channel-header__links'
|
||||
<OverlayTrigger
|
||||
trigger={['hover', 'focus']}
|
||||
delayShow={Constants.OVERLAY_TIME_DELAY}
|
||||
placement='bottom'
|
||||
overlay={recentMentionsTooltip}
|
||||
>
|
||||
<OverlayTrigger
|
||||
delayShow={Constants.OVERLAY_TIME_DELAY}
|
||||
placement='bottom'
|
||||
overlay={recentMentionsTooltip}
|
||||
<div
|
||||
className={'channel-header__icon ' + mentionBtnClass}
|
||||
onClick={this.searchMentions}
|
||||
>
|
||||
<a
|
||||
href='#'
|
||||
type='button'
|
||||
onClick={this.searchMentions}
|
||||
className={mentionBtnClass}
|
||||
>
|
||||
{'@'}
|
||||
</a>
|
||||
</OverlayTrigger>
|
||||
</div>
|
||||
<span
|
||||
className='icon icon__mentions'
|
||||
dangerouslySetInnerHTML={{__html: mentionsIcon}}
|
||||
aria-hidden='true'
|
||||
/>
|
||||
</div>
|
||||
</OverlayTrigger>
|
||||
);
|
||||
|
||||
var flagBtnClass = SearchStore.isFlaggedPosts ? 'active' : '';
|
||||
|
||||
flagBtn = (
|
||||
<div
|
||||
className='dropdown channel-header__links'
|
||||
<OverlayTrigger
|
||||
trigger={['hover', 'focus']}
|
||||
delayShow={Constants.OVERLAY_TIME_DELAY}
|
||||
placement='bottom'
|
||||
overlay={flaggedTooltip}
|
||||
>
|
||||
<OverlayTrigger
|
||||
delayShow={Constants.OVERLAY_TIME_DELAY}
|
||||
placement='bottom'
|
||||
overlay={flaggedTooltip}
|
||||
<div
|
||||
className={'channel-header__icon ' + flagBtnClass}
|
||||
>
|
||||
<a
|
||||
href='#'
|
||||
type='button'
|
||||
onClick={this.getFlagged}
|
||||
className={flagBtnClass}
|
||||
>
|
||||
<span
|
||||
className='icon icon__flag'
|
||||
dangerouslySetInnerHTML={{__html: flagIcon}}
|
||||
/>
|
||||
</a>
|
||||
</OverlayTrigger>
|
||||
</div>
|
||||
</div>
|
||||
</OverlayTrigger>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -305,55 +307,71 @@ export default class SearchBar extends React.Component {
|
||||
clearClass += ' visible';
|
||||
}
|
||||
|
||||
let searchFormClass = 'search__form';
|
||||
if (this.state.focused) {
|
||||
searchFormClass += ' focused';
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div
|
||||
className='sidebar__collapse'
|
||||
onClick={this.handleClose}
|
||||
>
|
||||
<span className='fa fa-angle-left'/>
|
||||
</div>
|
||||
<form
|
||||
role='form'
|
||||
className='search__form'
|
||||
onSubmit={this.handleSubmit}
|
||||
style={{overflow: 'visible'}}
|
||||
autoComplete='off'
|
||||
>
|
||||
<span className='fa fa-search sidebar__search-icon'/>
|
||||
<SuggestionBox
|
||||
ref={(search) => {
|
||||
this.search = search;
|
||||
}}
|
||||
className='form-control search-bar'
|
||||
placeholder={Utils.localizeMessage('search_bar.search', 'Search')}
|
||||
value={this.state.searchTerm}
|
||||
onFocus={this.handleUserFocus}
|
||||
onBlur={this.handleUserBlur}
|
||||
onChange={this.handleChange}
|
||||
onKeyDown={this.handleKeyDown}
|
||||
listComponent={SearchSuggestionList}
|
||||
providers={this.suggestionProviders}
|
||||
type='search'
|
||||
autoFocus={this.props.isFocus && this.state.searchTerm === ''}
|
||||
/>
|
||||
<div className='sidebar-right__table'>
|
||||
<div className='sidebar-collapse__container'>
|
||||
<div
|
||||
className={clearClass}
|
||||
onClick={this.handleClear}
|
||||
className='sidebar-collapse'
|
||||
onClick={this.handleClose}
|
||||
>
|
||||
<span className='fa fa-chevron-left'/>
|
||||
</div>
|
||||
</div>
|
||||
<div className='search-form__container'>
|
||||
<form
|
||||
role='form'
|
||||
className={searchFormClass}
|
||||
onSubmit={this.handleSubmit}
|
||||
style={{overflow: 'visible'}}
|
||||
autoComplete='off'
|
||||
>
|
||||
<span
|
||||
className='sidebar__search-clear-x'
|
||||
className='search__icon'
|
||||
dangerouslySetInnerHTML={{__html: searchIcon}}
|
||||
aria-hidden='true'
|
||||
/>
|
||||
<SuggestionBox
|
||||
ref={(search) => {
|
||||
this.search = search;
|
||||
}}
|
||||
className='search-bar'
|
||||
placeholder={Utils.localizeMessage('search_bar.search', 'Search')}
|
||||
value={this.state.searchTerm}
|
||||
onFocus={this.handleUserFocus}
|
||||
onBlur={this.handleUserBlur}
|
||||
onChange={this.handleChange}
|
||||
onKeyDown={this.handleKeyDown}
|
||||
listComponent={SearchSuggestionList}
|
||||
providers={this.suggestionProviders}
|
||||
type='search'
|
||||
autoFocus={this.props.isFocus && this.state.searchTerm === ''}
|
||||
/>
|
||||
<div
|
||||
className={clearClass}
|
||||
onClick={this.handleClear}
|
||||
>
|
||||
{'×'}
|
||||
</span>
|
||||
</div>
|
||||
{isSearching}
|
||||
{this.renderHintPopover(helpClass)}
|
||||
</form>
|
||||
|
||||
{mentionBtn}
|
||||
{flagBtn}
|
||||
<span
|
||||
className='sidebar__search-clear-x'
|
||||
aria-hidden='true'
|
||||
>
|
||||
{'×'}
|
||||
</span>
|
||||
</div>
|
||||
{isSearching}
|
||||
{this.renderHintPopover(helpClass)}
|
||||
</form>
|
||||
</div>
|
||||
<div>
|
||||
{mentionBtn}
|
||||
</div>
|
||||
<div>
|
||||
{flagBtn}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -104,6 +104,7 @@ export default class SearchResultsHeader extends React.Component {
|
||||
onClick={this.toggleSize}
|
||||
>
|
||||
<OverlayTrigger
|
||||
trigger={['hover', 'focus']}
|
||||
delayShow={Constants.OVERLAY_TIME_DELAY}
|
||||
placement='top'
|
||||
overlay={expandSidebarTooltip}
|
||||
@@ -111,6 +112,7 @@ export default class SearchResultsHeader extends React.Component {
|
||||
<i className='fa fa-expand'/>
|
||||
</OverlayTrigger>
|
||||
<OverlayTrigger
|
||||
trigger={['hover', 'focus']}
|
||||
delayShow={Constants.OVERLAY_TIME_DELAY}
|
||||
placement='top'
|
||||
overlay={shrinkSidebarTooltip}
|
||||
@@ -126,6 +128,7 @@ export default class SearchResultsHeader extends React.Component {
|
||||
onClick={this.handleClose}
|
||||
>
|
||||
<OverlayTrigger
|
||||
trigger={['hover', 'focus']}
|
||||
delayShow={Constants.OVERLAY_TIME_DELAY}
|
||||
placement='top'
|
||||
overlay={closeSidebarTooltip}
|
||||
|
||||
@@ -520,7 +520,7 @@ export default class Sidebar extends React.Component {
|
||||
linkClass = 'active';
|
||||
}
|
||||
|
||||
let rowClass = 'sidebar-channel';
|
||||
let rowClass = 'sidebar-item';
|
||||
|
||||
var unread = false;
|
||||
if (channelMember) {
|
||||
@@ -542,7 +542,7 @@ export default class Sidebar extends React.Component {
|
||||
var badge = null;
|
||||
if (channelMember) {
|
||||
if (unreadCount.mentions) {
|
||||
badge = <span className='badge pull-right small'>{unreadCount.mentions}</span>;
|
||||
badge = <span className='badge'>{unreadCount.mentions}</span>;
|
||||
this.badgesActive = true;
|
||||
}
|
||||
} else if (this.state.loadingDMChannel === index && channel.type === Constants.DM_CHANNEL) {
|
||||
@@ -554,17 +554,29 @@ export default class Sidebar extends React.Component {
|
||||
);
|
||||
}
|
||||
|
||||
if (msgCount > 0) {
|
||||
if (unreadCount.mentions > 0) {
|
||||
rowClass += ' has-badge';
|
||||
}
|
||||
|
||||
let displayName = channel.display_name;
|
||||
|
||||
var icon = null;
|
||||
const globeIcon = Constants.GLOBE_ICON_SVG;
|
||||
const lockIcon = Constants.LOCK_ICON_SVG;
|
||||
if (channel.type === Constants.OPEN_CHANNEL) {
|
||||
icon = <div className='status'><i className='fa fa-globe'/></div>;
|
||||
icon = (
|
||||
<span
|
||||
className='icon icon__globe'
|
||||
dangerouslySetInnerHTML={{__html: globeIcon}}
|
||||
/>
|
||||
);
|
||||
} else if (channel.type === Constants.PRIVATE_CHANNEL) {
|
||||
icon = <div className='status'><i className='fa fa-lock'/></div>;
|
||||
icon = (
|
||||
<span
|
||||
className='icon icon__lock'
|
||||
dangerouslySetInnerHTML={{__html: lockIcon}}
|
||||
/>
|
||||
);
|
||||
} else if (channel.type === Constants.GM_CHANNEL) {
|
||||
displayName = ChannelUtils.buildGroupChannelName(channel.id);
|
||||
icon = <div className='status status--group'>{UserStore.getProfileListInChannel(channel.id, true).length}</div>;
|
||||
@@ -589,6 +601,7 @@ export default class Sidebar extends React.Component {
|
||||
if (handleClose && !badge) {
|
||||
closeButton = (
|
||||
<OverlayTrigger
|
||||
trigger={['hover', 'focus']}
|
||||
delayShow={1000}
|
||||
placement='top'
|
||||
overlay={removeTooltip}
|
||||
@@ -630,7 +643,7 @@ export default class Sidebar extends React.Component {
|
||||
onClick={this.trackChannelSelectedEvent}
|
||||
>
|
||||
{icon}
|
||||
{displayName}
|
||||
<span className='sidebar-item__name'>{displayName}</span>
|
||||
{badge}
|
||||
{closeButton}
|
||||
</Link>
|
||||
@@ -644,6 +657,8 @@ export default class Sidebar extends React.Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const switchChannelIcon = Constants.SWITCH_CHANNEL_ICON_SVG;
|
||||
|
||||
// Check if we have all info needed to render
|
||||
if (this.state.currentTeam == null || this.state.currentUser == null) {
|
||||
return (<div/>);
|
||||
@@ -749,8 +764,8 @@ export default class Sidebar extends React.Component {
|
||||
|
||||
let createPublicChannelIcon = (
|
||||
<OverlayTrigger
|
||||
trigger={['hover', 'focus']}
|
||||
delayShow={500}
|
||||
trigger='hover'
|
||||
placement='top'
|
||||
overlay={createChannelTootlip}
|
||||
>
|
||||
@@ -767,9 +782,9 @@ export default class Sidebar extends React.Component {
|
||||
|
||||
let createPrivateChannelIcon = (
|
||||
<OverlayTrigger
|
||||
trigger={['hover', 'focus']}
|
||||
delayShow={500}
|
||||
placement='top'
|
||||
trigger='hover'
|
||||
overlay={createGroupTootlip}
|
||||
>
|
||||
<a
|
||||
@@ -866,7 +881,7 @@ export default class Sidebar extends React.Component {
|
||||
<h4>
|
||||
<FormattedMessage
|
||||
id='sidebar.favorite'
|
||||
defaultMessage='Favorites'
|
||||
defaultMessage='FAVORITE CHANNELS'
|
||||
/>
|
||||
</h4>
|
||||
</li>
|
||||
@@ -877,7 +892,7 @@ export default class Sidebar extends React.Component {
|
||||
<h4>
|
||||
<FormattedMessage
|
||||
id='sidebar.channels'
|
||||
defaultMessage='Channels'
|
||||
defaultMessage='PUBLIC CHANNELS'
|
||||
/>
|
||||
{createPublicChannelIcon}
|
||||
</h4>
|
||||
@@ -903,7 +918,7 @@ export default class Sidebar extends React.Component {
|
||||
<h4>
|
||||
<FormattedMessage
|
||||
id='sidebar.pg'
|
||||
defaultMessage='Private Channels'
|
||||
defaultMessage='PRIVATE CHANNELS'
|
||||
/>
|
||||
{createPrivateChannelIcon}
|
||||
</h4>
|
||||
@@ -915,7 +930,7 @@ export default class Sidebar extends React.Component {
|
||||
<h4>
|
||||
<FormattedMessage
|
||||
id='sidebar.direct'
|
||||
defaultMessage='Direct Messages'
|
||||
defaultMessage='DIRECT MESSAGES'
|
||||
/>
|
||||
</h4>
|
||||
</li>
|
||||
@@ -928,6 +943,10 @@ export default class Sidebar extends React.Component {
|
||||
className='btn btn-link'
|
||||
onClick={this.openQuickSwitcher}
|
||||
>
|
||||
<span
|
||||
className='icon icon__switch'
|
||||
dangerouslySetInnerHTML={{__html: switchChannelIcon}}
|
||||
/>
|
||||
<FormattedMessage
|
||||
id={quickSwitchText}
|
||||
defaultMessage='Switch Channels'
|
||||
|
||||
@@ -102,8 +102,8 @@ export default class SidebarHeader extends React.Component {
|
||||
<div className='team__header theme'>
|
||||
{tutorialTip}
|
||||
<div className='header__info'>
|
||||
<div className='user__name'>{'@' + this.props.currentUser.username}</div>
|
||||
{teamNameWithToolTip}
|
||||
<div className='user__name'>{'@' + this.props.currentUser.username}</div>
|
||||
</div>
|
||||
<SidebarHeaderDropdown
|
||||
ref='dropdown'
|
||||
|
||||
@@ -129,7 +129,7 @@ export default class SidebarRight extends React.Component {
|
||||
const wasOpen = prevState.searchVisible || prevProps.postRightVisible;
|
||||
|
||||
if (isOpen && !wasOpen) {
|
||||
postListScrollChange();
|
||||
setTimeout(() => postListScrollChange(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -210,7 +210,7 @@ export default class SidebarRight extends React.Component {
|
||||
if (this.state.searchVisible) {
|
||||
content = (
|
||||
<div className='sidebar--right__content'>
|
||||
<div className='search-bar__container sidebar--right__search-header'>{searchForm}</div>
|
||||
<div className='search-bar__container channel-header alt'>{searchForm}</div>
|
||||
<SearchResults
|
||||
isMentionSearch={this.state.isMentionSearch}
|
||||
isFlaggedPosts={this.state.isFlaggedPosts}
|
||||
@@ -226,7 +226,7 @@ export default class SidebarRight extends React.Component {
|
||||
content = (
|
||||
<div className='post-right__container'>
|
||||
<FileUploadOverlay overlayType='right'/>
|
||||
<div className='search-bar__container sidebar--right__search-header'>{searchForm}</div>
|
||||
<div className='search-bar__container channel-header alt'>{searchForm}</div>
|
||||
<RhsThread
|
||||
fromFlaggedPosts={this.props.fromFlaggedPosts}
|
||||
fromSearch={this.props.fromSearch}
|
||||
|
||||
@@ -26,6 +26,8 @@ class SwitchChannelSuggestion extends Suggestion {
|
||||
render() {
|
||||
const {item, isSelection} = this.props;
|
||||
const channel = item.channel;
|
||||
const globeIcon = Constants.GLOBE_ICON_SVG;
|
||||
const lockIcon = Constants.LOCK_ICON_SVG;
|
||||
|
||||
let className = 'mentions__name';
|
||||
if (isSelection) {
|
||||
@@ -35,9 +37,19 @@ class SwitchChannelSuggestion extends Suggestion {
|
||||
let displayName = channel.display_name;
|
||||
let icon = null;
|
||||
if (channel.type === Constants.OPEN_CHANNEL) {
|
||||
icon = <div className='status'><i className='fa fa-globe'/></div>;
|
||||
icon = (
|
||||
<span
|
||||
className='icon icon__globe icon--body'
|
||||
dangerouslySetInnerHTML={{__html: globeIcon}}
|
||||
/>
|
||||
);
|
||||
} else if (channel.type === Constants.PRIVATE_CHANNEL) {
|
||||
icon = <div className='status'><i className='fa fa-lock'/></div>;
|
||||
icon = (
|
||||
<span
|
||||
className='icon icon__lock icon--body'
|
||||
dangerouslySetInnerHTML={{__html: lockIcon}}
|
||||
/>
|
||||
);
|
||||
} else if (channel.type === Constants.GM_CHANNEL) {
|
||||
displayName = getChannelDisplayName(channel);
|
||||
icon = <div className='status status--group'>{'G'}</div>;
|
||||
|
||||
@@ -69,6 +69,7 @@ export default class TeamButton extends React.Component {
|
||||
} else {
|
||||
btn = (
|
||||
<OverlayTrigger
|
||||
trigger={['hover', 'focus']}
|
||||
delayShow={Constants.OVERLAY_TIME_DELAY}
|
||||
placement={this.props.placement}
|
||||
overlay={
|
||||
|
||||
@@ -295,6 +295,7 @@ class CustomThemeChooser extends React.Component {
|
||||
{codeThemeOptions}
|
||||
</select>
|
||||
<OverlayTrigger
|
||||
trigger={['hover', 'focus']}
|
||||
placement='top'
|
||||
overlay={popoverContent}
|
||||
ref='headerOverlay'
|
||||
|
||||
@@ -59,6 +59,7 @@ export default function WebrtcHeader(props) {
|
||||
onClick={props.toggleSize}
|
||||
>
|
||||
<OverlayTrigger
|
||||
trigger={['hover', 'focus']}
|
||||
delayShow={Constants.OVERLAY_TIME_DELAY}
|
||||
placement='top'
|
||||
overlay={expandSidebarTooltip}
|
||||
@@ -66,6 +67,7 @@ export default function WebrtcHeader(props) {
|
||||
<i className='fa fa-expand'/>
|
||||
</OverlayTrigger>
|
||||
<OverlayTrigger
|
||||
trigger={['hover', 'focus']}
|
||||
delayShow={Constants.OVERLAY_TIME_DELAY}
|
||||
placement='top'
|
||||
overlay={shrinkSidebarTooltip}
|
||||
|
||||
Ссылка в новой задаче
Block a user