mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-16 15:31:19 +00:00
feat(secret-approval): conflict ui, request count and secret path in request detail
This commit is contained in:
+15
-5
@@ -20,7 +20,11 @@ import {
|
||||
Skeleton
|
||||
} from "@app/components/v2";
|
||||
import { useUser, useWorkspace } from "@app/context";
|
||||
import { useGetSecretApprovalRequests, useGetWorkspaceUsers } from "@app/hooks/api";
|
||||
import {
|
||||
useGetSecretApprovalRequestCount,
|
||||
useGetSecretApprovalRequests,
|
||||
useGetWorkspaceUsers
|
||||
} from "@app/hooks/api";
|
||||
import { ApprovalStatus, TSecretApprovalRequest, TWorkspaceUser } from "@app/hooks/api/types";
|
||||
|
||||
import {
|
||||
@@ -51,6 +55,8 @@ export const SecretApprovalRequest = () => {
|
||||
environment: envFilter,
|
||||
committer: committerFilter
|
||||
});
|
||||
const { data: secretApprovalRequestCount, isSuccess: isSecretApprovalReqCountSuccess } =
|
||||
useGetSecretApprovalRequestCount({ workspaceId });
|
||||
const { user: presentUser } = useUser();
|
||||
const { data: members } = useGetWorkspaceUsers(workspaceId);
|
||||
const membersGroupById = members?.reduce<Record<string, TWorkspaceUser>>(
|
||||
@@ -103,13 +109,17 @@ export const SecretApprovalRequest = () => {
|
||||
onKeyDown={(evt) => {
|
||||
if (evt.key === "Enter") setStatusFilter("open");
|
||||
}}
|
||||
className={statusFilter === "close" ? "text-gray-500 hover:text-gray-400 duration-100" : ""}
|
||||
className={
|
||||
statusFilter === "close" ? "text-gray-500 hover:text-gray-400 duration-100" : ""
|
||||
}
|
||||
>
|
||||
<FontAwesomeIcon icon={faCodeBranch} className="mr-2" />
|
||||
Open
|
||||
{isSecretApprovalReqCountSuccess && secretApprovalRequestCount?.open} Open
|
||||
</div>
|
||||
<div
|
||||
className={statusFilter === "open" ? "text-gray-500 hover:text-gray-400 duration-100" : ""}
|
||||
className={
|
||||
statusFilter === "open" ? "text-gray-500 hover:text-gray-400 duration-100" : ""
|
||||
}
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
onClick={() => setStatusFilter("close")}
|
||||
@@ -118,7 +128,7 @@ export const SecretApprovalRequest = () => {
|
||||
}}
|
||||
>
|
||||
<FontAwesomeIcon icon={faCheck} className="mr-2" />
|
||||
Closed
|
||||
{isSecretApprovalReqCountSuccess && secretApprovalRequestCount.closed} Closed
|
||||
</div>
|
||||
<div className="flex-grow flex justify-end space-x-8">
|
||||
<DropdownMenu>
|
||||
|
||||
+2
-1
@@ -65,7 +65,8 @@ export const SecretApprovalRequestAction = ({
|
||||
try {
|
||||
await updateSecretStatusChange({
|
||||
id: approvalRequestId,
|
||||
status: reqState
|
||||
status: reqState,
|
||||
workspaceId
|
||||
});
|
||||
createNotification({
|
||||
type: "success",
|
||||
|
||||
+26
-5
@@ -1,4 +1,4 @@
|
||||
import { faFilePen } from "@fortawesome/free-solid-svg-icons";
|
||||
import { faExclamationTriangle, faInfo } from "@fortawesome/free-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
|
||||
import {
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
Td,
|
||||
Th,
|
||||
THead,
|
||||
Tooltip,
|
||||
Tr
|
||||
} from "@app/components/v2";
|
||||
import { CommitType, DecryptedSecret, TSecretApprovalSecChange, WsTag } from "@app/hooks/api/types";
|
||||
@@ -20,6 +21,7 @@ export type Props = {
|
||||
newVersion?: Omit<TSecretApprovalSecChange, "tags"> & { tags?: WsTag[] };
|
||||
presentSecretVersionNumber: number;
|
||||
hasMerged?: Boolean;
|
||||
conflicts: Array<{ secretId: string; op: CommitType }>;
|
||||
};
|
||||
|
||||
const generateItemTitle = (op: CommitType) => {
|
||||
@@ -35,25 +37,44 @@ const generateItemTitle = (op: CommitType) => {
|
||||
);
|
||||
};
|
||||
|
||||
const generateConflictText = (op: CommitType) => {
|
||||
if (op === CommitType.CREATE) return <div>Secret already exist</div>;
|
||||
if (op === CommitType.UPDATE) return <div>Secret not found</div>;
|
||||
return null;
|
||||
};
|
||||
|
||||
export const SecretApprovalRequestChangeItem = ({
|
||||
op,
|
||||
secretVersion,
|
||||
newVersion,
|
||||
presentSecretVersionNumber,
|
||||
hasMerged
|
||||
hasMerged,
|
||||
conflicts
|
||||
}: Props) => {
|
||||
// meaning request has changed
|
||||
const isStale = (secretVersion?.version || 1) < presentSecretVersionNumber && !hasMerged;
|
||||
const isStale = (secretVersion?.version || 1) < presentSecretVersionNumber;
|
||||
const itemConflict =
|
||||
hasMerged && conflicts.find((el) => el.op === op && el.secretId === newVersion?._id);
|
||||
const hasConflict = Boolean(itemConflict);
|
||||
|
||||
return (
|
||||
<div className="bg-bunker-500 rounded-lg pt-2 pb-4 px-4">
|
||||
<div className="py-3 px-1 flex items-center">
|
||||
<div className="flex-grow">{generateItemTitle(op)}</div>
|
||||
{isStale && (
|
||||
{!hasMerged && isStale && (
|
||||
<div className="flex items-center">
|
||||
<FontAwesomeIcon icon={faFilePen} className="text-primary-600 text-sm" />
|
||||
<FontAwesomeIcon icon={faInfo} className="text-primary-600 text-sm" />
|
||||
<span className="text-xs ml-2">Secret has been changed(stale)</span>
|
||||
</div>
|
||||
)}
|
||||
{hasMerged && hasConflict && (
|
||||
<div className="flex items-center text-sm text-bunker-300 space-x-2">
|
||||
<Tooltip content="Merge Conflict">
|
||||
<FontAwesomeIcon icon={faExclamationTriangle} className="text-red-700" />
|
||||
</Tooltip>
|
||||
<div>{generateConflictText(op)}</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<TableContainer>
|
||||
<Table>
|
||||
|
||||
+11
-3
@@ -5,6 +5,7 @@ import {
|
||||
faCheckCircle,
|
||||
faCircle,
|
||||
faCodeBranch,
|
||||
faFolder,
|
||||
faXmarkCircle
|
||||
} from "@fortawesome/free-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
@@ -175,13 +176,19 @@ export const SecretApprovalRequestChanges = ({
|
||||
<div className="text-lg mb-1">
|
||||
{generateCommitText(secretApprovalRequestDetails.commits)}
|
||||
</div>
|
||||
<div className="text-sm text-bunker-300">
|
||||
<div className="text-sm text-bunker-300 flex items-center">
|
||||
{committer?.user?.firstName}
|
||||
{committer?.user?.lastName} ({committer?.user?.email}) wants to change{" "}
|
||||
{secretApprovalRequestDetails.commits.length} secret values in{" "}
|
||||
<span className="text-blue-300 bg-blue-600/60 px-1">
|
||||
{secretApprovalRequestDetails.commits.length} secret values in
|
||||
<span className="text-primary-300 bg-primary-600/60 px-1 mx-1 rounded">
|
||||
{secretApprovalRequestDetails.environment}
|
||||
</span>
|
||||
<div className="flex items-center border border-mineshaft-500 pl-1 pr-2 rounded w-min">
|
||||
<div className="border-r border-mineshaft-500 pr-1">
|
||||
<FontAwesomeIcon icon={faFolder} className="text-primary" size="sm" />
|
||||
</div>
|
||||
<div className="text-sm pl-2 pb-0.5">{secretApprovalRequestDetails.secretPath}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{!hasMerged && secretApprovalRequestDetails.status === "open" && (
|
||||
@@ -213,6 +220,7 @@ export const SecretApprovalRequestChanges = ({
|
||||
({ op, secretVersion, secret, newVersion }, index) => (
|
||||
<SecretApprovalRequestChangeItem
|
||||
op={op}
|
||||
conflicts={secretApprovalRequestDetails.conflicts}
|
||||
hasMerged={hasMerged}
|
||||
secretVersion={secretVersion}
|
||||
presentSecretVersionNumber={secret?.version || 0}
|
||||
|
||||
Reference in New Issue
Block a user