This is an automated email from the ASF dual-hosted git repository.
dhavaljrajpara pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ranger.git
The following commit(s) were added to refs/heads/master by this push:
new f73cfcb4f RANGER-5445 : Implement Confirmation Modal for
Users/Groups/Roles Removal (#1087)
f73cfcb4f is described below
commit f73cfcb4f4e31da5a8ed7cf93fe69c545506cd4f
Author: Dhaval Rajpara <[email protected]>
AuthorDate: Fri Jul 17 17:09:53 2026 +0530
RANGER-5445 : Implement Confirmation Modal for Users/Groups/Roles Removal
(#1087)
---
.../src/components/CommonComponents.jsx | 64 ++++++++++++++++-
.../main/webapp/react-webapp/src/styles/style.css | 36 ++++++++--
.../webapp/react-webapp/src/utils/XAMessages.js | 14 ++--
.../main/webapp/react-webapp/src/utils/XAUtils.js | 12 +++-
.../Admin/AdminLogs/PolicyViewDetails.jsx | 26 +++----
.../views/PolicyListing/AddUpdatePolicyForm.jsx | 23 +++---
.../views/PolicyListing/PolicyConditionsComp.jsx | 2 +-
.../views/PolicyListing/PolicyPermissionItem.jsx | 39 +++++++---
.../src/views/Reports/SearchPolicyTable.jsx | 83 ++++++++++++++++------
.../src/views/Reports/UserAccessLayout.jsx | 2 +-
.../src/views/SecurityZone/SecurityZoneForm.jsx | 27 +++++--
.../src/views/ServiceManager/ServiceDefinition.jsx | 2 +-
.../src/views/ServiceManager/ServiceForm.jsx | 9 ++-
.../UserGroupRoleListing/role_details/RoleForm.jsx | 15 +++-
.../users_details/UserForm.jsx | 7 +-
15 files changed, 285 insertions(+), 76 deletions(-)
diff --git
a/security-admin/src/main/webapp/react-webapp/src/components/CommonComponents.jsx
b/security-admin/src/main/webapp/react-webapp/src/components/CommonComponents.jsx
index 0830f5e1d..e70345d6a 100644
---
a/security-admin/src/main/webapp/react-webapp/src/components/CommonComponents.jsx
+++
b/security-admin/src/main/webapp/react-webapp/src/components/CommonComponents.jsx
@@ -20,10 +20,18 @@
import { isEmpty, isObject, lastIndexOf } from "lodash";
import moment from "moment-timezone";
import React, { Component, useEffect, useMemo, useState } from "react";
-import { Alert, Badge, Button, OverlayTrigger, Popover } from
"react-bootstrap";
+import {
+ Alert,
+ Badge,
+ Button,
+ OverlayTrigger,
+ Popover,
+ Modal
+} from "react-bootstrap";
import { Field } from "react-final-form";
import { useLocation } from "react-router-dom";
import blockLoading from "Images/blockLoading.gif";
+import { components as selectComponents } from "react-select";
export const Loader = () => {
return (
@@ -336,7 +344,6 @@ export const CustomPopoverOnClick = ({
×
</i>
</Popover.Header>
-
<Popover.Body>{content}</Popover.Body>
</Popover>
}
@@ -594,3 +601,56 @@ export const trimInputValue = (e, input) => {
}
input.onBlur(e); // Always call onBlur to trigger validation
};
+
+export const ConfirmationClearIndicator = (props) => {
+ const [show, setShow] = useState(false);
+
+ const message = `Are you sure you want to remove all selected
${props?.selectProps?.clearConfirmMessage} from this field?`;
+
+ const open = (e) => {
+ e.preventDefault();
+ e.stopPropagation();
+ setShow(true);
+ };
+
+ const onNo = (e) => {
+ e.stopPropagation();
+ setShow(false);
+ };
+
+ const onYes = (e) => {
+ e.stopPropagation();
+ props.clearValue(); // clears all selected values (global clear)
+ props?.selectProps?.onClearConfirmed?.();
+ setShow(false);
+ };
+
+ // Remove react-select's default inner event handlers so clicks only on our
icon trigger the modal
+ const { innerProps = {}, ...rest } = props;
+ const { onMouseDown, ...cleanInnerProps } = innerProps;
+
+ return (
+ <>
+ <selectComponents.ClearIndicator {...rest} innerProps={cleanInnerProps}>
+ <span
+ style={{ cursor: "pointer" }}
+ onMouseDown={open}
+ title="Clear all"
+ >
+ <i className="fa fa-times fa-2"></i>
+ </span>
+ </selectComponents.ClearIndicator>
+ <Modal show={show} onHide={() => setShow(false)}>
+ <Modal.Body>{message}</Modal.Body>
+ <Modal.Footer>
+ <Button variant="secondary" size="sm" onMouseDown={onNo}>
+ No
+ </Button>
+ <Button variant="danger" size="sm" onMouseDown={onYes}>
+ Yes
+ </Button>
+ </Modal.Footer>
+ </Modal>
+ </>
+ );
+};
diff --git a/security-admin/src/main/webapp/react-webapp/src/styles/style.css
b/security-admin/src/main/webapp/react-webapp/src/styles/style.css
index a5c9cff2d..e273bd3e7 100644
--- a/security-admin/src/main/webapp/react-webapp/src/styles/style.css
+++ b/security-admin/src/main/webapp/react-webapp/src/styles/style.css
@@ -574,9 +574,9 @@ h3.wrap-header {
margin-top: 5px;
margin-bottom: 5px;
border-radius: 5px;
- font-size: 70%;
- font-weight: 700;
padding: 3px;
+ font-size: 14px;
+ display: block;
}
.rule-condition-wrapper {
@@ -635,6 +635,7 @@ table.no-bg-color thead tr th:first-child {
white-space: nowrap;
vertical-align: sub;
display: inline-block;
+ font-size: 14px;
}
.service-name,
@@ -1607,7 +1608,6 @@ header {
display: inline-flex;
flex-wrap: wrap;
font-size: 1rem;
- max-height: 100px;
overflow-y: auto;
width: 100%;
}
@@ -1617,7 +1617,6 @@ header {
flex-wrap: wrap;
font-size: 1rem;
overflow-y: auto;
- max-height: 100px;
width: 100%;
}
@@ -3053,3 +3052,32 @@ table a {
.switch[class*="btn-outline"] .switch-handle {
background-color: #6c757d !important;
}
+
+.line-clamp-3 {
+ --line-clamp: 3;
+}
+
+.line-clamp-5 {
+ --line-clamp: 5;
+}
+
+.line-clamp {
+ white-space: normal;
+ word-break: break-all;
+ width: 100%;
+ display: -webkit-box;
+ -webkit-box-orient: vertical;
+ -webkit-line-clamp: var(--line-clamp, 3);
+ overflow: auto;
+ line-height: 21px;
+}
+
+.condition-group-table td {
+ font-size: 14px;
+ color: rgb(33, 37, 41);
+}
+
+.condition-group-table th {
+ font-size: 15px !important;
+ color: #333;
+}
diff --git
a/security-admin/src/main/webapp/react-webapp/src/utils/XAMessages.js
b/security-admin/src/main/webapp/react-webapp/src/utils/XAMessages.js
index a9cf53944..806a34cae 100644
--- a/security-admin/src/main/webapp/react-webapp/src/utils/XAMessages.js
+++ b/security-admin/src/main/webapp/react-webapp/src/utils/XAMessages.js
@@ -50,10 +50,16 @@ export const RegexMessage = {
</p>
</>
),
- policyConditionInfoIcon:
- "1. Boolean expression Examples :\
- country_code == 'USA', time_range >= 900 time_range <=
1800 etc.\
- 2. Dragging bottom-right corner of condition
editor(Textarea) can resizable",
+ policyConditionInfoIcon:(
+ <>
+ <span className="mb-0" style={{ fontSize: "small" }}>
+ 1. Boolean expression Examples:
+ <br />
+ country_code == 'USA', time_range >= 900 time_range <= 1800
etc.
+ <br />
+ 2. The condition editor (textarea) can be resized by dragging its
bottom-right corner.
+ </span>
+ </>),
firstNameValidationMsg: (
<>
<p className="pd-10 mb-0" style={{ fontSize: "small" }}>
diff --git a/security-admin/src/main/webapp/react-webapp/src/utils/XAUtils.js
b/security-admin/src/main/webapp/react-webapp/src/utils/XAUtils.js
index d0ca53f8f..ceb4c3aef 100644
--- a/security-admin/src/main/webapp/react-webapp/src/utils/XAUtils.js
+++ b/security-admin/src/main/webapp/react-webapp/src/utils/XAUtils.js
@@ -1590,7 +1590,17 @@ export const currentTimeZone = (timeZoneDate) => {
// Common function to get display label for policy condition
export const getPolicyConditionDisplayLbl = (lbl) => {
- return policyConditionDisplayLabel.hasOwnProperty(lbl)
+ return has(policyConditionDisplayLabel, lbl)
? policyConditionDisplayLabel[lbl]
: lbl;
};
+
+// Common function to safeguard JSON parsing
+export const safeJsonParse = (value, fallback) => {
+ try {
+ return JSON.parse(value);
+ } catch (error) {
+ console.error("JSON Parsing Error:", error);
+ return fallback;
+ }
+};
diff --git
a/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Admin/AdminLogs/PolicyViewDetails.jsx
b/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Admin/AdminLogs/PolicyViewDetails.jsx
index 6feefb53c..2f011b6d4 100644
---
a/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Admin/AdminLogs/PolicyViewDetails.jsx
+++
b/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Admin/AdminLogs/PolicyViewDetails.jsx
@@ -454,7 +454,7 @@ export function PolicyViewDetails(props) {
{!isEmpty(
filterServiceDef && filterServiceDef.policyConditions
) && (
- <td className="text-center">
+ <td>
{!isEmpty(items.conditions)
? items.conditions.map((obj, index) => {
let conditionObj =
@@ -462,15 +462,13 @@ export function PolicyViewDetails(props) {
return e.name == obj.type;
});
return (
- <h6 className="d-inline me-1" key={index}>
- <Badge
- bg="info"
- className="d-inline me-1"
- key={obj.values}
- >{`${getPolicyConditionDisplayLbl(
- conditionObj.label
- )}: ${obj.values.join(", ")}`}</Badge>
- </h6>
+ <Badge
+ bg="info"
+ className="me-1 line-clamp line-clamp-3
text-start"
+ key={obj.values}
+ >{`${getPolicyConditionDisplayLbl(
+ conditionObj.label
+ )}: ${obj.values.join(", ")}`}</Badge>
);
})
: "--"}
@@ -565,8 +563,12 @@ export function PolicyViewDetails(props) {
<tbody>
{conditions.map((obj) => (
<tr key={obj.type} colSpan="2">
- <td width="40%">{getConditionLabel(obj.type)}</td>
- <td width="60% text-truncate">{obj.values.join(", ")}</td>
+ <td width="30%">{getConditionLabel(obj.type)}</td>
+ <td width="70%">
+ <span className="line-clamp line-clamp-5 text-start">
+ {obj.values.join(", ")}
+ </span>
+ </td>
</tr>
))}
</tbody>
diff --git
a/security-admin/src/main/webapp/react-webapp/src/views/PolicyListing/AddUpdatePolicyForm.jsx
b/security-admin/src/main/webapp/react-webapp/src/views/PolicyListing/AddUpdatePolicyForm.jsx
index 617c3d270..b4e6f03ab 100644
---
a/security-admin/src/main/webapp/react-webapp/src/views/PolicyListing/AddUpdatePolicyForm.jsx
+++
b/security-admin/src/main/webapp/react-webapp/src/views/PolicyListing/AddUpdatePolicyForm.jsx
@@ -72,7 +72,8 @@ import {
getResourcesDefVal,
getAllTimeZoneList,
policyConditionUpdatedJSON,
- policyInfo
+ policyInfo,
+ getPolicyConditionDisplayLbl
} from "Utils/XAUtils";
import { useAccordionButton } from "react-bootstrap/AccordionButton";
import AccordionContext from "react-bootstrap/AccordionContext";
@@ -1550,23 +1551,25 @@ export default function AddUpdatePolicyForm() {
return (
<tr key={keyName}>
<td>
- <center>
- {conditionObj.label}
- </center>
+ <span>
+
{getPolicyConditionDisplayLbl(
+ conditionObj.label
+ )}
+ </span>
</td>
<td>
{isArray(
values?.conditions[keyName]
) ? (
- <center>
+ <span className="line-clamp
line-clamp-3">
{values.conditions[
keyName
].join(", ")}
- </center>
+ </span>
) : (
- <center>
+ <span className="line-clamp
line-clamp-3">
{values.conditions[keyName]}
- </center>
+ </span>
)}
</td>
</tr>
@@ -1577,7 +1580,9 @@ export default function AddUpdatePolicyForm() {
) : (
<tr>
<td>
- <center> No Conditions </center>
+ <center className="text-muted">
+ No Conditions
+ </center>
</td>
</tr>
)}
diff --git
a/security-admin/src/main/webapp/react-webapp/src/views/PolicyListing/PolicyConditionsComp.jsx
b/security-admin/src/main/webapp/react-webapp/src/views/PolicyListing/PolicyConditionsComp.jsx
index 357053436..60ed5e3e6 100644
---
a/security-admin/src/main/webapp/react-webapp/src/views/PolicyListing/PolicyConditionsComp.jsx
+++
b/security-admin/src/main/webapp/react-webapp/src/views/PolicyListing/PolicyConditionsComp.jsx
@@ -379,7 +379,7 @@ export default function PolicyConditionsComp(props) {
: "form-control"
}
as="textarea"
- rows={3}
+ rows={12}
onBlur={(e) =>
trimInputValue(e, input)
}
diff --git
a/security-admin/src/main/webapp/react-webapp/src/views/PolicyListing/PolicyPermissionItem.jsx
b/security-admin/src/main/webapp/react-webapp/src/views/PolicyListing/PolicyPermissionItem.jsx
index 169f4ab52..6240525b8 100644
---
a/security-admin/src/main/webapp/react-webapp/src/views/PolicyListing/PolicyPermissionItem.jsx
+++
b/security-admin/src/main/webapp/react-webapp/src/views/PolicyListing/PolicyPermissionItem.jsx
@@ -43,9 +43,10 @@ import {
drop,
dragOver,
policyConditionUpdatedJSON,
- getPolicyConditionDisplayLbl
+ getPolicyConditionDisplayLbl,
+ safeJsonParse
} from "Utils/XAUtils";
-import { selectInputCustomStyles } from "Components/CommonComponents";
+import { selectInputCustomStyles, ConfirmationClearIndicator } from
"Components/CommonComponents";
import PolicyConditionsComp from "./PolicyConditionsComp";
import {
getSelectedLeafResourceTypes,
@@ -378,7 +379,7 @@ export default function PolicyPermissionItem(props) {
});
};
- const policyConditionDisplayValue = (value) => {
+ const ruleConditionDisplayValue = (value) => {
const selectVal = value;
let ipRangVal, uiHintVal;
if (selectVal) {
@@ -392,7 +393,7 @@ export default function PolicyPermissionItem(props) {
}
);
if (conditionObj?.uiHint && conditionObj?.uiHint != "") {
- uiHintVal = JSON.parse(conditionObj.uiHint);
+ uiHintVal = safeJsonParse(conditionObj.uiHint, {});
}
if (isArray(selectVal[property])) {
ipRangVal = (selectVal[property] || [])
@@ -402,19 +403,21 @@ export default function PolicyPermissionItem(props) {
.join(", ");
}
return (
- <h6 key={property}>
- <div
+ <div key={property}>
+ <span
className={`${
uiHintVal?.isMultiline
? "editable-label rule-condition-wrapper"
: "badge bg-dark rule-condition-wrapper"
}`}
>
- {`${getPolicyConditionDisplayLbl(conditionObj.label)}: ${
+ <span className="line-clamp line-clamp-5 text-start">
+ {`${getPolicyConditionDisplayLbl(conditionObj.label)}: ${
isArray(selectVal[property]) ? ipRangVal : selectVal[property]
}`}
- </div>
- </h6>
+ </span>
+ </span>
+ </div>
);
});
}
@@ -475,6 +478,11 @@ export default function PolicyPermissionItem(props) {
isMulti
tabSelectsValue={false}
placeholder="Select Roles"
+ clearConfirmMessage="Roles"
+ components={{
+ ClearIndicator:
+ ConfirmationClearIndicator
+ }}
/>
</div>
)}
@@ -508,6 +516,11 @@ export default function PolicyPermissionItem(props) {
isMulti
tabSelectsValue={false}
placeholder="Select Groups"
+ clearConfirmMessage="Groups"
+ components={{
+ ClearIndicator:
+ ConfirmationClearIndicator
+ }}
/>
</div>
)}
@@ -541,6 +554,11 @@ export default function PolicyPermissionItem(props) {
isMulti
tabSelectsValue={false}
placeholder="Select Users"
+ clearConfirmMessage="Users"
+ components={{
+ ClearIndicator:
+ ConfirmationClearIndicator
+ }}
/>
</div>
)}
@@ -587,7 +605,6 @@ export default function PolicyPermissionItem(props) {
serviceCompDetails?.name
}
actionReqsMap={actionReqsMap}
-
actionFilterContext={{
selectedAccessTypes:
getSelectedAccessTypesForRow(
@@ -780,7 +797,7 @@ export default function PolicyPermissionItem(props) {
)}
</div>
) : (
- <div>
+ <div className="text-center">
<span className="editable-add-text
text-secondary">
Select Masking Option
</span>
diff --git
a/security-admin/src/main/webapp/react-webapp/src/views/Reports/SearchPolicyTable.jsx
b/security-admin/src/main/webapp/react-webapp/src/views/Reports/SearchPolicyTable.jsx
index b88f664fd..c8f581eb4 100644
---
a/security-admin/src/main/webapp/react-webapp/src/views/Reports/SearchPolicyTable.jsx
+++
b/security-admin/src/main/webapp/react-webapp/src/views/Reports/SearchPolicyTable.jsx
@@ -280,7 +280,7 @@ function SearchPolicyTable(props) {
</Accordion.Body>
</Accordion.Item>
</Accordion>
- <Modal show={showModal} onHide={hidePolicyConditionModal} size="lg">
+ <Modal show={showModal} onHide={hidePolicyConditionModal} size="xl">
<Modal.Header closeButton>
<Modal.Title>Policy Condition Details</Modal.Title>
</Modal.Header>
@@ -330,22 +330,20 @@ function PolicyConditionData(props) {
)}
</td>
{!isEmpty(props?.serviceDef?.policyConditions) && (
- <td className="text-center">
+ <td>
{!isEmpty(items.conditions)
? items.conditions.map((obj, index) => {
let conditionObj =
props.serviceDef.policyConditions.find(
(condition) => condition.name === obj.type
);
return (
- <h6 className="d-inline me-1" key={index}>
- <Badge
- bg="info"
- className="d-inline me-1"
- key={obj.values}
- >{`${getPolicyConditionDisplayLbl(
- conditionObj.label
- )}: ${obj.values.join(", ")}`}</Badge>
- </h6>
+ <Badge
+ bg="info"
+ className="me-1 line-clamp line-clamp-3 text-start"
+ key={index}
+ >{`${getPolicyConditionDisplayLbl(
+ conditionObj.label
+ )}: ${obj.values.join(", ")}`}</Badge>
);
})
: "--"}
@@ -358,6 +356,15 @@ function PolicyConditionData(props) {
<div className="text-center">--</div>
)}
</td>
+ {props?.serviceDef?.name != "tag" && (
+ <td className="text-center">
+ <input
+ type="checkbox"
+ checked={items.delegateAdmin === false ? false : true}
+ disabled="disabled"
+ />
+ </td>
+ )}
</tr>
);
});
@@ -366,7 +373,7 @@ function PolicyConditionData(props) {
<tr key="no-data">
<td
className="text-center"
- colSpan={!isEmpty(props?.serviceDef?.policyConditions) ? "5" : "4"}
+ colSpan={!isEmpty(props?.serviceDef?.policyConditions) ? "6" : "5"}
>
<span className="text-muted">"No data to show!!"</span>
</td>
@@ -406,17 +413,20 @@ function PolicyConditionData(props) {
)}
</td>
{!isEmpty(props?.serviceDef?.policyConditions) && (
- <td className="text-center">
+ <td>
{!isEmpty(items.conditions)
? items.conditions.map((obj, index) => {
+ let conditionObj =
props.serviceDef.policyConditions.find(
+ (condition) => condition.name === obj.type
+ );
return (
- <h6 className="d-inline me-1" key={index}>
- <Badge
- bg="info"
- className="d-inline me-1"
- key={obj.values}
- >{`${obj.type}: ${obj.values.join(", ")}`}</Badge>
- </h6>
+ <Badge
+ bg="info"
+ className="me-1 line-clamp line-clamp-3 text-start"
+ key={index}
+ >{`${getPolicyConditionDisplayLbl(
+ conditionObj.label
+ )}: ${obj.values.join(", ")}`}</Badge>
);
})
: "--"}
@@ -487,6 +497,26 @@ function PolicyConditionData(props) {
<div className="text-center">--</div>
)}
</td>
+ {!isEmpty(props?.serviceDef?.policyConditions) && (
+ <td>
+ {!isEmpty(items.conditions)
+ ? items.conditions.map((obj, index) => {
+ let conditionObj =
props.serviceDef.policyConditions.find(
+ (condition) => condition.name === obj.type
+ );
+ return (
+ <Badge
+ bg="info"
+ className="me-1 line-clamp line-clamp-3 text-start"
+ key={index}
+ >{`${getPolicyConditionDisplayLbl(
+ conditionObj.label
+ )}: ${obj.values.join(", ")}`}</Badge>
+ );
+ })
+ : "--"}
+ </td>
+ )}
<td>
{!isEmpty(access) ? (
<MoreLess data={access} />
@@ -540,6 +570,7 @@ function PolicyConditionData(props) {
<th className="text-center text-nowrap">Rule
Conditions</th>
)}
<th>Accesses</th>
+ {props?.serviceDef?.name != "tag" && <th>Delegate Admin</th>}
</tr>
</thead>
<tbody>{getPolicyData(props.policyData.policyItems)}</tbody>
@@ -566,6 +597,9 @@ function PolicyConditionData(props) {
</th>
)}
<th>Accesses</th>
+ {props?.serviceDef?.name != "tag" && (
+ <th>Delegate Admin</th>
+ )}
</tr>
</thead>
<tbody>
@@ -591,6 +625,9 @@ function PolicyConditionData(props) {
</th>
)}
<th>Accesses</th>
+ {props?.serviceDef?.name != "tag" && (
+ <th>Delegate Admin</th>
+ )}
</tr>
</thead>
<tbody>
@@ -616,6 +653,9 @@ function PolicyConditionData(props) {
</th>
)}
<th>Accesses</th>
+ {props?.serviceDef?.name != "tag" && (
+ <th>Delegate Admin</th>
+ )}
</tr>
</thead>
<tbody>
@@ -671,6 +711,9 @@ function PolicyConditionData(props) {
<th>Roles</th>
<th>Groups</th>
<th>Users</th>
+ {!isEmpty(props?.serviceDef?.policyConditions) && (
+ <th className="text-center text-nowrap">Rule
Conditions</th>
+ )}
<th>Accesses</th>
<th>Row Level Filter</th>
</tr>
diff --git
a/security-admin/src/main/webapp/react-webapp/src/views/Reports/UserAccessLayout.jsx
b/security-admin/src/main/webapp/react-webapp/src/views/Reports/UserAccessLayout.jsx
index 5dc1c6914..f9fe792f9 100644
---
a/security-admin/src/main/webapp/react-webapp/src/views/Reports/UserAccessLayout.jsx
+++
b/security-admin/src/main/webapp/react-webapp/src/views/Reports/UserAccessLayout.jsx
@@ -494,7 +494,7 @@ function UserAccessLayout() {
<Accordion.Body>
<Form
onSubmit={onSubmit}
- initialValues={getInitialSearchParams}
+ initialValues={getInitialSearchParams()}
render={({ handleSubmit, submitting, values }) => (
<form onSubmit={handleSubmit}>
<Row className="form-group">
diff --git
a/security-admin/src/main/webapp/react-webapp/src/views/SecurityZone/SecurityZoneForm.jsx
b/security-admin/src/main/webapp/react-webapp/src/views/SecurityZone/SecurityZoneForm.jsx
index 7d9ad9d31..817320331 100644
---
a/security-admin/src/main/webapp/react-webapp/src/views/SecurityZone/SecurityZoneForm.jsx
+++
b/security-admin/src/main/webapp/react-webapp/src/views/SecurityZone/SecurityZoneForm.jsx
@@ -49,7 +49,8 @@ import {
scrollToError,
selectInputCustomStyles,
selectInputCustomErrorStyles,
- trimInputValue
+ trimInputValue,
+ ConfirmationClearIndicator
} from "Components/CommonComponents";
import usePrompt from "Hooks/usePrompt";
import { getServiceDef } from "Utils/appState";
@@ -873,11 +874,13 @@ const SecurityZoneForm = () => {
isMulti
components={{
DropdownIndicator: () => null,
- IndicatorSeparator: () => null
+ IndicatorSeparator: () => null,
+ ClearIndicator: ConfirmationClearIndicator
}}
isClearable={true}
placeholder="Select Users"
tabSelectsValue={false}
+ clearConfirmMessage="Users"
/>
</Col>
</Row>
@@ -918,11 +921,13 @@ const SecurityZoneForm = () => {
isMulti
components={{
DropdownIndicator: () => null,
- IndicatorSeparator: () => null
+ IndicatorSeparator: () => null,
+ ClearIndicator: ConfirmationClearIndicator
}}
isClearable={true}
placeholder="Select Groups"
tabSelectsValue={false}
+ clearConfirmMessage="Groups"
/>
</Col>
</Row>
@@ -963,11 +968,13 @@ const SecurityZoneForm = () => {
isMulti
components={{
DropdownIndicator: () => null,
- IndicatorSeparator: () => null
+ IndicatorSeparator: () => null,
+ ClearIndicator: ConfirmationClearIndicator
}}
isClearable={true}
placeholder="Select Roles"
tabSelectsValue={false}
+ clearConfirmMessage="Roles"
/>
{meta.touched && meta.error && (
<span className="invalid-field">
@@ -1013,11 +1020,13 @@ const SecurityZoneForm = () => {
isMulti
components={{
DropdownIndicator: () => null,
- IndicatorSeparator: () => null
+ IndicatorSeparator: () => null,
+ ClearIndicator: ConfirmationClearIndicator
}}
isClearable={true}
placeholder="Select Users"
tabSelectsValue={false}
+ clearConfirmMessage="Users"
/>
</Col>
</Row>
@@ -1058,11 +1067,13 @@ const SecurityZoneForm = () => {
isMulti
components={{
DropdownIndicator: () => null,
- IndicatorSeparator: () => null
+ IndicatorSeparator: () => null,
+ ClearIndicator: ConfirmationClearIndicator
}}
isClearable={true}
placeholder="Select Groups"
tabSelectsValue={false}
+ clearConfirmMessage="Groups"
/>
</Col>
</Row>
@@ -1103,11 +1114,13 @@ const SecurityZoneForm = () => {
isMulti
components={{
DropdownIndicator: () => null,
- IndicatorSeparator: () => null
+ IndicatorSeparator: () => null,
+ ClearIndicator: ConfirmationClearIndicator
}}
isClearable={true}
placeholder="Select Roles"
tabSelectsValue={false}
+ clearConfirmMessage="Roles"
/>
{meta.error && meta.touched && (
<span className="invalid-field">
diff --git
a/security-admin/src/main/webapp/react-webapp/src/views/ServiceManager/ServiceDefinition.jsx
b/security-admin/src/main/webapp/react-webapp/src/views/ServiceManager/ServiceDefinition.jsx
index cc60cd305..0fb63700e 100644
---
a/security-admin/src/main/webapp/react-webapp/src/views/ServiceManager/ServiceDefinition.jsx
+++
b/security-admin/src/main/webapp/react-webapp/src/views/ServiceManager/ServiceDefinition.jsx
@@ -178,7 +178,7 @@ class ServiceDefinition extends Component {
pathname:
`/service/${s.id}/policies/${RangerPolicyType.RANGER_ACCESS_POLICY_TYPE.value}`,
detail: this.props.selectedZone
}}
- className="service-name text-info"
+ className="service-name"
>
{s.displayName !== undefined ? s.displayName :
s.name}
</Link>
diff --git
a/security-admin/src/main/webapp/react-webapp/src/views/ServiceManager/ServiceForm.jsx
b/security-admin/src/main/webapp/react-webapp/src/views/ServiceManager/ServiceForm.jsx
index cb4d4e65f..6196cea37 100644
---
a/security-admin/src/main/webapp/react-webapp/src/views/ServiceManager/ServiceForm.jsx
+++
b/security-admin/src/main/webapp/react-webapp/src/views/ServiceManager/ServiceForm.jsx
@@ -42,7 +42,8 @@ import {
Loader,
scrollToError,
selectInputCustomStyles,
- trimInputValue
+ trimInputValue,
+ ConfirmationClearIndicator
} from "Components/CommonComponents";
import {
difference,
@@ -706,6 +707,12 @@ class ServiceForm extends Component {
isClearable={true}
styles={selectInputCustomStyles}
isMulti
+ clearConfirmMessage={
+ additionalConfig.type == "user" ? "Users" : "Groups"
+ }
+ components={{
+ ClearIndicator: ConfirmationClearIndicator
+ }}
/>
</Col>
</Row>
diff --git
a/security-admin/src/main/webapp/react-webapp/src/views/UserGroupRoleListing/role_details/RoleForm.jsx
b/security-admin/src/main/webapp/react-webapp/src/views/UserGroupRoleListing/role_details/RoleForm.jsx
index 746ff55a6..e459c2f12 100644
---
a/security-admin/src/main/webapp/react-webapp/src/views/UserGroupRoleListing/role_details/RoleForm.jsx
+++
b/security-admin/src/main/webapp/react-webapp/src/views/UserGroupRoleListing/role_details/RoleForm.jsx
@@ -26,7 +26,8 @@ import {
Loader,
CustomTooltip,
selectInputCustomStyles,
- trimInputValue
+ trimInputValue,
+ ConfirmationClearIndicator
} from "Components/CommonComponents";
import { FieldArray } from "react-final-form-arrays";
import arrayMutators from "final-form-arrays";
@@ -639,6 +640,10 @@ function RoleForm() {
styles={selectInputCustomStyles}
tabSelectsValue={false}
placeholder="Select Users"
+ clearConfirmMessage="Users"
+ components={{
+ ClearIndicator: ConfirmationClearIndicator
+ }}
/>
</div>
<div className="col-sm-3">
@@ -748,6 +753,10 @@ function RoleForm() {
styles={selectInputCustomStyles}
tabSelectsValue={false}
placeholder="Select Groups"
+ clearConfirmMessage="Groups"
+ components={{
+ ClearIndicator: ConfirmationClearIndicator
+ }}
/>
</div>
<div className="col-sm-3">
@@ -857,6 +866,10 @@ function RoleForm() {
styles={selectInputCustomStyles}
tabSelectsValue={false}
placeholder="Select Roles"
+ clearConfirmMessage="Roles"
+ components={{
+ ClearIndicator: ConfirmationClearIndicator
+ }}
/>
</div>
<div className="col-sm-3">
diff --git
a/security-admin/src/main/webapp/react-webapp/src/views/UserGroupRoleListing/users_details/UserForm.jsx
b/security-admin/src/main/webapp/react-webapp/src/views/UserGroupRoleListing/users_details/UserForm.jsx
index e00333e7d..068475d0f 100644
---
a/security-admin/src/main/webapp/react-webapp/src/views/UserGroupRoleListing/users_details/UserForm.jsx
+++
b/security-admin/src/main/webapp/react-webapp/src/views/UserGroupRoleListing/users_details/UserForm.jsx
@@ -24,7 +24,8 @@ import {
BlockUi,
scrollToError,
selectInputCustomStyles,
- trimInputValue
+ trimInputValue,
+ ConfirmationClearIndicator
} from "Components/CommonComponents";
import AsyncSelect from "react-select/async";
import Select from "react-select";
@@ -244,6 +245,10 @@ function UserForm(props) {
styles={selectInputCustomStyles}
tabSelectsValue={false}
placeholder="Select Groups"
+ clearConfirmMessage="Groups"
+ components={{
+ ClearIndicator: ConfirmationClearIndicator
+ }}
/>
);
};