diff --git a/extensions/data-workspace/package.json b/extensions/data-workspace/package.json index fdfd61d604..e67b53160b 100644 --- a/extensions/data-workspace/package.json +++ b/extensions/data-workspace/package.json @@ -26,10 +26,10 @@ { "title": "Projects", "properties": { - "dataworkspace.projects": { + "dataworkspace.excludedProjects": { "type": "array", "default": [], - "description": "" + "description": "%projects.excludedProjectsDescription%" }, "projects.defaultProjectSaveLocation": { "type": "string", @@ -68,6 +68,10 @@ "category": "", "icon": "$(close)" }, + { + "command": "projects.removeProject", + "title": "%remove-project-command%" + }, { "command": "projects.manageProject", "title": "%manage-project-command%" @@ -108,6 +112,10 @@ "command": "dataworkspace.close", "when": "false" }, + { + "command": "projects.removeProject", + "when": "false" + }, { "command": "projects.openExisting" }, @@ -121,6 +129,11 @@ "command": "projects.manageProject", "when": "view == dataworkspace.views.main && viewItem == databaseProject.itemType.project && azdataAvailable", "group": "0_projectsFirst@1" + }, + { + "command": "projects.removeProject", + "when": "view == dataworkspace.views.main && viewItem == databaseProject.itemType.project", + "group": "9_dbProjectsLast@9" } ] }, diff --git a/extensions/data-workspace/package.nls.json b/extensions/data-workspace/package.nls.json index 214a667ed3..0f5727e26d 100644 --- a/extensions/data-workspace/package.nls.json +++ b/extensions/data-workspace/package.nls.json @@ -12,5 +12,6 @@ "open-existing-command": "Open existing", "projects.defaultProjectSaveLocation": "Full path to folder where new projects are saved by default.", "projects.showNotAddedProjectsInWorkspacePrompt": "Always show information message when the current workspace folders contain projects that have not been added to the workspace's projects.", - "manage-project-command": "Manage" + "manage-project-command": "Manage", + "projects.excludedProjectsDescription": "List of projects in the workspace to exclude from the projects viewlet" } diff --git a/extensions/data-workspace/src/main.ts b/extensions/data-workspace/src/main.ts index f89ff91e8f..71d92c6f57 100644 --- a/extensions/data-workspace/src/main.ts +++ b/extensions/data-workspace/src/main.ts @@ -62,6 +62,10 @@ export async function activate(context: vscode.ExtensionContext): Promise { + await workspaceService.removeProject(vscode.Uri.file(treeItem.element.project.projectFilePath)); + })); + context.subscriptions.push(vscode.commands.registerCommand('projects.manageProject', async (treeItem: WorkspaceTreeItem) => { const dashboard = new ProjectDashboard(workspaceService, treeItem); await dashboard.showDashboard(); diff --git a/extensions/data-workspace/src/services/workspaceService.ts b/extensions/data-workspace/src/services/workspaceService.ts index c5be1f689c..3eadd5551d 100644 --- a/extensions/data-workspace/src/services/workspaceService.ts +++ b/extensions/data-workspace/src/services/workspaceService.ts @@ -16,6 +16,9 @@ import { TelemetryReporter, TelemetryViews, TelemetryActions } from '../common/t import { Deferred } from '../common/promise'; import { getAzdataApi } from '../common/utils'; +const WorkspaceConfigurationName = 'dataworkspace'; +const ExcludedProjectsConfigurationName = 'excludedProjects'; + export class WorkspaceService implements IWorkspaceService { private _onDidWorkspaceProjectsChange: vscode.EventEmitter = new vscode.EventEmitter(); readonly onDidWorkspaceProjectsChange: vscode.Event = this._onDidWorkspaceProjectsChange?.event; @@ -93,8 +96,14 @@ export class WorkspaceService implements IWorkspaceService { } } - // 3. If any new projects are detected, fire event to refresh projects tree + // 3. Check if the project was previously excluded and remove it from the list of excluded projects if it was + const excludedProjects = this.getWorkspaceConfigurationValue(ExcludedProjectsConfigurationName); + const updatedExcludedProjects = excludedProjects.filter(excludedProj => !projectFiles.find(newProj => vscode.workspace.asRelativePath(newProj) === excludedProj)); + if (excludedProjects.length !== updatedExcludedProjects.length) { + await this.setWorkspaceConfigurationValue(ExcludedProjectsConfigurationName, updatedExcludedProjects); + } + // 4. If any new projects are detected, fire event to refresh projects tree if (newProjectAdded) { this._onDidWorkspaceProjectsChange.fire(); } @@ -127,6 +136,10 @@ export class WorkspaceService implements IWorkspaceService { throw new Error(constants.openedProjectsUndefinedAfterRefresh); } + // remove excluded projects specified in workspace file + const excludedProjects = this.getWorkspaceConfigurationValue(ExcludedProjectsConfigurationName); + this.openedProjects = this.openedProjects.filter(project => !excludedProjects.find(excludedProject => excludedProject === vscode.workspace.asRelativePath(project))); + // filter by specified extension if (ext) { return this.openedProjects.filter(p => p.fsPath.toLowerCase().endsWith(ext.toLowerCase())); @@ -257,4 +270,28 @@ export class WorkspaceService implements IWorkspaceService { ProjectProviderRegistry.registerProvider(extension.exports, extension.id); } } + + /** + * Adds the specified project to list of projects to hide in projects viewlet. This list is kept track of in the workspace file + * @param projectFile uri of project to remove from projects viewlet + */ + async removeProject(projectFile: vscode.Uri): Promise { + TelemetryReporter.createActionEvent(TelemetryViews.WorkspaceTreePane, TelemetryActions.ProjectRemovedFromWorkspace) + .withAdditionalProperties({ + projectType: path.extname(projectFile.fsPath) + }).send(); + + const excludedProjects = this.getWorkspaceConfigurationValue(ExcludedProjectsConfigurationName); + excludedProjects.push(vscode.workspace.asRelativePath(projectFile.fsPath)); + await this.setWorkspaceConfigurationValue(ExcludedProjectsConfigurationName, [...new Set(excludedProjects)]); + this._onDidWorkspaceProjectsChange.fire(); + } + + getWorkspaceConfigurationValue(configurationName: string): T { + return vscode.workspace.getConfiguration(WorkspaceConfigurationName).get(configurationName) as T; + } + + async setWorkspaceConfigurationValue(configurationName: string, value: any): Promise { + await vscode.workspace.getConfiguration(WorkspaceConfigurationName).update(configurationName, value, vscode.ConfigurationTarget.Workspace); + } }