diff options
| author | James Elliott <james-d-elliott@users.noreply.github.com> | 2023-10-27 20:24:13 +1100 |
|---|---|---|
| committer | James Elliott <james-d-elliott@users.noreply.github.com> | 2024-03-04 20:28:24 +1100 |
| commit | 87d2a3419d6f29db900bc1aeb4cf5d7769a15ce3 (patch) | |
| tree | a4efff47cb7be04f9fb1ce344cb9e40f4096dee6 /web/src/components/CopyButton.tsx | |
| parent | c0dbdd97ab2ac580e3da07a0137dbc7a1b9c9b83 (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.tsx | 80 |
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; |
