Added loading to dropdowns (#12214)

* Added loading prop to dropdowns

* Added property for setting loading text message

* removed unnecessary sets

* changed code to match new changes

* Changed the dropdown loader to use select component instead of edit.
Added missing props in dropdown loader
This commit is contained in:
Aasim Khan
2020-09-11 16:57:28 -07:00
committed by GitHub
parent 173a715a4d
commit 8cc8dcc89c
5 changed files with 73 additions and 19 deletions

View File

@@ -108,7 +108,6 @@ describe('File config page', function () {
should.notEqual(fileConfigPage.tableNameTextBox, undefined, 'tableNameTextBox should not be undefined');
should.notEqual(fileConfigPage.schemaDropdown, undefined, 'schemaDropdown should not be undefined');
should.notEqual(fileConfigPage.form, undefined, 'form should not be undefined');
should.notEqual(fileConfigPage.databaseLoader, undefined, 'databaseLoader should not be undefined');
should.notEqual(fileConfigPage.schemaLoader, undefined, 'schemaLoader should not be undefined');
await fileConfigPage.onPageLeave();

View File

@@ -18,7 +18,6 @@ export class FileConfigPage extends ImportPage {
private _schemaDropdown: azdata.DropDownComponent;
private _form: azdata.FormContainer;
private _databaseLoader: azdata.LoadingComponent;
private _schemaLoader: azdata.LoadingComponent;
public get serverDropdown(): azdata.DropDownComponent {
@@ -77,14 +76,6 @@ export class FileConfigPage extends ImportPage {
this._form = form;
}
public get databaseLoader(): azdata.LoadingComponent {
return this._databaseLoader;
}
public set databaseLoader(databaseLoader: azdata.LoadingComponent) {
this._databaseLoader = databaseLoader;
}
public get schemaLoader(): azdata.LoadingComponent {
return this._schemaLoader;
}
@@ -139,7 +130,7 @@ export class FileConfigPage extends ImportPage {
public setupNavigationValidator() {
this.instance.registerNavigationValidator((info) => {
if (this.schemaLoader.loading || this.databaseLoader.loading) {
if (this.schemaLoader.loading || this.databaseDropdown.loading) {
return false;
}
return true;
@@ -195,22 +186,20 @@ export class FileConfigPage extends ImportPage {
this.populateSchemaDropdown();
});
this.databaseLoader = this.view.modelBuilder.loadingComponent().withItem(this.databaseDropdown).component();
return {
component: this.databaseLoader,
component: this.databaseDropdown,
title: constants.databaseDropdownTitleText
};
}
private async populateDatabaseDropdown(): Promise<boolean> {
this.databaseLoader.loading = true;
this.databaseDropdown.loading = true;
this.databaseDropdown.updateProperties({ values: [] });
this.schemaDropdown.updateProperties({ values: [] });
if (!this.model.server) {
//TODO handle error case
this.databaseLoader.loading = false;
this.databaseDropdown.loading = false;
return false;
}
@@ -233,7 +222,7 @@ export class FileConfigPage extends ImportPage {
});
this.databaseDropdown.value = { displayName: this.model.database, name: this.model.database };
this.databaseLoader.loading = false;
this.databaseDropdown.loading = false;
return true;
}

View File

@@ -6,6 +6,7 @@
// This is the place for API experiments and proposal.
import * as vscode from 'vscode';
import { LoadingComponentProperties } from 'azdata';
declare module 'azdata' {
/**
@@ -256,6 +257,9 @@ declare module 'azdata' {
withProps(properties: TPropertyBag): ComponentBuilder<TComponent, TPropertyBag>;
}
export interface DropDownProperties extends LoadingComponentProperties {
}
export interface RadioCard {
id: string;
descriptions: RadioCardDescription[];

View File

@@ -1450,6 +1450,22 @@ class DropDownWrapper extends ComponentWrapper implements azdata.DropDownCompone
this.setProperty('fireOnTextChange', v);
}
public get loading(): boolean {
return this.properties['loading'];
}
public set loading(v: boolean) {
this.setProperty('loading', v);
}
public get loadingText(): string {
return this.properties['loadingText'];
}
public set loadingText(v: string) {
this.setProperty('loadingText', v);
}
public get onValueChanged(): vscode.Event<any> {
let emitter = this._emitterMap.get(ComponentEventType.onDidChange);
return emitter && emitter.event;

View File

@@ -21,12 +21,17 @@ import { IContextViewService } from 'vs/platform/contextview/browser/contextView
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { find } from 'vs/base/common/arrays';
import { IComponent, IComponentDescriptor, IModelStore, ComponentEventType } from 'sql/platform/dashboard/browser/interfaces';
import { localize } from 'vs/nls';
@Component({
selector: 'modelview-dropdown',
template: `
<div [style.width]="getWidth()">
<div [style.display]="getLoadingDisplay()" style="width: 100%; position: relative">
<div class="modelview-loadingComponent-spinner" style="position:absolute; right: 0px; margin-right: 5px; height:15px; z-index:1" #spinnerElement></div>
<div [style.display]="getLoadingDisplay()" #loadingBox style="width: 100%;"></div>
</div>
<div [style.display]="getEditableDisplay()" #editableDropDown style="width: 100%;"></div>
<div [style.display]="getNotEditableDisplay()" #dropDown style="width: 100%;"></div>
</div>
@@ -38,9 +43,11 @@ export default class DropDownComponent extends ComponentBase<azdata.DropDownProp
private _editableDropdown: Dropdown;
private _selectBox: SelectBox;
private _isInAccessibilityMode: boolean;
private _loadingBox: SelectBox;
@ViewChild('editableDropDown', { read: ElementRef }) private _editableDropDownContainer: ElementRef;
@ViewChild('dropDown', { read: ElementRef }) private _dropDownContainer: ElementRef;
@ViewChild('loadingBox', { read: ElementRef }) private _loadingBoxContainer: ElementRef;
constructor(
@Inject(forwardRef(() => ChangeDetectorRef)) changeRef: ChangeDetectorRef,
@Inject(IWorkbenchThemeService) private themeService: IWorkbenchThemeService,
@@ -103,6 +110,12 @@ export default class DropDownComponent extends ComponentBase<azdata.DropDownProp
}));
this._validations.push(() => !this.required || this.editable || !!this._selectBox.value);
}
this._loadingBox = new SelectBox([this.getStatusText()], this.getStatusText(), this.contextViewService, this._loadingBoxContainer.nativeElement);
this._loadingBox.render(this._loadingBoxContainer.nativeElement);
this._register(this._loadingBox);
this._register(attachSelectBoxStyler(this._loadingBox, this.themeService));
this._loadingBoxContainer.nativeElement.className = ''; // Removing the dropdown arrow icon from the right
}
ngOnDestroy(): void {
@@ -122,6 +135,7 @@ export default class DropDownComponent extends ComponentBase<azdata.DropDownProp
if (this.ariaLabel !== '') {
this._selectBox.setAriaLabel(this.ariaLabel);
this._editableDropdown.ariaLabel = this.ariaLabel;
this._loadingBox.setAriaLabel(this.ariaLabel);
}
if (this.editable && !this._isInAccessibilityMode) {
@@ -141,6 +155,14 @@ export default class DropDownComponent extends ComponentBase<azdata.DropDownProp
}
}
if (this.loading) {
this._loadingBox.setOptions([this.getStatusText()]);
this._loadingBox.selectWithOptionName(this.getStatusText());
this._loadingBox.enable();
} else {
this._loadingBox.disable();
}
this._selectBox.selectElem.required = this.required;
this._editableDropdown.inputElement.required = this.required;
this.validate();
@@ -198,11 +220,15 @@ export default class DropDownComponent extends ComponentBase<azdata.DropDownProp
}
public getEditableDisplay(): string {
return this.editable && !this._isInAccessibilityMode ? '' : 'none';
return (this.editable && !this._isInAccessibilityMode) && !this.loading ? '' : 'none';
}
public getNotEditableDisplay(): string {
return !this.editable || this._isInAccessibilityMode ? '' : 'none';
return (!this.editable || this._isInAccessibilityMode) && !this.loading ? '' : 'none';
}
public getLoadingDisplay(): string {
return this.loading ? '' : 'none';
}
private set value(newValue: string | azdata.CategoryValue) {
@@ -240,4 +266,24 @@ export default class DropDownComponent extends ComponentBase<azdata.DropDownProp
this._selectBox.focus();
}
}
public get showText(): boolean {
return this.getPropertyOrDefault<boolean>((props) => props.showText, false);
}
public get loading(): boolean {
return this.getPropertyOrDefault<boolean>((props) => props.loading, false);
}
public get loadingText(): string {
return this.getPropertyOrDefault<string>((props) => props.loadingText, localize('loadingMessage', "Loading"));
}
public get loadingCompletedText(): string {
return this.getPropertyOrDefault<string>((props) => props.loadingCompletedText, localize('loadingCompletedMessage', "Loading completed"));
}
public getStatusText(): string {
return this.loading ? this.loadingText : this.loadingCompletedText;
}
}