Skip to content

Commit 72d97cd

Browse files
committed
Working visual explain UX
1 parent e1d5f02 commit 72d97cd

File tree

8 files changed

+283
-90
lines changed

8 files changed

+283
-90
lines changed

package.json

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,19 @@
9292
"name": "Results",
9393
"when": "code-for-ibmi:connected == true",
9494
"contextualTitle": "IBM i"
95+
},
96+
{
97+
"type": "tree",
98+
"id": "vscode-db2i.dove.nodes",
99+
"name": "Visual Explain",
100+
"when": "vscode-db2i:explaining == true",
101+
"contextualTitle": "IBM i"
102+
},
103+
{
104+
"type": "tree",
105+
"id": "vscode-db2i.dove.node",
106+
"name": "Node Detail",
107+
"when": "vscode-db2i:explainingNode == true"
95108
}
96109
],
97110
"db2-explorer": [
@@ -328,6 +341,18 @@
328341
"title": "Delete configuration",
329342
"category": "Db2 for i",
330343
"icon": "$(trash)"
344+
},
345+
{
346+
"command": "vscode-db2i.dove.close",
347+
"title": "Close detail",
348+
"category": "Db2 for i",
349+
"icon": "$(close-all)"
350+
},
351+
{
352+
"command": "vscode-db2i.dove.nodeDetail",
353+
"title": "See detail",
354+
"category": "Db2 for i",
355+
"icon": "$(info)"
331356
}
332357
],
333358
"menus": {
@@ -375,6 +400,10 @@
375400
{
376401
"command": "vscode-db2i.jobManager.deleteConfig",
377402
"when": "never"
403+
},
404+
{
405+
"command": "vscode-db2i.dove.nodeDetail",
406+
"when": "never"
378407
}
379408
],
380409
"editor/context": [
@@ -436,6 +465,11 @@
436465
"command": "vscode-db2i.jobManager.endAll",
437466
"group": "navigation",
438467
"when": "view == jobManager"
468+
},
469+
{
470+
"command": "vscode-db2i.dove.close",
471+
"group": "navigation",
472+
"when": "view == vscode-db2i.dove.nodes"
439473
}
440474
],
441475
"view/item/context": [
@@ -553,6 +587,11 @@
553587
"command": "vscode-db2i.jobManager.deleteConfig",
554588
"when": "view == jobManager && viewItem == savedConfig",
555589
"group": "inline"
590+
},
591+
{
592+
"command": "vscode-db2i.dove.nodeDetail",
593+
"when": "view == vscode-db2i.dove.nodes && viewItem == explainTreeItem",
594+
"group": "inline"
556595
}
557596
]
558597
}

src/connection/sqlJob.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { CommandResult } from "@halcyontech/vscode-ibmi-types";
22
import { getInstance } from "../base";
33
import { ServerComponent } from "./serverComponent";
4-
import { JDBCOptions, ConnectionResult, Rows, QueryResult, JobLogEntry, CLCommandResult, VersionCheckResult, GetTraceDataResult, ServerTraceDest, ServerTraceLevel, SetConfigResult, QueryOptions } from "./types";
4+
import { JDBCOptions, ConnectionResult, Rows, QueryResult, JobLogEntry, CLCommandResult, VersionCheckResult, GetTraceDataResult, ServerTraceDest, ServerTraceLevel, SetConfigResult, QueryOptions, ExplainResults } from "./types";
55
import { Query } from "./query";
66
import { EventEmitter } from "stream";
77

@@ -214,7 +214,7 @@ export class SQLJob {
214214
return version;
215215
}
216216

