From 5dd33f9062d51aa2fd4bcefb8fbb4a42b0629614 Mon Sep 17 00:00:00 2001 From: George Lima Date: Wed, 28 Nov 2018 11:06:11 -0300 Subject: [PATCH 1/6] feature: move redux structure to ducks pattern - Remove actions folder - Remove reducers folder - Remove actions constants file - Add redux folder with reducers and store --- app/actions/add-todo.js | 15 --- app/actions/cancel-update-todo.js | 8 -- app/actions/delete-todo.js | 8 -- app/actions/toggle-edit-todo.js | 8 -- app/actions/update-todo.js | 11 --- app/constants/actions.js | 7 -- app/reducers/todo.js | 53 ----------- app/{store/configure.js => redux/create.js} | 18 +--- .../index.js => redux/modules/reducer.js} | 4 +- app/redux/modules/todo.js | 92 +++++++++++++++++++ 10 files changed, 99 insertions(+), 125 deletions(-) delete mode 100644 app/actions/add-todo.js delete mode 100644 app/actions/cancel-update-todo.js delete mode 100644 app/actions/delete-todo.js delete mode 100644 app/actions/toggle-edit-todo.js delete mode 100644 app/actions/update-todo.js delete mode 100644 app/constants/actions.js delete mode 100644 app/reducers/todo.js rename app/{store/configure.js => redux/create.js} (61%) rename app/{reducers/index.js => redux/modules/reducer.js} (62%) create mode 100644 app/redux/modules/todo.js diff --git a/app/actions/add-todo.js b/app/actions/add-todo.js deleted file mode 100644 index e2410c6..0000000 --- a/app/actions/add-todo.js +++ /dev/null @@ -1,15 +0,0 @@ -// @flow - -import uuidv4 from 'uuid/v4'; -import { ADD_TODO } from '../constants/actions'; -import { getTimestamp } from '../utils/timestamp'; - -export const addTodo = (text: string) => ({ - type: ADD_TODO, - payload: { - text, - id: uuidv4(), - editing: false, - createdAt: getTimestamp(), - }, -}); diff --git a/app/actions/cancel-update-todo.js b/app/actions/cancel-update-todo.js deleted file mode 100644 index afa0aa0..0000000 --- a/app/actions/cancel-update-todo.js +++ /dev/null @@ -1,8 +0,0 @@ -// @flow - -import { CANCEL_UPDATE_TODO } from '../constants/actions'; - -export const cancelUpdateTodo = (id: string) => ({ - type: CANCEL_UPDATE_TODO, - payload: { id }, -}); diff --git a/app/actions/delete-todo.js b/app/actions/delete-todo.js deleted file mode 100644 index 0378af7..0000000 --- a/app/actions/delete-todo.js +++ /dev/null @@ -1,8 +0,0 @@ -// @flow - -import { DELETE_TODO } from '../constants/actions'; - -export const deleteTodo = (id: string) => ({ - type: DELETE_TODO, - payload: { id }, -}); diff --git a/app/actions/toggle-edit-todo.js b/app/actions/toggle-edit-todo.js deleted file mode 100644 index fd59481..0000000 --- a/app/actions/toggle-edit-todo.js +++ /dev/null @@ -1,8 +0,0 @@ -// @flow - -import { TOGGLE_EDIT_TODO } from '../constants/actions'; - -export const toggleEdit = (id: string) => ({ - type: TOGGLE_EDIT_TODO, - payload: { id }, -}); diff --git a/app/actions/update-todo.js b/app/actions/update-todo.js deleted file mode 100644 index 6332fea..0000000 --- a/app/actions/update-todo.js +++ /dev/null @@ -1,11 +0,0 @@ -// @flow - -import { UPDATE_TODO } from '../constants/actions'; - -export const updateTodo = (id: string, text: string) => ({ - type: UPDATE_TODO, - payload: { - text, - id, - }, -}); diff --git a/app/constants/actions.js b/app/constants/actions.js deleted file mode 100644 index 84ba2f5..0000000 --- a/app/constants/actions.js +++ /dev/null @@ -1,7 +0,0 @@ -// @flow - -export const ADD_TODO = 'ADD_TODO'; -export const DELETE_TODO = 'DELETE_TODO'; -export const UPDATE_TODO = 'UPDATE_TODO'; -export const TOGGLE_EDIT_TODO = 'TOGGLE_EDIT_TODO'; -export const CANCEL_UPDATE_TODO = 'CANCEL_UPDATE_TODO'; diff --git a/app/reducers/todo.js b/app/reducers/todo.js deleted file mode 100644 index ef1b944..0000000 --- a/app/reducers/todo.js +++ /dev/null @@ -1,53 +0,0 @@ -// @flow - -import { - ADD_TODO, - DELETE_TODO, - UPDATE_TODO, - CANCEL_UPDATE_TODO, - TOGGLE_EDIT_TODO, -} from '../constants/actions'; -import type { TodoType } from '../types/todo'; -import type { Action } from '../types/redux'; - -const initialState = []; - -export default (state: Array = initialState, action: Action) => { - switch (action.type) { - case ADD_TODO: - return [ - ...state, - action.payload, - ]; - case DELETE_TODO: - // $FlowFixMe - return state.filter((todo: Object) => todo.id !== action.payload.id); - case TOGGLE_EDIT_TODO: { - const { id } = action.payload; - const todos = [...state]; - const index = todos.map(todo => todo.id).indexOf(id); - todos[index].editing = true; - - return todos; - } - case UPDATE_TODO: { - const { id, text } = action.payload; - const todos = [...state]; - const index = todos.map(todo => todo.id).indexOf(id); - todos[index].text = text; - todos[index].editing = false; - - return todos; - } - case CANCEL_UPDATE_TODO: { - const { id } = action.payload; - const todos = [...state]; - const index = todos.map(todo => todo.id).indexOf(id); - todos[index].editing = false; - - return todos; - } - default: - return state; - } -}; diff --git a/app/store/configure.js b/app/redux/create.js similarity index 61% rename from app/store/configure.js rename to app/redux/create.js index 5acf821..a0cd79a 100644 --- a/app/store/configure.js +++ b/app/redux/create.js @@ -4,21 +4,15 @@ import { createStore, applyMiddleware, compose } from 'redux'; import { routerMiddleware } from 'connected-react-router'; import { createBrowserHistory } from 'history'; import thunk from 'redux-thunk'; -import { createRootReducer } from '../reducers'; +import { createRootReducer } from './modules/reducer'; export const history = createBrowserHistory(); export const configureStore = (initialState: Object) => { let enhancer; - const middleware = applyMiddleware( - thunk, - routerMiddleware(history), - ); + const middleware = applyMiddleware(thunk, routerMiddleware(history)); - if ( - process.env.NODE_ENV !== 'production' - || process.env.NODE_ENV !== 'staging' - ) { + if (process.env.NODE_ENV !== 'production' || process.env.NODE_ENV !== 'staging') { enhancer = compose( middleware, window.devToolsExtension ? window.devToolsExtension() : f => f, @@ -27,9 +21,5 @@ export const configureStore = (initialState: Object) => { enhancer = compose(middleware); } - return createStore( - createRootReducer(history), - initialState, - enhancer, - ); + return createStore(createRootReducer(history), initialState, enhancer); }; diff --git a/app/reducers/index.js b/app/redux/modules/reducer.js similarity index 62% rename from app/reducers/index.js rename to app/redux/modules/reducer.js index e91c19d..089bafa 100644 --- a/app/reducers/index.js +++ b/app/redux/modules/reducer.js @@ -2,9 +2,11 @@ import { combineReducers } from 'redux'; import { connectRouter } from 'connected-react-router'; +import type { History } from 'react-router-dom'; + import todoReducer from './todo'; -export const createRootReducer = (history: Object) => combineReducers({ +export const createRootReducer = (history: History) => combineReducers({ todos: todoReducer, router: connectRouter(history), }); diff --git a/app/redux/modules/todo.js b/app/redux/modules/todo.js new file mode 100644 index 0000000..9b50bf7 --- /dev/null +++ b/app/redux/modules/todo.js @@ -0,0 +1,92 @@ +// @flow + +import UUID from 'uuid/v4'; + +import { getTimestamp } from '../../utils/timestamp'; + +import type { Action } from '../../types/redux'; +import type { TodoType } from '../../types/todo'; + +// Actions +export const ADD_TODO = 'ADD_TODO'; +export const DELETE_TODO = 'DELETE_TODO'; +export const UPDATE_TODO = 'UPDATE_TODO'; +export const TOGGLE_EDIT_TODO = 'TOGGLE_EDIT_TODO'; +export const CANCEL_UPDATE_TODO = 'CANCEL_UPDATE_TODO'; + +// Actions Creators +export const addTodo = (text: string) => ({ + type: ADD_TODO, + payload: { + text, + id: UUID(), + editing: false, + createdAt: getTimestamp(), + }, +}); + +export const cancelUpdateTodo = (id: string) => ({ + type: CANCEL_UPDATE_TODO, + payload: { id }, +}); + +export const deleteTodo = (id: string) => ({ + type: DELETE_TODO, + payload: { id }, +}); + +export const toggleEdit = (id: string) => ({ + type: TOGGLE_EDIT_TODO, + payload: { id }, +}); + +export const updateTodo = (id: string, text: string) => ({ + type: UPDATE_TODO, + payload: { + text, + id, + }, +}); + +// Initial State +const initialState = []; + +// Reducers +export default (state: Array = initialState, action: Action) => { + switch (action.type) { + case ADD_TODO: + return [...state, action.payload]; + case DELETE_TODO: + // $FlowFixMe + return state.filter((todo: Object) => todo.id !== action.payload.id); + case TOGGLE_EDIT_TODO: { + const { id } = action.payload; + const todos = [...state]; + const index = todos.map(todo => todo.id).indexOf(id); + todos[index].editing = true; + + return todos; + } + case UPDATE_TODO: { + const { id, text } = action.payload; + const todos = [...state]; + const index = todos.map(todo => todo.id).indexOf(id); + todos[index].text = text; + todos[index].editing = false; + + return todos; + } + case CANCEL_UPDATE_TODO: { + const { id } = action.payload; + const todos = [...state]; + const index = todos.map(todo => todo.id).indexOf(id); + todos[index].editing = false; + + return todos; + } + default: + return state; + } +}; + +// SideEffects From 156fc925841bebec908f90e82c0112f12981f134 Mon Sep 17 00:00:00 2001 From: George Lima Date: Wed, 28 Nov 2018 11:06:29 -0300 Subject: [PATCH 2/6] hotfix: redux modules imports --- app/app.js | 2 +- app/containers/todo.js | 9 ++++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/app/app.js b/app/app.js index c6dff33..7d632aa 100644 --- a/app/app.js +++ b/app/app.js @@ -3,7 +3,7 @@ import React from 'react'; import { Provider } from 'react-redux'; import { ConnectedRouter } from 'connected-react-router'; -import { configureStore, history } from './store/configure'; +import { configureStore, history } from './redux/create'; import { Router } from './router/container'; const store = configureStore({}); diff --git a/app/containers/todo.js b/app/containers/todo.js index fbdb389..6d32347 100644 --- a/app/containers/todo.js +++ b/app/containers/todo.js @@ -2,11 +2,10 @@ import { connect } from 'react-redux'; import TodoView from '../views/todo'; -import { addTodo } from '../actions/add-todo'; -import { deleteTodo } from '../actions/delete-todo'; -import { toggleEdit } from '../actions/toggle-edit-todo'; -import { updateTodo } from '../actions/update-todo'; -import { cancelUpdateTodo } from '../actions/cancel-update-todo'; +import { + addTodo, deleteTodo, toggleEdit, updateTodo, cancelUpdateTodo, +} from '../redux/modules/todo'; + import type { AppState } from '../types/app-state'; import type { Dispatch } from '../types/redux'; From 4f2b5668587bb9a2f38e5c2aca253514f90b3fad Mon Sep 17 00:00:00 2001 From: George Lima Date: Wed, 28 Nov 2018 11:07:09 -0300 Subject: [PATCH 3/6] hotfix: add deb linux build target --- package.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 27f0257..bae8c8c 100644 --- a/package.json +++ b/package.json @@ -105,7 +105,10 @@ "./node_modules/**/*" ], "linux": { - "icon": "./build/icons/png" + "icon": "./build/icons/png", + "target": [ + "deb" + ] }, "mac": { "category": "public.app-category.productivity", From 1dc5c9877df589c4f56fdde9e1f6e7f9f7cf7a1f Mon Sep 17 00:00:00 2001 From: George Lima Date: Wed, 28 Nov 2018 16:32:08 -0300 Subject: [PATCH 4/6] chore: increase eslint line max-len --- .eslintrc | 59 +++++++++++++++++++++++-------------------------------- 1 file changed, 25 insertions(+), 34 deletions(-) diff --git a/.eslintrc b/.eslintrc index 4cbfd67..172b7ce 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,9 +1,6 @@ { "parser": "babel-eslint", - "extends": [ - "airbnb", - "plugin:flowtype/recommended" - ], + "extends": ["airbnb", "plugin:flowtype/recommended"], "env": { "browser": true, "node": true, @@ -17,39 +14,33 @@ }, "rules": { "jsx-quotes": ["error", "prefer-single"], - "import/prefer-default-export": [ - "off" - ], - "react/jsx-filename-extension": [ - 1, - { "extensions": [".js"] } - ], + "import/prefer-default-export": ["off"], + "react/jsx-filename-extension": [1, { "extensions": [".js"] }], "jsx-a11y/anchor-is-valid": [ "error", { - "components": [ - "Link" - ], - "specialLink": [ - "to", - "hrefLeft", - "hrefRight" - ], - "aspects": [ - "noHref", - "invalidHref", - "preferButton" - ] + "components": ["Link"], + "specialLink": ["to", "hrefLeft", "hrefRight"], + "aspects": ["noHref", "invalidHref", "preferButton"] } ], - "jsx-a11y/no-autofocus": [ 0, { - "ignoreNonDOM": true - }], - "max-len": ["error", { - "ignoreUrls": true, - "ignoreComments": true, - "ignoreStrings": true, - "ignorePattern": "]*>.*?

