Can now display comment sections

This commit is contained in:
Jubbeart 2018-02-04 17:44:04 +01:00
parent 1a1715a983
commit c0ce3aa5ab
22 changed files with 393 additions and 234 deletions

View file

@ -20,29 +20,12 @@
"import/no-unresolved": "off",
"import/prefer-default-export": "off",
"jsx-a11y/anchor-has-content": "off",
"jsx-a11y/anchor-is-valid": [
"error",
{
"aspects": [
"invalidHref",
"noHref",
"preferButton"
],
"components": [
"Link"
],
"specialLink": [
"hrefLeft",
"hrefRight",
"to"
]
}
],
"jsx-a11y/anchor-is-valid": "off",
"jsx-quotes": [
"error",
"prefer-single"
],
"max-len": "warn",
"max-len": "off",
"no-param-reassign": "warn",
"no-plusplus": [
"error",
@ -63,6 +46,8 @@
],
"no-use-before-define": "off",
"import/first": "off",
"prefer-destructuring": "off"
"prefer-destructuring": "off",
"jsx-a11y/click-events-have-key-events": "off",
"jsx-a11y/no-static-element-interactions": "off"
}
}

View file

@ -5,6 +5,8 @@ Just go to a reddit thread and change the `reddit` in the URL to `removeddit` to
This is a done by comparing the comments found from Reddit API and comments being stored in [Jason Baumgartners](https://pushshift.io/) [Pushshift Reddit API](https://github.com/pushshift/api). The frontend is written in react with redux for state management. There's also a seperate [backend](https://github.com/JubbeArt/removeddit-api) used for storing removed threads and banned subreddits.
# Development
Get lastest version of [Node](https://nodejs.org/en/download/current/)
```
sudo git clone https://github.com/JubbeArt/removeddit.git && cd removeddit
npm install

View file

@ -44,11 +44,13 @@ export const getComments = threadID => {
.then(comments => comments.map(comment => {
comment._source.id = toBase36(comment._id)
// Missing parent id === direct reply to thread
if (!comment._source.parent_id) {
console.error('MISSING PARENT ID')
comment._source.parent_id = threadID
} else {
comment._source.parent_id = toBase36(comment._source.parent_id)
}
comment._source.parent_id = toBase36(comment._source.parent_id)
return comment._source
}))
)

View file

@ -1,7 +1,7 @@
import React from 'react'
import { prettyScore, prettyDate, parse } from 'utils'
import { prettyScore, prettyDate, parse, sortComments } from 'utils'
export default (props) => {
const Comment = (props) => {
let commentStyle = 'comment '
if (props.removed) {
@ -18,12 +18,18 @@ export default (props) => {
return (
<div id={props.id} className={commentStyle}>
<div className='comment-head'>
<button onClick={false} className='author'>[]</button>
<a href={`https://www.reddit.com/user/${props.author}`} className='author comment-author'>
<a href='#' onClick={() => false} className='author'>[]</a>
<span className='space' />
<a
href={props.author !== '[deleted]' ? `https://www.reddit.com/user/${props.author}` : undefined}
className='author comment-author'
>
{props.author}
{props.deleted && ' (deleted by user)'}
</a>
<span className='space' />
<span className='comment-score'>{prettyScore(props.score)} point{(props.score !== 1) && 's'}</span>
<span className='space' />
<span className='comment-time'>{prettyDate(props.created_utc)}</span>
</div>
<div className='comment-body' dangerouslySetInnerHTML={{ __html: innerHTML }} />
@ -32,6 +38,16 @@ export default (props) => {
<a href={`https://www.reddit.com${permalink}`}>reddit</a>
<a href={`https://snew.github.io${permalink}`}>ceddit</a>
</div>
<div>
{props.replies.map(comment => (
<Comment
key={comment.id}
{...comment}
/>
))}
</div>
</div>
)
}
export default Comment

View file

@ -0,0 +1,13 @@
import React from 'react'
export default props => (
<div id='comment-info'>
<span className='removed-text'>
removed comments: {props.removed}/{props.total} ({((100 * props.removed) / props.total).toFixed(1)}%)
</span>
<br />
<span className='deleted-text'>
deleted comments: {props.deleted}/{props.total} ({((100 * props.deleted) / props.total).toFixed(1)}%)
</span>
</div>
)

View file

@ -1,18 +1,81 @@
import React from 'react'
import Comment from 'components/Comment'
import CommentInfo from 'components/CommentInfo'
import SortBy from 'components/SortBy'
import { topSort, bottomSort, newSort, oldSort } from 'utils'
const arrayToLookup = commentList => {
const arrayToLookup = (commentList, removed, deleted) => {
const lookup = {}
commentList.forEach(comment => {
comment.replies = []
if (removed.includes(comment.id)) {
comment.removed = true
} else if (deleted.includes(comment.id)) {
comment.deleted = true
}
lookup[comment.id] = comment
})
return lookup
}
const unflatten = (comments, root, removed, deleted) => {
const lookup = arrayToLookup(comments, removed, deleted)
const commentTree = []
Object.keys(lookup).forEach(commentID => {
const comment = lookup[commentID]
const parentID = comment.parent_id
if (parentID === root) {
commentTree.push(comment)
} else {
lookup[parentID].replies.push(comment)
}
})
return commentTree
}
const sortCommentTree = (comments, sortFunction) => {
comments.sort(sortFunction)
comments.forEach(comment => {
if (comment.replies.length > 0) {
sortCommentTree(comment.replies, sortFunction)
}
})
}
const commentSection = (props) => {
const commentTree = unflatten(props.comments, props.root, props.removed, props.deleted)
sortCommentTree(commentTree, newSort)// props.comments.sort(topSort)
export default (props) => {
const { children } = props
console.log('COMMENT SECTION RENDERED')
console.log(props.root)
console.log(commentTree)
return (
<div>
<h1>{props.root}</h1>
<h1>{children}</h1>
<CommentInfo
total={props.comments.length}
removed={props.removed.length}
deleted={props.deleted.length}
/>
<SortBy />
{commentTree.map(comment => (
<Comment
key={comment.id}
{...comment}
/>
))}
</div>
)
}
export default commentSection

View file

@ -0,0 +1,23 @@
import React from 'react'
export default props => (
<div id='comment-sort'>
sorted by:
<span className='space' />
<select>
<option value='top'>top</option>
<option value='bottom'>bottom</option>
<option value='new'>new</option>
<option value='old'>old</option>
</select>
<span className='space' />
show:
<span className='space' />
<select>
<option value='all'>All comments</option>
<option value='removed-deleted'>Removed and deleted</option>
<option value='removed'>Removed</option>
<option value='deleted'>Deleted</option>
</select>
</div>
)

View file

@ -3,13 +3,12 @@ import ReactDOM from 'react-dom'
import { Provider } from 'react-redux'
import { store } from 'state'
import App from 'App'
// import { setStatusLoading } from 'state'
import '../sass/main.sass'
import '../sass/index.sass'
// ReactDOM.render(
// <Provider store={store}>
// <App />
// </Provider>,
// document.getElementById('app')
// )
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('app')
)

View file

@ -50,14 +50,18 @@ export default class Thread extends React.Component {
const pushshiftComments = results[1]
this.setState({ pushshiftComments })
// Extract ids from pushshift response
const ids = pushshiftComments.map(comment => comment.id)
console.log('pushshift:', ids.length)
// Get all the comments from reddit
return getRedditComments(ids)
})
.then(redditComments => {
console.log('reddit:', redditComments.length)
const removed = []
const deleted = []
// Check what as removed / deleted according to reddit
redditComments.forEach(comment => {
if (isRemoved(comment.body)) {
removed.push(comment.id)
@ -76,11 +80,13 @@ export default class Thread extends React.Component {
}
render() {
console.log('loading', this.state.loadingComments)
return (
<div>
<Post {...this.state.post} />
{
this.state.loadingComments &&
!this.state.loadingComments &&
<CommentSection
root={this.state.post.id}
comments={this.state.pushshiftComments}

View file

@ -83,3 +83,28 @@ export const prettyScore = score => {
return score
}
// Sorting for comments
export const topSort = (commentA, commentB) => {
if (commentA.score > commentB.score) return -1
if (commentA.score < commentB.score) return 1
return 0
}
export const bottomSort = (commentA, commentB) => {
if (commentA.score < commentB.score) return -1
if (commentA.score > commentB.score) return 1
return 0
}
export const newSort = (commentA, commentB) => {
if (commentA.created_utc < commentB.created_utc) return -1
if (commentA.created_utc > commentB.created_utc) return 1
return 0
}
export const oldSort = (commentA, commentB) => {
if (commentA.created_utc < commentB.created_utc) return -1
if (commentA.created_utc > commentB.created_utc) return 1
return 0
}

View file

@ -1,33 +1,33 @@
#main-box
margin: 0 auto
padding: 20px
border-radius: 5px
color: #fff
word-wrap: break-word
max-width: 800px
background-color: #161616
margin: 0 auto
padding: 20px
border-radius: 5px
color: #fff
word-wrap: break-word
max-width: 800px
background-color: #161616
h2
margin: 20px 0px 12px
h2
margin: 20px 0px 12px
h2.about
margin: 0
color: $red
h2.todo
color: #239f2b
h2.contact
color: #1b767a
h2.about
margin: 0
color: $red
h2.todo
color: #239f2b
h2.contact
color: #1b767a
ul
padding-left: 30px
margin: 0
ul
padding-left: 30px
margin: 0
.bookmarklet
background: $red
color: #fff
padding: 9px
font-size: large
font-weight: bold
display: inline-block
border-radius: 5px
margin: 0 7px
.bookmarklet
background: $red
color: #fff
padding: 9px
font-size: large
font-weight: bold
display: inline-block
border-radius: 5px
margin: 0 7px

7
src/sass/colors.sass Normal file
View file

@ -0,0 +1,7 @@
$background: #262626
$red: #c70300
$blue: #00007d
$link: #8cb3d9
$author: #6a98af
$removed: #840c09
$deleted: #00007d

View file

@ -1,46 +1,61 @@
.comment
margin: 0 0 8px 0
padding: 5px 8px 5px 30px
border: 1px solid #333
border-radius: 3px
color: #ddd
font-size: 14px
margin: 0 0 8px 0
padding: 5px 8px 5px 30px
border: 1px solid #333
border-radius: 3px
color: #ddd
font-size: 14px
.comment-head
font-size: 10px
.comment-head
font-size: 10px
.comment-author
font-weight: bold
.comment-author
font-weight: bold
.comment-score
color: #b4b4b4
font-weight: bold
.comment-author:not([href])
color: #828282
.comment-time
color: #828282
.comment-score
color: #b4b4b4
font-weight: bold
.comment-body
max-width: 840px
line-height: 20px
p
margin: 5px 0
line-height: 20px
a:hover
text-decoration: none
.comment-time
color: #828282
.comment-links
margin-bottom: 6px
.comment-body
max-width: 840px
line-height: 20px
p
margin: 5px 0
line-height: 20px
a:hover
text-decoration: none
.comment-links a
color: #828282
font-weight: bold
font-size: 10px
margin-right: 4px
.comment-links
margin-bottom: 6px
.comment-links a
color: #828282
font-weight: bold
font-size: 10px
margin-right: 4px
.comment-odd
background-color: #121212
background-color: #121212
.comment-even
background-color: #161616
background-color: #161616
#comment-info
margin-top: 13px
font-weight: bold
padding-bottom: 5px
border-bottom: 1px dotted #808080
font-size: 16px
#sort-by
color: #828282
font-size: 12px
margin: 5px 0 10px

View file

@ -1,11 +1,3 @@
$background: #262626
$red: #c70300
$blue: #00007d
$link: #8cb3d9
$author: #6a98af
$removed: #840c09
$deleted: #00007d
html, body
margin: 0
padding: 0
@ -16,10 +8,10 @@ html, body
margin: 15px
.removed
background-color: $removed
background-color: $removed
.deleted
background-color: $deleted
background-color: $deleted
.removed-text
color: $red
@ -43,10 +35,10 @@ a:hover
color: inherit
text-decoration: none
@import header
@import about
@import comment
@import post
@import thread
@import subreddit
@import search
.space
margin-left: 5px
select
background: transparent
border: 0
color: #828282

View file

@ -1,40 +1,40 @@
header
background-color: $red///*#19171c;/*#181818*/
display: flex
justify-content: space-between
align-items: center
padding: 10px
#header
a
color: #fff
h1
margin: 7px 0
text-align: center
background-color: $red///*#19171c;/*#181818*/
display: flex
justify-content: space-between
align-items: center
padding: 10px
#header
a
color: #fff
h1
margin: 7px 0
text-align: center
a
transition: color 0.3s
a
transition: color 0.3s
a:hover
text-decoration: none
color: #ff8b88
nav
a
margin: 0 7px
font-size: 20px
#status
display: flex
justify-content: space-between
align-items: center
a:hover
text-decoration: none
color: #ff8b88
nav
a
margin: 0 7px
font-size: 20px
#status
display: flex
justify-content: space-between
align-items: center
#status-text
color: #fff
margin: 0 20px 0 0
#status-text
color: #fff
margin: 0 20px 0 0
#status-image
height: 64px
width: 64px
border-radius: 32px
#status-image
height: 64px
width: 64px
border-radius: 32px

11
src/sass/index.sass Normal file
View file

@ -0,0 +1,11 @@
@import colors
@import common
@import header
@import about
@import comment
@import post
@import thread
@import subreddit
@import search

View file

@ -1,13 +1,13 @@
#comment-info
color: #ca302c
margin-top: 10px
font-weight: bold
padding-bottom: 5px
border-bottom: 1px dotted #808080
font-size: 16px
color: #ca302c
margin-top: 10px
font-weight: bold
padding-bottom: 5px
border-bottom: 1px dotted #808080
font-size: 16px
#comment-sort
color: #808080
font-size: 12px
margin: 5px 0 10px
color: #808080
font-size: 12px
margin: 5px 0 10px

View file

@ -1,52 +1,52 @@
.search-box
font-size: 16px
font-size: 16px
.search-row
padding: 10px 6px 11px
border-bottom: 1px dotted #ccc
min-height: 26px
.search-left
font-weight: bold
display: inline-block
width: 190px
vertical-align: middle
.search-row
padding: 10px 6px 11px
border-bottom: 1px dotted #ccc
min-height: 26px
.search-left
font-weight: bold
display: inline-block
width: 190px
vertical-align: middle
input[type="text"]
font-size: 17px
width: 400px
border-radius: 2px
padding-left: 3px
.radioButton
background: #8a8888
color: black
border-radius: 3px
display: inline-block
margin-right: 9px
transition: all 0.3s
input[type="text"]
font-size: 17px
width: 400px
border-radius: 2px
padding-left: 3px
.radioButton
background: #8a8888
color: black
border-radius: 3px
display: inline-block
margin-right: 9px
transition: all 0.3s
label
padding: 7px 10px 7px 3px
display: inline-block
label
padding: 7px 10px 7px 3px
display: inline-block
input
margin: 0 0 0 5px
height: 35px
display: inline-block
vertical-align: top
select
padding: 3px
font-size: 15px
border-radius: 2px
input
margin: 0 0 0 5px
height: 35px
display: inline-block
vertical-align: top
select
padding: 3px
font-size: 15px
border-radius: 2px
input[type="submit"]
margin: 16px auto 0px
display: block
padding: 9px 16px
font-size: 18px
background: #239f2b
border: 0
border-radius: 2px
color: white
input[type="submit"]
margin: 16px auto 0px
display: block
padding: 9px 16px
font-size: 18px
background: #239f2b
border: 0
border-radius: 2px
color: white

View file

@ -1,29 +1,29 @@
.post-rank
min-width: 20px
color: #505050
font-size: 16px
text-align: right
margin: 14px 4px 0 0
min-width: 20px
color: #505050
font-size: 16px
text-align: right
margin: 14px 4px 0 0
.subreddit-info
border-bottom: 1px dotted gray
padding: 5px 10px
color: #ccc
font-size: 14px
margin-bottom: 5px
border-bottom: 1px dotted gray
padding: 5px 10px
color: #ccc
font-size: 14px
margin-bottom: 5px
select
background: #262626
color: #808080
font-size: 14px
font-weight: bold
text-decoration: underline
border: 0
select
background: #262626
color: #808080
font-size: 14px
font-weight: bold
text-decoration: underline
border: 0
#pagination
border-top: 1px dotted gray
padding: 5px 10px
color: #ccc
font-size: 16px
span, a
margin: 5px
border-top: 1px dotted gray
padding: 5px 10px
color: #ccc
font-size: 16px
span, a
margin: 5px