<commit_before>import React from 'react';
import ReactDOM from 'react-dom';
import classNames from 'classnames';
import { buildSchema, extendSchema, parse } from 'graphql';

import fakeIDL from 'raw-loader!../fake_definition.graphql';
import GraphQLEditor from './editor/GraphQLEditor';
import GraphiQL from 'graphiql';

import fetch from 'isomorphic-fetch'

import { EditIcon, ConsoleIcon, GithubIcon } from './icons';

import './css/app.css';
import './css/codemirror.css';
import './editor/editor.css';
import 'graphiql/graphiql.css';

// const fakeSchema = buildSchema(fakeIDL + ' schema { query: QueryType } type QueryType { a: String }');

class FakeEditor extends React.Component {
  constructor() {
    super();

    this.state = {
      value: null,
      cachedValue: null,
      activeTab: 0,
      dirty: false,
      error: null,
      status: null,
      schema: undefined
    }
  }

  componentDidMount() {
    fetch('/user-idl')
      .then(response => response.json())
      .then(idls => {
        this.updateValue(idls);
      });

    window.onbeforeunload = () => {
      if (this.state.dirty) return 'You have unsaved changes. Exit?'
    };
  }

  fetcher(graphQLParams) {
    return fetch(window.location.origin + '/graphql', {
      method: 'post',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(graphQLParams),
    }).then(response => response.json());
  }

  updateValue({schemaIDL, extensionIDL}) {
    let value = extensionIDL || schemaIDL;
    this.proxiedSchemaIDL = extensionIDL ? schemaIDL : null;
    this.setState({
      value,
      cachedValue: value,
      extendMode: !!extensionIDL
    });
  }

  postIDL(idl) {
    return fetch('/user-idl', {
      method: 'post',
      headers: { 'Content-Type': 'text/plain' },
      body: idl
    })
  }

  validateIdl(value) {
    let extensionIDL;
    let schemaIDL;
    if (this.state.extendMode) {
      extensionIDL = value;
      schemaIDL = this.proxiedSchemaIDL;
    } else {
      schemaIDL = value;
    }
    let fullIdl = schemaIDL + '\n' + fakeIDL;
    try {
      let schema = buildSchema(fullIdl);
      if (extensionIDL)
        schema = extendSchema(schema, parse(extensionIDL));
      this.setState(prevState => ({...prevState, schema: schema}));
      return true;
    } catch(e) {
      this.setState(prevState => ({...prevState, error: e.message}));
      return false;
    }
  }

  setStatus(status, delay) {
    this.setState(prevState => ({...prevState, status: status}));
    if (!delay) return;
    setTimeout(() => {
      this.setState(prevState => ({...prevState, status: null}));
    }, delay);
  }

  saveUserIDL = () => {
    let { value, dirty } = this.state;
    if (!dirty) return;

    if (!this.validateIdl(value)) return;

    this.postIDL(value).then(res => {
      if (res.ok) {
        this.setStatus('Saved!', 2000);
        return this.setState(prevState => ({...prevState, cachedValue: value, dirty: false, error: null}));
      } else {
        res.text().then(errorMessage => {
          return this.setState(prevState => ({...prevState, error: errorMessage}));
        });
      }
    });
  }

  switchTab(tab) {
    this.setState(prevState => ({...prevState, activeTab: tab}));
  }

  onEdit = (val) => {
    this.setState(prevState => ({...prevState, value: val, dirty: val !== this.state.cachedValue}))
  }

  render() {
    let { value, activeTab, dirty, extendMode } = this.state;
    let prefixIDL = fakeIDL + (this.proxiedSchemaIDL || '');
    return (<commit_msg>Validate IDL on each keystroke in editor<commit_after>import React from 'react';
import ReactDOM from 'react-dom';
import classNames from 'classnames';
import { buildSchema, extendSchema, parse } from 'graphql';

import fakeIDL from 'raw-loader!../fake_definition.graphql';
import GraphQLEditor from './editor/GraphQLEditor';
import GraphiQL from 'graphiql';

import fetch from 'isomorphic-fetch'

import { EditIcon, ConsoleIcon, GithubIcon } from './icons';

import './css/app.css';
import './css/codemirror.css';
import './editor/editor.css';
import 'graphiql/graphiql.css';

// const fakeSchema = buildSchema(fakeIDL + ' schema { query: QueryType } type QueryType { a: String }');

class FakeEditor extends React.Component {
  constructor() {
    super();

    this.state = {
      value: null,
      cachedValue: null,
      activeTab: 0,
      dirty: false,
      error: null,
      status: null,
      schema: undefined
    }
  }

  componentDidMount() {
    fetch('/user-idl')
      .then(response => response.json())
      .then(idls => {
        this.updateValue(idls);
      });

    window.onbeforeunload = () => {
      if (this.state.dirty) return 'You have unsaved changes. Exit?'
    };
  }

  fetcher(graphQLParams) {
    return fetch(window.location.origin + '/graphql', {
      method: 'post',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(graphQLParams),
    }).then(response => response.json());
  }

  updateValue({schemaIDL, extensionIDL}) {
    let value = extensionIDL || schemaIDL;
    this.proxiedSchemaIDL = extensionIDL ? schemaIDL : null;
    this.setState({
      value,
      cachedValue: value,
      extendMode: !!extensionIDL
    });
  }

  postIDL(idl) {
    return fetch('/user-idl', {
      method: 'post',
      headers: { 'Content-Type': 'text/plain' },
      body: idl
    })
  }

  updateIdl(value) {
    let extensionIDL;
    let schemaIDL;
    if (this.state.extendMode) {
      extensionIDL = value;
      schemaIDL = this.proxiedSchemaIDL;
    } else {
      schemaIDL = value;
    }
    let fullIdl = schemaIDL + '\n' + fakeIDL;
    try {
      let schema = buildSchema(fullIdl);
      if (extensionIDL)
        schema = extendSchema(schema, parse(extensionIDL));
      this.setState(prevState => ({...prevState, schema: schema, error: null}));
      return true;
    } catch(e) {
      this.setState(prevState => ({...prevState, error: e.message}));
      return false;
    }
  }

  setStatus(status, delay) {
    this.setState(prevState => ({...prevState, status: status}));
    if (!delay) return;
    setTimeout(() => {
      this.setState(prevState => ({...prevState, status: null}));
    }, delay);
  }

  saveUserIDL = () => {
    let { value, dirty } = this.state;
    if (!dirty) return;

    if (!this.updateIdl(value)) return;

    this.postIDL(value).then(res => {
      if (res.ok) {
        this.setStatus('Saved!', 2000);
        return this.setState(prevState => ({...prevState, cachedValue: value, dirty: false, error: null}));
      } else {
        res.text().then(errorMessage => {
          return this.setState(prevState => ({...prevState, error: errorMessage}));
        });
      }
    });
  }

  switchTab(tab) {
    this.setState(prevState => ({...prevState, activeTab: tab}));
  }

  onEdit = (val) => {
    this.updateIdl(val);
    this.setState(prevState => ({
      ...prevState,
      value: val,
      dirty: val !== this.state.cachedValue
    }))
  }

  render() {
    let { value, activeTab, dirty, extendMode } = this.state;
    let prefixIDL = fakeIDL + (this.proxiedSchemaIDL || '');
    return (
{'fraction_non_alphanumeric': 0.15703289013296012, 'fraction_numerical': 0.0013995801259622112, 'mean_word_length': 2.7630331753554502, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 37, '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': '2435009', 'n_tokens_mistral': 2325, 'n_tokens_neox': 2302, 'n_words': 503}