Skip to content

Commit febe150

Browse files
AmirMohammad CheraghaliAmirMohammad Cheraghali
authored andcommitted
feat: Dark Mode Maps for PDF Report
1 parent db6b41e commit febe150

1 file changed

Lines changed: 26 additions & 28 deletions

File tree

src/utils/pdfGenerator.ts

Lines changed: 26 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -72,28 +72,29 @@ const addSection = (
7272
data: InteractionData,
7373
filterFn: (type: string | null) => boolean,
7474
isLightMode: boolean,
75-
isFirstPage = false
75+
newPage: boolean = true,
76+
startY: number = 20
7677
) => {
7778
const margin = 15;
7879

79-
80-
if (!isFirstPage) {
80+
if (newPage) {
8181
doc.addPage();
8282
}
8383

8484
// Title
8585
doc.setFont("helvetica", "bold");
8686
doc.setFontSize(16);
87-
doc.text(title, margin, 20);
87+
doc.text(title, margin, startY);
8888

8989
// 1. Generate Image
9090
const mapImg = drawMapToDataURL(data, filterFn, isLightMode);
9191

9292
// 2. Add Image
9393
const desiredImgWidth = 100; // Fixed size
9494
const desiredImgHeight = 100;
95+
const imgY = startY + 10;
9596

96-
doc.addImage(mapImg, 'PNG', margin, 30, desiredImgWidth, desiredImgHeight);
97+
doc.addImage(mapImg, 'PNG', margin, imgY, desiredImgWidth, desiredImgHeight);
9798

9899
// 3. Generate Table Data
99100
const tableRows = [] as any[];
@@ -115,7 +116,7 @@ const addSection = (
115116
// Filter Row
116117
if (filterFn(type)) {
117118
// If generic "All" view, skip 'Close Contact' logs to save space for important stuff
118-
if (title === "All Interactions" && type === "Close Contact") continue;
119+
if (title.includes("All") && type === "Close Contact") continue;
119120

120121
tableRows.push({
121122
res1: `${l1.chain}:${l1.label}`,
@@ -134,10 +135,11 @@ const addSection = (
134135
const displayRows = tableRows.slice(0, MAX_ROWS);
135136

136137
doc.setFontSize(10);
137-
doc.text(`Identified Interactions (${tableRows.length} total, top ${displayRows.length} shown)`, margin, 30 + desiredImgHeight + 10);
138+
const summaryY = imgY + desiredImgHeight + 10;
139+
doc.text(`Identified Interactions (${tableRows.length} total, top ${displayRows.length} shown)`, margin, summaryY);
138140

139141
autoTable(doc, {
140-
startY: 30 + desiredImgHeight + 15,
142+
startY: summaryY + 5,
141143
head: [['Residue A', 'Residue B', 'Dist (Å)', 'Type']],
142144
body: displayRows.map(r => [r.res1, r.res2, r.dist, r.type]),
143145
theme: 'striped',
@@ -148,41 +150,37 @@ const addSection = (
148150

149151
export const generateProteinReport = (
150152
proteinName: string,
151-
_canvasIgnored: HTMLCanvasElement, // We draw our own now
153+
_canvasIgnored: HTMLCanvasElement,
152154
data: InteractionData
153155
) => {
154156
const doc = new jsPDF();
155-
const isLightMode = true; // Force light mode for print readability? Or pass user pref? Let's assume white paper = light mode.
157+
const isLightMode = false; // Force DARK MODE for Maps (User Request)
156158

157159
// Page 1: Overview
158160
doc.setFont("helvetica", "bold");
159161
doc.setFontSize(22);
160-
doc.text("Protein Analysis Report", 15, 15);
162+
doc.text("Protein Analysis Report", 15, 20);
161163
doc.setFontSize(12);
162164
doc.setFont("helvetica", "normal");
163-
doc.text(proteinName || "Unknown Protein", 15, 22);
165+
doc.text(proteinName || "Unknown Protein", 15, 28);
164166

165-
// Section 1: All Interactions (Salt Bridges, Disulfides, Pi, Hydrophobic)
166-
// We allow everything except simple 'Close Contact' to declutter
167-
const allFilter = (t: string | null) => t !== null && t !== 'Close Contact';
168-
addSection(doc, "All Significant Interactions", data, allFilter, isLightMode, false);
169-
// Wait, first page logic is tricky with title.
170-
// Let's make "All Interactions" start below the main title.
167+
doc.line(15, 32, 195, 32);
171168

172-
// Let's redefine addSection usage slightly or just manually do Page 1.
173-
// Actually, let's just run addSection for everything and rely on auto-paging.
169+
// Section 1: All Interactions (Page 1, below header)
170+
const allFilter = (t: string | null) => t !== null && t !== 'Close Contact';
171+
addSection(doc, "All Significant Interactions", data, allFilter, isLightMode, false, 45);
174172

175-
// 1. Salt Bridge
176-
addSection(doc, "Salt Bridges (Ionic Interactions)", data, (t) => t === 'Salt Bridge', isLightMode, true); // true = don't add page first (but we have title)
173+
// 2. Salt Bridge
174+
addSection(doc, "Salt Bridges (Ionic Interactions)", data, (t) => t === 'Salt Bridge', isLightMode, true);
177175

178-
// 2. Disulfide
179-
addSection(doc, "Disulfide Bonds (Covalent)", data, (t) => t === 'Disulfide Bond', isLightMode, false);
176+
// 3. Disulfide
177+
addSection(doc, "Disulfide Bonds (Covalent)", data, (t) => t === 'Disulfide Bond', isLightMode, true);
180178

181-
// 3. Hydrophobic
182-
addSection(doc, "Hydrophobic Clusters", data, (t) => t === 'Hydrophobic Contact', isLightMode, false);
179+
// 4. Hydrophobic
180+
addSection(doc, "Hydrophobic Clusters", data, (t) => t === 'Hydrophobic Contact', isLightMode, true);
183181

184-
// 4. Pi-Stacking
185-
addSection(doc, "Pi-Stacking & Cation-Pi", data, (t) => t === 'Pi-Stacking' || t === 'Cation-Pi Interaction', isLightMode, false);
182+
// 5. Pi-Stacking
183+
addSection(doc, "Pi-Stacking & Cation-Pi", data, (t) => t === 'Pi-Stacking' || t === 'Cation-Pi Interaction', isLightMode, true);
186184

187185
// Save
188186
const safeName = proteinName.replace(/[^a-z0-9]/yi, '_').toLowerCase();

0 commit comments

Comments
 (0)