Skip to content

Commit

Permalink
style: Move security/manage navigation tabs into a settings dropdown (a…
Browse files Browse the repository at this point in the history
  • Loading branch information
riahk authored and auxten committed Nov 20, 2020
1 parent eb2f72c commit b1f9c85
Show file tree
Hide file tree
Showing 4 changed files with 156 additions and 23 deletions.
38 changes: 24 additions & 14 deletions superset-frontend/spec/javascripts/components/Menu_spec.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,27 +18,14 @@
*/
import React from 'react';
import { shallow, mount } from 'enzyme';
import { Nav } from 'react-bootstrap';
import { Nav, NavDropdown, MenuItem } from 'react-bootstrap';
import { supersetTheme, ThemeProvider } from '@superset-ui/style';

import Menu from 'src/components/Menu/Menu';

const defaultProps = {
data: {
menu: [
{
name: 'Security',
icon: 'fa-cogs',
label: 'Security',
childs: [
{
name: 'List Users',
icon: 'fa-user',
label: 'List Users',
url: '/users/list/',
},
],
},
{
name: 'Sources',
icon: 'fa-table',
Expand Down Expand Up @@ -100,6 +87,21 @@ const defaultProps = {
user_login_url: '/login/',
locale: 'en',
},
settings: [
{
name: 'Security',
icon: 'fa-cogs',
label: 'Security',
childs: [
{
name: 'List Users',
icon: 'fa-user',
label: 'List Users',
url: '/users/list/',
},
],
},
],
},
};

Expand Down Expand Up @@ -164,4 +166,12 @@ describe('Menu', () => {

expect(versionedWrapper.find('.version-info div')).toHaveLength(2);
});

it('renders a NavDropdown (settings)', () => {
expect(wrapper.find(NavDropdown)).toHaveLength(1);
});

it('renders MenuItems in NavDropdown (settings)', () => {
expect(wrapper.find(NavDropdown).find(MenuItem)).toHaveLength(2);
});
});
70 changes: 68 additions & 2 deletions superset-frontend/src/components/Menu/Menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
*/
import React from 'react';
import { t } from '@superset-ui/translation';
import { Nav, Navbar, NavItem } from 'react-bootstrap';
import { Nav, Navbar, NavDropdown, NavItem, MenuItem } from 'react-bootstrap';
import styled from '@superset-ui/style';
import MenuObject, { MenuObjectProps } from './MenuObject';
import NewMenu from './NewMenu';
Expand Down Expand Up @@ -51,6 +51,7 @@ export interface MenuProps {
menu: MenuObjectProps[];
brand: BrandProps;
navbar_right: NavBarProps;
settings: MenuObjectProps[];
};
}

Expand Down Expand Up @@ -115,11 +116,44 @@ const StyledHeader = styled.header`
margin: 0;
}
}
.settings-divider {
margin-bottom: 8px;
border-bottom: 1px solid ${({ theme }) => theme.colors.grayscale.light2};
}
`;

export default function Menu({
data: { menu, brand, navbar_right: navbarRight },
data: { menu, brand, navbar_right: navbarRight, settings },
}: 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 (
<StyledHeader className="top" id="main-menu">
<Navbar inverse fluid staticTop role="navigation">
Expand All @@ -138,6 +172,38 @@ export default function Menu({
</Nav>
<Nav className="navbar-right">
{!navbarRight.user_is_anonymous && <NewMenu />}
{settings && settings.length && (
<NavDropdown id={`settings-dropdown`} title="Settings">
{flatSettings.map((section, index) => {
if (section === '-') {
return (
<MenuItem
key={`$${index}`}
divider
disabled
className="settings-divider"
/>
);
} else if (section.isHeader) {
return (
<MenuItem key={`${section.label}`} disabled>
{section.label}
</MenuItem>
);
}

return (
<MenuItem
key={`${section.label}`}
href={section.url}
eventKey={index}
>
{section.label}
</MenuItem>
);
})}
</NavDropdown>
)}
{navbarRight.documentation_url && (
<NavItem
href={navbarRight.documentation_url}
Expand Down
4 changes: 3 additions & 1 deletion superset-frontend/src/components/Menu/MenuObject.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@ import React from 'react';
import { NavItem, MenuItem } from 'react-bootstrap';
import NavDropdown from '../NavDropdown';

interface MenuObjectChildProps {
export interface MenuObjectChildProps {
label: string;
name?: string;
icon: string;
index: number;
url?: string;
Expand All @@ -33,6 +34,7 @@ export interface MenuObjectProps {
index: number;
url?: string;
childs?: (MenuObjectChildProps | string)[];
isHeader?: boolean;
}

export default function MenuObject({
Expand Down
67 changes: 61 additions & 6 deletions superset-frontend/src/views/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,16 @@ import ChartList from 'src/views/CRUD/chart/ChartList';
import DatasetList from 'src/views/CRUD/data/dataset/DatasetList';
import DatasourceList from 'src/views/CRUD/data/database/DatabaseList';

import messageToastReducer from 'src/messageToasts/reducers';
import { initEnhancer } from 'src/reduxUtils';
import setupApp from 'src/setup/setupApp';
import setupPlugins from 'src/setup/setupPlugins';
import Welcome from 'src/views/CRUD/welcome/Welcome';
import ToastPresenter from 'src/messageToasts/containers/ToastPresenter';
import messageToastReducer from '../messageToasts/reducers';
import { initEnhancer } from '../reduxUtils';
import setupApp from '../setup/setupApp';
import setupPlugins from '../setup/setupPlugins';
import Welcome from './CRUD/welcome/Welcome';
import ToastPresenter from '../messageToasts/containers/ToastPresenter';
import {
MenuObjectProps,
MenuObjectChildProps,
} from '../components/Menu/MenuObject';

setupApp();
setupPlugins();
Expand All @@ -58,6 +62,57 @@ const store = createStore(
compose(applyMiddleware(thunk), initEnhancer(false)),
);

// Menu items that should go into settings dropdown
const settingsMenus = {
Security: true,
Manage: true,
};

// Menu items that should be ignored
const ignore = {
'Import Dashboards': true,
};

// Cycle through menu.menu to build out cleanedMenu and settings
const cleanedMenu: object[] = [];
const settings: object[] = [];

menu.menu.forEach((item: any) => {
if (!item) {
return;
}

const children: (MenuObjectProps | string)[] = [];
const newItem = {
...item,
};

// Filter childs
if (item.childs) {
item.childs.forEach((child: MenuObjectChildProps | string) => {
if (typeof child === 'string') {
children.push(child);
} else if (
(child as MenuObjectChildProps).label &&
!ignore.hasOwnProperty(child.label)
) {
children.push(child);
}
});

newItem.childs = children;
}

if (!settingsMenus.hasOwnProperty(item.name)) {
cleanedMenu.push(newItem);
} else {
settings.push(newItem);
}
});

menu.menu = cleanedMenu;
menu.settings = settings;

const App = () => (
<Provider store={store}>
<ThemeProvider theme={supersetTheme}>
Expand Down

0 comments on commit b1f9c85

Please sign in to comment.