created thematique page

This commit is contained in:
Bachir Soussi Chiadmi 2020-12-25 17:37:15 +01:00
parent f65e8fb140
commit 144ab7db26
13 changed files with 589 additions and 67 deletions

View File

@ -0,0 +1,22 @@
uuid: f38038f5-afbd-48f5-98aa-f32fa56b3cd5
langcode: en
status: true
dependencies:
module:
- node
id: thematique
label: Thematique
type: 'canonical_entities:node'
pattern: 'thematique/[node:title]'
selection_criteria:
a7ecad62-8643-4783-9b2e-56f739bfa1b1:
id: node_type
bundles:
thematique: thematique
negate: false
context_mapping:
node: node
uuid: a7ecad62-8643-4783-9b2e-56f739bfa1b1
selection_logic: and
weight: -5
relationships: { }

View File

@ -2,12 +2,14 @@ scalar Violation
interface NodeInterface {
id: Int!
path: String!
}
type Materiau implements NodeInterface {
id: Int!
uuid: String!
title: String!
path: String!
author: String
body: String
short_description: String
@ -31,6 +33,7 @@ type Article implements NodeInterface {
id: Int!
uuid: String!
title: String!
path: String!
author: String
body: String
linked_materials: [Materiau]
@ -44,11 +47,25 @@ type Article implements NodeInterface {
memo: String
}
type Thematique implements NodeInterface {
id: Int!
uuid: String!
title: String!
path: String!
author: String
body: String
linked_materials: [Materiau]
images: [Image]
tags: [Tag]
memo: String
}
type SearchResult {
id: Int!
uuid: String!
title: String!
bundle: String
bundle: String!
path: String!
short_description: String
images: [Image]
visuels: [Image]

View File

@ -18,6 +18,10 @@ extend type Query {
article(id: Int!): Article
}
extend type Query {
thematique(id: Int!): Thematique
}
extend type Query {
showroom(id: Int!): Showroom
}

View File

@ -27,29 +27,7 @@ class MaterioSchemaExtension extends SdlSchemaExtensionPluginBase {
public function registerResolvers(ResolverRegistryInterface $registry) {
$builder = new ResolverBuilder();
// Tell GraphQL how to resolve types of a common interface.
$registry->addTypeResolver('NodeInterface', function ($value) {
$path = explode('\\', get_class($value));
$class = array_pop($path);
if ($class === 'Node') {
switch ($value->bundle()) {
case 'article': return 'Article';
case 'materiau': return 'Materiau';
}
}
throw new Error('Could not resolve content type.');
});
$registry->addFieldResolver('Query', 'route',
$builder->compose(
$builder->produce('route_load')
->map('path', $builder->fromArgument('path')),
$builder->produce('route_entity')
->map('url', $builder->fromParent())
));
$this->addRouteResolver($registry, $builder);
$this->addMateriau($registry, $builder);
@ -59,6 +37,8 @@ class MaterioSchemaExtension extends SdlSchemaExtensionPluginBase {
$this->addArticle($registry, $builder);
$this->addThematique($registry, $builder);
$this->addCompany($registry, $builder);
$this->addAddress($registry, $builder);
@ -88,6 +68,36 @@ class MaterioSchemaExtension extends SdlSchemaExtensionPluginBase {
]);
}
// ___ _
// | _ \___ _ _| |_ ___
// | / _ \ || | _/ -_)
// |_|_\___/\_,_|\__\___|
protected function addRouteResolver(ResolverRegistryInterface $registry, ResolverBuilder $builder) {
// Tell GraphQL how to resolve types of a common interface.
$registry->addTypeResolver('NodeInterface', function ($value) {
$path = explode('\\', get_class($value));
$class = array_pop($path);
if ($class === 'Node') {
switch ($value->bundle()) {
case 'article': return 'Article';
case 'materiau': return 'Materiau';
case 'thematique': return 'Thematique';
}
}
throw new Error('Could not resolve content type.');
});
$registry->addFieldResolver('Query', 'route',
$builder->compose(
$builder->produce('route_load')
->map('path', $builder->fromArgument('path')),
$builder->produce('route_entity')
->map('url', $builder->fromParent())
));
}
// __ __ _ _
// | \/ |__ _| |_ ___ _ _(_)__ _ _ _
// | |\/| / _` | _/ -_) '_| / _` | || |
@ -117,6 +127,15 @@ class MaterioSchemaExtension extends SdlSchemaExtensionPluginBase {
->map('entity', $builder->fromParent())
);
$registry->addFieldResolver('Materiau', 'path',
$builder->compose(
$builder->produce('entity_url')
->map('entity', $builder->fromParent()),
$builder->produce('url_path')
->map('url', $builder->fromParent())
)
);
$registry->addFieldResolver('Materiau', 'title',
$builder->compose(
$builder->produce('entity_label')
@ -269,6 +288,15 @@ class MaterioSchemaExtension extends SdlSchemaExtensionPluginBase {
->map('entity', $builder->fromParent())
);
$registry->addFieldResolver('SearchResult', 'path',
$builder->compose(
$builder->produce('entity_url')
->map('entity', $builder->fromParent()),
$builder->produce('url_path')
->map('url', $builder->fromParent())
)
);
$registry->addFieldResolver('SearchResult', 'title',
$builder->compose(
$builder->produce('entity_label')
@ -343,6 +371,15 @@ class MaterioSchemaExtension extends SdlSchemaExtensionPluginBase {
->map('entity', $builder->fromParent())
);
$registry->addFieldResolver('Article', 'path',
$builder->compose(
$builder->produce('entity_url')
->map('entity', $builder->fromParent()),
$builder->produce('url_path')
->map('url', $builder->fromParent())
)
);
$registry->addFieldResolver('Article', 'title',
$builder->compose(
$builder->produce('entity_label')
@ -428,6 +465,87 @@ class MaterioSchemaExtension extends SdlSchemaExtensionPluginBase {
);
}
// _____ _ _ _
// |_ _| |_ ___ _ __ __ _| |_(_)__ _ _ _ ___
// | | | ' \/ -_) ' \/ _` | _| / _` | || / -_)
// |_| |_||_\___|_|_|_\__,_|\__|_\__, |\_,_\___|
// |_|
protected function addThematique(ResolverRegistryInterface $registry, ResolverBuilder $builder) {
$registry->addFieldResolver('Query', 'Thematique',
$builder->produce('entity_load')
->map('type', $builder->fromValue('node'))
->map('bundles', $builder->fromValue(['thematique']))
->map('id', $builder->fromArgument('id'))
);
$registry->addFieldResolver('Thematique', 'id',
$builder->produce('entity_id')
->map('entity', $builder->fromParent())
);
$registry->addFieldResolver('Thematique', 'uuid',
$builder->produce('entity_uuid')
->map('entity', $builder->fromParent())
);
$registry->addFieldResolver('Thematique', 'path',
$builder->compose(
$builder->produce('entity_url')
->map('entity', $builder->fromParent()),
$builder->produce('url_path')
->map('url', $builder->fromParent())
)
);
$registry->addFieldResolver('Thematique', 'title',
$builder->compose(
$builder->produce('entity_label')
->map('entity', $builder->fromParent())
));
$registry->addFieldResolver('Thematique', 'author',
$builder->compose(
$builder->produce('entity_owner')
->map('entity', $builder->fromParent()),
$builder->produce('entity_label')
->map('entity', $builder->fromParent())
));
$registry->addFieldResolver('Thematique', 'body',
$builder->produce('property_path')
->map('type', $builder->fromValue('entity:node'))
->map('value', $builder->fromParent())
->map('path', $builder->fromValue('body.value'))
);
$registry->addFieldResolver('Thematique', 'memo',
$builder->produce('property_path')
->map('type', $builder->fromValue('entity:node'))
->map('value', $builder->fromParent())
->map('path', $builder->fromValue('field_memo.value'))
);
// https://github.com/drupal-graphql/graphql/blob/8.x-4.x/doc/SUMMARY.md
// https://blog.chrismitchellonline.com/posts/custom_graphql_data/
$registry->addFieldResolver('Thematique', 'linked_materials',
$builder->produce('entity_reference')
->map('entity', $builder->fromParent())
->map('field', $builder->fromValue('field_linked_materials'))
);
$registry->addFieldResolver('Thematique', 'images',
$builder->produce('entity_reference')
->map('entity', $builder->fromParent())
->map('field', $builder->fromValue('field_visuel'))
);
$registry->addFieldResolver('Thematique', 'tags',
$builder->produce('entity_reference')
->map('entity', $builder->fromParent())
->map('field', $builder->fromValue('field_tags'))
);
}
// ___
// |_ _|_ __ __ _ __ _ ___
// | || ' \/ _` / _` / -_)

View File

@ -1418,7 +1418,8 @@ header[role="banner"] {
body.path-showrooms header[role="banner"] #block-pagetitle h2 {
color: #fff;
background-color: #50aa3c; }
body.path-base header[role="banner"] #block-pagetitle h2 {
body.path-base header[role="banner"] #block-pagetitle h2,
body.path-thematique header[role="banner"] #block-pagetitle h2 {
color: #fff;
background-color: #69cdcf; }
header[role="banner"] #block-materiosapisearchblock {
@ -1798,6 +1799,46 @@ article.card {
article.card.modal-card section.col-right nav.tools section.close span.btn.mdi-close {
cursor: pointer; }
#main-content > article.thematique div.cols {
display: grid;
grid-template-rows: 1fr;
grid-template-columns: repeat(12, 1fr);
grid-gap: 1em; }
#main-content > article.thematique div.cols div.col-left {
grid-column: 1; }
#main-content > article.thematique div.cols div.col-right {
grid-column: 2/12; }
#main-content > article.thematique div.col-left section.body {
background-color: #69cdcf;
padding: 0.5em 1em 1em;
width: 423px; }
#main-content > article.thematique aside.linked-materials ul {
width: calc(100% + 13px); }
#main-content > article.thematique aside.linked-materials ul li {
display: inline-block;
vertical-align: top;
width: 205px;
margin: 0 13px 13px 0; }
#main-content > article.thematique aside.linked-materials h3.field__label {
font-size: 1em;
font-weight: 500;
margin: 2em 0 1em 0; }
#main-content > article.thematique aside.linked-materials h1.title {
font-size: 1em;
font-weight: 400; }
#main-content > article.thematique aside.linked-materials h3.ref {
font-size: 0.756em;
font-weight: 600; }
#main-content > article.thematique aside.linked-materials h2.description {
font-size: 0.756em;
font-weight: 400; }
#main-content > article.article div.cols {
display: grid;
grid-template-rows: 1fr;

File diff suppressed because one or more lines are too long

View File

@ -16,7 +16,6 @@ aside.messages{
border:none;
}
// _ _ _
// | || |___ __ _ __| |___ _ _
// | __ / -_) _` / _` / -_) '_|
@ -331,7 +330,8 @@ header[role="banner"]{
color: #fff;
background-color: $color-showrooms;
}
body.path-base & {
body.path-base &,
body.path-thematique & {
color: #fff;
background-color: $color-base;
}
@ -913,6 +913,60 @@ article.card{
}
// _____ _ _ _
// |_ _| |_ ___ _ __ __ _| |_(_)__ _ _ _ ___
// | | | ' \/ -_) ' \/ _` | _| / _` | || / -_)
// |_| |_||_\___|_|_|_\__,_|\__|_\__, |\_,_\___|
// |_|
#main-content > article.thematique{
div.cols{
display: grid;
grid-template-rows: 1fr;
grid-template-columns: repeat(12, 1fr);
grid-gap: 1em;
div.col-left{
grid-column: 1;
}
div.col-right{
grid-column: 2/12;
}
}
div.col-left section.body{
background-color: $color-base;
padding: 0.5em 1em 1em;
width:$column_width*2 + $column_goutiere;
}
aside.linked-materials{
ul{
width:calc(100% + #{$column_goutiere});
li{
display: inline-block;
vertical-align: top;
width:$column_width;
margin:0 $column_goutiere $column_goutiere 0;
}
}
h3.field__label{
font-size: 1em;
font-weight: 500;
margin: 2em 0 1em 0;
}
h1.title{
font-size: 1em;
font-weight: 400;
}
h3.ref{
font-size: 0.756em;
font-weight: 600;
}
h2.description{
font-size: 0.756em;
font-weight: 400;
}
}
}
// ___ _ _ _
// | _ ) |__ _| |__| |__ _

View File

@ -4,18 +4,17 @@ fragment SearchResultFields on SearchResult {
title
short_description
reference
path
images{
url
alt
style_cardmedium{
url
}
style_cardmedium_url
style_hd_url
}
visuels{
url
alt
style_cardmedium{
url
}
style_cardmedium_url
style_hd_url
}
}

View File

@ -0,0 +1,27 @@
fragment ThematiqueFields on Thematique {
id
title
body
tags {
id
name
}
linked_materials {
id
title
short_description
images {
url
style_cardmedium_url
style_hd_url
}
}
images {
id
url
alt
style_cardmedium{
url
}
}
}

View File

@ -118,7 +118,8 @@ export default {
}
},
openModalCard (e) {
if(this.isLoggedin){
console.log('openModalCard', this.isLoggedin);
if(this.isloggedin){
this.$modal.show(
ModalCard,
{ item: this.item },

View File

@ -1,10 +1,13 @@
<template>
<article class="card card-thematique search-card">
<header
@click="openThematique"
>
<h1>{{ item.title }}</h1>
<h4>{{ item.short_description }}</h4>
<header>
<a
:href="item.path"
@click.prevent="openThematique"
>
<h1>{{ item.title }}</h1>
<h4>{{ item.short_description }}</h4>
</a>
</header>
<section class="images" v-switcher>
<figure
@ -14,7 +17,7 @@
<img
class="lazy"
v-lazy="index"
:data-src="img.style_cardmedium.url"
:data-src="img.style_cardmedium_url"
:title="img.title"
/>
<img
@ -27,7 +30,7 @@
<CoolLightBox
:items="item.visuels"
:index="lightbox_index"
srcName="url"
srcName="style_hd_url"
:loop="true"
@close="lightbox_index = null">
</CoolLightBox>
@ -50,7 +53,8 @@ export default {
return {
blanksrc:`${drupalSettings.path.themePath}/assets/img/blank.gif`,
// loadingFlag: false,
lightbox_index: null
lightbox_index: null,
alias: this.item.path.replace(/^.?\/thematique\//g, '')
}
},
// computed: {
@ -95,15 +99,12 @@ export default {
// },
openThematique (e) {
console.log('openThematique', e);
// this.$modal.show(
// ModalCard,
// { item: this.item },
// {
// draggable: true,
// width: '850px',
// height: '610px'
// }
// )
this.$router.push({
name:`thematique`,
params: { alias:this.alias }
// query: { nid: this.item.nid }
// meta: { uuid:this.item.uuid },
})
}
}
}

View File

@ -0,0 +1,151 @@
<template>
<div class="loading" v-if="!thematique || loading">
<span>Loading ...</span>
</div>
<article class="thematique" v-else>
<div class="cols">
<div class="col col-left">
<section class="body" v-html="thematique.body"></section>
</div> <!-- //col-left -->
<div class="col col-right">
<aside class="linked-materials">
<div class="card-list">
<ul class="">
<li v-for="node in thematique.linked_materials" v-bind:key="node.id">
<Card :item="node" />
</li>
</ul>
</div>
</aside>
</div> <!-- // col-right -->
</div> <!-- // cols -->
</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 thematiqueFields from 'vuejs/api/gql/thematique.fragment.gql'
// import qs from 'querystring-es3'
import Card from 'vuejs/components/Content/Card'
import { mapState, mapActions } from 'vuex'
export default {
name: "Thematique",
router,
store,
data(){
return {
nid:null,
path: null,
thematique:{},
image_accroche: null,
loading:true,
}
},
metaInfo () {
return {
title: this.thematique.title
}
},
// computed: {
// ...mapState({
// items: state => state.Blabla.items
// })
// },
created(){
this.getThematique()
},
methods: {
// ...mapActions({
// getItems: 'Blabla/getItems',
// getItemIndex: 'Blabla/getItemIndex',
// getPrevNextItems: 'Blabla/getPrevNextItems'
// }),
getThematique(){
console.log('getThematique', 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.loadThematique()
}else{
// if for any reason we dont have the uuid
// redirect to home
this.$route.replace('home')
}
},
loadThematique(){
console.log('loadThematique')
this.loading = true
let ast = gql`{
route(path: "${this.path}") {
...ThematiqueFields
}
}
${ thematiqueFields }
`
MGQ.post('', { query: print(ast)
})
.then(({ data:{data:{route}}}) => {
console.log('loaded Thematique', route)
this.parseDataGQL(route)
})
.catch(error => {
console.warn('Issue with loadThematique', error)
Promise.reject(error)
})
},
parseDataGQL(thematique){
console.log('parseDataGQL thematique', thematique)
this.thematique = thematique
this.image_accroche = thematique.images[0]
// update main page title
this.$store.commit('Common/setPagetitle', thematique.title)
this.loading = false;
},
},
components: {
Card
},
watch: {
'$route' (to, from) {
console.log('route change')
this.getThematique()
}
}
}
</script>
<style lang="scss" scoped>
</style>

View File

@ -3,6 +3,7 @@ import VueRouter from 'vue-router'
import Home from 'vuejs/components/Pages/Home'
import Base from 'vuejs/components/Pages/Base'
import Thematique from 'vuejs/components/Pages/Thematique'
import Blabla from 'vuejs/components/Pages/Blabla'
import Article from 'vuejs/components/Pages/Article'
import Showrooms from 'vuejs/components/Pages/Showrooms'
@ -41,17 +42,11 @@ const routes = [
// 'base': Base
// }
},
// {
// name:'blabla',
// path: `${basePath}blabla`,
// component: Blabla,
// children: [
// {
// path: `${basePath}blabla/:alias`,
// component: Article
// }
// ]
// }
{
name: 'thematique',
path: `${basePath}thematique/:alias`,
component: Thematique
},
{
name: 'blabla',
path: `${basePath}blabla`,