github.com/treeverse/lakefs@v1.24.1-0.20240520134607-95648127bfb0/webui/src/lib/components/modals.tsx (about) 1 import React, {FC, useMemo, useState, ReactNode, MouseEventHandler, useContext} from "react"; 2 3 import Modal from "react-bootstrap/Modal"; 4 import Button from "react-bootstrap/Button"; 5 import Tooltip from "react-bootstrap/Tooltip"; 6 import {OverlayTrigger} from "react-bootstrap"; 7 import { ButtonVariant } from "react-bootstrap/esm/types"; 8 import { GetUserEmailByIdContext } from "../../pages/auth/users"; 9 10 interface ConfirmationModalProps { 11 show: boolean; 12 onHide: () => void; 13 msg: ReactNode; 14 onConfirm: MouseEventHandler<HTMLElement>; 15 variant: ButtonVariant; 16 } 17 18 interface ConfirmationButtonProps { 19 msg: ReactNode; 20 onConfirm: (hide: () => void) => void; 21 variant: ButtonVariant; 22 modalVariant?: ButtonVariant; 23 size?: 'sm' | 'lg'; 24 disabled?: boolean; 25 tooltip?: ReactNode; 26 children: ReactNode; 27 } 28 29 // Extend the ConfirmationButtonProps, but omit the msg property, 30 // so we can extend it for this use case 31 interface ConfirmationButtonWithContextProps extends Omit<ConfirmationButtonProps, "msg"> { 32 msg: ReactNode | ((email: string) => ReactNode); 33 userId: string; 34 } 35 export const ConfirmationModal: FC<ConfirmationModalProps> = ({ show, onHide, msg, onConfirm, variant = "danger" }) => { 36 return ( 37 <Modal show={show} onHide={onHide}> 38 <Modal.Header> 39 <Modal.Title>Confirmation</Modal.Title> 40 </Modal.Header> 41 <Modal.Body> 42 {msg} 43 </Modal.Body> 44 <Modal.Footer> 45 <Button variant={variant} onClick={onConfirm}>Yes</Button> 46 <Button variant="secondary" onClick={onHide}>Cancel</Button> 47 </Modal.Footer> 48 </Modal> 49 ); 50 }; 51 52 export const ConfirmationButtonWithContext: FC<ConfirmationButtonWithContextProps> = ({ userId, msg, onConfirm, variant, modalVariant, size, disabled = false, tooltip = null, children }) => { 53 const getUserEmailById = useContext(GetUserEmailByIdContext); 54 const email = useMemo(() => getUserEmailById(userId), [userId, getUserEmailById]); 55 56 let msgNode: ReactNode; 57 if (typeof msg === "function") { 58 msgNode = msg(email); 59 } else { 60 msgNode = msg; 61 } 62 63 return ( 64 <ConfirmationButton 65 msg={msgNode} 66 onConfirm={onConfirm} 67 variant={variant} 68 modalVariant={modalVariant} 69 size={size} 70 disabled={disabled} 71 tooltip={tooltip} 72 >{children}</ConfirmationButton> 73 ); 74 } 75 76 77 export const ConfirmationButton: FC<ConfirmationButtonProps> = ({ msg, onConfirm, variant, modalVariant = "danger", size, disabled = false, tooltip = null, children }) => { 78 const [show, setShow] = useState(false); 79 let btn = <Button variant={variant} size={size} disabled={disabled} onClick={() => setShow(true)}>{children}</Button>; 80 if (tooltip !== null) { 81 btn = ( 82 <OverlayTrigger placement="bottom" overlay={<Tooltip id="confirmation-tooltip">{tooltip}</Tooltip>}> 83 {btn} 84 </OverlayTrigger> 85 ); 86 } 87 88 const hide = () => setShow(false); 89 90 return ( 91 <> 92 <ConfirmationModal 93 show={show} 94 variant={modalVariant} 95 onConfirm={() => { 96 onConfirm(hide) 97 }} 98 onHide={hide} 99 msg={msg} 100 /> 101 {btn} 102 </> 103 ); 104 };