Skip to content

Commit 8c37c5d

Browse files
authored
Merge pull request #6 from OpenForgeProject/refactoring-logic
feat: refactor Magento project selection and improve button visibility logic
2 parents 424e745 + 42d4286 commit 8c37c5d

File tree

4 files changed

+183
-144
lines changed

4 files changed

+183
-144
lines changed

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how
1414

1515
### Changed
1616

17-
- update "Delete Logfiles" button visibility based on log file presence
17+
- Update "Delete Logfiles" button visibility based on log file presence
18+
- Refactored the Extention to improve Extention readability, performance and maintainability
1819

1920
## [1.3.0] - 2024-11-19
2021

src/extension.ts

Lines changed: 4 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,12 @@
11
import * as vscode from 'vscode';
2-
import * as path from 'path';
3-
import * as fs from 'fs';
4-
import { LogViewerProvider } from './logViewer';
2+
import { promptMagentoProjectSelection, showErrorMessage, activateExtension, isValidPath } from './helpers';
53

6-
export function activate(context: vscode.ExtensionContext) {
4+
export function activate(context: vscode.ExtensionContext): void {
75
const config = vscode.workspace.getConfiguration();
86
const isMagentoProject = config.get<string>('magentoLogViewer.isMagentoProject', 'Please select');
97

108
if (isMagentoProject === 'Please select') {
11-
vscode.window.showInformationMessage('Is this a Magento project?', 'Yes', 'No').then(selection => {
12-
if (selection === 'Yes') {
13-
selectMagentoRootFolder(config, context);
14-
} else {
15-
updateConfig(config, 'magentoLogViewer.isMagentoProject', selection);
16-
}
17-
});
9+
promptMagentoProjectSelection(config, context);
1810
} else if (isMagentoProject === 'Yes') {
1911
const magentoRoot = config.get<string>('magentoLogViewer.magentoRoot', '');
2012
if (!magentoRoot || !isValidPath(magentoRoot)) {
@@ -25,114 +17,5 @@ export function activate(context: vscode.ExtensionContext) {
2517
}
2618
}
2719

28-
function selectMagentoRootFolder(config: vscode.WorkspaceConfiguration, context: vscode.ExtensionContext) {
29-
vscode.window.showInformationMessage('Please select the Magento root folder.', 'Select Magento Root Folder').then(buttonSelection => {
30-
if (buttonSelection === 'Select Magento Root Folder') {
31-
const workspaceFolders = vscode.workspace.workspaceFolders;
32-
const defaultUri = workspaceFolders && workspaceFolders.length > 0 ? workspaceFolders[0].uri : undefined;
33-
vscode.window.showOpenDialog({ defaultUri, canSelectFolders: true, canSelectMany: false, openLabel: 'Select Magento Root Folder' }).then(folderUri => {
34-
if (folderUri?.[0]) {
35-
updateConfig(config, 'magentoLogViewer.magentoRoot', folderUri[0].fsPath).then(() => {
36-
showInformationMessage('Magento root folder successfully saved!');
37-
updateConfig(config, 'magentoLogViewer.isMagentoProject', 'Yes');
38-
activateExtension(context, folderUri[0].fsPath);
39-
});
40-
}
41-
});
42-
}
43-
});
44-
}
45-
46-
function updateConfig(config: vscode.WorkspaceConfiguration, key: string, value: unknown) {
47-
return config.update(key, value, vscode.ConfigurationTarget.Workspace);
48-
}
49-
50-
function showInformationMessage(message: string) {
51-
try {
52-
vscode.window.showInformationMessage(message);
53-
} catch (error) {
54-
console.error('Failed to show information message:', error instanceof Error ? error.message : String(error));
55-
}
56-
}
57-
58-
function showErrorMessage(message: string) {
59-
try {
60-
vscode.window.showErrorMessage(message);
61-
} catch (error) {
62-
console.error('Failed to show error message:', error instanceof Error ? error.message : String(error));
63-
}
64-
}
65-
66-
function activateExtension(context: vscode.ExtensionContext, magentoRoot: string) {
67-
const logViewerProvider = new LogViewerProvider(magentoRoot);
68-
const treeView = vscode.window.createTreeView('logFiles', { treeDataProvider: logViewerProvider });
69-
70-
vscode.commands.registerCommand('magento-log-viewer.refreshLogFiles', () => logViewerProvider.refresh());
71-
vscode.commands.registerCommand('magento-log-viewer.openFile', (filePath: string, lineNumber?: number) => {
72-
if (typeof filePath === 'string') {
73-
const options: vscode.TextDocumentShowOptions = lineNumber !== undefined && typeof lineNumber === 'number' ? {
74-
selection: new vscode.Range(new vscode.Position(lineNumber, 0), new vscode.Position(lineNumber, 0))
75-
} : {};
76-
vscode.window.showTextDocument(vscode.Uri.file(filePath), options);
77-
}
78-
});
79-
vscode.commands.registerCommand('magento-log-viewer.openFileAtLine', (filePath: string, lineNumber: number) => {
80-
const options: vscode.TextDocumentShowOptions = {
81-
selection: new vscode.Range(new vscode.Position(lineNumber, 0), new vscode.Position(lineNumber, 0))
82-
};
83-
vscode.window.showTextDocument(vscode.Uri.file(filePath), options);
84-
});
85-
86-
vscode.commands.registerCommand('magento-log-viewer.clearAllLogFiles', () => {
87-
vscode.window.showWarningMessage('Are you sure you want to delete all log files?', 'Yes', 'No').then(selection => {
88-
if (selection === 'Yes') {
89-
const logPath = path.join(magentoRoot, 'var', 'log');
90-
if (logViewerProvider.pathExists(logPath)) {
91-
const files = fs.readdirSync(logPath);
92-
files.forEach(file => fs.unlinkSync(path.join(logPath, file)));
93-
logViewerProvider.refresh();
94-
showInformationMessage('All log files have been cleared.');
95-
} else {
96-
showInformationMessage('No log files found to clear.');
97-
}
98-
}
99-
});
100-
});
101-
102-
context.subscriptions.push(treeView);
103-
104-
// Update the badge count
105-
const updateBadge = () => {
106-
const logFiles = logViewerProvider.getLogFilesWithoutUpdatingBadge(path.join(magentoRoot, 'var', 'log'));
107-
const totalEntries = logFiles.reduce((count, file) => count + parseInt(file.description?.match(/\d+/)?.[0] || '0', 10), 0);
108-
treeView.badge = { value: totalEntries, tooltip: `${totalEntries} log entries` };
109-
110-
// Enable or disable the "Delete Logfiles" button based on the presence of log files
111-
vscode.commands.executeCommand('setContext', 'magentoLogViewer.hasLogFiles', totalEntries > 0);
112-
};
113-
114-
logViewerProvider.onDidChangeTreeData(updateBadge);
115-
updateBadge();
116-
117-
vscode.commands.executeCommand('setContext', 'magentoLogViewerBadge', 0);
118-
119-
// Watch for changes in the log directory
120-
const logPath = path.join(magentoRoot, 'var', 'log');
121-
const watcher = vscode.workspace.createFileSystemWatcher(new vscode.RelativePattern(logPath, '*'));
122-
watcher.onDidChange(() => logViewerProvider.refresh());
123-
watcher.onDidCreate(() => logViewerProvider.refresh());
124-
watcher.onDidDelete(() => logViewerProvider.refresh());
125-
126-
context.subscriptions.push(watcher);
127-
}
128-
129-
function isValidPath(filePath: string): boolean {
130-
try {
131-
return fs.existsSync(filePath) && fs.lstatSync(filePath).isDirectory();
132-
} catch (error) {
133-
return false;
134-
}
135-
}
136-
13720
// This method is called when your extension is deactivated
138-
export function deactivate() {}
21+
export function deactivate(): void {}

src/helpers.ts

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
import * as vscode from 'vscode';
2+
import * as path from 'path';
3+
import * as fs from 'fs';
4+
import { LogViewerProvider } from './logViewer';
5+
6+
// Prompts the user to confirm if the current project is a Magento project.
7+
export function promptMagentoProjectSelection(config: vscode.WorkspaceConfiguration, context: vscode.ExtensionContext): void {
8+
vscode.window.showInformationMessage('Is this a Magento project?', 'Yes', 'No').then(selection => {
9+
if (selection === 'Yes') {
10+
selectMagentoRootFolder(config, context);
11+
} else {
12+
updateConfig(config, 'magentoLogViewer.isMagentoProject', selection);
13+
}
14+
});
15+
}
16+
17+
// Prompts the user to select the Magento root folder and updates the configuration.
18+
export function selectMagentoRootFolder(config: vscode.WorkspaceConfiguration, context: vscode.ExtensionContext): void {
19+
vscode.window.showInformationMessage('Please select the Magento root folder.', 'Select Magento Root Folder').then(buttonSelection => {
20+
if (buttonSelection === 'Select Magento Root Folder') {
21+
const workspaceFolders = vscode.workspace.workspaceFolders;
22+
const defaultUri = workspaceFolders && workspaceFolders.length > 0 ? workspaceFolders[0].uri : undefined;
23+
vscode.window.showOpenDialog({ defaultUri, canSelectFolders: true, canSelectMany: false, openLabel: 'Select Magento Root Folder' }).then(folderUri => {
24+
if (folderUri?.[0]) {
25+
updateConfig(config, 'magentoLogViewer.magentoRoot', folderUri[0].fsPath).then(() => {
26+
showInformationMessage('Magento root folder successfully saved!');
27+
updateConfig(config, 'magentoLogViewer.isMagentoProject', 'Yes');
28+
activateExtension(context, folderUri[0].fsPath);
29+
});
30+
}
31+
});
32+
}
33+
});
34+
}
35+
36+
// Updates the specified configuration key with the given value.
37+
export function updateConfig(config: vscode.WorkspaceConfiguration, key: string, value: unknown): Thenable<void> {
38+
return config.update(key, value, vscode.ConfigurationTarget.Workspace);
39+
}
40+
41+
// Displays an information message to the user.
42+
export function showInformationMessage(message: string): void {
43+
try {
44+
vscode.window.showInformationMessage(message);
45+
} catch (error) {
46+
console.error('Failed to show information message:', error instanceof Error ? error.message : String(error));
47+
}
48+
}
49+
50+
// Displays an error message to the user.
51+
export function showErrorMessage(message: string): void {
52+
try {
53+
vscode.window.showErrorMessage(message);
54+
} catch (error) {
55+
console.error('Failed to show error message:', error instanceof Error ? error.message : String(error));
56+
}
57+
}
58+
59+
// Activates the extension by setting up the log viewer and file system watcher.
60+
export function activateExtension(context: vscode.ExtensionContext, magentoRoot: string): void {
61+
const logViewerProvider = new LogViewerProvider(magentoRoot);
62+
const treeView = vscode.window.createTreeView('logFiles', { treeDataProvider: logViewerProvider });
63+
64+
registerCommands(context, logViewerProvider, magentoRoot);
65+
context.subscriptions.push(treeView);
66+
67+
updateBadge(treeView, logViewerProvider, magentoRoot);
68+
69+
const logPath = path.join(magentoRoot, 'var', 'log');
70+
const watcher = vscode.workspace.createFileSystemWatcher(new vscode.RelativePattern(logPath, '*'));
71+
watcher.onDidChange(() => logViewerProvider.refresh());
72+
watcher.onDidCreate(() => logViewerProvider.refresh());
73+
watcher.onDidDelete(() => logViewerProvider.refresh());
74+
75+
context.subscriptions.push(watcher);
76+
}
77+
78+
// Registers commands for the extension.
79+
export function registerCommands(context: vscode.ExtensionContext, logViewerProvider: LogViewerProvider, magentoRoot: string): void {
80+
vscode.commands.registerCommand('magento-log-viewer.refreshLogFiles', () => logViewerProvider.refresh());
81+
vscode.commands.registerCommand('magento-log-viewer.openFile', (filePath: string, lineNumber?: number) => {
82+
openFile(filePath, lineNumber);
83+
});
84+
vscode.commands.registerCommand('magento-log-viewer.openFileAtLine', (filePath: string, lineNumber: number) => {
85+
openFile(filePath, lineNumber);
86+
});
87+
vscode.commands.registerCommand('magento-log-viewer.clearAllLogFiles', () => {
88+
clearAllLogFiles(logViewerProvider, magentoRoot);
89+
});
90+
}
91+
92+
// Opens a file in the editor at the specified line number.
93+
export function openFile(filePath: string, lineNumber?: number): void {
94+
if (typeof filePath === 'string') {
95+
const options: vscode.TextDocumentShowOptions = lineNumber !== undefined && typeof lineNumber === 'number' ? {
96+
selection: new vscode.Range(new vscode.Position(lineNumber, 0), new vscode.Position(lineNumber, 0))
97+
} : {};
98+
vscode.window.showTextDocument(vscode.Uri.file(filePath), options);
99+
}
100+
}
101+
102+
// Clears all log files in the Magento log directory.
103+
export function clearAllLogFiles(logViewerProvider: LogViewerProvider, magentoRoot: string): void {
104+
vscode.window.showWarningMessage('Are you sure you want to delete all log files?', 'Yes', 'No').then(selection => {
105+
if (selection === 'Yes') {
106+
const logPath = path.join(magentoRoot, 'var', 'log');
107+
if (logViewerProvider.pathExists(logPath)) {
108+
const files = fs.readdirSync(logPath);
109+
files.forEach(file => fs.unlinkSync(path.join(logPath, file)));
110+
logViewerProvider.refresh();
111+
showInformationMessage('All log files have been cleared.');
112+
} else {
113+
showInformationMessage('No log files found to clear.');
114+
}
115+
}
116+
});
117+
}
118+
119+
// Updates the badge count for the tree view based on the number of log entries.
120+
export function updateBadge(treeView: vscode.TreeView<unknown>, logViewerProvider: LogViewerProvider, magentoRoot: string): void {
121+
const updateBadgeCount = () => {
122+
const logFiles = logViewerProvider.getLogFilesWithoutUpdatingBadge(path.join(magentoRoot, 'var', 'log'));
123+
const totalEntries = logFiles.reduce((count, file) => count + parseInt(file.description?.match(/\d+/)?.[0] || '0', 10), 0);
124+
treeView.badge = { value: totalEntries, tooltip: `${totalEntries} log entries` };
125+
126+
vscode.commands.executeCommand('setContext', 'magentoLogViewer.hasLogFiles', totalEntries > 0);
127+
};
128+
129+
logViewerProvider.onDidChangeTreeData(updateBadgeCount);
130+
updateBadgeCount();
131+
132+
vscode.commands.executeCommand('setContext', 'magentoLogViewerBadge', 0);
133+
}
134+
135+
// Checks if the given path is a valid directory.
136+
export function isValidPath(filePath: string): boolean {
137+
try {
138+
return fs.existsSync(filePath) && fs.lstatSync(filePath).isDirectory();
139+
} catch (error) {
140+
return false;
141+
}
142+
}
143+
144+
// Checks if the given path exists.
145+
export function pathExists(p: string): boolean {
146+
try {
147+
fs.accessSync(p);
148+
} catch (err) {
149+
return false;
150+
}
151+
return true;
152+
}
153+
154+
// Returns the number of lines in the specified file.
155+
export function getLineCount(filePath: string): number {
156+
const fileContent = fs.readFileSync(filePath, 'utf-8');
157+
return fileContent.split('\n').length;
158+
}
159+
160+
// Returns the appropriate icon for the given log level.
161+
export function getIconForLogLevel(level: string): vscode.ThemeIcon {
162+
switch (level) {
163+
case 'ERROR': return new vscode.ThemeIcon('error');
164+
case 'WARN': return new vscode.ThemeIcon('warning');
165+
case 'DEBUG': return new vscode.ThemeIcon('debug');
166+
case 'INFO': return new vscode.ThemeIcon('info');
167+
default: return new vscode.ThemeIcon('circle-outline');
168+
}
169+
}

0 commit comments

Comments
 (0)