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 { messages as commonMessages } from '@doodle/common-messages';

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

export const getDefaultNavLinks = (page, intl) => {
  const locale = intl ? intl.locale : 'en';

  const contactLinkByLocale =
    locale === 'de'
      ? 'https://go.doodle.com/WF-2021-01-Contact-Sales-DE_LP-02.html'
      : 'https://landing.doodle.com/contact-sales';

  return [
    {
      label: commonMessages.features,
      to: `/${locale}/features`,
      'data-track': JSON.stringify({
        event: 'Click Product',
        type: 'user Interaction',
        properties: { label: page, category: 'Global Navigation' },
      }),
    },
    {
      label: commonMessages.solutions,
      submenu: [
        {
          label: commonMessages.solutionsRecruiting,
          to: `/${locale}/solutions/recruiting`,
        },
        {
          label: commonMessages.solutionsBoardMeetings,
          to: `/${locale}/solutions/board-meetings`,
        },
        {
          label: commonMessages.solutionsSales,
          to: `/${locale}/solutions/sales`,
        },
        {
          label: commonMessages.solutionsEducation,
          to: `/${locale}/solutions/education`,
        },
        {
          label: commonMessages.solutionsNonProfit,
          to: `/${locale}/solutions/non-profit`,
        },
        {
          label: commonMessages.solutionsConsultants,
          to: `/${locale}/solutions/consultants`,
        },
        {
          label: commonMessages.solutionsEnterprise,
          to: `/${locale}/solutions/enterprise`,
        },
      ],
    },
    {
      label: commonMessages.pricing,
      to: '/premium',
      'data-track': JSON.stringify({
        event: 'Click Pricing',
        type: 'user Interaction',
        properties: { label: page, category: 'Global Navigation' },
      }),
    },
    {
      label: commonMessages.integrations,
      to: `/${locale}/integrations`,
      'data-track': JSON.stringify({
        event: 'Click Integrations',
        type: 'user Interaction',
        properties: { label: page, category: 'Global Navigation' },
      }),
    },
    {
      label: commonMessages.resources,
      submenu: [
        {
          label: commonMessages.resourceCenter,
          to: `/${locale}/resources`,
          'data-track': JSON.stringify({
            event: 'Click Resources',
            type: 'user Interaction',
            properties: { label: page, category: 'Global Navigation' },
          }),
        },
        {
          label: commonMessages.blog,
          to: 'https://blog.doodle.com/',
        },
      ],
    },
    {
      label: commonMessages.contact,
      submenu: [
        {
          label: commonMessages.sales,
          to: contactLinkByLocale,
          'data-track': JSON.stringify({
            event: 'Click Contact Sales',
            type: 'user Interaction',
            properties: {
              label: page,
              description: "user clicks on the 'Contact Sales' link placed in the header",
              category: 'Global Navigation',
              'Contact Sales': 'Header',
            },
          }),
        },
        {
          label: commonMessages.helpAndSupport,
          to: 'https://help.doodle.com',
        },
      ],
    },
  ];
};

const Navigation = ({
  links,
  user,
  theme,
  hideCreatePollMenu,
  onClickLogin,
  onClickLogout,
  onClickSignup,
  onClickCreatePoll,
  onClickCreateOneOnOne,
  onClickCreateBookingPage,
  onClickCreateSurvey,
  customUrl,
  page,
  currentPageType,
  customLogo,
  trackingClient,
  intl,
  showSignUp,
}) => {
  let navLinks = links || getDefaultNavLinks(page, intl);
  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 isOrgAdmin = checkIfOrgAdmin(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}
      isOrgAdmin={isOrgAdmin}
      intl={intl}
      showSignUp={showSignUp}
    />,
    <CreatePollMenu
      user={user}
      page={page}
      onClickCreatePoll={onClickCreatePoll}
      onClickCreateOneOnOne={onClickCreateOneOnOne}
      onClickCreateBookingPage={onClickCreateBookingPage}
      onClickCreateSurvey={onClickCreateSurvey}
      trackingClient={trackingClient}
      intl={intl}
    />,
    <HamburgerMenu
      className="Navigation-hamburgerMenu"
      items={navLinks}
      user={user}
      onClickLogin={onClickLogin}
      onClickLogout={onClickLogout}
      onClickSignup={onClickSignup}
      isOrgAdmin={isOrgAdmin}
      intl={intl}
    />,
  ];

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

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

export const NavigationTypes = {
  /** 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 "Bookable Calendar" button.
   * It can be overridden to add custom functionality such as tracking.
   * You can execute the default button behaviour within onClickCreateBookingPage 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
   */
  onClickCreateBookingPage: 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,

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

  /** An initialized instance of lib-tracking client */
  trackingClient: TrackingClientShape,

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

  /** Show Sign Up Button - defaults to true */
  showSignUp: PropTypes.bool,
};

Navigation.propTypes = NavigationTypes;

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(),
  onClickCreateBookingPage: defaultBehaviour => defaultBehaviour(),
  onClickCreateSurvey: defaultBehaviour => defaultBehaviour(),
  customUrl: '',
  currentPageType: '',
  customLogo: '',
  trackingClient: null,
  intl: null,
  showSignUp: true,
};

Navigation.displayName = 'Navigation';

export default Navigation;