<commit_before>import React, {Component, PropTypes} from 'react';
import { createSelector } from 'reselect';

import { DragDropContext } from 'react-dnd';
import HTML5Backend from 'react-dnd-html5-backend';

import ItemDatePicker from './ItemDatePicker.jsx';
import ItemsFilter from './ItemsFilter.jsx';
import ItemNote from './ItemNote.jsx';
import ItemAdd from './ItemAdd.jsx';
import Item from './Item.jsx';
import ItemGroup from './ItemGroup.jsx';

import Todo from '../../models/Todo';
import TreeNode from '../../models/TreeNode';

import * as TodoItemStateType from '../../constants/TodoItemStateTypes';
import * as HighlightType from '../../constants/HighlightTypes';
import * as FilterTypes from '../../constants/FilterTypes';

import {transformTodos} from '../../lib/todoTransformations';
import {getParentFor, isParentOf, searchr, findr, filterr, findrIndex, findrByIndex} from '../../lib/collectionUtils.js';
import * as TodoAction from '../../actions/todos';
import * as AppAction from '../../actions/app';


export class ItemsList extends Component {

  state;

  static contextTypes = {
    store: PropTypes.object.isRequired
  };

  constructor() {
    super();
    this.state = {
      // cards: [],
      focusedItemState: TodoItemStateType.VIEW,
      prevKey: null,
      editId: null,
      dropHoverStyle: HighlightType.NONE,
      dropHoverId: null
    };

    this.selectTodos  = () => this.curState().todos;
    this.selectFilter = () => this.curState().filter;

    this.curItems = createSelector(
      this.selectTodos, this.selectFilter,
      (todos, filter) => {
        return applyFilter(todos, filter);
      }
    );
  }  

  render() {
    let counter = 0;
    const store = this.context.store;

    const getItemComponent = (i, j) => (<Item
              ref={j}
              className={this.stylesForItem(i, j)}
              todo={i}
              focus={this.state.editId == null && this.curState().focusId == i.id}
              visible={this.isTodoVisible(i)}
              onDrop={this.dropItemHandler.bind(this)}
              highlight={this.highlightItem.bind(this)}
              onKeyDown={this.itemKeyPressHandler.bind(this)}
              onFocus={() => this.itemFocusHandler(i.id)}
              onFocusOut={() => this.focusOutHandler()}
              onChange={() => this.props.checkTodo(i.id)}
              onFlipTodo={() => store.dispatch(TodoAction.flipTodo(i.id))}
              onCheckTodo={() => {
                this.keepPositionAfterAction(i.id, () => store.dispatch(TodoAction.checkTodo(i.id)));
              }}
            >
              {this.getItemBody(i)}
            </Item>)    

    const getGroupComponent = (i, j) => (<ItemGroup key={j}>{i.text}</ItemGroup>)

    const getRightComponent = (i) => {
      if (i instanceof Todo) {
        return getItemComponent;
      } else {
        return getGroupComponent;
      }
    }

    const renderItems = (items) => {
      return items.map(
        (i) => (<div key={++counter}>
                    {getRightComponent(i)(i, counter)}
                    {i.children != undefined && i.children.length > 0 && i.open ?
                     <div className="items">{renderItems(i.children)}</div>
                     : ''}
                  </div>)        
      );
    };

    return (
      <ItemsFilter>
        {renderItems(this.curItems())}
      </ItemsFilter>
    );

    /*<p className="debug">focusedItemState: {this.state.focusedItemState},
     focusId: {this.curState().focusId},
     editId:  {this.state.editId},
     dropId:  {this.state.dropHoverId},
     dropStyle: {this.state.dropHoverStyle}</p>*/
  }

