mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-09-22 13:39:35 +00:00
Merge pull request #2859 from Infisical/daniel/copy-paste
fix(dashboard): pasting secrets into create secret modal
This commit is contained in:
@@ -1,14 +1,31 @@
|
||||
/** Extracts the key and value from a passed in env string based on the provided delimiters. */
|
||||
export const getKeyValue = (pastedContent: string, delimiters: string[]) => {
|
||||
const foundDelimiter = delimiters.find((delimiter) => pastedContent.includes(delimiter));
|
||||
if (!pastedContent) {
|
||||
return { key: "", value: "" };
|
||||
}
|
||||
|
||||
if (!foundDelimiter) {
|
||||
let firstDelimiterIndex = -1;
|
||||
let foundDelimiter = "";
|
||||
|
||||
delimiters.forEach((delimiter) => {
|
||||
const index = pastedContent.indexOf(delimiter);
|
||||
if (index !== -1 && (firstDelimiterIndex === -1 || index < firstDelimiterIndex)) {
|
||||
firstDelimiterIndex = index;
|
||||
foundDelimiter = delimiter;
|
||||
}
|
||||
});
|
||||
|
||||
const hasValueAfterDelimiter = pastedContent.length > firstDelimiterIndex + foundDelimiter.length;
|
||||
|
||||
if (firstDelimiterIndex === -1 || !hasValueAfterDelimiter) {
|
||||
return { key: pastedContent.trim(), value: "" };
|
||||
}
|
||||
|
||||
const [key, value] = pastedContent.split(foundDelimiter);
|
||||
const key = pastedContent.substring(0, firstDelimiterIndex);
|
||||
const value = pastedContent.substring(firstDelimiterIndex + foundDelimiter.length);
|
||||
|
||||
return {
|
||||
key: key.trim(),
|
||||
value: (value ?? "").trim()
|
||||
value: value.trim()
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ClipboardEvent } from "react";
|
||||
import { ClipboardEvent, useRef } from "react";
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
import { faTriangleExclamation } from "@fortawesome/free-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
@@ -46,6 +46,7 @@ export const CreateSecretForm = ({
|
||||
control,
|
||||
reset,
|
||||
setValue,
|
||||
watch,
|
||||
formState: { errors, isSubmitting }
|
||||
} = useForm<TFormSchema>({ resolver: zodResolver(typeSchema) });
|
||||
const { closePopUp } = usePopUpAction();
|
||||
@@ -59,6 +60,11 @@ export const CreateSecretForm = ({
|
||||
canReadTags ? workspaceId : ""
|
||||
);
|
||||
|
||||
const secretKeyInputRef = useRef<HTMLInputElement>(null);
|
||||
const { ref: setSecretKeyHookRef, ...secretKeyRegisterRest } = register("key");
|
||||
|
||||
const secretKey = watch("key");
|
||||
|
||||
const slugSchema = z.string().trim().toLowerCase().min(1);
|
||||
const createNewTag = async (slug: string) => {
|
||||
// TODO: Replace with slugSchema generic
|
||||
@@ -108,13 +114,23 @@ export const CreateSecretForm = ({
|
||||
};
|
||||
|
||||
const handlePaste = (e: ClipboardEvent<HTMLInputElement>) => {
|
||||
e.preventDefault();
|
||||
const delimitters = [":", "="];
|
||||
const pastedContent = e.clipboardData.getData("text");
|
||||
const { key, value } = getKeyValue(pastedContent, delimitters);
|
||||
|
||||
setValue("key", key);
|
||||
setValue("value", value);
|
||||
const isWholeKeyHighlighted =
|
||||
secretKeyInputRef.current &&
|
||||
secretKeyInputRef.current.selectionStart === 0 &&
|
||||
secretKeyInputRef.current.selectionEnd === secretKeyInputRef.current.value.length;
|
||||
|
||||
if (!secretKey || isWholeKeyHighlighted) {
|
||||
e.preventDefault();
|
||||
|
||||
setValue("key", key);
|
||||
if (value) {
|
||||
setValue("value", value);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -126,7 +142,12 @@ export const CreateSecretForm = ({
|
||||
errorText={errors?.key?.message}
|
||||
>
|
||||
<Input
|
||||
{...register("key")}
|
||||
{...secretKeyRegisterRest}
|
||||
ref={(e) => {
|
||||
setSecretKeyHookRef(e);
|
||||
// @ts-expect-error this is for multiple ref single component
|
||||
secretKeyInputRef.current = e;
|
||||
}}
|
||||
placeholder="Type your secret name"
|
||||
onPaste={handlePaste}
|
||||
autoCapitalization={autoCapitalize}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ClipboardEvent } from "react";
|
||||
import { ClipboardEvent, useRef } from "react";
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
import { subject } from "@casl/ability";
|
||||
import { faTriangleExclamation } from "@fortawesome/free-solid-svg-icons";
|
||||
@@ -46,6 +46,7 @@ export const CreateSecretForm = ({ secretPath = "/", onClose }: Props) => {
|
||||
control,
|
||||
reset,
|
||||
setValue,
|
||||
watch,
|
||||
formState: { isSubmitting, errors }
|
||||
} = useForm<TFormSchema>({ resolver: zodResolver(typeSchema) });
|
||||
|
||||
@@ -61,6 +62,11 @@ export const CreateSecretForm = ({ secretPath = "/", onClose }: Props) => {
|
||||
canReadTags ? workspaceId : ""
|
||||
);
|
||||
|
||||
const secretKeyInputRef = useRef<HTMLInputElement>(null);
|
||||
const { ref: setSecretKeyHookRef, ...secretKeyRegisterRest } = register("key");
|
||||
|
||||
const secretKey = watch("key");
|
||||
|
||||
const handleFormSubmit = async ({ key, value, environments: selectedEnv, tags }: TFormSchema) => {
|
||||
const promises = selectedEnv.map(async (env) => {
|
||||
const environment = env.slug;
|
||||
@@ -152,13 +158,23 @@ export const CreateSecretForm = ({ secretPath = "/", onClose }: Props) => {
|
||||
};
|
||||
|
||||
const handlePaste = (e: ClipboardEvent<HTMLInputElement>) => {
|
||||
e.preventDefault();
|
||||
const delimitters = [":", "="];
|
||||
const pastedContent = e.clipboardData.getData("text");
|
||||
const { key, value } = getKeyValue(pastedContent, delimitters);
|
||||
|
||||
setValue("key", key);
|
||||
setValue("value", value);
|
||||
const isWholeKeyHighlighted =
|
||||
secretKeyInputRef.current &&
|
||||
secretKeyInputRef.current.selectionStart === 0 &&
|
||||
secretKeyInputRef.current.selectionEnd === secretKeyInputRef.current.value.length;
|
||||
|
||||
if (!secretKey || isWholeKeyHighlighted) {
|
||||
e.preventDefault();
|
||||
|
||||
setValue("key", key);
|
||||
if (value) {
|
||||
setValue("value", value);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const createWsTag = useCreateWsTag();
|
||||
@@ -189,7 +205,12 @@ export const CreateSecretForm = ({ secretPath = "/", onClose }: Props) => {
|
||||
errorText={errors?.key?.message}
|
||||
>
|
||||
<Input
|
||||
{...register("key")}
|
||||
{...secretKeyRegisterRest}
|
||||
ref={(e) => {
|
||||
setSecretKeyHookRef(e);
|
||||
// @ts-expect-error this is for multiple ref single component
|
||||
secretKeyInputRef.current = e;
|
||||
}}
|
||||
placeholder="Type your secret name"
|
||||
onPaste={handlePaste}
|
||||
autoCapitalization={currentWorkspace?.autoCapitalization}
|
||||
|
||||
Reference in New Issue
Block a user