Commit 4b20651b authored by Evan You's avatar Evan You

comments & user view

parent af890a47
...@@ -11,8 +11,8 @@ ...@@ -11,8 +11,8 @@
<router-link to="/job">Jobs</router-link> <router-link to="/job">Jobs</router-link>
<router-link to="/about">About</router-link> <router-link to="/about">About</router-link>
</div> </div>
<transition name="view" mode="out-in"> <transition name="fade" mode="out-in">
<router-view class="view"></router-view> <router-view></router-view>
</transition> </transition>
</div> </div>
</template> </template>
...@@ -24,10 +24,10 @@ body ...@@ -24,10 +24,10 @@ body
.logo .logo
width 30px width 30px
.view .fade-enter-active, .fade-leave-active
transition all .2s ease transition all .2s ease
.view-enter, .view-leave-active .fade-enter, .fade-leave-active
opacity 0 opacity 0
a a
......
...@@ -3,9 +3,14 @@ import App from './App.vue' ...@@ -3,9 +3,14 @@ import App from './App.vue'
import store from './store' import store from './store'
import router from './router' import router from './router'
import { sync } from 'vuex-router-sync' import { sync } from 'vuex-router-sync'
import * as filters from './filters'
sync(store, router) sync(store, router)
Object.keys(filters).forEach(key => {
Vue.filter(key, filters[key])
})
const app = new Vue({ const app = new Vue({
router, router,
store, store,
......
<template>
<li v-if="comment">
<div>{{ comment.by }} {{ comment.time | timeAgo }} ago</div>
<div v-html="comment.text"></div>
<ul>
<comment v-for="id in comment.kids" :id="id"></comment>
</ul>
</li>
</template>
<script>
export default {
name: 'comment',
props: ['id'],
computed: {
comment () {
return this.$store.state.items[this.id]
}
},
beforeMount () {
this.$store.dispatch('FETCH_ITEMS', {
ids: [this.id]
})
}
}
</script>
<template> <template>
<li class="news-item"> <li class="news-item">
<a :href="item.url" target="_blank">{{ item.title }}</a><br> <span class="score">{{ item.score }}</span>
<router-link :to="'/item/' + item.id"> <template v-if="item.url">
{{ item.descendants }} comments <a :href="item.url" target="_blank">{{ item.title }}</a>
</router-link> <span>({{ item.url | host }})</span>
| by </template>
<template v-else>
<router-link :to="'/item/' + item.id">{{ item.title }}</router-link>
</template>
<br>
by
<router-link :to="'/user/' + item.by"> <router-link :to="'/user/' + item.by">
{{ item.by }} {{ item.by }}
</router-link> </router-link>
{{ item.time | timeAgo }} ago |
<router-link :to="'/item/' + item.id">
{{ item.descendants }} comments
</router-link>
</li> </li>
</template> </template>
......
export function host (url) {
const host = url.replace(/^https?:\/\//, '').replace(/\/.*$/, '')
const parts = host.split('.').slice(-3)
if (parts[0] === 'www') parts.shift()
return parts.join('.')
}
export function timeAgo (time) {
const between = Date.now() / 1000 - Number(time)
if (between < 3600) {
return pluralize(~~(between / 60), ' minute')
} else if (between < 86400) {
return pluralize(~~(between / 3600), ' hour')
} else {
return pluralize(~~(between / 86400), ' day')
}
}
function pluralize (time, label) {
if (time === 1) {
return time + label
}
return time + label + 's'
}
...@@ -7,7 +7,7 @@ const inBrowser = typeof window !== 'undefined' ...@@ -7,7 +7,7 @@ const inBrowser = typeof window !== 'undefined'
// context for each request. To allow caching across multiple requests, we need // context for each request. To allow caching across multiple requests, we need
// to attach the cache to the process which is shared across all requests. // to attach the cache to the process which is shared across all requests.
const cache = inBrowser const cache = inBrowser
? createCache() ? null
: (process.__API_CACHE__ || (process.__API_CACHE__ = createCache())) : (process.__API_CACHE__ || (process.__API_CACHE__ = createCache()))
function createCache () { function createCache () {
...@@ -44,11 +44,17 @@ function createServerSideAPI () { ...@@ -44,11 +44,17 @@ function createServerSideAPI () {
} }
function fetch (child) { function fetch (child) {
return new Promise((resolve, reject) => { if (cache && cache.has(child)) {
api.child(child).once('value', snapshot => { return Promise.resolve(cache.get(child))
resolve(snapshot.val()) } else {
}, reject) return new Promise((resolve, reject) => {
}) api.child(child).once('value', snapshot => {
const val = snapshot.val()
cache && cache.set(child, val)
resolve(val)
}, reject)
})
}
} }
export function fetchIdsByType (type) { export function fetchIdsByType (type) {
...@@ -57,15 +63,8 @@ export function fetchIdsByType (type) { ...@@ -57,15 +63,8 @@ export function fetchIdsByType (type) {
: fetch(`${type}stories`) : fetch(`${type}stories`)
} }
export function fetchItem (id, forceRefresh) { export function fetchItem (id) {
if (!forceRefresh && cache.get(id)) { return fetch(`item/${id}`)
return Promise.resolve(cache.get(id))
} else {
return fetch(`item/${id}`).then(item => {
cache.set(id, item)
return item
})
}
} }
export function fetchItems (ids) { export function fetchItems (ids) {
......
<template> <template>
<div class="item-view"> <div class="item-view" v-if="item">
<h2>Item!</h2> <div class="item-view-header">
<p v-if="item">{{ item.title }}</p> <a :href="item.url" target="_blank">
<h2>{{ item.title }}</h2>
</a>
<span v-if="item.url">({{ item.url | host }})</span>
<p>
{{ item.score }} points
| by <router-link :to="'/user/' + item.by">{{ item.by }}</router-link>
{{ item.time | timeAgo }} ago
| {{ item.descendants }} comments
</p>
</div>
<ul class="item-view-comments">
<comment v-for="id in item.kids" :id="id"></comment>
</ul>
</div> </div>
</template> </template>
<script> <script>
import Comment from '../components/Comment.vue'
function fetchItem (store) { function fetchItem (store) {
return store.dispatch('FETCH_ITEMS', { return store.dispatch('FETCH_ITEMS', {
ids: [store.state.route.params.id] ids: [store.state.route.params.id]
...@@ -14,6 +29,7 @@ function fetchItem (store) { ...@@ -14,6 +29,7 @@ function fetchItem (store) {
export default { export default {
name: 'item-view', name: 'item-view',
components: { Comment },
computed: { computed: {
item () { item () {
return this.$store.state.items[this.$route.params.id] return this.$store.state.items[this.$route.params.id]
......
<template> <template>
<div class="user-view"> <div class="user-view" v-if="user">
<h2 v-if="user">User: {{ user.id }}</h2> <ul>
<li><span class="label">user:</span> {{ user.id }}</li>
<li><span class="label">created:</span> {{ user.created | timeAgo }} ago</li>
<li><span class="label">karma:</span> {{user.karma}}</li>
<li>
<span class="label">about:</span>
<div class="about" v-html="user.about"></div>
</li>
</ul>
<p class="links">
<a :href="'https://news.ycombinator.com/submitted?id=' + user.id">submissions</a><br>
<a :href="'https://news.ycombinator.com/threads?id=' + user.id">comments</a>
</p>
</div> </div>
</template> </template>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment