diff --git a/app.vue b/app.vue index ddb792c..098f14f 100644 --- a/app.vue +++ b/app.vue @@ -58,12 +58,11 @@ Codev - RAG - en construction + recherche-média diff --git a/components/MediaTabVisuel.vue b/components/MediaTabVisuel.vue index 63188da..e758a5f 100644 --- a/components/MediaTabVisuel.vue +++ b/components/MediaTabVisuel.vue @@ -1,53 +1,13 @@ - - + + - - - - - - - Chargement de la carte... - - - - - - - - - - - - + + @@ -70,86 +30,153 @@ Vue partagee Chatbot plein ecran + - - + + + + + + + + + + + CARTE PRINCIPALE + + + + - - - - 📗 carte des pensées écologiques - - - - - - RAG backend + 📗 carte des pensées écologiques - - - - + + + + + + RAG backend + + - - - - - - + + - + + + + + + + + + + Chargement de la carte... + + + + + + + + + + + + + + + + + + + + + + + + + @@ -178,7 +205,7 @@ Telecharger le poster PDF (recto/verso) @@ -202,9 +229,9 @@ - + @@ -285,9 +312,11 @@ interface LivreRag { slug: string; titre: string; annee: number; couches: string interface AuteurData { id: string; nom: string; dates: string; ecoles: string[]; ecole_principale: string; livres_rag: LivreRag[]; theses_cles: string[]; bio_courte: string } interface PenseesData { meta: any; ecoles: EcoleData[]; auteurs: AuteurData[] } -type LayoutMode = 'split' | 'carte-full' | 'chatbot-full' | 'bonpote' | 'rag-backend' +type LayoutMode = 'split' | 'carte-full' | 'chatbot-full' +type ContentView = 'carte' | 'bonpote' | 'rag-backend' -const STORAGE_KEY = 'media-layout-mode' +const LAYOUT_KEY = 'media-layout-mode' +const CONTENT_KEY = 'media-content-view' const SPLIT_RATIO_KEY = 'media-split-ratio' const DEFAULT_SPLIT_RATIO = 0.66 @@ -297,7 +326,9 @@ const ficheEcoleOpen = ref(false) const ficheEcoleId = ref(null) const ragInfoOpen = ref(false) const chatbotAuteur = ref(null) + const layoutMode = ref('split') +const contentView = ref('carte') const cartePenseesRef = ref<{ triggerResize: () => void } | null>(null) const showFracasPdf = ref(false) @@ -313,12 +344,23 @@ let dragStartY = 0 let dragStartRatio = DEFAULT_SPLIT_RATIO let containerHeight = 0 +function showCarte() { + contentView.value = 'carte' + layoutMode.value = 'split' + if (typeof window !== 'undefined') { + localStorage.setItem(CONTENT_KEY, 'carte') + localStorage.setItem(LAYOUT_KEY, 'split') + } + nextTick(() => { + cartePenseesRef.value?.triggerResize() + }) +} + function onHandleMousedown(e: MouseEvent) { dragStartY = e.clientY dragStartRatio = splitRatio.value const container = (e.target as HTMLElement)?.closest('.layout-container') as HTMLElement | null containerHeight = container ? container.clientHeight : window.innerHeight - window.addEventListener('mousemove', onHandleMousemove) window.addEventListener('mouseup', onHandleMouseup) } @@ -340,9 +382,13 @@ function onHandleMouseup() { onMounted(async () => { if (typeof window !== 'undefined') { - const saved = localStorage.getItem(STORAGE_KEY) as LayoutMode | null - if (saved && (['split', 'carte-full', 'chatbot-full', 'bonpote', 'rag-backend'] as string[]).includes(saved)) { - layoutMode.value = saved + const savedLayout = localStorage.getItem(LAYOUT_KEY) as LayoutMode | null + if (savedLayout && (['split', 'carte-full', 'chatbot-full'] as string[]).includes(savedLayout)) { + layoutMode.value = savedLayout + } + const savedContent = localStorage.getItem(CONTENT_KEY) as ContentView | null + if (savedContent && (['carte', 'bonpote', 'rag-backend'] as string[]).includes(savedContent)) { + contentView.value = savedContent } const savedRatio = parseFloat(localStorage.getItem(SPLIT_RATIO_KEY) ?? '') if (!isNaN(savedRatio) && savedRatio >= 0.20 && savedRatio <= 0.80) { @@ -354,30 +400,23 @@ onMounted(async () => { } } try { - penseesData.value = await $fetch('/data/auteurs-pensees.json?v=4.2') + penseesData.value = await $fetch('/data/auteurs-pensees.json') } catch (e) { console.error('Erreur chargement auteurs-pensees.json', e) } }) -function setLayoutMode(mode: LayoutMode) { - layoutMode.value = mode - if (typeof window !== 'undefined') { - localStorage.setItem(STORAGE_KEY, mode) - } - if (mode === 'split' || mode === 'carte-full') { - setTimeout(() => { - cartePenseesRef.value?.triggerResize() - }, 350) - } -} - watch(layoutMode, (v) => { - if (typeof window !== 'undefined') { - localStorage.setItem(STORAGE_KEY, v) + if (typeof window !== 'undefined') localStorage.setItem(LAYOUT_KEY, v) + if (v === 'split' || v === 'carte-full') { + setTimeout(() => cartePenseesRef.value?.triggerResize(), 350) } }) +watch(contentView, (v) => { + if (typeof window !== 'undefined') localStorage.setItem(CONTENT_KEY, v) +}) + function onSelectAuteur(id: string) { ficheAuteurId.value = id ficheOpen.value = true @@ -398,16 +437,16 @@ function onInterrogerEcole(ecoleId: string) { ficheEcoleOpen.value = false const ecole = penseesData.value?.ecoles.find(e => e.id === ecoleId) chatbotAuteur.value = ecole?.label ?? null - if (layoutMode.value === 'carte-full') setLayoutMode('split') + if (contentView.value !== 'carte') showCarte() + else if (layoutMode.value === 'carte-full') layoutMode.value = 'split' } function onInterrogerRag(auteurId: string) { ficheOpen.value = false const auteur = penseesData.value?.auteurs.find(a => a.id === auteurId) chatbotAuteur.value = auteur?.nom ?? null - if (layoutMode.value === 'carte-full') { - setLayoutMode('split') - } + if (contentView.value !== 'carte') showCarte() + else if (layoutMode.value === 'carte-full') layoutMode.value = 'split' } @@ -420,49 +459,6 @@ function onInterrogerRag(auteurId: string) { min-height: 0; } -/* Conteneur des slots carte + toggle + chatbot */ -.layout-container { - flex: 1; - display: flex; - flex-direction: column; - overflow: hidden; - min-height: 0; -} - -/* --- Slot carte --- */ -.carte-slot { - overflow: hidden; - position: relative; - transition: opacity 0.2s ease; -} - -.carte-split { - flex: 0 0 66%; - min-height: 0; - opacity: 1; -} - -.carte-full { - flex: 1 1 100%; - min-height: 0; - opacity: 1; -} - -.carte-hidden { - flex: 0 0 0; - height: 0; - opacity: 0; - overflow: hidden; -} - -/* --- Overlay PDF FRACAS --- */ -.fracas-overlay { - position: absolute; - inset: 0; - z-index: 50; - pointer-events: none; -} - /* --- Barre de toggle --- */ .layout-toggle-bar { flex-shrink: 0; @@ -503,7 +499,7 @@ function onInterrogerRag(auteurId: string) { border-color: var(--nav-primary); } -/* --- Contrôle fusionné carte des pensées + tickbox --- */ +/* --- Contrôle fusionné carte des pensées --- */ .carte-pensees-ctrl { display: inline-flex; align-items: center; @@ -524,14 +520,56 @@ function onInterrogerRag(auteurId: string) { border: none; } -/* --- Slider opacité PDF --- */ .opacity-slider { width: 80px; cursor: pointer; accent-color: var(--nav-primary, #3b6ea5); } -/* --- Poignee draggable entre carte et chatbot --- */ +/* --- Conteneur principal --- */ +.layout-container { + flex: 1; + display: flex; + flex-direction: column; + overflow: hidden; + min-height: 0; +} + +/* --- Slot carte --- */ +.carte-slot { + overflow: hidden; + position: relative; + transition: opacity 0.2s ease; +} + +.carte-split { + flex: 0 0 66%; + min-height: 0; + opacity: 1; +} + +.carte-full { + flex: 1 1 100%; + min-height: 0; + opacity: 1; +} + +.carte-hidden { + flex: 0 0 0; + height: 0; + opacity: 0; + overflow: hidden; +} + +/* --- Overlay PDF FRACAS --- */ +.fracas-overlay { + position: absolute; + inset: 0; + z-index: 50; + pointer-events: none; +} + +/* --- Poignee draggable --- */ .split-handle { flex-shrink: 0; height: 8px; @@ -563,11 +601,8 @@ function onInterrogerRag(auteurId: string) { ); } -/* Masquer la poignee sur mobile (ratio fixe) */ @media (max-width: 767px) { - .split-handle { - display: none; - } + .split-handle { display: none; } } /* --- Slot chatbot --- */ @@ -605,19 +640,16 @@ function onInterrogerRag(auteurId: string) { .modal-enter-from { opacity: 0; transform: translate(-50%,-48%) scale(0.94); } .modal-leave-to { opacity: 0; transform: translate(-50%,-48%) scale(0.96); } -/* --- Responsive mobile (<768px) --- */ +/* --- Mobile --- */ @media (max-width: 767px) { .carte-split { flex: 0 0 60vh; height: 60vh; } - .chatbot-split { flex: 0 0 calc(40vh - 38px); height: calc(40vh - 38px); } - - .toggle-btn span, .toggle-btn { font-size: 0.7rem; padding: 3px 7px; diff --git a/pages/rag.vue b/pages/rag.vue index d408d55..7854e23 100644 --- a/pages/rag.vue +++ b/pages/rag.vue @@ -1,38 +1,3 @@ - - - - - - - - - - - RAG — Retrieval Augmented Generation - - Une base de connaissances interrogeable par IA — textes, rapports, manifestes et ressources documentaires sur l'architecture d'écologie politique. - - - Bientôt disponible - - - - - - - Retour à l'écosystème - - - - - diff --git a/server/routes/data/auteurs-pensees.json.get.ts b/server/routes/data/auteurs-pensees.json.get.ts new file mode 100644 index 0000000..a57378c --- /dev/null +++ b/server/routes/data/auteurs-pensees.json.get.ts @@ -0,0 +1,10 @@ +import { readFileSync } from 'node:fs' +import { join } from 'node:path' + +export default defineEventHandler(() => { + const path = join(process.cwd(), 'public', 'data', 'auteurs-pensees.json') + const raw = readFileSync(path, 'utf-8') + setResponseHeader(useEvent(), 'content-type', 'application/json; charset=utf-8') + setResponseHeader(useEvent(), 'cache-control', 'public, max-age=300') + return raw +})
- Une base de connaissances interrogeable par IA — textes, rapports, manifestes et ressources documentaires sur l'architecture d'écologie politique. -
- Bientôt disponible -