@@ -1610,6 +1610,11 @@ export class EmpathyDashboardProvider implements vscode.WebviewViewProvider {
16101610 }
16111611
16121612 // Report-specific actions
1613+ if ( cmdBase === 'fix-all' ) {
1614+ // After fix-all, offer to verify with tests
1615+ actionButtons . push ( { label : 'Run Tests to Verify' , icon : '✅' , command : 'run-tests' } ) ;
1616+ actionButtons . push ( { label : 'Security Scan' , icon : '🔒' , command : 'securityScan' } ) ;
1617+ }
16131618 if ( cmdBase === 'morning' || cmdBase === 'ship' ) {
16141619 actionButtons . push ( { label : 'Run Tests' , icon : '🧪' , command : 'run-tests' } ) ;
16151620 actionButtons . push ( { label : 'Security Scan' , icon : '🔒' , command : 'securityScan' } ) ;
@@ -1701,15 +1706,31 @@ export class EmpathyDashboardProvider implements vscode.WebviewViewProvider {
17011706 </div>
17021707
17031708 <div class="section-title">📋 Report Output</div>
1704- <div class="output">${ outputHtml } </div>
1709+ <div class="output" id="report-output">${ outputHtml } </div>
1710+
1711+ <div class="section-title">📤 Export</div>
1712+ <div class="actions">
1713+ <button class="action-btn export-btn" id="btn-copy">📋 Copy to Clipboard</button>
1714+ <button class="action-btn export-btn" id="btn-save">💾 Save as File</button>
1715+ </div>
17051716
17061717 <script>
17071718 const vscode = acquireVsCodeApi();
1708- document.querySelectorAll('.action-btn').forEach(btn => {
1719+ const rawOutput = ${ JSON . stringify ( output ) } ;
1720+
1721+ document.querySelectorAll('.action-btn:not(.export-btn)').forEach(btn => {
17091722 btn.addEventListener('click', () => {
17101723 vscode.postMessage({ type: 'runCommand', command: btn.dataset.cmd });
17111724 });
17121725 });
1726+
1727+ document.getElementById('btn-copy').addEventListener('click', () => {
1728+ vscode.postMessage({ type: 'copyToClipboard', content: rawOutput });
1729+ });
1730+
1731+ document.getElementById('btn-save').addEventListener('click', () => {
1732+ vscode.postMessage({ type: 'saveToFile', content: rawOutput, title: '${ title } ' });
1733+ });
17131734 </script>
17141735</body>
17151736</html>` ;
@@ -1731,6 +1752,29 @@ export class EmpathyDashboardProvider implements vscode.WebviewViewProvider {
17311752 if ( cmdConfig ) {
17321753 await this . _runQuickAction ( cmdConfig . cmd , cmdConfig . title ) ;
17331754 }
1755+ } else if ( message . type === 'copyToClipboard' ) {
1756+ await vscode . env . clipboard . writeText ( message . content ) ;
1757+ vscode . window . showInformationMessage ( 'Report copied to clipboard' ) ;
1758+ } else if ( message . type === 'saveToFile' ) {
1759+ const workspaceFolder = vscode . workspace . workspaceFolders ?. [ 0 ] ?. uri . fsPath ;
1760+ if ( workspaceFolder ) {
1761+ const timestamp = new Date ( ) . toISOString ( ) . replace ( / [: .] / g, '-' ) . slice ( 0 , 19 ) ;
1762+ const fileName = `${ message . title . replace ( / \s + / g, '_' ) } _${ timestamp } .txt` ;
1763+ const filePath = path . join ( workspaceFolder , '.empathy' , 'reports' , fileName ) ;
1764+
1765+ // Ensure reports directory exists
1766+ const reportsDir = path . join ( workspaceFolder , '.empathy' , 'reports' ) ;
1767+ if ( ! fs . existsSync ( reportsDir ) ) {
1768+ fs . mkdirSync ( reportsDir , { recursive : true } ) ;
1769+ }
1770+
1771+ fs . writeFileSync ( filePath , message . content ) ;
1772+ vscode . window . showInformationMessage ( `Report saved to ${ fileName } ` ) ;
1773+
1774+ // Open the saved file
1775+ const doc = await vscode . workspace . openTextDocument ( filePath ) ;
1776+ await vscode . window . showTextDocument ( doc , { preview : false } ) ;
1777+ }
17341778 }
17351779 } ) ;
17361780 }
0 commit comments