diff --git a/frontend/src/components/v2/GenericFieldLabel/GenericFieldLabel.tsx b/frontend/src/components/v2/GenericFieldLabel/GenericFieldLabel.tsx
index 95eaf5745..b746a32d7 100644
--- a/frontend/src/components/v2/GenericFieldLabel/GenericFieldLabel.tsx
+++ b/frontend/src/components/v2/GenericFieldLabel/GenericFieldLabel.tsx
@@ -1,4 +1,6 @@
import { ReactNode } from "react";
+import { IconDefinition } from "@fortawesome/free-solid-svg-icons";
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { twMerge } from "tailwind-merge";
type Props = {
@@ -7,6 +9,7 @@ type Props = {
className?: string;
labelClassName?: string;
truncate?: boolean;
+ icon?: IconDefinition;
};
export const GenericFieldLabel = ({
@@ -14,11 +17,15 @@ export const GenericFieldLabel = ({
children,
className,
labelClassName,
- truncate
+ truncate,
+ icon
}: Props) => {
return (
-
{label}
+
{children ? (
{children}
) : (
diff --git a/frontend/src/pages/secret-manager/SecretApprovalsPage/components/AccessApprovalRequest/AccessApprovalRequest.tsx b/frontend/src/pages/secret-manager/SecretApprovalsPage/components/AccessApprovalRequest/AccessApprovalRequest.tsx
index f8b935e29..a8cb199d4 100644
--- a/frontend/src/pages/secret-manager/SecretApprovalsPage/components/AccessApprovalRequest/AccessApprovalRequest.tsx
+++ b/frontend/src/pages/secret-manager/SecretApprovalsPage/components/AccessApprovalRequest/AccessApprovalRequest.tsx
@@ -247,9 +247,7 @@ export const AccessApprovalRequest = ({
};
else if (userReviewStatus === ApprovalStatus.APPROVED) {
displayData = {
- label: `Pending ${request.policy.approvals - request.reviewers.length} review${
- request.policy.approvals - request.reviewers.length > 1 ? "s" : ""
- }`,
+ label: "Pending Additional Reviews",
type: "primary",
icon: faClipboardCheck
};
diff --git a/frontend/src/pages/secret-manager/SecretApprovalsPage/components/AccessApprovalRequest/components/ReviewAccessModal.tsx b/frontend/src/pages/secret-manager/SecretApprovalsPage/components/AccessApprovalRequest/components/ReviewAccessModal.tsx
index 4cea61cbe..ee0f18ee0 100644
--- a/frontend/src/pages/secret-manager/SecretApprovalsPage/components/AccessApprovalRequest/components/ReviewAccessModal.tsx
+++ b/frontend/src/pages/secret-manager/SecretApprovalsPage/components/AccessApprovalRequest/components/ReviewAccessModal.tsx
@@ -1,10 +1,9 @@
-import { useCallback, useMemo, useState } from "react";
+import { ReactNode, useCallback, useMemo, useState } from "react";
import {
- faCheckCircle,
- faCircle,
- faTriangleExclamation,
- faUsers,
- faXmarkCircle
+ faBan,
+ faCheck,
+ faHourglass,
+ faTriangleExclamation
} from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import ms from "ms";
@@ -15,12 +14,10 @@ import {
Button,
Checkbox,
FormControl,
+ GenericFieldLabel,
Input,
Modal,
ModalContent,
- Popover,
- PopoverContent,
- PopoverTrigger,
Tooltip
} from "@app/components/v2";
import { Badge } from "@app/components/v2/Badge";
@@ -38,10 +35,22 @@ import { groupBy } from "@app/lib/fn/array";
const getReviewedStatusSymbol = (status?: ApprovalStatus) => {
if (status === ApprovalStatus.APPROVED)
- return
;
+ return (
+
+
+
+ );
if (status === ApprovalStatus.REJECTED)
- return
;
- return
;
+ return (
+
+
+
+ );
+ return (
+
+
+
+ );
};
export const ReviewAccessRequestModal = ({
@@ -267,139 +276,160 @@ export const ReviewAccessRequestModal = ({
-
-
-
Environment
-
{accessDetails.env || "-"}
-
-
-
Secret Path
-
{accessDetails.secretPath || "-"}
-
-
-
Access Type
-
{getAccessLabel()}
-
-
-
Permission
-
{requestedAccess}
-
-
-
Note
-
{request.note || "-"}
-
+
+ {accessDetails.env}
+
+ {accessDetails.secretPath}
+
+ {getAccessLabel()}
+ {requestedAccess}
+ {request.note && (
+
+ {request.note}
+
+ )}
-
Approvers
-
- {approverSequence?.approvers?.map((approver, index) => (
-
-
-
- {index + 1}
-
- {index !== (approverSequence?.approvers?.length || 0) - 1 && (
-
- )}
- {index !== 0 && (
-
- )}
-
-
-
-
Users
-
- {approver?.user
- ?.map(
- (el) => approverSequence?.membersGroupById?.[el.id]?.[0]?.user?.username
- )
- .join(",") || "-"}
-
-
-
-
Groups
-
- {approver?.group
- ?.map(
- (el) =>
- approverSequence?.projectGroupsGroupById?.[el.id]?.[0]?.group?.name
- )
- .join(",") || "-"}
-
-
-
-
-
Approvals Required
-
{approver.approvals || "-"}
-
-
-
-
-
-
-
-
-
Reviewers
-
- {approver.reviewers.map((el, idx) => (
-
-
{el.username}
-
- {getReviewedStatusSymbol(el?.status as ApprovalStatus)}
-
-
- ))}
-
-
-
-
-
-
-
-
- ))}
+
+
+ Approvers
+ {approverSequence.isMyReviewInThisSequence &&
+ request.status === ApprovalStatus.PENDING && (
+
+ Awaiting Your Review
+
+ )}
+
+
+ {approverSequence?.approvers &&
+ approverSequence.approvers.map((approver, index) => {
+ const isInactive =
+ approverSequence?.currentSequence <
+ (approver.sequence ?? approverSequence.approvers!.length);
+
+ const isPending = approverSequence?.currentSequence === approver.sequence;
+
+ let StepComponent: ReactNode;
+ let BadgeComponent: ReactNode = null;
+ if (approver.hasRejected) {
+ StepComponent = (
+
+
+
+ );
+ BadgeComponent =
Rejected;
+ } else if (approver.hasApproved) {
+ StepComponent = (
+
+
+
+ );
+ BadgeComponent =
Approved;
+ } else if (isPending) {
+ StepComponent = (
+
+
+
+ );
+ BadgeComponent =
Pending;
+ } else {
+ StepComponent = (
+
+ {index + 1}
+
+ );
+ }
+
+ return (
+
+ {approverSequence.approvers!.length > 1 && (
+
+ )}
+
+
+ {approver?.user
+ ?.map(
+ (el) => approverSequence?.membersGroupById?.[el.id]?.[0]?.user?.username
+ )
+ .join(", ")}
+
+
+ {approver?.group
+ ?.map(
+ (el) =>
+ approverSequence?.projectGroupsGroupById?.[el.id]?.[0]?.group?.name
+ )
+ .join(", ")}
+
+
+
+
{approver.approvals}
+ {BadgeComponent && (
+
+ Reviewers
+
+ {approver.reviewers.map((el, idx) => (
+
+
{el.username}
+ {getReviewedStatusSymbol(el?.status as ApprovalStatus)}
+
+ ))}
+
+
+ }
+ >
+ {BadgeComponent}
+
+ )}
+
+
+
+
+ );
+ })}
- {approverSequence.isMyReviewInThisSequence &&
- request.status === ApprovalStatus.PENDING && (
-
- Awaiting review from you.
-
- )}
{shouldBlockRequestActions ? (
) : (
<>
-
-
-
-
{isSoftEnforcement &&
request.isRequestedByCurrentUser &&
!(request.isApprover && request.isSelfApproveAllowed) &&
@@ -453,11 +448,7 @@ export const ReviewAccessRequestModal = ({
onCheckedChange={(checked) => setBypassApproval(checked === true)}
isChecked={bypassApproval}
id="byPassApproval"
- checkIndicatorBg="text-white"
- className={twMerge(
- "mr-2",
- bypassApproval ? "border-red bg-red hover:bg-red-600" : ""
- )}
+ className={twMerge("mr-2", bypassApproval ? "border-red/30 bg-red/10" : "")}
>
Approve without waiting for requirements to be met (bypass policy
@@ -481,6 +472,42 @@ export const ReviewAccessRequestModal = ({
)}
)}
+
+
+
+
>
)}
diff --git a/frontend/src/pages/secret-manager/SecretApprovalsPage/components/ApprovalPolicyList/components/ApprovalPolicyRow.tsx b/frontend/src/pages/secret-manager/SecretApprovalsPage/components/ApprovalPolicyList/components/ApprovalPolicyRow.tsx
index 0a674f5b4..408d718fa 100644
--- a/frontend/src/pages/secret-manager/SecretApprovalsPage/components/ApprovalPolicyList/components/ApprovalPolicyRow.tsx
+++ b/frontend/src/pages/secret-manager/SecretApprovalsPage/components/ApprovalPolicyList/components/ApprovalPolicyRow.tsx
@@ -1,5 +1,12 @@
import { useMemo } from "react";
-import { faEdit, faEllipsisV, faTrash } from "@fortawesome/free-solid-svg-icons";
+import {
+ faClipboardCheck,
+ faEdit,
+ faEllipsisV,
+ faTrash,
+ faUser,
+ faUserGroup
+} from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { twMerge } from "tailwind-merge";
@@ -179,26 +186,40 @@ export const ApprovalPolicyRow = ({
}`}
>
-
Approvers
+
Approvers
{labels?.map((el, index) => (
-
-
- {index !== labels.length - 1 && (
-
+
+ {labels.length > 1 && (
+
+
+ {labels.length > 1 && (
+
+ {index + 1}
+
+ )}
+
+
)}
- {index !== 0 && (
-
- )}
-
-
-
{el.userLabels}
-
{el.groupLabels}
-
{el.approvals}
+
+
+ {el.userLabels}
+
+
+ {el.groupLabels}
+
+
+ {el.approvals}
+
))}