/* Copyright (C) 2017 Cloudbase Solutions SRL This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ // @flow import React from 'react' import { observer } from 'mobx-react' import styled, { css } from 'styled-components' import Palette from '../../styleUtils/Palette' import StyleProps from '../../styleUtils/StyleProps' import { navigationMenu } from '../../../config' import type { User } from '../../../types/User' import userImage from './images/user.svg' import userWhiteImage from './images/user-white.svg' const Wrapper = styled.div` position: relative; ` const Icon = styled.div` position: relative; cursor: pointer; width: 32px; height: 32px; transition: all ${StyleProps.animations.swift}; background: url('${props => props.white ? userWhiteImage : userImage}') no-repeat center; &:hover { opacity: 0.8; } ` const List = styled.div` background: ${Palette.grayscale[1]}; border-radius: ${StyleProps.borderRadius}; position: absolute; right: 0; top: 45px; padding: 16px; display: flex; flex-direction: column; z-index: 10; ` const ListItem = styled.div` padding: 8px 0; &:last-child { padding-bottom: 0; } ` const Label = styled.div` display: inline-block; white-space: nowrap; ${props => props.selectable ? css` cursor: pointer; &:hover { color: ${Palette.primary}; } ` : ''} ` const ListHeader = styled.div` position: relative; &:after { content: ' '; position: absolute; width: 10px; height: 10px; background: ${Palette.grayscale[1]}; border: 1px solid ${Palette.grayscale[1]}; border-color: transparent transparent ${Palette.grayscale[1]} ${Palette.grayscale[1]}; transform: rotate(135deg); right: -6px; top: -22px; transition: all ${StyleProps.animations.swift}; } ` const Username = styled.a` font-size: 16px; color: ${Palette.black}; text-decoration: none; &:hover { color: ${props => props.href ? Palette.primary : 'inherit'}; } ` const Email = styled.div` font-size: 10px; color: ${Palette.grayscale[4]}; margin-top: 8px; padding-bottom: 8px; border-bottom: 1px solid ${Palette.grayscale[3]}; ` type DictItem = { label: string, value: string } type Props = { onItemClick: (item: DictItem) => void, user: ?User, white?: boolean, } type State = { showDropdownList: boolean, } @observer class UserDropdown extends React.Component { itemMouseDown: boolean constructor() { super() this.state = { showDropdownList: false, } // $FlowIssue this.handlePageClick = this.handlePageClick.bind(this) } componentDidMount() { window.addEventListener('mousedown', this.handlePageClick, false) } componentWillUnmount() { window.removeEventListener('mousedown', this.handlePageClick, false) } handleItemClick(item: DictItem) { if (this.props.onItemClick) { this.props.onItemClick(item) } this.setState({ showDropdownList: false }) } handlePageClick() { if (!this.itemMouseDown) { this.setState({ showDropdownList: false }) } } handleButtonClick() { this.setState({ showDropdownList: !this.state.showDropdownList }) } renderNoUser() { if (this.props.user) { return null } return } renderListHeader() { if (!this.props.user) { return null } let href: ?string let isAdmin = this.props.user.isAdmin if (isAdmin && navigationMenu.find(m => m.value === 'users' && !m.disabled && (!m.requiresAdmin || isAdmin))) { href = `#/user/${this.props.user.id}` } return ( { this.itemMouseDown = true }} onMouseUp={() => { this.itemMouseDown = false }} > {this.props.user.name} {this.props.user.email} ) } renderList() { if (!this.state.showDropdownList) { return null } let items = [{ label: 'Sign Out', value: 'signout', }] let list = ( {this.renderListHeader()} {this.renderNoUser()} {this.props.user ? items.map(item => { return ( { this.itemMouseDown = true }} onMouseUp={() => { this.itemMouseDown = false }} > ) }) : null} ) return list } render() { return ( { this.itemMouseDown = true }} onMouseUp={() => { this.itemMouseDown = false }} onClick={() => this.handleButtonClick()} white={this.props.white} data-test-id="userDropdown-button" /> {this.renderList()} ) } } export default UserDropdown