Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions examples/todomvc/actions/FilterActions.js
Original file line number Diff line number Diff line change
@@ -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}
}
86 changes: 50 additions & 36 deletions examples/todomvc/components/Footer.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
<span className="todo-count">
<strong>{activeCount || 'No'}</strong> {itemWord} left
</span>
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 (
<a className={classnames({ selected: filter === selectedFilter })}
style={{ cursor: 'pointer' }}
onClick={() => onShow(filter)}>
{title}
</a>
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 (
<button className="clear-completed"
onClick={onClearCompleted} >
Clear completed
</button>
return ( < button className = "clear-completed"
onClick = { this.onClearCompleted.bind(this) } >
Clear completed < /button>
)
}
}

render() {
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>
)
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

14 changes: 12 additions & 2 deletions examples/todomvc/components/TodoItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -36,11 +46,11 @@ class TodoItem extends Component {
} else {
element = (
<div className="view">
<input className="toggle"
<input ref="toggleCompleted" className="toggle"
type="checkbox"
checked={todo.completed}
onChange={() => completeTodo(todo.id)} />
<label onDoubleClick={this.handleDoubleClick.bind(this)}>
<label onDoubleClick={this.handleDoubleClick.bind(this)} onClick={this.handleClick.bind(this)}>
{todo.text}
</label>
<button className="destroy"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import React, { Component, PropTypes } from 'react'
import TodoItem from './TodoItem'
import Footer from './Footer'
import { SHOW_ALL, SHOW_COMPLETED, SHOW_ACTIVE } from '../constants/TodoFilters'

const TODO_FILTERS = {
Expand All @@ -9,18 +8,9 @@ const TODO_FILTERS = {
[SHOW_COMPLETED]: todo => todo.completed
}

class MainSection extends Component {
class TodosList extends Component {
constructor(props, context) {
super(props, context)
this.state = { filter: SHOW_ALL }
}

handleClearCompleted() {
this.props.actions.clearCompleted()
}

handleShow(filter) {
this.setState({ filter })
}

renderToggleAll(completedCount) {
Expand All @@ -35,26 +25,9 @@ class MainSection extends Component {
}
}

renderFooter(completedCount) {
const { todos } = this.props
const { filter } = this.state
const activeCount = todos.length - completedCount

if (todos.length) {
return (
<Footer completedCount={completedCount}
activeCount={activeCount}
filter={filter}
onClearCompleted={this.handleClearCompleted.bind(this)}
onShow={this.handleShow.bind(this)} />
)
}
}

render() {
const { todos, actions } = this.props
const { filter } = this.state

const { todos, actions ,filter} = this.props
console.log('TODO_FILTERS',TODO_FILTERS);
const filteredTodos = todos.filter(TODO_FILTERS[filter])
const completedCount = todos.reduce((count, todo) =>
todo.completed ? count + 1 : count,
Expand All @@ -69,15 +42,14 @@ class MainSection extends Component {
<TodoItem key={todo.id} todo={todo} {...actions} />
)}
</ul>
{this.renderFooter(completedCount)}
</section>
)
}
}

MainSection.propTypes = {
TodosList.propTypes = {
todos: PropTypes.array.isRequired,
actions: PropTypes.object.isRequired
}

export default MainSection
export default TodosList
6 changes: 3 additions & 3 deletions examples/todomvc/constants/TodoFilters.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export const SHOW_ALL = 'show_all'
export const SHOW_COMPLETED = 'show_completed'
export const SHOW_ACTIVE = 'show_active'
export const SHOW_ALL = 'SHOW_ALL'
export const SHOW_COMPLETED = 'SHOW_COMPLETED'
export const SHOW_ACTIVE = 'SHOW_ACTIVE'
23 changes: 15 additions & 8 deletions examples/todomvc/containers/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,42 @@ import React, { Component, PropTypes } from 'react'
import { bindActionCreators } from 'redux'
import { connect } from 'react-redux'
import Header from '../components/Header'
import MainSection from '../components/MainSection'
import * as TodoActions from '../actions'
import TodosList from '../components/TodosList'
import Footer from '../components/Footer'
import * as TodoActions from '../actions/TodoActions'
import * as FilterActions from '../actions/FilterActions'

class App extends Component {
render() {
const { todos, actions } = this.props
const { todos, filter, todoActions, filterActions } = this.props
return (
<div>
<Header addTodo={actions.addTodo} />
<MainSection todos={todos} actions={actions} />
<Header addTodo={todoActions.addTodo} />
<TodosList todos={todos} actions={todoActions} filter={filter}/>
<Footer todos={todos} filterActions={filterActions} todoActions={todoActions} />
</div>
)
}
}

App.propTypes = {
todos: PropTypes.array.isRequired,
actions: PropTypes.object.isRequired
filter: PropTypes.string.isRequired,
todoActions: PropTypes.object.isRequired,
filterActions: PropTypes.object.isRequired
}

function mapStateToProps(state) {
return {
todos: state.todos
todos: state.todos,
filter: state.filter
}
}

function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators(TodoActions, dispatch)
todoActions: bindActionCreators(TodoActions, dispatch),
filterActions: bindActionCreators(FilterActions, dispatch)
}
}

Expand Down
18 changes: 18 additions & 0 deletions examples/todomvc/reducers/filter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { SHOW_ALL, SHOW_COMPLETED, SHOW_ACTIVE } from '../constants/TodoFilters'

const filter = (state = 'SHOW_ALL', action) => {
console.log(state, action);
switch (action.type) {
case SHOW_COMPLETED:
return action.type
case SHOW_ACTIVE:
return action.type
case SHOW_ALL:
return action.type
default:
return 'SHOW_ALL'
}
}

export default filter

3 changes: 2 additions & 1 deletion examples/todomvc/reducers/index.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { combineReducers } from 'redux'
import todos from './todos'
import filter from './filter'

const rootReducer = combineReducers({
todos
todos,filter
})

export default rootReducer
11 changes: 6 additions & 5 deletions examples/todomvc/reducers/todos.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export default function todos(state = initialState, action) {
id: state.reduce((maxId, todo) => Math.max(todo.id, maxId), -1) + 1,
completed: false,
text: action.text
},
},
...state
]

Expand All @@ -28,15 +28,15 @@ export default function todos(state = initialState, action) {
case EDIT_TODO:
return state.map(todo =>
todo.id === action.id ?
Object.assign({}, todo, { text: action.text }) :
todo
Object.assign({}, todo, { text: action.text }) :
todo
)

case COMPLETE_TODO:
return state.map(todo =>
todo.id === action.id ?
Object.assign({}, todo, { completed: !todo.completed }) :
todo
Object.assign({}, todo, { completed: !todo.completed }) :
todo
)

case COMPLETE_ALL:
Expand All @@ -52,3 +52,4 @@ export default function todos(state = initialState, action) {
return state
}
}