mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 10:58:30 -05:00
Save publish profile in Publish UI workflow (#22700)
* Add profile section in Publish project UI * Move publish profile row below Publish Target * Add contract for savePublishProfie and SaveProfileAs button functionality * Make the DacFx contract functional * Send values from UI to DacFx service call * Fix build error * Address comment, remove print statements * Address comments * Set correct connection string * Fix functionality for rename, exclude, delete publish profiles. Add new profile to the tree and sqlproj. * Address comment to update alignement of button * Address comments * Update button to use title casing
This commit is contained in:
@@ -89,4 +89,8 @@ export class DacFxTestService implements mssql.IDacFxService {
|
|||||||
parseTSqlScript(filePath: string, databaseSchemaProvider: string): Thenable<mssql.ParseTSqlScriptResult> {
|
parseTSqlScript(filePath: string, databaseSchemaProvider: string): Thenable<mssql.ParseTSqlScriptResult> {
|
||||||
return Promise.resolve({ containsCreateTableStatement: true });
|
return Promise.resolve({ containsCreateTableStatement: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
savePublishProfile(profilePath: string, databaseName: string, connectionString: string, sqlCommandVariableValues?: Record<string, string>): Thenable<azdata.ResultStatus> {
|
||||||
|
return Promise.resolve(this.dacfxResult);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -551,6 +551,14 @@ export interface ParseTSqlScriptParams {
|
|||||||
databaseSchemaProvider: string;
|
databaseSchemaProvider: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface SavePublishProfileParams {
|
||||||
|
profilePath: string;
|
||||||
|
databaseName: string;
|
||||||
|
connectionString: string;
|
||||||
|
sqlCommandVariableValues?: Record<string, string>;
|
||||||
|
deploymentOptions?: mssql.DeploymentOptions;
|
||||||
|
}
|
||||||
|
|
||||||
export namespace ExportRequest {
|
export namespace ExportRequest {
|
||||||
export const type = new RequestType<ExportParams, mssql.DacFxResult, void, void>('dacfx/export');
|
export const type = new RequestType<ExportParams, mssql.DacFxResult, void, void>('dacfx/export');
|
||||||
}
|
}
|
||||||
@@ -587,6 +595,10 @@ export namespace ParseTSqlScriptRequest {
|
|||||||
export const type = new RequestType<ParseTSqlScriptParams, mssql.ParseTSqlScriptResult, void, void>('dacfx/parseTSqlScript');
|
export const type = new RequestType<ParseTSqlScriptParams, mssql.ParseTSqlScriptResult, void, void>('dacfx/parseTSqlScript');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export namespace SavePublishProfileRequest {
|
||||||
|
export const type = new RequestType<SavePublishProfileParams, azdata.ResultStatus, void, void>('dacfx/savePublishProfile');
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------------------- </ DacFx > ------------------------------------
|
// ------------------------------- </ DacFx > ------------------------------------
|
||||||
|
|
||||||
// ------------------------------- < Sql Projects > ------------------------------------
|
// ------------------------------- < Sql Projects > ------------------------------------
|
||||||
|
|||||||
@@ -84,4 +84,9 @@ export class DacFxService extends BaseService implements mssql.IDacFxService {
|
|||||||
const params: contracts.ParseTSqlScriptParams = { filePath, databaseSchemaProvider };
|
const params: contracts.ParseTSqlScriptParams = { filePath, databaseSchemaProvider };
|
||||||
return this.runWithErrorHandling(contracts.ParseTSqlScriptRequest.type, params);
|
return this.runWithErrorHandling(contracts.ParseTSqlScriptRequest.type, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async savePublishProfile(profilePath: string, databaseName: string, connectionString: string, sqlCommandVariableValues?: Record<string, string>, deploymentOptions?: mssql.DeploymentOptions): Promise<azdata.ResultStatus> {
|
||||||
|
const params: contracts.SavePublishProfileParams = { profilePath, databaseName, connectionString, sqlCommandVariableValues, deploymentOptions };
|
||||||
|
return this.runWithErrorHandling(contracts.SavePublishProfileRequest.type, params);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
1
extensions/mssql/src/mssql.d.ts
vendored
1
extensions/mssql/src/mssql.d.ts
vendored
@@ -242,6 +242,7 @@ declare module 'mssql' {
|
|||||||
getOptionsFromProfile(profilePath: string): Thenable<DacFxOptionsResult>;
|
getOptionsFromProfile(profilePath: string): Thenable<DacFxOptionsResult>;
|
||||||
validateStreamingJob(packageFilePath: string, createStreamingJobTsql: string): Thenable<ValidateStreamingJobResult>;
|
validateStreamingJob(packageFilePath: string, createStreamingJobTsql: string): Thenable<ValidateStreamingJobResult>;
|
||||||
parseTSqlScript(filePath: string, databaseSchemaProvider: string): Thenable<ParseTSqlScriptResult>;
|
parseTSqlScript(filePath: string, databaseSchemaProvider: string): Thenable<ParseTSqlScriptResult>;
|
||||||
|
savePublishProfile(profilePath: string, databaseName: string, connectionString: string, sqlCommandVariableValues?: Record<string, string>, deploymentOptions?: DeploymentOptions): Thenable<azdata.ResultStatus>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DacFxResult extends azdata.ResultStatus {
|
export interface DacFxResult extends azdata.ResultStatus {
|
||||||
|
|||||||
@@ -149,6 +149,8 @@ export const server = localize('server', "Server");
|
|||||||
export const defaultUser = localize('default', "default");
|
export const defaultUser = localize('default', "default");
|
||||||
export const selectProfileToUse = localize('selectProfileToUse', "Select publish profile to load");
|
export const selectProfileToUse = localize('selectProfileToUse', "Select publish profile to load");
|
||||||
export const selectProfile = localize('selectProfile', "Select Profile");
|
export const selectProfile = localize('selectProfile', "Select Profile");
|
||||||
|
export const saveProfileAsButtonText = localize('saveProfileAsButtonText', "Save Profile as...");
|
||||||
|
export const save = localize('save', "Save");
|
||||||
export const dontUseProfile = localize('dontUseProfile', "Don't use profile");
|
export const dontUseProfile = localize('dontUseProfile', "Don't use profile");
|
||||||
export const browseForProfileWithIcon = `$(folder) ${localize('browseForProfile', "Browse for profile")}`;
|
export const browseForProfileWithIcon = `$(folder) ${localize('browseForProfile', "Browse for profile")}`;
|
||||||
export const chooseAction = localize('chooseAction', "Choose action");
|
export const chooseAction = localize('chooseAction', "Choose action");
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ import { ImportDataModel } from '../models/api/import';
|
|||||||
import { NetCoreTool, DotNetError } from '../tools/netcoreTool';
|
import { NetCoreTool, DotNetError } from '../tools/netcoreTool';
|
||||||
import { ShellCommandOptions } from '../tools/shellExecutionHelper';
|
import { ShellCommandOptions } from '../tools/shellExecutionHelper';
|
||||||
import { BuildHelper } from '../tools/buildHelper';
|
import { BuildHelper } from '../tools/buildHelper';
|
||||||
import { readPublishProfile } 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 } from '../models/IDatabaseReferenceSettings';
|
||||||
import { DatabaseReferenceTreeItem } from '../models/tree/databaseReferencesTreeItem';
|
import { DatabaseReferenceTreeItem } from '../models/tree/databaseReferencesTreeItem';
|
||||||
@@ -445,6 +445,7 @@ export class ProjectsController {
|
|||||||
publishDatabaseDialog.publishToContainer = async (proj, prof) => this.publishToDockerContainer(proj, prof);
|
publishDatabaseDialog.publishToContainer = async (proj, prof) => this.publishToDockerContainer(proj, prof);
|
||||||
publishDatabaseDialog.generateScript = async (proj, prof) => this.publishOrScriptProject(proj, prof, false);
|
publishDatabaseDialog.generateScript = async (proj, prof) => this.publishOrScriptProject(proj, prof, false);
|
||||||
publishDatabaseDialog.readPublishProfile = async (profileUri) => readPublishProfile(profileUri);
|
publishDatabaseDialog.readPublishProfile = async (profileUri) => readPublishProfile(profileUri);
|
||||||
|
publishDatabaseDialog.savePublishProfile = async (profilePath, databaseName, connectionString, sqlCommandVariableValues, deploymentOptions) => savePublishProfile(profilePath, databaseName, connectionString, sqlCommandVariableValues, deploymentOptions);
|
||||||
|
|
||||||
publishDatabaseDialog.openDialog();
|
publishDatabaseDialog.openDialog();
|
||||||
|
|
||||||
@@ -820,6 +821,7 @@ export class ProjectsController {
|
|||||||
await project.excludePostDeploymentScript(fileEntry.relativePath);
|
await project.excludePostDeploymentScript(fileEntry.relativePath);
|
||||||
break;
|
break;
|
||||||
case constants.DatabaseProjectItemType.noneFile:
|
case constants.DatabaseProjectItemType.noneFile:
|
||||||
|
case constants.DatabaseProjectItemType.publishProfile:
|
||||||
await project.excludeNoneItem(fileEntry.relativePath);
|
await project.excludeNoneItem(fileEntry.relativePath);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -879,6 +881,7 @@ export class ProjectsController {
|
|||||||
await project.deletePostDeploymentScript(node.entryKey);
|
await project.deletePostDeploymentScript(node.entryKey);
|
||||||
break;
|
break;
|
||||||
case constants.DatabaseProjectItemType.noneFile:
|
case constants.DatabaseProjectItemType.noneFile:
|
||||||
|
case constants.DatabaseProjectItemType.publishProfile:
|
||||||
await project.deleteNoneItem(node.entryKey);
|
await project.deleteNoneItem(node.entryKey);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -903,13 +906,21 @@ export class ProjectsController {
|
|||||||
const node = context.element as BaseProjectTreeItem;
|
const node = context.element as BaseProjectTreeItem;
|
||||||
const project = await this.getProjectFromContext(node);
|
const project = await this.getProjectFromContext(node);
|
||||||
const file = this.getFileProjectEntry(project, node);
|
const file = this.getFileProjectEntry(project, node);
|
||||||
|
const baseName = path.basename(node.friendlyName);
|
||||||
|
let fileExtension: string;
|
||||||
|
|
||||||
|
if (utils.isPublishProfile(baseName)) {
|
||||||
|
fileExtension = constants.publishProfileExtension;
|
||||||
|
} else {
|
||||||
|
fileExtension = constants.sqlFileExtension;
|
||||||
|
}
|
||||||
|
|
||||||
// need to use quickpick because input box isn't supported in treeviews
|
// need to use quickpick because input box isn't supported in treeviews
|
||||||
// https://github.com/microsoft/vscode/issues/117502 and https://github.com/microsoft/vscode/issues/97190
|
// https://github.com/microsoft/vscode/issues/117502 and https://github.com/microsoft/vscode/issues/97190
|
||||||
const newFileName = await vscode.window.showInputBox(
|
const newFileName = await vscode.window.showInputBox(
|
||||||
{
|
{
|
||||||
title: constants.enterNewName,
|
title: constants.enterNewName,
|
||||||
value: path.basename(node.friendlyName, constants.sqlFileExtension),
|
value: path.basename(baseName, fileExtension),
|
||||||
ignoreFocusOut: true,
|
ignoreFocusOut: true,
|
||||||
validateInput: async (value) => {
|
validateInput: async (value) => {
|
||||||
return await this.fileAlreadyExists(value, file?.fsUri.fsPath!) ? constants.fileAlreadyExists(value) : undefined;
|
return await this.fileAlreadyExists(value, file?.fsUri.fsPath!) ? constants.fileAlreadyExists(value) : undefined;
|
||||||
@@ -920,7 +931,7 @@ export class ProjectsController {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const newFilePath = path.join(path.dirname(utils.getPlatformSafeFileEntryPath(file?.relativePath!)), `${newFileName}.sql`);
|
const newFilePath = path.join(path.dirname(utils.getPlatformSafeFileEntryPath(file?.relativePath!)), `${newFileName}${fileExtension}`);
|
||||||
|
|
||||||
const renameResult = await project.move(node, newFilePath);
|
const renameResult = await project.move(node, newFilePath);
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import * as vscode from 'vscode';
|
|||||||
import * as constants from '../common/constants';
|
import * as constants from '../common/constants';
|
||||||
import * as utils from '../common/utils';
|
import * as utils from '../common/utils';
|
||||||
import * as uiUtils from './utils';
|
import * as uiUtils from './utils';
|
||||||
|
import * as path from 'path';
|
||||||
|
|
||||||
import { Project } from '../models/project';
|
import { Project } from '../models/project';
|
||||||
import { SqlConnectionDataSource } from '../models/dataSources/sqlConnectionStringSource';
|
import { SqlConnectionDataSource } from '../models/dataSources/sqlConnectionStringSource';
|
||||||
@@ -62,6 +63,7 @@ export class PublishDatabaseDialog {
|
|||||||
protected optionsButton: azdataType.ButtonComponent | undefined;
|
protected optionsButton: azdataType.ButtonComponent | undefined;
|
||||||
private publishOptionsDialog: PublishOptionsDialog | undefined;
|
private publishOptionsDialog: PublishOptionsDialog | undefined;
|
||||||
public publishOptionsModified: boolean = false;
|
public publishOptionsModified: boolean = false;
|
||||||
|
private publishProfileUri: vscode.Uri | undefined;
|
||||||
|
|
||||||
private completionPromise: Deferred = new Deferred();
|
private completionPromise: Deferred = new Deferred();
|
||||||
|
|
||||||
@@ -71,6 +73,7 @@ export class PublishDatabaseDialog {
|
|||||||
public publishToContainer: ((proj: Project, profile: IPublishToDockerSettings) => any) | undefined;
|
public publishToContainer: ((proj: Project, profile: IPublishToDockerSettings) => any) | undefined;
|
||||||
public generateScript: ((proj: Project, profile: ISqlProjectPublishSettings) => any) | undefined;
|
public generateScript: ((proj: Project, profile: ISqlProjectPublishSettings) => any) | undefined;
|
||||||
public readPublishProfile: ((profileUri: vscode.Uri) => any) | undefined;
|
public readPublishProfile: ((profileUri: vscode.Uri) => any) | undefined;
|
||||||
|
public savePublishProfile: ((profilePath: string, databaseName: string, connectionString: string, sqlCommandVariableValues?: Record<string, string>, deploymentOptions?: DeploymentOptions) => any) | undefined;
|
||||||
|
|
||||||
constructor(private project: Project) {
|
constructor(private project: Project) {
|
||||||
this.dialog = utils.getAzdataApi()!.window.createModelViewDialog(constants.publishDialogName, 'sqlProjectPublishDialog');
|
this.dialog = utils.getAzdataApi()!.window.createModelViewDialog(constants.publishDialogName, 'sqlProjectPublishDialog');
|
||||||
@@ -144,13 +147,14 @@ export class PublishDatabaseDialog {
|
|||||||
const options = await this.getDefaultDeploymentOptions();
|
const options = await this.getDefaultDeploymentOptions();
|
||||||
this.setDeploymentOptions(options);
|
this.setDeploymentOptions(options);
|
||||||
|
|
||||||
const profileRow = this.createProfileRow(view);
|
const profileRow = this.createProfileSection(view);
|
||||||
|
|
||||||
this.connectionRow = this.createConnectionRow(view);
|
this.connectionRow = this.createConnectionRow(view);
|
||||||
this.databaseRow = this.createDatabaseRow(view);
|
this.databaseRow = this.createDatabaseRow(view);
|
||||||
const displayOptionsButton = this.createOptionsButton(view);
|
const displayOptionsButton = this.createOptionsButton(view);
|
||||||
|
|
||||||
const horizontalFormSection = view.modelBuilder.flexContainer().withLayout({ flexFlow: 'column' }).component();
|
const horizontalFormSection = view.modelBuilder.flexContainer().withLayout({ flexFlow: 'column' }).component();
|
||||||
horizontalFormSection.addItems([profileRow, this.databaseRow]);
|
horizontalFormSection.addItems([this.databaseRow]);
|
||||||
|
|
||||||
this.formBuilder = <azdataType.FormBuilder>view.modelBuilder.formContainer()
|
this.formBuilder = <azdataType.FormBuilder>view.modelBuilder.formContainer()
|
||||||
.withFormItems([
|
.withFormItems([
|
||||||
@@ -161,6 +165,10 @@ export class PublishDatabaseDialog {
|
|||||||
component: flexRadioButtonsModel,
|
component: flexRadioButtonsModel,
|
||||||
title: ''
|
title: ''
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
component: profileRow,
|
||||||
|
title: constants.profile
|
||||||
|
},
|
||||||
{
|
{
|
||||||
component: this.connectionRow,
|
component: this.connectionRow,
|
||||||
title: ''
|
title: ''
|
||||||
@@ -432,18 +440,20 @@ export class PublishDatabaseDialog {
|
|||||||
this.createDatabaseRow(view);
|
this.createDatabaseRow(view);
|
||||||
this.tryEnableGenerateScriptAndPublishButtons();
|
this.tryEnableGenerateScriptAndPublishButtons();
|
||||||
if (existingServer) {
|
if (existingServer) {
|
||||||
if (this.connectionRow) {
|
|
||||||
this.formBuilder!.insertFormItem({
|
|
||||||
title: '',
|
|
||||||
component: this.connectionRow
|
|
||||||
}, 2);
|
|
||||||
}
|
|
||||||
if (this.localDbSection) {
|
if (this.localDbSection) {
|
||||||
this.formBuilder!.removeFormItem({
|
this.formBuilder!.removeFormItem({
|
||||||
title: '',
|
title: '',
|
||||||
component: this.localDbSection
|
component: this.localDbSection
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.connectionRow) {
|
||||||
|
this.formBuilder!.insertFormItem({
|
||||||
|
title: '',
|
||||||
|
component: this.connectionRow
|
||||||
|
}, 3);
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (this.connectionRow) {
|
if (this.connectionRow) {
|
||||||
this.formBuilder!.removeFormItem({
|
this.formBuilder!.removeFormItem({
|
||||||
@@ -451,6 +461,7 @@ export class PublishDatabaseDialog {
|
|||||||
component: this.connectionRow
|
component: this.connectionRow
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.localDbSection) {
|
if (this.localDbSection) {
|
||||||
this.formBuilder!.insertFormItem({
|
this.formBuilder!.insertFormItem({
|
||||||
title: '',
|
title: '',
|
||||||
@@ -524,22 +535,19 @@ export class PublishDatabaseDialog {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private createProfileRow(view: azdataType.ModelView): azdataType.FlexContainer {
|
private createProfileSection(view: azdataType.ModelView): azdataType.FlexContainer {
|
||||||
const loadProfileButton = this.createLoadProfileButton(view);
|
const selectProfileButton = this.createSelectProfileButton(view);
|
||||||
|
const saveProfileAsButton = this.createSaveProfileAsButton(view);
|
||||||
|
|
||||||
this.loadProfileTextBox = view.modelBuilder.inputBox().withProps({
|
this.loadProfileTextBox = view.modelBuilder.inputBox().withProps({
|
||||||
placeHolder: constants.loadProfilePlaceholderText,
|
placeHolder: constants.loadProfilePlaceholderText,
|
||||||
ariaLabel: constants.profile,
|
ariaLabel: constants.profile,
|
||||||
width: cssStyles.publishDialogTextboxWidth,
|
width: '200px',
|
||||||
enabled: false
|
enabled: false
|
||||||
}).component();
|
}).component();
|
||||||
|
|
||||||
const profileLabel = view.modelBuilder.text().withProps({
|
const buttonsList = view.modelBuilder.flexContainer().withItems([selectProfileButton, saveProfileAsButton], { flex: '0 0 auto', CSSStyles: { 'margin-right': '5px', 'text-align': 'justify' } }).withLayout({ flexFlow: 'row', alignItems: 'center' }).component();
|
||||||
value: constants.profile,
|
const profileRow = view.modelBuilder.flexContainer().withItems([this.loadProfileTextBox, buttonsList], { flex: '0 0 auto', CSSStyles: { 'margin-right': '15px', 'text-align': 'justify' } }).withLayout({ flexFlow: 'row', alignItems: 'center' }).component();
|
||||||
width: cssStyles.publishDialogLabelWidth
|
|
||||||
}).component();
|
|
||||||
|
|
||||||
const profileRow = view.modelBuilder.flexContainer().withItems([profileLabel, this.loadProfileTextBox], { flex: '0 0 auto', CSSStyles: { 'margin-right': '10px' } }).withLayout({ flexFlow: 'row', alignItems: 'center' }).component();
|
|
||||||
profileRow.insertItem(loadProfileButton, 2, { CSSStyles: { 'margin-right': '0px' } });
|
|
||||||
|
|
||||||
return profileRow;
|
return profileRow;
|
||||||
}
|
}
|
||||||
@@ -862,13 +870,14 @@ export class PublishDatabaseDialog {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private createLoadProfileButton(view: azdataType.ModelView): azdataType.ButtonComponent {
|
private createSelectProfileButton(view: azdataType.ModelView): azdataType.ButtonComponent {
|
||||||
let loadProfileButton: azdataType.ButtonComponent = view.modelBuilder.button().withProps({
|
let loadProfileButton: azdataType.ButtonComponent = view.modelBuilder.button().withProps({
|
||||||
ariaLabel: constants.loadProfilePlaceholderText,
|
label: constants.selectProfile,
|
||||||
title: constants.loadProfilePlaceholderText,
|
title: constants.selectProfile,
|
||||||
iconPath: IconPathHelper.folder_blue,
|
ariaLabel: constants.selectProfile,
|
||||||
height: '18px',
|
width: '90px',
|
||||||
width: '18px'
|
height: '25px',
|
||||||
|
secondary: true,
|
||||||
}).component();
|
}).component();
|
||||||
|
|
||||||
loadProfileButton.onDidClick(async () => {
|
loadProfileButton.onDidClick(async () => {
|
||||||
@@ -917,12 +926,55 @@ export class PublishDatabaseDialog {
|
|||||||
await this.loadProfileTextBox!.updateProperty('title', fileUris[0].fsPath);
|
await this.loadProfileTextBox!.updateProperty('title', fileUris[0].fsPath);
|
||||||
|
|
||||||
this.profileUsed = true;
|
this.profileUsed = true;
|
||||||
|
this.publishProfileUri = fileUris[0];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return loadProfileButton;
|
return loadProfileButton;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private createSaveProfileAsButton(view: azdataType.ModelView): azdataType.ButtonComponent {
|
||||||
|
let saveProfileAsButton: azdataType.ButtonComponent = view.modelBuilder.button().withProps({
|
||||||
|
label: constants.saveProfileAsButtonText,
|
||||||
|
title: constants.saveProfileAsButtonText,
|
||||||
|
ariaLabel: constants.saveProfileAsButtonText,
|
||||||
|
width: cssStyles.PublishingOptionsButtonWidth,
|
||||||
|
height: '25px',
|
||||||
|
secondary: true
|
||||||
|
}).component();
|
||||||
|
|
||||||
|
saveProfileAsButton.onDidClick(async () => {
|
||||||
|
const filePath = await vscode.window.showSaveDialog(
|
||||||
|
{
|
||||||
|
defaultUri: this.publishProfileUri ?? vscode.Uri.file(path.join(this.project.projectFolderPath, `${this.project.projectFileName}_1`)),
|
||||||
|
saveLabel: constants.save,
|
||||||
|
filters: {
|
||||||
|
'Publish Settings Files': ['publish.xml'],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!filePath) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.savePublishProfile) {
|
||||||
|
const targetConnectionString = this.connectionId ? await utils.getAzdataApi()!.connection.getConnectionString(this.connectionId, false) : '';
|
||||||
|
const targetDatabaseName = this.targetDatabaseName ?? '';
|
||||||
|
const deploymentOptions = await this.getDeploymentOptions();
|
||||||
|
await this.savePublishProfile(filePath.fsPath, targetDatabaseName, targetConnectionString, this.getSqlCmdVariablesForPublish(), deploymentOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.profileUsed = true;
|
||||||
|
this.publishProfileUri = filePath;
|
||||||
|
|
||||||
|
await this.project.addNoneItem(path.relative(this.project.projectFolderPath, filePath.fsPath));
|
||||||
|
void vscode.commands.executeCommand(constants.refreshDataWorkspaceCommand); //refresh data workspace to load the newly added profile to the tree
|
||||||
|
});
|
||||||
|
|
||||||
|
return saveProfileAsButton;
|
||||||
|
}
|
||||||
|
|
||||||
private convertSqlCmdVarsToTableFormat(sqlCmdVars: Record<string, string>): azdataType.DeclarativeTableCellValue[][] {
|
private convertSqlCmdVarsToTableFormat(sqlCmdVars: Record<string, string>): azdataType.DeclarativeTableCellValue[][] {
|
||||||
let data = [];
|
let data = [];
|
||||||
for (let key in sqlCmdVars) {
|
for (let key in sqlCmdVars) {
|
||||||
|
|||||||
@@ -441,6 +441,7 @@ export class Project implements ISqlProject {
|
|||||||
this._noneDeployScripts = [];
|
this._noneDeployScripts = [];
|
||||||
this._outputPath = '';
|
this._outputPath = '';
|
||||||
this._configuration = Configuration.Debug;
|
this._configuration = Configuration.Debug;
|
||||||
|
this._publishProfiles = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
public async updateProjectForCrossPlatform(): Promise<void> {
|
public async updateProjectForCrossPlatform(): Promise<void> {
|
||||||
|
|||||||
@@ -125,3 +125,11 @@ async function readConnectionString(xmlDoc: any): Promise<{ connectionId: string
|
|||||||
server: server
|
server: server
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* saves publish settings to the specified profile file
|
||||||
|
*/
|
||||||
|
export async function savePublishProfile(profilePath: string, databaseName: string, connectionString: string, sqlCommandVariableValues?: Record<string, string>, deploymentOptions?: mssql.DeploymentOptions): Promise<void> {
|
||||||
|
const dacFxService = await utils.getDacFxService();
|
||||||
|
await dacFxService.savePublishProfile(profilePath, databaseName, connectionString, sqlCommandVariableValues, deploymentOptions);
|
||||||
|
}
|
||||||
|
|||||||
@@ -22,6 +22,11 @@ export const mockDacFxResult = {
|
|||||||
report: ''
|
report: ''
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const mockSavePublishResult = {
|
||||||
|
success: true,
|
||||||
|
errorMessage: ''
|
||||||
|
};
|
||||||
|
|
||||||
/* Get the deployment options sample model */
|
/* Get the deployment options sample model */
|
||||||
export function getDeploymentOptions(): mssql.DeploymentOptions {
|
export function getDeploymentOptions(): mssql.DeploymentOptions {
|
||||||
const sampleDesc = 'Sample Description text';
|
const sampleDesc = 'Sample Description text';
|
||||||
@@ -47,16 +52,17 @@ export const mockDacFxOptionsResult: mssql.DacFxOptionsResult = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export class MockDacFxService implements mssql.IDacFxService {
|
export class MockDacFxService implements mssql.IDacFxService {
|
||||||
public exportBacpac(_: string, __: string, ___: string, ____: azdata.TaskExecutionMode): Thenable<mssql.DacFxResult> { return Promise.resolve(mockDacFxResult); }
|
public exportBacpac(_databaseName: string, _packageFilePath: string, _ownerUri: string, _taskExecutionMode: azdata.TaskExecutionMode): Thenable<mssql.DacFxResult> { return Promise.resolve(mockDacFxResult); }
|
||||||
public importBacpac(_: string, __: string, ___: string, ____: azdata.TaskExecutionMode): Thenable<mssql.DacFxResult> { return Promise.resolve(mockDacFxResult); }
|
public importBacpac(_packageFilePath: string, _databaseName: string, _ownerUri: string, _taskExecutionMode: azdata.TaskExecutionMode): Thenable<mssql.DacFxResult> { return Promise.resolve(mockDacFxResult); }
|
||||||
public extractDacpac(_: string, __: string, ___: string, ____: string, _____: string, ______: azdata.TaskExecutionMode): Thenable<mssql.DacFxResult> { return Promise.resolve(mockDacFxResult); }
|
public extractDacpac(_databaseName: string, _packageFilePath: string, _applicationName: string, _applicationVersion: string, _ownerUri: string, _taskExecutionMode: azdata.TaskExecutionMode): Thenable<mssql.DacFxResult> { return Promise.resolve(mockDacFxResult); }
|
||||||
public createProjectFromDatabase(_: string, __: string, ___: string, ____: string, _____: string, ______: mssql.ExtractTarget, _______: azdata.TaskExecutionMode): Thenable<mssql.DacFxResult> { return Promise.resolve(mockDacFxResult); }
|
public createProjectFromDatabase(_databaseName: string, _targetFilePath: string, _applicationName: string, _applicationVersion: string, _ownerUri: string, _extractTarget: mssql.ExtractTarget, _taskExecutionMode: azdata.TaskExecutionMode, _includePermissions?: boolean): Thenable<mssql.DacFxResult> { return Promise.resolve(mockDacFxResult); }
|
||||||
public deployDacpac(_: string, __: string, ___: boolean, ____: string, _____: azdata.TaskExecutionMode, ______?: Record<string, string>): Thenable<mssql.DacFxResult> { return Promise.resolve(mockDacFxResult); }
|
public deployDacpac(_packageFilePath: string, _targetDatabaseName: string, _upgradeExisting: boolean, _ownerUri: string, _taskExecutionMode: azdata.TaskExecutionMode, _sqlCommandVariableValues?: Record<string, string>, _deploymentOptions?: mssql.DeploymentOptions): Thenable<mssql.DacFxResult> { return Promise.resolve(mockDacFxResult); }
|
||||||
public generateDeployScript(_: string, __: string, ___: string, ____: azdata.TaskExecutionMode, ______?: Record<string, string>): Thenable<mssql.DacFxResult> { return Promise.resolve(mockDacFxResult); }
|
public generateDeployScript(_packageFilePath: string, _targetDatabaseName: string, _ownerUri: string, _taskExecutionMode: azdata.TaskExecutionMode, _sqlCommandVariableValues?: Record<string, string>, _deploymentOptions?: mssql.DeploymentOptions): Thenable<mssql.DacFxResult> { return Promise.resolve(mockDacFxResult); }
|
||||||
public generateDeployPlan(_: string, __: string, ___: string, ____: azdata.TaskExecutionMode): Thenable<mssql.GenerateDeployPlanResult> { return Promise.resolve(mockDacFxResult); }
|
public generateDeployPlan(_packageFilePath: string, _targetDatabaseName: string, _ownerUri: string, _taskExecutionMode: azdata.TaskExecutionMode): Thenable<mssql.GenerateDeployPlanResult> { return Promise.resolve(mockDacFxResult); }
|
||||||
public getOptionsFromProfile(_: string): Thenable<mssql.DacFxOptionsResult> { return Promise.resolve(mockDacFxOptionsResult); }
|
public getOptionsFromProfile(_profilePath: string): Thenable<mssql.DacFxOptionsResult> { return Promise.resolve(mockDacFxOptionsResult); }
|
||||||
public validateStreamingJob(_: string, __: string): Thenable<mssql.ValidateStreamingJobResult> { return Promise.resolve(mockDacFxResult); }
|
public validateStreamingJob(_packageFilePath: string, _createStreamingJobTsql: string): Thenable<mssql.ValidateStreamingJobResult> { return Promise.resolve(mockDacFxResult); }
|
||||||
public parseTSqlScript(_: string, __: string): Thenable<mssql.ParseTSqlScriptResult> { return Promise.resolve({ containsCreateTableStatement: true }); }
|
public parseTSqlScript(_filePath: string, _databaseSchemaProvider: string): Thenable<mssql.ParseTSqlScriptResult> { return Promise.resolve({ containsCreateTableStatement: true }); }
|
||||||
|
public savePublishProfile(_profilePath: string, _databaseName: string, _connectionString: string, _sqlCommandVariableValues?: Record<string, string>, _deploymentOptions?: mssql.DeploymentOptions): Thenable<azdata.ResultStatus> { return Promise.resolve(mockSavePublishResult); }
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createContext(): TestContext {
|
export function createContext(): TestContext {
|
||||||
|
|||||||
9
extensions/types/vscode-mssql.d.ts
vendored
9
extensions/types/vscode-mssql.d.ts
vendored
@@ -431,6 +431,7 @@ declare module 'vscode-mssql' {
|
|||||||
generateDeployPlan(packageFilePath: string, databaseName: string, ownerUri: string, taskExecutionMode: TaskExecutionMode): Thenable<GenerateDeployPlanResult>;
|
generateDeployPlan(packageFilePath: string, databaseName: string, ownerUri: string, taskExecutionMode: TaskExecutionMode): Thenable<GenerateDeployPlanResult>;
|
||||||
getOptionsFromProfile(profilePath: string): Thenable<DacFxOptionsResult>;
|
getOptionsFromProfile(profilePath: string): Thenable<DacFxOptionsResult>;
|
||||||
validateStreamingJob(packageFilePath: string, createStreamingJobTsql: string): Thenable<ValidateStreamingJobResult>;
|
validateStreamingJob(packageFilePath: string, createStreamingJobTsql: string): Thenable<ValidateStreamingJobResult>;
|
||||||
|
savePublishProfile(profilePath: string, databaseName: string, connectionString: string, sqlCommandVariableValues?: Record<string, string>, deploymentOptions?: DeploymentOptions): Thenable<ResultStatus>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1106,6 +1107,14 @@ declare module 'vscode-mssql' {
|
|||||||
defaultDeploymentOptions: DeploymentOptions;
|
defaultDeploymentOptions: DeploymentOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface SavePublishProfileParams {
|
||||||
|
profilePath: string;
|
||||||
|
databaseName: string;
|
||||||
|
connectionString: string;
|
||||||
|
sqlCommandVariableValues?: Record<string, string>;
|
||||||
|
deploymentOptions?: DeploymentOptions;
|
||||||
|
}
|
||||||
|
|
||||||
//#region ISqlProjectsService
|
//#region ISqlProjectsService
|
||||||
|
|
||||||
//#region Parameters
|
//#region Parameters
|
||||||
|
|||||||
Reference in New Issue
Block a user