Skip to content

Commit 4c73ed4

Browse files
committed
A popup is now shown when the mouse pointer is hovered above an edge or a node.
It is now possible to click a node in the graphs to open the file the node is associated with.
1 parent e0817df commit 4c73ed4

14 files changed

+178
-15
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Change Log
22

3+
## Version 1.8.3
4+
5+
- When edges have the same source and target the edges no longer overlap.
6+
- A popup is now shown when the mouse pointer is hovered above an edge or a node.
7+
- It is now possible to click a node in the graphs to open the file the node is associated with.
8+
39
## Version 1.8.2
410

511
- The state of the checkbox and the dropdown boxes are now persisted.

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"displayName": "AngularTools",
55
"description": "AngularTools is a collection of tools for exploring an Angular project, help you with documenting, reverse engineering a project or help when refactoring.",
66
"icon": "logo.png",
7-
"version": "1.8.2",
7+
"version": "1.8.3",
88
"license": "MIT",
99
"repository": "https://github.com/CoderAllan/vscode-angulartools",
1010
"author": {
@@ -391,6 +391,11 @@
391391
"type": "string",
392392
"default": "Modules.md",
393393
"description": "The default name used when saving the project module to a markdown file."
394+
},
395+
"angularTools.showPopupsOverNodesAndEdges": {
396+
"type": "boolean",
397+
"default": true,
398+
"description": "When the setting is set to true a popup with various information from node or edge will be shown when the mouse pointer hovers over nodes and edges."
394399
}
395400
}
396401
}

src/commands/generateDependencyInjectionGraph.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,15 @@ export class GenerateDependencyInjectionGraph extends ShowHierarchyBase {
3131
this.addNodesAndEdges(project, this.appendNodes, this.appendEdges);
3232
this.generateAndSaveJavascriptContent(() => { });
3333
return;
34+
case 'openFile':
35+
const filename = message.text;
36+
if (this.fsUtils.fileExists(filename)) {
37+
var openPath = vscode.Uri.parse("file:///" + filename);
38+
vscode.workspace.openTextDocument(openPath).then(doc => {
39+
vscode.window.showTextDocument(doc);
40+
});
41+
}
42+
return;
3443
}
3544
},
3645
undefined,
@@ -106,10 +115,10 @@ export class GenerateDependencyInjectionGraph extends ShowHierarchyBase {
106115
let componentFilename = component.filename.replace(this.workspaceDirectory, '.');
107116
componentFilename = componentFilename.split('\\').join('/');
108117
const componentPosition = this.graphState.nodePositions[component.name];
109-
appendNodes([new Node(component.name, this.generatedComponentNode(component), componentFilename, false, NodeType.component, componentPosition)]);
118+
appendNodes([new Node(component.name, this.generatedComponentNode(component), componentFilename, component.filename, false, NodeType.component, componentPosition)]);
110119
component.dependencyInjections.forEach(injectable => {
111120
const injectablePosition = this.graphState.nodePositions[injectable.name];
112-
appendNodes([new Node(injectable.name, injectable.name, injectable.filename.replace(this.workspaceDirectory, ''), false, NodeType.injectable, injectablePosition)]);
121+
appendNodes([new Node(injectable.name, injectable.name, injectable.filename.replace(this.workspaceDirectory, ''), component.filename, false, NodeType.injectable, injectablePosition)]);
113122
appendEdges([new Edge((this.edges.length + 1).toString(), injectable.name, component.name, ArrowType.injectable)]);
114123
});
115124
});

