diff --git a/TODO.md b/TODO.md index b067a1c..9ebdf9e 100644 --- a/TODO.md +++ b/TODO.md @@ -2,4 +2,3 @@ 1. Fix up UX, return errors to screen instead of doing nothing. 2. Add filtering posts by tags -3. Comments diff --git a/src/actions/index.js b/src/actions/index.js index d37274c..af17cf4 100644 --- a/src/actions/index.js +++ b/src/actions/index.js @@ -7,8 +7,11 @@ export const fetchPosts = () => async (dispatch) => { }; export const fetchPost = (slug) => async (dispatch) => { - const response = await sudoscientist.get('/blog/posts/by-slug/' + slug); - dispatch({ type: 'FETCH_POST', payload: response.data }) + const post = await sudoscientist.get('/blog/posts/by-slug/' + slug) + const comments = await sudoscientist.get('/blog/comments/' + post.data.id); + const response = { post: post.data } + response.post.comments = comments.data + dispatch({ type: 'FETCH_POST', payload: response }) }; @@ -61,3 +64,10 @@ export const newBlogPost = (payload) => async (dispatch) => { history.push('/posts/' + response.data.slug) } }; + +export const newComment = (payload, parent_id) => async (dispatch) => { + const response = await sudoscientist.post('/blog/comments/' + parent_id, payload) + if (response.status === 201) { + window.location.reload() + } +}; diff --git a/src/components/Comments.js b/src/components/Comments.js new file mode 100644 index 0000000..362f232 --- /dev/null +++ b/src/components/Comments.js @@ -0,0 +1,49 @@ +import React from 'react'; +import ReactMde from "react-mde"; +import ReactMarkdown from 'react-markdown'; +import { connect } from 'react-redux'; +import 'github-markdown-css' +import "react-mde/lib/styles/css/react-mde-all.css" +import { newComment } from '../actions'; + +const Comment = (props) => { + const [content, setContent] = React.useState(""); + const [selectedTab, setSelectedTab] = React.useState("write"); + const submitComment = () => { + const payload = { + content: content + } + props.newComment(payload, props.post.currentId) + } + return ( +
+
+

Leave a comment!

+
+
+ + Promise.resolve()} + /> +
+
+ +
+
+ ) +} +const mapStateToProps = (state) => { + return { + post: state.posts, + user: state.auth, + }; +} + +export default connect( + mapStateToProps, + { newComment }, +)(Comment); diff --git a/src/components/Post.js b/src/components/Post.js index 350fd85..5ee2765 100644 --- a/src/components/Post.js +++ b/src/components/Post.js @@ -2,57 +2,96 @@ import React from 'react'; import ReactMarkdown from 'react-markdown'; import 'github-markdown-css' import { connect } from 'react-redux'; -import { fetchPost } from '../actions'; +import { fetchPost,newComment } from '../actions'; import { Link } from 'react-router-dom'; +import Comment from './Comments'; class Post extends React.Component { - constructor (props) { - super(props) - this.state = { - isLoading: true - } - } - componentDidMount() { - const { slug } = this.props.match.params - this.props.fetchPost(slug) - .then(() => this.setState({isLoading: false})) + constructor (props) { + super(props) + this.state = { + isLoading: true } + } - render () { - const {posts} = this.props - const {isLoading} = this.state + componentDidMount() { + const { slug } = this.props.match.params + this.props.fetchPost(slug) + .then(() => this.setState({isLoading: false, slug: slug})) + } - if (isLoading) { - return

Loading

- } else { - const post = posts.entities[posts.currentId] - return ( -
-
-
-

{post.title}

-

By {post.author}

-

Posted {post.time_published}

-
- -
-
-
+ renderComments(comments, parent_id) { + if (comments) { + return comments.map(comment => { + return ( +
+
+
Comment by {comment.author}

+ Posted: {comment.time_published} +
+
+
+
+ +
- ); - } +
+

+
+ ); + }); } + } + + renderPost() { + const {posts} = this.props + const post = posts.entities[posts.currentId] + return( +
+
+
+
+

{post.title}

+

By {post.author}

+

Posted {post.time_published}

+
+ +
+
+
+ { this.props.auth.verified && + + } +
+

Comments:

+ { this.renderComments(post.comments,post.id) } +
+ ) + } + + render () { + const {isLoading} = this.state + if (isLoading) { + return

Loading

+ } else { + return ( +
+ { this.renderPost() } +
+ ); + } + } } const mapStateToProps = (state) => { - return { - posts: state.posts, - slug: state.slug, - comments: state.comments - }; + return { + posts: state.posts, + slug: state.slug, + auth: state.auth + }; } export default connect( - mapStateToProps, - { fetchPost } + mapStateToProps, + { fetchPost, newComment }, )(Post); diff --git a/src/components/PostList.js b/src/components/PostList.js index 450a449..24e8805 100644 --- a/src/components/PostList.js +++ b/src/components/PostList.js @@ -7,52 +7,52 @@ import { Link } from 'react-router-dom'; class PostList extends React.Component { - componentDidMount() { - this.props.fetchPosts(); - } - renderList() { - const {posts} = this.props - const postKeys = Object.keys(posts.entities) - return postKeys.map(id => { - const post = posts.entities[id] - return ( -
-
-
-

{post.title}

-

By {post.author}

-

Posted {post.time_published}

-
- -
-
-
-
- ); - }).reverse(); - } - - - render () { - return ( -
-

Blog Posts

-
- {this.renderList()} -
+ componentDidMount() { + this.props.fetchPosts(); + } + renderList() { + const {posts} = this.props + const postKeys = Object.keys(posts.entities) + return postKeys.map(id => { + const post = posts.entities[id] + return ( +
+
+
+

{post.title}

+

By {post.author}

+

Posted {post.time_published}

+
+ +
- ); - } +
+
+ ); + }).reverse(); + } + + + render () { + return ( +
+

Blog Posts

+
+ {this.renderList()} +
+
+ ); + } } const mapStateToProps = (state) => { - return { - posts: state.posts, - slug: state.slug - }; + return { + posts: state.posts, + slug: state.slug + }; } export default connect( - mapStateToProps, - { fetchPosts } + mapStateToProps, + { fetchPosts } )(PostList); diff --git a/src/reducers/postsReducer.js b/src/reducers/postsReducer.js index 87faf24..e9feb70 100644 --- a/src/reducers/postsReducer.js +++ b/src/reducers/postsReducer.js @@ -17,8 +17,8 @@ export default (state = initialState, action) => { return {...state, ...{entities: mergedEntities}} case 'FETCH_POST': - mergedEntities = normalizeEntities(state.entities, [action.payload]) - return {...state, ...{entities: mergedEntities, currentId: action.payload.id}} + mergedEntities = normalizeEntities(state.entities, [action.payload.post]) + return {...state, ...{entities: mergedEntities, currentId: action.payload.post.id}} default: return state; } diff --git a/src/static/about.md b/src/static/about.md index d7b2d5e..5ca6a14 100644 --- a/src/static/about.md +++ b/src/static/about.md @@ -12,6 +12,8 @@ The frontend for this blog is written using react-redux and can be [found here]( ### Communication Matrix: `@Asara:devvul.com` +Fediverse: https://social.devvul.com/Asara + Email: `amarpreet@minhas.io` ### Lightning Network