mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-15 09:35:37 -05:00
Fixes for sql db projects dashboard (#15100)
* Fix ID assignment for sql db projects dashboard * Update with new fixes * Fix tests * Fix test
This commit is contained in:
@@ -37,12 +37,14 @@ export const buildAction = localize('buildAction', "Build");
|
||||
export const publishAction = localize('publishAction', "Publish");
|
||||
export const changeTargetPlatformAction = localize('changeTargetPlatformAction', "Change Target Platform");
|
||||
|
||||
export const ID = localize('ID', "ID");
|
||||
export const Status = localize('Status', "Status");
|
||||
export const Time = localize('Time', "Time");
|
||||
export const Date = localize('Date', "Date");
|
||||
export const Builds = localize('Builds', "Builds");
|
||||
export const Deployments = localize('Deployments', "Deployments");
|
||||
export const TargetPlatform = localize('TargetPlatform', "Target Platform");
|
||||
export const TargetServer = localize('TargetServer', "Target Server");
|
||||
export const TargetDatabase = localize('TargetDatabase', "Target Database");
|
||||
export const BuildHistory = localize('BuildHistory', "Build History");
|
||||
export const PublishHistory = localize('PublishHistory', "Publish History");
|
||||
|
||||
export const Success = localize('Success', "Success");
|
||||
export const Failed = localize('Failed', "Failed");
|
||||
|
||||
@@ -32,7 +32,7 @@ import { DatabaseReferenceTreeItem } from '../models/tree/databaseReferencesTree
|
||||
import { CreateProjectFromDatabaseDialog } from '../dialogs/createProjectFromDatabaseDialog';
|
||||
import { TelemetryActions, TelemetryReporter, TelemetryViews } from '../common/telemetry';
|
||||
import { IconPathHelper } from '../common/iconHelper';
|
||||
import { DashboardData, Status } from '../models/dashboardData/dashboardData';
|
||||
import { DashboardData, PublishData, Status } from '../models/dashboardData/dashboardData';
|
||||
|
||||
const maxTableLength = 10;
|
||||
|
||||
@@ -43,7 +43,7 @@ export class ProjectsController {
|
||||
private netCoreTool: NetCoreTool;
|
||||
private buildHelper: BuildHelper;
|
||||
private buildInfo: DashboardData[] = [];
|
||||
private deployInfo: DashboardData[] = [];
|
||||
private publishInfo: PublishData[] = [];
|
||||
|
||||
projFileWatchers = new Map<string, vscode.FileSystemWatcher>();
|
||||
|
||||
@@ -52,18 +52,17 @@ export class ProjectsController {
|
||||
this.buildHelper = new BuildHelper();
|
||||
}
|
||||
|
||||
public getDashboardDeployData(projectFile: string): (string | dataworkspace.IconCellValue)[][] {
|
||||
public getDashboardPublishData(projectFile: string): (string | dataworkspace.IconCellValue)[][] {
|
||||
const infoRows: (string | dataworkspace.IconCellValue)[][] = [];
|
||||
let count = 0;
|
||||
|
||||
for (let i = this.deployInfo.length - 1; i >= 0; i--) {
|
||||
if (this.deployInfo[i].projectFile === projectFile) {
|
||||
for (let i = this.publishInfo.length - 1; i >= 0; i--) {
|
||||
if (this.publishInfo[i].projectFile === projectFile) {
|
||||
let icon: azdata.IconPath;
|
||||
let text: string;
|
||||
if (this.deployInfo[i].status === Status.success) {
|
||||
if (this.publishInfo[i].status === Status.success) {
|
||||
icon = IconPathHelper.success;
|
||||
text = constants.Success;
|
||||
} else if (this.deployInfo[i].status === Status.failed) {
|
||||
} else if (this.publishInfo[i].status === Status.failed) {
|
||||
icon = IconPathHelper.error;
|
||||
text = constants.Failed;
|
||||
} else {
|
||||
@@ -71,13 +70,13 @@ export class ProjectsController {
|
||||
text = constants.InProgress;
|
||||
}
|
||||
|
||||
let infoRow: (string | dataworkspace.IconCellValue)[] = [count.toString(),
|
||||
{ text: text, icon: icon },
|
||||
this.deployInfo[i].target,
|
||||
this.deployInfo[i].timeToCompleteAction,
|
||||
this.deployInfo[i].startDate];
|
||||
let infoRow: (string | dataworkspace.IconCellValue)[] = [{ text: text, icon: icon },
|
||||
this.publishInfo[i].startDate,
|
||||
this.publishInfo[i].timeToCompleteAction,
|
||||
this.publishInfo[i].target,
|
||||
this.publishInfo[i].targetServer,
|
||||
this.publishInfo[i].targetDatabase];
|
||||
infoRows.push(infoRow);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,7 +85,6 @@ export class ProjectsController {
|
||||
|
||||
public getDashboardBuildData(projectFile: string): (string | dataworkspace.IconCellValue)[][] {
|
||||
const infoRows: (string | dataworkspace.IconCellValue)[][] = [];
|
||||
let count = 0;
|
||||
|
||||
for (let i = this.buildInfo.length - 1; i >= 0; i--) {
|
||||
if (this.buildInfo[i].projectFile === projectFile) {
|
||||
@@ -103,13 +101,11 @@ export class ProjectsController {
|
||||
text = constants.InProgress;
|
||||
}
|
||||
|
||||
let infoRow: (string | dataworkspace.IconCellValue)[] = [count.toString(),
|
||||
{ text: text, icon: icon },
|
||||
this.buildInfo[i].target,
|
||||
let infoRow: (string | dataworkspace.IconCellValue)[] = [{ text: text, icon: icon },
|
||||
this.buildInfo[i].startDate,
|
||||
this.buildInfo[i].timeToCompleteAction,
|
||||
this.buildInfo[i].startDate];
|
||||
this.buildInfo[i].target];
|
||||
infoRows.push(infoRow);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -278,13 +274,13 @@ export class ProjectsController {
|
||||
telemetryProps.profileUsed = (settings.profileUsed ?? false).toString();
|
||||
const currentDate = new Date();
|
||||
const actionStartTime = currentDate.getTime();
|
||||
const currentDeployTimeInfo = `${currentDate.toLocaleDateString()} ${constants.at} ${currentDate.toLocaleTimeString()}`;
|
||||
const currentPublishTimeInfo = `${currentDate.toLocaleDateString()} ${constants.at} ${currentDate.toLocaleTimeString()}`;
|
||||
|
||||
let deployInfoNew = new DashboardData(project.projectFilePath, Status.inProgress, project.getProjectTargetVersion(), currentDeployTimeInfo);
|
||||
this.deployInfo.push(deployInfoNew);
|
||||
let publishInfoNew = new PublishData(project.projectFilePath, Status.inProgress, project.getProjectTargetVersion(), currentPublishTimeInfo, settings.databaseName, settings.serverName);
|
||||
this.publishInfo.push(publishInfoNew);
|
||||
|
||||
if (this.deployInfo.length - 1 === maxTableLength) {
|
||||
this.deployInfo.shift(); // Remove the first element to maintain the length
|
||||
if (this.publishInfo.length - 1 === maxTableLength) {
|
||||
this.publishInfo.shift(); // Remove the first element to maintain the length
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -298,29 +294,29 @@ export class ProjectsController {
|
||||
}
|
||||
} catch (err) {
|
||||
const actionEndTime = new Date().getTime();
|
||||
const timeToFailureDeploy = actionEndTime - actionStartTime;
|
||||
telemetryProps.actionDuration = timeToFailureDeploy.toString();
|
||||
const timeToFailurePublish = actionEndTime - actionStartTime;
|
||||
telemetryProps.actionDuration = timeToFailurePublish.toString();
|
||||
telemetryProps.totalDuration = (actionEndTime - buildStartTime).toString();
|
||||
|
||||
TelemetryReporter.createErrorEvent(TelemetryViews.ProjectController, TelemetryActions.publishProject)
|
||||
.withAdditionalProperties(telemetryProps)
|
||||
.send();
|
||||
|
||||
const currentDeployIndex = this.deployInfo.findIndex(d => d.startDate === currentDeployTimeInfo);
|
||||
this.deployInfo[currentDeployIndex].status = Status.failed;
|
||||
this.deployInfo[currentDeployIndex].timeToCompleteAction = utils.timeConversion(timeToFailureDeploy);
|
||||
const currentPublishIndex = this.publishInfo.findIndex(d => d.startDate === currentPublishTimeInfo);
|
||||
this.publishInfo[currentPublishIndex].status = Status.failed;
|
||||
this.publishInfo[currentPublishIndex].timeToCompleteAction = utils.timeConversion(timeToFailurePublish);
|
||||
|
||||
throw err;
|
||||
}
|
||||
|
||||
const actionEndTime = new Date().getTime();
|
||||
const timeToDeploy = actionEndTime - actionStartTime;
|
||||
telemetryProps.actionDuration = timeToDeploy.toString();
|
||||
const timeToPublish = actionEndTime - actionStartTime;
|
||||
telemetryProps.actionDuration = timeToPublish.toString();
|
||||
telemetryProps.totalDuration = (actionEndTime - buildStartTime).toString();
|
||||
|
||||
const currentDeployIndex = this.deployInfo.findIndex(d => d.startDate === currentDeployTimeInfo);
|
||||
this.deployInfo[currentDeployIndex].status = result.success ? Status.success : Status.failed;
|
||||
this.deployInfo[currentDeployIndex].timeToCompleteAction = utils.timeConversion(timeToDeploy);
|
||||
const currentPublishIndex = this.publishInfo.findIndex(d => d.startDate === currentPublishTimeInfo);
|
||||
this.publishInfo[currentPublishIndex].status = result.success ? Status.success : Status.failed;
|
||||
this.publishInfo[currentPublishIndex].timeToCompleteAction = utils.timeConversion(timeToPublish);
|
||||
|
||||
TelemetryReporter.createActionEvent(TelemetryViews.ProjectController, TelemetryActions.publishProject)
|
||||
.withAdditionalProperties(telemetryProps)
|
||||
|
||||
@@ -42,6 +42,7 @@ export class PublishDatabaseDialog {
|
||||
private sqlCmdVars: Record<string, string> | undefined;
|
||||
private deploymentOptions: DeploymentOptions | undefined;
|
||||
private profileUsed: boolean = false;
|
||||
private serverName: string | undefined;
|
||||
|
||||
private toDispose: vscode.Disposable[] = [];
|
||||
|
||||
@@ -183,6 +184,7 @@ export class PublishDatabaseDialog {
|
||||
public async publishClick(): Promise<void> {
|
||||
const settings: IPublishSettings = {
|
||||
databaseName: this.getTargetDatabaseName(),
|
||||
serverName: this.getServerName(),
|
||||
upgradeExisting: true,
|
||||
connectionUri: await this.getConnectionUri(),
|
||||
sqlCmdVariables: this.getSqlCmdVariablesForPublish(),
|
||||
@@ -202,6 +204,7 @@ export class PublishDatabaseDialog {
|
||||
const sqlCmdVars = this.getSqlCmdVariablesForPublish();
|
||||
const settings: IGenerateScriptSettings = {
|
||||
databaseName: this.getTargetDatabaseName(),
|
||||
serverName: this.getServerName(),
|
||||
connectionUri: await this.getConnectionUri(),
|
||||
sqlCmdVariables: sqlCmdVars,
|
||||
deploymentOptions: await this.getDeploymentOptions(),
|
||||
@@ -249,6 +252,10 @@ export class PublishDatabaseDialog {
|
||||
return this.project.projectFileName;
|
||||
}
|
||||
|
||||
public getServerName(): string {
|
||||
return this.serverName!;
|
||||
}
|
||||
|
||||
private createRadioButtons(view: azdata.ModelView): azdata.Component {
|
||||
this.connectionsRadioButton = view.modelBuilder.radioButton()
|
||||
.withProperties({
|
||||
@@ -488,6 +495,7 @@ export class PublishDatabaseDialog {
|
||||
selectConnectionButton.onDidClick(async () => {
|
||||
let connection = await azdata.connection.openConnectionDialog();
|
||||
this.connectionId = connection.connectionId;
|
||||
this.serverName = connection.options['server'];
|
||||
|
||||
let connectionTextboxValue: string = getConnectionName(connection);
|
||||
|
||||
@@ -550,6 +558,7 @@ export class PublishDatabaseDialog {
|
||||
(<azdata.DropDownComponent>this.targetDatabaseDropDown).values = [];
|
||||
|
||||
this.connectionId = result.connectionId;
|
||||
this.serverName = result.serverName;
|
||||
await this.updateConnectionComponents(result.connection, <string>this.connectionId);
|
||||
|
||||
if (result.databaseName) {
|
||||
|
||||
@@ -7,6 +7,7 @@ import { DeploymentOptions } from '../../../mssql/src/mssql';
|
||||
|
||||
export interface IPublishSettings {
|
||||
databaseName: string;
|
||||
serverName: string;
|
||||
connectionUri: string;
|
||||
upgradeExisting: boolean;
|
||||
sqlCmdVariables?: Record<string, string>;
|
||||
@@ -16,6 +17,7 @@ export interface IPublishSettings {
|
||||
|
||||
export interface IGenerateScriptSettings {
|
||||
databaseName: string;
|
||||
serverName: string;
|
||||
connectionUri: string;
|
||||
sqlCmdVariables?: Record<string, string>;
|
||||
deploymentOptions?: DeploymentOptions;
|
||||
|
||||
@@ -19,6 +19,17 @@ export class DashboardData {
|
||||
}
|
||||
}
|
||||
|
||||
export class PublishData extends DashboardData {
|
||||
public targetServer: string;
|
||||
public targetDatabase: string;
|
||||
|
||||
constructor(projectFile: string, status: Status, target: string, startDate: string, targetDatabase: string, targetServer: string) {
|
||||
super(projectFile, status, target, startDate);
|
||||
this.targetDatabase = targetDatabase;
|
||||
this.targetServer = targetServer;
|
||||
}
|
||||
}
|
||||
|
||||
export enum Status {
|
||||
success,
|
||||
failed,
|
||||
|
||||
@@ -16,6 +16,7 @@ import { SqlConnectionDataSource } from '../dataSources/sqlConnectionStringSourc
|
||||
// only reading db name, connection string, and SQLCMD vars from profile for now
|
||||
export interface PublishProfile {
|
||||
databaseName: string;
|
||||
serverName: string;
|
||||
connectionId: string;
|
||||
connection: string;
|
||||
sqlCmdVariables: Record<string, string>;
|
||||
@@ -45,6 +46,7 @@ export async function load(profileUri: Uri, dacfxService: mssql.IDacFxService):
|
||||
|
||||
return {
|
||||
databaseName: targetDbName,
|
||||
serverName: connectionInfo.server,
|
||||
connectionId: connectionInfo.connectionId,
|
||||
connection: connectionInfo.connection,
|
||||
sqlCmdVariables: sqlCmdVariables,
|
||||
@@ -52,14 +54,14 @@ export async function load(profileUri: Uri, dacfxService: mssql.IDacFxService):
|
||||
};
|
||||
}
|
||||
|
||||
async function readConnectionString(xmlDoc: any): Promise<{ connectionId: string, connection: string }> {
|
||||
async function readConnectionString(xmlDoc: any): Promise<{ connectionId: string, connection: string, server: string }> {
|
||||
let targetConnection: string = '';
|
||||
let connId: string = '';
|
||||
let server: string = '';
|
||||
|
||||
if (xmlDoc.documentElement.getElementsByTagName(constants.targetConnectionString).length > 0) {
|
||||
const targetConnectionString = xmlDoc.documentElement.getElementsByTagName(constants.TargetConnectionString)[0].textContent;
|
||||
const dataSource = new SqlConnectionDataSource('', targetConnectionString);
|
||||
let server: string = '';
|
||||
let username: string = '';
|
||||
const connectionProfile = dataSource.getConnectionProfile();
|
||||
|
||||
@@ -86,6 +88,7 @@ async function readConnectionString(xmlDoc: any): Promise<{ connectionId: string
|
||||
|
||||
return {
|
||||
connectionId: connId,
|
||||
connection: targetConnection
|
||||
connection: targetConnection,
|
||||
server: server
|
||||
};
|
||||
}
|
||||
|
||||
@@ -127,27 +127,28 @@ export class SqlDatabaseProjectProvider implements dataworkspace.IProjectProvide
|
||||
* Gets the data to be displayed in the project dashboard
|
||||
*/
|
||||
getDashboardComponents(projectFile: string): dataworkspace.IDashboardTable[] {
|
||||
const deployInfo: dataworkspace.IDashboardTable = {
|
||||
name: constants.Deployments,
|
||||
columns: [{ displayName: constants.ID, width: 100 },
|
||||
{ displayName: constants.Status, width: 250, type: 'icon' },
|
||||
{ displayName: constants.Target, width: 250 },
|
||||
{ displayName: constants.Time, width: 250 },
|
||||
{ displayName: constants.Date, width: 250 }],
|
||||
data: this.projectController.getDashboardDeployData(projectFile)
|
||||
const width = 200;
|
||||
const publishInfo: dataworkspace.IDashboardTable = {
|
||||
name: constants.PublishHistory,
|
||||
columns: [{ displayName: constants.Status, width: width, type: 'icon' },
|
||||
{ displayName: constants.Date, width: width },
|
||||
{ displayName: constants.Time, width: width },
|
||||
{ displayName: constants.TargetPlatform, width: width },
|
||||
{ displayName: constants.TargetServer, width: width },
|
||||
{ displayName: constants.TargetDatabase, width: width }],
|
||||
data: this.projectController.getDashboardPublishData(projectFile)
|
||||
};
|
||||
|
||||
const buildInfo: dataworkspace.IDashboardTable = {
|
||||
name: constants.Builds,
|
||||
columns: [{ displayName: constants.ID, width: 100 },
|
||||
{ displayName: constants.Status, width: 250, type: 'icon' },
|
||||
{ displayName: constants.Target, width: 250 },
|
||||
{ displayName: constants.Time, width: 250 },
|
||||
{ displayName: constants.Date, width: 250 }],
|
||||
name: constants.BuildHistory,
|
||||
columns: [{ displayName: constants.Status, width: width, type: 'icon' },
|
||||
{ displayName: constants.Date, width: width },
|
||||
{ displayName: constants.Time, width: width },
|
||||
{ displayName: constants.TargetPlatform, width: width }],
|
||||
data: this.projectController.getDashboardBuildData(projectFile)
|
||||
};
|
||||
|
||||
return [deployInfo, buildInfo];
|
||||
return [publishInfo, buildInfo];
|
||||
}
|
||||
|
||||
get image(): ThemedIconPath {
|
||||
|
||||
@@ -67,12 +67,14 @@ describe('Publish Database Dialog', () => {
|
||||
dialog.setup(x => x.getTargetDatabaseName()).returns(() => 'MockDatabaseName');
|
||||
dialog.setup(x => x.getSqlCmdVariablesForPublish()).returns(() => proj.sqlCmdVariables);
|
||||
dialog.setup(x => x.getDeploymentOptions()).returns(() => { return Promise.resolve(mockDacFxOptionsResult.deploymentOptions); });
|
||||
dialog.setup(x => x.getServerName()).returns(() => 'MockServer');
|
||||
dialog.callBase = true;
|
||||
|
||||
let profile: IPublishSettings | IGenerateScriptSettings | undefined;
|
||||
|
||||
const expectedPublish: IPublishSettings = {
|
||||
databaseName: 'MockDatabaseName',
|
||||
serverName: 'MockServer',
|
||||
connectionUri: 'Mock|Connection|Uri',
|
||||
upgradeExisting: true,
|
||||
sqlCmdVariables: {
|
||||
@@ -90,6 +92,7 @@ describe('Publish Database Dialog', () => {
|
||||
|
||||
const expectedGenScript: IGenerateScriptSettings = {
|
||||
databaseName: 'MockDatabaseName',
|
||||
serverName: 'MockServer',
|
||||
connectionUri: 'Mock|Connection|Uri',
|
||||
sqlCmdVariables: {
|
||||
'ProdDatabaseName': 'MyProdDatabase',
|
||||
|
||||
@@ -411,7 +411,7 @@ describe('ProjectsController', function (): void {
|
||||
|
||||
const proj = await testUtils.createTestProject(baselines.openProjectFileBaseline);
|
||||
|
||||
await projController.object.publishProjectCallback(proj, { connectionUri: '', databaseName: '' });
|
||||
await projController.object.publishProjectCallback(proj, { connectionUri: '', databaseName: '' , serverName: ''});
|
||||
|
||||
should(builtDacpacPath).not.equal('', 'built dacpac path should be set');
|
||||
should(publishedDacpacPath).not.equal('', 'published dacpac path should be set');
|
||||
|
||||
Reference in New Issue
Block a user