fix properties widget (#9693)

* fix properties widget

* handle error scenario
This commit is contained in:
Alan Ren
2020-03-23 12:10:24 -07:00
committed by GitHub
parent 5a0dd18cba
commit c35221c076
3 changed files with 78 additions and 12 deletions

View File

@@ -4,20 +4,44 @@
*--------------------------------------------------------------------------------------------*/
import 'vs/css!./media/loadingComponent';
import { Component, Input } from '@angular/core';
import { Component, Input, OnChanges, SimpleChanges } from '@angular/core';
import * as nls from 'vs/nls';
import { status } from 'vs/base/browser/ui/aria/aria';
const DefaultLoadingMessage = nls.localize('loadingMessage', "Loading");
const DefaultLoadingCompletedMessage = nls.localize('loadingCompletedMessage', "Loading completed");
@Component({
selector: 'loading-spinner',
template: `
<div class="modelview-loadingComponent-container" *ngIf="loading">
<div class="modelview-loadingComponent-spinner" *ngIf="loading" [title]=_loadingTitle #spinnerElement></div>
<div class="modelview-loadingComponent-spinner" *ngIf="loading" [title]="_loadingMessage" #spinnerElement></div>
</div>
`
})
export default class LoadingSpinner {
public readonly _loadingTitle = nls.localize('loadingMessage', "Loading");
export default class LoadingSpinner implements OnChanges {
@Input() loading: boolean;
ngOnChanges(changes: SimpleChanges): void {
if (changes.loading !== undefined) {
const message = this.loading ? this._loadingMessage : this._loadingCompletedMessage;
status(message);
}
}
get _loadingMessage(): string {
return this.loadingMessage ? this.loadingMessage : DefaultLoadingMessage;
}
get _loadingCompletedMessage(): string {
return this.loadingCompletedMessage ? this.loadingCompletedMessage : DefaultLoadingCompletedMessage;
}
@Input()
loading: boolean;
@Input()
loadingMessage: string;
@Input()
loadingCompletedMessage: string;
}

View File

@@ -7,6 +7,8 @@
<div class="explorer-widget" style="display: flex; flex-flow: column; position: absolute; height:100%; width:100%; padding: 10px; box-sizing: border-box">
<div #input style="width: 100%"></div>
<div style="flex: 1 1 auto; position: relative">
<loading-spinner [loading]="loading" [loadingMessage]="loadingMessage"
[loadingCompletedMessage]="loadingCompletedMessage"></loading-spinner>
<div #table style="position: absolute; height: 100%; width: 100%"></div>
</div>
</div>

View File

@@ -6,7 +6,7 @@
import 'vs/css!sql/media/icons/common-icons';
import 'vs/css!./media/explorerWidget';
import { Component, Inject, forwardRef, OnInit, ViewChild, ElementRef } from '@angular/core';
import { Component, Inject, forwardRef, OnInit, ViewChild, ElementRef, ChangeDetectorRef } from '@angular/core';
import { Router } from '@angular/router';
import { DashboardWidget, IDashboardWidget, WidgetConfig, WIDGET_CONFIG } from 'sql/workbench/contrib/dashboard/browser/core/dashboardWidget';
@@ -27,6 +27,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti
import { ScrollbarVisibility } from 'vs/base/common/scrollable';
import { subscriptionToDisposable } from 'sql/base/browser/lifecycle';
import { ObjectMetadataWrapper } from 'sql/workbench/contrib/dashboard/browser/widgets/explorer/objectMetadataWrapper';
import { status, alert } from 'vs/base/browser/ui/aria/aria';
@Component({
selector: 'explorer-widget',
@@ -47,6 +48,9 @@ export class ExplorerWidget extends DashboardWidget implements IDashboardWidget,
private _treeFilter = new ExplorerFilter();
private _inited = false;
public loading: boolean = false;
public loadingMessage: string;
public loadingCompletedMessage: string;
@ViewChild('input') private _inputContainer: ElementRef;
@ViewChild('table') private _tableContainer: ElementRef;
@@ -59,9 +63,12 @@ export class ExplorerWidget extends DashboardWidget implements IDashboardWidget,
@Inject(IWorkbenchThemeService) private readonly themeService: IWorkbenchThemeService,
@Inject(IContextViewService) private readonly contextViewService: IContextViewService,
@Inject(IInstantiationService) private readonly instantiationService: IInstantiationService,
@Inject(ICapabilitiesService) private readonly capabilitiesService: ICapabilitiesService
@Inject(ICapabilitiesService) private readonly capabilitiesService: ICapabilitiesService,
@Inject(forwardRef(() => ChangeDetectorRef)) private readonly _cd: ChangeDetectorRef
) {
super();
this.loadingMessage = this._config.context === 'database' ? nls.localize('loadingObjects', "loading objects") : nls.localize('loadingDatabases', "loading databases");
this.loadingCompletedMessage = this._config.context === 'database' ? nls.localize('loadingObjectsCompleted', "loading objects completed.") : nls.localize('loadingDatabasesCompleted', "loading databases completed.");
this.init();
}
@@ -76,9 +83,25 @@ export class ExplorerWidget extends DashboardWidget implements IDashboardWidget,
};
this._input = new InputBox(this._inputContainer.nativeElement, this.contextViewService, inputOptions);
this._register(this._input.onDidChange(e => {
this._filterDelayer.trigger(() => {
this._filterDelayer.trigger(async () => {
this._treeFilter.filterString = e;
this._tree.refresh();
await this._tree.refresh();
const navigator = this._tree.getNavigator();
let item = navigator.next();
let count = 0;
while (item) {
count++;
item = navigator.next();
}
let message: string;
if (count === 0) {
message = nls.localize('explorerSearchNoMatchResultMessage', "No matching item found");
} else if (count === 1) {
message = nls.localize('explorerSearchSingleMatchResultMessage', "Filtered search list to 1 item");
} else {
message = nls.localize('explorerSearchMatchResultMessage', "Filtered search list to {0} items", count);
}
status(message);
});
}));
this._tree = new Tree(this._tableContainer.nativeElement, {
@@ -95,6 +118,8 @@ export class ExplorerWidget extends DashboardWidget implements IDashboardWidget,
}
private init(): void {
this.setLoadingStatus(true);
if (this._config.context === 'database') {
this._register(subscriptionToDisposable(this._bootstrap.metadataService.metadata.subscribe(
data => {
@@ -103,10 +128,11 @@ export class ExplorerWidget extends DashboardWidget implements IDashboardWidget,
objectData.sort(ObjectMetadataWrapper.sort);
this._treeDataSource.data = objectData;
this._tree.setInput(new ExplorerModel());
this.setLoadingStatus(false);
}
},
error => {
(<HTMLElement>this._el.nativeElement).innerText = nls.localize('dashboard.explorer.objectError', "Unable to load objects");
this.showErrorMessage(nls.localize('dashboard.explorer.objectError', "Unable to load objects"));
}
)));
} else {
@@ -122,9 +148,10 @@ export class ExplorerWidget extends DashboardWidget implements IDashboardWidget,
});
this._treeDataSource.data = profileData;
this._tree.setInput(new ExplorerModel());
this.setLoadingStatus(false);
},
error => {
(<HTMLElement>this._el.nativeElement).innerText = nls.localize('dashboard.explorer.databaseError', "Unable to load databases");
this.showErrorMessage(nls.localize('dashboard.explorer.databaseError', "Unable to load databases"));
}
)));
}
@@ -139,4 +166,17 @@ export class ExplorerWidget extends DashboardWidget implements IDashboardWidget,
this._tree.layout(getContentHeight(this._tableContainer.nativeElement));
}
}
private setLoadingStatus(loading: boolean): void {
this.loading = loading;
if (this._inited) {
this._cd.detectChanges();
}
}
private showErrorMessage(message: string): void {
(<HTMLElement>this._el.nativeElement).innerText = message;
alert(message);
}
}