Skip to content

@W-18670330 @W-18670348 Apex and LWC reports framework #279

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/migration/related/ApexMigration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ export class ApexMigration extends BaseRelatedObjectMigration {
if (file.ext !== '.cls') continue;
try {
const apexAssementInfo = this.processApexFile(file);
if (apexAssementInfo && apexAssementInfo.diff.length === 0) continue;
if (apexAssementInfo && apexAssementInfo.diff.length < 3) continue;
fileAssessmentInfo.push(apexAssementInfo);
} catch (err) {
Logger.logger.error(`Error processing ${file.name}`);
Expand Down Expand Up @@ -116,7 +116,7 @@ export class ApexMigration extends BaseRelatedObjectMigration {
updateMessages.push('File has been updated to allow calls to Omnistudio components');
tokenUpdates.push(...tokeUpdatesForMethodCalls);
}
let difference = '';
let difference = [];
if (tokenUpdates && tokenUpdates.length > 0) {
const updatedContent = parser.rewrite(tokenUpdates);
fs.writeFileSync(file.location, parser.rewrite(tokenUpdates));
Expand All @@ -134,7 +134,7 @@ export class ApexMigration extends BaseRelatedObjectMigration {
warnings: warningMessage,
infos: updateMessages,
path: file.location,
diff: difference,
diff: JSON.stringify(difference),
};
}

Expand Down
2 changes: 1 addition & 1 deletion src/migration/related/LwcMigration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ export class LwcMigration extends BaseRelatedObjectMigration {
const path = file.location;
const name = file.name + file.ext;
const diff = processor.process(file, type, this.namespace);
if (diff !== undefined && diff !== '') {
if (diff !== undefined && diff !== '[]') {
const fileInfo: FileChangeInfo = {
path,
name,
Expand Down
32 changes: 27 additions & 5 deletions src/utils/lwcparser/fileutils/FileDiffUtil.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,16 @@
/* eslint-disable @typescript-eslint/explicit-member-accessibility */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
import * as fs from 'fs';
import { createPatch } from 'diff';
import { Logger } from '../../../utils/logger';

export class FileDiffUtil {
public getFileDiff(filename: string, originalFileContent: string, modifiedFileContent: string): string {
public getFileDiff(
filename: string,
originalFileContent: string,
modifiedFileContent: string
): Array<[string | null, string | null]> {
const patch: string = createPatch('', originalFileContent, modifiedFileContent);
try {
// Split the patch into lines
Expand All @@ -17,8 +22,8 @@ export class FileDiffUtil {
let newLineNumber = 1;
let firstPlusAlreadySkipped = false;
let firstMinusAlreadySkipped = false;
const diff: Array<[string | null, string | null]> = [];
// Initialize result as HTML string
let result = '';

patchLines.forEach((line) => {
// Parse the hunk header (e.g., @@ -2,3 +2,3 @@)
Expand All @@ -36,7 +41,7 @@ export class FileDiffUtil {
oldLineNumber++;
return;
}
result += `<div style="color: red;">- Line ${oldLineNumber}: ${this.escapeHtml(line.slice(1))}</div>`;
diff.push([line.slice(1), null]);
oldLineNumber++;
} else if (line.startsWith('+')) {
// Skip the first line difference
Expand All @@ -45,16 +50,22 @@ export class FileDiffUtil {
newLineNumber++;
return;
}
result += `<div style="color: green;">+ Line ${newLineNumber}: ${this.escapeHtml(line.slice(1))}</div>`;
diff.push([null, line.slice(1)]);
newLineNumber++;
} else if (line.startsWith(' ')) {
diff.push([line.slice(1), line.slice(1)]);
// Unchanged line, skip it
oldLineNumber++;
newLineNumber++;
}
});
const diffJson = {
fileName: filename,
diff,
};
this.appendToJsonFile('new_assessment_reports/lwc_reports/assess.json', diffJson);
// Return the result string, or an empty string if no differences
return result.trim() ? result : '';
return diff;
} catch (error) {
Logger.logger.error('Error in FileDiffUtil', error.message);
}
Expand All @@ -63,4 +74,15 @@ export class FileDiffUtil {
escapeHtml(text: string): string {
return text.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/"/g, '&quot;').replace(/'/g, '&#039;');
}

private appendToJsonFile(filePath: string, newData: Record<string, unknown>): void {
try {
const fileData = fs.existsSync(filePath) ? fs.readFileSync(filePath, 'utf8') : '[]';
const jsonData = JSON.parse(fileData);
jsonData.push(newData);
fs.writeFileSync(filePath, JSON.stringify(jsonData, null, 2), 'utf8');
} catch (error) {
Logger.logger.error('Error appending to JSON file', error.message);
}
}
}
4 changes: 2 additions & 2 deletions src/utils/lwcparser/fileutils/HtmlFileProcessor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ export class HtmlFileProcessor implements FileProcessor {
fileContent.get(FileConstant.BASE_CONTENT),
fileContent.get(FileConstant.MODIFIED_CONTENT)
);
if (type != null && type === 'migration' && diff !== '') {
if (type != null && type === 'migration' && diff.length > 0) {
fileutil.saveToFile(filePath, fileContent.get(FileConstant.MODIFIED_CONTENT));
}
return diff;
return JSON.stringify(diff);
}
}
}
2 changes: 1 addition & 1 deletion src/utils/lwcparser/fileutils/JavascriptFileProcessor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export class JavascriptFileProcessor implements FileProcessor {
if (type != null && type === 'migration') {
fileutil.saveToFile(filePath, fileContent.get(FileConstant.MODIFIED_CONTENT));
}
return diff;
return JSON.stringify(diff);
}
}
}
2 changes: 1 addition & 1 deletion src/utils/lwcparser/fileutils/XmlFileProcessor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export class XmlFileProcessor implements FileProcessor {
if (type != null && type === 'migration') {
fileutil.saveToFile(filePath, fileContent.get(FileConstant.MODIFIED_CONTENT));
}
return diff;
return JSON.stringify(diff);
}
}
}
172 changes: 172 additions & 0 deletions src/utils/resultsbuilder/ApexAssessmentReporter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
import { ApexAssessmentInfo } from '../interfaces';
import { generateHtmlTable } from '../reportGenerator/reportGenerator';
import { Filter, HeaderColumn, ReportHeaderFormat, TableColumn } from '../reportGenerator/reportInterfaces';

export class ApexAssessmentReporter {
public static generateApexAssesment(
apexAssessmentInfos: ApexAssessmentInfo[],
instanceUrl: string,
org: ReportHeaderFormat[]
): string {
// Header Columns
const headerColumn: HeaderColumn[] = [
{
label: 'Name',
key: 'name',
colspan: 1,
rowspan: 1,
subColumn: [],
},
{
label: 'File Reference',
key: 'fileReference',
colspan: 1,
rowspan: 1,
subColumn: [],
},
{
label: 'Diff',
key: 'diff',
colspan: 1,
rowspan: 1,
subColumn: [],
},
{
label: 'Comments',
key: 'comments',
colspan: 1,
rowspan: 1,
subColumn: [],
},
{
label: 'Errors',
key: 'errors',
colspan: 1,
rowspan: 1,
subColumn: [],
},
];

// Define columns
const columns: Array<TableColumn<ApexAssessmentInfo>> = [
{
key: 'name',
cell: (row: ApexAssessmentInfo): string => row.name,
filterValue: (row: ApexAssessmentInfo): string => row.name,
title: (row: ApexAssessmentInfo): string => row.name,
},
{
key: 'fileReference',
cell: (row: ApexAssessmentInfo): string => `<span><a href="${row.path}">${row.name}</a></span>`,
filterValue: (row: ApexAssessmentInfo): string => row.name,
title: (row: ApexAssessmentInfo): string => row.name,
},
{
key: 'diff',
cell: (row: ApexAssessmentInfo): string => this.getDiffHTML(row.diff),
filterValue: (row: ApexAssessmentInfo): string => `Diff_${row.name}`,
title: (row: ApexAssessmentInfo): string => `Diff_${row.name}`,
},
{
key: 'comments',
cell: (row: ApexAssessmentInfo): string => this.generateMessages(row.infos),
filterValue: (row: ApexAssessmentInfo): string => row.name,
title: (row: ApexAssessmentInfo): string => row.name,
},
{
key: 'errors',
cell: (row: ApexAssessmentInfo): string => this.generateMessages(row.warnings),
filterValue: (row: ApexAssessmentInfo): string => row.name,
title: (row: ApexAssessmentInfo): string => row.name,
},
];

const filters: Filter[] = [
{
label: 'Comments',
key: 'comments',
filterOptions: Array.from(new Set(apexAssessmentInfos.map((row: ApexAssessmentInfo) => row.infos.join(', ')))),
},
{
label: 'Errors',
key: 'errors',
filterOptions: Array.from(
new Set(apexAssessmentInfos.map((row: ApexAssessmentInfo) => row.warnings.join(', ')))
),
},
];

// Render table
const tableHtml = generateHtmlTable(
headerColumn,
columns,
apexAssessmentInfos,
org,
filters,
undefined,
'Apex Assessment'
);
return `<div class="slds-text-heading_large">Apex Assessment Report</div>${tableHtml}`;
}

private static getDiffContent(diff: string, lineLimit = -1): string {
const diffArray: Array<[string | null, string | null]> = JSON.parse(diff) as Array<[string | null, string | null]>;
let result = '';
let originalLine = 1;
let modifiedLine = 1;
let linecount = 0;
for (const [original, modified] of diffArray) {
if (original === modified) {
result += `<div style="color: black;">• Line ${modifiedLine}: ${original}</div>`;
modifiedLine++;
originalLine++;
linecount++;
} else if (original !== null && modified === null) {
result += `<div style="color: red;">- Line ${originalLine}: ${original}</div>`;
originalLine++;
linecount++;
} else if (original === null && modified !== null) {
result += `<div style="color: green;">+ Line ${modifiedLine}: ${modified}</div>`;
modifiedLine++;
linecount++;
}
if (linecount >= lineLimit && lineLimit !== -1) {
result += '<div style="color: black;">..........</div>';
break;
}
}
return result;
}

private static getDiffHTML(diff: string): string {
const diffArray: Array<[string | null, string | null]> = JSON.parse(diff) as Array<[string | null, string | null]>;
let result = '<div style="height: 120px; text-align: left; overflow-x: auto;">';
if (diffArray.length <= 6) {
result += this.getDiffContent(diff);
result += '</div>';
} else {
result += this.getDiffContent(diff, 6);
result += '</div>';
result +=
'<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css">';
result +=
'<button onclick="document.getElementById(\'myModal\').style.display=\'flex\'" style="position: absolute; top: 5px; right: 5px; width: 30px; height: 30px; opacity: 0.7;"><i class="fa-solid fa-up-right-and-down-left-from-center"></i></button>';
result += `<div id="myModal" style="display: none; position: fixed; z-index: 1000; left: 0; top: 0; width: 100%; height: 100%; overflow: auto; background-color: rgba(0,0,0,0.4); align-items: center; justify-content: center;">
<div style="background-color: #fff; margin: auto; padding: 20px; width: 60%; height: 60%; box-shadow: 0 5px 15px rgba(0,0,0,.5); border-radius: 4px; text-align: left; position: relative;">
<span onclick="document.getElementById('myModal').style.display='none'" style="color: #222121; height: 30px; width: 30px; position: absolute; background-color: #fff; top: -35px; right: 0; font-size: 25px; cursor: pointer; display: flex; align-items: center; justify-content: center; border-radius: 3px;">&times;</span>
<h2 style="margin-top: 0; border-bottom: 1px solid #ddd; padding-bottom: 10px; text-align: center; font-size: 18px;">Summary</h2>
<p style="margin-top: 20px;">${this.getDiffContent(diff, -1)}</p>
</div>
</div>`;
}
return result;
}

private static generateMessages(messages: string[]): string {
let messageBody = '';
for (const message of messages) {
messageBody += `<li class="slds-item slds-text-color_destructive">${message}</li>`;
}
return messageBody;
}
}
Loading