<commit_before>import React from 'react';
import PropTypes from 'prop-types';
import { Controlled as CodeMirror } from 'react-codemirror2';
import classNames from 'classnames';
import defaultCodeMirrorOptions from '../defaultCodeMirrorOptions';
import ErrorDisplay from '../ErrorDisplay';
import LoadingIndicator from '../LoadingIndicator';

class CodeInput extends React.Component {
  static propTypes = {
    value: PropTypes.string.isRequired,
    onChange: PropTypes.func.isRequired,
    getPreviewContent: PropTypes.func.isRequired,
    mode: PropTypes.string.isRequired,
    onBlur: PropTypes.func,
    className: PropTypes.string,
    formControlClassName: PropTypes.string,
    lines: PropTypes.number,
    children: PropTypes.node,
  }

  static defaultProps = {
    className: null,
    formControlClassName: null,
    lines: null,
    children: null,
    onBlur: null,
  };

  constructor(props) {
    super(props);

    this.state = {
      previewing: false,
    };
  }

  onBeforeChange = (editor, data, value) => {
    this.props.onChange(value);
    this.setState({ previewContent: null });
  }

  editTabClicked = (event) => {
    event.preventDefault();
    this.setState({ previewing: false });
  }

  previewTabClicked = (event) => {
    event.preventDefault();
    this.setState({ previewing: true });

    if (this.state.previewContent == null) {
      this.setState({ previewContent: <LoadingIndicator /> });

      this.props.getPreviewContent(this.props.value).then((html) => {
        this.setState({
          previewContent: (
            <div dangerouslySetInnerHTML={{ __html: html }} />
          ),
        });
      }).catch(({ error }) => {
        this.setState({
          previewContent: (
            <ErrorDisplay graphQLError={error} />
          ),
        });
      });
    }
  }

  renderPreviewContent = () => (
    <div className="markdown-preview">
      {this.state.previewContent}
    </div>
  )

  renderContent = () => {
    if (this.state.previewing) {
      return this.renderPreviewContent();
    }

    return (
      <CodeMirror
        value={this.props.value}
        options={{
          ...defaultCodeMirrorOptions,
          lineNumbers: false,
          foldGutter: false,
          gutters: [],
          mode: this.props.mode,
        }}
        onBlur={this.props.onBlur}
        onBeforeChange={this.onBeforeChange}
      />
    );
  }

  render = () => (
    <div className={this.props.className}>
      <div
        className={classNames(
          `form-control p-0 codemirror-height-${this.props.lines || 10}`,
          this.props.formControlClassName,
        )}
        style={{ overflow: 'hidden' }}
      >
        <ul className="nav nav-pills bg-light p-1">
          <li className="nav-item">
            <a
              href="#"
              className={classNames('nav-link py-0 px-2', { active: !this.state.previewing })}
              onClick={this.editTabClicked}
            >
              Edit<commit_msg>Work around react-codemirror2's insistence on props being defined<commit_after>import React from 'react';
import PropTypes from 'prop-types';
import { Controlled as CodeMirror } from 'react-codemirror2';
import classNames from 'classnames';
import defaultCodeMirrorOptions from '../defaultCodeMirrorOptions';
import ErrorDisplay from '../ErrorDisplay';
import LoadingIndicator from '../LoadingIndicator';

class CodeInput extends React.Component {
  static propTypes = {
    value: PropTypes.string.isRequired,
    onChange: PropTypes.func.isRequired,
    getPreviewContent: PropTypes.func.isRequired,
    mode: PropTypes.string.isRequired,
    onBlur: PropTypes.func,
    className: PropTypes.string,
    formControlClassName: PropTypes.string,
    lines: PropTypes.number,
    children: PropTypes.node,
  }

  static defaultProps = {
    className: null,
    formControlClassName: null,
    lines: null,
    children: null,
    onBlur: null,
  };

  constructor(props) {
    super(props);

    this.state = {
      previewing: false,
    };
  }

  onBeforeChange = (editor, data, value) => {
    this.props.onChange(value);
    this.setState({ previewContent: null });
  }

  editTabClicked = (event) => {
    event.preventDefault();
    this.setState({ previewing: false });
  }

  previewTabClicked = (event) => {
    event.preventDefault();
    this.setState({ previewing: true });

    if (this.state.previewContent == null) {
      this.setState({ previewContent: <LoadingIndicator /> });

      this.props.getPreviewContent(this.props.value).then((html) => {
        this.setState({
          previewContent: (
            <div dangerouslySetInnerHTML={{ __html: html }} />
          ),
        });
      }).catch(({ error }) => {
        this.setState({
          previewContent: (
            <ErrorDisplay graphQLError={error} />
          ),
        });
      });
    }
  }

  renderPreviewContent = () => (
    <div className="markdown-preview">
      {this.state.previewContent}
    </div>
  )

  renderContent = () => {
    if (this.state.previewing) {
      return this.renderPreviewContent();
    }

    // react-codemirror2 doesn't want event handlers to be passed undefined
    const eventHandlers = {};
    if (this.props.onBlur) {
      eventHandlers.onBlur = this.props.onBlur;
    }

    return (
      <CodeMirror
        value={this.props.value}
        options={{
          ...defaultCodeMirrorOptions,
          lineNumbers: false,
          foldGutter: false,
          gutters: [],
          mode: this.props.mode,
        }}
        {...eventHandlers}
        onBeforeChange={this.onBeforeChange}
      />
    );
  }

  render = () => (
    <div className={this.props.className}>
      <div
        className={classNames(
          `form-control p-0 codemirror-height-${this.props.lines || 10}`,
          this.props.formControlClassName,
        )}
        style={{ overflow: 'hidden' }}
      >
        <ul className="nav nav-pills bg-light p-1">
          <li className="nav-item">
            <a
              href="#"
              className={classNames('nav-link py-0 px-2', { active: !this.state.previewing })}
              onClick={this.editTabClicked}
            >
              Edit
{'fraction_non_alphanumeric': 0.132764724814934, 'fraction_numerical': 0.002574831026713872, 'mean_word_length': 2.363095238095238, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 41, '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': '363893', 'n_tokens_mistral': 1799, 'n_tokens_neox': 1799, 'n_words': 347}