add vue-router and detail page
This commit is contained in:
parent
75b818c378
commit
c678841406
5
hn-vue/package-lock.json
generated
5
hn-vue/package-lock.json
generated
@ -10982,6 +10982,11 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"vue-router": {
|
||||
"version": "3.4.9",
|
||||
"resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.4.9.tgz",
|
||||
"integrity": "sha512-CGAKWN44RqXW06oC+u4mPgHLQQi2t6vLD/JbGRDAXm0YpMv0bgpKuU5bBd7AvMgfTz9kXVRIWKHqRwGEb8xFkA=="
|
||||
},
|
||||
"vue-style-loader": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/vue-style-loader/-/vue-style-loader-4.1.2.tgz",
|
||||
|
||||
@ -9,7 +9,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"core-js": "^3.6.5",
|
||||
"vue": "^2.6.11"
|
||||
"vue": "^2.6.11",
|
||||
"vue-router": "^3.4.9"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vue/cli-plugin-babel": "~4.5.0",
|
||||
|
||||
8
hn-vue/src/Layout.vue
Normal file
8
hn-vue/src/Layout.vue
Normal file
@ -0,0 +1,8 @@
|
||||
<template>
|
||||
<div>
|
||||
<nav>
|
||||
<router-link :to="{ name: 'links' }">Derniers liens publiés</router-link>
|
||||
</nav>
|
||||
<router-view></router-view>
|
||||
</div>
|
||||
</template>
|
||||
@ -7,12 +7,26 @@ class Api {
|
||||
return this._get("/api/links");
|
||||
}
|
||||
|
||||
getLinkById(id) {
|
||||
return this._get(`/api/links/${id}`);
|
||||
}
|
||||
|
||||
getLinkComments(id) {
|
||||
return this._get(`/api/links/${id}/comments`);
|
||||
}
|
||||
|
||||
_get(path) {
|
||||
return fetch(this.baseUrl + path, {
|
||||
headers: {
|
||||
Accept: "application/json",
|
||||
},
|
||||
}).then((r) => r.json());
|
||||
}).then((r) => {
|
||||
if (!r.ok) {
|
||||
return Promise.reject(new Error("Erreur dans la requête"));
|
||||
}
|
||||
|
||||
return r.json();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
20
hn-vue/src/components/Comment.vue
Normal file
20
hn-vue/src/components/Comment.vue
Normal file
@ -0,0 +1,20 @@
|
||||
<template>
|
||||
<article>
|
||||
<p>{{ comment.content }}</p>
|
||||
<p>
|
||||
Publié le {{ comment.createdAt }} par {{ comment.createdBy.username }}
|
||||
</p>
|
||||
<p>👍 {{ comment.upvotesCount }} / 👎 {{ comment.downvotesCount }}</p>
|
||||
</article>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
comment: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="error">{{ err.message }}</div>
|
||||
<div class="error">{{ error.message }}</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
@ -1,6 +1,10 @@
|
||||
<template>
|
||||
<article>
|
||||
<h2>{{ link.url }}</h2>
|
||||
<h2>
|
||||
<router-link :to="{ name: 'link', params: { id: link.id } }">{{
|
||||
link.url
|
||||
}}</router-link>
|
||||
</h2>
|
||||
<p>Publié le {{ link.createdAt }} par {{ link.createdBy.username }}</p>
|
||||
<p>👍 {{ link.upvotesCount }} / 👎 {{ link.downvotesCount }}</p>
|
||||
</article>
|
||||
|
||||
@ -1,8 +1,12 @@
|
||||
import Vue from "vue";
|
||||
import Links from "./Links.vue";
|
||||
import Layout from "./Layout.vue";
|
||||
import createRouter from "./router";
|
||||
|
||||
Vue.config.productionTip = false;
|
||||
|
||||
const router = createRouter();
|
||||
|
||||
new Vue({
|
||||
render: (h) => h(Links),
|
||||
router,
|
||||
render: (h) => h(Layout),
|
||||
}).$mount("#app");
|
||||
|
||||
69
hn-vue/src/pages/LinkDetail.vue
Normal file
69
hn-vue/src/pages/LinkDetail.vue
Normal file
@ -0,0 +1,69 @@
|
||||
<template>
|
||||
<div>
|
||||
<h1>Détail du lien</h1>
|
||||
<error v-if="err" :error="err" />
|
||||
<loading
|
||||
v-else-if="link === null"
|
||||
message="Chargement du lien en cours ..."
|
||||
/>
|
||||
<div v-else>
|
||||
<link-item :link="link" />
|
||||
<loading v-if="comments === null" message="Chargement des commentaires" />
|
||||
<p v-else-if="comments.length === 0">Aucun commentaire pour ce lien</p>
|
||||
<ul v-else>
|
||||
<li v-for="comment in comments" :key="comment.id">
|
||||
<comment :comment="comment" />
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import LinkItem from "../components/LinkItem.vue";
|
||||
import Comment from "../components/Comment.vue";
|
||||
import Error from "../components/Error.vue";
|
||||
import Loading from "../components/Loading.vue";
|
||||
import api from "../api";
|
||||
|
||||
export default {
|
||||
props: {
|
||||
id: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
link: null,
|
||||
comments: null,
|
||||
err: null,
|
||||
};
|
||||
},
|
||||
components: { LinkItem, Error, Loading, Comment },
|
||||
mounted() {
|
||||
this.fetchLinkDetail();
|
||||
},
|
||||
watch: {
|
||||
// id: 'fetchLinkDetail'
|
||||
id() {
|
||||
this.fetchLinkDetail();
|
||||
},
|
||||
// '$route': 'fetchLinkDetail'
|
||||
},
|
||||
methods: {
|
||||
async fetchLinkDetail() {
|
||||
this.link = null;
|
||||
this.comments = null;
|
||||
this.err = null;
|
||||
|
||||
try {
|
||||
this.link = await api.getLinkById(this.id);
|
||||
this.comments = await api.getLinkComments(this.id);
|
||||
} catch (e) {
|
||||
this.err = e;
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@ -1,11 +1,11 @@
|
||||
<template>
|
||||
<div>
|
||||
<h1>Derniers liens publiés</h1>
|
||||
<error v-if="err" :error="err" />
|
||||
<loading
|
||||
v-if="links === null"
|
||||
v-else-if="links === null"
|
||||
message="Chargement des liens en cours ..."
|
||||
/>
|
||||
<error v-else-if="err" :error="err" />
|
||||
<ul v-else>
|
||||
<li v-for="link in links" :key="link.id">
|
||||
<link-item :link="link" />
|
||||
@ -15,10 +15,10 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Error from "./components/Error.vue";
|
||||
import Loading from "./components/Loading.vue";
|
||||
import LinkItem from "./components/LinkItem.vue";
|
||||
import api from "./api";
|
||||
import Error from "../components/Error.vue";
|
||||
import Loading from "../components/Loading.vue";
|
||||
import LinkItem from "../components/LinkItem.vue";
|
||||
import api from "../api";
|
||||
|
||||
export default {
|
||||
components: { Loading, Error, LinkItem },
|
||||
23
hn-vue/src/router.js
Normal file
23
hn-vue/src/router.js
Normal file
@ -0,0 +1,23 @@
|
||||
import Vue from "vue";
|
||||
import VueRouter from "vue-router";
|
||||
import Links from "./pages/Links.vue";
|
||||
import LinkDetail from "./pages/LinkDetail.vue";
|
||||
|
||||
Vue.use(VueRouter);
|
||||
|
||||
export default function createRouter() {
|
||||
const router = new VueRouter({
|
||||
routes: [
|
||||
{ path: "/", name: "links", component: Links },
|
||||
{
|
||||
path: "/links/:id",
|
||||
name: "link",
|
||||
component: LinkDetail,
|
||||
props: true,
|
||||
},
|
||||
{ path: "*", redirect: "/" },
|
||||
],
|
||||
});
|
||||
|
||||
return router;
|
||||
}
|
||||
20
vue2/src/components/Link.vue
Normal file
20
vue2/src/components/Link.vue
Normal file
@ -0,0 +1,20 @@
|
||||
<template>
|
||||
<div>
|
||||
<p v-if="link">{{ link.url }}</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return { link: null };
|
||||
},
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
const link = await fetch(
|
||||
`https://hn-dotnet.herokuapp.com/api/links/${to.params.id}`
|
||||
).then((r) => r.json());
|
||||
to.meta.title = "Visualisation de " + link.url;
|
||||
next((vm) => (vm.link = link));
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@ -18,6 +18,8 @@ const AForm = () =>
|
||||
import(/* webpackChunkName: "aform" */ "./components/AForm.vue");
|
||||
const Counter = () =>
|
||||
import(/* webpackChunkName: "counter" */ "./components/Counter.vue");
|
||||
const Link = () =>
|
||||
import(/* webpackChunkName: "link" */ "./components/Link.vue");
|
||||
|
||||
Vue.use(VueRouter);
|
||||
|
||||
@ -74,6 +76,12 @@ const router = new VueRouter({
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: "/link/:id",
|
||||
component: Link,
|
||||
name: "link",
|
||||
meta: {},
|
||||
},
|
||||
{
|
||||
path: "/card/:a/:b",
|
||||
component: Card,
|
||||
@ -98,6 +106,7 @@ router.beforeEach((to, from, next) => {
|
||||
});
|
||||
|
||||
router.afterEach((to) => {
|
||||
console.log(to.matched);
|
||||
document.title = to.meta.title;
|
||||
});
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user