Skip to content

Commit f193222

Browse files
@W-18670330 @W-18670348 Apex and LWC reports framework (#279)
1 parent 26a0592 commit f193222

File tree

12 files changed

+424
-154
lines changed

12 files changed

+424
-154
lines changed

src/javascripts/reportGeneratorUtility.js

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@ function toggleFilterDropdown() {
1010
}
1111
}
1212

13+
function toggleDiffModal(name) {
14+
const modal = document.getElementById(`myModal_${name}`);
15+
modal.style.display = modal.style.display === 'none' ? 'flex' : 'none';
16+
}
17+
1318
function filterAndSearchTable() {
1419
const table = document.getElementById('filterable-table-body');
1520
const checkboxes = document.querySelectorAll('.filter-checkbox');
@@ -30,18 +35,22 @@ function filterAndSearchTable() {
3035
const noRowsMessage = document.getElementById('no-rows-message');
3136

3237
// NEW: If any filter group has zero selected values → show no rows
33-
const activeFilterKeys = [...new Set([...checkboxes].map(cb => cb.getAttribute('data-filter-key')))];
38+
const activeFilterKeys = [...new Set([...checkboxes].map((cb) => cb.getAttribute('data-filter-key')))];
3439
const hasEmptyGroup = activeFilterKeys.some((key) => !filters[key] || filters[key].length === 0);
3540
if (hasEmptyGroup) {
3641
// Hide all rows and show no match message
3742
rows.forEach((row) => {
3843
if (row.id !== 'no-rows-message') row.style.display = 'none';
3944
});
4045
if (noRowsMessage) noRowsMessage.style.display = '';
41-
46+
4247
// Update visible row count
43-
const visibleRows = Array.from(table.rows).filter(row => row.style.display !== 'none' && row.id !== 'no-rows-message');
44-
document.getElementById('row-count').textContent = `Showing ${visibleRows.length} record${visibleRows.length !== 1 ? 's' : ''}`;
48+
const visibleRows = Array.from(table.rows).filter(
49+
(row) => row.style.display !== 'none' && row.id !== 'no-rows-message'
50+
);
51+
document.getElementById('row-count').textContent = `Showing ${visibleRows.length} record${
52+
visibleRows.length !== 1 ? 's' : ''
53+
}`;
4554
return;
4655
}
4756

@@ -54,9 +63,7 @@ function filterAndSearchTable() {
5463
// Apply checkbox filters
5564
for (const key of Object.keys(filters)) {
5665
const selectedValues = filters[key];
57-
const cell = Array.from(row.cells).find(
58-
(c) => c.getAttribute('key') === key
59-
);
66+
const cell = Array.from(row.cells).find((c) => c.getAttribute('key') === key);
6067
const cellValue = cell?.getAttribute('value') || '';
6168
if (!selectedValues.includes(cellValue)) {
6269
show = false;
@@ -82,8 +89,12 @@ function filterAndSearchTable() {
8289
}
8390

8491
// Update visible row count
85-
const visibleRows = Array.from(table.rows).filter(row => row.style.display !== 'none' && row.id !== 'no-rows-message');
86-
document.getElementById('row-count').textContent = `Showing ${visibleRows.length} record${visibleRows.length !== 1 ? 's' : ''}`;
92+
const visibleRows = Array.from(table.rows).filter(
93+
(row) => row.style.display !== 'none' && row.id !== 'no-rows-message'
94+
);
95+
document.getElementById('row-count').textContent = `Showing ${visibleRows.length} record${
96+
visibleRows.length !== 1 ? 's' : ''
97+
}`;
8798
}
8899

89100
// Expose globally so HTML inline event handlers can access them

src/migration/related/ApexMigration.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ export class ApexMigration extends BaseRelatedObjectMigration {
7777
if (file.ext !== '.cls') continue;
7878
try {
7979
const apexAssementInfo = this.processApexFile(file);
80-
if (apexAssementInfo && apexAssementInfo.diff.length === 0) continue;
80+
if (apexAssementInfo && apexAssementInfo.diff.length < 3) continue;
8181
fileAssessmentInfo.push(apexAssementInfo);
8282
} catch (err) {
8383
Logger.logger.error(`Error processing ${file.name}`);
@@ -116,7 +116,7 @@ export class ApexMigration extends BaseRelatedObjectMigration {
116116
updateMessages.push('File has been updated to allow calls to Omnistudio components');
117117
tokenUpdates.push(...tokeUpdatesForMethodCalls);
118118
}
119-
let difference = '';
119+
let difference = [];
120120
if (tokenUpdates && tokenUpdates.length > 0) {
121121
const updatedContent = parser.rewrite(tokenUpdates);
122122
fs.writeFileSync(file.location, parser.rewrite(tokenUpdates));
@@ -134,7 +134,7 @@ export class ApexMigration extends BaseRelatedObjectMigration {
134134
warnings: warningMessage,
135135
infos: updateMessages,
136136
path: file.location,
137-
diff: difference,
137+
diff: JSON.stringify(difference),
138138
};
139139
}
140140

src/migration/related/LwcMigration.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ export class LwcMigration extends BaseRelatedObjectMigration {
8181
const path = file.location;
8282
const name = file.name + file.ext;
8383
const diff = processor.process(file, type, this.namespace);
84-
if (diff !== undefined && diff !== '') {
84+
if (diff !== undefined && diff !== '[]') {
8585
const fileInfo: FileChangeInfo = {
8686
path,
8787
name,

src/styles/reportGenerator.css

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
/* === Filter Header & Toggle === */
2+
3+
@import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css');
4+
25
.filter-header {
36
display: flex;
47
align-items: center;
@@ -217,3 +220,66 @@ tbody tr td {
217220
html {
218221
background: #f8f8f8;
219222
}
223+
224+
.diffModal {
225+
display: none;
226+
position: fixed;
227+
z-index: 1000;
228+
left: 0;
229+
top: 0;
230+
width: 100%;
231+
height: 100%;
232+
overflow: auto;
233+
background-color: rgba(0, 0, 0, 0.4);
234+
align-items: center;
235+
justify-content: center;
236+
}
237+
238+
.diffModalContent {
239+
background-color: #fff;
240+
margin: auto;
241+
padding: 20px;
242+
width: 60%;
243+
height: 60%;
244+
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);
245+
border-radius: 4px;
246+
text-align: left;
247+
position: relative;
248+
}
249+
250+
.closeButton {
251+
color: #222121;
252+
height: 30px;
253+
width: 30px;
254+
position: absolute;
255+
background-color: #fff;
256+
top: -35px;
257+
right: 0;
258+
font-size: 25px;
259+
cursor: pointer;
260+
display: flex;
261+
align-items: center;
262+
justify-content: center;
263+
border-radius: 3px;
264+
}
265+
266+
.modalHeader {
267+
margin-top: 0;
268+
border-bottom: 1px solid #ddd;
269+
padding-bottom: 10px;
270+
text-align: center;
271+
font-size: 18px;
272+
}
273+
274+
.modalContent {
275+
margin-top: 20px;
276+
}
277+
278+
.expandModalButton {
279+
position: absolute;
280+
top: 5px;
281+
right: 5px;
282+
width: 30px;
283+
height: 30px;
284+
opacity: 0.7;
285+
}

src/utils/interfaces.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ export interface MigratedRecordInfo {
1616
warnings: string[];
1717
}
1818

19+
export interface DiffPair {
20+
old: string | null;
21+
new: string | null;
22+
}
23+
1924
export interface LWCAssessmentInfo {
2025
name: string;
2126
changeInfos: FileChangeInfo[];

src/utils/lwcparser/fileutils/FileDiffUtil.ts

Lines changed: 62 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,64 @@
44
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
55
import { createPatch } from 'diff';
66
import { Logger } from '../../../utils/logger';
7+
import { DiffPair } from '../../interfaces';
78

89
export class FileDiffUtil {
9-
public getFileDiff(filename: string, originalFileContent: string, modifiedFileContent: string): string {
10+
public static getDiffHTML(diff: string, name: string): string {
11+
const diffArray: DiffPair[] = JSON.parse(diff) as DiffPair[];
12+
let result = '<div style="height: 120px; text-align: left; overflow-x: auto;">';
13+
if (diffArray.length <= 6) {
14+
result += this.getDiffContent(diff) + '</div>';
15+
} else {
16+
result +=
17+
this.getDiffContent(diff, 6) +
18+
'</div>' +
19+
`<button onclick="toggleDiffModal('${name}')" class="expandModalButton"><i class="fa-solid fa-up-right-and-down-left-from-center"></i></button>`;
20+
result += `<div id="myModal_${name}" class="diffModal" style="display: none;">
21+
<div class="diffModalContent">
22+
<span onclick="toggleDiffModal('${name}')" class="closeButton">&times;</span>
23+
<h2 class="modalHeader">Summary</h2>
24+
<p class="modalContent">${this.getDiffContent(diff, -1)}</p>
25+
</div>
26+
</div>`;
27+
}
28+
return result;
29+
}
30+
/*
31+
This function provides the diff html based on the diff array recieved
32+
linelimit is the number of lines we want in the html, this is required as we are showing only few lines in the table not the entire diff
33+
For the entire diff we are using modal, hence the requirement of lineLimit
34+
*/
35+
private static getDiffContent(diff: string, lineLimit = -1): string {
36+
const diffArray: DiffPair[] = JSON.parse(diff) as DiffPair[];
37+
let result = '';
38+
let originalLine = 1;
39+
let modifiedLine = 1;
40+
let linecount = 0;
41+
for (const { old: original, new: modified } of diffArray) {
42+
if (original === modified) {
43+
result += `<div style="color: black;">• Line ${modifiedLine}: ${original}</div>`;
44+
modifiedLine++;
45+
originalLine++;
46+
linecount++;
47+
} else if (original !== null && modified === null) {
48+
result += `<div style="color: red;">- Line ${originalLine}: ${original}</div>`;
49+
originalLine++;
50+
linecount++;
51+
} else if (original === null && modified !== null) {
52+
result += `<div style="color: green;">+ Line ${modifiedLine}: ${modified}</div>`;
53+
modifiedLine++;
54+
linecount++;
55+
}
56+
if (linecount >= lineLimit && lineLimit !== -1) {
57+
result += '<div style="color: black;">..........</div>';
58+
break;
59+
}
60+
}
61+
return result;
62+
}
63+
64+
public getFileDiff(filename: string, originalFileContent: string, modifiedFileContent: string): DiffPair[] {
1065
const patch: string = createPatch('', originalFileContent, modifiedFileContent);
1166
try {
1267
// Split the patch into lines
@@ -17,8 +72,8 @@ export class FileDiffUtil {
1772
let newLineNumber = 1;
1873
let firstPlusAlreadySkipped = false;
1974
let firstMinusAlreadySkipped = false;
75+
const diff: DiffPair[] = [];
2076
// Initialize result as HTML string
21-
let result = '';
2277

2378
patchLines.forEach((line) => {
2479
// Parse the hunk header (e.g., @@ -2,3 +2,3 @@)
@@ -36,7 +91,7 @@ export class FileDiffUtil {
3691
oldLineNumber++;
3792
return;
3893
}
39-
result += `<div style="color: red;">- Line ${oldLineNumber}: ${this.escapeHtml(line.slice(1))}</div>`;
94+
diff.push({ old: line.slice(1), new: null });
4095
oldLineNumber++;
4196
} else if (line.startsWith('+')) {
4297
// Skip the first line difference
@@ -45,16 +100,17 @@ export class FileDiffUtil {
45100
newLineNumber++;
46101
return;
47102
}
48-
result += `<div style="color: green;">+ Line ${newLineNumber}: ${this.escapeHtml(line.slice(1))}</div>`;
103+
diff.push({ old: null, new: line.slice(1) });
49104
newLineNumber++;
50105
} else if (line.startsWith(' ')) {
106+
diff.push({ old: line.slice(1), new: line.slice(1) });
51107
// Unchanged line, skip it
52108
oldLineNumber++;
53109
newLineNumber++;
54110
}
55111
});
56-
// Return the result string, or an empty string if no differences
57-
return result.trim() ? result : '';
112+
// Return the diff array
113+
return diff;
58114
} catch (error) {
59115
Logger.logger.error('Error in FileDiffUtil', error.message);
60116
}

src/utils/lwcparser/fileutils/HtmlFileProcessor.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@ export class HtmlFileProcessor implements FileProcessor {
2121
fileContent.get(FileConstant.BASE_CONTENT),
2222
fileContent.get(FileConstant.MODIFIED_CONTENT)
2323
);
24-
if (type != null && type === 'migration' && diff !== '') {
24+
if (type != null && type === 'migration' && diff.length > 0) {
2525
fileutil.saveToFile(filePath, fileContent.get(FileConstant.MODIFIED_CONTENT));
2626
}
27-
return diff;
27+
return JSON.stringify(diff);
2828
}
2929
}
3030
}

src/utils/lwcparser/fileutils/JavascriptFileProcessor.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ export class JavascriptFileProcessor implements FileProcessor {
2828
if (type != null && type === 'migration') {
2929
fileutil.saveToFile(filePath, fileContent.get(FileConstant.MODIFIED_CONTENT));
3030
}
31-
return diff;
31+
return JSON.stringify(diff);
3232
}
3333
}
3434
}

src/utils/lwcparser/fileutils/XmlFileProcessor.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ export class XmlFileProcessor implements FileProcessor {
2828
if (type != null && type === 'migration') {
2929
fileutil.saveToFile(filePath, fileContent.get(FileConstant.MODIFIED_CONTENT));
3030
}
31-
return diff;
31+
return JSON.stringify(diff);
3232
}
3333
}
3434
}

0 commit comments

Comments
 (0)