Updated Entities results panel styles (#2753)
Signed-off-by: Benjamin Perez <benjamin@bexsoft.net>
This commit is contained in:
@@ -27,13 +27,15 @@ import {
|
||||
InputBox,
|
||||
Loader,
|
||||
RemoveIcon,
|
||||
SearchIcon,
|
||||
SectionTitle,
|
||||
UptimeIcon,
|
||||
TimeIcon,
|
||||
} from "mds";
|
||||
import PolicySelectors from "../../Policies/PolicySelectors";
|
||||
import { useSelector } from "react-redux";
|
||||
import { LDAPEntitiesResponse } from "./types";
|
||||
import { DateTime } from "luxon";
|
||||
import LDAPResultsBlock from "./LDAPResultsBlock";
|
||||
|
||||
const LDAPEntitiesQuery = () => {
|
||||
const dispatch = useAppDispatch();
|
||||
@@ -107,90 +109,128 @@ const LDAPEntitiesQuery = () => {
|
||||
};
|
||||
|
||||
return (
|
||||
<Box sx={{ marginTop: 15, paddingTop: 0 }} withBorders>
|
||||
<Box sx={{ marginTop: 15, paddingTop: 0 }}>
|
||||
<Grid container sx={{ marginTop: 5 }}>
|
||||
<Grid item sm={12} md={6} lg={5} sx={{ padding: 10, paddingTop: 0 }}>
|
||||
<SectionTitle separator>Query Filters</SectionTitle>
|
||||
<SectionTitle>Query Filters</SectionTitle>
|
||||
|
||||
<Box sx={{ padding: "0 10px" }}>
|
||||
<h4>Users</h4>
|
||||
<Box
|
||||
sx={{
|
||||
overflowY: "auto",
|
||||
minHeight: 220,
|
||||
maxHeight: 250,
|
||||
"& > div > div": {
|
||||
width: "100%",
|
||||
},
|
||||
}}
|
||||
>
|
||||
{users.map((userDat, index) => {
|
||||
return (
|
||||
<InputBox
|
||||
id={`search-user-${index}`}
|
||||
key={`search-user-${index}`}
|
||||
value={userDat}
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const usersElements = [...users];
|
||||
usersElements[index] = e.target.value;
|
||||
setUsers(usersElements);
|
||||
}}
|
||||
overlayIcon={
|
||||
users.length === index + 1 ? <AddIcon /> : <RemoveIcon />
|
||||
}
|
||||
overlayAction={() => {
|
||||
alterUsersList(users.length === index + 1, index);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
<Box
|
||||
sx={{
|
||||
padding: "0 10px",
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
gap: 40,
|
||||
}}
|
||||
>
|
||||
<Box sx={{ padding: "10px 26px" }} withBorders>
|
||||
<Box sx={{ display: "flex" }}>
|
||||
<h4 style={{ margin: 0, marginBottom: 10, fontSize: 14 }}>
|
||||
Users
|
||||
</h4>
|
||||
</Box>
|
||||
<Box
|
||||
sx={{
|
||||
overflowY: "auto",
|
||||
minHeight: 50,
|
||||
maxHeight: 250,
|
||||
"& > div > div": {
|
||||
width: "100%",
|
||||
},
|
||||
}}
|
||||
>
|
||||
{users.map((userDat, index) => {
|
||||
return (
|
||||
<InputBox
|
||||
id={`search-user-${index}`}
|
||||
key={`search-user-${index}`}
|
||||
value={userDat}
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const usersElements = [...users];
|
||||
usersElements[index] = e.target.value;
|
||||
setUsers(usersElements);
|
||||
}}
|
||||
overlayIcon={
|
||||
users.length === index + 1 ? (
|
||||
<AddIcon />
|
||||
) : (
|
||||
<RemoveIcon />
|
||||
)
|
||||
}
|
||||
overlayAction={() => {
|
||||
alterUsersList(users.length === index + 1, index);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
<h4>Groups</h4>
|
||||
<Box
|
||||
sx={{
|
||||
overflowY: "auto",
|
||||
minHeight: 220,
|
||||
maxHeight: 250,
|
||||
"& > div > div": {
|
||||
width: "100%",
|
||||
},
|
||||
}}
|
||||
>
|
||||
{groups.map((groupDat, index) => {
|
||||
return (
|
||||
<InputBox
|
||||
id={`search-group-${index}`}
|
||||
key={`search-group-${index}`}
|
||||
value={groupDat}
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const groupsElements = [...groups];
|
||||
groupsElements[index] = e.target.value;
|
||||
setGroups(groupsElements);
|
||||
}}
|
||||
overlayIcon={
|
||||
groups.length === index + 1 ? <AddIcon /> : <RemoveIcon />
|
||||
}
|
||||
overlayAction={() => {
|
||||
alterGroupsList(groups.length === index + 1, index);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
<Box sx={{ padding: "10px 26px" }} withBorders>
|
||||
<h4 style={{ margin: 0, marginBottom: 10, fontSize: 14 }}>
|
||||
Groups
|
||||
</h4>
|
||||
<Box
|
||||
sx={{
|
||||
overflowY: "auto",
|
||||
minHeight: 50,
|
||||
maxHeight: "calc(100vh - 340px)",
|
||||
"& > div > div": {
|
||||
width: "100%",
|
||||
},
|
||||
}}
|
||||
>
|
||||
{groups.map((groupDat, index) => {
|
||||
return (
|
||||
<InputBox
|
||||
id={`search-group-${index}`}
|
||||
key={`search-group-${index}`}
|
||||
value={groupDat}
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const groupsElements = [...groups];
|
||||
groupsElements[index] = e.target.value;
|
||||
setGroups(groupsElements);
|
||||
}}
|
||||
overlayIcon={
|
||||
groups.length === index + 1 ? (
|
||||
<AddIcon />
|
||||
) : (
|
||||
<RemoveIcon />
|
||||
)
|
||||
}
|
||||
overlayAction={() => {
|
||||
alterGroupsList(groups.length === index + 1, index);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
<h4>Policies</h4>
|
||||
<Box
|
||||
sx={{
|
||||
minHeight: 220,
|
||||
maxHeight: "calc(100vh - 740px)",
|
||||
}}
|
||||
>
|
||||
<PolicySelectors selectedPolicy={selectedPolicies} noTitle />
|
||||
<Box sx={{ padding: "10px 26px" }} withBorders>
|
||||
<h4 style={{ margin: 0, marginBottom: 10, fontSize: 14 }}>
|
||||
Policies
|
||||
</h4>
|
||||
<Box
|
||||
sx={{
|
||||
minHeight: 265,
|
||||
maxHeight: "calc(100vh - 740px)",
|
||||
}}
|
||||
>
|
||||
<PolicySelectors selectedPolicy={selectedPolicies} noTitle />
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
</Grid>
|
||||
<Grid item sm={12} md={6} lg={7} sx={{ padding: 10, paddingTop: 0 }}>
|
||||
<Grid
|
||||
item
|
||||
sm={12}
|
||||
md={6}
|
||||
lg={7}
|
||||
sx={{
|
||||
padding: 10,
|
||||
paddingTop: 0,
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
}}
|
||||
>
|
||||
{loading ? (
|
||||
<Box sx={{ textAlign: "center" }}>
|
||||
<Loader />
|
||||
@@ -198,8 +238,6 @@ const LDAPEntitiesQuery = () => {
|
||||
) : (
|
||||
<Fragment>
|
||||
<SectionTitle
|
||||
separator
|
||||
sx={{ marginBottom: 15 }}
|
||||
actions={
|
||||
<Box
|
||||
sx={{
|
||||
@@ -211,8 +249,13 @@ const LDAPEntitiesQuery = () => {
|
||||
>
|
||||
{results?.timestamp ? (
|
||||
<Fragment>
|
||||
<UptimeIcon
|
||||
style={{ width: 18, height: 18, marginRight: 5 }}
|
||||
<TimeIcon
|
||||
style={{
|
||||
width: 14,
|
||||
height: 14,
|
||||
marginRight: 5,
|
||||
fill: "#BEBFBF",
|
||||
}}
|
||||
/>
|
||||
{DateTime.fromISO(results.timestamp).toFormat(
|
||||
"D HH:mm:ss"
|
||||
@@ -224,114 +267,30 @@ const LDAPEntitiesQuery = () => {
|
||||
</Box>
|
||||
}
|
||||
>
|
||||
Results
|
||||
Query Results
|
||||
</SectionTitle>
|
||||
{results ? (
|
||||
<Box>
|
||||
<Box
|
||||
sx={{
|
||||
backgroundColor: "#FBFAFA",
|
||||
padding: "8px 22px",
|
||||
flexGrow: 1,
|
||||
overflowY: "auto",
|
||||
}}
|
||||
>
|
||||
{!results.groups && !results.users && !results.policies && (
|
||||
<Box sx={{ textAlign: "center" }}>
|
||||
<h4>No Results Available</h4>
|
||||
</Box>
|
||||
)}
|
||||
{!!results.groups && (
|
||||
<Box className={"resultElement"}>
|
||||
<SectionTitle separator sx={{ fontSize: 12 }}>
|
||||
Group Mappings
|
||||
</SectionTitle>
|
||||
<Box sx={{ padding: "0 15px" }}>
|
||||
{results.groups.map((groupData, index) => {
|
||||
return (
|
||||
<Fragment key={`policy-res-${index}`}>
|
||||
<h4>{groupData.group}</h4>
|
||||
{groupData.policies && (
|
||||
<Fragment>
|
||||
Policies:
|
||||
<ul>
|
||||
{groupData.policies.map(
|
||||
(policy, index2) => (
|
||||
<li key={`policy-group-${index2}`}>
|
||||
{policy}
|
||||
</li>
|
||||
)
|
||||
)}
|
||||
</ul>
|
||||
</Fragment>
|
||||
)}
|
||||
</Fragment>
|
||||
);
|
||||
})}
|
||||
</Box>
|
||||
</Box>
|
||||
<LDAPResultsBlock results={results} entityName={"Group"} />
|
||||
)}
|
||||
{!!results.users && (
|
||||
<Box className={"resultElement"}>
|
||||
<SectionTitle separator sx={{ fontSize: 12 }}>
|
||||
User Mappings
|
||||
</SectionTitle>
|
||||
<Box sx={{ padding: "0 15px" }}>
|
||||
{results.users.map((groupData, index) => {
|
||||
return (
|
||||
<Fragment key={`users-res-${index}`}>
|
||||
<h4>{groupData.user}</h4>
|
||||
{groupData.policies && (
|
||||
<Fragment>
|
||||
Policies:
|
||||
<ul>
|
||||
{groupData.policies.map(
|
||||
(policy, index2) => (
|
||||
<li key={`policy-users-${index2}`}>
|
||||
{policy}
|
||||
</li>
|
||||
)
|
||||
)}
|
||||
</ul>
|
||||
</Fragment>
|
||||
)}
|
||||
</Fragment>
|
||||
);
|
||||
})}
|
||||
</Box>
|
||||
</Box>
|
||||
<LDAPResultsBlock results={results} entityName={"User"} />
|
||||
)}
|
||||
{!!results.policies && (
|
||||
<Box className={"resultElement"}>
|
||||
<SectionTitle separator sx={{ fontSize: 12 }}>
|
||||
Policy Mappings
|
||||
</SectionTitle>
|
||||
<Box sx={{ padding: "0 15px" }}>
|
||||
{results.policies.map((groupData, index) => {
|
||||
return (
|
||||
<Fragment key={`policy-map-${index}`}>
|
||||
<h4>{groupData.policy}</h4>
|
||||
{groupData.groups && (
|
||||
<Fragment>
|
||||
Groups:
|
||||
<ul>
|
||||
{groupData.groups.map((group, index2) => (
|
||||
<li key={`policy-map-group-${index}`}>
|
||||
{group}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</Fragment>
|
||||
)}
|
||||
{groupData.users && (
|
||||
<Fragment>
|
||||
Users:
|
||||
<ul>
|
||||
{groupData.users.map((user, index3) => (
|
||||
<li key={`policy-map-user-${index}`}>
|
||||
{user}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</Fragment>
|
||||
)}
|
||||
</Fragment>
|
||||
);
|
||||
})}
|
||||
</Box>
|
||||
</Box>
|
||||
<LDAPResultsBlock results={results} entityName={"Policy"} />
|
||||
)}
|
||||
</Box>
|
||||
) : (
|
||||
@@ -342,12 +301,22 @@ const LDAPEntitiesQuery = () => {
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid container>
|
||||
<Grid item xs={12} sx={{ display: "flex", justifyContent: "flex-end" }}>
|
||||
<Grid
|
||||
item
|
||||
xs={12}
|
||||
sx={{
|
||||
display: "flex",
|
||||
justifyContent: "flex-start",
|
||||
marginTop: 45,
|
||||
padding: "0 20px",
|
||||
}}
|
||||
>
|
||||
<Button
|
||||
id={"search-entity"}
|
||||
type={"button"}
|
||||
variant={"callAction"}
|
||||
onClick={searchEntities}
|
||||
icon={<SearchIcon />}
|
||||
>
|
||||
Search
|
||||
</Button>
|
||||
|
||||
165
portal-ui/src/screens/Console/IDP/LDAP/LDAPResultsBlock.tsx
Normal file
165
portal-ui/src/screens/Console/IDP/LDAP/LDAPResultsBlock.tsx
Normal file
@@ -0,0 +1,165 @@
|
||||
// This file is part of MinIO Console Server
|
||||
// Copyright (c) 2023 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, { Fragment } from "react";
|
||||
import { Box, CollapseCaret, GroupsMenuIcon, SectionTitle } from "mds";
|
||||
import { LDAPEntitiesResponse } from "./types";
|
||||
|
||||
interface IResultBlock {
|
||||
entityName: "Group" | "User" | "Policy";
|
||||
results: LDAPEntitiesResponse;
|
||||
}
|
||||
|
||||
interface IEntityResultName {
|
||||
name: string;
|
||||
}
|
||||
|
||||
interface IEntityResultItem {
|
||||
blockName: "Policies" | "Groups" | "Users";
|
||||
results: string[];
|
||||
}
|
||||
|
||||
const EntityResultTitle = ({ name }: IEntityResultName) => {
|
||||
return (
|
||||
<h4>
|
||||
<CollapseCaret style={{ transform: "rotateZ(90deg)" }} />
|
||||
{name}
|
||||
</h4>
|
||||
);
|
||||
};
|
||||
|
||||
const EntityResultItems = ({ blockName, results }: IEntityResultItem) => {
|
||||
return (
|
||||
<Fragment>
|
||||
<strong>{blockName}:</strong>
|
||||
<ul>
|
||||
{results.map((res, index) => (
|
||||
<li key={`policy-${blockName}-${index}`}>{res}</li>
|
||||
))}
|
||||
</ul>
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
const LDAPResultsBlock = ({ entityName, results }: IResultBlock) => {
|
||||
let entityLength = 0;
|
||||
|
||||
switch (entityName) {
|
||||
case "Group":
|
||||
entityLength = results.groups?.length || 0;
|
||||
break;
|
||||
case "Policy":
|
||||
entityLength = results.policies?.length || 0;
|
||||
break;
|
||||
case "User":
|
||||
entityLength = results.users?.length || 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return (
|
||||
<Box
|
||||
className={"resultElement"}
|
||||
sx={{
|
||||
marginTop: 50,
|
||||
"&:first-of-type": {
|
||||
marginTop: 0,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<SectionTitle
|
||||
separator
|
||||
sx={{ fontSize: 12 }}
|
||||
icon={<GroupsMenuIcon style={{ width: 17, height: 17 }} />}
|
||||
actions={
|
||||
<Box sx={{ fontSize: 14 }}>
|
||||
<strong>{entityLength}</strong> Entit
|
||||
{entityLength === 1 ? "y" : "ies"} Found
|
||||
</Box>
|
||||
}
|
||||
>
|
||||
{entityName} Mappings
|
||||
</SectionTitle>
|
||||
<Box
|
||||
className={"resultsList"}
|
||||
sx={{
|
||||
h4: {
|
||||
borderBottom: "#e2e2e2 1px solid",
|
||||
padding: "12px 0",
|
||||
margin: 0,
|
||||
marginBottom: 15,
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
"& svg": {
|
||||
marginRight: 10,
|
||||
fill: "#3C77A7",
|
||||
},
|
||||
},
|
||||
}}
|
||||
>
|
||||
{entityName === "Group" &&
|
||||
results.groups?.map((groupData, index) => {
|
||||
return (
|
||||
<Fragment key={`policy-res-${index}`}>
|
||||
<EntityResultTitle name={groupData.group} />
|
||||
{groupData.policies && (
|
||||
<EntityResultItems
|
||||
blockName={"Policies"}
|
||||
results={groupData.policies}
|
||||
/>
|
||||
)}
|
||||
</Fragment>
|
||||
);
|
||||
})}
|
||||
{entityName === "User" &&
|
||||
results.users?.map((groupData, index) => {
|
||||
return (
|
||||
<Fragment key={`users-res-${index}`}>
|
||||
<EntityResultTitle name={groupData.user} />
|
||||
{groupData.policies && (
|
||||
<EntityResultItems
|
||||
blockName={"Policies"}
|
||||
results={groupData.policies}
|
||||
/>
|
||||
)}
|
||||
</Fragment>
|
||||
);
|
||||
})}
|
||||
{entityName === "Policy" &&
|
||||
results.policies?.map((groupData, index) => {
|
||||
return (
|
||||
<Fragment key={`policy-map-${index}`}>
|
||||
<EntityResultTitle name={groupData.policy} />
|
||||
{groupData.groups && (
|
||||
<EntityResultItems
|
||||
blockName={"Groups"}
|
||||
results={groupData.groups}
|
||||
/>
|
||||
)}
|
||||
{groupData.users && (
|
||||
<EntityResultItems
|
||||
blockName={"Users"}
|
||||
results={groupData.users}
|
||||
/>
|
||||
)}
|
||||
</Fragment>
|
||||
);
|
||||
})}
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
export default LDAPResultsBlock;
|
||||
Reference in New Issue
Block a user