diff --git a/portal-ui/src/screens/Console/Tenants/TenantDetails/pvcs/PVCDescribe.tsx b/portal-ui/src/screens/Console/Tenants/TenantDetails/pvcs/PVCDescribe.tsx
new file mode 100644
index 000000000..945f5910a
--- /dev/null
+++ b/portal-ui/src/screens/Console/Tenants/TenantDetails/pvcs/PVCDescribe.tsx
@@ -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 .
+
+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 (
+
+ {title}
+
+ );
+};
+
+const PVCDescribeSummary = ({describeInfo}: IPVCDescribeSummaryProps) => {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
+
+const PVCDescribeAnnotations = ({annotations}: IPVCDescribeAnnotationsProps) => {
+ return (
+
+
+
+ {annotations.map((annotation, index) => (
+
+ ))}
+
+
+ );
+};
+
+const PVCDescribeLabels = ({labels}: IPVCDescribeLabelsProps) => {
+ return (
+
+
+
+ {labels.map((label, index) => (
+
+ ))}
+
+
+ );
+};
+
+const PVCDescribe = ({
+ tenant,
+ namespace,
+ pvcName,
+ propLoading,
+}: IPVCDescribeProps) => {
+ const [describeInfo, setDescribeInfo] = useState();
+ const [loading, setLoading] = useState(true);
+ const [curTab, setCurTab] = useState(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
+ case 1:
+ return
+ case 2:
+ return
+ default:
+ break;
+ }
+ };
+ return (
+
+ {describeInfo && (
+ , newValue: number) => {
+ setCurTab(newValue);
+ }}
+ indicatorColor="primary"
+ textColor="primary"
+ aria-label="cluster-tabs"
+ variant="scrollable"
+ scrollButtons="auto">
+
+
+
+
+ {renderTabComponent(curTab, describeInfo)}
+ )}
+
+ );
+};
+const mapState = (state: AppState) => ({
+ loadingTenant: state.tenants.tenantDetails.loadingTenant,
+});
+const connector = connect(mapState, {
+ setErrorSnackMessage,
+});
+
+export default withStyles(styles)(connector(PVCDescribe));
diff --git a/portal-ui/src/screens/Console/Tenants/TenantDetails/pvcs/TenantVolumes.tsx b/portal-ui/src/screens/Console/Tenants/TenantDetails/pvcs/TenantVolumes.tsx
index a0e43b0ea..e2443504c 100644
--- a/portal-ui/src/screens/Console/Tenants/TenantDetails/pvcs/TenantVolumes.tsx
+++ b/portal-ui/src/screens/Console/Tenants/TenantDetails/pvcs/TenantVolumes.tsx
@@ -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(0);
const dispatch = useDispatch();
const [loading, setLoading] = useState(true);
const tenantNamespace = match.params["tenantNamespace"];
@@ -89,8 +93,36 @@ const TenantVolumes = ({ classes, match }: IPVCDetailsProps) => {
- Events
-
+
+ , newValue: number) => {
+ setCurTab(newValue);
+ }}
+ indicatorColor="primary"
+ textColor="primary"
+ aria-label="cluster-tabs"
+ variant="scrollable"
+ scrollButtons="auto">
+
+
+
+
+
+ {curTab === 0 && (
+
+ Events
+
+
+ )}
+ {curTab === 1 && (
+
+ )}
);
diff --git a/portal-ui/src/screens/Console/Tenants/TenantDetails/pvcs/pvcTypes.ts b/portal-ui/src/screens/Console/Tenants/TenantDetails/pvcs/pvcTypes.ts
new file mode 100644
index 000000000..eb9cebeed
--- /dev/null
+++ b/portal-ui/src/screens/Console/Tenants/TenantDetails/pvcs/pvcTypes.ts
@@ -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 .
+
+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[];
+}
\ No newline at end of file