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

comments & user view

parent af890a47
......@@ -11,8 +11,8 @@
<router-link to="/job">Jobs</router-link>
<router-link to="/about">About</router-link>
</div>
<transition name="view" mode="out-in">
<router-view class="view"></router-view>
<transition name="fade" mode="out-in">
<router-view></router-view>
</transition>
</div>
</template>
......@@ -24,10 +24,10 @@ body
.logo
width 30px
.view
.fade-enter-active, .fade-leave-active
transition all .2s ease
.view-enter, .view-leave-active
.fade-enter, .fade-leave-active
opacity 0
a
......
......@@ -3,9 +3,14 @@ import App from './App.vue'
import store from './store'
import router from './router'
import { sync } from 'vuex-router-sync'
import * as filters from './filters'
sync(store, router)
Object.keys(filters).forEach(key => {
Vue.filter(key, filters[key])
})
const app = new Vue({
router,
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>
<li class="news-item">
<a :href="item.url" target="_blank">{{ item.title }}</a><br>
<router-link :to="'/item/' + item.id">
{{ item.descendants }} comments
</router-link>
| by
<span class="score">{{ item.score }}</span>
<template v-if="item.url">
<a :href="item.url" target="_blank">{{ item.title }}</a>
<span>({{ item.url | host }})</span>
</template>
<template v-else>
<router-link :to="'/item/' + item.id">{{ item.title }}</router-link>
</template>
<br>
by
<router-link :to="'/user/' + item.by">
{{ item.by }}
</router-link>
{{ item.time | timeAgo }} ago |
<router-link :to="'/item/' + item.id">
{{ item.descendants }} comments
</router-link>
</li>
</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'
// 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.
const cache = inBrowser
? createCache()
? null
: (process.__API_CACHE__ || (process.__API_CACHE__ = createCache()))
function createCache () {
......@@ -44,11 +44,17 @@ function createServerSideAPI () {
}
function fetch (child) {
if (cache && cache.has(child)) {
return Promise.resolve(cache.get(child))
} else {
return new Promise((resolve, reject) => {
api.child(child).once('value', snapshot => {
resolve(snapshot.val())
const val = snapshot.val()
cache && cache.set(child, val)
resolve(val)
}, reject)
})
}
}
export function fetchIdsByType (type) {
......@@ -57,15 +63,8 @@ export function fetchIdsByType (type) {
: fetch(`${type}stories`)
}
export function fetchItem (id, forceRefresh) {
if (!forceRefresh && cache.get(id)) {
return Promise.resolve(cache.get(id))
} else {
return fetch(`item/${id}`).then(item => {
cache.set(id, item)
return item
})
}
export function fetchItem (id) {
return fetch(`item/${id}`)
}
export function fetchItems (ids) {
......
<template>
<div class="item-view">
<h2>Item!</h2>
<p v-if="item">{{ item.title }}</p>
<div class="item-view" v-if="item">
<div class="item-view-header">
<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>
</template>
<script>
import Comment from '../components/Comment.vue'
function fetchItem (store) {
return store.dispatch('FETCH_ITEMS', {
ids: [store.state.route.params.id]
......@@ -14,6 +29,7 @@ function fetchItem (store) {
export default {
name: 'item-view',
components: { Comment },
computed: {
item () {
return this.$store.state.items[this.$route.params.id]
......
<template>
<div class="user-view">
<h2 v-if="user">User: {{ user.id }}</h2>
<div class="user-view" v-if="user">
<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>
</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