Files
AdGuardHome/client/src/components/Header/Menu.js
Artem Baskal 97df19898f Pull request #730: + client: Add Hot Module Replacement
Merge in DNS/adguard-home from feature/hmr to master

Squashed commit of the following:

commit 952ed1955c2a7a32446d99489f137f02eb47c99e
Merge: 83484931 de92c852
Author: ArtemBaskal <a.baskal@adguard.com>
Date:   Thu Aug 13 11:02:10 2020 +0300

    Merge branch 'master' into feature/hmr

commit 8348493105d7d63d8b0836a5c272df2b17a6b142
Author: ArtemBaskal <a.baskal@adguard.com>
Date:   Wed Aug 5 15:07:31 2020 +0300

    Remove empty prop types, remove Services empty container

commit b2fe4a30b79d91e482318ee5deea8e49c7038f7e
Author: ArtemBaskal <a.baskal@adguard.com>
Date:   Wed Aug 5 13:56:35 2020 +0300

    Move constants

commit f8be4c18c35193ad77bf5e25f311ad834c1d6870
Author: ArtemBaskal <a.baskal@adguard.com>
Date:   Wed Aug 5 13:19:02 2020 +0300

    Fix Setup bug, update webpack.dev

commit 1d9cc4ddf8af2c979eb707a7f0fc06744eec186c
Author: ArtemBaskal <a.baskal@adguard.com>
Date:   Wed Aug 5 12:10:38 2020 +0300

    Review changes

commit a1edb21358def21ed1808b081ffc2f0b6755e3da
Author: ArtemBaskal <a.baskal@adguard.com>
Date:   Wed Aug 5 11:46:58 2020 +0300

    Remove lazy loading, fix updated components

commit 0aa2cf55f8d4206ac9e2f99fc1b990ed8a9c7825
Author: ArtemBaskal <a.baskal@adguard.com>
Date:   Tue Aug 4 20:32:19 2020 +0300

    Refactor App component, add lazy loading

commit 3c2ba4772a91ff7b06641dba6c6bf3fdcd2fdf7f
Author: ArtemBaskal <a.baskal@adguard.com>
Date:   Tue Aug 4 17:12:41 2020 +0300

    Simplify App hot loading boilerplate, setup lazy loading, update Header

commit 8df3221f315372b066f2ac0c9a1687f1677b8415
Author: ArtemBaskal <a.baskal@adguard.com>
Date:   Tue Aug 4 15:16:06 2020 +0300

    + client: Add Hot Module Replacement
2020-08-13 11:15:45 +03:00

189 lines
5.1 KiB
JavaScript

import React, { Component } from 'react';
import { NavLink } from 'react-router-dom';
import PropTypes from 'prop-types';
import enhanceWithClickOutside from 'react-click-outside';
import classnames from 'classnames';
import { Trans, withTranslation } from 'react-i18next';
import { SETTINGS_URLS, FILTERS_URLS, MENU_URLS } from '../../helpers/constants';
import Dropdown from '../ui/Dropdown';
const MENU_ITEMS = [
{
route: MENU_URLS.root,
exact: true,
icon: 'dashboard',
text: 'dashboard',
order: 0,
},
// Settings dropdown should have visual order 1
// Filters dropdown should have visual order 2
{
route: MENU_URLS.logs,
icon: 'log',
text: 'query_log',
order: 3,
},
{
route: MENU_URLS.guide,
icon: 'setup',
text: 'setup_guide',
order: 4,
},
];
const SETTINGS_ITEMS = [
{
route: SETTINGS_URLS.settings,
text: 'general_settings',
},
{
route: SETTINGS_URLS.dns,
text: 'dns_settings',
},
{
route: SETTINGS_URLS.encryption,
text: 'encryption_settings',
},
{
route: SETTINGS_URLS.clients,
text: 'client_settings',
},
{
route: SETTINGS_URLS.dhcp,
text: 'dhcp_settings',
},
];
const FILTERS_ITEMS = [
{
route: FILTERS_URLS.dns_blocklists,
text: 'dns_blocklists',
},
{
route: FILTERS_URLS.dns_allowlists,
text: 'dns_allowlists',
},
{
route: FILTERS_URLS.dns_rewrites,
text: 'dns_rewrites',
},
{
route: FILTERS_URLS.blocked_services,
text: 'blocked_services',
},
{
route: FILTERS_URLS.custom_rules,
text: 'custom_filtering_rules',
},
];
class Menu extends Component {
handleClickOutside = () => {
this.props.closeMenu();
};
closeMenu = () => {
this.props.closeMenu();
};
getActiveClassForDropdown = (URLS) => {
const isActivePage = Object.values(URLS)
.some((item) => item === this.props.pathname);
return isActivePage ? 'active' : '';
};
getNavLink = ({
route, exact, text, order, className, icon,
}) => (
<NavLink
to={route}
key={route}
exact={exact || false}
className={`order-${order} ${className}`}
onClick={this.closeMenu}
>
{icon && (
<svg className="nav-icon">
<use xlinkHref={`#${icon}`} />
</svg>
)}
<Trans>{text}</Trans>
</NavLink>
);
getDropdown = ({
label, order, URLS, icon, ITEMS,
}) => (
<Dropdown
label={this.props.t(label)}
baseClassName='dropdown'
controlClassName={`nav-link ${this.getActiveClassForDropdown(URLS)}`}
icon={icon}>
{ITEMS.map((item) => (
this.getNavLink({
...item,
order,
className: 'dropdown-item',
})))}
</Dropdown>
);
render() {
const menuClass = classnames({
'header__column mobile-menu': true,
'mobile-menu--active': this.props.isMenuOpen,
});
return (
<>
<div className={menuClass}>
<ul className="nav nav-tabs border-0 flex-column flex-lg-row flex-nowrap">
{MENU_ITEMS.map((item) => (
<li
className={`nav-item order-${item.order}`}
key={item.text}
onClick={this.closeMenu}
>
{this.getNavLink({
...item,
className: 'nav-link',
})}
</li>
))}
<li className="nav-item order-1">
{this.getDropdown({
order: 1,
label: 'settings',
icon: 'settings',
URLS: SETTINGS_URLS,
ITEMS: SETTINGS_ITEMS,
})}
</li>
<li className="nav-item order-2">
{this.getDropdown({
order: 2,
label: 'filters',
icon: 'filters',
URLS: FILTERS_URLS,
ITEMS: FILTERS_ITEMS,
})}
</li>
</ul>
</div>
</>
);
}
}
Menu.propTypes = {
isMenuOpen: PropTypes.bool.isRequired,
closeMenu: PropTypes.func.isRequired,
pathname: PropTypes.string.isRequired,
t: PropTypes.func,
};
export default withTranslation()(enhanceWithClickOutside(Menu));