Skip to content

Commit 1a16be2

Browse files
authored
UI tweaks (#401)
- Unify: drop colons between tree label and description - Move "open in browser" to tope level groups - Remove URL tree items from cluster and sync destination - Replace "cores and CPUs" with information about node types for driver and worker - collapse state and state description into one tree item https://user-images.githubusercontent.com/40952/215496240-16c36857-5cf3-4df4-8439-6a774b3f9131.mov
1 parent e39a9ec commit 1a16be2

File tree

9 files changed

+119
-79
lines changed

9 files changed

+119
-79
lines changed

packages/databricks-vscode/package.json

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -270,30 +270,40 @@
270270
}
271271
],
272272
"view/item/context": [
273+
{
274+
"command": "databricks.utils.openExternal",
275+
"when": "view == configurationView && viewItem == workspace || view == configurationView && viewItem =~ /^.*cluster.*$/ || view == configurationView && viewItem =~ /^sync.*$/",
276+
"group": "inline@1"
277+
},
278+
{
279+
"command": "databricks.utils.openExternal",
280+
"when": "view == clusterView && viewItem == cluster",
281+
"group": "inline@1"
282+
},
273283
{
274284
"command": "databricks.connection.attachCluster",
275285
"when": "view == clusterView",
276-
"group": "inline@1"
286+
"group": "inline@2"
277287
},
278288
{
279289
"command": "databricks.connection.configureWorkspace",
280290
"when": "view == configurationView && viewItem == workspace",
281-
"group": "inline@1"
291+
"group": "inline@2"
282292
},
283293
{
284294
"command": "databricks.connection.attachClusterQuickPick",
285295
"when": "view == configurationView && viewItem == clusterDetached || view == configurationView && viewItem =~ /^databricks.cluster.*$/",
286-
"group": "inline@1"
296+
"group": "inline@2"
287297
},
288298
{
289299
"command": "databricks.connection.attachSyncDestination",
290300
"when": "view == configurationView && viewItem == syncDetached",
291-
"group": "inline@1"
301+
"group": "inline@2"
292302
},
293303
{
294304
"command": "databricks.connection.attachSyncDestination",
295305
"when": "view == configurationView && viewItem == syncStopped || view == configurationView && viewItem == syncRunning",
296-
"group": "inline@1"
306+
"group": "inline@2"
297307
},
298308
{
299309
"command": "databricks.sync.start",
@@ -315,11 +325,6 @@
315325
"when": "view == configurationView && viewItem == databricks.cluster.terminated",
316326
"group": "inline@0"
317327
},
318-
{
319-
"command": "databricks.utils.openExternal",
320-
"when": "viewItem =~ /^.*databricks-link.*$/ ",
321-
"group": "inline@0"
322-
},
323328
{
324329
"command": "databricks.wsfs.attachSyncDestination",
325330
"when": "view == workspaceFsView && viewItem =~ /^wsfs.(directory|repo).*$/ && config.databricks.sync.destinationType == workspace || view == workspaceFsView && viewItem =~ /^wsfs.repo.*$/ && config.databricks.sync.destinationType == repo"
@@ -657,4 +662,4 @@
657662
],
658663
"report-dir": "coverage"
659664
}
660-
}
665+
}

packages/databricks-vscode/src/cluster/ClusterListDataProvider.test.ts

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ const mockListClustersResponse: cluster.ListClustersResponse = {
1515
cluster_name: "cluster-name-2",
1616
cluster_source: "UI",
1717
creator_user_name: "user-2",
18+
driver_node_type_id: "Standard_DS3_v2",
19+
node_type_id: "Standard_DS3_v2",
1820
spark_version: "10.4.x-scala2.12",
1921
state: "TERMINATED",
2022
},
@@ -23,6 +25,8 @@ const mockListClustersResponse: cluster.ListClustersResponse = {
2325
cluster_name: "cluster-name-1",
2426
cluster_source: "UI",
2527
creator_user_name: "user-1",
28+
driver_node_type_id: "Standard_DS3_v2",
29+
node_type_id: "Standard_DS3_v2",
2630
spark_version: "10.4.x-scala2.12",
2731
state: "RUNNING",
2832
},
@@ -100,7 +104,7 @@ describe(__filename, () => {
100104
provider.getChildren(cluster)
101105
);
102106
assert(children);
103-
assert.equal(children.length, 5);
107+
assert.equal(children.length, 6);
104108
});
105109

