mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-31 09:35:39 -05:00
Load all data workspace projects directly from workspace (#15921)
* Load all projects directly from workspace * fixes * Remove relativity and fix tests * fix compile * PR comments * remove unused * distro
This commit is contained in:
@@ -5,17 +5,15 @@
|
||||
|
||||
import type * as azdataType from 'azdata';
|
||||
import * as vscode from 'vscode';
|
||||
import * as path from 'path';
|
||||
import { DialogBase } from './dialogBase';
|
||||
import * as constants from '../common/constants';
|
||||
import { IWorkspaceService } from '../common/interfaces';
|
||||
import { directoryExist, fileExist } from '../common/utils';
|
||||
import { IconPathHelper } from '../common/iconHelper';
|
||||
import { calculateRelativity, TelemetryActions, TelemetryReporter, TelemetryViews } from '../common/telemetry';
|
||||
import { TelemetryActions, TelemetryReporter, TelemetryViews } from '../common/telemetry';
|
||||
import { defaultProjectSaveLocation } from '../common/projectLocationHelper';
|
||||
|
||||
export class OpenExistingDialog extends DialogBase {
|
||||
public targetTypeRadioCardGroup: azdataType.RadioCardGroupComponent | undefined;
|
||||
public filePathTextBox: azdataType.InputBoxComponent | undefined;
|
||||
public filePathAndButtonComponent: azdataType.FormComponent | undefined;
|
||||
public gitRepoTextBoxComponent: azdataType.FormComponent | undefined;
|
||||
@@ -26,17 +24,7 @@ export class OpenExistingDialog extends DialogBase {
|
||||
public locationRadioButtonFormComponent: azdataType.FormComponent | undefined;
|
||||
public formBuilder: azdataType.FormBuilder | undefined;
|
||||
|
||||
private _targetTypes = [
|
||||
{
|
||||
name: constants.Project,
|
||||
icon: this.extensionContext.asAbsolutePath('images/Open_existing_Project.svg')
|
||||
}, {
|
||||
name: constants.Workspace,
|
||||
icon: this.extensionContext.asAbsolutePath('images/Open_existing_Workspace.svg')
|
||||
}
|
||||
];
|
||||
|
||||
constructor(private workspaceService: IWorkspaceService, private extensionContext: vscode.ExtensionContext) {
|
||||
constructor(private workspaceService: IWorkspaceService) {
|
||||
super(constants.OpenExistingDialogTitle, 'OpenProject', constants.OpenButtonText);
|
||||
|
||||
// dialog launched from Welcome message button (only visible when no current workspace) vs. "add project" button
|
||||
@@ -47,27 +35,15 @@ export class OpenExistingDialog extends DialogBase {
|
||||
|
||||
async validate(): Promise<boolean> {
|
||||
try {
|
||||
// the selected location should be an existing directory
|
||||
if (this.targetTypeRadioCardGroup?.selectedCardId === constants.Project) {
|
||||
if (this.localRadioButton?.checked) {
|
||||
await this.validateFile(this.filePathTextBox!.value!, constants.Project.toLowerCase());
|
||||
} else {
|
||||
await this.validateClonePath(<string>this.localClonePathTextBox!.value);
|
||||
}
|
||||
|
||||
if (this.workspaceInputBox!.enabled) {
|
||||
await this.validateNewWorkspace(false);
|
||||
}
|
||||
} else if (this.targetTypeRadioCardGroup?.selectedCardId === constants.Workspace) {
|
||||
if (this.localRadioButton?.checked) {
|
||||
await this.validateFile(this.filePathTextBox!.value!, constants.Workspace.toLowerCase());
|
||||
} else {
|
||||
// validate clone location
|
||||
// check if parent folder exists
|
||||
await this.validateClonePath(<string>this.localClonePathTextBox!.value);
|
||||
}
|
||||
if (await this.workspaceService.validateWorkspace() === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.localRadioButton?.checked) {
|
||||
await this.validateFile(this.filePathTextBox!.value!, constants.Project.toLowerCase());
|
||||
} else {
|
||||
await this.validateClonePath(<string>this.localClonePathTextBox!.value);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch (err) {
|
||||
@@ -94,55 +70,27 @@ export class OpenExistingDialog extends DialogBase {
|
||||
|
||||
override async onComplete(): Promise<void> {
|
||||
try {
|
||||
if (this.targetTypeRadioCardGroup?.selectedCardId === constants.Workspace) {
|
||||
// capture that workspace was selected, also if there's already an open workspace that's being replaced
|
||||
TelemetryReporter.createActionEvent(TelemetryViews.OpenExistingDialog, TelemetryActions.OpeningWorkspace)
|
||||
.withAdditionalProperties({ hasWorkspaceOpen: (vscode.workspace.workspaceFile !== undefined).toString() })
|
||||
// save datapoint now because it'll get set to new value during validateWorkspace()
|
||||
const telemetryProps: any = { hasWorkspaceOpen: (vscode.workspace.workspaceFile !== undefined).toString() };
|
||||
|
||||
let addProjectsPromise: Promise<void>;
|
||||
|
||||
if (this.remoteGitRepoRadioButton!.checked) {
|
||||
TelemetryReporter.createActionEvent(TelemetryViews.OpenExistingDialog, TelemetryActions.GitClone)
|
||||
.withAdditionalProperties({ selectedTarget: 'project' })
|
||||
.send();
|
||||
|
||||
if (this.remoteGitRepoRadioButton!.checked) {
|
||||
TelemetryReporter.createActionEvent(TelemetryViews.OpenExistingDialog, TelemetryActions.GitClone)
|
||||
.withAdditionalProperties({ selectedTarget: 'workspace' })
|
||||
.send();
|
||||
|
||||
// show git output channel
|
||||
vscode.commands.executeCommand('git.showOutput');
|
||||
// after this executes, the git extension will show a popup asking if you want to enter the workspace
|
||||
await vscode.commands.executeCommand('git.clone', (<azdataType.InputBoxComponent>this.gitRepoTextBoxComponent?.component).value, this.localClonePathTextBox!.value);
|
||||
} else {
|
||||
await this.workspaceService.enterWorkspace(vscode.Uri.file(this.filePathTextBox!.value!));
|
||||
}
|
||||
addProjectsPromise = this.workspaceService.gitCloneProject((<azdataType.InputBoxComponent>this.gitRepoTextBoxComponent?.component).value!, this.localClonePathTextBox!.value!);
|
||||
} else {
|
||||
// save datapoint now because it'll get set to new value during validateWorkspace()
|
||||
const telemetryProps: any = { hasWorkspaceOpen: (vscode.workspace.workspaceFile !== undefined).toString() };
|
||||
|
||||
const validateWorkspace = await this.workspaceService.validateWorkspace();
|
||||
let addProjectsPromise: Promise<void>;
|
||||
|
||||
if (this.remoteGitRepoRadioButton!.checked) {
|
||||
TelemetryReporter.createActionEvent(TelemetryViews.OpenExistingDialog, TelemetryActions.GitClone)
|
||||
.withAdditionalProperties({ selectedTarget: 'project' })
|
||||
.send();
|
||||
|
||||
addProjectsPromise = this.workspaceService.gitCloneProject((<azdataType.InputBoxComponent>this.gitRepoTextBoxComponent?.component).value!, this.localClonePathTextBox!.value!, vscode.Uri.file(this.workspaceInputBox!.value!));
|
||||
} else {
|
||||
if (validateWorkspace) {
|
||||
telemetryProps.workspaceProjectRelativity = calculateRelativity(this.filePathTextBox!.value!, this.workspaceInputBox!.value!);
|
||||
telemetryProps.cancelled = 'false';
|
||||
addProjectsPromise = this.workspaceService.addProjectsToWorkspace([vscode.Uri.file(this.filePathTextBox!.value!)], vscode.Uri.file(this.workspaceInputBox!.value!));
|
||||
} else {
|
||||
telemetryProps.workspaceProjectRelativity = 'none';
|
||||
telemetryProps.cancelled = 'true';
|
||||
addProjectsPromise = this.workspaceService.addProjectsToWorkspace([vscode.Uri.file(this.filePathTextBox!.value!)], vscode.Uri.file(this.workspaceInputBox!.value!));
|
||||
}
|
||||
}
|
||||
|
||||
TelemetryReporter.createActionEvent(TelemetryViews.OpenExistingDialog, TelemetryActions.OpeningProject)
|
||||
.withAdditionalProperties(telemetryProps)
|
||||
.send();
|
||||
|
||||
await addProjectsPromise;
|
||||
telemetryProps.cancelled = 'false';
|
||||
addProjectsPromise = this.workspaceService.addProjectsToWorkspace([vscode.Uri.file(this.filePathTextBox!.value!)]);
|
||||
}
|
||||
|
||||
TelemetryReporter.createActionEvent(TelemetryViews.OpenExistingDialog, TelemetryActions.OpeningProject)
|
||||
.withAdditionalProperties(telemetryProps)
|
||||
.send();
|
||||
|
||||
await addProjectsPromise;
|
||||
}
|
||||
catch (err) {
|
||||
vscode.window.showErrorMessage(err?.message ? err.message : err);
|
||||
@@ -150,32 +98,6 @@ export class OpenExistingDialog extends DialogBase {
|
||||
}
|
||||
|
||||
protected async initialize(view: azdataType.ModelView): Promise<void> {
|
||||
this.targetTypeRadioCardGroup = view.modelBuilder.radioCardGroup().withProperties<azdataType.RadioCardGroupComponentProperties>({
|
||||
cards: this._targetTypes.map((targetType) => {
|
||||
return <azdataType.RadioCard>{
|
||||
id: targetType.name,
|
||||
label: targetType.name,
|
||||
icon: targetType.icon,
|
||||
descriptions: [
|
||||
{
|
||||
textValue: targetType.name,
|
||||
textStyles: {
|
||||
'font-size': '13px'
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
}),
|
||||
iconHeight: '100px',
|
||||
iconWidth: '100px',
|
||||
cardWidth: '170px',
|
||||
cardHeight: '170px',
|
||||
ariaLabel: constants.TypeTitle,
|
||||
width: '500px',
|
||||
iconPosition: 'top',
|
||||
selectedCardId: constants.Project
|
||||
}).component();
|
||||
|
||||
this.localRadioButton = view.modelBuilder.radioButton().withProperties<azdataType.RadioButtonProperties>({
|
||||
name: 'location',
|
||||
label: constants.Local,
|
||||
@@ -186,7 +108,7 @@ export class OpenExistingDialog extends DialogBase {
|
||||
if (checked) {
|
||||
this.formBuilder?.removeFormItem(<azdataType.FormComponent>this.gitRepoTextBoxComponent);
|
||||
this.formBuilder?.removeFormItem(<azdataType.FormComponent>this.localClonePathComponent);
|
||||
this.formBuilder?.insertFormItem(<azdataType.FormComponent>this.filePathAndButtonComponent, 2);
|
||||
this.formBuilder?.insertFormItem(<azdataType.FormComponent>this.filePathAndButtonComponent, 1);
|
||||
}
|
||||
}));
|
||||
|
||||
@@ -207,8 +129,8 @@ export class OpenExistingDialog extends DialogBase {
|
||||
this.register(this.remoteGitRepoRadioButton.onDidChangeCheckedState(checked => {
|
||||
if (checked) {
|
||||
this.formBuilder?.removeFormItem(<azdataType.FormComponent>this.filePathAndButtonComponent);
|
||||
this.formBuilder?.insertFormItem(<azdataType.FormComponent>this.gitRepoTextBoxComponent, 2);
|
||||
this.formBuilder?.insertFormItem(<azdataType.FormComponent>this.localClonePathComponent, 3);
|
||||
this.formBuilder?.insertFormItem(<azdataType.FormComponent>this.gitRepoTextBoxComponent, 1);
|
||||
this.formBuilder?.insertFormItem(<azdataType.FormComponent>this.localClonePathComponent, 2);
|
||||
}
|
||||
}));
|
||||
|
||||
@@ -221,7 +143,6 @@ export class OpenExistingDialog extends DialogBase {
|
||||
|
||||
this.register(gitRepoTextBox.onTextChanged(() => {
|
||||
gitRepoTextBox.updateProperty('title', this.localClonePathTextBox!.value!);
|
||||
this.updateWorkspaceInputbox(this.localClonePathTextBox!.value!, path.basename(gitRepoTextBox!.value!, '.git'));
|
||||
}));
|
||||
|
||||
this.gitRepoTextBoxComponent = {
|
||||
@@ -238,7 +159,6 @@ export class OpenExistingDialog extends DialogBase {
|
||||
|
||||
this.register(this.localClonePathTextBox.onTextChanged(() => {
|
||||
this.localClonePathTextBox!.updateProperty('title', this.localClonePathTextBox!.value!);
|
||||
this.updateWorkspaceInputbox(this.localClonePathTextBox!.value!, path.basename(gitRepoTextBox!.value!, '.git'));
|
||||
}));
|
||||
|
||||
const localClonePathBrowseFolderButton = view.modelBuilder.button().withProperties<azdataType.ButtonProperties>({
|
||||
@@ -262,7 +182,6 @@ export class OpenExistingDialog extends DialogBase {
|
||||
const selectedFolder = folderUris[0].fsPath;
|
||||
this.localClonePathTextBox!.value = selectedFolder;
|
||||
this.localClonePathTextBox!.updateProperty('title', this.localClonePathTextBox!.value);
|
||||
this.updateWorkspaceInputbox(path.dirname(this.localClonePathTextBox!.value!), path.basename((<azdataType.InputBoxComponent>this.gitRepoTextBoxComponent?.component)!.value!, '.git'));
|
||||
}));
|
||||
|
||||
this.localClonePathComponent = {
|
||||
@@ -280,7 +199,6 @@ export class OpenExistingDialog extends DialogBase {
|
||||
|
||||
this.register(this.filePathTextBox.onTextChanged(() => {
|
||||
this.filePathTextBox!.updateProperty('title', this.filePathTextBox!.value!);
|
||||
this.updateWorkspaceInputbox(path.dirname(this.filePathTextBox!.value!), path.basename(this.filePathTextBox!.value!, path.extname(this.filePathTextBox!.value!)));
|
||||
}));
|
||||
|
||||
const localProjectBrowseFolderButton = view.modelBuilder.button().withProperties<azdataType.ButtonProperties>({
|
||||
@@ -290,11 +208,7 @@ export class OpenExistingDialog extends DialogBase {
|
||||
height: '16px'
|
||||
}).component();
|
||||
this.register(localProjectBrowseFolderButton.onDidClick(async () => {
|
||||
if (this.targetTypeRadioCardGroup?.selectedCardId === constants.Project) {
|
||||
await this.projectBrowse();
|
||||
} else if (this.targetTypeRadioCardGroup?.selectedCardId === constants.Workspace) {
|
||||
await this.workspaceBrowse();
|
||||
}
|
||||
await this.projectBrowse();
|
||||
}));
|
||||
|
||||
const flexContainer = this.createHorizontalContainer(view, [this.filePathTextBox, localProjectBrowseFolderButton]);
|
||||
@@ -303,74 +217,14 @@ export class OpenExistingDialog extends DialogBase {
|
||||
component: flexContainer
|
||||
};
|
||||
|
||||
this.register(this.targetTypeRadioCardGroup.onSelectionChanged(({ cardId }) => {
|
||||
if (cardId === constants.Project) {
|
||||
this.filePathTextBox!.placeHolder = constants.ProjectFilePlaceholder;
|
||||
|
||||
if (this.remoteGitRepoRadioButton!.checked) {
|
||||
this.formBuilder?.removeFormItem(<azdataType.FormComponent>this.filePathAndButtonComponent);
|
||||
this.formBuilder?.insertFormItem(<azdataType.FormComponent>this.gitRepoTextBoxComponent, 2);
|
||||
this.formBuilder?.insertFormItem(<azdataType.FormComponent>this.localClonePathComponent, 3);
|
||||
} else {
|
||||
this.formBuilder?.removeFormItem(<azdataType.FormComponent>this.gitRepoTextBoxComponent);
|
||||
this.formBuilder?.removeFormItem(<azdataType.FormComponent>this.localClonePathComponent);
|
||||
this.formBuilder?.addFormItem(this.filePathAndButtonComponent!);
|
||||
}
|
||||
|
||||
this.formBuilder?.addFormItem(this.workspaceDescriptionFormComponent!);
|
||||
this.formBuilder?.addFormItem(this.workspaceInputFormComponent!);
|
||||
} else if (cardId === constants.Workspace) {
|
||||
this.filePathTextBox!.placeHolder = constants.WorkspacePlaceholder;
|
||||
|
||||
this.formBuilder?.removeFormItem(this.workspaceDescriptionFormComponent!);
|
||||
this.formBuilder?.removeFormItem(this.workspaceInputFormComponent!);
|
||||
|
||||
if (this.remoteGitRepoRadioButton!.checked) {
|
||||
this.formBuilder?.removeFormItem(<azdataType.FormComponent>this.filePathAndButtonComponent);
|
||||
this.formBuilder?.insertFormItem(<azdataType.FormComponent>this.gitRepoTextBoxComponent, 2);
|
||||
this.formBuilder?.insertFormItem(<azdataType.FormComponent>this.localClonePathComponent, 3);
|
||||
}
|
||||
}
|
||||
|
||||
// clear selected file textbox
|
||||
this.filePathTextBox!.value = '';
|
||||
}));
|
||||
|
||||
this.createWorkspaceContainer(view);
|
||||
|
||||
this.formBuilder = view.modelBuilder.formContainer().withFormItems([
|
||||
{
|
||||
title: constants.TypeTitle,
|
||||
required: true,
|
||||
component: this.targetTypeRadioCardGroup,
|
||||
},
|
||||
this.locationRadioButtonFormComponent,
|
||||
this.filePathAndButtonComponent,
|
||||
this.workspaceDescriptionFormComponent!,
|
||||
this.workspaceInputFormComponent!
|
||||
]);
|
||||
await view.initializeModel(this.formBuilder?.component());
|
||||
this.initDialogComplete?.resolve();
|
||||
}
|
||||
|
||||
public async workspaceBrowse(): Promise<void> {
|
||||
const filters: { [name: string]: string[] } = { [constants.Workspace]: [constants.WorkspaceFileExtension.substring(1)] }; // filter already adds a period before the extension
|
||||
const fileUris = await vscode.window.showOpenDialog({
|
||||
canSelectFiles: true,
|
||||
canSelectFolders: false,
|
||||
canSelectMany: false,
|
||||
openLabel: constants.SelectProjectFileActionName,
|
||||
filters: filters
|
||||
});
|
||||
|
||||
if (!fileUris || fileUris.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const workspaceFilePath = fileUris[0].fsPath;
|
||||
this.filePathTextBox!.value = workspaceFilePath;
|
||||
}
|
||||
|
||||
public async projectBrowse(): Promise<void> {
|
||||
const filters: { [name: string]: string[] } = {};
|
||||
const projectTypes = await this.workspaceService.getAllProjectTypes();
|
||||
|
||||
Reference in New Issue
Block a user