Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
Notifier.jsx229 linesDownload Raw Back to helpers
1/////////////////////////////////////////////////////////////2//3// pgAdmin 4 - PostgreSQL Tools4//5// Copyright (C) 2013 - 2024, The pgAdmin Development Team6// This software is released under the PostgreSQL Licence7//8//////////////////////////////////////////////////////////////9 10import { SnackbarProvider, SnackbarContent } from 'notistack';11import { makeStyles } from '@mui/styles';12import {Box} from '@mui/material';13import CloseIcon from '@mui/icons-material/CloseRounded';14import { DefaultButton, PrimaryButton } from '../components/Buttons';15import HTMLReactParser from 'html-react-parser';16import CheckRoundedIcon from '@mui/icons-material/CheckRounded';17import PropTypes from 'prop-types';18import React, { useEffect } from 'react';19import { NotifierMessage, MESSAGE_TYPE } from '../components/FormComponents';20import CustomPropTypes from '../custom_prop_types';21import gettext from 'sources/gettext';22import _ from 'lodash';23import { useModal } from './ModalProvider';24import { parseApiError } from '../api_instance';25 26const AUTO_HIDE_DURATION = 3000;  // In milliseconds27 28export const FinalNotifyContent = React.forwardRef(({children}, ref) => {29  return <SnackbarContent style= {{ justifyContent: 'end', maxWidth: '700px' }} ref={ref}>{children}</SnackbarContent>;30});31FinalNotifyContent.displayName = 'FinalNotifyContent';32FinalNotifyContent.propTypes = {33  children: CustomPropTypes.children,34};35 36const useModalStyles = makeStyles((theme)=>({37  footer: {38    display: 'flex',39    justifyContent: 'flex-end',40    padding: '0.5rem',41    ...theme.mixins.panelBorder.top,42  },43  margin: {44    marginLeft: '0.25rem',45  },46}));47function AlertContent({text, confirm, okLabel=gettext('OK'), cancelLabel=gettext('Cancel'), onOkClick, onCancelClick}) {48  const classes = useModalStyles();49  return (50    <Box display="flex" flexDirection="column" height="100%">51      <Box flexGrow="1" p={2}>{HTMLReactParser(text)}</Box>52      <Box className={classes.footer}>53        {confirm &&54          <DefaultButton startIcon={<CloseIcon />} onClick={onCancelClick} >{cancelLabel}</DefaultButton>55        }56        <PrimaryButton className={classes.margin} startIcon={<CheckRoundedIcon />} onClick={onOkClick} autoFocus={true} >{okLabel}</PrimaryButton>57      </Box>58    </Box>59  );60}61AlertContent.propTypes = {62  text: PropTypes.string,63  confirm: PropTypes.bool,64  onOkClick: PropTypes.func,65  onCancelClick: PropTypes.func,66  okLabel: PropTypes.string,67  cancelLabel: PropTypes.string,68};69 70// This can be called from iframe,71// so need to separate the context to avoid hooks error72class SnackbarNotifier {73  constructor(snackbar) {74    this.snackbarObj = snackbar;75  }76 77  notify(content, autoHideDuration) {78    if (content) {79      let  options = {autoHideDuration, content:(key) => (80        <FinalNotifyContent>{React.cloneElement(content, {onClose:()=>{this.snackbarObj.closeSnackbar(key);}})}</FinalNotifyContent>81      )};82      options.content.displayName = 'content';83      this.snackbarObj.enqueueSnackbar(null, options);84    }85  }86 87  callNotify(msg, type, autoHideDuration) {88    this.notify(89      <NotifierMessage style={{maxWidth: '50vw'}} type={type} message={msg} closable={true} />,90      autoHideDuration91    );92  }93}94 95class Notifier {96  constructor(modal, snackbar) {97    this.modal = modal;98    this.snackbar = snackbar;99  }100 101  success(msg, autoHideDuration = AUTO_HIDE_DURATION) {102    this.snackbar.callNotify(msg, MESSAGE_TYPE.SUCCESS, autoHideDuration);103  }104 105  warning(msg, autoHideDuration = AUTO_HIDE_DURATION) {106    this.snackbar.callNotify(msg, MESSAGE_TYPE.WARNING, autoHideDuration);107  }108 109  info(msg, autoHideDuration = AUTO_HIDE_DURATION) {110    this.snackbar.callNotify(msg, MESSAGE_TYPE.INFO, autoHideDuration);111  }112 113  error(msg, autoHideDuration = AUTO_HIDE_DURATION) {114    this.snackbar.callNotify(msg, MESSAGE_TYPE.ERROR, autoHideDuration);115  }116 117  // proxy118  notify(...args) {119    this.snackbar.notify(...args);120  }121 122  pgRespErrorNotify(error, prefixMsg='') {123    if (error.response?.status === 410) {124      this.alert(gettext('Error: Object not found - %s.', error.response.statusText), parseApiError(error));125    } else {126      this.error(prefixMsg + ' ' + parseApiError(error));127    }128  }129 130  pgNotifier(type, error, promptmsg, onJSONResult) {131    let msg;132 133    if(!error.response) {134      msg = parseApiError(error);135      promptmsg = gettext('Connection Lost');136    } else if(error.response.headers['content-type'] == 'application/json') {137      let resp = error.response.data;138      if(resp.info == 'CRYPTKEY_MISSING') {139        let pgBrowser = window.pgAdmin.Browser;140        pgBrowser.set_master_password('', ()=> {141          if(onJSONResult && typeof(onJSONResult) == 'function') {142            onJSONResult('CRYPTKEY_SET');143          }144        }, ()=> {145          if(onJSONResult && typeof(onJSONResult) == 'function') {146            onJSONResult('CRYPTKEY_NOT_SET');147          }148        });149        return;150      } else if (resp.result != null && (!resp.errormsg || resp.errormsg == '') &&151        onJSONResult && typeof(onJSONResult) == 'function') {152        return onJSONResult(resp.result);153      }154      msg = _.escape(resp.result) || _.escape(resp.errormsg) || 'Unknown error';155    } else {156      if (type === 'error') {157        this.alert('Error', promptmsg);158      }159      return;160    }161    if(type == 'error-noalert' && onJSONResult && typeof(onJSONResult) == 'function') {162      return onJSONResult();163    }164    this.alert(promptmsg, msg.replace(new RegExp(/\r?\n/, 'g'), '<br />'));165    onJSONResult('ALERT_CALLED');166  }167 168  alert(title, text, onOkClick, okLabel=gettext('OK')) {169    /* Use this if you want to use pgAdmin global notifier.170    Or else, if you want to use modal inside iframe only then use ModalProvider eg- query tool */171    this.modal.alert(title, text, onOkClick, okLabel);172  }173 174  confirm(title, text, onOkClick, onCancelClick, okLabel=gettext('Yes'), cancelLabel=gettext('No')) {175    /* Use this if you want to use pgAdmin global notifier.176    Or else, if you want to use modal inside iframe only then use ModalProvider eg- query tool */177    this.modal.confirm(title, text, onOkClick, onCancelClick, okLabel, cancelLabel);178  }179 180  showModal(title, content, modalOptions) {181    this.modal.showModal(title, content, modalOptions);182  }183}184 185export function NotifierProvider({ pgAdmin, pgWindow, getInstance, children, onReady }) {186  const modal = useModal();187 188  useEffect(()=>{189    // if open in an iframe then use top pgAdmin190    if(window.self != window.top) {191      pgAdmin.Browser.notifier = new Notifier(modal, pgWindow.pgAdmin.Browser.notifier.snackbar);192      onReady?.();193      getInstance?.(pgAdmin.Browser.notifier);194    }195  }, []);196 197  // if open in a window, then create your own Snackbar198  if(window.self == window.top) {199    return (200      <SnackbarProvider201        maxSnack={30}202        anchorOrigin={{ horizontal: 'right', vertical: 'bottom' }}203        ref={(obj)=>{204          pgAdmin.Browser.notifier = new Notifier(modal, new SnackbarNotifier(obj));205          getInstance?.(pgAdmin.Browser.notifier);206          onReady?.();207        }}208      >209        {children}210      </SnackbarProvider>211    );212  }213  return (214    <>215      {children}216    </>217  );218}219 220NotifierProvider.propTypes = {221  pgAdmin: PropTypes.object,222  pgWindow: PropTypes.object,223  getInstance: PropTypes.func,224  children: CustomPropTypes.children,225  onReady: PropTypes.func,226};227 228export default Notifier;229 
codekingpro/portable-devtools · Team Ai