Smart Worklog Generator

Smart Worklog Generator

Create/Edit Task Template

Your Task Templates

NameDescriptionCategoryEst. DurationActions

Quick Add From Templates:

Log Custom or Template-Based Task:

Worklog for

Total Time Logged: 00:00

DescriptionCategory/ProjectStartEndDurationNotesActions
'; return; } swg_taskTemplates.forEach(template => { const button = document.createElement('button'); button.type = 'button'; button.className = 'swg-button swg-quick-add-btn'; button.textContent = template.name; button.onclick = () => swg_quickAddTaskFromTemplate(template.id); container.appendChild(button); }); } function swg_quickAddTaskFromTemplate(templateId) { const template = swg_taskTemplates.find(t => t.id == templateId); if (template) { swg_clearWorklogEntryForm(false); // Clear form but keep date document.getElementById('swg_logTaskDescription').value = template.defaultDescription || template.name; document.getElementById('swg_logCategory').value = template.defaultCategory; // Suggest next available start time const logDate = document.getElementById('swg_logDate').value; const logsForDay = swg_dailyWorklogEntries.filter(log => log.date === logDate).sort((a,b) => a.endTime.localeCompare(b.endTime)); let suggestedStartTime = "09:00"; // Default start if (logsForDay.length > 0) { suggestedStartTime = logsForDay[logsForDay.length - 1].endTime; } document.getElementById('swg_logStartTime').value = suggestedStartTime; if (template.defaultEstMinutes > 0) { const startMinutes = swg_calculateDurationMinutes("00:00", suggestedStartTime); // Convert HH:MM to minutes from midnight const endTotalMinutes = startMinutes + template.defaultEstMinutes; const endHours = String(Math.floor(endTotalMinutes / 60) % 24).padStart(2, '0'); const endMinutes = String(endTotalMinutes % 60).padStart(2, '0'); document.getElementById('swg_logEndTime').value = `${endHours}:${endMinutes}`; } document.getElementById('swg_logTaskDescription').focus(); // Focus on description for potential minor edits } } function swg_clearWorklogEntryForm(clearDate = false) { document.getElementById('swg_worklogEntryId').value = ''; if(clearDate) document.getElementById('swg_logDate').value = SWG_CONTEXT_DATE_STR; document.getElementById('swg_logTaskDescription').value = ''; document.getElementById('swg_logStartTime').value = ''; document.getElementById('swg_logEndTime').value = ''; document.getElementById('swg_logCategory').value = ''; document.getElementById('swg_logNotes').value = ''; document.getElementById('swg_saveWorklogEntryButton').textContent = 'Add/Update Entry'; const cancelBtn = document.getElementById('swg_cancelEntryEditBtn'); if(cancelBtn) cancelBtn.style.display = 'none'; } function swg_saveWorklogEntry() { const id = document.getElementById('swg_worklogEntryId').value; const date = document.getElementById('swg_logDate').value; const description = document.getElementById('swg_logTaskDescription').value.trim(); const startTime = document.getElementById('swg_logStartTime').value; const endTime = document.getElementById('swg_logEndTime').value; const category = document.getElementById('swg_logCategory').value.trim(); const notes = document.getElementById('swg_logNotes').value.trim(); const durationMinutes = swg_calculateDurationMinutes(startTime, endTime); if (!date) { alert("Please select a date for the worklog entry."); return; } if (!description || !startTime || !endTime || !category) { alert("Description, Start/End Times, and Category are required."); return; } if (durationMinutes <= 0) { alert("End Time must be after Start Time for a valid duration."); return; } const entry = {date, description, startTime, endTime, durationMinutes, category, notes}; if (id) { const index = swg_dailyWorklogEntries.findIndex(e => e.id == id); if(index > -1) swg_dailyWorklogEntries[index] = {...swg_dailyWorklogEntries[index], ...entry}; } else { swg_dailyWorklogEntries.push({id: Date.now(), ...entry}); } swg_clearWorklogEntryForm(false); // Keep date, clear rest swg_renderDailyLogTable(); } function swg_editWorklogEntry(entryId) { const entry = swg_dailyWorklogEntries.find(e => e.id == entryId); if (entry) { document.getElementById('swg_worklogEntryId').value = entry.id; document.getElementById('swg_logDate').value = entry.date; // Ensure date is correct document.getElementById('swg_currentLogDateDisplay').textContent = entry.date; document.getElementById('swg_logTaskDescription').value = entry.description; document.getElementById('swg_logStartTime').value = entry.startTime; document.getElementById('swg_logEndTime').value = entry.endTime; document.getElementById('swg_logCategory').value = entry.category; document.getElementById('swg_logNotes').value = entry.notes; document.getElementById('swg_saveWorklogEntryButton').textContent = 'Update Entry'; const cancelBtn = document.getElementById('swg_cancelEntryEditBtn'); if(cancelBtn) cancelBtn.style.display = 'inline-block'; } } function swg_deleteWorklogEntry(entryId) { if (confirm("Delete this worklog entry?")) { swg_dailyWorklogEntries = swg_dailyWorklogEntries.filter(e => e.id != entryId); swg_renderDailyLogTable(); } } function swg_renderDailyLogTable() { const currentDate = document.getElementById('swg_logDate').value; const tbody = document.getElementById('swg_dailyLogTable')?.getElementsByTagName('tbody')[0]; if (!tbody) return; tbody.innerHTML = ''; const entriesForDate = swg_dailyWorklogEntries.filter(e => e.date === currentDate).sort((a,b) => a.startTime.localeCompare(b.startTime)); let totalMinutesToday = 0; const categoryTimes = {}; if (entriesForDate.length === 0) { tbody.innerHTML = `No work logged for this date.`; } else { entriesForDate.forEach(entry => { totalMinutesToday += entry.durationMinutes; categoryTimes[entry.category] = (categoryTimes[entry.category] || 0) + entry.durationMinutes; const row = tbody.insertRow(); row.insertCell().textContent = entry.description; row.insertCell().textContent = entry.category; row.insertCell().textContent = entry.startTime; row.insertCell().textContent = entry.endTime; row.insertCell().textContent = swg_formatMinutesToHHMM(entry.durationMinutes); row.insertCell().textContent = entry.notes || '-'; const actionsCell = row.insertCell(); actionsCell.innerHTML = ``; }); } document.getElementById('swg_logTotalTime').textContent = swg_formatMinutesToHHMM(totalMinutesToday); const categorySummaryDiv = document.getElementById('swg_logCategorySummary'); categorySummaryDiv.innerHTML = '
Time by Category:
'; if (Object.keys(categoryTimes).length > 0) { const ul = document.createElement('ul'); ul.style.paddingLeft = '20px'; ul.style.fontSize = '0.9em'; Object.entries(categoryTimes).sort((a,b)=>b[1]-a[1]).forEach(([cat, min]) => { // Sort by time desc const li = document.createElement('li'); li.textContent = `${cat}: ${swg_formatMinutesToHHMM(min)}`; ul.appendChild(li); }); categorySummaryDiv.appendChild(ul); } else { categorySummaryDiv.innerHTML += '

