From beb0abfc85d500418792973d9bf5e3894cdd8235 Mon Sep 17 00:00:00 2001 From: Andres Saldarriaga Date: Tue, 23 Jan 2018 15:31:35 -0500 Subject: [PATCH 1/8] update --- index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.html b/index.html index c3452f25e3..b588b33868 100644 --- a/index.html +++ b/index.html @@ -9,5 +9,5 @@
- + From 9d72a23d5f20698561b9976a40d621fd5c532b78 Mon Sep 17 00:00:00 2001 From: Andres Saldarriaga Date: Wed, 24 Jan 2018 09:53:35 -0500 Subject: [PATCH 2/8] actions --- src/actions/index.js | 15 +++++++++++++++ src/components/app.js | 9 --------- src/components/post_index.js | 16 ++++++++++++++++ src/index.js | 27 +++++++++++++++++---------- src/reducers/index.js | 3 ++- src/reducers/reducer_posts.js | 12 ++++++++++++ 6 files changed, 62 insertions(+), 20 deletions(-) delete mode 100644 src/components/app.js create mode 100644 src/components/post_index.js create mode 100644 src/reducers/reducer_posts.js diff --git a/src/actions/index.js b/src/actions/index.js index e69de29bb2..57536c900f 100644 --- a/src/actions/index.js +++ b/src/actions/index.js @@ -0,0 +1,15 @@ +import axios from "axios"; + +export const FETCH_POSTS = "fetch_posts"; +const ROOT_URL = "https://reduxblog.herokuapp.com/api"; +const API_KEY = "?key=mykey4445"; + +export function fetchPosts() { + const url = `${ROOT_URL}/posts${API_KEY}`; + const request = axios.get(url); + + return { + type: FETCH_POSTS, + payload: request + }; +} diff --git a/src/components/app.js b/src/components/app.js deleted file mode 100644 index 58614b02cf..0000000000 --- a/src/components/app.js +++ /dev/null @@ -1,9 +0,0 @@ -import React, { Component } from 'react'; - -export default class App extends Component { - render() { - return ( -
React simple starter
- ); - } -} diff --git a/src/components/post_index.js b/src/components/post_index.js new file mode 100644 index 0000000000..10ed0efa5e --- /dev/null +++ b/src/components/post_index.js @@ -0,0 +1,16 @@ +import React, { Component } from "react"; +import { connect } from "react-redux"; +import { fetchPosts } from "../actions"; + +class PostIndex extends Component { + componentDidMount() { + this.props.fetchPosts(); + } + + render() { + + return
Post Index
; + } +} + +export default connect(null, { fetchPosts })(PostIndex); diff --git a/src/index.js b/src/index.js index 69d577acd1..631382f449 100644 --- a/src/index.js +++ b/src/index.js @@ -1,15 +1,22 @@ -import React from 'react'; -import ReactDOM from 'react-dom'; -import { Provider } from 'react-redux'; -import { createStore, applyMiddleware } from 'redux'; +import React from "react"; +import ReactDOM from "react-dom"; +import { Provider } from "react-redux"; +import { createStore, applyMiddleware } from "redux"; +import { BrowserRouter, Route } from "react-router-dom"; +import promise from "redux-promise"; -import App from './components/app'; -import reducers from './reducers'; +import reducers from "./reducers"; +import PostIndex from "./components/post_index"; -const createStoreWithMiddleware = applyMiddleware()(createStore); +const createStoreWithMiddleware = applyMiddleware(promise)(createStore); ReactDOM.render( - - - , document.querySelector('.container')); + +
+ +
+
+ , + document.querySelector(".container") +); diff --git a/src/reducers/index.js b/src/reducers/index.js index d12506f382..0bdfa58680 100644 --- a/src/reducers/index.js +++ b/src/reducers/index.js @@ -1,7 +1,8 @@ import { combineReducers } from 'redux'; +import PostReducer from './reducer_posts' const rootReducer = combineReducers({ - state: (state = {}) => state + posts: PostReducer }); export default rootReducer; diff --git a/src/reducers/reducer_posts.js b/src/reducers/reducer_posts.js new file mode 100644 index 0000000000..5e6e1d42bf --- /dev/null +++ b/src/reducers/reducer_posts.js @@ -0,0 +1,12 @@ +import _ from "lodash"; +import { FETCH_POSTS } from "../actions"; + +export default function(state = {}, action) { + switch (action.type) { + case FETCH_POSTS: + return _.mapKeys(action.payload.data, 'id'); + + default: + return state; + } +} From 17c0f49bd0d1f2aaa5736d93f1b5c616f4062761 Mon Sep 17 00:00:00 2001 From: Andres Saldarriaga Date: Thu, 25 Jan 2018 09:34:49 -0500 Subject: [PATCH 3/8] blog with glitch --- src/actions/index.js | 28 ++++++++++- src/components/post_index.js | 16 ------ src/components/posts_index.js | 41 ++++++++++++++++ src/components/posts_new.js | 91 +++++++++++++++++++++++++++++++++++ src/components/posts_show.js | 27 +++++++++++ src/index.js | 13 +++-- src/reducers/index.js | 4 +- src/reducers/reducer_posts.js | 11 ++++- style/style.css | 3 ++ 9 files changed, 212 insertions(+), 22 deletions(-) delete mode 100644 src/components/post_index.js create mode 100644 src/components/posts_index.js create mode 100644 src/components/posts_new.js create mode 100644 src/components/posts_show.js diff --git a/src/actions/index.js b/src/actions/index.js index 57536c900f..11bc7cc0e1 100644 --- a/src/actions/index.js +++ b/src/actions/index.js @@ -1,11 +1,18 @@ import axios from "axios"; export const FETCH_POSTS = "fetch_posts"; +export const CREATE_POST = "create_posts"; +export const FETCH_POST = "fetch_post"; + + + const ROOT_URL = "https://reduxblog.herokuapp.com/api"; const API_KEY = "?key=mykey4445"; +const url = `${ROOT_URL}/posts${API_KEY}`; + export function fetchPosts() { - const url = `${ROOT_URL}/posts${API_KEY}`; + const request = axios.get(url); return { @@ -13,3 +20,22 @@ export function fetchPosts() { payload: request }; } + + +export function createPost(values, callback){ +const request = axios.post(url, values) +.then(() => callback()); + return { + type: CREATE_POST, + payload: request + }; +} + +export function fetchPost(id){ + const request = axios.get(`${ROOT_URL}/posts/${id}${API_KEY}`); + + return { + type: FETCH_POST, + payload: request + }; +} \ No newline at end of file diff --git a/src/components/post_index.js b/src/components/post_index.js deleted file mode 100644 index 10ed0efa5e..0000000000 --- a/src/components/post_index.js +++ /dev/null @@ -1,16 +0,0 @@ -import React, { Component } from "react"; -import { connect } from "react-redux"; -import { fetchPosts } from "../actions"; - -class PostIndex extends Component { - componentDidMount() { - this.props.fetchPosts(); - } - - render() { - - return
Post Index
; - } -} - -export default connect(null, { fetchPosts })(PostIndex); diff --git a/src/components/posts_index.js b/src/components/posts_index.js new file mode 100644 index 0000000000..f87b76f6b3 --- /dev/null +++ b/src/components/posts_index.js @@ -0,0 +1,41 @@ +import _ from "lodash"; +import React, { Component } from "react"; + +import { connect } from "react-redux"; +import { Link } from "react-router-dom"; +import { fetchPosts } from "../actions"; + +class PostIndex extends Component { + componentDidMount() { + this.props.fetchPosts(); + } + + renderPosts() { + return _.map(this.props.posts, post => { + return ( +
  • + {post.title} +
  • + ); + }); + } + + render() { + return ( +
    +
    + add a Post +
    + +

    Posts:

    +
      {this.renderPosts()}
    +
    + ); + } +} + +function mapStateToProps(state) { + return { posts: state.posts }; +} + +export default connect(mapStateToProps, { fetchPosts })(PostIndex); diff --git a/src/components/posts_new.js b/src/components/posts_new.js new file mode 100644 index 0000000000..8b44863405 --- /dev/null +++ b/src/components/posts_new.js @@ -0,0 +1,91 @@ +import React, { Component } from "react"; +import { Link } from "react-router-dom"; +import { Field, reduxForm } from "redux-form"; +import {connect} from 'react-redux'; +import {createPost} from '../actions'; + +class PostsNew extends Component { + renderField(field) { + const { meta: { touched, error} } =field; + const className=`form-group ${touched && error ? 'has-danger': ''}`; + return ( +
    + + +
    + {touched ? error: ''} +
    + +
    + ); + } + +onSubmit(values){ + +this.props.createPost(values, () => { + this.props.history.push('/'); + +}); + +} + + render() { + const { handleSubmit } = this.props + return ( +
    + + +
    + + + + + + Cancel + + +
    + ); + } +} + +function validate(values) { + const errors = {}; + + //Validate the inputs from 'values' + if (!values.title) { + errors.title = "Enter a title!"; + } + if (!values.categories) { + errors.categories = "Enter a categories!"; + } + if (!values.content) { + errors.content = "Enter some content!"; + } + + // If errors is empty the form is fine to submit + //If errors has *any* properties, redux form assumes form is valid + return errors; +} + +export default reduxForm({ + validate, + form: "PostsNewForm" +})( + connect(null,{ createPost })(PostsNew) + ); + diff --git a/src/components/posts_show.js b/src/components/posts_show.js new file mode 100644 index 0000000000..6c8f18fa3a --- /dev/null +++ b/src/components/posts_show.js @@ -0,0 +1,27 @@ +import React, { Component } from "react"; +import { connect } from "react-redux"; +import { fetchPost } from "../actions"; + +class PostsShow extends Component { + componentDidMount() { + const { id } = this.props.match.params; + this.props.fetchPost(id); + } + + render() { + const { post } = this.props; + return ( +
    +

    Title

    +
    Categories:
    +

    Content

    +
    + ); + } +} + +function mapStateToProps({ posts }, ownProps) { + return { post: posts[ownProps.match.params.id] }; +} + +export default connect(mapStateToProps, { fetchPost })(PostsShow); diff --git a/src/index.js b/src/index.js index 631382f449..b878c53729 100644 --- a/src/index.js +++ b/src/index.js @@ -2,11 +2,13 @@ import React from "react"; import ReactDOM from "react-dom"; import { Provider } from "react-redux"; import { createStore, applyMiddleware } from "redux"; -import { BrowserRouter, Route } from "react-router-dom"; +import { BrowserRouter, Route, Switch } from "react-router-dom"; import promise from "redux-promise"; import reducers from "./reducers"; -import PostIndex from "./components/post_index"; +import PostsIndex from "./components/posts_index"; +import PostsNew from "./components/posts_new"; +import PostsShow from "./components/posts_show"; const createStoreWithMiddleware = applyMiddleware(promise)(createStore); @@ -14,7 +16,12 @@ ReactDOM.render(
    - + + + + + +
    , diff --git a/src/reducers/index.js b/src/reducers/index.js index 0bdfa58680..d2de719c95 100644 --- a/src/reducers/index.js +++ b/src/reducers/index.js @@ -1,8 +1,10 @@ import { combineReducers } from 'redux'; +import { reducer as formReducer} from 'redux-form'; import PostReducer from './reducer_posts' const rootReducer = combineReducers({ - posts: PostReducer + posts: PostReducer, + form: formReducer }); export default rootReducer; diff --git a/src/reducers/reducer_posts.js b/src/reducers/reducer_posts.js index 5e6e1d42bf..e5b2c5d8b2 100644 --- a/src/reducers/reducer_posts.js +++ b/src/reducers/reducer_posts.js @@ -1,9 +1,18 @@ import _ from "lodash"; -import { FETCH_POSTS } from "../actions"; +import { FETCH_POSTS,FETCH_POST } from "../actions"; export default function(state = {}, action) { switch (action.type) { + case FETCH_POST: + // const post = action.payload.data; + // const newState = { ...state }; + // newState[post.id] = post; + // return newState; + + return{...state, [action.payload.data.id]: action.payload.data}; + case FETCH_POSTS: + return _.mapKeys(action.payload.data, 'id'); default: diff --git a/style/style.css b/style/style.css index e69de29bb2..5f1c816285 100644 --- a/style/style.css +++ b/style/style.css @@ -0,0 +1,3 @@ +form a{ + margin-left:10px; +} \ No newline at end of file From 77256815810a43bda363df206cc7b6f37691e7e1 Mon Sep 17 00:00:00 2001 From: Andres Saldarriaga Date: Thu, 25 Jan 2018 11:13:01 -0500 Subject: [PATCH 4/8] Showing post but not post. --- src/components/posts_show.js | 9 ++++++--- src/index.js | 1 - src/reducers/reducer_posts.js | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/components/posts_show.js b/src/components/posts_show.js index 6c8f18fa3a..84c4054b5d 100644 --- a/src/components/posts_show.js +++ b/src/components/posts_show.js @@ -6,13 +6,16 @@ class PostsShow extends Component { componentDidMount() { const { id } = this.props.match.params; this.props.fetchPost(id); + } render() { + const { post } = this.props; + console.log(post); return (
    -

    Title

    +

    Categories:

    Content

    @@ -21,7 +24,7 @@ class PostsShow extends Component { } function mapStateToProps({ posts }, ownProps) { - return { post: posts[ownProps.match.params.id] }; + return { post: posts[ ownProps.match.params.id ] }; } -export default connect(mapStateToProps, { fetchPost })(PostsShow); +export default connect(mapStateToProps, { fetchPost })(PostsShow); \ No newline at end of file diff --git a/src/index.js b/src/index.js index b878c53729..80091582f9 100644 --- a/src/index.js +++ b/src/index.js @@ -20,7 +20,6 @@ ReactDOM.render( - diff --git a/src/reducers/reducer_posts.js b/src/reducers/reducer_posts.js index e5b2c5d8b2..c834d49468 100644 --- a/src/reducers/reducer_posts.js +++ b/src/reducers/reducer_posts.js @@ -9,7 +9,7 @@ export default function(state = {}, action) { // newState[post.id] = post; // return newState; - return{...state, [action.payload.data.id]: action.payload.data}; + return { ...state, [action.payload.data.id]: action.payload.data}; case FETCH_POSTS: From 1cde3b12e889604b93a91445b61ab9ca30972d94 Mon Sep 17 00:00:00 2001 From: Andres Saldarriaga Date: Thu, 25 Jan 2018 12:13:38 -0500 Subject: [PATCH 5/8] full --- src/actions/index.js | 10 +++++++++ src/components/posts_index.js | 6 +++-- src/components/posts_show.js | 41 +++++++++++++++++++++++++++-------- src/reducers/reducer_posts.js | 21 +++++++++--------- 4 files changed, 57 insertions(+), 21 deletions(-) diff --git a/src/actions/index.js b/src/actions/index.js index 11bc7cc0e1..6735c8cfeb 100644 --- a/src/actions/index.js +++ b/src/actions/index.js @@ -3,6 +3,7 @@ import axios from "axios"; export const FETCH_POSTS = "fetch_posts"; export const CREATE_POST = "create_posts"; export const FETCH_POST = "fetch_post"; +export const DELETE_POST = "delete_post"; @@ -38,4 +39,13 @@ export function fetchPost(id){ type: FETCH_POST, payload: request }; +} + +export function deletePost(id, callback) { + const request = axios.delete(`${ROOT_URL}/posts/${id}${API_KEY}`) +.then(() => callback()); + return { + type: DELETE_POST, + payload: id + }; } \ No newline at end of file diff --git a/src/components/posts_index.js b/src/components/posts_index.js index f87b76f6b3..2850bb5525 100644 --- a/src/components/posts_index.js +++ b/src/components/posts_index.js @@ -14,7 +14,7 @@ class PostIndex extends Component { return _.map(this.props.posts, post => { return (
  • - {post.title} + {post.title}
  • ); }); @@ -24,7 +24,9 @@ class PostIndex extends Component { return (
    - add a Post + + add a Post +

    Posts:

    diff --git a/src/components/posts_show.js b/src/components/posts_show.js index 84c4054b5d..c35fdfb44e 100644 --- a/src/components/posts_show.js +++ b/src/components/posts_show.js @@ -1,30 +1,53 @@ import React, { Component } from "react"; import { connect } from "react-redux"; import { fetchPost } from "../actions"; +import { deletePost } from "../actions"; +import { Link } from "react-router-dom"; class PostsShow extends Component { componentDidMount() { + //To fetch info just once + // if (!this.props.post) { + const { id } = this.props.match.params; + this.props.fetchPost(id); + } + // } + + onDeleteClick(){ const { id } = this.props.match.params; - this.props.fetchPost(id); - + this.props.deletePost(id, () => { + this.props.history.push('/'); + }); } render() { - const { post } = this.props; - console.log(post); + + if (!post) { + return
    Loading...
    ; + } + return (
    -

    -
    Categories:
    -

    Content

    + + Back to index + + +

    {post.title}

    +
    Categories:{post.categories}
    +

    {post.content}

    ); } } function mapStateToProps({ posts }, ownProps) { - return { post: posts[ ownProps.match.params.id ] }; + return { post: posts[ownProps.match.params.id] }; } -export default connect(mapStateToProps, { fetchPost })(PostsShow); \ No newline at end of file +export default connect(mapStateToProps, { fetchPost, deletePost })(PostsShow); diff --git a/src/reducers/reducer_posts.js b/src/reducers/reducer_posts.js index c834d49468..763cd19199 100644 --- a/src/reducers/reducer_posts.js +++ b/src/reducers/reducer_posts.js @@ -1,20 +1,21 @@ import _ from "lodash"; -import { FETCH_POSTS,FETCH_POST } from "../actions"; +import { FETCH_POSTS, FETCH_POST } from "../actions"; export default function(state = {}, action) { switch (action.type) { + + case FETCH_POST: - // const post = action.payload.data; - // const newState = { ...state }; - // newState[post.id] = post; - // return newState; + // const post = action.payload.data; + // const newState = { ...state }; + // newState[post.id] = post; + // return newState; + + return { ...state, [action.payload.data.id]: action.payload.data }; - return { ...state, [action.payload.data.id]: action.payload.data}; - case FETCH_POSTS: - - return _.mapKeys(action.payload.data, 'id'); - + return _.mapKeys(action.payload.data, "id"); + default: return state; } From 4bb1d691d3b45d9bbbb5abb4840719b94c3f5735 Mon Sep 17 00:00:00 2001 From: Andres Saldarriaga Date: Thu, 25 Jan 2018 12:33:09 -0500 Subject: [PATCH 6/8] full --- src/actions/index.js | 19 +++++++------------ src/components/posts_show.js | 3 +-- 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/src/actions/index.js b/src/actions/index.js index 6735c8cfeb..c6ee26971b 100644 --- a/src/actions/index.js +++ b/src/actions/index.js @@ -5,15 +5,11 @@ export const CREATE_POST = "create_posts"; export const FETCH_POST = "fetch_post"; export const DELETE_POST = "delete_post"; - - const ROOT_URL = "https://reduxblog.herokuapp.com/api"; const API_KEY = "?key=mykey4445"; const url = `${ROOT_URL}/posts${API_KEY}`; - export function fetchPosts() { - const request = axios.get(url); return { @@ -22,17 +18,15 @@ export function fetchPosts() { }; } - -export function createPost(values, callback){ -const request = axios.post(url, values) -.then(() => callback()); +export function createPost(values, callback) { + const request = axios.post(url, values).then(() => callback()); return { type: CREATE_POST, payload: request }; } -export function fetchPost(id){ +export function fetchPost(id) { const request = axios.get(`${ROOT_URL}/posts/${id}${API_KEY}`); return { @@ -42,10 +36,11 @@ export function fetchPost(id){ } export function deletePost(id, callback) { - const request = axios.delete(`${ROOT_URL}/posts/${id}${API_KEY}`) -.then(() => callback()); + const request = axios + .delete(`${ROOT_URL}/posts/${id}${API_KEY}`) + .then(() => callback()); return { type: DELETE_POST, payload: id }; -} \ No newline at end of file +} diff --git a/src/components/posts_show.js b/src/components/posts_show.js index c35fdfb44e..8df76bdcf3 100644 --- a/src/components/posts_show.js +++ b/src/components/posts_show.js @@ -1,7 +1,6 @@ import React, { Component } from "react"; import { connect } from "react-redux"; -import { fetchPost } from "../actions"; -import { deletePost } from "../actions"; +import { fetchPost, deletePost } from "../actions"; import { Link } from "react-router-dom"; class PostsShow extends Component { From a736271b3a3fa0aead40b125da290d2b30e44f07 Mon Sep 17 00:00:00 2001 From: Andres Saldarriaga Date: Thu, 25 Jan 2018 12:59:44 -0500 Subject: [PATCH 7/8] complete --- src/reducers/reducer_posts.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/reducers/reducer_posts.js b/src/reducers/reducer_posts.js index 763cd19199..7962e9a2a4 100644 --- a/src/reducers/reducer_posts.js +++ b/src/reducers/reducer_posts.js @@ -1,9 +1,10 @@ import _ from "lodash"; -import { FETCH_POSTS, FETCH_POST } from "../actions"; +import { FETCH_POSTS, FETCH_POST, DELETE_POST } from "../actions"; export default function(state = {}, action) { switch (action.type) { - + case DELETE_POST: + return _.omit(state, action.payload); case FETCH_POST: // const post = action.payload.data; From 645bfdd79ea036674f56e0203ac2a19dd93a4743 Mon Sep 17 00:00:00 2001 From: Andres Saldarriaga Date: Thu, 25 Jan 2018 14:34:47 -0500 Subject: [PATCH 8/8] css --- src/components/posts_new.js | 2 +- src/index.js | 1 + style/style.css | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/components/posts_new.js b/src/components/posts_new.js index 8b44863405..4f27d97e80 100644 --- a/src/components/posts_new.js +++ b/src/components/posts_new.js @@ -54,7 +54,7 @@ this.props.createPost(values, () => { - + Cancel diff --git a/src/index.js b/src/index.js index 80091582f9..4db991f9ba 100644 --- a/src/index.js +++ b/src/index.js @@ -4,6 +4,7 @@ import { Provider } from "react-redux"; import { createStore, applyMiddleware } from "redux"; import { BrowserRouter, Route, Switch } from "react-router-dom"; import promise from "redux-promise"; +import '/style/style.css'; import reducers from "./reducers"; import PostsIndex from "./components/posts_index"; diff --git a/style/style.css b/style/style.css index 5f1c816285..efb9b1240d 100644 --- a/style/style.css +++ b/style/style.css @@ -1,3 +1,4 @@ form a{ margin-left:10px; + } \ No newline at end of file