Add new tab and section for displaying describe PVC output (#2008)

This commit is contained in:
Javier Adriel
2022-05-23 21:43:29 -05:00
committed by GitHub
parent 17684f37d9
commit 85c0e5eca2
3 changed files with 294 additions and 2 deletions

View File

@@ -0,0 +1,202 @@
// 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, { useEffect, useState, Fragment } from "react";
import { connect } from "react-redux";
import { Theme } from "@mui/material/styles";
import createStyles from "@mui/styles/createStyles";
import withStyles from "@mui/styles/withStyles";
import {
actionsTray,
buttonsStyles,
hrClass,
searchField,
} from "../../../Common/FormComponents/common/styleLibrary";
import { Box } from "@mui/material";
import Grid from "@mui/material/Grid";
import Chip from "@mui/material/Chip";
import Tabs from "@mui/material/Tabs";
import Tab from "@mui/material/Tab";
import { useDispatch } from "react-redux";
import { setErrorSnackMessage } from "../../../../../systemSlice";
import { ErrorResponseHandler } from "../../../../../common/types";
import api from "../../../../../common/api";
import { AppState } from "../../../../../store";
import LabelValuePair from "../../../Common/UsageBarWrapper/LabelValuePair";
import {
IPVCDescribeProps,
DescribeResponse,
IPVCDescribeSummaryProps,
IPVCDescribeAnnotationsProps,
IPVCDescribeLabelsProps
} from "./pvcTypes";
const styles = (theme: Theme) =>
createStyles({
...actionsTray,
...buttonsStyles,
...searchField,
...hrClass,
actionsTray: {
...actionsTray.actionsTray,
padding: "15px 0 0",
},
});
const twoColCssGridLayoutConfig = {
display: "grid",
gridTemplateColumns: { xs: "1fr", sm: "2fr 1fr" },
gridAutoFlow: { xs: "dense", sm: "row" },
gap: 2,
padding: "15px",
};
const HeaderSection = ({ title }: { title: string }) => {
return (
<Box
sx={{
borderBottom: "1px solid #eaeaea",
margin: 0,
marginBottom: "20px",
}}
>
<h3>{title}</h3>
</Box>
);
};
const PVCDescribeSummary = ({describeInfo}: IPVCDescribeSummaryProps) => {
return (
<Fragment>
<HeaderSection title={"Summary"} />
<Box sx={{ ...twoColCssGridLayoutConfig }}>
<LabelValuePair label={"Name"} value={describeInfo.name} />
<LabelValuePair label={"Namespace"} value={describeInfo.namespace} />
<LabelValuePair label={"Capacity"} value={describeInfo.capacity} />
<LabelValuePair label={"Status"} value={describeInfo.status} />
<LabelValuePair label={"Storage Class"} value={describeInfo.storageClass} />
<LabelValuePair label={"Access Modes"} value={describeInfo.accessModes.join(", ")} />
<LabelValuePair label={"Finalizers"} value={describeInfo.finalizers.join(", ")} />
<LabelValuePair label={"Volume"} value={describeInfo.volume} />
<LabelValuePair label={"Volume Mode"} value={describeInfo.volumeMode} />
</Box>
</Fragment>
);
};
const PVCDescribeAnnotations = ({annotations}: IPVCDescribeAnnotationsProps) => {
return (
<Fragment>
<HeaderSection title={"Annotations"} />
<Box>
{annotations.map((annotation, index) => (
<Chip style={{ margin: "0.5%" }} label={`${annotation.key}: ${annotation.value}`} key={index} />
))}
</Box>
</Fragment>
);
};
const PVCDescribeLabels = ({labels}: IPVCDescribeLabelsProps) => {
return (
<Fragment>
<HeaderSection title={"Labels"} />
<Box>
{labels.map((label, index) => (
<Chip style={{ margin: "0.5%" }} label={`${label.key}: ${label.value}`} key={index} />
))}
</Box>
</Fragment>
);
};
const PVCDescribe = ({
tenant,
namespace,
pvcName,
propLoading,
}: IPVCDescribeProps) => {
const [describeInfo, setDescribeInfo] = useState<DescribeResponse>();
const [loading, setLoading] = useState<boolean>(true);
const [curTab, setCurTab] = useState<number>(0);
const dispatch = useDispatch();
useEffect(() => {
if (propLoading) {
setLoading(true);
}
}, [propLoading]);
useEffect(() => {
if (loading) {
api
.invoke(
"GET",
`/api/v1/namespaces/${namespace}/tenants/${tenant}/pvcs/${pvcName}/describe`
)
.then((res: DescribeResponse) => {
setDescribeInfo(res);
setLoading(false);
})
.catch((err: ErrorResponseHandler) => {
dispatch(setErrorSnackMessage(err));
setLoading(false);
});
}
}, [loading, pvcName, namespace, tenant, dispatch]);
const renderTabComponent = (index: number, info: DescribeResponse) => {
switch (index) {
case 0:
return <PVCDescribeSummary describeInfo={info} />
case 1:
return <PVCDescribeAnnotations annotations={info.annotations} />
case 2:
return <PVCDescribeLabels labels={info.labels} />
default:
break;
}
};
return (
<Fragment>
{describeInfo && (<Grid item xs={12}>
<Tabs
value={curTab}
onChange={(e: React.ChangeEvent<{}>, newValue: number) => {
setCurTab(newValue);
}}
indicatorColor="primary"
textColor="primary"
aria-label="cluster-tabs"
variant="scrollable"
scrollButtons="auto">
<Tab label="Summary" />
<Tab label="Annotations" />
<Tab label="Labels" />
</Tabs>
{renderTabComponent(curTab, describeInfo)}
</Grid>)}
</Fragment>
);
};
const mapState = (state: AppState) => ({
loadingTenant: state.tenants.tenantDetails.loadingTenant,
});
const connector = connect(mapState, {
setErrorSnackMessage,
});
export default withStyles(styles)(connector(PVCDescribe));

View File

@@ -20,6 +20,8 @@ import createStyles from "@mui/styles/createStyles";
import withStyles from "@mui/styles/withStyles";
import { containerForHeader } from "../../../Common/FormComponents/common/styleLibrary";
import Grid from "@mui/material/Grid";
import Tabs from "@mui/material/Tabs";
import Tab from "@mui/material/Tab";
import { Link } from "react-router-dom";
import api from "../../../../../common/api";
@@ -27,6 +29,7 @@ import { IEvent } from "../../ListTenants/types";
import { niceDays } from "../../../../../common/utils";
import { ErrorResponseHandler } from "../../../../../common/types";
import EventsList from "../events/EventsList";
import PVCDescribe from "./PVCDescribe";
import { useDispatch } from "react-redux";
import { setErrorSnackMessage } from "../../../../../systemSlice";
@@ -45,6 +48,7 @@ const styles = (theme: Theme) =>
});
const TenantVolumes = ({ classes, match }: IPVCDetailsProps) => {
const [curTab, setCurTab] = useState<number>(0);
const dispatch = useDispatch();
const [loading, setLoading] = useState<boolean>(true);
const tenantNamespace = match.params["tenantNamespace"];
@@ -89,8 +93,36 @@ const TenantVolumes = ({ classes, match }: IPVCDetailsProps) => {
</h1>
</Grid>
<Grid container>
<h1 className={classes.sectionTitle}>Events</h1>
<EventsList events={events} loading={loading} />
<Grid item xs={12}>
<Tabs
value={curTab}
onChange={(e: React.ChangeEvent<{}>, newValue: number) => {
setCurTab(newValue);
}}
indicatorColor="primary"
textColor="primary"
aria-label="cluster-tabs"
variant="scrollable"
scrollButtons="auto">
<Tab label="Events" id="simple-tab-0"/>
<Tab label="Describe" id="simple-tab-0"/>
</Tabs>
</Grid>
{curTab === 0 && (
<React.Fragment>
<h1 className={classes.sectionTitle}>Events</h1>
<EventsList events={events} loading={loading} />
</React.Fragment>
)}
{curTab === 1 && (
<PVCDescribe
tenant={tenantName}
namespace={tenantNamespace}
pvcName={PVCName}
propLoading={loading}
/>
)}
</Grid>
</Fragment>
);

View File

@@ -0,0 +1,58 @@
// 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/>.
export interface IPVCDescribeProps {
tenant: string;
namespace: string;
pvcName: string;
propLoading: boolean;
}
export interface Annotation {
key: string;
value: string;
}
export interface Label {
key: string;
value: string;
}
export interface DescribeResponse {
annotations: Annotation[];
labels: Label[];
name: string;
namespace: string;
status: string;
storageClass: string;
capacity: string;
accessModes: string[];
finalizers: string[];
volume: string;
volumeMode: string;
}
export interface IPVCDescribeSummaryProps {
describeInfo: DescribeResponse;
}
export interface IPVCDescribeAnnotationsProps {
annotations: Annotation[];
}
export interface IPVCDescribeLabelsProps {
labels: Label[];
}