diff --git a/frontend/src/hooks/api/secretFolders/types.ts b/frontend/src/hooks/api/secretFolders/types.ts
index 8fde9c63d..412f2686d 100644
--- a/frontend/src/hooks/api/secretFolders/types.ts
+++ b/frontend/src/hooks/api/secretFolders/types.ts
@@ -1,3 +1,7 @@
+export enum ReservedFolders {
+ SecretReplication = "__reserve_replication_"
+}
+
export type TSecretFolder = {
id: string;
name: string;
diff --git a/frontend/src/hooks/api/secretImports/types.ts b/frontend/src/hooks/api/secretImports/types.ts
index 64b55425d..1a6c06dd3 100644
--- a/frontend/src/hooks/api/secretImports/types.ts
+++ b/frontend/src/hooks/api/secretImports/types.ts
@@ -10,6 +10,7 @@ export type TSecretImport = {
position: string;
createdAt: string;
updatedAt: string;
+ isReserved?: boolean;
isReplication?: boolean;
isReplicationSuccess?: boolean;
replicationStatus?: string;
diff --git a/frontend/src/lib/fn/string.ts b/frontend/src/lib/fn/string.ts
new file mode 100644
index 000000000..a7de20262
--- /dev/null
+++ b/frontend/src/lib/fn/string.ts
@@ -0,0 +1,9 @@
+import { ReservedFolders } from "@app/hooks/api/secretFolders/types";
+
+export const formatReservedPaths = (secretPath: string) => {
+ const i = secretPath.indexOf(ReservedFolders.SecretReplication);
+ if (i !== -1) {
+ return secretPath.slice(0, i);
+ }
+ return secretPath;
+};
diff --git a/frontend/src/views/SecretApprovalPage/components/SecretApprovalRequest/components/SecretApprovalRequestChanges.tsx b/frontend/src/views/SecretApprovalPage/components/SecretApprovalRequest/components/SecretApprovalRequestChanges.tsx
index 4815c7535..33025342f 100644
--- a/frontend/src/views/SecretApprovalPage/components/SecretApprovalRequest/components/SecretApprovalRequestChanges.tsx
+++ b/frontend/src/views/SecretApprovalPage/components/SecretApprovalRequest/components/SecretApprovalRequestChanges.tsx
@@ -20,6 +20,7 @@ import {
useUpdateSecretApprovalReviewStatus
} from "@app/hooks/api";
import { ApprovalStatus, CommitType, TWorkspaceUser } from "@app/hooks/api/types";
+import { formatReservedPaths } from "@app/lib/fn/string";
import { SecretApprovalRequestAction } from "./SecretApprovalRequestAction";
import { SecretApprovalRequestChangeItem } from "./SecretApprovalRequestChangeItem";
@@ -200,7 +201,9 @@ export const SecretApprovalRequestChanges = ({
- {secretApprovalRequestDetails.secretPath}
+
+ {formatReservedPaths(secretApprovalRequestDetails.secretPath)}
+
diff --git a/frontend/src/views/SecretMainPage/components/ActionBar/CreateSecretImportForm.tsx b/frontend/src/views/SecretMainPage/components/ActionBar/CreateSecretImportForm.tsx
index a2a0b4354..5832779e3 100644
--- a/frontend/src/views/SecretMainPage/components/ActionBar/CreateSecretImportForm.tsx
+++ b/frontend/src/views/SecretMainPage/components/ActionBar/CreateSecretImportForm.tsx
@@ -6,7 +6,6 @@ import { z } from "zod";
import { createNotification } from "@app/components/notifications";
import {
Button,
- Checkbox,
FormControl,
Modal,
ModalContent,
@@ -151,11 +150,25 @@ export const CreateSecretImportForm = ({
name="isReplication"
control={control}
defaultValue={false}
- render={({ field }) => (
-
- Enable replication to synchronize changes.
Warning: This will overwrite any
- existing secrets with the same name.
-
+ render={({ field: { value, onChange }, fieldState: { error } }) => (
+
+
+
)}
/>
diff --git a/frontend/src/views/SecretMainPage/components/SecretImportListView/SecretImportItem.tsx b/frontend/src/views/SecretMainPage/components/SecretImportListView/SecretImportItem.tsx
index c78af8ffd..07c66f17c 100644
--- a/frontend/src/views/SecretMainPage/components/SecretImportListView/SecretImportItem.tsx
+++ b/frontend/src/views/SecretMainPage/components/SecretImportListView/SecretImportItem.tsx
@@ -30,20 +30,17 @@ import {
import { ProjectPermissionActions, ProjectPermissionSub, useWorkspace } from "@app/context";
import { useToggle } from "@app/hooks";
import { useResyncSecretReplication } from "@app/hooks/api";
+import { TSecretImport } from "@app/hooks/api/types";
type Props = {
onDelete: () => void;
environment: string;
secretPath?: string;
- isReplication?: boolean;
- isReplicationSuccess?: boolean;
- replicationStatus?: string;
- lastReplicated?: string;
- importEnvName: string;
- importEnvPath: string;
+ secretImport?: TSecretImport;
+ isReplicationExpand?: boolean;
importedSecrets: { key: string; value: string; overriden: { env: string; secretPath: string } }[];
searchTerm: string;
- id: string;
+ onExpandReplicateSecrets: (id: string) => void;
};
// to show the environment and folder icon
@@ -70,25 +67,29 @@ export const EnvFolderIcon = ({
export const SecretImportItem = ({
onDelete,
- id,
- importEnvName,
- importEnvPath,
- isReplication,
+ isReplicationExpand,
importedSecrets = [],
searchTerm = "",
secretPath,
environment,
- isReplicationSuccess,
- replicationStatus,
- lastReplicated
+ secretImport,
+ onExpandReplicateSecrets: onExpandReplicate
}: Props) => {
+ const {
+ isReserved,
+ id,
+ isReplication,
+ isReplicationSuccess,
+ replicationStatus,
+ lastReplicated,
+ importEnv
+ } = secretImport as TSecretImport;
const { currentWorkspace } = useWorkspace();
const [isExpanded, setIsExpanded] = useToggle();
const { attributes, listeners, transform, transition, setNodeRef, isDragging } = useSortable({
id
});
const resyncSecretReplication = useResyncSecretReplication();
-
useEffect(() => {
const filteredSecrets = importedSecrets.filter((secret) =>
secret.key.toUpperCase().includes(searchTerm.toUpperCase())
@@ -134,24 +135,39 @@ export const SecretImportItem = ({
}
};
+ const handleRowClick = () => {
+ if (isReplication) {
+ onExpandReplicate(id);
+ } else {
+ setIsExpanded.toggle();
+ }
+ };
+
return (
<>
setIsExpanded.toggle()}
- onKeyDown={() => setIsExpanded.toggle()}
+ onClick={handleRowClick}
+ onKeyDown={(e) => {
+ if (e.key === "Enter") {
+ handleRowClick();
+ }
+ }}
>
@@ -193,29 +209,31 @@ export const SecretImportItem = ({
)}
-
- {(isAllowed) => (
-
-
-
- )}
-
+ {isReplication && (
+
+ {(isAllowed) => (
+
+
+
+ )}
+
+ )}
- {!isReplication && isExpanded && !isDragging && (
+ {!isReplication && (isReplicationExpand || isExpanded) && !isDragging && (
{
overridenSec[el.key] = {
env: importSecrets[i].environmentInfo.name,
- secretPath: importSecrets[i].secretPath
+ secretPath: formatReservedPaths(importSecrets[i].secretPath)
};
});
}
@@ -91,6 +93,8 @@ export const SecretImportListView = ({
"deleteSecretImport"
] as const);
+ const [replicationSecrets, setReplicationSecrets] = useState>({});
+
const sensors = useSensors(
useSensor(MouseSensor, {}),
useSensor(TouchSensor, {}),
@@ -149,6 +153,22 @@ export const SecretImportListView = ({
}
};
+ const handleOpenReplicationSecrets = (replicationImportId: string) => {
+ console.log(secretImports);
+ const reservedImport = secretImports.find(
+ ({ isReserved, importPath, importEnv }) =>
+ importEnv.slug === environment &&
+ isReserved &&
+ importPath === `/${ReservedFolders.SecretReplication}${replicationImportId}`
+ );
+ if (reservedImport) {
+ setReplicationSecrets((state) => ({
+ ...state,
+ [reservedImport.id]: !state?.[reservedImport.id]
+ }));
+ }
+ };
+
return (
<>
{items?.map((item) => {
- const {
- importPath,
- importEnv,
- id,
- isReplication,
- replicationStatus,
- lastReplicated,
- isReplicationSuccess
- } = item;
+ // TODO(akhilmhdh): change this and pass this whole object instead of one by one
return (
|