<commit_before>import { h, thunk } from 'snabbdom'
import { VNode } from 'snabbdom/vnode'
import { throttle } from 'common';
import AnalyseCtrl from '../ctrl';
import { StudyCtrl, StudyChapter } from './interfaces';

function editable(value: string, submit: (v: string, el: HTMLInputElement) => void): VNode {
  return h('input', {
    attrs: {
      spellcheck: false,
      value
    },
    hook: {
      insert: vnode => {
        const el = vnode.elm as HTMLInputElement;
        el.onblur = function() {
          submit(el.value, el);
        };
        el.onkeypress = function(e) {
          if ((e.keyCode || e.which) == 13) el.blur();
        }
      }
    }
  });
}

function fixed(text) {
  return h('span', text);
}

let fenElement: HTMLElement;
let selectedType: string;

function renderPgnTags(chapter: StudyChapter, submit, types: string[]): VNode {
  let rows = [
    ['Fen', h('pre#study_fen', {
      hook: {
        insert(vnode) { fenElement = vnode.elm as HTMLElement; }
      }
    })]
  ];
  if (chapter.setup.variant.key !== 'standard')
  rows.push(['Variant', fixed(chapter.setup.variant.name)]);
  rows = rows.concat(chapter.tags.map(function(tag) {
    return [
      tag[0],
      submit ? editable(tag[1], submit(tag[0])) : fixed(tag[1])
    ];
  }));
  if (submit) {
    const existingTypes = chapter.tags.map(t => t[0]);
    rows.push([
      h('select', {
        hook: {
          insert: vnode => {
            const el = vnode.elm as HTMLInputElement;
            selectedType = el.value;
            el.addEventListener('change', _ => {
              selectedType = el.value;
              $(el).parents('tr').find('input').focus();
            });
          },
          postpatch: (_, vnode) => {
            selectedType = (vnode.elm as HTMLInputElement).value;
          }
        }
      }, [
        h('option', 'New tag'),
        ...types.map(function(t) {
          if (!window.lichess.fp.contains(existingTypes, t)) return h('option', {
            attrs: { value: t }
          }, t);
        })
      ]),
      editable('', (value, el) => {
        if (selectedType) {
          submit(selectedType)(value);
          el.value = '';
        }
      })
    ]);
  }

  return h('table.tags.slist', h('tbody', rows.map(function(r) {
    return h('tr', {
      key: '' + r[0]
    }, [
      h('th', [r[0]]),
      h('td', [r[1]])
    ]);
  })));
}

export function ctrl(root: AnalyseCtrl, getChapter: () => StudyChapter, types) {

  const submit = throttle(500, false, function(name, value) {
    root.study!.makeChange('setTag', {
      chapterId: getChapter().id,
      name,
      value: value.substr(0, 140)
    });
  });

  return {
    submit(name) {
      return value => submit(name, value);
    },
    getChapter,
    types
  }
}
function doRender(root: StudyCtrl): VNode {
  return h('div.undertable_inner', renderPgnTags(
    root.tags.getChapter(),
    root.vm.mode.write && root.tags.submit,
    root.tags.types))
}

export function view(root: StudyCtrl): VNode {
  const chapter = root.tags.getChapter(),
  key = chapter.id + root.data.name + chapter.name + root.data.likes + chapter.tags + root.vm.mode.write;
  window.lichess.raf(function() {
    if (fenElement) fenElement.textContent = root.currentNode().fen;
  });
  return thunk('div.undertable_inner', doRender, [root, key]);
}<commit_msg>fix study PGN tags redraw on chapter switch, after edit<commit_after>import { h, thunk } from 'snabbdom'
import { VNode } from 'snabbdom/vnode'
import { throttle } from 'common';
import AnalyseCtrl from '../ctrl';
import { StudyCtrl, StudyChapter } from './interfaces';

function editable(value: string, submit: (v: string, el: HTMLInputElement) => void): VNode {
  return h('input', {
    attrs: {
      spellcheck: false,
      value
    },
    hook: {
      insert: vnode => {
        const el = vnode.elm as HTMLInputElement;
        el.onblur = function() {
          submit(el.value, el);
        };
        el.onkeypress = function(e) {
          if ((e.keyCode || e.which) == 13) el.blur();
        }
      }
    }
  });
}

function fixed(text) {
  return h('span', text);
}

let fenElement: HTMLElement;
let selectedType: string;

function renderPgnTags(chapter: StudyChapter, submit, types: string[]): VNode {
  let rows = [
    ['Fen', h('pre#study_fen', {
      hook: {
        insert(vnode) { fenElement = vnode.elm as HTMLElement; }
      }
    })]
  ];
  if (chapter.setup.variant.key !== 'standard')
  rows.push(['Variant', fixed(chapter.setup.variant.name)]);
  rows = rows.concat(chapter.tags.map(function(tag) {
    return [
      tag[0],
      submit ? editable(tag[1], submit(tag[0])) : fixed(tag[1])
    ];
  }));
  if (submit) {
    const existingTypes = chapter.tags.map(t => t[0]);
    rows.push([
      h('select', {
        hook: {
          insert: vnode => {
            const el = vnode.elm as HTMLInputElement;
            selectedType = el.value;
            el.addEventListener('change', _ => {
              selectedType = el.value;
              $(el).parents('tr').find('input').focus();
            });
          },
          postpatch: (_, vnode) => {
            selectedType = (vnode.elm as HTMLInputElement).value;
          }
        }
      }, [
        h('option', 'New tag'),
        ...types.map(function(t) {
          if (!window.lichess.fp.contains(existingTypes, t)) return h('option', {
            attrs: { value: t }
          }, t);
        })
      ]),
      editable('', (value, el) => {
        if (selectedType) {
          submit(selectedType)(value);
          el.value = '';
        }
      })
    ]);
  }

  return h('table.tags.slist', h('tbody', rows.map(function(r) {
    return h('tr', {
      key: '' + r[0]
    }, [
      h('th', [r[0]]),
      h('td', [r[1]])
    ]);
  })));
}

export function ctrl(root: AnalyseCtrl, getChapter: () => StudyChapter, types) {

  const submit = throttle(500, false, function(name, value) {
    root.study!.makeChange('setTag', {
      chapterId: getChapter().id,
      name,
      value: value.substr(0, 140)
    });
  });

  return {
    submit(name) {
      return value => submit(name, value);
    },
    getChapter,
    types
  }
}
function doRender(root: StudyCtrl): VNode {
  return h('div.undertable_inner', renderPgnTags(
    root.tags.getChapter(),
    root.vm.mode.write && root.tags.submit,
    root.tags.types))
}

export function view(root: StudyCtrl): VNode {
  const chapter = root.tags.getChapter(),
  key = chapter.id + root.data.name + chapter.name + root.data.likes + chapter.tags + root.vm.mode.write;
  window.lichess.raf(function() {
    if (fenElement) fenElement.textContent = root.currentNode().fen;
  });
  return thunk('div.undertable_inner.' + chapter.id, doRender, [root, key]);
}
{'fraction_non_alphanumeric': 0.16996748448122967, 'fraction_numerical': 0.005025125628140704, 'mean_word_length': 2.3533201189296333, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 21, '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': '7537584', 'n_tokens_mistral': 2264, 'n_tokens_neox': 2198, 'n_words': 454}