" - }] + "jsx-a11y/no-autofocus": [ + 0, + { + "ignoreNonDOM": true + } + ], + "max-len": [ + "error", + { + "code": 120, + "tabWidth": 2, + "ignoreUrls": true, + "ignoreComments": true, + "ignoreStrings": true, + "ignorePattern": "]*>.*?

", + "ignoreTrailingComments": true + } + ] } -} \ No newline at end of file +} From 1de717d31b4a6170e7dc14a711de4d5f3c3bdf40 Mon Sep 17 00:00:00 2001 From: George Lima Date: Wed, 28 Nov 2018 16:32:50 -0300 Subject: [PATCH 5/6] hotfix: remove mutability from reducers --- app/redux/modules/todo.js | 24 +++++------------------- 1 file changed, 5 insertions(+), 19 deletions(-) diff --git a/app/redux/modules/todo.js b/app/redux/modules/todo.js index 9b50bf7..fea3072 100644 --- a/app/redux/modules/todo.js +++ b/app/redux/modules/todo.js @@ -52,37 +52,23 @@ export const updateTodo = (id: string, text: string) => ({ const initialState = []; // Reducers -export default (state: Array = initialState, action: Action) => { +export default (state: Array = initialState, action: Action): Array => { switch (action.type) { case ADD_TODO: return [...state, action.payload]; case DELETE_TODO: - // $FlowFixMe - return state.filter((todo: Object) => todo.id !== action.payload.id); + return state.filter((todo: TodoType) => todo.id !== action.payload.id); case TOGGLE_EDIT_TODO: { const { id } = action.payload; - const todos = [...state]; - const index = todos.map(todo => todo.id).indexOf(id); - todos[index].editing = true; - - return todos; + return state.map(todo => (todo.id === id ? { ...todo, editing: true } : todo)); } case UPDATE_TODO: { const { id, text } = action.payload; - const todos = [...state]; - const index = todos.map(todo => todo.id).indexOf(id); - todos[index].text = text; - todos[index].editing = false; - - return todos; + return state.map(todo => (todo.id === id ? { ...todo, editing: false, text } : todo)); } case CANCEL_UPDATE_TODO: { const { id } = action.payload; - const todos = [...state]; - const index = todos.map(todo => todo.id).indexOf(id); - todos[index].editing = false; - - return todos; + return state.map(todo => (todo.id === id ? { ...todo, editing: false } : todo)); } default: return state; From 22b92bc10d74e271a190249cfdf52c8c7737ecbd Mon Sep 17 00:00:00 2001 From: George Lima Date: Wed, 28 Nov 2018 16:33:19 -0300 Subject: [PATCH 6/6] hotfix: remove mutability from createStore --- app/redux/create.js | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/app/redux/create.js b/app/redux/create.js index a0cd79a..c574d10 100644 --- a/app/redux/create.js +++ b/app/redux/create.js @@ -8,18 +8,15 @@ import { createRootReducer } from './modules/reducer'; export const history = createBrowserHistory(); +const shouldEnableDevTools = (process.env.NODE_ENV !== 'production' || process.env.NODE_ENV !== 'staging') && window.devToolsExtension; + export const configureStore = (initialState: Object) => { - let enhancer; const middleware = applyMiddleware(thunk, routerMiddleware(history)); - if (process.env.NODE_ENV !== 'production' || process.env.NODE_ENV !== 'staging') { - enhancer = compose( - middleware, - window.devToolsExtension ? window.devToolsExtension() : f => f, - ); - } else { - enhancer = compose(middleware); - } + const enhancer = compose( + middleware, + shouldEnableDevTools ? window.devToolsExtension() : f => f, + ); return createStore(createRootReducer(history), initialState, enhancer); };