From 017ad5f3e67c0b0a1f95d2fb374d9ac588a0113b Mon Sep 17 00:00:00 2001 From: Ehab Younes Date: Tue, 30 Sep 2025 14:47:42 +0300 Subject: [PATCH] Add search filter to the tree views and enhance the refresh process --- package.json | 38 ++++++++++++++++++++++++++--- src/extension.ts | 18 ++++++++++++-- src/workspace/workspacesProvider.ts | 8 ++++++ 3 files changed, 59 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 23a49a20..438ef3c7 100644 --- a/package.json +++ b/package.json @@ -204,6 +204,7 @@ { "command": "coder.createWorkspace", "title": "Create Workspace", + "category": "Coder", "when": "coder.authenticated", "icon": "$(add)" }, @@ -226,7 +227,8 @@ }, { "command": "coder.refreshWorkspaces", - "title": "Coder: Refresh Workspace", + "title": "Refresh Workspace", + "category": "Coder", "icon": "$(refresh)", "when": "coder.authenticated" }, @@ -241,6 +243,18 @@ "title": "Coder: Open App Status", "icon": "$(robot)", "when": "coder.authenticated" + }, + { + "command": "coder.searchMyWorkspaces", + "title": "Search", + "category": "Coder", + "icon": "$(search)" + }, + { + "command": "coder.searchAllWorkspaces", + "title": "Search", + "category": "Coder", + "icon": "$(search)" } ], "menus": { @@ -248,6 +262,14 @@ { "command": "coder.openFromSidebar", "when": "false" + }, + { + "command": "coder.searchMyWorkspaces", + "when": "false" + }, + { + "command": "coder.searchAllWorkspaces", + "when": "false" } ], "view/title": [ @@ -262,12 +284,22 @@ { "command": "coder.createWorkspace", "when": "coder.authenticated && view == myWorkspaces", - "group": "navigation" + "group": "navigation@1" }, { "command": "coder.refreshWorkspaces", "when": "coder.authenticated && view == myWorkspaces", - "group": "navigation" + "group": "navigation@2" + }, + { + "command": "coder.searchMyWorkspaces", + "when": "coder.authenticated && view == myWorkspaces", + "group": "navigation@3" + }, + { + "command": "coder.searchAllWorkspaces", + "when": "coder.authenticated && view == allWorkspaces", + "group": "navigation@3" } ], "view/item/context": [ diff --git a/src/extension.ts b/src/extension.ts index f7453cec..982342eb 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -18,6 +18,9 @@ import { WorkspaceQuery, } from "./workspace/workspacesProvider"; +const MY_WORKSPACES_TREE_ID = "myWorkspaces"; +const ALL_WORKSPACES_TREE_ID = "allWorkspaces"; + export async function activate(ctx: vscode.ExtensionContext): Promise { // The Remote SSH extension's proposed APIs are used to override the SSH host // name in VS Code itself. It's visually unappealing having a lengthy name! @@ -86,7 +89,7 @@ export async function activate(ctx: vscode.ExtensionContext): Promise { // createTreeView, unlike registerTreeDataProvider, gives us the tree view API // (so we can see when it is visible) but otherwise they have the same effect. - const myWsTree = vscode.window.createTreeView("myWorkspaces", { + const myWsTree = vscode.window.createTreeView(MY_WORKSPACES_TREE_ID, { treeDataProvider: myWorkspacesProvider, }); myWorkspacesProvider.setVisibility(myWsTree.visible); @@ -94,7 +97,7 @@ export async function activate(ctx: vscode.ExtensionContext): Promise { myWorkspacesProvider.setVisibility(event.visible); }); - const allWsTree = vscode.window.createTreeView("allWorkspaces", { + const allWsTree = vscode.window.createTreeView(ALL_WORKSPACES_TREE_ID, { treeDataProvider: allWorkspacesProvider, }); allWorkspacesProvider.setVisibility(allWsTree.visible); @@ -298,6 +301,12 @@ export async function activate(ctx: vscode.ExtensionContext): Promise { "coder.viewLogs", commands.viewLogs.bind(commands), ); + vscode.commands.registerCommand("coder.searchMyWorkspaces", async () => + showTreeViewSearch(MY_WORKSPACES_TREE_ID), + ); + vscode.commands.registerCommand("coder.searchAllWorkspaces", async () => + showTreeViewSearch(ALL_WORKSPACES_TREE_ID), + ); // Since the "onResolveRemoteAuthority:ssh-remote" activation event exists // in package.json we're able to perform actions before the authority is @@ -421,3 +430,8 @@ export async function activate(ctx: vscode.ExtensionContext): Promise { } } } + +async function showTreeViewSearch(id: string): Promise { + await vscode.commands.executeCommand(`${id}.focus`); + await vscode.commands.executeCommand("list.find"); +} diff --git a/src/workspace/workspacesProvider.ts b/src/workspace/workspacesProvider.ts index 86279401..915ef32a 100644 --- a/src/workspace/workspacesProvider.ts +++ b/src/workspace/workspacesProvider.ts @@ -262,6 +262,7 @@ export class WorkspaceProvider // yet. appStatuses.push( new AppStatusTreeItem({ + id: status.id, name: status.message, command: app.command, workspace_name: element.workspace.name, @@ -335,6 +336,7 @@ class AgentMetadataTreeItem extends vscode.TreeItem { metadataEvent.result.collected_at, ).toLocaleString(); + this.id = metadataEvent.description.key; this.tooltip = "Collected at " + collected_at; this.contextValue = "coderAgentMetadata"; } @@ -343,6 +345,7 @@ class AgentMetadataTreeItem extends vscode.TreeItem { class AppStatusTreeItem extends vscode.TreeItem { constructor( public readonly app: { + id: string; name: string; url?: string; command?: string; @@ -350,6 +353,7 @@ class AppStatusTreeItem extends vscode.TreeItem { }, ) { super("", vscode.TreeItemCollapsibleState.None); + this.id = app.id; this.description = app.name; this.contextValue = "coderAppStatus"; @@ -369,6 +373,7 @@ type CoderOpenableTreeItemType = export class OpenableTreeItem extends vscode.TreeItem { constructor( + id: string, label: string, tooltip: string, description: string, @@ -379,6 +384,7 @@ export class OpenableTreeItem extends vscode.TreeItem { contextValue: CoderOpenableTreeItemType, ) { super(label, collapsibleState); + this.id = id; this.contextValue = contextValue; this.tooltip = tooltip; this.description = description; @@ -397,6 +403,7 @@ export class AgentTreeItem extends OpenableTreeItem { watchMetadata = false, ) { super( + agent.id, // id agent.name, // label `Status: ${agent.status}`, // tooltip agent.status, // description @@ -434,6 +441,7 @@ export class WorkspaceTreeItem extends OpenableTreeItem { const detail = `Template: ${workspace.template_display_name || workspace.template_name} • Status: ${status}`; const agents = extractAgents(workspace.latest_build.resources); super( + workspace.id, label, detail, workspace.latest_build.status, // description