Files
checkcle/application/src/services/incident/pdf/sections.ts
T

201 lines
6.1 KiB
TypeScript

import jsPDF from 'jspdf';
import { IncidentItem } from '../types';
import { fonts, formatDate, capitalize } from './utils';
import autoTable from 'jspdf-autotable';
/**
* Add the incident overview section to the PDF
*/
export const addBasicInfoSection = (doc: jsPDF, incident: IncidentItem, yPos: number): number => {
doc.setFont(fonts.bold);
doc.setFontSize(14);
doc.setTextColor(30, 64, 175); // Blue-800
doc.text('Incident Overview', 15, yPos);
// Draw a line under the heading
doc.line(15, yPos + 2, 195, yPos + 2);
yPos += 10;
// Basic information table
autoTable(doc, {
startY: yPos,
head: [['Field', 'Information']],
body: [
['ID', incident.id],
['Status', capitalize(incident.status || 'Unknown')],
['Priority', capitalize(incident.priority || 'Unknown')],
['Impact', capitalize(incident.impact || 'Unknown')],
['Created', formatDate(incident.created)],
['Last Updated', formatDate(incident.updated)],
],
headStyles: {
fillColor: [30, 64, 175], // Blue-800
textColor: [255, 255, 255],
fontStyle: 'bold',
},
alternateRowStyles: {
fillColor: [241, 245, 249], // Slate-100
},
margin: { left: 15, right: 15 },
});
// Return the new Y position after the table
return (doc as any).lastAutoTable.finalY + 10;
};
/**
* Add the description section to the PDF
*/
export const addDescriptionSection = (doc: jsPDF, incident: IncidentItem, yPos: number): number => {
doc.setFont(fonts.bold);
doc.setFontSize(14);
doc.setTextColor(30, 64, 175); // Blue-800
doc.text('Description', 15, yPos);
// Draw a line under the heading
doc.line(15, yPos + 2, 195, yPos + 2);
// Add incident description
doc.setFont(fonts.normal);
doc.setFontSize(10);
doc.setTextColor(0, 0, 0);
const description = incident.description || 'No description provided';
const splitDescription = doc.splitTextToSize(description, 180);
doc.text(splitDescription, 15, yPos + 10);
// Update y position after the description
return yPos + 15 + (splitDescription.length * 5);
};
/**
* Add the affected systems section to the PDF
*/
export const addAffectedSystemsSection = (doc: jsPDF, incident: IncidentItem, yPos: number): number => {
doc.setFont(fonts.bold);
doc.setFontSize(14);
doc.setTextColor(30, 64, 175); // Blue-800
doc.text('Affected Systems', 15, yPos);
// Draw a line under the heading
doc.line(15, yPos + 2, 195, yPos + 2);
// Add affected systems
doc.setFont(fonts.normal);
doc.setFontSize(10);
doc.setTextColor(0, 0, 0);
const affectedSystems = incident.affected_systems || 'None specified';
const systemsList = affectedSystems.split(',').map(system => system.trim());
let currentY = yPos + 10;
systemsList.forEach((system) => {
doc.text(`${system}`, 15, currentY);
currentY += 5;
});
return currentY + 5; // Return updated Y position with some padding
};
/**
* Add the root cause section to the PDF
*/
export const addRootCauseSection = (doc: jsPDF, incident: IncidentItem, yPos: number): number => {
doc.setFont(fonts.bold);
doc.setFontSize(14);
doc.setTextColor(30, 64, 175); // Blue-800
doc.text('Root Cause', 15, yPos);
// Draw a line under the heading
doc.line(15, yPos + 2, 195, yPos + 2);
// Add root cause
doc.setFont(fonts.normal);
doc.setFontSize(10);
doc.setTextColor(0, 0, 0);
const rootCause = incident.root_cause || 'Root cause not identified yet';
const splitRootCause = doc.splitTextToSize(rootCause, 180);
doc.text(splitRootCause, 15, yPos + 10);
// Update y position after the root cause
return yPos + 15 + (splitRootCause.length * 5);
};
/**
* Add the resolution steps section to the PDF
*/
export const addResolutionSection = (doc: jsPDF, incident: IncidentItem, yPos: number): number => {
doc.setFont(fonts.bold);
doc.setFontSize(14);
doc.setTextColor(30, 64, 175); // Blue-800
doc.text('Resolution Steps', 15, yPos);
// Draw a line under the heading
doc.line(15, yPos + 2, 195, yPos + 2);
// Create resolution data table - Using resolution_steps
const resolutionSteps = incident.resolution_steps || 'No resolution steps provided';
const splitResolutionSteps = doc.splitTextToSize(resolutionSteps, 180);
doc.setFontSize(10);
doc.setTextColor(0, 0, 0);
doc.text(splitResolutionSteps, 15, yPos + 10);
return yPos + 20 + (splitResolutionSteps.length * 5);
};
/**
* Add the assignment information section to the PDF
*/
export const addAssignmentSection = (doc: jsPDF, incident: IncidentItem, yPos: number, assignedUser?: { full_name?: string; username?: string } | null): number => {
doc.setFontSize(14);
doc.setTextColor(30, 64, 175); // Blue-800
doc.text('Assignment Information', 15, yPos);
// Draw a line under the heading
doc.line(15, yPos + 2, 195, yPos + 2);
// Add assigned user info
yPos += 10;
doc.setFontSize(10);
doc.setTextColor(0, 0, 0);
if (assignedUser) {
// Show user name if available
const userName = assignedUser.full_name || assignedUser.username || 'Unknown User';
doc.text(`Assigned to: ${userName}`, 15, yPos);
} else {
// Fallback to ID if no user data available
const assignedTo = incident.assigned_users || incident.assigned_to || 'Not assigned';
doc.text(`Assigned to: ${assignedTo}`, 15, yPos);
}
return yPos + 10;
};
/**
* Add the lessons learned section to the PDF if available
*/
export const addLessonsLearnedSection = (doc: jsPDF, incident: IncidentItem, yPos: number): number => {
if (!incident.lessons_learned) {
return yPos; // No lessons learned, return current position
}
doc.setFontSize(14);
doc.setTextColor(30, 64, 175); // Blue-800
doc.text('Lessons Learned', 15, yPos);
// Draw a line under the heading
doc.line(15, yPos + 2, 195, yPos + 2);
// Add lessons learned
const lessonsLearned = incident.lessons_learned;
const splitLessonsLearned = doc.splitTextToSize(lessonsLearned, 180);
doc.setFontSize(10);
doc.setTextColor(0, 0, 0);
doc.text(splitLessonsLearned, 15, yPos + 10);
return yPos + 15 + (splitLessonsLearned.length * 5);
};