From 95f8c3c8b0fb770cdd86b97ba5f7ad91468eca75 Mon Sep 17 00:00:00 2001 From: Christopher Suh Date: Wed, 7 Apr 2021 11:07:15 -0700 Subject: [PATCH] ADS Migration UI Fixes (#15011) * wip database count * wip * added warnings count * changed warnings to issue details when DB selected * updated selected dbs * issues -> issue * fix issues/warnings --- .../sql-migration/src/constants/strings.ts | 11 ++++- .../assessmentResults/sqlDatabasesTree.ts | 42 +++++++++++++++---- .../sql-migration/src/models/stateMachine.ts | 7 ++-- 3 files changed, 47 insertions(+), 13 deletions(-) diff --git a/extensions/sql-migration/src/constants/strings.ts b/extensions/sql-migration/src/constants/strings.ts index cdd16aba2e..4898252e40 100644 --- a/extensions/sql-migration/src/constants/strings.ts +++ b/extensions/sql-migration/src/constants/strings.ts @@ -341,7 +341,6 @@ export const SERVER = localize('sql.migration.server', "Server"); export const USERNAME = localize('sql.migration.username', "Username"); //Assessment Dialog -export const DATABASES = localize('sql.migration.databases', "Databases"); export const ISSUES = localize('sql.migration.issues', "Issues"); export const SEARCH = localize('sql.migration.search', "Search"); export const INSTANCE = localize('sql.migration.instance', "Instance"); @@ -355,6 +354,7 @@ export const RECOMMENDATION = localize('sql.migration.recommendation', "Recommen export const MORE_INFO = localize('sql.migration.more.info', "More Info"); export const TARGET_PLATFORM = localize('sql.migration.target.platform', "Target Platform"); export const WARNINGS_DETAILS = localize('sql.migration.warnings.details', "Warnings Details"); +export const ISSUES_DETAILS = localize('sql.migration.issues.details', "Issue Details"); export const SELECT_DB_PROMPT = localize('sql.migration.select.prompt', "Click on SQL Server Instance or any of the databases on the left to view its details."); export function IMPACT_OBJECT_TYPE(objectType: string): string { return localize('sql.migration.impact.object.type', "Type: {0}", objectType); @@ -362,6 +362,15 @@ export function IMPACT_OBJECT_TYPE(objectType: string): string { export function IMPACT_OBJECT_NAME(objectName: string): string { return localize('sql.migration.impact.object.name', "Name: {0}", objectName); } +export function DATABASES(selectedCount: number, totalCount: number): string { + return localize('sql.migration.databases', "Databases ({0}/{1})", selectedCount, totalCount); +} +export function ISSUES_COUNT(totalCount: number): string { + return localize('sql.migration.issues.count', "Issues ({0})", totalCount); +} +export function WARNINGS_COUNT(totalCount: number): string { + return localize('sql.migration.warnings.count', "Warnings ({0})", totalCount); +} export const AUTHENTICATION_TYPE = localize('sql.migration.authentication.type', "Authentication Type"); export const SQL_LOGIN = localize('sql.migration.sql.login', "SQL Login"); export const WINDOWS_AUTHENTICATION = localize('sql.migration.windows.auth', "Windows Authentication"); diff --git a/extensions/sql-migration/src/dialog/assessmentResults/sqlDatabasesTree.ts b/extensions/sql-migration/src/dialog/assessmentResults/sqlDatabasesTree.ts index ce1b97baa1..9277cf39df 100644 --- a/extensions/sql-migration/src/dialog/assessmentResults/sqlDatabasesTree.ts +++ b/extensions/sql-migration/src/dialog/assessmentResults/sqlDatabasesTree.ts @@ -54,6 +54,7 @@ export class SqlDatabaseTree { private _recommendation!: azdata.TextComponent; private _dbName!: azdata.TextComponent; private _recommendationText!: azdata.TextComponent; + private _recommendationTitle!: azdata.TextComponent; private _descriptionText!: azdata.TextComponent; private _impactedObjects!: SqlMigrationImpactedObjectInfo[]; private _objectDetailsType!: azdata.TextComponent; @@ -61,6 +62,7 @@ export class SqlDatabaseTree { private _objectDetailsSample!: azdata.TextComponent; private _moreInfo!: azdata.HyperlinkComponent; private _assessmentTitle!: azdata.TextComponent; + private _databaseTableValues!: azdata.DeclarativeTableCellValue[][]; private _activeIssues!: SqlMigrationAssessmentResultItem[]; private _selectedIssue!: SqlMigrationAssessmentResultItem; @@ -68,6 +70,7 @@ export class SqlDatabaseTree { private _serverName!: string; private _dbNames!: string[]; + private _databaseCount!: azdata.TextComponent; constructor( @@ -107,10 +110,23 @@ export class SqlDatabaseTree { component.addItem(this.createSearchComponent(), { flex: '0 0 auto' }); component.addItem(this.createInstanceComponent(), { flex: '0 0 auto' }); + component.addItem(this.createDatabaseCount(), { flex: '0 0 auto' }); component.addItem(this.createDatabaseComponent(dbs), { flex: '1 1 auto', CSSStyles: { 'overflow-y': 'auto' } }); return component; } + private createDatabaseCount(): azdata.TextComponent { + this._databaseCount = this._view.modelBuilder.text().withProps({ + CSSStyles: { + 'font-size': '11px', + 'font-weight': 'bold', + 'margin': '0px 8px 0px 36px' + }, + value: constants.DATABASES(this.selectedDbs.length, this._model._serverDatabases.length) + }).component(); + return this._databaseCount; + } + private createDatabaseComponent(dbs: string[]): azdata.DivContainer { this._databaseTable = this._view.modelBuilder.declarativeTable().withProps( @@ -130,7 +146,7 @@ export class SqlDatabaseTree { headerCssStyles: headerLeft, }, { - displayName: constants.DATABASES, + displayName: constants.DATABASE, valueType: azdata.DeclarativeDataType.component, width: 100, isReadOnly: true, @@ -146,12 +162,19 @@ export class SqlDatabaseTree { ] } ).component(); - + this._databaseTable.onDataChanged(() => { + this._databaseCount.updateProperties({ + 'value': constants.DATABASES(this.selectedDbs().length, this._model._serverDatabases.length) + }); + }); this._databaseTable.onRowSelected(({ row }) => { + this._databaseTable.focus(); this._activeIssues = this._model._assessmentResults?.databaseAssessments[row].issues; this._selectedIssue = this._model._assessmentResults?.databaseAssessments[row].issues[0]; this._dbName.value = this._dbNames[row]; + this._recommendationTitle.value = constants.ISSUES_COUNT(this._activeIssues.length); + this._recommendation.value = constants.ISSUES_DETAILS; this._resultComponent.updateCssStyles({ 'display': 'block' }); @@ -227,7 +250,8 @@ export class SqlDatabaseTree { this._dbMessageContainer.updateCssStyles({ 'display': 'none' }); - + this._recommendation.value = constants.WARNINGS_DETAILS; + this._recommendationTitle.value = constants.WARNINGS_COUNT(this._activeIssues.length); if (this._model._targetType === MigrationTargetType.SQLMI) { this.refreshResults(); } @@ -578,7 +602,7 @@ export class SqlDatabaseTree { } private createAssessmentResultsTitle(): azdata.TextComponent { - this._recommendation = this._view.modelBuilder.text().withProps({ + this._recommendationTitle = this._view.modelBuilder.text().withProps({ value: constants.WARNINGS, CSSStyles: { 'font-size': '13px', @@ -589,7 +613,7 @@ export class SqlDatabaseTree { } }).component(); - return this._recommendation; + return this._recommendationTitle; } private createAssessmentDetailsTitle(): azdata.TextComponent { @@ -722,7 +746,7 @@ export class SqlDatabaseTree { public async initialize(): Promise { let instanceTableValues: azdata.DeclarativeTableCellValue[][] = []; - let databaseTableValues: azdata.DeclarativeTableCellValue[][] = []; + this._databaseTableValues = []; const excludedDatabases = ['master', 'msdb', 'tempdb', 'model']; this._dbNames = (await azdata.connection.listDatabases(this._model.sourceConnectionId)).filter(db => !excludedDatabases.includes(db)); const selectedDbs = (this._targetType === MigrationTargetType.SQLVM) ? this._model._vmDbs : this._model._miDbs; @@ -742,7 +766,7 @@ export class SqlDatabaseTree { ] ]; this._dbNames.forEach((db) => { - databaseTableValues.push( + this._databaseTableValues.push( [ { value: selectedDbs.includes(db), @@ -776,7 +800,7 @@ export class SqlDatabaseTree { return db2.issues.length - db1.issues.length; }); this._model._assessmentResults.databaseAssessments.forEach((db) => { - databaseTableValues.push( + this._databaseTableValues.push( [ { value: selectedDbs.includes(db.name), @@ -795,7 +819,7 @@ export class SqlDatabaseTree { }); } this._instanceTable.dataValues = instanceTableValues; - this._databaseTable.dataValues = databaseTableValues; + this._databaseTable.dataValues = this._databaseTableValues; } private createIconTextCell(icon: IconPath, text: string): azdata.FlexContainer { diff --git a/extensions/sql-migration/src/models/stateMachine.ts b/extensions/sql-migration/src/models/stateMachine.ts index 0074ba1c33..c7311c6aba 100644 --- a/extensions/sql-migration/src/models/stateMachine.ts +++ b/extensions/sql-migration/src/models/stateMachine.ts @@ -116,6 +116,7 @@ export class MigrationStateModel implements Model, vscode.Disposable { public _blobContainers!: azureResource.BlobContainer[]; public _refreshNetworkShareLocation!: azureResource.BlobContainer[]; public _targetDatabaseNames!: string[]; + public _serverDatabases!: string[]; public _sqlMigrationService!: SqlMigrationService; public _sqlMigrationServices!: SqlMigrationService[]; @@ -169,9 +170,9 @@ export class MigrationStateModel implements Model, vscode.Disposable { ownerUri ); - const serverDatabases = await (await azdata.connection.listDatabases(this.sourceConnectionId)).filter((name) => !excludeDbs.includes(name)); + this._serverDatabases = await (await azdata.connection.listDatabases(this.sourceConnectionId)).filter((name) => !excludeDbs.includes(name)); const serverLevelAssessments: mssql.SqlMigrationAssessmentResultItem[] = []; - const databaseLevelAssessments = serverDatabases.map(db => { + const databaseLevelAssessments = this._serverDatabases.map(db => { return { name: db, issues: [] @@ -180,7 +181,7 @@ export class MigrationStateModel implements Model, vscode.Disposable { assessmentResults?.items.forEach((item) => { if (item.appliesToMigrationTargetPlatform === MigrationTargetType.SQLMI) { - const dbIndex = serverDatabases.indexOf(item.databaseName); + const dbIndex = this._serverDatabases.indexOf(item.databaseName); if (dbIndex === -1) { serverLevelAssessments.push(item); } else {