// Messages functionality let messagesData = []; let messageModal; let currentEditingId = null; // Initialize messages on page load document.addEventListener('DOMContentLoaded', function() { // Initialize Bootstrap modal const modalElement = document.getElementById('messageModal'); if (modalElement) { messageModal = new bootstrap.Modal(modalElement); } // Tab switching const tabButtons = document.querySelectorAll('.tab-button'); tabButtons.forEach(button => { button.addEventListener('click', () => { const targetTab = button.getAttribute('data-tab'); // Update tab buttons tabButtons.forEach(btn => { if (btn.getAttribute('data-tab') === targetTab) { btn.classList.add('active'); } else { btn.classList.remove('active'); } }); // Update tab content const tabContents = document.querySelectorAll('.tab-content'); tabContents.forEach(content => { content.classList.remove('active'); }); const targetContent = document.getElementById(targetTab + '-section'); if (targetContent) { targetContent.classList.add('active'); } // Load messages when switching to messages tab if (targetTab === 'messages') { loadMessages(); } }); }); // Add message button const addMessageBtn = document.getElementById('add-message-btn'); if (addMessageBtn) { addMessageBtn.addEventListener('click', () => { openMessageModal(); }); } // Save message button const saveMessageBtn = document.getElementById('saveMessageBtn'); if (saveMessageBtn) { saveMessageBtn.addEventListener('click', () => { saveMessage(); }); } // Insert link button const insertLinkBtn = document.getElementById('insertLinkBtn'); if (insertLinkBtn) { insertLinkBtn.addEventListener('click', (e) => { e.preventDefault(); e.stopPropagation(); toggleFileBrowser(); }); } // Event delegation for file browser actions const fileBrowserContent = document.getElementById('fileBrowserContent'); if (fileBrowserContent) { fileBrowserContent.addEventListener('click', (e) => { e.preventDefault(); e.stopPropagation(); // Check if button was clicked const button = e.target.closest('button[data-action="insert-link"]'); if (button) { const path = button.getAttribute('data-path'); const name = button.getAttribute('data-name'); const type = button.getAttribute('data-type'); insertLink(path, name, type); return; } // Check if list item was clicked for navigation const navItem = e.target.closest('li[data-action="navigate"]'); if (navItem && !e.target.closest('button')) { const path = navItem.getAttribute('data-path'); loadFileBrowser(path); return; } // Check if list item was clicked for insert (files) const insertItem = e.target.closest('li[data-action="insert-link"]'); if (insertItem && !e.target.closest('button')) { const path = insertItem.getAttribute('data-path'); const name = insertItem.getAttribute('data-name'); const type = insertItem.getAttribute('data-type'); insertLink(path, name, type); return; } }); } // Event delegation for folder links in messages const messagesContainer = document.getElementById('messages-container'); if (messagesContainer) { messagesContainer.addEventListener('click', (e) => { const folderLink = e.target.closest('button[data-folder-path]'); if (folderLink) { e.preventDefault(); const folderPath = folderLink.getAttribute('data-folder-path'); // Update tab buttons without changing hash const tabButtons = document.querySelectorAll('.tab-button'); tabButtons.forEach(btn => { if (btn.getAttribute('data-tab') === 'browse') { btn.classList.add('active'); } else { btn.classList.remove('active'); } }); // Update tab content const tabContents = document.querySelectorAll('.tab-content'); tabContents.forEach(content => { content.classList.remove('active'); }); const browseSection = document.getElementById('browse-section'); if (browseSection) { browseSection.classList.add('active'); } // Load the directory directly without setTimeout if (typeof loadDirectory === 'function') { loadDirectory(folderPath); } } }); } }); async function loadMessages() { try { const response = await fetch('/api/messages'); if (!response.ok) { throw new Error('Failed to load messages'); } messagesData = await response.json(); renderMessages(); } catch (error) { console.error('Error loading messages:', error); const container = document.getElementById('messages-container'); container.innerHTML = '
Fehler beim Laden der Nachrichten
'; } } function renderMessages() { const container = document.getElementById('messages-container'); if (messagesData.length === 0) { container.innerHTML = '
Keine Nachrichten vorhanden
'; return; } let html = ''; messagesData.forEach(message => { const datetime = formatDateTime(message.datetime); // Convert folder: protocol to clickable buttons before markdown parsing let processedContent = message.content || ''; processedContent = processedContent.replace(/\[([^\]]+)\]\(folder:([^)]+)\)/g, (match, name, path) => `` ); // Configure marked to allow all links marked.setOptions({ breaks: true, gfm: true }); const contentHtml = marked.parse(processedContent); html += `

${escapeHtml(message.title)}

