Fix dropdown error & editor database dropdown validation (#14946)

* Fix dropdown error & editor database dropdown validation

* Set initial values

* Update comment

* hygiene

* remove unused

* Fix tests
This commit is contained in:
Charles Gagnon
2021-04-01 14:52:55 -07:00
committed by GitHub
parent a00ffa0469
commit ce6ea8af41
4 changed files with 49 additions and 46 deletions

View File

@@ -13,7 +13,6 @@ import { IMessage, MessageType } from 'vs/base/browser/ui/inputbox/inputBox';
import { IListVirtualDelegate } from 'vs/base/browser/ui/list/list';
import { IListStyles, List } from 'vs/base/browser/ui/list/listWidget';
import { Color } from 'vs/base/common/color';
import { onUnexpectedError } from 'vs/base/common/errors';
import { Emitter, Event } from 'vs/base/common/event';
import { KeyCode } from 'vs/base/common/keyCodes';
import { Disposable } from 'vs/base/common/lifecycle';
@@ -221,7 +220,7 @@ export class Dropdown extends Disposable implements IListVirtualDelegate<string>
}));
this._input.onDidChange(e => {
if (this._dataSource.values?.length > 0) {
if (this._dataSource.values.length > 0) {
this._dataSource.filter = e;
if (this._isDropDownVisible) {
this._updateDropDownList();
@@ -297,25 +296,21 @@ export class Dropdown extends Disposable implements IListVirtualDelegate<string>
}
private _updateDropDownList(): void {
try {
this._selectList.splice(0, this._selectList.length, this._dataSource.filteredValues.map(v => { return { text: v }; }));
} catch (e) {
onUnexpectedError(e);
}
this._selectList.splice(0, this._selectList.length, this._dataSource.filteredValues.map(v => { return { text: v }; }));
let width = this._inputContainer.clientWidth;
if (this._dataSource && this._dataSource.filteredValues) {
const longestOption = this._dataSource.filteredValues.reduce((previous, current) => {
return previous.length > current.length ? previous : current;
}, '');
this._widthControlElement.innerText = longestOption;
const inputContainerWidth = DOM.getContentWidth(this._inputContainer);
const longestOptionWidth = DOM.getTotalWidth(this._widthControlElement);
width = clamp(longestOptionWidth, inputContainerWidth, 500);
}
// Find the longest option in the list and set our width to that (max 500px)
const longestOption = this._dataSource.filteredValues.reduce((previous, current) => {
return previous.length > current.length ? previous : current;
}, '');
this._widthControlElement.innerText = longestOption;
const height = Math.min((this._dataSource.filteredValues?.length ?? 0) * this.getHeight(), this._options.maxHeight ?? 500);
const inputContainerWidth = DOM.getContentWidth(this._inputContainer);
const longestOptionWidth = DOM.getTotalWidth(this._widthControlElement);
width = clamp(longestOptionWidth, inputContainerWidth, 500);
const height = Math.min(this._dataSource.filteredValues.length * this.getHeight(), this._options.maxHeight ?? 500);
this._selectListContainer.style.width = `${width}px`;
this._selectListContainer.style.height = `${height}px`;
this._selectList.layout(height, width);
@@ -361,7 +356,7 @@ export class Dropdown extends Disposable implements IListVirtualDelegate<string>
}
private _inputValidator(value: string): IMessage | null {
if (!this._input.hasFocus() && !this._selectList.isDOMFocused() && this._dataSource.values && !this._dataSource.values.some(i => i === value)) {
if (!this._input.hasFocus() && this._input.isEnabled() && !this._selectList.isDOMFocused() && !this._dataSource.values.some(i => i === value)) {
if (this._options.strictSelection && this._options.errorMessage) {
return {
content: this._options.errorMessage,

View File

@@ -42,9 +42,9 @@ export class DropdownListRenderer implements IListRenderer<IDropdownListItem, ID
}
export class DropdownDataSource {
values: string[];
public values: string[] = [];
filter: string | undefined;
public filter: string | undefined = undefined;
public get filteredValues(): string[] {
if (this.filter) {

View File

@@ -44,6 +44,7 @@ import { ConnectionProfile } from 'sql/platform/connection/common/connectionProf
import { IQueryManagementService } from 'sql/workbench/services/query/common/queryManagement';
import { ILogService } from 'vs/platform/log/common/log';
import { IRange } from 'vs/editor/common/core/range';
import { onUnexpectedError } from 'vs/base/common/errors';
/**
* Action class that query-based Actions will extend. This base class automatically handles activating and
@@ -761,48 +762,54 @@ export class ListDatabasesActionItem extends Disposable implements IActionViewIt
}
private onDropdownFocus(): void {
this.getDatabaseNames().then(databaseNames => {
this._dropdown.values = databaseNames;
}).catch(onUnexpectedError);
}
/**
* Fetches the list of database names from the current editor connection
* @returns The list of database names
*/
private async getDatabaseNames(): Promise<string[]> {
if (!this._editor.input) {
this.logService.error('editor input was null');
return;
return [];
}
let uri = this._editor.input.uri;
if (!uri) {
return;
return [];
}
this.connectionManagementService.listDatabases(uri)
.then(result => {
if (result && result.databaseNames) {
this._dropdown.values = result.databaseNames;
}
});
try {
const result = await this.connectionManagementService.listDatabases(uri);
return result.databaseNames;
} catch (err) {
this.logService.error(`Error loading database names for query editor `, err);
}
return [];
}
private updateConnection(databaseName: string) {
private updateConnection(databaseName: string): void {
this._isConnected = true;
this._currentDatabaseName = databaseName;
if (this._isInAccessibilityMode) {
this._databaseSelectBox.enable();
if (!this._editor.input) {
this.logService.error('editor input was null');
return;
}
let uri = this._editor.input.uri;
if (!uri) {
return;
}
this.connectionManagementService.listDatabases(uri)
.then(result => {
if (result && result.databaseNames) {
this._databaseSelectBox.setOptions(result.databaseNames);
}
this.getDatabaseNames()
.then(databaseNames => {
this._databaseSelectBox.setOptions(databaseNames);
this._databaseSelectBox.selectWithOptionName(databaseName);
});
}).catch(onUnexpectedError);
} else {
this._dropdown.enabled = true;
// Set the value immediately to the initial database so the user can see that, and then
// populate the list with just that value to avoid displaying an error while we load
// the full list of databases
this._dropdown.value = databaseName;
this._dropdown.values = [databaseName];
this._dropdown.enabled = true;
this.getDatabaseNames().then(databaseNames => {
this._dropdown.values = databaseNames;
}).catch(onUnexpectedError);
}
}

View File

@@ -68,6 +68,7 @@ suite('SQL QueryAction Tests', () => {
queryModelService.setup(q => q.onRunQueryComplete).returns(() => Event.None);
connectionManagementService = TypeMoq.Mock.ofType<TestConnectionManagementService>(TestConnectionManagementService);
connectionManagementService.setup(q => q.onDisconnect).returns(() => Event.None);
connectionManagementService.setup(q => q.listDatabases(TypeMoq.It.isAny())).returns(() => Promise.resolve({ databaseNames: ['master', 'msdb', 'model'] }));
const workbenchinstantiationService = workbenchInstantiationService();
const accessor = workbenchinstantiationService.createInstance(ServiceAccessor);
const service = accessor.untitledTextEditorService;