Tenant Details Thunk (#2072)
Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>
This commit is contained in:
@@ -26,6 +26,9 @@ import { niceBytes, niceBytesInt } from "../../../../common/utils";
|
||||
import InformationItem from "./InformationItem";
|
||||
import TenantCapacity from "./TenantCapacity";
|
||||
import { DrivesIcon } from "../../../../icons";
|
||||
import { setTenantName } from "../tenantsSlice";
|
||||
import { getTenantAsync } from "../thunks/tenantDetailsAsync";
|
||||
import { useDispatch } from "react-redux";
|
||||
|
||||
const styles = (theme: Theme) =>
|
||||
createStyles({
|
||||
@@ -104,6 +107,7 @@ interface ITenantListItem {
|
||||
}
|
||||
|
||||
const TenantListItem = ({ tenant, classes }: ITenantListItem) => {
|
||||
const dispatch = useDispatch();
|
||||
const healthStatusToClass = (health_status: string) => {
|
||||
switch (health_status) {
|
||||
case "red":
|
||||
@@ -174,6 +178,13 @@ const TenantListItem = ({ tenant, classes }: ITenantListItem) => {
|
||||
}
|
||||
|
||||
const openTenantDetails = () => {
|
||||
dispatch(
|
||||
setTenantName({
|
||||
name: tenant.name,
|
||||
namespace: tenant.namespace,
|
||||
})
|
||||
);
|
||||
dispatch(getTenantAsync());
|
||||
history.push(`/namespaces/${tenant.namespace}/tenants/${tenant.name}`);
|
||||
};
|
||||
|
||||
|
||||
@@ -22,16 +22,12 @@ import createStyles from "@mui/styles/createStyles";
|
||||
import withStyles from "@mui/styles/withStyles";
|
||||
import get from "lodash/get";
|
||||
import Grid from "@mui/material/Grid";
|
||||
|
||||
import { ITenant } from "../ListTenants/types";
|
||||
import {
|
||||
containerForHeader,
|
||||
pageContentStyles,
|
||||
tenantDetailsStyles,
|
||||
} from "../../Common/FormComponents/common/styleLibrary";
|
||||
import { AppState } from "../../../../store";
|
||||
import { ErrorResponseHandler } from "../../../../common/types";
|
||||
import api from "../../../../common/api";
|
||||
import PageHeader from "../../Common/PageHeader/PageHeader";
|
||||
import { CircleIcon, MinIOTierIconXs, TrashIcon } from "../../../../icons";
|
||||
import { niceBytes } from "../../../../common/utils";
|
||||
@@ -46,15 +42,10 @@ import BoxIconButton from "../../Common/BoxIconButton/BoxIconButton";
|
||||
import withSuspense from "../../Common/Components/withSuspense";
|
||||
import { IAM_PAGES } from "../../../../common/SecureComponent/permissions";
|
||||
import { tenantIsOnline } from "../ListTenants/utils";
|
||||
import {
|
||||
setErrorSnackMessage,
|
||||
setSnackBarMessage,
|
||||
} from "../../../../systemSlice";
|
||||
import {
|
||||
setTenantDetailsLoad,
|
||||
setTenantInfo,
|
||||
setTenantName,
|
||||
} from "../tenantsSlice";
|
||||
import { setSnackBarMessage } from "../../../../systemSlice";
|
||||
import { setTenantDetailsLoad, setTenantName } from "../tenantsSlice";
|
||||
import { getTenantAsync } from "../thunks/tenantDetailsAsync";
|
||||
import { LinearProgress } from "@mui/material";
|
||||
|
||||
const TenantYAML = withSuspense(React.lazy(() => import("./TenantYAML")));
|
||||
const TenantSummary = withSuspense(React.lazy(() => import("./TenantSummary")));
|
||||
@@ -188,23 +179,21 @@ const TenantDetails = ({ classes, match, history }: ITenantDetailsProps) => {
|
||||
const tenantNamespace = match.params["tenantNamespace"];
|
||||
const [deleteOpen, setDeleteOpen] = useState<boolean>(false);
|
||||
|
||||
// if the current tenant selected is not the one in the redux, reload it
|
||||
useEffect(() => {
|
||||
if (!loadingTenant) {
|
||||
if (
|
||||
tenantName !== selectedTenant ||
|
||||
tenantNamespace !== selectedNamespace
|
||||
) {
|
||||
dispatch(
|
||||
setTenantName({
|
||||
name: tenantName,
|
||||
namespace: tenantNamespace,
|
||||
})
|
||||
);
|
||||
dispatch(setTenantDetailsLoad(true));
|
||||
}
|
||||
if (
|
||||
selectedNamespace !== tenantNamespace ||
|
||||
selectedTenant !== tenantName
|
||||
) {
|
||||
dispatch(
|
||||
setTenantName({
|
||||
name: tenantName,
|
||||
namespace: tenantNamespace,
|
||||
})
|
||||
);
|
||||
dispatch(getTenantAsync());
|
||||
}
|
||||
}, [
|
||||
loadingTenant,
|
||||
selectedTenant,
|
||||
selectedNamespace,
|
||||
dispatch,
|
||||
@@ -212,48 +201,6 @@ const TenantDetails = ({ classes, match, history }: ITenantDetailsProps) => {
|
||||
tenantNamespace,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
if (loadingTenant) {
|
||||
api
|
||||
.invoke(
|
||||
"GET",
|
||||
`/api/v1/namespaces/${tenantNamespace}/tenants/${tenantName}`
|
||||
)
|
||||
.then((res: ITenant) => {
|
||||
// add computed fields
|
||||
const resPools = !res.pools ? [] : res.pools;
|
||||
|
||||
let totalInstances = 0;
|
||||
let totalVolumes = 0;
|
||||
let poolNamedIndex = 0;
|
||||
for (let pool of resPools) {
|
||||
const cap =
|
||||
pool.volumes_per_server *
|
||||
pool.servers *
|
||||
pool.volume_configuration.size;
|
||||
pool.label = `pool-${poolNamedIndex}`;
|
||||
if (pool.name === undefined || pool.name === "") {
|
||||
pool.name = pool.label;
|
||||
}
|
||||
pool.capacity = niceBytes(cap + "");
|
||||
pool.volumes = pool.servers * pool.volumes_per_server;
|
||||
totalInstances += pool.servers;
|
||||
totalVolumes += pool.volumes;
|
||||
poolNamedIndex += 1;
|
||||
}
|
||||
res.total_instances = totalInstances;
|
||||
res.total_volumes = totalVolumes;
|
||||
|
||||
dispatch(setTenantInfo(res));
|
||||
dispatch(setTenantDetailsLoad(false));
|
||||
})
|
||||
.catch((err: ErrorResponseHandler) => {
|
||||
dispatch(setErrorSnackMessage(err));
|
||||
dispatch(setTenantDetailsLoad(false));
|
||||
});
|
||||
}
|
||||
}, [loadingTenant, tenantNamespace, tenantName, dispatch]);
|
||||
|
||||
const path = get(match, "path", "/");
|
||||
const splitSections = path.split("/");
|
||||
|
||||
@@ -332,6 +279,11 @@ const TenantDetails = ({ classes, match, history }: ITenantDetailsProps) => {
|
||||
/>
|
||||
|
||||
<PageLayout className={classes.pageContainer}>
|
||||
{loadingTenant && (
|
||||
<Grid item xs={12}>
|
||||
<LinearProgress />
|
||||
</Grid>
|
||||
)}
|
||||
<Grid item xs={12}>
|
||||
<ScreenTitle
|
||||
icon={
|
||||
@@ -417,7 +369,7 @@ const TenantDetails = ({ classes, match, history }: ITenantDetailsProps) => {
|
||||
variant="outlined"
|
||||
aria-label="Refresh List"
|
||||
onClick={() => {
|
||||
dispatch(setTenantDetailsLoad(true));
|
||||
dispatch(getTenantAsync());
|
||||
}}
|
||||
>
|
||||
<span>Refresh</span> <RefreshIcon />
|
||||
|
||||
@@ -25,6 +25,7 @@ import get from "lodash/get";
|
||||
import { has } from "lodash";
|
||||
import { Opts } from "./ListTenants/utils";
|
||||
import { ITenant } from "./ListTenants/types";
|
||||
import { getTenantAsync } from "./thunks/tenantDetailsAsync";
|
||||
|
||||
export interface FileValue {
|
||||
fileName: string;
|
||||
@@ -247,6 +248,19 @@ export const tenantSlice = createSlice({
|
||||
state.tenantDetails.poolDetailsOpen = action.payload;
|
||||
},
|
||||
},
|
||||
extraReducers: (builder) => {
|
||||
builder
|
||||
.addCase(getTenantAsync.pending, (state) => {
|
||||
state.tenantDetails.loadingTenant = true;
|
||||
})
|
||||
.addCase(getTenantAsync.rejected, (state) => {
|
||||
state.tenantDetails.loadingTenant = false;
|
||||
})
|
||||
.addCase(getTenantAsync.fulfilled, (state, action) => {
|
||||
state.tenantDetails.loadingTenant = false;
|
||||
state.tenantDetails.tenantInfo = action.payload;
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
// Action creators are generated for each case reducer function
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
// 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 { createAsyncThunk } from "@reduxjs/toolkit";
|
||||
import { AppState } from "../../../../store";
|
||||
import { niceBytes } from "../../../../common/utils";
|
||||
import { ITenant } from "../ListTenants/types";
|
||||
import api from "../../../../common/api";
|
||||
import { ErrorResponseHandler } from "../../../../common/types";
|
||||
import { setErrorSnackMessage } from "../../../../systemSlice";
|
||||
|
||||
export const getTenantAsync = createAsyncThunk(
|
||||
"tenantDetails/getTenantAsync",
|
||||
async (_, { getState, rejectWithValue, dispatch }) => {
|
||||
const state = getState() as AppState;
|
||||
|
||||
const currentNamespace = state.tenants.tenantDetails.currentNamespace;
|
||||
const currentTenant = state.tenants.tenantDetails.currentTenant;
|
||||
|
||||
return api
|
||||
.invoke(
|
||||
"GET",
|
||||
`/api/v1/namespaces/${currentNamespace}/tenants/${currentTenant}`
|
||||
)
|
||||
.then((res: ITenant) => {
|
||||
// add computed fields
|
||||
const resPools = !res.pools ? [] : res.pools;
|
||||
|
||||
let totalInstances = 0;
|
||||
let totalVolumes = 0;
|
||||
let poolNamedIndex = 0;
|
||||
for (let pool of resPools) {
|
||||
const cap =
|
||||
pool.volumes_per_server *
|
||||
pool.servers *
|
||||
pool.volume_configuration.size;
|
||||
pool.label = `pool-${poolNamedIndex}`;
|
||||
if (pool.name === undefined || pool.name === "") {
|
||||
pool.name = pool.label;
|
||||
}
|
||||
pool.capacity = niceBytes(cap + "");
|
||||
pool.volumes = pool.servers * pool.volumes_per_server;
|
||||
totalInstances += pool.servers;
|
||||
totalVolumes += pool.volumes;
|
||||
poolNamedIndex += 1;
|
||||
}
|
||||
res.total_instances = totalInstances;
|
||||
res.total_volumes = totalVolumes;
|
||||
|
||||
return res;
|
||||
})
|
||||
.catch((err: ErrorResponseHandler) => {
|
||||
dispatch(setErrorSnackMessage(err));
|
||||
return rejectWithValue(err);
|
||||
});
|
||||
}
|
||||
);
|
||||
Reference in New Issue
Block a user