From f44fbd8d06de565af625c55908afdd45c261a37d Mon Sep 17 00:00:00 2001 From: Valentin Le Moign Date: Thu, 26 Jun 2025 15:26:18 +0200 Subject: [PATCH] rerefactor du fetching de contenus une mielleure ux au load des modales (description dans le readme) --- web/README.md | 5 + web/themes/custom/caravane/assets/js/main.js | 18 +- .../caravane/assets/js/stores/content.js | 208 ++++-------------- .../caravane/assets/js/stores/layout.js | 10 +- .../custom/caravane/assets/js/stores/map.js | 33 +++ .../js/utils/content/contentFetchUtils.js | 2 +- .../assets/js/utils/content/fetchMultiple.js | 43 ++++ .../assets/js/utils/content/fetchSingleton.js | 153 +++++++++++++ .../assets/js/utils/content/multiItemPages.js | 2 +- .../assets/js/utils/handle-navigation.js | 31 ++- .../caravane/assets/js/utils/layout-setup.js | 10 +- .../caravane/assets/js/utils/map-setup.js | 9 +- .../assets/js/utils/set-active-nav-item.js | 15 +- .../caravane/assets/js/utils/vue-setup.js | 9 +- .../caravane/assets/js/vuejs/Modale.vue | 188 ++++++---------- .../assets/js/vuejs/components/EtapeCard.vue | 7 +- .../js/vuejs/components/ModaleHeader.vue | 5 +- .../js/vuejs/components/RessourceCard.vue | 14 +- .../vuejs/components/RessourceItemHeader.vue | 19 +- .../caravane/assets/pictograms/90-ring.svg | 1 + .../custom/caravane/assets/scss/main.scss | 50 ++++- 21 files changed, 465 insertions(+), 367 deletions(-) create mode 100644 web/themes/custom/caravane/assets/js/utils/content/fetchMultiple.js create mode 100644 web/themes/custom/caravane/assets/js/utils/content/fetchSingleton.js create mode 100644 web/themes/custom/caravane/assets/pictograms/90-ring.svg diff --git a/web/README.md b/web/README.md index c3e5371..9524499 100644 --- a/web/README.md +++ b/web/README.md @@ -1,3 +1,8 @@ +## Routing flow + +![routing flow 1](https://nextcloud.val.kiwi/s/rCJPJgEPrkSNJAC) +![routing flow 2](https://nextcloud.val.kiwi/s/CpebG9MZAaKCwe3) + Drupal Logo Drupal is an open source content management platform supporting a variety of diff --git a/web/themes/custom/caravane/assets/js/main.js b/web/themes/custom/caravane/assets/js/main.js index ef18b6f..f5e92b7 100644 --- a/web/themes/custom/caravane/assets/js/main.js +++ b/web/themes/custom/caravane/assets/js/main.js @@ -1,6 +1,6 @@ import { initVueContentModale } from './utils/vue-setup'; import { processClickableElements } from './utils/process-clickable-elements'; -import { handleReactiveness, setMenuToggle, setHamburgerWhenLogged } from './utils/layout-setup'; +import { handleReactiveness, setMenuToggle, setRightSectionsWhenLogged } from './utils/layout-setup'; import { initFirstLoadRouting, handleClickableElements, handleBrowserNavigation } from './utils/handle-navigation'; import { setupMapStore, preloadEtapesTiles } from './utils/map-setup'; @@ -13,16 +13,15 @@ import '../scss/main.scss' (function ($, Drupal, drupalSettings) { const CaravaneTheme = function () { function init () { - console.log('07/04 ci-cd fonctionne, import des configs ?') // console.log('DrupalSettings', drupalSettings); const baseUrl = window.location.protocol + "//" + window.location.host; const siteName = document.querySelector('#site_name').innerText; - const { store, mapStore, router, route } = initVueContentModale(); + const router = initVueContentModale(); handleReactiveness(); setMenuToggle(); - setHamburgerWhenLogged(drupalSettings); + setRightSectionsWhenLogged(drupalSettings); // https://www.drupal.org/docs/extending-drupal/contributed-modules/contributed-module-documentation/leaflet/leaflet-api @@ -44,22 +43,21 @@ import '../scss/main.scss' } = processClickableElements(); const clickableElements = [...etapeListLinks, ...generalListLinks, logoLink, ...mapIcons, mapContainer]; - setupMapStore(mapStore, map, settings); + setupMapStore(map, settings); - // preloadEtapesTiles(mapStore, map); + // preloadEtapesTiles(map); - initFirstLoadRouting(store, router, baseUrl, siteName); + initFirstLoadRouting(router, baseUrl, siteName); - handleClickableElements(clickableElements, store, router, baseUrl, siteName, mapStore); + handleClickableElements(clickableElements, router, baseUrl, siteName); window.addEventListener("popstate", () => { - handleBrowserNavigation(store, baseUrl, siteName, mapStore); + handleBrowserNavigation(baseUrl, siteName); }); }); } } } - init() } CaravaneTheme() diff --git a/web/themes/custom/caravane/assets/js/stores/content.js b/web/themes/custom/caravane/assets/js/stores/content.js index 14fec4e..47686f9 100644 --- a/web/themes/custom/caravane/assets/js/stores/content.js +++ b/web/themes/custom/caravane/assets/js/stores/content.js @@ -1,201 +1,68 @@ // query et traitement des contenus import { defineStore } from 'pinia'; -import REST from '../api/rest-axios'; import { useLayoutStore } from './layout'; - import { findContentByPath } from '../utils/content/findContentByPath'; -import { getCleanDate, fetchFromRelationships, getRelatedEtape, getRelatedRessources } from '../utils/content/contentFetchUtils'; -import { getCarteSensible, getTitreTexte, getChiffresCles, getDiaporama, getEntretien, getVideos, getDocument, getGallerie } from '../utils/content/cleanParties'; -import { getPartenaires, getGouvernance, getRessources } from '../utils/content/multiItemPages'; +import { fetchSingletonFullContent, fetchSingletonPartialContent } from '../utils/content/fetchSingleton'; +import { fetchMultipleFullContent, fetchMultiplePartialContent } from '../utils/content/fetchMultiple'; export const useContentStore = defineStore('content', { state: () => ({ contentType: '', + rawContent: {}, pageTitle: '', content: {}, + partialLoading: false, loading: false, error: null, }), actions: { - async fetchContentData(path) { + // pages etape, statiques et ressource ont un seul item par page (singuliers) + // pages gouvernance (contact), ressources et partenaire ont plusieurs items par pages (multiples) + async fetchPartialContentData(path) { this.resetStore(false); const contentTypes = ['etape', 'static', 'gouvernance', 'partenaire', 'ressource']; + try { const { contentType, rawContent } = await findContentByPath(contentTypes, path); this.contentType = contentType; + this.rawContent = rawContent; if ( this.contentType === 'etape' || this.contentType === 'static' || this.contentType === 'ressourceItem' - ) { - const vignettePromise = fetchFromRelationships('field_vignette', rawContent.relationships); - const partiesPromise = fetchFromRelationships(this.contentType === 'ressourceItem' ? 'field_parties_ressource' : 'field_parties', rawContent.relationships); - - let previousEtapePromise, nextEtapePromise; - - - if (this.contentType === 'etape') { - previousEtapePromise = getRelatedEtape('previous', path); - nextEtapePromise = getRelatedEtape('next', path); - - this.content.coordinates = { - lat: rawContent.attributes.field_geofield.lat, - lon: rawContent.attributes.field_geofield.lon, - }; - this.content.adresse = rawContent.attributes.field_adresse; - this.content.etape_number = rawContent.attributes.field_arret_numero; - this.content.couleur = rawContent.attributes.field_couleur; - this.content.dates = { - start: getCleanDate(rawContent.attributes.field_dates.value), - end: getCleanDate(rawContent.attributes.field_dates.end_value), - } - this.content.relatedRessources = await getRelatedRessources(rawContent.id); - } - - if (this.contentType === 'ressourceItem') { - console.log(rawContent); - - this.content.ressourceType = rawContent.attributes.field_type_de_ressource; - this.content.auteurice = rawContent.attributes.field_autheurice; - this.content.date = getCleanDate(rawContent.attributes.field_date_ressource); - this.content.introduction = rawContent.attributes.field_introduction?.processed; - if (rawContent.relationships.field_etape.data) { - const relatedEtapeFetch = fetchFromRelationships('field_etape', rawContent.relationships); - const relatedEtape = await Promise.resolve(relatedEtapeFetch); - const relatedEtapeUrl = relatedEtape.attributes.metatag.find(tag => tag.tag === "link")?.attributes.href; - this.content.relatedEtape = await getRelatedEtape('', relatedEtapeUrl); - } - - useLayoutStore().hideEtapeList(true); - } - - this.pageTitle = rawContent.attributes.metatag.find(tag => tag.tag === "meta")?.attributes.content; - this.content.contentTitle = rawContent.attributes.title; - - const [vignetteData, partiesData] = await Promise.all([vignettePromise, partiesPromise]); - - if (vignetteData) { - this.content.vignette = { - url: { - original: vignetteData.attributes.uri.url, - small: vignetteData.attributes.image_style_uri.content_small, - medium: vignetteData.attributes.image_style_uri.content_medium, - large: vignetteData.attributes.image_style_uri.content_large, - }, - alt: rawContent.relationships.field_vignette.data.meta.alt - }; - } - - if (partiesData) { - const partiesPromises = partiesData.map(async (partie) => { - const partieType = partie.type.replace(/^paragraph--/, ""); - let partieContent = { type: partieType }; - - switch (partieType) { - case 'carte_sensible': - partieContent.carteSensible = await getCarteSensible(partie); - break; - case 'titre_texte': - const { titre, texte } = await getTitreTexte(partie); - partieContent.titre = titre; - partieContent.texte = texte; - break; - case 'chiffres_cles': - 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; - case 'document': - partieContent.document = await getDocument(partie); - break; - case 'galleries': - partieContent.gallerie = await getGallerie(partie); - break; - } - return partieContent; - }); - - // 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, - }); - } - } - } - - this.content.parties = await Promise.all(partiesPromises); - } - - // related étapes - if (contentType === 'etape') { - const [prevContent, nextContent] = await Promise.all([previousEtapePromise, nextEtapePromise]); - this.content.previous = prevContent; - this.content.next = nextContent; - } + ) { + let { pageTitle, partialContent } = fetchSingletonPartialContent(this.contentType, this.rawContent); + this.pageTitle = pageTitle; + this.content = partialContent; } else { - // pages gouvernance (contact), ressources 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 = - `${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; - - let multiItemPageArray = []; - - switch (this.contentType) { - case 'ressource': - multiItemPageArray = await getRessources(rawContent); - this.content.ressourceTypes = new Set(multiItemPageArray.map(item => item.ressourceType)); - useLayoutStore().hideEtapeList(true); - break; - case 'partenaire': - multiItemPageArray = await getPartenaires(rawContent); - break; - case 'gouvernance': - multiItemPageArray = await getGouvernance(rawContent); - break; - } - - this.content[`${this.contentType}s`] = multiItemPageArray; - + let { pageTitle, partialContent } = await fetchMultiplePartialContent(this.contentType); + this.pageTitle = pageTitle; + this.content = partialContent; } - } catch (error) { - this.error = 'Failed to fetch data'; - console.error('Issue with getNodeData', error); + } catch(error) { + this.error = 'Failed to fetch partial data'; + console.error('Issue with fetchPartialContentData', error); + } finally { + this.partialLoading = false; + } + }, + async fetchFullContentData(path) { + try { + if ( + this.contentType === 'etape' + || this.contentType === 'static' + || this.contentType === 'ressourceItem' + ) { + this.content = { ...this.content, ...await fetchSingletonFullContent(this.contentType, this.rawContent, path) }; + } else { + this.content = { ...this.content, ...await fetchMultipleFullContent(this.contentType, this.rawContent) }; + } + } catch(error) { + this.error = 'Failed to fetch full data'; + console.error('Issue with fetchFullContentData', error); } finally { this.loading = false; } @@ -204,6 +71,7 @@ export const useContentStore = defineStore('content', { this.contentType = ''; this.pageTitle = ''; this.content = {}; + this.partialLoading = !forFrontDisplay; this.loading = !forFrontDisplay; this.error = null; useLayoutStore().hideEtapeList(false); diff --git a/web/themes/custom/caravane/assets/js/stores/layout.js b/web/themes/custom/caravane/assets/js/stores/layout.js index 823985d..d2505f2 100644 --- a/web/themes/custom/caravane/assets/js/stores/layout.js +++ b/web/themes/custom/caravane/assets/js/stores/layout.js @@ -128,6 +128,14 @@ export const useLayoutStore = defineStore('layout', { setHeaderPosition(currentPageIsIndex) { const header = document.querySelector('.layout-container > header'); header.style.position = currentPageIsIndex ? 'fixed' : 'relative'; - } + }, + toggleModaleTransition(shouldModaleTransition, enterDelay) { + if (shouldModaleTransition) { + document.documentElement.style.setProperty('--modale-enter-delay', `${enterDelay}s`); + } else { + document.documentElement.style.setProperty('margin-top', '0'); + document.documentElement.style.setProperty('transition', 'none'); + } + }, }, }) diff --git a/web/themes/custom/caravane/assets/js/stores/map.js b/web/themes/custom/caravane/assets/js/stores/map.js index a53bf8f..709b9f6 100644 --- a/web/themes/custom/caravane/assets/js/stores/map.js +++ b/web/themes/custom/caravane/assets/js/stores/map.js @@ -16,6 +16,39 @@ export const useMapStore = defineStore('mapState', { animationDuration: 3, }), actions: { + handleMapMovement(isModaleEtape, wasModaleEtape, lat = this.defaultMapCenter.lat, lon = this.defaultMapCenter.lng) { + if (this.animationsAreEnabled) { + if (isModaleEtape) { + if (!wasModaleEtape) { + // national -> détail + useLayoutStore().toggleModaleTransition(true, this.animationDuration); + this.zoomToPlace(lat, lon); + } else { + // détail -> détail + useLayoutStore().toggleModaleTransition(true, this.animationDuration); + this.zoomToPlace(lat, lon); + } + } else { + if (wasModaleEtape) { + // détail -> national + useLayoutStore().toggleModaleTransition(true, this.animationDuration); + this.resetMap(); + } else { + // national -> national + useLayoutStore().toggleModaleTransition(true, 0); + } + } + } else { + if (isModaleEtape) { + // ? -> détail + this.zoomToPlace(lat, lon); + } else { + // ? -> national + this.resetMap(); + } + useLayoutStore().toggleModaleTransition(false); + } + }, zoomToPlace(lat, long) { if (useLayoutStore().isDesktop) long = long - 0.03; this.map.flyTo( diff --git a/web/themes/custom/caravane/assets/js/utils/content/contentFetchUtils.js b/web/themes/custom/caravane/assets/js/utils/content/contentFetchUtils.js index 9ab0a1c..75e9c99 100644 --- a/web/themes/custom/caravane/assets/js/utils/content/contentFetchUtils.js +++ b/web/themes/custom/caravane/assets/js/utils/content/contentFetchUtils.js @@ -122,7 +122,7 @@ export async function getRessourceItemCard(item) { } const relatedEtape = await REST.get(item.relationships.field_etape.links.related.href); - console.log(item); + // console.log(item); return { diff --git a/web/themes/custom/caravane/assets/js/utils/content/fetchMultiple.js b/web/themes/custom/caravane/assets/js/utils/content/fetchMultiple.js new file mode 100644 index 0000000..5454001 --- /dev/null +++ b/web/themes/custom/caravane/assets/js/utils/content/fetchMultiple.js @@ -0,0 +1,43 @@ +import REST from '../../api/rest-axios'; +import { useLayoutStore } from '../../stores/layout'; +import { getPartenaires, getGouvernance, getRessources } from './multiItemPages'; + +export async function fetchMultiplePartialContent(contentType) { + let partialContent = {}; + let pageTitle = ''; + + const intro = await REST.get(`/jsonapi/config_pages/intro_${contentType}/`); + const introContent = intro.data.data[0]; + + pageTitle = + `${introContent.attributes.field_titre} ${introContent.attributes.metatag.find(tag => tag.tag === "meta")?.attributes.content}`; + + partialContent.contentTitle = introContent.attributes.field_titre; + partialContent.intro = introContent.attributes.field_intro?.value; + + return { pageTitle, partialContent }; +} + +export async function fetchMultipleFullContent(contentType, rawContent) { + let content = {}; + + let multiItemPageArray = []; + + switch (contentType) { + case 'ressource': + multiItemPageArray = await getRessources(rawContent); + content.ressourceTypes = new Set(multiItemPageArray.map(item => item.ressourceType)); + useLayoutStore().hideEtapeList(true); + break; + case 'partenaire': + multiItemPageArray = await getPartenaires(rawContent); + break; + case 'gouvernance': + multiItemPageArray = await getGouvernance(rawContent); + break; + } + + content[`${contentType}s`] = multiItemPageArray; + + return content; +} \ No newline at end of file diff --git a/web/themes/custom/caravane/assets/js/utils/content/fetchSingleton.js b/web/themes/custom/caravane/assets/js/utils/content/fetchSingleton.js new file mode 100644 index 0000000..a4425fb --- /dev/null +++ b/web/themes/custom/caravane/assets/js/utils/content/fetchSingleton.js @@ -0,0 +1,153 @@ +import REST from '../../api/rest-axios'; + +import { getCleanDate, fetchFromRelationships, getRelatedEtape, getRelatedRessources } from './contentFetchUtils'; +import { getCarteSensible, getTitreTexte, getChiffresCles, getDiaporama, getEntretien, getVideos, getDocument, getGallerie } from './cleanParties'; +import { useLayoutStore } from '../../stores/layout'; + +export function fetchSingletonPartialContent(contentType, rawContent) { + let partialContent = {}; + + let pageTitle = rawContent.attributes.metatag.find(tag => tag.tag === "meta")?.attributes.content; + + partialContent.contentTitle = rawContent.attributes.title; + + if (contentType === 'etape') { + partialContent.coordinates = { + lat: rawContent.attributes.field_geofield.lat, + lon: rawContent.attributes.field_geofield.lon, + }; + partialContent.adresse = rawContent.attributes.field_adresse; + partialContent.etape_number = rawContent.attributes.field_arret_numero; + partialContent.couleur = rawContent.attributes.field_couleur; + partialContent.dates = { + start: getCleanDate(rawContent.attributes.field_dates.value), + end: getCleanDate(rawContent.attributes.field_dates.end_value), + } + } + + if (contentType === 'ressourceItem') { + partialContent.ressourceType = rawContent.attributes.field_type_de_ressource; + partialContent.auteurice = rawContent.attributes.field_autheurice; + partialContent.date = getCleanDate(rawContent.attributes.field_date_ressource); + } + + return { pageTitle, partialContent }; +} + +export async function fetchSingletonFullContent(contentType, rawContent, path) { + let content = {}; + + const vignettePromise = fetchFromRelationships('field_vignette', rawContent.relationships); + const partiesPromise = fetchFromRelationships(contentType === 'ressourceItem' ? 'field_parties_ressource' : 'field_parties', rawContent.relationships); + + let previousEtapePromise, nextEtapePromise; + + if (contentType === 'etape') { + previousEtapePromise = getRelatedEtape('previous', path); + nextEtapePromise = getRelatedEtape('next', path); + content.relatedRessources = await getRelatedRessources(rawContent.id); + } + + if (contentType === 'ressourceItem') { + content.introduction = rawContent.attributes.field_introduction?.processed; + if (rawContent.relationships.field_etape.data) { + const relatedEtapeFetch = fetchFromRelationships('field_etape', rawContent.relationships); + const relatedEtape = await Promise.resolve(relatedEtapeFetch); + const relatedEtapeUrl = relatedEtape.attributes.metatag.find(tag => tag.tag === "link")?.attributes.href; + content.relatedEtape = await getRelatedEtape('', relatedEtapeUrl); + } + + useLayoutStore().hideEtapeList(true); + } + + const [vignetteData, partiesData] = await Promise.all([vignettePromise, partiesPromise]); + + if (vignetteData) { + content.vignette = { + url: { + original: vignetteData.attributes.uri.url, + small: vignetteData.attributes.image_style_uri.content_small, + medium: vignetteData.attributes.image_style_uri.content_medium, + large: vignetteData.attributes.image_style_uri.content_large, + }, + alt: rawContent.relationships.field_vignette.data.meta.alt + }; + } + + + if (partiesData) { + const partiesPromises = partiesData.map(async (partie) => { + const partieType = partie.type.replace(/^paragraph--/, ""); + let partieContent = { type: partieType }; + + switch (partieType) { + case 'carte_sensible': + partieContent.carteSensible = await getCarteSensible(partie); + break; + case 'titre_texte': + const { titre, texte } = await getTitreTexte(partie); + partieContent.titre = titre; + partieContent.texte = texte; + break; + case 'chiffres_cles': + 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; + case 'document': + partieContent.document = await getDocument(partie); + break; + case 'galleries': + partieContent.gallerie = await getGallerie(partie); + break; + } + return partieContent; + }); + + // liens + if (rawContent.attributes.field_liens?.length) { + content.liens = []; + for (let lien of rawContent.attributes.field_liens) { + content.liens.push({ + title: lien.title, + url: lien.uri, + }); + } + } + // pièces jointes + if (rawContent.relationships.field_pieces_jointes?.data.length) { + 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}`); + content.pieces_jointes.push({ + title: pieceJointe.meta.description, + url: response.data.data.attributes.uri.url, + }); + } + } + } + + content.parties = await Promise.all(partiesPromises); + } + + // related étapes + if (contentType === 'etape') { + const [prevContent, nextContent] = await Promise.all([previousEtapePromise, nextEtapePromise]); + content.previous = prevContent; + content.next = nextContent; + } + + return content; +} \ No newline at end of file diff --git a/web/themes/custom/caravane/assets/js/utils/content/multiItemPages.js b/web/themes/custom/caravane/assets/js/utils/content/multiItemPages.js index 9b960e4..0ab300c 100644 --- a/web/themes/custom/caravane/assets/js/utils/content/multiItemPages.js +++ b/web/themes/custom/caravane/assets/js/utils/content/multiItemPages.js @@ -55,7 +55,7 @@ export async function getGouvernance(rawContent) { } export async function getRessources(rawContent) { - console.log(rawContent); + // console.log(rawContent); const ressourcesPromises = rawContent.map(item => getRessourceItemCard(item)); diff --git a/web/themes/custom/caravane/assets/js/utils/handle-navigation.js b/web/themes/custom/caravane/assets/js/utils/handle-navigation.js index a0a845c..0939f7c 100644 --- a/web/themes/custom/caravane/assets/js/utils/handle-navigation.js +++ b/web/themes/custom/caravane/assets/js/utils/handle-navigation.js @@ -1,23 +1,27 @@ import { setActiveNavItem } from "./set-active-nav-item"; +import { useContentStore } from "../stores/content"; +import { useMapStore } from "../stores/map"; import { useLayoutStore } from '../stores/layout'; -export async function initFirstLoadRouting(store, router, baseUrl, siteName) { +export async function initFirstLoadRouting(router, baseUrl, siteName) { + const store = useContentStore(); const decoupled_origin = JSON.parse(window.localStorage.getItem('decoupled_origin')); if(decoupled_origin) { router.push(decoupled_origin.url); - await store.fetchContentData(baseUrl + decoupled_origin.url); + await store.fetchPartialContentData(baseUrl + decoupled_origin.url); window.localStorage.removeItem("decoupled_origin"); document.title = store.pageTitle; setActiveNavItem(store.contentType, decoupled_origin.url); useLayoutStore().setHeaderPosition(false); + await store.fetchFullContentData(baseUrl + decoupled_origin.url); } else { document.title = siteName; useLayoutStore().setHeaderPosition(true); } } -export function handleClickableElements(clickableElements, store, router, baseUrl, siteName, mapStore) { +export function handleClickableElements(clickableElements, router, baseUrl, siteName) { for (const link of clickableElements) { let href = link.href || link.dataset.href; if (href.startsWith(baseUrl)) href = href.replace(baseUrl, ''); @@ -25,26 +29,29 @@ export function handleClickableElements(clickableElements, store, router, baseUr link.onclick = async function (e) { if (href !== window.location.pathname) { router.push(href); - pageChange(href, store, siteName, mapStore, baseUrl); + pageChange(href, siteName, baseUrl); } } } } -export async function handleBrowserNavigation(store, baseUrl, siteName, mapStore) { - let href = window.location.pathname; - if (href.startsWith(baseUrl)) href = href.replace(baseUrl, ''); - pageChange(href, store, siteName, mapStore, baseUrl) +export async function handleBrowserNavigation(baseUrl, siteName) { + let href = window.location.pathname; + if (href.startsWith(baseUrl)) href = href.replace(baseUrl, ''); + pageChange(href, siteName, baseUrl) } -export async function pageChange(href, store, siteName, mapStore, baseUrl) { +export async function pageChange(href, siteName, baseUrl) { + const store = useContentStore(); + const mapStore = useMapStore(); + if (href === '/') { store.resetStore(true); document.title = siteName; mapStore.resetMap(); useLayoutStore().setHeaderPosition(true); } else { - await store.fetchContentData(baseUrl + href); + await store.fetchPartialContentData(baseUrl + href); document.title = store.pageTitle; useLayoutStore().setHeaderPosition(false); } @@ -53,4 +60,8 @@ export async function pageChange(href, store, siteName, mapStore, baseUrl) { const listeEtape = document.querySelector('#etapes-liste'); const animationToggle = document.querySelector('#animation-toggle'); if (!useLayoutStore().isDesktop) useLayoutStore().collapseEtapeListe(listeEtape, animationToggle); + + if (href !== '/') { + await store.fetchFullContentData(baseUrl + href); + } } diff --git a/web/themes/custom/caravane/assets/js/utils/layout-setup.js b/web/themes/custom/caravane/assets/js/utils/layout-setup.js index ae052c5..f4a5777 100644 --- a/web/themes/custom/caravane/assets/js/utils/layout-setup.js +++ b/web/themes/custom/caravane/assets/js/utils/layout-setup.js @@ -56,7 +56,7 @@ export function setMenuToggle() { layoutStore.setUpHamburgerToggle(menuBurger, menuContainer); } -export function setHamburgerWhenLogged(drupalSettings) { +export function setRightSectionsWhenLogged(drupalSettings) { if (drupalSettings.user.uid != 0) { const menuBurger = document.querySelector('#hamburger'); const menuTitle = document.querySelector('#menu-title'); @@ -65,7 +65,11 @@ export function setHamburgerWhenLogged(drupalSettings) { const headerTop = header.getBoundingClientRect().top; menuTitle.style.top = `${headerTop}px`; - menuBurger.style.top = `${headerTop}px`; - menuContainer.style.paddingTop = `${headerTop}px`; + menuContainer.style.paddingTop = `${headerTop + 10}px`; + menuBurger.style.top = `${headerTop + 2}px`; + + const etapesListContainer = document.querySelector('.block-region-third'); + etapesListContainer.style.paddingTop = `50px`; + } } diff --git a/web/themes/custom/caravane/assets/js/utils/map-setup.js b/web/themes/custom/caravane/assets/js/utils/map-setup.js index 32a377c..fbb0194 100644 --- a/web/themes/custom/caravane/assets/js/utils/map-setup.js +++ b/web/themes/custom/caravane/assets/js/utils/map-setup.js @@ -1,7 +1,10 @@ import { useLayoutStore } from '../stores/layout'; +import { useMapStore } from '../stores/map'; import REST from '../api/rest-axios'; -export function setupMapStore(mapStore, map, settings) { +export function setupMapStore(map, settings) { + const mapStore = useMapStore(); + mapStore.map = map; mapStore.defaultMapCenter = map.getCenter(); mapStore.maxZoom = settings.settings.maxZoom; @@ -13,7 +16,9 @@ export function setupMapStore(mapStore, map, settings) { // not working // may or may not rework on it later -export async function preloadEtapesTiles(mapStore, map) { +export async function preloadEtapesTiles(map) { + const mapStore = useMapStore(); + function waitForEvent(el, eventName) { return new Promise((resolve) => { el.once(eventName, resolve); diff --git a/web/themes/custom/caravane/assets/js/utils/set-active-nav-item.js b/web/themes/custom/caravane/assets/js/utils/set-active-nav-item.js index 26509c5..81289a7 100644 --- a/web/themes/custom/caravane/assets/js/utils/set-active-nav-item.js +++ b/web/themes/custom/caravane/assets/js/utils/set-active-nav-item.js @@ -11,13 +11,19 @@ export function setActiveNavItem(contentType, href) { } if (href === '/' || href === '') { - staticNavItems[0].classList.add('is-active'); + staticNavItems[1].classList.add('is-active'); for (let item of etapeNavItems) { item.closest('li').classList.remove('inactive'); } } else { - if (contentType === 'static') { + + if ( + contentType === 'static' + || contentType === 'partenaire' + || contentType === 'gouvernance' + || contentType === 'ressource' + ) { for (let item of staticNavItems) { if (item.getAttribute('href') === href) { item.classList.add('is-active'); @@ -26,9 +32,12 @@ export function setActiveNavItem(contentType, href) { } else if (contentType === 'etape') { for (let item of etapeNavItems) { if (item.getAttribute('href') === href) { - item.closest('li').classList.remove('inactive'); + item.closest('li').classList.remove('inactive'); + document.querySelector('#etapes-liste').scrollTo(0, item.closest('li').offsetTop); } } + } else if (contentType === "ressourceItem") { + staticNavItems[2].classList.add('is-active'); } } diff --git a/web/themes/custom/caravane/assets/js/utils/vue-setup.js b/web/themes/custom/caravane/assets/js/utils/vue-setup.js index 6e9b286..d54da46 100644 --- a/web/themes/custom/caravane/assets/js/utils/vue-setup.js +++ b/web/themes/custom/caravane/assets/js/utils/vue-setup.js @@ -6,9 +6,6 @@ import AnimationToggle from '../vuejs/AnimationToggle.vue'; import VueImageZoomer from 'vue-image-zoomer'; import 'vue-image-zoomer/dist/style.css'; -import { useContentStore } from '../stores/content'; -import { useMapStore } from '../stores/map'; - export function initVueContentModale() { const pinia = createPinia(); @@ -16,14 +13,12 @@ export function initVueContentModale() { .use(pinia) .use(router) .use(VueImageZoomer); - - const store = useContentStore(); - const mapStore = useMapStore(); + app.mount('#content-modale'); const animationToggle = createApp(AnimationToggle) .use(pinia) .mount('#animation-toggle'); - return { store, mapStore, router }; + return router; } diff --git a/web/themes/custom/caravane/assets/js/vuejs/Modale.vue b/web/themes/custom/caravane/assets/js/vuejs/Modale.vue index eaabde8..bb0174d 100644 --- a/web/themes/custom/caravane/assets/js/vuejs/Modale.vue +++ b/web/themes/custom/caravane/assets/js/vuejs/Modale.vue @@ -3,9 +3,15 @@ :enter-active-class="animationsAreEnabled ? 'v-enter-active' : 'no-transition'" :leave-active-class="animationsAreEnabled ? 'v-leave-active' : 'no-transition'" > -
-
+
+
@@ -14,7 +20,7 @@ v-if="contentType === 'ressourceItem'" :content="content" :couleur="brandColor" /> -
+
@@ -50,21 +56,27 @@ :partie="partie" :couleur="content.couleur || brandColor" />
- - - - +
+
+