  keepPositionAfterAction(id, action) {
    let idx = this.findIndexById(id); // index before action
    action();
    let newId = false;
    while (true) {
      newId = this.findIdByIndex(idx--);
      if (newId != undefined || idx < 0) break;
    }
    if (newId != undefined) {
      // set focus if item exists
      this.context.store.dispatch(TodoAction.selectTodo(newId));
    }<commit_msg>mend<commit_after>import React, {Component, PropTypes} from 'react';
import { createSelector } from 'reselect';

import { DragDropContext } from 'react-dnd';
import HTML5Backend from 'react-dnd-html5-backend';

import ItemDatePicker from './ItemDatePicker.jsx';
import ItemsFilter from './ItemsFilter.jsx';
import ItemNote from './ItemNote.jsx';
import ItemAdd from './ItemAdd.jsx';
import Item from './Item.jsx';
import ItemGroup from './ItemGroup.jsx';

import Todo from '../../models/Todo';
import TreeNode from '../../models/TreeNode';

import * as TodoItemStateType from '../../constants/TodoItemStateTypes';
import * as HighlightType from '../../constants/HighlightTypes';
import * as FilterTypes from '../../constants/FilterTypes';

import {transformTodos} from '../../lib/todoTransformations';
import {getParentFor, isParentOf, searchr, findr, filterr, findrIndex, findrByIndex} from '../../lib/collectionUtils.js';
import * as TodoAction from '../../actions/todos';
import * as AppAction from '../../actions/app';


export class ItemsList extends Component {

  state;

  static contextTypes = {
    store: PropTypes.object.isRequired
  };

  constructor() {
    super();
    this.state = {
      // cards: [],
      focusedItemState: TodoItemStateType.VIEW,
      prevKey: null,
      editId: null,
      dropHoverStyle: HighlightType.NONE,
      dropHoverId: null
    };

    this.selectTodos  = () => this.curState().todos;
    this.selectFilter = () => this.curState().filter;

    this.curItems = createSelector(
      this.selectTodos, this.selectFilter,
      (todos, filter) => {
        return applyFilter(todos, filter);
      }
    );
  }

  getItemComponent(i, j) {
    return (<Item
      ref={j}
      className={this.stylesForItem(i, j)}
      todo={i}
      focus={this.state.editId == null && this.curState().focusId == i.id}
      visible={this.isTodoVisible(i)}
      onDrop={this.dropItemHandler.bind(this)}
      highlight={this.highlightItem.bind(this)}
      onKeyDown={this.itemKeyPressHandler.bind(this)}
      onFocus={() => this.itemFocusHandler(i.id)}
      onFocusOut={() => this.focusOutHandler()}
      onChange={() => this.props.checkTodo(i.id)}
      onFlipTodo={() => store.dispatch(TodoAction.flipTodo(i.id))}
      onCheckTodo={() => {
        this.keepPositionAfterAction(i.id, () => store.dispatch(TodoAction.checkTodo(i.id)));
      }}
    >
      {this.getItemBody(i)}
    </Item>);
  }

  getGroupComponent(i, j) {
    return (<ItemGroup key={j}>{i.text}</ItemGroup>);
  }

  getRightComponent(i) {
    if (i instanceof Todo) {
      return (i, j) => this.getItemComponent(i, j);
    } else {
      return (i, j) => this.getGroupComponent(i, j);
    }
  }

  render() {
    let counter = 0;

    const renderItems = (items) => {
      return items.map(
        (i) => (<div key={++counter}>
                    {this.getRightComponent(i)(i, counter)}
                    {i.children != undefined && i.children.length > 0 && i.open ?
                     <div className="items">{renderItems(i.children)}</div>
                     : ''}
                  </div>)
      );
    };

    return (
      <ItemsFilter>
        {renderItems(this.curItems())}
      </ItemsFilter>
    );

    /*<p className="debug">focusedItemState: {this.state.focusedItemState},
     focusId: {this.curState().focusId},
     editId:  {this.state.editId},
     dropId:  {this.state.dropHoverId},
     dropStyle: {this.state.dropHoverStyle}</p>*/
  }

  keepPositionAfterAction(id, action) {
    let idx = this.findIndexById(id); // index before action
    action();
    let newId = false;
    while (true) {
      newId = this.findIdByIndex(idx--);
      if (newId != undefined || idx < 0) break;
    }
    if (newId != undefined) {
      // set focus if item exists
      this.context.store.dispatch(TodoAction.selectTodo(newId));
    }
{'fraction_non_alphanumeric': 0.1571753986332574, 'fraction_numerical': 0.0012655024044545685, 'mean_word_length': 2.5727848101265822, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 56, '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': '2544636', 'n_tokens_mistral': 2461, 'n_tokens_neox': 2437, 'n_words': 489}