diff --git a/examples/todomvc/actions/FilterActions.js b/examples/todomvc/actions/FilterActions.js new file mode 100644 index 0000000000..41ea3d40cb --- /dev/null +++ b/examples/todomvc/actions/FilterActions.js @@ -0,0 +1,13 @@ +import * as types from '../constants/TodoFilters' + +export function showAll() { + return {type:types.SHOW_ALL} +} + +export function showActive() { + return {type:types.SHOW_ACTIVE} +} + +export function showCompleted() { + return {type:types.SHOW_COMPLETED} +} \ No newline at end of file diff --git a/examples/todomvc/actions/index.js b/examples/todomvc/actions/TodoActions.js similarity index 100% rename from examples/todomvc/actions/index.js rename to examples/todomvc/actions/TodoActions.js diff --git a/examples/todomvc/components/Footer.js b/examples/todomvc/components/Footer.js index 8ae9c59983..0a2bed5107 100644 --- a/examples/todomvc/components/Footer.js +++ b/examples/todomvc/components/Footer.js @@ -9,65 +9,79 @@ const FILTER_TITLES = { } class Footer extends Component { + renderTodoCount() { - const { activeCount } = this.props + const { todos } = this.props; + const completedCount = todos.reduce((count, todo) => + todo.completed ? count + 1 : count, + 0 + ) + const activeCount = todos.length - completedCount + const itemWord = activeCount === 1 ? 'item' : 'items' - return ( - - {activeCount || 'No'} {itemWord} left - + return ( < span className = "todo-count" > + < strong > { activeCount || 'No' } < /strong> {itemWord} left < /span> ) } + onShow(filter) { + switch (filter) { + case SHOW_COMPLETED: + this.props.filterActions.showCompleted(); + break; + case SHOW_ACTIVE: + this.props.filterActions.showActive(); + break; + default: + this.props.filterActions.showAll(); + } + } + renderFilterLink(filter) { const title = FILTER_TITLES[filter] const { filter: selectedFilter, onShow } = this.props - - return ( - onShow(filter)}> - {title} - + return ( < a className = { classnames({ selected: filter === selectedFilter }) } + style = { + { cursor: 'pointer' } } + onClick = { + () => this.onShow(filter) } > { title } < /a> ) } + onClearCompleted() { + this.props.todoActions.clearCompleted() + } + renderClearButton() { - const { completedCount, onClearCompleted } = this.props + const { todos } = this.props; + const completedCount = todos.reduce((count, todo) => + todo.completed ? count + 1 : count, + 0 + ) + const activeCount = todos.length - completedCount if (completedCount > 0) { - return ( - + return ( < button className = "clear-completed" + onClick = { this.onClearCompleted.bind(this) } > + Clear completed < /button> ) } } render() { - return ( - - ) + return ( < footer className = "footer" > { this.renderTodoCount() } < ul className = "filters" > { + [SHOW_ALL, SHOW_ACTIVE, SHOW_COMPLETED].map(filter => + < li key = { filter } > { this.renderFilterLink(filter) } < /li> + ) + } < /ul> { this.renderClearButton() } < /footer>) } } Footer.propTypes = { - completedCount: PropTypes.number.isRequired, - activeCount: PropTypes.number.isRequired, - filter: PropTypes.string.isRequired, - onClearCompleted: PropTypes.func.isRequired, - onShow: PropTypes.func.isRequired + todos: PropTypes.array.isRequired, + todoActions: PropTypes.object.isRequired, + filterActions: PropTypes.object.isRequired } export default Footer + diff --git a/examples/todomvc/components/TodoItem.js b/examples/todomvc/components/TodoItem.js index a892951842..fa75646384 100644 --- a/examples/todomvc/components/TodoItem.js +++ b/examples/todomvc/components/TodoItem.js @@ -14,6 +14,16 @@ class TodoItem extends Component { this.setState({ editing: true }) } + handleClick(evt) { + evt.preventDefault(); + // because of linkState call in render, field will get value from this.state.editValue + setTimeout(function () { + if(!this.state.editing){ + this.refs.toggleCompleted.getDOMNode().click(); + } + }.bind(this), 200); + } + handleSave(id, text) { if (text.length === 0) { this.props.deleteTodo(id) @@ -36,11 +46,11 @@ class TodoItem extends Component { } else { element = (
- completeTodo(todo.id)} /> -