summaryrefslogtreecommitdiffstats
path: root/webapp
diff options
context:
space:
mode:
authorHarrison Healey <harrisonmhealey@gmail.com>2016-09-29 10:58:30 -0400
committerGitHub <noreply@github.com>2016-09-29 10:58:30 -0400
commit53ba8ec9c2bbaee510c2b1c9b5b59f9fdf44f365 (patch)
treead171bacc5ad7c8c9629ccb512d6787a8e79f5ec /webapp
parentac6ae23c8e72b0b79998c32b0e91873ed2bb0e59 (diff)
downloadchat-53ba8ec9c2bbaee510c2b1c9b5b59f9fdf44f365.tar.gz
chat-53ba8ec9c2bbaee510c2b1c9b5b59f9fdf44f365.tar.bz2
chat-53ba8ec9c2bbaee510c2b1c9b5b59f9fdf44f365.zip
Renamed NavbarDropdown to SidebarHeaderDropdown and switched it to react-bootstrap (#4109)
Diffstat (limited to 'webapp')
-rw-r--r--webapp/components/admin_console/admin_navbar_dropdown.jsx6
-rw-r--r--webapp/components/sidebar_header.jsx34
-rw-r--r--webapp/components/sidebar_header_dropdown.jsx (renamed from webapp/components/navbar_dropdown.jsx)246
-rw-r--r--webapp/sass/layout/_headers.scss49
-rw-r--r--webapp/sass/responsive/_mobile.scss2
-rw-r--r--webapp/utils/constants.jsx14
-rw-r--r--webapp/utils/utils.jsx2
7 files changed, 193 insertions, 160 deletions
diff --git a/webapp/components/admin_console/admin_navbar_dropdown.jsx b/webapp/components/admin_console/admin_navbar_dropdown.jsx
index f57635a11..7b958cbb0 100644
--- a/webapp/components/admin_console/admin_navbar_dropdown.jsx
+++ b/webapp/components/admin_console/admin_navbar_dropdown.jsx
@@ -82,20 +82,20 @@ export default class AdminNavbarDropdown extends React.Component {
}
return (
- <ul className='nav navbar-nav navbar-right'>
+ <ul className='nav navbar-nav navbar-right admin-navbar-dropdown'>
<li
ref='dropdown'
className='dropdown'
>
<a
href='#'
- className='dropdown-toggle'
+ className='dropdown-toggle admin-navbar-dropdown__toggle'
data-toggle='dropdown'
role='button'
aria-expanded='false'
>
<span
- className='dropdown__icon'
+ className='dropdown__icon admin-navbar-dropdown__icon'
dangerouslySetInnerHTML={{__html: Constants.MENU_ICON}}
/>
</a>
diff --git a/webapp/components/sidebar_header.jsx b/webapp/components/sidebar_header.jsx
index a57a809be..cd41cfb84 100644
--- a/webapp/components/sidebar_header.jsx
+++ b/webapp/components/sidebar_header.jsx
@@ -1,24 +1,18 @@
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
-import NavbarDropdown from './navbar_dropdown.jsx';
-import 'bootstrap';
+import React from 'react';
+import Client from 'client/web_client.jsx';
import PreferenceStore from 'stores/preference_store.jsx';
-
import * as Utils from 'utils/utils.jsx';
-import Client from 'client/web_client.jsx';
-import Constants from 'utils/constants.jsx';
-
-const Preferences = Constants.Preferences;
-const TutorialSteps = Constants.TutorialSteps;
+import SidebarHeaderDropdown from './sidebar_header_dropdown.jsx';
import {Tooltip, OverlayTrigger} from 'react-bootstrap';
+import {Preferences, TutorialSteps} from 'utils/constants.jsx';
import {createMenuTip} from 'components/tutorial/tutorial_tip.jsx';
-import React from 'react';
-
export default class SidebarHeader extends React.Component {
constructor(props) {
super(props);
@@ -28,34 +22,31 @@ export default class SidebarHeader extends React.Component {
this.state = this.getStateFromStores();
}
+
componentDidMount() {
PreferenceStore.addChangeListener(this.onPreferenceChange);
}
+
componentWillUnmount() {
PreferenceStore.removeChangeListener(this.onPreferenceChange);
}
+
getStateFromStores() {
const tutorialStep = PreferenceStore.getInt(Preferences.TUTORIAL_STEP, this.props.currentUser.id, 999);
return {showTutorialTip: tutorialStep === TutorialSteps.MENU_POPOVER && !Utils.isMobile()};
}
+
onPreferenceChange() {
this.setState(this.getStateFromStores());
}
+
toggleDropdown(e) {
e.preventDefault();
- if (this.refs.dropdown.blockToggle) {
- this.refs.dropdown.blockToggle = false;
- return;
- }
- const menu = document.querySelector('.team__header .dropdown-toggle');
- const isOpen = menu.parentElement.classList.toggle('open');
- menu.setAttribute('aria-expanded', isOpen);
- if (!isOpen) {
- document.querySelector('.sidebar--left .dropdown-menu').scrollTop = 0;
- }
+ this.refs.dropdown.toggleDropdown();
}
+
render() {
var me = this.props.currentUser;
var profilePicture = null;
@@ -99,13 +90,12 @@ export default class SidebarHeader extends React.Component {
</OverlayTrigger>
</div>
</a>
- <NavbarDropdown
+ <SidebarHeaderDropdown
ref='dropdown'
teamType={this.props.teamType}
teamDisplayName={this.props.teamDisplayName}
teamName={this.props.teamName}
currentUser={this.props.currentUser}
- toggleDropdown={this.toggleDropdown}
/>
</div>
);
diff --git a/webapp/components/navbar_dropdown.jsx b/webapp/components/sidebar_header_dropdown.jsx
index 60be47767..e33d6d5ec 100644
--- a/webapp/components/navbar_dropdown.jsx
+++ b/webapp/components/sidebar_header_dropdown.jsx
@@ -1,6 +1,8 @@
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
+import $ from 'jquery';
+import ReactDOM from 'react-dom';
import * as Utils from 'utils/utils.jsx';
import * as GlobalActions from 'actions/global_actions.jsx';
@@ -14,18 +16,35 @@ import UserSettingsModal from './user_settings/user_settings_modal.jsx';
import {Constants, WebrtcActionTypes} from 'utils/constants.jsx';
+import {Dropdown} from 'react-bootstrap';
import {FormattedMessage} from 'react-intl';
import {Link} from 'react-router/es6';
import React from 'react';
-export default class NavbarDropdown extends React.Component {
+export default class SidebarHeaderDropdown extends React.Component {
+ static propTypes = {
+ teamType: React.PropTypes.string,
+ teamDisplayName: React.PropTypes.string,
+ teamName: React.PropTypes.string,
+ currentUser: React.PropTypes.object
+ };
+
+ static defaultProps = {
+ teamType: ''
+ };
+
constructor(props) {
super(props);
- this.blockToggle = false;
+
+ this.toggleDropdown = this.toggleDropdown.bind(this);
this.handleAboutModal = this.handleAboutModal.bind(this);
this.aboutModalDismissed = this.aboutModalDismissed.bind(this);
+ this.toggleAccountSettingsModal = this.toggleAccountSettingsModal.bind(this);
+ this.showInviteMemberModal = this.showInviteMemberModal.bind(this);
+ this.showGetTeamInviteLinkModal = this.showGetTeamInviteLinkModal.bind(this);
+
this.onTeamChange = this.onTeamChange.bind(this);
this.openAccountSettings = this.openAccountSettings.bind(this);
@@ -34,10 +53,9 @@ export default class NavbarDropdown extends React.Component {
this.handleClick = this.handleClick.bind(this);
this.state = {
- showUserSettingsModal: false,
- showAboutModal: false,
teams: TeamStore.getAll(),
- teamMembers: TeamStore.getTeamMembers()
+ teamMembers: TeamStore.getTeamMembers(),
+ showDropdown: false
};
}
@@ -48,14 +66,50 @@ export default class NavbarDropdown extends React.Component {
}
}
+ toggleDropdown(e) {
+ if (e) {
+ e.preventDefault();
+ }
+
+ this.setState({showDropdown: !this.state.showDropdown});
+ }
+
handleAboutModal() {
- this.setState({showAboutModal: true});
+ this.setState({
+ showAboutModal: true,
+ showDropdown: false
+ });
}
aboutModalDismissed() {
this.setState({showAboutModal: false});
}
+ toggleAccountSettingsModal(e) {
+ e.preventDefault();
+
+ this.setState({
+ showUserSettingsModal: !this.state.showUserSettingsModal,
+ showDropdown: false
+ });
+ }
+
+ showInviteMemberModal(e) {
+ e.preventDefault();
+
+ this.setState({showDropdown: false});
+
+ GlobalActions.showInviteMemberModal();
+ }
+
+ showGetTeamInviteLinkModal(e) {
+ e.preventDefault();
+
+ this.setState({showDropdown: false});
+
+ GlobalActions.showGetTeamInviteLinkModal();
+ }
+
componentDidMount() {
TeamStore.addChangeListener(this.onTeamChange);
document.addEventListener('keydown', this.openAccountSettings);
@@ -69,14 +123,14 @@ export default class NavbarDropdown extends React.Component {
}
componentWillUnmount() {
+ $(ReactDOM.findDOMNode(this.refs.dropdown)).off('hide.bs.dropdown');
TeamStore.removeChangeListener(this.onTeamChange);
document.removeEventListener('keydown', this.openAccountSettings);
}
openAccountSettings(e) {
if (Utils.cmdOrCtrlPressed(e) && e.shiftKey && e.keyCode === Constants.KeyCodes.A) {
- e.preventDefault();
- this.setState({showUserSettingsModal: !this.state.showUserSettingsModal});
+ this.toggleAccountSettingsModal(e);
}
}
@@ -101,7 +155,7 @@ export default class NavbarDropdown extends React.Component {
}
render() {
- const config = global.window.mm_config;
+ const config = global.mm_config;
var teamLink = '';
var inviteLink = '';
var manageLink = '';
@@ -124,7 +178,7 @@ export default class NavbarDropdown extends React.Component {
<li>
<a
href='#'
- onClick={GlobalActions.showInviteMemberModal}
+ onClick={this.showInviteMemberModal}
>
<FormattedMessage
id='navbar_dropdown.inviteMember'
@@ -139,7 +193,7 @@ export default class NavbarDropdown extends React.Component {
<li>
<a
href='#'
- onClick={GlobalActions.showGetTeamInviteLinkModal}
+ onClick={this.showGetTeamInviteLinkModal}
>
<FormattedMessage
id='navbar_dropdown.teamLink'
@@ -197,6 +251,7 @@ export default class NavbarDropdown extends React.Component {
<ToggleModalButton
dialogType={TeamMembersModal}
dialogProps={{isAdmin}}
+ onClick={this.toggleDropdown}
>
{membersName}
</ToggleModalButton>
@@ -362,99 +417,82 @@ export default class NavbarDropdown extends React.Component {
}
return (
- <ul className='nav navbar-nav navbar-right'>
- <li
- ref='dropdown'
- className='dropdown'
+ <Dropdown
+ open={this.state.showDropdown}
+ onClose={this.toggleDropdown}
+ className='sidebar-header-dropdown'
+ pullRight={true}
+ >
+ <a
+ href='#'
+ className='sidebar-header-dropdown__toggle'
+ bsRole='toggle'
+ onClick={this.toggleDropdown}
>
- <a
- href='#'
- className='dropdown-toggle'
- role='button'
- onClick={this.props.toggleDropdown}
- >
- <span
- className='dropdown__icon'
- dangerouslySetInnerHTML={{__html: Constants.MENU_ICON}}
- />
- </a>
- <ul
- className='dropdown-menu'
- role='menu'
- >
- <li>
- <a
- href='#'
- onClick={(e) => {
- e.preventDefault();
- this.setState({showUserSettingsModal: true});
- }}
- >
- <FormattedMessage
- id='navbar_dropdown.accountSettings'
- defaultMessage='Account Settings'
- />
- </a>
- </li>
- {inviteLink}
- {teamLink}
- <li>
- <a
- href='#'
- onClick={GlobalActions.emitUserLoggedOutEvent}
- >
- <FormattedMessage
- id='navbar_dropdown.logout'
- defaultMessage='Logout'
- />
- </a>
- </li>
- <li className='divider'/>
- {integrationsLink}
- {this.renderCustomEmojiLink()}
- <li className='divider'/>
- {teamSettings}
- {manageLink}
- {sysAdminLink}
- {teams}
- <li className='divider'/>
- {helpLink}
- {reportLink}
- <li>
- <a
- href='#'
- onClick={this.handleAboutModal}
- >
- <FormattedMessage
- id='navbar_dropdown.about'
- defaultMessage='About Mattermost'
- />
- </a>
- </li>
- {nativeAppDivider}
- {nativeAppLink}
- <UserSettingsModal
- show={this.state.showUserSettingsModal}
- onModalDismissed={() => this.setState({showUserSettingsModal: false})}
- />
- <AboutBuildModal
- show={this.state.showAboutModal}
- onModalDismissed={this.aboutModalDismissed}
- />
- </ul>
- </li>
- </ul>
+ <span
+ className='sidebar-header-dropdown__icon'
+ dangerouslySetInnerHTML={{__html: Constants.MENU_ICON}}
+ />
+ </a>
+ <Dropdown.Menu>
+ <li>
+ <a
+ href='#'
+ onClick={this.toggleAccountSettingsModal}
+ >
+ <FormattedMessage
+ id='navbar_dropdown.accountSettings'
+ defaultMessage='Account Settings'
+ />
+ </a>
+ </li>
+ {inviteLink}
+ {teamLink}
+ <li>
+ <a
+ href='#'
+ onClick={GlobalActions.emitUserLoggedOutEvent}
+ >
+ <FormattedMessage
+ id='navbar_dropdown.logout'
+ defaultMessage='Logout'
+ />
+ </a>
+ </li>
+ <li className='divider'/>
+ {integrationsLink}
+ {this.renderCustomEmojiLink()}
+ <li className='divider'/>
+ {teamSettings}
+ {manageLink}
+ {sysAdminLink}
+ {teams}
+ <li className='divider'/>
+ {helpLink}
+ {reportLink}
+ <li>
+ <a
+ href='#'
+ onClick={this.handleAboutModal}
+ >
+ <FormattedMessage
+ id='navbar_dropdown.about'
+ defaultMessage='About Mattermost'
+ />
+ </a>
+ </li>
+ {nativeAppDivider}
+ {nativeAppLink}
+ <UserSettingsModal
+ show={this.state.showUserSettingsModal}
+ onModalDismissed={() => this.setState({showUserSettingsModal: false})}
+ />
+ <AboutBuildModal
+ show={this.state.showAboutModal}
+ onModalDismissed={this.aboutModalDismissed}
+ />
+ </Dropdown.Menu>
+ </Dropdown>
);
}
-}
-
-NavbarDropdown.defaultProps = {
- teamType: ''
-};
-NavbarDropdown.propTypes = {
- teamType: React.PropTypes.string,
- teamDisplayName: React.PropTypes.string,
- teamName: React.PropTypes.string,
- currentUser: React.PropTypes.object,
- toggleDropdown: React.PropTypes.function
-};
+} \ No newline at end of file
diff --git a/webapp/sass/layout/_headers.scss b/webapp/sass/layout/_headers.scss
index ee13e3c54..71dc98804 100644
--- a/webapp/sass/layout/_headers.scss
+++ b/webapp/sass/layout/_headers.scss
@@ -244,14 +244,16 @@
@include alpha-property(background, $black, .1);
}
- a {
- text-decoration: none;
- }
-
.user__name {
color: $white;
}
+ .sidebar-header-dropdown {
+ .sidebar-header-dropdown__toggle {
+ @include opacity(1);
+ }
+ }
+
.navbar-right {
.dropdown-toggle {
@include opacity(1);
@@ -259,16 +261,28 @@
}
}
- .navbar-right {
+ a {
+ text-decoration: none;
+ }
+
+ .sidebar-header-dropdown,
+ .admin-navbar-dropdown {
font-size: .85em;
position: absolute;
+ margin-right: -15px;
right: 22px;
top: 10px;
z-index: 5;
- .dropdown-toggle {
+ .sidebar-header-dropdown__toggle,
+ .admin-navbar-dropdown__toggle {
@include opacity(.8);
@include single-transition(all, .1s, linear);
+ background: none;
+ color: $white;
+ float: right;
+ font-size: 1em;
+ line-height: 1.8;
padding: 10px;
}
@@ -284,9 +298,14 @@
}
}
- .dropdown__icon {
+ .sidebar-header-dropdown__icon,
+ .admin-navbar-dropdown__icon {
fill: $white;
}
+
+ .divider + .divider {
+ display: none;
+ }
}
.user__picture {
@@ -330,22 +349,6 @@
font-weight: 400;
line-height: 18px;
}
-
- > .nav {
- > li {
- > a {
- background: none;
- float: right;
- padding: 2px;
- }
-
- .dropdown-toggle {
- color: $white;
- font-size: 1em;
- line-height: 1.8;
- }
- }
- }
}
.search__clear {
diff --git a/webapp/sass/responsive/_mobile.scss b/webapp/sass/responsive/_mobile.scss
index f819bd4d0..c55713058 100644
--- a/webapp/sass/responsive/_mobile.scss
+++ b/webapp/sass/responsive/_mobile.scss
@@ -824,7 +824,7 @@
margin: 10px 0;
}
- .navbar-right {
+ .sidebar-header-dropdown {
display: none;
}
}
diff --git a/webapp/utils/constants.jsx b/webapp/utils/constants.jsx
index 9e3eac5c0..039d48aaa 100644
--- a/webapp/utils/constants.jsx
+++ b/webapp/utils/constants.jsx
@@ -197,12 +197,20 @@ export const SocketEvents = {
WEBRTC: 'webrtc'
};
+export const TutorialSteps = {
+ INTRO_SCREENS: 0,
+ POST_POPOVER: 1,
+ CHANNEL_POPOVER: 2,
+ MENU_POPOVER: 3
+};
+
export const Constants = {
Preferences,
SocketEvents,
ActionTypes,
WebrtcActionTypes,
UserStatuses,
+ TutorialSteps,
PayloadSources: keyMirror({
SERVER_ACTION: null,
@@ -614,12 +622,6 @@ export const Constants = {
Ubuntu: 'font--ubuntu'
},
DEFAULT_FONT: 'Open Sans',
- TutorialSteps: {
- INTRO_SCREENS: 0,
- POST_POPOVER: 1,
- CHANNEL_POPOVER: 2,
- MENU_POPOVER: 3
- },
KeyCodes: {
BACKSPACE: 8,
TAB: 9,
diff --git a/webapp/utils/utils.jsx b/webapp/utils/utils.jsx
index d59687606..ffc676e63 100644
--- a/webapp/utils/utils.jsx
+++ b/webapp/utils/utils.jsx
@@ -522,7 +522,7 @@ export function applyTheme(theme) {
if (theme.sidebarHeaderTextColor) {
changeCss('.app__body .sidebar--left .team__header .header__info, .app__body .sidebar--menu .team__header .header__info, .app__body .post-list__timestamp > div', 'color:' + theme.sidebarHeaderTextColor, 1);
- changeCss('.app__body .sidebar--left .team__header .navbar-right .dropdown__icon, .app__body .sidebar--menu .team__header .navbar-right .dropdown__icon', 'fill:' + theme.sidebarHeaderTextColor, 1);
+ changeCss('.app__body .sidebar-header-dropdown__icon', 'fill:' + theme.sidebarHeaderTextColor, 1);
changeCss('.app__body .sidebar--left .team__header .user__name, .app__body .sidebar--menu .team__header .user__name', 'color:' + changeOpacity(theme.sidebarHeaderTextColor, 0.8), 1);
changeCss('.app__body .sidebar--left .team__header:hover .user__name, .app__body .sidebar--menu .team__header:hover .user__name', 'color:' + theme.sidebarHeaderTextColor, 1);
changeCss('.app__body .modal .modal-header .modal-title, .app__body .modal .modal-header .modal-title .name, .app__body .modal .modal-header button.close', 'color:' + theme.sidebarHeaderTextColor, 1);