Add nupkg option to add database reference dialog (#22772)

* add nupkg option to add database reference dialog

* Add required indicator

* only show nupkg radio button for SDK-style projects

* fix enable ok button

* hookup

* fix typo
This commit is contained in:
Kim Santiago
2023-04-19 10:09:15 -07:00
committed by GitHub
parent c29bb27d9e
commit 39a28c5f51
3 changed files with 111 additions and 10 deletions

View File

@@ -292,6 +292,10 @@ export const referenceRadioButtonsGroupTitle = localize('referenceRadioButtonsGr
export const projectLabel = localize('projectLocString', "Project"); export const projectLabel = localize('projectLocString', "Project");
export const systemDatabase = localize('systemDatabase', "System database"); export const systemDatabase = localize('systemDatabase', "System database");
export const dacpacText = localize('dacpacText', "Data-tier application (.dacpac)"); export const dacpacText = localize('dacpacText', "Data-tier application (.dacpac)");
export const nupkgText = localize('nupkgText', "Published data-tier application (.nupkg)");
export const nupkgNamePlaceholder = localize('nupkgNamePlaceholder', "NuGet package name");
export const version = localize('version', "Version");
export const versionPlaceholder = localize('versionPlaceholder', "NuGet package version");
export const selectDacpac = localize('selectDacpac', "Select .dacpac"); export const selectDacpac = localize('selectDacpac', "Select .dacpac");
export const sameDatabase = localize('sameDatabase', "Same database"); export const sameDatabase = localize('sameDatabase', "Same database");
export const differentDbSameServer = localize('differentDbSameServer', "Different database, same server"); export const differentDbSameServer = localize('differentDbSameServer', "Different database, same server");

View File

@@ -27,7 +27,7 @@ import { ShellCommandOptions } from '../tools/shellExecutionHelper';
import { BuildHelper } from '../tools/buildHelper'; import { BuildHelper } from '../tools/buildHelper';
import { readPublishProfile, savePublishProfile } from '../models/publishProfile/publishProfile'; import { readPublishProfile, savePublishProfile } from '../models/publishProfile/publishProfile';
import { AddDatabaseReferenceDialog } from '../dialogs/addDatabaseReferenceDialog'; import { AddDatabaseReferenceDialog } from '../dialogs/addDatabaseReferenceDialog';
import { ISystemDatabaseReferenceSettings, IDacpacReferenceSettings, IProjectReferenceSettings } from '../models/IDatabaseReferenceSettings'; import { ISystemDatabaseReferenceSettings, IDacpacReferenceSettings, IProjectReferenceSettings, INugetPackageReferenceSettings } from '../models/IDatabaseReferenceSettings';
import { DatabaseReferenceTreeItem } from '../models/tree/databaseReferencesTreeItem'; import { DatabaseReferenceTreeItem } from '../models/tree/databaseReferencesTreeItem';
import { CreateProjectFromDatabaseDialog } from '../dialogs/createProjectFromDatabaseDialog'; import { CreateProjectFromDatabaseDialog } from '../dialogs/createProjectFromDatabaseDialog';
import { UpdateProjectFromDatabaseDialog } from '../dialogs/updateProjectFromDatabaseDialog'; import { UpdateProjectFromDatabaseDialog } from '../dialogs/updateProjectFromDatabaseDialog';
@@ -65,7 +65,7 @@ export enum TaskExecutionMode {
executeAndScript = 2 executeAndScript = 2
} }
export type AddDatabaseReferenceSettings = ISystemDatabaseReferenceSettings | IDacpacReferenceSettings | IProjectReferenceSettings; export type AddDatabaseReferenceSettings = ISystemDatabaseReferenceSettings | IDacpacReferenceSettings | IProjectReferenceSettings | INugetPackageReferenceSettings;
interface FileWatcherStatus { interface FileWatcherStatus {
fileWatcher: vscode.FileSystemWatcher; fileWatcher: vscode.FileSystemWatcher;
@@ -1193,11 +1193,13 @@ export class ProjectsController {
await project.addProjectReference(projectReferenceSettings); await project.addProjectReference(projectReferenceSettings);
} else if ((<ISystemDatabaseReferenceSettings>settings).systemDb !== undefined) { } else if ((<ISystemDatabaseReferenceSettings>settings).systemDb !== undefined) {
await project.addSystemDatabaseReference(<ISystemDatabaseReferenceSettings>settings); await project.addSystemDatabaseReference(<ISystemDatabaseReferenceSettings>settings);
} else { } else if ((<IDacpacReferenceSettings>settings).dacpacFileLocation !== undefined) {
// update dacpacFileLocation to relative path to project file // update dacpacFileLocation to relative path to project file
const dacpacRefSettings = settings as IDacpacReferenceSettings; const dacpacRefSettings = settings as IDacpacReferenceSettings;
dacpacRefSettings.dacpacFileLocation = vscode.Uri.file(path.relative(project.projectFolderPath, dacpacRefSettings.dacpacFileLocation.fsPath)); dacpacRefSettings.dacpacFileLocation = vscode.Uri.file(path.relative(project.projectFolderPath, dacpacRefSettings.dacpacFileLocation.fsPath));
await project.addDatabaseReference(dacpacRefSettings); await project.addDatabaseReference(dacpacRefSettings);
} else {
await project.addNugetPackageReference(<INugetPackageReferenceSettings>settings);
} }
this.refreshProjectsTree(context); this.refreshProjectsTree(context);

View File

@@ -12,16 +12,17 @@ import * as utils from '../common/utils';
import { Project } from '../models/project'; import { Project } from '../models/project';
import { cssStyles } from '../common/uiConstants'; import { cssStyles } from '../common/uiConstants';
import { IconPathHelper } from '../common/iconHelper'; import { IconPathHelper } from '../common/iconHelper';
import { ISystemDatabaseReferenceSettings, IDacpacReferenceSettings, IProjectReferenceSettings } from '../models/IDatabaseReferenceSettings'; import { ISystemDatabaseReferenceSettings, IDacpacReferenceSettings, IProjectReferenceSettings, INugetPackageReferenceSettings } from '../models/IDatabaseReferenceSettings';
import { Deferred } from '../common/promise'; import { Deferred } from '../common/promise';
import { TelemetryActions, TelemetryReporter, TelemetryViews } from '../common/telemetry'; import { TelemetryActions, TelemetryReporter, TelemetryViews } from '../common/telemetry';
import { SystemDatabase } from 'mssql'; import { ProjectType, SystemDatabase } from 'mssql';
import { DbServerValues, ensureSetOrDefined, populateResultWithVars } from './utils'; import { DbServerValues, ensureSetOrDefined, populateResultWithVars } from './utils';
export enum ReferenceType { export enum ReferenceType {
project, project,
systemDb, systemDb,
dacpac dacpac,
nupkg
} }
export class AddDatabaseReferenceDialog { export class AddDatabaseReferenceDialog {
@@ -35,6 +36,9 @@ export class AddDatabaseReferenceDialog {
private systemDatabaseFormComponent: azdataType.FormComponent | undefined; private systemDatabaseFormComponent: azdataType.FormComponent | undefined;
public dacpacTextbox: azdataType.InputBoxComponent | undefined; public dacpacTextbox: azdataType.InputBoxComponent | undefined;
private dacpacFormComponent: azdataType.FormComponent | undefined; private dacpacFormComponent: azdataType.FormComponent | undefined;
public nupkgNameTextbox: azdataType.InputBoxComponent | undefined;
public nupkgVersionTextbox: azdataType.InputBoxComponent | undefined;
private nupkgFormComponent: azdataType.FormComponentGroup | undefined;
public locationDropdown: azdataType.DropDownComponent | undefined; public locationDropdown: azdataType.DropDownComponent | undefined;
public databaseNameTextbox: azdataType.InputBoxComponent | undefined; public databaseNameTextbox: azdataType.InputBoxComponent | undefined;
public databaseVariableTextbox: azdataType.InputBoxComponent | undefined; public databaseVariableTextbox: azdataType.InputBoxComponent | undefined;
@@ -50,7 +54,7 @@ export class AddDatabaseReferenceDialog {
private toDispose: vscode.Disposable[] = []; private toDispose: vscode.Disposable[] = [];
private initDialogComplete: Deferred = new Deferred(); private initDialogComplete: Deferred = new Deferred();
public addReference: ((proj: Project, settings: ISystemDatabaseReferenceSettings | IDacpacReferenceSettings | IProjectReferenceSettings) => any) | undefined; public addReference: ((proj: Project, settings: ISystemDatabaseReferenceSettings | IDacpacReferenceSettings | IProjectReferenceSettings | INugetPackageReferenceSettings) => any) | undefined;
constructor(private project: Project) { constructor(private project: Project) {
this.dialog = utils.getAzdataApi()!.window.createModelViewDialog(constants.addDatabaseReferenceDialogName, 'addDatabaseReferencesDialog'); this.dialog = utils.getAzdataApi()!.window.createModelViewDialog(constants.addDatabaseReferenceDialogName, 'addDatabaseReferencesDialog');
@@ -106,6 +110,7 @@ export class AddDatabaseReferenceDialog {
const radioButtonGroup = this.createRadioButtons(); const radioButtonGroup = this.createRadioButtons();
this.systemDatabaseFormComponent = this.createSystemDatabaseDropdown(); this.systemDatabaseFormComponent = this.createSystemDatabaseDropdown();
this.dacpacFormComponent = this.createDacpacTextbox(); this.dacpacFormComponent = this.createDacpacTextbox();
this.nupkgFormComponent = this.createNupkgFormComponentGroup();
const locationDropdown = this.createLocationDropdown(); const locationDropdown = this.createLocationDropdown();
const variableSection = this.createVariableSection(); const variableSection = this.createVariableSection();
this.suppressMissingDependenciesErrorsCheckbox = view.modelBuilder.checkBox().withProps({ this.suppressMissingDependenciesErrorsCheckbox = view.modelBuilder.checkBox().withProps({
@@ -150,7 +155,7 @@ export class AddDatabaseReferenceDialog {
} }
public async addReferenceClick(): Promise<void> { public async addReferenceClick(): Promise<void> {
let referenceSettings: ISystemDatabaseReferenceSettings | IDacpacReferenceSettings | IProjectReferenceSettings; let referenceSettings: ISystemDatabaseReferenceSettings | IDacpacReferenceSettings | IProjectReferenceSettings | INugetPackageReferenceSettings;
if (this.currentReferenceType === ReferenceType.systemDb) { if (this.currentReferenceType === ReferenceType.systemDb) {
const systemDbRef: ISystemDatabaseReferenceSettings = { const systemDbRef: ISystemDatabaseReferenceSettings = {
@@ -170,7 +175,7 @@ export class AddDatabaseReferenceDialog {
}; };
referenceSettings = projRef; referenceSettings = projRef;
} else { // this.currentReferenceType === ReferenceType.dacpac } else if (this.currentReferenceType === ReferenceType.dacpac) {
const dacpacRef: IDacpacReferenceSettings = { const dacpacRef: IDacpacReferenceSettings = {
databaseName: ensureSetOrDefined(this.databaseNameTextbox?.value), databaseName: ensureSetOrDefined(this.databaseNameTextbox?.value),
dacpacFileLocation: vscode.Uri.file(<string>this.dacpacTextbox?.value), dacpacFileLocation: vscode.Uri.file(<string>this.dacpacTextbox?.value),
@@ -178,6 +183,14 @@ export class AddDatabaseReferenceDialog {
}; };
referenceSettings = dacpacRef; referenceSettings = dacpacRef;
} else { // this.currentReferenceType === ReferenceType.nupkg
const nupkgRef: INugetPackageReferenceSettings = {
packageName: <string>this.nupkgNameTextbox?.value,
packageVersion: <string>this.nupkgVersionTextbox?.value,
suppressMissingDependenciesErrors: <boolean>this.suppressMissingDependenciesErrorsCheckbox?.checked
}
referenceSettings = nupkgRef;
} }
const dbServerValues: DbServerValues = { const dbServerValues: DbServerValues = {
@@ -236,6 +249,18 @@ export class AddDatabaseReferenceDialog {
} }
}); });
const nupkgRadioButton = this.view!.modelBuilder.radioButton()
.withProps({
name: 'referenceType',
label: constants.nupkgText
}).component();
nupkgRadioButton.onDidChangeCheckedState((checked) => {
if (checked) {
this.nupkgRadioButtonClick();
}
});
if (this.projectDropdown?.values?.length) { if (this.projectDropdown?.values?.length) {
this.projectRadioButton.checked = true; this.projectRadioButton.checked = true;
this.currentReferenceType = ReferenceType.project; this.currentReferenceType = ReferenceType.project;
@@ -247,9 +272,16 @@ export class AddDatabaseReferenceDialog {
this.projectRadioButton.enabled = false; this.projectRadioButton.enabled = false;
} }
const radioButtons = [this.projectRadioButton, this.systemDatabaseRadioButton, dacpacRadioButton];
// only add the nupkg radio button for SDK-style projects
if (this.project.sqlProjStyle === ProjectType.SdkStyle) {
radioButtons.push(nupkgRadioButton);
}
let flexRadioButtonsModel: azdataType.FlexContainer = this.view!.modelBuilder.flexContainer() let flexRadioButtonsModel: azdataType.FlexContainer = this.view!.modelBuilder.flexContainer()
.withLayout({ flexFlow: 'column' }) .withLayout({ flexFlow: 'column' })
.withItems([this.projectRadioButton, this.systemDatabaseRadioButton, dacpacRadioButton]) .withItems(radioButtons)
.withProps({ ariaRole: 'radiogroup', ariaLabel: constants.referenceRadioButtonsGroupTitle }) .withProps({ ariaRole: 'radiogroup', ariaLabel: constants.referenceRadioButtonsGroupTitle })
.component(); .component();
@@ -262,6 +294,7 @@ export class AddDatabaseReferenceDialog {
public projectRadioButtonClick(): void { public projectRadioButtonClick(): void {
this.formBuilder!.removeFormItem(<azdataType.FormComponent>this.dacpacFormComponent); this.formBuilder!.removeFormItem(<azdataType.FormComponent>this.dacpacFormComponent);
this.formBuilder!.removeFormItem(<azdataType.FormComponent>this.systemDatabaseFormComponent); this.formBuilder!.removeFormItem(<azdataType.FormComponent>this.systemDatabaseFormComponent);
this.formBuilder!.removeFormItem(<azdataType.FormComponentGroup>this.nupkgFormComponent);
this.formBuilder!.insertFormItem(<azdataType.FormComponent>this.projectFormComponent, 2); this.formBuilder!.insertFormItem(<azdataType.FormComponent>this.projectFormComponent, 2);
this.locationDropdown!.values = constants.locationDropdownValues; this.locationDropdown!.values = constants.locationDropdownValues;
@@ -275,6 +308,7 @@ export class AddDatabaseReferenceDialog {
public systemDbRadioButtonClick(): void { public systemDbRadioButtonClick(): void {
this.formBuilder!.removeFormItem(<azdataType.FormComponent>this.dacpacFormComponent); this.formBuilder!.removeFormItem(<azdataType.FormComponent>this.dacpacFormComponent);
this.formBuilder!.removeFormItem(<azdataType.FormComponent>this.projectFormComponent); this.formBuilder!.removeFormItem(<azdataType.FormComponent>this.projectFormComponent);
this.formBuilder!.removeFormItem(<azdataType.FormComponentGroup>this.nupkgFormComponent);
this.formBuilder!.insertFormItem(<azdataType.FormComponent>this.systemDatabaseFormComponent, 2); this.formBuilder!.insertFormItem(<azdataType.FormComponent>this.systemDatabaseFormComponent, 2);
// update dropdown values because only different database, same server is a valid location for system db references // update dropdown values because only different database, same server is a valid location for system db references
@@ -290,6 +324,7 @@ export class AddDatabaseReferenceDialog {
public dacpacRadioButtonClick(): void { public dacpacRadioButtonClick(): void {
this.formBuilder!.removeFormItem(<azdataType.FormComponent>this.systemDatabaseFormComponent); this.formBuilder!.removeFormItem(<azdataType.FormComponent>this.systemDatabaseFormComponent);
this.formBuilder!.removeFormItem(<azdataType.FormComponent>this.projectFormComponent); this.formBuilder!.removeFormItem(<azdataType.FormComponent>this.projectFormComponent);
this.formBuilder!.removeFormItem(<azdataType.FormComponentGroup>this.nupkgFormComponent);
this.formBuilder!.insertFormItem(<azdataType.FormComponent>this.dacpacFormComponent, 2); this.formBuilder!.insertFormItem(<azdataType.FormComponent>this.dacpacFormComponent, 2);
this.locationDropdown!.values = constants.locationDropdownValues; this.locationDropdown!.values = constants.locationDropdownValues;
@@ -300,6 +335,20 @@ export class AddDatabaseReferenceDialog {
this.updateExampleUsage(); this.updateExampleUsage();
} }
public nupkgRadioButtonClick(): void {
this.formBuilder!.removeFormItem(<azdataType.FormComponent>this.systemDatabaseFormComponent);
this.formBuilder!.removeFormItem(<azdataType.FormComponent>this.projectFormComponent);
this.formBuilder!.removeFormItem(<azdataType.FormComponent>this.dacpacFormComponent);
this.formBuilder!.insertFormItem(<azdataType.FormComponentGroup>this.nupkgFormComponent, 2);
this.locationDropdown!.values = constants.locationDropdownValues;
this.currentReferenceType = ReferenceType.nupkg;
this.updateEnabledInputBoxes();
this.tryEnableAddReferenceButton();
this.updateExampleUsage();
}
private async createProjectDropdown(): Promise<azdataType.FormComponent> { private async createProjectDropdown(): Promise<azdataType.FormComponent> {
this.projectDropdown = this.view!.modelBuilder.dropDown().withProps({ this.projectDropdown = this.view!.modelBuilder.dropDown().withProps({
ariaLabel: constants.databaseProject ariaLabel: constants.databaseProject
@@ -361,6 +410,34 @@ export class AddDatabaseReferenceDialog {
}; };
} }
private createNupkgFormComponentGroup(): azdataType.FormComponentGroup {
this.nupkgNameTextbox = this.view!.modelBuilder.inputBox().withProps({
ariaLabel: constants.nupkgText,
placeHolder: constants.nupkgNamePlaceholder,
required: true
}).component();
this.nupkgVersionTextbox = this.view!.modelBuilder.inputBox().withProps({
ariaLabel: constants.version,
placeHolder: constants.versionPlaceholder,
required: true
}).component();
return {
components: [
{
title: constants.nupkgText,
component: this.nupkgNameTextbox
},
{
title: constants.version,
component: this.nupkgVersionTextbox
}
],
title: ''
}
}
private createLoadDacpacButton(): azdataType.ButtonComponent { private createLoadDacpacButton(): azdataType.ButtonComponent {
const loadDacpacButton = this.view!.modelBuilder.button().withProps({ const loadDacpacButton = this.view!.modelBuilder.button().withProps({
ariaLabel: constants.selectDacpac, ariaLabel: constants.selectDacpac,
@@ -466,6 +543,12 @@ export class AddDatabaseReferenceDialog {
this.databaseVariableTextbox!.value = dacpacName ? `${dacpacName}` : ''; this.databaseVariableTextbox!.value = dacpacName ? `${dacpacName}` : '';
break; break;
} }
case ReferenceType.nupkg: {
const nupkgName = this.nupkgNameTextbox!.value ? path.parse(this.nupkgNameTextbox!.value!).name : '';
this.databaseNameTextbox!.value = nupkgName;
this.databaseVariableTextbox!.value = nupkgName ? `${nupkgName}` : '';
break;
}
} }
} }
} }
@@ -603,6 +686,10 @@ export class AddDatabaseReferenceDialog {
this.dialog.okButton.enabled = this.dacpacRequiredFieldsFilled(); this.dialog.okButton.enabled = this.dacpacRequiredFieldsFilled();
break; break;
} }
case ReferenceType.nupkg: {
this.dialog.okButton.enabled = this.nupkgRequiredFieldsFilled();
break;
}
} }
} }
@@ -621,6 +708,14 @@ export class AddDatabaseReferenceDialog {
|| ((this.locationDropdown?.value === constants.differentDbDifferentServer && this.differentDatabaseDifferentServerRequiredFieldsFilled()))); || ((this.locationDropdown?.value === constants.differentDbDifferentServer && this.differentDatabaseDifferentServerRequiredFieldsFilled())));
} }
private nupkgRequiredFieldsFilled(): boolean {
return !!this.nupkgNameTextbox?.value
&& !!this.nupkgVersionTextbox?.value
&& ((this.locationDropdown?.value === constants.sameDatabase)
|| (this.locationDropdown?.value === constants.differentDbSameServer && this.differentDatabaseSameServerRequiredFieldsFilled())
|| ((this.locationDropdown?.value === constants.differentDbDifferentServer && this.differentDatabaseDifferentServerRequiredFieldsFilled())));
}
private differentDatabaseSameServerRequiredFieldsFilled(): boolean { private differentDatabaseSameServerRequiredFieldsFilled(): boolean {
return !!this.databaseNameTextbox?.value; return !!this.databaseNameTextbox?.value;
} }