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,
|
InputBox,
|
||||||
Loader,
|
Loader,
|
||||||
RemoveIcon,
|
RemoveIcon,
|
||||||
|
SearchIcon,
|
||||||
SectionTitle,
|
SectionTitle,
|
||||||
UptimeIcon,
|
TimeIcon,
|
||||||
} from "mds";
|
} from "mds";
|
||||||
import PolicySelectors from "../../Policies/PolicySelectors";
|
import PolicySelectors from "../../Policies/PolicySelectors";
|
||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
import { LDAPEntitiesResponse } from "./types";
|
import { LDAPEntitiesResponse } from "./types";
|
||||||
import { DateTime } from "luxon";
|
import { DateTime } from "luxon";
|
||||||
|
import LDAPResultsBlock from "./LDAPResultsBlock";
|
||||||
|
|
||||||
const LDAPEntitiesQuery = () => {
|
const LDAPEntitiesQuery = () => {
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
@@ -107,90 +109,128 @@ const LDAPEntitiesQuery = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box sx={{ marginTop: 15, paddingTop: 0 }} withBorders>
|
<Box sx={{ marginTop: 15, paddingTop: 0 }}>
|
||||||
<Grid container sx={{ marginTop: 5 }}>
|
<Grid container sx={{ marginTop: 5 }}>
|
||||||
<Grid item sm={12} md={6} lg={5} sx={{ padding: 10, paddingTop: 0 }}>
|
<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" }}>
|
<Box
|
||||||
<h4>Users</h4>
|
sx={{
|
||||||
<Box
|
padding: "0 10px",
|
||||||
sx={{
|
display: "flex",
|
||||||
overflowY: "auto",
|
flexDirection: "column",
|
||||||
minHeight: 220,
|
gap: 40,
|
||||||
maxHeight: 250,
|
}}
|
||||||
"& > div > div": {
|
>
|
||||||
width: "100%",
|
<Box sx={{ padding: "10px 26px" }} withBorders>
|
||||||
},
|
<Box sx={{ display: "flex" }}>
|
||||||
}}
|
<h4 style={{ margin: 0, marginBottom: 10, fontSize: 14 }}>
|
||||||
>
|
Users
|
||||||
{users.map((userDat, index) => {
|
</h4>
|
||||||
return (
|
</Box>
|
||||||
<InputBox
|
<Box
|
||||||
id={`search-user-${index}`}
|
sx={{
|
||||||
key={`search-user-${index}`}
|
overflowY: "auto",
|
||||||
value={userDat}
|
minHeight: 50,
|
||||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
maxHeight: 250,
|
||||||
const usersElements = [...users];
|
"& > div > div": {
|
||||||
usersElements[index] = e.target.value;
|
width: "100%",
|
||||||
setUsers(usersElements);
|
},
|
||||||
}}
|
}}
|
||||||
overlayIcon={
|
>
|
||||||
users.length === index + 1 ? <AddIcon /> : <RemoveIcon />
|
{users.map((userDat, index) => {
|
||||||
}
|
return (
|
||||||
overlayAction={() => {
|
<InputBox
|
||||||
alterUsersList(users.length === index + 1, index);
|
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>
|
</Box>
|
||||||
|
<Box sx={{ padding: "10px 26px" }} withBorders>
|
||||||
<h4>Groups</h4>
|
<h4 style={{ margin: 0, marginBottom: 10, fontSize: 14 }}>
|
||||||
<Box
|
Groups
|
||||||
sx={{
|
</h4>
|
||||||
overflowY: "auto",
|
<Box
|
||||||
minHeight: 220,
|
sx={{
|
||||||
maxHeight: 250,
|
overflowY: "auto",
|
||||||
"& > div > div": {
|
minHeight: 50,
|
||||||
width: "100%",
|
maxHeight: "calc(100vh - 340px)",
|
||||||
},
|
"& > div > div": {
|
||||||
}}
|
width: "100%",
|
||||||
>
|
},
|
||||||
{groups.map((groupDat, index) => {
|
}}
|
||||||
return (
|
>
|
||||||
<InputBox
|
{groups.map((groupDat, index) => {
|
||||||
id={`search-group-${index}`}
|
return (
|
||||||
key={`search-group-${index}`}
|
<InputBox
|
||||||
value={groupDat}
|
id={`search-group-${index}`}
|
||||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
key={`search-group-${index}`}
|
||||||
const groupsElements = [...groups];
|
value={groupDat}
|
||||||
groupsElements[index] = e.target.value;
|
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
setGroups(groupsElements);
|
const groupsElements = [...groups];
|
||||||
}}
|
groupsElements[index] = e.target.value;
|
||||||
overlayIcon={
|
setGroups(groupsElements);
|
||||||
groups.length === index + 1 ? <AddIcon /> : <RemoveIcon />
|
}}
|
||||||
}
|
overlayIcon={
|
||||||
overlayAction={() => {
|
groups.length === index + 1 ? (
|
||||||
alterGroupsList(groups.length === index + 1, index);
|
<AddIcon />
|
||||||
}}
|
) : (
|
||||||
/>
|
<RemoveIcon />
|
||||||
);
|
)
|
||||||
})}
|
}
|
||||||
|
overlayAction={() => {
|
||||||
|
alterGroupsList(groups.length === index + 1, index);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
|
<Box sx={{ padding: "10px 26px" }} withBorders>
|
||||||
<h4>Policies</h4>
|
<h4 style={{ margin: 0, marginBottom: 10, fontSize: 14 }}>
|
||||||
<Box
|
Policies
|
||||||
sx={{
|
</h4>
|
||||||
minHeight: 220,
|
<Box
|
||||||
maxHeight: "calc(100vh - 740px)",
|
sx={{
|
||||||
}}
|
minHeight: 265,
|
||||||
>
|
maxHeight: "calc(100vh - 740px)",
|
||||||
<PolicySelectors selectedPolicy={selectedPolicies} noTitle />
|
}}
|
||||||
|
>
|
||||||
|
<PolicySelectors selectedPolicy={selectedPolicies} noTitle />
|
||||||
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
</Grid>
|
</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 ? (
|
{loading ? (
|
||||||
<Box sx={{ textAlign: "center" }}>
|
<Box sx={{ textAlign: "center" }}>
|
||||||
<Loader />
|
<Loader />
|
||||||
@@ -198,8 +238,6 @@ const LDAPEntitiesQuery = () => {
|
|||||||
) : (
|
) : (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<SectionTitle
|
<SectionTitle
|
||||||
separator
|
|
||||||
sx={{ marginBottom: 15 }}
|
|
||||||
actions={
|
actions={
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
@@ -211,8 +249,13 @@ const LDAPEntitiesQuery = () => {
|
|||||||
>
|
>
|
||||||
{results?.timestamp ? (
|
{results?.timestamp ? (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<UptimeIcon
|
<TimeIcon
|
||||||
style={{ width: 18, height: 18, marginRight: 5 }}
|
style={{
|
||||||
|
width: 14,
|
||||||
|
height: 14,
|
||||||
|
marginRight: 5,
|
||||||
|
fill: "#BEBFBF",
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
{DateTime.fromISO(results.timestamp).toFormat(
|
{DateTime.fromISO(results.timestamp).toFormat(
|
||||||
"D HH:mm:ss"
|
"D HH:mm:ss"
|
||||||
@@ -224,114 +267,30 @@ const LDAPEntitiesQuery = () => {
|
|||||||
</Box>
|
</Box>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
Results
|
Query Results
|
||||||
</SectionTitle>
|
</SectionTitle>
|
||||||
{results ? (
|
{results ? (
|
||||||
<Box>
|
<Box
|
||||||
|
sx={{
|
||||||
|
backgroundColor: "#FBFAFA",
|
||||||
|
padding: "8px 22px",
|
||||||
|
flexGrow: 1,
|
||||||
|
overflowY: "auto",
|
||||||
|
}}
|
||||||
|
>
|
||||||
{!results.groups && !results.users && !results.policies && (
|
{!results.groups && !results.users && !results.policies && (
|
||||||
<Box sx={{ textAlign: "center" }}>
|
<Box sx={{ textAlign: "center" }}>
|
||||||
<h4>No Results Available</h4>
|
<h4>No Results Available</h4>
|
||||||
</Box>
|
</Box>
|
||||||
)}
|
)}
|
||||||
{!!results.groups && (
|
{!!results.groups && (
|
||||||
<Box className={"resultElement"}>
|
<LDAPResultsBlock results={results} entityName={"Group"} />
|
||||||
<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>
|
|
||||||
)}
|
)}
|
||||||
{!!results.users && (
|
{!!results.users && (
|
||||||
<Box className={"resultElement"}>
|
<LDAPResultsBlock results={results} entityName={"User"} />
|
||||||
<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>
|
|
||||||
)}
|
)}
|
||||||
{!!results.policies && (
|
{!!results.policies && (
|
||||||
<Box className={"resultElement"}>
|
<LDAPResultsBlock results={results} entityName={"Policy"} />
|
||||||
<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>
|
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
) : (
|
) : (
|
||||||
@@ -342,12 +301,22 @@ const LDAPEntitiesQuery = () => {
|
|||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid container>
|
<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
|
<Button
|
||||||
id={"search-entity"}
|
id={"search-entity"}
|
||||||
type={"button"}
|
type={"button"}
|
||||||
variant={"callAction"}
|
variant={"callAction"}
|
||||||
onClick={searchEntities}
|
onClick={searchEntities}
|
||||||
|
icon={<SearchIcon />}
|
||||||
>
|
>
|
||||||
Search
|
Search
|
||||||
</Button>
|
</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