Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"editor.formatOnSave": true
}
1 change: 1 addition & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
```

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
"coder": [
{
"id": "coderRemote",
"name": "",
"name": "Workspaces",
"visibility": "visible",
"icon": "media/logo.svg",
"contextualTitle": "Coder Remote"
Expand Down
21 changes: 7 additions & 14 deletions src/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<void> {
let url: string | undefined = args.length >= 1 ? args[0] : undefined
Expand Down Expand Up @@ -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<void> {
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")
Expand Down
6 changes: 5 additions & 1 deletion src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<void> {
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)
Expand Down Expand Up @@ -50,7 +54,7 @@ export async function activate(ctx: vscode.ExtensionContext): Promise<void> {
},
})

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))
Expand Down
65 changes: 65 additions & 0 deletions src/workspaces.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { getWorkspaces } from "coder/site/src/api/api"
import * as vscode from "vscode"

export class WorkspacesProvider implements vscode.TreeDataProvider<Workspace> {
private _onDidChangeTreeData: vscode.EventEmitter<Workspace | undefined | void> = new vscode.EventEmitter<
Workspace | undefined | void
>()
readonly onDidChangeTreeData: vscode.Event<Workspace | undefined | void> = this._onDidChangeTreeData.event
constructor() {
// intentional blank link for ESLint
}

refresh(): void {
this._onDidChangeTreeData.fire()
}

getTreeItem(element: Workspace): vscode.TreeItem {
return element
}

async getChildren(): Promise<Workspace[]> {
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)
}