106110
it("should get cluster tree node items", async () => {
@@ -115,25 +119,27 @@ describe(__filename, () => {
115119
assert.deepEqual(items, [
116120
{
117121
description: "cluster-id-2",
118-
label: "Cluster ID:",
122+
label: "Cluster ID",
119123
},
120124
{
121-
contextValue: "databricks-link",
122-
description:
123-
"https://www.example.com/#setting/clusters/cluster-id-2/configuration",
124-
label: "URL:",
125+
description: "Standard_DS3_v2",
126+
label: "Driver",
127+
},
128+
{
129+
description: "None (single node cluster)",
130+
label: "Worker",
125131
},
126132
{
127133
description: "10.4.x",
128-
label: "Databricks Runtime:",
134+
label: "Databricks Runtime",
129135
},
130136
{
131137
description: "TERMINATED",
132-
label: "State:",
138+
label: "State",
133139
},
134140
{
135141
description: "user-2",
136-
label: "Creator:",
142+
label: "Creator",
137143
},
138144
]);
139145
});
@@ -147,6 +153,7 @@ describe(__filename, () => {
147153
let item = ClusterListDataProvider.clusterNodeToTreeItem(cluster);
148154
assert.deepEqual(item, {
149155
collapsibleState: 1,
156+
contextValue: "cluster",
150157
iconPath: {
151158
color: undefined,
152159
id: "debug-stop",
@@ -163,6 +170,7 @@ describe(__filename, () => {
163170
item = ClusterListDataProvider.clusterNodeToTreeItem(cluster);
164171
assert.deepEqual(item, {
165172
collapsibleState: 1,
173+
contextValue: "cluster",
166174
iconPath: {
167175
color: undefined,
168176
id: "debug-start",

packages/databricks-vscode/src/cluster/ClusterListDataProvider.ts

Lines changed: 29 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ export class ClusterListDataProvider
100100
label: element.name,
101101
iconPath: icon,
102102
id: element.id,
103+
contextValue: "cluster",
103104
collapsibleState: TreeItemCollapsibleState.Collapsed,
104105
};
105106
}
@@ -114,57 +115,53 @@ export class ClusterListDataProvider
114115
): Promise<Array<TreeItem>> {
115116
const children: TreeItem[] = [
116117
{
117-
label: "Cluster ID:",
118+
label: "Cluster ID",
118119
description: element.id,
119120
},
120-
{
121-
label: "URL:",
122-
description: await element.url,
123-
contextValue: "databricks-link",
124-
},
125121
];
126-
if (element.cores) {
122+
123+
children.push({
124+
label: "Driver",
125+
description: element.details.driver_node_type_id,
126+
});
127+
128+
if (element.details.autoscale) {
127129
children.push({
128-
label: "Cores:",
129-
description: element.cores + "",
130+
label: "Worker",
131+
description: `${element.details.node_type_id}, ${element.details.autoscale.min_workers}-${element.details.autoscale.max_workers} workers`,
130132
});
131-
}
132-
if (element.memoryMb) {
133+
} else if (element.details.num_workers || 0 > 0) {
133134
children.push({
134-
label: "Memory:",
135-
description: formatSize(element.memoryMb),
135+
label: "Worker",
136+
description: `${element.details.node_type_id}, ${element.details.num_workers} workers`,
136137
});
138+
} else {
139+
children.push({
140+
label: "Worker",
141+
description: `None (single node cluster)`,
142+
});
143+
}
144+
145+
let stateDescription: string = element.state;
146+
if (element.stateMessage && element.state !== "RUNNING") {
147+
stateDescription = `${element.state} - ${element.stateMessage}`;
137148
}
149+
138150
children.push(
139151
{
140-
label: "Databricks Runtime:",
152+
label: "Databricks Runtime",
141153
description: element.dbrVersion.join("."),
142154
},
143155
{
144-
label: "State:",
145-
description: element.state,
156+
label: "State",
157+
description: stateDescription,
146158
},
147159
{
148-
label: "Creator:",
160+
label: "Creator",
149161
description: element.creator,
150162
}
151163
);
152164

153-
if (element.stateMessage && element.state !== "RUNNING") {
154-
children.push({
155-
label: "State message:",
156-
description: element.stateMessage,
157-
});
158-
}
159-
160-
function formatSize(sizeInMB: number): string {
161-
if (sizeInMB > 1024) {
162-
return Math.round(sizeInMB / 1024).toString() + " GB";
163-
} else {
164-
return `${sizeInMB} MB`;
165-
}
166-
}
167-
168165
return children;
169166
}
170167
}

packages/databricks-vscode/src/configuration/ConfigurationDataProvider.test.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,11 @@ describe(__filename, () => {
102102
});
103103

104104
it("should return cluster children", async () => {
105-
const cluster = new Cluster(instance(mock(ApiClient)), {
105+
const mockApiClient = mock(ApiClient);
106+
when(mockApiClient.host).thenResolve(
107+
new URL("https://www.example.com")
108+
);
109+
const cluster = new Cluster(instance(mockApiClient), {
106110
cluster_id: "cluster-id-2",
107111
cluster_name: "cluster-name-2",
108112
cluster_source: "UI",
@@ -129,6 +133,7 @@ describe(__filename, () => {
129133
},
130134
id: "WORKSPACE",
131135
label: "Workspace",
136+
url: undefined,
132137
},
133138
{
134139
collapsibleState: 2,
@@ -139,6 +144,7 @@ describe(__filename, () => {
139144
},
140145
id: "CLUSTER",
141146
label: "Cluster",
147+
url: "https://www.example.com/#setting/clusters/cluster-id-2/configuration",
142148
},
143149
{
144150
collapsibleState: 2,

packages/databricks-vscode/src/configuration/ConfigurationDataProvider.ts

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,27 @@ import {
88
TreeItem,
99
TreeItemCollapsibleState,
1010
} from "vscode";
11+
1112
import {ClusterListDataProvider} from "../cluster/ClusterListDataProvider";
1213
import {CodeSynchronizer} from "../sync/CodeSynchronizer";
1314
import {ConnectionManager} from "./ConnectionManager";
1415

16+
export type ConfigurationTreeItem = TreeItem & {
17+
url?: string;
18+
};
19+
1520
/**
1621
* Data provider for the cluster tree view
1722
*/
1823
export class ConfigurationDataProvider
19-
implements TreeDataProvider<TreeItem>, Disposable
24+
implements TreeDataProvider<ConfigurationTreeItem>, Disposable
2025
{
21-
private _onDidChangeTreeData: EventEmitter<TreeItem | undefined | void> =
22-
new EventEmitter<TreeItem | undefined | void>();
23-
readonly onDidChangeTreeData: Event<TreeItem | undefined | void> =
24-
this._onDidChangeTreeData.event;
26+
private _onDidChangeTreeData: EventEmitter<
27+
ConfigurationTreeItem | undefined | void
28+
> = new EventEmitter<ConfigurationTreeItem | undefined | void>();
29+
readonly onDidChangeTreeData: Event<
30+
ConfigurationTreeItem | undefined | void
31+
> = this._onDidChangeTreeData.event;
2532

2633
private disposables: Array<Disposable> = [];
2734

@@ -51,13 +58,13 @@ export class ConfigurationDataProvider
5158
this.disposables.forEach((d) => d.dispose());
5259
}
5360

54-
getTreeItem(element: TreeItem): TreeItem | Thenable<TreeItem> {
61+
getTreeItem(element: ConfigurationTreeItem): TreeItem | Thenable<TreeItem> {
5562
return element;
5663
}
5764

5865
async getChildren(
59-
element?: TreeItem | undefined
60-
): Promise<Array<TreeItem>> {
66+
element?: ConfigurationTreeItem | undefined
67+
): Promise<Array<ConfigurationTreeItem>> {
6168
switch (this.connectionManager.state) {
6269
case "CONNECTED":
6370
break;
@@ -72,13 +79,14 @@ export class ConfigurationDataProvider
7279
const syncDestination = this.connectionManager.syncDestination;
7380

7481
if (!element) {
75-
const children: Array<TreeItem> = [];
82+
const children: Array<ConfigurationTreeItem> = [];
7683
children.push({
7784
label: `Workspace`,
7885
iconPath: new ThemeIcon("account"),
7986
id: "WORKSPACE",
8087
collapsibleState: TreeItemCollapsibleState.Expanded,
8188
contextValue: "workspace",
89+
url: this.connectionManager.databricksWorkspace?.host?.toString(),
8290
});
8391

8492
if (cluster) {
@@ -112,6 +120,7 @@ export class ConfigurationDataProvider
112120
id: "CLUSTER",
113121
collapsibleState: TreeItemCollapsibleState.Expanded,
114122
contextValue,
123+
url: (await cluster.url).toString(),
115124
});
116125
} else {
117126
children.push({
@@ -131,6 +140,7 @@ export class ConfigurationDataProvider
131140
iconPath: new ThemeIcon("file-directory"),
132141
id: "SYNC-DESTINATION",
133142
collapsibleState: TreeItemCollapsibleState.Expanded,
143+
url: await syncDestination.wsfsDir.url,
134144
contextValue:
135145
this.sync.state === "WATCHING_FOR_CHANGES" ||
136146
this.sync.state === "IN_PROGRESS"
@@ -231,7 +241,7 @@ export class ConfigurationDataProvider
231241

232242
return [
233243
{
234-
label: "Name:",
244+
label: "Name",
235245
description: cluster.name,
236246
iconPath: clusterItem.iconPath,
237247
collapsibleState: TreeItemCollapsibleState.None,
@@ -246,7 +256,7 @@ export class ConfigurationDataProvider
246256
if (element.id === "SYNC-DESTINATION" && syncDestination) {
247257
const children: Array<TreeItem> = [
248258
{
249-
label: `Name:`,
259+
label: `Name`,
250260
description: syncDestination.name,
251261
iconPath:
252262
this.sync.state === "WATCHING_FOR_CHANGES" ||
@@ -272,17 +282,12 @@ export class ConfigurationDataProvider
272282
}
273283
children.push(
274284
{
275-
label: `URL:`,
276-
description: await syncDestination.wsfsDir.url,
277-
contextValue: "databricks-link",
278-
},
279-
{
280-
label: `State:`,
285+
label: `State`,
281286
description: this.sync.state,
282287
collapsibleState: TreeItemCollapsibleState.None,
283288
},
284289
{
285-
label: `Path:`,
290+
label: `Path`,
286291
description: syncDestination.path.path,
287292
collapsibleState: TreeItemCollapsibleState.None,
288293
}

packages/databricks-vscode/src/extension.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ export async function activate(
287287
NamedLogger.getOrCreate("Extension").error("Quick Start error", e);
288288
});
289289

290-
//utils
290+
// Utils
291291
const utilCommands = new UtilsCommands.UtilsCommands();
292292
context.subscriptions.push(
293293
commands.registerCommand(

0 commit comments

Comments
 (0)