/////////////////////////////////////////////////////////////
//
// pgAdmin 4 - PostgreSQL Tools
//
// Copyright (C) 2013 - 2022, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////
import { Box, Dialog, DialogContent, DialogTitle, makeStyles, Paper } from '@material-ui/core';
import React, { useState } from 'react';
import clsx from 'clsx';
import { getEpoch } from 'sources/utils';
import { DefaultButton, PgIconButton, PrimaryButton } from '../components/Buttons';
import Draggable from 'react-draggable';
import CloseIcon from '@material-ui/icons/CloseRounded';
import CustomPropTypes from '../custom_prop_types';
import PropTypes from 'prop-types';
import gettext from 'sources/gettext';
import HTMLReactParser from 'html-react-parser';
import CheckRoundedIcon from '@material-ui/icons/CheckRounded';
import { Rnd } from 'react-rnd';
import { ExpandDialogIcon, MinimizeDialogIcon } from '../components/ExternalIcon';
export const ModalContext = React.createContext({});
const MIN_HEIGHT = 190;
const MIN_WIDTH = 500;
export function useModal() {
return React.useContext(ModalContext);
}
const useAlertStyles = makeStyles((theme) => ({
footer: {
display: 'flex',
justifyContent: 'flex-end',
padding: '0.5rem',
...theme.mixins.panelBorder.top,
},
margin: {
marginLeft: '0.25rem',
}
}));
function AlertContent({ text, confirm, okLabel = gettext('OK'), cancelLabel = gettext('Cancel'), onOkClick, onCancelClick }) {
const classes = useAlertStyles();
return (
{typeof (text) == 'string' ? HTMLReactParser(text) : text}
{confirm &&
} onClick={onCancelClick} >{cancelLabel}
}
} onClick={onOkClick} autoFocus={true} >{okLabel}
);
}
AlertContent.propTypes = {
text: PropTypes.string,
confirm: PropTypes.bool,
onOkClick: PropTypes.func,
onCancelClick: PropTypes.func,
okLabel: PropTypes.string,
cancelLabel: PropTypes.string,
};
function alert(title, text, onOkClick, okLabel = gettext('OK')) {
// bind the modal provider before calling
this.showModal(title, (closeModal) => {
const onOkClickClose = () => {
onOkClick && onOkClick();
closeModal();
};
return (
);
});
}
function confirm(title, text, onOkClick, onCancelClick, okLabel = gettext('Yes'), cancelLabel = gettext('No')) {
// bind the modal provider before calling
this.showModal(title, (closeModal) => {
const onCancelClickClose = () => {
onCancelClick && onCancelClick();
closeModal();
};
const onOkClickClose = () => {
onOkClick && onOkClick();
closeModal();
};
return (
);
});
}
export default function ModalProvider({ children }) {
const [modals, setModals] = React.useState([]);
const showModal = (title, content, modalOptions) => {
let id = getEpoch().toString() + Math.random();
setModals((prev) => [...prev, {
id: id,
title: title,
content: content,
...modalOptions,
}]);
};
const closeModal = (id) => {
setModals((prev) => {
return prev.filter((o) => o.id != id);
});
};
const fullScreenModal = (fullScreen) => {
setModals((prev) => [...prev, {
fullScreen: fullScreen,
}]);
};
const modalContextBase = {
showModal: showModal,
closeModal: closeModal,
fullScreenModal: fullScreenModal
};
const modalContext = React.useMemo(() => ({
...modalContextBase,
confirm: confirm.bind(modalContextBase),
alert: alert.bind(modalContextBase)
}), []);
return (
{children}
{modals.map((modalOptions, i) => (
))}
);
}
ModalProvider.propTypes = {
children: CustomPropTypes.children,
};
const dialogStyle = makeStyles((theme) => ({
dialog: {
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
border: '1px solid ' + theme.otherVars.inputBorderColor,
borderRadius: theme.shape.borderRadius,
},
fullScreen: {
transform: 'none !important'
}
}));
function PaperComponent({minHeight, minWidth, ...props}) {
let classes = dialogStyle();
let [dialogPosition, setDialogPosition] = useState(null);
let resizeable = props.isresizeable == 'true' ? true : false;
const setEnableResizing = () => {
return props.isfullscreen == 'true' ? false : resizeable;
};
const setConditionalPosition = () => {
return props.isfullscreen == 'true' ? { x: 0, y: 0 } : dialogPosition && { x: dialogPosition.x, y: dialogPosition.y };
};
const y_position = window.innerHeight*0.02; // 2% of total height
const x_position = props.width ? (window.innerWidth/2) - (props.width/2) : (window.innerWidth/2) - (MIN_WIDTH/2);
return (
props.isresizeable == 'true' ?
{
if (props.isfullscreen !== 'true') {
setDialogPosition({
...position,
});
}
}}
onResize={(e, direction, ref, delta, position) => {
setDialogPosition({
...position,
});
}}
dragHandleClassName="modal-drag-area"
>
:
);
}
PaperComponent.propTypes = {
isfullscreen: PropTypes.string,
isresizeable: PropTypes.string,
width: PropTypes.number,
height: PropTypes.number,
minWidth: PropTypes.number,
minHeight: PropTypes.number,
};
export const useModalStyles = makeStyles((theme) => ({
container: {
backgroundColor: theme.palette.background.default
},
titleBar: {
display: 'flex',
flexGrow: 1
},
title: {
flexGrow: 1
},
icon: {
fill: 'currentColor',
width: '1em',
height: '1em',
display: 'inline-block',
fontSize: '1.5rem',
transition: 'none',
flexShrink: 0,
userSelect: 'none',
},
footer: {
display: 'flex',
justifyContent: 'flex-end',
padding: '0.5rem',
...theme.mixins.panelBorder?.top,
},
margin: {
marginLeft: '0.25rem',
},
iconButtonStyle: {
marginLeft: 'auto',
marginRight: '4px'
}
}));
function ModalContainer({ id, title, content, dialogHeight, dialogWidth, onClose, fullScreen = false, isFullWidth = false, showFullScreen = false, isResizeable = false, minHeight = MIN_HEIGHT, minWidth = MIN_WIDTH }) {
let useModalRef = useModal();
const classes = useModalStyles();
let closeModal = (_e, reason) => {
useModalRef.closeModal(id);
if(reason == 'escapeKeyDown') {
onClose?.();
}
};
const [isfullScreen, setIsFullScreen] = useState(fullScreen);
return (
);
}
ModalContainer.propTypes = {
id: PropTypes.string,
title: CustomPropTypes.children,
content: PropTypes.func,
fullScreen: PropTypes.bool,
maxWidth: PropTypes.string,
isFullWidth: PropTypes.bool,
showFullScreen: PropTypes.bool,
isResizeable: PropTypes.bool,
dialogHeight: PropTypes.number,
dialogWidth: PropTypes.number,
onClose: PropTypes.func,
minWidth: PropTypes.number,
minHeight: PropTypes.number,
};