No categories logged.

'; } } // PDF Download function swg_downloadPDF() { const logDate = document.getElementById('swg_logDate').value; const entriesForDate = swg_dailyWorklogEntries.filter(e => e.date === logDate).sort((a,b) => a.startTime.localeCompare(b.startTime)); if (entriesForDate.length === 0) { alert("No worklog entries for this date to download."); return; } const doc = new jsPDF(); const primaryColorPDF = getComputedStyle(document.documentElement).getPropertyValue('--primary-color').trim(); const textColorPDF = getComputedStyle(document.documentElement).getPropertyValue('--text-color').trim(); const whiteColorPDF = '#FFFFFF'; doc.setFontSize(18); doc.setTextColor(primaryColorPDF); doc.text("Daily Worklog Report", 14, 20); doc.setFontSize(10); doc.setTextColor(textColorPDF); doc.text(`Date: ${logDate}`, 14, 28); doc.text(`Generated On: ${SWG_GENERATED_ON_STRING}`, 14, 33); let currentY = 45; let totalMinutes = 0; const categoryTimesPDF = {}; entriesForDate.forEach(entry => { totalMinutes += entry.durationMinutes; categoryTimesPDF[entry.category] = (categoryTimesPDF[entry.category] || 0) + entry.durationMinutes; }); doc.setFontSize(12); doc.setFont(undefined, 'bold'); doc.setTextColor(primaryColorPDF); doc.text("Summary:", 14, currentY); currentY += 7; doc.setFontSize(10); doc.setFont(undefined, 'normal'); doc.setTextColor(textColorPDF); doc.text(`Total Hours Logged: ${swg_formatMinutesToHHMM(totalMinutes)}`, 16, currentY); currentY += 7; doc.setFont(undefined, 'bold'); doc.text("Time by Category/Project:", 16, currentY); currentY +=6; doc.setFont(undefined, 'normal'); if (Object.keys(categoryTimesPDF).length > 0) { Object.entries(categoryTimesPDF).sort((a,b)=>b[1]-a[1]).forEach(([cat, min]) => { if (currentY > 270) { doc.addPage(); currentY = 20;} doc.text(`- ${cat}: ${swg_formatMinutesToHHMM(min)}`, 18, currentY); currentY +=5; }); } else { doc.text("- No categories logged.", 18, currentY); currentY +=5; } currentY += 5; doc.setFontSize(12); doc.setFont(undefined, 'bold'); doc.setTextColor(primaryColorPDF); if (currentY > 250) { doc.addPage(); currentY = 20; } doc.text("Detailed Worklog:", 14, currentY); currentY += 7; const tableData = entriesForDate.map(e => [ e.description, e.category, e.startTime, e.endTime, swg_formatMinutesToHHMM(e.durationMinutes), e.notes || '-' ]); doc.autoTable({ startY: currentY, head: [['Description', 'Category/Project', 'Start', 'End', 'Duration', 'Notes']], body: tableData, theme: 'grid', headStyles: { fillColor: primaryColorPDF, textColor: whiteColorPDF, fontSize: 9 }, styles: { fontSize: 8, cellPadding: 1.5, overflow: 'linebreak' }, columnStyles: { 0: { cellWidth: 60 }, 5: { cellWidth: 'auto'} } }); doc.save(`Daily_Worklog_${logDate}.pdf`); }
Scroll to Top