mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-07 17:23:56 -05:00
Move DacFx wizard into separate extension (#4115)
* Moved dacfx wizard into separate extension * updating to use azdata * one more azdata change * bump import extension version * renaming extension to dacpac
This commit is contained in:
139
extensions/dacpac/src/wizard/api/basePage.ts
Normal file
139
extensions/dacpac/src/wizard/api/basePage.ts
Normal file
@@ -0,0 +1,139 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import * as azdata from 'azdata';
|
||||
import { DacFxDataModel } from './models';
|
||||
|
||||
export abstract class BasePage {
|
||||
|
||||
protected readonly wizardPage: azdata.window.modelviewdialog.WizardPage;
|
||||
protected readonly model: DacFxDataModel;
|
||||
protected readonly view: azdata.ModelView;
|
||||
|
||||
/**
|
||||
* This method constructs all the elements of the page.
|
||||
* @returns {Promise<boolean>}
|
||||
*/
|
||||
public async abstract start(): Promise<boolean>;
|
||||
|
||||
/**
|
||||
* This method is called when the user is entering the page.
|
||||
* @returns {Promise<boolean>}
|
||||
*/
|
||||
public async abstract onPageEnter(): Promise<boolean>;
|
||||
|
||||
/**
|
||||
* This method is called when the user is leaving the page.
|
||||
* @returns {Promise<boolean>}
|
||||
*/
|
||||
async onPageLeave(): Promise<boolean> {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override this method to cleanup what you don't need cached in the page.
|
||||
* @returns {Promise<boolean>}
|
||||
*/
|
||||
public async cleanup(): Promise<boolean> {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up a navigation validator.
|
||||
* This will be called right before onPageEnter().
|
||||
*/
|
||||
public abstract setupNavigationValidator();
|
||||
|
||||
protected async getServerValues(): Promise<{ connection, displayName, name }[]> {
|
||||
let cons = await azdata.connection.getActiveConnections();
|
||||
// This user has no active connections ABORT MISSION
|
||||
if (!cons || cons.length === 0) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
let count = -1;
|
||||
let idx = -1;
|
||||
|
||||
|
||||
let values = cons.map(c => {
|
||||
// Handle the code to remember what the user's choice was from before
|
||||
count++;
|
||||
if (idx === -1) {
|
||||
if (this.model.server && c.connectionId === this.model.server.connectionId) {
|
||||
idx = count;
|
||||
} else if (this.model.serverId && c.connectionId === this.model.serverId) {
|
||||
idx = count;
|
||||
}
|
||||
}
|
||||
|
||||
let db = c.options.databaseDisplayName;
|
||||
let usr = c.options.user;
|
||||
let srv = c.options.server;
|
||||
|
||||
if (!db) {
|
||||
db = '<default>';
|
||||
}
|
||||
|
||||
if (!usr) {
|
||||
usr = 'default';
|
||||
}
|
||||
|
||||
let finalName = `${srv}, ${db} (${usr})`;
|
||||
return {
|
||||
connection: c,
|
||||
displayName: finalName,
|
||||
name: c.connectionId
|
||||
};
|
||||
});
|
||||
|
||||
if (idx >= 0) {
|
||||
let tmp = values[0];
|
||||
values[0] = values[idx];
|
||||
values[idx] = tmp;
|
||||
} else {
|
||||
this.deleteServerValues();
|
||||
}
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
protected async getDatabaseValues(): Promise<{ displayName, name }[]> {
|
||||
let idx = -1;
|
||||
let count = -1;
|
||||
let values = (await azdata.connection.listDatabases(this.model.server.connectionId)).map(db => {
|
||||
count++;
|
||||
if (this.model.database && db === this.model.database) {
|
||||
idx = count;
|
||||
}
|
||||
|
||||
return {
|
||||
displayName: db,
|
||||
name: db
|
||||
};
|
||||
});
|
||||
|
||||
if (idx >= 0) {
|
||||
let tmp = values[0];
|
||||
values[0] = values[idx];
|
||||
values[idx] = tmp;
|
||||
} else {
|
||||
this.deleteDatabaseValues();
|
||||
}
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
protected deleteServerValues() {
|
||||
delete this.model.server;
|
||||
delete this.model.serverId;
|
||||
delete this.model.database;
|
||||
}
|
||||
|
||||
protected deleteDatabaseValues() {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
158
extensions/dacpac/src/wizard/api/dacFxConfigPage.ts
Normal file
158
extensions/dacpac/src/wizard/api/dacFxConfigPage.ts
Normal file
@@ -0,0 +1,158 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import * as azdata from 'azdata';
|
||||
import * as nls from 'vscode-nls';
|
||||
import * as os from 'os';
|
||||
import * as path from 'path';
|
||||
import { DataTierApplicationWizard } from '../dataTierApplicationWizard';
|
||||
import { DacFxDataModel } from './models';
|
||||
import { BasePage } from './basePage';
|
||||
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
export abstract class DacFxConfigPage extends BasePage {
|
||||
|
||||
protected readonly wizardPage: azdata.window.WizardPage;
|
||||
protected readonly instance: DataTierApplicationWizard;
|
||||
protected readonly model: DacFxDataModel;
|
||||
protected readonly view: azdata.ModelView;
|
||||
protected serverDropdown: azdata.DropDownComponent;
|
||||
protected databaseTextBox: azdata.InputBoxComponent;
|
||||
protected databaseDropdown: azdata.DropDownComponent;
|
||||
protected databaseLoader: azdata.LoadingComponent;
|
||||
protected fileTextBox: azdata.InputBoxComponent;
|
||||
protected fileButton: azdata.ButtonComponent;
|
||||
protected fileExtension: string;
|
||||
|
||||
protected constructor(instance: DataTierApplicationWizard, wizardPage: azdata.window.WizardPage, model: DacFxDataModel, view: azdata.ModelView) {
|
||||
super();
|
||||
this.instance = instance;
|
||||
this.wizardPage = wizardPage;
|
||||
this.model = model;
|
||||
this.view = view;
|
||||
}
|
||||
|
||||
public setupNavigationValidator() {
|
||||
this.instance.registerNavigationValidator(() => {
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
protected async createServerDropdown(isTargetServer: boolean): Promise<azdata.FormComponent> {
|
||||
this.serverDropdown = this.view.modelBuilder.dropDown().withProperties({
|
||||
required: true
|
||||
}).component();
|
||||
|
||||
// Handle server changes
|
||||
this.serverDropdown.onValueChanged(async () => {
|
||||
this.model.server = (this.serverDropdown.value as ConnectionDropdownValue).connection;
|
||||
this.model.serverName = (this.serverDropdown.value as ConnectionDropdownValue).displayName;
|
||||
await this.populateDatabaseDropdown();
|
||||
});
|
||||
|
||||
let targetServerTitle = localize('dacFx.targetServerDropdownTitle', 'Target Server');
|
||||
let sourceServerTitle = localize('dacFx.sourceServerDropdownTitle', 'Source Server');
|
||||
|
||||
return {
|
||||
component: this.serverDropdown,
|
||||
title: isTargetServer ? targetServerTitle : sourceServerTitle
|
||||
};
|
||||
}
|
||||
|
||||
protected async populateServerDropdown(): Promise<boolean> {
|
||||
let values = await this.getServerValues();
|
||||
if (values === undefined) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.model.server = values[0].connection;
|
||||
this.model.serverName = values[0].displayName;
|
||||
|
||||
this.serverDropdown.updateProperties({
|
||||
values: values
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
protected async createDatabaseTextBox(): Promise<azdata.FormComponent> {
|
||||
this.databaseTextBox = this.view.modelBuilder.inputBox().withProperties({
|
||||
required: true
|
||||
}).component();
|
||||
|
||||
this.databaseTextBox.onTextChanged(async () => {
|
||||
this.model.database = this.databaseTextBox.value;
|
||||
});
|
||||
|
||||
return {
|
||||
component: this.databaseTextBox,
|
||||
title: localize('dacFx.databaseNameTextBox', 'Target Database')
|
||||
};
|
||||
}
|
||||
|
||||
protected async createDatabaseDropdown(): Promise<azdata.FormComponent> {
|
||||
this.databaseDropdown = this.view.modelBuilder.dropDown().withProperties({
|
||||
required: true
|
||||
}).component();
|
||||
|
||||
// Handle database changes
|
||||
this.databaseDropdown.onValueChanged(async () => {
|
||||
this.model.database = (<azdata.CategoryValue>this.databaseDropdown.value).name;
|
||||
this.fileTextBox.value = this.generateFilePath();
|
||||
this.model.filePath = this.fileTextBox.value;
|
||||
});
|
||||
|
||||
this.databaseLoader = this.view.modelBuilder.loadingComponent().withItem(this.databaseDropdown).component();
|
||||
|
||||
return {
|
||||
component: this.databaseLoader,
|
||||
title: localize('dacFx.sourceDatabaseDropdownTitle', 'Source Database')
|
||||
};
|
||||
}
|
||||
|
||||
protected async populateDatabaseDropdown(): Promise<boolean> {
|
||||
this.databaseLoader.loading = true;
|
||||
this.databaseDropdown.updateProperties({ values: [] });
|
||||
|
||||
if (!this.model.server) {
|
||||
this.databaseLoader.loading = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
let values = await this.getDatabaseValues();
|
||||
this.model.database = values[0].name;
|
||||
this.model.filePath = this.generateFilePath();
|
||||
this.fileTextBox.value = this.model.filePath;
|
||||
|
||||
this.databaseDropdown.updateProperties({
|
||||
values: values
|
||||
});
|
||||
this.databaseLoader.loading = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected async createFileBrowserParts() {
|
||||
this.fileTextBox = this.view.modelBuilder.inputBox().withProperties({
|
||||
required: true
|
||||
}).component();
|
||||
|
||||
this.fileButton = this.view.modelBuilder.button().withProperties({
|
||||
label: '•••',
|
||||
}).component();
|
||||
}
|
||||
|
||||
protected generateFilePath(): string {
|
||||
let now = new Date();
|
||||
let datetime = now.getFullYear() + '-' + (now.getMonth() + 1) + '-' + now.getDate() + '-' + now.getHours() + '-' + now.getMinutes();
|
||||
return path.join(os.homedir(), this.model.database + '-' + datetime + this.fileExtension);
|
||||
}
|
||||
}
|
||||
|
||||
interface ConnectionDropdownValue extends azdata.CategoryValue {
|
||||
connection: azdata.connection.Connection;
|
||||
}
|
||||
|
||||
22
extensions/dacpac/src/wizard/api/models.ts
Normal file
22
extensions/dacpac/src/wizard/api/models.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import * as azdata from 'azdata';
|
||||
|
||||
/**
|
||||
* Data model to communicate between DacFx pages
|
||||
*/
|
||||
export interface DacFxDataModel {
|
||||
server: azdata.connection.Connection;
|
||||
database: string;
|
||||
serverName: string;
|
||||
serverId: string;
|
||||
filePath: string;
|
||||
version: string;
|
||||
upgradeExisting: boolean;
|
||||
scriptFilePath: string;
|
||||
generateScriptAndDeploy: boolean;
|
||||
}
|
||||
Reference in New Issue
Block a user