Customizable Task Templates

Customizable Task Templates

Existing Templates

Generate Tasks from Template

Due: ${generatedTask.calculatedDueDate} | Prio: ${generatedTask.priority} ${generatedTask.duration ? ` | Dur: ${generatedTask.duration}` : ''} ${generatedTask.value ? ` | Val: ${generatedTask.value}` : ''}

`; generatedTasksListUL.appendChild(li); generatedCount++; }); generatedTasksHeader.textContent = `Generated Tasks from "${template.name}"` + (projectName ? ` for "${projectName}"` : ''); generatedTasksSection.style.display = generatedCount > 0 ? 'block' : 'none'; if (generatedCount === 0) { generatedTasksListUL.innerHTML = '
  • This template has no sub-tasks defined.
  • '; } }); // --- PDF Downloads --- function downloadTemplateDefinition(templateId) { const template = taskTemplates.find(t => t.id === templateId); if (!template) { alert('Template not found for download.'); return; } const { jsPDF } = window.jspdf; const doc = new jsPDF(); doc.setFontSize(18); doc.text(`Template Definition: ${template.name}`, 14, 22); doc.setFontSize(12); doc.text(`ID: ${template.id}`, 14, 30); doc.text(`Number of Sub-Tasks: ${template.subTasks ? template.subTasks.length : 0}`, 14, 36); if (template.subTasks && template.subTasks.length > 0) { const body = template.subTasks.map((sub, index) => [ index + 1, sub.description, sub.priority, `+${sub.dueOffsetDays}d`, sub.duration || 'N/A', sub.value || 'N/A' ]); doc.autoTable({ startY: 45, head: [['#', 'Description', 'Priority', 'Due Offset', 'Duration', 'Value']], body: body, theme: 'grid' }); } else { doc.text('No sub-tasks defined in this template.', 14, 45); } doc.save(`Template_${template.name.replace(/\s+/g, '_')}.pdf`); } downloadGeneratedTasksPdfBtn.addEventListener('click', () => { const templateId = selectTemplateToUse.value; const template = templateId ? taskTemplates.find(t => t.id === templateId) : null; const projectName = instanceProjectNameInput.value.trim(); const startDateStr = instanceStartDateInput.value; const { jsPDF } = window.jspdf; const doc = new jsPDF(); doc.setFontSize(18); doc.text('Generated Task List', 14, 22); doc.setFontSize(11); if (template) doc.text(`From Template: ${template.name}`, 14, 30); if (projectName) doc.text(`For Project/Reference: ${projectName}`, 14, template ? 36 : 30); if (startDateStr) doc.text(`Based on Start Date: ${new Date(startDateStr+"T00:00:00").toLocaleDateString()}`, 14, (template || projectName) ? (template && projectName ? 42 : 36) : 30); const body = []; generatedTasksListUL.querySelectorAll('.generated-task-item').forEach((li, index) => { const descElement = li.querySelector('.task-description-generated'); const description = descElement ? descElement.textContent.trim() : 'N/A'; const metaText = li.querySelector('.task-meta').textContent; const dueDateMatch = metaText.match(/Due: ([\d\/\.]+)/); const prioMatch = metaText.match(/Prio: (\w+)/); const durMatch = metaText.match(/Dur: ([^\|\s]+)/); const valMatch = metaText.match(/Val: (\d+)/); body.push([ index + 1, description, prioMatch ? prioMatch[1] : 'N/A', dueDateMatch ? dueDateMatch[1] : 'N/A', durMatch ? durMatch[1] : 'N/A', valMatch ? valMatch[1] : 'N/A' ]); }); if (body.length > 0) { doc.autoTable({ startY: (template || projectName || startDateStr) ? 50 : 30, head: [['#', 'Description', 'Priority', 'Due Date', 'Duration', 'Value']], body: body, theme: 'grid', headStyles: { fillColor: [0, 123, 255], textColor: 255 } }); } else { doc.text('No tasks were generated or are currently displayed.', 14, 50); } const safeProjectName = projectName.replace(/\s+/g, '_') || "Tasks"; doc.save(`Generated_${safeProjectName}.pdf`); }); // --- Initializations --- renderTemplatesList(); // Includes populating the select for generation // Default start date is set via HTML value, but could also be set here if needed })();
    Scroll to Top