mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 10:58:30 -05:00
Handle no azdata API in data-workspace extension gracefully (#15871)
This commit is contained in:
@@ -9,7 +9,7 @@
|
||||
"icon": "images/extension.png",
|
||||
"aiKey": "AIF-37eefaf0-8022-4671-a3fb-64752724682e",
|
||||
"engines": {
|
||||
"vscode": "*",
|
||||
"vscode": ">=1.48.0",
|
||||
"azdata": ">=1.25.0"
|
||||
},
|
||||
"activationEvents": [
|
||||
@@ -172,7 +172,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"fast-glob": "^3.1.0",
|
||||
"@microsoft/ads-extension-telemetry": "^1.1.3",
|
||||
"@microsoft/ads-extension-telemetry": "^1.1.5",
|
||||
"vscode-nls": "^4.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
import * as fs from 'fs';
|
||||
import * as vscode from 'vscode';
|
||||
import type * as azdataType from 'azdata';
|
||||
|
||||
export async function directoryExist(directoryPath: string): Promise<boolean> {
|
||||
const stats = await getFileStatus(directoryPath);
|
||||
@@ -55,3 +56,20 @@ export function getPackageInfo(packageJson: any): IPackageInfo | undefined {
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// Try to load the azdata API - but gracefully handle the failure in case we're running
|
||||
// in a context where the API doesn't exist (such as VS Code)
|
||||
let azdataApi: typeof azdataType | undefined = undefined;
|
||||
try {
|
||||
azdataApi = require('azdata');
|
||||
} catch {
|
||||
// no-op
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the azdata API if it's available in the context this extension is running in.
|
||||
* @returns The azdata API if it's available
|
||||
*/
|
||||
export function getAzdataApi(): typeof azdataType | undefined {
|
||||
return azdataApi;
|
||||
}
|
||||
|
||||
@@ -3,12 +3,12 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as azdata from 'azdata';
|
||||
import type * as azdataType from 'azdata';
|
||||
import * as vscode from 'vscode';
|
||||
import * as path from 'path';
|
||||
import * as constants from '../common/constants';
|
||||
import { IconPathHelper } from '../common/iconHelper';
|
||||
import { directoryExist, fileExist, isCurrentWorkspaceUntitled } from '../common/utils';
|
||||
import { directoryExist, fileExist, getAzdataApi, isCurrentWorkspaceUntitled } from '../common/utils';
|
||||
|
||||
interface Deferred<T> {
|
||||
resolve: (result: T | Promise<T>) => void;
|
||||
@@ -17,15 +17,15 @@ interface Deferred<T> {
|
||||
|
||||
export abstract class DialogBase {
|
||||
protected _toDispose: vscode.Disposable[] = [];
|
||||
public dialogObject: azdata.window.Dialog;
|
||||
public dialogObject: azdataType.window.Dialog;
|
||||
protected initDialogComplete: Deferred<void> | undefined;
|
||||
protected initDialogPromise: Promise<void> = new Promise<void>((resolve, reject) => this.initDialogComplete = { resolve, reject });
|
||||
protected workspaceDescriptionFormComponent: azdata.FormComponent | undefined;
|
||||
public workspaceInputBox: azdata.InputBoxComponent | undefined;
|
||||
protected workspaceInputFormComponent: azdata.FormComponent | undefined;
|
||||
protected workspaceDescriptionFormComponent: azdataType.FormComponent | undefined;
|
||||
public workspaceInputBox: azdataType.InputBoxComponent | undefined;
|
||||
protected workspaceInputFormComponent: azdataType.FormComponent | undefined;
|
||||
|
||||
constructor(dialogTitle: string, dialogName: string, okButtonText: string, dialogWidth: azdata.window.DialogWidth = 600) {
|
||||
this.dialogObject = azdata.window.createModelViewDialog(dialogTitle, dialogName, dialogWidth);
|
||||
constructor(dialogTitle: string, dialogName: string, okButtonText: string, dialogWidth: azdataType.window.DialogWidth = 600) {
|
||||
this.dialogObject = getAzdataApi()!.window.createModelViewDialog(dialogTitle, dialogName, dialogWidth);
|
||||
this.dialogObject.okButton.label = okButtonText;
|
||||
this.register(this.dialogObject.cancelButton.onClick(() => this.onCancelButtonClicked()));
|
||||
this.register(this.dialogObject.okButton.onClick(() => this.onOkButtonClicked()));
|
||||
@@ -34,17 +34,17 @@ export abstract class DialogBase {
|
||||
});
|
||||
}
|
||||
|
||||
protected abstract initialize(view: azdata.ModelView): Promise<void>;
|
||||
protected abstract initialize(view: azdataType.ModelView): Promise<void>;
|
||||
|
||||
abstract validate(): Promise<boolean>;
|
||||
|
||||
public async open(): Promise<void> {
|
||||
const tab = azdata.window.createTab('');
|
||||
tab.registerContent(async (view: azdata.ModelView) => {
|
||||
const tab = getAzdataApi()!.window.createTab('');
|
||||
tab.registerContent(async (view: azdataType.ModelView) => {
|
||||
return this.initialize(view);
|
||||
});
|
||||
this.dialogObject.content = [tab];
|
||||
azdata.window.openDialog(this.dialogObject);
|
||||
getAzdataApi()!.window.openDialog(this.dialogObject);
|
||||
await this.initDialogPromise;
|
||||
}
|
||||
|
||||
@@ -71,15 +71,15 @@ export abstract class DialogBase {
|
||||
protected showErrorMessage(message: string): void {
|
||||
this.dialogObject.message = {
|
||||
text: message,
|
||||
level: azdata.window.MessageLevel.Error
|
||||
level: getAzdataApi()!.window.MessageLevel.Error
|
||||
};
|
||||
}
|
||||
|
||||
public getErrorMessage(): azdata.window.DialogMessage {
|
||||
public getErrorMessage(): azdataType.window.DialogMessage {
|
||||
return this.dialogObject.message;
|
||||
}
|
||||
|
||||
protected createHorizontalContainer(view: azdata.ModelView, items: azdata.Component[]): azdata.FlexContainer {
|
||||
protected createHorizontalContainer(view: azdataType.ModelView, items: azdataType.Component[]): azdataType.FlexContainer {
|
||||
return view.modelBuilder.flexContainer().withItems(items, { CSSStyles: { 'margin-right': '5px', 'margin-bottom': '10px' } }).withLayout({ flexFlow: 'row', alignItems: 'center' }).component();
|
||||
}
|
||||
|
||||
@@ -88,15 +88,15 @@ export abstract class DialogBase {
|
||||
* created if no workspace is currently open
|
||||
* @param view
|
||||
*/
|
||||
protected createWorkspaceContainer(view: azdata.ModelView): void {
|
||||
const workspaceDescription = view.modelBuilder.text().withProperties<azdata.TextComponentProperties>({
|
||||
protected createWorkspaceContainer(view: azdataType.ModelView): void {
|
||||
const workspaceDescription = view.modelBuilder.text().withProperties<azdataType.TextComponentProperties>({
|
||||
value: vscode.workspace.workspaceFile ? constants.AddProjectToCurrentWorkspace : constants.NewWorkspaceWillBeCreated,
|
||||
CSSStyles: { 'margin-top': '3px', 'margin-bottom': '0px' }
|
||||
}).component();
|
||||
|
||||
const initialWorkspaceInputBoxValue = !!vscode.workspace.workspaceFile && !isCurrentWorkspaceUntitled() ? vscode.workspace.workspaceFile.fsPath : '';
|
||||
|
||||
this.workspaceInputBox = view.modelBuilder.inputBox().withProperties<azdata.InputBoxProperties>({
|
||||
this.workspaceInputBox = view.modelBuilder.inputBox().withProperties<azdataType.InputBoxProperties>({
|
||||
ariaLabel: constants.WorkspaceLocationTitle,
|
||||
width: constants.DefaultInputWidth,
|
||||
enabled: !vscode.workspace.workspaceFile || isCurrentWorkspaceUntitled(), // want it editable if no saved workspace is open
|
||||
@@ -104,7 +104,7 @@ export abstract class DialogBase {
|
||||
title: initialWorkspaceInputBoxValue // hovertext for if file path is too long to be seen in textbox
|
||||
}).component();
|
||||
|
||||
const browseFolderButton = view.modelBuilder.button().withProperties<azdata.ButtonProperties>({
|
||||
const browseFolderButton = view.modelBuilder.button().withProperties<azdataType.ButtonProperties>({
|
||||
ariaLabel: constants.BrowseButtonText,
|
||||
iconPath: IconPathHelper.folder,
|
||||
height: '16px',
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as azdata from 'azdata';
|
||||
import type * as azdataType from 'azdata';
|
||||
import * as vscode from 'vscode';
|
||||
import * as path from 'path';
|
||||
import { DialogBase } from './dialogBase';
|
||||
@@ -84,11 +84,11 @@ export class NewProjectDialog extends DialogBase {
|
||||
}
|
||||
}
|
||||
|
||||
protected async initialize(view: azdata.ModelView): Promise<void> {
|
||||
protected async initialize(view: azdataType.ModelView): Promise<void> {
|
||||
const allProjectTypes = await this.workspaceService.getAllProjectTypes();
|
||||
const projectTypeRadioCardGroup = view.modelBuilder.radioCardGroup().withProperties<azdata.RadioCardGroupComponentProperties>({
|
||||
const projectTypeRadioCardGroup = view.modelBuilder.radioCardGroup().withProperties<azdataType.RadioCardGroupComponentProperties>({
|
||||
cards: allProjectTypes.map((projectType: IProjectType) => {
|
||||
return <azdata.RadioCard>{
|
||||
return <azdataType.RadioCard>{
|
||||
id: projectType.id,
|
||||
label: projectType.displayName,
|
||||
icon: projectType.icon,
|
||||
@@ -119,7 +119,7 @@ export class NewProjectDialog extends DialogBase {
|
||||
this.model.projectTypeId = e.cardId;
|
||||
}));
|
||||
|
||||
const projectNameTextBox = view.modelBuilder.inputBox().withProperties<azdata.InputBoxProperties>({
|
||||
const projectNameTextBox = view.modelBuilder.inputBox().withProperties<azdataType.InputBoxProperties>({
|
||||
ariaLabel: constants.ProjectNameTitle,
|
||||
placeHolder: constants.ProjectNamePlaceholder,
|
||||
required: true,
|
||||
@@ -133,7 +133,7 @@ export class NewProjectDialog extends DialogBase {
|
||||
this.updateWorkspaceInputbox(path.join(this.model.location, this.model.name), this.model.name);
|
||||
}));
|
||||
|
||||
const locationTextBox = view.modelBuilder.inputBox().withProperties<azdata.InputBoxProperties>({
|
||||
const locationTextBox = view.modelBuilder.inputBox().withProperties<azdataType.InputBoxProperties>({
|
||||
ariaLabel: constants.ProjectLocationTitle,
|
||||
placeHolder: constants.ProjectLocationPlaceholder,
|
||||
required: true,
|
||||
@@ -146,7 +146,7 @@ export class NewProjectDialog extends DialogBase {
|
||||
this.updateWorkspaceInputbox(path.join(this.model.location, this.model.name), this.model.name);
|
||||
}));
|
||||
|
||||
const browseFolderButton = view.modelBuilder.button().withProperties<azdata.ButtonProperties>({
|
||||
const browseFolderButton = view.modelBuilder.button().withProperties<azdataType.ButtonProperties>({
|
||||
ariaLabel: constants.BrowseButtonText,
|
||||
iconPath: IconPathHelper.folder,
|
||||
height: '16px',
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as azdata from 'azdata';
|
||||
import type * as azdataType from 'azdata';
|
||||
import * as vscode from 'vscode';
|
||||
import * as path from 'path';
|
||||
import { DialogBase } from './dialogBase';
|
||||
@@ -15,16 +15,16 @@ import { calculateRelativity, TelemetryActions, TelemetryReporter, TelemetryView
|
||||
import { defaultProjectSaveLocation } from '../common/projectLocationHelper';
|
||||
|
||||
export class OpenExistingDialog extends DialogBase {
|
||||
public targetTypeRadioCardGroup: azdata.RadioCardGroupComponent | undefined;
|
||||
public filePathTextBox: azdata.InputBoxComponent | undefined;
|
||||
public filePathAndButtonComponent: azdata.FormComponent | undefined;
|
||||
public gitRepoTextBoxComponent: azdata.FormComponent | undefined;
|
||||
public localClonePathComponent: azdata.FormComponent | undefined;
|
||||
public localClonePathTextBox: azdata.InputBoxComponent | undefined;
|
||||
public localRadioButton: azdata.RadioButtonComponent | undefined;
|
||||
public remoteGitRepoRadioButton: azdata.RadioButtonComponent | undefined;
|
||||
public locationRadioButtonFormComponent: azdata.FormComponent | undefined;
|
||||
public formBuilder: azdata.FormBuilder | undefined;
|
||||
public targetTypeRadioCardGroup: azdataType.RadioCardGroupComponent | undefined;
|
||||
public filePathTextBox: azdataType.InputBoxComponent | undefined;
|
||||
public filePathAndButtonComponent: azdataType.FormComponent | undefined;
|
||||
public gitRepoTextBoxComponent: azdataType.FormComponent | undefined;
|
||||
public localClonePathComponent: azdataType.FormComponent | undefined;
|
||||
public localClonePathTextBox: azdataType.InputBoxComponent | undefined;
|
||||
public localRadioButton: azdataType.RadioButtonComponent | undefined;
|
||||
public remoteGitRepoRadioButton: azdataType.RadioButtonComponent | undefined;
|
||||
public locationRadioButtonFormComponent: azdataType.FormComponent | undefined;
|
||||
public formBuilder: azdataType.FormBuilder | undefined;
|
||||
|
||||
private _targetTypes = [
|
||||
{
|
||||
@@ -108,7 +108,7 @@ export class OpenExistingDialog extends DialogBase {
|
||||
// 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', (<azdata.InputBoxComponent>this.gitRepoTextBoxComponent?.component).value, this.localClonePathTextBox!.value);
|
||||
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!));
|
||||
}
|
||||
@@ -124,7 +124,7 @@ export class OpenExistingDialog extends DialogBase {
|
||||
.withAdditionalProperties({ selectedTarget: 'project' })
|
||||
.send();
|
||||
|
||||
addProjectsPromise = this.workspaceService.gitCloneProject((<azdata.InputBoxComponent>this.gitRepoTextBoxComponent?.component).value!, this.localClonePathTextBox!.value!, vscode.Uri.file(this.workspaceInputBox!.value!));
|
||||
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!);
|
||||
@@ -149,10 +149,10 @@ export class OpenExistingDialog extends DialogBase {
|
||||
}
|
||||
}
|
||||
|
||||
protected async initialize(view: azdata.ModelView): Promise<void> {
|
||||
this.targetTypeRadioCardGroup = view.modelBuilder.radioCardGroup().withProperties<azdata.RadioCardGroupComponentProperties>({
|
||||
protected async initialize(view: azdataType.ModelView): Promise<void> {
|
||||
this.targetTypeRadioCardGroup = view.modelBuilder.radioCardGroup().withProperties<azdataType.RadioCardGroupComponentProperties>({
|
||||
cards: this._targetTypes.map((targetType) => {
|
||||
return <azdata.RadioCard>{
|
||||
return <azdataType.RadioCard>{
|
||||
id: targetType.name,
|
||||
label: targetType.name,
|
||||
icon: targetType.icon,
|
||||
@@ -176,7 +176,7 @@ export class OpenExistingDialog extends DialogBase {
|
||||
selectedCardId: constants.Project
|
||||
}).component();
|
||||
|
||||
this.localRadioButton = view.modelBuilder.radioButton().withProperties<azdata.RadioButtonProperties>({
|
||||
this.localRadioButton = view.modelBuilder.radioButton().withProperties<azdataType.RadioButtonProperties>({
|
||||
name: 'location',
|
||||
label: constants.Local,
|
||||
checked: true
|
||||
@@ -184,13 +184,13 @@ export class OpenExistingDialog extends DialogBase {
|
||||
|
||||
this.register(this.localRadioButton.onDidChangeCheckedState(checked => {
|
||||
if (checked) {
|
||||
this.formBuilder?.removeFormItem(<azdata.FormComponent>this.gitRepoTextBoxComponent);
|
||||
this.formBuilder?.removeFormItem(<azdata.FormComponent>this.localClonePathComponent);
|
||||
this.formBuilder?.insertFormItem(<azdata.FormComponent>this.filePathAndButtonComponent, 2);
|
||||
this.formBuilder?.removeFormItem(<azdataType.FormComponent>this.gitRepoTextBoxComponent);
|
||||
this.formBuilder?.removeFormItem(<azdataType.FormComponent>this.localClonePathComponent);
|
||||
this.formBuilder?.insertFormItem(<azdataType.FormComponent>this.filePathAndButtonComponent, 2);
|
||||
}
|
||||
}));
|
||||
|
||||
this.remoteGitRepoRadioButton = view.modelBuilder.radioButton().withProperties<azdata.RadioButtonProperties>({
|
||||
this.remoteGitRepoRadioButton = view.modelBuilder.radioButton().withProperties<azdataType.RadioButtonProperties>({
|
||||
name: 'location',
|
||||
label: constants.RemoteGitRepo
|
||||
}).component();
|
||||
@@ -206,13 +206,13 @@ export class OpenExistingDialog extends DialogBase {
|
||||
|
||||
this.register(this.remoteGitRepoRadioButton.onDidChangeCheckedState(checked => {
|
||||
if (checked) {
|
||||
this.formBuilder?.removeFormItem(<azdata.FormComponent>this.filePathAndButtonComponent);
|
||||
this.formBuilder?.insertFormItem(<azdata.FormComponent>this.gitRepoTextBoxComponent, 2);
|
||||
this.formBuilder?.insertFormItem(<azdata.FormComponent>this.localClonePathComponent, 3);
|
||||
this.formBuilder?.removeFormItem(<azdataType.FormComponent>this.filePathAndButtonComponent);
|
||||
this.formBuilder?.insertFormItem(<azdataType.FormComponent>this.gitRepoTextBoxComponent, 2);
|
||||
this.formBuilder?.insertFormItem(<azdataType.FormComponent>this.localClonePathComponent, 3);
|
||||
}
|
||||
}));
|
||||
|
||||
const gitRepoTextBox = view.modelBuilder.inputBox().withProperties<azdata.InputBoxProperties>({
|
||||
const gitRepoTextBox = view.modelBuilder.inputBox().withProperties<azdataType.InputBoxProperties>({
|
||||
ariaLabel: constants.GitRepoUrlTitle,
|
||||
placeHolder: constants.GitRepoUrlPlaceholder,
|
||||
required: true,
|
||||
@@ -229,7 +229,7 @@ export class OpenExistingDialog extends DialogBase {
|
||||
component: gitRepoTextBox
|
||||
};
|
||||
|
||||
this.localClonePathTextBox = view.modelBuilder.inputBox().withProperties<azdata.InputBoxProperties>({
|
||||
this.localClonePathTextBox = view.modelBuilder.inputBox().withProperties<azdataType.InputBoxProperties>({
|
||||
ariaLabel: constants.LocalClonePathTitle,
|
||||
placeHolder: constants.LocalClonePathPlaceholder,
|
||||
required: true,
|
||||
@@ -241,7 +241,7 @@ export class OpenExistingDialog extends DialogBase {
|
||||
this.updateWorkspaceInputbox(this.localClonePathTextBox!.value!, path.basename(gitRepoTextBox!.value!, '.git'));
|
||||
}));
|
||||
|
||||
const localClonePathBrowseFolderButton = view.modelBuilder.button().withProperties<azdata.ButtonProperties>({
|
||||
const localClonePathBrowseFolderButton = view.modelBuilder.button().withProperties<azdataType.ButtonProperties>({
|
||||
ariaLabel: constants.BrowseButtonText,
|
||||
iconPath: IconPathHelper.folder,
|
||||
width: '18px',
|
||||
@@ -262,7 +262,7 @@ 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((<azdata.InputBoxComponent>this.gitRepoTextBoxComponent?.component)!.value!, '.git'));
|
||||
this.updateWorkspaceInputbox(path.dirname(this.localClonePathTextBox!.value!), path.basename((<azdataType.InputBoxComponent>this.gitRepoTextBoxComponent?.component)!.value!, '.git'));
|
||||
}));
|
||||
|
||||
this.localClonePathComponent = {
|
||||
@@ -271,7 +271,7 @@ export class OpenExistingDialog extends DialogBase {
|
||||
required: true
|
||||
};
|
||||
|
||||
this.filePathTextBox = view.modelBuilder.inputBox().withProperties<azdata.InputBoxProperties>({
|
||||
this.filePathTextBox = view.modelBuilder.inputBox().withProperties<azdataType.InputBoxProperties>({
|
||||
ariaLabel: constants.LocationSelectorTitle,
|
||||
placeHolder: constants.ProjectFilePlaceholder,
|
||||
required: true,
|
||||
@@ -283,7 +283,7 @@ export class OpenExistingDialog extends DialogBase {
|
||||
this.updateWorkspaceInputbox(path.dirname(this.filePathTextBox!.value!), path.basename(this.filePathTextBox!.value!, path.extname(this.filePathTextBox!.value!)));
|
||||
}));
|
||||
|
||||
const localProjectBrowseFolderButton = view.modelBuilder.button().withProperties<azdata.ButtonProperties>({
|
||||
const localProjectBrowseFolderButton = view.modelBuilder.button().withProperties<azdataType.ButtonProperties>({
|
||||
ariaLabel: constants.BrowseButtonText,
|
||||
iconPath: IconPathHelper.folder,
|
||||
width: '18px',
|
||||
@@ -308,12 +308,12 @@ export class OpenExistingDialog extends DialogBase {
|
||||
this.filePathTextBox!.placeHolder = constants.ProjectFilePlaceholder;
|
||||
|
||||
if (this.remoteGitRepoRadioButton!.checked) {
|
||||
this.formBuilder?.removeFormItem(<azdata.FormComponent>this.filePathAndButtonComponent);
|
||||
this.formBuilder?.insertFormItem(<azdata.FormComponent>this.gitRepoTextBoxComponent, 2);
|
||||
this.formBuilder?.insertFormItem(<azdata.FormComponent>this.localClonePathComponent, 3);
|
||||
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(<azdata.FormComponent>this.gitRepoTextBoxComponent);
|
||||
this.formBuilder?.removeFormItem(<azdata.FormComponent>this.localClonePathComponent);
|
||||
this.formBuilder?.removeFormItem(<azdataType.FormComponent>this.gitRepoTextBoxComponent);
|
||||
this.formBuilder?.removeFormItem(<azdataType.FormComponent>this.localClonePathComponent);
|
||||
this.formBuilder?.addFormItem(this.filePathAndButtonComponent!);
|
||||
}
|
||||
|
||||
@@ -326,9 +326,9 @@ export class OpenExistingDialog extends DialogBase {
|
||||
this.formBuilder?.removeFormItem(this.workspaceInputFormComponent!);
|
||||
|
||||
if (this.remoteGitRepoRadioButton!.checked) {
|
||||
this.formBuilder?.removeFormItem(<azdata.FormComponent>this.filePathAndButtonComponent);
|
||||
this.formBuilder?.insertFormItem(<azdata.FormComponent>this.gitRepoTextBoxComponent, 2);
|
||||
this.formBuilder?.insertFormItem(<azdata.FormComponent>this.localClonePathComponent, 3);
|
||||
this.formBuilder?.removeFormItem(<azdataType.FormComponent>this.filePathAndButtonComponent);
|
||||
this.formBuilder?.insertFormItem(<azdataType.FormComponent>this.gitRepoTextBoxComponent, 2);
|
||||
this.formBuilder?.insertFormItem(<azdataType.FormComponent>this.localClonePathComponent, 3);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,23 +3,23 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as azdata from 'azdata';
|
||||
import type * as azdataType from 'azdata';
|
||||
import { IDashboardColumnInfo, IDashboardTable, IProjectAction, IProjectActionGroup, IProjectProvider, WorkspaceTreeItem } from 'dataworkspace';
|
||||
import * as path from 'path';
|
||||
import * as vscode from 'vscode';
|
||||
import * as constants from '../common/constants';
|
||||
import { IconPathHelper } from '../common/iconHelper';
|
||||
import { IWorkspaceService } from '../common/interfaces';
|
||||
import { fileExist } from '../common/utils';
|
||||
import { fileExist, getAzdataApi } from '../common/utils';
|
||||
|
||||
export class ProjectDashboard {
|
||||
|
||||
private dashboard: azdata.window.ModelViewDashboard | undefined;
|
||||
private modelView: azdata.ModelView | undefined;
|
||||
private dashboard: azdataType.window.ModelViewDashboard | undefined;
|
||||
private modelView: azdataType.ModelView | undefined;
|
||||
private projectProvider: IProjectProvider | undefined;
|
||||
private overviewTab: azdata.DashboardTab | undefined;
|
||||
private rootContainer: azdata.FlexContainer | undefined;
|
||||
private tableContainer: azdata.Component | undefined;
|
||||
private overviewTab: azdataType.DashboardTab | undefined;
|
||||
private rootContainer: azdataType.FlexContainer | undefined;
|
||||
private tableContainer: azdataType.Component | undefined;
|
||||
|
||||
constructor(private _workspaceService: IWorkspaceService, private _treeItem: WorkspaceTreeItem) {
|
||||
}
|
||||
@@ -45,8 +45,8 @@ export class ProjectDashboard {
|
||||
}
|
||||
|
||||
private async createDashboard(title: string, projectFilePath: string): Promise<void> {
|
||||
this.dashboard = azdata.window.createModelViewDashboard(title, 'ProjectDashboard', { alwaysShowTabs: false });
|
||||
this.dashboard.registerTabs(async (modelView: azdata.ModelView) => {
|
||||
this.dashboard = getAzdataApi()!.window.createModelViewDashboard(title, 'ProjectDashboard', { alwaysShowTabs: false });
|
||||
this.dashboard.registerTabs(async (modelView: azdataType.ModelView) => {
|
||||
this.modelView = modelView;
|
||||
|
||||
this.overviewTab = {
|
||||
@@ -61,11 +61,11 @@ export class ProjectDashboard {
|
||||
});
|
||||
}
|
||||
|
||||
private createToolbarContainer(projectFilePath: string): azdata.ToolbarContainer {
|
||||
private createToolbarContainer(projectFilePath: string): azdataType.ToolbarContainer {
|
||||
const projectActions: (IProjectAction | IProjectActionGroup)[] = this.projectProvider!.projectToolbarActions;
|
||||
|
||||
// Add actions as buttons
|
||||
const buttons: azdata.ToolbarComponent[] = [];
|
||||
const buttons: azdataType.ToolbarComponent[] = [];
|
||||
|
||||
const projectActionsLength = projectActions.length;
|
||||
|
||||
@@ -84,7 +84,7 @@ export class ProjectDashboard {
|
||||
});
|
||||
|
||||
const refreshButton = this.modelView!.modelBuilder.button()
|
||||
.withProperties<azdata.ButtonProperties>({
|
||||
.withProperties<azdataType.ButtonProperties>({
|
||||
label: constants.Refresh,
|
||||
iconPath: IconPathHelper.refresh,
|
||||
height: '20px'
|
||||
@@ -108,9 +108,9 @@ export class ProjectDashboard {
|
||||
return obj.id !== undefined;
|
||||
}
|
||||
|
||||
private createButton(projectAction: IProjectAction): azdata.ButtonComponent {
|
||||
private createButton(projectAction: IProjectAction): azdataType.ButtonComponent {
|
||||
let button = this.modelView!.modelBuilder.button()
|
||||
.withProperties<azdata.ButtonProperties>({
|
||||
.withProperties<azdataType.ButtonProperties>({
|
||||
label: projectAction.id,
|
||||
iconPath: projectAction.icon,
|
||||
height: '20px'
|
||||
@@ -123,7 +123,7 @@ export class ProjectDashboard {
|
||||
return button;
|
||||
}
|
||||
|
||||
private createContainer(title: string, projectFilePath: string): azdata.FlexContainer {
|
||||
private createContainer(title: string, projectFilePath: string): azdataType.FlexContainer {
|
||||
this.rootContainer = this.modelView!.modelBuilder.flexContainer().withLayout(
|
||||
{
|
||||
flexFlow: 'column',
|
||||
@@ -143,7 +143,7 @@ export class ProjectDashboard {
|
||||
/**
|
||||
* Create header with title, location and background
|
||||
*/
|
||||
private createHeader(title: string, location: string): azdata.Component {
|
||||
private createHeader(title: string, location: string): azdataType.Component {
|
||||
const headerContainer = this.modelView!.modelBuilder.flexContainer().withLayout(
|
||||
{
|
||||
flexFlow: 'column',
|
||||
@@ -159,13 +159,13 @@ export class ProjectDashboard {
|
||||
}).component();
|
||||
|
||||
const titleLabel = this.modelView!.modelBuilder.text()
|
||||
.withProperties<azdata.TextComponentProperties>({ value: title, CSSStyles: { 'margin-block-start': '20px', 'margin-block-end': '0px' } })
|
||||
.withProperties<azdataType.TextComponentProperties>({ value: title, CSSStyles: { 'margin-block-start': '20px', 'margin-block-end': '0px' } })
|
||||
.component();
|
||||
header.addItem(titleLabel, { CSSStyles: { 'padding-left': '34px', 'padding-top': '15px', 'font-size': '36px', 'font-weight': '400' } });
|
||||
|
||||
const projectFolderPath = path.dirname(location);
|
||||
const locationLabel = this.modelView!.modelBuilder.text()
|
||||
.withProperties<azdata.TextComponentProperties>({ value: projectFolderPath, CSSStyles: { 'margin-block-start': '20px', 'margin-block-end': '0px' } })
|
||||
.withProperties<azdataType.TextComponentProperties>({ value: projectFolderPath, CSSStyles: { 'margin-block-start': '20px', 'margin-block-end': '0px' } })
|
||||
.component();
|
||||
header.addItem(locationLabel, { CSSStyles: { 'padding-left': '34px', 'padding-top': '15px', 'padding-bottom': '50px', 'font-size': '16px' } });
|
||||
|
||||
@@ -188,7 +188,7 @@ export class ProjectDashboard {
|
||||
/**
|
||||
* Adds all the tables to the container
|
||||
*/
|
||||
private createTables(projectFile: string): azdata.Component {
|
||||
private createTables(projectFile: string): azdataType.Component {
|
||||
const dashboardData: IDashboardTable[] = this.projectProvider!.getDashboardComponents(projectFile);
|
||||
|
||||
const tableContainer = this.modelView!.modelBuilder.flexContainer().withLayout(
|
||||
@@ -200,22 +200,22 @@ export class ProjectDashboard {
|
||||
|
||||
dashboardData.forEach(info => {
|
||||
const tableNameLabel = this.modelView!.modelBuilder.text()
|
||||
.withProperties<azdata.TextComponentProperties>({ value: info.name, CSSStyles: { 'margin-block-start': '30px', 'margin-block-end': '0px' } })
|
||||
.withProperties<azdataType.TextComponentProperties>({ value: info.name, CSSStyles: { 'margin-block-start': '30px', 'margin-block-end': '0px' } })
|
||||
.component();
|
||||
tableContainer.addItem(tableNameLabel, { CSSStyles: { 'padding-left': '25px', 'padding-bottom': '20px', ...constants.cssStyles.title } });
|
||||
|
||||
if (info.data.length === 0) {
|
||||
const noDataText = constants.noPreviousData(info.name.toLocaleLowerCase());
|
||||
const noDataLabel = this.modelView!.modelBuilder.text()
|
||||
.withProperties<azdata.TextComponentProperties>({ value: noDataText })
|
||||
.withProperties<azdataType.TextComponentProperties>({ value: noDataText })
|
||||
.component();
|
||||
tableContainer.addItem(noDataLabel, { CSSStyles: { 'padding-left': '25px', 'padding-bottom': '20px' } });
|
||||
} else {
|
||||
const columns: azdata.DeclarativeTableColumn[] = [];
|
||||
const columns: azdataType.DeclarativeTableColumn[] = [];
|
||||
info.columns.forEach((column: IDashboardColumnInfo) => {
|
||||
let col = {
|
||||
displayName: column.displayName,
|
||||
valueType: column.type === 'icon' ? azdata.DeclarativeDataType.component : azdata.DeclarativeDataType.string,
|
||||
valueType: column.type === 'icon' ? getAzdataApi()!.DeclarativeDataType.component : getAzdataApi()!.DeclarativeDataType.string,
|
||||
isReadOnly: true,
|
||||
width: column.width,
|
||||
headerCssStyles: {
|
||||
@@ -229,21 +229,21 @@ export class ProjectDashboard {
|
||||
columns.push(col);
|
||||
});
|
||||
|
||||
const data: azdata.DeclarativeTableCellValue[][] = [];
|
||||
const data: azdataType.DeclarativeTableCellValue[][] = [];
|
||||
info.data.forEach(values => {
|
||||
const columnValue: azdata.DeclarativeTableCellValue[] = [];
|
||||
const columnValue: azdataType.DeclarativeTableCellValue[] = [];
|
||||
values.forEach(val => {
|
||||
if (typeof val === 'string') {
|
||||
columnValue.push({ value: val });
|
||||
} else {
|
||||
const iconComponent = this.modelView!.modelBuilder.image().withProperties<azdata.ImageComponentProperties>({
|
||||
const iconComponent = this.modelView!.modelBuilder.image().withProperties<azdataType.ImageComponentProperties>({
|
||||
iconPath: val.icon,
|
||||
width: '15px',
|
||||
height: '15px',
|
||||
iconHeight: '15px',
|
||||
iconWidth: '15px'
|
||||
}).component();
|
||||
const stringComponent = this.modelView!.modelBuilder.text().withProperties<azdata.TextComponentProperties>({
|
||||
const stringComponent = this.modelView!.modelBuilder.text().withProperties<azdataType.TextComponentProperties>({
|
||||
value: val.text,
|
||||
CSSStyles: { 'margin-block-start': 'auto', 'block-size': 'auto', 'margin-block-end': '0px' }
|
||||
}).component();
|
||||
@@ -256,7 +256,7 @@ export class ProjectDashboard {
|
||||
});
|
||||
|
||||
const table = this.modelView!.modelBuilder.declarativeTable()
|
||||
.withProperties<azdata.DeclarativeTableProperties>({ columns: columns, dataValues: data, ariaLabel: info.name, CSSStyles: { 'margin-left': '30px' } }).component();
|
||||
.withProperties<azdataType.DeclarativeTableProperties>({ columns: columns, dataValues: data, ariaLabel: info.name, CSSStyles: { 'margin-left': '30px' } }).component();
|
||||
|
||||
tableContainer.addItem(table);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as azdata from 'azdata';
|
||||
import * as vscode from 'vscode';
|
||||
import * as dataworkspace from 'dataworkspace';
|
||||
import * as path from 'path';
|
||||
@@ -14,7 +13,7 @@ import { IWorkspaceService } from '../common/interfaces';
|
||||
import { ProjectProviderRegistry } from '../common/projectProviderRegistry';
|
||||
import Logger from '../common/logger';
|
||||
import { TelemetryReporter, TelemetryViews, calculateRelativity, TelemetryActions } from '../common/telemetry';
|
||||
import { isCurrentWorkspaceUntitled } from '../common/utils';
|
||||
import { getAzdataApi, isCurrentWorkspaceUntitled } from '../common/utils';
|
||||
|
||||
const WorkspaceConfigurationName = 'dataworkspace';
|
||||
const ProjectsConfigurationName = 'projects';
|
||||
@@ -58,9 +57,9 @@ export class WorkspaceService implements IWorkspaceService {
|
||||
|
||||
if (isCurrentWorkspaceUntitled()) {
|
||||
vscode.workspace.updateWorkspaceFolders(vscode.workspace.workspaceFolders!.length, null, { uri: projectFolder });
|
||||
await azdata.workspace.saveAndEnterWorkspace(workspaceFile!);
|
||||
await getAzdataApi()?.workspace.saveAndEnterWorkspace(workspaceFile!);
|
||||
} else {
|
||||
await azdata.workspace.createAndEnterWorkspace(projectFolder, workspaceFile);
|
||||
await getAzdataApi()?.workspace.createAndEnterWorkspace(projectFolder, workspaceFile);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,7 +97,7 @@ export class WorkspaceService implements IWorkspaceService {
|
||||
async enterWorkspace(workspaceFile: vscode.Uri): Promise<void> {
|
||||
const result = await vscode.window.showWarningMessage(constants.EnterWorkspaceConfirmation, { modal: true }, constants.OkButtonText);
|
||||
if (result === constants.OkButtonText) {
|
||||
await azdata.workspace.enterWorkspace(workspaceFile);
|
||||
await getAzdataApi()?.workspace.enterWorkspace(workspaceFile);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -182,10 +182,10 @@
|
||||
resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.2.tgz#26520bf09abe4a5644cd5414e37125a8954241dd"
|
||||
integrity sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw==
|
||||
|
||||
"@microsoft/ads-extension-telemetry@^1.1.3":
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/@microsoft/ads-extension-telemetry/-/ads-extension-telemetry-1.1.3.tgz#54160eefa21f2a536622b0617f3c3f2018cf9c87"
|
||||
integrity sha512-+h6hM9oOA6Zj/N0nCGPzRgydR0YHiHpNJoNlv6a/ziWXO3RYSbQX+3U/PpT3gEA6+8RwByf6RVICo7uIGBy1LQ==
|
||||
"@microsoft/ads-extension-telemetry@^1.1.5":
|
||||
version "1.1.5"
|
||||
resolved "https://registry.yarnpkg.com/@microsoft/ads-extension-telemetry/-/ads-extension-telemetry-1.1.5.tgz#4f2ec72a7730131fdd939ace307a1ff5feef16b6"
|
||||
integrity sha512-Xq8qQi8CHxXPTCO5cRvJABgtVdFO42kQgVoHkBc7ByBhN4VMdw/kakbWgVtHbMl4oRARtpncE2xYCiVeZHK6XA==
|
||||
dependencies:
|
||||
vscode-extension-telemetry "^0.1.6"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user