${datetime}
${contentHtml}
${admin_enabled ? `
` : ''}
`; }); container.innerHTML = html; } function formatDateTime(datetimeStr) { try { const date = new Date(datetimeStr); const options = { year: 'numeric', month: 'long', day: 'numeric', hour: '2-digit', minute: '2-digit' }; return date.toLocaleDateString('de-DE', options); } catch (error) { return datetimeStr; } } function escapeHtml(text) { const map = { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }; return text.replace(/[&<>"']/g, m => map[m]); } function openMessageModal(messageId = null) { currentEditingId = messageId; const modalTitle = document.getElementById('messageModalLabel'); const messageIdInput = document.getElementById('messageId'); const titleInput = document.getElementById('messageTitle'); const datetimeInput = document.getElementById('messageDateTime'); const contentInput = document.getElementById('messageContent'); if (messageId) { // Edit mode const message = messagesData.find(m => m.id === messageId); if (message) { modalTitle.textContent = 'Nachricht bearbeiten'; messageIdInput.value = message.id; titleInput.value = message.title; // Format datetime for input const date = new Date(message.datetime); const formattedDate = date.toISOString().slice(0, 16); datetimeInput.value = formattedDate; contentInput.value = message.content; } } else { // Add mode modalTitle.textContent = 'Neue Nachricht'; messageIdInput.value = ''; titleInput.value = ''; // Set current datetime const now = new Date(); const formattedNow = now.toISOString().slice(0, 16); datetimeInput.value = formattedNow; contentInput.value = ''; } messageModal.show(); } async function saveMessage() { const messageId = document.getElementById('messageId').value; const title = document.getElementById('messageTitle').value.trim(); const datetime = document.getElementById('messageDateTime').value; const content = document.getElementById('messageContent').value.trim(); if (!title || !datetime || !content) { alert('Bitte füllen Sie alle Felder aus.'); return; } // Convert datetime-local to ISO string const datetimeISO = new Date(datetime).toISOString(); const data = { title: title, datetime: datetimeISO, content: content }; try { let response; if (messageId) { // Update existing message response = await fetch(`/api/messages/${messageId}`, { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(data) }); } else { // Create new message response = await fetch('/api/messages', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(data) }); } if (!response.ok) { throw new Error('Failed to save message'); } messageModal.hide(); loadMessages(); } catch (error) { console.error('Error saving message:', error); alert('Fehler beim Speichern der Nachricht.'); } } function editMessage(messageId) { openMessageModal(messageId); } async function deleteMessage(messageId) { if (!confirm('Möchten Sie diese Nachricht wirklich löschen?')) { return; } try { const response = await fetch(`/api/messages/${messageId}`, { method: 'DELETE' }); if (!response.ok) { throw new Error('Failed to delete message'); } loadMessages(); } catch (error) { console.error('Error deleting message:', error); alert('Fehler beim Löschen der Nachricht.'); } } // File browser functionality let currentBrowserPath = ''; let fileBrowserCollapse = null; function toggleFileBrowser() { const collapse = document.getElementById('fileBrowserCollapse'); // Initialize collapse on first use if (!fileBrowserCollapse) { fileBrowserCollapse = new bootstrap.Collapse(collapse, { toggle: false }); } if (collapse.classList.contains('show')) { fileBrowserCollapse.hide(); } else { fileBrowserCollapse.show(); loadFileBrowser(''); } } async function loadFileBrowser(path) { currentBrowserPath = path; const container = document.getElementById('fileBrowserContent'); const pathDisplay = document.getElementById('currentPath'); pathDisplay.textContent = path || '/'; container.innerHTML = '
'; try { const response = await fetch(`/api/path/${path}`); if (!response.ok) { throw new Error('Failed to load directory'); } const data = await response.json(); renderFileBrowser(data); } catch (error) { console.error('Error loading directory:', error); container.innerHTML = '
Fehler beim Laden des Verzeichnisses
'; } } function renderFileBrowser(data) { const container = document.getElementById('fileBrowserContent'); let html = ''; container.innerHTML = html; } function insertLink(path, name, type) { const contentTextarea = document.getElementById('messageContent'); // For folders, use folder: protocol; for files use /media/ const url = type === 'folder' ? `folder:${path}` : `/media/${path}`; const linkText = `[${name}](${url})`; // Insert at cursor position const start = contentTextarea.selectionStart; const end = contentTextarea.selectionEnd; const text = contentTextarea.value; contentTextarea.value = text.substring(0, start) + linkText + text.substring(end); contentTextarea.selectionStart = contentTextarea.selectionEnd = start + linkText.length; contentTextarea.focus(); // Optionally close the browser after inserting fileBrowserCollapse.hide(); }