<commit_before>import React from 'react'
import PropTypes from 'prop-types'
import CopyToClipboard from 'react-copy-to-clipboard'
import JSONPretty from 'react-json-pretty'
import Button from 'react-bootstrap/lib/Button'
import Modal from 'react-bootstrap/lib/Modal'

import {withSpinner} from '../shared/Spinner'

import FetchPonyfill from 'fetch-ponyfill'
const fetch = FetchPonyfill().fetch

/**
 * Button that reveals a backend resouce at 'url' when clicked.
 *
 * Used to show the underlying JSON that a view was rendered with OR for
 * showing a related resource, eg. an anchor's server.toml file.
 */
const BackendResourceBadgeButton = ({handleClickFn, label, url}) => (
  <a
    className="backend-resource-badge-button"
    href={url}
    onClick={handleClickFn}
  >
    {label}
  </a>
)

BackendResourceBadgeButton.propTypes = {
  handleClickFn: PropTypes.func.isRequired,
  label: PropTypes.string.isRequired,
  url: PropTypes.string.isRequired,
}

class ClipboardCopyButton extends React.Component {
  state = {copied: false}

  constructor(props, context) {
    super(props, context)
    this.handleClickCopy = this.handleClickCopy.bind(this)
  }

  handleClickCopy() {
    this.setState({copied: true})
  }

  render() {
    return (
      <CopyToClipboard text={this.props.text} onCopy={this.handleClickCopy}>
        <span>
          <Button
            style={{backgroundColor: '#08b5e5', color: 'white', border: 0}}
          >
            Copy
          </Button>
          {this.state.copied && <span style={{marginLeft: 5}}>Copied!</span>}
        </span>
      </CopyToClipboard>
    )
  }
}

ClipboardCopyButton.propTypes = {
  text: PropTypes.string.isRequired,
}

const ResourceModalBody = ({handleCloseFn, isJson, show, text, url}) => (
  <div>
    <div>
      <ClipboardCopyButton text={text} />
      <Button
        bsSize="sm"
        style={{float: 'right', backgroundColor: '#96a2b4'}}
        onClick={handleCloseFn}
        aria-label="Close"
      >
        <span aria-hidden="true">&times;</span>
      </Button>
    </div>
    <div style={{marginTop: 20, marginBottom: 20, wordBreak: 'break-all'}}>
      <a href={url} target="_blank">
        {url}
      </a>
    </div>
    <div>
      {isJson ? <JSONPretty id="json-pretty" json={text} /> : <pre>{text}</pre>}
    </div>
  </div>
)

const ResourceModalBodyWithSpinner = withSpinner()(ResourceModalBody)

const ResourceModal = props => (
  <Modal show={props.show} onHide={props.handleCloseFn}>
    <Modal.Body style={{backgroundColor: '#383f4b'}}>
      <ResourceModalBodyWithSpinner {...props} />
    </Modal.Body>
  </Modal>
)

ResourceModal.propTypes = {
  handleCloseFn: PropTypes.func.isRequired,
  isJson: PropTypes.bool.isRequired,
  show: PropTypes.bool.isRequired,
  text: PropTypes.string.isRequired,
  url: PropTypes.string.isRequired,
}

class ResourceModalContainer extends React.Component {
  state = {
    fetchFailed: false,
    isJson: false,
    isLoading: true,
    show: false,
    text: '',
  }

  isJsonResponse(rsp) {
    return (
      rsp.headers.has('content-type') &&
      rsp.headers.get('content-type').indexOf('json') !== -1<commit_msg>mark any url ending in .json as JSON so the backend modal pretty formats it<commit_after>import React from 'react'
import PropTypes from 'prop-types'
import CopyToClipboard from 'react-copy-to-clipboard'
import JSONPretty from 'react-json-pretty'
import Button from 'react-bootstrap/lib/Button'
import Modal from 'react-bootstrap/lib/Modal'

import {withSpinner} from '../shared/Spinner'

import FetchPonyfill from 'fetch-ponyfill'
const fetch = FetchPonyfill().fetch

/**
 * Button that reveals a backend resouce at 'url' when clicked.
 *
 * Used to show the underlying JSON that a view was rendered with OR for
 * showing a related resource, eg. an anchor's server.toml file.
 */
const BackendResourceBadgeButton = ({handleClickFn, label, url}) => (
  <a
    className="backend-resource-badge-button"
    href={url}
    onClick={handleClickFn}
  >
    {label}
  </a>
)

BackendResourceBadgeButton.propTypes = {
  handleClickFn: PropTypes.func.isRequired,
  label: PropTypes.string.isRequired,
  url: PropTypes.string.isRequired,
}

class ClipboardCopyButton extends React.Component {
  state = {copied: false}

  constructor(props, context) {
    super(props, context)
    this.handleClickCopy = this.handleClickCopy.bind(this)
  }

  handleClickCopy() {
    this.setState({copied: true})
  }

  render() {
    return (
      <CopyToClipboard text={this.props.text} onCopy={this.handleClickCopy}>
        <span>
          <Button
            style={{backgroundColor: '#08b5e5', color: 'white', border: 0}}
          >
            Copy
          </Button>
          {this.state.copied && <span style={{marginLeft: 5}}>Copied!</span>}
        </span>
      </CopyToClipboard>
    )
  }
}

ClipboardCopyButton.propTypes = {
  text: PropTypes.string.isRequired,
}

const ResourceModalBody = ({handleCloseFn, isJson, show, text, url}) => (
  <div>
    <div>
      <ClipboardCopyButton text={text} />
      <Button
        bsSize="sm"
        style={{float: 'right', backgroundColor: '#96a2b4'}}
        onClick={handleCloseFn}
        aria-label="Close"
      >
        <span aria-hidden="true">&times;</span>
      </Button>
    </div>
    <div style={{marginTop: 20, marginBottom: 20, wordBreak: 'break-all'}}>
      <a href={url} target="_blank">
        {url}
      </a>
    </div>
    <div>
      {isJson ? <JSONPretty id="json-pretty" json={text} /> : <pre>{text}</pre>}
    </div>
  </div>
)

const ResourceModalBodyWithSpinner = withSpinner()(ResourceModalBody)

const ResourceModal = props => (
  <Modal show={props.show} onHide={props.handleCloseFn}>
    <Modal.Body style={{backgroundColor: '#383f4b'}}>
      <ResourceModalBodyWithSpinner {...props} />
    </Modal.Body>
  </Modal>
)

ResourceModal.propTypes = {
  handleCloseFn: PropTypes.func.isRequired,
  isJson: PropTypes.bool.isRequired,
  show: PropTypes.bool.isRequired,
  text: PropTypes.string.isRequired,
  url: PropTypes.string.isRequired,
}

class ResourceModalContainer extends React.Component {
  state = {
    fetchFailed: false,
    isJson: false,
    isLoading: true,
    show: false,
    text: '',
  }

  isJsonResponse(rsp) {
    return (
      this.props.url.endsWith('.json') ||
      (rsp.headers.has('content-type') &&
        rsp.headers.get('content-type').indexOf('json') !== -1)
{'fraction_non_alphanumeric': 0.14185611958891312, 'fraction_numerical': 0.005917159763313609, 'mean_word_length': 3.287716955941255, 'pattern_counts': {'":': 0, '<': 69, '<?xml version=': 0, '>': 75, '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': '930148', 'n_tokens_mistral': 2077, 'n_tokens_neox': 2077, 'n_words': 446}