refactor content store data fetching with promises

This commit is contained in:
Valentin Le Moign 2025-03-07 17:46:13 +01:00
parent dffd179bc9
commit 2ca44f2550
8 changed files with 354 additions and 487 deletions

View File

@ -3,6 +3,25 @@
import { defineStore } from 'pinia';
import REST from '../api/rest-axios';
import { findContentByPath } from '../utils/content/findContentByPath';
import {
getCleanDate,
fetchFromRelationships,
getRelatedEtape,
} from '../utils/content/contentFetchUtils';
import {
getCarteSensible,
getTitreTexte,
getChiffresCles,
getDiaporama,
getEntretien,
getVideos,
} from '../utils/content/cleanParties';
import {
getPartenaires,
getGouvernance,
} from '../utils/content/multiItemPages';
export const useContentStore = defineStore('content', {
state: () => ({
contentType: '',
@ -14,7 +33,7 @@ export const useContentStore = defineStore('content', {
etape_number: '',
couleur: '',
dates: {},
previous : {},
previous: {},
next: {},
vignette: {},
parties: [],
@ -30,105 +49,23 @@ export const useContentStore = defineStore('content', {
}),
actions: {
async fetchContentData(path) {
console.log('start fetch content');
this.resetStore(false);
const contentTypes = [ 'etape', 'static', 'gouvernance', 'partenaire' ];
const contentTypes = ['etape', 'static', 'gouvernance', 'partenaire'];
try {
const findContentByPath = async (contentTypes, path) => {
for (let type of contentTypes) {
const response = await REST.get(`/jsonapi/node/${type}/`);
const content = response.data.data.find(content =>
content.attributes.metatag.some(tag =>
tag.tag === "link" && tag.attributes.href === path
)
);
if (content) {
console.log('content found');
return {
contentType: type,
rawContent: content,
};
}
// Handle special case for governance/partners (multiple items per page)
const pageRequested = window.location.href.split('/').pop().replace(/s?$/, '');
if (type === pageRequested
|| (type === 'gouvernance' && pageRequested === 'contact')
) {
return {
contentType: type,
rawContent: response.data.data,
};
}
}
return null;
};
const { contentType, rawContent } = await findContentByPath(contentTypes, path);
this.contentType = contentType;
// console.log(`current type: ${contentType}`);
if (this.contentType !== 'gouvernance' && this.contentType !== 'partenaire') {
const vignettePromise = fetchFromRelationships('field_vignette', rawContent.relationships);
const partiesPromise = fetchFromRelationships('field_parties', rawContent.relationships);
// TO DEBUG
const cleanContentMethod = 'original';
if (this.contentType !== 'gouvernance' && this.contentType !== 'partenaire'
&& cleanContentMethod === 'original'
) {
console.time('etape content processing');
// pageTitle
for (let tag of rawContent.attributes.metatag) {
if (tag.tag === "meta") {
this.pageTitle = tag.attributes.content;
break;
}
}
// contentTitle
this.content.contentTitle = rawContent.attributes.title;
// vignette
const vignetteFetch = await this.fetchFromRelationships('field_vignette', rawContent.relationships);
if (vignetteFetch) {
this.content.vignette = {
url: {
original: vignetteFetch.attributes.uri.url,
small: vignetteFetch.attributes.image_style_uri.content_small,
medium: vignetteFetch.attributes.image_style_uri.content_medium,
large: vignetteFetch.attributes.image_style_uri.content_large,
},
alt: rawContent.relationships.field_vignette.data.meta.alt
};
}
// liens
if (rawContent.attributes.field_liens.length) {
this.content.liens = [];
for (let lien of rawContent.attributes.field_liens) {
this.content.liens.push({
title: lien.title,
url: lien.uri,
});
}
}
// pièces jointes
if (rawContent.relationships.field_pieces_jointes.data.length) {
this.content.pieces_jointes = [];
for (let pieceJointe of rawContent.relationships.field_pieces_jointes.data) {
if (pieceJointe.meta.display) {
const uuid = pieceJointe.id;
const response = await REST.get(`/jsonapi/file/file/${uuid}`);
this.content.pieces_jointes.push({
title: pieceJointe.meta.description,
url: response.data.data.attributes.uri.url,
});
}
}
}
let previousEtapePromise, nextEtapePromise;
if (contentType === 'etape') {
// related étapes
previousEtapePromise = getRelatedEtape('previous', path);
nextEtapePromise = getRelatedEtape('next', path);
// coordinates
this.content.coordinates = {
lat: rawContent.attributes.field_geofield.lat,
@ -142,185 +79,9 @@ export const useContentStore = defineStore('content', {
this.content.couleur = rawContent.attributes.field_couleur;
// dates
this.content.dates = {
start: this.getCleanDate(rawContent.attributes.field_dates.value),
end: this.getCleanDate(rawContent.attributes.field_dates.end_value),
start: getCleanDate(rawContent.attributes.field_dates.value),
end: getCleanDate(rawContent.attributes.field_dates.end_value),
}
// previous / next
await this.getRelatedEtape('previous', path);
await this.getRelatedEtape('next', path);
}
// parties
const fieldParties = contentType === 'etape' ? 'field_parties' : 'field_parties_static';
const partiesFetch = await this.fetchFromRelationships(fieldParties, rawContent.relationships);
console.log(this.content);
console.timeEnd('etape content processing');
if (partiesFetch) {
this.content.parties = [];
for (let partie of partiesFetch) {
const partieType = partie.type.replace(/^paragraph--/, "");
let partieContent = {
type: partieType,
};
switch (partieType) {
case 'carte_sensible':
const carteSensibleFetch = await this.fetchFromRelationships('field_image_carte', partie.relationships);
if (carteSensibleFetch) {
partieContent.carteSensible = {
url: {
original: carteSensibleFetch.attributes.uri.url,
small: carteSensibleFetch.attributes.image_style_uri.content_small,
medium: carteSensibleFetch.attributes.image_style_uri.content_medium,
large: carteSensibleFetch.attributes.image_style_uri.content_large,
xlarge: carteSensibleFetch.attributes.image_style_uri.content_x_large,
},
alt: partie.relationships.field_image_carte.data.meta.alt,
};
}
break;
case 'titre_texte':
console.time('get images from text original')
partieContent.titre = partie.attributes.field_titre;
partieContent.texte = partie.attributes.field_texte.value;
// get the resized images from the text
const imgRegex = /<img[^>]+>/g;
const uuidRegex = /data-entity-uuid="([^"]+)"/;
const imgTags = partieContent.texte.match(imgRegex);
if (imgTags) {
for (const imgTag of imgTags) {
const uuidMatch = imgTag.match(uuidRegex);
if (uuidMatch && uuidMatch[1]) {
const uuid = uuidMatch[1];
const response = await REST.get(`/jsonapi/file/file/${uuid}`);
const imagesFetch = response.data.data;
const newImgTag = imgTag
.replace(/src="[^"]+"/,`src="${imagesFetch.attributes.image_style_uri.content_medium}"`)
.replace('>',' data-large-src="' + imagesFetch.attributes.image_style_uri.content_large + '">');
partieContent.texte = partieContent.texte.replace(imgTag, newImgTag);
}
}
}
console.timeEnd('get images from text original')
break;
case 'chiffres_cles':
const chiffresClesFetch = await this.fetchFromRelationships('field_chiffres_clefs', partie.relationships);
if (chiffresClesFetch) {
partieContent.chiffresCles = [];
for (let chiffre of chiffresClesFetch) {
partieContent.chiffresCles.push({
chiffre: chiffre.attributes.field_chiffre,
description: chiffre.attributes.field_description,
});
}
}
break;
case 'diaporama':
const diaporamaFetch = await this.fetchFromRelationships('field_diaporama', partie.relationships);
if (diaporamaFetch) {
partieContent.diaporama = [];
for (let [index, image] of diaporamaFetch.entries()) {
partieContent.diaporama.push({
url: {
original: image.attributes.uri.url,
small: image.attributes.image_style_uri.content_small,
medium: image.attributes.image_style_uri.content_medium,
large: image.attributes.image_style_uri.content_large,
},
alt: partie.relationships.field_diaporama.data[index].meta.alt,
});
}
}
break;
case 'entretien':
partieContent.entretien = {};
partieContent.entretien.titre = partie.attributes.field_titre;
const personnesFetch = await this.fetchFromRelationships('field_personne_s', partie.relationships);
const questionsReponsesFetch = await this.fetchFromRelationships('field_questions_reponses', partie.relationships);
if (personnesFetch && questionsReponsesFetch) {
partieContent.entretien.personnes = [];
for (let personne of personnesFetch) {
const portraitFetch = await this.fetchFromRelationships('field_portrait', personne.relationships);
if (portraitFetch) {
partieContent.entretien.personnes.push({
portrait: {
original: portraitFetch.attributes.uri.url,
small: portraitFetch.attributes.image_style_uri.content_small,
medium: portraitFetch.attributes.image_style_uri.content_medium,
large: portraitFetch.attributes.image_style_uri.content_large,
},
alt: personne.relationships.field_portrait.data.meta.alt,
description: personne.attributes.field_description,
});
}
}
partieContent.entretien.questionsReponses = [];
for (let qr of questionsReponsesFetch) {
partieContent.entretien.questionsReponses.push({
question: qr.attributes.field_question,
reponse: qr.attributes.field_reponse.value,
});
}
}
break;
case 'exergue':
partieContent.exergue = partie.attributes.field_texte_exergue.value;
break;
case 'video':
partieContent.videos = [];
for (let video of partie.attributes.field_videos) {
const videoId = video.split('?v=')[1];
const videoUrl = `https://www.youtube.com/embed/${videoId}`;
partieContent.videos.push(videoUrl);
}
break;
}
this.content.parties.push(partieContent);
}
}
console.log('content cleaned');
} else if (this.contentType !== 'gouvernance' && this.contentType !== 'partenaire'
&& cleanContentMethod === 'promise'
) {
console.time('etape content promise processing');
const vignettePromise = this.fetchFromRelationships('field_vignette', rawContent.relationships);
const partiesPromise = this.fetchFromRelationships('field_parties', rawContent.relationships);
const previousEtapePromise = contentType === 'etape'? this.getRelatedEtape('previous', path) : null;
const nextEtapePromise = contentType === 'etape' ? this.getRelatedEtape('next', path) : null;
if (contentType === 'etape') {
// coordinates
this.content.coordinates = {
lat: rawContent.attributes.field_geofield.lat,
lon: rawContent.attributes.field_geofield.lon,
};
// adresse
this.content.adresse = rawContent.attributes.field_adresse;
// étape number
this.content.etape_number = rawContent.attributes.field_arret_numero;
// couleur
this.content.couleur = rawContent.attributes.field_couleur;
// dates
this.content.dates = {
start: this.getCleanDate(rawContent.attributes.field_dates.value),
end: this.getCleanDate(rawContent.attributes.field_dates.end_value),
}
}
// pageTitle
@ -353,74 +114,29 @@ export const useContentStore = defineStore('content', {
const partieType = partie.type.replace(/^paragraph--/, "");
let partieContent = { type: partieType };
switch(partieType) {
switch (partieType) {
case 'carte_sensible':
const carteSensiblePromise = this.fetchFromRelationships('field_image_carte', partie.relationships);
const carteSensibleData = await carteSensiblePromise;
if (carteSensibleData) {
partieContent.carteSensible = {
url: {
original: carteSensibleData.attributes.uri.url,
small: carteSensibleData.attributes.image_style_uri.content_small,
medium: carteSensibleData.attributes.image_style_uri.content_medium,
large: carteSensibleData.attributes.image_style_uri.content_large,
xlarge: carteSensibleData.attributes.image_style_uri.content_x_large,
},
alt: partie.relationships.field_image_carte.data.meta.alt,
};
}
partieContent.carteSensible = await getCarteSensible(partie);
break;
case 'titre_texte':
partieContent.titre = partie.attributes.field_titre;
partieContent.texte = partie.attributes.field_texte.value;
// get the resized images from the text
const imgRegex = /<img[^>]+>/g;
const uuidRegex = /data-entity-uuid="([^"]+)"/;
const imgTags = partieContent.texte.match(imgRegex);
if (imgTags) {
const imagePromises = imgTags.map(imgTag => {
const uuidMatch = imgTag.match(uuidRegex);
if (uuidMatch && uuidMatch[1]) {
return REST.get(`/jsonapi/file/file/${uuidMatch[1]}`)
.then(response => ({
originalTag: imgTag,
imageData: response.data.data
}));
}
});
const images = await Promise.all(imagePromises);
images.forEach(({originalTag, imageData}) => {
const newImgTag = originalTag
.replace(/src="[^"]+"/,`src="${imageData.attributes.image_style_uri.content_medium}"`)
.replace('>',' data-large-src="' + imageData.attributes.image_style_uri.content_large + '">');
partieContent.texte = partieContent.texte.replace(originalTag, newImgTag);
});
}
const { titre, texte } = await getTitreTexte(partie);
partieContent.titre = titre;
partieContent.texte = texte;
break;
case 'chiffres_cles':
const chiffresClesFetch = await this.fetchFromRelationships('field_chiffres_clefs', partie.relationships);
if (chiffresClesFetch) {
partieContent.chiffresCles = [];
for (let chiffre of chiffresClesFetch) {
partieContent.chiffresCles.push({
chiffre: chiffre.attributes.field_chiffre,
description: chiffre.attributes.field_description,
});
}
}
partieContent.chiffresCles = await getChiffresCles(partie);
break;
case 'diaporama':
partieContent.diaporama = await getDiaporama(partie);
break;
case 'entretien':
partieContent.entretien = await getEntretien(partie);
break;
case 'exergue':
partieContent.exergue = partie.attributes.field_texte_exergue.value;
break;
case 'video':
partieContent.videos = getVideos(partie);
break;
}
return partieContent;
@ -430,72 +146,32 @@ export const useContentStore = defineStore('content', {
}
// related étapes
if (contentType === 'etape') await Promise.all([previousEtapePromise, nextEtapePromise]);
console.log(this.content);
console.timeEnd('etape content promise processing');
if (contentType === 'etape') {
const [prevContent, nextContent] = await Promise.all([previousEtapePromise, nextEtapePromise]);
this.content.previous = prevContent;
this.content.next = nextContent;
}
} else {
// pages gouvernance (contact) et partenaire
// ont plusieurs items par pages
const intro = await REST.get(`/jsonapi/config_pages/intro_${this.contentType}/`);
const introContent = intro.data.data[0];
this.pageTitle =
this.pageTitle =
`${introContent.attributes.field_titre} ${introContent.attributes.metatag.find(tag => tag.tag === "meta")?.attributes.content}`;
this.content.contentTitle = introContent.attributes.field_titre;
this.content.intro = introContent.attributes.field_intro?.value;
const multiItemPageArray = [];
let multiItemPageArray = [];
if (this.contentType === 'partenaire') {
for (let item of rawContent) {
const logoFetch = await REST.get(item.relationships.field_logo.links.related.href);
multiItemPageArray.push({
title: item.attributes.title,
description: item.attributes.body.value,
weight: item.attributes.field_poid,
link_url: item.attributes.field_lien.uri ,
logo_alt: item.relationships.field_logo.data.meta.alt,
logo_url: {
original: logoFetch.data.data.attributes.uri.url,
small: logoFetch.data.data.attributes.image_style_uri.content_small,
medium: logoFetch.data.data.attributes.image_style_uri.content_medium,
large: logoFetch.data.data.attributes.image_style_uri.content_large,
},
});
}
multiItemPageArray = await getPartenaires(rawContent);
} else if (this.contentType === 'gouvernance') {
for (let item of rawContent) {
const personnesFetch = await REST.get(item.relationships.field_personne_s.links.related.href);
let personnes = [];
for (let personne of personnesFetch.data.data) {
const portraitFetch = await REST.get(personne.relationships.field_portrait.links.related.href);
personnes.push({
nom: personne.attributes.field_nom,
prenom: personne.attributes.field_prenom,
description: personne.attributes.field_description,
photo_meta: personne.relationships.field_portrait.data?.meta.alt,
photo_url: portraitFetch.data.data ? {
original: portraitFetch.data.data.attributes.uri.url,
small: portraitFetch.data.data.attributes.image_style_uri.content_small,
medium: portraitFetch.data.data.attributes.image_style_uri.content_medium,
large: portraitFetch.data.data.attributes.image_style_uri.content_large,
} : null
});
}
multiItemPageArray.push({
title: item.attributes.title,
weight: item.attributes.field_poid,
personnes: personnes,
});
}
multiItemPageArray = await getGouvernance(rawContent);
}
this.content[`${this.contentType}s`] = multiItemPageArray;
// console.log(this.content);
}
} catch (error) {
this.error = 'Failed to fetch data';
@ -504,107 +180,6 @@ export const useContentStore = defineStore('content', {
this.loading = false;
}
},
getCleanDate(date) {
return {
d: date.split('-')[2],
m: new Intl.DateTimeFormat('fr-FR', { month: 'long' }).format(new Date(date)),
y: date.split('-')[0],
}
},
async getRelatedEtape(direction, path) {
const getRelatedEtapeContent = async (relatedEtapeData) => {
if (relatedEtapeData) {
const vignetteFetch = await REST.get(relatedEtapeData.relationships.field_vignette.links.related.href);
if (vignetteFetch.data.data) {
this.content[direction] = {
url: relatedEtapeData.attributes.metatag.find(tag => tag.tag === "link")?.attributes.href,
couleur: relatedEtapeData.attributes.field_couleur,
title: relatedEtapeData.attributes.title,
postalCode: relatedEtapeData.attributes.field_adresse.postal_code,
dates: {
start: this.getCleanDate(relatedEtapeData.attributes.field_dates.value),
end: this.getCleanDate(relatedEtapeData.attributes.field_dates.end_value),
},
vignette: {
url: {
original: vignetteFetch.data.data.attributes.uri.url,
small: vignetteFetch.data.data.attributes.image_style_uri.content_small,
medium: vignetteFetch.data.data.attributes.image_style_uri.content_medium,
large: vignetteFetch.data.data.attributes.image_style_uri.content_large,
},
alt: relatedEtapeData.relationships.field_vignette.data.meta.alt,
},
}
}
}
}
const allEtapesData = await REST.get('/jsonapi/views/etapes/block_1/');
for (let [index, etape] of allEtapesData.data.data.entries()) {
if (etape.attributes.metatag.some(tag =>
tag.tag === "link" && tag.attributes.href === path
)) {
const relatedEtapeIndex = direction === 'next' ? index + 1 : index - 1;
await getRelatedEtapeContent(allEtapesData.data.data[relatedEtapeIndex]);
}
}
},
async getRelatedEtape(direction, path) {
const getRelatedEtapeContent = (relatedEtapeData) => {
if (relatedEtapeData) {
return this.fetchFromRelationships('field_vignette', relatedEtapeData.relationships)
.then(vignetteFetch => {
if (vignetteFetch) {
this.content[direction] = {
url: relatedEtapeData.attributes.metatag.find(tag => tag.tag === "link")?.attributes.href,
couleur: relatedEtapeData.attributes.field_couleur,
title: relatedEtapeData.attributes.title,
postalCode: relatedEtapeData.attributes.field_adresse.postal_code,
dates: {
start: this.getCleanDate(relatedEtapeData.attributes.field_dates.value),
end: this.getCleanDate(relatedEtapeData.attributes.field_dates.end_value),
},
vignette: {
url: {
original: vignetteFetch.attributes.uri.url,
small: vignetteFetch.attributes.image_style_uri.content_small,
medium: vignetteFetch.attributes.image_style_uri.content_medium,
large: vignetteFetch.attributes.image_style_uri.content_large,
},
alt: relatedEtapeData.relationships.field_vignette.data.meta.alt,
},
}
}
});
}
}
const allEtapesPromise = REST.get('/jsonapi/views/etapes/block_1/');
return allEtapesPromise.then(allEtapesData => {
for (let [index, etape] of allEtapesData.data.data.entries()) {
if (etape.attributes.metatag.some(tag =>
tag.tag === "link" && tag.attributes.href === path
)) {
const relatedEtapeIndex = direction === 'next' ? index + 1 : index - 1;
return getRelatedEtapeContent(allEtapesData.data.data[relatedEtapeIndex]);
}
}
});
},
async fetchFromRelationships(field, relationships) {
if (relationships[field].links) {
const contentLink = relationships[field].links.related.href;
return REST.get(contentLink)
.then(contentFetch => contentFetch.data.data)
.catch(error => {
this.error = 'Failed to fetch data';
console.error('Issue with getNodeData', error);
});
}
return null;
},
resetStore(forFrontDisplay) {
this.contentType = '';
this.pageTitle = '';

View File

@ -0,0 +1,134 @@
import REST from '../../api/rest-axios';
import { fetchFromRelationships } from './contentFetchUtils';
export async function getCarteSensible(partie) {
const carteSensiblePromise = fetchFromRelationships('field_image_carte', partie.relationships);
const carteSensibleData = await carteSensiblePromise;
if (carteSensibleData) {
return {
url: {
original: carteSensibleData.attributes.uri.url,
small: carteSensibleData.attributes.image_style_uri.content_small,
medium: carteSensibleData.attributes.image_style_uri.content_medium,
large: carteSensibleData.attributes.image_style_uri.content_large,
xlarge: carteSensibleData.attributes.image_style_uri.content_x_large,
},
alt: partie.relationships.field_image_carte.data.meta.alt,
};
}
}
export async function getTitreTexte(partie) {
let titre = partie.attributes.field_titre;
let texte = partie.attributes.field_texte.value;
// get the resized images from the text
const imgRegex = /<img[^>]+>/g;
const uuidRegex = /data-entity-uuid="([^"]+)"/;
const imgTags = texte.match(imgRegex);
if (imgTags) {
const imagePromises = imgTags.map(imgTag => {
const uuidMatch = imgTag.match(uuidRegex);
if (uuidMatch && uuidMatch[1]) {
return REST.get(`/jsonapi/file/file/${uuidMatch[1]}`)
.then(response => ({
originalTag: imgTag,
imageData: response.data.data
}));
}
});
const images = await Promise.all(imagePromises);
images.forEach(({originalTag, imageData}) => {
const newImgTag = originalTag
.replace(/src="[^"]+"/,`src="${imageData.attributes.image_style_uri.content_medium}"`)
.replace('>',' data-large-src="' + imageData.attributes.image_style_uri.content_large + '">');
texte = texte.replace(originalTag, newImgTag);
});
}
return { titre, texte };
}
export async function getChiffresCles(partie) {
const chiffresClesFetch = await fetchFromRelationships('field_chiffres_clefs', partie.relationships);
if (chiffresClesFetch) {
let chiffresCles = [];
for (let chiffre of chiffresClesFetch) {
chiffresCles.push({
chiffre: chiffre.attributes.field_chiffre,
description: chiffre.attributes.field_description,
});
}
return chiffresCles;
}
}
export async function getDiaporama(partie) {
const diaporamaFetch = await fetchFromRelationships('field_diaporama', partie.relationships);
if (diaporamaFetch) {
const diaporamaPromises = diaporamaFetch.map((image, index) => {
return {
url: {
original: image.attributes.uri.url,
small: image.attributes.image_style_uri.content_small,
medium: image.attributes.image_style_uri.content_medium,
large: image.attributes.image_style_uri.content_large,
},
alt: partie.relationships.field_diaporama.data[index].meta.alt,
};
});
return await Promise.all(diaporamaPromises);
}
}
export async function getEntretien(partie) {
const [personnesFetch, questionsReponsesFetch] = await Promise.all([
fetchFromRelationships('field_personne_s', partie.relationships),
fetchFromRelationships('field_questions_reponses', partie.relationships)
]);
if (personnesFetch && questionsReponsesFetch) {
const personnesPromises = personnesFetch.map(async (personne) => {
const portraitFetch = await fetchFromRelationships('field_portrait', personne.relationships);
if (portraitFetch) {
return {
portrait: {
original: portraitFetch.attributes.uri.url,
small: portraitFetch.attributes.image_style_uri.content_small,
medium: portraitFetch.attributes.image_style_uri.content_medium,
large: portraitFetch.attributes.image_style_uri.content_large,
},
alt: personne.relationships.field_portrait.data.meta.alt,
description: personne.attributes.field_description,
};
}
});
const questionsReponses = questionsReponsesFetch.map(qr => ({
question: qr.attributes.field_question,
reponse: qr.attributes.field_reponse.value,
}));
return {
titre: partie.attributes.field_titre,
personnes: await Promise.all(personnesPromises),
questionsReponses: questionsReponses
}
}
}
export function getVideos(partie) {
let videos = [];
for (let video of partie.attributes.field_videos) {
const videoId = video.split('?v=')[1];
const videoUrl = `https://www.youtube.com/embed/${videoId}`;
videos.push(videoUrl);
}
return videos;
}

View File

@ -0,0 +1,68 @@
import REST from '../../api/rest-axios';
export async function fetchFromRelationships(field, relationships) {
field = relationships[field] ? field : `${field}_static`;
if (relationships[field].links) {
const contentLink = relationships[field].links.related.href;
return REST.get(contentLink)
.then(contentFetch => contentFetch.data.data)
.catch(error => {
this.error = 'Failed to fetch data';
console.error('Issue with getNodeData', error);
});
}
return null;
}
export function getCleanDate(date) {
return {
d: date.split('-')[2],
m: new Intl.DateTimeFormat('fr-FR', { month: 'long' }).format(new Date(date)),
y: date.split('-')[0],
}
}
export async function getRelatedEtape(direction, path) {
const getRelatedEtapeContent = (relatedEtapeData) => {
if (relatedEtapeData) {
return fetchFromRelationships('field_vignette', relatedEtapeData.relationships)
.then(vignetteFetch => {
if (vignetteFetch) {
return {
url: relatedEtapeData.attributes.metatag.find(tag => tag.tag === "link")?.attributes.href,
couleur: relatedEtapeData.attributes.field_couleur,
title: relatedEtapeData.attributes.title,
postalCode: relatedEtapeData.attributes.field_adresse.postal_code,
dates: {
start: getCleanDate(relatedEtapeData.attributes.field_dates.value),
end: getCleanDate(relatedEtapeData.attributes.field_dates.end_value),
},
vignette: {
url: {
original: vignetteFetch.attributes.uri.url,
small: vignetteFetch.attributes.image_style_uri.content_small,
medium: vignetteFetch.attributes.image_style_uri.content_medium,
large: vignetteFetch.attributes.image_style_uri.content_large,
},
alt: relatedEtapeData.relationships.field_vignette.data.meta.alt,
},
}
}
});
}
}
const allEtapesPromise = REST.get('/jsonapi/views/etapes/block_1/');
return allEtapesPromise.then(allEtapesData => {
for (let [index, etape] of allEtapesData.data.data.entries()) {
if (etape.attributes.metatag.some(tag =>
tag.tag === "link" && tag.attributes.href === path
)) {
const relatedEtapeIndex = direction === 'next' ? index + 1 : index - 1;
return getRelatedEtapeContent(allEtapesData.data.data[relatedEtapeIndex]);
}
}
});
}

View File

@ -0,0 +1,32 @@
import REST from '../../api/rest-axios';
export async function findContentByPath(contentTypes, path) {
for (let type of contentTypes) {
const response = await REST.get(`/jsonapi/node/${type}/`);
const content = response.data.data.find(content =>
content.attributes.metatag.some(tag =>
tag.tag === "link" && tag.attributes.href === path
)
);
if (content) {
return {
contentType: type,
rawContent: content,
};
}
// Handle special case for governance/partners (multiple items per page)
const pageRequested = window.location.href.split('/').pop().replace(/s?$/, '');
if (type === pageRequested
|| (type === 'gouvernance' && pageRequested === 'contact')
) {
return {
contentType: type,
rawContent: response.data.data,
};
}
}
return null;
}

View File

@ -0,0 +1,54 @@
import REST from '../../api/rest-axios';
export async function getPartenaires(rawContent) {
const logoPromises = rawContent.map(item =>
REST.get(item.relationships.field_logo.links.related.href)
.then(logoFetch => ({
title: item.attributes.title,
description: item.attributes.body.value,
weight: item.attributes.field_poid,
link_url: item.attributes.field_lien.uri,
logo_alt: item.relationships.field_logo.data.meta.alt,
logo_url: {
original: logoFetch.data.data.attributes.uri.url,
small: logoFetch.data.data.attributes.image_style_uri.content_small,
medium: logoFetch.data.data.attributes.image_style_uri.content_medium,
large: logoFetch.data.data.attributes.image_style_uri.content_large,
}
}))
);
return await Promise.all(logoPromises);
}
export async function getGouvernance(rawContent) {
const itemPromises = rawContent.map(item =>
REST.get(item.relationships.field_personne_s.links.related.href)
.then(async personnesFetch => {
const portraitPromises = personnesFetch.data.data.map(personne =>
REST.get(personne.relationships.field_portrait.links.related.href)
.then(portraitFetch => ({
nom: personne.attributes.field_nom,
prenom: personne.attributes.field_prenom,
description: personne.attributes.field_description,
photo_meta: personne.relationships.field_portrait.data?.meta.alt,
photo_url: portraitFetch.data.data ? {
original: portraitFetch.data.data.attributes.uri.url,
small: portraitFetch.data.data.attributes.image_style_uri.content_small,
medium: portraitFetch.data.data.attributes.image_style_uri.content_medium,
large: portraitFetch.data.data.attributes.image_style_uri.content_large,
} : null
}))
);
return Promise.all(portraitPromises)
.then(personnes => ({
title: item.attributes.title,
weight: item.attributes.field_poid,
personnes
}));
})
);
return await Promise.all(itemPromises);
}

View File

@ -22,7 +22,7 @@ export function handleClickableElements(clickableElements, store, router, baseUr
let href = link.href || link.dataset.href;
if (href.startsWith(baseUrl)) href = href.replace(baseUrl, '');
link.onclick = async function (e) {
link.onclick = async function (e) {
if (href !== window.location.pathname) {
router.push(href);
pageChange(href, store, siteName, mapStore, baseUrl);

View File

@ -5,7 +5,7 @@
</div>
<div v-if="contentType === 'etape' && (content.previous || content.next)" class="related-etape-links">
<div v-if="content.previous" class="card previous" @click="goToRelatedElement(content.previous.url)">
<div v-if="content.previous" class="card previous" :data-href="content.previous.url">
<div class="icon" :style="{ backgroundColor: content.previous.couleur }"></div>
<div class="card-content">
<div class="infos">
@ -17,7 +17,7 @@
</div>
</div>
</div>
<div v-if="content.next" class="card next" @click="goToRelatedElement(content.next.url)">
<div v-if="content.next" class="card next" :data-href="content.next.url">
<div class="icon" :style="{ backgroundColor: content.next.couleur }"></div>
<div class="card-content">
<div class="infos">
@ -34,13 +34,18 @@
</template>
<script setup>
import { onMounted } from 'vue';
import router from '../../router/router';
import { useContentStore } from '../../stores/content';
import { pageChange } from '../../utils/handle-navigation.js';
import { useMapStore } from '../../stores/map';
import { handleClickableElements } from '../../utils/handle-navigation.js';
const brandColor = "#80c8bf";
const store = useContentStore();
const mapStore = useContentStore();
const mapStore = useMapStore();
const siteName = document.querySelector('#site_name').innerText;
@ -51,10 +56,9 @@ const props = defineProps({
map: Object,
});
async function goToRelatedElement(href) {
const baseUrl = window.location.protocol + "//" + window.location.host;
if (href.startsWith(baseUrl)) href = href.replace(baseUrl, '');
pageChange(href, store, siteName, mapStore, baseUrl)
}
onMounted(() => {
const relatedEtapesCards = document.querySelectorAll('.card');
const baseUrl = window.location.protocol + "//" + window.location.host;
handleClickableElements(relatedEtapesCards, store, router, baseUrl, siteName, mapStore);
});
</script>

View File

@ -18,4 +18,4 @@ regions:
content: 'Content'
sidebar_first: 'Sidebar first'
sidebar_second: 'Sidebar second'
footer: 'Footer'
footer: 'Footer'