src/commands/showComponentHierarchy.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,15 @@ export class ShowComponentHierarchy extends ShowHierarchyBase {
3434
this.addNodesAndEdges(components, this.appendNodes, this.appendEdges);
3535
this.generateAndSaveJavascriptContent(() => { });
3636
return;
37+
case 'openFile':
38+
const filename = message.text;
39+
if (this.fsUtils.fileExists(filename)) {
40+
var openPath = vscode.Uri.parse("file:///" + filename);
41+
vscode.workspace.openTextDocument(openPath).then(doc => {
42+
vscode.window.showTextDocument(doc);
43+
});
44+
}
45+
return;
3746
}
3847
},
3948
undefined,
@@ -88,7 +97,7 @@ export class ShowComponentHierarchy extends ShowHierarchyBase {
8897
let componentFilename = component.tsFilename.replace(this.directoryPath, '.');
8998
componentFilename = componentFilename.split('\\').join('/');
9099
const componentPosition = this.graphState.nodePositions[component.selector];
91-
appendNodes([new Node(component.selector, component.selector, componentFilename, isRoot, isRoot ? NodeType.rootNode : NodeType.component, componentPosition)]);
100+
appendNodes([new Node(component.selector, component.selector, componentFilename, component.tsFilename, isRoot, isRoot ? NodeType.rootNode : NodeType.component, componentPosition)]);
92101
if (components.length > 0) {
93102
components.forEach((subComponent) => {
94103
if (parentSelector !== subComponent.selector) {

src/commands/showHierarchyBase.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,19 +36,22 @@ export class ShowHierarchyBase extends CommandBase {
3636
}
3737
protected appendNodes = (nodeList: Node[]) => {
3838
nodeList.forEach(newNode => {
39+
newNode.showPopupsOverNodesAndEdges = this.config.showPopupsOverNodesAndEdges;
3940
if (!this.nodes.some(node => node.id === newNode.id)) {
4041
this.nodes.push(newNode);
4142
}
4243
else {
4344
const existingNode = this.nodes.find(node => node.id === newNode.id);
4445
if (existingNode && (!existingNode.tsFilename || existingNode.tsFilename?.length === 0) && newNode.tsFilename && newNode.tsFilename.length > 0) {
4546
existingNode.tsFilename = newNode.tsFilename;
47+
existingNode.filename = newNode.filename;
4648
}
4749
}
4850
});
4951
};
5052
protected appendEdges = (edgeList: Edge[]) => {
5153
edgeList.forEach(newEdge => {
54+
newEdge.showPopupsOverNodesAndEdges = this.config.showPopupsOverNodesAndEdges;
5255
const mutualEdges = this.edges.filter(edge => edge.target === newEdge.source && edge. source=== newEdge.target);
5356
if (mutualEdges.length > 0) {
5457
newEdge.mutualEdgeCount += 1;
@@ -158,6 +161,11 @@ export class ShowHierarchyBase extends CommandBase {
158161
cssUri = webview.asWebviewUri(cssPath);
159162
htmlContent = htmlContent.replace(this.fontAwesomeCssFilename, cssUri.toString());
160163

164+
const visJsMinCss = 'vis-network.min.css';
165+
const visCssPath = vscode.Uri.joinPath(this.extensionContext.extensionUri, 'stylesheet', visJsMinCss);
166+
const visCssUri = webview.asWebviewUri(visCssPath);
167+
htmlContent = htmlContent.replace(visJsMinCss, visCssUri.toString());
168+
161169
const nonce = this.getNonce();
162170
htmlContent = htmlContent.replace('nonce-nonce', `nonce-${nonce}`);
163171
htmlContent = htmlContent.replace(/<script /g, `<script nonce="${nonce}" `);

src/commands/showModuleHierarchy.ts

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,15 @@ export class ShowModuleHierarchy extends ShowHierarchyBase {
3131
this.addNodesAndEdges(project, this.appendNodes, this.appendEdges);
3232
this.generateAndSaveJavascriptContent(() => { });
3333
return;
34+
case 'openFile':
35+
const filename = message.text;
36+
if (this.fsUtils.fileExists(filename)) {
37+
var openPath = vscode.Uri.parse("file:///" + filename);
38+
vscode.workspace.openTextDocument(openPath).then(doc => {
39+
vscode.window.showTextDocument(doc);
40+
});
41+
}
42+
return;
3443
}
3544
},
3645
undefined,
@@ -75,19 +84,21 @@ export class ShowModuleHierarchy extends ShowHierarchyBase {
7584
private addNodesAndEdges(project: Project, appendNodes: (nodeList: Node[]) => void, appendEdges: (edgeList: Edge[]) => void) {
7685
project.modules.forEach(module => {
7786
let moduleFilename = module.filename.replace(this.workspaceDirectory, '.');
78-
moduleFilename = moduleFilename.split('\\').join('/');
87+
moduleFilename = moduleFilename.replace(/\\/g, '/');
7988
const modulePosition = this.graphState.nodePositions[module.moduleName];
80-
appendNodes([new Node(module.moduleName, module.moduleName, moduleFilename, false, NodeType.module, modulePosition)]);
89+
appendNodes([new Node(module.moduleName, module.moduleName, moduleFilename, module.filename, false, NodeType.module, modulePosition)]);
8190
module.imports.forEach(_import => {
8291
const nodeType = Node.getNodeType(project, _import);
8392
const importPosition = this.graphState.nodePositions[_import];
84-
appendNodes([new Node(_import, _import, this.getNodeFilename(_import, nodeType, project), false, nodeType, importPosition)]);
93+
const nodeFilename = this.getNodeFilename(_import, nodeType, project);
94+
appendNodes([new Node(_import, _import, nodeFilename?.replace(this.workspaceDirectory, ''), nodeFilename, false, nodeType, importPosition)]);
8595
appendEdges([new Edge((this.edges.length + 1).toString(), _import, module.moduleName, ArrowType.import)]);
8696
});
8797
module.exports.forEach(_export => {
8898
const nodeType = Node.getNodeType(project, _export);
8999
const exportPosition = this.graphState.nodePositions[_export];
90-
appendNodes([new Node(_export, _export, this.getNodeFilename(_export, nodeType, project), false, nodeType, exportPosition)]);
100+
const nodeFilename = this.getNodeFilename(_export, nodeType, project);
101+
appendNodes([new Node(_export, _export, nodeFilename?.replace(this.workspaceDirectory, ''), nodeFilename, false, nodeType, exportPosition)]);
91102
appendEdges([new Edge((this.edges.length + 1).toString(), module.moduleName, _export, ArrowType.export)]);
92103
});
93104
});
@@ -105,8 +116,10 @@ export class ShowModuleHierarchy extends ShowHierarchyBase {
105116
case (NodeType.component):
106117
nodeFilename = project.components.get(nodeName)?.filename;
107118
break;
119+
default:
120+
nodeFilename = '';
108121
}
109-
return nodeFilename?.replace(this.workspaceDirectory, '');
122+
return nodeFilename;
110123
}
111124

112125
private generateJavascriptContent(nodesJson: string, edgesJson: string) {

src/config.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,9 @@ export class Config {
7171
public get injectableEdgeColor(): string { return this.getSetting<string>('edges.exportEdgeColor', '#0288d1'); }
7272
public get usesEdgeColor(): string { return this.getSetting<string>('edges.exportEdgeColor', '#0288d1'); }
7373

74+
// Popups
75+
public get showPopupsOverNodesAndEdges(): boolean { return this.getSetting<boolean>('showPopupsOverNodesAndEdges', true); }
76+
7477
// PackageJsonToMarkdown
7578
public get packageJsonMarkdownFilename(): string { return this.getSetting<string>('packageJsonMarkdownFilename', 'ReadMe-PackagesJson.md'); }
7679

src/filesystemUtils.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,14 @@ export class FileSystemUtils {
2525
return files;
2626
}
2727

28+
public fileExists(filename: string): boolean {
29+
try{
30+
return fs.lstatSync(filename).isFile();
31+
} catch {
32+
return false;
33+
}
34+
}
35+
2836
private isDirectory(directoryName: any): boolean {
2937
return fs.lstatSync(directoryName).isDirectory();
3038
};

src/model/Edge.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export class Edge {
1414
public target: string;
1515
public arrowType: ArrowType;
1616
public mutualEdgeCount: number = 1;
17+
public showPopupsOverNodesAndEdges: boolean = true;
1718

1819
public toJsonString(): string {
1920
let arrowColorAttr = `, color: "${this.getEdgeTypeColor(this.arrowType)}"`;
@@ -27,6 +28,24 @@ export class Edge {
2728
} else {
2829
jsStringProperties.push(`smooth: false`);
2930
}
31+
if (this.showPopupsOverNodesAndEdges) {
32+
switch (this.arrowType) {
33+
case ArrowType.injectable:
34+
jsStringProperties.push(`title: "${this.source} injected into ${this.target}"`);
35+
break;
36+
case ArrowType.import:
37+
jsStringProperties.push(`title: "${this.target} imports ${this.source}"`);
38+
break;
39+
case ArrowType.export:
40+
jsStringProperties.push(`title: "${this.source} exports ${this.target}"`);
41+
break;
42+
case ArrowType.uses:
43+
jsStringProperties.push(`title: "${this.source} uses ${this.target}"`);
44+
break;
45+
default:
46+
break;
47+
}
48+
}
3049
return `{${jsStringProperties.join(', ')}}`;
3150
}
3251

0 commit comments

Comments
 (0)