Skip to content

Commit e9813d8

Browse files
committed
implemente open workspace command
1 parent 255d6b6 commit e9813d8

File tree

5 files changed

+77
-28
lines changed

5 files changed

+77
-28
lines changed

package.json

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,8 @@
7979
"title": "Create Workspace"
8080
},
8181
{
82-
"command": "coder.removeWorkspace",
83-
"title": "Remove Workspace"
82+
"command": "coder.navigateToWorkspace",
83+
"title": "Open Workspace in Browser"
8484
},
8585
{
8686
"command": "coder.workspace.update",
@@ -105,6 +105,10 @@
105105
"command": "coder.open",
106106
"when": "coder.authenticated && view == myWorkspaces || coder.authenticated && view == allWorkspaces",
107107
"group": "inline"
108+
},
109+
{
110+
"command": "coder.navigateToWorkspace",
111+
"when": "coder.authenticated && view == myWorkspaces || coder.authenticated && view == allWorkspaces"
108112
}
109113
]
110114
}

src/api-helper.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { Workspace, WorkspaceAgent } from "coder/site/src/api/typesGenerated"
2+
3+
export function extractAgentsAndFolderPath(
4+
workspace: Workspace,
5+
): [agents: WorkspaceAgent[], folderPath: string | undefined] {
6+
// TODO: multiple agent support
7+
const agents = workspace.latest_build.resources.reduce((acc, resource) => {
8+
return acc.concat(resource.agents || [])
9+
}, [] as WorkspaceAgent[])
10+
11+
let folderPath = undefined
12+
if (agents.length === 1) {
13+
folderPath = agents[0].expanded_directory
14+
}
15+
return [agents, folderPath]
16+
}

src/commands.ts

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@ import axios from "axios"
22
import { getAuthenticatedUser, getWorkspaces, updateWorkspaceVersion } from "coder/site/src/api/api"
33
import { Workspace, WorkspaceAgent } from "coder/site/src/api/typesGenerated"
44
import * as vscode from "vscode"
5+
import { extractAgentsAndFolderPath } from "./api-helper"
56
import { Remote } from "./remote"
67
import { Storage } from "./storage"
8+
import { WorkspaceTreeItem } from "./workspacesProvider"
79

