Skip to content

Commit 3c9e48c

Browse files
Jonathan ZakJonathan Zak
authored andcommitted
refactor explain graph
1 parent 6a4c4a3 commit 3c9e48c

File tree

4 files changed

+56
-91
lines changed

4 files changed

+56
-91
lines changed

src/views/cytoscape/index.ts

Lines changed: 24 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
import { ViewColumn, window } from "vscode";
2+
import * as vscode from 'vscode';
3+
import { ContextProvider } from "../../contextProvider";
24

3-
type Styles = {[key: string]: string};
5+
export type Styles = {[key: string]: string};
46

57
export interface Element {
68
data: {id: string, label: string},
7-
style: Styles
9+
style: Styles,
10+
classes: string
811
}
912

1013
export interface Edge {
@@ -36,7 +39,8 @@ export class CytoscapeGraph {
3639

3740
this.elements.push({
3841
data: {id, label: node.label},
39-
style: node.styles || {}
42+
style: node.styles || {},
43+
classes: ".l1"
4044
});
4145

4246
if (node.parent) {
@@ -50,7 +54,7 @@ export class CytoscapeGraph {
5054

5155
createView(title: string, onNodeSelected: (data: unknown) => void): any {
5256
const webview = window.createWebviewPanel(`c`, title, {viewColumn: ViewColumn.One}, {enableScripts: true, retainContextWhenHidden: true});
53-
webview.webview.html = this.getHtml();
57+
webview.webview.html = this.getHtml(webview.webview);
5458

5559
webview.webview.onDidReceiveMessage((message) => {
5660
if (message.command === 'selected') {
@@ -62,98 +66,33 @@ export class CytoscapeGraph {
6266
return webview;
6367
}
6468

65-
private getHtml(): string {
69+
private getHtml(webview: vscode.Webview): string {
70+
const data = JSON.stringify([...this.elements, ...this.edges])
71+
const context = ContextProvider.getContext()
72+
const cssUri = webview.asWebviewUri(vscode.Uri.joinPath(context.extensionUri,'src', 'views', 'cytoscape', 'media', 'explain.css'))
73+
const cytoscapeUri = webview.asWebviewUri(vscode.Uri.joinPath(context.extensionUri,'src', 'views', 'cytoscape', 'media', 'cytoscape.min.js'))
74+
const cytoscapeHtmlLabelUri = webview.asWebviewUri(vscode.Uri.joinPath(context.extensionUri,'src', 'views', 'cytoscape', 'media', 'cytoscape-node-html-label.min.js'))
75+
const explainUri = webview.asWebviewUri(vscode.Uri.joinPath(context.extensionUri,'src', 'views', 'cytoscape', 'media', 'explain.js'))
76+
77+
6678
return /*html*/`
6779
<!DOCTYPE html>
6880
<html lang="en">
6981
7082
<head>
7183
<meta charset="UTF-8">
7284
<meta name="viewport" content="width=device-width, initial-scale=1.0">
73-
<script src="https://cdnjs.cloudflare.com/ajax/libs/cytoscape/3.23.0/cytoscape.min.js"></script>
74-
<style>
75-
/* html,
76-
body {
77-
margin: 0;
78-
padding: 0;
79-
height: 100%;
80-
width: 100%;
81-
overflow: hidden;
82-
} */
83-
84-
.diagram-container {
85-
position: absolute;
86-
top: 0;
87-
left: 0;
88-
width: 100%;
89-
height: 100%;
90-
border: none;
91-
margin: 0;
92-
}
93-
</style>
85+
<link href="${cssUri}" rel="stylesheet" />
86+
<script src="${cytoscapeUri}"></script>
87+
<script src="${cytoscapeHtmlLabelUri}"></script>
88+
<script src="${explainUri}" defer></script>
89+
<script>
90+
window.data = ${data};
91+
</script>
9492
</head>
95-
9693
<body>
9794
<div class="diagram-container" id="diagramContainer"></div>
98-
99-
<script>
100-
const vscode = acquireVsCodeApi();
101-
document.addEventListener("DOMContentLoaded", function () {
102-
// Initialize Cytoscape
103-
const cy = cytoscape({
104-
container: document.getElementById('diagramContainer'),
105-
106-
elements: ${JSON.stringify([...this.elements, ...this.edges])},
107-
108-
style: [
109-
{
110-
selector: 'node',
111-
style: {
112-
'width': '120px',
113-
'height': '60px',
114-
'background-color': 'var(--vscode-list-activeSelectionBackground)',
115-
'color': 'var(--vscode-list-activeSelectionForeground)',
116-
'label': 'data(label)',
117-
'text-valign': 'center',
118-
'text-halign': 'center',
119-
'font-size': '14px',
120-
'text-wrap': 'wrap',
121-
'text-max-width': '100px'
122-
}
123-
},
124-
{
125-
selector: 'edge',
126-
style: {
127-
'width': 2,
128-
'line-color': '#5c96bc',
129-
'target-arrow-color': '#5c96bc',
130-
'target-arrow-shape': 'triangle',
131-
'curve-style': 'bezier'
132-
}
133-
}
134-
],
135-
136-
// Layout options
137-
layout: {
138-
name: 'breadthfirst',
139-
directed: true, // Directional tree
140-
padding: 10, // Padding around the graph
141-
spacingFactor: 1.5 // Spacing between nodes
142-
}
143-
});
144-
145-
// Add click event to show alert for nodes
146-
cy.on('tap', 'node', function (evt) {
147-
const id = evt.target.id();
148-
vscode.postMessage({
149-
command: 'selected',
150-
nodeId: id
151-
});
152-
});
153-
});
154-
</script>
15595
</body>
156-
15796
</html>
15897
`;
15998
}

src/views/results/explain/doveTreeDecorationProvider.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ export class DoveTreeDecorationProvider implements FileDecorationProvider {
3535
* @inheritdoc
3636
* Provides tree node decorations specific to Db2 for i Visual Explain.
3737
*/
38-
async provideFileDecoration(uri: Uri): Promise<FileDecoration | undefined> {
38+
provideFileDecoration(uri: Uri): FileDecoration | null {
3939
// Only decorate tree items tagged with the VE scheme
4040
if (uri?.scheme === doveUriScheme) {
4141
// The Uri path should simply be a number that represents the highlight attributes

src/views/results/explain/nodes.ts

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ import Statement from "../../../database/statement";
22
import { ThemeColor } from "vscode";
33
import Configuration from "../../../configuration";
44
import { DoveNodeView } from "./doveNodeView";
5+
import { Styles } from "../../cytoscape";
6+
import * as vscode from 'vscode';
7+
import * as path from 'path';
58

69
export interface ExplainNode {
710
id: number;
@@ -15,8 +18,9 @@ export interface ExplainNode {
1518
highlights: NodeHighlights;
1619
/** Context objects include advised indexes and statistics */
1720
contextObjects: ContextObject[];
18-
/** Context to set when displaying this node, used to identify additional actions */
21+
/** Context to set when displaying t;his node, used to identify additional actions */
1922
nodeContext: string;
23+
styles: Styles
2024
}
2125

2226
export interface ExplainProperty {
@@ -54,10 +58,21 @@ export class ExplainTree {
5458
public get(): ExplainNode {
5559
return this.topNode;
5660
}
61+
62+
private setNodeShape(node: ExplainNode, shape:string){
63+
node.styles["shape"] = shape
64+
}
65+
66+
private setBackgroundImage(node: ExplainNode, imagePath:string){
67+
node.styles['background-image'] = imagePath
68+
69+
}
5770

5871
private processNode(index: number): ExplainNode {
59-
let node = this.newNode(this.order[index]);
6072
let state = new NodeProcessingState();
73+
let node = this.newNode(this.order[index]);
74+
this.setNodeShape(node, "roundrectangle");
75+
// this.setBackgroundImage(node, `url("../../../../media/explain/racing-finish-svgrepo-com.svg")`)
6176

6277
for (const data of this.flatNodes[node.id]) {
6378
// When a DELTA_ATTRIBUTES_INDICATOR row is encountered, the rows following it provide new values for previously processed attributes,
@@ -201,7 +216,8 @@ export class ExplainTree {
201216
tooltipProps: [],
202217
highlights: new NodeHighlights(),
203218
contextObjects: [],
204-
nodeContext: ``
219+
nodeContext: ``,
220+
styles: {}
205221
};
206222
}
207223

src/views/results/index.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { ObjectRef, ParsedEmbeddedStatement, StatementGroup, StatementType } fro
1010
import Statement from "../../language/sql/statement";
1111
import { ExplainNode, ExplainTree } from "./explain/nodes";
1212
import { DoveNodeView, PropertyNode } from "./explain/doveNodeView";
13-
import { DoveTreeDecorationProvider } from "./explain/doveTreeDecorationProvider";
13+
import { DoveTreeDecorationProvider, toDoveTreeDecorationProviderUri } from "./explain/doveTreeDecorationProvider";
1414
import { ResultSetPanelProvider, SqlParameter } from "./resultSetPanelProvider";
1515
import { generateSqlForAdvisedIndexes } from "./explain/advice";
1616
import { updateStatusBar } from "../jobManager/statusBar";
@@ -389,9 +389,10 @@ async function runHandler(options?: StatementInfo) {
389389

390390
function addNode(node: ExplainNode, parent?: string) {
391391
const id = graph.addNode({
392-
label: node.title,
392+
label: ` ${node.title}`,
393393
parent: parent,
394394
data: node,
395+
styles: node.styles
395396
});
396397

397398
if (node.children) {
@@ -401,6 +402,15 @@ async function runHandler(options?: StatementInfo) {
401402
}
402403
}
403404

405+
const uri = toDoveTreeDecorationProviderUri(topLevel.highlights);
406+
const decoration = doveTreeDecorationProvider.provideFileDecoration(uri)
407+
// if (decoration?.color){
408+
// topLevel.styles["background-color"] = decoration.color.id;
409+
// topLevel.styles["shape"] = "rectangle"
410+
// }
411+
// topLevel.styles["shape"] = "rectangle"
412+
413+
404414
addNode(topLevel);
405415

406416
const webview = graph.createView(`Explain Graph`, (data: ExplainNode) => {

0 commit comments

Comments
 (0)