Skip to content

Commit c2dc739

Browse files
bexsoftBenjamin Perez
andauthored
Added URL navigation to tenant details (#795)
Added URL navigation to tenant details and fixed a couple of warnings Co-authored-by: Benjamin Perez <[email protected]>
1 parent bb0f613 commit c2dc739

File tree

17 files changed

+1268
-682
lines changed

17 files changed

+1268
-682
lines changed

pkg/acl/endpoints.go

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@ var (
4444
tenants = "/tenants"
4545
tenantsDetail = "/namespaces/:tenantNamespace/tenants/:tenantName"
4646
podsDetail = "/namespaces/:tenantNamespace/tenants/:tenantName/pods/:podName"
47+
tenantsDetailSummary = "/namespaces/:tenantNamespace/tenants/:tenantName/summary"
48+
tenantsDetailPods = "/namespaces/:tenantNamespace/tenants/:tenantName/pods"
49+
tenantsDetailPools = "/namespaces/:tenantNamespace/tenants/:tenantName/pools"
50+
tenantsDetailLicense = "/namespaces/:tenantNamespace/tenants/:tenantName/license"
4751
storage = "/storage"
4852
storageVolumes = "/storage/volumes"
4953
storageDrives = "/storage/drives"
@@ -318,13 +322,17 @@ var endpointRules = map[string]ConfigurationActionSet{
318322

319323
// operatorRules contains the mapping between endpoints and ActionSets for operator only mode
320324
var operatorRules = map[string]ConfigurationActionSet{
321-
tenants: tenantsActionSet,
322-
tenantsDetail: tenantsActionSet,
323-
podsDetail: tenantsActionSet,
324-
storage: storageActionSet,
325-
storageDrives: storageActionSet,
326-
storageVolumes: storageActionSet,
327-
license: licenseActionSet,
325+
tenants: tenantsActionSet,
326+
tenantsDetail: tenantsActionSet,
327+
tenantsDetailSummary: tenantsActionSet,
328+
tenantsDetailPods: tenantsActionSet,
329+
tenantsDetailPools: tenantsActionSet,
330+
tenantsDetailLicense: tenantsActionSet,
331+
podsDetail: tenantsActionSet,
332+
storage: storageActionSet,
333+
storageDrives: storageActionSet,
334+
storageVolumes: storageActionSet,
335+
license: licenseActionSet,
328336
}
329337

330338
// operatorOnly ENV variable

pkg/acl/endpoints_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ func TestOperatorOnlyEndpoints(t *testing.T) {
116116
"admin:*",
117117
},
118118
},
119-
want: 7,
119+
want: 11,
120120
},
121121
{
122122
name: "Operator Only - all s3 endpoints",
@@ -125,7 +125,7 @@ func TestOperatorOnlyEndpoints(t *testing.T) {
125125
"s3:*",
126126
},
127127
},
128-
want: 7,
128+
want: 11,
129129
},
130130
{
131131
name: "Operator Only - all admin and s3 endpoints",
@@ -135,14 +135,14 @@ func TestOperatorOnlyEndpoints(t *testing.T) {
135135
"s3:*",
136136
},
137137
},
138-
want: 7,
138+
want: 11,
139139
},
140140
{
141141
name: "Operator Only - default endpoints",
142142
args: args{
143143
[]string{},
144144
},
145-
want: 7,
145+
want: 11,
146146
},
147147
}
148148

