diff --git a/extensions/schema-compare/src/dialogs/schemaCompareOptionsDialog.ts b/extensions/schema-compare/src/dialogs/schemaCompareOptionsDialog.ts index 74c0e1e682..956012b715 100644 --- a/extensions/schema-compare/src/dialogs/schemaCompareOptionsDialog.ts +++ b/extensions/schema-compare/src/dialogs/schemaCompareOptionsDialog.ts @@ -249,8 +249,12 @@ export class SchemaCompareOptionsDialog { private descriptionHeading: azdata.TableComponent; private descriptionText: azdata.TextComponent; - private generaloptionsCheckBoxes: azdata.CheckBoxComponent[] = []; - private objectTypesCheckBoxes: azdata.CheckBoxComponent[] = []; + private optionsTable: azdata.TableComponent; + private objectsTable: azdata.TableComponent; + private optionsLookup = {}; + private objectsLookup = {}; + private disposableListeners: vscode.Disposable[] = []; + private excludedObjectTypes: azdata.SchemaObjectType[] = []; private optionsLabels: string[] = [ @@ -436,9 +440,11 @@ export class SchemaCompareOptionsDialog { protected async execute() { this.SetDeploymentOptions(); this.SetObjectTypeOptions(); + this.disposeListeners(); } protected async cancel() { + this.disposeListeners(); } private async reset() { @@ -446,29 +452,25 @@ export class SchemaCompareOptionsDialog { let result = await service.schemaCompareGetDefaultOptions(); this.deploymentOptions = result.defaultDeploymentOptions; - this.generaloptionsCheckBoxes.forEach(option => { - option.checked = this.GetSchemaCompareOptionUtil(option.label); - }); - this.objectTypesCheckBoxes.forEach(obj => { - obj.checked = this.GetSchemaCompareIncludedObjectsUtil(obj.label); - }); + this.updateOptionsTable(); + this.optionsFlexBuilder.removeItem(this.optionsTable); + this.optionsFlexBuilder.insertItem(this.optionsTable, 0, { CSSStyles: { 'overflow': 'scroll', 'height': '65vh' } }); + + this.updateObjectsTable(); + this.objectTypesFlexBuilder.removeItem(this.objectsTable); + this.objectTypesFlexBuilder.addItem(this.objectsTable, { CSSStyles: { 'overflow': 'scroll', 'height': '80vh' } }); } private async initializeSchemaCompareOptionsDialogTab() { this.generalOptionsTab.registerContent(async view => { - this.optionsFlexBuilder = view.modelBuilder.flexContainer() - .withLayout({ - flexFlow: 'column', - }).component(); - this.descriptionHeading = view.modelBuilder.table().withProperties({ columns: [ { value: 'Option Description', headerCssClass: 'no-borders', toolTip: 'Option Description' - }, + } ] }).component(); @@ -476,20 +478,35 @@ export class SchemaCompareOptionsDialog { value: ' ' }).component(); - this.GetGeneralOptionCheckBoxes(view); - this.generaloptionsCheckBoxes.forEach(box => { - this.optionsFlexBuilder.addItem(box); - }); - let uberOptionsFlexBuilder = view.modelBuilder.flexContainer() + this.optionsTable = view.modelBuilder.table().component(); + this.updateOptionsTable(); + + this.disposableListeners.push(this.optionsTable.onRowSelected(async () => { + let row = this.optionsTable.selectedRows[0]; + let label = this.optionsLabels[row]; + this.descriptionText.updateProperties({ + value: this.GetDescription(label) + }); + })); + + this.disposableListeners.push(this.optionsTable.onCellAction(async (rowState) => { + let checkboxState = rowState; + if (checkboxState && checkboxState.row !== undefined) { + let label = this.optionsLabels[checkboxState.row]; + this.optionsLookup[label] = checkboxState.checked; + } + })); + + this.optionsFlexBuilder = view.modelBuilder.flexContainer() .withLayout({ - flexFlow: 'column', + flexFlow: 'column' }).component(); - uberOptionsFlexBuilder.addItem(this.optionsFlexBuilder, { CSSStyles: { 'overflow': 'scroll', 'height': '65vh' } }); - uberOptionsFlexBuilder.addItem(this.descriptionHeading, { CSSStyles: { 'font-weight': 'bold', 'height': '30px' } }); - uberOptionsFlexBuilder.addItem(this.descriptionText, { CSSStyles: { 'padding': '4px', 'overflow': 'scroll', 'height': '10vh' } }); - await view.initializeModel(uberOptionsFlexBuilder); + this.optionsFlexBuilder.addItem(this.optionsTable, { CSSStyles: { 'overflow': 'scroll', 'height': '65vh' } }); + this.optionsFlexBuilder.addItem(this.descriptionHeading, { CSSStyles: { 'font-weight': 'bold', 'height': '30px' } }); + this.optionsFlexBuilder.addItem(this.descriptionText, { CSSStyles: { 'padding': '4px', 'margin-right': '10px', 'overflow': 'scroll', 'height': '10vh' } }); + await view.initializeModel(this.optionsFlexBuilder); }); } @@ -498,56 +515,104 @@ export class SchemaCompareOptionsDialog { this.objectTypesFlexBuilder = view.modelBuilder.flexContainer() .withLayout({ - flexFlow: 'column', - height: 900 + flexFlow: 'column' }).component(); - this.GetObjectTypesCheckBoxes(view); - this.objectTypesCheckBoxes.forEach(b => { - this.objectTypesFlexBuilder.addItem(b); - }); + this.objectsTable = view.modelBuilder.table().component(); + this.updateObjectsTable(); - let uberOptionsFlexBuilder = view.modelBuilder.flexContainer() - .withLayout({ - flexFlow: 'column', - }).component(); + this.disposableListeners.push(this.objectsTable.onCellAction(async (rowState) => { + let checkboxState = rowState; + if (checkboxState && checkboxState.row !== undefined) { + let label = this.objectTypeLabels[checkboxState.row]; + this.objectsLookup[label] = checkboxState.checked; + } + })); - uberOptionsFlexBuilder.addItem(this.objectTypesFlexBuilder, { CSSStyles: { 'overflow': 'scroll' } }); + this.objectTypesFlexBuilder.addItem(this.objectsTable, { CSSStyles: { 'overflow': 'scroll', 'height': '80vh' } }); - await view.initializeModel(uberOptionsFlexBuilder); + await view.initializeModel(this.objectTypesFlexBuilder); }); } - private GetGeneralOptionCheckBoxes(view: azdata.ModelView) { + private disposeListeners(): void { + if (this.disposableListeners) { + this.disposableListeners.forEach(x => x.dispose()); + } + } + + private updateOptionsTable(): void { + let data = this.getOptionsData(); + this.optionsTable.updateProperties({ + data: data, + columns: [ + { + value: 'Include', + type: azdata.ColumnType.checkBox, + options: { actionOnCheckbox: azdata.ActionOnCellCheckboxCheck.customAction }, + headerCssClass: 'display-none', + cssClass: 'no-borders align-with-header', + width: 50 + }, + { + value: 'Option Name', + headerCssClass: 'display-none', + cssClass: 'no-borders align-with-header', + width: 50 + } + ] + }); + } + + private updateObjectsTable(): void { + let data = this.getObjectsData(); + this.objectsTable.updateProperties({ + data: data, + columns: [ + { + value: 'Include', + type: azdata.ColumnType.checkBox, + options: { actionOnCheckbox: azdata.ActionOnCellCheckboxCheck.customAction }, + headerCssClass: 'display-none', + cssClass: 'no-borders align-with-header', + width: 50 + }, + { + value: 'Option Name', + headerCssClass: 'display-none', + cssClass: 'no-borders align-with-header', + width: 50 + } + ] + }); + } + + private getOptionsData(): string[][] { + let data = []; + this.optionsLookup = {}; this.optionsLabels.forEach(l => { - let box: azdata.CheckBoxComponent = view.modelBuilder.checkBox().withProperties({ - checked: this.GetSchemaCompareOptionUtil(l), - label: l, - }).component(); - - box.onChanged(() => { - this.descriptionText.updateProperties({ - value: this.GetDescription(box.label) - }); - }); - this.generaloptionsCheckBoxes.push(box); + let checked: boolean = this.GetSchemaCompareOptionUtil(l); + data.push([checked, l]); + this.optionsLookup[l] = checked; }); + return data; } - private GetObjectTypesCheckBoxes(view: azdata.ModelView) { + private getObjectsData(): string[][] { + let data = []; + this.objectsLookup = {}; this.objectTypeLabels.forEach(l => { - let box: azdata.CheckBoxComponent = view.modelBuilder.checkBox().withProperties({ - checked: this.GetSchemaCompareIncludedObjectsUtil(l), - label: l - }).component(); - this.objectTypesCheckBoxes.push(box); + let checked: boolean = this.GetSchemaCompareIncludedObjectsUtil(l); + data.push([checked, l]); + this.objectsLookup[l] = checked; }); + return data; } private SetDeploymentOptions() { - this.generaloptionsCheckBoxes.forEach(box => { - this.SetSchemaCompareOptionUtil(box.label, box.checked); - }); + for (let option in this.optionsLookup) { + this.SetSchemaCompareOptionUtil(option, this.optionsLookup[option]); + } } private SetSchemaCompareOptionUtil(label: string, value: boolean) { @@ -1017,9 +1082,9 @@ export class SchemaCompareOptionsDialog { } private SetObjectTypeOptions() { - this.objectTypesCheckBoxes.forEach(box => { - this.SetSchemaCompareIncludedObjectsUtil(box.label, box.checked); - }); + for (let option in this.objectsLookup) { + this.SetSchemaCompareIncludedObjectsUtil(option, this.objectsLookup[option]); + } this.deploymentOptions.excludeObjectTypes = this.excludedObjectTypes; } diff --git a/src/sql/base/browser/ui/table/plugins/checkboxSelectColumn.plugin.ts b/src/sql/base/browser/ui/table/plugins/checkboxSelectColumn.plugin.ts index a975673896..016dde0941 100644 --- a/src/sql/base/browser/ui/table/plugins/checkboxSelectColumn.plugin.ts +++ b/src/sql/base/browser/ui/table/plugins/checkboxSelectColumn.plugin.ts @@ -12,6 +12,7 @@ import { range } from 'vs/base/common/arrays'; export interface ICheckboxSelectColumnOptions extends Slick.PluginOptions, ICheckboxStyles { columnId?: string; cssClass?: string; + headerCssClass?: string; toolTip?: string; width?: number; title?: string; @@ -34,6 +35,7 @@ export interface ICheckboxCellActionEventArgs { const defaultOptions: ICheckboxSelectColumnOptions = { columnId: '_checkbox_selector', cssClass: undefined, + headerCssClass: undefined, toolTip: nls.localize('selectDeselectAll', 'Select/Deselect All'), width: 30 }; @@ -228,6 +230,7 @@ export class CheckboxSelectColumn implements Slick.Plugin { resizable: false, sortable: false, cssClass: this._options.cssClass, + headerCssClass: this._options.headerCssClass, formatter: (r, c, v, cd, dc) => this.checkboxSelectionFormatter(r, c, v, cd, dc) }; } diff --git a/src/sql/workbench/electron-browser/modelComponents/media/table.css b/src/sql/workbench/electron-browser/modelComponents/media/table.css index 109a7f7053..939e05ebc7 100644 --- a/src/sql/workbench/electron-browser/modelComponents/media/table.css +++ b/src/sql/workbench/electron-browser/modelComponents/media/table.css @@ -16,4 +16,8 @@ .no-borders { border: none !important +} + +.display-none { + display: none; } \ No newline at end of file diff --git a/src/sql/workbench/electron-browser/modelComponents/table.component.ts b/src/sql/workbench/electron-browser/modelComponents/table.component.ts index dd7f5ff7aa..6c15021ba9 100644 --- a/src/sql/workbench/electron-browser/modelComponents/table.component.ts +++ b/src/sql/workbench/electron-browser/modelComponents/table.component.ts @@ -196,6 +196,7 @@ export default class TableComponent extends ComponentBase implements IComponent, toolTip: col.toolTip, width: col.width, cssClass: col.cssClass, + headerCssClass: col.headerCssClass, actionOnCheck: col.options ? col.options.actionOnCheckbox : null }, index);