Skip to content

Commit

Permalink
ADDED: new podcast detail page
Browse files Browse the repository at this point in the history
  • Loading branch information
sd-ditoy committed Sep 27, 2023
1 parent 5584a12 commit 49c515a
Show file tree
Hide file tree
Showing 3 changed files with 278 additions and 14 deletions.
41 changes: 27 additions & 14 deletions src/components/blocks/PodcastList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,17 @@
<img :src="pod.image" alt="">
<SVGIconPlay />
</a>
<div class="content">
<a :href="pod.detail_url" class="content">
<h4>{{ pod.title }}</h4>
<div
class="description"
:class="{ open: pod.readmore }"
v-html="pod.description"
/>
<button class="more" @click="readMore(idx, pod.readmore)">
<button class="more" @click.prevent.stop="readMore(idx, pod.readmore)">
{{ pod.readmore ? 'Read less' : 'Read more' }}
</button>
</div>
</a>
<div class="release-date">
<SVGClock />
{{ pod.release_date | date }}
Expand Down Expand Up @@ -145,16 +145,23 @@ export default {
window.h1Set = true;
}
const locale = Intl.getCanonicalLocales(this.$i18n.locale);
const { data } = await this.$d.api.get(`/podcasts?fields[]=url&fields[]=image&fields[]=release_date&fields[]=content.title,content.description&fields[]=status&filter[status][_eq]=published&filter[content][languages_code][_eq]=${locale}&limit=-1`);
const podcasts = (data || []).map((o) => ({
image: `${API_URL}/assets/${o.image}`,
release_date: o.release_date,
url: o.url,
title: (o.content[0] || {}).title,
description: (o.content[0] || {}).description,
readmore: false,
}));
const siteLocale = this.$i18n.locale;
const locale = Intl.getCanonicalLocales(siteLocale);
const { data } = await this.$d.api.get(`/podcasts?fields[]=url&fields[]=image&fields[]=release_date&fields[]=content.title,content.description,content.episode&fields[]=status&filter[status][_eq]=published&filter[content][languages_code][_eq]=${locale}&limit=-1`);
const podcasts = (data || []).map((o) => {
const episode = (o.content[0] || {}).episode ?? null;
const hasEpisode = episode !== null;
const siteUrl = `/${siteLocale}/lp/podcast`;
return {
image: `${API_URL}/assets/${o.image}`,
release_date: o.release_date,
url: o.url,
detail_url: hasEpisode ? `${siteUrl}/episode/${episode}` : siteUrl,
title: (o.content[0] || {}).title,
description: (o.content[0] || {}).description,
readmore: false,
};
});
this.podcasts = podcasts.sort((a, b) => new Date(b.release_date) - new Date(a.release_date));
},
// beforeUpdate() {},
Expand Down Expand Up @@ -308,9 +315,15 @@ export default {
}
}
& > div.content {
& > a.content {
display: block;
text-decoration: none !important;
line-height: normal;
color: inherit;
h4 {
margin-bottom: 10px;
line-height: 1.1;
}
.description {
display: -webkit-box;
Expand Down
7 changes: 7 additions & 0 deletions src/router/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import SingleJob from '@/views/SingleJob.vue';
import NewsIndex from '@/views/news/index.vue';
import EcoSystemFiltered from '@/views/ecosystem/filtered.vue';
import NewsFiltered from '@/views/news/filtered.vue';
import PodcastDetail from '@/views/PodcastDetail.vue';

const { api } = directus;
const { LANGUAGES, API_URL } = config;
Expand Down Expand Up @@ -64,6 +65,12 @@ export function getRouter() {
...r,
component: VIEW_MAPPING[r.meta.page || r.meta.details || r.meta.filtered],
}));
routes = routes.concat([{
name: 'podcast-detail',
path: '/:lang/lp/podcast/episode/:slug',
component: PodcastDetail,
props: route => ({ episode: route.params.slug }),
}]);
Vue.use(Router);
const router = new Router({
mode: 'history',
Expand Down
244 changes: 244 additions & 0 deletions src/views/PodcastDetail.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,244 @@
<template>
<main v-if="details">
<div class="container" v-if="hasLeadSection">
<ArticleLead
:title="leadSection.title"
:content="leadSection.content">
</ArticleLead>
</div>
<ArticleHeroImage
:img-src="leadImage.media"
:img-alt="leadImage.media.caption">
</ArticleHeroImage>
<ArticleDeepLinkBar></ArticleDeepLinkBar>
<section v-for="(block, blockIndex) in computedPageBlocks" :key="blockIndex">
<ArticleTextBlock
v-if="block.blocktype === 'section'"
:title="block.title"
:content="block.content">
</ArticleTextBlock>
<div class="container -long" v-if="block.blocktype === 'highlight'">
<div class="container">
<SingleQuote
:quote="block.content"/>
</div>
</div>
<div class="container block" v-if="block.blocktype === 'carousel'">
<Glider :glide-data="glideData"></Glider>
</div>
</section>
</main>
</template>

<script>
import config from '@/directus/config';
const { API_URL } = config;
export default {
name: 'PodcastDetail',
components: {},
//---------------------------------------------------
//
// Properties
//
//---------------------------------------------------
props: {
episode: {
type: String,
default: null,
},
},
//---------------------------------------------------
//
// Data model
//
//---------------------------------------------------
data() {
return {
details: null,
};
},
metaInfo() {
const title = this.metaTitle;
const description = this.metaDescription;
const image = this.metaImage;
if (title && image) {
return {
title,
meta: [
{ name: 'description', content: description },
{ itemprop: 'title', content: title },
{ itemprop: 'description', content: description },
{ itemprop: 'name', content: title },
{ itemprop: 'image', content: image },
{ name: 'twitter:card', content: 'summary_large_image' },
{ property: 'og:title', content: title },
{ property: 'og:site_name', content: window.location.hostname },
{ property: 'og:description', content: description },
{ property: 'og:type', content: 'website' },
{ property: 'og:url', content: window.location.href },
{ property: 'og:image', content: image },
],
};
}
return null;
},
//---------------------------------------------------
//
// Computed Properties
//
//---------------------------------------------------
computed: {
pageblocks() {
const content = this.details?.content[0] || null;
return content?.page_blocks || [];
},
computedPageBlocks() {
const blocks = this.pageblocks;
let offset = 0;
if (this.hasLeadSection) {
offset += 1;
}
if (this.hasLeadImage) {
offset += 1;
}
return blocks.slice(offset, blocks.length);
},
hasLeadSection() {
const block = this.pageblocks[0] || {};
return block.blocktype === 'section';
},
hasLeadImage() {
const block = this.pageblocks[1] || {};
return block.blocktype === 'image';
},
leadSection() {
return this.pageblocks[0] || {};
},
leadImage() {
return this.pageblocks[1] || {};
},
metaTitle() {
const content = this.details?.content[0] || {};
const lead = this.leadSection;
let title = content.title || `Podcast Episode #${this.episode}`;
title = lead.title || title;
return title;
},
metaDescription() {
const div = document.createElement('div');
const content = this.details?.content[0] || {};
const lead = this.leadSection;
let description = content.description || '';
div.innerHTML = lead.content || description;
description = div.textContent;
return description;
},
metaImage() {
let image = this.leadImage?.media || null;
image = this.details?.image || image;
if (image) {
return `${API_URL}/assets/${image}`;
}
return null;
},
},
//---------------------------------------------------
//
// Watch Properties
//
//---------------------------------------------------
watch: {
},
//---------------------------------------------------
//
// Filter Properties
//
//---------------------------------------------------
// filters: {},
//---------------------------------------------------
//
// Validation Properties
//
//---------------------------------------------------
// validations: {},
//---------------------------------------------------
//
// Vue Lifecycle
//
//---------------------------------------------------
// beforeCreate() {},
// created() {},
// beforeMount() {},
// render(h) { return h(); },
async mounted() {
const locale = Intl.getCanonicalLocales(this.$i18n.locale);
const { data } = await this.$d.api.get(`/podcasts?fields[]=image&fields[]=content.title,content.description,content.page_blocks&filter[status][_eq]=published&filter[content][languages_code][_eq]=${locale}&filter[content][episode][_eq]=${this.episode}&limit=1`);
this.details = (Array.isArray(data) && data[0] !== null) ? data[0] : null;
/*
if (!this.$d.data) {
const url = `/${this.$i18n.locale}/case-studies/`;
window.canonical = window.location.origin + url;
this.$router.replace(url);
} else {
this.getRelatedCasestudies();
const root = document.querySelector(':root');
root.style.setProperty('--headerHeight', `${document.querySelector('header').clientHeight}px`);
}
*/
},
// beforeUpdate() {},
// updated() {},
// beforeDestroy() {},
// destroyed() {},
//---------------------------------------------------
//
// Methods
//
//---------------------------------------------------
methods: {
},
};
</script>
<style lang="scss" scoped>
@import '~scss/mixins';
div.container {
padding-top: 270px;
@include breakpoint(sm) {
padding-top: 120px;
}
&.block {
padding-top: 0;
margin-top: 80px;
margin-bottom: 80px;
display: block;
@include breakpoint('sm') {
margin-top: 32px;
margin-bottom: 80px;
}
}
&.-long {
padding: 0;
> div.container {
padding: 0;
margin-top: 80px;
@include breakpoint('sm') {
margin-top: 32px;
}
}
}
&.redactor-content {
flex-direction: column;
}
}
</style>

0 comments on commit 49c515a

Please sign in to comment.