1
0
Fork 0

Merge branch 'comments' of Asara/sudoscientist-js-frontend into master

This commit is contained in:
Amarpreet Minhas 2020-02-09 19:37:31 -05:00 committed by Gogs
commit b53cd23708
7 changed files with 184 additions and 85 deletions

View file

@ -2,4 +2,3 @@
1. Fix up UX, return errors to screen instead of doing nothing. 1. Fix up UX, return errors to screen instead of doing nothing.
2. Add filtering posts by tags 2. Add filtering posts by tags
3. Comments

View file

@ -7,8 +7,11 @@ export const fetchPosts = () => async (dispatch) => {
}; };
export const fetchPost = (slug) => async (dispatch) => { export const fetchPost = (slug) => async (dispatch) => {
const response = await sudoscientist.get('/blog/posts/by-slug/' + slug); const post = await sudoscientist.get('/blog/posts/by-slug/' + slug)
dispatch({ type: 'FETCH_POST', payload: response.data }) 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) 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()
}
};

View file

@ -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 (
<div>
<div className="comment">
<h3><b>Leave a comment!</b></h3>
</div>
<div className="markdown-body">
<ReactMde
value={content}
onChange={setContent}
selectedTab={selectedTab}
onTabChange={setSelectedTab}
generateMarkdownPreview={(markdown) =>
Promise.resolve(<ReactMarkdown source={markdown} />)}
/>
</div>
<div>
<button onClick={submitComment}>Submit Comment</button>
</div>
</div>
)
}
const mapStateToProps = (state) => {
return {
post: state.posts,
user: state.auth,
};
}
export default connect(
mapStateToProps,
{ newComment },
)(Comment);

View file

@ -2,8 +2,9 @@ import React from 'react';
import ReactMarkdown from 'react-markdown'; import ReactMarkdown from 'react-markdown';
import 'github-markdown-css' import 'github-markdown-css'
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { fetchPost } from '../actions'; import { fetchPost,newComment } from '../actions';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import Comment from './Comments';
class Post extends React.Component { class Post extends React.Component {
constructor (props) { constructor (props) {
@ -12,25 +13,45 @@ class Post extends React.Component {
isLoading: true isLoading: true
} }
} }
componentDidMount() { componentDidMount() {
const { slug } = this.props.match.params const { slug } = this.props.match.params
this.props.fetchPost(slug) this.props.fetchPost(slug)
.then(() => this.setState({isLoading: false})) .then(() => this.setState({isLoading: false, slug: slug}))
} }
render () { renderComments(comments, parent_id) {
const {posts} = this.props if (comments) {
const {isLoading} = this.state return comments.map(comment => {
if (isLoading) {
return <p>Loading</p>
} else {
const post = posts.entities[posts.currentId]
return ( return (
<div key={comment.id}>
<div className="item" style={{outlineOffset: 2, outline: '1px solid', outlineColor: '#DADADA'}}>
<h5><b>Comment by <Link to={"/users/"+ comment.author}>{comment.author}</Link></b><br></br>
Posted: {comment.time_published}
</h5>
<hr></hr>
<div className="content">
<div className="markdown-body">
<ReactMarkdown source={comment.content} />
</div>
</div>
</div>
<br></br>
</div>
);
});
}
}
renderPost() {
const {posts} = this.props
const post = posts.entities[posts.currentId]
return(
<div className="container">
<div className="item" key={post.id}> <div className="item" key={post.id}>
<div className="content"> <div className="content">
<div className="description"> <div className="description">
<h1><b><u><Link to={"/posts/" + post.slug}>{post.title}</Link></u></b></h1> <h4><b><u><Link to={"/posts/" + post.slug}>{post.title}</Link></u></b></h4>
<h3><b>By <Link to={"/users/"+ post.author}>{post.author}</Link></b></h3> <h3><b>By <Link to={"/users/"+ post.author}>{post.author}</Link></b></h3>
<h4>Posted {post.time_published}</h4> <h4>Posted {post.time_published}</h4>
<div className="markdown-body"> <div className="markdown-body">
@ -38,6 +59,24 @@ class Post extends React.Component {
</div> </div>
</div> </div>
</div> </div>
{ this.props.auth.verified &&
<Comment></Comment>
}
</div>
<h3>Comments:</h3>
{ this.renderComments(post.comments,post.id) }
</div>
)
}
render () {
const {isLoading} = this.state
if (isLoading) {
return <p>Loading</p>
} else {
return (
<div>
{ this.renderPost() }
</div> </div>
); );
} }
@ -48,11 +87,11 @@ const mapStateToProps = (state) => {
return { return {
posts: state.posts, posts: state.posts,
slug: state.slug, slug: state.slug,
comments: state.comments auth: state.auth
}; };
} }
export default connect( export default connect(
mapStateToProps, mapStateToProps,
{ fetchPost } { fetchPost, newComment },
)(Post); )(Post);

View file

@ -17,8 +17,8 @@ export default (state = initialState, action) => {
return {...state, ...{entities: mergedEntities}} return {...state, ...{entities: mergedEntities}}
case 'FETCH_POST': case 'FETCH_POST':
mergedEntities = normalizeEntities(state.entities, [action.payload]) mergedEntities = normalizeEntities(state.entities, [action.payload.post])
return {...state, ...{entities: mergedEntities, currentId: action.payload.id}} return {...state, ...{entities: mergedEntities, currentId: action.payload.post.id}}
default: default:
return state; return state;
} }

View file

@ -12,6 +12,8 @@ The frontend for this blog is written using react-redux and can be [found here](
### Communication ### Communication
Matrix: `@Asara:devvul.com` Matrix: `@Asara:devvul.com`
Fediverse: https://social.devvul.com/Asara
Email: `amarpreet@minhas.io` Email: `amarpreet@minhas.io`
### Lightning Network ### Lightning Network