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:
/**
 * The navigation header used for all landing pages.
 */

import React from 'react';
import PropTypes from 'prop-types';

import commonMessages from '@doodle/common-messages';

import { userPropType, isLoggedIn as checkIfLoggedIn } from '../../utils/user';
import Header from '../Header';
import { Button } from '../../controls/Button';
import LogoLink from '../../visuals/LogoLink';
import CreatePollMenu from './CreatePollMenu';
import HamburgerMenu from './HamburgerMenu';
import { translateMenuItems } from '../../utils/translate';
import pickDataAttributes from '../../utils/pickDataAttributes';
import Menu from '../../controls/Menu/Menu';
import Icon from '../../visuals/Icon';
import ArrowDownIcon from '../../visuals/Icon/svg/ic_keyboard_arrow_down.svg';
import HeaderWidget from '../../user/HeaderWidget';
import { submenuKey } from './constants';

export const getDefaultNavLinks = page => [
  {
    label: commonMessages.features,
    to: '/en/features',
    'data-tracking': 'true',
    'data-ga-action': 'clickProduct',
    'data-ga-category': 'userInteraction',
    'data-ga-label': page,
  },
  {
    label: commonMessages.solutions,
    submenu: [
      {
        label: commonMessages.solutionsRecruiting,
        to: '/en/solutions/recruiting',
      },
      {
        label: commonMessages.solutionsBoardMeetings,
        to: '/en/solutions/board-meetings',
      },
      {
        label: commonMessages.solutionsSales,
        to: '/en/solutions/sales',
      },
      {
        label: commonMessages.solutionsEducation,
        to: '/en/solutions/education',
      },
      {
        label: commonMessages.solutionsNonProfit,
        to: '/en/solutions/non-profit',
      },
      {
        label: commonMessages.solutionsConsultants,
        to: '/en/solutions/consultants',
      },
      {
        label: commonMessages.solutionsEnterprise,
        to: '/en/solutions/enterprise',
      },
    ],
  },
  {
    label: commonMessages.pricing,
    to: '/premium',
    'data-tracking': 'true',
    'data-ga-action': 'clickPricing',
    'data-ga-category': 'userInteraction',
    'data-ga-label': page,
  },
  {
    label: commonMessages.integrations,
    to: '/en/integrations',
    'data-tracking': 'true',
    'data-ga-action': 'clickIntegrations',
    'data-ga-category': 'userInteraction',
    'data-ga-label': page,
  },
  {
    label: commonMessages.resources,
    submenu: [
      {
        label: commonMessages.resourceCenter,
        to: '/en/resources',
        'data-tracking': 'true',
        'data-ga-action': 'clickResources',
        'data-ga-category': 'userInteraction',
        'data-ga-label': page,
      },
      {
        label: commonMessages.blog,
        to: 'https://blog.doodle.com/',
      },
    ],
  },
  {
    label: commonMessages.contact,
    submenu: [
      {
        label: commonMessages.sales,
        to: 'https://landing.doodle.com/contact-sales',
        'data-tracking': 'true',
        'data-ga-action': 'contactSales',
        'data-ga-category': 'userInteraction',
        'data-ga-label': page,
        'data-amplitude-type': 'user Interaction',
        'data-amplitude-name': 'Click Contact Sales',
        'data-amplitude-properties': JSON.stringify({
          'Contact Sales': 'Header',
          'Event description': 'user clicks on the "Contact Sales” link placed in the header or in the footer',
        }),
      },
      {
        label: commonMessages.helpAndSupport,
        to: 'https://help.doodle.com',
      },
    ],
  },
];

