Add feature hide-menu for embedded screens on Operator UI (#1604)
* Add feature hide-menu for embedded screens on Operator UI Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>
This commit is contained in:
@@ -129,8 +129,7 @@ export const IAM_PAGES = {
|
||||
TOOLS_LOGS: "/tools/logs",
|
||||
TOOLS_AUDITLOGS: "/tools/audit-logs",
|
||||
TOOLS_TRACE: "/tools/trace",
|
||||
METRICS: "/tools/metrics",
|
||||
DASHBOARD: "/tools/dashboard",
|
||||
DASHBOARD: "/tools/metrics",
|
||||
TOOLS_HEAL: "/tools/heal",
|
||||
TOOLS_WATCH: "/tools/watch",
|
||||
/* Health */
|
||||
@@ -178,6 +177,8 @@ export const IAM_PAGES = {
|
||||
"/namespaces/:tenantNamespace/tenants/:tenantName/summary",
|
||||
NAMESPACE_TENANT_METRICS:
|
||||
"/namespaces/:tenantNamespace/tenants/:tenantName/metrics",
|
||||
NAMESPACE_TENANT_TRACE:
|
||||
"/namespaces/:tenantNamespace/tenants/:tenantName/trace",
|
||||
NAMESPACE_TENANT_POOLS:
|
||||
"/namespaces/:tenantNamespace/tenants/:tenantName/pools",
|
||||
NAMESPACE_TENANT_VOLUMES:
|
||||
@@ -297,9 +298,6 @@ export const IAM_PAGES_PERMISSIONS = {
|
||||
[IAM_PAGES.DASHBOARD]: [
|
||||
IAM_SCOPES.ADMIN_SERVER_INFO, // displays dashboard information
|
||||
],
|
||||
[IAM_PAGES.METRICS]: [
|
||||
IAM_SCOPES.ADMIN_SERVER_INFO, // displays dashboard information
|
||||
],
|
||||
[IAM_PAGES.POLICIES_VIEW]: [
|
||||
IAM_SCOPES.ADMIN_DELETE_POLICY,
|
||||
IAM_SCOPES.ADMIN_LIST_GROUPS,
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
// 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 React, { Fragment } from "react";
|
||||
import { Theme } from "@mui/material/styles";
|
||||
import { connect } from "react-redux";
|
||||
import Grid from "@mui/material/Grid";
|
||||
@@ -38,6 +38,7 @@ interface IPageHeader {
|
||||
managerObjects?: IFileItem[];
|
||||
toggleList: typeof toggleList;
|
||||
middleComponent?: React.ReactNode;
|
||||
features: string[];
|
||||
}
|
||||
|
||||
const styles = (theme: Theme) =>
|
||||
@@ -88,7 +89,11 @@ const PageHeader = ({
|
||||
managerObjects,
|
||||
toggleList,
|
||||
middleComponent,
|
||||
features,
|
||||
}: IPageHeader) => {
|
||||
if (features.includes("hide-menu")) {
|
||||
return <Fragment />;
|
||||
}
|
||||
return (
|
||||
<Grid
|
||||
container
|
||||
@@ -157,6 +162,7 @@ const mapState = (state: AppState) => ({
|
||||
sidebarOpen: state.system.sidebarOpen,
|
||||
operatorMode: state.system.operatorMode,
|
||||
managerObjects: state.objectBrowser.objectManager.objectsToManage,
|
||||
features: state.console.session.features,
|
||||
});
|
||||
|
||||
const mapDispatchToProps = {
|
||||
|
||||
@@ -56,7 +56,6 @@ const Heal = React.lazy(() => import("./Heal/Heal"));
|
||||
const Watch = React.lazy(() => import("./Watch/Watch"));
|
||||
const HealthInfo = React.lazy(() => import("./HealthInfo/HealthInfo"));
|
||||
const Storage = React.lazy(() => import("./Storage/Storage"));
|
||||
const Metrics = React.lazy(() => import("./Dashboard/Metrics"));
|
||||
const Hop = React.lazy(() => import("./Tenants/TenantDetails/hop/Hop"));
|
||||
|
||||
const AddTenant = React.lazy(() => import("./Tenants/AddTenant/AddTenant"));
|
||||
@@ -211,10 +210,6 @@ const Console = ({
|
||||
component: Dashboard,
|
||||
path: IAM_PAGES.DASHBOARD,
|
||||
},
|
||||
{
|
||||
component: Metrics,
|
||||
path: IAM_PAGES.METRICS,
|
||||
},
|
||||
{
|
||||
component: Buckets,
|
||||
path: IAM_PAGES.ADD_BUCKETS,
|
||||
@@ -433,6 +428,11 @@ const Console = ({
|
||||
path: IAM_PAGES.NAMESPACE_TENANT_METRICS,
|
||||
forceDisplay: true,
|
||||
},
|
||||
{
|
||||
component: TenantDetails,
|
||||
path: IAM_PAGES.NAMESPACE_TENANT_TRACE,
|
||||
forceDisplay: true,
|
||||
},
|
||||
{
|
||||
component: TenantDetails,
|
||||
path: IAM_PAGES.NAMESPACE_TENANT_PODS_LIST,
|
||||
@@ -513,7 +513,7 @@ const Console = ({
|
||||
const location = useLocation();
|
||||
|
||||
let hideMenu = false;
|
||||
if (location.pathname === IAM_PAGES.METRICS) {
|
||||
if (features?.includes("hide-menu")) {
|
||||
hideMenu = true;
|
||||
} else if (location.pathname.endsWith("/hop")) {
|
||||
hideMenu = true;
|
||||
|
||||
@@ -84,6 +84,10 @@ const ConsoleKBar = ({
|
||||
operatorMode: boolean;
|
||||
features: string[] | null;
|
||||
}) => {
|
||||
if (features?.includes("hide-menu")) {
|
||||
return <Console />;
|
||||
}
|
||||
|
||||
const allowedMenuItems = validRoutes(features, operatorMode);
|
||||
|
||||
const initialActions = [];
|
||||
|
||||
@@ -1,91 +0,0 @@
|
||||
// This file is part of MinIO Console Server
|
||||
// Copyright (c) 2021 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, useCallback, useEffect, useState } from "react";
|
||||
import { connect } from "react-redux";
|
||||
import get from "lodash/get";
|
||||
import Grid from "@mui/material/Grid";
|
||||
import { Theme } from "@mui/material/styles";
|
||||
import createStyles from "@mui/styles/createStyles";
|
||||
import withStyles from "@mui/styles/withStyles";
|
||||
import { LinearProgress } from "@mui/material";
|
||||
import api from "../../../common/api";
|
||||
import { Usage } from "./types";
|
||||
import { setErrorSnackMessage } from "../../../actions";
|
||||
import { ErrorResponseHandler } from "../../../common/types";
|
||||
import PrDashboard from "./Prometheus/PrDashboard";
|
||||
import BasicDashboard from "./BasicDashboard/BasicDashboard";
|
||||
|
||||
interface IMetricsSimple {
|
||||
classes: any;
|
||||
displayErrorMessage: typeof setErrorSnackMessage;
|
||||
}
|
||||
|
||||
const styles = (theme: Theme) => createStyles({});
|
||||
|
||||
const Metrics = ({ classes, displayErrorMessage }: IMetricsSimple) => {
|
||||
const [loading, setLoading] = useState<boolean>(true);
|
||||
const [basicResult, setBasicResult] = useState<Usage | null>(null);
|
||||
|
||||
const fetchUsage = useCallback(() => {
|
||||
api
|
||||
.invoke("GET", `/api/v1/admin/info`)
|
||||
.then((res: Usage) => {
|
||||
setBasicResult(res);
|
||||
setLoading(false);
|
||||
})
|
||||
.catch((err: ErrorResponseHandler) => {
|
||||
displayErrorMessage(err);
|
||||
setLoading(false);
|
||||
});
|
||||
}, [setBasicResult, setLoading, displayErrorMessage]);
|
||||
|
||||
useEffect(() => {
|
||||
if (loading) {
|
||||
fetchUsage();
|
||||
}
|
||||
}, [loading, fetchUsage]);
|
||||
|
||||
const widgets = get(basicResult, "widgets", null);
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<Grid container>
|
||||
{loading ? (
|
||||
<Grid item xs={12}>
|
||||
<LinearProgress />
|
||||
</Grid>
|
||||
) : (
|
||||
<Fragment>
|
||||
{widgets !== null ? (
|
||||
<Grid container>
|
||||
<PrDashboard />
|
||||
</Grid>
|
||||
) : (
|
||||
<BasicDashboard usage={basicResult} />
|
||||
)}
|
||||
</Fragment>
|
||||
)}
|
||||
</Grid>
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
const connector = connect(null, {
|
||||
displayErrorMessage: setErrorSnackMessage,
|
||||
});
|
||||
|
||||
export default withStyles(styles)(connector(Metrics));
|
||||
@@ -50,7 +50,6 @@ import BackLink from "../../../../common/BackLink";
|
||||
import VerticalTabs from "../../Common/VerticalTabs/VerticalTabs";
|
||||
import BoxIconButton from "../../Common/BoxIconButton/BoxIconButton";
|
||||
import withSuspense from "../../Common/Components/withSuspense";
|
||||
import PVCDetails from "./pvcs/PVCDetails";
|
||||
|
||||
const TenantYAML = withSuspense(React.lazy(() => import("./TenantYAML")));
|
||||
const TenantSummary = withSuspense(React.lazy(() => import("./TenantSummary")));
|
||||
@@ -63,6 +62,10 @@ const VolumesSummary = withSuspense(
|
||||
React.lazy(() => import("./VolumesSummary"))
|
||||
);
|
||||
const TenantMetrics = withSuspense(React.lazy(() => import("./TenantMetrics")));
|
||||
const TenantTrace = withSuspense(React.lazy(() => import("./TenantTrace")));
|
||||
const TenantVolumes = withSuspense(
|
||||
React.lazy(() => import("./pvcs/TenantVolumes"))
|
||||
);
|
||||
const TenantSecurity = withSuspense(
|
||||
React.lazy(() => import("./TenantSecurity"))
|
||||
);
|
||||
@@ -424,6 +427,10 @@ const TenantDetails = ({
|
||||
path="/namespaces/:tenantNamespace/tenants/:tenantName/metrics"
|
||||
component={TenantMetrics}
|
||||
/>
|
||||
<Route
|
||||
path="/namespaces/:tenantNamespace/tenants/:tenantName/trace"
|
||||
component={TenantTrace}
|
||||
/>
|
||||
<Route
|
||||
path="/namespaces/:tenantNamespace/tenants/:tenantName/security"
|
||||
component={TenantSecurity}
|
||||
@@ -442,7 +449,7 @@ const TenantDetails = ({
|
||||
/>
|
||||
<Route
|
||||
path="/namespaces/:tenantNamespace/tenants/:tenantName/pvcs/:PVCName"
|
||||
component={PVCDetails}
|
||||
component={TenantVolumes}
|
||||
/>
|
||||
<Route
|
||||
path="/namespaces/:tenantNamespace/tenants/:tenantName/volumes"
|
||||
|
||||
@@ -28,6 +28,7 @@ import { ITenant } from "../ListTenants/types";
|
||||
import { setErrorSnackMessage } from "../../../../actions";
|
||||
import { AppState } from "../../../../store";
|
||||
import { LinearProgress } from "@mui/material";
|
||||
import { IAM_PAGES } from "../../../../common/SecureComponent/permissions";
|
||||
|
||||
interface ITenantMetrics {
|
||||
classes: any;
|
||||
@@ -66,7 +67,7 @@ const TenantMetrics = ({ classes, match }: ITenantMetrics) => {
|
||||
<iframe
|
||||
className={classes.iframeStyle}
|
||||
title={"metrics"}
|
||||
src={`/api/proxy/${tenantNamespace}/${tenantName}/metrics?cp=y`}
|
||||
src={`/api/proxy/${tenantNamespace}/${tenantName}${IAM_PAGES.DASHBOARD}?cp=y`}
|
||||
onLoad={() => {
|
||||
setLoading(false);
|
||||
}}
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
// This file is part of MinIO Console Server
|
||||
// Copyright (c) 2021 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, { useState } from "react";
|
||||
import { connect } from "react-redux";
|
||||
import get from "lodash/get";
|
||||
import { Theme } from "@mui/material/styles";
|
||||
import createStyles from "@mui/styles/createStyles";
|
||||
import withStyles from "@mui/styles/withStyles";
|
||||
import {
|
||||
containerForHeader,
|
||||
tenantDetailsStyles,
|
||||
} from "../../Common/FormComponents/common/styleLibrary";
|
||||
import { ITenant } from "../ListTenants/types";
|
||||
import { setErrorSnackMessage } from "../../../../actions";
|
||||
import { AppState } from "../../../../store";
|
||||
import { LinearProgress } from "@mui/material";
|
||||
import { IAM_PAGES } from "../../../../common/SecureComponent/permissions";
|
||||
|
||||
interface ITenantTrace {
|
||||
classes: any;
|
||||
match: any;
|
||||
tenant: ITenant | null;
|
||||
|
||||
setErrorSnackMessage: typeof setErrorSnackMessage;
|
||||
}
|
||||
|
||||
const styles = (theme: Theme) =>
|
||||
createStyles({
|
||||
...tenantDetailsStyles,
|
||||
iframeStyle: {
|
||||
border: "0px",
|
||||
flex: "1 1 auto",
|
||||
minHeight: "800px",
|
||||
width: "100%",
|
||||
},
|
||||
...containerForHeader(theme.spacing(4)),
|
||||
});
|
||||
|
||||
const TenantTrace = ({ classes, match }: ITenantTrace) => {
|
||||
const tenantName = match.params["tenantName"];
|
||||
const tenantNamespace = match.params["tenantNamespace"];
|
||||
|
||||
const [loading, setLoading] = useState<boolean>(true);
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<h1 className={classes.sectionTitle}>Metrics</h1>
|
||||
{loading && (
|
||||
<div style={{ marginTop: "80px" }}>
|
||||
<LinearProgress />
|
||||
</div>
|
||||
)}
|
||||
<iframe
|
||||
className={classes.iframeStyle}
|
||||
title={"metrics"}
|
||||
src={`/api/proxy/${tenantNamespace}/${tenantName}${IAM_PAGES.TOOLS_TRACE}?cp=y`}
|
||||
onLoad={() => {
|
||||
setLoading(false);
|
||||
}}
|
||||
/>
|
||||
</React.Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
const mapState = (state: AppState) => ({
|
||||
loadingTenant: state.tenants.tenantDetails.loadingTenant,
|
||||
selectedTenant: state.tenants.tenantDetails.currentTenant,
|
||||
tenant: state.tenants.tenantDetails.tenantInfo,
|
||||
logEnabled: get(state.tenants.tenantDetails.tenantInfo, "logEnabled", false),
|
||||
monitoringEnabled: get(
|
||||
state.tenants.tenantDetails.tenantInfo,
|
||||
"monitoringEnabled",
|
||||
false
|
||||
),
|
||||
encryptionEnabled: get(
|
||||
state.tenants.tenantDetails.tenantInfo,
|
||||
"encryptionEnabled",
|
||||
false
|
||||
),
|
||||
adEnabled: get(state.tenants.tenantDetails.tenantInfo, "idpAdEnabled", false),
|
||||
oidcEnabled: get(
|
||||
state.tenants.tenantDetails.tenantInfo,
|
||||
"idpOidcEnabled",
|
||||
false
|
||||
),
|
||||
});
|
||||
|
||||
const connector = connect(mapState, {
|
||||
setErrorSnackMessage,
|
||||
});
|
||||
|
||||
export default withStyles(styles)(connector(TenantTrace));
|
||||
@@ -43,7 +43,7 @@ const styles = (theme: Theme) =>
|
||||
...containerForHeader(theme.spacing(4)),
|
||||
});
|
||||
|
||||
const PVCDetails = ({
|
||||
const TenantVolumes = ({
|
||||
classes,
|
||||
match,
|
||||
setErrorSnackMessage,
|
||||
@@ -98,4 +98,4 @@ const PVCDetails = ({
|
||||
);
|
||||
};
|
||||
|
||||
export default withStyles(styles)(PVCDetails);
|
||||
export default withStyles(styles)(TenantVolumes);
|
||||
@@ -23,6 +23,6 @@ fixture("For user with default permissions").page("http://localhost:9090");
|
||||
test("Login to Operator Web Page", async (t) => {
|
||||
await t
|
||||
.navigateTo("http://localhost:9090/login")
|
||||
.typeText("#jwt","anyrandompasswordwillwork")
|
||||
.click("button.MuiButton-root")
|
||||
});
|
||||
.typeText("#jwt", "anyrandompasswordwillwork")
|
||||
.click("button.MuiButton-root");
|
||||
});
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
import * as constants from "./constants";
|
||||
import { Selector } from "testcafe";
|
||||
import { IAM_PAGES } from "../../src/common/SecureComponent/permissions";
|
||||
|
||||
//----------------------------------------------------
|
||||
// General sidebar element
|
||||
@@ -32,7 +33,7 @@ export const monitoringElement = Selector(".MuiPaper-root")
|
||||
export const monitoringChildren = Selector("#tools-children");
|
||||
export const dashboardElement = monitoringChildren
|
||||
.find("a")
|
||||
.withAttribute("href", "/tools/dashboard");
|
||||
.withAttribute("href", IAM_PAGES.DASHBOARD);
|
||||
export const logsElement = monitoringChildren
|
||||
.find("a")
|
||||
.withAttribute("href", "/tools/logs");
|
||||
|
||||
Reference in New Issue
Block a user