From e14b0a347876d415f094dccff400a654ccaecc9e Mon Sep 17 00:00:00 2001 From: Esenjin Date: Mon, 17 Feb 2025 13:03:10 +0100 Subject: [PATCH] =?UTF-8?q?r=C3=A9organisation=20de=20la=20page=20"options?= =?UTF-8?q?"=20et=20ajout=20d'une=20fonction=20de=20lien=20personnalis?= =?UTF-8?q?=C3=A9=20pour=20la=20page=20"=C3=A0=20propos"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- about.php | 148 +++++++++++++++++-------------- admin/options.php | 197 +++++++++++++----------------------------- assets/css/forms.css | 94 ++++++++++++++++++++ assets/css/public.css | 139 +++++++++++++++++++++++++++++ assets/js/options.js | 187 +++++++++++++++++++++++++++++++++++++++ config.json | 9 +- version.txt | 2 +- 7 files changed, 573 insertions(+), 203 deletions(-) create mode 100644 assets/js/options.js diff --git a/about.php b/about.php index 2c095ba..edd02c6 100644 --- a/about.php +++ b/about.php @@ -37,77 +37,97 @@ $siteStats = $stats->getStats(); -
-
- +
+
+
-
diff --git a/admin/options.php b/admin/options.php index 7841855..ce1b86f 100644 --- a/admin/options.php +++ b/admin/options.php @@ -25,6 +25,20 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { $config['about']['title'] = trim($_POST['about_title'] ?? 'À propos'); $config['about']['content'] = $_POST['about_content'] ?? ''; + // Traitement des liens personnalisés + $config['about']['links'] = []; + if (!empty($_POST['links'])) { + foreach ($_POST['links'] as $link) { + if (!empty($link['title']) && !empty($link['url'])) { + $config['about']['links'][] = [ + 'title' => trim($link['title']), + 'url' => trim($link['url']), + 'target' => isset($link['target']) ? '_blank' : '' + ]; + } + } + } + // Validation if (empty($config['site']['name'])) { throw new Exception('Le nom du site est requis'); @@ -92,10 +106,10 @@ $config = Config::load();
-

Options générales

+
Image de fond actuelle + alt="Image de fond actuelle">
-
+
+ + +

Liens personnalisés

+ + - +
- - + diff --git a/assets/css/forms.css b/assets/css/forms.css index b493cd9..8827f95 100644 --- a/assets/css/forms.css +++ b/assets/css/forms.css @@ -104,4 +104,98 @@ height: auto; display: block; margin: var(--spacing-md) 0; +} + +/* Section Options */ +/* Conteneur des options */ +.options-container { + margin: 0 auto; +} + +.options-section { + background: var(--bg-tertiary); + padding: var(--spacing-xl); + border-radius: var(--radius-md); + border: 1px solid var(--border-color); + margin-bottom: var(--spacing-xl); +} + +.options-section h2 { + margin: var(--spacing-xl) 0 var(--spacing-lg); + padding-bottom: var(--spacing-sm); + border-bottom: 2px solid var(--accent-primary); + color: var(--text-primary); +} + +.options-section h2:first-child { + margin-top: 0; +} + +/* Aperçus des images */ +.current-logo img, +.current-background img { + max-height: 100px; + margin: var(--spacing-sm) 0; + border-radius: var(--radius-sm); + border: 1px solid var(--border-color); +} + +/* Section des liens personnalisés */ +.custom-links { + margin: var(--spacing-lg) 0; +} + +.link-item { + background: var(--bg-secondary); + padding: var(--spacing-lg); + border-radius: var(--radius-sm); + margin-bottom: var(--spacing-md); + border: 1px solid var(--border-color); +} + +.link-item .form-group { + margin-bottom: var(--spacing-md); +} + +.link-item .form-group:last-of-type { + margin-bottom: var(--spacing-sm); +} + +.link-item label { + display: block; + margin-bottom: var(--spacing-xs); +} + +.link-item label:has(input[type="checkbox"]) { + display: flex; + align-items: center; + gap: var(--spacing-xs); + cursor: pointer; +} + +.link-item input[type="checkbox"] { + margin: 0; +} + +/* Bouton d'ajout de lien */ +#addLink { + margin-bottom: var(--spacing-xl); +} + +/* Bouton de soumission */ +.submit-button { + margin-top: var(--spacing-xl); + width: 100%; + padding: var(--spacing-md); +} + +/* Responsive */ +@media (max-width: 768px) { + .options-section { + padding: var(--spacing-md); + } + + .link-item { + padding: var(--spacing-md); + } } \ No newline at end of file diff --git a/assets/css/public.css b/assets/css/public.css index f32a43a..1670124 100644 --- a/assets/css/public.css +++ b/assets/css/public.css @@ -522,6 +522,120 @@ body { color: var(--text-tertiary); } +/* Styles pour la page À propos */ +.about-content { + max-width: var(--content-width); + margin: 0 auto; + padding: 0 var(--spacing-md); + display: grid; + grid-template-columns: 1fr 300px; + gap: var(--spacing-xl); +} + +.about-description { + background: var(--bg-tertiary); + padding: var(--spacing-lg); + border-radius: var(--radius-md); + border: 1px solid var(--border-color); +} + +/* Sidebar */ +.sidebar { + display: flex; + flex-direction: column; + gap: var(--spacing-xl); +} + +.sidebar-section { + background: var(--bg-tertiary); + padding: var(--spacing-lg); + border-radius: var(--radius-md); + border: 1px solid var(--border-color); + position: sticky; + top: var(--spacing-lg); +} + +.sidebar-section h2 { + font-size: 1.5rem; + margin-bottom: var(--spacing-md); + color: var(--text-primary); + padding-bottom: var(--spacing-sm); + border-bottom: 2px solid var(--accent-primary); +} + +/* Liens personnalisés */ +.custom-links-list { + list-style: none; + margin: 0; + padding: 0; +} + +.custom-links-list li { + margin-bottom: var(--spacing-sm); +} + +.custom-links-list a { + display: block; + padding: var(--spacing-sm); + color: var(--text-primary); + text-decoration: none; + border-radius: var(--radius-sm); + transition: all var(--transition-fast); +} + +.custom-links-list a:hover { + background: var(--bg-secondary); + color: var(--accent-primary); +} + +/* Statistiques */ +.stats-list { + list-style: none; + margin: 0; + padding: 0; +} + +.stats-item { + margin-bottom: var(--spacing-md); + padding-bottom: var(--spacing-md); + border-bottom: 1px solid var(--border-color); +} + +.stats-item:last-child { + border-bottom: none; + margin-bottom: 0; + padding-bottom: 0; +} + +.stats-label { + font-size: 0.9rem; + color: var(--text-secondary); + margin-bottom: var(--spacing-xs); +} + +.stats-value { + font-size: 1.2rem; + color: var(--text-primary); + font-weight: bold; +} + +.stats-detail { + font-size: 0.85rem; + color: var(--accent-primary); + margin-top: var(--spacing-xs); +} + +.stats-detail a { + color: var(--accent-primary); + text-decoration: none; + transition: color var(--transition-fast); +} + +.stats-detail a:hover { + color: var(--accent-secondary); + text-decoration: underline; +} + /* Responsive */ @media (max-width: 1200px) { :root { @@ -542,6 +656,18 @@ body { .novel-header h1 { font-size: 2.5rem; } + + .about-content { + grid-template-columns: 1fr; + } + + .sidebar { + gap: var(--spacing-lg); + } + + .sidebar-section { + position: static; + } } @media (max-width: 768px) { @@ -610,4 +736,17 @@ body { .site-header h1 { font-size: 2.4rem; } + + .about-content { + padding: var(--spacing-sm); + } + + .about-description, + .sidebar-section { + padding: var(--spacing-md); + } + + .stats-value { + font-size: 1.1rem; + } } \ No newline at end of file diff --git a/assets/js/options.js b/assets/js/options.js new file mode 100644 index 0000000..069bef2 --- /dev/null +++ b/assets/js/options.js @@ -0,0 +1,187 @@ +document.addEventListener('DOMContentLoaded', function() { + // Configuration de l'éditeur Quill + const aboutEditor = new Quill('#aboutEditor', { + theme: 'snow', + modules: { + toolbar: { + container: [ + [{ 'header': [1, 2, 3, false] }], + ['bold', 'italic', 'underline', 'strike'], + [{ 'color': [] }, { 'background': [] }], + [{ 'font': [] }], + [{ 'align': [] }], + ['blockquote', 'code-block'], + [{ 'list': 'ordered'}, { 'list': 'bullet' }], + [{ 'script': 'sub'}, { 'script': 'super' }], + [{ 'indent': '-1'}, { 'indent': '+1' }], + [{ 'direction': 'rtl' }], + ['link', 'image', 'video'], + ['clean'] + ], + handlers: { + image: handleImageUpload + } + } + }, + placeholder: 'Commencez à écrire le contenu de la page À propos...' + }); + + // Gestion de l'upload d'images + function handleImageUpload() { + const input = document.createElement('input'); + input.setAttribute('type', 'file'); + input.setAttribute('accept', 'image/*'); + input.click(); + + input.onchange = async () => { + const file = input.files[0]; + if (file) { + const formData = new FormData(); + formData.append('image', file); + + try { + const response = await fetch('api/upload-image.php', { + method: 'POST', + body: formData + }); + + if (!response.ok) throw new Error('Upload failed'); + + const result = await response.json(); + if (result.success) { + const range = aboutEditor.getSelection(true); + aboutEditor.insertEmbed(range.index, 'image', result.url); + aboutEditor.setSelection(range.index + 1); + } else { + showNotification(result.error || 'Erreur lors de l\'upload', 'error'); + } + } catch (error) { + console.error('Error:', error); + showNotification('Erreur lors de l\'upload de l\'image', 'error'); + } + } + }; + } + + // Initialisation du contenu si existant + const editorElement = document.getElementById('aboutEditor'); + const initialContent = editorElement.getAttribute('data-initial-content'); + if (initialContent) { + aboutEditor.root.innerHTML = initialContent; + } + + // Gestion des prévisualisations d'images + function handleImagePreview(inputId, previewClass) { + const input = document.getElementById(inputId); + if (!input) return; + + input.addEventListener('change', function(e) { + const file = e.target.files[0]; + if (file) { + const reader = new FileReader(); + reader.onload = function(e) { + let previewContainer = input.parentElement.querySelector('.' + previewClass); + if (!previewContainer) { + previewContainer = document.createElement('div'); + previewContainer.className = previewClass; + input.parentElement.insertBefore(previewContainer, input.nextSibling); + } + previewContainer.innerHTML = `Aperçu`; + }; + reader.readAsDataURL(file); + } + }); + } + + // Initialisation des prévisualisations + handleImagePreview('site_logo', 'current-logo'); + handleImagePreview('about_background', 'current-background'); + + // Gestion des liens personnalisés + const customLinks = document.getElementById('customLinks'); + const addLinkBtn = document.getElementById('addLink'); + + // Ajout d'un nouveau lien + addLinkBtn.addEventListener('click', function() { + const index = customLinks.children.length; + const linkItem = document.createElement('div'); + linkItem.className = 'link-item'; + linkItem.innerHTML = ` +
+ + +
+
+ + +
+
+ +
+ + `; + customLinks.appendChild(linkItem); + }); + + // Suppression d'un lien + customLinks.addEventListener('click', function(e) { + if (e.target.matches('.remove-link')) { + const linkItem = e.target.closest('.link-item'); + confirmDialog.show({ + title: 'Supprimer le lien', + message: 'Êtes-vous sûr de vouloir supprimer ce lien ?', + confirmText: 'Supprimer', + confirmClass: 'danger', + onConfirm: () => { + linkItem.remove(); + // Réindexer les champs + customLinks.querySelectorAll('.link-item').forEach((item, index) => { + item.querySelectorAll('input').forEach(input => { + const name = input.getAttribute('name'); + input.setAttribute('name', name.replace(/\[\d+\]/, `[${index}]`)); + }); + }); + } + }); + } + }); + + // Mise à jour du champ caché avant la soumission + document.querySelector('form').addEventListener('submit', function() { + document.querySelector('#about_content').value = aboutEditor.root.innerHTML; + }); + + // Détection des changements non sauvegardés + const form = document.querySelector('form'); + const initialState = new FormData(form).toString(); + + window.addEventListener('beforeunload', (e) => { + if (new FormData(form).toString() !== initialState) { + e.preventDefault(); + e.returnValue = ''; + } + }); + + // Fonction utilitaire pour les notifications + function showNotification(message, type = 'success') { + const notification = document.createElement('div'); + notification.className = `notification ${type}`; + notification.textContent = message; + + document.body.appendChild(notification); + + setTimeout(() => { + notification.style.opacity = '1'; + notification.style.transform = 'translateY(0)'; + }, 10); + + setTimeout(() => { + notification.style.opacity = '0'; + notification.style.transform = 'translateY(-100%)'; + setTimeout(() => notification.remove(), 300); + }, 3000); + } +}); \ No newline at end of file diff --git a/config.json b/config.json index 81f7fb1..8702411 100644 --- a/config.json +++ b/config.json @@ -6,7 +6,14 @@ "about": { "title": "À propos", "content": "", - "background": "assets/images/site/about-bg.jpg" + "background": "assets/images/site/about-bg.jpg", + "links": [ + { + "title": "Mon Blog", + "url": "https://blog.example.com", + "target": "_blank" + } + ] }, "users": [ { diff --git a/version.txt b/version.txt index 1b87bcd..314c3d7 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.1.4 \ No newline at end of file +1.1.5 \ No newline at end of file