<commit_before>import "./TodoList.scss";

import React from "react";
import { FormattedMessage, InjectedIntlProps, injectIntl } from "react-intl";
import { connect } from "react-redux";
import { Dispatch } from "redux";

import find from "lodash-es/find";
import noop from "lodash-es/noop";

import FontIcon from "react-md/lib/FontIcons/FontIcon";

import { sendNotification } from "../notifications/NotificationProvider";
import { AppState } from "../state";
import { TodoModel } from "./todo.model";
import {
  AddTodo,
  DeleteTodo,
  TodoAddAction,
  TodoDeleteAction,
  UpdateTodo
} from "./todo.state";
import TodoEntry from "./TodoEntry";

// Todo list.
export interface TodoListProps {
  todos: TodoModel[];
  onTodoAdd: (headline: string, description: string, deadline: Date) => void;
  onTodoUpdate: (todo: TodoModel) => void;
  onTodoDelete: (id: number) => void;
}

const mapStateToProps = (state: AppState) => {
  return {
    todos: state.todos
  };
};

const mapDispatchToProps = (
  dispatch: Dispatch<TodoAddAction> | Dispatch<TodoDeleteAction>
) => {
  return {
    onTodoAdd: (headline: string, description: string, deadline: Date) => {
      dispatch(AddTodo(headline, description, deadline));
    },
    onTodoUpdate: (updated: TodoModel) => {
      dispatch(UpdateTodo(updated));
    },
    onTodoDelete: (id: number) => {
      (dispatch as Dispatch<TodoDeleteAction>)(DeleteTodo(id));
    }
  };
};

class TodoList extends React.Component<TodoListProps & InjectedIntlProps, any> {
  state = {
    showNewTodoBlock: false
  };

  constructor(props: TodoListProps & InjectedIntlProps, context: any) {
    super(props, context);

    this.createTodo = this.createTodo.bind(this);
    this.showNewTodoBlock = this.showNewTodoBlock.bind(this);
    this.hideNewTodoBlock = this.hideNewTodoBlock.bind(this);
    this.deleteTodo = this.deleteTodo.bind(this);
    this.createTodoEntry = this.createTodoEntry.bind(this);
  }

  createTodo(
    headline: string,
    description: string,
    deadline: Date,
    id?: number
  ) {
    this.setState({ showNewTodoBlock: false });

    if (id) {
      const oldTodo = find(this.props.todos, e => !!e && e.id === id);

      this.props.onTodoUpdate({
        ...oldTodo,
        id,
        headline,
        description,
        deadline
      } as TodoModel);
    } else {
      this.props.onTodoAdd(headline, description, deadline);
    }

    sendNotification(
      this.props.intl.formatMessage({
        id: `todos.newTodo.${id ? "updated" : "added"}`
      }),
      {
        icon: "favicon.ico",
        body: headline
      },
      5000
    );
  }

  render() {
    const displayContent = this.state.showNewTodoBlock ? (
      <TodoEntry
        editable
        createOrUpdateTodo={this.createTodo}
        onCancel={this.hideNewTodoBlock}
        onDelete={noop}
      />
    ) : (
      <div className="new-todo" onClick={this.showNewTodoBlock}><commit_msg>fix(unhandled-rejection): Fix unhandled rejection when trying to send a notification about a created todo.<commit_after>import "./TodoList.scss";

import React from "react";
import { FormattedMessage, InjectedIntlProps, injectIntl } from "react-intl";
import { connect } from "react-redux";
import { Dispatch } from "redux";

import find from "lodash-es/find";
import noop from "lodash-es/noop";

import FontIcon from "react-md/lib/FontIcons/FontIcon";

import { sendNotification } from "../notifications/NotificationProvider";
import { AppState } from "../state";
import { TodoModel } from "./todo.model";
import {
  AddTodo,
  DeleteTodo,
  TodoAddAction,
  TodoDeleteAction,
  UpdateTodo
} from "./todo.state";
import TodoEntry from "./TodoEntry";

// Todo list.
export interface TodoListProps {
  todos: TodoModel[];
  onTodoAdd: (headline: string, description: string, deadline: Date) => void;
  onTodoUpdate: (todo: TodoModel) => void;
  onTodoDelete: (id: number) => void;
}

const mapStateToProps = (state: AppState) => {
  return {
    todos: state.todos
  };
};

const mapDispatchToProps = (
  dispatch: Dispatch<TodoAddAction> | Dispatch<TodoDeleteAction>
) => {
  return {
    onTodoAdd: (headline: string, description: string, deadline: Date) => {
      dispatch(AddTodo(headline, description, deadline));
    },
    onTodoUpdate: (updated: TodoModel) => {
      dispatch(UpdateTodo(updated));
    },
    onTodoDelete: (id: number) => {
      (dispatch as Dispatch<TodoDeleteAction>)(DeleteTodo(id));
    }
  };
};

class TodoList extends React.Component<TodoListProps & InjectedIntlProps, any> {
  state = {
    showNewTodoBlock: false
  };

  constructor(props: TodoListProps & InjectedIntlProps, context: any) {
    super(props, context);

    this.createTodo = this.createTodo.bind(this);
    this.showNewTodoBlock = this.showNewTodoBlock.bind(this);
    this.hideNewTodoBlock = this.hideNewTodoBlock.bind(this);
    this.deleteTodo = this.deleteTodo.bind(this);
    this.createTodoEntry = this.createTodoEntry.bind(this);
  }

  createTodo(
    headline: string,
    description: string,
    deadline: Date,
    id?: number
  ) {
    this.setState({ showNewTodoBlock: false });

    if (id) {
      const oldTodo = find(this.props.todos, e => !!e && e.id === id);

      this.props.onTodoUpdate({
        ...oldTodo,
        id,
        headline,
        description,
        deadline
      } as TodoModel);
    } else {
      this.props.onTodoAdd(headline, description, deadline);
    }

    sendNotification(
      this.props.intl.formatMessage({
        id: `todos.newTodo.${id ? "updated" : "added"}`
      }),
      {
        icon: "favicon.ico",
        body: headline
      },
      5000
    ).catch(error => {
      console.error("Could not send notification:", error);
    });
  }

  render() {
    const displayContent = this.state.showNewTodoBlock ? (
      <TodoEntry
        editable
        createOrUpdateTodo={this.createTodo}
        onCancel={this.hideNewTodoBlock}
        onDelete={noop}
      />
    ) : (
      <div className="new-todo" onClick={this.showNewTodoBlock}>
{'fraction_non_alphanumeric': 0.13445934757410166, 'fraction_numerical': 0.001324722636198046, 'mean_word_length': 3.217877094972067, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 34, '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': '7125417', 'n_tokens_mistral': 2028, 'n_tokens_neox': 2004, 'n_words': 406}