diff --git a/messages/en-US.json b/messages/en-US.json index 6864ef489..760a42a24 100644 --- a/messages/en-US.json +++ b/messages/en-US.json @@ -2397,6 +2397,7 @@ "exportBlueprintTitle": "Export Blueprint", "exportBlueprintDescription": "Download a blueprint YAML snippet for \"{name}\" that can be applied to recreate this resource.", "exportBlueprintError": "Failed to generate blueprint", + "copy": "Copy", "download": "Download", "searchBlueprintProgress": "Search blueprints...", "appliedAt": "Applied At", diff --git a/src/components/ExportBlueprintModal.tsx b/src/components/ExportBlueprintModal.tsx index d6ad61440..0e768a086 100644 --- a/src/components/ExportBlueprintModal.tsx +++ b/src/components/ExportBlueprintModal.tsx @@ -17,7 +17,7 @@ import { useEnvContext } from "@app/hooks/useEnvContext"; import { toast } from "@app/hooks/useToast"; import { createApiClient, formatAxiosError } from "@app/lib/api"; import { cn } from "@app/lib/cn"; -import { Download, Loader2 } from "lucide-react"; +import { Check, Copy, Download, Loader2 } from "lucide-react"; import { useTranslations } from "next-intl"; type ExportBlueprintModalProps = { @@ -40,6 +40,7 @@ export default function ExportBlueprintModal({ const [loading, setLoading] = useState(false); const [contents, setContents] = useState(null); const [fileName, setFileName] = useState(resourceName); + const [copied, setCopied] = useState(false); useEffect(() => { if (!open) { @@ -69,6 +70,20 @@ export default function ExportBlueprintModal({ // eslint-disable-next-line react-hooks/exhaustive-deps }, [open, endpoint]); + async function handleCopy() { + if (!contents) { + return; + } + + try { + await navigator.clipboard.writeText(contents); + setCopied(true); + setTimeout(() => setCopied(false), 2000); + } catch (err) { + console.error(t("copyTextFailed"), err); + } + } + function handleDownload() { if (!contents) { return; @@ -124,6 +139,18 @@ export default function ExportBlueprintModal({ +