template html & css

This commit is contained in:
ph
2025-11-26 22:34:43 +01:00
commit ea21779b05
20 changed files with 3208 additions and 0 deletions

View File

@@ -0,0 +1,103 @@
// static/script.js
const fileListPanel = document.getElementById('file-list-panel');
const resizer = document.getElementById('resizer');
const container = document.querySelector('.container');
const fileListUl = document.getElementById('file-list');
const fileContentPre = document.getElementById('file-content');
const contentTitle = document.getElementById('content-title');
let isResizing = false;
// 1. GESTION DU REDIMENSIONNEMENT (Même logique que précédemment)
resizer.addEventListener('mousedown', function(e) {
isResizing = true;
container.classList.add('resizing');
document.body.style.userSelect = 'none';
});
document.addEventListener('mousemove', function(e) {
if (!isResizing) return;
const newWidth = e.clientX - container.getBoundingClientRect().left;
const minWidth = 150;
const maxWidth = container.clientWidth * 0.5;
if (newWidth >= minWidth && newWidth <= maxWidth) {
fileListPanel.style.width = newWidth + 'px';
}
});
document.addEventListener('mouseup', function() {
isResizing = false;
container.classList.remove('resizing');
document.body.style.userSelect = '';
});
// 2. LOGIQUE DU CHARGEMENT DES FICHIERS (Communication avec Flask)
// A. Récupérer la liste des fichiers depuis le serveur
async function fetchFileList() {
try {
const response = await fetch('/api/list_files');
const files = await response.json();
if (response.ok) {
fileListUl.innerHTML = ''; // Vider la liste existante
if (files.length === 0) {
fileListUl.innerHTML = '<li>Aucun fichier trouvé.</li>';
fileContentPre.textContent = 'Le répertoire est vide.';
} else {
files.forEach(filename => {
const li = document.createElement('li');
li.textContent = filename;
li.onclick = () => loadFileContent(filename, li);
fileListUl.appendChild(li);
});
// Charger le contenu du premier fichier par défaut
if (files.length > 0) {
loadFileContent(files[0], fileListUl.querySelector('li'));
}
}
} else {
// Afficher l'erreur retournée par Flask
fileContentPre.textContent = `Erreur: ${files.error}`;
}
} catch (error) {
fileContentPre.textContent = `Erreur de connexion au serveur : ${error.message}`;
console.error('Erreur lors de la récupération des fichiers:', error);
}
}
// B. Charger le contenu du fichier sélectionné
async function loadFileContent(filename, element) {
// Retirer la classe 'selected' de tous les éléments
document.querySelectorAll('#file-list li').forEach(li => {
li.classList.remove('selected');
});
// Ajouter la classe 'selected' à l'élément cliqué
if (element) {
element.classList.add('selected');
}
contentTitle.textContent = `Contenu de : ${filename}`;
fileContentPre.textContent = 'Chargement en cours...';
try {
const response = await fetch(`/api/get_content/${filename}`);
const data = await response.json();
if (response.ok) {
// Enlève le slice(1, -1) sauf si ton serveur renvoie le contenu entre guillemets
fileContentPre.innerHTML = marked.parse(data.content);
} else {
fileContentPre.innerHTML = `Erreur (${response.status}) : ${data.error}`;
}
} catch (error) {
fileContentPre.textContent = `Erreur réseau lors du chargement : ${error.message}`;
console.error('Erreur lors du chargement du contenu:', error);
}
}
// Exécuter au chargement de la page
document.addEventListener('DOMContentLoaded', fetchFileList);

View File

@@ -0,0 +1,73 @@
/* static/style.css */
body {
margin: 0;
font-family: Arial, sans-serif;
height: 100vh;
display: flex;
overflow: hidden;
}
.container {
display: flex;
width: 100%;
height: 100%;
border: 1px solid #ccc;
}
/* --- Panneau de la Liste des Fichiers (Gauche) --- */
#file-list-panel {
width: 300px;
min-width: 150px;
max-width: 50%;
overflow-y: auto;
padding: 10px;
background-color: #f4f4f4;
box-sizing: border-box;
}
#file-list {
list-style: none;
padding: 0;
}
#file-list li {
padding: 8px;
cursor: pointer;
border-bottom: 1px solid #eee;
}
#file-list li:hover {
background-color: #e0e0e0;
}
#file-list li.selected {
background-color: #007bff;
color: white;
}
/* --- Poignée de Redimensionnement --- */
#resizer {
width: 6px;
cursor: col-resize;
background-color: #ccc;
flex-shrink: 0;
}
#resizer:hover {
background-color: #aaa;
}
/* --- Panneau de Contenu (Droite) --- */
#content {
flex-grow: 1;
overflow-y: auto;
padding: 10px;
box-sizing: border-box;
}
#file-content {
padding: 15px;
border: 1px dashed #ddd;
background-color: #fff;
min-height: 80%;
}

View File

@@ -0,0 +1,81 @@
/* static/style_md.css */
#file-content {
background: white;
padding: 30px 40px;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}
h1, h2, h3 {
color: #333;
margin-top: 1.5em;
}
h1 {
border-bottom: 2px solid #eee;
padding-bottom: 10px;
}
code {
background: #f4f4f4;
padding: 2px 6px;
border-radius: 4px;
font-family: 'Consolas', 'Monaco', monospace;
}
pre {
background: #2d2d2d;
color: #f8f8f2;
padding: 15px;
border-radius: 6px;
overflow-x: auto;
}
pre code {
background: none;
color: inherit;
}
blockquote {
border-left: 4px solid #ddd;
margin: 0;
padding-left: 20px;
color: #666;
}
a {
color: #0066cc;
}
table {
border-collapse: collapse;
width: 100%;
}
th, td {
border: 1px solid #ddd;
padding: 8px 12px;
text-align: left;
}
th {
background: #f4f4f4;
}
img {
max-width: 100%;
}
.loader {
text-align: center;
color: #666;
padding: 40px;
}
.error {
color: #c00;
background: #fee;
padding: 15px;
border-radius: 6px;
}