const Navigation = ({
  links,
  user,
  theme,
  hideCreatePollMenu,
  onClickLogin,
  onClickLogout,
  onClickSignup,
  onClickCreatePoll,
  onClickCreateOneOnOne,
  onClickCreateSurvey,
  customUrl,
  page,
  currentPageType,
  intl,
  customLogo,
}) => {
  let navLinks = links || getDefaultNavLinks(page);
  navLinks = translateMenuItems(navLinks, intl);

  // Transform menu items to Menu and Link elements
  const navElements = navLinks.map(itemOrElement => {
    if (React.isValidElement(itemOrElement)) {
      return itemOrElement;
    }
    if (submenuKey in itemOrElement) {
      const { label: menuTitle, submenu } = itemOrElement;
      // Only items as props objects supported here, not elements, due to Menu API
      return (
        <Menu items={submenu} horizontalAlign="left" dimension="compact" variant="linkDark" className={menuTitle}>
          {menuTitle}
          <Icon icon={ArrowDownIcon} />
        </Menu>
      );
    }
    const { label, to, ...rest } = itemOrElement;
    return (
      <Button href={to} variant="linkDark" dimension="compact" {...pickDataAttributes(rest)}>
        {label}
      </Button>
    );
  });

  const isLoggedIn = checkIfLoggedIn(user);

  const headerLeft = [
    <LogoLink user={user} currentPageType={currentPageType} customUrl={customUrl} logoUrl={customLogo} />,
    ...navElements,
  ];
  const headerRight = [
    <HeaderWidget
      username={null} // hide username by design
      userAvatar={isLoggedIn ? user.data.avatarSmallUrl : null}
      isLoggedIn={isLoggedIn}
      onClickLogin={onClickLogin}
      onClickLogout={onClickLogout}
      onClickSignup={onClickSignup}
    />,
    <CreatePollMenu
      user={user}
      onClickCreatePoll={onClickCreatePoll}
      onClickCreateOneOnOne={onClickCreateOneOnOne}
      onClickCreateSurvey={onClickCreateSurvey}
      intl={intl}
    />,
    <HamburgerMenu
      className="Navigation-hamburgerMenu"
      items={navLinks}
      user={user}
      onClickLogin={onClickLogin}
      onClickLogout={onClickLogout}
      onClickSignup={onClickSignup}
    />,
  ];

  if (hideCreatePollMenu) {
    headerRight.splice(1, 1);
  }

  return <Header theme={theme} left={headerLeft} right={headerRight} />;
};

Navigation.propTypes = {
  /** Custom array to override the default links of the header. If no links are needed, an empty array should be passed to this prop. */
  links: PropTypes.array,

  /** Defines the user and the shape of the data. */
  user: userPropType,

  /** The background colour for the header - defaults to transparent. */
  theme: PropTypes.oneOf(['white', 'transparent']),

  /** Hide or show the create poll menu (Create/Create a doodle). */
  hideCreatePollMenu: PropTypes.bool,

  /**
   * Callback executed when the user clicks on the "Login" button.
   * It can be overridden to add custom functionality such as tracking.
   * You can execute the default button behaviour within onClickLogin 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
   */
  onClickLogin: PropTypes.func,

  /**
   * 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,

  /**
   * Callback executed when the user clicks on the "Signup" button.
   * It can be overridden to add custom functionality such as tracking.
   * You can execute the default button behaviour within onClickSignup 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
   */
  onClickSignup: PropTypes.func,

  /**
   * Callback executed when the user clicks on the "Group Meeting" button.
   * It can be overridden to add custom functionality such as tracking.
   * You can execute the default button behaviour within onClickCreatePoll 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
   */
  onClickCreatePoll: PropTypes.func,

  /**
   * Callback executed when the user clicks on the "1:1 Meeting" button.
   * It can be overridden to add custom functionality such as tracking.
   * You can execute the default button behaviour within onClickCreateOneOnOne 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
   */
  onClickCreateOneOnOne: PropTypes.func,

  /**
   * Callback executed when the user clicks on the "Survey" button.
   * It can be overridden to add custom functionality such as tracking.
   * You can execute the default button behaviour within onClickCreateSurvey 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
   */
  onClickCreateSurvey: PropTypes.func,

  /** Page that the header will be added in - this prop is used for tracking purposes. */
  page: PropTypes.string.isRequired,

  /** CustomUrl prop that is passed into the LogoLink to redirect the user to a custom link */
  customUrl: PropTypes.string,

  /** An object used for internationalization. */
  intl: PropTypes.object,

  /** Props to pass through to the LogoLink which will determine where to redirect the user */
  currentPageType: PropTypes.string,

  /** A prop for passing in a custom logo into LogoLink.
   * If this prop is not used, Doodle's logo will be displayed */
  customLogo: PropTypes.string,
};

Navigation.defaultProps = {
  links: null,
  user: null,
  theme: 'transparent',
  hideCreatePollMenu: false,
  onClickLogin: defaultBehaviour => defaultBehaviour(),
  onClickLogout: defaultBehaviour => defaultBehaviour(),
  onClickSignup: defaultBehaviour => defaultBehaviour(),
  onClickCreatePoll: defaultBehaviour => defaultBehaviour(),
  onClickCreateOneOnOne: defaultBehaviour => defaultBehaviour(),
  onClickCreateSurvey: defaultBehaviour => defaultBehaviour(),
  intl: null,
  customUrl: '',
  currentPageType: '',
  customLogo: '',
};

Navigation.displayName = 'Navigation';

export default Navigation;