mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-07 19:28:09 +00:00
Merge pull request #1537 from Infisical/daniel/copy-project-slug
Feat: Copy project slug button
This commit is contained in:
+52
@@ -0,0 +1,52 @@
|
|||||||
|
import { useCallback } from "react";
|
||||||
|
import { faCheck, faCopy } from "@fortawesome/free-solid-svg-icons";
|
||||||
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
|
|
||||||
|
import { useNotificationContext } from "@app/components/context/Notifications/NotificationProvider";
|
||||||
|
import { Button } from "@app/components/v2";
|
||||||
|
import { useToggle } from "@app/hooks";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
value: string;
|
||||||
|
hoverText: string;
|
||||||
|
notificationText: string;
|
||||||
|
children: React.ReactNode;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const CopyButton = ({ value, children, hoverText, notificationText }: Props) => {
|
||||||
|
const [isProjectIdCopied, setIsProjectIdCopied] = useToggle(false);
|
||||||
|
const { createNotification } = useNotificationContext();
|
||||||
|
|
||||||
|
const copyToClipboard = useCallback(() => {
|
||||||
|
if (isProjectIdCopied) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setIsProjectIdCopied.on();
|
||||||
|
navigator.clipboard.writeText(value);
|
||||||
|
|
||||||
|
createNotification({
|
||||||
|
text: notificationText,
|
||||||
|
type: "success"
|
||||||
|
});
|
||||||
|
|
||||||
|
const timer = setTimeout(() => setIsProjectIdCopied.off(), 2000);
|
||||||
|
|
||||||
|
// eslint-disable-next-line consistent-return
|
||||||
|
return () => clearTimeout(timer);
|
||||||
|
}, [isProjectIdCopied]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Button
|
||||||
|
colorSchema="secondary"
|
||||||
|
className="group relative"
|
||||||
|
leftIcon={<FontAwesomeIcon icon={isProjectIdCopied ? faCheck : faCopy} />}
|
||||||
|
onClick={copyToClipboard}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
<span className="absolute -left-8 -top-20 hidden translate-y-full justify-center rounded-md bg-bunker-800 py-2 px-3 text-sm text-gray-400 group-hover:flex group-hover:animate-fadeIn">
|
||||||
|
{hoverText}
|
||||||
|
</span>
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
};
|
||||||
+17
-36
@@ -1,7 +1,5 @@
|
|||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
import { Controller, useForm } from "react-hook-form";
|
import { Controller, useForm } from "react-hook-form";
|
||||||
import { faCheck, faCopy } from "@fortawesome/free-solid-svg-icons";
|
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
|
||||||
import { yupResolver } from "@hookform/resolvers/yup";
|
import { yupResolver } from "@hookform/resolvers/yup";
|
||||||
import * as yup from "yup";
|
import * as yup from "yup";
|
||||||
|
|
||||||
@@ -9,9 +7,10 @@ import { useNotificationContext } from "@app/components/context/Notifications/No
|
|||||||
import { ProjectPermissionCan } from "@app/components/permissions";
|
import { ProjectPermissionCan } from "@app/components/permissions";
|
||||||
import { Button, FormControl, Input } from "@app/components/v2";
|
import { Button, FormControl, Input } from "@app/components/v2";
|
||||||
import { ProjectPermissionActions, ProjectPermissionSub, useWorkspace } from "@app/context";
|
import { ProjectPermissionActions, ProjectPermissionSub, useWorkspace } from "@app/context";
|
||||||
import { useToggle } from "@app/hooks";
|
|
||||||
import { useRenameWorkspace } from "@app/hooks/api";
|
import { useRenameWorkspace } from "@app/hooks/api";
|
||||||
|
|
||||||
|
import { CopyButton } from "./CopyButton";
|
||||||
|
|
||||||
const formSchema = yup.object({
|
const formSchema = yup.object({
|
||||||
name: yup.string().required().label("Project Name")
|
name: yup.string().required().label("Project Name")
|
||||||
});
|
});
|
||||||
@@ -22,7 +21,6 @@ export const ProjectNameChangeSection = () => {
|
|||||||
const { createNotification } = useNotificationContext();
|
const { createNotification } = useNotificationContext();
|
||||||
const { currentWorkspace } = useWorkspace();
|
const { currentWorkspace } = useWorkspace();
|
||||||
const { mutateAsync, isLoading } = useRenameWorkspace();
|
const { mutateAsync, isLoading } = useRenameWorkspace();
|
||||||
const [isProjectIdCopied, setIsProjectIdCopied] = useToggle(false);
|
|
||||||
|
|
||||||
const { handleSubmit, control, reset } = useForm<FormData>({ resolver: yupResolver(formSchema) });
|
const { handleSubmit, control, reset } = useForm<FormData>({ resolver: yupResolver(formSchema) });
|
||||||
|
|
||||||
@@ -34,16 +32,6 @@ export const ProjectNameChangeSection = () => {
|
|||||||
}
|
}
|
||||||
}, [currentWorkspace]);
|
}, [currentWorkspace]);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
let timer: NodeJS.Timeout;
|
|
||||||
|
|
||||||
if (isProjectIdCopied) {
|
|
||||||
timer = setTimeout(() => setIsProjectIdCopied.off(), 2000);
|
|
||||||
}
|
|
||||||
|
|
||||||
return () => clearTimeout(timer);
|
|
||||||
}, [setIsProjectIdCopied]);
|
|
||||||
|
|
||||||
const onFormSubmit = async ({ name }: FormData) => {
|
const onFormSubmit = async ({ name }: FormData) => {
|
||||||
try {
|
try {
|
||||||
if (!currentWorkspace?.id) return;
|
if (!currentWorkspace?.id) return;
|
||||||
@@ -66,35 +54,28 @@ export const ProjectNameChangeSection = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const copyProjectIdToClipboard = () => {
|
|
||||||
navigator.clipboard.writeText(currentWorkspace?.id || "");
|
|
||||||
setIsProjectIdCopied.on();
|
|
||||||
|
|
||||||
createNotification({
|
|
||||||
text: "Copied Project ID to clipboard",
|
|
||||||
type: "success"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form
|
<form
|
||||||
onSubmit={handleSubmit(onFormSubmit)}
|
onSubmit={handleSubmit(onFormSubmit)}
|
||||||
className="mb-6 rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4"
|
className="mb-6 rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4"
|
||||||
>
|
>
|
||||||
<div className="flex justify-betweens">
|
<div className="justify-betweens flex">
|
||||||
<h2 className="text-xl font-semibold flex-1 text-mineshaft-100 mb-8">Project Name</h2>
|
<h2 className="mb-8 flex-1 text-xl font-semibold text-mineshaft-100">Project Name</h2>
|
||||||
<div>
|
<div className="space-x-2">
|
||||||
<Button
|
<CopyButton
|
||||||
colorSchema="secondary"
|
value={currentWorkspace?.slug || ""}
|
||||||
className="group relative"
|
hoverText="Click to project slug"
|
||||||
leftIcon={<FontAwesomeIcon icon={isProjectIdCopied ? faCheck : faCopy} />}
|
notificationText="Copied project slug to clipboard"
|
||||||
onClick={copyProjectIdToClipboard}
|
>
|
||||||
|
Copy Project Slug
|
||||||
|
</CopyButton>
|
||||||
|
<CopyButton
|
||||||
|
value={currentWorkspace?.id || ""}
|
||||||
|
hoverText="Click to project ID"
|
||||||
|
notificationText="Copied project ID to clipboard"
|
||||||
>
|
>
|
||||||
Copy Project ID
|
Copy Project ID
|
||||||
<span className="absolute -left-8 -top-20 hidden w-28 translate-y-full rounded-md bg-bunker-800 py-2 pl-3 text-center text-sm text-gray-400 group-hover:flex group-hover:animate-fadeIn">
|
</CopyButton>
|
||||||
Click to copy
|
|
||||||
</span>
|
|
||||||
</Button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user