Chargement du contenu...

+
+ { - watch( - () => content.value.couleur, - () => { - if (contentType.value === 'etape' && content.value.couleur) { - document.documentElement.style.setProperty('--etape-couleur', content.value.couleur || brandColor); - } - } - ); -}; - -const handleMapMovement = () => { - watch( - () => loading.value, - () => { - if (!loading.value) { - isModaleEtape = contentType.value === 'etape'; - console.log(contentType.value); - - - // Define helper functions in variables - const disableModaleTransition = () => { - document.documentElement.style.setProperty('margin-top', '0'); - document.documentElement.style.setProperty('transition', 'none'); - } - const setModaleTransition = (enterDelay) => { - document.documentElement.style.setProperty('--modale-enter-delay', `${enterDelay}s`); - }; - - const zoomToContentPlace = () => { - mapState.zoomToPlace( - content.value.coordinates.lat ? content.value.coordinates.lat : defaultMapCenter.value.lat, - content.value.coordinates.lon ? content.value.coordinates.lon : defaultMapCenter.value.lng - ); - }; - - if (animationsAreEnabled.value) { - if (isModaleEtape) { - if (!wasModaleEtape) { - // national -> détail - setModaleTransition(animationDuration.value); - zoomToContentPlace(); - } else { - // détail -> détail - setModaleTransition(animationDuration.value); - zoomToContentPlace(); - } - } else { - if (wasModaleEtape) { - // détail -> national - setModaleTransition(animationDuration.value); - mapState.resetMap(); - } else { - // national -> national - setModaleTransition(0); - } - } - } else { - if (isModaleEtape) { - // ? -> détail - zoomToContentPlace(); - } else { - // ? -> national - mapState.resetMap(); - } - disableModaleTransition(); - } - - scrollTo(0, 0); - - wasModaleEtape = isModaleEtape; - } - }, - ); -}; - -watch(() => contentType.value, () => { - if (contentType.value === '') { - handleMapLock(false); - } else { - handleMapLock(true); - } -}); - -const handleMapLock = (shoudLock) => { - const checkAndExecute = () => { - const leafletLayer = document.querySelector('.leaflet-layer'); - - if (leafletLayer) { - if (shoudLock) { - mapState.lockMap(); - } else { - mapState.unlockMap(); - } - } else { - setTimeout(checkAndExecute, 100); - } - } - checkAndExecute(); -} - onMounted(() => { nextTick(() => { + watch( + () => content.value.couleur, + () => { + if (contentType.value === 'etape' && content.value.couleur) { + document.documentElement.style.setProperty('--etape-couleur', content.value.couleur || brandColor); + } + } + ); isModaleEtape = contentType.value === 'etape'; wasModaleEtape = isModaleEtape; - handleColorChange(); - handleMapMovement(); + watch( + () => partialLoading.value, + () => { + if (!partialLoading.value) { + isModaleEtape = contentType.value === 'etape'; + mapState.handleMapMovement( + isModaleEtape, + wasModaleEtape, + content.value.coordinates?.lat, + content.value.coordinates?.lon + ); + scrollTo(0, 0); + wasModaleEtape = isModaleEtape; + } + } + ); + watch( + () => contentType.value, + () => { + if (contentType.value === '') { + mapState.unlockMap(); + } else { + mapState.lockMap(); + } + } + ); }); }); diff --git a/web/themes/custom/caravane/assets/js/vuejs/components/EtapeCard.vue b/web/themes/custom/caravane/assets/js/vuejs/components/EtapeCard.vue index f48da34..a4da6b4 100644 --- a/web/themes/custom/caravane/assets/js/vuejs/components/EtapeCard.vue +++ b/web/themes/custom/caravane/assets/js/vuejs/components/EtapeCard.vue @@ -22,18 +22,13 @@ const props = defineProps({ import { onMounted } from 'vue'; import router from '../../router/router'; -import { useContentStore } from '../../stores/content'; -import { useMapStore } from '../../stores/map'; - import { handleClickableElements } from '../../utils/handle-navigation.js'; -const store = useContentStore(); -const mapStore = useMapStore(); const siteName = document.querySelector('#site_name').innerText; onMounted(() => { const relatedEtapesCards = document.querySelectorAll('.card'); const baseUrl = window.location.protocol + "//" + window.location.host; - handleClickableElements(relatedEtapesCards, store, router, baseUrl, siteName, mapStore); + handleClickableElements(relatedEtapesCards, router, baseUrl, siteName); }); \ No newline at end of file diff --git a/web/themes/custom/caravane/assets/js/vuejs/components/ModaleHeader.vue b/web/themes/custom/caravane/assets/js/vuejs/components/ModaleHeader.vue index 52eebe7..11278c6 100644 --- a/web/themes/custom/caravane/assets/js/vuejs/components/ModaleHeader.vue +++ b/web/themes/custom/caravane/assets/js/vuejs/components/ModaleHeader.vue @@ -1,7 +1,7 @@