Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add logic for posts and comments #3

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11,624 changes: 11,624 additions & 0 deletions package-lock.json

Large diffs are not rendered by default.

21 changes: 14 additions & 7 deletions src/api/PostsApi.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import http from './httpService'

const RedditApi = (() => {
// const beautifyReplies = (comments) => {
// return comments.map(comment => {
// comment.replies = comment.replies ? comment.replies.data.children.map(reply => reply.data).filter(c => c.body) : [];
// this.beautifyReplies(comment.replies);
// return comment;
// })
// }
const beautifyReplies = (comments) => {
return comments.map(comment => {
comment.replies = comment.replies ? comment.replies.data.children.map(reply => reply.data).filter(c => c.body) : []
beautifyReplies(comment.replies)
return comment
})
}

const redditCollectionToPosts = (response) => {
return response.data.data.children.map(c => c.data)
Expand All @@ -19,6 +19,13 @@ const RedditApi = (() => {
return redditCollectionToPosts(response)
},

async fetchComments (post) {
let response = await http.get(`${post.permalink}.json`)
const editedComments = response.data.map(res => res.data.children.map(c => c.data).filter(c => c.body))
.map(beautifyReplies.bind(this))
return editedComments[1]
},

async fetchMorePosts (prevPost, subreddit) {
let response = await http.get(`${subreddit}.json?count=25&after=${prevPost.name}`)
return redditCollectionToPosts(response)
Expand Down
23 changes: 21 additions & 2 deletions src/components/AppLayoutNavbar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,16 @@
color="primary"
>
<v-toolbar-side-icon @click.stop="changeSidebarState"></v-toolbar-side-icon>
<v-toolbar-title>Vue Reddit PWA {{subredditTitle}}</v-toolbar-title>
<v-toolbar-title>
<span >Vue Reddit PWA {{ subredditTitle }}</span>
</v-toolbar-title>
<div v-if="!isHome" class="back-button">
<router-link :to="{ path: '/' }">
<v-btn icon>
<v-icon>reply</v-icon>
</v-btn>
</router-link>
</div>
</v-toolbar>
</template>

Expand All @@ -26,6 +35,13 @@
]),
subredditTitle () {
return this.selectedSubreddit ? `- ${this.selectedSubreddit}` : ''
},
isHome () {
if (this.$route.name === 'Subreddit') {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

redundant construction

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also, can we do it some other, more beautiful way (no === 'Subreddit)?

return true
} else {
return false
}
}
},
methods: {
Expand All @@ -37,5 +53,8 @@
</script>

<style>

.back-button {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe, vuetify has some prebuild button? explore it's docs

position: absolute;
right: 10px;
}
</style>
1 change: 0 additions & 1 deletion src/components/AppLayoutSidebarSearchField.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
:search-input.sync="search"
v-model="select"
label="Explore subreddits"
autocomplete
dense
cache-items
@input="onSelectionChange"
Expand Down
33 changes: 33 additions & 0 deletions src/components/CommentsItem.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<template>
<div class="comments-item">
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

play with styles - no border bottom, no strange icon. Some user info (eg name, time, upvotes - inspire from reddit and ionic2-reddit-reader)

Collapse/expand would be good

<v-icon color="black">chat</v-icon>
<span>{{ comment.body }}</span>
<div class="comments-reply" v-for="reply in comment.replies">
<comments-item :comment="reply"></comments-item>
</div>
</div>
</template>

<script>
export default {
name: 'CommentsItem',
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rename to SelectedPostComment

props: {
comment: {
type: Object,
default: function () { return {} }
}
}
}
</script>

<style>
.comments-item {
margin-top: 10px;
}
.comments-reply {
border-left: 1px solid black;
border-bottom: 1px solid black;
padding-left: 10px;
padding-bottom: 10px;
}
</style>
63 changes: 63 additions & 0 deletions src/components/PostsItem.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<template>
<div class="posts-item">
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Play with vuetify components - everything might look much better (cards, panels etc)

<h1>{{ openedPost.title }}</h1>
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't it good to split Post component to wrapper, body (3 types) and comments list?

<div class="post-item__content"
v-if="!openedPost.post_hint">
<span v-if="openedPost.selftext">
{{ openedPost.selftext }}
</span>
<a v-else :href="openedPost.url">
{{ openedPost.url }}
</a>
</div>
<div class="post-item__image"
v-if="openedPost.post_hint && openedPost.post_hint === 'image'">
<img :src="openedPost.url"/>
</div>
<div class="post-item__image"
v-if="openedPost.post_hint && openedPost.post_hint === 'link'">
<a :href="openedPost.url">
{{ openedPost.url }}
</a>
</div>
<div class="post-item__comments"
v-if="openedPost.num_comments !== 0">
<h3>Comments</h3>
<div class="post-item__comment"
v-for="comment in comments">
<comments-item :comment="comment"/>
</div>
</div>
</div>
</template>

<script>
import {mapGetters, mapActions} from 'vuex'
import CommentsItem from './CommentsItem'

export default {
name: 'PostsItem',
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rename to SelectedPost

components: {CommentsItem},
mounted () {
this.getComments(this.openedPost)
},
methods: {
...mapActions('posts', [
'getComments'
])
},
computed: {
...mapGetters('posts', {
openedPost: 'openedPost',
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

selectedPost

comments: 'comments'
})
}
}
</script>

<style>
.post-item__comments {
margin-top: 10px;
}
</style>

60 changes: 38 additions & 22 deletions src/components/PostsListItem.vue
Original file line number Diff line number Diff line change
@@ -1,29 +1,36 @@
<template>
<v-list-tile :key="post.title" avatar @click="" class="posts-list-item">
<v-list-tile-avatar>
<img :src="thumbnail"/>
</v-list-tile-avatar>
<v-list-tile-content>
<v-list-tile-title v-html="post.title"/>
<v-list-tile-sub-title>
<div>
Submitted {{timeAgo}} by <a>{{post.author}}</a>
</div>
<div class="posts-list-item-metrics">
<span>
<v-icon>keyboard_arrow_up</v-icon> {{post.ups}}
</span>
<a>
<v-icon color="blue darken-2" small class="posts-list-item-comment-icon">comment</v-icon> {{post.num_comments}} comments
</a>
</div>
</v-list-tile-sub-title>
</v-list-tile-content>
</v-list-tile>
<div class="posts-list-item">
<router-link :to="{ path: `${post.id}` }">
<v-list-tile :key="post.title" avatar @click="openPost()">
<v-list-tile-avatar>
<img :src="thumbnail"/>
</v-list-tile-avatar>
<v-list-tile-content>
<v-list-tile-title v-html="post.title"/>
<v-list-tile-sub-title>
<div>
Submitted {{timeAgo}} by <a>{{post.author}}</a>
</div>
<div class="posts-list-item-metrics">
<span>
<v-icon>keyboard_arrow_up</v-icon> {{post.ups}}
</span>
<a @click="moveToComments()">
<v-icon color="blue darken-2" small class="posts-list-item-comment-icon">comment</v-icon>
{{post.num_comments}} comments
</a>
</div>
</v-list-tile-sub-title>
</v-list-tile-content>
</v-list-tile>
</router-link>
</div>
</template>

<script>
import moment from 'moment'
import { mapActions } from 'vuex'

export default {
name: 'PostsListItem',
props: {
Expand All @@ -41,11 +48,16 @@
return moment(date).fromNow()
}
},

methods: {
...mapActions('posts', [
'setOpenedPost'
]),
isURL (str) {
// eslint-disable-next-line no-useless-escape
return /^(?:\w+:)?\/\/([^\s\.]+\.\S{2}|localhost[\:?\d]*)\S*$/.test(str)
},
openPost () {
this.setOpenedPost(this.post)
}
}
}
Expand All @@ -66,4 +78,8 @@
line-height: 24px;
width: 20px;
}

.posts-list-item a {
text-decoration: none;
}
</style>
2 changes: 2 additions & 0 deletions src/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import 'vuetify/src/stylus/app.styl'
import {
Vuetify,
VApp,
VBtn,
VGrid,
VNavigationDrawer,
VFooter,
Expand All @@ -31,6 +32,7 @@ import { sync } from 'vuex-router-sync'
Vue.use(Vuetify, {
components: {
VApp,
VBtn,
VGrid,
VNavigationDrawer,
VFooter,
Expand Down
6 changes: 6 additions & 0 deletions src/router/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import Vue from 'vue'
import Router from 'vue-router'
import Subreddit from '@/components/Subreddit'
import PostsItem from '@/components/PostsItem'

Vue.use(Router)

Expand All @@ -11,6 +12,11 @@ export default new Router({
path: '/',
name: 'Subreddit',
component: Subreddit
},
{
path: '/:id',
name: 'Post',
component: PostsItem
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rename everywhere

}
]
})
36 changes: 34 additions & 2 deletions src/store/modules/posts.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,22 @@ export default {
state: {
error: null,
isLoading: false,
posts: []
openedPost: localStorage.getItem('openedPost') ? JSON.parse(localStorage.getItem('openedPost')) : '',
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't think we need local storage here

posts: [],
comments: []
},
getters: {
isLoading: state => state.isLoading,
error: state => state.error,
posts: state => state.posts
posts: state => state.posts,
openedPost: state => state.openedPost,
comments: state => state.comments
},
mutations: {
updateOpenedPost (state, payload) {
state.openedPost = payload
localStorage.setItem('openedPost', JSON.stringify(state.openedPost))
},
updateError (state, payload) {
state.error = payload
},
Expand All @@ -22,6 +30,9 @@ export default {
updatePosts (state, payload) {
state.posts = payload
},
updateComments (state, payload) {
state.comments = payload
},
concatenatePosts (state, payload) {
state.posts = [...state.posts, ...payload]
}
Expand All @@ -31,6 +42,14 @@ export default {
commit('updatePosts', [])
},

resetComments ({commit}) {
commit('updateComments', [])
},

setOpenedPost ({commit}, post) {
commit('updateOpenedPost', post)
},

async getPostsFromSubreddit ({commit}, subreddit) {
commit('updateError', null)
commit('updateIsLoading', true)
Expand All @@ -55,6 +74,19 @@ export default {
} finally {
commit('updateIsLoading', false)
}
},

async getComments ({commit}, post) {
commit('updateError', null)
commit('updateIsLoading', true)
try {
let comments = await PostsApi.fetchComments(post)
commit('updateComments', comments)
} catch (err) {
commit('updateError', err.message)
} finally {
commit('updateIsLoading', false)
}
}
}
}