Skip to content

Commit

Permalink
Node Explorer: Some error message improvements (#169)
Browse files Browse the repository at this point in the history
Using a Tree View Item as a button to trigger a command, which we are
doing, is explicitly [called
out](https://code.visualstudio.com/api/ux-guidelines/views#tree-views)
as a "Don't" in the UX Guidelines.

To adhere to this, we should use an inline context for the external docs
link.

On hover, you see the following:

**Tailscale not running:**


![image](https://github.com/tailscale-dev/vscode-tailscale/assets/40265/2a674311-7a92-4c8d-b161-59cad9552b49)

**Running but not logged in:**


![image](https://github.com/tailscale-dev/vscode-tailscale/assets/40265/7fc8b67c-4c4d-43fe-920f-f5e12246813a)

Signed-off-by: Tyler Smalley <tyler@tailscale.com>
  • Loading branch information
tylersmalley committed Aug 4, 2023
1 parent 2bf170f commit 717cc79
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 35 deletions.
10 changes: 10 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,11 @@
"command": "tailscale.node.fs.delete",
"group": "4_fileAction@2",
"when": "view == node-explorer-view && viewItem =~ /^peer-file-explorer-(dir|file)/"
},
{
"command": "tailscale.node.openDocsLink",
"group": "inline",
"when": "view == node-explorer-view && viewItem =~ /^peer-error-link/"
}
]
},
Expand Down Expand Up @@ -309,6 +314,11 @@
{
"command": "tailscale.openExternal",
"title": "Open External Link"
},
{
"command": "tailscale.node.openDocsLink",
"title": "Open Documentation",
"icon": "$(link-external)"
}
],
"viewsContainers": {
Expand Down
20 changes: 9 additions & 11 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,12 @@ import { ADMIN_CONSOLE } from './utils/url';
import { Tailscale } from './tailscale';
import { Logger } from './logger';
import { errorForType } from './tailscale/error';
import { FileExplorer, NodeExplorerProvider, PeerRoot, ErrorItem } from './node-explorer-provider';
import {
FileExplorer,
NodeExplorerProvider,
PeerRoot,
PeerErrorItem,
} from './node-explorer-provider';

import { FileSystemProviderSFTP } from './filesystem-provider-sftp';
import { ConfigManager } from './config-manager';
Expand Down Expand Up @@ -65,13 +70,13 @@ export async function activate(context: vscode.ExtensionContext) {
);

// eslint-disable-next-line prefer-const
let nodeExplorerView: vscode.TreeView<PeerRoot | FileExplorer | ErrorItem>;
let nodeExplorerView: vscode.TreeView<PeerRoot | FileExplorer | PeerErrorItem>;

function updateNodeExplorerDisplayName(name: string) {
nodeExplorerView.title = name;
}

const createNodeExplorerView = (): vscode.TreeView<PeerRoot | FileExplorer | ErrorItem> => {
const createNodeExplorerView = (): vscode.TreeView<PeerRoot | FileExplorer | PeerErrorItem> => {
return vscode.window.createTreeView('node-explorer-view', {
treeDataProvider: nodeExplorerProvider,
showCollapseAll: true,
Expand All @@ -90,13 +95,6 @@ export async function activate(context: vscode.ExtensionContext) {
vscode.window.registerTreeDataProvider('node-explorer-view', nodeExplorerProvider);
context.subscriptions.push(nodeExplorerView);

context.subscriptions.push(
vscode.commands.registerCommand('tailscale.openExternal', (url: string) => {
Logger.info('called tailscale.openExternal', 'command');
vscode.env.openExternal(vscode.Uri.parse(url));
})
);

context.subscriptions.push(
vscode.commands.registerCommand('tailscale.refreshServe', () => {
Logger.info('called tailscale.refreshServe', 'command');
Expand Down Expand Up @@ -144,7 +142,7 @@ export async function activate(context: vscode.ExtensionContext) {
context.subscriptions.push(
vscode.commands.registerCommand(
'tailscale.node.setRootDir',
async (node: PeerRoot | FileExplorer | ErrorItem) => {
async (node: PeerRoot | FileExplorer | PeerErrorItem) => {
let address: string;

if (node instanceof FileExplorer) {
Expand Down
59 changes: 35 additions & 24 deletions src/node-explorer-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ export class NodeExplorerProvider implements vscode.TreeDataProvider<PeerBaseTre
this.registerOpenRemoteCodeCommand();
this.registerOpenTerminalCommand();
this.registerRefresh();
this.registerOpenDocsLink();
}

onDidChangeFileDecorations?: vscode.Event<vscode.Uri | vscode.Uri[] | undefined> | undefined;
Expand All @@ -60,7 +61,7 @@ export class NodeExplorerProvider implements vscode.TreeDataProvider<PeerBaseTre
}

async getChildren(element?: PeerBaseTreeItem): Promise<PeerBaseTreeItem[]> {
if (element instanceof ErrorItem) {
if (element instanceof PeerErrorItem) {
return [];
}

Expand All @@ -83,9 +84,8 @@ export class NodeExplorerProvider implements vscode.TreeDataProvider<PeerBaseTre
if (element instanceof PeerRoot) {
if (!element.SSHEnabled) {
return [
new ErrorItem({
label: 'Enable Tailsale SSH',
iconPath: 'link-external',
new PeerErrorItem({
label: 'Enable Tailscale SSH',
link: 'https://tailscale.com/kb/1193/tailscale-ssh/#prerequisites',
tooltip: 'You need Tailscale SSH in order to use the File Explorer with this node.',
}),
Expand Down Expand Up @@ -139,18 +139,17 @@ export class NodeExplorerProvider implements vscode.TreeDataProvider<PeerBaseTre
switch (err.Type) {
case 'NOT_RUNNING':
return [
new ErrorItem({
new PeerErrorItem({
label: 'Tailscale may not be installed. Install now',
iconPath: 'link-external',
link: 'https://tailscale.com/download',
}),
];
case 'OFFLINE':
return [
new ErrorItem({
label: 'Tailscale is not running',
iconPath: 'alert',
tooltip: 'Make sure that Tailscale is signed in and enabled',
new PeerErrorItem({
label: 'Tailscale offline. Log in and try again',
tooltip: 'Make sure that Tailscale is installed and running',
link: 'https://tailscale.com/download',
}),
];
}
Expand Down Expand Up @@ -205,9 +204,9 @@ export class NodeExplorerProvider implements vscode.TreeDataProvider<PeerBaseTre
// If there are no groups at all, render an onboarding item.
if (!hasErr && !groups.length) {
return [
new ErrorItem({
new PeerErrorItem({
label: 'Add your first node',
iconPath: 'link-external',
tooltip: 'Click to read the docs to learn how to add your first node',
link: 'https://tailscale.com/kb/1017/install/',
}),
];
Expand Down Expand Up @@ -441,6 +440,19 @@ export class NodeExplorerProvider implements vscode.TreeDataProvider<PeerBaseTre
}
);
}

registerOpenDocsLink(): void {
vscode.commands.registerCommand('tailscale.node.openDocsLink', (e: PeerErrorItem) => {
Logger.info('called tailscale.openDocsLink', 'command');

if (!e.link) {
Logger.error('no link provided to openDocsLink', 'command');
return;
}

vscode.env.openExternal(vscode.Uri.parse(e.link));
});
}
}

export class PeerBaseTreeItem extends vscode.TreeItem {
Expand Down Expand Up @@ -561,20 +573,19 @@ export class PeerDetailTreeItem extends PeerBaseTreeItem {
}
}

export class ErrorItem extends vscode.TreeItem {
export class PeerErrorItem extends vscode.TreeItem {
public link?: string;

constructor(opts: { label: string; iconPath?: string; link?: string; tooltip?: string }) {
super(opts.label);
if (opts.iconPath) {
this.iconPath = new vscode.ThemeIcon(opts.iconPath);
}
if (opts.link) {
this.command = {
command: 'tailscale.openExternal',
title: 'Open External Link',
arguments: [opts.link],
};
}
this.tooltip = opts.tooltip ?? 'Open Link';

this.link = opts.link;

this.iconPath = new vscode.ThemeIcon(opts?.iconPath || 'alert');

this.tooltip = opts.tooltip;

this.contextValue = `peer-error${opts.link && '-link'}`;
}
}

Expand Down

0 comments on commit 717cc79

Please sign in to comment.