<commit_before>import * as m from 'mithril'
import socket from '../../socket';
import router from '../../router';
import settings from '../../settings';
import { apiVersion } from '../../http';
import redraw from '../../utils/redraw';
import { hasNetwork, serializeQueryParameters, handleXhrError } from '../../utils'
import { fetchJSON } from '../../http';
import * as helper from '../helper';
import { header } from '../shared/common';
import layout from '../layout';
import i18n from '../../i18n';
import formWidgets from '../shared/form';
import { validateFen, cleanFenUri } from '../../utils/fen';
import * as stream from 'mithril/stream';

export interface State {
  importGame(e: Event): void
  importing: Mithril.Stream<boolean>
}

interface SendData {
  pgn: string
  analyse?: boolean
}

const ImporterScreen: Mithril.Component<{}, State> = {
  oninit(vnode) {
    helper.analyticsTrackView('Import game');

    socket.createDefault();

    const importing = stream(false);

    function submitOnline(pgn: string, analyse: boolean): Promise<OnlineGameData> {
      const data: SendData = { pgn }
      if (analyse) data.analyse = true;

      return fetchJSON('/import', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
          'X-Requested-With': 'XMLHttpRequest',
          'Accept': 'application/vnd.lichess.v' + apiVersion + '+json'
        },
        body: serializeQueryParameters(data)
      }, true);
    }

    window.addEventListener('native.keyboardhide', helper.onKeyboardHide);
    window.addEventListener('native.keyboardshow', helper.onKeyboardShow);

    vnode.state = {
      importGame(e: Event) {
        const target = e.target as EventTarget;
        const pgn = target[0].value;
        if (!pgn) return;
        importing(true);
        redraw()
        if (hasNetwork()) {
          if(validateFen(pgn).valid){
            // They are importing a FEN.
            router.set(`/analyse/fen/${encodeURIComponent(pgn)}`)
          } else {
            submitOnline(pgn, settings.importer.analyse())
            .then(data => {
              router.set(`/analyse/online${data.url.round}`);
            })
            .catch(err => {
              importing(false);
              redraw()
              console.error(err);
              handleXhrError(err);
            })
          }
        }
      },
      importing
    };
  },

  oncreate: helper.viewFadeIn,

  onremove() {
    window.removeEventListener('native.keyboardshow', helper.onKeyboardShow);
    window.removeEventListener('native.keyboardhide', helper.onKeyboardHide);
  },

  view(vnode) {
    const headerCtrl = () => header(i18n('importGame'));
    const bodyCtrl = () => renderBody(vnode.state);
    return layout.free(headerCtrl, bodyCtrl);
  }

}

function renderBody(ctrl: State) {
  return m('div.gameImporter.native_scroller', [
    m('p', 'When pasting a game PGN, you get a browsable replay and a computer analysis.'),
    m('form', {
      onsubmit: (e: Event) => {
        e.preventDefault();
        ctrl.importGame(e);
      }
    }, [
      m('label', i18n('pasteThePgnStringHere') + ' :'),
      m('textarea.pgnImport'),
      formWidgets.renderCheckbox(i18n('requestAComputerAnalysis'), 'analyse', settings.importer.analyse),
      m('button.fatButton', ctrl.importing() ?
        m('div.fa.fa-hourglass-half') : i18n('importGame'))
    ])
  ]);
}

export default ImporterScreen
<commit_msg>When PGN Import fails, attempt to import as FEN.<commit_after>import * as m from 'mithril'
import socket from '../../socket';
import router from '../../router';
import settings from '../../settings';
import { apiVersion } from '../../http';
import redraw from '../../utils/redraw';
import { hasNetwork, serializeQueryParameters, handleXhrError } from '../../utils'
import { fetchJSON } from '../../http';
import * as helper from '../helper';
import { header } from '../shared/common';
import layout from '../layout';
import i18n from '../../i18n';
import formWidgets from '../shared/form';
import { validateFen, cleanFenUri } from '../../utils/fen';
import * as stream from 'mithril/stream';

export interface State {
  importGame(e: Event): void
  importing: Mithril.Stream<boolean>
}

interface SendData {
  pgn: string
  analyse?: boolean
}

const ImporterScreen: Mithril.Component<{}, State> = {
  oninit(vnode) {
    helper.analyticsTrackView('Import game');

    socket.createDefault();

    const importing = stream(false);

    function submitOnline(pgn: string, analyse: boolean): Promise<OnlineGameData> {
      const data: SendData = { pgn }
      if (analyse) data.analyse = true;

      return fetchJSON('/import', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
          'X-Requested-With': 'XMLHttpRequest',
          'Accept': 'application/vnd.lichess.v' + apiVersion + '+json'
        },
        body: serializeQueryParameters(data)
      }, true);
    }

    window.addEventListener('native.keyboardhide', helper.onKeyboardHide);
    window.addEventListener('native.keyboardshow', helper.onKeyboardShow);

    vnode.state = {
      importGame(e: Event) {
        const target = e.target as EventTarget;
        const pgn = target[0].value;
        if (!pgn) return;
        importing(true);
        redraw()
        if (hasNetwork()) {
          if(validateFen(pgn).valid){
            // They are importing a FEN.
            router.set(`/analyse/fen/${encodeURIComponent(pgn)}`)
          } else {
            submitOnline(pgn, settings.importer.analyse())
            .then(data => {
              router.set(`/analyse/online${data.url.round}`);
            })
            .catch(err => {
              importing(false);
              redraw()
              console.error(err);
              handleXhrError(err);
            })
          }
        }
      },
      importing
    };
  },

  oncreate: helper.viewFadeIn,

  onremove() {
    window.removeEventListener('native.keyboardshow', helper.onKeyboardShow);
    window.removeEventListener('native.keyboardhide', helper.onKeyboardHide);
  },

  view(vnode) {
    const headerCtrl = () => header(i18n('importGame'));
    const bodyCtrl = () => renderBody(vnode.state);
    return layout.free(headerCtrl, bodyCtrl);
  }

}

function renderBody(ctrl: State) {
  return m('div.gameImporter.native_scroller', [
    m('p', 'When pasting a game PGN, you get a browsable replay and a computer analysis.'),
    m('form', {
      onsubmit: (e: Event) => {
        e.preventDefault();
        ctrl.importGame(e);
      }
    }, [
      m('label', i18n('pasteThePgnStringHere') + ' :'),
      m('textarea.pgnImport'),
      formWidgets.renderCheckbox(i18n('requestAComputerAnalysis'), 'analyse', settings.importer.analyse),
      m('button.fatButton', ctrl.importing() ?
        m('div.fa.fa-hourglass-half') : i18n('importGame'))
    ])
  ]);
}

function fetchImport(data: SendData) {
  return fetchJSON('/import', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
          'X-Requested-With': 'XMLHttpRequest',
          'Accept': 'application/vnd.lichess.v' + apiVersion + '+json'
        },
        body: serializeQueryParameters(data)
      }, true)
}

export default ImporterScreen

{'fraction_non_alphanumeric': 0.15442969384990518, 'fraction_numerical': 0.003928474668111623, 'mean_word_length': 2.6387382947264664, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 3, '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': '2732714', 'n_tokens_mistral': 2229, 'n_tokens_neox': 2205, 'n_words': 464}