<commit_before>// Copyright (c) ppy Pty Ltd <<EMAIL>>. Licensed under the GNU Affero General Public License v3.0.
// See the LICENCE file in the repository root for full licence text.

import { BeatmapIcon } from 'beatmap-icon';
import BeatmapJsonExtended from 'interfaces/beatmap-json-extended';
import * as React from 'react';
import { Node, Transforms } from 'slate';
import { ReactEditor } from 'slate-react';
import IconDropdownMenu, { MenuItem } from './icon-dropdown-menu';
import { SlateContext } from './slate-context';

interface Props {
  beatmaps: BeatmapJsonExtended[];
  disabled: boolean;
  element: Node;
}

export default class EditorBeatmapSelector extends React.Component<Props> {
  static contextType = SlateContext;
  declare context: React.ContextType<typeof SlateContext>;

  render(): React.ReactNode {
    const menuOptions: MenuItem[] = [];
    menuOptions.push({
      icon: <i className='fas fa-fw fa-star-of-life' />,
      id: 'all',
      label: osu.trans('beatmaps.discussions.mode.scopes.generalAll'),
    });

    this.props.beatmaps.forEach((beatmap: BeatmapJsonExtended) => {
      if (beatmap.deleted_at) {
        return;
      }

      menuOptions.push({
        icon: <BeatmapIcon beatmap={beatmap} showTitle={false} />,
        id: beatmap.id.toString(),
        label: beatmap.version,
      });
    });

    return (
      <IconDropdownMenu
        disabled={this.props.disabled}
        menuOptions={menuOptions}
        onSelect={this.select}
        selected={(this.props.element.beatmapId as number)?.toString()}
      />
    );
  }

  select = (id: string) => {
    const beatmapId = id !== 'all' ? parseInt(id, 10) : 'all';

    if (beatmapId) {
      const path = ReactEditor.findPath(this.context, this.props.element);
      Transforms.setNodes(this.context, {beatmapId}, {at: path});
    }
  };
}
<commit_msg>also don't error when switching to general with invalid timestamps...<commit_after>// Copyright (c) ppy Pty Ltd <<EMAIL>>. Licensed under the GNU Affero General Public License v3.0.
// See the LICENCE file in the repository root for full licence text.

import { BeatmapIcon } from 'beatmap-icon';
import BeatmapJsonExtended from 'interfaces/beatmap-json-extended';
import * as React from 'react';
import { Node, Transforms } from 'slate';
import { ReactEditor } from 'slate-react';
import IconDropdownMenu, { MenuItem } from './icon-dropdown-menu';
import { SlateContext } from './slate-context';

interface Props {
  beatmaps: BeatmapJsonExtended[];
  disabled: boolean;
  element: Node;
}

export default class EditorBeatmapSelector extends React.Component<Props> {
  static contextType = SlateContext;
  declare context: React.ContextType<typeof SlateContext>;

  render(): React.ReactNode {
    const menuOptions: MenuItem[] = [];
    menuOptions.push({
      icon: <i className='fas fa-fw fa-star-of-life' />,
      id: 'all',
      label: osu.trans('beatmaps.discussions.mode.scopes.generalAll'),
    });

    this.props.beatmaps.forEach((beatmap: BeatmapJsonExtended) => {
      if (beatmap.deleted_at) {
        return;
      }

      menuOptions.push({
        icon: <BeatmapIcon beatmap={beatmap} showTitle={false} />,
        id: beatmap.id.toString(),
        label: beatmap.version,
      });
    });

    return (
      <IconDropdownMenu
        disabled={this.props.disabled}
        menuOptions={menuOptions}
        onSelect={this.select}
        selected={(this.props.element.beatmapId as number)?.toString()}
      />
    );
  }

  select = (id: string) => {
    // FIXME: used 0 here because null breaks other things atm (and some other stuff assumes number).
    const beatmapId = id !== 'all' ? parseInt(id, 10) : 0;

    const path = ReactEditor.findPath(this.context, this.props.element);
    Transforms.setNodes(this.context, {beatmapId}, {at: path});
  };
}

{'fraction_non_alphanumeric': 0.13315994798439532, 'fraction_numerical': 0.002600780234070221, 'mean_word_length': 3.3164983164983166, 'pattern_counts': {'":': 0, '<': 17, '<?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': '2561942', 'n_tokens_mistral': 1188, 'n_tokens_neox': 1166, 'n_words': 297}