Skip to content

Commit 4b20651

Browse files
committed
comments & user view
1 parent af890a4 commit 4b20651

File tree

8 files changed

+120
-29
lines changed

8 files changed

+120
-29
lines changed

src/App.vue

+4-4
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111
<router-link to="/job">Jobs</router-link>
1212
<router-link to="/about">About</router-link>
1313
</div>
14-
<transition name="view" mode="out-in">
15-
<router-view class="view"></router-view>
14+
<transition name="fade" mode="out-in">
15+
<router-view></router-view>
1616
</transition>
1717
</div>
1818
</template>
@@ -24,10 +24,10 @@ body
2424
.logo
2525
width 30px
2626
27-
.view
27+
.fade-enter-active, .fade-leave-active
2828
transition all .2s ease
2929
30-
.view-enter, .view-leave-active
30+
.fade-enter, .fade-leave-active
3131
opacity 0
3232
3333
a

src/app.js

+5
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,14 @@ import App from './App.vue'
33
import store from './store'
44
import router from './router'
55
import { sync } from 'vuex-router-sync'
6+
import * as filters from './filters'
67

78
sync(store, router)
89

10+
Object.keys(filters).forEach(key => {
11+
Vue.filter(key, filters[key])
12+
})
13+
914
const app = new Vue({
1015
router,
1116
store,

src/components/Comment.vue

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<template>
2+
<li v-if="comment">
3+
<div>{{ comment.by }} {{ comment.time | timeAgo }} ago</div>
4+
<div v-html="comment.text"></div>
5+
<ul>
6+
<comment v-for="id in comment.kids" :id="id"></comment>
7+
</ul>
8+
</li>
9+
</template>
10+
11+
<script>
12+
export default {
13+
name: 'comment',
14+
props: ['id'],
15+
computed: {
16+
comment () {
17+
return this.$store.state.items[this.id]
18+
}
19+
},
20+
beforeMount () {
21+
this.$store.dispatch('FETCH_ITEMS', {
22+
ids: [this.id]
23+
})
24+
}
25+
}
26+
</script>

src/components/Item.vue

+14-5
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,22 @@
11
<template>
22
<li class="news-item">
3-
<a :href="item.url" target="_blank">{{ item.title }}</a><br>
4-
<router-link :to="'/item/' + item.id">
5-
{{ item.descendants }} comments
6-
</router-link>
7-
| by
3+
<span class="score">{{ item.score }}</span>
4+
<template v-if="item.url">
5+
<a :href="item.url" target="_blank">{{ item.title }}</a>
6+
<span>({{ item.url | host }})</span>
7+
</template>
8+
<template v-else>
9+
<router-link :to="'/item/' + item.id">{{ item.title }}</router-link>
10+
</template>
11+
<br>
12+
by
813
<router-link :to="'/user/' + item.by">
914
{{ item.by }}
1015
</router-link>
16+
{{ item.time | timeAgo }} ago |
17+
<router-link :to="'/item/' + item.id">
18+
{{ item.descendants }} comments
19+
</router-link>
1120
</li>
1221
</template>
1322

src/filters/index.js

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
export function host (url) {
2+
const host = url.replace(/^https?:\/\//, '').replace(/\/.*$/, '')
3+
const parts = host.split('.').slice(-3)
4+
if (parts[0] === 'www') parts.shift()
5+
return parts.join('.')
6+
}
7+
8+
export function timeAgo (time) {
9+
const between = Date.now() / 1000 - Number(time)
10+
if (between < 3600) {
11+
return pluralize(~~(between / 60), ' minute')
12+
} else if (between < 86400) {
13+
return pluralize(~~(between / 3600), ' hour')
14+
} else {
15+
return pluralize(~~(between / 86400), ' day')
16+
}
17+
}
18+
19+
function pluralize (time, label) {
20+
if (time === 1) {
21+
return time + label
22+
}
23+
return time + label + 's'
24+
}

src/store/api.js

+14-15
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ const inBrowser = typeof window !== 'undefined'
77
// context for each request. To allow caching across multiple requests, we need
88
// to attach the cache to the process which is shared across all requests.
99
const cache = inBrowser
10-
? createCache()
10+
? null
1111
: (process.__API_CACHE__ || (process.__API_CACHE__ = createCache()))
1212

1313
function createCache () {
@@ -44,11 +44,17 @@ function createServerSideAPI () {
4444
}
4545

4646
function fetch (child) {
47-
return new Promise((resolve, reject) => {
48-
api.child(child).once('value', snapshot => {
49-
resolve(snapshot.val())
50-
}, reject)
51-
})
47+
if (cache && cache.has(child)) {
48+
return Promise.resolve(cache.get(child))
49+
} else {
50+
return new Promise((resolve, reject) => {
51+
api.child(child).once('value', snapshot => {
52+
const val = snapshot.val()
53+
cache && cache.set(child, val)
54+
resolve(val)
55+
}, reject)
56+
})
57+
}
5258
}
5359

5460
export function fetchIdsByType (type) {
@@ -57,15 +63,8 @@ export function fetchIdsByType (type) {
5763
: fetch(`${type}stories`)
5864
}
5965

60-
export function fetchItem (id, forceRefresh) {
61-
if (!forceRefresh && cache.get(id)) {
62-
return Promise.resolve(cache.get(id))
63-
} else {
64-
return fetch(`item/${id}`).then(item => {
65-
cache.set(id, item)
66-
return item
67-
})
68-
}
66+
export function fetchItem (id) {
67+
return fetch(`item/${id}`)
6968
}
7069

7170
export function fetchItems (ids) {

src/views/ItemView.vue

+19-3
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,26 @@
11
<template>
2-
<div class="item-view">
3-
<h2>Item!</h2>
4-
<p v-if="item">{{ item.title }}</p>
2+
<div class="item-view" v-if="item">
3+
<div class="item-view-header">
4+
<a :href="item.url" target="_blank">
5+
<h2>{{ item.title }}</h2>
6+
</a>
7+
<span v-if="item.url">({{ item.url | host }})</span>
8+
<p>
9+
{{ item.score }} points
10+
| by <router-link :to="'/user/' + item.by">{{ item.by }}</router-link>
11+
{{ item.time | timeAgo }} ago
12+
| {{ item.descendants }} comments
13+
</p>
14+
</div>
15+
<ul class="item-view-comments">
16+
<comment v-for="id in item.kids" :id="id"></comment>
17+
</ul>
518
</div>
619
</template>
720

821
<script>
22+
import Comment from '../components/Comment.vue'
23+
924
function fetchItem (store) {
1025
return store.dispatch('FETCH_ITEMS', {
1126
ids: [store.state.route.params.id]
@@ -14,6 +29,7 @@ function fetchItem (store) {
1429
1530
export default {
1631
name: 'item-view',
32+
components: { Comment },
1733
computed: {
1834
item () {
1935
return this.$store.state.items[this.$route.params.id]

src/views/UserView.vue

+14-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,18 @@
11
<template>
2-
<div class="user-view">
3-
<h2 v-if="user">User: {{ user.id }}</h2>
2+
<div class="user-view" v-if="user">
3+
<ul>
4+
<li><span class="label">user:</span> {{ user.id }}</li>
5+
<li><span class="label">created:</span> {{ user.created | timeAgo }} ago</li>
6+
<li><span class="label">karma:</span> {{user.karma}}</li>
7+
<li>
8+
<span class="label">about:</span>
9+
<div class="about" v-html="user.about"></div>
10+
</li>
11+
</ul>
12+
<p class="links">
13+
<a :href="'https://news.ycombinator.com/submitted?id=' + user.id">submissions</a><br>
14+
<a :href="'https://news.ycombinator.com/threads?id=' + user.id">comments</a>
15+
</p>
416
</div>
517
</template>
618

0 commit comments

Comments
 (0)