|
|
|
|
@@ -10,7 +10,7 @@
|
|
|
|
|
:class="[
|
|
|
|
|
layoutMode === 'split' ? 'carte-split' : '',
|
|
|
|
|
layoutMode === 'carte-full' ? 'carte-full' : '',
|
|
|
|
|
layoutMode === 'chatbot-full' ? 'carte-hidden' : '',
|
|
|
|
|
(layoutMode === 'chatbot-full' || layoutMode === 'bonpote' || layoutMode === 'rag-backend') ? 'carte-hidden' : '',
|
|
|
|
|
]"
|
|
|
|
|
:style="layoutMode === 'split' ? { flexBasis: carteFlexBasis } : {}"
|
|
|
|
|
style="position: relative;"
|
|
|
|
|
@@ -80,33 +80,46 @@
|
|
|
|
|
</svg>
|
|
|
|
|
Chatbot plein ecran
|
|
|
|
|
</button>
|
|
|
|
|
<button
|
|
|
|
|
@click="setLayoutMode('bonpote')"
|
|
|
|
|
:class="{ active: layoutMode === 'bonpote' }"
|
|
|
|
|
class="toggle-btn"
|
|
|
|
|
title="A propos de la carte FRACAS Bonpote V2"
|
|
|
|
|
style="margin-left: auto;"
|
|
|
|
|
>
|
|
|
|
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
|
|
|
|
<circle cx="12" cy="12" r="10"/><polyline points="12 8 12 12 14 14"/>
|
|
|
|
|
</svg>
|
|
|
|
|
Bonpote V2
|
|
|
|
|
</button>
|
|
|
|
|
|
|
|
|
|
<!-- Toggle PDF FRACAS -->
|
|
|
|
|
<label class="layer-toggle" title="Superposer la carte FRACAS Bonpote V2 en PDF">
|
|
|
|
|
<input type="checkbox" v-model="showFracasPdf" />
|
|
|
|
|
📄 Carte FRACAS (PDF)
|
|
|
|
|
</label>
|
|
|
|
|
<input
|
|
|
|
|
v-if="showFracasPdf"
|
|
|
|
|
type="range"
|
|
|
|
|
min="0"
|
|
|
|
|
max="100"
|
|
|
|
|
v-model.number="fracasOpacity"
|
|
|
|
|
class="opacity-slider"
|
|
|
|
|
:title="`Opacité ${fracasOpacity}%`"
|
|
|
|
|
/>
|
|
|
|
|
<!-- Groupe droit : carte des pensées + RAG backend -->
|
|
|
|
|
<div style="margin-left: auto; display: flex; align-items: center; gap: 4px; flex-wrap: wrap;">
|
|
|
|
|
<input
|
|
|
|
|
v-if="showFracasPdf"
|
|
|
|
|
type="range"
|
|
|
|
|
min="0"
|
|
|
|
|
max="100"
|
|
|
|
|
v-model.number="fracasOpacity"
|
|
|
|
|
class="opacity-slider"
|
|
|
|
|
:title="`Opacité ${fracasOpacity}%`"
|
|
|
|
|
/>
|
|
|
|
|
<div class="carte-pensees-ctrl">
|
|
|
|
|
<input
|
|
|
|
|
type="checkbox"
|
|
|
|
|
v-model="showFracasPdf"
|
|
|
|
|
class="fracas-check"
|
|
|
|
|
title="Superposer la carte FRACAS en PDF"
|
|
|
|
|
/>
|
|
|
|
|
<button
|
|
|
|
|
@click="setLayoutMode('bonpote')"
|
|
|
|
|
:class="{ active: layoutMode === 'bonpote' }"
|
|
|
|
|
class="toggle-btn carte-pensees-btn"
|
|
|
|
|
title="Carte des pensées écologiques — référence FRACAS Bonpote V2"
|
|
|
|
|
>
|
|
|
|
|
📗 carte des pensées écologiques
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
<button
|
|
|
|
|
@click="setLayoutMode('rag-backend')"
|
|
|
|
|
:class="{ active: layoutMode === 'rag-backend' }"
|
|
|
|
|
class="toggle-btn"
|
|
|
|
|
title="Interface LightRAG backend"
|
|
|
|
|
>
|
|
|
|
|
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
|
|
|
|
<circle cx="12" cy="12" r="3"/><path d="M19.07 4.93a10 10 0 0 1 0 14.14M4.93 4.93a10 10 0 0 0 0 14.14"/>
|
|
|
|
|
</svg>
|
|
|
|
|
RAG backend
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- Poignee draggable (visible uniquement en mode split, pas sur mobile) -->
|
|
|
|
|
@@ -125,7 +138,7 @@
|
|
|
|
|
:class="[
|
|
|
|
|
layoutMode === 'split' ? 'chatbot-split' : '',
|
|
|
|
|
layoutMode === 'chatbot-full' ? 'chatbot-full-mode' : '',
|
|
|
|
|
layoutMode === 'carte-full' ? 'chatbot-hidden' : '',
|
|
|
|
|
(layoutMode === 'carte-full' || layoutMode === 'bonpote' || layoutMode === 'rag-backend') ? 'chatbot-hidden' : '',
|
|
|
|
|
]"
|
|
|
|
|
:style="layoutMode === 'split' ? { flexBasis: chatbotFlexBasis } : {}"
|
|
|
|
|
>
|
|
|
|
|
@@ -189,6 +202,14 @@
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- Vue RAG backend -->
|
|
|
|
|
<div
|
|
|
|
|
v-if="layoutMode === 'rag-backend'"
|
|
|
|
|
style="flex: 1; overflow: hidden; display: flex; flex-direction: column;"
|
|
|
|
|
>
|
|
|
|
|
<MediaTabBackend />
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- Fiche auteur modal -->
|
|
|
|
|
@@ -264,7 +285,7 @@ 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'
|
|
|
|
|
type LayoutMode = 'split' | 'carte-full' | 'chatbot-full' | 'bonpote' | 'rag-backend'
|
|
|
|
|
|
|
|
|
|
const STORAGE_KEY = 'media-layout-mode'
|
|
|
|
|
const SPLIT_RATIO_KEY = 'media-split-ratio'
|
|
|
|
|
@@ -279,19 +300,15 @@ const chatbotAuteur = ref<string | null>(null)
|
|
|
|
|
const layoutMode = ref<LayoutMode>('split')
|
|
|
|
|
const cartePenseesRef = ref<{ triggerResize: () => void } | null>(null)
|
|
|
|
|
|
|
|
|
|
// Toggle PDF FRACAS
|
|
|
|
|
const showFracasPdf = ref(false)
|
|
|
|
|
const fracasOpacity = ref(60)
|
|
|
|
|
|
|
|
|
|
// Props injectées depuis le parent (penseesData)
|
|
|
|
|
const props = defineProps<{ penseesData: PenseesData | null }>()
|
|
|
|
|
const penseesData = ref<PenseesData | null>(null)
|
|
|
|
|
|
|
|
|
|
// Ratio de la carte vs chatbot en mode split (0.2 a 0.8)
|
|
|
|
|
const splitRatio = ref(DEFAULT_SPLIT_RATIO)
|
|
|
|
|
const carteFlexBasis = computed(() => `${splitRatio.value * 100}%`)
|
|
|
|
|
const chatbotFlexBasis = computed(() => `${(1 - splitRatio.value) * 100}%`)
|
|
|
|
|
|
|
|
|
|
// Logique poignee draggable
|
|
|
|
|
let dragStartY = 0
|
|
|
|
|
let dragStartRatio = DEFAULT_SPLIT_RATIO
|
|
|
|
|
let containerHeight = 0
|
|
|
|
|
@@ -321,10 +338,10 @@ function onHandleMouseup() {
|
|
|
|
|
cartePenseesRef.value?.triggerResize()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
onMounted(() => {
|
|
|
|
|
onMounted(async () => {
|
|
|
|
|
if (typeof window !== 'undefined') {
|
|
|
|
|
const saved = localStorage.getItem(STORAGE_KEY) as LayoutMode | null
|
|
|
|
|
if (saved && ['split', 'carte-full', 'chatbot-full', 'bonpote'].includes(saved)) {
|
|
|
|
|
if (saved && (['split', 'carte-full', 'chatbot-full', 'bonpote', 'rag-backend'] as string[]).includes(saved)) {
|
|
|
|
|
layoutMode.value = saved
|
|
|
|
|
}
|
|
|
|
|
const savedRatio = parseFloat(localStorage.getItem(SPLIT_RATIO_KEY) ?? '')
|
|
|
|
|
@@ -336,6 +353,11 @@ onMounted(() => {
|
|
|
|
|
localStorage.setItem('rag-fracas-info-seen', '1')
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
try {
|
|
|
|
|
penseesData.value = await $fetch<PenseesData>('/data/auteurs-pensees.json?v=4.2')
|
|
|
|
|
} catch (e) {
|
|
|
|
|
console.error('Erreur chargement auteurs-pensees.json', e)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
function setLayoutMode(mode: LayoutMode) {
|
|
|
|
|
@@ -343,7 +365,7 @@ function setLayoutMode(mode: LayoutMode) {
|
|
|
|
|
if (typeof window !== 'undefined') {
|
|
|
|
|
localStorage.setItem(STORAGE_KEY, mode)
|
|
|
|
|
}
|
|
|
|
|
if (mode !== 'chatbot-full') {
|
|
|
|
|
if (mode === 'split' || mode === 'carte-full') {
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
cartePenseesRef.value?.triggerResize()
|
|
|
|
|
}, 350)
|
|
|
|
|
@@ -374,14 +396,14 @@ function onSelectAuteurFromEcole(auteurId: string) {
|
|
|
|
|
|
|
|
|
|
function onInterrogerEcole(ecoleId: string) {
|
|
|
|
|
ficheEcoleOpen.value = false
|
|
|
|
|
const ecole = props.penseesData?.ecoles.find(e => e.id === ecoleId)
|
|
|
|
|
const ecole = penseesData.value?.ecoles.find(e => e.id === ecoleId)
|
|
|
|
|
chatbotAuteur.value = ecole?.label ?? null
|
|
|
|
|
if (layoutMode.value === 'carte-full') setLayoutMode('split')
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function onInterrogerRag(auteurId: string) {
|
|
|
|
|
ficheOpen.value = false
|
|
|
|
|
const auteur = props.penseesData?.auteurs.find(a => a.id === auteurId)
|
|
|
|
|
const auteur = penseesData.value?.auteurs.find(a => a.id === auteurId)
|
|
|
|
|
chatbotAuteur.value = auteur?.nom ?? null
|
|
|
|
|
if (layoutMode.value === 'carte-full') {
|
|
|
|
|
setLayoutMode('split')
|
|
|
|
|
@@ -481,28 +503,28 @@ function onInterrogerRag(auteurId: string) {
|
|
|
|
|
border-color: var(--nav-primary);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* --- Toggle layer PDF FRACAS --- */
|
|
|
|
|
.layer-toggle {
|
|
|
|
|
/* --- Contrôle fusionné carte des pensées + tickbox --- */
|
|
|
|
|
.carte-pensees-ctrl {
|
|
|
|
|
display: inline-flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
gap: 5px;
|
|
|
|
|
padding: 4px 10px;
|
|
|
|
|
gap: 0;
|
|
|
|
|
border-radius: 6px;
|
|
|
|
|
font-size: 0.75rem;
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
background: var(--nav-bg-alt);
|
|
|
|
|
color: var(--nav-text-muted);
|
|
|
|
|
border: 1px solid transparent;
|
|
|
|
|
user-select: none;
|
|
|
|
|
margin-left: 4px;
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
border: 1px solid rgba(180, 170, 160, 0.3);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.layer-toggle input[type="checkbox"] {
|
|
|
|
|
margin: 0;
|
|
|
|
|
.fracas-check {
|
|
|
|
|
margin: 0 2px 0 7px;
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
accent-color: var(--nav-primary, #3b6ea5);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.carte-pensees-btn {
|
|
|
|
|
border-radius: 0;
|
|
|
|
|
border: none;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* --- Slider opacité PDF --- */
|
|
|
|
|
.opacity-slider {
|
|
|
|
|
width: 80px;
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|