Add account loading screen until provider accounts have finished loading (#18692)

* Added wait for accounts to be loaded to prevent premature loading

* revert changes

* WIP loading screen

* added work in progress emitter.

* added test event fire

* added test for accountDialogController emitter

* fixed test

* added event emitters inside accountDialog

* WIP changes to loading

* added fixed filter removed unnecessary emitters

* added working loading page

* fix for spaces

* added improvements

* fixed space

* added loading provider label xlf

* moved spinner = false to show views

* Added loadingSpinner

* removed additional localization

* removed change to css

* removed newline

* small changes

* fixed spaces

* fixed line positions

* removed loadingComplete

* added spinner container (so that account loading spinner appears on top)

* added small fix

* changed wording

* changed wording slightly

* removed comment
This commit is contained in:
Alex Ma
2022-03-14 09:44:09 -07:00
committed by GitHub
parent 02093f8497
commit 26e6cd28c2
3 changed files with 28 additions and 10 deletions

View File

@@ -87,7 +87,7 @@ function createInstantiationService(addAccountFailureEmitter?: Emitter<string>):
.returns(() => undefined); .returns(() => undefined);
// Create a mock account dialog // Create a mock account dialog
let accountDialog = new AccountDialog(undefined!, undefined!, instantiationService.object, undefined!, undefined!, undefined!, undefined!, new MockContextKeyService(), undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!); let accountDialog = new AccountDialog(undefined!, undefined!, instantiationService.object, undefined!, undefined!, undefined!, undefined!, new MockContextKeyService(), undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!);
let mockAccountDialog = TypeMoq.Mock.ofInstance(accountDialog); let mockAccountDialog = TypeMoq.Mock.ofInstance(accountDialog);
mockAccountDialog.setup(x => x.onAddAccountErrorEvent) mockAccountDialog.setup(x => x.onAddAccountErrorEvent)
.returns(() => { return addAccountFailureEmitter ? addAccountFailureEmitter.event : mockEvent.event; }); .returns(() => { return addAccountFailureEmitter ? addAccountFailureEmitter.event : mockEvent.event; });

View File

@@ -45,7 +45,9 @@ import { ILayoutService } from 'vs/platform/layout/browser/layoutService';
import { Registry } from 'vs/platform/registry/common/platform'; import { Registry } from 'vs/platform/registry/common/platform';
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
import { Iterable } from 'vs/base/common/iterator'; import { Iterable } from 'vs/base/common/iterator';
import { LoadingSpinner } from 'sql/base/browser/ui/loadingSpinner/loadingSpinner';
import { Tenant, TenantListDelegate, TenantListRenderer } from 'sql/workbench/services/accountManagement/browser/tenantListRenderer'; import { Tenant, TenantListDelegate, TenantListRenderer } from 'sql/workbench/services/accountManagement/browser/tenantListRenderer';
import { IAccountManagementService } from 'sql/platform/accounts/common/interfaces';
export const VIEWLET_ID = 'workbench.view.accountpanel'; export const VIEWLET_ID = 'workbench.view.accountpanel';
@@ -130,6 +132,7 @@ export class AccountDialog extends Modal {
// MEMBER VARIABLES //////////////////////////////////////////////////// // MEMBER VARIABLES ////////////////////////////////////////////////////
private _providerViewsMap = new Map<string, IProviderViewUiComponent>(); private _providerViewsMap = new Map<string, IProviderViewUiComponent>();
private _loadingSpinner: LoadingSpinner;
private _closeButton?: Button; private _closeButton?: Button;
private _addAccountButton?: Button; private _addAccountButton?: Button;
@@ -161,7 +164,8 @@ export class AccountDialog extends Modal {
@IQuickInputService private _quickInputService: IQuickInputService, @IQuickInputService private _quickInputService: IQuickInputService,
@INotificationService private _notificationService: INotificationService, @INotificationService private _notificationService: INotificationService,
@IOpenerService protected readonly openerService: IOpenerService, @IOpenerService protected readonly openerService: IOpenerService,
@ITelemetryService private readonly vstelemetryService: ITelemetryService @ITelemetryService private readonly vstelemetryService: ITelemetryService,
@IAccountManagementService private readonly _accountManagementService: IAccountManagementService,
) { ) {
super( super(
localize('linkedAccounts', "Linked accounts"), localize('linkedAccounts', "Linked accounts"),
@@ -172,8 +176,7 @@ export class AccountDialog extends Modal {
themeService, themeService,
logService, logService,
textResourcePropertiesService, textResourcePropertiesService,
contextKeyService, contextKeyService
{ hasSpinner: true }
); );
// Setup the event emitters // Setup the event emitters
@@ -209,6 +212,9 @@ export class AccountDialog extends Modal {
protected renderBody(container: HTMLElement) { protected renderBody(container: HTMLElement) {
this._container = container; this._container = container;
this._loadingSpinner = new LoadingSpinner(this._container, { showText: true, fullSize: true });
this._splitViewContainer = DOM.$('div.account-view.monaco-pane-view'); this._splitViewContainer = DOM.$('div.account-view.monaco-pane-view');
DOM.append(container, this._splitViewContainer); DOM.append(container, this._splitViewContainer);
this._splitView = new SplitView(this._splitViewContainer); this._splitView = new SplitView(this._splitViewContainer);
@@ -252,23 +258,37 @@ export class AccountDialog extends Modal {
this.hide(hideReason); this.hide(hideReason);
} }
public open() { public async open() {
let accountMetadata = await this._accountManagementService.getAccountProviderMetadata();
this.show(); this.show();
if (!this.isEmptyLinkedAccount()) { if (!this.isEmptyLinkedAccount()) {
this.showSplitView(); this.showSplitView();
} else { }
else if (accountMetadata.length === 0) {
this.showLoadingSpinner();
}
else {
this.showNoAccountContainer(); this.showNoAccountContainer();
} }
} }
private showNoAccountContainer() { private showNoAccountContainer() {
this._loadingSpinner.loading = false;
this._splitViewContainer!.hidden = true; this._splitViewContainer!.hidden = true;
this._noaccountViewContainer!.hidden = false; this._noaccountViewContainer!.hidden = false;
this._addAccountButton!.focus(); this._addAccountButton!.focus();
} }
private showLoadingSpinner() {
this._loadingSpinner.loadingMessage = localize('accountDialog.loadingProviderLabel', "Loading accounts...");
this._loadingSpinner.loading = true;
this._splitViewContainer!.hidden = true;
this._noaccountViewContainer!.hidden = true;
}
private showSplitView() { private showSplitView() {
this._loadingSpinner.loading = false;
this._splitViewContainer!.hidden = false; this._splitViewContainer!.hidden = false;
this._noaccountViewContainer!.hidden = true; this._noaccountViewContainer!.hidden = true;
if (Iterable.consume(this._providerViewsMap.values()).length > 0) { if (Iterable.consume(this._providerViewsMap.values()).length > 0) {
@@ -318,9 +338,7 @@ export class AccountDialog extends Modal {
AddAccountAction, AddAccountAction,
newProvider.addedProvider.id newProvider.addedProvider.id
); );
addAccountAction.addAccountCompleteEvent(() => this.spinner = false);
addAccountAction.addAccountErrorEvent(msg => this._onAddAccountErrorEmitter.fire(msg)); addAccountAction.addAccountErrorEvent(msg => this._onAddAccountErrorEmitter.fire(msg));
addAccountAction.addAccountStartEvent(() => this.spinner = true);
let providerView = new AccountPanel( let providerView = new AccountPanel(
{ {

View File

@@ -377,8 +377,8 @@ export class AccountManagementService implements IAccountManagementService {
const accounts = await this._accountStore.getAccountsByProvider(providerMetadata.id); const accounts = await this._accountStore.getAccountsByProvider(providerMetadata.id);
const updatedAccounts = await provider.initialize(accounts); const updatedAccounts = await provider.initialize(accounts);
// Don't add the accounts that are about to get deleted to the cache. // Don't add the accounts that are explicitly marked to be deleted to the cache.
this._providers[providerMetadata.id].accounts = updatedAccounts.filter(s => s.delete === false); this._providers[providerMetadata.id].accounts = updatedAccounts.filter(s => !s.delete);
const writePromises = updatedAccounts.map(async (account) => { const writePromises = updatedAccounts.map(async (account) => {
if (account.delete === true) { if (account.delete === true) {