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

388 lines
12 KiB
Vue
Raw Normal View History

<template>
2019-07-25 21:23:23 +02:00
<div class="loading" v-if="!content || loading">
<span>Loading ...</span>
</div>
<article class="article" v-else>
2019-07-25 21:23:23 +02:00
<nav class="prevnext top">
<ul>
<li>
<a
@click.prevent="onPrev"
href="#"
v-if="prevnext.prev"
v-html="prevnext.prev.title"
/>
</li>
<li>
<a
@click.prevent="onNext"
href="#"
v-if="prevnext.next"
v-html="prevnext.next.title"
/>
</li>
</ul>
</nav>
2020-02-20 10:36:49 +01:00
<div class="cols">
<div class="col col-left">
2020-02-20 12:57:35 +01:00
<section v-if="content.image_accroche" class="accroche">
2020-02-20 10:36:49 +01:00
<figure>
<img
:src="content.image_accroche.src"
:alt="content.image_accroche.alt"
:title="content.image_accroche.title"
2020-02-19 17:59:26 +01:00
/>
2020-02-20 10:36:49 +01:00
</figure>
</section>
<section class="taxonomy">
<div class="thesaurus">
<ul>
<li
v-for="term in content.field_thesaurus" v-bind:key="term.id"
>{{ term.name }}</li>
</ul>
</div>
<div class="tags">
<ul>
<li
v-for="term in content.field_tags" v-bind:key="term.id"
>{{ term.name }}</li>
</ul>
</div>
</section>
2020-02-20 12:57:35 +01:00
<section v-if="content.field_showroom" class="showroom">
<h2>{{ content.field_showroom.name }}</h2>
<a class="mail" :href="'mail:'+content.field_showroom.field_public_email">
{{ content.field_showroom.field_public_email }}</a>
<br/>
<a class="phone" :href="'tel:' + content.field_showroom.field_public_phone">
{{ content.field_showroom.field_public_phone }}</a>
</section>
2020-02-20 10:36:49 +01:00
</div> <!-- //col-left -->
<div class="col col-right">
<section class="body" v-html="content.body"></section>
<CoolLightBox
:items="content.lightbox_items"
:index="lightbox_index"
:loop="true"
@close="lightbox_index = null">
</CoolLightBox>
<div class="gallery-wrapper">
<div
class="image"
v-for="(image, imageIndex) in content.lightbox_items"
:key="imageIndex"
@click="setLightboxIndex(imageIndex)"
:style="{ backgroundImage: 'url(' + image.thumb + ')' }"
></div>
</div>
<aside class="linked-materials">
<h3 class="field__label">Linked Materials</h3>
<div class="card-list">
<ul class="">
<li v-for="node in content.field_linked_materials" v-bind:key="node.id">
<Card :item="node" />
</li>
</ul>
</div>
</aside>
2020-02-20 10:36:49 +01:00
</div> <!-- // col-right -->
</div> <!-- // cols -->
2019-07-25 21:23:23 +02:00
<nav class="prevnext bottom">
<ul>
<li>
<a
@click.prevent="onPrev"
href="#"
v-if="prevnext.prev"
v-html="prevnext.prev.title"
/>
</li>
<li>
<a
@click.prevent="onNext"
href="#"
v-if="prevnext.next"
v-html="prevnext.next.title"
/>
</li>
</ul>
</nav>
</article>
</template>
<script>
import router from 'vuejs/route'
2019-07-25 21:23:23 +02:00
import store from 'vuejs/store'
import { JSONAPI } from 'vuejs/api/json-axios'
2020-11-25 21:42:56 +01:00
import qs from 'querystring-es3'
2019-07-25 21:23:23 +02:00
import Card from 'vuejs/components/Content/Card'
2019-07-14 17:12:18 +02:00
import { mapState, mapActions } from 'vuex'
export default {
name: "Article",
router,
2019-07-25 21:23:23 +02:00
store,
props: ['item'],
data(){
return {
2019-07-14 17:12:18 +02:00
index:-1,
prevnext:{},
uuid:null,
2019-07-25 21:23:23 +02:00
content:null,
loading:true,
lightbox_index:null,
}
},
2019-07-25 21:23:23 +02:00
computed: {
...mapState({
items: state => state.Blabla.items
})
},
created(){
this.getArticle()
},
methods: {
2019-07-14 17:12:18 +02:00
...mapActions({
2019-07-25 21:23:23 +02:00
getItems: 'Blabla/getItems',
2019-07-14 17:12:18 +02:00
getItemIndex: 'Blabla/getItemIndex',
getPrevNextItems: 'Blabla/getPrevNextItems'
}),
getArticle(){
console.log(this.$route);
// get the article uuid
if(this.$route.query.uuid){
// we come from internal link with vuejs
// directly record uuid
this.uuid = this.$route.query.uuid
}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.uuid = drupalDecoupled.entity_uuid
}
if(this.uuid){
this.loadArticle()
2019-07-25 21:23:23 +02:00
// 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()
}
}else{
// if for any reason we dont have the uuid
// redirect to home
this.$route.replace('home')
}
},
2019-07-25 21:23:23 +02:00
getIndex(){
console.log("Article getIndex");
this.getItemIndex(this.uuid).then((index) => {
this.index = index
// console.log('article index', index, this);
this.getPrevNextItems(index).then((pn) => {
this.prevnext = pn
})
})
},
loadArticle(){
console.log('loadArticle', this.uuid)
2019-07-25 21:23:23 +02:00
this.loading = true;
let params = {
2019-07-25 21:23:23 +02:00
include:'field_linked_materials.images,field_showroom,field_tags,field_thesaurus,field_visuel,uid'
}
let q = qs.stringify(params)
JSONAPI.get(`node/article/${this.uuid}?${q}`)
.then(({ data }) => {
console.log('loadArticle data', data)
this.parseData(data)
})
.catch(( error ) => {
console.warn('Issue with loadArticle', error)
Promise.reject(error)
})
},
parseData(data){
let attrs = data.data.attributes
let relations = data.data.relationships
console.log('relations', relations);
let inc = data.included
console.log('included', inc);
this.content = {
title:attrs.title,
body: attrs.body.value
}
// build lightbox array
// will be filled by videos and field_visuel
this.content.lightbox_items = [];
2020-02-20 12:57:35 +01:00
// parse embeded videos pushing it in lightbox
for(let key in attrs.field_video){
let videolink = attrs.field_video[key]
2020-02-20 12:57:35 +01:00
// console.log('videolink', videolink);
let provider_regex = /https:\/\/(www\.)?(?<provider>youtube|vimeo)\.com\/.+/;
let match = provider_regex.exec(videolink)
2020-02-20 12:57:35 +01:00
// 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(videolink).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(videolink).groups.id || null;
video_thumb = "http://img.youtube.com/vi/"+video_id+"/0.jpg"
break;
}
2020-02-20 12:57:35 +01:00
// console.log('video_id', video_id);
this.content.lightbox_items.push({
src: videolink,
title: "",
description: "",
thumb: video_thumb
});
// this.content.videos.push({
// provider: match.groups.provider,
// id: video_id,
// href: videolink
// });
}
// parse all relationships
for (let key in relations) {
// skip loop if the property is from prototype
if (!relations.hasOwnProperty(key)) continue;
2019-07-25 21:23:23 +02:00
let relation_obj = relations[key]
2020-02-20 12:57:35 +01:00
console.log("relation", key, relation_obj);
// console.log('typeof relation_obj.data', typeof relation_obj.data);
if(!relation_obj.data) continue;
// showroom is unique field so no array in data
// we parse it here
switch (key) {
case 'field_showroom':
let included = inc.find((i) => { return i.id == relation_obj.data.id })
// console.log('included',included);
this.content[key] = included.attributes;
break
}
2019-07-25 21:23:23 +02:00
// skip relation_obj if data is not array
if(!Array.isArray(relation_obj.data)) continue
// create empty field array
this.content[key] = []
// parse relationship values using included
let field = {}
2019-07-25 21:23:23 +02:00
// loop through all relation items
relation_obj.data.forEach((e) => {
// get the included values for each item using id
let included = inc.find((i) => { return i.id == e.id })
2019-07-25 21:23:23 +02:00
// if we not found an included item skip the item
if(typeof included != 'undefined'){
2019-07-25 21:23:23 +02:00
// fill the item values
switch (key) {
case 'field_visuel':
// build the field object (not used for now)
field = e.meta
field.id = e.id
field.src = included.attributes.uri.url
field.thumb = included.links.article_card_medium.href
break;
case 'field_linked_materials':
2019-07-25 21:23:23 +02:00
field = included.attributes
field.id = field.uuid = included.id
2019-07-25 21:23:23 +02:00
// get the linked material included images
field.images = [];
included.relationships.images.data.forEach((img) => {
// console.log('href', img.meta.imageDerivatives.links.card_medium.href);
if(img.meta.imageDerivatives){
field.images.push({
title:img.meta.title,
src: img.meta.imageDerivatives.links.hd.href,
img_styles: {
card_medium: img.meta.imageDerivatives.links.card_medium.href,
card_full: img.meta.imageDerivatives.links.card_full.href
}
})
}
2019-07-25 21:23:23 +02:00
})
break;
case 'field_thesaurus':
case 'field_tags':
field = included.attributes
field.id = included.id
break;
default:
}
this.content[key].push(field)
}
})
2020-02-19 15:58:15 +01:00
}
2020-02-19 15:58:15 +01:00
// extract first visuel as accroche
this.content.image_accroche = this.content.field_visuel.shift()
// fill the lightbox
for(let visuel of this.content.field_visuel){
this.content.lightbox_items.push(visuel);
2020-02-19 17:59:26 +01:00
}
console.log('this.content.lightbox_items', this.content.lightbox_items);
2020-02-19 17:59:26 +01:00
2019-07-25 21:23:23 +02:00
// update main page title
this.$store.commit('Common/setPagetitle', this.content.title)
2019-07-25 21:23:23 +02:00
this.loading = false;
console.log('article.content',this.content);
2019-07-14 17:12:18 +02:00
},
onNext(){
2019-07-25 21:23:23 +02:00
// console.log('clicked on next', this.prevnext.next);
2019-07-14 17:12:18 +02:00
let alias = this.prevnext.next.view_node.replace(/^.?\/blabla\//g, '')
this.$router.push({
name:`article`,
params: { alias:alias },
query: { uuid: this.prevnext.next.uuid }
})
},
onPrev(){
2019-07-25 21:23:23 +02:00
// console.log('clicked on prev', this.prevnext.next);
2019-07-14 17:12:18 +02:00
let alias = this.prevnext.prev.view_node.replace(/^.?\/blabla\//g, '')
this.$router.push({
name:`article`,
params: { alias:alias },
query: { uuid: this.prevnext.prev.uuid }
})
},
setLightboxIndex(index) {
this.lightbox_index = index
2019-07-14 17:12:18 +02:00
}
},
2019-07-25 21:23:23 +02:00
components: {
Card
},
2019-07-14 17:12:18 +02:00
watch: {
'$route' (to, from) {
console.log('route change')
this.getArticle()
}
}
}
</script>
<style lang="scss" scoped>
</style>