diff options
Diffstat (limited to 'webapp')
-rw-r--r-- | webapp/components/admin_console/admin_navbar_dropdown.jsx | 6 | ||||
-rw-r--r-- | webapp/components/sidebar_header.jsx | 34 | ||||
-rw-r--r-- | webapp/components/sidebar_header_dropdown.jsx (renamed from webapp/components/navbar_dropdown.jsx) | 246 | ||||
-rw-r--r-- | webapp/sass/layout/_headers.scss | 49 | ||||
-rw-r--r-- | webapp/sass/responsive/_mobile.scss | 2 | ||||
-rw-r--r-- | webapp/utils/constants.jsx | 14 | ||||
-rw-r--r-- | webapp/utils/utils.jsx | 2 |
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); |