Create view for Pages
GhostPost and GhostPage are copies of each other: they conditionally render depending on whether the path matches a post or page. The reason for this workaround is that, otherwise, the router would show a 404 for non-matching posts even when a matching page existed, since they both lie under the same path.
This commit is contained in:
parent
fcc8cda747
commit
9a0415d3ff
4 changed files with 210 additions and 69 deletions
|
@ -9,6 +9,7 @@ module.exports = {
|
|||
|
||||
templates: {
|
||||
GhostPost: '/:slug',
|
||||
GhostPage: '/:slug',
|
||||
GhostTag: '/tag/:slug',
|
||||
GhostAuthor: '/author/:slug'
|
||||
},
|
||||
|
|
|
@ -1,51 +0,0 @@
|
|||
<template>
|
||||
<Page>
|
||||
<article class="post-full post page" :class="pageClass">
|
||||
|
||||
<header class="post-full-header">
|
||||
<h1 class="post-full-title">About us</h1>
|
||||
</header>
|
||||
|
||||
<figure v-if="image" class="post-full-image">
|
||||
<g-image v-bind="image" src="" alt="" />
|
||||
</figure>
|
||||
|
||||
<section class="post-full-content">
|
||||
<div class="post-content">
|
||||
<p>This is a Gridsome starter casper theme cloned from <a target="_blank" href="https://demo.ghost.io/">Casper</a>. I've put a lot of time and effort into making <strong>Gridsome Starter Casper</strong> project. If you love it, you can <a target="_blank" href="https://www.patreon.com/bePatron?u=8494594">Become a Patron</a>. I promise it will be a good investment 😉.</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</article>
|
||||
</Page>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Page from "../layouts/Page";
|
||||
|
||||
export default {
|
||||
metaInfo() {
|
||||
return {
|
||||
title: 'About',
|
||||
bodyAttrs: {
|
||||
class: `page-about`
|
||||
}
|
||||
};
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
image: ''
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
pageClass() {
|
||||
if (this.image === '') {
|
||||
return 'no-image'
|
||||
}
|
||||
}
|
||||
},
|
||||
components: {
|
||||
Page
|
||||
}
|
||||
};
|
||||
</script>
|
165
src/templates/GhostPage.vue
Normal file
165
src/templates/GhostPage.vue
Normal file
|
@ -0,0 +1,165 @@
|
|||
<template>
|
||||
<Layout>
|
||||
<header class="site-header outer">
|
||||
<div class="inner">
|
||||
<Navbar :logo="true"/>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- <FloatingHeader/> -->
|
||||
|
||||
<main id="site-main" class="site-main outer">
|
||||
<div class="inner">
|
||||
<article :class="postClass">
|
||||
<header class="post-full-header">
|
||||
<section class="post-full-meta" v-if="thisPost.tags">
|
||||
<time class="post-full-meta-date" :datetime="thisPost.date | moment('d, MMMM YYYY')">{{ thisPost.date | moment("d, MMMM YYYY") }}</time>
|
||||
<span class="date-divider">/</span>
|
||||
<a
|
||||
:href="thisPost.tags[0].path"
|
||||
>{{ thisPost.tags[0].title.replace('-', ' ') }}</a>
|
||||
</section>
|
||||
<h1 class="post-full-title">{{ thisPost.title }}</h1>
|
||||
</header>
|
||||
|
||||
<figure v-if="thisPost.image" class="post-full-image">
|
||||
<g-image :src="thisPost.image|changeUrls" :alt="thisPost.title"/>
|
||||
</figure>
|
||||
|
||||
<section class="post-full-content">
|
||||
<div class="post-content" v-html="fullPost"></div>
|
||||
</section>
|
||||
|
||||
<!-- Email subscribe form at the bottom of the page -->
|
||||
<section v-if="Admin.site.subscribers" class="subscribe-form">
|
||||
<h3 class="subscribe-form-title">Subscribe to {{ Admin.site.title }}</h3>
|
||||
<p>Get the latest posts delivered right to your inbox</p>
|
||||
<subscribeForm placeholder="youremail@example.com"/>
|
||||
</section>
|
||||
|
||||
<bylineMultiple :author="thisPost.authors" v-if="thisPost.authors && thisPost.authors.length > 1"/>
|
||||
<bylineSingle :author="thisPost.authors" v-if="thisPost.authors && thisPost.authors.length == 1" />
|
||||
|
||||
<!-- NOTE Comment section -->
|
||||
<!-- <section class="post-full-comments">
|
||||
If you want to embed comments, this is a good place to do it!
|
||||
</section>-->
|
||||
</article>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<PreviousNext :id="thisPost.id" :tag="thisPost.tags[0]" :posts="thisPost.tags[0].belongsTo.edges" v-if="thisPost.tags"/>
|
||||
</Layout>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Admin from "../../data/admin.yml";
|
||||
import Navbar from "../components/Navbar";
|
||||
import FloatingHeader from "../components/FloatingHeader";
|
||||
import subscribeForm from "../components/subscribeForm";
|
||||
import bylineMultiple from "../components/bylineMultiple";
|
||||
import bylineSingle from "../components/bylineSingle";
|
||||
import PreviousNext from "../components/PreviousNext";
|
||||
import changeUrls from '../filters/changeUrls';
|
||||
|
||||
export default {
|
||||
metaInfo() {
|
||||
let bodyAttrs;
|
||||
if (this.$page.post) {
|
||||
bodyAttrs = `post-template tag-${this.$page.post.tags[0].title}`
|
||||
} else {
|
||||
bodyAttrs = "page-template"
|
||||
}
|
||||
return {
|
||||
title: this.$page.post ? this.$page.post.title : this.$page.page.title,
|
||||
bodyAttrs: {
|
||||
class: bodyAttrs
|
||||
}
|
||||
};
|
||||
},
|
||||
components: {
|
||||
Navbar,
|
||||
FloatingHeader,
|
||||
subscribeForm,
|
||||
bylineMultiple,
|
||||
bylineSingle,
|
||||
PreviousNext
|
||||
},
|
||||
filters: {
|
||||
changeUrls: changeUrls
|
||||
},
|
||||
computed: {
|
||||
Admin() {
|
||||
return Admin;
|
||||
},
|
||||
fullPost() {
|
||||
let thisPost = this.$page.post || this.$page.page
|
||||
return changeUrls(thisPost.content);
|
||||
},
|
||||
postClass() {
|
||||
let classes = []
|
||||
if (this.$page.post) {
|
||||
classes.push("post-full");
|
||||
classes.push("post");
|
||||
if (!this.$page.post.image) {
|
||||
classes.push("no-image");
|
||||
}
|
||||
const postTagClass = "tag-" + this.$page.post.tags[0].title;
|
||||
classes.push(postTagClass);
|
||||
} else {
|
||||
classes.push("page-full");
|
||||
classes.push("page");
|
||||
}
|
||||
return classes;
|
||||
},
|
||||
thisPost() {
|
||||
// Return post or page, whichever exists
|
||||
return this.$page.page || this.$page.post
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<page-query>
|
||||
query Post ($path: String!) {
|
||||
post: ghostPost (path: $path) {
|
||||
id
|
||||
title
|
||||
path
|
||||
date: published_at (format: "D. MMMM YYYY")
|
||||
tags {
|
||||
id
|
||||
slug
|
||||
path
|
||||
title: name
|
||||
belongsTo {
|
||||
edges {
|
||||
node {
|
||||
... on GhostPost {
|
||||
id
|
||||
title
|
||||
path
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
authors {
|
||||
name
|
||||
id
|
||||
slug
|
||||
image: profile_image
|
||||
}
|
||||
description: excerpt
|
||||
content: html
|
||||
image: feature_image
|
||||
}
|
||||
page: ghostPage (path: $path) {
|
||||
id
|
||||
title
|
||||
path
|
||||
date: updated_at (format: "D. MMMM YYYY")
|
||||
description: excerpt
|
||||
content: html
|
||||
}
|
||||
}
|
||||
</page-query>
|
|
@ -12,18 +12,18 @@
|
|||
<div class="inner">
|
||||
<article :class="postClass">
|
||||
<header class="post-full-header">
|
||||
<section class="post-full-meta">
|
||||
<time class="post-full-meta-date" :datetime="$page.post.date | moment('d, MMMM YYYY')">{{ $page.post.date | moment("d, MMMM YYYY") }}</time>
|
||||
<section class="post-full-meta" v-if="thisPost.tags">
|
||||
<time class="post-full-meta-date" :datetime="thisPost.date | moment('d, MMMM YYYY')">{{ thisPost.date | moment("d, MMMM YYYY") }}</time>
|
||||
<span class="date-divider">/</span>
|
||||
<a
|
||||
:href="$page.post.tags[0].path"
|
||||
>{{ $page.post.tags[0].title.replace('-', ' ') }}</a>
|
||||
:href="thisPost.tags[0].path"
|
||||
>{{ thisPost.tags[0].title.replace('-', ' ') }}</a>
|
||||
</section>
|
||||
<h1 class="post-full-title">{{ $page.post.title }}</h1>
|
||||
<h1 class="post-full-title">{{ thisPost.title }}</h1>
|
||||
</header>
|
||||
|
||||
<figure v-if="$page.post.image" class="post-full-image">
|
||||
<g-image :src="$page.post.image|changeUrls" :alt="$page.post.title"/>
|
||||
<figure v-if="thisPost.image" class="post-full-image">
|
||||
<g-image :src="thisPost.image|changeUrls" :alt="thisPost.title"/>
|
||||
</figure>
|
||||
|
||||
<section class="post-full-content">
|
||||
|
@ -37,8 +37,8 @@
|
|||
<subscribeForm placeholder="youremail@example.com"/>
|
||||
</section>
|
||||
|
||||
<bylineMultiple :author="$page.post.authors" v-if="$page.post.authors.length > 1"/>
|
||||
<bylineSingle :author="$page.post.authors" v-else/>
|
||||
<bylineMultiple :author="thisPost.authors" v-if="thisPost.authors && thisPost.authors.length > 1"/>
|
||||
<bylineSingle :author="thisPost.authors" v-if="thisPost.authors && thisPost.authors.length == 1" />
|
||||
|
||||
<!-- NOTE Comment section -->
|
||||
<!-- <section class="post-full-comments">
|
||||
|
@ -48,7 +48,7 @@
|
|||
</div>
|
||||
</main>
|
||||
|
||||
<PreviousNext :id="$page.post.id" :tag="$page.post.tags[0]" :posts="$page.post.tags[0].belongsTo.edges"/>
|
||||
<PreviousNext :id="thisPost.id" :tag="thisPost.tags[0]" :posts="thisPost.tags[0].belongsTo.edges" v-if="thisPost.tags"/>
|
||||
</Layout>
|
||||
</template>
|
||||
|
||||
|
@ -64,10 +64,16 @@ import changeUrls from '../filters/changeUrls';
|
|||
|
||||
export default {
|
||||
metaInfo() {
|
||||
let bodyAttrs;
|
||||
if (this.$page.post) {
|
||||
bodyAttrs = `post-template tag-${this.$page.post.tags[0].title}`
|
||||
} else {
|
||||
bodyAttrs = "page-template"
|
||||
}
|
||||
return {
|
||||
title: this.$page.post.title,
|
||||
title: this.$page.post ? this.$page.post.title : this.$page.page.title,
|
||||
bodyAttrs: {
|
||||
class: `post-template tag-${this.$page.post.tags[0].title}`
|
||||
class: bodyAttrs
|
||||
}
|
||||
};
|
||||
},
|
||||
|
@ -87,16 +93,28 @@ export default {
|
|||
return Admin;
|
||||
},
|
||||
fullPost() {
|
||||
return changeUrls(this.$page.post.content);
|
||||
let thisPost = this.$page.post || this.$page.page
|
||||
return changeUrls(thisPost.content);
|
||||
},
|
||||
postClass() {
|
||||
let classes = ["post-full", "post"];
|
||||
let classes = []
|
||||
if (this.$page.post) {
|
||||
classes.push("post-full");
|
||||
classes.push("post");
|
||||
if (!this.$page.post.image) {
|
||||
classes.push("no-image");
|
||||
}
|
||||
const postTagClass = "tag-" + this.$page.post.tags[0].title;
|
||||
classes.push(postTagClass);
|
||||
} else {
|
||||
classes.push("page-full");
|
||||
classes.push("page");
|
||||
}
|
||||
return classes;
|
||||
},
|
||||
thisPost() {
|
||||
// Return post or page, whichever exists
|
||||
return this.$page.page || this.$page.post
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -135,5 +153,13 @@ export default {
|
|||
content: html
|
||||
image: feature_image
|
||||
}
|
||||
page: ghostPage (path: $path) {
|
||||
id
|
||||
title
|
||||
path
|
||||
date: updated_at (format: "D. MMMM YYYY")
|
||||
description: excerpt
|
||||
content: html
|
||||
}
|
||||
}
|
||||
</page-query>
|
||||
|
|
Loading…
Reference in a new issue