materio-d9/web/themes/custom/materiotheme/vuejs/components/Pages/Article.vue

323 lines
9.2 KiB
Vue

<template>
<div class="loading" v-if="!article || loading">
<span>Loading ...</span>
</div>
<article class="article" v-else>
<nav class="prevnext top">
<ul>
<li>
<a
v-if="prevnext.prev"
:href="prevnext.prev.view_node"
v-html="prevnext.prev.title"
@click.prevent="onPrevNext(prevnext.prev.view_node)"
/>
</li>
<li>
<a
v-if="prevnext.next"
:href="prevnext.next.view_node"
v-html="prevnext.next.title"
@click.prevent="onPrevNext(prevnext.next.view_node)"
/>
</li>
</ul>
</nav>
<div class="cols">
<div class="col col-left">
<section v-if="image_accroche" class="accroche">
<figure>
<img
:src="image_accroche.url"
:alt="image_accroche.alt"
:title="image_accroche.title"
@click="setLightboxIndex(0)"
/>
</figure>
</section>
<section class="taxonomy">
<div class="thesaurus">
<ul>
<li
v-for="term in article.thesaurus" v-bind:key="term.id"
>{{ term.name }}</li>
</ul>
</div>
<div class="tags">
<ul>
<li
v-for="term in article.tags" v-bind:key="term.id"
>{{ term.name }}</li>
</ul>
</div>
</section>
<section v-if="article.showroom" class="showroom">
<h2>{{ article.showroom.name }}</h2>
<a class="mail" :href="'mail:'+article.showroom.field_public_email">
{{ article.showroom.field_public_email }}</a>
<br/>
<a class="phone" :href="'tel:' + article.showroom.field_public_phone">
{{ article.showroom.field_public_phone }}</a>
</section>
</div> <!-- //col-left -->
<div class="col col-right">
<section class="body" v-html="article.body"></section>
<CoolLightBox
:items="lightbox_items"
:index="lightbox_index"
:loop="true"
srcName="url"
@close="lightbox_index = null">
</CoolLightBox>
<div class="gallery-wrapper">
<div
class="image"
v-for="(image, imageIndex) in lightbox_items"
v-if="imageIndex > 0"
:key="imageIndex"
@click="setLightboxIndex(imageIndex)"
:style="{ backgroundImage: 'url(' + image.thumb + ')' }"
></div>
</div>
<aside class="linked-materials">
<h3 class="field__label">{{$t("materio.Linked Materials")}}</h3>
<div class="card-list">
<ul class="">
<li v-for="node in article.linked_materials" v-bind:key="node.id">
<Card :item="node" />
</li>
</ul>
</div>
</aside>
</div> <!-- // col-right -->
</div> <!-- // cols -->
<nav class="prevnext bottom">
<ul>
<li>
<a
v-if="prevnext.prev"
:href="prevnext.prev.view_node"
v-html="prevnext.prev.title"
@click.prevent="onPrevNext(prevnext.prev.view_node)"
/>
</li>
<li>
<a
v-if="prevnext.next"
:href="prevnext.next.view_node"
v-html="prevnext.next.title"
@click.prevent="onPrevNext(prevnext.next.view_node)"
/>
</li>
</ul>
</nav>
</article>
</template>
<script>
import router from 'vuejs/route'
import store from 'vuejs/store'
// import { JSONAPI } from 'vuejs/api/json-axios'
import { REST } from 'vuejs/api/rest-axios'
import { MGQ } from 'vuejs/api/graphql-axios'
import { print } from 'graphql/language/printer'
import gql from 'graphql-tag'
// import materiauFields from 'vuejs/api/gql/materiau.fragment.gql'
import articleFields from 'vuejs/api/gql/article.fragment.gql'
// import qs from 'querystring-es3'
import Card from 'vuejs/components/Content/Card'
import { mapState, mapActions } from 'vuex'
export default {
name: "Article",
router,
store,
props: ['item'],
data(){
return {
index:-1,
prevnext:{},
nid:null,
path: null,
article:{},
image_accroche: null,
lightbox_items: null,
loading:true,
lightbox_index:null,
}
},
metaInfo () {
return {
title: this.article.title
}
},
computed: {
...mapState({
items: state => state.Blabla.items
})
},
created(){
this.getArticle()
},
methods: {
...mapActions({
getItems: 'Blabla/getItems',
getItemIndex: 'Blabla/getItemIndex',
getPrevNextItems: 'Blabla/getPrevNextItems'
}),
getArticle(){
console.log(this.$route);
// get the article uuid
// if(this.$route.query.nid){
// // we come from internal link with vuejs
// // directly record uuid
// this.nid = this.$route.query.nid
//
// }else if(drupalDecoupled.entity_type == 'node' && drupalDecoupled.entity_bundle == 'article'){
// // we landed in an internal page
// // get the uuid from drupalDeclouped, provided by materio_decoupled.module
// this.nid = drupalDecoupled.entity_id
// }
if (this.$route.path) {
// we come from internal link with vuejs
this.path = this.$route.path
} else {
// we landed in an internal page
this.path = window.location.pathname
}
if(this.path){
this.loadArticle()
}else{
// if for any reason we dont have the uuid
// redirect to home
this.$route.replace('home')
}
},
getIndex(){
console.log("Article getIndex article.id:", this.article.id);
this.getItemIndex(this.article.id).then((index) => {
this.index = index
console.log('article index', index, this);
this.getPrevNextItems(index).then((pn) => {
this.prevnext = pn
})
})
},
loadArticle(){
console.log('loadArticle')
this.loading = true
let ast = gql`{
route(path: "${this.path}") {
...ArticleFields
}
}
${ articleFields }
`
MGQ.post('', { query: print(ast)
})
.then(({ data:{data:{route}}}) => {
console.log('loadArticle', route )
this.parseDataGQL(route)
})
.catch(error => {
console.warn('Issue with loadArticle', error)
Promise.reject(error)
})
},
parseDataGQL(article){
console.log('parseDataGQL article', article)
this.article = article
// get the prev next items
if(!this.items.length){
// if items list not yet loaded preload them
this.getItems().then(() => {
// then get the index
this.getIndex()
})
}else{
// or directly get the index
this.getIndex()
}
this.image_accroche = article.images[0]
this.lightbox_items = [];
// fill the lightbox
for (var i = 0; i < article.images.length; i++) {
article.images[i].thumb = article.images[i].style_articlecardmedium.url
this.lightbox_items.push(article.images[i]);
}
// parse embeded videos pushing it in lightbox
for (var i = 0; i < article.videos.length; i++) {
let videoUrl = article.videos[i].url
let provider_regex = /https:\/\/(www\.)?(?<provider>youtube|vimeo)\.com\/.+/;
let match = provider_regex.exec(videoUrl)
// console.log('provider', match.groups.provider);
let video_id = null;
let video_thumb = null;
switch (match.groups.provider) {
case 'vimeo':
let vimeo_regex = /https:\/\/vimeo\.com\/(?<id>\d+)/;
video_id = vimeo_regex.exec(videoUrl).groups.id || null;
// TODO: get the vimeo thumb https://coderwall.com/p/fdrdmg/get-a-thumbnail-from-a-vimeo-video
video_thumb = "http://blogpeda.ac-poitiers.fr/ent-lyc/files/2015/06/Vimeo_icon_block.png"
break;
case 'youtube':
let youtube_regex = /https:\/\/(www\.)?youtube\.com\/watch\?v=(?<id>.+)/;
video_id = youtube_regex.exec(videoUrl).groups.id || null;
video_thumb = "http://img.youtube.com/vi/"+video_id+"/0.jpg"
break;
}
// console.log('video_id', video_id);
this.lightbox_items.push({
url: videoUrl,
title: "",
description: "",
thumb: video_thumb
});
}
// console.log('this.content.lightbox_items', this.lightbox_items);
// update main page title
this.$store.commit('Common/setPagetitle', article.title)
this.loading = false;
},
onPrevNext(a){
// console.log('clicked on next', this.prevnext.next);
let alias = a.replace(/^.?\/blabla\//g, '')
this.$router.push({
name:`article`,
params: { alias:alias }
})
},
setLightboxIndex(index) {
this.lightbox_index = index
}
},
components: {
Card
},
watch: {
'$route' (to, from) {
console.log('route change')
this.getArticle()
}
}
}
</script>
<style lang="scss" scoped>
</style>