diff --git a/frontend/src/components/v2/Checkbox/Checkbox.tsx b/frontend/src/components/v2/Checkbox/Checkbox.tsx
index 87e278119..dc0e1a491 100644
--- a/frontend/src/components/v2/Checkbox/Checkbox.tsx
+++ b/frontend/src/components/v2/Checkbox/Checkbox.tsx
@@ -30,7 +30,7 @@ export const Checkbox = ({
-
- handlePopUpToggle("addSecretsInAllEnvs", isOpen)}
onClose={() => handlePopUpClose("addSecretsInAllEnvs")}
decryptFileKey={latestFileKey!}
diff --git a/frontend/src/views/SecretOverviewPage/components/CreateSecretForm/CreateSecretForm.tsx b/frontend/src/views/SecretOverviewPage/components/CreateSecretForm/CreateSecretForm.tsx
new file mode 100644
index 000000000..52eebed9e
--- /dev/null
+++ b/frontend/src/views/SecretOverviewPage/components/CreateSecretForm/CreateSecretForm.tsx
@@ -0,0 +1,222 @@
+import { Controller, useForm } from "react-hook-form";
+import { faWarning } from "@fortawesome/free-solid-svg-icons";
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import { zodResolver } from "@hookform/resolvers/zod";
+import { z } from "zod";
+
+import { useNotificationContext } from "@app/components/context/Notifications/NotificationProvider";
+import {
+ Button,
+ Checkbox,
+ FormControl,
+ FormLabel,
+ Input,
+ Modal,
+ ModalContent,
+ SecretInput,
+ Tooltip
+} from "@app/components/v2";
+import { useWorkspace } from "@app/context";
+import { useCreateFolder, useCreateSecretV3, useUpdateSecretV3 } from "@app/hooks/api";
+import { DecryptedSecret, UserWsKeyPair } from "@app/hooks/api/types";
+
+const typeSchema = z
+ .object({
+ key: z.string().min(1, "Key is required"),
+ value: z.string().optional(),
+ environments: z.record(z.boolean().optional())
+ })
+ .refine((data) => data.key !== undefined, {
+ message: "Please enter secret name"
+ });
+
+type TFormSchema = z.infer;
+
+type Props = {
+ secretPath?: string;
+ decryptFileKey: UserWsKeyPair;
+ getSecretByKey: (slug: string, key: string) => DecryptedSecret | undefined;
+ // modal props
+ isOpen?: boolean;
+ onClose: () => void;
+ onTogglePopUp: (isOpen: boolean) => void;
+};
+
+export const CreateSecretForm = ({
+ secretPath = "/",
+ decryptFileKey,
+ isOpen,
+ getSecretByKey,
+ onClose,
+ onTogglePopUp
+}: Props) => {
+ const {
+ register,
+ handleSubmit,
+ control,
+ reset,
+ watch,
+ formState: { isSubmitting, errors }
+ } = useForm({ resolver: zodResolver(typeSchema) });
+ const newSecretKey = watch("key");
+
+ const { currentWorkspace } = useWorkspace();
+ const workspaceId = currentWorkspace?.id || "";
+ const environments = currentWorkspace?.environments || [];
+
+ const { createNotification } = useNotificationContext();
+
+ const { mutateAsync: createSecretV3 } = useCreateSecretV3();
+ const { mutateAsync: updateSecretV3 } = useUpdateSecretV3();
+ const { mutateAsync: createFolder } = useCreateFolder();
+
+ const handleFormSubmit = async ({ key, value, environments: selectedEnv }: TFormSchema) => {
+ const environmentsSelected = environments.filter(({ slug }) => selectedEnv[slug]);
+ const isEnvironmentsSelected = environmentsSelected.length;
+
+ if (!isEnvironmentsSelected) {
+ createNotification({ type: "error", text: "Select atleast one environment" });
+ return;
+ }
+
+ const promises = environmentsSelected.map(async (env) => {
+ const environment = env.slug;
+ // create folder if not existing
+ if (secretPath !== "/") {
+ // /hello/world -> [hello","world"]
+ const pathSegment = secretPath.split("/").filter(Boolean);
+ const parentPath = `/${pathSegment.slice(0, -1).join("/")}`;
+ const folderName = pathSegment.at(-1);
+ if (folderName && parentPath) {
+ await createFolder({
+ projectId: workspaceId,
+ path: parentPath,
+ environment,
+ name: folderName
+ });
+ }
+ }
+
+ const isEdit = getSecretByKey(environment, key) !== undefined;
+ if (isEdit) {
+ return updateSecretV3({
+ environment,
+ workspaceId,
+ secretPath,
+ secretName: key,
+ secretValue: value || "",
+ type: "shared",
+ latestFileKey: decryptFileKey
+ });
+ }
+
+ return createSecretV3({
+ environment,
+ workspaceId,
+ secretPath,
+ secretName: key,
+ secretValue: value || "",
+ secretComment: "",
+ type: "shared",
+ latestFileKey: decryptFileKey
+ });
+ });
+
+ const results = await Promise.allSettled(promises);
+ const isSecretsAdded = results.some((result) => result.status === "fulfilled");
+
+ if (isSecretsAdded) {
+ createNotification({
+ type: "success",
+ text: "Secrets created successfully"
+ });
+ onClose();
+ reset();
+ } else {
+ createNotification({
+ type: "error",
+ text: "Failed to create secrets"
+ });
+ }
+ };
+ return (
+
+
+
+
+
+ );
+};
diff --git a/frontend/src/views/SecretOverviewPage/components/CreateSecretForm/index.tsx b/frontend/src/views/SecretOverviewPage/components/CreateSecretForm/index.tsx
new file mode 100644
index 000000000..ffbe98f57
--- /dev/null
+++ b/frontend/src/views/SecretOverviewPage/components/CreateSecretForm/index.tsx
@@ -0,0 +1 @@
+export { CreateSecretForm } from "./CreateSecretForm"
diff --git a/frontend/src/views/SecretOverviewPage/components/CreateSecretsSection/CreateSecretInAllEnvsForm.tsx b/frontend/src/views/SecretOverviewPage/components/CreateSecretsSection/CreateSecretInAllEnvsForm.tsx
deleted file mode 100644
index bc716edff..000000000
--- a/frontend/src/views/SecretOverviewPage/components/CreateSecretsSection/CreateSecretInAllEnvsForm.tsx
+++ /dev/null
@@ -1,156 +0,0 @@
-import { Controller, useForm } from "react-hook-form";
-import { zodResolver } from "@hookform/resolvers/zod";
-import { z } from "zod";
-
-import { useNotificationContext } from "@app/components/context/Notifications/NotificationProvider";
-import { Button, FormControl, Input, Modal, ModalContent, SecretInput } from "@app/components/v2";
-import { useWorkspace } from "@app/context";
-import { useCreateSecretV3 } from "@app/hooks/api";
-import { UserWsKeyPair } from "@app/hooks/api/types";
-
-const typeSchema = z
- .object({
- key: z.string(),
- values: z.record(z.string().optional())
- })
- .refine((data) => data.key !== undefined, {
- message: "Please enter secret name"
- });
-
-type TFormSchema = z.infer;
-
-type Props = {
- workspaceId: string;
- secretPath?: string;
- decryptFileKey: UserWsKeyPair;
-
- // modal props
- isOpen?: boolean;
- onClose: () => void;
- onTogglePopUp: (isOpen: boolean) => void;
-};
-
-export const CreateSecretInAllEnvsForm = ({
- workspaceId,
- secretPath = "/",
- decryptFileKey,
- isOpen,
- onClose,
- onTogglePopUp
-}: Props) => {
- const {
- register,
- handleSubmit,
- control,
- reset,
- setError,
- formState: { isSubmitting, errors }
- } = useForm({ resolver: zodResolver(typeSchema) });
- const { currentWorkspace } = useWorkspace();
- const environments = currentWorkspace?.environments || [];
-
- const { createNotification } = useNotificationContext();
-
- const { mutateAsync: createSecretV3 } = useCreateSecretV3();
-
- const handleFormSubmit = async ({ key, values }: TFormSchema) => {
- if (!key) {
- setError("key", { message: "Please enter secret name" });
- return;
- }
-
- const promises = environments.map((env) => {
- const environment = env.slug;
- const value = values[environment] || "";
-
- return createSecretV3({
- environment,
- workspaceId,
- secretPath,
- secretName: key,
- secretValue: value,
- secretComment: "",
- type: "shared",
- latestFileKey: decryptFileKey
- });
- });
-
- const results = await Promise.allSettled(promises);
- const isSecretsAdded = results.some((result) => result.status === "fulfilled");
-
- if (isSecretsAdded) {
- createNotification({
- type: "success",
- text: "Secrets created successfully"
- });
- onClose();
- reset();
- } else {
- createNotification({
- type: "error",
- text: "Failed to create secrets"
- });
- }
- };
- return (
-
-
-
-
-
- );
-};