217-
async explain(statement: string, type: ExplainType = ExplainType.Run) {
217+
async explain(statement: string, type: ExplainType = ExplainType.Run): Promise<ExplainResults<any>> {
218218
if (type !== ExplainType.Run) {
219219
throw new Error("TODO: support more types of explains");
220220
}
@@ -226,12 +226,13 @@ export class SQLJob {
226226
const explainRequest = {
227227
id: SQLJob.getNewUniqueId(),
228228
type: `dove`,
229-
sql: statement
229+
sql: statement,
230+
run: type === ExplainType.Run
230231
}
231232

232233
const result = await this.send(JSON.stringify(explainRequest));
233234

234-
const explainResult: any = JSON.parse(result);
235+
const explainResult: ExplainResults<any> = JSON.parse(result);
235236

236237
if (explainResult.success !== true) {
237238
this.dispose();

src/connection/types.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@ export interface VersionCheckResult extends ServerResponse {
1414
version: string;
1515
}
1616

17+
export interface ExplainResults<T> extends QueryResult<T> {
18+
veMetadata: QueryMetaData,
19+
veData: any;
20+
}
21+
1722
export interface GetTraceDataResult extends ServerResponse {
1823
tracedata: string
1924
}

src/testing/jobs.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { getInstance } from "../base";
55
import { ServerComponent } from "../connection/serverComponent";
66
import { ServerTraceDest, ServerTraceLevel } from "../connection/types";
77
import { Query } from "../connection/query";
8-
import { ExplainTree } from "../views/explain/nodes";
8+
import { ExplainTree } from "../views/results/nodes";
99

1010
export const JobsSuite: TestSuite = {
1111
name: `Connection tests`,

src/views/results/doveNodeView.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import { CancellationToken, Event, EventEmitter, ProviderResult, TreeDataProvider, TreeItem, TreeItemCollapsibleState, commands } from "vscode";
2+
import { ExplainNode, ExplainProperty } from "./nodes";
3+
4+
export class DoveNodeView implements TreeDataProvider<any> {
5+
private _onDidChangeTreeData: EventEmitter<PropertyNode | undefined | null | void> = new EventEmitter<PropertyNode | undefined | null | void>();
6+
readonly onDidChangeTreeData: Event<PropertyNode | undefined | null | void> = this._onDidChangeTreeData.event;
7+
8+
private propertyNodes: PropertyNode[];
9+
10+
setNode(currentNode: ExplainNode) {
11+
this.propertyNodes = currentNode.props.map(p => new PropertyNode(p));
12+
this._onDidChangeTreeData.fire();
13+
14+
// Show tree in the view
15+
commands.executeCommand(`setContext`, `vscode-db2i:explainingNode`, true);
16+
}
17+
18+
close() {
19+
commands.executeCommand(`setContext`, `vscode-db2i:explainingNode`, false);
20+
}
21+
22+
getTreeItem(element: PropertyNode): PropertyNode | Thenable<PropertyNode> {
23+
return element;
24+
}
25+
26+
getChildren(element?: PropertyNode): ProviderResult<PropertyNode[]> {
27+
return this.propertyNodes;
28+
}
29+
30+
getParent?(element: any) {
31+
throw new Error("Method not implemented.");
32+
}
33+
resolveTreeItem?(item: TreeItem, element: any, token: CancellationToken): ProviderResult<PropertyNode> {
34+
throw new Error("Method not implemented.");
35+
}
36+
}
37+
38+
export class PropertyNode extends TreeItem {
39+
constructor(property: ExplainProperty) {
40+
super(property.title);
41+
42+
this.description = String(property.value);
43+
}
44+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import { CancellationToken, Event, EventEmitter, ProviderResult, TreeDataProvider, TreeItem, TreeItemCollapsibleState, commands } from "vscode";
2+
import { ExplainNode } from "./nodes";
3+
4+
export class DoveResultsView implements TreeDataProvider<any> {
5+
private _onDidChangeTreeData: EventEmitter<ExplainTreeItem | undefined | null | void> = new EventEmitter<ExplainTreeItem | undefined | null | void>();
6+
readonly onDidChangeTreeData: Event<ExplainTreeItem | undefined | null | void> = this._onDidChangeTreeData.event;
7+
8+
private topNode: ExplainTreeItem;
9+
10+
setRootNode(topNode: ExplainNode) {
11+
this.topNode = new ExplainTreeItem(topNode);
12+
this._onDidChangeTreeData.fire();
13+
14+
// Show tree in the view
15+
commands.executeCommand(`setContext`, `vscode-db2i:explaining`, true);
16+
}
17+
18+
close() {
19+
commands.executeCommand(`setContext`, `vscode-db2i:explaining`, false);
20+
}
21+
22+
getTreeItem(element: ExplainTreeItem): ExplainTreeItem | Thenable<ExplainTreeItem> {
23+
return element;
24+
}
25+
26+
getChildren(element?: ExplainTreeItem): ProviderResult<ExplainTreeItem[]> {
27+
if (element) {
28+
return element.getChildren();
29+
}
30+
else if (this.topNode) {
31+
return [this.topNode];
32+
} else {
33+
return [];
34+
}
35+
}
36+
37+
getParent?(element: any) {
38+
throw new Error("Method not implemented.");
39+
}
40+
resolveTreeItem?(item: TreeItem, element: any, token: CancellationToken): ProviderResult<ExplainTreeItem> {
41+
throw new Error("Method not implemented.");
42+
}
43+
}
44+
45+
export class ExplainTreeItem extends TreeItem {
46+
children: ExplainTreeItem[];
47+
explainNode: ExplainNode;
48+
constructor(node: ExplainNode) {
49+
super(node.title, node.childrenNodes > 0 ? TreeItemCollapsibleState.Expanded : TreeItemCollapsibleState.None);
50+
51+
this.explainNode = node;
52+
this.contextValue = `explainTreeItem`;
53+
54+
// TODO: icons
55+
}
56+
57+
getChildren() {
58+
return this.explainNode.children.map(c => new ExplainTreeItem(c));
59+
}
60+
}

0 commit comments

Comments
 (0)