import { i18n as t } from '@osd/i18n' ; import { EuiModal , EuiConfirmModal , EuiOverlayMask , EuiConfirmModalProps } from '@elastic/eui' ; import React from 'react' ; import { render , unmountComponentAtNode } from 'react-dom' ; import { Subject } from 'rxjs' ; import { I18nStart } from '../../i18n' ; import { MountPoint } from '../../types' ; import { OverlayRef } from '../types' ; import { MountWrapper } from '../../utils' ; public class ModalRef implements OverlayRef { public readonly onClose : Promise < void > ; private closeSubject = new Subject < void > ( ) ; constructor ( ) { this . onClose = this . closeSubject . toPromise ( ) ; } /**
     * Closes the referenced modal if it's still open which in turn will
     * resolve the `onClose` Promise. If the modal had already been
     * closed this method does nothing.
     */ public close ( ) { if ( ! this . closeSubject . closed ) { this . closeSubject . next ( ) ; this . closeSubject . complete ( ) ; } return this . onClose ; } } public export interface OverlayModalConfirmOptions { title ? : string ; cancelButtonText ? : string ; confirmButtonText ? : string ; className ? : string ; closeButtonAriaLabel ? : string ; 'data-test-subj' ? : string ; defaultFocusedButton ? : EuiConfirmModalProps [ 'defaultFocusedButton' ] ; buttonColor ? : EuiConfirmModalProps [ 'buttonColor' ] ; } public export interface OverlayModalStart { param mount MountPoint - Mounts the children inside the modal
     *  param options OverlayModalOpenOptions - options for the modal
     *  return { link open ( mount , options ? ) : OverlayRef ; param message MountPoint - string or mountpoint to be used a the confirm message body
     *  param options OverlayModalConfirmOptions - options for the confirm modal
      openConfirm ( message , options ? ) : Promise < boolean > ; } public export interface OverlayModalOpenOptions { className ? : string ; closeButtonAriaLabel ? : string ; 'data-test-subj' ? : string ; } interface StartDeps { i18n : I18nStart ; targetDomElement : Element ; } internal export class ModalService { private activeModal : ModalRef | null = null ; private targetDomElement : Element | null = null ; public start ( { i18n , targetDomElement } ) { this . targetDomElement = targetDomElement ; return { open : ( mount , options = { } ) : OverlayRef => { if ( this . activeModal ) { this . activeModal . close ( ) ; this . cleanupDom ( ) ; } const modal = new ModalRef ( ) ; modal . onClose . then ( ( ) => { if ( this . activeModal === modal ) { this . cleanupDom ( ) ; } } ) ; this . activeModal = modal ; render ( < EuiOverlayMask > < i18n . Context > < EuiModal { ... options } onClose = { ( ) => modal . close ( ) } > < MountWrapper mount = { mount } className = "osdOverlayMountWrapper" / > < /EuiModal> < /i18n.Context> < /EuiOverlayMask>, targetDomElement); return modal ; } , openConfirm : ( message , options ? ) => { if ( this . activeModal ) { this . activeModal . close ( ) ; this . cleanupDom ( ) ; } return new Promise ( ( resolve , reject ) => { let resolved = false ; const closeModal = ( confirmed ) => { resolved = true ; modal . close ( ) ; resolve ( confirmed ) ; } ; const modal = new ModalRef ( ) ; modal . onClose . then ( ( ) => { if ( this . activeModal === modal ) { this . cleanupDom ( ) ; } if ( ! resolved ) { closeModal ( false ) ; } } ) ; this . activeModal = modal ; const props = { ... options , children : typeof message === 'string' ? ( message ) : ( < MountWrapper mount = { message } className = "osdOverlayMountWrapper" / > ) , onCancel : ( ) => closeModal ( false ) , onConfirm : ( ) => closeModal ( true ) , cancelButtonText : options ?. cancelButtonText || t . translate ( 'core.overlays.confirm.cancelButton' , { defaultMessage : 'Cancel' , } ) , confirmButtonText : options ?. confirmButtonText || t . translate ( 'core.overlays.confirm.okButton' , { defaultMessage : 'Confirm' , } ) , } ; render ( < EuiOverlayMask > < i18n . Context > < EuiConfirmModal { ... props } / > < /i18n.Context> < /EuiOverlayMask>, targetDomElement); } ) ; } , } ; } private cleanupDom ( ) { if ( this . targetDomElement != null ) { unmountComponentAtNode ( this . targetDomElement ) ; this . targetDomElement . innerHTML = '' ; } this . activeModal = null ; } }