Tenant events UI (#1590)

This commit is contained in:
adfost
2022-02-16 16:29:41 -08:00
committed by GitHub
parent 8d7cddc20a
commit 5dc8d1808c
4 changed files with 143 additions and 0 deletions

View File

@@ -190,6 +190,8 @@ export const IAM_PAGES = {
"/namespaces/:tenantNamespace/tenants/:tenantName/monitoring",
NAMESPACE_TENANT_LOGGING:
"/namespaces/:tenantNamespace/tenants/:tenantName/logging",
NAMESPACE_TENANT_EVENTS:
"/namespaces/:tenantNamespace/tenants/:tenantName/events",
};
// roles

View File

@@ -468,6 +468,11 @@ const Console = ({
path: IAM_PAGES.NAMESPACE_TENANT_LOGGING,
forceDisplay: true,
},
{
component: TenantDetails,
path: IAM_PAGES.NAMESPACE_TENANT_EVENTS,
forceDisplay: true,
},
{
component: License,
path: IAM_PAGES.LICENSE,

View File

@@ -58,6 +58,7 @@ const TenantLicense = withSuspense(React.lazy(() => import("./TenantLicense")));
const PoolsSummary = withSuspense(React.lazy(() => import("./PoolsSummary")));
const PodsSummary = withSuspense(React.lazy(() => import("./PodsSummary")));
const TenantLogging = withSuspense(React.lazy(() => import("./TenantLogging")));
const TenantEvents = withSuspense(React.lazy(() => import("./TenantEvents")));
const VolumesSummary = withSuspense(
React.lazy(() => import("./VolumesSummary"))
);
@@ -459,6 +460,10 @@ const TenantDetails = ({
path="/namespaces/:tenantNamespace/tenants/:tenantName/logging"
component={TenantLogging}
/>
<Route
path="/namespaces/:tenantNamespace/tenants/:tenantName/events"
component={TenantEvents}
/>
<Route
path="/namespaces/:tenantNamespace/tenants/:tenantName"
component={() => (
@@ -537,6 +542,14 @@ const TenantDetails = ({
to: getRoutePath("volumes"),
},
}}
{{
tabConfig: {
label: "Events",
value: "events",
component: Link,
to: getRoutePath("events"),
},
}}
{{
tabConfig: {
label: "License",

View File

@@ -0,0 +1,123 @@
// 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, { useEffect, useState } 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,
containerForHeader,
searchField, tableStyles,
} from "../../Common/FormComponents/common/styleLibrary";
import Grid from "@mui/material/Grid";
import { IEvent } from "../ListTenants/types";
import { setErrorSnackMessage } from "../../../../actions";
import { niceDays } from "../../../../common/utils";
import { ErrorResponseHandler } from "../../../../common/types";
import TableWrapper from "../../Common/TableWrapper/TableWrapper";
import api from "../../../../common/api";
import { AppState } from "../../../../store";
interface ITenantEventsProps {
classes: any;
match: any;
loadingTenant: boolean;
setErrorSnackMessage: typeof setErrorSnackMessage;
}
const styles = (theme: Theme) =>
createStyles({
tableWrapper: {
height: "450px",
},
...actionsTray,
...searchField,
...tableStyles,
...containerForHeader(theme.spacing(4)),
});
const TenantEvents = ({
classes,
match,
loadingTenant,
setErrorSnackMessage,
}: ITenantEventsProps) => {
const [event, setEvent] = useState<IEvent[]>([]);
const [loading, setLoading] = useState<boolean>(true);
const tenantName = match.params["tenantName"];
const tenantNamespace = match.params["tenantNamespace"];
useEffect(() => {
if (loadingTenant) {
setLoading(true);
}
}, [loadingTenant]);
useEffect(() => {
if (loading) {
api
.invoke(
"GET",
`/api/v1/namespaces/${tenantNamespace}/tenants/${tenantName}/events`
)
.then((res: IEvent[]) => {
for (let i = 0; i < res.length; i++) {
let currentTime = (Date.now() / 1000) | 0;
res[i].seen = niceDays((currentTime - res[i].last_seen).toString());
}
setEvent(res);
setLoading(false);
})
.catch((err: ErrorResponseHandler) => {
setErrorSnackMessage(err);
setLoading(false);
});
}
}, [loading, tenantNamespace, tenantName, setErrorSnackMessage]);
return (
<React.Fragment>
<h1 className={classes.sectionTitle}>Events</h1>
<Grid item xs={12} className={classes.actionsTray}>
<TableWrapper
itemActions={[]}
columns={[
{ label: "Namespace", elementKey: "namespace" },
{ label: "Last Seen", elementKey: "seen" },
{ label: "Message", elementKey: "message" },
{ label: "Event Type", elementKey: "event_type" },
{ label: "Reason", elementKey: "reason" },
]}
isLoading={loading}
records={event}
entityName="Events"
idField="event"
/>
</Grid>
</React.Fragment>
);
};
const mapState = (state: AppState) => ({
loadingTenant: state.tenants.tenantDetails.loadingTenant,
});
const connector = connect(mapState, {
setErrorSnackMessage,
});
export default withStyles(styles)(connector(TenantEvents));