Enhances the modal provider to make it more reusable.

This commit is contained in:
Aditya Toshniwal 2022-02-23 14:27:48 +05:30 committed by Akshay Joshi
parent 0cd67b15cb
commit 44b2f49839
2 changed files with 103 additions and 80 deletions

View File

@ -7,21 +7,88 @@
//
//////////////////////////////////////////////////////////////
import { Box, Dialog, DialogContent, DialogTitle, Paper } from '@material-ui/core';
import { Box, Dialog, DialogContent, DialogTitle, makeStyles, Paper } from '@material-ui/core';
import React from 'react';
import {getEpoch} from 'sources/utils';
import { PgIconButton } from '../components/Buttons';
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 Theme from '../Theme';
import HTMLReactParser from 'html-react-parser';
import CheckRoundedIcon from '@material-ui/icons/CheckRounded';
const ModalContext = React.createContext({});
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 (
<Box display="flex" flexDirection="column" height="100%">
<Box flexGrow="1" p={2}>{typeof(text) == 'string' ? HTMLReactParser(text) : text}</Box>
<Box className={classes.footer}>
{confirm &&
<DefaultButton startIcon={<CloseIcon />} onClick={onCancelClick} >{cancelLabel}</DefaultButton>
}
<PrimaryButton className={classes.margin} startIcon={<CheckRoundedIcon />} onClick={onOkClick} autoFocus={true} >{okLabel}</PrimaryButton>
</Box>
</Box>
);
}
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 (
<AlertContent text={text} onOkClick={onOkClickClose} okLabel={okLabel} />
);
});
}
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 (
<AlertContent text={text} confirm onOkClick={onOkClickClose} onCancelClick={onCancelClickClose} okLabel={okLabel} cancelLabel={cancelLabel}/>
);
});
}
export default function ModalProvider({children}) {
const [modals, setModals] = React.useState([]);
@ -40,9 +107,14 @@ export default function ModalProvider({children}) {
return prev.filter((o)=>o.id!=id);
});
};
const modalContext = React.useMemo(()=>({
const modalContextBase = {
showModal: showModal,
closeModal: closeModal,
};
const modalContext = React.useMemo(()=>({
...modalContextBase,
confirm: confirm.bind(modalContextBase),
alert: alert.bind(modalContextBase)
}), []);
return (
<ModalContext.Provider value={modalContext}>
@ -70,20 +142,22 @@ function ModalContainer({id, title, content}) {
let useModalRef = useModal();
let closeModal = ()=>useModalRef.closeModal(id);
return (
<Dialog
open={true}
onClose={closeModal}
PaperComponent={PaperComponent}
disableBackdropClick
>
<DialogTitle>
<Box marginRight="0.25rem">{title}</Box>
<Box marginLeft="auto"><PgIconButton title={gettext('Close')} icon={<CloseIcon />} size="xs" noBorder onClick={closeModal}/></Box>
</DialogTitle>
<DialogContent>
{content(closeModal)}
</DialogContent>
</Dialog>
<Theme>
<Dialog
open={true}
onClose={closeModal}
PaperComponent={PaperComponent}
disableBackdropClick
>
<DialogTitle>
<Box marginRight="0.25rem">{title}</Box>
<Box marginLeft="auto"><PgIconButton title={gettext('Close')} icon={<CloseIcon />} size="xs" noBorder onClick={closeModal}/></Box>
</DialogTitle>
<DialogContent>
{content(closeModal)}
</DialogContent>
</Dialog>
</Theme>
);
}
ModalContainer.propTypes = {

View File

@ -17,13 +17,6 @@ import gettext from 'sources/gettext';
import _ from 'lodash';
import pgWindow from 'sources/window';
import ModalProvider, { useModal } from './ModalProvider';
import { DefaultButton, PrimaryButton } from '../components/Buttons';
import { Box } from '@material-ui/core';
import { makeStyles } from '@material-ui/styles';
import HTMLReactParse from 'html-react-parser';
import CloseIcon from '@material-ui/icons/CloseRounded';
import CheckRoundedIcon from '@material-ui/icons/CheckRounded';
import PropTypes from 'prop-types';
const AUTO_HIDE_DURATION = 3000; // In milliseconds
@ -83,40 +76,6 @@ FinalNotifyContent.propTypes = {
children: CustomPropTypes.children,
};
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 (
<Box display="flex" flexDirection="column" height="100%">
<Box flexGrow="1" p={2}>{typeof(text) == 'string' ? HTMLReactParse(text) : text}</Box>
<Box className={classes.footer}>
{confirm &&
<DefaultButton startIcon={<CloseIcon />} onClick={onCancelClick} >{cancelLabel}</DefaultButton>
}
<PrimaryButton className={classes.margin} startIcon={<CheckRoundedIcon />} onClick={onOkClick} autoFocus={true} >{okLabel}</PrimaryButton>
</Box>
</Box>
);
}
AlertContent.propTypes = {
text: PropTypes.string,
confirm: PropTypes.bool,
onOkClick: PropTypes.func,
onCancelClick: PropTypes.func,
okLabel: PropTypes.string,
cancelLabel: PropTypes.string,
};
var Notifier = {
success(msg, autoHideDuration = AUTO_HIDE_DURATION) {
this._callNotify(msg, MESSAGE_TYPE.SUCCESS, autoHideDuration);
@ -221,37 +180,27 @@ var Notifier = {
this.alert(promptmsg, msg.replace(new RegExp(/\r?\n/, 'g'), '<br />'));
},
alert: (title, text, onOkClick, okLabel=gettext('OK'))=>{
/* Use this if you want to use pgAdmin global notifier.
Or else, if you want to use modal inside iframe only then use ModalProvider eg- query tool */
if(!modalInitialized) {
initializeModalProvider();
}
modalRef.showModal(title, (closeModal)=>{
const onOkClickClose = ()=>{
onOkClick && onOkClick();
closeModal();
};
return (
<AlertContent text={text} onOkClick={onOkClickClose} okLabel={okLabel} />
);
});
modalRef.alert(title, text, onOkClick, okLabel);
},
confirm: (title, text, onOkClick, onCancelClick, okLabel=gettext('Yes'), cancelLabel=gettext('No'))=>{
/* Use this if you want to use pgAdmin global notifier.
Or else, if you want to use modal inside iframe only then use ModalProvider eg- query tool */
if(!modalInitialized) {
initializeModalProvider();
}
modalRef.showModal(title, (closeModal)=>{
const onCancelClickClose = ()=>{
onCancelClick && onCancelClick();
closeModal();
};
const onOkClickClose = ()=>{
onOkClick && onOkClick();
closeModal();
};
return (
<AlertContent text={text} confirm onOkClick={onOkClickClose} onCancelClick={onCancelClickClose} okLabel={okLabel} cancelLabel={cancelLabel}/>
);
});
modalRef.confirm(title, text, onOkClick, onCancelClick, okLabel, cancelLabel);
},
showModal(title, content) {
if(!modalInitialized) {
initializeModalProvider();
}
modalRef.showModal(title, content);
}
};
if(window.frameElement) {