From 93310739265bc0fe0d8ca34bd1b1c9d06386ff5a Mon Sep 17 00:00:00 2001 From: Joe Previte Date: Tue, 17 Jan 2023 08:48:13 -0700 Subject: [PATCH 1/4] docs: update CONTRIBUTING.md Add line to help Mac users place binary in correct tmpdir. --- CONTRIBUTING.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 26375083..f86c8230 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -40,6 +40,7 @@ Coder Remote periodically reads the `network-info-dir + "/" + matchingSSHPID` fi ```bash # Inside https://github.com/coder/coder + # on Mac replace /tmp/coder with "$TMPDIR" $ go build -o /tmp/coder ./cmd/coder ``` From 78ef01c8a4a225590ba715ec2d4c605ed1d7314b Mon Sep 17 00:00:00 2001 From: Joe Previte Date: Tue, 17 Jan 2023 08:50:03 -0700 Subject: [PATCH 2/4] feat: add name Workspaces to extension view --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a3e3a4e3..8825dfd2 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,7 @@ "coder": [ { "id": "coderRemote", - "name": "", + "name": "Workspaces", "visibility": "visible", "icon": "media/logo.svg", "contextualTitle": "Coder Remote" From fca7974f523874140406506eb59379b57ce81f12 Mon Sep 17 00:00:00 2001 From: Joe Previte Date: Tue, 17 Jan 2023 08:50:58 -0700 Subject: [PATCH 3/4] refactor: add Workspaces treeDataProvider This adds a new `TreeDataProvider` to allow us to have more control over the view in the Activity Bar to show the user's Coder Workspaces. --- src/commands.ts | 21 +++++---------- src/extension.ts | 6 ++++- src/workspaces.ts | 65 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 77 insertions(+), 15 deletions(-) create mode 100644 src/workspaces.ts diff --git a/src/commands.ts b/src/commands.ts index 1ea8d5c3..fe8867e5 100644 --- a/src/commands.ts +++ b/src/commands.ts @@ -4,9 +4,10 @@ import { Workspace } from "coder/site/src/api/typesGenerated" import * as vscode from "vscode" import { Remote } from "./remote" import { Storage } from "./storage" +import { WorkspacesProvider } from "./workspaces" export class Commands { - public constructor(private readonly storage: Storage) {} + public constructor(private readonly storage: Storage, private readonly treeDataProvider: WorkspacesProvider) {} public async login(...args: string[]): Promise { let url: string | undefined = args.length >= 1 ? args[0] : undefined @@ -64,25 +65,17 @@ export class Commands { await this.storage.setSessionToken(token) const user = await getUser() await vscode.commands.executeCommand("setContext", "coder.authenticated", true) - vscode.window - .showInformationMessage( - `Welcome to Coder, ${user.username}!`, - { - detail: "You can now use the Coder extension to manage your Coder instance.", - }, - "Open Workspace", - ) - .then((action) => { - if (action === "Open Workspace") { - vscode.commands.executeCommand("coder.open") - } - }) + this.treeDataProvider.refresh() + vscode.window.showInformationMessage(`Welcome to Coder, ${user.username}!`, { + detail: "You can now use the Coder extension to manage your Coder instance.", + }) } public async logout(): Promise { await this.storage.setURL(undefined) await this.storage.setSessionToken(undefined) await vscode.commands.executeCommand("setContext", "coder.authenticated", false) + this.treeDataProvider.refresh() vscode.window.showInformationMessage("You've been logged out of Coder!", "Login").then((action) => { if (action === "Login") { vscode.commands.executeCommand("coder.login") diff --git a/src/extension.ts b/src/extension.ts index 64ab01d2..65ce8d86 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -6,12 +6,16 @@ import * as vscode from "vscode" import { Commands } from "./commands" import { Remote } from "./remote" import { Storage } from "./storage" +import { WorkspacesProvider } from "./workspaces" export async function activate(ctx: vscode.ExtensionContext): Promise { const output = vscode.window.createOutputChannel("Coder") + const workspacesProvider = new WorkspacesProvider() const storage = new Storage(output, ctx.globalState, ctx.secrets, ctx.globalStorageUri, ctx.logUri) await storage.init() + vscode.window.registerTreeDataProvider("coderRemote", workspacesProvider) + getUser() .then(() => { vscode.commands.executeCommand("setContext", "coder.authenticated", true) @@ -50,7 +54,7 @@ export async function activate(ctx: vscode.ExtensionContext): Promise { }, }) - const commands = new Commands(storage) + const commands = new Commands(storage, workspacesProvider) vscode.commands.registerCommand("coder.login", commands.login.bind(commands)) vscode.commands.registerCommand("coder.logout", commands.logout.bind(commands)) diff --git a/src/workspaces.ts b/src/workspaces.ts new file mode 100644 index 00000000..19508825 --- /dev/null +++ b/src/workspaces.ts @@ -0,0 +1,65 @@ +import { getWorkspaces } from "coder/site/src/api/api" +import * as vscode from "vscode" + +export class WorkspacesProvider implements vscode.TreeDataProvider { + private _onDidChangeTreeData: vscode.EventEmitter = new vscode.EventEmitter< + Workspace | undefined | void + >() + readonly onDidChangeTreeData: vscode.Event = this._onDidChangeTreeData.event + constructor() { + // intentional blank link for ESLint + } + + refresh(): void { + this._onDidChangeTreeData.fire() + } + + getTreeItem(element: Workspace): vscode.TreeItem { + return element + } + + async getChildren(): Promise { + const workspaces = await getWorkspaces({ + q: "owner:me", + }).catch(() => { + // TODO: we should probably warn or error here + return + }) + + if (workspaces) { + const items: Workspace[] = workspaces.workspaces.map((workspace) => { + return new Workspace( + `${workspace.name}`, + vscode.TreeItemCollapsibleState.None, + `${workspace.latest_build.status !== "running" ? "circle-outline" : "circle-filled"}`, + { + command: "coder.open", + title: "", + arguments: [workspace.owner_name, workspace.name], + }, + ) + }) + + return Promise.resolve(items) + } else { + // TODO: should we issue a warning new workspaces found? + // Or return a link to create a new Workspace from the dashboard? + return Promise.resolve([]) + } + } +} + +export class Workspace extends vscode.TreeItem { + constructor( + public readonly label: string, + public readonly collapsibleState: vscode.TreeItemCollapsibleState, + public readonly iconId: vscode.ThemeIcon["id"], + public readonly command?: vscode.Command, + ) { + super(label, collapsibleState) + + this.tooltip = `${this.label}` + } + + iconPath = new vscode.ThemeIcon(this.iconId) +} From 3a7548686415854d0db847cd2945795458c66fbe Mon Sep 17 00:00:00 2001 From: Joe Previte Date: Tue, 17 Jan 2023 08:51:49 -0700 Subject: [PATCH 4/4] chore: commit vscode settings.json Format on save saves so much time. --- .vscode/settings.json | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..3b614348 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "editor.formatOnSave": true +} \ No newline at end of file