Skip to content

Commit acf0b8c

Browse files
authored
new migration report generation with dashboard
Merge pull request #284 from snehaljha-sf/u/snehal-jha/W-18480445/migrationReport
2 parents f193222 + a08a098 commit acf0b8c

File tree

15 files changed

+758
-312
lines changed

15 files changed

+758
-312
lines changed

.gitignore

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,8 @@ out.log
4343
migrationresults.html
4444

4545
oclif.manifest.json
46-
omnistudio_migration
46+
omnistudio_migration
47+
48+
assessment_reports/
49+
migration_report/
50+
.sfdx/

src/commands/omnistudio/migration/migrate.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,8 @@ export default class Migrate extends OmniStudioBaseCommand {
174174
relatedObjectMigrationResult.apexAssessmentInfos,
175175
relatedObjectMigrationResult.lwcAssessmentInfos
176176
);
177-
await ResultsBuilder.generate(objectMigrationResults, relatedObjectMigrationResult, conn.instanceUrl);
177+
178+
await ResultsBuilder.generateReport(objectMigrationResults, relatedObjectMigrationResult, conn.instanceUrl, orgs);
178179

179180
// save timer to debug logger
180181
this.logger.debug(timer);

src/javascripts/reportGeneratorUtility.js

Lines changed: 57 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
function toggleFilterDropdown() {
2-
const dropdown = document.getElementById('filter-dropdown');
3-
const chevronUp = document.getElementById('chevron-up');
4-
const chevronDown = document.getElementById('chevron-down');
1+
function toggleFilterDropdown(tableId) {
2+
const reportTable = document.getElementById(tableId);
3+
const dropdown = reportTable.querySelector('#filter-dropdown');
4+
const chevronUp = reportTable.querySelector('#chevron-up');
5+
const chevronDown = reportTable.querySelector('#chevron-down');
56

67
if (dropdown && chevronUp && chevronDown) {
78
dropdown.classList.toggle('show');
@@ -15,10 +16,16 @@ function toggleDiffModal(name) {
1516
modal.style.display = modal.style.display === 'none' ? 'flex' : 'none';
1617
}
1718

18-
function filterAndSearchTable() {
19-
const table = document.getElementById('filterable-table-body');
20-
const checkboxes = document.querySelectorAll('.filter-checkbox');
21-
const searchInput = document.getElementById('name-search-input');
19+
function toggleDiffModal(name) {
20+
const modal = document.getElementById(`myModal_${name}`);
21+
modal.style.display = modal.style.display === 'none' ? 'flex' : 'none';
22+
}
23+
24+
function filterAndSearchTable(tableId) {
25+
const reportTable = document.getElementById(tableId);
26+
const table = reportTable.querySelector('#filterable-table-body');
27+
const checkboxes = reportTable.querySelectorAll('.filter-checkbox');
28+
const searchInput = reportTable.querySelector('#name-search-input');
2229
const searchText = searchInput.value.trim().toLowerCase();
2330
const filters = {};
2431
const rows = Array.from(table?.rows || []);
@@ -32,7 +39,7 @@ function filterAndSearchTable() {
3239
if (cb.checked) filters[key].push(cb.value);
3340
});
3441

35-
const noRowsMessage = document.getElementById('no-rows-message');
42+
const noRowsMessage = reportTable.querySelector('#no-rows-message');
3643

3744
// NEW: If any filter group has zero selected values → show no rows
3845
const activeFilterKeys = [...new Set([...checkboxes].map((cb) => cb.getAttribute('data-filter-key')))];
@@ -44,17 +51,19 @@ function filterAndSearchTable() {
4451
});
4552
if (noRowsMessage) noRowsMessage.style.display = '';
4653

54+
4755
// Update visible row count
4856
const visibleRows = Array.from(table.rows).filter(
4957
(row) => row.style.display !== 'none' && row.id !== 'no-rows-message'
5058
);
51-
document.getElementById('row-count').textContent = `Showing ${visibleRows.length} record${
59+
reportTable.querySelector('#row-count').textContent = `Showing ${visibleRows.length} record${
5260
visibleRows.length !== 1 ? 's' : ''
5361
}`;
5462
return;
5563
}
5664

5765
// Otherwise, apply filters and search
66+
let processedClasses = new Set();
5867
rows.forEach((row) => {
5968
if (row.id === 'no-rows-message') return;
6069

@@ -80,7 +89,11 @@ function filterAndSearchTable() {
8089
}
8190
}
8291

83-
row.style.display = show ? '' : 'none';
92+
// row.style.display = show ? '' : 'none';
93+
if (!processedClasses.has(row.classList[0])) {
94+
hideOrShowData(reportTable, row.classList[0], show);
95+
processedClasses.add(row.classList[0]);
96+
}
8497
if (show) visibleRowCount++;
8598
});
8699

@@ -92,11 +105,43 @@ function filterAndSearchTable() {
92105
const visibleRows = Array.from(table.rows).filter(
93106
(row) => row.style.display !== 'none' && row.id !== 'no-rows-message'
94107
);
95-
document.getElementById('row-count').textContent = `Showing ${visibleRows.length} record${
108+
reportTable.querySelector('#row-count').textContent = `Showing ${visibleRows.length} record${
96109
visibleRows.length !== 1 ? 's' : ''
97110
}`;
98111
}
99112

113+
function hideOrShowData(reportTable, rowClass, show) {
114+
const rows = Array.from(reportTable.querySelectorAll(`.${rowClass}`));
115+
rows.forEach((row) => {
116+
row.style.display = show ? '' : 'none';
117+
});
118+
}
119+
120+
document.addEventListener('DOMContentLoaded', () => {
121+
document.querySelectorAll('.collapsible-content').forEach((collapsibleContent) => {
122+
collapsibleContent.style.display = 'none';
123+
});
124+
125+
var coll = document.getElementsByClassName('collapsible');
126+
var i;
127+
128+
for (i = 0; i < coll.length; i++) {
129+
coll[i].addEventListener('click', function () {
130+
this.classList.toggle('active');
131+
var content = this.nextElementSibling;
132+
if (content.style.display === 'block') {
133+
content.style.display = 'none';
134+
} else {
135+
content.style.display = 'block';
136+
}
137+
});
138+
}
139+
140+
document.querySelectorAll('.rpt-table-container').forEach((tableContainer) => {
141+
filterAndSearchTable(tableContainer.id);
142+
});
143+
});
144+
100145
// Expose globally so HTML inline event handlers can access them
101146
window.toggleFilterDropdown = toggleFilterDropdown;
102147
window.filterAndSearchTable = filterAndSearchTable;

src/migration/related/ApexMigration.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import {
1313
TokenUpdater,
1414
} from '../../utils/apex/parser/apexparser';
1515
import { sfProject } from '../../utils/sfcli/project/sfProject';
16-
import { fileutil, File } from '../../utils/file/fileutil';
16+
import { fileutil, File } from '../../utils/file/fileUtil';
1717
import { Logger } from '../../utils/logger';
1818
import { ApexAssessmentInfo } from '../../utils';
1919
import { FileDiffUtil } from '../../utils/lwcparser/fileutils/FileDiffUtil';

src/migration/related/LwcMigration.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/* eslint-disable @typescript-eslint/no-shadow */
22
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
33
import * as shell from 'shelljs';
4-
import { fileutil, File } from '../../utils/file/fileutil';
4+
import { fileutil, File } from '../../utils/file/fileUtil';
55
import { sfProject } from '../../utils/sfcli/project/sfProject';
66
import { Logger } from '../../utils/logger';
77
import { FileProcessorFactory } from '../../utils/lwcparser/fileutils/FileProcessorFactory';

src/styles/reportGenerator.css

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,10 @@
106106
.slds-table th {
107107
position: relative;
108108
max-width: 250px;
109-
text-align: center;
109+
text-align: left;
110+
word-wrap: break-word;
111+
overflow-wrap: break-word;
112+
white-space: normal;
110113
}
111114

112115
.slds-table--bordered,
@@ -283,3 +286,51 @@ html {
283286
height: 30px;
284287
opacity: 0.7;
285288
}
289+
290+
.details-body {
291+
display: flex;
292+
flex-direction: row;
293+
gap: 10px;
294+
margin-top: 2rem;
295+
flex-wrap: wrap;
296+
}
297+
298+
.detail-row {
299+
justify-content: space-between;
300+
display: flex;
301+
flex-direction: row;
302+
gap: 10px;
303+
}
304+
305+
.slds-box {
306+
display: flex;
307+
flex-direction: column;
308+
gap: 10px;
309+
height: 14rem;
310+
min-width: 25rem;
311+
background-color: #fff;
312+
}
313+
314+
hr {
315+
margin: 1rem;
316+
}
317+
318+
.text-success {
319+
color: #2e844a;
320+
}
321+
322+
.text-error {
323+
color: #ea001e;
324+
}
325+
326+
.text-warning {
327+
color: #fe9339;
328+
}
329+
330+
.card-footer {
331+
margin-top: auto;
332+
}
333+
334+
td {
335+
border-left: 1px solid #e5e5e5;
336+
}

src/utils/file/fileutil.ts

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import * as fs from 'fs';
66
import * as path from 'path';
77
import { Logger } from '../logger';
88

9-
export class fileutil {
9+
export class fileUtil {
1010
public static readFilesSync(dir: string): File[] {
1111
const files: File[] = [];
1212
fs.readdirSync(dir).forEach((filename) => {
@@ -144,3 +144,44 @@ export class File {
144144
this.ext = ext;
145145
}
146146
}
147+
148+
/**
149+
* Copies `.js` and `.css` files from a source directory (based on `folderName`)
150+
* to a specified destination directory.
151+
*
152+
* @param folderName - The subdirectory under `/src/` where source asset files are located (e.g., `'javascripts'`, `'styles'`).
153+
* @param destDir - The absolute or relative path to the destination directory where the assets should be copied.
154+
*
155+
* @remarks
156+
* - If the destination directory does not exist, the method logs a warning and exits.
157+
* - Only `.js` and `.css` files are copied.
158+
* - The source files remain in place after copying.
159+
*/
160+
export function pushAssestUtilites(folderName: string, destDir: string): void {
161+
const sourceDir = path.join(process.cwd(), 'src', folderName);
162+
163+
if (!fs.existsSync(destDir)) {
164+
Logger.logger.warn(`Destination directory does not exist: ${destDir}`);
165+
return;
166+
}
167+
168+
try {
169+
const files = fs.readdirSync(sourceDir);
170+
171+
files.forEach((file) => {
172+
const ext = path.extname(file);
173+
if (ext === '.js' || ext === '.css') {
174+
const srcPath = path.join(sourceDir, file);
175+
const destPath = path.join(destDir, file);
176+
177+
try {
178+
fs.copyFileSync(srcPath, destPath);
179+
} catch (copyErr) {
180+
Logger.logger.error(`Error copying file ${srcPath} to ${destPath}: ${copyErr}`);
181+
}
182+
}
183+
});
184+
} catch (readDirErr) {
185+
Logger.logger.error(`Error reading directory ${sourceDir}: ${readDirErr}`);
186+
}
187+
}

src/utils/interfaces.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { File } from '../utils/file/fileutil';
1+
import { File } from '../utils/file/fileUtil';
22

33
export interface MigratedObject {
44
name: string;

src/utils/lwcparser/fileutils/HtmlFileProcessor.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/* eslint-disable @typescript-eslint/explicit-member-accessibility */
22
import { FileProcessor } from '../../../utils';
3-
import { File, fileutil } from '../../file/fileutil';
3+
import { File, fileUtil } from '../../file/fileUtil';
44
import { HTMLParser } from '../../lwcparser/htmlParser/HTMLParser';
55
import { FileConstant } from '../fileutils/FileConstant';
66
import { FileDiffUtil } from './FileDiffUtil';
@@ -22,7 +22,7 @@ export class HtmlFileProcessor implements FileProcessor {
2222
fileContent.get(FileConstant.MODIFIED_CONTENT)
2323
);
2424
if (type != null && type === 'migration' && diff.length > 0) {
25-
fileutil.saveToFile(filePath, fileContent.get(FileConstant.MODIFIED_CONTENT));
25+
fileUtil.saveToFile(filePath, fileContent.get(FileConstant.MODIFIED_CONTENT));
2626
}
2727
return JSON.stringify(diff);
2828
}

src/utils/lwcparser/fileutils/JavascriptFileProcessor.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
55
/* eslint-disable @typescript-eslint/explicit-member-accessibility */
66
import { FileProcessor } from '../../../utils';
7-
import { File, fileutil } from '../../file/fileutil';
7+
import { File, fileUtil } from '../../file/fileUtil';
88
import { JavaScriptParser } from '../../lwcparser/jsParser/JavaScriptParser';
99
import { FileConstant } from '../fileutils/FileConstant';
1010
import { FileDiffUtil } from './FileDiffUtil';
@@ -26,7 +26,7 @@ export class JavascriptFileProcessor implements FileProcessor {
2626
fileContent.get(FileConstant.MODIFIED_CONTENT)
2727
);
2828
if (type != null && type === 'migration') {
29-
fileutil.saveToFile(filePath, fileContent.get(FileConstant.MODIFIED_CONTENT));
29+
fileUtil.saveToFile(filePath, fileContent.get(FileConstant.MODIFIED_CONTENT));
3030
}
3131
return JSON.stringify(diff);
3232
}

0 commit comments

Comments
 (0)