diff --git a/extensions/sql-migration/src/api/utils.ts b/extensions/sql-migration/src/api/utils.ts index a6585ba2b4..f03e5f2fe4 100644 --- a/extensions/sql-migration/src/api/utils.ts +++ b/extensions/sql-migration/src/api/utils.ts @@ -156,3 +156,35 @@ export function findDropDownItemIndex(dropDown: DropDownComponent, value: string return -1; } + +export function debounce(delay: number): Function { + return decorate((fn, key) => { + const timerKey = `$debounce$${key}`; + + return function (this: any, ...args: any[]) { + clearTimeout(this[timerKey]); + this[timerKey] = setTimeout(() => fn.apply(this, args), delay); + }; + }); +} + +export function decorate(decorator: (fn: Function, key: string) => Function): Function { + return (_target: any, key: string, descriptor: any) => { + let fnKey: string | null = null; + let fn: Function | null = null; + + if (typeof descriptor.value === 'function') { + fnKey = 'value'; + fn = descriptor.value; + } else if (typeof descriptor.get === 'function') { + fnKey = 'get'; + fn = descriptor.get; + } + + if (!fn || !fnKey) { + throw new Error('not supported'); + } + + descriptor[fnKey] = decorator(fn, key); + }; +} diff --git a/extensions/sql-migration/src/dialog/assessmentResults/assessmentResultsDialog.ts b/extensions/sql-migration/src/dialog/assessmentResults/assessmentResultsDialog.ts index 805cb1f8b5..8f6e026e1e 100644 --- a/extensions/sql-migration/src/dialog/assessmentResults/assessmentResultsDialog.ts +++ b/extensions/sql-migration/src/dialog/assessmentResults/assessmentResultsDialog.ts @@ -46,7 +46,7 @@ export class AssessmentResultsDialog { }).component(); flex.addItem(await this._tree.createRootContainer(view), { flex: '1 1 auto' }); - view.initializeModel(flex); + await view.initializeModel(flex); resolve(); } catch (ex) { reject(ex); diff --git a/extensions/sql-migration/src/dialog/assessmentResults/sqlDatabasesTree.ts b/extensions/sql-migration/src/dialog/assessmentResults/sqlDatabasesTree.ts index 5e1dadc651..dff73ce523 100644 --- a/extensions/sql-migration/src/dialog/assessmentResults/sqlDatabasesTree.ts +++ b/extensions/sql-migration/src/dialog/assessmentResults/sqlDatabasesTree.ts @@ -7,6 +7,7 @@ import { SqlMigrationAssessmentResultItem, SqlMigrationImpactedObjectInfo } from import { IconPath, IconPathHelper } from '../../constants/iconPathHelper'; import { MigrationStateModel, MigrationTargetType } from '../../models/stateMachine'; import * as constants from '../../constants/strings'; +import { debounce } from '../../api/utils'; const styleLeft: azdata.CssStyles = { 'border': 'none', @@ -201,10 +202,13 @@ export class SqlDatabaseTree { private createSearchComponent(): azdata.DivContainer { let resourceSearchBox = this._view.modelBuilder.inputBox().withProps({ + stopEnterPropagation: true, placeHolder: constants.SEARCH, width: 200 }).component(); + resourceSearchBox.onTextChanged(value => this._filterTableList(value)); + const searchContainer = this._view.modelBuilder.divContainer().withItems([resourceSearchBox]).withProps({ CSSStyles: { 'width': '200px', @@ -215,6 +219,26 @@ export class SqlDatabaseTree { return searchContainer; } + @debounce(500) + private _filterTableList(value: string): void { + if (this._databaseTableValues && value?.length > 0) { + const filter: number[] = []; + this._databaseTableValues.forEach((row, index) => { + const flexContainer: azdata.FlexContainer = row[1]?.value as azdata.FlexContainer; + const textComponent: azdata.TextComponent = flexContainer.items[1] as azdata.TextComponent; + const cellText = textComponent.value?.toLowerCase(); + const searchText: string = value.toLowerCase(); + if (cellText?.includes(searchText)) { + filter.push(index); + } + }); + + this._databaseTable.setFilter(filter); + } else { + this._databaseTable.setFilter(undefined); + } + } + private createInstanceComponent(): azdata.DivContainer { this._instanceTable = this._view.modelBuilder.declarativeTable().withProps( { diff --git a/extensions/sql-migration/src/dialog/migrationStatus/migrationStatusDialog.ts b/extensions/sql-migration/src/dialog/migrationStatus/migrationStatusDialog.ts index ebbe96e09d..1a342f41f4 100644 --- a/extensions/sql-migration/src/dialog/migrationStatus/migrationStatusDialog.ts +++ b/extensions/sql-migration/src/dialog/migrationStatus/migrationStatusDialog.ts @@ -33,7 +33,7 @@ export class MigrationStatusDialog { initialize() { let tab = azdata.window.createTab(''); - tab.registerContent((view: azdata.ModelView) => { + tab.registerContent(async (view: azdata.ModelView) => { this._view = view; this._statusDropdown = this._view.modelBuilder.dropDown().withProps({ @@ -85,6 +85,7 @@ export class MigrationStatusDialog { private createSearchAndRefreshContainer(): azdata.FlexContainer { this._searchBox = this._view.modelBuilder.inputBox().withProps({ + stopEnterPropagation: true, placeHolder: loc.SEARCH_FOR_MIGRATIONS, width: '360px' }).component();