mirror of
https://github.com/usatiuk/ustk-todolist.git
synced 2025-10-28 15:47:48 +01:00
flatten redux store
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { API_ROOT, getToken } from './util';
|
||||
import { RECIEVE_TODOS } from './todos';
|
||||
|
||||
export const ADD_LIST = 'ADD_LIST';
|
||||
export const REMOVE_LIST = 'REMOVE_LIST';
|
||||
@@ -42,9 +43,6 @@ export function stopCreateList() {
|
||||
export function stopEditList() {
|
||||
return { type: STOP_EDIT_LIST };
|
||||
}
|
||||
function addListToState(list) {
|
||||
return { type: ADD_LIST, list };
|
||||
}
|
||||
|
||||
export function addList(name) {
|
||||
return async dispatch => {
|
||||
@@ -59,16 +57,12 @@ export function addList(name) {
|
||||
});
|
||||
const json = await response.json();
|
||||
const list = json.data;
|
||||
dispatch(addListToState(list));
|
||||
dispatch({ type: ADD_LIST, list });
|
||||
dispatch(changeList(list.id));
|
||||
dispatch(validateLists());
|
||||
};
|
||||
}
|
||||
|
||||
function removeListFromState(id) {
|
||||
return { type: REMOVE_LIST, id };
|
||||
}
|
||||
|
||||
export function removeList() {
|
||||
return async (dispatch, getState) => {
|
||||
let state = getState();
|
||||
@@ -83,7 +77,7 @@ export function removeList() {
|
||||
});
|
||||
const json = await response.json();
|
||||
if (json.success) {
|
||||
dispatch(removeListFromState(list));
|
||||
dispatch({ type: REMOVE_LIST, list });
|
||||
state = getState();
|
||||
const lists = Object.values(state.lists.lists);
|
||||
const newList = lists.length ? lists[lists.length - 1].id : '';
|
||||
@@ -93,10 +87,6 @@ export function removeList() {
|
||||
};
|
||||
}
|
||||
|
||||
function editListNameInState(id, name) {
|
||||
return { type: EDIT_LIST_NAME, id, name };
|
||||
}
|
||||
|
||||
export function editList(name) {
|
||||
return async (dispatch, getState) => {
|
||||
const state = getState();
|
||||
@@ -112,12 +102,25 @@ export function editList(name) {
|
||||
});
|
||||
const json = await response.json();
|
||||
if (json.success) {
|
||||
dispatch(editListNameInState(list, name));
|
||||
dispatch({ type: EDIT_LIST_NAME, list, name });
|
||||
}
|
||||
dispatch(validateLists());
|
||||
};
|
||||
}
|
||||
|
||||
function normalizeTodos(lists) {
|
||||
return lists.reduce((todos, list) => {
|
||||
const listTodosObj = list.todos.reduce(
|
||||
(listTodos, todo) => ({
|
||||
...listTodos,
|
||||
[todo.id]: { ...todo },
|
||||
}),
|
||||
{},
|
||||
);
|
||||
return { ...todos, ...listTodosObj };
|
||||
}, {});
|
||||
}
|
||||
|
||||
export function fetchLists() {
|
||||
return async dispatch => {
|
||||
dispatch(requestLists());
|
||||
@@ -135,11 +138,12 @@ export function fetchLists() {
|
||||
fetching: false,
|
||||
editing: false,
|
||||
...list,
|
||||
todos: [...list.todos.reverse()],
|
||||
todos: list.todos.map(todo => todo.id),
|
||||
};
|
||||
return newObj;
|
||||
}, {});
|
||||
|
||||
dispatch({ type: RECIEVE_TODOS, todos: normalizeTodos(lists) });
|
||||
dispatch(recieveLists(listsObj));
|
||||
if (lists.length !== 0) {
|
||||
dispatch(changeList(listsObj[Object.keys(listsObj)[0]].id));
|
||||
|
||||
@@ -16,20 +16,10 @@ export const VisibilityFilters = {
|
||||
SHOW_ACTIVE: 'SHOW_ACTIVE',
|
||||
};
|
||||
|
||||
function toggleTodoInList(id) {
|
||||
return { type: TOGGLE_TODO, id };
|
||||
}
|
||||
|
||||
export function setVisibilityFilter(filter) {
|
||||
return { type: SET_VISIBILITY_FILTER, filter };
|
||||
}
|
||||
|
||||
function requestTodos(list) {
|
||||
return { type: REQUEST_TODOS, list };
|
||||
}
|
||||
function recieveTodos(list, todos) {
|
||||
return { type: RECIEVE_TODOS, list, todos };
|
||||
}
|
||||
function invalidateTodos() {
|
||||
return { type: INVALIDATE_TODOS };
|
||||
}
|
||||
@@ -37,10 +27,6 @@ function validateTodos() {
|
||||
return { type: VALIDATE_TODOS };
|
||||
}
|
||||
|
||||
function addTodoToList(todo) {
|
||||
return { type: ADD_TODO, todo };
|
||||
}
|
||||
|
||||
export function addTodo(text) {
|
||||
return async (dispatch, getState) => {
|
||||
const state = getState();
|
||||
@@ -57,16 +43,12 @@ export function addTodo(text) {
|
||||
});
|
||||
const json = await response.json();
|
||||
const todo = json.data;
|
||||
dispatch(addTodoToList(todo));
|
||||
dispatch({ type: ADD_TODO, todo });
|
||||
dispatch(validateTodos());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function removeTodoFromList(id) {
|
||||
return { type: REMOVE_TODO, id };
|
||||
}
|
||||
|
||||
export function removeTodo(id) {
|
||||
return async dispatch => {
|
||||
dispatch(invalidateTodos());
|
||||
@@ -79,7 +61,7 @@ export function removeTodo(id) {
|
||||
});
|
||||
const json = await response.json();
|
||||
if (json.success) {
|
||||
dispatch(removeTodoFromList(id));
|
||||
dispatch({ type: REMOVE_TODO, id });
|
||||
}
|
||||
dispatch(validateTodos());
|
||||
};
|
||||
@@ -89,8 +71,7 @@ export function toggleTodo(id) {
|
||||
return async (dispatch, getState) => {
|
||||
dispatch(invalidateTodos());
|
||||
const state = getState();
|
||||
const listObj = state.lists.lists[state.lists.list];
|
||||
const todoObj = listObj.todos.find(todo => todo.id === id);
|
||||
const todoObj = state.todos.todos[id];
|
||||
const completed = !todoObj.completed;
|
||||
const response = await fetch(`${API_ROOT}/todos/${id}`, {
|
||||
body: JSON.stringify({ completed }),
|
||||
@@ -102,16 +83,12 @@ export function toggleTodo(id) {
|
||||
});
|
||||
const json = await response.json();
|
||||
if (json.success) {
|
||||
dispatch(toggleTodoInList(id));
|
||||
dispatch({ type: TOGGLE_TODO, id });
|
||||
}
|
||||
dispatch(validateTodos());
|
||||
};
|
||||
}
|
||||
|
||||
function editTodoInList(id, todo) {
|
||||
return { type: EDIT_TODO, id, todo };
|
||||
}
|
||||
|
||||
export function editTodo(id, text) {
|
||||
return async dispatch => {
|
||||
dispatch(invalidateTodos());
|
||||
@@ -126,7 +103,7 @@ export function editTodo(id, text) {
|
||||
const json = await response.json();
|
||||
if (json.success) {
|
||||
const todo = json.data;
|
||||
dispatch(editTodoInList(id, todo));
|
||||
dispatch({ type: EDIT_TODO, id, todo });
|
||||
}
|
||||
dispatch(validateTodos());
|
||||
};
|
||||
@@ -134,14 +111,14 @@ export function editTodo(id, text) {
|
||||
|
||||
export function fetchTodos(list) {
|
||||
return async dispatch => {
|
||||
dispatch(requestTodos(list));
|
||||
const response = await fetch(`${API_ROOT}/lists/${list.id}/todos`, {
|
||||
dispatch({ type: REQUEST_TODOS, list });
|
||||
const response = await fetch(`${API_ROOT}/todos`, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${getToken()}`,
|
||||
},
|
||||
});
|
||||
const json = await response.json();
|
||||
const todos = json.data;
|
||||
dispatch(recieveTodos(list, todos));
|
||||
dispatch({ type: RECIEVE_TODOS, todos });
|
||||
};
|
||||
}
|
||||
|
||||
@@ -16,4 +16,7 @@ function mapDispatchToProps(dispatch) {
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(App);
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps,
|
||||
)(App);
|
||||
|
||||
@@ -9,14 +9,10 @@ import {
|
||||
} from '../actions/lists';
|
||||
|
||||
function mapStateToProps(state) {
|
||||
const editing =
|
||||
state.lists.list && !state.lists.dirty
|
||||
? state.lists.lists[state.lists.list].editing
|
||||
: false;
|
||||
return {
|
||||
list: state.lists.list,
|
||||
creating: state.lists.creating,
|
||||
editing,
|
||||
editing: state.lists.editing,
|
||||
};
|
||||
}
|
||||
function mapDispatchToProps(dispatch) {
|
||||
|
||||
@@ -3,14 +3,10 @@ import Selector from '../components/Selector';
|
||||
import { changeList, addList, editList } from '../actions/lists';
|
||||
|
||||
function mapStateToProps(state) {
|
||||
const editing =
|
||||
state.lists.list && !state.lists.dirty
|
||||
? state.lists.lists[state.lists.list].editing
|
||||
: false;
|
||||
return {
|
||||
lists: state.lists,
|
||||
list: state.lists.list,
|
||||
editing,
|
||||
editing: state.lists.editing,
|
||||
creating: state.lists.creating,
|
||||
};
|
||||
}
|
||||
@@ -19,7 +15,7 @@ function mapDispatchToProps(dispatch) {
|
||||
return {
|
||||
onChange: list => dispatch(changeList(list)),
|
||||
addList: name => dispatch(addList(name)),
|
||||
editList: (id, name) => dispatch(editList(id, name)),
|
||||
editList: name => dispatch(editList(name)),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -5,23 +5,17 @@ import { toggleTodo, removeTodo, editTodo } from '../actions/todos';
|
||||
import getVisibleTodos from './getVisibleTodos';
|
||||
|
||||
function mapStateToProps(state) {
|
||||
const { list } = state.lists;
|
||||
try {
|
||||
const listObj = state.lists.lists[list];
|
||||
const listTodos = state.lists.lists[list].todos;
|
||||
|
||||
return {
|
||||
list,
|
||||
todos: getVisibleTodos(listTodos, state.visibilityFilter),
|
||||
dirty: listObj.dirty,
|
||||
};
|
||||
} catch (e) {
|
||||
return {
|
||||
list: '',
|
||||
todos: [],
|
||||
dirty: true,
|
||||
};
|
||||
}
|
||||
return {
|
||||
todos: state.lists.list
|
||||
? getVisibleTodos(
|
||||
state.lists.lists[state.lists.list].todos.map(
|
||||
id => state.todos.todos[id],
|
||||
),
|
||||
state.visibilityFilter,
|
||||
)
|
||||
: [],
|
||||
dirty: state.todos.dirty,
|
||||
};
|
||||
}
|
||||
|
||||
function mapDispatchToProps(dispatch) {
|
||||
|
||||
@@ -17,4 +17,9 @@ function mapDispatchToProps(dispatch) {
|
||||
};
|
||||
}
|
||||
|
||||
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Todos));
|
||||
export default withRouter(
|
||||
connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps,
|
||||
)(Todos),
|
||||
);
|
||||
|
||||
@@ -4,9 +4,11 @@ import { reducer as formReducer } from 'redux-form';
|
||||
import lists from './lists';
|
||||
import visibilityFilter from './visibilityFilter';
|
||||
import user from './user';
|
||||
import todos from './todos';
|
||||
|
||||
const todoApp = combineReducers({
|
||||
lists,
|
||||
todos,
|
||||
visibilityFilter,
|
||||
form: formReducer,
|
||||
user,
|
||||
|
||||
@@ -12,17 +12,7 @@ import {
|
||||
STOP_CREATE_LIST,
|
||||
STOP_EDIT_LIST,
|
||||
} from '../actions/lists';
|
||||
import {
|
||||
ADD_TODO,
|
||||
INVALIDATE_TODOS,
|
||||
VALIDATE_TODOS,
|
||||
REQUEST_TODOS,
|
||||
RECIEVE_TODOS,
|
||||
REMOVE_TODO,
|
||||
TOGGLE_TODO,
|
||||
EDIT_TODO,
|
||||
} from '../actions/todos';
|
||||
import list from './list';
|
||||
import { REMOVE_TODO, ADD_TODO } from '../actions/todos';
|
||||
|
||||
export default function lists(
|
||||
state = {
|
||||
@@ -32,6 +22,7 @@ export default function lists(
|
||||
loaded: false,
|
||||
creating: false,
|
||||
list: null,
|
||||
editing: false,
|
||||
},
|
||||
action,
|
||||
) {
|
||||
@@ -64,45 +55,60 @@ export default function lists(
|
||||
};
|
||||
case REMOVE_LIST: {
|
||||
const newLists = { ...state.lists };
|
||||
delete newLists[action.id];
|
||||
delete newLists[action.list];
|
||||
return {
|
||||
...state,
|
||||
list: null,
|
||||
lists: newLists,
|
||||
};
|
||||
}
|
||||
case START_EDIT_LIST: {
|
||||
return {
|
||||
...state,
|
||||
lists: {
|
||||
...state.lists,
|
||||
[state.list]: {
|
||||
...state.lists[state.list],
|
||||
editing: true,
|
||||
},
|
||||
},
|
||||
editing: true,
|
||||
};
|
||||
}
|
||||
case STOP_EDIT_LIST: {
|
||||
return {
|
||||
...state,
|
||||
lists: {
|
||||
...state.lists,
|
||||
[state.list]: {
|
||||
...state.lists[state.list],
|
||||
editing: false,
|
||||
},
|
||||
},
|
||||
editing: false,
|
||||
};
|
||||
}
|
||||
case EDIT_LIST_NAME: {
|
||||
return {
|
||||
...state,
|
||||
editing: false,
|
||||
lists: {
|
||||
...state.lists,
|
||||
[action.id]: {
|
||||
...state.lists[action.id],
|
||||
[action.list]: {
|
||||
...state.lists[action.list],
|
||||
name: action.name,
|
||||
editing: false,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
case REMOVE_TODO: {
|
||||
return {
|
||||
...state,
|
||||
lists: {
|
||||
...state.lists,
|
||||
[state.list]: {
|
||||
...state.lists[state.list],
|
||||
todos: state.lists[state.list].todos.filter(
|
||||
todo => todo !== action.id,
|
||||
),
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
case ADD_TODO: {
|
||||
return {
|
||||
...state,
|
||||
lists: {
|
||||
...state.lists,
|
||||
[state.list]: {
|
||||
...state.lists[state.list],
|
||||
todos: [action.todo.id, ...state.lists[state.list].todos],
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -122,21 +128,6 @@ export default function lists(
|
||||
...state,
|
||||
fetching: true,
|
||||
};
|
||||
case RECIEVE_TODOS:
|
||||
case ADD_TODO:
|
||||
case EDIT_TODO:
|
||||
case INVALIDATE_TODOS:
|
||||
case VALIDATE_TODOS:
|
||||
case REQUEST_TODOS:
|
||||
case REMOVE_TODO:
|
||||
case TOGGLE_TODO:
|
||||
return {
|
||||
...state,
|
||||
lists: {
|
||||
...state.lists,
|
||||
[state.list]: list(state.lists[state.list], action),
|
||||
},
|
||||
};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
||||
@@ -8,13 +8,13 @@ import {
|
||||
VALIDATE_TODOS,
|
||||
EDIT_TODO,
|
||||
} from '../actions/todos';
|
||||
import { REMOVE_LIST } from '../actions/lists';
|
||||
|
||||
export default function todos(
|
||||
state = {
|
||||
dirty: true,
|
||||
fetching: false,
|
||||
todos: null,
|
||||
editing: false,
|
||||
},
|
||||
action,
|
||||
) {
|
||||
@@ -29,7 +29,7 @@ export default function todos(
|
||||
case ADD_TODO:
|
||||
return {
|
||||
...state,
|
||||
todos: [action.todo, ...state.todos],
|
||||
todos: { [action.todo.id]: action.todo, ...state.todos },
|
||||
};
|
||||
case INVALIDATE_TODOS:
|
||||
return {
|
||||
@@ -44,29 +44,46 @@ export default function todos(
|
||||
case EDIT_TODO:
|
||||
return {
|
||||
...state,
|
||||
todos: state.todos.map(
|
||||
todo => (todo.id === action.id ? action.todo : todo),
|
||||
),
|
||||
todos: {
|
||||
...state.todos,
|
||||
[action.id]: action.todo,
|
||||
},
|
||||
};
|
||||
case REQUEST_TODOS:
|
||||
return {
|
||||
...state,
|
||||
fetching: true,
|
||||
};
|
||||
case REMOVE_TODO:
|
||||
case REMOVE_TODO: {
|
||||
const newTodos = { ...state.todos };
|
||||
delete newTodos[action.id];
|
||||
return {
|
||||
...state,
|
||||
todos: state.todos.filter(todo => todo.id !== action.id),
|
||||
todos: newTodos,
|
||||
};
|
||||
}
|
||||
case REMOVE_LIST: {
|
||||
const newTodos = { ...state.todos };
|
||||
Object.keys(newTodos).forEach(todoId => {
|
||||
if (newTodos[todoId].list === action.list) {
|
||||
delete newTodos[todoId];
|
||||
}
|
||||
});
|
||||
return {
|
||||
...state,
|
||||
todos: newTodos,
|
||||
};
|
||||
}
|
||||
case TOGGLE_TODO: {
|
||||
return {
|
||||
...state,
|
||||
todos: state.todos.map(
|
||||
todo =>
|
||||
todo.id === action.id
|
||||
? { ...todo, completed: !todo.completed }
|
||||
: todo,
|
||||
),
|
||||
todos: {
|
||||
...state.todos,
|
||||
[action.id]: {
|
||||
...state.todos[action.id],
|
||||
completed: !state.todos[action.id].completed,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
default:
|
||||
Reference in New Issue
Block a user