810
export class Commands {
911
public constructor(private readonly vscodeProposed: typeof vscode, private readonly storage: Storage) {}
@@ -113,7 +115,12 @@ export class Commands {
113115
await vscode.commands.executeCommand("vscode.open", uri)
114116
}
115117

116-
public async open(...args: string[]): Promise<void> {
118+
public async navigateToWorkspace(workspace: WorkspaceTreeItem): Promise<void> {
119+
const uri = this.storage.getURL() + `/@${workspace.workspaceOwner}/${workspace.workspaceName}`
120+
await vscode.commands.executeCommand("vscode.open", uri)
121+
}
122+
123+
public async open(...args: unknown[]): Promise<void> {
117124
let workspaceOwner: string
118125
let workspaceName: string
119126
let folderPath: string | undefined
@@ -170,19 +177,19 @@ export class Commands {
170177
workspaceOwner = workspace.owner_name
171178
workspaceName = workspace.name
172179

173-
// TODO: multiple agent support
174-
const agents = workspace.latest_build.resources.reduce((acc, resource) => {
175-
return acc.concat(resource.agents || [])
176-
}, [] as WorkspaceAgent[])
177-
178-
if (agents.length === 1) {
179-
folderPath = agents[0].expanded_directory
180-
}
180+
const [, folderPathExtracted] = extractAgentsAndFolderPath(workspace)
181+
folderPath = folderPathExtracted
182+
} else if (args.length === 2) {
183+
// opening a workspace from the sidebar
184+
const workspaceTreeItem = args[0] as WorkspaceTreeItem
185+
workspaceOwner = workspaceTreeItem.workspaceOwner
186+
workspaceName = workspaceTreeItem.workspaceName
187+
folderPath = workspaceTreeItem.workspaceFolderPath
181188
} else {
182-
workspaceOwner = args[0]
183-
workspaceName = args[1]
189+
workspaceOwner = args[0] as string
190+
workspaceName = args[1] as string
184191
// workspaceAgent is reserved for args[2], but multiple agents aren't supported yet.
185-
folderPath = args[3]
192+
folderPath = args[3] as string | undefined
186193
}
187194

188195
// A workspace can have multiple agents, but that's handled

src/extension.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,15 @@ import * as vscode from "vscode"
66
import { Commands } from "./commands"
77
import { Remote } from "./remote"
88
import { Storage } from "./storage"
9-
import { WorkspaceProvider } from "./workspacesProvider"
9+
import { WorkspaceQuery, WorkspaceProvider } from "./workspacesProvider"
1010

1111
export async function activate(ctx: vscode.ExtensionContext): Promise<void> {
1212
const output = vscode.window.createOutputChannel("Coder")
1313
const storage = new Storage(output, ctx.globalState, ctx.secrets, ctx.globalStorageUri, ctx.logUri)
1414
await storage.init()
1515

16-
vscode.window.registerTreeDataProvider("myWorkspaces", new WorkspaceProvider("owner:me"))
17-
vscode.window.registerTreeDataProvider("allWorkspaces", new WorkspaceProvider())
16+
vscode.window.registerTreeDataProvider("myWorkspaces", new WorkspaceProvider(WorkspaceQuery.Mine))
17+
vscode.window.registerTreeDataProvider("allWorkspaces", new WorkspaceProvider(WorkspaceQuery.All))
1818

1919
getAuthenticatedUser()
2020
.then(() => {
@@ -81,6 +81,7 @@ export async function activate(ctx: vscode.ExtensionContext): Promise<void> {
8181
vscode.commands.registerCommand("coder.open", commands.open.bind(commands))
8282
vscode.commands.registerCommand("coder.workspace.update", commands.updateWorkspace.bind(commands))
8383
vscode.commands.registerCommand("coder.createWorkspace", commands.createWorkspace.bind(commands))
84+
vscode.commands.registerCommand("coder.navigateToWorkspace", commands.navigateToWorkspace.bind(commands))
8485

8586
// Since the "onResolveRemoteAuthority:ssh-remote" activation event exists
8687
// in package.json we're able to perform actions before the authority is

src/workspacesProvider.ts

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,47 @@
11
import { getWorkspaces } from "coder/site/src/api/api"
22
import * as path from "path"
33
import * as vscode from "vscode"
4+
import { extractAgentsAndFolderPath } from "./api-helper"
45

5-
export class WorkspaceProvider implements vscode.TreeDataProvider<TreeItem> {
6-
constructor(private readonly getWorkspacesQuery?: string) {}
7-
getTreeItem(element: TreeItem): vscode.TreeItem {
6+
export enum WorkspaceQuery {
7+
Mine = "owner:me",
8+
All = "",
9+
}
10+
11+
export class WorkspaceProvider implements vscode.TreeDataProvider<WorkspaceTreeItem> {
12+
constructor(private readonly getWorkspacesQuery: WorkspaceQuery) {}
13+
14+
getTreeItem(element: WorkspaceTreeItem): vscode.TreeItem {
815
return element
916
}
1017

11-
getChildren(): Thenable<TreeItem[]> {
18+
getChildren(): Thenable<WorkspaceTreeItem[]> {
1219
return getWorkspaces({ q: this.getWorkspacesQuery }).then((workspaces) => {
13-
return workspaces.workspaces.map(
14-
(workspace) => new TreeItem(workspace.name, vscode.TreeItemCollapsibleState.None),
15-
)
20+
return workspaces.workspaces.map((workspace) => {
21+
const status =
22+
workspace.latest_build.status.substring(0, 1).toUpperCase() + workspace.latest_build.status.substring(1)
23+
24+
const label =
25+
this.getWorkspacesQuery === WorkspaceQuery.All
26+
? `${workspace.owner_name} / ${workspace.name}`
27+
: workspace.name
28+
const detail = `Template: ${workspace.template_display_name || workspace.template_name} • Status: ${status}`
29+
const [, folderPath] = extractAgentsAndFolderPath(workspace)
30+
return new WorkspaceTreeItem(label, detail, workspace.owner_name, workspace.name, folderPath)
31+
})
1632
})
1733
}
1834
}
1935

20-
class TreeItem extends vscode.TreeItem {
21-
constructor(public readonly label: string, public readonly collapsibleState: vscode.TreeItemCollapsibleState) {
22-
super(label, collapsibleState)
23-
this.tooltip = `${this.label}`
36+
export class WorkspaceTreeItem extends vscode.TreeItem {
37+
constructor(
38+
public readonly label: string,
39+
public readonly tooltip: string,
40+
public readonly workspaceOwner: string,
41+
public readonly workspaceName: string,
42+
public readonly workspaceFolderPath: string | undefined,
43+
) {
44+
super(label, vscode.TreeItemCollapsibleState.None)
2445
}
2546

2647
iconPath = {

0 commit comments

Comments
 (0)