Privilege Log Entry Creator
Privilege Log (Editable)
Date
Document Description
Author(s)
Recipient(s)
Privilege
Bates #
Go to the "Data Configuration" tab to add entries and generate the log.
Add Log Entry
Current Log Entries
No entries added yet.
No entries added yet.
"; return; } logEntries.forEach(entry => { const itemEl = document.createElement("div"); itemEl.className = "plec-config-item"; itemEl.dataset.id = entry.id; itemEl.innerHTML = ` ${entry.date} - ${escapeHTML(entry.desc.substring(0, 50))}... (${entry.privilege}) `; configList.appendChild(itemEl); }); } /** * Handles clicks in the config list (for remove) */ function handleConfigListClick(e) { if (e.target.dataset.action === "remove") { const itemEl = e.target.closest(".plec-config-item"); if (itemEl) { logEntries = logEntries.filter(entry => entry.id !== itemEl.dataset.id); updateConfigListDisplay(); // Update this list renderDashboard(); // Also update the dashboard } } } /** * Renders the editable dashboard grid/table */ function renderDashboard() { // Clear everything except the header row const items = dashboardList.querySelectorAll(".plec-dash-item"); items.forEach(item => item.remove()); // Remove the initial 'empty' message if it exists const emptyMsg = dashboardList.querySelector("p"); if(emptyMsg) emptyMsg.remove(); if (logEntries.length === 0) { const p = document.createElement('p'); p.style.textAlign = 'center'; p.style.padding = '20px'; p.textContent = 'Go to the "Data Configuration" tab to add entries and generate the log.'; dashboardList.appendChild(p); return; } logEntries.forEach(entry => { dashboardList.appendChild(createDashboardItem(entry)); }); } /** * Creates an editable item row for the dashboard */ function createDashboardItem(entry) { const itemEl = document.createElement("div"); itemEl.className = "plec-dash-item"; itemEl.dataset.id = entry.id; // Add data-label attributes for responsive view itemEl.innerHTML = ` `; return itemEl; } /** * Handles removing an item directly from the dashboard */ function handleDashboardClick(e) { if (e.target.dataset.action === "remove") { const itemEl = e.target.closest(".plec-dash-item"); if (itemEl) { logEntries = logEntries.filter(entry => entry.id !== itemEl.dataset.id); renderDashboard(); // Re-render dashboard updateConfigListDisplay(); // Re-render config list } } } /** * Updates the master `logEntries` array when dashboard fields change */ function handleDashboardInput(e) { const itemEl = e.target.closest(".plec-dash-item"); if (!itemEl) return; const entryId = itemEl.dataset.id; const entry = logEntries.find(e => e.id === entryId); if (!entry) return; // Update the specific field in the master array if (e.target.classList.contains('plec-dash-date')) entry.date = e.target.value; else if (e.target.classList.contains('plec-dash-desc')) entry.desc = e.target.value; else if (e.target.classList.contains('plec-dash-author')) entry.author = e.target.value; else if (e.target.classList.contains('plec-dash-recipient')) entry.recipient = e.target.value; else if (e.target.classList.contains('plec-dash-privilege')) entry.privilege = e.target.value; else if (e.target.classList.contains('plec-dash-bates')) entry.bates = e.target.value; // Optional: Update the config list display immediately as well // updateConfigListDisplay(); // Can be slightly slow if many entries } /** * Generates a PDF report from the dashboard data */ function downloadPDF() { if (typeof window.jspdf === 'undefined' || typeof window.jspdf.jsPDF.autoTable === 'undefined') { alert("Error: PDF library could not be loaded. Please try again."); return; } const { jsPDF } = window.jspdf; const doc = new jsPDF("l", "pt", "a4"); // Landscape const margin = 40; const tableHead = [["Date", "Description", "Author(s)", "Recipient(s)", "Privilege", "Bates #"]]; const tableBody = []; // Get data *from the dashboard's editable fields* const dashItems = dashboardList.querySelectorAll(".plec-dash-item"); if (dashItems.length === 0) { alert("Log is empty. Please add entries first."); return; } dashItems.forEach((item) => { const date = item.querySelector(".plec-dash-date").value; const desc = item.querySelector(".plec-dash-desc").value; const author = item.querySelector(".plec-dash-author").value; const recipient = item.querySelector(".plec-dash-recipient").value; const privilege = item.querySelector(".plec-dash-privilege").value; const bates = item.querySelector(".plec-dash-bates").value; tableBody.push([date, desc, author, recipient, privilege, bates]); }); doc.setFontSize(18); doc.text("Privilege Log", margin, margin); doc.autoTable({ startY: margin + 20, head: tableHead, body: tableBody, theme: 'striped', headStyles: { fillColor: [0, 115, 230], // Blue textColor: [255, 255, 255], }, columnStyles: { 0: { cellWidth: 70 }, // Date 1: { cellWidth: 'auto' }, // Description 2: { cellWidth: 100 }, // Author 3: { cellWidth: 100 }, // Recipient 4: { cellWidth: 80 }, // Privilege 5: { cellWidth: 70 }, // Bates }, styles: { fontSize: 9, cellPadding: 4, overflow: 'linebreak' }, margin: { left: margin, right: margin } }); doc.save("Privilege_Log.pdf"); } /** * Helper to escape HTML */ function escapeHTML(str) { if (!str) return ""; return str .replace(/&/g, "&") .replace(//g, ">") .replace(/"/g, """) .replace(/'/g, "'"); } // --- 4. INITIALIZATION & EVENT LISTENERS --- // Tab Listeners tabButtons.forEach((btn) => { btn.addEventListener("click", () => showTab(btn.dataset.target)); }); navButtons.forEach((btn) => { btn.addEventListener("click", () => showTab(btn.dataset.target)); }); // Config Tab Listeners if (addEntryForm) { addEntryForm.addEventListener("submit", handleAddEntry); } if (configList) { configList.addEventListener("click", handleConfigListClick); } if (generateBtn) { // This button now just switches to the dashboard, as adding updates it generateBtn.addEventListener("click", () => showTab('plec-tab-dashboard')); } // Dashboard Tab Listeners if (pdfBtn) { pdfBtn.addEventListener("click", downloadPDF); } if (dashboardList) { dashboardList.addEventListener("click", handleDashboardClick); // Listen for changes/inputs to update the master array dashboardList.addEventListener("input", handleDashboardInput); dashboardList.addEventListener("change", handleDashboardInput); // For select/date } // Initial State configDate.valueAsDate = new Date(); // Set date to today // Load sample data logEntries = [ { id: 'entry-1', date: '2025-10-27', desc: 'Email from J. Smith (Attorney) to A. Client discussing potential litigation strategy regarding Project X.', author: 'J. Smith (Attorney)', recipient: 'A. Client', privilege: 'Attorney-Client', bates: 'ABC000123' }, { id: 'entry-2', date: '2025-10-26', desc: 'Internal memorandum prepared by paralegal K. Lee at direction of counsel, analyzing deposition testimony.', author: 'K. Lee (Paralegal)', recipient: 'J. Smith (Attorney)', privilege: 'Work Product', bates: 'ABC000115-118' } ]; updateConfigListDisplay(); // Show samples in config list renderDashboard(); // Show samples in dashboard showTab("plec-tab-dashboard"); // Start on dashboard });