Updated menu component to use mds (#2866)

Signed-off-by: Benjamin Perez <benjamin@bexsoft.net>
This commit is contained in:
Alex
2023-06-13 15:16:46 -06:00
committed by GitHub
parent ee8fac8be8
commit 08a3ff65c7
12 changed files with 242 additions and 600 deletions

View File

@@ -33,7 +33,6 @@ import { useSelector } from "react-redux";
import { AppState, useAppDispatch } from "../../store";
import { snackBarCommon } from "./Common/FormComponents/common/styleLibrary";
import { ErrorResponseHandler } from "../../common/types";
import Menu from "./Menu/Menu";
import api from "../../common/api";
import MainError from "./Common/MainError/MainError";
import {
@@ -55,6 +54,7 @@ import {
setSnackBarMessage,
} from "../../systemSlice";
import { selFeatures, selSession } from "./consoleSlice";
import MenuWrapper from "./Menu/MenuWrapper";
const Trace = React.lazy(() => import("./Trace/Trace"));
const Heal = React.lazy(() => import("./Heal/Heal"));
@@ -481,7 +481,7 @@ const Console = ({ classes }: IConsoleProps) => {
<Fragment>
{session && session.status === "ok" ? (
<MainContainer
menu={!hideMenu ? <Menu /> : <Fragment />}
menu={!hideMenu ? <MenuWrapper /> : <Fragment />}
mobileModeAuto={false}
>
<Fragment>

View File

@@ -1,183 +0,0 @@
// This file is part of MinIO Console Server
// Copyright (c) 2022 MinIO, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import React, { Fragment, useEffect, useState } from "react";
import { Box } from "@mui/material";
import { useLocation } from "react-router-dom";
import ListItem from "@mui/material/ListItem";
import ListItemIcon from "@mui/material/ListItemIcon";
import { LogoutIcon } from "mds";
import ListItemText from "@mui/material/ListItemText";
import List from "@mui/material/List";
import {
LogoutItemIconStyle,
menuItemContainerStyles,
menuItemMiniStyles,
menuItemTextStyles,
} from "./MenuStyleUtils";
import MenuItem from "./MenuItem";
import { IAM_PAGES } from "../../../common/SecureComponent/permissions";
import MenuSectionHeader from "./MenuSectionHeader";
const ConsoleMenuList = ({
menuItems,
isOpen,
displayHeaders = false,
}: {
menuItems: any[];
isOpen: boolean;
displayHeaders?: boolean;
}) => {
const stateClsName = isOpen ? "wide" : "mini";
const { pathname = "" } = useLocation();
let groupToSelect = pathname.slice(1, pathname.length); //single path
if (groupToSelect.indexOf("/") !== -1) {
groupToSelect = groupToSelect.slice(0, groupToSelect.indexOf("/")); //nested path
}
const [expandGroup, setExpandGroup] = useState(IAM_PAGES.BUCKETS);
const [selectedMenuItem, setSelectedMenuItem] =
useState<string>(groupToSelect);
const [previewMenuGroup, setPreviewMenuGroup] = useState<string>("");
useEffect(() => {
setExpandGroup(groupToSelect);
setSelectedMenuItem(groupToSelect);
}, [groupToSelect]);
let basename = document.baseURI.replace(window.location.origin, "");
let header = "";
return (
<Box
className={`${stateClsName} wrapper`}
sx={{
display: "flex",
flexFlow: "column",
justifyContent: "space-between",
height: "100%",
flex: 1,
paddingRight: "8px",
"&.wide": {
marginLeft: "30px",
},
"&.mini": {
marginLeft: "10px",
"& .menuHeader": {
display: "none",
},
},
}}
>
<List
sx={{
flex: 1,
paddingTop: 0,
"&.mini": {
padding: 0,
display: "flex",
alignItems: "center",
flexFlow: "column",
"& .main-menu-item": {
marginBottom: "20px",
},
},
}}
className={`${stateClsName} group-wrapper main-list`}
>
<React.Fragment>
{(menuItems || []).map((menuGroup: any, index) => {
if (menuGroup) {
let grHeader = null;
if (menuGroup.group !== header && displayHeaders) {
grHeader = <MenuSectionHeader label={menuGroup.group} />;
header = menuGroup.group;
}
return (
<Fragment key={`${menuGroup.id}-${index.toString()}`}>
{grHeader}
<MenuItem
stateClsName={stateClsName}
page={menuGroup}
id={menuGroup.id}
selectedMenuItem={selectedMenuItem}
setSelectedMenuItem={setSelectedMenuItem}
pathValue={pathname}
onExpand={setExpandGroup}
expandedGroup={expandGroup}
previewMenuGroup={previewMenuGroup}
setPreviewMenuGroup={setPreviewMenuGroup}
/>
</Fragment>
);
}
return null;
})}
</React.Fragment>
</List>
{/* List of Bottom anchored menus */}
<List
sx={{
paddingTop: 0,
"&.mini": {
padding: 0,
display: "flex",
alignItems: "center",
justifyContent: "center",
flexFlow: "column",
},
}}
className={`${stateClsName} group-wrapper bottom-list`}
>
<ListItem
button
component="a"
href={`${window.location.origin}${basename}logout`}
disableRipple
sx={{
...menuItemContainerStyles,
...menuItemMiniStyles,
marginBottom: "3px",
}}
className={`$ ${stateClsName} bottom-menu-item`}
>
<ListItemIcon
sx={{
...LogoutItemIconStyle,
}}
>
<LogoutIcon />
</ListItemIcon>
<ListItemText
primary="Sign Out"
id={"logout"}
sx={{ ...menuItemTextStyles }}
className={stateClsName}
/>
</ListItem>
</List>
</Box>
);
};
export default ConsoleMenuList;

View File

@@ -1,65 +0,0 @@
// This file is part of MinIO Console Server
// Copyright (c) 2022 MinIO, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import React from "react";
import { useSelector } from "react-redux";
import { AppState } from "../../../store";
import { Box } from "@mui/material";
import { CircleIcon } from "mds";
import { getLicenseConsent } from "../License/utils";
import { registeredCluster } from "../../../config";
const LicenseBadge = () => {
const licenseInfo = useSelector(
(state: AppState) => state?.system?.licenseInfo
);
const isAgplAckDone = getLicenseConsent();
const clusterRegistered = registeredCluster();
const { plan = "" } = licenseInfo || {};
if (plan || isAgplAckDone || clusterRegistered) {
return null;
}
return (
<Box
sx={{
position: "absolute",
top: 1,
transform: "translateX(5px)",
zIndex: 400,
border: 0,
}}
style={{
border: 0,
}}
>
<CircleIcon
style={{
fill: "#FF3958",
border: "1px solid #FF3958",
borderRadius: "100%",
width: 8,
height: 8,
}}
/>
</Box>
);
};
export default LicenseBadge;

View File

@@ -1,126 +0,0 @@
// This file is part of MinIO Console Server
// Copyright (c) 2022 MinIO, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import React from "react";
import { useSelector } from "react-redux";
import { Drawer } from "@mui/material";
import withStyles from "@mui/styles/withStyles";
import { Theme } from "@mui/material/styles";
import createStyles from "@mui/styles/createStyles";
import clsx from "clsx";
import { AppState, useAppDispatch } from "../../../store";
import MenuToggle from "./MenuToggle";
import ConsoleMenuList from "./ConsoleMenuList";
import { validRoutes } from "../valid-routes";
import { menuOpen } from "../../../systemSlice";
import { selFeatures } from "../consoleSlice";
const drawerWidth = 250;
const styles = (theme: Theme) =>
createStyles({
drawer: {
width: drawerWidth,
flexShrink: 0,
whiteSpace: "nowrap",
background:
"transparent linear-gradient(90deg, #073052 0%, #081C42 100%) 0% 0% no-repeat padding-box !important",
boxShadow: "0px 3px 7px #00000014",
"& .MuiPaper-root": {
backgroundColor: "inherit",
},
"& ::-webkit-scrollbar": {
width: "5px",
},
"& ::-webkit-scrollbar-track": {
background: "#F0F0F0",
borderRadius: 0,
boxShadow: "inset 0px 0px 0px 0px #F0F0F0",
},
"& ::-webkit-scrollbar-thumb": {
background: "#5A6375",
borderRadius: 0,
},
"& ::-webkit-scrollbar-thumb:hover": {
background: "#081C42",
},
},
drawerOpen: {
width: drawerWidth,
transition: theme.transitions.create("width", {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.enteringScreen,
}),
},
drawerClose: {
transition: theme.transitions.create("width", {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.leavingScreen,
}),
overflowX: "hidden",
[theme.breakpoints.up("xs")]: {
width: 75,
},
},
});
interface IMenuProps {
classes?: any;
}
const Menu = ({ classes }: IMenuProps) => {
const dispatch = useAppDispatch();
const features = useSelector(selFeatures);
const sidebarOpen = useSelector(
(state: AppState) => state.system.sidebarOpen
);
const allowedMenuItems = validRoutes(features);
return (
<Drawer
id="app-menu"
variant="permanent"
className={clsx(classes.drawer, {
[classes.drawerOpen]: sidebarOpen,
[classes.drawerClose]: !sidebarOpen,
})}
classes={{
paper: clsx({
[classes.drawerOpen]: sidebarOpen,
[classes.drawerClose]: !sidebarOpen,
}),
}}
>
<MenuToggle
onToggle={(nextState) => {
dispatch(menuOpen(nextState));
}}
isOpen={sidebarOpen}
/>
<ConsoleMenuList
menuItems={allowedMenuItems}
isOpen={sidebarOpen}
displayHeaders
/>
</Drawer>
);
};
export default withStyles(styles)(Menu);

View File

@@ -0,0 +1,74 @@
// This file is part of MinIO Console Server
// Copyright (c) 2023 MinIO, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import React from "react";
import { useSelector } from "react-redux";
import { Menu } from "mds";
import { AppState, useAppDispatch } from "../../../store";
import { validRoutes } from "../valid-routes";
import { menuOpen } from "../../../systemSlice";
import { selFeatures } from "../consoleSlice";
import { getLogoVar, registeredCluster } from "../../../config";
import { useLocation, useNavigate } from "react-router-dom";
import { getLicenseConsent } from "../License/utils";
const MenuWrapper = () => {
const dispatch = useAppDispatch();
const features = useSelector(selFeatures);
const navigate = useNavigate();
const { pathname = "" } = useLocation();
const sidebarOpen = useSelector(
(state: AppState) => state.system.sidebarOpen
);
const licenseInfo = useSelector(
(state: AppState) => state?.system?.licenseInfo
);
const isAgplAckDone = getLicenseConsent();
const clusterRegistered = registeredCluster();
const { plan = "" } = licenseInfo || {};
let licenseNotification = true;
if (plan || isAgplAckDone || clusterRegistered) {
licenseNotification = false;
}
const allowedMenuItems = validRoutes(features, licenseNotification);
return (
<Menu
isOpen={sidebarOpen}
displayGroupTitles
options={allowedMenuItems}
applicationLogo={{ applicationName: "console", subVariant: getLogoVar() }}
callPathAction={(path) => {
navigate(path);
}}
signOutAction={() => {
navigate("/logout");
}}
collapseAction={() => {
dispatch(menuOpen(!sidebarOpen));
}}
currentPath={pathname}
mobileModeAuto={false}
/>
);
};
export default MenuWrapper;

View File

@@ -14,21 +14,13 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
export interface IMenuItem {
group?: string;
type?: string;
component?: any;
to?: string;
name: string;
id?: string;
icon: any;
onClick?: any;
import { MenuItemProps } from "mds";
export interface IMenuItem extends MenuItemProps {
forceDisplay?: boolean;
extraMargin?: boolean;
fsHidden?: boolean;
customPermissionFnc?: any;
customPermissionFnc?: () => boolean;
children?: IMenuItem[];
badge?: any;
}
export interface IRouteRule {

View File

@@ -34,8 +34,8 @@ export const routesAsKbarActions = (
id: `${childI.id}`,
name: childI.name,
section: i.name,
perform: () => navigate(`${childI.to}`),
icon: <childI.icon />,
perform: () => navigate(`${childI.path}`),
icon: childI.icon,
};
initialActions.push(a);
}
@@ -44,8 +44,8 @@ export const routesAsKbarActions = (
id: `${i.id}`,
name: i.name,
section: "Navigation",
perform: () => navigate(`${i.to}`),
icon: <i.icon />,
perform: () => navigate(`${i.path}`),
icon: i.icon,
};
initialActions.push(a);
}

View File

@@ -14,8 +14,8 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import React from "react";
import { IMenuItem } from "./Menu/types";
import { NavLink } from "react-router-dom";
import {
adminUserPermissions,
CONSOLE_UI_RESOURCE,
@@ -52,296 +52,272 @@ import {
WatchIcon,
} from "mds";
import { hasPermission } from "../../common/SecureComponent";
import React from "react";
import LicenseBadge from "./Menu/LicenseBadge";
import EncryptionIcon from "../../icons/SidebarMenus/EncryptionIcon";
import EncryptionStatusIcon from "../../icons/SidebarMenus/EncryptionStatusIcon";
import { LockOpen, Login } from "@mui/icons-material";
export const validRoutes = (features: string[] | null | undefined) => {
const permissionsValidation = (item: IMenuItem) => {
return (
((item.customPermissionFnc
? item.customPermissionFnc()
: hasPermission(
CONSOLE_UI_RESOURCE,
IAM_PAGES_PERMISSIONS[item.path ?? ""]
)) ||
item.forceDisplay) &&
!item.fsHidden
);
};
const validateItem = (item: IMenuItem) => {
// We clean up child items first
if (item.children && item.children.length > 0) {
const childArray: IMenuItem[] = item.children.reduce(
(acc: IMenuItem[], item) => {
if (!validateItem(item)) {
return [...acc];
}
return [...acc, item];
},
[]
);
const ret = { ...item, children: childArray };
return ret;
}
if (permissionsValidation(item)) {
return item;
}
return false;
};
export const validRoutes = (
features: string[] | null | undefined,
licenseNotification: boolean = false
) => {
const ldapIsEnabled = (features && features.includes("ldap-idp")) || false;
const kmsIsEnabled = (features && features.includes("kms")) || false;
let consoleMenus: IMenuItem[] = [
{
group: "User",
name: "Object Browser",
id: "object-browser",
component: NavLink,
to: IAM_PAGES.OBJECT_BROWSER_VIEW,
icon: ObjectBrowserIcon,
path: IAM_PAGES.OBJECT_BROWSER_VIEW,
icon: <ObjectBrowserIcon />,
forceDisplay: true,
children: [],
},
{
group: "User",
component: NavLink,
id: "nav-accesskeys",
to: IAM_PAGES.ACCOUNT,
path: IAM_PAGES.ACCOUNT,
name: "Access Keys",
icon: AccountsMenuIcon,
icon: <AccountsMenuIcon />,
forceDisplay: true,
},
{
group: "User",
type: "item",
component: NavLink,
to: IAM_PAGES.DOCUMENTATION,
path: "https://min.io/docs/minio/linux/index.html?ref=con",
name: "Documentation",
icon: DocumentationIcon,
icon: <DocumentationIcon />,
forceDisplay: true,
onClick: (
e:
| React.MouseEvent<HTMLLIElement>
| React.MouseEvent<HTMLAnchorElement>
| React.MouseEvent<HTMLDivElement>
) => {
e.preventDefault();
window.open(
"https://min.io/docs/minio/linux/index.html?ref=con",
"_blank",
"noopener"
);
},
},
{
group: "Administrator",
name: "Buckets",
id: "buckets",
component: NavLink,
to: IAM_PAGES.BUCKETS,
icon: BucketsMenuIcon,
path: IAM_PAGES.BUCKETS,
icon: <BucketsMenuIcon />,
forceDisplay: true,
children: [],
},
{
group: "Administrator",
name: "Policies",
component: NavLink,
id: "policies",
to: IAM_PAGES.POLICIES,
icon: AccessMenuIcon,
path: IAM_PAGES.POLICIES,
icon: <AccessMenuIcon />,
},
{
group: "Administrator",
name: "Identity",
id: "identity",
icon: IdentityMenuIcon,
icon: <IdentityMenuIcon />,
children: [
{
component: NavLink,
id: "users",
to: IAM_PAGES.USERS,
path: IAM_PAGES.USERS,
customPermissionFnc: () =>
hasPermission(CONSOLE_UI_RESOURCE, adminUserPermissions) ||
hasPermission(S3_ALL_RESOURCES, adminUserPermissions) ||
hasPermission(CONSOLE_UI_RESOURCE, [IAM_SCOPES.ADMIN_ALL_ACTIONS]),
name: "Users",
icon: UsersMenuIcon,
icon: <UsersMenuIcon />,
fsHidden: ldapIsEnabled,
},
{
component: NavLink,
id: "groups",
to: IAM_PAGES.GROUPS,
path: IAM_PAGES.GROUPS,
name: "Groups",
icon: GroupsMenuIcon,
icon: <GroupsMenuIcon />,
fsHidden: ldapIsEnabled,
},
{
name: "OpenID",
component: NavLink,
id: "openID",
to: IAM_PAGES.IDP_OPENID_CONFIGURATIONS,
icon: LockOpen,
path: IAM_PAGES.IDP_OPENID_CONFIGURATIONS,
icon: <LockOpen />,
},
{
name: "LDAP",
component: NavLink,
id: "ldap",
to: IAM_PAGES.IDP_LDAP_CONFIGURATIONS,
icon: Login,
path: IAM_PAGES.IDP_LDAP_CONFIGURATIONS,
icon: <Login />,
},
],
},
{
group: "Administrator",
name: "Monitoring",
id: "tools",
icon: MonitoringMenuIcon,
icon: <MonitoringMenuIcon />,
children: [
{
name: "Metrics",
id: "monitorMetrics",
to: IAM_PAGES.DASHBOARD,
icon: MetricsMenuIcon,
component: NavLink,
path: IAM_PAGES.DASHBOARD,
icon: <MetricsMenuIcon />,
},
{
name: "Logs ",
id: "monitorLogs",
to: IAM_PAGES.TOOLS_LOGS,
icon: LogsMenuIcon,
component: NavLink,
path: IAM_PAGES.TOOLS_LOGS,
icon: <LogsMenuIcon />,
},
{
name: "Audit",
id: "monitorAudit",
to: IAM_PAGES.TOOLS_AUDITLOGS,
icon: AuditLogsMenuIcon,
component: NavLink,
path: IAM_PAGES.TOOLS_AUDITLOGS,
icon: <AuditLogsMenuIcon />,
},
{
name: "Trace",
id: "monitorTrace",
to: IAM_PAGES.TOOLS_TRACE,
icon: TraceMenuIcon,
component: NavLink,
path: IAM_PAGES.TOOLS_TRACE,
icon: <TraceMenuIcon />,
},
{
name: "Watch",
id: "watch",
component: NavLink,
icon: WatchIcon,
to: IAM_PAGES.TOOLS_WATCH,
id: "monitorWatch",
icon: <WatchIcon />,
path: IAM_PAGES.TOOLS_WATCH,
},
{
name: "Drives",
id: "monitorDrives",
to: IAM_PAGES.TOOLS_HEAL,
icon: DrivesMenuIcon,
component: NavLink,
path: IAM_PAGES.TOOLS_HEAL,
icon: <DrivesMenuIcon />,
},
{
name: "Encryption",
id: "monitorEncryption",
to: IAM_PAGES.KMS_STATUS,
icon: EncryptionStatusIcon,
component: NavLink,
path: IAM_PAGES.KMS_STATUS,
icon: <EncryptionStatusIcon />,
fsHidden: !kmsIsEnabled,
},
],
},
{
group: "Administrator",
component: NavLink,
to: IAM_PAGES.EVENT_DESTINATIONS,
path: IAM_PAGES.EVENT_DESTINATIONS,
name: "Events",
icon: LambdaIcon,
icon: <LambdaIcon />,
id: "lambda",
},
{
group: "Administrator",
component: NavLink,
to: IAM_PAGES.TIERS,
path: IAM_PAGES.TIERS,
name: "Tiering",
icon: TiersIcon,
icon: <TiersIcon />,
id: "tiers",
},
{
group: "Administrator",
component: NavLink,
to: IAM_PAGES.SITE_REPLICATION,
path: IAM_PAGES.SITE_REPLICATION,
name: "Site Replication",
icon: RecoverIcon,
icon: <RecoverIcon />,
id: "sitereplication",
},
{
group: "Administrator",
component: NavLink,
to: IAM_PAGES.KMS_KEYS,
path: IAM_PAGES.KMS_KEYS,
name: "Encryption",
icon: EncryptionIcon,
icon: <EncryptionIcon />,
id: "encryption",
fsHidden: !kmsIsEnabled,
},
{
group: "Administrator",
component: NavLink,
to: IAM_PAGES.SETTINGS,
path: IAM_PAGES.SETTINGS,
name: "Settings",
id: "configurations",
icon: SettingsIcon,
icon: <SettingsIcon />,
},
{
group: "Subscription",
component: NavLink,
to: IAM_PAGES.LICENSE,
path: IAM_PAGES.LICENSE,
name: "License",
id: "license",
icon: LicenseIcon,
badge: LicenseBadge,
icon: <LicenseIcon />,
badge: licenseNotification,
forceDisplay: true,
},
{
group: "Subscription",
name: "Health",
id: "diagnostics",
component: NavLink,
icon: HealthMenuIcon,
to: IAM_PAGES.TOOLS_DIAGNOSTICS,
icon: <HealthMenuIcon />,
path: IAM_PAGES.TOOLS_DIAGNOSTICS,
},
{
group: "Subscription",
name: "Performance",
id: "performance",
component: NavLink,
icon: PerformanceMenuIcon,
to: IAM_PAGES.TOOLS_SPEEDTEST,
icon: <PerformanceMenuIcon />,
path: IAM_PAGES.TOOLS_SPEEDTEST,
},
{
group: "Subscription",
name: "Profile",
id: "profile",
component: NavLink,
icon: ProfileMenuIcon,
to: IAM_PAGES.PROFILE,
icon: <ProfileMenuIcon />,
path: IAM_PAGES.PROFILE,
},
{
group: "Subscription",
name: "Inspect",
id: "inspectObjects",
to: IAM_PAGES.SUPPORT_INSPECT,
icon: InspectMenuIcon,
component: NavLink,
path: IAM_PAGES.SUPPORT_INSPECT,
icon: <InspectMenuIcon />,
},
{
group: "Subscription",
name: "Call Home",
id: "callhome",
component: NavLink,
icon: CallHomeMenuIcon,
to: IAM_PAGES.CALL_HOME,
icon: <CallHomeMenuIcon />,
path: IAM_PAGES.CALL_HOME,
},
];
const allowedItems = consoleMenus.filter((item: IMenuItem) => {
if (item.children && item.children.length > 0) {
const c = item.children?.filter((childItem: IMenuItem) => {
return (
((childItem.customPermissionFnc
? childItem.customPermissionFnc()
: hasPermission(
CONSOLE_UI_RESOURCE,
IAM_PAGES_PERMISSIONS[childItem.to ?? ""]
)) ||
childItem.forceDisplay) &&
!childItem.fsHidden
);
});
return c.length > 0;
return consoleMenus.reduce((acc: IMenuItem[], item) => {
const validation = validateItem(item);
if (!validation) {
return [...acc];
}
const res =
((item.customPermissionFnc
? item.customPermissionFnc()
: hasPermission(
CONSOLE_UI_RESOURCE,
IAM_PAGES_PERMISSIONS[item.to ?? ""]
)) ||
item.forceDisplay) &&
!item.fsHidden;
return res;
});
return allowedItems;
return [...acc, validation];
}, []);
};

View File

@@ -16,6 +16,7 @@
import { Role, Selector } from "testcafe";
import { readFileSync } from "fs";
import { getMenuElement } from "../utils/elements-menu";
const data = readFileSync(__dirname + "/../constants/timestamp.txt", "utf-8");
const $TIMESTAMP = data.trim();
@@ -39,14 +40,7 @@ const bucketsScreenUrl = `${testDomainUrl}/buckets`;
const loginSubmitBtn = Selector("button").withAttribute("id", "do-login");
export const bucketsSidebarEl = Selector(".MuiPaper-root")
.find("ul")
.child("#buckets");
export const menuListchildren = Selector("#tools-children");
export const bucketsEl = menuListchildren
.find("a")
.withAttribute("href", "/buckets");
export const bucketsSidebarEl = getMenuElement("buckets");
export const inspectAllowedRole = Role(
loginUrl,

View File

@@ -17,12 +17,11 @@
import * as roles from "../utils/roles";
import { IAM_PAGES } from "../../src/common/SecureComponent/permissions";
import { Selector } from "testcafe";
import { getMenuElement } from "../utils/elements-menu";
let testDomainUrl = "http://localhost:9090";
const screenUrl = `${testDomainUrl}${IAM_PAGES.SITE_REPLICATION}`;
const siteReplicationEl = Selector(".MuiPaper-root")
.find("ul")
.child("#sitereplication");
const siteReplicationEl = getMenuElement("sitereplication");
export const addSitesBtn = Selector("button").withText("Add Sites");
/* Begin Local Testing config block */

View File

@@ -15,85 +15,70 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import { Selector } from "testcafe";
import { IAM_PAGES } from "../../src/common/SecureComponent/permissions";
//----------------------------------------------------
// Functions to get elements
//----------------------------------------------------
export const getMenuElement = (item) => {
return Selector("div.menuItems").find("button").withAttribute("id", item);
};
export const getSubmenuBlock = (item) => {
return getMenuElement(item).sibling("div.subItemsBox");
};
//----------------------------------------------------
// General sidebar element
//----------------------------------------------------
export const sidebarItem = Selector(".MuiPaper-root").find("ul").child("a");
export const logoutItem = Selector(".MuiPaper-root").find("ul").child("div");
export const logoutItem = getMenuElement("sign-out");
//----------------------------------------------------
// Specific sidebar elements
//----------------------------------------------------
export const monitoringElement = Selector(".MuiPaper-root")
.find("ul")
.child("#tools");
export const monitoringChildren = Selector("#tools-children");
export const monitoringElement = getMenuElement("tools");
export const monitoringChildren = getSubmenuBlock("tools");
export const dashboardElement = monitoringChildren
.find("a")
.withAttribute("href", IAM_PAGES.DASHBOARD);
.find("button")
.withAttribute("id", "monitorMetrics");
export const logsElement = monitoringChildren
.find("a")
.withAttribute("href", "/tools/logs");
.find("button")
.withAttribute("id", "monitorLogs");
export const traceElement = monitoringChildren
.find("a")
.withAttribute("href", "/tools/trace");
.find("button")
.withAttribute("id", "monitorTrace");
export const drivesElement = monitoringChildren
.find("a")
.withAttribute("href", "/tools/heal");
.find("button")
.withAttribute("id", "monitorDrives");
export const watchElement = monitoringChildren
.find("a")
.withAttribute("href", "/tools/watch");
.find("button")
.withAttribute("id", "monitorWatch");
export const bucketsElement = sidebarItem.withAttribute("href", "/buckets");
export const bucketsElement = getMenuElement("buckets");
export const serviceAcctsElement = sidebarItem.withAttribute(
"href",
IAM_PAGES.ACCOUNT
);
export const serviceAcctsElement = getMenuElement("nav-accesskeys");
export const identityElement = Selector(".MuiPaper-root")
.find("ul")
.child("#identity");
export const identityChildren = Selector("#identity-children");
export const identityElement = getMenuElement("identity");
export const identityChildren = getSubmenuBlock("identity");
export const usersElement = identityChildren
.find("a")
.withAttribute("href", IAM_PAGES.USERS);
.find("button")
.withAttribute("id", "users");
export const groupsElement = identityChildren
.find("a")
.withAttribute("href", IAM_PAGES.GROUPS);
.find("button")
.withAttribute("id", "groups");
export const iamPoliciesElement = sidebarItem.withAttribute(
"href",
IAM_PAGES.POLICIES
);
export const iamPoliciesElement = getMenuElement("policies");
export const configurationsElement = Selector(".MuiPaper-root")
.find("ul")
.child("#configurations");
export const configurationsElement = getMenuElement("configurations");
export const notificationEndpointsElement = Selector(".MuiPaper-root")
.find("ul")
.child("#lambda");
export const notificationEndpointsElement = getMenuElement("lambda");
export const tiersElement = Selector(".MuiPaper-root")
.find("ul")
.child("#tiers");
export const tiersElement = getMenuElement("tiers");
export const diagnosticsElement = Selector(".MuiPaper-root")
.find("ul")
.child("#diagnostics");
export const performanceElement = Selector(".MuiPaper-root")
.find("ul")
.child("#performance");
export const profileElement = Selector(".MuiPaper-root")
.find("ul")
.child("#profile");
export const inspectElement = sidebarItem.withAttribute(
"href",
"/support/inspect"
);
export const diagnosticsElement = getMenuElement("diagnostics");
export const performanceElement = getMenuElement("performance");
export const inspectElement = getMenuElement("inspectObjects");
export const licenseElement = sidebarItem.withAttribute("href", "/license");
export const licenseElement = getMenuElement("license");

View File

@@ -382,7 +382,6 @@
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz#7844f9289546efa9febac2de4cfe358a050bd703"
integrity sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==
"@babel/plugin-proposal-unicode-property-regex@^7.4.4":
version "7.18.6"
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz#af613d2cd5e643643b65cded64207b15c85cb78e"
@@ -4873,9 +4872,9 @@ destroy@1.2.0:
integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==
detect-gpu@^5.0.27:
version "5.0.28"
resolved "https://registry.yarnpkg.com/detect-gpu/-/detect-gpu-5.0.28.tgz#e7762c04cc3b5a33d902eb5719add195494df60a"
integrity sha512-sdT5Ti9ZHBBq39mK0DRwnm/5xZOVAz2+vxYLdPcFP83+3DGkzucEK0lzw1XFwct4zWDAXYrSTFUjC33qsoRAoQ==
version "5.0.27"
resolved "https://registry.yarnpkg.com/detect-gpu/-/detect-gpu-5.0.27.tgz#821d9331c87e32568c483d85e12a9adee43d7bb2"
integrity sha512-IDjjqTkS+f0xm/ntbD21IPYiF0srzpePC/hhUMmctEsoklZwJwStJiMi/KN0pnH0LjSsgjwbP+QwW7y+Qf4/SQ==
dependencies:
webgl-constants "^1.1.1"
@@ -5093,7 +5092,6 @@ electron-to-chromium@^1.4.411:
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.425.tgz#399df13091b836d28283a545c25c8e4d9da86da8"
integrity sha512-wv1NufHxu11zfDbY4fglYQApMswleE9FL/DSeyOyauVXDZ+Kco96JK/tPfBUaDqfRarYp2WH2hJ/5UnVywp9Jg==
elegant-spinner@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/elegant-spinner/-/elegant-spinner-1.0.1.tgz#db043521c95d7e303fd8f345bedc3349cfb0729e"
@@ -8294,7 +8292,6 @@ memfs@^3.1.2, memfs@^3.4.3:
version "3.5.3"
resolved "https://registry.yarnpkg.com/memfs/-/memfs-3.5.3.tgz#d9b40fe4f8d5788c5f895bda804cd0d9eeee9f3b"
integrity sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==
dependencies:
fs-monkey "^1.0.4"
@@ -12534,7 +12531,6 @@ webpack@^5.64.4:
version "5.86.0"
resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.86.0.tgz#b0eb81794b62aee0b7e7eb8c5073495217d9fc6d"
integrity sha512-3BOvworZ8SO/D4GVP+GoRC3fVeg5MO4vzmq8TJJEkdmopxyazGDxN8ClqN12uzrZW9Tv8EED8v5VSb6Sqyi0pg==
dependencies:
"@types/eslint-scope" "^3.7.3"
"@types/estree" "^1.0.0"