mirror of
https://github.com/apache/superset.git
synced 2024-09-12 00:29:39 -04:00
refactor: Use Antd Menu in Menu component (#11528)
* Menu dropdown refactored * MenuObject refactored * Fix unit tests * Style menu * Use theme variables
This commit is contained in:
parent
536346ff5e
commit
15111db6c5
@ -18,7 +18,8 @@
|
|||||||
*/
|
*/
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { shallow, mount } from 'enzyme';
|
import { shallow, mount } from 'enzyme';
|
||||||
import { Nav, MenuItem } from 'react-bootstrap';
|
import { Nav } from 'react-bootstrap';
|
||||||
|
import { Menu as DropdownMenu } from 'src/common/components';
|
||||||
import NavDropdown from 'src/components/NavDropdown';
|
import NavDropdown from 'src/components/NavDropdown';
|
||||||
import { supersetTheme, ThemeProvider } from '@superset-ui/core';
|
import { supersetTheme, ThemeProvider } from '@superset-ui/core';
|
||||||
|
|
||||||
@ -165,7 +166,7 @@ describe('Menu', () => {
|
|||||||
wrappingComponentProps: { theme: supersetTheme },
|
wrappingComponentProps: { theme: supersetTheme },
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(versionedWrapper.find('.version-info div')).toHaveLength(2);
|
expect(versionedWrapper.find('.version-info span')).toHaveLength(2);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('renders a NavDropdown (settings)', () => {
|
it('renders a NavDropdown (settings)', () => {
|
||||||
@ -173,6 +174,6 @@ describe('Menu', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('renders MenuItems in NavDropdown (settings)', () => {
|
it('renders MenuItems in NavDropdown (settings)', () => {
|
||||||
expect(wrapper.find(NavDropdown).find(MenuItem)).toHaveLength(6);
|
expect(wrapper.find(NavDropdown).find(DropdownMenu.Item)).toHaveLength(3);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -44,6 +44,11 @@ export const MenuItem = styled(AntdMenu.Item)`
|
|||||||
> a {
|
> a {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.ant-menu-item {
|
||||||
|
height: ${({ theme }) => theme.gridUnit * 7}px;
|
||||||
|
line-height: ${({ theme }) => theme.gridUnit * 7}px;
|
||||||
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const Menu = Object.assign(AntdMenu, {
|
export const Menu = Object.assign(AntdMenu, {
|
||||||
|
@ -18,8 +18,9 @@
|
|||||||
*/
|
*/
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { t, styled } from '@superset-ui/core';
|
import { t, styled } from '@superset-ui/core';
|
||||||
import { Nav, Navbar, NavItem, MenuItem } from 'react-bootstrap';
|
import { Nav, Navbar, NavItem } from 'react-bootstrap';
|
||||||
import NavDropdown from 'src/components/NavDropdown';
|
import NavDropdown from 'src/components/NavDropdown';
|
||||||
|
import { Menu as DropdownMenu } from 'src/common/components';
|
||||||
import MenuObject, {
|
import MenuObject, {
|
||||||
MenuObjectProps,
|
MenuObjectProps,
|
||||||
MenuObjectChildProps,
|
MenuObjectChildProps,
|
||||||
@ -71,7 +72,10 @@ const StyledHeader = styled.header`
|
|||||||
}
|
}
|
||||||
|
|
||||||
.version-info {
|
.version-info {
|
||||||
padding: 5px 20px;
|
padding: ${({ theme }) => theme.gridUnit * 1.5}px
|
||||||
|
${({ theme }) => theme.gridUnit * 4}px
|
||||||
|
${({ theme }) => theme.gridUnit * 1.5}px
|
||||||
|
${({ theme }) => theme.gridUnit * 7}px;
|
||||||
color: ${({ theme }) => theme.colors.grayscale.base};
|
color: ${({ theme }) => theme.colors.grayscale.base};
|
||||||
font-size: ${({ theme }) => theme.typography.sizes.xs}px;
|
font-size: ${({ theme }) => theme.typography.sizes.xs}px;
|
||||||
|
|
||||||
@ -107,7 +111,6 @@ const StyledHeader = styled.header`
|
|||||||
left: 50%;
|
left: 50%;
|
||||||
width: 0;
|
width: 0;
|
||||||
height: 3px;
|
height: 3px;
|
||||||
background-color: ${({ theme }) => theme.colors.primary.base};
|
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform: translateX(-50%);
|
transform: translateX(-50%);
|
||||||
transition: all ${({ theme }) => theme.transitionTiming}s;
|
transition: all ${({ theme }) => theme.transitionTiming}s;
|
||||||
@ -127,10 +130,6 @@ const StyledHeader = styled.header`
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.settings-divider {
|
|
||||||
margin-bottom: 8px;
|
|
||||||
border-bottom: 1px solid ${({ theme }) => theme.colors.grayscale.light2};
|
|
||||||
}
|
|
||||||
.navbar-right {
|
.navbar-right {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@ -140,34 +139,6 @@ const StyledHeader = styled.header`
|
|||||||
export function Menu({
|
export function Menu({
|
||||||
data: { menu, brand, navbar_right: navbarRight, settings },
|
data: { menu, brand, navbar_right: navbarRight, settings },
|
||||||
}: MenuProps) {
|
}: MenuProps) {
|
||||||
// Flatten settings
|
|
||||||
const flatSettings: any[] = [];
|
|
||||||
|
|
||||||
if (settings) {
|
|
||||||
settings.forEach((section: object, index: number) => {
|
|
||||||
const newSection: MenuObjectProps = {
|
|
||||||
...section,
|
|
||||||
index,
|
|
||||||
isHeader: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
flatSettings.push(newSection);
|
|
||||||
|
|
||||||
// Filter out '-'
|
|
||||||
if (newSection.childs) {
|
|
||||||
newSection.childs.forEach((child: any) => {
|
|
||||||
if (child !== '-') {
|
|
||||||
flatSettings.push(child);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (index !== settings.length - 1) {
|
|
||||||
flatSettings.push('-');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledHeader className="top" id="main-menu">
|
<StyledHeader className="top" id="main-menu">
|
||||||
<Navbar inverse fluid staticTop role="navigation">
|
<Navbar inverse fluid staticTop role="navigation">
|
||||||
@ -188,76 +159,56 @@ export function Menu({
|
|||||||
{!navbarRight.user_is_anonymous && <NewMenu />}
|
{!navbarRight.user_is_anonymous && <NewMenu />}
|
||||||
{settings && settings.length > 0 && (
|
{settings && settings.length > 0 && (
|
||||||
<NavDropdown id="settings-dropdown" title={t('Settings')}>
|
<NavDropdown id="settings-dropdown" title={t('Settings')}>
|
||||||
{flatSettings.map((section, index) => {
|
<DropdownMenu>
|
||||||
if (section === '-') {
|
{settings.map((section, index) => [
|
||||||
return (
|
<DropdownMenu.ItemGroup
|
||||||
<MenuItem
|
|
||||||
key={`$${index}`}
|
|
||||||
divider
|
|
||||||
disabled
|
|
||||||
className="settings-divider"
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (section.isHeader) {
|
|
||||||
return (
|
|
||||||
<MenuItem key={`${section.label}`} header>
|
|
||||||
{section.label}
|
|
||||||
</MenuItem>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<MenuItem
|
|
||||||
key={`${section.label}`}
|
key={`${section.label}`}
|
||||||
href={section.url}
|
title={section.label}
|
||||||
eventKey={index}
|
|
||||||
>
|
>
|
||||||
{section.label}
|
{section.childs?.map(child => {
|
||||||
</MenuItem>
|
if (typeof child !== 'string') {
|
||||||
);
|
return (
|
||||||
})}
|
<DropdownMenu.Item key={`${child.label}`}>
|
||||||
|
<a href={child.url}>{child.label}</a>
|
||||||
|
</DropdownMenu.Item>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
})}
|
||||||
|
</DropdownMenu.ItemGroup>,
|
||||||
|
index < settings.length - 1 && <DropdownMenu.Divider />,
|
||||||
|
])}
|
||||||
|
|
||||||
{!navbarRight.user_is_anonymous && (
|
{!navbarRight.user_is_anonymous && [
|
||||||
<>
|
<DropdownMenu.Divider key="user-divider" />,
|
||||||
<MenuItem
|
<DropdownMenu.ItemGroup key="user-section" title={t('User')}>
|
||||||
key="user-divider"
|
<DropdownMenu.Item key="profile">
|
||||||
divider
|
<a href={navbarRight.user_info_url}>{t('Profile')}</a>
|
||||||
disabled
|
</DropdownMenu.Item>
|
||||||
className="settings-divider"
|
<DropdownMenu.Item key="logout">
|
||||||
/>
|
<a href={navbarRight.user_logout_url}>{t('Logout')}</a>
|
||||||
<MenuItem key="user-section" header>
|
</DropdownMenu.Item>
|
||||||
{t('User')}
|
</DropdownMenu.ItemGroup>,
|
||||||
</MenuItem>
|
]}
|
||||||
<MenuItem href={navbarRight.user_info_url}>
|
{(navbarRight.version_string || navbarRight.version_sha) && [
|
||||||
{t('Profile')}
|
<DropdownMenu.Divider key="user-divider" />,
|
||||||
</MenuItem>
|
<DropdownMenu.ItemGroup
|
||||||
<MenuItem href={navbarRight.user_logout_url}>
|
key="about-section"
|
||||||
{t('Logout')}
|
title={t('About')}
|
||||||
</MenuItem>
|
>
|
||||||
</>
|
|
||||||
)}
|
|
||||||
{(navbarRight.version_string || navbarRight.version_sha) && (
|
|
||||||
<>
|
|
||||||
<MenuItem
|
|
||||||
key="user-divider"
|
|
||||||
divider
|
|
||||||
disabled
|
|
||||||
className="settings-divider"
|
|
||||||
/>
|
|
||||||
<MenuItem key="about-section" header>
|
|
||||||
{t('About')}
|
|
||||||
</MenuItem>
|
|
||||||
<li className="version-info">
|
|
||||||
{navbarRight.version_string && (
|
{navbarRight.version_string && (
|
||||||
<div>Version: {navbarRight.version_string}</div>
|
<li className="version-info">
|
||||||
|
<span>Version: {navbarRight.version_string}</span>
|
||||||
|
</li>
|
||||||
)}
|
)}
|
||||||
{navbarRight.version_sha && (
|
{navbarRight.version_sha && (
|
||||||
<div>SHA: {navbarRight.version_sha}</div>
|
<li className="version-info">
|
||||||
|
<span>SHA: {navbarRight.version_sha}</span>
|
||||||
|
</li>
|
||||||
)}
|
)}
|
||||||
</li>
|
</DropdownMenu.ItemGroup>,
|
||||||
</>
|
]}
|
||||||
)}
|
</DropdownMenu>
|
||||||
</NavDropdown>
|
</NavDropdown>
|
||||||
)}
|
)}
|
||||||
{navbarRight.documentation_url && (
|
{navbarRight.documentation_url && (
|
||||||
|
@ -17,7 +17,8 @@
|
|||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { NavItem, MenuItem } from 'react-bootstrap';
|
import { NavItem } from 'react-bootstrap';
|
||||||
|
import { Menu } from 'src/common/components';
|
||||||
import NavDropdown from '../NavDropdown';
|
import NavDropdown from '../NavDropdown';
|
||||||
|
|
||||||
export interface MenuObjectChildProps {
|
export interface MenuObjectChildProps {
|
||||||
@ -52,24 +53,22 @@ export default function MenuObject({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<NavDropdown id={`menu-dropdown-${label}`} eventKey={index} title={label}>
|
<NavDropdown id={`menu-dropdown-${label}`} title={label}>
|
||||||
{childs?.map((child: MenuObjectChildProps | string, index1: number) => {
|
<Menu>
|
||||||
if (typeof child === 'string' && child === '-') {
|
{childs?.map((child: MenuObjectChildProps | string, index1: number) => {
|
||||||
return <MenuItem key={`$${index1}`} divider />;
|
if (typeof child === 'string' && child === '-') {
|
||||||
}
|
return <Menu.Divider key={`$${index1}`} />;
|
||||||
if (typeof child !== 'string') {
|
}
|
||||||
return (
|
if (typeof child !== 'string') {
|
||||||
<MenuItem
|
return (
|
||||||
key={`${child.label}`}
|
<Menu.Item key={`${child.label}`}>
|
||||||
href={child.url}
|
<a href={child.url}> {child.label}</a>
|
||||||
eventKey={parseFloat(`${index}.${index1}`)}
|
</Menu.Item>
|
||||||
>
|
);
|
||||||
{child.label}
|
}
|
||||||
</MenuItem>
|
return null;
|
||||||
);
|
})}
|
||||||
}
|
</Menu>
|
||||||
return null;
|
|
||||||
})}
|
|
||||||
</NavDropdown>
|
</NavDropdown>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
*/
|
*/
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { t, styled } from '@superset-ui/core';
|
import { t, styled } from '@superset-ui/core';
|
||||||
import { MenuItem } from 'react-bootstrap';
|
import { Menu } from 'src/common/components';
|
||||||
import NavDropdown from 'src/components/NavDropdown';
|
import NavDropdown from 'src/components/NavDropdown';
|
||||||
|
|
||||||
const dropdownItems = [
|
const dropdownItems = [
|
||||||
@ -45,11 +45,15 @@ const StyledI = styled.div`
|
|||||||
export default function NewMenu() {
|
export default function NewMenu() {
|
||||||
return (
|
return (
|
||||||
<NavDropdown id="new-dropdown" title={<StyledI className="fa fa-plus" />}>
|
<NavDropdown id="new-dropdown" title={<StyledI className="fa fa-plus" />}>
|
||||||
{dropdownItems.map((menu, i) => (
|
<Menu>
|
||||||
<MenuItem key={i} href={menu.url}>
|
{dropdownItems.map((menu, i) => (
|
||||||
<i className={`fa ${menu.icon}`} /> {menu.label}
|
<Menu.Item key={i}>
|
||||||
</MenuItem>
|
<a href={menu.url}>
|
||||||
))}
|
<i className={`fa ${menu.icon}`} /> {menu.label}
|
||||||
|
</a>
|
||||||
|
</Menu.Item>
|
||||||
|
))}
|
||||||
|
</Menu>
|
||||||
</NavDropdown>
|
</NavDropdown>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -57,15 +57,6 @@ const NavDropdown = styled(ReactBootstrapNavDropdown)`
|
|||||||
padding: ${({ theme }) => theme.gridUnit}px 0;
|
padding: ${({ theme }) => theme.gridUnit}px 0;
|
||||||
top: 100%;
|
top: 100%;
|
||||||
border: none;
|
border: none;
|
||||||
& li a {
|
|
||||||
padding: ${({ theme }) => theme.gridUnit}px
|
|
||||||
${({ theme }) => theme.gridUnit * 4}px;
|
|
||||||
transition: all ${({ theme }) => theme.transitionTiming}s;
|
|
||||||
&:hover {
|
|
||||||
background: ${({ theme }) => theme.colors.primary.light4};
|
|
||||||
color: ${({ theme }) => theme.colors.grayscale.dark1};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user