portal-ui/src/screens/Console/Account/ChangeUserPasswordModal.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ import {
2929
import { ChangeUserPasswordRequest } from "../Buckets/types";
3030
import api from "../../../common/api";
3131
import { setModalErrorSnackMessage } from "../../../actions";
32-
import { User, UsersList } from "../Users/types";
32+
import { User } from "../Users/types";
3333

3434
const styles = (theme: Theme) =>
3535
createStyles({
@@ -143,7 +143,7 @@ const ChangeUserPassword = ({
143143
color="primary"
144144
disabled={
145145
loading ||
146-
!(reNewPassword.length > 0 && newPassword == reNewPassword)
146+
!(reNewPassword.length > 0 && newPassword === reNewPassword)
147147
}
148148
>
149149
Save

portal-ui/src/screens/Console/Common/FormComponents/common/styleLibrary.ts

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -593,3 +593,82 @@ export const hrClass = {
593593
backgroundColor: "transparent" as const,
594594
},
595595
};
596+
597+
export const tenantDetailsStyles = {
598+
buttonContainer: {
599+
textAlign: "right" as const,
600+
},
601+
multiContainer: {
602+
display: "flex" as const,
603+
alignItems: "center" as const,
604+
justifyContent: "flex-start" as const,
605+
},
606+
sizeFactorContainer: {
607+
marginLeft: 8,
608+
},
609+
containerHeader: {
610+
display: "flex" as const,
611+
justifyContent: "space-between" as const,
612+
},
613+
paperContainer: {
614+
padding: "15px 15px 15px 50px",
615+
},
616+
infoGrid: {
617+
display: "grid" as const,
618+
gridTemplateColumns: "auto auto auto auto",
619+
gridGap: 8,
620+
"& div": {
621+
display: "flex" as const,
622+
alignItems: "center" as const,
623+
},
624+
"& div:nth-child(odd)": {
625+
justifyContent: "flex-end" as const,
626+
fontWeight: 700,
627+
},
628+
"& div:nth-child(2n)": {
629+
paddingRight: 35,
630+
},
631+
},
632+
masterActions: {
633+
width: "25%",
634+
minWidth: "120px",
635+
"& div": {
636+
margin: "5px 0px",
637+
},
638+
},
639+
updateButton: {
640+
backgroundColor: "transparent" as const,
641+
border: 0,
642+
padding: "0 6px",
643+
cursor: "pointer" as const,
644+
"&:focus, &:active": {
645+
outline: "none",
646+
},
647+
"& svg": {
648+
height: 12,
649+
},
650+
},
651+
poolLabel: {
652+
color: "#666666",
653+
},
654+
titleCol: {
655+
fontWeight: 700,
656+
},
657+
breadcrumLink: {
658+
textDecoration: "none",
659+
color: "black",
660+
},
661+
healthCol: {
662+
fontWeight: 700,
663+
paddingRight: "10px",
664+
},
665+
...modalBasic,
666+
...actionsTray,
667+
...buttonsStyles,
668+
...searchField,
669+
...hrClass,
670+
actionsTray: {
671+
...actionsTray.actionsTray,
672+
padding: "15px 0 0",
673+
},
674+
};

portal-ui/src/screens/Console/Console.tsx

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,22 @@ const Console = ({
358358
component: PodDetails,
359359
path: "/namespaces/:tenantNamespace/tenants/:tenantName/pods/:podName",
360360
},
361+
{
362+
component: TenantDetails,
363+
path: "/namespaces/:tenantNamespace/tenants/:tenantName/summary",
364+
},
365+
{
366+
component: TenantDetails,
367+
path: "/namespaces/:tenantNamespace/tenants/:tenantName/pods",
368+
},
369+
{
370+
component: TenantDetails,
371+
path: "/namespaces/:tenantNamespace/tenants/:tenantName/pools",
372+
},
373+
{
374+
component: TenantDetails,
375+
path: "/namespaces/:tenantNamespace/tenants/:tenantName/license",
376+
},
361377
{
362378
component: License,
363379
path: "/license",

portal-ui/src/screens/Console/License/LicenseModal.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ const LicenseModal = ({ classes, open, closeModal }: ILicenseModalProps) => {
6565
<Grid item className={classes.subnetLicenseKey} xs={12}>
6666
<p>
6767
Copyright &copy; 2007 Free Software Foundation, Inc. &lt;
68-
<a target="_blank" href="https://fsf.org/">
68+
<a target="_blank" href="https://fsf.org/" rel="noreferrer">
6969
https://fsf.org/
7070
</a>
7171
&gt;
@@ -904,7 +904,7 @@ const LicenseModal = ({ classes, open, closeModal }: ILicenseModalProps) => {
904904
school, if any, to sign a &quot;copyright disclaimer&quot; for the
905905
program, if necessary. For more information on this, and how to
906906
apply and follow the GNU AGPL, see &lt;
907-
<a target="_blank" href="https://www.gnu.org/licenses/">
907+
<a target="_blank" href="https://www.gnu.org/licenses/" rel="noreferrer">
908908
https://www.gnu.org/licenses/
909909
</a>
910910
&gt;.

portal-ui/src/screens/Console/Tenants/ListTenants/ListTenants.tsx

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -216,13 +216,16 @@ const ListTenants = ({
216216
};
217217

218218
const healthStatusToClass = (health_status: string) => {
219-
return health_status == "red"
220-
? classes.redState
221-
: health_status == "yellow"
222-
? classes.yellowState
223-
: health_status == "green"
224-
? classes.greenState
225-
: classes.greyState;
219+
switch(health_status) {
220+
case "red":
221+
return classes.redState;
222+
case "yellow":
223+
return classes.yellowState;
224+
case "green":
225+
return classes.greenState;
226+
default:
227+
return classes.greyState;
228+
}
226229
};
227230

228231
return (
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
// This file is part of MinIO Console Server
2+
// Copyright (c) 2021 MinIO, Inc.
3+
//
4+
// This program is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU Affero General Public License as published by
6+
// the Free Software Foundation, either version 3 of the License, or
7+
// (at your option) any later version.
8+
//
9+
// This program is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU Affero General Public License for more details.
13+
//
14+
// You should have received a copy of the GNU Affero General Public License
15+
// along with this program. If not, see <http://www.gnu.org/licenses/>.
16+
17+
import React, { Fragment, useEffect, useState } from "react";
18+
import { connect } from "react-redux";
19+
import { createStyles, Theme, withStyles } from "@material-ui/core/styles";
20+
import {
21+
containerForHeader,
22+
tenantDetailsStyles,
23+
} from "../../Common/FormComponents/common/styleLibrary";
24+
import { niceDays } from "../../../../common/utils";
25+
import { IPodListElement } from "../ListTenants/types";
26+
import { setErrorSnackMessage } from "../../../../actions";
27+
import api from "../../../../common/api";
28+
import TableWrapper from "../../Common/TableWrapper/TableWrapper";
29+
30+
interface IPodsSummary {
31+
match: any;
32+
history: any;
33+
}
34+
35+
const styles = (theme: Theme) =>
36+
createStyles({
37+
...tenantDetailsStyles,
38+
...containerForHeader(theme.spacing(4)),
39+
});
40+
41+
const PodsSummary = ({ match, history }: IPodsSummary) => {
42+
const [pods, setPods] = useState<IPodListElement[]>([]);
43+
const [loadingPods, setLoadingPods] = useState<boolean>(true);
44+
45+
const tenantName = match.params["tenantName"];
46+
const tenantNamespace = match.params["tenantNamespace"];
47+
48+
const podViewAction = (pod: IPodListElement) => {
49+
history.push(
50+
`/namespaces/${tenantNamespace}/tenants/${tenantName}/pods/${pod.name}`
51+
);
52+
return;
53+
};
54+
const podTableActions = [{ type: "view", onClick: podViewAction }];
55+
56+
useEffect(() => {
57+
if (loadingPods) {
58+
api
59+
.invoke(
60+
"GET",
61+
`/api/v1/namespaces/${tenantNamespace}/tenants/${tenantName}/pods`
62+
)
63+
.then((result: IPodListElement[]) => {
64+
for (let i = 0; i < result.length; i++) {
65+
let currentTime = new Date().getSeconds();
66+
result[i].time = niceDays(
67+
(currentTime - parseInt(result[i].timeCreated)).toString()
68+
);
69+
}
70+
setPods(result);
71+
setLoadingPods(false);
72+
})
73+
.catch((err) => {
74+
setErrorSnackMessage("Error loading pods");
75+
});
76+
}
77+
}, [loadingPods, tenantName, tenantNamespace]);
78+
79+
return (
80+
<Fragment>
81+
<br />
82+
<TableWrapper
83+
columns={[
84+
{ label: "Name", elementKey: "name" },
85+
{ label: "Status", elementKey: "status" },
86+
{ label: "Age", elementKey: "time" },
87+
{ label: "Pod IP", elementKey: "podIP" },
88+
{
89+
label: "Restarts",
90+
elementKey: "restarts",
91+
renderFunction: (input) => {
92+
return input != null ? input : 0;
93+
},
94+
},
95+
{ label: "Node", elementKey: "node" },
96+
]}
97+
isLoading={loadingPods}
98+
records={pods}
99+
itemActions={podTableActions}
100+
entityName="Servers"
101+
idField="name"
102+
/>
103+
</Fragment>
104+
);
105+
};
106+
107+
const connector = connect(null, {
108+
setErrorSnackMessage,
109+
});
110+
111+
export default withStyles(styles)(connector(PodsSummary));

0 commit comments

Comments
 (0)