Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
Size: Mime:
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import { messages as commonMessages } from '@doodle/common-messages';

import ArrowDown from '../../visuals/Icon/svg/ic_keyboard_arrow_down.svg';
import Icon from '../../visuals/Icon';
import Menu from '../../controls/Menu';
import UserAvatar from '../UserAvatar';
import { buttonVariants } from '../../controls/Button/Button';
import { menuDimensions, defaultMenuDimension } from '../../controls/Menu/Menu';
import { translateMenuItems } from '../../utils/translate';
import navigateToUrl from '../../utils/helper';

// The menu items will always appear in the order defined here. Any custom items
// will be inserted in the middle, in-between the 2nd and 3rd item here.
export const defaultItems = [
  {
    label: commonMessages.dashboard,
    to: '/dashboard',
  },
  {
    label: commonMessages.account,
    to: '/account',
  },
  {
    label: commonMessages.helpAndSupport,
    to: 'https://help.doodle.com',
  },
  {
    label: commonMessages.logout,
    // action added in render method
    // url is added in navigateToUrl within handleClickLogout
  },
];

export const adminMenuItem = [
  {
    label: commonMessages.adminSettings,
    to: '/admin',
  },
];

class UserMenu extends Component {
  static propTypes = {
    name: PropTypes.string,
    avatar: PropTypes.string,
    /** Is the logged in user an admin of an organisation
     */
    isOrgAdmin: PropTypes.bool,
    /**
     * Callback executed when the user clicks on the "Logout" button.
     * It can be overridden to add custom functionality such as tracking.
     * You can execute the default button behaviour within onClickLogout by running
     * the function provided as first parameter. If your custom code is asynchronous,
     * run the default behaviour as callback of your asynchronous action. This guarantees
     * that your custom action completes before navigating to another page.
     * @param {Function} defaultBehaviour - Function to execute the default click behaviour
     */
    onClickLogout: PropTypes.func,
    customItems: PropTypes.arrayOf(
      PropTypes.shape({
        label: PropTypes.shape({ id: PropTypes.string, defaultMessage: PropTypes.string }).isRequired,
        to: PropTypes.string,
        action: PropTypes.func,
      })
    ),
    variant: PropTypes.oneOf(buttonVariants),
    dimension: PropTypes.oneOf(menuDimensions),
    intl: PropTypes.object,
  };

  static defaultProps = {
    name: null,
    avatar: null,
    isOrgAdmin: false,
    onClickLogout: defaultBehaviour => defaultBehaviour(),
    customItems: [],
    variant: 'linkWhite',
    dimension: defaultMenuDimension,
    intl: null,
  };

  constructor(props) {
    super(props);
    this.handleClickLogout = this.handleClickLogout.bind(this);
  }

  /**
   * Handles calling the onClickLogout and passes the default behaviour
   * into the onClickLogout callback as an argument.
   * To override or add behaviour, see onClickLogout prop.
   */
  handleClickLogout() {
    const { onClickLogout } = this.props;
    onClickLogout(() => navigateToUrl('/logout'));
  }

  render() {
    const { name, avatar, customItems, variant, dimension, intl, isOrgAdmin } = this.props;

    const translatedDefaultItems = translateMenuItems(defaultItems, intl);
    const translatedCustomItems = translateMenuItems(customItems, intl);

    const menuItems = [
      translatedDefaultItems[0],
      translatedDefaultItems[1],
      ...translatedCustomItems,
      translatedDefaultItems[2],
      {
        ...translatedDefaultItems[3],
        action: this.handleClickLogout,
      },
    ];

    /**
     * If the current user is an organisation admin insert
     * a link to admin settings as the 3rd menu item
     */
    if (isOrgAdmin) {
      menuItems.splice(2, 0, translateMenuItems(adminMenuItem, intl)[0]);
    }

    const menuClassNames = classnames('UserMenu', {
      [`UserMenu--${dimension}`]: dimension,
    });

    return (
      <Menu
        className={menuClassNames}
        variant={variant}
        horizontalAlign="right"
        items={menuItems}
        dimension={dimension}
      >
        <UserAvatar name={name} avatar={avatar} />
        <Icon icon={ArrowDown} />
      </Menu>
    );
  }
}

export default UserMenu;