<commit_before>import isArray from 'lodash/isArray'
import isString from 'lodash/isString'
import map from 'lodash/map'
import React, { Component, cloneElement } from 'react'
import { Modal as ReactModal } from 'react-bootstrap-4/lib'

import _ from './intl'
import Button from './button'
import Icon from './icon'
import propTypes from './prop-types-decorator'
import Tooltip from './tooltip'
import {
  disable as disableShortcuts,
  enable as enableShortcuts
} from './shortcuts'

let instance

const modal = (content, onClose) => {
  if (!instance) {
    throw new Error('No modal instance.')
  } else if (instance.state.showModal) {
    throw new Error('Other modal still open.')
  }
  instance.setState({ content, onClose, showModal: true }, disableShortcuts)
}

@propTypes({
  buttons: propTypes.arrayOf(propTypes.shape({
    btnStyle: propTypes.string,
    icon: propTypes.string,
    label: propTypes.string.isRequired,
    tooltip: propTypes.node,
    value: propTypes.any
  })).isRequired,
  children: propTypes.node.isRequired,
  icon: propTypes.string,
  title: propTypes.node.isRequired
})
class GenericModal extends Component {
  _getBodyValue = () => {
    const { body } = this.refs
    if (body !== undefined) {
      return body.getWrappedInstance === undefined
        ? body.value
        : body.getWrappedInstance().value
    }
  }

  _resolve = (value = this._getBodyValue()) => {
    this.props.resolve(value)
    instance.close()
  }

  _reject = () => {
    this.props.reject()
    instance.close()
  }

  render () {
    const { Body, Footer, Header, Title } = ReactModal

    const {
      buttons,
      icon,
      title
    } = this.props

    const body = _addRef(this.props.children, 'body')

    return <div>
      <Header closeButton>
        <Title>
          {icon
            ? <span><Icon icon={icon} /> {title}</span>
            : title
          }
        </Title>
      </Header>
      <Body>
        {body}
      </Body>
      <Footer>
        {map(buttons, ({
          label,
          tooltip,
          value,
          icon,
          ...props
        }) => {
          const button = <Button
            onClick={() => this._resolve(value)}
            key={value}
            {...props}
          >
            {icon !== undefined && <Icon icon={icon} fixedWidth />}
            {label}
          </Button>
          return <span>
            {tooltip !== undefined
              ? <Tooltip content={tooltip}>{button}</Tooltip>
              : button
            }
            {' '}
          </span>
        })}
        {this.props.reject !== undefined &&
          <Button onClick={this._reject} >
            {_('genericCancel')}
          </Button>
        }
      </Footer>
    </div>
  }
}

const ALERT_BUTTONS = [ { label: _('alertOk'), value: 'ok' } ]

export const alert = (title, body) => (
  new Promise(resolve => {
    modal(
      <GenericModal
        buttons={ALERT_BUTTONS}
        resolve={resolve}
        title={title}
      >
        {body}
      </GenericModal>
    )
  })
)

const _addRef = (component, ref) => {
  if (isString(component) || isArray(component)) {
    return component
  }

  try {
    return cloneElement(component, { ref })
  } catch (_) {} // Stateless component.
  return component
}

const CONFIRM_BUTTONS = [ { btnStyle: 'primary', label: _('confirmOk') } ]

export const confirm = ({
  body,
  icon = 'alarm',
  title
}) => (
  chooseAction({
    body,
    buttons: CONFIRM_BUTTONS,
    icon,
    title
  })<commit_msg>fix(modal/alert): resolve on close (#2224)<commit_after>import isArray from 'lodash/isArray'
import isString from 'lodash/isString'
import map from 'lodash/map'
import React, { Component, cloneElement } from 'react'
import { Modal as ReactModal } from 'react-bootstrap-4/lib'

import _ from './intl'
import Button from './button'
import Icon from './icon'
import propTypes from './prop-types-decorator'
import Tooltip from './tooltip'
import {
  disable as disableShortcuts,
  enable as enableShortcuts
} from './shortcuts'

let instance

const modal = (content, onClose) => {
  if (!instance) {
    throw new Error('No modal instance.')
  } else if (instance.state.showModal) {
    throw new Error('Other modal still open.')
  }
  instance.setState({ content, onClose, showModal: true }, disableShortcuts)
}

@propTypes({
  buttons: propTypes.arrayOf(propTypes.shape({
    btnStyle: propTypes.string,
    icon: propTypes.string,
    label: propTypes.string.isRequired,
    tooltip: propTypes.node,
    value: propTypes.any
  })).isRequired,
  children: propTypes.node.isRequired,
  icon: propTypes.string,
  title: propTypes.node.isRequired
})
class GenericModal extends Component {
  _getBodyValue = () => {
    const { body } = this.refs
    if (body !== undefined) {
      return body.getWrappedInstance === undefined
        ? body.value
        : body.getWrappedInstance().value
    }
  }

  _resolve = (value = this._getBodyValue()) => {
    this.props.resolve(value)
    instance.close()
  }

  _reject = () => {
    this.props.reject()
    instance.close()
  }

  render () {
    const { Body, Footer, Header, Title } = ReactModal

    const {
      buttons,
      icon,
      title
    } = this.props

    const body = _addRef(this.props.children, 'body')

    return <div>
      <Header closeButton>
        <Title>
          {icon
            ? <span><Icon icon={icon} /> {title}</span>
            : title
          }
        </Title>
      </Header>
      <Body>
        {body}
      </Body>
      <Footer>
        {map(buttons, ({
          label,
          tooltip,
          value,
          icon,
          ...props
        }) => {
          const button = <Button
            onClick={() => this._resolve(value)}
            key={value}
            {...props}
          >
            {icon !== undefined && <Icon icon={icon} fixedWidth />}
            {label}
          </Button>
          return <span>
            {tooltip !== undefined
              ? <Tooltip content={tooltip}>{button}</Tooltip>
              : button
            }
            {' '}
          </span>
        })}
        {this.props.reject !== undefined &&
          <Button onClick={this._reject} >
            {_('genericCancel')}
          </Button>
        }
      </Footer>
    </div>
  }
}

const ALERT_BUTTONS = [ { label: _('alertOk'), value: 'ok' } ]

export const alert = (title, body) => (
  new Promise(resolve => {
    modal(
      <GenericModal
        buttons={ALERT_BUTTONS}
        resolve={resolve}
        title={title}
      >
        {body}
      </GenericModal>,
      resolve
    )
  })
)

const _addRef = (component, ref) => {
  if (isString(component) || isArray(component)) {
    return component
  }

  try {
    return cloneElement(component, { ref })
  } catch (_) {} // Stateless component.
  return component
}

const CONFIRM_BUTTONS = [ { btnStyle: 'primary', label: _('confirmOk') } ]

export const confirm = ({
  body,
  icon = 'alarm',
  title
}) => (
  chooseAction({
    body,
    buttons: CONFIRM_BUTTONS,
    icon,
    title
  })
{'fraction_non_alphanumeric': 0.13849632560768796, 'fraction_numerical': 0.0008479366873940079, 'mean_word_length': 2.124503311258278, 'pattern_counts': {'":': 0, '<': 51, '<?xml version=': 0, '>': 71, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6395436', 'n_tokens_mistral': 2159, 'n_tokens_neox': 2142, 'n_words': 503}