summaryrefslogtreecommitdiff
path: root/web/src/components/CopyButton.tsx
diff options
context:
space:
mode:
authorJames Elliott <james-d-elliott@users.noreply.github.com>2023-10-27 20:24:13 +1100
committerJames Elliott <james-d-elliott@users.noreply.github.com>2024-03-04 20:28:24 +1100
commit87d2a3419d6f29db900bc1aeb4cf5d7769a15ce3 (patch)
treea4efff47cb7be04f9fb1ce344cb9e40f4096dee6 /web/src/components/CopyButton.tsx
parentc0dbdd97ab2ac580e3da07a0137dbc7a1b9c9b83 (diff)
feat(web): user one-time password preferences
This allows administrators to configure a list of Time-based One-Time Password parameters that users can pick from the web UI during registrations. Signed-off-by: James Elliott <james-d-elliott@users.noreply.github.com>
Diffstat (limited to 'web/src/components/CopyButton.tsx')
-rw-r--r--web/src/components/CopyButton.tsx80
1 files changed, 80 insertions, 0 deletions
diff --git a/web/src/components/CopyButton.tsx b/web/src/components/CopyButton.tsx
new file mode 100644
index 000000000..d74173d06
--- /dev/null
+++ b/web/src/components/CopyButton.tsx
@@ -0,0 +1,80 @@
+import React, { ReactNode, useState } from "react";
+
+import { Check, ContentCopy } from "@mui/icons-material";
+import { Button, CircularProgress, SxProps, Tooltip } from "@mui/material";
+
+export interface Props {
+ variant?: "contained" | "outlined" | "text";
+ tooltip: string;
+ children: ReactNode;
+ childrenCopied?: ReactNode;
+ value: string | null;
+ xs?: number;
+ msTimeoutCopying?: number;
+ msTimeoutCopied?: number;
+ sx?: SxProps;
+ fullWidth?: boolean;
+}
+
+const msTmeoutDefaultCopying = 500;
+const msTmeoutDefaultCopied = 2000;
+
+const CopyButton = function (props: Props) {
+ const [isCopied, setIsCopied] = useState(false);
+ const [isCopying, setIsCopying] = useState(false);
+ const msTimeoutCopying = props.msTimeoutCopying ? props.msTimeoutCopying : msTmeoutDefaultCopying;
+ const msTimeoutCopied = props.msTimeoutCopied ? props.msTimeoutCopied : msTmeoutDefaultCopied;
+
+ const handleCopyToClipboard = () => {
+ if (isCopied || !props.value || props.value === "") {
+ return;
+ }
+
+ (async (value: string) => {
+ setIsCopying(true);
+
+ await navigator.clipboard.writeText(value);
+
+ setTimeout(() => {
+ setIsCopying(false);
+ setIsCopied(true);
+ }, msTimeoutCopying);
+
+ setTimeout(() => {
+ setIsCopied(false);
+ }, msTimeoutCopied);
+ })(props.value);
+ };
+
+ return props.value === null || props.value === "" ? (
+ <Button
+ variant={props.variant ? props.variant : "outlined"}
+ color={isCopied ? "success" : "primary"}
+ disabled
+ sx={props.sx}
+ fullWidth={props.fullWidth}
+ startIcon={
+ isCopying ? <CircularProgress color="inherit" size={20} /> : isCopied ? <Check /> : <ContentCopy />
+ }
+ >
+ {isCopied && props.childrenCopied ? props.childrenCopied : props.children}
+ </Button>
+ ) : (
+ <Tooltip title={props.tooltip}>
+ <Button
+ variant={props.variant ? props.variant : "outlined"}
+ color={isCopied ? "success" : "primary"}
+ onClick={isCopying ? undefined : handleCopyToClipboard}
+ sx={props.sx}
+ fullWidth={props.fullWidth}
+ startIcon={
+ isCopying ? <CircularProgress color="inherit" size={20} /> : isCopied ? <Check /> : <ContentCopy />
+ }
+ >
+ {isCopied && props.childrenCopied ? props.childrenCopied : props.children}
+ </Button>
+ </Tooltip>
+ );
+};
+
+export default CopyButton;